{"id":5700,"date":"2024-03-09T15:51:46","date_gmt":"2024-03-09T14:51:46","guid":{"rendered":"https:\/\/gpmfactory.com\/?p=5700"},"modified":"2024-03-09T15:58:08","modified_gmt":"2024-03-09T14:58:08","slug":"call-host-commands-from-a-browser","status":"publish","type":"post","link":"https:\/\/gpmfactory.com\/index.php\/2024\/03\/09\/call-host-commands-from-a-browser\/","title":{"rendered":"Call Host commands from a browser"},"content":{"rendered":"\n<p>A method for replacing old ActiveX which is no longer supported in IE.<\/p>\n\n\n\n<p>General approach: Install a daemon on the desktop and use a <strong>Websocket<\/strong> to communicate between a page and the server in order to launch local commands.<\/p>\n\n\n\n<p>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. <br>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.  <br>Never allow to send directly a windows\/DOS command !<\/p>\n\n\n\n<p>In the following case, the dameon is implemented in node.js<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Install Node.js<\/li>\n\n\n\n<li>Install modules for webSocket, FileSystem and Node Commands (ws, fs and node-cmd)<\/li>\n\n\n\n<li>Write the js script server which will listen for the commands to be executed<\/li>\n\n\n\n<li>Write the js script to be included in the html page. The js will send requests through a websocket.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Code of the Node.js server<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/ ------------------------------------------------------------------\n\/\/ serverws.js\n\/\/ v0.1\n\/\/ GPM FACTORY\n\/\/ Nov 2023\n\/\/ \n\/\/ Websocket server used for creating files and \n\/\/ triggering a limited set of OS commands \n\/\/ usage : node serversws.js\n\/\/ ------------------------------------------------------------------\n\nconst WebSocket = require('ws')\nconst fs = require('fs');\nconst nodeCmd = require('node-cmd')\nlet content\nlet fidir = ''\nconst LOG = 1       \/\/ 1= Yes, 0= No\nconst PORT = '8088'\nconst U_DIR = 'C:\/_main\/Projets\/chronoA\/out\/'  \nconst C_DIR = 'C:\/_main\/Projets\/chronoB\/out\/'      \nconst C1 = 'DIR'   \/\/ 'C:\/temp\/print_acrobat.cmd'\n\/\/const ss = require('stream-string')  \/\/ not needed\nconst wss = new WebSocket.Server({ port: PORT })\n\n\/\/ Each message from client is structured as :\n\/\/ For a file:\n\/\/   #&lt;FILE_TYPE>#&lt;FILE_NAME>#&lt;CONTENT>\n\/\/   with &lt;FILE_TYPE> = U or C\n\/\/ For an OS command:\n\/\/  !&lt;COMMAND_NUMBER>\n\nwss.on('connection', ws => {\n       \n    ws.on('message', function message(data) {\n        content = '' + data\n        if (content.substring(0,1) == '#') {\n            \/\/ it's a file content\n            \/\/ we must detect the type of content \n            let fity = content.substring(1,2)\n            \n            if (fity == 'U'){        \n\n                fidir = U_DIR\n               }\n            if (fity == 'C'){       \n\n                fidir = C_DIR\n            }   \n\n            let nend = content.indexOf(\"#\",3)\n            \n            let finame = content.substring(3,nend)\n            if (LOG == 1) {\n                console.log(\"file name=\" + finame)\n            }\n            let writeStream = fs.createWriteStream(fidir+finame) \n            writeStream.write(content.substr(nend+1))\n            writeStream.end() \n            ws.send('File has been created')\n        }\n        if (content.substring(0,1) == '!') {\n            \/\/ it's a command\n            \/\/ we avoid to pass an arbitrary command because potential securiy issues. Instead, we pass a command type (!TBD)\n            cmd = content.substring(1)\n            if (LOG == 1) {\n                console.log(\"commande=\"+ cmd)\n            }\n            if (cmd == '1') {\n                nodeCmd.run(C1, (err, data, stderr) => console.log(data));\n            }\n            else {\n                ws.send('Unknown command')\n            }\n         }\n        if (LOG == 1) {\n            console.log('received: %s', data)\n        }\n    });    \n\n\n})<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Code of the JS script in the HTML page<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;SCRIPT LANGUAGE=\"JavaScript\"&gt;\n\tfunction makefile(){\n\t\tvar fso;var thefile;\n\n\n    ws.onopen = () =&gt; {\n      console.log('Send the chrono to ws');\n\n       finame = 'etiq-&lt;?php echo $_GET&#91;\"ord_id\"]?&gt;.csv'; \n        \/\/ #C# means : CHRONO\n      msg = '#C#'+ finame + '#' + document.tags.chrono.value;\n      ws.send(msg)\n    }\n    \n    ws.onmessage = (message) =&gt; {\n        alert (message.data);\n        console.log('message received', message.data)\n    }\n    \n\/\/    alert(\\'Le fichier est cr\u00e9e.\\');\t\n}\n<\/code><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A method for replacing old ActiveX which is no longer supported in IE. General approach: Install a daemon on the desktop and use a&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"ppma_author":[150],"class_list":["post-5700","post","type-post","status-publish","format-standard","hentry","category-non-classe"],"authors":[{"term_id":150,"user_id":1,"is_guest":0,"slug":"admin8700","display_name":"Patrick","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/209d5ed69b74d288390621ab4c1d3773?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/posts\/5700","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/comments?post=5700"}],"version-history":[{"count":4,"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/posts\/5700\/revisions"}],"predecessor-version":[{"id":5705,"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/posts\/5700\/revisions\/5705"}],"wp:attachment":[{"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/media?parent=5700"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/categories?post=5700"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/tags?post=5700"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/gpmfactory.com\/index.php\/wp-json\/wp\/v2\/ppma_author?post=5700"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}