/* poppler-form.h: qt interface to poppler
 * Copyright (C) 2007-2008, 2011, Pino Toscano <pino@kde.org>
 * Copyright (C) 2008, 2011, 2012, 2015-2023 Albert Astals Cid <aacid@kde.org>
 * Copyright (C) 2011 Carlos Garcia Campos <carlosgc@gnome.org>
 * Copyright (C) 2012, Adam Reichold <adamreichold@myopera.com>
 * Copyright (C) 2016, Hanno Meyer-Thurow <h.mth@web.de>
 * Copyright (C) 2017, Hans-Ulrich Jüttner <huj@froreich-bioscientia.de>
 * Copyright (C) 2018, Andre Heinecke <aheinecke@intevation.de>
 * 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
 * Copyright (C) 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@protonmail.com>
 * Copyright (C) 2018, 2020 Oliver Sander <oliver.sander@tu-dresden.de>
 * Copyright (C) 2019 João Netto <joaonetto901@gmail.com>
 * Copyright (C) 2020 David García Garzón <voki@canvoki.net>
 * Copyright (C) 2020 Thorsten Behrens <Thorsten.Behrens@CIB.de>
 * Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden
 * Copyright (C) 2021 Georgiy Sgibnev <georgiy@sgibnev.com>. Work sponsored by lab50.net.
 * Copyright (C) 2021 Theofilos Intzoglou <int.teo@gmail.com>
 * Copyright (C) 2022 Alexander Sulfrian <asulfrian@zedat.fu-berlin.de>
 * Copyright (C) 2023, 2024 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "poppler-form.h"

#include <config.h>

#include <QtCore/QSizeF>
#include <QUrl>

#include <Form.h>
#include <Object.h>
#include <Link.h>
#include <SignatureInfo.h>
#include <CertificateInfo.h>
#include <CryptoSignBackend.h>
#ifdef ENABLE_NSS3
#    include <NSSCryptoSignBackend.h>
#endif

#include "poppler-page-private.h"
#include "poppler-private.h"
#include "poppler-annotation-helper.h"

#include <cmath>
#include <cctype>

namespace {

Qt::Alignment formTextAlignment(::FormWidget *fm)
{
    Qt::Alignment qtalign = Qt::AlignLeft;
    switch (fm->getField()->getTextQuadding()) {
    case VariableTextQuadding::centered:
        qtalign = Qt::AlignHCenter;
        break;
    case VariableTextQuadding::rightJustified:
        qtalign = Qt::AlignRight;
        break;
    case VariableTextQuadding::leftJustified:
        qtalign = Qt::AlignLeft;
    }
    return qtalign;
}

}

namespace Poppler {

FormFieldIcon::FormFieldIcon(FormFieldIconData *data) : d_ptr(data) { }

FormFieldIcon::FormFieldIcon(const FormFieldIcon &ffIcon)
{
    d_ptr = new FormFieldIconData;
    d_ptr->icon = ffIcon.d_ptr->icon;
}

FormFieldIcon &FormFieldIcon::operator=(const FormFieldIcon &ffIcon)
{
    if (this != &ffIcon) {
        delete d_ptr;
        d_ptr = nullptr;

        d_ptr = new FormFieldIconData;
        *d_ptr = *ffIcon.d_ptr;
    }

    return *this;
}

FormFieldIcon::~FormFieldIcon()
{
    delete d_ptr;
}

FormField::FormField(std::unique_ptr<FormFieldData> dd) : m_formData(std::move(dd))
{
    if (m_formData->page) {
        const int rotation = m_formData->page->getRotate();
        // reading the coords
        double left, top, right, bottom;
        m_formData->fm->getRect(&left, &bottom, &right, &top);
        // build a normalized transform matrix for this page at 100% scale
        GfxState gfxState(72.0, 72.0, m_formData->page->getCropBox(), rotation, true);
        const double *gfxCTM = gfxState.getCTM();
        double MTX[6];
        double pageWidth = m_formData->page->getCropWidth();
        double pageHeight = m_formData->page->getCropHeight();
        // landscape and seascape page rotation: be sure to use the correct (== rotated) page size
        if (((rotation / 90) % 2) == 1) {
            qSwap(pageWidth, pageHeight);
        }
        for (int i = 0; i < 6; i += 2) {
            MTX[i] = gfxCTM[i] / pageWidth;
            MTX[i + 1] = gfxCTM[i + 1] / pageHeight;
        }
        QPointF topLeft;
        XPDFReader::transform(MTX, qMin(left, right), qMax(top, bottom), topLeft);
        QPointF bottomRight;
        XPDFReader::transform(MTX, qMax(left, right), qMin(top, bottom), bottomRight);
        m_formData->box = QRectF(topLeft, QSizeF(bottomRight.x() - topLeft.x(), bottomRight.y() - topLeft.y()));
    }
}

FormField::~FormField() = default;

QRectF FormField::rect() const
{
    return m_formData->box;
}

int FormField::id() const
{
    return m_formData->fm->getID();
}

QString FormField::name() const
{
    QString name;
    if (const GooString *goo = m_formData->fm->getPartialName()) {
        name = UnicodeParsedString(goo);
    }
    return name;
}

void FormField::setName(const QString &name) const
{
    GooString *goo = QStringToGooString(name);
    m_formData->fm->setPartialName(*goo);
    delete goo;
}

QString FormField::fullyQualifiedName() const
{
    QString name;
    if (GooString *goo = m_formData->fm->getFullyQualifiedName()) {
        name = UnicodeParsedString(goo);
    }
    return name;
}

QString FormField::uiName() const
{
    QString name;
    if (const GooString *goo = m_formData->fm->getAlternateUiName()) {
        name = UnicodeParsedString(goo);
    }
    return name;
}

bool FormField::isReadOnly() const
{
    return m_formData->fm->isReadOnly();
}

void FormField::setReadOnly(bool value)
{
    m_formData->fm->setReadOnly(value);
}

bool FormField::isVisible() const
{
    const unsigned int flags = m_formData->fm->getWidgetAnnotation()->getFlags();
    if (flags & Annot::flagHidden) {
        return false;
    }
    if (flags & Annot::flagNoView) {
        return false;
    }
    return true;
}

void FormField::setVisible(bool value)
{
    unsigned int flags = m_formData->fm->getWidgetAnnotation()->getFlags();
    if (value) {
        flags &= ~Annot::flagHidden;
        flags &= ~Annot::flagNoView;
    } else {
        flags |= Annot::flagHidden;
    }
    m_formData->fm->getWidgetAnnotation()->setFlags(flags);
}

bool FormField::isPrintable() const
{
    return (m_formData->fm->getWidgetAnnotation()->getFlags() & Annot::flagPrint);
}

void FormField::setPrintable(bool value)
{
    unsigned int flags = m_formData->fm->getWidgetAnnotation()->getFlags();
    if (value) {
        flags |= Annot::flagPrint;
    } else {
        flags &= ~Annot::flagPrint;
    }
    m_formData->fm->getWidgetAnnotation()->setFlags(flags);
}

Link *FormField::activationAction() const
{
    Link *action = nullptr;
    if (::LinkAction *act = m_formData->fm->getActivationAction()) {
        action = PageData::convertLinkActionToLink(act, m_formData->doc, QRectF());
    }
    return action;
}

Link *FormField::additionalAction(AdditionalActionType type) const
{
    Annot::FormAdditionalActionsType actionType = Annot::actionFieldModified;
    switch (type) {
    case FieldModified:
        actionType = Annot::actionFieldModified;
        break;
    case FormatField:
        actionType = Annot::actionFormatField;
        break;
    case ValidateField:
        actionType = Annot::actionValidateField;
        break;
    case CalculateField:
        actionType = Annot::actionCalculateField;
        break;
    }

    Link *action = nullptr;
    if (std::unique_ptr<::LinkAction> act = m_formData->fm->getAdditionalAction(actionType)) {
        action = PageData::convertLinkActionToLink(act.get(), m_formData->doc, QRectF());
    }
    return action;
}

Link *FormField::additionalAction(Annotation::AdditionalActionType type) const
{
    ::AnnotWidget *w = m_formData->fm->getWidgetAnnotation();
    if (!w) {
        return nullptr;
    }

    const Annot::AdditionalActionsType actionType = toPopplerAdditionalActionType(type);

    Link *action = nullptr;
    if (std::unique_ptr<::LinkAction> act = w->getAdditionalAction(actionType)) {
        action = PageData::convertLinkActionToLink(act.get(), m_formData->doc, QRectF());
    }
    return action;
}

FormFieldButton::FormFieldButton(DocumentData *doc, ::Page *p, ::FormWidgetButton *w) : FormField(std::make_unique<FormFieldData>(doc, p, w)) { }

FormFieldButton::~FormFieldButton() { }

FormFieldButton::FormType FormFieldButton::type() const
{
    return FormField::FormButton;
}

FormFieldButton::ButtonType FormFieldButton::buttonType() const
{
    FormWidgetButton *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
    switch (fwb->getButtonType()) {
    case formButtonCheck:
        return FormFieldButton::CheckBox;
        break;
    case formButtonPush:
        return FormFieldButton::Push;
        break;
    case formButtonRadio:
        return FormFieldButton::Radio;
        break;
    }
    return FormFieldButton::CheckBox;
}

QString FormFieldButton::caption() const
{
    FormWidgetButton *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
    QString ret;
    if (fwb->getButtonType() == formButtonPush) {
        Dict *dict = m_formData->fm->getObj()->getDict();
        Object obj1 = dict->lookup("MK");
        if (obj1.isDict()) {
            AnnotAppearanceCharacs appearCharacs(obj1.getDict());
            if (appearCharacs.getNormalCaption()) {
                ret = UnicodeParsedString(appearCharacs.getNormalCaption());
            }
        }
    } else {
        if (const char *goo = fwb->getOnStr()) {
            ret = QString::fromUtf8(goo);
        }
    }
    return ret;
}

FormFieldIcon FormFieldButton::icon() const
{
    FormWidgetButton *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
    if (fwb->getButtonType() == formButtonPush) {
        Dict *dict = m_formData->fm->getObj()->getDict();
        FormFieldIconData *data = new FormFieldIconData;
        data->icon = dict;
        return FormFieldIcon(data);
    }
    return FormFieldIcon(nullptr);
}

void FormFieldButton::setIcon(const FormFieldIcon &icon)
{
    if (FormFieldIconData::getData(icon) == nullptr) {
        return;
    }

    FormWidgetButton *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
    if (fwb->getButtonType() == formButtonPush) {
        ::AnnotWidget *w = m_formData->fm->getWidgetAnnotation();
        FormFieldIconData *data = FormFieldIconData::getData(icon);
        if (data->icon != nullptr) {
            w->setNewAppearance(data->icon->lookup("AP"));
        }
    }
}

bool FormFieldButton::state() const
{
    FormWidgetButton *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
    return fwb->getState();
}

void FormFieldButton::setState(bool state)
{
    FormWidgetButton *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
    fwb->setState((bool)state);
}

QList<int> FormFieldButton::siblings() const
{
    FormWidgetButton *fwb = static_cast<FormWidgetButton *>(m_formData->fm);
    ::FormFieldButton *ffb = static_cast<::FormFieldButton *>(fwb->getField());
    if (fwb->getButtonType() == formButtonPush) {
        return QList<int>();
    }

    QList<int> ret;
    for (int i = 0; i < ffb->getNumSiblings(); ++i) {
        ::FormFieldButton *sibling = static_cast<::FormFieldButton *>(ffb->getSibling(i));
        for (int j = 0; j < sibling->getNumWidgets(); ++j) {
            FormWidget *w = sibling->getWidget(j);
            if (w) {
                ret.append(w->getID());
            }
        }
    }

    return ret;
}

FormFieldText::FormFieldText(DocumentData *doc, ::Page *p, ::FormWidgetText *w) : FormField(std::make_unique<FormFieldData>(doc, p, w)) { }

FormFieldText::~FormFieldText() { }

FormField::FormType FormFieldText::type() const
{
    return FormField::FormText;
}

FormFieldText::TextType FormFieldText::textType() const
{
    FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
    if (fwt->isFileSelect()) {
        return FormFieldText::FileSelect;
    } else if (fwt->isMultiline()) {
        return FormFieldText::Multiline;
    }
    return FormFieldText::Normal;
}

QString FormFieldText::text() const
{
    const GooString *goo = static_cast<FormWidgetText *>(m_formData->fm)->getContent();
    return UnicodeParsedString(goo);
}

void FormFieldText::setText(const QString &text)
{
    FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
    GooString *goo = QStringToUnicodeGooString(text);
    fwt->setContent(goo);
    delete goo;
}

void FormFieldText::setAppearanceText(const QString &text)
{
    FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
    GooString *goo = QStringToUnicodeGooString(text);
    fwt->setAppearanceContent(goo);
    delete goo;
}

bool FormFieldText::isPassword() const
{
    FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
    return fwt->isPassword();
}

bool FormFieldText::isRichText() const
{
    FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
    return fwt->isRichText();
}

int FormFieldText::maximumLength() const
{
    FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
    const int maxlen = fwt->getMaxLen();
    return maxlen > 0 ? maxlen : -1;
}

Qt::Alignment FormFieldText::textAlignment() const
{
    return formTextAlignment(m_formData->fm);
}

bool FormFieldText::canBeSpellChecked() const
{
    FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
    return !fwt->noSpellCheck();
}

double FormFieldText::getFontSize() const
{
    FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
    return fwt->getTextFontSize();
}

void FormFieldText::setFontSize(int fontSize)
{
    FormWidgetText *fwt = static_cast<FormWidgetText *>(m_formData->fm);
    fwt->setTextFontSize(fontSize);
}

FormFieldChoice::FormFieldChoice(DocumentData *doc, ::Page *p, ::FormWidgetChoice *w) : FormField(std::make_unique<FormFieldData>(doc, p, w)) { }

FormFieldChoice::~FormFieldChoice() { }

FormFieldChoice::FormType FormFieldChoice::type() const
{
    return FormField::FormChoice;
}

FormFieldChoice::ChoiceType FormFieldChoice::choiceType() const
{
    FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
    if (fwc->isCombo()) {
        return FormFieldChoice::ComboBox;
    }
    return FormFieldChoice::ListBox;
}

QStringList FormFieldChoice::choices() const
{
    FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
    QStringList ret;
    int num = fwc->getNumChoices();
    ret.reserve(num);
    for (int i = 0; i < num; ++i) {
        ret.append(UnicodeParsedString(fwc->getChoice(i)));
    }
    return ret;
}

QVector<QPair<QString, QString>> FormFieldChoice::choicesWithExportValues() const
{
    FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
    QVector<QPair<QString, QString>> ret;
    const int num = fwc->getNumChoices();
    ret.reserve(num);
    for (int i = 0; i < num; ++i) {
        const QString display = UnicodeParsedString(fwc->getChoice(i));
        const GooString *exportValueG = fwc->getExportVal(i);
        const QString exportValue = exportValueG ? UnicodeParsedString(exportValueG) : display;
        ret.append({ display, exportValue });
    }
    return ret;
}

bool FormFieldChoice::isEditable() const
{
    FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
    return fwc->isCombo() ? fwc->hasEdit() : false;
}

bool FormFieldChoice::multiSelect() const
{
    FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
    return !fwc->isCombo() ? fwc->isMultiSelect() : false;
}

QList<int> FormFieldChoice::currentChoices() const
{
    FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
    int num = fwc->getNumChoices();
    QList<int> choices;
    for (int i = 0; i < num; ++i) {
        if (fwc->isSelected(i)) {
            choices.append(i);
        }
    }
    return choices;
}

void FormFieldChoice::setCurrentChoices(const QList<int> &choice)
{
    FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
    fwc->deselectAll();
    for (int i = 0; i < choice.count(); ++i) {
        fwc->select(choice.at(i));
    }
}

QString FormFieldChoice::editChoice() const
{
    FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);

    if (fwc->isCombo() && fwc->hasEdit()) {
        return UnicodeParsedString(fwc->getEditChoice());
    } else {
        return QString();
    }
}

void FormFieldChoice::setEditChoice(const QString &text)
{
    FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);

    if (fwc->isCombo() && fwc->hasEdit()) {
        GooString *goo = QStringToUnicodeGooString(text);
        fwc->setEditChoice(goo);
        delete goo;
    }
}

Qt::Alignment FormFieldChoice::textAlignment() const
{
    return formTextAlignment(m_formData->fm);
}

bool FormFieldChoice::canBeSpellChecked() const
{
    FormWidgetChoice *fwc = static_cast<FormWidgetChoice *>(m_formData->fm);
    return !fwc->noSpellCheck();
}

class CertificateInfoPrivate
{
public:
    struct EntityInfo
    {
        QString common_name;
        QString email_address;
        QString org_name;
        QString distinguished_name;
    };

    EntityInfo issuer_info;
    EntityInfo subject_info;
    QString nick_name;
    QByteArray certificate_der;
    QByteArray serial_number;
    QByteArray public_key;
    QDateTime validity_start;
    QDateTime validity_end;
    int public_key_type;
    int public_key_strength;
    int ku_extensions;
    int version;
    bool is_self_signed;
    bool is_null;
    CertificateInfo::KeyLocation keyLocation;
};

CertificateInfo::CertificateInfo() : d_ptr(new CertificateInfoPrivate())
{
    d_ptr->is_null = true;
}

CertificateInfo::CertificateInfo(CertificateInfoPrivate *priv) : d_ptr(priv) { }

CertificateInfo::CertificateInfo(const CertificateInfo &other) : d_ptr(other.d_ptr) { }

CertificateInfo::~CertificateInfo() = default;

CertificateInfo &CertificateInfo::operator=(const CertificateInfo &other)
{
    if (this != &other) {
        d_ptr = other.d_ptr;
    }

    return *this;
}

bool CertificateInfo::isNull() const
{
    Q_D(const CertificateInfo);
    return d->is_null;
}

int CertificateInfo::version() const
{
    Q_D(const CertificateInfo);
    return d->version;
}

QByteArray CertificateInfo::serialNumber() const
{
    Q_D(const CertificateInfo);
    return d->serial_number;
}

QString CertificateInfo::issuerInfo(EntityInfoKey key) const
{
    Q_D(const CertificateInfo);
    switch (key) {
    case CommonName:
        return d->issuer_info.common_name;
    case DistinguishedName:
        return d->issuer_info.distinguished_name;
    case EmailAddress:
        return d->issuer_info.email_address;
    case Organization:
        return d->issuer_info.org_name;
    default:
        return QString();
    }
}

QString CertificateInfo::subjectInfo(EntityInfoKey key) const
{
    Q_D(const CertificateInfo);
    switch (key) {
    case CommonName:
        return d->subject_info.common_name;
    case DistinguishedName:
        return d->subject_info.distinguished_name;
    case EmailAddress:
        return d->subject_info.email_address;
    case Organization:
        return d->subject_info.org_name;
    default:
        return QString();
    }
}

QString CertificateInfo::nickName() const
{
    Q_D(const CertificateInfo);
    return d->nick_name;
}

QDateTime CertificateInfo::validityStart() const
{
    Q_D(const CertificateInfo);
    return d->validity_start;
}

QDateTime CertificateInfo::validityEnd() const
{
    Q_D(const CertificateInfo);
    return d->validity_end;
}

CertificateInfo::KeyUsageExtensions CertificateInfo::keyUsageExtensions() const
{
    Q_D(const CertificateInfo);

    KeyUsageExtensions kuExtensions = KuNone;
    if (d->ku_extensions & KU_DIGITAL_SIGNATURE) {
        kuExtensions |= KuDigitalSignature;
    }
    if (d->ku_extensions & KU_NON_REPUDIATION) {
        kuExtensions |= KuNonRepudiation;
    }
    if (d->ku_extensions & KU_KEY_ENCIPHERMENT) {
        kuExtensions |= KuKeyEncipherment;
    }
    if (d->ku_extensions & KU_DATA_ENCIPHERMENT) {
        kuExtensions |= KuDataEncipherment;
    }
    if (d->ku_extensions & KU_KEY_AGREEMENT) {
        kuExtensions |= KuKeyAgreement;
    }
    if (d->ku_extensions & KU_KEY_CERT_SIGN) {
        kuExtensions |= KuKeyCertSign;
    }
    if (d->ku_extensions & KU_CRL_SIGN) {
        kuExtensions |= KuClrSign;
    }
    if (d->ku_extensions & KU_ENCIPHER_ONLY) {
        kuExtensions |= KuEncipherOnly;
    }

    return kuExtensions;
}

CertificateInfo::KeyLocation CertificateInfo::keyLocation() const
{
    Q_D(const CertificateInfo);
    return d->keyLocation;
}

QByteArray CertificateInfo::publicKey() const
{
    Q_D(const CertificateInfo);
    return d->public_key;
}

CertificateInfo::PublicKeyType CertificateInfo::publicKeyType() const
{
    Q_D(const CertificateInfo);
    switch (d->public_key_type) {
    case RSAKEY:
        return RsaKey;
    case DSAKEY:
        return DsaKey;
    case ECKEY:
        return EcKey;
    default:
        return OtherKey;
    }
}

int CertificateInfo::publicKeyStrength() const
{
    Q_D(const CertificateInfo);
    return d->public_key_strength;
}

bool CertificateInfo::isSelfSigned() const
{
    Q_D(const CertificateInfo);
    return d->is_self_signed;
}

QByteArray CertificateInfo::certificateData() const
{
    Q_D(const CertificateInfo);
    return d->certificate_der;
}

bool CertificateInfo::checkPassword(const QString &password) const
{
#ifdef ENABLE_SIGNATURES
    auto backend = CryptoSign::Factory::createActive();
    if (!backend) {
        return false;
    }
    Q_D(const CertificateInfo);
    auto sigHandler = backend->createSigningHandler(d->nick_name.toStdString(), HashAlgorithm::Sha256);
    unsigned char buffer[5];
    memcpy(buffer, "test", 5);
    sigHandler->addData(buffer, 5);
    std::optional<GooString> tmpSignature = sigHandler->signDetached(password.toStdString());
    return tmpSignature.has_value();
#else
    return false;
#endif
}

class SignatureValidationInfoPrivate
{
public:
    explicit SignatureValidationInfoPrivate(CertificateInfo &&ci) : cert_info(ci) { }

    SignatureValidationInfo::SignatureStatus signature_status;
    SignatureValidationInfo::CertificateStatus certificate_status;
    CertificateInfo cert_info;

    QByteArray signature;
    QString signer_name;
    QString signer_subject_dn;
    QString location;
    QString reason;
    HashAlgorithm hash_algorithm;
    time_t signing_time;
    QList<qint64> range_bounds;
    qint64 docLength;
};

SignatureValidationInfo::SignatureValidationInfo(SignatureValidationInfoPrivate *priv) : d_ptr(priv) { }

SignatureValidationInfo::SignatureValidationInfo(const SignatureValidationInfo &other) : d_ptr(other.d_ptr) { }

SignatureValidationInfo::~SignatureValidationInfo() { }

SignatureValidationInfo::SignatureStatus SignatureValidationInfo::signatureStatus() const
{
    Q_D(const SignatureValidationInfo);
    return d->signature_status;
}

SignatureValidationInfo::CertificateStatus SignatureValidationInfo::certificateStatus() const
{
    Q_D(const SignatureValidationInfo);
    return d->certificate_status;
}

QString SignatureValidationInfo::signerName() const
{
    Q_D(const SignatureValidationInfo);
    return d->signer_name;
}

QString SignatureValidationInfo::signerSubjectDN() const
{
    Q_D(const SignatureValidationInfo);
    return d->signer_subject_dn;
}

QString SignatureValidationInfo::location() const
{
    Q_D(const SignatureValidationInfo);
    return d->location;
}

QString SignatureValidationInfo::reason() const
{
    Q_D(const SignatureValidationInfo);
    return d->reason;
}

SignatureValidationInfo::HashAlgorithm SignatureValidationInfo::hashAlgorithm() const
{
#ifdef ENABLE_SIGNATURES
    Q_D(const SignatureValidationInfo);

    switch (d->hash_algorithm) {
    case ::HashAlgorithm::Md2:
        return HashAlgorithmMd2;
    case ::HashAlgorithm::Md5:
        return HashAlgorithmMd5;
    case ::HashAlgorithm::Sha1:
        return HashAlgorithmSha1;
    case ::HashAlgorithm::Sha256:
        return HashAlgorithmSha256;
    case ::HashAlgorithm::Sha384:
        return HashAlgorithmSha384;
    case ::HashAlgorithm::Sha512:
        return HashAlgorithmSha512;
    case ::HashAlgorithm::Sha224:
        return HashAlgorithmSha224;
    case ::HashAlgorithm::Unknown:
        return HashAlgorithmUnknown;
    }
#endif
    return HashAlgorithmUnknown;
}

time_t SignatureValidationInfo::signingTime() const
{
    Q_D(const SignatureValidationInfo);
    return d->signing_time;
}

QByteArray SignatureValidationInfo::signature() const
{
    Q_D(const SignatureValidationInfo);
    return d->signature;
}

QList<qint64> SignatureValidationInfo::signedRangeBounds() const
{
    Q_D(const SignatureValidationInfo);
    return d->range_bounds;
}

bool SignatureValidationInfo::signsTotalDocument() const
{
    Q_D(const SignatureValidationInfo);
    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)) {
        // The range from d->range_bounds.value(1) to d->range_bounds.value(2) is
        // not authenticated by the signature and should only contain the signature
        // itself padded with 0 bytes. This has been checked in readSignature().
        // If it failed, d->signature is empty.
        // A potential range after d->range_bounds.value(3) would be also not
        // authenticated. Therefore d->range_bounds.value(3) should coincide with
        // the end of the document.
        if (d->docLength == d->range_bounds.value(3) && !d->signature.isEmpty()) {
            return true;
        }
    }
    return false;
}

CertificateInfo SignatureValidationInfo::certificateInfo() const
{
    Q_D(const SignatureValidationInfo);
    return d->cert_info;
}

SignatureValidationInfo &SignatureValidationInfo::operator=(const SignatureValidationInfo &other)
{
    if (this != &other) {
        d_ptr = other.d_ptr;
    }

    return *this;
}

FormFieldSignature::FormFieldSignature(DocumentData *doc, ::Page *p, ::FormWidgetSignature *w) : FormField(std::make_unique<FormFieldData>(doc, p, w)) { }

FormFieldSignature::~FormFieldSignature() { }

FormField::FormType FormFieldSignature::type() const
{
    return FormField::FormSignature;
}

FormFieldSignature::SignatureType FormFieldSignature::signatureType() const
{
    SignatureType sigType = AdbePkcs7detached;
    FormWidgetSignature *fws = static_cast<FormWidgetSignature *>(m_formData->fm);
    switch (fws->signatureType()) {
    case adbe_pkcs7_sha1:
        sigType = AdbePkcs7sha1;
        break;
    case adbe_pkcs7_detached:
        sigType = AdbePkcs7detached;
        break;
    case ETSI_CAdES_detached:
        sigType = EtsiCAdESdetached;
        break;
    case unknown_signature_type:
        sigType = UnknownSignatureType;
        break;
    case unsigned_signature_field:
        sigType = UnsignedSignature;
        break;
    }
    return sigType;
}

SignatureValidationInfo FormFieldSignature::validate(ValidateOptions opt) const
{
    auto tempResult = validateAsync(opt);
    tempResult.first.d_ptr->certificate_status = validateResult();
    return tempResult.first;
}

static CertificateInfo::KeyLocation fromPopplerCore(KeyLocation location)
{
    switch (location) {
    case KeyLocation::Computer:
        return CertificateInfo::KeyLocation::Computer;
    case KeyLocation::Other:
        return CertificateInfo::KeyLocation::Other;
    case KeyLocation::Unknown:
        return CertificateInfo::KeyLocation::Unknown;
    case KeyLocation::HardwareToken:
        return CertificateInfo::KeyLocation::HardwareToken;
    }
    return CertificateInfo::KeyLocation::Unknown;
}

static CertificateInfoPrivate *createCertificateInfoPrivate(const X509CertificateInfo *ci)
{
    CertificateInfoPrivate *certPriv = new CertificateInfoPrivate;
    certPriv->is_null = true;
    if (ci) {
        certPriv->version = ci->getVersion();
        certPriv->ku_extensions = ci->getKeyUsageExtensions();
        certPriv->keyLocation = fromPopplerCore(ci->getKeyLocation());

        const GooString &certSerial = ci->getSerialNumber();
        certPriv->serial_number = QByteArray(certSerial.c_str(), certSerial.getLength());

        const X509CertificateInfo::EntityInfo &issuerInfo = ci->getIssuerInfo();
        certPriv->issuer_info.common_name = issuerInfo.commonName.c_str();
        certPriv->issuer_info.distinguished_name = issuerInfo.distinguishedName.c_str();
        certPriv->issuer_info.email_address = issuerInfo.email.c_str();
        certPriv->issuer_info.org_name = issuerInfo.organization.c_str();

        const X509CertificateInfo::EntityInfo &subjectInfo = ci->getSubjectInfo();
        certPriv->subject_info.common_name = subjectInfo.commonName.c_str();
        certPriv->subject_info.distinguished_name = subjectInfo.distinguishedName.c_str();
        certPriv->subject_info.email_address = subjectInfo.email.c_str();
        certPriv->subject_info.org_name = subjectInfo.organization.c_str();

        certPriv->nick_name = ci->getNickName().c_str();

        X509CertificateInfo::Validity certValidity = ci->getValidity();
        certPriv->validity_start = QDateTime::fromSecsSinceEpoch(certValidity.notBefore, Qt::UTC);
        certPriv->validity_end = QDateTime::fromSecsSinceEpoch(certValidity.notAfter, Qt::UTC);

        const X509CertificateInfo::PublicKeyInfo &pkInfo = ci->getPublicKeyInfo();
        certPriv->public_key = QByteArray(pkInfo.publicKey.c_str(), pkInfo.publicKey.getLength());
        certPriv->public_key_type = static_cast<int>(pkInfo.publicKeyType);
        certPriv->public_key_strength = pkInfo.publicKeyStrength;

        const GooString &certDer = ci->getCertificateDER();
        certPriv->certificate_der = QByteArray(certDer.c_str(), certDer.getLength());

        certPriv->is_null = false;
    }

    return certPriv;
}

static SignatureValidationInfo::CertificateStatus fromInternal(CertificateValidationStatus status)
{
    switch (status) {
    case CERTIFICATE_TRUSTED:
        return SignatureValidationInfo::CertificateTrusted;
    case CERTIFICATE_UNTRUSTED_ISSUER:
        return SignatureValidationInfo::CertificateUntrustedIssuer;
    case CERTIFICATE_UNKNOWN_ISSUER:
        return SignatureValidationInfo::CertificateUnknownIssuer;
    case CERTIFICATE_REVOKED:
        return SignatureValidationInfo::CertificateRevoked;
    case CERTIFICATE_EXPIRED:
        return SignatureValidationInfo::CertificateExpired;
    default:
    case CERTIFICATE_GENERIC_ERROR:
        return SignatureValidationInfo::CertificateGenericError;
    case CERTIFICATE_NOT_VERIFIED:
        return SignatureValidationInfo::CertificateNotVerified;
    }
}

static SignatureValidationInfo fromInternal(SignatureInfo *si, FormWidgetSignature *fws)
{
    // get certificate info
    const X509CertificateInfo *ci = si->getCertificateInfo();
    CertificateInfoPrivate *certPriv = createCertificateInfoPrivate(ci);

    SignatureValidationInfoPrivate *priv = new SignatureValidationInfoPrivate(CertificateInfo(certPriv));
    switch (si->getSignatureValStatus()) {
    case SIGNATURE_VALID:
        priv->signature_status = SignatureValidationInfo::SignatureValid;
        break;
    case SIGNATURE_INVALID:
        priv->signature_status = SignatureValidationInfo::SignatureInvalid;
        break;
    case SIGNATURE_DIGEST_MISMATCH:
        priv->signature_status = SignatureValidationInfo::SignatureDigestMismatch;
        break;
    case SIGNATURE_DECODING_ERROR:
        priv->signature_status = SignatureValidationInfo::SignatureDecodingError;
        break;
    default:
    case SIGNATURE_GENERIC_ERROR:
        priv->signature_status = SignatureValidationInfo::SignatureGenericError;
        break;
    case SIGNATURE_NOT_FOUND:
        priv->signature_status = SignatureValidationInfo::SignatureNotFound;
        break;
    case SIGNATURE_NOT_VERIFIED:
        priv->signature_status = SignatureValidationInfo::SignatureNotVerified;
        break;
    }
    priv->certificate_status = SignatureValidationInfo::CertificateVerificationInProgress;
    priv->signer_name = QString::fromStdString(si->getSignerName());
    priv->signer_subject_dn = QString::fromStdString(si->getSubjectDN());
    priv->hash_algorithm = si->getHashAlgorithm();
    priv->location = UnicodeParsedString(si->getLocation().toStr());
    priv->reason = UnicodeParsedString(si->getReason().toStr());

    priv->signing_time = si->getSigningTime();
    const std::vector<Goffset> ranges = fws->getSignedRangeBounds();
    if (!ranges.empty()) {
        for (Goffset bound : ranges) {
            priv->range_bounds.append(bound);
        }
    }
    const std::optional<GooString> checkedSignature = fws->getCheckedSignature(&priv->docLength);
    if (priv->range_bounds.size() == 4 && checkedSignature) {
        priv->signature = QByteArray::fromHex(checkedSignature->c_str());
    }

    return SignatureValidationInfo(priv);
}

SignatureValidationInfo FormFieldSignature::validate(int opt, const QDateTime &validationTime) const
{
    auto tempResult = validateAsync(static_cast<ValidateOptions>(opt), validationTime);
    tempResult.first.d_ptr->certificate_status = validateResult();
    return tempResult.first;
}

class AsyncObjectPrivate
{ /*Currently unused. Created for abi future proofing*/
};

