diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2024-11-22 15:21:34 +0900 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2024-12-23 15:23:06 +0100 |
commit | 31427786778946b9d6f0f23731fdaae40e967e21 (patch) | |
tree | 7f5712a7df400b6d8644e20f325b54e2f1d6b0a6 /vcl | |
parent | b8ea5a835ec07d0f84cd8ec2d0dab976edcfcebe (diff) |
pdf: move PDFStructureWriter into own file, rename to COSWriter
This needs to duplicate some functions from pdfwriter_impl to make
this possible.
Change-Id: Ie738c9690306d6498c883f034a3fcd6483f24eef
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176985
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178762
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/pdf/COSWriter.hxx | 196 | ||||
-rw-r--r-- | vcl/source/gdi/pdfwriter_impl.cxx | 98 |
2 files changed, 208 insertions, 86 deletions
diff --git a/vcl/inc/pdf/COSWriter.hxx b/vcl/inc/pdf/COSWriter.hxx new file mode 100644 index 000000000000..767654689b73 --- /dev/null +++ b/vcl/inc/pdf/COSWriter.hxx @@ -0,0 +1,196 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <pdf/IPDFEncryptor.hxx> + +namespace vcl::pdf +{ +/** Writes the "Carousel" object structure (COS) to the string buffer. + * + * "Carousel" object structure (COS) is used by PDF. + * + * Structure elements like: objects, IDs, dictionaries, key/values, ... + */ +class COSWriter +{ + std::unique_ptr<IPDFEncryptor>& mpPDFEncryptor; + OStringBuffer maLine; + + void appendLiteralString(const char* pStr, sal_Int32 nLength) + { + while (nLength) + { + switch (*pStr) + { + case '\n': + maLine.append("\\n"); + break; + case '\r': + maLine.append("\\r"); + break; + case '\t': + maLine.append("\\t"); + break; + case '\b': + maLine.append("\\b"); + break; + case '\f': + maLine.append("\\f"); + break; + case '(': + case ')': + case '\\': + maLine.append("\\"); + maLine.append(static_cast<char>(*pStr)); + break; + default: + maLine.append(static_cast<char>(*pStr)); + break; + } + pStr++; + nLength--; + } + } + template <typename T> void appendHex(T nValue) + { + static constexpr const auto constHexDigits = std::to_array<char>( + { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }); + maLine.append(constHexDigits[(nValue >> 4) & 15]); + maLine.append(constHexDigits[nValue & 15]); + } + + void appendHexArray(sal_uInt8* pArray, size_t nSize) + { + for (size_t i = 0; i < nSize; i++) + appendHex(pArray[i]); + } + +public: + COSWriter(std::unique_ptr<IPDFEncryptor>& pPDFEncryptor) + : mpPDFEncryptor(pPDFEncryptor) + , maLine(1024) + { + } + + void startObject(sal_Int32 nObjectID) + { + maLine.append(nObjectID); + maLine.append(" 0 obj\n"); + } + + void endObject() { maLine.append("endobj\n\n"); } + + OStringBuffer& getLine() { return maLine; } + + void startDict() { maLine.append("<<"); } + + void endDict() { maLine.append(">>\n"); } + + void write(std::string_view key, std::string_view value) + { + maLine.append(key); + maLine.append(value); + } + + void write(std::string_view key, sal_Int32 value) + { + maLine.append(key); + maLine.append(" "); + maLine.append(value); + } + + void writeString(std::string_view key, char* pString, sal_Int32 nSize) + { + maLine.append(key); + maLine.append(" ("); + appendLiteralString(pString, nSize); + maLine.append(")"); + } + + void writeUnicodeEncrypt(std::string_view key, OUString const& rString, sal_Int32 nObject, + bool bEncrypt, std::vector<sal_uInt8>& rKey) + { + maLine.append(key); + maLine.append("<"); + + if (bEncrypt) + { + const sal_Unicode* pString = rString.getStr(); + size_t nLength = rString.getLength(); + //prepare a unicode string, encrypt it + mpPDFEncryptor->setupEncryption(rKey, nObject); + sal_Int32 nChars = 2 + (nLength * 2); + std::vector<sal_uInt8> aEncryptionBuffer(nChars); + sal_uInt8* pCopy = aEncryptionBuffer.data(); + *pCopy++ = 0xFE; + *pCopy++ = 0xFF; + // we need to prepare a byte stream from the unicode string buffer + for (size_t i = 0; i < nLength; i++) + { + sal_Unicode aUnicodeChar = pString[i]; + *pCopy++ = sal_uInt8(aUnicodeChar >> 8); + *pCopy++ = sal_uInt8(aUnicodeChar & 255); + } + std::vector<sal_uInt8> aNewBuffer(nChars); + mpPDFEncryptor->encrypt(aEncryptionBuffer.data(), nChars, aNewBuffer, nChars); + //now append, hexadecimal (appendHex), the encrypted result + appendHexArray(aNewBuffer.data(), aNewBuffer.size()); + } + else + { + //PDFWriter::AppendUnicodeTextString(rInString, maLine); + maLine.append("FEFF"); + const sal_Unicode* pString = rString.getStr(); + size_t nLength = rString.getLength(); + for (size_t i = 0; i < nLength; i++) + { + sal_Unicode aChar = pString[i]; + appendHex(sal_Int8(aChar >> 8)); + appendHex(sal_Int8(aChar & 255)); + } + } + maLine.append(">"); + } + + void writeLiteralEncrypt(std::string_view key, std::string_view value, sal_Int32 nObject, + bool bEncrypt, std::vector<sal_uInt8>& rKey) + { + maLine.append(key); + + maLine.append("("); + size_t nChars = value.size(); + + if (bEncrypt) + { + std::vector<sal_uInt8> aEncryptionBuffer(nChars); + mpPDFEncryptor->setupEncryption(rKey, nObject); + mpPDFEncryptor->encrypt(value.data(), nChars, aEncryptionBuffer, nChars); + appendLiteralString(reinterpret_cast<char*>(aEncryptionBuffer.data()), + aEncryptionBuffer.size()); + } + else + { + appendLiteralString(value.data(), nChars); + } + maLine.append(")"); + } + + void writeHexArray(std::string_view key, sal_uInt8* pData, size_t nSize) + { + maLine.append(key); + maLine.append(" <"); + appendHexArray(pData, nSize); + maLine.append(">"); + } +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 56311e7f2791..a4c2a501443b 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -85,6 +85,7 @@ #include <svdata.hxx> #include <vcl/BitmapWriteAccess.hxx> +#include <pdf/COSWriter.hxx> #include <fontsubset.hxx> #include <font/EmphasisMark.hxx> #include <font/PhysicalFontFace.hxx> @@ -308,83 +309,6 @@ GEOMETRY lcl_convert( const MapMode& _rSource, const MapMode& _rDest, OutputDevi void removePlaceholderSE(std::vector<PDFStructureElement> & rStructure, PDFStructureElement& rEle); -/** Writes the PDF structure to the string buffer. - * - * Structure elements like: objects, IDs, dictionaries, key/values, ... - */ -class PDFStructureWriter -{ - OStringBuffer maLine; - PDFWriterImpl& mrWriterImpl; -public: - PDFStructureWriter(PDFWriterImpl& rWriterImpl) - : maLine(1024) - , mrWriterImpl(rWriterImpl) - { - } - - void startObject(sal_Int32 nID) - { - appendObjectID(nID, maLine); - } - - void endObject() - { - maLine.append("endobj\n\n"); - } - - OStringBuffer& getLine() - { - return maLine; - } - - void startDict() - { - maLine.append("<<"); - } - - void endDict() - { - maLine.append(">>\n"); - } - - void write(std::string_view key, std::string_view value) - { - maLine.append(key); - maLine.append(value); - } - - void write(std::string_view key, sal_Int32 value) - { - maLine.append(key); - maLine.append(" "); - maLine.append(value); - } - - void writeUnicodeEncrypt(std::string_view key, OUString const& rString, sal_Int32 nObject) - { - maLine.append(key); - mrWriterImpl.appendUnicodeTextStringEncrypt(rString, nObject, maLine); - } - - void writeLiteralEncrypt(std::string_view key, std::string_view value, sal_Int32 nObject) - { - maLine.append(key); - mrWriterImpl.appendLiteralStringEncrypt(value, nObject, maLine); - } - - void writeHexArray(std::string_view key, sal_uInt8* pData, size_t nSize) - { - maLine.append(key); - maLine.append(" <"); - for (size_t i = 0; i < nSize; i++) - { - appendHex(sal_Int8(pData[i]), maLine); - } - maLine.append(">"); - } -}; - } // end anonymous namespace void PDFWriter::AppendUnicodeTextString(const OUString& rString, OStringBuffer& rBuffer) @@ -5880,7 +5804,9 @@ sal_Int32 PDFWriterImpl::emitInfoDict( ) if (!updateObject(nObject)) return 0; - PDFStructureWriter aWriter(*this); + COSWriter aWriter(m_pPDFEncryptor); + bool bEncrypt = m_aContext.Encryption.canEncrypt(); + auto& rKey = m_aContext.Encryption.EncryptionKey; aWriter.startObject(nObject); aWriter.startDict(); @@ -5890,31 +5816,31 @@ sal_Int32 PDFWriterImpl::emitInfoDict( ) { if (!m_aContext.DocumentInfo.Title.isEmpty()) { - aWriter.writeUnicodeEncrypt("/Title", m_aContext.DocumentInfo.Title, nObject); + aWriter.writeUnicodeEncrypt("/Title", m_aContext.DocumentInfo.Title, nObject, bEncrypt, rKey); } if (!m_aContext.DocumentInfo.Author.isEmpty()) { - aWriter.writeUnicodeEncrypt("/Author", m_aContext.DocumentInfo.Author, nObject); + aWriter.writeUnicodeEncrypt("/Author", m_aContext.DocumentInfo.Author, nObject, bEncrypt, rKey); } if (!m_aContext.DocumentInfo.Subject.isEmpty()) { - aWriter.writeUnicodeEncrypt("/Subject", m_aContext.DocumentInfo.Subject, nObject); + aWriter.writeUnicodeEncrypt("/Subject", m_aContext.DocumentInfo.Subject, nObject, bEncrypt, rKey); } if (!m_aContext.DocumentInfo.Keywords.isEmpty()) { - aWriter.writeUnicodeEncrypt("/Keywords", m_aContext.DocumentInfo.Keywords, nObject); + aWriter.writeUnicodeEncrypt("/Keywords", m_aContext.DocumentInfo.Keywords, nObject, bEncrypt, rKey); } if (!m_aContext.DocumentInfo.Creator.isEmpty()) { - aWriter.writeUnicodeEncrypt("/Creator", m_aContext.DocumentInfo.Creator, nObject); + aWriter.writeUnicodeEncrypt("/Creator", m_aContext.DocumentInfo.Creator, nObject, bEncrypt, rKey); } if (!m_aContext.DocumentInfo.Producer.isEmpty()) { - aWriter.writeUnicodeEncrypt("/Producer", m_aContext.DocumentInfo.Producer, nObject); + aWriter.writeUnicodeEncrypt("/Producer", m_aContext.DocumentInfo.Producer, nObject, bEncrypt, rKey); } } // Allowed in PDF 2.0 - aWriter.writeLiteralEncrypt("/CreationDate", m_aCreationDateString, nObject); + aWriter.writeLiteralEncrypt("/CreationDate", m_aCreationDateString, nObject, bEncrypt, rKey); aWriter.endDict(); aWriter.endObject(); @@ -6173,7 +6099,7 @@ sal_Int32 PDFWriterImpl::emitEncrypt() if (updateObject(nObject)) { PDFEncryptionProperties& rProperties = m_aContext.Encryption; - PDFStructureWriter aWriter(*this); + COSWriter aWriter(m_pPDFEncryptor); aWriter.startObject(nObject); aWriter.startDict(); aWriter.write("/Filter", "/Standard"); |