@workflow/core 5.0.0-beta.46 → 5.0.0-beta.47

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.
Files changed (49) hide show
  1. package/dist/capabilities.d.ts +6 -5
  2. package/dist/capabilities.d.ts.map +1 -1
  3. package/dist/capabilities.js +14 -12
  4. package/dist/events-consumer.d.ts +29 -6
  5. package/dist/events-consumer.d.ts.map +1 -1
  6. package/dist/events-consumer.js +66 -11
  7. package/dist/private.d.ts +11 -7
  8. package/dist/private.d.ts.map +1 -1
  9. package/dist/private.js +57 -29
  10. package/dist/replay-payload-cache.d.ts +13 -17
  11. package/dist/replay-payload-cache.d.ts.map +1 -1
  12. package/dist/replay-payload-cache.js +55 -57
  13. package/dist/runtime/constants.d.ts +3 -3
  14. package/dist/runtime/constants.d.ts.map +1 -1
  15. package/dist/runtime/constants.js +4 -4
  16. package/dist/runtime/helpers.d.ts +14 -33
  17. package/dist/runtime/helpers.d.ts.map +1 -1
  18. package/dist/runtime/helpers.js +18 -43
  19. package/dist/runtime/resume-hook.d.ts +19 -26
  20. package/dist/runtime/resume-hook.d.ts.map +1 -1
  21. package/dist/runtime/resume-hook.js +201 -255
  22. package/dist/runtime/resume-latency.d.ts +8 -11
  23. package/dist/runtime/resume-latency.d.ts.map +1 -1
  24. package/dist/runtime/resume-latency.js +1 -1
  25. package/dist/runtime/start.js +12 -10
  26. package/dist/runtime/vm-mode.d.ts +1 -1
  27. package/dist/runtime/vm-mode.d.ts.map +1 -1
  28. package/dist/runtime/vm-mode.js +1 -1
  29. package/dist/runtime.d.ts.map +1 -1
  30. package/dist/runtime.js +146 -60
  31. package/dist/serialization.d.ts +3 -3
  32. package/dist/serialization.d.ts.map +1 -1
  33. package/dist/serialization.js +22 -22
  34. package/dist/telemetry/semantic-conventions.d.ts +41 -7
  35. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  36. package/dist/telemetry/semantic-conventions.js +30 -6
  37. package/dist/telemetry.d.ts +12 -0
  38. package/dist/telemetry.d.ts.map +1 -1
  39. package/dist/telemetry.js +62 -2
  40. package/dist/version.d.ts +1 -1
  41. package/dist/version.js +2 -2
  42. package/dist/vm/script-cache.d.ts +9 -11
  43. package/dist/vm/script-cache.d.ts.map +1 -1
  44. package/dist/vm/script-cache.js +25 -40
  45. package/dist/workflow.d.ts +16 -0
  46. package/dist/workflow.d.ts.map +1 -1
  47. package/dist/workflow.js +67 -22
  48. package/docs/foundations/errors-and-retries.mdx +1 -1
  49. package/package.json +6 -6
@@ -1,5 +1,5 @@
1
- import { EntityConflictError, ERROR_SLUGS, HookNotFoundError, RunExpiredError, WorkflowRuntimeError, } from '@workflow/errors';
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';
1
+ import { ERROR_SLUGS, HookNotFoundError, RunExpiredError, WorkflowRuntimeError, } from '@workflow/errors';
2
+ import { HOOK_RESUME_DEDUP_VERSION, isLegacySpecVersion, isTerminalWorkflowRunStatus, SPEC_VERSION_CURRENT, SPEC_VERSION_LEGACY, SPEC_VERSION_SUPPORTS_COMPRESSION, } from '@workflow/world';
3
3
  import { monotonicFactory } from 'ulid';
4
4
  import { getRunCapabilities } from '../capabilities.js';
5
5
  import { importKey } from '../encryption.js';
@@ -15,26 +15,10 @@ import { getWorkflowQueueName } from './helpers.js';
15
15
  import { safeWaitUntil, waitedUntil } from './wait-until.js';
16
16
  /** Monotonic ULID factory for per-call resume idempotency keys. */
17
17
  const generateResumeId = monotonicFactory();
18
- /**
19
- * Upper bound on the serialized hook payload that the lazy path will inline
20
- * into the queue message's `hookInput`. Vercel Queues caps a single message at
21
- * ~256 KiB, and the message also carries the runId, hookId, token, resumeId,
22
- * digest, and trace carrier alongside CBOR framing overhead. Staying well under
23
- * that ceiling keeps the queue publish from rejecting an oversized message,
24
- * which on the lazy path would drop the resume entirely: the message is the
25
- * only copy of the payload. Above this size we fall back to the sequential
26
- * path, whose queue message carries only the run ID (the payload lives in the
27
- * event log).
28
- */
29
- const MAX_INLINE_RESUME_PAYLOAD_BYTES = 128 * 1024;
30
18
  /**
31
19
  * Hex SHA-256 of the serialized resume payload bytes. Computed once by the
32
- * producer and carried on the queue message's `hookInput`, so every delivery of
33
- * that message records an identical digest against the server's
34
- * `(runId, resumeId)` constraint and redeliveries converge on the one committed
35
- * `hook_received`. Hashing the already-serialized bytes (not the raw value)
36
- * keeps the digest stable across deliveries: the consumer forwards this string
37
- * without recomputing.
20
+ * producer and sent with its durable `hook_received` write so transport and
21
+ * slot retries converge through the server's `(runId, resumeId)` constraint.
38
22
  */
39
23
  async function computeResumePayloadDigest(bytes) {
40
24
  const digest = await crypto.subtle.digest('SHA-256', bytes);
@@ -45,6 +29,62 @@ async function computeResumePayloadDigest(bytes) {
45
29
  }
46
30
  return hex;
47
31
  }
32
+ const HOOK_WAKE_RETRY_DELAYS_MS = [25, 100];
33
+ /**
34
+ * A wake failure worth retrying is transport-shaped (network error, 5xx,
35
+ * throttle). A definitive rejection will not change on a 25ms retry, so
36
+ * spending the budget on it only delays the caller's error.
37
+ *
38
+ * `@vercel/queue` errors carry no `status` field — they are bare `Error`
39
+ * subclasses distinguished by `name` — so classification checks the World's
40
+ * deployment-unavailable hook first (a deployment the queue cannot discover
41
+ * will not come back within this function's ~125ms budget), then a numeric
42
+ * status when one exists (non-Vercel queue implementations), then the queue
43
+ * client's definitive-4xx error names.
44
+ */
45
+ function isRetryableWakeError(error, isDeploymentUnavailableError) {
46
+ if (isDeploymentUnavailableError?.(error))
47
+ return false;
48
+ const status = error ?? {};
49
+ const code = status.status ?? status.statusCode;
50
+ if (typeof code === 'number') {
51
+ return code >= 500 || code === 408 || code === 429;
52
+ }
53
+ const name = error?.name;
54
+ return (name !== 'BadRequestError' &&
55
+ name !== 'UnauthorizedError' &&
56
+ name !== 'ForbiddenError');
57
+ }
58
+ // A publish may succeed even when its response is lost, so a retry can
59
+ // enqueue a duplicate wake. That is harmless: the event is already durable,
60
+ // and deterministic replay makes a second delivery of the same run a no-op.
61
+ async function publishHookWakeWithRetry(publish, isDeploymentUnavailableError) {
62
+ let lastError;
63
+ for (let attempt = 0; attempt <= HOOK_WAKE_RETRY_DELAYS_MS.length; attempt++) {
64
+ try {
65
+ await publish();
66
+ return;
67
+ }
68
+ catch (error) {
69
+ lastError = error;
70
+ if (!isRetryableWakeError(error, isDeploymentUnavailableError))
71
+ break;
72
+ const delayMs = HOOK_WAKE_RETRY_DELAYS_MS[attempt];
73
+ if (delayMs !== undefined) {
74
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
75
+ }
76
+ }
77
+ }
78
+ // The wake only runs after the hook_received write committed, so a wake
79
+ // failure here is necessarily "durable but not yet dispatched": the event
80
+ // survives, and any later wake of the run delivers it. Do not let a queue
81
+ // implementation reuse HookNotFoundError and accidentally imply that no
82
+ // hook_received exists.
83
+ if (HookNotFoundError.is(lastError)) {
84
+ throw new WorkflowRuntimeError('The hook resume was committed, but its workflow wake could not be published', { cause: lastError });
85
+ }
86
+ throw lastError;
87
+ }
48
88
  /** Derive a resume context from a full run (fallback for pre-`resumeContext` hooks). */
49
89
  function resumeContextFromRun(run) {
50
90
  const coreVersion = run.executionContext?.workflowCoreVersion;
@@ -146,6 +186,22 @@ export async function getHookByToken(token) {
146
186
  * This function is called externally (e.g., from an API route or server action)
147
187
  * to send data to a hook and resume the associated workflow run.
148
188
  *
189
+ * Resolving means BOTH that the `hook_received` event is durably recorded in
190
+ * the run's event log and that the workflow wake was accepted by the queue, in
191
+ * that order. A {@link HookNotFoundError} means this invocation committed no
192
+ * event. Any other error after the write is ambiguous only in dispatch, never
193
+ * in durability: the event may already be committed, and a later wake of the
194
+ * run (from any source) will deliver it.
195
+ *
196
+ * Prefer passing the token string over a cached {@link Hook} object. A token
197
+ * is looked up fresh, so the live backend can attest its atomic resume claim
198
+ * and the durable write becomes idempotent-on-retry (transport retries of the
199
+ * same write converge on one event). A supplied Hook object may carry a stale
200
+ * attestation, so it is deliberately ignored and the write is claim-less —
201
+ * meaning a lost response cannot be retried safely: retrying at the
202
+ * application level mints a fresh claim and can commit a second
203
+ * `hook_received`.
204
+ *
149
205
  * @param tokenOrHook - The unique token identifying the hook, or the hook object itself
150
206
  * @param payload - The data payload to send to the hook
151
207
  * @returns Promise resolving to the {@link ResumedHook}
@@ -173,37 +229,16 @@ export async function resumeHook(tokenOrHook, payload, encryptionKeyOverride) {
173
229
  // Public entry point. It never attests hook freshness, so a Hook object
174
230
  // supplied here (which may carry a `resumeCapabilities` cached before a
175
231
  // server rollback or kill switch) is ignored by the dynamic-dedup gate and
176
- // fails closed to the sequential path. Only `resumeWebhook`, which fetches
177
- // the hook by token in-line during the same resume, reaches the internal
178
- // implementation with the fresh attestation set. Keeping the freshness flag
179
- // off the exported signature prevents a caller from passing a stale Hook plus
180
- // `true` and reactivating dynamic dedup against a rolled-back backend.
232
+ // fails closed to a plain, claim-less write. Only `resumeWebhook`, which
233
+ // fetches the hook by token in-line during the same resume, reaches the
234
+ // internal implementation with the fresh attestation set. Keeping the
235
+ // freshness flag off the exported signature prevents a caller from passing a
236
+ // stale Hook plus `true` and reactivating dynamic dedup against a
237
+ // rolled-back backend.
181
238
  //
182
239
  // T0 of the hook-resume TTR window is taken HERE, at the public entry point,
183
240
  // rather than inside the implementation; see the parameter's doc comment.
184
- return resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, false, Date.now(), false);
185
- }
186
- /**
187
- * {@link resumeHook} with the `hook_received` event written BEFORE this
188
- * resolves, for the one caller that needs the resume to be durable at that
189
- * instant rather than merely dispatched.
190
- *
191
- * The lazy path leaves the write to the queue consumer, so a normal
192
- * `resumeHook()` resolves while the event is still in flight. That is fine for
193
- * an external resume, whose caller has nothing racing it. It is NOT fine for a
194
- * resume the runtime itself issues as a barrier: a step that aborts a shared
195
- * `AbortController` resumes the hook that records the abort in the event log,
196
- * and that write has to land before the step completes, or the workflow
197
- * continuation `step_completed` enqueues can dispatch the next step with a
198
- * stale, non-aborted signal (see `reviveAbortController` in serialization.ts).
199
- *
200
- * Forcing the eager write costs the round trip the lazy path removes, which is
201
- * the right trade here: this is an internal ordering barrier, not the
202
- * latency-sensitive external resume the optimization targets. The resume span
203
- * reports `resume_fallback_reason: durable_required`.
204
- */
205
- export async function resumeHookDurable(tokenOrHook, payload, encryptionKeyOverride) {
206
- return resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, false, Date.now(), true);
241
+ return resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, false, Date.now());
207
242
  }
208
243
  /**
209
244
  * Internal implementation of {@link resumeHook}. NOT exported: the
@@ -221,10 +256,8 @@ export async function resumeHookDurable(tokenOrHook, payload, encryptionKeyOverr
221
256
  * resolution that hydrates hook metadata, and the `respondWith` setup) and
222
257
  * stamping locally would silently exclude all of it, so the two entry points
223
258
  * would report the same metric over different windows.
224
- * @param requireDurableWrite - Force the sequential path so `hook_received` is
225
- * committed before this resolves. See {@link resumeHookDurable}.
226
259
  */
