Node JS - Backspace not working in Node-Pty Terminal - javascript

I have this simple code
const os = require('os')
const pty = require('node-pty')
const process = require('process')
const { msleep } = require('sleep');
const { readFileSync, writeFileSync } = require('fs');
const { exit } = require('process');
const usage = `Usage: term-record [OPTION]
OPTION:
play [Filename] Play a recorded .json file
record [Filename] Record your terminal session to a .json file`
var shell = os.platform() === 'win32' ? 'powershell.exe' : 'bash'
var lastRecordTimestamp = null
var recording = []
var args = process.argv
args.splice(0, 2)
function getDuration() {
var now = new Date().getMilliseconds()
var duration = now - lastRecordTimestamp
lastRecordTimestamp = new Date().getMilliseconds()
return duration
}
function play(filename) {
try {
var data = readFileSync(filename, { encoding: 'utf8', flag: 'r'})
} catch (err) {
if (err.code == 'ENOENT') {
console.error("Error: File Not Found!")
exit(1)
} else {
console.error(err)
exit(1)
}
}
try {
data = JSON.parse(data)
} catch (err) {
console.error("Error: Invalid File!");
exit(1)
}
console.log("------------ STARTING ------------");
for (let i = 0; i < data.length; i++) {
process.stdout.write(data[i].content);
msleep(data[i].delay)
}
console.log("-------------- END ---------------");
}
function record(filename) {
var ptyProcess = pty.spawn(shell, [], {
name: 'TermRecord Session',
cols: process.stdout.columns,
rows: process.stdout.rows,
cwd: process.env.HOME,
env: process.env
});
process.stdout.setDefaultEncoding('utf8');
process.stdin.setEncoding('utf8')
process.stdin.setRawMode(true)
process.stdin.resume();
ptyProcess.on('data', function(data) {
process.stdout.write(data)
var duration = getDuration();
if (duration < 5) {
duration = 100
}
recording.push({
delay: Math.abs(duration),
content: data
});
});
ptyProcess.on('exit', () => {
process.stdin.setRawMode(false);
process.stdin.pause()
recording[0].delay = 1000
try {
writeFileSync(filename, JSON.stringify(recording, null, '\t')); // JSON.stringify(recording, null, '\t') For Tabs
} catch (err) {
console.log(err);
}
})
var onInput = ptyProcess.write.bind(ptyProcess)
process.stdin.on('data', onInput)
}
if (args.length === 2) {
var file = args[1]
if (args[0] == "record") {
console.info("Setting App Mode to 'Record'")
console.info("Setting Output file To '" + file + "'")
record(file)
}
if (args[0] == "play") {
console.info("Setting App Mode to 'Play'")
console.info("Setting Input file To '" + file + "'")
play(file)
}
} else {
console.log(usage);
}
The record function takes a argument filename and then starts a new terminal using node-pty module, and when on data event occurs it simply calculates the the milliseconds from the last time this on data event triggered, and pushes a object into recording array, and this object has two properties, 1st is delay, and second is the text. and when the on exit event triggers, it simply closes the terminal and saves the recording array to a json file with name equal to the variable filename
The play function takes a argument filename and then reads the data from the file and parses it to a JavaScript Array which contains multiple objects, and if something goes wrong it throws an error. after parsing it simply uses a for loop to iterate over the array and writes the data to the console and waits for some milliseconds.
Problem is, when I record my session, and when i press Backspace key to remove a character, then it weirdly puts a space between it, like shown below:
In the gif, after I ran the first command and typed out ls -ls then i pressed Backspace 2 Times, which resulted a weird blank space 2 times.
and after i pressed enter it showed a error ls: cannot access '-': No such file or directory which meant the Backspace key removed 2 characters from the input but and it executed ls - instead of ls -ls but for some reason those 2 characters were not removed from the console when i pressed Backspace twice instead it added a weird blank space
How do i fix this issue?
This is what my package.json looks like:
{
"name": "term-record",
"version": "0.0.1",
"description": "A Simple Terminal Session Recorder",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js"
},
"author": "ADITYA MISHRA",
"license": "MIT",
"dependencies": {
"node-pty": "^0.10.1",
"sleep": "^6.3.0"
}
}
My NodeJS version: v16.11.1
My NPM version: 8.1.2
My Linux Distro: Arch Linux with XFCE 4
I tried switching to nodejs version 14.18.1-1, but that didn't help too

