Acrobat User Community

Dynamic stamp secrets using JavaScript and Acrobat XI

By Thom ParkerMay 30, 2013

So you’ve finally figured out how to create a custom dynamic stamp for Acrobat.  But after all that hard work, what seemed like days of slogging through molasses, it still doesn’t do what it’s supposed to and your boss is getting impatient.  There are three things yet to be done.  The stamp needs to display the file-name of the document on which it is being placed, it needs to ask the user for some state information (i.e., approved, rejected, and so on), and it needs to write this information and a date into the document metadata.  This is crazy! Documentation on dynamic stamps is already hard enough to come by.  But there’s nothing anywhere about how to do these tasks (There is now, see the link to www.pdfscripting.com at the bottom of the page).  Take heart! There is a solution. 

Building a dynamic stamp

Before getting into the advanced details, let’s review some dynamic stamp basics (full dynamic stamp tutorial).  A dynamic stamp is created by adding form fields to an existing PDF Stamp, in a Stamp File.  It doesn’t count if the fields are added to the original PDF that is turned into a stamp.  Those fields are flattened out when the new stamp is added to a Stamp File.  The fields have to be added after the custom stamp is created.

A Stamp File is a regular PDF in which Acrobat has added some special information. The stamps are the pages in the Stamp File. Acrobat creates a new Stamp File when you create a new Stamp Category. Let me repeat that in a different way. All the stamps in a Stamp Category are placed in the same Stamp File, Figure 1.

Figure 1 — Creating a Category creates a new Stamp File

The trick to creating a dynamic stamp is to first locate the Stamp File that contains your custom stamp. Fortunately, all the Stamp Files are contained within two folders, a "user" folder and an "app" folder. Acrobat keeps its own built-in stamps in the "app" folder.  Your custom stamp will be located in the "user" folder. You can find the locations of these folders by executing the following lines of code in the JavaScript Console:

    app.getPath ("app", "stamps");
    app.getPath ("user", "stamps");

The results are shown below in Figure 2.

Figure 2 — Locating the Acrobat Stamp Folders
Unfortunately, when Acrobat creates the Stamp File, it gives it a cryptic looking name.  You cannot know from the file name, which Stamp File contains your stamp. But remember, a Stamp File is a PDF, so you can open each one of the Stamp Files in the user stamp folder to find the stamp you want to make dynamic. Once you find the Stamp File, rename it so you'll know what it is the next time you need to make a dynamic stamp. Acrobat does not care about the name, you can make it anything you want.

To make the stamp dynamic you add form fields to it. At least one of the added form fields must have a calculation script.  Acrobat runs the stamp calculation script every time it accesses the Stamp File. This means the script is run when Acrobat first opens the Stamp File, when the stamp is displayed on the Stamp Menu, and when any stamp in the Stamp File is placed on a PDF. None of the other document or field scripts are useful. You must use the Field Calculation Script, and only the Field Calculation Script.

This calculation script runs in the context of the Stamp File, i.e., the this keyword is the Doc Object of the Stamp File.  To demonstrate, place the following line of code in the calculation script for a field on your dynamic stamp. 
      event.value = this.documentFileName;
When you place the stamp on a PDF, it will display the name of the Stamp File, not the name of the file on which the stamp is placed.

Limitations

There is only one serious limitation to a dynamic stamp script.  Stamp Files do not execute JavaScript like a normal PDF file.  For example, there are no document or page events.  Variables and functions cannot be defined in a document script.   The only scripts guaranteed to execute are the calculation scripts of the fields placed on the stamp.  Everything necessary to execute this script must be present in the script.

Another, less important limitation is that the event.rc value is meaningless in a dynamic stamp calculation script.   It doesn’t block the field from acquiring the assigned value as it would in a normal calculation script.

Privileges

Acrobat grants dynamic stamp scripts a small amount of privilege.  They are able to access the identity object, which is normally off limits to scripts in a PDF.  The identity object contains the same user information listed in the Identity panel in the Acrobat Preferences.  However, dynamic stamp scripts are not fully privileged, so they cannot use other secure Acrobat properties and functions, i.e., anything in the Acrobat JavaScript Reference marked with a red (S) in the Rights Bar is off limited, except for the Identity object.

Figure 3 — Identity Object Entry from the Acrobat JavaScript Reference

Dynamic scripts can call functions defined in a Folder level script, so if you need some privileged code for your stamp, you can always place it in an external script file. 

The secrets

Now, down to business.  In the introduction, our intrepid PDF developer was directed to accomplish three seemingly impossible dynamic stamp features.

  1. Display the name of the file (onto which the stamp is being placed) onto the stamp.
  2. Ask the user to choose some document state text to display on the stamp.
    (Approved, Rejected or In Process)
  3. Write the document state info and a date into the document metadata.

