mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Fix decryption of objects with number > 511, better use of zlib library
This commit is contained in:
@ -135,6 +135,16 @@ openssl_lib.files = $$PDFFORQT_DEPENDENCIES_PATH/OpenSSL/libcrypto-3.dll $$PDFFO
|
|||||||
openssl_lib.path = $$DESTDIR/install
|
openssl_lib.path = $$DESTDIR/install
|
||||||
INSTALLS += openssl_lib
|
INSTALLS += openssl_lib
|
||||||
|
|
||||||
|
# Link zlib
|
||||||
|
LIBS += -L$$PDFFORQT_DEPENDENCIES_PATH/zlib/bin/ -lzlib
|
||||||
|
INCLUDEPATH += $$PDFFORQT_DEPENDENCIES_PATH/zlib/include
|
||||||
|
DEPENDPATH += $$PDFFORQT_DEPENDENCIES_PATH/zlib/include
|
||||||
|
|
||||||
|
# Add zlib to installations
|
||||||
|
zlib.files = $$PDFFORQT_DEPENDENCIES_PATH/zlib/bin/zlib.dll
|
||||||
|
zlib.path = $$DESTDIR/install
|
||||||
|
INSTALLS += zlib
|
||||||
|
|
||||||
# ensure debug info even for RELEASE build
|
# ensure debug info even for RELEASE build
|
||||||
CONFIG += force_debug_info
|
CONFIG += force_debug_info
|
||||||
|
|
||||||
|
@ -517,11 +517,19 @@ void PDFPageContentProcessor::processContent(const QByteArray& content)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PDFPageContentProcessor::processContentStream(const PDFStream* stream)
|
void PDFPageContentProcessor::processContentStream(const PDFStream* stream)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
QByteArray content = m_document->getDecodedStream(stream);
|
QByteArray content = m_document->getDecodedStream(stream);
|
||||||
|
|
||||||
processContent(content);
|
processContent(content);
|
||||||
}
|
}
|
||||||
|
catch (PDFParserException exception)
|
||||||
|
{
|
||||||
|
m_operands.clear();
|
||||||
|
m_errorList.append(PDFRenderError(RenderErrorType::Error, exception.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PDFPageContentProcessor::processForm(const QMatrix& matrix, const QRectF& boundingBox, const PDFObject& resources, const QByteArray& content)
|
void PDFPageContentProcessor::processForm(const QMatrix& matrix, const QRectF& boundingBox, const PDFObject& resources, const QByteArray& content)
|
||||||
{
|
{
|
||||||
|
@ -660,7 +660,7 @@ QByteArray PDFStandardSecurityHandler::decryptUsingFilter(const QByteArray& data
|
|||||||
std::vector<uint8_t> inputKeyData = convertByteArrayToVector(m_authorizationData.fileEncryptionKey);
|
std::vector<uint8_t> inputKeyData = convertByteArrayToVector(m_authorizationData.fileEncryptionKey);
|
||||||
uint32_t objectNumber = qToLittleEndian(static_cast<uint32_t>(reference.objectNumber));
|
uint32_t objectNumber = qToLittleEndian(static_cast<uint32_t>(reference.objectNumber));
|
||||||
uint32_t generation = qToLittleEndian(static_cast<uint32_t>(reference.generation));
|
uint32_t generation = qToLittleEndian(static_cast<uint32_t>(reference.generation));
|
||||||
inputKeyData.insert(inputKeyData.cend(), { uint8_t(objectNumber & 0xFF), uint8_t((objectNumber >> 8) && 0xFF), uint8_t((objectNumber >> 16) && 0xFF), uint8_t(generation & 0xFF), uint8_t((generation >> 8) && 0xFF), });
|
inputKeyData.insert(inputKeyData.cend(), { uint8_t(objectNumber & 0xFF), uint8_t((objectNumber >> 8) & 0xFF), uint8_t((objectNumber >> 16) & 0xFF), uint8_t(generation & 0xFF), uint8_t((generation >> 8) & 0xFF) });
|
||||||
std::vector<uint8_t> objectEncryptionKey(MD5_DIGEST_LENGTH, uint8_t(0));
|
std::vector<uint8_t> objectEncryptionKey(MD5_DIGEST_LENGTH, uint8_t(0));
|
||||||
MD5(inputKeyData.data(), inputKeyData.size(), objectEncryptionKey.data());
|
MD5(inputKeyData.data(), inputKeyData.size(), objectEncryptionKey.data());
|
||||||
|
|
||||||
@ -682,7 +682,7 @@ QByteArray PDFStandardSecurityHandler::decryptUsingFilter(const QByteArray& data
|
|||||||
std::vector<uint8_t> inputKeyData = convertByteArrayToVector(m_authorizationData.fileEncryptionKey);
|
std::vector<uint8_t> inputKeyData = convertByteArrayToVector(m_authorizationData.fileEncryptionKey);
|
||||||
uint32_t objectNumber = qToLittleEndian(static_cast<uint32_t>(reference.objectNumber));
|
uint32_t objectNumber = qToLittleEndian(static_cast<uint32_t>(reference.objectNumber));
|
||||||
uint32_t generation = qToLittleEndian(static_cast<uint32_t>(reference.generation));
|
uint32_t generation = qToLittleEndian(static_cast<uint32_t>(reference.generation));
|
||||||
inputKeyData.insert(inputKeyData.cend(), { uint8_t(objectNumber & 0xFF), uint8_t((objectNumber >> 8) && 0xFF), uint8_t((objectNumber >> 16) && 0xFF), uint8_t(generation & 0xFF), uint8_t((generation >> 8) && 0xFF), 0x73, 0x41, 0x6C, 0x54 });
|
inputKeyData.insert(inputKeyData.cend(), { uint8_t(objectNumber & 0xFF), uint8_t((objectNumber >> 8) & 0xFF), uint8_t((objectNumber >> 16) & 0xFF), uint8_t(generation & 0xFF), uint8_t((generation >> 8) & 0xFF), 0x73, 0x41, 0x6C, 0x54 });
|
||||||
std::vector<uint8_t> objectEncryptionKey(MD5_DIGEST_LENGTH, uint8_t(0));
|
std::vector<uint8_t> objectEncryptionKey(MD5_DIGEST_LENGTH, uint8_t(0));
|
||||||
MD5(inputKeyData.data(), inputKeyData.size(), objectEncryptionKey.data());
|
MD5(inputKeyData.data(), inputKeyData.size(), objectEncryptionKey.data());
|
||||||
|
|
||||||
|
@ -20,6 +20,9 @@
|
|||||||
#include "pdfconstants.h"
|
#include "pdfconstants.h"
|
||||||
#include "pdfparser.h"
|
#include "pdfparser.h"
|
||||||
#include "pdfsecurityhandler.h"
|
#include "pdfsecurityhandler.h"
|
||||||
|
#include "pdfutils.h"
|
||||||
|
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
#include <QtEndian>
|
#include <QtEndian>
|
||||||
|
|
||||||
@ -395,16 +398,55 @@ QByteArray PDFFlateDecodeFilter::apply(const QByteArray& data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t size = data.size();
|
|
||||||
|
|
||||||
QByteArray dataToUncompress;
|
|
||||||
dataToUncompress.resize(sizeof(decltype(size)) + data.size());
|
|
||||||
|
|
||||||
qToBigEndian(size, dataToUncompress.data());
|
|
||||||
std::copy(data.cbegin(), data.cend(), std::next(dataToUncompress.begin(), sizeof(decltype(size))));
|
|
||||||
|
|
||||||
PDFStreamPredictor predictor = PDFStreamPredictor::createPredictor(objectFetcher, parameters);
|
PDFStreamPredictor predictor = PDFStreamPredictor::createPredictor(objectFetcher, parameters);
|
||||||
return predictor.apply(qUncompress(dataToUncompress));
|
return predictor.apply(uncompress(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray PDFFlateDecodeFilter::uncompress(const QByteArray& data)
|
||||||
|
{
|
||||||
|
QByteArray result;
|
||||||
|
|
||||||
|
z_stream stream = { };
|
||||||
|
stream.next_in = const_cast<Bytef*>(convertByteArrayToUcharPtr(data));
|
||||||
|
stream.avail_in = data.size();
|
||||||
|
|
||||||
|
std::array<Bytef, 1024> outputBuffer = { };
|
||||||
|
|
||||||
|
int error = inflateInit(&stream);
|
||||||
|
if (error != Z_OK)
|
||||||
|
{
|
||||||
|
throw PDFParserException(PDFTranslationContext::tr("Failed to initialize flate decompression stream."));
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
stream.next_out = outputBuffer.data();
|
||||||
|
stream.avail_out = static_cast<uInt>(outputBuffer.size());
|
||||||
|
|
||||||
|
error = inflate(&stream, Z_NO_FLUSH);
|
||||||
|
|
||||||
|
int bytesWritten = int(outputBuffer.size()) - stream.avail_out;
|
||||||
|
result.append(reinterpret_cast<const char*>(outputBuffer.data()), bytesWritten);
|
||||||
|
} while (error == Z_OK);
|
||||||
|
|
||||||
|
QString errorMessage;
|
||||||
|
if (stream.msg)
|
||||||
|
{
|
||||||
|
errorMessage = QString::fromLatin1(stream.msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
inflateEnd(&stream);
|
||||||
|
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case Z_STREAM_END:
|
||||||
|
break; // No error, normal behaviour
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw PDFParserException(PDFTranslationContext::tr("Error decompressing by flate method: %1").arg(errorMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray PDFRunLengthDecodeFilter::apply(const QByteArray& data,
|
QByteArray PDFRunLengthDecodeFilter::apply(const QByteArray& data,
|
||||||
|
@ -184,6 +184,9 @@ public:
|
|||||||
const PDFObjectFetcher& objectFetcher,
|
const PDFObjectFetcher& objectFetcher,
|
||||||
const PDFObject& parameters,
|
const PDFObject& parameters,
|
||||||
const PDFSecurityHandler* securityHandler) const override;
|
const PDFSecurityHandler* securityHandler) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static QByteArray uncompress(const QByteArray& data);
|
||||||
};
|
};
|
||||||
|
|
||||||
class PDFFORQTLIBSHARED_EXPORT PDFRunLengthDecodeFilter : public PDFStreamFilter
|
class PDFFORQTLIBSHARED_EXPORT PDFRunLengthDecodeFilter : public PDFStreamFilter
|
||||||
|
Reference in New Issue
Block a user