Write text file using acrobat javascript - javascript

Trying to write to a text file w/ Adobe Acrobat Reader utilizing AcroJS.
As a concept I got how to use trusted functions in Acrobat but when I tried to run following example to save (different problem then the original) the pdf form under a different name using this.saveAs(..) received an error.
My question is two fold;
1- Why do I get "Security settings prevent access to this property or method" error and how do I get rid of it?
trusted function in javascript folder is as follwos (copeid off the web)
var mySaveAs = app.trustedFunction( function(cFlName)
{
app.beginPriv();
try{
this.saveAs(cFlName);
}
catch(e){
app.alert("Error During Save " + e.message );
}
app.endPriv();
});
I am calling the trusted function from the doucment as follwos and expecting a file with the name sample.pdf will be generated inside "C:/test"
if(typeof(mySaveAs) == "function")
{
mySaveAs("/C/test/sample.pdf");
}
else
{
app.alert("Missing Save Function");
}
2- How do I write to a text file? Here I want to extract some field values from the PDF form and write those into a text file (or XML)!

As you might have guessed, it's a security measure to prevent malicious scripts from causing havoc. You'll need to turn down the security settings. To do this, Ctrl+K into Preferences, go to the Enhanced Security tab and disable it.
For addition information on Enhanced Security, refer to: http://www.adobe.com/devnet-docs/acrobatetk/tools/AppSec/enhanced.html
As far as I know, there aren't any functions that will allow you to write arbitrary data to a text file or XML file. However, you have a couple of options:
Use Doc.exportAsText (text) and Doc.exportAsFDF (XML) to export data from carefully crafted fields. This isn't very straightforward and a little awkward, but it works.
Use Net.HTTP.request or Net.SOAP to send data to an ad-hoc local web server (eg: something simple, running Python or PHP) and let them handle the request. This allows you to do pretty much anything you want, but requires more work to setup the server.
See: Acrobat JS API Reference

Related

How can I get information from a local text file without browsing?

So what I'm trying to do is get text from a file in the same directory as my html file using JavaScript. I want to store an array inside a text file and change it whenever i want instead of constantly having to go into the code, save it, check if it works etc.
I've tried looking around but couldn't find any clear information, most of what I found is using .readAsBinaryString, etc..
I'm mostly seeing things like this but i can't seem find anything which is actually getting information from a textfile without making the person find the text file directory.
function storearray(newval){
var file = "file location;"
var txt = file.txt;
var array = txt.split("|");
txt = txt + newval + " | ";
return array;
}
To read a file from the user's disk you need to use FileReader and the user must explicitly select the file using a file input. (See JavaScript read file without using input).
To read a a file from the website you need to use Ajax (with fetch, XMLHttpRequest or a library that wraps around them like Axios). (See Using fetch from MDN).
If (as it seems here) you want to read data from the website but the website exists only on the user's disk then you still need to use Ajax but will usually run into security restrictions. Some browsers allow you to disable the security protection, but the general solution is to install a web server and load both HTML and the data file using HTTP.
Alternatively, you can store your data in JavaScript (you are generating an array from your text file, you can so that manually or have a build-time script do it) and just load it with a <script> element.

make ASP.Net file upload secure

