goo/TiffWriter.cc | 5 +++++ poppler/PDFDoc.cc | 35 ++++++++++++++++++++++++++++++++--- poppler/XRef.cc | 15 +++++++++++++++ poppler/XRef.h | 2 ++ utils/pdfseparate.cc | 4 ---- 5 files changed, 54 insertions(+), 7 deletions(-)
New commits: commit c470a3929c0a02b8a543fcada22138ab1fc18176 Author: Thomas Freitag <[email protected]> Date: Mon Sep 17 23:13:48 2012 +0200 Support encrypted pdf files in pdfseparate diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc index dd93a64..f52d498 100644 --- a/poppler/PDFDoc.cc +++ b/poppler/PDFDoc.cc @@ -610,6 +610,15 @@ int PDFDoc::savePageAs(GooString *name, int pageNo) OutStream *outStr; XRef *yRef, *countRef; int rootNum = getXRef()->getNumObjects() + 1; + + // 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); if (pageNo < 1 || pageNo > getNumPages()) { error(errInternal, -1, "Illegal pageNo: {0:d}({1:d})", pageNo, getNumPages() ); @@ -634,7 +643,18 @@ int PDFDoc::savePageAs(GooString *name, int pageNo) outStr = new FileOutStream(f,0); yRef = new XRef(getXRef()->getTrailerDict()); + Object encrypt; + getXRef()->getTrailerDict()->dictLookup("Encrypt", &encrypt); + + if (secHdlr != NULL && !secHdlr->isUnencrypted()) { + yRef->setEncryption(secHdlr->getPermissionFlags(), + secHdlr->getOwnerPasswordOk(), fileKey, keyLength, secHdlr->getEncVersion(), secHdlr->getEncRevision(), encAlgorithm); + } countRef = new XRef(); + Object *trailerObj = getXRef()->getTrailerDict(); + if (trailerObj->isDict()) { + markPageObjects(trailerObj->getDict(), yRef, countRef, 0); + } yRef->add(0, 65535, 0, gFalse); writeHeader(outStr, getPDFMajorVersion(), getPDFMinorVersion()); @@ -644,7 +664,6 @@ int PDFDoc::savePageAs(GooString *name, int pageNo) if (infoObj.isDict()) { Dict *infoDict = infoObj.getDict(); markPageObjects(infoDict, yRef, countRef, 0); - Object *trailerObj = getXRef()->getTrailerDict(); if (trailerObj->isDict()) { Dict *trailerDict = trailerObj->getDict(); Object ref; @@ -673,6 +692,7 @@ int PDFDoc::savePageAs(GooString *name, int pageNo) Dict *pageDict = page.getDict(); markPageObjects(pageDict, yRef, countRef, 0); + yRef->markUnencrypted(); Guint objectsCount = writePageObjects(outStr, yRef, 0); yRef->add(rootNum,0,outStr->getPos(),gTrue); @@ -1498,7 +1518,8 @@ void PDFDoc::markPageObjects(Dict *pageDict, XRef *xRef, XRef *countRef, Guint n const char *key = pageDict->getKey(n); Object value; pageDict->getValNF(n, &value); if (strcmp(key, "Parent") != 0 && - strcmp(key, "Pages") != 0) { + strcmp(key, "Pages") != 0 && + strcmp(key, "Root") != 0) { markObject(&value, xRef, countRef, numOffset); } value.free(); @@ -1508,6 +1529,10 @@ void PDFDoc::markPageObjects(Dict *pageDict, XRef *xRef, XRef *countRef, Guint n Guint PDFDoc::writePageObjects(OutStream *outStr, XRef *xRef, Guint numOffset) { Guint objectsCount = 0; //count the number of objects in the XRef(s) + Guchar *fileKey; + CryptAlgorithm encAlgorithm; + int keyLength; + xRef->getEncryptionParameters(&fileKey, &encAlgorithm, &keyLength); for (int n = numOffset; n < xRef->getNumObjects(); n++) { if (xRef->getEntry(n)->type != xrefEntryFree) { @@ -1518,7 +1543,11 @@ Guint PDFDoc::writePageObjects(OutStream *outStr, XRef *xRef, Guint numOffset) objectsCount++; getXRef()->fetch(ref.num - numOffset, ref.gen, &obj); Guint offset = writeObjectHeader(&ref, outStr); - writeObject(&obj, outStr, xRef, numOffset, NULL, cryptRC4, 0, 0, 0); + if (xRef->getEntry(n)->getFlag(XRefEntry::Unencrypted)) { + writeObject(&obj, outStr, NULL, cryptRC4, 0, 0, 0); + } else { + writeObject(&obj, outStr, fileKey, encAlgorithm, keyLength, ref.num, ref.gen); + } writeObjectFooter(outStr); xRef->add(ref.num, ref.gen, offset, gTrue); obj.free(); diff --git a/poppler/XRef.cc b/poppler/XRef.cc index 7ca205e..acbc16a 100644 --- a/poppler/XRef.cc +++ b/poppler/XRef.cc @@ -276,6 +276,11 @@ XRef::XRef() { XRef::XRef(Object *trailerDictA) { init(); + + encrypted = gFalse; + permFlags = defPermFlags; + ownerPasswordOk = gFalse; + if (trailerDictA->isDict()) trailerDict.initDict(trailerDictA->getDict()); } @@ -1582,4 +1587,14 @@ void XRef::scanSpecialFlags() { obj.free(); } +void XRef::markUnencrypted() { + // Mark objects referred from the Encrypt dict as Unencrypted + Object obj; + trailerDict.dictLookupNF("Encrypt", &obj); + if (obj.isRef()) { + XRefEntry *e = getEntry(obj.getRefNum()); + e->setFlag(XRefEntry::Unencrypted, gTrue); + } + obj.free(); +} diff --git a/poppler/XRef.h b/poppler/XRef.h index 310572f..2defc6c 100644 --- a/poppler/XRef.h +++ b/poppler/XRef.h @@ -113,6 +113,8 @@ public: Guchar *fileKeyA, int keyLengthA, int encVersionA, int encRevisionA, CryptAlgorithm encAlgorithmA); + // Mark Encrypt entry as Unencrypted + void markUnencrypted(); void getEncryptionParameters(Guchar **fileKeyA, CryptAlgorithm *encAlgorithmA, int *keyLengthA); diff --git a/utils/pdfseparate.cc b/utils/pdfseparate.cc index 25fac5a..35ae020 100644 --- a/utils/pdfseparate.cc +++ b/utils/pdfseparate.cc @@ -52,10 +52,6 @@ bool extractPages (const char *srcFileName, const char *destFileName) { error(errSyntaxError, -1, "Could not extract page(s) from damaged file ('{0:s}')", srcFileName); return false; } - if (doc->isEncrypted()) { - error(errSyntaxError, -1, "Could not extract page(s) from encrypted file ('{0:s}')", srcFileName); - return false; - } if (firstPage == 0 && lastPage == 0) { firstPage = 1; commit 9b613dcf3c77bc2801d1125dc9bbc5a4dd04e16b Author: Albert Astals Cid <[email protected]> Date: Mon Sep 17 23:12:43 2012 +0200 Compile diff --git a/goo/TiffWriter.cc b/goo/TiffWriter.cc index d00f6c4..9c134f9 100644 --- a/goo/TiffWriter.cc +++ b/goo/TiffWriter.cc @@ -5,6 +5,7 @@ // This file is licensed under the GPLv2 or later // // Copyright (C) 2010, 2012 William Bader <[email protected]> +// Copyright (C) 2012 Albert Astals Cid <[email protected]> // //======================================================================== @@ -126,11 +127,13 @@ bool TiffWriter::init(FILE *openedFile, int width, int height, int hDPI, int vDP photometric = PHOTOMETRIC_RGB; break; +#if SPLASH_CMYK case splashModeCMYK8: case splashModeDeviceN8: samplesperpixel = 4; photometric = PHOTOMETRIC_SEPARATED; break; +#endif default: fprintf(stderr, "TiffWriter: Mode %d not supported\n", splashMode); @@ -165,10 +168,12 @@ bool TiffWriter::init(FILE *openedFile, int width, int height, int hDPI, int vDP TIFFSetField(f, TIFFTAG_YRESOLUTION, (double) vDPI); TIFFSetField(f, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); +#if SPLASH_CMYK if (splashMode == splashModeCMYK8 || splashMode == splashModeDeviceN8) { TIFFSetField(f, TIFFTAG_INKSET, INKSET_CMYK); TIFFSetField(f, TIFFTAG_NUMBEROFINKS, 4); } +#endif return true; } _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
