UNPKG

appium-doctor

Version:

Test environment for fitness to run Appium

507 lines (391 loc) 26.8 kB
'use strict'; var _get = require('babel-runtime/helpers/get')['default']; var _inherits = require('babel-runtime/helpers/inherits')['default']; var _createClass = require('babel-runtime/helpers/create-class')['default']; var _classCallCheck = require('babel-runtime/helpers/class-call-check')['default']; var _regeneratorRuntime = require('babel-runtime/regenerator')['default']; var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; Object.defineProperty(exports, '__esModule', { value: true }); var _utils = require('./utils'); var _appiumSupport = require('appium-support'); var _teen_process = require('teen_process'); var _doctor = require('./doctor'); var _logger = require('./logger'); var _logger2 = _interopRequireDefault(_logger); var _nodeDetector = require('./node-detector'); var _nodeDetector2 = _interopRequireDefault(_nodeDetector); var _prompt = require('./prompt'); var _env = require('./env'); var _env2 = _interopRequireDefault(_env); var checks = []; var fixes = {}; // Check for Xcode. var XcodeCheck = (function (_DoctorCheck) { _inherits(XcodeCheck, _DoctorCheck); function XcodeCheck() { _classCallCheck(this, XcodeCheck); _get(Object.getPrototypeOf(XcodeCheck.prototype), 'constructor', this).apply(this, arguments); } _createClass(XcodeCheck, [{ key: 'diagnose', value: function diagnose() { var xcodePath, _ref, stdout; return _regeneratorRuntime.async(function diagnose$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: xcodePath = undefined; context$2$0.prev = 1; context$2$0.next = 4; return _regeneratorRuntime.awrap((0, _teen_process.exec)('xcode-select', ['--print-path'])); case 4: _ref = context$2$0.sent; stdout = _ref.stdout; xcodePath = (stdout || '').replace("\n", ""); context$2$0.next = 12; break; case 9: context$2$0.prev = 9; context$2$0.t0 = context$2$0['catch'](1); return context$2$0.abrupt('return', (0, _utils.nok)('Xcode is NOT installed!')); case 12: context$2$0.t1 = xcodePath; if (!context$2$0.t1) { context$2$0.next = 17; break; } context$2$0.next = 16; return _regeneratorRuntime.awrap(_appiumSupport.fs.exists(xcodePath)); case 16: context$2$0.t1 = context$2$0.sent; case 17: if (!context$2$0.t1) { context$2$0.next = 21; break; } context$2$0.t2 = (0, _utils.ok)('Xcode is installed at: ' + xcodePath); context$2$0.next = 22; break; case 21: context$2$0.t2 = (0, _utils.nok)('Xcode cannot be found at \'' + xcodePath + '\'!'); case 22: return context$2$0.abrupt('return', context$2$0.t2); case 23: case 'end': return context$2$0.stop(); } }, null, this, [[1, 9]]); } }, { key: 'fix', value: function fix() { return _regeneratorRuntime.async(function fix$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: return context$2$0.abrupt('return', 'Manually install Xcode.'); case 1: case 'end': return context$2$0.stop(); } }, null, this); } }]); return XcodeCheck; })(_doctor.DoctorCheck); checks.push(new XcodeCheck()); // Check for Xcode Command Line Tools. var XcodeCmdLineToolsCheck = (function (_DoctorCheck2) { _inherits(XcodeCmdLineToolsCheck, _DoctorCheck2); function XcodeCmdLineToolsCheck() { _classCallCheck(this, XcodeCmdLineToolsCheck); _get(Object.getPrototypeOf(XcodeCmdLineToolsCheck.prototype), 'constructor', this).call(this, { autofix: true }); } _createClass(XcodeCmdLineToolsCheck, [{ key: 'diagnose', value: function diagnose() { var errMess, pkgName, stdout; return _regeneratorRuntime.async(function diagnose$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: errMess = 'Xcode Command Line Tools are NOT installed!'; context$2$0.next = 3; return _regeneratorRuntime.awrap(_appiumSupport.system.macOsxVersion()); case 3: context$2$0.t0 = context$2$0.sent; if (!(context$2$0.t0 === '10.8')) { context$2$0.next = 8; break; } context$2$0.t1 = 'com.apple.pkg.DeveloperToolsCLI'; context$2$0.next = 9; break; case 8: context$2$0.t1 = 'com.apple.pkg.CLTools_Executables'; case 9: pkgName = context$2$0.t1; stdout = undefined; context$2$0.prev = 11; context$2$0.next = 14; return _regeneratorRuntime.awrap((0, _teen_process.exec)('pkgutil', ['--pkg-info=' + pkgName])); case 14: stdout = context$2$0.sent.stdout; context$2$0.next = 21; break; case 17: context$2$0.prev = 17; context$2$0.t2 = context$2$0['catch'](11); _logger2['default'].debug(context$2$0.t2); return context$2$0.abrupt('return', (0, _utils.nok)(errMess)); case 21: return context$2$0.abrupt('return', stdout.match(/install-time/) ? (0, _utils.ok)('Xcode Command Line Tools are installed.') : (0, _utils.nok)(errMess)); case 22: case 'end': return context$2$0.stop(); } }, null, this, [[11, 17]]); } }, { key: 'fix', value: function fix() { var yesno; return _regeneratorRuntime.async(function fix$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: _logger2['default'].info('The following command need be executed: xcode-select --install'); context$2$0.next = 3; return _regeneratorRuntime.awrap((0, _prompt.fixIt)()); case 3: yesno = context$2$0.sent; if (!(yesno === 'yes')) { context$2$0.next = 9; break; } context$2$0.next = 7; return _regeneratorRuntime.awrap((0, _teen_process.exec)('xcode-select', ['--install'])); case 7: context$2$0.next = 11; break; case 9: _logger2['default'].info('Skipping you will need to install Xcode manually.'); throw new _doctor.FixSkippedError(); case 11: case 'end': return context$2$0.stop(); } }, null, this); } }]); return XcodeCmdLineToolsCheck; })(_doctor.DoctorCheck); checks.push(new XcodeCmdLineToolsCheck()); // Automatically run authorize iOS if requested fixes.authorizeIosFix = function callee$0$0() { var yesno; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: _logger2['default'].info('The authorize iOS script need to be run.'); context$1$0.next = 3; return _regeneratorRuntime.awrap((0, _prompt.fixIt)()); case 3: yesno = context$1$0.sent; if (!(yesno === 'yes')) { context$1$0.next = 9; break; } context$1$0.next = 7; return _regeneratorRuntime.awrap((0, _utils.authorize)()); case 7: context$1$0.next = 11; break; case 9: _logger2['default'].info('Skipping you will need to run the authorize iOS manually.'); throw new _doctor.FixSkippedError(); case 11: case 'end': return context$1$0.stop(); } }, null, this); }; // Dev Tools Security var DevToolsSecurityCheck = (function (_DoctorCheck3) { _inherits(DevToolsSecurityCheck, _DoctorCheck3); function DevToolsSecurityCheck() { _classCallCheck(this, DevToolsSecurityCheck); _get(Object.getPrototypeOf(DevToolsSecurityCheck.prototype), 'constructor', this).call(this, { autofix: true }); } _createClass(DevToolsSecurityCheck, [{ key: 'diagnose', value: function diagnose() { var errMess, stdout; return _regeneratorRuntime.async(function diagnose$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: errMess = 'DevToolsSecurity is NOT enabled!'; stdout = undefined; context$2$0.prev = 2; context$2$0.next = 5; return _regeneratorRuntime.awrap((0, _teen_process.exec)('DevToolsSecurity', [])); case 5: stdout = context$2$0.sent.stdout; context$2$0.next = 12; break; case 8: context$2$0.prev = 8; context$2$0.t0 = context$2$0['catch'](2); _logger2['default'].debug(context$2$0.t0); return context$2$0.abrupt('return', (0, _utils.nok)(errMess)); case 12: return context$2$0.abrupt('return', stdout && stdout.match(/enabled/) ? (0, _utils.ok)('DevToolsSecurity is enabled.') : (0, _utils.nok)(errMess)); case 13: case 'end': return context$2$0.stop(); } }, null, this, [[2, 8]]); } }, { key: 'fix', value: function fix() { return _regeneratorRuntime.async(function fix$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: context$2$0.next = 2; return _regeneratorRuntime.awrap(fixes.authorizeIosFix()); case 2: return context$2$0.abrupt('return', context$2$0.sent); case 3: case 'end': return context$2$0.stop(); } }, null, this); } }]); return DevToolsSecurityCheck; })(_doctor.DoctorCheck); checks.push(new DevToolsSecurityCheck()); // Authorization DB var AuthorizationDbCheck = (function (_DoctorCheck4) { _inherits(AuthorizationDbCheck, _DoctorCheck4); function AuthorizationDbCheck() { _classCallCheck(this, AuthorizationDbCheck); _get(Object.getPrototypeOf(AuthorizationDbCheck.prototype), 'constructor', this).call(this, { autofix: true }); } _createClass(AuthorizationDbCheck, [{ key: 'diagnose', value: function diagnose() { var successMess, errMess, stdout, data, rg; return _regeneratorRuntime.async(function diagnose$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: successMess = 'The Authorization DB is set up properly.'; errMess = 'The Authorization DB is NOT set up properly.'; stdout = undefined; context$2$0.prev = 3; context$2$0.next = 6; return _regeneratorRuntime.awrap((0, _teen_process.exec)('security', ['authorizationdb', 'read', 'system.privilege.taskport'])); case 6: stdout = context$2$0.sent.stdout; context$2$0.next = 32; break; case 9: context$2$0.prev = 9; context$2$0.t0 = context$2$0['catch'](3); context$2$0.next = 13; return _regeneratorRuntime.awrap(_appiumSupport.system.macOsxVersion()); case 13: context$2$0.t1 = context$2$0.sent; if (!(context$2$0.t1 === '10.8')) { context$2$0.next = 30; break; } data = undefined; context$2$0.prev = 16; context$2$0.next = 19; return _regeneratorRuntime.awrap(_appiumSupport.fs.readFile('/etc/authorization', 'utf8')); case 19: data = context$2$0.sent; context$2$0.next = 26; break; case 22: context$2$0.prev = 22; context$2$0.t2 = context$2$0['catch'](16); _logger2['default'].debug(context$2$0.t2); return context$2$0.abrupt('return', (0, _utils.nok)(errMess)); case 26: rg = /<key>system.privilege.taskport<\/key>\s*\n\s*<dict>\n\s*<key>allow-root<\/key>\n\s*(<true\/>)/; return context$2$0.abrupt('return', data && data.match(rg) ? (0, _utils.ok)(successMess) : (0, _utils.nok)(errMess)); case 30: _logger2['default'].debug(context$2$0.t0); return context$2$0.abrupt('return', (0, _utils.nok)(errMess)); case 32: return context$2$0.abrupt('return', stdout && (stdout.match(/is-developer/) || stdout.match(/allow/)) ? (0, _utils.ok)(successMess) : (0, _utils.nok)(errMess)); case 33: case 'end': return context$2$0.stop(); } }, null, this, [[3, 9], [16, 22]]); } }, { key: 'fix', value: function fix() { return _regeneratorRuntime.async(function fix$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: context$2$0.next = 2; return _regeneratorRuntime.awrap(fixes.authorizeIosFix()); case 2: return context$2$0.abrupt('return', context$2$0.sent); case 3: case 'end': return context$2$0.stop(); } }, null, this); } }]); return AuthorizationDbCheck; })(_doctor.DoctorCheck); checks.push(new AuthorizationDbCheck()); // Node Binary var NodeBinaryCheck = (function (_DoctorCheck5) { _inherits(NodeBinaryCheck, _DoctorCheck5); function NodeBinaryCheck() { _classCallCheck(this, NodeBinaryCheck); _get(Object.getPrototypeOf(NodeBinaryCheck.prototype), 'constructor', this).apply(this, arguments); } _createClass(NodeBinaryCheck, [{ key: 'diagnose', value: function diagnose() { var nodePath; return _regeneratorRuntime.async(function diagnose$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: context$2$0.next = 2; return _regeneratorRuntime.awrap(_nodeDetector2['default'].detect()); case 2: nodePath = context$2$0.sent; return context$2$0.abrupt('return', nodePath ? (0, _utils.ok)('The Node.js binary was found at: ' + nodePath) : (0, _utils.nok)('The Node.js binary was NOT found!')); case 4: case 'end': return context$2$0.stop(); } }, null, this); } }, { key: 'fix', value: function fix() { return 'Manually setup Node.js.'; } }]); return NodeBinaryCheck; })(_doctor.DoctorCheck); checks.push(new NodeBinaryCheck()); checks.push(new _env2['default']('HOME')); exports.fixes = fixes; exports.XcodeCheck = XcodeCheck; exports.XcodeCmdLineToolsCheck = XcodeCmdLineToolsCheck; exports.DevToolsSecurityCheck = DevToolsSecurityCheck; exports.AuthorizationDbCheck = AuthorizationDbCheck; exports.NodeBinaryCheck = NodeBinaryCheck; exports['default'] = checks; //# sourceMappingURL=data:application/json;base64,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QUFDLENBQUM7O0FBRW5DLE1BQU0sQ0FBQyxJQUFJLENBQUMscUJBQXVCLE1BQU0sQ0FBQyxDQUFDLENBQUM7O1FBRW5DLEtBQUssR0FBTCxLQUFLO1FBQUUsVUFBVSxHQUFWLFVBQVU7UUFBRSxzQkFBc0IsR0FBdEIsc0JBQXNCO1FBQUUscUJBQXFCLEdBQXJCLHFCQUFxQjtRQUNoRSxvQkFBb0IsR0FBcEIsb0JBQW9CO1FBQUUsZUFBZSxHQUFmLGVBQWU7cUJBQy9CLE1BQU0iLCJmaWxlIjoibGliL2lvcy5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IG9rLCBub2ssIGF1dGhvcml6ZSB9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHsgZnMsIHN5c3RlbSB9IGZyb20gJ2FwcGl1bS1zdXBwb3J0JztcbmltcG9ydCB7IGV4ZWMgfSBmcm9tICd0ZWVuX3Byb2Nlc3MnO1xuaW1wb3J0IHsgRG9jdG9yQ2hlY2sgfSBmcm9tICcuL2RvY3Rvcic7XG5pbXBvcnQgbG9nIGZyb20gJy4vbG9nZ2VyJztcbmltcG9ydCB7IEZpeFNraXBwZWRFcnJvciB9IGZyb20gJy4vZG9jdG9yJztcbmltcG9ydCBOb2RlRGV0ZWN0b3IgZnJvbSAnLi9ub2RlLWRldGVjdG9yJztcbmltcG9ydCB7IGZpeEl0IH0gZnJvbSAnLi9wcm9tcHQnO1xuaW1wb3J0IEVudlZhckFuZFBhdGhDaGVjayBmcm9tICcuL2Vudic7XG5cblxubGV0IGNoZWNrcyA9IFtdO1xubGV0IGZpeGVzID0ge307XG5cbi8vIENoZWNrIGZvciBYY29kZS5cbmNsYXNzIFhjb2RlQ2hlY2sgZXh0ZW5kcyBEb2N0b3JDaGVjayB7XG4gIGFzeW5jIGRpYWdub3NlKCkge1xuICAgIGxldCB4Y29kZVBhdGg7XG4gICAgdHJ5IHtcbiAgICAgIGxldCB7c3Rkb3V0fSA9IGF3YWl0IGV4ZWMoJ3hjb2RlLXNlbGVjdCcsIFsnLS1wcmludC1wYXRoJ10pO1xuICAgICAgeGNvZGVQYXRoID0gKHN0ZG91dCB8fCAnJykucmVwbGFjZShcIlxcblwiLCBcIlwiKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHJldHVybiBub2soJ1hjb2RlIGlzIE5PVCBpbnN0YWxsZWQhJyk7XG4gICAgfVxuICAgIHJldHVybiB4Y29kZVBhdGggJiYgYXdhaXQgZnMuZXhpc3RzKHhjb2RlUGF0aCkgPyBvayhgWGNvZGUgaXMgaW5zdGFsbGVkIGF0OiAke3hjb2RlUGF0aH1gKSA6XG4gICAgICBub2soYFhjb2RlIGNhbm5vdCBiZSBmb3VuZCBhdCBcXCcke3hjb2RlUGF0aH1cXCchYCk7XG4gIH1cblxuICBhc3luYyBmaXggKCkge1xuICAgIHJldHVybiAnTWFudWFsbHkgaW5zdGFsbCBYY29kZS4nO1xuICB9XG59XG5jaGVja3MucHVzaChuZXcgWGNvZGVDaGVjaygpKTtcblxuLy8gQ2hlY2sgZm9yIFhjb2RlIENvbW1hbmQgTGluZSBUb29scy5cbmNsYXNzIFhjb2RlQ21kTGluZVRvb2xzQ2hlY2sgZXh0ZW5kcyBEb2N0b3JDaGVjayB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKHthdXRvZml4OiB0cnVlfSk7XG4gIH1cblxuICBhc3luYyBkaWFnbm9zZSAoKSB7XG4gICAgY29uc3QgZXJyTWVzcyA9ICdYY29kZSBDb21tYW5kIExpbmUgVG9vbHMgYXJlIE5PVCBpbnN0YWxsZWQhJztcbiAgICBsZXQgcGtnTmFtZSA9IGF3YWl0IHN5c3RlbS5tYWNPc3hWZXJzaW9uKCkgPT09ICcxMC44JyA/ICdjb20uYXBwbGUucGtnLkRldmVsb3BlclRvb2xzQ0xJJyA6ICdjb20uYXBwbGUucGtnLkNMVG9vbHNfRXhlY3V0YWJsZXMnO1xuICAgIGxldCBzdGRvdXQ7XG4gICAgdHJ5IHtcbiAgICAgIHN0ZG91dCA9IChhd2FpdCBleGVjKCdwa2d1dGlsJywgW2AtLXBrZy1pbmZvPSR7cGtnTmFtZX1gXSkpLnN0ZG91dDtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGxvZy5kZWJ1ZyhlcnIpO1xuICAgICAgcmV0dXJuIG5vayhlcnJNZXNzKTtcbiAgICB9XG4gICAgcmV0dXJuIHN0ZG91dC5tYXRjaCgvaW5zdGFsbC10aW1lLykgPyBvaygnWGNvZGUgQ29tbWFuZCBMaW5lIFRvb2xzIGFyZSBpbnN0YWxsZWQuJykgOlxuICAgICAgbm9rKGVyck1lc3MpO1xuICB9XG5cbiAgYXN5bmMgZml4ICgpIHtcbiAgICBsb2cuaW5mbyhgVGhlIGZvbGxvd2luZyBjb21tYW5kIG5lZWQgYmUgZXhlY3V0ZWQ6IHhjb2RlLXNlbGVjdCAtLWluc3RhbGxgKTtcbiAgICBsZXQgeWVzbm8gPSBhd2FpdCBmaXhJdCgpO1xuICAgIGlmICh5ZXNubyA9PT0gJ3llcycpIHtcbiAgICAgIGF3YWl0IGV4ZWMoJ3hjb2RlLXNlbGVjdCcsIFsnLS1pbnN0YWxsJ10pO1xuICAgIH0gZWxzZSB7XG4gICAgICBsb2cuaW5mbygnU2tpcHBpbmcgeW91IHdpbGwgbmVlZCB0byBpbnN0YWxsIFhjb2RlIG1hbnVhbGx5LicpO1xuICAgICAgdGhyb3cgbmV3IEZpeFNraXBwZWRFcnJvcigpO1xuICAgIH1cbiAgfVxufVxuXG5jaGVja3MucHVzaChuZXcgWGNvZGVDbWRMaW5lVG9vbHNDaGVjaygpKTtcblxuLy8gQXV0b21hdGljYWxseSBydW4gYXV0aG9yaXplIGlPUyBpZiByZXF1ZXN0ZWRcbmZpeGVzLmF1dGhvcml6ZUlvc0ZpeCA9IGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgbG9nLmluZm8oYFRoZSBhdXRob3JpemUgaU9TIHNjcmlwdCBuZWVkIHRvIGJlIHJ1bi5gKTtcbiAgbGV0IHllc25vID0gYXdhaXQgZml4SXQoKTtcbiAgaWYgKHllc25vID09PSAneWVzJykge1xuICAgIGF3YWl0IGF1dGhvcml6ZSgpO1xuICB9IGVsc2Uge1xuICAgIGxvZy5pbmZvKCdTa2lwcGluZyB5b3Ugd2lsbCBuZWVkIHRvIHJ1biB0aGUgYXV0aG9yaXplIGlPUyBtYW51YWxseS4nKTtcbiAgICB0aHJvdyBuZXcgRml4U2tpcHBlZEVycm9yKCk7XG4gIH1cbn07XG5cbi8vIERldiBUb29scyBTZWN1cml0eVxuY2xhc3MgRGV2VG9vbHNTZWN1cml0eUNoZWNrIGV4dGVuZHMgRG9jdG9yQ2hlY2sge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcih7YXV0b2ZpeDogdHJ1ZX0pO1xuICB9XG5cbiAgYXN5bmMgZGlhZ25vc2UgKCkge1xuICAgIGNvbnN0IGVyck1lc3MgPSAnRGV2VG9vbHNTZWN1cml0eSBpcyBOT1QgZW5hYmxlZCEnO1xuICAgIGxldCBzdGRvdXQ7XG4gICAgdHJ5IHtcbiAgICAgIHN0ZG91dCA9IChhd2FpdCBleGVjKCdEZXZUb29sc1NlY3VyaXR5JywgW10pKS5zdGRvdXQ7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2cuZGVidWcoZXJyKTtcbiAgICAgIHJldHVybiBub2soZXJyTWVzcyk7XG4gICAgfVxuICAgIHJldHVybiBzdGRvdXQgJiYgc3Rkb3V0Lm1hdGNoKC9lbmFibGVkLykgPyBvaygnRGV2VG9vbHNTZWN1cml0eSBpcyBlbmFibGVkLicpXG4gICAgICA6IG5vayhlcnJNZXNzKTtcbiAgfVxuICBhc3luYyBmaXggKCkge1xuICAgIHJldHVybiBhd2FpdCBmaXhlcy5hdXRob3JpemVJb3NGaXgoKTtcbiAgfVxufVxuY2hlY2tzLnB1c2gobmV3IERldlRvb2xzU2VjdXJpdHlDaGVjaygpKTtcblxuLy8gQXV0aG9yaXphdGlvbiBEQlxuY2xhc3MgQXV0aG9yaXphdGlvbkRiQ2hlY2sgZXh0ZW5kcyBEb2N0b3JDaGVjayB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKHthdXRvZml4OiB0cnVlfSk7XG4gIH1cblxuICBhc3luYyBkaWFnbm9zZSAoKSB7XG4gICAgY29uc3Qgc3VjY2Vzc01lc3MgPSAnVGhlIEF1dGhvcml6YXRpb24gREIgaXMgc2V0IHVwIHByb3Blcmx5Lic7XG4gICAgY29uc3QgZXJyTWVzcyA9ICdUaGUgQXV0aG9yaXphdGlvbiBEQiBpcyBOT1Qgc2V0IHVwIHByb3Blcmx5Lic7XG4gICAgbGV0IHN0ZG91dDtcbiAgICB0cnkge1xuICAgICAgc3Rkb3V0ID0gKGF3YWl0IGV4ZWMoJ3NlY3VyaXR5JywgWydhdXRob3JpemF0aW9uZGInLCAncmVhZCcsICdzeXN0ZW0ucHJpdmlsZWdlLnRhc2twb3J0J10pKS5zdGRvdXQ7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAoYXdhaXQgc3lzdGVtLm1hY09zeFZlcnNpb24oKSA9PT0gJzEwLjgnKSB7XG4gICAgICAgIGxldCBkYXRhO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGRhdGEgPSBhd2FpdCBmcy5yZWFkRmlsZSgnL2V0Yy9hdXRob3JpemF0aW9uJywgJ3V0ZjgnKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgbG9nLmRlYnVnKGVycik7XG4gICAgICAgICAgcmV0dXJuIG5vayhlcnJNZXNzKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcmcgPS88a2V5PnN5c3RlbS5wcml2aWxlZ2UudGFza3BvcnQ8XFwva2V5PlxccypcXG5cXHMqPGRpY3Q+XFxuXFxzKjxrZXk+YWxsb3ctcm9vdDxcXC9rZXk+XFxuXFxzKig8dHJ1ZVxcLz4pLztcbiAgICAgICAgcmV0dXJuIGRhdGEgJiYgZGF0YS5tYXRjaChyZykgPyBvayhzdWNjZXNzTWVzcykgOiBub2soZXJyTWVzcyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb2cuZGVidWcoZXJyKTtcbiAgICAgICAgcmV0dXJuIG5vayhlcnJNZXNzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHN0ZG91dCAmJiAoc3Rkb3V0Lm1hdGNoKC9pcy1kZXZlbG9wZXIvKSB8fCBzdGRvdXQubWF0Y2goL2FsbG93LykpID9cbiAgICAgICBvayhzdWNjZXNzTWVzcykgOiBub2soZXJyTWVzcyk7XG4gIH1cbiAgYXN5bmMgZml4ICgpIHtcbiAgICByZXR1cm4gYXdhaXQgZml4ZXMuYXV0aG9yaXplSW9zRml4KCk7XG4gIH1cbn1cbmNoZWNrcy5wdXNoKG5ldyBBdXRob3JpemF0aW9uRGJDaGVjaygpKTtcblxuLy8gTm9kZSBCaW5hcnlcbmNsYXNzIE5vZGVCaW5hcnlDaGVjayBleHRlbmRzIERvY3RvckNoZWNrIHtcbiAgYXN5bmMgZGlhZ25vc2UgKCkge1xuICAgIGxldCBub2RlUGF0aCA9IGF3YWl0IE5vZGVEZXRlY3Rvci5kZXRlY3QoKTtcbiAgICByZXR1cm4gbm9kZVBhdGggPyBvayhgVGhlIE5vZGUuanMgYmluYXJ5IHdhcyBmb3VuZCBhdDogJHtub2RlUGF0aH1gKSA6XG4gICAgICBub2soJ1RoZSBOb2RlLmpzIGJpbmFyeSB3YXMgTk9UIGZvdW5kIScpO1xuICB9XG5cbiAgZml4KCkge1xuICAgIHJldHVybiBgTWFudWFsbHkgc2V0dXAgTm9kZS5qcy5gO1xuICB9XG59XG5jaGVja3MucHVzaChuZXcgTm9kZUJpbmFyeUNoZWNrKCkpO1xuXG5jaGVja3MucHVzaChuZXcgRW52VmFyQW5kUGF0aENoZWNrKCdIT01FJykpO1xuXG5leHBvcnQgeyBmaXhlcywgWGNvZGVDaGVjaywgWGNvZGVDbWRMaW5lVG9vbHNDaGVjaywgRGV2VG9vbHNTZWN1cml0eUNoZWNrLFxuICAgICAgICAgQXV0aG9yaXphdGlvbkRiQ2hlY2ssIE5vZGVCaW5hcnlDaGVjayB9O1xuZXhwb3J0IGRlZmF1bHQgY2hlY2tzO1xuIl19