@dbx-tools/lakebox 0.9.153 → 0.9.157

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/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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX3NzaC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9fc3NoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxXQUFXLEVBQThCLE1BQU0sYUFBYSxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRXpELE9BQU8sRUFBRSxVQUFVLEVBQXlDLE1BQU0sY0FBYyxDQUFDO0FBSWpGLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsdUJBQXVCLENBQUMsQ0FBQztBQUNuRCw2RUFBNkU7QUFDN0UsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLEVBQUUsQ0FBQztBQWlCL0IsZ0ZBQWdGO0FBQ2hGLE1BQU0sT0FBTyxVQUFVO0lBNkJWO0lBQ0E7SUE3QkYsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsWUFBWSxDQUFDO0lBQzdDLHFEQUFxRDtJQUM1QyxNQUFNLENBQW1DO0lBQ2xELG9EQUFvRDtJQUMzQyxNQUFNLENBQW1DO0lBQ2xELDJFQUEyRTtJQUNsRSxNQUFNLENBQWdDO0lBQy9DLDBDQUEwQztJQUMxQyxRQUFRLENBQXFCO0lBRVosU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUN2QixZQUFZLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztJQUNqQyxZQUFZLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztJQUNqQyxhQUFhLEdBQUcsSUFBSSxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDMUMsYUFBYSxHQUFHLElBQUksYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzFDLGVBQWUsR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO0lBQ3hDLFVBQVUsQ0FBa0I7SUFDckMsaUJBQWlCLENBQThCO0lBQy9DLGdCQUFnQixDQUE0QjtJQUM1QyxhQUFhLENBQThCO0lBQzNDLFlBQVksQ0FBaUI7SUFDN0IsVUFBVSxHQUFHLEVBQUUsQ0FBQztJQUNoQixVQUFVLEdBQUcsRUFBRSxDQUFDO0lBQ2hCLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFDaEIsUUFBUSxHQUFHLEtBQUssQ0FBQztJQUV6Qiw0RUFBNEU7SUFDNUUsWUFDVyxPQUFlLEVBQ2YsSUFBdUIsRUFDaEMsT0FBNEIsRUFDNUIsS0FBMEQ7UUFIakQsWUFBTyxHQUFQLE9BQU8sQ0FBUTtRQUNmLFNBQUksR0FBSixJQUFJLENBQW1CO1FBSWhDLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFlBQWdELENBQUM7UUFDcEUsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsWUFBZ0QsQ0FBQztRQUNwRSxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksT0FBTyxDQUFTLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3hELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxPQUFPLENBQUM7WUFDakMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLE1BQU0sQ0FBQztRQUNqQyxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDaEQsT0FBTyxFQUFFLFFBQVEsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUTtZQUN6QyxRQUFRO1lBQ1IsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVO1lBQ3ZCLE1BQU0sRUFBRSxJQUFJLENBQUMsVUFBVTtZQUN2QixlQUFlLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxTQUFTO1lBQzVDLEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQzVDLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTztZQUNyQixJQUFJLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7U0FDckIsQ0FBQyxDQUFDLENBQUM7UUFDSixLQUFLLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzVDLEtBQUssSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFeEMsTUFBTSxhQUFhLEdBQUcsR0FBRyxFQUFFO1lBQ3pCLEtBQUssSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM1QyxDQUFDLENBQUM7UUFDRixJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUUsT0FBTztZQUFFLGFBQWEsRUFBRSxDQUFDOztZQUN4QyxPQUFPLENBQUMsTUFBTSxFQUFFLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxhQUFhLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUM5RSxNQUFNLE9BQU8sR0FBRyxVQUFVLENBQUMsR0FBRyxFQUFFO1lBQzlCLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO1lBQ3JCLEtBQUssSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDL0MsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUN0QixPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQztRQUNsQixNQUFNLE9BQU8sR0FBRyxHQUFHLEVBQUU7WUFDbkIsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3RCLE9BQU8sQ0FBQyxNQUFNLEVBQUUsbUJBQW1CLENBQUMsT0FBTyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBQzlELENBQUMsQ0FBQztRQUNGLEtBQUssSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBRTVDLGNBQWMsQ0FBQyxHQUFHLEVBQUU7WUFDbEIsSUFBSSxJQUFJLENBQUMsT0FBTztnQkFBRSxPQUFPO1lBQ3pCLEtBQUssS0FBSyxDQUFDO2dCQUNULE1BQU0sRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU07Z0JBQ25DLE1BQU0sRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDO2dCQUNwRCxNQUFNLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQztnQkFDcEQsU0FBUyxFQUFFLENBQUMsTUFBTSxFQUFFLEVBQUU7b0JBQ3BCLElBQUksQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFDO29CQUM1QixJQUFJLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO3dCQUN4QyxLQUFLLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7b0JBQ2xELENBQUM7Z0JBQ0gsQ0FBQztnQkFDRCxNQUFNLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDO2FBQzFDLENBQUMsQ0FBQyxJQUFJLENBQ0wsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQ25DLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUM1QixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsZ0ZBQWdGO0lBQ2hGLE1BQU0sQ0FBQyxRQUFRLEdBQUcsR0FBRztRQUNuQixJQUFJLElBQUksQ0FBQyxPQUFPO1lBQUUsT0FBTyxJQUFJLENBQUMsWUFBWSxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNoRSxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsT0FBTztZQUFFLElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDdkUsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3pDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdEIsT0FBTyxZQUFZLENBQUM7SUFDdEIsQ0FBQztJQUVELElBQUksQ0FDRixXQUEwRSxFQUMxRSxVQUEyRTtRQUUzRSxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxVQUFVLENBQUMsQ0FBQztJQUN2RCxDQUFDO0lBRUQsS0FBSyxDQUNILFVBQXlFO1FBRXpFLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVELE9BQU8sQ0FBQyxTQUErQjtRQUNyQyxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLFNBQVMsSUFBSSxTQUFTLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBRU8sWUFBWTtRQUNsQixJQUFJLElBQUksQ0FBQyxZQUFZO1lBQUUsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO1FBQ2hELElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYTtZQUFFLE9BQU8sT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2xELE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUM7UUFDekMsSUFBSSxDQUFDLFlBQVksR0FBRyxPQUFPLENBQUMsT0FBTyxFQUFFO2FBQ2xDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxhQUFhLEVBQUUsQ0FBQzthQUMzQixJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDekIsS0FBSyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM5QyxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDM0IsQ0FBQztJQUVPLFdBQVcsQ0FBQyxNQUEyQixFQUFFLEtBQXNCO1FBQ3JFLElBQUksSUFBSSxDQUFDLE9BQU87WUFBRSxPQUFPO1FBQ3pCLE1BQU0sT0FBTyxHQUFHLE1BQU0sS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUM7UUFDOUUsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFPLEtBQUssS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3BGLElBQUksQ0FBQyxLQUFLO1lBQUUsT0FBTztRQUNuQixJQUFJLE1BQU0sS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsVUFBVSxJQUFJLEtBQUssQ0FBQztZQUN6QixJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNqQyxDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxVQUFVLElBQUksS0FBSyxDQUFDO1lBQ3pCLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pDLENBQUM7SUFDSCxDQUFDO0lBRU8sS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFtQjtRQUN0QyxJQUFJLENBQUMsYUFBYSxHQUFHLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUM1QyxJQUFJLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3hDLEtBQUssSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNsRCxDQUFDO1FBQ0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ3ZGLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUN2RixNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQztRQUMvQixNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUNwQyxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0lBRU8sS0FBSyxDQUFDLElBQUksQ0FBQyxNQUE2QixFQUFFLEtBQThCO1FBQzlFLElBQUksS0FBSyxFQUFFLE1BQU0sS0FBSyxJQUFJLE1BQU07WUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDakQsQ0FBQztJQUVPLE1BQU0sQ0FBQyxRQUFnQjtRQUM3QixJQUFJLElBQUksQ0FBQyxPQUFPO1lBQUUsT0FBTztRQUN6QixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztRQUNwQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUN6QixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFTyxJQUFJLENBQUMsS0FBYztRQUN6QixJQUFJLElBQUksQ0FBQyxPQUFPO1lBQUUsT0FBTztRQUN6QixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztRQUNwQixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQy9CLENBQUM7SUFFTyxXQUFXO1FBQ2pCLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDakQsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNqRCxJQUFJLGVBQWUsRUFBRSxDQUFDO1lBQ3BCLElBQUksQ0FBQyxVQUFVLElBQUksZUFBZSxDQUFDO1lBQ25DLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQzNDLENBQUM7UUFDRCxJQUFJLGVBQWUsRUFBRSxDQUFDO1lBQ3BCLElBQUksQ0FBQyxVQUFVLElBQUksZUFBZSxDQUFDO1lBQ25DLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQzNDLENBQUM7UUFDRCxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDMUIsQ0FBQztDQUNGO0FBMkNEOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxPQUFnQixrQkFBa0I7SUFhbkI7SUFWRixXQUFXLENBQVU7SUFDckIsY0FBYyxDQUFVO0lBQ3hCLGVBQWUsR0FBRyxJQUFJLEdBQUcsRUFBYyxDQUFDO0lBQ3hDLGVBQWUsR0FBUSxFQUFFLENBQUM7SUFDbkMsZUFBZSxDQUFVO0lBQ3pCLFFBQVEsQ0FBaUI7SUFDekIsT0FBTyxDQUFpQjtJQUN4QixNQUFNLEdBQUcsS0FBSyxDQUFDO0lBRXZCLFlBQ21CLFNBQWtDLEVBQ25ELFVBQTBCLEVBQUU7UUFEWCxjQUFTLEdBQVQsU0FBUyxDQUF5QjtRQUduRCxNQUFNLE9BQU8sR0FBZTtZQUMxQixNQUFNLEVBQUUsS0FBSyxJQUFJLEVBQUU7Z0JBQ2pCLElBQUksQ0FBQztvQkFDSCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTSxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztvQkFDNUUsSUFBSSxDQUFDLGVBQWUsR0FBRyxTQUFTLENBQUM7b0JBQ2pDLE9BQU8sUUFBUSxDQUFDO2dCQUNsQixDQUFDO2dCQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7b0JBQ2YsSUFBSSxDQUFDLGVBQWUsR0FBRyxLQUFLLENBQUM7b0JBQzdCLE1BQU0sS0FBSyxDQUFDO2dCQUNkLENBQUM7WUFDSCxDQUFDO1lBQ0QsT0FBTyxFQUFFLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQztZQUNsRCxRQUFRLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxFQUFFO2dCQUMzQixJQUFJLENBQUM7b0JBQ0gsT0FBTyxNQUFNLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQ3hDLENBQUM7Z0JBQUMsTUFBTSxDQUFDO29CQUNQLE9BQU8sS0FBSyxDQUFDO2dCQUNmLENBQUM7WUFDSCxDQUFDO1NBQ0YsQ0FBQztRQUNGLE1BQU0sUUFBUSxHQUFZO1lBQ3hCLEdBQUcsRUFBRSxPQUFPLENBQUMsR0FBRyxJQUFJLFlBQVk7WUFDaEMsb0JBQW9CLEVBQUUsT0FBTyxDQUFDLG9CQUFvQixJQUFJLE1BQU07WUFDNUQsaUJBQWlCLEVBQUUsT0FBTyxDQUFDLGlCQUFpQixJQUFJLE1BQU07WUFDdEQseUJBQXlCLEVBQUUsT0FBTyxDQUFDLHlCQUF5QixJQUFJLE1BQU07WUFDdEUsc0JBQXNCLEVBQUUsT0FBTyxDQUFDLHNCQUFzQixJQUFJLENBQUM7WUFDM0QsWUFBWSxFQUFFLElBQUk7WUFDbEIsU0FBUyxFQUFFLEtBQUs7U0FDakIsQ0FBQztRQUNGLElBQUksQ0FBQyxXQUFXLEdBQUcsVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLEdBQUcsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ2hFLElBQUksQ0FBQyxjQUFjLEdBQUcsVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLEdBQUcsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3JFLENBQUM7SUFFRCw2RUFBNkU7SUFDN0UsS0FBSztRQUNILElBQUksSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSwwQkFBMEIsQ0FBQyxDQUFDLENBQUM7UUFDMUYsSUFBSSxJQUFJLENBQUMsUUFBUTtZQUFFLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztRQUN4QyxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNsQyxLQUFLLElBQUksQ0FBQyxRQUFRO2FBQ2YsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQzthQUN6QixLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUNmLE1BQU0sQ0FBQyxJQUFJLENBQUMscURBQXFELEVBQUU7WUFDakUsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO1lBQ2YsS0FBSyxFQUFFLFVBQVUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDO1NBQ2pDLENBQUMsQ0FDSCxDQUFDO1FBQ0osT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQ3ZCLENBQUM7SUFFTyxLQUFLLENBQUMsVUFBVTtRQUN0QixJQUFJLElBQUksQ0FBQyxNQUFNO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLDBCQUEwQixDQUFDLENBQUM7UUFDekUsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQy9DLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2hCLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDdkMsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLDBCQUEwQixDQUFDLENBQUM7UUFDMUQsQ0FBQztRQUNELElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3BDLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUM7WUFDSCxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDbEQsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMzQyxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sSUFBSSxDQUFDLGVBQWUsSUFBSSxLQUFLLENBQUM7UUFDdEMsQ0FBQztJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsR0FBRyxDQUFDLE1BQWMsRUFBRSxTQUE4QjtRQUN0RCxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3RELElBQUksQ0FBQztZQUNILElBQUksU0FBUyxDQUFDLE1BQU0sQ0FBQyxPQUFPO2dCQUFFLE9BQU8sR0FBRyxDQUFDO1lBQ3pDLE9BQU8sTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDakUsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDakQsQ0FBQztJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsT0FBTyxDQUFDLFVBQWtCLEVBQUUsVUFBa0I7UUFDbEQsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUN0RCxJQUFJLENBQUM7WUFDSCxPQUFPLE1BQU0sSUFBSSxDQUFDLDJCQUEyQixDQUFDLEtBQUssRUFBRSxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDL0UsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUMvQyxJQUFJLElBQUksQ0FBQyxNQUFNO2dCQUFFLE1BQU0sS0FBSyxDQUFDO1FBQy9CLENBQUM7UUFDRCxNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3RELElBQUksQ0FBQztZQUNILE9BQU8sTUFBTSxJQUFJLENBQUMsMkJBQTJCLENBQUMsS0FBSyxFQUFFLFVBQVUsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUMvRSxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQy9DLE1BQU0sS0FBSyxDQUFDO1FBQ2QsQ0FBQztJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsS0FBSztRQUNULElBQUksSUFBSSxDQUFDLE9BQU87WUFBRSxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7UUFDdEMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7UUFDbkIsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDakMsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBQ3RCLENBQUM7SUFjTyxLQUFLLENBQUMsMkJBQTJCLENBQ3ZDLFFBQVcsRUFDWCxVQUFrQixFQUNsQixVQUFrQjtRQUVsQixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxRQUFRLEVBQUUsVUFBVSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBQ2hGLElBQUksUUFBUSxHQUFHLEtBQUssQ0FBQztRQUNyQixNQUFNLE9BQU8sR0FBRyxHQUFHLEVBQUU7WUFDbkIsSUFBSSxRQUFRO2dCQUFFLE9BQU87WUFDckIsUUFBUSxHQUFHLElBQUksQ0FBQztZQUNoQixLQUFLLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUNuRCxDQUFDLENBQUM7UUFDRixNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUM5QixNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUM5QixJQUFJLE1BQU0sQ0FBQyxTQUFTO1lBQUUsT0FBTyxFQUFFLENBQUM7UUFDaEMsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVPLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBYTtRQUNqQyxJQUFJLElBQUksQ0FBQyxNQUFNO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLDBCQUEwQixDQUFDLENBQUM7UUFDekUsSUFBSSxRQUFXLENBQUM7UUFDaEIsSUFBSSxDQUFDO1lBQ0gsUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2xDLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsTUFBTSxJQUFJLENBQUMsZUFBZSxJQUFJLEtBQUssQ0FBQztRQUN0QyxDQUFDO1FBQ0QsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3pDLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2hCLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDbkMsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLDBCQUEwQixDQUFDLENBQUM7UUFDMUQsQ0FBQztRQUNELE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFFTyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQWEsRUFBRSxRQUFXO1FBQzlDLElBQUksSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEtBQUssSUFBSTtZQUFFLE9BQU87UUFDeEQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDO1lBQ0gsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQy9CLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsTUFBTSxDQUFDLElBQUksQ0FBQyx1Q0FBdUMsRUFBRTtnQkFDbkQsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO2dCQUNmLEtBQUssRUFBRSxVQUFVLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQzthQUNqQyxDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxVQUFVO1FBQ3RCLE1BQU0sSUFBSSxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDNUMsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUM5QyxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3BELE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FDZixDQUFDLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUNsRixDQUFDO1FBQ0YsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsWUFBWSxFQUFFLGVBQWUsQ0FBQyxDQUFDLENBQUM7UUFDbkQsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsRUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM3RSxDQUFDO0NBQ0Y7QUFTRDs7O0dBR0c7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGtCQUFrQixDQUN0QyxPQUE0QixFQUM1QixZQUE0QyxFQUFFO0lBRTlDLE1BQU0sU0FBUyxHQUFHLEVBQUUsR0FBRyw0QkFBNEIsRUFBRSxHQUFHLFNBQVMsRUFBRSxDQUFDO0lBQ3BFLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxVQUFVLElBQUksS0FBSyxDQUFDO0lBQy9DLE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxTQUFTLElBQUksTUFBTSxDQUFDO0lBQ2xELElBQUksYUFBYSxLQUFLLE1BQU0sRUFBRSxDQUFDO1FBQzdCLE9BQU8sU0FBUyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBQ0QsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLFNBQVMsQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDckUsSUFBSSxhQUFhLEtBQUssU0FBUyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUNyRCxNQUFNLElBQUksS0FBSyxDQUFDLHNEQUFzRCxDQUFDLENBQUM7SUFDMUUsQ0FBQztJQUNELElBQUksZ0JBQWdCLEVBQUUsQ0FBQztRQUNyQixPQUFPLFNBQVMsQ0FBQyxhQUFhLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3RELENBQUM7SUFDRCxJQUFJLGFBQWEsS0FBSyxNQUFNLEVBQUUsQ0FBQztRQUM3QixNQUFNLElBQUksS0FBSyxDQUFDLDhCQUE4QixhQUFhLEVBQUUsQ0FBQyxDQUFDO0lBQ2pFLENBQUM7SUFDRCxPQUFPLFNBQVMsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDdkMsQ0FBQztBQUVELE1BQU0sNEJBQTRCLEdBQTBCO0lBQzFELGVBQWUsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7UUFDakMsTUFBTSxFQUFFLHFCQUFxQixFQUFFLEdBQUcsTUFBTSxNQUFNLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUNwRSxPQUFPLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3hDLENBQUM7SUFDRCxhQUFhLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRTtRQUN4QyxNQUFNLEVBQUUsZ0JBQWdCLEVBQUUsR0FBRyxNQUFNLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBQy9ELE1BQU0sU0FBUyxHQUFHLElBQUksZ0JBQWdCLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3pELElBQUksQ0FBQztZQUNILE1BQU0sU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3hCLE9BQU8sU0FBUyxDQUFDO1FBQ25CLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsTUFBTSxTQUFTLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDeEIsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUNELFVBQVUsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7UUFDNUIsTUFBTSxFQUFFLGFBQWEsRUFBRSxHQUFHLE1BQU0sTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDekQsTUFBTSxTQUFTLEdBQUcsSUFBSSxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDN0MsSUFBSSxDQUFDO1lBQ0gsTUFBTSxTQUFTLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDeEIsT0FBTyxTQUFTLENBQUM7UUFDbkIsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixNQUFNLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUN4QixNQUFNLEtBQUssQ0FBQztRQUNkLENBQUM7SUFDSCxDQUFDO0NBQ0YsQ0FBQztBQVdGLHNGQUFzRjtBQUN0RixNQUFNLFVBQVUsZ0JBQWdCLENBQzlCLE9BQWUsRUFDZixJQUFjLEVBQ2QsR0FBdUIsRUFDdkIsR0FBdUMsRUFDdkMsUUFBNEI7SUFFNUIsd0JBQXdCLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDOUIsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLElBQUksS0FBSyxNQUFNLENBQUM7SUFDdEMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7SUFDNUMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7SUFDM0MsTUFBTSxnQkFBZ0IsR0FBRyxHQUFHLElBQUksSUFBSSxDQUFDO0lBQ3JDLE1BQU0sVUFBVSxHQUFHLENBQUMsT0FBTyxFQUFFLEdBQUcsc0JBQXNCLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqRyxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDO1FBQ2pDLElBQUksRUFBRSxJQUFJO1FBQ1YsSUFBSSxFQUFFLElBQUk7UUFDVixPQUFPLEVBQUUsSUFBSTtRQUNiLEtBQUssRUFBRSxXQUFXO1FBQ2xCLEdBQUcsRUFBRSxnQkFBZ0I7UUFDckIsSUFBSSxFQUFFLElBQUk7WUFDUixDQUFDLENBQUMsOERBQThEO1lBQ2hFLENBQUMsQ0FBQyxHQUFHLElBQUksMENBQTBDO1FBQ3JELHNCQUFzQixFQUFFLFdBQVc7UUFDbkMsR0FBRyxHQUFHO0tBQ1AsQ0FBQztTQUNDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLGVBQWUsQ0FBQyxHQUFHLENBQUMsSUFBSSxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztTQUNyRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDYixNQUFNLEdBQUcsR0FBRyxTQUFTLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLFVBQVUsRUFBRSxDQUFDO0lBQ3JFLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDaEUsTUFBTSxRQUFRLEdBQUcsQ0FBQyxNQUFNLEVBQUUsR0FBRyxRQUFRLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3BGLE9BQU8sR0FBRywwQkFBMEIsVUFBVSxRQUFRLElBQUksV0FBVyxtQkFBbUIsVUFBVSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUM7QUFDdkgsQ0FBQztBQUVELFNBQVMsc0JBQXNCLENBQUMsT0FBZSxFQUFFLElBQWM7SUFDN0QsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM3QyxJQUFJLENBQUMsVUFBVSxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssS0FBSyxFQUFFLENBQUM7UUFDcEYsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQ0QsTUFBTSxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUM7SUFDdEMsSUFBSSxNQUFNLEtBQUssU0FBUztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3RDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsR0FBRywwQkFBMEIsS0FBSyxNQUFNLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0FBQ3RFLENBQUM7QUFFRCxNQUFNLDBCQUEwQixHQUFHOzs7Ozs7O3dDQU9LLENBQUM7QUFFekMsU0FBUyx3QkFBd0IsQ0FBQyxHQUFpRDtJQUNqRixLQUFLLE1BQU0sSUFBSSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUFDMUMsSUFDRSxJQUFJLEtBQUssTUFBTTtZQUNmLElBQUksS0FBSyxNQUFNO1lBQ2YsSUFBSSxLQUFLLFNBQVM7WUFDbEIsSUFBSSxLQUFLLE9BQU87WUFDaEIsSUFBSSxLQUFLLEtBQUs7WUFDZCxJQUFJLEtBQUssTUFBTTtZQUNmLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDO1lBQ3hCLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDO1lBQzlCLElBQUksS0FBSyxlQUFlLEVBQ3hCLENBQUM7WUFDRCxNQUFNLElBQUksS0FBSyxDQUNiLDhHQUE4RyxDQUMvRyxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDO0FBRUQsU0FBUyxVQUFVLENBQUMsS0FBYTtJQUMvQixPQUFPLElBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQztBQUMvQyxDQUFDO0FBRUQsU0FBUyxlQUFlLENBQUMsS0FBYTtJQUNwQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDNUMsTUFBTSxJQUFJLEtBQUssQ0FBQywwQ0FBMEMsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGFzc1Rocm91Z2gsIHR5cGUgRHVwbGV4LCB0eXBlIFJlYWRhYmxlIH0gZnJvbSBcIm5vZGU6c3RyZWFtXCI7XG5pbXBvcnQgeyBTdHJpbmdEZWNvZGVyIH0gZnJvbSBcIm5vZGU6c3RyaW5nX2RlY29kZXJcIjtcbmltcG9ydCB7IGVycm9yVXRpbHMsIGxvZyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgdHlwZSB7IExha2Vib3hDb21tYW5kUmVzdWx0IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWxha2Vib3hcIjtcbmltcG9ydCB7IGNyZWF0ZVBvb2wsIHR5cGUgRmFjdG9yeSwgdHlwZSBPcHRpb25zLCB0eXBlIFBvb2wgfSBmcm9tIFwiZ2VuZXJpYy1wb29sXCI7XG5pbXBvcnQgdHlwZSB7IENsaWVudCBhcyBTc2gyQ2xpZW50IH0gZnJvbSBcInNzaDJcIjtcbmltcG9ydCB0eXBlIHsgU3NoMlBhdGNoTW9kZSwgU3NoVHJhbnNwb3J0TW9kZSB9IGZyb20gXCIuL3RyYW5zcG9ydC50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwibGFrZWJveDpzc2gtdHJhbnNwb3J0XCIpO1xuLyoqIE1heGltdW0gYXV0aGVudGljYXRlZCByZXNvdXJjZXMgbWFpbnRhaW5lZCBieSBlYWNoIFNTSCBvcGVyYXRpb24gcG9vbC4gKi9cbmV4cG9ydCBjb25zdCBTU0hfUE9PTF9NQVggPSAxMDtcblxuLyoqIE9uZSBjb21tYW5kIGV4ZWN1dGlvbiByZXF1ZXN0IGFmdGVyIHRoZSByZW1vdGUgc2hlbGwgc2NyaXB0IGlzIGFzc2VtYmxlZC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3NoRXhlY3V0aW9uT3B0aW9ucyB7XG4gIHRpbWVvdXRNczogbnVtYmVyO1xuICBzaWduYWw/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