I'm creating an ASP.Net form with a fileupload control which will then email the details of the form and the file to another admin. I want to ensure this secure (for the server and the recipient). The attachment should be a CV so I will restrict it to typical text documents.
From what I can tell the best bet is to check that the file extension or MIME Type is of that kind and check it against the "magic numbers" to verify that the extension hasn't been changed. I'm not too concerned about how to go about doing that but want to know if that really is enough.
I'd also be happy to use a third party product that takes care of this and I've looked at a couple:
blueimp jQuery file upload
http://blueimp.github.io/jQuery-File-Upload/
and cutesoft ajaxuploader
http://ajaxuploader.com/Demo/
But blueimp one still seems to require custom server validation (i guess just being jQuery it just handles client-side validation) and the .net one checks the MIME-type matches the extension but I thought the MIME type followed the extension anyway.
So,
Do I need to worry about server security when the file is added as an attachment but not saved?
Is there a plugin or control that takes care of this well?
If I need to implement something for server validation myself is matching the MIME-type to the "magic numbers" good enough?
I'm sure nothing is 100% bulletproof but file upload is pretty common stuff and I assume most implementations are "safe enough" - but how!?
If it's relevant, here is my basic code so far
<p>Please attach your CV here</p>
<asp:FileUpload ID="fileUploader" runat="server" />
and on submit
MailMessage message = new MailMessage();
if (fileUploader.HasFile)
{
try
{
if (fileUploader.PostedFile.ContentType == "text")
{
// check magic numbers indicate same content type... if(){}
if (fileUploader.PostedFile.ContentLength < 102400)
{
string fileName = System.IO.Path.GetFileName(fileUploader.PostedFile.FileName);
message.Attachments.Add(new Attachment(fileUploader.PostedFile.InputStream, fileName));
}
else
{
// show a message saying the file is too large
}
}
else
{
// show a message saying the file is not a text based document
}
}
catch (Exception ex)
{
// display ex.Message;
}
}
A server can never be 100% secure, but we should do our best to minimize the risk on an incident. I should say at this point that I am not an expert, I am just a computer science student. So, here is an approach that I would follow in such a case. Please, comment any additional tip you can give.
Generally speaking, to have a secure form, all client inputs must be checked and validated. Any information that does not origin from our system is not trusted.
Inputs from the client in our case:
file's name
name
extension
file's content
Extension
We don't really care about the minetype, this is info for a web server. We care about the file extension, because this is the indicator for the OS on how to run/read/open a file. We have to support only specific file extensions (what ever your admin's pc can handle) there is no point supporting unknown file types.
Name (without the extension)
The name of the file is not always a valuable info. When I deal with file uploading I usually rename it (set it) to an id (a username, a time-stamp, hashes etc). If the name is important, always check/trim it, if you only expect letters or numbers delete all other chars (I avoid to leave "/", "\", "." because they can be used to inject paths).
So now we suppose that the generated file name is safe.
Content
When you support no structured files, you just can not validate the file's content. Thus, let an expert program do this for you... scan them with an antivirus. Call the antivirus from the console (carefully, use mechanics that avoid injections). Many antivirus can scan zips contents too (a malicious file, in a folder on your server is not a good idea). Always keep the scan program updated.
On the comments I suggested zipping the file, in order to avoid any automatic execution on the admin's machine and on the sever. The admin's machine's antivirus can then handle it before unzip.
Some more tips, don't give more information's to the client than he needs... don't let the client know where the files are saved, don't let the web-server access them for distribution if there no need to. Keep a log with weird actions (slashes in filenames, too big files, too long names, warning extensions like "sh" "exe" "bat") and report the admins with an email if anything weird happen (it is good to know if your protections work).
All these creates server work load (more system holes), so you may should count the number of files that are scanned/checked at the moment before accepting a new file upload request (that is where I would launch a DDoS attack).
With a quick google search Avast! For Linux - Command Line Guide, I do not promote Avast, I am just showing it as an existing example.
Lastly but not least, you are not paranoid, I manage a custom translation system that I coded... spams and hack attacks have occurred more than once.
Some more thoughts, JavaScript running on a web-page is only secure for the client's computer (thanks to the browser's security). We can use it to prevent invalid posts to the server but this does not ensures that such requests will not be done as JavaScript can be bypassed/edited.
So, all JavaScript solutions are only for a first validation (usually just to help the user correct mistakes) and to correctly set the form data.

How to write a text file in Acrobat Javascript

