Issue #161: Can it be possible to trust a certificate like in acrobat?

This commit is contained in:
Jakub Melka
2025-02-17 18:11:28 +01:00
parent 2024a7c2d0
commit 7dededa324
11 changed files with 202 additions and 17 deletions

View File

@ -666,11 +666,11 @@ void MainWindow::setViewDocument(pdf::PDFDocument* document, bool updateCustomPa
if (document) if (document)
{ {
pdf::PDFModifiedDocument modifiedDocument(document, m_optionalContentActivity); pdf::PDFModifiedDocument modifiedDocument(document, m_optionalContentActivity);
m_pdfWidget->setDocument(modifiedDocument); m_pdfWidget->setDocument(modifiedDocument, {});
} }
else else
{ {
m_pdfWidget->setDocument(pdf::PDFModifiedDocument()); m_pdfWidget->setDocument(pdf::PDFModifiedDocument(), {});
} }
} }

View File

@ -24,7 +24,6 @@
#include "pdfparser.h" #include "pdfparser.h"
#include "pdfform.h" #include "pdfform.h"
#include "pdfpainterutils.h" #include "pdfpainterutils.h"
#include "pdfdocumentbuilder.h"
#include <QtMath> #include <QtMath>
#include <QIcon> #include <QIcon>

View File

