From f03bbfa89dcb77d64bfffa8a21d08caee23f8e59 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Wed, 29 Dec 2021 19:28:34 +0100 Subject: [PATCH] PDF: Allow signing documents that need password to open them We need the password since in the middle of the signing process we need to reopen the document we just created to do some final modifications --- core/document.cpp | 11 +++++++++++ core/document.h | 6 ++++++ generators/poppler/CMakeLists.txt | 10 ++++++++++ generators/poppler/config-okular-poppler.h.cmake | 2 ++ generators/poppler/generator_pdf.cpp | 12 ++++++++++++ part/pageview.cpp | 11 +++++++++++ part/pageviewannotator.cpp | 12 ++++++++++++ 7 files changed, 64 insertions(+) diff --git a/core/document.cpp b/core/document.cpp index 8d0a6ff85..bb26c5266 100644 --- a/core/document.cpp +++ b/core/document.cpp @@ -5516,6 +5516,7 @@ struct Okular::NewSignatureDataPrivate { QString certNickname; QString certSubjectCommonName; QString password; + QString documentPassword; int page; NormalizedRect boundingRectangle; }; @@ -5580,6 +5581,16 @@ void NewSignatureData::setBoundingRectangle(const NormalizedRect &rect) d->boundingRectangle = rect; } +QString NewSignatureData::documentPassword() const +{ + return d->documentPassword; +} + +void NewSignatureData::setDocumentPassword(const QString &password) +{ + d->documentPassword = password; +} + #undef foreachObserver #undef foreachObserverD diff --git a/core/document.h b/core/document.h index a941b5efb..0ce1db2ce 100644 --- a/core/document.h +++ b/core/document.h @@ -1520,6 +1520,12 @@ public: NormalizedRect boundingRectangle() const; void setBoundingRectangle(const NormalizedRect &rect); + /// @since 22.04 + QString documentPassword() const; + + /// @since 22.04 + void setDocumentPassword(const QString &password); + private: NewSignatureDataPrivate *const d; }; diff --git a/generators/poppler/CMakeLists.txt b/generators/poppler/CMakeLists.txt index c23e334b0..82fb63aab 100644 --- a/generators/poppler/CMakeLists.txt +++ b/generators/poppler/CMakeLists.txt @@ -55,6 +55,16 @@ int main() } " HAVE_POPPLER_21_10) +check_cxx_source_compiles(" +#include +#include +int main() +{ + Poppler::PDFConverter::NewSignatureData pData; + pData.setDocumentOwnerPassword(QByteArray()); +} +" HAVE_POPPLER_22_02) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/config-okular-poppler.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-okular-poppler.h diff --git a/generators/poppler/config-okular-poppler.h.cmake b/generators/poppler/config-okular-poppler.h.cmake index d1a8e5df1..24c165f5f 100644 --- a/generators/poppler/config-okular-poppler.h.cmake +++ b/generators/poppler/config-okular-poppler.h.cmake @@ -13,3 +13,5 @@ /* Defined if we have the 21.10 version of the Poppler library or later */ #cmakedefine HAVE_POPPLER_21_10 1 +/* Defined if we have the 22.02 version of the Poppler library or later */ +#cmakedefine HAVE_POPPLER_22_02 1 diff --git a/generators/poppler/generator_pdf.cpp b/generators/poppler/generator_pdf.cpp index 65ddd9bd1..5192b077f 100644 --- a/generators/poppler/generator_pdf.cpp +++ b/generators/poppler/generator_pdf.cpp @@ -1469,6 +1469,14 @@ QVariant PDFGenerator::metaData(const QString &key, const QVariant &option) cons return QStringLiteral("no"); #else return QStringLiteral("yes"); +#endif + } else if (key == QLatin1String("DocumentHasPassword")) { + return pdfdoc->isEncrypted() ? QStringLiteral("yes") : QStringLiteral("no"); + } else if (key == QLatin1String("CanSignDocumentWithPassword")) { +#ifdef HAVE_POPPLER_22_02 + return QStringLiteral("yes"); +#else + return QStringLiteral("no"); #endif } return QVariant(); @@ -1920,6 +1928,10 @@ bool PDFGenerator::sign(const Okular::NewSignatureData &oData, const QString &rF pData.setBoundingRectangle({bRect.left, bRect.top, bRect.width(), bRect.height()}); pData.setFontColor(Qt::black); pData.setBorderColor(Qt::black); +#if HAVE_POPPLER_22_02 + pData.setDocumentOwnerPassword(oData.documentPassword().toLatin1()); + pData.setDocumentUserPassword(oData.documentPassword().toLatin1()); +#endif if (!converter->sign(pData)) return false; diff --git a/part/pageview.cpp b/part/pageview.cpp index 1e3659120..ac73069c3 100644 --- a/part/pageview.cpp +++ b/part/pageview.cpp @@ -4901,6 +4901,17 @@ void PageView::slotSignature() return; } + const bool documentHasPassword = d->document->metaData(QStringLiteral("DocumentHasPassword")).toString() == QLatin1String("yes"); + if (documentHasPassword) { + if (d->document->metaData(QStringLiteral("CanSignDocumentWithPassword")).toString() == QLatin1String("no")) { + KMessageBox::information(nullptr, + i18nc("@info", "The version of the Poppler library this Okular was compiled with does not support signing documents with passwords. Please ask your provider to update it to 22.02 or later."), + i18nc("@title:window", "Poppler library is too old"), + QStringLiteral("popplerOldSignVersion")); + return; + } + } + const Okular::CertificateStore *certStore = d->document->certificateStore(); bool userCancelled, nonDateValidCerts; const QList &certs = certStore->signingCertificatesForNow(&userCancelled, &nonDateValidCerts); diff --git a/part/pageviewannotator.cpp b/part/pageviewannotator.cpp index 393683b2d..4a076e3bf 100644 --- a/part/pageviewannotator.cpp +++ b/part/pageviewannotator.cpp @@ -409,6 +409,15 @@ public: m_aborted = true; } + if (m_document->metaData(QStringLiteral("DocumentHasPassword")).toString() == QLatin1String("yes")) { + bool ok; + documentPassword = QInputDialog::getText(m_pageView, i18n("Enter document password"), i18n("Enter document password"), QLineEdit::Password, QString(), &ok); + if (!ok) { + passToUse.clear(); + m_aborted = true; + } + } + m_creationCompleted = false; clicked = false; @@ -438,9 +447,11 @@ public: data.setCertNickname(certNicknameToUse); data.setCertSubjectCommonName(certCommonName); data.setPassword(passToUse); + data.setDocumentPassword(documentPassword); data.setPage(m_page->number()); data.setBoundingRectangle(rect); passToUse.clear(); + documentPassword.clear(); return m_document->sign(data, newFilePath); } @@ -448,6 +459,7 @@ private: QString certNicknameToUse; QString certCommonName; QString passToUse; + QString documentPassword; Okular::Document *m_document; const Okular::Page *m_page;