Decrypt application

This commit is contained in:
Jakub Melka 2021-05-11 18:46:33 +02:00
parent d607c24459
commit aa059ea1f6
30 changed files with 295 additions and 87 deletions

View File

@ -1141,6 +1141,11 @@ void PDFDocumentBuilder::copyAnnotation(PDFObjectReference pageReference, PDFObj
appendTo(pageReference, pageAnnots);
}
void PDFDocumentBuilder::setSecurityHandler(PDFSecurityHandlerPointer handler)
{
m_storage.setSecurityHandler(qMove(handler));
}
PDFObjectReference PDFDocumentBuilder::getCatalogReference() const
{
if (const PDFDictionary* trailerDictionary = getDictionaryFromObject(m_storage.getTrailerDictionary()))
@ -1582,7 +1587,7 @@ PDFContentStreamBuilder::ContentStream PDFContentStreamBuilder::end(QPainter* pa
delete m_buffer;
m_buffer = nullptr;
PDFDocumentReader reader(nullptr, nullptr, false);
PDFDocumentReader reader(nullptr, nullptr, false, false);
result.document = reader.readFromBuffer(bufferData);
if (result.document.getCatalog()->getPageCount() > 0)
@ -4288,6 +4293,20 @@ void PDFDocumentBuilder::removeDocumentActions()
}
void PDFDocumentBuilder::removeEncryption()
{
PDFObjectFactory objectBuilder;
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Encrypt");
objectBuilder << PDFObject();
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObject updatedTrailerDictionary = objectBuilder.takeObject();
m_storage.updateTrailerDictionary(qMove(updatedTrailerDictionary));
}
void PDFDocumentBuilder::removeOutline()
{
PDFObjectFactory objectBuilder;
@ -4731,14 +4750,6 @@ void PDFDocumentBuilder::setFormFieldValue(PDFObjectReference formField,
}
void PDFDocumentBuilder::setLanguage(QLocale locale)
{
PDFObjectFactory objectBuilder;
setLanguage(locale.name());
}
void PDFDocumentBuilder::setLanguage(QString language)
{
PDFObjectFactory objectBuilder;
@ -4753,6 +4764,14 @@ void PDFDocumentBuilder::setLanguage(QString language)
}
void PDFDocumentBuilder::setLanguage(QLocale locale)
{
PDFObjectFactory objectBuilder;
setLanguage(locale.name());
}
void PDFDocumentBuilder::setOutline(PDFObjectReference outline)
{
PDFObjectFactory objectBuilder;
@ -4856,6 +4875,7 @@ void PDFDocumentBuilder::setPageRotation(PDFObjectReference page,
mergeTo(page, updatedPageObject);
}
void PDFDocumentBuilder::setPageTrimBox(PDFObjectReference page,
QRectF box)
{

View File

@ -421,6 +421,11 @@ public:
/// \param annotationReference Annotation reference
void copyAnnotation(PDFObjectReference pageReference, PDFObjectReference annotationReference);
/// Sets security handler to the object storage. Trailer dictionary is not
/// updated and so must be updated manually.
/// \param handler New security handler
void setSecurityHandler(PDFSecurityHandlerPointer handler);
/* START GENERATED CODE */
/// Appends a new page after last page.
@ -1185,6 +1190,10 @@ public:
void removeDocumentActions();
/// Removes encryption from a document.
void removeEncryption();
/// Removes outline tree from document catalog.
void removeOutline();
@ -1371,11 +1380,6 @@ public:
PDFObject value);
/// Set document language.
/// \param locale Locale, from which is language determined
void setLanguage(QLocale locale);
/// Set document language.
/// \param language Document language. It should be a language identifier, as defined in ISO 639
/// and ISO 3166. For example, "en-US", where first two letter means language code (en =
@ -1383,6 +1387,11 @@ public:
void setLanguage(QString language);
/// Set document language.
/// \param locale Locale, from which is language determined
void setLanguage(QLocale locale);
/// Set document outline.
/// \param outline Document outline root
void setOutline(PDFObjectReference outline);

View File

@ -34,11 +34,12 @@
namespace pdf
{
PDFDocumentReader::PDFDocumentReader(PDFProgress* progress, const std::function<QString(bool*)>& getPasswordCallback, bool permissive) :
PDFDocumentReader::PDFDocumentReader(PDFProgress* progress, const std::function<QString(bool*)>& getPasswordCallback, bool permissive, bool authorizeOwnerOnly) :
m_result(Result::OK),
m_getPasswordCallback(getPasswordCallback),
m_progress(progress),
m_permissive(permissive)
m_permissive(permissive),
m_authorizeOwnerOnly(authorizeOwnerOnly)
{
}
@ -375,7 +376,7 @@ PDFDocumentReader::Result PDFDocumentReader::processSecurityHandler(const PDFObj
// Read the security handler
m_securityHandler = PDFSecurityHandler::createSecurityHandler(encryptObject, id);
PDFSecurityHandler::AuthorizationResult authorizationResult = m_securityHandler->authenticate(m_getPasswordCallback);
PDFSecurityHandler::AuthorizationResult authorizationResult = m_securityHandler->authenticate(m_getPasswordCallback, m_authorizeOwnerOnly);
if (authorizationResult == PDFSecurityHandler::AuthorizationResult::Cancelled)
{

View File

@ -40,7 +40,7 @@ class Pdf4QtLIBSHARED_EXPORT PDFDocumentReader
Q_DECLARE_TR_FUNCTIONS(pdf::PDFDocumentReader)
public:
explicit PDFDocumentReader(PDFProgress* progress, const std::function<QString(bool*)>& getPasswordCallback, bool permissive);
explicit PDFDocumentReader(PDFProgress* progress, const std::function<QString(bool*)>& getPasswordCallback, bool permissive, bool authorizeOwnerOnly);
constexpr inline PDFDocumentReader(const PDFDocumentReader&) = delete;
constexpr inline PDFDocumentReader(PDFDocumentReader&&) = delete;
@ -166,6 +166,10 @@ private:
/// Be permissive when reading, tolerate errors and try to fix broken document
bool m_permissive;
/// Authorize as owner only (if owner authorization fails, then whole document
/// reading fails)
bool m_authorizeOwnerOnly;
/// Warnings
QStringList m_warnings;
};

View File

@ -369,7 +369,7 @@ PDFSecurityHandlerPointer PDFSecurityHandler::createSecurityHandler(const PDFObj
if (it == handler.m_cryptFilters.cend())
{
throw PDFException(PDFTranslationContext::tr("Uknown crypt filter '%1'.").arg(QString::fromLatin1(name)));
throw PDFException(PDFTranslationContext::tr("Unknown crypt filter '%1'.").arg(QString::fromLatin1(name)));
}
return it->second;
@ -446,7 +446,7 @@ PDFSecurityHandlerPointer PDFSecurityHandler::createSecurityHandler(const PDFObj
return PDFSecurityHandlerPointer(new PDFStandardSecurityHandler(qMove(handler)));
}
PDFSecurityHandler::AuthorizationResult PDFStandardSecurityHandler::authenticate(const std::function<QString(bool*)>& getPasswordCallback)
PDFSecurityHandler::AuthorizationResult PDFStandardSecurityHandler::authenticate(const std::function<QString(bool*)>& getPasswordCallback, bool authorizeOwnerOnly)
{
QByteArray password;
bool passwordObtained = true;
@ -478,15 +478,18 @@ PDFSecurityHandler::AuthorizationResult PDFStandardSecurityHandler::authenticate
}
// Try to authorize user password
QByteArray fileEncryptionKey = createFileEncryptionKey(password);
QByteArray U = createEntryValueU_r234(fileEncryptionKey);
if (U == m_U)
if (!authorizeOwnerOnly)
{
// We have authorized owner access
m_authorizationData.authorizationResult = AuthorizationResult::UserAuthorized;
m_authorizationData.fileEncryptionKey = fileEncryptionKey;
return AuthorizationResult::UserAuthorized;
QByteArray fileEncryptionKey = createFileEncryptionKey(password);
QByteArray U = createEntryValueU_r234(fileEncryptionKey);
if (U == m_U)
{
// We have authorized user access
m_authorizationData.authorizationResult = AuthorizationResult::UserAuthorized;
m_authorizationData.fileEncryptionKey = fileEncryptionKey;
return AuthorizationResult::UserAuthorized;
}
}
break;
@ -534,7 +537,7 @@ PDFSecurityHandler::AuthorizationResult PDFStandardSecurityHandler::authenticate
}
// Try to authorize user password
if (!m_authorizationData.isAuthorized())
if (!m_authorizationData.isAuthorized() && !authorizeOwnerOnly)
{
QByteArray inputData = password + userData.validationSalt;
QByteArray hash = createHash_r56(inputData, password, false);
@ -925,7 +928,7 @@ QByteArray PDFStandardSecurityHandler::createUserPasswordFromOwnerPassword(const
const int keyByteLength = m_keyLength / 8;
if (keyByteLength > MD5_DIGEST_LENGTH)
{
throw PDFException(PDFTranslationContext::tr("Encryption key length (%1) exceeded maximal value of.").arg(keyByteLength).arg(MD5_DIGEST_LENGTH));
throw PDFException(PDFTranslationContext::tr("Encryption key length (%1) exceeded maximal value of %2.").arg(keyByteLength).arg(MD5_DIGEST_LENGTH));
}
if (m_R >= 3)

View File

@ -116,8 +116,9 @@ public:
/// to cancel the authentication (and \p Cancelled authentication result is returned) or true,
/// to try provided password.
/// \param getPasswordCallback Callback to get user password
/// \param authorizeOwnerOnly Authorize owner only
/// \returns Result of authentication
virtual AuthorizationResult authenticate(const std::function<QString(bool*)>& getPasswordCallback) = 0;
virtual AuthorizationResult authenticate(const std::function<QString(bool*)>& getPasswordCallback, bool authorizeOwnerOnly) = 0;
/// Decrypts the PDF object. This function works properly only (and only if)
/// \p authenticate function returns user/owner authorization code.
@ -188,7 +189,7 @@ class PDFNoneSecurityHandler : public PDFSecurityHandler
{
public:
virtual EncryptionMode getMode() const override { return EncryptionMode::None; }
virtual AuthorizationResult authenticate(const std::function<QString(bool*)>&) override { return AuthorizationResult::OwnerAuthorized; }
virtual AuthorizationResult authenticate(const std::function<QString(bool*)>&, bool) override { return AuthorizationResult::OwnerAuthorized; }
virtual QByteArray decrypt(const QByteArray& data, PDFObjectReference, EncryptionScope) const override { return data; }
virtual QByteArray decryptByFilter(const QByteArray& data, const QByteArray&, PDFObjectReference) const override { return data; }
virtual bool isMetadataEncrypted() const override { return true; }
@ -202,7 +203,7 @@ class PDFStandardSecurityHandler : public PDFSecurityHandler
{
public:
virtual EncryptionMode getMode() const override { return EncryptionMode::Standard; }
virtual AuthorizationResult authenticate(const std::function<QString(bool*)>& getPasswordCallback) override;
virtual AuthorizationResult authenticate(const std::function<QString(bool*)>& getPasswordCallback, bool authorizeOwnerOnly) override;
virtual QByteArray decrypt(const QByteArray& data, PDFObjectReference reference, EncryptionScope encryptionScope) const override;
virtual QByteArray decryptByFilter(const QByteArray& data, const QByteArray& filterName, PDFObjectReference reference) const override;
virtual bool isMetadataEncrypted() const override { return m_encryptMetadata; }

View File

@ -1416,7 +1416,7 @@ void PDFProgramController::openDocument(const QString& fileName)
};
// Try to open a new document
pdf::PDFDocumentReader reader(m_progress, qMove(queryPassword), true);
pdf::PDFDocumentReader reader(m_progress, qMove(queryPassword), true, false);
pdf::PDFDocument document = reader.readFromFile(fileName);
result.errorMessage = reader.getErrorMessage();

View File

@ -46,6 +46,7 @@ SOURCES += \
pdftoolaudiobook.cpp \
pdftoolcertstore.cpp \
pdftoolcolorprofiles.cpp \
pdftooldecrypt.cpp \
pdftoolfetchimages.cpp \
pdftoolfetchtext.cpp \
pdftoolinfo.cpp \
@ -78,6 +79,7 @@ HEADERS += \
pdftoolaudiobook.h \
pdftoolcertstore.h \
pdftoolcolorprofiles.h \
pdftooldecrypt.h \
pdftoolfetchimages.h \
pdftoolfetchtext.h \
pdftoolinfo.h \

View File

@ -899,7 +899,7 @@ PDFToolOptions PDFToolAbstractApplication::getOptions(QCommandLineParser* parser
return options;
}
bool PDFToolAbstractApplication::readDocument(const PDFToolOptions& options, pdf::PDFDocument& document, QByteArray* sourceData)
bool PDFToolAbstractApplication::readDocument(const PDFToolOptions& options, pdf::PDFDocument& document, QByteArray* sourceData, bool authorizeOwnerOnly)
{
bool isFirstPasswordAttempt = true;
auto passwordCallback = [&options, &isFirstPasswordAttempt](bool* ok) -> QString
@ -908,7 +908,7 @@ bool PDFToolAbstractApplication::readDocument(const PDFToolOptions& options, pdf
isFirstPasswordAttempt = false;
return options.password;
};
pdf::PDFDocumentReader reader(nullptr, passwordCallback, options.permissiveReading);
pdf::PDFDocumentReader reader(nullptr, passwordCallback, options.permissiveReading, authorizeOwnerOnly);
document = reader.readFromFile(options.document);
switch (reader.getReadingResult())

View File

@ -187,6 +187,7 @@ public:
ErrorUnknown,
ErrorNoDocumentSpecified,
ErrorDocumentReading,
ErrorDocumentWriting,
ErrorCertificateReading,
ErrorInvalidArguments,
ErrorFailedWriteToFile,
@ -245,7 +246,8 @@ protected:
/// \param options Options
/// \param document Document
/// \param[out] sourceData Pointer, to which source data are stored
bool readDocument(const PDFToolOptions& options, pdf::PDFDocument& document, QByteArray* sourceData = nullptr);
/// \param authorizeOwnerOnly Require to authorize as owner
bool readDocument(const PDFToolOptions& options, pdf::PDFDocument& document, QByteArray* sourceData, bool authorizeOwnerOnly);
};
/// This class stores information about all applications available. Application

View File

@ -47,7 +47,7 @@ QString PDFToolAttachmentsApplication::getStandardString(StandardString standard
int PDFToolAttachmentsApplication::execute(const PDFToolOptions& options)
{
pdf::PDFDocument document;
if (!readDocument(options, document))
if (!readDocument(options, document, nullptr, false))
{
return ErrorDocumentReading;
}

View File

@ -332,7 +332,7 @@ int PDFToolAudioBook::getDocumentTextFlow(const PDFToolOptions& options, pdf::PD
{
pdf::PDFDocument document;
QByteArray sourceData;
if (!readDocument(options, document, &sourceData))
if (!readDocument(options, document, &sourceData, false))
{
return ErrorDocumentReading;
}

View File

@ -0,0 +1,89 @@
// Copyright (C) 2021 Jakub Melka
//
// This file is part of Pdf4Qt.
//
// Pdf4Qt is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// with the written consent of the copyright owner, any later version.
//
// Pdf4Qt is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Pdf4Qt. If not, see <https://www.gnu.org/licenses/>.
#include "pdftooldecrypt.h"
#include "pdfdocumentbuilder.h"
#include "pdfdocumentwriter.h"
namespace pdftool
{
static PDFToolDecryptApplication s_decryptApplication;
QString PDFToolDecryptApplication::getStandardString(StandardString standardString) const
{
switch (standardString)
{
case Command:
return "decrypt";
case Name:
return PDFToolTranslationContext::tr("Decrypt");
case Description:
return PDFToolTranslationContext::tr("Remove encryption from a document (with only owner access only).");
default:
Q_ASSERT(false);
break;
}
return QString();
}
int PDFToolDecryptApplication::execute(const PDFToolOptions& options)
{
pdf::PDFDocument document;
QByteArray sourceData;
if (!readDocument(options, document, &sourceData, true))
{
if (readDocument(options, document, &sourceData, false))
{
PDFConsole::writeError(PDFToolTranslationContext::tr("Authorization as owner failed. Encryption removal is not permitted if authorized as user only."), options.outputCodec);
}
return ErrorDocumentReading;
}
if (document.getStorage().getSecurityHandler()->getMode() == pdf::EncryptionMode::None)
{
PDFConsole::writeError(PDFToolTranslationContext::tr("Document is not encrypted."), options.outputCodec);
return ExitSuccess;
}
pdf::PDFDocumentBuilder builder(&document);
builder.removeEncryption();
builder.setSecurityHandler(pdf::PDFSecurityHandlerPointer(new pdf::PDFNoneSecurityHandler()));
document = builder.build();
pdf::PDFDocumentWriter writer(nullptr);
pdf::PDFOperationResult result = writer.write(options.document, &document, true);
if (!result)
{
PDFConsole::writeError(result.getErrorMessage(), options.outputCodec);
return ErrorDocumentWriting;
}
return ExitSuccess;
}
PDFToolAbstractApplication::Options PDFToolDecryptApplication::getOptionsFlags() const
{
return ConsoleFormat | OpenDocument;
}
} // namespace pdftool

36
PdfTool/pdftooldecrypt.h Normal file
View File

@ -0,0 +1,36 @@
// Copyright (C) 2021 Jakub Melka
//
// This file is part of Pdf4Qt.
//
// Pdf4Qt is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// with the written consent of the copyright owner, any later version.
//
// Pdf4Qt is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Pdf4Qt. If not, see <https://www.gnu.org/licenses/>.
#ifndef PDFTOOLDECRYPT_H
#define PDFTOOLDECRYPT_H
#include "pdftoolabstractapplication.h"
namespace pdftool
{
class PDFToolDecryptApplication : public PDFToolAbstractApplication
{
public:
virtual QString getStandardString(StandardString standardString) const override;
virtual int execute(const PDFToolOptions& options) override;
virtual Options getOptionsFlags() const override;
};
} // namespace pdftool
#endif // PDFTOOLDECRYPT_H

View File

@ -120,7 +120,7 @@ int PDFToolFetchImages::execute(const PDFToolOptions& options)
{
pdf::PDFDocument document;
QByteArray sourceData;
if (!readDocument(options, document, &sourceData))
if (!readDocument(options, document, &sourceData, false))
{
return ErrorDocumentReading;
}

View File

@ -48,7 +48,7 @@ int PDFToolFetchTextApplication::execute(const PDFToolOptions& options)
{
pdf::PDFDocument document;
QByteArray sourceData;
if (!readDocument(options, document, &sourceData))
if (!readDocument(options, document, &sourceData, false))
{
return ErrorDocumentReading;
}

View File

@ -52,7 +52,7 @@ int PDFToolInfoApplication::execute(const PDFToolOptions& options)
{
pdf::PDFDocument document;
QByteArray sourceData;
if (!readDocument(options, document, &sourceData))
if (!readDocument(options, document, &sourceData, false))
{
return ErrorDocumentReading;
}

View File

@ -66,7 +66,7 @@ int PDFToolInfoFonts::execute(const PDFToolOptions& options)
{
pdf::PDFDocument document;
QByteArray sourceData;
if (!readDocument(options, document, &sourceData))
if (!readDocument(options, document, &sourceData, false))
{
return ErrorDocumentReading;
}

View File

@ -48,7 +48,7 @@ int PDFToolInfoJavaScriptApplication::execute(const PDFToolOptions& options)
{
pdf::PDFDocument document;
QByteArray sourceData;
if (!readDocument(options, document, &sourceData))
if (!readDocument(options, document, &sourceData, false))
{
return ErrorDocumentReading;
}

View File

@ -48,7 +48,7 @@ int PDFToolInfoMetadataApplication::execute(const PDFToolOptions& options)
{
pdf::PDFDocument document;
QByteArray sourceData;
if (!readDocument(options, document, &sourceData))
if (!readDocument(options, document, &sourceData, false))
{
return ErrorDocumentReading;
}

View File

@ -48,7 +48,7 @@ int PDFToolInfoNamedDestinationsApplication::execute(const PDFToolOptions& optio
{
pdf::PDFDocument document;
QByteArray sourceData;
if (!readDocument(options, document, &sourceData))
if (!readDocument(options, document, &sourceData, false))
{
return ErrorDocumentReading;
}

View File

@ -67,7 +67,7 @@ int PDFToolInfoPageBoxesApplication::execute(const PDFToolOptions& options)
{
pdf::PDFDocument document;
QByteArray sourceData;
if (!readDocument(options, document, &sourceData))
if (!readDocument(options, document, &sourceData, false))
{
return ErrorDocumentReading;
}

View File

@ -266,7 +266,7 @@ int PDFToolInfoStructureTreeApplication::execute(const PDFToolOptions& options)
{
pdf::PDFDocument document;
QByteArray sourceData;
if (!readDocument(options, document, &sourceData))
if (!readDocument(options, document, &sourceData, false))
{
return ErrorDocumentReading;
}

View File

@ -55,7 +55,7 @@ int PDFToolOptimize::execute(const PDFToolOptions& options)
pdf::PDFDocument document;
QByteArray sourceData;
if (!readDocument(options, document, &sourceData))
if (!readDocument(options, document, &sourceData, false))
{
return ErrorDocumentReading;
}

View File

@ -147,7 +147,7 @@ int PDFToolRenderBase::execute(const PDFToolOptions& options)
{
pdf::PDFDocument document;
QByteArray sourceData;
if (!readDocument(options, document, &sourceData))
if (!readDocument(options, document, &sourceData, false))
{
return ErrorDocumentReading;
}

View File

@ -51,7 +51,7 @@ int PDFToolSeparate::execute(const PDFToolOptions& options)
{
pdf::PDFDocument document;
QByteArray sourceData;
if (!readDocument(options, document, &sourceData))
if (!readDocument(options, document, &sourceData, false))
{
return ErrorDocumentReading;
}

View File

@ -79,7 +79,7 @@ int PDFToolUnite::execute(const PDFToolOptions& options)
std::vector<pdf::PDFObjectReference> pages;
for (const QString& fileName : files)
{
pdf::PDFDocumentReader reader(nullptr, [](bool* ok) { *ok = false; return QString(); }, options.permissiveReading);
pdf::PDFDocumentReader reader(nullptr, [](bool* ok) { *ok = false; return QString(); }, options.permissiveReading, false);
pdf::PDFDocument document = reader.readFromFile(fileName);
if (reader.getReadingResult() != pdf::PDFDocumentReader::Result::OK)
{

View File

@ -63,7 +63,7 @@ int PDFToolVerifySignaturesApplication::execute(const PDFToolOptions& options)
isFirstPasswordAttempt = false;
return options.password;
};
pdf::PDFDocumentReader reader(nullptr, passwordCallback, options.permissiveReading);
pdf::PDFDocumentReader reader(nullptr, passwordCallback, options.permissiveReading, false);
pdf::PDFDocument document = reader.readFromFile(options.document);
switch (reader.getReadingResult())

View File

@ -196,7 +196,7 @@ QString PDFToolXmlApplication::getStandardString(StandardString standardString)
int PDFToolXmlApplication::execute(const PDFToolOptions& options)
{
pdf::PDFDocument document;
if (!readDocument(options, document))
if (!readDocument(options, document, nullptr, false))
{
return ErrorDocumentReading;
}

View File

@ -8932,6 +8932,47 @@ return rootNodeReference;</property>
<property name="functionDescription">Removes document actions from document catalog.</property>
<property name="returnType">_void</property>
</QObject>
<QObject class="codegen::GeneratedFunction">
<property name="objectName"></property>
<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">
<property name="objectName"></property>
<property name="items"/>
<property name="actionType">Code</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code">m_storage.updateTrailerDictionary(qMove(updatedTrailerDictionary));</property>
</QObject>
</property>
<property name="functionType">Structure</property>
<property name="functionName">removeEncryption</property>
<property name="functionDescription">Removes encryption from a document.</property>
<property name="returnType">_void</property>
</QObject>
<QObject class="codegen::GeneratedFunction">
<property name="objectName"></property>
<property name="items">
@ -10722,39 +10763,6 @@ return rootNodeReference;</property>
<property name="functionDescription">Sets form field value. Value must be correct for this form field, no checking is performed. Also, if you use this function, annotation widgets, which are attached to this form field, should also be updated (for example, appearance state and sometimes appearance streams).</property>
<property name="returnType">_void</property>
</QObject>
<QObject class="codegen::GeneratedFunction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">locale</property>
<property name="parameterType">_QLocale</property>
<property name="parameterDescription">Locale, from which is language determined</property>
</QObject>
</property>
<property name="actionType">Parameters</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items"/>
<property name="actionType">Code</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code">setLanguage(locale.name());</property>
</QObject>
</property>
<property name="functionType">Structure</property>
<property name="functionName">setLanguage</property>
<property name="functionDescription">Set document language.</property>
<property name="returnType">_void</property>
</QObject>
<QObject class="codegen::GeneratedFunction">
<property name="objectName"></property>
<property name="items">
@ -10812,6 +10820,39 @@ return rootNodeReference;</property>
<property name="functionDescription">Set document language.</property>
<property name="returnType">_void</property>
</QObject>
<QObject class="codegen::GeneratedFunction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">locale</property>
<property name="parameterType">_QLocale</property>
<property name="parameterDescription">Locale, from which is language determined</property>
</QObject>
</property>
<property name="actionType">Parameters</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items"/>
<property name="actionType">Code</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code">setLanguage(locale.name());</property>
</QObject>
</property>
<property name="functionType">Structure</property>
<property name="functionName">setLanguage</property>
<property name="functionDescription">Set document language.</property>
<property name="returnType">_void</property>
</QObject>
<QObject class="codegen::GeneratedFunction">
<property name="objectName"></property>
<property name="items">