@ -1744,7 +1744,7 @@ void PDFProgramController::onFileChanged(const QString& fileName)
QByteArray hash = pdf::PDFDocumentReader::hash(data); QByteArray hash = pdf::PDFDocumentReader::hash(data);
if (m_pdfDocument && m_pdfDocument->getSourceDataHash() != hash) if (m_pdfDocument && m_pdfDocument->getSourceDataHash() != hash)
{ {
auto queryPassword = [this](bool* ok) auto queryPassword = [](bool* ok)
{ {
*ok = false; *ok = false;
return QString(); return QString();
@ -1879,7 +1879,7 @@ void PDFProgramController::onDocumentReadingFinished()
m_pdfDocument = qMove(result.document); m_pdfDocument = qMove(result.document);
m_signatures = qMove(result.signatures); m_signatures = qMove(result.signatures);
pdf::PDFModifiedDocument document(m_pdfDocument.data(), m_optionalContentActivity); pdf::PDFModifiedDocument document(m_pdfDocument.data(), m_optionalContentActivity);
setDocument(document, true); setDocument(document, m_signatures, true);
if (m_formManager) if (m_formManager)
{ {
@ -1951,17 +1951,17 @@ void PDFProgramController::onDocumentModified(pdf::PDFModifiedDocument document)
m_pdfDocument = document; m_pdfDocument = document;
document.setOptionalContentActivity(m_optionalContentActivity); document.setOptionalContentActivity(m_optionalContentActivity);
setDocument(document, false); setDocument(document, {}, false);
} }
void PDFProgramController::onDocumentUndoRedo(pdf::PDFModifiedDocument document) void PDFProgramController::onDocumentUndoRedo(pdf::PDFModifiedDocument document)
{ {
m_pdfDocument = document; m_pdfDocument = document;
document.setOptionalContentActivity(m_optionalContentActivity); document.setOptionalContentActivity(m_optionalContentActivity);
setDocument(document, false); setDocument(document, {}, false);
} }
void PDFProgramController::setDocument(pdf::PDFModifiedDocument document, bool isCurrentSaved) void PDFProgramController::setDocument(pdf::PDFModifiedDocument document, std::vector<pdf::PDFSignatureVerificationResult> signatureVerificationResult, bool isCurrentSaved)
{ {
if (document.hasReset()) if (document.hasReset())
{ {
@ -2021,7 +2021,7 @@ void PDFProgramController::setDocument(pdf::PDFModifiedDocument document, bool i
m_undoRedoManager->setIsCurrentSaved(isCurrentSaved); m_undoRedoManager->setIsCurrentSaved(isCurrentSaved);
} }
m_pdfWidget->setDocument(document); m_pdfWidget->setDocument(document, std::move(signatureVerificationResult));
m_mainWindowInterface->setDocument(document); m_mainWindowInterface->setDocument(document);
m_CMSManager->setDocument(document); m_CMSManager->setDocument(document);
@ -2065,7 +2065,7 @@ void PDFProgramController::closeDocument()
} }
m_signatures.clear(); m_signatures.clear();
setDocument(pdf::PDFModifiedDocument(), true); setDocument(pdf::PDFModifiedDocument(), {}, true);
m_pdfDocument.reset(); m_pdfDocument.reset();
updateActionsAvailability(); updateActionsAvailability();
updateTitle(); updateTitle();

View File

@ -275,7 +275,7 @@ public:
Q_DECLARE_FLAGS(Features, Feature) Q_DECLARE_FLAGS(Features, Feature)
void openDocument(const QString& fileName); void openDocument(const QString& fileName);
void setDocument(pdf::PDFModifiedDocument document, bool isCurrentSaved); void setDocument(pdf::PDFModifiedDocument document, std::vector<pdf::PDFSignatureVerificationResult> signatureVerificationResult, bool isCurrentSaved);
void closeDocument(); void closeDocument();
pdf::PDFWidget* getPdfWidget() const { return m_pdfWidget; } pdf::PDFWidget* getPdfWidget() const { return m_pdfWidget; }

View File

@ -487,7 +487,7 @@ PDFDrawWidgetProxy::~PDFDrawWidgetProxy()
} }
void PDFDrawWidgetProxy::setDocument(const PDFModifiedDocument& document) void PDFDrawWidgetProxy::setDocument(const PDFModifiedDocument& document, std::vector<PDFSignatureVerificationResult> signatureVerificationResult)
{ {
if (getDocument() != document) if (getDocument() != document)
{ {
@ -509,6 +509,8 @@ void PDFDrawWidgetProxy::setDocument(const PDFModifiedDocument& document)
m_cacheClearTimer->start(CACHE_CLEAR_TIMEOUT); m_cacheClearTimer->start(CACHE_CLEAR_TIMEOUT);
} }
} }
m_signatureVerificationResult = std::move(signatureVerificationResult);
} }
void PDFDrawWidgetProxy::init(PDFWidget* widget) void PDFDrawWidgetProxy::init(PDFWidget* widget)

View File

@ -18,6 +18,7 @@
#ifndef PDFDRAWSPACECONTROLLER_H #ifndef PDFDRAWSPACECONTROLLER_H
#define PDFDRAWSPACECONTROLLER_H #define PDFDRAWSPACECONTROLLER_H
#include "pdfsignaturehandler.h"
#include "pdfwidgetsglobal.h" #include "pdfwidgetsglobal.h"
#include "pdfglobal.h" #include "pdfglobal.h"
#include "pdfdocument.h" #include "pdfdocument.h"
@ -190,7 +191,7 @@ public:
/// in that case, draw space is cleared. Optional content activity can be nullptr, /// in that case, draw space is cleared. Optional content activity can be nullptr,
/// in that case, no content is suppressed. /// in that case, no content is suppressed.
/// \param document Document /// \param document Document
void setDocument(const PDFModifiedDocument& document); void setDocument(const PDFModifiedDocument& document, std::vector<PDFSignatureVerificationResult> signatureVerificationResult);
void init(PDFWidget* widget); void init(PDFWidget* widget);
@ -374,6 +375,7 @@ public:
void setGroupTransparency(PDFInteger groupIndex, bool drawPaper = true, PDFReal transparency = 1.0); void setGroupTransparency(PDFInteger groupIndex, bool drawPaper = true, PDFReal transparency = 1.0);
PDFWidgetAnnotationManager* getAnnotationManager() const; PDFWidgetAnnotationManager* getAnnotationManager() const;
const std::vector<PDFSignatureVerificationResult>& getSignatureVerificationResult() const { return m_signatureVerificationResult; }
signals: signals:
void drawSpaceChanged(); void drawSpaceChanged();
@ -540,6 +542,9 @@ private:
/// can be rendered with transparency or without paper /// can be rendered with transparency or without paper
/// as overlay. /// as overlay.
std::map<PDFInteger, GroupInfo> m_groupInfos; std::map<PDFInteger, GroupInfo> m_groupInfos;
/// Signature verification results
std::vector<PDFSignatureVerificationResult> m_signatureVerificationResult;
}; };
} // namespace pdf } // namespace pdf

View File

@ -86,9 +86,9 @@ bool PDFWidget::focusNextPrevChild(bool next)
return QWidget::focusNextPrevChild(next); return QWidget::focusNextPrevChild(next);
} }
void PDFWidget::setDocument(const PDFModifiedDocument& document) void PDFWidget::setDocument(const PDFModifiedDocument& document, std::vector<PDFSignatureVerificationResult> signatureVerificationResult)
{ {
m_proxy->setDocument(document); m_proxy->setDocument(document, std::move(signatureVerificationResult));
m_pageRenderingErrors.clear(); m_pageRenderingErrors.clear();
m_drawWidget->getWidget()->update(); m_drawWidget->getWidget()->update();
} }

