poppler/PDFDoc.cc | 33 +++++++++++++++++++-------------- poppler/PDFDoc.h | 11 ++++++----- qt4/src/poppler-pdf-converter.cc | 14 +++++++++++++- qt4/src/poppler-qt4.h | 4 +++- qt5/src/poppler-pdf-converter.cc | 14 +++++++++++++- qt5/src/poppler-qt5.h | 4 +++- utils/pdfunite.cc | 3 ++- 7 files changed, 59 insertions(+), 24 deletions(-)
New commits: commit a42614284c94c6742b2343abd797657fffa80e0e Author: Adam Reichold <[email protected]> Date: Tue Sep 1 00:15:46 2015 +0200 Add option to strip encryption Adds a PDF write mode that forces a complete rewrite that ignores the original encryption parameters of the document and also removes the encryption entry from the trailer dictionary. diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc index 46c4544..153dc75 100644 --- a/poppler/PDFDoc.cc +++ b/poppler/PDFDoc.cc @@ -29,7 +29,7 @@ // Copyright (C) 2011-2015 Thomas Freitag <[email protected]> // Copyright (C) 2012, 2013 Fabio D'Urso <[email protected]> // Copyright (C) 2013, 2014 Adrian Johnson <[email protected]> -// Copyright (C) 2013 Adam Reichold <[email protected]> +// Copyright (C) 2013, 2015 Adam Reichold <[email protected]> // Copyright (C) 2014 Bogdan Cristea <[email protected]> // Copyright (C) 2015 Li Junling <[email protected]> // @@ -763,7 +763,7 @@ int PDFDoc::savePageAs(GooString *name, int pageNo) Ref ref; ref.num = rootNum; ref.gen = 0; - Dict *trailerDict = createTrailerDict(rootNum + 3, gFalse, 0, &ref, getXRef(), + Dict *trailerDict = createTrailerDict(rootNum + 3, gFalse, gFalse, 0, &ref, getXRef(), name->getCString(), uxrefOffset); writeXRefTableTrailer(trailerDict, yRef, gFalse /* do not write unnecessary entries */, uxrefOffset, outStr, getXRef()); @@ -809,7 +809,10 @@ int PDFDoc::saveAs(OutStream *outStr, PDFWriteMode mode) { // simply copy the original file saveWithoutChangesAs (outStr); } else if (mode == writeForceRewrite) { - saveCompleteRewrite(outStr); + saveCompleteRewrite(outStr, false); + } else if (mode == writeStripEncryption) { + // do a complete rewrite ignoring the original encryption parameters + saveCompleteRewrite(outStr, true); } else { saveIncrementalUpdate(outStr); } @@ -916,7 +919,7 @@ void PDFDoc::saveIncrementalUpdate (OutStream* outStr) uxref->add(uxrefStreamRef.num, uxrefStreamRef.gen, uxrefOffset, gTrue); } - Dict *trailerDict = createTrailerDict(numobjects, gTrue, getStartXRef(), &rootRef, getXRef(), fileNameA, uxrefOffset); + Dict *trailerDict = createTrailerDict(numobjects, gTrue, gFalse, getStartXRef(), &rootRef, getXRef(), fileNameA, uxrefOffset); if (xRefStream) { writeXRefStreamTrailer(trailerDict, uxref, &uxrefStreamRef, uxrefOffset, outStr, getXRef()); } else { @@ -927,16 +930,18 @@ void PDFDoc::saveIncrementalUpdate (OutStream* outStr) delete uxref; } -void PDFDoc::saveCompleteRewrite (OutStream* outStr) +void PDFDoc::saveCompleteRewrite (OutStream* outStr, GBool stripEncryption) { // Make sure that special flags are set, because we are going to read // all objects, including Unencrypted ones. xref->scanSpecialFlags(); - Guchar *fileKey; - CryptAlgorithm encAlgorithm; - int keyLength; - xref->getEncryptionParameters(&fileKey, &encAlgorithm, &keyLength); + Guchar *fileKey = NULL; + CryptAlgorithm encAlgorithm = cryptRC4; + int keyLength = 0; + + if (!stripEncryption) + xref->getEncryptionParameters(&fileKey, &encAlgorithm, &keyLength); outStr->printf("%%PDF-%d.%d\r\n",pdfMajorVersion,pdfMinorVersion); XRef *uxref = new XRef(); @@ -986,7 +991,7 @@ void PDFDoc::saveCompleteRewrite (OutStream* outStr) xref->unlock(); Goffset uxrefOffset = outStr->getPos(); writeXRefTableTrailer(uxrefOffset, uxref, gTrue /* write all entries */, - uxref->getNumObjects(), outStr, gFalse /* complete rewrite */); + uxref->getNumObjects(), outStr, gFalse /* complete rewrite */, stripEncryption); delete uxref; } @@ -1269,7 +1274,7 @@ void PDFDoc::writeObjectFooter (OutStream* outStr) outStr->printf("endobj\r\n"); } -Dict *PDFDoc::createTrailerDict(int uxrefSize, GBool incrUpdate, Goffset startxRef, +Dict *PDFDoc::createTrailerDict(int uxrefSize, GBool incrUpdate, GBool stripEncryption, Goffset startxRef, Ref *root, XRef *xRef, const char *fileName, Goffset fileSize) { Dict *trailerDict = new Dict(xRef); @@ -1308,7 +1313,7 @@ Dict *PDFDoc::createTrailerDict(int uxrefSize, GBool incrUpdate, Goffset startxR obj1.free(); GBool hasEncrypt = gFalse; - if (!xRef->getTrailerDict()->isNone()) { + if (!stripEncryption && !xRef->getTrailerDict()->isNone()) { Object obj2; xRef->getTrailerDict()->dictLookupNF("Encrypt", &obj2); if (!obj2.isNull()) { @@ -1401,7 +1406,7 @@ void PDFDoc::writeXRefStreamTrailer (Dict *trailerDict, XRef *uxref, Ref *uxrefS } void PDFDoc::writeXRefTableTrailer(Goffset uxrefOffset, XRef *uxref, GBool writeAllEntries, - int uxrefSize, OutStream* outStr, GBool incrUpdate) + int uxrefSize, OutStream* outStr, GBool incrUpdate, GBool stripEncryption) { const char *fileNameA = fileName ? fileName->getCString() : NULL; // file size (doesn't include the trailer) @@ -1415,7 +1420,7 @@ void PDFDoc::writeXRefTableTrailer(Goffset uxrefOffset, XRef *uxref, GBool write Ref ref; ref.num = getXRef()->getRootNum(); ref.gen = getXRef()->getRootGen(); - Dict * trailerDict = createTrailerDict(uxrefSize, incrUpdate, getStartXRef(), &ref, + Dict * trailerDict = createTrailerDict(uxrefSize, incrUpdate, stripEncryption, getStartXRef(), &ref, getXRef(), fileNameA, fileSize); writeXRefTableTrailer(trailerDict, uxref, writeAllEntries, uxrefOffset, outStr, getXRef()); delete trailerDict; diff --git a/poppler/PDFDoc.h b/poppler/PDFDoc.h index 6c40f7b..d4a8b5e 100644 --- a/poppler/PDFDoc.h +++ b/poppler/PDFDoc.h @@ -25,7 +25,7 @@ // Copyright (C) 2011, 2013, 2014 Thomas Freitag <[email protected]> // Copyright (C) 2012 Fabio D'Urso <[email protected]> // Copyright (C) 2013 Adrian Johnson <[email protected]> -// Copyright (C) 2013 Adam Reichold <[email protected]> +// Copyright (C) 2013, 2015 Adam Reichold <[email protected]> // Copyright (C) 2013 Adrian Perez de Castro <[email protected]> // // To see a description of the changes please see the Changelog file that @@ -66,7 +66,8 @@ class StructTreeRoot; enum PDFWriteMode { writeStandard, writeForceRewrite, - writeForceIncremental + writeForceIncremental, + writeStripEncryption }; //------------------------------------------------------------------------ @@ -258,7 +259,7 @@ public: static void writeHeader(OutStream *outStr, int major, int minor); // Ownership goes to the caller - static Dict *createTrailerDict (int uxrefSize, GBool incrUpdate, Goffset startxRef, + static Dict *createTrailerDict (int uxrefSize, GBool incrUpdate, GBool stripEncryption, Goffset startxRef, Ref *root, XRef *xRef, const char *fileName, Goffset fileSize); static void writeXRefTableTrailer (Dict *trailerDict, XRef *uxref, GBool writeAllEntries, Goffset uxrefOffset, OutStream* outStr, XRef *xRef); @@ -285,11 +286,11 @@ private: static void writeStream (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); + int uxrefSize, OutStream* outStr, GBool incrUpdate, GBool stripEncryption); static void writeString (GooString* s, OutStream* outStr, Guchar *fileKey, CryptAlgorithm encAlgorithm, int keyLength, int objNum, int objGen); void saveIncrementalUpdate (OutStream* outStr); - void saveCompleteRewrite (OutStream* outStr); + void saveCompleteRewrite (OutStream* outStr, GBool stripEncryption); Page *parsePage(int page); diff --git a/qt4/src/poppler-pdf-converter.cc b/qt4/src/poppler-pdf-converter.cc index 9699b75..362d56c 100644 --- a/qt4/src/poppler-pdf-converter.cc +++ b/qt4/src/poppler-pdf-converter.cc @@ -1,6 +1,7 @@ /* poppler-pdf-converter.cc: qt4 interface to poppler * Copyright (C) 2008, Pino Toscano <[email protected]> * Copyright (C) 2008, 2009, Albert Astals Cid <[email protected]> + * Copyright (C) 2015 Adam Reichold <[email protected]> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -92,7 +93,18 @@ bool PDFConverter::convert() QIODeviceOutStream stream(dev); if (d->opts & WithChanges) { - errorCode = d->document->doc->saveAs(&stream); + PDFWriteMode mode = writeStandard; + + if (d->opts & StripEncryption) + { + mode = writeStripEncryption; + } + else if (d->opts & ForceRewrite) + { + mode = writeForceRewrite; + } + + errorCode = d->document->doc->saveAs(&stream, mode); } else { diff --git a/qt4/src/poppler-qt4.h b/qt4/src/poppler-qt4.h index c0340a4..bf7d05c 100644 --- a/qt4/src/poppler-qt4.h +++ b/qt4/src/poppler-qt4.h @@ -1668,7 +1668,9 @@ height = dummy.height(); Options for the PDF export. */ enum PDFOption { - WithChanges = 0x00000001 ///< The changes done to the document are saved as well + WithChanges = 0x00000001, ///< The changes done to the document are saved as well + ForceRewrite = 0x00000002, ///< The document is rewritten instead of update incrementally (only applicable if WithChanges is also set) \since 0.36 + StripEncryption = 0x00000004 ///< The document is saved without encryption (only applicable if WithChanges is also set and implies ForceRewrite) \since 0.36 }; Q_DECLARE_FLAGS( PDFOptions, PDFOption ) diff --git a/qt5/src/poppler-pdf-converter.cc b/qt5/src/poppler-pdf-converter.cc index 557a9f8..0a8588c 100644 --- a/qt5/src/poppler-pdf-converter.cc +++ b/qt5/src/poppler-pdf-converter.cc @@ -1,6 +1,7 @@ /* poppler-pdf-converter.cc: qt interface to poppler * Copyright (C) 2008, Pino Toscano <[email protected]> * Copyright (C) 2008, 2009, Albert Astals Cid <[email protected]> + * Copyright (C) 2015 Adam Reichold <[email protected]> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -92,7 +93,18 @@ bool PDFConverter::convert() QIODeviceOutStream stream(dev); if (d->opts & WithChanges) { - errorCode = d->document->doc->saveAs(&stream); + PDFWriteMode mode = writeStandard; + + if (d->opts & StripEncryption) + { + mode = writeStripEncryption; + } + else if (d->opts & ForceRewrite) + { + mode = writeForceRewrite; + } + + errorCode = d->document->doc->saveAs(&stream, mode); } else { diff --git a/qt5/src/poppler-qt5.h b/qt5/src/poppler-qt5.h index b159477..53fcf51 100644 --- a/qt5/src/poppler-qt5.h +++ b/qt5/src/poppler-qt5.h @@ -1629,7 +1629,9 @@ height = dummy.height(); Options for the PDF export. */ enum PDFOption { - WithChanges = 0x00000001 ///< The changes done to the document are saved as well + WithChanges = 0x00000001, ///< The changes done to the document are saved as well + ForceRewrite = 0x00000002, ///< The document is rewritten instead of update incrementally (only applicable if WithChanges is also set) \since 0.36 + StripEncryption = 0x00000004 ///< The document is saved without encryption (only applicable if WithChanges is also set and implies ForceRewrite) \since 0.36 }; Q_DECLARE_FLAGS( PDFOptions, PDFOption ) diff --git a/utils/pdfunite.cc b/utils/pdfunite.cc index 19a1eb5..9aa80be 100644 --- a/utils/pdfunite.cc +++ b/utils/pdfunite.cc @@ -11,6 +11,7 @@ // Copyright (C) 2013 Adrian Johnson <[email protected]> // Copyright (C) 2013 Hib Eris <[email protected]> // Copyright (C) 2015 Arthur Stavisky <[email protected]> +// Copyright (C) 2015 Adam Reichold <[email protected]> // //======================================================================== @@ -450,7 +451,7 @@ int main (int argc, char *argv[]) Ref ref; ref.num = rootNum; ref.gen = 0; - Dict *trailerDict = PDFDoc::createTrailerDict(objectsCount, gFalse, 0, &ref, yRef, + Dict *trailerDict = PDFDoc::createTrailerDict(objectsCount, gFalse, gFalse, 0, &ref, yRef, fileName, outStr->getPos()); PDFDoc::writeXRefTableTrailer(trailerDict, yRef, gTrue, // write all entries according to ISO 32000-1, 7.5.4 Cross-Reference Table: "For a file that has never been incrementally updated, the cross-reference section shall contain only one subsection, whose object numbering begins at 0." uxrefOffset, outStr, yRef); _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
