--- qt5/src/poppler-form.h 2016-11-30 04:03:36.923458836 +0100 +++ qt5/src/poppler-form.h 2016-12-04 10:32:21.478554137 +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 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(SignatureStatus signatureStatus, + CertificateStatus certificateStatus, QString signerName, time_t signingTime); + /// \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: + SignatureStatus signature_status; + CertificateStatus certificate_status; + + QString signer_name; + time_t signing_time; + }; + + /** + 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. + */ + SignatureValidationInfo *validate(ValidateOptions opt) const; + + private: + Q_DISABLE_COPY(FormFieldSignature) + }; + } #endif --- qt5/src/poppler-page.cc 2016-11-30 04:03:56.807459434 +0100 +++ qt5/src/poppler-page.cc 2016-11-30 04:04:19.355460112 +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 2016-11-30 04:03:44.655459068 +0100 +++ qt5/src/poppler-form.cc 2016-12-04 19:38:06.347538929 +0100 @@ -26,6 +26,7 @@ #include #include #include +#include #include "poppler-form.h" #include "poppler-page-private.h" @@ -414,4 +415,114 @@ return !fwc->noSpellCheck(); } + +SignatureValidationInfo::SignatureValidationInfo(SignatureStatus signatureStatus, + CertificateStatus certificateStatus, QString signerName, time_t signingTime) + : signature_status(signatureStatus), + certificate_status(certificateStatus), + signer_name(signerName), + signing_time(signingTime) +{ +} + +SignatureValidationInfo::~SignatureValidationInfo() +{ +} + +const SignatureValidationInfo::SignatureStatus SignatureValidationInfo::signatureStatus() const +{ + return signature_status; +} + +const SignatureValidationInfo::CertificateStatus SignatureValidationInfo::certificateStatus() const +{ + return certificate_status; +} + +const QString SignatureValidationInfo::signerName() const +{ + return signer_name; +} + +const time_t SignatureValidationInfo::signingTime() const +{ + return 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; +} + +SignatureValidationInfo *FormFieldSignature::validate(ValidateOptions opt) const +{ + FormWidgetSignature* fws = static_cast(m_formData->fm); + SignatureInfo* si = fws->validateSignature( + opt & ValidateVerifyCertificate, opt & ValidateForceRevalidation); + SignatureValidationInfo::SignatureStatus signature_status; + SignatureValidationInfo::CertificateStatus certificate_status; + switch (si->getSignatureValStatus()) { + case SIGNATURE_VALID: + signature_status = SignatureValidationInfo::SignatureValid; + break; + case SIGNATURE_INVALID: + signature_status = SignatureValidationInfo::SignatureInvalid; + break; + case SIGNATURE_DIGEST_MISMATCH: + signature_status = SignatureValidationInfo::SignatureDigestMismatch; + break; + case SIGNATURE_DECODING_ERROR: + signature_status = SignatureValidationInfo::SignatureDecodingError; + break; + default: + case SIGNATURE_GENERIC_ERROR: + signature_status = SignatureValidationInfo::SignatureGenericError; + break; + case SIGNATURE_NOT_FOUND: + signature_status = SignatureValidationInfo::SignatureNotFound; + break; + case SIGNATURE_NOT_VERIFIED: + signature_status = SignatureValidationInfo::SignatureNotVerified; + break; + } + switch (si->getCertificateValStatus()) { + case CERTIFICATE_TRUSTED: + certificate_status = SignatureValidationInfo::CertificateTrusted; + break; + case CERTIFICATE_UNTRUSTED_ISSUER: + certificate_status = SignatureValidationInfo::CertificateUntrustedIssuer; + break; + case CERTIFICATE_UNKNOWN_ISSUER: + certificate_status = SignatureValidationInfo::CertificateUnknownIssuer; + break; + case CERTIFICATE_REVOKED: + certificate_status = SignatureValidationInfo::CertificateRevoked; + break; + case CERTIFICATE_EXPIRED: + certificate_status = SignatureValidationInfo::CertificateExpired; + break; + default: + case CERTIFICATE_GENERIC_ERROR: + certificate_status = SignatureValidationInfo::CertificateGenericError; + break; + case CERTIFICATE_NOT_VERIFIED: + certificate_status = SignatureValidationInfo::CertificateNotVerified; + break; + } + QString signer_name = si->getSignerName(); + time_t signing_time = si->getSigningTime(); + + return new SignatureValidationInfo(signature_status, certificate_status, signer_name, signing_time); +} + } --- qt5/tests/poppler-forms.cpp 2016-11-30 04:04:07.319459750 +0100 +++ qt5/tests/poppler-forms.cpp 2016-12-04 10:34:43.434558406 +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,23 @@ } break; - case Poppler::FormField::FormSignature: + case Poppler::FormField::FormSignature: { + const Poppler::FormFieldSignature *signatureForm = static_cast(form); + 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; + delete svi; + } break; } }