UNPKG

appium-adb

Version:

Android Debug Bridge interface

465 lines (359 loc) 29.3 kB
'use strict'; var _regeneratorRuntime = require('babel-runtime/regenerator')['default']; var _getIterator = require('babel-runtime/core-js/get-iterator')['default']; var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; Object.defineProperty(exports, '__esModule', { value: true }); var _teen_process = require('teen_process'); var _path = require('path'); var _path2 = _interopRequireDefault(_path); var _loggerJs = require('../logger.js'); var _loggerJs2 = _interopRequireDefault(_loggerJs); var _appiumSupport = require('appium-support'); var _admZip = require('adm-zip'); var _admZip2 = _interopRequireDefault(_admZip); var _helpersJs = require('../helpers.js'); var apkSigningMethods = {}; apkSigningMethods.signWithDefaultCert = function callee$0$0(apk) { var java, signPath; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: java = (0, _helpersJs.getJavaForOs)(); signPath = _path2['default'].resolve(this.helperJarPath, 'sign.jar'); _loggerJs2['default'].debug("Resigning apk."); context$1$0.prev = 3; context$1$0.next = 6; return _regeneratorRuntime.awrap(_appiumSupport.fs.exists(apk)); case 6: if (context$1$0.sent) { context$1$0.next = 8; break; } throw new Error(apk + ' file doesn\'t exist.'); case 8: context$1$0.next = 10; return _regeneratorRuntime.awrap((0, _teen_process.exec)(java, ['-jar', signPath, apk, '--override'])); case 10: context$1$0.next = 15; break; case 12: context$1$0.prev = 12; context$1$0.t0 = context$1$0['catch'](3); _loggerJs2['default'].errorAndThrow('Could not sign with default ceritficate. Original error ' + context$1$0.t0.message); case 15: case 'end': return context$1$0.stop(); } }, null, this, [[3, 12]]); }; apkSigningMethods.signWithCustomCert = function callee$0$0(apk) { var java, javaHome, jarsigner; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: _loggerJs2['default'].debug('Signing \'' + apk + '\' with custom cert'); java = (0, _helpersJs.getJavaForOs)(); javaHome = (0, _helpersJs.getJavaHome)(); jarsigner = _path2['default'].resolve(javaHome, 'bin', 'jarsigner'); if (_appiumSupport.system.isWindows()) { jarsigner = jarsigner + '.exe'; } context$1$0.next = 7; return _regeneratorRuntime.awrap(_appiumSupport.fs.exists(this.keystorePath)); case 7: if (context$1$0.sent) { context$1$0.next = 9; break; } throw new Error('Keystore: ' + this.keystorePath + ' doesn\'t exist.'); case 9: context$1$0.next = 11; return _regeneratorRuntime.awrap(_appiumSupport.fs.exists(apk)); case 11: if (context$1$0.sent) { context$1$0.next = 13; break; } throw new Error(apk + ' file doesn\'t exist.'); case 13: context$1$0.prev = 13; _loggerJs2['default'].debug("Unsigning apk."); context$1$0.next = 17; return _regeneratorRuntime.awrap((0, _teen_process.exec)(java, ['-jar', _path2['default'].resolve(this.helperJarPath, 'unsign.jar'), apk])); case 17: _loggerJs2['default'].debug("Signing apk."); context$1$0.next = 20; return _regeneratorRuntime.awrap((0, _teen_process.exec)(jarsigner, ['-sigalg', 'MD5withRSA', '-digestalg', 'SHA1', '-keystore', this.keystorePath, '-storepass', this.keystorePassword, '-keypass', this.keyPassword, apk, this.keyAlias])); case 20: context$1$0.next = 25; break; case 22: context$1$0.prev = 22; context$1$0.t0 = context$1$0['catch'](13); _loggerJs2['default'].errorAndThrow('Could not sign with custom ceritficate. Original error ' + context$1$0.t0.message); case 25: case 'end': return context$1$0.stop(); } }, null, this, [[13, 22]]); }; apkSigningMethods.sign = function callee$0$0(apk) { return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: if (!this.useKeystore) { context$1$0.next = 5; break; } context$1$0.next = 3; return _regeneratorRuntime.awrap(this.signWithCustomCert(apk)); case 3: context$1$0.next = 7; break; case 5: context$1$0.next = 7; return _regeneratorRuntime.awrap(this.signWithDefaultCert(apk)); case 7: context$1$0.next = 9; return _regeneratorRuntime.awrap(this.zipAlignApk(apk)); case 9: case 'end': return context$1$0.stop(); } }, null, this); }; apkSigningMethods.zipAlignApk = function callee$0$0(apk) { var alignedApk; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: _loggerJs2['default'].debug('Zip-aligning \'' + apk + '\''); context$1$0.next = 3; return _regeneratorRuntime.awrap(this.initZipAlign()); case 3: context$1$0.next = 5; return _regeneratorRuntime.awrap(_appiumSupport.tempDir.path({ prefix: 'appium', suffix: '.tmp' })); case 5: alignedApk = context$1$0.sent; context$1$0.next = 8; return _regeneratorRuntime.awrap((0, _appiumSupport.mkdirp)(_path2['default'].dirname(alignedApk))); case 8: _loggerJs2['default'].debug("Zip-aligning apk."); context$1$0.prev = 9; context$1$0.next = 12; return _regeneratorRuntime.awrap((0, _teen_process.exec)(this.binaries.zipalign, ['-f', '4', apk, alignedApk])); case 12: context$1$0.next = 14; return _regeneratorRuntime.awrap(_appiumSupport.fs.mv(alignedApk, apk, { mkdirp: true })); case 14: context$1$0.next = 19; break; case 16: context$1$0.prev = 16; context$1$0.t0 = context$1$0['catch'](9); _loggerJs2['default'].errorAndThrow('zipAlignApk failed. Original error: ' + context$1$0.t0.message); case 19: case 'end': return context$1$0.stop(); } }, null, this, [[9, 16]]); }; // returns true when already signed, false otherwise. apkSigningMethods.checkApkCert = function callee$0$0(apk, pkg) { var java; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: java = (0, _helpersJs.getJavaForOs)(); context$1$0.next = 3; return _regeneratorRuntime.awrap(_appiumSupport.fs.exists(apk)); case 3: if (context$1$0.sent) { context$1$0.next = 6; break; } _loggerJs2['default'].debug('APK doesn\'t exist. ' + apk); return context$1$0.abrupt('return', false); case 6: if (!this.useKeystore) { context$1$0.next = 10; break; } context$1$0.next = 9; return _regeneratorRuntime.awrap(this.checkCustomApkCert(apk, pkg)); case 9: return context$1$0.abrupt('return', context$1$0.sent); case 10: _loggerJs2['default'].debug('Checking app cert for ' + apk + '.'); context$1$0.prev = 11; context$1$0.next = 14; return _regeneratorRuntime.awrap((0, _teen_process.exec)(java, ['-jar', _path2['default'].resolve(this.helperJarPath, 'verify.jar'), apk])); case 14: _loggerJs2['default'].debug("App already signed."); context$1$0.next = 17; return _regeneratorRuntime.awrap(this.zipAlignApk(apk)); case 17: return context$1$0.abrupt('return', true); case 20: context$1$0.prev = 20; context$1$0.t0 = context$1$0['catch'](11); _loggerJs2['default'].debug("App not signed with debug cert."); return context$1$0.abrupt('return', false); case 24: case 'end': return context$1$0.stop(); } }, null, this, [[11, 20]]); }; apkSigningMethods.checkCustomApkCert = function callee$0$0(apk, pkg) { var h, md5Str, md5, javaHome, keytool, keystoreHash; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: _loggerJs2['default'].debug('Checking custom app cert for ' + apk); h = "a-fA-F0-9"; md5Str = ['.*MD5.*((?:[' + h + ']{2}:){15}[' + h + ']{2})']; md5 = new RegExp(md5Str, 'mi'); javaHome = (0, _helpersJs.getJavaHome)(); keytool = _path2['default'].resolve(javaHome, 'bin', 'keytool'); keytool = _appiumSupport.system.isWindows() ? keytool + '.exe' : keytool; context$1$0.next = 9; return _regeneratorRuntime.awrap(this.getKeystoreMd5(keytool, md5)); case 9: keystoreHash = context$1$0.sent; context$1$0.next = 12; return _regeneratorRuntime.awrap(this.checkApkKeystoreMatch(keytool, md5, keystoreHash, pkg, apk)); case 12: return context$1$0.abrupt('return', context$1$0.sent); case 13: case 'end': return context$1$0.stop(); } }, null, this); }; apkSigningMethods.getKeystoreMd5 = function callee$0$0(keytool, md5re) { var keystoreHash, _ref, stdout; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: keystoreHash = undefined; _loggerJs2['default'].debug("Printing keystore md5."); context$1$0.prev = 2; context$1$0.next = 5; return _regeneratorRuntime.awrap((0, _teen_process.exec)(keytool, ['-v', '-list', '-alias', this.keyAlias, '-keystore', this.keystorePath, '-storepass', this.keystorePassword])); case 5: _ref = context$1$0.sent; stdout = _ref.stdout; keystoreHash = md5re.exec(stdout); keystoreHash = keystoreHash ? keystoreHash[1] : null; _loggerJs2['default'].debug('Keystore MD5: ' + keystoreHash); return context$1$0.abrupt('return', keystoreHash); case 13: context$1$0.prev = 13; context$1$0.t0 = context$1$0['catch'](2); _loggerJs2['default'].errorAndThrow('getKeystoreMd5 failed. Original error: ' + context$1$0.t0.message); case 16: case 'end': return context$1$0.stop(); } }, null, this, [[2, 13]]); }; apkSigningMethods.checkApkKeystoreMatch = function callee$0$0(keytool, md5re, keystoreHash, pkg, apk) { var entryHash, zip, rsa, entries, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, entry, entryPath, entryFile, _ref2, stdout, matchesKeystore; return _regeneratorRuntime.async(function callee$0$0$(context$1$0) { while (1) switch (context$1$0.prev = context$1$0.next) { case 0: entryHash = null; zip = new _admZip2['default'](apk); rsa = /^META-INF\/.*\.[rR][sS][aA]$/; entries = zip.getEntries(); _iteratorNormalCompletion = true; _didIteratorError = false; _iteratorError = undefined; context$1$0.prev = 7; _iterator = _getIterator(entries); case 9: if (_iteratorNormalCompletion = (_step = _iterator.next()).done) { context$1$0.next = 39; break; } entry = _step.value; entry = entry.entryName; if (rsa.test(entry)) { context$1$0.next = 14; break; } return context$1$0.abrupt('continue', 36); case 14: _loggerJs2['default'].debug('Entry: ' + entry); entryPath = _path2['default'].join(this.tmpDir, pkg, 'cert'); _loggerJs2['default'].debug('entryPath: ' + entryPath); entryFile = _path2['default'].join(entryPath, entry); _loggerJs2['default'].debug('entryFile: ' + entryFile); // ensure /tmp/pkg/cert/ doesn't exist or extract will fail. context$1$0.next = 21; return _regeneratorRuntime.awrap(_appiumSupport.fs.rimraf(entryPath)); case 21: // META-INF/CERT.RSA zip.extractEntryTo(entry, entryPath, true); // overwrite = true _loggerJs2['default'].debug("extracted!"); // check for match _loggerJs2['default'].debug("Printing apk md5."); context$1$0.next = 26; return _regeneratorRuntime.awrap((0, _teen_process.exec)(keytool, ['-v', '-printcert', '-file', entryFile])); case 26: _ref2 = context$1$0.sent; stdout = _ref2.stdout; entryHash = md5re.exec(stdout); entryHash = entryHash ? entryHash[1] : null; _loggerJs2['default'].debug('entryHash MD5: ' + entryHash); _loggerJs2['default'].debug('keystore MD5: ' + keystoreHash); matchesKeystore = entryHash && entryHash === keystoreHash; _loggerJs2['default'].debug('Matches keystore? ' + matchesKeystore); if (!matchesKeystore) { context$1$0.next = 36; break; } return context$1$0.abrupt('return', true); case 36: _iteratorNormalCompletion = true; context$1$0.next = 9; break; case 39: context$1$0.next = 45; break; case 41: context$1$0.prev = 41; context$1$0.t0 = context$1$0['catch'](7); _didIteratorError = true; _iteratorError = context$1$0.t0; case 45: context$1$0.prev = 45; context$1$0.prev = 46; if (!_iteratorNormalCompletion && _iterator['return']) { _iterator['return'](); } case 48: context$1$0.prev = 48; if (!_didIteratorError) { context$1$0.next = 51; break; } throw _iteratorError; case 51: return context$1$0.finish(48); case 52: return context$1$0.finish(45); case 53: return context$1$0.abrupt('return', false); case 54: case 'end': return context$1$0.stop(); } }, null, this, [[7, 41, 45, 53], [46,, 48, 52]]); }; exports['default'] = apkSigningMethods; module.exports = exports['default']; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi90b29scy9hcGstc2lnbmluZy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7NEJBQXFCLGNBQWM7O29CQUNsQixNQUFNOzs7O3dCQUNQLGNBQWM7Ozs7NkJBQ2MsZ0JBQWdCOztzQkFDekMsU0FBUzs7Ozt5QkFDYyxlQUFlOztBQUV6RCxJQUFJLGlCQUFpQixHQUFHLEVBQUUsQ0FBQzs7QUFHM0IsaUJBQWlCLENBQUMsbUJBQW1CLEdBQUcsb0JBQWdCLEdBQUc7TUFDbkQsSUFBSSxFQUNOLFFBQVE7Ozs7QUFETixZQUFJLEdBQUcsOEJBQWM7QUFDdkIsZ0JBQVEsR0FBRyxrQkFBSyxPQUFPLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxVQUFVLENBQUM7O0FBQzNELDhCQUFJLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDOzs7eUNBRWQsa0JBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQzs7Ozs7Ozs7Y0FDbEIsSUFBSSxLQUFLLENBQUksR0FBRywyQkFBdUI7Ozs7eUNBRXpDLHdCQUFLLElBQUksRUFBRSxDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFFLFlBQVksQ0FBQyxDQUFDOzs7Ozs7Ozs7O0FBRXZELDhCQUFJLGFBQWEsOERBQTRELGVBQUUsT0FBTyxDQUFHLENBQUM7Ozs7Ozs7Q0FFN0YsQ0FBQzs7QUFFRixpQkFBaUIsQ0FBQyxrQkFBa0IsR0FBRyxvQkFBZ0IsR0FBRztNQUVsRCxJQUFJLEVBQ04sUUFBUSxFQUNSLFNBQVM7Ozs7QUFIYiw4QkFBSSxLQUFLLGdCQUFhLEdBQUcseUJBQXFCLENBQUM7QUFDekMsWUFBSSxHQUFHLDhCQUFjO0FBQ3ZCLGdCQUFRLEdBQUcsNkJBQWE7QUFDeEIsaUJBQVMsR0FBRyxrQkFBSyxPQUFPLENBQUMsUUFBUSxFQUFFLEtBQUssRUFBRSxXQUFXLENBQUM7O0FBQzFELFlBQUksc0JBQU8sU0FBUyxFQUFFLEVBQUU7QUFDdEIsbUJBQVMsR0FBRyxTQUFTLEdBQUcsTUFB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LENBQUM7QUFDakMsaUJBQVMsR0FBRyxrQkFBSyxJQUFJLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQzs7QUFDM0MsOEJBQUksS0FBSyxpQkFBZSxTQUFTLENBQUcsQ0FBQzs7O3lDQUUvQixrQkFBRyxNQUFNLENBQUMsU0FBUyxDQUFDOzs7O0FBRTFCLFdBQUcsQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUMzQyw4QkFBSSxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7O0FBRXhCLDhCQUFJLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDOzt5Q0FDVix3QkFBSyxPQUFPLEVBQUUsQ0FBQyxJQUFJLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQzs7OztBQUF2RSxjQUFNLFNBQU4sTUFBTTs7QUFDWCxpQkFBUyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDL0IsaUJBQVMsR0FBRyxTQUFTLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQztBQUM1Qyw4QkFBSSxLQUFLLHFCQUFtQixTQUFTLENBQUcsQ0FBQztBQUN6Qyw4QkFBSSxLQUFLLG9CQUFrQixZQUFZLENBQUcsQ0FBQztBQUN2Qyx1QkFBZSxHQUFHLFNBQVMsSUFBSSxTQUFTLEtBQUssWUFBWTs7QUFDN0QsOEJBQUksS0FBSyx3QkFBc0IsZUFBZSxDQUFHLENBQUM7O2FBQzlDLGVBQWU7Ozs7OzRDQUNWLElBQUk7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs0Q0FHUixLQUFLOzs7Ozs7O0NBQ2IsQ0FBQzs7cUJBRWEsaUJBQWlCIiwiZmlsZSI6ImxpYi90b29scy9hcGstc2lnbmluZy5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGV4ZWMgfSBmcm9tICd0ZWVuX3Byb2Nlc3MnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgbG9nIGZyb20gJy4uL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyB0ZW1wRGlyLCBzeXN0ZW0sIG1rZGlycCwgZnMgfSBmcm9tICdhcHBpdW0tc3VwcG9ydCc7XG5pbXBvcnQgQWRtWmlwIGZyb20gJ2FkbS16aXAnO1xuaW1wb3J0IHsgZ2V0SmF2YUZvck9zLCBnZXRKYXZhSG9tZSB9IGZyb20gJy4uL2hlbHBlcnMuanMnO1xuXG5sZXQgYXBrU2lnbmluZ01ldGhvZHMgPSB7fTtcblxuXG5hcGtTaWduaW5nTWV0aG9kcy5zaWduV2l0aERlZmF1bHRDZXJ0ID0gYXN5bmMgZnVuY3Rpb24gKGFwaykge1xuICBjb25zdCBqYXZhID0gZ2V0SmF2YUZvck9zKCk7XG4gIGxldCBzaWduUGF0aCA9IHBhdGgucmVzb2x2ZSh0aGlzLmhlbHBlckphclBhdGgsICdzaWduLmphcicpO1xuICBsb2cuZGVidWcoXCJSZXNpZ25pbmcgYXBrLlwiKTtcbiAgdHJ5IHtcbiAgICBpZiAoIShhd2FpdCBmcy5leGlzdHMoYXBrKSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHthcGt9IGZpbGUgZG9lc24ndCBleGlzdC5gKTtcbiAgICB9XG4gICAgYXdhaXQgZXhlYyhqYXZhLCBbJy1qYXInLCBzaWduUGF0aCwgYXBrLCAnLS1vdmVycmlkZSddKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxvZy5lcnJvckFuZFRocm93KGBDb3VsZCBub3Qgc2lnbiB3aXRoIGRlZmF1bHQgY2VyaXRmaWNhdGUuIE9yaWdpbmFsIGVycm9yICR7ZS5tZXNzYWdlfWApO1xuICB9XG59O1xuXG5hcGtTaWduaW5nTWV0aG9kcy5zaWduV2l0aEN1c3RvbUNlcnQgPSBhc3luYyBmdW5jdGlvbiAoYXBrKSB7XG4gIGxvZy5kZWJ1ZyhgU2lnbmluZyAnJHthcGt9JyB3aXRoIGN1c3RvbSBjZXJ0YCk7XG4gIGNvbnN0IGphdmEgPSBnZXRKYXZhRm9yT3MoKTtcbiAgbGV0IGphdmFIb21lID0gZ2V0SmF2YUhvbWUoKTtcbiAgbGV0IGphcnNpZ25lciA9IHBhdGgucmVzb2x2ZShqYXZhSG9tZSwgJ2JpbicsICdqYXJzaWduZXInKTtcbiAgaWYgKHN5c3RlbS5pc1dpbmRvd3MoKSkge1xuICAgIGphcnNpZ25lciA9IGphcnNpZ25lciArICcuZXhlJztcbiAgfVxuICBpZiAoIShhd2FpdCBmcy5leGlzdHModGhpcy5rZXlzdG9yZVBhdGgpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgS2V5c3RvcmU6ICR7dGhpcy5rZXlzdG9yZVBhdGh9IGRvZXNuJ3QgZXhpc3QuYCk7XG4gIH1cbiAgaWYgKCEoYXdhaXQgZnMuZXhpc3RzKGFwaykpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke2Fwa30gZmlsZSBkb2Vzbid0IGV4aXN0LmApO1xuICB9XG4gIHRyeSB7XG4gICAgbG9nLmRlYnVnKFwiVW5zaWduaW5nIGFway5cIik7XG4gICAgYXdhaXQgZXhlYyhqYXZhLCBbJy1qYXInLCBwYXRoLnJlc29sdmUodGhpcy5oZWxwZXJKYXJQYXRoLCAndW5zaWduLmphcicpLCBhcGtdKTtcbiAgICBsb2cuZGVidWcoXCJTaWduaW5nIGFway5cIik7XG4gICAgYXdhaXQgZXhlYyhqYXJzaWduZXIsIFsnLXNpZ2FsZycsICdNRDV3aXRoUlNBJywgJy1kaWdlc3RhbGcnLCAnU0hBMScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAnLWtleXN0b3JlJywgdGhpcy5rZXlzdG9yZVBhdGgsICctc3RvcmVwYXNzJywgdGhpcy5rZXlzdG9yZVBhc3N3b3JkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgJy1rZXlwYXNzJywgdGhpcy5rZXlQYXNzd29yZCwgYXBrLCB0aGlzLmtleUFsaWFzXSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBsb2cuZXJyb3JBbmRUaHJvdyhgQ291bGQgbm90IHNpZ24gd2l0aCBjdXN0b20gY2VyaXRmaWNhdGUuIE9yaWdpbmFsIGVycm9yICR7ZS5tZXNzYWdlfWApO1xuICB9XG59O1xuXG5hcGtTaWduaW5nTWV0aG9kcy5zaWduID0gYXN5bmMgZnVuY3Rpb24gKGFwaykge1xuICBpZiAodGhpcy51c2VLZXlzdG9yZSkge1xuICAgIGF3YWl0IHRoaXMuc2lnbldpdGhDdXN0b21DZXJ0KGFwayk7XG4gIH0gZWxzZSB7XG4gICAgYXdhaXQgdGhpcy5zaWduV2l0aERlZmF1bHRDZXJ0KGFwayk7XG4gIH1cbiAgYXdhaXQgdGhpcy56aXBBbGlnbkFwayhhcGspO1xufTtcblxuYXBrU2lnbmluZ01ldGhvZHMuemlwQWxpZ25BcGsgPSBhc3luYyBmdW5jdGlvbiAoYXBrKSB7XG4gIGxvZy5kZWJ1ZyhgWmlwLWFsaWduaW5nICcke2Fwa30nYCk7XG4gIGF3YWl0IHRoaXMuaW5pdFppcEFsaWduKCk7XG4gIGxldCBhbGlnbmVkQXBrID0gYXdhaXQgdGVtcERpci5wYXRoKHtwcmVmaXg6ICdhcHBpdW0nLCBzdWZmaXg6ICcudG1wJ30pO1xuICBhd2FpdCBta2RpcnAocGF0aC5kaXJuYW1lKGFsaWduZWRBcGspKTtcbiAgbG9nLmRlYnVnKFwiWmlwLWFsaWduaW5nIGFway5cIik7XG4gIHRyeSB7XG4gICAgYXdhaXQgZXhlYyh0aGlzLmJpbmFyaWVzLnppcGFsaWduLCBbJy1mJywgJzQnLCBhcGssIGFsaWduZWRBcGtdKTtcbiAgICBhd2FpdCBmcy5tdihhbGlnbmVkQXBrLCBhcGssIHsgbWtkaXJwOiB0cnVlIH0pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbG9nLmVycm9yQW5kVGhyb3coYHppcEFsaWduQXBrIGZhaWxlZC4gT3JpZ2luYWwgZXJyb3I6ICR7ZS5tZXNzYWdlfWApO1xuICB9XG59O1xuXG4vLyByZXR1cm5zIHRydWUgd2hlbiBhbHJlYWR5IHNpZ25lZCwgZmFsc2Ugb3RoZXJ3aXNlLlxuYXBrU2lnbmluZ01ldGhvZHMuY2hlY2tBcGtDZXJ0ID0gYXN5bmMgZnVuY3Rpb24gKGFwaywgcGtnKSB7XG4gIGNvbnN0IGphdmEgPSBnZXRKYXZhRm9yT3MoKTtcbiAgaWYgKCEoYXdhaXQgZnMuZXhpc3RzKGFwaykpKSB7XG4gICAgbG9nLmRlYnVnKGBBUEsgZG9lc24ndCBleGlzdC4gJHthcGt9YCk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmICh0aGlzLnVzZUtleXN0b3JlKSB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuY2hlY2tDdXN0b21BcGtDZXJ0KGFwaywgcGtnKTtcbiAgfVxuICBsb2cuZGVidWcoYENoZWNraW5nIGFwcCBjZXJ0IGZvciAke2Fwa30uYCk7XG4gIHRyeSB7XG4gICAgYXdhaXQgZXhlYyhqYXZhLCBbJy1qYXInLCBwYXRoLnJlc29sdmUodGhpcy5oZWxwZXJKYXJQYXRoLCAndmVyaWZ5LmphcicpLCBhcGtdKTtcbiAgICBsb2cuZGVidWcoXCJBcHAgYWxyZWFkeSBzaWduZWQuXCIpO1xuICAgIGF3YWl0IHRoaXMuemlwQWxpZ25BcGsoYXBrKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxvZy5kZWJ1ZyhcIkFwcCBub3Qgc2lnbmVkIHdpdGggZGVidWcgY2VydC5cIik7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59O1xuXG5hcGtTaWduaW5nTWV0aG9kcy5jaGVja0N1c3RvbUFwa0NlcnQgPSBhc3luYyBmdW5jdGlvbiAoYXBrLCBwa2cpIHtcbiAgbG9nLmRlYnVnKGBDaGVja2luZyBjdXN0b20gYXBwIGNlcnQgZm9yICR7YXBrfWApO1xuICBsZXQgaCA9IFwiYS1mQS1GMC05XCI7XG4gIGxldCBtZDVTdHIgPSBbYC4qTUQ1LiooKD86WyR7aH1dezJ9Oil7MTV9WyR7aH1dezJ9KWBdO1xuICBsZXQgbWQ1ID0gbmV3IFJlZ0V4cChtZDVTdHIsICdtaScpO1xuICBsZXQgamF2YUhvbWUgPSBnZXRKYXZhSG9tZSgpO1xuICBsZXQga2V5dG9vbCA9IHBhdGgucmVzb2x2ZShqYXZhSG9tZSwgJ2JpbicsICdrZXl0b29sJyk7XG4gIGtleXRvb2wgPSBzeXN0ZW0uaXNXaW5kb3dzKCkgPyBgJHtrZXl0b29sfS5leGVgIDoga2V5dG9vbDtcbiAgbGV0IGtleXN0b3JlSGFzaCA9IGF3YWl0IHRoaXMuZ2V0S2V5c3RvcmVNZDUoa2V5dG9vbCwgbWQ1KTtcbiAgcmV0dXJuIGF3YWl0IHRoaXMuY2hlY2tBcGtLZXlzdG9yZU1hdGNoKGtleXRvb2wsIG1kNSwga2V5c3RvcmVIYXNoLCBwa2csIGFwayk7XG59O1xuXG5hcGtTaWduaW5nTWV0aG9kcy5nZXRLZXlzdG9yZU1kNSA9IGFzeW5jIGZ1bmN0aW9uIChrZXl0b29sLCBtZDVyZSkge1xuICBsZXQga2V5c3RvcmVIYXNoO1xuICBsb2cuZGVidWcoXCJQcmludGluZyBrZXlzdG9yZSBtZDUuXCIpO1xuICB0cnkge1xuICAgIGxldCB7c3Rkb3V0fSA9IGF3YWl0IGV4ZWMoa2V5dG9vbCwgWyctdicsICctbGlzdCcsICctYWxpYXMnLCB0aGlzLmtleUFsaWFzLFxuICAgICAgICAgICAgICAgICAgICAgICAgJy1rZXlzdG9yZScsIHRoaXMua2V5c3RvcmVQYXRoLCAnLXN0b3JlcGFzcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5rZXlzdG9yZVBhc3N3b3JkXSk7XG4gICAga2V5c3RvcmVIYXNoID0gbWQ1cmUuZXhlYyhzdGRvdXQpO1xuICAgIGtleXN0b3JlSGFzaCA9IGtleXN0b3JlSGFzaCA/IGtleXN0b3JlSGFzaFsxXSA6IG51bGw7XG4gICAgbG9nLmRlYnVnKGBLZXlzdG9yZSBNRDU6ICR7a2V5c3RvcmVIYXNofWApO1xuICAgIHJldHVybiBrZXlzdG9yZUhhc2g7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBsb2cuZXJyb3JBbmRUaHJvdyhgZ2V0S2V5c3RvcmVNZDUgZmFpbGVkLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbmFwa1NpZ25pbmdNZXRob2RzLmNoZWNrQXBrS2V5c3RvcmVNYXRjaCA9IGFzeW5jIGZ1bmN0aW9uIChrZXl0b29sLCBtZDVyZSwga2V5c3RvcmVIYXNoLFxuICAgIHBrZywgYXBrKSB7XG4gIGxldCBlbnRyeUhhc2ggPSBudWxsO1xuICBsZXQgemlwID0gbmV3IEFkbVppcChhcGspO1xuICBsZXQgcnNhID0gL15NRVRBLUlORlxcLy4qXFwuW3JSXVtzU11bYUFdJC87XG4gIGxldCBlbnRyaWVzID0gemlwLmdldEVudHJpZXMoKTtcblxuICBmb3IgKGxldCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgZW50cnkgPSBlbnRyeS5lbnRyeU5hbWU7XG4gICAgaWYgKCFyc2EudGVzdChlbnRyeSkpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBsb2cuZGVidWcoYEVudHJ5OiAke2VudHJ5fWApO1xuICAgIGxldCBlbnRyeVBhdGggPSBwYXRoLmpvaW4odGhpcy50bXBEaXIsIHBrZywgJ2NlcnQnKTtcbiAgICBsb2cuZGVidWcoYGVudHJ5UGF0aDogJHtlbnRyeVBhdGh9YCk7XG4gICAgbGV0IGVudHJ5RmlsZSA9IHBhdGguam9pbihlbnRyeVBhdGgsIGVudHJ5KTtcbiAgICBsb2cuZGVidWcoYGVudHJ5RmlsZTogJHtlbnRyeUZpbGV9YCk7XG4gICAgLy8gZW5zdXJlIC90bXAvcGtnL2NlcnQvIGRvZXNuJ3QgZXhpc3Qgb3IgZXh0cmFjdCB3aWxsIGZhaWwuXG4gICAgYXdhaXQgZnMucmltcmFmKGVudHJ5UGF0aCk7XG4gICAgLy8gTUVUQS1JTkYvQ0VSVC5SU0FcbiAgICB6aXAuZXh0cmFjdEVudHJ5VG8oZW50cnksIGVudHJ5UGF0aCwgdHJ1ZSk7IC8vIG92ZXJ3cml0ZSA9IHRydWVcbiAgICBsb2cuZGVidWcoXCJleHRyYWN0ZWQhXCIpO1xuICAgIC8vIGNoZWNrIGZvciBtYXRjaFxuICAgIGxvZy5kZWJ1ZyhcIlByaW50aW5nIGFwayBtZDUuXCIpO1xuICAgIGxldCB7c3Rkb3V0fSA9IGF3YWl0IGV4ZWMoa2V5dG9vbCwgWyctdicsICctcHJpbnRjZXJ0JywgJy1maWxlJywgZW50cnlGaWxlXSk7XG4gICAgZW50cnlIYXNoID0gbWQ1cmUuZXhlYyhzdGRvdXQpO1xuICAgIGVudHJ5SGFzaCA9IGVudHJ5SGFzaCA/IGVudHJ5SGFzaFsxXSA6IG51bGw7XG4gICAgbG9nLmRlYnVnKGBlbnRyeUhhc2ggTUQ1OiAke2VudHJ5SGFzaH1gKTtcbiAgICBsb2cuZGVidWcoYGtleXN0b3JlIE1ENTogJHtrZXlzdG9yZUhhc2h9YCk7XG4gICAgbGV0IG1hdGNoZXNLZXlzdG9yZSA9IGVudHJ5SGFzaCAmJiBlbnRyeUhhc2ggPT09IGtleXN0b3JlSGFzaDtcbiAgICBsb2cuZGVidWcoYE1hdGNoZXMga2V5c3RvcmU/ICR7bWF0Y2hlc0tleXN0b3JlfWApO1xuICAgIGlmIChtYXRjaGVzS2V5c3RvcmUpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2U7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBhcGtTaWduaW5nTWV0aG9kcztcbiJdfQ==