AsyncObject::AsyncObject() : QObject(nullptr), d {} { }

AsyncObject::~AsyncObject() = default;

std::pair<SignatureValidationInfo, std::shared_ptr<Poppler::AsyncObject>> FormFieldSignature::validateAsync(ValidateOptions opt, const QDateTime &validationTime) const
{
    auto object = std::make_shared<AsyncObject>();
    FormWidgetSignature *fws = static_cast<FormWidgetSignature *>(m_formData->fm);
    const time_t validationTimeT = validationTime.isValid() ? validationTime.toSecsSinceEpoch() : -1;
    SignatureInfo *si = fws->validateSignatureAsync(opt & ValidateVerifyCertificate, opt & ValidateForceRevalidation, validationTimeT, !(opt & ValidateWithoutOCSPRevocationCheck), opt & ValidateUseAIACertFetch,
                                                    [obj = std::weak_ptr<AsyncObject>(object)]() {
                                                        if (auto l = obj.lock()) {
                                                            // We need to roundtrip over the eventloop
                                                            // to ensure callers have a chance of connecting to AsyncObject::done
                                                            QMetaObject::invokeMethod(
                                                                    l.get(),
                                                                    [innerObj = std::weak_ptr<AsyncObject>(l)]() {
                                                                        if (auto innerLocked = innerObj.lock()) {
                                                                            emit innerLocked->done();
                                                                        }
                                                                    },
                                                                    Qt::QueuedConnection);
                                                        }
                                                    });

    return { fromInternal(si, fws), object };
}

