mirror of https://github.com/JakubMelka/PDF4QT.git
Fix decryption of objects with number > 511, better use of zlib library
This commit is contained in:
parent
cf0f91fdb0
commit
23a36f14a4
|
@ -135,6 +135,16 @@ openssl_lib.files = $$PDFFORQT_DEPENDENCIES_PATH/OpenSSL/libcrypto-3.dll $$PDFFO
|
|||
openssl_lib.path = $$DESTDIR/install
|
||||
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
|
||||
CONFIG += force_debug_info
|
||||
|
||||
|
|
|
@ -518,9 +518,17 @@ void PDFPageContentProcessor::processContent(const QByteArray& content)
|
|||
|
||||
void PDFPageContentProcessor::processContentStream(const PDFStream* stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
QByteArray content = m_document->getDecodedStream(stream);
|
||||
|
||||
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)
|
||||
|
|
|
@ -660,7 +660,7 @@ QByteArray PDFStandardSecurityHandler::decryptUsingFilter(const QByteArray& data
|
|||
std::vector<uint8_t> inputKeyData = convertByteArrayToVector(m_authorizationData.fileEncryptionKey);
|
||||
uint32_t objectNumber = qToLittleEndian(static_cast<uint32_t>(reference.objectNumber));
|
||||
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));
|
||||
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);
|
||||
uint32_t objectNumber = qToLittleEndian(static_cast<uint32_t>(reference.objectNumber));
|
||||
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));
|
||||
MD5(inputKeyData.data(), inputKeyData.size(), objectEncryptionKey.data());
|
||||
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
#include "pdfconstants.h"
|
||||
#include "pdfparser.h"
|
||||
#include "pdfsecurityhandler.h"
|
||||
#include "pdfutils.h"
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#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);
|
||||
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,
|
||||
|
|
|
@ -184,6 +184,9 @@ public:
|
|||
const PDFObjectFetcher& objectFetcher,
|
||||
const PDFObject& parameters,
|
||||
const PDFSecurityHandler* securityHandler) const override;
|
||||
|
||||
private:
|
||||
static QByteArray uncompress(const QByteArray& data);
|
||||
};
|
||||
|
||||
class PDFFORQTLIBSHARED_EXPORT PDFRunLengthDecodeFilter : public PDFStreamFilter
|
||||
|
|
Loading…
Reference in New Issue