These forums are now Read Only. If you have an Acrobat question, ask questions and get help from one of our experts.

Trusted Javascript

csearl
Registered: Aug 10 2006
Posts: 28

I have written a couple of trusted "app-level" JavaScript functions, mostly to perform silent saves and reads from XFA type forms. The scripts do work as expected when associated with menu items or buttons from within standard Acrobat 8.
 
My trusted JavaScript functions use this technique:
 
myExportXFAData = app.trustPropagatorFunction(function(oDoc, sPath, bXDP, sPackets)
{
app.beginPriv(); // explicitly raise privilege
oDoc.exportXFAData(sPath, bXDP);
app.endPriv();
});
 
TrustedExportXFAData = app.trustedFunction(function(oDoc, sPath, bXDP, sPackets)
{
var bSuccess = false;
app.beginPriv();
try {
myExportXFAData(oDoc, sPath, bXDP, sPackets);
bSuccess = true;
}
catch(e){
app.alert(sPath + " NOT exported!\n" + e.message + "\n" + e.name);
}
app.endPriv();
return( bSuccess );
});
  
However, what I really need to do is perform those same functions but trigger them from my hosting VB application's menu items and toolbars.
 
When I try this:
 
Set AcroExchApp = CreateObject("AcroExch.App")
Set AcroExchAVDoc = CreateObject("AcroExch.AVDoc")
ok = AcroExchAVDoc.OpenInWindowEx(sFullPathName, Me.hWnd, CLng(AV_page_view), True, 0, CInt(PDUseBookmarks), CInt(AVZoomFitWidth), 0, 0, 0)
Set AcroPDDoc = AcroExchAVDoc.GetPDDoc
Set jso = AcroPDDoc.GetJSObject
 
If jso.dynamicxfaform Then
rc = jso.TrustedExportXFAData(AcroPDDoc, sFilePath, True, "datasets")
End If
 
I find that the trusted JavaScript does indeed execute, but it throws the exeception:
 
"Run-time error '1001':
NotAllowedError: Security settings prevent access to this property or method."
 
My objective is to save the XFA data to a known and safe path, so that it can be reloaded and displayed later (and saved to a database).
 
Any help on this would be greatly appreciated.

My Product Information:
Acrobat Pro 8, Windows
thomp
Expert
Registered: Feb 15 2006
Posts: 4411
All external scripts run in the context of the current document, such as a script injected into Acrobat from an IAC app.

There is really only one way to create a trusted function, i.e., in a Folder Level script. All other scripts are suspect and are therefore a security risk.

Thom Parker
The source for PDF Scripting Info
www.pdfscripting.com
Very Important - How to Debug Your Script

tarekahf
Registered: May 1 2008
Posts: 91
csearl,

I like your technique ... very cool !

I have nearly same requirements like yours.

I need to write VB.NET Program to do the following:

1. Enumerate through all the PDF Files in a given folder (based on Adobe LiveCycle 7.1 Form),

2.For Each PDF File:

2.1. Open the PDF and Extract the XML Data from the form, and save it into a sting variable,

2.2. Convert the XML String to .NET XML Document Object,

2.3. Extract the single fields and repeating group of fields and update the Database,

2.4. Generate Key Values.

2.5. Send email Notification to the sender of the form, to confirm receiving the form and start initial processing.
---

The problems I faced is that from VB using PDDoc.GetJSObject, you can only export the XML Data into a Text File (.xml) on the Local Drive. And, I could not find a way to use the other XFA based JavaScript Objects from the VB Hosting Program.

I will try your technique ...

Could you please tell me how did it go with you with regards to your requirement ?

I need your help.

Tarek.
thomp
Expert
Registered: Feb 15 2006
Posts: 4411
Rather than exporting the data from Acrobat directly, write the data out from your VB program. That way you can control how it's done.

You can write a folder level JavaScript function, just like csearl did, and access it from your VB script. Except, don't use a trusted fucntion. It's unnecessary for this and will may cause the same problem that he had. I've done this many times and it works really well.

