@workflow/core 5.0.0-beta.38 → 5.0.0-beta.39
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/dist/capabilities.d.ts +5 -0
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +20 -2
- package/dist/context-violation-error.d.ts.map +1 -1
- package/dist/context-violation-error.js +4 -2
- package/dist/replay-payload-cache.d.ts +11 -0
- package/dist/replay-payload-cache.d.ts.map +1 -1
- package/dist/replay-payload-cache.js +21 -4
- package/dist/runtime/compute-instance.d.ts +12 -0
- package/dist/runtime/compute-instance.d.ts.map +1 -0
- package/dist/runtime/compute-instance.js +13 -0
- package/dist/runtime/constants.d.ts +18 -0
- package/dist/runtime/constants.d.ts.map +1 -1
- package/dist/runtime/constants.js +42 -1
- package/dist/runtime/helpers.d.ts +103 -31
- package/dist/runtime/helpers.d.ts.map +1 -1
- package/dist/runtime/helpers.js +138 -61
- package/dist/runtime/replay-recovery-reporter.d.ts +36 -0
- package/dist/runtime/replay-recovery-reporter.d.ts.map +1 -0
- package/dist/runtime/replay-recovery-reporter.js +64 -0
- package/dist/runtime/resume-hook.d.ts +22 -2
- package/dist/runtime/resume-hook.d.ts.map +1 -1
- package/dist/runtime/resume-hook.js +281 -47
- package/dist/runtime/start.d.ts.map +1 -1
- package/dist/runtime/start.js +50 -3
- package/dist/runtime/step-executor.d.ts +17 -13
- package/dist/runtime/step-executor.d.ts.map +1 -1
- package/dist/runtime/step-executor.js +36 -24
- package/dist/runtime/suspension-handler.d.ts +13 -8
- package/dist/runtime/suspension-handler.d.ts.map +1 -1
- package/dist/runtime/suspension-handler.js +60 -18
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +622 -67
- package/dist/serialization/codec-devalue.d.ts.map +1 -1
- package/dist/serialization/codec-devalue.js +9 -2
- package/dist/serialization/codec.d.ts +17 -0
- package/dist/serialization/codec.d.ts.map +1 -1
- package/dist/serialization/codec.js +1 -1
- package/dist/serialization/hardened.d.ts +155 -0
- package/dist/serialization/hardened.d.ts.map +1 -0
- package/dist/serialization/hardened.js +523 -0
- package/dist/serialization/index.d.ts +2 -1
- package/dist/serialization/index.d.ts.map +1 -1
- package/dist/serialization/index.js +1 -1
- package/dist/serialization/reducers/class.d.ts.map +1 -1
- package/dist/serialization/reducers/class.js +11 -6
- package/dist/serialization/reducers/common.d.ts +1 -1
- package/dist/serialization/reducers/common.d.ts.map +1 -1
- package/dist/serialization/reducers/common.js +100 -61
- package/dist/serialization/reducers/step-function.d.ts.map +1 -1
- package/dist/serialization/reducers/step-function.js +25 -9
- package/dist/serialization.d.ts +13 -9
- package/dist/serialization.d.ts.map +1 -1
- package/dist/serialization.js +149 -48
- package/dist/set-attributes.d.ts.map +1 -1
- package/dist/set-attributes.js +5 -1
- package/dist/step/context-storage.d.ts +1 -1
- package/dist/step/context-storage.d.ts.map +1 -1
- package/dist/step/context-storage.js +6 -4
- package/dist/step/writable-stream.d.ts.map +1 -1
- package/dist/step/writable-stream.js +3 -2
- package/dist/step.d.ts.map +1 -1
- package/dist/step.js +9 -2
- package/dist/telemetry/semantic-conventions.d.ts +41 -0
- package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
- package/dist/telemetry/semantic-conventions.js +32 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +2 -2
- package/dist/workflow/hook.d.ts.map +1 -1
- package/dist/workflow/hook.js +38 -1
- package/dist/workflow.d.ts +1 -1
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +6 -2
- package/package.json +6 -6
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { EntityConflictError, ERROR_SLUGS, HookNotFoundError, RunExpiredError, WorkflowRuntimeError, } from '@workflow/errors';
|
|
2
|
-
import { isLegacySpecVersion, isTerminalWorkflowRunStatus, SPEC_VERSION_CURRENT, SPEC_VERSION_LEGACY, SPEC_VERSION_SUPPORTS_COMPRESSION, } from '@workflow/world';
|
|
2
|
+
import { HOOK_RESUME_DEDUP_VERSION, HOOK_RESUME_INPUT_VERSION, isLegacySpecVersion, isTerminalWorkflowRunStatus, SPEC_VERSION_CURRENT, SPEC_VERSION_LEGACY, SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT, SPEC_VERSION_SUPPORTS_COMPRESSION, } from '@workflow/world';
|
|
3
|
+
import { monotonicFactory } from 'ulid';
|
|
3
4
|
import { getRunCapabilities } from '../capabilities.js';
|
|
5
|
+
import { isRetryableWorldError } from '../classify-error.js';
|
|
4
6
|
import { importKey } from '../encryption.js';
|
|
5
7
|
import { runtimeLogger } from '../logger.js';
|
|
6
8
|
import { decodeRunPublicKey } from '../sealed-box.js';
|
|
@@ -12,10 +14,41 @@ import { linkToTraceCarrier, trace } from '../telemetry.js';
|
|
|
12
14
|
import { getWorldLazy } from './get-world-lazy.js';
|
|
13
15
|
import { getWorkflowQueueName } from './helpers.js';
|
|
14
16
|
import { safeWaitUntil, waitedUntil } from './wait-until.js';
|
|
17
|
+
/** Monotonic ULID factory for per-call resume idempotency keys. */
|
|
18
|
+
const generateResumeId = monotonicFactory();
|
|
19
|
+
/**
|
|
20
|
+
* Upper bound on the serialized hook payload that the parallel fast path will
|
|
21
|
+
* inline into the queue message's `hookInput`. Vercel Queues caps a single
|
|
22
|
+
* message at ~256 KiB, and the message also carries the runId, hookId, token,
|
|
23
|
+
* resumeId, digest, and trace carrier alongside CBOR framing overhead. Staying
|
|
24
|
+
* well under that ceiling keeps the queue publish from rejecting an oversized
|
|
25
|
+
* message — which, on the parallel path, would persist `hook_received` but never
|
|
26
|
+
* re-trigger the run. Above this size we fall back to the sequential path, whose
|
|
27
|
+
* queue message carries only the run ID (the payload lives in the event log).
|
|
28
|
+
*/
|
|
29
|
+
const MAX_INLINE_RESUME_PAYLOAD_BYTES = 128 * 1024;
|
|
30
|
+
/**
|
|
31
|
+
* Hex SHA-256 of the serialized resume payload bytes. Computed once by the
|
|
32
|
+
* producer and forwarded verbatim on both the direct `hook_received` write and
|
|
33
|
+
* the queue `hookInput`, so both writers of the same `resumeId` record an
|
|
34
|
+
* identical digest on the server's `(runId, resumeId)` constraint. Hashing the
|
|
35
|
+
* already-serialized bytes (not the raw value) keeps producer and consumer in
|
|
36
|
+
* lockstep — the consumer forwards this string without recomputing.
|
|
37
|
+
*/
|
|
38
|
+
async function computeResumePayloadDigest(bytes) {
|
|
39
|
+
const digest = await crypto.subtle.digest('SHA-256', bytes);
|
|
40
|
+
const view = new Uint8Array(digest);
|
|
41
|
+
let hex = '';
|
|
42
|
+
for (const b of view) {
|
|
43
|
+
hex += b.toString(16).padStart(2, '0');
|
|
44
|
+
}
|
|
45
|
+
return hex;
|
|
46
|
+
}
|
|
15
47
|
/** Derive a resume context from a full run (fallback for pre-`resumeContext` hooks). */
|
|
16
48
|
function resumeContextFromRun(run) {
|
|
17
49
|
const coreVersion = run.executionContext?.workflowCoreVersion;
|
|
18
50
|
const traceCarrier = run.executionContext?.traceCarrier;
|
|
51
|
+
const hookResumeInputVersion = run.executionContext?.hookResumeInputVersion;
|
|
19
52
|
return {
|
|
20
53
|
deploymentId: run.deploymentId,
|
|
21
54
|
workflowName: run.workflowName,
|
|
@@ -25,6 +58,9 @@ function resumeContextFromRun(run) {
|
|
|
25
58
|
? traceCarrier
|
|
26
59
|
: undefined,
|
|
27
60
|
encryptionPublicKey: run.encryptionPublicKey,
|
|
61
|
+
hookResumeInputVersion: typeof hookResumeInputVersion === 'number'
|
|
62
|
+
? hookResumeInputVersion
|
|
63
|
+
: undefined,
|
|
28
64
|
};
|
|
29
65
|
}
|
|
30
66
|
/**
|
|
@@ -111,7 +147,7 @@ export async function getHookByToken(token) {
|
|
|
111
147
|
*
|
|
112
148
|
* @param tokenOrHook - The unique token identifying the hook, or the hook object itself
|
|
113
149
|
* @param payload - The data payload to send to the hook
|
|
114
|
-
* @returns Promise resolving to the
|
|
150
|
+
* @returns Promise resolving to the {@link ResumedHook}
|
|
115
151
|
* @throws {HookNotFoundError} If the Hook does not exist or its run has ended
|
|
116
152
|
*
|
|
117
153
|
* @example
|
|
@@ -133,13 +169,38 @@ export async function getHookByToken(token) {
|
|
|
133
169
|
* ```
|
|
134
170
|
*/
|
|
135
171
|
export async function resumeHook(tokenOrHook, payload, encryptionKeyOverride) {
|
|
172
|
+
// Public entry point. It never attests hook freshness, so a Hook object
|
|
173
|
+
// supplied here — which may carry a `resumeCapabilities` cached before a
|
|
174
|
+
// server rollback or kill switch — is ignored by the dynamic-dedup gate and
|
|
175
|
+
// fails closed to the sequential path. Only `resumeWebhook`, which fetches
|
|
176
|
+
// the hook by token in-line during the same resume, reaches the internal
|
|
177
|
+
// implementation with the fresh attestation set. Keeping the freshness flag
|
|
178
|
+
// off the exported signature prevents a caller from passing a stale Hook plus
|
|
179
|
+
// `true` and reactivating dynamic dedup against a rolled-back backend.
|
|
180
|
+
return resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, false);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Internal implementation of {@link resumeHook}. NOT exported: the
|
|
184
|
+
* `hookFreshlyLookedUp` attestation must never be reachable by public callers
|
|
185
|
+
* (see the wrapper above).
|
|
186
|
+
*
|
|
187
|
+
* @param hookFreshlyLookedUp - Attests that a supplied Hook object was fetched
|
|
188
|
+
* by token during THIS resume, so its response-only `resumeCapabilities`
|
|
189
|
+
* reflects the live backend and may be trusted for the dynamic-dedup gate.
|
|
190
|
+
* A token string is always fetched fresh here, so it is implicitly fresh.
|
|
191
|
+
*/
|
|
192
|
+
async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp) {
|
|
136
193
|
return await waitedUntil(() => {
|
|
137
194
|
return trace('hook.resume', async (span) => {
|
|
138
195
|
const world = await getWorldLazy();
|
|
139
196
|
try {
|
|
140
|
-
const
|
|
197
|
+
const suppliedToken = typeof tokenOrHook === 'string';
|
|
198
|
+
const hook = suppliedToken
|
|
141
199
|
? await world.hooks.getByToken(tokenOrHook)
|
|
142
200
|
: tokenOrHook;
|
|
201
|
+
// The dynamic, response-only `resumeCapabilities` may only be trusted
|
|
202
|
+
// when it came from a by-token lookup performed during this resume.
|
|
203
|
+
const hookResumeCapabilitiesAreFresh = suppliedToken || hookFreshlyLookedUp;
|
|
143
204
|
const info = await resolveHookResumeInfo(hook);
|
|
144
205
|
const { resumeContext } = info;
|
|
145
206
|
span?.setAttributes({
|
|
@@ -228,59 +289,227 @@ export async function resumeHook(tokenOrHook, payload, encryptionKeyOverride) {
|
|
|
228
289
|
error: err instanceof Error ? err.message : String(err),
|
|
229
290
|
});
|
|
230
291
|
});
|
|
231
|
-
// Create a hook_received event with the payload
|
|
232
|
-
try {
|
|
233
|
-
await world.events.create(hook.runId, {
|
|
234
|
-
eventType: 'hook_received',
|
|
235
|
-
specVersion: SPEC_VERSION_CURRENT,
|
|
236
|
-
correlationId: hook.hookId,
|
|
237
|
-
eventData: {
|
|
238
|
-
...(v1Compat ? {} : { token: hook.token }),
|
|
239
|
-
payload: dehydratedPayload,
|
|
240
|
-
},
|
|
241
|
-
}, { v1Compat });
|
|
242
|
-
}
|
|
243
|
-
catch (err) {
|
|
244
|
-
// Re-key any "hook can no longer be received" rejection to
|
|
245
|
-
// HookNotFoundError(hook.token) so `.token` matches the
|
|
246
|
-
// pre-fast-path contract, where resumeHook threw
|
|
247
|
-
// `HookNotFoundError(hook.token)` after its own terminal check.
|
|
248
|
-
// The specific error depends on the World:
|
|
249
|
-
// - a genuinely missing hook maps to HookNotFoundError (keyed on
|
|
250
|
-
// the event correlationId / hook ID);
|
|
251
|
-
// - a terminal run on Vercel rejects hook_received with 404, which
|
|
252
|
-
// world-vercel maps to HookNotFoundError;
|
|
253
|
-
// - a terminal run on world-local / world-postgres rejects with
|
|
254
|
-
// RunExpiredError.
|
|
255
|
-
// EntityConflictError (HTTP 409) is kept for compatibility with
|
|
256
|
-
// older / conflict-shaped rejection behavior.
|
|
257
|
-
if (HookNotFoundError.is(err) ||
|
|
258
|
-
EntityConflictError.is(err) ||
|
|
259
|
-
RunExpiredError.is(err)) {
|
|
260
|
-
throw new HookNotFoundError(hook.token);
|
|
261
|
-
}
|
|
262
|
-
throw err;
|
|
263
|
-
}
|
|
264
292
|
span?.setAttributes({
|
|
265
293
|
...Attribute.WorkflowName(resumeContext.workflowName),
|
|
266
294
|
});
|
|
267
295
|
// Link to the run-origin context from the stored trace carrier
|
|
268
|
-
// (skipped when absent or invalid).
|
|
296
|
+
// (skipped when absent or invalid). Resolved before dispatch so both
|
|
297
|
+
// the sequential and parallel paths attach it.
|
|
269
298
|
const originLink = await linkToTraceCarrier(resumeContext.traceCarrier);
|
|
270
299
|
if (originLink) {
|
|
271
300
|
span?.addLink?.(originLink);
|
|
272
301
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}, {
|
|
302
|
+
const eventData = {
|
|
303
|
+
...(v1Compat ? {} : { token: hook.token }),
|
|
304
|
+
payload: dehydratedPayload,
|
|
305
|
+
};
|
|
306
|
+
const queueName = getWorkflowQueueName(resumeContext.workflowName);
|
|
307
|
+
const queueOptions = {
|
|
280
308
|
deploymentId: resumeContext.deploymentId,
|
|
281
309
|
specVersion: resumeContext.runSpecVersion ?? SPEC_VERSION_LEGACY,
|
|
310
|
+
};
|
|
311
|
+
// Decide whether to parallelize the `hook_received` write and the queue
|
|
312
|
+
// publish. The fast path is only safe when EVERY precondition holds; the
|
|
313
|
+
// first that fails names the fallback reason (emitted as a span
|
|
314
|
+
// attribute for observability, and to make "why did this run sequential"
|
|
315
|
+
// answerable in production). All conditions:
|
|
316
|
+
//
|
|
317
|
+
// - kill switch: `WORKFLOW_DISABLE_LAZY_HOOK_RESUME` forces sequential
|
|
318
|
+
// if the fast path ever misbehaves. It is an SDK-deployment env var,
|
|
319
|
+
// so changing it generally requires redeploying the workflow
|
|
320
|
+
// deployment. (The backend can independently drop new resumes to the
|
|
321
|
+
// sequential path fleet-wide by ceasing to attest dedup support on
|
|
322
|
+
// the by-token lookup — see the backend-dedup condition below.)
|
|
323
|
+
// - backend dedup: the live backend must enforce the
|
|
324
|
+
// `(runId, resumeId)` constraint, or the two writers would commit two
|
|
325
|
+
// `hook_received` events. Fail closed. Attested by EITHER a fresh,
|
|
326
|
+
// response-only `hook.resumeCapabilities.hookResumeDedupVersion` from
|
|
327
|
+
// the by-token lookup (world-vercel — recomputed every read, so a
|
|
328
|
+
// server rollback or kill switch drops to sequential immediately) OR
|
|
329
|
+
// the static `world.capabilities.hookResumeDedup` (world-local, whose
|
|
330
|
+
// adapter and backend ship together). The response-only capability is
|
|
331
|
+
// trusted ONLY when the hook was looked up by token during this
|
|
332
|
+
// resume (`hookResumeCapabilitiesAreFresh`); a Hook object handed in
|
|
333
|
+
// by a public caller may carry a capability cached before a rollback,
|
|
334
|
+
// so it is ignored and the path falls back to sequential.
|
|
335
|
+
// - consumer support: the target run's deployment must re-ensure the
|
|
336
|
+
// event from `hookInput` on replay. Attested by the run's explicit
|
|
337
|
+
// `hookResumeInputVersion` execution-context marker (mirrored onto
|
|
338
|
+
// resumeContext), NOT a version-compare against a predicted release
|
|
339
|
+
// cutoff. Absent → a lost producer write would be a lost resume.
|
|
340
|
+
// - not legacy: v1Compat runs omit `token` from the producer's event
|
|
341
|
+
// body but the consumer's re-ensure always includes it, so the two
|
|
342
|
+
// writers would disagree on the event body. Legacy stays sequential.
|
|
343
|
+
// - CBOR transport: the run must use CBOR queue transport so the binary
|
|
344
|
+
// payload survives the queue message.
|
|
345
|
+
// - raw bytes: the dehydrated payload must be a `Uint8Array` (the
|
|
346
|
+
// content digest that keys the dedup constraint is over these bytes).
|
|
347
|
+
// - size: a payload above the queue's message ceiling would fail the
|
|
348
|
+
// publish — which, on the parallel path, would persist the event but
|
|
349
|
+
// never re-trigger the run — so oversized payloads stay sequential
|
|
350
|
+
// (their queue message carries only the run ID).
|
|
351
|
+
const parallelResumeDisabled = process.env.WORKFLOW_DISABLE_LAZY_HOOK_RESUME === '1';
|
|
352
|
+
// Backend dedup is supported when EITHER the live server attests it
|
|
353
|
+
// fresh on this by-token hook (world-vercel: response-only, recomputed
|
|
354
|
+
// every read, so rollback/kill-switch take effect immediately) OR the
|
|
355
|
+
// static world capability is set (world-local: adapter + backend ship
|
|
356
|
+
// together). Both are re-evaluated per resume, so every rollout and
|
|
357
|
+
// rollback direction degrades safely to the sequential path.
|
|
358
|
+
const backendDedupSupported = (hookResumeCapabilitiesAreFresh
|
|
359
|
+
? (hook.resumeCapabilities?.hookResumeDedupVersion ?? 0)
|
|
360
|
+
: 0) >= HOOK_RESUME_DEDUP_VERSION ||
|
|
361
|
+
world.capabilities?.hookResumeDedup === true;
|
|
362
|
+
const fallbackReason = parallelResumeDisabled
|
|
363
|
+
? 'disabled'
|
|
364
|
+
: !backendDedupSupported
|
|
365
|
+
? 'backend_unsupported'
|
|
366
|
+
: (resumeContext.hookResumeInputVersion ?? 0) <
|
|
367
|
+
HOOK_RESUME_INPUT_VERSION
|
|
368
|
+
? 'consumer_unsupported'
|
|
369
|
+
: v1Compat
|
|
370
|
+
? 'legacy'
|
|
371
|
+
: (resumeContext.runSpecVersion ?? 0) <
|
|
372
|
+
SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT
|
|
373
|
+
? 'non_cbor_transport'
|
|
374
|
+
: !(dehydratedPayload instanceof Uint8Array)
|
|
375
|
+
? 'non_bytes'
|
|
376
|
+
: dehydratedPayload.byteLength >
|
|
377
|
+
MAX_INLINE_RESUME_PAYLOAD_BYTES
|
|
378
|
+
? 'oversized'
|
|
379
|
+
: null;
|
|
380
|
+
const useParallelResume = fallbackReason === null;
|
|
381
|
+
span?.setAttributes({
|
|
382
|
+
'workflow.hook.resume_strategy': useParallelResume
|
|
383
|
+
? 'parallel'
|
|
384
|
+
: 'sequential',
|
|
385
|
+
...(fallbackReason
|
|
386
|
+
? { 'workflow.hook.resume_fallback_reason': fallbackReason }
|
|
387
|
+
: {}),
|
|
282
388
|
});
|
|
283
|
-
|
|
389
|
+
// Re-key any "hook can no longer be received" rejection to
|
|
390
|
+
// HookNotFoundError(hook.token) so `.token` matches the pre-fast-path
|
|
391
|
+
// contract, where resumeHook threw `HookNotFoundError(hook.token)`
|
|
392
|
+
// after its own terminal check. The specific error depends on the
|
|
393
|
+
// World:
|
|
394
|
+
// - a genuinely missing hook maps to HookNotFoundError (keyed on the
|
|
395
|
+
// event correlationId / hook ID);
|
|
396
|
+
// - a terminal run on Vercel rejects hook_received with 404, which
|
|
397
|
+
// world-vercel maps to HookNotFoundError;
|
|
398
|
+
// - a terminal run on world-local / world-postgres rejects with
|
|
399
|
+
// RunExpiredError.
|
|
400
|
+
//
|
|
401
|
+
// On the SEQUENTIAL path an EntityConflictError (HTTP 409) is also
|
|
402
|
+
// treated as "hook gone" for historical / conflict-shaped-rejection
|
|
403
|
+
// compatibility: there is no queue message in flight, so a conflict has
|
|
404
|
+
// no re-ensuring consumer to converge on. The PARALLEL path handles 409
|
|
405
|
+
// differently (see below) — it published the queue message before the
|
|
406
|
+
// conflict, so the consumer will converge the event.
|
|
407
|
+
const isHookGoneError = (err) => HookNotFoundError.is(err) ||
|
|
408
|
+
EntityConflictError.is(err) ||
|
|
409
|
+
RunExpiredError.is(err);
|
|
410
|
+
if (!useParallelResume) {
|
|
411
|
+
// Sequential path: create a hook_received event, then re-trigger.
|
|
412
|
+
try {
|
|
413
|
+
await world.events.create(hook.runId, {
|
|
414
|
+
eventType: 'hook_received',
|
|
415
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
416
|
+
correlationId: hook.hookId,
|
|
417
|
+
eventData,
|
|
418
|
+
}, { v1Compat });
|
|
419
|
+
}
|
|
420
|
+
catch (err) {
|
|
421
|
+
if (isHookGoneError(err)) {
|
|
422
|
+
throw new HookNotFoundError(hook.token);
|
|
423
|
+
}
|
|
424
|
+
throw err;
|
|
425
|
+
}
|
|
426
|
+
await world.queue(queueName, {
|
|
427
|
+
runId: hook.runId,
|
|
428
|
+
traceCarrier: resumeContext.traceCarrier ?? undefined,
|
|
429
|
+
}, queueOptions);
|
|
430
|
+
return hook;
|
|
431
|
+
}
|
|
432
|
+
// Parallel fast path. A stable idempotency key ties the direct write to
|
|
433
|
+
// the queue consumer's re-ensure; the payload digest lets the server
|
|
434
|
+
// detect key reuse across byte-identical payloads.
|
|
435
|
+
const resumeId = generateResumeId();
|
|
436
|
+
const payloadDigest = await computeResumePayloadDigest(dehydratedPayload);
|
|
437
|
+
span?.setAttributes({ 'workflow.hook.resume_id': resumeId });
|
|
438
|
+
const [eventResult, queueResult] = await Promise.allSettled([
|
|
439
|
+
world.events.create(hook.runId, {
|
|
440
|
+
eventType: 'hook_received',
|
|
441
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
442
|
+
correlationId: hook.hookId,
|
|
443
|
+
eventData,
|
|
444
|
+
}, { v1Compat, resumeId, resumePayloadDigest: payloadDigest }),
|
|
445
|
+
world.queue(queueName, {
|
|
446
|
+
runId: hook.runId,
|
|
447
|
+
traceCarrier: resumeContext.traceCarrier ?? undefined,
|
|
448
|
+
hookInput: {
|
|
449
|
+
resumeId,
|
|
450
|
+
hookId: hook.hookId,
|
|
451
|
+
token: hook.token,
|
|
452
|
+
payload: dehydratedPayload,
|
|
453
|
+
payloadDigest,
|
|
454
|
+
},
|
|
455
|
+
}, queueOptions),
|
|
456
|
+
]);
|
|
457
|
+
// Queue failure is always fatal — the run was not re-triggered, so no
|
|
458
|
+
// consumer will re-ensure the event.
|
|
459
|
+
if (queueResult.status === 'rejected') {
|
|
460
|
+
throw queueResult.reason;
|
|
461
|
+
}
|
|
462
|
+
// Set when the direct write did not land but the queue dispatch did, so
|
|
463
|
+
// the consumer materializes the event before replay. Surfaced to the
|
|
464
|
+
// caller as `ResumedHook.resilientResume` and on the span.
|
|
465
|
+
let resilientResume = false;
|
|
466
|
+
if (eventResult.status === 'rejected') {
|
|
467
|
+
const err = eventResult.reason;
|
|
468
|
+
if (HookNotFoundError.is(err) || RunExpiredError.is(err)) {
|
|
469
|
+
// The hook's run has genuinely ended: surface the same contract as
|
|
470
|
+
// the sequential path. The queue message already went out, but the
|
|
471
|
+
// consumer's re-ensure will also reject against the terminal run
|
|
472
|
+
// and no-op, so the workflow does not resume.
|
|
473
|
+
throw new HookNotFoundError(hook.token);
|
|
474
|
+
}
|
|
475
|
+
if (EntityConflictError.is(err) || isRetryableWorldError(err)) {
|
|
476
|
+
// Resilient. Two shapes reach here, both non-terminal:
|
|
477
|
+
// - EntityConflict (409): this write raced its own re-ensuring
|
|
478
|
+
// consumer (or a redrive) on the shared `resumeId` — the run is
|
|
479
|
+
// NOT gone, and the consumer converges on the one committed
|
|
480
|
+
// event. Unlike the sequential path, a 409 here is expected
|
|
481
|
+
// concurrency, not a vanished hook.
|
|
482
|
+
// - 429 / 5xx / transport: a transient backend failure.
|
|
483
|
+
// In both cases the run WAS re-triggered via the queue and the
|
|
484
|
+
// consumer idempotently ensures the hook_received before replay, so
|
|
485
|
+
// swallow rather than failing the caller.
|
|
486
|
+
//
|
|
487
|
+
// Producer telemetry: record that the direct write did not land but
|
|
488
|
+
// the resume is still guaranteed via queue-delivered `hookInput`.
|
|
489
|
+
// This is the operational signal that the recovery path fired,
|
|
490
|
+
// surfaced both on the span and as the public `resilientResume`
|
|
491
|
+
// flag on the returned hook (the resume outcome is otherwise
|
|
492
|
+
// identical to the happy path from the caller's perspective).
|
|
493
|
+
resilientResume = true;
|
|
494
|
+
span?.setAttributes({
|
|
495
|
+
...Attribute.HookResilientResume(true),
|
|
496
|
+
'workflow.hook.resume_event_write_recovered': true,
|
|
497
|
+
'workflow.hook.resume_event_write_error': err instanceof Error ? err.name : 'unknown',
|
|
498
|
+
});
|
|
499
|
+
runtimeLogger.warn('Hook resume event write failed, but the run was re-triggered via ' +
|
|
500
|
+
'the queue. The hook_received event will be ensured by the ' +
|
|
501
|
+
'queue consumer.', {
|
|
502
|
+
workflowRunId: hook.runId,
|
|
503
|
+
hookId: hook.hookId,
|
|
504
|
+
resumeId,
|
|
505
|
+
error: err instanceof Error ? err.message : String(err),
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
throw err;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return (resilientResume ? { ...hook, resilientResume: true } : hook);
|
|
284
513
|
}
|
|
285
514
|
catch (err) {
|
|
286
515
|
span?.setAttributes({
|
|
@@ -359,7 +588,12 @@ export async function resumeWebhook(token, request) {
|
|
|
359
588
|
// No `respondWith` value implies the default behavior of returning a 202
|
|
360
589
|
response = new Response(null, { status: 202 });
|
|
361
590
|
}
|
|
362
|
-
|
|
591
|
+
// `hook` was just fetched via `getHookByTokenWithKey` (a fresh by-token
|
|
592
|
+
// lookup) above, so its response-only `resumeCapabilities` reflects the live
|
|
593
|
+
// backend — call the internal implementation with the fresh attestation so
|
|
594
|
+
// the parallel fast path stays available without a second GET. (The public
|
|
595
|
+
// `resumeHook` never sets this, so a caller cannot forge it.)
|
|
596
|
+
await resumeHookImpl(hook, request, encryptionKey, true);
|
|
363
597
|
if (responseReadable) {
|
|
364
598
|
// Wait for the readable stream to emit one chunk,
|
|
365
599
|
// which is the `Response` object
|
|
@@ -377,4 +611,4 @@ export async function resumeWebhook(token, request) {
|
|
|
377
611
|
}
|
|
378
612
|
return response;
|
|
379
613
|
}
|
|
380
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzdW1lLWhvb2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVudGltZS9yZXN1bWUtaG9vay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLFdBQVcsRUFDWCxpQkFBaUIsRUFDakIsZUFBZSxFQUNmLG9CQUFvQixHQUNyQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFHTCxtQkFBbUIsRUFDbkIsMkJBQTJCLEVBQzNCLG9CQUFvQixFQUNwQixtQkFBbUIsRUFDbkIsaUNBQWlDLEdBR2xDLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDeEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDN0MsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDdEQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDdEUsT0FBTyxFQUNMLHdCQUF3QixFQUN4QixvQkFBb0IsRUFFcEIsbUJBQW1CLEVBQ25CLE1BQU0sR0FDUCxNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMxRCxPQUFPLEtBQUssU0FBUyxNQUFNLHNDQUFzQyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxLQUFLLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDbkQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3BELE9BQU8sRUFBRSxhQUFhLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFjN0Qsd0ZBQXdGO0FBQ3hGLFNBQVMsb0JBQW9CLENBQUMsR0FBZ0I7SUFDNUMsTUFBTSxXQUFXLEdBQUcsR0FBRyxDQUFDLGdCQUFnQixFQUFFLG1CQUFtQixDQUFDO0lBQzlELE1BQU0sWUFBWSxHQUFHLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxZQUFZLENBQUM7SUFDeEQsT0FBTztRQUNMLFlBQVksRUFBRSxHQUFHLENBQUMsWUFBWTtRQUM5QixZQUFZLEVBQUUsR0FBRyxDQUFDLFlBQVk7UUFDOUIsY0FBYyxFQUFFLEdBQUcsQ0FBQyxXQUFXO1FBQy9CLG1CQUFtQixFQUNqQixPQUFPLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsU0FBUztRQUMzRCxZQUFZLEVBQ1YsWUFBWSxJQUFJLE9BQU8sWUFBWSxLQUFLLFFBQVE7WUFDOUMsQ0FBQyxDQUFFLFlBQWtEO1lBQ3JELENBQUMsQ0FBQyxTQUFTO1FBQ2YsbUJBQW1CLEVBQUUsR0FBRyxDQUFDLG1CQUFtQjtLQUM3QyxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsS0FBSyxVQUFVLHFCQUFxQixDQUFDLElBQVU7SUFDN0MsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDdkIsT0FBTyxFQUFFLGFBQWEsRUFBRSxJQUFJLENBQUMsYUFBYSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsQ0FBQztJQUMvRCxDQUFDO0lBQ0QsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLE1BQU0sWUFBWSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM5RCxPQUFPO1FBQ0wsYUFBYSxFQUFFLG9CQUFvQixDQUFDLEdBQUcsQ0FBQztRQUN4QyxNQUFNLEVBQUUsY0FBYztRQUN0QixHQUFHO0tBQ0osQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxLQUFLLFVBQVUsd0JBQXdCLENBQ3JDLElBQVUsRUFDVixJQUFvQjtJQUVwQixNQUFNLEtBQUssR0FBRyxNQUFNLFlBQVksRUFBRSxDQUFDO0lBQ25DLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHO1FBQ3JCLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxzQkFBc0IsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7UUFDaEQsQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLHNCQUFzQixFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRTtZQUMvQyxZQUFZLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxZQUFZO1NBQzlDLENBQUMsQ0FBQztJQUNQLE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQ3RELENBQUM7QUFFRCxLQUFLLFVBQVUscUJBQXFCLENBQUMsS0FBYTtJQUloRCxNQUFNLEtBQUssR0FBRyxNQUFNLFlBQVksRUFBRSxDQUFDO0lBQ25DLE1BQU0sSUFBSSxHQUFHLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFakQsMEVBQTBFO0lBQzFFLDZFQUE2RTtJQUM3RSw4RUFBOEU7SUFDOUUsc0VBQXNFO0lBQ3RFLDJFQUEyRTtJQUMzRSw2RUFBNkU7SUFDN0Usd0VBQXdFO0lBQ3hFLGlFQUFpRTtJQUNqRSxJQUFJLGFBQXFDLENBQUM7SUFDMUMsSUFBSSxPQUFPLElBQUksQ0FBQyxRQUFRLEtBQUssV0FBVyxFQUFFLENBQUM7UUFDekMsTUFBTSxJQUFJLEdBQUcsTUFBTSxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMvQyx5RUFBeUU7UUFDekUsaUVBQWlFO1FBQ2pFLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHO1lBQ3JCLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxzQkFBc0IsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7WUFDaEQsQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLHNCQUFzQixFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRTtnQkFDL0MsWUFBWSxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWTthQUM5QyxDQUFDLENBQUM7UUFDUCxhQUFhLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7UUFDeEUsSUFBSSxDQUFDLFFBQVEsR0FBRyxNQUFNLG9CQUFvQixDQUN4QyxJQUFJLENBQUMsUUFBZSxFQUNwQixJQUFJLENBQUMsS0FBSyxFQUNWLGFBQWEsQ0FDZCxDQUFDO0lBQ0osQ0FBQztJQUNELE9BQU8sRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLENBQUM7QUFDakMsQ0FBQztBQUVEOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsY0FBYyxDQUFDLEtBQWE7SUFDaEQsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLE1BQU0scUJBQXFCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDcEQsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E0Qkc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLFVBQVUsQ0FDOUIsV0FBMEIsRUFDMUIsT0FBVSxFQUNWLHFCQUFrQztJQUVsQyxPQUFPLE1BQU0sV0FBVyxDQUFDLEdBQUcsRUFBRTtRQUM1QixPQUFPLEtBQUssQ0FBQyxhQUFhLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxFQUFFO1lBQ3pDLE1BQU0sS0FBSyxHQUFHLE1BQU0sWUFBWSxFQUFFLENBQUM7WUFFbkMsSUFBSSxDQUFDO2dCQUNILE1BQU0sSUFBSSxHQUNSLE9BQU8sV0FBVyxLQUFLLFFBQVE7b0JBQzdCLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQztvQkFDM0MsQ0FBQyxDQUFDLFdBQVcsQ0FBQztnQkFFbEIsTUFBTSxJQUFJLEdBQUcsTUFBTSxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDL0MsTUFBTSxFQUFFLGFBQWEsRUFBRSxHQUFHLElBQUksQ0FBQztnQkFFL0IsSUFBSSxFQUFFLGFBQWEsQ0FBQztvQkFDbEIsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7b0JBQ2xDLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO29CQUNoQyxHQUFHLFNBQVMsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztvQkFDdEMscUNBQXFDLEVBQUUsSUFBSSxDQUFDLE1BQU07aUJBQ25ELENBQUMsQ0FBQztnQkFFSCxtRUFBbUU7Z0JBQ25FLCtEQUErRDtnQkFDL0QsdUVBQXVFO2dCQUN2RSxxRUFBcUU7Z0JBQ3JFLHVFQUF1RTtnQkFDdkUsaUVBQWlFO2dCQUNqRSxJQUFJLElBQUksQ0FBQyxHQUFHLElBQUksMkJBQTJCLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO29CQUM3RCxNQUFNLElBQUksaUJBQWlCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUMxQyxDQUFDO2dCQUVELDhEQUE4RDtnQkFDOUQsb0VBQW9FO2dCQUNwRSxpRUFBaUU7Z0JBQ2pFLDJEQUEyRDtnQkFDM0QsaUVBQWlFO2dCQUNqRSxNQUFNLFlBQVksR0FBRyxrQkFBa0IsQ0FDckMsYUFBYSxDQUFDLG1CQUFtQixDQUNsQyxDQUFDO2dCQUVGLG1FQUFtRTtnQkFDbkUsRUFBRTtnQkFDRix1RUFBdUU7Z0JBQ3ZFLHNFQUFzRTtnQkFDdEUscUVBQXFFO2dCQUNyRSxrRUFBa0U7Z0JBQ2xFLG1FQUFtRTtnQkFDbkUsZ0RBQWdEO2dCQUNoRCxFQUFFO2dCQUNGLG9FQUFvRTtnQkFDcEUsaUVBQWlFO2dCQUNqRSx1REFBdUQ7Z0JBQ3ZELEVBQUU7Z0JBQ0Ysb0VBQW9FO2dCQUNwRSx3RUFBd0U7Z0JBQ3hFLGlFQUFpRTtnQkFDakUsc0VBQXNFO2dCQUN0RSx3RUFBd0U7Z0JBQ3hFLGtFQUFrRTtnQkFDbEUsa0JBQWtCO2dCQUNsQixJQUFJLFVBQWtDLENBQUM7Z0JBQ3ZDLE1BQU0sWUFBWSxHQUFHLHFCQUFxQjtvQkFDeEMsQ0FBQyxDQUFDLGdFQUFnRTt3QkFDaEUsOERBQThEO3dCQUM5RCw0Q0FBNEM7d0JBQzVDLFNBQVM7b0JBQ1gsQ0FBQyxDQUFDLGtCQUFrQixDQUFDLGFBQWEsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO2dCQUUxRCxJQUFJLFlBQVksRUFBRSxDQUFDO29CQUNqQixVQUFVLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUNwQyxDQUFDO3FCQUFNLENBQUM7b0JBQ04sMERBQTBEO29CQUMxRCw2REFBNkQ7b0JBQzdELDRCQUE0QjtvQkFDNUIsSUFBSSxhQUFhLEdBQ2YscUJBQXFCO3dCQUNyQixDQUFDLE1BQU0sd0JBQXdCLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7b0JBQy9DLElBQ0UsQ0FBQyxZQUFZLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDLFNBQVMsQ0FBQyxFQUNqRSxDQUFDO3dCQUNELGFBQWEsR0FBRyxTQUFTLENBQUM7b0JBQzVCLENBQUM7b0JBQ0QsVUFBVSxHQUFHLGFBQWEsQ0FBQztnQkFDN0IsQ0FBQztnQkFFRCxtRUFBbUU7Z0JBQ25FLHNEQUFzRDtnQkFDdEQsTUFBTSxXQUFXLEdBQ2YsQ0FBQyxhQUFhLENBQUMsY0FBYyxJQUFJLENBQUMsQ0FBQztvQkFDakMsaUNBQWlDO29CQUNuQyxZQUFZLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUU5RCxvQ0FBb0M7Z0JBQ3BDLE1BQU0sR0FBRyxHQUFtQixFQUFFLENBQUM7Z0JBQy9CLE1BQU0sUUFBUSxHQUFHLG1CQUFtQixDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFDdkQsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLHdCQUF3QixDQUN0RCxPQUFPLEVBQ1AsSUFBSSxDQUFDLEtBQUssRUFDVixVQUFVLEVBQ1YsR0FBRyxFQUNILFVBQVUsRUFDVixRQUFRLEVBQ1IsWUFBWSxDQUFDLGlCQUFpQixFQUM5QixXQUFXLENBQ1osQ0FBQztnQkFDRiw4REFBOEQ7Z0JBQzlELCtEQUErRDtnQkFDL0Qsa0VBQWtFO2dCQUNsRSw2Q0FBNkM7Z0JBQzdDLG9FQUFvRTtnQkFDcEUsMkNBQTJDO2dCQUMzQyxhQUFhLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFO29CQUN0QyxJQUFJLEdBQUcsS0FBSyxTQUFTO3dCQUFFLE9BQU87b0JBQzlCLGFBQWEsQ0FBQyxJQUFJLENBQUMsNkNBQTZDLEVBQUU7d0JBQ2hFLGFBQWEsRUFBRSxJQUFJLENBQUMsS0FBSzt3QkFDekIsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO3dCQUNuQixLQUFLLEVBQUUsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQztxQkFDeEQsQ0FBQyxDQUFDO2dCQUNMLENBQUMsQ0FBQyxDQUFDO2dCQUVILGdEQUFnRDtnQkFDaEQsSUFBSSxDQUFDO29CQUNILE1BQU0sS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQ3ZCLElBQUksQ0FBQyxLQUFLLEVBQ1Y7d0JBQ0UsU0FBUyxFQUFFLGVBQWU7d0JBQzFCLFdBQVcsRUFBRSxvQkFBb0I7d0JBQ2pDLGFBQWEsRUFBRSxJQUFJLENBQUMsTUFBTTt3QkFDMUIsU0FBUyxFQUFFOzRCQUNULEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDOzRCQUMxQyxPQUFPLEVBQUUsaUJBQWlCO3lCQUMzQjtxQkFDRixFQUNELEVBQUUsUUFBUSxFQUFFLENBQ2IsQ0FBQztnQkFDSixDQUFDO2dCQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7b0JBQ2IsMkRBQTJEO29CQUMzRCx3REFBd0Q7b0JBQ3hELGlEQUFpRDtvQkFDakQsZ0VBQWdFO29CQUNoRSwyQ0FBMkM7b0JBQzNDLG1FQUFtRTtvQkFDbkUsMENBQTBDO29CQUMxQyxxRUFBcUU7b0JBQ3JFLDhDQUE4QztvQkFDOUMsa0VBQWtFO29CQUNsRSx1QkFBdUI7b0JBQ3ZCLGdFQUFnRTtvQkFDaEUsOENBQThDO29CQUM5QyxJQUNFLGlCQUFpQixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7d0JBQ3pCLG1CQUFtQixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7d0JBQzNCLGVBQWUsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQ3ZCLENBQUM7d0JBQ0QsTUFBTSxJQUFJLGlCQUFpQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDMUMsQ0FBQztvQkFDRCxNQUFNLEdBQUcsQ0FBQztnQkFDWixDQUFDO2dCQUVELElBQUksRUFBRSxhQUFhLENBQUM7b0JBQ2xCLEdBQUcsU0FBUyxDQUFDLFlBQVksQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDO2lCQUN0RCxDQUFDLENBQUM7Z0JBRUgsK0RBQStEO2dCQUMvRCxvQ0FBb0M7Z0JBQ3BDLE1BQU0sVUFBVSxHQUFHLE1BQU0sa0JBQWtCLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUN4RSxJQUFJLFVBQVUsRUFBRSxDQUFDO29CQUNmLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDOUIsQ0FBQztnQkFFRCwrREFBK0Q7Z0JBQy9ELGlEQUFpRDtnQkFDakQsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUNmLG9CQUFvQixDQUFDLGFBQWEsQ0FBQyxZQUFZLENBQUMsRUFDaEQ7b0JBQ0UsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLO29CQUNqQix5REFBeUQ7b0JBQ3pELFlBQVksRUFBRSxhQUFhLENBQUMsWUFBWSxJQUFJLFNBQVM7aUJBQ3RCLEVBQ2pDO29CQUNFLFlBQVksRUFBRSxhQUFhLENBQUMsWUFBWTtvQkFDeEMsV0FBVyxFQUFFLGFBQWEsQ0FBQyxjQUFjLElBQUksbUJBQW1CO2lCQUNqRSxDQUNGLENBQUM7Z0JBRUYsT0FBTyxJQUFJLENBQUM7WUFDZCxDQUFDO1lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztnQkFDYixJQUFJLEVBQUUsYUFBYSxDQUFDO29CQUNsQixHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQ3BCLE9BQU8sV0FBVyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUNsRTtvQkFDRCxHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDO2lCQUM5QixDQUFDLENBQUM7Z0JBQ0gsTUFBTSxHQUFHLENBQUM7WUFDWixDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWtDRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsYUFBYSxDQUNqQyxLQUFhLEVBQ2IsT0FBZ0I7SUFFaEIsTUFBTSxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsR0FBRyxNQUFNLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRW5FLHdEQUF3RDtJQUN4RCxpRUFBaUU7SUFDakUsdUVBQXVFO0lBQ3ZFLHdEQUF3RDtJQUN4RCxJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssS0FBSyxFQUFFLENBQUM7UUFDN0IsTUFBTSxJQUFJLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFRCxJQUFJLFFBQThCLENBQUM7SUFDbkMsSUFBSSxnQkFBc0QsQ0FBQztJQUMzRCxJQUNFLElBQUksQ0FBQyxRQUFRO1FBQ2IsT0FBTyxJQUFJLENBQUMsUUFBUSxLQUFLLFFBQVE7UUFDakMsYUFBYSxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQzlCLENBQUM7UUFDRCxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQzNDLE1BQU0sRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLEdBQUcsSUFBSSxlQUFlLEVBQXNCLENBQUM7WUFDekUsZ0JBQWdCLEdBQUcsUUFBUSxDQUFDO1lBRTVCLHVFQUF1RTtZQUN2RSxtRUFBbUU7WUFDbEUsT0FBZSxDQUFDLHlCQUF5QixDQUFDLEdBQUcsUUFBUSxDQUFDO1FBQ3pELENBQUM7YUFBTSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxZQUFZLFFBQVEsRUFBRSxDQUFDO1lBQ3pELFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQztRQUN2QyxDQUFDO2FBQU0sQ0FBQztZQUNOLE1BQU0sSUFBSSxvQkFBb0IsQ0FDNUIsa0NBQWtDLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLEVBQzdELEVBQUUsSUFBSSxFQUFFLFdBQVcsQ0FBQyxrQ0FBa0MsRUFBRSxDQUN6RCxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7U0FBTSxDQUFDO1FBQ04seUVBQXlFO1FBQ3pFLFFBQVEsR0FBRyxJQUFJLFFBQVEsQ0FBQyxJQUFJLEVBQUUsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRUQsTUFBTSxVQUFVLENBQUMsSUFBSSxFQUFFLE9BQU8sRUFBRSxhQUFhLENBQUMsQ0FBQztJQUUvQyxJQUFJLGdCQUFnQixFQUFFLENBQUM7UUFDckIsa0RBQWtEO1FBQ2xELGlDQUFpQztRQUNqQyxNQUFNLE1BQU0sR0FBRyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUM1QyxNQUFNLEtBQUssR0FBRyxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNsQyxJQUFJLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNoQixRQUFRLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQztRQUN6QixDQUFDO1FBQ0QsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ2xCLENBQUM7SUFFRCxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDZCxNQUFNLElBQUksb0JBQW9CLENBQUMsc0NBQXNDLEVBQUU7WUFDckUsSUFBSSxFQUFFLFdBQVcsQ0FBQyx5QkFBeUI7U0FDNUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBFbnRpdHlDb25mbGljdEVycm9yLFxuICBFUlJPUl9TTFVHUyxcbiAgSG9va05vdEZvdW5kRXJyb3IsXG4gIFJ1bkV4cGlyZWRFcnJvcixcbiAgV29ya2Zsb3dSdW50aW1lRXJyb3IsXG59IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHtcbiAgdHlwZSBIb29rLFxuICB0eXBlIEhvb2tSZXN1bWVDb250ZXh0LFxuICBpc0xlZ2FjeVNwZWNWZXJzaW9uLFxuICBpc1Rlcm1pbmFsV29ya2Zsb3dSdW5TdGF0dXMsXG4gIFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICBTUEVDX1ZFUlNJT05fTEVHQUNZLFxuICBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ09NUFJFU1NJT04sXG4gIHR5cGUgV29ya2Zsb3dJbnZva2VQYXlsb2FkLFxuICB0eXBlIFdvcmtmbG93UnVuLFxufSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgZ2V0UnVuQ2FwYWJpbGl0aWVzIH0gZnJvbSAnLi4vY2FwYWJpbGl0aWVzLmpzJztcbmltcG9ydCB7IGltcG9ydEtleSB9IGZyb20gJy4uL2VuY3J5cHRpb24uanMnO1xuaW1wb3J0IHsgcnVudGltZUxvZ2dlciB9IGZyb20gJy4uL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBkZWNvZGVSdW5QdWJsaWNLZXkgfSBmcm9tICcuLi9zZWFsZWQtYm94LmpzJztcbmltcG9ydCB7IGRlcml2ZVJ1blBheWxvYWRLZXlzIH0gZnJvbSAnLi4vc2VyaWFsaXphdGlvbi9lbmNyeXB0aW9uLmpzJztcbmltcG9ydCB7XG4gIGRlaHlkcmF0ZVN0ZXBSZXR1cm5WYWx1ZSxcbiAgaHlkcmF0ZVN0ZXBBcmd1bWVudHMsXG4gIHR5cGUgUGF5bG9hZEtleSxcbiAgU2VyaWFsaXphdGlvbkZvcm1hdCxcbiAgc2VhbFRvLFxufSBmcm9tICcuLi9zZXJpYWxpemF0aW9uLmpzJztcbmltcG9ydCB7IFdFQkhPT0tfUkVTUE9OU0VfV1JJVEFCTEUgfSBmcm9tICcuLi9zeW1ib2xzLmpzJztcbmltcG9ydCAqIGFzIEF0dHJpYnV0ZSBmcm9tICcuLi90ZWxlbWV0cnkvc2VtYW50aWMtY29udmVudGlvbnMuanMnO1xuaW1wb3J0IHsgbGlua1RvVHJhY2VDYXJyaWVyLCB0cmFjZSB9IGZyb20gJy4uL3RlbGVtZXRyeS5qcyc7XG5pbXBvcnQgeyBnZXRXb3JsZExhenkgfSBmcm9tICcuL2dldC13b3JsZC1sYXp5LmpzJztcbmltcG9ydCB7IGdldFdvcmtmbG93UXVldWVOYW1lIH0gZnJvbSAnLi9oZWxwZXJzLmpzJztcbmltcG9ydCB7IHNhZmVXYWl0VW50aWwsIHdhaXRlZFVudGlsIH0gZnJvbSAnLi93YWl0LXVudGlsLmpzJztcblxuLyoqXG4gKiBUaGUgcmVzdW1lIGNvbnRleHQgZm9yIGEgaG9vayBwbHVzIHdoZXJlIGl0IGNhbWUgZnJvbS4gYHJ1bmAgaXMgcHJlc2VudCBvbmx5XG4gKiBvbiB0aGUgZmFsbGJhY2sgcGF0aCAocHJlLWByZXN1bWVDb250ZXh0YCBob29rcyksIHdoZXJlIGl0IGFsc28gY2FycmllcyB0aGVcbiAqIHJ1bidzIG11dGFibGUgc3RhdHVzIGZvciB0aGUgdGVybWluYWwtcnVuIGNoZWNrLiBLZXkgcmVzb2x1dGlvbiBpcyBrZXB0XG4gKiBzZXBhcmF0ZSBzbyBjYWxsZXJzIGNhbiBnYXRlIGl0IGJlaGluZCB0aGF0IGNoZWNrLlxuICovXG5pbnRlcmZhY2UgSG9va1Jlc3VtZUluZm8ge1xuICByZXN1bWVDb250ZXh0OiBIb29rUmVzdW1lQ29udGV4dDtcbiAgc291cmNlOiAnaG9vaycgfCAncnVuX2ZhbGxiYWNrJztcbiAgcnVuPzogV29ya2Zsb3dSdW47XG59XG5cbi8qKiBEZXJpdmUgYSByZXN1bWUgY29udGV4dCBmcm9tIGEgZnVsbCBydW4gKGZhbGxiYWNrIGZvciBwcmUtYHJlc3VtZUNvbnRleHRgIGhvb2tzKS4gKi9cbmZ1bmN0aW9uIHJlc3VtZUNvbnRleHRGcm9tUnVuKHJ1bjogV29ya2Zsb3dSdW4pOiBIb29rUmVzdW1lQ29udGV4dCB7XG4gIGNvbnN0IGNvcmVWZXJzaW9uID0gcnVuLmV4ZWN1dGlvbkNvbnRleHQ/LndvcmtmbG93Q29yZVZlcnNpb247XG4gIGNvbnN0IHRyYWNlQ2FycmllciA9IHJ1bi5leGVjdXRpb25Db250ZXh0Py50cmFjZUNhcnJpZXI7XG4gIHJldHVybiB7XG4gICAgZGVwbG95bWVudElkOiBydW4uZGVwbG95bWVudElkLFxuICAgIHdvcmtmbG93TmFtZTogcnVuLndvcmtmbG93TmFtZSxcbiAgICBydW5TcGVjVmVyc2lvbjogcnVuLnNwZWNWZXJzaW9uLFxuICAgIHdvcmtmbG93Q29yZVZlcnNpb246XG4gICAgICB0eXBlb2YgY29yZVZlcnNpb24gPT09ICdzdHJpbmcnID8gY29yZVZlcnNpb24gOiB1bmRlZmluZWQsXG4gICAgdHJhY2VDYXJyaWVyOlxuICAgICAgdHJhY2VDYXJyaWVyICYmIHR5cGVvZiB0cmFjZUNhcnJpZXIgPT09ICdvYmplY3QnXG4gICAgICAgID8gKHRyYWNlQ2FycmllciBhcyBIb29rUmVzdW1lQ29udGV4dFsndHJhY2VDYXJyaWVyJ10pXG4gICAgICAgIDogdW5kZWZpbmVkLFxuICAgIGVuY3J5cHRpb25QdWJsaWNLZXk6IHJ1bi5lbmNyeXB0aW9uUHVibGljS2V5LFxuICB9O1xufVxuXG4vKipcbiAqIFJlc29sdmUgcmVzdW1lIGNvbnRleHQgZm9yIGEgaG9vay4gVXNlcyB0aGUgc3RvcmVkIGByZXN1bWVDb250ZXh0YCB3aGVuXG4gKiBwcmVzZW50IChmYXN0IHBhdGgg4oCUIG5vIHJ1biByZWFkKTsgb3RoZXJ3aXNlIGZldGNoZXMgdGhlIHJ1biBhbmQgc3ludGhlc2l6ZXNcbiAqIGl0LiBEb2VzIE5PVCByZXNvbHZlIHRoZSBlbmNyeXB0aW9uIGtleSDigJQgY2FsbGVycyBkbyB0aGF0IHNlcGFyYXRlbHkuIE9ubHlcbiAqIHRoZSBmYWxsYmFjayBwYXRoIGNhbiBnYXRlIGtleSB3b3JrIGJlaGluZCBhIGxvY2FsIHRlcm1pbmFsLXJ1biBjaGVjayAoaXRcbiAqIGhhcyB0aGUgZmV0Y2hlZCBydW4pOyB0aGUgZmFzdCBwYXRoJ3Mgc3RvcmVkIGNvbnRleHQgY2FycmllcyBubyBzdGF0dXMsIHNvXG4gKiBzZWFsL3NlcmlhbGl6YXRpb24gd29yayBtYXkgcnVuIGJlZm9yZSB0aGUgcmVjZWl2aW5nIHNpZGUgcmVqZWN0c1xuICogYGhvb2tfcmVjZWl2ZWRgIGZvciBhbiBlbmRlZCBydW4uXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVIb29rUmVzdW1lSW5mbyhob29rOiBIb29rKTogUHJvbWlzZTxIb29rUmVzdW1lSW5mbz4ge1xuICBpZiAoaG9vay5yZXN1bWVDb250ZXh0KSB7XG4gICAgcmV0dXJuIHsgcmVzdW1lQ29udGV4dDogaG9vay5yZXN1bWVDb250ZXh0LCBzb3VyY2U6ICdob29rJyB9O1xuICB9XG4gIGNvbnN0IHJ1biA9IGF3YWl0IChhd2FpdCBnZXRXb3JsZExhenkoKSkucnVucy5nZXQoaG9vay5ydW5JZCk7XG4gIHJldHVybiB7XG4gICAgcmVzdW1lQ29udGV4dDogcmVzdW1lQ29udGV4dEZyb21SdW4ocnVuKSxcbiAgICBzb3VyY2U6ICdydW5fZmFsbGJhY2snLFxuICAgIHJ1bixcbiAgfTtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHRoZSBydW4ncyBzeW1tZXRyaWMga2V5IGZvciBhIHBheWxvYWQgV1JJVEUsIGFzIGEgYmFyZSBgQ3J5cHRvS2V5YFxuICogKGBpbXBvcnRLZXlgKSDigJQgdGhlIGBlbmNyYCB3cml0ZSBmYWxsYmFjayB1c2VkIHdoZW4gdGhlIHJ1biBwdWJsaXNoZWQgbm9cbiAqIHB1YmxpYyBrZXkgdG8gc2VhbCB0by4gV3JpdGluZyBuZWVkcyBvbmx5IHRoZSBBRVMga2V5LCBub3QgdGhlIHJlYWQtc2lkZVxuICoga2V5cGFpci4gT24gdGhlIGZhc3QgcGF0aCB0aGlzIG5lZWRzIG9ubHkgYHJ1bklkYCArIGBkZXBsb3ltZW50SWRgIChubyBydW5cbiAqIGVudGl0eSk7IG9uIHRoZSBmYWxsYmFjayBwYXRoIHRoZSBhbHJlYWR5IGZldGNoZWQgcnVuIGlzIHJldXNlZC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZUhvb2tFbmNyeXB0aW9uS2V5KFxuICBob29rOiBIb29rLFxuICBpbmZvOiBIb29rUmVzdW1lSW5mb1xuKTogUHJvbWlzZTxBd2FpdGVkPFJldHVyblR5cGU8dHlwZW9mIGltcG9ydEtleT4+IHwgdW5kZWZpbmVkPiB7XG4gIGNvbnN0IHdvcmxkID0gYXdhaXQgZ2V0V29ybGRMYXp5KCk7XG4gIGNvbnN0IHJhd0tleSA9IGluZm8ucnVuXG4gICAgPyBhd2FpdCB3b3JsZC5nZXRFbmNyeXB0aW9uS2V5Rm9yUnVuPy4oaW5mby5ydW4pXG4gICAgOiBhd2FpdCB3b3JsZC5nZXRFbmNyeXB0aW9uS2V5Rm9yUnVuPy4oaG9vay5ydW5JZCwge1xuICAgICAgICBkZXBsb3ltZW50SWQ6IGluZm8ucmVzdW1lQ29udGV4dC5kZXBsb3ltZW50SWQsXG4gICAgICB9KTtcbiAgcmV0dXJuIHJhd0tleSA/IGF3YWl0IGltcG9ydEtleShyYXdLZXkpIDogdW5kZWZpbmVkO1xufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRIb29rQnlUb2tlbldpdGhLZXkodG9rZW46IHN0cmluZyk6IFByb21pc2U8e1xuICBob29rOiBIb29rO1xuICBlbmNyeXB0aW9uS2V5OiBQYXlsb2FkS2V5IHwgdW5kZWZpbmVkO1xufT4ge1xuICBjb25zdCB3b3JsZCA9IGF3YWl0IGdldFdvcmxkTGF6eSgpO1xuICBjb25zdCBob29rID0gYXdhaXQgd29ybGQuaG9va3MuZ2V0QnlUb2tlbih0b2tlbik7XG5cbiAgLy8gT25seSBhIGhvb2sgdGhhdCBhY3R1YWxseSBjYXJyaWVzIG1ldGFkYXRhIG5lZWRzIHRoZSBydW4ncyBrZXkgcmVzb2x2ZWRcbiAgLy8gaGVyZTogaHlkcmF0aW5nIHRoYXQgbWV0YWRhdGEgaXMgYSBSRUFELCBzbyBkZXJpdmUgdGhlIGZ1bGwgUnVuUGF5bG9hZEtleXNcbiAgLy8gKHdoaWNoIG9wZW5zIHNlYWxlZCBgZW5jcGAgbWV0YWRhdGEsIG5vdCBqdXN0IHN5bW1ldHJpYyBgZW5jcmApLiBUaGUgY29tbW9uXG4gIC8vIGRlZmF1bHQgd2ViaG9vayDigJQgY3JlYXRlV2ViaG9vaygpIHdpdGggbm8gYHJlc3BvbmRXaXRoYCDigJQgc3RvcmVzIG5vXG4gIC8vIG1ldGFkYXRhLCBzbyBpdCBza2lwcyB0aGlzIGVudGlyZWx5OiBubyB+MzUwbXMgYHJ1bi1rZXlgIEFQSSByb3VuZCB0cmlwLFxuICAvLyBhbmQsIGNydWNpYWxseSwgbm8gcmVzb2x2ZWQga2V5IGhhbmRlZCB0byBgcmVzdW1lSG9va2AsIGxlYXZpbmcgaXQgZnJlZSB0b1xuICAvLyBzZWFsIHRoZSBwYXlsb2FkIHRvIHRoZSBydW4ncyBwdWJsaXNoZWQgcHVibGljIGtleSBpbnN0ZWFkLiBNZXRhZGF0YS1cbiAgLy8gYmVhcmluZyB3ZWJob29rcyBzdGlsbCBsZWdpdGltYXRlbHkgcGF5IG9uZSBsb29rdXAgdG8gaHlkcmF0ZS5cbiAgbGV0IGVuY3J5cHRpb25LZXk6IFBheWxvYWRLZXkgfCB1bmRlZmluZWQ7XG4gIGlmICh0eXBlb2YgaG9vay5tZXRhZGF0YSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBjb25zdCBpbmZvID0gYXdhaXQgcmVzb2x2ZUhvb2tSZXN1bWVJbmZvKGhvb2spO1xuICAgIC8vIE9uIHRoZSBmYXN0IHBhdGggdGhpcyByZXNvbHZlcyB0aGUga2V5IGJ5IHJ1bklkICsgZGVwbG95bWVudElkIChubyBydW5cbiAgICAvLyByZWFkKTsgb24gdGhlIGZhbGxiYWNrIHBhdGggaXQgcmV1c2VzIHRoZSBhbHJlYWR5LWZldGNoZWQgcnVuLlxuICAgIGNvbnN0IHJhd0tleSA9IGluZm8ucnVuXG4gICAgICA/IGF3YWl0IHdvcmxkLmdldEVuY3J5cHRpb25LZXlGb3JSdW4/LihpbmZvLnJ1bilcbiAgICAgIDogYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKGhvb2sucnVuSWQsIHtcbiAgICAgICAgICBkZXBsb3ltZW50SWQ6IGluZm8ucmVzdW1lQ29udGV4dC5kZXBsb3ltZW50SWQsXG4gICAgICAgIH0pO1xuICAgIGVuY3J5cHRpb25LZXkgPSByYXdLZXkgPyBhd2FpdCBkZXJpdmVSdW5QYXlsb2FkS2V5cyhyYXdLZXkpIDogdW5kZWZpbmVkO1xuICAgIGhvb2subWV0YWRhdGEgPSBhd2FpdCBoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgICAgIGhvb2subWV0YWRhdGEgYXMgYW55LFxuICAgICAgaG9vay5ydW5JZCxcbiAgICAgIGVuY3J5cHRpb25LZXlcbiAgICApO1xuICB9XG4gIHJldHVybiB7IGhvb2ssIGVuY3J5cHRpb25LZXkgfTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIGhvb2sgYnkgdG9rZW4gdG8gZmluZCB0aGUgYXNzb2NpYXRlZCB3b3JrZmxvdyBydW4sXG4gKiBhbmQgaHlkcmF0ZSB0aGUgYG1ldGFkYXRhYCBwcm9wZXJ0eSBpZiBpdCB3YXMgc2V0IGZyb20gd2l0aGluXG4gKiB0aGUgd29ya2Zsb3cgcnVuLlxuICpcbiAqIEEgSG9vayBrZXB0IGJ5IG1pbmltdW0gcmV0ZW50aW9uIHJlbWFpbnMgYXZhaWxhYmxlIGhlcmUgYWZ0ZXIgaXRzIHJ1biBlbmRzLFxuICogYnV0IGNhbm5vdCBiZSByZXN1bWVkLlxuICpcbiAqIEBwYXJhbSB0b2tlbiAtIFRoZSB1bmlxdWUgdG9rZW4gaWRlbnRpZnlpbmcgdGhlIGhvb2tcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldEhvb2tCeVRva2VuKHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPEhvb2s+IHtcbiAgY29uc3QgeyBob29rIH0gPSBhd2FpdCBnZXRIb29rQnlUb2tlbldpdGhLZXkodG9rZW4pO1xuICByZXR1cm4gaG9vaztcbn1cblxuLyoqXG4gKiBSZXN1bWVzIGEgd29ya2Zsb3cgcnVuIGJ5IHNlbmRpbmcgYSBwYXlsb2FkIHRvIGEgaG9vayBpZGVudGlmaWVkIGJ5IGl0cyB0b2tlbi5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBleHRlcm5hbGx5IChlLmcuLCBmcm9tIGFuIEFQSSByb3V0ZSBvciBzZXJ2ZXIgYWN0aW9uKVxuICogdG8gc2VuZCBkYXRhIHRvIGEgaG9vayBhbmQgcmVzdW1lIHRoZSBhc3NvY2lhdGVkIHdvcmtmbG93IHJ1bi5cbiAqXG4gKiBAcGFyYW0gdG9rZW5Pckhvb2sgLSBUaGUgdW5pcXVlIHRva2VuIGlkZW50aWZ5aW5nIHRoZSBob29rLCBvciB0aGUgaG9vayBvYmplY3QgaXRzZWxmXG4gKiBAcGFyYW0gcGF5bG9hZCAtIFRoZSBkYXRhIHBheWxvYWQgdG8gc2VuZCB0byB0aGUgaG9va1xuICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIGhvb2tcbiAqIEB0aHJvd3Mge0hvb2tOb3RGb3VuZEVycm9yfSBJZiB0aGUgSG9vayBkb2VzIG5vdCBleGlzdCBvciBpdHMgcnVuIGhhcyBlbmRlZFxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogYGBgdHNcbiAqIC8vIEluIGFuIEFQSSByb3V0ZVxuICogaW1wb3J0IHsgcmVzdW1lSG9vayB9IGZyb20gJ0B3b3JrZmxvdy9jb3JlL3J1bnRpbWUnO1xuICpcbiAqIGV4cG9ydCBhc3luYyBmdW5jdGlvbiBQT1NUKHJlcXVlc3Q6IFJlcXVlc3QpIHtcbiAqICAgY29uc3QgeyB0b2tlbiwgZGF0YSB9ID0gYXdhaXQgcmVxdWVzdC5qc29uKCk7XG4gKlxuICogICB0cnkge1xuICogICAgIGNvbnN0IGhvb2sgPSBhd2FpdCByZXN1bWVIb29rKHRva2VuLCBkYXRhKTtcbiAqICAgICByZXR1cm4gUmVzcG9uc2UuanNvbih7IHJ1bklkOiBob29rLnJ1bklkIH0pO1xuICogICB9IGNhdGNoIChlcnJvcikge1xuICogICAgIHJldHVybiBuZXcgUmVzcG9uc2UoJ0hvb2sgbm90IGZvdW5kJywgeyBzdGF0dXM6IDQwNCB9KTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXN1bWVIb29rPFQgPSBhbnk+KFxuICB0b2tlbk9ySG9vazogc3RyaW5nIHwgSG9vayxcbiAgcGF5bG9hZDogVCxcbiAgZW5jcnlwdGlvbktleU92ZXJyaWRlPzogUGF5bG9hZEtleVxuKTogUHJvbWlzZTxIb29rPiB7XG4gIHJldHVybiBhd2FpdCB3YWl0ZWRVbnRpbCgoKSA9PiB7XG4gICAgcmV0dXJuIHRyYWNlKCdob29rLnJlc3VtZScsIGFzeW5jIChzcGFuKSA9PiB7XG4gICAgICBjb25zdCB3b3JsZCA9IGF3YWl0IGdldFdvcmxkTGF6eSgpO1xuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBob29rOiBIb29rID1cbiAgICAgICAgICB0eXBlb2YgdG9rZW5Pckhvb2sgPT09ICdzdHJpbmcnXG4gICAgICAgICAgICA/IGF3YWl0IHdvcmxkLmhvb2tzLmdldEJ5VG9rZW4odG9rZW5Pckhvb2spXG4gICAgICAgICAgICA6IHRva2VuT3JIb29rO1xuXG4gICAgICAgIGNvbnN0IGluZm8gPSBhd2FpdCByZXNvbHZlSG9va1Jlc3VtZUluZm8oaG9vayk7XG4gICAgICAgIGNvbnN0IHsgcmVzdW1lQ29udGV4dCB9ID0gaW5mbztcblxuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuSG9va1Rva2VuKGhvb2sudG9rZW4pLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Ib29rSWQoaG9vay5ob29rSWQpLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1bklkKGhvb2sucnVuSWQpLFxuICAgICAgICAgICd3b3JrZmxvdy5ob29rLnJlc3VtZV9jb250ZXh0X3NvdXJjZSc6IGluZm8uc291cmNlLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBUaGUgc3RvcmVkIGByZXN1bWVDb250ZXh0YCBpbnRlbnRpb25hbGx5IG9taXRzIHRoZSBydW4ncyBtdXRhYmxlXG4gICAgICAgIC8vIHN0YXR1cywgc28gdGhpcyBlYXJseSBjbGllbnQtc2lkZSByZWplY3Rpb24gb25seSBydW5zIG9uIHRoZVxuICAgICAgICAvLyBmYWxsYmFjayBwYXRoICh3aGljaCBmZXRjaGVkIHRoZSBydW4pLiBPbiB0aGUgZmFzdCBwYXRoIHRoZSB0ZXJtaW5hbFxuICAgICAgICAvLyBjaGVjayBoYXBwZW5zIHNlcnZlci1zaWRlOiBgaG9va19yZWNlaXZlZGAgYWdhaW5zdCBhbiBlbmRlZCBydW4gaXNcbiAgICAgICAgLy8gcmVqZWN0ZWQsIHdoaWNoIHRoZSBjYXRjaCBhcm91bmQgYHdvcmxkLmV2ZW50cy5jcmVhdGVgIGJlbG93IHJlLWtleXNcbiAgICAgICAgLy8gdG8gSG9va05vdEZvdW5kRXJyb3Ig4oCUIHNhbWUgcHVibGljIGNvbnRyYWN0LCBubyBydW4gcHJlLWZldGNoLlxuICAgICAgICBpZiAoaW5mby5ydW4gJiYgaXNUZXJtaW5hbFdvcmtmbG93UnVuU3RhdHVzKGluZm8ucnVuLnN0YXR1cykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgSG9va05vdEZvdW5kRXJyb3IoaG9vay50b2tlbik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayB0aGUgdGFyZ2V0IHJ1bidzIGNhcGFiaWxpdGllcyB0byBlbnN1cmUgd2UgZW5jb2RlIHRoZVxuICAgICAgICAvLyBwYXlsb2FkIGluIGEgZm9ybWF0IHRoZSBydW4ncyBkZXBsb3ltZW50IGNhbiBkZWNvZGUuIEZvciBleGFtcGxlLFxuICAgICAgICAvLyBydW5zIGNyZWF0ZWQgYmVmb3JlIGVuY3J5cHRpb24gc3VwcG9ydCB3YXMgYWRkZWQgY2Fubm90IGRlY29kZVxuICAgICAgICAvLyB0aGUgJ2VuY3InIHNlcmlhbGl6YXRpb24gZm9ybWF0LCBhbmQgcnVucyBjcmVhdGVkIGJlZm9yZVxuICAgICAgICAvLyBieXRlLXN0cmVhbSBmcmFtaW5nIHN1cHBvcnQgY2Fubm90IGRlY29kZSBmcmFtZWQgYnl0ZSBzdHJlYW1zLlxuICAgICAgICBjb25zdCBjYXBhYmlsaXRpZXMgPSBnZXRSdW5DYXBhYmlsaXRpZXMoXG4gICAgICAgICAgcmVzdW1lQ29udGV4dC53b3JrZmxvd0NvcmVWZXJzaW9uXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gUmVzb2x2ZSBob3cgdG8gZW5jcnlwdCB0aGUgcGF5bG9hZCBmb3IgdGhlIHRhcmdldCBydW4gKGEgV1JJVEUpLlxuICAgICAgICAvL1xuICAgICAgICAvLyBQcmVmZXJyZWQgcGF0aDogc2VhbCB0byB0aGUgcnVuJ3MgcHVibGlzaGVkIFgyNTUxOSBwdWJsaWMga2V5LCB3aGljaFxuICAgICAgICAvLyB0aGUgc3RvcmVkIGByZXN1bWVDb250ZXh0YCBjYXJyaWVzIGlubGluZS4gT24gdGhlIGZhc3QgcGF0aCB0aGlzIGlzXG4gICAgICAgIC8vIHRoZSB3aG9sZSB3aW4g4oCUIG5vIHJ1biByZWFkIEFORCBubyBgZ2V0RW5jcnlwdGlvbktleUZvclJ1bmAsIHdob3NlXG4gICAgICAgIC8vIH4zNTBtcyBgcnVuLWtleWAgQVBJIHJvdW5kIHRyaXAgZG9taW5hdGVzIGNyb3NzLWRlcGxveW1lbnQgaG9va1xuICAgICAgICAvLyByZXN1bXB0aW9uIGxhdGVuY3kuIChPbiB0aGUgZmFsbGJhY2sgcGF0aCB0aGUga2V5IGlzIHN5bnRoZXNpemVkXG4gICAgICAgIC8vIGZyb20gdGhlIGZldGNoZWQgcnVuLCB3aGljaCBhbHNvIGNhcnJpZXMgaXQuKVxuICAgICAgICAvL1xuICAgICAgICAvLyBTZWFsaW5nIGFsc28gZHJvcHMgcHJpdmlsZWdlOiB0aGUgcmVzdW1lciBlbmRzIHVwIGFibGUgdG8gd3JpdGUgYVxuICAgICAgICAvLyBwYXlsb2FkIGZvciB0aGUgcnVuIHdpdGhvdXQgYmVpbmcgYWJsZSB0byByZWFkIGFueXRoaW5nIG9mIHRoZVxuICAgICAgICAvLyBydW4ncywgd2hlcmUgZmV0Y2hpbmcgdGhlIHN5bW1ldHJpYyBrZXkgZ3JhbnRzIGJvdGguXG4gICAgICAgIC8vXG4gICAgICAgIC8vIERlbGliZXJhdGVseSBOT1QgZ2F0ZWQgb24gYGNhcGFiaWxpdGllcy5zdXBwb3J0ZWRGb3JtYXRzYCB0aGUgd2F5XG4gICAgICAgIC8vIHRoZSBzeW1tZXRyaWMgZmFsbGJhY2sgYmVsb3cgZ2F0ZXMgYGVuY3JgOiBwcmVzZW5jZSBvZiB0aGUgcHVibGljIGtleVxuICAgICAgICAvLyBpcyBpdHNlbGYgdGhlIGdhdGUuIEEgcnVuIG9ubHkgY2FycmllcyBvbmUgaWYgdGhlIHJ1bnRpbWUgdGhhdFxuICAgICAgICAvLyBjcmVhdGVkIGl0IGNvdWxkIGFsc28gb3BlbiBhIHNlYWxlZCBwYXlsb2FkLCBhbmQgcnVucyBhcmUgcGlubmVkIHRvXG4gICAgICAgIC8vIHRoZWlyIGNyZWF0aW5nIGRlcGxveW1lbnQsIHNvIHByZXNlbmNlIGlzIGEgbW9yZSByZWxpYWJsZSBhdHRlc3RhdGlvblxuICAgICAgICAvLyB0aGFuIGEgdmVyc2lvbiBjb21wYXJlIOKAlCBhbmQgaXQgc3RheXMgY29ycmVjdCBldmVuIHdoZW4gcGFja2FnZVxuICAgICAgICAvLyB2ZXJzaW9ucyBkcmlmdC5cbiAgICAgICAgbGV0IHBheWxvYWRLZXk6IFBheWxvYWRLZXkgfCB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IHJ1blB1YmxpY0tleSA9IGVuY3J5cHRpb25LZXlPdmVycmlkZVxuICAgICAgICAgID8gLy8gVGhlIGNhbGxlciBhbHJlYWR5IGhvbGRzIGEga2V5IChyZXN1bWVXZWJob29rIHJlc29sdmVkIG9uZSB0b1xuICAgICAgICAgICAgLy8gaHlkcmF0ZSBob29rIG1ldGFkYXRhKSwgc28gc2VhbGluZyB3b3VsZCBhZGQgYW4gRUNESCBmb3Igbm9cbiAgICAgICAgICAgIC8vIHNhdmVkIHJvdW5kIHRyaXAuIFJldXNlIHdoYXQgaXQgcmVzb2x2ZWQuXG4gICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgICA6IGRlY29kZVJ1blB1YmxpY0tleShyZXN1bWVDb250ZXh0LmVuY3J5cHRpb25QdWJsaWNLZXkpO1xuXG4gICAgICAgIGlmIChydW5QdWJsaWNLZXkpIHtcbiAgICAgICAgICBwYXlsb2FkS2V5ID0gc2VhbFRvKHJ1blB1YmxpY0tleSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gU3ltbWV0cmljIGBlbmNyYCB3cml0ZSBmYWxsYmFjazogbmVlZHMgb25seSB0aGUgQUVTIGtleVxuICAgICAgICAgIC8vIChhIGJhcmUgQ3J5cHRvS2V5IHZpYSBgcmVzb2x2ZUhvb2tFbmNyeXB0aW9uS2V5YCksIG5vdCB0aGVcbiAgICAgICAgICAvLyByZWFkLXNpZGUgUnVuUGF5bG9hZEtleXMuXG4gICAgICAgICAgbGV0IGVuY3J5cHRpb25LZXkgPVxuICAgICAgICAgICAgZW5jcnlwdGlvbktleU92ZXJyaWRlID8/XG4gICAgICAgICAgICAoYXdhaXQgcmVzb2x2ZUhvb2tFbmNyeXB0aW9uS2V5KGhvb2ssIGluZm8pKTtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAhY2FwYWJpbGl0aWVzLnN1cHBvcnRlZEZvcm1hdHMuaGFzKFNlcmlhbGl6YXRpb25Gb3JtYXQuRU5DUllQVEVEKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgZW5jcnlwdGlvbktleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcGF5bG9hZEtleSA9IGVuY3J5cHRpb25LZXk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb21wcmVzcyBvbmx5IHdoZW4gdGhlIHRhcmdldCBydW4gYW5kIGl0cyBkZXBsb3ltZW50IHN1cHBvcnQgdGhlXG4gICAgICAgIC8vIGNvbXByZXNzaW9uIGZvcm1hdHMgaW50cm9kdWNlZCB3aXRoIHNwZWMgdmVyc2lvbiA1LlxuICAgICAgICBjb25zdCBjb21wcmVzc2lvbiA9XG4gICAgICAgICAgKHJlc3VtZUNvbnRleHQucnVuU3BlY1ZlcnNpb24gPz8gMCkgPj1cbiAgICAgICAgICAgIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DT01QUkVTU0lPTiAmJlxuICAgICAgICAgIGNhcGFiaWxpdGllcy5zdXBwb3J0ZWRGb3JtYXRzLmhhcyhTZXJpYWxpemF0aW9uRm9ybWF0LkdaSVApO1xuXG4gICAgICAgIC8vIERlaHlkcmF0ZSB0aGUgcGF5bG9hZCBmb3Igc3RvcmFnZVxuICAgICAgICBjb25zdCBvcHM6IFByb21pc2U8YW55PltdID0gW107XG4gICAgICAgIGNvbnN0IHYxQ29tcGF0ID0gaXNMZWdhY3lTcGVjVmVyc2lvbihob29rLnNwZWNWZXJzaW9uKTtcbiAgICAgICAgY29uc3QgZGVoeWRyYXRlZFBheWxvYWQgPSBhd2FpdCBkZWh5ZHJhdGVTdGVwUmV0dXJuVmFsdWUoXG4gICAgICAgICAgcGF5bG9hZCxcbiAgICAgICAgICBob29rLnJ1bklkLFxuICAgICAgICAgIHBheWxvYWRLZXksXG4gICAgICAgICAgb3BzLFxuICAgICAgICAgIGdsb2JhbFRoaXMsXG4gICAgICAgICAgdjFDb21wYXQsXG4gICAgICAgICAgY2FwYWJpbGl0aWVzLmZyYW1lZEJ5dGVTdHJlYW1zLFxuICAgICAgICAgIGNvbXByZXNzaW9uXG4gICAgICAgICk7XG4gICAgICAgIC8vIFRoZXNlIHBheWxvYWQtc3RyZWFtIG9wcyBhcmUgZmx1c2hlZCBpbiB0aGUgYmFja2dyb3VuZDsgdGhlXG4gICAgICAgIC8vIHByb21pc2UgaGFuZGVkIHRvIHdhaXRVbnRpbCBtdXN0IG5ldmVyIHJlamVjdCAoYW4gdW5jb25zdW1lZFxuICAgICAgICAvLyB3YWl0VW50aWwgcmVqZWN0aW9uIGNyYXNoZXMgdGhlIHByb2Nlc3MgYXMgdW5oYW5kbGVkUmVqZWN0aW9uKSxcbiAgICAgICAgLy8gc28gdW5leHBlY3RlZCBmYWlsdXJlcyBhcmUgbG9nZ2VkIGluc3RlYWQuXG4gICAgICAgIC8vIE5PVEU6IHJlamVjdGlvbnMgd2l0aCBgdW5kZWZpbmVkYCBhcmUgYW4gZXhwZWN0ZWQgYXJ0aWZhY3Qgb2YgdGhlXG4gICAgICAgIC8vIHdlYmhvb2sgYnVuZGxlIGFuZCBhcmUgaWdub3JlZCBlbnRpcmVseS5cbiAgICAgICAgc2FmZVdhaXRVbnRpbChQcm9taXNlLmFsbChvcHMpLCAoZXJyKSA9PiB7XG4gICAgICAgICAgaWYgKGVyciA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG4gICAgICAgICAgcnVudGltZUxvZ2dlci53YXJuKCdCYWNrZ3JvdW5kIGZsdXNoIG9mIGhvb2sgcGF5bG9hZCBvcHMgZmFpbGVkJywge1xuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogaG9vay5ydW5JZCxcbiAgICAgICAgICAgIGhvb2tJZDogaG9vay5ob29rSWQsXG4gICAgICAgICAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBDcmVhdGUgYSBob29rX3JlY2VpdmVkIGV2ZW50IHdpdGggdGhlIHBheWxvYWRcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgaG9vay5ydW5JZCxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnaG9va19yZWNlaXZlZCcsXG4gICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogaG9vay5ob29rSWQsXG4gICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgIC4uLih2MUNvbXBhdCA/IHt9IDogeyB0b2tlbjogaG9vay50b2tlbiB9KSxcbiAgICAgICAgICAgICAgICBwYXlsb2FkOiBkZWh5ZHJhdGVkUGF5bG9hZCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7IHYxQ29tcGF0IH1cbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAvLyBSZS1rZXkgYW55IFwiaG9vayBjYW4gbm8gbG9uZ2VyIGJlIHJlY2VpdmVkXCIgcmVqZWN0aW9uIHRvXG4gICAgICAgICAgLy8gSG9va05vdEZvdW5kRXJyb3IoaG9vay50b2tlbikgc28gYC50b2tlbmAgbWF0Y2hlcyB0aGVcbiAgICAgICAgICAvLyBwcmUtZmFzdC1wYXRoIGNvbnRyYWN0LCB3aGVyZSByZXN1bWVIb29rIHRocmV3XG4gICAgICAgICAgLy8gYEhvb2tOb3RGb3VuZEVycm9yKGhvb2sudG9rZW4pYCBhZnRlciBpdHMgb3duIHRlcm1pbmFsIGNoZWNrLlxuICAgICAgICAgIC8vIFRoZSBzcGVjaWZpYyBlcnJvciBkZXBlbmRzIG9uIHRoZSBXb3JsZDpcbiAgICAgICAgICAvLyAgIC0gYSBnZW51aW5lbHkgbWlzc2luZyBob29rIG1hcHMgdG8gSG9va05vdEZvdW5kRXJyb3IgKGtleWVkIG9uXG4gICAgICAgICAgLy8gICAgIHRoZSBldmVudCBjb3JyZWxhdGlvbklkIC8gaG9vayBJRCk7XG4gICAgICAgICAgLy8gICAtIGEgdGVybWluYWwgcnVuIG9uIFZlcmNlbCByZWplY3RzIGhvb2tfcmVjZWl2ZWQgd2l0aCA0MDQsIHdoaWNoXG4gICAgICAgICAgLy8gICAgIHdvcmxkLXZlcmNlbCBtYXBzIHRvIEhvb2tOb3RGb3VuZEVycm9yO1xuICAgICAgICAgIC8vICAgLSBhIHRlcm1pbmFsIHJ1biBvbiB3b3JsZC1sb2NhbCAvIHdvcmxkLXBvc3RncmVzIHJlamVjdHMgd2l0aFxuICAgICAgICAgIC8vICAgICBSdW5FeHBpcmVkRXJyb3IuXG4gICAgICAgICAgLy8gRW50aXR5Q29uZmxpY3RFcnJvciAoSFRUUCA0MDkpIGlzIGtlcHQgZm9yIGNvbXBhdGliaWxpdHkgd2l0aFxuICAgICAgICAgIC8vIG9sZGVyIC8gY29uZmxpY3Qtc2hhcGVkIHJlamVjdGlvbiBiZWhhdmlvci5cbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBIb29rTm90Rm91bmRFcnJvci5pcyhlcnIpIHx8XG4gICAgICAgICAgICBFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikgfHxcbiAgICAgICAgICAgIFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgSG9va05vdEZvdW5kRXJyb3IoaG9vay50b2tlbik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfVxuXG4gICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd05hbWUocmVzdW1lQ29udGV4dC53b3JrZmxvd05hbWUpLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBMaW5rIHRvIHRoZSBydW4tb3JpZ2luIGNvbnRleHQgZnJvbSB0aGUgc3RvcmVkIHRyYWNlIGNhcnJpZXJcbiAgICAgICAgLy8gKHNraXBwZWQgd2hlbiBhYnNlbnQgb3IgaW52YWxpZCkuXG4gICAgICAgIGNvbnN0IG9yaWdpbkxpbmsgPSBhd2FpdCBsaW5rVG9UcmFjZUNhcnJpZXIocmVzdW1lQ29udGV4dC50cmFjZUNhcnJpZXIpO1xuICAgICAgICBpZiAob3JpZ2luTGluaykge1xuICAgICAgICAgIHNwYW4/LmFkZExpbms/LihvcmlnaW5MaW5rKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlLXRyaWdnZXIgdGhlIHdvcmtmbG93IGFnYWluc3QgdGhlIGRlcGxveW1lbnQgSUQgYXNzb2NpYXRlZFxuICAgICAgICAvLyB3aXRoIHRoZSB3b3JrZmxvdyBydW4gdGhhdCB0aGUgaG9vayBiZWxvbmdzIHRvXG4gICAgICAgIGF3YWl0IHdvcmxkLnF1ZXVlKFxuICAgICAgICAgIGdldFdvcmtmbG93UXVldWVOYW1lKHJlc3VtZUNvbnRleHQud29ya2Zsb3dOYW1lKSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBydW5JZDogaG9vay5ydW5JZCxcbiAgICAgICAgICAgIC8vIGF0dGFjaCB0aGUgdHJhY2UgY2FycmllciBmcm9tIHRoZSBydW4ncyByZXN1bWUgY29udGV4dFxuICAgICAgICAgICAgdHJhY2VDYXJyaWVyOiByZXN1bWVDb250ZXh0LnRyYWNlQ2FycmllciA/PyB1bmRlZmluZWQsXG4gICAgICAgICAgfSBzYXRpc2ZpZXMgV29ya2Zsb3dJbnZva2VQYXlsb2FkLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGRlcGxveW1lbnRJZDogcmVzdW1lQ29udGV4dC5kZXBsb3ltZW50SWQsXG4gICAgICAgICAgICBzcGVjVmVyc2lvbjogcmVzdW1lQ29udGV4dC5ydW5TcGVjVmVyc2lvbiA/PyBTUEVDX1ZFUlNJT05fTEVHQUNZLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICByZXR1cm4gaG9vaztcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuSG9va1Rva2VuKFxuICAgICAgICAgICAgdHlwZW9mIHRva2VuT3JIb29rID09PSAnc3RyaW5nJyA/IHRva2VuT3JIb29rIDogdG9rZW5Pckhvb2sudG9rZW5cbiAgICAgICAgICApLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Ib29rRm91bmQoZmFsc2UpLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcbn1cblxuLyoqXG4gKiBSZXN1bWVzIGEgd2ViaG9vayBieSBzZW5kaW5nIGEge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9SZXF1ZXN0IHwgUmVxdWVzdH1cbiAqIG9iamVjdCB0byBhIGhvb2sgaWRlbnRpZmllZCBieSBpdHMgdG9rZW4uXG4gKlxuICogVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgZXh0ZXJuYWxseSAoZS5nLiwgZnJvbSBhbiBBUEkgcm91dGUgb3Igc2VydmVyIGFjdGlvbilcbiAqIHRvIHNlbmQgYSByZXF1ZXN0IHRvIGEgd2ViaG9vayBhbmQgcmVzdW1lIHRoZSBhc3NvY2lhdGVkIHdvcmtmbG93IHJ1bi5cbiAqXG4gKiBAcGFyYW0gdG9rZW4gLSBUaGUgdW5pcXVlIHRva2VuIGlkZW50aWZ5aW5nIHRoZSBob29rXG4gKiBAcGFyYW0gcmVxdWVzdCAtIFRoZSByZXF1ZXN0IHRvIHNlbmQgdG8gdGhlIGhvb2tcbiAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSByZXNwb25zZVxuICogQHRocm93cyBFcnJvciBpZiB0aGUgaG9vayBpcyBub3QgZm91bmQgb3IgaWYgdGhlcmUncyBhbiBlcnJvciBkdXJpbmcgdGhlIHByb2Nlc3NcbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqIGBgYHRzXG4gKiAvLyBJbiBhbiBBUEkgcm91dGVcbiAqIGltcG9ydCB7IHJlc3VtZVdlYmhvb2sgfSBmcm9tICdAd29ya2Zsb3cvY29yZS9ydW50aW1lJztcbiAqXG4gKiBleHBvcnQgYXN5bmMgZnVuY3Rpb24gUE9TVChyZXF1ZXN0OiBSZXF1ZXN0KSB7XG4gKiAgIGNvbnN0IHVybCA9IG5ldyBVUkwocmVxdWVzdC51cmwpO1xuICogICBjb25zdCB0b2tlbiA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCd0b2tlbicpO1xuICpcbiAqICAgaWYgKCF0b2tlbikge1xuICogICAgIHJldHVybiBuZXcgUmVzcG9uc2UoJ01pc3NpbmcgdG9rZW4nLCB7IHN0YXR1czogNDAwIH0pO1xuICogICB9XG4gKlxuICogICB0cnkge1xuICogICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgcmVzdW1lV2ViaG9vayh0b2tlbiwgcmVxdWVzdCk7XG4gKiAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICogICB9IGNhdGNoIChlcnJvcikge1xuICogICAgIHJldHVybiBuZXcgUmVzcG9uc2UoJ1dlYmhvb2sgbm90IGZvdW5kJywgeyBzdGF0dXM6IDQwNCB9KTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXN1bWVXZWJob29rKFxuICB0b2tlbjogc3RyaW5nLFxuICByZXF1ZXN0OiBSZXF1ZXN0XG4pOiBQcm9taXNlPFJlc3BvbnNlPiB7XG4gIGNvbnN0IHsgaG9vaywgZW5jcnlwdGlvbktleSB9ID0gYXdhaXQgZ2V0SG9va0J5VG9rZW5XaXRoS2V5KHRva2VuKTtcblxuICAvLyBPbmx5IHdlYmhvb2tzIGNhbiBiZSByZXN1bWVkIHZpYSB0aGUgcHVibGljIGVuZHBvaW50LlxuICAvLyBJZiB0aGUgaG9vayB3YXMgY3JlYXRlZCB2aWEgY3JlYXRlSG9vaygpIChpc1dlYmhvb2sgIT09IHRydWUpLFxuICAvLyB0aHJvdyB0aGUgc2FtZSBcIm5vdCBmb3VuZFwiIGVycm9yIHRoZSB3b3JsZCB3b3VsZCB0aHJvdyBmb3IgYSBtaXNzaW5nXG4gIC8vIHRva2VuLiBUaGlzIHByZXZlbnRzIGxlYWtpbmcgdGhhdCB0aGUgdG9rZW4gaXMgdmFsaWQuXG4gIGlmIChob29rLmlzV2ViaG9vayA9PT0gZmFsc2UpIHtcbiAgICB0aHJvdyBuZXcgSG9va05vdEZvdW5kRXJyb3IodG9rZW4pO1xuICB9XG5cbiAgbGV0IHJlc3BvbnNlOiBSZXNwb25zZSB8IHVuZGVmaW5lZDtcbiAgbGV0IHJlc3BvbnNlUmVhZGFibGU6IFJlYWRhYmxlU3RyZWFtPFJlc3BvbnNlPiB8IHVuZGVmaW5lZDtcbiAgaWYgKFxuICAgIGhvb2subWV0YWRhdGEgJiZcbiAgICB0eXBlb2YgaG9vay5tZXRhZGF0YSA9PT0gJ29iamVjdCcgJiZcbiAgICAncmVzcG9uZFdpdGgnIGluIGhvb2subWV0YWRhdGFcbiAgKSB7XG4gICAgaWYgKGhvb2subWV0YWRhdGEucmVzcG9uZFdpdGggPT09ICdtYW51YWwnKSB7XG4gICAgICBjb25zdCB7IHJlYWRhYmxlLCB3cml0YWJsZSB9ID0gbmV3IFRyYW5zZm9ybVN0cmVhbTxSZXNwb25zZSwgUmVzcG9uc2U+KCk7XG4gICAgICByZXNwb25zZVJlYWRhYmxlID0gcmVhZGFibGU7XG5cbiAgICAgIC8vIFRoZSByZXF1ZXN0IGluc3RhbmNlIGluY2x1ZGVzIHRoZSB3cml0YWJsZSBzdHJlYW0gd2hpY2ggd2lsbCBiZSB1c2VkXG4gICAgICAvLyB0byB3cml0ZSB0aGUgcmVzcG9uc2UgdG8gdGhlIGNsaWVudCBmcm9tIHdpdGhpbiB0aGUgd29ya2Zsb3cgcnVuXG4gICAgICAocmVxdWVzdCBhcyBhbnkpW1dFQkhPT0tfUkVTUE9OU0VfV1JJVEFCTEVdID0gd3JpdGFibGU7XG4gICAgfSBlbHNlIGlmIChob29rLm1ldGFkYXRhLnJlc3BvbmRXaXRoIGluc3RhbmNlb2YgUmVzcG9uc2UpIHtcbiAgICAgIHJlc3BvbnNlID0gaG9vay5tZXRhZGF0YS5yZXNwb25kV2l0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgICBgSW52YWxpZCBcXGByZXNwb25kV2l0aFxcYCB2YWx1ZTogJHtob29rLm1ldGFkYXRhLnJlc3BvbmRXaXRofWAsXG4gICAgICAgIHsgc2x1ZzogRVJST1JfU0xVR1MuV0VCSE9PS19JTlZBTElEX1JFU1BPTkRfV0lUSF9WQUxVRSB9XG4gICAgICApO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBObyBgcmVzcG9uZFdpdGhgIHZhbHVlIGltcGxpZXMgdGhlIGRlZmF1bHQgYmVoYXZpb3Igb2YgcmV0dXJuaW5nIGEgMjAyXG4gICAgcmVzcG9uc2UgPSBuZXcgUmVzcG9uc2UobnVsbCwgeyBzdGF0dXM6IDIwMiB9KTtcbiAgfVxuXG4gIGF3YWl0IHJlc3VtZUhvb2soaG9vaywgcmVxdWVzdCwgZW5jcnlwdGlvbktleSk7XG5cbiAgaWYgKHJlc3BvbnNlUmVhZGFibGUpIHtcbiAgICAvLyBXYWl0IGZvciB0aGUgcmVhZGFibGUgc3RyZWFtIHRvIGVtaXQgb25lIGNodW5rLFxuICAgIC8vIHdoaWNoIGlzIHRoZSBgUmVzcG9uc2VgIG9iamVjdFxuICAgIGNvbnN0IHJlYWRlciA9IHJlc3BvbnNlUmVhZGFibGUuZ2V0UmVhZGVyKCk7XG4gICAgY29uc3QgY2h1bmsgPSBhd2FpdCByZWFkZXIucmVhZCgpO1xuICAgIGlmIChjaHVuay52YWx1ZSkge1xuICAgICAgcmVzcG9uc2UgPSBjaHVuay52YWx1ZTtcbiAgICB9XG4gICAgcmVhZGVyLmNhbmNlbCgpO1xuICB9XG5cbiAgaWYgKCFyZXNwb25zZSkge1xuICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcignV29ya2Zsb3cgcnVuIGRpZCBub3Qgc2VuZCBhIHJlc3BvbnNlJywge1xuICAgICAgc2x1ZzogRVJST1JfU0xVR1MuV0VCSE9PS19SRVNQT05TRV9OT1RfU0VOVCxcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiByZXNwb25zZTtcbn1cbiJdfQ==
|
|
614
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzdW1lLWhvb2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVudGltZS9yZXN1bWUtaG9vay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLFdBQVcsRUFDWCxpQkFBaUIsRUFDakIsZUFBZSxFQUNmLG9CQUFvQixHQUNyQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFDTCx5QkFBeUIsRUFDekIseUJBQXlCLEVBR3pCLG1CQUFtQixFQUNuQiwyQkFBMkIsRUFDM0Isb0JBQW9CLEVBQ3BCLG1CQUFtQixFQUNuQiwwQ0FBMEMsRUFDMUMsaUNBQWlDLEdBR2xDLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzdELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3RFLE9BQU8sRUFDTCx3QkFBd0IsRUFDeEIsb0JBQW9CLEVBRXBCLG1CQUFtQixFQUNuQixNQUFNLEdBQ1AsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUQsT0FBTyxLQUFLLFNBQVMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsS0FBSyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDNUQsT0FBTyxFQUFFLFlBQVksRUFB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RUFBRSxXQUFXLENBQUMseUJBQXlCO1NBQzVDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgRW50aXR5Q29uZmxpY3RFcnJvcixcbiAgRVJST1JfU0xVR1MsXG4gIEhvb2tOb3RGb3VuZEVycm9yLFxuICBSdW5FeHBpcmVkRXJyb3IsXG4gIFdvcmtmbG93UnVudGltZUVycm9yLFxufSBmcm9tICdAd29ya2Zsb3cvZXJyb3JzJztcbmltcG9ydCB7XG4gIEhPT0tfUkVTVU1FX0RFRFVQX1ZFUlNJT04sXG4gIEhPT0tfUkVTVU1FX0lOUFVUX1ZFUlNJT04sXG4gIHR5cGUgSG9vayxcbiAgdHlwZSBIb29rUmVzdW1lQ29udGV4dCxcbiAgaXNMZWdhY3lTcGVjVmVyc2lvbixcbiAgaXNUZXJtaW5hbFdvcmtmbG93UnVuU3RhdHVzLFxuICBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgU1BFQ19WRVJTSU9OX0xFR0FDWSxcbiAgU1BFQ19WRVJTSU9OX1NVUFBPUlRTX0NCT1JfUVVFVUVfVFJBTlNQT1JULFxuICBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ09NUFJFU1NJT04sXG4gIHR5cGUgV29ya2Zsb3dJbnZva2VQYXlsb2FkLFxuICB0eXBlIFdvcmtmbG93UnVuLFxufSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgbW9ub3RvbmljRmFjdG9yeSB9IGZyb20gJ3VsaWQnO1xuaW1wb3J0IHsgZ2V0UnVuQ2FwYWJpbGl0aWVzIH0gZnJvbSAnLi4vY2FwYWJpbGl0aWVzLmpzJztcbmltcG9ydCB7IGlzUmV0cnlhYmxlV29ybGRFcnJvciB9IGZyb20gJy4uL2NsYXNzaWZ5LWVycm9yLmpzJztcbmltcG9ydCB7IGltcG9ydEtleSB9IGZyb20gJy4uL2VuY3J5cHRpb24uanMnO1xuaW1wb3J0IHsgcnVudGltZUxvZ2dlciB9IGZyb20gJy4uL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBkZWNvZGVSdW5QdWJsaWNLZXkgfSBmcm9tICcuLi9zZWFsZWQtYm94LmpzJztcbmltcG9ydCB7IGRlcml2ZVJ1blBheWxvYWRLZXlzIH0gZnJvbSAnLi4vc2VyaWFsaXphdGlvbi9lbmNyeXB0aW9uLmpzJztcbmltcG9ydCB7XG4gIGRlaHlkcmF0ZVN0ZXBSZXR1cm5WYWx1ZSxcbiAgaHlkcmF0ZVN0ZXBBcmd1bWVudHMsXG4gIHR5cGUgUGF5bG9hZEtleSxcbiAgU2VyaWFsaXphdGlvbkZvcm1hdCxcbiAgc2VhbFRvLFxufSBmcm9tICcuLi9zZXJpYWxpemF0aW9uLmpzJztcbmltcG9ydCB7IFdFQkhPT0tfUkVTUE9OU0VfV1JJVEFCTEUgfSBmcm9tICcuLi9zeW1ib2xzLmpzJztcbmltcG9ydCAqIGFzIEF0dHJpYnV0ZSBmcm9tICcuLi90ZWxlbWV0cnkvc2VtYW50aWMtY29udmVudGlvbnMuanMnO1xuaW1wb3J0IHsgbGlua1RvVHJhY2VDYXJyaWVyLCB0cmFjZSB9IGZyb20gJy4uL3RlbGVtZXRyeS5qcyc7XG5pbXBvcnQgeyBnZXRXb3JsZExhenkgfSBmcm9tICcuL2dldC13b3JsZC1sYXp5LmpzJztcbmltcG9ydCB7IGdldFdvcmtmbG93UXVldWVOYW1lIH0gZnJvbSAnLi9oZWxwZXJzLmpzJztcbmltcG9ydCB7IHNhZmVXYWl0VW50aWwsIHdhaXRlZFVudGlsIH0gZnJvbSAnLi93YWl0LXVudGlsLmpzJztcblxuLyoqIE1vbm90b25pYyBVTElEIGZhY3RvcnkgZm9yIHBlci1jYWxsIHJlc3VtZSBpZGVtcG90ZW5jeSBrZXlzLiAqL1xuY29uc3QgZ2VuZXJhdGVSZXN1bWVJZCA9IG1vbm90b25pY0ZhY3RvcnkoKTtcblxuLyoqXG4gKiBVcHBlciBib3VuZCBvbiB0aGUgc2VyaWFsaXplZCBob29rIHBheWxvYWQgdGhhdCB0aGUgcGFyYWxsZWwgZmFzdCBwYXRoIHdpbGxcbiAqIGlubGluZSBpbnRvIHRoZSBxdWV1ZSBtZXNzYWdlJ3MgYGhvb2tJbnB1dGAuIFZlcmNlbCBRdWV1ZXMgY2FwcyBhIHNpbmdsZVxuICogbWVzc2FnZSBhdCB+MjU2IEtpQiwgYW5kIHRoZSBtZXNzYWdlIGFsc28gY2FycmllcyB0aGUgcnVuSWQsIGhvb2tJZCwgdG9rZW4sXG4gKiByZXN1bWVJZCwgZGlnZXN0LCBhbmQgdHJhY2UgY2FycmllciBhbG9uZ3NpZGUgQ0JPUiBmcmFtaW5nIG92ZXJoZWFkLiBTdGF5aW5nXG4gKiB3ZWxsIHVuZGVyIHRoYXQgY2VpbGluZyBrZWVwcyB0aGUgcXVldWUgcHVibGlzaCBmcm9tIHJlamVjdGluZyBhbiBvdmVyc2l6ZWRcbiAqIG1lc3NhZ2Ug4oCUIHdoaWNoLCBvbiB0aGUgcGFyYWxsZWwgcGF0aCwgd291bGQgcGVyc2lzdCBgaG9va19yZWNlaXZlZGAgYnV0IG5ldmVyXG4gKiByZS10cmlnZ2VyIHRoZSBydW4uIEFib3ZlIHRoaXMgc2l6ZSB3ZSBmYWxsIGJhY2sgdG8gdGhlIHNlcXVlbnRpYWwgcGF0aCwgd2hvc2VcbiAqIHF1ZXVlIG1lc3NhZ2UgY2FycmllcyBvbmx5IHRoZSBydW4gSUQgKHRoZSBwYXlsb2FkIGxpdmVzIGluIHRoZSBldmVudCBsb2cpLlxuICovXG5jb25zdCBNQVhfSU5MSU5FX1JFU1VNRV9QQVlMT0FEX0JZVEVTID0gMTI4ICogMTAyNDtcblxuLyoqXG4gKiBIZXggU0hBLTI1NiBvZiB0aGUgc2VyaWFsaXplZCByZXN1bWUgcGF5bG9hZCBieXRlcy4gQ29tcHV0ZWQgb25jZSBieSB0aGVcbiAqIHByb2R1Y2VyIGFuZCBmb3J3YXJkZWQgdmVyYmF0aW0gb24gYm90aCB0aGUgZGlyZWN0IGBob29rX3JlY2VpdmVkYCB3cml0ZSBhbmRcbiAqIHRoZSBxdWV1ZSBgaG9va0lucHV0YCwgc28gYm90aCB3cml0ZXJzIG9mIHRoZSBzYW1lIGByZXN1bWVJZGAgcmVjb3JkIGFuXG4gKiBpZGVudGljYWwgZGlnZXN0IG9uIHRoZSBzZXJ2ZXIncyBgKHJ1bklkLCByZXN1bWVJZClgIGNvbnN0cmFpbnQuIEhhc2hpbmcgdGhlXG4gKiBhbHJlYWR5LXNlcmlhbGl6ZWQgYnl0ZXMgKG5vdCB0aGUgcmF3IHZhbHVlKSBrZWVwcyBwcm9kdWNlciBhbmQgY29uc3VtZXIgaW5cbiAqIGxvY2tzdGVwIOKAlCB0aGUgY29uc3VtZXIgZm9yd2FyZHMgdGhpcyBzdHJpbmcgd2l0aG91dCByZWNvbXB1dGluZy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gY29tcHV0ZVJlc3VtZVBheWxvYWREaWdlc3QoYnl0ZXM6IFVpbnQ4QXJyYXkpOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBkaWdlc3QgPSBhd2FpdCBjcnlwdG8uc3VidGxlLmRpZ2VzdCgnU0hBLTI1NicsIGJ5dGVzKTtcbiAgY29uc3QgdmlldyA9IG5ldyBVaW50OEFycmF5KGRpZ2VzdCk7XG4gIGxldCBoZXggPSAnJztcbiAgZm9yIChjb25zdCBiIG9mIHZpZXcpIHtcbiAgICBoZXggKz0gYi50b1N0cmluZygxNikucGFkU3RhcnQoMiwgJzAnKTtcbiAgfVxuICByZXR1cm4gaGV4O1xufVxuXG4vKipcbiAqIFRoZSByZXN1bWUgY29udGV4dCBmb3IgYSBob29rIHBsdXMgd2hlcmUgaXQgY2FtZSBmcm9tLiBgcnVuYCBpcyBwcmVzZW50IG9ubHlcbiAqIG9uIHRoZSBmYWxsYmFjayBwYXRoIChwcmUtYHJlc3VtZUNvbnRleHRgIGhvb2tzKSwgd2hlcmUgaXQgYWxzbyBjYXJyaWVzIHRoZVxuICogcnVuJ3MgbXV0YWJsZSBzdGF0dXMgZm9yIHRoZSB0ZXJtaW5hbC1ydW4gY2hlY2suIEtleSByZXNvbHV0aW9uIGlzIGtlcHRcbiAqIHNlcGFyYXRlIHNvIGNhbGxlcnMgY2FuIGdhdGUgaXQgYmVoaW5kIHRoYXQgY2hlY2suXG4gKi9cbmludGVyZmFjZSBIb29rUmVzdW1lSW5mbyB7XG4gIHJlc3VtZUNvbnRleHQ6IEhvb2tSZXN1bWVDb250ZXh0O1xuICBzb3VyY2U6ICdob29rJyB8ICdydW5fZmFsbGJhY2snO1xuICBydW4/OiBXb3JrZmxvd1J1bjtcbn1cblxuLyoqIERlcml2ZSBhIHJlc3VtZSBjb250ZXh0IGZyb20gYSBmdWxsIHJ1biAoZmFsbGJhY2sgZm9yIHByZS1gcmVzdW1lQ29udGV4dGAgaG9va3MpLiAqL1xuZnVuY3Rpb24gcmVzdW1lQ29udGV4dEZyb21SdW4ocnVuOiBXb3JrZmxvd1J1bik6IEhvb2tSZXN1bWVDb250ZXh0IHtcbiAgY29uc3QgY29yZVZlcnNpb24gPSBydW4uZXhlY3V0aW9uQ29udGV4dD8ud29ya2Zsb3dDb3JlVmVyc2lvbjtcbiAgY29uc3QgdHJhY2VDYXJyaWVyID0gcnVuLmV4ZWN1dGlvbkNvbnRleHQ/LnRyYWNlQ2FycmllcjtcbiAgY29uc3QgaG9va1Jlc3VtZUlucHV0VmVyc2lvbiA9IHJ1bi5leGVjdXRpb25Db250ZXh0Py5ob29rUmVzdW1lSW5wdXRWZXJzaW9uO1xuICByZXR1cm4ge1xuICAgIGRlcGxveW1lbnRJZDogcnVuLmRlcGxveW1lbnRJZCxcbiAgICB3b3JrZmxvd05hbWU6IHJ1bi53b3JrZmxvd05hbWUsXG4gICAgcnVuU3BlY1ZlcnNpb246IHJ1bi5zcGVjVmVyc2lvbixcbiAgICB3b3JrZmxvd0NvcmVWZXJzaW9uOlxuICAgICAgdHlwZW9mIGNvcmVWZXJzaW9uID09PSAnc3RyaW5nJyA/IGNvcmVWZXJzaW9uIDogdW5kZWZpbmVkLFxuICAgIHRyYWNlQ2FycmllcjpcbiAgICAgIHRyYWNlQ2FycmllciAmJiB0eXBlb2YgdHJhY2VDYXJyaWVyID09PSAnb2JqZWN0J1xuICAgICAgICA/ICh0cmFjZUNhcnJpZXIgYXMgSG9va1Jlc3VtZUNvbnRleHRbJ3RyYWNlQ2FycmllciddKVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICBlbmNyeXB0aW9uUHVibGljS2V5OiBydW4uZW5jcnlwdGlvblB1YmxpY0tleSxcbiAgICBob29rUmVzdW1lSW5wdXRWZXJzaW9uOlxuICAgICAgdHlwZW9mIGhvb2tSZXN1bWVJbnB1dFZlcnNpb24gPT09ICdudW1iZXInXG4gICAgICAgID8gaG9va1Jlc3VtZUlucHV0VmVyc2lvblxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgfTtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHJlc3VtZSBjb250ZXh0IGZvciBhIGhvb2suIFVzZXMgdGhlIHN0b3JlZCBgcmVzdW1lQ29udGV4dGAgd2hlblxuICogcHJlc2VudCAoZmFzdCBwYXRoIOKAlCBubyBydW4gcmVhZCk7IG90aGVyd2lzZSBmZXRjaGVzIHRoZSBydW4gYW5kIHN5bnRoZXNpemVzXG4gKiBpdC4gRG9lcyBOT1QgcmVzb2x2ZSB0aGUgZW5jcnlwdGlvbiBrZXkg4oCUIGNhbGxlcnMgZG8gdGhhdCBzZXBhcmF0ZWx5LiBPbmx5XG4gKiB0aGUgZmFsbGJhY2sgcGF0aCBjYW4gZ2F0ZSBrZXkgd29yayBiZWhpbmQgYSBsb2NhbCB0ZXJtaW5hbC1ydW4gY2hlY2sgKGl0XG4gKiBoYXMgdGhlIGZldGNoZWQgcnVuKTsgdGhlIGZhc3QgcGF0aCdzIHN0b3JlZCBjb250ZXh0IGNhcnJpZXMgbm8gc3RhdHVzLCBzb1xuICogc2VhbC9zZXJpYWxpemF0aW9uIHdvcmsgbWF5IHJ1biBiZWZvcmUgdGhlIHJlY2VpdmluZyBzaWRlIHJlamVjdHNcbiAqIGBob29rX3JlY2VpdmVkYCBmb3IgYW4gZW5kZWQgcnVuLlxuICovXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlSG9va1Jlc3VtZUluZm8oaG9vazogSG9vayk6IFByb21pc2U8SG9va1Jlc3VtZUluZm8+IHtcbiAgaWYgKGhvb2sucmVzdW1lQ29udGV4dCkge1xuICAgIHJldHVybiB7IHJlc3VtZUNvbnRleHQ6IGhvb2sucmVzdW1lQ29udGV4dCwgc291cmNlOiAnaG9vaycgfTtcbiAgfVxuICBjb25zdCBydW4gPSBhd2FpdCAoYXdhaXQgZ2V0V29ybGRMYXp5KCkpLnJ1bnMuZ2V0KGhvb2sucnVuSWQpO1xuICByZXR1cm4ge1xuICAgIHJlc3VtZUNvbnRleHQ6IHJlc3VtZUNvbnRleHRGcm9tUnVuKHJ1biksXG4gICAgc291cmNlOiAncnVuX2ZhbGxiYWNrJyxcbiAgICBydW4sXG4gIH07XG59XG5cbi8qKlxuICogUmVzb2x2ZSB0aGUgcnVuJ3Mgc3ltbWV0cmljIGtleSBmb3IgYSBwYXlsb2FkIFdSSVRFLCBhcyBhIGJhcmUgYENyeXB0b0tleWBcbiAqIChgaW1wb3J0S2V5YCkg4oCUIHRoZSBgZW5jcmAgd3JpdGUgZmFsbGJhY2sgdXNlZCB3aGVuIHRoZSBydW4gcHVibGlzaGVkIG5vXG4gKiBwdWJsaWMga2V5IHRvIHNlYWwgdG8uIFdyaXRpbmcgbmVlZHMgb25seSB0aGUgQUVTIGtleSwgbm90IHRoZSByZWFkLXNpZGVcbiAqIGtleXBhaXIuIE9uIHRoZSBmYXN0IHBhdGggdGhpcyBuZWVkcyBvbmx5IGBydW5JZGAgKyBgZGVwbG95bWVudElkYCAobm8gcnVuXG4gKiBlbnRpdHkpOyBvbiB0aGUgZmFsbGJhY2sgcGF0aCB0aGUgYWxyZWFkeSBmZXRjaGVkIHJ1biBpcyByZXVzZWQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVIb29rRW5jcnlwdGlvbktleShcbiAgaG9vazogSG9vayxcbiAgaW5mbzogSG9va1Jlc3VtZUluZm9cbik6IFByb21pc2U8QXdhaXRlZDxSZXR1cm5UeXBlPHR5cGVvZiBpbXBvcnRLZXk+PiB8IHVuZGVmaW5lZD4ge1xuICBjb25zdCB3b3JsZCA9IGF3YWl0IGdldFdvcmxkTGF6eSgpO1xuICBjb25zdCByYXdLZXkgPSBpbmZvLnJ1blxuICAgID8gYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKGluZm8ucnVuKVxuICAgIDogYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKGhvb2sucnVuSWQsIHtcbiAgICAgICAgZGVwbG95bWVudElkOiBpbmZvLnJlc3VtZUNvbnRleHQuZGVwbG95bWVudElkLFxuICAgICAgfSk7XG4gIHJldHVybiByYXdLZXkgPyBhd2FpdCBpbXBvcnRLZXkocmF3S2V5KSA6IHVuZGVmaW5lZDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0SG9va0J5VG9rZW5XaXRoS2V5KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPHtcbiAgaG9vazogSG9vaztcbiAgZW5jcnlwdGlvbktleTogUGF5bG9hZEtleSB8IHVuZGVmaW5lZDtcbn0+IHtcbiAgY29uc3Qgd29ybGQgPSBhd2FpdCBnZXRXb3JsZExhenkoKTtcbiAgY29uc3QgaG9vayA9IGF3YWl0IHdvcmxkLmhvb2tzLmdldEJ5VG9rZW4odG9rZW4pO1xuXG4gIC8vIE9ubHkgYSBob29rIHRoYXQgYWN0dWFsbHkgY2FycmllcyBtZXRhZGF0YSBuZWVkcyB0aGUgcnVuJ3Mga2V5IHJlc29sdmVkXG4gIC8vIGhlcmU6IGh5ZHJhdGluZyB0aGF0IG1ldGFkYXRhIGlzIGEgUkVBRCwgc28gZGVyaXZlIHRoZSBmdWxsIFJ1blBheWxvYWRLZXlzXG4gIC8vICh3aGljaCBvcGVucyBzZWFsZWQgYGVuY3BgIG1ldGFkYXRhLCBub3QganVzdCBzeW1tZXRyaWMgYGVuY3JgKS4gVGhlIGNvbW1vblxuICAvLyBkZWZhdWx0IHdlYmhvb2sg4oCUIGNyZWF0ZVdlYmhvb2soKSB3aXRoIG5vIGByZXNwb25kV2l0aGAg4oCUIHN0b3JlcyBub1xuICAvLyBtZXRhZGF0YSwgc28gaXQgc2tpcHMgdGhpcyBlbnRpcmVseTogbm8gfjM1MG1zIGBydW4ta2V5YCBBUEkgcm91bmQgdHJpcCxcbiAgLy8gYW5kLCBjcnVjaWFsbHksIG5vIHJlc29sdmVkIGtleSBoYW5kZWQgdG8gYHJlc3VtZUhvb2tgLCBsZWF2aW5nIGl0IGZyZWUgdG9cbiAgLy8gc2VhbCB0aGUgcGF5bG9hZCB0byB0aGUgcnVuJ3MgcHVibGlzaGVkIHB1YmxpYyBrZXkgaW5zdGVhZC4gTWV0YWRhdGEtXG4gIC8vIGJlYXJpbmcgd2ViaG9va3Mgc3RpbGwgbGVnaXRpbWF0ZWx5IHBheSBvbmUgbG9va3VwIHRvIGh5ZHJhdGUuXG4gIGxldCBlbmNyeXB0aW9uS2V5OiBQYXlsb2FkS2V5IHwgdW5kZWZpbmVkO1xuICBpZiAodHlwZW9mIGhvb2subWV0YWRhdGEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgY29uc3QgaW5mbyA9IGF3YWl0IHJlc29sdmVIb29rUmVzdW1lSW5mbyhob29rKTtcbiAgICAvLyBPbiB0aGUgZmFzdCBwYXRoIHRoaXMgcmVzb2x2ZXMgdGhlIGtleSBieSBydW5JZCArIGRlcGxveW1lbnRJZCAobm8gcnVuXG4gICAgLy8gcmVhZCk7IG9uIHRoZSBmYWxsYmFjayBwYXRoIGl0IHJldXNlcyB0aGUgYWxyZWFkeS1mZXRjaGVkIHJ1bi5cbiAgICBjb25zdCByYXdLZXkgPSBpbmZvLnJ1blxuICAgICAgPyBhd2FpdCB3b3JsZC5nZXRFbmNyeXB0aW9uS2V5Rm9yUnVuPy4oaW5mby5ydW4pXG4gICAgICA6IGF3YWl0IHdvcmxkLmdldEVuY3J5cHRpb25LZXlGb3JSdW4/Lihob29rLnJ1bklkLCB7XG4gICAgICAgICAgZGVwbG95bWVudElkOiBpbmZvLnJlc3VtZUNvbnRleHQuZGVwbG95bWVudElkLFxuICAgICAgICB9KTtcbiAgICBlbmNyeXB0aW9uS2V5ID0gcmF3S2V5ID8gYXdhaXQgZGVyaXZlUnVuUGF5bG9hZEtleXMocmF3S2V5KSA6IHVuZGVmaW5lZDtcbiAgICBob29rLm1ldGFkYXRhID0gYXdhaXQgaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gICAgICBob29rLm1ldGFkYXRhIGFzIGFueSxcbiAgICAgIGhvb2sucnVuSWQsXG4gICAgICBlbmNyeXB0aW9uS2V5XG4gICAgKTtcbiAgfVxuICByZXR1cm4geyBob29rLCBlbmNyeXB0aW9uS2V5IH07XG59XG5cbi8qKlxuICogR2V0IHRoZSBob29rIGJ5IHRva2VuIHRvIGZpbmQgdGhlIGFzc29jaWF0ZWQgd29ya2Zsb3cgcnVuLFxuICogYW5kIGh5ZHJhdGUgdGhlIGBtZXRhZGF0YWAgcHJvcGVydHkgaWYgaXQgd2FzIHNldCBmcm9tIHdpdGhpblxuICogdGhlIHdvcmtmbG93IHJ1bi5cbiAqXG4gKiBBIEhvb2sga2VwdCBieSBtaW5pbXVtIHJldGVudGlvbiByZW1haW5zIGF2YWlsYWJsZSBoZXJlIGFmdGVyIGl0cyBydW4gZW5kcyxcbiAqIGJ1dCBjYW5ub3QgYmUgcmVzdW1lZC5cbiAqXG4gKiBAcGFyYW0gdG9rZW4gLSBUaGUgdW5pcXVlIHRva2VuIGlkZW50aWZ5aW5nIHRoZSBob29rXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIb29rQnlUb2tlbih0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxIb29rPiB7XG4gIGNvbnN0IHsgaG9vayB9ID0gYXdhaXQgZ2V0SG9va0J5VG9rZW5XaXRoS2V5KHRva2VuKTtcbiAgcmV0dXJuIGhvb2s7XG59XG5cbi8qKlxuICogVGhlIHJlc3VsdCBvZiB7QGxpbmsgcmVzdW1lSG9va306IGEge0BsaW5rIEhvb2t9IGF1Z21lbnRlZCB3aXRoIGFuIG9wdGlvbmFsXG4gKiByZXNpbGllbmNlIHNpZ25hbC5cbiAqXG4gKiBPbiB0aGUgcGFyYWxsZWwgZmFzdCBwYXRoLCBgcmVzdW1lSG9vaygpYCB3cml0ZXMgdGhlIGBob29rX3JlY2VpdmVkYCBldmVudCBhbmRcbiAqIGRpc3BhdGNoZXMgdGhlIHdvcmtmbG93IHF1ZXVlIG1lc3NhZ2UgY29uY3VycmVudGx5LiBXaGVuIHRoZSBkaXJlY3QgZXZlbnRcbiAqIHdyaXRlIGZhaWxzICp0cmFuc2llbnRseSog4oCUIGEgNDI5LzV4eCwgYSB0cmFuc3BvcnQgZXJyb3IsIG9yIGFuIGV4cGVjdGVkXG4gKiBgKHJ1bklkLCByZXN1bWVJZClgIGNvbmZsaWN0IHdpdGggaXRzIG93biByZS1lbnN1cmluZyBjb25zdW1lciDigJQgYnV0IHRoZSBxdWV1ZVxuICogZGlzcGF0Y2ggc3VjY2VlZHMsIHRoZSByZXN1bWUgaXMgc3RpbGwgZ3VhcmFudGVlZDogdGhlIHF1ZXVlIGNvbnN1bWVyXG4gKiBpZGVtcG90ZW50bHkgbWF0ZXJpYWxpemVzIHRoZSBgaG9va19yZWNlaXZlZGAgZXZlbnQgZnJvbSB0aGUgcGF5bG9hZCBjYXJyaWVkXG4gKiBvbiB0aGUgbWVzc2FnZSBiZWZvcmUgcmVwbGF5LiBJbiB0aGF0IHJlY292ZXJlZCBjYXNlIHRoZSByZXR1cm5lZCBob29rIGNhcnJpZXNcbiAqIGByZXNpbGllbnRSZXN1bWU6IHRydWVgLlxuICpcbiAqIE9uIHRoZSBoYXBweSBwYXRoICh0aGUgZGlyZWN0IHdyaXRlIGxhbmRlZCkgYW5kIG9uIHRoZSBzZXF1ZW50aWFsIGZhbGxiYWNrXG4gKiBwYXRoLCB0aGUgZmxhZyBpcyBhYnNlbnQgKGB1bmRlZmluZWRgKS4gQ2FsbGVycyB0aGF0IGRvbid0IGNhcmUgYWJvdXQgdGhlXG4gKiBkaXN0aW5jdGlvbiBjYW4gdHJlYXQgdGhlIHJlc3VsdCBhcyBhIHBsYWluIHtAbGluayBIb29rfS5cbiAqL1xuZXhwb3J0IHR5cGUgUmVzdW1lZEhvb2sgPSBIb29rICYgeyByZXNpbGllbnRSZXN1bWU/OiBib29sZWFuIH07XG5cbi8qKlxuICogUmVzdW1lcyBhIHdvcmtmbG93IHJ1biBieSBzZW5kaW5nIGEgcGF5bG9hZCB0byBhIGhvb2sgaWRlbnRpZmllZCBieSBpdHMgdG9rZW4uXG4gKlxuICogVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgZXh0ZXJuYWxseSAoZS5nLiwgZnJvbSBhbiBBUEkgcm91dGUgb3Igc2VydmVyIGFjdGlvbilcbiAqIHRvIHNlbmQgZGF0YSB0byBhIGhvb2sgYW5kIHJlc3VtZSB0aGUgYXNzb2NpYXRlZCB3b3JrZmxvdyBydW4uXG4gKlxuICogQHBhcmFtIHRva2VuT3JIb29rIC0gVGhlIHVuaXF1ZSB0b2tlbiBpZGVudGlmeWluZyB0aGUgaG9vaywgb3IgdGhlIGhvb2sgb2JqZWN0IGl0c2VsZlxuICogQHBhcmFtIHBheWxvYWQgLSBUaGUgZGF0YSBwYXlsb2FkIHRvIHNlbmQgdG8gdGhlIGhvb2tcbiAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSB7QGxpbmsgUmVzdW1lZEhvb2t9XG4gKiBAdGhyb3dzIHtIb29rTm90Rm91bmRFcnJvcn0gSWYgdGhlIEhvb2sgZG9lcyBub3QgZXhpc3Qgb3IgaXRzIHJ1biBoYXMgZW5kZWRcbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqIGBgYHRzXG4gKiAvLyBJbiBhbiBBUEkgcm91dGVcbiAqIGltcG9ydCB7IHJlc3VtZUhvb2sgfSBmcm9tICdAd29ya2Zsb3cvY29yZS9ydW50aW1lJztcbiAqXG4gKiBleHBvcnQgYXN5bmMgZnVuY3Rpb24gUE9TVChyZXF1ZXN0OiBSZXF1ZXN0KSB7XG4gKiAgIGNvbnN0IHsgdG9rZW4sIGRhdGEgfSA9IGF3YWl0IHJlcXVlc3QuanNvbigpO1xuICpcbiAqICAgdHJ5IHtcbiAqICAgICBjb25zdCBob29rID0gYXdhaXQgcmVzdW1lSG9vayh0b2tlbiwgZGF0YSk7XG4gKiAgICAgcmV0dXJuIFJlc3BvbnNlLmpzb24oeyBydW5JZDogaG9vay5ydW5JZCB9KTtcbiAqICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAqICAgICByZXR1cm4gbmV3IFJlc3BvbnNlKCdIb29rIG5vdCBmb3VuZCcsIHsgc3RhdHVzOiA0MDQgfSk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzdW1lSG9vazxUID0gYW55PihcbiAgdG9rZW5Pckhvb2s6IHN0cmluZyB8IEhvb2ssXG4gIHBheWxvYWQ6IFQsXG4gIGVuY3J5cHRpb25LZXlPdmVycmlkZT86IFBheWxvYWRLZXlcbik6IFByb21pc2U8UmVzdW1lZEhvb2s+IHtcbiAgLy8gUHVibGljIGVudHJ5IHBvaW50LiBJdCBuZXZlciBhdHRlc3RzIGhvb2sgZnJlc2huZXNzLCBzbyBhIEhvb2sgb2JqZWN0XG4gIC8vIHN1cHBsaWVkIGhlcmUg4oCUIHdoaWNoIG1heSBjYXJyeSBhIGByZXN1bWVDYXBhYmlsaXRpZXNgIGNhY2hlZCBiZWZvcmUgYVxuICAvLyBzZXJ2ZXIgcm9sbGJhY2sgb3Iga2lsbCBzd2l0Y2gg4oCUIGlzIGlnbm9yZWQgYnkgdGhlIGR5bmFtaWMtZGVkdXAgZ2F0ZSBhbmRcbiAgLy8gZmFpbHMgY2xvc2VkIHRvIHRoZSBzZXF1ZW50aWFsIHBhdGguIE9ubHkgYHJlc3VtZVdlYmhvb2tgLCB3aGljaCBmZXRjaGVzXG4gIC8vIHRoZSBob29rIGJ5IHRva2VuIGluLWxpbmUgZHVyaW5nIHRoZSBzYW1lIHJlc3VtZSwgcmVhY2hlcyB0aGUgaW50ZXJuYWxcbiAgLy8gaW1wbGVtZW50YXRpb24gd2l0aCB0aGUgZnJlc2ggYXR0ZXN0YXRpb24gc2V0LiBLZWVwaW5nIHRoZSBmcmVzaG5lc3MgZmxhZ1xuICAvLyBvZmYgdGhlIGV4cG9ydGVkIHNpZ25hdHVyZSBwcmV2ZW50cyBhIGNhbGxlciBmcm9tIHBhc3NpbmcgYSBzdGFsZSBIb29rIHBsdXNcbiAgLy8gYHRydWVgIGFuZCByZWFjdGl2YXRpbmcgZHluYW1pYyBkZWR1cCBhZ2FpbnN0IGEgcm9sbGVkLWJhY2sgYmFja2VuZC5cbiAgcmV0dXJuIHJlc3VtZUhvb2tJbXBsKHRva2VuT3JIb29rLCBwYXlsb2FkLCBlbmNyeXB0aW9uS2V5T3ZlcnJpZGUsIGZhbHNlKTtcbn1cblxuLyoqXG4gKiBJbnRlcm5hbCBpbXBsZW1lbnRhdGlvbiBvZiB7QGxpbmsgcmVzdW1lSG9va30uIE5PVCBleHBvcnRlZDogdGhlXG4gKiBgaG9va0ZyZXNobHlMb29rZWRVcGAgYXR0ZXN0YXRpb24gbXVzdCBuZXZlciBiZSByZWFjaGFibGUgYnkgcHVibGljIGNhbGxlcnNcbiAqIChzZWUgdGhlIHdyYXBwZXIgYWJvdmUpLlxuICpcbiAqIEBwYXJhbSBob29rRnJlc2hseUxvb2tlZFVwIC0gQXR0ZXN0cyB0aGF0IGEgc3VwcGxpZWQgSG9vayBvYmplY3Qgd2FzIGZldGNoZWRcbiAqICAgYnkgdG9rZW4gZHVyaW5nIFRISVMgcmVzdW1lLCBzbyBpdHMgcmVzcG9uc2Utb25seSBgcmVzdW1lQ2FwYWJpbGl0aWVzYFxuICogICByZWZsZWN0cyB0aGUgbGl2ZSBiYWNrZW5kIGFuZCBtYXkgYmUgdHJ1c3RlZCBmb3IgdGhlIGR5bmFtaWMtZGVkdXAgZ2F0ZS5cbiAqICAgQSB0b2tlbiBzdHJpbmcgaXMgYWx3YXlzIGZldGNoZWQgZnJlc2ggaGVyZSwgc28gaXQgaXMgaW1wbGljaXRseSBmcmVzaC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVzdW1lSG9va0ltcGw8VCA9IGFueT4oXG4gIHRva2VuT3JIb29rOiBzdHJpbmcgfCBIb29rLFxuICBwYXlsb2FkOiBULFxuICBlbmNyeXB0aW9uS2V5T3ZlcnJpZGU6IFBheWxvYWRLZXkgfCB1bmRlZmluZWQsXG4gIGhvb2tGcmVzaGx5TG9va2VkVXA6IGJvb2xlYW5cbik6IFByb21pc2U8UmVzdW1lZEhvb2s+IHtcbiAgcmV0dXJuIGF3YWl0IHdhaXRlZFVudGlsKCgpID0+IHtcbiAgICByZXR1cm4gdHJhY2UoJ2hvb2sucmVzdW1lJywgYXN5bmMgKHNwYW4pID0+IHtcbiAgICAgIGNvbnN0IHdvcmxkID0gYXdhaXQgZ2V0V29ybGRMYXp5KCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHN1cHBsaWVkVG9rZW4gPSB0eXBlb2YgdG9rZW5Pckhvb2sgPT09ICdzdHJpbmcnO1xuICAgICAgICBjb25zdCBob29rOiBIb29rID0gc3VwcGxpZWRUb2tlblxuICAgICAgICAgID8gYXdhaXQgd29ybGQuaG9va3MuZ2V0QnlUb2tlbih0b2tlbk9ySG9vaylcbiAgICAgICAgICA6IHRva2VuT3JIb29rO1xuICAgICAgICAvLyBUaGUgZHluYW1pYywgcmVzcG9uc2Utb25seSBgcmVzdW1lQ2FwYWJpbGl0aWVzYCBtYXkgb25seSBiZSB0cnVzdGVkXG4gICAgICAgIC8vIHdoZW4gaXQgY2FtZSBmcm9tIGEgYnktdG9rZW4gbG9va3VwIHBlcmZvcm1lZCBkdXJpbmcgdGhpcyByZXN1bWUuXG4gICAgICAgIGNvbnN0IGhvb2tSZXN1bWVDYXBhYmlsaXRpZXNBcmVGcmVzaCA9XG4gICAgICAgICAgc3VwcGxpZWRUb2tlbiB8fCBob29rRnJlc2hseUxvb2tlZFVwO1xuXG4gICAgICAgIGNvbnN0IGluZm8gPSBhd2FpdCByZXNvbHZlSG9va1Jlc3VtZUluZm8oaG9vayk7XG4gICAgICAgIGNvbnN0IHsgcmVzdW1lQ29udGV4dCB9ID0gaW5mbztcblxuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuSG9va1Rva2VuKGhvb2sudG9rZW4pLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Ib29rSWQoaG9vay5ob29rSWQpLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1bklkKGhvb2sucnVuSWQpLFxuICAgICAgICAgICd3b3JrZmxvdy5ob29rLnJlc3VtZV9jb250ZXh0X3NvdXJjZSc6IGluZm8uc291cmNlLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBUaGUgc3RvcmVkIGByZXN1bWVDb250ZXh0YCBpbnRlbnRpb25hbGx5IG9taXRzIHRoZSBydW4ncyBtdXRhYmxlXG4gICAgICAgIC8vIHN0YXR1cywgc28gdGhpcyBlYXJseSBjbGllbnQtc2lkZSByZWplY3Rpb24gb25seSBydW5zIG9uIHRoZVxuICAgICAgICAvLyBmYWxsYmFjayBwYXRoICh3aGljaCBmZXRjaGVkIHRoZSBydW4pLiBPbiB0aGUgZmFzdCBwYXRoIHRoZSB0ZXJtaW5hbFxuICAgICAgICAvLyBjaGVjayBoYXBwZW5zIHNlcnZlci1zaWRlOiBgaG9va19yZWNlaXZlZGAgYWdhaW5zdCBhbiBlbmRlZCBydW4gaXNcbiAgICAgICAgLy8gcmVqZWN0ZWQsIHdoaWNoIHRoZSBjYXRjaCBhcm91bmQgYHdvcmxkLmV2ZW50cy5jcmVhdGVgIGJlbG93IHJlLWtleXNcbiAgICAgICAgLy8gdG8gSG9va05vdEZvdW5kRXJyb3Ig4oCUIHNhbWUgcHVibGljIGNvbnRyYWN0LCBubyBydW4gcHJlLWZldGNoLlxuICAgICAgICBpZiAoaW5mby5ydW4gJiYgaXNUZXJtaW5hbFdvcmtmbG93UnVuU3RhdHVzKGluZm8ucnVuLnN0YXR1cykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgSG9va05vdEZvdW5kRXJyb3IoaG9vay50b2tlbik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayB0aGUgdGFyZ2V0IHJ1bidzIGNhcGFiaWxpdGllcyB0byBlbnN1cmUgd2UgZW5jb2RlIHRoZVxuICAgICAgICAvLyBwYXlsb2FkIGluIGEgZm9ybWF0IHRoZSBydW4ncyBkZXBsb3ltZW50IGNhbiBkZWNvZGUuIEZvciBleGFtcGxlLFxuICAgICAgICAvLyBydW5zIGNyZWF0ZWQgYmVmb3JlIGVuY3J5cHRpb24gc3VwcG9ydCB3YXMgYWRkZWQgY2Fubm90IGRlY29kZVxuICAgICAgICAvLyB0aGUgJ2VuY3InIHNlcmlhbGl6YXRpb24gZm9ybWF0LCBhbmQgcnVucyBjcmVhdGVkIGJlZm9yZVxuICAgICAgICAvLyBieXRlLXN0cmVhbSBmcmFtaW5nIHN1cHBvcnQgY2Fubm90IGRlY29kZSBmcmFtZWQgYnl0ZSBzdHJlYW1zLlxuICAgICAgICBjb25zdCBjYXBhYmlsaXRpZXMgPSBnZXRSdW5DYXBhYmlsaXRpZXMoXG4gICAgICAgICAgcmVzdW1lQ29udGV4dC53b3JrZmxvd0NvcmVWZXJzaW9uXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gUmVzb2x2ZSBob3cgdG8gZW5jcnlwdCB0aGUgcGF5bG9hZCBmb3IgdGhlIHRhcmdldCBydW4gKGEgV1JJVEUpLlxuICAgICAgICAvL1xuICAgICAgICAvLyBQcmVmZXJyZWQgcGF0aDogc2VhbCB0byB0aGUgcnVuJ3MgcHVibGlzaGVkIFgyNTUxOSBwdWJsaWMga2V5LCB3aGljaFxuICAgICAgICAvLyB0aGUgc3RvcmVkIGByZXN1bWVDb250ZXh0YCBjYXJyaWVzIGlubGluZS4gT24gdGhlIGZhc3QgcGF0aCB0aGlzIGlzXG4gICAgICAgIC8vIHRoZSB3aG9sZSB3aW4g4oCUIG5vIHJ1biByZWFkIEFORCBubyBgZ2V0RW5jcnlwdGlvbktleUZvclJ1bmAsIHdob3NlXG4gICAgICAgIC8vIH4zNTBtcyBgcnVuLWtleWAgQVBJIHJvdW5kIHRyaXAgZG9taW5hdGVzIGNyb3NzLWRlcGxveW1lbnQgaG9va1xuICAgICAgICAvLyByZXN1bXB0aW9uIGxhdGVuY3kuIChPbiB0aGUgZmFsbGJhY2sgcGF0aCB0aGUga2V5IGlzIHN5bnRoZXNpemVkXG4gICAgICAgIC8vIGZyb20gdGhlIGZldGNoZWQgcnVuLCB3aGljaCBhbHNvIGNhcnJpZXMgaXQuKVxuICAgICAgICAvL1xuICAgICAgICAvLyBTZWFsaW5nIGFsc28gZHJvcHMgcHJpdmlsZWdlOiB0aGUgcmVzdW1lciBlbmRzIHVwIGFibGUgdG8gd3JpdGUgYVxuICAgICAgICAvLyBwYXlsb2FkIGZvciB0aGUgcnVuIHdpdGhvdXQgYmVpbmcgYWJsZSB0byByZWFkIGFueXRoaW5nIG9mIHRoZVxuICAgICAgICAvLyBydW4ncywgd2hlcmUgZmV0Y2hpbmcgdGhlIHN5bW1ldHJpYyBrZXkgZ3JhbnRzIGJvdGguXG4gICAgICAgIC8vXG4gICAgICAgIC8vIERlbGliZXJhdGVseSBOT1QgZ2F0ZWQgb24gYGNhcGFiaWxpdGllcy5zdXBwb3J0ZWRGb3JtYXRzYCB0aGUgd2F5XG4gICAgICAgIC8vIHRoZSBzeW1tZXRyaWMgZmFsbGJhY2sgYmVsb3cgZ2F0ZXMgYGVuY3JgOiBwcmVzZW5jZSBvZiB0aGUgcHVibGljIGtleVxuICAgICAgICAvLyBpcyBpdHNlbGYgdGhlIGdhdGUuIEEgcnVuIG9ubHkgY2FycmllcyBvbmUgaWYgdGhlIHJ1bnRpbWUgdGhhdFxuICAgICAgICAvLyBjcmVhdGVkIGl0IGNvdWxkIGFsc28gb3BlbiBhIHNlYWxlZCBwYXlsb2FkLCBhbmQgcnVucyBhcmUgcGlubmVkIHRvXG4gICAgICAgIC8vIHRoZWlyIGNyZWF0aW5nIGRlcGxveW1lbnQsIHNvIHByZXNlbmNlIGlzIGEgbW9yZSByZWxpYWJsZSBhdHRlc3RhdGlvblxuICAgICAgICAvLyB0aGFuIGEgdmVyc2lvbiBjb21wYXJlIOKAlCBhbmQgaXQgc3RheXMgY29ycmVjdCBldmVuIHdoZW4gcGFja2FnZVxuICAgICAgICAvLyB2ZXJzaW9ucyBkcmlmdC5cbiAgICAgICAgbGV0IHBheWxvYWRLZXk6IFBheWxvYWRLZXkgfCB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IHJ1blB1YmxpY0tleSA9IGVuY3J5cHRpb25LZXlPdmVycmlkZVxuICAgICAgICAgID8gLy8gVGhlIGNhbGxlciBhbHJlYWR5IGhvbGRzIGEga2V5IChyZXN1bWVXZWJob29rIHJlc29sdmVkIG9uZSB0b1xuICAgICAgICAgICAgLy8gaHlkcmF0ZSBob29rIG1ldGFkYXRhKSwgc28gc2VhbGluZyB3b3VsZCBhZGQgYW4gRUNESCBmb3Igbm9cbiAgICAgICAgICAgIC8vIHNhdmVkIHJvdW5kIHRyaXAuIFJldXNlIHdoYXQgaXQgcmVzb2x2ZWQuXG4gICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgICA6IGRlY29kZVJ1blB1YmxpY0tleShyZXN1bWVDb250ZXh0LmVuY3J5cHRpb25QdWJsaWNLZXkpO1xuXG4gICAgICAgIGlmIChydW5QdWJsaWNLZXkpIHtcbiAgICAgICAgICBwYXlsb2FkS2V5ID0gc2VhbFRvKHJ1blB1YmxpY0tleSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gU3ltbWV0cmljIGBlbmNyYCB3cml0ZSBmYWxsYmFjazogbmVlZHMgb25seSB0aGUgQUVTIGtleVxuICAgICAgICAgIC8vIChhIGJhcmUgQ3J5cHRvS2V5IHZpYSBgcmVzb2x2ZUhvb2tFbmNyeXB0aW9uS2V5YCksIG5vdCB0aGVcbiAgICAgICAgICAvLyByZWFkLXNpZGUgUnVuUGF5bG9hZEtleXMuXG4gICAgICAgICAgbGV0IGVuY3J5cHRpb25LZXkgPVxuICAgICAgICAgICAgZW5jcnlwdGlvbktleU92ZXJyaWRlID8/XG4gICAgICAgICAgICAoYXdhaXQgcmVzb2x2ZUhvb2tFbmNyeXB0aW9uS2V5KGhvb2ssIGluZm8pKTtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAhY2FwYWJpbGl0aWVzLnN1cHBvcnRlZEZvcm1hdHMuaGFzKFNlcmlhbGl6YXRpb25Gb3JtYXQuRU5DUllQVEVEKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgZW5jcnlwdGlvbktleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcGF5bG9hZEtleSA9IGVuY3J5cHRpb25LZXk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb21wcmVzcyBvbmx5IHdoZW4gdGhlIHRhcmdldCBydW4gYW5kIGl0cyBkZXBsb3ltZW50IHN1cHBvcnQgdGhlXG4gICAgICAgIC8vIGNvbXByZXNzaW9uIGZvcm1hdHMgaW50cm9kdWNlZCB3aXRoIHNwZWMgdmVyc2lvbiA1LlxuICAgICAgICBjb25zdCBjb21wcmVzc2lvbiA9XG4gICAgICAgICAgKHJlc3VtZUNvbnRleHQucnVuU3BlY1ZlcnNpb24gPz8gMCkgPj1cbiAgICAgICAgICAgIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DT01QUkVTU0lPTiAmJlxuICAgICAgICAgIGNhcGFiaWxpdGllcy5zdXBwb3J0ZWRGb3JtYXRzLmhhcyhTZXJpYWxpemF0aW9uRm9ybWF0LkdaSVApO1xuXG4gICAgICAgIC8vIERlaHlkcmF0ZSB0aGUgcGF5bG9hZCBmb3Igc3RvcmFnZVxuICAgICAgICBjb25zdCBvcHM6IFByb21pc2U8YW55PltdID0gW107XG4gICAgICAgIGNvbnN0IHYxQ29tcGF0ID0gaXNMZWdhY3lTcGVjVmVyc2lvbihob29rLnNwZWNWZXJzaW9uKTtcbiAgICAgICAgY29uc3QgZGVoeWRyYXRlZFBheWxvYWQgPSBhd2FpdCBkZWh5ZHJhdGVTdGVwUmV0dXJuVmFsdWUoXG4gICAgICAgICAgcGF5bG9hZCxcbiAgICAgICAgICBob29rLnJ1bklkLFxuICAgICAgICAgIHBheWxvYWRLZXksXG4gICAgICAgICAgb3BzLFxuICAgICAgICAgIGdsb2JhbFRoaXMsXG4gICAgICAgICAgdjFDb21wYXQsXG4gICAgICAgICAgY2FwYWJpbGl0aWVzLmZyYW1lZEJ5dGVTdHJlYW1zLFxuICAgICAgICAgIGNvbXByZXNzaW9uXG4gICAgICAgICk7XG4gICAgICAgIC8vIFRoZXNlIHBheWxvYWQtc3RyZWFtIG9wcyBhcmUgZmx1c2hlZCBpbiB0aGUgYmFja2dyb3VuZDsgdGhlXG4gICAgICAgIC8vIHByb21pc2UgaGFuZGVkIHRvIHdhaXRVbnRpbCBtdXN0IG5ldmVyIHJlamVjdCAoYW4gdW5jb25zdW1lZFxuICAgICAgICAvLyB3YWl0VW50aWwgcmVqZWN0aW9uIGNyYXNoZXMgdGhlIHByb2Nlc3MgYXMgdW5oYW5kbGVkUmVqZWN0aW9uKSxcbiAgICAgICAgLy8gc28gdW5leHBlY3RlZCBmYWlsdXJlcyBhcmUgbG9nZ2VkIGluc3RlYWQuXG4gICAgICAgIC8vIE5PVEU6IHJlamVjdGlvbnMgd2l0aCBgdW5kZWZpbmVkYCBhcmUgYW4gZXhwZWN0ZWQgYXJ0aWZhY3Qgb2YgdGhlXG4gICAgICAgIC8vIHdlYmhvb2sgYnVuZGxlIGFuZCBhcmUgaWdub3JlZCBlbnRpcmVseS5cbiAgICAgICAgc2FmZVdhaXRVbnRpbChQcm9taXNlLmFsbChvcHMpLCAoZXJyKSA9PiB7XG4gICAgICAgICAgaWYgKGVyciA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG4gICAgICAgICAgcnVudGltZUxvZ2dlci53YXJuKCdCYWNrZ3JvdW5kIGZsdXNoIG9mIGhvb2sgcGF5bG9hZCBvcHMgZmFpbGVkJywge1xuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogaG9vay5ydW5JZCxcbiAgICAgICAgICAgIGhvb2tJZDogaG9vay5ob29rSWQsXG4gICAgICAgICAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dOYW1lKHJlc3VtZUNvbnRleHQud29ya2Zsb3dOYW1lKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gTGluayB0byB0aGUgcnVuLW9yaWdpbiBjb250ZXh0IGZyb20gdGhlIHN0b3JlZCB0cmFjZSBjYXJyaWVyXG4gICAgICAgIC8vIChza2lwcGVkIHdoZW4gYWJzZW50IG9yIGludmFsaWQpLiBSZXNvbHZlZCBiZWZvcmUgZGlzcGF0Y2ggc28gYm90aFxuICAgICAgICAvLyB0aGUgc2VxdWVudGlhbCBhbmQgcGFyYWxsZWwgcGF0aHMgYXR0YWNoIGl0LlxuICAgICAgICBjb25zdCBvcmlnaW5MaW5rID0gYXdhaXQgbGlua1RvVHJhY2VDYXJyaWVyKHJlc3VtZUNvbnRleHQudHJhY2VDYXJyaWVyKTtcbiAgICAgICAgaWYgKG9yaWdpbkxpbmspIHtcbiAgICAgICAgICBzcGFuPy5hZGRMaW5rPy4ob3JpZ2luTGluayk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBldmVudERhdGEgPSB7XG4gICAgICAgICAgLi4uKHYxQ29tcGF0ID8ge30gOiB7IHRva2VuOiBob29rLnRva2VuIH0pLFxuICAgICAgICAgIHBheWxvYWQ6IGRlaHlkcmF0ZWRQYXlsb2FkLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHF1ZXVlTmFtZSA9IGdldFdvcmtmbG93UXVldWVOYW1lKHJlc3VtZUNvbnRleHQud29ya2Zsb3dOYW1lKTtcbiAgICAgICAgY29uc3QgcXVldWVPcHRpb25zID0ge1xuICAgICAgICAgIGRlcGxveW1lbnRJZDogcmVzdW1lQ29udGV4dC5kZXBsb3ltZW50SWQsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IHJlc3VtZUNvbnRleHQucnVuU3BlY1ZlcnNpb24gPz8gU1BFQ19WRVJTSU9OX0xFR0FDWSxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBEZWNpZGUgd2hldGhlciB0byBwYXJhbGxlbGl6ZSB0aGUgYGhvb2tfcmVjZWl2ZWRgIHdyaXRlIGFuZCB0aGUgcXVldWVcbiAgICAgICAgLy8gcHVibGlzaC4gVGhlIGZhc3QgcGF0aCBpcyBvbmx5IHNhZmUgd2hlbiBFVkVSWSBwcmVjb25kaXRpb24gaG9sZHM7IHRoZVxuICAgICAgICAvLyBmaXJzdCB0aGF0IGZhaWxzIG5hbWVzIHRoZSBmYWxsYmFjayByZWFzb24gKGVtaXR0ZWQgYXMgYSBzcGFuXG4gICAgICAgIC8vIGF0dHJpYnV0ZSBmb3Igb2JzZXJ2YWJpbGl0eSwgYW5kIHRvIG1ha2UgXCJ3aHkgZGlkIHRoaXMgcnVuIHNlcXVlbnRpYWxcIlxuICAgICAgICAvLyBhbnN3ZXJhYmxlIGluIHByb2R1Y3Rpb24pLiBBbGwgY29uZGl0aW9uczpcbiAgICAgICAgLy9cbiAgICAgICAgLy8gIC0ga2lsbCBzd2l0Y2g6IGBXT1JLRkxPV19ESVNBQkxFX0xBWllfSE9PS19SRVNVTUVgIGZvcmNlcyBzZXF1ZW50aWFsXG4gICAgICAgIC8vICAgIGlmIHRoZSBmYXN0IHBhdGggZXZlciBtaXNiZWhhdmVzLiBJdCBpcyBhbiBTREstZGVwbG95bWVudCBlbnYgdmFyLFxuICAgICAgICAvLyAgICBzbyBjaGFuZ2luZyBpdCBnZW5lcmFsbHkgcmVxdWlyZXMgcmVkZXBsb3lpbmcgdGhlIHdvcmtmbG93XG4gICAgICAgIC8vICAgIGRlcGxveW1lbnQuIChUaGUgYmFja2VuZCBjYW4gaW5kZXBlbmRlbnRseSBkcm9wIG5ldyByZXN1bWVzIHRvIHRoZVxuICAgICAgICAvLyAgICBzZXF1ZW50aWFsIHBhdGggZmxlZXQtd2lkZSBieSBjZWFzaW5nIHRvIGF0dGVzdCBkZWR1cCBzdXBwb3J0IG9uXG4gICAgICAgIC8vICAgIHRoZSBieS10b2tlbiBsb29rdXAg4oCUIHNlZSB0aGUgYmFja2VuZC1kZWR1cCBjb25kaXRpb24gYmVsb3cuKVxuICAgICAgICAvLyAgLSBiYWNrZW5kIGRlZHVwOiB0aGUgbGl2ZSBiYWNrZW5kIG11c3QgZW5mb3JjZSB0aGVcbiAgICAgICAgLy8gICAgYChydW5JZCwgcmVzdW1lSWQpYCBjb25zdHJhaW50LCBvciB0aGUgdHdvIHdyaXRlcnMgd291bGQgY29tbWl0IHR3b1xuICAgICAgICAvLyAgICBgaG9va19yZWNlaXZlZGAgZXZlbnRzLiBGYWlsIGNsb3NlZC4gQXR0ZXN0ZWQgYnkgRUlUSEVSIGEgZnJlc2gsXG4gICAgICAgIC8vICAgIHJlc3BvbnNlLW9ubHkgYGhvb2sucmVzdW1lQ2FwYWJpbGl0aWVzLmhvb2tSZXN1bWVEZWR1cFZlcnNpb25gIGZyb21cbiAgICAgICAgLy8gICAgdGhlIGJ5LXRva2VuIGxvb2t1cCAod29ybGQtdmVyY2VsIOKAlCByZWNvbXB1dGVkIGV2ZXJ5IHJlYWQsIHNvIGFcbiAgICAgICAgLy8gICAgc2VydmVyIHJvbGxiYWNrIG9yIGtpbGwgc3dpdGNoIGRyb3BzIHRvIHNlcXVlbnRpYWwgaW1tZWRpYXRlbHkpIE9SXG4gICAgICAgIC8vICAgIHRoZSBzdGF0aWMgYHdvcmxkLmNhcGFiaWxpdGllcy5ob29rUmVzdW1lRGVkdXBgICh3b3JsZC1sb2NhbCwgd2hvc2VcbiAgICAgICAgLy8gICAgYWRhcHRlciBhbmQgYmFja2VuZCBzaGlwIHRvZ2V0aGVyKS4gVGhlIHJlc3BvbnNlLW9ubHkgY2FwYWJpbGl0eSBpc1xuICAgICAgICAvLyAgICB0cnVzdGVkIE9OTFkgd2hlbiB0aGUgaG9vayB3YXMgbG9va2VkIHVwIGJ5IHRva2VuIGR1cmluZyB0aGlzXG4gICAgICAgIC8vICAgIHJlc3VtZSAoYGhvb2tSZXN1bWVDYXBhYmlsaXRpZXNBcmVGcmVzaGApOyBhIEhvb2sgb2JqZWN0IGhhbmRlZCBpblxuICAgICAgICAvLyAgICBieSBhIHB1YmxpYyBjYWxsZXIgbWF5IGNhcnJ5IGEgY2FwYWJpbGl0eSBjYWNoZWQgYmVmb3JlIGEgcm9sbGJhY2ssXG4gICAgICAgIC8vICAgIHNvIGl0IGlzIGlnbm9yZWQgYW5kIHRoZSBwYXRoIGZhbGxzIGJhY2sgdG8gc2VxdWVudGlhbC5cbiAgICAgICAgLy8gIC0gY29uc3VtZXIgc3VwcG9ydDogdGhlIHRhcmdldCBydW4ncyBkZXBsb3ltZW50IG11c3QgcmUtZW5zdXJlIHRoZVxuICAgICAgICAvLyAgICBldmVudCBmcm9tIGBob29rSW5wdXRgIG9uIHJlcGxheS4gQXR0ZXN0ZWQgYnkgdGhlIHJ1bidzIGV4cGxpY2l0XG4gICAgICAgIC8vICAgIGBob29rUmVzdW1lSW5wdXRWZXJzaW9uYCBleGVjdXRpb24tY29udGV4dCBtYXJrZXIgKG1pcnJvcmVkIG9udG9cbiAgICAgICAgLy8gICAgcmVzdW1lQ29udGV4dCksIE5PVCBhIHZlcnNpb24tY29tcGFyZSBhZ2FpbnN0IGEgcHJlZGljdGVkIHJlbGVhc2VcbiAgICAgICAgLy8gICAgY3V0b2ZmLiBBYnNlbnQg4oaSIGEgbG9zdCBwcm9kdWNlciB3cml0ZSB3b3VsZCBiZSBhIGxvc3QgcmVzdW1lLlxuICAgICAgICAvLyAgLSBub3QgbGVnYWN5OiB2MUNvbXBhdCBydW5zIG9taXQgYHRva2VuYCBmcm9tIHRoZSBwcm9kdWNlcidzIGV2ZW50XG4gICAgICAgIC8vICAgIGJvZHkgYnV0IHRoZSBjb25zdW1lcidzIHJlLWVuc3VyZSBhbHdheXMgaW5jbHVkZXMgaXQsIHNvIHRoZSB0d29cbiAgICAgICAgLy8gICAgd3JpdGVycyB3b3VsZCBkaXNhZ3JlZSBvbiB0aGUgZXZlbnQgYm9keS4gTGVnYWN5IHN0YXlzIHNlcXVlbnRpYWwuXG4gICAgICAgIC8vICAtIENCT1IgdHJhbnNwb3J0OiB0aGUgcnVuIG11c3QgdXNlIENCT1IgcXVldWUgdHJhbnNwb3J0IHNvIHRoZSBiaW5hcnlcbiAgICAgICAgLy8gICAgcGF5bG9hZCBzdXJ2aXZlcyB0aGUgcXVldWUgbWVzc2FnZS5cbiAgICAgICAgLy8gIC0gcmF3IGJ5dGVzOiB0aGUgZGVoeWRyYXRlZCBwYXlsb2FkIG11c3QgYmUgYSBgVWludDhBcnJheWAgKHRoZVxuICAgICAgICAvLyAgICBjb250ZW50IGRpZ2VzdCB0aGF0IGtleXMgdGhlIGRlZHVwIGNvbnN0cmFpbnQgaXMgb3ZlciB0aGVzZSBieXRlcykuXG4gICAgICAgIC8vICAtIHNpemU6IGEgcGF5bG9hZCBhYm92ZSB0aGUgcXVldWUncyBtZXNzYWdlIGNlaWxpbmcgd291bGQgZmFpbCB0aGVcbiAgICAgICAgLy8gICAgcHVibGlzaCDigJQgd2hpY2gsIG9uIHRoZSBwYXJhbGxlbCBwYXRoLCB3b3VsZCBwZXJzaXN0IHRoZSBldmVudCBidXRcbiAgICAgICAgLy8gICAgbmV2ZXIgcmUtdHJpZ2dlciB0aGUgcnVuIOKAlCBzbyBvdmVyc2l6ZWQgcGF5bG9hZHMgc3RheSBzZXF1ZW50aWFsXG4gICAgICAgIC8vICAgICh0aGVpciBxdWV1ZSBtZXNzYWdlIGNhcnJpZXMgb25seSB0aGUgcnVuIElEKS5cbiAgICAgICAgY29uc3QgcGFyYWxsZWxSZXN1bWVEaXNhYmxlZCA9XG4gICAgICAgICAgcHJvY2Vzcy5lbnYuV09SS0ZMT1dfRElTQUJMRV9MQVpZX0hPT0tfUkVTVU1FID09PSAnMSc7XG4gICAgICAgIC8vIEJhY2tlbmQgZGVkdXAgaXMgc3VwcG9ydGVkIHdoZW4gRUlUSEVSIHRoZSBsaXZlIHNlcnZlciBhdHRlc3RzIGl0XG4gICAgICAgIC8vIGZyZXNoIG9uIHRoaXMgYnktdG9rZW4gaG9vayAod29ybGQtdmVyY2VsOiByZXNwb25zZS1vbmx5LCByZWNvbXB1dGVkXG4gICAgICAgIC8vIGV2ZXJ5IHJlYWQsIHNvIHJvbGxiYWNrL2tpbGwtc3dpdGNoIHRha2UgZWZmZWN0IGltbWVkaWF0ZWx5KSBPUiB0aGVcbiAgICAgICAgLy8gc3RhdGljIHdvcmxkIGNhcGFiaWxpdHkgaXMgc2V0ICh3b3JsZC1sb2NhbDogYWRhcHRlciArIGJhY2tlbmQgc2hpcFxuICAgICAgICAvLyB0b2dldGhlcikuIEJvdGggYXJlIHJlLWV2YWx1YXRlZCBwZXIgcmVzdW1lLCBzbyBldmVyeSByb2xsb3V0IGFuZFxuICAgICAgICAvLyByb2xsYmFjayBkaXJlY3Rpb24gZGVncmFkZXMgc2FmZWx5IHRvIHRoZSBzZXF1ZW50aWFsIHBhdGguXG4gICAgICAgIGNvbnN0IGJhY2tlbmREZWR1cFN1cHBvcnRlZCA9XG4gICAgICAgICAgKGhvb2tSZXN1bWVDYXBhYmlsaXRpZXNBcmVGcmVzaFxuICAgICAgICAgICAgPyAoaG9vay5yZXN1bWVDYXBhYmlsaXRpZXM/Lmhvb2tSZXN1bWVEZWR1cFZlcnNpb24gPz8gMClcbiAgICAgICAgICAgIDogMCkgPj0gSE9PS19SRVNVTUVfREVEVVBfVkVSU0lPTiB8fFxuICAgICAgICAgIHdvcmxkLmNhcGFiaWxpdGllcz8uaG9va1Jlc3VtZURlZHVwID09PSB0cnVlO1xuICAgICAgICBjb25zdCBmYWxsYmFja1JlYXNvbjogc3RyaW5nIHwgbnVsbCA9IHBhcmFsbGVsUmVzdW1lRGlzYWJsZWRcbiAgICAgICAgICA/ICdkaXNhYmxlZCdcbiAgICAgICAgICA6ICFiYWNrZW5kRGVkdXBTdXBwb3J0ZWRcbiAgICAgICAgICAgID8gJ2JhY2tlbmRfdW5zdXBwb3J0ZWQnXG4gICAgICAgICAgICA6IChyZXN1bWVDb250ZXh0Lmhvb2tSZXN1bWVJbnB1dFZlcnNpb24gPz8gMCkgPFxuICAgICAgICAgICAgICAgIEhPT0tfUkVTVU1FX0lOUFVUX1ZFUlNJT05cbiAgICAgICAgICAgICAgPyAnY29uc3VtZXJfdW5zdXBwb3J0ZWQnXG4gICAgICAgICAgICAgIDogdjFDb21wYXRcbiAgICAgICAgICAgICAgICA/ICdsZWdhY3knXG4gICAgICAgICAgICAgICAgOiAocmVzdW1lQ29udGV4dC5ydW5TcGVjVmVyc2lvbiA/PyAwKSA8XG4gICAgICAgICAgICAgICAgICAgIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DQk9SX1FVRVVFX1RSQU5TUE9SVFxuICAgICAgICAgICAgICAgICAgPyAnbm9uX2Nib3JfdHJhbnNwb3J0J1xuICAgICAgICAgICAgICAgICAgOiAhKGRlaHlkcmF0ZWRQYXlsb2FkIGluc3RhbmNlb2YgVWludDhBcnJheSlcbiAgICAgICAgICAgICAgICAgICAgPyAnbm9uX2J5dGVzJ1xuICAgICAgICAgICAgICAgICAgICA6IGRlaHlkcmF0ZWRQYXlsb2FkLmJ5dGVMZW5ndGggPlxuICAgICAgICAgICAgICAgICAgICAgICAgTUFYX0lOTElORV9SRVNVTUVfUEFZTE9BRF9CWVRFU1xuICAgICAgICAgICAgICAgICAgICAgID8gJ292ZXJzaXplZCdcbiAgICAgICAgICAgICAgICAgICAgICA6IG51bGw7XG4gICAgICAgIGNvbnN0IHVzZVBhcmFsbGVsUmVzdW1lID0gZmFsbGJhY2tSZWFzb24gPT09IG51bGw7XG5cbiAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgJ3dvcmtmbG93Lmhvb2sucmVzdW1lX3N0cmF0ZWd5JzogdXNlUGFyYWxsZWxSZXN1bWVcbiAgICAgICAgICAgID8gJ3BhcmFsbGVsJ1xuICAgICAgICAgICAgOiAnc2VxdWVudGlhbCcsXG4gICAgICAgICAgLi4uKGZhbGxiYWNrUmVhc29uXG4gICAgICAgICAgICA/IHsgJ3dvcmtmbG93Lmhvb2sucmVzdW1lX2ZhbGxiYWNrX3JlYXNvbic6IGZhbGxiYWNrUmVhc29uIH1cbiAgICAgICAgICAgIDoge30pLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBSZS1rZXkgYW55IFwiaG9vayBjYW4gbm8gbG9uZ2VyIGJlIHJlY2VpdmVkXCIgcmVqZWN0aW9uIHRvXG4gICAgICAgIC8vIEhvb2tOb3RGb3VuZEVycm9yKGhvb2sudG9rZW4pIHNvIGAudG9rZW5gIG1hdGNoZXMgdGhlIHByZS1mYXN0LXBhdGhcbiAgICAgICAgLy8gY29udHJhY3QsIHdoZXJlIHJlc3VtZUhvb2sgdGhyZXcgYEhvb2tOb3RGb3VuZEVycm9yKGhvb2sudG9rZW4pYFxuICAgICAgICAvLyBhZnRlciBpdHMgb3duIHRlcm1pbmFsIGNoZWNrLiBUaGUgc3BlY2lmaWMgZXJyb3IgZGVwZW5kcyBvbiB0aGVcbiAgICAgICAgLy8gV29ybGQ6XG4gICAgICAgIC8vICAgLSBhIGdlbnVpbmVseSBtaXNzaW5nIGhvb2sgbWFwcyB0byBIb29rTm90Rm91bmRFcnJvciAoa2V5ZWQgb24gdGhlXG4gICAgICAgIC8vICAgICBldmVudCBjb3JyZWxhdGlvbklkIC8gaG9vayBJRCk7XG4gICAgICAgIC8vICAgLSBhIHRlcm1pbmFsIHJ1biBvbiBWZXJjZWwgcmVqZWN0cyBob29rX3JlY2VpdmVkIHdpdGggNDA0LCB3aGljaFxuICAgICAgICAvLyAgICAgd29ybGQtdmVyY2VsIG1hcHMgdG8gSG9va05vdEZvdW5kRXJyb3I7XG4gICAgICAgIC8vICAgLSBhIHRlcm1pbmFsIHJ1biBvbiB3b3JsZC1sb2NhbCAvIHdvcmxkLXBvc3RncmVzIHJlamVjdHMgd2l0aFxuICAgICAgICAvLyAgICAgUnVuRXhwaXJlZEVycm9yLlxuICAgICAgICAvL1xuICAgICAgICAvLyBPbiB0aGUgU0VRVUVOVElBTCBwYXRoIGFuIEVudGl0eUNvbmZsaWN0RXJyb3IgKEhUVFAgNDA5KSBpcyBhbHNvXG4gICAgICAgIC8vIHRyZWF0ZWQgYXMgXCJob29rIGdvbmVcIiBmb3IgaGlzdG9yaWNhbCAvIGNvbmZsaWN0LXNoYXBlZC1yZWplY3Rpb25cbiAgICAgICAgLy8gY29tcGF0aWJpbGl0eTogdGhlcmUgaXMgbm8gcXVldWUgbWVzc2FnZSBpbiBmbGlnaHQsIHNvIGEgY29uZmxpY3QgaGFzXG4gICAgICAgIC8vIG5vIHJlLWVuc3VyaW5nIGNvbnN1bWVyIHRvIGNvbnZlcmdlIG9uLiBUaGUgUEFSQUxMRUwgcGF0aCBoYW5kbGVzIDQwOVxuICAgICAgICAvLyBkaWZmZXJlbnRseSAoc2VlIGJlbG93KSDigJQgaXQgcHVibGlzaGVkIHRoZSBxdWV1ZSBtZXNzYWdlIGJlZm9yZSB0aGVcbiAgICAgICAgLy8gY29uZmxpY3QsIHNvIHRoZSBjb25zdW1lciB3aWxsIGNvbnZlcmdlIHRoZSBldmVudC5cbiAgICAgICAgY29uc3QgaXNIb29rR29uZUVycm9yID0gKGVycjogdW5rbm93bik6IGJvb2xlYW4gPT5cbiAgICAgICAgICBIb29rTm90Rm91bmRFcnJvci5pcyhlcnIpIHx8XG4gICAgICAgICAgRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpIHx8XG4gICAgICAgICAgUnVuRXhwaXJlZEVycm9yLmlzKGVycik7XG5cbiAgICAgICAgaWYgKCF1c2VQYXJhbGxlbFJlc3VtZSkge1xuICAgICAgICAgIC8vIFNlcXVlbnRpYWwgcGF0aDogY3JlYXRlIGEgaG9va19yZWNlaXZlZCBldmVudCwgdGhlbiByZS10cmlnZ2VyLlxuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgICBob29rLnJ1bklkLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnaG9va19yZWNlaXZlZCcsXG4gICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IGhvb2suaG9va0lkLFxuICAgICAgICAgICAgICAgIGV2ZW50RGF0YSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgeyB2MUNvbXBhdCB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKGlzSG9va0dvbmVFcnJvcihlcnIpKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBIb29rTm90Rm91bmRFcnJvcihob29rLnRva2VuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBhd2FpdCB3b3JsZC5xdWV1ZShcbiAgICAgICAgICAgIHF1ZXVlTmFtZSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgcnVuSWQ6IGhvb2sucnVuSWQsXG4gICAgICAgICAgICAgIHRyYWNlQ2FycmllcjogcmVzdW1lQ29udGV4dC50cmFjZUNhcnJpZXIgPz8gdW5kZWZpbmVkLFxuICAgICAgICAgICAgfSBzYXRpc2ZpZXMgV29ya2Zsb3dJbnZva2VQYXlsb2FkLFxuICAgICAgICAgICAgcXVldWVPcHRpb25zXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIHJldHVybiBob29rO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUGFyYWxsZWwgZmFzdCBwYXRoLiBBIHN0YWJsZSBpZGVtcG90ZW5jeSBrZXkgdGllcyB0aGUgZGlyZWN0IHdyaXRlIHRvXG4gICAgICAgIC8vIHRoZSBxdWV1ZSBjb25zdW1lcidzIHJlLWVuc3VyZTsgdGhlIHBheWxvYWQgZGlnZXN0IGxldHMgdGhlIHNlcnZlclxuICAgICAgICAvLyBkZXRlY3Qga2V5IHJldXNlIGFjcm9zcyBieXRlLWlkZW50aWNhbCBwYXlsb2Fkcy5cbiAgICAgICAgY29uc3QgcmVzdW1lSWQgPSBnZW5lcmF0ZVJlc3VtZUlkKCk7XG4gICAgICAgIGNvbnN0IHBheWxvYWREaWdlc3QgPSBhd2FpdCBjb21wdXRlUmVzdW1lUGF5bG9hZERpZ2VzdChcbiAgICAgICAgICBkZWh5ZHJhdGVkUGF5bG9hZCBhcyBVaW50OEFycmF5XG4gICAgICAgICk7XG4gICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoeyAnd29ya2Zsb3cuaG9vay5yZXN1bWVfaWQnOiByZXN1bWVJZCB9KTtcblxuICAgICAgICBjb25zdCBbZXZlbnRSZXN1bHQsIHF1ZXVlUmVzdWx0XSA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChbXG4gICAgICAgICAgd29ybGQuZXZlbnRzLmNyZWF0ZShcbiAgICAgICAgICAgIGhvb2sucnVuSWQsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfcmVjZWl2ZWQnLFxuICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IGhvb2suaG9va0lkLFxuICAgICAgICAgICAgICBldmVudERhdGEsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgeyB2MUNvbXBhdCwgcmVzdW1lSWQsIHJlc3VtZVBheWxvYWREaWdlc3Q6IHBheWxvYWREaWdlc3QgfVxuICAgICAgICAgICksXG4gICAgICAgICAgd29ybGQucXVldWUoXG4gICAgICAgICAgICBxdWV1ZU5hbWUsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHJ1bklkOiBob29rLnJ1bklkLFxuICAgICAgICAgICAgICB0cmFjZUNhcnJpZXI6IHJlc3VtZUNvbnRleHQudHJhY2VDYXJyaWVyID8/IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgaG9va0lucHV0OiB7XG4gICAgICAgICAgICAgICAgcmVzdW1lSWQsXG4gICAgICAgICAgICAgICAgaG9va0lkOiBob29rLmhvb2tJZCxcbiAgICAgICAgICAgICAgICB0b2tlbjogaG9vay50b2tlbixcbiAgICAgICAgICAgICAgICBwYXlsb2FkOiBkZWh5ZHJhdGVkUGF5bG9hZCxcbiAgICAgICAgICAgICAgICBwYXlsb2FkRGlnZXN0LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSBzYXRpc2ZpZXMgV29ya2Zsb3dJbnZva2VQYXlsb2FkLFxuICAgICAgICAgICAgcXVldWVPcHRpb25zXG4gICAgICAgICAgKSxcbiAgICAgICAgXSk7XG5cbiAgICAgICAgLy8gUXVldWUgZmFpbHVyZSBpcyBhbHdheXMgZmF0YWwg4oCUIHRoZSBydW4gd2FzIG5vdCByZS10cmlnZ2VyZWQsIHNvIG5vXG4gICAgICAgIC8vIGNvbnN1bWVyIHdpbGwgcmUtZW5zdXJlIHRoZSBldmVudC5cbiAgICAgICAgaWYgKHF1ZXVlUmVzdWx0LnN0YXR1cyA9PT0gJ3JlamVjdGVkJykge1xuICAgICAgICAgIHRocm93IHF1ZXVlUmVzdWx0LnJlYXNvbjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldCB3aGVuIHRoZSBkaXJlY3Qgd3JpdGUgZGlkIG5vdCBsYW5kIGJ1dCB0aGUgcXVldWUgZGlzcGF0Y2ggZGlkLCBzb1xuICAgICAgICAvLyB0aGUgY29uc3VtZXIgbWF0ZXJpYWxpemVzIHRoZSBldmVudCBiZWZvcmUgcmVwbGF5LiBTdXJmYWNlZCB0byB0aGVcbiAgICAgICAgLy8gY2FsbGVyIGFzIGBSZXN1bWVkSG9vay5yZXNpbGllbnRSZXN1bWVgIGFuZCBvbiB0aGUgc3Bhbi5cbiAgICAgICAgbGV0IHJlc2lsaWVudFJlc3VtZSA9IGZhbHNlO1xuICAgICAgICBpZiAoZXZlbnRSZXN1bHQuc3RhdHVzID09PSAncmVqZWN0ZWQnKSB7XG4gICAgICAgICAgY29uc3QgZXJyID0gZXZlbnRSZXN1bHQucmVhc29uO1xuICAgICAgICAgIGlmIChIb29rTm90Rm91bmRFcnJvci5pcyhlcnIpIHx8IFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAvLyBUaGUgaG9vaydzIHJ1biBoYXMgZ2VudWluZWx5IGVuZGVkOiBzdXJmYWNlIHRoZSBzYW1lIGNvbnRyYWN0IGFzXG4gICAgICAgICAgICAvLyB0aGUgc2VxdWVudGlhbCBwYXRoLiBUaGUgcXVldWUgbWVzc2FnZSBhbHJlYWR5IHdlbnQgb3V0LCBidXQgdGhlXG4gICAgICAgICAgICAvLyBjb25zdW1lcidzIHJlLWVuc3VyZSB3aWxsIGFsc28gcmVqZWN0IGFnYWluc3QgdGhlIHRlcm1pbmFsIHJ1blxuICAgICAgICAgICAgLy8gYW5kIG5vLW9wLCBzbyB0aGUgd29ya2Zsb3cgZG9lcyBub3QgcmVzdW1lLlxuICAgICAgICAgICAgdGhyb3cgbmV3IEhvb2tOb3RGb3VuZEVycm9yKGhvb2sudG9rZW4pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpIHx8IGlzUmV0cnlhYmxlV29ybGRFcnJvcihlcnIpKSB7XG4gICAgICAgICAgICAvLyBSZXNpbGllbnQuIFR3byBzaGFwZXMgcmVhY2ggaGVyZSwgYm90aCBub24tdGVybWluYWw6XG4gICAgICAgICAgICAvLyAgIC0gRW50aXR5Q29uZmxpY3QgKDQwOSk6IHRoaXMgd3JpdGUgcmFjZWQgaXRzIG93biByZS1lbnN1cmluZ1xuICAgICAgICAgICAgLy8gICAgIGNvbnN1bWVyIChvciBhIHJlZHJpdmUpIG9uIHRoZSBzaGFyZWQgYHJlc3VtZUlkYCDigJQgdGhlIHJ1biBpc1xuICAgICAgICAgICAgLy8gICAgIE5PVCBnb25lLCBhbmQgdGhlIGNvbnN1bWVyIGNvbnZlcmdlcyBvbiB0aGUgb25lIGNvbW1pdHRlZFxuICAgICAgICAgICAgLy8gICAgIGV2ZW50LiBVbmxpa2UgdGhlIHNlcXVlbnRpYWwgcGF0aCwgYSA0MDkgaGVyZSBpcyBleHBlY3RlZFxuICAgICAgICAgICAgLy8gICAgIGNvbmN1cnJlbmN5LCBub3QgYSB2YW5pc2hlZCBob29rLlxuICAgICAgICAgICAgLy8gICAtIDQyOSAvIDV4eCAvIHRyYW5zcG9ydDogYSB0cmFuc2llbnQgYmFja2VuZCBmYWlsdXJlLlxuICAgICAgICAgICAgLy8gSW4gYm90aCBjYXNlcyB0aGUgcnVuIFdBUyByZS10cmlnZ2VyZWQgdmlhIHRoZSBxdWV1ZSBhbmQgdGhlXG4gICAgICAgICAgICAvLyBjb25zdW1lciBpZGVtcG90ZW50bHkgZW5zdXJlcyB0aGUgaG9va19yZWNlaXZlZCBiZWZvcmUgcmVwbGF5LCBzb1xuICAgICAgICAgICAgLy8gc3dhbGxvdyByYXRoZXIgdGhhbiBmYWlsaW5nIHRoZSBjYWxsZXIuXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gUHJvZHVjZXIgdGVsZW1ldHJ5OiByZWNvcmQgdGhhdCB0aGUgZGlyZWN0IHdyaXRlIGRpZCBub3QgbGFuZCBidXRcbiAgICAgICAgICAgIC8vIHRoZSByZXN1bWUgaXMgc3RpbGwgZ3VhcmFudGVlZCB2aWEgcXVldWUtZGVsaXZlcmVkIGBob29rSW5wdXRgLlxuICAgICAgICAgICAgLy8gVGhpcyBpcyB0aGUgb3BlcmF0aW9uYWwgc2lnbmFsIHRoYXQgdGhlIHJlY292ZXJ5IHBhdGggZmlyZWQsXG4gICAgICAgICAgICAvLyBzdXJmYWNlZCBib3RoIG9uIHRoZSBzcGFuIGFuZCBhcyB0aGUgcHVibGljIGByZXNpbGllbnRSZXN1bWVgXG4gICAgICAgICAgICAvLyBmbGFnIG9uIHRoZSByZXR1cm5lZCBob29rICh0aGUgcmVzdW1lIG91dGNvbWUgaXMgb3RoZXJ3aXNlXG4gICAgICAgICAgICAvLyBpZGVudGljYWwgdG8gdGhlIGhhcHB5IHBhdGggZnJvbSB0aGUgY2FsbGVyJ3MgcGVyc3BlY3RpdmUpLlxuICAgICAgICAgICAgcmVzaWxpZW50UmVzdW1lID0gdHJ1ZTtcbiAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuSG9va1Jlc2lsaWVudFJlc3VtZSh0cnVlKSxcbiAgICAgICAgICAgICAgJ3dvcmtmbG93Lmhvb2sucmVzdW1lX2V2ZW50X3dyaXRlX3JlY292ZXJlZCc6IHRydWUsXG4gICAgICAgICAgICAgICd3b3JrZmxvdy5ob29rLnJlc3VtZV9ldmVudF93cml0ZV9lcnJvcic6XG4gICAgICAgICAgICAgICAgZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubmFtZSA6ICd1bmtub3duJyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci53YXJuKFxuICAgICAgICAgICAgICAnSG9vayByZXN1bWUgZXZlbnQgd3JpdGUgZmFpbGVkLCBidXQgdGhlIHJ1biB3YXMgcmUtdHJpZ2dlcmVkIHZpYSAnICtcbiAgICAgICAgICAgICAgICAndGhlIHF1ZXVlLiBUaGUgaG9va19yZWNlaXZlZCBldmVudCB3aWxsIGJlIGVuc3VyZWQgYnkgdGhlICcgK1xuICAgICAgICAgICAgICAgICdxdWV1ZSBjb25zdW1lci4nLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogaG9vay5ydW5JZCxcbiAgICAgICAgICAgICAgICBob29rSWQ6IGhvb2suaG9va0lkLFxuICAgICAgICAgICAgICAgIHJlc3VtZUlkLFxuICAgICAgICAgICAgICAgIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIHJlc2lsaWVudFJlc3VtZSA/IHsgLi4uaG9vaywgcmVzaWxpZW50UmVzdW1lOiB0cnVlIH0gOiBob29rXG4gICAgICAgICkgc2F0aXNmaWVzIFJlc3VtZWRIb29rO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Ib29rVG9rZW4oXG4gICAgICAgICAgICB0eXBlb2YgdG9rZW5Pckhvb2sgPT09ICdzdHJpbmcnID8gdG9rZW5Pckhvb2sgOiB0b2tlbk9ySG9vay50b2tlblxuICAgICAgICAgICksXG4gICAgICAgICAgLi4uQXR0cmlidXRlLkhvb2tGb3VuZChmYWxzZSksXG4gICAgICAgIH0pO1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuXG4vKipcbiAqIFJlc3VtZXMgYSB3ZWJob29rIGJ5IHNlbmRpbmcgYSB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1JlcXVlc3QgfCBSZXF1ZXN0fVxuICogb2JqZWN0IHRvIGEgaG9vayBpZGVudGlmaWVkIGJ5IGl0cyB0b2tlbi5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBleHRlcm5hbGx5IChlLmcuLCBmcm9tIGFuIEFQSSByb3V0ZSBvciBzZXJ2ZXIgYWN0aW9uKVxuICogdG8gc2VuZCBhIHJlcXVlc3QgdG8gYSB3ZWJob29rIGFuZCByZXN1bWUgdGhlIGFzc29jaWF0ZWQgd29ya2Zsb3cgcnVuLlxuICpcbiAqIEBwYXJhbSB0b2tlbiAtIFRoZSB1bmlxdWUgdG9rZW4gaWRlbnRpZnlpbmcgdGhlIGhvb2tcbiAqIEBwYXJhbSByZXF1ZXN0IC0gVGhlIHJlcXVlc3QgdG8gc2VuZCB0byB0aGUgaG9va1xuICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHJlc3BvbnNlXG4gKiBAdGhyb3dzIEVycm9yIGlmIHRoZSBob29rIGlzIG5vdCBmb3VuZCBvciBpZiB0aGVyZSdzIGFuIGVycm9yIGR1cmluZyB0aGUgcHJvY2Vzc1xuICpcbiAqIEBleGFtcGxlXG4gKlxuICogYGBgdHNcbiAqIC8vIEluIGFuIEFQSSByb3V0ZVxuICogaW1wb3J0IHsgcmVzdW1lV2ViaG9vayB9IGZyb20gJ0B3b3JrZmxvdy9jb3JlL3J1bnRpbWUnO1xuICpcbiAqIGV4cG9ydCBhc3luYyBmdW5jdGlvbiBQT1NUKHJlcXVlc3Q6IFJlcXVlc3QpIHtcbiAqICAgY29uc3QgdXJsID0gbmV3IFVSTChyZXF1ZXN0LnVybCk7XG4gKiAgIGNvbnN0IHRva2VuID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3Rva2VuJyk7XG4gKlxuICogICBpZiAoIXRva2VuKSB7XG4gKiAgICAgcmV0dXJuIG5ldyBSZXNwb25zZSgnTWlzc2luZyB0b2tlbicsIHsgc3RhdHVzOiA0MDAgfSk7XG4gKiAgIH1cbiAqXG4gKiAgIHRyeSB7XG4gKiAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCByZXN1bWVXZWJob29rKHRva2VuLCByZXF1ZXN0KTtcbiAqICAgICByZXR1cm4gcmVzcG9uc2U7XG4gKiAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gKiAgICAgcmV0dXJuIG5ldyBSZXNwb25zZSgnV2ViaG9vayBub3QgZm91bmQnLCB7IHN0YXR1czogNDA0IH0pO1xuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlc3VtZVdlYmhvb2soXG4gIHRva2VuOiBzdHJpbmcsXG4gIHJlcXVlc3Q6IFJlcXVlc3Rcbik6IFByb21pc2U8UmVzcG9uc2U+IHtcbiAgY29uc3QgeyBob29rLCBlbmNyeXB0aW9uS2V5IH0gPSBhd2FpdCBnZXRIb29rQnlUb2tlbldpdGhLZXkodG9rZW4pO1xuXG4gIC8vIE9ubHkgd2ViaG9va3MgY2FuIGJlIHJlc3VtZWQgdmlhIHRoZSBwdWJsaWMgZW5kcG9pbnQuXG4gIC8vIElmIHRoZSBob29rIHdhcyBjcmVhdGVkIHZpYSBjcmVhdGVIb29rKCkgKGlzV2ViaG9vayAhPT0gdHJ1ZSksXG4gIC8vIHRocm93IHRoZSBzYW1lIFwibm90IGZvdW5kXCIgZXJyb3IgdGhlIHdvcmxkIHdvdWxkIHRocm93IGZvciBhIG1pc3NpbmdcbiAgLy8gdG9rZW4uIFRoaXMgcHJldmVudHMgbGVha2luZyB0aGF0IHRoZSB0b2tlbiBpcyB2YWxpZC5cbiAgaWYgKGhvb2suaXNXZWJob29rID09PSBmYWxzZSkge1xuICAgIHRocm93IG5ldyBIb29rTm90Rm91bmRFcnJvcih0b2tlbik7XG4gIH1cblxuICBsZXQgcmVzcG9uc2U6IFJlc3BvbnNlIHwgdW5kZWZpbmVkO1xuICBsZXQgcmVzcG9uc2VSZWFkYWJsZTogUmVhZGFibGVTdHJlYW08UmVzcG9uc2U+IHwgdW5kZWZpbmVkO1xuICBpZiAoXG4gICAgaG9vay5tZXRhZGF0YSAmJlxuICAgIHR5cGVvZiBob29rLm1ldGFkYXRhID09PSAnb2JqZWN0JyAmJlxuICAgICdyZXNwb25kV2l0aCcgaW4gaG9vay5tZXRhZGF0YVxuICApIHtcbiAgICBpZiAoaG9vay5tZXRhZGF0YS5yZXNwb25kV2l0aCA9PT0gJ21hbnVhbCcpIHtcbiAgICAgIGNvbnN0IHsgcmVhZGFibGUsIHdyaXRhYmxlIH0gPSBuZXcgVHJhbnNmb3JtU3RyZWFtPFJlc3BvbnNlLCBSZXNwb25zZT4oKTtcbiAgICAgIHJlc3BvbnNlUmVhZGFibGUgPSByZWFkYWJsZTtcblxuICAgICAgLy8gVGhlIHJlcXVlc3QgaW5zdGFuY2UgaW5jbHVkZXMgdGhlIHdyaXRhYmxlIHN0cmVhbSB3aGljaCB3aWxsIGJlIHVzZWRcbiAgICAgIC8vIHRvIHdyaXRlIHRoZSByZXNwb25zZSB0byB0aGUgY2xpZW50IGZyb20gd2l0aGluIHRoZSB3b3JrZmxvdyBydW5cbiAgICAgIChyZXF1ZXN0IGFzIGFueSlbV0VCSE9PS19SRVNQT05TRV9XUklUQUJMRV0gPSB3cml0YWJsZTtcbiAgICB9IGVsc2UgaWYgKGhvb2subWV0YWRhdGEucmVzcG9uZFdpdGggaW5zdGFuY2VvZiBSZXNwb25zZSkge1xuICAgICAgcmVzcG9uc2UgPSBob29rLm1ldGFkYXRhLnJlc3BvbmRXaXRoO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoXG4gICAgICAgIGBJbnZhbGlkIFxcYHJlc3BvbmRXaXRoXFxgIHZhbHVlOiAke2hvb2subWV0YWRhdGEucmVzcG9uZFdpdGh9YCxcbiAgICAgICAgeyBzbHVnOiBFUlJPUl9TTFVHUy5XRUJIT09LX0lOVkFMSURfUkVTUE9ORF9XSVRIX1ZBTFVFIH1cbiAgICAgICk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIE5vIGByZXNwb25kV2l0aGAgdmFsdWUgaW1wbGllcyB0aGUgZGVmYXVsdCBiZWhhdmlvciBvZiByZXR1cm5pbmcgYSAyMDJcbiAgICByZXNwb25zZSA9IG5ldyBSZXNwb25zZShudWxsLCB7IHN0YXR1czogMjAyIH0pO1xuICB9XG5cbiAgLy8gYGhvb2tgIHdhcyBqdXN0IGZldGNoZWQgdmlhIGBnZXRIb29rQnlUb2tlbldpdGhLZXlgIChhIGZyZXNoIGJ5LXRva2VuXG4gIC8vIGxvb2t1cCkgYWJvdmUsIHNvIGl0cyByZXNwb25zZS1vbmx5IGByZXN1bWVDYXBhYmlsaXRpZXNgIHJlZmxlY3RzIHRoZSBsaXZlXG4gIC8vIGJhY2tlbmQg4oCUIGNhbGwgdGhlIGludGVybmFsIGltcGxlbWVudGF0aW9uIHdpdGggdGhlIGZyZXNoIGF0dGVzdGF0aW9uIHNvXG4gIC8vIHRoZSBwYXJhbGxlbCBmYXN0IHBhdGggc3RheXMgYXZhaWxhYmxlIHdpdGhvdXQgYSBzZWNvbmQgR0VULiAoVGhlIHB1YmxpY1xuICAvLyBgcmVzdW1lSG9va2AgbmV2ZXIgc2V0cyB0aGlzLCBzbyBhIGNhbGxlciBjYW5ub3QgZm9yZ2UgaXQuKVxuICBhd2FpdCByZXN1bWVIb29rSW1wbChob29rLCByZXF1ZXN0LCBlbmNyeXB0aW9uS2V5LCB0cnVlKTtcblxuICBpZiAocmVzcG9uc2VSZWFkYWJsZSkge1xuICAgIC8vIFdhaXQgZm9yIHRoZSByZWFkYWJsZSBzdHJlYW0gdG8gZW1pdCBvbmUgY2h1bmssXG4gICAgLy8gd2hpY2ggaXMgdGhlIGBSZXNwb25zZWAgb2JqZWN0XG4gICAgY29uc3QgcmVhZGVyID0gcmVzcG9uc2VSZWFkYWJsZS5nZXRSZWFkZXIoKTtcbiAgICBjb25zdCBjaHVuayA9IGF3YWl0IHJlYWRlci5yZWFkKCk7XG4gICAgaWYgKGNodW5rLnZhbHVlKSB7XG4gICAgICByZXNwb25zZSA9IGNodW5rLnZhbHVlO1xuICAgIH1cbiAgICByZWFkZXIuY2FuY2VsKCk7XG4gIH1cblxuICBpZiAoIXJlc3BvbnNlKSB7XG4gICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKCdXb3JrZmxvdyBydW4gZGlkIG5vdCBzZW5kIGEgcmVzcG9uc2UnLCB7XG4gICAgICBzbHVnOiBFUlJPUl9TTFVHUy5XRUJIT09LX1JFU1BPTlNFX05PVF9TRU5ULFxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHJlc3BvbnNlO1xufVxuIl19
|