PdfScriptRunner

class PdfScriptRunner(document: PdfDocument, val formState: PdfFormState = PdfFormState(document), val policy: PdfScriptPolicy = PdfScriptPolicy(), onAlert: (PdfScriptAlert) -> Int = { 1 }, onConsole: (String) -> Unit = {}, onRequest: (PdfScriptRequest) -> Unit = {}, onResponse: (PdfScriptPrompt) -> String? = { null }, clock: () -> Long? = null, engine: KiteScriptEngine? = null) : PdfScriptHandler, AutoCloseable

Runs the JavaScript a PDF carries: its document scripts, the actions of its pages and buttons, and the four scripts a form field runs while it is filled.

Scripts see the objects Acrobat defines and Chrome's PDF engine implements: the document's own members as globals, getField, event, app, util, color, console, and the AF helper library every form tool calls. A script that works in Chrome's viewer is meant to work here.

val state = PdfFormState(doc)
PdfScriptRunner(doc, state, onAlert = { alert -> showDialog(alert.message); 1 }).use { runner ->
runner.runDocumentOpen() // document scripts, then the open action
runner.setFieldValue("price", "12") // keystroke, validate, calculate, format
state.value("total") // what the form's own script worked out
}

Nothing here touches the file. Values land in formState, which a viewer draws and the editor saves. One runner belongs to one document and to one thread, because the engine does.

Scripts are untrusted input, so policy decides whether they run at all and how long they may take, and anything that reaches outside the document arrives at onRequest for the host to allow or refuse.

Constructors

Link copied to clipboard
constructor(document: PdfDocument, formState: PdfFormState = PdfFormState(document), policy: PdfScriptPolicy = PdfScriptPolicy(), onAlert: (PdfScriptAlert) -> Int = { 1 }, onConsole: (String) -> Unit = {}, onRequest: (PdfScriptRequest) -> Unit = {}, onResponse: (PdfScriptPrompt) -> String? = { null }, clock: () -> Long? = null, engine: KiteScriptEngine? = null)

Types

Link copied to clipboard

What a keystroke script decided: whether the change is allowed, and what the field would hold if it is.

Properties

Link copied to clipboard

What the engine did with each "use asm" function in the document, one line each. Empty until the first script runs, and for an engine that does not compile such a function.

Link copied to clipboard

The page the reader is on, which this.pageNum reports to scripts.

Link copied to clipboard

Every script that failed since the runner opened, newest last.

Link copied to clipboard

The name a script sees as this.documentFileName.

Link copied to clipboard
open override val formState: PdfFormState

Where field values live while the reader has the file open.

Link copied to clipboard
open override val hasTimers: Boolean

True when a script is waiting on a timer, so a viewer knows to keep pumping.

Link copied to clipboard

What the document's scripts are allowed to do.

Functions

Link copied to clipboard
open override fun blur(fieldName: String)

Runs a widget's blur script, which a viewer fires when the field loses the caret.

Link copied to clipboard
open override fun close()
Link copied to clipboard
open override fun commit(fieldName: String, value: String): Boolean
Link copied to clipboard
open override fun documentOpened()

Runs the document's own scripts and then its open action, which is what a viewer does when the file opens (ISO 32000-1 §7.7.4 and §12.6.4.16). Returns the scripts that failed.

Link copied to clipboard
open override fun focus(fieldName: String)

Runs a widget's focus script.

Link copied to clipboard
fun formattedValue(fieldName: String): String

The text a field shows, after its format script has had it. The stored value does not change: a formatted total still calculates as a number.

Link copied to clipboard
open override fun keystroke(fieldName: String, change: String, selectionStart: Int, selectionEnd: Int): String?

The viewer's keystroke: the value the field should show, or null when a script refused it.

fun keystroke(fieldName: String, change: String, selectionStart: Int = (formState.value(fieldName) ?: "").length, selectionEnd: Int = selectionStart, commit: Boolean = false): PdfScriptRunner.KeystrokeResult

Runs a field's keystroke script for one edit, without committing it (ISO 32000-1 §12.6.3). A viewer calls this for each character the reader types, so a script can refuse it.

Link copied to clipboard
open override fun mouseDown(fieldName: String)

Runs a widget's mouse down script, which is how an on-screen button reports a press.

Link copied to clipboard
open override fun mouseUp(fieldName: String)

Runs a widget's mouse up script, which is how an on-screen button reports a release.

Link copied to clipboard
open override fun pageClosed(pageIndex: Int)
Link copied to clipboard
open override fun pageOpened(pageIndex: Int)
Link copied to clipboard
open override fun pumpTimers(nowMillis: Long): Long?

Runs the timers a script set with app.setInterval or app.setTimeOut and that are due at nowMillis. Returns how long to wait before the next one, or null when none is waiting.

Link copied to clipboard

Runs one JavaScript action, such as a link's or a button's.

Link copied to clipboard
open override fun runAction(action: PdfAction.JavaScript)
Link copied to clipboard

Runs every calculate script, in the order of the form's /CO array (ISO 32000-1 §12.7.2). A form with no order runs them in the order its fields appear.

Link copied to clipboard
Link copied to clipboard

Runs every document-level script in the order of their names (ISO 32000-1 §7.7.4). A script that fails is recorded and the ones after it still run.

Link copied to clipboard

Runs the page's close script, its /AA /C entry.

Link copied to clipboard

Runs the page's open script, its /AA /O entry (ISO 32000-1 §12.6.3, Table 195).

Link copied to clipboard
fun setFieldValue(fieldName: String, value: String): Boolean

Commits a value to a field the way a viewer does when the reader leaves it: the keystroke script sees the whole value, then validate, then the value is stored, then every calculate script runs in the form's own order, then the format scripts decide what is shown (ISO 32000-1 §12.6.3 for the triggers and §12.7.2 for the calculation order).