227
- async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs, requireDurableWrite) {
260
+ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs) {
228
261
  return await waitedUntil(() => {
229
262
  return trace('hook.resume', async (span) => {
230
263
  const world = await getWorldLazy();
@@ -307,18 +340,31 @@ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookF
307
340
  capabilities.supportedFormats.has(SerializationFormat.GZIP);
308
341
  // Dehydrate the payload for storage
309
342
  const ops = [];
343
+ const readbackOps = [];
310
344
  const v1Compat = isLegacySpecVersion(hook.specVersion);
311
- const dehydratedPayload = await dehydrateStepReturnValue(payload, hook.runId, payloadKey, ops, globalThis, v1Compat, capabilities.framedByteStreams, compression);
312
- // These payload-stream ops are flushed in the background; the
313
- // promise handed to waitUntil must never reject (an unconsumed
314
- // waitUntil rejection crashes the process as unhandledRejection),
315
- // so unexpected failures are logged instead.
316
- // NOTE: rejections with `undefined` are an expected artifact of the
317
- // webhook bundle and are ignored entirely.
318
- safeWaitUntil(Promise.all(ops), (err) => {
345
+ const dehydratedPayload = await dehydrateStepReturnValue(payload, hook.runId, payloadKey, ops, globalThis, v1Compat, capabilities.framedByteStreams, compression, undefined, readbackOps);
346
+ // A hook_received event is not durable while its payload still points
347
+ // at stream uploads in flight. Finish those before committing the
348
+ // event but ONLY the producer-push ops in `ops`. A dehydrated
349
+ // WritableStream lands in `readbackOps` instead: it is a server-stream
350
+ // READER that resolves only once the woken workflow writes into it (a
351
+ // manual webhook's `responseWritable` is the canonical case), so
352
+ // awaiting it here would deadlock the resume against its own wake.
353
+ //
354
+ // A rejection with `undefined` is an expected artifact of the webhook
355
+ // bundle and was historically ignored by the background flush. Keep
356
+ // that tolerance now that the flush is awaited inline.
357
+ await Promise.all(ops.map((op) => op.catch((error) => {
358
+ if (error !== undefined)
359
+ throw error;
360
+ })));
361
+ // Readback pipes (notably a manual webhook response writable) can only
362
+ // finish after the workflow wakes and writes to them. Keep them alive,
363
+ // but never place them in the durability barrier above.
364
+ safeWaitUntil(Promise.all(readbackOps), (err) => {
319
365
  if (err === undefined)
320
366
  return;
321
- runtimeLogger.warn('Background flush of hook payload ops failed', {
367
+ runtimeLogger.warn('Background readback of hook payload failed', {
322
368
  workflowRunId: hook.runId,
323
369
  hookId: hook.hookId,
324
370
  error: err instanceof Error ? err.message : String(err),
@@ -328,8 +374,8 @@ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookF
328
374
  ...Attribute.WorkflowName(resumeContext.workflowName),
329
375
  });
330
376
  // Link to the run-origin context from the stored trace carrier
331
- // (skipped when absent or invalid). Resolved before dispatch so both
332
- // the sequential and lazy paths attach it.
377
+ // (skipped when absent or invalid). Resolved before dispatch so the
378
+ // write and the wake both sit under a span that carries it.
333
379
  const originLink = await linkToTraceCarrier(resumeContext.traceCarrier);
334
380
  if (originLink) {
335
381
  span?.addLink?.(originLink);
@@ -339,214 +385,114 @@ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookF
339
385
  deploymentId: resumeContext.deploymentId,
340
386
  specVersion: resumeContext.runSpecVersion ?? SPEC_VERSION_LEGACY,
341
387
  };
342
- // Decide whether the `hook_received` event is written lazily by the
343
- // queue consumer (from the message's `hookInput`) or eagerly here,
344
- // before the publish. The lazy path is only safe when EVERY
345
- // precondition holds; the first that fails names the fallback reason
346
- // (emitted as a span attribute for observability, and to make "why did
347
- // this run sequential" answerable in production). All conditions:
388
+ // The dispatch is strictly serial: the hook_received event is made
389
+ // durable FIRST, and the workflow wake is published only after the
390
+ // write is acknowledged. This is what lets `resumeHook()` resolving
391
+ // mean "the resume survives anything that happens next" a disposal
392
+ // or run completion racing the queue delivery cannot erase a committed
393
+ // event, and the wake itself carries no payload, so nothing rides on
394
+ // the message but the trigger.
348
395
  //
349
- // - kill switch: `WORKFLOW_DISABLE_LAZY_HOOK_RESUME` forces sequential
350
- // if the lazy path ever misbehaves. It is an SDK-deployment env var,
351
- // so changing it generally requires redeploying the workflow
352
- // deployment. (The backend can independently drop new resumes to the
353
- // sequential path fleet-wide by ceasing to attest dedup support on
354
- // the by-token lookup; see the backend-dedup condition below.)
355
- // - backend dedup: the live backend must enforce the
356
- // `(runId, resumeId)` constraint, or a queue redelivery would commit
357
- // a second `hook_received`. Fail closed. Attested by EITHER a fresh,
358
- // response-only `hook.resumeCapabilities.hookResumeDedupVersion` from
359
- // the by-token lookup (world-vercel: recomputed every read, so a
360
- // server rollback or kill switch drops to sequential immediately) OR
361
- // the static `world.capabilities.hookResumeDedup` (world-local, whose
362
- // adapter and backend ship together). The response-only capability is
363
- // trusted ONLY when the hook was looked up by token during this
364
- // resume (`hookResumeCapabilitiesAreFresh`); a Hook object handed in
365
- // by a public caller may carry a capability cached before a rollback,
366
- // so it is ignored and the path falls back to sequential.
367
- // - consumer support: the target run's deployment must materialize the
368
- // event from `hookInput` on replay. Attested by the run's explicit
369
- // `hookResumeInputVersion` execution-context marker (mirrored onto
370
- // resumeContext), NOT a version-compare against a predicted release
371
- // cutoff. Absent → nothing would ever write the event, so the resume
372
- // would be lost outright.
373
- // - not legacy: v1Compat runs omit `token` from the eagerly written
374
- // event body but the consumer always includes it, so a legacy run
375
- // would get a different event depending on which path ran. Legacy
376
- // stays sequential.
377
- // - CBOR transport: the run must use CBOR queue transport so the binary
378
- // payload survives the queue message.
379
- // - raw bytes: the dehydrated payload must be a `Uint8Array` (the
380
- // content digest that keys the dedup constraint is over these bytes).
381
- // - size: on the lazy path the queue message carries the only copy of
382
- // the payload, so a payload above the message ceiling would fail the
383
- // publish and lose the resume. Oversized payloads stay sequential
384
- // (their queue message carries only the run ID; the payload lives in
385
- // the event log).
386
- const lazyResumeDisabled = process.env.WORKFLOW_DISABLE_LAZY_HOOK_RESUME === '1';
387
- // Backend dedup is supported when EITHER the live server attests it
396
+ // Backend dedup is attested when EITHER the live server attests it
388
397
  // fresh on this by-token hook (world-vercel: response-only, recomputed
389
398
  // every read, so rollback/kill-switch take effect immediately) OR the
390
399
  // static world capability is set (world-local: adapter + backend ship
391
- // together). Both are re-evaluated per resume, so every rollout and
392
- // rollback direction degrades safely to the sequential path.
400
+ // together). When attested, the write carries a per-call resumeId +
401
+ // payload digest so transport-level retries of the SAME write converge
402
+ // on exactly one committed event via the backend's (runId, resumeId)
403
+ // constraint. Without it the write is a plain single-shot create,
404
+ // exactly as before dedup existed.
393
405
  const backendDedupSupported = (hookResumeCapabilitiesAreFresh
394
406
  ? (hook.resumeCapabilities?.hookResumeDedupVersion ?? 0)
395
407
  : 0) >= HOOK_RESUME_DEDUP_VERSION ||
396
408
  world.capabilities?.hookResumeDedup === true;
397
- const fallbackReason = requireDurableWrite
398
- ? // An internal caller needs the event committed before this
399
- // resolves (an ordering barrier), which only the eager write
400
- // provides. Checked first so the span names the real reason
401
- // rather than whichever gate happens to fail alongside it.
402
- 'durable_required'
403
- : lazyResumeDisabled
404
- ? 'disabled'
405
- : !backendDedupSupported
406
- ? 'backend_unsupported'
407
- : (resumeContext.hookResumeInputVersion ?? 0) <
408
- HOOK_RESUME_INPUT_VERSION
409
- ? 'consumer_unsupported'
410
- : v1Compat
411
- ? 'legacy'
412
- : (resumeContext.runSpecVersion ?? 0) <
413
- SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT
414
- ? 'non_cbor_transport'
415
- : !(dehydratedPayload instanceof Uint8Array)
416
- ? 'non_bytes'
417
- : dehydratedPayload.byteLength >
418
- MAX_INLINE_RESUME_PAYLOAD_BYTES
419
- ? 'oversized'
420
- : null;
421
- const useLazyResume = fallbackReason === null;
409
+ const canClaimResume = backendDedupSupported &&
410
+ !v1Compat &&
411
+ dehydratedPayload instanceof Uint8Array;
422
412
  span?.setAttributes({
423
- 'workflow.hook.resume_strategy': useLazyResume
424
- ? 'lazy'
425
- : 'sequential',
426
- ...(fallbackReason
427
- ? { 'workflow.hook.resume_fallback_reason': fallbackReason }
428
- : {}),
413
+ 'workflow.hook.resume_strategy': 'sequential',
429
414
  });
430
- if (!useLazyResume) {
431
- // Sequential path: create a hook_received event, then re-trigger.
432
- //
433
- // Re-key any "hook can no longer be received" rejection to
434
- // HookNotFoundError(hook.token) so `.token` matches the historical
435
- // contract, where resumeHook threw `HookNotFoundError(hook.token)`
436
- // after its own terminal check. The specific error depends on the
437
- // World:
438
- // - a genuinely missing hook maps to HookNotFoundError (keyed on
439
- // the event correlationId / hook ID);
440
- // - a terminal run on Vercel rejects hook_received with 404, which
441
- // world-vercel maps to HookNotFoundError;
442
- // - a terminal run on world-local / world-postgres rejects with
443
- // RunExpiredError.
444
- //
445
- // An EntityConflictError (HTTP 409) is also treated as "hook gone"
446
- // here for historical / conflict-shaped-rejection compatibility:
447
- // this path holds no queue message in flight, so a conflict has no
448
- // consumer to converge on.
449
- //
450
- // The lazy path performs no write, so it raises none of these: see
451
- // the note on its terminal-run behavior below.
452
- const isHookGoneError = (err) => HookNotFoundError.is(err) ||
453
- EntityConflictError.is(err) ||
454
- RunExpiredError.is(err);
455
- try {
456
- await world.events.create(hook.runId, {
457
- eventType: 'hook_received',
458
- specVersion: SPEC_VERSION_CURRENT,
459
- correlationId: hook.hookId,
460
- eventData: {
461
- ...(v1Compat ? {} : { token: hook.token }),
462
- payload: dehydratedPayload,
463
- },
464
- }, { v1Compat });
465
- }
466
- catch (err) {
467
- if (isHookGoneError(err)) {
468
- throw new HookNotFoundError(hook.token);
469
- }
470
- throw err;
471
- }
472
- // T1 of the TTR window. Stamped immediately before the publish so
473
- // `producer_prep` covers exactly the work above it (hook lookup,
474
- // key resolution, serialization, and, on this path, the awaited
475
- // `hook_received` write, which is genuinely serial here).
476
- const queuePublishRequestedAtMs = Date.now();
477
- await world.queue(queueName, {
478
- runId: hook.runId,
479
- traceCarrier: resumeContext.traceCarrier ?? undefined,
480
- hookResumeTiming: {
481
- resumeRequestedAtMs,
482
- queuePublishRequestedAtMs,
483
- strategy: 'sequential',
484
- },
485
- }, queueOptions);
486
- return hook;
415
+ const resumeId = canClaimResume ? generateResumeId() : undefined;
416
+ const payloadDigest = canClaimResume
417
+ ? await computeResumePayloadDigest(dehydratedPayload)
418
+ : undefined;
419
+ if (resumeId) {
420
+ span?.setAttributes({ 'workflow.hook.resume_id': resumeId });
487
421
  }
488
- // Lazy path: publish the queue message and let the consumer write the
489
- // `hook_received` event from `hookInput` before it replays. The
490
- // producer writes nothing, so the resume costs exactly one round trip
491
- // (the publish) instead of two, and the event is created once, by the
492
- // side that is about to replay it.
493
- //
494
- // `resumeId` is the idempotency key the consumer sends with that write;
495
- // `payloadDigest` lets the server detect key reuse across
496
- // byte-different payloads. Both ride the message, so every redelivery
497
- // of it converges on the one committed event via the backend's
498
- // `(runId, resumeId)` constraint (the precondition gated above).
422
+ // Re-key any "hook can no longer be received" rejection to
423
+ // HookNotFoundError(hook.token) so `.token` matches the historical
424
+ // contract. The specific error depends on the World:
425
+ // - a genuinely missing hook maps to HookNotFoundError (keyed on
426
+ // the event correlationId / hook ID);
427
+ // - a terminal run on Vercel rejects hook_received with 404, which
428
+ // world-vercel maps to HookNotFoundError;
429
+ // - a terminal run on world-local / world-postgres rejects with
430
+ // RunExpiredError.
499
431
  //
500
- // Two things a caller could previously infer from a resolved resume,
501
- // and can no longer:
502
- //
503
- // - Visibility. This returns once the publish is accepted, not once
504
- // `hook_received` exists, so a caller that reads the run back
505
- // immediately can see a log without it. Delivery is unaffected: the
506
- // payload is on the message.
507
- // - The run still being live. The hook lookup above still validates
508
- // that a hook holds the token (and which run it belongs to), but
509
- // `resumeContext` is an immutable slice and carries no status, and
510
- // with no write there is no server rejection to observe. A resume
511
- // against an ended run therefore resolves rather than throwing
512
- // HookNotFoundError. It is reachable only while the hook outlives
513
- // its run (minimum retention, or before the token is released);
514
- // otherwise the lookup itself fails. Nothing resumes either way:
515
- // the consumer's write is rejected the same way and the delivery is
516
- // consumed. The paths that do observe the status are unchanged: the
517
- // `run_fallback` terminal pre-check above, and the sequential
518
- // path's own write.
519
- const resumeId = generateResumeId();
520
- const payloadDigest = await computeResumePayloadDigest(dehydratedPayload);
521
- span?.setAttributes({ 'workflow.hook.resume_id': resumeId });
522
- // T1 of the TTR window, stamped at the instant the publish is
523
- // requested: `producer_prep` covers exactly the work above it (hook
524
- // lookup, key resolution, serialization) and nothing else, since no
525
- // event write remains on this path.
432
+ // An EntityConflictError (HTTP 409) is deliberately NOT re-keyed,
433
+ // breaking with the historical mapping: every 409 the backend emits
434
+ // on this write today is TRANSIENT — a slot conflict that escaped the
435
+ // server's own retry budget under contention, or a resume-claim race
436
+ // mid-resolution and its transaction committed nothing. Re-keying
437
+ // it to HookNotFoundError told the caller (and a webhook sender, via
438
+ // 404) that a retryable failure was permanent, silently dropping the
439
+ // resume. It now surfaces as-is: retryable, with nothing committed.
440
+ // (A 422 resumeId-reuse error likewise passes through unmapped it
441
+ // means the caller replayed a resumeId with a different payload, and
442
+ // hiding that behind "not found" would mask the bug.)
443
+ const isHookGoneError = (err) => HookNotFoundError.is(err) || RunExpiredError.is(err);
444
+ try {
445
+ await world.events.create(hook.runId, {
446
+ eventType: 'hook_received',
447
+ specVersion: SPEC_VERSION_CURRENT,
448
+ correlationId: hook.hookId,
449
+ eventData: {
450
+ ...(v1Compat ? {} : { token: hook.token }),
451
+ payload: dehydratedPayload,
452
+ },
453
+ }, {
454
+ v1Compat,
455
+ ...(resumeId && payloadDigest
456
+ ? { resumeId, resumePayloadDigest: payloadDigest }
457
+ : {}),
458
+ });
459
+ }
460
+ catch (err) {
461
+ if (isHookGoneError(err)) {
462
+ throw new HookNotFoundError(hook.token);
463
+ }
464
+ throw err;
465
+ }
466
+ // Stamped AFTER the write resolves (entry-time attributes cannot tell
467
+ // an attempted resume from a committed one): together with
468
+ // HookWakePublished below, this is what makes a stranded resume — a
469
+ // committed event whose wake never went out or was never delivered —
470
+ // queryable from traces. See the alerting note on HookWakePublished.
471
+ span?.setAttributes(Attribute.HookResumeCommitted(true));
472
+ // T1 of the TTR window. Stamped immediately before the publish so
473
+ // `producer_prep` covers exactly the work above it (hook lookup, key
474
+ // resolution, serialization, and the awaited hook_received write,
475
+ // which is genuinely serial here).
526
476
  const queuePublishRequestedAtMs = Date.now();
527
- await world.queue(queueName, {
477
+ await publishHookWakeWithRetry(() => world.queue(queueName, {
528
478
  runId: hook.runId,
529
479
  traceCarrier: resumeContext.traceCarrier ?? undefined,
530
- hookInput: {
531
- resumeId,
532
- hookId: hook.hookId,
533
- token: hook.token,
534
- payload: dehydratedPayload,
535
- payloadDigest,
536
- // Deployment affinity for the consumer's cheap pre-write
537
- // check: lets a misrouted delivery re-route before its
538
- // hoisted hook_received write instead of after.
539
- deploymentId: resumeContext.deploymentId,
540
- },
541
480
  hookResumeTiming: {
542
481
  resumeRequestedAtMs,
543
482
  queuePublishRequestedAtMs,
544
- strategy: 'lazy',
483
+ strategy: 'sequential',
545
484
  },
546
- }, queueOptions);
547
- // A rejected publish propagates: the message is the only carrier of
548
- // both the trigger and the payload, so a failed publish is a failed
549
- // resume, with nothing persisted for a later delivery to pick up.
485
+ }, {
486
+ ...queueOptions,
487
+ // Dedup retried publishes whose response was lost: a
488
+ // duplicate wake is harmless for correctness (deterministic
489
+ // replay) but costs a full replay of the run, and the queue
490
+ // accepts a repeated idempotency key by delivering only one
491
+ // of the messages. Claim-less writes have no resumeId and
492
+ // keep the previous behavior.
493
+ ...(resumeId ? { idempotencyKey: `hook-${resumeId}` } : {}),
494
+ }), world.isDeploymentUnavailableError?.bind(world));
495
+ span?.setAttributes(Attribute.HookWakePublished(true));
550
496
  return hook;
551
497
  }
552
498
  catch (err) {
@@ -635,9 +581,9 @@ export async function resumeWebhook(token, request) {
635
581
  // `hook` was just fetched via `getHookByTokenWithKey` (a fresh by-token
636
582
  // lookup) above, so its response-only `resumeCapabilities` reflects the live
637
583
  // backend. Call the internal implementation with the fresh attestation so
638
- // the lazy path stays available without a second GET. (The public
639
- // `resumeHook` never sets this, so a caller cannot forge it.)
640
- await resumeHookImpl(hook, request, encryptionKey, true, resumeRequestedAtMs, false);
584
+ // the write's idempotency claim stays available without a second GET. (The
585
+ // public `resumeHook` never sets this, so a caller cannot forge it.)
586
+ await resumeHookImpl(hook, request, encryptionKey, true, resumeRequestedAtMs);
641
587
  if (responseReadable) {
642
588
  // Wait for the readable stream to emit one chunk,
643
589
  // which is the `Response` object
@@ -655,4 +601,4 @@ export async function resumeWebhook(token, request) {
655
601
  }
656
602
  return response;
657
603
  }
658
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzdW1lLWhvb2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVudGltZS9yZXN1bWUtaG9vay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLFdBQVcsRUFDWCxpQkFBaUIsRUFDakIsZUFBZSxFQUNmLG9CQUFvQixHQUNyQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFDTCx5QkFBeUIsRUFDekIseUJBQXlCLEVBR3pCLG1CQUFtQixFQUNuQiwyQkFBMkIsRUFDM0Isb0JBQW9CLEVBQ3BCLG1CQUFtQixFQUNuQiwwQ0FBMEMsRUFDMUMsaUNBQWlDLEdBR2xDLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3RFLE9BQU8sRUFDTCx3QkFBd0IsRUFDeEIsb0JBQW9CLEVBRXBCLG1CQUFtQixFQUNuQixNQUFNLEdBQ1AsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUQsT0FBTyxLQUFLLFNBQVMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsS0FBSyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDNUQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNwRCxPQUFPLEVBQUUsYUFBYSxFQUFFLFdBQVcsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRTdELG1FQUFtRTtBQUNuRSxNQUFNLGdCQUFnQixHQUFHLGdCQUFnQixFQUFFLENBQUM7QUFFNUM7Ozs7Ozs7Ozs7R0FVRztBQUNILE1BQU0sK0JBQStCLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQztBQUVuRDs7Ozs7Ozs7R0FRRztBQUNILEtBQUssVUFBVSwwQkFBMEIsQ0FBQyxLQUFpQjtJQUN6RCxNQUFNLE1BQU0sR0FBRyxNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUM1RCxNQUFNLElBQUksR0FBRyxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNwQyxJQUFJLEdBQUcsR0FBRyxFQUFFLENBQUM7SUFDYixLQUFLLE1BQU0sQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQ3JCLEdBQUcsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQWNELHdGQUF3RjtBQUN4RixTQUFTLG9CQUFvQixDQUFDLEdBQWdCO0lBQzVDLE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxtQkFBbUIsQ0FBQztJQUM5RCxNQUFNLFlBQVksR0FBRyxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsWUFBWSxDQUFDO0lBQ3hELE1BQU0sc0JBQXNCLEdBQUcsR0FBRyxDQUFDLGdCQUFnQixFQUFFLHNCQUFzQixDQUFDO0lBQzVFLE9BQU87UUFDTCxZQUFZLEVBQUUsR0FBRyxDQUFDLFlBQVk7UUFDOUIsWUFBWSxFQUFFLEdBQUcsQ0FBQyxZQUFZO1FBQzlCLGNBQWMsRUFBRSxHQUFHLENBQUMsV0FBVztRQUMvQixtQkFBbUIsRUFDakIsT0FBTyxXQUFXLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLFNBQVM7UUFDM0QsWUFBWSxFQUNWLFlBQVksSUFBSSxPQUFPLFlBQVksS0FBSyxRQUFRO1lBQzlDLENBQUMsQ0FBRSxZQUFrRDtZQUNyRCxDQUFDLENBQUMsU0FBUztRQUNmLG1CQUFtQixFQUFFLEdBQUcsQ0FBQyxtQkFBbUI7UUFDNUMsc0JBQXNCLEVBQ3BCLE9BQU8sc0JBQXNCLEtBQUssUUFBUTtZQUN4QyxDQUFDLENBQUMsc0JBQXNCO1lBQ3hCLENBQUMsQ0FBQyxTQUFTO0tBQ2hCLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSCxLQUFLLFVBQVUscUJBQXFCLENBQUMsSUFBVTtJQUM3QyxJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUN2QixPQUFPLEVBQUUsYUFBYSxFQUFFLElBQUksQ0FBQyxhQUFhLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxDQUFDO0lBQy9ELENBQUM7SUFDRCxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsTUFBTSxZQUFZLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzlELE9BQU87UUFDTCxhQUFhLEVBQUUsb0JBQW9CLENBQUMsR0FBRyxDQUFDO1FBQ3hDLE1BQU0sRUFBRSxjQUFjO1FBQ3RCLEdBQUc7S0FDSixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILEtBQUssVUFBVSx3QkFBd0IsQ0FDckMsSUFBVSxFQUNWLElBQW9CO0lBRXBCLE1BQU0sS0FBSyxHQUFHLE1BQU0sWUFBWSxFQUFFLENBQUM7SUFDbkMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUc7UUFDckIsQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLHNCQUFzQixFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztRQUNoRCxDQUFDLENBQUMsTUFBTSxLQUFLLENBQUMsc0JBQXNCLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQy9DLFlBQVksRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLFlBQVk7U0FDOUMsQ0FBQyxDQUFDO0lBQ1AsT0FBTyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDdEQsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxLQUFhO0lBSWhELE1BQU0sS0FBSyxHQUFHLE1BQU0sWUFBWSxFQUFFLENBQUM7SUFDbkMsTUFBTSxJQUFJLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUVqRCwwRUFBMEU7SUFDMUUsNkVBQTZFO0lBQzdFLDhFQUE4RTtJQUM5RSxvRUFBb0U7SUFDcEUsMkVBQTJFO0lBQzNFLDZFQUE2RTtJQUM3RSx3RUFBd0U7SUFDeEUsaUVBQWlFO0lBQ2pFLElBQUksYUFBcUMsQ0FBQztJQUMxQyxJQUFJLE9BQU8sSUFBSSxDQUFDLFFBQVEsS0FBSyxXQUFXLEVBQUUsQ0FBQztRQUN6QyxNQUFNLElBQUksR0FBRyxNQUFNLHFCQUFxQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQy9DLHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUc7WUFDckIsQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLHNCQUFzQixFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztZQUNoRCxDQUFDLENBQUMsTUFBTSxLQUFLLENBQUMsc0JBQXNCLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFO2dCQUMvQyxZQUFZLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxZQUFZO2FBQzlDLENBQUMsQ0FBQztRQUNQLGFBQWEsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sb0JBQW9CLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztRQUN4RSxJQUFJLENBQUMsUUFBUSxHQUFHLE1BQU0sb0JBQW9CLENBQ3hDLElBQUksQ0FBQyxRQUFlLEVBQ3BCLElBQUksQ0FBQyxLQUFLLEVBQ1YsYUFBYSxDQUNkLENBQUM7SUFDSixDQUFDO0lBQ0QsT0FBTyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsQ0FBQztBQUNqQyxDQUFDO0FBRUQ7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxjQUFjLENBQUMsS0FBYTtJQUNoRCxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsTUFBTSxxQkFBcUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNwRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFnQkQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E0Qkc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLFVBQVUsQ0FDOUIsV0FBMEIsRUFDMUIsT0FBVSxFQUNWLHFCQUFrQztJQUVsQyx3RUFBd0U7SUFDeEUsd0VBQXdFO0lBQ3hFLDJFQUEyRTtJQUMzRSwyRUFBMkU7SUFDM0UseUVBQXlFO0lBQ3pFLDRFQUE0RTtJQUM1RSw4RUFBOEU7SUFDOUUsdUVBQXVFO0lBQ3ZFLEVBQUU7SUFDRiw2RUFBNkU7SUFDN0UsMEVBQTBFO0lBQzFFLE9BQU8sY0FBYyxDQUNuQixXQUFXLEVBQ1gsT0FBTyxFQUNQLHFCQUFxQixFQUNyQixLQUFLLEVBQ0wsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUNWLEtBQUssQ0FDTixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrQkc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGlCQUFpQixDQUNyQyxXQUEwQixFQUMxQixPQUFVLEVBQ1YscUJBQWtDO0lBRWxDLE9BQU8sY0FBYyxDQUNuQixXQUFXLEVBQ1gsT0FBTyxFQUNQLHFCQUFxQixFQUNyQixLQUFLLEVBQ0wsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUNWLElBQUksQ0FDTCxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrQkc7QUFDSCxLQUFLLFVBQVUsY0FBYyxDQUMzQixXQUEwQixFQUMxQixPQUFVLEVBQ1YscUJBQTZDLEVBQzdDLG1CQUE0QixFQUM1QixtQkFBMkIsRUFDM0IsbUJBQTRCO0lBRTVCLE9BQU8sTUFBTSxXQUFXLENBQUMsR0FBRyxFQUFFO1FBQzVCLE9BQU8sS0FBSyxDQUFDLGFBQWEsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUU7WUFDekMsTUFBTSxLQUFLLEdBQUcsTUFBTSxZQUFZLEVBQUUsQ0FBQztZQUVuQyxJQUFJLENBQUM7Z0JBQ0gsTUFBTSxhQUFhLEdBQUcsT0FBTyxXQUFXLEtBQUssUUFBUSxDQUFDO2dCQUN0RCxNQUFNLElBQUksR0FBUyxhQUFhO29CQUM5QixDQUFDLENBQUMsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUM7b0JBQzNDLENBQUMsQ0FBQyxXQUFXLENBQUM7Z0JBQ2hCLHNFQUFzRTtnQkFDdEUsb0VBQW9FO2dCQUNwRSxNQUFNLDhCQUE4QixHQUNsQyxhQUFhLElBQUksbUJBQW1CLENBQUM7Z0JBRXZDLE1BQU0sSUFBSSxHQUFHLE1BQU0scUJBQXFCLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQy9DLE1BQU0sRUFBRSxhQUFhLEVBQUUsR0FBRyxJQUFJLENBQUM7Z0JBRS9CLElBQUksRUFBRSxhQUFhLENBQUM7b0JBQ2xCLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO29CQUNsQyxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQztvQkFDaEMsR0FBRyxTQUFTLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7b0JBQ3RDLHFDQUFxQyxFQUFFLElBQUksQ0FBQyxNQUFNO2lCQUNuRCxDQUFDLENBQUM7Z0JBRUgsbUVBQW1FO2dCQUNuRSwrREFBK0Q7Z0JBQy9ELHVFQUF1RTtnQkFDdkUscUVBQXFFO2dCQUNyRSx1RUFBdUU7Z0JBQ3ZFLGdFQUFnRTtnQkFDaEUsSUFBSSxJQUFJLENBQUMsR0FBRyxJQUFJLDJCQUEyQixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztvQkFDN0QsTUFBTSxJQUFJLGlCQUFpQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDMUMsQ0FBQztnQkFFRCw4REFBOEQ7Z0JBQzlELG9FQUFvRTtnQkFDcEUsaUVBQWlFO2dCQUNqRSwyREFBMkQ7Z0JBQzNELGlFQUFpRTtnQkFDakUsTUFBTSxZQUFZLEdBQUcsa0JBQWtCLENBQ3JDLGFBQWEsQ0FBQyxtQkFBbUIsQ0FDbEMsQ0FBQztnQkFFRixtRUFBbUU7Z0JBQ25FLEVBQUU7Z0JBQ0YsdUVBQXVFO2dCQUN2RSxzRUFBc0U7Z0JBQ3RFLG9FQUFvRTtnQkFDcEUsa0VBQWtFO2dCQUNsRSxtRUFBbUU7Z0JBQ25FLGdEQUFnRDtnQkFDaEQsRUFBRTtnQkFDRixvRUFBb0U7Z0JBQ3BFLGlFQUFpRTtnQkFDakUsdURBQXVEO2dCQUN2RCxFQUFFO2dCQUNGLG9FQUFvRTtnQkFDcEUsd0VBQXdFO2dCQUN4RSxpRUFBaUU7Z0JBQ2pFLHNFQUFzRTtnQkFDdEUsd0VBQXdFO2dCQUN4RSxpRUFBaUU7Z0JBQ2pFLGtCQUFrQjtnQkFDbEIsSUFBSSxVQUFrQyxDQUFDO2dCQUN2QyxNQUFNLFlBQVksR0FBRyxxQkFBcUI7b0JBQ3hDLENBQUMsQ0FBQyxnRUFBZ0U7d0JBQ2hFLDhEQUE4RDt3QkFDOUQsNENBQTRDO3dCQUM1QyxTQUFTO29CQUNYLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLENBQUMsbUJBQW1CLENBQUMsQ0FBQztnQkFFMUQsSUFBSSxZQUFZLEVBQUUsQ0FBQztvQkFDakIsVUFBVSxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztnQkFDcEMsQ0FBQztxQkFBTSxDQUFDO29CQUNOLDBEQUEwRDtvQkFDMUQsNkRBQTZEO29CQUM3RCw0QkFBNEI7b0JBQzVCLElBQUksYUFBYSxHQUNmLHFCQUFxQjt3QkFDckIsQ0FBQyxNQUFNLHdCQUF3QixDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO29CQUMvQyxJQUNFLENBQUMsWUFBWSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLENBQUMsRUFDakUsQ0FBQzt3QkFDRCxhQUFhLEdBQUcsU0FBUyxDQUFDO29CQUM1QixDQUFDO29CQUNELFVBQVUsR0FBRyxhQUFhLENBQUM7Z0JBQzdCLENBQUM7Z0JBRUQsbUVBQW1FO2dCQUNuRSxzREFBc0Q7Z0JBQ3RELE1BQU0sV0FBVyxHQUNmLENBQUMsYUFBYSxDQUFDLGNBQWMsSUFBSSxDQUFDLENBQUM7b0JBQ2pDLGlDQUFpQztvQkFDbkMsWUFBWSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFFOUQsb0NBQW9DO2dCQUNwQyxNQUFNLEdBQUcsR0FBbUIsRUFBRSxDQUFDO2dCQUMvQixNQUFNLFFBQVEsR0FBRyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQ3ZELE1BQU0saUJBQWlCLEdBQUcsTUFBTSx3QkFBd0IsQ0FDdEQsT0FBTyxFQUNQLElBQUksQ0FBQyxLQUFLLEVBQ1YsVUFBVSxFQUNWLEdBQUcsRUFDSCxVQUFVLEVBQ1YsUUFBUSxFQUNSLFlBQVksQ0FBQyxpQkFBaUIsRUFDOUIsV0FBVyxDQUNaLENBQUM7Z0JBQ0YsOERBQThEO2dCQUM5RCwrREFBK0Q7Z0JBQy9ELGtFQUFrRTtnQkFDbEUsNkNBQTZDO2dCQUM3QyxvRUFBb0U7Z0JBQ3BFLDJDQUEyQztnQkFDM0MsYUFBYSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRTtvQkFDdEMsSUFBSSxHQUFHLEtBQUssU0FBUzt3QkFBRSxPQUFPO29CQUM5QixhQUFhLENBQUMsSUFBSSxDQUFDLDZDQUE2QyxFQUFFO3dCQUNoRSxhQUFhLEVBQUUsSUFBSSxDQUFDLEtBQUs7d0JBQ3pCLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTt3QkFDbkIsS0FBSyxFQUFFLEdBQUcsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUM7cUJBQ3hELENBQUMsQ0FBQztnQkFDTCxDQUFDLENBQUMsQ0FBQztnQkFFSCxJQUFJLEVBQUUsYUFBYSxDQUFDO29CQUNsQixHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQztpQkFDdEQsQ0FBQyxDQUFDO2dCQUVILCtEQUErRDtnQkFDL0QscUVBQXFFO2dCQUNyRSwyQ0FBMkM7Z0JBQzNDLE1BQU0sVUFBVSxHQUFHLE1BQU0sa0JBQWtCLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUN4RSxJQUFJLFVBQVUsRUFBRSxDQUFDO29CQUNmLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDOUIsQ0FBQztnQkFFRCxNQUFNLFNBQVMsR0FBRyxvQkFBb0IsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7Z0JBQ25FLE1BQU0sWUFBWSxHQUFHO29CQUNuQixZQUFZLEVBQUUsYUFBYSxDQUFDLFlBQVk7b0JBQ3hDLFdBQVcsRUFBRSxhQUFhLENBQUMsY0FBYyxJQUFJLG1CQUFtQjtpQkFDakUsQ0FBQztnQkFFRixvRUFBb0U7Z0JBQ3BFLG1FQUFtRTtnQkFDbkUsNERBQTREO2dCQUM1RCxxRUFBcUU7Z0JBQ3JFLHVFQUF1RTtnQkFDdkUsa0VBQWtFO2dCQUNsRSxFQUFFO2dCQUNGLHdFQUF3RTtnQkFDeEUsd0VBQXdFO2dCQUN4RSxnRUFBZ0U7Z0JBQ2hFLHdFQUF3RTtnQkFDeEUsc0VBQXNFO2dCQUN0RSxrRUFBa0U7Z0JBQ2xFLHNEQUFzRDtnQkFDdEQsd0VBQXdFO2dCQUN4RSx3RUFBd0U7Z0JBQ3hFLHlFQUF5RTtnQkFDekUsb0VBQW9FO2dCQUNwRSx3RUFBd0U7Z0JBQ3hFLHlFQUF5RTtnQkFDekUseUVBQXlFO2dCQUN6RSxtRUFBbUU7Z0JBQ25FLHdFQUF3RTtnQkFDeEUseUVBQXlFO2dCQUN6RSw2REFBNkQ7Z0JBQzdELHdFQUF3RTtnQkFDeEUsc0VBQXNFO2dCQUN0RSxzRUFBc0U7Z0JBQ3RFLHVFQUF1RTtnQkFDdkUsd0VBQXdFO2dCQUN4RSw2QkFBNkI7Z0JBQzdCLHFFQUFxRTtnQkFDckUscUVBQXFFO2dCQUNyRSxxRUFBcUU7Z0JBQ3JFLHVCQUF1QjtnQkFDdkIseUVBQXlFO2dCQUN6RSx5Q0FBeUM7Z0JBQ3pDLG1FQUFtRTtnQkFDbkUseUVBQXlFO2dCQUN6RSx1RUFBdUU7Z0JBQ3ZFLHdFQUF3RTtnQkFDeEUscUVBQXFFO2dCQUNyRSx3RUFBd0U7Z0JBQ3hFLHFCQUFxQjtnQkFDckIsTUFBTSxrQkFBa0IsR0FDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQ0FBaUMsS0FBSyxHQUFHLENBQUM7Z0JBQ3hELG9FQUFvRTtnQkFDcEUsdUVBQXVFO2dCQUN2RSxzRUFBc0U7Z0JBQ3RFLHNFQUFzRTtnQkFDdEUsb0VBQW9FO2dCQUNwRSw2REFBNkQ7Z0JBQzdELE1BQU0scUJBQXFCLEdBQ3pCLENBQUMsOEJBQThCO29CQUM3QixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsc0JBQXNCLElBQUksQ0FBQyxDQUFDO29CQUN4RCxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUkseUJBQXlCO29CQUNuQyxLQUFLLENBQUMsWUFBWSxFQUFFLGVBQWUsS0FBSyxJQUFJLENBQUM7Z0JBQy9DLE1BQU0sY0FBYyxHQUFrQixtQkFBbUI7b0JBQ3ZELENBQUMsQ0FBQywyREFBMkQ7d0JBQzNELDZEQUE2RDt3QkFDN0QsNERBQTREO3dCQUM1RCwyREFBMkQ7d0JBQzNELGtCQUFrQjtvQkFDcEIsQ0FBQyxDQUFDLGtCQUFrQjt3QkFDbEIsQ0FBQyxDQUFDLFVBQVU7d0JBQ1osQ0FBQyxDQUFDLENBQUMscUJBQXFCOzRCQUN0QixDQUFDLENBQUMscUJBQXFCOzRCQUN2QixDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsc0JBQXNCLElBQUksQ0FBQyxDQUFDO2dDQUN6Qyx5QkFBeUI7Z0NBQzNCLENBQUMsQ0FBQyxzQkFBc0I7Z0NBQ3hCLENBQUMsQ0FBQyxRQUFRO29DQUNSLENBQUMsQ0FBQyxRQUFRO29DQUNWLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxjQUFjLElBQUksQ0FBQyxDQUFDO3dDQUNqQywwQ0FBMEM7d0NBQzVDLENBQUMsQ0FBQyxvQkFBb0I7d0NBQ3RCLENBQUMsQ0FBQyxDQUFDLENBQUMsaUJBQWlCLFlBQVksVUFBVSxDQUFDOzRDQUMxQyxDQUFDLENBQUMsV0FBVzs0Q0FDYixDQUFDLENBQUMsaUJBQWlCLENBQUMsVUFBVTtnREFDMUIsK0JBQStCO2dEQUNqQyxDQUFDLENBQUMsV0FBVztnREFDYixDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUN2QixNQUFNLGFBQWEsR0FBRyxjQUFjLEtBQUssSUFBSSxDQUFDO2dCQUU5QyxJQUFJLEVBQUUsYUFBYSxDQUFDO29CQUNsQiwrQkFBK0IsRUFBRSxhQUFhO3dCQUM1QyxDQUFDLENBQUMsTUFBTTt3QkFDUixDQUFDLENBQUMsWUFBWTtvQkFDaEIsR0FBRyxDQUFDLGNBQWM7d0JBQ2hCLENBQUMsQ0FBQyxFQUFFLHNDQUFzQyxFQUFFLGNBQWMsRUFBRTt3QkFDNUQsQ0FBQyxDQUFDLEVBQUUsQ0FBQztpQkFDUixDQUFDLENBQUM7Z0JBRUgsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO29CQUNuQixrRUFBa0U7b0JBQ2xFLEVBQUU7b0JBQ0YsMkRBQTJEO29CQUMzRCxtRUFBbUU7b0JBQ25FLG1FQUFtRTtvQkFDbkUsa0VBQWtFO29CQUNsRSxTQUFTO29CQUNULG1FQUFtRTtvQkFDbkUsMENBQTBDO29CQUMxQyxxRUFBcUU7b0JBQ3JFLDhDQUE4QztvQkFDOUMsa0VBQWtFO29CQUNsRSx1QkFBdUI7b0JBQ3ZCLEVBQUU7b0JBQ0YsbUVBQW1FO29CQUNuRSxpRUFBaUU7b0JBQ2pFLG1FQUFtRTtvQkFDbkUsMkJBQTJCO29CQUMzQixFQUFFO29CQUNGLG1FQUFtRTtvQkFDbkUsK0NBQStDO29CQUMvQyxNQUFNLGVBQWUsR0FBRyxDQUFDLEdBQVksRUFBVyxFQUFFLENBQ2hELGlCQUFpQixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7d0JBQ3pCLG1CQUFtQixDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7d0JBQzNCLGVBQWUsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBQzFCLElBQUksQ0FBQzt3QkFDSCxNQUFNLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUN2QixJQUFJLENBQUMsS0FBSyxFQUNWOzRCQUNFLFNBQVMsRUFBRSxlQUFlOzRCQUMxQixXQUFXLEVBQUUsb0JBQW9COzRCQUNqQyxhQUFhLEVBQUUsSUFBSSxDQUFDLE1BQU07NEJBQzFCLFNBQVMsRUFBRTtnQ0FDVCxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQ0FDMUMsT0FBTyxFQUFFLGlCQUFpQjs2QkFDM0I7eUJBQ0YsRUFDRCxFQUFFLFFBQVEsRUFBRSxDQUNiLENBQUM7b0JBQ0osQ0FBQztvQkFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO3dCQUNiLElBQUksZUFBZSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7NEJBQ3pCLE1BQU0sSUFBSSxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7d0JBQzFDLENBQUM7d0JBQ0QsTUFBTSxHQUFHLENBQUM7b0JBQ1osQ0FBQztvQkFFRCxrRUFBa0U7b0JBQ2xFLGlFQUFpRTtvQkFDakUsZ0VBQWdFO29CQUNoRSwwREFBMEQ7b0JBQzFELE1BQU0seUJBQXlCLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO29CQUM3QyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQ2YsU0FBUyxFQUNUO3dCQUNFLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSzt3QkFDakIsWUFBWSxFQUFFLGFBQWEsQ0FBQyxZQUFZLElBQUksU0FBUzt3QkFDckQsZ0JBQWdCLEVBQUU7NEJBQ2hCLG1CQUFtQjs0QkFDbkIseUJBQXlCOzRCQUN6QixRQUFRLEVBQUUsWUFBWTt5QkFDdkI7cUJBQzhCLEVBQ2pDLFlBQVksQ0FDYixDQUFDO29CQUVGLE9BQU8sSUFBSSxDQUFDO2dCQUNkLENBQUM7Z0JBRUQsc0VBQXNFO2dCQUN0RSxnRUFBZ0U7Z0JBQ2hFLHNFQUFzRTtnQkFDdEUsc0VBQXNFO2dCQUN0RSxtQ0FBbUM7Z0JBQ25DLEVBQUU7Z0JBQ0Ysd0VBQXdFO2dCQUN4RSwwREFBMEQ7Z0JBQzFELHNFQUFzRTtnQkFDdEUsK0RBQStEO2dCQUMvRCxpRUFBaUU7Z0JBQ2pFLEVBQUU7Z0JBQ0YscUVBQXFFO2dCQUNyRSxxQkFBcUI7Z0JBQ3JCLEVBQUU7Z0JBQ0YscUVBQXFFO2dCQUNyRSxpRUFBaUU7Z0JBQ2pFLHVFQUF1RTtnQkFDdkUsZ0NBQWdDO2dCQUNoQyxxRUFBcUU7Z0JBQ3JFLG9FQUFvRTtnQkFDcEUsc0VBQXNFO2dCQUN0RSxxRUFBcUU7Z0JBQ3JFLGtFQUFrRTtnQkFDbEUscUVBQXFFO2dCQUNyRSxtRUFBbUU7Z0JBQ25FLG9FQUFvRTtnQkFDcEUsdUVBQXVFO2dCQUN2RSx1RUFBdUU7Z0JBQ3ZFLGlFQUFpRTtnQkFDakUsdUJBQXVCO2dCQUN2QixNQUFNLFFBQVEsR0FBRyxnQkFBZ0IsRUFBRSxDQUFDO2dCQUNwQyxNQUFNLGFBQWEsR0FBRyxNQUFNLDBCQUEwQixDQUNwRCxpQkFBK0IsQ0FDaEMsQ0FBQztnQkFDRixJQUFJLEVBQUUsYUFBYSxDQUFDLEVBQUUseUJBQXlCLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztnQkFFN0QsOERBQThEO2dCQUM5RCxvRUFBb0U7Z0JBQ3BFLG9FQUFvRTtnQkFDcEUsb0NBQW9DO2dCQUNwQyxNQUFNLHlCQUF5QixHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDN0MsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUNmLFNBQVMsRUFDVDtvQkFDRSxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUs7b0JBQ2pCLFlBQVksRUFBRSxhQUFhLENBQUMsWUFBWSxJQUFJLFNBQVM7b0JBQ3JELFNBQVMsRUFBRTt3QkFDVCxRQUFRO3dCQUNSLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTt3QkFDbkIsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLO3dCQUNqQixPQUFPLEVBQUUsaUJBQWlCO3dCQUMxQixhQUFhO3dCQUNiLHlEQUF5RDt3QkFDekQsdURBQXVEO3dCQUN2RCxnREFBZ0Q7d0JBQ2hELFlBQVksRUFBRSxhQUFhLENBQUMsWUFBWTtxQkFDekM7b0JBQ0QsZ0JBQWdCLEVBQUU7d0JBQ2hCLG1CQUFtQjt3QkFDbkIseUJBQXlCO3dCQUN6QixRQUFRLEVBQUUsTUFBTTtxQkFDakI7aUJBQzhCLEVBQ2pDLFlBQVksQ0FDYixDQUFDO2dCQUVGLG9FQUFvRTtnQkFDcEUsb0VBQW9FO2dCQUNwRSxrRUFBa0U7Z0JBQ2xFLE9BQU8sSUFBMEIsQ0FBQztZQUNwQyxDQUFDO1lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztnQkFDYixJQUFJLEVBQUUsYUFBYSxDQUFDO29CQUNsQixHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQ3BCLE9BQU8sV0FBVyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUNsRTtvQkFDRCxHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDO2lCQUM5QixDQUFDLENBQUM7Z0JBQ0gsTUFBTSxHQUFHLENBQUM7WUFDWixDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWtDRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsYUFBYSxDQUNqQyxLQUFhLEVBQ2IsT0FBZ0I7SUFFaEIsMkVBQTJFO0lBQzNFLHlFQUF5RTtJQUN6RSwwRUFBMEU7SUFDMUUsNEVBQTRFO0lBQzVFLDRFQUE0RTtJQUM1RSxNQUFNLG1CQUFtQixHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUN2QyxNQUFNLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxHQUFHLE1BQU0scUJBQXFCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFbkUsd0RBQXdEO0lBQ3hELGlFQUFpRTtJQUNqRSx1RUFBdUU7SUFDdkUsd0RBQXdEO0lBQ3hELElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxLQUFLLEVBQUUsQ0FBQztRQUM3QixNQUFNLElBQUksaUJBQWlCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVELElBQUksUUFBOEIsQ0FBQztJQUNuQyxJQUFJLGdCQUFzRCxDQUFDO0lBQzNELElBQ0UsSUFBSSxDQUFDLFFBQVE7UUFDYixPQUFPLElBQUksQ0FBQyxRQUFRLEtBQUssUUFBUTtRQUNqQyxhQUFhLElBQUksSUFBSSxDQUFDLFFBQVEsRUFDOUIsQ0FBQztRQUNELElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDM0MsTUFBTSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsR0FBRyxJQUFJLGVBQWUsRUFBc0IsQ0FBQztZQUN6RSxnQkFBZ0IsR0FBRyxRQUFRLENBQUM7WUFFNUIsdUVBQXVFO1lBQ3ZFLG1FQUFtRTtZQUNsRSxPQUFlLENBQUMseUJBQXlCLENBQUMsR0FBRyxRQUFRLENBQUM7UUFDekQsQ0FBQzthQUFNLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLFlBQVksUUFBUSxFQUFFLENBQUM7WUFDekQsUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDO1FBQ3ZDLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxJQUFJLG9CQUFvQixDQUM1QixrQ0FBa0MsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsRUFDN0QsRUFBRSxJQUFJLEVBQUUsV0FBVyxDQUFDLGtDQUFrQyxFQUFFLENBQ3pELENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztTQUFNLENBQUM7UUFDTix5RUFBeUU7UUFDekUsUUFBUSxHQUFHLElBQUksUUFBUSxDQUFDLElBQUksRUFBRSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFFRCx3RUFBd0U7SUFDeEUsNkVBQTZFO0lBQzdFLDBFQUEwRTtJQUMxRSxrRUFBa0U7SUFDbEUsOERBQThEO0lBQzlELE1BQU0sY0FBYyxDQUNsQixJQUFJLEVBQ0osT0FBTyxFQUNQLGFBQWEsRUFDYixJQUFJLEVBQ0osbUJBQW1CLEVBQ25CLEtBQUssQ0FDTixDQUFDO0lBRUYsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3JCLGtEQUFrRDtRQUNsRCxpQ0FBaUM7UUFDakMsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDNUMsTUFBTSxLQUFLLEdBQUcsTUFBTSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDbEMsSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDaEIsUUFBUSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7UUFDekIsQ0FBQztRQUNELE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUNsQixDQUFDO0lBRUQsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2QsTUFBTSxJQUFJLG9CQUFvQixDQUFDLHNDQUFzQyxFQUFFO1lBQ3JFLElBQUksRUFBRSxXQUFXLENBQUMseUJBQXlCO1NBQzVDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgRW50aXR5Q29uZmxpY3RFcnJvcixcbiAgRVJST1JfU0xVR1MsXG4gIEhvb2tOb3RGb3VuZEVycm9yLFxuICBSdW5FeHBpcmVkRXJyb3IsXG4gIFdvcmtmbG93UnVudGltZUVycm9yLFxufSBmcm9tICdAd29ya2Zsb3cvZXJyb3JzJztcbmltcG9ydCB7XG4gIEhPT0tfUkVTVU1FX0RFRFVQX1ZFUlNJT04sXG4gIEhPT0tfUkVTVU1FX0lOUFVUX1ZFUlNJT04sXG4gIHR5cGUgSG9vayxcbiAgdHlwZSBIb29rUmVzdW1lQ29udGV4dCxcbiAgaXNMZWdhY3lTcGVjVmVyc2lvbixcbiAgaXNUZXJtaW5hbFdvcmtmbG93UnVuU3RhdHVzLFxuICBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgU1BFQ19WRVJTSU9OX0xFR0FDWSxcbiAgU1BFQ19WRVJTSU9OX1NVUFBPUlRTX0NCT1JfUVVFVUVfVFJBTlNQT1JULFxuICBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ09NUFJFU1NJT04sXG4gIHR5cGUgV29ya2Zsb3dJbnZva2VQYXlsb2FkLFxuICB0eXBlIFdvcmtmbG93UnVuLFxufSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgbW9ub3RvbmljRmFjdG9yeSB9IGZyb20gJ3VsaWQnO1xuaW1wb3J0IHsgZ2V0UnVuQ2FwYWJpbGl0aWVzIH0gZnJvbSAnLi4vY2FwYWJpbGl0aWVzLmpzJztcbmltcG9ydCB7IGltcG9ydEtleSB9IGZyb20gJy4uL2VuY3J5cHRpb24uanMnO1xuaW1wb3J0IHsgcnVudGltZUxvZ2dlciB9IGZyb20gJy4uL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBkZWNvZGVSdW5QdWJsaWNLZXkgfSBmcm9tICcuLi9zZWFsZWQtYm94LmpzJztcbmltcG9ydCB7IGRlcml2ZVJ1blBheWxvYWRLZXlzIH0gZnJvbSAnLi4vc2VyaWFsaXphdGlvbi9lbmNyeXB0aW9uLmpzJztcbmltcG9ydCB7XG4gIGRlaHlkcmF0ZVN0ZXBSZXR1cm5WYWx1ZSxcbiAgaHlkcmF0ZVN0ZXBBcmd1bWVudHMsXG4gIHR5cGUgUGF5bG9hZEtleSxcbiAgU2VyaWFsaXphdGlvbkZvcm1hdCxcbiAgc2VhbFRvLFxufSBmcm9tICcuLi9zZXJpYWxpemF0aW9uLmpzJztcbmltcG9ydCB7IFdFQkhPT0tfUkVTUE9OU0VfV1JJVEFCTEUgfSBmcm9tICcuLi9zeW1ib2xzLmpzJztcbmltcG9ydCAqIGFzIEF0dHJpYnV0ZSBmcm9tICcuLi90ZWxlbWV0cnkvc2VtYW50aWMtY29udmVudGlvbnMuanMnO1xuaW1wb3J0IHsgbGlua1RvVHJhY2VDYXJyaWVyLCB0cmFjZSB9IGZyb20gJy4uL3RlbGVtZXRyeS5qcyc7XG5pbXBvcnQgeyBnZXRXb3JsZExhenkgfSBmcm9tICcuL2dldC13b3JsZC1sYXp5LmpzJztcbmltcG9ydCB7IGdldFdvcmtmbG93UXVldWVOYW1lIH0gZnJvbSAnLi9oZWxwZXJzLmpzJztcbmltcG9ydCB7IHNhZmVXYWl0VW50aWwsIHdhaXRlZFVudGlsIH0gZnJvbSAnLi93YWl0LXVudGlsLmpzJztcblxuLyoqIE1vbm90b25pYyBVTElEIGZhY3RvcnkgZm9yIHBlci1jYWxsIHJlc3VtZSBpZGVtcG90ZW5jeSBrZXlzLiAqL1xuY29uc3QgZ2VuZXJhdGVSZXN1bWVJZCA9IG1vbm90b25pY0ZhY3RvcnkoKTtcblxuLyoqXG4gKiBVcHBlciBib3VuZCBvbiB0aGUgc2VyaWFsaXplZCBob29rIHBheWxvYWQgdGhhdCB0aGUgbGF6eSBwYXRoIHdpbGwgaW5saW5lXG4gKiBpbnRvIHRoZSBxdWV1ZSBtZXNzYWdlJ3MgYGhvb2tJbnB1dGAuIFZlcmNlbCBRdWV1ZXMgY2FwcyBhIHNpbmdsZSBtZXNzYWdlIGF0XG4gKiB+MjU2IEtpQiwgYW5kIHRoZSBtZXNzYWdlIGFsc28gY2FycmllcyB0aGUgcnVuSWQsIGhvb2tJZCwgdG9rZW4sIHJlc3VtZUlkLFxuICogZGlnZXN0LCBhbmQgdHJhY2UgY2FycmllciBhbG9uZ3NpZGUgQ0JPUiBmcmFtaW5nIG92ZXJoZWFkLiBTdGF5aW5nIHdlbGwgdW5kZXJcbiAqIHRoYXQgY2VpbGluZyBrZWVwcyB0aGUgcXVldWUgcHVibGlzaCBmcm9tIHJlamVjdGluZyBhbiBvdmVyc2l6ZWQgbWVzc2FnZSxcbiAqIHdoaWNoIG9uIHRoZSBsYXp5IHBhdGggd291bGQgZHJvcCB0aGUgcmVzdW1lIGVudGlyZWx5OiB0aGUgbWVzc2FnZSBpcyB0aGVcbiAqIG9ubHkgY29weSBvZiB0aGUgcGF5bG9hZC4gQWJvdmUgdGhpcyBzaXplIHdlIGZhbGwgYmFjayB0byB0aGUgc2VxdWVudGlhbFxuICogcGF0aCwgd2hvc2UgcXVldWUgbWVzc2FnZSBjYXJyaWVzIG9ubHkgdGhlIHJ1biBJRCAodGhlIHBheWxvYWQgbGl2ZXMgaW4gdGhlXG4gKiBldmVudCBsb2cpLlxuICovXG5jb25zdCBNQVhfSU5MSU5FX1JFU1VNRV9QQVlMT0FEX0JZVEVTID0gMTI4ICogMTAyNDtcblxuLyoqXG4gKiBIZXggU0hBLTI1NiBvZiB0aGUgc2VyaWFsaXplZCByZXN1bWUgcGF5bG9hZCBieXRlcy4gQ29tcHV0ZWQgb25jZSBieSB0aGVcbiAqIHByb2R1Y2VyIGFuZCBjYXJyaWVkIG9uIHRoZSBxdWV1ZSBtZXNzYWdlJ3MgYGhvb2tJbnB1dGAsIHNvIGV2ZXJ5IGRlbGl2ZXJ5IG9mXG4gKiB0aGF0IG1lc3NhZ2UgcmVjb3JkcyBhbiBpZGVudGljYWwgZGlnZXN0IGFnYWluc3QgdGhlIHNlcnZlcidzXG4gKiBgKHJ1bklkLCByZXN1bWVJZClgIGNvbnN0cmFpbnQgYW5kIHJlZGVsaXZlcmllcyBjb252ZXJnZSBvbiB0aGUgb25lIGNvbW1pdHRlZFxuICogYGhvb2tfcmVjZWl2ZWRgLiBIYXNoaW5nIHRoZSBhbHJlYWR5LXNlcmlhbGl6ZWQgYnl0ZXMgKG5vdCB0aGUgcmF3IHZhbHVlKVxuICoga2VlcHMgdGhlIGRpZ2VzdCBzdGFibGUgYWNyb3NzIGRlbGl2ZXJpZXM6IHRoZSBjb25zdW1lciBmb3J3YXJkcyB0aGlzIHN0cmluZ1xuICogd2l0aG91dCByZWNvbXB1dGluZy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gY29tcHV0ZVJlc3VtZVBheWxvYWREaWdlc3QoYnl0ZXM6IFVpbnQ4QXJyYXkpOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBkaWdlc3QgPSBhd2FpdCBjcnlwdG8uc3VidGxlLmRpZ2VzdCgnU0hBLTI1NicsIGJ5dGVzKTtcbiAgY29uc3QgdmlldyA9IG5ldyBVaW50OEFycmF5KGRpZ2VzdCk7XG4gIGxldCBoZXggPSAnJztcbiAgZm9yIChjb25zdCBiIG9mIHZpZXcpIHtcbiAgICBoZXggKz0gYi50b1N0cmluZygxNikucGFkU3RhcnQoMiwgJzAnKTtcbiAgfVxuICByZXR1cm4gaGV4O1xufVxuXG4vKipcbiAqIFRoZSByZXN1bWUgY29udGV4dCBmb3IgYSBob29rIHBsdXMgd2hlcmUgaXQgY2FtZSBmcm9tLiBgcnVuYCBpcyBwcmVzZW50IG9ubHlcbiAqIG9uIHRoZSBmYWxsYmFjayBwYXRoIChwcmUtYHJlc3VtZUNvbnRleHRgIGhvb2tzKSwgd2hlcmUgaXQgYWxzbyBjYXJyaWVzIHRoZVxuICogcnVuJ3MgbXV0YWJsZSBzdGF0dXMgZm9yIHRoZSB0ZXJtaW5hbC1ydW4gY2hlY2suIEtleSByZXNvbHV0aW9uIGlzIGtlcHRcbiAqIHNlcGFyYXRlIHNvIGNhbGxlcnMgY2FuIGdhdGUgaXQgYmVoaW5kIHRoYXQgY2hlY2suXG4gKi9cbmludGVyZmFjZSBIb29rUmVzdW1lSW5mbyB7XG4gIHJlc3VtZUNvbnRleHQ6IEhvb2tSZXN1bWVDb250ZXh0O1xuICBzb3VyY2U6ICdob29rJyB8ICdydW5fZmFsbGJhY2snO1xuICBydW4/OiBXb3JrZmxvd1J1bjtcbn1cblxuLyoqIERlcml2ZSBhIHJlc3VtZSBjb250ZXh0IGZyb20gYSBmdWxsIHJ1biAoZmFsbGJhY2sgZm9yIHByZS1gcmVzdW1lQ29udGV4dGAgaG9va3MpLiAqL1xuZnVuY3Rpb24gcmVzdW1lQ29udGV4dEZyb21SdW4ocnVuOiBXb3JrZmxvd1J1bik6IEhvb2tSZXN1bWVDb250ZXh0IHtcbiAgY29uc3QgY29yZVZlcnNpb24gPSBydW4uZXhlY3V0aW9uQ29udGV4dD8ud29ya2Zsb3dDb3JlVmVyc2lvbjtcbiAgY29uc3QgdHJhY2VDYXJyaWVyID0gcnVuLmV4ZWN1dGlvbkNvbnRleHQ/LnRyYWNlQ2FycmllcjtcbiAgY29uc3QgaG9va1Jlc3VtZUlucHV0VmVyc2lvbiA9IHJ1bi5leGVjdXRpb25Db250ZXh0Py5ob29rUmVzdW1lSW5wdXRWZXJzaW9uO1xuICByZXR1cm4ge1xuICAgIGRlcGxveW1lbnRJZDogcnVuLmRlcGxveW1lbnRJZCxcbiAgICB3b3JrZmxvd05hbWU6IHJ1bi53b3JrZmxvd05hbWUsXG4gICAgcnVuU3BlY1ZlcnNpb246IHJ1bi5zcGVjVmVyc2lvbixcbiAgICB3b3JrZmxvd0NvcmVWZXJzaW9uOlxuICAgICAgdHlwZW9mIGNvcmVWZXJzaW9uID09PSAnc3RyaW5nJyA/IGNvcmVWZXJzaW9uIDogdW5kZWZpbmVkLFxuICAgIHRyYWNlQ2FycmllcjpcbiAgICAgIHRyYWNlQ2FycmllciAmJiB0eXBlb2YgdHJhY2VDYXJyaWVyID09PSAnb2JqZWN0J1xuICAgICAgICA/ICh0cmFjZUNhcnJpZXIgYXMgSG9va1Jlc3VtZUNvbnRleHRbJ3RyYWNlQ2FycmllciddKVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICBlbmNyeXB0aW9uUHVibGljS2V5OiBydW4uZW5jcnlwdGlvblB1YmxpY0tleSxcbiAgICBob29rUmVzdW1lSW5wdXRWZXJzaW9uOlxuICAgICAgdHlwZW9mIGhvb2tSZXN1bWVJbnB1dFZlcnNpb24gPT09ICdudW1iZXInXG4gICAgICAgID8gaG9va1Jlc3VtZUlucHV0VmVyc2lvblxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgfTtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHJlc3VtZSBjb250ZXh0IGZvciBhIGhvb2suIFVzZXMgdGhlIHN0b3JlZCBgcmVzdW1lQ29udGV4dGAgd2hlblxuICogcHJlc2VudCAoZmFzdCBwYXRoLCBubyBydW4gcmVhZCk7IG90aGVyd2lzZSBmZXRjaGVzIHRoZSBydW4gYW5kIHN5bnRoZXNpemVzXG4gKiBpdC4gRG9lcyBOT1QgcmVzb2x2ZSB0aGUgZW5jcnlwdGlvbiBrZXk7IGNhbGxlcnMgZG8gdGhhdCBzZXBhcmF0ZWx5LiBPbmx5XG4gKiB0aGUgZmFsbGJhY2sgcGF0aCBjYW4gZ2F0ZSBrZXkgd29yayBiZWhpbmQgYSBsb2NhbCB0ZXJtaW5hbC1ydW4gY2hlY2sgKGl0XG4gKiBoYXMgdGhlIGZldGNoZWQgcnVuKTsgdGhlIGZhc3QgcGF0aCdzIHN0b3JlZCBjb250ZXh0IGNhcnJpZXMgbm8gc3RhdHVzLCBzb1xuICogc2VhbC9zZXJpYWxpemF0aW9uIHdvcmsgbWF5IHJ1biBiZWZvcmUgdGhlIHJlY2VpdmluZyBzaWRlIHJlamVjdHNcbiAqIGBob29rX3JlY2VpdmVkYCBmb3IgYW4gZW5kZWQgcnVuLlxuICovXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlSG9va1Jlc3VtZUluZm8oaG9vazogSG9vayk6IFByb21pc2U8SG9va1Jlc3VtZUluZm8+IHtcbiAgaWYgKGhvb2sucmVzdW1lQ29udGV4dCkge1xuICAgIHJldHVybiB7IHJlc3VtZUNvbnRleHQ6IGhvb2sucmVzdW1lQ29udGV4dCwgc291cmNlOiAnaG9vaycgfTtcbiAgfVxuICBjb25zdCBydW4gPSBhd2FpdCAoYXdhaXQgZ2V0V29ybGRMYXp5KCkpLnJ1bnMuZ2V0KGhvb2sucnVuSWQpO1xuICByZXR1cm4ge1xuICAgIHJlc3VtZUNvbnRleHQ6IHJlc3VtZUNvbnRleHRGcm9tUnVuKHJ1biksXG4gICAgc291cmNlOiAncnVuX2ZhbGxiYWNrJyxcbiAgICBydW4sXG4gIH07XG59XG5cbi8qKlxuICogUmVzb2x2ZSB0aGUgcnVuJ3Mgc3ltbWV0cmljIGtleSBmb3IgYSBwYXlsb2FkIFdSSVRFLCBhcyBhIGJhcmUgYENyeXB0b0tleWBcbiAqIChgaW1wb3J0S2V5YCk6IHRoZSBgZW5jcmAgd3JpdGUgZmFsbGJhY2sgdXNlZCB3aGVuIHRoZSBydW4gcHVibGlzaGVkIG5vXG4gKiBwdWJsaWMga2V5IHRvIHNlYWwgdG8uIFdyaXRpbmcgbmVlZHMgb25seSB0aGUgQUVTIGtleSwgbm90IHRoZSByZWFkLXNpZGVcbiAqIGtleXBhaXIuIE9uIHRoZSBmYXN0IHBhdGggdGhpcyBuZWVkcyBvbmx5IGBydW5JZGAgKyBgZGVwbG95bWVudElkYCAobm8gcnVuXG4gKiBlbnRpdHkpOyBvbiB0aGUgZmFsbGJhY2sgcGF0aCB0aGUgYWxyZWFkeSBmZXRjaGVkIHJ1biBpcyByZXVzZWQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVIb29rRW5jcnlwdGlvbktleShcbiAgaG9vazogSG9vayxcbiAgaW5mbzogSG9va1Jlc3VtZUluZm9cbik6IFByb21pc2U8QXdhaXRlZDxSZXR1cm5UeXBlPHR5cGVvZiBpbXBvcnRLZXk+PiB8IHVuZGVmaW5lZD4ge1xuICBjb25zdCB3b3JsZCA9IGF3YWl0IGdldFdvcmxkTGF6eSgpO1xuICBjb25zdCByYXdLZXkgPSBpbmZvLnJ1blxuICAgID8gYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKGluZm8ucnVuKVxuICAgIDogYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKGhvb2sucnVuSWQsIHtcbiAgICAgICAgZGVwbG95bWVudElkOiBpbmZvLnJlc3VtZUNvbnRleHQuZGVwbG95bWVudElkLFxuICAgICAgfSk7XG4gIHJldHVybiByYXdLZXkgPyBhd2FpdCBpbXBvcnRLZXkocmF3S2V5KSA6IHVuZGVmaW5lZDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0SG9va0J5VG9rZW5XaXRoS2V5KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPHtcbiAgaG9vazogSG9vaztcbiAgZW5jcnlwdGlvbktleTogUGF5bG9hZEtleSB8IHVuZGVmaW5lZDtcbn0+IHtcbiAgY29uc3Qgd29ybGQgPSBhd2FpdCBnZXRXb3JsZExhenkoKTtcbiAgY29uc3QgaG9vayA9IGF3YWl0IHdvcmxkLmhvb2tzLmdldEJ5VG9rZW4odG9rZW4pO1xuXG4gIC8vIE9ubHkgYSBob29rIHRoYXQgYWN0dWFsbHkgY2FycmllcyBtZXRhZGF0YSBuZWVkcyB0aGUgcnVuJ3Mga2V5IHJlc29sdmVkXG4gIC8vIGhlcmU6IGh5ZHJhdGluZyB0aGF0IG1ldGFkYXRhIGlzIGEgUkVBRCwgc28gZGVyaXZlIHRoZSBmdWxsIFJ1blBheWxvYWRLZXlzXG4gIC8vICh3aGljaCBvcGVucyBzZWFsZWQgYGVuY3BgIG1ldGFkYXRhLCBub3QganVzdCBzeW1tZXRyaWMgYGVuY3JgKS4gVGhlIGNvbW1vblxuICAvLyBkZWZhdWx0IHdlYmhvb2sgKGNyZWF0ZVdlYmhvb2soKSB3aXRoIG5vIGByZXNwb25kV2l0aGApIHN0b3JlcyBub1xuICAvLyBtZXRhZGF0YSwgc28gaXQgc2tpcHMgdGhpcyBlbnRpcmVseTogbm8gfjM1MG1zIGBydW4ta2V5YCBBUEkgcm91bmQgdHJpcCxcbiAgLy8gYW5kLCBjcnVjaWFsbHksIG5vIHJlc29sdmVkIGtleSBoYW5kZWQgdG8gYHJlc3VtZUhvb2tgLCBsZWF2aW5nIGl0IGZyZWUgdG9cbiAgLy8gc2VhbCB0aGUgcGF5bG9hZCB0byB0aGUgcnVuJ3MgcHVibGlzaGVkIHB1YmxpYyBrZXkgaW5zdGVhZC4gTWV0YWRhdGEtXG4gIC8vIGJlYXJpbmcgd2ViaG9va3Mgc3RpbGwgbGVnaXRpbWF0ZWx5IHBheSBvbmUgbG9va3VwIHRvIGh5ZHJhdGUuXG4gIGxldCBlbmNyeXB0aW9uS2V5OiBQYXlsb2FkS2V5IHwgdW5kZWZpbmVkO1xuICBpZiAodHlwZW9mIGhvb2subWV0YWRhdGEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgY29uc3QgaW5mbyA9IGF3YWl0IHJlc29sdmVIb29rUmVzdW1lSW5mbyhob29rKTtcbiAgICAvLyBPbiB0aGUgZmFzdCBwYXRoIHRoaXMgcmVzb2x2ZXMgdGhlIGtleSBieSBydW5JZCArIGRlcGxveW1lbnRJZCAobm8gcnVuXG4gICAgLy8gcmVhZCk7IG9uIHRoZSBmYWxsYmFjayBwYXRoIGl0IHJldXNlcyB0aGUgYWxyZWFkeS1mZXRjaGVkIHJ1bi5cbiAgICBjb25zdCByYXdLZXkgPSBpbmZvLnJ1blxuICAgICAgPyBhd2FpdCB3b3JsZC5nZXRFbmNyeXB0aW9uS2V5Rm9yUnVuPy4oaW5mby5ydW4pXG4gICAgICA6IGF3YWl0IHdvcmxkLmdldEVuY3J5cHRpb25LZXlGb3JSdW4/Lihob29rLnJ1bklkLCB7XG4gICAgICAgICAgZGVwbG95bWVudElkOiBpbmZvLnJlc3VtZUNvbnRleHQuZGVwbG95bWVudElkLFxuICAgICAgICB9KTtcbiAgICBlbmNyeXB0aW9uS2V5ID0gcmF3S2V5ID8gYXdhaXQgZGVyaXZlUnVuUGF5bG9hZEtleXMocmF3S2V5KSA6IHVuZGVmaW5lZDtcbiAgICBob29rLm1ldGFkYXRhID0gYXdhaXQgaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gICAgICBob29rLm1ldGFkYXRhIGFzIGFueSxcbiAgICAgIGhvb2sucnVuSWQsXG4gICAgICBlbmNyeXB0aW9uS2V5XG4gICAgKTtcbiAgfVxuICByZXR1cm4geyBob29rLCBlbmNyeXB0aW9uS2V5IH07XG59XG5cbi8qKlxuICogR2V0IHRoZSBob29rIGJ5IHRva2VuIHRvIGZpbmQgdGhlIGFzc29jaWF0ZWQgd29ya2Zsb3cgcnVuLFxuICogYW5kIGh5ZHJhdGUgdGhlIGBtZXRhZGF0YWAgcHJvcGVydHkgaWYgaXQgd2FzIHNldCBmcm9tIHdpdGhpblxuICogdGhlIHdvcmtmbG93IHJ1bi5cbiAqXG4gKiBBIEhvb2sga2VwdCBieSBtaW5pbXVtIHJldGVudGlvbiByZW1haW5zIGF2YWlsYWJsZSBoZXJlIGFmdGVyIGl0cyBydW4gZW5kcyxcbiAqIGJ1dCBjYW5ub3QgYmUgcmVzdW1lZC5cbiAqXG4gKiBAcGFyYW0gdG9rZW4gLSBUaGUgdW5pcXVlIHRva2VuIGlkZW50aWZ5aW5nIHRoZSBob29rXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIb29rQnlUb2tlbih0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxIb29rPiB7XG4gIGNvbnN0IHsgaG9vayB9ID0gYXdhaXQgZ2V0SG9va0J5VG9rZW5XaXRoS2V5KHRva2VuKTtcbiAgcmV0dXJuIGhvb2s7XG59XG5cbi8qKlxuICogVGhlIHJlc3VsdCBvZiB7QGxpbmsgcmVzdW1lSG9va306IGEge0BsaW5rIEhvb2t9IGF1Z21lbnRlZCB3aXRoIGFuIG9wdGlvbmFsXG4gKiByZXNpbGllbmNlIHNpZ25hbC5cbiAqXG4gKiBgcmVzaWxpZW50UmVzdW1lYCBpcyByZXRhaW5lZCBmb3Igc291cmNlIGNvbXBhdGliaWxpdHkgYW5kIGlzIG5ldmVyIHNldC4gSXRcbiAqIHNpZ25hbGxlZCBhIHJlc3VtZSB3aG9zZSBkaXJlY3QgYGhvb2tfcmVjZWl2ZWRgIHdyaXRlIGhhZCBmYWlsZWQgd2hpbGUgdGhlXG4gKiBxdWV1ZSBkaXNwYXRjaCBzdWNjZWVkZWQsIGJhY2sgd2hlbiB0aGUgbGF6eSBwYXRoIHJhY2VkIHRoZSB0d28uIFRoZSBsYXp5XG4gKiBwYXRoIG5vIGxvbmdlciB3cml0ZXMgdGhlIGV2ZW50IGF0IGFsbCAodGhlIHF1ZXVlIGNvbnN1bWVyIG1hdGVyaWFsaXplcyBpdFxuICogZnJvbSBgaG9va0lucHV0YCksIHNvIHRoZXJlIGlzIG5vIGxvbmdlciBhIGRpc3RpbmN0aW9uIHRvIHJlcG9ydCwgYW5kIHRoZVxuICogc2VxdWVudGlhbCBwYXRoIG5ldmVyIHNldCB0aGUgZmxhZyBlaXRoZXIuIFRyZWF0IHRoZSByZXN1bHQgYXMgYSBwbGFpblxuICoge0BsaW5rIEhvb2t9LlxuICovXG5leHBvcnQgdHlwZSBSZXN1bWVkSG9vayA9IEhvb2sgJiB7IHJlc2lsaWVudFJlc3VtZT86IGJvb2xlYW4gfTtcblxuLyoqXG4gKiBSZXN1bWVzIGEgd29ya2Zsb3cgcnVuIGJ5IHNlbmRpbmcgYSBwYXlsb2FkIHRvIGEgaG9vayBpZGVudGlmaWVkIGJ5IGl0cyB0b2tlbi5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBleHRlcm5hbGx5IChlLmcuLCBmcm9tIGFuIEFQSSByb3V0ZSBvciBzZXJ2ZXIgYWN0aW9uKVxuICogdG8gc2VuZCBkYXRhIHRvIGEgaG9vayBhbmQgcmVzdW1lIHRoZSBhc3NvY2lhdGVkIHdvcmtmbG93IHJ1bi5cbiAqXG4gKiBAcGFyYW0gdG9rZW5Pckhvb2sgLSBUaGUgdW5pcXVlIHRva2VuIGlkZW50aWZ5aW5nIHRoZSBob29rLCBvciB0aGUgaG9vayBvYmplY3QgaXRzZWxmXG4gKiBAcGFyYW0gcGF5bG9hZCAtIFRoZSBkYXRhIHBheWxvYWQgdG8gc2VuZCB0byB0aGUgaG9va1xuICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHtAbGluayBSZXN1bWVkSG9va31cbiAqIEB0aHJvd3Mge0hvb2tOb3RGb3VuZEVycm9yfSBJZiB0aGUgSG9vayBkb2VzIG5vdCBleGlzdCBvciBpdHMgcnVuIGhhcyBlbmRlZFxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogYGBgdHNcbiAqIC8vIEluIGFuIEFQSSByb3V0ZVxuICogaW1wb3J0IHsgcmVzdW1lSG9vayB9IGZyb20gJ0B3b3JrZmxvdy9jb3JlL3J1bnRpbWUnO1xuICpcbiAqIGV4cG9ydCBhc3luYyBmdW5jdGlvbiBQT1NUKHJlcXVlc3Q6IFJlcXVlc3QpIHtcbiAqICAgY29uc3QgeyB0b2tlbiwgZGF0YSB9ID0gYXdhaXQgcmVxdWVzdC5qc29uKCk7XG4gKlxuICogICB0cnkge1xuICogICAgIGNvbnN0IGhvb2sgPSBhd2FpdCByZXN1bWVIb29rKHRva2VuLCBkYXRhKTtcbiAqICAgICByZXR1cm4gUmVzcG9uc2UuanNvbih7IHJ1bklkOiBob29rLnJ1bklkIH0pO1xuICogICB9IGNhdGNoIChlcnJvcikge1xuICogICAgIHJldHVybiBuZXcgUmVzcG9uc2UoJ0hvb2sgbm90IGZvdW5kJywgeyBzdGF0dXM6IDQwNCB9KTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXN1bWVIb29rPFQgPSBhbnk+KFxuICB0b2tlbk9ySG9vazogc3RyaW5nIHwgSG9vayxcbiAgcGF5bG9hZDogVCxcbiAgZW5jcnlwdGlvbktleU92ZXJyaWRlPzogUGF5bG9hZEtleVxuKTogUHJvbWlzZTxSZXN1bWVkSG9vaz4ge1xuICAvLyBQdWJsaWMgZW50cnkgcG9pbnQuIEl0IG5ldmVyIGF0dGVzdHMgaG9vayBmcmVzaG5lc3MsIHNvIGEgSG9vayBvYmplY3RcbiAgLy8gc3VwcGxpZWQgaGVyZSAod2hpY2ggbWF5IGNhcnJ5IGEgYHJlc3VtZUNhcGFiaWxpdGllc2AgY2FjaGVkIGJlZm9yZSBhXG4gIC8vIHNlcnZlciByb2xsYmFjayBvciBraWxsIHN3aXRjaCkgaXMgaWdub3JlZCBieSB0aGUgZHluYW1pYy1kZWR1cCBnYXRlIGFuZFxuICAvLyBmYWlscyBjbG9zZWQgdG8gdGhlIHNlcXVlbnRpYWwgcGF0aC4gT25seSBgcmVzdW1lV2ViaG9va2AsIHdoaWNoIGZldGNoZXNcbiAgLy8gdGhlIGhvb2sgYnkgdG9rZW4gaW4tbGluZSBkdXJpbmcgdGhlIHNhbWUgcmVzdW1lLCByZWFjaGVzIHRoZSBpbnRlcm5hbFxuICAvLyBpbXBsZW1lbnRhdGlvbiB3aXRoIHRoZSBmcmVzaCBhdHRlc3RhdGlvbiBzZXQuIEtlZXBpbmcgdGhlIGZyZXNobmVzcyBmbGFnXG4gIC8vIG9mZiB0aGUgZXhwb3J0ZWQgc2lnbmF0dXJlIHByZXZlbnRzIGEgY2FsbGVyIGZyb20gcGFzc2luZyBhIHN0YWxlIEhvb2sgcGx1c1xuICAvLyBgdHJ1ZWAgYW5kIHJlYWN0aXZhdGluZyBkeW5hbWljIGRlZHVwIGFnYWluc3QgYSByb2xsZWQtYmFjayBiYWNrZW5kLlxuICAvL1xuICAvLyBUMCBvZiB0aGUgaG9vay1yZXN1bWUgVFRSIHdpbmRvdyBpcyB0YWtlbiBIRVJFLCBhdCB0aGUgcHVibGljIGVudHJ5IHBvaW50LFxuICAvLyByYXRoZXIgdGhhbiBpbnNpZGUgdGhlIGltcGxlbWVudGF0aW9uOyBzZWUgdGhlIHBhcmFtZXRlcidzIGRvYyBjb21tZW50LlxuICByZXR1cm4gcmVzdW1lSG9va0ltcGwoXG4gICAgdG9rZW5Pckhvb2ssXG4gICAgcGF5bG9hZCxcbiAgICBlbmNyeXB0aW9uS2V5T3ZlcnJpZGUsXG4gICAgZmFsc2UsXG4gICAgRGF0ZS5ub3coKSxcbiAgICBmYWxzZVxuICApO1xufVxuXG4vKipcbiAqIHtAbGluayByZXN1bWVIb29rfSB3aXRoIHRoZSBgaG9va19yZWNlaXZlZGAgZXZlbnQgd3JpdHRlbiBCRUZPUkUgdGhpc1xuICogcmVzb2x2ZXMsIGZvciB0aGUgb25lIGNhbGxlciB0aGF0IG5lZWRzIHRoZSByZXN1bWUgdG8gYmUgZHVyYWJsZSBhdCB0aGF0XG4gKiBpbnN0YW50IHJhdGhlciB0aGFuIG1lcmVseSBkaXNwYXRjaGVkLlxuICpcbiAqIFRoZSBsYXp5IHBhdGggbGVhdmVzIHRoZSB3cml0ZSB0byB0aGUgcXVldWUgY29uc3VtZXIsIHNvIGEgbm9ybWFsXG4gKiBgcmVzdW1lSG9vaygpYCByZXNvbHZlcyB3aGlsZSB0aGUgZXZlbnQgaXMgc3RpbGwgaW4gZmxpZ2h0LiBUaGF0IGlzIGZpbmUgZm9yXG4gKiBhbiBleHRlcm5hbCByZXN1bWUsIHdob3NlIGNhbGxlciBoYXMgbm90aGluZyByYWNpbmcgaXQuIEl0IGlzIE5PVCBmaW5lIGZvciBhXG4gKiByZXN1bWUgdGhlIHJ1bnRpbWUgaXRzZWxmIGlzc3VlcyBhcyBhIGJhcnJpZXI6IGEgc3RlcCB0aGF0IGFib3J0cyBhIHNoYXJlZFxuICogYEFib3J0Q29udHJvbGxlcmAgcmVzdW1lcyB0aGUgaG9vayB0aGF0IHJlY29yZHMgdGhlIGFib3J0IGluIHRoZSBldmVudCBsb2csXG4gKiBhbmQgdGhhdCB3cml0ZSBoYXMgdG8gbGFuZCBiZWZvcmUgdGhlIHN0ZXAgY29tcGxldGVzLCBvciB0aGUgd29ya2Zsb3dcbiAqIGNvbnRpbnVhdGlvbiBgc3RlcF9jb21wbGV0ZWRgIGVucXVldWVzIGNhbiBkaXNwYXRjaCB0aGUgbmV4dCBzdGVwIHdpdGggYVxuICogc3RhbGUsIG5vbi1hYm9ydGVkIHNpZ25hbCAoc2VlIGByZXZpdmVBYm9ydENvbnRyb2xsZXJgIGluIHNlcmlhbGl6YXRpb24udHMpLlxuICpcbiAqIEZvcmNpbmcgdGhlIGVhZ2VyIHdyaXRlIGNvc3RzIHRoZSByb3VuZCB0cmlwIHRoZSBsYXp5IHBhdGggcmVtb3Zlcywgd2hpY2ggaXNcbiAqIHRoZSByaWdodCB0cmFkZSBoZXJlOiB0aGlzIGlzIGFuIGludGVybmFsIG9yZGVyaW5nIGJhcnJpZXIsIG5vdCB0aGVcbiAqIGxhdGVuY3ktc2Vuc2l0aXZlIGV4dGVybmFsIHJlc3VtZSB0aGUgb3B0aW1pemF0aW9uIHRhcmdldHMuIFRoZSByZXN1bWUgc3BhblxuICogcmVwb3J0cyBgcmVzdW1lX2ZhbGxiYWNrX3JlYXNvbjogZHVyYWJsZV9yZXF1aXJlZGAuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXN1bWVIb29rRHVyYWJsZTxUID0gYW55PihcbiAgdG9rZW5Pckhvb2s6IHN0cmluZyB8IEhvb2ssXG4gIHBheWxvYWQ6IFQsXG4gIGVuY3J5cHRpb25LZXlPdmVycmlkZT86IFBheWxvYWRLZXlcbik6IFByb21pc2U8UmVzdW1lZEhvb2s+IHtcbiAgcmV0dXJuIHJlc3VtZUhvb2tJbXBsKFxuICAgIHRva2VuT3JIb29rLFxuICAgIHBheWxvYWQsXG4gICAgZW5jcnlwdGlvbktleU92ZXJyaWRlLFxuICAgIGZhbHNlLFxuICAgIERhdGUubm93KCksXG4gICAgdHJ1ZVxuICApO1xufVxuXG4vKipcbiAqIEludGVybmFsIGltcGxlbWVudGF0aW9uIG9mIHtAbGluayByZXN1bWVIb29rfS4gTk9UIGV4cG9ydGVkOiB0aGVcbiAqIGBob29rRnJlc2hseUxvb2tlZFVwYCBhdHRlc3RhdGlvbiBtdXN0IG5ldmVyIGJlIHJlYWNoYWJsZSBieSBwdWJsaWMgY2FsbGVyc1xuICogKHNlZSB0aGUgd3JhcHBlciBhYm92ZSkuXG4gKlxuICogQHBhcmFtIGhvb2tGcmVzaGx5TG9va2VkVXAgLSBBdHRlc3RzIHRoYXQgYSBzdXBwbGllZCBIb29rIG9iamVjdCB3YXMgZmV0Y2hlZFxuICogICBieSB0b2tlbiBkdXJpbmcgVEhJUyByZXN1bWUsIHNvIGl0cyByZXNwb25zZS1vbmx5IGByZXN1bWVDYXBhYmlsaXRpZXNgXG4gKiAgIHJlZmxlY3RzIHRoZSBsaXZlIGJhY2tlbmQgYW5kIG1heSBiZSB0cnVzdGVkIGZvciB0aGUgZHluYW1pYy1kZWR1cCBnYXRlLlxuICogICBBIHRva2VuIHN0cmluZyBpcyBhbHdheXMgZmV0Y2hlZCBmcmVzaCBoZXJlLCBzbyBpdCBpcyBpbXBsaWNpdGx5IGZyZXNoLlxuICogQHBhcmFtIHJlc3VtZVJlcXVlc3RlZEF0TXMgLSBUMCBvZiB0aGUgaG9vay1yZXN1bWUgVFRSIHdpbmRvdyAoc2VlXG4gKiAgIHJ1bnRpbWUvcmVzdW1lLWxhdGVuY3kudHMpLCBzdGFtcGVkIGJ5IHRoZSBQVUJMSUMgZW50cnkgcG9pbnQgdGhlIGNhbGxlclxuICogICB1c2VkLiBJdCBpcyBhIHBhcmFtZXRlciByYXRoZXIgdGhhbiBhIGxvY2FsIGJlY2F1c2UgYHJlc3VtZVdlYmhvb2tgIGRvZXNcbiAqICAgcmVhbCB3b3JrIGJlZm9yZSBpdCBnZXRzIGhlcmUgKHRoZSBieS10b2tlbiBsb29rdXAsIHRoZSBydW4ta2V5XG4gKiAgIHJlc29sdXRpb24gdGhhdCBoeWRyYXRlcyBob29rIG1ldGFkYXRhLCBhbmQgdGhlIGByZXNwb25kV2l0aGAgc2V0dXApIGFuZFxuICogICBzdGFtcGluZyBsb2NhbGx5IHdvdWxkIHNpbGVudGx5IGV4Y2x1ZGUgYWxsIG9mIGl0LCBzbyB0aGUgdHdvIGVudHJ5IHBvaW50c1xuICogICB3b3VsZCByZXBvcnQgdGhlIHNhbWUgbWV0cmljIG92ZXIgZGlmZmVyZW50IHdpbmRvd3MuXG4gKiBAcGFyYW0gcmVxdWlyZUR1cmFibGVXcml0ZSAtIEZvcmNlIHRoZSBzZXF1ZW50aWFsIHBhdGggc28gYGhvb2tfcmVjZWl2ZWRgIGlzXG4gKiAgIGNvbW1pdHRlZCBiZWZvcmUgdGhpcyByZXNvbHZlcy4gU2VlIHtAbGluayByZXN1bWVIb29rRHVyYWJsZX0uXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlc3VtZUhvb2tJbXBsPFQgPSBhbnk+KFxuICB0b2tlbk9ySG9vazogc3RyaW5nIHwgSG9vayxcbiAgcGF5bG9hZDogVCxcbiAgZW5jcnlwdGlvbktleU92ZXJyaWRlOiBQYXlsb2FkS2V5IHwgdW5kZWZpbmVkLFxuICBob29rRnJlc2hseUxvb2tlZFVwOiBib29sZWFuLFxuICByZXN1bWVSZXF1ZXN0ZWRBdE1zOiBudW1iZXIsXG4gIHJlcXVpcmVEdXJhYmxlV3JpdGU6IGJvb2xlYW5cbik6IFByb21pc2U8UmVzdW1lZEhvb2s+IHtcbiAgcmV0dXJuIGF3YWl0IHdhaXRlZFVudGlsKCgpID0+IHtcbiAgICByZXR1cm4gdHJhY2UoJ2hvb2sucmVzdW1lJywgYXN5bmMgKHNwYW4pID0+IHtcbiAgICAgIGNvbnN0IHdvcmxkID0gYXdhaXQgZ2V0V29ybGRMYXp5KCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHN1cHBsaWVkVG9rZW4gPSB0eXBlb2YgdG9rZW5Pckhvb2sgPT09ICdzdHJpbmcnO1xuICAgICAgICBjb25zdCBob29rOiBIb29rID0gc3VwcGxpZWRUb2tlblxuICAgICAgICAgID8gYXdhaXQgd29ybGQuaG9va3MuZ2V0QnlUb2tlbih0b2tlbk9ySG9vaylcbiAgICAgICAgICA6IHRva2VuT3JIb29rO1xuICAgICAgICAvLyBUaGUgZHluYW1pYywgcmVzcG9uc2Utb25seSBgcmVzdW1lQ2FwYWJpbGl0aWVzYCBtYXkgb25seSBiZSB0cnVzdGVkXG4gICAgICAgIC8vIHdoZW4gaXQgY2FtZSBmcm9tIGEgYnktdG9rZW4gbG9va3VwIHBlcmZvcm1lZCBkdXJpbmcgdGhpcyByZXN1bWUuXG4gICAgICAgIGNvbnN0IGhvb2tSZXN1bWVDYXBhYmlsaXRpZXNBcmVGcmVzaCA9XG4gICAgICAgICAgc3VwcGxpZWRUb2tlbiB8fCBob29rRnJlc2hseUxvb2tlZFVwO1xuXG4gICAgICAgIGNvbnN0IGluZm8gPSBhd2FpdCByZXNvbHZlSG9va1Jlc3VtZUluZm8oaG9vayk7XG4gICAgICAgIGNvbnN0IHsgcmVzdW1lQ29udGV4dCB9ID0gaW5mbztcblxuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuSG9va1Rva2VuKGhvb2sudG9rZW4pLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Ib29rSWQoaG9vay5ob29rSWQpLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1bklkKGhvb2sucnVuSWQpLFxuICAgICAgICAgICd3b3JrZmxvdy5ob29rLnJlc3VtZV9jb250ZXh0X3NvdXJjZSc6IGluZm8uc291cmNlLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBUaGUgc3RvcmVkIGByZXN1bWVDb250ZXh0YCBpbnRlbnRpb25hbGx5IG9taXRzIHRoZSBydW4ncyBtdXRhYmxlXG4gICAgICAgIC8vIHN0YXR1cywgc28gdGhpcyBlYXJseSBjbGllbnQtc2lkZSByZWplY3Rpb24gb25seSBydW5zIG9uIHRoZVxuICAgICAgICAvLyBmYWxsYmFjayBwYXRoICh3aGljaCBmZXRjaGVkIHRoZSBydW4pLiBPbiB0aGUgZmFzdCBwYXRoIHRoZSB0ZXJtaW5hbFxuICAgICAgICAvLyBjaGVjayBoYXBwZW5zIHNlcnZlci1zaWRlOiBgaG9va19yZWNlaXZlZGAgYWdhaW5zdCBhbiBlbmRlZCBydW4gaXNcbiAgICAgICAgLy8gcmVqZWN0ZWQsIHdoaWNoIHRoZSBjYXRjaCBhcm91bmQgYHdvcmxkLmV2ZW50cy5jcmVhdGVgIGJlbG93IHJlLWtleXNcbiAgICAgICAgLy8gdG8gSG9va05vdEZvdW5kRXJyb3I6IHNhbWUgcHVibGljIGNvbnRyYWN0LCBubyBydW4gcHJlLWZldGNoLlxuICAgICAgICBpZiAoaW5mby5ydW4gJiYgaXNUZXJtaW5hbFdvcmtmbG93UnVuU3RhdHVzKGluZm8ucnVuLnN0YXR1cykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgSG9va05vdEZvdW5kRXJyb3IoaG9vay50b2tlbik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayB0aGUgdGFyZ2V0IHJ1bidzIGNhcGFiaWxpdGllcyB0byBlbnN1cmUgd2UgZW5jb2RlIHRoZVxuICAgICAgICAvLyBwYXlsb2FkIGluIGEgZm9ybWF0IHRoZSBydW4ncyBkZXBsb3ltZW50IGNhbiBkZWNvZGUuIEZvciBleGFtcGxlLFxuICAgICAgICAvLyBydW5zIGNyZWF0ZWQgYmVmb3JlIGVuY3J5cHRpb24gc3VwcG9ydCB3YXMgYWRkZWQgY2Fubm90IGRlY29kZVxuICAgICAgICAvLyB0aGUgJ2VuY3InIHNlcmlhbGl6YXRpb24gZm9ybWF0LCBhbmQgcnVucyBjcmVhdGVkIGJlZm9yZVxuICAgICAgICAvLyBieXRlLXN0cmVhbSBmcmFtaW5nIHN1cHBvcnQgY2Fubm90IGRlY29kZSBmcmFtZWQgYnl0ZSBzdHJlYW1zLlxuICAgICAgICBjb25zdCBjYXBhYmlsaXRpZXMgPSBnZXRSdW5DYXBhYmlsaXRpZXMoXG4gICAgICAgICAgcmVzdW1lQ29udGV4dC53b3JrZmxvd0NvcmVWZXJzaW9uXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gUmVzb2x2ZSBob3cgdG8gZW5jcnlwdCB0aGUgcGF5bG9hZCBmb3IgdGhlIHRhcmdldCBydW4gKGEgV1JJVEUpLlxuICAgICAgICAvL1xuICAgICAgICAvLyBQcmVmZXJyZWQgcGF0aDogc2VhbCB0byB0aGUgcnVuJ3MgcHVibGlzaGVkIFgyNTUxOSBwdWJsaWMga2V5LCB3aGljaFxuICAgICAgICAvLyB0aGUgc3RvcmVkIGByZXN1bWVDb250ZXh0YCBjYXJyaWVzIGlubGluZS4gT24gdGhlIGZhc3QgcGF0aCB0aGlzIGlzXG4gICAgICAgIC8vIHRoZSB3aG9sZSB3aW46IG5vIHJ1biByZWFkIEFORCBubyBgZ2V0RW5jcnlwdGlvbktleUZvclJ1bmAsIHdob3NlXG4gICAgICAgIC8vIH4zNTBtcyBgcnVuLWtleWAgQVBJIHJvdW5kIHRyaXAgZG9taW5hdGVzIGNyb3NzLWRlcGxveW1lbnQgaG9va1xuICAgICAgICAvLyByZXN1bXB0aW9uIGxhdGVuY3kuIChPbiB0aGUgZmFsbGJhY2sgcGF0aCB0aGUga2V5IGlzIHN5bnRoZXNpemVkXG4gICAgICAgIC8vIGZyb20gdGhlIGZldGNoZWQgcnVuLCB3aGljaCBhbHNvIGNhcnJpZXMgaXQuKVxuICAgICAgICAvL1xuICAgICAgICAvLyBTZWFsaW5nIGFsc28gZHJvcHMgcHJpdmlsZWdlOiB0aGUgcmVzdW1lciBlbmRzIHVwIGFibGUgdG8gd3JpdGUgYVxuICAgICAgICAvLyBwYXlsb2FkIGZvciB0aGUgcnVuIHdpdGhvdXQgYmVpbmcgYWJsZSB0byByZWFkIGFueXRoaW5nIG9mIHRoZVxuICAgICAgICAvLyBydW4ncywgd2hlcmUgZmV0Y2hpbmcgdGhlIHN5bW1ldHJpYyBrZXkgZ3JhbnRzIGJvdGguXG4gICAgICAgIC8vXG4gICAgICAgIC8vIERlbGliZXJhdGVseSBOT1QgZ2F0ZWQgb24gYGNhcGFiaWxpdGllcy5zdXBwb3J0ZWRGb3JtYXRzYCB0aGUgd2F5XG4gICAgICAgIC8vIHRoZSBzeW1tZXRyaWMgZmFsbGJhY2sgYmVsb3cgZ2F0ZXMgYGVuY3JgOiBwcmVzZW5jZSBvZiB0aGUgcHVibGljIGtleVxuICAgICAgICAvLyBpcyBpdHNlbGYgdGhlIGdhdGUuIEEgcnVuIG9ubHkgY2FycmllcyBvbmUgaWYgdGhlIHJ1bnRpbWUgdGhhdFxuICAgICAgICAvLyBjcmVhdGVkIGl0IGNvdWxkIGFsc28gb3BlbiBhIHNlYWxlZCBwYXlsb2FkLCBhbmQgcnVucyBhcmUgcGlubmVkIHRvXG4gICAgICAgIC8vIHRoZWlyIGNyZWF0aW5nIGRlcGxveW1lbnQsIHNvIHByZXNlbmNlIGlzIGEgbW9yZSByZWxpYWJsZSBhdHRlc3RhdGlvblxuICAgICAgICAvLyB0aGFuIGEgdmVyc2lvbiBjb21wYXJlLCBhbmQgaXQgc3RheXMgY29ycmVjdCBldmVuIHdoZW4gcGFja2FnZVxuICAgICAgICAvLyB2ZXJzaW9ucyBkcmlmdC5cbiAgICAgICAgbGV0IHBheWxvYWRLZXk6IFBheWxvYWRLZXkgfCB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IHJ1blB1YmxpY0tleSA9IGVuY3J5cHRpb25LZXlPdmVycmlkZVxuICAgICAgICAgID8gLy8gVGhlIGNhbGxlciBhbHJlYWR5IGhvbGRzIGEga2V5IChyZXN1bWVXZWJob29rIHJlc29sdmVkIG9uZSB0b1xuICAgICAgICAgICAgLy8gaHlkcmF0ZSBob29rIG1ldGFkYXRhKSwgc28gc2VhbGluZyB3b3VsZCBhZGQgYW4gRUNESCBmb3Igbm9cbiAgICAgICAgICAgIC8vIHNhdmVkIHJvdW5kIHRyaXAuIFJldXNlIHdoYXQgaXQgcmVzb2x2ZWQuXG4gICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgICA6IGRlY29kZVJ1blB1YmxpY0tleShyZXN1bWVDb250ZXh0LmVuY3J5cHRpb25QdWJsaWNLZXkpO1xuXG4gICAgICAgIGlmIChydW5QdWJsaWNLZXkpIHtcbiAgICAgICAgICBwYXlsb2FkS2V5ID0gc2VhbFRvKHJ1blB1YmxpY0tleSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gU3ltbWV0cmljIGBlbmNyYCB3cml0ZSBmYWxsYmFjazogbmVlZHMgb25seSB0aGUgQUVTIGtleVxuICAgICAgICAgIC8vIChhIGJhcmUgQ3J5cHRvS2V5IHZpYSBgcmVzb2x2ZUhvb2tFbmNyeXB0aW9uS2V5YCksIG5vdCB0aGVcbiAgICAgICAgICAvLyByZWFkLXNpZGUgUnVuUGF5bG9hZEtleXMuXG4gICAgICAgICAgbGV0IGVuY3J5cHRpb25LZXkgPVxuICAgICAgICAgICAgZW5jcnlwdGlvbktleU92ZXJyaWRlID8/XG4gICAgICAgICAgICAoYXdhaXQgcmVzb2x2ZUhvb2tFbmNyeXB0aW9uS2V5KGhvb2ssIGluZm8pKTtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAhY2FwYWJpbGl0aWVzLnN1cHBvcnRlZEZvcm1hdHMuaGFzKFNlcmlhbGl6YXRpb25Gb3JtYXQuRU5DUllQVEVEKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgZW5jcnlwdGlvbktleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcGF5bG9hZEtleSA9IGVuY3J5cHRpb25LZXk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb21wcmVzcyBvbmx5IHdoZW4gdGhlIHRhcmdldCBydW4gYW5kIGl0cyBkZXBsb3ltZW50IHN1cHBvcnQgdGhlXG4gICAgICAgIC8vIGNvbXByZXNzaW9uIGZvcm1hdHMgaW50cm9kdWNlZCB3aXRoIHNwZWMgdmVyc2lvbiA1LlxuICAgICAgICBjb25zdCBjb21wcmVzc2lvbiA9XG4gICAgICAgICAgKHJlc3VtZUNvbnRleHQucnVuU3BlY1ZlcnNpb24gPz8gMCkgPj1cbiAgICAgICAgICAgIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DT01QUkVTU0lPTiAmJlxuICAgICAgICAgIGNhcGFiaWxpdGllcy5zdXBwb3J0ZWRGb3JtYXRzLmhhcyhTZXJpYWxpemF0aW9uRm9ybWF0LkdaSVApO1xuXG4gICAgICAgIC8vIERlaHlkcmF0ZSB0aGUgcGF5bG9hZCBmb3Igc3RvcmFnZVxuICAgICAgICBjb25zdCBvcHM6IFByb21pc2U8YW55PltdID0gW107XG4gICAgICAgIGNvbnN0IHYxQ29tcGF0ID0gaXNMZWdhY3lTcGVjVmVyc2lvbihob29rLnNwZWNWZXJzaW9uKTtcbiAgICAgICAgY29uc3QgZGVoeWRyYXRlZFBheWxvYWQgPSBhd2FpdCBkZWh5ZHJhdGVTdGVwUmV0dXJuVmFsdWUoXG4gICAgICAgICAgcGF5bG9hZCxcbiAgICAgICAgICBob29rLnJ1bklkLFxuICAgICAgICAgIHBheWxvYWRLZXksXG4gICAgICAgICAgb3BzLFxuICAgICAgICAgIGdsb2JhbFRoaXMsXG4gICAgICAgICAgdjFDb21wYXQsXG4gICAgICAgICAgY2FwYWJpbGl0aWVzLmZyYW1lZEJ5dGVTdHJlYW1zLFxuICAgICAgICAgIGNvbXByZXNzaW9uXG4gICAgICAgICk7XG4gICAgICAgIC8vIFRoZXNlIHBheWxvYWQtc3RyZWFtIG9wcyBhcmUgZmx1c2hlZCBpbiB0aGUgYmFja2dyb3VuZDsgdGhlXG4gICAgICAgIC8vIHByb21pc2UgaGFuZGVkIHRvIHdhaXRVbnRpbCBtdXN0IG5ldmVyIHJlamVjdCAoYW4gdW5jb25zdW1lZFxuICAgICAgICAvLyB3YWl0VW50aWwgcmVqZWN0aW9uIGNyYXNoZXMgdGhlIHByb2Nlc3MgYXMgdW5oYW5kbGVkUmVqZWN0aW9uKSxcbiAgICAgICAgLy8gc28gdW5leHBlY3RlZCBmYWlsdXJlcyBhcmUgbG9nZ2VkIGluc3RlYWQuXG4gICAgICAgIC8vIE5PVEU6IHJlamVjdGlvbnMgd2l0aCBgdW5kZWZpbmVkYCBhcmUgYW4gZXhwZWN0ZWQgYXJ0aWZhY3Qgb2YgdGhlXG4gICAgICAgIC8vIHdlYmhvb2sgYnVuZGxlIGFuZCBhcmUgaWdub3JlZCBlbnRpcmVseS5cbiAgICAgICAgc2FmZVdhaXRVbnRpbChQcm9taXNlLmFsbChvcHMpLCAoZXJyKSA9PiB7XG4gICAgICAgICAgaWYgKGVyciA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG4gICAgICAgICAgcnVudGltZUxvZ2dlci53YXJuKCdCYWNrZ3JvdW5kIGZsdXNoIG9mIGhvb2sgcGF5bG9hZCBvcHMgZmFpbGVkJywge1xuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogaG9vay5ydW5JZCxcbiAgICAgICAgICAgIGhvb2tJZDogaG9vay5ob29rSWQsXG4gICAgICAgICAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dOYW1lKHJlc3VtZUNvbnRleHQud29ya2Zsb3dOYW1lKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gTGluayB0byB0aGUgcnVuLW9yaWdpbiBjb250ZXh0IGZyb20gdGhlIHN0b3JlZCB0cmFjZSBjYXJyaWVyXG4gICAgICAgIC8vIChza2lwcGVkIHdoZW4gYWJzZW50IG9yIGludmFsaWQpLiBSZXNvbHZlZCBiZWZvcmUgZGlzcGF0Y2ggc28gYm90aFxuICAgICAgICAvLyB0aGUgc2VxdWVudGlhbCBhbmQgbGF6eSBwYXRocyBhdHRhY2ggaXQuXG4gICAgICAgIGNvbnN0IG9yaWdpbkxpbmsgPSBhd2FpdCBsaW5rVG9UcmFjZUNhcnJpZXIocmVzdW1lQ29udGV4dC50cmFjZUNhcnJpZXIpO1xuICAgICAgICBpZiAob3JpZ2luTGluaykge1xuICAgICAgICAgIHNwYW4/LmFkZExpbms/LihvcmlnaW5MaW5rKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHF1ZXVlTmFtZSA9IGdldFdvcmtmbG93UXVldWVOYW1lKHJlc3VtZUNvbnRleHQud29ya2Zsb3dOYW1lKTtcbiAgICAgICAgY29uc3QgcXVldWVPcHRpb25zID0ge1xuICAgICAgICAgIGRlcGxveW1lbnRJZDogcmVzdW1lQ29udGV4dC5kZXBsb3ltZW50SWQsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IHJlc3VtZUNvbnRleHQucnVuU3BlY1ZlcnNpb24gPz8gU1BFQ19WRVJTSU9OX0xFR0FDWSxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBEZWNpZGUgd2hldGhlciB0aGUgYGhvb2tfcmVjZWl2ZWRgIGV2ZW50IGlzIHdyaXR0ZW4gbGF6aWx5IGJ5IHRoZVxuICAgICAgICAvLyBxdWV1ZSBjb25zdW1lciAoZnJvbSB0aGUgbWVzc2FnZSdzIGBob29rSW5wdXRgKSBvciBlYWdlcmx5IGhlcmUsXG4gICAgICAgIC8vIGJlZm9yZSB0aGUgcHVibGlzaC4gVGhlIGxhenkgcGF0aCBpcyBvbmx5IHNhZmUgd2hlbiBFVkVSWVxuICAgICAgICAvLyBwcmVjb25kaXRpb24gaG9sZHM7IHRoZSBmaXJzdCB0aGF0IGZhaWxzIG5hbWVzIHRoZSBmYWxsYmFjayByZWFzb25cbiAgICAgICAgLy8gKGVtaXR0ZWQgYXMgYSBzcGFuIGF0dHJpYnV0ZSBmb3Igb2JzZXJ2YWJpbGl0eSwgYW5kIHRvIG1ha2UgXCJ3aHkgZGlkXG4gICAgICAgIC8vIHRoaXMgcnVuIHNlcXVlbnRpYWxcIiBhbnN3ZXJhYmxlIGluIHByb2R1Y3Rpb24pLiBBbGwgY29uZGl0aW9uczpcbiAgICAgICAgLy9cbiAgICAgICAgLy8gIC0ga2lsbCBzd2l0Y2g6IGBXT1JLRkxPV19ESVNBQkxFX0xBWllfSE9PS19SRVNVTUVgIGZvcmNlcyBzZXF1ZW50aWFsXG4gICAgICAgIC8vICAgIGlmIHRoZSBsYXp5IHBhdGggZXZlciBtaXNiZWhhdmVzLiBJdCBpcyBhbiBTREstZGVwbG95bWVudCBlbnYgdmFyLFxuICAgICAgICAvLyAgICBzbyBjaGFuZ2luZyBpdCBnZW5lcmFsbHkgcmVxdWlyZXMgcmVkZXBsb3lpbmcgdGhlIHdvcmtmbG93XG4gICAgICAgIC8vICAgIGRlcGxveW1lbnQuIChUaGUgYmFja2VuZCBjYW4gaW5kZXBlbmRlbnRseSBkcm9wIG5ldyByZXN1bWVzIHRvIHRoZVxuICAgICAgICAvLyAgICBzZXF1ZW50aWFsIHBhdGggZmxlZXQtd2lkZSBieSBjZWFzaW5nIHRvIGF0dGVzdCBkZWR1cCBzdXBwb3J0IG9uXG4gICAgICAgIC8vICAgIHRoZSBieS10b2tlbiBsb29rdXA7IHNlZSB0aGUgYmFja2VuZC1kZWR1cCBjb25kaXRpb24gYmVsb3cuKVxuICAgICAgICAvLyAgLSBiYWNrZW5kIGRlZHVwOiB0aGUgbGl2ZSBiYWNrZW5kIG11c3QgZW5mb3JjZSB0aGVcbiAgICAgICAgLy8gICAgYChydW5JZCwgcmVzdW1lSWQpYCBjb25zdHJhaW50LCBvciBhIHF1ZXVlIHJlZGVsaXZlcnkgd291bGQgY29tbWl0XG4gICAgICAgIC8vICAgIGEgc2Vjb25kIGBob29rX3JlY2VpdmVkYC4gRmFpbCBjbG9zZWQuIEF0dGVzdGVkIGJ5IEVJVEhFUiBhIGZyZXNoLFxuICAgICAgICAvLyAgICByZXNwb25zZS1vbmx5IGBob29rLnJlc3VtZUNhcGFiaWxpdGllcy5ob29rUmVzdW1lRGVkdXBWZXJzaW9uYCBmcm9tXG4gICAgICAgIC8vICAgIHRoZSBieS10b2tlbiBsb29rdXAgKHdvcmxkLXZlcmNlbDogcmVjb21wdXRlZCBldmVyeSByZWFkLCBzbyBhXG4gICAgICAgIC8vICAgIHNlcnZlciByb2xsYmFjayBvciBraWxsIHN3aXRjaCBkcm9wcyB0byBzZXF1ZW50aWFsIGltbWVkaWF0ZWx5KSBPUlxuICAgICAgICAvLyAgICB0aGUgc3RhdGljIGB3b3JsZC5jYXBhYmlsaXRpZXMuaG9va1Jlc3VtZURlZHVwYCAod29ybGQtbG9jYWwsIHdob3NlXG4gICAgICAgIC8vICAgIGFkYXB0ZXIgYW5kIGJhY2tlbmQgc2hpcCB0b2dldGhlcikuIFRoZSByZXNwb25zZS1vbmx5IGNhcGFiaWxpdHkgaXNcbiAgICAgICAgLy8gICAgdHJ1c3RlZCBPTkxZIHdoZW4gdGhlIGhvb2sgd2FzIGxvb2tlZCB1cCBieSB0b2tlbiBkdXJpbmcgdGhpc1xuICAgICAgICAvLyAgICByZXN1bWUgKGBob29rUmVzdW1lQ2FwYWJpbGl0aWVzQXJlRnJlc2hgKTsgYSBIb29rIG9iamVjdCBoYW5kZWQgaW5cbiAgICAgICAgLy8gICAgYnkgYSBwdWJsaWMgY2FsbGVyIG1heSBjYXJyeSBhIGNhcGFiaWxpdHkgY2FjaGVkIGJlZm9yZSBhIHJvbGxiYWNrLFxuICAgICAgICAvLyAgICBzbyBpdCBpcyBpZ25vcmVkIGFuZCB0aGUgcGF0aCBmYWxscyBiYWNrIHRvIHNlcXVlbnRpYWwuXG4gICAgICAgIC8vICAtIGNvbnN1bWVyIHN1cHBvcnQ6IHRoZSB0YXJnZXQgcnVuJ3MgZGVwbG95bWVudCBtdXN0IG1hdGVyaWFsaXplIHRoZVxuICAgICAgICAvLyAgICBldmVudCBmcm9tIGBob29rSW5wdXRgIG9uIHJlcGxheS4gQXR0ZXN0ZWQgYnkgdGhlIHJ1bidzIGV4cGxpY2l0XG4gICAgICAgIC8vICAgIGBob29rUmVzdW1lSW5wdXRWZXJzaW9uYCBleGVjdXRpb24tY29udGV4dCBtYXJrZXIgKG1pcnJvcmVkIG9udG9cbiAgICAgICAgLy8gICAgcmVzdW1lQ29udGV4dCksIE5PVCBhIHZlcnNpb24tY29tcGFyZSBhZ2FpbnN0IGEgcHJlZGljdGVkIHJlbGVhc2VcbiAgICAgICAgLy8gICAgY3V0b2ZmLiBBYnNlbnQg4oaSIG5vdGhpbmcgd291bGQgZXZlciB3cml0ZSB0aGUgZXZlbnQsIHNvIHRoZSByZXN1bWVcbiAgICAgICAgLy8gICAgd291bGQgYmUgbG9zdCBvdXRyaWdodC5cbiAgICAgICAgLy8gIC0gbm90IGxlZ2FjeTogdjFDb21wYXQgcnVucyBvbWl0IGB0b2tlbmAgZnJvbSB0aGUgZWFnZXJseSB3cml0dGVuXG4gICAgICAgIC8vICAgIGV2ZW50IGJvZHkgYnV0IHRoZSBjb25zdW1lciBhbHdheXMgaW5jbHVkZXMgaXQsIHNvIGEgbGVnYWN5IHJ1blxuICAgICAgICAvLyAgICB3b3VsZCBnZXQgYSBkaWZmZXJlbnQgZXZlbnQgZGVwZW5kaW5nIG9uIHdoaWNoIHBhdGggcmFuLiBMZWdhY3lcbiAgICAgICAgLy8gICAgc3RheXMgc2VxdWVudGlhbC5cbiAgICAgICAgLy8gIC0gQ0JPUiB0cmFuc3BvcnQ6IHRoZSBydW4gbXVzdCB1c2UgQ0JPUiBxdWV1ZSB0cmFuc3BvcnQgc28gdGhlIGJpbmFyeVxuICAgICAgICAvLyAgICBwYXlsb2FkIHN1cnZpdmVzIHRoZSBxdWV1ZSBtZXNzYWdlLlxuICAgICAgICAvLyAgLSByYXcgYnl0ZXM6IHRoZSBkZWh5ZHJhdGVkIHBheWxvYWQgbXVzdCBiZSBhIGBVaW50OEFycmF5YCAodGhlXG4gICAgICAgIC8vICAgIGNvbnRlbnQgZGlnZXN0IHRoYXQga2V5cyB0aGUgZGVkdXAgY29uc3RyYWludCBpcyBvdmVyIHRoZXNlIGJ5dGVzKS5cbiAgICAgICAgLy8gIC0gc2l6ZTogb24gdGhlIGxhenkgcGF0aCB0aGUgcXVldWUgbWVzc2FnZSBjYXJyaWVzIHRoZSBvbmx5IGNvcHkgb2ZcbiAgICAgICAgLy8gICAgdGhlIHBheWxvYWQsIHNvIGEgcGF5bG9hZCBhYm92ZSB0aGUgbWVzc2FnZSBjZWlsaW5nIHdvdWxkIGZhaWwgdGhlXG4gICAgICAgIC8vICAgIHB1Ymxpc2ggYW5kIGxvc2UgdGhlIHJlc3VtZS4gT3ZlcnNpemVkIHBheWxvYWRzIHN0YXkgc2VxdWVudGlhbFxuICAgICAgICAvLyAgICAodGhlaXIgcXVldWUgbWVzc2FnZSBjYXJyaWVzIG9ubHkgdGhlIHJ1biBJRDsgdGhlIHBheWxvYWQgbGl2ZXMgaW5cbiAgICAgICAgLy8gICAgdGhlIGV2ZW50IGxvZykuXG4gICAgICAgIGNvbnN0IGxhenlSZXN1bWVEaXNhYmxlZCA9XG4gICAgICAgICAgcHJvY2Vzcy5lbnYuV09SS0ZMT1dfRElTQUJMRV9MQVpZX0hPT0tfUkVTVU1FID09PSAnMSc7XG4gICAgICAgIC8vIEJhY2tlbmQgZGVkdXAgaXMgc3VwcG9ydGVkIHdoZW4gRUlUSEVSIHRoZSBsaXZlIHNlcnZlciBhdHRlc3RzIGl0XG4gICAgICAgIC8vIGZyZXNoIG9uIHRoaXMgYnktdG9rZW4gaG9vayAod29ybGQtdmVyY2VsOiByZXNwb25zZS1vbmx5LCByZWNvbXB1dGVkXG4gICAgICAgIC8vIGV2ZXJ5IHJlYWQsIHNvIHJvbGxiYWNrL2tpbGwtc3dpdGNoIHRha2UgZWZmZWN0IGltbWVkaWF0ZWx5KSBPUiB0aGVcbiAgICAgICAgLy8gc3RhdGljIHdvcmxkIGNhcGFiaWxpdHkgaXMgc2V0ICh3b3JsZC1sb2NhbDogYWRhcHRlciArIGJhY2tlbmQgc2hpcFxuICAgICAgICAvLyB0b2dldGhlcikuIEJvdGggYXJlIHJlLWV2YWx1YXRlZCBwZXIgcmVzdW1lLCBzbyBldmVyeSByb2xsb3V0IGFuZFxuICAgICAgICAvLyByb2xsYmFjayBkaXJlY3Rpb24gZGVncmFkZXMgc2FmZWx5IHRvIHRoZSBzZXF1ZW50aWFsIHBhdGguXG4gICAgICAgIGNvbnN0IGJhY2tlbmREZWR1cFN1cHBvcnRlZCA9XG4gICAgICAgICAgKGhvb2tSZXN1bWVDYXBhYmlsaXRpZXNBcmVGcmVzaFxuICAgICAgICAgICAgPyAoaG9vay5yZXN1bWVDYXBhYmlsaXRpZXM/Lmhvb2tSZXN1bWVEZWR1cFZlcnNpb24gPz8gMClcbiAgICAgICAgICAgIDogMCkgPj0gSE9PS19SRVNVTUVfREVEVVBfVkVSU0lPTiB8fFxuICAgICAgICAgIHdvcmxkLmNhcGFiaWxpdGllcz8uaG9va1Jlc3VtZURlZHVwID09PSB0cnVlO1xuICAgICAgICBjb25zdCBmYWxsYmFja1JlYXNvbjogc3RyaW5nIHwgbnVsbCA9IHJlcXVpcmVEdXJhYmxlV3JpdGVcbiAgICAgICAgICA/IC8vIEFuIGludGVybmFsIGNhbGxlciBuZWVkcyB0aGUgZXZlbnQgY29tbWl0dGVkIGJlZm9yZSB0aGlzXG4gICAgICAgICAgICAvLyByZXNvbHZlcyAoYW4gb3JkZXJpbmcgYmFycmllciksIHdoaWNoIG9ubHkgdGhlIGVhZ2VyIHdyaXRlXG4gICAgICAgICAgICAvLyBwcm92aWRlcy4gQ2hlY2tlZCBmaXJzdCBzbyB0aGUgc3BhbiBuYW1lcyB0aGUgcmVhbCByZWFzb25cbiAgICAgICAgICAgIC8vIHJhdGhlciB0aGFuIHdoaWNoZXZlciBnYXRlIGhhcHBlbnMgdG8gZmFpbCBhbG9uZ3NpZGUgaXQuXG4gICAgICAgICAgICAnZHVyYWJsZV9yZXF1aXJlZCdcbiAgICAgICAgICA6IGxhenlSZXN1bWVEaXNhYmxlZFxuICAgICAgICAgICAgPyAnZGlzYWJsZWQnXG4gICAgICAgICAgICA6ICFiYWNrZW5kRGVkdXBTdXBwb3J0ZWRcbiAgICAgICAgICAgICAgPyAnYmFja2VuZF91bnN1cHBvcnRlZCdcbiAgICAgICAgICAgICAgOiAocmVzdW1lQ29udGV4dC5ob29rUmVzdW1lSW5wdXRWZXJzaW9uID8/IDApIDxcbiAgICAgICAgICAgICAgICAgIEhPT0tfUkVTVU1FX0lOUFVUX1ZFUlNJT05cbiAgICAgICAgICAgICAgICA/ICdjb25zdW1lcl91bnN1cHBvcnRlZCdcbiAgICAgICAgICAgICAgICA6IHYxQ29tcGF0XG4gICAgICAgICAgICAgICAgICA/ICdsZWdhY3knXG4gICAgICAgICAgICAgICAgICA6IChyZXN1bWVDb250ZXh0LnJ1blNwZWNWZXJzaW9uID8/IDApIDxcbiAgICAgICAgICAgICAgICAgICAgICBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ0JPUl9RVUVVRV9UUkFOU1BPUlRcbiAgICAgICAgICAgICAgICAgICAgPyAnbm9uX2Nib3JfdHJhbnNwb3J0J1xuICAgICAgICAgICAgICAgICAgICA6ICEoZGVoeWRyYXRlZFBheWxvYWQgaW5zdGFuY2VvZiBVaW50OEFycmF5KVxuICAgICAgICAgICAgICAgICAgICAgID8gJ25vbl9ieXRlcydcbiAgICAgICAgICAgICAgICAgICAgICA6IGRlaHlkcmF0ZWRQYXlsb2FkLmJ5dGVMZW5ndGggPlxuICAgICAgICAgICAgICAgICAgICAgICAgICBNQVhfSU5MSU5FX1JFU1VNRV9QQVlMT0FEX0JZVEVTXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICdvdmVyc2l6ZWQnXG4gICAgICAgICAgICAgICAgICAgICAgICA6IG51bGw7XG4gICAgICAgIGNvbnN0IHVzZUxhenlSZXN1bWUgPSBmYWxsYmFja1JlYXNvbiA9PT0gbnVsbDtcblxuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAnd29ya2Zsb3cuaG9vay5yZXN1bWVfc3RyYXRlZ3knOiB1c2VMYXp5UmVzdW1lXG4gICAgICAgICAgICA/ICdsYXp5J1xuICAgICAgICAgICAgOiAnc2VxdWVudGlhbCcsXG4gICAgICAgICAgLi4uKGZhbGxiYWNrUmVhc29uXG4gICAgICAgICAgICA/IHsgJ3dvcmtmbG93Lmhvb2sucmVzdW1lX2ZhbGxiYWNrX3JlYXNvbic6IGZhbGxiYWNrUmVhc29uIH1cbiAgICAgICAgICAgIDoge30pLFxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoIXVzZUxhenlSZXN1bWUpIHtcbiAgICAgICAgICAvLyBTZXF1ZW50aWFsIHBhdGg6IGNyZWF0ZSBhIGhvb2tfcmVjZWl2ZWQgZXZlbnQsIHRoZW4gcmUtdHJpZ2dlci5cbiAgICAgICAgICAvL1xuICAgICAgICAgIC8vIFJlLWtleSBhbnkgXCJob29rIGNhbiBubyBsb25nZXIgYmUgcmVjZWl2ZWRcIiByZWplY3Rpb24gdG9cbiAgICAgICAgICAvLyBIb29rTm90Rm91bmRFcnJvcihob29rLnRva2VuKSBzbyBgLnRva2VuYCBtYXRjaGVzIHRoZSBoaXN0b3JpY2FsXG4gICAgICAgICAgLy8gY29udHJhY3QsIHdoZXJlIHJlc3VtZUhvb2sgdGhyZXcgYEhvb2tOb3RGb3VuZEVycm9yKGhvb2sudG9rZW4pYFxuICAgICAgICAgIC8vIGFmdGVyIGl0cyBvd24gdGVybWluYWwgY2hlY2suIFRoZSBzcGVjaWZpYyBlcnJvciBkZXBlbmRzIG9uIHRoZVxuICAgICAgICAgIC8vIFdvcmxkOlxuICAgICAgICAgIC8vICAgLSBhIGdlbnVpbmVseSBtaXNzaW5nIGhvb2sgbWFwcyB0byBIb29rTm90Rm91bmRFcnJvciAoa2V5ZWQgb25cbiAgICAgICAgICAvLyAgICAgdGhlIGV2ZW50IGNvcnJlbGF0aW9uSWQgLyBob29rIElEKTtcbiAgICAgICAgICAvLyAgIC0gYSB0ZXJtaW5hbCBydW4gb24gVmVyY2VsIHJlamVjdHMgaG9va19yZWNlaXZlZCB3aXRoIDQwNCwgd2hpY2hcbiAgICAgICAgICAvLyAgICAgd29ybGQtdmVyY2VsIG1hcHMgdG8gSG9va05vdEZvdW5kRXJyb3I7XG4gICAgICAgICAgLy8gICAtIGEgdGVybWluYWwgcnVuIG9uIHdvcmxkLWxvY2FsIC8gd29ybGQtcG9zdGdyZXMgcmVqZWN0cyB3aXRoXG4gICAgICAgICAgLy8gICAgIFJ1bkV4cGlyZWRFcnJvci5cbiAgICAgICAgICAvL1xuICAgICAgICAgIC8vIEFuIEVudGl0eUNvbmZsaWN0RXJyb3IgKEhUVFAgNDA5KSBpcyBhbHNvIHRyZWF0ZWQgYXMgXCJob29rIGdvbmVcIlxuICAgICAgICAgIC8vIGhlcmUgZm9yIGhpc3RvcmljYWwgLyBjb25mbGljdC1zaGFwZWQtcmVqZWN0aW9uIGNvbXBhdGliaWxpdHk6XG4gICAgICAgICAgLy8gdGhpcyBwYXRoIGhvbGRzIG5vIHF1ZXVlIG1lc3NhZ2UgaW4gZmxpZ2h0LCBzbyBhIGNvbmZsaWN0IGhhcyBub1xuICAgICAgICAgIC8vIGNvbnN1bWVyIHRvIGNvbnZlcmdlIG9uLlxuICAgICAgICAgIC8vXG4gICAgICAgICAgLy8gVGhlIGxhenkgcGF0aCBwZXJmb3JtcyBubyB3cml0ZSwgc28gaXQgcmFpc2VzIG5vbmUgb2YgdGhlc2U6IHNlZVxuICAgICAgICAgIC8vIHRoZSBub3RlIG9uIGl0cyB0ZXJtaW5hbC1ydW4gYmVoYXZpb3IgYmVsb3cuXG4gICAgICAgICAgY29uc3QgaXNIb29rR29uZUVycm9yID0gKGVycjogdW5rbm93bik6IGJvb2xlYW4gPT5cbiAgICAgICAgICAgIEhvb2tOb3RGb3VuZEVycm9yLmlzKGVycikgfHxcbiAgICAgICAgICAgIEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSB8fFxuICAgICAgICAgICAgUnVuRXhwaXJlZEVycm9yLmlzKGVycik7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgICAgIGhvb2sucnVuSWQsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdob29rX3JlY2VpdmVkJyxcbiAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogaG9vay5ob29rSWQsXG4gICAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgICAuLi4odjFDb21wYXQgPyB7fSA6IHsgdG9rZW46IGhvb2sudG9rZW4gfSksXG4gICAgICAgICAgICAgICAgICBwYXlsb2FkOiBkZWh5ZHJhdGVkUGF5bG9hZCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB7IHYxQ29tcGF0IH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoaXNIb29rR29uZUVycm9yKGVycikpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEhvb2tOb3RGb3VuZEVycm9yKGhvb2sudG9rZW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIFQxIG9mIHRoZSBUVFIgd2luZG93LiBTdGFtcGVkIGltbWVkaWF0ZWx5IGJlZm9yZSB0aGUgcHVibGlzaCBzb1xuICAgICAgICAgIC8vIGBwcm9kdWNlcl9wcmVwYCBjb3ZlcnMgZXhhY3RseSB0aGUgd29yayBhYm92ZSBpdCAoaG9vayBsb29rdXAsXG4gICAgICAgICAgLy8ga2V5IHJlc29sdXRpb24sIHNlcmlhbGl6YXRpb24sIGFuZCwgb24gdGhpcyBwYXRoLCB0aGUgYXdhaXRlZFxuICAgICAgICAgIC8vIGBob29rX3JlY2VpdmVkYCB3cml0ZSwgd2hpY2ggaXMgZ2VudWluZWx5IHNlcmlhbCBoZXJlKS5cbiAgICAgICAgICBjb25zdCBxdWV1ZVB1Ymxpc2hSZXF1ZXN0ZWRBdE1zID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICBhd2FpdCB3b3JsZC5xdWV1ZShcbiAgICAgICAgICAgIHF1ZXVlTmFtZSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgcnVuSWQ6IGhvb2sucnVuSWQsXG4gICAgICAgICAgICAgIHRyYWNlQ2FycmllcjogcmVzdW1lQ29udGV4dC50cmFjZUNhcnJpZXIgPz8gdW5kZWZpbmVkLFxuICAgICAgICAgICAgICBob29rUmVzdW1lVGltaW5nOiB7XG4gICAgICAgICAgICAgICAgcmVzdW1lUmVxdWVzdGVkQXRNcyxcbiAgICAgICAgICAgICAgICBxdWV1ZVB1Ymxpc2hSZXF1ZXN0ZWRBdE1zLFxuICAgICAgICAgICAgICAgIHN0cmF0ZWd5OiAnc2VxdWVudGlhbCcsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9IHNhdGlzZmllcyBXb3JrZmxvd0ludm9rZVBheWxvYWQsXG4gICAgICAgICAgICBxdWV1ZU9wdGlvbnNcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgcmV0dXJuIGhvb2s7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBMYXp5IHBhdGg6IHB1Ymxpc2ggdGhlIHF1ZXVlIG1lc3NhZ2UgYW5kIGxldCB0aGUgY29uc3VtZXIgd3JpdGUgdGhlXG4gICAgICAgIC8vIGBob29rX3JlY2VpdmVkYCBldmVudCBmcm9tIGBob29rSW5wdXRgIGJlZm9yZSBpdCByZXBsYXlzLiBUaGVcbiAgICAgICAgLy8gcHJvZHVjZXIgd3JpdGVzIG5vdGhpbmcsIHNvIHRoZSByZXN1bWUgY29zdHMgZXhhY3RseSBvbmUgcm91bmQgdHJpcFxuICAgICAgICAvLyAodGhlIHB1Ymxpc2gpIGluc3RlYWQgb2YgdHdvLCBhbmQgdGhlIGV2ZW50IGlzIGNyZWF0ZWQgb25jZSwgYnkgdGhlXG4gICAgICAgIC8vIHNpZGUgdGhhdCBpcyBhYm91dCB0byByZXBsYXkgaXQuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIGByZXN1bWVJZGAgaXMgdGhlIGlkZW1wb3RlbmN5IGtleSB0aGUgY29uc3VtZXIgc2VuZHMgd2l0aCB0aGF0IHdyaXRlO1xuICAgICAgICAvLyBgcGF5bG9hZERpZ2VzdGAgbGV0cyB0aGUgc2VydmVyIGRldGVjdCBrZXkgcmV1c2UgYWNyb3NzXG4gICAgICAgIC8vIGJ5dGUtZGlmZmVyZW50IHBheWxvYWRzLiBCb3RoIHJpZGUgdGhlIG1lc3NhZ2UsIHNvIGV2ZXJ5IHJlZGVsaXZlcnlcbiAgICAgICAgLy8gb2YgaXQgY29udmVyZ2VzIG9uIHRoZSBvbmUgY29tbWl0dGVkIGV2ZW50IHZpYSB0aGUgYmFja2VuZCdzXG4gICAgICAgIC8vIGAocnVuSWQsIHJlc3VtZUlkKWAgY29uc3RyYWludCAodGhlIHByZWNvbmRpdGlvbiBnYXRlZCBhYm92ZSkuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFR3byB0aGluZ3MgYSBjYWxsZXIgY291bGQgcHJldmlvdXNseSBpbmZlciBmcm9tIGEgcmVzb2x2ZWQgcmVzdW1lLFxuICAgICAgICAvLyBhbmQgY2FuIG5vIGxvbmdlcjpcbiAgICAgICAgLy9cbiAgICAgICAgLy8gIC0gVmlzaWJpbGl0eS4gVGhpcyByZXR1cm5zIG9uY2UgdGhlIHB1Ymxpc2ggaXMgYWNjZXB0ZWQsIG5vdCBvbmNlXG4gICAgICAgIC8vICAgIGBob29rX3JlY2VpdmVkYCBleGlzdHMsIHNvIGEgY2FsbGVyIHRoYXQgcmVhZHMgdGhlIHJ1biBiYWNrXG4gICAgICAgIC8vICAgIGltbWVkaWF0ZWx5IGNhbiBzZWUgYSBsb2cgd2l0aG91dCBpdC4gRGVsaXZlcnkgaXMgdW5hZmZlY3RlZDogdGhlXG4gICAgICAgIC8vICAgIHBheWxvYWQgaXMgb24gdGhlIG1lc3NhZ2UuXG4gICAgICAgIC8vICAtIFRoZSBydW4gc3RpbGwgYmVpbmcgbGl2ZS4gVGhlIGhvb2sgbG9va3VwIGFib3ZlIHN0aWxsIHZhbGlkYXRlc1xuICAgICAgICAvLyAgICB0aGF0IGEgaG9vayBob2xkcyB0aGUgdG9rZW4gKGFuZCB3aGljaCBydW4gaXQgYmVsb25ncyB0byksIGJ1dFxuICAgICAgICAvLyAgICBgcmVzdW1lQ29udGV4dGAgaXMgYW4gaW1tdXRhYmxlIHNsaWNlIGFuZCBjYXJyaWVzIG5vIHN0YXR1cywgYW5kXG4gICAgICAgIC8vICAgIHdpdGggbm8gd3JpdGUgdGhlcmUgaXMgbm8gc2VydmVyIHJlamVjdGlvbiB0byBvYnNlcnZlLiBBIHJlc3VtZVxuICAgICAgICAvLyAgICBhZ2FpbnN0IGFuIGVuZGVkIHJ1biB0aGVyZWZvcmUgcmVzb2x2ZXMgcmF0aGVyIHRoYW4gdGhyb3dpbmdcbiAgICAgICAgLy8gICAgSG9va05vdEZvdW5kRXJyb3IuIEl0IGlzIHJlYWNoYWJsZSBvbmx5IHdoaWxlIHRoZSBob29rIG91dGxpdmVzXG4gICAgICAgIC8vICAgIGl0cyBydW4gKG1pbmltdW0gcmV0ZW50aW9uLCBvciBiZWZvcmUgdGhlIHRva2VuIGlzIHJlbGVhc2VkKTtcbiAgICAgICAgLy8gICAgb3RoZXJ3aXNlIHRoZSBsb29rdXAgaXRzZWxmIGZhaWxzLiBOb3RoaW5nIHJlc3VtZXMgZWl0aGVyIHdheTpcbiAgICAgICAgLy8gICAgdGhlIGNvbnN1bWVyJ3Mgd3JpdGUgaXMgcmVqZWN0ZWQgdGhlIHNhbWUgd2F5IGFuZCB0aGUgZGVsaXZlcnkgaXNcbiAgICAgICAgLy8gICAgY29uc3VtZWQuIFRoZSBwYXRocyB0aGF0IGRvIG9ic2VydmUgdGhlIHN0YXR1cyBhcmUgdW5jaGFuZ2VkOiB0aGVcbiAgICAgICAgLy8gICAgYHJ1bl9mYWxsYmFja2AgdGVybWluYWwgcHJlLWNoZWNrIGFib3ZlLCBhbmQgdGhlIHNlcXVlbnRpYWxcbiAgICAgICAgLy8gICAgcGF0aCdzIG93biB3cml0ZS5cbiAgICAgICAgY29uc3QgcmVzdW1lSWQgPSBnZW5lcmF0ZVJlc3VtZUlkKCk7XG4gICAgICAgIGNvbnN0IHBheWxvYWREaWdlc3QgPSBhd2FpdCBjb21wdXRlUmVzdW1lUGF5bG9hZERpZ2VzdChcbiAgICAgICAgICBkZWh5ZHJhdGVkUGF5bG9hZCBhcyBVaW50OEFycmF5XG4gICAgICAgICk7XG4gICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoeyAnd29ya2Zsb3cuaG9vay5yZXN1bWVfaWQnOiByZXN1bWVJZCB9KTtcblxuICAgICAgICAvLyBUMSBvZiB0aGUgVFRSIHdpbmRvdywgc3RhbXBlZCBhdCB0aGUgaW5zdGFudCB0aGUgcHVibGlzaCBpc1xuICAgICAgICAvLyByZXF1ZXN0ZWQ6IGBwcm9kdWNlcl9wcmVwYCBjb3ZlcnMgZXhhY3RseSB0aGUgd29yayBhYm92ZSBpdCAoaG9va1xuICAgICAgICAvLyBsb29rdXAsIGtleSByZXNvbHV0aW9uLCBzZXJpYWxpemF0aW9uKSBhbmQgbm90aGluZyBlbHNlLCBzaW5jZSBub1xuICAgICAgICAvLyBldmVudCB3cml0ZSByZW1haW5zIG9uIHRoaXMgcGF0aC5cbiAgICAgICAgY29uc3QgcXVldWVQdWJsaXNoUmVxdWVzdGVkQXRNcyA9IERhdGUubm93KCk7XG4gICAgICAgIGF3YWl0IHdvcmxkLnF1ZXVlKFxuICAgICAgICAgIHF1ZXVlTmFtZSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBydW5JZDogaG9vay5ydW5JZCxcbiAgICAgICAgICAgIHRyYWNlQ2FycmllcjogcmVzdW1lQ29udGV4dC50cmFjZUNhcnJpZXIgPz8gdW5kZWZpbmVkLFxuICAgICAgICAgICAgaG9va0lucHV0OiB7XG4gICAgICAgICAgICAgIHJlc3VtZUlkLFxuICAgICAgICAgICAgICBob29rSWQ6IGhvb2suaG9va0lkLFxuICAgICAgICAgICAgICB0b2tlbjogaG9vay50b2tlbixcbiAgICAgICAgICAgICAgcGF5bG9hZDogZGVoeWRyYXRlZFBheWxvYWQsXG4gICAgICAgICAgICAgIHBheWxvYWREaWdlc3QsXG4gICAgICAgICAgICAgIC8vIERlcGxveW1lbnQgYWZmaW5pdHkgZm9yIHRoZSBjb25zdW1lcidzIGNoZWFwIHByZS13cml0ZVxuICAgICAgICAgICAgICAvLyBjaGVjazogbGV0cyBhIG1pc3JvdXRlZCBkZWxpdmVyeSByZS1yb3V0ZSBiZWZvcmUgaXRzXG4gICAgICAgICAgICAgIC8vIGhvaXN0ZWQgaG9va19yZWNlaXZlZCB3cml0ZSBpbnN0ZWFkIG9mIGFmdGVyLlxuICAgICAgICAgICAgICBkZXBsb3ltZW50SWQ6IHJlc3VtZUNvbnRleHQuZGVwbG95bWVudElkLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGhvb2tSZXN1bWVUaW1pbmc6IHtcbiAgICAgICAgICAgICAgcmVzdW1lUmVxdWVzdGVkQXRNcyxcbiAgICAgICAgICAgICAgcXVldWVQdWJsaXNoUmVxdWVzdGVkQXRNcyxcbiAgICAgICAgICAgICAgc3RyYXRlZ3k6ICdsYXp5JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSBzYXRpc2ZpZXMgV29ya2Zsb3dJbnZva2VQYXlsb2FkLFxuICAgICAgICAgIHF1ZXVlT3B0aW9uc1xuICAgICAgICApO1xuXG4gICAgICAgIC8vIEEgcmVqZWN0ZWQgcHVibGlzaCBwcm9wYWdhdGVzOiB0aGUgbWVzc2FnZSBpcyB0aGUgb25seSBjYXJyaWVyIG9mXG4gICAgICAgIC8vIGJvdGggdGhlIHRyaWdnZXIgYW5kIHRoZSBwYXlsb2FkLCBzbyBhIGZhaWxlZCBwdWJsaXNoIGlzIGEgZmFpbGVkXG4gICAgICAgIC8vIHJlc3VtZSwgd2l0aCBub3RoaW5nIHBlcnNpc3RlZCBmb3IgYSBsYXRlciBkZWxpdmVyeSB0byBwaWNrIHVwLlxuICAgICAgICByZXR1cm4gaG9vayBzYXRpc2ZpZXMgUmVzdW1lZEhvb2s7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgLi4uQXR0cmlidXRlLkhvb2tUb2tlbihcbiAgICAgICAgICAgIHR5cGVvZiB0b2tlbk9ySG9vayA9PT0gJ3N0cmluZycgPyB0b2tlbk9ySG9vayA6IHRva2VuT3JIb29rLnRva2VuXG4gICAgICAgICAgKSxcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuSG9va0ZvdW5kKGZhbHNlKSxcbiAgICAgICAgfSk7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG59XG5cbi8qKlxuICogUmVzdW1lcyBhIHdlYmhvb2sgYnkgc2VuZGluZyBhIHtAbGluayBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvUmVxdWVzdCB8IFJlcXVlc3R9XG4gKiBvYmplY3QgdG8gYSBob29rIGlkZW50aWZpZWQgYnkgaXRzIHRva2VuLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIGV4dGVybmFsbHkgKGUuZy4sIGZyb20gYW4gQVBJIHJvdXRlIG9yIHNlcnZlciBhY3Rpb24pXG4gKiB0byBzZW5kIGEgcmVxdWVzdCB0byBhIHdlYmhvb2sgYW5kIHJlc3VtZSB0aGUgYXNzb2NpYXRlZCB3b3JrZmxvdyBydW4uXG4gKlxuICogQHBhcmFtIHRva2VuIC0gVGhlIHVuaXF1ZSB0b2tlbiBpZGVudGlmeWluZyB0aGUgaG9va1xuICogQHBhcmFtIHJlcXVlc3QgLSBUaGUgcmVxdWVzdCB0byBzZW5kIHRvIHRoZSBob29rXG4gKiBAcmV0dXJucyBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgcmVzcG9uc2VcbiAqIEB0aHJvd3MgRXJyb3IgaWYgdGhlIGhvb2sgaXMgbm90IGZvdW5kIG9yIGlmIHRoZXJlJ3MgYW4gZXJyb3IgZHVyaW5nIHRoZSBwcm9jZXNzXG4gKlxuICogQGV4YW1wbGVcbiAqXG4gKiBgYGB0c1xuICogLy8gSW4gYW4gQVBJIHJvdXRlXG4gKiBpbXBvcnQgeyByZXN1bWVXZWJob29rIH0gZnJvbSAnQHdvcmtmbG93L2NvcmUvcnVudGltZSc7XG4gKlxuICogZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIFBPU1QocmVxdWVzdDogUmVxdWVzdCkge1xuICogICBjb25zdCB1cmwgPSBuZXcgVVJMKHJlcXVlc3QudXJsKTtcbiAqICAgY29uc3QgdG9rZW4gPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgndG9rZW4nKTtcbiAqXG4gKiAgIGlmICghdG9rZW4pIHtcbiAqICAgICByZXR1cm4gbmV3IFJlc3BvbnNlKCdNaXNzaW5nIHRva2VuJywgeyBzdGF0dXM6IDQwMCB9KTtcbiAqICAgfVxuICpcbiAqICAgdHJ5IHtcbiAqICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHJlc3VtZVdlYmhvb2sodG9rZW4sIHJlcXVlc3QpO1xuICogICAgIHJldHVybiByZXNwb25zZTtcbiAqICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAqICAgICByZXR1cm4gbmV3IFJlc3BvbnNlKCdXZWJob29rIG5vdCBmb3VuZCcsIHsgc3RhdHVzOiA0MDQgfSk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzdW1lV2ViaG9vayhcbiAgdG9rZW46IHN0cmluZyxcbiAgcmVxdWVzdDogUmVxdWVzdFxuKTogUHJvbWlzZTxSZXNwb25zZT4ge1xuICAvLyBUMCBvZiB0aGUgaG9vay1yZXN1bWUgVFRSIHdpbmRvdy4gRXZlcnl0aGluZyBiZWxvdyAodGhlIGJ5LXRva2VuIGxvb2t1cCxcbiAgLy8gdGhlIHJ1bi1rZXkgcmVzb2x1dGlvbiBpdCBtYXkgdHJpZ2dlciwgYW5kIHRoZSBgcmVzcG9uZFdpdGhgIHNldHVwKSBpc1xuICAvLyByZWFsIHByb2R1Y2VyLXNpZGUgbGF0ZW5jeSBvbiB0aGlzIHBhdGgsIHNvIHRoZSB3aW5kb3cgaGFzIHRvIG9wZW4gaGVyZVxuICAvLyBhbmQgbm90IGluc2lkZSBgcmVzdW1lSG9va0ltcGxgOyBvdGhlcndpc2Ugd2ViaG9vayByZXN1bWVzIHdvdWxkIHJlcG9ydCBhXG4gIC8vIHN5c3RlbWF0aWNhbGx5IHNob3J0ZXIgdG90YWwgdGhhbiBgcmVzdW1lSG9va2Agb25lcyBpbnRvIHRoZSBzYW1lIG1ldHJpYy5cbiAgY29uc3QgcmVzdW1lUmVxdWVzdGVkQXRNcyA9IERhdGUubm93KCk7XG4gIGNvbnN0IHsgaG9vaywgZW5jcnlwdGlvbktleSB9ID0gYXdhaXQgZ2V0SG9va0J5VG9rZW5XaXRoS2V5KHRva2VuKTtcblxuICAvLyBPbmx5IHdlYmhvb2tzIGNhbiBiZSByZXN1bWVkIHZpYSB0aGUgcHVibGljIGVuZHBvaW50LlxuICAvLyBJZiB0aGUgaG9vayB3YXMgY3JlYXRlZCB2aWEgY3JlYXRlSG9vaygpIChpc1dlYmhvb2sgIT09IHRydWUpLFxuICAvLyB0aHJvdyB0aGUgc2FtZSBcIm5vdCBmb3VuZFwiIGVycm9yIHRoZSB3b3JsZCB3b3VsZCB0aHJvdyBmb3IgYSBtaXNzaW5nXG4gIC8vIHRva2VuLiBUaGlzIHByZXZlbnRzIGxlYWtpbmcgdGhhdCB0aGUgdG9rZW4gaXMgdmFsaWQuXG4gIGlmIChob29rLmlzV2ViaG9vayA9PT0gZmFsc2UpIHtcbiAgICB0aHJvdyBuZXcgSG9va05vdEZvdW5kRXJyb3IodG9rZW4pO1xuICB9XG5cbiAgbGV0IHJlc3BvbnNlOiBSZXNwb25zZSB8IHVuZGVmaW5lZDtcbiAgbGV0IHJlc3BvbnNlUmVhZGFibGU6IFJlYWRhYmxlU3RyZWFtPFJlc3BvbnNlPiB8IHVuZGVmaW5lZDtcbiAgaWYgKFxuICAgIGhvb2subWV0YWRhdGEgJiZcbiAgICB0eXBlb2YgaG9vay5tZXRhZGF0YSA9PT0gJ29iamVjdCcgJiZcbiAgICAncmVzcG9uZFdpdGgnIGluIGhvb2subWV0YWRhdGFcbiAgKSB7XG4gICAgaWYgKGhvb2subWV0YWRhdGEucmVzcG9uZFdpdGggPT09ICdtYW51YWwnKSB7XG4gICAgICBjb25zdCB7IHJlYWRhYmxlLCB3cml0YWJsZSB9ID0gbmV3IFRyYW5zZm9ybVN0cmVhbTxSZXNwb25zZSwgUmVzcG9uc2U+KCk7XG4gICAgICByZXNwb25zZVJlYWRhYmxlID0gcmVhZGFibGU7XG5cbiAgICAgIC8vIFRoZSByZXF1ZXN0IGluc3RhbmNlIGluY2x1ZGVzIHRoZSB3cml0YWJsZSBzdHJlYW0gd2hpY2ggd2lsbCBiZSB1c2VkXG4gICAgICAvLyB0byB3cml0ZSB0aGUgcmVzcG9uc2UgdG8gdGhlIGNsaWVudCBmcm9tIHdpdGhpbiB0aGUgd29ya2Zsb3cgcnVuXG4gICAgICAocmVxdWVzdCBhcyBhbnkpW1dFQkhPT0tfUkVTUE9OU0VfV1JJVEFCTEVdID0gd3JpdGFibGU7XG4gICAgfSBlbHNlIGlmIChob29rLm1ldGFkYXRhLnJlc3BvbmRXaXRoIGluc3RhbmNlb2YgUmVzcG9uc2UpIHtcbiAgICAgIHJlc3BvbnNlID0gaG9vay5tZXRhZGF0YS5yZXNwb25kV2l0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgICBgSW52YWxpZCBcXGByZXNwb25kV2l0aFxcYCB2YWx1ZTogJHtob29rLm1ldGFkYXRhLnJlc3BvbmRXaXRofWAsXG4gICAgICAgIHsgc2x1ZzogRVJST1JfU0xVR1MuV0VCSE9PS19JTlZBTElEX1JFU1BPTkRfV0lUSF9WQUxVRSB9XG4gICAgICApO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBObyBgcmVzcG9uZFdpdGhgIHZhbHVlIGltcGxpZXMgdGhlIGRlZmF1bHQgYmVoYXZpb3Igb2YgcmV0dXJuaW5nIGEgMjAyXG4gICAgcmVzcG9uc2UgPSBuZXcgUmVzcG9uc2UobnVsbCwgeyBzdGF0dXM6IDIwMiB9KTtcbiAgfVxuXG4gIC8vIGBob29rYCB3YXMganVzdCBmZXRjaGVkIHZpYSBgZ2V0SG9va0J5VG9rZW5XaXRoS2V5YCAoYSBmcmVzaCBieS10b2tlblxuICAvLyBsb29rdXApIGFib3ZlLCBzbyBpdHMgcmVzcG9uc2Utb25seSBgcmVzdW1lQ2FwYWJpbGl0aWVzYCByZWZsZWN0cyB0aGUgbGl2ZVxuICAvLyBiYWNrZW5kLiBDYWxsIHRoZSBpbnRlcm5hbCBpbXBsZW1lbnRhdGlvbiB3aXRoIHRoZSBmcmVzaCBhdHRlc3RhdGlvbiBzb1xuICAvLyB0aGUgbGF6eSBwYXRoIHN0YXlzIGF2YWlsYWJsZSB3aXRob3V0IGEgc2Vjb25kIEdFVC4gKFRoZSBwdWJsaWNcbiAgLy8gYHJlc3VtZUhvb2tgIG5ldmVyIHNldHMgdGhpcywgc28gYSBjYWxsZXIgY2Fubm90IGZvcmdlIGl0LilcbiAgYXdhaXQgcmVzdW1lSG9va0ltcGwoXG4gICAgaG9vayxcbiAgICByZXF1ZXN0LFxuICAgIGVuY3J5cHRpb25LZXksXG4gICAgdHJ1ZSxcbiAgICByZXN1bWVSZXF1ZXN0ZWRBdE1zLFxuICAgIGZhbHNlXG4gICk7XG5cbiAgaWYgKHJlc3BvbnNlUmVhZGFibGUpIHtcbiAgICAvLyBXYWl0IGZvciB0aGUgcmVhZGFibGUgc3RyZWFtIHRvIGVtaXQgb25lIGNodW5rLFxuICAgIC8vIHdoaWNoIGlzIHRoZSBgUmVzcG9uc2VgIG9iamVjdFxuICAgIGNvbnN0IHJlYWRlciA9IHJlc3BvbnNlUmVhZGFibGUuZ2V0UmVhZGVyKCk7XG4gICAgY29uc3QgY2h1bmsgPSBhd2FpdCByZWFkZXIucmVhZCgpO1xuICAgIGlmIChjaHVuay52YWx1ZSkge1xuICAgICAgcmVzcG9uc2UgPSBjaHVuay52YWx1ZTtcbiAgICB9XG4gICAgcmVhZGVyLmNhbmNlbCgpO1xuICB9XG5cbiAgaWYgKCFyZXNwb25zZSkge1xuICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcignV29ya2Zsb3cgcnVuIGRpZCBub3Qgc2VuZCBhIHJlc3BvbnNlJywge1xuICAgICAgc2x1ZzogRVJST1JfU0xVR1MuV0VCSE9PS19SRVNQT05TRV9OT1RfU0VOVCxcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiByZXNwb25zZTtcbn1cbiJdfQ==
604
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzdW1lLWhvb2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVudGltZS9yZXN1bWUtaG9vay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsV0FBVyxFQUNYLGlCQUFpQixFQUNqQixlQUFlLEVBQ2Ysb0JBQW9CLEdBQ3JCLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUNMLHlCQUF5QixFQUd6QixtQkFBbUIsRUFDbkIsMkJBQTJCLEVBQzNCLG9CQUFvQixFQUNwQixtQkFBbUIsRUFDbkIsaUNBQWlDLEdBR2xDLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3RFLE9BQU8sRUFDTCx3QkFBd0IsRUFDeEIsb0JBQW9CLEVBRXBCLG1CQUFtQixFQUNuQixNQUFNLEdBQ1AsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUQsT0FBTyxLQUFLLFNBQVMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsS0FBSyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDNUQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNwRCxPQUFPLEVBQUUsYUFBYSxF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LEVBQUUsSUFBSSxFQUFFLG1CQUFtQixDQUFDLENBQUM7SUFFOUUsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3JCLGtEQUFrRDtRQUNsRCxpQ0FBaUM7UUFDakMsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDNUMsTUFBTSxLQUFLLEdBQUcsTUFBTSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDbEMsSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDaEIsUUFBUSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7UUFDekIsQ0FBQztRQUNELE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUNsQixDQUFDO0lBRUQsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2QsTUFBTSxJQUFJLG9CQUFvQixDQUFDLHNDQUFzQyxFQUFFO1lBQ3JFLElBQUksRUFBRSxXQUFXLENBQUMseUJBQXlCO1NBQzVDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgRVJST1JfU0xVR1MsXG4gIEhvb2tOb3RGb3VuZEVycm9yLFxuICBSdW5FeHBpcmVkRXJyb3IsXG4gIFdvcmtmbG93UnVudGltZUVycm9yLFxufSBmcm9tICdAd29ya2Zsb3cvZXJyb3JzJztcbmltcG9ydCB7XG4gIEhPT0tfUkVTVU1FX0RFRFVQX1ZFUlNJT04sXG4gIHR5cGUgSG9vayxcbiAgdHlwZSBIb29rUmVzdW1lQ29udGV4dCxcbiAgaXNMZWdhY3lTcGVjVmVyc2lvbixcbiAgaXNUZXJtaW5hbFdvcmtmbG93UnVuU3RhdHVzLFxuICBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgU1BFQ19WRVJTSU9OX0xFR0FDWSxcbiAgU1BFQ19WRVJTSU9OX1NVUFBPUlRTX0NPTVBSRVNTSU9OLFxuICB0eXBlIFdvcmtmbG93SW52b2tlUGF5bG9hZCxcbiAgdHlwZSBXb3JrZmxvd1J1bixcbn0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB7IG1vbm90b25pY0ZhY3RvcnkgfSBmcm9tICd1bGlkJztcbmltcG9ydCB7IGdldFJ1bkNhcGFiaWxpdGllcyB9IGZyb20gJy4uL2NhcGFiaWxpdGllcy5qcyc7XG5pbXBvcnQgeyBpbXBvcnRLZXkgfSBmcm9tICcuLi9lbmNyeXB0aW9uLmpzJztcbmltcG9ydCB7IHJ1bnRpbWVMb2dnZXIgfSBmcm9tICcuLi9sb2dnZXIuanMnO1xuaW1wb3J0IHsgZGVjb2RlUnVuUHVibGljS2V5IH0gZnJvbSAnLi4vc2VhbGVkLWJveC5qcyc7XG5pbXBvcnQgeyBkZXJpdmVSdW5QYXlsb2FkS2V5cyB9IGZyb20gJy4uL3NlcmlhbGl6YXRpb24vZW5jcnlwdGlvbi5qcyc7XG5pbXBvcnQge1xuICBkZWh5ZHJhdGVTdGVwUmV0dXJuVmFsdWUsXG4gIGh5ZHJhdGVTdGVwQXJndW1lbnRzLFxuICB0eXBlIFBheWxvYWRLZXksXG4gIFNlcmlhbGl6YXRpb25Gb3JtYXQsXG4gIHNlYWxUbyxcbn0gZnJvbSAnLi4vc2VyaWFsaXphdGlvbi5qcyc7XG5pbXBvcnQgeyBXRUJIT09LX1JFU1BPTlNFX1dSSVRBQkxFIH0gZnJvbSAnLi4vc3ltYm9scy5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyaWJ1dGUgZnJvbSAnLi4vdGVsZW1ldHJ5L3NlbWFudGljLWNvbnZlbnRpb25zLmpzJztcbmltcG9ydCB7IGxpbmtUb1RyYWNlQ2FycmllciwgdHJhY2UgfSBmcm9tICcuLi90ZWxlbWV0cnkuanMnO1xuaW1wb3J0IHsgZ2V0V29ybGRMYXp5IH0gZnJvbSAnLi9nZXQtd29ybGQtbGF6eS5qcyc7XG5pbXBvcnQgeyBnZXRXb3JrZmxvd1F1ZXVlTmFtZSB9IGZyb20gJy4vaGVscGVycy5qcyc7XG5pbXBvcnQgeyBzYWZlV2FpdFVudGlsLCB3YWl0ZWRVbnRpbCB9IGZyb20gJy4vd2FpdC11bnRpbC5qcyc7XG5cbi8qKiBNb25vdG9uaWMgVUxJRCBmYWN0b3J5IGZvciBwZXItY2FsbCByZXN1bWUgaWRlbXBvdGVuY3kga2V5cy4gKi9cbmNvbnN0IGdlbmVyYXRlUmVzdW1lSWQgPSBtb25vdG9uaWNGYWN0b3J5KCk7XG5cbi8qKlxuICogSGV4IFNIQS0yNTYgb2YgdGhlIHNlcmlhbGl6ZWQgcmVzdW1lIHBheWxvYWQgYnl0ZXMuIENvbXB1dGVkIG9uY2UgYnkgdGhlXG4gKiBwcm9kdWNlciBhbmQgc2VudCB3aXRoIGl0cyBkdXJhYmxlIGBob29rX3JlY2VpdmVkYCB3cml0ZSBzbyB0cmFuc3BvcnQgYW5kXG4gKiBzbG90IHJldHJpZXMgY29udmVyZ2UgdGhyb3VnaCB0aGUgc2VydmVyJ3MgYChydW5JZCwgcmVzdW1lSWQpYCBjb25zdHJhaW50LlxuICovXG5hc3luYyBmdW5jdGlvbiBjb21wdXRlUmVzdW1lUGF5bG9hZERpZ2VzdChieXRlczogVWludDhBcnJheSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IGRpZ2VzdCA9IGF3YWl0IGNyeXB0by5zdWJ0bGUuZGlnZXN0KCdTSEEtMjU2JywgYnl0ZXMpO1xuICBjb25zdCB2aWV3ID0gbmV3IFVpbnQ4QXJyYXkoZGlnZXN0KTtcbiAgbGV0IGhleCA9ICcnO1xuICBmb3IgKGNvbnN0IGIgb2Ygdmlldykge1xuICAgIGhleCArPSBiLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCAnMCcpO1xuICB9XG4gIHJldHVybiBoZXg7XG59XG5cbmNvbnN0IEhPT0tfV0FLRV9SRVRSWV9ERUxBWVNfTVMgPSBbMjUsIDEwMF0gYXMgY29uc3Q7XG5cbi8qKlxuICogQSB3YWtlIGZhaWx1cmUgd29ydGggcmV0cnlpbmcgaXMgdHJhbnNwb3J0LXNoYXBlZCAobmV0d29yayBlcnJvciwgNXh4LFxuICogdGhyb3R0bGUpLiBBIGRlZmluaXRpdmUgcmVqZWN0aW9uIHdpbGwgbm90IGNoYW5nZSBvbiBhIDI1bXMgcmV0cnksIHNvXG4gKiBzcGVuZGluZyB0aGUgYnVkZ2V0IG9uIGl0IG9ubHkgZGVsYXlzIHRoZSBjYWxsZXIncyBlcnJvci5cbiAqXG4gKiBgQHZlcmNlbC9xdWV1ZWAgZXJyb3JzIGNhcnJ5IG5vIGBzdGF0dXNgIGZpZWxkIOKAlCB0aGV5IGFyZSBiYXJlIGBFcnJvcmBcbiAqIHN1YmNsYXNzZXMgZGlzdGluZ3Vpc2hlZCBieSBgbmFtZWAg4oCUIHNvIGNsYXNzaWZpY2F0aW9uIGNoZWNrcyB0aGUgV29ybGQnc1xuICogZGVwbG95bWVudC11bmF2YWlsYWJsZSBob29rIGZpcnN0IChhIGRlcGxveW1lbnQgdGhlIHF1ZXVlIGNhbm5vdCBkaXNjb3ZlclxuICogd2lsbCBub3QgY29tZSBiYWNrIHdpdGhpbiB0aGlzIGZ1bmN0aW9uJ3MgfjEyNW1zIGJ1ZGdldCksIHRoZW4gYSBudW1lcmljXG4gKiBzdGF0dXMgd2hlbiBvbmUgZXhpc3RzIChub24tVmVyY2VsIHF1ZXVlIGltcGxlbWVudGF0aW9ucyksIHRoZW4gdGhlIHF1ZXVlXG4gKiBjbGllbnQncyBkZWZpbml0aXZlLTR4eCBlcnJvciBuYW1lcy5cbiAqL1xuZnVuY3Rpb24gaXNSZXRyeWFibGVXYWtlRXJyb3IoXG4gIGVycm9yOiB1bmtub3duLFxuICBpc0RlcGxveW1lbnRVbmF2YWlsYWJsZUVycm9yPzogKGVycm9yOiB1bmtub3duKSA9PiBib29sZWFuXG4pOiBib29sZWFuIHtcbiAgaWYgKGlzRGVwbG95bWVudFVuYXZhaWxhYmxlRXJyb3I/LihlcnJvcikpIHJldHVybiBmYWxzZTtcbiAgY29uc3Qgc3RhdHVzID0gKGVycm9yIGFzIHsgc3RhdHVzPzogdW5rbm93bjsgc3RhdHVzQ29kZT86IHVua25vd24gfSkgPz8ge307XG4gIGNvbnN0IGNvZGUgPSBzdGF0dXMuc3RhdHVzID8/IHN0YXR1cy5zdGF0dXNDb2RlO1xuICBpZiAodHlwZW9mIGNvZGUgPT09ICdudW1iZXInKSB7XG4gICAgcmV0dXJuIGNvZGUgPj0gNTAwIHx8IGNvZGUgPT09IDQwOCB8fCBjb2RlID09PSA0Mjk7XG4gIH1cbiAgY29uc3QgbmFtZSA9IChlcnJvciBhcyBFcnJvciB8IG51bGwpPy5uYW1lO1xuICByZXR1cm4gKFxuICAgIG5hbWUgIT09ICdCYWRSZXF1ZXN0RXJyb3InICYmXG4gICAgbmFtZSAhPT0gJ1VuYXV0aG9yaXplZEVycm9yJyAmJlxuICAgIG5hbWUgIT09ICdGb3JiaWRkZW5FcnJvcidcbiAgKTtcbn1cblxuLy8gQSBwdWJsaXNoIG1heSBzdWNjZWVkIGV2ZW4gd2hlbiBpdHMgcmVzcG9uc2UgaXMgbG9zdCwgc28gYSByZXRyeSBjYW5cbi8vIGVucXVldWUgYSBkdXBsaWNhdGUgd2FrZS4gVGhhdCBpcyBoYXJtbGVzczogdGhlIGV2ZW50IGlzIGFscmVhZHkgZHVyYWJsZSxcbi8vIGFuZCBkZXRlcm1pbmlzdGljIHJlcGxheSBtYWtlcyBhIHNlY29uZCBkZWxpdmVyeSBvZiB0aGUgc2FtZSBydW4gYSBuby1vcC5cbmFzeW5jIGZ1bmN0aW9uIHB1Ymxpc2hIb29rV2FrZVdpdGhSZXRyeShcbiAgcHVibGlzaDogKCkgPT4gUHJvbWlzZTx1bmtub3duPixcbiAgaXNEZXBsb3ltZW50VW5hdmFpbGFibGVFcnJvcj86IChlcnJvcjogdW5rbm93bikgPT4gYm9vbGVhblxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGxldCBsYXN0RXJyb3I6IHVua25vd247XG4gIGZvciAoXG4gICAgbGV0IGF0dGVtcHQgPSAwO1xuICAgIGF0dGVtcHQgPD0gSE9PS19XQUtFX1JFVFJZX0RFTEFZU19NUy5sZW5ndGg7XG4gICAgYXR0ZW1wdCsrXG4gICkge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBwdWJsaXNoKCk7XG4gICAgICByZXR1cm47XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxhc3RFcnJvciA9IGVycm9yO1xuICAgICAgaWYgKCFpc1JldHJ5YWJsZVdha2VFcnJvcihlcnJvciwgaXNEZXBsb3ltZW50VW5hdmFpbGFibGVFcnJvcikpIGJyZWFrO1xuICAgICAgY29uc3QgZGVsYXlNcyA9IEhPT0tfV0FLRV9SRVRSWV9ERUxBWVNfTVNbYXR0ZW1wdF07XG4gICAgICBpZiAoZGVsYXlNcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIGRlbGF5TXMpKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBUaGUgd2FrZSBvbmx5IHJ1bnMgYWZ0ZXIgdGhlIGhvb2tfcmVjZWl2ZWQgd3JpdGUgY29tbWl0dGVkLCBzbyBhIHdha2VcbiAgLy8gZmFpbHVyZSBoZXJlIGlzIG5lY2Vzc2FyaWx5IFwiZHVyYWJsZSBidXQgbm90IHlldCBkaXNwYXRjaGVkXCI6IHRoZSBldmVudFxuICAvLyBzdXJ2aXZlcywgYW5kIGFueSBsYXRlciB3YWtlIG9mIHRoZSBydW4gZGVsaXZlcnMgaXQuIERvIG5vdCBsZXQgYSBxdWV1ZVxuICAvLyBpbXBsZW1lbnRhdGlvbiByZXVzZSBIb29rTm90Rm91bmRFcnJvciBhbmQgYWNjaWRlbnRhbGx5IGltcGx5IHRoYXQgbm9cbiAgLy8gaG9va19yZWNlaXZlZCBleGlzdHMuXG4gIGlmIChIb29rTm90Rm91bmRFcnJvci5pcyhsYXN0RXJyb3IpKSB7XG4gICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgJ1RoZSBob29rIHJlc3VtZSB3YXMgY29tbWl0dGVkLCBidXQgaXRzIHdvcmtmbG93IHdha2UgY291bGQgbm90IGJlIHB1Ymxpc2hlZCcsXG4gICAgICB7IGNhdXNlOiBsYXN0RXJyb3IgfVxuICAgICk7XG4gIH1cbiAgdGhyb3cgbGFzdEVycm9yO1xufVxuXG4vKipcbiAqIFRoZSByZXN1bWUgY29udGV4dCBmb3IgYSBob29rIHBsdXMgd2hlcmUgaXQgY2FtZSBmcm9tLiBgcnVuYCBpcyBwcmVzZW50IG9ubHlcbiAqIG9uIHRoZSBmYWxsYmFjayBwYXRoIChwcmUtYHJlc3VtZUNvbnRleHRgIGhvb2tzKSwgd2hlcmUgaXQgYWxzbyBjYXJyaWVzIHRoZVxuICogcnVuJ3MgbXV0YWJsZSBzdGF0dXMgZm9yIHRoZSB0ZXJtaW5hbC1ydW4gY2hlY2suIEtleSByZXNvbHV0aW9uIGlzIGtlcHRcbiAqIHNlcGFyYXRlIHNvIGNhbGxlcnMgY2FuIGdhdGUgaXQgYmVoaW5kIHRoYXQgY2hlY2suXG4gKi9cbmludGVyZmFjZSBIb29rUmVzdW1lSW5mbyB7XG4gIHJlc3VtZUNvbnRleHQ6IEhvb2tSZXN1bWVDb250ZXh0O1xuICBzb3VyY2U6ICdob29rJyB8ICdydW5fZmFsbGJhY2snO1xuICBydW4/OiBXb3JrZmxvd1J1bjtcbn1cblxuLyoqIERlcml2ZSBhIHJlc3VtZSBjb250ZXh0IGZyb20gYSBmdWxsIHJ1biAoZmFsbGJhY2sgZm9yIHByZS1gcmVzdW1lQ29udGV4dGAgaG9va3MpLiAqL1xuZnVuY3Rpb24gcmVzdW1lQ29udGV4dEZyb21SdW4ocnVuOiBXb3JrZmxvd1J1bik6IEhvb2tSZXN1bWVDb250ZXh0IHtcbiAgY29uc3QgY29yZVZlcnNpb24gPSBydW4uZXhlY3V0aW9uQ29udGV4dD8ud29ya2Zsb3dDb3JlVmVyc2lvbjtcbiAgY29uc3QgdHJhY2VDYXJyaWVyID0gcnVuLmV4ZWN1dGlvbkNvbnRleHQ/LnRyYWNlQ2FycmllcjtcbiAgY29uc3QgaG9va1Jlc3VtZUlucHV0VmVyc2lvbiA9IHJ1bi5leGVjdXRpb25Db250ZXh0Py5ob29rUmVzdW1lSW5wdXRWZXJzaW9uO1xuICByZXR1cm4ge1xuICAgIGRlcGxveW1lbnRJZDogcnVuLmRlcGxveW1lbnRJZCxcbiAgICB3b3JrZmxvd05hbWU6IHJ1bi53b3JrZmxvd05hbWUsXG4gICAgcnVuU3BlY1ZlcnNpb246IHJ1bi5zcGVjVmVyc2lvbixcbiAgICB3b3JrZmxvd0NvcmVWZXJzaW9uOlxuICAgICAgdHlwZW9mIGNvcmVWZXJzaW9uID09PSAnc3RyaW5nJyA/IGNvcmVWZXJzaW9uIDogdW5kZWZpbmVkLFxuICAgIHRyYWNlQ2FycmllcjpcbiAgICAgIHRyYWNlQ2FycmllciAmJiB0eXBlb2YgdHJhY2VDYXJyaWVyID09PSAnb2JqZWN0J1xuICAgICAgICA/ICh0cmFjZUNhcnJpZXIgYXMgSG9va1Jlc3VtZUNvbnRleHRbJ3RyYWNlQ2FycmllciddKVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICBlbmNyeXB0aW9uUHVibGljS2V5OiBydW4uZW5jcnlwdGlvblB1YmxpY0tleSxcbiAgICBob29rUmVzdW1lSW5wdXRWZXJzaW9uOlxuICAgICAgdHlwZW9mIGhvb2tSZXN1bWVJbnB1dFZlcnNpb24gPT09ICdudW1iZXInXG4gICAgICAgID8gaG9va1Jlc3VtZUlucHV0VmVyc2lvblxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgfTtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHJlc3VtZSBjb250ZXh0IGZvciBhIGhvb2suIFVzZXMgdGhlIHN0b3JlZCBgcmVzdW1lQ29udGV4dGAgd2hlblxuICogcHJlc2VudCAoZmFzdCBwYXRoLCBubyBydW4gcmVhZCk7IG90aGVyd2lzZSBmZXRjaGVzIHRoZSBydW4gYW5kIHN5bnRoZXNpemVzXG4gKiBpdC4gRG9lcyBOT1QgcmVzb2x2ZSB0aGUgZW5jcnlwdGlvbiBrZXk7IGNhbGxlcnMgZG8gdGhhdCBzZXBhcmF0ZWx5LiBPbmx5XG4gKiB0aGUgZmFsbGJhY2sgcGF0aCBjYW4gZ2F0ZSBrZXkgd29yayBiZWhpbmQgYSBsb2NhbCB0ZXJtaW5hbC1ydW4gY2hlY2sgKGl0XG4gKiBoYXMgdGhlIGZldGNoZWQgcnVuKTsgdGhlIGZhc3QgcGF0aCdzIHN0b3JlZCBjb250ZXh0IGNhcnJpZXMgbm8gc3RhdHVzLCBzb1xuICogc2VhbC9zZXJpYWxpemF0aW9uIHdvcmsgbWF5IHJ1biBiZWZvcmUgdGhlIHJlY2VpdmluZyBzaWRlIHJlamVjdHNcbiAqIGBob29rX3JlY2VpdmVkYCBmb3IgYW4gZW5kZWQgcnVuLlxuICovXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlSG9va1Jlc3VtZUluZm8oaG9vazogSG9vayk6IFByb21pc2U8SG9va1Jlc3VtZUluZm8+IHtcbiAgaWYgKGhvb2sucmVzdW1lQ29udGV4dCkge1xuICAgIHJldHVybiB7IHJlc3VtZUNvbnRleHQ6IGhvb2sucmVzdW1lQ29udGV4dCwgc291cmNlOiAnaG9vaycgfTtcbiAgfVxuICBjb25zdCBydW4gPSBhd2FpdCAoYXdhaXQgZ2V0V29ybGRMYXp5KCkpLnJ1bnMuZ2V0KGhvb2sucnVuSWQpO1xuICByZXR1cm4ge1xuICAgIHJlc3VtZUNvbnRleHQ6IHJlc3VtZUNvbnRleHRGcm9tUnVuKHJ1biksXG4gICAgc291cmNlOiAncnVuX2ZhbGxiYWNrJyxcbiAgICBydW4sXG4gIH07XG59XG5cbi8qKlxuICogUmVzb2x2ZSB0aGUgcnVuJ3Mgc3ltbWV0cmljIGtleSBmb3IgYSBwYXlsb2FkIFdSSVRFLCBhcyBhIGJhcmUgYENyeXB0b0tleWBcbiAqIChgaW1wb3J0S2V5YCk6IHRoZSBgZW5jcmAgd3JpdGUgZmFsbGJhY2sgdXNlZCB3aGVuIHRoZSBydW4gcHVibGlzaGVkIG5vXG4gKiBwdWJsaWMga2V5IHRvIHNlYWwgdG8uIFdyaXRpbmcgbmVlZHMgb25seSB0aGUgQUVTIGtleSwgbm90IHRoZSByZWFkLXNpZGVcbiAqIGtleXBhaXIuIE9uIHRoZSBmYXN0IHBhdGggdGhpcyBuZWVkcyBvbmx5IGBydW5JZGAgKyBgZGVwbG95bWVudElkYCAobm8gcnVuXG4gKiBlbnRpdHkpOyBvbiB0aGUgZmFsbGJhY2sgcGF0aCB0aGUgYWxyZWFkeSBmZXRjaGVkIHJ1biBpcyByZXVzZWQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVIb29rRW5jcnlwdGlvbktleShcbiAgaG9vazogSG9vayxcbiAgaW5mbzogSG9va1Jlc3VtZUluZm9cbik6IFByb21pc2U8QXdhaXRlZDxSZXR1cm5UeXBlPHR5cGVvZiBpbXBvcnRLZXk+PiB8IHVuZGVmaW5lZD4ge1xuICBjb25zdCB3b3JsZCA9IGF3YWl0IGdldFdvcmxkTGF6eSgpO1xuICBjb25zdCByYXdLZXkgPSBpbmZvLnJ1blxuICAgID8gYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKGluZm8ucnVuKVxuICAgIDogYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKGhvb2sucnVuSWQsIHtcbiAgICAgICAgZGVwbG95bWVudElkOiBpbmZvLnJlc3VtZUNvbnRleHQuZGVwbG95bWVudElkLFxuICAgICAgfSk7XG4gIHJldHVybiByYXdLZXkgPyBhd2FpdCBpbXBvcnRLZXkocmF3S2V5KSA6IHVuZGVmaW5lZDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0SG9va0J5VG9rZW5XaXRoS2V5KHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPHtcbiAgaG9vazogSG9vaztcbiAgZW5jcnlwdGlvbktleTogUGF5bG9hZEtleSB8IHVuZGVmaW5lZDtcbn0+IHtcbiAgY29uc3Qgd29ybGQgPSBhd2FpdCBnZXRXb3JsZExhenkoKTtcbiAgY29uc3QgaG9vayA9IGF3YWl0IHdvcmxkLmhvb2tzLmdldEJ5VG9rZW4odG9rZW4pO1xuXG4gIC8vIE9ubHkgYSBob29rIHRoYXQgYWN0dWFsbHkgY2FycmllcyBtZXRhZGF0YSBuZWVkcyB0aGUgcnVuJ3Mga2V5IHJlc29sdmVkXG4gIC8vIGhlcmU6IGh5ZHJhdGluZyB0aGF0IG1ldGFkYXRhIGlzIGEgUkVBRCwgc28gZGVyaXZlIHRoZSBmdWxsIFJ1blBheWxvYWRLZXlzXG4gIC8vICh3aGljaCBvcGVucyBzZWFsZWQgYGVuY3BgIG1ldGFkYXRhLCBub3QganVzdCBzeW1tZXRyaWMgYGVuY3JgKS4gVGhlIGNvbW1vblxuICAvLyBkZWZhdWx0IHdlYmhvb2sgKGNyZWF0ZVdlYmhvb2soKSB3aXRoIG5vIGByZXNwb25kV2l0aGApIHN0b3JlcyBub1xuICAvLyBtZXRhZGF0YSwgc28gaXQgc2tpcHMgdGhpcyBlbnRpcmVseTogbm8gfjM1MG1zIGBydW4ta2V5YCBBUEkgcm91bmQgdHJpcCxcbiAgLy8gYW5kLCBjcnVjaWFsbHksIG5vIHJlc29sdmVkIGtleSBoYW5kZWQgdG8gYHJlc3VtZUhvb2tgLCBsZWF2aW5nIGl0IGZyZWUgdG9cbiAgLy8gc2VhbCB0aGUgcGF5bG9hZCB0byB0aGUgcnVuJ3MgcHVibGlzaGVkIHB1YmxpYyBrZXkgaW5zdGVhZC4gTWV0YWRhdGEtXG4gIC8vIGJlYXJpbmcgd2ViaG9va3Mgc3RpbGwgbGVnaXRpbWF0ZWx5IHBheSBvbmUgbG9va3VwIHRvIGh5ZHJhdGUuXG4gIGxldCBlbmNyeXB0aW9uS2V5OiBQYXlsb2FkS2V5IHwgdW5kZWZpbmVkO1xuICBpZiAodHlwZW9mIGhvb2subWV0YWRhdGEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgY29uc3QgaW5mbyA9IGF3YWl0IHJlc29sdmVIb29rUmVzdW1lSW5mbyhob29rKTtcbiAgICAvLyBPbiB0aGUgZmFzdCBwYXRoIHRoaXMgcmVzb2x2ZXMgdGhlIGtleSBieSBydW5JZCArIGRlcGxveW1lbnRJZCAobm8gcnVuXG4gICAgLy8gcmVhZCk7IG9uIHRoZSBmYWxsYmFjayBwYXRoIGl0IHJldXNlcyB0aGUgYWxyZWFkeS1mZXRjaGVkIHJ1bi5cbiAgICBjb25zdCByYXdLZXkgPSBpbmZvLnJ1blxuICAgICAgPyBhd2FpdCB3b3JsZC5nZXRFbmNyeXB0aW9uS2V5Rm9yUnVuPy4oaW5mby5ydW4pXG4gICAgICA6IGF3YWl0IHdvcmxkLmdldEVuY3J5cHRpb25LZXlGb3JSdW4/Lihob29rLnJ1bklkLCB7XG4gICAgICAgICAgZGVwbG95bWVudElkOiBpbmZvLnJlc3VtZUNvbnRleHQuZGVwbG95bWVudElkLFxuICAgICAgICB9KTtcbiAgICBlbmNyeXB0aW9uS2V5ID0gcmF3S2V5ID8gYXdhaXQgZGVyaXZlUnVuUGF5bG9hZEtleXMocmF3S2V5KSA6IHVuZGVmaW5lZDtcbiAgICBob29rLm1ldGFkYXRhID0gYXdhaXQgaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gICAgICBob29rLm1ldGFkYXRhIGFzIGFueSxcbiAgICAgIGhvb2sucnVuSWQsXG4gICAgICBlbmNyeXB0aW9uS2V5XG4gICAgKTtcbiAgfVxuICByZXR1cm4geyBob29rLCBlbmNyeXB0aW9uS2V5IH07XG59XG5cbi8qKlxuICogR2V0IHRoZSBob29rIGJ5IHRva2VuIHRvIGZpbmQgdGhlIGFzc29jaWF0ZWQgd29ya2Zsb3cgcnVuLFxuICogYW5kIGh5ZHJhdGUgdGhlIGBtZXRhZGF0YWAgcHJvcGVydHkgaWYgaXQgd2FzIHNldCBmcm9tIHdpdGhpblxuICogdGhlIHdvcmtmbG93IHJ1bi5cbiAqXG4gKiBBIEhvb2sga2VwdCBieSBtaW5pbXVtIHJldGVudGlvbiByZW1haW5zIGF2YWlsYWJsZSBoZXJlIGFmdGVyIGl0cyBydW4gZW5kcyxcbiAqIGJ1dCBjYW5ub3QgYmUgcmVzdW1lZC5cbiAqXG4gKiBAcGFyYW0gdG9rZW4gLSBUaGUgdW5pcXVlIHRva2VuIGlkZW50aWZ5aW5nIHRoZSBob29rXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRIb29rQnlUb2tlbih0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxIb29rPiB7XG4gIGNvbnN0IHsgaG9vayB9ID0gYXdhaXQgZ2V0SG9va0J5VG9rZW5XaXRoS2V5KHRva2VuKTtcbiAgcmV0dXJuIGhvb2s7XG59XG5cbi8qKlxuICogVGhlIHJlc3VsdCBvZiB7QGxpbmsgcmVzdW1lSG9va306IGEge0BsaW5rIEhvb2t9IGF1Z21lbnRlZCB3aXRoIGFuIG9wdGlvbmFsXG4gKiByZXNpbGllbmNlIHNpZ25hbC5cbiAqXG4gKiBgcmVzaWxpZW50UmVzdW1lYCBpcyByZXRhaW5lZCBmb3Igc291cmNlIGNvbXBhdGliaWxpdHkgYW5kIGlzIG5ldmVyIHNldC5cbiAqIGByZXN1bWVIb29rKClgIG5vdyByZXF1aXJlcyB0aGUgZHVyYWJsZSBgaG9va19yZWNlaXZlZGAgd3JpdGUgYW5kIHdvcmtmbG93XG4gKiB3YWtlIHRvIGJvdGggc3VjY2VlZCBiZWZvcmUgaXQgcmVzb2x2ZXMuIFRyZWF0IHRoZSByZXN1bHQgYXMgYSBwbGFpblxuICoge0BsaW5rIEhvb2t9LlxuICovXG5leHBvcnQgdHlwZSBSZXN1bWVkSG9vayA9IEhvb2sgJiB7IHJlc2lsaWVudFJlc3VtZT86IGJvb2xlYW4gfTtcblxuLyoqXG4gKiBSZXN1bWVzIGEgd29ya2Zsb3cgcnVuIGJ5IHNlbmRpbmcgYSBwYXlsb2FkIHRvIGEgaG9vayBpZGVudGlmaWVkIGJ5IGl0cyB0b2tlbi5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBleHRlcm5hbGx5IChlLmcuLCBmcm9tIGFuIEFQSSByb3V0ZSBvciBzZXJ2ZXIgYWN0aW9uKVxuICogdG8gc2VuZCBkYXRhIHRvIGEgaG9vayBhbmQgcmVzdW1lIHRoZSBhc3NvY2lhdGVkIHdvcmtmbG93IHJ1bi5cbiAqXG4gKiBSZXNvbHZpbmcgbWVhbnMgQk9USCB0aGF0IHRoZSBgaG9va19yZWNlaXZlZGAgZXZlbnQgaXMgZHVyYWJseSByZWNvcmRlZCBpblxuICogdGhlIHJ1bidzIGV2ZW50IGxvZyBhbmQgdGhhdCB0aGUgd29ya2Zsb3cgd2FrZSB3YXMgYWNjZXB0ZWQgYnkgdGhlIHF1ZXVlLCBpblxuICogdGhhdCBvcmRlci4gQSB7QGxpbmsgSG9va05vdEZvdW5kRXJyb3J9IG1lYW5zIHRoaXMgaW52b2NhdGlvbiBjb21taXR0ZWQgbm9cbiAqIGV2ZW50LiBBbnkgb3RoZXIgZXJyb3IgYWZ0ZXIgdGhlIHdyaXRlIGlzIGFtYmlndW91cyBvbmx5IGluIGRpc3BhdGNoLCBuZXZlclxuICogaW4gZHVyYWJpbGl0eTogdGhlIGV2ZW50IG1heSBhbHJlYWR5IGJlIGNvbW1pdHRlZCwgYW5kIGEgbGF0ZXIgd2FrZSBvZiB0aGVcbiAqIHJ1biAoZnJvbSBhbnkgc291cmNlKSB3aWxsIGRlbGl2ZXIgaXQuXG4gKlxuICogUHJlZmVyIHBhc3NpbmcgdGhlIHRva2VuIHN0cmluZyBvdmVyIGEgY2FjaGVkIHtAbGluayBIb29rfSBvYmplY3QuIEEgdG9rZW5cbiAqIGlzIGxvb2tlZCB1cCBmcmVzaCwgc28gdGhlIGxpdmUgYmFja2VuZCBjYW4gYXR0ZXN0IGl0cyBhdG9taWMgcmVzdW1lIGNsYWltXG4gKiBhbmQgdGhlIGR1cmFibGUgd3JpdGUgYmVjb21lcyBpZGVtcG90ZW50LW9uLXJldHJ5ICh0cmFuc3BvcnQgcmV0cmllcyBvZiB0aGVcbiAqIHNhbWUgd3JpdGUgY29udmVyZ2Ugb24gb25lIGV2ZW50KS4gQSBzdXBwbGllZCBIb29rIG9iamVjdCBtYXkgY2FycnkgYSBzdGFsZVxuICogYXR0ZXN0YXRpb24sIHNvIGl0IGlzIGRlbGliZXJhdGVseSBpZ25vcmVkIGFuZCB0aGUgd3JpdGUgaXMgY2xhaW0tbGVzcyDigJRcbiAqIG1lYW5pbmcgYSBsb3N0IHJlc3BvbnNlIGNhbm5vdCBiZSByZXRyaWVkIHNhZmVseTogcmV0cnlpbmcgYXQgdGhlXG4gKiBhcHBsaWNhdGlvbiBsZXZlbCBtaW50cyBhIGZyZXNoIGNsYWltIGFuZCBjYW4gY29tbWl0IGEgc2Vjb25kXG4gKiBgaG9va19yZWNlaXZlZGAuXG4gKlxuICogQHBhcmFtIHRva2VuT3JIb29rIC0gVGhlIHVuaXF1ZSB0b2tlbiBpZGVudGlmeWluZyB0aGUgaG9vaywgb3IgdGhlIGhvb2sgb2JqZWN0IGl0c2VsZlxuICogQHBhcmFtIHBheWxvYWQgLSBUaGUgZGF0YSBwYXlsb2FkIHRvIHNlbmQgdG8gdGhlIGhvb2tcbiAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSB7QGxpbmsgUmVzdW1lZEhvb2t9XG4gKiBAdGhyb3dzIHtIb29rTm90Rm91bmRFcnJvcn0gSWYgdGhlIEhvb2sgZG9lcyBub3QgZXhpc3Qgb3IgaXRzIHJ1biBoYXMgZW5kZWRcbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqIGBgYHRzXG4gKiAvLyBJbiBhbiBBUEkgcm91dGVcbiAqIGltcG9ydCB7IHJlc3VtZUhvb2sgfSBmcm9tICdAd29ya2Zsb3cvY29yZS9ydW50aW1lJztcbiAqXG4gKiBleHBvcnQgYXN5bmMgZnVuY3Rpb24gUE9TVChyZXF1ZXN0OiBSZXF1ZXN0KSB7XG4gKiAgIGNvbnN0IHsgdG9rZW4sIGRhdGEgfSA9IGF3YWl0IHJlcXVlc3QuanNvbigpO1xuICpcbiAqICAgdHJ5IHtcbiAqICAgICBjb25zdCBob29rID0gYXdhaXQgcmVzdW1lSG9vayh0b2tlbiwgZGF0YSk7XG4gKiAgICAgcmV0dXJuIFJlc3BvbnNlLmpzb24oeyBydW5JZDogaG9vay5ydW5JZCB9KTtcbiAqICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAqICAgICByZXR1cm4gbmV3IFJlc3BvbnNlKCdIb29rIG5vdCBmb3VuZCcsIHsgc3RhdHVzOiA0MDQgfSk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzdW1lSG9vazxUID0gYW55PihcbiAgdG9rZW5Pckhvb2s6IHN0cmluZyB8IEhvb2ssXG4gIHBheWxvYWQ6IFQsXG4gIGVuY3J5cHRpb25LZXlPdmVycmlkZT86IFBheWxvYWRLZXlcbik6IFByb21pc2U8UmVzdW1lZEhvb2s+IHtcbiAgLy8gUHVibGljIGVudHJ5IHBvaW50LiBJdCBuZXZlciBhdHRlc3RzIGhvb2sgZnJlc2huZXNzLCBzbyBhIEhvb2sgb2JqZWN0XG4gIC8vIHN1cHBsaWVkIGhlcmUgKHdoaWNoIG1heSBjYXJyeSBhIGByZXN1bWVDYXBhYmlsaXRpZXNgIGNhY2hlZCBiZWZvcmUgYVxuICAvLyBzZXJ2ZXIgcm9sbGJhY2sgb3Iga2lsbCBzd2l0Y2gpIGlzIGlnbm9yZWQgYnkgdGhlIGR5bmFtaWMtZGVkdXAgZ2F0ZSBhbmRcbiAgLy8gZmFpbHMgY2xvc2VkIHRvIGEgcGxhaW4sIGNsYWltLWxlc3Mgd3JpdGUuIE9ubHkgYHJlc3VtZVdlYmhvb2tgLCB3aGljaFxuICAvLyBmZXRjaGVzIHRoZSBob29rIGJ5IHRva2VuIGluLWxpbmUgZHVyaW5nIHRoZSBzYW1lIHJlc3VtZSwgcmVhY2hlcyB0aGVcbiAgLy8gaW50ZXJuYWwgaW1wbGVtZW50YXRpb24gd2l0aCB0aGUgZnJlc2ggYXR0ZXN0YXRpb24gc2V0LiBLZWVwaW5nIHRoZVxuICAvLyBmcmVzaG5lc3MgZmxhZyBvZmYgdGhlIGV4cG9ydGVkIHNpZ25hdHVyZSBwcmV2ZW50cyBhIGNhbGxlciBmcm9tIHBhc3NpbmcgYVxuICAvLyBzdGFsZSBIb29rIHBsdXMgYHRydWVgIGFuZCByZWFjdGl2YXRpbmcgZHluYW1pYyBkZWR1cCBhZ2FpbnN0IGFcbiAgLy8gcm9sbGVkLWJhY2sgYmFja2VuZC5cbiAgLy9cbiAgLy8gVDAgb2YgdGhlIGhvb2stcmVzdW1lIFRUUiB3aW5kb3cgaXMgdGFrZW4gSEVSRSwgYXQgdGhlIHB1YmxpYyBlbnRyeSBwb2ludCxcbiAgLy8gcmF0aGVyIHRoYW4gaW5zaWRlIHRoZSBpbXBsZW1lbnRhdGlvbjsgc2VlIHRoZSBwYXJhbWV0ZXIncyBkb2MgY29tbWVudC5cbiAgcmV0dXJuIHJlc3VtZUhvb2tJbXBsKFxuICAgIHRva2VuT3JIb29rLFxuICAgIHBheWxvYWQsXG4gICAgZW5jcnlwdGlvbktleU92ZXJyaWRlLFxuICAgIGZhbHNlLFxuICAgIERhdGUubm93KClcbiAgKTtcbn1cblxuLyoqXG4gKiBJbnRlcm5hbCBpbXBsZW1lbnRhdGlvbiBvZiB7QGxpbmsgcmVzdW1lSG9va30uIE5PVCBleHBvcnRlZDogdGhlXG4gKiBgaG9va0ZyZXNobHlMb29rZWRVcGAgYXR0ZXN0YXRpb24gbXVzdCBuZXZlciBiZSByZWFjaGFibGUgYnkgcHVibGljIGNhbGxlcnNcbiAqIChzZWUgdGhlIHdyYXBwZXIgYWJvdmUpLlxuICpcbiAqIEBwYXJhbSBob29rRnJlc2hseUxvb2tlZFVwIC0gQXR0ZXN0cyB0aGF0IGEgc3VwcGxpZWQgSG9vayBvYmplY3Qgd2FzIGZldGNoZWRcbiAqICAgYnkgdG9rZW4gZHVyaW5nIFRISVMgcmVzdW1lLCBzbyBpdHMgcmVzcG9uc2Utb25seSBgcmVzdW1lQ2FwYWJpbGl0aWVzYFxuICogICByZWZsZWN0cyB0aGUgbGl2ZSBiYWNrZW5kIGFuZCBtYXkgYmUgdHJ1c3RlZCBmb3IgdGhlIGR5bmFtaWMtZGVkdXAgZ2F0ZS5cbiAqICAgQSB0b2tlbiBzdHJpbmcgaXMgYWx3YXlzIGZldGNoZWQgZnJlc2ggaGVyZSwgc28gaXQgaXMgaW1wbGljaXRseSBmcmVzaC5cbiAqIEBwYXJhbSByZXN1bWVSZXF1ZXN0ZWRBdE1zIC0gVDAgb2YgdGhlIGhvb2stcmVzdW1lIFRUUiB3aW5kb3cgKHNlZVxuICogICBydW50aW1lL3Jlc3VtZS1sYXRlbmN5LnRzKSwgc3RhbXBlZCBieSB0aGUgUFVCTElDIGVudHJ5IHBvaW50IHRoZSBjYWxsZXJcbiAqICAgdXNlZC4gSXQgaXMgYSBwYXJhbWV0ZXIgcmF0aGVyIHRoYW4gYSBsb2NhbCBiZWNhdXNlIGByZXN1bWVXZWJob29rYCBkb2VzXG4gKiAgIHJlYWwgd29yayBiZWZvcmUgaXQgZ2V0cyBoZXJlICh0aGUgYnktdG9rZW4gbG9va3VwLCB0aGUgcnVuLWtleVxuICogICByZXNvbHV0aW9uIHRoYXQgaHlkcmF0ZXMgaG9vayBtZXRhZGF0YSwgYW5kIHRoZSBgcmVzcG9uZFdpdGhgIHNldHVwKSBhbmRcbiAqICAgc3RhbXBpbmcgbG9jYWxseSB3b3VsZCBzaWxlbnRseSBleGNsdWRlIGFsbCBvZiBpdCwgc28gdGhlIHR3byBlbnRyeSBwb2ludHNcbiAqICAgd291bGQgcmVwb3J0IHRoZSBzYW1lIG1ldHJpYyBvdmVyIGRpZmZlcmVudCB3aW5kb3dzLlxuICovXG5hc3luYyBmdW5jdGlvbiByZXN1bWVIb29rSW1wbDxUID0gYW55PihcbiAgdG9rZW5Pckhvb2s6IHN0cmluZyB8IEhvb2ssXG4gIHBheWxvYWQ6IFQsXG4gIGVuY3J5cHRpb25LZXlPdmVycmlkZTogUGF5bG9hZEtleSB8IHVuZGVmaW5lZCxcbiAgaG9va0ZyZXNobHlMb29rZWRVcDogYm9vbGVhbixcbiAgcmVzdW1lUmVxdWVzdGVkQXRNczogbnVtYmVyXG4pOiBQcm9taXNlPFJlc3VtZWRIb29rPiB7XG4gIHJldHVybiBhd2FpdCB3YWl0ZWRVbnRpbCgoKSA9PiB7XG4gICAgcmV0dXJuIHRyYWNlKCdob29rLnJlc3VtZScsIGFzeW5jIChzcGFuKSA9PiB7XG4gICAgICBjb25zdCB3b3JsZCA9IGF3YWl0IGdldFdvcmxkTGF6eSgpO1xuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBzdXBwbGllZFRva2VuID0gdHlwZW9mIHRva2VuT3JIb29rID09PSAnc3RyaW5nJztcbiAgICAgICAgY29uc3QgaG9vazogSG9vayA9IHN1cHBsaWVkVG9rZW5cbiAgICAgICAgICA/IGF3YWl0IHdvcmxkLmhvb2tzLmdldEJ5VG9rZW4odG9rZW5Pckhvb2spXG4gICAgICAgICAgOiB0b2tlbk9ySG9vaztcbiAgICAgICAgLy8gVGhlIGR5bmFtaWMsIHJlc3BvbnNlLW9ubHkgYHJlc3VtZUNhcGFiaWxpdGllc2AgbWF5IG9ubHkgYmUgdHJ1c3RlZFxuICAgICAgICAvLyB3aGVuIGl0IGNhbWUgZnJvbSBhIGJ5LXRva2VuIGxvb2t1cCBwZXJmb3JtZWQgZHVyaW5nIHRoaXMgcmVzdW1lLlxuICAgICAgICBjb25zdCBob29rUmVzdW1lQ2FwYWJpbGl0aWVzQXJlRnJlc2ggPVxuICAgICAgICAgIHN1cHBsaWVkVG9rZW4gfHwgaG9va0ZyZXNobHlMb29rZWRVcDtcblxuICAgICAgICBjb25zdCBpbmZvID0gYXdhaXQgcmVzb2x2ZUhvb2tSZXN1bWVJbmZvKGhvb2spO1xuICAgICAgICBjb25zdCB7IHJlc3VtZUNvbnRleHQgfSA9IGluZm87XG5cbiAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgLi4uQXR0cmlidXRlLkhvb2tUb2tlbihob29rLnRva2VuKSxcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuSG9va0lkKGhvb2suaG9va0lkKSxcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dSdW5JZChob29rLnJ1bklkKSxcbiAgICAgICAgICAnd29ya2Zsb3cuaG9vay5yZXN1bWVfY29udGV4dF9zb3VyY2UnOiBpbmZvLnNvdXJjZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gVGhlIHN0b3JlZCBgcmVzdW1lQ29udGV4dGAgaW50ZW50aW9uYWxseSBvbWl0cyB0aGUgcnVuJ3MgbXV0YWJsZVxuICAgICAgICAvLyBzdGF0dXMsIHNvIHRoaXMgZWFybHkgY2xpZW50LXNpZGUgcmVqZWN0aW9uIG9ubHkgcnVucyBvbiB0aGVcbiAgICAgICAgLy8gZmFsbGJhY2sgcGF0aCAod2hpY2ggZmV0Y2hlZCB0aGUgcnVuKS4gT24gdGhlIGZhc3QgcGF0aCB0aGUgdGVybWluYWxcbiAgICAgICAgLy8gY2hlY2sgaGFwcGVucyBzZXJ2ZXItc2lkZTogYGhvb2tfcmVjZWl2ZWRgIGFnYWluc3QgYW4gZW5kZWQgcnVuIGlzXG4gICAgICAgIC8vIHJlamVjdGVkLCB3aGljaCB0aGUgY2F0Y2ggYXJvdW5kIGB3b3JsZC5ldmVudHMuY3JlYXRlYCBiZWxvdyByZS1rZXlzXG4gICAgICAgIC8vIHRvIEhvb2tOb3RGb3VuZEVycm9yOiBzYW1lIHB1YmxpYyBjb250cmFjdCwgbm8gcnVuIHByZS1mZXRjaC5cbiAgICAgICAgaWYgKGluZm8ucnVuICYmIGlzVGVybWluYWxXb3JrZmxvd1J1blN0YXR1cyhpbmZvLnJ1bi5zdGF0dXMpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEhvb2tOb3RGb3VuZEVycm9yKGhvb2sudG9rZW4pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgdGhlIHRhcmdldCBydW4ncyBjYXBhYmlsaXRpZXMgdG8gZW5zdXJlIHdlIGVuY29kZSB0aGVcbiAgICAgICAgLy8gcGF5bG9hZCBpbiBhIGZvcm1hdCB0aGUgcnVuJ3MgZGVwbG95bWVudCBjYW4gZGVjb2RlLiBGb3IgZXhhbXBsZSxcbiAgICAgICAgLy8gcnVucyBjcmVhdGVkIGJlZm9yZSBlbmNyeXB0aW9uIHN1cHBvcnQgd2FzIGFkZGVkIGNhbm5vdCBkZWNvZGVcbiAgICAgICAgLy8gdGhlICdlbmNyJyBzZXJpYWxpemF0aW9uIGZvcm1hdCwgYW5kIHJ1bnMgY3JlYXRlZCBiZWZvcmVcbiAgICAgICAgLy8gYnl0ZS1zdHJlYW0gZnJhbWluZyBzdXBwb3J0IGNhbm5vdCBkZWNvZGUgZnJhbWVkIGJ5dGUgc3RyZWFtcy5cbiAgICAgICAgY29uc3QgY2FwYWJpbGl0aWVzID0gZ2V0UnVuQ2FwYWJpbGl0aWVzKFxuICAgICAgICAgIHJlc3VtZUNvbnRleHQud29ya2Zsb3dDb3JlVmVyc2lvblxuICAgICAgICApO1xuXG4gICAgICAgIC8vIFJlc29sdmUgaG93IHRvIGVuY3J5cHQgdGhlIHBheWxvYWQgZm9yIHRoZSB0YXJnZXQgcnVuIChhIFdSSVRFKS5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gUHJlZmVycmVkIHBhdGg6IHNlYWwgdG8gdGhlIHJ1bidzIHB1Ymxpc2hlZCBYMjU1MTkgcHVibGljIGtleSwgd2hpY2hcbiAgICAgICAgLy8gdGhlIHN0b3JlZCBgcmVzdW1lQ29udGV4dGAgY2FycmllcyBpbmxpbmUuIE9uIHRoZSBmYXN0IHBhdGggdGhpcyBpc1xuICAgICAgICAvLyB0aGUgd2hvbGUgd2luOiBubyBydW4gcmVhZCBBTkQgbm8gYGdldEVuY3J5cHRpb25LZXlGb3JSdW5gLCB3aG9zZVxuICAgICAgICAvLyB+MzUwbXMgYHJ1bi1rZXlgIEFQSSByb3VuZCB0cmlwIGRvbWluYXRlcyBjcm9zcy1kZXBsb3ltZW50IGhvb2tcbiAgICAgICAgLy8gcmVzdW1wdGlvbiBsYXRlbmN5LiAoT24gdGhlIGZhbGxiYWNrIHBhdGggdGhlIGtleSBpcyBzeW50aGVzaXplZFxuICAgICAgICAvLyBmcm9tIHRoZSBmZXRjaGVkIHJ1biwgd2hpY2ggYWxzbyBjYXJyaWVzIGl0LilcbiAgICAgICAgLy9cbiAgICAgICAgLy8gU2VhbGluZyBhbHNvIGRyb3BzIHByaXZpbGVnZTogdGhlIHJlc3VtZXIgZW5kcyB1cCBhYmxlIHRvIHdyaXRlIGFcbiAgICAgICAgLy8gcGF5bG9hZCBmb3IgdGhlIHJ1biB3aXRob3V0IGJlaW5nIGFibGUgdG8gcmVhZCBhbnl0aGluZyBvZiB0aGVcbiAgICAgICAgLy8gcnVuJ3MsIHdoZXJlIGZldGNoaW5nIHRoZSBzeW1tZXRyaWMga2V5IGdyYW50cyBib3RoLlxuICAgICAgICAvL1xuICAgICAgICAvLyBEZWxpYmVyYXRlbHkgTk9UIGdhdGVkIG9uIGBjYXBhYmlsaXRpZXMuc3VwcG9ydGVkRm9ybWF0c2AgdGhlIHdheVxuICAgICAgICAvLyB0aGUgc3ltbWV0cmljIGZhbGxiYWNrIGJlbG93IGdhdGVzIGBlbmNyYDogcHJlc2VuY2Ugb2YgdGhlIHB1YmxpYyBrZXlcbiAgICAgICAgLy8gaXMgaXRzZWxmIHRoZSBnYXRlLiBBIHJ1biBvbmx5IGNhcnJpZXMgb25lIGlmIHRoZSBydW50aW1lIHRoYXRcbiAgICAgICAgLy8gY3JlYXRlZCBpdCBjb3VsZCBhbHNvIG9wZW4gYSBzZWFsZWQgcGF5bG9hZCwgYW5kIHJ1bnMgYXJlIHBpbm5lZCB0b1xuICAgICAgICAvLyB0aGVpciBjcmVhdGluZyBkZXBsb3ltZW50LCBzbyBwcmVzZW5jZSBpcyBhIG1vcmUgcmVsaWFibGUgYXR0ZXN0YXRpb25cbiAgICAgICAgLy8gdGhhbiBhIHZlcnNpb24gY29tcGFyZSwgYW5kIGl0IHN0YXlzIGNvcnJlY3QgZXZlbiB3aGVuIHBhY2thZ2VcbiAgICAgICAgLy8gdmVyc2lvbnMgZHJpZnQuXG4gICAgICAgIGxldCBwYXlsb2FkS2V5OiBQYXlsb2FkS2V5IHwgdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBydW5QdWJsaWNLZXkgPSBlbmNyeXB0aW9uS2V5T3ZlcnJpZGVcbiAgICAgICAgICA/IC8vIFRoZSBjYWxsZXIgYWxyZWFkeSBob2xkcyBhIGtleSAocmVzdW1lV2ViaG9vayByZXNvbHZlZCBvbmUgdG9cbiAgICAgICAgICAgIC8vIGh5ZHJhdGUgaG9vayBtZXRhZGF0YSksIHNvIHNlYWxpbmcgd291bGQgYWRkIGFuIEVDREggZm9yIG5vXG4gICAgICAgICAgICAvLyBzYXZlZCByb3VuZCB0cmlwLiBSZXVzZSB3aGF0IGl0IHJlc29sdmVkLlxuICAgICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICAgOiBkZWNvZGVSdW5QdWJsaWNLZXkocmVzdW1lQ29udGV4dC5lbmNyeXB0aW9uUHVibGljS2V5KTtcblxuICAgICAgICBpZiAocnVuUHVibGljS2V5KSB7XG4gICAgICAgICAgcGF5bG9hZEtleSA9IHNlYWxUbyhydW5QdWJsaWNLZXkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIFN5bW1ldHJpYyBgZW5jcmAgd3JpdGUgZmFsbGJhY2s6IG5lZWRzIG9ubHkgdGhlIEFFUyBrZXlcbiAgICAgICAgICAvLyAoYSBiYXJlIENyeXB0b0tleSB2aWEgYHJlc29sdmVIb29rRW5jcnlwdGlvbktleWApLCBub3QgdGhlXG4gICAgICAgICAgLy8gcmVhZC1zaWRlIFJ1blBheWxvYWRLZXlzLlxuICAgICAgICAgIGxldCBlbmNyeXB0aW9uS2V5ID1cbiAgICAgICAgICAgIGVuY3J5cHRpb25LZXlPdmVycmlkZSA/P1xuICAgICAgICAgICAgKGF3YWl0IHJlc29sdmVIb29rRW5jcnlwdGlvbktleShob29rLCBpbmZvKSk7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgIWNhcGFiaWxpdGllcy5zdXBwb3J0ZWRGb3JtYXRzLmhhcyhTZXJpYWxpemF0aW9uRm9ybWF0LkVOQ1JZUFRFRClcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGVuY3J5cHRpb25LZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIHBheWxvYWRLZXkgPSBlbmNyeXB0aW9uS2V5O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29tcHJlc3Mgb25seSB3aGVuIHRoZSB0YXJnZXQgcnVuIGFuZCBpdHMgZGVwbG95bWVudCBzdXBwb3J0IHRoZVxuICAgICAgICAvLyBjb21wcmVzc2lvbiBmb3JtYXRzIGludHJvZHVjZWQgd2l0aCBzcGVjIHZlcnNpb24gNS5cbiAgICAgICAgY29uc3QgY29tcHJlc3Npb24gPVxuICAgICAgICAgIChyZXN1bWVDb250ZXh0LnJ1blNwZWNWZXJzaW9uID8/IDApID49XG4gICAgICAgICAgICBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ09NUFJFU1NJT04gJiZcbiAgICAgICAgICBjYXBhYmlsaXRpZXMuc3VwcG9ydGVkRm9ybWF0cy5oYXMoU2VyaWFsaXphdGlvbkZvcm1hdC5HWklQKTtcblxuICAgICAgICAvLyBEZWh5ZHJhdGUgdGhlIHBheWxvYWQgZm9yIHN0b3JhZ2VcbiAgICAgICAgY29uc3Qgb3BzOiBQcm9taXNlPGFueT5bXSA9IFtdO1xuICAgICAgICBjb25zdCByZWFkYmFja09wczogUHJvbWlzZTxhbnk+W10gPSBbXTtcbiAgICAgICAgY29uc3QgdjFDb21wYXQgPSBpc0xlZ2FjeVNwZWNWZXJzaW9uKGhvb2suc3BlY1ZlcnNpb24pO1xuICAgICAgICBjb25zdCBkZWh5ZHJhdGVkUGF5bG9hZCA9IGF3YWl0IGRlaHlkcmF0ZVN0ZXBSZXR1cm5WYWx1ZShcbiAgICAgICAgICBwYXlsb2FkLFxuICAgICAgICAgIGhvb2sucnVuSWQsXG4gICAgICAgICAgcGF5bG9hZEtleSxcbiAgICAgICAgICBvcHMsXG4gICAgICAgICAgZ2xvYmFsVGhpcyxcbiAgICAgICAgICB2MUNvbXBhdCxcbiAgICAgICAgICBjYXBhYmlsaXRpZXMuZnJhbWVkQnl0ZVN0cmVhbXMsXG4gICAgICAgICAgY29tcHJlc3Npb24sXG4gICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgIHJlYWRiYWNrT3BzXG4gICAgICAgICk7XG4gICAgICAgIC8vIEEgaG9va19yZWNlaXZlZCBldmVudCBpcyBub3QgZHVyYWJsZSB3aGlsZSBpdHMgcGF5bG9hZCBzdGlsbCBwb2ludHNcbiAgICAgICAgLy8gYXQgc3RyZWFtIHVwbG9hZHMgaW4gZmxpZ2h0LiBGaW5pc2ggdGhvc2UgYmVmb3JlIGNvbW1pdHRpbmcgdGhlXG4gICAgICAgIC8vIGV2ZW50IOKAlCBidXQgT05MWSB0aGUgcHJvZHVjZXItcHVzaCBvcHMgaW4gYG9wc2AuIEEgZGVoeWRyYXRlZFxuICAgICAgICAvLyBXcml0YWJsZVN0cmVhbSBsYW5kcyBpbiBgcmVhZGJhY2tPcHNgIGluc3RlYWQ6IGl0IGlzIGEgc2VydmVyLXN0cmVhbVxuICAgICAgICAvLyBSRUFERVIgdGhhdCByZXNvbHZlcyBvbmx5IG9uY2UgdGhlIHdva2VuIHdvcmtmbG93IHdyaXRlcyBpbnRvIGl0IChhXG4gICAgICAgIC8vIG1hbnVhbCB3ZWJob29rJ3MgYHJlc3BvbnNlV3JpdGFibGVgIGlzIHRoZSBjYW5vbmljYWwgY2FzZSksIHNvXG4gICAgICAgIC8vIGF3YWl0aW5nIGl0IGhlcmUgd291bGQgZGVhZGxvY2sgdGhlIHJlc3VtZSBhZ2FpbnN0IGl0cyBvd24gd2FrZS5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gQSByZWplY3Rpb24gd2l0aCBgdW5kZWZpbmVkYCBpcyBhbiBleHBlY3RlZCBhcnRpZmFjdCBvZiB0aGUgd2ViaG9va1xuICAgICAgICAvLyBidW5kbGUgYW5kIHdhcyBoaXN0b3JpY2FsbHkgaWdub3JlZCBieSB0aGUgYmFja2dyb3VuZCBmbHVzaC4gS2VlcFxuICAgICAgICAvLyB0aGF0IHRvbGVyYW5jZSBub3cgdGhhdCB0aGUgZmx1c2ggaXMgYXdhaXRlZCBpbmxpbmUuXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICAgIG9wcy5tYXAoKG9wKSA9PlxuICAgICAgICAgICAgb3AuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChlcnJvciAhPT0gdW5kZWZpbmVkKSB0aHJvdyBlcnJvcjtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICAvLyBSZWFkYmFjayBwaXBlcyAobm90YWJseSBhIG1hbnVhbCB3ZWJob29rIHJlc3BvbnNlIHdyaXRhYmxlKSBjYW4gb25seVxuICAgICAgICAvLyBmaW5pc2ggYWZ0ZXIgdGhlIHdvcmtmbG93IHdha2VzIGFuZCB3cml0ZXMgdG8gdGhlbS4gS2VlcCB0aGVtIGFsaXZlLFxuICAgICAgICAvLyBidXQgbmV2ZXIgcGxhY2UgdGhlbSBpbiB0aGUgZHVyYWJpbGl0eSBiYXJyaWVyIGFib3ZlLlxuICAgICAgICBzYWZlV2FpdFVudGlsKFByb21pc2UuYWxsKHJlYWRiYWNrT3BzKSwgKGVycikgPT4ge1xuICAgICAgICAgIGlmIChlcnIgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICAgICAgICAgIHJ1bnRpbWVMb2dnZXIud2FybignQmFja2dyb3VuZCByZWFkYmFjayBvZiBob29rIHBheWxvYWQgZmFpbGVkJywge1xuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogaG9vay5ydW5JZCxcbiAgICAgICAgICAgIGhvb2tJZDogaG9vay5ob29rSWQsXG4gICAgICAgICAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dOYW1lKHJlc3VtZUNvbnRleHQud29ya2Zsb3dOYW1lKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gTGluayB0byB0aGUgcnVuLW9yaWdpbiBjb250ZXh0IGZyb20gdGhlIHN0b3JlZCB0cmFjZSBjYXJyaWVyXG4gICAgICAgIC8vIChza2lwcGVkIHdoZW4gYWJzZW50IG9yIGludmFsaWQpLiBSZXNvbHZlZCBiZWZvcmUgZGlzcGF0Y2ggc28gdGhlXG4gICAgICAgIC8vIHdyaXRlIGFuZCB0aGUgd2FrZSBib3RoIHNpdCB1bmRlciBhIHNwYW4gdGhhdCBjYXJyaWVzIGl0LlxuICAgICAgICBjb25zdCBvcmlnaW5MaW5rID0gYXdhaXQgbGlua1RvVHJhY2VDYXJyaWVyKHJlc3VtZUNvbnRleHQudHJhY2VDYXJyaWVyKTtcbiAgICAgICAgaWYgKG9yaWdpbkxpbmspIHtcbiAgICAgICAgICBzcGFuPy5hZGRMaW5rPy4ob3JpZ2luTGluayk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBxdWV1ZU5hbWUgPSBnZXRXb3JrZmxvd1F1ZXVlTmFtZShyZXN1bWVDb250ZXh0LndvcmtmbG93TmFtZSk7XG4gICAgICAgIGNvbnN0IHF1ZXVlT3B0aW9ucyA9IHtcbiAgICAgICAgICBkZXBsb3ltZW50SWQ6IHJlc3VtZUNvbnRleHQuZGVwbG95bWVudElkLFxuICAgICAgICAgIHNwZWNWZXJzaW9uOiByZXN1bWVDb250ZXh0LnJ1blNwZWNWZXJzaW9uID8/IFNQRUNfVkVSU0lPTl9MRUdBQ1ksXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gVGhlIGRpc3BhdGNoIGlzIHN0cmljdGx5IHNlcmlhbDogdGhlIGhvb2tfcmVjZWl2ZWQgZXZlbnQgaXMgbWFkZVxuICAgICAgICAvLyBkdXJhYmxlIEZJUlNULCBhbmQgdGhlIHdvcmtmbG93IHdha2UgaXMgcHVibGlzaGVkIG9ubHkgYWZ0ZXIgdGhlXG4gICAgICAgIC8vIHdyaXRlIGlzIGFja25vd2xlZGdlZC4gVGhpcyBpcyB3aGF0IGxldHMgYHJlc3VtZUhvb2soKWAgcmVzb2x2aW5nXG4gICAgICAgIC8vIG1lYW4gXCJ0aGUgcmVzdW1lIHN1cnZpdmVzIGFueXRoaW5nIHRoYXQgaGFwcGVucyBuZXh0XCIg4oCUIGEgZGlzcG9zYWxcbiAgICAgICAgLy8gb3IgcnVuIGNvbXBsZXRpb24gcmFjaW5nIHRoZSBxdWV1ZSBkZWxpdmVyeSBjYW5ub3QgZXJhc2UgYSBjb21taXR0ZWRcbiAgICAgICAgLy8gZXZlbnQsIGFuZCB0aGUgd2FrZSBpdHNlbGYgY2FycmllcyBubyBwYXlsb2FkLCBzbyBub3RoaW5nIHJpZGVzIG9uXG4gICAgICAgIC8vIHRoZSBtZXNzYWdlIGJ1dCB0aGUgdHJpZ2dlci5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gQmFja2VuZCBkZWR1cCBpcyBhdHRlc3RlZCB3aGVuIEVJVEhFUiB0aGUgbGl2ZSBzZXJ2ZXIgYXR0ZXN0cyBpdFxuICAgICAgICAvLyBmcmVzaCBvbiB0aGlzIGJ5LXRva2VuIGhvb2sgKHdvcmxkLXZlcmNlbDogcmVzcG9uc2Utb25seSwgcmVjb21wdXRlZFxuICAgICAgICAvLyBldmVyeSByZWFkLCBzbyByb2xsYmFjay9raWxsLXN3aXRjaCB0YWtlIGVmZmVjdCBpbW1lZGlhdGVseSkgT1IgdGhlXG4gICAgICAgIC8vIHN0YXRpYyB3b3JsZCBjYXBhYmlsaXR5IGlzIHNldCAod29ybGQtbG9jYWw6IGFkYXB0ZXIgKyBiYWNrZW5kIHNoaXBcbiAgICAgICAgLy8gdG9nZXRoZXIpLiBXaGVuIGF0dGVzdGVkLCB0aGUgd3JpdGUgY2FycmllcyBhIHBlci1jYWxsIHJlc3VtZUlkICtcbiAgICAgICAgLy8gcGF5bG9hZCBkaWdlc3Qgc28gdHJhbnNwb3J0LWxldmVsIHJldHJpZXMgb2YgdGhlIFNBTUUgd3JpdGUgY29udmVyZ2VcbiAgICAgICAgLy8gb24gZXhhY3RseSBvbmUgY29tbWl0dGVkIGV2ZW50IHZpYSB0aGUgYmFja2VuZCdzIChydW5JZCwgcmVzdW1lSWQpXG4gICAgICAgIC8vIGNvbnN0cmFpbnQuIFdpdGhvdXQgaXQgdGhlIHdyaXRlIGlzIGEgcGxhaW4gc2luZ2xlLXNob3QgY3JlYXRlLFxuICAgICAgICAvLyBleGFjdGx5IGFzIGJlZm9yZSBkZWR1cCBleGlzdGVkLlxuICAgICAgICBjb25zdCBiYWNrZW5kRGVkdXBTdXBwb3J0ZWQgPVxuICAgICAgICAgIChob29rUmVzdW1lQ2FwYWJpbGl0aWVzQXJlRnJlc2hcbiAgICAgICAgICAgID8gKGhvb2sucmVzdW1lQ2FwYWJpbGl0aWVzPy5ob29rUmVzdW1lRGVkdXBWZXJzaW9uID8/IDApXG4gICAgICAgICAgICA6IDApID49IEhPT0tfUkVTVU1FX0RFRFVQX1ZFUlNJT04gfHxcbiAgICAgICAgICB3b3JsZC5jYXBhYmlsaXRpZXM/Lmhvb2tSZXN1bWVEZWR1cCA9PT0gdHJ1ZTtcbiAgICAgICAgY29uc3QgY2FuQ2xhaW1SZXN1bWUgPVxuICAgICAgICAgIGJhY2tlbmREZWR1cFN1cHBvcnRlZCAmJlxuICAgICAgICAgICF2MUNvbXBhdCAmJlxuICAgICAgICAgIGRlaHlkcmF0ZWRQYXlsb2FkIGluc3RhbmNlb2YgVWludDhBcnJheTtcblxuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAnd29ya2Zsb3cuaG9vay5yZXN1bWVfc3RyYXRlZ3knOiAnc2VxdWVudGlhbCcsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHJlc3VtZUlkID0gY2FuQ2xhaW1SZXN1bWUgPyBnZW5lcmF0ZVJlc3VtZUlkKCkgOiB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IHBheWxvYWREaWdlc3QgPSBjYW5DbGFpbVJlc3VtZVxuICAgICAgICAgID8gYXdhaXQgY29tcHV0ZVJlc3VtZVBheWxvYWREaWdlc3QoZGVoeWRyYXRlZFBheWxvYWQpXG4gICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChyZXN1bWVJZCkge1xuICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoeyAnd29ya2Zsb3cuaG9vay5yZXN1bWVfaWQnOiByZXN1bWVJZCB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlLWtleSBhbnkgXCJob29rIGNhbiBubyBsb25nZXIgYmUgcmVjZWl2ZWRcIiByZWplY3Rpb24gdG9cbiAgICAgICAgLy8gSG9va05vdEZvdW5kRXJyb3IoaG9vay50b2tlbikgc28gYC50b2tlbmAgbWF0Y2hlcyB0aGUgaGlzdG9yaWNhbFxuICAgICAgICAvLyBjb250cmFjdC4gVGhlIHNwZWNpZmljIGVycm9yIGRlcGVuZHMgb24gdGhlIFdvcmxkOlxuICAgICAgICAvLyAgIC0gYSBnZW51aW5lbHkgbWlzc2luZyBob29rIG1hcHMgdG8gSG9va05vdEZvdW5kRXJyb3IgKGtleWVkIG9uXG4gICAgICAgIC8vICAgICB0aGUgZXZlbnQgY29ycmVsYXRpb25JZCAvIGhvb2sgSUQpO1xuICAgICAgICAvLyAgIC0gYSB0ZXJtaW5hbCBydW4gb24gVmVyY2VsIHJlamVjdHMgaG9va19yZWNlaXZlZCB3aXRoIDQwNCwgd2hpY2hcbiAgICAgICAgLy8gICAgIHdvcmxkLXZlcmNlbCBtYXBzIHRvIEhvb2tOb3RGb3VuZEVycm9yO1xuICAgICAgICAvLyAgIC0gYSB0ZXJtaW5hbCBydW4gb24gd29ybGQtbG9jYWwgLyB3b3JsZC1wb3N0Z3JlcyByZWplY3RzIHdpdGhcbiAgICAgICAgLy8gICAgIFJ1bkV4cGlyZWRFcnJvci5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gQW4gRW50aXR5Q29uZmxpY3RFcnJvciAoSFRUUCA0MDkpIGlzIGRlbGliZXJhdGVseSBOT1QgcmUta2V5ZWQsXG4gICAgICAgIC8vIGJyZWFraW5nIHdpdGggdGhlIGhpc3RvcmljYWwgbWFwcGluZzogZXZlcnkgNDA5IHRoZSBiYWNrZW5kIGVtaXRzXG4gICAgICAgIC8vIG9uIHRoaXMgd3JpdGUgdG9kYXkgaXMgVFJBTlNJRU5UIOKAlCBhIHNsb3QgY29uZmxpY3QgdGhhdCBlc2NhcGVkIHRoZVxuICAgICAgICAvLyBzZXJ2ZXIncyBvd24gcmV0cnkgYnVkZ2V0IHVuZGVyIGNvbnRlbnRpb24sIG9yIGEgcmVzdW1lLWNsYWltIHJhY2VcbiAgICAgICAgLy8gbWlkLXJlc29sdXRpb24g4oCUIGFuZCBpdHMgdHJhbnNhY3Rpb24gY29tbWl0dGVkIG5vdGhpbmcuIFJlLWtleWluZ1xuICAgICAgICAvLyBpdCB0byBIb29rTm90Rm91bmRFcnJvciB0b2xkIHRoZSBjYWxsZXIgKGFuZCBhIHdlYmhvb2sgc2VuZGVyLCB2aWFcbiAgICAgICAgLy8gNDA0KSB0aGF0IGEgcmV0cnlhYmxlIGZhaWx1cmUgd2FzIHBlcm1hbmVudCwgc2lsZW50bHkgZHJvcHBpbmcgdGhlXG4gICAgICAgIC8vIHJlc3VtZS4gSXQgbm93IHN1cmZhY2VzIGFzLWlzOiByZXRyeWFibGUsIHdpdGggbm90aGluZyBjb21taXR0ZWQuXG4gICAgICAgIC8vIChBIDQyMiByZXN1bWVJZC1yZXVzZSBlcnJvciBsaWtld2lzZSBwYXNzZXMgdGhyb3VnaCB1bm1hcHBlZCDigJQgaXRcbiAgICAgICAgLy8gbWVhbnMgdGhlIGNhbGxlciByZXBsYXllZCBhIHJlc3VtZUlkIHdpdGggYSBkaWZmZXJlbnQgcGF5bG9hZCwgYW5kXG4gICAgICAgIC8vIGhpZGluZyB0aGF0IGJlaGluZCBcIm5vdCBmb3VuZFwiIHdvdWxkIG1hc2sgdGhlIGJ1Zy4pXG4gICAgICAgIGNvbnN0IGlzSG9va0dvbmVFcnJvciA9IChlcnI6IHVua25vd24pOiBib29sZWFuID0+XG4gICAgICAgICAgSG9va05vdEZvdW5kRXJyb3IuaXMoZXJyKSB8fCBSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgaG9vay5ydW5JZCxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnaG9va19yZWNlaXZlZCcsXG4gICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogaG9vay5ob29rSWQsXG4gICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgIC4uLih2MUNvbXBhdCA/IHt9IDogeyB0b2tlbjogaG9vay50b2tlbiB9KSxcbiAgICAgICAgICAgICAgICBwYXlsb2FkOiBkZWh5ZHJhdGVkUGF5bG9hZCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHYxQ29tcGF0LFxuICAgICAgICAgICAgICAuLi4ocmVzdW1lSWQgJiYgcGF5bG9hZERpZ2VzdFxuICAgICAgICAgICAgICAgID8geyByZXN1bWVJZCwgcmVzdW1lUGF5bG9hZERpZ2VzdDogcGF5bG9hZERpZ2VzdCB9XG4gICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgaWYgKGlzSG9va0dvbmVFcnJvcihlcnIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgSG9va05vdEZvdW5kRXJyb3IoaG9vay50b2tlbik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfVxuICAgICAgICAvLyBTdGFtcGVkIEFGVEVSIHRoZSB3cml0ZSByZXNvbHZlcyAoZW50cnktdGltZSBhdHRyaWJ1dGVzIGNhbm5vdCB0ZWxsXG4gICAgICAgIC8vIGFuIGF0dGVtcHRlZCByZXN1bWUgZnJvbSBhIGNvbW1pdHRlZCBvbmUpOiB0b2dldGhlciB3aXRoXG4gICAgICAgIC8vIEhvb2tXYWtlUHVibGlzaGVkIGJlbG93LCB0aGlzIGlzIHdoYXQgbWFrZXMgYSBzdHJhbmRlZCByZXN1bWUg4oCUIGFcbiAgICAgICAgLy8gY29tbWl0dGVkIGV2ZW50IHdob3NlIHdha2UgbmV2ZXIgd2VudCBvdXQgb3Igd2FzIG5ldmVyIGRlbGl2ZXJlZCDigJRcbiAgICAgICAgLy8gcXVlcnlhYmxlIGZyb20gdHJhY2VzLiBTZWUgdGhlIGFsZXJ0aW5nIG5vdGUgb24gSG9va1dha2VQdWJsaXNoZWQuXG4gICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoQXR0cmlidXRlLkhvb2tSZXN1bWVDb21taXR0ZWQodHJ1ZSkpO1xuXG4gICAgICAgIC8vIFQxIG9mIHRoZSBUVFIgd2luZG93LiBTdGFtcGVkIGltbWVkaWF0ZWx5IGJlZm9yZSB0aGUgcHVibGlzaCBzb1xuICAgICAgICAvLyBgcHJvZHVjZXJfcHJlcGAgY292ZXJzIGV4YWN0bHkgdGhlIHdvcmsgYWJvdmUgaXQgKGhvb2sgbG9va3VwLCBrZXlcbiAgICAgICAgLy8gcmVzb2x1dGlvbiwgc2VyaWFsaXphdGlvbiwgYW5kIHRoZSBhd2FpdGVkIGhvb2tfcmVjZWl2ZWQgd3JpdGUsXG4gICAgICAgIC8vIHdoaWNoIGlzIGdlbnVpbmVseSBzZXJpYWwgaGVyZSkuXG4gICAgICAgIGNvbnN0IHF1ZXVlUHVibGlzaFJlcXVlc3RlZEF0TXMgPSBEYXRlLm5vdygpO1xuICAgICAgICBhd2FpdCBwdWJsaXNoSG9va1dha2VXaXRoUmV0cnkoXG4gICAgICAgICAgKCkgPT5cbiAgICAgICAgICAgIHdvcmxkLnF1ZXVlKFxuICAgICAgICAgICAgICBxdWV1ZU5hbWUsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBydW5JZDogaG9vay5ydW5JZCxcbiAgICAgICAgICAgICAgICB0cmFjZUNhcnJpZXI6IHJlc3VtZUNvbnRleHQudHJhY2VDYXJyaWVyID8/IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBob29rUmVzdW1lVGltaW5nOiB7XG4gICAgICAgICAgICAgICAgICByZXN1bWVSZXF1ZXN0ZWRBdE1zLFxuICAgICAgICAgICAgICAgICAgcXVldWVQdWJsaXNoUmVxdWVzdGVkQXRNcyxcbiAgICAgICAgICAgICAgICAgIHN0cmF0ZWd5OiAnc2VxdWVudGlhbCcsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSBzYXRpc2ZpZXMgV29ya2Zsb3dJbnZva2VQYXlsb2FkLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgLi4ucXVldWVPcHRpb25zLFxuICAgICAgICAgICAgICAgIC8vIERlZHVwIHJldHJpZWQgcHVibGlzaGVzIHdob3NlIHJlc3BvbnNlIHdhcyBsb3N0OiBhXG4gICAgICAgICAgICAgICAgLy8gZHVwbGljYXRlIHdha2UgaXMgaGFybWxlc3MgZm9yIGNvcnJlY3RuZXNzIChkZXRlcm1pbmlzdGljXG4gICAgICAgICAgICAgICAgLy8gcmVwbGF5KSBidXQgY29zdHMgYSBmdWxsIHJlcGxheSBvZiB0aGUgcnVuLCBhbmQgdGhlIHF1ZXVlXG4gICAgICAgICAgICAgICAgLy8gYWNjZXB0cyBhIHJlcGVhdGVkIGlkZW1wb3RlbmN5IGtleSBieSBkZWxpdmVyaW5nIG9ubHkgb25lXG4gICAgICAgICAgICAgICAgLy8gb2YgdGhlIG1lc3NhZ2VzLiBDbGFpbS1sZXNzIHdyaXRlcyBoYXZlIG5vIHJlc3VtZUlkIGFuZFxuICAgICAgICAgICAgICAgIC8vIGtlZXAgdGhlIHByZXZpb3VzIGJlaGF2aW9yLlxuICAgICAgICAgICAgICAgIC4uLihyZXN1bWVJZCA/IHsgaWRlbXBvdGVuY3lLZXk6IGBob29rLSR7cmVzdW1lSWR9YCB9IDoge30pLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApLFxuICAgICAgICAgIHdvcmxkLmlzRGVwbG95bWVudFVuYXZhaWxhYmxlRXJyb3I/LmJpbmQod29ybGQpXG4gICAgICAgICk7XG4gICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoQXR0cmlidXRlLkhvb2tXYWtlUHVibGlzaGVkKHRydWUpKTtcblxuICAgICAgICByZXR1cm4gaG9vayBzYXRpc2ZpZXMgUmVzdW1lZEhvb2s7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgLi4uQXR0cmlidXRlLkhvb2tUb2tlbihcbiAgICAgICAgICAgIHR5cGVvZiB0b2tlbk9ySG9vayA9PT0gJ3N0cmluZycgPyB0b2tlbk9ySG9vayA6IHRva2VuT3JIb29rLnRva2VuXG4gICAgICAgICAgKSxcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuSG9va0ZvdW5kKGZhbHNlKSxcbiAgICAgICAgfSk7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG59XG5cbi8qKlxuICogUmVzdW1lcyBhIHdlYmhvb2sgYnkgc2VuZGluZyBhIHtAbGluayBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvUmVxdWVzdCB8IFJlcXVlc3R9XG4gKiBvYmplY3QgdG8gYSBob29rIGlkZW50aWZpZWQgYnkgaXRzIHRva2VuLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIGV4dGVybmFsbHkgKGUuZy4sIGZyb20gYW4gQVBJIHJvdXRlIG9yIHNlcnZlciBhY3Rpb24pXG4gKiB0byBzZW5kIGEgcmVxdWVzdCB0byBhIHdlYmhvb2sgYW5kIHJlc3VtZSB0aGUgYXNzb2NpYXRlZCB3b3JrZmxvdyBydW4uXG4gKlxuICogQHBhcmFtIHRva2VuIC0gVGhlIHVuaXF1ZSB0b2tlbiBpZGVudGlmeWluZyB0aGUgaG9va1xuICogQHBhcmFtIHJlcXVlc3QgLSBUaGUgcmVxdWVzdCB0byBzZW5kIHRvIHRoZSBob29rXG4gKiBAcmV0dXJucyBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgcmVzcG9uc2VcbiAqIEB0aHJvd3MgRXJyb3IgaWYgdGhlIGhvb2sgaXMgbm90IGZvdW5kIG9yIGlmIHRoZXJlJ3MgYW4gZXJyb3IgZHVyaW5nIHRoZSBwcm9jZXNzXG4gKlxuICogQGV4YW1wbGVcbiAqXG4gKiBgYGB0c1xuICogLy8gSW4gYW4gQVBJIHJvdXRlXG4gKiBpbXBvcnQgeyByZXN1bWVXZWJob29rIH0gZnJvbSAnQHdvcmtmbG93L2NvcmUvcnVudGltZSc7XG4gKlxuICogZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIFBPU1QocmVxdWVzdDogUmVxdWVzdCkge1xuICogICBjb25zdCB1cmwgPSBuZXcgVVJMKHJlcXVlc3QudXJsKTtcbiAqICAgY29uc3QgdG9rZW4gPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgndG9rZW4nKTtcbiAqXG4gKiAgIGlmICghdG9rZW4pIHtcbiAqICAgICByZXR1cm4gbmV3IFJlc3BvbnNlKCdNaXNzaW5nIHRva2VuJywgeyBzdGF0dXM6IDQwMCB9KTtcbiAqICAgfVxuICpcbiAqICAgdHJ5IHtcbiAqICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHJlc3VtZVdlYmhvb2sodG9rZW4sIHJlcXVlc3QpO1xuICogICAgIHJldHVybiByZXNwb25zZTtcbiAqICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAqICAgICByZXR1cm4gbmV3IFJlc3BvbnNlKCdXZWJob29rIG5vdCBmb3VuZCcsIHsgc3RhdHVzOiA0MDQgfSk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzdW1lV2ViaG9vayhcbiAgdG9rZW46IHN0cmluZyxcbiAgcmVxdWVzdDogUmVxdWVzdFxuKTogUHJvbWlzZTxSZXNwb25zZT4ge1xuICAvLyBUMCBvZiB0aGUgaG9vay1yZXN1bWUgVFRSIHdpbmRvdy4gRXZlcnl0aGluZyBiZWxvdyAodGhlIGJ5LXRva2VuIGxvb2t1cCxcbiAgLy8gdGhlIHJ1bi1rZXkgcmVzb2x1dGlvbiBpdCBtYXkgdHJpZ2dlciwgYW5kIHRoZSBgcmVzcG9uZFdpdGhgIHNldHVwKSBpc1xuICAvLyByZWFsIHByb2R1Y2VyLXNpZGUgbGF0ZW5jeSBvbiB0aGlzIHBhdGgsIHNvIHRoZSB3aW5kb3cgaGFzIHRvIG9wZW4gaGVyZVxuICAvLyBhbmQgbm90IGluc2lkZSBgcmVzdW1lSG9va0ltcGxgOyBvdGhlcndpc2Ugd2ViaG9vayByZXN1bWVzIHdvdWxkIHJlcG9ydCBhXG4gIC8vIHN5c3RlbWF0aWNhbGx5IHNob3J0ZXIgdG90YWwgdGhhbiBgcmVzdW1lSG9va2Agb25lcyBpbnRvIHRoZSBzYW1lIG1ldHJpYy5cbiAgY29uc3QgcmVzdW1lUmVxdWVzdGVkQXRNcyA9IERhdGUubm93KCk7XG4gIGNvbnN0IHsgaG9vaywgZW5jcnlwdGlvbktleSB9ID0gYXdhaXQgZ2V0SG9va0J5VG9rZW5XaXRoS2V5KHRva2VuKTtcblxuICAvLyBPbmx5IHdlYmhvb2tzIGNhbiBiZSByZXN1bWVkIHZpYSB0aGUgcHVibGljIGVuZHBvaW50LlxuICAvLyBJZiB0aGUgaG9vayB3YXMgY3JlYXRlZCB2aWEgY3JlYXRlSG9vaygpIChpc1dlYmhvb2sgIT09IHRydWUpLFxuICAvLyB0aHJvdyB0aGUgc2FtZSBcIm5vdCBmb3VuZFwiIGVycm9yIHRoZSB3b3JsZCB3b3VsZCB0aHJvdyBmb3IgYSBtaXNzaW5nXG4gIC8vIHRva2VuLiBUaGlzIHByZXZlbnRzIGxlYWtpbmcgdGhhdCB0aGUgdG9rZW4gaXMgdmFsaWQuXG4gIGlmIChob29rLmlzV2ViaG9vayA9PT0gZmFsc2UpIHtcbiAgICB0aHJvdyBuZXcgSG9va05vdEZvdW5kRXJyb3IodG9rZW4pO1xuICB9XG5cbiAgbGV0IHJlc3BvbnNlOiBSZXNwb25zZSB8IHVuZGVmaW5lZDtcbiAgbGV0IHJlc3BvbnNlUmVhZGFibGU6IFJlYWRhYmxlU3RyZWFtPFJlc3BvbnNlPiB8IHVuZGVmaW5lZDtcbiAgaWYgKFxuICAgIGhvb2subWV0YWRhdGEgJiZcbiAgICB0eXBlb2YgaG9vay5tZXRhZGF0YSA9PT0gJ29iamVjdCcgJiZcbiAgICAncmVzcG9uZFdpdGgnIGluIGhvb2subWV0YWRhdGFcbiAgKSB7XG4gICAgaWYgKGhvb2subWV0YWRhdGEucmVzcG9uZFdpdGggPT09ICdtYW51YWwnKSB7XG4gICAgICBjb25zdCB7IHJlYWRhYmxlLCB3cml0YWJsZSB9ID0gbmV3IFRyYW5zZm9ybVN0cmVhbTxSZXNwb25zZSwgUmVzcG9uc2U+KCk7XG4gICAgICByZXNwb25zZVJlYWRhYmxlID0gcmVhZGFibGU7XG5cbiAgICAgIC8vIFRoZSByZXF1ZXN0IGluc3RhbmNlIGluY2x1ZGVzIHRoZSB3cml0YWJsZSBzdHJlYW0gd2hpY2ggd2lsbCBiZSB1c2VkXG4gICAgICAvLyB0byB3cml0ZSB0aGUgcmVzcG9uc2UgdG8gdGhlIGNsaWVudCBmcm9tIHdpdGhpbiB0aGUgd29ya2Zsb3cgcnVuXG4gICAgICAocmVxdWVzdCBhcyBhbnkpW1dFQkhPT0tfUkVTUE9OU0VfV1JJVEFCTEVdID0gd3JpdGFibGU7XG4gICAgfSBlbHNlIGlmIChob29rLm1ldGFkYXRhLnJlc3BvbmRXaXRoIGluc3RhbmNlb2YgUmVzcG9uc2UpIHtcbiAgICAgIHJlc3BvbnNlID0gaG9vay5tZXRhZGF0YS5yZXNwb25kV2l0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgICBgSW52YWxpZCBcXGByZXNwb25kV2l0aFxcYCB2YWx1ZTogJHtob29rLm1ldGFkYXRhLnJlc3BvbmRXaXRofWAsXG4gICAgICAgIHsgc2x1ZzogRVJST1JfU0xVR1MuV0VCSE9PS19JTlZBTElEX1JFU1BPTkRfV0lUSF9WQUxVRSB9XG4gICAgICApO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBObyBgcmVzcG9uZFdpdGhgIHZhbHVlIGltcGxpZXMgdGhlIGRlZmF1bHQgYmVoYXZpb3Igb2YgcmV0dXJuaW5nIGEgMjAyXG4gICAgcmVzcG9uc2UgPSBuZXcgUmVzcG9uc2UobnVsbCwgeyBzdGF0dXM6IDIwMiB9KTtcbiAgfVxuXG4gIC8vIGBob29rYCB3YXMganVzdCBmZXRjaGVkIHZpYSBgZ2V0SG9va0J5VG9rZW5XaXRoS2V5YCAoYSBmcmVzaCBieS10b2tlblxuICAvLyBsb29rdXApIGFib3ZlLCBzbyBpdHMgcmVzcG9uc2Utb25seSBgcmVzdW1lQ2FwYWJpbGl0aWVzYCByZWZsZWN0cyB0aGUgbGl2ZVxuICAvLyBiYWNrZW5kLiBDYWxsIHRoZSBpbnRlcm5hbCBpbXBsZW1lbnRhdGlvbiB3aXRoIHRoZSBmcmVzaCBhdHRlc3RhdGlvbiBzb1xuICAvLyB0aGUgd3JpdGUncyBpZGVtcG90ZW5jeSBjbGFpbSBzdGF5cyBhdmFpbGFibGUgd2l0aG91dCBhIHNlY29uZCBHRVQuIChUaGVcbiAgLy8gcHVibGljIGByZXN1bWVIb29rYCBuZXZlciBzZXRzIHRoaXMsIHNvIGEgY2FsbGVyIGNhbm5vdCBmb3JnZSBpdC4pXG4gIGF3YWl0IHJlc3VtZUhvb2tJbXBsKGhvb2ssIHJlcXVlc3QsIGVuY3J5cHRpb25LZXksIHRydWUsIHJlc3VtZVJlcXVlc3RlZEF0TXMpO1xuXG4gIGlmIChyZXNwb25zZVJlYWRhYmxlKSB7XG4gICAgLy8gV2FpdCBmb3IgdGhlIHJlYWRhYmxlIHN0cmVhbSB0byBlbWl0IG9uZSBjaHVuayxcbiAgICAvLyB3aGljaCBpcyB0aGUgYFJlc3BvbnNlYCBvYmplY3RcbiAgICBjb25zdCByZWFkZXIgPSByZXNwb25zZVJlYWRhYmxlLmdldFJlYWRlcigpO1xuICAgIGNvbnN0IGNodW5rID0gYXdhaXQgcmVhZGVyLnJlYWQoKTtcbiAgICBpZiAoY2h1bmsudmFsdWUpIHtcbiAgICAgIHJlc3BvbnNlID0gY2h1bmsudmFsdWU7XG4gICAgfVxuICAgIHJlYWRlci5jYW5jZWwoKTtcbiAgfVxuXG4gIGlmICghcmVzcG9uc2UpIHtcbiAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoJ1dvcmtmbG93IHJ1biBkaWQgbm90IHNlbmQgYSByZXNwb25zZScsIHtcbiAgICAgIHNsdWc6IEVSUk9SX1NMVUdTLldFQkhPT0tfUkVTUE9OU0VfTk9UX1NFTlQsXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gcmVzcG9uc2U7XG59XG4iXX0=