Hello again, Am 01.09.2015 um 00:16 schrieb Albert Astals Cid: > El Dissabte, 25 de juliol de 2015, a les 14:26:48, Adam Reichold va escriure: >> Hello, >> >> the attached patch adds an option to strip the encryption from a >> document by doing a complete rewrite but ignoring the original >> encryption parameters and removing the encryption entry form the trailer >> dictionary. It also exposes this via the two Qt frontends. >> >> This might be useful for a separate command-line utility but for now my >> primary use case is submitting a rewritten but unencrypted document to >> CUPS for printing instead of converting to PostScript. > > Pushed. >
I am very sorry, but during further testing, I noticed that the raw stream copying done in "PDFDoc::writeObject" breaks documents generated using this flag. It seems this yields the encrypted data being written instead of the decrypted data. The attached patch tries to solve this by passing the "stripEncryption" flag to the "writeObject" method to suppress the raw stream copying, which however yields a horribly large patch for what is effectively a single-line change due to the recursive calls to "writeObject" from various places. While this changes does yield correctly decrypted files which CUPS prints properly, it also "strips" various other stream filters like "Flate" yielding much larger documents. I think the better solution would be to reliably detect this situation within "writeObject" to suppress the raw stream copying on a case-by-case basis, but I have not yet managed to implement this. I would be grateful for any advice on how to do this. Best regards, Adam.
diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc
index 153dc75..06b0487 100644
--- a/poppler/PDFDoc.cc
+++ b/poppler/PDFDoc.cc
@@ -722,7 +722,7 @@ int PDFDoc::savePageAs(GooString *name, int pageNo)
if (j > 0) outStr->printf(" ");
Object value; catDict->getValNF(j, &value);
outStr->printf("/%s ", key);
- writeObject(&value, outStr, getXRef(), 0, NULL, cryptRC4, 0, 0, 0);
+ writeObject(&value, outStr, getXRef(), 0, NULL, cryptRC4, 0, gFalse, 0, 0);
value.free();
}
}
@@ -735,7 +735,7 @@ int PDFDoc::savePageAs(GooString *name, int pageNo)
outStr->printf("<< /Type /Pages /Kids [ %d 0 R ] /Count 1 ", rootNum + 2);
if (resourcesObj.isDict()) {
outStr->printf("/Resources ");
- writeObject(&resourcesObj, outStr, getXRef(), 0, NULL, cryptRC4, 0, 0, 0);
+ writeObject(&resourcesObj, outStr, getXRef(), 0, NULL, cryptRC4, 0, gFalse, 0, 0);
resourcesObj.free();
}
outStr->printf(">>\n");
@@ -752,7 +752,7 @@ int PDFDoc::savePageAs(GooString *name, int pageNo)
outStr->printf("/Parent %d 0 R", rootNum + 1);
} else {
outStr->printf("/%s ", key);
- writeObject(&value, outStr, getXRef(), 0, NULL, cryptRC4, 0, 0, 0);
+ writeObject(&value, outStr, getXRef(), 0, NULL, cryptRC4, 0, gFalse, 0, 0);
}
value.free();
}
@@ -887,7 +887,7 @@ void PDFDoc::saveIncrementalUpdate (OutStream* outStr)
Object obj1;
xref->fetch(ref.num, ref.gen, &obj1, 1);
Goffset offset = writeObjectHeader(&ref, outStr);
- writeObject(&obj1, outStr, fileKey, encAlgorithm, keyLength, ref.num, ref.gen);
+ writeObject(&obj1, outStr, fileKey, encAlgorithm, keyLength, gFalse, ref.num, ref.gen);
writeObjectFooter(outStr);
uxref->add(ref.num, ref.gen, offset, gTrue);
obj1.free();
@@ -970,9 +970,9 @@ void PDFDoc::saveCompleteRewrite (OutStream* outStr, GBool stripEncryption)
Goffset offset = writeObjectHeader(&ref, outStr);
// Write unencrypted objects in unencrypted form
if (xref->getEntry(i)->getFlag(XRefEntry::Unencrypted)) {
- writeObject(&obj1, outStr, NULL, cryptRC4, 0, 0, 0);
+ writeObject(&obj1, outStr, NULL, cryptRC4, 0, gFalse, 0, 0);
} else {
- writeObject(&obj1, outStr, fileKey, encAlgorithm, keyLength, ref.num, ref.gen);
+ writeObject(&obj1, outStr, fileKey, encAlgorithm, keyLength, stripEncryption, ref.num, ref.gen);
}
writeObjectFooter(outStr);
uxref->add(ref.num, ref.gen, offset, gTrue);
@@ -982,7 +982,7 @@ void PDFDoc::saveCompleteRewrite (OutStream* outStr, GBool stripEncryption)
ref.gen = 0; //compressed entries have gen == 0
xref->fetch(ref.num, ref.gen, &obj1, 1);
Goffset offset = writeObjectHeader(&ref, outStr);
- writeObject(&obj1, outStr, fileKey, encAlgorithm, keyLength, ref.num, ref.gen);
+ writeObject(&obj1, outStr, fileKey, encAlgorithm, keyLength, stripEncryption, ref.num, ref.gen);
writeObjectFooter(outStr);
uxref->add(ref.num, ref.gen, offset, gTrue);
obj1.free();
@@ -996,7 +996,7 @@ void PDFDoc::saveCompleteRewrite (OutStream* outStr, GBool stripEncryption)
}
void PDFDoc::writeDictionnary (Dict* dict, OutStream* outStr, XRef *xRef, Guint numOffset, Guchar *fileKey,
- CryptAlgorithm encAlgorithm, int keyLength, int objNum, int objGen)
+ CryptAlgorithm encAlgorithm, int keyLength, GBool stripEncryption, int objNum, int objGen)
{
Object obj1;
outStr->printf("<<");
@@ -1005,7 +1005,7 @@ void PDFDoc::writeDictionnary (Dict* dict, OutStream* outStr, XRef *xRef, Guint
GooString *keyNameToPrint = keyName.sanitizedName(gFalse /* non ps mode */);
outStr->printf("/%s ", keyNameToPrint->getCString());
delete keyNameToPrint;
- writeObject(dict->getValNF(i, &obj1), outStr, xRef, numOffset, fileKey, encAlgorithm, keyLength, objNum, objGen);
+ writeObject(dict->getValNF(i, &obj1), outStr, xRef, numOffset, fileKey, encAlgorithm, keyLength, stripEncryption, objNum, objGen);
obj1.free();
}
outStr->printf(">> ");
@@ -1115,7 +1115,7 @@ Goffset PDFDoc::writeObjectHeader (Ref *ref, OutStream* outStr)
}
void PDFDoc::writeObject (Object* obj, OutStream* outStr, XRef *xRef, Guint numOffset, Guchar *fileKey,
- CryptAlgorithm encAlgorithm, int keyLength, int objNum, int objGen)
+ CryptAlgorithm encAlgorithm, int keyLength, GBool stripEncryption, int objNum, int objGen)
{
Array *array;
Object obj1;
@@ -1156,20 +1156,20 @@ void PDFDoc::writeObject (Object* obj, OutStream* outStr, XRef *xRef, Guint numO
array = obj->getArray();
outStr->printf("[");
for (int i=0; i<array->getLength(); i++) {
- writeObject(array->getNF(i, &obj1), outStr, xRef, numOffset, fileKey, encAlgorithm, keyLength, objNum, objGen);
+ writeObject(array->getNF(i, &obj1), outStr, xRef, numOffset, fileKey, encAlgorithm, keyLength, stripEncryption, objNum, objGen);
obj1.free();
}
outStr->printf("] ");
break;
case objDict:
- writeDictionnary (obj->getDict(), outStr, xRef, numOffset, fileKey, encAlgorithm, keyLength, objNum, objGen);
+ writeDictionnary (obj->getDict(), outStr, xRef, numOffset, fileKey, encAlgorithm, keyLength, stripEncryption, objNum, objGen);
break;
case objStream:
{
//We can't modify stream with the current implementation (no write functions in Stream API)
// => the only type of streams which that have been modified are internal streams (=strWeird)
Stream *stream = obj->getStream();
- if (stream->getKind() == strWeird || stream->getKind() == strCrypt) {
+ if (stripEncryption || stream->getKind() == strWeird || stream->getKind() == strCrypt) {
//we write the stream unencoded => TODO: write stream encoder
// Encrypt stream
@@ -1225,7 +1225,7 @@ void PDFDoc::writeObject (Object* obj, OutStream* outStr, XRef *xRef, Guint numO
}
stream->getDict()->remove("DecodeParms");
- writeDictionnary (stream->getDict(),outStr, xRef, numOffset, fileKey, encAlgorithm, keyLength, objNum, objGen);
+ writeDictionnary (stream->getDict(),outStr, xRef, numOffset, fileKey, encAlgorithm, stripEncryption, keyLength, objNum, objGen);
writeStream (stream,outStr);
delete encStream;
obj1.free();
@@ -1243,7 +1243,7 @@ void PDFDoc::writeObject (Object* obj, OutStream* outStr, XRef *xRef, Guint numO
}
}
}
- writeDictionnary (stream->getDict(), outStr, xRef, numOffset, fileKey, encAlgorithm, keyLength, objNum, objGen);
+ writeDictionnary (stream->getDict(), outStr, xRef, numOffset, fileKey, encAlgorithm, stripEncryption, keyLength, objNum, objGen);
writeRawStream (stream, outStr);
}
break;
@@ -1378,7 +1378,7 @@ void PDFDoc::writeXRefTableTrailer(Dict *trailerDict, XRef *uxref, GBool writeAl
{
uxref->writeTableToFile( outStr, writeAllEntries );
outStr->printf( "trailer\r\n");
- writeDictionnary(trailerDict, outStr, xRef, 0, NULL, cryptRC4, 0, 0, 0);
+ writeDictionnary(trailerDict, outStr, xRef, 0, NULL, cryptRC4, 0, gFalse, 0, 0);
outStr->printf( "\r\nstartxref\r\n");
outStr->printf( "%lli\r\n", uxrefOffset);
outStr->printf( "%%%%EOF\r\n");
@@ -1396,7 +1396,7 @@ void PDFDoc::writeXRefStreamTrailer (Dict *trailerDict, XRef *uxref, Ref *uxrefS
MemStream *mStream = new MemStream( stmData.getCString(), 0,
stmData.getLength(), obj1.initDict(trailerDict) );
writeObjectHeader(uxrefStreamRef, outStr);
- writeObject(obj1.initStream(mStream), outStr, xRef, 0, NULL, cryptRC4, 0, 0, 0);
+ writeObject(obj1.initStream(mStream), outStr, xRef, 0, NULL, cryptRC4, 0, gFalse, 0, 0);
writeObjectFooter(outStr);
obj1.free();
@@ -1756,11 +1756,11 @@ Guint PDFDoc::writePageObjects(OutStream *outStr, XRef *xRef, Guint numOffset, G
getXRef()->fetch(ref.num - numOffset, ref.gen, &obj);
Goffset offset = writeObjectHeader(&ref, outStr);
if (combine) {
- writeObject(&obj, outStr, getXRef(), numOffset, NULL, cryptRC4, 0, 0, 0);
+ writeObject(&obj, outStr, getXRef(), numOffset, NULL, cryptRC4, 0, gFalse, 0, 0);
} else if (xRef->getEntry(n)->getFlag(XRefEntry::Unencrypted)) {
- writeObject(&obj, outStr, NULL, cryptRC4, 0, 0, 0);
+ writeObject(&obj, outStr, NULL, cryptRC4, 0, gFalse, 0, 0);
} else {
- writeObject(&obj, outStr, fileKey, encAlgorithm, keyLength, ref.num, ref.gen);
+ writeObject(&obj, outStr, fileKey, encAlgorithm, keyLength, gFalse, ref.num, ref.gen);
}
writeObjectFooter(outStr);
xRef->add(ref.num, ref.gen, offset, gTrue);
diff --git a/poppler/PDFDoc.h b/poppler/PDFDoc.h
index d4a8b5e..b791636 100644
--- a/poppler/PDFDoc.h
+++ b/poppler/PDFDoc.h
@@ -255,7 +255,7 @@ public:
// write all objects used by pageDict to outStr
Guint writePageObjects(OutStream *outStr, XRef *xRef, Guint numOffset, GBool combine = gFalse);
static void writeObject (Object *obj, OutStream* outStr, XRef *xref, Guint numOffset, Guchar *fileKey,
- CryptAlgorithm encAlgorithm, int keyLength, int objNum, int objGen);
+ CryptAlgorithm encAlgorithm, int keyLength, GBool stripEncryption, int objNum, int objGen);
static void writeHeader(OutStream *outStr, int major, int minor);
// Ownership goes to the caller
@@ -271,18 +271,18 @@ private:
void markDictionnary (Dict* dict, XRef *xRef, XRef *countRef, Guint numOffset, int oldRefNum, int newRefNum);
void markObject (Object *obj, XRef *xRef, XRef *countRef, Guint numOffset, int oldRefNum, int newRefNum);
static void writeDictionnary (Dict* dict, OutStream* outStr, XRef *xRef, Guint numOffset, Guchar *fileKey,
- CryptAlgorithm encAlgorithm, int keyLength, int objNum, int objGen);
+ CryptAlgorithm encAlgorithm, int keyLength, GBool stripEncryption, int objNum, int objGen);
// Write object header to current file stream and return its offset
static Goffset writeObjectHeader (Ref *ref, OutStream* outStr);
static void writeObjectFooter (OutStream* outStr);
void writeObject (Object *obj, OutStream* outStr, Guchar *fileKey, CryptAlgorithm encAlgorithm,
- int keyLength, int objNum, int objGen)
- { writeObject(obj, outStr, getXRef(), 0, fileKey, encAlgorithm, keyLength, objNum, objGen); }
+ int keyLength, GBool stripEncryption, int objNum, int objGen)
+ { writeObject(obj, outStr, getXRef(), 0, fileKey, encAlgorithm, keyLength, stripEncryption, objNum, objGen); }
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); }
+ int keyLength, GBool stripEncryption, int objNum, int objGen)
+ { writeDictionnary(dict, outStr, getXRef(), 0, fileKey, encAlgorithm, keyLength, stripEncryption, objNum, objGen); }
static void writeStream (Stream* str, OutStream* outStr);
static void writeRawStream (Stream* str, OutStream* outStr);
void writeXRefTableTrailer (Goffset uxrefOffset, XRef *uxref, GBool writeAllEntries,
diff --git a/utils/pdfunite.cc b/utils/pdfunite.cc
index 9aa80be..c8ffa52 100644
--- a/utils/pdfunite.cc
+++ b/utils/pdfunite.cc
@@ -389,7 +389,7 @@ int main (int argc, char *argv[])
Object intent;
intents.arrayGet(j, &intent, 0);
if (intent.isDict()) {
- PDFDoc::writeObject(&intent, outStr, yRef, 0, NULL, cryptRC4, 0, 0, 0);
+ PDFDoc::writeObject(&intent, outStr, yRef, 0, NULL, cryptRC4, 0, gFalse, 0, 0);
}
intent.free();
}
@@ -399,19 +399,19 @@ int main (int argc, char *argv[])
// insert AcroForm
if (!afObj.isNull()) {
outStr->printf(" /AcroForm ");
- PDFDoc::writeObject(&afObj, outStr, yRef, 0, NULL, cryptRC4, 0, 0, 0);
+ PDFDoc::writeObject(&afObj, outStr, yRef, 0, NULL, cryptRC4, 0, gFalse, 0, 0);
afObj.free();
}
// insert OCProperties
if (!ocObj.isNull() && ocObj.isDict()) {
outStr->printf(" /OCProperties ");
- PDFDoc::writeObject(&ocObj, outStr, yRef, 0, NULL, cryptRC4, 0, 0, 0);
+ PDFDoc::writeObject(&ocObj, outStr, yRef, 0, NULL, cryptRC4, 0, gFalse, 0, 0);
ocObj.free();
}
// insert Names
if (!names.isNull() && names.isDict()) {
outStr->printf(" /Names ");
- PDFDoc::writeObject(&names, outStr, yRef, 0, NULL, cryptRC4, 0, 0, 0);
+ PDFDoc::writeObject(&names, outStr, yRef, 0, NULL, cryptRC4, 0, gFalse, 0, 0);
names.free();
}
outStr->printf(">>\nendobj\n");
@@ -440,7 +440,7 @@ int main (int argc, char *argv[])
outStr->printf("/Parent %d 0 R", rootNum + 1);
} else {
outStr->printf("/%s ", key);
- PDFDoc::writeObject(&value, outStr, yRef, offsets[i], NULL, cryptRC4, 0, 0, 0);
+ PDFDoc::writeObject(&value, outStr, yRef, offsets[i], NULL, cryptRC4, 0, gFalse, 0, 0);
}
value.free();
}
signature.asc
Description: OpenPGP digital signature
_______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