SignatureValidationInfo::CertificateStatus FormFieldSignature::validateResult() const
{
    return fromInternal(static_cast<FormWidgetSignature *>(m_formData->fm)->validateSignatureResult());
}

FormFieldSignature::SigningResult FormFieldSignature::sign(const QString &outputFileName, const PDFConverter::NewSignatureData &data) const
{
    FormWidgetSignature *fws = static_cast<FormWidgetSignature *>(m_formData->fm);
    if (fws->signatureType() != unsigned_signature_field) {
        return FieldAlreadySigned;
    }

    Goffset file_size = 0;
    const std::optional<GooString> sig = fws->getCheckedSignature(&file_size);
    if (sig) {
        // the above unsigned_signature_field check
        // should already catch this, but double check
        return FieldAlreadySigned;
    }
    const auto reason = std::unique_ptr<GooString>(data.reason().isEmpty() ? nullptr : QStringToUnicodeGooString(data.reason()));
    const auto location = std::unique_ptr<GooString>(data.location().isEmpty() ? nullptr : QStringToUnicodeGooString(data.location()));
    const auto ownerPwd = std::optional<GooString>(data.documentOwnerPassword().constData());
    const auto userPwd = std::optional<GooString>(data.documentUserPassword().constData());
    const auto gSignatureText = std::unique_ptr<GooString>(QStringToUnicodeGooString(data.signatureText()));
    const auto gSignatureLeftText = std::unique_ptr<GooString>(QStringToUnicodeGooString(data.signatureLeftText()));

    const bool success = fws->signDocumentWithAppearance(outputFileName.toStdString(), data.certNickname().toStdString(), data.password().toStdString(), reason.get(), location.get(), ownerPwd, userPwd, *gSignatureText, *gSignatureLeftText,
                                                         data.fontSize(), data.leftFontSize(), convertQColor(data.fontColor()), data.borderWidth(), convertQColor(data.borderColor()), convertQColor(data.backgroundColor()));

    return success ? SigningSuccess : GenericSigningError;
}

