A method for replacing old ActiveX which is no longer supported in IE.
General approach: Install a daemon on the desktop and use a Websocket to communicate between a page and the server in order to launch local commands.
Beware of the potential risks of this method because we open a breach on the PC but we can still control the level of risk.
ie: Because a malicious js code could call the websocket, I would advise to improve this prototype by adding a token (One-Time Password) which will be shared between the server and the genuine page.
Never allow to send directly a windows/DOS command !
In the following case, the dameon is implemented in node.js
- Install Node.js
- Install modules for webSocket, FileSystem and Node Commands (ws, fs and node-cmd)
- Write the js script server which will listen for the commands to be executed
- Write the js script to be included in the html page. The js will send requests through a websocket.
Code of the Node.js server
// ------------------------------------------------------------------ // serverws.js // v0.1 // GPM FACTORY // Nov 2023 // // Websocket server used for creating files and // triggering a limited set of OS commands // usage : node serversws.js // ------------------------------------------------------------------ const WebSocket = require('ws') const fs = require('fs'); const nodeCmd = require('node-cmd') let content let fidir = '' const LOG = 1 // 1= Yes, 0= No const PORT = '8088' const U_DIR = 'C:/_main/Projets/chronoA/out/' const C_DIR = 'C:/_main/Projets/chronoB/out/' const C1 = 'DIR' // 'C:/temp/print_acrobat.cmd' //const ss = require('stream-string') // not needed const wss = new WebSocket.Server({ port: PORT }) // Each message from client is structured as : // For a file: // #<FILE_TYPE>#<FILE_NAME>#<CONTENT> // with <FILE_TYPE> = U or C // For an OS command: // !<COMMAND_NUMBER> wss.on('connection', ws => { ws.on('message', function message(data) { content = '' + data if (content.substring(0,1) == '#') { // it's a file content // we must detect the type of content let fity = content.substring(1,2) if (fity == 'U'){ fidir = U_DIR } if (fity == 'C'){ fidir = C_DIR } let nend = content.indexOf("#",3) let finame = content.substring(3,nend) if (LOG == 1) { console.log("file name=" + finame) } let writeStream = fs.createWriteStream(fidir+finame) writeStream.write(content.substr(nend+1)) writeStream.end() ws.send('File has been created') } if (content.substring(0,1) == '!') { // it's a command // we avoid to pass an arbitrary command because potential securiy issues. Instead, we pass a command type (!TBD) cmd = content.substring(1) if (LOG == 1) { console.log("commande="+ cmd) } if (cmd == '1') { nodeCmd.run(C1, (err, data, stderr) => console.log(data)); } else { ws.send('Unknown command') } } if (LOG == 1) { console.log('received: %s', data) } }); })
Code of the JS script in the HTML page
<SCRIPT LANGUAGE="JavaScript">
function makefile(){
var fso;var thefile;
ws.onopen = () => {
console.log('Send the chrono to ws');
finame = 'etiq-<?php echo $_GET["ord_id"]?>.csv';
// #C# means : CHRONO
msg = '#C#'+ finame + '#' + document.tags.chrono.value;
ws.send(msg)
}
ws.onmessage = (message) => {
alert (message.data);
console.log('message received', message.data)
}
// alert(\'Le fichier est crée.\');
}