--- qt5/src/poppler-form.h 2016-12-06 18:52:54.748654289 +0100 +++ qt5/src/poppler-form.h 2016-12-07 08:01:43.770077696 +0100 @@ -30,6 +30,7 @@ class FormWidgetButton; class FormWidgetText; class FormWidgetChoice; +class FormWidgetSignature; namespace Poppler { @@ -338,6 +339,108 @@ Q_DISABLE_COPY(FormFieldChoice) }; + /** + A signature validation info helper class. + + \since xy.z + */ + class SignatureValidationInfoPrivate; + class POPPLER_QT5_EXPORT SignatureValidationInfo { + public: + + /** + The verfication result of the signature. + */ + enum SignatureStatus { + SignatureValid, ///< The signature is cryptographically valid. + SignatureInvalid, ///< The signature is cryptographically invalid. + SignatureDigestMismatch, ///< The document content was changed after the signature was applied. + SignatureDecodingError, ///< The signature CMS/PKCS7 structure is malformed. + SignatureGenericError, ///< The signature could not be verified. + SignatureNotFound, ///< The requested signature is not present in the document. + SignatureNotVerified ///< The signature is not yet verified. + }; + + /** + The verification result of the certificate. + */ + enum CertificateStatus { + CertificateTrusted, ///< The certificate is considered trusted. + CertificateUntrustedIssuer, ///< The issuer of this certificate has been marked as untrusted by the user. + CertificateUnknownIssuer, ///< The certificate trust chain has not finished in a trusted root certificate. + CertificateRevoked, ///< The certificate was revoked by the issuing certificate authority. + CertificateExpired, ///< The signing time is outside the validity bounds of this certificate. + CertificateGenericError, ///< The certificate could not be verified. + CertificateNotVerified ///< The certificate is not yet verified. + }; + + /// \cond PRIVATE + SignatureValidationInfo(SignatureValidationInfoPrivate *priv); + /// \endcond + ~SignatureValidationInfo(); + + /** + The signature status of the signature. + */ + const SignatureStatus signatureStatus() const; + + /** + The certificate status of the signature. + */ + const CertificateStatus certificateStatus() const; + + /** + The signer name associated with the signature. + */ + const QString signerName() const; + + /** + The signing time associated with the signature. + */ + const time_t signingTime() const; + + private: + Q_DISABLE_COPY(SignatureValidationInfo) + Q_DECLARE_PRIVATE(SignatureValidationInfo) + + private: + SignatureValidationInfoPrivate *d_ptr; + }; + + /** + A form field that represents a signature. + + \since xy.z + */ + class POPPLER_QT5_EXPORT FormFieldSignature : public FormField { + public: + + /** + The validation options of this signature. + */ + enum ValidateOptions { + ValidateVerifyCertificate = 1, ///< Validate the certificate. + ValidateForceRevalidation = 2, ///< Force revalidation of the certificate. + }; + + /// \cond PRIVATE + FormFieldSignature(DocumentData *doc, ::Page *p, ::FormWidgetSignature *w); + /// \endcond + virtual ~FormFieldSignature(); + + virtual FormType type() const; + + /** + Validate the signature. + + Return validatation info of the signature. + */ + const SignatureValidationInfo validate(ValidateOptions opt) const; + + private: + Q_DISABLE_COPY(FormFieldSignature) + }; + } #endif --- ./qt5/src/poppler-page.cc.orig 2016-12-06 18:53:02.140654512 +0100 +++ ./qt5/src/poppler-page.cc 2016-12-06 18:53:19.396655031 +0100 @@ -767,6 +767,12 @@ } break; + case formSignature: + { + ff = new FormFieldSignature(m_page->parentDoc, p, static_cast(fm)); + } + break; + default: ; } --- ./qt5/src/poppler-form.cc.orig 2016-12-06 18:53:09.544654734 +0100 +++ ./qt5/src/poppler-form.cc 2016-12-06 20:45:57.580858281 +0100 @@ -26,6 +26,7 @@ #include #include #include +#include #include "poppler-form.h" #include "poppler-page-private.h" @@ -414,4 +415,124 @@ return !fwc->noSpellCheck(); } + + +struct SignatureValidationInfoPrivate { + SignatureValidationInfo::SignatureStatus signature_status; + SignatureValidationInfo::CertificateStatus certificate_status; + + QString signer_name; + time_t signing_time; +}; + + +SignatureValidationInfo::SignatureValidationInfo(SignatureValidationInfoPrivate* priv) + : d_ptr(priv) +{ +} + +SignatureValidationInfo::~SignatureValidationInfo() +{ + delete d_ptr; +} + +const SignatureValidationInfo::SignatureStatus SignatureValidationInfo::signatureStatus() const +{ + Q_D(const SignatureValidationInfo); + return d->signature_status; +} + +const SignatureValidationInfo::CertificateStatus SignatureValidationInfo::certificateStatus() const +{ + Q_D(const SignatureValidationInfo); + return d->certificate_status; +} + +const QString SignatureValidationInfo::signerName() const +{ + Q_D(const SignatureValidationInfo); + return d->signer_name; +} + +const time_t SignatureValidationInfo::signingTime() const +{ + Q_D(const SignatureValidationInfo); + return d->signing_time; +} + + +FormFieldSignature::FormFieldSignature(DocumentData *doc, ::Page *p, ::FormWidgetSignature *w) + : FormField(*new FormFieldData(doc, p, w)) +{ +} + +FormFieldSignature::~FormFieldSignature() +{ +} + +FormField::FormType FormFieldSignature::type() const +{ + return FormField::FormSignature; +} + +const SignatureValidationInfo FormFieldSignature::validate(ValidateOptions opt) const +{ + FormWidgetSignature* fws = static_cast(m_formData->fm); + SignatureInfo* si = fws->validateSignature( + opt & ValidateVerifyCertificate, opt & ValidateForceRevalidation); + SignatureValidationInfoPrivate* priv(new SignatureValidationInfoPrivate); + 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; + } + switch (si->getCertificateValStatus()) { + case CERTIFICATE_TRUSTED: + priv->certificate_status = SignatureValidationInfo::CertificateTrusted; + break; + case CERTIFICATE_UNTRUSTED_ISSUER: + priv->certificate_status = SignatureValidationInfo::CertificateUntrustedIssuer; + break; + case CERTIFICATE_UNKNOWN_ISSUER: + priv->certificate_status = SignatureValidationInfo::CertificateUnknownIssuer; + break; + case CERTIFICATE_REVOKED: + priv->certificate_status = SignatureValidationInfo::CertificateRevoked; + break; + case CERTIFICATE_EXPIRED: + priv->certificate_status = SignatureValidationInfo::CertificateExpired; + break; + default: + case CERTIFICATE_GENERIC_ERROR: + priv->certificate_status = SignatureValidationInfo::CertificateGenericError; + break; + case CERTIFICATE_NOT_VERIFIED: + priv->certificate_status = SignatureValidationInfo::CertificateNotVerified; + break; + } + priv->signer_name = si->getSignerName(); + priv->signing_time = si->getSigningTime(); + + return SignatureValidationInfo(priv); +} + } --- ./qt5/tests/poppler-forms.cpp.orig 2016-12-06 18:53:16.612654947 +0100 +++ ./qt5/tests/poppler-forms.cpp 2016-12-06 20:39:13.088846116 +0100 @@ -1,4 +1,5 @@ #include +#include #include #include @@ -46,6 +47,34 @@ return out; } +std::ostream& operator<< (std::ostream &out, Poppler::SignatureValidationInfo::SignatureStatus status) +{ + switch (status) { + case Poppler::SignatureValidationInfo::SignatureValid: out << "Valid"; break; + case Poppler::SignatureValidationInfo::SignatureInvalid: out << "Invalid"; break; + case Poppler::SignatureValidationInfo::SignatureDigestMismatch: out << "DigestMismatch"; break; + case Poppler::SignatureValidationInfo::SignatureDecodingError: out << "DecodingError"; break; + case Poppler::SignatureValidationInfo::SignatureGenericError: out << "GenericError"; break; + case Poppler::SignatureValidationInfo::SignatureNotFound: out << "NotFound"; break; + case Poppler::SignatureValidationInfo::SignatureNotVerified: out << "NotVerifiedYet"; break; + } + return out; +} + +std::ostream& operator<< (std::ostream &out, Poppler::SignatureValidationInfo::CertificateStatus status) +{ + switch (status) { + case Poppler::SignatureValidationInfo::CertificateTrusted: out << "Trusted"; break; + case Poppler::SignatureValidationInfo::CertificateUntrustedIssuer: out << "UntrustedIssuer"; break; + case Poppler::SignatureValidationInfo::CertificateUnknownIssuer: out << "UnknownIssuer"; break; + case Poppler::SignatureValidationInfo::CertificateRevoked: out << "Revoked"; break; + case Poppler::SignatureValidationInfo::CertificateExpired: out << "Expired"; break; + case Poppler::SignatureValidationInfo::CertificateGenericError: out << "GenericError"; break; + case Poppler::SignatureValidationInfo::CertificateNotVerified: out << "NotVerifiedYet"; break; + } + return out; +} + std::ostream& operator<< (std::ostream &out, Qt::Alignment alignment) { switch (alignment) { @@ -155,7 +184,22 @@ } break; - case Poppler::FormField::FormSignature: + case Poppler::FormField::FormSignature: { + const Poppler::FormFieldSignature *signatureForm = static_cast(form); + const Poppler::SignatureValidationInfo svi = signatureForm->validate(Poppler::FormFieldSignature::ValidateVerifyCertificate); + std::cout << "\t\t\tSignatureStatus: " << svi.signatureStatus() << std::endl; + std::cout << "\t\t\tCertificateStatus: " << svi.certificateStatus() << std::endl; + if (svi.signerName().isEmpty() == false) + std::cout << "\t\t\tSignerName: " << svi.signerName() << std::endl; + else + std::cout << "\t\t\tSignerName: " << "(null)" << std::endl; + // http://doc.qt.io/qt-5/qdatetime.html#fromTime_t-1 + // Requires Qt 5.2 -> configure.ac update + // QDateTime::fromTime_t(svi.signingTime(), Qt::UTC).toString(); + QDateTime sviTime; + sviTime.setTime_t(svi.signingTime()); + std::cout << "\t\t\tSigningTime: " << sviTime.toString() << std::endl; + } break; } }