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

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 (228) hide show
  1. package/dist/attribute-changes.d.ts +3 -5
  2. package/dist/attribute-changes.d.ts.map +1 -1
  3. package/dist/attribute-changes.js +2 -2
  4. package/dist/capabilities.d.ts +6 -6
  5. package/dist/capabilities.js +8 -8
  6. package/dist/capture-stack.d.ts +1 -1
  7. package/dist/capture-stack.js +2 -2
  8. package/dist/class-serialization.d.ts +8 -8
  9. package/dist/class-serialization.js +9 -9
  10. package/dist/classify-error.js +5 -5
  11. package/dist/context-violation-error.d.ts +5 -5
  12. package/dist/context-violation-error.d.ts.map +1 -1
  13. package/dist/context-violation-error.js +5 -5
  14. package/dist/create-hook.d.ts +2 -2
  15. package/dist/create-hook.js +1 -1
  16. package/dist/define-hook.js +2 -2
  17. package/dist/describe-error.d.ts +7 -7
  18. package/dist/describe-error.js +8 -8
  19. package/dist/encryption.d.ts +5 -5
  20. package/dist/encryption.js +7 -7
  21. package/dist/events-consumer.d.ts +20 -8
  22. package/dist/events-consumer.d.ts.map +1 -1
  23. package/dist/events-consumer.js +34 -12
  24. package/dist/flushable-stream.d.ts +4 -4
  25. package/dist/flushable-stream.js +13 -13
  26. package/dist/global.d.ts +4 -2
  27. package/dist/global.d.ts.map +1 -1
  28. package/dist/global.js +8 -5
  29. package/dist/index.d.ts +1 -1
  30. package/dist/index.js +2 -2
  31. package/dist/log-format.d.ts +2 -2
  32. package/dist/log-format.js +5 -5
  33. package/dist/logger.js +4 -4
  34. package/dist/private.d.ts +29 -71
  35. package/dist/private.d.ts.map +1 -1
  36. package/dist/private.js +170 -38
  37. package/dist/replay-payload-cache.d.ts +1 -1
  38. package/dist/replay-payload-cache.js +4 -4
  39. package/dist/runtime/compute-instance.d.ts +4 -3
  40. package/dist/runtime/compute-instance.d.ts.map +1 -1
  41. package/dist/runtime/compute-instance.js +5 -4
  42. package/dist/runtime/constants.d.ts +24 -24
  43. package/dist/runtime/constants.d.ts.map +1 -1
  44. package/dist/runtime/constants.js +49 -43
  45. package/dist/runtime/count-step-started-events.d.ts +7 -7
  46. package/dist/runtime/count-step-started-events.js +4 -4
  47. package/dist/runtime/deployment-guard.d.ts +7 -7
  48. package/dist/runtime/deployment-guard.js +8 -8
  49. package/dist/runtime/get-port-lazy.d.ts +2 -2
  50. package/dist/runtime/get-port-lazy.d.ts.map +1 -1
  51. package/dist/runtime/get-port-lazy.js +37 -30
  52. package/dist/runtime/get-world-lazy.d.ts +2 -2
  53. package/dist/runtime/get-world-lazy.js +3 -3
  54. package/dist/runtime/helpers.d.ts +21 -21
  55. package/dist/runtime/helpers.js +27 -27
  56. package/dist/runtime/quickjs-entrypoint.d.ts +21 -10
  57. package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -1
  58. package/dist/runtime/quickjs-entrypoint.js +206 -81
  59. package/dist/runtime/quickjs-runtime.d.ts +31 -15
  60. package/dist/runtime/quickjs-runtime.d.ts.map +1 -1
  61. package/dist/runtime/quickjs-runtime.js +132 -77
  62. package/dist/runtime/quickjs-serde.d.ts +10 -10
  63. package/dist/runtime/quickjs-serde.js +20 -20
  64. package/dist/runtime/replay-budget.d.ts +4 -4
  65. package/dist/runtime/replay-budget.js +5 -5
  66. package/dist/runtime/replay-recovery-reporter.d.ts +1 -1
  67. package/dist/runtime/replay-recovery-reporter.js +2 -2
  68. package/dist/runtime/resume-hook.d.ts +27 -12
  69. package/dist/runtime/resume-hook.d.ts.map +1 -1
  70. package/dist/runtime/resume-hook.js +200 -200
  71. package/dist/runtime/resume-latency.d.ts +40 -30
  72. package/dist/runtime/resume-latency.d.ts.map +1 -1
  73. package/dist/runtime/resume-latency.js +7 -5
  74. package/dist/runtime/run-id-time.d.ts +2 -2
  75. package/dist/runtime/run-id-time.js +5 -5
  76. package/dist/runtime/run.d.ts +22 -5
  77. package/dist/runtime/run.d.ts.map +1 -1
  78. package/dist/runtime/run.js +106 -11
  79. package/dist/runtime/runs.d.ts +4 -4
  80. package/dist/runtime/runs.js +2 -2
  81. package/dist/runtime/start.d.ts +3 -3
  82. package/dist/runtime/start.d.ts.map +1 -1
  83. package/dist/runtime/start.js +29 -25
  84. package/dist/runtime/step-executor.d.ts +14 -14
  85. package/dist/runtime/step-executor.d.ts.map +1 -1
  86. package/dist/runtime/step-executor.js +54 -39
  87. package/dist/runtime/step-latency.d.ts +42 -25
  88. package/dist/runtime/step-latency.d.ts.map +1 -1
  89. package/dist/runtime/step-latency.js +29 -23
  90. package/dist/runtime/step-ownership.d.ts +6 -6
  91. package/dist/runtime/step-ownership.js +8 -8
  92. package/dist/runtime/step-single-flight.d.ts +1 -1
  93. package/dist/runtime/step-single-flight.d.ts.map +1 -1
  94. package/dist/runtime/step-single-flight.js +17 -11
  95. package/dist/runtime/suspension-handler.d.ts +38 -24
  96. package/dist/runtime/suspension-handler.d.ts.map +1 -1
  97. package/dist/runtime/suspension-handler.js +238 -103
  98. package/dist/runtime/unserializable-step.d.ts +34 -0
  99. package/dist/runtime/unserializable-step.d.ts.map +1 -0
  100. package/dist/runtime/unserializable-step.js +52 -0
  101. package/dist/runtime/vm-mode.d.ts +1 -1
  102. package/dist/runtime/vm-mode.js +2 -2
  103. package/dist/runtime/wait-continuation.d.ts +31 -9
  104. package/dist/runtime/wait-continuation.d.ts.map +1 -1
  105. package/dist/runtime/wait-continuation.js +44 -13
  106. package/dist/runtime/wait-until.d.ts +1 -1
  107. package/dist/runtime/wait-until.js +2 -2
  108. package/dist/runtime/world-compatibility.d.ts +20 -9
  109. package/dist/runtime/world-compatibility.d.ts.map +1 -1
  110. package/dist/runtime/world-compatibility.js +24 -13
  111. package/dist/runtime/world-init.d.ts +5 -5
  112. package/dist/runtime/world-init.js +6 -6
  113. package/dist/runtime/world.d.ts.map +1 -1
  114. package/dist/runtime/world.js +13 -3
  115. package/dist/runtime.d.ts.map +1 -1
  116. package/dist/runtime.js +427 -266
  117. package/dist/sealed-box.d.ts +7 -7
  118. package/dist/sealed-box.js +15 -15
  119. package/dist/serialization/client.js +2 -2
  120. package/dist/serialization/codec-devalue-vm.d.ts +1 -1
  121. package/dist/serialization/codec-devalue-vm.js +4 -4
  122. package/dist/serialization/codec-devalue.d.ts +1 -1
  123. package/dist/serialization/codec-devalue.js +2 -2
  124. package/dist/serialization/codec.d.ts +4 -4
  125. package/dist/serialization/codec.js +2 -2
  126. package/dist/serialization/compression.d.ts +12 -11
  127. package/dist/serialization/compression.d.ts.map +1 -1
  128. package/dist/serialization/compression.js +16 -15
  129. package/dist/serialization/encryption.d.ts +7 -7
  130. package/dist/serialization/encryption.d.ts.map +1 -1
  131. package/dist/serialization/encryption.js +8 -8
  132. package/dist/serialization/errors.js +2 -2
  133. package/dist/serialization/format.d.ts +6 -6
  134. package/dist/serialization/format.js +7 -7
  135. package/dist/serialization/hardened.d.ts +23 -22
  136. package/dist/serialization/hardened.d.ts.map +1 -1
  137. package/dist/serialization/hardened.js +47 -32
  138. package/dist/serialization/index.d.ts +1 -1
  139. package/dist/serialization/index.js +2 -2
  140. package/dist/serialization/reducers/class-vm.d.ts +1 -1
  141. package/dist/serialization/reducers/class-vm.js +2 -2
  142. package/dist/serialization/reducers/class.js +2 -2
  143. package/dist/serialization/reducers/common-vm.js +12 -12
  144. package/dist/serialization/reducers/common.js +12 -12
  145. package/dist/serialization/reducers/step-function-vm.d.ts +1 -1
  146. package/dist/serialization/reducers/step-function-vm.js +2 -2
  147. package/dist/serialization/reducers/step-function.js +2 -2
  148. package/dist/serialization/step.js +2 -2
  149. package/dist/serialization/types.d.ts +5 -5
  150. package/dist/serialization/types.js +2 -2
  151. package/dist/serialization/workflow-vm.d.ts +1 -1
  152. package/dist/serialization/workflow-vm.d.ts.map +1 -1
  153. package/dist/serialization/workflow-vm.js +13 -10
  154. package/dist/serialization-format.d.ts +11 -11
  155. package/dist/serialization-format.d.ts.map +1 -1
  156. package/dist/serialization-format.js +30 -24
  157. package/dist/serialization.d.ts +15 -16
  158. package/dist/serialization.d.ts.map +1 -1
  159. package/dist/serialization.js +116 -109
  160. package/dist/set-attributes.js +2 -2
  161. package/dist/source-map.d.ts +1 -1
  162. package/dist/source-map.d.ts.map +1 -1
  163. package/dist/source-map.js +18 -12
  164. package/dist/step/context-storage.d.ts +5 -5
  165. package/dist/step/context-storage.js +1 -1
  166. package/dist/step/writable-stream.d.ts +3 -3
  167. package/dist/step/writable-stream.js +7 -7
  168. package/dist/step.d.ts.map +1 -1
  169. package/dist/step.js +14 -22
  170. package/dist/symbols.d.ts +2 -2
  171. package/dist/symbols.js +3 -3
  172. package/dist/telemetry/semantic-conventions.d.ts +34 -17
  173. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  174. package/dist/telemetry/semantic-conventions.js +32 -17
  175. package/dist/telemetry.d.ts +3 -3
  176. package/dist/telemetry.d.ts.map +1 -1
  177. package/dist/telemetry.js +19 -10
  178. package/dist/test-support/orchestrator-context.d.ts.map +1 -1
  179. package/dist/test-support/orchestrator-context.js +12 -2
  180. package/dist/version.d.ts +1 -1
  181. package/dist/version.js +2 -2
  182. package/dist/vm/index.js +4 -4
  183. package/dist/vm/script-cache.d.ts.map +1 -1
  184. package/dist/vm/script-cache.js +23 -17
  185. package/dist/vm/uint8array-base64.js +1 -1
  186. package/dist/workflow/abort-controller.d.ts +1 -1
  187. package/dist/workflow/abort-controller.js +12 -12
  188. package/dist/workflow/attribute-dispatcher.d.ts.map +1 -1
  189. package/dist/workflow/attribute-dispatcher.js +3 -6
  190. package/dist/workflow/create-hook.js +2 -2
  191. package/dist/workflow/get-workflow-metadata.js +2 -2
  192. package/dist/workflow/hook.d.ts.map +1 -1
  193. package/dist/workflow/hook.js +21 -30
  194. package/dist/workflow/set-attributes.d.ts +1 -1
  195. package/dist/workflow/set-attributes.js +2 -2
  196. package/dist/workflow/sleep.js +2 -2
  197. package/dist/workflow/world-init-stub.d.ts +1 -1
  198. package/dist/workflow/world-init-stub.js +2 -2
  199. package/dist/workflow.d.ts +2 -2
  200. package/dist/workflow.js +26 -13
  201. package/docs/api-reference/create-hook.mdx +15 -15
  202. package/docs/api-reference/create-webhook.mdx +15 -15
  203. package/docs/api-reference/define-hook.mdx +10 -10
  204. package/docs/api-reference/fatal-error.mdx +2 -2
  205. package/docs/api-reference/fetch.mdx +7 -7
  206. package/docs/api-reference/get-step-metadata.mdx +2 -2
  207. package/docs/api-reference/get-workflow-metadata.mdx +3 -3
  208. package/docs/api-reference/get-writable.mdx +7 -7
  209. package/docs/api-reference/index.mdx +1 -1
  210. package/docs/api-reference/retryable-error.mdx +1 -1
  211. package/docs/api-reference/set-attributes.mdx +2 -2
  212. package/docs/api-reference/sleep.mdx +3 -3
  213. package/docs/foundations/cancellation.mdx +31 -31
  214. package/docs/foundations/errors-and-retries.mdx +42 -11
  215. package/docs/foundations/hooks.mdx +35 -35
  216. package/docs/foundations/idempotency.mdx +9 -9
  217. package/docs/foundations/serialization.mdx +21 -22
  218. package/docs/foundations/starting-workflows.mdx +36 -37
  219. package/docs/foundations/streaming.mdx +46 -41
  220. package/docs/foundations/versioning.mdx +3 -3
  221. package/docs/foundations/workflows-and-steps.mdx +9 -9
  222. package/docs/how-it-works/cancellation.mdx +62 -62
  223. package/docs/how-it-works/code-transform.mdx +66 -54
  224. package/docs/how-it-works/encryption.mdx +25 -21
  225. package/docs/how-it-works/event-sourcing.mdx +53 -35
  226. package/docs/how-it-works/framework-integrations.mdx +12 -12
  227. package/docs/how-it-works/understanding-directives.mdx +21 -21
  228. package/package.json +7 -7
