mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-02-24 15:37:45 +01:00
Encryption bugfixing (RC4)
This commit is contained in:
parent
e3fecc0568
commit
e001adc65b
@ -43,6 +43,26 @@ bool PDFDocument::operator==(const PDFDocument& other) const
|
|||||||
return m_pdfObjectStorage == other.m_pdfObjectStorage;
|
return m_pdfObjectStorage == other.m_pdfObjectStorage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray PDFDocument::getIdPart(size_t index) const
|
||||||
|
{
|
||||||
|
QByteArray id;
|
||||||
|
const PDFObject& idArrayObject = getTrailerDictionary()->get("ID");
|
||||||
|
if (idArrayObject.isArray())
|
||||||
|
{
|
||||||
|
const PDFArray* idArray = idArrayObject.getArray();
|
||||||
|
if (idArray->getCount() > index)
|
||||||
|
{
|
||||||
|
const PDFObject& idArrayItem = idArray->getItem(index);
|
||||||
|
if (idArrayItem.isString())
|
||||||
|
{
|
||||||
|
id = idArrayItem.getString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray PDFDocument::getDecodedStream(const PDFStream* stream) const
|
QByteArray PDFDocument::getDecodedStream(const PDFStream* stream) const
|
||||||
{
|
{
|
||||||
return m_pdfObjectStorage.getDecodedStream(stream);
|
return m_pdfObjectStorage.getDecodedStream(stream);
|
||||||
|
@ -419,6 +419,10 @@ public:
|
|||||||
/// Returns info about the document (title, author, etc.)
|
/// Returns info about the document (title, author, etc.)
|
||||||
const PDFDocumentInfo* getInfo() const { return &m_info; }
|
const PDFDocumentInfo* getInfo() const { return &m_info; }
|
||||||
|
|
||||||
|
/// Returns document id part with given index. If index is invalid,
|
||||||
|
/// then empty id is returned.
|
||||||
|
QByteArray getIdPart(size_t index) const;
|
||||||
|
|
||||||
/// If object is reference, the dereference attempt is performed
|
/// If object is reference, the dereference attempt is performed
|
||||||
/// and object is returned. If it is not a reference, then self
|
/// and object is returned. If it is not a reference, then self
|
||||||
/// is returned. If dereference attempt fails, then null object
|
/// is returned. If dereference attempt fails, then null object
|
||||||
|
@ -1143,6 +1143,31 @@ void PDFDocumentBuilder::copyAnnotation(PDFObjectReference pageReference, PDFObj
|
|||||||
|
|
||||||
void PDFDocumentBuilder::setSecurityHandler(PDFSecurityHandlerPointer handler)
|
void PDFDocumentBuilder::setSecurityHandler(PDFSecurityHandlerPointer handler)
|
||||||
{
|
{
|
||||||
|
if (!handler)
|
||||||
|
{
|
||||||
|
handler.reset(new PDFNoneSecurityHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFObjectFactory objectBuilder;
|
||||||
|
|
||||||
|
objectBuilder.beginDictionary();
|
||||||
|
objectBuilder.beginDictionaryItem("Encrypt");
|
||||||
|
|
||||||
|
PDFObject encryptionDictionaryObject = handler->createEncryptionDictionaryObject();
|
||||||
|
Q_ASSERT(!encryptionDictionaryObject.isReference());
|
||||||
|
|
||||||
|
if (!encryptionDictionaryObject.isNull())
|
||||||
|
{
|
||||||
|
encryptionDictionaryObject = PDFObject::createReference(addObject(encryptionDictionaryObject));
|
||||||
|
}
|
||||||
|
|
||||||
|
objectBuilder << encryptionDictionaryObject;
|
||||||
|
|
||||||
|
objectBuilder.endDictionaryItem();
|
||||||
|
objectBuilder.endDictionary();
|
||||||
|
PDFObject updatedTrailerDictionary = objectBuilder.takeObject();
|
||||||
|
m_storage.updateTrailerDictionary(qMove(updatedTrailerDictionary));
|
||||||
|
|
||||||
m_storage.setSecurityHandler(qMove(handler));
|
m_storage.setSecurityHandler(qMove(handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4297,13 +4322,7 @@ void PDFDocumentBuilder::removeEncryption()
|
|||||||
{
|
{
|
||||||
PDFObjectFactory objectBuilder;
|
PDFObjectFactory objectBuilder;
|
||||||
|
|
||||||
objectBuilder.beginDictionary();
|
setSecurityHandler(nullptr);
|
||||||
objectBuilder.beginDictionaryItem("Encrypt");
|
|
||||||
objectBuilder << PDFObject();
|
|
||||||
objectBuilder.endDictionaryItem();
|
|
||||||
objectBuilder.endDictionary();
|
|
||||||
PDFObject updatedTrailerDictionary = objectBuilder.takeObject();
|
|
||||||
m_storage.updateTrailerDictionary(qMove(updatedTrailerDictionary));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,6 +72,12 @@ struct WrapString
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WrapString(const QByteArray& byteArray) :
|
||||||
|
string(byteArray)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray string;
|
QByteArray string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -421,9 +427,10 @@ public:
|
|||||||
/// \param annotationReference Annotation reference
|
/// \param annotationReference Annotation reference
|
||||||
void copyAnnotation(PDFObjectReference pageReference, PDFObjectReference annotationReference);
|
void copyAnnotation(PDFObjectReference pageReference, PDFObjectReference annotationReference);
|
||||||
|
|
||||||
/// Sets security handler to the object storage. Trailer dictionary is not
|
/// Sets security handler to the object storage. Trailer dictionary is also
|
||||||
/// updated and so must be updated manually.
|
/// updated, so it is not needed to update it. Pass nullptr as handler to remove
|
||||||
/// \param handler New security handler
|
/// security.
|
||||||
|
/// \param handler New security handler, or nullptr
|
||||||
void setSecurityHandler(PDFSecurityHandlerPointer handler);
|
void setSecurityHandler(PDFSecurityHandlerPointer handler);
|
||||||
|
|
||||||
/* START GENERATED CODE */
|
/* START GENERATED CODE */
|
||||||
|
@ -319,8 +319,18 @@ PDFOperationResult PDFDocumentWriter::write(QIODevice* device, const PDFDocument
|
|||||||
|
|
||||||
// Jakub Melka: Adjust trailer dictionary, to be really dictionary, not a stream
|
// Jakub Melka: Adjust trailer dictionary, to be really dictionary, not a stream
|
||||||
PDFDictionary trailerDictionary = *document->getTrailerDictionary();
|
PDFDictionary trailerDictionary = *document->getTrailerDictionary();
|
||||||
trailerDictionary.removeEntry("XRefStm");
|
PDFDictionary newTrailerDictionary;
|
||||||
PDFObject trailerDictionaryObject = PDFObject::createDictionary(std::make_shared<PDFDictionary>(qMove(trailerDictionary)));
|
|
||||||
|
for (const char* entry : { "Size", "Root", "Encrypt", "Info", "ID"})
|
||||||
|
{
|
||||||
|
PDFObject object = trailerDictionary.get(entry);
|
||||||
|
if (!object.isNull())
|
||||||
|
{
|
||||||
|
newTrailerDictionary.addEntry(PDFInplaceOrMemoryString(entry), qMove(object));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFObject trailerDictionaryObject = PDFObject::createDictionary(std::make_shared<PDFDictionary>(qMove(newTrailerDictionary)));
|
||||||
|
|
||||||
device->write("trailer");
|
device->write("trailer");
|
||||||
writeCRLF(device);
|
writeCRLF(device);
|
||||||
|
@ -509,7 +509,7 @@ PDFSecurityHandlerPointer PDFSecurityHandler::createSecurityHandler(const PDFObj
|
|||||||
return PDFSecurityHandlerPointer(new PDFStandardSecurityHandler(qMove(handler)));
|
return PDFSecurityHandlerPointer(new PDFStandardSecurityHandler(qMove(handler)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFSecurityHandler::fillEncryptionDictionary(PDFObjectFactory& factory)
|
void PDFSecurityHandler::fillEncryptionDictionary(PDFObjectFactory& factory) const
|
||||||
{
|
{
|
||||||
factory.beginDictionaryItem("V");
|
factory.beginDictionaryItem("V");
|
||||||
factory << PDFInteger(m_V);
|
factory << PDFInteger(m_V);
|
||||||
@ -621,15 +621,15 @@ void PDFSecurityHandler::fillEncryptionDictionary(PDFObjectFactory& factory)
|
|||||||
|
|
||||||
// Store StmF, StrF, EFF
|
// Store StmF, StrF, EFF
|
||||||
factory.beginDictionaryItem("StmF");
|
factory.beginDictionaryItem("StmF");
|
||||||
factory << stmfName;
|
factory << WrapName(stmfName);
|
||||||
factory.endDictionaryItem();
|
factory.endDictionaryItem();
|
||||||
|
|
||||||
factory.beginDictionaryItem("StrF");
|
factory.beginDictionaryItem("StrF");
|
||||||
factory << strfName;
|
factory << WrapName(strfName);
|
||||||
factory.endDictionaryItem();
|
factory.endDictionaryItem();
|
||||||
|
|
||||||
factory.beginDictionaryItem("EFF");
|
factory.beginDictionaryItem("EFF");
|
||||||
factory << effName;
|
factory << WrapName(effName);
|
||||||
factory.endDictionaryItem();
|
factory.endDictionaryItem();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1141,6 +1141,8 @@ PDFObject PDFStandardSecurityHandler::createEncryptionDictionaryObject() const
|
|||||||
|
|
||||||
factory.beginDictionary();
|
factory.beginDictionary();
|
||||||
|
|
||||||
|
fillEncryptionDictionary(factory);
|
||||||
|
|
||||||
factory.beginDictionaryItem("Filter");
|
factory.beginDictionaryItem("Filter");
|
||||||
factory << WrapName("Standard");
|
factory << WrapName("Standard");
|
||||||
factory.endDictionaryItem();
|
factory.endDictionaryItem();
|
||||||
@ -1150,21 +1152,21 @@ PDFObject PDFStandardSecurityHandler::createEncryptionDictionaryObject() const
|
|||||||
factory.endDictionaryItem();
|
factory.endDictionaryItem();
|
||||||
|
|
||||||
factory.beginDictionaryItem("O");
|
factory.beginDictionaryItem("O");
|
||||||
factory << m_O;
|
factory << WrapString(m_O);
|
||||||
factory.endDictionaryItem();
|
factory.endDictionaryItem();
|
||||||
|
|
||||||
factory.beginDictionaryItem("U");
|
factory.beginDictionaryItem("U");
|
||||||
factory << m_U;
|
factory << WrapString(m_U);
|
||||||
factory.endDictionaryItem();
|
factory.endDictionaryItem();
|
||||||
|
|
||||||
if (m_R == 6)
|
if (m_R == 6)
|
||||||
{
|
{
|
||||||
factory.beginDictionaryItem("OE");
|
factory.beginDictionaryItem("OE");
|
||||||
factory << m_OE;
|
factory << WrapString(m_OE);
|
||||||
factory.endDictionaryItem();
|
factory.endDictionaryItem();
|
||||||
|
|
||||||
factory.beginDictionaryItem("UE");
|
factory.beginDictionaryItem("UE");
|
||||||
factory << m_UE;
|
factory << WrapString(m_UE);
|
||||||
factory.endDictionaryItem();
|
factory.endDictionaryItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1175,7 +1177,7 @@ PDFObject PDFStandardSecurityHandler::createEncryptionDictionaryObject() const
|
|||||||
if (m_R == 6)
|
if (m_R == 6)
|
||||||
{
|
{
|
||||||
factory.beginDictionaryItem("Perms");
|
factory.beginDictionaryItem("Perms");
|
||||||
factory << m_Perms;
|
factory << WrapString(m_Perms);
|
||||||
factory.endDictionaryItem();
|
factory.endDictionaryItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1689,6 +1691,7 @@ PDFSecurityHandlerPointer PDFSecurityHandlerFactory::createSecurityHandler(const
|
|||||||
|
|
||||||
// Jakub Melka: create standard security handler, with given settings
|
// Jakub Melka: create standard security handler, with given settings
|
||||||
PDFStandardSecurityHandler* handler = new PDFStandardSecurityHandler();
|
PDFStandardSecurityHandler* handler = new PDFStandardSecurityHandler();
|
||||||
|
handler->m_ID = settings.id;
|
||||||
|
|
||||||
const bool isEncryptingEmbeddedFilesOnly = settings.encryptContents == EncryptContents::EmbeddedFiles;
|
const bool isEncryptingEmbeddedFilesOnly = settings.encryptContents == EncryptContents::EmbeddedFiles;
|
||||||
|
|
||||||
@ -1820,7 +1823,8 @@ PDFSecurityHandlerPointer PDFSecurityHandlerFactory::createSecurityHandler(const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handler->authenticate([&settings](bool* b) { *b = false; return settings.ownerPassword; }, true);
|
bool firstTry = true;
|
||||||
|
handler->authenticate([&settings, &firstTry](bool* b) { *b = firstTry; firstTry = false; return settings.ownerPassword; }, true);
|
||||||
Q_ASSERT(handler->getAuthorizationResult() == PDFSecurityHandler::AuthorizationResult::OwnerAuthorized);
|
Q_ASSERT(handler->getAuthorizationResult() == PDFSecurityHandler::AuthorizationResult::OwnerAuthorized);
|
||||||
return PDFSecurityHandlerPointer(handler);
|
return PDFSecurityHandlerPointer(handler);
|
||||||
}
|
}
|
||||||
@ -1884,7 +1888,7 @@ int PDFSecurityHandlerFactory::getRevisionFromAlgorithm(Algorithm algorithm)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case RC4:
|
case RC4:
|
||||||
return 3;
|
return 4;
|
||||||
|
|
||||||
case AES_128:
|
case AES_128:
|
||||||
return 4;
|
return 4;
|
||||||
|
@ -199,7 +199,7 @@ protected:
|
|||||||
|
|
||||||
/// Fills encryption dictionary with basic data
|
/// Fills encryption dictionary with basic data
|
||||||
/// \param factory Factory
|
/// \param factory Factory
|
||||||
void fillEncryptionDictionary(PDFObjectFactory& factory);
|
void fillEncryptionDictionary(PDFObjectFactory& factory) const;
|
||||||
|
|
||||||
/// Version of the encryption, shall be a number from 1 to 5, according the
|
/// Version of the encryption, shall be a number from 1 to 5, according the
|
||||||
/// PDF specification. Other values are invalid.
|
/// PDF specification. Other values are invalid.
|
||||||
@ -404,6 +404,7 @@ public:
|
|||||||
QString userPassword;
|
QString userPassword;
|
||||||
QString ownerPassword;
|
QString ownerPassword;
|
||||||
uint32_t permissions = 0;
|
uint32_t permissions = 0;
|
||||||
|
QByteArray id;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Creates security handler based on given settings. If security handler cannot
|
/// Creates security handler based on given settings. If security handler cannot
|
||||||
|
@ -24,10 +24,11 @@
|
|||||||
namespace pdfviewer
|
namespace pdfviewer
|
||||||
{
|
{
|
||||||
|
|
||||||
PDFEncryptionSettingsDialog::PDFEncryptionSettingsDialog(QWidget* parent) :
|
PDFEncryptionSettingsDialog::PDFEncryptionSettingsDialog(QByteArray documentId, QWidget* parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
ui(new Ui::PDFEncryptionSettingsDialog),
|
ui(new Ui::PDFEncryptionSettingsDialog),
|
||||||
m_isUpdatingUi(false)
|
m_isUpdatingUi(false),
|
||||||
|
m_documentId(documentId)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
@ -175,6 +176,7 @@ void PDFEncryptionSettingsDialog::accept()
|
|||||||
encryptContents = pdf::PDFSecurityHandlerFactory::EmbeddedFiles;
|
encryptContents = pdf::PDFSecurityHandlerFactory::EmbeddedFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
settings.id = m_documentId;
|
||||||
settings.algorithm = static_cast<const pdf::PDFSecurityHandlerFactory::Algorithm>(ui->algorithmComboBox->currentData().toInt());
|
settings.algorithm = static_cast<const pdf::PDFSecurityHandlerFactory::Algorithm>(ui->algorithmComboBox->currentData().toInt());
|
||||||
settings.encryptContents = encryptContents;
|
settings.encryptContents = encryptContents;
|
||||||
settings.userPassword = ui->userPasswordEdit->text();
|
settings.userPassword = ui->userPasswordEdit->text();
|
||||||
|
@ -38,9 +38,11 @@ class PDFEncryptionSettingsDialog : public QDialog
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit PDFEncryptionSettingsDialog(QWidget* parent);
|
explicit PDFEncryptionSettingsDialog(QByteArray documentId, QWidget* parent);
|
||||||
virtual ~PDFEncryptionSettingsDialog() override;
|
virtual ~PDFEncryptionSettingsDialog() override;
|
||||||
|
|
||||||
|
pdf::PDFSecurityHandlerPointer getUpdatedSecurityHandler() const { return m_updatedSecurityHandler; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual void accept() override;
|
virtual void accept() override;
|
||||||
|
|
||||||
@ -53,6 +55,7 @@ private:
|
|||||||
bool m_isUpdatingUi;
|
bool m_isUpdatingUi;
|
||||||
std::map<QCheckBox*, pdf::PDFSecurityHandler::Permission> m_checkBoxToPermission;
|
std::map<QCheckBox*, pdf::PDFSecurityHandler::Permission> m_checkBoxToPermission;
|
||||||
pdf::PDFSecurityHandlerPointer m_updatedSecurityHandler;
|
pdf::PDFSecurityHandlerPointer m_updatedSecurityHandler;
|
||||||
|
QByteArray m_documentId;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdfviewer
|
} // namespace pdfviewer
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "pdfdrawspacecontroller.h"
|
#include "pdfdrawspacecontroller.h"
|
||||||
#include "pdfwidgetutils.h"
|
#include "pdfwidgetutils.h"
|
||||||
#include "pdfconstants.h"
|
#include "pdfconstants.h"
|
||||||
|
#include "pdfdocumentbuilder.h"
|
||||||
|
|
||||||
#include "pdfviewersettings.h"
|
#include "pdfviewersettings.h"
|
||||||
#include "pdfundoredomanager.h"
|
#include "pdfundoredomanager.h"
|
||||||
@ -1133,16 +1134,6 @@ void PDFProgramController::onActionOptimizeTriggered()
|
|||||||
|
|
||||||
void PDFProgramController::onActionEncryptionTriggered()
|
void PDFProgramController::onActionEncryptionTriggered()
|
||||||
{
|
{
|
||||||
// Check that we have owner acces to the document
|
|
||||||
const pdf::PDFSecurityHandler* securityHandler = m_pdfDocument->getStorage().getSecurityHandler();
|
|
||||||
pdf::PDFSecurityHandler::AuthorizationResult authorizationResult = securityHandler->getAuthorizationResult();
|
|
||||||
if (authorizationResult != pdf::PDFSecurityHandler::AuthorizationResult::OwnerAuthorized &&
|
|
||||||
authorizationResult != pdf::PDFSecurityHandler::AuthorizationResult::NoAuthorizationRequired)
|
|
||||||
{
|
|
||||||
// Jakub Melka: we must authorize as owner, otherwise we can't continue,
|
|
||||||
// because we don't have sufficient permissions.
|
|
||||||
pdf::PDFSecurityHandlerPointer clonedSecurityHandler(securityHandler->clone());
|
|
||||||
|
|
||||||
auto queryPassword = [this](bool* ok)
|
auto queryPassword = [this](bool* ok)
|
||||||
{
|
{
|
||||||
QString result;
|
QString result;
|
||||||
@ -1151,6 +1142,15 @@ void PDFProgramController::onActionEncryptionTriggered()
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check that we have owner access to the document
|
||||||
|
const pdf::PDFSecurityHandler* securityHandler = m_pdfDocument->getStorage().getSecurityHandler();
|
||||||
|
pdf::PDFSecurityHandler::AuthorizationResult authorizationResult = securityHandler->getAuthorizationResult();
|
||||||
|
if (authorizationResult != pdf::PDFSecurityHandler::AuthorizationResult::OwnerAuthorized &&
|
||||||
|
authorizationResult != pdf::PDFSecurityHandler::AuthorizationResult::NoAuthorizationRequired)
|
||||||
|
{
|
||||||
|
// Jakub Melka: we must authorize as owner, otherwise we can't continue,
|
||||||
|
// because we don't have sufficient permissions.
|
||||||
|
pdf::PDFSecurityHandlerPointer clonedSecurityHandler(securityHandler->clone());
|
||||||
authorizationResult = clonedSecurityHandler->authenticate(queryPassword, true);
|
authorizationResult = clonedSecurityHandler->authenticate(queryPassword, true);
|
||||||
|
|
||||||
if (authorizationResult != pdf::PDFSecurityHandler::AuthorizationResult::OwnerAuthorized)
|
if (authorizationResult != pdf::PDFSecurityHandler::AuthorizationResult::OwnerAuthorized)
|
||||||
@ -1167,8 +1167,30 @@ void PDFProgramController::onActionEncryptionTriggered()
|
|||||||
onDocumentModified(qMove(document));
|
onDocumentModified(qMove(document));
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFEncryptionSettingsDialog dialog(m_mainWindow);
|
PDFEncryptionSettingsDialog dialog(m_pdfDocument->getIdPart(0), m_mainWindow);
|
||||||
dialog.exec();
|
if (dialog.exec() == QDialog::Accepted)
|
||||||
|
{
|
||||||
|
pdf::PDFSecurityHandlerPointer updatedSecurityHandler = dialog.getUpdatedSecurityHandler();
|
||||||
|
|
||||||
|
// Jakub Melka: If we changed encryption (password), recheck, that user doesn't
|
||||||
|
// forgot (or accidentally entered wrong) password. So, we require owner authentization
|
||||||
|
// to continue.
|
||||||
|
if (updatedSecurityHandler->getMode() != pdf::EncryptionMode::None)
|
||||||
|
{
|
||||||
|
if (updatedSecurityHandler->authenticate(queryPassword, true) != pdf::PDFSecurityHandler::AuthorizationResult::OwnerAuthorized)
|
||||||
|
{
|
||||||
|
QMessageBox::critical(m_mainWindow, QApplication::applicationDisplayName(), tr("Reauthorization is required to change document encryption."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pdf::PDFDocumentBuilder builder(m_pdfDocument.data());
|
||||||
|
builder.setSecurityHandler(qMove(updatedSecurityHandler));
|
||||||
|
|
||||||
|
pdf::PDFDocumentPointer pointer(new pdf::PDFDocument(builder.build()));
|
||||||
|
pdf::PDFModifiedDocument document(qMove(pointer), m_optionalContentActivity, pdf::PDFModifiedDocument::Reset);
|
||||||
|
onDocumentModified(qMove(document));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFProgramController::onActionFitPageTriggered()
|
void PDFProgramController::onActionFitPageTriggered()
|
||||||
|
@ -8935,37 +8935,13 @@ return rootNodeReference;</property>
|
|||||||
<QObject class="codegen::GeneratedFunction">
|
<QObject class="codegen::GeneratedFunction">
|
||||||
<property name="objectName"></property>
|
<property name="objectName"></property>
|
||||||
<property name="items">
|
<property name="items">
|
||||||
<QObject class="codegen::GeneratedAction">
|
|
||||||
<property name="objectName"></property>
|
|
||||||
<property name="items">
|
|
||||||
<QObject class="codegen::GeneratedPDFObject">
|
|
||||||
<property name="objectName"></property>
|
|
||||||
<property name="items">
|
|
||||||
<QObject class="codegen::GeneratedPDFObject">
|
|
||||||
<property name="objectName"></property>
|
|
||||||
<property name="items"/>
|
|
||||||
<property name="dictionaryItemName">Encrypt</property>
|
|
||||||
<property name="objectType">DictionaryItemSimple</property>
|
|
||||||
<property name="value">PDFObject()</property>
|
|
||||||
</QObject>
|
|
||||||
</property>
|
|
||||||
<property name="dictionaryItemName"></property>
|
|
||||||
<property name="objectType">Dictionary</property>
|
|
||||||
<property name="value"></property>
|
|
||||||
</QObject>
|
|
||||||
</property>
|
|
||||||
<property name="actionType">CreateObject</property>
|
|
||||||
<property name="variableName">updatedTrailerDictionary</property>
|
|
||||||
<property name="variableType">_PDFObject</property>
|
|
||||||
<property name="code"></property>
|
|
||||||
</QObject>
|
|
||||||
<QObject class="codegen::GeneratedAction">
|
<QObject class="codegen::GeneratedAction">
|
||||||
<property name="objectName"></property>
|
<property name="objectName"></property>
|
||||||
<property name="items"/>
|
<property name="items"/>
|
||||||
<property name="actionType">Code</property>
|
<property name="actionType">Code</property>
|
||||||
<property name="variableName"></property>
|
<property name="variableName"></property>
|
||||||
<property name="variableType">_void</property>
|
<property name="variableType">_void</property>
|
||||||
<property name="code">m_storage.updateTrailerDictionary(qMove(updatedTrailerDictionary));</property>
|
<property name="code">setSecurityHandler(nullptr);</property>
|
||||||
</QObject>
|
</QObject>
|
||||||
</property>
|
</property>
|
||||||
<property name="functionType">Structure</property>
|
<property name="functionType">Structure</property>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user