bool hasNSSSupport()
{
#ifdef ENABLE_NSS3
    return true;
#else
    return false;
#endif
}

QVector<CertificateInfo> getAvailableSigningCertificates()
{
    auto backend = CryptoSign::Factory::createActive();
    if (!backend) {
        return {};
    }
    QVector<CertificateInfo> vReturnCerts;
    std::vector<std::unique_ptr<X509CertificateInfo>> vCerts = backend->getAvailableSigningCertificates();

    for (auto &cert : vCerts) {
        CertificateInfoPrivate *certPriv = createCertificateInfoPrivate(cert.get());
        vReturnCerts.append(CertificateInfo(certPriv));
    }

    return vReturnCerts;
}

static std::optional<CryptoSignBackend> convertToFrontend(std::optional<CryptoSign::Backend::Type> type)
{
    if (!type) {
        return std::nullopt;
    }
    switch (type.value()) {
    case CryptoSign::Backend::Type::NSS3:
        return CryptoSignBackend::NSS;
    case CryptoSign::Backend::Type::GPGME:
        return CryptoSignBackend::GPG;
    }
    return std::nullopt;
}

static std::optional<CryptoSign::Backend::Type> convertToBackend(std::optional<CryptoSignBackend> backend)
{
    if (!backend) {
        return std::nullopt;
    }
    switch (backend.value()) {
    case CryptoSignBackend::NSS:
        return CryptoSign::Backend::Type::NSS3;
    case CryptoSignBackend::GPG:
        return CryptoSign::Backend::Type::GPGME;
    }
    return std::nullopt;
}

