From e418f752f85adcb6de6782e3881ca208156cef39 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 4 Nov 2013 20:58:23 +1030 Subject: [PATCH 6/8] PDFDoc: compress decrypted streams --- poppler/PDFDoc.cc | 48 ++++++++++++++++++++++++++++++++++-------------- poppler/PDFDoc.h | 3 ++- poppler/Stream.h | 21 +++++++++++++++++++++ 3 files changed, 57 insertions(+), 15 deletions(-) diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc index ab02eda..7590690 100644 --- a/poppler/PDFDoc.cc +++ b/poppler/PDFDoc.cc @@ -77,6 +77,7 @@ #endif #include "PDFDoc.h" #include "Hints.h" +#include "DeflateStream.h" #if MULTITHREADED # define pdfdocLocker() MutexLocker locker(&mutex) @@ -990,13 +991,35 @@ void PDFDoc::writeDictionnary (Dict* dict, OutStream* outStr, XRef *xRef, Guint outStr->printf(">> "); } -void PDFDoc::writeStream (Stream* str, OutStream* outStr) +// Find the length of this stream after compressing with Deflate +Goffset PDFDoc::getFlateStreamLength (Stream* str) { + int n; + Guchar buf[4096]; + NullOutStream nullStr; + DeflateStream deflateStr(&nullStr); + str->reset(); + do { + n = str->doGetChars(sizeof(buf), buf); + deflateStr.write(buf, n); + } while (n); + deflateStr.close(); + return nullStr.getNumBytesWritten(); +} + +// Write stream using Deflate compression +void PDFDoc::writeFlateStream (Stream* str, OutStream* outStr) +{ + int n; + Guchar buf[4096]; outStr->printf("stream\r\n"); + DeflateStream deflateStr(outStr); str->reset(); - for (int c=str->getChar(); c!= EOF; c=str->getChar()) { - outStr->printf("%c", c); - } + do { + n = str->doGetChars(sizeof(buf), buf); + deflateStr.write(buf, n); + } while (n); + deflateStr.close(); outStr->printf("\r\nendstream\r\n"); } @@ -1093,8 +1116,7 @@ void PDFDoc::writeObject (Object* obj, OutStream* outStr, XRef *xRef, Guint numO CryptAlgorithm encAlgorithm, int keyLength, int objNum, int objGen) { Array *array; - Object obj1; - Goffset tmp; + Object obj1, obj2; switch (obj->getType()) { case objBool: @@ -1194,13 +1216,7 @@ void PDFDoc::writeObject (Object* obj, OutStream* outStr, XRef *xRef, Guint numO stream = encStream; } - stream->reset(); - //recalculate stream length - tmp = 0; - for (int c=stream->getChar(); c!=EOF; c=stream->getChar()) { - tmp++; - } - obj1.initInt64(tmp); + obj1.initInt64(getFlateStreamLength(stream)); stream->getDict()->set("Length", &obj1); //Remove Stream encoding @@ -1209,8 +1225,12 @@ void PDFDoc::writeObject (Object* obj, OutStream* outStr, XRef *xRef, Guint numO } stream->getDict()->remove("DecodeParms"); + // Set FlateDecode filter + obj2.initName("FlateDecode"); + stream->getDict()->set("Filter", &obj2); + writeDictionnary (stream->getDict(),outStr, xRef, numOffset, fileKey, encAlgorithm, keyLength, objNum, objGen); - writeStream (stream,outStr); + writeFlateStream (stream,outStr); delete encStream; obj1.free(); } else { diff --git a/poppler/PDFDoc.h b/poppler/PDFDoc.h index 2d62d02..8f576f1 100644 --- a/poppler/PDFDoc.h +++ b/poppler/PDFDoc.h @@ -279,7 +279,8 @@ private: void writeDictionnary (Dict* dict, OutStream* outStr, Guchar *fileKey, CryptAlgorithm encAlgorithm, int keyLength, int objNum, int objGen) { writeDictionnary(dict, outStr, getXRef(), 0, fileKey, encAlgorithm, keyLength, objNum, objGen); } - static void writeStream (Stream* str, OutStream* outStr); + static Goffset getFlateStreamLength (Stream* str); + static void writeFlateStream (Stream* str, OutStream* outStr); static void writeRawStream (Stream* str, OutStream* outStr); void writeXRefTableTrailer (Goffset uxrefOffset, XRef *uxref, GBool writeAllEntries, int uxrefSize, OutStream* outStr, GBool incrUpdate); diff --git a/poppler/Stream.h b/poppler/Stream.h index ae089b0..3f21ca4 100644 --- a/poppler/Stream.h +++ b/poppler/Stream.h @@ -303,6 +303,27 @@ private: }; +//------------------------------------------------------------------------ +// NullOutStream +//------------------------------------------------------------------------ +class NullOutStream : public OutStream { +public: + NullOutStream () { count = 0;}; + + ~NullOutStream () {}; + + Goffset getNumBytesWritten() { return count; } + + void close() {} + + Goffset getPos() { return 0; } + + void write (const Guchar *data, long length) { count += length; } + +private: + Goffset count; +}; + //------------------------------------------------------------------------ // BaseStream -- 1.8.3.2