View File

@ -18,6 +18,7 @@
#ifndef PDFDRAWWIDGET_H #ifndef PDFDRAWWIDGET_H
#define PDFDRAWWIDGET_H #define PDFDRAWWIDGET_H
#include "pdfsignaturehandler.h"
#include "pdfwidgetsglobal.h" #include "pdfwidgetsglobal.h"
#include "pdfglobal.h" #include "pdfglobal.h"
#include "pdfrenderer.h" #include "pdfrenderer.h"
@ -73,7 +74,7 @@ public:
/// in that case, widget contents are cleared. Optional content activity can be nullptr, /// in that case, widget contents are cleared. Optional content activity can be nullptr,
/// if this occurs, no content is suppressed. /// if this occurs, no content is suppressed.
/// \param document Document /// \param document Document
void setDocument(const PDFModifiedDocument& document); void setDocument(const PDFModifiedDocument& document, std::vector<PDFSignatureVerificationResult> signatureVerificationResult);
/// Update rendering engine according the settings /// Update rendering engine according the settings
/// \param engine Engine type /// \param engine Engine type

View File

@ -248,6 +248,179 @@ private:
PDFTextEditPseudowidget m_textEdit; PDFTextEditPseudowidget m_textEdit;
}; };
/// Editor for signatures
class PDFFormFieldSignatureEditor : public PDFFormFieldWidgetEditor
{
Q_DECLARE_TR_FUNCTIONS(pdf::PDFFormFieldSignatureEditor)
private:
using BaseClass = PDFFormFieldWidgetEditor;
public:
explicit PDFFormFieldSignatureEditor(PDFWidgetFormManager* formManager, PDFFormWidget formWidget);
virtual ~PDFFormFieldSignatureEditor() = default;
virtual bool isEditorDrawEnabled() const override;
virtual void draw(AnnotationDrawParameters& parameters, bool edit) const override;
};
PDFFormFieldSignatureEditor::PDFFormFieldSignatureEditor(PDFWidgetFormManager* formManager, PDFFormWidget formWidget) :
BaseClass(formManager, formWidget)
{
}
bool PDFFormFieldSignatureEditor::isEditorDrawEnabled() const
{
PDFDrawWidgetProxy* proxy = m_formManager->getProxy();
if (proxy)
{
const std::vector<PDFSignatureVerificationResult>& signatureVerificationResult = proxy->getSignatureVerificationResult();
QString qualifiedName = m_formWidget.getParent()->getName(PDFFormField::NameType::FullyQualified);
for (const PDFSignatureVerificationResult& result : signatureVerificationResult)
{
if (result.getSignatureFieldQualifiedName() == qualifiedName)
{
return true;
}
}
}
return false;
}
void PDFFormFieldSignatureEditor::draw(AnnotationDrawParameters& parameters, bool edit) const
{
PDFPainterStateGuard guard(parameters.painter);
PDFDrawWidgetProxy* proxy = m_formManager->getProxy();
const PDFSignatureVerificationResult* verificationResult = nullptr;
Q_UNUSED(edit);
if (proxy)
{
const std::vector<PDFSignatureVerificationResult>& signatureVerificationResult = proxy->getSignatureVerificationResult();
QString qualifiedName = m_formWidget.getParent()->getName(PDFFormField::NameType::FullyQualified);
for (const PDFSignatureVerificationResult& result : signatureVerificationResult)
{
if (result.getSignatureFieldQualifiedName() == qualifiedName)
{
verificationResult = &result;
break;
}
}
}
bool isValid = false;
QString text = tr("Signature Unknown");
if (verificationResult)
{
if (verificationResult->isValid())
{
isValid = true;
text = tr("Signature Valid");
}
else
{
isValid = false;
text = tr("Signature Invalid");
}
}
QColor foregroundColor = parameters.colorConvertor.convert(QColor(Qt::black), false, true);
parameters.painter->setPen(foregroundColor);
parameters.painter->setBrush(parameters.colorConvertor.convert(QColor(Qt::white), true, false));
QRectF rect = m_formManager->getWidgetRectangle(m_formWidget);
parameters.boundingRectangle = rect;
parameters.painter->drawRect(rect);
QRectF textRect = rect;
textRect.setHeight(rect.height() * 0.25);
textRect.setWidth(rect.width() * 0.95);
textRect.translate((rect.width() - textRect.width()) * 0.5, rect.height() * 0.75);
QPainterPath path;
path.addText(0, 0, parameters.painter->font(), text);
QSizeF textSize = path.boundingRect().size();
qreal factor = qMin(textRect.width() / textSize.width(), textRect.height() / textSize.height());
QTransform matrix;
matrix.scale(factor, -factor);
path = matrix.map(path);
path.translate(textRect.center() - path.boundingRect().center());
parameters.painter->fillPath(path, foregroundColor);
QPainterPath mark;
if (isValid)
{
parameters.painter->setBrush(Qt::darkGreen);
parameters.painter->setPen(Qt::NoPen);
QPolygonF checkmark;
checkmark << QPointF(40, 120)
<< QPointF(70, 150)
<< QPointF(160, 40)
<< QPointF(140, 20)
<< QPointF(70, 120)
<< QPointF(50, 100);
mark.addPolygon(checkmark);
}
else
{
parameters.painter->setBrush(Qt::darkRed);
parameters.painter->setPen(Qt::NoPen);
const double halfThickness = 10.0;
const double halfLength = 50.0;
QPolygonF checkmark;
checkmark << QPointF(-halfLength, -halfThickness)
<< QPointF(-halfLength, +halfThickness)
<< QPointF(+halfLength, +halfThickness)
<< QPointF(+halfLength, -halfThickness)
<< QPointF(-halfLength, -halfThickness);
mark.addPolygon(checkmark);
checkmark.clear();
checkmark << QPointF(-halfThickness, -halfLength)
<< QPointF(-halfThickness, +halfLength)
<< QPointF(+halfThickness, +halfLength)
<< QPointF(+halfThickness, -halfLength)
<< QPointF(-halfThickness, -halfLength);
mark.addPolygon(checkmark);
mark.setFillRule(Qt::WindingFill);
QTransform transform;
transform.rotate(45.0);
mark = transform.map(mark);
}
QRectF markRect = rect;
markRect.setHeight(rect.height() - textRect.height());
QPointF markCenter = markRect.center();
markRect.setHeight(markRect.height() * 0.75);
markRect.setWidth(markRect.width() * 0.75);
markRect.moveCenter(markCenter);
QRectF markSymbolRect = mark.boundingRect();
qreal symbolFactor = qMin(markRect.width() / markSymbolRect.width(), markRect.height() / markSymbolRect.height());
QTransform markTransform;
markTransform.scale(symbolFactor, -symbolFactor);
mark = markTransform.map(mark);
mark.translate(markRect.center() - mark.boundingRect().center());
parameters.painter->drawPath(mark);
}
/// Editor for combo boxes /// Editor for combo boxes
class PDFFormFieldComboBoxEditor : public PDFFormFieldWidgetEditor class PDFFormFieldComboBoxEditor : public PDFFormFieldWidgetEditor
{ {
@ -761,8 +934,10 @@ void PDFWidgetFormManager::updateFormWidgetEditors()
} }
case PDFFormField::FieldType::Signature: case PDFFormField::FieldType::Signature:
// Signature fields doesn't have editor {
m_widgetEditors.push_back(new PDFFormFieldSignatureEditor(this, widget));
break; break;
}
default: default:
Q_ASSERT(false); Q_ASSERT(false);