Since i had my keyboard layout poorly selected, which caused the backspace key to add a space.
I ran the following command setxkbmap -layout us, to change my keyboard layout to US and now it works

Related

I am have a problem reading some data using the serial.read() command

I am periodically reading the temperature and Humidity values from a DHT22 sensor in a green house tunnel.
The sensor is attached to a Arduino Pro Mini. The Pro Mini also has a nF24l01 transceiver attached to it, and the readings are transmitted to another nF24L01/Arduino Pro Mini in my office.
The Arduino is connected to a desktop PC via a USB serial cable.
The intention is to write the received Temperatue and Humidity readings to a file in a CSV format.
I am receiving all the data over the radio link which in-turn is feed to my PC via my USB port. I am running Node with a file called index.js.
Below is the code from the Arduino connected to the PC. It is the receiver side of the radio link.
[code]
/*
See documentation at https://nRF24.github.io/RF24
See License information at root directory of this library
Author: Brendan Doherty (2bndy5)
*/
/**
A simple example of sending data from 1 nRF24L01 transceiver to another.
String message = "";
This example was written to be used on 2 devices acting as "nodes".
Use the Serial Monitor to change each node's behavior.
*/
#include <SPI.h>
#include <printf.h>
#include <nRF24L01.h>
#include <RF24.h>
struct dataStruct {
float HumH;
float TempC;
} myData;
bool newData = false;
RF24 radio(9, 10); // using pin 7 for the CE pin, andradio.read(&data, sizeof(MyData)); pin 8 for the CSN pin
uint8_t address[][6] = {"1Node", "2Node"};
bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to transmit
bool role = false; // true = TX role, false = RX role
void setup() {
Serial.begin(115200);
if (!radio.begin()) {
Serial.println(F("radio hardware is not responding!!"));
while (1) {} // hold in infinite loop
}
radio.setPALevel(RF24_PA_HIGH); // RF24_PA_MAX is default.
radio.setPayloadSize(sizeof(dataStruct)); // float datatype occupies 4 bytes
radio.openWritingPipe(address[radioNumber]); // always uses pipe 0
radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1
radio.startListening(); // put radio in RX mode
// For debugging info
printf_begin(); // needed only once for printing details
radio.printDetails(); // (smaller) function that prints raw register values
radio.printPrettyDetails(); // (larger) function that prints human readable data
} // end of setup
void getData() {
if (radio.available()) {
//Serial.println("Radio is available******");
radio.read(&myData, sizeof(dataStruct));
newData = true;
}
//Serial.println("Radio is NOT available******");
}
void showData() {
if (newData == true) {
String message = "";
message = message + "{\"humidity\": ";
message = message + myData.HumH;
message = message + ", \"temperature\": ";
message = message + myData.TempC;
message = message + "}";
Serial.println(message);
newData = false;
}
}
void loop() {
getData();
showData();
}
[/code]
Below is a screen shot of the serial output of the Arduino Pro Mini connected to my PC shown what is being received from the green house and what is being sent to the PC.
Arduino Serial port screen shot
The index2.js code is listed below
const SerialPort = require('serialport');
//const Readline = new SerialPort.parsers.Readline('\n');
const port = new SerialPort('/dev/ttyUSB0', {
baudRate: 115200
});
const fs = require('fs');
const { endianness } = require('os');
const { exit } = require('process');
const { Console } = require('console');
//const logIntervalMinutes = 1;
let lastMoment = new Date();
function tryParseJson(str) {
try {
JSON.parse(str);
} catch (e) {
console.log("JSON error")
return false;
}
return JSON.parse(str);
}
console.log('Initialising...');
port.on('open', function () {
console.log('Opened port...');
port.on('data', function (data) {
const sensorData = tryParseJson(data);
console.log('Data: ' + data);
const moment = new Date();
fs.appendFile('log.txt', `\n${sensorData.temperature} , ${sensorData.humidity} , ${moment}`, function (err) {
if (err) {
console.log('Your Jason has failed to get a complete string...');
} else {
console.log('Logged data: ', moment);
};
});
});
});
When I run node index2.js and look at the log.txt file I see that sometimes the temp/Hum values are listed as undefined as show in the screen shot below.
log.txt
After a bit of debugging I saw the following in the console.log() as show in the screen shot below.
Console.log() screen shot with program running.
So my problem is that every now and again, the fs.append can't determine the value of sensorData.temperature and sensorData.humidity. The fs.append still appends a record to the log.txt file but the 1st two fields have undefined in them.
fs.appendFile('log.txt', `\n${sensorData.temperature} , ${sensorData.humidity} , ${moment}`, function (err) {
if (err) {
console.log('Your Jason has failed to get a complete string...');
} else {
console.log('Logged data: ', moment);
};
});
It appears that function tryParseJson(str) sometimes only gets some of the data and not the full JSON object. see code below,
function tryParseJson(str) {
try {
JSON.parse(str);
} catch (e) {
console.log("JSON error")
return false;
}
return JSON.parse(str);
I see that catch (e) gets called and my console.log("JSON error") gets printed.
I need some help to work out how to resolve this..
I did some changes to my code to check the contents of the const sensorData = tryParseJson(data) as shown below.
const sensorData = tryParseJson(data);
if (sensorData.temperature == undefined || sensorData.humidity == undefined){
//console.log('Temperature or Humidity is undefined');
} else {
and then used a IF statement to append or not append to the log.txt file.
Everything is now working, however there is still one minor issue.
I noticed something in the log.txt file. If the value of the temp or humidity is say 25.00, then the file will have 25. will no trailing zero's. This will not happen say if the temp is 25.4
if I check the values of sensorData in this line of code const sensorData = tryParseJson(data); the values are correct. They seem to change with fs.appendFile
Any idea why?

How to run a JavaScript solution from HackerRank on Idea / WebStorm IDE?

Say you want to run / debug a HackerRank solution locally on your WebStorm / IntelliJ Idea IDE for for macOS before submitting it. What are the needed steps, considering node.js is already installed in your machine?
Sample Hello.js file as below:
const fs = require('fs');
function processData(input) {
const ws = fs.createWriteStream(process.env.OUTPUT_PATH);
var i, result = "";
for (i = 0; i < parseInt(input); i++) {
result += 'Hello - ' + i + '\n';
}
ws.write(result + "\n");
ws.end();
}
process.stdin.resume();
process.stdin.setEncoding("ascii");
_input = "";
process.stdin.on("data", function (input) {
_input += input;
});
process.stdin.on("end", function () {
processData(_input);
});
On macOS Mojave the steps are:
On Preferences > Keymap, add a keyboard shortcut Ctrl+D to run the Other > Send EOF action; beware this may remove other actions associated to this shortcut, such as "Debug" (credits to this answer)
Add the Hello.js file to your project and open it in the editor
Enter Modify Run Configuration... dialog (Cmd+Shift+A`, type "modify ..." and select it)
make sure Node interpreter:, Working directory: and JavaScript file: are properly set
(if the solution writes output to a file) Set also the Environment variables: to OUTPUT_PATH=./hello.txt or as desired
Save it
Run the configuration. In the terminal pane that opens:
provide the needed input; e.g. 4, then Enter
press Ctrl+D to fire the "end" event
check the generated file hello.txt
You may want to use console.log() to help debugging; make sure it's commented out before submitting your solution back to HackerRank.
Run Configuration:
Run Tool Window:
Try this works on windows, you can run it using node here end event gets triggered when you hit ctrl+D just like hackerrank or Mac os
'use strict';
const { METHODS } = require('http');
const readline = require('readline')
process.stdin.resume();
process.stdin.setEncoding('utf-8');
readline.emitKeypressEvents(process.stdin);
let inputString = '';
let currentLine = 0;
process.stdin.setRawMode(false)
process.stdin.on('data', inputStdin => {
inputString += inputStdin;
});
process.stdin.on('keypress', (str, key) => {
if (key && key.ctrl && key.name == 'd'){
inputString = inputString.trim().split('\n').map(string => {
return string.trim();
})
main();
}
});
function readLine() {
return inputString[currentLine++];
}
function method() {
}
function main() {
const n = parseInt(readLine().trim());
const arr = readLine().replace(/\s+$/g, '').split(' ').map(qTemp =>parseInt(qTemp,10))
method();
}

How to execute local bash code from VSCode extension

I am creating an extension for simple git commands, and when a user enters a command in the Command Palette, like Init, I want to call git init on their current directory.
Unfortunately, there is no documentation on executing code locally with the VSCode extensions API. Is there any way to do this?
Yes, this is possible, by using child_process.spawn. I have used it in my extension to run a Java jar. The core of the execution is shown here:
let spawnOptions = { cwd: options.baseDir ? options.baseDir : undefined };
let java = child_process.spawn("java", parameters, spawnOptions);
let buffer = "";
java.stderr.on("data", (data) => {
let text = data.toString();
if (text.startsWith("Picked up _JAVA_OPTIONS:")) {
let endOfInfo = text.indexOf("\n");
if (endOfInfo == -1) {
text = "";
} else {
text = text.substr(endOfInfo + 1, text.length);
}
}
if (text.length > 0) {
buffer += "\n" + text;
}
});
java.on("close", (code) => {
// Handle the result + errors (i.e. the text in "buffer") here.
}

Two Node.JS scripts read/write on a single .JSON file but the first script cant modify the file

I have two discord bots(app.js and activity.js) running in Node.JS on a Ubuntu server. The problem i am facing is that when both of them are running, only the activity.js is able to modify the file. The file is users.JSON . Code of the app.js:
const Discord = require("discord.js")
var moment = require("moment")
var data_users = fs.readFileSync('/home/discord/activity_bot/users.json', 'utf-8')
var arxeio = JSON.parse(data_users)
...
for (var i in duos) {
if (arxeio[duos[i].username]) {
console.log(`before: ` + arxeio[duos[i].username])
arxeio[duos[i].username]+=15
console.log(`after: ` + arxeio[duos[i].username])
} else {
arxeio[duos[i].username]=15
}
}
fs.writeFile('/home/discord/activity_bot/users.json', JSON.stringify(arxeio, null, 2), 'utf-8', function(err) {
if (err) throw err
console.log('entered')
})
And the code for the Activity.js is:
const Discord = require("discord.js");
var fs = require('fs');
var data = fs.readFileSync('/home/discord/activity_bot/users.json', 'utf-8')
var arxeio = JSON.parse(data)
...
var kuklos = setInterval(function(done) {
client.guilds.get('323921290543235073').channels.forEach(function(kanali, kanaliID) {
if (kanali.type === 'voice' && !kanali.name.includes("AFK")) {
kanali.members.forEach(function(melos, melosID) {
let xristis = melos.user.username;
if (arxeio[xristis]) {
arxeio[xristis]++;
} else {
arxeio[xristis] = 1
}
fs.writeFile('/home/discord/activity_bot/users.json', JSON.stringify(arxeio, null, 2), 'utf-8', function(err) {
if (err) throw err
})
})
}
})
}, 60*1000);
Where, duos is a table of members.
I have concluded that the problem is the fs.writeFile in the App.js because when activity.js is not running it works. When activity.js is runnning "entered" is indeed logged in the app.js but the file is not modified. Also both commands above and below the += command show it is modified but not saved in the users.Json file. Any idea what is to blame? (except for my skillz :P )
I think that the problem is in your app design. You can absolutely share a file with two processes, but you'll always have concurrency problems.
For these kind of things you have to use a database that locks rows/tables.

Expose file writing to a webpage with a Firefox extension

I have a web application that my client uses for the cash registry.
What I need to do is to create a local file as the cash register's software needs to read from that file in order to print.
Until now i was using this code:
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var file = Components.classes["#mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(filePath);
Unfortunately with the latest version of firefox this isn't working anymore so I was told that i need and add-on to create the file.I've tried to develop an add-on(don't know if succesfully) and i have main.js looking like this :
var FileManager =
{
Write:
function (File, Text)
{
if (!File) return;
const unicodeConverter = Components.classes["#mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
unicodeConverter.charset = "UTF-8";
Text = unicodeConverter.ConvertFromUnicode(Text);
const os = Components.classes["#mozilla.org/network/file-output-stream;1"]
.createInstance(Components.interfaces.nsIFileOutputStream);
os.init(File, 0x02 | 0x08 | 0x20, 0700, 0);
os.write(Text, Text.length);
os.close();
},
Read:
function (File)
{
if (!File) return;
var res;
const is = Components.classes["#mozilla.org/network/file-input-stream;1"]
.createInstance(Components.interfaces.nsIFileInputStream);
const sis = Components.classes["#mozilla.org/scriptableinputstream;1"]
.createInstance(Components.interfaces.nsIScriptableInputStream);
is.init(File, 0x01, 0400, null);
sis.init(is);
res = sis.read(sis.available());
is.close();
return res;
},
};
Any ideas how should I use main.js?Where I find it after the add-on is installed?
I need to use something like this : FileManager.Write(path,text).
Sorry about the super-late reply.
If I understand your question correctly, you have a P.O.S application that runs in Firefox talking to some sort of local webserver via HTTP. The client-side JavaScript of your application needs to be able to read & write files from the local filesystem of the browser's PC.
If that's correct, then you can do so as follows. You'll need to create a Firefox addon, the simpliest kind of which is called a "bootstrapped" (or "restartless") addon.
A restartless addon consists of two files:
bootstrap.js (The JavaScript file containing your 'privileged' code)
install.rdf (an XML file describing your addon to Firefrox)
To build the addon, simply place both files inside the top-level (no folders!) of a ZIP file with the file extension .xpi. To install the addon, navigate to about:addons then from the tools menu, click Install from file, find your XPI, open it, then after a short delay choose Install.
In install.rdf put something like this:
<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>youraddonname#yourdomain</em:id>
<em:type>2</em:type>
<em:name>Name of your addon</em:name>
<em:version>1.0</em:version>
<em:bootstrap>true</em:bootstrap>
<em:description>Describe your addon.</em:description>
<em:creator>Your name</em:creator>
<!-- Firefox Desktop -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>4.0.*</em:minVersion>
<em:maxVersion>29.0.*</em:maxVersion>
</Description>
</em:targetApplication>
</Description>
</RDF>
You need to implement two mandatory JavaScript functions in the bootstrap.js:
startup() - called when you install the addon, and when your browser starts up.
shutdown() - called when you uninstall the addon, and when your browser shuts down.
You should call the rest of your 'privileged' code in startup(). For hygiene, you can (and probably should) also implement install() and uninstall() functions.
Start by implementing the following code in bootstrap.js:
const Cc = Components.classes;
const Ci = Components.interfaces;
let consoleService = Cc["#mozilla.org/consoleservice;1"]
.getService(Ci.nsIConsoleService);
let wm = Cc["#mozilla.org/appshell/window-mediator;1"]
.getService(Ci.nsIWindowMediator);
function LOG(msg) {
consoleService.logStringMessage("EXTENSION: "+msg);
}
function startup() {
try {
LOG("starting up...");
let windows = wm.getEnumerator("navigator:browser");
while (windows.hasMoreElements()) {
let chromeWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
WindowListener.setupBrowserUI(chromeWindow);
}
wm.addListener(WindowListener);
LOG("done startup.");
} catch (e) {
LOG("error starting up: "+e);
}
}
function shutdown() {
try {
LOG("shutting down...");
let windows = wm.getEnumerator("navigator:browser");
while (windows.hasMoreElements()) {
let chromeWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
WindowListener.tearDownBrowserUI(chromeWindow);
}
wm.addListener(WindowListener);
LOG("done shutdown.");
} catch (e) {
LOG("error shutting down: "+e);
}
}
Basically, that calls WindowListener.setupBrowserUI() for each current & future window of your web-browser. WindowListener is defined as follows:
var WindowListener = {
setupBrowserUI: function(chromeWindow) {
chromeWindow.gBrowser.addEventListener('load', my_load_handler, true);
},
tearDownBrowserUI: function(chromeWindow) {
chromeWindow.gBrowser.removeEventListener('load', my_load_handler, true);
},
onOpenWindow: function(xulWindow) {
let chromeWindow = xulWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
chromeWindow.addEventListener("load", function listener() {
chromeWindow.removeEventListener("load", listener, false);
var domDocument = chromeWindow.document.documentElement;
var windowType = domDocument.getAttribute("windowtype");
if (windowType == "navigator:browser")
WindowListener.setupBrowserUI(chromeWindow);
}, false);
},
onCloseWindow: function(chromeWindow) { },
onWindowTitleChange: function(chromeWindow, newTitle) { }
};
That sets up an event listener for the OpenWindow event, and in turn installs an event listener for load events in the TabBrowser of each ChromeWindow. The load event handler is defined as:
var my_load_handler = function (evt) {
try {
var browserEnumerator = wm.getEnumerator("navigator:browser");
while (browserEnumerator.hasMoreElements()) {
var browserWin = browserEnumerator.getNext();
var tabbrowser = browserWin.gBrowser;
var numTabs = tabbrowser.browsers.length;
for (var index = 0; index < numTabs; index++) {
var currentBrowser = tabbrowser.getBrowserAtIndex(index);
var domWindow = currentBrowser.contentWindow.wrappedJSObject;
// identify your target page(s)...
if (domWindow.location.href == 'http://yourserver/yourpage') {
// install the privileged methods (if not already there)
if (!domWindow.hasOwnProperty('__my_priv_members__') {
install_my_privileged_methods(browserWin, domWindow);
}
}
}
}
} catch (e) {
LOG(e);
}
}
That targets the correct pages (by checking the window.location.href and calls install_my_privileged_methods on their window object, which is defined as:
function install_my_privileged_methods(chromeWindow, domWindow) {
install_privileged_method(chromeWindow, domWindow, 'WriteFile',
function(priv) {
return function(File, Text, cb) {
priv.call([File, Text], function(rstatus, rdata, rerror){
if (cb) cb(rstatus, rerror);
});
};
},
function (chromeWindow, args, cb) {
var [File, Text] = args;
if (!File) return cb(0, null, "need a filename");
try {
const unicodeConverter =
Cc["#mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Ci.nsIScriptableUnicodeConverter);
unicodeConverter.charset = "UTF-8";
Text = unicodeConverter.ConvertFromUnicode(Text);
const os = Cc["#mozilla.org/network/file-output-stream;1"]
.createInstance(Ci.nsIFileOutputStream);
os.init(File, 0x02 | 0x08 | 0x20, 0700, 0);
os.write(Text, Text.length);
os.close();
cb(1, null, null);
} catch (e) {
cb(0, null, "error writing file: "+e);
}
}
);
install_privileged_method(chromeWindow, domWindow, 'ReadFile',
function(priv) {
return function(File, cb) {
priv.call([File], function(rstatus, rdata, rerror){
if (cb) cb(rstatus, rdata, rerror);
});
};
},
function (chromeWindow, args, cb) {
var [File] = args;
if (!File) return cb(0, null, "need a filename");
try {
const is = Cc["#mozilla.org/network/file-input-stream;1"]
.createInstance(Ci.nsIFileInputStream);
const sis = Cc["#mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
is.init(File, 0x01, 0400, null);
sis.init(is);
var Text = sis.read(sis.available());
is.close();
cb(1, Text, null);
} catch (e) {
cb(0, null, "error reading file: "+e);
}
}
);
}
I didn't test this code. It's a straigh-forward translation of what you wrote above... I'll assume that works!
That add two special methods, WriteFile & ReadFile, to the chosen window objects. In your web application's (unprivileged) JavaScript code use them like this:
var buffer = '...'; // the text to be written
window.WriteFile('C:\\path\\to\\file.txt', buffer, function(ok, errmsg) {
if (!ok) alert(errmsg);
});
window.ReadFile('C:\\path\\to\\file.txt', function(ok, buffer, errmsg) {
if (!ok) return alert(errmsg);
// use buffer here!
});
Finally, install_privileged_method is defined as:
var install_privileged_method = (function(){
var gensym = (function (){
var __sym = 0;
return function () { return '__sym_'+(__sym++); }
})();
return function (chromeWindow, target, slot, handler, methodFactory) {
try {
target.__pmcache__ = target.hasOwnProperty('__pmcache__')
? target.__pmcache__
: { ticket_no: 0, callbacks: {}, namespace: gensym() };
target[slot] = methodFactory({ call: function(fargs, fcb) {
try {
var ticket_no = target.__pmcache__.ticket_no++;
target.__pmcache__.callbacks[ticket_no] = fcb;
var cevent = target.document.createEvent("CustomEvent");
cevent.initCustomEvent(
target.__pmcache__.namespace+'.'+slot,
true, true, { fargs: fargs, ticket_no: ticket_no }
);
target.dispatchEvent(cevent);
} catch (ue) {
fcb(0, null, 'untrusted dispatcher error: '+ue);
}
}});
LOG("installed untrusted dispatcher for method '"+slot+"'.");
target.addEventListener(
target.__pmcache__.namespace+'.'+slot,
function(cevent){
var ticket_no = cevent.detail.ticket_no;
var fargs = cevent.detail.fargs;
var fcb = target.__pmcache__.callbacks[ticket_no];
try {
handler(chromeWindow, fargs, fcb);
} catch (pe) {
fcb(0, null, 'privileged handler error: '+pe);
}
},
false,
true
);
LOG("installed privileged handler for method '"+slot+"'.");
} catch (ie) {
LOG("ERROR installing handler/factory for privileged "+
"method '"+slot+"': "+ie);
}
};
})();

Categories