-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.js
77 lines (66 loc) · 1.85 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
const express = require('express');
const path = require('node:path');
const crypto = require('node:crypto');
function uuid() {
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
(
c ^
(crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
).toString(16)
);
}
class BrowserExec {
constructor(port, host = '', debug = false) {
this.host = host;
this.port = port;
this.debug = debug;
this.app = express();
require('express-ws')(this.app);
this.ws = null;
this.connected = false;
this.results = {};
this.app.get('/', (req, res, next) => {
if (this.debug) console.log('GET /');
res.sendFile(path.join(path.join(__dirname, ''), 'index.html'));
});
this.app.ws('/', (ws, req) => {
if (this.debug) console.log('Connected!');
this.ws = ws;
this.connected = true;
this.onConnect();
this.ws.on('message', (msg) => {
const data = JSON.parse(msg);
if (data.event === 'result') this.results[data.id] = data;
});
});
}
listen() {
if (this.debug)
console.log(
`[+] listening on ${!!this.host ? 'http://' + this.host + ':' : ''}${
this.port
}`
);
this.app.listen(this.port);
}
onConnect() {}
exec(code) {
return new Promise((resolve, reject) => {
const id = uuid();
if (this.debug) console.log(`[+] Executing in browser (${id})`);
this.ws.send(JSON.stringify({ exec: code, id: id }));
const checkIfDone = () => {
if (this.results[id]) {
const res = this.results[id];
delete this.results[id];
if (res.result === 'error') reject(res.error);
resolve(res.result);
} else {
setTimeout(checkIfDone, 100);
}
};
checkIfDone();
});
}
}
module.exports = BrowserExec;