QVector<CryptoSignBackend> availableCryptoSignBackends()
{
    QVector<CryptoSignBackend> backends;
    for (auto &backend : CryptoSign::Factory::getAvailable()) {
        auto converted = convertToFrontend(backend);
        if (converted) {
            backends.push_back(converted.value());
        }
    }
    return backends;
}

std::optional<CryptoSignBackend> activeCryptoSignBackend()
{
    return convertToFrontend(CryptoSign::Factory::getActive());
}

bool setActiveCryptoSignBackend(CryptoSignBackend backend)
{
    auto available = availableCryptoSignBackends();
    if (!available.contains(backend)) {
        return false;
    }
    auto converted = convertToBackend(backend);
    if (!converted) {
        return false;
    }
    CryptoSign::Factory::setPreferredBackend(converted.value());
    return activeCryptoSignBackend() == backend;
}

static bool hasNSSBackendFeature(CryptoSignBackendFeature feature)
{
    switch (feature) {
    case CryptoSignBackendFeature::BackendAsksPassphrase:
        return false;
    }
    return false;
}

static bool hasGPGBackendFeature(CryptoSignBackendFeature feature)
{
    switch (feature) {
    case CryptoSignBackendFeature::BackendAsksPassphrase:
        return true;
    }
    return false;
}

