WebAssembly/emscripten: write files to disk from within browser - javascript

I have some C code I would like to execute in a Browser (testing with Firefox 64.0). The C code writes a file to disk.
I have been trying to use the emscripten's File System API for many many hours now and I am getting nowhere.
I have read this relevant question and the emscripten doc states the same:
if your C/C++ code does use files, then file system support will be automatically included.
Here is my test code which uses the file system:
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *f = fopen("testfile.txt", "w");
if (f == NULL) {
printf("Error opening file!\n");
exit(1);
}
const char *text = "This is my test string";
int i = 1234;
fprintf(f, "Some text: %s; and an int: %d\n", text, i);
fclose(f);
printf("End of file.\n");
}
After I compiled this code with:
emcc test.c -o test.html
And opening it with Firefox, I initially expected the file to be saved onto my machine. (I have no JS background.)
I am now almost certain that it does not work like that.
The file is accessible as Uint8Array via:
var array = FS.readfile("testfile.txt")
in the console.
Specifically, I am now interested in this:
Is there a way to write a file to my local filesystem from inside the browser?
Can I download the created file in some way?
Thank you for your time.

TLDR; Never expect you could write anything in your machine on a browser.
Modern web browsers are designed with security in mind so they are highly sandboxed. They are never going to allow web pages to write/open a local file in your machine. Imagine someone visit your website and then a file called testfile.txt is created in their machine, and the website keeps creating files every time you press the refresh button.
WebAssembly has no exception. It is just a virtual machine to run code written in languages other than Javascript. Keep in mind that WebAssembly is run by a JavaScript engine. So saying "I have no JS background." is simply an invalid statement. What JS can't do is what WebAssembly can't.
According to the Emscripten File System Overview documentation, the files you create will stay in the memory. You have to convert it to Blob (this has to be done using JavaScript API) to allow users to download.

Related

Executing a whole js file as a module in Chromium Embedded Framework

I am using the Chromium Embedded Framework in C# (cefSharp) als testing platform for a software I am currently working on. In these tests i use the cefSharp to inject my js file on various websites. Up till now my software consistet of one big js file and i was able to inject it in following way.
//Wait for the MainFrame to finish loading
Browser.FrameLoadEnd += (sender, args) =>
{
//Wait for the MainFrame to finish loading
if (args.Frame.IsMain)
{
byte[] bytes = File.ReadAllBytes("../../js/myJs.js");
string script = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
Browser.ShowDevTools();
Browser.ExecuteScriptAsync(script);
};
};
This solution worked fine.
Now i refactored some code and split my js file up into multiple modules.
If i execute the modules the same way i did with the previous js file i instantly get errors stating "import statements can only be used in modules". (normally the fix for it would be simply to reference the js file as "module" in the html file instead of "text/javascript") Because I´m injecting it via cef i cant do that. My question is: Is there a possibility to run this js modules as modules via cefSharp?

Photoshop 8800 Error only after python creates the file

I have a bit of a weird situation that I will try to explain the best I can.
I am using Python to launch photoshop and run a javascript file. But my goal is for python to generate the javascript first, then run it in photoshop.
In order to do that I have python copying the javascript file, then replacing a single line of code and running this new copy.
When I run the original javascript file it works as intended with no problems.
When I run the copied javascript file it works as intended with no problems.
When I run the copied javascript file that has the line replaced, it gives me an 8800 error.
At this point, even if I manually type the replaced line to match the original javascript file. I will still get an 8800 error.
Does python somehow write files differently?
Here is the code I am using to replace the copy and replace the javascript contents:
from shutil import copyfile
jsx_file = r'E:\PS\_javascript_constructor_template.jsx'
jsx_file_new = r'E:\PS\_javascript_constructor_template_new.jsx'
copyfile(jsx_file, jsx_file_new)
with open(jsx_file_new, "r") as fin:
data = fin.read()
with open(jsx_file_new, "w") as fout:
fout.write(data.replace("!REPLACEME!",'"E:\PS\MockVar.csv"'))
Any ideas?
SIDE NOTE: I am only doing this because I have no idea how to pass an argument from python into the javascript file I am subprocess calling.
I would much rather send an argument to the javascript file than build new files enitrely.
If you'd rather send an argument to the Photoshop script, I'd recommend using interprocess communication. You can use the socket module in Python and the Socket object in Extendscript to send messages back and forth. Check out External Communications Tools in the Adobe Tools Guide for more information.

Passing Value from C++ to Javascript

i have a c++ file which reads values from a sensor and I want to display those values on a website dynamically. So Im looking for a way to pass these values(integers) from my cpp file to an javascript which displays them on the site.
My first, simple try was to write the values into a js file as variables every second from my cpp script. The Js then uses this file as a source and displays its variables on the site:
cpp:
fprintf(file, "var mx=%d, my=%d, mz=%d, ax=%d, ay=%d, az=%d, gx=%d, gy=%d, gz=%d;\n",
imu.raw_m[0], imu.raw_m[1], imu.raw_m[2], // M = Magnetometer
imu.raw_a[0], imu.raw_a[1], imu.raw_a[2], // A = Accelerometer
imu.raw_g[0], imu.raw_g[1], imu.raw_g[2] // G = Gyroscope
);
html/js:
<script src="./imu.js" type="text/javascript"></script>
The Problem now is of course, that I need to refresh the page all the time, because the imu.js file is cached by the website.
I'd rather have a way to directly pass to integers from the cpp file to the js script. I read something about json or Googles V8 script. But I'd like to hear your suggestions first.
By the way, Im running this on a raspi, if this is important.
Thanks for your help
EDIT:
I'm goning to try it with a mysql database, in which my cpp file writes the data from the sensor with Connector/c++ from http://dev.mysql.com/doc/connector-cpp/en/ and my website reads them.
You could compile your C++ code into a Node.js plugin, you can then register a JavaScript function with your plugin which the C++ calls when it updates the value. That way you can pass values directly from C++ into Javascript in a managed and controlled way.
Node.js has the added benefit of being able to host your webpage and do all the Websocket and HTTP stuff that can be a pain in C++.
You do not have to refresh if your script is smart about how to access the data file! In case you do have a webserver at hand: Take care that your data file is accessible by your webserver and then let your script request the file via ajax (link to w3schools)
I'm doing something similar on a BeagleBone Black. With websocketd you can turn pretty much any program into a websocket endpoint and then send data via stdin and stdout commands. This would be a particularly good solution for you since websockets are designed to handle information that's constantly changing.

