Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disallow editing but allow page extraction in Java iText / PDF

I'm using iText to generate PDF files. I want to disallow editing of the PDF, but allow the reader to extract pages. Here's my code to set encryption:

writer.setEncryption(null, null, 0xffffffff, PdfWriter.STANDARD_ENCRYPTION_128);

The third parameter specifies permissions. I'm using 0xffffffff instead of the individual iText flags ALLOW_PRINTING etc. This will ask iText to enable everything. But this is what I get in the PDF file:

enter image description here

I should think I should be allowed to enable extraction but disable editing, but am not certain. Here are the permissions bits per Adobe: enter image description hereenter image description here

(From here, but be warned it's 30 meg)

So turn off bits 6 and 11 but leave on the others (especially bits 5 and 10), and that would turn off editing but allow extraction. In any case, by specifying 0xffffffff I would think that everything would be allowed; but instead everything except extraction is allowed.

I've skimmed the iText source code for setting permissions and don't see anything that would cause this. Here is the relevant code from PdfEncryption.setupAllKeys:

permissions |= (revision == STANDARD_ENCRYPTION_128 || revision == AES_128 || revision == AES_256) ? 0xfffff0c0
        : 0xffffffc0;
permissions &= 0xfffffffc;

The first line is doing an OR and so wouldn't remove any permissions; the second line is setting the two right-most bites to 0, per the PDF specification.

I'm wondering if it's an iText thing, a PDF thing or if I'm doing something else wrong.

Thanks

like image 551
Bumptious Q Bangwhistle Avatar asked Mar 04 '14 17:03

Bumptious Q Bangwhistle


1 Answers

A similar issue already has been raised here.

Using encryption actually is counter-productive as it can only be used to remove permissions, not to add them.

According to this, it might be helpful to completely unlock the PDF first:

PdfReader reader = new PdfReader(file.toURI().toURL());
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(
    file.getAbsolutePath().replace(".pdf", "_UNLOCKED.pdf")));
stamper.close();
reader.close();

Afterwards you can grab the output and start from scratch (mess around with the permission bits). Hope this helps.

EDIT: If you don't have access to the password, the iText sources can be modified. Simply comment out if (!reader.isOpenedWithFullPermissions()) throw ... (line 121 and 122 in version 5.5.0) in com.itextpdf.text.pdf.PdfStamperImp.

like image 128
beatngu13 Avatar answered Oct 06 '22 19:10

beatngu13