bool hasCryptoSignBackendFeature(CryptoSignBackend backend, CryptoSignBackendFeature feature)
{
    switch (backend) {
    case CryptoSignBackend::NSS:
        return hasNSSBackendFeature(feature);
    case CryptoSignBackend::GPG:
        return hasGPGBackendFeature(feature);
    }
    return false;
}

QString POPPLER_QT5_EXPORT getNSSDir()
{
#ifdef ENABLE_NSS3
    return QString::fromLocal8Bit(NSSSignatureConfiguration::getNSSDir().c_str());
#else
    return QString();
#endif
}

void setNSSDir(const QString &path)
{
#ifdef ENABLE_NSS3
    if (path.isEmpty()) {
        return;
    }

    GooString *goo = QStringToGooString(path);
    NSSSignatureConfiguration::setNSSDir(*goo);
    delete goo;
#else
    (void)path;
#endif
}

namespace {
std::function<QString(const QString &)> nssPasswordCall;
}

void setNSSPasswordCallback(const std::function<char *(const char *)> &f)
{
#ifdef ENABLE_NSS3
    NSSSignatureConfiguration::setNSSPasswordCallback(f);
#else
    qWarning() << "setNSSPasswordCallback called but this poppler is built without NSS support";
    (void)f;
#endif
}

}