I am using acrobat XI
I have tried output a text file like this
var cMyC = "abc";
var doc = this.createDataObject({cName: "test.txt", cValue: cMyC});
this.exportDataObject({cName: "test.txt", nLaunch:0});
This is working , but I would like to provided a fixed path and no dialog is popup to request the user choose a saving path
Are there any way to fix the problem? thanks
All Acrobat JavaScript functions that write a file to the user’s local disk pose a security risk, so there are some restrictions placed on their use. These functions include doc.saveAs() and all of the data export functions, like doc.exportAsFDF().
As you can read here:
Acrobat provides us with two modes of operation for these
functions--with a path and without a path. If no path parameter is
provided to the function, Acrobat displays a file-browser dialog. The
file browser dialog gives users control over how data is saved to
their systems. If a path is provided to the function, then no dialog
is displayed and the operation is handled silently, i.e., the user is
not necessarily aware that data has been saved to their hard drive.
This is a security problem, so to use one of these functions in silent
mode, the function must be executed from a privileged context. This
means the code must reside in a trusted location. For example, code
executed from the Console Window, a Batch Process or a certified PDF
is privileged. When any of these functions are used with a path
parameter and executed in a non-privileged context, Acrobat will throw
an exception. The reasoning behind this restriction is, if the code
can’t be trusted, then the user has to specifically select the file
location.
Another restriction on saving data to the user’s system is that the
path specification must be a Safe Path. A safe path is one that
doesn’t point to a restricted location on the user’s hard drive or one
that might pose a security risk. Examples of these restricted
locations are the system folder and the root folder of any hard drive.
Other folders that might be restricted are dependent on the operating
system and the sensibilities of the Acrobat developers. Neither is
well documented, so it’s best to use these functions carefully.
About "Safe Paths", the Acrobat JS API doc.saveAS method documentation states:
Acrobat 6.0 introduced the concept of a safe path for JavaScript
methods that write data to the local hard drive based on a path passed
to it by one of its parameters. A path cannot point to a system
critical folder, for example a root, windows or system directory. A
path is also subject to other unspecified tests. For many methods, the
file name must have an extension appropriate to the type of data that
is to be saved. Some methods may have a no-overwrite restriction.
These additional restrictions are noted in the documentation.
Generally, when a path is judged to be not safe, a NotAllowedError
exception is thrown (see Error object) and the method fails.
For sure you can't do it with the exportDataObject method, since it has no path parameter, as you can also read here:
The "cName" parameter is a required input and specifies the specific
file attachment that will be exported. Notice there is no path
parameter. There is in fact a "cPath" input to this function, but it
is no longer valid. If you try to use a path in this function, it will
fail and throw an exception. It doesn't matter what context the
function is called from because the "cPath" parameter was removed from
all usage.
Further references:
Write Text file using Acrobat Javascript
Acrobat Javascript Save and Exit Button
Here's a way to output to a fixed path text file using doc.exportAsText:
// set up output text
var TEMP_FIELD_NAME = "testHeader"
var textValue = "test";
// add a temporary text field
var f = this.addField(TEMP_FIELD_NAME, "text", 0, [30,30,100,20]);
f.value = textValue;
// export field name and value to defined file
this.exportAsText({aFields: TEMP_FIELD_NAME, cPath: "test-text.txt"});
// remove text field
this.removeField(TEMP_FIELD_NAME);
The resulting text file will have two lines:
testHeader
test
Impossible. For security reasons, saving a file automatically is not allowed.
As stated in the SDK:
Beginning with Acrobat 6.0, if the parameter cDIPath is non-null, a NotAllowedError exception is thrown and the method fails.
If cDIPath is not passed to this method, a file selection dialog box opens to allow the user to select a save path for the embedded data object.

Reading local XML file with javascript