Can I secure resources other than javascript in Nodewebkit?

I read this post
securing the source code in a node-webkit desktop application
I would like to secure my font files and I was thinking this snapshot approach might be a way. So instead of running this
nwsnapshot --extra-code application.js application.bin
Could I run
nwsnapshot --extra-code font_file font_file.bin
Then in package.json add this?
snapshot: 'font_file.bin'
Or would there be an alternative mechanism to reference the binary font? Would it be possible to convert the CSS file referencing the font into binary? Can anything else other than javascript be converted to binary?
One dumb thing you can do is to add your assets to the exe file as stated here:
https://github.com/nwjs/nw.js/wiki/How-to-package-and-distribute-your-apps#step-2a-put-your-app-with-nw-executable
Basically you have to create a zip of your content (included your package.json) and rename it to "package.nw" then you can "merge it" into the exe file by typing this if you're in windows (the link explains how to do this in other OS's):
`copy /b nw.exe+app.nw app.exe `
This is not a great security measure (beacuse it can be opened as a zip file) but is one step further.
Another thing that could add security to your files is to encrypt them and then add them dinamically through js (while decrypting them) for this you could use the encrypt and decrypt methods available in node.
http://lollyrock.com/articles/nodejs-encryption/
However the weakest point in the application is still the packages.json file and for this nw provides nothing.
Cheers!

How to create a file using javascript in Mozilla Firefox

I want to write a function in javascript which creates a file and write some content to it, iam working with firefox, can anybody help me in this case.
Thanks...
You can write files in JavaScript in Firefox, but you have to use an XPCOM object (internal browser API). This is not allowed for JavaScript loaded from a web page, and it is intended to be used by JavaScript running inside a Firefox add-on (with high level of privileges).
There is a way for unprivileged (web page) JavaScript to request more privileges and if the user grants it (there will be a pop up dialog asking for permission), the web page code would be able to write to a file.
But before you read further, a warning:
This is not standard JavaScript and I would not recommend this approach unless you are developing a very specific application, that will be used in a very specific way (like for example, http://www.tiddlywiki.com/ a client-side JavaScript-HTML only wiki).
Requesting XPCOM privileges on a website is a bad practice! It's basicly equivalent to running an .exe you just downloaded from a site. You are asking a user to grant full access to their computer (read, write, execute) with the identity of the user running Firefox.
Request permission to use XPCOM (this will prompt the user for confirmation, no way to avoid it):
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
Then, write to a file using an XPCOM object (example code from Mozilla Developer Network):
1. // file is nsIFile, data is a string
2. var foStream = Components.classes["#mozilla.org/network/file-output-stream;1"].
3. createInstance(Components.interfaces.nsIFileOutputStream);
4.
5. // use 0x02 | 0x10 to open file for appending.
6. foStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0);
7. // write, create, truncate
8. // In a c file operation, we have no need to set file mode with or operation,
9. // directly using "r" or "w" usually.
10.
11. // if you are sure there will never ever be any non-ascii text in data you can
12. // also call foStream.writeData directly
13. var converter = Components.classes["#mozilla.org/intl/converter-output-stream;1"].
14. createInstance(Components.interfaces.nsIConverterOutputStream);
15. converter.init(foStream, "UTF-8", 0, 0);
16. converter.writeString(data);
17. converter.close(); // this closes foStream
You can find more information about I/O in Firefox using XPCOM here: https://developer.mozilla.org/en-US/docs/Code_snippets/File_I_O
Javascript from websites cannot access the local file system.
If you like to store data either store it on the server or in a cookie.
writing to the file system directly from a browser is prohibited for security reasons. With html5 however it'll be possible to have offline storage support. Take a look here.
Grz, Kris.
Javascript executes in a client-side context.
http://www.tek-tips.com/viewthread.cfm?qid=1171273&page=1
There will be an API for this.. File Writer API. The early specification is here:
http://www.w3.org/TR/file-writer-api/
It is not implemented in any browser yet.
Update: It seems there already exists an implementation. Check out http://caniuse.com/filesystem and http://www.html5rocks.com/en/tutorials/file/filesystem/
While everyone who's responded that javascript does not have the ability to write files on a remote server are correct, and this is true for security reasons, what you want to accomplish may still be possible.
For example, if you wanted to make it possible to create a file on your website with the use of javascript, you can do so with some server side scripting language and and AJAX call.
Example:
You have a file on your server called update_last_access.php which will create a file which stores the last time the file was accessed in some arbitrary file.
If you then had your javascript function make an AJAX call out to that script, for instance, in jquery
$.get("update_last_access.php")
Then this would execute the server side script and write to the file.
Before any more help can be provided for you, you're going to have to clarify what you're trying to do.
You can read files from the filesystem in JavaScript with Firefox 3.6 - see my EPUB reader proof of concept, for example.
You can't write files directly from JavaScript, though. You have to go via a server.
Mozilla is planning to include FileSaver to Gecko 9:
https://bugzilla.mozilla.org/show_bug.cgi?id=557540

Categories

Resources