summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2024-10-31 23:40:35 +0100
committerTomaž Vajngerl <quikee@gmail.com>2024-11-04 21:51:00 +0100
commitb0a6a402f00e966c24f5b1e74b9c8aefeb62af8b (patch)
treea29eadd6f5d7d4e5cd0b97752eb97ae92edff163
parentcbc51154c02ec7a52a3ad047f3bab1670c9d481a (diff)
pdf: move encrypt code into emitEncrypt, add PDFStructureWriter
Move the encryption code into emitEncrypt and rewrite that with the newly introduced PDFStructureWriter, which is now responsible to write the PDF basic structure elements into a string buffer. The PDFStructureWriter will be extended with new features when there is demand. Change-Id: I4f4099886860b72b4f1866b19a8afb7cc8fb4ea4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176024 Reviewed-by: Tomaž Vajngerl <quikee@gmail.com> Tested-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r--vcl/inc/pdf/pdfwriter_impl.hxx2
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx122
2 files changed, 97 insertions, 27 deletions
diff --git a/vcl/inc/pdf/pdfwriter_impl.hxx b/vcl/inc/pdf/pdfwriter_impl.hxx
index df86ea640e96..24a2858ec994 100644
--- a/vcl/inc/pdf/pdfwriter_impl.hxx
+++ b/vcl/inc/pdf/pdfwriter_impl.hxx
@@ -1025,6 +1025,8 @@ i12626
// creates a PKCS7 object using the ByteRange and overwrite /Contents
// of the signature dictionary
bool finalizeSignature();
+ //writes encrypt
+ sal_Int32 emitEncrypt();
// writes xref and trailer
bool emitTrailer();
// emits info dict (if applicable)
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index ce3d102d5c55..b5d7ad31cf08 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -276,6 +276,67 @@ void appendDestinationName( const OUString& rString, OStringBuffer& rBuffer )
}
}
+/** Writes the PDF structure to the string buffer.
+ *
+ * Structure elements like: objects, IDs, dictionaries, key/values, ...
+ *
+ */
+class PDFStructureWriter
+{
+ OStringBuffer maLine;
+public:
+ PDFStructureWriter()
+ : maLine(1024)
+ {
+ }
+
+ 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 writeString(std::string_view key, char* pString, sal_Int32 nSize)
+ {
+ maLine.append(key);
+ maLine.append(" (");
+ appendLiteralString(pString, nSize, maLine);
+ maLine.append(")");
+ }
+};
+
} // end anonymous namespace
namespace vcl
@@ -6085,6 +6146,39 @@ sal_Int32 PDFWriterImpl::emitDocumentMetadata()
return nObject;
}
+sal_Int32 PDFWriterImpl::emitEncrypt()
+{
+ //emit the security information
+ //must be emitted as indirect dictionary object, since
+ //Acrobat Reader 5 works only with this kind of implementation
+
+ sal_Int32 nObject = createObject();
+
+ if (updateObject(nObject))
+ {
+ PDFStructureWriter aWriter;
+ aWriter.startObject(nObject);
+ aWriter.startDict();
+ aWriter.write("/Filter", "/Standard");
+ aWriter.write("/V", 2);
+ aWriter.write("/Length", 128);
+ aWriter.write("/R", 3);
+ // 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_nAccessPermissions);
+ aWriter.endDict();
+ aWriter.endObject();
+
+ if (!writeBuffer(aWriter.getLine()))
+ nObject = 0;
+ }
+ else
+ nObject = 0;
+
+ return nObject;
+}
+
bool PDFWriterImpl::emitTrailer()
{
// emit doc info
@@ -6094,33 +6188,7 @@ bool PDFWriterImpl::emitTrailer()
if( m_aContext.Encryption.Encrypt() )
{
- //emit the security information
- //must be emitted as indirect dictionary object, since
- //Acrobat Reader 5 works only with this kind of implementation
- nSecObject = createObject();
-
- if( updateObject( nSecObject ) )
- {
- OStringBuffer aLineS( 1024 );
- aLineS.append( nSecObject );
- aLineS.append( " 0 obj\n"
- "<</Filter/Standard/V " );
- // check the version
- aLineS.append( "2/Length 128/R 3" );
-
- // emit the owner password, must not be encrypted
- aLineS.append( "/O(" );
- appendLiteralString( reinterpret_cast<char*>(m_aContext.Encryption.OValue.data()), sal_Int32(m_aContext.Encryption.OValue.size()), aLineS );
- aLineS.append( ")/U(" );
- appendLiteralString( reinterpret_cast<char*>(m_aContext.Encryption.UValue.data()), sal_Int32(m_aContext.Encryption.UValue.size()), aLineS );
- aLineS.append( ")/P " );// the permission set
- aLineS.append( m_nAccessPermissions );
- aLineS.append( ">>\nendobj\n\n" );
- if( !writeBuffer( aLineS ) )
- nSecObject = 0;
- }
- else
- nSecObject = 0;
+ nSecObject = emitEncrypt();
}
// emit xref table
// remember start