@@ -2,7 +2,6 @@ import { EntityConflictError, ERROR_SLUGS, HookNotFoundError, RunExpiredError, W
2
2
  import { HOOK_RESUME_DEDUP_VERSION, HOOK_RESUME_INPUT_VERSION, isLegacySpecVersion, isTerminalWorkflowRunStatus, SPEC_VERSION_CURRENT, SPEC_VERSION_LEGACY, SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT, SPEC_VERSION_SUPPORTS_COMPRESSION, } from '@workflow/world';
3
3
  import { monotonicFactory } from 'ulid';
4
4
  import { getRunCapabilities } from '../capabilities.js';
5
- import { isRetryableWorldError } from '../classify-error.js';
6
5
  import { importKey } from '../encryption.js';
7
6
  import { runtimeLogger } from '../logger.js';
8
7
  import { decodeRunPublicKey } from '../sealed-box.js';
@@ -17,23 +16,25 @@ import { safeWaitUntil, waitedUntil } from './wait-until.js';
17
16
  /** Monotonic ULID factory for per-call resume idempotency keys. */
18
17
  const generateResumeId = monotonicFactory();
19
18
  /**
20
- * Upper bound on the serialized hook payload that the parallel fast path will
21
- * inline into the queue message's `hookInput`. Vercel Queues caps a single
22
- * message at ~256 KiB, and the message also carries the runId, hookId, token,
23
- * resumeId, digest, and trace carrier alongside CBOR framing overhead. Staying
24
- * well under that ceiling keeps the queue publish from rejecting an oversized
25
- * message — which, on the parallel path, would persist `hook_received` but never
26
- * re-trigger the run. Above this size we fall back to the sequential path, whose
27
- * queue message carries only the run ID (the payload lives in the event log).
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
28
  */
29
29
  const MAX_INLINE_RESUME_PAYLOAD_BYTES = 128 * 1024;
30
30
  /**
31
31
  * Hex SHA-256 of the serialized resume payload bytes. Computed once by the
32
- * producer and forwarded verbatim on both the direct `hook_received` write and
33
- * the queue `hookInput`, so both writers of the same `resumeId` record an
34
- * identical digest on the server's `(runId, resumeId)` constraint. Hashing the
35
- * already-serialized bytes (not the raw value) keeps producer and consumer in
36
- * lockstep the consumer forwards this string without recomputing.
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.
37
38
  */
38
39
  async function computeResumePayloadDigest(bytes) {
39
40
  const digest = await crypto.subtle.digest('SHA-256', bytes);
@@ -65,8 +66,8 @@ function resumeContextFromRun(run) {
65
66
  }
66
67
  /**
67
68
  * Resolve resume context for a hook. Uses the stored `resumeContext` when
68
- * present (fast path no run read); otherwise fetches the run and synthesizes
69
- * it. Does NOT resolve the encryption key callers do that separately. Only
69
+ * present (fast path, no run read); otherwise fetches the run and synthesizes
70
+ * it. Does NOT resolve the encryption key; callers do that separately. Only
70
71
  * the fallback path can gate key work behind a local terminal-run check (it
71
72
  * has the fetched run); the fast path's stored context carries no status, so
72
73
  * seal/serialization work may run before the receiving side rejects
@@ -85,7 +86,7 @@ async function resolveHookResumeInfo(hook) {
85
86
  }
86
87
  /**
87
88
  * Resolve the run's symmetric key for a payload WRITE, as a bare `CryptoKey`
88
- * (`importKey`) the `encr` write fallback used when the run published no
89
+ * (`importKey`): the `encr` write fallback used when the run published no
89
90
  * public key to seal to. Writing needs only the AES key, not the read-side
90
91
  * keypair. On the fast path this needs only `runId` + `deploymentId` (no run
91
92
  * entity); on the fallback path the already fetched run is reused.
@@ -105,7 +106,7 @@ async function getHookByTokenWithKey(token) {
105
106
  // Only a hook that actually carries metadata needs the run's key resolved
106
107
  // here: hydrating that metadata is a READ, so derive the full RunPayloadKeys
107
108
  // (which opens sealed `encp` metadata, not just symmetric `encr`). The common
108
- // default webhook createWebhook() with no `respondWith` stores no
109
+ // default webhook (createWebhook() with no `respondWith`) stores no
109
110
  // metadata, so it skips this entirely: no ~350ms `run-key` API round trip,
110
111
  // and, crucially, no resolved key handed to `resumeHook`, leaving it free to
111
112
  // seal the payload to the run's published public key instead. Metadata-
@@ -170,8 +171,8 @@ export async function getHookByToken(token) {
170
171
  */
171
172
  export async function resumeHook(tokenOrHook, payload, encryptionKeyOverride) {
172
173
  // Public entry point. It never attests hook freshness, so a Hook object
173
- // supplied here which may carry a `resumeCapabilities` cached before a
174
- // server rollback or kill switch is ignored by the dynamic-dedup gate and
174
+ // supplied here (which may carry a `resumeCapabilities` cached before a
175
+ // server rollback or kill switch) is ignored by the dynamic-dedup gate and
175
176
  // fails closed to the sequential path. Only `resumeWebhook`, which fetches
176
177
  // the hook by token in-line during the same resume, reaches the internal
177
178
  // implementation with the fresh attestation set. Keeping the freshness flag
@@ -179,8 +180,30 @@ export async function resumeHook(tokenOrHook, payload, encryptionKeyOverride) {
179
180
  // `true` and reactivating dynamic dedup against a rolled-back backend.
180
181
  //
181
182
  // T0 of the hook-resume TTR window is taken HERE, at the public entry point,
182
- // rather than inside the implementation see the parameter's doc comment.
183
- return resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, false, Date.now());
183
+ // 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);
184
207
  }
185
208
  /**
186
209
  * Internal implementation of {@link resumeHook}. NOT exported: the
@@ -194,12 +217,14 @@ export async function resumeHook(tokenOrHook, payload, encryptionKeyOverride) {
194
217
  * @param resumeRequestedAtMs - T0 of the hook-resume TTR window (see
195
218
  * runtime/resume-latency.ts), stamped by the PUBLIC entry point the caller
196
219
  * used. It is a parameter rather than a local because `resumeWebhook` does
197
- * real work before it gets here the by-token lookup, the run-key
198
- * resolution that hydrates hook metadata, and the `respondWith` setup and
220
+ * real work before it gets here (the by-token lookup, the run-key
221
+ * resolution that hydrates hook metadata, and the `respondWith` setup) and
199
222
  * stamping locally would silently exclude all of it, so the two entry points
200
223
  * 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}.
201
226
  */
202
- async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs) {
227
+ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs, requireDurableWrite) {
203
228
  return await waitedUntil(() => {
204
229
  return trace('hook.resume', async (span) => {
205
230
  const world = await getWorldLazy();
@@ -224,7 +249,7 @@ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookF
224
249
  // fallback path (which fetched the run). On the fast path the terminal
225
250
  // check happens server-side: `hook_received` against an ended run is
226
251
  // rejected, which the catch around `world.events.create` below re-keys
227
- // to HookNotFoundError same public contract, no run pre-fetch.
252
+ // to HookNotFoundError: same public contract, no run pre-fetch.
228
253
  if (info.run && isTerminalWorkflowRunStatus(info.run.status)) {
229
254
  throw new HookNotFoundError(hook.token);
230
255
  }
@@ -238,7 +263,7 @@ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookF
238
263
  //
239
264
  // Preferred path: seal to the run's published X25519 public key, which
240
265
  // the stored `resumeContext` carries inline. On the fast path this is
241
- // the whole win no run read AND no `getEncryptionKeyForRun`, whose
266
+ // the whole win: no run read AND no `getEncryptionKeyForRun`, whose
242
267
  // ~350ms `run-key` API round trip dominates cross-deployment hook
243
268
  // resumption latency. (On the fallback path the key is synthesized
244
269
  // from the fetched run, which also carries it.)
@@ -252,7 +277,7 @@ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookF
252
277
  // is itself the gate. A run only carries one if the runtime that
253
278
  // created it could also open a sealed payload, and runs are pinned to
254
279
  // their creating deployment, so presence is a more reliable attestation
255
- // than a version compare and it stays correct even when package
280
+ // than a version compare, and it stays correct even when package
256
281
  // versions drift.
257
282
  let payloadKey;
258
283
  const runPublicKey = encryptionKeyOverride
@@ -304,37 +329,34 @@ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookF
304
329
  });
305
330
  // Link to the run-origin context from the stored trace carrier
306
331
  // (skipped when absent or invalid). Resolved before dispatch so both
307
- // the sequential and parallel paths attach it.
332
+ // the sequential and lazy paths attach it.
308
333
  const originLink = await linkToTraceCarrier(resumeContext.traceCarrier);
309
334
  if (originLink) {
310
335
  span?.addLink?.(originLink);
311
336
  }
312
- const eventData = {
313
- ...(v1Compat ? {} : { token: hook.token }),
314
- payload: dehydratedPayload,
315
- };
316
337
  const queueName = getWorkflowQueueName(resumeContext.workflowName);
317
338
  const queueOptions = {
318
339
  deploymentId: resumeContext.deploymentId,
319
340
  specVersion: resumeContext.runSpecVersion ?? SPEC_VERSION_LEGACY,
320
341
  };
321
- // Decide whether to parallelize the `hook_received` write and the queue
322
- // publish. The fast path is only safe when EVERY precondition holds; the
323
- // first that fails names the fallback reason (emitted as a span
324
- // attribute for observability, and to make "why did this run sequential"
325
- // answerable in production). All conditions:
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:
326
348
  //
327
349
  // - kill switch: `WORKFLOW_DISABLE_LAZY_HOOK_RESUME` forces sequential
328
- // if the fast path ever misbehaves. It is an SDK-deployment env var,
350
+ // if the lazy path ever misbehaves. It is an SDK-deployment env var,
329
351
  // so changing it generally requires redeploying the workflow
330
352
  // deployment. (The backend can independently drop new resumes to the
331
353
  // sequential path fleet-wide by ceasing to attest dedup support on
332
- // the by-token lookup see the backend-dedup condition below.)
354
+ // the by-token lookup; see the backend-dedup condition below.)
333
355
  // - backend dedup: the live backend must enforce the
334
- // `(runId, resumeId)` constraint, or the two writers would commit two
335
- // `hook_received` events. Fail closed. Attested by EITHER a fresh,
356
+ // `(runId, resumeId)` constraint, or a queue redelivery would commit
357
+ // a second `hook_received`. Fail closed. Attested by EITHER a fresh,
336
358
  // response-only `hook.resumeCapabilities.hookResumeDedupVersion` from
337
- // the by-token lookup (world-vercel recomputed every read, so a
359
+ // the by-token lookup (world-vercel: recomputed every read, so a
338
360
  // server rollback or kill switch drops to sequential immediately) OR
339
361
  // the static `world.capabilities.hookResumeDedup` (world-local, whose
340
362
  // adapter and backend ship together). The response-only capability is
@@ -342,23 +364,26 @@ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookF
342
364
  // resume (`hookResumeCapabilitiesAreFresh`); a Hook object handed in
343
365
  // by a public caller may carry a capability cached before a rollback,
344
366
  // so it is ignored and the path falls back to sequential.
345
- // - consumer support: the target run's deployment must re-ensure the
367
+ // - consumer support: the target run's deployment must materialize the
346
368
  // event from `hookInput` on replay. Attested by the run's explicit
347
369
  // `hookResumeInputVersion` execution-context marker (mirrored onto
348
370
  // resumeContext), NOT a version-compare against a predicted release
349
- // cutoff. Absent → a lost producer write would be a lost resume.
350
- // - not legacy: v1Compat runs omit `token` from the producer's event
351
- // body but the consumer's re-ensure always includes it, so the two
352
- // writers would disagree on the event body. Legacy stays sequential.
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.
353
377
  // - CBOR transport: the run must use CBOR queue transport so the binary
354
378
  // payload survives the queue message.
355
379
  // - raw bytes: the dehydrated payload must be a `Uint8Array` (the
356
380
  // content digest that keys the dedup constraint is over these bytes).
357
- // - size: a payload above the queue's message ceiling would fail the
358
- // publish — which, on the parallel path, would persist the event but
359
- // never re-trigger the run so oversized payloads stay sequential
360
- // (their queue message carries only the run ID).
361
- const parallelResumeDisabled = process.env.WORKFLOW_DISABLE_LAZY_HOOK_RESUME === '1';
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';
362
387
  // Backend dedup is supported when EITHER the live server attests it
363
388
  // fresh on this by-token hook (world-vercel: response-only, recomputed
364
389
  // every read, so rollback/kill-switch take effect immediately) OR the
@@ -369,62 +394,73 @@ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookF
369
394
  ? (hook.resumeCapabilities?.hookResumeDedupVersion ?? 0)
370
395
  : 0) >= HOOK_RESUME_DEDUP_VERSION ||
371
396
  world.capabilities?.hookResumeDedup === true;
372
- const fallbackReason = parallelResumeDisabled
373
- ? 'disabled'
374
- : !backendDedupSupported
375
- ? 'backend_unsupported'
376
- : (resumeContext.hookResumeInputVersion ?? 0) <
377
- HOOK_RESUME_INPUT_VERSION
378
- ? 'consumer_unsupported'
379
- : v1Compat
380
- ? 'legacy'
381
- : (resumeContext.runSpecVersion ?? 0) <
382
- SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT
383
- ? 'non_cbor_transport'
384
- : !(dehydratedPayload instanceof Uint8Array)
385
- ? 'non_bytes'
386
- : dehydratedPayload.byteLength >
387
- MAX_INLINE_RESUME_PAYLOAD_BYTES
388
- ? 'oversized'
389
- : null;
390
- const useParallelResume = fallbackReason === null;
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;
391
422
  span?.setAttributes({
392
- 'workflow.hook.resume_strategy': useParallelResume
393
- ? 'parallel'
423
+ 'workflow.hook.resume_strategy': useLazyResume
424
+ ? 'lazy'
394
425
  : 'sequential',
395
426
  ...(fallbackReason
396
427
  ? { 'workflow.hook.resume_fallback_reason': fallbackReason }
397
428
  : {}),
398
429
  });
399
- // Re-key any "hook can no longer be received" rejection to
400
- // HookNotFoundError(hook.token) so `.token` matches the pre-fast-path
401
- // contract, where resumeHook threw `HookNotFoundError(hook.token)`
402
- // after its own terminal check. The specific error depends on the
403
- // World:
404
- // - a genuinely missing hook maps to HookNotFoundError (keyed on the
405
- // event correlationId / hook ID);
406
- // - a terminal run on Vercel rejects hook_received with 404, which
407
- // world-vercel maps to HookNotFoundError;
408
- // - a terminal run on world-local / world-postgres rejects with
409
- // RunExpiredError.
410
- //
411
- // On the SEQUENTIAL path an EntityConflictError (HTTP 409) is also
412
- // treated as "hook gone" for historical / conflict-shaped-rejection
413
- // compatibility: there is no queue message in flight, so a conflict has
414
- // no re-ensuring consumer to converge on. The PARALLEL path handles 409
415
- // differently (see below) — it published the queue message before the
416
- // conflict, so the consumer will converge the event.
417
- const isHookGoneError = (err) => HookNotFoundError.is(err) ||
418
- EntityConflictError.is(err) ||
419
- RunExpiredError.is(err);
420
- if (!useParallelResume) {
430
+ if (!useLazyResume) {
421
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);
422
455
  try {
423
456
  await world.events.create(hook.runId, {
424
457
  eventType: 'hook_received',
425
458
  specVersion: SPEC_VERSION_CURRENT,
426
459
  correlationId: hook.hookId,
427
- eventData,
460
+ eventData: {
461
+ ...(v1Compat ? {} : { token: hook.token }),
462
+ payload: dehydratedPayload,
463
+ },
428
464
  }, { v1Compat });
429
465
  }
430
466
  catch (err) {
@@ -435,7 +471,7 @@ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookF
435
471
  }
436
472
  // T1 of the TTR window. Stamped immediately before the publish so
437
473
  // `producer_prep` covers exactly the work above it (hook lookup,
438
- // key resolution, serialization, and on this path the awaited
474
+ // key resolution, serialization, and, on this path, the awaited
439
475
  // `hook_received` write, which is genuinely serial here).
440
476
  const queuePublishRequestedAtMs = Date.now();
441
477
  await world.queue(queueName, {
@@ -449,105 +485,69 @@ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookF
449
485
  }, queueOptions);
450
486
  return hook;
451
487
  }
452
- // Parallel fast path. A stable idempotency key ties the direct write to
453
- // the queue consumer's re-ensure; the payload digest lets the server
454
- // detect key reuse across byte-identical payloads.
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).
499
+ //
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.
455
519
  const resumeId = generateResumeId();
456
520
  const payloadDigest = await computeResumePayloadDigest(dehydratedPayload);
457
521
  span?.setAttributes({ 'workflow.hook.resume_id': resumeId });
458
- // Wrapped in a thunk purely so T1 of the TTR window is stamped at the
459
- // exact instant the publish is requested after the racing
460
- // `hook_received` write has been kicked off, which is where the
461
- // additive `producer_prep` phase must end. The two calls still start
462
- // in the same turn and race exactly as before.
463
- const publishInvocation = () => {
464
- const queuePublishRequestedAtMs = Date.now();
465
- return world.queue(queueName, {
466
- runId: hook.runId,
467
- traceCarrier: resumeContext.traceCarrier ?? undefined,
468
- hookInput: {
469
- resumeId,
470
- hookId: hook.hookId,
471
- token: hook.token,
472
- payload: dehydratedPayload,
473
- payloadDigest,
474
- // Deployment affinity for the consumer's cheap pre-write
475
- // check: lets a misrouted delivery re-route before its
476
- // hoisted hook_received write instead of after.
477
- deploymentId: resumeContext.deploymentId,
478
- },
479
- hookResumeTiming: {
480
- resumeRequestedAtMs,
481
- queuePublishRequestedAtMs,
482
- strategy: 'parallel',
483
- },
484
- }, queueOptions);
485
- };
486
- const [eventResult, queueResult] = await Promise.allSettled([
487
- world.events.create(hook.runId, {
488
- eventType: 'hook_received',
489
- specVersion: SPEC_VERSION_CURRENT,
490
- correlationId: hook.hookId,
491
- eventData,
492
- }, { v1Compat, resumeId, resumePayloadDigest: payloadDigest }),
493
- publishInvocation(),
494
- ]);
495
- // Queue failure is always fatal — the run was not re-triggered, so no
496
- // consumer will re-ensure the event.
497
- if (queueResult.status === 'rejected') {
498
- throw queueResult.reason;
499
- }
500
- // Set when the direct write did not land but the queue dispatch did, so
501
- // the consumer materializes the event before replay. Surfaced to the
502
- // caller as `ResumedHook.resilientResume` and on the span.
503
- let resilientResume = false;
504
- if (eventResult.status === 'rejected') {
505
- const err = eventResult.reason;
506
- if (HookNotFoundError.is(err) || RunExpiredError.is(err)) {
507
- // The hook's run has genuinely ended: surface the same contract as
508
- // the sequential path. The queue message already went out, but the
509
- // consumer's re-ensure will also reject against the terminal run
510
- // and no-op, so the workflow does not resume.
511
- throw new HookNotFoundError(hook.token);
512
- }
513
- if (EntityConflictError.is(err) || isRetryableWorldError(err)) {
514
- // Resilient. Two shapes reach here, both non-terminal:
515
- // - EntityConflict (409): this write raced its own re-ensuring
516
- // consumer (or a redrive) on the shared `resumeId` — the run is
517
- // NOT gone, and the consumer converges on the one committed
518
- // event. Unlike the sequential path, a 409 here is expected
519
- // concurrency, not a vanished hook.
520
- // - 429 / 5xx / transport: a transient backend failure.
521
- // In both cases the run WAS re-triggered via the queue and the
522
- // consumer idempotently ensures the hook_received before replay, so
523
- // swallow rather than failing the caller.
524
- //
525
- // Producer telemetry: record that the direct write did not land but
526
- // the resume is still guaranteed via queue-delivered `hookInput`.
527
- // This is the operational signal that the recovery path fired,
528
- // surfaced both on the span and as the public `resilientResume`
529
- // flag on the returned hook (the resume outcome is otherwise
530
- // identical to the happy path from the caller's perspective).
531
- resilientResume = true;
532
- span?.setAttributes({
533
- ...Attribute.HookResilientResume(true),
534
- 'workflow.hook.resume_event_write_recovered': true,
535
- 'workflow.hook.resume_event_write_error': err instanceof Error ? err.name : 'unknown',
536
- });
537
- runtimeLogger.warn('Hook resume event write failed, but the run was re-triggered via ' +
538
- 'the queue. The hook_received event will be ensured by the ' +
539
- 'queue consumer.', {
540
- workflowRunId: hook.runId,
541
- hookId: hook.hookId,
542
- resumeId,
543
- error: err instanceof Error ? err.message : String(err),
544
- });
545
- }
546
- else {
547
- throw err;
548
- }
549
- }
550
- return (resilientResume ? { ...hook, resilientResume: true } : hook);
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.
526
+ const queuePublishRequestedAtMs = Date.now();
527
+ await world.queue(queueName, {
528
+ runId: hook.runId,
529
+ 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
+ hookResumeTiming: {
542
+ resumeRequestedAtMs,
543
+ queuePublishRequestedAtMs,
544
+ strategy: 'lazy',
545
+ },
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.
550
+ return hook;
551
551
  }
552
552
  catch (err) {
553
553
  span?.setAttributes({
@@ -595,8 +595,8 @@ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookF
595
595
  * ```
596
596
  */
597
597
  export async function resumeWebhook(token, request) {
598
- // T0 of the hook-resume TTR window. Everything below the by-token lookup,
599
- // the run-key resolution it may trigger, and the `respondWith` setup is
598
+ // T0 of the hook-resume TTR window. Everything below (the by-token lookup,
599
+ // the run-key resolution it may trigger, and the `respondWith` setup) is
600
600
  // real producer-side latency on this path, so the window has to open here
601
601
  // and not inside `resumeHookImpl`; otherwise webhook resumes would report a
602
602
  // systematically shorter total than `resumeHook` ones into the same metric.
@@ -634,10 +634,10 @@ export async function resumeWebhook(token, request) {
634
634
  }
635
635
  // `hook` was just fetched via `getHookByTokenWithKey` (a fresh by-token
636
636
  // lookup) above, so its response-only `resumeCapabilities` reflects the live
637
- // backend call the internal implementation with the fresh attestation so
638
- // the parallel fast path stays available without a second GET. (The public
637
+ // backend. Call the internal implementation with the fresh attestation so
638
+ // the lazy path stays available without a second GET. (The public
639
639
  // `resumeHook` never sets this, so a caller cannot forge it.)
640
- await resumeHookImpl(hook, request, encryptionKey, true, resumeRequestedAtMs);
640
+ await resumeHookImpl(hook, request, encryptionKey, true, resumeRequestedAtMs, false);
641
641
  if (responseReadable) {
642
642
  // Wait for the readable stream to emit one chunk,
643
643
  // which is the `Response` object
@@ -655,4 +655,4 @@ export async function resumeWebhook(token, request) {
655
655
  }
656
656
  return response;
657
657
  }
658
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzdW1lLWhvb2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVudGltZS9yZXN1bWUtaG9vay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLFdBQVcsRUFDWCxpQkFBaUIsRUFDakIsZUFBZSxFQUNmLG9CQUFvQixHQUNyQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFDTCx5QkFBeUIsRUFDekIseUJBQXlCLEVBR3pCLG1CQUFtQixFQUNuQiwyQkFBMkIsRUFDM0Isb0JBQW9CLEVBQ3BCLG1CQUFtQixFQUNuQiwwQ0FBMEMsRUFDMUMsaUNBQWlDLEdBR2xDLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzdELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3RFLE9BQU8sRUFDTCx3QkFBd0IsRUFDeEIsb0JBQW9CLEVBRXBCLG1CQUFtQixFQUNuQixNQUFNLEdBQ1AsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUQsT0FBTyxLQUFLLFNBQVMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsS0FBSyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDNUQsT0FBTyxFQUFFLFlBQVksRUFB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SUFBSSxvQkFBb0IsQ0FDNUIsa0NBQWtDLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLEVBQzdELEVBQUUsSUFBSSxFQUFFLFdBQVcsQ0FBQyxrQ0FBa0MsRUFBRSxDQUN6RCxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7U0FBTSxDQUFDO1FBQ04seUVBQXlFO1FBQ3pFLFFBQVEsR0FBRyxJQUFJLFFBQVEsQ0FBQyxJQUFJLEVBQUUsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRUQsd0VBQXdFO0lBQ3hFLDZFQUE2RTtJQUM3RSwyRUFBMkU7SUFDM0UsMkVBQTJFO0lBQzNFLDhEQUE4RDtJQUM5RCxNQUFNLGNBQWMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztJQUU5RSxJQUFJLGdCQUFnQixFQUFFLENBQUM7UUFDckIsa0RBQWtEO1FBQ2xELGlDQUFpQztRQUNqQyxNQUFNLE1BQU0sR0FBRyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUM1QyxNQUFNLEtBQUssR0FBRyxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNsQyxJQUFJLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNoQixRQUFRLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQztRQUN6QixDQUFDO1FBQ0QsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ2xCLENBQUM7SUFFRCxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDZCxNQUFNLElBQUksb0JBQW9CLENBQUMsc0NBQXNDLEVBQUU7WUFDckUsSUFBSSxFQUFFLFdBQVcsQ0FBQyx5QkFBeUI7U0FDNUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBFbnRpdHlDb25mbGljdEVycm9yLFxuICBFUlJPUl9TTFVHUyxcbiAgSG9va05vdEZvdW5kRXJyb3IsXG4gIFJ1bkV4cGlyZWRFcnJvcixcbiAgV29ya2Zsb3dSdW50aW1lRXJyb3IsXG59IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHtcbiAgSE9PS19SRVNVTUVfREVEVVBfVkVSU0lPTixcbiAgSE9PS19SRVNVTUVfSU5QVVRfVkVSU0lPTixcbiAgdHlwZSBIb29rLFxuICB0eXBlIEhvb2tSZXN1bWVDb250ZXh0LFxuICBpc0xlZ2FjeVNwZWNWZXJzaW9uLFxuICBpc1Rlcm1pbmFsV29ya2Zsb3dSdW5TdGF0dXMsXG4gIFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICBTUEVDX1ZFUlNJT05fTEVHQUNZLFxuICBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ0JPUl9RVUVVRV9UUkFOU1BPUlQsXG4gIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DT01QUkVTU0lPTixcbiAgdHlwZSBXb3JrZmxvd0ludm9rZVBheWxvYWQsXG4gIHR5cGUgV29ya2Zsb3dSdW4sXG59IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQgeyBtb25vdG9uaWNGYWN0b3J5IH0gZnJvbSAndWxpZCc7XG5pbXBvcnQgeyBnZXRSdW5DYXBhYmlsaXRpZXMgfSBmcm9tICcuLi9jYXBhYmlsaXRpZXMuanMnO1xuaW1wb3J0IHsgaXNSZXRyeWFibGVXb3JsZEVycm9yIH0gZnJvbSAnLi4vY2xhc3NpZnktZXJyb3IuanMnO1xuaW1wb3J0IHsgaW1wb3J0S2V5IH0gZnJvbSAnLi4vZW5jcnlwdGlvbi5qcyc7XG5pbXBvcnQgeyBydW50aW1lTG9nZ2VyIH0gZnJvbSAnLi4vbG9nZ2VyLmpzJztcbmltcG9ydCB7IGRlY29kZVJ1blB1YmxpY0tleSB9IGZyb20gJy4uL3NlYWxlZC1ib3guanMnO1xuaW1wb3J0IHsgZGVyaXZlUnVuUGF5bG9hZEtleXMgfSBmcm9tICcuLi9zZXJpYWxpemF0aW9uL2VuY3J5cHRpb24uanMnO1xuaW1wb3J0IHtcbiAgZGVoeWRyYXRlU3RlcFJldHVyblZhbHVlLFxuICBoeWRyYXRlU3RlcEFyZ3VtZW50cyxcbiAgdHlwZSBQYXlsb2FkS2V5LFxuICBTZXJpYWxpemF0aW9uRm9ybWF0LFxuICBzZWFsVG8sXG59IGZyb20gJy4uL3NlcmlhbGl6YXRpb24uanMnO1xuaW1wb3J0IHsgV0VCSE9PS19SRVNQT05TRV9XUklUQUJMRSB9IGZyb20gJy4uL3N5bWJvbHMuanMnO1xuaW1wb3J0ICogYXMgQXR0cmlidXRlIGZyb20gJy4uL3RlbGVtZXRyeS9zZW1hbnRpYy1jb252ZW50aW9ucy5qcyc7XG5pbXBvcnQgeyBsaW5rVG9UcmFjZUNhcnJpZXIsIHRyYWNlIH0gZnJvbSAnLi4vdGVsZW1ldHJ5LmpzJztcbmltcG9ydCB7IGdldFdvcmxkTGF6eSB9IGZyb20gJy4vZ2V0LXdvcmxkLWxhenkuanMnO1xuaW1wb3J0IHsgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUgfSBmcm9tICcuL2hlbHBlcnMuanMnO1xuaW1wb3J0IHsgc2FmZVdhaXRVbnRpbCwgd2FpdGVkVW50aWwgfSBmcm9tICcuL3dhaXQtdW50aWwuanMnO1xuXG4vKiogTW9ub3RvbmljIFVMSUQgZmFjdG9yeSBmb3IgcGVyLWNhbGwgcmVzdW1lIGlkZW1wb3RlbmN5IGtleXMuICovXG5jb25zdCBnZW5lcmF0ZVJlc3VtZUlkID0gbW9ub3RvbmljRmFjdG9yeSgpO1xuXG4vKipcbiAqIFVwcGVyIGJvdW5kIG9uIHRoZSBzZXJpYWxpemVkIGhvb2sgcGF5bG9hZCB0aGF0IHRoZSBwYXJhbGxlbCBmYXN0IHBhdGggd2lsbFxuICogaW5saW5lIGludG8gdGhlIHF1ZXVlIG1lc3NhZ2UncyBgaG9va0lucHV0YC4gVmVyY2VsIFF1ZXVlcyBjYXBzIGEgc2luZ2xlXG4gKiBtZXNzYWdlIGF0IH4yNTYgS2lCLCBhbmQgdGhlIG1lc3NhZ2UgYWxzbyBjYXJyaWVzIHRoZSBydW5JZCwgaG9va0lkLCB0b2tlbixcbiAqIHJlc3VtZUlkLCBkaWdlc3QsIGFuZCB0cmFjZSBjYXJyaWVyIGFsb25nc2lkZSBDQk9SIGZyYW1pbmcgb3ZlcmhlYWQuIFN0YXlpbmdcbiAqIHdlbGwgdW5kZXIgdGhhdCBjZWlsaW5nIGtlZXBzIHRoZSBxdWV1ZSBwdWJsaXNoIGZyb20gcmVqZWN0aW5nIGFuIG92ZXJzaXplZFxuICogbWVzc2FnZSDigJQgd2hpY2gsIG9uIHRoZSBwYXJhbGxlbCBwYXRoLCB3b3VsZCBwZXJzaXN0IGBob29rX3JlY2VpdmVkYCBidXQgbmV2ZXJcbiAqIHJlLXRyaWdnZXIgdGhlIHJ1bi4gQWJvdmUgdGhpcyBzaXplIHdlIGZhbGwgYmFjayB0byB0aGUgc2VxdWVudGlhbCBwYXRoLCB3aG9zZVxuICogcXVldWUgbWVzc2FnZSBjYXJyaWVzIG9ubHkgdGhlIHJ1biBJRCAodGhlIHBheWxvYWQgbGl2ZXMgaW4gdGhlIGV2ZW50IGxvZykuXG4gKi9cbmNvbnN0IE1BWF9JTkxJTkVfUkVTVU1FX1BBWUxPQURfQllURVMgPSAxMjggKiAxMDI0O1xuXG4vKipcbiAqIEhleCBTSEEtMjU2IG9mIHRoZSBzZXJpYWxpemVkIHJlc3VtZSBwYXlsb2FkIGJ5dGVzLiBDb21wdXRlZCBvbmNlIGJ5IHRoZVxuICogcHJvZHVjZXIgYW5kIGZvcndhcmRlZCB2ZXJiYXRpbSBvbiBib3RoIHRoZSBkaXJlY3QgYGhvb2tfcmVjZWl2ZWRgIHdyaXRlIGFuZFxuICogdGhlIHF1ZXVlIGBob29rSW5wdXRgLCBzbyBib3RoIHdyaXRlcnMgb2YgdGhlIHNhbWUgYHJlc3VtZUlkYCByZWNvcmQgYW5cbiAqIGlkZW50aWNhbCBkaWdlc3Qgb24gdGhlIHNlcnZlcidzIGAocnVuSWQsIHJlc3VtZUlkKWAgY29uc3RyYWludC4gSGFzaGluZyB0aGVcbiAqIGFscmVhZHktc2VyaWFsaXplZCBieXRlcyAobm90IHRoZSByYXcgdmFsdWUpIGtlZXBzIHByb2R1Y2VyIGFuZCBjb25zdW1lciBpblxuICogbG9ja3N0ZXAg4oCUIHRoZSBjb25zdW1lciBmb3J3YXJkcyB0aGlzIHN0cmluZyB3aXRob3V0IHJlY29tcHV0aW5nLlxuICovXG5hc3luYyBmdW5jdGlvbiBjb21wdXRlUmVzdW1lUGF5bG9hZERpZ2VzdChieXRlczogVWludDhBcnJheSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IGRpZ2VzdCA9IGF3YWl0IGNyeXB0by5zdWJ0bGUuZGlnZXN0KCdTSEEtMjU2JywgYnl0ZXMpO1xuICBjb25zdCB2aWV3ID0gbmV3IFVpbnQ4QXJyYXkoZGlnZXN0KTtcbiAgbGV0IGhleCA9ICcnO1xuICBmb3IgKGNvbnN0IGIgb2Ygdmlldykge1xuICAgIGhleCArPSBiLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCAnMCcpO1xuICB9XG4gIHJldHVybiBoZXg7XG59XG5cbi8qKlxuICogVGhlIHJlc3VtZSBjb250ZXh0IGZvciBhIGhvb2sgcGx1cyB3aGVyZSBpdCBjYW1lIGZyb20uIGBydW5gIGlzIHByZXNlbnQgb25seVxuICogb24gdGhlIGZhbGxiYWNrIHBhdGggKHByZS1gcmVzdW1lQ29udGV4dGAgaG9va3MpLCB3aGVyZSBpdCBhbHNvIGNhcnJpZXMgdGhlXG4gKiBydW4ncyBtdXRhYmxlIHN0YXR1cyBmb3IgdGhlIHRlcm1pbmFsLXJ1biBjaGVjay4gS2V5IHJlc29sdXRpb24gaXMga2VwdFxuICogc2VwYXJhdGUgc28gY2FsbGVycyBjYW4gZ2F0ZSBpdCBiZWhpbmQgdGhhdCBjaGVjay5cbiAqL1xuaW50ZXJmYWNlIEhvb2tSZXN1bWVJbmZvIHtcbiAgcmVzdW1lQ29udGV4dDogSG9va1Jlc3VtZUNvbnRleHQ7XG4gIHNvdXJjZTogJ2hvb2snIHwgJ3J1bl9mYWxsYmFjayc7XG4gIHJ1bj86IFdvcmtmbG93UnVuO1xufVxuXG4vKiogRGVyaXZlIGEgcmVzdW1lIGNvbnRleHQgZnJvbSBhIGZ1bGwgcnVuIChmYWxsYmFjayBmb3IgcHJlLWByZXN1bWVDb250ZXh0YCBob29rcykuICovXG5mdW5jdGlvbiByZXN1bWVDb250ZXh0RnJvbVJ1bihydW46IFdvcmtmbG93UnVuKTogSG9va1Jlc3VtZUNvbnRleHQge1xuICBjb25zdCBjb3JlVmVyc2lvbiA9IHJ1bi5leGVjdXRpb25Db250ZXh0Py53b3JrZmxvd0NvcmVWZXJzaW9uO1xuICBjb25zdCB0cmFjZUNhcnJpZXIgPSBydW4uZXhlY3V0aW9uQ29udGV4dD8udHJhY2VDYXJyaWVyO1xuICBjb25zdCBob29rUmVzdW1lSW5wdXRWZXJzaW9uID0gcnVuLmV4ZWN1dGlvbkNvbnRleHQ/Lmhvb2tSZXN1bWVJbnB1dFZlcnNpb247XG4gIHJldHVybiB7XG4gICAgZGVwbG95bWVudElkOiBydW4uZGVwbG95bWVudElkLFxuICAgIHdvcmtmbG93TmFtZTogcnVuLndvcmtmbG93TmFtZSxcbiAgICBydW5TcGVjVmVyc2lvbjogcnVuLnNwZWNWZXJzaW9uLFxuICAgIHdvcmtmbG93Q29yZVZlcnNpb246XG4gICAgICB0eXBlb2YgY29yZVZlcnNpb24gPT09ICdzdHJpbmcnID8gY29yZVZlcnNpb24gOiB1bmRlZmluZWQsXG4gICAgdHJhY2VDYXJyaWVyOlxuICAgICAgdHJhY2VDYXJyaWVyICYmIHR5cGVvZiB0cmFjZUNhcnJpZXIgPT09ICdvYmplY3QnXG4gICAgICAgID8gKHRyYWNlQ2FycmllciBhcyBIb29rUmVzdW1lQ29udGV4dFsndHJhY2VDYXJyaWVyJ10pXG4gICAgICAgIDogdW5kZWZpbmVkLFxuICAgIGVuY3J5cHRpb25QdWJsaWNLZXk6IHJ1bi5lbmNyeXB0aW9uUHVibGljS2V5LFxuICAgIGhvb2tSZXN1bWVJbnB1dFZlcnNpb246XG4gICAgICB0eXBlb2YgaG9va1Jlc3VtZUlucHV0VmVyc2lvbiA9PT0gJ251bWJlcidcbiAgICAgICAgPyBob29rUmVzdW1lSW5wdXRWZXJzaW9uXG4gICAgICAgIDogdW5kZWZpbmVkLFxuICB9O1xufVxuXG4vKipcbiAqIFJlc29sdmUgcmVzdW1lIGNvbnRleHQgZm9yIGEgaG9vay4gVXNlcyB0aGUgc3RvcmVkIGByZXN1bWVDb250ZXh0YCB3aGVuXG4gKiBwcmVzZW50IChmYXN0IHBhdGgg4oCUIG5vIHJ1biByZWFkKTsgb3RoZXJ3aXNlIGZldGNoZXMgdGhlIHJ1biBhbmQgc3ludGhlc2l6ZXNcbiAqIGl0LiBEb2VzIE5PVCByZXNvbHZlIHRoZSBlbmNyeXB0aW9uIGtleSDigJQgY2FsbGVycyBkbyB0aGF0IHNlcGFyYXRlbHkuIE9ubHlcbiAqIHRoZSBmYWxsYmFjayBwYXRoIGNhbiBnYXRlIGtleSB3b3JrIGJlaGluZCBhIGxvY2FsIHRlcm1pbmFsLXJ1biBjaGVjayAoaXRcbiAqIGhhcyB0aGUgZmV0Y2hlZCBydW4pOyB0aGUgZmFzdCBwYXRoJ3Mgc3RvcmVkIGNvbnRleHQgY2FycmllcyBubyBzdGF0dXMsIHNvXG4gKiBzZWFsL3NlcmlhbGl6YXRpb24gd29yayBtYXkgcnVuIGJlZm9yZSB0aGUgcmVjZWl2aW5nIHNpZGUgcmVqZWN0c1xuICogYGhvb2tfcmVjZWl2ZWRgIGZvciBhbiBlbmRlZCBydW4uXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVIb29rUmVzdW1lSW5mbyhob29rOiBIb29rKTogUHJvbWlzZTxIb29rUmVzdW1lSW5mbz4ge1xuICBpZiAoaG9vay5yZXN1bWVDb250ZXh0KSB7XG4gICAgcmV0dXJuIHsgcmVzdW1lQ29udGV4dDogaG9vay5yZXN1bWVDb250ZXh0LCBzb3VyY2U6ICdob29rJyB9O1xuICB9XG4gIGNvbnN0IHJ1biA9IGF3YWl0IChhd2FpdCBnZXRXb3JsZExhenkoKSkucnVucy5nZXQoaG9vay5ydW5JZCk7XG4gIHJldHVybiB7XG4gICAgcmVzdW1lQ29udGV4dDogcmVzdW1lQ29udGV4dEZyb21SdW4ocnVuKSxcbiAgICBzb3VyY2U6ICdydW5fZmFsbGJhY2snLFxuICAgIHJ1bixcbiAgfTtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHRoZSBydW4ncyBzeW1tZXRyaWMga2V5IGZvciBhIHBheWxvYWQgV1JJVEUsIGFzIGEgYmFyZSBgQ3J5cHRvS2V5YFxuICogKGBpbXBvcnRLZXlgKSDigJQgdGhlIGBlbmNyYCB3cml0ZSBmYWxsYmFjayB1c2VkIHdoZW4gdGhlIHJ1biBwdWJsaXNoZWQgbm9cbiAqIHB1YmxpYyBrZXkgdG8gc2VhbCB0by4gV3JpdGluZyBuZWVkcyBvbmx5IHRoZSBBRVMga2V5LCBub3QgdGhlIHJlYWQtc2lkZVxuICoga2V5cGFpci4gT24gdGhlIGZhc3QgcGF0aCB0aGlzIG5lZWRzIG9ubHkgYHJ1bklkYCArIGBkZXBsb3ltZW50SWRgIChubyBydW5cbiAqIGVudGl0eSk7IG9uIHRoZSBmYWxsYmFjayBwYXRoIHRoZSBhbHJlYWR5IGZldGNoZWQgcnVuIGlzIHJldXNlZC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZUhvb2tFbmNyeXB0aW9uS2V5KFxuICBob29rOiBIb29rLFxuICBpbmZvOiBIb29rUmVzdW1lSW5mb1xuKTogUHJvbWlzZTxBd2FpdGVkPFJldHVyblR5cGU8dHlwZW9mIGltcG9ydEtleT4+IHwgdW5kZWZpbmVkPiB7XG4gIGNvbnN0IHdvcmxkID0gYXdhaXQgZ2V0V29ybGRMYXp5KCk7XG4gIGNvbnN0IHJhd0tleSA9IGluZm8ucnVuXG4gICAgPyBhd2FpdCB3b3JsZC5nZXRFbmNyeXB0aW9uS2V5Rm9yUnVuPy4oaW5mby5ydW4pXG4gICAgOiBhd2FpdCB3b3JsZC5nZXRFbmNyeXB0aW9uS2V5Rm9yUnVuPy4oaG9vay5ydW5JZCwge1xuICAgICAgICBkZXBsb3ltZW50SWQ6IGluZm8ucmVzdW1lQ29udGV4dC5kZXBsb3ltZW50SWQsXG4gICAgICB9KTtcbiAgcmV0dXJuIHJhd0tleSA/IGF3YWl0IGltcG9ydEtleShyYXdLZXkpIDogdW5kZWZpbmVkO1xufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRIb29rQnlUb2tlbldpdGhLZXkodG9rZW46IHN0cmluZyk6IFByb21pc2U8e1xuICBob29rOiBIb29rO1xuICBlbmNyeXB0aW9uS2V5OiBQYXlsb2FkS2V5IHwgdW5kZWZpbmVkO1xufT4ge1xuICBjb25zdCB3b3JsZCA9IGF3YWl0IGdldFdvcmxkTGF6eSgpO1xuICBjb25zdCBob29rID0gYXdhaXQgd29ybGQuaG9va3MuZ2V0QnlUb2tlbih0b2tlbik7XG5cbiAgLy8gT25seSBhIGhvb2sgdGhhdCBhY3R1YWxseSBjYXJyaWVzIG1ldGFkYXRhIG5lZWRzIHRoZSBydW4ncyBrZXkgcmVzb2x2ZWRcbiAgLy8gaGVyZTogaHlkcmF0aW5nIHRoYXQgbWV0YWRhdGEgaXMgYSBSRUFELCBzbyBkZXJpdmUgdGhlIGZ1bGwgUnVuUGF5bG9hZEtleXNcbiAgLy8gKHdoaWNoIG9wZW5zIHNlYWxlZCBgZW5jcGAgbWV0YWRhdGEsIG5vdCBqdXN0IHN5bW1ldHJpYyBgZW5jcmApLiBUaGUgY29tbW9uXG4gIC8vIGRlZmF1bHQgd2ViaG9vayDigJQgY3JlYXRlV2ViaG9vaygpIHdpdGggbm8gYHJlc3BvbmRXaXRoYCDigJQgc3RvcmVzIG5vXG4gIC8vIG1ldGFkYXRhLCBzbyBpdCBza2lwcyB0aGlzIGVudGlyZWx5OiBubyB+MzUwbXMgYHJ1bi1rZXlgIEFQSSByb3VuZCB0cmlwLFxuICAvLyBhbmQsIGNydWNpYWxseSwgbm8gcmVzb2x2ZWQga2V5IGhhbmRlZCB0byBgcmVzdW1lSG9va2AsIGxlYXZpbmcgaXQgZnJlZSB0b1xuICAvLyBzZWFsIHRoZSBwYXlsb2FkIHRvIHRoZSBydW4ncyBwdWJsaXNoZWQgcHVibGljIGtleSBpbnN0ZWFkLiBNZXRhZGF0YS1cbiAgLy8gYmVhcmluZyB3ZWJob29rcyBzdGlsbCBsZWdpdGltYXRlbHkgcGF5IG9uZSBsb29rdXAgdG8gaHlkcmF0ZS5cbiAgbGV0IGVuY3J5cHRpb25LZXk6IFBheWxvYWRLZXkgfCB1bmRlZmluZWQ7XG4gIGlmICh0eXBlb2YgaG9vay5tZXRhZGF0YSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBjb25zdCBpbmZvID0gYXdhaXQgcmVzb2x2ZUhvb2tSZXN1bWVJbmZvKGhvb2spO1xuICAgIC8vIE9uIHRoZSBmYXN0IHBhdGggdGhpcyByZXNvbHZlcyB0aGUga2V5IGJ5IHJ1bklkICsgZGVwbG95bWVudElkIChubyBydW5cbiAgICAvLyByZWFkKTsgb24gdGhlIGZhbGxiYWNrIHBhdGggaXQgcmV1c2VzIHRoZSBhbHJlYWR5LWZldGNoZWQgcnVuLlxuICAgIGNvbnN0IHJhd0tleSA9IGluZm8ucnVuXG4gICAgICA/IGF3YWl0IHdvcmxkLmdldEVuY3J5cHRpb25LZXlGb3JSdW4/LihpbmZvLnJ1bilcbiAgICAgIDogYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKGhvb2sucnVuSWQsIHtcbiAgICAgICAgICBkZXBsb3ltZW50SWQ6IGluZm8ucmVzdW1lQ29udGV4dC5kZXBsb3ltZW50SWQsXG4gICAgICAgIH0pO1xuICAgIGVuY3J5cHRpb25LZXkgPSByYXdLZXkgPyBhd2FpdCBkZXJpdmVSdW5QYXlsb2FkS2V5cyhyYXdLZXkpIDogdW5kZWZpbmVkO1xuICAgIGhvb2subWV0YWRhdGEgPSBhd2FpdCBoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgICAgIGhvb2subWV0YWRhdGEgYXMgYW55LFxuICAgICAgaG9vay5ydW5JZCxcbiAgICAgIGVuY3J5cHRpb25LZXlcbiAgICApO1xuICB9XG4gIHJldHVybiB7IGhvb2ssIGVuY3J5cHRpb25LZXkgfTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIGhvb2sgYnkgdG9rZW4gdG8gZmluZCB0aGUgYXNzb2NpYXRlZCB3b3JrZmxvdyBydW4sXG4gKiBhbmQgaHlkcmF0ZSB0aGUgYG1ldGFkYXRhYCBwcm9wZXJ0eSBpZiBpdCB3YXMgc2V0IGZyb20gd2l0aGluXG4gKiB0aGUgd29ya2Zsb3cgcnVuLlxuICpcbiAqIEEgSG9vayBrZXB0IGJ5IG1pbmltdW0gcmV0ZW50aW9uIHJlbWFpbnMgYXZhaWxhYmxlIGhlcmUgYWZ0ZXIgaXRzIHJ1biBlbmRzLFxuICogYnV0IGNhbm5vdCBiZSByZXN1bWVkLlxuICpcbiAqIEBwYXJhbSB0b2tlbiAtIFRoZSB1bmlxdWUgdG9rZW4gaWRlbnRpZnlpbmcgdGhlIGhvb2tcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldEhvb2tCeVRva2VuKHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPEhvb2s+IHtcbiAgY29uc3QgeyBob29rIH0gPSBhd2FpdCBnZXRIb29rQnlUb2tlbldpdGhLZXkodG9rZW4pO1xuICByZXR1cm4gaG9vaztcbn1cblxuLyoqXG4gKiBUaGUgcmVzdWx0IG9mIHtAbGluayByZXN1bWVIb29rfTogYSB7QGxpbmsgSG9va30gYXVnbWVudGVkIHdpdGggYW4gb3B0aW9uYWxcbiAqIHJlc2lsaWVuY2Ugc2lnbmFsLlxuICpcbiAqIE9uIHRoZSBwYXJhbGxlbCBmYXN0IHBhdGgsIGByZXN1bWVIb29rKClgIHdyaXRlcyB0aGUgYGhvb2tfcmVjZWl2ZWRgIGV2ZW50IGFuZFxuICogZGlzcGF0Y2hlcyB0aGUgd29ya2Zsb3cgcXVldWUgbWVzc2FnZSBjb25jdXJyZW50bHkuIFdoZW4gdGhlIGRpcmVjdCBldmVudFxuICogd3JpdGUgZmFpbHMgKnRyYW5zaWVudGx5KiDigJQgYSA0MjkvNXh4LCBhIHRyYW5zcG9ydCBlcnJvciwgb3IgYW4gZXhwZWN0ZWRcbiAqIGAocnVuSWQsIHJlc3VtZUlkKWAgY29uZmxpY3Qgd2l0aCBpdHMgb3duIHJlLWVuc3VyaW5nIGNvbnN1bWVyIOKAlCBidXQgdGhlIHF1ZXVlXG4gKiBkaXNwYXRjaCBzdWNjZWVkcywgdGhlIHJlc3VtZSBpcyBzdGlsbCBndWFyYW50ZWVkOiB0aGUgcXVldWUgY29uc3VtZXJcbiAqIGlkZW1wb3RlbnRseSBtYXRlcmlhbGl6ZXMgdGhlIGBob29rX3JlY2VpdmVkYCBldmVudCBmcm9tIHRoZSBwYXlsb2FkIGNhcnJpZWRcbiAqIG9uIHRoZSBtZXNzYWdlIGJlZm9yZSByZXBsYXkuIEluIHRoYXQgcmVjb3ZlcmVkIGNhc2UgdGhlIHJldHVybmVkIGhvb2sgY2Fycmllc1xuICogYHJlc2lsaWVudFJlc3VtZTogdHJ1ZWAuXG4gKlxuICogT24gdGhlIGhhcHB5IHBhdGggKHRoZSBkaXJlY3Qgd3JpdGUgbGFuZGVkKSBhbmQgb24gdGhlIHNlcXVlbnRpYWwgZmFsbGJhY2tcbiAqIHBhdGgsIHRoZSBmbGFnIGlzIGFic2VudCAoYHVuZGVmaW5lZGApLiBDYWxsZXJzIHRoYXQgZG9uJ3QgY2FyZSBhYm91dCB0aGVcbiAqIGRpc3RpbmN0aW9uIGNhbiB0cmVhdCB0aGUgcmVzdWx0IGFzIGEgcGxhaW4ge0BsaW5rIEhvb2t9LlxuICovXG5leHBvcnQgdHlwZSBSZXN1bWVkSG9vayA9IEhvb2sgJiB7IHJlc2lsaWVudFJlc3VtZT86IGJvb2xlYW4gfTtcblxuLyoqXG4gKiBSZXN1bWVzIGEgd29ya2Zsb3cgcnVuIGJ5IHNlbmRpbmcgYSBwYXlsb2FkIHRvIGEgaG9vayBpZGVudGlmaWVkIGJ5IGl0cyB0b2tlbi5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBleHRlcm5hbGx5IChlLmcuLCBmcm9tIGFuIEFQSSByb3V0ZSBvciBzZXJ2ZXIgYWN0aW9uKVxuICogdG8gc2VuZCBkYXRhIHRvIGEgaG9vayBhbmQgcmVzdW1lIHRoZSBhc3NvY2lhdGVkIHdvcmtmbG93IHJ1bi5cbiAqXG4gKiBAcGFyYW0gdG9rZW5Pckhvb2sgLSBUaGUgdW5pcXVlIHRva2VuIGlkZW50aWZ5aW5nIHRoZSBob29rLCBvciB0aGUgaG9vayBvYmplY3QgaXRzZWxmXG4gKiBAcGFyYW0gcGF5bG9hZCAtIFRoZSBkYXRhIHBheWxvYWQgdG8gc2VuZCB0byB0aGUgaG9va1xuICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHtAbGluayBSZXN1bWVkSG9va31cbiAqIEB0aHJvd3Mge0hvb2tOb3RGb3VuZEVycm9yfSBJZiB0aGUgSG9vayBkb2VzIG5vdCBleGlzdCBvciBpdHMgcnVuIGhhcyBlbmRlZFxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogYGBgdHNcbiAqIC8vIEluIGFuIEFQSSByb3V0ZVxuICogaW1wb3J0IHsgcmVzdW1lSG9vayB9IGZyb20gJ0B3b3JrZmxvdy9jb3JlL3J1bnRpbWUnO1xuICpcbiAqIGV4cG9ydCBhc3luYyBmdW5jdGlvbiBQT1NUKHJlcXVlc3Q6IFJlcXVlc3QpIHtcbiAqICAgY29uc3QgeyB0b2tlbiwgZGF0YSB9ID0gYXdhaXQgcmVxdWVzdC5qc29uKCk7XG4gKlxuICogICB0cnkge1xuICogICAgIGNvbnN0IGhvb2sgPSBhd2FpdCByZXN1bWVIb29rKHRva2VuLCBkYXRhKTtcbiAqICAgICByZXR1cm4gUmVzcG9uc2UuanNvbih7IHJ1bklkOiBob29rLnJ1bklkIH0pO1xuICogICB9IGNhdGNoIChlcnJvcikge1xuICogICAgIHJldHVybiBuZXcgUmVzcG9uc2UoJ0hvb2sgbm90IGZvdW5kJywgeyBzdGF0dXM6IDQwNCB9KTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXN1bWVIb29rPFQgPSBhbnk+KFxuICB0b2tlbk9ySG9vazogc3RyaW5nIHwgSG9vayxcbiAgcGF5bG9hZDogVCxcbiAgZW5jcnlwdGlvbktleU92ZXJyaWRlPzogUGF5bG9hZEtleVxuKTogUHJvbWlzZTxSZXN1bWVkSG9vaz4ge1xuICAvLyBQdWJsaWMgZW50cnkgcG9pbnQuIEl0IG5ldmVyIGF0dGVzdHMgaG9vayBmcmVzaG5lc3MsIHNvIGEgSG9vayBvYmplY3RcbiAgLy8gc3VwcGxpZWQgaGVyZSDigJQgd2hpY2ggbWF5IGNhcnJ5IGEgYHJlc3VtZUNhcGFiaWxpdGllc2AgY2FjaGVkIGJlZm9yZSBhXG4gIC8vIHNlcnZlciByb2xsYmFjayBvciBraWxsIHN3aXRjaCDigJQgaXMgaWdub3JlZCBieSB0aGUgZHluYW1pYy1kZWR1cCBnYXRlIGFuZFxuICAvLyBmYWlscyBjbG9zZWQgdG8gdGhlIHNlcXVlbnRpYWwgcGF0aC4gT25seSBgcmVzdW1lV2ViaG9va2AsIHdoaWNoIGZldGNoZXNcbiAgLy8gdGhlIGhvb2sgYnkgdG9rZW4gaW4tbGluZSBkdXJpbmcgdGhlIHNhbWUgcmVzdW1lLCByZWFjaGVzIHRoZSBpbnRlcm5hbFxuICAvLyBpbXBsZW1lbnRhdGlvbiB3aXRoIHRoZSBmcmVzaCBhdHRlc3RhdGlvbiBzZXQuIEtlZXBpbmcgdGhlIGZyZXNobmVzcyBmbGFnXG4gIC8vIG9mZiB0aGUgZXhwb3J0ZWQgc2lnbmF0dXJlIHByZXZlbnRzIGEgY2FsbGVyIGZyb20gcGFzc2luZyBhIHN0YWxlIEhvb2sgcGx1c1xuICAvLyBgdHJ1ZWAgYW5kIHJlYWN0aXZhdGluZyBkeW5hbWljIGRlZHVwIGFnYWluc3QgYSByb2xsZWQtYmFjayBiYWNrZW5kLlxuICAvL1xuICAvLyBUMCBvZiB0aGUgaG9vay1yZXN1bWUgVFRSIHdpbmRvdyBpcyB0YWtlbiBIRVJFLCBhdCB0aGUgcHVibGljIGVudHJ5IHBvaW50LFxuICAvLyByYXRoZXIgdGhhbiBpbnNpZGUgdGhlIGltcGxlbWVudGF0aW9uIOKAlCBzZWUgdGhlIHBhcmFtZXRlcidzIGRvYyBjb21tZW50LlxuICByZXR1cm4gcmVzdW1lSG9va0ltcGwoXG4gICAgdG9rZW5Pckhvb2ssXG4gICAgcGF5bG9hZCxcbiAgICBlbmNyeXB0aW9uS2V5T3ZlcnJpZGUsXG4gICAgZmFsc2UsXG4gICAgRGF0ZS5ub3coKVxuICApO1xufVxuXG4vKipcbiAqIEludGVybmFsIGltcGxlbWVudGF0aW9uIG9mIHtAbGluayByZXN1bWVIb29rfS4gTk9UIGV4cG9ydGVkOiB0aGVcbiAqIGBob29rRnJlc2hseUxvb2tlZFVwYCBhdHRlc3RhdGlvbiBtdXN0IG5ldmVyIGJlIHJlYWNoYWJsZSBieSBwdWJsaWMgY2FsbGVyc1xuICogKHNlZSB0aGUgd3JhcHBlciBhYm92ZSkuXG4gKlxuICogQHBhcmFtIGhvb2tGcmVzaGx5TG9va2VkVXAgLSBBdHRlc3RzIHRoYXQgYSBzdXBwbGllZCBIb29rIG9iamVjdCB3YXMgZmV0Y2hlZFxuICogICBieSB0b2tlbiBkdXJpbmcgVEhJUyByZXN1bWUsIHNvIGl0cyByZXNwb25zZS1vbmx5IGByZXN1bWVDYXBhYmlsaXRpZXNgXG4gKiAgIHJlZmxlY3RzIHRoZSBsaXZlIGJhY2tlbmQgYW5kIG1heSBiZSB0cnVzdGVkIGZvciB0aGUgZHluYW1pYy1kZWR1cCBnYXRlLlxuICogICBBIHRva2VuIHN0cmluZyBpcyBhbHdheXMgZmV0Y2hlZCBmcmVzaCBoZXJlLCBzbyBpdCBpcyBpbXBsaWNpdGx5IGZyZXNoLlxuICogQHBhcmFtIHJlc3VtZVJlcXVlc3RlZEF0TXMgLSBUMCBvZiB0aGUgaG9vay1yZXN1bWUgVFRSIHdpbmRvdyAoc2VlXG4gKiAgIHJ1bnRpbWUvcmVzdW1lLWxhdGVuY3kudHMpLCBzdGFtcGVkIGJ5IHRoZSBQVUJMSUMgZW50cnkgcG9pbnQgdGhlIGNhbGxlclxuICogICB1c2VkLiBJdCBpcyBhIHBhcmFtZXRlciByYXRoZXIgdGhhbiBhIGxvY2FsIGJlY2F1c2UgYHJlc3VtZVdlYmhvb2tgIGRvZXNcbiAqICAgcmVhbCB3b3JrIGJlZm9yZSBpdCBnZXRzIGhlcmUg4oCUIHRoZSBieS10b2tlbiBsb29rdXAsIHRoZSBydW4ta2V5XG4gKiAgIHJlc29sdXRpb24gdGhhdCBoeWRyYXRlcyBob29rIG1ldGFkYXRhLCBhbmQgdGhlIGByZXNwb25kV2l0aGAgc2V0dXAg4oCUIGFuZFxuICogICBzdGFtcGluZyBsb2NhbGx5IHdvdWxkIHNpbGVudGx5IGV4Y2x1ZGUgYWxsIG9mIGl0LCBzbyB0aGUgdHdvIGVudHJ5IHBvaW50c1xuICogICB3b3VsZCByZXBvcnQgdGhlIHNhbWUgbWV0cmljIG92ZXIgZGlmZmVyZW50IHdpbmRvd3MuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlc3VtZUhvb2tJbXBsPFQgPSBhbnk+KFxuICB0b2tlbk9ySG9vazogc3RyaW5nIHwgSG9vayxcbiAgcGF5bG9hZDogVCxcbiAgZW5jcnlwdGlvbktleU92ZXJyaWRlOiBQYXlsb2FkS2V5IHwgdW5kZWZpbmVkLFxuICBob29rRnJlc2hseUxvb2tlZFVwOiBib29sZWFuLFxuICByZXN1bWVSZXF1ZXN0ZWRBdE1zOiBudW1iZXJcbik6IFByb21pc2U8UmVzdW1lZEhvb2s+IHtcbiAgcmV0dXJuIGF3YWl0IHdhaXRlZFVudGlsKCgpID0+IHtcbiAgICByZXR1cm4gdHJhY2UoJ2hvb2sucmVzdW1lJywgYXN5bmMgKHNwYW4pID0+IHtcbiAgICAgIGNvbnN0IHdvcmxkID0gYXdhaXQgZ2V0V29ybGRMYXp5KCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHN1cHBsaWVkVG9rZW4gPSB0eXBlb2YgdG9rZW5Pckhvb2sgPT09ICdzdHJpbmcnO1xuICAgICAgICBjb25zdCBob29rOiBIb29rID0gc3VwcGxpZWRUb2tlblxuICAgICAgICAgID8gYXdhaXQgd29ybGQuaG9va3MuZ2V0QnlUb2tlbih0b2tlbk9ySG9vaylcbiAgICAgICAgICA6IHRva2VuT3JIb29rO1xuICAgICAgICAvLyBUaGUgZHluYW1pYywgcmVzcG9uc2Utb25seSBgcmVzdW1lQ2FwYWJpbGl0aWVzYCBtYXkgb25seSBiZSB0cnVzdGVkXG4gICAgICAgIC8vIHdoZW4gaXQgY2FtZSBmcm9tIGEgYnktdG9rZW4gbG9va3VwIHBlcmZvcm1lZCBkdXJpbmcgdGhpcyByZXN1bWUuXG4gICAgICAgIGNvbnN0IGhvb2tSZXN1bWVDYXBhYmlsaXRpZXNBcmVGcmVzaCA9XG4gICAgICAgICAgc3VwcGxpZWRUb2tlbiB8fCBob29rRnJlc2hseUxvb2tlZFVwO1xuXG4gICAgICAgIGNvbnN0IGluZm8gPSBhd2FpdCByZXNvbHZlSG9va1Jlc3VtZUluZm8oaG9vayk7XG4gICAgICAgIGNvbnN0IHsgcmVzdW1lQ29udGV4dCB9ID0gaW5mbztcblxuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuSG9va1Rva2VuKGhvb2sudG9rZW4pLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Ib29rSWQoaG9vay5ob29rSWQpLFxuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1bklkKGhvb2sucnVuSWQpLFxuICAgICAgICAgICd3b3JrZmxvdy5ob29rLnJlc3VtZV9jb250ZXh0X3NvdXJjZSc6IGluZm8uc291cmNlLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBUaGUgc3RvcmVkIGByZXN1bWVDb250ZXh0YCBpbnRlbnRpb25hbGx5IG9taXRzIHRoZSBydW4ncyBtdXRhYmxlXG4gICAgICAgIC8vIHN0YXR1cywgc28gdGhpcyBlYXJseSBjbGllbnQtc2lkZSByZWplY3Rpb24gb25seSBydW5zIG9uIHRoZVxuICAgICAgICAvLyBmYWxsYmFjayBwYXRoICh3aGljaCBmZXRjaGVkIHRoZSBydW4pLiBPbiB0aGUgZmFzdCBwYXRoIHRoZSB0ZXJtaW5hbFxuICAgICAgICAvLyBjaGVjayBoYXBwZW5zIHNlcnZlci1zaWRlOiBgaG9va19yZWNlaXZlZGAgYWdhaW5zdCBhbiBlbmRlZCBydW4gaXNcbiAgICAgICAgLy8gcmVqZWN0ZWQsIHdoaWNoIHRoZSBjYXRjaCBhcm91bmQgYHdvcmxkLmV2ZW50cy5jcmVhdGVgIGJlbG93IHJlLWtleXNcbiAgICAgICAgLy8gdG8gSG9va05vdEZvdW5kRXJyb3Ig4oCUIHNhbWUgcHVibGljIGNvbnRyYWN0LCBubyBydW4gcHJlLWZldGNoLlxuICAgICAgICBpZiAoaW5mby5ydW4gJiYgaXNUZXJtaW5hbFdvcmtmbG93UnVuU3RhdHVzKGluZm8ucnVuLnN0YXR1cykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgSG9va05vdEZvdW5kRXJyb3IoaG9vay50b2tlbik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayB0aGUgdGFyZ2V0IHJ1bidzIGNhcGFiaWxpdGllcyB0byBlbnN1cmUgd2UgZW5jb2RlIHRoZVxuICAgICAgICAvLyBwYXlsb2FkIGluIGEgZm9ybWF0IHRoZSBydW4ncyBkZXBsb3ltZW50IGNhbiBkZWNvZGUuIEZvciBleGFtcGxlLFxuICAgICAgICAvLyBydW5zIGNyZWF0ZWQgYmVmb3JlIGVuY3J5cHRpb24gc3VwcG9ydCB3YXMgYWRkZWQgY2Fubm90IGRlY29kZVxuICAgICAgICAvLyB0aGUgJ2VuY3InIHNlcmlhbGl6YXRpb24gZm9ybWF0LCBhbmQgcnVucyBjcmVhdGVkIGJlZm9yZVxuICAgICAgICAvLyBieXRlLXN0cmVhbSBmcmFtaW5nIHN1cHBvcnQgY2Fubm90IGRlY29kZSBmcmFtZWQgYnl0ZSBzdHJlYW1zLlxuICAgICAgICBjb25zdCBjYXBhYmlsaXRpZXMgPSBnZXRSdW5DYXBhYmlsaXRpZXMoXG4gICAgICAgICAgcmVzdW1lQ29udGV4dC53b3JrZmxvd0NvcmVWZXJzaW9uXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gUmVzb2x2ZSBob3cgdG8gZW5jcnlwdCB0aGUgcGF5bG9hZCBmb3IgdGhlIHRhcmdldCBydW4gKGEgV1JJVEUpLlxuICAgICAgICAvL1xuICAgICAgICAvLyBQcmVmZXJyZWQgcGF0aDogc2VhbCB0byB0aGUgcnVuJ3MgcHVibGlzaGVkIFgyNTUxOSBwdWJsaWMga2V5LCB3aGljaFxuICAgICAgICAvLyB0aGUgc3RvcmVkIGByZXN1bWVDb250ZXh0YCBjYXJyaWVzIGlubGluZS4gT24gdGhlIGZhc3QgcGF0aCB0aGlzIGlzXG4gICAgICAgIC8vIHRoZSB3aG9sZSB3aW4g4oCUIG5vIHJ1biByZWFkIEFORCBubyBgZ2V0RW5jcnlwdGlvbktleUZvclJ1bmAsIHdob3NlXG4gICAgICAgIC8vIH4zNTBtcyBgcnVuLWtleWAgQVBJIHJvdW5kIHRyaXAgZG9taW5hdGVzIGNyb3NzLWRlcGxveW1lbnQgaG9va1xuICAgICAgICAvLyByZXN1bXB0aW9uIGxhdGVuY3kuIChPbiB0aGUgZmFsbGJhY2sgcGF0aCB0aGUga2V5IGlzIHN5bnRoZXNpemVkXG4gICAgICAgIC8vIGZyb20gdGhlIGZldGNoZWQgcnVuLCB3aGljaCBhbHNvIGNhcnJpZXMgaXQuKVxuICAgICAgICAvL1xuICAgICAgICAvLyBTZWFsaW5nIGFsc28gZHJvcHMgcHJpdmlsZWdlOiB0aGUgcmVzdW1lciBlbmRzIHVwIGFibGUgdG8gd3JpdGUgYVxuICAgICAgICAvLyBwYXlsb2FkIGZvciB0aGUgcnVuIHdpdGhvdXQgYmVpbmcgYWJsZSB0byByZWFkIGFueXRoaW5nIG9mIHRoZVxuICAgICAgICAvLyBydW4ncywgd2hlcmUgZmV0Y2hpbmcgdGhlIHN5bW1ldHJpYyBrZXkgZ3JhbnRzIGJvdGguXG4gICAgICAgIC8vXG4gICAgICAgIC8vIERlbGliZXJhdGVseSBOT1QgZ2F0ZWQgb24gYGNhcGFiaWxpdGllcy5zdXBwb3J0ZWRGb3JtYXRzYCB0aGUgd2F5XG4gICAgICAgIC8vIHRoZSBzeW1tZXRyaWMgZmFsbGJhY2sgYmVsb3cgZ2F0ZXMgYGVuY3JgOiBwcmVzZW5jZSBvZiB0aGUgcHVibGljIGtleVxuICAgICAgICAvLyBpcyBpdHNlbGYgdGhlIGdhdGUuIEEgcnVuIG9ubHkgY2FycmllcyBvbmUgaWYgdGhlIHJ1bnRpbWUgdGhhdFxuICAgICAgICAvLyBjcmVhdGVkIGl0IGNvdWxkIGFsc28gb3BlbiBhIHNlYWxlZCBwYXlsb2FkLCBhbmQgcnVucyBhcmUgcGlubmVkIHRvXG4gICAgICAgIC8vIHRoZWlyIGNyZWF0aW5nIGRlcGxveW1lbnQsIHNvIHByZXNlbmNlIGlzIGEgbW9yZSByZWxpYWJsZSBhdHRlc3RhdGlvblxuICAgICAgICAvLyB0aGFuIGEgdmVyc2lvbiBjb21wYXJlIOKAlCBhbmQgaXQgc3RheXMgY29ycmVjdCBldmVuIHdoZW4gcGFja2FnZVxuICAgICAgICAvLyB2ZXJzaW9ucyBkcmlmdC5cbiAgICAgICAgbGV0IHBheWxvYWRLZXk6IFBheWxvYWRLZXkgfCB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IHJ1blB1YmxpY0tleSA9IGVuY3J5cHRpb25LZXlPdmVycmlkZVxuICAgICAgICAgID8gLy8gVGhlIGNhbGxlciBhbHJlYWR5IGhvbGRzIGEga2V5IChyZXN1bWVXZWJob29rIHJlc29sdmVkIG9uZSB0b1xuICAgICAgICAgICAgLy8gaHlkcmF0ZSBob29rIG1ldGFkYXRhKSwgc28gc2VhbGluZyB3b3VsZCBhZGQgYW4gRUNESCBmb3Igbm9cbiAgICAgICAgICAgIC8vIHNhdmVkIHJvdW5kIHRyaXAuIFJldXNlIHdoYXQgaXQgcmVzb2x2ZWQuXG4gICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgICA6IGRlY29kZVJ1blB1YmxpY0tleShyZXN1bWVDb250ZXh0LmVuY3J5cHRpb25QdWJsaWNLZXkpO1xuXG4gICAgICAgIGlmIChydW5QdWJsaWNLZXkpIHtcbiAgICAgICAgICBwYXlsb2FkS2V5ID0gc2VhbFRvKHJ1blB1YmxpY0tleSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gU3ltbWV0cmljIGBlbmNyYCB3cml0ZSBmYWxsYmFjazogbmVlZHMgb25seSB0aGUgQUVTIGtleVxuICAgICAgICAgIC8vIChhIGJhcmUgQ3J5cHRvS2V5IHZpYSBgcmVzb2x2ZUhvb2tFbmNyeXB0aW9uS2V5YCksIG5vdCB0aGVcbiAgICAgICAgICAvLyByZWFkLXNpZGUgUnVuUGF5bG9hZEtleXMuXG4gICAgICAgICAgbGV0IGVuY3J5cHRpb25LZXkgPVxuICAgICAgICAgICAgZW5jcnlwdGlvbktleU92ZXJyaWRlID8/XG4gICAgICAgICAgICAoYXdhaXQgcmVzb2x2ZUhvb2tFbmNyeXB0aW9uS2V5KGhvb2ssIGluZm8pKTtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAhY2FwYWJpbGl0aWVzLnN1cHBvcnRlZEZvcm1hdHMuaGFzKFNlcmlhbGl6YXRpb25Gb3JtYXQuRU5DUllQVEVEKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgZW5jcnlwdGlvbktleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcGF5bG9hZEtleSA9IGVuY3J5cHRpb25LZXk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb21wcmVzcyBvbmx5IHdoZW4gdGhlIHRhcmdldCBydW4gYW5kIGl0cyBkZXBsb3ltZW50IHN1cHBvcnQgdGhlXG4gICAgICAgIC8vIGNvbXByZXNzaW9uIGZvcm1hdHMgaW50cm9kdWNlZCB3aXRoIHNwZWMgdmVyc2lvbiA1LlxuICAgICAgICBjb25zdCBjb21wcmVzc2lvbiA9XG4gICAgICAgICAgKHJlc3VtZUNvbnRleHQucnVuU3BlY1ZlcnNpb24gPz8gMCkgPj1cbiAgICAgICAgICAgIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DT01QUkVTU0lPTiAmJlxuICAgICAgICAgIGNhcGFiaWxpdGllcy5zdXBwb3J0ZWRGb3JtYXRzLmhhcyhTZXJpYWxpemF0aW9uRm9ybWF0LkdaSVApO1xuXG4gICAgICAgIC8vIERlaHlkcmF0ZSB0aGUgcGF5bG9hZCBmb3Igc3RvcmFnZVxuICAgICAgICBjb25zdCBvcHM6IFByb21pc2U8YW55PltdID0gW107XG4gICAgICAgIGNvbnN0IHYxQ29tcGF0ID0gaXNMZWdhY3lTcGVjVmVyc2lvbihob29rLnNwZWNWZXJzaW9uKTtcbiAgICAgICAgY29uc3QgZGVoeWRyYXRlZFBheWxvYWQgPSBhd2FpdCBkZWh5ZHJhdGVTdGVwUmV0dXJuVmFsdWUoXG4gICAgICAgICAgcGF5bG9hZCxcbiAgICAgICAgICBob29rLnJ1bklkLFxuICAgICAgICAgIHBheWxvYWRLZXksXG4gICAgICAgICAgb3BzLFxuICAgICAgICAgIGdsb2JhbFRoaXMsXG4gICAgICAgICAgdjFDb21wYXQsXG4gICAgICAgICAgY2FwYWJpbGl0aWVzLmZyYW1lZEJ5dGVTdHJlYW1zLFxuICAgICAgICAgIGNvbXByZXNzaW9uXG4gICAgICAgICk7XG4gICAgICAgIC8vIFRoZXNlIHBheWxvYWQtc3RyZWFtIG9wcyBhcmUgZmx1c2hlZCBpbiB0aGUgYmFja2dyb3VuZDsgdGhlXG4gICAgICAgIC8vIHByb21pc2UgaGFuZGVkIHRvIHdhaXRVbnRpbCBtdXN0IG5ldmVyIHJlamVjdCAoYW4gdW5jb25zdW1lZFxuICAgICAgICAvLyB3YWl0VW50aWwgcmVqZWN0aW9uIGNyYXNoZXMgdGhlIHByb2Nlc3MgYXMgdW5oYW5kbGVkUmVqZWN0aW9uKSxcbiAgICAgICAgLy8gc28gdW5leHBlY3RlZCBmYWlsdXJlcyBhcmUgbG9nZ2VkIGluc3RlYWQuXG4gICAgICAgIC8vIE5PVEU6IHJlamVjdGlvbnMgd2l0aCBgdW5kZWZpbmVkYCBhcmUgYW4gZXhwZWN0ZWQgYXJ0aWZhY3Qgb2YgdGhlXG4gICAgICAgIC8vIHdlYmhvb2sgYnVuZGxlIGFuZCBhcmUgaWdub3JlZCBlbnRpcmVseS5cbiAgICAgICAgc2FmZVdhaXRVbnRpbChQcm9taXNlLmFsbChvcHMpLCAoZXJyKSA9PiB7XG4gICAgICAgICAgaWYgKGVyciA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG4gICAgICAgICAgcnVudGltZUxvZ2dlci53YXJuKCdCYWNrZ3JvdW5kIGZsdXNoIG9mIGhvb2sgcGF5bG9hZCBvcHMgZmFpbGVkJywge1xuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogaG9vay5ydW5JZCxcbiAgICAgICAgICAgIGhvb2tJZDogaG9vay5ob29rSWQsXG4gICAgICAgICAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dOYW1lKHJlc3VtZUNvbnRleHQud29ya2Zsb3dOYW1lKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gTGluayB0byB0aGUgcnVuLW9yaWdpbiBjb250ZXh0IGZyb20gdGhlIHN0b3JlZCB0cmFjZSBjYXJyaWVyXG4gICAgICAgIC8vIChza2lwcGVkIHdoZW4gYWJzZW50IG9yIGludmFsaWQpLiBSZXNvbHZlZCBiZWZvcmUgZGlzcGF0Y2ggc28gYm90aFxuICAgICAgICAvLyB0aGUgc2VxdWVudGlhbCBhbmQgcGFyYWxsZWwgcGF0aHMgYXR0YWNoIGl0LlxuICAgICAgICBjb25zdCBvcmlnaW5MaW5rID0gYXdhaXQgbGlua1RvVHJhY2VDYXJyaWVyKHJlc3VtZUNvbnRleHQudHJhY2VDYXJyaWVyKTtcbiAgICAgICAgaWYgKG9yaWdpbkxpbmspIHtcbiAgICAgICAgICBzcGFuPy5hZGRMaW5rPy4ob3JpZ2luTGluayk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBldmVudERhdGEgPSB7XG4gICAgICAgICAgLi4uKHYxQ29tcGF0ID8ge30gOiB7IHRva2VuOiBob29rLnRva2VuIH0pLFxuICAgICAgICAgIHBheWxvYWQ6IGRlaHlkcmF0ZWRQYXlsb2FkLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHF1ZXVlTmFtZSA9IGdldFdvcmtmbG93UXVldWVOYW1lKHJlc3VtZUNvbnRleHQud29ya2Zsb3dOYW1lKTtcbiAgICAgICAgY29uc3QgcXVldWVPcHRpb25zID0ge1xuICAgICAgICAgIGRlcGxveW1lbnRJZDogcmVzdW1lQ29udGV4dC5kZXBsb3ltZW50SWQsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IHJlc3VtZUNvbnRleHQucnVuU3BlY1ZlcnNpb24gPz8gU1BFQ19WRVJTSU9OX0xFR0FDWSxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBEZWNpZGUgd2hldGhlciB0byBwYXJhbGxlbGl6ZSB0aGUgYGhvb2tfcmVjZWl2ZWRgIHdyaXRlIGFuZCB0aGUgcXVldWVcbiAgICAgICAgLy8gcHVibGlzaC4gVGhlIGZhc3QgcGF0aCBpcyBvbmx5IHNhZmUgd2hlbiBFVkVSWSBwcmVjb25kaXRpb24gaG9sZHM7IHRoZVxuICAgICAgICAvLyBmaXJzdCB0aGF0IGZhaWxzIG5hbWVzIHRoZSBmYWxsYmFjayByZWFzb24gKGVtaXR0ZWQgYXMgYSBzcGFuXG4gICAgICAgIC8vIGF0dHJpYnV0ZSBmb3Igb2JzZXJ2YWJpbGl0eSwgYW5kIHRvIG1ha2UgXCJ3aHkgZGlkIHRoaXMgcnVuIHNlcXVlbnRpYWxcIlxuICAgICAgICAvLyBhbnN3ZXJhYmxlIGluIHByb2R1Y3Rpb24pLiBBbGwgY29uZGl0aW9uczpcbiAgICAgICAgLy9cbiAgICAgICAgLy8gIC0ga2lsbCBzd2l0Y2g6IGBXT1JLRkxPV19ESVNBQkxFX0xBWllfSE9PS19SRVNVTUVgIGZvcmNlcyBzZXF1ZW50aWFsXG4gICAgICAgIC8vICAgIGlmIHRoZSBmYXN0IHBhdGggZXZlciBtaXNiZWhhdmVzLiBJdCBpcyBhbiBTREstZGVwbG95bWVudCBlbnYgdmFyLFxuICAgICAgICAvLyAgICBzbyBjaGFuZ2luZyBpdCBnZW5lcmFsbHkgcmVxdWlyZXMgcmVkZXBsb3lpbmcgdGhlIHdvcmtmbG93XG4gICAgICAgIC8vICAgIGRlcGxveW1lbnQuIChUaGUgYmFja2VuZCBjYW4gaW5kZXBlbmRlbnRseSBkcm9wIG5ldyByZXN1bWVzIHRvIHRoZVxuICAgICAgICAvLyAgICBzZXF1ZW50aWFsIHBhdGggZmxlZXQtd2lkZSBieSBjZWFzaW5nIHRvIGF0dGVzdCBkZWR1cCBzdXBwb3J0IG9uXG4gICAgICAgIC8vICAgIHRoZSBieS10b2tlbiBsb29rdXAg4oCUIHNlZSB0aGUgYmFja2VuZC1kZWR1cCBjb25kaXRpb24gYmVsb3cuKVxuICAgICAgICAvLyAgLSBiYWNrZW5kIGRlZHVwOiB0aGUgbGl2ZSBiYWNrZW5kIG11c3QgZW5mb3JjZSB0aGVcbiAgICAgICAgLy8gICAgYChydW5JZCwgcmVzdW1lSWQpYCBjb25zdHJhaW50LCBvciB0aGUgdHdvIHdyaXRlcnMgd291bGQgY29tbWl0IHR3b1xuICAgICAgICAvLyAgICBgaG9va19yZWNlaXZlZGAgZXZlbnRzLiBGYWlsIGNsb3NlZC4gQXR0ZXN0ZWQgYnkgRUlUSEVSIGEgZnJlc2gsXG4gICAgICAgIC8vICAgIHJlc3BvbnNlLW9ubHkgYGhvb2sucmVzdW1lQ2FwYWJpbGl0aWVzLmhvb2tSZXN1bWVEZWR1cFZlcnNpb25gIGZyb21cbiAgICAgICAgLy8gICAgdGhlIGJ5LXRva2VuIGxvb2t1cCAod29ybGQtdmVyY2VsIOKAlCByZWNvbXB1dGVkIGV2ZXJ5IHJlYWQsIHNvIGFcbiAgICAgICAgLy8gICAgc2VydmVyIHJvbGxiYWNrIG9yIGtpbGwgc3dpdGNoIGRyb3BzIHRvIHNlcXVlbnRpYWwgaW1tZWRpYXRlbHkpIE9SXG4gICAgICAgIC8vICAgIHRoZSBzdGF0aWMgYHdvcmxkLmNhcGFiaWxpdGllcy5ob29rUmVzdW1lRGVkdXBgICh3b3JsZC1sb2NhbCwgd2hvc2VcbiAgICAgICAgLy8gICAgYWRhcHRlciBhbmQgYmFja2VuZCBzaGlwIHRvZ2V0aGVyKS4gVGhlIHJlc3BvbnNlLW9ubHkgY2FwYWJpbGl0eSBpc1xuICAgICAgICAvLyAgICB0cnVzdGVkIE9OTFkgd2hlbiB0aGUgaG9vayB3YXMgbG9va2VkIHVwIGJ5IHRva2VuIGR1cmluZyB0aGlzXG4gICAgICAgIC8vICAgIHJlc3VtZSAoYGhvb2tSZXN1bWVDYXBhYmlsaXRpZXNBcmVGcmVzaGApOyBhIEhvb2sgb2JqZWN0IGhhbmRlZCBpblxuICAgICAgICAvLyAgICBieSBhIHB1YmxpYyBjYWxsZXIgbWF5IGNhcnJ5IGEgY2FwYWJpbGl0eSBjYWNoZWQgYmVmb3JlIGEgcm9sbGJhY2ssXG4gICAgICAgIC8vICAgIHNvIGl0IGlzIGlnbm9yZWQgYW5kIHRoZSBwYXRoIGZhbGxzIGJhY2sgdG8gc2VxdWVudGlhbC5cbiAgICAgICAgLy8gIC0gY29uc3VtZXIgc3VwcG9ydDogdGhlIHRhcmdldCBydW4ncyBkZXBsb3ltZW50IG11c3QgcmUtZW5zdXJlIHRoZVxuICAgICAgICAvLyAgICBldmVudCBmcm9tIGBob29rSW5wdXRgIG9uIHJlcGxheS4gQXR0ZXN0ZWQgYnkgdGhlIHJ1bidzIGV4cGxpY2l0XG4gICAgICAgIC8vICAgIGBob29rUmVzdW1lSW5wdXRWZXJzaW9uYCBleGVjdXRpb24tY29udGV4dCBtYXJrZXIgKG1pcnJvcmVkIG9udG9cbiAgICAgICAgLy8gICAgcmVzdW1lQ29udGV4dCksIE5PVCBhIHZlcnNpb24tY29tcGFyZSBhZ2FpbnN0IGEgcHJlZGljdGVkIHJlbGVhc2VcbiAgICAgICAgLy8gICAgY3V0b2ZmLiBBYnNlbnQg4oaSIGEgbG9zdCBwcm9kdWNlciB3cml0ZSB3b3VsZCBiZSBhIGxvc3QgcmVzdW1lLlxuICAgICAgICAvLyAgLSBub3QgbGVnYWN5OiB2MUNvbXBhdCBydW5zIG9taXQgYHRva2VuYCBmcm9tIHRoZSBwcm9kdWNlcidzIGV2ZW50XG4gICAgICAgIC8vICAgIGJvZHkgYnV0IHRoZSBjb25zdW1lcidzIHJlLWVuc3VyZSBhbHdheXMgaW5jbHVkZXMgaXQsIHNvIHRoZSB0d29cbiAgICAgICAgLy8gICAgd3JpdGVycyB3b3VsZCBkaXNhZ3JlZSBvbiB0aGUgZXZlbnQgYm9keS4gTGVnYWN5IHN0YXlzIHNlcXVlbnRpYWwuXG4gICAgICAgIC8vICAtIENCT1IgdHJhbnNwb3J0OiB0aGUgcnVuIG11c3QgdXNlIENCT1IgcXVldWUgdHJhbnNwb3J0IHNvIHRoZSBiaW5hcnlcbiAgICAgICAgLy8gICAgcGF5bG9hZCBzdXJ2aXZlcyB0aGUgcXVldWUgbWVzc2FnZS5cbiAgICAgICAgLy8gIC0gcmF3IGJ5dGVzOiB0aGUgZGVoeWRyYXRlZCBwYXlsb2FkIG11c3QgYmUgYSBgVWludDhBcnJheWAgKHRoZVxuICAgICAgICAvLyAgICBjb250ZW50IGRpZ2VzdCB0aGF0IGtleXMgdGhlIGRlZHVwIGNvbnN0cmFpbnQgaXMgb3ZlciB0aGVzZSBieXRlcykuXG4gICAgICAgIC8vICAtIHNpemU6IGEgcGF5bG9hZCBhYm92ZSB0aGUgcXVldWUncyBtZXNzYWdlIGNlaWxpbmcgd291bGQgZmFpbCB0aGVcbiAgICAgICAgLy8gICAgcHVibGlzaCDigJQgd2hpY2gsIG9uIHRoZSBwYXJhbGxlbCBwYXRoLCB3b3VsZCBwZXJzaXN0IHRoZSBldmVudCBidXRcbiAgICAgICAgLy8gICAgbmV2ZXIgcmUtdHJpZ2dlciB0aGUgcnVuIOKAlCBzbyBvdmVyc2l6ZWQgcGF5bG9hZHMgc3RheSBzZXF1ZW50aWFsXG4gICAgICAgIC8vICAgICh0aGVpciBxdWV1ZSBtZXNzYWdlIGNhcnJpZXMgb25seSB0aGUgcnVuIElEKS5cbiAgICAgICAgY29uc3QgcGFyYWxsZWxSZXN1bWVEaXNhYmxlZCA9XG4gICAgICAgICAgcHJvY2Vzcy5lbnYuV09SS0ZMT1dfRElTQUJMRV9MQVpZX0hPT0tfUkVTVU1FID09PSAnMSc7XG4gICAgICAgIC8vIEJhY2tlbmQgZGVkdXAgaXMgc3VwcG9ydGVkIHdoZW4gRUlUSEVSIHRoZSBsaXZlIHNlcnZlciBhdHRlc3RzIGl0XG4gICAgICAgIC8vIGZyZXNoIG9uIHRoaXMgYnktdG9rZW4gaG9vayAod29ybGQtdmVyY2VsOiByZXNwb25zZS1vbmx5LCByZWNvbXB1dGVkXG4gICAgICAgIC8vIGV2ZXJ5IHJlYWQsIHNvIHJvbGxiYWNrL2tpbGwtc3dpdGNoIHRha2UgZWZmZWN0IGltbWVkaWF0ZWx5KSBPUiB0aGVcbiAgICAgICAgLy8gc3RhdGljIHdvcmxkIGNhcGFiaWxpdHkgaXMgc2V0ICh3b3JsZC1sb2NhbDogYWRhcHRlciArIGJhY2tlbmQgc2hpcFxuICAgICAgICAvLyB0b2dldGhlcikuIEJvdGggYXJlIHJlLWV2YWx1YXRlZCBwZXIgcmVzdW1lLCBzbyBldmVyeSByb2xsb3V0IGFuZFxuICAgICAgICAvLyByb2xsYmFjayBkaXJlY3Rpb24gZGVncmFkZXMgc2FmZWx5IHRvIHRoZSBzZXF1ZW50aWFsIHBhdGguXG4gICAgICAgIGNvbnN0IGJhY2tlbmREZWR1cFN1cHBvcnRlZCA9XG4gICAgICAgICAgKGhvb2tSZXN1bWVDYXBhYmlsaXRpZXNBcmVGcmVzaFxuICAgICAgICAgICAgPyAoaG9vay5yZXN1bWVDYXBhYmlsaXRpZXM/Lmhvb2tSZXN1bWVEZWR1cFZlcnNpb24gPz8gMClcbiAgICAgICAgICAgIDogMCkgPj0gSE9PS19SRVNVTUVfREVEVVBfVkVSU0lPTiB8fFxuICAgICAgICAgIHdvcmxkLmNhcGFiaWxpdGllcz8uaG9va1Jlc3VtZURlZHVwID09PSB0cnVlO1xuICAgICAgICBjb25zdCBmYWxsYmFja1JlYXNvbjogc3RyaW5nIHwgbnVsbCA9IHBhcmFsbGVsUmVzdW1lRGlzYWJsZWRcbiAgICAgICAgICA/ICdkaXNhYmxlZCdcbiAgICAgICAgICA6ICFiYWNrZW5kRGVkdXBTdXBwb3J0ZWRcbiAgICAgICAgICAgID8gJ2JhY2tlbmRfdW5zdXBwb3J0ZWQnXG4gICAgICAgICAgICA6IChyZXN1bWVDb250ZXh0Lmhvb2tSZXN1bWVJbnB1dFZlcnNpb24gPz8gMCkgPFxuICAgICAgICAgICAgICAgIEhPT0tfUkVTVU1FX0lOUFVUX1ZFUlNJT05cbiAgICAgICAgICAgICAgPyAnY29uc3VtZXJfdW5zdXBwb3J0ZWQnXG4gICAgICAgICAgICAgIDogdjFDb21wYXRcbiAgICAgICAgICAgICAgICA/ICdsZWdhY3knXG4gICAgICAgICAgICAgICAgOiAocmVzdW1lQ29udGV4dC5ydW5TcGVjVmVyc2lvbiA/PyAwKSA8XG4gICAgICAgICAgICAgICAgICAgIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DQk9SX1FVRVVFX1RSQU5TUE9SVFxuICAgICAgICAgICAgICAgICAgPyAnbm9uX2Nib3JfdHJhbnNwb3J0J1xuICAgICAgICAgICAgICAgICAgOiAhKGRlaHlkcmF0ZWRQYXlsb2FkIGluc3RhbmNlb2YgVWludDhBcnJheSlcbiAgICAgICAgICAgICAgICAgICAgPyAnbm9uX2J5dGVzJ1xuICAgICAgICAgICAgICAgICAgICA6IGRlaHlkcmF0ZWRQYXlsb2FkLmJ5dGVMZW5ndGggPlxuICAgICAgICAgICAgICAgICAgICAgICAgTUFYX0lOTElORV9SRVNVTUVfUEFZTE9BRF9CWVRFU1xuICAgICAgICAgICAgICAgICAgICAgID8gJ292ZXJzaXplZCdcbiAgICAgICAgICAgICAgICAgICAgICA6IG51bGw7XG4gICAgICAgIGNvbnN0IHVzZVBhcmFsbGVsUmVzdW1lID0gZmFsbGJhY2tSZWFzb24gPT09IG51bGw7XG5cbiAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgJ3dvcmtmbG93Lmhvb2sucmVzdW1lX3N0cmF0ZWd5JzogdXNlUGFyYWxsZWxSZXN1bWVcbiAgICAgICAgICAgID8gJ3BhcmFsbGVsJ1xuICAgICAgICAgICAgOiAnc2VxdWVudGlhbCcsXG4gICAgICAgICAgLi4uKGZhbGxiYWNrUmVhc29uXG4gICAgICAgICAgICA/IHsgJ3dvcmtmbG93Lmhvb2sucmVzdW1lX2ZhbGxiYWNrX3JlYXNvbic6IGZhbGxiYWNrUmVhc29uIH1cbiAgICAgICAgICAgIDoge30pLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBSZS1rZXkgYW55IFwiaG9vayBjYW4gbm8gbG9uZ2VyIGJlIHJlY2VpdmVkXCIgcmVqZWN0aW9uIHRvXG4gICAgICAgIC8vIEhvb2tOb3RGb3VuZEVycm9yKGhvb2sudG9rZW4pIHNvIGAudG9rZW5gIG1hdGNoZXMgdGhlIHByZS1mYXN0LXBhdGhcbiAgICAgICAgLy8gY29udHJhY3QsIHdoZXJlIHJlc3VtZUhvb2sgdGhyZXcgYEhvb2tOb3RGb3VuZEVycm9yKGhvb2sudG9rZW4pYFxuICAgICAgICAvLyBhZnRlciBpdHMgb3duIHRlcm1pbmFsIGNoZWNrLiBUaGUgc3BlY2lmaWMgZXJyb3IgZGVwZW5kcyBvbiB0aGVcbiAgICAgICAgLy8gV29ybGQ6XG4gICAgICAgIC8vICAgLSBhIGdlbnVpbmVseSBtaXNzaW5nIGhvb2sgbWFwcyB0byBIb29rTm90Rm91bmRFcnJvciAoa2V5ZWQgb24gdGhlXG4gICAgICAgIC8vICAgICBldmVudCBjb3JyZWxhdGlvbklkIC8gaG9vayBJRCk7XG4gICAgICAgIC8vICAgLSBhIHRlcm1pbmFsIHJ1biBvbiBWZXJjZWwgcmVqZWN0cyBob29rX3JlY2VpdmVkIHdpdGggNDA0LCB3aGljaFxuICAgICAgICAvLyAgICAgd29ybGQtdmVyY2VsIG1hcHMgdG8gSG9va05vdEZvdW5kRXJyb3I7XG4gICAgICAgIC8vICAgLSBhIHRlcm1pbmFsIHJ1biBvbiB3b3JsZC1sb2NhbCAvIHdvcmxkLXBvc3RncmVzIHJlamVjdHMgd2l0aFxuICAgICAgICAvLyAgICAgUnVuRXhwaXJlZEVycm9yLlxuICAgICAgICAvL1xuICAgICAgICAvLyBPbiB0aGUgU0VRVUVOVElBTCBwYXRoIGFuIEVudGl0eUNvbmZsaWN0RXJyb3IgKEhUVFAgNDA5KSBpcyBhbHNvXG4gICAgICAgIC8vIHRyZWF0ZWQgYXMgXCJob29rIGdvbmVcIiBmb3IgaGlzdG9yaWNhbCAvIGNvbmZsaWN0LXNoYXBlZC1yZWplY3Rpb25cbiAgICAgICAgLy8gY29tcGF0aWJpbGl0eTogdGhlcmUgaXMgbm8gcXVldWUgbWVzc2FnZSBpbiBmbGlnaHQsIHNvIGEgY29uZmxpY3QgaGFzXG4gICAgICAgIC8vIG5vIHJlLWVuc3VyaW5nIGNvbnN1bWVyIHRvIGNvbnZlcmdlIG9uLiBUaGUgUEFSQUxMRUwgcGF0aCBoYW5kbGVzIDQwOVxuICAgICAgICAvLyBkaWZmZXJlbnRseSAoc2VlIGJlbG93KSDigJQgaXQgcHVibGlzaGVkIHRoZSBxdWV1ZSBtZXNzYWdlIGJlZm9yZSB0aGVcbiAgICAgICAgLy8gY29uZmxpY3QsIHNvIHRoZSBjb25zdW1lciB3aWxsIGNvbnZlcmdlIHRoZSBldmVudC5cbiAgICAgICAgY29uc3QgaXNIb29rR29uZUVycm9yID0gKGVycjogdW5rbm93bik6IGJvb2xlYW4gPT5cbiAgICAgICAgICBIb29rTm90Rm91bmRFcnJvci5pcyhlcnIpIHx8XG4gICAgICAgICAgRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpIHx8XG4gICAgICAgICAgUnVuRXhwaXJlZEVycm9yLmlzKGVycik7XG5cbiAgICAgICAgaWYgKCF1c2VQYXJhbGxlbFJlc3VtZSkge1xuICAgICAgICAgIC8vIFNlcXVlbnRpYWwgcGF0aDogY3JlYXRlIGEgaG9va19yZWNlaXZlZCBldmVudCwgdGhlbiByZS10cmlnZ2VyLlxuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKFxuICAgICAgICAgICAgICBob29rLnJ1bklkLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnaG9va19yZWNlaXZlZCcsXG4gICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IGhvb2suaG9va0lkLFxuICAgICAgICAgICAgICAgIGV2ZW50RGF0YSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgeyB2MUNvbXBhdCB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKGlzSG9va0dvbmVFcnJvcihlcnIpKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBIb29rTm90Rm91bmRFcnJvcihob29rLnRva2VuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBUMSBvZiB0aGUgVFRSIHdpbmRvdy4gU3RhbXBlZCBpbW1lZGlhdGVseSBiZWZvcmUgdGhlIHB1Ymxpc2ggc29cbiAgICAgICAgICAvLyBgcHJvZHVjZXJfcHJlcGAgY292ZXJzIGV4YWN0bHkgdGhlIHdvcmsgYWJvdmUgaXQgKGhvb2sgbG9va3VwLFxuICAgICAgICAgIC8vIGtleSByZXNvbHV0aW9uLCBzZXJpYWxpemF0aW9uLCBhbmQg4oCUIG9uIHRoaXMgcGF0aCDigJQgdGhlIGF3YWl0ZWRcbiAgICAgICAgICAvLyBgaG9va19yZWNlaXZlZGAgd3JpdGUsIHdoaWNoIGlzIGdlbnVpbmVseSBzZXJpYWwgaGVyZSkuXG4gICAgICAgICAgY29uc3QgcXVldWVQdWJsaXNoUmVxdWVzdGVkQXRNcyA9IERhdGUubm93KCk7XG4gICAgICAgICAgYXdhaXQgd29ybGQucXVldWUoXG4gICAgICAgICAgICBxdWV1ZU5hbWUsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHJ1bklkOiBob29rLnJ1bklkLFxuICAgICAgICAgICAgICB0cmFjZUNhcnJpZXI6IHJlc3VtZUNvbnRleHQudHJhY2VDYXJyaWVyID8/IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgaG9va1Jlc3VtZVRpbWluZzoge1xuICAgICAgICAgICAgICAgIHJlc3VtZVJlcXVlc3RlZEF0TXMsXG4gICAgICAgICAgICAgICAgcXVldWVQdWJsaXNoUmVxdWVzdGVkQXRNcyxcbiAgICAgICAgICAgICAgICBzdHJhdGVneTogJ3NlcXVlbnRpYWwnLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSBzYXRpc2ZpZXMgV29ya2Zsb3dJbnZva2VQYXlsb2FkLFxuICAgICAgICAgICAgcXVldWVPcHRpb25zXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIHJldHVybiBob29rO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUGFyYWxsZWwgZmFzdCBwYXRoLiBBIHN0YWJsZSBpZGVtcG90ZW5jeSBrZXkgdGllcyB0aGUgZGlyZWN0IHdyaXRlIHRvXG4gICAgICAgIC8vIHRoZSBxdWV1ZSBjb25zdW1lcidzIHJlLWVuc3VyZTsgdGhlIHBheWxvYWQgZGlnZXN0IGxldHMgdGhlIHNlcnZlclxuICAgICAgICAvLyBkZXRlY3Qga2V5IHJldXNlIGFjcm9zcyBieXRlLWlkZW50aWNhbCBwYXlsb2Fkcy5cbiAgICAgICAgY29uc3QgcmVzdW1lSWQgPSBnZW5lcmF0ZVJlc3VtZUlkKCk7XG4gICAgICAgIGNvbnN0IHBheWxvYWREaWdlc3QgPSBhd2FpdCBjb21wdXRlUmVzdW1lUGF5bG9hZERpZ2VzdChcbiAgICAgICAgICBkZWh5ZHJhdGVkUGF5bG9hZCBhcyBVaW50OEFycmF5XG4gICAgICAgICk7XG4gICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoeyAnd29ya2Zsb3cuaG9vay5yZXN1bWVfaWQnOiByZXN1bWVJZCB9KTtcblxuICAgICAgICAvLyBXcmFwcGVkIGluIGEgdGh1bmsgcHVyZWx5IHNvIFQxIG9mIHRoZSBUVFIgd2luZG93IGlzIHN0YW1wZWQgYXQgdGhlXG4gICAgICAgIC8vIGV4YWN0IGluc3RhbnQgdGhlIHB1Ymxpc2ggaXMgcmVxdWVzdGVkIOKAlCBhZnRlciB0aGUgcmFjaW5nXG4gICAgICAgIC8vIGBob29rX3JlY2VpdmVkYCB3cml0ZSBoYXMgYmVlbiBraWNrZWQgb2ZmLCB3aGljaCBpcyB3aGVyZSB0aGVcbiAgICAgICAgLy8gYWRkaXRpdmUgYHByb2R1Y2VyX3ByZXBgIHBoYXNlIG11c3QgZW5kLiBUaGUgdHdvIGNhbGxzIHN0aWxsIHN0YXJ0XG4gICAgICAgIC8vIGluIHRoZSBzYW1lIHR1cm4gYW5kIHJhY2UgZXhhY3RseSBhcyBiZWZvcmUuXG4gICAgICAgIGNvbnN0IHB1Ymxpc2hJbnZvY2F0aW9uID0gKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHF1ZXVlUHVibGlzaFJlcXVlc3RlZEF0TXMgPSBEYXRlLm5vdygpO1xuICAgICAgICAgIHJldHVybiB3b3JsZC5xdWV1ZShcbiAgICAgICAgICAgIHF1ZXVlTmFtZSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgcnVuSWQ6IGhvb2sucnVuSWQsXG4gICAgICAgICAgICAgIHRyYWNlQ2FycmllcjogcmVzdW1lQ29udGV4dC50cmFjZUNhcnJpZXIgPz8gdW5kZWZpbmVkLFxuICAgICAgICAgICAgICBob29rSW5wdXQ6IHtcbiAgICAgICAgICAgICAgICByZXN1bWVJZCxcbiAgICAgICAgICAgICAgICBob29rSWQ6IGhvb2suaG9va0lkLFxuICAgICAgICAgICAgICAgIHRva2VuOiBob29rLnRva2VuLFxuICAgICAgICAgICAgICAgIHBheWxvYWQ6IGRlaHlkcmF0ZWRQYXlsb2FkLFxuICAgICAgICAgICAgICAgIHBheWxvYWREaWdlc3QsXG4gICAgICAgICAgICAgICAgLy8gRGVwbG95bWVudCBhZmZpbml0eSBmb3IgdGhlIGNvbnN1bWVyJ3MgY2hlYXAgcHJlLXdyaXRlXG4gICAgICAgICAgICAgICAgLy8gY2hlY2s6IGxldHMgYSBtaXNyb3V0ZWQgZGVsaXZlcnkgcmUtcm91dGUgYmVmb3JlIGl0c1xuICAgICAgICAgICAgICAgIC8vIGhvaXN0ZWQgaG9va19yZWNlaXZlZCB3cml0ZSBpbnN0ZWFkIG9mIGFmdGVyLlxuICAgICAgICAgICAgICAgIGRlcGxveW1lbnRJZDogcmVzdW1lQ29udGV4dC5kZXBsb3ltZW50SWQsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGhvb2tSZXN1bWVUaW1pbmc6IHtcbiAgICAgICAgICAgICAgICByZXN1bWVSZXF1ZXN0ZWRBdE1zLFxuICAgICAgICAgICAgICAgIHF1ZXVlUHVibGlzaFJlcXVlc3RlZEF0TXMsXG4gICAgICAgICAgICAgICAgc3RyYXRlZ3k6ICdwYXJhbGxlbCcsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9IHNhdGlzZmllcyBXb3JrZmxvd0ludm9rZVBheWxvYWQsXG4gICAgICAgICAgICBxdWV1ZU9wdGlvbnNcbiAgICAgICAgICApO1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCBbZXZlbnRSZXN1bHQsIHF1ZXVlUmVzdWx0XSA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChbXG4gICAgICAgICAgd29ybGQuZXZlbnRzLmNyZWF0ZShcbiAgICAgICAgICAgIGhvb2sucnVuSWQsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfcmVjZWl2ZWQnLFxuICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IGhvb2suaG9va0lkLFxuICAgICAgICAgICAgICBldmVudERhdGEsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgeyB2MUNvbXBhdCwgcmVzdW1lSWQsIHJlc3VtZVBheWxvYWREaWdlc3Q6IHBheWxvYWREaWdlc3QgfVxuICAgICAgICAgICksXG4gICAgICAgICAgcHVibGlzaEludm9jYXRpb24oKSxcbiAgICAgICAgXSk7XG5cbiAgICAgICAgLy8gUXVldWUgZmFpbHVyZSBpcyBhbHdheXMgZmF0YWwg4oCUIHRoZSBydW4gd2FzIG5vdCByZS10cmlnZ2VyZWQsIHNvIG5vXG4gICAgICAgIC8vIGNvbnN1bWVyIHdpbGwgcmUtZW5zdXJlIHRoZSBldmVudC5cbiAgICAgICAgaWYgKHF1ZXVlUmVzdWx0LnN0YXR1cyA9PT0gJ3JlamVjdGVkJykge1xuICAgICAgICAgIHRocm93IHF1ZXVlUmVzdWx0LnJlYXNvbjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldCB3aGVuIHRoZSBkaXJlY3Qgd3JpdGUgZGlkIG5vdCBsYW5kIGJ1dCB0aGUgcXVldWUgZGlzcGF0Y2ggZGlkLCBzb1xuICAgICAgICAvLyB0aGUgY29uc3VtZXIgbWF0ZXJpYWxpemVzIHRoZSBldmVudCBiZWZvcmUgcmVwbGF5LiBTdXJmYWNlZCB0byB0aGVcbiAgICAgICAgLy8gY2FsbGVyIGFzIGBSZXN1bWVkSG9vay5yZXNpbGllbnRSZXN1bWVgIGFuZCBvbiB0aGUgc3Bhbi5cbiAgICAgICAgbGV0IHJlc2lsaWVudFJlc3VtZSA9IGZhbHNlO1xuICAgICAgICBpZiAoZXZlbnRSZXN1bHQuc3RhdHVzID09PSAncmVqZWN0ZWQnKSB7XG4gICAgICAgICAgY29uc3QgZXJyID0gZXZlbnRSZXN1bHQucmVhc29uO1xuICAgICAgICAgIGlmIChIb29rTm90Rm91bmRFcnJvci5pcyhlcnIpIHx8IFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAvLyBUaGUgaG9vaydzIHJ1biBoYXMgZ2VudWluZWx5IGVuZGVkOiBzdXJmYWNlIHRoZSBzYW1lIGNvbnRyYWN0IGFzXG4gICAgICAgICAgICAvLyB0aGUgc2VxdWVudGlhbCBwYXRoLiBUaGUgcXVldWUgbWVzc2FnZSBhbHJlYWR5IHdlbnQgb3V0LCBidXQgdGhlXG4gICAgICAgICAgICAvLyBjb25zdW1lcidzIHJlLWVuc3VyZSB3aWxsIGFsc28gcmVqZWN0IGFnYWluc3QgdGhlIHRlcm1pbmFsIHJ1blxuICAgICAgICAgICAgLy8gYW5kIG5vLW9wLCBzbyB0aGUgd29ya2Zsb3cgZG9lcyBub3QgcmVzdW1lLlxuICAgICAgICAgICAgdGhyb3cgbmV3IEhvb2tOb3RGb3VuZEVycm9yKGhvb2sudG9rZW4pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpIHx8IGlzUmV0cnlhYmxlV29ybGRFcnJvcihlcnIpKSB7XG4gICAgICAgICAgICAvLyBSZXNpbGllbnQuIFR3byBzaGFwZXMgcmVhY2ggaGVyZSwgYm90aCBub24tdGVybWluYWw6XG4gICAgICAgICAgICAvLyAgIC0gRW50aXR5Q29uZmxpY3QgKDQwOSk6IHRoaXMgd3JpdGUgcmFjZWQgaXRzIG93biByZS1lbnN1cmluZ1xuICAgICAgICAgICAgLy8gICAgIGNvbnN1bWVyIChvciBhIHJlZHJpdmUpIG9uIHRoZSBzaGFyZWQgYHJlc3VtZUlkYCDigJQgdGhlIHJ1biBpc1xuICAgICAgICAgICAgLy8gICAgIE5PVCBnb25lLCBhbmQgdGhlIGNvbnN1bWVyIGNvbnZlcmdlcyBvbiB0aGUgb25lIGNvbW1pdHRlZFxuICAgICAgICAgICAgLy8gICAgIGV2ZW50LiBVbmxpa2UgdGhlIHNlcXVlbnRpYWwgcGF0aCwgYSA0MDkgaGVyZSBpcyBleHBlY3RlZFxuICAgICAgICAgICAgLy8gICAgIGNvbmN1cnJlbmN5LCBub3QgYSB2YW5pc2hlZCBob29rLlxuICAgICAgICAgICAgLy8gICAtIDQyOSAvIDV4eCAvIHRyYW5zcG9ydDogYSB0cmFuc2llbnQgYmFja2VuZCBmYWlsdXJlLlxuICAgICAgICAgICAgLy8gSW4gYm90aCBjYXNlcyB0aGUgcnVuIFdBUyByZS10cmlnZ2VyZWQgdmlhIHRoZSBxdWV1ZSBhbmQgdGhlXG4gICAgICAgICAgICAvLyBjb25zdW1lciBpZGVtcG90ZW50bHkgZW5zdXJlcyB0aGUgaG9va19yZWNlaXZlZCBiZWZvcmUgcmVwbGF5LCBzb1xuICAgICAgICAgICAgLy8gc3dhbGxvdyByYXRoZXIgdGhhbiBmYWlsaW5nIHRoZSBjYWxsZXIuXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gUHJvZHVjZXIgdGVsZW1ldHJ5OiByZWNvcmQgdGhhdCB0aGUgZGlyZWN0IHdyaXRlIGRpZCBub3QgbGFuZCBidXRcbiAgICAgICAgICAgIC8vIHRoZSByZXN1bWUgaXMgc3RpbGwgZ3VhcmFudGVlZCB2aWEgcXVldWUtZGVsaXZlcmVkIGBob29rSW5wdXRgLlxuICAgICAgICAgICAgLy8gVGhpcyBpcyB0aGUgb3BlcmF0aW9uYWwgc2lnbmFsIHRoYXQgdGhlIHJlY292ZXJ5IHBhdGggZmlyZWQsXG4gICAgICAgICAgICAvLyBzdXJmYWNlZCBib3RoIG9uIHRoZSBzcGFuIGFuZCBhcyB0aGUgcHVibGljIGByZXNpbGllbnRSZXN1bWVgXG4gICAgICAgICAgICAvLyBmbGFnIG9uIHRoZSByZXR1cm5lZCBob29rICh0aGUgcmVzdW1lIG91dGNvbWUgaXMgb3RoZXJ3aXNlXG4gICAgICAgICAgICAvLyBpZGVudGljYWwgdG8gdGhlIGhhcHB5IHBhdGggZnJvbSB0aGUgY2FsbGVyJ3MgcGVyc3BlY3RpdmUpLlxuICAgICAgICAgICAgcmVzaWxpZW50UmVzdW1lID0gdHJ1ZTtcbiAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuSG9va1Jlc2lsaWVudFJlc3VtZSh0cnVlKSxcbiAgICAgICAgICAgICAgJ3dvcmtmbG93Lmhvb2sucmVzdW1lX2V2ZW50X3dyaXRlX3JlY292ZXJlZCc6IHRydWUsXG4gICAgICAgICAgICAgICd3b3JrZmxvdy5ob29rLnJlc3VtZV9ldmVudF93cml0ZV9lcnJvcic6XG4gICAgICAgICAgICAgICAgZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubmFtZSA6ICd1bmtub3duJyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci53YXJuKFxuICAgICAgICAgICAgICAnSG9vayByZXN1bWUgZXZlbnQgd3JpdGUgZmFpbGVkLCBidXQgdGhlIHJ1biB3YXMgcmUtdHJpZ2dlcmVkIHZpYSAnICtcbiAgICAgICAgICAgICAgICAndGhlIHF1ZXVlLiBUaGUgaG9va19yZWNlaXZlZCBldmVudCB3aWxsIGJlIGVuc3VyZWQgYnkgdGhlICcgK1xuICAgICAgICAgICAgICAgICdxdWV1ZSBjb25zdW1lci4nLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogaG9vay5ydW5JZCxcbiAgICAgICAgICAgICAgICBob29rSWQ6IGhvb2suaG9va0lkLFxuICAgICAgICAgICAgICAgIHJlc3VtZUlkLFxuICAgICAgICAgICAgICAgIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIHJlc2lsaWVudFJlc3VtZSA/IHsgLi4uaG9vaywgcmVzaWxpZW50UmVzdW1lOiB0cnVlIH0gOiBob29rXG4gICAgICAgICkgc2F0aXNmaWVzIFJlc3VtZWRIb29rO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Ib29rVG9rZW4oXG4gICAgICAgICAgICB0eXBlb2YgdG9rZW5Pckhvb2sgPT09ICdzdHJpbmcnID8gdG9rZW5Pckhvb2sgOiB0b2tlbk9ySG9vay50b2tlblxuICAgICAgICAgICksXG4gICAgICAgICAgLi4uQXR0cmlidXRlLkhvb2tGb3VuZChmYWxzZSksXG4gICAgICAgIH0pO1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuXG4vKipcbiAqIFJlc3VtZXMgYSB3ZWJob29rIGJ5IHNlbmRpbmcgYSB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1JlcXVlc3QgfCBSZXF1ZXN0fVxuICogb2JqZWN0IHRvIGEgaG9vayBpZGVudGlmaWVkIGJ5IGl0cyB0b2tlbi5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBleHRlcm5hbGx5IChlLmcuLCBmcm9tIGFuIEFQSSByb3V0ZSBvciBzZXJ2ZXIgYWN0aW9uKVxuICogdG8gc2VuZCBhIHJlcXVlc3QgdG8gYSB3ZWJob29rIGFuZCByZXN1bWUgdGhlIGFzc29jaWF0ZWQgd29ya2Zsb3cgcnVuLlxuICpcbiAqIEBwYXJhbSB0b2tlbiAtIFRoZSB1bmlxdWUgdG9rZW4gaWRlbnRpZnlpbmcgdGhlIGhvb2tcbiAqIEBwYXJhbSByZXF1ZXN0IC0gVGhlIHJlcXVlc3QgdG8gc2VuZCB0byB0aGUgaG9va1xuICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHJlc3BvbnNlXG4gKiBAdGhyb3dzIEVycm9yIGlmIHRoZSBob29rIGlzIG5vdCBmb3VuZCBvciBpZiB0aGVyZSdzIGFuIGVycm9yIGR1cmluZyB0aGUgcHJvY2Vzc1xuICpcbiAqIEBleGFtcGxlXG4gKlxuICogYGBgdHNcbiAqIC8vIEluIGFuIEFQSSByb3V0ZVxuICogaW1wb3J0IHsgcmVzdW1lV2ViaG9vayB9IGZyb20gJ0B3b3JrZmxvdy9jb3JlL3J1bnRpbWUnO1xuICpcbiAqIGV4cG9ydCBhc3luYyBmdW5jdGlvbiBQT1NUKHJlcXVlc3Q6IFJlcXVlc3QpIHtcbiAqICAgY29uc3QgdXJsID0gbmV3IFVSTChyZXF1ZXN0LnVybCk7XG4gKiAgIGNvbnN0IHRva2VuID0gdXJsLnNlYXJjaFBhcmFtcy5nZXQoJ3Rva2VuJyk7XG4gKlxuICogICBpZiAoIXRva2VuKSB7XG4gKiAgICAgcmV0dXJuIG5ldyBSZXNwb25zZSgnTWlzc2luZyB0b2tlbicsIHsgc3RhdHVzOiA0MDAgfSk7XG4gKiAgIH1cbiAqXG4gKiAgIHRyeSB7XG4gKiAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCByZXN1bWVXZWJob29rKHRva2VuLCByZXF1ZXN0KTtcbiAqICAgICByZXR1cm4gcmVzcG9uc2U7XG4gKiAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gKiAgICAgcmV0dXJuIG5ldyBSZXNwb25zZSgnV2ViaG9vayBub3QgZm91bmQnLCB7IHN0YXR1czogNDA0IH0pO1xuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlc3VtZVdlYmhvb2soXG4gIHRva2VuOiBzdHJpbmcsXG4gIHJlcXVlc3Q6IFJlcXVlc3Rcbik6IFByb21pc2U8UmVzcG9uc2U+IHtcbiAgLy8gVDAgb2YgdGhlIGhvb2stcmVzdW1lIFRUUiB3aW5kb3cuIEV2ZXJ5dGhpbmcgYmVsb3cg4oCUIHRoZSBieS10b2tlbiBsb29rdXAsXG4gIC8vIHRoZSBydW4ta2V5IHJlc29sdXRpb24gaXQgbWF5IHRyaWdnZXIsIGFuZCB0aGUgYHJlc3BvbmRXaXRoYCBzZXR1cCDigJQgaXNcbiAgLy8gcmVhbCBwcm9kdWNlci1zaWRlIGxhdGVuY3kgb24gdGhpcyBwYXRoLCBzbyB0aGUgd2luZG93IGhhcyB0byBvcGVuIGhlcmVcbiAgLy8gYW5kIG5vdCBpbnNpZGUgYHJlc3VtZUhvb2tJbXBsYDsgb3RoZXJ3aXNlIHdlYmhvb2sgcmVzdW1lcyB3b3VsZCByZXBvcnQgYVxuICAvLyBzeXN0ZW1hdGljYWxseSBzaG9ydGVyIHRvdGFsIHRoYW4gYHJlc3VtZUhvb2tgIG9uZXMgaW50byB0aGUgc2FtZSBtZXRyaWMuXG4gIGNvbnN0IHJlc3VtZVJlcXVlc3RlZEF0TXMgPSBEYXRlLm5vdygpO1xuICBjb25zdCB7IGhvb2ssIGVuY3J5cHRpb25LZXkgfSA9IGF3YWl0IGdldEhvb2tCeVRva2VuV2l0aEtleSh0b2tlbik7XG5cbiAgLy8gT25seSB3ZWJob29rcyBjYW4gYmUgcmVzdW1lZCB2aWEgdGhlIHB1YmxpYyBlbmRwb2ludC5cbiAgLy8gSWYgdGhlIGhvb2sgd2FzIGNyZWF0ZWQgdmlhIGNyZWF0ZUhvb2soKSAoaXNXZWJob29rICE9PSB0cnVlKSxcbiAgLy8gdGhyb3cgdGhlIHNhbWUgXCJub3QgZm91bmRcIiBlcnJvciB0aGUgd29ybGQgd291bGQgdGhyb3cgZm9yIGEgbWlzc2luZ1xuICAvLyB0b2tlbi4gVGhpcyBwcmV2ZW50cyBsZWFraW5nIHRoYXQgdGhlIHRva2VuIGlzIHZhbGlkLlxuICBpZiAoaG9vay5pc1dlYmhvb2sgPT09IGZhbHNlKSB7XG4gICAgdGhyb3cgbmV3IEhvb2tOb3RGb3VuZEVycm9yKHRva2VuKTtcbiAgfVxuXG4gIGxldCByZXNwb25zZTogUmVzcG9uc2UgfCB1bmRlZmluZWQ7XG4gIGxldCByZXNwb25zZVJlYWRhYmxlOiBSZWFkYWJsZVN0cmVhbTxSZXNwb25zZT4gfCB1bmRlZmluZWQ7XG4gIGlmIChcbiAgICBob29rLm1ldGFkYXRhICYmXG4gICAgdHlwZW9mIGhvb2subWV0YWRhdGEgPT09ICdvYmplY3QnICYmXG4gICAgJ3Jlc3BvbmRXaXRoJyBpbiBob29rLm1ldGFkYXRhXG4gICkge1xuICAgIGlmIChob29rLm1ldGFkYXRhLnJlc3BvbmRXaXRoID09PSAnbWFudWFsJykge1xuICAgICAgY29uc3QgeyByZWFkYWJsZSwgd3JpdGFibGUgfSA9IG5ldyBUcmFuc2Zvcm1TdHJlYW08UmVzcG9uc2UsIFJlc3BvbnNlPigpO1xuICAgICAgcmVzcG9uc2VSZWFkYWJsZSA9IHJlYWRhYmxlO1xuXG4gICAgICAvLyBUaGUgcmVxdWVzdCBpbnN0YW5jZSBpbmNsdWRlcyB0aGUgd3JpdGFibGUgc3RyZWFtIHdoaWNoIHdpbGwgYmUgdXNlZFxuICAgICAgLy8gdG8gd3JpdGUgdGhlIHJlc3BvbnNlIHRvIHRoZSBjbGllbnQgZnJvbSB3aXRoaW4gdGhlIHdvcmtmbG93IHJ1blxuICAgICAgKHJlcXVlc3QgYXMgYW55KVtXRUJIT09LX1JFU1BPTlNFX1dSSVRBQkxFXSA9IHdyaXRhYmxlO1xuICAgIH0gZWxzZSBpZiAoaG9vay5tZXRhZGF0YS5yZXNwb25kV2l0aCBpbnN0YW5jZW9mIFJlc3BvbnNlKSB7XG4gICAgICByZXNwb25zZSA9IGhvb2subWV0YWRhdGEucmVzcG9uZFdpdGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcihcbiAgICAgICAgYEludmFsaWQgXFxgcmVzcG9uZFdpdGhcXGAgdmFsdWU6ICR7aG9vay5tZXRhZGF0YS5yZXNwb25kV2l0aH1gLFxuICAgICAgICB7IHNsdWc6IEVSUk9SX1NMVUdTLldFQkhPT0tfSU5WQUxJRF9SRVNQT05EX1dJVEhfVkFMVUUgfVxuICAgICAgKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgLy8gTm8gYHJlc3BvbmRXaXRoYCB2YWx1ZSBpbXBsaWVzIHRoZSBkZWZhdWx0IGJlaGF2aW9yIG9mIHJldHVybmluZyBhIDIwMlxuICAgIHJlc3BvbnNlID0gbmV3IFJlc3BvbnNlKG51bGwsIHsgc3RhdHVzOiAyMDIgfSk7XG4gIH1cblxuICAvLyBgaG9va2Agd2FzIGp1c3QgZmV0Y2hlZCB2aWEgYGdldEhvb2tCeVRva2VuV2l0aEtleWAgKGEgZnJlc2ggYnktdG9rZW5cbiAgLy8gbG9va3VwKSBhYm92ZSwgc28gaXRzIHJlc3BvbnNlLW9ubHkgYHJlc3VtZUNhcGFiaWxpdGllc2AgcmVmbGVjdHMgdGhlIGxpdmVcbiAgLy8gYmFja2VuZCDigJQgY2FsbCB0aGUgaW50ZXJuYWwgaW1wbGVtZW50YXRpb24gd2l0aCB0aGUgZnJlc2ggYXR0ZXN0YXRpb24gc29cbiAgLy8gdGhlIHBhcmFsbGVsIGZhc3QgcGF0aCBzdGF5cyBhdmFpbGFibGUgd2l0aG91dCBhIHNlY29uZCBHRVQuIChUaGUgcHVibGljXG4gIC8vIGByZXN1bWVIb29rYCBuZXZlciBzZXRzIHRoaXMsIHNvIGEgY2FsbGVyIGNhbm5vdCBmb3JnZSBpdC4pXG4gIGF3YWl0IHJlc3VtZUhvb2tJbXBsKGhvb2ssIHJlcXVlc3QsIGVuY3J5cHRpb25LZXksIHRydWUsIHJlc3VtZVJlcXVlc3RlZEF0TXMpO1xuXG4gIGlmIChyZXNwb25zZVJlYWRhYmxlKSB7XG4gICAgLy8gV2FpdCBmb3IgdGhlIHJlYWRhYmxlIHN0cmVhbSB0byBlbWl0IG9uZSBjaHVuayxcbiAgICAvLyB3aGljaCBpcyB0aGUgYFJlc3BvbnNlYCBvYmplY3RcbiAgICBjb25zdCByZWFkZXIgPSByZXNwb25zZVJlYWRhYmxlLmdldFJlYWRlcigpO1xuICAgIGNvbnN0IGNodW5rID0gYXdhaXQgcmVhZGVyLnJlYWQoKTtcbiAgICBpZiAoY2h1bmsudmFsdWUpIHtcbiAgICAgIHJlc3BvbnNlID0gY2h1bmsudmFsdWU7XG4gICAgfVxuICAgIHJlYWRlci5jYW5jZWwoKTtcbiAgfVxuXG4gIGlmICghcmVzcG9uc2UpIHtcbiAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoJ1dvcmtmbG93IHJ1biBkaWQgbm90IHNlbmQgYSByZXNwb25zZScsIHtcbiAgICAgIHNsdWc6IEVSUk9SX1NMVUdTLldFQkhPT0tfUkVTUE9OU0VfTk9UX1NFTlQsXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gcmVzcG9uc2U7XG59XG4iXX0=
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==