Features 1 and 3 require access to the document being stamped.  We can’t use the this keyword because the dynamic stamp script is in the context of the Stamp File and we can’t use the app.activeDocs property because a document has to be disclosed before it shows up on the list.  There are some other possible coding solutions, but they are all awkward and pose problems with version compatibility.
This issue seems impossible, but fortunately Acrobat JavaScript provides us with a solution. For dynamic stamp scripts, the event.source property is an object containing several useful parameters, one of which is the Doc Object for the PDF being stamped,  event.source.source. Use the following code to get the file name for the  PDF on which the stamp is being placed:

event.value = event.source.source.documentFileName;

To write a value into the document’s metadata, use this code

var cDate = util.printd("mm/dd/yyyy", new Date());
event.source.source.info.StampInfo = "Rejected:" + cDate;

That takes care of two issues, 1 and 3. For feature 2 we can use app.response() to ask the user for a simple string. But there is a problem. We want this popup to appear only when the user places the stamp on the PDF. But as discussed previously, the calculate script is called in several different situations. We can't have the app.response() dialog popping up at odd times. So, how does the stamp script know when our particular stamp is being placed on the document

Again, event.source comes to the rescue. In this case, we use the event.source.forReal and event.source.stampName properties. The forReal property is true when any stamp in the Stamp File is being placed on the document and false at all other times. This property narrows things down, but we need one more property to uniquely identify the situation when our particular stamp is being placed. The stampName property identifies the stamp in current use. Both of these properties must be used together to qualify stamp code that performs any kind of blocking operation, such as displaying a popup dialog.

The Stamp Name

So what is the name of our stamp? If you look back at Figure 1, you might think that the name you entered into the "Create Custom Stamp" dialog is the stamp name. But this would be incorrect. The name you gave the stamp is just a label. Acrobat gives the stamp a unique internal name you don't see. This name is a string of very cryptic looking letters and numbers and it is always prefixed with a "#" symbol.  This is the name you need for your stamp script. But how do you find it?
There are several ways to get the real name of your stamp, but here is the easiest.

  1. Place your stamp onto a PDF file. It doesn't matter which file, this is just a dummy placement so you can get some information. You can delete it later.
  2. Select the stamp with the cursor.
  3. Open the console window and run the following code (Figure 4)
this.selectedAnnots[0].AP

This code displays the internal name of the dynamic stamp in the JavaScript Console, as shown in Figure 4.

Figure 4 — Acquiring the real name of the stamp

You can now use this name to qualify any stamp code that needs to be protected from running at odd times by using the following "if" statement. Of course you'll need to change the stamp name to match your stamp.

if( event.source.forReal &&
   (event.source.stampName == "#yCY1HRSQtWDRvKLBcmfDcA""))
{
   event.value = app.response();
}

The sample file linked below also shows another way you can acquire the stamp name, by displaying it on the stamp using the stamp script.

Putting it all together

Let’s lay out the code our intrepid developer has created for his stamp.  The stamp needs two fields:  one on which to place PDF file name and one on which to place the user entered value.

Calculation (Dynamic) Script for Document Name Field

event.value = event.source.source.documentFileName;

Calculation (Dynamic) Script for User Data Field
(this is also the same script that will set metadata)

var cAsk = "Enter One of: Approved, Rejected, or In Process";
var cTitle = "Document State For Stamp";
	
if(event.source.forReal &&
   (event.source.stampName == "#UdzyXagRctZoS5p43TZ43C"))
{
   var cMsg = app.response(cAsk, cTitle);
   cMsg += " : " + util.printd("mm/dd/yyyy", new Date());
   event.value = cMsg;
   event.source.source.info.DocumentState = cMsg;
}

That’s all there is to it.  Here’s what the stamp and popup response box look like.

Figure 5 — User input response box and resulting stamp

Yet Another Stamp Secret

All code presented here is in the example Stamp File, StampSecrets_Sample.pdf, which will operate on Acrobat 7 or later. You heard that right. Stamps have not changed significantly in a very long time. The only reason the sample won't work in early versions is because of changes to the JavaScript model, not stamps. And to make things even better, Reader XI will apply dynamic stamps to any PDF document, without any special Reader Rights enabling. If you don't know about Reader Rights, then don't worry about it. The important bit is that you can use your dynamic Stamp Files with Adobe Reader XI to stamp any PDF file.

To use these stamps, place the sample file linked above into one of Acrobat’s stamp folders.  Then close and restart Acrobat/Reader. “Secrets Examples” should now be visible in your Stamps menu.
Good Stamping!

For complete information on using and creating Acrobat and PDF stamps in document workflows (for both managers and users), and  to learn all about stamp scripting from entry level to advanced automation, see The Stamp Book: