UNPKG

wifi-setup

Version:

WiFi AP setup, particularly useful for IoT devices

357 lines (356 loc) 55.3 kB
"use strict"; var exec = require('child_process').exec; var fs = require('fs'); var utils_1 = require('./utils'); var network_type_1 = require('../types/network.type'); var Promise = require('bluebird'); Promise.onPossiblyUnhandledRejection(function (error) { throw error; }); function camelize(str) { if (str.includes(' ')) { return str.replace(/(?:^\w|[A-Z]|\b\w)/g, function (letter, index) { return index == 0 ? letter.toLowerCase() : letter.toUpperCase(); }).replace(/\s+/g, ''); } else { return str.toLowerCase(); } } var noSudoMessage = "The wifi-setup module requires root permissions in order to modify system config files.\n\n Please try running node as root"; module.exports = function () { var wifi = { init: function () { return new Promise(function (resolve) { resolve(); }); }, stop: function () { return new Promise(function (resolve) { wifi.accessPoint.down(); resolve(); }); }, accessPoint: { status: 'down', up: function (SSID, password) { return new Promise(function (resolve, reject) { console.log('Turning AP on'); console.log("SSID: " + SSID); console.log("password: " + password); if (wifi.client.status !== 'down') { resolve(); } else { wifi.configFiles.all.setAP(SSID, password).then(function () { exec('/etc/init.d/hostapd restart', function (err, stdout) { if (err) { if (err.message.indexOf('Access denied') > -1) { console.log(noSudoMessage); } else { console.log(err); } reject(err); } else { console.log(stdout); if (stdout.indexOf('Restarting hostapd') > -1) { exec('ifdown wlan0 && ifup wlan0', function () { wifi.accessPoint.status = 'up'; resolve({ SSID: SSID, password: password }); }); } else { wifi.accessPoint.status = 'down'; reject(); } } }); }); } }); }, down: function () { return new Promise(function (resolve, reject) { console.log('Turning AP off'); exec('/etc/init.d/hostapd stop', function (err) { if (err) { if (err.message.indexOf('Access denied') > -1) { console.log(noSudoMessage); } else { console.log(err); } reject(); } else { exec('ifdown wlan0', function () { console.log('WiFi AP stopped'); wifi.accessPoint.status = 'down'; resolve(); }); } }); }); } }, client: { status: 'down', connect: function (SSID, password) { return new Promise(function (resolve, reject) { console.log("Connecting to " + SSID); if (wifi.accessPoint.status !== 'down') { reject(); } else { wifi.configFiles.all.setClient(SSID, password).then(function () { exec('ifup wlan0', function (err, stdout) { if (err) { console.log(err); reject(err); } else { console.log(stdout); wifi.client.status = 'connected'; resolve(stdout); } }); }); } }); }, disconnect: function () { return new Promise(function (resolve) { console.log('Disconnecting WiFi'); exec('ifdown wlan0', function (err) { if (err) { console.log(err); } }); wifi.client.status = 'down'; resolve(); }); } }, configFiles: { defaultHostapd: { path: '/etc/default/hostapd', setAP: function () { return new Promise(function (resolve, reject) { try { if (fs.readFileSync(wifi.configFiles.defaultHostapd.path).toString().indexOf('# wifi-setup config') === -1) { utils_1.Utils.backupFile(wifi.configFiles.defaultHostapd.path); } } catch (e) { } fs.readFile(__dirname + "/hostapd.fill", function (err, file) { var defaultHostapdConf = file.toString(); defaultHostapdConf = utils_1.Utils.replaceAll(defaultHostapdConf, '{{path}}', wifi.configFiles.hostapdConf.path); fs.writeFile(wifi.configFiles.defaultHostapd.path, defaultHostapdConf, function (err) { if (err) { reject(err); } else { resolve(); } }); }); }); }, setClient: function () { return new Promise(function (resolve) { utils_1.Utils.backupFile(wifi.configFiles.defaultHostapd.path + '.back', function (path) { return path.split('.back')[0]; }); resolve(); }); } }, hostapdConf: { path: '/etc/hostapd/hostapd.conf', setAP: function (SSID, password) { return new Promise(function (resolve, reject) { try { if (fs.readFileSync(wifi.configFiles.hostapdConf.path).toString().indexOf('# wifi-setup config') === -1) { utils_1.Utils.backupFile(wifi.configFiles.hostapdConf.path); } } catch (e) { } var getHostapdFile = new Promise(function (resolve, reject) { fs.readFile(__dirname + "/hostapd.conf.fill", function (err, file) { if (err) { reject(err); } else { resolve(file); } }); }); Promise.all([getHostapdFile, wifi.getDriver()]).then(function (results) { var file = results[0]; // let driver = results[1] || 'rtl871xdrv'; var driver = 'rtl871xdrv'; var hostapdConf = file.toString(); hostapdConf = utils_1.Utils.replaceAll(hostapdConf, '{{SSID}}', SSID); hostapdConf = utils_1.Utils.replaceAll(hostapdConf, '{{password}}', password); hostapdConf = utils_1.Utils.replaceAll(hostapdConf, '{{driver}}', driver); fs.writeFile(wifi.configFiles.hostapdConf.path, hostapdConf, function (err) { if (err) { reject(err); } else { resolve(); } }); }); }); }, setClient: function () { return new Promise(function (resolve) { utils_1.Utils.backupFile(wifi.configFiles.hostapdConf.path + '.back', function (path) { return path.split('.back')[0]; }); resolve(); }); } }, interfaces: { path: '/etc/network/interfaces', setAP: function () { return new Promise(function (resolve, reject) { try { if (fs.readFileSync(wifi.configFiles.interfaces.path).toString().indexOf('# wifi-setup config') === -1) { utils_1.Utils.backupFile(wifi.configFiles.interfaces.path); } } catch (e) { } fs.readFile(__dirname + "/interfaces.ap.fill", function (err, file) { var interfaces = file.toString(); interfaces = utils_1.Utils.replaceAll(interfaces, '{{IP}}', '192.168.42.1'); interfaces = utils_1.Utils.replaceAll(interfaces, '{{hostapd}}', wifi.configFiles.hostapdConf.path); fs.writeFile(wifi.configFiles.interfaces.path, interfaces, function (err) { if (err) { reject(err); } else { resolve(); } }); }); }); }, setClient: function (SSID, password) { return new Promise(function (resolve, reject) { try { if (fs.readFileSync(wifi.configFiles.interfaces.path).toString().indexOf('# wifi-setup config') === -1) { utils_1.Utils.backupFile(wifi.configFiles.interfaces.path); } } catch (e) { } fs.readFile(__dirname + "/interfaces.client.fill", function (err, file) { var interfaces = file.toString(); interfaces = utils_1.Utils.replaceAll(interfaces, '{{SSID}}', SSID); interfaces = utils_1.Utils.replaceAll(interfaces, '{{password}}', password); fs.writeFile(wifi.configFiles.interfaces.path, interfaces, function (err) { if (err) { reject(err); } else { resolve(); } }); }); }); } }, all: { setAP: function (SSID, password) { return new Promise(function (resolve, reject) { Promise.all([ wifi.configFiles.defaultHostapd.setAP(), wifi.configFiles.hostapdConf.setAP(SSID, password), wifi.configFiles.interfaces.setAP() ]).then(function (results) { resolve(results); }).catch(function (errs) { console.log(JSON.stringify(errs)); if (errs.code === 'EACCES') { console.log(noSudoMessage); } reject(errs); }); }); }, setClient: function (SSID, password) { return new Promise(function (resolve, reject) { Promise.all([ wifi.configFiles.defaultHostapd.setClient(), wifi.configFiles.hostapdConf.setClient(), wifi.configFiles.interfaces.setClient(SSID, password) ]).then(function (results) { resolve(results); }).catch(function (errs) { if (errs.code === 'EACCES') { console.log(noSudoMessage); } reject(errs); }); }); } } }, getDriver: function () { return new Promise(function (resolve, reject) { exec('basename $( readlink /sys/class/net/wlan0/device/driver )', function (err, stdout) { if (err) { reject(err); } else { resolve(stdout); } }); }); }, scan: function () { return new Promise(function (resolve, reject) { exec('iwlist wlan0 scan', function (err, res) { if (err) { reject(err); } else { res = res.split('wlan0 Scan completed :\n')[1]; // Splitting long network list into one network per index var networks = res.split(/\s*Cell [0-9]{2,3} - /g); for (var i in networks) { // Splitting single network string into one key/value per line var splitNetwork = networks[i].split(/\n[\s]*/g); // console.log(splitNetwork); networks[i] = {}; for (var j in splitNetwork) { // Splitting key/value string on the first colon var keyVal = splitNetwork[j].replace(':', '\n'); keyVal = keyVal.split('\n'); if (keyVal[0] && keyVal[0] !== '' && keyVal[0] !== ' ' && keyVal[1]) { // Camel case ify key keyVal[0] = camelize(keyVal[0]); // Strip paranthesis from key keyVal[0] = keyVal[0].replace('(', ''); keyVal[0] = keyVal[0].replace(')', ''); // Stripping whitespace and double quotes from start and end of values keyVal[1] = keyVal[1].replace(/^[\s"]/, ''); keyVal[1] = keyVal[1].replace(/[\s"]$/, ''); networks[i][keyVal[0]] = keyVal[1]; networks[i] = new network_type_1.Network(networks[i]); } } } resolve(networks); } }); }); } }; return wifi; }; //# sourceMappingURL=data:application/json;base64,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ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBleGVjID0gcmVxdWlyZSgnY2hpbGRfcHJvY2VzcycpLmV4ZWM7XG5jb25zdCBmcyA9IHJlcXVpcmUoJ2ZzJyk7XG5pbXBvcnQge1V0aWxzfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7TmV0d29ya30gZnJvbSAnLi4vdHlwZXMvbmV0d29yay50eXBlJztcblxuaW1wb3J0ICogYXMgUHJvbWlzZSBmcm9tICdibHVlYmlyZCc7XG5Qcm9taXNlLm9uUG9zc2libHlVbmhhbmRsZWRSZWplY3Rpb24oKGVycm9yKSA9PiB7XG4gICAgdGhyb3cgZXJyb3I7XG59KTtcblxuZnVuY3Rpb24gY2FtZWxpemUgKHN0cikge1xuICAgIGlmIChzdHIuaW5jbHVkZXMoJyAnKSkge1xuICAgICAgICByZXR1cm4gc3RyLnJlcGxhY2UoLyg/Ol5cXHd8W0EtWl18XFxiXFx3KS9nLCBmdW5jdGlvbihsZXR0ZXIsIGluZGV4KSB7XG4gICAgICAgICAgICByZXR1cm4gaW5kZXggPT0gMCA/IGxldHRlci50b0xvd2VyQ2FzZSgpIDogbGV0dGVyLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgIH0pLnJlcGxhY2UoL1xccysvZywgJycpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBzdHIudG9Mb3dlckNhc2UoKTtcbiAgICB9XG59XG5cbnZhciBub1N1ZG9NZXNzYWdlID0gYFRoZSB3aWZpLXNldHVwIG1vZHVsZSByZXF1aXJlcyByb290IHBlcm1pc3Npb25zIGluIG9yZGVyIHRvIG1vZGlmeSBzeXN0ZW0gY29uZmlnIGZpbGVzLlxcblxuICAgIFBsZWFzZSB0cnkgcnVubmluZyBub2RlIGFzIHJvb3RgO1xuXG5tb2R1bGUuZXhwb3J0cyA9ICgpID0+IHtcbiAgICB2YXIgd2lmaSA9IHtcbiAgICAgICAgaW5pdDogKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIHN0b3A6ICgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgICAgIHdpZmkuYWNjZXNzUG9pbnQuZG93bigpO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuXG4gICAgICAgIGFjY2Vzc1BvaW50OiB7XG4gICAgICAgICAgICBzdGF0dXM6ICdkb3duJyxcbiAgICAgICAgICAgIHVwOiAoU1NJRCwgcGFzc3dvcmQpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnVHVybmluZyBBUCBvbicpO1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhgU1NJRDogJHtTU0lEfWApO1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhgcGFzc3dvcmQ6ICR7cGFzc3dvcmR9YCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3aWZpLmNsaWVudC5zdGF0dXMgIT09ICdkb3duJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2lmaS5jb25maWdGaWxlcy5hbGwuc2V0QVAoU1NJRCwgcGFzc3dvcmQpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4ZWMoJy9ldGMvaW5pdC5kL2hvc3RhcGQgcmVzdGFydCcsIChlcnIsIHN0ZG91dCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyLm1lc3NhZ2UuaW5kZXhPZignQWNjZXNzIGRlbmllZCcpID4gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhub1N1ZG9NZXNzYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coc3Rkb3V0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGRvdXQuaW5kZXhPZignUmVzdGFydGluZyBob3N0YXBkJykgPiAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4ZWMoJ2lmZG93biB3bGFuMCAmJiBpZnVwIHdsYW4wJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWZpLmFjY2Vzc1BvaW50LnN0YXR1cyA9ICd1cCc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoe1NTSUQ6IFNTSUQsIHBhc3N3b3JkOiBwYXNzd29yZH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWZpLmFjY2Vzc1BvaW50LnN0YXR1cyA9ICdkb3duJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkb3duOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1R1cm5pbmcgQVAgb2ZmJyk7XG4gICAgICAgICAgICAgICAgICAgIGV4ZWMoJy9ldGMvaW5pdC5kL2hvc3RhcGQgc3RvcCcsIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyLm1lc3NhZ2UuaW5kZXhPZignQWNjZXNzIGRlbmllZCcpID4gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2cobm9TdWRvTWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4ZWMoJ2lmZG93biB3bGFuMCcsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1dpRmkgQVAgc3RvcHBlZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWZpLmFjY2Vzc1BvaW50LnN0YXR1cyA9ICdkb3duJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgY2xpZW50OiB7XG4gICAgICAgICAgICBzdGF0dXM6ICdkb3duJyxcbiAgICAgICAgICAgIGNvbm5lY3Q6IChTU0lELCBwYXNzd29yZCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBDb25uZWN0aW5nIHRvICR7U1NJRH1gKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdpZmkuYWNjZXNzUG9pbnQuc3RhdHVzICE9PSAnZG93bicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2lmaS5jb25maWdGaWxlcy5hbGwuc2V0Q2xpZW50KFNTSUQsIHBhc3N3b3JkKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGVjKCdpZnVwIHdsYW4wJywgKGVyciwgc3Rkb3V0KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGVycik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHN0ZG91dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWZpLmNsaWVudC5zdGF0dXMgPSAnY29ubmVjdGVkJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoc3Rkb3V0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkaXNjb25uZWN0OiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdEaXNjb25uZWN0aW5nIFdpRmknKTtcbiAgICAgICAgICAgICAgICAgICAgZXhlYygnaWZkb3duIHdsYW4wJywgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGVycik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB3aWZpLmNsaWVudC5zdGF0dXMgPSAnZG93bic7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgY29uZmlnRmlsZXM6IHtcbiAgICAgICAgICAgIGRlZmF1bHRIb3N0YXBkOiB7XG4gICAgICAgICAgICAgICAgcGF0aDogJy9ldGMvZGVmYXVsdC9ob3N0YXBkJyxcbiAgICAgICAgICAgICAgICBzZXRBUDogKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnMucmVhZEZpbGVTeW5jKHdpZmkuY29uZmlnRmlsZXMuZGVmYXVsdEhvc3RhcGQucGF0aCkudG9TdHJpbmcoKS5pbmRleE9mKCcjIHdpZmktc2V0dXAgY29uZmlnJykgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFV0aWxzLmJhY2t1cEZpbGUod2lmaS5jb25maWdGaWxlcy5kZWZhdWx0SG9zdGFwZC5wYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBmcy5yZWFkRmlsZShgJHtfX2Rpcm5hbWV9L2hvc3RhcGQuZmlsbGAsIChlcnIsIGZpbGUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgZGVmYXVsdEhvc3RhcGRDb25mID0gZmlsZS50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHRIb3N0YXBkQ29uZiA9IFV0aWxzLnJlcGxhY2VBbGwoZGVmYXVsdEhvc3RhcGRDb25mLCAne3twYXRofX0nLCB3aWZpLmNvbmZpZ0ZpbGVzLmhvc3RhcGRDb25mLnBhdGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZzLndyaXRlRmlsZSh3aWZpLmNvbmZpZ0ZpbGVzLmRlZmF1bHRIb3N0YXBkLnBhdGgsIGRlZmF1bHRIb3N0YXBkQ29uZiwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc2V0Q2xpZW50OiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgVXRpbHMuYmFja3VwRmlsZSh3aWZpLmNvbmZpZ0ZpbGVzLmRlZmF1bHRIb3N0YXBkLnBhdGggKyAnLmJhY2snLCAocGF0aCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRoLnNwbGl0KCcuYmFjaycpWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBob3N0YXBkQ29uZjoge1xuICAgICAgICAgICAgICAgIHBhdGg6ICcvZXRjL2hvc3RhcGQvaG9zdGFwZC5jb25mJyxcbiAgICAgICAgICAgICAgICBzZXRBUDogKFNTSUQsIHBhc3N3b3JkKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcy5yZWFkRmlsZVN5bmMod2lmaS5jb25maWdGaWxlcy5ob3N0YXBkQ29uZi5wYXRoKS50b1N0cmluZygpLmluZGV4T2YoJyMgd2lmaS1zZXR1cCBjb25maWcnKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVXRpbHMuYmFja3VwRmlsZSh3aWZpLmNvbmZpZ0ZpbGVzLmhvc3RhcGRDb25mLnBhdGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBnZXRIb3N0YXBkRmlsZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcy5yZWFkRmlsZShgJHtfX2Rpcm5hbWV9L2hvc3RhcGQuY29uZi5maWxsYCwgKGVyciwgZmlsZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoZmlsZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgUHJvbWlzZS5hbGwoW2dldEhvc3RhcGRGaWxlLCB3aWZpLmdldERyaXZlcigpXSkudGhlbigocmVzdWx0cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmaWxlID0gcmVzdWx0c1swXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBsZXQgZHJpdmVyID0gcmVzdWx0c1sxXSB8fCAncnRsODcxeGRydic7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGRyaXZlciA9ICdydGw4NzF4ZHJ2JztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBob3N0YXBkQ29uZiA9IGZpbGUudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob3N0YXBkQ29uZiA9IFV0aWxzLnJlcGxhY2VBbGwoaG9zdGFwZENvbmYsICd7e1NTSUR9fScsIFNTSUQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvc3RhcGRDb25mID0gVXRpbHMucmVwbGFjZUFsbChob3N0YXBkQ29uZiwgJ3t7cGFzc3dvcmR9fScsIHBhc3N3b3JkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob3N0YXBkQ29uZiA9IFV0aWxzLnJlcGxhY2VBbGwoaG9zdGFwZENvbmYsICd7e2RyaXZlcn19JywgZHJpdmVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcy53cml0ZUZpbGUod2lmaS5jb25maWdGaWxlcy5ob3N0YXBkQ29uZi5wYXRoLCBob3N0YXBkQ29uZiwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc2V0Q2xpZW50OiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgVXRpbHMuYmFja3VwRmlsZSh3aWZpLmNvbmZpZ0ZpbGVzLmhvc3RhcGRDb25mLnBhdGggKyAnLmJhY2snLCAocGF0aCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRoLnNwbGl0KCcuYmFjaycpWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpbnRlcmZhY2VzOiB7XG4gICAgICAgICAgICAgICAgcGF0aDogJy9ldGMvbmV0d29yay9pbnRlcmZhY2VzJyxcbiAgICAgICAgICAgICAgICBzZXRBUDogKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnMucmVhZEZpbGVTeW5jKHdpZmkuY29uZmlnRmlsZXMuaW50ZXJmYWNlcy5wYXRoKS50b1N0cmluZygpLmluZGV4T2YoJyMgd2lmaS1zZXR1cCBjb25maWcnKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVXRpbHMuYmFja3VwRmlsZSh3aWZpLmNvbmZpZ0ZpbGVzLmludGVyZmFjZXMucGF0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge31cblxuICAgICAgICAgICAgICAgICAgICAgICAgZnMucmVhZEZpbGUoYCR7X19kaXJuYW1lfS9pbnRlcmZhY2VzLmFwLmZpbGxgLCAoZXJyLCBmaWxlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGludGVyZmFjZXMgPSBmaWxlLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJmYWNlcyA9IFV0aWxzLnJlcGxhY2VBbGwoaW50ZXJmYWNlcywgJ3t7SVB9fScsICcxOTIuMTY4LjQyLjEnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcmZhY2VzID0gVXRpbHMucmVwbGFjZUFsbChpbnRlcmZhY2VzLCAne3tob3N0YXBkfX0nLCB3aWZpLmNvbmZpZ0ZpbGVzLmhvc3RhcGRDb25mLnBhdGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZzLndyaXRlRmlsZSh3aWZpLmNvbmZpZ0ZpbGVzLmludGVyZmFjZXMucGF0aCwgaW50ZXJmYWNlcywgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc2V0Q2xpZW50OiAoU1NJRCwgcGFzc3dvcmQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZzLnJlYWRGaWxlU3luYyh3aWZpLmNvbmZpZ0ZpbGVzLmludGVyZmFjZXMucGF0aCkudG9TdHJpbmcoKS5pbmRleE9mKCcjIHdpZmktc2V0dXAgY29uZmlnJykgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFV0aWxzLmJhY2t1cEZpbGUod2lmaS5jb25maWdGaWxlcy5pbnRlcmZhY2VzLnBhdGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZzLnJlYWRGaWxlKGAke19fZGlybmFtZX0vaW50ZXJmYWNlcy5jbGllbnQuZmlsbGAsIChlcnIsIGZpbGUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaW50ZXJmYWNlcyA9IGZpbGUudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcmZhY2VzID0gVXRpbHMucmVwbGFjZUFsbChpbnRlcmZhY2VzLCAne3tTU0lEfX0nLCBTU0lEKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcmZhY2VzID0gVXRpbHMucmVwbGFjZUFsbChpbnRlcmZhY2VzLCAne3twYXNzd29yZH19JywgcGFzc3dvcmQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZzLndyaXRlRmlsZSh3aWZpLmNvbmZpZ0ZpbGVzLmludGVyZmFjZXMucGF0aCwgaW50ZXJmYWNlcywgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBhbGw6IHtcbiAgICAgICAgICAgICAgICBzZXRBUDogKFNTSUQsIHBhc3N3b3JkKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBQcm9taXNlLmFsbChbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lmaS5jb25maWdGaWxlcy5kZWZhdWx0SG9zdGFwZC5zZXRBUCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZmkuY29uZmlnRmlsZXMuaG9zdGFwZENvbmYuc2V0QVAoU1NJRCwgcGFzc3dvcmQpLFxuICAgICA