diff --git a/core/form.h b/core/form.h --- a/core/form.h +++ b/core/form.h @@ -24,6 +24,7 @@ class FormFieldButtonPrivate; class FormFieldTextPrivate; class FormFieldChoicePrivate; +class FormFieldSignaturePrivate; /** * @short The base interface of a form field. @@ -363,6 +364,61 @@ Q_DISABLE_COPY( FormFieldChoice ) }; +/** + * @short Interface of a signature form field. + * + * This is the base interface to reimplement to represent a signature field. + */ +class OKULARCORE_EXPORT FormFieldSignature : public FormField +{ + public: + /** + * The types of signature. + */ + enum SignatureType { + AdbePkcs7sha1, + AdbePkcs7detached, + EtsiCAdESdetached, + UnknownType + }; + + /** + * The validation options of this signature. + */ + enum ValidateOptions { + ValidateVerifyCertificate = 1, ///< Validate the certificate. + ValidateForceRevalidation = 2, ///< Force revalidation of the certificate. + }; + + ~FormFieldSignature(); + + /** + * The signature type + */ + virtual SignatureType signatureType() const = 0; + + /** + * Validate the signature with 'now' as validation time. + * + * @return QByteArray containing signature validation info as binary data. + */ + virtual QMap validate( ValidateOptions opt ) const = 0; + + /** + * Validate the signature with @p validationTime as validation time. + * + * @return QByteArray containing signature validation info as binary data. + */ + virtual QMap validate( int opt, const QString& validationTime ) const = 0; + + protected: + FormFieldSignature(); + + private: + Q_DECLARE_PRIVATE( FormFieldSignature ) + Q_DISABLE_COPY( FormFieldSignature ) +}; + } #endif diff --git a/core/form.cpp b/core/form.cpp --- a/core/form.cpp +++ b/core/form.cpp @@ -271,3 +271,32 @@ return false; } +class Okular::FormFieldSignaturePrivate : public Okular::FormFieldPrivate +{ + public: + FormFieldSignaturePrivate() + : FormFieldPrivate( FormField::FormSignature ) + { + } + + Q_DECLARE_PUBLIC( FormFieldSignature ) + + void setValue( const QString& v ) override + { + Q_UNUSED( v ) + } + + QString value() const override + { + return QString(); + } +}; + +FormFieldSignature::FormFieldSignature() + : FormField( *new FormFieldSignaturePrivate() ) +{ +} + +FormFieldSignature::~FormFieldSignature() +{ +} diff --git a/generators/poppler/formfields.h b/generators/poppler/formfields.h --- a/generators/poppler/formfields.h +++ b/generators/poppler/formfields.h @@ -105,4 +105,64 @@ }; +class PopplerFormFieldSignature : public Okular::FormFieldSignature +{ + public: + PopplerFormFieldSignature( Poppler::FormFieldSignature * field ); + virtual ~PopplerFormFieldSignature(); + + // inherited from Okular::FormField + Okular::NormalizedRect rect() const override; + int id() const override; + QString name() const override; + QString uiName() const override; + bool isReadOnly() const override; + bool isVisible() const override; + + // inherited from Okular::FormFieldSignature + FormFieldSignature::SignatureType signatureType() const override; + QVariantMap validate( FormFieldSignature::ValidateOptions opt ) const override; + QVariantMap validate( int opt, const QString& validationTime) const override; + + private: + Poppler::FormFieldSignature * m_field; + Okular::NormalizedRect m_rect; + int m_id; +}; + + +class PopplerSignatureValidationInfo +{ + public: + PopplerSignatureValidationInfo( const Poppler::SignatureValidationInfo &info ); + PopplerSignatureValidationInfo( const QVariantMap &info ); + + 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. + }; + + 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. + }; + + QVariantMap toMap() const; + + private: + QVariantMap m_info; + +}; + + #endif diff --git a/generators/poppler/formfields.cpp b/generators/poppler/formfields.cpp --- a/generators/poppler/formfields.cpp +++ b/generators/poppler/formfields.cpp @@ -300,4 +300,165 @@ return m_field->canBeSpellChecked(); } +PopplerFormFieldSignature::PopplerFormFieldSignature( Poppler::FormFieldSignature * field ) + : Okular::FormFieldSignature(), m_field( field ) +{ + m_rect = Okular::NormalizedRect::fromQRectF( m_field->rect() ); + m_id = m_field->id(); + SET_ACTIONS +} + +PopplerFormFieldSignature::~PopplerFormFieldSignature() +{ + delete m_field; +} + +Okular::NormalizedRect PopplerFormFieldSignature::rect() const +{ + return m_rect; +} + +int PopplerFormFieldSignature::id() const +{ + return m_id; +} + +QString PopplerFormFieldSignature::name() const +{ + return m_field->name(); +} + +QString PopplerFormFieldSignature::uiName() const +{ + return m_field->uiName(); +} + +bool PopplerFormFieldSignature::isReadOnly() const +{ + return m_field->isReadOnly(); +} + +bool PopplerFormFieldSignature::isVisible() const +{ + return m_field->isVisible(); +} + +PopplerFormFieldSignature::SignatureType PopplerFormFieldSignature::signatureType() const +{ + switch ( m_field->signatureType() ) + { + case Poppler::FormFieldSignature::AdbePkcs7sha1: + return Okular::FormFieldSignature::AdbePkcs7sha1; + case Poppler::FormFieldSignature::AdbePkcs7detached: + return Okular::FormFieldSignature::AdbePkcs7detached; + case Poppler::FormFieldSignature::EtsiCAdESdetached: + return Okular::FormFieldSignature::EtsiCAdESdetached; + default: + return Okular::FormFieldSignature::UnknownType; + } +} + +QVariantMap PopplerFormFieldSignature::validate( ValidateOptions opt ) const +{ + Poppler::FormFieldSignature::ValidateOptions popplerOpt; + switch ( opt ) + { + case Okular::FormFieldSignature::ValidateVerifyCertificate: + popplerOpt = Poppler::FormFieldSignature::ValidateVerifyCertificate; + break; + case Okular::FormFieldSignature::ValidateForceRevalidation: + popplerOpt = Poppler::FormFieldSignature::ValidateForceRevalidation; + break; + } + + return PopplerSignatureValidationInfo( m_field->validate( popplerOpt ) ).toMap(); +} + +QVariantMap PopplerFormFieldSignature::validate( int opt, const QString& validationTimeStr ) const +{ + QDateTime validationTime = QDateTime::fromString(validationTimeStr); + return PopplerSignatureValidationInfo( m_field->validate( opt, validationTime ) ).toMap(); +} + +PopplerSignatureValidationInfo::PopplerSignatureValidationInfo( const Poppler::SignatureValidationInfo& info ) +{ + QString signStat; + switch ( info.signatureStatus() ) + { + case PopplerSignatureValidationInfo::SignatureValid: + signStat = QStringLiteral( "Signature is Valid." ); + break; + + case PopplerSignatureValidationInfo::SignatureInvalid: + signStat = QStringLiteral( "Signature is Invalid." ); + break; + + case PopplerSignatureValidationInfo::SignatureDigestMismatch: + signStat = QStringLiteral( "Digest Mismatch." ); + break; + + case PopplerSignatureValidationInfo::SignatureDecodingError: + signStat = QStringLiteral( "Document isn't signed or corrupted data." ); + break; + + case PopplerSignatureValidationInfo::SignatureNotVerified: + signStat = QStringLiteral( "Signature has not yet been verified." ); + break; + default: + signStat = QStringLiteral( "Unknown Validation Failure." ); + break; + } + + QString certStat; + switch( info.certificateStatus() ) + { + case PopplerSignatureValidationInfo::CertificateTrusted: + certStat = QStringLiteral( "Certificate is Trusted." ); + break; + + case PopplerSignatureValidationInfo::CertificateUntrustedIssuer: + certStat = QStringLiteral( "Certificate issuer isn't Trusted." ); + break; + + case PopplerSignatureValidationInfo::CertificateUnknownIssuer: + certStat = QStringLiteral( "Certificate issuer is unknown." ); + break; + + case PopplerSignatureValidationInfo::CertificateRevoked: + certStat = QStringLiteral( "Certificate has been Revoked." ); + break; + + case PopplerSignatureValidationInfo::CertificateExpired: + certStat = QStringLiteral( "Certificate has Expired." ); + break; + + case PopplerSignatureValidationInfo::CertificateNotVerified: + certStat = QStringLiteral( "Certificate has not yet been verified." ); + break; + + default: + certStat = QStringLiteral( "Unknown issue with Certificate or corrupted data." ); + break; + } + + m_info["SignatureStatus"] = signStat; + m_info["CertificateStatus"] = certStat; + m_info["SignerName"] = info.signerName(); + m_info["SubjectDN"] = info.signerSubjectDN(); + m_info["HashAlgorithm"] = info.hashAlgorithm(); + m_info["SigningTime"] = qint64(info.signingTime()); + m_info["Signature"] = info.signature(); + m_info["SignedRanges"] = QVariant::fromValue>(info.signedRangeBounds()); + m_info["IsTotalDocumentSigned"] = info.signsTotalDocument(); +} + +PopplerSignatureValidationInfo::PopplerSignatureValidationInfo( const QVariantMap &info ) +{ + m_info = info; +} + +QVariantMap PopplerSignatureValidationInfo::toMap() const +{ + return m_info; +} diff --git a/generators/poppler/generator_pdf.h b/generators/poppler/generator_pdf.h --- a/generators/poppler/generator_pdf.h +++ b/generators/poppler/generator_pdf.h @@ -35,6 +35,8 @@ class PDFOptionsPage; class PopplerAnnotationProxy; +class PopplerFormFieldSignature; +class PopplerSignatureValidationInfo; /** * @short A generator that builds contents from a PDF document. @@ -149,6 +151,8 @@ QPointer pdfOptionsPage; PrintError lastPrintError; + + QList signValidationInfoList; }; #endif diff --git a/generators/poppler/generator_pdf.cpp b/generators/poppler/generator_pdf.cpp --- a/generators/poppler/generator_pdf.cpp +++ b/generators/poppler/generator_pdf.cpp @@ -1802,6 +1802,7 @@ { QList popplerFormFields = popplerPage->formFields(); QLinkedList okularFormFields; + signValidationInfoList.clear(); foreach( Poppler::FormField *f, popplerFormFields ) { Okular::FormField * of = 0; @@ -1816,6 +1817,14 @@ case Poppler::FormField::FormChoice: of = new PopplerFormFieldChoice( static_cast( f ) ); break; + case Poppler::FormField::FormSignature: { + auto of = new PopplerFormFieldSignature( static_cast( f ) ); + if ( of ) + { + signValidationInfoList.append( of->validate( PopplerFormFieldSignature::ValidateVerifyCertificate ) ); + } + break; + } default: ; } if ( of )