Skip to content

Commit

Permalink
JS -- Actions must be evaluated in global scope
Browse files Browse the repository at this point in the history
 * All the public properties of doc are injected into globalThis, in order to make them available through `this`
 * Put event in the global scope too.
  • Loading branch information
calixteman committed Dec 17, 2020
1 parent c366390 commit 167ff1a
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 53 deletions.
3 changes: 3 additions & 0 deletions src/pdf.sandbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class Sandbox {
}

create(data) {
if (TESTING) {
this._module.ccall("nukeSandbox", null, []);
}
const sandboxData = JSON.stringify(data);
const code = [
// Next line is replaced by code from initialization.js
Expand Down
25 changes: 11 additions & 14 deletions src/scripting_api/aform.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,7 @@ class AForm {
}
}

AFMergeChange(event) {
if (!event) {
event = this._document._event;
}
AFMergeChange(event = globalThis.event) {
if (event.willCommit) {
return event.value.toString();
}
Expand Down Expand Up @@ -128,7 +125,7 @@ class AForm {
strCurrency,
bCurrencyPrepend
) {
const event = this._document._event;
const event = globalThis.event;
if (!event.value) {
return;
}
Expand Down Expand Up @@ -193,7 +190,7 @@ class AForm {
strCurrency /* unused */,
bCurrencyPrepend /* unused */
) {
const event = this._document._event;
const event = globalThis.event;
let value = this.AFMergeChange(event);
if (!value) {
return;
Expand Down Expand Up @@ -236,7 +233,7 @@ class AForm {
throw new Error("Invalid nDec value in AFPercent_Format");
}

const event = this._document._event;
const event = globalThis.event;
if (nDec > 512) {
event.value = "%";
return;
Expand Down Expand Up @@ -268,7 +265,7 @@ class AForm {
}

AFDate_FormatEx(cFormat) {
const event = this._document._event;
const event = globalThis.event;
const value = event.value;
if (!value) {
return;
Expand All @@ -287,7 +284,7 @@ class AForm {
}

AFDate_KeystrokeEx(cFormat) {
const event = this._document._event;
const event = globalThis.event;
if (!event.willCommit) {
return;
}
Expand All @@ -310,7 +307,7 @@ class AForm {
}

AFRange_Validate(bGreaterThan, nGreaterThan, bLessThan, nLessThan) {
const event = this._document._event;
const event = globalThis.event;
if (!event.value) {
return;
}
Expand Down Expand Up @@ -397,7 +394,7 @@ class AForm {
throw new TypeError("Invalid function in AFSimple_Calculate");
}

const event = this._document._event;
const event = globalThis.event;
const values = [];
for (const cField of cFields) {
const field = this._document.getField(cField);
Expand All @@ -417,7 +414,7 @@ class AForm {
}

AFSpecial_Format(psf) {
const event = this._document._event;
const event = globalThis.event;
if (!event.value) {
return;
}
Expand Down Expand Up @@ -457,7 +454,7 @@ class AForm {
return;
}

const event = this._document._event;
const event = globalThis.event;
const value = this.AFMergeChange(event);
const checkers = new Map([
["9", char => char >= "0" && char <= "9"],
Expand Down Expand Up @@ -526,7 +523,7 @@ class AForm {
}

AFSpecial_Keystroke(psf) {
const event = this._document._event;
const event = globalThis.event;
if (!event.value) {
return;
}
Expand Down
114 changes: 103 additions & 11 deletions src/scripting_api/doc.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,21 @@ class Doc extends PDFObject {
constructor(data) {
super(data);

this.baseURL = data.baseURL || "";
this.calculate = true;
this.delay = false;
this.dirty = false;
this.disclosed = false;
this.media = undefined;
this.metadata = data.metadata;
this.noautocomplete = undefined;
this.nocache = undefined;
this.spellDictionaryOrder = [];
this.spellLanguageOrder = [];
// In a script doc === this.
// So adding a property to the doc means adding it to this
this._expandos = globalThis;

this._baseURL = data.baseURL || "";
this._calculate = true;
this._delay = false;
this._dirty = false;
this._disclosed = false;
this._media = undefined;
this._metadata = data.metadata;
this._noautocomplete = undefined;
this._nocache = undefined;
this._spellDictionaryOrder = [];
this._spellLanguageOrder = [];

this._printParams = null;
this._fields = new Map();
Expand Down Expand Up @@ -127,6 +131,14 @@ class Doc extends PDFObject {
throw new Error("doc.author is read-only");
}

get baseURL() {
return this._baseURL;
}

set baseURL(baseURL) {
this._baseURL = baseURL;
}

get bookmarkRoot() {
return undefined;
}
Expand All @@ -135,6 +147,14 @@ class Doc extends PDFObject {
throw new Error("doc.bookmarkRoot is read-only");
}

get calculate() {
return this._calculate;
}

set calculate(calculate) {
this._calculate = calculate;
}

get creator() {
return this._creator;
}
Expand All @@ -151,6 +171,30 @@ class Doc extends PDFObject {
throw new Error("doc.dataObjects is read-only");
}

get delay() {
return this._delay;
}

set delay(delay) {
this._delay = delay;
}

get dirty() {
return this._dirty;
}

set dirty(dirty) {
this._dirty = dirty;
}

get disclosed() {
return this._disclosed;
}

set disclosed(disclosed) {
this._disclosed = disclosed;
}

get docID() {
return this._docID;
}
Expand Down Expand Up @@ -278,6 +322,22 @@ class Doc extends PDFObject {
this._layout = value;
}

get media() {
return this._media;
}

set media(media) {
this._media = media;
}

get metadata() {
return this._metadata;
}

set metadata(metadata) {
this._metadata = metadata;
}

get modDate() {
return this._modDate;
}
Expand All @@ -302,6 +362,22 @@ class Doc extends PDFObject {
throw new Error("doc.mouseY is read-only");
}

get noautocomplete() {
return this._noautocomplete;
}

set noautocomplete(noautocomplete) {
this._noautocomplete = noautocomplete;
}

get nocache() {
return this._nocache;
}

set nocache(nocache) {
this._nocache = nocache;
}

get numFields() {
return this._numFields;
}
Expand Down Expand Up @@ -418,6 +494,22 @@ class Doc extends PDFObject {
throw new Error("doc.sounds is read-only");
}

get spellDictionaryOrder() {
return this._spellDictionaryOrder;
}

set spellDictionaryOrder(spellDictionaryOrder) {
this._spellDictionaryOrder = spellDictionaryOrder;
}

get spellLanguageOrder() {
return this._spellLanguageOrder;
}

set spellLanguageOrder(spellLanguageOrder) {
this._spellLanguageOrder = spellLanguageOrder;
}

get subject() {
return this._subject;
}
Expand Down
4 changes: 2 additions & 2 deletions src/scripting_api/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class EventDispatcher {

const name = baseEvent.name.replace(" ", "");
const source = this._objects[id];
const event = (this._document.obj._event = new Event(baseEvent));
globalThis.event = new Event(baseEvent);
let savedChange;

if (source.obj._isButton()) {
Expand Down Expand Up @@ -155,7 +155,7 @@ class EventDispatcher {
}
const first = this._calculationOrder[0];
const source = this._objects[first];
const event = (this._document.obj._event = new Event({}));
globalThis.event = new Event({});
this.runCalculate(source, event);
}

Expand Down
31 changes: 6 additions & 25 deletions src/scripting_api/field.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ class Field extends PDFObject {
this._fillColor = data.fillColor || ["T"];
this._strokeColor = data.strokeColor || ["G", 0];
this._textColor = data.textColor || ["G", 0];

this._globalEval = data.globalEval;
}

get fillColor() {
Expand Down Expand Up @@ -117,31 +119,14 @@ class Field extends PDFObject {
this._valueAsString = val ? val.toString() : "";
}

_getFunction(code, actionName) {
try {
// This eval is running in a sandbox so it's safe to use Function
// eslint-disable-next-line no-new-func
return Function("event", `with (this) {${code}}`).bind(this._document);
} catch (error) {
const value =
`"${error.toString()}" for action ` +
`"${actionName}" in object ${this._id}.`;
this._send({ command: "error", value });
}
return null;
}

setAction(cTrigger, cScript) {
if (typeof cTrigger !== "string" || typeof cScript !== "string") {
return;
}
if (!(cTrigger in this._actions)) {
this._actions[cTrigger] = [];
}
const fun = this._getFunction(cScript, cTrigger);
if (fun) {
this._actions[cTrigger].push(fun);
}
this._actions[cTrigger].push(cScript);
}

setFocus() {
Expand All @@ -152,12 +137,7 @@ class Field extends PDFObject {
const actionsMap = new Map();
if (actions) {
for (const [eventType, actionsForEvent] of Object.entries(actions)) {
const functions = actionsForEvent
.map(action => this._getFunction(action, eventType))
.filter(fun => !!fun);
if (functions.length > 0) {
actionsMap.set(eventType, functions);
}
actionsMap.set(eventType, actionsForEvent);
}
}
return actionsMap;
Expand All @@ -176,7 +156,8 @@ class Field extends PDFObject {
const actions = this._actions.get(eventName);
try {
for (const action of actions) {
action(event);
// Action evaluation must happen in the global scope
this._globalEval(action);
}
} catch (error) {
event.rc = false;
Expand Down
Loading

0 comments on commit 167ff1a

Please sign in to comment.