I am new to HTML/Javascript, as well as coding in general so bear with me :). I am trying to create a "Spot the Difference" game in html5 using javascript. Everything is local (on my machine). I have two pictures, of the same size, one with differences. To generate data about the clickable fields, I have a java program that reads both of the images and outputs all of the positions in which pixels are different into a XML file. My plan was to then use this XML file with my javascript to define where the user could click. However, it appears (correct me if I'm wrong) that javascript cannot read local XML files for security reasons. I do not want to use an ActiveXObject because I plan on putting this onto mobile devices via phone gap or a webkit object. Does anyone have a better approach to this problem, or perhaps a way to read local XML files via javascript? Any help would be greatly appreciated, thanks.
If you are planning to put this into a smart phones (iOS and Android) and read local files, I have done similar things with JSON (yes, please don't use XML).
Convert your output to JSON
Put this as part of your application package. For example, in Android, I put it as part of the .apk in /appFiles/json
Create a custom content provider that would read the local file. I create mine as content:// but you create whatever scheme you want. You could leverage android.content.ContentProvider in order to achieve custom URL Scheme. iOS has its own way to create custom scheme as well. The implementation simply read your local storage and give the content
To read it from Javascript, I simply call ajax with the custom scheme to get the json file. For example content://myfile/theFile.json simply redirect me to particular directory in local storage with /myfile/theFile.json appended to it
Below is the sample to override openFile() in the ContentProvider
public ParcelFileDescriptor openFile (Uri uri, String mode) {
try {
Context c = getContext();
File cacheDir = c.getCacheDir();
String uriString = uri.toString();
String htmlFile = uriString.replaceAll(CUSTOM_CONTENT_URI, "");
// Translate the uri into pointer in the cache
File htmlResource = new File(cacheDir.toString() + File.separator + htmlFile);
File parentDir = htmlResource.getParentFile();
if(!parentDir.exists()) {
parentDir.mkdirs();
}
// get the file from one of the resources within the local storage
InputStream in = WebViewContentProvider.class.getResourceAsStream(htmlFile);
// copy the local storage to a cache file
copy(in, new FileOutputStream(htmlResource));
return ParcelFileDescriptor.open(htmlResource, ParcelFileDescriptor.MODE_READ_WRITE);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
I hope it helps
I would suggest modifying your java program to output a JSON formatted file instead of XML. JSON is native to JavaScript and will be much simpler for you to load.
As for actually loading the data, i'm not sure what the best option is as you say you want to evenutally run this on a mobile device. If you were just making a normal website you could setup a web server using either Apache or IIS depending on your OS and put the files in the document root. Once you've done that you can load the JSON file via Ajax, which can easily be googled for.
Not sure if this helps any.
Since this is a local file, you can do this with jQuery
$.ajax({
type: "GET",
url: "your.xml",
dataType: "xml",
success: function(xml){
///do your thing
}
});
http://api.jquery.com/jQuery.ajax/

Check if a file exists locally using JavaScript only

I want to check if a file exists locally, where the HTML file is located. It has to be JavaScript. JavaScript will never be disabled. jQuery is not good but can do.
By the way, I am making a titanium app for Mac so I am looking for a way of protecting my files from people who click "show package contents".
Your question is ambiguous, so there are multiple possible answers depending on what you're really trying to achieve.
If you're developping as I'm guessing a desktop application using Titanium, then you can use the FileSystem module's getFile to get the file object, then check if it exists using the exists method.
Here's an example taken from the Appcelerator website:
var homeDir = Titanium.Filesystem.getUserDirectory();
var mySampleFile = Titanium.Filesystem.getFile(homeDir, 'sample.txt');
if (mySampleFile.exists()) {
alert('A file called sample.txt already exists in your home directory.');
...
}
Check the getFile method reference documentation
And the exists method reference documentation
For those who thought that he was asking about an usual Web development situation, then thse are the two answers I'd have given:
1) you want to check if a server-side file exists.
In this case you can use an ajax request try and get the file and react upon the received answer. Although, be aware that you can only check for files that are exposed by your web server. A better approach would be to write a server-side script (e.g., php) that would do the check for you, given a filename and call that script via ajax. Also, be aware that you could very easily create a security hole in your application/server if you're not careful enough.
2) you want to check if a client-side file exists.
In this case, as pointed you by others, it is not allowed for security reasons (although IE allowed this in the past via ActiveX and the Scripting.FileSystemObject class) and it's fine like that (nobody wants you to be able to go through their files), so forget about this.
Since 'Kranu' helpfully advises 'The only interaction with the filesystem is with loading js files . . .', that suggests doing so with error checking would at least tell you if the file does not exist - which may be sufficient for your purposes?
From a local machine, you can check whether a file does not exist by attempting to load it as an external script then checking for an error. For example:
<span>File exists? </span>
<SCRIPT>
function get_error(x){
document.getElementsByTagName('span')[0].innerHTML+=x+" does not exist.";
}
url=" (put your path/file name in here) ";
url+="?"+new Date().getTime()+Math.floor(Math.random()*1000000);
var el=document.createElement('script');
el.id="123";
el.onerror=function(){if(el.onerror)get_error(this.id)}
el.src=url;
document.body.appendChild(el);
</SCRIPT>
Some notes...
append some random data to the file name (url+="?"+new Date etc) so that the browser cache doesn't serve an old result.
set a unique element id (el.id=) if you're using this in a loop, so that the get_error function can reference the correct item.
setting the onerror (el.onerror=function) line is a tad complex because one needs it to call the get_error function AND pass el.id - if just a normal reference to the function (eg: el.onerror=get_error) were set, then no el.id parameter could be passed.
remember that this only checks if a file does not exist.
You can use this
function LinkCheck(url)
{
var http = new XMLHttpRequest();
http.open('HEAD', url, false);
http.send();
return http.status!=404;
}
Javascript cannot access the filesystem and check for existence. The only interaction with the filesystem is with loading js files and images (png/gif/etc).
Javascript is not the task for this
Fortunately, it's not possible (for security reasons) to access client-side filesystem with standard JS. Some proprietary solutions exist though (like Microsoft's IE-only ActiveX component).
If you want to check if file exists using javascript then no, as far as I know, javascript has no access to file system due to security reasons..
But as for me it is not clear enough what are you trying to do..
An alternative:
you can use a "hidden" applet element which implements this exist-check using a privileged action object and override your run method by:
File file = new File(yourPath);
return file.exists();
One way I've found to do this is to create an img tag and set the src attribute to the file you are looking for. The onload or onerror of the img element will fire based on whether the file exists. You can't load any data using this method, but you can determine if a particular file exists or not.
No need for an external library if you use Nodejs all you need to do is import the file system module. feel free to edit the code below:
const fs = require('fs')
const path = './file.txt'
fs.access(path, fs.F_OK, (err) => {
if (err) {
console.error(err)
return
}
//file exists
})

Categories

Resources