velocious 1.0.654 → 1.0.655

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2889,7 +2889,7 @@ When the server runs in the `development` environment, Velocious watches applica
2889
2889
 
2890
2890
  Starting the HTTP server creates `tmp/server.lock` under the configured application directory before Beacon, workers, or the TCP listener start. A second server for the same app fails fast with the lock owner details instead of partially starting. Normal shutdown removes the lock; stale locks with a dead local PID are reclaimed automatically, while locks from another host or unreadable metadata should be removed manually only after confirming no server is running. See [docs/http-server.md](docs/http-server.md#server-lock).
2891
2891
 
2892
- Buffered string and `Uint8Array` responses are compressed with Brotli (`br`) or gzip by default whenever request negotiation and response eligibility allow — no opt-in is required. Disable compression globally with `httpServer.compression: false` or `httpServer.compression: {enabled: false}`, and tune it with `threshold`/`brotliQuality`/`gzipLevel` overrides. Negotiation honors `Accept-Encoding` q-values, wildcards, and identity semantics (empty `406` when no acceptable representation exists), merges `Accept-Encoding` into `Vary`, and skips streamed `sendFile` responses, already-encoded or `no-transform` responses, server-sent events, partial/range responses, bodyless statuses, and non-allowlisted content types. Transformation is additionally excluded automatically for credentialed traffic and validator-carrying responses — requests with `Authorization`/`Cookie` and responses with `Set-Cookie`, `ETag`, `Digest`, or `Content-Digest` are never compressed (compression-oracle protection, and validators stay application-owned). Controllers opt out per response with `response.disableCompression()`, and HEAD requests compute GET-equivalent representation headers without emitting a body. See [docs/http-server.md](docs/http-server.md#response-compression).
2892
+ Buffered string and `Uint8Array` responses are compressed with Brotli (`br`) or gzip by default whenever request negotiation and response eligibility allow — no opt-in is required. Disable compression globally with `httpServer.compression: false` or `httpServer.compression: {enabled: false}`, and tune it with `threshold`/`brotliQuality`/`gzipLevel` overrides. Negotiation honors `Accept-Encoding` q-values, wildcards, and identity semantics (empty `406` when no acceptable representation exists), combines repeated `Accept-Encoding` header fields in wire order, and advertises a framework-owned `Vary: Accept-Encoding` on every framework-selected representation (transformed, identity, `406`, and file) so caches key on the field. Streamed `sendFile` responses are never buffered or re-encoded: they are sent identity, so when the client forbids identity the server answers with the same empty `406` without opening or streaming the file. Transformation also skips already-encoded or `no-transform` responses, server-sent events, partial/range responses, bodyless statuses, and non-allowlisted content types. Transformation is additionally excluded automatically for credentialed traffic and validator-carrying responses — requests with `Authorization`/`Cookie` and responses with `Set-Cookie`, `ETag`, `Digest`, or `Content-Digest` are never compressed (compression-oracle protection, and validators stay application-owned). Controllers opt out per response with `response.disableCompression()`, and HEAD requests compute GET-equivalent representation headers without emitting a body. See [docs/http-server.md](docs/http-server.md#response-compression).
2893
2893
 
2894
2894
  # Authorization (CanCan-style)
2895
2895
 
@@ -8,7 +8,7 @@ import EventEmitter from "../../utils/event-emitter.js"
8
8
  import Logger from "../../logger.js"
9
9
  import Request from "./request.js"
10
10
  import RequestRunner from "./request-runner.js"
11
- import {applyResponseCompression} from "./response-compression.js"
11
+ import {addAcceptEncodingToVary, applyResponseCompression, negotiateContentEncoding} from "./response-compression.js"
12
12
  import WebsocketSession from "./websocket-session.js"
13
13
 
14
14
  /**
@@ -384,7 +384,15 @@ export default class VeoliciousHttpServerClient {
384
384
  }
385
385
 
386
386
  /**
387
- * Runs send response.
387
+ * Sends a finished response to the client. Owns the framework-owned
388
+ * `Vary: Accept-Encoding` dimension (emitted for every selected
389
+ * representation — transformed, identity, 406, and file — and for
390
+ * header-present and header-absent requests alike, so it is stable across
391
+ * requests on the same connection; never added when compression is disabled,
392
+ * the response is truly bodyless, or the application supplied a fixed
393
+ * `Content-Encoding`) and the file 406 rule (a sendFile response whose
394
+ * client forbids identity is answered with the empty 406, the file is never
395
+ * opened or streamed, and `onFinished` settles once as "completed").
388
396
  * @param {RequestRunner} requestRunner - Request runner.
389
397
  * @returns {Promise<void>} - Resolves when complete.
390
398
  */
@@ -436,12 +444,41 @@ export default class VeoliciousHttpServerClient {
436
444
  /** @type {string | Uint8Array | null} */
437
445
  let bodyToEmit = body
438
446
 
447
+ // The response representation can depend on the client's Accept-Encoding:
448
+ // the same request is answered with an identity body (or a file) when
449
+ // identity is acceptable and with an empty 406 when it is forbidden.
450
+ const compression = this.configuration.getHttpServerCompression()
451
+ const negotiated = compression.enabled ? negotiateContentEncoding(request.header("accept-encoding")) : undefined
452
+ // An application-supplied Content-Encoding is an application-owned
453
+ // representation contract, captured before the framework may add its own.
454
+ // A file carrying one is a fixed, application-owned representation: the
455
+ // framework neither negotiates it nor re-advertises it, so it is never a
456
+ // candidate for the identity-only 406.
457
+ const hasApplicationContentEncoding = response.getHeader("Content-Encoding").length > 0
458
+ // A file response only ever serves the identity representation: whenever
459
+ // the client forbids identity (including the not-acceptable case where no
460
+ // coding applies) and the file does not carry an application-supplied
461
+ // Content-Encoding, the file is rejected with the empty 406. A truly
462
+ // bodyless status selects no representation, so it is never rejected here.
463
+ const isFileNotAcceptable = hasFilePath && !!negotiated && ("notAcceptable" in negotiated || negotiated.identityAcceptable === false) && hasApplicationContentEncoding === false && !isBodylessStatus
464
+
439
465
  if (!isBodylessStatus) {
440
466
  let contentLength
441
467
 
442
468
  if (hasFilePath) {
443
- const stats = await fs.stat(filePath)
444
- contentLength = stats.size
469
+ if (isFileNotAcceptable) {
470
+ // The client forbids identity and files are only ever sent identity:
471
+ // answer with the same empty 406 every other representation path
472
+ // uses. The file is never opened or streamed; onFinished is settled
473
+ // below, after the committed 406 headers are emitted.
474
+ response.setStatus(406)
475
+ response.setBody("")
476
+ bodyToEmit = ""
477
+ contentLength = 0
478
+ } else {
479
+ const stats = await fs.stat(filePath)
480
+ contentLength = stats.size
481
+ }
445
482
  } else {
446
483
  // String bodies are UTF-8 framed, so the buffered bytes are the UTF-8 encoding;
447
484
  // Uint8Array bodies are already the exact wire bytes.
@@ -474,6 +511,18 @@ export default class VeoliciousHttpServerClient {
474
511
  response.setHeader("Content-Length", contentLength)
475
512
  }
476
513
 
514
+ // Framework-owned Vary dimension: whenever compression is enabled and a
515
+ // representation was selected, the response depends on Accept-Encoding,
516
+ // so caches must key on it. Applied identically for every outcome
517
+ // (transformed, identity, 406, file) and for header-present and
518
+ // header-absent requests alike, so the header is stable across requests on
519
+ // the same connection. A truly bodyless response selects no representation
520
+ // and carries no dimension; an application-supplied Content-Encoding keeps
521
+ // the representation contract application-owned and is never re-advertised.
522
+ if (negotiated && !isBodylessStatus && hasApplicationContentEncoding === false) {
523
+ addAcceptEncodingToVary(response)
524
+ }
525
+
477
526
  response.setHeader("Date", date.toUTCString())
478
527
  response.setHeader("Server", "Velocious")
479
528
 
@@ -492,8 +541,21 @@ export default class VeoliciousHttpServerClient {
492
541
  this.events.emit("output", headers)
493
542
  this.logger.debug(() => ["sendResponse headers emitted", {clientCount: this.clientCount, headersLength: headers.length}])
494
543
 
495
- if (isBodylessStatus) {
544
+ // A negotiated file 406 is committed above (status 406, empty body) and its
545
+ // headers were just emitted: settle onFinished now, so the callback runs
546
+ // after the response is committed — a slow or app-stopping callback cannot
547
+ // delay or block delivery of the already-emitted 406. The file is never
548
+ // opened, streamed, or reported (no file event), and the callback settles
549
+ // exactly once as "completed".
550
+ if (isFileNotAcceptable) {
551
+ this.logger.debug(() => ["sendResponse file body suppressed for 406", {clientCount: this.clientCount, filePath}])
552
+ await this.runFileOnFinished({filePath, onFinished: fileOnFinished, result: "completed"})
553
+ } else if (isBodylessStatus) {
496
554
  this.logger.debug(() => ["sendResponse body suppressed for no-body status", {clientCount: this.clientCount, statusCode: response.getStatusCode()}])
555
+ // A bodyless status (1xx/204/304) selects no representation, so no file
556
+ // body or framework Vary is emitted. The file-ownership path still settles
557
+ // onFinished exactly once as "completed" (nothing was aborted) — even when
558
+ // the client forbids identity — preserving the pre-change settlement.
497
559
  if (hasFilePath) await this.sendFileOutput(filePath, false, fileOnFinished)
498
560
  } else if (isHeadRequest) {
499
561
  this.logger.debug(() => ["sendResponse body suppressed for HEAD request", {clientCount: this.clientCount}])
@@ -8,6 +8,12 @@ import Logger from "../../../logger.js"
8
8
  import ParamsToObject from "../params-to-object.js"
9
9
  import querystring from "querystring"
10
10
 
11
+ /**
12
+ * Request header fields whose repeated wire fields combine into one value
13
+ * (RFC 9110 §5.3) before the server consumes them.
14
+ * @type {Set<string>} */
15
+ const COMBINING_HEADER_FIELDS = new Set(["accept-encoding"])
16
+
11
17
  /**
12
18
  * Runs truncate preview.
13
19
  * @param {string | undefined} input - Input string.
@@ -367,8 +373,16 @@ export default class RequestBuffer {
367
373
  */
368
374
  addHeader(header) {
369
375
  const formattedName = header.getFormattedName()
376
+ const existingHeader = this.headersByName[formattedName]
370
377
 
371
- this.headersByName[formattedName] = header
378
+ // RFC 9110 §5.3: a field may be repeated; its value is the concatenation of
379
+ // all field values separated by commas, in wire order. Only Accept-Encoding
380
+ // is consumed as a combined field by the server.
381
+ if (existingHeader && COMBINING_HEADER_FIELDS.has(formattedName)) {
382
+ existingHeader.value += `, ${header.getValue()}`
383
+ } else {
384
+ this.headersByName[formattedName] = header
385
+ }
372
386
 
373
387
  if (formattedName == "content-length") this.contentLength = parseInt(header.getValue())
374
388
  }
@@ -22,9 +22,9 @@ const COMPRESSIBLE_EXACT_MEDIA_TYPES = new Set([
22
22
 
23
23
  /**
24
24
  * RFC 9110 §12.4.2 qvalue grammar: `0` or `1` with at most three fractional
25
- * digits, and only zeros after `1`.
25
+ * digits (the boundary forms `0.` and `1.` are valid), and only zeros after `1`.
26
26
  * @type {RegExp} */
27
- const QVALUE_PATTERN = /^(?:0(?:\.\d{1,3})?|1(?:\.0{1,3})?)$/u
27
+ const QVALUE_PATTERN = /^(?:0(?:\.\d{0,3})?|1(?:\.0{0,3})?)$/u
28
28
 
29
29
  /**
30
30
  * Runs parse accept encoding.
@@ -118,7 +118,9 @@ export function isCompressibleContentType(contentType) {
118
118
  /**
119
119
  * Merges Accept-Encoding into the response Vary header case-insensitively and
120
120
  * without duplicates. An existing `Vary: *` already covers every request header
121
- * and is preserved as-is.
121
+ * and is preserved as-is. Called by the response sender for every
122
+ * framework-selected representation so the header is identical for every
123
+ * request on the same connection.
122
124
  * @param {import("./response.js").default} response - Response instance.
123
125
  * @returns {void} - No return value.
124
126
  */
@@ -160,7 +162,7 @@ export function addAcceptEncodingToVary(response) {
160
162
  * @param {import("../../configuration-types.js").NormalizedHttpCompressionConfiguration} args.compression - Normalized compression configuration.
161
163
  * @param {import("./request.js").default | import("./websocket-request.js").default} args.request - Request object.
162
164
  * @param {import("./response.js").default} args.response - Response instance.
163
- * @returns {Promise<{outcome: "identity"} | {outcome: "compressed", body: Buffer} | {outcome: "not-acceptable"}>} - Compression outcome.
165
+ * @returns {Promise<{outcome: "identity"} | {outcome: "compressed", body: Buffer} | {outcome: "not-acceptable"}>} - Compression outcome. The caller owns the Vary header and the file/406 representation decisions.
164
166
  */
165
167
  export async function applyResponseCompression({bodyBuffer, compression, request, response}) {
166
168
  if (!compression.enabled) return {outcome: "identity"}
@@ -203,10 +205,6 @@ export async function applyResponseCompression({bodyBuffer, compression, request
203
205
  return negotiated.identityAcceptable ? {outcome: "identity"} : {outcome: "not-acceptable"}
204
206
  }
205
207
 
206
- // The representation now depends on the request's Accept-Encoding, even when this
207
- // particular response ends up identity (missing header, higher-q identity, below threshold).
208
- addAcceptEncodingToVary(response)
209
-
210
208
  if (negotiated.encoding == "identity") return {outcome: "identity"}
211
209
 
212
210
  // Below the threshold the smaller identity representation is sent instead — but only
@@ -84,7 +84,15 @@ export default class VeoliciousHttpServerClient {
84
84
  _drainDoneRequests(): Promise<void>;
85
85
  sendDoneRequests(): Promise<void>;
86
86
  /**
87
- * Runs send response.
87
+ * Sends a finished response to the client. Owns the framework-owned
88
+ * `Vary: Accept-Encoding` dimension (emitted for every selected
89
+ * representation — transformed, identity, 406, and file — and for
90
+ * header-present and header-absent requests alike, so it is stable across
91
+ * requests on the same connection; never added when compression is disabled,
92
+ * the response is truly bodyless, or the application supplied a fixed
93
+ * `Content-Encoding`) and the file 406 rule (a sendFile response whose
94
+ * client forbids identity is answered with the empty 406, the file is never
95
+ * opened or streamed, and `onFinished` settles once as "completed").
88
96
  * @param {RequestRunner} requestRunner - Request runner.
89
97
  * @returns {Promise<void>} - Resolves when complete.
90
98
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/http-server/client/index.js"],"names":[],"mappings":"AAOA,OAAO,MAAM,MAAM,iBAAiB,CAAA;AACpC,OAAO,OAAO,MAAM,cAAc,CAAA;AAClC,OAAO,aAAa,MAAM,qBAAqB,CAAA;AAE/C,OAAO,gBAAgB,MAAM,wBAAwB,CAAA;AAerD,MAAM,CAAC,OAAO,OAAO,0BAA0B;IAwBtC,MAAM;IACN,WAAW;IACX,aAAa;IACb,aAAa;IAElB;;iCAE6B;IACxB,cAAc,EADT,aAAa,EAAE;IAGzB,sEAAsE;IACjE,oBAAoB,EADd,GAAG,CAAC,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IA4D7D,cAAc;IA2Kd,gBAAgB;IAxQvB,MAAM,6DAAqB;IAC3B,KAAK,SAAY;IAEjB;;yBAEqB;IACrB,wBAAwB,EADd,OAAO,CACe;IAEhC;;yBAEqB;IACrB,yBAAyB,EADf,OAAO,CACgB;IAEjC;;;;;;OAMG;IACH,YAAY,EAAC,WAAW,EAAE,aAAa,EAAE,aAAa,EAAC,EAJpD;QAAqB,WAAW,EAAxB,MAAM,CACd;QAAuD,aAAa,EAA5D,OAAO,wBAAwB,EAAE,OAAO,CAChD;QAAsB,aAAa,AAAnC,CACF,EADU,MAAM,CAChB;KACsD,EAetD;IAED;;;;OAIG;IACH,uBAAuB,CAAC,OAAO,EAHpB,MAGoB,GAFlB,IAAI,CAgBhB;IAED;;;;OAIG;IACH,uBAAuB,CAAC,OAAO,EAHpB,MAGoB,GAFlB,IAAI,CAgBhB;IAED;;;;OAIG;IACH,gBAAgB,CAAC,KAAK,EAHX,KAGW,GAFT,IAAI,CAehB;IAED,qBAAqB,aAkCpB;IAED;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAHD,MAGC,GAFC,IAAI,CAgEhB;IAED;;;;OAIG;IACH,mBAAmB,CAAC,OAAO,EAHhB,OAAO,cAAc,EAAE,OAGP,GAFd,OAAO,CAOnB;IAED;;;OAGG;IACH,mBAAmB,IAFN,IAAI,CAyEhB;IAED,WAAW,sBAOV;IAED;;;;;;OAMG;IACG,kBAAkB,IAFX,OAAO,CAAC,IAAI,CAAC,CAkBzB;IAEK,gBAAgB,kBA6BrB;IAED;;;;OAIG;IACG,YAAY,CAAC,aAAa,EAHrB,aAGqB,GAFnB,OAAO,CAAC,IAAI,CAAC,CA6HzB;IAED;;;;;;OAMG;IACG,cAAc,CAAC,QAAQ,EALlB,MAKkB,EAAE,QAAQ,EAJ5B,OAI4B,EAAE,UAAU,EAHxC,CAAC,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAGtB,GAFtC,OAAO,CAAC,IAAI,CAAC,CAuBzB;IAED;;;;;;;OAOG;IACG,iBAAiB,CAAC,EAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAC,EALnD;QAAqB,QAAQ,EAArB,MAAM,CACd;QAAiF,UAAU,EAAnF,CAAC,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAC1E;QAAsC,MAAM,EAApC,WAAW,GAAG,SAAS,CAC/B;KAEmD,GAFzC,OAAO,CAAC,IAAI,CAAC,CAoBzB;IAED;;;OAGG;IACG,yBAAyB,IAFlB,OAAO,CAAC,IAAI,CAAC,CAIzB;IAED;;;;OAIG;IACH,qBAAqB,CAAC,OAAO,EAHlB,OAAO,cAAc,EAAE,OAAO,GAAG,OAAO,wBAAwB,EAAE,OAGhD,GAFhB,OAAO,CAenB;CACF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/http-server/client/index.js"],"names":[],"mappings":"AAOA,OAAO,MAAM,MAAM,iBAAiB,CAAA;AACpC,OAAO,OAAO,MAAM,cAAc,CAAA;AAClC,OAAO,aAAa,MAAM,qBAAqB,CAAA;AAE/C,OAAO,gBAAgB,MAAM,wBAAwB,CAAA;AAerD,MAAM,CAAC,OAAO,OAAO,0BAA0B;IAwBtC,MAAM;IACN,WAAW;IACX,aAAa;IACb,aAAa;IAElB;;iCAE6B;IACxB,cAAc,EADT,aAAa,EAAE;IAGzB,sEAAsE;IACjE,oBAAoB,EADd,GAAG,CAAC,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IA4D7D,cAAc;IA2Kd,gBAAgB;IAxQvB,MAAM,6DAAqB;IAC3B,KAAK,SAAY;IAEjB;;yBAEqB;IACrB,wBAAwB,EADd,OAAO,CACe;IAEhC;;yBAEqB;IACrB,yBAAyB,EADf,OAAO,CACgB;IAEjC;;;;;;OAMG;IACH,YAAY,EAAC,WAAW,EAAE,aAAa,EAAE,aAAa,EAAC,EAJpD;QAAqB,WAAW,EAAxB,MAAM,CACd;QAAuD,aAAa,EAA5D,OAAO,wBAAwB,EAAE,OAAO,CAChD;QAAsB,aAAa,AAAnC,CACF,EADU,MAAM,CAChB;KACsD,EAetD;IAED;;;;OAIG;IACH,uBAAuB,CAAC,OAAO,EAHpB,MAGoB,GAFlB,IAAI,CAgBhB;IAED;;;;OAIG;IACH,uBAAuB,CAAC,OAAO,EAHpB,MAGoB,GAFlB,IAAI,CAgBhB;IAED;;;;OAIG;IACH,gBAAgB,CAAC,KAAK,EAHX,KAGW,GAFT,IAAI,CAehB;IAED,qBAAqB,aAkCpB;IAED;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAHD,MAGC,GAFC,IAAI,CAgEhB;IAED;;;;OAIG;IACH,mBAAmB,CAAC,OAAO,EAHhB,OAAO,cAAc,EAAE,OAGP,GAFd,OAAO,CAOnB;IAED;;;OAGG;IACH,mBAAmB,IAFN,IAAI,CAyEhB;IAED,WAAW,sBAOV;IAED;;;;;;OAMG;IACG,kBAAkB,IAFX,OAAO,CAAC,IAAI,CAAC,CAkBzB;IAEK,gBAAgB,kBA6BrB;IAED;;;;;;;;;;;;OAYG;IACG,YAAY,CAAC,aAAa,EAHrB,aAGqB,GAFnB,OAAO,CAAC,IAAI,CAAC,CAmLzB;IAED;;;;;;OAMG;IACG,cAAc,CAAC,QAAQ,EALlB,MAKkB,EAAE,QAAQ,EAJ5B,OAI4B,EAAE,UAAU,EAHxC,CAAC,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAGtB,GAFtC,OAAO,CAAC,IAAI,CAAC,CAuBzB;IAED;;;;;;;OAOG;IACG,iBAAiB,CAAC,EAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAC,EALnD;QAAqB,QAAQ,EAArB,MAAM,CACd;QAAiF,UAAU,EAAnF,CAAC,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAC1E;QAAsC,MAAM,EAApC,WAAW,GAAG,SAAS,CAC/B;KAEmD,GAFzC,OAAO,CAAC,IAAI,CAAC,CAoBzB;IAED;;;OAGG;IACG,yBAAyB,IAFlB,OAAO,CAAC,IAAI,CAAC,CAIzB;IAED;;;;OAIG;IACH,qBAAqB,CAAC,OAAO,EAHlB,OAAO,cAAc,EAAE,OAAO,GAAG,OAAO,wBAAwB,EAAE,OAGhD,GAFhB,OAAO,CAenB;CACF"}
@@ -7,7 +7,7 @@ import EventEmitter from "../../utils/event-emitter.js";
7
7
  import Logger from "../../logger.js";
8
8
  import Request from "./request.js";
9
9
  import RequestRunner from "./request-runner.js";
10
- import { applyResponseCompression } from "./response-compression.js";
10
+ import { addAcceptEncodingToVary, applyResponseCompression, negotiateContentEncoding } from "./response-compression.js";
11
11
  import WebsocketSession from "./websocket-session.js";
12
12
  /**
13
13
  * Runs bad request details.
@@ -335,7 +335,15 @@ export default class VeoliciousHttpServerClient {
335
335
  }
336
336
  }
337
337
  /**
338
- * Runs send response.
338
+ * Sends a finished response to the client. Owns the framework-owned
339
+ * `Vary: Accept-Encoding` dimension (emitted for every selected
340
+ * representation — transformed, identity, 406, and file — and for
341
+ * header-present and header-absent requests alike, so it is stable across
342
+ * requests on the same connection; never added when compression is disabled,
343
+ * the response is truly bodyless, or the application supplied a fixed
344
+ * `Content-Encoding`) and the file 406 rule (a sendFile response whose
345
+ * client forbids identity is answered with the empty 406, the file is never
346
+ * opened or streamed, and `onFinished` settles once as "completed").
339
347
  * @param {RequestRunner} requestRunner - Request runner.
340
348
  * @returns {Promise<void>} - Resolves when complete.
341
349
  */
@@ -381,11 +389,40 @@ export default class VeoliciousHttpServerClient {
381
389
  const isHeadRequest = request.httpMethod() == "HEAD";
382
390
  /** @type {string | Uint8Array | null} */
383
391
  let bodyToEmit = body;
392
+ // The response representation can depend on the client's Accept-Encoding:
393
+ // the same request is answered with an identity body (or a file) when
394
+ // identity is acceptable and with an empty 406 when it is forbidden.
395
+ const compression = this.configuration.getHttpServerCompression();
396
+ const negotiated = compression.enabled ? negotiateContentEncoding(request.header("accept-encoding")) : undefined;
397
+ // An application-supplied Content-Encoding is an application-owned
398
+ // representation contract, captured before the framework may add its own.
399
+ // A file carrying one is a fixed, application-owned representation: the
400
+ // framework neither negotiates it nor re-advertises it, so it is never a
401
+ // candidate for the identity-only 406.
402
+ const hasApplicationContentEncoding = response.getHeader("Content-Encoding").length > 0;
403
+ // A file response only ever serves the identity representation: whenever
404
+ // the client forbids identity (including the not-acceptable case where no
405
+ // coding applies) and the file does not carry an application-supplied
406
+ // Content-Encoding, the file is rejected with the empty 406. A truly
407
+ // bodyless status selects no representation, so it is never rejected here.
408
+ const isFileNotAcceptable = hasFilePath && !!negotiated && ("notAcceptable" in negotiated || negotiated.identityAcceptable === false) && hasApplicationContentEncoding === false && !isBodylessStatus;
384
409
  if (!isBodylessStatus) {
385
410
  let contentLength;
386
411
  if (hasFilePath) {
387
- const stats = await fs.stat(filePath);
388
- contentLength = stats.size;
412
+ if (isFileNotAcceptable) {
413
+ // The client forbids identity and files are only ever sent identity:
414
+ // answer with the same empty 406 every other representation path
415
+ // uses. The file is never opened or streamed; onFinished is settled
416
+ // below, after the committed 406 headers are emitted.
417
+ response.setStatus(406);
418
+ response.setBody("");
419
+ bodyToEmit = "";
420
+ contentLength = 0;
421
+ }
422
+ else {
423
+ const stats = await fs.stat(filePath);
424
+ contentLength = stats.size;
425
+ }
389
426
  }
390
427
  else {
391
428
  // String bodies are UTF-8 framed, so the buffered bytes are the UTF-8 encoding;
@@ -418,6 +455,17 @@ export default class VeoliciousHttpServerClient {
418
455
  response.removeHeader("Content-Length");
419
456
  response.setHeader("Content-Length", contentLength);
420
457
  }
458
+ // Framework-owned Vary dimension: whenever compression is enabled and a
459
+ // representation was selected, the response depends on Accept-Encoding,
460
+ // so caches must key on it. Applied identically for every outcome
461
+ // (transformed, identity, 406, file) and for header-present and
462
+ // header-absent requests alike, so the header is stable across requests on
463
+ // the same connection. A truly bodyless response selects no representation
464
+ // and carries no dimension; an application-supplied Content-Encoding keeps
465
+ // the representation contract application-owned and is never re-advertised.
466
+ if (negotiated && !isBodylessStatus && hasApplicationContentEncoding === false) {
467
+ addAcceptEncodingToVary(response);
468
+ }
421
469
  response.setHeader("Date", date.toUTCString());
422
470
  response.setHeader("Server", "Velocious");
423
471
  let headers = "";
@@ -430,8 +478,22 @@ export default class VeoliciousHttpServerClient {
430
478
  headers += "\r\n";
431
479
  this.events.emit("output", headers);
432
480
  this.logger.debug(() => ["sendResponse headers emitted", { clientCount: this.clientCount, headersLength: headers.length }]);
433
- if (isBodylessStatus) {
481
+ // A negotiated file 406 is committed above (status 406, empty body) and its
482
+ // headers were just emitted: settle onFinished now, so the callback runs
483
+ // after the response is committed — a slow or app-stopping callback cannot
484
+ // delay or block delivery of the already-emitted 406. The file is never
485
+ // opened, streamed, or reported (no file event), and the callback settles
486
+ // exactly once as "completed".
487
+ if (isFileNotAcceptable) {
488
+ this.logger.debug(() => ["sendResponse file body suppressed for 406", { clientCount: this.clientCount, filePath }]);
489
+ await this.runFileOnFinished({ filePath, onFinished: fileOnFinished, result: "completed" });
490
+ }
491
+ else if (isBodylessStatus) {
434
492
  this.logger.debug(() => ["sendResponse body suppressed for no-body status", { clientCount: this.clientCount, statusCode: response.getStatusCode() }]);
493
+ // A bodyless status (1xx/204/304) selects no representation, so no file
494
+ // body or framework Vary is emitted. The file-ownership path still settles
495
+ // onFinished exactly once as "completed" (nothing was aborted) — even when
496
+ // the client forbids identity — preserving the pre-change settlement.
435
497
  if (hasFilePath)
436
498
  await this.sendFileOutput(filePath, false, fileOnFinished);
437
499
  }
@@ -540,4 +602,4 @@ export default class VeoliciousHttpServerClient {
540
602
  function isNoBodyStatusCode(statusCode) {
541
603
  return (statusCode >= 100 && statusCode < 200) || statusCode === 204 || statusCode === 304;
542
604
  }
543
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvaHR0cC1zZXJ2ZXIvY2xpZW50L2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLE1BQU0sTUFBTSxRQUFRLENBQUE7QUFDM0IsT0FBTyxFQUFFLE1BQU0sa0JBQWtCLENBQUE7QUFDakMsT0FBTyxFQUFDLElBQUksRUFBQyxNQUFNLFdBQVcsQ0FBQTtBQUM5QixPQUFPLEVBQUMsV0FBVyxFQUFDLE1BQU0sU0FBUyxDQUFBO0FBQ25DLE9BQU8sWUFBWSxNQUFNLDhCQUE4QixDQUFBO0FBQ3ZELE9BQU8sTUFBTSxNQUFNLGlCQUFpQixDQUFBO0FBQ3BDLE9BQU8sT0FBTyxNQUFNLGNBQWMsQ0FBQTtBQUNsQyxPQUFPLGFBQWEsTUFBTSxxQkFBcUIsQ0FBQTtBQUMvQyxPQUFPLEVBQUMsd0JBQXdCLEVBQUMsTUFBTSwyQkFBMkIsQ0FBQTtBQUNsRSxPQUFPLGdCQUFnQixNQUFNLHdCQUF3QixDQUFBO0FBRXJEOzs7O0dBSUc7QUFDSCxTQUFTLGlCQUFpQixDQUFDLEtBQUs7SUFDOUIsT0FBTztRQUNMLFVBQVUsRUFBRSxLQUFLLENBQUMsSUFBSTtRQUN0QixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87UUFDdEIsZ0JBQWdCLEVBQUUsS0FBSyxDQUFDLGdCQUFnQjtLQUN6QyxDQUFBO0FBQ0gsQ0FBQztBQUVELE1BQU0sQ0FBQyxPQUFPLE9BQU8sMEJBQTBCO0lBQzdDLE1BQU0sR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFBO0lBQzNCLEtBQUssR0FBRyxTQUFTLENBQUE7SUFFakI7O3lCQUVxQjtJQUNyQix3QkFBd0IsR0FBRyxLQUFLLENBQUE7SUFFaEM7O3lCQUVxQjtJQUNyQix5QkFBeUIsR0FBRyxLQUFLLENBQUE7SUFFakM7Ozs7OztPQU1HO0lBQ0gsWUFBWSxFQUFDLFdBQVcsRUFBRSxhQUFhLEVBQUUsYUFBYSxFQUFD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QUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxFQUFFLFdBQVcsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFBO1FBQzVFLE1BQU0sZ0JBQWdCLEdBQUcsZ0JBQWdCO1lBQ3ZDLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDO1lBQzFFLENBQUMsQ0FBQyxFQUFFLENBQUE7UUFFTixJQUFJLFdBQVcsSUFBSSxXQUFXO1lBQUUsT0FBTyxLQUFLLENBQUE7UUFDNUMsSUFBSSxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO1lBQUUsT0FBTyxJQUFJLENBQUE7UUFFbkQsSUFBSSxXQUFXLElBQUksS0FBSyxJQUFJLGdCQUFnQixJQUFJLFlBQVk7WUFBRSxPQUFPLElBQUksQ0FBQTtRQUV6RSxPQUFPLEtBQUssQ0FBQTtJQUNkLENBQUM7Q0FDRjtBQUVEOzs7Ozs7R0FNRztBQUNILFNBQVMsa0JBQWtCLENBQUMsVUFBVTtJQUNwQyxPQUFPLENBQUMsVUFBVSxJQUFJLEdBQUcsSUFBSSxVQUFVLEdBQUcsR0FBRyxDQUFDLElBQUksVUFBVSxLQUFLLEdBQUcsSUFBSSxVQUFVLEtBQUssR0FBRyxDQUFBO0FBQzVGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IGNyeXB0byBmcm9tIFwiY3J5cHRvXCJcbmltcG9ydCBmcyBmcm9tIFwibm9kZTpmcy9wcm9taXNlc1wiXG5pbXBvcnQge2RpZ2d9IGZyb20gXCJkaWdnZXJpemVcIlxuaW1wb3J0IHtlbnN1cmVFcnJvcn0gZnJvbSBcInR5cGFuaWNcIlxuaW1wb3J0IEV2ZW50RW1pdHRlciBmcm9tIFwiLi4vLi4vdXRpbHMvZXZlbnQtZW1pdHRlci5qc1wiXG5pbXBvcnQgTG9nZ2VyIGZyb20gXCIuLi8uLi9sb2dnZXIuanNcIlxuaW1wb3J0IFJlcXVlc3QgZnJvbSBcIi4vcmVxdWVzdC5qc1wiXG5pbXBvcnQgUmVxdWVzdFJ1bm5lciBmcm9tIFwiLi9yZXF1ZXN0LXJ1bm5lci5qc1wiXG5pbXBvcnQge2FwcGx5UmVzcG9uc2VDb21wcmVzc2lvbn0gZnJvbSBcIi4vcmVzcG9uc2UtY29tcHJlc3Npb24uanNcIlxuaW1wb3J0IFdlYnNvY2tldFNlc3Npb24gZnJvbSBcIi4vd2Vic29ja2V0LXNlc3Npb24uanNcIlxuXG4vKipcbiAqIFJ1bnMgYmFkIHJlcXVlc3QgZGV0YWlscy5cbiAqIEBwYXJhbSB7RXJyb3IgJiB7dmVsb2Npb3VzQ29udGV4dD86IFJlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn19IGVycm9yIC0gRXJyb3IgaW5zdGFuY2UuXG4gKiBAcmV0dXJucyB7UmVjb3JkPHN0cmluZywgUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+fSAtIFNhZmUgYmFkLXJlcXVlc3QgZGV0YWlscyBmb3IgbG9ncy5cbiAqL1xuZnVuY3Rpb24gYmFkUmVxdWVzdERldGFpbHMoZXJyb3IpIHtcbiAgcmV0dXJuIHtcbiAgICBlcnJvckNsYXNzOiBlcnJvci5uYW1lLFxuICAgIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2UsXG4gICAgdmVsb2Npb3VzQ29udGV4dDogZXJyb3IudmVsb2Npb3VzQ29udGV4dFxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFZlb2xpY2lvdXNIdHRwU2VydmVyQ2xpZW50IHtcbiAgZXZlbnRzID0gbmV3IEV2ZW50RW1pdHRlcigpXG4gIHN0YXRlID0gXCJpbml0aWFsXCJcblxuICAvKipcbiAgICogV2hldGhlciBhIGRvbmUtcmVxdWVzdHMgZHJhaW4gaXMgY3VycmVudGx5IHNlbmRpbmcgcmVzcG9uc2VzIGZvciB0aGlzIGNsaWVudC5cbiAgICogQHR5cGUge2Jvb2xlYW59ICovXG4gIF9kb25lUmVxdWVzdHNEcmFpbkFjdGl2ZSA9IGZhbHNlXG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgYW5vdGhlciBkcmFpbiB3YXMgcmVxdWVzdGVkIHdoaWxlIG9uZSB3YXMgYWxyZWFkeSBhY3RpdmUuXG4gICAqIEB0eXBlIHtib29sZWFufSAqL1xuICBfZG9uZVJlcXVlc3RzRHJhaW5QZW5kaW5nID0gZmFsc2VcblxuICAvKipcbiAgICogUnVucyBjb25zdHJ1Y3Rvci5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zIG9iamVjdC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGFyZ3MuY2xpZW50Q291bnQgLSBDbGllbnQgY291bnQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0fSBhcmdzLmNvbmZpZ3VyYXRpb24gLSBDb25maWd1cmF0aW9uIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2FyZ3MucmVtb3RlQWRkcmVzc10gLSBSZW1vdGUgYWRkcmVzcy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHtjbGllbnRDb3VudCwgY29uZmlndXJhdGlvbiwgcmVtb3RlQWRkcmVzc30pIHtcbiAgICBpZiAoIWNvbmZpZ3VyYXRpb24pIHRocm93IG5ldyBFcnJvcihcIk5vIGNvbmZpZ3VyYXRpb24gZ2l2ZW5cIilcblxuICAgIHRoaXMubG9nZ2VyID0gbmV3IExvZ2dlcih0aGlzKVxuICAgIHRoaXMuY2xpZW50Q291bnQgPSBjbGllbnRDb3VudFxuICAgIHRoaXMuY29uZmlndXJhdGlvbiA9IGNvbmZpZ3VyYXRpb25cbiAgICB0aGlzLnJlbW90ZUFkZHJlc3MgPSByZW1vdGVBZGRyZXNzXG5cbiAgICAvKipcbiAgICAgKiBOYXJyb3dzIHRoZSBydW50aW1lIHZhbHVlIHRvIHRoZSBkb2N1bWVudGVkIHR5cGUuXG4gICAgICogQHR5cGUge1JlcXVlc3RSdW5uZXJbXX0gKi9cbiAgICB0aGlzLnJlcXVlc3RSdW5uZXJzID0gW11cblxuICAgIC8qKiBAdHlwZSB7U2V0PChyZXN1bHQ6IFwiY29tcGxldGVkXCIgfCBcImFib3J0ZWRcIikgPT4gUHJvbWlzZTx2b2lkPj59ICovXG4gICAgdGhpcy5wZW5kaW5nRmlsZVJlc3BvbnNlcyA9IG5ldyBTZXQoKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgc2VuZCBiYWQgdXBncmFkZSByZXNwb25zZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBNZXNzYWdlIHRleHQuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIF9zZW5kQmFkVXBncmFkZVJlc3BvbnNlKG1lc3NhZ2UpIHtcbiAgICBjb25zdCBodHRwVmVyc2lvbiA9IHRoaXMuY3VycmVudFJlcXVlc3Q/Lmh0dHBWZXJzaW9uKCkgfHwgXCIxLjFcIlxuICAgIGNvbnN0IGJvZHkgPSBgJHttZXNzYWdlfVxcbmBcbiAgICBjb25zdCBoZWFkZXJzID0gW1xuICAgICAgYEhUVFAvJHtodHRwVmVyc2lvbn0gNDAwIEJhZCBSZXF1ZXN0YCxcbiAgICAgIFwiQ29ubmVjdGlvbjogQ2xvc2VcIixcbiAgICAgIFwiQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PVVURi04XCIsXG4gICAgICBgQ29udGVudC1MZW5ndGg6ICR7QnVmZmVyLmJ5dGVMZW5ndGgoYm9keSwgXCJ1dGY4XCIpfWAsXG4gICAgICBcIlwiLFxuICAgICAgYm9keVxuICAgIF0uam9pbihcIlxcclxcblwiKVxuXG4gICAgdGhpcy5ldmVudHMuZW1pdChcIm91dHB1dFwiLCBoZWFkZXJzKVxuICAgIHRoaXMuZXZlbnRzLmVtaXQoXCJjbG9zZVwiKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgc2VuZCBiYWQgcmVxdWVzdCByZXNwb25zZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBSZXNwb25zZSBtZXNzYWdlLlxuICAgKiBAcmV0dXJucyB7dm9pZH0gLSBObyByZXR1cm4gdmFsdWUuXG4gICAqL1xuICBfc2VuZEJhZFJlcXVlc3RSZXNwb25zZShtZXNzYWdlKSB7XG4gICAgY29uc3QgaHR0cFZlcnNpb24gPSB0aGlzLmN1cnJlbnRSZXF1ZXN0Py5odHRwVmVyc2lvbigpIHx8IFwiMS4xXCJcbiAgICBjb25zdCBib2R5ID0gYCR7bWVzc2FnZX1cXG5gXG4gICAgY29uc3QgaGVhZGVycyA9IFtcbiAgICAgIGBIVFRQLyR7aHR0cFZlcnNpb259IDQwMCBCYWQgUmVxdWVzdGAsXG4gICAgICBcIkNvbm5lY3Rpb246IENsb3NlXCIsXG4gICAgICBcIkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD1VVEYtOFwiLFxuICAgICAgYENvbnRlbnQtTGVuZ3RoOiAke0J1ZmZlci5ieXRlTGVuZ3RoKGJvZHksIFwidXRmOFwiKX1gLFxuICAgICAgXCJcIixcbiAgICAgIGJvZHlcbiAgICBdLmpvaW4oXCJcXHJcXG5cIilcblxuICAgIHRoaXMuZXZlbnRzLmVtaXQoXCJvdXRwdXRcIiwgaGVhZGVycylcbiAgICB0aGlzLmV2ZW50cy5lbWl0KFwiY2xvc2VcIilcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGhhbmRsZSBiYWQgcmVxdWVzdC5cbiAgICogQHBhcmFtIHtFcnJvcn0gZXJyb3IgLSBFcnJvciBpbnN0YW5jZS5cbiAgICogQHJldHVybnMge3ZvaWR9IC0gTm8gcmV0dXJuIHZhbHVlLlxuICAgKi9cbiAgaGFuZGxlQmFkUmVxdWVzdChlcnJvcikge1xuICAgIHRoaXMubG9nZ2VyLndhcm4oKCkgPT4gW1wiRmFpbGVkIHRvIHBhcnNlIEhUVFAgcmVxdWVzdFwiLCBiYWRSZXF1ZXN0RGV0YWlscygvKiogQHR5cGUge0Vycm9yICYge3ZlbG9jaW91c0NvbnRleHQ/OiBSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59fSAqLyAoZXJyb3IpKV0pXG5cbiAgICBpZiAodGhpcy5jdXJyZW50UmVxdWVzdCAmJiBcImdldFJlcXVlc3RQYXJzZXJcIiBpbiB0aGlzLmN1cnJlbnRSZXF1ZXN0KSB7XG4gICAgICBjb25zdCBodHRwUmVxdWVzdCA9IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9yZXF1ZXN0LmpzXCIpLmRlZmF1bHR9ICovICh0aGlzLmN1cnJlbnRSZXF1ZXN0KVxuXG4gICAgICBodHRwUmVxdWVzdC5nZXRSZXF1ZXN0UGFyc2VyKCkuZGVzdHJveSgpXG4gICAgfVxuXG4gICAgdGhpcy5jdXJyZW50UmVxdWVzdCA9IHVuZGVmaW5lZFxuICAgIHRoaXMuc3RhdGUgPSBcImluaXRpYWxcIlxuXG4gICAgdGhpcy5fc2VuZEJhZFJlcXVlc3RSZXNwb25zZShcIkJhZCBSZXF1ZXN0XCIpXG4gIH1cblxuICBleGVjdXRlQ3VycmVudFJlcXVlc3QgPSAoKSA9PiB7XG4gICAgdGhpcy5sb2dnZXIuZGVidWcoXCJleGVjdXRlQ3VycmVudFJlcXVlc3RcIilcblxuICAgIGNvbnN0IGN1cnJlbnRSZXF1ZXN0ID0gdGhpcy5jdXJyZW50UmVxdWVzdFxuXG4gICAgaWYgKCFjdXJyZW50UmVxdWVzdCkgdGhyb3cgbmV3IEVycm9yKFwiTm8gY3VycmVudCByZXF1ZXN0XCIpXG4gICAgY29uc3QgcmVkYWN0b3IgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0TG9nUmVkYWN0b3IoKVxuICAgIGNvbnN0IHNlbnNpdGl2ZVZhbHVlcyA9IHJlZGFjdG9yLnJlcXVlc3RTZW5zaXRpdmVWYWx1ZXMoY3VycmVudFJlcXVlc3QpXG5cbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZygoKSA9PiBbXCJleGVjdXRlQ3VycmVudFJlcXVlc3QgcmVxdWVzdFwiLCB7XG4gICAgICBjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudCxcbiAgICAgIGh0dHBNZXRob2Q6IGN1cnJlbnRSZXF1ZXN0Lmh0dHBNZXRob2QoKSxcbiAgICAgIGh0dHBWZXJzaW9uOiBjdXJyZW50UmVxdWVzdC5odHRwVmVyc2lvbigpLFxuICAgICAgcGF0aDogcmVkYWN0b3IucmVkYWN0UGF0aChjdXJyZW50UmVxdWVzdC5wYXRoKCksIHNlbnNpdGl2ZVZhbHVlcyksXG4gICAgICBxdWV1ZUxlbmd0aDogdGhpcy5yZXF1ZXN0UnVubmVycy5sZW5ndGhcbiAgICB9XSlcblxuICAgIGlmICh0aGlzLl9pc1dlYnNvY2tldFVwZ3JhZGUoY3VycmVudFJlcXVlc3QpKSB7XG4gICAgICB0aGlzLl91cGdyYWRlVG9XZWJzb2NrZXQoKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gV2UgYXJlIGRvbmUgcGFyc2luZyB0aGUgZ2l2ZW4gcmVxdWVzdCBhbmQgY2FuIHRoZW9yZXRpY2FsbHkgc3RhcnQgcGFyc2luZyBhIG5ldyBvbmUsIGJlZm9yZSB0aGUgY3VycmVudCByZXF1ZXN0IGlzIGRvbmUgLSBzbyByZXNldCB0aGUgc3RhdGUuXG4gICAgdGhpcy5zdGF0ZSA9IFwiaW5pdGlhbFwiXG5cbiAgICBjb25zdCByZXF1ZXN0UnVubmVyID0gbmV3IFJlcXVlc3RSdW5uZXIoe1xuICAgICAgY29uZmlndXJhdGlvbjogdGhpcy5jb25maWd1cmF0aW9uLFxuICAgICAgcmVxdWVzdDogY3VycmVudFJlcXVlc3RcbiAgICB9KVxuXG4gICAgdGhpcy5yZXF1ZXN0UnVubmVycy5wdXNoKHJlcXVlc3RSdW5uZXIpXG5cbiAgICByZXF1ZXN0UnVubmVyLmV2ZW50cy5vbihcImRvbmVcIiwgdGhpcy5yZXF1ZXN0RG9uZSlcbiAgICByZXF1ZXN0UnVubmVyLnJ1bigpXG4gIH1cblxuICAvKipcbiAgICogUnVucyBvbiB3cml0ZS5cbiAgICogQHBhcmFtIHtCdWZmZXJ9IGRhdGEgLSBEYXRhIHBheWxvYWQuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIG9uV3JpdGUoZGF0YSkge1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKCgpID0+IFtcIm9uV3JpdGUgc3RhcnRcIiwge1xuICAgICAgY2xpZW50Q291bnQ6IHRoaXMuY2xpZW50Q291bnQsXG4gICAgICBsZW5ndGg6IGRhdGEubGVuZ3RoLFxuICAgICAgc3RhdGU6IHRoaXMuc3RhdGUsXG4gICAgfV0pXG5cbiAgICBpZiAodGhpcy53ZWJzb2NrZXRTZXNzaW9uKSB7XG4gICAgICB0aGlzLndlYnNvY2tldFNlc3Npb24ub25EYXRhKGRhdGEpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgLyoqXG4gICAgICAgKiBSZW1haW5pbmcuXG4gICAgICAgKiBAdHlwZSB7QnVmZmVyIHwgdW5kZWZpbmVkfSAqL1xuICAgICAgbGV0IHJlbWFpbmluZyA9IGRhdGFcblxuICAgICAgd2hpbGUgKHJlbWFpbmluZykge1xuICAgICAgICBpZiAocmVtYWluaW5nLmxlbmd0aCA8PSAwKSBicmVha1xuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlID09IFwiaW5pdGlhbFwiKSB7XG4gICAgICAgICAgY29uc3QgcmVtYWluaW5nTGVuZ3RoID0gcmVtYWluaW5nLmxlbmd0aFxuXG4gICAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoKCkgPT4gW1wib25Xcml0ZSBjcmVhdGluZyByZXF1ZXN0IHBhcnNlclwiLCB7Y2xpZW50Q291bnQ6IHRoaXMuY2xpZW50Q291bnQsIHJlbWFpbmluZ0xlbmd0aH1dKVxuICAgICAgICAgIHRoaXMuY3VycmVudFJlcXVlc3QgPSBuZXcgUmVxdWVzdCh7Y2xpZW50OiB0aGlzLCBjb25maWd1cmF0aW9uOiB0aGlzLmNvbmZpZ3VyYXRpb259KVxuICAgICAgICAgIHRoaXMuY3VycmVudFJlcXVlc3QucmVxdWVzdFBhcnNlci5ldmVudHMub24oXCJkb25lXCIsIHRoaXMuZXhlY3V0ZUN1cnJlbnRSZXF1ZXN0KVxuICAgICAgICAgIHRoaXMuc3RhdGUgPSBcInJlcXVlc3RTdGFydGVkXCJcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlICE9IFwicmVxdWVzdFN0YXJ0ZWRcIikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBzdGF0ZSBmb3IgY2xpZW50OiAke3RoaXMuc3RhdGV9YClcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5jdXJyZW50UmVxdWVzdCkgdGhyb3cgbmV3IEVycm9yKFwiTm8gY3VycmVudCByZXF1ZXN0XCIpXG5cbiAgICAgICAgcmVtYWluaW5nID0gdGhpcy5jdXJyZW50UmVxdWVzdC5mZWVkKHJlbWFpbmluZylcbiAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoKCkgPT4gW1wib25Xcml0ZSBmZWQgcGFyc2VyXCIsIHtcbiAgICAgICAgICBjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudCxcbiAgICAgICAgICBoYXNSZW1haW5pbmc6IEJvb2xlYW4ocmVtYWluaW5nPy5sZW5ndGgpLFxuICAgICAgICAgIHJlbWFpbmluZ0xlbmd0aDogcmVtYWluaW5nPy5sZW5ndGggfHwgMCxcbiAgICAgICAgICBwYXJzZXJDb21wbGV0ZWQ6IHRoaXMuY3VycmVudFJlcXVlc3Q/LmdldFJlcXVlc3RQYXJzZXIoKS5oYXNDb21wbGV0ZWRcbiAgICAgICAgfV0pXG5cbiAgICAgICAgaWYgKHJlbWFpbmluZyAmJiByZW1haW5pbmcubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGNvbnN0IHJlcXVlc3RQYXJzZXIgPSB0aGlzLmN1cnJlbnRSZXF1ZXN0LmdldFJlcXVlc3RQYXJzZXIoKVxuXG4gICAgICAgICAgaWYgKCFyZXF1ZXN0UGFyc2VyLmhhc0NvbXBsZXRlZCkge1xuICAgICAgICAgICAgY29uc3QgcmVtYWluaW5nTGVuZ3RoID0gcmVtYWluaW5nLmxlbmd0aFxuXG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZygoKSA9PiBbXCJvbldyaXRlIHdhaXRpbmcgZm9yIG1vcmUgZGF0YVwiLCB7Y2xpZW50Q291bnQ6IHRoaXMuY2xpZW50Q291bnQsIHJlbWFpbmluZ0xlbmd0aH1dKVxuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLnN0YXRlID0gXCJpbml0aWFsXCJcbiAgICAgICAgICBjb25zdCByZW1haW5pbmdMZW5ndGggPSByZW1haW5pbmcubGVuZ3RoXG5cbiAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZygoKSA9PiBbXCJvbldyaXRlIHBhcnNlciBjb21wbGV0ZWQgd2l0aCByZW1haW5pbmcgYnl0ZXNcIiwge2NsaWVudENvdW50OiB0aGlzLmNsaWVudENvdW50LCByZW1haW5pbmdMZW5ndGh9XSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhpcy5sb2dnZXIuZGVidWcoKCkgPT4gW1wib25Xcml0ZSBlbmRcIiwge2NsaWVudENvdW50OiB0aGlzLmNsaWVudENvdW50LCBzdGF0ZTogdGhpcy5zdGF0ZSwgcXVldWVMZW5ndGg6IHRoaXMucmVxdWVzdFJ1bm5lcnMubGVuZ3RofV0pXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMuaGFuZGxlQmFkUmVxdWVzdChlbnN1cmVFcnJvcihlcnJvcikpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgaXMgd2Vic29ja2V0IHVwZ3JhZGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9yZXF1ZXN0LmpzXCIpLmRlZmF1bHR9IHJlcXVlc3QgLSBSZXF1ZXN0IG9iamVjdC5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gV2hldGhlciB3ZWJzb2NrZXQgdXBncmFkZS5cbiAgICovXG4gIF9pc1dlYnNvY2tldFVwZ3JhZGUocmVxdWVzdCkge1xuICAgIGNvbnN0IHVwZ3JhZGVIZWFkZXIgPSByZXF1ZXN0LmhlYWRlcihcInVwZ3JhZGVcIik/LnRvTG93ZXJDYXNlKClcbiAgICBjb25zdCBjb25uZWN0aW9uSGVhZGVyID0gcmVxdWVzdC5oZWFkZXIoXCJjb25uZWN0aW9uXCIpPy50b0xvd2VyQ2FzZSgpXG5cbiAgICByZXR1cm4gQm9vbGVhbih1cGdyYWRlSGVhZGVyID09IFwid2Vic29ja2V0XCIgJiYgY29ubmVjdGlvbkhlYWRlcj8uaW5jbHVkZXMoXCJ1cGdyYWRlXCIpKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgdXBncmFkZSB0byB3ZWJzb2NrZXQuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIF91cGdyYWRlVG9XZWJzb2NrZXQoKSB7XG4gICAgaWYgKCF0aGlzLmN1cnJlbnRSZXF1ZXN0KSB0aHJvdyBuZXcgRXJyb3IoXCJObyBjdXJyZW50IHJlcXVlc3RcIilcblxuICAgIGNvbnN0IHNlY1dlYnNvY2tldEtleSA9IHRoaXMuY3VycmVudFJlcXVlc3QuaGVhZGVyKFwic2VjLXdlYnNvY2tldC1rZXlcIilcblxuICAgIGlmICghc2VjV2Vic29ja2V0S2V5KSB7XG4gICAgICB0aGlzLl9zZW5kQmFkVXBncmFkZVJlc3BvbnNlKFwiTWlzc2luZyBTZWMtV2ViU29ja2V0LUtleSBoZWFkZXJcIilcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNvbnN0IHdlYnNvY2tldEFjY2VwdEtleSA9IGNyeXB0by5jcmVhdGVIYXNoKFwic2hhMVwiKVxuICAgICAgLnVwZGF0ZShgJHtzZWNXZWJzb2NrZXRLZXl9MjU4RUFGQTUtRTkxNC00N0RBLTk1Q0EtQzVBQjBEQzg1QjExYCwgXCJiaW5hcnlcIilcbiAgICAgIC5kaWdlc3QoXCJiYXNlNjRcIilcbiAgICBjb25zdCBodHRwVmVyc2lvbiA9IHRoaXMuY3VycmVudFJlcXVlc3QuaHR0cFZlcnNpb24oKSB8fCBcIjEuMVwiXG4gICAgY29uc3QgcmVzcG9uc2VMaW5lcyA9IFtcbiAgICAgIGBIVFRQLyR7aHR0cFZlcnNpb259IDEwMSBTd2l0Y2hpbmcgUHJvdG9jb2xzYCxcbiAgICAgIFwiVXBncmFkZTogd2Vic29ja2V0XCIsXG4gICAgICBcIkNvbm5lY3Rpb246IFVwZ3JhZGVcIixcbiAgICAgIGBTZWMtV2ViU29ja2V0LUFjY2VwdDogJHt3ZWJzb2NrZXRBY2NlcHRLZXl9YCxcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiXG4gICAgXVxuICAgIGNvbnN0IHJlc3BvbnNlID0gcmVzcG9uc2VMaW5lcy5qb2luKFwiXFxyXFxuXCIpXG5cbiAgICBjb25zdCBtZXNzYWdlSGFuZGxlclJlc29sdmVyID0gdGhpcy5jb25maWd1cmF0aW9uLmdldFdlYnNvY2tldE1lc3NhZ2VIYW5kbGVyUmVzb2x2ZXI/LigpXG4gICAgbGV0IG1lc3NhZ2VIYW5kbGVyXG4gICAgbGV0IG1lc3NhZ2VIYW5kbGVyUHJvbWlzZVxuXG4gICAgaWYgKG1lc3NhZ2VIYW5kbGVyUmVzb2x2ZXIpIHtcbiAgICAgIGNvbnN0IHJlc29sdmVkSGFuZGxlciA9IG1lc3NhZ2VIYW5kbGVyUmVzb2x2ZXIoe1xuICAgICAgICBjbGllbnQ6IHRoaXMsXG4gICAgICAgIGNvbmZpZ3VyYXRpb246IHRoaXMuY29uZmlndXJhdGlvbixcbiAgICAgICAgcmVxdWVzdDogdGhpcy5jdXJyZW50UmVxdWVzdFxuICAgICAgfSlcblxuICAgICAgY29uc3QgcmVzb2x2ZWRUaGVuYWJsZSA9IC8qKiBAdHlwZSB7e3RoZW4/OiAoLi4uYXJnczogQXJyYXk8UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+KSA9PiBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPn19ICovIChyZXNvbHZlZEhhbmRsZXIpXG5cbiAgICAgIGlmIChyZXNvbHZlZFRoZW5hYmxlPy50aGVuKSB7XG4gICAgICAgIG1lc3NhZ2VIYW5kbGVyUHJvbWlzZSA9IC8qKiBAdHlwZSB7UHJvbWlzZTxpbXBvcnQoXCIuLi8uLi9jb25maWd1cmF0aW9uLXR5cGVzLmpzXCIpLldlYnNvY2tldE1lc3NhZ2VIYW5kbGVyIHwgdm9pZD59ICovIChyZXNvbHZlZEhhbmRsZXIpXG4gICAgICB9IGVsc2UgaWYgKHJlc29sdmVkSGFuZGxlcikge1xuICAgICAgICBtZXNzYWdlSGFuZGxlciA9IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5XZWJzb2NrZXRNZXNzYWdlSGFuZGxlcn0gKi8gKHJlc29sdmVkSGFuZGxlcilcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLndlYnNvY2tldFNlc3Npb24gPSBuZXcgV2Vic29ja2V0U2Vzc2lvbih7XG4gICAgICBjbGllbnQ6IHRoaXMsXG4gICAgICBjb25maWd1cmF0aW9uOiB0aGlzLmNvbmZpZ3VyYXRpb24sXG4gICAgICB1cGdyYWRlUmVxdWVzdDogdGhpcy5jdXJyZW50UmVxdWVzdCxcbiAgICAgIG1lc3NhZ2VIYW5kbGVyOiBtZXNzYWdlSGFuZGxlcixcbiAgICAgIG1lc3NhZ2VIYW5kbGVyUHJvbWlzZTogbWVzc2FnZUhhbmRsZXJQcm9taXNlXG4gICAgfSlcbiAgICB0aGlzLndlYnNvY2tldFNlc3Npb24uZXZlbnRzLm9uKFwiY2xvc2VcIiwgKCkgPT4ge1xuICAgICAgLy8gUGF1c2VkIHNlc3Npb25zIHN1cnZpdmUgdGhlIHNvY2tldCBjbG9zZTsgZG9uJ3QgZGVzdHJveSgpLlxuICAgICAgLy8gVGhlIGdyYWNlLWV4cGlyeSBwYXRoIChfZmluYWxpemVHcmFjZUV4cGlyeSkgd2lsbCBkZXN0cm95XG4gICAgICAvLyB0aGVtIHBlcm1hbmVudGx5IGlmIHJlc3VtZSBkb2Vzbid0IGhhcHBlbiBpbiB0aW1lLlxuICAgICAgaWYgKCF0aGlzLndlYnNvY2tldFNlc3Npb24/LmlzUGF1c2VkKCkpIHtcbiAgICAgICAgdGhpcy53ZWJzb2NrZXRTZXNzaW9uPy5kZXN0cm95KClcbiAgICAgIH1cbiAgICAgIHRoaXMud2Vic29ja2V0U2Vzc2lvbiA9IHVuZGVmaW5lZFxuICAgICAgdGhpcy5ldmVudHMuZW1pdChcImNsb3NlXCIpXG4gICAgfSlcbiAgICB0aGlzLndlYnNvY2tldFNlc3Npb24uZXZlbnRzLm9uKFwib3duZXJzaGlwQ2xhaW1lZFwiLCAoe3Nlc3Npb25JZH0pID0+IHtcbiAgICAgIHRoaXMuZXZlbnRzLmVtaXQoXCJ3ZWJzb2NrZXRTZXNzaW9uT3duZWRcIiwge3Nlc3Npb25JZH0pXG4gICAgfSlcbiAgICB0aGlzLndlYnNvY2tldFNlc3Npb24uZXZlbnRzLm9uKFwib3duZXJzaGlwUmVsZWFzZWRcIiwgKHtzZXNzaW9uSWR9KSA9PiB7XG4gICAgICB0aGlzLmV2ZW50cy5lbWl0KFwid2Vic29ja2V0U2Vzc2lvblJlbGVhc2VkXCIsIHtzZXNzaW9uSWR9KVxuICAgIH0pXG4gICAgdGhpcy5zdGF0ZSA9IFwid2Vic29ja2V0XCJcbiAgICB0aGlzLmV2ZW50cy5lbWl0KFwib3V0cHV0XCIsIHJlc3BvbnNlKVxuICAgIHZvaWQgdGhpcy53ZWJzb2NrZXRTZXNzaW9uLmluaXRpYWxpemVDaGFubmVsKClcbiAgICB0aGlzLndlYnNvY2tldFNlc3Npb24uc2VuZFNlc3Npb25Fc3RhYmxpc2hlZCgpXG4gIH1cblxuICByZXF1ZXN0RG9uZSA9ICgpID0+IHtcbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZygoKSA9PiBbXCJyZXF1ZXN0RG9uZVwiLCB7Y2xpZW50Q291bnQ6IHRoaXMuY2xpZW50Q291bnQsIHF1ZXVlTGVuZ3RoOiB0aGlzLnJlcXVlc3RSdW5uZXJzLmxlbmd0aH1dKVxuXG4gICAgcmV0dXJuIHRoaXMuX2RyYWluRG9uZVJlcXVlc3RzKCkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICB0aGlzLmxvZ2dlci53YXJuKFwiRmFpbGVkIHdoaWxlIHNlbmRpbmcgZG9uZSByZXF1ZXN0c1wiLCBlcnJvcilcbiAgICAgIHRoaXMuZXZlbnRzLmVtaXQoXCJjbG9zZVwiKVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogRHJhaW5zIGRvbmUgcmVxdWVzdHMgb25lIGF0IGEgdGltZS4gQSBydW5uZXIgaXMgc2hpZnRlZCBvdXQgb2YgdGhlIHF1ZXVlIGJlZm9yZVxuICAgKiBpdHMgcmVzcG9uc2UgZmluaXNoZXMgc2VuZGluZyAoYXN5bmMgY29tcHJlc3Npb24sIGZpbGUgdHJhbnNmZXIpLCBzbyBhblxuICAgKiBvdmVybGFwcGluZyBkcmFpbiB3b3VsZCBvdGhlcndpc2UgcGljayB1cCB0aGUgbmV4dCBydW5uZXIgYW5kIHJlb3JkZXIgcGlwZWxpbmVkXG4gICAqIHNvY2tldCB3cml0ZXMuIENhbGxzIHRoYXQgYXJyaXZlIHdoaWxlIGEgZHJhaW4gaXMgYWN0aXZlIGFyZSBmb2xkZWQgaW50byBpdC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBldmVyeSBkb25lIHJlc3BvbnNlIGhhcyBiZWVuIHNlbnQuXG4gICAqL1xuICBhc3luYyBfZHJhaW5Eb25lUmVxdWVzdHMoKSB7XG4gICAgaWYgKHRoaXMuX2RvbmVSZXF1ZXN0c0RyYWluQWN0aXZlKSB7XG4gICAgICB0aGlzLl9kb25lUmVxdWVzdHNEcmFpblBlbmRpbmcgPSB0cnVlXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICB0aGlzLl9kb25lUmVxdWVzdHNEcmFpbkFjdGl2ZSA9IHRydWVcblxuICAgIHRyeSB7XG4gICAgICBkbyB7XG4gICAgICAgIHRoaXMuX2RvbmVSZXF1ZXN0c0RyYWluUGVuZGluZyA9IGZhbHNlXG4gICAgICAgIGF3YWl0IHRoaXMuc2VuZERvbmVSZXF1ZXN0cygpXG4gICAgICB9IHdoaWxlICh0aGlzLl9kb25lUmVxdWVzdHNEcmFpblBlbmRpbmcpXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuX2RvbmVSZXF1ZXN0c0RyYWluQWN0aXZlID0gZmFsc2VcbiAgICB9XG4gIH1cblxuICBhc3luYyBzZW5kRG9uZVJlcXVlc3RzKCkge1xuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBjb25zdCByZXF1ZXN0UnVubmVyID0gdGhpcy5yZXF1ZXN0UnVubmVyc1swXVxuICAgICAgY29uc3QgcmVxdWVzdCA9IHJlcXVlc3RSdW5uZXI/LmdldFJlcXVlc3QoKVxuXG4gICAgICBpZiAocmVxdWVzdFJ1bm5lcj8uZ2V0U3RhdGUoKSA9PSBcImRvbmVcIikge1xuICAgICAgICBjb25zdCBodHRwVmVyc2lvbiA9IHJlcXVlc3QuaHR0cFZlcnNpb24oKVxuICAgICAgICBjb25zdCBjb25uZWN0aW9uSGVhZGVyID0gcmVxdWVzdC5oZWFkZXIoXCJjb25uZWN0aW9uXCIpPy50b0xvd2VyQ2FzZSgpPy50cmltKClcbiAgICAgICAgY29uc3Qgc2hvdWxkQ2xvc2VDb25uZWN0aW9uID0gdGhpcy5zaG91bGRDbG9zZUNvbm5lY3Rpb24ocmVxdWVzdClcblxuICAgICAgICB0aGlzLnJlcXVlc3RSdW5uZXJzLnNoaWZ0KClcbiAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoKCkgPT4gW1wic2VuZERvbmVSZXF1ZXN0cyBzaGlmdGVkIHF1ZXVlXCIsIHtjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudCwgcXVldWVMZW5ndGg6IHRoaXMucmVxdWVzdFJ1bm5lcnMubGVuZ3RofV0pXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5zZW5kUmVzcG9uc2UocmVxdWVzdFJ1bm5lcilcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcigoKSA9PiBbYFZlbG9jaW91cyBjbGllbnQgJHt0aGlzLmNsaWVudENvdW50fSBmYWlsZWQgd2hpbGUgc2VuZGluZyByZXNwb25zZWAsIGVycm9yXSlcbiAgICAgICAgICB0aHJvdyBlcnJvclxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRSZXF1ZXN0ID09PSByZXF1ZXN0ICYmIHRoaXMuc3RhdGUgPT09IFwiaW5pdGlhbFwiKSB0aGlzLmN1cnJlbnRSZXF1ZXN0ID0gdW5kZWZpbmVkXG4gICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKCgpID0+IFtcInNlbmREb25lUmVxdWVzdHNcIiwge2NsaWVudENvdW50OiB0aGlzLmNsaWVudENvdW50LCBjb25uZWN0aW9uSGVhZGVyLCBodHRwVmVyc2lvbn1dKVxuXG4gICAgICAgIGlmIChzaG91bGRDbG9zZUNvbm5lY3Rpb24pIHtcbiAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZygoKSA9PiBbYENsb3NpbmcgdGhlIGNvbm5lY3Rpb24gYmVjYXVzZSAke2h0dHBWZXJzaW9ufSBhbmQgY29ubmVjdGlvbiBoZWFkZXIgJHtjb25uZWN0aW9uSGVhZGVyfWAsIHtjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudH1dKVxuICAgICAgICAgIHRoaXMuZXZlbnRzLmVtaXQoXCJjbG9zZVwiKVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVha1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHNlbmQgcmVzcG9uc2UuXG4gICAqIEBwYXJhbSB7UmVxdWVzdFJ1bm5lcn0gcmVxdWVzdFJ1bm5lciAtIFJlcXVlc3QgcnVubmVyLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbXBsZXRlLlxuICAgKi9cbiAgYXN5bmMgc2VuZFJlc3BvbnNlKHJlcXVlc3RSdW5uZXIpIHtcbiAgICBjb25zdCByZXNwb25zZSA9IGRpZ2cocmVxdWVzdFJ1bm5lciwgXCJyZXNwb25zZVwiKVxuICAgIGNvbnN0IHJlcXVlc3QgPSByZXF1ZXN0UnVubmVyLmdldFJlcXVlc3QoKVxuICAgIGNvbnN0IGZpbGVQYXRoID0gcmVzcG9uc2UuZ2V0RmlsZVBhdGgoKVxuICAgIGNvbnN0IGZpbGVPbkZpbmlzaGVkID0gcmVzcG9uc2UuZ2V0RmlsZU9uRmluaXNoZWQoKVxuICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZSgpXG4gICAgY29uc3QgY29ubmVjdGlvbkhlYWRlciA9IHJlcXVlc3QuaGVhZGVyKFwiY29ubmVjdGlvblwiKT8udG9Mb3dlckNhc2UoKT8udHJpbSgpXG4gICAgY29uc3QgaHR0cFZlcnNpb24gPSByZXF1ZXN0Lmh0dHBWZXJzaW9uKClcbiAgICBjb25zdCBzaG91bGRDbG9zZUNvbm5lY3Rpb24gPSB0aGlzLnNob3VsZENsb3NlQ29ubmVjdGlvbihyZXF1ZXN0KVxuICAgIGNvbnN0IGhhc0ZpbGVQYXRoID0gdHlwZW9mIGZpbGVQYXRoID09PSBcInN0cmluZ1wiICYmIGZpbGVQYXRoLmxlbmd0aCA+IDBcbiAgICBjb25zdCBib2R5ID0gaGFzRmlsZVBhdGggPyBudWxsIDogcmVzcG9uc2UuZ2V0Qm9keSgpXG4gICAgY29uc3QgYm9keUlzU3RyaW5nID0gdHlwZW9mIGJvZHkgPT09IFwic3RyaW5nXCJcbiAgICBjb25zdCBib2R5SXNCaW5hcnkgPSBib2R5IGluc3RhbmNlb2YgVWludDhBcnJheVxuXG4gICAgaWYgKCFoYXNGaWxlUGF0aCAmJiAhYm9keUlzU3RyaW5nICYmICFib2R5SXNCaW5hcnkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgcmVzcG9uc2UgYm9keSB0byBiZSBhIHN0cmluZyBvciBVaW50OEFycmF5LCBnb3QgJHt0eXBlb2YgYm9keX1gKVxuICAgIH1cblxuICAgIHRoaXMubG9nZ2VyLmRlYnVnKFwic2VuZFJlc3BvbnNlXCIsIHtjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudCwgY29ubmVjdGlvbkhlYWRlciwgaHR0cFZlcnNpb259KVxuICAgIHRoaXMubG9nZ2VyLmRlYnVnKCgpID0+IFtcInNlbmRSZXNwb25zZSBwYXlsb2FkXCIsIHtcbiAgICAgIGNsaWVudENvdW50OiB0aGlzLmNsaWVudENvdW50LFxuICAgICAgaGFzRmlsZVBhdGgsXG4gICAgICBmaWxlUGF0aCxcbiAgICAgIGJvZHlJc0JpbmFyeSxcbiAgICAgIGJvZHlJc1N0cmluZ1xuICAgIH1dKVxuXG4gICAgaWYgKHNob3VsZENsb3NlQ29ubmVjdGlvbikge1xuICAgICAgcmVzcG9uc2Uuc2V0SGVhZGVyKFwiQ29ubmVjdGlvblwiLCBcIkNsb3NlXCIpXG4gICAgfSBlbHNlIGlmIChodHRwVmVyc2lvbiA9PSBcIjEuMFwiICYmIGNvbm5lY3Rpb25IZWFkZXIgPT0gXCJrZWVwLWFsaXZlXCIpIHtcbiAgICAgIHJlc3BvbnNlLnNldEhlYWRlcihcIkNvbm5lY3Rpb25cIiwgXCJLZWVwLUFsaXZlXCIpXG4gICAgfVxuXG4gICAgLy8gUGVyIFJGQyA3MjMwIMKnMy4zLjMsIHJlc3BvbnNlcyB3aXRoIHN0YXR1cyBjb2RlcyAxeHgsIDIwNCwgYW5kIDMwNFxuICAgIC8vIE1VU1QgTk9UIGNhcnJ5IGEgbWVzc2FnZSBib2R5IGFuZCBNVVNUIE5PVCBpbmNsdWRlIENvbnRlbnQtTGVuZ3RoXG4gICAgLy8gKHdpdGggYSBuYXJyb3cgMzA0IGV4Y2VwdGlvbiB3ZSBkb24ndCBsZWFuIG9uKS4gU2VuZGluZyBvbmUgd291bGRcbiAgICAvLyBkZXN5bmNocm9uaXplIGtlZXAtYWxpdmUgY2xpZW50cyB3YWl0aW5nIGZvciBieXRlcyB0aGF0IG5ldmVyXG4gICAgLy8gYXJyaXZlIOKAlCBkcm9wIHRoZSBib2R5IGVudGlyZWx5IGZvciB0aG9zZSBjb2Rlcy5cbiAgICBjb25zdCBpc0JvZHlsZXNzU3RhdHVzID0gaXNOb0JvZHlTdGF0dXNDb2RlKHJlc3BvbnNlLmdldFN0YXR1c0NvZGUoKSlcblxuICAgIC8vIEhFQUQgcmVzcG9uc2VzIHNlbGVjdCBhbmQgY29tcHV0ZSB0aGUgZXhhY3Qgc2FtZSByZXByZXNlbnRhdGlvbiBoZWFkZXJzIGFzIHRoZVxuICAgIC8vIGVxdWl2YWxlbnQgR0VUIChpbmNsdWRpbmcgQ29udGVudC1MZW5ndGggYW5kIGFueSBuZWdvdGlhdGVkIENvbnRlbnQtRW5jb2RpbmcpLFxuICAgIC8vIGJ1dCBubyBidWZmZXJlZCBvciBmaWxlIGJvZHkgaXMgZW1pdHRlZCBiZWxvdy5cbiAgICBjb25zdCBpc0hlYWRSZXF1ZXN0ID0gcmVxdWVzdC5odHRwTWV0aG9kKCkgPT0gXCJIRUFEXCJcblxuICAgIC8qKiBAdHlwZSB7c3RyaW5nIHwgVWludDhBcnJheSB8IG51bGx9ICovXG4gICAgbGV0IGJvZHlUb0VtaXQgPSBib2R5XG5cbiAgICBpZiAoIWlzQm9keWxlc3NTdGF0dXMpIHtcbiAgICAgIGxldCBjb250ZW50TGVuZ3RoXG5cbiAgICAgIGlmIChoYXNGaWxlUGF0aCkge1xuICAgICAgICBjb25zdCBzdGF0cyA9IGF3YWl0IGZzLnN0YXQoZmlsZVBhdGgpXG4gICAgICAgIGNvbnRlbnRMZW5ndGggPSBzdGF0cy5zaXplXG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBTdHJpbmcgYm9kaWVzIGFyZSBVVEYtOCBmcmFtZWQsIHNvIHRoZSBidWZmZXJlZCBieXRlcyBhcmUgdGhlIFVURi04IGVuY29kaW5nO1xuICAgICAgICAvLyBVaW50OEFycmF5IGJvZGllcyBhcmUgYWxyZWFkeSB0aGUgZXhhY3Qgd2lyZSBieXRlcy5cbiAgICAgICAgY29uc3QgYm9keUJ1ZmZlciA9IGJvZHlJc1N0cmluZyA/IEJ1ZmZlci5mcm9tKGJvZHksIFwidXRmOFwiKSA6IEJ1ZmZlci5mcm9tKGJvZHkpXG4gICAgICAgIGNvbnN0IGNvbXByZXNzaW9uUmVzdWx0ID0gYXdhaXQgYXBwbHlSZXNwb25zZUNvbXByZXNzaW9uKHtcbiAgICAgICAgICBib2R5QnVmZmVyLFxuICAgICAgICAgIGNvbXByZXNzaW9uOiB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0SHR0cFNlcnZlckNvbXByZXNzaW9uKCksXG4gICAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgICByZXNwb25zZVxuICAgICAgICB9KVxuXG4gICAgICAgIGlmIChjb21wcmVzc2lvblJlc3VsdC5vdXRjb21lID09IFwibm90LWFjY2VwdGFibGVcIikge1xuICAgICAgICAgIC8vIFRoZSBjbGllbnQgZm9yYmlkcyBpZGVudGl0eSBhbmQgbm8gc3VwcG9ydGVkIGNvZGluZyBpcyBhY2NlcHRhYmxlOiBhbnN3ZXJcbiAgICAgICAgICAvLyB3aXRoIGFuIGVtcHR5IDQwNiBpbnN0ZWFkIG9mIGFuIHVuYWNjZXB0YWJsZSByZXByZXNlbnRhdGlvbi5cbiAgICAgICAgICByZXNwb25zZS5zZXRTdGF0dXMoNDA2KVxuICAgICAgICAgIHJlc3BvbnNlLnNldEJvZHkoXCJcIilcbiAgICAgICAgICBib2R5VG9FbWl0ID0gXCJcIlxuICAgICAgICAgIGNvbnRlbnRMZW5ndGggPSAwXG4gICAgICAgIH0gZWxzZSBpZiAoY29tcHJlc3Npb25SZXN1bHQub3V0Y29tZSA9PSBcImNvbXByZXNzZWRcIikge1xuICAgICAgICAgIGJvZHlUb0VtaXQgPSBjb21wcmVzc2lvblJlc3VsdC5ib2R5XG4gICAgICAgICAgY29udGVudExlbmd0aCA9IGNvbXByZXNzaW9uUmVzdWx0LmJvZHkubGVuZ3RoXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29udGVudExlbmd0aCA9IGJvZHlCdWZmZXIubGVuZ3RoXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gUmVtb3ZlIGFueSBhcHBsaWNhdGlvbiBwcmUtc2V0IENvbnRlbnQtTGVuZ3RoIChhbnkgY2FzaW5nKSBzbyBleGFjdGx5IG9uZVxuICAgICAgLy8gcmVjb21wdXRlZCB2YWx1ZSBnb2VzIG9uIHRoZSB3aXJlLlxuICAgICAgcmVzcG9uc2UucmVtb3ZlSGVhZGVyKFwiQ29udGVudC1MZW5ndGhcIilcbiAgICAgIHJlc3BvbnNlLnNldEhlYWRlcihcIkNvbnRlbnQtTGVuZ3RoXCIsIGNvbnRlbnRMZW5ndGgpXG4gICAgfVxuXG4gICAgcmVzcG9uc2Uuc2V0SGVhZGVyKFwiRGF0ZVwiLCBkYXRlLnRvVVRDU3RyaW5nKCkpXG4gICAgcmVzcG9uc2Uuc2V0SGVhZGVyKFwiU2VydmVyXCIsIFwiVmVsb2Npb3VzXCIpXG5cbiAgICBsZXQgaGVhZGVycyA9IFwiXCJcblxuICAgIGhlYWRlcnMgKz0gYEhUVFAvJHtyZXF1ZXN0Lmh0dHBWZXJzaW9uKCl9ICR7cmVzcG9uc2UuZ2V0U3RhdHVzQ29kZSgpfSAke3Jlc3BvbnNlLmdldFN0YXR1c01lc3NhZ2UoKX1cXHJcXG5gXG5cbiAgICBmb3IgKGNvbnN0IGhlYWRlcktleSBpbiByZXNwb25zZS5oZWFkZXJzKSB7XG4gICAgICBmb3IgKGNvbnN0IGhlYWRlclZhbHVlIG9mIHJlc3BvbnNlLmhlYWRlcnNbaGVhZGVyS2V5XSkge1xuICAgICAgICBoZWFkZXJzICs9IGAke2hlYWRlcktleX06ICR7aGVhZGVyVmFsdWV9XFxyXFxuYFxuICAgICAgfVxuICAgIH1cblxuICAgIGhlYWRlcnMgKz0gXCJcXHJcXG5cIlxuXG4gICAgdGhpcy5ldmVudHMuZW1pdChcIm91dHB1dFwiLCBoZWFkZXJzKVxuICAgIHRoaXMubG9nZ2VyLmRlYnVnKCgpID0+IFtcInNlbmRSZXNwb25zZSBoZWFkZXJzIGVtaXR0ZWRcIiwge2NsaWVudENvdW50OiB0aGlzLmNsaWVudENvdW50LCBoZWFkZXJzTGVuZ3RoOiBoZWFkZXJzLmxlbmd0aH1dKVxuXG4gICAgaWYgKGlzQm9keWxlc3NTdGF0dXMpIHtcbiAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKCgpID0+IFtcInNlbmRSZXNwb25zZSBib2R5IHN1cHByZXNzZWQgZm9yIG5vLWJvZHkgc3RhdHVzXCIsIHtjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudCwgc3RhdHVzQ29kZTogcmVzcG9uc2UuZ2V0U3RhdHVzQ29kZSgpfV0pXG4gICAgICBpZiAoaGFzRmlsZVBhdGgpIGF3YWl0IHRoaXMuc2VuZEZpbGVPdXRwdXQoZmlsZVBhdGgsIGZhbHNlLCBmaWxlT25GaW5pc2hlZClcbiAgICB9IGVsc2UgaWYgKGlzSGVhZFJlcXVlc3QpIHtcbiAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKCgpID0+IFtcInNlbmRSZXNwb25zZSBib2R5IHN1cHByZXNzZWQgZm9yIEhFQUQgcmVxdWVzdFwiLCB7Y2xpZW50Q291bnQ6IHRoaXMuY2xpZW50Q291bnR9XSlcbiAgICAgIGlmIChoYXNGaWxlUGF0aCkgYXdhaXQgdGhpcy5zZW5kRmlsZU91dHB1dChmaWxlUGF0aCwgZmFsc2UsIGZpbGVPbkZpbmlzaGVkKVxuICAgIH0gZWxzZSBpZiAoaGFzRmlsZVBhdGgpIHtcbiAgICAgIGF3YWl0IHRoaXMuc2VuZEZpbGVPdXRwdXQoZmlsZVBhdGgsIHRydWUsIGZpbGVPbkZpbmlzaGVkKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmV2ZW50cy5lbWl0KFwib3V0cHV0XCIsIGJvZHlUb0VtaXQpXG4gICAgICB0aGlzLmxvZ2dlci5kZWJ1ZygoKSA9PiBbXCJzZW5kUmVzcG9uc2UgYm9keSBlbWl0dGVkXCIsIHtjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudCwgYm9keUxlbmd0aDogYm9keVRvRW1pdCA/IGJvZHlUb0VtaXQubGVuZ3RoIDogMH1dKVxuICAgIH1cblxuICAgIGF3YWl0IHJlcXVlc3RSdW5uZXIubG9nQ29tcGxldGVkUmVxdWVzdCgpXG5cbiAgICBpZiAoXCJnZXRSZXF1ZXN0UGFyc2VyXCIgaW4gcmVxdWVzdCkge1xuICAgICAgY29uc3QgaHR0cFJlcXVlc3QgPSAvKiogQHR5cGUge2ltcG9ydChcIi4vcmVxdWVzdC5qc1wiKS5kZWZhdWx0fSAqLyAocmVxdWVzdClcbiAgICAgIGh0dHBSZXF1ZXN0LmdldFJlcXVlc3RQYXJzZXIoKS5kZXN0cm95KClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyBzZW5kIGZpbGUgb3V0cHV0LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gZmlsZVBhdGggLSBGaWxlIHBhdGguXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gc2VuZEJvZHkgLSBXaGV0aGVyIHRoZSBmaWxlIGJvZHkgc2hvdWxkIGJlIHNlbnQuXG4gICAqIEBwYXJhbSB7KChyZXN1bHQ6IFwiY29tcGxldGVkXCIgfCBcImFib3J0ZWRcIikgPT4gdm9pZCB8IFByb21pc2U8dm9pZD4pIHwgbnVsbH0gb25GaW5pc2hlZCAtIENvbXBsZXRpb24gY2FsbGJhY2suXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuXG4gICAqL1xuICBhc3luYyBzZW5kRmlsZU91dHB1dChmaWxlUGF0aCwgc2VuZEJvZHksIG9uRmluaXNoZWQpIHtcbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZygoKSA9PiBbXCJzZW5kRmlsZU91dHB1dCBzdGFydFwiLCB7Y2xpZW50Q291bnQ6IHRoaXMuY2xpZW50Q291bnQsIGZpbGVQYXRofV0pXG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgLyoqIEB0eXBlIHtQcm9taXNlPHZvaWQ+IHwgbnVsbH0gKi9cbiAgICAgIGxldCBzZXR0bGVtZW50ID0gbnVsbFxuICAgICAgY29uc3Qgc2V0dGxlID0gKC8qKiBAdHlwZSB7XCJjb21wbGV0ZWRcIiB8IFwiYWJvcnRlZFwifSAqLyB0cmFuc2ZlclJlc3VsdCkgPT4ge1xuICAgICAgICBpZiAoc2V0dGxlbWVudCkgcmV0dXJuIHNldHRsZW1lbnRcblxuICAgICAgICB0aGlzLnBlbmRpbmdGaWxlUmVzcG9uc2VzLmRlbGV0ZShzZXR0bGUpXG4gICAgICAgIHNldHRsZW1lbnQgPSB0aGlzLnJ1bkZpbGVPbkZpbmlzaGVkKHtmaWxlUGF0aCwgb25GaW5pc2hlZCwgcmVzdWx0OiB0cmFuc2ZlclJlc3VsdH0pXG4gICAgICAgICAgLmZpbmFsbHkoKCkgPT4gcmVzb2x2ZSh0cmFuc2ZlclJlc3VsdCkpXG5cbiAgICAgICAgcmV0dXJuIHNldHRsZW1lbnRcbiAgICAgIH1cblxuICAgICAgdGhpcy5wZW5kaW5nRmlsZVJlc3BvbnNlcy5hZGQoc2V0dGxlKVxuICAgICAgdGhpcy5ldmVudHMuZW1pdChcImZpbGVcIiwge2ZpbGVQYXRoLCBzZW5kQm9keSwgc2V0dGxlfSlcbiAgICB9KVxuXG4gICAgdGhpcy5sb2dnZXIuZGVidWcoKCkgPT4gW1wic2VuZEZpbGVPdXRwdXQgZG9uZVwiLCB7Y2xpZW50Q291bnQ6IHRoaXMuY2xpZW50Q291bnQsIGZpbGVQYXRoLCByZXN1bHR9XSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGEgZmlsZSBjb21wbGV0aW9uIGNhbGxiYWNrIHdpdGhvdXQgYWxsb3dpbmcgY2xlYW51cCBmYWlsdXJlcyB0byByZXBsYWNlIHRoZSBjb21taXR0ZWQgcmVzcG9uc2UuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gQ29tcGxldGlvbiBkZXRhaWxzLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXJncy5maWxlUGF0aCAtIEZpbGUgcGF0aC5cbiAgICogQHBhcmFtIHsoKHJlc3VsdDogXCJjb21wbGV0ZWRcIiB8IFwiYWJvcnRlZFwiKSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPikgfCBudWxsfSBhcmdzLm9uRmluaXNoZWQgLSBDb21wbGV0aW9uIGNhbGxiYWNrLlxuICAgKiBAcGFyYW0ge1wiY29tcGxldGVkXCIgfCBcImFib3J0ZWRcIn0gYXJncy5yZXN1bHQgLSBUcmFuc2ZlciByZXN1bHQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIGFmdGVyIGNhbGxiYWNrIGNsZWFudXAgYW5kIGVycm9yIHJlcG9ydGluZyBmaW5pc2guXG4gICAqL1xuICBhc3luYyBydW5GaWxlT25GaW5pc2hlZCh7ZmlsZVBhdGgsIG9uRmluaXNoZWQsIHJlc3VsdH0pIHtcbiAgICBpZiAoIW9uRmluaXNoZWQpIHJldHVyblxuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IG9uRmluaXNoZWQocmVzdWx0KVxuICAgIH0gY2F0Y2ggKGNhdWdodEVycm9yKSB7XG4gICAgICBjb25zdCBlcnJvciA9IGVuc3VyZUVycm9yKGNhdWdodEVycm9yKVxuXG4gICAgICBhd2FpdCB0aGlzLmxvZ2dlci5lcnJvcigoKSA9PiBbXCJGaWxlIHJlc3BvbnNlIG9uRmluaXNoZWQgY2FsbGJhY2sgZmFpbGVkXCIsIHtjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudCwgZmlsZVBhdGgsIHJlc3VsdH0sIGVycm9yXSlcblxuICAgICAgY29uc3QgZXJyb3JQYXlsb2FkID0ge1xuICAgICAgICBjb250ZXh0OiB7Y2xpZW50Q291bnQ6IHRoaXMuY2xpZW50Q291bnQsIGZpbGVQYXRoLCByZXN1bHQsIHN0YWdlOiBcInNlbmQtZmlsZS1vbi1maW5pc2hlZFwifSxcbiAgICAgICAgZXJyb3JcbiAgICAgIH1cblxuICAgICAgdGhpcy5jb25maWd1cmF0aW9uLmdldEVycm9yRXZlbnRzKCkuZW1pdChcImZyYW1ld29yay1lcnJvclwiLCBlcnJvclBheWxvYWQpXG4gICAgICB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0RXJyb3JFdmVudHMoKS5lbWl0KFwiYWxsLWVycm9yXCIsIHsuLi5lcnJvclBheWxvYWQsIGVycm9yVHlwZTogXCJmcmFtZXdvcmstZXJyb3JcIn0pXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFib3J0cyBhbGwgZmlsZSByZXNwb25zZXMgYXdhaXRpbmcgdHJhbnNwb3J0IGFja25vd2xlZGdlbWVudC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgYWZ0ZXIgcGVuZGluZyBjYWxsYmFja3Mgc2V0dGxlLlxuICAgKi9cbiAgYXN5bmMgYWJvcnRQZW5kaW5nRmlsZVJlc3BvbnNlcygpIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChbLi4udGhpcy5wZW5kaW5nRmlsZVJlc3BvbnNlc10ubWFwKChzZXR0bGUpID0+IHNldHRsZShcImFib3J0ZWRcIikpKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgc2hvdWxkIGNsb3NlIGNvbm5lY3Rpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9yZXF1ZXN0LmpzXCIpLmRlZmF1bHQgfCBpbXBvcnQoXCIuL3dlYnNvY2tldC1yZXF1ZXN0LmpzXCIpLmRlZmF1bHR9IHJlcXVlc3QgLSBSZXF1ZXN0IG9iamVjdC5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gV2hldGhlciB0aGUgY29ubmVjdGlvbiBzaG91bGQgYmUgY2xvc2VkLlxuICAgKi9cbiAgc2hvdWxkQ2xvc2VDb25uZWN0aW9uKHJlcXVlc3QpIHtcbiAgICBjb25zdCBodHRwVmVyc2lvbiA9IHJlcXVlc3QuaHR0cFZlcnNpb24oKVxuICAgIGNvbnN0IGNvbm5lY3Rpb25IZWFkZXIgPSByZXF1ZXN0LmhlYWRlcihcImNvbm5lY3Rpb25cIik/LnRvTG93ZXJDYXNlKCk/LnRyaW0oKVxuICAgIGNvbnN0IGNvbm5lY3Rpb25Ub2tlbnMgPSBjb25uZWN0aW9uSGVhZGVyXG4gICAgICA/IGNvbm5lY3Rpb25IZWFkZXIuc3BsaXQoXCIsXCIpLm1hcCgodG9rZW4pID0+IHRva2VuLnRyaW0oKSkuZmlsdGVyKEJvb2xlYW4pXG4gICAgICA6IFtdXG5cbiAgICBpZiAoaHR0cFZlcnNpb24gPT0gXCJ3ZWJzb2NrZXRcIikgcmV0dXJuIGZhbHNlXG4gICAgaWYgKGNvbm5lY3Rpb25Ub2tlbnMuaW5jbHVkZXMoXCJjbG9zZVwiKSkgcmV0dXJuIHRydWVcblxuICAgIGlmIChodHRwVmVyc2lvbiA9PSBcIjEuMFwiICYmIGNvbm5lY3Rpb25IZWFkZXIgIT0gXCJrZWVwLWFsaXZlXCIpIHJldHVybiB0cnVlXG5cbiAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBmb3IgdGhlIHN0YXR1cyBjb2RlcyB0aGF0IFJGQyA3MjMwIMKnMy4zLjMgZGVjbGFyZXNcbiAqIGNhbm5vdCBjYXJyeSBhIG1lc3NhZ2UgYm9keTogZXZlcnkgMXh4IGluZm9ybWF0aW9uYWwsIDIwNCBOb1xuICogQ29udGVudCwgYW5kIDMwNCBOb3QgTW9kaWZpZWQuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RhdHVzQ29kZSAtIEhUVFAgc3RhdHVzIGNvZGUuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBXaGV0aGVyIHRoZSBzdGF0dXMgY29kZSBmb3JiaWRzIGEgcmVzcG9uc2UgYm9keS5cbiAqL1xuZnVuY3Rpb24gaXNOb0JvZHlTdGF0dXNDb2RlKHN0YXR1c0NvZGUpIHtcbiAgcmV0dXJuIChzdGF0dXNDb2RlID49IDEwMCAmJiBzdGF0dXNDb2RlIDwgMjAwKSB8fCBzdGF0dXNDb2RlID09PSAyMDQgfHwgc3RhdHVzQ29kZSA9PT0gMzA0XG59XG4iXX0=
605
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvaHR0cC1zZXJ2ZXIvY2xpZW50L2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLE1BQU0sTUFBTSxRQUFRLENBQUE7QUFDM0IsT0FBTyxFQUFFLE1BQU0sa0JBQWtCLENBQUE7QUFDakMsT0FBTyxFQUFDLElBQUksRUFBQyxNQUFNLFdBQVcsQ0FBQTtBQUM5QixPQUFPLEVBQUMsV0FBVyxFQUFDLE1BQU0sU0FBUyxDQUFBO0FBQ25DLE9BQU8sWUFBWSxNQUFNLDhCQUE4QixDQUFBO0FBQ3ZELE9BQU8sTUFBTSxNQUFNLGlCQUFpQixDQUFBO0FBQ3BDLE9BQU8sT0FBTyxNQUFNLGNBQWMsQ0FBQTtBQUNsQyxPQUFPLGFBQWEsTUFBTSxxQkFBcUIsQ0FBQTtBQUMvQyxPQUFPLEVBQUMsdUJBQXVCLEVBQUUsd0JBQXdCLEVBQUUsd0JBQXdCLEVBQUMsTUFBTSwyQkFBMkIsQ0FBQTtBQUNySCxPQUFPLGdCQUFnQixNQUFNLHdCQUF3QixDQUFBO0FBRXJEOzs7O0dBSUc7QUFDSCxTQUFTLGlCQUFpQixDQUFDLEtBQUs7SUFDOUIsT0FBTztRQUNMLFVBQVUsRUFBRSxLQUFLLENBQUMsSUFBSTtRQUN0QixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87UUFDdEIsZ0JBQWdCLEVBQUUsS0FBSyxDQUFDLGdCQUFnQjtLQUN6QyxDQUFBO0FBQ0gsQ0FBQztBQUVELE1BQU0sQ0FBQyxPQUFPLE9BQU8sMEJBQTBCO0lBQzdDLE1BQU0sR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFBO0lBQzNCLEtBQUssR0FBRyxTQUFTLENBQUE7SUFFakI7O3lCQUVxQjtJQUNyQix3QkFBd0IsR0FBRyxLQUFLLENBQUE7SUFFaEM7O3lCQUVxQjtJQUNyQix5QkFBeUIsR0FBRyxLQUFLLENBQUE7SUFFakM7Ozs7OztPQU1HO0lBQ0gsWUFBWSxFQUFDLFdBQVcs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QUFRLENBQUMsT0FBTyxDQUFDO1lBQUUsT0FBTyxJQUFJLENBQUE7UUFFbkQsSUFBSSxXQUFXLElBQUksS0FBSyxJQUFJLGdCQUFnQixJQUFJLFlBQVk7WUFBRSxPQUFPLElBQUksQ0FBQTtRQUV6RSxPQUFPLEtBQUssQ0FBQTtJQUNkLENBQUM7Q0FDRjtBQUVEOzs7Ozs7R0FNRztBQUNILFNBQVMsa0JBQWtCLENBQUMsVUFBVTtJQUNwQyxPQUFPLENBQUMsVUFBVSxJQUFJLEdBQUcsSUFBSSxVQUFVLEdBQUcsR0FBRyxDQUFDLElBQUksVUFBVSxLQUFLLEdBQUcsSUFBSSxVQUFVLEtBQUssR0FBRyxDQUFBO0FBQzVGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IGNyeXB0byBmcm9tIFwiY3J5cHRvXCJcbmltcG9ydCBmcyBmcm9tIFwibm9kZTpmcy9wcm9taXNlc1wiXG5pbXBvcnQge2RpZ2d9IGZyb20gXCJkaWdnZXJpemVcIlxuaW1wb3J0IHtlbnN1cmVFcnJvcn0gZnJvbSBcInR5cGFuaWNcIlxuaW1wb3J0IEV2ZW50RW1pdHRlciBmcm9tIFwiLi4vLi4vdXRpbHMvZXZlbnQtZW1pdHRlci5qc1wiXG5pbXBvcnQgTG9nZ2VyIGZyb20gXCIuLi8uLi9sb2dnZXIuanNcIlxuaW1wb3J0IFJlcXVlc3QgZnJvbSBcIi4vcmVxdWVzdC5qc1wiXG5pbXBvcnQgUmVxdWVzdFJ1bm5lciBmcm9tIFwiLi9yZXF1ZXN0LXJ1bm5lci5qc1wiXG5pbXBvcnQge2FkZEFjY2VwdEVuY29kaW5nVG9WYXJ5LCBhcHBseVJlc3BvbnNlQ29tcHJlc3Npb24sIG5lZ290aWF0ZUNvbnRlbnRFbmNvZGluZ30gZnJvbSBcIi4vcmVzcG9uc2UtY29tcHJlc3Npb24uanNcIlxuaW1wb3J0IFdlYnNvY2tldFNlc3Npb24gZnJvbSBcIi4vd2Vic29ja2V0LXNlc3Npb24uanNcIlxuXG4vKipcbiAqIFJ1bnMgYmFkIHJlcXVlc3QgZGV0YWlscy5cbiAqIEBwYXJhbSB7RXJyb3IgJiB7dmVsb2Npb3VzQ29udGV4dD86IFJlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn19IGVycm9yIC0gRXJyb3IgaW5zdGFuY2UuXG4gKiBAcmV0dXJucyB7UmVjb3JkPHN0cmluZywgUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+fSAtIFNhZmUgYmFkLXJlcXVlc3QgZGV0YWlscyBmb3IgbG9ncy5cbiAqL1xuZnVuY3Rpb24gYmFkUmVxdWVzdERldGFpbHMoZXJyb3IpIHtcbiAgcmV0dXJuIHtcbiAgICBlcnJvckNsYXNzOiBlcnJvci5uYW1lLFxuICAgIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2UsXG4gICAgdmVsb2Npb3VzQ29udGV4dDogZXJyb3IudmVsb2Npb3VzQ29udGV4dFxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFZlb2xpY2lvdXNIdHRwU2VydmVyQ2xpZW50IHtcbiAgZXZlbnRzID0gbmV3IEV2ZW50RW1pdHRlcigpXG4gIHN0YXRlID0gXCJpbml0aWFsXCJcblxuICAvKipcbiAgICogV2hldGhlciBhIGRvbmUtcmVxdWVzdHMgZHJhaW4gaXMgY3VycmVudGx5IHNlbmRpbmcgcmVzcG9uc2VzIGZvciB0aGlzIGNsaWVudC5cbiAgICogQHR5cGUge2Jvb2xlYW59ICovXG4gIF9kb25lUmVxdWVzdHNEcmFpbkFjdGl2ZSA9IGZhbHNlXG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgYW5vdGhlciBkcmFpbiB3YXMgcmVxdWVzdGVkIHdoaWxlIG9uZSB3YXMgYWxyZWFkeSBhY3RpdmUuXG4gICAqIEB0eXBlIHtib29sZWFufSAqL1xuICBfZG9uZVJlcXVlc3RzRHJhaW5QZW5kaW5nID0gZmFsc2VcblxuICAvKipcbiAgICogUnVucyBjb25zdHJ1Y3Rvci5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zIG9iamVjdC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGFyZ3MuY2xpZW50Q291bnQgLSBDbGllbnQgY291bnQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0fSBhcmdzLmNvbmZpZ3VyYXRpb24gLSBDb25maWd1cmF0aW9uIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2FyZ3MucmVtb3RlQWRkcmVzc10gLSBSZW1vdGUgYWRkcmVzcy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHtjbGllbnRDb3VudCwgY29uZmlndXJhdGlvbiwgcmVtb3RlQWRkcmVzc30pIHtcbiAgICBpZiAoIWNvbmZpZ3VyYXRpb24pIHRocm93IG5ldyBFcnJvcihcIk5vIGNvbmZpZ3VyYXRpb24gZ2l2ZW5cIilcblxuICAgIHRoaXMubG9nZ2VyID0gbmV3IExvZ2dlcih0aGlzKVxuICAgIHRoaXMuY2xpZW50Q291bnQgPSBjbGllbnRDb3VudFxuICAgIHRoaXMuY29uZmlndXJhdGlvbiA9IGNvbmZpZ3VyYXRpb25cbiAgICB0aGlzLnJlbW90ZUFkZHJlc3MgPSByZW1vdGVBZGRyZXNzXG5cbiAgICAvKipcbiAgICAgKiBOYXJyb3dzIHRoZSBydW50aW1lIHZhbHVlIHRvIHRoZSBkb2N1bWVudGVkIHR5cGUuXG4gICAgICogQHR5cGUge1JlcXVlc3RSdW5uZXJbXX0gKi9cbiAgICB0aGlzLnJlcXVlc3RSdW5uZXJzID0gW11cblxuICAgIC8qKiBAdHlwZSB7U2V0PChyZXN1bHQ6IFwiY29tcGxldGVkXCIgfCBcImFib3J0ZWRcIikgPT4gUHJvbWlzZTx2b2lkPj59ICovXG4gICAgdGhpcy5wZW5kaW5nRmlsZVJlc3BvbnNlcyA9IG5ldyBTZXQoKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgc2VuZCBiYWQgdXBncmFkZSByZXNwb25zZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBNZXNzYWdlIHRleHQuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIF9zZW5kQmFkVXBncmFkZVJlc3BvbnNlKG1lc3NhZ2UpIHtcbiAgICBjb25zdCBodHRwVmVyc2lvbiA9IHRoaXMuY3VycmVudFJlcXVlc3Q/Lmh0dHBWZXJzaW9uKCkgfHwgXCIxLjFcIlxuICAgIGNvbnN0IGJvZHkgPSBgJHttZXNzYWdlfVxcbmBcbiAgICBjb25zdCBoZWFkZXJzID0gW1xuICAgICAgYEhUVFAvJHtodHRwVmVyc2lvbn0gNDAwIEJhZCBSZXF1ZXN0YCxcbiAgICAgIFwiQ29ubmVjdGlvbjogQ2xvc2VcIixcbiAgICAgIFwiQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PVVURi04XCIsXG4gICAgICBgQ29udGVudC1MZW5ndGg6ICR7QnVmZmVyLmJ5dGVMZW5ndGgoYm9keSwgXCJ1dGY4XCIpfWAsXG4gICAgICBcIlwiLFxuICAgICAgYm9keVxuICAgIF0uam9pbihcIlxcclxcblwiKVxuXG4gICAgdGhpcy5ldmVudHMuZW1pdChcIm91dHB1dFwiLCBoZWFkZXJzKVxuICAgIHRoaXMuZXZlbnRzLmVtaXQoXCJjbG9zZVwiKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgc2VuZCBiYWQgcmVxdWVzdCByZXNwb25zZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBSZXNwb25zZSBtZXNzYWdlLlxuICAgKiBAcmV0dXJucyB7dm9pZH0gLSBObyByZXR1cm4gdmFsdWUuXG4gICAqL1xuICBfc2VuZEJhZFJlcXVlc3RSZXNwb25zZShtZXNzYWdlKSB7XG4gICAgY29uc3QgaHR0cFZlcnNpb24gPSB0aGlzLmN1cnJlbnRSZXF1ZXN0Py5odHRwVmVyc2lvbigpIHx8IFwiMS4xXCJcbiAgICBjb25zdCBib2R5ID0gYCR7bWVzc2FnZX1cXG5gXG4gICAgY29uc3QgaGVhZGVycyA9IFtcbiAgICAgIGBIVFRQLyR7aHR0cFZlcnNpb259IDQwMCBCYWQgUmVxdWVzdGAsXG4gICAgICBcIkNvbm5lY3Rpb246IENsb3NlXCIsXG4gICAgICBcIkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD1VVEYtOFwiLFxuICAgICAgYENvbnRlbnQtTGVuZ3RoOiAke0J1ZmZlci5ieXRlTGVuZ3RoKGJvZHksIFwidXRmOFwiKX1gLFxuICAgICAgXCJcIixcbiAgICAgIGJvZHlcbiAgICBdLmpvaW4oXCJcXHJcXG5cIilcblxuICAgIHRoaXMuZXZlbnRzLmVtaXQoXCJvdXRwdXRcIiwgaGVhZGVycylcbiAgICB0aGlzLmV2ZW50cy5lbWl0KFwiY2xvc2VcIilcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGhhbmRsZSBiYWQgcmVxdWVzdC5cbiAgICogQHBhcmFtIHtFcnJvcn0gZXJyb3IgLSBFcnJvciBpbnN0YW5jZS5cbiAgICogQHJldHVybnMge3ZvaWR9IC0gTm8gcmV0dXJuIHZhbHVlLlxuICAgKi9cbiAgaGFuZGxlQmFkUmVxdWVzdChlcnJvcikge1xuICAgIHRoaXMubG9nZ2VyLndhcm4oKCkgPT4gW1wiRmFpbGVkIHRvIHBhcnNlIEhUVFAgcmVxdWVzdFwiLCBiYWRSZXF1ZXN0RGV0YWlscygvKiogQHR5cGUge0Vycm9yICYge3ZlbG9jaW91c0NvbnRleHQ/OiBSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59fSAqLyAoZXJyb3IpKV0pXG5cbiAgICBpZiAodGhpcy5jdXJyZW50UmVxdWVzdCAmJiBcImdldFJlcXVlc3RQYXJzZXJcIiBpbiB0aGlzLmN1cnJlbnRSZXF1ZXN0KSB7XG4gICAgICBjb25zdCBodHRwUmVxdWVzdCA9IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9yZXF1ZXN0LmpzXCIpLmRlZmF1bHR9ICovICh0aGlzLmN1cnJlbnRSZXF1ZXN0KVxuXG4gICAgICBodHRwUmVxdWVzdC5nZXRSZXF1ZXN0UGFyc2VyKCkuZGVzdHJveSgpXG4gICAgfVxuXG4gICAgdGhpcy5jdXJyZW50UmVxdWVzdCA9IHVuZGVmaW5lZFxuICAgIHRoaXMuc3RhdGUgPSBcImluaXRpYWxcIlxuXG4gICAgdGhpcy5fc2VuZEJhZFJlcXVlc3RSZXNwb25zZShcIkJhZCBSZXF1ZXN0XCIpXG4gIH1cblxuICBleGVjdXRlQ3VycmVudFJlcXVlc3QgPSAoKSA9PiB7XG4gICAgdGhpcy5sb2dnZXIuZGVidWcoXCJleGVjdXRlQ3VycmVudFJlcXVlc3RcIilcblxuICAgIGNvbnN0IGN1cnJlbnRSZXF1ZXN0ID0gdGhpcy5jdXJyZW50UmVxdWVzdFxuXG4gICAgaWYgKCFjdXJyZW50UmVxdWVzdCkgdGhyb3cgbmV3IEVycm9yKFwiTm8gY3VycmVudCByZXF1ZXN0XCIpXG4gICAgY29uc3QgcmVkYWN0b3IgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0TG9nUmVkYWN0b3IoKVxuICAgIGNvbnN0IHNlbnNpdGl2ZVZhbHVlcyA9IHJlZGFjdG9yLnJlcXVlc3RTZW5zaXRpdmVWYWx1ZXMoY3VycmVudFJlcXVlc3QpXG5cbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZygoKSA9PiBbXCJleGVjdXRlQ3VycmVudFJlcXVlc3QgcmVxdWVzdFwiLCB7XG4gICAgICBjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudCxcbiAgICAgIGh0dHBNZXRob2Q6IGN1cnJlbnRSZXF1ZXN0Lmh0dHBNZXRob2QoKSxcbiAgICAgIGh0dHBWZXJzaW9uOiBjdXJyZW50UmVxdWVzdC5odHRwVmVyc2lvbigpLFxuICAgICAgcGF0aDogcmVkYWN0b3IucmVkYWN0UGF0aChjdXJyZW50UmVxdWVzdC5wYXRoKCksIHNlbnNpdGl2ZVZhbHVlcyksXG4gICAgICBxdWV1ZUxlbmd0aDogdGhpcy5yZXF1ZXN0UnVubmVycy5sZW5ndGhcbiAgICB9XSlcblxuICAgIGlmICh0aGlzLl9pc1dlYnNvY2tldFVwZ3JhZGUoY3VycmVudFJlcXVlc3QpKSB7XG4gICAgICB0aGlzLl91cGdyYWRlVG9XZWJzb2NrZXQoKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gV2UgYXJlIGRvbmUgcGFyc2luZyB0aGUgZ2l2ZW4gcmVxdWVzdCBhbmQgY2FuIHRoZW9yZXRpY2FsbHkgc3RhcnQgcGFyc2luZyBhIG5ldyBvbmUsIGJlZm9yZSB0aGUgY3VycmVudCByZXF1ZXN0IGlzIGRvbmUgLSBzbyByZXNldCB0aGUgc3RhdGUuXG4gICAgdGhpcy5zdGF0ZSA9IFwiaW5pdGlhbFwiXG5cbiAgICBjb25zdCByZXF1ZXN0UnVubmVyID0gbmV3IFJlcXVlc3RSdW5uZXIoe1xuICAgICAgY29uZmlndXJhdGlvbjogdGhpcy5jb25maWd1cmF0aW9uLFxuICAgICAgcmVxdWVzdDogY3VycmVudFJlcXVlc3RcbiAgICB9KVxuXG4gICAgdGhpcy5yZXF1ZXN0UnVubmVycy5wdXNoKHJlcXVlc3RSdW5uZXIpXG5cbiAgICByZXF1ZXN0UnVubmVyLmV2ZW50cy5vbihcImRvbmVcIiwgdGhpcy5yZXF1ZXN0RG9uZSlcbiAgICByZXF1ZXN0UnVubmVyLnJ1bigpXG4gIH1cblxuICAvKipcbiAgICogUnVucyBvbiB3cml0ZS5cbiAgICogQHBhcmFtIHtCdWZmZXJ9IGRhdGEgLSBEYXRhIHBheWxvYWQuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIG9uV3JpdGUoZGF0YSkge1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKCgpID0+IFtcIm9uV3JpdGUgc3RhcnRcIiwge1xuICAgICAgY2xpZW50Q291bnQ6IHRoaXMuY2xpZW50Q291bnQsXG4gICAgICBsZW5ndGg6IGRhdGEubGVuZ3RoLFxuICAgICAgc3RhdGU6IHRoaXMuc3RhdGUsXG4gICAgfV0pXG5cbiAgICBpZiAodGhpcy53ZWJzb2NrZXRTZXNzaW9uKSB7XG4gICAgICB0aGlzLndlYnNvY2tldFNlc3Npb24ub25EYXRhKGRhdGEpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgLyoqXG4gICAgICAgKiBSZW1haW5pbmcuXG4gICAgICAgKiBAdHlwZSB7QnVmZmVyIHwgdW5kZWZpbmVkfSAqL1xuICAgICAgbGV0IHJlbWFpbmluZyA9IGRhdGFcblxuICAgICAgd2hpbGUgKHJlbWFpbmluZykge1xuICAgICAgICBpZiAocmVtYWluaW5nLmxlbmd0aCA8PSAwKSBicmVha1xuXG4gICAgICAgIGlmICh0aGlzLnN0YXRlID09IFwiaW5pdGlhbFwiKSB7XG4gICAgICAgICAgY29uc3QgcmVtYWluaW5nTGVuZ3RoID0gcmVtYWluaW5nLmxlbmd0aFxuXG4gICAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoKCkgPT4gW1wib25Xcml0ZSBjcmVhdGluZyByZXF1ZXN0IHBhcnNlclwiLCB7Y2xpZW50Q291bnQ6IHRoaXMuY2xpZW50Q291bnQsIHJlbWFpbmluZ0xlbmd0aH1dKVxuICAgICAgICAgIHRoaXMuY3VycmVudFJlcXVlc3QgPSBuZXcgUmVxdWVzdCh7Y2xpZW50OiB0aGlzLCBjb25maWd1cmF0aW9uOiB0aGlzLmNvbmZpZ3VyYXRpb259KVxuICAgICAgICAgIHRoaXMuY3VycmVudFJlcXVlc3QucmVxdWVzdFBhcnNlci5ldmVudHMub24oXCJkb25lXCIsIHRoaXMuZXhlY3V0ZUN1cnJlbnRSZXF1ZXN0KVxuICAgICAgICAgIHRoaXMuc3RhdGUgPSBcInJlcXVlc3RTdGFydGVkXCJcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlICE9IFwicmVxdWVzdFN0YXJ0ZWRcIikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBzdGF0ZSBmb3IgY2xpZW50OiAke3RoaXMuc3RhdGV9YClcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5jdXJyZW50UmVxdWVzdCkgdGhyb3cgbmV3IEVycm9yKFwiTm8gY3VycmVudCByZXF1ZXN0XCIpXG5cbiAgICAgICAgcmVtYWluaW5nID0gdGhpcy5jdXJyZW50UmVxdWVzdC5mZWVkKHJlbWFpbmluZylcbiAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoKCkgPT4gW1wib25Xcml0ZSBmZWQgcGFyc2VyXCIsIHtcbiAgICAgICAgICBjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudCxcbiAgICAgICAgICBoYXNSZW1haW5pbmc6IEJvb2xlYW4ocmVtYWluaW5nPy5sZW5ndGgpLFxuICAgICAgICAgIHJlbWFpbmluZ0xlbmd0aDogcmVtYWluaW5nPy5sZW5ndGggfHwgMCxcbiAgICAgICAgICBwYXJzZXJDb21wbGV0ZWQ6IHRoaXMuY3VycmVudFJlcXVlc3Q/LmdldFJlcXVlc3RQYXJzZXIoKS5oYXNDb21wbGV0ZWRcbiAgICAgICAgfV0pXG5cbiAgICAgICAgaWYgKHJlbWFpbmluZyAmJiByZW1haW5pbmcubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGNvbnN0IHJlcXVlc3RQYXJzZXIgPSB0aGlzLmN1cnJlbnRSZXF1ZXN0LmdldFJlcXVlc3RQYXJzZXIoKVxuXG4gICAgICAgICAgaWYgKCFyZXF1ZXN0UGFyc2VyLmhhc0NvbXBsZXRlZCkge1xuICAgICAgICAgICAgY29uc3QgcmVtYWluaW5nTGVuZ3RoID0gcmVtYWluaW5nLmxlbmd0aFxuXG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZygoKSA9PiBbXCJvbldyaXRlIHdhaXRpbmcgZm9yIG1vcmUgZGF0YVwiLCB7Y2xpZW50Q291bnQ6IHRoaXMuY2xpZW50Q291bnQsIHJlbWFpbmluZ0xlbmd0aH1dKVxuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLnN0YXRlID0gXCJpbml0aWFsXCJcbiAgICAgICAgICBjb25zdCByZW1haW5pbmdMZW5ndGggPSByZW1haW5pbmcubGVuZ3RoXG5cbiAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZygoKSA9PiBbXCJvbldyaXRlIHBhcnNlciBjb21wbGV0ZWQgd2l0aCByZW1haW5pbmcgYnl0ZXNcIiwge2NsaWVudENvdW50OiB0aGlzLmNsaWVudENvdW50LCByZW1haW5pbmdMZW5ndGh9XSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhpcy5sb2dnZXIuZGVidWcoKCkgPT4gW1wib25Xcml0ZSBlbmRcIiwge2NsaWVudENvdW50OiB0aGlzLmNsaWVudENvdW50LCBzdGF0ZTogdGhpcy5zdGF0ZSwgcXVldWVMZW5ndGg6IHRoaXMucmVxdWVzdFJ1bm5lcnMubGVuZ3RofV0pXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMuaGFuZGxlQmFkUmVxdWVzdChlbnN1cmVFcnJvcihlcnJvcikpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgaXMgd2Vic29ja2V0IHVwZ3JhZGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9yZXF1ZXN0LmpzXCIpLmRlZmF1bHR9IHJlcXVlc3QgLSBSZXF1ZXN0IG9iamVjdC5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gV2hldGhlciB3ZWJzb2NrZXQgdXBncmFkZS5cbiAgICovXG4gIF9pc1dlYnNvY2tldFVwZ3JhZGUocmVxdWVzdCkge1xuICAgIGNvbnN0IHVwZ3JhZGVIZWFkZXIgPSByZXF1ZXN0LmhlYWRlcihcInVwZ3JhZGVcIik/LnRvTG93ZXJDYXNlKClcbiAgICBjb25zdCBjb25uZWN0aW9uSGVhZGVyID0gcmVxdWVzdC5oZWFkZXIoXCJjb25uZWN0aW9uXCIpPy50b0xvd2VyQ2FzZSgpXG5cbiAgICByZXR1cm4gQm9vbGVhbih1cGdyYWRlSGVhZGVyID09IFwid2Vic29ja2V0XCIgJiYgY29ubmVjdGlvbkhlYWRlcj8uaW5jbHVkZXMoXCJ1cGdyYWRlXCIpKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgdXBncmFkZSB0byB3ZWJzb2NrZXQuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIF91cGdyYWRlVG9XZWJzb2NrZXQoKSB7XG4gICAgaWYgKCF0aGlzLmN1cnJlbnRSZXF1ZXN0KSB0aHJvdyBuZXcgRXJyb3IoXCJObyBjdXJyZW50IHJlcXVlc3RcIilcblxuICAgIGNvbnN0IHNlY1dlYnNvY2tldEtleSA9IHRoaXMuY3VycmVudFJlcXVlc3QuaGVhZGVyKFwic2VjLXdlYnNvY2tldC1rZXlcIilcblxuICAgIGlmICghc2VjV2Vic29ja2V0S2V5KSB7XG4gICAgICB0aGlzLl9zZW5kQmFkVXBncmFkZVJlc3BvbnNlKFwiTWlzc2luZyBTZWMtV2ViU29ja2V0LUtleSBoZWFkZXJcIilcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNvbnN0IHdlYnNvY2tldEFjY2VwdEtleSA9IGNyeXB0by5jcmVhdGVIYXNoKFwic2hhMVwiKVxuICAgICAgLnVwZGF0ZShgJHtzZWNXZWJzb2NrZXRLZXl9MjU4RUFGQTUtRTkxNC00N0RBLTk1Q0EtQzVBQjBEQzg1QjExYCwgXCJiaW5hcnlcIilcbiAgICAgIC5kaWdlc3QoXCJiYXNlNjRcIilcbiAgICBjb25zdCBodHRwVmVyc2lvbiA9IHRoaXMuY3VycmVudFJlcXVlc3QuaHR0cFZlcnNpb24oKSB8fCBcIjEuMVwiXG4gICAgY29uc3QgcmVzcG9uc2VMaW5lcyA9IFtcbiAgICAgIGBIVFRQLyR7aHR0cFZlcnNpb259IDEwMSBTd2l0Y2hpbmcgUHJvdG9jb2xzYCxcbiAgICAgIFwiVXBncmFkZTogd2Vic29ja2V0XCIsXG4gICAgICBcIkNvbm5lY3Rpb246IFVwZ3JhZGVcIixcbiAgICAgIGBTZWMtV2ViU29ja2V0LUFjY2VwdDogJHt3ZWJzb2NrZXRBY2NlcHRLZXl9YCxcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiXG4gICAgXVxuICAgIGNvbnN0IHJlc3BvbnNlID0gcmVzcG9uc2VMaW5lcy5qb2luKFwiXFxyXFxuXCIpXG5cbiAgICBjb25zdCBtZXNzYWdlSGFuZGxlclJlc29sdmVyID0gdGhpcy5jb25maWd1cmF0aW9uLmdldFdlYnNvY2tldE1lc3NhZ2VIYW5kbGVyUmVzb2x2ZXI/LigpXG4gICAgbGV0IG1lc3NhZ2VIYW5kbGVyXG4gICAgbGV0IG1lc3NhZ2VIYW5kbGVyUHJvbWlzZVxuXG4gICAgaWYgKG1lc3NhZ2VIYW5kbGVyUmVzb2x2ZXIpIHtcbiAgICAgIGNvbnN0IHJlc29sdmVkSGFuZGxlciA9IG1lc3NhZ2VIYW5kbGVyUmVzb2x2ZXIoe1xuICAgICAgICBjbGllbnQ6IHRoaXMsXG4gICAgICAgIGNvbmZpZ3VyYXRpb246IHRoaXMuY29uZmlndXJhdGlvbixcbiAgICAgICAgcmVxdWVzdDogdGhpcy5jdXJyZW50UmVxdWVzdFxuICAgICAgfSlcblxuICAgICAgY29uc3QgcmVzb2x2ZWRUaGVuYWJsZSA9IC8qKiBAdHlwZSB7e3RoZW4/OiAoLi4uYXJnczogQXJyYXk8UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+KSA9PiBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPn19ICovIChyZXNvbHZlZEhhbmRsZXIpXG5cbiAgICAgIGlmIChyZXNvbHZlZFRoZW5hYmxlPy50aGVuKSB7XG4gICAgICAgIG1lc3NhZ2VIYW5kbGVyUHJvbWlzZSA9IC8qKiBAdHlwZSB7UHJvbWlzZTxpbXBvcnQoXCIuLi8uLi9jb25maWd1cmF0aW9uLXR5cGVzLmpzXCIpLldlYnNvY2tldE1lc3NhZ2VIYW5kbGVyIHwgdm9pZD59ICovIChyZXNvbHZlZEhhbmRsZXIpXG4gICAgICB9IGVsc2UgaWYgKHJlc29sdmVkSGFuZGxlcikge1xuICAgICAgICBtZXNzYWdlSGFuZGxlciA9IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5XZWJzb2NrZXRNZXNzYWdlSGFuZGxlcn0gKi8gKHJlc29sdmVkSGFuZGxlcilcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLndlYnNvY2tldFNlc3Npb24gPSBuZXcgV2Vic29ja2V0U2Vzc2lvbih7XG4gICAgICBjbGllbnQ6IHRoaXMsXG4gICAgICBjb25maWd1cmF0aW9uOiB0aGlzLmNvbmZpZ3VyYXRpb24sXG4gICAgICB1cGdyYWRlUmVxdWVzdDogdGhpcy5jdXJyZW50UmVxdWVzdCxcbiAgICAgIG1lc3NhZ2VIYW5kbGVyOiBtZXNzYWdlSGFuZGxlcixcbiAgICAgIG1lc3NhZ2VIYW5kbGVyUHJvbWlzZTogbWVzc2FnZUhhbmRsZXJQcm9taXNlXG4gICAgfSlcbiAgICB0aGlzLndlYnNvY2tldFNlc3Npb24uZXZlbnRzLm9uKFwiY2xvc2VcIiwgKCkgPT4ge1xuICAgICAgLy8gUGF1c2VkIHNlc3Npb25zIHN1cnZpdmUgdGhlIHNvY2tldCBjbG9zZTsgZG9uJ3QgZGVzdHJveSgpLlxuICAgICAgLy8gVGhlIGdyYWNlLWV4cGlyeSBwYXRoIChfZmluYWxpemVHcmFjZUV4cGlyeSkgd2lsbCBkZXN0cm95XG4gICAgICAvLyB0aGVtIHBlcm1hbmVudGx5IGlmIHJlc3VtZSBkb2Vzbid0IGhhcHBlbiBpbiB0aW1lLlxuICAgICAgaWYgKCF0aGlzLndlYnNvY2tldFNlc3Npb24/LmlzUGF1c2VkKCkpIHtcbiAgICAgICAgdGhpcy53ZWJzb2NrZXRTZXNzaW9uPy5kZXN0cm95KClcbiAgICAgIH1cbiAgICAgIHRoaXMud2Vic29ja2V0U2Vzc2lvbiA9IHVuZGVmaW5lZFxuICAgICAgdGhpcy5ldmVudHMuZW1pdChcImNsb3NlXCIpXG4gICAgfSlcbiAgICB0aGlzLndlYnNvY2tldFNlc3Npb24uZXZlbnRzLm9uKFwib3duZXJzaGlwQ2xhaW1lZFwiLCAoe3Nlc3Npb25JZH0pID0+IHtcbiAgICAgIHRoaXMuZXZlbnRzLmVtaXQoXCJ3ZWJzb2NrZXRTZXNzaW9uT3duZWRcIiwge3Nlc3Npb25JZH0pXG4gICAgfSlcbiAgICB0aGlzLndlYnNvY2tldFNlc3Npb24uZXZlbnRzLm9uKFwib3duZXJzaGlwUmVsZWFzZWRcIiwgKHtzZXNzaW9uSWR9KSA9PiB7XG4gICAgICB0aGlzLmV2ZW50cy5lbWl0KFwid2Vic29ja2V0U2Vzc2lvblJlbGVhc2VkXCIsIHtzZXNzaW9uSWR9KVxuICAgIH0pXG4gICAgdGhpcy5zdGF0ZSA9IFwid2Vic29ja2V0XCJcbiAgICB0aGlzLmV2ZW50cy5lbWl0KFwib3V0cHV0XCIsIHJlc3BvbnNlKVxuICAgIHZvaWQgdGhpcy53ZWJzb2NrZXRTZXNzaW9uLmluaXRpYWxpemVDaGFubmVsKClcbiAgICB0aGlzLndlYnNvY2tldFNlc3Npb24uc2VuZFNlc3Npb25Fc3RhYmxpc2hlZCgpXG4gIH1cblxuICByZXF1ZXN0RG9uZSA9ICgpID0+IHtcbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZygoKSA9PiBbXCJyZXF1ZXN0RG9uZVwiLCB7Y2xpZW50Q291bnQ6IHRoaXMuY2xpZW50Q291bnQsIHF1ZXVlTGVuZ3RoOiB0aGlzLnJlcXVlc3RSdW5uZXJzLmxlbmd0aH1dKVxuXG4gICAgcmV0dXJuIHRoaXMuX2RyYWluRG9uZVJlcXVlc3RzKCkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICB0aGlzLmxvZ2dlci53YXJuKFwiRmFpbGVkIHdoaWxlIHNlbmRpbmcgZG9uZSByZXF1ZXN0c1wiLCBlcnJvcilcbiAgICAgIHRoaXMuZXZlbnRzLmVtaXQoXCJjbG9zZVwiKVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogRHJhaW5zIGRvbmUgcmVxdWVzdHMgb25lIGF0IGEgdGltZS4gQSBydW5uZXIgaXMgc2hpZnRlZCBvdXQgb2YgdGhlIHF1ZXVlIGJlZm9yZVxuICAgKiBpdHMgcmVzcG9uc2UgZmluaXNoZXMgc2VuZGluZyAoYXN5bmMgY29tcHJlc3Npb24sIGZpbGUgdHJhbnNmZXIpLCBzbyBhblxuICAgKiBvdmVybGFwcGluZyBkcmFpbiB3b3VsZCBvdGhlcndpc2UgcGljayB1cCB0aGUgbmV4dCBydW5uZXIgYW5kIHJlb3JkZXIgcGlwZWxpbmVkXG4gICAqIHNvY2tldCB3cml0ZXMuIENhbGxzIHRoYXQgYXJyaXZlIHdoaWxlIGEgZHJhaW4gaXMgYWN0aXZlIGFyZSBmb2xkZWQgaW50byBpdC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBldmVyeSBkb25lIHJlc3BvbnNlIGhhcyBiZWVuIHNlbnQuXG4gICAqL1xuICBhc3luYyBfZHJhaW5Eb25lUmVxdWVzdHMoKSB7XG4gICAgaWYgKHRoaXMuX2RvbmVSZXF1ZXN0c0RyYWluQWN0aXZlKSB7XG4gICAgICB0aGlzLl9kb25lUmVxdWVzdHNEcmFpblBlbmRpbmcgPSB0cnVlXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICB0aGlzLl9kb25lUmVxdWVzdHNEcmFpbkFjdGl2ZSA9IHRydWVcblxuICAgIHRyeSB7XG4gICAgICBkbyB7XG4gICAgICAgIHRoaXMuX2RvbmVSZXF1ZXN0c0RyYWluUGVuZGluZyA9IGZhbHNlXG4gICAgICAgIGF3YWl0IHRoaXMuc2VuZERvbmVSZXF1ZXN0cygpXG4gICAgICB9IHdoaWxlICh0aGlzLl9kb25lUmVxdWVzdHNEcmFpblBlbmRpbmcpXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuX2RvbmVSZXF1ZXN0c0RyYWluQWN0aXZlID0gZmFsc2VcbiAgICB9XG4gIH1cblxuICBhc3luYyBzZW5kRG9uZVJlcXVlc3RzKCkge1xuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBjb25zdCByZXF1ZXN0UnVubmVyID0gdGhpcy5yZXF1ZXN0UnVubmVyc1swXVxuICAgICAgY29uc3QgcmVxdWVzdCA9IHJlcXVlc3RSdW5uZXI/LmdldFJlcXVlc3QoKVxuXG4gICAgICBpZiAocmVxdWVzdFJ1bm5lcj8uZ2V0U3RhdGUoKSA9PSBcImRvbmVcIikge1xuICAgICAgICBjb25zdCBodHRwVmVyc2lvbiA9IHJlcXVlc3QuaHR0cFZlcnNpb24oKVxuICAgICAgICBjb25zdCBjb25uZWN0aW9uSGVhZGVyID0gcmVxdWVzdC5oZWFkZXIoXCJjb25uZWN0aW9uXCIpPy50b0xvd2VyQ2FzZSgpPy50cmltKClcbiAgICAgICAgY29uc3Qgc2hvdWxkQ2xvc2VDb25uZWN0aW9uID0gdGhpcy5zaG91bGRDbG9zZUNvbm5lY3Rpb24ocmVxdWVzdClcblxuICAgICAgICB0aGlzLnJlcXVlc3RSdW5uZXJzLnNoaWZ0KClcbiAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoKCkgPT4gW1wic2VuZERvbmVSZXF1ZXN0cyBzaGlmdGVkIHF1ZXVlXCIsIHtjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudCwgcXVldWVMZW5ndGg6IHRoaXMucmVxdWVzdFJ1bm5lcnMubGVuZ3RofV0pXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5zZW5kUmVzcG9uc2UocmVxdWVzdFJ1bm5lcilcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcigoKSA9PiBbYFZlbG9jaW91cyBjbGllbnQgJHt0aGlzLmNsaWVudENvdW50fSBmYWlsZWQgd2hpbGUgc2VuZGluZyByZXNwb25zZWAsIGVycm9yXSlcbiAgICAgICAgICB0aHJvdyBlcnJvclxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRSZXF1ZXN0ID09PSByZXF1ZXN0ICYmIHRoaXMuc3RhdGUgPT09IFwiaW5pdGlhbFwiKSB0aGlzLmN1cnJlbnRSZXF1ZXN0ID0gdW5kZWZpbmVkXG4gICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKCgpID0+IFtcInNlbmREb25lUmVxdWVzdHNcIiwge2NsaWVudENvdW50OiB0aGlzLmNsaWVudENvdW50LCBjb25uZWN0aW9uSGVhZGVyLCBodHRwVmVyc2lvbn1dKVxuXG4gICAgICAgIGlmIChzaG91bGRDbG9zZUNvbm5lY3Rpb24pIHtcbiAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZygoKSA9PiBbYENsb3NpbmcgdGhlIGNvbm5lY3Rpb24gYmVjYXVzZSAke2h0dHBWZXJzaW9ufSBhbmQgY29ubmVjdGlvbiBoZWFkZXIgJHtjb25uZWN0aW9uSGVhZGVyfWAsIHtjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudH1dKVxuICAgICAgICAgIHRoaXMuZXZlbnRzLmVtaXQoXCJjbG9zZVwiKVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVha1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZW5kcyBhIGZpbmlzaGVkIHJlc3BvbnNlIHRvIHRoZSBjbGllbnQuIE93bnMgdGhlIGZyYW1ld29yay1vd25lZFxuICAgKiBgVmFyeTogQWNjZXB0LUVuY29kaW5nYCBkaW1lbnNpb24gKGVtaXR0ZWQgZm9yIGV2ZXJ5IHNlbGVjdGVkXG4gICAqIHJlcHJlc2VudGF0aW9uIOKAlCB0cmFuc2Zvcm1lZCwgaWRlbnRpdHksIDQwNiwgYW5kIGZpbGUg4oCUIGFuZCBmb3JcbiAgICogaGVhZGVyLXByZXNlbnQgYW5kIGhlYWRlci1hYnNlbnQgcmVxdWVzdHMgYWxpa2UsIHNvIGl0IGlzIHN0YWJsZSBhY3Jvc3NcbiAgICogcmVxdWVzdHMgb24gdGhlIHNhbWUgY29ubmVjdGlvbjsgbmV2ZXIgYWRkZWQgd2hlbiBjb21wcmVzc2lvbiBpcyBkaXNhYmxlZCxcbiAgICogdGhlIHJlc3BvbnNlIGlzIHRydWx5IGJvZHlsZXNzLCBvciB0aGUgYXBwbGljYXRpb24gc3VwcGxpZWQgYSBmaXhlZFxuICAgKiBgQ29udGVudC1FbmNvZGluZ2ApIGFuZCB0aGUgZmlsZSA0MDYgcnVsZSAoYSBzZW5kRmlsZSByZXNwb25zZSB3aG9zZVxuICAgKiBjbGllbnQgZm9yYmlkcyBpZGVudGl0eSBpcyBhbnN3ZXJlZCB3aXRoIHRoZSBlbXB0eSA0MDYsIHRoZSBmaWxlIGlzIG5ldmVyXG4gICAqIG9wZW5lZCBvciBzdHJlYW1lZCwgYW5kIGBvbkZpbmlzaGVkYCBzZXR0bGVzIG9uY2UgYXMgXCJjb21wbGV0ZWRcIikuXG4gICAqIEBwYXJhbSB7UmVxdWVzdFJ1bm5lcn0gcmVxdWVzdFJ1bm5lciAtIFJlcXVlc3QgcnVubmVyLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbXBsZXRlLlxuICAgKi9cbiAgYXN5bmMgc2VuZFJlc3BvbnNlKHJlcXVlc3RSdW5uZXIpIHtcbiAgICBjb25zdCByZXNwb25zZSA9IGRpZ2cocmVxdWVzdFJ1bm5lciwgXCJyZXNwb25zZVwiKVxuICAgIGNvbnN0IHJlcXVlc3QgPSByZXF1ZXN0UnVubmVyLmdldFJlcXVlc3QoKVxuICAgIGNvbnN0IGZpbGVQYXRoID0gcmVzcG9uc2UuZ2V0RmlsZVBhdGgoKVxuICAgIGNvbnN0IGZpbGVPbkZpbmlzaGVkID0gcmVzcG9uc2UuZ2V0RmlsZU9uRmluaXNoZWQoKVxuICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZSgpXG4gICAgY29uc3QgY29ubmVjdGlvbkhlYWRlciA9IHJlcXVlc3QuaGVhZGVyKFwiY29ubmVjdGlvblwiKT8udG9Mb3dlckNhc2UoKT8udHJpbSgpXG4gICAgY29uc3QgaHR0cFZlcnNpb24gPSByZXF1ZXN0Lmh0dHBWZXJzaW9uKClcbiAgICBjb25zdCBzaG91bGRDbG9zZUNvbm5lY3Rpb24gPSB0aGlzLnNob3VsZENsb3NlQ29ubmVjdGlvbihyZXF1ZXN0KVxuICAgIGNvbnN0IGhhc0ZpbGVQYXRoID0gdHlwZW9mIGZpbGVQYXRoID09PSBcInN0cmluZ1wiICYmIGZpbGVQYXRoLmxlbmd0aCA+IDBcbiAgICBjb25zdCBib2R5ID0gaGFzRmlsZVBhdGggPyBudWxsIDogcmVzcG9uc2UuZ2V0Qm9keSgpXG4gICAgY29uc3QgYm9keUlzU3RyaW5nID0gdHlwZW9mIGJvZHkgPT09IFwic3RyaW5nXCJcbiAgICBjb25zdCBib2R5SXNCaW5hcnkgPSBib2R5IGluc3RhbmNlb2YgVWludDhBcnJheVxuXG4gICAgaWYgKCFoYXNGaWxlUGF0aCAmJiAhYm9keUlzU3RyaW5nICYmICFib2R5SXNCaW5hcnkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgcmVzcG9uc2UgYm9keSB0byBiZSBhIHN0cmluZyBvciBVaW50OEFycmF5LCBnb3QgJHt0eXBlb2YgYm9keX1gKVxuICAgIH1cblxuICAgIHRoaXMubG9nZ2VyLmRlYnVnKFwic2VuZFJlc3BvbnNlXCIsIHtjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudCwgY29ubmVjdGlvbkhlYWRlciwgaHR0cFZlcnNpb259KVxuICAgIHRoaXMubG9nZ2VyLmRlYnVnKCgpID0+IFtcInNlbmRSZXNwb25zZSBwYXlsb2FkXCIsIHtcbiAgICAgIGNsaWVudENvdW50OiB0aGlzLmNsaWVudENvdW50LFxuICAgICAgaGFzRmlsZVBhdGgsXG4gICAgICBmaWxlUGF0aCxcbiAgICAgIGJvZHlJc0JpbmFyeSxcbiAgICAgIGJvZHlJc1N0cmluZ1xuICAgIH1dKVxuXG4gICAgaWYgKHNob3VsZENsb3NlQ29ubmVjdGlvbikge1xuICAgICAgcmVzcG9uc2Uuc2V0SGVhZGVyKFwiQ29ubmVjdGlvblwiLCBcIkNsb3NlXCIpXG4gICAgfSBlbHNlIGlmIChodHRwVmVyc2lvbiA9PSBcIjEuMFwiICYmIGNvbm5lY3Rpb25IZWFkZXIgPT0gXCJrZWVwLWFsaXZlXCIpIHtcbiAgICAgIHJlc3BvbnNlLnNldEhlYWRlcihcIkNvbm5lY3Rpb25cIiwgXCJLZWVwLUFsaXZlXCIpXG4gICAgfVxuXG4gICAgLy8gUGVyIFJGQyA3MjMwIMKnMy4zLjMsIHJlc3BvbnNlcyB3aXRoIHN0YXR1cyBjb2RlcyAxeHgsIDIwNCwgYW5kIDMwNFxuICAgIC8vIE1VU1QgTk9UIGNhcnJ5IGEgbWVzc2FnZSBib2R5IGFuZCBNVVNUIE5PVCBpbmNsdWRlIENvbnRlbnQtTGVuZ3RoXG4gICAgLy8gKHdpdGggYSBuYXJyb3cgMzA0IGV4Y2VwdGlvbiB3ZSBkb24ndCBsZWFuIG9uKS4gU2VuZGluZyBvbmUgd291bGRcbiAgICAvLyBkZXN5bmNocm9uaXplIGtlZXAtYWxpdmUgY2xpZW50cyB3YWl0aW5nIGZvciBieXRlcyB0aGF0IG5ldmVyXG4gICAgLy8gYXJyaXZlIOKAlCBkcm9wIHRoZSBib2R5IGVudGlyZWx5IGZvciB0aG9zZSBjb2Rlcy5cbiAgICBjb25zdCBpc0JvZHlsZXNzU3RhdHVzID0gaXNOb0JvZHlTdGF0dXNDb2RlKHJlc3BvbnNlLmdldFN0YXR1c0NvZGUoKSlcblxuICAgIC8vIEhFQUQgcmVzcG9uc2VzIHNlbGVjdCBhbmQgY29tcHV0ZSB0aGUgZXhhY3Qgc2FtZSByZXByZXNlbnRhdGlvbiBoZWFkZXJzIGFzIHRoZVxuICAgIC8vIGVxdWl2YWxlbnQgR0VUIChpbmNsdWRpbmcgQ29udGVudC1MZW5ndGggYW5kIGFueSBuZWdvdGlhdGVkIENvbnRlbnQtRW5jb2RpbmcpLFxuICAgIC8vIGJ1dCBubyBidWZmZXJlZCBvciBmaWxlIGJvZHkgaXMgZW1pdHRlZCBiZWxvdy5cbiAgICBjb25zdCBpc0hlYWRSZXF1ZXN0ID0gcmVxdWVzdC5odHRwTWV0aG9kKCkgPT0gXCJIRUFEXCJcblxuICAgIC8qKiBAdHlwZSB7c3RyaW5nIHwgVWludDhBcnJheSB8IG51bGx9ICovXG4gICAgbGV0IGJvZHlUb0VtaXQgPSBib2R5XG5cbiAgICAvLyBUaGUgcmVzcG9uc2UgcmVwcmVzZW50YXRpb24gY2FuIGRlcGVuZCBvbiB0aGUgY2xpZW50J3MgQWNjZXB0LUVuY29kaW5nOlxuICAgIC8vIHRoZSBzYW1lIHJlcXVlc3QgaXMgYW5zd2VyZWQgd2l0aCBhbiBpZGVudGl0eSBib2R5IChvciBhIGZpbGUpIHdoZW5cbiAgICAvLyBpZGVudGl0eSBpcyBhY2NlcHRhYmxlIGFuZCB3aXRoIGFuIGVtcHR5IDQwNiB3aGVuIGl0IGlzIGZvcmJpZGRlbi5cbiAgICBjb25zdCBjb21wcmVzc2lvbiA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRIdHRwU2VydmVyQ29tcHJlc3Npb24oKVxuICAgIGNvbnN0IG5lZ290aWF0ZWQgPSBjb21wcmVzc2lvbi5lbmFibGVkID8gbmVnb3RpYXRlQ29udGVudEVuY29kaW5nKHJlcXVlc3QuaGVhZGVyKFwiYWNjZXB0LWVuY29kaW5nXCIpKSA6IHVuZGVmaW5lZFxuICAgIC8vIEFuIGFwcGxpY2F0aW9uLXN1cHBsaWVkIENvbnRlbnQtRW5jb2RpbmcgaXMgYW4gYXBwbGljYXRpb24tb3duZWRcbiAgICAvLyByZXByZXNlbnRhdGlvbiBjb250cmFjdCwgY2FwdHVyZWQgYmVmb3JlIHRoZSBmcmFtZXdvcmsgbWF5IGFkZCBpdHMgb3duLlxuICAgIC8vIEEgZmlsZSBjYXJyeWluZyBvbmUgaXMgYSBmaXhlZCwgYXBwbGljYXRpb24tb3duZWQgcmVwcmVzZW50YXRpb246IHRoZVxuICAgIC8vIGZyYW1ld29yayBuZWl0aGVyIG5lZ290aWF0ZXMgaXQgbm9yIHJlLWFkdmVydGlzZXMgaXQsIHNvIGl0IGlzIG5ldmVyIGFcbiAgICAvLyBjYW5kaWRhdGUgZm9yIHRoZSBpZGVudGl0eS1vbmx5IDQwNi5cbiAgICBjb25zdCBoYXNBcHBsaWNhdGlvbkNvbnRlbnRFbmNvZGluZyA9IHJlc3BvbnNlLmdldEhlYWRlcihcIkNvbnRlbnQtRW5jb2RpbmdcIikubGVuZ3RoID4gMFxuICAgIC8vIEEgZmlsZSByZXNwb25zZSBvbmx5IGV2ZXIgc2VydmVzIHRoZSBpZGVudGl0eSByZXByZXNlbnRhdGlvbjogd2hlbmV2ZXJcbiAgICAvLyB0aGUgY2xpZW50IGZvcmJpZHMgaWRlbnRpdHkgKGluY2x1ZGluZyB0aGUgbm90LWFjY2VwdGFibGUgY2FzZSB3aGVyZSBub1xuICAgIC8vIGNvZGluZyBhcHBsaWVzKSBhbmQgdGhlIGZpbGUgZG9lcyBub3QgY2FycnkgYW4gYXBwbGljYXRpb24tc3VwcGxpZWRcbiAgICAvLyBDb250ZW50LUVuY29kaW5nLCB0aGUgZmlsZSBpcyByZWplY3RlZCB3aXRoIHRoZSBlbXB0eSA0MDYuIEEgdHJ1bHlcbiAgICAvLyBib2R5bGVzcyBzdGF0dXMgc2VsZWN0cyBubyByZXByZXNlbnRhdGlvbiwgc28gaXQgaXMgbmV2ZXIgcmVqZWN0ZWQgaGVyZS5cbiAgICBjb25zdCBpc0ZpbGVOb3RBY2NlcHRhYmxlID0gaGFzRmlsZVBhdGggJiYgISFuZWdvdGlhdGVkICYmIChcIm5vdEFjY2VwdGFibGVcIiBpbiBuZWdvdGlhdGVkIHx8IG5lZ290aWF0ZWQuaWRlbnRpdHlBY2NlcHRhYmxlID09PSBmYWxzZSkgJiYgaGFzQXBwbGljYXRpb25Db250ZW50RW5jb2RpbmcgPT09IGZhbHNlICYmICFpc0JvZHlsZXNzU3RhdHVzXG5cbiAgICBpZiAoIWlzQm9keWxlc3NTdGF0dXMpIHtcbiAgICAgIGxldCBjb250ZW50TGVuZ3RoXG5cbiAgICAgIGlmIChoYXNGaWxlUGF0aCkge1xuICAgICAgICBpZiAoaXNGaWxlTm90QWNjZXB0YWJsZSkge1xuICAgICAgICAgIC8vIFRoZSBjbGllbnQgZm9yYmlkcyBpZGVudGl0eSBhbmQgZmlsZXMgYXJlIG9ubHkgZXZlciBzZW50IGlkZW50aXR5OlxuICAgICAgICAgIC8vIGFuc3dlciB3aXRoIHRoZSBzYW1lIGVtcHR5IDQwNiBldmVyeSBvdGhlciByZXByZXNlbnRhdGlvbiBwYXRoXG4gICAgICAgICAgLy8gdXNlcy4gVGhlIGZpbGUgaXMgbmV2ZXIgb3BlbmVkIG9yIHN0cmVhbWVkOyBvbkZpbmlzaGVkIGlzIHNldHRsZWRcbiAgICAgICAgICAvLyBiZWxvdywgYWZ0ZXIgdGhlIGNvbW1pdHRlZCA0MDYgaGVhZGVycyBhcmUgZW1pdHRlZC5cbiAgICAgICAgICByZXNwb25zZS5zZXRTdGF0dXMoNDA2KVxuICAgICAgICAgIHJlc3BvbnNlLnNldEJvZHkoXCJcIilcbiAgICAgICAgICBib2R5VG9FbWl0ID0gXCJcIlxuICAgICAgICAgIGNvbnRlbnRMZW5ndGggPSAwXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3Qgc3RhdHMgPSBhd2FpdCBmcy5zdGF0KGZpbGVQYXRoKVxuICAgICAgICAgIGNvbnRlbnRMZW5ndGggPSBzdGF0cy5zaXplXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFN0cmluZyBib2RpZXMgYXJlIFVURi04IGZyYW1lZCwgc28gdGhlIGJ1ZmZlcmVkIGJ5dGVzIGFyZSB0aGUgVVRGLTggZW5jb2Rpbmc7XG4gICAgICAgIC8vIFVpbnQ4QXJyYXkgYm9kaWVzIGFyZSBhbHJlYWR5IHRoZSBleGFjdCB3aXJlIGJ5dGVzLlxuICAgICAgICBjb25zdCBib2R5QnVmZmVyID0gYm9keUlzU3RyaW5nID8gQnVmZmVyLmZyb20oYm9keSwgXCJ1dGY4XCIpIDogQnVmZmVyLmZyb20oYm9keSlcbiAgICAgICAgY29uc3QgY29tcHJlc3Npb25SZXN1bHQgPSBhd2FpdCBhcHBseVJlc3BvbnNlQ29tcHJlc3Npb24oe1xuICAgICAgICAgIGJvZHlCdWZmZXIsXG4gICAgICAgICAgY29tcHJlc3Npb246IHRoaXMuY29uZmlndXJhdGlvbi5nZXRIdHRwU2VydmVyQ29tcHJlc3Npb24oKSxcbiAgICAgICAgICByZXF1ZXN0LFxuICAgICAgICAgIHJlc3BvbnNlXG4gICAgICAgIH0pXG5cbiAgICAgICAgaWYgKGNvbXByZXNzaW9uUmVzdWx0Lm91dGNvbWUgPT0gXCJub3QtYWNjZXB0YWJsZVwiKSB7XG4gICAgICAgICAgLy8gVGhlIGNsaWVudCBmb3JiaWRzIGlkZW50aXR5IGFuZCBubyBzdXBwb3J0ZWQgY29kaW5nIGlzIGFjY2VwdGFibGU6IGFuc3dlclxuICAgICAgICAgIC8vIHdpdGggYW4gZW1wdHkgNDA2IGluc3RlYWQgb2YgYW4gdW5hY2NlcHRhYmxlIHJlcHJlc2VudGF0aW9uLlxuICAgICAgICAgIHJlc3BvbnNlLnNldFN0YXR1cyg0MDYpXG4gICAgICAgICAgcmVzcG9uc2Uuc2V0Qm9keShcIlwiKVxuICAgICAgICAgIGJvZHlUb0VtaXQgPSBcIlwiXG4gICAgICAgICAgY29udGVudExlbmd0aCA9IDBcbiAgICAgICAgfSBlbHNlIGlmIChjb21wcmVzc2lvblJlc3VsdC5vdXRjb21lID09IFwiY29tcHJlc3NlZFwiKSB7XG4gICAgICAgICAgYm9keVRvRW1pdCA9IGNvbXByZXNzaW9uUmVzdWx0LmJvZHlcbiAgICAgICAgICBjb250ZW50TGVuZ3RoID0gY29tcHJlc3Npb25SZXN1bHQuYm9keS5sZW5ndGhcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb250ZW50TGVuZ3RoID0gYm9keUJ1ZmZlci5sZW5ndGhcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBSZW1vdmUgYW55IGFwcGxpY2F0aW9uIHByZS1zZXQgQ29udGVudC1MZW5ndGggKGFueSBjYXNpbmcpIHNvIGV4YWN0bHkgb25lXG4gICAgICAvLyByZWNvbXB1dGVkIHZhbHVlIGdvZXMgb24gdGhlIHdpcmUuXG4gICAgICByZXNwb25zZS5yZW1vdmVIZWFkZXIoXCJDb250ZW50LUxlbmd0aFwiKVxuICAgICAgcmVzcG9uc2Uuc2V0SGVhZGVyKFwiQ29udGVudC1MZW5ndGhcIiwgY29udGVudExlbmd0aClcbiAgICB9XG5cbiAgICAvLyBGcmFtZXdvcmstb3duZWQgVmFyeSBkaW1lbnNpb246IHdoZW5ldmVyIGNvbXByZXNzaW9uIGlzIGVuYWJsZWQgYW5kIGFcbiAgICAvLyByZXByZXNlbnRhdGlvbiB3YXMgc2VsZWN0ZWQsIHRoZSByZXNwb25zZSBkZXBlbmRzIG9uIEFjY2VwdC1FbmNvZGluZyxcbiAgICAvLyBzbyBjYWNoZXMgbXVzdCBrZXkgb24gaXQuIEFwcGxpZWQgaWRlbnRpY2FsbHkgZm9yIGV2ZXJ5IG91dGNvbWVcbiAgICAvLyAodHJhbnNmb3JtZWQsIGlkZW50aXR5LCA0MDYsIGZpbGUpIGFuZCBmb3IgaGVhZGVyLXByZXNlbnQgYW5kXG4gICAgLy8gaGVhZGVyLWFic2VudCByZXF1ZXN0cyBhbGlrZSwgc28gdGhlIGhlYWRlciBpcyBzdGFibGUgYWNyb3NzIHJlcXVlc3RzIG9uXG4gICAgLy8gdGhlIHNhbWUgY29ubmVjdGlvbi4gQSB0cnVseSBib2R5bGVzcyByZXNwb25zZSBzZWxlY3RzIG5vIHJlcHJlc2VudGF0aW9uXG4gICAgLy8gYW5kIGNhcnJpZXMgbm8gZGltZW5zaW9uOyBhbiBhcHBsaWNhdGlvbi1zdXBwbGllZCBDb250ZW50LUVuY29kaW5nIGtlZXBzXG4gICAgLy8gdGhlIHJlcHJlc2VudGF0aW9uIGNvbnRyYWN0IGFwcGxpY2F0aW9uLW93bmVkIGFuZCBpcyBuZXZlciByZS1hZHZlcnRpc2VkLlxuICAgIGlmIChuZWdvdGlhdGVkICYmICFpc0JvZHlsZXNzU3RhdHVzICYmIGhhc0FwcGxpY2F0aW9uQ29udGVudEVuY29kaW5nID09PSBmYWxzZSkge1xuICAgICAgYWRkQWNjZXB0RW5jb2RpbmdUb1ZhcnkocmVzcG9uc2UpXG4gICAgfVxuXG4gICAgcmVzcG9uc2Uuc2V0SGVhZGVyKFwiRGF0ZVwiLCBkYXRlLnRvVVRDU3RyaW5nKCkpXG4gICAgcmVzcG9uc2Uuc2V0SGVhZGVyKFwiU2VydmVyXCIsIFwiVmVsb2Npb3VzXCIpXG5cbiAgICBsZXQgaGVhZGVycyA9IFwiXCJcblxuICAgIGhlYWRlcnMgKz0gYEhUVFAvJHtyZXF1ZXN0Lmh0dHBWZXJzaW9uKCl9ICR7cmVzcG9uc2UuZ2V0U3RhdHVzQ29kZSgpfSAke3Jlc3BvbnNlLmdldFN0YXR1c01lc3NhZ2UoKX1cXHJcXG5gXG5cbiAgICBmb3IgKGNvbnN0IGhlYWRlcktleSBpbiByZXNwb25zZS5oZWFkZXJzKSB7XG4gICAgICBmb3IgKGNvbnN0IGhlYWRlclZhbHVlIG9mIHJlc3BvbnNlLmhlYWRlcnNbaGVhZGVyS2V5XSkge1xuICAgICAgICBoZWFkZXJzICs9IGAke2hlYWRlcktleX06ICR7aGVhZGVyVmFsdWV9XFxyXFxuYFxuICAgICAgfVxuICAgIH1cblxuICAgIGhlYWRlcnMgKz0gXCJcXHJcXG5cIlxuXG4gICAgdGhpcy5ldmVudHMuZW1pdChcIm91dHB1dFwiLCBoZWFkZXJzKVxuICAgIHRoaXMubG9nZ2VyLmRlYnVnKCgpID0+IFtcInNlbmRSZXNwb25zZSBoZWFkZXJzIGVtaXR0ZWRcIiwge2NsaWVudENvdW50OiB0aGlzLmNsaWVudENvdW50LCBoZWFkZXJzTGVuZ3RoOiBoZWFkZXJzLmxlbmd0aH1dKVxuXG4gICAgLy8gQSBuZWdvdGlhdGVkIGZpbGUgNDA2IGlzIGNvbW1pdHRlZCBhYm92ZSAoc3RhdHVzIDQwNiwgZW1wdHkgYm9keSkgYW5kIGl0c1xuICAgIC8vIGhlYWRlcnMgd2VyZSBqdXN0IGVtaXR0ZWQ6IHNldHRsZSBvbkZpbmlzaGVkIG5vdywgc28gdGhlIGNhbGxiYWNrIHJ1bnNcbiAgICAvLyBhZnRlciB0aGUgcmVzcG9uc2UgaXMgY29tbWl0dGVkIOKAlCBhIHNsb3cgb3IgYXBwLXN0b3BwaW5nIGNhbGxiYWNrIGNhbm5vdFxuICAgIC8vIGRlbGF5IG9yIGJsb2NrIGRlbGl2ZXJ5IG9mIHRoZSBhbHJlYWR5LWVtaXR0ZWQgNDA2LiBUaGUgZmlsZSBpcyBuZXZlclxuICAgIC8vIG9wZW5lZCwgc3RyZWFtZWQsIG9yIHJlcG9ydGVkIChubyBmaWxlIGV2ZW50KSwgYW5kIHRoZSBjYWxsYmFjayBzZXR0bGVzXG4gICAgLy8gZXhhY3RseSBvbmNlIGFzIFwiY29tcGxldGVkXCIuXG4gICAgaWYgKGlzRmlsZU5vdEFjY2VwdGFibGUpIHtcbiAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKCgpID0+IFtcInNlbmRSZXNwb25zZSBmaWxlIGJvZHkgc3VwcHJlc3NlZCBmb3IgNDA2XCIsIHtjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudCwgZmlsZVBhdGh9XSlcbiAgICAgIGF3YWl0IHRoaXMucnVuRmlsZU9uRmluaXNoZWQoe2ZpbGVQYXRoLCBvbkZpbmlzaGVkOiBmaWxlT25GaW5pc2hlZCwgcmVzdWx0OiBcImNvbXBsZXRlZFwifSlcbiAgICB9IGVsc2UgaWYgKGlzQm9keWxlc3NTdGF0dXMpIHtcbiAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKCgpID0+IFtcInNlbmRSZXNwb25zZSBib2R5IHN1cHByZXNzZWQgZm9yIG5vLWJvZHkgc3RhdHVzXCIsIHtjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudCwgc3RhdHVzQ29kZTogcmVzcG9uc2UuZ2V0U3RhdHVzQ29kZSgpfV0pXG4gICAgICAvLyBBIGJvZHlsZXNzIHN0YXR1cyAoMXh4LzIwNC8zMDQpIHNlbGVjdHMgbm8gcmVwcmVzZW50YXRpb24sIHNvIG5vIGZpbGVcbiAgICAgIC8vIGJvZHkgb3IgZnJhbWV3b3JrIFZhcnkgaXMgZW1pdHRlZC4gVGhlIGZpbGUtb3duZXJzaGlwIHBhdGggc3RpbGwgc2V0dGxlc1xuICAgICAgLy8gb25GaW5pc2hlZCBleGFjdGx5IG9uY2UgYXMgXCJjb21wbGV0ZWRcIiAobm90aGluZyB3YXMgYWJvcnRlZCkg4oCUIGV2ZW4gd2hlblxuICAgICAgLy8gdGhlIGNsaWVudCBmb3JiaWRzIGlkZW50aXR5IOKAlCBwcmVzZXJ2aW5nIHRoZSBwcmUtY2hhbmdlIHNldHRsZW1lbnQuXG4gICAgICBpZiAoaGFzRmlsZVBhdGgpIGF3YWl0IHRoaXMuc2VuZEZpbGVPdXRwdXQoZmlsZVBhdGgsIGZhbHNlLCBmaWxlT25GaW5pc2hlZClcbiAgICB9IGVsc2UgaWYgKGlzSGVhZFJlcXVlc3QpIHtcbiAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKCgpID0+IFtcInNlbmRSZXNwb25zZSBib2R5IHN1cHByZXNzZWQgZm9yIEhFQUQgcmVxdWVzdFwiLCB7Y2xpZW50Q291bnQ6IHRoaXMuY2xpZW50Q291bnR9XSlcbiAgICAgIGlmIChoYXNGaWxlUGF0aCkgYXdhaXQgdGhpcy5zZW5kRmlsZU91dHB1dChmaWxlUGF0aCwgZmFsc2UsIGZpbGVPbkZpbmlzaGVkKVxuICAgIH0gZWxzZSBpZiAoaGFzRmlsZVBhdGgpIHtcbiAgICAgIGF3YWl0IHRoaXMuc2VuZEZpbGVPdXRwdXQoZmlsZVBhdGgsIHRydWUsIGZpbGVPbkZpbmlzaGVkKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmV2ZW50cy5lbWl0KFwib3V0cHV0XCIsIGJvZHlUb0VtaXQpXG4gICAgICB0aGlzLmxvZ2dlci5kZWJ1ZygoKSA9PiBbXCJzZW5kUmVzcG9uc2UgYm9keSBlbWl0dGVkXCIsIHtjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudCwgYm9keUxlbmd0aDogYm9keVRvRW1pdCA/IGJvZHlUb0VtaXQubGVuZ3RoIDogMH1dKVxuICAgIH1cblxuICAgIGF3YWl0IHJlcXVlc3RSdW5uZXIubG9nQ29tcGxldGVkUmVxdWVzdCgpXG5cbiAgICBpZiAoXCJnZXRSZXF1ZXN0UGFyc2VyXCIgaW4gcmVxdWVzdCkge1xuICAgICAgY29uc3QgaHR0cFJlcXVlc3QgPSAvKiogQHR5cGUge2ltcG9ydChcIi4vcmVxdWVzdC5qc1wiKS5kZWZhdWx0fSAqLyAocmVxdWVzdClcbiAgICAgIGh0dHBSZXF1ZXN0LmdldFJlcXVlc3RQYXJzZXIoKS5kZXN0cm95KClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyBzZW5kIGZpbGUgb3V0cHV0LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gZmlsZVBhdGggLSBGaWxlIHBhdGguXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gc2VuZEJvZHkgLSBXaGV0aGVyIHRoZSBmaWxlIGJvZHkgc2hvdWxkIGJlIHNlbnQuXG4gICAqIEBwYXJhbSB7KChyZXN1bHQ6IFwiY29tcGxldGVkXCIgfCBcImFib3J0ZWRcIikgPT4gdm9pZCB8IFByb21pc2U8dm9pZD4pIHwgbnVsbH0gb25GaW5pc2hlZCAtIENvbXBsZXRpb24gY2FsbGJhY2suXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuXG4gICAqL1xuICBhc3luYyBzZW5kRmlsZU91dHB1dChmaWxlUGF0aCwgc2VuZEJvZHksIG9uRmluaXNoZWQpIHtcbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZygoKSA9PiBbXCJzZW5kRmlsZU91dHB1dCBzdGFydFwiLCB7Y2xpZW50Q291bnQ6IHRoaXMuY2xpZW50Q291bnQsIGZpbGVQYXRofV0pXG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgLyoqIEB0eXBlIHtQcm9taXNlPHZvaWQ+IHwgbnVsbH0gKi9cbiAgICAgIGxldCBzZXR0bGVtZW50ID0gbnVsbFxuICAgICAgY29uc3Qgc2V0dGxlID0gKC8qKiBAdHlwZSB7XCJjb21wbGV0ZWRcIiB8IFwiYWJvcnRlZFwifSAqLyB0cmFuc2ZlclJlc3VsdCkgPT4ge1xuICAgICAgICBpZiAoc2V0dGxlbWVudCkgcmV0dXJuIHNldHRsZW1lbnRcblxuICAgICAgICB0aGlzLnBlbmRpbmdGaWxlUmVzcG9uc2VzLmRlbGV0ZShzZXR0bGUpXG4gICAgICAgIHNldHRsZW1lbnQgPSB0aGlzLnJ1bkZpbGVPbkZpbmlzaGVkKHtmaWxlUGF0aCwgb25GaW5pc2hlZCwgcmVzdWx0OiB0cmFuc2ZlclJlc3VsdH0pXG4gICAgICAgICAgLmZpbmFsbHkoKCkgPT4gcmVzb2x2ZSh0cmFuc2ZlclJlc3VsdCkpXG5cbiAgICAgICAgcmV0dXJuIHNldHRsZW1lbnRcbiAgICAgIH1cblxuICAgICAgdGhpcy5wZW5kaW5nRmlsZVJlc3BvbnNlcy5hZGQoc2V0dGxlKVxuICAgICAgdGhpcy5ldmVudHMuZW1pdChcImZpbGVcIiwge2ZpbGVQYXRoLCBzZW5kQm9keSwgc2V0dGxlfSlcbiAgICB9KVxuXG4gICAgdGhpcy5sb2dnZXIuZGVidWcoKCkgPT4gW1wic2VuZEZpbGVPdXRwdXQgZG9uZVwiLCB7Y2xpZW50Q291bnQ6IHRoaXMuY2xpZW50Q291bnQsIGZpbGVQYXRoLCByZXN1bHR9XSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGEgZmlsZSBjb21wbGV0aW9uIGNhbGxiYWNrIHdpdGhvdXQgYWxsb3dpbmcgY2xlYW51cCBmYWlsdXJlcyB0byByZXBsYWNlIHRoZSBjb21taXR0ZWQgcmVzcG9uc2UuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gQ29tcGxldGlvbiBkZXRhaWxzLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXJncy5maWxlUGF0aCAtIEZpbGUgcGF0aC5cbiAgICogQHBhcmFtIHsoKHJlc3VsdDogXCJjb21wbGV0ZWRcIiB8IFwiYWJvcnRlZFwiKSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPikgfCBudWxsfSBhcmdzLm9uRmluaXNoZWQgLSBDb21wbGV0aW9uIGNhbGxiYWNrLlxuICAgKiBAcGFyYW0ge1wiY29tcGxldGVkXCIgfCBcImFib3J0ZWRcIn0gYXJncy5yZXN1bHQgLSBUcmFuc2ZlciByZXN1bHQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIGFmdGVyIGNhbGxiYWNrIGNsZWFudXAgYW5kIGVycm9yIHJlcG9ydGluZyBmaW5pc2guXG4gICAqL1xuICBhc3luYyBydW5GaWxlT25GaW5pc2hlZCh7ZmlsZVBhdGgsIG9uRmluaXNoZWQsIHJlc3VsdH0pIHtcbiAgICBpZiAoIW9uRmluaXNoZWQpIHJldHVyblxuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IG9uRmluaXNoZWQocmVzdWx0KVxuICAgIH0gY2F0Y2ggKGNhdWdodEVycm9yKSB7XG4gICAgICBjb25zdCBlcnJvciA9IGVuc3VyZUVycm9yKGNhdWdodEVycm9yKVxuXG4gICAgICBhd2FpdCB0aGlzLmxvZ2dlci5lcnJvcigoKSA9PiBbXCJGaWxlIHJlc3BvbnNlIG9uRmluaXNoZWQgY2FsbGJhY2sgZmFpbGVkXCIsIHtjbGllbnRDb3VudDogdGhpcy5jbGllbnRDb3VudCwgZmlsZVBhdGgsIHJlc3VsdH0sIGVycm9yXSlcblxuICAgICAgY29uc3QgZXJyb3JQYXlsb2FkID0ge1xuICAgICAgICBjb250ZXh0OiB7Y2xpZW50Q291bnQ6IHRoaXMuY2xpZW50Q291bnQsIGZpbGVQYXRoLCByZXN1bHQsIHN0YWdlOiBcInNlbmQtZmlsZS1vbi1maW5pc2hlZFwifSxcbiAgICAgICAgZXJyb3JcbiAgICAgIH1cblxuICAgICAgdGhpcy5jb25maWd1cmF0aW9uLmdldEVycm9yRXZlbnRzKCkuZW1pdChcImZyYW1ld29yay1lcnJvclwiLCBlcnJvclBheWxvYWQpXG4gICAgICB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0RXJyb3JFdmVudHMoKS5lbWl0KFwiYWxsLWVycm9yXCIsIHsuLi5lcnJvclBheWxvYWQsIGVycm9yVHlwZTogXCJmcmFtZXdvcmstZXJyb3JcIn0pXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFib3J0cyBhbGwgZmlsZSByZXNwb25zZXMgYXdhaXRpbmcgdHJhbnNwb3J0IGFja25vd2xlZGdlbWVudC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgYWZ0ZXIgcGVuZGluZyBjYWxsYmFja3Mgc2V0dGxlLlxuICAgKi9cbiAgYXN5bmMgYWJvcnRQZW5kaW5nRmlsZVJlc3BvbnNlcygpIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChbLi4udGhpcy5wZW5kaW5nRmlsZVJlc3BvbnNlc10ubWFwKChzZXR0bGUpID0+IHNldHRsZShcImFib3J0ZWRcIikpKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgc2hvdWxkIGNsb3NlIGNvbm5lY3Rpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9yZXF1ZXN0LmpzXCIpLmRlZmF1bHQgfCBpbXBvcnQoXCIuL3dlYnNvY2tldC1yZXF1ZXN0LmpzXCIpLmRlZmF1bHR9IHJlcXVlc3QgLSBSZXF1ZXN0IG9iamVjdC5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gV2hldGhlciB0aGUgY29ubmVjdGlvbiBzaG91bGQgYmUgY2xvc2VkLlxuICAgKi9cbiAgc2hvdWxkQ2xvc2VDb25uZWN0aW9uKHJlcXVlc3QpIHtcbiAgICBjb25zdCBodHRwVmVyc2lvbiA9IHJlcXVlc3QuaHR0cFZlcnNpb24oKVxuICAgIGNvbnN0IGNvbm5lY3Rpb25IZWFkZXIgPSByZXF1ZXN0LmhlYWRlcihcImNvbm5lY3Rpb25cIik/LnRvTG93ZXJDYXNlKCk/LnRyaW0oKVxuICAgIGNvbnN0IGNvbm5lY3Rpb25Ub2tlbnMgPSBjb25uZWN0aW9uSGVhZGVyXG4gICAgICA/IGNvbm5lY3Rpb25IZWFkZXIuc3BsaXQoXCIsXCIpLm1hcCgodG9rZW4pID0+IHRva2VuLnRyaW0oKSkuZmlsdGVyKEJvb2xlYW4pXG4gICAgICA6IFtdXG5cbiAgICBpZiAoaHR0cFZlcnNpb24gPT0gXCJ3ZWJzb2NrZXRcIikgcmV0dXJuIGZhbHNlXG4gICAgaWYgKGNvbm5lY3Rpb25Ub2tlbnMuaW5jbHVkZXMoXCJjbG9zZVwiKSkgcmV0dXJuIHRydWVcblxuICAgIGlmIChodHRwVmVyc2lvbiA9PSBcIjEuMFwiICYmIGNvbm5lY3Rpb25IZWFkZXIgIT0gXCJrZWVwLWFsaXZlXCIpIHJldHVybiB0cnVlXG5cbiAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBmb3IgdGhlIHN0YXR1cyBjb2RlcyB0aGF0IFJGQyA3MjMwIMKnMy4zLjMgZGVjbGFyZXNcbiAqIGNhbm5vdCBjYXJyeSBhIG1lc3NhZ2UgYm9keTogZXZlcnkgMXh4IGluZm9ybWF0aW9uYWwsIDIwNCBOb1xuICogQ29udGVudCwgYW5kIDMwNCBOb3QgTW9kaWZpZWQuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RhdHVzQ29kZSAtIEhUVFAgc3RhdHVzIGNvZGUuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBXaGV0aGVyIHRoZSBzdGF0dXMgY29kZSBmb3JiaWRzIGEgcmVzcG9uc2UgYm9keS5cbiAqL1xuZnVuY3Rpb24gaXNOb0JvZHlTdGF0dXNDb2RlKHN0YXR1c0NvZGUpIHtcbiAgcmV0dXJuIChzdGF0dXNDb2RlID49IDEwMCAmJiBzdGF0dXNDb2RlIDwgMjAwKSB8fCBzdGF0dXNDb2RlID09PSAyMDQgfHwgc3RhdHVzQ29kZSA9PT0gMzA0XG59XG4iXX0=