The script can easily collect the XML data from a liveCycle document into a string that can be returned from the JS function to the VB app.

In the JS function use:

var strXML = xfa.data.saveXML();

This string can then be parsed by the regular .NET XML functions.

You can easily send and email from Acrobat with the "app.mailMsg()" function.

The rest of your items are .NET issues.

Thom Parker
The source for PDF Scripting Info
[url=http://www.pdfScripting.com]pdfscripting.com[/url]

The Acrobat JavaScript Reference, Use it Early and Often
[url=http://www.adobe.com/devnet/acrobat/]http://www.adobe.com/devnet/acrobat/[/url]

Thom Parker
The source for PDF Scripting Info
www.pdfscripting.com
Very Important - How to Debug Your Script

tarekahf
Registered: May 1 2008
Posts: 91
thomp,

Wonderful !

Simple and right to the point.

Just to make sure I understand how to implement this, I will create a Folder Level JavaScript, and create the required function that will return the XML Data.

But, where is this Folder Level JavaScript ?

Is it the one specified by the return of this function:

app.getPath("app", "javascript")

or

app.getPath("user", "javascript")


Also, I would like to share with you my feedback/understanding about using Folder Level JavaScript. Usually, they are used in case you need to execute a function which has security restrictions. As a mater of fact, this subject is not yet 100% clear to me.

I was reading in Adobe Acrobat 7.0 JavaScript API Reference, and I am really confused big time !!. Check this on page 679:
---
Privileged versus Non-privileged Context
In versions of Acrobat prior to 7.0, certain security restricted methods could only be executed in a privileged context1, typically, during a console, batch, menu or application initialization event. All other events (for example, page open and mouse up events) are considered non-privileged.

In Acrobat 7.0, the concept of a trusted function is introduced. Trusted functions allow privileged code—code that normally requires a privileged context to execute—to execute in non-privileged contexts. For details and examples, see app.trustedFunction().
---

If a function is security restricted, such as "Identity.loginName", then I can put it in a folder level javascript, and wrap it in another function, and it works great. No need to make it as a trusted function. In this case, no need to use "app.trustedFunction()".

As another alternative, I can create a trusted function as a wrapper for "Identity.loginName", to allow it to execute in a non-privileged context. This means that I have to use "app.trustedFunction()". Now, this function "app.trustedFunction()" is again security restricted, and we are back to square one !. This means that I cannot put it in a non-privileged context, so there is no escape from using a Folder Level JavaScript, and if I will put such security restricted functions in a Folder Level JavaScript, then why I have to make it trusted by wrapping it in with app.trustedFunction(). So this makes the use of "app.trustedFunction()" of no value what so ever.

The above seems very complicated, and seems there is a conflict, and I hope I was able to clarify it.

I have another comment about using Folder Level JavaScript.

I did not like the idea of Folder Level/Application Level JavaScript if I need to add functionality in PDF to be distributed to large number of users. I tried it once, and dropped this idea. First of all, there will be a huge maintenance overhead because I will always have to distribute a .js file, and there will be effort needed to deploy it in the proper place. Also, if the client/user of the PDF is a power user, then he can mess with the .js file !!!, and then I have to look for ways to protect it ... too much work and risk, does not worth the effort.

Due to the above drawbacks of using Folder Level JavaScript, it use will be limited for the developers and for a very small number of trusted users, and for a very dedicated functionality.

You comments and feedback will be greatly appreciated.

Tarek.
thomp
Expert
Registered: Feb 15 2006
Posts: 4411
Either folder level location will work.

The folder level script is used to create JavaScript functionality that is global to Acrobat. Whether that functionality is trusted or not is another issue. In your case, it does not need to be trusted, so forget about trustedFunctions for now.

All you need is a function that will return the XML data as a string. Once it's created from a folder level script, this function can be called from any JavaScript context anywhere in the Acrobat/PDF JavaScript environment, including from the JSO in your VB app.

You cannot easily get the XML data out of the LiveCycle form without the help of Acrobat JavaScript, and the folder level fucntion is the most reliable way to do this.

But I do have another suggestion. try executing this from the JSO in the VB app.

Jso.eval("xfa.data.saveXML()");

This statement, if it works, will return the XML string.

Cheers.
Thom Parker
The source for PDF Scripting Info
[url=http://www.pdfScripting.com]pdfscripting.com[/url]

The Acrobat JavaScript Reference, Use it Early and Often
[url=http://www.adobe.com/devnet/acrobat/]http://www.adobe.com/devnet/acrobat/[/url]

Thom Parker
The source for PDF Scripting Info
www.pdfscripting.com
Very Important - How to Debug Your Script

tarekahf
Registered: May 1 2008
Posts: 91
thomp, thank you again.

For the case of getting the XML Data from XFA model, I have no problem what so ever in using Folder Level JavaScript. This is because it is a dedicated functionality, and will be executed by one user, who is trusted.

---

Now, this totally different subject. Sorry to make this switch, and appreciate your patience.

I truly like to get your feedback and comments on the concerns I had earlier about using Trusted Functions and Folder Level JavaScript.

This subject is becoming a source of confusion for me since a very long time back.

In summary:

1. For Security Restricted fuctions to be executed in non-privileged context, must be put in folder level JavaScript.

2, You can make a security restricted function run in a non-privileged context, by wrapping it using using app.trustedFcuntion() to make trusted,

3. The function app.trustedFunction is security restricted, and hence must be put in a Folder Level JavaScript. So, there is no need to used in the first place.

4. Using Folder Level JavaScript to add custom functionality using JavaScript (security restricted or normal function), will create a big overhead for distributing the PDF to large number of users, and will cause some risk in messing with the JavaScript by power users. So the question, is there a method to reduce the overhead of deploying folder level JavaScript and protect it from being changed by the end users ?

Tarek.
thomp
Expert
Registered: Feb 15 2006
Posts: 4411
You are right that wrapping privileged functionality in a trusted function allows scripts in non-privileged areas to gain access to that functionality.

And also that a trusted function can only be created from a privileged context. Like a batch sequence, the console window, or a folder level script.

A folder level script is only privileged when it is executed at startup by Acrobat. The folder level script is never run after this. You use the folder level script do define variables and functions for later use. These variables and functions are held in memory as long as Acrobat is active. These variables and functions are not privileged. They were simply created by the folder level script when it ran, they are not the folder level script itself.

To illustrate this concept, create a folder level script with the following code:
function GetUserID_1(){return identity.name;} var GetUserID_2 = app.trustedFunction(function(){app.beginPriv();return identity.name;app.endPriv();});

Now open a pdf and add two buttons to it. Set each button to run one of these functions. Open the console window and see what happens when you press the buttons.

Thom Parker
The source for PDF Scripting Info
pdfscripting.com

The Acrobat JavaScript Reference, Use it Early and Often
http://www.adobe.com/devnet/acrobat/

Thom Parker
The source for PDF Scripting Info
www.pdfscripting.com
Very Important - How to Debug Your Script

tarekahf
Registered: May 1 2008
Posts: 91
thomp,

Thank you sooo much ... !

Just now I understand and the confusion is cleared 100%.

So, in Folder Level Script, you can execute security restricted function (Sec. Res.). So, using app.trustedFunction, you make a Sec. Res. func trusted and allow it to run anywhere else. So, when the folder level script is loaded it is executed, and things work fine. But when you call it from a non-privileged context, it must be wrapped by app.trustedFunction() to make it work.

I discovered this by adding this line of code to the folder level script:


var myLogin2 = identity.loginName;


Then, I was able to use the variable myLogin2 from anywhere else.

----

I just tried using this code from Folder Level Script:



function getXMLData() {
return xfa.data.saveXML();
}


And, when I call getXMLData() from a mouseUp Event, I get this error:

ReferenceError: xfa is not defined
27:Folder-Level:App:test.js

Looks like xfa cannot be used in Folder Level Script.

Please help.

Tarek.
thomp
Expert
Registered: Feb 15 2006
Posts: 4411
try executing the xfa code from the console window.

"xfa" is a property of a LiveCycle form. It does not exist for any other PDF file. So, in order for the code to work there must be a LiveCycle form open in Acrobat.

Thom Parker
The source for PDF Scripting Info
[url=http://www.pdfScripting.com]pdfscripting.com[/url]

The Acrobat JavaScript Reference, Use it Early and Often
[url=http://www.adobe.com/devnet/acrobat/]http://www.adobe.com/devnet/acrobat/[/url]

Thom Parker
The source for PDF Scripting Info
www.pdfscripting.com
Very Important - How to Debug Your Script

tarekahf
Registered: May 1 2008
Posts: 91
thomp,

I did some research, and found the answer here :

http://forms.stefcameron.com/2006/06/10/acroform-objects/

Goto comment #11 by Sérgio.

using event.target.xfa will expose the XFA object in Folder Level Script. I will have to try that as soon as I am back to the office.

I will confirm.

Tarek.
thomp
Expert
Registered: Feb 15 2006
Posts: 4411
Using "event.target.xfa" may or may not work. This is an interesting point. In the discussion on that blog they are talking about events called from the LiveCycle document, "event.target" points to the AcroForm document object for XFA events, i.e., events called from within the LiveCycle form.

When you use the JSO from a VB app you are calling an AcroForm event, so "event.target" may have a different meaning, although, it may very well point to the document object. The document object is a common value for event.target in many of the standard AcroForm events. The call from VB is called an "External Event" and the reference does not state the expected value of event.target for external events.

Thanks for finding the post. Cameron really knows what he's doing when it comes to LiveCycle Scripting.

However, I've written plenty of Folder Level JavaScript functions that are called from a VB app and "this" is always a pointer to the document object. At least in the top level call. The error you are getting:

xfa is not defined

Would seem to indicate that you are calling the function when the current file is not a LiveCycle form. Can you confirm that you are seeing the error when the current file is a LiveCycle form. And this line run from the console window:

this.xfa

returns the string "[object XFAObject]"

Thom Parker
The source for PDF Scripting Info
[url=http://www.pdfScripting.com]pdfscripting.com[/url]

The Acrobat JavaScript Reference, Use it Early and Often
[url=http://www.adobe.com/devnet/acrobat/]http://www.adobe.com/devnet/acrobat/[/url]

Thom Parker
The source for PDF Scripting Info
www.pdfscripting.com
Very Important - How to Debug Your Script

tarekahf
Registered: May 1 2008
Posts: 91
thomp,

I am sure I am using a LiveCycle From.

Puting the function:


function getXMLData() {
return event.target.xfa.data.saveXML();
}

in Folder Level Java, and it is working fine from within the document running under Acrobat (ver 7.0.5). But, when I use IAC from VB, I get error "event.target" does not exist or something like that.

So, it looks like xfa is not available from VB IAC Programming Model. To me, this looks like a bug or limitation.

I also put this code in folder level javascript:

var theXMLData = event.target.xfa.data.saveXML();

function getXMLData2() {
return theXMLData;
}

Again, it works from Acrobat, but from VB IAC, I get a very wierd error with a long hex number, as soon as I try to open the PDF File.

Also, I defined the same function getXMLData() in the DocReady of the main form (form1), but this function is only visible from the DocReady Event, and cannot be called from any other place not from Acrobat nor from VB.NET using IAC.

This is not really a big deal, since I am able to save the XML Data to a text file. But, I just want to write a cool program and avoid saving to a local file.

However, if you could give me more info on how to acheive this, I really appreacite it.

Tarek.
tarekahf
Registered: May 1 2008
Posts: 91
CONGRATULATIONS !

Issue resolved.

Check solution here:

http://www.adobeforums.com/webx?14@@.59b4be28/41

(click on "Show all messages" if needed")

We need to pass the "jso" from VB to the folder level javascript function, where jso will be the doc object:

function getXMLData(theDoc) {
return theDoc.xfa.data.saveXML();
}

Again, many thanks to thomp who was of a greate help to resolve this issue.

But I am still unable to call a Document Level JavaScript from VB, any idea ?

Tarek.
thomp
Expert
Registered: Feb 15 2006
Posts: 4411
Excellent!! I hadn't realized that VB could pass an integrated object, like the doc object, into a function. That pretty much solves it.

Thanks for reporting it. This will be a big help in the future.

Working with these two technologies can be frustrating. Like I said before, I've written plenty of VB scripts that use the JSO to call folder level functions that operate on the open document, and never run into this problem. But of course, I've never operated on a LiveCycle form in this way either. It seems strange that the top level operation (i.e. the meaning of "this") would be so different between LC and AcroForms.

But that's how it goes, thanks again for really digging into this issue and getting a solution.

Now, as far as calling a doc level script. LC Forms don't really have doc level scripts, at least not ones that are accessible from Acrobat UI. They have global script objects that are attached to form elements. So for example, if you had a script object called "MyScripts" attached to the top level form, "form1". You'd access a function in it like this.

xfa.form.form1.MyScripts.MyFunction();

True document level scripts are in the PDF, not the LiveCycle form. They can't be edited from LiveCycle Designer because it edits the XFA XML, and Acrobat blocks you from being able to edit them in the generated PDF.

Cheers,
Thom Parker
The source for PDF Scripting Info
[url=http://www.pdfScripting.com]pdfscripting.com[/url]

The Acrobat JavaScript Reference, Use it Early and Often
[url=http://www.adobe.com/devnet/acrobat/]http://www.adobe.com/devnet/acrobat/[/url]

Thom Parker
The source for PDF Scripting Info
www.pdfscripting.com
Very Important - How to Debug Your Script

tarekahf
Registered: May 1 2008
Posts: 91
thomp,

I have to say that discussing this topic with you clarified a lot of concepts which were so much confiding to me, and helped me find the solution faster.

I tried to put some code in a Form Level JavaScript Object in xfa form, and seems that it is not visible from VB. However, I did not spend much effort to try make it work.

For example, in VB, a setup a break point, and start using the immediate window to try different commands against VB JavaScript Object (jso).

I tried the following:


? jso.xfa ---> success? jso.xfa.data.saveXML() ---> success? jso.xfa.form ----> not found error? jso.xfa.resolveNode("TextField1") ---> Nothing? jso.xfa.resolveNode("xfa.form.form1.mainform.TextField1") ---> success? jso.xfa.resolveNode("xfa.form.form1.mainform.TextField1").rawValue ---> not found error? jso.xfa.form.form1.MyScriptObject.myNewFunction() ---> not found error? jso.getField("fully.qualified.SOM.name") ---> successSo, looks like you very few xfa related functions work from VB jso.

Is this because I am using the old Acrobat 7.0.5 ?

Is this a limitation by design ?

What is the requirement now:
==================

The required process, is to loop over all the PDF Files in a given folder, extract the XML Data, convert to .NET XML Doc Object, and post the Data Fields into the Database, generate a Key Value, and ....>>>> most important:1, UPDATE THE PDF back with the new key value generated in the Database,

2. Save the PDF with a different name to indicate that it is processed and qualified with the newly generated key value. For example, the data in the PDF named "XYZ_Application.PDF" has been posted to the Database and the key value is "12345", then I want to update a Read-Only Field in the Database with new key value, and rename the PDF file to:

XYZ_Application_12345_Done.PDF

or something like that.

I am thinking that I need to generate a new XML in .NET with the new key value, and import it back to the PDF, because I cannot update a read-only filed using doc.getField("App_No").value = NewKeyValue,

I tried using jso.getField("fully.qualified.xfa.field.name").value = NewKeyValue, and it worked.

Any help will be appreciated.

Tarek.
thomp
Expert
Registered: Feb 15 2006
Posts: 4411
All doable. You already know how to get the XML into the VB app. From there you can write it to disk or into a DB. But these are not Acrobat/PDF issues.

I think the only PDF related issue is setting a field value from the VB app? Since this is an XFA form you shouldn't use the "getField" fucntion. This is an AcroForm fucntion and only works because your form is static.

I would suggest using a folder level function that uses the XFA syntax. Just like you did it before by passing in the jso.

function MySetField(oDoc, path, value)
{
oDoc.xfa.form.resolveNode(path).rawVaue = value;
}

or something along these lines.

Thom Parker
The source for PDF Scripting Info
[url=http://www.pdfScripting.com]pdfscripting.com[/url]

The Acrobat JavaScript Reference, Use it Early and Often
[url=http://www.adobe.com/devnet/acrobat/]http://www.adobe.com/devnet/acrobat/[/url]

Thom Parker
The source for PDF Scripting Info
www.pdfscripting.com
Very Important - How to Debug Your Script

tarekahf
Registered: May 1 2008
Posts: 91
I need help about dynamic creation of objects (text fields and drop-down lists) during runtime and binding them to the appropriate data source node.

I am referring this article here:

http://avokahhh.wordpress.com/2008/06/19/best-practise-for-pre-populating-a-drop-down-with-data/

I have a project which uses a PDF Form that has Text Fields or Dynamic Drop-Down List Fields to capture Laboratory Results.

So, if the type of result is selected from a list of values, the field must be Drop-Down, and it must be bound to the list of valid values from XML Data Source, and only one of the selected values should be allowed.

And, if the type of the result is numeric, only numeric data should be allowed for data entry.

For example, the value for CBC Test can be: Normal, Boarder Line, and Abnormal.

Or, another test result could be: Positive or Negative.

In other cases, the result is just a number value, with Min/Max values, or a free text entry.

I can write an ASP.NET Program to Generate the XML to describe the type of field and what are the possible values, and inject this XML to a PDF using XDP Format and render the result to the Browser on the client side (response.write(...)).

But, I am not sure how to do the dynamic binding and change the field type between a Text Field and Drop-Down during/after rendering the form to the client.

The XML Data which describe the Result Field Types, and Valid Entries could look like the following:

CBC Test
DropDownNormal
Boarder Line
AbnormalStool
Number5
15Urine Color
FreeText....other data elements...

Please help me to implement this, or give me some hints.

Thank you so much in advance for your help.

Tarek.
thomp
Expert
Registered: Feb 15 2006
Posts: 4411
These are some very big issues, and I'm afraid you've gone beyond the scope of what can be answered on this forum. This forum is for answering single, narrowly focused, and short questions. With each question being asked on a separate thread. What you are asking here is something you should hire a consultant for.

I would suggest that you break down your issues into single, simple items and ask them one at a time. Creating a new thread for each. And please keep the questions as short as possible.

Thom Parker
The source for PDF Scripting Info
[url=http://www.pdfScripting.com]pdfscripting.com[/url]

The Acrobat JavaScript Reference, Use it Early and Often
[url=http://www.adobe.com/devnet/acrobat/]http://www.adobe.com/devnet/acrobat/[/url]

Thom Parker
The source for PDF Scripting Info
www.pdfscripting.com
Very Important - How to Debug Your Script

tarekahf
Registered: May 1 2008
Posts: 91
Dear thomp,

As per your recommendation, I have created a separate thread here:

http://www.acrobatusers.com/forums/aucbb/viewtopic.php?pid=36552#p36552

Hiring consultant is a greate idea, and our management supports this direction. However, as per my experience in the past 5 years, is that by the time I submit a request to hire a consultant, and by the time they understands the requirements, and by the time I go through lenghty routine procedures, probably, with the help of experts like you, I would have found a solution already. I have already contacted 3rd party for development support and Adobe Partner Solutions for Support also, and I have already made good progress in the previous project and in this new project too.

If you have contact for 3rd party support, please let me know.

Tarek.
tarekahf
Registered: May 1 2008
Posts: 91
Dear thomp,

I have created this new thread, and appreciate your help:

http://www.acrobatusers.com/forums/aucbb/viewtopic.php?pid=36555#p36555


Tarek.