appium-adb-test
Version:
Android Debug Bridge interface
497 lines (403 loc) • 34.1 kB
JavaScript
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 _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _appiumSupport = require('appium-support');
var _loggerJs = require('./logger.js');
var _loggerJs2 = _interopRequireDefault(_loggerJs);
var _admZip = require('adm-zip');
var _admZip2 = _interopRequireDefault(_admZip);
var _teen_process = require('teen_process');
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var rootDir = _path2['default'].resolve(__dirname, process.env.NO_PRECOMPILE ? '..' : '../..');
var androidPlatforms = ['android-4.2', 'android-17', 'android-4.3', 'android-18', 'android-4.4', 'android-19', 'android-L', 'android-20', 'android-5.0', 'android-21', 'android-22', 'android-MNC', 'android-23', 'android-6.0'];
function getDirectories(rootPath) {
var files, dirs, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, file, pathString;
return _regeneratorRuntime.async(function getDirectories$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
context$1$0.next = 2;
return _regeneratorRuntime.awrap(_appiumSupport.fs.readdir(rootPath));
case 2:
files = context$1$0.sent;
dirs = [];
_iteratorNormalCompletion = true;
_didIteratorError = false;
_iteratorError = undefined;
context$1$0.prev = 7;
_iterator = _getIterator(files);
case 9:
if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
context$1$0.next = 19;
break;
}
file = _step.value;
pathString = _path2['default'].resolve(rootPath, file);
context$1$0.next = 14;
return _regeneratorRuntime.awrap(_appiumSupport.fs.lstat(pathString));
case 14:
if (!context$1$0.sent.isDirectory()) {
context$1$0.next = 16;
break;
}
dirs.push(file);
case 16:
_iteratorNormalCompletion = true;
context$1$0.next = 9;
break;
case 19:
context$1$0.next = 25;
break;
case 21:
context$1$0.prev = 21;
context$1$0.t0 = context$1$0['catch'](7);
_didIteratorError = true;
_iteratorError = context$1$0.t0;
case 25:
context$1$0.prev = 25;
context$1$0.prev = 26;
if (!_iteratorNormalCompletion && _iterator['return']) {
_iterator['return']();
}
case 28:
context$1$0.prev = 28;
if (!_didIteratorError) {
context$1$0.next = 31;
break;
}
throw _iteratorError;
case 31:
return context$1$0.finish(28);
case 32:
return context$1$0.finish(25);
case 33:
return context$1$0.abrupt('return', dirs.sort());
case 34:
case 'end':
return context$1$0.stop();
}
}, null, this, [[7, 21, 25, 33], [26,, 28, 32]]);
}
function getAndroidPlatformAndPath() {
var androidHome, platforms, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, platform, platformPath;
return _regeneratorRuntime.async(function getAndroidPlatformAndPath$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
androidHome = process.env.ANDROID_HOME;
if (_lodash2['default'].isString(androidHome)) {
context$1$0.next = 4;
break;
}
_loggerJs2['default'].error("ANDROID_HOME was not exported!");
return context$1$0.abrupt('return', null);
case 4:
platforms = _path2['default'].resolve(androidHome, 'platforms');
_iteratorNormalCompletion2 = true;
_didIteratorError2 = false;
_iteratorError2 = undefined;
context$1$0.prev = 8;
_iterator2 = _getIterator(_lodash2['default'].clone(androidPlatforms).reverse());
case 10:
if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) {
context$1$0.next = 20;
break;
}
platform = _step2.value;
platformPath = _path2['default'].resolve(platforms, platform);
context$1$0.next = 15;
return _regeneratorRuntime.awrap(_appiumSupport.fs.exists(platformPath));
case 15:
if (!context$1$0.sent) {
context$1$0.next = 17;
break;
}
return context$1$0.abrupt('return', { platform: platform, platformPath: platformPath });
case 17:
_iteratorNormalCompletion2 = true;
context$1$0.next = 10;
break;
case 20:
context$1$0.next = 26;
break;
case 22:
context$1$0.prev = 22;
context$1$0.t0 = context$1$0['catch'](8);
_didIteratorError2 = true;
_iteratorError2 = context$1$0.t0;
case 26:
context$1$0.prev = 26;
context$1$0.prev = 27;
if (!_iteratorNormalCompletion2 && _iterator2['return']) {
_iterator2['return']();
}
case 29:
context$1$0.prev = 29;
if (!_didIteratorError2) {
context$1$0.next = 32;
break;
}
throw _iteratorError2;
case 32:
return context$1$0.finish(29);
case 33:
return context$1$0.finish(26);
case 34:
return context$1$0.abrupt('return', null);
case 35:
case 'end':
return context$1$0.stop();
}
}, null, this, [[8, 22, 26, 34], [27,, 29, 33]]);
}
function unzipFile(zipPath) {
var zip;
return _regeneratorRuntime.async(function unzipFile$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
_loggerJs2['default'].debug('Unzipping ' + zipPath);
context$1$0.prev = 1;
context$1$0.next = 4;
return _regeneratorRuntime.awrap(assertZipArchive(zipPath));
case 4:
if (!_appiumSupport.system.isWindows()) {
context$1$0.next = 10;
break;
}
zip = new _admZip2['default'](zipPath);
zip.extractAllTo(_path2['default'].dirname(zipPath), true);
_loggerJs2['default'].debug("Unzip successful");
context$1$0.next = 13;
break;
case 10:
context$1$0.next = 12;
return _regeneratorRuntime.awrap((0, _teen_process.exec)('unzip', ['-o', zipPath], { cwd: _path2['default'].dirname(zipPath) }));
case 12:
_loggerJs2['default'].debug("Unzip successful");
case 13:
context$1$0.next = 18;
break;
case 15:
context$1$0.prev = 15;
context$1$0.t0 = context$1$0['catch'](1);
throw new Error('Error occurred while unzipping. Original error: ' + context$1$0.t0.message);
case 18:
case 'end':
return context$1$0.stop();
}
}, null, this, [[1, 15]]);
}
function assertZipArchive(zipPath) {
var execOpts;
return _regeneratorRuntime.async(function assertZipArchive$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
_loggerJs2['default'].debug('Testing zip archive: ' + zipPath);
if (!_appiumSupport.system.isWindows()) {
context$1$0.next = 11;
break;
}
context$1$0.next = 4;
return _regeneratorRuntime.awrap(_appiumSupport.fs.exists(zipPath));
case 4:
if (!context$1$0.sent) {
context$1$0.next = 8;
break;
}
_loggerJs2['default'].debug("Zip archive tested clean");
context$1$0.next = 9;
break;
case 8:
throw new Error('Zip archive not present at ' + zipPath);
case 9:
context$1$0.next = 14;
break;
case 11:
execOpts = { cwd: _path2['default'].dirname(zipPath) };
context$1$0.next = 14;
return _regeneratorRuntime.awrap((0, _teen_process.exec)('unzip', ['-tq', zipPath], execOpts));
case 14:
case 'end':
return context$1$0.stop();
}
}, null, this);
}
function getIMEListFromOutput(stdout) {
var engines = [];
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
for (var _iterator3 = _getIterator(stdout.split('\n')), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var line = _step3.value;
if (line.length > 0 && line[0] !== ' ') {
// remove newline and trailing colon, and add to the list
engines.push(line.trim().replace(/:$/, ''));
}
}
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3['return']) {
_iterator3['return']();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
}
}
return engines;
}
function getJavaForOs() {
var sep = _path2['default'].sep;
var java = '' + getJavaHome() + sep + 'bin' + sep + 'java';
if (_appiumSupport.system.isWindows()) {
java = java + '.exe';
}
return java;
}
function getJavaHome() {
if (process.env.JAVA_HOME) {
return process.env.JAVA_HOME;
}
throw new Error("JAVA_HOME is not set currently. Please set JAVA_HOME.");
}
/*
* Checks mShowingLockscreen in dumpsys output to determine if lock screen is showing
*/
function isShowingLockscreen(dumpsys) {
var m = /mShowingLockscreen=\w+/gi.exec(dumpsys);
var ret = m && m.length && m[0].split('=')[1] === 'true' || false;
return ret;
}
/*
* Checks mCurrentFocus in dumpsys output to determine if Keyguard is activated
*/
function isCurrentFocusOnKeyguard(dumpsys) {
var m = /mCurrentFocus.+Keyguard/gi.exec(dumpsys);
return m && m.length && m[0] ? true : false;
}
/*
* Reads SurfaceOrientation in dumpsys output
*/
function getSurfaceOrientation(dumpsys) {
var m = /SurfaceOrientation: \d/gi.exec(dumpsys);
return m && parseInt(m[0].split(':')[1]);
}
/*
* Checks mScreenOnFully in dumpsys output to determine if screen is showing
* Default is true
*/
function isScreenOnFully(dumpsys) {
var m = /mScreenOnFully=\w+/gi.exec(dumpsys);
return !m || // if information is missing we assume screen is fully on
m && m.length > 0 && m[0].split('=')[1] === 'true' || false;
}
function buildStartCmd(startAppOptions, apiLevel) {
var cmd = ['am', 'start', '-W', '-n', startAppOptions.pkg + '/' + startAppOptions.activity];
if (startAppOptions.stopApp && apiLevel >= 15) {
cmd.push('-S');
}
if (startAppOptions.action) {
cmd.push('-a', startAppOptions.action);
}
if (startAppOptions.category) {
cmd.push('-c', startAppOptions.category);
}
if (startAppOptions.flags) {
cmd.push('-f', startAppOptions.flags);
}
if (startAppOptions.optionalIntentArguments) {
// expect optionalIntentArguments to be a single string of the form:
// "-flag key"
// "-flag key value"
// or a combination of these (e.g., "-flag1 key1 -flag2 key2 value2")
// take a string and parse out the part before any spaces, and anything after
// the first space
var parseKeyValue = function parseKeyValue(str) {
str = str.trim();
var space = str.indexOf(' ');
if (space === -1) {
return str.length ? [str] : [];
} else {
return [str.substring(0, space).trim(), str.substring(space + 1).trim()];
}
};
// cycle through the optionalIntentArguments and pull out the arguments
// add a space initially so flags can be distinguished from arguments that
// have internal hyphens
var optionalIntentArguments = ' ' + startAppOptions.optionalIntentArguments;
var re = / (-[^\s]+) (.+)/;
while (true) {
// eslint-disable-line no-constant-condition
var args = re.exec(optionalIntentArguments);
if (!args) {
if (optionalIntentArguments.length) {
// no more flags, so the remainder can be treated as 'key' or 'key value'
cmd.push.apply(cmd, parseKeyValue(optionalIntentArguments));
}
// we are done
break;
}
// take the flag and see if it is at the beginning of the string
// if it is not, then it means we have been through already, and
// what is before the flag is the argument for the previous flag
var flag = args[1];
var flagPos = optionalIntentArguments.indexOf(flag);
if (flagPos !== 0) {
var prevArgs = optionalIntentArguments.substring(0, flagPos);
cmd.push.apply(cmd, parseKeyValue(prevArgs));
}
// add the flag, as there are no more earlier arguments
cmd.push(flag);
// make optionalIntentArguments hold the remainder
optionalIntentArguments = args[2];
}
}
return cmd;
}
// turns pkg.activity.name to .activity.name
// also turns activity.name to .activity.name
function getPossibleActivityNames(pkgName, activityName) {
var names = [activityName];
// need to beware of namespaces with overlapping chars:
// com.foo.bar
// com.foo.barx
if (activityName.indexOf(pkgName + '.') === 0) {
names.push(activityName.substring(pkgName.length));
}
if (activityName[0] !== '.') {
names.push('.' + activityName);
}
return names;
}
exports.getDirectories = getDirectories;
exports.getAndroidPlatformAndPath = getAndroidPlatformAndPath;
exports.unzipFile = unzipFile;
exports.assertZipArchive = assertZipArchive;
exports.getIMEListFromOutput = getIMEListFromOutput;
exports.getJavaForOs = getJavaForOs;
exports.isShowingLockscreen = isShowingLockscreen;
exports.isCurrentFocusOnKeyguard = isCurrentFocusOnKeyguard;
exports.getSurfaceOrientation = getSurfaceOrientation;
exports.isScreenOnFully = isScreenOnFully;
exports.buildStartCmd = buildStartCmd;
exports.getPossibleActivityNames = getPossibleActivityNames;
exports.getJavaHome = getJavaHome;
exports.rootDir = rootDir;
exports.androidPlatforms = androidPlatforms;
// It is not a clean way to sort it, but in this case would work fine because
// we have numerics and alphanumeric
// will return some thing like this
// ["17.0.0", "18.0.1", "19.0.0", "19.0.1", "19.1.0", "20.0.0",
// "android-4.2.2", "android-4.3", "android-4.4"]
// get the latest platform and path
//# sourceMappingURL=data:application/json;charset=utf8;base64,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dCI6WyJpbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcclxuaW1wb3J0IHsgc3lzdGVtLCBmcyB9IGZyb20gJ2FwcGl1bS1zdXBwb3J0JztcclxuaW1wb3J0IGxvZyBmcm9tICcuL2xvZ2dlci5qcyc7XHJcbmltcG9ydCBBZG1aaXAgZnJvbSAnYWRtLXppcCc7XHJcbmltcG9ydCB7IGV4ZWMgfSBmcm9tICd0ZWVuX3Byb2Nlc3MnO1xyXG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xyXG5cclxuXHJcbmNvbnN0IHJvb3REaXIgPSBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCBwcm9jZXNzLmVudi5OT19QUkVDT01QSUxFID8gJy4uJyA6ICcuLi8uLicpO1xyXG5jb25zdCBhbmRyb2lkUGxhdGZvcm1zID0gWydhbmRyb2lkLTQuMicsICdhbmRyb2lkLTE3JywgJ2FuZHJvaWQtNC4zJywgJ2FuZHJvaWQtMTgnLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdhbmRyb2lkLTQuNCcsICdhbmRyb2lkLTE5JywgJ2FuZHJvaWQtTCcsICdhbmRyb2lkLTIwJyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAnYW5kcm9pZC01LjAnLCAnYW5kcm9pZC0yMScsICdhbmRyb2lkLTIyJywgJ2FuZHJvaWQtTU5DJyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAnYW5kcm9pZC0yMycsICdhbmRyb2lkLTYuMCddO1xyXG5cclxuYXN5bmMgZnVuY3Rpb24gZ2V0RGlyZWN0b3JpZXMgKHJvb3RQYXRoKSB7XHJcbiAgbGV0IGZpbGVzID0gYXdhaXQgZnMucmVhZGRpcihyb290UGF0aCk7XHJcbiAgbGV0IGRpcnMgPSBbXTtcclxuICBmb3IgKGxldCBmaWxlIG9mIGZpbGVzKSB7XHJcbiAgICBsZXQgcGF0aFN0cmluZyA9IHBhdGgucmVzb2x2ZShyb290UGF0aCwgZmlsZSk7XHJcbiAgICBpZiAoKGF3YWl0IGZzLmxzdGF0KHBhdGhTdHJpbmcpKS5pc0RpcmVjdG9yeSgpKSB7XHJcbiAgICAgIGRpcnMucHVzaChmaWxlKTtcclxuICAgIH1cclxuICB9XHJcbiAgLy8gSXQgaXMgbm90IGEgY2xlYW4gd2F5IHRvIHNvcnQgaXQsIGJ1dCBpbiB0aGlzIGNhc2Ugd291bGQgd29yayBmaW5lIGJlY2F1c2VcclxuICAvLyB3ZSBoYXZlIG51bWVyaWNzIGFuZCBhbHBoYW51bWVyaWNcclxuICAvLyB3aWxsIHJldHVybiBzb21lIHRoaW5nIGxpa2UgdGhpc1xyXG4gIC8vIFtcIjE3LjAuMFwiLCBcIjE4LjAuMVwiLCBcIjE5LjAuMFwiLCBcIjE5LjAuMVwiLCBcIjE5LjEuMFwiLCBcIjIwLjAuMFwiLFxyXG4gIC8vICBcImFuZHJvaWQtNC4yLjJcIiwgXCJhbmRyb2lkLTQuM1wiLCBcImFuZHJvaWQtNC40XCJdXHJcbiAgcmV0dXJuIGRpcnMuc29ydCgpO1xyXG59XHJcblxyXG5hc3luYyBmdW5jdGlvbiBnZXRBbmRyb2lkUGxhdGZvcm1BbmRQYXRoICgpIHtcclxuICBjb25zdCBhbmRyb2lkSG9tZSA9IHByb2Nlc3MuZW52LkFORFJPSURfSE9NRTtcclxuICBpZiAoIV8uaXNTdHJpbmcoYW5kcm9pZEhvbWUpKSB7XHJcbiAgICBsb2cuZXJyb3IoXCJBTkRST0lEX0hPTUUgd2FzIG5vdCBleHBvcnRlZCFcIik7XHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIC8vIGdldCB0aGUgbGF0ZXN0IHBsYXRmb3JtIGFuZCBwYXRoXHJcbiAgbGV0IHBsYXRmb3JtcyA9IHBhdGgucmVzb2x2ZShhbmRyb2lkSG9tZSwgJ3BsYXRmb3JtcycpO1xyXG4gIGZvciAobGV0IHBsYXRmb3JtIG9mIF8uY2xvbmUoYW5kcm9pZFBsYXRmb3JtcykucmV2ZXJzZSgpKSB7XHJcbiAgICBsZXQgcGxhdGZvcm1QYXRoID0gcGF0aC5yZXNvbHZlKHBsYXRmb3JtcywgcGxhdGZvcm0pO1xyXG4gICAgaWYgKGF3YWl0IGZzLmV4aXN0cyhwbGF0Zm9ybVBhdGgpKSB7XHJcbiAgICAgIHJldHVybiB7cGxhdGZvcm0sIHBsYXRmb3JtUGF0aH07XHJcbiAgICB9XHJcbiAgfVxyXG4gIHJldHVybiBudWxsO1xyXG59XHJcblxyXG5hc3luYyBmdW5jdGlvbiB1bnppcEZpbGUgKHppcFBhdGgpIHtcclxuICBsb2cuZGVidWcoYFVuemlwcGluZyAke3ppcFBhdGh9YCk7XHJcbiAgdHJ5IHtcclxuICAgIGF3YWl0IGFzc2VydFppcEFyY2hpdmUoemlwUGF0aCk7XHJcbiAgICBpZiAoc3lzdGVtLmlzV2luZG93cygpKSB7XHJcbiAgICAgIGxldCB6aXAgPSBuZXcgQWRtWmlwKHppcFBhdGgpO1xyXG4gICAgICB6aXAuZXh0cmFjdEFsbFRvKHBhdGguZGlybmFtZSh6aXBQYXRoKSwgdHJ1ZSk7XHJcbiAgICAgIGxvZy5kZWJ1ZyhcIlVuemlwIHN1Y2Nlc3NmdWxcIik7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBhd2FpdCBleGVjKCd1bnppcCcsIFsnLW8nLCB6aXBQYXRoXSwge2N3ZDogcGF0aC5kaXJuYW1lKHppcFBhdGgpfSk7XHJcbiAgICAgIGxvZy5kZWJ1ZyhcIlVuemlwIHN1Y2Nlc3NmdWxcIik7XHJcbiAgICB9XHJcbiAgfSBjYXRjaCAoZSkge1xyXG4gICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBvY2N1cnJlZCB3aGlsZSB1bnppcHBpbmcuIE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKTtcclxuICB9XHJcbn1cclxuXHJcbmFzeW5jIGZ1bmN0aW9uIGFzc2VydFppcEFyY2hpdmUgKHppcFBhdGgpIHtcclxuICBsb2cuZGVidWcoYFRlc3RpbmcgemlwIGFyY2hpdmU6ICR7emlwUGF0aH1gKTtcclxuICBpZiAoc3lzdGVtLmlzV2luZG93cygpKSB7XHJcbiAgICBpZiAoYXdhaXQgZnMuZXhpc3RzKHppcFBhdGgpKSB7XHJcbiAgICAgIGxvZy5kZWJ1ZyhcIlppcCBhcmNoaXZlIHRlc3RlZCBjbGVhblwiKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihgWmlwIGFyY2hpdmUgbm90IHByZXNlbnQgYXQgJHt6aXBQYXRofWApO1xyXG4gICAgfVxyXG4gIH0gZWxzZSB7XHJcbiAgICBsZXQgZXhlY09wdHMgPSB7Y3dkOiBwYXRoLmRpcm5hbWUoemlwUGF0aCl9O1xyXG4gICAgYXdhaXQgZXhlYygndW56aXAnLCBbJy10cScsIHppcFBhdGhdLCBleGVjT3B0cyk7XHJcbiAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRJTUVMaXN0RnJvbU91dHB1dCAoc3Rkb3V0KSB7XHJcbiAgbGV0IGVuZ2luZXMgPSBbXTtcclxuICBmb3IgKGxldCBsaW5lIG9mIHN0ZG91dC5zcGxpdCgnXFxuJykpIHtcclxuICAgIGlmIChsaW5lLmxlbmd0aCA+IDAgJiYgbGluZVswXSAhPT0gJyAnKSB7XHJcbiAgICAgIC8vIHJlbW92ZSBuZXdsaW5lIGFuZCB0cmFpbGluZyBjb2xvbiwgYW5kIGFkZCB0byB0aGUgbGlzdFxyXG4gICAgICBlbmdpbmVzLnB1c2gobGluZS50cmltKCkucmVwbGFjZSgvOiQvLCAnJykpO1xyXG4gICAgfVxyXG4gIH1cclxuICByZXR1cm4gZW5naW5lcztcclxufVxyXG5cclxuZnVuY3Rpb24gZ2V0SmF2YUZvck9zICgpIHtcclxuICBjb25zdCBzZXAgPSBwYXRoLnNlcDtcclxuICBsZXQgamF2YSA9IGAke2dldEphdmFIb21lKCl9JHtzZXB9YmluJHtzZXB9amF2YWA7XHJcbiAgaWYgKHN5c3RlbS5pc1dpbmRvd3MoKSkge1xyXG4gICAgamF2YSA9IGphdmEgKyAnLmV4ZSc7XHJcbiAgfVxyXG4gIHJldHVybiBqYXZhO1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRKYXZhSG9tZSAoKSB7XHJcbiAgaWYgKHByb2Nlc3MuZW52LkpBVkFfSE9NRSkge1xyXG4gICAgcmV0dXJuIHByb2Nlc3MuZW52LkpBVkFfSE9NRTtcclxuICB9XHJcbiAgdGhyb3cgbmV3IEVycm9yKFwiSkFWQV9IT01FIGlzIG5vdCBzZXQgY3VycmVudGx5LiBQbGVhc2Ugc2V0IEpBVkFfSE9NRS5cIik7XHJcbn1cclxuXHJcbi8qXHJcbiAqIENoZWNrcyBtU2hvd2luZ0xvY2tzY3JlZW4gaW4gZHVtcHN5cyBvdXRwdXQgdG8gZGV0ZXJtaW5lIGlmIGxvY2sgc2NyZWVuIGlzIHNob3dpbmdcclxuICovXHJcbmZ1bmN0aW9uIGlzU2hvd2luZ0xvY2tzY3JlZW4gKGR1bXBzeXMpIHtcclxuICBsZXQgbSA9IC9tU2hvd2luZ0xvY2tzY3JlZW49XFx3Ky9naS5leGVjKGR1bXBzeXMpO1xyXG4gIGxldCByZXQgPSAobSAmJiBtLmxlbmd0aCAmJiBtWzBdLnNwbGl0KCc9JylbMV0gPT09ICd0cnVlJykgfHwgZmFsc2U7XHJcbiAgcmV0dXJuIHJldDtcclxufVxyXG5cclxuLypcclxuICogQ2hlY2tzIG1DdXJyZW50Rm9jdXMgaW4gZHVtcHN5cyBvdXRwdXQgdG8gZGV0ZXJtaW5lIGlmIEtleWd1YXJkIGlzIGFjdGl2YXRlZFxyXG4gKi9cclxuZnVuY3Rpb24gaXNDdXJyZW50Rm9jdXNPbktleWd1YXJkIChkdW1wc3lzKSB7XHJcbiAgbGV0IG0gPSAvbUN1cnJlbnRGb2N1cy4rS2V5Z3VhcmQvZ2kuZXhlYyhkdW1wc3lzKTtcclxuICByZXR1cm4gKG0gJiYgbS5sZW5ndGggJiYgbVswXSkgPyB0cnVlIDogZmFsc2U7XHJcbn1cclxuXHJcbi8qXHJcbiAqIFJlYWRzIFN1cmZhY2VPcmllbnRhdGlvbiBpbiBkdW1wc3lzIG91dHB1dFxyXG4gKi9cclxuZnVuY3Rpb24gZ2V0U3VyZmFjZU9yaWVudGF0aW9uIChkdW1wc3lzKSB7XHJcbiAgbGV0IG0gPSAvU3VyZmFjZU9yaWVudGF0aW9uOiBcXGQvZ2kuZXhlYyhkdW1wc3lzKTtcclxuICByZXR1cm4gbSAmJiBwYXJzZUludChtWzBdLnNwbGl0KCc6JylbMV0pO1xyXG59XHJcblxyXG4vKlxyXG4gKiBDaGVja3MgbVNjcmVlbk9uRnVsbHkgaW4gZHVtcHN5cyBvdXRwdXQgdG8gZGV0ZXJtaW5lIGlmIHNjcmVlbiBpcyBzaG93aW5nXHJcbiAqIERlZmF1bHQgaXMgdHJ1ZVxyXG4gKi9cclxuZnVuY3Rpb24gaXNTY3JlZW5PbkZ1bGx5IChkdW1wc3lzKSB7XHJcbiAgbGV0IG0gPSAvbVNjcmVlbk9uRnVsbHk9XFx3Ky9naS5leGVjKGR1bXBzeXMpO1xyXG4gIHJldHVybiAhbSB8fCAvLyBpZiBpbmZvcm1hdGlvbiBpcyBtaXNzaW5nIHdlIGFzc3VtZSBzY3JlZW4gaXMgZnVsbHkgb25cclxuICAgICAgICAgKG0gJiYgbS5sZW5ndGggPiAwICYmIG1bMF0uc3BsaXQoJz0nKVsxXSA9PT0gJ3RydWUnKSB8fCBmYWxzZTtcclxufVxyXG5cclxuZnVuY3Rpb24gYnVpbGRTdGFydENtZCAoc3RhcnRBcHBPcHRpb25zLCBhcGlMZXZlbCkge1xyXG4gIGxldCBjbWQgPSBbJ2FtJywgJ3N0YXJ0JywgJy1XJywgJy1uJywgYCR7c3RhcnRBcHBPcHRpb25zLnBrZ30vJHtzdGFydEFwcE9wdGlvbnMuYWN0aXZpdHl9YF07XHJcbiAgaWYgKHN0YXJ0QXBwT3B0aW9ucy5zdG9wQXBwICYmIGFwaUxldmVsID49IDE1KSB7XHJcbiAgICBjbWQucHVzaCgnLVMnKTtcclxuICB9XHJcbiAgaWYgKHN0YXJ0QXBwT3B0aW9ucy5hY3Rpb24pIHtcclxuICAgIGNtZC5wdXNoKCctYScsIHN0YXJ0QXBwT3B0aW9ucy5hY3Rpb24pO1xyXG4gIH1cclxuICBpZiAoc3RhcnRBcHBPcHRpb25zLmNhdGVnb3J5KSB7XHJcbiAgICBjbWQucHVzaCgnLWMnLCBzdGFydEFwcE9wdGlvbnMuY2F0ZWdvcnkpO1xyXG4gIH1cclxuICBpZiAoc3RhcnRBcHBPcHRpb25zLmZsYWdzKSB7XHJcbiAgICBjbWQucHVzaCgnLWYnLCBzdGFydEFwcE9wdGlvbnMuZmxhZ3MpO1xyXG4gIH1cclxuICBpZiAoc3RhcnRBcHBPcHRpb25zLm9wdGlvbmFsSW50ZW50QXJndW1lbnRzKSB7XHJcbiAgICAvLyBleHBlY3Qgb3B0aW9uYWxJbnRlbnRBcmd1bWVudHMgdG8gYmUgYSBzaW5nbGUgc3RyaW5nIG9mIHRoZSBmb3JtOlxyXG4gICAgLy8gICAgIFwiLWZsYWcga2V5XCJcclxuICAgIC8vICAgICBcIi1mbGFnIGtleSB2YWx1ZVwiXHJcbiAgICAvLyBvciBhIGNvbWJpbmF0aW9uIG9mIHRoZXNlIChlLmcuLCBcIi1mbGFnMSBrZXkxIC1mbGFnMiBrZXkyIHZhbHVlMlwiKVxyXG5cclxuICAgIC8vIHRha2UgYSBzdHJpbmcgYW5kIHBhcnNlIG91dCB0aGUgcGFydCBiZWZvcmUgYW55IHNwYWNlcywgYW5kIGFueXRoaW5nIGFmdGVyXHJcbiAgICAvLyB0aGUgZmlyc3Qgc3BhY2VcclxuICAgIGxldCBwYXJzZUtleVZhbHVlID0gZnVuY3Rpb24gKHN0cikge1xyXG4gICAgICBzdHIgPSBzdHIudHJpbSgpO1xyXG4gICAgICBsZXQgc3BhY2UgPSBzdHIuaW5kZXhPZignICcpO1xyXG4gICAgICBpZiAoc3BhY2UgPT09IC0xKSB7XHJcbiAgICAgICAgcmV0dXJuIHN0ci5sZW5ndGggPyBbc3RyXSA6IFtdO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJldHVybiBbc3RyLnN1YnN0cmluZygwLCBzcGFjZSkudHJpbSgpLCBzdHIuc3Vic3RyaW5nKHNwYWNlICsgMSkudHJpbSgpXTtcclxuICAgICAgfVxyXG4gICAgfTtcclxuXHJcbiAgICAvLyBjeWNsZSB0aHJvdWdoIHRoZSBvcHRpb25hbEludGVudEFyZ3VtZW50cyBhbmQgcHVsbCBvdXQgdGhlIGFyZ3VtZW50c1xyXG4gICAgLy8gYWRkIGEgc3BhY2UgaW5pdGlhbGx5IHNvIGZsYWdzIGNhbiBiZSBkaXN0aW5ndWlzaGVkIGZyb20gYXJndW1lbnRzIHRoYXRcclxuICAgIC8vIGhhdmUgaW50ZXJuYWwgaHlwaGVuc1xyXG4gICAgbGV0IG9wdGlvbmFsSW50ZW50QXJndW1lbnRzID0gYCAke3N0YXJ0QXBwT3B0aW9ucy5vcHRpb25hbEludGVudEFyZ3VtZW50c31gO1xyXG4gICAgbGV0IHJlID0gLyAoLVteXFxzXSspICguKykvO1xyXG4gICAgd2hpbGUgKHRydWUpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1jb25zdGFudC1jb25kaXRpb25cclxuICAgICAgbGV0IGFyZ3MgPSByZS5leGVjKG9wdGlvbmFsSW50ZW50QXJndW1lbnRzKTtcclxuICAgICAgaWYgKCFhcmdzKSB7XHJcbiAgICAgICAgaWYgKG9wdGlvbmFsSW50ZW50QXJndW1lbnRzLmxlbmd0aCkge1xyXG4gICAgICAgICAgLy8gbm8gbW9yZSBmbGFncywgc28gdGhlIHJlbWFpbmRlciBjYW4gYmUgdHJlYXRlZCBhcyAna2V5JyBvciAna2V5IHZhbHVlJ1xyXG4gICAgICAgICAgY21kLnB1c2guYXBwbHkoY21kLCBwYXJzZUtleVZhbHVlKG9wdGlvbmFsSW50ZW50QXJndW1lbnRzKSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIHdlIGFyZSBkb25lXHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIHRha2UgdGhlIGZsYWcgYW5kIHNlZSBpZiBpdCBpcyBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzdHJpbmdcclxuICAgICAgLy8gaWYgaXQgaXMgbm90LCB0aGVuIGl0IG1lYW5zIHdlIGhhdmUgYmVlbiB0aHJvdWdoIGFscmVhZHksIGFuZFxyXG4gICAgICAvLyB3aGF0IGlzIGJlZm9yZSB0aGUgZmxhZyBpcyB0aGUgYXJndW1lbnQgZm9yIHRoZSBwcmV2aW91cyBmbGFnXHJcbiAgICAgIGxldCBmbGFnID0gYXJnc1sxXTtcclxuICAgICAgbGV0IGZsYWdQb3MgPSBvcHRpb25hbEludGVudEFyZ3VtZW50cy5pbmRleE9mKGZsYWcpO1xyXG4gICAgICBpZiAoZmxhZ1BvcyAhPT0gMCkge1xyXG4gICAgICAgIGxldCBwcmV2QXJncyA9IG9wdGlvbmFsSW50ZW50QXJndW1lbnRzLnN1YnN0cmluZygwLCBmbGFnUG9zKTtcclxuICAgICAgICBjbWQucHVzaC5hcHBseShjbWQsIHBhcnNlS2V5VmFsdWUocHJldkFyZ3MpKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gYWRkIHRoZSBmbGFnLCBhcyB0aGVyZSBhcmUgbm8gbW9yZSBlYXJsaWVyIGFyZ3VtZW50c1xyXG4gICAgICBjbWQucHVzaChmbGFnKTtcclxuXHJcbiAgICAgIC8vIG1ha2Ugb3B0aW9uYWxJbnRlbnRBcmd1bWVudHMgaG9sZCB0aGUgcmVtYWluZGVyXHJcbiAgICAgIG9wdGlvbmFsSW50ZW50QXJndW1lbnRzID0gYXJnc1syXTtcclxuICAgIH1cclxuICB9XHJcbiAgcmV0dXJuIGNtZDtcclxufVxyXG5cclxuLy8gdHVybnMgcGtnLmFjdGl2aXR5Lm5hbWUgdG8gLmFjdGl2aXR5Lm5hbWVcclxuLy8gYWxzbyB0dXJucyBhY3Rpdml0eS5uYW1lIHRvIC5hY3Rpdml0eS5uYW1lXHJcbmZ1bmN0aW9uIGdldFBvc3NpYmxlQWN0aXZpdHlOYW1lcyAocGtnTmFtZSwgYWN0aXZpdHlOYW1lKSB7XHJcbiAgbGV0IG5hbWVzID0gW2FjdGl2aXR5TmFtZV07XHJcbiAgLy8gbmVlZCB0byBiZXdhcmUgb2YgbmFtZXNwYWNlcyB3aXRoIG92ZXJsYXBwaW5nIGNoYXJzOlxyXG4gIC8vICAgY29tLmZvby5iYXJcclxuICAvLyAgIGNvbS5mb28uYmFyeFxyXG4gIGlmIChhY3Rpdml0eU5hbWUuaW5kZXhPZihgJHtwa2dOYW1lfS5gKSA9PT0gMCkge1xyXG4gICAgbmFtZXMucHVzaChhY3Rpdml0eU5hbWUuc3Vic3RyaW5nKHBrZ05hbWUubGVuZ3RoKSk7XHJcbiAgfVxyXG4gIGlmIChhY3Rpdml0eU5hbWVbMF0gIT09ICcuJykge1xyXG4gICAgbmFtZXMucHVzaChgLiR7YWN0aXZpdHlOYW1lfWApO1xyXG4gIH1cclxuICByZXR1cm4gbmFtZXM7XHJcbn1cclxuXHJcbmV4cG9ydCB7IGdldERpcmVjdG9yaWVzLCBnZXRBbmRyb2lkUGxhdGZvcm1BbmRQYXRoLCB1bnppcEZpbGUsIGFzc2VydFppcEFyY2hpdmUsXHJcbiAgICAgICAgIGdldElNRUxpc3RGcm9tT3V0cHV0LCBnZXRKYXZhRm9yT3MsIGlzU2hvd2luZ0xvY2tzY3JlZW4sIGlzQ3VycmVudEZvY3VzT25LZXlndWFyZCxcclxuICAgICAgICAgZ2V0U3VyZmFjZU9yaWVudGF0aW9uLCBpc1NjcmVlbk9uRnVsbHksIGJ1aWxkU3RhcnRDbWQsIGdldFBvc3NpYmxlQWN0aXZpdHlOYW1lcyxcclxuICAgICAgICAgZ2V0SmF2YUhvbWUsIHJvb3REaXIsIGFuZHJvaWRQbGF0Zm9ybXMgfTtcclxuIl0sInNvdXJjZVJvb3QiOiIuLlxcLi4ifQ==
;