Reader Enabled Documents Things to know about handling of rights enabled documents

Introduction

Normally PDF forms are not saveable in the free Adobe Reader (before version X/10). But Adobe offers different services which enable hidden features in Adobe Reader by passing special digital signatures to a document, such as Adobe Acrobat or the LiveCycle Server.

Generally the SetaPDF-FormFiller component is able to handle such rights enabled documents, but there are things to take care about. 

Things You Shoud Take Care About

The SetaPDF-FormFiller component is able to handle rights enabled documents if you take care about the following facts:

  • You should never touch any metadata entry through the documents info object or make any other change to any PDF object at a lower level.
  • Do not pass false to the save() method (default behavior) to force an incremental update.
  • Unicode support is not possible without preparing the original document before the rights are granted. Never make use of setNeedAppearances() on the FormFiller instance. It will destroy the signature and will make the reader enabled rights invalid. Anyhow, it is also possible to use an external font file if characters are missing.

How to Prepare a Document for Unicode Usage

An easy way to support unicode values is simply done by delegating the rendering process of form fields to the reader application. This is done by setting a flag via the setNeedAppearances() method of the  FormFiller instance. If the component sets this flag in a rights enabled document, the digital signature will get invalid, the document will lose the rights and the client will receive an annoying error message.

If we would prepare a document with this special flag before attaching the rights, Acrobat, for example, will remove this flag automatically before enabling the rights...

Finally the only solution to simulate the needed behavior is a simple JavaScript which has to be included into the "Document JavaScripts"-part of the document before enabling the reader rights. It will force the fields to be re-rendered by swapping a simple property back and forth:

var isDirty = this.dirty;
var nFields = this.numFields;
var t = app.thermometer;
t.duration = nFields;
t.begin();
for (var i = 0; i < nFields; i++) {
    var f = this.getField(this.getNthFieldName(i));
    try {
        var v = f.value;
        if (v == '')
            continue;
        f.multiline = !f.multiline;
        f.multiline = !f.multiline;
        f.value = v;
    } catch(e) {}
    t.value = i;
}
this.dirty = isDirty;
t.end();