[poppler] 2 commits - goo/TiffWriter.cc poppler/PDFDoc.cc poppler/XRef.cc poppler/XRef.h utils/pdfseparate.cc

Albert Astals Cid aacid at kemper.freedesktop.org
Mon Sep 17 14:14:21 PDT 2012


 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 <Thomas.Freitag at alfa.de>
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 <aacid at kde.org>
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 <williambader at hotmail.com>
+// Copyright (C) 2012 Albert Astals Cid <aacid at kde.org>
 //
 //========================================================================
 
@@ -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;
 }


More information about the poppler mailing list