interactive/javascript
Count javascript occurrences in the document.
Download Java Code Show Output Show Input (PDFlib-purchase-order.pdf)
/*
* Count Javascript occurrences in document.
*
* Required software: pCOS interface 8 (PDFlib+PDI/PPS 9, TET 4.1, PLOP 5.0)
* Required data: PDF document
*/
package com.pdflib.cookbook.pcos.interactive;
import com.pdflib.IpCOS;
import com.pdflib.cookbook.pcos.pcos_cookbook_example;
public class javascript extends pcos_cookbook_example {
/* This is where the data files are. Adjust as necessary. */
private final static String SEARCH_PATH = "../input";
private interface script_info_printer {
/**
* Prints information about a JavaScript found in an action dictionary.
*
* @param scriptnr
* number of the script
* @param length
* length of script in bytes
*/
void print_info(int scriptnr, int length);
}
public void example_code(IpCOS p, int doc) throws Exception {
System.out.println("File name: " + p.pcos_get_string(doc, "filename"));
/* Document-level JavaScript */
int docscripts = get_documentscripts(p, doc);
/* Open action JavaScript */
int openscripts = get_openscripts(p, doc);
/* Page-level JavaScript */
int pagescripts = get_pagescripts(p, doc);
/* Annotation-level JavaScript */
int annotscripts = get_annotscripts(p, doc);
/* Field-level JavaScript */
int fieldscripts = get_fieldscripts(p, doc);
/* Bookmark-level JavaScript */
int bookmarkscripts = get_bookmarkscripts(p, doc);
System.out.println();
System.out.println(openscripts + " JavaScript(s) for open action");
System.out.println(docscripts + " JavaScript(s) on document level");
System.out.println(pagescripts + " JavaScript(s) on page level");
System.out.println(annotscripts + " JavaScript(s) on annotation level");
System.out.println(fieldscripts + " JavaScript(s) on field level");
System.out
.println(bookmarkscripts + " JavaScript(s) on bookmark level");
}
private class bookmark_info_printer implements script_info_printer {
private String title;
bookmark_info_printer(String title) {
this.title = title;
}
public void print_info(int scriptnr, int length) {
System.out.println("Bookmark '" + title + "', script number "
+ (scriptnr + 1) + ", length=" + length);
}
}
private int get_bookmarkscripts(IpCOS p, int doc) throws Exception {
int bookmarkscripts = 0;
int bookmarkcount = (int) p.pcos_get_number(doc, "length:bookmarks");
for (int bookmark = 0; bookmark < bookmarkcount; bookmark++) {
int objid;
String base = "bookmarks[" + bookmark + "]/A";
objid = (int) p.pcos_get_number(doc, "pcosid:" + base);
String bookmark_name = p.pcos_get_string(doc, "bookmarks["
+ bookmark + "]/Title");
script_info_printer info_printer = new bookmark_info_printer(
bookmark_name);
bookmarkscripts += walk_action_dictionary(p, doc, objid, 0,
info_printer);
}
return bookmarkscripts;
}
private class field_trigger_info_printer implements script_info_printer {
private String trigger;
private String fullname;
field_trigger_info_printer(String trigger, String fullname) {
this.trigger = trigger;
this.fullname = fullname;
}
public void print_info(int scriptnr, int length) {
System.out.println("Form field '" + fullname + "', " + "trigger '"
+ trigger + "', script number " + (scriptnr + 1) + ", length="
+ length);
}
}
private int get_fieldscripts(IpCOS p, int doc) throws Exception {
int fieldcount = (int) p.pcos_get_number(doc, "length:fields");
int fieldscripts = 0;
for (int field = 0; field < fieldcount; field++) {
int actioncount = (int) p.pcos_get_number(doc, "length:fields["
+ field + "]/AA");
for (int action = 0; action < actioncount; action++) {
String base = "fields[" + field + "]/AA[" + action + "]";
int objid = (int) p.pcos_get_number(doc, "pcosid:" + base);
String trigger = p.pcos_get_string(doc, base + ".key");
String form_field = p.pcos_get_string(doc, "fields[" + field
+ "]/fullname");
script_info_printer info_printer = new field_trigger_info_printer(
trigger, form_field);
fieldscripts += walk_action_dictionary(p, doc, objid, 0,
info_printer);
}
}
return fieldscripts;
}
private class annot_activation_info_printer implements script_info_printer {
private String subtype;
private int pagenr;
annot_activation_info_printer(String subtype, int pagenr) {
this.subtype = subtype;
this.pagenr = pagenr;
}
public void print_info(int scriptnr, int length) {
System.out.print("Page " + (pagenr + 1) + ", " + subtype
+ " annotation, script number " + (scriptnr + 1) + ", ");
System.out.println("activation script, length=" + length);
}
}
private class annot_trigger_info_printer implements script_info_printer {
private String subtype;
private String trigger;
private int pagenr;
annot_trigger_info_printer(String subtype, String trigger, int pagenr) {
this.subtype = subtype;
this.trigger = trigger;
this.pagenr = pagenr;
}
public void print_info(int scriptnr, int length) {
System.out.print("Page " + (pagenr + 1) + ", " + subtype
+ " annotation, script number " + scriptnr + ", ");
System.out.println("trigger '" + trigger + "', length=" + length);
}
}
private int get_annotscripts(IpCOS p, int doc) throws Exception {
int annotscripts = 0;
int pagecount = (int) p.pcos_get_number(doc, "length:pages");
for (int page = 0; page < pagecount; page++) {
int annotcount = (int) p.pcos_get_number(doc, "length:pages["
+ page + "]/annots");
for (int ann = 0; ann < annotcount; ann++) {
/* Avoid double-counting of form field Widgets */
String subtype = p.pcos_get_string(doc, "pages[" + page
+ "]/annots[" + ann + "]/Subtype");
if ("Widget".equals(subtype))
continue;
/* old-style A entry with a single action */
String base = "pages[" + page + "]/annots[" + ann + "]/A";
int objid = (int) p.pcos_get_number(doc, "pcosid:" + base);
script_info_printer info_printer = new annot_activation_info_printer(
subtype, page);
annotscripts += walk_action_dictionary(p, doc, objid, 0,
info_printer);
/* newer AA entry with multiple actions */
int actioncount = (int) p.pcos_get_number(doc, "length:pages["
+ page + "]/annots[" + ann + "]/AA");
for (int action = 0; action < actioncount; action++) {
base = "pages[" + page + "]/annots[" + ann + "]/AA["
+ action + "]";
objid = (int) p.pcos_get_number(doc, "pcosid:" + base);
String trigger = p.pcos_get_string(doc, base + ".key");
info_printer = new annot_trigger_info_printer(subtype,
trigger, page);
annotscripts += walk_action_dictionary(p, doc, objid, 0,
info_printer);
}
}
}
return annotscripts;
}
private class open_action_info_printer implements script_info_printer {
public void print_info(int scriptnr, int length) {
System.out.println("Open action script number " + (scriptnr + 1)
+ ", length=" + length);
}
}
private int get_openscripts(IpCOS p, int doc) throws Exception {
int openscripts = 0;
String base = "/Root/OpenAction";
/*
* The "OpenAction" entry can be a "destination" or an "action
* dictionary". Only examine the latter case for JavaScript occurences.
*/
String type = p.pcos_get_string(doc, "type:" + base);
if (type.equals("dict")) {
int objid = (int) p.pcos_get_number(doc, "pcosid:" + base);
script_info_printer info_printer = new open_action_info_printer();
openscripts = walk_action_dictionary(p, doc, objid, 0, info_printer);
}
return openscripts;
}
private class document_info_printer implements script_info_printer {
private String scriptname;
document_info_printer(String scriptname) {
this.scriptname = scriptname;
}
public void print_info(int scriptnr, int length) {
System.out.println("Document-level script '" + scriptname
+ "', length=" + length);
}
}
private class document_action_info_printer implements script_info_printer {
private String trigger;
document_action_info_printer(String trigger) {
this.trigger = trigger;
}
public void print_info(int scriptnr, int length) {
System.out.println("Document-level script, trigger '" + trigger
+ "', number " + (scriptnr + 1) + ", length=" + length);
}
}
private int get_documentscripts(IpCOS p, int doc) throws Exception {
int docscripts = 0;
int scriptcount = (int) p.pcos_get_number(doc,
"length:names/JavaScript");
for (int script = 0; script < scriptcount; script++) {
String base = "names/JavaScript[" + script + "]";
int objid = (int) p.pcos_get_number(doc, "pcosid:" + base);
String script_name = p.pcos_get_string(doc, base + ".key");
script_info_printer info_printer = new document_info_printer(
script_name);
if (check_for_script(p, doc, objid, docscripts, info_printer)) {
docscripts++;
}
}
/* Additional document-level JavaScript */
int actioncount = (int) p.pcos_get_number(doc, "length:/Root/AA");
for (int action = 0; action < actioncount; action++) {
String base = "/Root/AA[" + action + "]";
int objid = (int) p.pcos_get_number(doc, "pcosid:" + base);
String trigger = p.pcos_get_string(doc, base + ".key");
script_info_printer info_printer = new document_action_info_printer(
trigger);
docscripts += walk_action_dictionary(p, doc, objid, 0, info_printer);
}
return docscripts;
}
private class page_info_printer implements script_info_printer {
private int pagenr;
private String trigger;
page_info_printer(int pagenr, String trigger) {
this.trigger = trigger;
this.pagenr = pagenr;
}
public void print_info(int scriptnr, int length) {
System.out.println("Page " + (pagenr + 1) + ", trigger '" + trigger
+ "', script number " + (scriptnr + 1) + ", length=" + length);
}
}
private int get_pagescripts(IpCOS p, int doc) throws Exception {
int pagecount = (int) p.pcos_get_number(doc, "length:pages");
int pagescripts = 0;
for (int page = 0; page < pagecount; page++) {
int actioncount = (int) p.pcos_get_number(doc, "length:pages["
+ page + "]/AA");
for (int action = 0; action < actioncount; action++) {
String base = "pages[" + page + "]/AA[" + action + "]";
int objid = (int) p.pcos_get_number(doc, "pcosid:" + base);
String trigger = p.pcos_get_string(doc, base + ".key");
script_info_printer info_printer = new page_info_printer(page,
trigger);
pagescripts += walk_action_dictionary(p, doc, objid, 0,
info_printer);
}
}
return pagescripts;
}
/**
* Traverses an action dictionary.
*
* An action dictionary can contain a tree of action definitions, and a
* subset of them can be JavaScript actions. This routine recursively
* traverses the action tree and counts the JavaScript occurrences.
*
* For the definition of an action dictionary, see for example "8.5.1 Action
* Dictionaries" in the PDF Reference version 1.7. The
*
* @param p
* IpCOS object
* @param doc
* document handle
* @param objid
* pCOS id of the action dictionary to traverse
* @param scriptnr
* counter for the JavaScript occurrences in the action
* dictionary tree
* @param info_printer
* used to print out the information about the action
*
* @return number of scripts found in the action dictionary tree
*
* @throws Exception
* an error was detected in the PDF structure
*/
private int walk_action_dictionary(IpCOS p, int doc, int objid,
int scriptnr, script_info_printer info_printer) throws Exception {
int scripts = 0;
while (objid != -1) {
if (check_for_script(p, doc, objid, scriptnr + scripts,
info_printer)) {
scripts += 1;
}
String type = p.pcos_get_string(doc, "type:objects[" + objid
+ "]/Next");
if (type.equals("dict")) {
objid = (int) p.pcos_get_number(doc, "pcosid:objects[" + objid
+ "]/Next");
}
else if (type.equals("array")) {
int length = (int) p.pcos_get_number(doc, "length:objects["
+ objid + "]/Next");
for (int child = 0; child < length; child += 1) {
objid = (int) p.pcos_get_number(doc, "pcosid:objects["
+ objid + "]/Next[" + child + "]");
scripts += walk_action_dictionary(p, doc, objid, scriptnr
+ scripts, info_printer);
}
objid = -1;
}
else {
objid = -1;
}
}
return scripts;
}
/**
* Checks whether the given action dictionary entry is a JavaScript action.
*
* @param p
* IpCOS object
* @param doc
* document handle
* @param objid
* pCOS id of the action dictionary entry
* @param scriptnr
* counter for the JavaScript occurrences in the action
* dictionary tree
* @param info_printer
* for printing the information about the action
*
* @return true if a script was found, false otherwise
* @throws Exception
*/
private boolean check_for_script(IpCOS p, int doc, int objid, int scriptnr,
script_info_printer info_printer) throws Exception {
boolean retval = false;
String action_dict_obj = "objects[" + objid + "]";
String objtype = p.pcos_get_string(doc, "type:" + action_dict_obj);
if (objtype.equals("dict")) {
/* The action type, not the type of PDF object */
String actiontype = p.pcos_get_string(doc, action_dict_obj + "/S");
if (actiontype.equals("JavaScript")) {
int len;
String js_path = action_dict_obj + "/JS";
objtype = p.pcos_get_string(doc, "type:" + js_path);
if (objtype.equals("string")) {
/* fetch string contents to determine length */
String js = p.pcos_get_string(doc, js_path);
len = js.length();
}
else if (objtype.equals("stream")) {
/* fetch uncompressed stream data to determine length */
byte[] js = p.pcos_get_stream(doc, "convert=unicode",
js_path);
len = js.length;
/* Unicode detection: test for BOM, determine proper length */
if (js[0] == 0xFF && js[1] == 0xFE) {
len = (len - 2) / 2;
}
}
else {
throw new Exception("Could not get JavaScript contents"
+ "for object with id " + objid);
}
/* call the method that prints action-specific information */
info_printer.print_info(scriptnr, len);
retval = true;
}
}
return retval;
}
public javascript(String[] argv, String readable_name, String search_path) {
super(argv, readable_name, search_path);
}
public static void main(String argv[]) {
javascript example = new javascript(argv, "JavaScript", SEARCH_PATH);
example.execute();
}
}