vcl/inc/pdf/PDFEncryptor.hxx       |   46 +++++++++++++++++++++++++++----------
 vcl/inc/pdf/pdfwriter_impl.hxx     |    2 -
 vcl/source/gdi/pdfwriter_impl.cxx  |   30 +++++++++++++-----------
 vcl/source/gdi/pdfwriter_impl2.cxx |   14 +++++------
 4 files changed, 59 insertions(+), 33 deletions(-)

New commits:
commit d60d4bd4b58a52fa70cb3364213f4ba69a04dcaf
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Fri Nov 8 11:50:14 2024 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Nov 29 09:30:14 2024 +0100

    pdf: Introduce a IPDFEncryptor and use it in PDFWriterImpl
    
    The idea of IPDFEncryptor is to be the interface to encrypt the
    stream/string in the same way, irregardless which PDF encryption
    version/revision we are using.
    
    Change-Id: Ie7835384f1be5a44c53985b01c8187323400aa0e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176448
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/vcl/inc/pdf/PDFEncryptor.hxx b/vcl/inc/pdf/PDFEncryptor.hxx
index 5b9f50492742..f6182be7f93c 100644
--- a/vcl/inc/pdf/PDFEncryptor.hxx
+++ b/vcl/inc/pdf/PDFEncryptor.hxx
@@ -33,7 +33,29 @@ namespace vcl::pdf
 {
 class EncryptionHashTransporter;
 
-class PDFEncryptor
+class IPDFEncryptor
+{
+public:
+    virtual ~IPDFEncryptor() {}
+    virtual sal_Int32 getAccessPermissions() = 0;
+    virtual sal_Int32 getKeyLength() = 0;
+    virtual bool prepareEncryption(
+        const css::uno::Reference<css::beans::XMaterialHolder>& 
xEncryptionMaterialHolder,
+        PDFEncryptionProperties& rProperties)
+        = 0;
+    virtual void setupKeysAndCheck(PDFEncryptionProperties& rProperties) = 0;
+
+    virtual void setupEncryption(std::vector<sal_uInt8> const& rEncryptionKey, 
sal_Int32 nObject)
+        = 0;
+    virtual void enableStreamEncryption() = 0;
+    virtual void disableStreamEncryption() = 0;
+    virtual bool isStreamEncryptionEnabled() = 0;
+    virtual void encrypt(const void* pInput, sal_uInt64 nInputSize, sal_uInt8* 
pOutput,
+                         sal_uInt64 nOutputsSize)
+        = 0;
+};
+
+class PDFEncryptor : public IPDFEncryptor
 {
 private:
     /* the numerical value of the access permissions, according to PDF spec, 
must be signed */
@@ -50,30 +72,30 @@ private:
 
 public:
     PDFEncryptor();
-    ~PDFEncryptor();
+    virtual ~PDFEncryptor();
 
     /* used to cipher the stream data and for password management */
     rtlCipher m_aCipher = nullptr;
 
-    sal_Int32 getAccessPermissions() { return m_nAccessPermissions; }
-    sal_Int32 getKeyLength() { return m_nKeyLength; }
+    sal_Int32 getAccessPermissions() override { return m_nAccessPermissions; }
+    sal_Int32 getKeyLength() override { return m_nKeyLength; }
     sal_Int32 getRC4KeyLength() { return m_nRC4KeyLength; }
 
     static css::uno::Reference<css::beans::XMaterialHolder>
     initEncryption(const OUString& i_rOwnerPassword, const OUString& 
i_rUserPassword);
-    virtual bool prepareEncryption(
+    bool prepareEncryption(
         const css::uno::Reference<css::beans::XMaterialHolder>& 
xEncryptionMaterialHolder,
-        PDFEncryptionProperties& rProperties);
-    void setupKeysAndCheck(PDFEncryptionProperties& rProperties);
+        PDFEncryptionProperties& rProperties) override;
+    void setupKeysAndCheck(PDFEncryptionProperties& rProperties) override;
 
-    void setupEncryption(std::vector<sal_uInt8> const& rEncryptionKey, 
sal_Int32 nObject);
-    void enableStreamEncryption();
-    void disableStreamEncryption();
+    void setupEncryption(std::vector<sal_uInt8> const& rEncryptionKey, 
sal_Int32 nObject) override;
+    void enableStreamEncryption() override;
+    void disableStreamEncryption() override;
 
-    bool isStreamEncryptionEnabled() { return m_bEncryptThisStream; }
+    bool isStreamEncryptionEnabled() override { return m_bEncryptThisStream; }
 
     void encrypt(const void* pInput, sal_uInt64 nInputSize, sal_uInt8* pOutput,
-                 sal_uInt64 nOutputsSize);
+                 sal_uInt64 nOutputsSize) override;
 };
 }
 
diff --git a/vcl/inc/pdf/pdfwriter_impl.hxx b/vcl/inc/pdf/pdfwriter_impl.hxx
index 5756bebf0082..fe0052915a23 100644
--- a/vcl/inc/pdf/pdfwriter_impl.hxx
+++ b/vcl/inc/pdf/pdfwriter_impl.hxx
@@ -800,7 +800,7 @@ private:
 
     ExternalPDFStreams m_aExternalPDFStreams;
 
-    PDFEncryptor m_aPDFEncryptor;
+    std::unique_ptr<IPDFEncryptor> m_pPDFEncryptor;
 
     /* output redirection; e.g. to accumulate content streams for
        XObjects
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx 
b/vcl/source/gdi/pdfwriter_impl.cxx
index 893471b3a34b..e80af24f1679 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -1454,11 +1454,14 @@ PDFWriterImpl::PDFWriterImpl( const 
PDFWriter::PDFWriterContext& rContext,
     setupDocInfo();
 
     if (xEncryptionMaterialHolder.is())
-        m_aPDFEncryptor.prepareEncryption(xEncryptionMaterialHolder, 
m_aContext.Encryption);
+    {
+        m_pPDFEncryptor.reset(new PDFEncryptor);
+        m_pPDFEncryptor->prepareEncryption(xEncryptionMaterialHolder, 
m_aContext.Encryption);
+    }
 
     if (m_aContext.Encryption.Encrypt())
     {
-        m_aPDFEncryptor.setupKeysAndCheck(m_aContext.Encryption);
+        m_pPDFEncryptor->setupKeysAndCheck(m_aContext.Encryption);
     }
 
     // write header
@@ -1592,7 +1595,7 @@ append the string as unicode hex, encrypted if needed
 inline void PDFWriterImpl::appendUnicodeTextStringEncrypt( const OUString& 
rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer )
 {
     rOutBuffer.append( "<" );
-    if( m_aContext.Encryption.Encrypt() )
+    if (m_aContext.Encryption.Encrypt())
     {
         const sal_Unicode* pStr = rInString.getStr();
         sal_Int32 nLen = rInString.getLength();
@@ -1611,7 +1614,7 @@ inline void 
PDFWriterImpl::appendUnicodeTextStringEncrypt( const OUString& rInSt
             *pCopy++ = static_cast<sal_uInt8>( aUnChar & 255 );
         }
         //encrypt in place
-        rtl_cipher_encodeARCFOUR( m_aPDFEncryptor.m_aCipher, 
m_vEncryptionBuffer.data(), nChars, m_vEncryptionBuffer.data(), nChars);
+        m_pPDFEncryptor->encrypt(m_vEncryptionBuffer.data(), nChars, 
m_vEncryptionBuffer.data(), nChars);
         //now append, hexadecimal (appendHex), the encrypted result
         for(int i = 0; i < nChars; i++)
             appendHex( m_vEncryptionBuffer[i], rOutBuffer );
@@ -1626,12 +1629,12 @@ inline void PDFWriterImpl::appendLiteralStringEncrypt( 
std::string_view rInStrin
     rOutBuffer.append( "(" );
     sal_Int32 nChars = rInString.size();
     //check for encryption, if ok, encrypt the string, then convert with 
appndLiteralString
-    if( m_aContext.Encryption.Encrypt() )
+    if (m_aContext.Encryption.Encrypt())
     {
         m_vEncryptionBuffer.resize(nChars);
         //encrypt the string in a buffer, then append it
-        enableStringEncryption( nInObjectNumber );
-        rtl_cipher_encodeARCFOUR(m_aPDFEncryptor.m_aCipher, rInString.data(), 
nChars, m_vEncryptionBuffer.data(), nChars);
+        enableStringEncryption(nInObjectNumber);
+        m_pPDFEncryptor->encrypt(rInString.data(), nChars, 
m_vEncryptionBuffer.data(), nChars);
         appendLiteralString( 
reinterpret_cast<char*>(m_vEncryptionBuffer.data()), nChars, rOutBuffer );
     }
     else
@@ -1739,16 +1742,17 @@ bool PDFWriterImpl::writeBufferBytes( const void* 
pBuffer, sal_uInt64 nBytes )
     else
     {
         bool  buffOK = true;
-        if (m_aPDFEncryptor.isStreamEncryptionEnabled())
+        bool bStreamEncryption = m_pPDFEncryptor && 
m_pPDFEncryptor->isStreamEncryptionEnabled();
+        if (bStreamEncryption)
         {
             m_vEncryptionBuffer.resize(nBytes);
             if (buffOK)
             {
-                m_aPDFEncryptor.encrypt(pBuffer, nBytes, 
m_vEncryptionBuffer.data(), nBytes);
+                m_pPDFEncryptor->encrypt(pBuffer, nBytes, 
m_vEncryptionBuffer.data(), nBytes);
             }
         }
 
-        const void* pWriteBuffer = 
(m_aPDFEncryptor.isStreamEncryptionEnabled() && buffOK) ? 
m_vEncryptionBuffer.data() : pBuffer;
+        const void* pWriteBuffer = (bStreamEncryption && buffOK) ? 
m_vEncryptionBuffer.data() : pBuffer;
         m_DocDigest.update(static_cast<unsigned char const*>(pWriteBuffer), 
static_cast<sal_uInt32>(nBytes));
 
         if (m_aFile.write(pWriteBuffer, nBytes, nWritten) != osl::File::E_None)
@@ -6099,7 +6103,7 @@ sal_Int32 PDFWriterImpl::emitEncrypt()
         // emit the owner password, must not be encrypted
         aWriter.writeString("/O", 
reinterpret_cast<char*>(m_aContext.Encryption.OValue.data()), 
sal_Int32(m_aContext.Encryption.OValue.size()));
         aWriter.writeString("/U", 
reinterpret_cast<char*>(m_aContext.Encryption.UValue.data()), 
sal_Int32(m_aContext.Encryption.UValue.size()));
-        aWriter.write("/P", m_aPDFEncryptor.getAccessPermissions());
+        aWriter.write("/P", m_pPDFEncryptor->getAccessPermissions());
         aWriter.endDict();
         aWriter.endObject();
 
@@ -9667,7 +9671,7 @@ bool PDFWriterImpl::writeBitmapObject( const BitmapEmit& 
rObject, bool bMask )
             aLine.append( "
<" );
             if( m_aContext.Encryption.Encrypt() )
             {
-                enableStringEncryption( rObject.m_nObject );
+                enableStringEncryption(rObject.m_nObject);
                 //check encryption buffer size
                 m_vEncryptionBuffer.resize(pAccess->GetPaletteEntryCount()*3);
                 int nChar = 0;
@@ -9680,7 +9684,7 @@ bool PDFWriterImpl::writeBitmapObject( const BitmapEmit& 
rObject, bool bMask )
                     m_vEncryptionBuffer[nChar++] = rColor.GetBlue();
                 }
                 //encrypt the colorspace lookup table
-                rtl_cipher_encodeARCFOUR(m_aPDFEncryptor.m_aCipher, 
m_vEncryptionBuffer.data(), nChar, m_vEncryptionBuffer.data(), nChar);
+                m_pPDFEncryptor->encrypt(m_vEncryptionBuffer.data(), nChar, 
m_vEncryptionBuffer.data(), nChar);
                 //now queue the data for output
                 nChar = 0;
                 for( sal_uInt16 i = 0; i < pAccess->GetPaletteEntryCount(); 
i++ )
diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx 
b/vcl/source/gdi/pdfwriter_impl2.cxx
index 547c0fb36896..2f67295b9a7f 100644
--- a/vcl/source/gdi/pdfwriter_impl2.cxx
+++ b/vcl/source/gdi/pdfwriter_impl2.cxx
@@ -1080,25 +1080,25 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& 
i_rMtf, vcl::PDFExtOutDevDa
 
 void PDFWriterImpl::checkAndEnableStreamEncryption(sal_Int32 nObject)
 {
-    if (!m_aContext.Encryption.Encrypt())
+    if (!m_aContext.Encryption.Encrypt() || !m_pPDFEncryptor)
         return;
 
-    m_aPDFEncryptor.enableStreamEncryption();
-    m_aPDFEncryptor.setupEncryption(m_aContext.Encryption.EncryptionKey, 
nObject);
+    m_pPDFEncryptor->enableStreamEncryption();
+    m_pPDFEncryptor->setupEncryption(m_aContext.Encryption.EncryptionKey, 
nObject);
 }
 
 void PDFWriterImpl::disableStreamEncryption()
 {
-    m_aPDFEncryptor.disableStreamEncryption();
-
+    if (m_pPDFEncryptor)
+        m_pPDFEncryptor->disableStreamEncryption();
 }
 
 void PDFWriterImpl::enableStringEncryption(sal_Int32 nObject)
 {
-    if (!m_aContext.Encryption.Encrypt())
+    if (!m_aContext.Encryption.Encrypt() || !m_pPDFEncryptor)
         return;
 
-    m_aPDFEncryptor.setupEncryption(m_aContext.Encryption.EncryptionKey, 
nObject);
+    m_pPDFEncryptor->setupEncryption(m_aContext.Encryption.EncryptionKey, 
nObject);
 }
 
 const tools::Long unsetRun[256] =

Reply via email to