android-manifest.js
29.1 KB
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
require("source-map-support/register");
var _teen_process = require("teen_process");
var _logger = _interopRequireDefault(require("../logger.js"));
var _helpers = require("../helpers.js");
var _appiumSupport = require("appium-support");
var _lodash = _interopRequireDefault(require("lodash"));
var _path = _interopRequireDefault(require("path"));
var _adbkitApkreader = _interopRequireDefault(require("adbkit-apkreader"));
let manifestMethods = {};
manifestMethods.packageAndLaunchActivityFromManifest = async function packageAndLaunchActivityFromManifest(appPath) {
if (appPath.endsWith(_helpers.APKS_EXTENSION)) {
appPath = await this.extractBaseApk(appPath);
}
const apkReader = await _adbkitApkreader.default.open(appPath);
const manifest = await apkReader.readManifest();
const {
pkg,
activity
} = (0, _helpers.parseManifest)(manifest);
_logger.default.info(`Package name: '${pkg}'`);
_logger.default.info(`Main activity name: '${activity}'`);
return {
apkPackage: pkg,
apkActivity: activity
};
};
manifestMethods.targetSdkVersionFromManifest = async function targetSdkVersionFromManifest(appPath) {
_logger.default.debug(`Extracting target SDK version of '${appPath}'`);
const originalAppPath = appPath;
if (appPath.endsWith(_helpers.APKS_EXTENSION)) {
appPath = await this.extractBaseApk(appPath);
}
const getTargetSdkViaApkReader = async () => {
const apkReader = await _adbkitApkreader.default.open(appPath);
const manifest = await apkReader.readManifest();
if (manifest.usesSdk && _lodash.default.isInteger(manifest.usesSdk.targetSdkVersion)) {
return manifest.usesSdk.targetSdkVersion;
}
throw new Error('Cannot find the information about targetSdkVersion in the manifest');
};
const getTargetSdkViaAapt = async () => {
await this.initAapt();
const args = ['dump', 'badging', appPath];
const {
stdout
} = await (0, _teen_process.exec)(this.binaries.aapt, args);
const targetSdkVersion = /targetSdkVersion:'([^']+)'/g.exec(stdout);
if (!targetSdkVersion) {
_logger.default.debug(stdout);
throw new Error('Cannot parse the command output');
}
return parseInt(targetSdkVersion[1], 10);
};
const versionGetters = [['ApkReader', getTargetSdkViaApkReader], ['aapt', getTargetSdkViaAapt]];
for (const [toolName, versionGetter] of versionGetters) {
try {
return await versionGetter();
} catch (e) {
_logger.default.info(`Cannot extract targetSdkVersion of '${originalAppPath}' using ${toolName}. ` + `Original error: ${e.message}`);
}
}
throw new Error(`Cannot extract the target SDK version number of '${originalAppPath}' using either of ` + `${JSON.stringify(versionGetters.map(pair => pair[0]))} tools. ` + `Check the server log for more details`);
};
manifestMethods.targetSdkVersionUsingPKG = async function targetSdkVersionUsingPKG(pkg, cmdOutput = null) {
let stdout = cmdOutput || (await this.shell(['dumpsys', 'package', pkg]));
let targetSdkVersion = new RegExp(/targetSdk=([^\s\s]+)/g).exec(stdout);
if (targetSdkVersion && targetSdkVersion.length >= 2) {
targetSdkVersion = targetSdkVersion[1];
} else {
targetSdkVersion = 0;
}
return parseInt(targetSdkVersion, 10);
};
manifestMethods.compileManifest = async function compileManifest(manifest, manifestPackage, targetPackage) {
const {
platform,
platformPath
} = await (0, _helpers.getAndroidPlatformAndPath)();
if (!platform) {
throw new Error('Cannot compile the manifest. The required platform does not exist (API level >= 17)');
}
const resultPath = `${manifest}.apk`;
const androidJarPath = _path.default.resolve(platformPath, 'android.jar');
if (await _appiumSupport.fs.exists(resultPath)) {
await _appiumSupport.fs.rimraf(resultPath);
}
try {
await this.initAapt2();
const args = ['link', '-o', resultPath, '--manifest', manifest, '--rename-manifest-package', manifestPackage, '--rename-instrumentation-target-package', targetPackage, '-I', androidJarPath, '-v'];
_logger.default.debug(`Compiling the manifest using '${_appiumSupport.util.quote([this.binaries.aapt2, ...args])}'`);
await (0, _teen_process.exec)(this.binaries.aapt2, args);
} catch (e) {
_logger.default.debug('Cannot compile the manifest using aapt2. Defaulting to aapt. ' + `Original error: ${e.stderr || e.message}`);
await this.initAapt();
const args = ['package', '-M', manifest, '--rename-manifest-package', manifestPackage, '--rename-instrumentation-target-package', targetPackage, '-I', androidJarPath, '-F', resultPath, '-f'];
_logger.default.debug(`Compiling the manifest using '${_appiumSupport.util.quote([this.binaries.aapt, ...args])}'`);
try {
await (0, _teen_process.exec)(this.binaries.aapt, args);
} catch (e1) {
throw new Error(`Cannot compile the manifest. Original error: ${e1.stderr || e1.message}`);
}
}
_logger.default.debug(`Compiled the manifest at '${resultPath}'`);
};
manifestMethods.insertManifest = async function insertManifest(manifest, srcApk, dstApk) {
_logger.default.debug(`Inserting manifest '${manifest}', src: '${srcApk}', dst: '${dstApk}'`);
await _appiumSupport.zip.assertValidZip(srcApk);
await (0, _helpers.unzipFile)(`${manifest}.apk`);
const manifestName = _path.default.basename(manifest);
try {
await this.initAapt();
await _appiumSupport.fs.copyFile(srcApk, dstApk);
_logger.default.debug('Moving manifest');
try {
await (0, _teen_process.exec)(this.binaries.aapt, ['remove', dstApk, manifestName]);
} catch (ign) {}
await (0, _teen_process.exec)(this.binaries.aapt, ['add', dstApk, manifestName], {
cwd: _path.default.dirname(manifest)
});
} catch (e) {
_logger.default.debug('Cannot insert manifest using aapt. Defaulting to zip. ' + `Original error: ${e.stderr || e.message}`);
const tmpRoot = await _appiumSupport.tempDir.openDir();
try {
_logger.default.debug(`Extracting the source apk at '${srcApk}'`);
await _appiumSupport.zip.extractAllTo(srcApk, tmpRoot);
_logger.default.debug('Moving manifest');
await _appiumSupport.fs.mv(manifest, _path.default.resolve(tmpRoot, manifestName));
_logger.default.debug(`Collecting the destination apk at '${dstApk}'`);
await _appiumSupport.zip.toArchive(dstApk, {
cwd: tmpRoot
});
} finally {
await _appiumSupport.fs.rimraf(tmpRoot);
}
}
_logger.default.debug(`Manifest insertion into '${dstApk}' is completed`);
};
manifestMethods.hasInternetPermissionFromManifest = async function hasInternetPermissionFromManifest(appPath) {
_logger.default.debug(`Checking if '${appPath}' requires internet access permission in the manifest`);
if (appPath.endsWith(_helpers.APKS_EXTENSION)) {
appPath = await this.extractBaseApk(appPath);
}
const apkReader = await _adbkitApkreader.default.open(appPath);
const manifest = await apkReader.readManifest();
return (manifest.usesPermissions || []).some(({
name
}) => name === 'android.permission.INTERNET');
};
var _default = manifestMethods;
exports.default = _default;require('source-map-support').install();
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi90b29scy9hbmRyb2lkLW1hbmlmZXN0LmpzIl0sIm5hbWVzIjpbIm1hbmlmZXN0TWV0aG9kcyIsInBhY2thZ2VBbmRMYXVuY2hBY3Rpdml0eUZyb21NYW5pZmVzdCIsImFwcFBhdGgiLCJlbmRzV2l0aCIsIkFQS1NfRVhURU5TSU9OIiwiZXh0cmFjdEJhc2VBcGsiLCJhcGtSZWFkZXIiLCJBcGtSZWFkZXIiLCJvcGVuIiwibWFuaWZlc3QiLCJyZWFkTWFuaWZlc3QiLCJwa2ciLCJhY3Rpdml0eSIsImxvZyIsImluZm8iLCJhcGtQYWNrYWdlIiwiYXBrQWN0aXZpdHkiLCJ0YXJnZXRTZGtWZXJzaW9uRnJvbU1hbmlmZXN0IiwiZGVidWciLCJvcmlnaW5hbEFwcFBhdGgiLCJnZXRUYXJnZXRTZGtWaWFBcGtSZWFkZXIiLCJ1c2VzU2RrIiwiXyIsImlzSW50ZWdlciIsInRhcmdldFNka1ZlcnNpb24iLCJFcnJvciIsImdldFRhcmdldFNka1ZpYUFhcHQiLCJpbml0QWFwdCIsImFyZ3MiLCJzdGRvdXQiLCJiaW5hcmllcyIsImFhcHQiLCJleGVjIiwicGFyc2VJbnQiLCJ2ZXJzaW9uR2V0dGVycyIsInRvb2xOYW1lIiwidmVyc2lvbkdldHRlciIsImUiLCJtZXNzYWdlIiwiSlNPTiIsInN0cmluZ2lmeSIsIm1hcCIsInBhaXIiLCJ0YXJnZXRTZGtWZXJzaW9uVXNpbmdQS0ciLCJjbWRPdXRwdXQiLCJzaGVsbCIsIlJlZ0V4cCIsImxlbmd0aCIsImNvbXBpbGVNYW5pZmVzdCIsIm1hbmlmZXN0UGFja2FnZSIsInRhcmdldFBhY2thZ2UiLCJwbGF0Zm9ybSIsInBsYXRmb3JtUGF0aCIsInJlc3VsdFBhdGgiLCJhbmRyb2lkSmFyUGF0aCIsInBhdGgiLCJyZXNvbHZlIiwiZnMiLCJleGlzdHMiLCJyaW1yYWYiLCJpbml0QWFwdDIiLCJ1dGlsIiwicXVvdGUiLCJhYXB0MiIsInN0ZGVyciIsImUxIiwiaW5zZXJ0TWFuaWZlc3QiLCJzcmNBcGsiLCJkc3RBcGsiLCJ6aXAiLCJhc3NlcnRWYWxpZFppcCIsIm1hbmlmZXN0TmFtZSIsImJhc2VuYW1lIiwiY29weUZpbGUiLCJpZ24iLCJjd2QiLCJkaXJuYW1lIiwidG1wUm9vdCIsInRlbXBEaXIiLCJvcGVuRGlyIiwiZXh0cmFjdEFsbFRvIiwibXYiLCJ0b0FyY2hpdmUiLCJoYXNJbnRlcm5ldFBlcm1pc3Npb25Gcm9tTWFuaWZlc3QiLCJ1c2VzUGVybWlzc2lvbnMiLCJzb21lIiwibmFtZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFHQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFFQSxJQUFJQSxlQUFlLEdBQUcsRUFBdEI7O0FBZ0JBQSxlQUFlLENBQUNDLG9DQUFoQixHQUF1RCxlQUFlQSxvQ0FBZixDQUFxREMsT0FBckQsRUFBOEQ7QUFDbkgsTUFBSUEsT0FBTyxDQUFDQyxRQUFSLENBQWlCQyx1QkFBakIsQ0FBSixFQUFzQztBQUNwQ0YsSUFBQUEsT0FBTyxHQUFHLE1BQU0sS0FBS0csY0FBTCxDQUFvQkgsT0FBcEIsQ0FBaEI7QUFDRDs7QUFFRCxRQUFNSSxTQUFTLEdBQUcsTUFBTUMseUJBQVVDLElBQVYsQ0FBZU4sT0FBZixDQUF4QjtBQUNBLFFBQU1PLFFBQVEsR0FBRyxNQUFNSCxTQUFTLENBQUNJLFlBQVYsRUFBdkI7QUFDQSxRQUFNO0FBQUNDLElBQUFBLEdBQUQ7QUFBTUMsSUFBQUE7QUFBTixNQUFrQiw0QkFBY0gsUUFBZCxDQUF4Qjs7QUFDQUksa0JBQUlDLElBQUosQ0FBVSxrQkFBaUJILEdBQUksR0FBL0I7O0FBQ0FFLGtCQUFJQyxJQUFKLENBQVUsd0JBQXVCRixRQUFTLEdBQTFDOztBQUNBLFNBQU87QUFDTEcsSUFBQUEsVUFBVSxFQUFFSixHQURQO0FBRUxLLElBQUFBLFdBQVcsRUFBRUo7QUFGUixHQUFQO0FBSUQsQ0FkRDs7QUF3QkFaLGVBQWUsQ0FBQ2lCLDRCQUFoQixHQUErQyxlQUFlQSw0QkFBZixDQUE2Q2YsT0FBN0MsRUFBc0Q7QUFDbkdXLGtC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QXNCTixZQUF0QixDQUFoQixDQUFOOztBQUNBMUQsc0JBQUlLLEtBQUosQ0FBVyxzQ0FBcUNrRCxNQUFPLEdBQXZEOztBQUNBLFlBQU1DLG1CQUFJYSxTQUFKLENBQWNkLE1BQWQsRUFBc0I7QUFDMUJPLFFBQUFBLEdBQUcsRUFBRUU7QUFEcUIsT0FBdEIsQ0FBTjtBQUdELEtBWkQsU0FZVTtBQUNSLFlBQU1wQixrQkFBR0UsTUFBSCxDQUFVa0IsT0FBVixDQUFOO0FBQ0Q7QUFDRjs7QUFDRGhFLGtCQUFJSyxLQUFKLENBQVcsNEJBQTJCa0QsTUFBTyxnQkFBN0M7QUFDRCxDQXRDRDs7QUE4Q0FwRSxlQUFlLENBQUNtRixpQ0FBaEIsR0FBb0QsZUFBZUEsaUNBQWYsQ0FBa0RqRixPQUFsRCxFQUEyRDtBQUM3R1csa0JBQUlLLEtBQUosQ0FBVyxnQkFBZWhCLE9BQVEsdURBQWxDOztBQUNBLE1BQUlBLE9BQU8sQ0FBQ0MsUUFBUixDQUFpQkMsdUJBQWpCLENBQUosRUFBc0M7QUFDcENGLElBQUFBLE9BQU8sR0FBRyxNQUFNLEtBQUtHLGNBQUwsQ0FBb0JILE9BQXBCLENBQWhCO0FBQ0Q7O0FBRUQsUUFBTUksU0FBUyxHQUFHLE1BQU1DLHlCQUFVQyxJQUFWLENBQWVOLE9BQWYsQ0FBeEI7QUFDQSxRQUFNTyxRQUFRLEdBQUcsTUFBTUgsU0FBUyxDQUFDSSxZQUFWLEVBQXZCO0FBQ0EsU0FBTyxDQUFDRCxRQUFRLENBQUMyRSxlQUFULElBQTRCLEVBQTdCLEVBQWlDQyxJQUFqQyxDQUFzQyxDQUFDO0FBQUNDLElBQUFBO0FBQUQsR0FBRCxLQUFZQSxJQUFJLEtBQUssNkJBQTNELENBQVA7QUFDRCxDQVREOztlQVdldEYsZSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGV4ZWMgfSBmcm9tICd0ZWVuX3Byb2Nlc3MnO1xuaW1wb3J0IGxvZyBmcm9tICcuLi9sb2dnZXIuanMnO1xuaW1wb3J0IHtcbiAgZ2V0QW5kcm9pZFBsYXRmb3JtQW5kUGF0aCwgdW56aXBGaWxlLFxuICBBUEtTX0VYVEVOU0lPTiwgcGFyc2VNYW5pZmVzdCB9IGZyb20gJy4uL2hlbHBlcnMuanMnO1xuaW1wb3J0IHsgZnMsIHppcCwgdGVtcERpciwgdXRpbCB9IGZyb20gJ2FwcGl1bS1zdXBwb3J0JztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCBBcGtSZWFkZXIgZnJvbSAnYWRia2l0LWFwa3JlYWRlcic7XG5cbmxldCBtYW5pZmVzdE1ldGhvZHMgPSB7fTtcblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBBUEtJbmZvXG4gKiBAcHJvcGVydHkge3N0cmluZ30gYXBrUGFja2FnZSAtIFRoZSBuYW1lIG9mIGFwcGxpY2F0aW9uIHBhY2thZ2UsIGZvciBleGFtcGxlICdjb20uYWNtZS5hcHAnLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IGFwa0FjdGl2aXR5IC0gVGhlIG5hbWUgb2YgbWFpbiBhcHBsaWNhdGlvbiBhY3Rpdml0eS5cbiAqL1xuXG4vKipcbiAqIEV4dHJhY3QgcGFja2FnZSBhbmQgbWFpbiBhY3Rpdml0eSBuYW1lIGZyb20gYXBwbGljYXRpb24gbWFuaWZlc3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGFwcFBhdGggLSBUaGUgZnVsbCBwYXRoIHRvIGFwcGxpY2F0aW9uIC5hcGsocykgcGFja2FnZVxuICogQHJldHVybiB7QVBLSW5mb30gVGhlIHBhcnNlZCBhcHBsaWNhdGlvbiBpbmZvLlxuICogQHRocm93cyB7ZXJyb3J9IElmIHRoZXJlIHdhcyBhbiBlcnJvciB3aGlsZSBnZXR0aW5nIHRoZSBkYXRhIGZyb20gdGhlIGdpdmVuXG4gKiAgICAgICAgICAgICAgICAgYXBwbGljYXRpb24gcGFja2FnZS5cbiAqL1xubWFuaWZlc3RNZXRob2RzLnBhY2thZ2VBbmRMYXVuY2hBY3Rpdml0eUZyb21NYW5pZmVzdCA9IGFzeW5jIGZ1bmN0aW9uIHBhY2thZ2VBbmRMYXVuY2hBY3Rpdml0eUZyb21NYW5pZmVzdCAoYXBwUGF0aCkge1xuICBpZiAoYXBwUGF0aC5lbmRzV2l0aChBUEtTX0VYVEVOU0lPTikpIHtcbiAgICBhcHBQYXRoID0gYXdhaXQgdGhpcy5leHRyYWN0QmFzZUFwayhhcHBQYXRoKTtcbiAgfVxuXG4gIGNvbnN0IGFwa1JlYWRlciA9IGF3YWl0IEFwa1JlYWRlci5vcGVuKGFwcFBhdGgpO1xuICBjb25zdCBtYW5pZmVzdCA9IGF3YWl0IGFwa1JlYWRlci5yZWFkTWFuaWZlc3QoKTtcbiAgY29uc3Qge3BrZywgYWN0aXZpdHl9ID0gcGFyc2VNYW5pZmVzdChtYW5pZmVzdCk7XG4gIGxvZy5pbmZvKGBQYWNrYWdlIG5hbWU6ICcke3BrZ30nYCk7XG4gIGxvZy5pbmZvKGBNYWluIGFjdGl2aXR5IG5hbWU6ICcke2FjdGl2aXR5fSdgKTtcbiAgcmV0dXJuIHtcbiAgICBhcGtQYWNrYWdlOiBwa2csXG4gICAgYXBrQWN0aXZpdHk6IGFjdGl2aXR5LFxuICB9O1xufTtcblxuLyoqXG4gKiBFeHRyYWN0IHRhcmdldCBTREsgdmVyc2lvbiBmcm9tIGFwcGxpY2F0aW9uIG1hbmlmZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBhcHBQYXRoIC0gVGhlIGZ1bGwgcGF0aCB0byAuYXBrKHMpIHBhY2thZ2UuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSB2ZXJzaW9uIG9mIHRoZSB0YXJnZXQgU0RLLlxuICogQHRocm93cyB7ZXJyb3J9IElmIHRoZXJlIHdhcyBhbiBlcnJvciB3aGlsZSBnZXR0aW5nIHRoZSBkYXRhIGZyb20gdGhlIGdpdmVuXG4gKiAgICAgICAgICAgICAgICAgYXBwbGljYXRpb24gcGFja2FnZS5cbiAqL1xubWFuaWZlc3RNZXRob2RzLnRhcmdldFNka1ZlcnNpb25Gcm9tTWFuaWZlc3QgPSBhc3luYyBmdW5jdGlvbiB0YXJnZXRTZGtWZXJzaW9uRnJvbU1hbmlmZXN0IChhcHBQYXRoKSB7XG4gIGxvZy5kZWJ1ZyhgRXh0cmFjdGluZyB0YXJnZXQgU0RLIHZlcnNpb24gb2YgJyR7YXBwUGF0aH0nYCk7XG4gIGNvbnN0IG9yaWdpbmFsQXBwUGF0aCA9IGFwcFBhdGg7XG4gIGlmIChhcHBQYXRoLmVuZHNXaXRoKEFQS1NfRVhURU5TSU9OKSkge1xuICAgIGFwcFBhdGggPSBhd2FpdCB0aGlzLmV4dHJhY3RCYXNlQXBrKGFwcFBhdGgpO1xuICB9XG5cbiAgY29uc3QgZ2V0VGFyZ2V0U2RrVmlhQXBrUmVhZGVyID0gYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGFwa1JlYWRlciA9IGF3YWl0IEFwa1JlYWRlci5vcGVuKGFwcFBhdGgpO1xuICAgIGNvbnN0IG1hbmlmZXN0ID0gYXdhaXQgYXBrUmVhZGVyLnJlYWRNYW5pZmVzdCgpO1xuICAgIGlmIChtYW5pZmVzdC51c2VzU2RrICYmIF8uaXNJbnRlZ2VyKG1hbmlmZXN0LnVzZXNTZGsudGFyZ2V0U2RrVmVyc2lvbikpIHtcbiAgICAgIHJldHVybiBtYW5pZmVzdC51c2VzU2RrLnRhcmdldFNka1ZlcnNpb247XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGZpbmQgdGhlIGluZm9ybWF0aW9uIGFib3V0IHRhcmdldFNka1ZlcnNpb24gaW4gdGhlIG1hbmlmZXN0Jyk7XG4gIH07XG4gIGNvbnN0IGdldFRhcmdldFNka1ZpYUFhcHQgPSBhc3luYyAoKSA9PiB7XG4gICAgYXdhaXQgdGhpcy5pbml0QWFwdCgpO1xuICAgIGNvbnN0IGFyZ3MgPSBbJ2R1bXAnLCAnYmFkZ2luZycsIGFwcFBhdGhdO1xuICAgIGNvbnN0IHtzdGRvdXR9ID0gYXdhaXQgZXhlYyh0aGlzLmJpbmFyaWVzLmFhcHQsIGFyZ3MpO1xuICAgIGNvbnN0IHRhcmdldFNka1ZlcnNpb24gPSAvdGFyZ2V0U2RrVmVyc2lvbjonKFteJ10rKScvZy5leGVjKHN0ZG91dCk7XG4gICAgaWYgKCF0YXJnZXRTZGtWZXJzaW9uKSB7XG4gICAgICBsb2cuZGVidWcoc3Rkb3V0KTtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHBhcnNlIHRoZSBjb21tYW5kIG91dHB1dCcpO1xuICAgIH1cbiAgICByZXR1cm4gcGFyc2VJbnQodGFyZ2V0U2RrVmVyc2lvblsxXSwgMTApO1xuICB9O1xuICBjb25zdCB2ZXJzaW9uR2V0dGVycyA9IFtcbiAgICBbJ0Fwa1JlYWRlcicsIGdldFRhcmdldFNka1ZpYUFwa1JlYWRlcl0sXG4gICAgWydhYXB0JywgZ2V0VGFyZ2V0U2RrVmlhQWFwdF0sXG4gIF07XG4gIGZvciAoY29uc3QgW3Rvb2xOYW1lLCB2ZXJzaW9uR2V0dGVyXSBvZiB2ZXJzaW9uR2V0dGVycykge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgdmVyc2lvbkdldHRlcigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxvZy5pbmZvKGBDYW5ub3QgZXh0cmFjdCB0YXJnZXRTZGtWZXJzaW9uIG9mICcke29yaWdpbmFsQXBwUGF0aH0nIHVzaW5nICR7dG9vbE5hbWV9LiBgICtcbiAgICAgICAgYE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgICB9XG4gIH1cbiAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgZXh0cmFjdCB0aGUgdGFyZ2V0IFNESyB2ZXJzaW9uIG51bWJlciBvZiAnJHtvcmlnaW5hbEFwcFBhdGh9JyB1c2luZyBlaXRoZXIgb2YgYCArXG4gICAgYCR7SlNPTi5zdHJpbmdpZnkodmVyc2lvbkdldHRlcnMubWFwKChwYWlyKSA9PiBwYWlyWzBdKSl9IHRvb2xzLiBgICtcbiAgICBgQ2hlY2sgdGhlIHNlcnZlciBsb2cgZm9yIG1vcmUgZGV0YWlsc2ApO1xufTtcblxuLyoqXG4gKiBFeHRyYWN0IHRhcmdldCBTREsgdmVyc2lvbiBmcm9tIHBhY2thZ2UgaW5mb3JtYXRpb24uXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBrZyAtIFRoZSBjbGFzcyBuYW1lIG9mIHRoZSBwYWNrYWdlIGluc3RhbGxlZCBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKiBAcGFyYW0gez9zdHJpbmd9IGNtZE91dHB1dCAtIE9wdGlvbmFsIHBhcmFtZXRlciBjb250YWluaW5nIHRoZSBvdXRwdXQgb2ZcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2R1bXBzeXMgcGFja2FnZV8gY29tbWFuZC4gSXQgbWF5IHNwZWVkIHVwIHRoZSBtZXRob2QgZXhlY3V0aW9uLlxuICogQHJldHVybiB7bnVtYmVyfSBUaGUgdmVyc2lvbiBvZiB0aGUgdGFyZ2V0IFNESy5cbiAqL1xubWFuaWZlc3RNZXRob2RzLnRhcmdldFNka1ZlcnNpb25Vc2luZ1BLRyA9IGFzeW5jIGZ1bmN0aW9uIHRhcmdldFNka1ZlcnNpb25Vc2luZ1BLRyAocGtnLCBjbWRPdXRwdXQgPSBudWxsKSB7XG4gIGxldCBzdGRvdXQgPSBjbWRPdXRwdXQgfHwgYXdhaXQgdGhpcy5zaGVsbChbJ2R1bXBzeXMnLCAncGFja2FnZScsIHBrZ10pO1xuICBsZXQgdGFyZ2V0U2RrVmVyc2lvbiA9IG5ldyBSZWdFeHAoL3RhcmdldFNkaz0oW15cXHNcXHNdKykvZykuZXhlYyhzdGRvdXQpO1xuICBpZiAodGFyZ2V0U2RrVmVyc2lvbiAmJiB0YXJnZXRTZGtWZXJzaW9uLmxlbmd0aCA+PSAyKSB7XG4gICAgdGFyZ2V0U2RrVmVyc2lvbiA9IHRhcmdldFNka1ZlcnNpb25bMV07XG4gIH0gZWxzZSB7XG4gICAgLy8gdGFyZ2V0U2RrIG5vdCBmb3VuZCBpbiB0aGUgZHVtcCwgYXNzaWduaW5nIDAgdG8gdGFyZ2V0U2RrVmVyc2lvblxuICAgIHRhcmdldFNka1ZlcnNpb24gPSAwO1xuICB9XG4gIHJldHVybiBwYXJzZUludCh0YXJnZXRTZGtWZXJzaW9uLCAxMCk7XG59O1xuXG4vKipcbiAqIENyZWF0ZSBiaW5hcnkgcmVwcmVzZW50YXRpb24gb2YgcGFja2FnZSBtYW5pZmVzdCAodXN1YWxseSBBbmRyb2lkTWFuaWZlc3QueG1sKS5cbiAqIGAke21hbmlmZXN0fS5hcGtgIGZpbGUgd2lsbCBiZSBjcmVhdGVkIGFzIHRoZSByZXN1bHQgb2YgdGhpcyBtZXRob2RcbiAqIGNvbnRhaW5pbmcgdGhlIGNvbXBpbGVkIG1hbmlmZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtYW5pZmVzdCAtIEZ1bGwgcGF0aCB0byB0aGUgaW5pdGlhbCBtYW5pZmVzdCB0ZW1wbGF0ZVxuICogQHBhcmFtIHtzdHJpbmd9IG1hbmlmZXN0UGFja2FnZSAtIFRoZSBuYW1lIG9mIHRoZSBtYW5pZmVzdCBwYWNrYWdlXG4gKiBAcGFyYW0ge3N0cmluZ30gdGFyZ2V0UGFja2FnZSAtIFRoZSBuYW1lIG9mIHRoZSBkZXN0aW5hdGlvbiBwYWNrYWdlXG4gKi9cbm1hbmlmZXN0TWV0aG9kcy5jb21waWxlTWFuaWZlc3QgPSBhc3luYyBmdW5jdGlvbiBjb21waWxlTWFuaWZlc3QgKG1hbmlmZXN0LCBtYW5pZmVzdFBhY2thZ2UsIHRhcmdldFBhY2thZ2UpIHtcbiAgY29uc3Qge3BsYXRmb3JtLCBwbGF0Zm9ybVBhdGh9ID0gYXdhaXQgZ2V0QW5kcm9pZFBsYXRmb3JtQW5kUGF0aCgpO1xuICBpZiAoIXBsYXRmb3JtKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgY29tcGlsZSB0aGUgbWFuaWZlc3QuIFRoZSByZXF1aXJlZCBwbGF0Zm9ybSBkb2VzIG5vdCBleGlzdCAoQVBJIGxldmVsID49IDE3KScpO1xuICB9XG4gIGNvbnN0IHJlc3VsdFBhdGggPSBgJHttYW5pZmVzdH0uYXBrYDtcbiAgY29uc3QgYW5kcm9pZEphclBhdGggPSBwYXRoLnJlc29sdmUocGxhdGZvcm1QYXRoLCAnYW5kcm9pZC5qYXInKTtcbiAgaWYgKGF3YWl0IGZzLmV4aXN0cyhyZXN1bHRQYXRoKSkge1xuICAgIGF3YWl0IGZzLnJpbXJhZihyZXN1bHRQYXRoKTtcbiAgfVxuICB0cnkge1xuICAgIGF3YWl0IHRoaXMuaW5pdEFhcHQyKCk7XG4gICAgLy8gaHR0cHM6Ly9kZXZlbG9wZXIuYW5kcm9pZC5jb20vc3R1ZGlvL2NvbW1hbmQtbGluZS9hYXB0MlxuICAgIGNvbnN0IGFyZ3MgPSBbXG4gICAgICAnbGluaycsXG4gICAgICAnLW8nLCByZXN1bHRQYXRoLFxuICAgICAgJy0tbWFuaWZlc3QnLCBtYW5pZmVzdCxcbiAgICAgICctLXJlbmFtZS1tYW5pZmVzdC1wYWNrYWdlJywgbWFuaWZlc3RQYWNrYWdlLFxuICAgICAgJy0tcmVuYW1lLWluc3RydW1lbnRhdGlvbi10YXJnZXQtcGFja2FnZScsIHRhcmdldFBhY2thZ2UsXG4gICAgICAnLUknLCBhbmRyb2lkSmFyUGF0aCxcbiAgICAgICctdicsXG4gICAgXTtcbiAgICBsb2cuZGVidWcoYENvbXBpbGluZyB0aGUgbWFuaWZlc3QgdXNpbmcgJyR7dXRpbC5xdW90ZShbdGhpcy5iaW5hcmllcy5hYXB0MiwgLi4uYXJnc10pfSdgKTtcbiAgICBhd2FpdCBleGVjKHRoaXMuYmluYXJpZXMuYWFwdDIsIGFyZ3MpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbG9nLmRlYnVnKCdDYW5ub3QgY29tcGlsZSB0aGUgbWFuaWZlc3QgdXNpbmcgYWFwdDIuIERlZmF1bHRpbmcgdG8gYWFwdC4gJyArXG4gICAgICBgT3JpZ2luYWwgZXJyb3I6ICR7ZS5zdGRlcnIgfHwgZS5tZXNzYWdlfWApO1xuICAgIGF3YWl0IHRoaXMuaW5pdEFhcHQoKTtcbiAgICBjb25zdCBhcmdzID0gW1xuICAgICAgJ3BhY2thZ2UnLFxuICAgICAgJy1NJywgbWFuaWZlc3QsXG4gICAgICAnLS1yZW5hbWUtbWFuaWZlc3QtcGFja2FnZScsIG1hbmlmZXN0UGFja2FnZSxcbiAgICAgICctLXJlbmFtZS1pbnN0cnVtZW50YXRpb24tdGFyZ2V0LXBhY2thZ2UnLCB0YXJnZXRQYWNrYWdlLFxuICAgICAgJy1JJywgYW5kcm9pZEphclBhdGgsXG4gICAgICAnLUYnLCByZXN1bHRQYXRoLFxuICAgICAgJy1mJyxcbiAgICBdO1xuICAgIGxvZy5kZWJ1ZyhgQ29tcGlsaW5nIHRoZSBtYW5pZmVzdCB1c2luZyAnJHt1dGlsLnF1b3RlKFt0aGlzLmJpbmFyaWVzLmFhcHQsIC4uLmFyZ3NdKX0nYCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGV4ZWModGhpcy5iaW5hcmllcy5hYXB0LCBhcmdzKTtcbiAgICB9IGNhdGNoIChlMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgY29tcGlsZSB0aGUgbWFuaWZlc3QuIE9yaWdpbmFsIGVycm9yOiAke2UxLnN0ZGVyciB8fCBlMS5tZXNzYWdlfWApO1xuICAgIH1cbiAgfVxuICBsb2cuZGVidWcoYENvbXBpbGVkIHRoZSBtYW5pZmVzdCBhdCAnJHtyZXN1bHRQYXRofSdgKTtcbn07XG5cbi8qKlxuICogUmVwbGFjZS9pbnNlcnQgdGhlIHNwZWNpYWxseSBwcmVjb21waWxlZCBtYW5pZmVzdCBmaWxlIGludG8gdGhlXG4gKiBwYXJ0aWN1bGFyIHBhY2thZ2UuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1hbmlmZXN0IC0gRnVsbCBwYXRoIHRvIHRoZSBwcmVjb21waWxlZCBtYW5pZmVzdFxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlZCBieSBgY29tcGlsZU1hbmlmZXN0YCBtZXRob2QgY2FsbFxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2l0aG91dCAuYXBrIGV4dGVuc2lvblxuICogQHBhcmFtIHtzdHJpbmd9IHNyY0FwayAtIEZ1bGwgcGF0aCB0byB0aGUgZXhpc3RpbmcgdmFsaWQgYXBwbGljYXRpb24gcGFja2FnZSwgd2hlcmVcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzIG1hbmlmZXN0IGhhcyB0byBiZSBpbnNldHJlZCB0by4gVGhpcyBwYWNrYWdlXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgd2lsbCBOT1QgYmUgbW9kaWZpZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gZHN0QXBrIC0gRnVsbCBwYXRoIHRvIHRoZSByZXN1bHRpbmcgcGFja2FnZS5cbiAqICAgICAgICAgICAgICAgICAgICAgICAgICBUaGUgZmlsZSB3aWxsIGJlIG92ZXJyaWRkZW4gaWYgaXQgYWxyZWFkeSBleGlzdHMuXG4gKi9cbm1hbmlmZXN0TWV0aG9kcy5pbnNlcnRNYW5pZmVzdCA9IGFzeW5jIGZ1bmN0aW9uIGluc2VydE1hbmlmZXN0IChtYW5pZmVzdCwgc3JjQXBrLCBkc3RBcGspIHtcbiAgbG9nLmRlYnVnKGBJbnNlcnRpbmcgbWFuaWZlc3QgJyR7bWFuaWZlc3R9Jywgc3JjOiAnJHtzcmNBcGt9JywgZHN0OiAnJHtkc3RBcGt9J2ApO1xuICBhd2FpdCB6aXAuYXNzZXJ0VmFsaWRaaXAoc3JjQXBrKTtcbiAgYXdhaXQgdW56aXBGaWxlKGAke21hbmlmZXN0fS5hcGtgKTtcbiAgY29uc3QgbWFuaWZlc3ROYW1lID0gcGF0aC5iYXNlbmFtZShtYW5pZmVzdCk7XG4gIHRyeSB7XG4gICAgYXdhaXQgdGhpcy5pbml0QWFwdCgpO1xuICAgIGF3YWl0IGZzLmNvcHlGaWxlKHNyY0FwaywgZHN0QXBrKTtcbiAgICBsb2cuZGVidWcoJ01vdmluZyBtYW5pZmVzdCcpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBleGVjKHRoaXMuYmluYXJpZXMuYWFwdCwgW1xuICAgICAgICAncmVtb3ZlJywgZHN0QXBrLCBtYW5pZmVzdE5hbWVcbiAgICAgIF0pO1xuICAgIH0gY2F0Y2ggKGlnbikge31cbiAgICBhd2FpdCBleGVjKHRoaXMuYmluYXJpZXMuYWFwdCwgW1xuICAgICAgJ2FkZCcsIGRzdEFwaywgbWFuaWZlc3ROYW1lXG4gICAgXSwge2N3ZDogcGF0aC5kaXJuYW1lKG1hbmlmZXN0KX0pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbG9nLmRlYnVnKCdDYW5ub3QgaW5zZXJ0IG1hbmlmZXN0IHVzaW5nIGFhcHQuIERlZmF1bHRpbmcgdG8gemlwLiAnICtcbiAgICAgIGBPcmlnaW5hbCBlcnJvcjogJHtlLnN0ZGVyciB8fCBlLm1lc3NhZ2V9YCk7XG4gICAgY29uc3QgdG1wUm9vdCA9IGF3YWl0IHRlbXBEaXIub3BlbkRpcigpO1xuICAgIHRyeSB7XG4gICAgICAvLyBVbmZvcnR1bmF0ZWx5IE5vZGVKUyBkb2VzIG5vdCBwcm92aWRlIGFueSByZWxpYWJsZSBtZXRob2RzXG4gICAgICAvLyB0byByZXBsYWNlIGZpbGVzIGluc2lkZSB6aXAgYXJjaGl2ZXMgd2l0aG91dCBsb2FkaW5nIHRoZVxuICAgICAgLy8gd2hvbGUgYXJjaGl2ZSBjb250ZW50IGludG8gUkFNXG4gICAgICBsb2cuZGVidWcoYEV4dHJhY3RpbmcgdGhlIHNvdXJjZSBhcGsgYXQgJyR7c3JjQXBrfSdgKTtcbiAgICAgIGF3YWl0IHppcC5leHRyYWN0QWxsVG8oc3JjQXBrLCB0bXBSb290KTtcbiAgICAgIGxvZy5kZWJ1ZygnTW92aW5nIG1hbmlmZXN0Jyk7XG4gICAgICBhd2FpdCBmcy5tdihtYW5pZmVzdCwgcGF0aC5yZXNvbHZlKHRtcFJvb3QsIG1hbmlmZXN0TmFtZSkpO1xuICAgICAgbG9nLmRlYnVnKGBDb2xsZWN0aW5nIHRoZSBkZXN0aW5hdGlvbiBhcGsgYXQgJyR7ZHN0QXBrfSdgKTtcbiAgICAgIGF3YWl0IHppcC50b0FyY2hpdmUoZHN0QXBrLCB7XG4gICAgICAgIGN3ZDogdG1wUm9vdCxcbiAgICAgIH0pO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCBmcy5yaW1yYWYodG1wUm9vdCk7XG4gICAgfVxuICB9XG4gIGxvZy5kZWJ1ZyhgTWFuaWZlc3QgaW5zZXJ0aW9uIGludG8gJyR7ZHN0QXBrfScgaXMgY29tcGxldGVkYCk7XG59O1xuXG4vKipcbiAqIENoZWNrIHdoZXRoZXIgcGFja2FnZSBtYW5pZmVzdCBjb250YWlucyBJbnRlcm5ldCBwZXJtaXNzaW9ucy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gYXBwUGF0aCAtIFRoZSBmdWxsIHBhdGggdG8gLmFwayhzKSBwYWNrYWdlLlxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgbWFuaWZlc3QgcmVxdWlyZXMgSW50ZXJuZXQgYWNjZXNzIHBlcm1pc3Npb24uXG4gKi9cbm1hbmlmZXN0TWV0aG9kcy5oYXNJbnRlcm5ldFBlcm1pc3Npb25Gcm9tTWFuaWZlc3QgPSBhc3luYyBmdW5jdGlvbiBoYXNJbnRlcm5ldFBlcm1pc3Npb25Gcm9tTWFuaWZlc3QgKGFwcFBhdGgpIHtcbiAgbG9nLmRlYnVnKGBDaGVja2luZyBpZiAnJHthcHBQYXRofScgcmVxdWlyZXMgaW50ZXJuZXQgYWNjZXNzIHBlcm1pc3Npb24gaW4gdGhlIG1hbmlmZXN0YCk7XG4gIGlmIChhcHBQYXRoLmVuZHNXaXRoKEFQS1NfRVhURU5TSU9OKSkge1xuICAgIGFwcFBhdGggPSBhd2FpdCB0aGlzLmV4dHJhY3RCYXNlQXBrKGFwcFBhdGgpO1xuICB9XG5cbiAgY29uc3QgYXBrUmVhZGVyID0gYXdhaXQgQXBrUmVhZGVyLm9wZW4oYXBwUGF0aCk7XG4gIGNvbnN0IG1hbmlmZXN0ID0gYXdhaXQgYXBrUmVhZGVyLnJlYWRNYW5pZmVzdCgpO1xuICByZXR1cm4gKG1hbmlmZXN0LnVzZXNQZXJtaXNzaW9ucyB8fCBbXSkuc29tZSgoe25hbWV9KSA9PiBuYW1lID09PSAnYW5kcm9pZC5wZXJtaXNzaW9uLklOVEVSTkVUJyk7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBtYW5pZmVzdE1ldGhvZHM7XG4iXSwiZmlsZSI6ImxpYi90b29scy9hbmRyb2lkLW1hbmlmZXN0LmpzIiwic291cmNlUm9vdCI6Ii4uLy4uLy4uIn0=