summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2024-11-22 15:21:34 +0900
committerTomaž Vajngerl <quikee@gmail.com>2024-12-23 15:23:06 +0100
commit31427786778946b9d6f0f23731fdaae40e967e21 (patch)
tree7f5712a7df400b6d8644e20f325b54e2f1d6b0a6 /vcl
parentb8ea5a835ec07d0f84cd8ec2d0dab976edcfcebe (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.hxx196
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx98
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");