View File

@ -144,6 +144,8 @@ public:
PDFWidgetAnnotationManager* getAnnotationManager() const; PDFWidgetAnnotationManager* getAnnotationManager() const;
void setAnnotationManager(PDFWidgetAnnotationManager* annotationManager); void setAnnotationManager(PDFWidgetAnnotationManager* annotationManager);
PDFDrawWidgetProxy* getProxy() const { return m_proxy; }
protected: protected:
virtual void updateFieldValues() override; virtual void updateFieldValues() override;
virtual void onDocumentReset() override; virtual void onDocumentReset() override;

View File

@ -10,6 +10,7 @@ CURRENT:
- Issue #200: Icons under dark theme on Arch/KDE is broken - Issue #200: Icons under dark theme on Arch/KDE is broken
- Issue #185: Latest git fails to build in linux - Issue #185: Latest git fails to build in linux
- Issue #165: Insert > Inline Text latency issues on Flatpak and Appimage packages - Issue #165: Insert > Inline Text latency issues on Flatpak and Appimage packages
- Issue #161: Can it be possible to trust a certificate like in acrobat?
V: 1.4.0.0 4.7.2024 V: 1.4.0.0 4.7.2024
- Issue #190: PageMaster crash + black bubbles instead of bubbles with correct color - Issue #190: PageMaster crash + black bubbles instead of bubbles with correct color