mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-01-29 16:49:32 +01:00
Validation settings, certificate store
This commit is contained in:
parent
aa36af6587
commit
49a2af275f
@ -26,6 +26,7 @@
|
||||
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QDataStream>
|
||||
|
||||
#include <array>
|
||||
|
||||
@ -139,24 +140,24 @@ PDFSignature PDFSignature::parse(const PDFObjectStorage* storage, PDFObject obje
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFSignatureHandler* PDFSignatureHandler::createHandler(const PDFFormFieldSignature* signatureField, const QByteArray& sourceData)
|
||||
PDFSignatureHandler* PDFSignatureHandler::createHandler(const PDFFormFieldSignature* signatureField, const QByteArray& sourceData, const Parameters& parameters)
|
||||
{
|
||||
Q_ASSERT(signatureField);
|
||||
|
||||
const QByteArray& subfilter = signatureField->getSignature().getSubfilter();
|
||||
if (subfilter == "adbe.pkcs7.detached")
|
||||
{
|
||||
return new PDFSignatureHandler_adbe_pkcs7_detached(signatureField, sourceData);
|
||||
return new PDFSignatureHandler_adbe_pkcs7_detached(signatureField, sourceData, parameters);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<PDFSignatureVerificationResult> PDFSignatureHandler::verifySignatures(const PDFForm& form, const QByteArray& sourceData)
|
||||
std::vector<PDFSignatureVerificationResult> PDFSignatureHandler::verifySignatures(const PDFForm& form, const QByteArray& sourceData, const Parameters& parameters)
|
||||
{
|
||||
std::vector<PDFSignatureVerificationResult> result;
|
||||
|
||||
if (form.isAcroForm() || form.isXFAForm())
|
||||
if (parameters.enableVerification && (form.isAcroForm() || form.isXFAForm()))
|
||||
{
|
||||
std::vector<const PDFFormFieldSignature*> signatureFields;
|
||||
auto getSignatureFields = [&signatureFields](const PDFFormField* field)
|
||||
@ -173,7 +174,7 @@ std::vector<PDFSignatureVerificationResult> PDFSignatureHandler::verifySignature
|
||||
|
||||
for (const PDFFormFieldSignature* signatureField : signatureFields)
|
||||
{
|
||||
if (const PDFSignatureHandler* signatureHandler = createHandler(signatureField, sourceData))
|
||||
if (const PDFSignatureHandler* signatureHandler = createHandler(signatureField, sourceData, parameters))
|
||||
{
|
||||
result.emplace_back(signatureHandler->verify());
|
||||
delete signatureHandler;
|
||||
@ -399,7 +400,12 @@ void PDFPublicKeySignatureHandler::verifyCertificate(PDFSignatureVerificationRes
|
||||
break;
|
||||
}
|
||||
|
||||
X509_STORE_CTX_set_flags(context, X509_V_FLAG_TRUSTED_FIRST);
|
||||
unsigned long flags = X509_V_FLAG_TRUSTED_FIRST;
|
||||
if (m_parameters.ignoreExpirationDate)
|
||||
{
|
||||
flags |= X509_V_FLAG_NO_CHECK_TIME;
|
||||
}
|
||||
X509_STORE_CTX_set_flags(context, flags);
|
||||
|
||||
int verificationResult = X509_verify_cert(context);
|
||||
if (verificationResult <= 0)
|
||||
@ -766,11 +772,47 @@ PDFCertificateInfo PDFPublicKeySignatureHandler::getCertificateInfo(X509* certif
|
||||
|
||||
info.setKeyUsage(static_cast<PDFCertificateInfo::KeyUsageFlags>(keyUsage));
|
||||
}
|
||||
|
||||
unsigned char* buffer = nullptr;
|
||||
int length = i2d_X509(certificate, &buffer);
|
||||
if (length >= 0)
|
||||
{
|
||||
Q_ASSERT(buffer);
|
||||
info.setCertificateData(QByteArray(reinterpret_cast<const char*>(buffer), length));
|
||||
OPENSSL_free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void PDFCertificateInfo::serialize(QDataStream& stream) const
|
||||
{
|
||||
stream << persist_version;
|
||||
stream << m_version;
|
||||
stream << m_keySize;
|
||||
stream << m_publicKey;
|
||||
stream << m_nameEntries;
|
||||
stream << m_notValidBefore;
|
||||
stream << m_notValidAfter;
|
||||
stream << m_keyUsage;
|
||||
stream << m_certificateData;
|
||||
}
|
||||
|
||||
void PDFCertificateInfo::deserialize(QDataStream& stream)
|
||||
{
|
||||
int persist_version = 0;
|
||||
stream >> persist_version;
|
||||
stream >> m_version;
|
||||
stream >> m_keySize;
|
||||
stream >> m_publicKey;
|
||||
stream >> m_nameEntries;
|
||||
stream >> m_notValidBefore;
|
||||
stream >> m_notValidAfter;
|
||||
stream >> m_keyUsage;
|
||||
stream >> m_certificateData;
|
||||
}
|
||||
|
||||
QDateTime PDFCertificateInfo::getNotValidBefore() const
|
||||
{
|
||||
return m_notValidBefore;
|
||||
@ -791,12 +833,12 @@ void PDFCertificateInfo::setNotValidAfter(const QDateTime& notValidAfter)
|
||||
m_notValidAfter = notValidAfter;
|
||||
}
|
||||
|
||||
long PDFCertificateInfo::getVersion() const
|
||||
int32_t PDFCertificateInfo::getVersion() const
|
||||
{
|
||||
return m_version;
|
||||
}
|
||||
|
||||
void PDFCertificateInfo::setVersion(long version)
|
||||
void PDFCertificateInfo::setVersion(int32_t version)
|
||||
{
|
||||
m_version = version;
|
||||
}
|
||||
@ -831,6 +873,46 @@ void PDFCertificateInfo::setKeyUsage(KeyUsageFlags keyUsage)
|
||||
m_keyUsage = keyUsage;
|
||||
}
|
||||
|
||||
std::optional<PDFCertificateInfo> PDFCertificateInfo::getCertificateInfo(const QByteArray& certificateData)
|
||||
{
|
||||
std::optional<PDFCertificateInfo> result;
|
||||
|
||||
PDFOpenSSLGlobalLock lock;
|
||||
const unsigned char* data = reinterpret_cast<const unsigned char*>(certificateData.constData());
|
||||
if (X509* certificate = d2i_X509(nullptr, &data, certificateData.length()))
|
||||
{
|
||||
result = PDFPublicKeySignatureHandler::getCertificateInfo(certificate);
|
||||
X509_free(certificate);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QByteArray PDFCertificateInfo::getCertificateData() const
|
||||
{
|
||||
return m_certificateData;
|
||||
}
|
||||
|
||||
void PDFCertificateInfo::setCertificateData(const QByteArray& certificateData)
|
||||
{
|
||||
m_certificateData = certificateData;
|
||||
}
|
||||
|
||||
void PDFCertificateStore::CertificateEntry::serialize(QDataStream& stream) const
|
||||
{
|
||||
stream << persist_version;
|
||||
stream << type;
|
||||
stream << info;
|
||||
}
|
||||
|
||||
void PDFCertificateStore::CertificateEntry::deserialize(QDataStream& stream)
|
||||
{
|
||||
int persist_version = 0;
|
||||
stream >> persist_version;
|
||||
stream >> type;
|
||||
stream >> info;
|
||||
}
|
||||
|
||||
QString PDFPublicKeySignatureHandler::getStringFromX509Name(X509_NAME* name, int nid)
|
||||
{
|
||||
QString result;
|
||||
@ -852,7 +934,7 @@ QString PDFPublicKeySignatureHandler::getStringFromX509Name(X509_NAME* name, int
|
||||
return result;
|
||||
}
|
||||
|
||||
QDateTime pdf::PDFPublicKeySignatureHandler::getDateTimeFromASN(const ASN1_TIME* time)
|
||||
QDateTime PDFPublicKeySignatureHandler::getDateTimeFromASN(const ASN1_TIME* time)
|
||||
{
|
||||
QDateTime result;
|
||||
|
||||
@ -869,6 +951,45 @@ QDateTime pdf::PDFPublicKeySignatureHandler::getDateTimeFromASN(const ASN1_TIME*
|
||||
return result;
|
||||
}
|
||||
|
||||
void PDFCertificateStore::serialize(QDataStream& stream) const
|
||||
{
|
||||
stream << persist_version;
|
||||
stream << m_certificates;
|
||||
}
|
||||
|
||||
void pdf::PDFCertificateStore::deserialize(QDataStream& stream)
|
||||
{
|
||||
int persist_version = 0;
|
||||
stream >> persist_version;
|
||||
stream >> m_certificates;
|
||||
}
|
||||
|
||||
bool PDFCertificateStore::add(EntryType type, const QByteArray& certificate)
|
||||
{
|
||||
if (auto certificateInfo = PDFCertificateInfo::getCertificateInfo(certificate))
|
||||
{
|
||||
return add(type, qMove(*certificateInfo));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PDFCertificateStore::add(EntryType type, PDFCertificateInfo info)
|
||||
{
|
||||
auto it = std::find_if(m_certificates.cbegin(), m_certificates.cend(), [&info](const auto& entry) { return entry.info == info; });
|
||||
if (it == m_certificates.cend())
|
||||
{
|
||||
m_certificates.push_back({ type, qMove(info) });
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pdf::PDFCertificateStore::contains(const pdf::PDFCertificateInfo& info)
|
||||
{
|
||||
return std::find_if(m_certificates.cbegin(), m_certificates.cend(), [&info](const auto& entry) { return entry.info == info; }) != m_certificates.cend();
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
@ -879,23 +1000,42 @@ QDateTime pdf::PDFPublicKeySignatureHandler::getDateTimeFromASN(const ASN1_TIME*
|
||||
|
||||
void pdf::PDFPublicKeySignatureHandler::addTrustedCertificates(X509_STORE* store) const
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
HCERTSTORE certStore = CertOpenSystemStore(NULL, L"ROOT");
|
||||
PCCERT_CONTEXT context = nullptr;
|
||||
if (certStore)
|
||||
if (m_parameters.store)
|
||||
{
|
||||
while (context = CertEnumCertificatesInStore(certStore, context))
|
||||
const PDFCertificateStore::CertificateEntries& certificates = m_parameters.store->getCertificates();
|
||||
for (const auto& entry : certificates)
|
||||
{
|
||||
const unsigned char* pointer = context->pbCertEncoded;
|
||||
X509* certificate = d2i_X509(nullptr, &pointer, context->cbCertEncoded);
|
||||
QByteArray certificateData = entry.info.getCertificateData();
|
||||
const unsigned char* pointer = reinterpret_cast<const unsigned char*>(certificateData.constData());
|
||||
X509* certificate = d2i_X509(nullptr, &pointer, certificateData.length());
|
||||
if (certificate)
|
||||
{
|
||||
X509_STORE_add_cert(store, certificate);
|
||||
X509_free(certificate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CertCloseStore(certStore, CERT_CLOSE_STORE_FORCE_FLAG);
|
||||
#ifdef Q_OS_WIN
|
||||
if (m_parameters.useSystemCertificateStore)
|
||||
{
|
||||
HCERTSTORE certStore = CertOpenSystemStore(NULL, L"ROOT");
|
||||
PCCERT_CONTEXT context = nullptr;
|
||||
if (certStore)
|
||||
{
|
||||
while (context = CertEnumCertificatesInStore(certStore, context))
|
||||
{
|
||||
const unsigned char* pointer = context->pbCertEncoded;
|
||||
X509* certificate = d2i_X509(nullptr, &pointer, context->cbCertEncoded);
|
||||
if (certificate)
|
||||
{
|
||||
X509_STORE_add_cert(store, certificate);
|
||||
X509_free(certificate);
|
||||
}
|
||||
}
|
||||
|
||||
CertCloseStore(certStore, CERT_CLOSE_STORE_FORCE_FLAG);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -26,10 +26,13 @@
|
||||
|
||||
#include <optional>
|
||||
|
||||
class QDataStream;
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
class PDFForm;
|
||||
class PDFObjectStorage;
|
||||
class PDFCertificateStore;
|
||||
class PDFFormFieldSignature;
|
||||
|
||||
/// Signature reference dictionary.
|
||||
@ -153,6 +156,15 @@ class PDFFORQTLIBSHARED_EXPORT PDFCertificateInfo
|
||||
public:
|
||||
explicit inline PDFCertificateInfo() = default;
|
||||
|
||||
void serialize(QDataStream& stream) const;
|
||||
void deserialize(QDataStream& stream);
|
||||
|
||||
friend inline QDataStream& operator<<(QDataStream& stream, const PDFCertificateInfo& info) { info.serialize(stream); return stream; }
|
||||
friend inline QDataStream& operator>>(QDataStream& stream, PDFCertificateInfo& info) { info.deserialize(stream); return stream; }
|
||||
|
||||
bool operator ==(const PDFCertificateInfo&) const = default;
|
||||
bool operator !=(const PDFCertificateInfo&) const = default;
|
||||
|
||||
/// These entries are taken from RFC 5280, section 4.1.2.4,
|
||||
/// they are supported and loaded from the certificate, with
|
||||
/// exception of Email entry.
|
||||
@ -210,8 +222,8 @@ public:
|
||||
QDateTime getNotValidAfter() const;
|
||||
void setNotValidAfter(const QDateTime& notValidAfter);
|
||||
|
||||
long getVersion() const;
|
||||
void setVersion(long version);
|
||||
int32_t getVersion() const;
|
||||
void setVersion(int32_t version);
|
||||
|
||||
PublicKey getPublicKey() const;
|
||||
void setPublicKey(const PublicKey& publicKey);
|
||||
@ -222,14 +234,25 @@ public:
|
||||
KeyUsageFlags getKeyUsage() const;
|
||||
void setKeyUsage(KeyUsageFlags keyUsage);
|
||||
|
||||
QByteArray getCertificateData() const;
|
||||
void setCertificateData(const QByteArray& certificateData);
|
||||
|
||||
/// Creates certificate info from binary data. Binary data must
|
||||
/// contain DER-encoded certificate.
|
||||
/// \param certificateData Data
|
||||
static std::optional<PDFCertificateInfo> getCertificateInfo(const QByteArray& certificateData);
|
||||
|
||||
private:
|
||||
long m_version = 0;
|
||||
static constexpr int persist_version = 1;
|
||||
|
||||
int32_t m_version = 0;
|
||||
int m_keySize = 0;
|
||||
PublicKey m_publicKey = KeyUnknown;
|
||||
std::array<QString, NameEnd> m_nameEntries;
|
||||
QDateTime m_notValidBefore;
|
||||
QDateTime m_notValidAfter;
|
||||
KeyUsageFlags m_keyUsage;
|
||||
QByteArray m_certificateData;
|
||||
};
|
||||
|
||||
using PDFCertificateInfos = std::vector<PDFCertificateInfo>;
|
||||
@ -349,11 +372,20 @@ public:
|
||||
|
||||
virtual PDFSignatureVerificationResult verify() const = 0;
|
||||
|
||||
struct Parameters
|
||||
{
|
||||
const PDFCertificateStore* store = nullptr;
|
||||
bool enableVerification = true;
|
||||
bool ignoreExpirationDate = false;
|
||||
bool useSystemCertificateStore = true;
|
||||
};
|
||||
|
||||
/// Tries to verify all signatures in the form. If form is invalid, then
|
||||
/// empty vector is returned.
|
||||
/// \param form Form
|
||||
/// \param sourceData Source data
|
||||
static std::vector<PDFSignatureVerificationResult> verifySignatures(const PDFForm& form, const QByteArray& sourceData);
|
||||
/// \param parameters Verification settings
|
||||
static std::vector<PDFSignatureVerificationResult> verifySignatures(const PDFForm& form, const QByteArray& sourceData, const Parameters& parameters);
|
||||
|
||||
private:
|
||||
|
||||
@ -361,7 +393,71 @@ private:
|
||||
/// If signature format is unknown, then nullptr is returned.
|
||||
/// \param signatureField Signature field
|
||||
/// \param sourceData
|
||||
static PDFSignatureHandler* createHandler(const PDFFormFieldSignature* signatureField, const QByteArray& sourceData);
|
||||
/// \param parameters Verification settings
|
||||
static PDFSignatureHandler* createHandler(const PDFFormFieldSignature* signatureField, const QByteArray& sourceData, const Parameters& parameters);
|
||||
};
|
||||
|
||||
/// Trusted certificate store. Contains list of trusted certificates. Store
|
||||
/// can be persisted to the persistent storage trough serialization/deserialization.
|
||||
/// Persisting method is versioned.
|
||||
class PDFFORQTLIBSHARED_EXPORT PDFCertificateStore
|
||||
{
|
||||
public:
|
||||
explicit inline PDFCertificateStore() = default;
|
||||
|
||||
void serialize(QDataStream& stream) const;
|
||||
void deserialize(QDataStream& stream);
|
||||
|
||||
enum class EntryType : int
|
||||
{
|
||||
User, ///< Certificate has been added manually by the user
|
||||
EUTL ///< Certificate comes EU trusted list
|
||||
};
|
||||
|
||||
struct CertificateEntry
|
||||
{
|
||||
void serialize(QDataStream& stream) const;
|
||||
void deserialize(QDataStream& stream);
|
||||
|
||||
friend inline QDataStream& operator<<(QDataStream& stream, const CertificateEntry& entry) { entry.serialize(stream); return stream; }
|
||||
friend inline QDataStream& operator>>(QDataStream& stream, CertificateEntry& entry) { entry.deserialize(stream); return stream; }
|
||||
|
||||
static constexpr int persist_version = 1;
|
||||
EntryType type = EntryType::User;
|
||||
PDFCertificateInfo info;
|
||||
};
|
||||
|
||||
using CertificateEntries = std::vector<CertificateEntry>;
|
||||
|
||||
/// Tries to add new certificate to the certificate store. If certificate
|
||||
/// is already here, then nothing happens and function returns true.
|
||||
/// Otherwise data are checked, if they really contains a certificate,
|
||||
/// and if yes, then it is added. Function returns false if, and only if,
|
||||
/// error occured and certificate was not added.
|
||||
/// \param type Type
|
||||
/// \param certificate Certificate
|
||||
bool add(EntryType type, const QByteArray& certificate);
|
||||
|
||||
/// Tries to add new certificate to the certificate store. If certificate
|
||||
/// is already here, then nothing happens and function returns true.
|
||||
/// Otherwise data are checked, if they really contains a certificate,
|
||||
/// and if yes, then it is added. Function returns false if, and only if,
|
||||
/// error occured and certificate was not added.
|
||||
/// \param type Type
|
||||
/// \param info Certificate info
|
||||
bool add(EntryType type, PDFCertificateInfo info);
|
||||
|
||||
/// Returns true, if storage contains given certificate
|
||||
/// \param info Certificate info
|
||||
bool contains(const PDFCertificateInfo& info);
|
||||
|
||||
/// Get certificates stored in the store
|
||||
const CertificateEntries& getCertificates() const { return m_certificates; }
|
||||
|
||||
private:
|
||||
static constexpr int persist_version = 1;
|
||||
|
||||
CertificateEntries m_certificates;
|
||||
};
|
||||
|
||||
} // namespace pdf
|
||||
|
@ -31,9 +31,10 @@ namespace pdf
|
||||
class PDFPublicKeySignatureHandler : public PDFSignatureHandler
|
||||
{
|
||||
protected:
|
||||
explicit PDFPublicKeySignatureHandler(const PDFFormFieldSignature* signatureField, const QByteArray& sourceData) :
|
||||
explicit PDFPublicKeySignatureHandler(const PDFFormFieldSignature* signatureField, const QByteArray& sourceData, const Parameters& parameters) :
|
||||
m_signatureField(signatureField),
|
||||
m_sourceData(sourceData)
|
||||
m_sourceData(sourceData),
|
||||
m_parameters(parameters)
|
||||
{
|
||||
|
||||
}
|
||||
@ -45,6 +46,7 @@ protected:
|
||||
|
||||
BIO* getSignedDataBuffer(PDFSignatureVerificationResult& result, QByteArray& outputBuffer) const;
|
||||
|
||||
public:
|
||||
/// Return a list of certificates from PKCS7 object
|
||||
static STACK_OF(X509)* getCertificates(PKCS7* pkcs7);
|
||||
|
||||
@ -61,13 +63,14 @@ protected:
|
||||
protected:
|
||||
const PDFFormFieldSignature* m_signatureField;
|
||||
QByteArray m_sourceData;
|
||||
Parameters m_parameters;
|
||||
};
|
||||
|
||||
class PDFSignatureHandler_adbe_pkcs7_detached : public PDFPublicKeySignatureHandler
|
||||
{
|
||||
public:
|
||||
explicit PDFSignatureHandler_adbe_pkcs7_detached(const PDFFormFieldSignature* signatureField, const QByteArray& sourceData) :
|
||||
PDFPublicKeySignatureHandler(signatureField, sourceData)
|
||||
explicit PDFSignatureHandler_adbe_pkcs7_detached(const PDFFormFieldSignature* signatureField, const QByteArray& sourceData, const Parameters& parameters) :
|
||||
PDFPublicKeySignatureHandler(signatureField, sourceData, parameters)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -248,55 +248,6 @@ size_t PDFTextCharacterSpatialIndex::queryImpl(size_t nodeIndex, const QRectF& r
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
QDataStream& operator>>(QDataStream& stream, std::vector<T>& vector)
|
||||
{
|
||||
std::vector<T>::size_type size = 0;
|
||||
stream >> size;
|
||||
vector.resize(size);
|
||||
for (T& item : vector)
|
||||
{
|
||||
stream >> item;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
QDataStream& operator<<(QDataStream& stream, const std::vector<T>& vector)
|
||||
{
|
||||
stream << vector.size();
|
||||
for (const T& item : vector)
|
||||
{
|
||||
stream << item;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
QDataStream& operator>>(QDataStream& stream, std::set<T>& set)
|
||||
{
|
||||
std::set<T>::size_type size = 0;
|
||||
stream >> size;
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
T item;
|
||||
stream >> item;
|
||||
set.insert(set.end(), qMove(item));
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
QDataStream& operator<<(QDataStream& stream, const std::set<T>& set)
|
||||
{
|
||||
stream << set.size();
|
||||
for (const T& item : set)
|
||||
{
|
||||
stream << item;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
PDFTextLayout::PDFTextLayout()
|
||||
{
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <QByteArray>
|
||||
#include <QDataStream>
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <functional>
|
||||
@ -567,6 +568,94 @@ private:
|
||||
std::vector<ClosedInterval> m_intervals;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
QDataStream& operator>>(QDataStream& stream, std::vector<T>& vector)
|
||||
{
|
||||
std::vector<T>::size_type size = 0;
|
||||
stream >> size;
|
||||
vector.resize(size);
|
||||
for (T& item : vector)
|
||||
{
|
||||
stream >> item;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
QDataStream& operator<<(QDataStream& stream, const std::vector<T>& vector)
|
||||
{
|
||||
stream << vector.size();
|
||||
for (const T& item : vector)
|
||||
{
|
||||
stream << item;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
template<typename T, size_t Size>
|
||||
QDataStream& operator>>(QDataStream& stream, std::array<T, Size>& array)
|
||||
{
|
||||
std::array<T, Size>::size_type size = 0;
|
||||
stream >> size;
|
||||
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
if (i < array.size())
|
||||
{
|
||||
stream >> array[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
T item;
|
||||
stream >> item;
|
||||
}
|
||||
}
|
||||
|
||||
// If array size was changed, then fill in empty objects
|
||||
for (size_t i = size; i < array.size(); ++i)
|
||||
{
|
||||
array[i] = T();
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
template<typename T, size_t Size>
|
||||
QDataStream& operator<<(QDataStream& stream, const std::array<T, Size>& array)
|
||||
{
|
||||
stream << array.size();
|
||||
for (const T& item : array)
|
||||
{
|
||||
stream << item;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
QDataStream& operator>>(QDataStream& stream, std::set<T>& set)
|
||||
{
|
||||
std::set<T>::size_type size = 0;
|
||||
stream >> size;
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
T item;
|
||||
stream >> item;
|
||||
set.insert(set.end(), qMove(item));
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
QDataStream& operator<<(QDataStream& stream, const std::set<T>& set)
|
||||
{
|
||||
stream << set.size();
|
||||
for (const T& item : set)
|
||||
{
|
||||
stream << item;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
||||
#endif // PDFUTILS_H
|
||||
|
@ -50,5 +50,6 @@
|
||||
<file>resources/result-information.svg</file>
|
||||
<file>resources/result-ok.svg</file>
|
||||
<file>resources/result-warning.svg</file>
|
||||
<file>resources/signature.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "pdfsidebarwidget.h"
|
||||
#include "ui_pdfsidebarwidget.h"
|
||||
|
||||
#include "pdfviewersettings.h"
|
||||
|
||||
#include "pdfwidgetutils.h"
|
||||
#include "pdftexttospeech.h"
|
||||
|
||||
@ -45,11 +47,17 @@ constexpr const char* STYLESHEET =
|
||||
"QWidget#speechPage { background-color: #F0F0F0 }"
|
||||
"QWidget#PDFSidebarWidget { background-color: #404040; background: green;}";
|
||||
|
||||
PDFSidebarWidget::PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy, PDFTextToSpeech* textToSpeech, QWidget* parent) :
|
||||
PDFSidebarWidget::PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy,
|
||||
PDFTextToSpeech* textToSpeech,
|
||||
pdf::PDFCertificateStore* certificateStore,
|
||||
PDFViewerSettings* settings,
|
||||
QWidget* parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::PDFSidebarWidget),
|
||||
m_proxy(proxy),
|
||||
m_textToSpeech(textToSpeech),
|
||||
m_certificateStore(certificateStore),
|
||||
m_settings(settings),
|
||||
m_outlineTreeModel(nullptr),
|
||||
m_thumbnailsModel(nullptr),
|
||||
m_optionalContentTreeModel(nullptr),
|
||||
@ -114,6 +122,9 @@ PDFSidebarWidget::PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy, PDFTextToSpee
|
||||
ui->speechRateValueLabel, ui->speechPitchValueLabel, ui->speechVolumeValueLabel,
|
||||
ui->speechActualTextEdit);
|
||||
|
||||
ui->signatureTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->signatureTreeWidget, &QTreeWidget::customContextMenuRequested, this, &PDFSidebarWidget::onSignatureCustomContextMenuRequested);
|
||||
|
||||
selectPage(Invalid);
|
||||
updateButtons();
|
||||
}
|
||||
@ -342,11 +353,18 @@ void PDFSidebarWidget::updateSignatures(const std::vector<pdf::PDFSignatureVerif
|
||||
ui->signatureTreeWidget->setUpdatesEnabled(false);
|
||||
ui->signatureTreeWidget->clear();
|
||||
|
||||
m_certificateInfos.clear();
|
||||
|
||||
QIcon okIcon(":/resources/result-ok.svg");
|
||||
QIcon errorIcon(":/resources/result-error.svg");
|
||||
QIcon warningIcon(":/resources/result-warning.svg");
|
||||
QIcon infoIcon(":/resources/result-information.svg");
|
||||
|
||||
if (m_settings->getSettings().m_signatureTreatWarningsAsErrors)
|
||||
{
|
||||
warningIcon = errorIcon;
|
||||
}
|
||||
|
||||
for (const pdf::PDFSignatureVerificationResult& signature : signatures)
|
||||
{
|
||||
const pdf::PDFCertificateInfos& certificateInfos = signature.getCertificateInfos();
|
||||
@ -401,6 +419,13 @@ void PDFSidebarWidget::updateSignatures(const std::vector<pdf::PDFSignatureVerif
|
||||
QTreeWidgetItem* certRoot = new QTreeWidgetItem(certChainRoot, QStringList(currentCertificateInfo.getName(pdf::PDFCertificateInfo::CommonName)));
|
||||
certRoot->setIcon(0, infoIcon);
|
||||
|
||||
pdf::PDFCertificateInfo::KeyUsageFlags keyUsageFlags = currentCertificateInfo.getKeyUsage();
|
||||
if (keyUsageFlags.testFlag(pdf::PDFCertificateInfo::KeyUsageCertSign))
|
||||
{
|
||||
m_certificateInfos.push_back(currentCertificateInfo);
|
||||
certRoot->setData(0, Qt::UserRole, m_certificateInfos.size() - 1);
|
||||
}
|
||||
|
||||
auto addName = [certRoot, ¤tCertificateInfo, &infoIcon](pdf::PDFCertificateInfo::NameEntry nameEntry, QString caption)
|
||||
{
|
||||
QString text = currentCertificateInfo.getName(nameEntry);
|
||||
@ -473,7 +498,6 @@ void PDFSidebarWidget::updateSignatures(const std::vector<pdf::PDFSignatureVerif
|
||||
}
|
||||
|
||||
QStringList keyUsages;
|
||||
pdf::PDFCertificateInfo::KeyUsageFlags keyUsageFlags = currentCertificateInfo.getKeyUsage();
|
||||
if (keyUsageFlags.testFlag(pdf::PDFCertificateInfo::KeyUsageDigitalSignature))
|
||||
{
|
||||
keyUsages << tr("Digital signatures");
|
||||
@ -619,6 +643,37 @@ void PDFSidebarWidget::onThumbnailClicked(const QModelIndex& index)
|
||||
}
|
||||
}
|
||||
|
||||
void PDFSidebarWidget::onSignatureCustomContextMenuRequested(const QPoint& pos)
|
||||
{
|
||||
if (QTreeWidgetItem* item = ui->signatureTreeWidget->itemAt(pos))
|
||||
{
|
||||
QVariant data = item->data(0, Qt::UserRole);
|
||||
if (data.isValid())
|
||||
{
|
||||
const pdf::PDFCertificateInfo& info = m_certificateInfos.at(data.toInt());
|
||||
if (!m_certificateStore->contains(info))
|
||||
{
|
||||
QMenu menu;
|
||||
QAction* action = menu.addAction(tr("Add to trusted certificates"));
|
||||
|
||||
auto addCertificate = [this, info]()
|
||||
{
|
||||
if (QMessageBox::question(this, tr("Add to Trusted Certificate Store"), tr("Are you sure want to add '%1' to the trusted certificate store?").arg(info.getName(pdf::PDFCertificateInfo::CommonName))) == QMessageBox::Yes)
|
||||
{
|
||||
if (!m_certificateStore->add(pdf::PDFCertificateStore::EntryType::User, info))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Trusted Certificate Store Error"), tr("Failed to add certificate to the trusted certificate store."));
|
||||
}
|
||||
}
|
||||
};
|
||||
connect(action, &QAction::triggered, this, addCertificate);
|
||||
|
||||
menu.exec(ui->signatureTreeWidget->viewport()->mapToGlobal(pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PDFSidebarWidget::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
@ -35,7 +35,9 @@ namespace pdf
|
||||
{
|
||||
class PDFAction;
|
||||
class PDFDocument;
|
||||
class PDFCertificateInfo;
|
||||
class PDFDrawWidgetProxy;
|
||||
class PDFCertificateStore;
|
||||
class PDFModifiedDocument;
|
||||
class PDFThumbnailsItemModel;
|
||||
class PDFOutlineTreeItemModel;
|
||||
@ -48,13 +50,18 @@ class PDFOptionalContentTreeItemModel;
|
||||
namespace pdfviewer
|
||||
{
|
||||
class PDFTextToSpeech;
|
||||
class PDFViewerSettings;
|
||||
|
||||
class PDFSidebarWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy, PDFTextToSpeech* textToSpeech, QWidget* parent);
|
||||
explicit PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy,
|
||||
PDFTextToSpeech* textToSpeech,
|
||||
pdf::PDFCertificateStore* certificateStore,
|
||||
PDFViewerSettings* settings,
|
||||
QWidget* parent);
|
||||
virtual ~PDFSidebarWidget() override;
|
||||
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
@ -102,6 +109,7 @@ private:
|
||||
void onThumbnailsSizeChanged(int size);
|
||||
void onAttachmentCustomContextMenuRequested(const QPoint& pos);
|
||||
void onThumbnailClicked(const QModelIndex& index);
|
||||
void onSignatureCustomContextMenuRequested(const QPoint &pos);
|
||||
|
||||
struct PageInfo
|
||||
{
|
||||
@ -112,6 +120,8 @@ private:
|
||||
Ui::PDFSidebarWidget* ui;
|
||||
pdf::PDFDrawWidgetProxy* m_proxy;
|
||||
PDFTextToSpeech* m_textToSpeech;
|
||||
pdf::PDFCertificateStore* m_certificateStore;
|
||||
PDFViewerSettings* m_settings;
|
||||
pdf::PDFOutlineTreeItemModel* m_outlineTreeModel;
|
||||
pdf::PDFThumbnailsItemModel* m_thumbnailsModel;
|
||||
pdf::PDFOptionalContentTreeItemModel* m_optionalContentTreeModel;
|
||||
@ -120,6 +130,7 @@ private:
|
||||
pdf::PDFAttachmentsTreeItemModel* m_attachmentsTreeModel;
|
||||
std::map<Page, PageInfo> m_pageInfo;
|
||||
std::vector<pdf::PDFSignatureVerificationResult> m_signatures;
|
||||
std::vector<pdf::PDFCertificateInfo> m_certificateInfos;
|
||||
};
|
||||
|
||||
} // namespace pdfviewer
|
||||
|
@ -217,7 +217,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
|
||||
m_pdfWidget->getDrawWidgetProxy()->setProgress(m_progress);
|
||||
m_textToSpeech->setProxy(m_pdfWidget->getDrawWidgetProxy());
|
||||
|
||||
m_sidebarWidget = new PDFSidebarWidget(m_pdfWidget->getDrawWidgetProxy(), m_textToSpeech, this);
|
||||
m_sidebarWidget = new PDFSidebarWidget(m_pdfWidget->getDrawWidgetProxy(), m_textToSpeech, &m_certificateStore, m_settings, this);
|
||||
m_sidebarDockWidget = new QDockWidget(tr("Sidebar"), this);
|
||||
m_sidebarDockWidget->setObjectName("SidebarDockWidget");
|
||||
m_sidebarDockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
||||
@ -966,8 +966,14 @@ void PDFViewerMainWindow::openDocument(const QString& fileName)
|
||||
if (result.result == pdf::PDFDocumentReader::Result::OK)
|
||||
{
|
||||
// Verify signatures
|
||||
pdf::PDFSignatureHandler::Parameters parameters;
|
||||
parameters.store = &m_certificateStore;
|
||||
parameters.enableVerification = m_settings->getSettings().m_signatureVerificationEnabled;
|
||||
parameters.ignoreExpirationDate = m_settings->getSettings().m_signatureIgnoreCertificateValidityTime;
|
||||
parameters.useSystemCertificateStore = m_settings->getSettings().m_signatureUseSystemStore;
|
||||
|
||||
pdf::PDFForm form = pdf::PDFForm::parse(&document, document.getCatalog()->getFormObject());
|
||||
result.signatures = pdf::PDFSignatureHandler::verifySignatures(form, reader.getSource());
|
||||
result.signatures = pdf::PDFSignatureHandler::verifySignatures(form, reader.getSource(), parameters);
|
||||
result.document.reset(new pdf::PDFDocument(qMove(document)));
|
||||
}
|
||||
|
||||
|
@ -98,11 +98,8 @@ private slots:
|
||||
void on_actionRotateLeft_triggered();
|
||||
void on_actionPrint_triggered();
|
||||
void on_actionRender_to_Images_triggered();
|
||||
|
||||
void on_actionOptimize_triggered();
|
||||
|
||||
void on_actionSave_As_triggered();
|
||||
|
||||
void on_actionSave_triggered();
|
||||
|
||||
private:
|
||||
@ -180,6 +177,7 @@ private:
|
||||
QWinTaskbarButton* m_taskbarButton;
|
||||
QWinTaskbarProgress* m_progressTaskbarIndicator;
|
||||
PDFFileInfo m_fileInfo;
|
||||
pdf::PDFCertificateStore m_certificateStore;
|
||||
std::vector<pdf::PDFSignatureVerificationResult> m_signatures;
|
||||
|
||||
QFuture<AsyncReadingResult> m_future;
|
||||
|
@ -86,6 +86,13 @@ void PDFViewerSettings::readSettings(QSettings& settings, const pdf::PDFCMSSetti
|
||||
m_settings.m_formAppearanceFlags = static_cast<pdf::PDFFormManager::FormAppearanceFlags>(settings.value("formAppearance", int(pdf::PDFFormManager::getDefaultApperanceFlags())).toInt());
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup("Signature");
|
||||
m_settings.m_signatureVerificationEnabled = settings.value("signatureVerificationEnabled", defaultSettings.m_signatureVerificationEnabled).toBool();
|
||||
m_settings.m_signatureTreatWarningsAsErrors = settings.value("signatureTreatWarningsAsErrors", defaultSettings.m_signatureTreatWarningsAsErrors).toBool();
|
||||
m_settings.m_signatureIgnoreCertificateValidityTime = settings.value("signatureIgnoreCertificateValidityTime", defaultSettings.m_signatureIgnoreCertificateValidityTime).toBool();
|
||||
m_settings.m_signatureUseSystemStore = settings.value("signatureUseSystemStore", defaultSettings.m_signatureUseSystemStore).toBool();
|
||||
settings.endGroup();
|
||||
|
||||
emit settingsChanged();
|
||||
}
|
||||
|
||||
@ -139,6 +146,13 @@ void PDFViewerSettings::writeSettings(QSettings& settings)
|
||||
settings.beginGroup("Forms");
|
||||
settings.setValue("formAppearance", int(m_settings.m_formAppearanceFlags));
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup("Signature");
|
||||
settings.setValue("signatureVerificationEnabled", m_settings.m_signatureVerificationEnabled);
|
||||
settings.setValue("signatureTreatWarningsAsErrors", m_settings.m_signatureTreatWarningsAsErrors);
|
||||
settings.setValue("signatureIgnoreCertificateValidityTime", m_settings.m_signatureIgnoreCertificateValidityTime);
|
||||
settings.setValue("signatureUseSystemStore", m_settings.m_signatureUseSystemStore);
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
QString PDFViewerSettings::getDirectory() const
|
||||
@ -247,7 +261,11 @@ PDFViewerSettings::Settings::Settings() :
|
||||
m_magnifierZoom(2.0),
|
||||
m_maximumUndoSteps(5),
|
||||
m_maximumRedoSteps(5),
|
||||
m_formAppearanceFlags(pdf::PDFFormManager::getDefaultApperanceFlags())
|
||||
m_formAppearanceFlags(pdf::PDFFormManager::getDefaultApperanceFlags()),
|
||||
m_signatureVerificationEnabled(true),
|
||||
m_signatureTreatWarningsAsErrors(false),
|
||||
m_signatureIgnoreCertificateValidityTime(false),
|
||||
m_signatureUseSystemStore(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -83,6 +83,12 @@ public:
|
||||
|
||||
// Form settings
|
||||
pdf::PDFFormManager::FormAppearanceFlags m_formAppearanceFlags;
|
||||
|
||||
// Signature settings
|
||||
bool m_signatureVerificationEnabled;
|
||||
bool m_signatureTreatWarningsAsErrors;
|
||||
bool m_signatureIgnoreCertificateValidityTime;
|
||||
bool m_signatureUseSystemStore;
|
||||
};
|
||||
|
||||
const Settings& getSettings() const { return m_settings; }
|
||||
|
@ -59,6 +59,7 @@ PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settin
|
||||
new QListWidgetItem(QIcon(":/resources/ui.svg"), tr("UI"), ui->optionsPagesWidget, UISettings);
|
||||
new QListWidgetItem(QIcon(":/resources/speech.svg"), tr("Speech"), ui->optionsPagesWidget, SpeechSettings);
|
||||
new QListWidgetItem(QIcon(":/resources/form-settings.svg"), tr("Forms"), ui->optionsPagesWidget, FormSettings);
|
||||
new QListWidgetItem(QIcon(":/resources/signature.svg"), tr("Signature"), ui->optionsPagesWidget, SignatureSettings);
|
||||
|
||||
ui->renderingEngineComboBox->addItem(tr("Software"), static_cast<int>(pdf::RendererEngine::Software));
|
||||
ui->renderingEngineComboBox->addItem(tr("Hardware accelerated (OpenGL)"), static_cast<int>(pdf::RendererEngine::OpenGL));
|
||||
@ -198,6 +199,10 @@ void PDFViewerSettingsDialog::on_optionsPagesWidget_currentItemChanged(QListWidg
|
||||
ui->stackedWidget->setCurrentWidget(ui->formPage);
|
||||
break;
|
||||
|
||||
case SignatureSettings:
|
||||
ui->stackedWidget->setCurrentWidget(ui->signaturePage);
|
||||
break;
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
@ -327,6 +332,12 @@ void PDFViewerSettingsDialog::loadData()
|
||||
// Form Settings
|
||||
ui->formHighlightFieldsCheckBox->setChecked(m_settings.m_formAppearanceFlags.testFlag(pdf::PDFFormManager::HighlightFields));
|
||||
ui->formHighlightRequiredFieldsCheckBox->setChecked(m_settings.m_formAppearanceFlags.testFlag(pdf::PDFFormManager::HighlightRequiredFields));
|
||||
|
||||
// Signature Settings
|
||||
ui->signatureVerificationEnableCheckBox->setChecked(m_settings.m_signatureVerificationEnabled);
|
||||
ui->signatureStrictModeEnabledCheckBox->setChecked(m_settings.m_signatureTreatWarningsAsErrors);
|
||||
ui->signatureIgnoreExpiredCheckBox->setChecked(m_settings.m_signatureIgnoreCertificateValidityTime);
|
||||
ui->signatureUseSystemCertificateStoreCheckBox->setChecked(m_settings.m_signatureUseSystemStore);
|
||||
}
|
||||
|
||||
void PDFViewerSettingsDialog::saveData()
|
||||
@ -514,6 +525,22 @@ void PDFViewerSettingsDialog::saveData()
|
||||
{
|
||||
m_settings.m_maximumRedoSteps = ui->maximumRedoStepsEdit->value();
|
||||
}
|
||||
else if (sender == ui->signatureVerificationEnableCheckBox)
|
||||
{
|
||||
m_settings.m_signatureVerificationEnabled = ui->signatureVerificationEnableCheckBox->isChecked();
|
||||
}
|
||||
else if (sender == ui->signatureStrictModeEnabledCheckBox)
|
||||
{
|
||||
m_settings.m_signatureTreatWarningsAsErrors = ui->signatureStrictModeEnabledCheckBox->isChecked();
|
||||
}
|
||||
else if (sender == ui->signatureIgnoreExpiredCheckBox)
|
||||
{
|
||||
m_settings.m_signatureIgnoreCertificateValidityTime = ui->signatureIgnoreExpiredCheckBox->isChecked();
|
||||
}
|
||||
else if (sender == ui->signatureUseSystemCertificateStoreCheckBox)
|
||||
{
|
||||
m_settings.m_signatureUseSystemStore = ui->signatureUseSystemCertificateStoreCheckBox->isChecked();
|
||||
}
|
||||
|
||||
const bool loadData = !qobject_cast<const QDoubleSpinBox*>(sender) && !qobject_cast<const QSpinBox*>(sender);
|
||||
if (loadData)
|
||||
|
@ -71,7 +71,8 @@ public:
|
||||
SecuritySettings,
|
||||
UISettings,
|
||||
SpeechSettings,
|
||||
FormSettings
|
||||
FormSettings,
|
||||
SignatureSettings
|
||||
};
|
||||
|
||||
const PDFViewerSettings::Settings& getSettings() const { return m_settings; }
|
||||
|
@ -26,7 +26,7 @@
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>10</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="enginePage">
|
||||
<layout class="QVBoxLayout" name="enginePageLayout">
|
||||
@ -1176,6 +1176,156 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="signaturePage">
|
||||
<layout class="QVBoxLayout" name="signaturePageLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="signatureGroupBox">
|
||||
<property name="title">
|
||||
<string>Digital Signature Verification</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="signatureGroupBoxLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="signatureWidgetsLayout">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="signatureIgnoreExpiredLabel">
|
||||
<property name="text">
|
||||
<string>Ignore expired certificates</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="signatureVerificationLabel">
|
||||
<property name="text">
|
||||
<string>Signature verification</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="signatureStrictModeLabel">
|
||||
<property name="text">
|
||||
<string>Strict mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="signatureVerificationEnableCheckBox">
|
||||
<property name="text">
|
||||
<string>Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="signatureStrictModeEnabledCheckBox">
|
||||
<property name="text">
|
||||
<string>Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="signatureUseSystemCertificateStoreLabel">
|
||||
<property name="text">
|
||||
<string>Use system certificate store</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="signatureIgnoreExpiredCheckBox">
|
||||
<property name="text">
|
||||
<string>Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="signatureUseSystemCertificateStoreCheckBox">
|
||||
<property name="text">
|
||||
<string>Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="signatureCertificatesTableLabel">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-weight:600;">Trusted certificate store</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="trustedCertificateStoreTableWidget"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="trustedCertificateStoreButtonsLayout">
|
||||
<item>
|
||||
<spacer name="trustedCertificateStoreButtonsSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="removeCertificateButton">
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="trustedCertificateStoreDownloadEUTLButton">
|
||||
<property name="text">
|
||||
<string>Download EUTL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="signatureInfoLabel">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Settings for verification of digital signatures. Digital signatures are verified as strict, as possible, to avoid any malicious content or signature manipulation. Verification can also be turned off, if it is not wanted. When <span style=" font-weight:600;">Strict mode</span> is turned on, every warning is treated as error. You can also ignore certificate expiration date, but do this only, if you know what you are doing, because it is dangerous. For verification, list of trusted certificates is used. System certificates can be inserted into the list, and also you can manage your own list of trusted certificates. Also, certificates from EUTL (EU trusted list) can be downloaded into the trusted certificate storage.</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
94
PdfForQtViewer/resources/signature.svg
Normal file
94
PdfForQtViewer/resources/signature.svg
Normal file
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="30mm"
|
||||
height="30mm"
|
||||
viewBox="0 0 30 30"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="signature.svg">
|
||||
<defs
|
||||
id="defs2">
|
||||
<inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect831"
|
||||
is_visible="true" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6"
|
||||
inkscape:cx="166.75422"
|
||||
inkscape:cy="113.44001"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2035"
|
||||
inkscape:window-x="-13"
|
||||
inkscape:window-y="-13"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Melka</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Vrstva 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-267)">
|
||||
<g
|
||||
aria-label="✍"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25.39999962px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
id="text837">
|
||||
<path
|
||||
d="m 24.320405,282.11063 h 4.7625 v 12.47675 H 2.7899365 q -0.471289,0 -0.8805664,-0.17363 -0.396875,-0.17363 -0.7069336,-0.48369 -0.29765621,-0.29766 -0.47128902,-0.70693 -0.17363281,-0.39688 -0.17363281,-0.86817 0,-0.59531 0.24804687,-1.00459 0.24804686,-0.40928 0.64492186,-0.80615 v -1.15342 l 1.5875,-1.5875 q -0.3348633,-0.47129 -0.5208984,-1.00459 -0.1736329,-0.5457 -0.1736329,-1.12861 0,-0.70693 0.2604493,-1.35186 0.2728515,-0.65732 0.7813476,-1.16582 l 5.3454101,-5.34541 q 0.5084961,-0.50849 1.1534179,-0.76894 0.657324,-0.27285 1.364258,-0.27285 h 2.827734 l 6.98252,-6.98252 4.303613,4.30361 -4.526856,4.52686 z m -0.744141,1.78593 -4.638476,-4.65088 q -0.111621,0.11163 -0.496094,0.4961 -0.37207,0.38447 -0.880566,0.89297 -0.496094,0.50849 -1.066602,1.079 -0.558105,0.57051 -1.041797,1.0542 -0.483691,0.48369 -0.818554,0.81856 -0.334864,0.32246 -0.396875,0.35966 0.384472,0.13643 0.483691,0.47129 0.111621,0.32246 0.111621,0.68213 0,0.14883 -0.0124,0.29766 0,0.13642 0,0.27285 0,0.74414 -0.285254,1.40146 -0.272852,0.64493 -0.756543,1.12862 -0.483691,0.48369 -1.141016,0.76894 -0.644922,0.27285 -1.389062,0.27285 H 7.6888622 q -0.3720703,0 -0.6945312,0.13643 -0.322461,0.14883 -0.5705078,0.38447 -0.2356446,0.24805 -0.3844727,0.57051 -0.1364258,0.32246 -0.1364258,0.69453 0,0.33486 0.1364258,0.68213 0.062012,0.0992 0.1116211,0.18604 0.049609,0.0992 0.1116211,0.19843 0.2480469,0.32246 0.6325195,0.5085 0.396875,0.19844 0.79375,0.19844 H 27.296967 v -8.90489 z m -18.566308,8.01192 0.1240234,-0.11162 q -0.1240234,-0.35967 -0.1240234,-0.76895 0,-0.5581 0.2108398,-1.0418 0.2108399,-0.48369 0.5705079,-0.84335 0.3720703,-0.37208 0.8557617,-0.58292 0.4836914,-0.21083 1.0417968,-0.21083 H 8.581831 q 3.150195,-3.1254 6.238379,-6.22598 3.100586,-3.11299 6.238379,-6.25078 l -1.785938,-1.78594 q -4.005957,4.00596 -8.024316,8.01191 -4.0183595,4.00596 -8.0119141,8.03672 v 1.77354 z m 6.238379,-13.36973 q -0.731738,0 -1.2526369,0.5209 l -5.3454101,5.35781 q -0.2480468,0.24805 -0.396875,0.58291 -0.1364257,0.32246 -0.1364257,0.68213 0,0.48369 0.2232422,0.84336 0.2356445,0.35967 0.5953124,0.64492 l 8.6196291,-8.63203 z m 9.810254,-6.23838 -1.153418,1.15342 1.785937,1.78594 1.153418,-1.15342 z"
|
||||
style="stroke-width:0.26458332"
|
||||
id="path839"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.2 KiB |
Loading…
x
Reference in New Issue
Block a user