@dbx-tools/lakebox 0.9.154 → 0.9.158
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/index.ts +7 -3
- package/lib/index.d.ts +7 -3
- package/lib/index.js +7 -4
- package/lib/src/_ssh_openssh.d.ts +1 -1
- package/lib/src/_ssh_openssh.js +13 -13
- package/lib/src/_ssh_ssh2.d.ts +1 -1
- package/lib/src/_ssh_ssh2.js +2 -2
- package/lib/src/key-store.js +3 -3
- package/lib/src/lifecycle.js +3 -3
- package/lib/src/rest.js +4 -4
- package/lib/src/session.d.ts +2 -3
- package/lib/src/session.js +6 -7
- package/lib/src/ssh.js +489 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -53
- package/src/_ssh_openssh.ts +13 -13
- package/src/_ssh_ssh2.ts +1 -1
- package/src/key-store.ts +2 -2
- package/src/lifecycle.ts +2 -2
- package/src/rest.ts +3 -3
- package/src/session.ts +5 -7
- package/src/{_ssh.ts → ssh.ts} +3 -3
- package/lib/src/_ssh.js +0 -489
- /package/lib/src/{_ssh.d.ts → ssh.d.ts} +0 -0
package/lib/src/_ssh.js
DELETED
|
@@ -1,489 +0,0 @@
|
|
|
1
|
-
import { PassThrough } from "node:stream";
|
|
2
|
-
import { StringDecoder } from "node:string_decoder";
|
|
3
|
-
import { errorUtils, log } from "@dbx-tools/shared-core";
|
|
4
|
-
import { createPool } from "generic-pool";
|
|
5
|
-
const logger = log.logger("lakebox:ssh-transport");
|
|
6
|
-
/** Maximum authenticated resources maintained by each SSH operation pool. */
|
|
7
|
-
export const SSH_POOL_MAX = 10;
|
|
8
|
-
/** Live SSH command that streams output and awaits to its numeric exit code. */
|
|
9
|
-
export class SshCommand {
|
|
10
|
-
command;
|
|
11
|
-
args;
|
|
12
|
-
[Symbol.toStringTag] = "SshCommand";
|
|
13
|
-
/** Live standard output decoded as UTF-8 strings. */
|
|
14
|
-
stdout;
|
|
15
|
-
/** Live standard error decoded as UTF-8 strings. */
|
|
16
|
-
stderr;
|
|
17
|
-
/** Completed result with captured output, timing, and timeout metadata. */
|
|
18
|
-
result;
|
|
19
|
-
/** Numeric exit code after completion. */
|
|
20
|
-
exitCode;
|
|
21
|
-
startedAt = Date.now();
|
|
22
|
-
stdoutStream = new PassThrough();
|
|
23
|
-
stderrStream = new PassThrough();
|
|
24
|
-
stdoutDecoder = new StringDecoder("utf8");
|
|
25
|
-
stderrDecoder = new StringDecoder("utf8");
|
|
26
|
-
abortController = new AbortController();
|
|
27
|
-
completion;
|
|
28
|
-
resolveCompletion;
|
|
29
|
-
rejectCompletion;
|
|
30
|
-
cancelBackend;
|
|
31
|
-
cancellation;
|
|
32
|
-
stdoutText = "";
|
|
33
|
-
stderrText = "";
|
|
34
|
-
settled = false;
|
|
35
|
-
timedOut = false;
|
|
36
|
-
/** Creates a command and schedules its asynchronous setup and execution. */
|
|
37
|
-
constructor(command, args, options, start) {
|
|
38
|
-
this.command = command;
|
|
39
|
-
this.args = args;
|
|
40
|
-
this.stdoutStream.setEncoding("utf8");
|
|
41
|
-
this.stderrStream.setEncoding("utf8");
|
|
42
|
-
this.stdout = this.stdoutStream;
|
|
43
|
-
this.stderr = this.stderrStream;
|
|
44
|
-
this.completion = new Promise((resolve, reject) => {
|
|
45
|
-
this.resolveCompletion = resolve;
|
|
46
|
-
this.rejectCompletion = reject;
|
|
47
|
-
});
|
|
48
|
-
this.result = this.completion.then((exitCode) => ({
|
|
49
|
-
success: exitCode === 0 && !this.timedOut,
|
|
50
|
-
exitCode,
|
|
51
|
-
stdout: this.stdoutText,
|
|
52
|
-
stderr: this.stderrText,
|
|
53
|
-
executionTimeMs: Date.now() - this.startedAt,
|
|
54
|
-
...(this.timedOut ? { timedOut: true } : {}),
|
|
55
|
-
command: this.command,
|
|
56
|
-
args: [...this.args],
|
|
57
|
-
}));
|
|
58
|
-
void this.completion.catch(() => undefined);
|
|
59
|
-
void this.result.catch(() => undefined);
|
|
60
|
-
const externalAbort = () => {
|
|
61
|
-
void this.cancel().catch(() => undefined);
|
|
62
|
-
};
|
|
63
|
-
if (options.signal?.aborted)
|
|
64
|
-
externalAbort();
|
|
65
|
-
else
|
|
66
|
-
options.signal?.addEventListener("abort", externalAbort, { once: true });
|
|
67
|
-
const timeout = setTimeout(() => {
|
|
68
|
-
this.timedOut = true;
|
|
69
|
-
void this.cancel(124).catch(() => undefined);
|
|
70
|
-
}, options.timeoutMs);
|
|
71
|
-
timeout.unref?.();
|
|
72
|
-
const cleanup = () => {
|
|
73
|
-
clearTimeout(timeout);
|
|
74
|
-
options.signal?.removeEventListener("abort", externalAbort);
|
|
75
|
-
};
|
|
76
|
-
void this.completion.then(cleanup, cleanup);
|
|
77
|
-
queueMicrotask(() => {
|
|
78
|
-
if (this.settled)
|
|
79
|
-
return;
|
|
80
|
-
void start({
|
|
81
|
-
signal: this.abortController.signal,
|
|
82
|
-
stdout: (chunk) => this.writeOutput("stdout", chunk),
|
|
83
|
-
stderr: (chunk) => this.writeOutput("stderr", chunk),
|
|
84
|
-
setCancel: (cancel) => {
|
|
85
|
-
this.cancelBackend = cancel;
|
|
86
|
-
if (this.abortController.signal.aborted) {
|
|
87
|
-
void this.invokeCancel().catch(() => undefined);
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
follow: (command) => this.follow(command),
|
|
91
|
-
}).then((exitCode) => this.finish(exitCode), (error) => this.fail(error));
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
/** Cancel the command once. Caller cancellation resolves with exit code 130. */
|
|
95
|
-
cancel(exitCode = 130) {
|
|
96
|
-
if (this.settled)
|
|
97
|
-
return this.cancellation ?? Promise.resolve();
|
|
98
|
-
if (!this.abortController.signal.aborted)
|
|
99
|
-
this.abortController.abort();
|
|
100
|
-
const cancellation = this.invokeCancel();
|
|
101
|
-
this.finish(exitCode);
|
|
102
|
-
return cancellation;
|
|
103
|
-
}
|
|
104
|
-
then(onfulfilled, onrejected) {
|
|
105
|
-
return this.completion.then(onfulfilled, onrejected);
|
|
106
|
-
}
|
|
107
|
-
catch(onrejected) {
|
|
108
|
-
return this.completion.catch(onrejected);
|
|
109
|
-
}
|
|
110
|
-
finally(onfinally) {
|
|
111
|
-
return this.completion.finally(onfinally ?? undefined);
|
|
112
|
-
}
|
|
113
|
-
invokeCancel() {
|
|
114
|
-
if (this.cancellation)
|
|
115
|
-
return this.cancellation;
|
|
116
|
-
if (!this.cancelBackend)
|
|
117
|
-
return Promise.resolve();
|
|
118
|
-
const cancelBackend = this.cancelBackend;
|
|
119
|
-
this.cancellation = Promise.resolve()
|
|
120
|
-
.then(() => cancelBackend())
|
|
121
|
-
.then(() => undefined);
|
|
122
|
-
void this.cancellation.catch(() => undefined);
|
|
123
|
-
return this.cancellation;
|
|
124
|
-
}
|
|
125
|
-
writeOutput(stream, chunk) {
|
|
126
|
-
if (this.settled)
|
|
127
|
-
return;
|
|
128
|
-
const decoder = stream === "stdout" ? this.stdoutDecoder : this.stderrDecoder;
|
|
129
|
-
const value = decoder.write(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
130
|
-
if (!value)
|
|
131
|
-
return;
|
|
132
|
-
if (stream === "stdout") {
|
|
133
|
-
this.stdoutText += value;
|
|
134
|
-
this.stdoutStream.write(value);
|
|
135
|
-
}
|
|
136
|
-
else {
|
|
137
|
-
this.stderrText += value;
|
|
138
|
-
this.stderrStream.write(value);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
async follow(command) {
|
|
142
|
-
this.cancelBackend = () => command.cancel();
|
|
143
|
-
if (this.abortController.signal.aborted) {
|
|
144
|
-
void this.invokeCancel().catch(() => undefined);
|
|
145
|
-
}
|
|
146
|
-
const stdout = this.pipe(command.stdout, (chunk) => this.writeOutput("stdout", chunk));
|
|
147
|
-
const stderr = this.pipe(command.stderr, (chunk) => this.writeOutput("stderr", chunk));
|
|
148
|
-
const exitCode = await command;
|
|
149
|
-
await Promise.all([stdout, stderr]);
|
|
150
|
-
return exitCode;
|
|
151
|
-
}
|
|
152
|
-
async pipe(stream, write) {
|
|
153
|
-
for await (const chunk of stream)
|
|
154
|
-
write(chunk);
|
|
155
|
-
}
|
|
156
|
-
finish(exitCode) {
|
|
157
|
-
if (this.settled)
|
|
158
|
-
return;
|
|
159
|
-
this.settled = true;
|
|
160
|
-
this.exitCode = exitCode;
|
|
161
|
-
this.closeOutput();
|
|
162
|
-
this.resolveCompletion(exitCode);
|
|
163
|
-
}
|
|
164
|
-
fail(error) {
|
|
165
|
-
if (this.settled)
|
|
166
|
-
return;
|
|
167
|
-
this.settled = true;
|
|
168
|
-
this.closeOutput();
|
|
169
|
-
this.rejectCompletion(error);
|
|
170
|
-
}
|
|
171
|
-
closeOutput() {
|
|
172
|
-
const stdoutRemainder = this.stdoutDecoder.end();
|
|
173
|
-
const stderrRemainder = this.stderrDecoder.end();
|
|
174
|
-
if (stdoutRemainder) {
|
|
175
|
-
this.stdoutText += stdoutRemainder;
|
|
176
|
-
this.stdoutStream.write(stdoutRemainder);
|
|
177
|
-
}
|
|
178
|
-
if (stderrRemainder) {
|
|
179
|
-
this.stderrText += stderrRemainder;
|
|
180
|
-
this.stderrStream.write(stderrRemainder);
|
|
181
|
-
}
|
|
182
|
-
this.stdoutStream.end();
|
|
183
|
-
this.stderrStream.end();
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Exclusive, single-operation SSH resource pool.
|
|
188
|
-
*
|
|
189
|
-
* The command pool keeps one authenticated resource warm. Forwarding uses a
|
|
190
|
-
* separate zero-minimum pool so long-lived WebSockets cannot consume the warm
|
|
191
|
-
* command connection. Every borrowed resource is destroyed after its command
|
|
192
|
-
* or forwarded stream because the Databricks Russh gateway may accept only one
|
|
193
|
-
* operation during a connection's lifetime.
|
|
194
|
-
*/
|
|
195
|
-
export class PooledSshTransport {
|
|
196
|
-
lifecycle;
|
|
197
|
-
commandPool;
|
|
198
|
-
forwardingPool;
|
|
199
|
-
activeResources = new Map();
|
|
200
|
-
seededResources = [];
|
|
201
|
-
lastCreateError;
|
|
202
|
-
starting;
|
|
203
|
-
closing;
|
|
204
|
-
closed = false;
|
|
205
|
-
constructor(lifecycle, options = {}) {
|
|
206
|
-
this.lifecycle = lifecycle;
|
|
207
|
-
const factory = {
|
|
208
|
-
create: async () => {
|
|
209
|
-
try {
|
|
210
|
-
const resource = this.seededResources.shift() ?? (await lifecycle.create());
|
|
211
|
-
this.lastCreateError = undefined;
|
|
212
|
-
return resource;
|
|
213
|
-
}
|
|
214
|
-
catch (error) {
|
|
215
|
-
this.lastCreateError = error;
|
|
216
|
-
throw error;
|
|
217
|
-
}
|
|
218
|
-
},
|
|
219
|
-
destroy: (resource) => lifecycle.destroy(resource),
|
|
220
|
-
validate: async (resource) => {
|
|
221
|
-
try {
|
|
222
|
-
return await lifecycle.test(resource);
|
|
223
|
-
}
|
|
224
|
-
catch {
|
|
225
|
-
return false;
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
};
|
|
229
|
-
const defaults = {
|
|
230
|
-
max: options.max ?? SSH_POOL_MAX,
|
|
231
|
-
acquireTimeoutMillis: options.acquireTimeoutMillis ?? 15_000,
|
|
232
|
-
idleTimeoutMillis: options.idleTimeoutMillis ?? 30_000,
|
|
233
|
-
evictionRunIntervalMillis: options.evictionRunIntervalMillis ?? 10_000,
|
|
234
|
-
numTestsPerEvictionRun: options.numTestsPerEvictionRun ?? 3,
|
|
235
|
-
testOnBorrow: true,
|
|
236
|
-
autostart: false,
|
|
237
|
-
};
|
|
238
|
-
this.commandPool = createPool(factory, { ...defaults, min: 1 });
|
|
239
|
-
this.forwardingPool = createPool(factory, { ...defaults, min: 0 });
|
|
240
|
-
}
|
|
241
|
-
/** Starts both pools and waits until one tested command resource is warm. */
|
|
242
|
-
start() {
|
|
243
|
-
if (this.closed)
|
|
244
|
-
return Promise.reject(new Error(`${this.kind} SSH transport is closed`));
|
|
245
|
-
if (this.starting)
|
|
246
|
-
return this.starting;
|
|
247
|
-
this.starting = this.startPools();
|
|
248
|
-
void this.starting
|
|
249
|
-
.catch(() => this.close())
|
|
250
|
-
.catch((error) => logger.warn("failed to close SSH transport after startup failure", {
|
|
251
|
-
kind: this.kind,
|
|
252
|
-
error: errorUtils.toError(error),
|
|
253
|
-
}));
|
|
254
|
-
return this.starting;
|
|
255
|
-
}
|
|
256
|
-
async startPools() {
|
|
257
|
-
if (this.closed)
|
|
258
|
-
throw new Error(`${this.kind} SSH transport is closed`);
|
|
259
|
-
const resource = await this.lifecycle.create();
|
|
260
|
-
if (this.closed) {
|
|
261
|
-
await this.lifecycle.destroy(resource);
|
|
262
|
-
throw new Error(`${this.kind} SSH transport is closed`);
|
|
263
|
-
}
|
|
264
|
-
this.seededResources.push(resource);
|
|
265
|
-
this.commandPool.start();
|
|
266
|
-
this.forwardingPool.start();
|
|
267
|
-
try {
|
|
268
|
-
const resource = await this.commandPool.acquire();
|
|
269
|
-
await this.commandPool.release(resource);
|
|
270
|
-
}
|
|
271
|
-
catch (error) {
|
|
272
|
-
throw this.lastCreateError ?? error;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
async run(script, execution) {
|
|
276
|
-
const resource = await this.acquire(this.commandPool);
|
|
277
|
-
try {
|
|
278
|
-
if (execution.signal.aborted)
|
|
279
|
-
return 130;
|
|
280
|
-
return await this.runWithResource(resource, script, execution);
|
|
281
|
-
}
|
|
282
|
-
finally {
|
|
283
|
-
await this.destroy(this.commandPool, resource);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
async connect(remoteHost, remotePort) {
|
|
287
|
-
const first = await this.acquire(this.forwardingPool);
|
|
288
|
-
try {
|
|
289
|
-
return await this.connectWithBorrowedResource(first, remoteHost, remotePort);
|
|
290
|
-
}
|
|
291
|
-
catch (error) {
|
|
292
|
-
await this.destroy(this.forwardingPool, first);
|
|
293
|
-
if (this.closed)
|
|
294
|
-
throw error;
|
|
295
|
-
}
|
|
296
|
-
const retry = await this.acquire(this.forwardingPool);
|
|
297
|
-
try {
|
|
298
|
-
return await this.connectWithBorrowedResource(retry, remoteHost, remotePort);
|
|
299
|
-
}
|
|
300
|
-
catch (error) {
|
|
301
|
-
await this.destroy(this.forwardingPool, retry);
|
|
302
|
-
throw error;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
async close() {
|
|
306
|
-
if (this.closing)
|
|
307
|
-
return this.closing;
|
|
308
|
-
this.closed = true;
|
|
309
|
-
this.closing = this.closePools();
|
|
310
|
-
return this.closing;
|
|
311
|
-
}
|
|
312
|
-
async connectWithBorrowedResource(resource, remoteHost, remotePort) {
|
|
313
|
-
const stream = await this.connectWithResource(resource, remoteHost, remotePort);
|
|
314
|
-
let disposed = false;
|
|
315
|
-
const dispose = () => {
|
|
316
|
-
if (disposed)
|
|
317
|
-
return;
|
|
318
|
-
disposed = true;
|
|
319
|
-
void this.destroy(this.forwardingPool, resource);
|
|
320
|
-
};
|
|
321
|
-
stream.once("close", dispose);
|
|
322
|
-
stream.once("error", dispose);
|
|
323
|
-
if (stream.destroyed)
|
|
324
|
-
dispose();
|
|
325
|
-
return stream;
|
|
326
|
-
}
|
|
327
|
-
async acquire(pool) {
|
|
328
|
-
if (this.closed)
|
|
329
|
-
throw new Error(`${this.kind} SSH transport is closed`);
|
|
330
|
-
let resource;
|
|
331
|
-
try {
|
|
332
|
-
resource = await pool.acquire();
|
|
333
|
-
}
|
|
334
|
-
catch (error) {
|
|
335
|
-
throw this.lastCreateError ?? error;
|
|
336
|
-
}
|
|
337
|
-
this.activeResources.set(resource, pool);
|
|
338
|
-
if (this.closed) {
|
|
339
|
-
await this.destroy(pool, resource);
|
|
340
|
-
throw new Error(`${this.kind} SSH transport is closed`);
|
|
341
|
-
}
|
|
342
|
-
return resource;
|
|
343
|
-
}
|
|
344
|
-
async destroy(pool, resource) {
|
|
345
|
-
if (this.activeResources.get(resource) !== pool)
|
|
346
|
-
return;
|
|
347
|
-
this.activeResources.delete(resource);
|
|
348
|
-
try {
|
|
349
|
-
await pool.destroy(resource);
|
|
350
|
-
}
|
|
351
|
-
catch (error) {
|
|
352
|
-
logger.warn("failed to destroy pooled SSH resource", {
|
|
353
|
-
kind: this.kind,
|
|
354
|
-
error: errorUtils.toError(error),
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
async closePools() {
|
|
359
|
-
await this.starting?.catch(() => undefined);
|
|
360
|
-
const commandDrain = this.commandPool.drain();
|
|
361
|
-
const forwardingDrain = this.forwardingPool.drain();
|
|
362
|
-
await Promise.all([...this.activeResources].map(([resource, pool]) => this.destroy(pool, resource)));
|
|
363
|
-
await Promise.all([commandDrain, forwardingDrain]);
|
|
364
|
-
await Promise.all([this.commandPool.clear(), this.forwardingPool.clear()]);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
/**
|
|
368
|
-
* Select one SSH transport from resolved policy and keep it for the session.
|
|
369
|
-
* Auto prefers native OpenSSH and otherwise selects ssh2.
|
|
370
|
-
*/
|
|
371
|
-
export async function createSshTransport(options, overrides = {}) {
|
|
372
|
-
const factories = { ...defaultSshTransportFactories, ...overrides };
|
|
373
|
-
const sshCommand = options.sshCommand ?? "ssh";
|
|
374
|
-
const transportMode = options.transport ?? "auto";
|
|
375
|
-
if (transportMode === "ssh2") {
|
|
376
|
-
return factories.createSsh2(options);
|
|
377
|
-
}
|
|
378
|
-
const openSshSupported = await factories.supportsOpenSsh(sshCommand);
|
|
379
|
-
if (transportMode === "openssh" && !openSshSupported) {
|
|
380
|
-
throw new Error("Native OpenSSH with SOCKS5 forwarding is unavailable");
|
|
381
|
-
}
|
|
382
|
-
if (openSshSupported) {
|
|
383
|
-
return factories.createOpenSsh(options, sshCommand);
|
|
384
|
-
}
|
|
385
|
-
if (transportMode !== "auto") {
|
|
386
|
-
throw new Error(`Unsupported SSH transport: ${transportMode}`);
|
|
387
|
-
}
|
|
388
|
-
return factories.createSsh2(options);
|
|
389
|
-
}
|
|
390
|
-
const defaultSshTransportFactories = {
|
|
391
|
-
supportsOpenSsh: async (command) => {
|
|
392
|
-
const { supportsNativeOpenSsh } = await import("./_ssh_openssh.js");
|
|
393
|
-
return supportsNativeOpenSsh(command);
|
|
394
|
-
},
|
|
395
|
-
createOpenSsh: async (options, command) => {
|
|
396
|
-
const { OpenSshTransport } = await import("./_ssh_openssh.js");
|
|
397
|
-
const transport = new OpenSshTransport(options, command);
|
|
398
|
-
try {
|
|
399
|
-
await transport.start();
|
|
400
|
-
return transport;
|
|
401
|
-
}
|
|
402
|
-
catch (error) {
|
|
403
|
-
await transport.close();
|
|
404
|
-
throw error;
|
|
405
|
-
}
|
|
406
|
-
},
|
|
407
|
-
createSsh2: async (options) => {
|
|
408
|
-
const { Ssh2Transport } = await import("./_ssh_ssh2.js");
|
|
409
|
-
const transport = new Ssh2Transport(options);
|
|
410
|
-
try {
|
|
411
|
-
await transport.start();
|
|
412
|
-
return transport;
|
|
413
|
-
}
|
|
414
|
-
catch (error) {
|
|
415
|
-
await transport.close();
|
|
416
|
-
throw error;
|
|
417
|
-
}
|
|
418
|
-
},
|
|
419
|
-
};
|
|
420
|
-
/** @internal Builds a remote command after clearing inherited machine credentials. */
|
|
421
|
-
export function sshCommandScript(command, args, cwd, env, identity) {
|
|
422
|
-
assertSafeSshEnvironment(env);
|
|
423
|
-
const root = identity.kind === "root";
|
|
424
|
-
const home = root ? "/root" : identity.home;
|
|
425
|
-
const name = root ? "root" : identity.name;
|
|
426
|
-
const workingDirectory = cwd ?? home;
|
|
427
|
-
const invocation = [command, ...scrubLoginShellCommand(command, args)].map(shellQuote).join(" ");
|
|
428
|
-
const environment = Object.entries({
|
|
429
|
-
HOME: home,
|
|
430
|
-
USER: name,
|
|
431
|
-
LOGNAME: name,
|
|
432
|
-
SHELL: "/bin/bash",
|
|
433
|
-
PWD: workingDirectory,
|
|
434
|
-
PATH: root
|
|
435
|
-
? "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
436
|
-
: `${home}/.local/bin:/usr/local/bin:/usr/bin:/bin`,
|
|
437
|
-
DATABRICKS_CONFIG_FILE: "/dev/null",
|
|
438
|
-
...env,
|
|
439
|
-
})
|
|
440
|
-
.map(([key, value]) => `${environmentName(key)}=${shellQuote(value)}`)
|
|
441
|
-
.join(" ");
|
|
442
|
-
const run = `cd -- ${shellQuote(workingDirectory)} && ${invocation}`;
|
|
443
|
-
const sudoArgs = root ? ["-n", "-H"] : ["-n", "-H", "-u", name];
|
|
444
|
-
const switched = ["sudo", ...sudoArgs, "--", "env", "-i"].map(shellQuote).join(" ");
|
|
445
|
-
return `${SSH_AUTH_ENVIRONMENT_SCRUB}\nexec ${switched} ${environment} '/bin/sh' '-c' ${shellQuote(run)} </dev/null`;
|
|
446
|
-
}
|
|
447
|
-
function scrubLoginShellCommand(command, args) {
|
|
448
|
-
const executable = command.split("/").at(-1);
|
|
449
|
-
if (!executable || !["sh", "bash", "zsh"].includes(executable) || args[0] !== "-lc") {
|
|
450
|
-
return args;
|
|
451
|
-
}
|
|
452
|
-
const [flags, script, ...rest] = args;
|
|
453
|
-
if (script === undefined)
|
|
454
|
-
return args;
|
|
455
|
-
return [flags, `${SSH_AUTH_ENVIRONMENT_SCRUB}\n${script}`, ...rest];
|
|
456
|
-
}
|
|
457
|
-
const SSH_AUTH_ENVIRONMENT_SCRUB = `for __dbx_tools_name in $(env | sed -n 's/^\\([A-Za-z_][A-Za-z0-9_]*\\)=.*/\\1/p'); do
|
|
458
|
-
case "$__dbx_tools_name" in
|
|
459
|
-
DATABRICKS_*|SSH_AUTH_SOCK)
|
|
460
|
-
unset "$__dbx_tools_name"
|
|
461
|
-
;;
|
|
462
|
-
esac
|
|
463
|
-
done
|
|
464
|
-
export DATABRICKS_CONFIG_FILE=/dev/null`;
|
|
465
|
-
function assertSafeSshEnvironment(env) {
|
|
466
|
-
for (const name of Object.keys(env ?? {})) {
|
|
467
|
-
if (name === "HOME" ||
|
|
468
|
-
name === "USER" ||
|
|
469
|
-
name === "LOGNAME" ||
|
|
470
|
-
name === "SHELL" ||
|
|
471
|
-
name === "PWD" ||
|
|
472
|
-
name === "PATH" ||
|
|
473
|
-
name.startsWith("SUDO_") ||
|
|
474
|
-
name.startsWith("DATABRICKS_") ||
|
|
475
|
-
name === "SSH_AUTH_SOCK") {
|
|
476
|
-
throw new Error("SSH environment overlays cannot replace the Lakebox identity or restore Databricks or SSH agent credentials.");
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
function shellQuote(value) {
|
|
481
|
-
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
482
|
-
}
|
|
483
|
-
function environmentName(value) {
|
|
484
|
-
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
|
|
485
|
-
throw new Error(`Invalid SSH environment variable name: ${value}`);
|
|
486
|
-
}
|
|
487
|
-
return value;
|
|
488
|
-
}
|
|
489
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX3NzaC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9fc3NoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxXQUFXLEVBQThCLE1BQU0sYUFBYSxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRXpELE9BQU8sRUFBRSxVQUFVLEVBQXlDLE1BQU0sY0FBYyxDQUFDO0FBSWpGLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsdUJBQXVCLENBQUMsQ0FBQztBQUNuRCw2RUFBNkU7QUFDN0UsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLEVBQUUsQ0FBQztBQWlCL0IsZ0ZBQWdGO0FBQ2hGLE1BQU0sT0FBTyxVQUFVO0lBNkJWO0lBQ0E7SUE3QkYsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsWUFBWSxDQUFDO0lBQzdDLHFEQUFxRDtJQUM1QyxNQUFNLENBQW1DO0lBQ2xELG9EQUFvRDtJQUMzQyxNQUFNLENBQW1DO0lBQ2xELDJFQUEyRTtJQUNsRSxNQUFNLENBQWdDO0lBQy9DLDBDQUEwQztJQUMxQyxRQUFRLENBQXFCO0lBRVosU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUN2QixZQUFZLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztJQUNqQyxZQUFZLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztJQUNqQyxhQUFhLEdBQUcsSUFBSSxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDMUMsYUFBYSxHQUFHLElBQUksYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzFDLGVBQWUsR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO0lBQ3hDLFVBQVUsQ0FBa0I7SUFDckMsaUJBQWlCLENBQThCO0lBQy9DLGdCQUFnQixDQUE0QjtJ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LEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0FBQ3RFLENBQUM7QUFFRCxNQUFNLDBCQUEwQixHQUFHOzs7Ozs7O3dDQU9LLENBQUM7QUFFekMsU0FBUyx3QkFBd0IsQ0FBQyxHQUFpRDtJQUNqRixLQUFLLE1BQU0sSUFBSSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUFDMUMsSUFDRSxJQUFJLEtBQUssTUFBTTtZQUNmLElBQUksS0FBSyxNQUFNO1lBQ2YsSUFBSSxLQUFLLFNBQVM7WUFDbEIsSUFBSSxLQUFLLE9BQU87WUFDaEIsSUFBSSxLQUFLLEtBQUs7WUFDZCxJQUFJLEtBQUssTUFBTTtZQUNmLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDO1lBQ3hCLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDO1lBQzlCLElBQUksS0FBSyxlQUFlLEVBQ3hCLENBQUM7WUFDRCxNQUFNLElBQUksS0FBSyxDQUNiLDhHQUE4RyxDQUMvRyxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsS0FBYTtJQUMvQixPQUFPLElBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQztBQUMvQyxDQUFDO0FBRUQsU0FBUyxlQUFlLENBQUMsS0FBYTtJQUNwQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDNUMsTUFBTSxJQUFJLEtBQUssQ0FBQywwQ0FBMEMsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGFzc1Rocm91Z2gsIHR5cGUgRHVwbGV4LCB0eXBlIFJlYWRhYmxlIH0gZnJvbSBcIm5vZGU6c3RyZWFtXCI7XG5pbXBvcnQgeyBTdHJpbmdEZWNvZGVyIH0gZnJvbSBcIm5vZGU6c3RyaW5nX2RlY29kZXJcIjtcbmltcG9ydCB7IGVycm9yVXRpbHMsIGxvZyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgdHlwZSB7IExha2Vib3hDb21tYW5kUmVzdWx0IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWxha2Vib3hcIjtcbmltcG9ydCB7IGNyZWF0ZVBvb2wsIHR5cGUgRmFjdG9yeSwgdHlwZSBPcHRpb25zLCB0eXBlIFBvb2wgfSBmcm9tIFwiZ2VuZXJpYy1wb29sXCI7XG5pbXBvcnQgdHlwZSB7IENsaWVudCBhcyBTc2gyQ2xpZW50IH0gZnJvbSBcInNzaDJcIjtcbmltcG9ydCB0eXBlIHsgU3NoMlBhdGNoTW9kZSwgU3NoVHJhbnNwb3J0TW9kZSB9IGZyb20gXCIuL3RyYW5zcG9ydC50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwibGFrZWJveDpzc2gtdHJhbnNwb3J0XCIpO1xuLyoqIE1heGltdW0gYXV0aGVudGljYXRlZCByZXNvdXJjZXMgbWFpbnRhaW5lZCBieSBlYWNoIFNTSCBvcGVyYXRpb24gcG9vbC4gKi9cbmV4cG9ydCBjb25zdCBTU0hfUE9PTF9NQVggPSAxMDtcblxuLyoqIE9uZSBjb21tYW5kIGV4ZWN1dGlvbiByZXF1ZXN0IGFmdGVyIHRoZSByZW1vdGUgc2hlbGwgc2NyaXB0IGlzIGFzc2VtYmxlZC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3NoRXhlY3V0aW9uT3B0aW9ucyB7XG4gIHRpbWVvdXRNczogbnVtYmVyO1xuICBzaWduYWw/OiBBYm9ydFNpZ25hbDtcbn1cblxuLyoqIFRyYW5zcG9ydCBjYWxsYmFja3Mgb3duZWQgYnkgb25lIGxpdmUgU1NIIGNvbW1hbmQuICovXG5leHBvcnQgaW50ZXJmYWNlIFNzaENvbW1hbmRFeGVjdXRpb24ge1xuICByZWFkb25seSBzaWduYWw6IEFib3J0U2lnbmFsO1xuICBzdGRvdXQoY2h1bms6IEJ1ZmZlciB8IHN0cmluZyk6IHZvaWQ7XG4gIHN0ZGVycihjaHVuazogQnVmZmVyIHwgc3RyaW5nKTogdm9pZDtcbiAgc2V0Q2FuY2VsKGNhbmNlbDogKCkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD4pOiB2b2lkO1xuICBmb2xsb3coY29tbWFuZDogU3NoQ29tbWFuZCk6IFByb21pc2U8bnVtYmVyPjtcbn1cblxuLyoqIExpdmUgU1NIIGNvbW1hbmQgdGhhdCBzdHJlYW1zIG91dHB1dCBhbmQgYXdhaXRzIHRvIGl0cyBudW1lcmljIGV4aXQgY29kZS4gKi9cbmV4cG9ydCBjbGFzcyBTc2hDb21tYW5kIGltcGxlbWVudHMgUHJvbWlzZTxudW1iZXI+IHtcbiAgcmVhZG9ubHkgW1N5bWJvbC50b1N0cmluZ1RhZ10gPSBcIlNzaENvbW1hbmRcIjtcbiAgLyoqIExpdmUgc3RhbmRhcmQgb3V0cHV0IGRlY29kZWQgYXMgVVRGLTggc3RyaW5ncy4gKi9cbiAgcmVhZG9ubHkgc3Rkb3V0OiBSZWFkYWJsZSAmIEFzeW5jSXRlcmFibGU8c3RyaW5nPjtcbiAgLyoqIExpdmUgc3RhbmRhcmQgZXJyb3IgZGVjb2RlZCBhcyBVVEYtOCBzdHJpbmdzLiAqL1xuICByZWFkb25seSBzdGRlcnI6IFJlYWRhYmxlICYgQXN5bmNJdGVyYWJsZTxzdHJpbmc+O1xuICAvKiogQ29tcGxldGVkIHJlc3VsdCB3aXRoIGNhcHR1cmVkIG91dHB1dCwgdGltaW5nLCBhbmQgdGltZW91dCBtZXRhZGF0YS4gKi9cbiAgcmVhZG9ubHkgcmVzdWx0OiBQcm9taXNlPExha2Vib3hDb21tYW5kUmVzdWx0PjtcbiAgLyoqIE51bWVyaWMgZXhpdCBjb2RlIGFmdGVyIGNvbXBsZXRpb24uICovXG4gIGV4aXRDb2RlOiBudW1iZXIgfCB1bmRlZmluZWQ7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBzdGFydGVkQXQgPSBEYXRlLm5vdygpO1xuICBwcml2YXRlIHJlYWRvbmx5IHN0ZG91dFN0cmVhbSA9IG5ldyBQYXNzVGhyb3VnaCgpO1xuICBwcml2YXRlIHJlYWRvbmx5IHN0ZGVyclN0cmVhbSA9IG5ldyBQYXNzVGhyb3VnaCgpO1xuICBwcml2YXRlIHJlYWRvbmx5IHN0ZG91dERlY29kZXIgPSBuZXcgU3RyaW5nRGVjb2RlcihcInV0ZjhcIik7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3RkZXJyRGVjb2RlciA9IG5ldyBTdHJpbmdEZWNvZGVyKFwidXRmOFwiKTtcbiAgcHJpdmF0ZSByZWFkb25seSBhYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgY29tcGxldGlvbjogUHJvbWlzZTxudW1iZXI+O1xuICBwcml2YXRlIHJlc29sdmVDb21wbGV0aW9uITogKGV4aXRDb2RlOiBudW1iZXIpID0+IHZvaWQ7XG4gIHByaXZhdGUgcmVqZWN0Q29tcGxldGlvbiE6IChlcnJvcjogdW5rbm93bikgPT4gdm9pZDtcbiAgcHJpdmF0ZSBjYW5jZWxCYWNrZW5kPzogKCkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD47XG4gIHByaXZhdGUgY2FuY2VsbGF0aW9uPzogUHJvbWlzZTx2b2lkPjtcbiAgcHJpdmF0ZSBzdGRvdXRUZXh0ID0gXCJcIjtcbiAgcHJpdmF0ZSBzdGRlcnJUZXh0ID0gXCJcIjtcbiAgcHJpdmF0ZSBzZXR0bGVkID0gZmFsc2U7XG4gIHByaXZhdGUgdGltZWRPdXQgPSBmYWxzZTtcblxuICAvKiogQ3JlYXRlcyBhIGNvbW1hbmQgYW5kIHNjaGVkdWxlcyBpdHMgYXN5bmNocm9ub3VzIHNldHVwIGFuZCBleGVjdXRpb24uICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIHJlYWRvbmx5IGNvbW1hbmQ6IHN0cmluZyxcbiAgICByZWFkb25seSBhcmdzOiByZWFkb25seSBzdHJpbmdbXSxcbiAgICBvcHRpb25zOiBTc2hFeGVjdXRpb25PcHRpb25zLFxuICAgIHN0YXJ0OiAoZXhlY3V0aW9uOiBTc2hDb21tYW5kRXhlY3V0aW9uKSA9PiBQcm9taXNlPG51bWJlcj4sXG4gICkge1xuICAgIHRoaXMuc3Rkb3V0U3RyZWFtLnNldEVuY29kaW5nKFwidXRmOFwiKTtcbiAgICB0aGlzLnN0ZGVyclN0cmVhbS5zZXRFbmNvZGluZyhcInV0ZjhcIik7XG4gICAgdGhpcy5zdGRvdXQgPSB0aGlzLnN0ZG91dFN0cmVhbSBhcyBSZWFkYWJsZSAmIEFzeW5jSXRlcmFibGU8c3RyaW5nPjtcbiAgICB0aGlzLnN0ZGVyciA9IHRoaXMuc3RkZXJyU3RyZWFtIGFzIFJlYWRhYmxlICYgQXN5bmNJdGVyYWJsZTxzdHJpbmc+O1xuICAgIHRoaXMuY29tcGxldGlvbiA9IG5ldyBQcm9taXNlPG51bWJlcj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5yZXNvbHZlQ29tcGxldGlvbiA9IHJlc29sdmU7XG4gICAgICB0aGlzLnJlamVjdENvbXBsZXRpb24gPSByZWplY3Q7XG4gICAgfSk7XG4gICAgdGhpcy5yZXN1bHQgPSB0aGlzLmNvbXBsZXRpb24udGhlbigoZXhpdENvZGUpID0+ICh7XG4gICAgICBzdWNjZXNzOiBleGl0Q29kZSA9PT0gMCAmJiAhdGhpcy50aW1lZE91dCxcbiAgICAgIGV4aXRDb2RlLFxuICAgICAgc3Rkb3V0OiB0aGlzLnN0ZG91dFRleHQsXG4gICAgICBzdGRlcnI6IHRoaXMuc3RkZXJyVGV4dCxcbiAgICAgIGV4ZWN1dGlvblRpbWVNczogRGF0ZS5ub3coKSAtIHRoaXMuc3RhcnRlZEF0LFxuICAgICAgLi4uKHRoaXMudGltZWRPdXQgPyB7IHRpbWVkT3V0OiB0cnVlIH0gOiB7fSksXG4gICAgICBjb21tYW5kOiB0aGlzLmNvbW1hbmQsXG4gICAgICBhcmdzOiBbLi4udGhpcy5hcmdzXSxcbiAgICB9KSk7XG4gICAgdm9pZCB0aGlzLmNvbXBsZXRpb24uY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB2b2lkIHRoaXMucmVzdWx0LmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG5cbiAgICBjb25zdCBleHRlcm5hbEFib3J0ID0gKCkgPT4ge1xuICAgICAgdm9pZCB0aGlzLmNhbmNlbCgpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfTtcbiAgICBpZiAob3B0aW9ucy5zaWduYWw/LmFib3J0ZWQpIGV4dGVybmFsQWJvcnQoKTtcbiAgICBlbHNlIG9wdGlvbnMuc2lnbmFsPy5hZGRFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgZXh0ZXJuYWxBYm9ydCwgeyBvbmNlOiB0cnVlIH0pO1xuICAgIGNvbnN0IHRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMudGltZWRPdXQgPSB0cnVlO1xuICAgICAgdm9pZCB0aGlzLmNhbmNlbCgxMjQpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfSwgb3B0aW9ucy50aW1lb3V0TXMpO1xuICAgIHRpbWVvdXQudW5yZWY/LigpO1xuICAgIGNvbnN0IGNsZWFudXAgPSAoKSA9PiB7XG4gICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICBvcHRpb25zLnNpZ25hbD8ucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsIGV4dGVybmFsQWJvcnQpO1xuICAgIH07XG4gICAgdm9pZCB0aGlzLmNvbXBsZXRpb24udGhlbihjbGVhbnVwLCBjbGVhbnVwKTtcblxuICAgIHF1ZXVlTWljcm90YXNrKCgpID0+IHtcbiAgICAgIGlmICh0aGlzLnNldHRsZWQpIHJldHVybjtcbiAgICAgIHZvaWQgc3RhcnQoe1xuICAgICAgICBzaWduYWw6IHRoaXMuYWJvcnRDb250cm9sbGVyLnNpZ25hbCxcbiAgICAgICAgc3Rkb3V0OiAoY2h1bmspID0+IHRoaXMud3JpdGVPdXRwdXQoXCJzdGRvdXRcIiwgY2h1bmspLFxuICAgICAgICBzdGRlcnI6IChjaHVuaykgPT4gdGhpcy53cml0ZU91dHB1dChcInN0ZGVyclwiLCBjaHVuayksXG4gICAgICAgIHNldENhbmNlbDogKGNhbmNlbCkgPT4ge1xuICAgICAgICAgIHRoaXMuY2FuY2VsQmFja2VuZCA9IGNhbmNlbDtcbiAgICAgICAgICBpZiAodGhpcy5hYm9ydENvbnRyb2xsZXIuc2lnbmFsLmFib3J0ZWQpIHtcbiAgICAgICAgICAgIHZvaWQgdGhpcy5pbnZva2VDYW5jZWwoKS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZm9sbG93OiAoY29tbWFuZCkgPT4gdGhpcy5mb2xsb3coY29tbWFuZCksXG4gICAgICB9KS50aGVuKFxuICAgICAgICAoZXhpdENvZGUpID0+IHRoaXMuZmluaXNoKGV4aXRDb2RlKSxcbiAgICAgICAgKGVycm9yKSA9PiB0aGlzLmZhaWwoZXJyb3IpLFxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBDYW5jZWwgdGhlIGNvbW1hbmQgb25jZS4gQ2FsbGVyIGNhbmNlbGxhdGlvbiByZXNvbHZlcyB3aXRoIGV4aXQgY29kZSAxMzAuICovXG4gIGNhbmNlbChleGl0Q29kZSA9IDEzMCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLnNldHRsZWQpIHJldHVybiB0aGlzLmNhbmNlbGxhdGlvbiA/PyBQcm9taXNlLnJlc29sdmUoKTtcbiAgICBpZiAoIXRoaXMuYWJvcnRDb250cm9sbGVyLnNpZ25hbC5hYm9ydGVkKSB0aGlzLmFib3J0Q29udHJvbGxlci5hYm9ydCgpO1xuICAgIGNvbnN0IGNhbmNlbGxhdGlvbiA9IHRoaXMuaW52b2tlQ2FuY2VsKCk7XG4gICAgdGhpcy5maW5pc2goZXhpdENvZGUpO1xuICAgIHJldHVybiBjYW5jZWxsYXRpb247XG4gIH1cblxuICB0aGVuPFRSZXN1bHQxID0gbnVtYmVyLCBUUmVzdWx0MiA9IG5ldmVyPihcbiAgICBvbmZ1bGZpbGxlZD86ICgodmFsdWU6IG51bWJlcikgPT4gVFJlc3VsdDEgfCBQcm9taXNlTGlrZTxUUmVzdWx0MT4pIHwgbnVsbCxcbiAgICBvbnJlamVjdGVkPzogKChyZWFzb246IHVua25vd24pID0+IFRSZXN1bHQyIHwgUHJvbWlzZUxpa2U8VFJlc3VsdDI+KSB8IG51bGwsXG4gICk6IFByb21pc2U8VFJlc3VsdDEgfCBUUmVzdWx0Mj4ge1xuICAgIHJldHVybiB0aGlzLmNvbXBsZXRpb24udGhlbihvbmZ1bGZpbGxlZCwgb25yZWplY3RlZCk7XG4gIH1cblxuICBjYXRjaDxUUmVzdWx0ID0gbmV2ZXI+KFxuICAgIG9ucmVqZWN0ZWQ/OiAoKHJlYXNvbjogdW5rbm93bikgPT4gVFJlc3VsdCB8IFByb21pc2VMaWtlPFRSZXN1bHQ+KSB8IG51bGwsXG4gICk6IFByb21pc2U8bnVtYmVyIHwgVFJlc3VsdD4ge1xuICAgIHJldHVybiB0aGlzLmNvbXBsZXRpb24uY2F0Y2gob25yZWplY3RlZCk7XG4gIH1cblxuICBmaW5hbGx5KG9uZmluYWxseT86ICgoKSA9PiB2b2lkKSB8IG51bGwpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIHJldHVybiB0aGlzLmNvbXBsZXRpb24uZmluYWxseShvbmZpbmFsbHkgPz8gdW5kZWZpbmVkKTtcbiAgfVxuXG4gIHByaXZhdGUgaW52b2tlQ2FuY2VsKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmNhbmNlbGxhdGlvbikgcmV0dXJuIHRoaXMuY2FuY2VsbGF0aW9uO1xuICAgIGlmICghdGhpcy5jYW5jZWxCYWNrZW5kKSByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgY29uc3QgY2FuY2VsQmFja2VuZCA9IHRoaXMuY2FuY2VsQmFja2VuZDtcbiAgICB0aGlzLmNhbmNlbGxhdGlvbiA9IFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAudGhlbigoKSA9PiBjYW5jZWxCYWNrZW5kKCkpXG4gICAgICAudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuICAgIHZvaWQgdGhpcy5jYW5jZWxsYXRpb24uY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICByZXR1cm4gdGhpcy5jYW5jZWxsYXRpb247XG4gIH1cblxuICBwcml2YXRlIHdyaXRlT3V0cHV0KHN0cmVhbTogXCJzdGRvdXRcIiB8IFwic3RkZXJyXCIsIGNodW5rOiBCdWZmZXIgfCBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zZXR0bGVkKSByZXR1cm47XG4gICAgY29uc3QgZGVjb2RlciA9IHN0cmVhbSA9PT0gXCJzdGRvdXRcIiA/IHRoaXMuc3Rkb3V0RGVjb2RlciA6IHRoaXMuc3RkZXJyRGVjb2RlcjtcbiAgICBjb25zdCB2YWx1ZSA9IGRlY29kZXIud3JpdGUodHlwZW9mIGNodW5rID09PSBcInN0cmluZ1wiID8gQnVmZmVyLmZyb20oY2h1bmspIDogY2h1bmspO1xuICAgIGlmICghdmFsdWUpIHJldHVybjtcbiAgICBpZiAoc3RyZWFtID09PSBcInN0ZG91dFwiKSB7XG4gICAgICB0aGlzLnN0ZG91dFRleHQgKz0gdmFsdWU7XG4gICAgICB0aGlzLnN0ZG91dFN0cmVhbS53cml0ZSh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc3RkZXJyVGV4dCArPSB2YWx1ZTtcbiAgICAgIHRoaXMuc3RkZXJyU3RyZWFtLndyaXRlKHZhbHVlKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGZvbGxvdyhjb21tYW5kOiBTc2hDb21tYW5kKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICB0aGlzLmNhbmNlbEJhY2tlbmQgPSAoKSA9PiBjb21tYW5kLmNhbmNlbCgpO1xuICAgIGlmICh0aGlzLmFib3J0Q29udHJvbGxlci5zaWduYWwuYWJvcnRlZCkge1xuICAgICAgdm9pZCB0aGlzLmludm9rZUNhbmNlbCgpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIGNvbnN0IHN0ZG91dCA9IHRoaXMucGlwZShjb21tYW5kLnN0ZG91dCwgKGNodW5rKSA9PiB0aGlzLndyaXRlT3V0cHV0KFwic3Rkb3V0XCIsIGNodW5rKSk7XG4gICAgY29uc3Qgc3RkZXJyID0gdGhpcy5waXBlKGNvbW1hbmQuc3RkZXJyLCAoY2h1bmspID0+IHRoaXMud3JpdGVPdXRwdXQoXCJzdGRlcnJcIiwgY2h1bmspKTtcbiAgICBjb25zdCBleGl0Q29kZSA9IGF3YWl0IGNvbW1hbmQ7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoW3N0ZG91dCwgc3RkZXJyXSk7XG4gICAgcmV0dXJuIGV4aXRDb2RlO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBwaXBlKHN0cmVhbTogQXN5bmNJdGVyYWJsZTxzdHJpbmc+LCB3cml0ZTogKGNodW5rOiBzdHJpbmcpID0+IHZvaWQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBmb3IgYXdhaXQgKGNvbnN0IGNodW5rIG9mIHN0cmVhbSkgd3JpdGUoY2h1bmspO1xuICB9XG5cbiAgcHJpdmF0ZSBmaW5pc2goZXhpdENvZGU6IG51bWJlcik6IHZvaWQge1xuICAgIGlmICh0aGlzLnNldHRsZWQpIHJldHVybjtcbiAgICB0aGlzLnNldHRsZWQgPSB0cnVlO1xuICAgIHRoaXMuZXhpdENvZGUgPSBleGl0Q29kZTtcbiAgICB0aGlzLmNsb3NlT3V0cHV0KCk7XG4gICAgdGhpcy5yZXNvbHZlQ29tcGxldGlvbihleGl0Q29kZSk7XG4gIH1cblxuICBwcml2YXRlIGZhaWwoZXJyb3I6IHVua25vd24pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zZXR0bGVkKSByZXR1cm47XG4gICAgdGhpcy5zZXR0bGVkID0gdHJ1ZTtcbiAgICB0aGlzLmNsb3NlT3V0cHV0KCk7XG4gICAgdGhpcy5yZWplY3RDb21wbGV0aW9uKGVycm9yKTtcbiAgfVxuXG4gIHByaXZhdGUgY2xvc2VPdXRwdXQoKTogdm9pZCB7XG4gICAgY29uc3Qgc3Rkb3V0UmVtYWluZGVyID0gdGhpcy5zdGRvdXREZWNvZGVyLmVuZCgpO1xuICAgIGNvbnN0IHN0ZGVyclJlbWFpbmRlciA9IHRoaXMuc3RkZXJyRGVjb2Rlci5lbmQoKTtcbiAgICBpZiAoc3Rkb3V0UmVtYWluZGVyKSB7XG4gICAgICB0aGlzLnN0ZG91dFRleHQgKz0gc3Rkb3V0UmVtYWluZGVyO1xuICAgICAgdGhpcy5zdGRvdXRTdHJlYW0ud3JpdGUoc3Rkb3V0UmVtYWluZGVyKTtcbiAgICB9XG4gICAgaWYgKHN0ZGVyclJlbWFpbmRlcikge1xuICAgICAgdGhpcy5zdGRlcnJUZXh0ICs9IHN0ZGVyclJlbWFpbmRlcjtcbiAgICAgIHRoaXMuc3RkZXJyU3RyZWFtLndyaXRlKHN0ZGVyclJlbWFpbmRlcik7XG4gICAgfVxuICAgIHRoaXMuc3Rkb3V0U3RyZWFtLmVuZCgpO1xuICAgIHRoaXMuc3RkZXJyU3RyZWFtLmVuZCgpO1xuICB9XG59XG5cbi8qKiBDb25uZWN0aW9uIGRldGFpbHMgc2hhcmVkIGJ5IG5hdGl2ZSBPcGVuU1NIIGFuZCB0aGUgZ3VhcmRlZCBzc2gyIGZhbGxiYWNrLiAqL1xuZXhwb3J0IGludGVyZmFjZSBTc2hUcmFuc3BvcnRPcHRpb25zIHtcbiAgaG9zdDogc3RyaW5nO1xuICBjb25uZWN0SG9zdDogc3RyaW5nO1xuICBwb3J0OiBudW1iZXI7XG4gIHVzZXJuYW1lOiBzdHJpbmc7XG4gIHByaXZhdGVLZXlQYXRoOiBzdHJpbmc7XG4gIGtub3duSG9zdHNQYXRoOiBzdHJpbmc7XG4gIGNvbm5lY3RUaW1lb3V0TXM6IG51bWJlcjtcbiAgc3NoMkNsaWVudDogU3NoMkNsaWVudDtcbiAgY3JlYXRlU3NoMkNvbW1hbmRDbGllbnQ6ICgpID0+IFByb21pc2U8U3NoMkNsaWVudD47XG4gIHRyYW5zcG9ydD86IFNzaFRyYW5zcG9ydE1vZGU7XG4gIHNzaDJQYXRjaD86IFNzaDJQYXRjaE1vZGU7XG4gIHNzaENvbW1hbmQ/OiBzdHJpbmc7XG59XG5cbi8qKiBTZWxlY3RlZCBjb21tYW5kIGFuZCByZW1vdGUgVENQIHRyYW5zcG9ydCBmb3Igb25lIHZlcmlmaWVkIFNTSCBnYXRld2F5LiAqL1xuZXhwb3J0IGludGVyZmFjZSBTc2hUcmFuc3BvcnQge1xuICByZWFkb25seSBraW5kOiBcIm9wZW5zc2hcIiB8IFwic3NoMlwiO1xuICBydW4oc2NyaXB0OiBzdHJpbmcsIGV4ZWN1dGlvbjogU3NoQ29tbWFuZEV4ZWN1dGlvbik6IFByb21pc2U8bnVtYmVyPjtcbiAgY29ubmVjdChyZW1vdGVIb3N0OiBzdHJpbmcsIHJlbW90ZVBvcnQ6IG51bWJlcik6IFByb21pc2U8RHVwbGV4PjtcbiAgY2xvc2UoKTogUHJvbWlzZTx2b2lkPjtcbn1cblxuLyoqIEFzeW5jIGxpZmVjeWNsZSB1c2VkIGJ5IGJvdGggbmF0aXZlIE9wZW5TU0ggYW5kIHNzaDIgY29ubmVjdGlvbiBwb29scy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3NoUmVzb3VyY2VMaWZlY3ljbGU8VD4ge1xuICBjcmVhdGUoKTogUHJvbWlzZTxUPjtcbiAgZGVzdHJveShyZXNvdXJjZTogVCk6IFByb21pc2U8dm9pZD47XG4gIHRlc3QocmVzb3VyY2U6IFQpOiBQcm9taXNlPGJvb2xlYW4+O1xufVxuXG4vKiogT3B0aW9uYWwgcG9vbCBvdmVycmlkZXMgdXNlZCBieSB0cmFuc3BvcnQgdGVzdHMgYW5kIGNvbnN0cmFpbmVkIHJ1bnRpbWVzLiAqL1xuZXhwb3J0IHR5cGUgU3NoUG9vbE9wdGlvbnMgPSBQaWNrPFxuICBPcHRpb25zLFxuICB8IFwibWF4XCJcbiAgfCBcImFjcXVpcmVUaW1lb3V0TWlsbGlzXCJcbiAgfCBcImlkbGVUaW1lb3V0TWlsbGlzXCJcbiAgfCBcImV2aWN0aW9uUnVuSW50ZXJ2YWxNaWxsaXNcIlxuICB8IFwibnVtVGVzdHNQZXJFdmljdGlvblJ1blwiXG4+O1xuXG4vKipcbiAqIEV4Y2x1c2l2ZSwgc2luZ2xlLW9wZXJhdGlvbiBTU0ggcmVzb3VyY2UgcG9vbC5cbiAqXG4gKiBUaGUgY29tbWFuZCBwb29sIGtlZXBzIG9uZSBhdXRoZW50aWNhdGVkIHJlc291cmNlIHdhcm0uIEZvcndhcmRpbmcgdXNlcyBhXG4gKiBzZXBhcmF0ZSB6ZXJvLW1pbmltdW0gcG9vbCBzbyBsb25nLWxpdmVkIFdlYlNvY2tldHMgY2Fubm90IGNvbnN1bWUgdGhlIHdhcm1cbiAqIGNvbW1hbmQgY29ubmVjdGlvbi4gRXZlcnkgYm9ycm93ZWQgcmVzb3VyY2UgaXMgZGVzdHJveWVkIGFmdGVyIGl0cyBjb21tYW5kXG4gKiBvciBmb3J3YXJkZWQgc3RyZWFtIGJlY2F1c2UgdGhlIERhdGFicmlja3MgUnVzc2ggZ2F0ZXdheSBtYXkgYWNjZXB0IG9ubHkgb25lXG4gKiBvcGVyYXRpb24gZHVyaW5nIGEgY29ubmVjdGlvbidzIGxpZmV0aW1lLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgUG9vbGVkU3NoVHJhbnNwb3J0PFQ+IGltcGxlbWVudHMgU3NoVHJhbnNwb3J0IHtcbiAgYWJzdHJhY3QgcmVhZG9ubHkga2luZDogXCJvcGVuc3NoXCIgfCBcInNzaDJcIjtcblxuICBwcml2YXRlIHJlYWRvbmx5IGNvbW1hbmRQb29sOiBQb29sPFQ+O1xuICBwcml2YXRlIHJlYWRvbmx5IGZvcndhcmRpbmdQb29sOiBQb29sPFQ+O1xuICBwcml2YXRlIHJlYWRvbmx5IGFjdGl2ZVJlc291cmNlcyA9IG5ldyBNYXA8VCwgUG9vbDxUPj4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBzZWVkZWRSZXNvdXJjZXM6IFRbXSA9IFtdO1xuICBwcml2YXRlIGxhc3RDcmVhdGVFcnJvcjogdW5rbm93bjtcbiAgcHJpdmF0ZSBzdGFydGluZz86IFByb21pc2U8dm9pZD47XG4gIHByaXZhdGUgY2xvc2luZz86IFByb21pc2U8dm9pZD47XG4gIHByaXZhdGUgY2xvc2VkID0gZmFsc2U7XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgbGlmZWN5Y2xlOiBTc2hSZXNvdXJjZUxpZmVjeWNsZTxUPixcbiAgICBvcHRpb25zOiBTc2hQb29sT3B0aW9ucyA9IHt9LFxuICApIHtcbiAgICBjb25zdCBmYWN0b3J5OiBGYWN0b3J5PFQ+ID0ge1xuICAgICAgY3JlYXRlOiBhc3luYyAoKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVzb3VyY2UgPSB0aGlzLnNlZWRlZFJlc291cmNlcy5zaGlmdCgpID8/IChhd2FpdCBsaWZlY3ljbGUuY3JlYXRlKCkpO1xuICAgICAgICAgIHRoaXMubGFzdENyZWF0ZUVycm9yID0gdW5kZWZpbmVkO1xuICAgICAgICAgIHJldHVybiByZXNvdXJjZTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICB0aGlzLmxhc3RDcmVhdGVFcnJvciA9IGVycm9yO1xuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgZGVzdHJveTogKHJlc291cmNlKSA9PiBsaWZlY3ljbGUuZGVzdHJveShyZXNvdXJjZSksXG4gICAgICB2YWxpZGF0ZTogYXN5bmMgKHJlc291cmNlKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IGxpZmVjeWNsZS50ZXN0KHJlc291cmNlKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH07XG4gICAgY29uc3QgZGVmYXVsdHM6IE9wdGlvbnMgPSB7XG4gICAgICBtYXg6IG9wdGlvbnMubWF4ID8/IFNTSF9QT09MX01BWCxcbiAgICAgIGFjcXVpcmVUaW1lb3V0TWlsbGlzOiBvcHRpb25zLmFjcXVpcmVUaW1lb3V0TWlsbGlzID8/IDE1XzAwMCxcbiAgICAgIGlkbGVUaW1lb3V0TWlsbGlzOiBvcHRpb25zLmlkbGVUaW1lb3V0TWlsbGlzID8/IDMwXzAwMCxcbiAgICAgIGV2aWN0aW9uUnVuSW50ZXJ2YWxNaWxsaXM6IG9wdGlvbnMuZXZpY3Rpb25SdW5JbnRlcnZhbE1pbGxpcyA/PyAxMF8wMDAsXG4gICAgICBudW1UZXN0c1BlckV2aWN0aW9uUnVuOiBvcHRpb25zLm51bVRlc3RzUGVyRXZpY3Rpb25SdW4gPz8gMyxcbiAgICAgIHRlc3RPbkJvcnJvdzogdHJ1ZSxcbiAgICAgIGF1dG9zdGFydDogZmFsc2UsXG4gICAgfTtcbiAgICB0aGlzLmNvbW1hbmRQb29sID0gY3JlYXRlUG9vbChmYWN0b3J5LCB7IC4uLmRlZmF1bHRzLCBtaW46IDEgfSk7XG4gICAgdGhpcy5mb3J3YXJkaW5nUG9vbCA9IGNyZWF0ZVBvb2woZmFjdG9yeSwgeyAuLi5kZWZhdWx0cywgbWluOiAwIH0pO1xuICB9XG5cbiAgLyoqIFN0YXJ0cyBib3RoIHBvb2xzIGFuZCB3YWl0cyB1bnRpbCBvbmUgdGVzdGVkIGNvbW1hbmQgcmVzb3VyY2UgaXMgd2FybS4gKi9cbiAgc3RhcnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuY2xvc2VkKSByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKGAke3RoaXMua2luZH0gU1NIIHRyYW5zcG9ydCBpcyBjbG9zZWRgKSk7XG4gICAgaWYgKHRoaXMuc3RhcnRpbmcpIHJldHVybiB0aGlzLnN0YXJ0aW5nO1xuICAgIHRoaXMuc3RhcnRpbmcgPSB0aGlzLnN0YXJ0UG9vbHMoKTtcbiAgICB2b2lkIHRoaXMuc3RhcnRpbmdcbiAgICAgIC5jYXRjaCgoKSA9PiB0aGlzLmNsb3NlKCkpXG4gICAgICAuY2F0Y2goKGVycm9yKSA9PlxuICAgICAgICBsb2dnZXIud2FybihcImZhaWxlZCB0byBjbG9zZSBTU0ggdHJhbnNwb3J0IGFmdGVyIHN0YXJ0dXAgZmFpbHVyZVwiLCB7XG4gICAgICAgICAga2luZDogdGhpcy5raW5kLFxuICAgICAgICAgIGVycm9yOiBlcnJvclV0aWxzLnRvRXJyb3IoZXJyb3IpLFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgcmV0dXJuIHRoaXMuc3RhcnRpbmc7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHN0YXJ0UG9vbHMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuY2xvc2VkKSB0aHJvdyBuZXcgRXJyb3IoYCR7dGhpcy5raW5kfSBTU0ggdHJhbnNwb3J0IGlzIGNsb3NlZGApO1xuICAgIGNvbnN0IHJlc291cmNlID0gYXdhaXQgdGhpcy5saWZlY3ljbGUuY3JlYXRlKCk7XG4gICAgaWYgKHRoaXMuY2xvc2VkKSB7XG4gICAgICBhd2FpdCB0aGlzLmxpZmVjeWNsZS5kZXN0cm95KHJlc291cmNlKTtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0aGlzLmtpbmR9IFNTSCB0cmFuc3BvcnQgaXMgY2xvc2VkYCk7XG4gICAgfVxuICAgIHRoaXMuc2VlZGVkUmVzb3VyY2VzLnB1c2gocmVzb3VyY2UpO1xuICAgIHRoaXMuY29tbWFuZFBvb2wuc3RhcnQoKTtcbiAgICB0aGlzLmZvcndhcmRpbmdQb29sLnN0YXJ0KCk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc291cmNlID0gYXdhaXQgdGhpcy5jb21tYW5kUG9vbC5hY3F1aXJlKCk7XG4gICAgICBhd2FpdCB0aGlzLmNvbW1hbmRQb29sLnJlbGVhc2UocmVzb3VyY2UpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyB0aGlzLmxhc3RDcmVhdGVFcnJvciA/PyBlcnJvcjtcbiAgICB9XG4gIH1cblxuICBhc3luYyBydW4oc2NyaXB0OiBzdHJpbmcsIGV4ZWN1dGlvbjogU3NoQ29tbWFuZEV4ZWN1dGlvbik6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgcmVzb3VyY2UgPSBhd2FpdCB0aGlzLmFjcXVpcmUodGhpcy5jb21tYW5kUG9vbCk7XG4gICAgdHJ5IHtcbiAgICAgIGlmIChleGVjdXRpb24uc2lnbmFsLmFib3J0ZWQpIHJldHVybiAxMzA7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5ydW5XaXRoUmVzb3VyY2UocmVzb3VyY2UsIHNjcmlwdCwgZXhlY3V0aW9uKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgdGhpcy5kZXN0cm95KHRoaXMuY29tbWFuZFBvb2wsIHJlc291cmNlKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBjb25uZWN0KHJlbW90ZUhvc3Q6IHN0cmluZywgcmVtb3RlUG9ydDogbnVtYmVyKTogUHJvbWlzZTxEdXBsZXg+IHtcbiAgICBjb25zdCBmaXJzdCA9IGF3YWl0IHRoaXMuYWNxdWlyZSh0aGlzLmZvcndhcmRpbmdQb29sKTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuY29ubmVjdFdpdGhCb3Jyb3dlZFJlc291cmNlKGZpcnN0LCByZW1vdGVIb3N0LCByZW1vdGVQb3J0KTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgYXdhaXQgdGhpcy5kZXN0cm95KHRoaXMuZm9yd2FyZGluZ1Bvb2wsIGZpcnN0KTtcbiAgICAgIGlmICh0aGlzLmNsb3NlZCkgdGhyb3cgZXJyb3I7XG4gICAgfVxuICAgIGNvbnN0IHJldHJ5ID0gYXdhaXQgdGhpcy5hY3F1aXJlKHRoaXMuZm9yd2FyZGluZ1Bvb2wpO1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5jb25uZWN0V2l0aEJvcnJvd2VkUmVzb3VyY2UocmV0cnksIHJlbW90ZUhvc3QsIHJlbW90ZVBvcnQpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBhd2FpdCB0aGlzLmRlc3Ryb3kodGhpcy5mb3J3YXJkaW5nUG9vbCwgcmV0cnkpO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgY2xvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuY2xvc2luZykgcmV0dXJuIHRoaXMuY2xvc2luZztcbiAgICB0aGlzLmNsb3NlZCA9IHRydWU7XG4gICAgdGhpcy5jbG9zaW5nID0gdGhpcy5jbG9zZVBvb2xzKCk7XG4gICAgcmV0dXJuIHRoaXMuY2xvc2luZztcbiAgfVxuXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBydW5XaXRoUmVzb3VyY2UoXG4gICAgcmVzb3VyY2U6IFQsXG4gICAgc2NyaXB0OiBzdHJpbmcsXG4gICAgZXhlY3V0aW9uOiBTc2hDb21tYW5kRXhlY3V0aW9uLFxuICApOiBQcm9taXNlPG51bWJlcj47XG5cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGNvbm5lY3RXaXRoUmVzb3VyY2UoXG4gICAgcmVzb3VyY2U6IFQsXG4gICAgcmVtb3RlSG9zdDogc3RyaW5nLFxuICAgIHJlbW90ZVBvcnQ6IG51bWJlcixcbiAgKTogUHJvbWlzZTxEdXBsZXg+O1xuXG4gIHByaXZhdGUgYXN5bmMgY29ubmVjdFdpdGhCb3Jyb3dlZFJlc291cmNlKFxuICAgIHJlc291cmNlOiBULFxuICAgIHJlbW90ZUhvc3Q6IHN0cmluZyxcbiAgICByZW1vdGVQb3J0OiBudW1iZXIsXG4gICk6IFByb21pc2U8RHVwbGV4PiB7XG4gICAgY29uc3Qgc3RyZWFtID0gYXdhaXQgdGhpcy5jb25uZWN0V2l0aFJlc291cmNlKHJlc291cmNlLCByZW1vdGVIb3N0LCByZW1vdGVQb3J0KTtcbiAgICBsZXQgZGlzcG9zZWQgPSBmYWxzZTtcbiAgICBjb25zdCBkaXNwb3NlID0gKCkgPT4ge1xuICAgICAgaWYgKGRpc3Bvc2VkKSByZXR1cm47XG4gICAgICBkaXNwb3NlZCA9IHRydWU7XG4gICAgICB2b2lkIHRoaXMuZGVzdHJveSh0aGlzLmZvcndhcmRpbmdQb29sLCByZXNvdXJjZSk7XG4gICAgfTtcbiAgICBzdHJlYW0ub25jZShcImNsb3NlXCIsIGRpc3Bvc2UpO1xuICAgIHN0cmVhbS5vbmNlKFwiZXJyb3JcIiwgZGlzcG9zZSk7XG4gICAgaWYgKHN0cmVhbS5kZXN0cm95ZWQpIGRpc3Bvc2UoKTtcbiAgICByZXR1cm4gc3RyZWFtO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBhY3F1aXJlKHBvb2w6IFBvb2w8VD4pOiBQcm9taXNlPFQ+IHtcbiAgICBpZiAodGhpcy5jbG9zZWQpIHRocm93IG5ldyBFcnJvcihgJHt0aGlzLmtpbmR9IFNTSCB0cmFuc3BvcnQgaXMgY2xvc2VkYCk7XG4gICAgbGV0IHJlc291cmNlOiBUO1xuICAgIHRyeSB7XG4gICAgICByZXNvdXJjZSA9IGF3YWl0IHBvb2wuYWNxdWlyZSgpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyB0aGlzLmxhc3RDcmVhdGVFcnJvciA/PyBlcnJvcjtcbiAgICB9XG4gICAgdGhpcy5hY3RpdmVSZXNvdXJjZXMuc2V0KHJlc291cmNlLCBwb29sKTtcbiAgICBpZiAodGhpcy5jbG9zZWQpIHtcbiAgICAgIGF3YWl0IHRoaXMuZGVzdHJveShwb29sLCByZXNvdXJjZSk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7dGhpcy5raW5kfSBTU0ggdHJhbnNwb3J0IGlzIGNsb3NlZGApO1xuICAgIH1cbiAgICByZXR1cm4gcmVzb3VyY2U7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGRlc3Ryb3kocG9vbDogUG9vbDxUPiwgcmVzb3VyY2U6IFQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5hY3RpdmVSZXNvdXJjZXMuZ2V0KHJlc291cmNlKSAhPT0gcG9vbCkgcmV0dXJuO1xuICAgIHRoaXMuYWN0aXZlUmVzb3VyY2VzLmRlbGV0ZShyZXNvdXJjZSk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHBvb2wuZGVzdHJveShyZXNvdXJjZSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci53YXJuKFwiZmFpbGVkIHRvIGRlc3Ryb3kgcG9vbGVkIFNTSCByZXNvdXJjZVwiLCB7XG4gICAgICAgIGtpbmQ6IHRoaXMua2luZCxcbiAgICAgICAgZXJyb3I6IGVycm9yVXRpbHMudG9FcnJvcihlcnJvciksXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNsb3NlUG9vbHMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5zdGFydGluZz8uY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICBjb25zdCBjb21tYW5kRHJhaW4gPSB0aGlzLmNvbW1hbmRQb29sLmRyYWluKCk7XG4gICAgY29uc3QgZm9yd2FyZGluZ0RyYWluID0gdGhpcy5mb3J3YXJkaW5nUG9vbC5kcmFpbigpO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgWy4uLnRoaXMuYWN0aXZlUmVzb3VyY2VzXS5tYXAoKFtyZXNvdXJjZSwgcG9vbF0pID0+IHRoaXMuZGVzdHJveShwb29sLCByZXNvdXJjZSkpLFxuICAgICk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoW2NvbW1hbmREcmFpbiwgZm9yd2FyZGluZ0RyYWluXSk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoW3RoaXMuY29tbWFuZFBvb2wuY2xlYXIoKSwgdGhpcy5mb3J3YXJkaW5nUG9vbC5jbGVhcigpXSk7XG4gIH1cbn1cblxuLyoqIEluamVjdGFibGUgdHJhbnNwb3J0IGNvbnN0cnVjdG9ycyB1c2VkIHRvIGlzb2xhdGUgcG9saWN5IHNlbGVjdGlvbiBpbiB0ZXN0cy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3NoVHJhbnNwb3J0RmFjdG9yaWVzIHtcbiAgc3VwcG9ydHNPcGVuU3NoKGNvbW1hbmQ6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj47XG4gIGNyZWF0ZU9wZW5Tc2gob3B0aW9uczogU3NoVHJhbnNwb3J0T3B0aW9ucywgY29tbWFuZDogc3RyaW5nKTogUHJvbWlzZTxTc2hUcmFuc3BvcnQ+O1xuICBjcmVhdGVTc2gyKG9wdGlvbnM6IFNzaFRyYW5zcG9ydE9wdGlvbnMpOiBQcm9taXNlPFNzaFRyYW5zcG9ydD47XG59XG5cbi8qKlxuICogU2VsZWN0IG9uZSBTU0ggdHJhbnNwb3J0IGZyb20gcmVzb2x2ZWQgcG9saWN5IGFuZCBrZWVwIGl0IGZvciB0aGUgc2Vzc2lvbi5cbiAqIEF1dG8gcHJlZmVycyBuYXRpdmUgT3BlblNTSCBhbmQgb3RoZXJ3aXNlIHNlbGVjdHMgc3NoMi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVNzaFRyYW5zcG9ydChcbiAgb3B0aW9uczogU3NoVHJhbnNwb3J0T3B0aW9ucyxcbiAgb3ZlcnJpZGVzOiBQYXJ0aWFsPFNzaFRyYW5zcG9ydEZhY3Rvcmllcz4gPSB7fSxcbik6IFByb21pc2U8U3NoVHJhbnNwb3J0PiB7XG4gIGNvbnN0IGZhY3RvcmllcyA9IHsgLi4uZGVmYXVsdFNzaFRyYW5zcG9ydEZhY3RvcmllcywgLi4ub3ZlcnJpZGVzIH07XG4gIGNvbnN0IHNzaENvbW1hbmQgPSBvcHRpb25zLnNzaENvbW1hbmQgPz8gXCJzc2hcIjtcbiAgY29uc3QgdHJhbnNwb3J0TW9kZSA9IG9wdGlvbnMudHJhbnNwb3J0ID8/IFwiYXV0b1wiO1xuICBpZiAodHJhbnNwb3J0TW9kZSA9PT0gXCJzc2gyXCIpIHtcbiAgICByZXR1cm4gZmFjdG9yaWVzLmNyZWF0ZVNzaDIob3B0aW9ucyk7XG4gIH1cbiAgY29uc3Qgb3BlblNzaFN1cHBvcnRlZCA9IGF3YWl0IGZhY3Rvcmllcy5zdXBwb3J0c09wZW5Tc2goc3NoQ29tbWFuZCk7XG4gIGlmICh0cmFuc3BvcnRNb2RlID09PSBcIm9wZW5zc2hcIiAmJiAhb3BlblNzaFN1cHBvcnRlZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIk5hdGl2ZSBPcGVuU1NIIHdpdGggU09DS1M1IGZvcndhcmRpbmcgaXMgdW5hdmFpbGFibGVcIik7XG4gIH1cbiAgaWYgKG9wZW5Tc2hTdXBwb3J0ZWQpIHtcbiAgICByZXR1cm4gZmFjdG9yaWVzLmNyZWF0ZU9wZW5Tc2gob3B0aW9ucywgc3NoQ29tbWFuZCk7XG4gIH1cbiAgaWYgKHRyYW5zcG9ydE1vZGUgIT09IFwiYXV0b1wiKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBTU0ggdHJhbnNwb3J0OiAke3RyYW5zcG9ydE1vZGV9YCk7XG4gIH1cbiAgcmV0dXJuIGZhY3Rvcmllcy5jcmVhdGVTc2gyKG9wdGlvbnMpO1xufVxuXG5jb25zdCBkZWZhdWx0U3NoVHJhbnNwb3J0RmFjdG9yaWVzOiBTc2hUcmFuc3BvcnRGYWN0b3JpZXMgPSB7XG4gIHN1cHBvcnRzT3BlblNzaDogYXN5bmMgKGNvbW1hbmQpID0+IHtcbiAgICBjb25zdCB7IHN1cHBvcnRzTmF0aXZlT3BlblNzaCB9ID0gYXdhaXQgaW1wb3J0KFwiLi9fc3NoX29wZW5zc2gudHNcIik7XG4gICAgcmV0dXJuIHN1cHBvcnRzTmF0aXZlT3BlblNzaChjb21tYW5kKTtcbiAgfSxcbiAgY3JlYXRlT3BlblNzaDogYXN5bmMgKG9wdGlvbnMsIGNvbW1hbmQpID0+IHtcbiAgICBjb25zdCB7IE9wZW5Tc2hUcmFuc3BvcnQgfSA9IGF3YWl0IGltcG9ydChcIi4vX3NzaF9vcGVuc3NoLnRzXCIpO1xuICAgIGNvbnN0IHRyYW5zcG9ydCA9IG5ldyBPcGVuU3NoVHJhbnNwb3J0KG9wdGlvbnMsIGNvbW1hbmQpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0cmFuc3BvcnQuc3RhcnQoKTtcbiAgICAgIHJldHVybiB0cmFuc3BvcnQ7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGF3YWl0IHRyYW5zcG9ydC5jbG9zZSgpO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9LFxuICBjcmVhdGVTc2gyOiBhc3luYyAob3B0aW9ucykgPT4ge1xuICAgIGNvbnN0IHsgU3NoMlRyYW5zcG9ydCB9ID0gYXdhaXQgaW1wb3J0KFwiLi9fc3NoX3NzaDIudHNcIik7XG4gICAgY29uc3QgdHJhbnNwb3J0ID0gbmV3IFNzaDJUcmFuc3BvcnQob3B0aW9ucyk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRyYW5zcG9ydC5zdGFydCgpO1xuICAgICAgcmV0dXJuIHRyYW5zcG9ydDtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgYXdhaXQgdHJhbnNwb3J0LmNsb3NlKCk7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH0sXG59O1xuXG4vKipcbiAqIEFjY291bnQgdGhhdCBydW5zIG9uZSByZW1vdGUgY29tbWFuZC5cbiAqXG4gKiBgdXNlcmAgdGFyZ2V0cyBhIGxvY2tlZCwgbm9uLXN1ZG8gTGFrZWJveCBhY2NvdW50LiBgcm9vdGAgaXMgcmVzZXJ2ZWQgZm9yXG4gKiBmaXhlZCBwYWNrYWdlLW93bmVkIGJvb3RzdHJhcCBzY3JpcHRzIGFuZCBpcyBuZXZlciByZWFjaGFibGUgZnJvbSBSRVNULFxuICogYWdlbnQgdG9vbHMsIG9yIHNlcnZpY2UgZGVmaW5pdGlvbnMuXG4gKi9cbmV4cG9ydCB0eXBlIFNzaENvbW1hbmRJZGVudGl0eSA9IHsga2luZDogXCJ1c2VyXCI7IG5hbWU6IHN0cmluZzsgaG9tZTogc3RyaW5nIH0gfCB7IGtpbmQ6IFwicm9vdFwiIH07XG5cbi8qKiBAaW50ZXJuYWwgQnVpbGRzIGEgcmVtb3RlIGNvbW1hbmQgYWZ0ZXIgY2xlYXJpbmcgaW5oZXJpdGVkIG1hY2hpbmUgY3JlZGVudGlhbHMuICovXG5leHBvcnQgZnVuY3Rpb24gc3NoQ29tbWFuZFNjcmlwdChcbiAgY29tbWFuZDogc3RyaW5nLFxuICBhcmdzOiBzdHJpbmdbXSxcbiAgY3dkOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIGVudjogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IHVuZGVmaW5lZCxcbiAgaWRlbnRpdHk6IFNzaENvbW1hbmRJZGVudGl0eSxcbik6IHN0cmluZyB7XG4gIGFzc2VydFNhZmVTc2hFbnZpcm9ubWVudChlbnYpO1xuICBjb25zdCByb290ID0gaWRlbnRpdHkua2luZCA9PT0gXCJyb290XCI7XG4gIGNvbnN0IGhvbWUgPSByb290ID8gXCIvcm9vdFwiIDogaWRlbnRpdHkuaG9tZTtcbiAgY29uc3QgbmFtZSA9IHJvb3QgPyBcInJvb3RcIiA6IGlkZW50aXR5Lm5hbWU7XG4gIGNvbnN0IHdvcmtpbmdEaXJlY3RvcnkgPSBjd2QgPz8gaG9tZTtcbiAgY29uc3QgaW52b2NhdGlvbiA9IFtjb21tYW5kLCAuLi5zY3J1YkxvZ2luU2hlbGxDb21tYW5kKGNvbW1hbmQsIGFyZ3MpXS5tYXAoc2hlbGxRdW90ZSkuam9pbihcIiBcIik7XG4gIGNvbnN0IGVudmlyb25tZW50ID0gT2JqZWN0LmVudHJpZXMoe1xuICAgIEhPTUU6IGhvbWUsXG4gICAgVVNFUjogbmFtZSxcbiAgICBMT0dOQU1FOiBuYW1lLFxuICAgIFNIRUxMOiBcIi9iaW4vYmFzaFwiLFxuICAgIFBXRDogd29ya2luZ0RpcmVjdG9yeSxcbiAgICBQQVRIOiByb290XG4gICAgICA/IFwiL3Vzci9sb2NhbC9zYmluOi91c3IvbG9jYWwvYmluOi91c3Ivc2JpbjovdXNyL2Jpbjovc2JpbjovYmluXCJcbiAgICAgIDogYCR7aG9tZX0vLmxvY2FsL2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL2JpbjovYmluYCxcbiAgICBEQVRBQlJJQ0tTX0NPTkZJR19GSUxFOiBcIi9kZXYvbnVsbFwiLFxuICAgIC4uLmVudixcbiAgfSlcbiAgICAubWFwKChba2V5LCB2YWx1ZV0pID0+IGAke2Vudmlyb25tZW50TmFtZShrZXkpfT0ke3NoZWxsUXVvdGUodmFsdWUpfWApXG4gICAgLmpvaW4oXCIgXCIpO1xuICBjb25zdCBydW4gPSBgY2QgLS0gJHtzaGVsbFF1b3RlKHdvcmtpbmdEaXJlY3RvcnkpfSAmJiAke2ludm9jYXRpb259YDtcbiAgY29uc3Qgc3Vkb0FyZ3MgPSByb290ID8gW1wiLW5cIiwgXCItSFwiXSA6IFtcIi1uXCIsIFwiLUhcIiwgXCItdVwiLCBuYW1lXTtcbiAgY29uc3Qgc3dpdGNoZWQgPSBbXCJzdWRvXCIsIC4uLnN1ZG9BcmdzLCBcIi0tXCIsIFwiZW52XCIsIFwiLWlcIl0ubWFwKHNoZWxsUXVvdGUpLmpvaW4oXCIgXCIpO1xuICByZXR1cm4gYCR7U1NIX0FVVEhfRU5WSVJPTk1FTlRfU0NSVUJ9XFxuZXhlYyAke3N3aXRjaGVkfSAke2Vudmlyb25tZW50fSAnL2Jpbi9zaCcgJy1jJyAke3NoZWxsUXVvdGUocnVuKX0gPC9kZXYvbnVsbGA7XG59XG5cbmZ1bmN0aW9uIHNjcnViTG9naW5TaGVsbENvbW1hbmQoY29tbWFuZDogc3RyaW5nLCBhcmdzOiBzdHJpbmdbXSk6IHN0cmluZ1tdIHtcbiAgY29uc3QgZXhlY3V0YWJsZSA9IGNvbW1hbmQuc3BsaXQoXCIvXCIpLmF0KC0xKTtcbiAgaWYgKCFleGVjdXRhYmxlIHx8ICFbXCJzaFwiLCBcImJhc2hcIiwgXCJ6c2hcIl0uaW5jbHVkZXMoZXhlY3V0YWJsZSkgfHwgYXJnc1swXSAhPT0gXCItbGNcIikge1xuICAgIHJldHVybiBhcmdzO1xuICB9XG4gIGNvbnN0IFtmbGFncywgc2NyaXB0LCAuLi5yZXN0XSA9IGFyZ3M7XG4gIGlmIChzY3JpcHQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIGFyZ3M7XG4gIHJldHVybiBbZmxhZ3MsIGAke1NTSF9BVVRIX0VOVklST05NRU5UX1NDUlVCfVxcbiR7c2NyaXB0fWAsIC4uLnJlc3RdO1xufVxuXG5jb25zdCBTU0hfQVVUSF9FTlZJUk9OTUVOVF9TQ1JVQiA9IGBmb3IgX19kYnhfdG9vbHNfbmFtZSBpbiAkKGVudiB8IHNlZCAtbiAncy9eXFxcXChbQS1aYS16X11bQS1aYS16MC05X10qXFxcXCk9LiovXFxcXDEvcCcpOyBkb1xuICBjYXNlIFwiJF9fZGJ4X3Rvb2xzX25hbWVcIiBpblxuICAgIERBVEFCUklDS1NfKnxTU0hfQVVUSF9TT0NLKVxuICAgICAgdW5zZXQgXCIkX19kYnhfdG9vbHNfbmFtZVwiXG4gICAgICA7O1xuICBlc2FjXG5kb25lXG5leHBvcnQgREFUQUJSSUNLU19DT05GSUdfRklMRT0vZGV2L251bGxgO1xuXG5mdW5jdGlvbiBhc3NlcnRTYWZlU3NoRW52aXJvbm1lbnQoZW52OiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PiB8IHVuZGVmaW5lZCk6IHZvaWQge1xuICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmtleXMoZW52ID8/IHt9KSkge1xuICAgIGlmIChcbiAgICAgIG5hbWUgPT09IFwiSE9NRVwiIHx8XG4gICAgICBuYW1lID09PSBcIlVTRVJcIiB8fFxuICAgICAgbmFtZSA9PT0gXCJMT0dOQU1FXCIgfHxcbiAgICAgIG5hbWUgPT09IFwiU0hFTExcIiB8fFxuICAgICAgbmFtZSA9PT0gXCJQV0RcIiB8fFxuICAgICAgbmFtZSA9PT0gXCJQQVRIXCIgfHxcbiAgICAgIG5hbWUuc3RhcnRzV2l0aChcIlNVRE9fXCIpIHx8XG4gICAgICBuYW1lLnN0YXJ0c1dpdGgoXCJEQVRBQlJJQ0tTX1wiKSB8fFxuICAgICAgbmFtZSA9PT0gXCJTU0hfQVVUSF9TT0NLXCJcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJTU0ggZW52aXJvbm1lbnQgb3ZlcmxheXMgY2Fubm90IHJlcGxhY2UgdGhlIExha2Vib3ggaWRlbnRpdHkgb3IgcmVzdG9yZSBEYXRhYnJpY2tzIG9yIFNTSCBhZ2VudCBjcmVkZW50aWFscy5cIixcbiAgICAgICk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIHNoZWxsUXVvdGUodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJyR7dmFsdWUucmVwbGFjZUFsbChcIidcIiwgXCInXFxcXCcnXCIpfSdgO1xufVxuXG5mdW5jdGlvbiBlbnZpcm9ubWVudE5hbWUodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmICghL15bQS1aYS16X11bQS1aYS16MC05X10qJC8udGVzdCh2YWx1ZSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgU1NIIGVudmlyb25tZW50IHZhcmlhYmxlIG5hbWU6ICR7dmFsdWV9YCk7XG4gIH1cbiAgcmV0dXJuIHZhbHVlO1xufVxuIl19
|
|
File without changes
|