@appium/support 2.61.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/lib/console.d.ts +1 -1
- package/build/lib/console.js +169 -105
- package/build/lib/console.js.map +1 -1
- package/build/lib/env.js +142 -117
- package/build/lib/env.js.map +1 -1
- package/build/lib/fs.d.ts +9 -2
- package/build/lib/fs.d.ts.map +1 -1
- package/build/lib/fs.js +358 -246
- package/build/lib/fs.js.map +1 -1
- package/build/lib/image-util.js +139 -124
- package/build/lib/image-util.js.map +1 -1
- package/build/lib/index.js +64 -103
- package/build/lib/index.js.map +1 -1
- package/build/lib/log-internal.d.ts +4 -27
- package/build/lib/log-internal.d.ts.map +1 -1
- package/build/lib/log-internal.js +141 -123
- package/build/lib/log-internal.js.map +1 -1
- package/build/lib/logger.d.ts +1 -1
- package/build/lib/logger.d.ts.map +1 -1
- package/build/lib/logger.js +5 -14
- package/build/lib/logger.js.map +1 -1
- package/build/lib/logging.d.ts +3 -4
- package/build/lib/logging.d.ts.map +1 -1
- package/build/lib/logging.js +139 -110
- package/build/lib/logging.js.map +1 -1
- package/build/lib/mjpeg.js +169 -141
- package/build/lib/mjpeg.js.map +1 -1
- package/build/lib/mkdirp.js +7 -13
- package/build/lib/mkdirp.js.map +1 -1
- package/build/lib/net.d.ts.map +1 -1
- package/build/lib/net.js +278 -254
- package/build/lib/net.js.map +1 -1
- package/build/lib/node.js +203 -192
- package/build/lib/node.js.map +1 -1
- package/build/lib/npm.d.ts +19 -4
- package/build/lib/npm.d.ts.map +1 -1
- package/build/lib/npm.js +277 -228
- package/build/lib/npm.js.map +1 -1
- package/build/lib/plist.js +145 -136
- package/build/lib/plist.js.map +1 -1
- package/build/lib/process.js +41 -42
- package/build/lib/process.js.map +1 -1
- package/build/lib/system.js +39 -56
- package/build/lib/system.js.map +1 -1
- package/build/lib/tempdir.js +112 -73
- package/build/lib/tempdir.js.map +1 -1
- package/build/lib/timing.js +99 -84
- package/build/lib/timing.js.map +1 -1
- package/build/lib/util.js +454 -356
- package/build/lib/util.js.map +1 -1
- package/build/lib/zip.js +469 -423
- package/build/lib/zip.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/lib/fs.js +15 -1
- package/lib/log-internal.js +12 -16
- package/lib/logging.js +2 -3
- package/lib/net.js +15 -6
- package/lib/npm.js +28 -18
- package/package.json +20 -19
package/build/lib/zip.js
CHANGED
|
@@ -1,461 +1,507 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
});
|
|
6
|
-
exports._extractEntryTo =
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
require("
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
var _fs2 = _interopRequireDefault(require("./fs"));
|
|
31
|
-
|
|
32
|
-
var _system = require("./system");
|
|
33
|
-
|
|
34
|
-
var _base64Stream = require("base64-stream");
|
|
35
|
-
|
|
36
|
-
var _util = require("./util");
|
|
37
|
-
|
|
38
|
-
var _timing = _interopRequireDefault(require("./timing"));
|
|
39
|
-
|
|
40
|
-
var _logger = _interopRequireDefault(require("./logger"));
|
|
41
|
-
|
|
42
|
-
var _getStream = _interopRequireDefault(require("get-stream"));
|
|
43
|
-
|
|
44
|
-
var _teen_process = require("teen_process");
|
|
45
|
-
|
|
46
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
47
|
-
|
|
48
|
-
const openZip = _bluebird.default.promisify(_yauzl.default.open);
|
|
49
|
-
|
|
50
|
-
const pipeline = _bluebird.default.promisify(_stream.default.pipeline);
|
|
51
|
-
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.toArchive = exports.assertValidZip = exports._extractEntryTo = exports.toInMemoryZip = exports.readEntries = exports.extractAllTo = void 0;
|
|
7
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
8
|
+
const bluebird_1 = __importDefault(require("bluebird"));
|
|
9
|
+
const yauzl_1 = __importDefault(require("yauzl"));
|
|
10
|
+
const archiver_1 = __importDefault(require("archiver"));
|
|
11
|
+
const fs_1 = require("fs");
|
|
12
|
+
const path_1 = __importDefault(require("path"));
|
|
13
|
+
const stream_1 = __importDefault(require("stream"));
|
|
14
|
+
const fs_2 = __importDefault(require("./fs"));
|
|
15
|
+
const system_1 = require("./system");
|
|
16
|
+
const base64_stream_1 = require("base64-stream");
|
|
17
|
+
const util_1 = require("./util");
|
|
18
|
+
const timing_1 = __importDefault(require("./timing"));
|
|
19
|
+
const logger_1 = __importDefault(require("./logger"));
|
|
20
|
+
const get_stream_1 = __importDefault(require("get-stream"));
|
|
21
|
+
const teen_process_1 = require("teen_process");
|
|
22
|
+
/**
|
|
23
|
+
* @type {(path: string, options?: yauzl.Options) => Promise<yauzl.ZipFile>}
|
|
24
|
+
*/
|
|
25
|
+
const openZip = bluebird_1.default.promisify(yauzl_1.default.open);
|
|
26
|
+
/**
|
|
27
|
+
* @type {(source: NodeJS.ReadableStream, destination: NodeJS.WritableStream) => Promise<NodeJS.WritableStream>}
|
|
28
|
+
*/
|
|
29
|
+
const pipeline = bluebird_1.default.promisify(stream_1.default.pipeline);
|
|
52
30
|
const ZIP_MAGIC = 'PK';
|
|
53
31
|
const IFMT = 61440;
|
|
54
32
|
const IFDIR = 16384;
|
|
55
33
|
const IFLNK = 40960;
|
|
56
|
-
|
|
34
|
+
// This class is mostly copied from https://github.com/maxogden/extract-zip/blob/master/index.js
|
|
57
35
|
class ZipExtractor {
|
|
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
|
-
|
|
36
|
+
constructor(sourcePath, opts = {}) {
|
|
37
|
+
this.zipPath = sourcePath;
|
|
38
|
+
this.opts = opts;
|
|
39
|
+
this.canceled = false;
|
|
40
|
+
}
|
|
41
|
+
extractFileName(entry) {
|
|
42
|
+
return lodash_1.default.isBuffer(entry.fileName)
|
|
43
|
+
? entry.fileName.toString(this.opts.fileNamesEncoding)
|
|
44
|
+
: entry.fileName;
|
|
45
|
+
}
|
|
46
|
+
async extract() {
|
|
47
|
+
const { dir, fileNamesEncoding } = this.opts;
|
|
48
|
+
this.zipfile = await openZip(this.zipPath, {
|
|
49
|
+
lazyEntries: true,
|
|
50
|
+
// https://github.com/thejoshwolfe/yauzl/commit/cc7455ac789ba84973184e5ebde0581cdc4c3b39#diff-04c6e90faac2675aa89e2176d2eec7d8R95
|
|
51
|
+
decodeStrings: !fileNamesEncoding,
|
|
52
|
+
});
|
|
53
|
+
this.canceled = false;
|
|
54
|
+
return new bluebird_1.default((resolve, reject) => {
|
|
55
|
+
this.zipfile.on('error', (err) => {
|
|
56
|
+
this.canceled = true;
|
|
57
|
+
reject(err);
|
|
58
|
+
});
|
|
59
|
+
this.zipfile.readEntry();
|
|
60
|
+
this.zipfile.on('close', () => {
|
|
61
|
+
if (!this.canceled) {
|
|
62
|
+
resolve();
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
this.zipfile.on('entry', async (entry) => {
|
|
66
|
+
if (this.canceled) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const fileName = this.extractFileName(entry);
|
|
70
|
+
if (fileName.startsWith('__MACOSX/')) {
|
|
71
|
+
this.zipfile.readEntry();
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const destDir = path_1.default.dirname(path_1.default.join(dir, fileName));
|
|
75
|
+
try {
|
|
76
|
+
await fs_2.default.mkdir(destDir, { recursive: true });
|
|
77
|
+
const canonicalDestDir = await fs_2.default.realpath(destDir);
|
|
78
|
+
const relativeDestDir = path_1.default.relative(dir, canonicalDestDir);
|
|
79
|
+
if (relativeDestDir.split(path_1.default.sep).includes('..')) {
|
|
80
|
+
new Error(`Out of bound path "${canonicalDestDir}" found while processing file ${fileName}`);
|
|
81
|
+
}
|
|
82
|
+
await this.extractEntry(entry);
|
|
83
|
+
this.zipfile.readEntry();
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
this.canceled = true;
|
|
87
|
+
this.zipfile.close();
|
|
88
|
+
reject(err);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
async extractEntry(entry) {
|
|
92
94
|
if (this.canceled) {
|
|
93
|
-
|
|
95
|
+
return;
|
|
94
96
|
}
|
|
95
|
-
|
|
97
|
+
const { dir } = this.opts;
|
|
96
98
|
const fileName = this.extractFileName(entry);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
const dest = path_1.default.join(dir, fileName);
|
|
100
|
+
// convert external file attr int into a fs stat mode int
|
|
101
|
+
const mode = (entry.externalFileAttributes >> 16) & 0xffff;
|
|
102
|
+
// check if it's a symlink or dir (using stat mode constants)
|
|
103
|
+
const isSymlink = (mode & IFMT) === IFLNK;
|
|
104
|
+
const isDir = (mode & IFMT) === IFDIR ||
|
|
105
|
+
// Failsafe, borrowed from jsZip
|
|
106
|
+
fileName.endsWith('/') ||
|
|
107
|
+
// check for windows weird way of specifying a directory
|
|
108
|
+
// https://github.com/maxogden/extract-zip/issues/13#issuecomment-154494566
|
|
109
|
+
(entry.versionMadeBy >> 8 === 0 && entry.externalFileAttributes === 16);
|
|
110
|
+
const procMode = this.getExtractedMode(mode, isDir) & 0o777;
|
|
111
|
+
// always ensure folders are created
|
|
112
|
+
const destDir = isDir ? dest : path_1.default.dirname(dest);
|
|
113
|
+
const mkdirOptions = { recursive: true };
|
|
114
|
+
if (isDir) {
|
|
115
|
+
mkdirOptions.mode = procMode;
|
|
101
116
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
await this.extractEntry(entry);
|
|
118
|
-
this.zipfile.readEntry();
|
|
119
|
-
} catch (err) {
|
|
120
|
-
this.canceled = true;
|
|
121
|
-
this.zipfile.close();
|
|
122
|
-
reject(err);
|
|
117
|
+
await fs_2.default.mkdir(destDir, mkdirOptions);
|
|
118
|
+
if (isDir) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
/** @type {(entry: yauzl.Entry) => Promise<NodeJS.ReadableStream>} */
|
|
122
|
+
const openReadStream = bluebird_1.default.promisify(this.zipfile.openReadStream.bind(this.zipfile));
|
|
123
|
+
const readStream = await openReadStream(entry);
|
|
124
|
+
if (isSymlink) {
|
|
125
|
+
const link = await (0, get_stream_1.default)(readStream);
|
|
126
|
+
await fs_2.default.symlink(link, dest);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
await pipeline(readStream, fs_2.default.createWriteStream(dest, { mode: procMode }));
|
|
123
130
|
}
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
async extractEntry(entry) {
|
|
129
|
-
if (this.canceled) {
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const {
|
|
134
|
-
dir
|
|
135
|
-
} = this.opts;
|
|
136
|
-
const fileName = this.extractFileName(entry);
|
|
137
|
-
|
|
138
|
-
const dest = _path.default.join(dir, fileName);
|
|
139
|
-
|
|
140
|
-
const mode = entry.externalFileAttributes >> 16 & 0xffff;
|
|
141
|
-
const isSymlink = (mode & IFMT) === IFLNK;
|
|
142
|
-
const isDir = (mode & IFMT) === IFDIR || fileName.endsWith('/') || entry.versionMadeBy >> 8 === 0 && entry.externalFileAttributes === 16;
|
|
143
|
-
const procMode = this.getExtractedMode(mode, isDir) & 0o777;
|
|
144
|
-
const destDir = isDir ? dest : _path.default.dirname(dest);
|
|
145
|
-
const mkdirOptions = {
|
|
146
|
-
recursive: true
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
if (isDir) {
|
|
150
|
-
mkdirOptions.mode = procMode;
|
|
151
131
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
132
|
+
getExtractedMode(entryMode, isDir) {
|
|
133
|
+
const { defaultDirMode, defaultFileMode } = this.opts;
|
|
134
|
+
let mode = entryMode;
|
|
135
|
+
// Set defaults, if necessary
|
|
136
|
+
if (mode === 0) {
|
|
137
|
+
if (isDir) {
|
|
138
|
+
if (defaultDirMode) {
|
|
139
|
+
mode = parseInt(defaultDirMode, 10);
|
|
140
|
+
}
|
|
141
|
+
if (!mode) {
|
|
142
|
+
mode = 0o755;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
if (defaultFileMode) {
|
|
147
|
+
mode = parseInt(defaultFileMode, 10);
|
|
148
|
+
}
|
|
149
|
+
if (!mode) {
|
|
150
|
+
mode = 0o644;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return mode;
|
|
157
155
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* @typedef ExtractAllOptions
|
|
159
|
+
* @property {string} [fileNamesEncoding] The encoding to use for extracted file names.
|
|
160
|
+
* For ZIP archives created on MacOS it is usually expected to be `utf8`.
|
|
161
|
+
* By default it is autodetected based on the entry metadata and is only needed to be set explicitly
|
|
162
|
+
* if the particular archive does not comply to the standards, which leads to corrupted file names
|
|
163
|
+
* after extraction. Only applicable if system unzip binary is NOT being used.
|
|
164
|
+
* @property {boolean} [useSystemUnzip] If true, attempt to use system unzip; if this fails,
|
|
165
|
+
* fallback to the JS unzip implementation.
|
|
166
|
+
*/
|
|
167
|
+
/**
|
|
168
|
+
* Extract zipfile to a directory
|
|
169
|
+
*
|
|
170
|
+
* @param {string} zipFilePath The full path to the source ZIP file
|
|
171
|
+
* @param {string} destDir The full path to the destination folder
|
|
172
|
+
* @param {ExtractAllOptions} [opts]
|
|
173
|
+
*/
|
|
174
|
+
async function extractAllTo(zipFilePath, destDir, opts = /** @type {ExtractAllOptions} */ ({})) {
|
|
175
|
+
if (!path_1.default.isAbsolute(destDir)) {
|
|
176
|
+
throw new Error(`Target path '${destDir}' is expected to be absolute`);
|
|
170
177
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
} = this.opts;
|
|
178
|
-
let mode = entryMode;
|
|
179
|
-
|
|
180
|
-
if (mode === 0) {
|
|
181
|
-
if (isDir) {
|
|
182
|
-
if (defaultDirMode) {
|
|
183
|
-
mode = parseInt(defaultDirMode, 10);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (!mode) {
|
|
187
|
-
mode = 0o755;
|
|
188
|
-
}
|
|
189
|
-
} else {
|
|
190
|
-
if (defaultFileMode) {
|
|
191
|
-
mode = parseInt(defaultFileMode, 10);
|
|
178
|
+
await fs_2.default.mkdir(destDir, { recursive: true });
|
|
179
|
+
const dir = await fs_2.default.realpath(destDir);
|
|
180
|
+
if (opts.useSystemUnzip) {
|
|
181
|
+
try {
|
|
182
|
+
await extractWithSystemUnzip(zipFilePath, dir);
|
|
183
|
+
return;
|
|
192
184
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
mode = 0o644;
|
|
185
|
+
catch (err) {
|
|
186
|
+
logger_1.default.warn('unzip failed; falling back to JS: %s', err.stderr || err.message);
|
|
196
187
|
}
|
|
197
|
-
}
|
|
198
188
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
189
|
+
const extractor = new ZipExtractor(zipFilePath, {
|
|
190
|
+
...opts,
|
|
191
|
+
dir,
|
|
192
|
+
});
|
|
193
|
+
await extractor.extract();
|
|
203
194
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
195
|
+
exports.extractAllTo = extractAllTo;
|
|
196
|
+
/**
|
|
197
|
+
* Executes system unzip (e.g., `/usr/bin/unzip`). If available, it is
|
|
198
|
+
* significantly faster than the JS implementation.
|
|
199
|
+
* By default all files in the destDir get overridden if already exist.
|
|
200
|
+
*
|
|
201
|
+
* @param {string} zipFilePath The full path to the source ZIP file
|
|
202
|
+
* @param {string} destDir The full path to the destination folder.
|
|
203
|
+
* This folder is expected to already exist before extracting the archive.
|
|
204
|
+
*/
|
|
205
|
+
async function extractWithSystemUnzip(zipFilePath, destDir) {
|
|
206
|
+
const isWindowsHost = (0, system_1.isWindows)();
|
|
207
|
+
let executablePath;
|
|
216
208
|
try {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
209
|
+
executablePath = await getExecutablePath(isWindowsHost ? 'powershell.exe' : 'unzip');
|
|
210
|
+
}
|
|
211
|
+
catch (e) {
|
|
212
|
+
throw new Error('Could not find system unzip');
|
|
213
|
+
}
|
|
214
|
+
if (isWindowsHost) {
|
|
215
|
+
// on Windows we use PowerShell to unzip files
|
|
216
|
+
await (0, teen_process_1.exec)(executablePath, [
|
|
217
|
+
'-command',
|
|
218
|
+
'Expand-Archive',
|
|
219
|
+
'-LiteralPath',
|
|
220
|
+
zipFilePath,
|
|
221
|
+
'-DestinationPath',
|
|
222
|
+
destDir,
|
|
223
|
+
'-Force',
|
|
224
|
+
]);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
// -q means quiet (no stdout)
|
|
228
|
+
// -o means overwrite
|
|
229
|
+
// -d is the dest dir
|
|
230
|
+
await (0, teen_process_1.exec)(executablePath, ['-q', '-o', zipFilePath, '-d', destDir]);
|
|
221
231
|
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const extractor = new ZipExtractor(zipFilePath, { ...opts,
|
|
225
|
-
dir
|
|
226
|
-
});
|
|
227
|
-
await extractor.extract();
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
async function extractWithSystemUnzip(zipFilePath, destDir) {
|
|
231
|
-
const isWindowsHost = (0, _system.isWindows)();
|
|
232
|
-
let executablePath;
|
|
233
|
-
|
|
234
|
-
try {
|
|
235
|
-
executablePath = await getExecutablePath(isWindowsHost ? 'powershell.exe' : 'unzip');
|
|
236
|
-
} catch (e) {
|
|
237
|
-
throw new Error('Could not find system unzip');
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
if (isWindowsHost) {
|
|
241
|
-
await (0, _teen_process.exec)(executablePath, ['-command', 'Expand-Archive', '-LiteralPath', zipFilePath, '-DestinationPath', destDir, '-Force']);
|
|
242
|
-
} else {
|
|
243
|
-
await (0, _teen_process.exec)(executablePath, ['-q', '-o', zipFilePath, '-d', destDir]);
|
|
244
|
-
}
|
|
245
232
|
}
|
|
246
|
-
|
|
233
|
+
/**
|
|
234
|
+
* Extract a single zip entry to a directory
|
|
235
|
+
*
|
|
236
|
+
* @param {yauzl.ZipFile} zipFile The source ZIP stream
|
|
237
|
+
* @param {yauzl.Entry} entry The entry instance
|
|
238
|
+
* @param {string} destDir The full path to the destination folder
|
|
239
|
+
*/
|
|
247
240
|
async function _extractEntryTo(zipFile, entry, destDir) {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
241
|
+
const dstPath = path_1.default.resolve(destDir, entry.fileName);
|
|
242
|
+
// Create dest directory if doesn't exist already
|
|
243
|
+
if (/\/$/.test(entry.fileName)) {
|
|
244
|
+
if (!(await fs_2.default.exists(dstPath))) {
|
|
245
|
+
await fs_2.default.mkdirp(dstPath);
|
|
246
|
+
}
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
else if (!(await fs_2.default.exists(path_1.default.dirname(dstPath)))) {
|
|
250
|
+
await fs_2.default.mkdirp(path_1.default.dirname(dstPath));
|
|
253
251
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
zipReadStream.once('error', reject);
|
|
273
|
-
});
|
|
274
|
-
zipReadStream.pipe(writeStream);
|
|
275
|
-
return await _bluebird.default.all([zipReadStreamPromise, writeStreamPromise]);
|
|
252
|
+
// Create a write stream
|
|
253
|
+
const writeStream = (0, fs_1.createWriteStream)(dstPath, { flags: 'w' });
|
|
254
|
+
const writeStreamPromise = new bluebird_1.default((resolve, reject) => {
|
|
255
|
+
writeStream.once('finish', resolve);
|
|
256
|
+
writeStream.once('error', reject);
|
|
257
|
+
});
|
|
258
|
+
// Create zipReadStream and pipe data to the write stream
|
|
259
|
+
// (for some odd reason B.promisify doesn't work on zipfile.openReadStream, it causes an error 'closed')
|
|
260
|
+
const zipReadStream = await new bluebird_1.default((resolve, reject) => {
|
|
261
|
+
zipFile.openReadStream(entry, (err, readStream) => (err ? reject(err) : resolve(readStream)));
|
|
262
|
+
});
|
|
263
|
+
const zipReadStreamPromise = new bluebird_1.default((resolve, reject) => {
|
|
264
|
+
zipReadStream.once('end', resolve);
|
|
265
|
+
zipReadStream.once('error', reject);
|
|
266
|
+
});
|
|
267
|
+
zipReadStream.pipe(writeStream);
|
|
268
|
+
// Wait for the zipReadStream and writeStream to end before returning
|
|
269
|
+
return await bluebird_1.default.all([zipReadStreamPromise, writeStreamPromise]);
|
|
276
270
|
}
|
|
277
|
-
|
|
271
|
+
exports._extractEntryTo = _extractEntryTo;
|
|
272
|
+
/**
|
|
273
|
+
* @typedef ZipEntry
|
|
274
|
+
* @property {yauzl.Entry} entry The actual entry instance
|
|
275
|
+
* @property {function} extractEntryTo An async function, which accepts one parameter.
|
|
276
|
+
* This parameter contains the destination folder path to which this function is going to extract the entry.
|
|
277
|
+
*/
|
|
278
|
+
/**
|
|
279
|
+
* Get entries for a zip folder
|
|
280
|
+
*
|
|
281
|
+
* @param {string} zipFilePath The full path to the source ZIP file
|
|
282
|
+
* @param {function} onEntry Callback when entry is read.
|
|
283
|
+
* The callback is expected to accept one argument of ZipEntry type.
|
|
284
|
+
* The iteration through the source zip file will bi terminated as soon as
|
|
285
|
+
* the result of this function equals to `false`.
|
|
286
|
+
*/
|
|
278
287
|
async function readEntries(zipFilePath, onEntry) {
|
|
279
|
-
|
|
280
|
-
lazyEntries: true
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
zipfile.readEntry();
|
|
288
|
+
// Open a zip file and start reading entries
|
|
289
|
+
const zipfile = await openZip(zipFilePath, { lazyEntries: true });
|
|
290
|
+
const zipReadStreamPromise = new bluebird_1.default((resolve, reject) => {
|
|
291
|
+
zipfile.once('end', resolve);
|
|
292
|
+
zipfile.once('error', reject);
|
|
293
|
+
// On each entry, call 'onEntry' and then read the next entry
|
|
294
|
+
zipfile.on('entry', async (entry) => {
|
|
295
|
+
const res = await onEntry({
|
|
296
|
+
entry,
|
|
297
|
+
extractEntryTo: async (destDir) => await _extractEntryTo(zipfile, entry, destDir),
|
|
298
|
+
});
|
|
299
|
+
if (res === false) {
|
|
300
|
+
return zipfile.emit('end');
|
|
301
|
+
}
|
|
302
|
+
zipfile.readEntry();
|
|
303
|
+
});
|
|
296
304
|
});
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
305
|
+
zipfile.readEntry();
|
|
306
|
+
// Wait for the entries to finish being iterated through
|
|
307
|
+
return await zipReadStreamPromise;
|
|
300
308
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
309
|
+
exports.readEntries = readEntries;
|
|
310
|
+
/**
|
|
311
|
+
* @typedef ZipOptions
|
|
312
|
+
* @property {boolean} encodeToBase64 [false] Whether to encode
|
|
313
|
+
* the resulting archive to a base64-encoded string
|
|
314
|
+
* @property {boolean} isMetered [true] Whether to log the actual
|
|
315
|
+
* archiver performance
|
|
316
|
+
* @property {number} maxSize [1073741824] The maximum size of
|
|
317
|
+
* the resulting archive in bytes. This is set to 1GB by default, because
|
|
318
|
+
* Appium limits the maximum HTTP body size to 1GB. Also, the NodeJS heap
|
|
319
|
+
* size must be enough to keep the resulting object (usually this size is
|
|
320
|
+
* limited to 1.4 GB)
|
|
321
|
+
* @property {number} level [9] The compression level. The maximum
|
|
322
|
+
* level is 9 (the best compression, worst performance). The minimum
|
|
323
|
+
* compression level is 0 (no compression).
|
|
324
|
+
*/
|
|
325
|
+
/**
|
|
326
|
+
* Converts contents of local directory to an in-memory .zip buffer
|
|
327
|
+
*
|
|
328
|
+
* @param {string} srcPath The full path to the folder or file being zipped
|
|
329
|
+
* @param {ZipOptions} opts Zipping options
|
|
330
|
+
* @returns {Promise<Buffer>} Zipped (and encoded if `encodeToBase64` is truthy)
|
|
331
|
+
* content of the source path as memory buffer
|
|
332
|
+
* @throws {Error} if there was an error while reading the source
|
|
333
|
+
* or the source is too big
|
|
334
|
+
*/
|
|
335
|
+
async function toInMemoryZip(srcPath, opts = /** @type {ZipOptions} */ ({})) {
|
|
336
|
+
if (!(await fs_2.default.exists(srcPath))) {
|
|
337
|
+
throw new Error(`No such file or folder: ${srcPath}`);
|
|
330
338
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
resultWriteStream
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
339
|
+
const { isMetered = true, encodeToBase64 = false, maxSize = 1 * util_1.GiB, level = 9 } = opts;
|
|
340
|
+
const resultBuffers = [];
|
|
341
|
+
let resultBuffersSize = 0;
|
|
342
|
+
// Create a writable stream that zip buffers will be streamed to
|
|
343
|
+
const resultWriteStream = new stream_1.default.Writable({
|
|
344
|
+
write: (buffer, encoding, next) => {
|
|
345
|
+
resultBuffers.push(buffer);
|
|
346
|
+
resultBuffersSize += buffer.length;
|
|
347
|
+
if (maxSize > 0 && resultBuffersSize > maxSize) {
|
|
348
|
+
resultWriteStream.emit('error', new Error(`The size of the resulting ` +
|
|
349
|
+
`archive must not be greater than ${(0, util_1.toReadableSizeString)(maxSize)}`));
|
|
350
|
+
}
|
|
351
|
+
next();
|
|
352
|
+
},
|
|
353
|
+
});
|
|
354
|
+
// Zip 'srcDir' and stream it to the above writable stream
|
|
355
|
+
const archive = (0, archiver_1.default)('zip', {
|
|
356
|
+
zlib: { level },
|
|
346
357
|
});
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
358
|
+
let srcSize = null;
|
|
359
|
+
const base64EncoderStream = encodeToBase64 ? new base64_stream_1.Base64Encode() : null;
|
|
360
|
+
const resultWriteStreamPromise = new bluebird_1.default((resolve, reject) => {
|
|
361
|
+
resultWriteStream.once('error', (e) => {
|
|
362
|
+
if (base64EncoderStream) {
|
|
363
|
+
archive.unpipe(base64EncoderStream);
|
|
364
|
+
base64EncoderStream.unpipe(resultWriteStream);
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
archive.unpipe(resultWriteStream);
|
|
368
|
+
}
|
|
369
|
+
archive.abort();
|
|
370
|
+
archive.destroy();
|
|
371
|
+
reject(e);
|
|
372
|
+
});
|
|
373
|
+
resultWriteStream.once('finish', () => {
|
|
374
|
+
srcSize = archive.pointer();
|
|
375
|
+
resolve();
|
|
376
|
+
});
|
|
350
377
|
});
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
archive.once('error', e => reject(new Error(`Failed to archive '${srcPath}': ${e.message}`)));
|
|
355
|
-
});
|
|
356
|
-
const timer = isMetered ? new _timing.default().start() : null;
|
|
357
|
-
|
|
358
|
-
if ((await _fs2.default.stat(srcPath)).isDirectory()) {
|
|
359
|
-
archive.directory(srcPath, false);
|
|
360
|
-
} else {
|
|
361
|
-
archive.file(srcPath, {
|
|
362
|
-
name: _path.default.basename(srcPath)
|
|
378
|
+
const archiveStreamPromise = new bluebird_1.default((resolve, reject) => {
|
|
379
|
+
archive.once('finish', resolve);
|
|
380
|
+
archive.once('error', (e) => reject(new Error(`Failed to archive '${srcPath}': ${e.message}`)));
|
|
363
381
|
});
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
382
|
+
const timer = isMetered ? new timing_1.default().start() : null;
|
|
383
|
+
if ((await fs_2.default.stat(srcPath)).isDirectory()) {
|
|
384
|
+
archive.directory(srcPath, false);
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
archive.file(srcPath, {
|
|
388
|
+
name: path_1.default.basename(srcPath),
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
if (base64EncoderStream) {
|
|
392
|
+
archive.pipe(base64EncoderStream);
|
|
393
|
+
base64EncoderStream.pipe(resultWriteStream);
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
archive.pipe(resultWriteStream);
|
|
397
|
+
}
|
|
398
|
+
archive.finalize();
|
|
399
|
+
// Wait for the streams to finish
|
|
400
|
+
await bluebird_1.default.all([archiveStreamPromise, resultWriteStreamPromise]);
|
|
401
|
+
if (timer) {
|
|
402
|
+
logger_1.default.debug(`Zipped ${encodeToBase64 ? 'and base64-encoded ' : ''}` +
|
|
403
|
+
`'${path_1.default.basename(srcPath)}' ` +
|
|
404
|
+
(srcSize ? `(${(0, util_1.toReadableSizeString)(srcSize)}) ` : '') +
|
|
405
|
+
`in ${timer.getDuration().asSeconds.toFixed(3)}s ` +
|
|
406
|
+
`(compression level: ${level})`);
|
|
407
|
+
}
|
|
408
|
+
// Return the array of zip buffers concatenated into one buffer
|
|
409
|
+
return Buffer.concat(resultBuffers);
|
|
381
410
|
}
|
|
382
|
-
|
|
411
|
+
exports.toInMemoryZip = toInMemoryZip;
|
|
412
|
+
/**
|
|
413
|
+
* Verifies whether the given file is a valid ZIP archive
|
|
414
|
+
*
|
|
415
|
+
* @param {string} filePath - Full path to the file
|
|
416
|
+
* @throws {Error} If the file does not exist or is not a valid ZIP archive
|
|
417
|
+
*/
|
|
383
418
|
async function assertValidZip(filePath) {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
const {
|
|
389
|
-
size
|
|
390
|
-
} = await _fs2.default.stat(filePath);
|
|
391
|
-
|
|
392
|
-
if (size < 4) {
|
|
393
|
-
throw new Error(`The file at '${filePath}' is too small to be a ZIP archive`);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
const fd = await _fs2.default.open(filePath, 'r');
|
|
397
|
-
|
|
398
|
-
try {
|
|
399
|
-
const buffer = Buffer.alloc(ZIP_MAGIC.length);
|
|
400
|
-
await _fs2.default.read(fd, buffer, 0, ZIP_MAGIC.length, 0);
|
|
401
|
-
const signature = buffer.toString('ascii');
|
|
402
|
-
|
|
403
|
-
if (signature !== ZIP_MAGIC) {
|
|
404
|
-
throw new Error(`The file signature '${signature}' of '${filePath}' ` + `is not equal to the expected ZIP archive signature '${ZIP_MAGIC}'`);
|
|
419
|
+
if (!(await fs_2.default.exists(filePath))) {
|
|
420
|
+
throw new Error(`The file at '${filePath}' does not exist`);
|
|
405
421
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
zlib: {
|
|
424
|
-
level
|
|
422
|
+
const { size } = await fs_2.default.stat(filePath);
|
|
423
|
+
if (size < 4) {
|
|
424
|
+
throw new Error(`The file at '${filePath}' is too small to be a ZIP archive`);
|
|
425
|
+
}
|
|
426
|
+
const fd = await fs_2.default.open(filePath, 'r');
|
|
427
|
+
try {
|
|
428
|
+
const buffer = Buffer.alloc(ZIP_MAGIC.length);
|
|
429
|
+
await fs_2.default.read(fd, buffer, 0, ZIP_MAGIC.length, 0);
|
|
430
|
+
const signature = buffer.toString('ascii');
|
|
431
|
+
if (signature !== ZIP_MAGIC) {
|
|
432
|
+
throw new Error(`The file signature '${signature}' of '${filePath}' ` +
|
|
433
|
+
`is not equal to the expected ZIP archive signature '${ZIP_MAGIC}'`);
|
|
434
|
+
}
|
|
435
|
+
return true;
|
|
436
|
+
}
|
|
437
|
+
finally {
|
|
438
|
+
await fs_2.default.close(fd);
|
|
425
439
|
}
|
|
426
|
-
});
|
|
427
|
-
|
|
428
|
-
const stream = _fs2.default.createWriteStream(dstPath);
|
|
429
|
-
|
|
430
|
-
return await new _bluebird.default((resolve, reject) => {
|
|
431
|
-
archive.glob(pattern, {
|
|
432
|
-
cwd,
|
|
433
|
-
ignore
|
|
434
|
-
}).on('error', reject).pipe(stream);
|
|
435
|
-
stream.on('error', e => {
|
|
436
|
-
archive.unpipe(stream);
|
|
437
|
-
archive.abort();
|
|
438
|
-
archive.destroy();
|
|
439
|
-
reject(e);
|
|
440
|
-
}).on('finish', resolve);
|
|
441
|
-
archive.finalize();
|
|
442
|
-
});
|
|
443
440
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
441
|
+
exports.assertValidZip = assertValidZip;
|
|
442
|
+
/**
|
|
443
|
+
* @typedef ZipCompressionOptions
|
|
444
|
+
* @property {number} level [9] - Compression level in range 0..9
|
|
445
|
+
* (greater numbers mean better compression, but longer processing time)
|
|
446
|
+
*/
|
|
447
|
+
/**
|
|
448
|
+
* @typedef ZipSourceOptions
|
|
449
|
+
* @property {string} pattern ['**\/*'] - GLOB pattern for compression
|
|
450
|
+
* @property {string} cwd - The source root folder (the parent folder of
|
|
451
|
+
* the destination file by default)
|
|
452
|
+
* @property {string[]} [ignore] - The list of ignored patterns
|
|
453
|
+
*/
|
|
454
|
+
/**
|
|
455
|
+
* Creates an archive based on the given glob pattern
|
|
456
|
+
*
|
|
457
|
+
* @param {string} dstPath - The resulting archive path
|
|
458
|
+
* @param {ZipSourceOptions} src - Source options
|
|
459
|
+
* @param {ZipCompressionOptions} opts - Compression options
|
|
460
|
+
* @throws {Error} If there was an error while creating the archive
|
|
461
|
+
*/
|
|
462
|
+
async function toArchive(dstPath, src = /** @type {ZipSourceOptions} */ ({}), opts = /** @type {ZipCompressionOptions} */ ({})) {
|
|
463
|
+
const { level = 9 } = opts;
|
|
464
|
+
const { pattern = '**/*', cwd = path_1.default.dirname(dstPath), ignore = [] } = src;
|
|
465
|
+
const archive = (0, archiver_1.default)('zip', { zlib: { level } });
|
|
466
|
+
const stream = fs_2.default.createWriteStream(dstPath);
|
|
467
|
+
return await new bluebird_1.default((resolve, reject) => {
|
|
468
|
+
archive
|
|
469
|
+
.glob(pattern, {
|
|
470
|
+
cwd,
|
|
471
|
+
ignore,
|
|
472
|
+
})
|
|
473
|
+
.on('error', reject)
|
|
474
|
+
.pipe(stream);
|
|
475
|
+
stream
|
|
476
|
+
.on('error', (e) => {
|
|
477
|
+
archive.unpipe(stream);
|
|
478
|
+
archive.abort();
|
|
479
|
+
archive.destroy();
|
|
480
|
+
reject(e);
|
|
481
|
+
})
|
|
482
|
+
.on('finish', resolve);
|
|
483
|
+
archive.finalize();
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
exports.toArchive = toArchive;
|
|
487
|
+
/**
|
|
488
|
+
* Finds and memoizes the full path to the given executable.
|
|
489
|
+
* Rejects if it is not found.
|
|
490
|
+
*/
|
|
491
|
+
const getExecutablePath = lodash_1.default.memoize(
|
|
492
|
+
/**
|
|
493
|
+
* @returns {Promise<string>} Full Path to the executable
|
|
494
|
+
*/
|
|
495
|
+
async function getExecutablePath(binaryName) {
|
|
496
|
+
const fullPath = await fs_2.default.which(binaryName);
|
|
497
|
+
logger_1.default.debug(`Found '${binaryName}' at '${fullPath}'`);
|
|
498
|
+
return fullPath;
|
|
451
499
|
});
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
toArchive
|
|
500
|
+
exports.default = {
|
|
501
|
+
extractAllTo,
|
|
502
|
+
readEntries,
|
|
503
|
+
toInMemoryZip,
|
|
504
|
+
assertValidZip,
|
|
505
|
+
toArchive,
|
|
459
506
|
};
|
|
460
|
-
|
|
461
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJvcGVuWmlwIiwiQiIsInByb21pc2lmeSIsInlhdXpsIiwib3BlbiIsInBpcGVsaW5lIiwic3RyZWFtIiwiWklQX01BR0lDIiwiSUZNVCIsIklGRElSIiwiSUZMTksiLCJaaXBFeHRyYWN0b3IiLCJ6aXBmaWxlIiwiY29uc3RydWN0b3IiLCJzb3VyY2VQYXRoIiwib3B0cyIsInppcFBhdGgiLCJjYW5jZWxlZCIsImV4dHJhY3RGaWxlTmFtZSIsImVudHJ5IiwiXyIsImlzQnVmZmVyIiwiZmlsZU5hbWUiLCJ0b1N0cmluZyIsImZpbGVOYW1lc0VuY29kaW5nIiwiZXh0cmFjdCIsImRpciIsImxhenlFbnRyaWVzIiwiZGVjb2RlU3RyaW5ncyIsInJlc29sdmUiLCJyZWplY3QiLCJvbiIsImVyciIsInJlYWRFbnRyeSIsInN0YXJ0c1dpdGgiLCJkZXN0RGlyIiwicGF0aCIsImRpcm5hbWUiLCJqb2luIiwiZnMiLCJta2RpciIsInJlY3Vyc2l2ZSIsImNhbm9uaWNhbERlc3REaXIiLCJyZWFscGF0aCIsInJlbGF0aXZlRGVzdERpciIsInJlbGF0aXZlIiwic3BsaXQiLCJzZXAiLCJpbmNsdWRlcyIsIkVycm9yIiwiZXh0cmFjdEVudHJ5IiwiY2xvc2UiLCJkZXN0IiwibW9kZSIsImV4dGVybmFsRmlsZUF0dHJpYnV0ZXMiLCJpc1N5bWxpbmsiLCJpc0RpciIsImVuZHNXaXRoIiwidmVyc2lvbk1hZGVCeSIsInByb2NNb2RlIiwiZ2V0RXh0cmFjdGVkTW9kZSIsIm1rZGlyT3B0aW9ucyIsIm9wZW5SZWFkU3RyZWFtIiwiYmluZCIsInJlYWRTdHJlYW0iLCJsaW5rIiwiZ2V0U3RyZWFtIiwic3ltbGluayIsImNyZWF0ZVdyaXRlU3RyZWFtIiwiZW50cnlNb2RlIiwiZGVmYXVsdERpck1vZGUiLCJkZWZhdWx0RmlsZU1vZGUiLCJwYXJzZUludCIsImV4dHJhY3RBbGxUbyIsInppcEZpbGVQYXRoIiwiaXNBYnNvbHV0ZSIsInVzZVN5c3RlbVVuemlwIiwiZXh0cmFjdFdpdGhTeXN0ZW1VbnppcCIsImxvZyIsIndhcm4iLCJzdGRlcnIiLCJtZXNzYWdlIiwiZXh0cmFjdG9yIiwiaXNXaW5kb3dzSG9zdCIsImlzV2luZG93cyIsImV4ZWN1dGFibGVQYXRoIiwiZ2V0RXhlY3V0YWJsZVBhdGgiLCJlIiwiZXhlYyIsIl9leHRyYWN0RW50cnlUbyIsInppcEZpbGUiLCJkc3RQYXRoIiwidGVzdCIsImV4aXN0cyIsIm1rZGlycCIsIndyaXRlU3RyZWFtIiwiZmxhZ3MiLCJ3cml0ZVN0cmVhbVByb21pc2UiLCJvbmNlIiwiemlwUmVhZFN0cmVhbSIsInppcFJlYWRTdHJlYW1Qcm9taXNlIiwicGlwZSIsImFsbCIsInJlYWRFbnRyaWVzIiwib25FbnRyeSIsInJlcyIsImV4dHJhY3RFbnRyeVRvIiwiZW1pdCIsInRvSW5NZW1vcnlaaXAiLCJzcmNQYXRoIiwiaXNNZXRlcmVkIiwiZW5jb2RlVG9CYXNlNjQiLCJtYXhTaXplIiwiR2lCIiwibGV2ZWwiLCJyZXN1bHRCdWZmZXJzIiwicmVzdWx0QnVmZmVyc1NpemUiLCJyZXN1bHRXcml0ZVN0cmVhbSIsIldyaXRhYmxlIiwid3JpdGUiLCJidWZmZXIiLCJlbmNvZGluZyIsIm5leHQiLCJwdXNoIiwibGVuZ3RoIiwidG9SZWFkYWJsZVNpemVTdHJpbmciLCJhcmNoaXZlIiwiYXJjaGl2ZXIiLCJ6bGliIiwic3JjU2l6ZSIsImJhc2U2NEVuY29kZXJTdHJlYW0iLCJCYXNlNjRFbmNvZGUiLCJyZXN1bHRXcml0ZVN0cmVhbVByb21pc2UiLCJ1bnBpcGUiLCJhYm9ydCIsImRlc3Ryb3kiLCJwb2ludGVyIiwiYXJjaGl2ZVN0cmVhbVByb21pc2UiLCJ0aW1lciIsIlRpbWVyIiwic3RhcnQiLCJzdGF0IiwiaXNEaXJlY3RvcnkiLCJkaXJlY3RvcnkiLCJmaWxlIiwibmFtZSIsImJhc2VuYW1lIiwiZmluYWxpemUiLCJkZWJ1ZyIsImdldER1cmF0aW9uIiwiYXNTZWNvbmRzIiwidG9GaXhlZCIsIkJ1ZmZlciIsImNvbmNhdCIsImFzc2VydFZhbGlkWmlwIiwiZmlsZVBhdGgiLCJzaXplIiwiZmQiLCJhbGxvYyIsInJlYWQiLCJzaWduYXR1cmUiLCJ0b0FyY2hpdmUiLCJzcmMiLCJwYXR0ZXJuIiwiY3dkIiwiaWdub3JlIiwiZ2xvYiIsIm1lbW9pemUiLCJiaW5hcnlOYW1lIiwiZnVsbFBhdGgiLCJ3aGljaCJdLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi96aXAuanMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCBCIGZyb20gJ2JsdWViaXJkJztcbmltcG9ydCB5YXV6bCBmcm9tICd5YXV6bCc7XG5pbXBvcnQgYXJjaGl2ZXIgZnJvbSAnYXJjaGl2ZXInO1xuaW1wb3J0IHtjcmVhdGVXcml0ZVN0cmVhbX0gZnJvbSAnZnMnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgc3RyZWFtIGZyb20gJ3N0cmVhbSc7XG5pbXBvcnQgZnMgZnJvbSAnLi9mcyc7XG5pbXBvcnQge2lzV2luZG93c30gZnJvbSAnLi9zeXN0ZW0nO1xuaW1wb3J0IHtCYXNlNjRFbmNvZGV9IGZyb20gJ2Jhc2U2NC1zdHJlYW0nO1xuaW1wb3J0IHt0b1JlYWRhYmxlU2l6ZVN0cmluZywgR2lCfSBmcm9tICcuL3V0aWwnO1xuaW1wb3J0IFRpbWVyIGZyb20gJy4vdGltaW5nJztcbmltcG9ydCBsb2cgZnJvbSAnLi9sb2dnZXInO1xuaW1wb3J0IGdldFN0cmVhbSBmcm9tICdnZXQtc3RyZWFtJztcbmltcG9ydCB7ZXhlY30gZnJvbSAndGVlbl9wcm9jZXNzJztcblxuLyoqXG4gKiBAdHlwZSB7KHBhdGg6IHN0cmluZywgb3B0aW9ucz86IHlhdXpsLk9wdGlvbnMpID0+IFByb21pc2U8eWF1emwuWmlwRmlsZT59XG4gKi9cbmNvbnN0IG9wZW5aaXAgPSBCLnByb21pc2lmeSh5YXV6bC5vcGVuKTtcbi8qKlxuICogQHR5cGUgeyhzb3VyY2U6IE5vZGVKUy5SZWFkYWJsZVN0cmVhbSwgZGVzdGluYXRpb246IE5vZGVKUy5Xcml0YWJsZVN0cmVhbSkgPT4gUHJvbWlzZTxOb2RlSlMuV3JpdGFibGVTdHJlYW0+fVxuICovXG5jb25zdCBwaXBlbGluZSA9IEIucHJvbWlzaWZ5KHN0cmVhbS5waXBlbGluZSk7XG5jb25zdCBaSVBfTUFHSUMgPSAnUEsnO1xuY29uc3QgSUZNVCA9IDYxNDQwO1xuY29uc3QgSUZESVIgPSAxNjM4NDtcbmNvbnN0IElGTE5LID0gNDA5NjA7XG5cbi8vIFRoaXMgY2xhc3MgaXMgbW9zdGx5IGNvcGllZCBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9tYXhvZ2Rlbi9leHRyYWN0LXppcC9ibG9iL21hc3Rlci9pbmRleC5qc1xuY2xhc3MgWmlwRXh0cmFjdG9yIHtcbiAgLyoqIEB0eXBlIHt5YXV6bC5aaXBGaWxlfSAqL1xuICB6aXBmaWxlO1xuXG4gIGNvbnN0cnVjdG9yKHNvdXJjZVBhdGgsIG9wdHMgPSB7fSkge1xuICAgIHRoaXMuemlwUGF0aCA9IHNvdXJjZVBhdGg7XG4gICAgdGhpcy5vcHRzID0gb3B0cztcbiAgICB0aGlzLmNhbmNlbGVkID0gZmFsc2U7XG4gIH1cblxuICBleHRyYWN0RmlsZU5hbWUoZW50cnkpIHtcbiAgICByZXR1cm4gXy5pc0J1ZmZlcihlbnRyeS5maWxlTmFtZSlcbiAgICAgID8gZW50cnkuZmlsZU5hbWUudG9TdHJpbmcodGhpcy5vcHRzLmZpbGVOYW1lc0VuY29kaW5nKVxuICAgICAgOiBlbnRyeS5maWxlTmFtZTtcbiAgfVxuXG4gIGFzeW5jIGV4dHJhY3QoKSB7XG4gICAgY29uc3Qge2RpciwgZmlsZU5hbWVzRW5jb2Rpbmd9ID0gdGhpcy5vcHRzO1xuICAgIHRoaXMuemlwZmlsZSA9IGF3YWl0IG9wZW5aaXAodGhpcy56aXBQYXRoLCB7XG4gICAgICBsYXp5RW50cmllczogdHJ1ZSxcbiAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS90aGVqb3Nod29sZmUveWF1emwvY29tbWl0L2NjNzQ1NWFjNzg5YmE4NDk3MzE4NGU1ZWJkZTA1ODFjZGM0YzNiMzkjZGlmZi0wNGM2ZTkwZmFhYzI2NzVhYTg5ZTIxNzZkMmVlYzdkOFI5NVxuICAgICAgZGVjb2RlU3RyaW5nczogIWZpbGVOYW1lc0VuY29kaW5nLFxuICAgIH0pO1xuICAgIHRoaXMuY2FuY2VsZWQgPSBmYWxzZTtcblxuICAgIHJldHVybiBuZXcgQigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLnppcGZpbGUub24oJ2Vycm9yJywgKGVycikgPT4ge1xuICAgICAgICB0aGlzLmNhbmNlbGVkID0gdHJ1ZTtcbiAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICB9KTtcbiAgICAgIHRoaXMuemlwZmlsZS5yZWFkRW50cnkoKTtcblxuICAgICAgdGhpcy56aXBmaWxlLm9uKCdjbG9zZScsICgpID0+IHtcbiAgICAgICAgaWYgKCF0aGlzLmNhbmNlbGVkKSB7XG4gICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgdGhpcy56aXBmaWxlLm9uKCdlbnRyeScsIGFzeW5jIChlbnRyeSkgPT4ge1xuICAgICAgICBpZiAodGhpcy5jYW5jZWxlZCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGZpbGVOYW1lID0gdGhpcy5leHRyYWN0RmlsZU5hbWUoZW50cnkpO1xuICAgICAgICBpZiAoZmlsZU5hbWUuc3RhcnRzV2l0aCgnX19NQUNPU1gvJykpIHtcbiAgICAgICAgICB0aGlzLnppcGZpbGUucmVhZEVudHJ5KCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZGVzdERpciA9IHBhdGguZGlybmFtZShwYXRoLmpvaW4oZGlyLCBmaWxlTmFtZSkpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGZzLm1rZGlyKGRlc3REaXIsIHtyZWN1cnNpdmU6IHRydWV9KTtcblxuICAgICAgICAgIGNvbnN0IGNhbm9uaWNhbERlc3REaXIgPSBhd2FpdCBmcy5yZWFscGF0aChkZXN0RGlyKTtcbiAgICAgICAgICBjb25zdCByZWxhdGl2ZURlc3REaXIgPSBwYXRoLnJlbGF0aXZlKGRpciwgY2Fub25pY2FsRGVzdERpcik7XG5cbiAgICAgICAgICBpZiAocmVsYXRpdmVEZXN0RGlyLnNwbGl0KHBhdGguc2VwKS5pbmNsdWRlcygnLi4nKSkge1xuICAgICAgICAgICAgbmV3IEVycm9yKFxuICAgICAgICAgICAgICBgT3V0IG9mIGJvdW5kIHBhdGggXCIke2Nhbm9uaWNhbERlc3REaXJ9XCIgZm91bmQgd2hpbGUgcHJvY2Vzc2luZyBmaWxlICR7ZmlsZU5hbWV9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBhd2FpdCB0aGlzLmV4dHJhY3RFbnRyeShlbnRyeSk7XG4gICAgICAgICAgdGhpcy56aXBmaWxlLnJlYWRFbnRyeSgpO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICB0aGlzLmNhbmNlbGVkID0gdHJ1ZTtcbiAgICAgICAgICB0aGlzLnppcGZpbGUuY2xvc2UoKTtcbiAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBleHRyYWN0RW50cnkoZW50cnkpIHtcbiAgICBpZiAodGhpcy5jYW5jZWxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHtkaXJ9ID0gdGhpcy5vcHRzO1xuXG4gICAgY29uc3QgZmlsZU5hbWUgPSB0aGlzLmV4dHJhY3RGaWxlTmFtZShlbnRyeSk7XG4gICAgY29uc3QgZGVzdCA9IHBhdGguam9pbihkaXIsIGZpbGVOYW1lKTtcblxuICAgIC8vIGNvbnZlcnQgZXh0ZXJuYWwgZmlsZSBhdHRyIGludCBpbnRvIGEgZnMgc3RhdCBtb2RlIGludFxuICAgIGNvbnN0IG1vZGUgPSAoZW50cnkuZXh0ZXJuYWxGaWxlQXR0cmlidXRlcyA+PiAxNikgJiAweGZmZmY7XG4gICAgLy8gY2hlY2sgaWYgaXQncyBhIHN5bWxpbmsgb3IgZGlyICh1c2luZyBzdGF0IG1vZGUgY29uc3RhbnRzKVxuICAgIGNvbnN0IGlzU3ltbGluayA9IChtb2RlICYgSUZNVCkgPT09IElGTE5LO1xuICAgIGNvbnN0IGlzRGlyID1cbiAgICAgIChtb2RlICYgSUZNVCkgPT09IElGRElSIHx8XG4gICAgICAvLyBGYWlsc2FmZSwgYm9ycm93ZWQgZnJvbSBqc1ppcFxuICAgICAgZmlsZU5hbWUuZW5kc1dpdGgoJy8nKSB8fFxuICAgICAgLy8gY2hlY2sgZm9yIHdpbmRvd3Mgd2VpcmQgd2F5IG9mIHNwZWNpZnlpbmcgYSBkaXJlY3RvcnlcbiAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tYXhvZ2Rlbi9leHRyYWN0LXppcC9pc3N1ZXMvMTMjaXNzdWVjb21tZW50LTE1NDQ5NDU2NlxuICAgICAgKGVudHJ5LnZlcnNpb25NYWRlQnkgPj4gOCA9PT0gMCAmJiBlbnRyeS5leHRlcm5hbEZpbGVBdHRyaWJ1dGVzID09PSAxNik7XG4gICAgY29uc3QgcHJvY01vZGUgPSB0aGlzLmdldEV4dHJhY3RlZE1vZGUobW9kZSwgaXNEaXIpICYgMG83Nzc7XG4gICAgLy8gYWx3YXlzIGVuc3VyZSBmb2xkZXJzIGFyZSBjcmVhdGVkXG4gICAgY29uc3QgZGVzdERpciA9IGlzRGlyID8gZGVzdCA6IHBhdGguZGlybmFtZShkZXN0KTtcbiAgICBjb25zdCBta2Rpck9wdGlvbnMgPSB7cmVjdXJzaXZlOiB0cnVlfTtcbiAgICBpZiAoaXNEaXIpIHtcbiAgICAgIG1rZGlyT3B0aW9ucy5tb2RlID0gcHJvY01vZGU7XG4gICAgfVxuICAgIGF3YWl0IGZzLm1rZGlyKGRlc3REaXIsIG1rZGlyT3B0aW9ucyk7XG4gICAgaWYgKGlzRGlyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLyoqIEB0eXBlIHsoZW50cnk6IHlhdXpsLkVudHJ5KSA9PiBQcm9taXNlPE5vZGVKUy5SZWFkYWJsZVN0cmVhbT59ICovXG4gICAgY29uc3Qgb3BlblJlYWRTdHJlYW0gPSBCLnByb21pc2lmeSh0aGlzLnppcGZpbGUub3BlblJlYWRTdHJlYW0uYmluZCh0aGlzLnppcGZpbGUpKTtcbiAgICBjb25zdCByZWFkU3RyZWFtID0gYXdhaXQgb3BlblJlYWRTdHJlYW0oZW50cnkpO1xuICAgIGlmIChpc1N5bWxpbmspIHtcbiAgICAgIGNvbnN0IGxpbmsgPSBhd2FpdCBnZXRTdHJlYW0ocmVhZFN0cmVhbSk7XG4gICAgICBhd2FpdCBmcy5zeW1saW5rKGxpbmssIGRlc3QpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCBwaXBlbGluZShyZWFkU3RyZWFtLCBmcy5jcmVhdGVXcml0ZVN0cmVhbShkZXN0LCB7bW9kZTogcHJvY01vZGV9KSk7XG4gICAgfVxuICB9XG5cbiAgZ2V0RXh0cmFjdGVkTW9kZShlbnRyeU1vZGUsIGlzRGlyKSB7XG4gICAgY29uc3Qge2RlZmF1bHREaXJNb2RlLCBkZWZhdWx0RmlsZU1vZGV9ID0gdGhpcy5vcHRzO1xuXG4gICAgbGV0IG1vZGUgPSBlbnRyeU1vZGU7XG4gICAgLy8gU2V0IGRlZmF1bHRzLCBpZiBuZWNlc3NhcnlcbiAgICBpZiAobW9kZSA9PT0gMCkge1xuICAgICAgaWYgKGlzRGlyKSB7XG4gICAgICAgIGlmIChkZWZhdWx0RGlyTW9kZSkge1xuICAgICAgICAgIG1vZGUgPSBwYXJzZUludChkZWZhdWx0RGlyTW9kZSwgMTApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFtb2RlKSB7XG4gICAgICAgICAgbW9kZSA9IDBvNzU1O1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoZGVmYXVsdEZpbGVNb2RlKSB7XG4gICAgICAgICAgbW9kZSA9IHBhcnNlSW50KGRlZmF1bHRGaWxlTW9kZSwgMTApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFtb2RlKSB7XG4gICAgICAgICAgbW9kZSA9IDBvNjQ0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGU7XG4gIH1cbn1cblxuLyoqXG4gKiBAdHlwZWRlZiBFeHRyYWN0QWxsT3B0aW9uc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IFtmaWxlTmFtZXNFbmNvZGluZ10gVGhlIGVuY29kaW5nIHRvIHVzZSBmb3IgZXh0cmFjdGVkIGZpbGUgbmFtZXMuXG4gKiBGb3IgWklQIGFyY2hpdmVzIGNyZWF0ZWQgb24gTWFjT1MgaXQgaXMgdXN1YWxseSBleHBlY3RlZCB0byBiZSBgdXRmOGAuXG4gKiBCeSBkZWZhdWx0IGl0IGlzIGF1dG9kZXRlY3RlZCBiYXNlZCBvbiB0aGUgZW50cnkgbWV0YWRhdGEgYW5kIGlzIG9ubHkgbmVlZGVkIHRvIGJlIHNldCBleHBsaWNpdGx5XG4gKiBpZiB0aGUgcGFydGljdWxhciBhcmNoaXZlIGRvZXMgbm90IGNvbXBseSB0byB0aGUgc3RhbmRhcmRzLCB3aGljaCBsZWFkcyB0byBjb3JydXB0ZWQgZmlsZSBuYW1lc1xuICogYWZ0ZXIgZXh0cmFjdGlvbi4gT25seSBhcHBsaWNhYmxlIGlmIHN5c3RlbSB1bnppcCBiaW5hcnkgaXMgTk9UIGJlaW5nIHVzZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFt1c2VTeXN0ZW1VbnppcF0gSWYgdHJ1ZSwgYXR0ZW1wdCB0byB1c2Ugc3lzdGVtIHVuemlwOyBpZiB0aGlzIGZhaWxzLFxuICogZmFsbGJhY2sgdG8gdGhlIEpTIHVuemlwIGltcGxlbWVudGF0aW9uLlxuICovXG5cbi8qKlxuICogRXh0cmFjdCB6aXBmaWxlIHRvIGEgZGlyZWN0b3J5XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHppcEZpbGVQYXRoIFRoZSBmdWxsIHBhdGggdG8gdGhlIHNvdXJjZSBaSVAgZmlsZVxuICogQHBhcmFtIHtzdHJpbmd9IGRlc3REaXIgVGhlIGZ1bGwgcGF0aCB0byB0aGUgZGVzdGluYXRpb24gZm9sZGVyXG4gKiBAcGFyYW0ge0V4dHJhY3RBbGxPcHRpb25zfSBbb3B0c11cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZXh0cmFjdEFsbFRvKHppcEZpbGVQYXRoLCBkZXN0RGlyLCBvcHRzID0gLyoqIEB0eXBlIHtFeHRyYWN0QWxsT3B0aW9uc30gKi8gKHt9KSkge1xuICBpZiAoIXBhdGguaXNBYnNvbHV0ZShkZXN0RGlyKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVGFyZ2V0IHBhdGggJyR7ZGVzdERpcn0nIGlzIGV4cGVjdGVkIHRvIGJlIGFic29sdXRlYCk7XG4gIH1cblxuICBhd2FpdCBmcy5ta2RpcihkZXN0RGlyLCB7cmVjdXJzaXZlOiB0cnVlfSk7XG4gIGNvbnN0IGRpciA9IGF3YWl0IGZzLnJlYWxwYXRoKGRlc3REaXIpO1xuICBpZiAob3B0cy51c2VTeXN0ZW1VbnppcCkge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBleHRyYWN0V2l0aFN5c3RlbVVuemlwKHppcEZpbGVQYXRoLCBkaXIpO1xuICAgICAgcmV0dXJuO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgbG9nLndhcm4oJ3VuemlwIGZhaWxlZDsgZmFsbGluZyBiYWNrIHRvIEpTOiAlcycsIGVyci5zdGRlcnIgfHwgZXJyLm1lc3NhZ2UpO1xuICAgIH1cbiAgfVxuICBjb25zdCBleHRyYWN0b3IgPSBuZXcgWmlwRXh0cmFjdG9yKHppcEZpbGVQYXRoLCB7XG4gICAgLi4ub3B0cyxcbiAgICBkaXIsXG4gIH0pO1xuICBhd2FpdCBleHRyYWN0b3IuZXh0cmFjdCgpO1xufVxuXG4vKipcbiAqIEV4ZWN1dGVzIHN5c3RlbSB1bnppcCAoZS5nLiwgYC91c3IvYmluL3VuemlwYCkuIElmIGF2YWlsYWJsZSwgaXQgaXNcbiAqIHNpZ25pZmljYW50bHkgZmFzdGVyIHRoYW4gdGhlIEpTIGltcGxlbWVudGF0aW9uLlxuICogQnkgZGVmYXVsdCBhbGwgZmlsZXMgaW4gdGhlIGRlc3REaXIgZ2V0IG92ZXJyaWRkZW4gaWYgYWxyZWFkeSBleGlzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gemlwRmlsZVBhdGggVGhlIGZ1bGwgcGF0aCB0byB0aGUgc291cmNlIFpJUCBmaWxlXG4gKiBAcGFyYW0ge3N0cmluZ30gZGVzdERpciBUaGUgZnVsbCBwYXRoIHRvIHRoZSBkZXN0aW5hdGlvbiBmb2xkZXIuXG4gKiBUaGlzIGZvbGRlciBpcyBleHBlY3RlZCB0byBhbHJlYWR5IGV4aXN0IGJlZm9yZSBleHRyYWN0aW5nIHRoZSBhcmNoaXZlLlxuICovXG5hc3luYyBmdW5jdGlvbiBleHRyYWN0V2l0aFN5c3RlbVVuemlwKHppcEZpbGVQYXRoLCBkZXN0RGlyKSB7XG4gIGNvbnN0IGlzV2luZG93c0hvc3QgPSBpc1dpbmRvd3MoKTtcbiAgbGV0IGV4ZWN1dGFibGVQYXRoO1xuICB0cnkge1xuICAgIGV4ZWN1dGFibGVQYXRoID0gYXdhaXQgZ2V0RXhlY3V0YWJsZVBhdGgoaXNXaW5kb3dzSG9zdCA/ICdwb3dlcnNoZWxsLmV4ZScgOiAndW56aXAnKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGZpbmQgc3lzdGVtIHVuemlwJyk7XG4gIH1cblxuICBpZiAoaXNXaW5kb3dzSG9zdCkge1xuICAgIC8vIG9uIFdpbmRvd3Mgd2UgdXNlIFBvd2VyU2hlbGwgdG8gdW56aXAgZmlsZXNcbiAgICBhd2FpdCBleGVjKGV4ZWN1dGFibGVQYXRoLCBbXG4gICAgICAnLWNvbW1hbmQnLFxuICAgICAgJ0V4cGFuZC1BcmNoaXZlJyxcbiAgICAgICctTGl0ZXJhbFBhdGgnLFxuICAgICAgemlwRmlsZVBhdGgsXG4gICAgICAnLURlc3RpbmF0aW9uUGF0aCcsXG4gICAgICBkZXN0RGlyLFxuICAgICAgJy1Gb3JjZScsXG4gICAgXSk7XG4gIH0gZWxzZSB7XG4gICAgLy8gLXEgbWVhbnMgcXVpZXQgKG5vIHN0ZG91dClcbiAgICAvLyAtbyBtZWFucyBvdmVyd3JpdGVcbiAgICAvLyAtZCBpcyB0aGUgZGVzdCBkaXJcbiAgICBhd2FpdCBleGVjKGV4ZWN1dGFibGVQYXRoLCBbJy1xJywgJy1vJywgemlwRmlsZVBhdGgsICctZCcsIGRlc3REaXJdKTtcbiAgfVxufVxuXG4vKipcbiAqIEV4dHJhY3QgYSBzaW5nbGUgemlwIGVudHJ5IHRvIGEgZGlyZWN0b3J5XG4gKlxuICogQHBhcmFtIHt5YXV6bC5aaXBGaWxlfSB6aXBGaWxlIFRoZSBzb3VyY2UgWklQIHN0cmVhbVxuICogQHBhcmFtIHt5YXV6bC5FbnRyeX0gZW50cnkgVGhlIGVudHJ5IGluc3RhbmNlXG4gKiBAcGFyYW0ge3N0cmluZ30gZGVzdERpciBUaGUgZnVsbCBwYXRoIHRvIHRoZSBkZXN0aW5hdGlvbiBmb2xkZXJcbiAqL1xuYXN5bmMgZnVuY3Rpb24gX2V4dHJhY3RFbnRyeVRvKHppcEZpbGUsIGVudHJ5LCBkZXN0RGlyKSB7XG4gIGNvbnN0IGRzdFBhdGggPSBwYXRoLnJlc29sdmUoZGVzdERpciwgZW50cnkuZmlsZU5hbWUpO1xuXG4gIC8vIENyZWF0ZSBkZXN0IGRpcmVjdG9yeSBpZiBkb2Vzbid0IGV4aXN0IGFscmVhZHlcbiAgaWYgKC9cXC8kLy50ZXN0KGVudHJ5LmZpbGVOYW1lKSkge1xuICAgIGlmICghKGF3YWl0IGZzLmV4aXN0cyhkc3RQYXRoKSkpIHtcbiAgICAgIGF3YWl0IGZzLm1rZGlycChkc3RQYXRoKTtcbiAgICB9XG4gICAgcmV0dXJuO1xuICB9IGVsc2UgaWYgKCEoYXdhaXQgZnMuZXhpc3RzKHBhdGguZGlybmFtZShkc3RQYXRoKSkpKSB7XG4gICAgYXdhaXQgZnMubWtkaXJwKHBhdGguZGlybmFtZShkc3RQYXRoKSk7XG4gIH1cblxuICAvLyBDcmVhdGUgYSB3cml0ZSBzdHJlYW1cbiAgY29uc3Qgd3JpdGVTdHJlYW0gPSBjcmVhdGVXcml0ZVN0cmVhbShkc3RQYXRoLCB7ZmxhZ3M6ICd3J30pO1xuICBjb25zdCB3cml0ZVN0cmVhbVByb21pc2UgPSBuZXcgQigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgd3JpdGVTdHJlYW0ub25jZSgnZmluaXNoJywgcmVzb2x2ZSk7XG4gICAgd3JpdGVTdHJlYW0ub25jZSgnZXJyb3InLCByZWplY3QpO1xuICB9KTtcblxuICAvLyBDcmVhdGUgemlwUmVhZFN0cmVhbSBhbmQgcGlwZSBkYXRhIHRvIHRoZSB3cml0ZSBzdHJlYW1cbiAgLy8gKGZvciBzb21lIG9kZCByZWFzb24gQi5wcm9taXNpZnkgZG9lc24ndCB3b3JrIG9uIHppcGZpbGUub3BlblJlYWRTdHJlYW0sIGl0IGNhdXNlcyBhbiBlcnJvciAnY2xvc2VkJylcbiAgY29uc3QgemlwUmVhZFN0cmVhbSA9IGF3YWl0IG5ldyBCKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICB6aXBGaWxlLm9wZW5SZWFkU3RyZWFtKGVudHJ5LCAoZXJyLCByZWFkU3RyZWFtKSA9PiAoZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlYWRTdHJlYW0pKSk7XG4gIH0pO1xuICBjb25zdCB6aXBSZWFkU3RyZWFtUHJvbWlzZSA9IG5ldyBCKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICB6aXBSZWFkU3RyZWFtLm9uY2UoJ2VuZCcsIHJlc29sdmUpO1xuICAgIHppcFJlYWRTdHJlYW0ub25jZSgnZXJyb3InLCByZWplY3QpO1xuICB9KTtcbiAgemlwUmVhZFN0cmVhbS5waXBlKHdyaXRlU3RyZWFtKTtcblxuICAvLyBXYWl0IGZvciB0aGUgemlwUmVhZFN0cmVhbSBhbmQgd3JpdGVTdHJlYW0gdG8gZW5kIGJlZm9yZSByZXR1cm5pbmdcbiAgcmV0dXJuIGF3YWl0IEIuYWxsKFt6aXBSZWFkU3RyZWFtUHJvbWlzZSwgd3JpdGVTdHJlYW1Qcm9taXNlXSk7XG59XG5cbi8qKlxuICogQHR5cGVkZWYgWmlwRW50cnlcbiAqIEBwcm9wZXJ0eSB7eWF1emwuRW50cnl9IGVudHJ5IFRoZSBhY3R1YWwgZW50cnkgaW5zdGFuY2VcbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb259IGV4dHJhY3RFbnRyeVRvIEFuIGFzeW5jIGZ1bmN0aW9uLCB3aGljaCBhY2NlcHRzIG9uZSBwYXJhbWV0ZXIuXG4gKiBUaGlzIHBhcmFtZXRlciBjb250YWlucyB0aGUgZGVzdGluYXRpb24gZm9sZGVyIHBhdGggdG8gd2hpY2ggdGhpcyBmdW5jdGlvbiBpcyBnb2luZyB0byBleHRyYWN0IHRoZSBlbnRyeS5cbiAqL1xuXG4vKipcbiAqIEdldCBlbnRyaWVzIGZvciBhIHppcCBmb2xkZXJcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gemlwRmlsZVBhdGggVGhlIGZ1bGwgcGF0aCB0byB0aGUgc291cmNlIFpJUCBmaWxlXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBvbkVudHJ5IENhbGxiYWNrIHdoZW4gZW50cnkgaXMgcmVhZC5cbiAqIFRoZSBjYWxsYmFjayBpcyBleHBlY3RlZCB0byBhY2NlcHQgb25lIGFyZ3VtZW50IG9mIFppcEVudHJ5IHR5cGUuXG4gKiBUaGUgaXRlcmF0aW9uIHRocm91Z2ggdGhlIHNvdXJjZSB6aXAgZmlsZSB3aWxsIGJpIHRlcm1pbmF0ZWQgYXMgc29vbiBhc1xuICogdGhlIHJlc3VsdCBvZiB0aGlzIGZ1bmN0aW9uIGVxdWFscyB0byBgZmFsc2VgLlxuICovXG5hc3luYyBmdW5jdGlvbiByZWFkRW50cmllcyh6aXBGaWxlUGF0aCwgb25FbnRyeSkge1xuICAvLyBPcGVuIGEgemlwIGZpbGUgYW5kIHN0YXJ0IHJlYWRpbmcgZW50cmllc1xuICBjb25zdCB6aXBmaWxlID0gYXdhaXQgb3BlblppcCh6aXBGaWxlUGF0aCwge2xhenlFbnRyaWVzOiB0cnVlfSk7XG4gIGNvbnN0IHppcFJlYWRTdHJlYW1Qcm9taXNlID0gbmV3IEIoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHppcGZpbGUub25jZSgnZW5kJywgcmVzb2x2ZSk7XG4gICAgemlwZmlsZS5vbmNlKCdlcnJvcicsIHJlamVjdCk7XG5cbiAgICAvLyBPbiBlYWNoIGVudHJ5LCBjYWxsICdvbkVudHJ5JyBhbmQgdGhlbiByZWFkIHRoZSBuZXh0IGVudHJ5XG4gICAgemlwZmlsZS5vbignZW50cnknLCBhc3luYyAoZW50cnkpID0+IHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IG9uRW50cnkoe1xuICAgICAgICBlbnRyeSxcbiAgICAgICAgZXh0cmFjdEVudHJ5VG86IGFzeW5jIChkZXN0RGlyKSA9PiBhd2FpdCBfZXh0cmFjdEVudHJ5VG8oemlwZmlsZSwgZW50cnksIGRlc3REaXIpLFxuICAgICAgfSk7XG4gICAgICBpZiAocmVzID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm4gemlwZmlsZS5lbWl0KCdlbmQnKTtcbiAgICAgIH1cbiAgICAgIHppcGZpbGUucmVhZEVudHJ5KCk7XG4gICAgfSk7XG4gIH0pO1xuICB6aXBmaWxlLnJlYWRFbnRyeSgpO1xuXG4gIC8vIFdhaXQgZm9yIHRoZSBlbnRyaWVzIHRvIGZpbmlzaCBiZWluZyBpdGVyYXRlZCB0aHJvdWdoXG4gIHJldHVybiBhd2FpdCB6aXBSZWFkU3RyZWFtUHJvbWlzZTtcbn1cblxuLyoqXG4gKiBAdHlwZWRlZiBaaXBPcHRpb25zXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGVuY29kZVRvQmFzZTY0IFtmYWxzZV0gV2hldGhlciB0byBlbmNvZGVcbiAqIHRoZSByZXN1bHRpbmcgYXJjaGl2ZSB0byBhIGJhc2U2NC1lbmNvZGVkIHN0cmluZ1xuICogQHByb3BlcnR5IHtib29sZWFufSBpc01ldGVyZWQgW3RydWVdIFdoZXRoZXIgdG8gbG9nIHRoZSBhY3R1YWxcbiAqIGFyY2hpdmVyIHBlcmZvcm1hbmNlXG4gKiBAcHJvcGVydHkge251bWJlcn0gbWF4U2l6ZSBbMTA3Mzc0MTgyNF0gVGhlIG1heGltdW0gc2l6ZSBvZlxuICogdGhlIHJlc3VsdGluZyBhcmNoaXZlIGluIGJ5dGVzLiBUaGlzIGlzIHNldCB0byAxR0IgYnkgZGVmYXVsdCwgYmVjYXVzZVxuICogQXBwaXVtIGxpbWl0cyB0aGUgbWF4aW11bSBIVFRQIGJvZHkgc2l6ZSB0byAxR0IuIEFsc28sIHRoZSBOb2RlSlMgaGVhcFxuICogc2l6ZSBtdXN0IGJlIGVub3VnaCB0byBrZWVwIHRoZSByZXN1bHRpbmcgb2JqZWN0ICh1c3VhbGx5IHRoaXMgc2l6ZSBpc1xuICogbGltaXRlZCB0byAxLjQgR0IpXG4gKiBAcHJvcGVydHkge251bWJlcn0gbGV2ZWwgWzldIFRoZSBjb21wcmVzc2lvbiBsZXZlbC4gVGhlIG1heGltdW1cbiAqIGxldmVsIGlzIDkgKHRoZSBiZXN0IGNvbXByZXNzaW9uLCB3b3JzdCBwZXJmb3JtYW5jZSkuIFRoZSBtaW5pbXVtXG4gKiBjb21wcmVzc2lvbiBsZXZlbCBpcyAwIChubyBjb21wcmVzc2lvbikuXG4gKi9cblxuLyoqXG4gKiBDb252ZXJ0cyBjb250ZW50cyBvZiBsb2NhbCBkaXJlY3RvcnkgdG8gYW4gaW4tbWVtb3J5IC56aXAgYnVmZmVyXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHNyY1BhdGggVGhlIGZ1bGwgcGF0aCB0byB0aGUgZm9sZGVyIG9yIGZpbGUgYmVpbmcgemlwcGVkXG4gKiBAcGFyYW0ge1ppcE9wdGlvbnN9IG9wdHMgWmlwcGluZyBvcHRpb25zXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxCdWZmZXI+fSBaaXBwZWQgKGFuZCBlbmNvZGVkIGlmIGBlbmNvZGVUb0Jhc2U2NGAgaXMgdHJ1dGh5KVxuICogY29udGVudCBvZiB0aGUgc291cmNlIHBhdGggYXMgbWVtb3J5IGJ1ZmZlclxuICogQHRocm93cyB7RXJyb3J9IGlmIHRoZXJlIHdhcyBhbiBlcnJvciB3aGlsZSByZWFkaW5nIHRoZSBzb3VyY2VcbiAqIG9yIHRoZSBzb3VyY2UgaXMgdG9vIGJpZ1xuICovXG5hc3luYyBmdW5jdGlvbiB0b0luTWVtb3J5WmlwKHNyY1BhdGgsIG9wdHMgPSAvKiogQHR5cGUge1ppcE9wdGlvbnN9ICovICh7fSkpIHtcbiAgaWYgKCEoYXdhaXQgZnMuZXhpc3RzKHNyY1BhdGgpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgTm8gc3VjaCBmaWxlIG9yIGZvbGRlcjogJHtzcmNQYXRofWApO1xuICB9XG5cbiAgY29uc3Qge2lzTWV0ZXJlZCA9IHRydWUsIGVuY29kZVRvQmFzZTY0ID0gZmFsc2UsIG1heFNpemUgPSAxICogR2lCLCBsZXZlbCA9IDl9ID0gb3B0cztcbiAgY29uc3QgcmVzdWx0QnVmZmVycyA9IFtdO1xuICBsZXQgcmVzdWx0QnVmZmVyc1NpemUgPSAwO1xuICAvLyBDcmVhdGUgYSB3cml0YWJsZSBzdHJlYW0gdGhhdCB6aXAgYnVmZmVycyB3aWxsIGJlIHN0cmVhbWVkIHRvXG4gIGNvbnN0IHJlc3VsdFdyaXRlU3RyZWFtID0gbmV3IHN0cmVhbS5Xcml0YWJsZSh7XG4gICAgd3JpdGU6IChidWZmZXIsIGVuY29kaW5nLCBuZXh0KSA9PiB7XG4gICAgICByZXN1bHRCdWZmZXJzLnB1c2goYnVmZmVyKTtcbiAgICAgIHJlc3VsdEJ1ZmZlcnNTaXplICs9IGJ1ZmZlci5sZW5ndGg7XG4gICAgICBpZiAobWF4U2l6ZSA+IDAgJiYgcmVzdWx0QnVmZmVyc1NpemUgPiBtYXhTaXplKSB7XG4gICAgICAgIHJlc3VsdFdyaXRlU3RyZWFtLmVtaXQoXG4gICAgICAgICAgJ2Vycm9yJyxcbiAgICAgICAgICBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgVGhlIHNpemUgb2YgdGhlIHJlc3VsdGluZyBgICtcbiAgICAgICAgICAgICAgYGFyY2hpdmUgbXVzdCBub3QgYmUgZ3JlYXRlciB0aGFuICR7dG9SZWFkYWJsZVNpemVTdHJpbmcobWF4U2l6ZSl9YFxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIG5leHQoKTtcbiAgICB9LFxuICB9KTtcblxuICAvLyBaaXAgJ3NyY0RpcicgYW5kIHN0cmVhbSBpdCB0byB0aGUgYWJvdmUgd3JpdGFibGUgc3RyZWFtXG4gIGNvbnN0IGFyY2hpdmUgPSBhcmNoaXZlcignemlwJywge1xuICAgIHpsaWI6IHtsZXZlbH0sXG4gIH0pO1xuICBsZXQgc3JjU2l6ZSA9IG51bGw7XG4gIGNvbnN0IGJhc2U2NEVuY29kZXJTdHJlYW0gPSBlbmNvZGVUb0Jhc2U2NCA/IG5ldyBCYXNlNjRFbmNvZGUoKSA6IG51bGw7XG4gIGNvbnN0IHJlc3VsdFdyaXRlU3RyZWFtUHJvbWlzZSA9IG5ldyBCKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICByZXN1bHRXcml0ZVN0cmVhbS5vbmNlKCdlcnJvcicsIChlKSA9PiB7XG4gICAgICBpZiAoYmFzZTY0RW5jb2RlclN0cmVhbSkge1xuICAgICAgICBhcmNoaXZlLnVucGlwZShiYXNlNjRFbmNvZGVyU3RyZWFtKTtcbiAgICAgICAgYmFzZTY0RW5jb2RlclN0cmVhbS51bnBpcGUocmVzdWx0V3JpdGVTdHJlYW0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXJjaGl2ZS51bnBpcGUocmVzdWx0V3JpdGVTdHJlYW0pO1xuICAgICAgfVxuICAgICAgYXJjaGl2ZS5hYm9ydCgpO1xuICAgICAgYXJjaGl2ZS5kZXN0cm95KCk7XG4gICAgICByZWplY3QoZSk7XG4gICAgfSk7XG4gICAgcmVzdWx0V3JpdGVTdHJlYW0ub25jZSgnZmluaXNoJywgKCkgPT4ge1xuICAgICAgc3JjU2l6ZSA9IGFyY2hpdmUucG9pbnRlcigpO1xuICAgICAgcmVzb2x2ZSgpO1xuICAgIH0pO1xuICB9KTtcbiAgY29uc3QgYXJjaGl2ZVN0cmVhbVByb21pc2UgPSBuZXcgQigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgYXJjaGl2ZS5vbmNlKCdmaW5pc2gnLCByZXNvbHZlKTtcbiAgICBhcmNoaXZlLm9uY2UoJ2Vycm9yJywgKGUpID0+IHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBhcmNoaXZlICcke3NyY1BhdGh9JzogJHtlLm1lc3NhZ2V9YCkpKTtcbiAgfSk7XG4gIGNvbnN0IHRpbWVyID0gaXNNZXRlcmVkID8gbmV3IFRpbWVyKCkuc3RhcnQoKSA6IG51bGw7XG4gIGlmICgoYXdhaXQgZnMuc3RhdChzcmNQYXRoKSkuaXNEaXJlY3RvcnkoKSkge1xuICAgIGFyY2hpdmUuZGlyZWN0b3J5KHNyY1BhdGgsIGZhbHNlKTtcbiAgfSBlbHNlIHtcbiAgICBhcmNoaXZlLmZpbGUoc3JjUGF0aCwge1xuICAgICAgbmFtZTogcGF0aC5iYXNlbmFtZShzcmNQYXRoKSxcbiAgICB9KTtcbiAgfVxuICBpZiAoYmFzZTY0RW5jb2RlclN0cmVhbSkge1xuICAgIGFyY2hpdmUucGlwZShiYXNlNjRFbmNvZGVyU3RyZWFtKTtcbiAgICBiYXNlNjRFbmNvZGVyU3RyZWFtLnBpcGUocmVzdWx0V3JpdGVTdHJlYW0pO1xuICB9IGVsc2Uge1xuICAgIGFyY2hpdmUucGlwZShyZXN1bHRXcml0ZVN0cmVhbSk7XG4gIH1cbiAgYXJjaGl2ZS5maW5hbGl6ZSgpO1xuXG4gIC8vIFdhaXQgZm9yIHRoZSBzdHJlYW1zIHRvIGZpbmlzaFxuICBhd2FpdCBCLmFsbChbYXJjaGl2ZVN0cmVhbVByb21pc2UsIHJlc3VsdFdyaXRlU3RyZWFtUHJvbWlzZV0pO1xuXG4gIGlmICh0aW1lcikge1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGBaaXBwZWQgJHtlbmNvZGVUb0Jhc2U2NCA/ICdhbmQgYmFzZTY0LWVuY29kZWQgJyA6ICcnfWAgK1xuICAgICAgICBgJyR7cGF0aC5iYXNlbmFtZShzcmNQYXRoKX0nIGAgK1xuICAgICAgICAoc3JjU2l6ZSA/IGAoJHt0b1JlYWRhYmxlU2l6ZVN0cmluZyhzcmNTaXplKX0pIGAgOiAnJykgK1xuICAgICAgICBgaW4gJHt0aW1lci5nZXREdXJhdGlvbigpLmFzU2Vjb25kcy50b0ZpeGVkKDMpfXMgYCArXG4gICAgICAgIGAoY29tcHJlc3Npb24gbGV2ZWw6ICR7bGV2ZWx9KWBcbiAgICApO1xuICB9XG4gIC8vIFJldHVybiB0aGUgYXJyYXkgb2YgemlwIGJ1ZmZlcnMgY29uY2F0ZW5hdGVkIGludG8gb25lIGJ1ZmZlclxuICByZXR1cm4gQnVmZmVyLmNvbmNhdChyZXN1bHRCdWZmZXJzKTtcbn1cblxuLyoqXG4gKiBWZXJpZmllcyB3aGV0aGVyIHRoZSBnaXZlbiBmaWxlIGlzIGEgdmFsaWQgWklQIGFyY2hpdmVcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZVBhdGggLSBGdWxsIHBhdGggdG8gdGhlIGZpbGVcbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgZmlsZSBkb2VzIG5vdCBleGlzdCBvciBpcyBub3QgYSB2YWxpZCBaSVAgYXJjaGl2ZVxuICovXG5hc3luYyBmdW5jdGlvbiBhc3NlcnRWYWxpZFppcChmaWxlUGF0aCkge1xuICBpZiAoIShhd2FpdCBmcy5leGlzdHMoZmlsZVBhdGgpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVGhlIGZpbGUgYXQgJyR7ZmlsZVBhdGh9JyBkb2VzIG5vdCBleGlzdGApO1xuICB9XG5cbiAgY29uc3Qge3NpemV9ID0gYXdhaXQgZnMuc3RhdChmaWxlUGF0aCk7XG4gIGlmIChzaXplIDwgNCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVGhlIGZpbGUgYXQgJyR7ZmlsZVBhdGh9JyBpcyB0b28gc21hbGwgdG8gYmUgYSBaSVAgYXJjaGl2ZWApO1xuICB9XG4gIGNvbnN0IGZkID0gYXdhaXQgZnMub3BlbihmaWxlUGF0aCwgJ3InKTtcbiAgdHJ5IHtcbiAgICBjb25zdCBidWZmZXIgPSBCdWZmZXIuYWxsb2MoWklQX01BR0lDLmxlbmd0aCk7XG4gICAgYXdhaXQgZnMucmVhZChmZCwgYnVmZmVyLCAwLCBaSVBfTUFHSUMubGVuZ3RoLCAwKTtcbiAgICBjb25zdCBzaWduYXR1cmUgPSBidWZmZXIudG9TdHJpbmcoJ2FzY2lpJyk7XG4gICAgaWYgKHNpZ25hdHVyZSAhPT0gWklQX01BR0lDKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBUaGUgZmlsZSBzaWduYXR1cmUgJyR7c2lnbmF0dXJlfScgb2YgJyR7ZmlsZVBhdGh9JyBgICtcbiAgICAgICAgICBgaXMgbm90IGVxdWFsIHRvIHRoZSBleHBlY3RlZCBaSVAgYXJjaGl2ZSBzaWduYXR1cmUgJyR7WklQX01BR0lDfSdgXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCBmcy5jbG9zZShmZCk7XG4gIH1cbn1cblxuLyoqXG4gKiBAdHlwZWRlZiBaaXBDb21wcmVzc2lvbk9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBsZXZlbCBbOV0gLSBDb21wcmVzc2lvbiBsZXZlbCBpbiByYW5nZSAwLi45XG4gKiAoZ3JlYXRlciBudW1iZXJzIG1lYW4gYmV0dGVyIGNvbXByZXNzaW9uLCBidXQgbG9uZ2VyIHByb2Nlc3NpbmcgdGltZSlcbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIFppcFNvdXJjZU9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBwYXR0ZXJuIFsnKipcXC8qJ10gLSBHTE9CIHBhdHRlcm4gZm9yIGNvbXByZXNzaW9uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gY3dkIC0gVGhlIHNvdXJjZSByb290IGZvbGRlciAodGhlIHBhcmVudCBmb2xkZXIgb2ZcbiAqIHRoZSBkZXN0aW5hdGlvbiBmaWxlIGJ5IGRlZmF1bHQpXG4gKiBAcHJvcGVydHkge3N0cmluZ1tdfSBbaWdub3JlXSAtIFRoZSBsaXN0IG9mIGlnbm9yZWQgcGF0dGVybnNcbiAqL1xuXG4vKipcbiAqIENyZWF0ZXMgYW4gYXJjaGl2ZSBiYXNlZCBvbiB0aGUgZ2l2ZW4gZ2xvYiBwYXR0ZXJuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGRzdFBhdGggLSBUaGUgcmVzdWx0aW5nIGFyY2hpdmUgcGF0aFxuICogQHBhcmFtIHtaaXBTb3VyY2VPcHRpb25zfSBzcmMgLSBTb3VyY2Ugb3B0aW9uc1xuICogQHBhcmFtIHtaaXBDb21wcmVzc2lvbk9wdGlvbnN9IG9wdHMgLSBDb21wcmVzc2lvbiBvcHRpb25zXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlcmUgd2FzIGFuIGVycm9yIHdoaWxlIGNyZWF0aW5nIHRoZSBhcmNoaXZlXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHRvQXJjaGl2ZShcbiAgZHN0UGF0aCxcbiAgc3JjID0gLyoqIEB0eXBlIHtaaXBTb3VyY2VPcHRpb25zfSAqLyAoe30pLFxuICBvcHRzID0gLyoqIEB0eXBlIHtaaXBDb21wcmVzc2lvbk9wdGlvbnN9ICovICh7fSlcbikge1xuICBjb25zdCB7bGV2ZWwgPSA5fSA9IG9wdHM7XG4gIGNvbnN0IHtwYXR0ZXJuID0gJyoqLyonLCBjd2QgPSBwYXRoLmRpcm5hbWUoZHN0UGF0aCksIGlnbm9yZSA9IFtdfSA9IHNyYztcbiAgY29uc3QgYXJjaGl2ZSA9IGFyY2hpdmVyKCd6aXAnLCB7emxpYjoge2xldmVsfX0pO1xuICBjb25zdCBzdHJlYW0gPSBmcy5jcmVhdGVXcml0ZVN0cmVhbShkc3RQYXRoKTtcbiAgcmV0dXJuIGF3YWl0IG5ldyBCKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBhcmNoaXZlXG4gICAgICAuZ2xvYihwYXR0ZXJuLCB7XG4gICAgICAgIGN3ZCxcbiAgICAgICAgaWdub3JlLFxuICAgICAgfSlcbiAgICAgIC5vbignZXJyb3InLCByZWplY3QpXG4gICAgICAucGlwZShzdHJlYW0pO1xuICAgIHN0cmVhbVxuICAgICAgLm9uKCdlcnJvcicsIChlKSA9PiB7XG4gICAgICAgIGFyY2hpdmUudW5waXBlKHN0cmVhbSk7XG4gICAgICAgIGFyY2hpdmUuYWJvcnQoKTtcbiAgICAgICAgYXJjaGl2ZS5kZXN0cm95KCk7XG4gICAgICAgIHJlamVjdChlKTtcbiAgICAgIH0pXG4gICAgICAub24oJ2ZpbmlzaCcsIHJlc29sdmUpO1xuICAgIGFyY2hpdmUuZmluYWxpemUoKTtcbiAgfSk7XG59XG5cbi8qKlxuICogRmluZHMgYW5kIG1lbW9pemVzIHRoZSBmdWxsIHBhdGggdG8gdGhlIGdpdmVuIGV4ZWN1dGFibGUuXG4gKiBSZWplY3RzIGlmIGl0IGlzIG5vdCBmb3VuZC5cbiAqL1xuY29uc3QgZ2V0RXhlY3V0YWJsZVBhdGggPSBfLm1lbW9pemUoXG4gIC8qKlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSBGdWxsIFBhdGggdG8gdGhlIGV4ZWN1dGFibGVcbiAgICovXG4gIGFzeW5jIGZ1bmN0aW9uIGdldEV4ZWN1dGFibGVQYXRoKGJpbmFyeU5hbWUpIHtcbiAgICBjb25zdCBmdWxsUGF0aCA9IGF3YWl0IGZzLndoaWNoKGJpbmFyeU5hbWUpO1xuICAgIGxvZy5kZWJ1ZyhgRm91bmQgJyR7YmluYXJ5TmFtZX0nIGF0ICcke2Z1bGxQYXRofSdgKTtcbiAgICByZXR1cm4gZnVsbFBhdGg7XG4gIH1cbik7XG5cbmV4cG9ydCB7ZXh0cmFjdEFsbFRvLCByZWFkRW50cmllcywgdG9Jbk1lbW9yeVppcCwgX2V4dHJhY3RFbnRyeVRvLCBhc3NlcnRWYWxpZFppcCwgdG9BcmNoaXZlfTtcbmV4cG9ydCBkZWZhdWx0IHtcbiAgZXh0cmFjdEFsbFRvLFxuICByZWFkRW50cmllcyxcbiAgdG9Jbk1lbW9yeVppcCxcbiAgYXNzZXJ0VmFsaWRaaXAsXG4gIHRvQXJjaGl2ZSxcbn07XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBS0EsTUFBTUEsT0FBTyxHQUFHQyxpQkFBQSxDQUFFQyxTQUFGLENBQVlDLGNBQUEsQ0FBTUMsSUFBbEIsQ0FBaEI7O0FBSUEsTUFBTUMsUUFBUSxHQUFHSixpQkFBQSxDQUFFQyxTQUFGLENBQVlJLGVBQUEsQ0FBT0QsUUFBbkIsQ0FBakI7O0FBQ0EsTUFBTUUsU0FBUyxHQUFHLElBQWxCO0FBQ0EsTUFBTUMsSUFBSSxHQUFHLEtBQWI7QUFDQSxNQUFNQyxLQUFLLEdBQUcsS0FBZDtBQUNBLE1BQU1DLEtBQUssR0FBRyxLQUFkOztBQUdBLE1BQU1DLFlBQU4sQ0FBbUI7RUFFakJDLE9BQU87O0VBRVBDLFdBQVcsQ0FBQ0MsVUFBRCxFQUFhQyxJQUFJLEdBQUcsRUFBcEIsRUFBd0I7SUFDakMsS0FBS0MsT0FBTCxHQUFlRixVQUFmO0lBQ0EsS0FBS0MsSUFBTCxHQUFZQSxJQUFaO0lBQ0EsS0FBS0UsUUFBTCxHQUFnQixLQUFoQjtFQUNEOztFQUVEQyxlQUFlLENBQUNDLEtBQUQsRUFBUTtJQUNyQixPQUFPQyxlQUFBLENBQUVDLFFBQUYsQ0FBV0YsS0FBSyxDQUFDRyxRQUFqQixJQUNISCxLQUFLLENBQUNH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
|
|
507
|
+
//# sourceMappingURL=zip.js.map
|