cdk-nextjs 0.6.1 → 0.7.0
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/.jsii +2467 -2714
- package/.jsii.tabl.json +1 -1
- package/API.md +1725 -1909
- package/CLAUDE.md +2 -1
- package/README.md +429 -130
- package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +152 -170
- package/assets/lambdas/redeploy-stage/redeploy-stage.lambda/index.js +875 -0
- package/docs/adapter-runtime.md +185 -0
- package/docs/breaking-changes.md +687 -4
- package/docs/caching-guide.md +156 -112
- package/docs/cdk-nextjs-cfn-exec-policy.json +2 -1
- package/docs/development-guide.md +1 -1
- package/docs/harness-coverage.md +598 -0
- package/docs/init-cache-deployment.md +32 -1
- package/docs/next-build-output-guide.md +30 -20
- package/examples/README.md +5 -1
- package/lib/adapter/__fixtures__/app-playground-base-path.json +4926 -0
- package/lib/adapter/__fixtures__/app-playground.json +4917 -0
- package/lib/adapter/__fixtures__/pages-i18n.json +1728 -0
- package/lib/adapter/adapter.mjs +1548 -185
- package/lib/adapter/adapter.test.js +106 -0
- package/lib/adapter/aws-cache-store.d.ts +489 -0
- package/lib/adapter/aws-cache-store.js +1004 -0
- package/lib/adapter/aws-cache-store.test.d.ts +1 -0
- package/lib/adapter/aws-cache-store.test.js +361 -0
- package/lib/adapter/build-outputs.d.ts +80 -0
- package/lib/adapter/build-outputs.js +852 -0
- package/lib/adapter/build-outputs.test.d.ts +1 -0
- package/lib/adapter/build-outputs.test.js +861 -0
- package/lib/adapter/cache-handler.d.ts +9 -2
- package/lib/adapter/cache-handler.js +72 -96
- package/lib/adapter/cache-handler.mjs +18956 -17774
- package/lib/adapter/cache-handler.test.js +263 -31
- package/lib/adapter/cache-kinds.d.ts +32 -0
- package/lib/adapter/cache-kinds.js +35 -0
- package/lib/adapter/cache-kinds.test.d.ts +1 -0
- package/lib/adapter/cache-kinds.test.js +69 -0
- package/lib/adapter/cache-utils.d.ts +90 -0
- package/lib/adapter/cache-utils.js +199 -4
- package/lib/adapter/cache-utils.test.d.ts +1 -0
- package/lib/adapter/cache-utils.test.js +179 -0
- package/lib/adapter/function-groups.d.ts +215 -0
- package/lib/adapter/function-groups.js +1099 -0
- package/lib/adapter/function-groups.test.d.ts +1 -0
- package/lib/adapter/function-groups.test.js +743 -0
- package/lib/adapter/init-cache.d.ts +6 -0
- package/lib/adapter/init-cache.js +245 -0
- package/lib/adapter/init-cache.test.d.ts +1 -0
- package/lib/adapter/init-cache.test.js +137 -0
- package/lib/adapter/local-file-cache-handler.d.ts +23 -0
- package/lib/adapter/local-file-cache-handler.js +52 -1
- package/lib/adapter/memory-cache-handler.d.ts +26 -17
- package/lib/adapter/memory-cache-handler.js +32 -50
- package/lib/adapter/memory-cache-handler.test.js +105 -85
- package/lib/adapter/s3-cache-handler.d.ts +179 -40
- package/lib/adapter/s3-cache-handler.js +807 -277
- package/lib/adapter/s3-cache-handler.test.js +1186 -31
- package/lib/adapter/use-cache-common.d.ts +90 -0
- package/lib/adapter/use-cache-common.js +250 -0
- package/lib/adapter/use-cache-common.test.d.ts +1 -0
- package/lib/adapter/use-cache-common.test.js +646 -0
- package/lib/adapter/use-cache-default-handler.d.ts +24 -0
- package/lib/adapter/use-cache-default-handler.js +90 -0
- package/lib/adapter/use-cache-default-handler.mjs +38645 -0
- package/lib/adapter/use-cache-handlers.test.d.ts +1 -0
- package/lib/adapter/use-cache-handlers.test.js +349 -0
- package/lib/adapter/use-cache-remote-handler.d.ts +26 -0
- package/lib/adapter/use-cache-remote-handler.js +186 -0
- package/lib/{image-optimization/handler.mjs → adapter/use-cache-remote-handler.mjs} +33572 -38798
- package/lib/generated-structs/OptionalNextjsApiProps.d.ts +59 -0
- package/lib/generated-structs/OptionalNextjsApiProps.js +3 -0
- package/lib/generated-structs/OptionalNextjsCacheProps.d.ts +15 -6
- package/lib/generated-structs/OptionalNextjsCacheProps.js +1 -1
- package/lib/generated-structs/OptionalNextjsContainersProps.d.ts +25 -11
- package/lib/generated-structs/OptionalNextjsContainersProps.js +1 -1
- package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +31 -9
- package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
- package/lib/generated-structs/OptionalNextjsPostDeployProps.d.ts +13 -0
- package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
- package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +11 -2
- package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.js +1 -1
- package/lib/index.d.ts +6 -7
- package/lib/index.js +2 -4
- package/lib/lambdas/post-deploy/post-deploy.lambda.js +3 -2
- package/lib/lambdas/post-deploy/prune-cache-bucket.d.ts +7 -3
- package/lib/lambdas/post-deploy/prune-cache-bucket.js +57 -71
- package/lib/lambdas/post-deploy/prune-cache-bucket.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-cache-bucket.test.js +114 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.js +23 -31
- package/lib/lambdas/post-deploy/prune-revalidation-table.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +71 -0
- package/lib/lambdas/post-deploy/prune-s3.d.ts +19 -3
- package/lib/lambdas/post-deploy/prune-s3.js +54 -15
- package/lib/lambdas/post-deploy/prune-s3.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-s3.test.js +255 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage-function.d.ts +13 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage-function.js +55 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.d.ts +24 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.js +68 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.d.ts +20 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.js +24 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.test.d.ts +1 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.test.js +93 -0
- package/lib/nextjs-api.d.ts +107 -18
- package/lib/nextjs-api.js +349 -39
- package/lib/nextjs-api.test.js +582 -1
- package/lib/nextjs-build/global-containers.Dockerfile +15 -10
- package/lib/nextjs-build/nextjs-build.d.ts +339 -63
- package/lib/nextjs-build/nextjs-build.js +684 -327
- package/lib/nextjs-build/nextjs-build.test.d.ts +1 -0
- package/lib/nextjs-build/nextjs-build.test.js +412 -0
- package/lib/nextjs-build/patch-fetch.js +1 -1
- package/lib/nextjs-build/patch-fetch.test.js +166 -11
- package/lib/nextjs-build/regional-containers.Dockerfile +17 -10
- package/lib/nextjs-cache.d.ts +82 -4
- package/lib/nextjs-cache.js +186 -10
- package/lib/nextjs-cache.test.js +176 -1
- package/lib/nextjs-compute/nextjs-compute-base-props.d.ts +21 -8
- package/lib/nextjs-compute/nextjs-compute-base-props.js +41 -1
- package/lib/nextjs-compute/nextjs-compute-base-props.test.d.ts +1 -0
- package/lib/nextjs-compute/nextjs-compute-base-props.test.js +44 -0
- package/lib/nextjs-compute/nextjs-containers.d.ts +19 -0
- package/lib/nextjs-compute/nextjs-containers.js +57 -20
- package/lib/nextjs-compute/nextjs-functions.d.ts +122 -7
- package/lib/nextjs-compute/nextjs-functions.js +113 -67
- package/lib/nextjs-compute/nextjs-functions.test.d.ts +1 -0
- package/lib/nextjs-compute/nextjs-functions.test.js +99 -0
- package/lib/nextjs-distribution.d.ts +194 -23
- package/lib/nextjs-distribution.js +535 -62
- package/lib/nextjs-distribution.test.d.ts +1 -0
- package/lib/nextjs-distribution.test.js +697 -0
- package/lib/nextjs-post-deploy.d.ts +23 -3
- package/lib/nextjs-post-deploy.js +14 -10
- package/lib/nextjs-post-deploy.test.d.ts +1 -0
- package/lib/nextjs-post-deploy.test.js +34 -0
- package/lib/nextjs-static-assets.d.ts +23 -4
- package/lib/nextjs-static-assets.js +29 -6
- package/lib/nextjs-static-assets.test.js +20 -1
- package/lib/root-constructs/nextjs-base-construct.d.ts +105 -45
- package/lib/root-constructs/nextjs-base-construct.js +144 -34
- package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
- package/lib/root-constructs/nextjs-global-containers.js +20 -70
- package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
- package/lib/root-constructs/nextjs-global-functions.js +52 -69
- package/lib/root-constructs/nextjs-regional-containers.d.ts +25 -5
- package/lib/root-constructs/nextjs-regional-containers.js +17 -15
- package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
- package/lib/root-constructs/nextjs-regional-functions.js +8 -25
- package/lib/runtime/api-gateway-path.d.ts +34 -0
- package/lib/runtime/api-gateway-path.js +71 -0
- package/lib/runtime/api-gateway-path.test.d.ts +1 -0
- package/lib/runtime/api-gateway-path.test.js +65 -0
- package/lib/runtime/case-redirect.d.ts +22 -0
- package/lib/runtime/case-redirect.js +63 -0
- package/lib/runtime/case-redirect.test.d.ts +1 -0
- package/lib/runtime/case-redirect.test.js +32 -0
- package/lib/runtime/core.d.ts +234 -0
- package/lib/runtime/core.js +1213 -0
- package/lib/runtime/core.test.d.ts +1 -0
- package/lib/runtime/core.test.js +1678 -0
- package/lib/runtime/deployment-root.d.ts +13 -0
- package/lib/runtime/deployment-root.js +29 -0
- package/lib/runtime/dispatch.d.ts +331 -0
- package/lib/runtime/dispatch.js +751 -0
- package/lib/runtime/dispatch.test.d.ts +1 -0
- package/lib/runtime/dispatch.test.js +853 -0
- package/lib/runtime/entrypoints.d.ts +57 -0
- package/lib/runtime/entrypoints.js +115 -0
- package/lib/runtime/http/abort-signal.d.ts +6 -0
- package/lib/runtime/http/abort-signal.js +19 -0
- package/lib/runtime/http/abort-signal.test.d.ts +1 -0
- package/lib/runtime/http/abort-signal.test.js +49 -0
- package/lib/runtime/http/node-server.d.ts +38 -0
- package/lib/runtime/http/node-server.js +99 -0
- package/lib/runtime/http/node-server.test.d.ts +1 -0
- package/lib/runtime/http/node-server.test.js +96 -0
- package/lib/runtime/http/node-sink.d.ts +16 -0
- package/lib/runtime/http/node-sink.js +48 -0
- package/lib/runtime/http/node-sink.test.d.ts +1 -0
- package/lib/runtime/http/node-sink.test.js +66 -0
- package/lib/runtime/http/request.d.ts +62 -0
- package/lib/runtime/http/request.js +134 -0
- package/lib/runtime/http/request.test.d.ts +1 -0
- package/lib/runtime/http/request.test.js +103 -0
- package/lib/runtime/http/response.d.ts +77 -0
- package/lib/runtime/http/response.js +229 -0
- package/lib/runtime/http/response.test.d.ts +1 -0
- package/lib/runtime/http/response.test.js +178 -0
- package/lib/runtime/http/sink.d.ts +73 -0
- package/lib/runtime/http/sink.js +188 -0
- package/lib/runtime/http/sink.test.d.ts +1 -0
- package/lib/runtime/http/sink.test.js +257 -0
- package/lib/runtime/image-utils.d.ts +78 -0
- package/lib/runtime/image-utils.js +129 -0
- package/lib/runtime/image-utils.test.d.ts +1 -0
- package/lib/runtime/image-utils.test.js +237 -0
- package/lib/runtime/image.d.ts +76 -0
- package/lib/runtime/image.js +296 -0
- package/lib/runtime/image.test.d.ts +1 -0
- package/lib/runtime/image.test.js +405 -0
- package/lib/runtime/lambda-event.d.ts +4 -0
- package/lib/runtime/lambda-event.js +113 -0
- package/lib/runtime/lambda-event.test.d.ts +1 -0
- package/lib/runtime/lambda-event.test.js +119 -0
- package/lib/runtime/lambda.mjs +41595 -0
- package/lib/runtime/load-module.d.ts +8 -0
- package/lib/runtime/load-module.js +35 -0
- package/lib/runtime/manifest.d.ts +215 -0
- package/lib/runtime/manifest.js +118 -0
- package/lib/runtime/middleware.d.ts +43 -0
- package/lib/runtime/middleware.js +113 -0
- package/lib/runtime/middleware.test.d.ts +1 -0
- package/lib/runtime/middleware.test.js +259 -0
- package/lib/runtime/next-modules.d.ts +55 -0
- package/lib/runtime/next-modules.js +124 -0
- package/lib/runtime/next-modules.test.d.ts +1 -0
- package/lib/runtime/next-modules.test.js +34 -0
- package/lib/runtime/public-files.d.ts +32 -0
- package/lib/runtime/public-files.js +117 -0
- package/lib/runtime/public-files.test.d.ts +1 -0
- package/lib/runtime/public-files.test.js +97 -0
- package/lib/runtime/server.mjs +41588 -0
- package/lib/runtime/static-files.d.ts +50 -0
- package/lib/runtime/static-files.js +266 -0
- package/lib/runtime/static-files.test.d.ts +1 -0
- package/lib/runtime/static-files.test.js +118 -0
- package/lib/runtime/util.d.ts +28 -0
- package/lib/runtime/util.js +79 -0
- package/lib/utils/base-path.d.ts +123 -11
- package/lib/utils/base-path.js +276 -39
- package/lib/utils/base-path.test.js +275 -50
- package/lib/utils/get-architecture.d.ts +7 -8
- package/lib/utils/get-architecture.js +12 -13
- package/lib/utils/zip-directory.d.ts +14 -0
- package/lib/utils/zip-directory.js +121 -0
- package/lib/utils/zip-directory.test.d.ts +1 -0
- package/lib/utils/zip-directory.test.js +99 -0
- package/package.json +22 -3
- package/scripts/capture-adapter-fixture.mjs +325 -0
- package/scripts/e2e-deploy.sh +398 -0
- package/scripts/e2e-harness/README.md +707 -0
- package/scripts/e2e-harness/app.js +370 -0
- package/scripts/e2e-harness/common.sh +249 -0
- package/scripts/e2e-harness/screen.mjs +302 -0
- package/scripts/e2e-harness/stage-proxy.mjs +145 -0
- package/scripts/e2e-harness/type-filters.mjs +47 -0
- package/scripts/e2e-logs.sh +75 -0
- package/scripts/e2e-offline.sh +91 -0
- package/scripts/e2e-sweep.sh +370 -0
- package/scripts/e2e-warm.sh +114 -0
- package/scripts/zero-config-build.mjs +418 -0
- package/docs/1k-concurrent-users-executions.png +0 -0
- package/docs/plans/adapter-runtime-release.md +0 -362
- package/docs/plans/phase-0-image-function-opt-in.md +0 -295
- package/lib/generated-structs/OptionalDockerImageFunctionProps.d.ts +0 -425
- package/lib/generated-structs/OptionalDockerImageFunctionProps.js +0 -3
- package/lib/image-optimization/handler-utils.d.ts +0 -34
- package/lib/image-optimization/handler-utils.js +0 -83
- package/lib/image-optimization/handler-utils.test.js +0 -178
- package/lib/nextjs-build/functions.Dockerfile +0 -31
- package/lib/nextjs-compute/nextjs-image-function.d.ts +0 -53
- package/lib/nextjs-compute/nextjs-image-function.js +0 -59
- package/lib/utils/experimental-flags.d.ts +0 -24
- package/lib/utils/experimental-flags.js +0 -30
- /package/lib/{image-optimization/handler-utils.test.d.ts → adapter/adapter.test.d.ts} +0 -0
|
@@ -0,0 +1,751 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Dispatcher = void 0;
|
|
4
|
+
exports.toRedirect = toRedirect;
|
|
5
|
+
exports.repairRouteParamQuery = repairRouteParamQuery;
|
|
6
|
+
exports.outOfBandRouteParams = outOfBandRouteParams;
|
|
7
|
+
exports.statusTargets = statusTargets;
|
|
8
|
+
/* eslint-disable import/no-extraneous-dependencies */
|
|
9
|
+
/**
|
|
10
|
+
* Request dispatch: URL in, routing decision out.
|
|
11
|
+
*
|
|
12
|
+
* All route matching is delegated to `@next/routing`'s `resolveRoutes`, the
|
|
13
|
+
* first-party package `next start` was refactored to expose. Reimplementing
|
|
14
|
+
* redirects/rewrites/i18n/dynamic-route matching is what previous versions of
|
|
15
|
+
* this construct did, and it is the thing this rewrite exists to delete.
|
|
16
|
+
*
|
|
17
|
+
* This module is pure decision-making: it never touches the filesystem, never
|
|
18
|
+
* requires an entrypoint, and never builds a `Response`. It returns a
|
|
19
|
+
* {@link DispatchResult} and the caller (the runtime core, step 4) acts on it.
|
|
20
|
+
* That split is what makes it unit-testable against the committed
|
|
21
|
+
* `onBuildComplete` fixtures with no AWS and no Next.js server.
|
|
22
|
+
*/
|
|
23
|
+
const routing_1 = require("@next/routing");
|
|
24
|
+
const manifest_1 = require("./manifest");
|
|
25
|
+
const public_files_1 = require("./public-files");
|
|
26
|
+
const util_1 = require("./util");
|
|
27
|
+
/**
|
|
28
|
+
* `ctx.routing` is persisted into the manifest verbatim and typed `unknown`
|
|
29
|
+
* there, because the manifest must not depend on `@next/routing` (it is also
|
|
30
|
+
* read at synth by the CDK constructs). Dispatch is the one place that knows
|
|
31
|
+
* the real shape, so the cast lives here.
|
|
32
|
+
*
|
|
33
|
+
* `ctx.routing` is a superset of `ResolveRoutesParams["routes"]` — it also
|
|
34
|
+
* carries `rsc` — which is why this is a cast and not an assignment.
|
|
35
|
+
*/
|
|
36
|
+
function asRoutes(routing) {
|
|
37
|
+
return routing;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Likewise for `i18n`: `NextConfigComplete["i18n"]` is wider than
|
|
41
|
+
* `ResolveRoutesParams["i18n"]` (extra fields, and `localeDetection?: boolean`
|
|
42
|
+
* against `false`), and the manifest stores the config value as-is.
|
|
43
|
+
*/
|
|
44
|
+
function asI18n(i18n) {
|
|
45
|
+
return i18n ? i18n : undefined;
|
|
46
|
+
}
|
|
47
|
+
class Dispatcher {
|
|
48
|
+
options;
|
|
49
|
+
/** The 404 to render for a request to a URL; see {@link statusTargets}. */
|
|
50
|
+
notFoundFor;
|
|
51
|
+
routes;
|
|
52
|
+
i18n;
|
|
53
|
+
table;
|
|
54
|
+
imagePathname;
|
|
55
|
+
trailingSlash;
|
|
56
|
+
constructor(options) {
|
|
57
|
+
this.options = options;
|
|
58
|
+
const { manifest } = options;
|
|
59
|
+
this.routes = asRoutes(manifest.routing);
|
|
60
|
+
this.i18n = asI18n(manifest.config.i18n);
|
|
61
|
+
this.trailingSlash = manifest.config.trailingSlash;
|
|
62
|
+
this.table = buildRoutingTable(manifest, options.publicFiles ?? []);
|
|
63
|
+
this.imagePathname = `${manifest.config.basePath}/_next/image`;
|
|
64
|
+
this.notFoundFor = statusTargets(manifest, 404);
|
|
65
|
+
}
|
|
66
|
+
get manifest() {
|
|
67
|
+
return this.options.manifest;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Drop the `trailingSlash` slash a resolved pathname may carry, so it can be
|
|
71
|
+
* looked up in `entrypoints`/`staticFiles` and rendered under the same cache
|
|
72
|
+
* key as its prerender. A no-op unless the app sets `trailingSlash`.
|
|
73
|
+
*/
|
|
74
|
+
normalizePathname(pathname) {
|
|
75
|
+
if (!this.trailingSlash || pathname === undefined)
|
|
76
|
+
return pathname;
|
|
77
|
+
return pathname.length > 1 && pathname.endsWith("/")
|
|
78
|
+
? pathname.slice(0, -1)
|
|
79
|
+
: pathname;
|
|
80
|
+
}
|
|
81
|
+
/** The request path with `basePath` removed, which is what i18n applies to. */
|
|
82
|
+
withoutBasePath(pathname) {
|
|
83
|
+
return (0, util_1.withoutPathPrefix)(pathname, this.manifest.config.basePath);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Put the locale in front of a request for the app's root *here*, when the
|
|
87
|
+
* locale is the one the request is already in.
|
|
88
|
+
*
|
|
89
|
+
* `resolveRoutes` prefixes the locale itself, as `${basePath}/${locale}${pathname}`
|
|
90
|
+
* — which for the root turns `/` into `/en-US/`. The slash-stripping 308 that
|
|
91
|
+
* `next build` always compiles into `routing.beforeMiddleware` then matches it,
|
|
92
|
+
* so `GET /` came back as a redirect no `next start` sends: measured against
|
|
93
|
+
* `test/e2e/i18n-support-catchall`, where `/` answers 200. Next.js's own router
|
|
94
|
+
* special-cases exactly this (`resolve-routes.ts`: `pathname === '/' ?
|
|
95
|
+
* `/${defaultLocale}` : …`).
|
|
96
|
+
*
|
|
97
|
+
* With `trailingSlash`, the prefixed root keeps its slash (`/en-US/`): the
|
|
98
|
+
* slash-*adding* 308 that build compiles instead matches `/en-US` the same
|
|
99
|
+
* way, and `/en-US/` is the canonical URL `next start` serves with a 200.
|
|
100
|
+
*
|
|
101
|
+
* Only the root, and only when no redirect is owed: a request whose detected
|
|
102
|
+
* locale is *not* the default has to reach `resolveRoutes`, which answers it
|
|
103
|
+
* with the 307 Next.js sends — after middleware has had the request, which is
|
|
104
|
+
* the ordering that matters and the reason this does not redirect itself.
|
|
105
|
+
*/
|
|
106
|
+
withRootLocale(url, headers) {
|
|
107
|
+
const i18n = this.i18n;
|
|
108
|
+
if (!i18n)
|
|
109
|
+
return url;
|
|
110
|
+
const pathname = this.withoutBasePath(url.pathname);
|
|
111
|
+
if (pathname !== "/")
|
|
112
|
+
return url;
|
|
113
|
+
const defaultLocale = (0, routing_1.detectDomainLocale)(i18n.domains, url.hostname)?.defaultLocale ??
|
|
114
|
+
i18n.defaultLocale;
|
|
115
|
+
const detected = (0, routing_1.detectLocale)({
|
|
116
|
+
pathname,
|
|
117
|
+
hostname: url.hostname,
|
|
118
|
+
cookieHeader: headers.get("cookie") ?? undefined,
|
|
119
|
+
acceptLanguageHeader: headers.get("accept-language") ?? undefined,
|
|
120
|
+
i18n,
|
|
121
|
+
});
|
|
122
|
+
if (detected.locale !== defaultLocale)
|
|
123
|
+
return url;
|
|
124
|
+
const prefixed = new URL(url.toString());
|
|
125
|
+
prefixed.pathname = `${this.manifest.config.basePath}/${defaultLocale}${this.trailingSlash ? "/" : ""}`;
|
|
126
|
+
return prefixed;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Repair the two things `resolveRoutes` gets wrong about a redirect it built
|
|
130
|
+
* from the locale-prefixed root — the same `${basePath}/${locale}${pathname}`
|
|
131
|
+
* concatenation as in {@link withRootLocale}, this time reported as a location:
|
|
132
|
+
*
|
|
133
|
+
* - the stray trailing slash (`/nl/`, where Next.js sends `/nl`), which
|
|
134
|
+
* otherwise costs a second round trip to the 308 that strips it, and
|
|
135
|
+
* - the absolute URL, where Next.js sends a path. Both are legal, but a test
|
|
136
|
+
* asserting `headers.location` sees the difference, and so does any client
|
|
137
|
+
* comparing it to a link.
|
|
138
|
+
*/
|
|
139
|
+
normalizeRedirectLocation(location, request) {
|
|
140
|
+
let resolved;
|
|
141
|
+
try {
|
|
142
|
+
resolved = new URL(location, request);
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return location;
|
|
146
|
+
}
|
|
147
|
+
if (resolved.origin !== request.origin)
|
|
148
|
+
return location;
|
|
149
|
+
const target = this.withoutBasePath(resolved.pathname);
|
|
150
|
+
const isLocaleRoot = this.i18n !== undefined &&
|
|
151
|
+
!this.trailingSlash &&
|
|
152
|
+
this.withoutBasePath(request.pathname) === "/" &&
|
|
153
|
+
this.i18n.locales.some((locale) => target === `/${locale}/`);
|
|
154
|
+
if (isLocaleRoot) {
|
|
155
|
+
resolved.pathname = resolved.pathname.slice(0, -1);
|
|
156
|
+
}
|
|
157
|
+
return `${resolved.pathname}${resolved.search}${resolved.hash}`;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* The `headers()` rules a request matched, for a response middleware wrote
|
|
161
|
+
* itself.
|
|
162
|
+
*
|
|
163
|
+
* They compile into `routing.beforeMiddleware`, and `resolveRoutes` applies
|
|
164
|
+
* them there, but when middleware answers it returns `{ middlewareResponded:
|
|
165
|
+
* true }` and nothing else, so they were lost: a middleware 401 went out
|
|
166
|
+
* without the app's HSTS and CSP. `next start` sends them with it (its
|
|
167
|
+
* `resolve-routes.js` sets them on the response before middleware runs). So
|
|
168
|
+
* that one phase is run again on its own — no middleware, no files, nothing
|
|
169
|
+
* after it — which leaves exactly the headers it set.
|
|
170
|
+
*/
|
|
171
|
+
async beforeMiddlewareHeaders(url, headers) {
|
|
172
|
+
const result = await (0, routing_1.resolveRoutes)({
|
|
173
|
+
url,
|
|
174
|
+
buildId: this.manifest.buildId,
|
|
175
|
+
basePath: this.manifest.config.basePath,
|
|
176
|
+
headers,
|
|
177
|
+
requestBody: new Blob([]).stream(),
|
|
178
|
+
pathnames: [],
|
|
179
|
+
routes: {
|
|
180
|
+
...this.routes,
|
|
181
|
+
middlewareMatchers: [],
|
|
182
|
+
beforeFiles: [],
|
|
183
|
+
afterFiles: [],
|
|
184
|
+
dynamicRoutes: [],
|
|
185
|
+
onMatch: [],
|
|
186
|
+
fallback: [],
|
|
187
|
+
},
|
|
188
|
+
i18n: this.i18n,
|
|
189
|
+
invokeMiddleware: async () => ({}),
|
|
190
|
+
});
|
|
191
|
+
const responseHeaders = new Headers(result.resolvedHeaders ?? undefined);
|
|
192
|
+
// A locale-detection redirect is decided after middleware, and middleware
|
|
193
|
+
// already answered, so its `location` is not owed.
|
|
194
|
+
if (result.redirect) {
|
|
195
|
+
responseHeaders.delete("location");
|
|
196
|
+
}
|
|
197
|
+
return responseHeaders;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* The URL to optimize, once `/_next/image` has resolved: as middleware
|
|
201
|
+
* rewrote it, or as received — or, when a `next.config` rewrite is what put
|
|
202
|
+
* the request on the image path, rebuilt from the query `resolveRoutes`
|
|
203
|
+
* resolved, which is the only place that rewrite's destination query is.
|
|
204
|
+
*/
|
|
205
|
+
imageUrl(result, received) {
|
|
206
|
+
if (received.pathname === this.imagePathname)
|
|
207
|
+
return received;
|
|
208
|
+
const url = new URL(received.toString());
|
|
209
|
+
url.pathname = this.imagePathname;
|
|
210
|
+
if (result.resolvedQuery) {
|
|
211
|
+
url.search = (0, util_1.toSearch)(result.resolvedQuery);
|
|
212
|
+
}
|
|
213
|
+
return url;
|
|
214
|
+
}
|
|
215
|
+
async dispatch(request) {
|
|
216
|
+
// Copied because `resolveRoutes` is free to mutate what it is handed, and
|
|
217
|
+
// the caller's headers object outlives this call.
|
|
218
|
+
const requestHeaders = new Headers(request.headers);
|
|
219
|
+
// A second copy, as the request reached `beforeMiddleware`, for
|
|
220
|
+
// {@link beforeMiddlewareHeaders}.
|
|
221
|
+
const receivedHeaders = new Headers(request.headers);
|
|
222
|
+
const url = this.withRootLocale(request.url, requestHeaders);
|
|
223
|
+
let middlewareRequestHeaders;
|
|
224
|
+
let middlewareRewrite;
|
|
225
|
+
let middlewareResponse;
|
|
226
|
+
const result = await (0, routing_1.resolveRoutes)({
|
|
227
|
+
url,
|
|
228
|
+
buildId: this.manifest.buildId,
|
|
229
|
+
basePath: this.manifest.config.basePath,
|
|
230
|
+
headers: requestHeaders,
|
|
231
|
+
requestBody: request.body,
|
|
232
|
+
pathnames: this.table.pathnames,
|
|
233
|
+
routes: this.routes,
|
|
234
|
+
i18n: this.i18n,
|
|
235
|
+
// Only called when a `middlewareMatchers` entry matches, which only a
|
|
236
|
+
// build with middleware has.
|
|
237
|
+
invokeMiddleware: async (ctx) => {
|
|
238
|
+
const { response, ...middleware } = await request.invokeMiddleware({
|
|
239
|
+
...ctx,
|
|
240
|
+
method: request.method,
|
|
241
|
+
});
|
|
242
|
+
middlewareResponse = response;
|
|
243
|
+
// `resolveRoutes` drops `MiddlewareResult.requestHeaders` entirely: it
|
|
244
|
+
// neither returns them nor mutates the `headers` passed in. Capturing
|
|
245
|
+
// them here is what keeps `NextResponse.next({ request: { headers } })`
|
|
246
|
+
// working.
|
|
247
|
+
if (middleware.requestHeaders) {
|
|
248
|
+
middlewareRequestHeaders = middleware.requestHeaders;
|
|
249
|
+
}
|
|
250
|
+
// Captured for the same reason: `resolveRoutes` routes the rewritten URL
|
|
251
|
+
// internally but never reports it back, and `/_next/image` is matched
|
|
252
|
+
// here rather than by `resolveRoutes` (see below), so this is the only
|
|
253
|
+
// way to see the path middleware actually asked for.
|
|
254
|
+
if (middleware.rewrite) {
|
|
255
|
+
middlewareRewrite = middleware.rewrite;
|
|
256
|
+
}
|
|
257
|
+
return middleware;
|
|
258
|
+
},
|
|
259
|
+
});
|
|
260
|
+
const responseHeaders = new Headers(result.resolvedHeaders ?? undefined);
|
|
261
|
+
// `@next/routing` echoes the rewrite it followed into `resolvedHeaders`;
|
|
262
|
+
// Next.js's own router consumes that header rather than sending it, and so do
|
|
263
|
+
// we — it is an internal routing signal, and forwarding it would expose the
|
|
264
|
+
// app's post-middleware paths to clients.
|
|
265
|
+
responseHeaders.delete("x-middleware-rewrite");
|
|
266
|
+
const forwardedHeaders = middlewareRequestHeaders ?? requestHeaders;
|
|
267
|
+
const status = result.status;
|
|
268
|
+
if (result.middlewareResponded && middlewareResponse) {
|
|
269
|
+
return {
|
|
270
|
+
kind: "middleware-responded",
|
|
271
|
+
response: middlewareResponse,
|
|
272
|
+
responseHeaders: await this.beforeMiddlewareHeaders(url, receivedHeaders),
|
|
273
|
+
status,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
if (result.externalRewrite) {
|
|
277
|
+
return {
|
|
278
|
+
kind: "external-rewrite",
|
|
279
|
+
url: result.externalRewrite,
|
|
280
|
+
requestHeaders: forwardedHeaders,
|
|
281
|
+
responseHeaders,
|
|
282
|
+
status,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
const redirect = toRedirect(result, responseHeaders);
|
|
286
|
+
if (redirect) {
|
|
287
|
+
return {
|
|
288
|
+
kind: "redirect",
|
|
289
|
+
...redirect,
|
|
290
|
+
location: this.normalizeRedirectLocation(redirect.location, request.url),
|
|
291
|
+
responseHeaders,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
// Both are keys into `entrypoints`/`staticFiles`, which never carry a
|
|
295
|
+
// trailing slash; see {@link withTrailingSlashVariants}.
|
|
296
|
+
const resolvedPathname = this.normalizePathname(result.resolvedPathname);
|
|
297
|
+
// In `pathnames` (see {@link buildRoutingTable}), so it resolves in the
|
|
298
|
+
// filesystem phase: after middleware and `beforeFiles`, and before any
|
|
299
|
+
// dynamic route, which is `next start`'s order. Unlisted, a root catch-all
|
|
300
|
+
// (`app/[...slug]`) or any two-segment dynamic route took every image
|
|
301
|
+
// request as `slug: ["_next", "image"]`.
|
|
302
|
+
if (resolvedPathname === this.imagePathname) {
|
|
303
|
+
return {
|
|
304
|
+
kind: "image-optimization",
|
|
305
|
+
url: this.imageUrl(result, middlewareRewrite ?? request.url),
|
|
306
|
+
requestHeaders: forwardedHeaders,
|
|
307
|
+
responseHeaders,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
if (resolvedPathname !== undefined) {
|
|
311
|
+
const staticFile = this.table.staticFiles.get(resolvedPathname);
|
|
312
|
+
const asStaticFile = (file) => ({
|
|
313
|
+
kind: "static-file",
|
|
314
|
+
pathname: resolvedPathname,
|
|
315
|
+
filePath: file.filePath,
|
|
316
|
+
source: file.source,
|
|
317
|
+
requestHeaders: forwardedHeaders,
|
|
318
|
+
responseHeaders,
|
|
319
|
+
status,
|
|
320
|
+
});
|
|
321
|
+
// Ahead of the entrypoints, which is `next start`'s order: its filesystem
|
|
322
|
+
// check tries `_next/static` and then `public/` before any app or page
|
|
323
|
+
// route, so `public/robots.txt` beats `app/robots.ts` and
|
|
324
|
+
// `public/favicon.ico` beats `app/favicon.ico`.
|
|
325
|
+
if (staticFile && staticFile.source !== "server") {
|
|
326
|
+
return asStaticFile(staticFile);
|
|
327
|
+
}
|
|
328
|
+
const entrypoint = this.manifest.entrypoints[resolvedPathname];
|
|
329
|
+
if (entrypoint) {
|
|
330
|
+
const query = repairRouteParamQuery(result.resolvedQuery ?? {}, result.routeMatches ?? {});
|
|
331
|
+
return {
|
|
332
|
+
kind: "entrypoint",
|
|
333
|
+
entrypoint,
|
|
334
|
+
resolvedPathname,
|
|
335
|
+
// `invocationTarget` is always present alongside `resolvedPathname` in
|
|
336
|
+
// practice; the fallback keeps a `next` shape change from crashing.
|
|
337
|
+
invocationTarget: {
|
|
338
|
+
pathname: this.normalizePathname(result.invocationTarget?.pathname) ??
|
|
339
|
+
resolvedPathname,
|
|
340
|
+
query,
|
|
341
|
+
},
|
|
342
|
+
requestHeaders: forwardedHeaders,
|
|
343
|
+
responseHeaders,
|
|
344
|
+
status,
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
if (staticFile) {
|
|
348
|
+
return asStaticFile(staticFile);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
if (status !== undefined) {
|
|
352
|
+
return { kind: "response", status, responseHeaders };
|
|
353
|
+
}
|
|
354
|
+
const resolvedUrl = middlewareRewrite ?? request.url;
|
|
355
|
+
return {
|
|
356
|
+
kind: "not-found",
|
|
357
|
+
pathname: resolvedPathname ?? resolvedUrl.pathname,
|
|
358
|
+
requestHeaders: forwardedHeaders,
|
|
359
|
+
responseHeaders,
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
exports.Dispatcher = Dispatcher;
|
|
364
|
+
/**
|
|
365
|
+
* Build outputs first, then `public/` on top of them, except over
|
|
366
|
+
* `_next/static`: that is `next start`'s precedence (see
|
|
367
|
+
* {@link Dispatcher.dispatch}).
|
|
368
|
+
*
|
|
369
|
+
* A `public/` file is registered under its pathname with the default locale in
|
|
370
|
+
* front, too, for an i18n app. `resolveRoutes` puts a locale on every path
|
|
371
|
+
* outside `/_next/` and `/api/` before it matches, so `/test.txt` is looked up
|
|
372
|
+
* as `/en-US/test.txt` and never matched the bare key: no `public/` file
|
|
373
|
+
* resolved in an i18n app at all. `next start` strips the default locale — and
|
|
374
|
+
* each domain's — off a `public/` request and no other locale (filesystem.js:
|
|
375
|
+
* "legacy behavior allows visiting static assets under default locale but no
|
|
376
|
+
* other locale"), which these entries reproduce: `/en-US/test.txt` serves and
|
|
377
|
+
* `/fr/test.txt` does not.
|
|
378
|
+
*/
|
|
379
|
+
function buildRoutingTable(manifest, publicFiles) {
|
|
380
|
+
const { basePath, trailingSlash } = manifest.config;
|
|
381
|
+
const staticFiles = new Map();
|
|
382
|
+
const nextStaticPrefix = `${basePath}/_next/static/`;
|
|
383
|
+
for (const [pathname, filePath] of Object.entries(manifest.staticFiles)) {
|
|
384
|
+
const target = {
|
|
385
|
+
filePath,
|
|
386
|
+
source: pathname.startsWith(nextStaticPrefix) ? "next-static" : "server",
|
|
387
|
+
};
|
|
388
|
+
// The key as Next.js reported it, and then as a request spells it: a build
|
|
389
|
+
// output's pathname is the file's own name, unencoded, and the HTML that
|
|
390
|
+
// loads it percent-encodes it. `app/isr/[id]/page.tsx`'s webpack chunk is
|
|
391
|
+
// `/_next/static/chunks/app/isr/[id]/page-<hash>.js` in the outputs and
|
|
392
|
+
// `…/isr/%5Bid%5D/page-<hash>.js` in the `<script>` tag.
|
|
393
|
+
for (const spelling of [pathname, ...requestSpellings(pathname)]) {
|
|
394
|
+
if (!staticFiles.has(spelling)) {
|
|
395
|
+
staticFiles.set(spelling, target);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
const publicDir = (0, public_files_1.publicDirKey)(manifest);
|
|
400
|
+
const i18n = asI18n(manifest.config.i18n);
|
|
401
|
+
const localePrefixes = [
|
|
402
|
+
"",
|
|
403
|
+
...new Set(i18n
|
|
404
|
+
? [
|
|
405
|
+
i18n.defaultLocale,
|
|
406
|
+
...(i18n.domains ?? []).map((domain) => domain.defaultLocale),
|
|
407
|
+
].map((locale) => `/${locale}`)
|
|
408
|
+
: []),
|
|
409
|
+
];
|
|
410
|
+
for (const file of publicFiles) {
|
|
411
|
+
const target = {
|
|
412
|
+
filePath: `${publicDir}/${file}`,
|
|
413
|
+
source: "public",
|
|
414
|
+
};
|
|
415
|
+
for (const spelling of requestSpellings(`/${file}`)) {
|
|
416
|
+
for (const prefix of localePrefixes) {
|
|
417
|
+
const pathname = `${basePath}${prefix}${spelling}`;
|
|
418
|
+
if (staticFiles.get(pathname)?.source !== "next-static") {
|
|
419
|
+
staticFiles.set(pathname, target);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
// `/_next/image` is not an adapter output, but it is a filesystem route to
|
|
425
|
+
// `next start` (`filesystem.js` answers it as `nextImage`), and listing it is
|
|
426
|
+
// what lets it resolve ahead of the dynamic routes; see
|
|
427
|
+
// {@link Dispatcher.dispatch}.
|
|
428
|
+
const pathnames = [
|
|
429
|
+
...new Set([
|
|
430
|
+
...manifest.pathnames,
|
|
431
|
+
...staticFiles.keys(),
|
|
432
|
+
`${basePath}/_next/image`,
|
|
433
|
+
]),
|
|
434
|
+
];
|
|
435
|
+
return {
|
|
436
|
+
pathnames: trailingSlash ? withTrailingSlashVariants(pathnames) : pathnames,
|
|
437
|
+
staticFiles,
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* The ways a request spells an unencoded path, for the exact match
|
|
442
|
+
* `@next/routing` does against `pathnames`.
|
|
443
|
+
*
|
|
444
|
+
* Two, because there are two ways to write a link to `public/images/logo@2x.png`
|
|
445
|
+
* and a browser sends each as written: `/images/logo@2x.png`, which the WHATWG
|
|
446
|
+
* URL parser leaves alone — it only encodes spaces, quotes, `#`, `?`, `<>`,
|
|
447
|
+
* `` ` ``, `{}` and non-ASCII in a path — and `/images/logo%402x.png`, which is
|
|
448
|
+
* `encodeURIComponent` a segment at a time and is how Next.js keys its own
|
|
449
|
+
* `public/` set (`encodeURIPath`). For most names the two are the same string;
|
|
450
|
+
* they differ for `@ + & , ; = $ : [ ]` and the like, and a key in only the
|
|
451
|
+
* second form 404'd every `logo@2x.png`, `c++.svg` and `icon[1].png`.
|
|
452
|
+
*
|
|
453
|
+
* `%` is encoded in both, since a literal `%` in a name can only be requested
|
|
454
|
+
* as `%25`; so are `?` and `#`, which would otherwise end the path, and `\`,
|
|
455
|
+
* which the parser turns into `/`.
|
|
456
|
+
*/
|
|
457
|
+
function requestSpellings(path) {
|
|
458
|
+
const segments = path.split("/");
|
|
459
|
+
const encoded = segments.map(encodeURIComponent).join("/");
|
|
460
|
+
const parsed = new URL(segments
|
|
461
|
+
.map((segment) => segment.replace(/[%?#\\]/g, encodeURIComponent))
|
|
462
|
+
.join("/"), "http://n").pathname;
|
|
463
|
+
return parsed === encoded ? [encoded] : [encoded, parsed];
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Normalize the two shapes `resolveRoutes` reports a redirect in.
|
|
467
|
+
*
|
|
468
|
+
* `ResolveRoutesResult.redirect` is documented, and an i18n locale-detection 307
|
|
469
|
+
* arrives that way, but the rest — the slash-stripping 308, a middleware
|
|
470
|
+
* `NextResponse.redirect()` — arrive instead as a bare `status` with `location`
|
|
471
|
+
* in `resolvedHeaders`. `next.config` `redirects()` too: they compile to routes
|
|
472
|
+
* carrying `headers: { Location }` plus `status`. Both shapes are handled, and
|
|
473
|
+
* {@link Dispatcher.normalizeRedirectLocation} then puts the location itself in
|
|
474
|
+
* the form Next.js sends.
|
|
475
|
+
*/
|
|
476
|
+
function toRedirect(result, responseHeaders) {
|
|
477
|
+
if (result.redirect) {
|
|
478
|
+
return {
|
|
479
|
+
location: result.redirect.url.href,
|
|
480
|
+
status: result.redirect.status,
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
const location = responseHeaders.get("location");
|
|
484
|
+
if (location !== null &&
|
|
485
|
+
result.status !== undefined &&
|
|
486
|
+
result.status >= 300 &&
|
|
487
|
+
result.status < 400) {
|
|
488
|
+
return { location, status: result.status };
|
|
489
|
+
}
|
|
490
|
+
return undefined;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Add `<pathname>/` alongside every route pathname, for a `trailingSlash` app.
|
|
494
|
+
*
|
|
495
|
+
* `trailingSlash: true` makes `/a/` the canonical URL — Next.js compiles a
|
|
496
|
+
* `priority` 308 from `/a` to `/a/` into `routing.beforeMiddleware`, and that
|
|
497
|
+
* redirect is the *first* thing `resolveRoutes` applies. But the build's output
|
|
498
|
+
* pathnames have no trailing slash (`/a`, `/api/revalidate`), and
|
|
499
|
+
* `@next/routing` matches them by exact string equality with no normalization of
|
|
500
|
+
* its own. So every canonical URL in such an app resolved to nothing: browsers
|
|
501
|
+
* followed the 308 to `/a/` and got a 404, and `fetch('/api/revalidate')` got
|
|
502
|
+
* the 404 *page* — measured against next.js's `test/e2e/app-dir/trailingslash`,
|
|
503
|
+
* where 6 of 8 cases failed this way. Dynamic routes escaped it only because
|
|
504
|
+
* their `sourceRegex` happens to end in `(?:/)?`.
|
|
505
|
+
*
|
|
506
|
+
* Normalizing the request URL before `resolveRoutes` instead would be wrong: the
|
|
507
|
+
* add-slash redirect matches the *slashless* path, so a normalized `/a/` would
|
|
508
|
+
* come back as a 308 to `/a/` and loop. Teaching the match about the slash and
|
|
509
|
+
* normalizing it off the *result* ({@link Dispatcher.normalizePathname}) keeps
|
|
510
|
+
* the redirect exactly as Next.js compiled it.
|
|
511
|
+
*
|
|
512
|
+
* Pathnames whose last segment has an extension are skipped: those are static
|
|
513
|
+
* files, and Next.js compiles the opposite redirect for them (`/x.js/` → 308
|
|
514
|
+
* `/x.js`), which this must not shadow.
|
|
515
|
+
*/
|
|
516
|
+
function withTrailingSlashVariants(pathnames) {
|
|
517
|
+
const variants = [];
|
|
518
|
+
for (const pathname of pathnames) {
|
|
519
|
+
variants.push(pathname);
|
|
520
|
+
if (pathname !== "/" && !/\.[^/]+$/.test(pathname)) {
|
|
521
|
+
variants.push(`${pathname}/`);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return variants;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Correct the `nxtP` route params in a resolved query from `routeMatches`.
|
|
528
|
+
*
|
|
529
|
+
* `@next/routing` expands a dynamic route's destination
|
|
530
|
+
* (`/[id]/[id2]?nxtPid=$nxtPid&nxtPid2=$nxtPid2`) by looping over the source
|
|
531
|
+
* regex's named groups and doing one global string replace per group name. Group
|
|
532
|
+
* names are substituted in insertion order, so `$nxtPid` — a *prefix* of
|
|
533
|
+
* `$nxtPid2` — is replaced first and leaves the trailing `2` behind as a
|
|
534
|
+
* literal: `/a/b` resolves with `nxtPid2=a2` instead of `nxtPid2=b`. Next.js
|
|
535
|
+
* recovers `params` from exactly these query values (`RouteModule.prepare`), so
|
|
536
|
+
* the page renders `id2: "a2"` — measured against
|
|
537
|
+
* `test/e2e/app-dir/use-params`, whose fixture is `app/[id]/[id2]/page.tsx`.
|
|
538
|
+
*
|
|
539
|
+
* `routeMatches` is the raw capture map, before any destination expansion, so it
|
|
540
|
+
* is the authority for every param it names. Only keys the expansion already
|
|
541
|
+
* produced are overwritten: adding others would invent params for a rewrite that
|
|
542
|
+
* deliberately dropped them.
|
|
543
|
+
*
|
|
544
|
+
* The same prefix collision reaches positional placeholders (`$1` inside `$10`,
|
|
545
|
+
* so a route with ten or more captures), and `next.config` `rewrites()`
|
|
546
|
+
* destinations that interpolate their own query values. Those are not route
|
|
547
|
+
* params and are left alone — there is no second source of truth to repair them
|
|
548
|
+
* from.
|
|
549
|
+
*
|
|
550
|
+
* The second correction is the opposite shape: a param the route *has* but the
|
|
551
|
+
* request did not fill. An optional catchall's group is the only one a match can
|
|
552
|
+
* leave unset — `^/optional\-catchall(?:/(?<nxtPparams>.+?))?(?:/)?$` against
|
|
553
|
+
* `/optional-catchall` — and both `routeMatches` and the expanded query keep the
|
|
554
|
+
* key with no value: `{ nxtPparams: undefined }`, which the `@next/routing` types
|
|
555
|
+
* do not admit. The key is what matters, not the value. `RouteModule.prepare`
|
|
556
|
+
* recovers a param for every `nxtP` key it finds, so a layout reading `params`
|
|
557
|
+
* renders a segment that was never requested — as `["undefined"]`, because
|
|
558
|
+
* `URLSearchParams.append` stringifies — where `next start` gives it no `params`
|
|
559
|
+
* key at all. Measured against `test/e2e/app-dir/layout-params`, whose fixture is
|
|
560
|
+
* `app/optional-catchall/[[...params]]`. No other param shape can be legitimately
|
|
561
|
+
* unfilled — a required segment captures `[^/]+?` and a required catchall `.+?` —
|
|
562
|
+
* so an unfilled value `routeMatches` does not vouch for is always this.
|
|
563
|
+
*/
|
|
564
|
+
function repairRouteParamQuery(query, routeMatches) {
|
|
565
|
+
let repaired;
|
|
566
|
+
for (const [key, value] of Object.entries(routeMatches)) {
|
|
567
|
+
if (!key.startsWith("nxtP") || value === undefined)
|
|
568
|
+
continue;
|
|
569
|
+
if (!(key in query) || query[key] === value)
|
|
570
|
+
continue;
|
|
571
|
+
repaired ??= { ...query };
|
|
572
|
+
repaired[key] = value;
|
|
573
|
+
}
|
|
574
|
+
for (const [key, value] of Object.entries(repaired ?? query)) {
|
|
575
|
+
if (!key.startsWith("nxtP") || isFilledParam(value))
|
|
576
|
+
continue;
|
|
577
|
+
if (isFilledParam(routeMatches[key]))
|
|
578
|
+
continue;
|
|
579
|
+
repaired ??= { ...query };
|
|
580
|
+
delete repaired[key];
|
|
581
|
+
}
|
|
582
|
+
return repaired ?? query;
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Route params to hand Next.js out-of-band, for the one request shape the `nxtP`
|
|
586
|
+
* query contract cannot carry: a capture containing an encoded `/`. `undefined`
|
|
587
|
+
* — the common case — means the contract is lossless and nothing special is
|
|
588
|
+
* needed.
|
|
589
|
+
*
|
|
590
|
+
* The contract normally is lossless, which is why {@link NextjsRuntime} passes
|
|
591
|
+
* route params as query values everywhere else. But `RouteModule.prepare`
|
|
592
|
+
* recovers them by running `normalizeQueryParams` — which calls
|
|
593
|
+
* `decodeQueryPathParameter`, a **second** `decodeURIComponent`, on every
|
|
594
|
+
* de-prefixed value because "when deployed to Vercel the value may be encoded" —
|
|
595
|
+
* and then `normalizeDynamicRouteParams`, which splits a string repeat param on
|
|
596
|
+
* `/` because "query values from the proxy aren't already split into arrays".
|
|
597
|
+
* Two decodes and a split: `nxtPrest=..%252F..%252Fserver-reference-manifest`
|
|
598
|
+
* (what the contract asks for, and what we send) arrives as the three params
|
|
599
|
+
* `['..', '..', 'server-reference-manifest']` rather than the one the client
|
|
600
|
+
* requested. The resolved pathname built back out of those is
|
|
601
|
+
* `/pages-cache/../../server-reference-manifest`, and `normalizePagePath` throws
|
|
602
|
+
* `Requested and resolved page mismatch` on it when the cache asks for a key —
|
|
603
|
+
* so a `_next/data` request for a catch-all whose segment contains `%2F` 500s.
|
|
604
|
+
* Measured against `test/e2e/incremental-cache-path-traversal`. No encoding can
|
|
605
|
+
* fix it from this side: whatever survives two decodes still gets split.
|
|
606
|
+
*
|
|
607
|
+
* `next start` never hits it because its `router-server` sets
|
|
608
|
+
* `requestMeta.params` instead, which `prepare` takes as-is
|
|
609
|
+
* (`route-module.ts`: `getRequestMeta(req, 'params')`) with no decode and no
|
|
610
|
+
* split. That is what this reproduces — narrowly, only for the affected
|
|
611
|
+
* requests, so that the documented query contract stays the path for everything
|
|
612
|
+
* else.
|
|
613
|
+
*
|
|
614
|
+
* The `nxtP` values have to leave the query as well as arrive in `params`.
|
|
615
|
+
* `prepare` prefers the query over `params` when both parse and are the same
|
|
616
|
+
* size, so leaving them in would just restore the split. Dropping them also
|
|
617
|
+
* matches `next start`, which has no `nxtP` query at all.
|
|
618
|
+
*/
|
|
619
|
+
function outOfBandRouteParams(query, resolvedPathname) {
|
|
620
|
+
const entries = Object.entries(query);
|
|
621
|
+
if (!entries.some(([key, value]) => key.startsWith("nxtP") &&
|
|
622
|
+
typeof value === "string" &&
|
|
623
|
+
ENCODED_PATH_DELIMITER.test(value))) {
|
|
624
|
+
return undefined;
|
|
625
|
+
}
|
|
626
|
+
// Which params are repeats — `[...rest]`, `[[...rest]]` — decides array versus
|
|
627
|
+
// string, the same distinction `normalizeDynamicRouteParams` makes from the
|
|
628
|
+
// route's own `groups`. `resolvedPathname` is the matched route, brackets and
|
|
629
|
+
// all.
|
|
630
|
+
const repeats = new Set();
|
|
631
|
+
for (const match of resolvedPathname.matchAll(/\[\[?\.\.\.([^\]]+?)\]\]?/g)) {
|
|
632
|
+
repeats.add(match[1]);
|
|
633
|
+
}
|
|
634
|
+
const params = {};
|
|
635
|
+
const remaining = {};
|
|
636
|
+
for (const [key, value] of entries) {
|
|
637
|
+
if (!key.startsWith("nxtP")) {
|
|
638
|
+
remaining[key] = value;
|
|
639
|
+
continue;
|
|
640
|
+
}
|
|
641
|
+
// Anything but a filled string is a param we cannot restate — an optional
|
|
642
|
+
// catchall the request left unset, or a repeated key. Rather than hand
|
|
643
|
+
// `prepare` a param set that is missing one, leave the whole request on the
|
|
644
|
+
// query contract.
|
|
645
|
+
if (typeof value !== "string" || value === "")
|
|
646
|
+
return undefined;
|
|
647
|
+
const name = key.slice("nxtP".length);
|
|
648
|
+
params[name] = repeats.has(name)
|
|
649
|
+
? value.split("/").map(util_1.safeDecode)
|
|
650
|
+
: (0, util_1.safeDecode)(value);
|
|
651
|
+
}
|
|
652
|
+
return { params, query: remaining };
|
|
653
|
+
}
|
|
654
|
+
/** An encoded `/`: the delimiter the query contract's split would consume. */
|
|
655
|
+
const ENCODED_PATH_DELIMITER = /%2f/i;
|
|
656
|
+
/** Whether a route param carries a segment, as opposed to `""` or nothing. */
|
|
657
|
+
function isFilledParam(value) {
|
|
658
|
+
return Array.isArray(value) ? value.length > 0 : Boolean(value);
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* The order next itself uses, in `base-server.ts`'s `renderErrorToResponse`:
|
|
662
|
+
* the status page's entrypoints, then its prerender, then `/_error`, which is
|
|
663
|
+
* the built-in error page unless the app wrote its own.
|
|
664
|
+
*
|
|
665
|
+
* For a 404 the entrypoints are App Router's `/_not-found`, then Pages
|
|
666
|
+
* Router's `/404`. `/404` has to come before `/_error` — it is the app's
|
|
667
|
+
* *custom* 404, and `/_error` is the built-in "404: This page could not be
|
|
668
|
+
* found". Measured against `test/e2e/404-page-app`, where every URL got the
|
|
669
|
+
* built-in page. For a 500 it is `/500`.
|
|
670
|
+
*
|
|
671
|
+
* The prerender is almost always there: `next build` emits `404.html` whenever
|
|
672
|
+
* `pages/_app` has no `getInitialProps` (`useStaticPages404`), from the app's
|
|
673
|
+
* `pages/404.js` or else from `_error`, and `pages/500.js` is a
|
|
674
|
+
* `STATIC_STATUS_PAGES` entry. So it reaches us as a static file — under i18n
|
|
675
|
+
* one per locale (`/en-US/404`), and never a bare `/404` — and `next start`
|
|
676
|
+
* serves it ahead of `/_error`, which every Pages build has. The page is an
|
|
677
|
+
* entrypoint only when something forces a per-request render, which a
|
|
678
|
+
* `getInitialProps` in `_app` does.
|
|
679
|
+
*
|
|
680
|
+
* A 500 is only rendered when an entrypoint *throws*. Next.js's page handlers
|
|
681
|
+
* deliberately rethrow ("rethrow so that we can handle serving error page",
|
|
682
|
+
* `pages-handler.ts`), leaving the error page to whatever is hosting them —
|
|
683
|
+
* measured against `test/e2e/async-modules`, whose `/make-error` throws in
|
|
684
|
+
* `getServerSideProps` and expects the app's `pages/_error`.
|
|
685
|
+
*
|
|
686
|
+
* Apps with none of these get nothing.
|
|
687
|
+
*/
|
|
688
|
+
function statusTarget(manifest, status,
|
|
689
|
+
/** Which locale's prerender to look for, in an i18n app. */
|
|
690
|
+
locale) {
|
|
691
|
+
const { basePath } = manifest.config;
|
|
692
|
+
for (const suffix of manifest_1.STATUS_PAGE_SUFFIXES[status]) {
|
|
693
|
+
const pathname = `${basePath}${suffix}`;
|
|
694
|
+
const entrypoint = manifest.entrypoints[pathname];
|
|
695
|
+
if (entrypoint) {
|
|
696
|
+
return { kind: "entrypoint", pathname, entrypoint };
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
const prerendered = `${basePath}${locale ? `/${locale}` : ""}/${status}`;
|
|
700
|
+
const filePath = manifest.staticFiles[prerendered];
|
|
701
|
+
if (filePath !== undefined) {
|
|
702
|
+
return { kind: "static-file", pathname: prerendered, filePath };
|
|
703
|
+
}
|
|
704
|
+
const errorPathname = `${basePath}${manifest_1.STATUS_PAGE_SUFFIXES.fallback}`;
|
|
705
|
+
const errorEntrypoint = manifest.entrypoints[errorPathname];
|
|
706
|
+
if (errorEntrypoint) {
|
|
707
|
+
return {
|
|
708
|
+
kind: "entrypoint",
|
|
709
|
+
pathname: errorPathname,
|
|
710
|
+
entrypoint: errorEntrypoint,
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
return { kind: "none" };
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* {@link statusTarget} for every locale, resolved once, and a lookup of the
|
|
717
|
+
* request's: in an i18n app, the prerender of the locale the URL is in
|
|
718
|
+
* (`/fr/nope` gets `/fr/404`), and otherwise of the domain's default locale —
|
|
719
|
+
* which is how `next start` picks the locale it renders a status page in. A
|
|
720
|
+
* request whose URL could not be parsed, `undefined`, gets the default
|
|
721
|
+
* locale's.
|
|
722
|
+
*/
|
|
723
|
+
function statusTargets(manifest, status) {
|
|
724
|
+
const i18n = asI18n(manifest.config.i18n);
|
|
725
|
+
const fallback = statusTarget(manifest, status, i18n?.defaultLocale);
|
|
726
|
+
const byLocale = new Map((i18n?.locales ?? []).map((locale) => [
|
|
727
|
+
locale,
|
|
728
|
+
statusTarget(manifest, status, locale),
|
|
729
|
+
]));
|
|
730
|
+
return (url) => {
|
|
731
|
+
const locale = url ? requestLocale(manifest, url) : undefined;
|
|
732
|
+
return (locale !== undefined && byLocale.get(locale)) || fallback;
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* The locale a request's status page renders in, the way `next start` picks it:
|
|
737
|
+
* the locale the URL's first segment names (case-insensitively, as
|
|
738
|
+
* `normalizeLocalePath` matches it), and otherwise the domain's default locale,
|
|
739
|
+
* then the app's. `undefined` without i18n.
|
|
740
|
+
*/
|
|
741
|
+
function requestLocale(manifest, url) {
|
|
742
|
+
const i18n = asI18n(manifest.config.i18n);
|
|
743
|
+
if (!i18n)
|
|
744
|
+
return undefined;
|
|
745
|
+
const pathname = (0, util_1.withoutPathPrefix)(url.pathname, manifest.config.basePath);
|
|
746
|
+
const segment = (pathname.split("/")[1] ?? "").toLowerCase();
|
|
747
|
+
return (i18n.locales.find((candidate) => candidate.toLowerCase() === segment) ??
|
|
748
|
+
(0, routing_1.detectDomainLocale)(i18n.domains, url.hostname)?.defaultLocale ??
|
|
749
|
+
i18n.defaultLocale);
|
|
750
|
+
}
|
|
751
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlzcGF0Y2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVudGltZS9kaXNwYXRjaC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFzc0JBLGdDQW9CQztBQTJFRCxzREFrQkM7QUFxQ0Qsb0RBMkNDO0FBNkVELHNDQWdCQztBQXArQkQsc0RBQXNEO0FBQ3REOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCwyQ0FXdUI7QUFDdkIseUNBSW9CO0FBQ3BCLGlEQUE4QztBQUM5QyxpQ0FBaUU7QUFpS2pFOzs7Ozs7OztHQVFHO0FBQ0gsU0FBUyxRQUFRLENBQUMsT0FBZ0I7SUFDaEMsT0FBTyxPQUF3QyxDQUFDO0FBQ2xELENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxNQUFNLENBQUMsSUFBb0I7SUFDbEMsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFFLElBQW9DLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztBQUNsRSxDQUFDO0FBRUQsTUFBYSxVQUFVO0lBVWU7SUFUcEMsMkVBQTJFO0lBQzNELFdBQVcsQ0FBNkI7SUFFdkMsTUFBTSxDQUFnQztJQUN0QyxJQUFJLENBQTBDO0lBQzlDLEtBQUssQ0FBZTtJQUNwQixhQUFhLENBQVM7SUFDdEIsYUFBYSxDQUFVO0lBRXhDLFlBQW9DLE9BQTBCO1FBQTFCLFlBQU8sR0FBUCxPQUFPLENBQW1CO1FBQzVELE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxPQUFPLENBQUM7UUFDN0IsSUFBSSxDQUFDLE1BQU0sR0FBRyxRQUFRLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3pDLElBQUksQ0FBQyxJQUFJLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekMsSUFBSSxDQUFDLGFBQWEsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQztRQUNuRCxJQUFJLENBQUMsS0FBSyxHQUFHLGlCQUFpQixDQUFDLFFBQVEs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QUFTLElBQUksUUFBUSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLFFBQVEsQ0FBQztJQUNwRSxDQUFDLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFTLGFBQWEsQ0FDcEIsUUFBeUIsRUFDekIsR0FBUTtJQUVSLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLElBQUksQ0FBQyxJQUFJO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDNUIsTUFBTSxRQUFRLEdBQUcsSUFBQSx3QkFBaUIsRUFBQyxHQUFHLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDM0UsTUFBTSxPQUFPLEdBQUcsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQzdELE9BQU8sQ0FDTCxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLFdBQVcsRUFBRSxLQUFLLE9BQU8sQ0FBQztRQUNyRSxJQUFBLDRCQUFrQixFQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLFFBQVEsQ0FBQyxFQUFFLGFBQWE7UUFDN0QsSUFBSSxDQUFDLGFBQWEsQ0FDbkIsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXMgKi9cbi8qKlxuICogUmVxdWVzdCBkaXNwYXRjaDogVVJMIGluLCByb3V0aW5nIGRlY2lzaW9uIG91dC5cbiAqXG4gKiBBbGwgcm91dGUgbWF0Y2hpbmcgaXMgZGVsZWdhdGVkIHRvIGBAbmV4dC9yb3V0aW5nYCdzIGByZXNvbHZlUm91dGVzYCwgdGhlXG4gKiBmaXJzdC1wYXJ0eSBwYWNrYWdlIGBuZXh0IHN0YXJ0YCB3YXMgcmVmYWN0b3JlZCB0byBleHBvc2UuIFJlaW1wbGVtZW50aW5nXG4gKiByZWRpcmVjdHMvcmV3cml0ZXMvaTE4bi9keW5hbWljLXJvdXRlIG1hdGNoaW5nIGlzIHdoYXQgcHJldmlvdXMgdmVyc2lvbnMgb2ZcbiAqIHRoaXMgY29uc3RydWN0IGRpZCwgYW5kIGl0IGlzIHRoZSB0aGluZyB0aGlzIHJld3JpdGUgZXhpc3RzIHRvIGRlbGV0ZS5cbiAqXG4gKiBUaGlzIG1vZHVsZSBpcyBwdXJlIGRlY2lzaW9uLW1ha2luZzogaXQgbmV2ZXIgdG91Y2hlcyB0aGUgZmlsZXN5c3RlbSwgbmV2ZXJcbiAqIHJlcXVpcmVzIGFuIGVudHJ5cG9pbnQsIGFuZCBuZXZlciBidWlsZHMgYSBgUmVzcG9uc2VgLiBJdCByZXR1cm5zIGFcbiAqIHtAbGluayBEaXNwYXRjaFJlc3VsdH0gYW5kIHRoZSBjYWxsZXIgKHRoZSBydW50aW1lIGNvcmUsIHN0ZXAgNCkgYWN0cyBvbiBpdC5cbiAqIFRoYXQgc3BsaXQgaXMgd2hhdCBtYWtlcyBpdCB1bml0LXRlc3RhYmxlIGFnYWluc3QgdGhlIGNvbW1pdHRlZFxuICogYG9uQnVpbGRDb21wbGV0ZWAgZml4dHVyZXMgd2l0aCBubyBBV1MgYW5kIG5vIE5leHQuanMgc2VydmVyLlxuICovXG5pbXBvcnQge1xuICBNaWRkbGV3YXJlQ29udGV4dCxcbiAgTWlkZGxld2FyZVJlc3VsdCxcbiAgUmVzb2x2ZVJvdXRlc1BhcmFtcyxcbiAgUmVzb2x2ZVJvdXRlc1F1ZXJ5LFxuICBSZXNvbHZlUm91dGVzUXVlcnlWYWx1ZSxcbiAgUmVzb2x2ZVJvdXRlc1Jlc3VsdCxcbiAgUm91dGVJbnZvY2F0aW9uVGFyZ2V0LFxuICBkZXRlY3REb21haW5Mb2NhbGUsXG4gIGRldGVjdExvY2FsZSxcbiAgcmVzb2x2ZVJvdXRlcyxcbn0gZnJvbSBcIkBuZXh0L3JvdXRpbmdcIjtcbmltcG9ydCB7XG4gIEFkYXB0ZXJFbnRyeXBvaW50LFxuICBBZGFwdGVyTWFuaWZlc3QsXG4gIFNUQVRVU19QQUdFX1NVRkZJWEVTLFxufSBmcm9tIFwiLi9tYW5pZmVzdFwiO1xuaW1wb3J0IHsgcHVibGljRGlyS2V5IH0gZnJvbSBcIi4vcHVibGljLWZpbGVzXCI7XG5pbXBvcnQgeyBzYWZlRGVjb2RlLCB0b1NlYXJjaCwgd2l0aG91dFBhdGhQcmVmaXggfSBmcm9tIFwiLi91dGlsXCI7XG5cbi8qKlxuICogUnVucyB0aGUgYXBwJ3MgbWlkZGxld2FyZSBmb3Igb25lIHJlcXVlc3QuIFN1cHBsaWVkIGJ5IGBNaWRkbGV3YXJlUnVubmVyYCBpblxuICogYC4vbWlkZGxld2FyZWAuXG4gKlxuICogYE1pZGRsZXdhcmVDb250ZXh0YCBjYXJyaWVzIG5vIG1ldGhvZCDigJQgYHJlc29sdmVSb3V0ZXNgIG5ldmVyIG5lZWRzIG9uZSDigJQgYnV0XG4gKiBtaWRkbGV3YXJlIHZlcnkgbXVjaCBkb2VzIChgaWYgKHJlcXVlc3QubWV0aG9kID09PSBcIlBPU1RcIilgKSwgc28gZGlzcGF0Y2ggYWRkc1xuICogaXQgZnJvbSB0aGUgcmVxdWVzdCBpdCB3YXMgZ2l2ZW4uIFRoZSBgUmVzcG9uc2VgIG1pZGRsZXdhcmUgcmV0dXJuZWQgY29tZXNcbiAqIGJhY2sgYmVzaWRlIHRoZSByZXN1bHQsIGJlY2F1c2UgYHJlc29sdmVSb3V0ZXNgIHJlcG9ydHMgYG1pZGRsZXdhcmVSZXNwb25kZWRgXG4gKiB3aXRob3V0IGl0LlxuICovXG5leHBvcnQgdHlwZSBNaWRkbGV3YXJlSW52b2tlciA9IChcbiAgY3R4OiBNaWRkbGV3YXJlQ29udGV4dCAmIHsgcmVhZG9ubHkgbWV0aG9kOiBzdHJpbmcgfSxcbikgPT4gUHJvbWlzZTxNaWRkbGV3YXJlUmVzdWx0ICYgeyByZWFkb25seSByZXNwb25zZTogUmVzcG9uc2UgfT47XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGlzcGF0Y2hlck9wdGlvbnMge1xuICByZWFkb25seSBtYW5pZmVzdDogQWRhcHRlck1hbmlmZXN0O1xuICAvKipcbiAgICogVGhlIGZpbGVzIHVuZGVyIGBwdWJsaWMvYCwgZnJvbSBgcmVhZFB1YmxpY0ZpbGVzYDogdW5lbmNvZGVkIHBhdGhzIHJlbGF0aXZlXG4gICAqIHRvIGl0LiBTZXJ2ZWQgYWhlYWQgb2YgZXZlcnkgcm91dGUsIGFzIGBuZXh0IHN0YXJ0YCBzZXJ2ZXMgdGhlbS5cbiAgICogQGRlZmF1bHQgLSBubyBgcHVibGljL2AgZmlsZXNcbiAgICovXG4gIHJlYWRvbmx5IHB1YmxpY0ZpbGVzPzogcmVhZG9ubHkgc3RyaW5nW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGlzcGF0Y2hSZXF1ZXN0IHtcbiAgcmVhZG9ubHkgbWV0aG9kOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHVybDogVVJMO1xuICByZWFkb25seSBoZWFkZXJzOiBIZWFkZXJzO1xuICAvKipcbiAgICogQWx3YXlzIGEgc3RyZWFtIOKAlCBgcmVzb2x2ZVJvdXRlc2AgcmVxdWlyZXMgb25lIGJlY2F1c2UgbWlkZGxld2FyZSBtYXkgcmVhZFxuICAgKiB0aGUgYm9keS4gVXNlIGFuIGFscmVhZHktY2xvc2VkIHN0cmVhbSBmb3IgR0VUL0hFQUQuXG4gICAqL1xuICByZWFkb25seSBib2R5OiBSZWFkYWJsZVN0cmVhbTtcbiAgLyoqXG4gICAqIFJlcXVpcmVkIHdoZW5ldmVyIGBtYW5pZmVzdC5taWRkbGV3YXJlYCBpcyBub24tbnVsbC4gYHJlc29sdmVSb3V0ZXNgIGRlY2lkZXNcbiAgICogKndoZXRoZXIqIHRvIGNhbGwgaXQgZnJvbSBgcm91dGluZy5taWRkbGV3YXJlTWF0Y2hlcnNgOyB3ZSBvbmx5IHN1cHBseSB0aGVcbiAgICogaG93LlxuICAgKi9cbiAgcmVhZG9ubHkgaW52b2tlTWlkZGxld2FyZT86IE1pZGRsZXdhcmVJbnZva2VyO1xufVxuXG5pbnRlcmZhY2UgRGlzcGF0Y2hSZXN1bHRCYXNlIHtcbiAgLyoqXG4gICAqIEhlYWRlcnMgdG8gbWVyZ2UgaW50byB0aGUgcmVzcG9uc2U6IGBoZWFkZXJzKClgIHJ1bGVzLCB0aGUgaW1tdXRhYmxlXG4gICAqIGBjYWNoZS1jb250cm9sYCBmb3IgYF9uZXh0L3N0YXRpY2AsIGFuZCBhbnl0aGluZyBtaWRkbGV3YXJlIHNldCB2aWFcbiAgICogYE5leHRSZXNwb25zZS5uZXh0KHsgaGVhZGVycyB9KWAuIE5ldmVyIHJlcXVlc3QgaGVhZGVycy5cbiAgICovXG4gIHJlYWRvbmx5IHJlc3BvbnNlSGVhZGVyczogSGVhZGVycztcbiAgLyoqIFN0YXR1cyBmb3JjZWQgYnkgYSBtYXRjaGVkIHJvdXRlLCBpZiBhbnkuICovXG4gIHJlYWRvbmx5IHN0YXR1cz86IG51bWJlcjtcbn1cblxuLyoqIEEgcm91dGUgd2UgbXVzdCBpbnZva2UuICovXG5leHBvcnQgaW50ZXJmYWNlIERpc3BhdGNoRW50cnlwb2ludFJlc3VsdCBleHRlbmRzIERpc3BhdGNoUmVzdWx0QmFzZSB7XG4gIHJlYWRvbmx5IGtpbmQ6IFwiZW50cnlwb2ludFwiO1xuICByZWFkb25seSBlbnRyeXBvaW50OiBBZGFwdGVyRW50cnlwb2ludDtcbiAgLyoqIFRoZSBtYXRjaGVkIHRlbXBsYXRlLCBpLmUuIHRoZSBgbWFuaWZlc3QuZW50cnlwb2ludHNgIGtleS4gKi9cbiAgcmVhZG9ubHkgcmVzb2x2ZWRQYXRobmFtZTogc3RyaW5nO1xuICAvKiogVGhlICpjb25jcmV0ZSogcGF0aG5hbWUgKyBxdWVyeSB0byBpbnZva2UgdGhlIHJvdXRlIHdpdGguICovXG4gIHJlYWRvbmx5IGludm9jYXRpb25UYXJnZXQ6IFJvdXRlSW52b2NhdGlvblRhcmdldDtcbiAgLyoqIFJlcXVlc3QgaGVhZGVycyBhcyBtaWRkbGV3YXJlIGxlZnQgdGhlbS4gKi9cbiAgcmVhZG9ubHkgcmVxdWVzdEhlYWRlcnM6IEhlYWRlcnM7XG59XG5cbi8qKiBBIGZpbGUgaW4gYG1hbmlmZXN0LnN0YXRpY0ZpbGVzYCBvciBgcHVibGljL2A6IHJlYWQgb2ZmIGRpc2ssIG5vdCBpbnZva2VkLiAqL1xuZXhwb3J0IGludGVyZmFjZSBEaXNwYXRjaFN0YXRpY0ZpbGVSZXN1bHQgZXh0ZW5kcyBEaXNwYXRjaFJlc3VsdEJhc2Uge1xuICByZWFkb25seSBraW5kOiBcInN0YXRpYy1maWxlXCI7XG4gIHJlYWRvbmx5IHBhdGhuYW1lOiBzdHJpbmc7XG4gIC8qKiBSZXBvLXJvb3QtcmVsYXRpdmUga2V5IGluc2lkZSB0aGUgZGVwbG95bWVudCByb290LiAqL1xuICByZWFkb25seSBmaWxlUGF0aDogc3RyaW5nO1xuICByZWFkb25seSBzb3VyY2U6IFN0YXRpY0ZpbGVTb3VyY2U7XG4gIC8qKlxuICAgKiBSZXF1ZXN0IGhlYWRlcnMgYXMgbWlkZGxld2FyZSBsZWZ0IHRoZW0sIGZvciB0aGUgNDA0IHRoZSBydW50aW1lIHJlbmRlcnNcbiAgICogd2hlbiB0aGUgZmlsZSBpcyBub3QgaW4gdGhlIHBhY2thZ2UgYWZ0ZXIgYWxsLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVxdWVzdEhlYWRlcnM6IEhlYWRlcnM7XG59XG5cbi8qKlxuICogV2hlcmUgYSBzdGF0aWMgZmlsZSBjYW1lIGZyb20sIHdoaWNoIGRlY2lkZXMgd2hhdCBlbHNlIGl0IGlzIGFsbG93ZWQgdG8gZG8uXG4gKlxuICogLSBgcHVibGljYCDigJQgYSBmaWxlIGluIGBwdWJsaWMvYC5cbiAqIC0gYG5leHQtc3RhdGljYCDigJQgYDxkaXN0RGlyPi9zdGF0aWNgLCB0aGUgY2xpZW50IGJ1bmRsZXMuXG4gKiAtIGBzZXJ2ZXJgIOKAlCBhIGJ1aWxkIG91dHB1dCB1bmRlciBgPGRpc3REaXI+L3NlcnZlcmA6IHByZXJlbmRlcmVkIEhUTUwsIGFcbiAqICAgc3RhdGljIG1ldGFkYXRhIHJvdXRlJ3MgYC5ib2R5YC5cbiAqXG4gKiBUaGUgZmlyc3QgdHdvIGFyZSB3aGF0IGBuZXh0IHN0YXJ0YCBzZXJ2ZXMgYXMgcGxhaW4gZmlsZXMsIHdpdGggYHNlbmRgLCBhbmRcbiAqIG9ubHkgdG8gR0VUIGFuZCBIRUFEIChgcm91dGVyLXNlcnZlci5qc2AsIHRoZSBgZnNQYXRoYCBicmFuY2gpOyB0aGUgdGhpcmQgaXRcbiAqIHNlcnZlcyBieSBpbnZva2luZyB0aGUgcm91dGUgaXQgY2FtZSBmcm9tLlxuICovXG5leHBvcnQgdHlwZSBTdGF0aWNGaWxlU291cmNlID0gXCJwdWJsaWNcIiB8IFwibmV4dC1zdGF0aWNcIiB8IFwic2VydmVyXCI7XG5cbi8qKiBgL19uZXh0L2ltYWdlYDogb3VyIG93biBvcHRpbWl6ZXIsIGRlbGliZXJhdGVseSByZWFjaGVkIGFmdGVyIG1pZGRsZXdhcmUuICovXG5leHBvcnQgaW50ZXJmYWNlIERpc3BhdGNoSW1hZ2VPcHRpbWl6YXRpb25SZXN1bHQgZXh0ZW5kcyBEaXNwYXRjaFJlc3VsdEJhc2Uge1xuICByZWFkb25seSBraW5kOiBcImltYWdlLW9wdGltaXphdGlvblwiO1xuICByZWFkb25seSB1cmw6IFVSTDtcbiAgcmVhZG9ubHkgcmVxdWVzdEhlYWRlcnM6IEhlYWRlcnM7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGlzcGF0Y2hSZWRpcmVjdFJlc3VsdCBleHRlbmRzIERpc3BhdGNoUmVzdWx0QmFzZSB7XG4gIHJlYWRvbmx5IGtpbmQ6IFwicmVkaXJlY3RcIjtcbiAgcmVhZG9ubHkgbG9jYXRpb246IHN0cmluZztcbiAgcmVhZG9ubHkgc3RhdHVzOiBudW1iZXI7XG59XG5cbi8qKiBBIHJld3JpdGUgdG8gYW5vdGhlciBvcmlnaW46IHByb3h5IHRoZSByZXF1ZXN0IHRocm91Z2guICovXG5leHBvcnQgaW50ZXJmYWNlIERpc3BhdGNoRXh0ZXJuYWxSZXdyaXRlUmVzdWx0IGV4dGVuZHMgRGlzcGF0Y2hSZXN1bHRCYXNlIHtcbiAgcmVhZG9ubHkga2luZDogXCJleHRlcm5hbC1yZXdyaXRlXCI7XG4gIHJlYWRvbmx5IHVybDogVVJMO1xuICByZWFkb25seSByZXF1ZXN0SGVhZGVyczogSGVhZGVycztcbn1cblxuLyoqIE1pZGRsZXdhcmUgcmV0dXJuZWQgaXRzIG93biByZXNwb25zZTogc2VuZCBpdC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGlzcGF0Y2hNaWRkbGV3YXJlUmVzcG9uZGVkUmVzdWx0IGV4dGVuZHMgRGlzcGF0Y2hSZXN1bHRCYXNlIHtcbiAgcmVhZG9ubHkga2luZDogXCJtaWRkbGV3YXJlLXJlc3BvbmRlZFwiO1xuICByZWFkb25seSByZXNwb25zZTogUmVzcG9uc2U7XG59XG5cbi8qKiBBIG1hdGNoZWQgcm91dGUgZm9yY2VkIGEgc3RhdHVzIHdpdGggbm90aGluZyB0byBpbnZva2UuICovXG5leHBvcnQgaW50ZXJmYWNlIERpc3BhdGNoRGlyZWN0UmVzcG9uc2VSZXN1bHQgZXh0ZW5kcyBEaXNwYXRjaFJlc3VsdEJhc2Uge1xuICByZWFkb25seSBraW5kOiBcInJlc3BvbnNlXCI7XG4gIHJlYWRvbmx5IHN0YXR1czogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIERpc3BhdGNoTm90Rm91bmRSZXN1bHQgZXh0ZW5kcyBEaXNwYXRjaFJlc3VsdEJhc2Uge1xuICByZWFkb25seSBraW5kOiBcIm5vdC1mb3VuZFwiO1xuICAvKiogV2hhdCBmYWlsZWQgdG8gcmVzb2x2ZS4gRm9yIGxvZ2dpbmcuICovXG4gIHJlYWRvbmx5IHBhdGhuYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHJlcXVlc3RIZWFkZXJzOiBIZWFkZXJzO1xufVxuXG5leHBvcnQgdHlwZSBEaXNwYXRjaFJlc3VsdCA9XG4gIHwgRGlzcGF0Y2hFbnRyeXBvaW50UmVzdWx0XG4gIHwgRGlzcGF0Y2hTdGF0aWNGaWxlUmVzdWx0XG4gIHwgRGlzcGF0Y2hJbWFnZU9wdGltaXphdGlvblJlc3VsdFxuICB8IERpc3BhdGNoUmVkaXJlY3RSZXN1bHRcbiAgfCBEaXNwYXRjaEV4dGVybmFsUmV3cml0ZVJlc3VsdFxuICB8IERpc3BhdGNoTWlkZGxld2FyZVJlc3BvbmRlZFJlc3VsdFxuICB8IERpc3BhdGNoRGlyZWN0UmVzcG9uc2VSZXN1bHRcbiAgfCBEaXNwYXRjaE5vdEZvdW5kUmVzdWx0O1xuXG4vKipcbiAqIEhvdyB0byBwcm9kdWNlIGEgNDA0IG9yIDUwMCBib2R5LiBSZXNvbHZlZCBvbmNlIHBlciBsb2NhbGUgZnJvbSB0aGUgbWFuaWZlc3RcbiAqIChzZWUge0BsaW5rIHN0YXR1c1RhcmdldHN9KTsgaG9ub3JpbmcgYG5vdEZvdW5kKClgIGZyb20gYSByb3V0ZSBpcyB0aGVcbiAqIHJ1bnRpbWUgY29yZSdzIGpvYiwgbm90IGRpc3BhdGNoJ3MuXG4gKi9cbmV4cG9ydCB0eXBlIFN0YXR1c1RhcmdldCA9XG4gIHwge1xuICAgICAgcmVhZG9ubHkga2luZDogXCJlbnRyeXBvaW50XCI7XG4gICAgICByZWFkb25seSBwYXRobmFtZTogc3RyaW5nO1xuICAgICAgcmVhZG9ubHkgZW50cnlwb2ludDogQWRhcHRlckVudHJ5cG9pbnQ7XG4gICAgfVxuICB8IHtcbiAgICAgIHJlYWRvbmx5IGtpbmQ6IFwic3RhdGljLWZpbGVcIjtcbiAgICAgIHJlYWRvbmx5IHBhdGhuYW1lOiBzdHJpbmc7XG4gICAgICByZWFkb25seSBmaWxlUGF0aDogc3RyaW5nO1xuICAgIH1cbiAgfCB7IHJlYWRvbmx5IGtpbmQ6IFwibm9uZVwiIH07XG5cbi8qKlxuICogYGN0eC5yb3V0aW5nYCBpcyBwZXJzaXN0ZWQgaW50byB0aGUgbWFuaWZlc3QgdmVyYmF0aW0gYW5kIHR5cGVkIGB1bmtub3duYFxuICogdGhlcmUsIGJlY2F1c2UgdGhlIG1hbmlmZXN0IG11c3Qgbm90IGRlcGVuZCBvbiBgQG5leHQvcm91dGluZ2AgKGl0IGlzIGFsc29cbiAqIHJlYWQgYXQgc3ludGggYnkgdGhlIENESyBjb25zdHJ1Y3RzKS4gRGlzcGF0Y2ggaXMgdGhlIG9uZSBwbGFjZSB0aGF0IGtub3dzXG4gKiB0aGUgcmVhbCBzaGFwZSwgc28gdGhlIGNhc3QgbGl2ZXMgaGVyZS5cbiAqXG4gKiBgY3R4LnJvdXRpbmdgIGlzIGEgc3VwZXJzZXQgb2YgYFJlc29sdmVSb3V0ZXNQYXJhbXNbXCJyb3V0ZXNcIl1gIOKAlCBpdCBhbHNvXG4gKiBjYXJyaWVzIGByc2NgIOKAlCB3aGljaCBpcyB3aHkgdGhpcyBpcyBhIGNhc3QgYW5kIG5vdCBhbiBhc3NpZ25tZW50LlxuICovXG5mdW5jdGlvbiBhc1JvdXRlcyhyb3V0aW5nOiB1bmtub3duKTogUmVzb2x2ZVJvdXRlc1BhcmFtc1tcInJvdXRlc1wiXSB7XG4gIHJldHVybiByb3V0aW5nIGFzIFJlc29sdmVSb3V0ZXNQYXJhbXNbXCJyb3V0ZXNcIl07XG59XG5cbi8qKlxuICogTGlrZXdpc2UgZm9yIGBpMThuYDogYE5leHRDb25maWdDb21wbGV0ZVtcImkxOG5cIl1gIGlzIHdpZGVyIHRoYW5cbiAqIGBSZXNvbHZlUm91dGVzUGFyYW1zW1wiaTE4blwiXWAgKGV4dHJhIGZpZWxkcywgYW5kIGBsb2NhbGVEZXRlY3Rpb24/OiBib29sZWFuYFxuICogYWdhaW5zdCBgZmFsc2VgKSwgYW5kIHRoZSBtYW5pZmVzdCBzdG9yZXMgdGhlIGNvbmZpZyB2YWx1ZSBhcy1pcy5cbiAqL1xuZnVuY3Rpb24gYXNJMThuKGkxOG46IHVua25vd24gfCBudWxsKTogUmVzb2x2ZVJvdXRlc1BhcmFtc1tcImkxOG5cIl0gfCB1bmRlZmluZWQge1xuICByZXR1cm4gaTE4biA/IChpMThuIGFzIFJlc29sdmVSb3V0ZXNQYXJhbXNbXCJpMThuXCJdKSA6IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IGNsYXNzIERpc3BhdGNoZXIge1xuICAvKiogVGhlIDQwNCB0byByZW5kZXIgZm9yIGEgcmVxdWVzdCB0byBhIFVSTDsgc2VlIHtAbGluayBzdGF0dXNUYXJnZXRzfS4gKi9cbiAgcHVibGljIHJlYWRvbmx5IG5vdEZvdW5kRm9yOiAodXJsOiBVUkwpID0+IFN0YXR1c1RhcmdldDtcblxuICBwcml2YXRlIHJlYWRvbmx5IHJvdXRlczogUmVzb2x2ZVJvdXRlc1BhcmFtc1tcInJvdXRlc1wiXTtcbiAgcHJpdmF0ZSByZWFkb25seSBpMThuOiBSZXNvbHZlUm91dGVzUGFyYW1zW1wiaTE4blwiXSB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSByZWFkb25seSB0YWJsZTogUm91dGluZ1RhYmxlO1xuICBwcml2YXRlIHJlYWRvbmx5IGltYWdlUGF0aG5hbWU6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSB0cmFpbGluZ1NsYXNoOiBib29sZWFuO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IG9wdGlvbnM6IERpc3BhdGNoZXJPcHRpb25zKSB7XG4gICAgY29uc3QgeyBtYW5pZmVzdCB9ID0gb3B0aW9ucztcbiAgICB0aGlzLnJvdXRlcyA9IGFzUm91dGVzKG1hbmlmZXN0LnJvdXRpbmcpO1xuICAgIHRoaXMuaTE4biA9IGFzSTE4bihtYW5pZmVzdC5jb25maWcuaTE4bik7XG4gICAgdGhpcy50cmFpbGluZ1NsYXNoID0gbWFuaWZlc3QuY29uZmlnLnRyYWlsaW5nU2xhc2g7XG4gICAgdGhpcy50YWJsZSA9IGJ1aWxkUm91dGluZ1RhYmxlKG1hbmlmZXN0LCBvcHRpb25zLnB1YmxpY0ZpbGVzID8/IFtdKTtcbiAgICB0aGlzLmltYWdlUGF0aG5hbWUgPSBgJHttYW5pZmVzdC5jb25maWcuYmFzZVBhdGh9L19uZXh0L2ltYWdlYDtcbiAgICB0aGlzLm5vdEZvdW5kRm9yID0gc3RhdHVzVGFyZ2V0cyhtYW5pZmVzdCwgNDA0KTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgbWFuaWZlc3QoKTogQWRhcHRlck1hbmlmZXN0IHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLm1hbmlmZXN0O1xuICB9XG5cbiAgLyoqXG4gICAqIERyb3AgdGhlIGB0cmFpbGluZ1NsYXNoYCBzbGFzaCBhIHJlc29sdmVkIHBhdGhuYW1lIG1heSBjYXJyeSwgc28gaXQgY2FuIGJlXG4gICAqIGxvb2tlZCB1cCBpbiBgZW50cnlwb2ludHNgL2BzdGF0aWNGaWxlc2AgYW5kIHJlbmRlcmVkIHVuZGVyIHRoZSBzYW1lIGNhY2hlXG4gICAqIGtleSBhcyBpdHMgcHJlcmVuZGVyLiBBIG5vLW9wIHVubGVzcyB0aGUgYXBwIHNldHMgYHRyYWlsaW5nU2xhc2hgLlxuICAgKi9cbiAgcHJpdmF0ZSBub3JtYWxpemVQYXRobmFtZShwYXRobmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIXRoaXMudHJhaWxpbmdTbGFzaCB8fCBwYXRobmFtZSA9PT0gdW5kZWZpbmVkKSByZXR1cm4gcGF0aG5hbWU7XG4gICAgcmV0dXJuIHBhdGhuYW1lLmxlbmd0aCA+IDEgJiYgcGF0aG5hbWUuZW5kc1dpdGgoXCIvXCIpXG4gICAgICA/IHBhdGhuYW1lLnNsaWNlKDAsIC0xKVxuICAgICAgOiBwYXRobmFtZTtcbiAgfVxuXG4gIC8qKiBUaGUgcmVxdWVzdCBwYXRoIHdpdGggYGJhc2VQYXRoYCByZW1vdmVkLCB3aGljaCBpcyB3aGF0IGkxOG4gYXBwbGllcyB0by4gKi9cbiAgcHJpdmF0ZSB3aXRob3V0QmFzZVBhdGgocGF0aG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHdpdGhvdXRQYXRoUHJlZml4KHBhdGhuYW1lLCB0aGlzLm1hbmlmZXN0LmNvbmZpZy5iYXNlUGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogUHV0IHRoZSBsb2NhbGUgaW4gZnJvbnQgb2YgYSByZXF1ZXN0IGZvciB0aGUgYXBwJ3Mgcm9vdCAqaGVyZSosIHdoZW4gdGhlXG4gICAqIGxvY2FsZSBpcyB0aGUgb25lIHRoZSByZXF1ZXN0IGlzIGFscmVhZHkgaW4uXG4gICAqXG4gICAqIGByZXNvbHZlUm91dGVzYCBwcmVmaXhlcyB0aGUgbG9jYWxlIGl0c2VsZiwgYXMgYCR7YmFzZVBhdGh9LyR7bG9jYWxlfSR7cGF0aG5hbWV9YFxuICAgKiDigJQgd2hpY2ggZm9yIHRoZSByb290IHR1cm5zIGAvYCBpbnRvIGAvZW4tVVMvYC4gVGhlIHNsYXNoLXN0cmlwcGluZyAzMDggdGhhdFxuICAgKiBgbmV4dCBidWlsZGAgYWx3YXlzIGNvbXBpbGVzIGludG8gYHJvdXRpbmcuYmVmb3JlTWlkZGxld2FyZWAgdGhlbiBtYXRjaGVzIGl0LFxuICAgKiBzbyBgR0VUIC9gIGNhbWUgYmFjayBhcyBhIHJlZGlyZWN0IG5vIGBuZXh0IHN0YXJ0YCBzZW5kczogbWVhc3VyZWQgYWdhaW5zdFxuICAgKiBgdGVzdC9lMmUvaTE4bi1zdXBwb3J0LWNhdGNoYWxsYCwgd2hlcmUgYC9gIGFuc3dlcnMgMjAwLiBOZXh0LmpzJ3Mgb3duIHJvdXRlclxuICAgKiBzcGVjaWFsLWNhc2VzIGV4YWN0bHkgdGhpcyAoYHJlc29sdmUtcm91dGVzLnRzYDogYHBhdGhuYW1lID09PSAnLycgP1xuICAgKiBgLyR7ZGVmYXVsdExvY2FsZX1gIDog4oCmYCkuXG4gICAqXG4gICAqIFdpdGggYHRyYWlsaW5nU2xhc2hgLCB0aGUgcHJlZml4ZWQgcm9vdCBrZWVwcyBpdHMgc2xhc2ggKGAvZW4tVVMvYCk6IHRoZVxuICAgKiBzbGFzaC0qYWRkaW5nKiAzMDggdGhhdCBidWlsZCBjb21waWxlcyBpbnN0ZWFkIG1hdGNoZXMgYC9lbi1VU2AgdGhlIHNhbWVcbiAgICogd2F5LCBhbmQgYC9lbi1VUy9gIGlzIHRoZSBjYW5vbmljYWwgVVJMIGBuZXh0IHN0YXJ0YCBzZXJ2ZXMgd2l0aCBhIDIwMC5cbiAgICpcbiAgICogT25seSB0aGUgcm9vdCwgYW5kIG9ubHkgd2hlbiBubyByZWRpcmVjdCBpcyBvd2VkOiBhIHJlcXVlc3Qgd2hvc2UgZGV0ZWN0ZWRcbiAgICogbG9jYWxlIGlzICpub3QqIHRoZSBkZWZhdWx0IGhhcyB0byByZWFjaCBgcmVzb2x2ZVJvdXRlc2AsIHdoaWNoIGFuc3dlcnMgaXRcbiAgICogd2l0aCB0aGUgMzA3IE5leHQuanMgc2VuZHMg4oCUIGFmdGVyIG1pZGRsZXdhcmUgaGFzIGhhZCB0aGUgcmVxdWVzdCwgd2hpY2ggaXNcbiAgICogdGhlIG9yZGVyaW5nIHRoYXQgbWF0dGVycyBhbmQgdGhlIHJlYXNvbiB0aGlzIGRvZXMgbm90IHJlZGlyZWN0IGl0c2VsZi5cbiAgICovXG4gIHByaXZhdGUgd2l0aFJvb3RMb2NhbGUodXJsOiBVUkwsIGhlYWRlcnM6IEhlYWRlcnMpOiBVUkwge1xuICAgIGNvbnN0IGkxOG4gPSB0aGlzLmkxOG47XG4gICAgaWYgKCFpMThuKSByZXR1cm4gdXJsO1xuICAgIGNvbnN0IHBhdGhuYW1lID0gdGhpcy53aXRob3V0QmFzZVBhdGgodXJsLnBhdGhuYW1lKTtcbiAgICBpZiAocGF0aG5hbWUgIT09IFwiL1wiKSByZXR1cm4gdXJsO1xuXG4gICAgY29uc3QgZGVmYXVsdExvY2FsZSA9XG4gICAgICBkZXRlY3REb21haW5Mb2NhbGUoaTE4bi5kb21haW5zLCB1cmwuaG9zdG5hbWUpPy5kZWZhdWx0TG9jYWxlID8/XG4gICAgICBpMThuLmRlZmF1bHRMb2NhbGU7XG4gICAgY29uc3QgZGV0ZWN0ZWQgPSBkZXRlY3RMb2NhbGUoe1xuICAgICAgcGF0aG5hbWUsXG4gICAgICBob3N0bmFtZTogdXJsLmhvc3RuYW1lLFxuICAgICAgY29va2llSGVhZGVyOiBoZWFkZXJzLmdldChcImNvb2tpZVwiKSA/PyB1bmRlZmluZWQsXG4gICAgICBhY2NlcHRMYW5ndWFnZUhlYWRlcjogaGVhZGVycy5nZXQoXCJhY2NlcHQtbGFuZ3VhZ2VcIikgPz8gdW5kZWZpbmVkLFxuICAgICAgaTE4bixcbiAgICB9KTtcbiAgICBpZiAoZGV0ZWN0ZWQubG9jYWxlICE9PSBkZWZhdWx0TG9jYWxlKSByZXR1cm4gdXJsO1xuXG4gICAgY29uc3QgcHJlZml4ZWQgPSBuZXcgVVJMKHVybC50b1N0cmluZygpKTtcbiAgICBwcmVmaXhlZC5wYXRobmFtZSA9IGAke3RoaXMubWFuaWZlc3QuY29uZmlnLmJhc2VQYXRofS8ke2RlZmF1bHRMb2NhbGV9JHtcbiAgICAgIHRoaXMudHJhaWxpbmdTbGFzaCA/IFwiL1wiIDogXCJcIlxuICAgIH1gO1xuICAgIHJldHVybiBwcmVmaXhlZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBhaXIgdGhlIHR3byB0aGluZ3MgYHJlc29sdmVSb3V0ZXNgIGdldHMgd3JvbmcgYWJvdXQgYSByZWRpcmVjdCBpdCBidWlsdFxuICAgKiBmcm9tIHRoZSBsb2NhbGUtcHJlZml4ZWQgcm9vdCDigJQgdGhlIHNhbWUgYCR7YmFzZVBhdGh9LyR7bG9jYWxlfSR7cGF0aG5hbWV9YFxuICAgKiBjb25jYXRlbmF0aW9uIGFzIGluIHtAbGluayB3aXRoUm9vdExvY2FsZX0sIHRoaXMgdGltZSByZXBvcnRlZCBhcyBhIGxvY2F0aW9uOlxuICAgKlxuICAgKiAtIHRoZSBzdHJheSB0cmFpbGluZyBzbGFzaCAoYC9ubC9gLCB3aGVyZSBOZXh0LmpzIHNlbmRzIGAvbmxgKSwgd2hpY2hcbiAgICogICBvdGhlcndpc2UgY29zdHMgYSBzZWNvbmQgcm91bmQgdHJpcCB0byB0aGUgMzA4IHRoYXQgc3RyaXBzIGl0LCBhbmRcbiAgICogLSB0aGUgYWJzb2x1dGUgVVJMLCB3aGVyZSBOZXh0LmpzIHNlbmRzIGEgcGF0aC4gQm90aCBhcmUgbGVnYWwsIGJ1dCBhIHRlc3RcbiAgICogICBhc3NlcnRpbmcgYGhlYWRlcnMubG9jYXRpb25gIHNlZXMgdGhlIGRpZmZlcmVuY2UsIGFuZCBzbyBkb2VzIGFueSBjbGllbnRcbiAgICogICBjb21wYXJpbmcgaXQgdG8gYSBsaW5rLlxuICAgKi9cbiAgcHJpdmF0ZSBub3JtYWxpemVSZWRpcmVjdExvY2F0aW9uKGxvY2F0aW9uOiBzdHJpbmcsIHJlcXVlc3Q6IFVSTCk6IHN0cmluZyB7XG4gICAgbGV0IHJlc29sdmVkOiBVUkw7XG4gICAgdHJ5IHtcbiAgICAgIHJlc29sdmVkID0gbmV3IFVSTChsb2NhdGlvbiwgcmVxdWVzdCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gbG9jYXRpb247XG4gICAgfVxuICAgIGlmIChyZXNvbHZlZC5vcmlnaW4gIT09IHJlcXVlc3Qub3JpZ2luKSByZXR1cm4gbG9jYXRpb247XG5cbiAgICBjb25zdCB0YXJnZXQgPSB0aGlzLndpdGhvdXRCYXNlUGF0aChyZXNvbHZlZC5wYXRobmFtZSk7XG4gICAgY29uc3QgaXNMb2NhbGVSb290ID1cbiAgICAgIHRoaXMuaTE4biAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAhdGhpcy50cmFpbGluZ1NsYXNoICYmXG4gICAgICB0aGlzLndpdGhvdXRCYXNlUGF0aChyZXF1ZXN0LnBhdGhuYW1lKSA9PT0gXCIvXCIgJiZcbiAgICAgIHRoaXMuaTE4bi5sb2NhbGVzLnNvbWUoKGxvY2FsZSkgPT4gdGFyZ2V0ID09PSBgLyR7bG9jYWxlfS9gKTtcbiAgICBpZiAoaXNMb2NhbGVSb290KSB7XG4gICAgICByZXNvbHZlZC5wYXRobmFtZSA9IHJlc29sdmVkLnBhdGhuYW1lLnNsaWNlKDAsIC0xKTtcbiAgICB9XG4gICAgcmV0dXJuIGAke3Jlc29sdmVkLnBhdGhuYW1lfSR7cmVzb2x2ZWQuc2VhcmNofSR7cmVzb2x2ZWQuaGFzaH1gO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBgaGVhZGVycygpYCBydWxlcyBhIHJlcXVlc3QgbWF0Y2hlZCwgZm9yIGEgcmVzcG9uc2UgbWlkZGxld2FyZSB3cm90ZVxuICAgKiBpdHNlbGYuXG4gICAqXG4gICAqIFRoZXkgY29tcGlsZSBpbnRvIGByb3V0aW5nLmJlZm9yZU1pZGRsZXdhcmVgLCBhbmQgYHJlc29sdmVSb3V0ZXNgIGFwcGxpZXNcbiAgICogdGhlbSB0aGVyZSwgYnV0IHdoZW4gbWlkZGxld2FyZSBhbnN3ZXJzIGl0IHJldHVybnMgYHsgbWlkZGxld2FyZVJlc3BvbmRlZDpcbiAgICogdHJ1ZSB9YCBhbmQgbm90aGluZyBlbHNlLCBzbyB0aGV5IHdlcmUgbG9zdDogYSBtaWRkbGV3YXJlIDQwMSB3ZW50IG91dFxuICAgKiB3aXRob3V0IHRoZSBhcHAncyBIU1RTIGFuZCBDU1AuIGBuZXh0IHN0YXJ0YCBzZW5kcyB0aGVtIHdpdGggaXQgKGl0c1xuICAgKiBgcmVzb2x2ZS1yb3V0ZXMuanNgIHNldHMgdGhlbSBvbiB0aGUgcmVzcG9uc2UgYmVmb3JlIG1pZGRsZXdhcmUgcnVucykuIFNvXG4gICAqIHRoYXQgb25lIHBoYXNlIGlzIHJ1biBhZ2FpbiBvbiBpdHMgb3duIOKAlCBubyBtaWRkbGV3YXJlLCBubyBmaWxlcywgbm90aGluZ1xuICAgKiBhZnRlciBpdCDigJQgd2hpY2ggbGVhdmVzIGV4YWN0bHkgdGhlIGhlYWRlcnMgaXQgc2V0LlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBiZWZvcmVNaWRkbGV3YXJlSGVhZGVycyhcbiAgICB1cmw6IFVSTCxcbiAgICBoZWFkZXJzOiBIZWFkZXJzLFxuICApOiBQcm9taXNlPEhlYWRlcnM+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCByZXNvbHZlUm91dGVzKHtcbiAgICAgIHVybCxcbiAgICAgIGJ1aWxkSWQ6IHRoaXMubWFuaWZlc3QuYnVpbGRJZCxcbiAgICAgIGJhc2VQYXRoOiB0aGlzLm1hbmlmZXN0LmNvbmZpZy5iYXNlUGF0aCxcbiAgICAgIGhlYWRlcnMsXG4gICAgICByZXF1ZXN0Qm9keTogbmV3IEJsb2IoW10pLnN0cmVhbSgpLFxuICAgICAgcGF0aG5hbWVzOiBbXSxcbiAgICAgIHJvdXRlczoge1xuICAgICAgICAuLi50aGlzLnJvdXRlcyxcbiAgICAgICAgbWlkZGxld2FyZU1hdGNoZXJzOiBbXSxcbiAgICAgICAgYmVmb3JlRmlsZXM6IFtdLFxuICAgICAgICBhZnRlckZpbGVzOiBbXSxcbiAgICAgICAgZHluYW1pY1JvdXRlczogW10sXG4gICAgICAgIG9uTWF0Y2g6IFtdLFxuICAgICAgICBmYWxsYmFjazogW10sXG4gICAgICB9LFxuICAgICAgaTE4bjogdGhpcy5pMThuLFxuICAgICAgaW52b2tlTWlkZGxld2FyZTogYXN5bmMgKCkgPT4gKHt9KSxcbiAgICB9KTtcbiAgICBjb25zdCByZXNwb25zZUhlYWRlcnMgPSBuZXcgSGVhZGVycyhyZXN1bHQucmVzb2x2ZWRIZWFkZXJzID8/IHVuZGVmaW5lZCk7XG4gICAgLy8gQSBsb2NhbGUtZGV0ZWN0aW9uIHJlZGlyZWN0IGlzIGRlY2lkZWQgYWZ0ZXIgbWlkZGxld2FyZSwgYW5kIG1pZGRsZXdhcmVcbiAgICAvLyBhbHJlYWR5IGFuc3dlcmVkLCBzbyBpdHMgYGxvY2F0aW9uYCBpcyBub3Qgb3dlZC5cbiAgICBpZiAocmVzdWx0LnJlZGlyZWN0KSB7XG4gICAgICByZXNwb25zZUhlYWRlcnMuZGVsZXRlKFwibG9jYXRpb25cIik7XG4gICAgfVxuICAgIHJldHVybiByZXNwb25zZUhlYWRlcnM7XG4gIH1cblxuICAvKipcbiAgICogVGhlIFVSTCB0byBvcHRpbWl6ZSwgb25jZSBgL19uZXh0L2ltYWdlYCBoYXMgcmVzb2x2ZWQ6IGFzIG1pZGRsZXdhcmVcbiAgICogcmV3cm90ZSBpdCwgb3IgYXMgcmVjZWl2ZWQg4oCUIG9yLCB3aGVuIGEgYG5leHQuY29uZmlnYCByZXdyaXRlIGlzIHdoYXQgcHV0XG4gICAqIHRoZSByZXF1ZXN0IG9uIHRoZSBpbWFnZSBwYXRoLCByZWJ1aWx0IGZyb20gdGhlIHF1ZXJ5IGByZXNvbHZlUm91dGVzYFxuICAgKiByZXNvbHZlZCwgd2hpY2ggaXMgdGhlIG9ubHkgcGxhY2UgdGhhdCByZXdyaXRlJ3MgZGVzdGluYXRpb24gcXVlcnkgaXMuXG4gICAqL1xuICBwcml2YXRlIGltYWdlVXJsKHJlc3VsdDogUmVzb2x2ZVJvdXRlc1Jlc3VsdCwgcmVjZWl2ZWQ6IFVSTCk6IFVSTCB7XG4gICAgaWYgKHJlY2VpdmVkLnBhdGhuYW1lID09PSB0aGlzLmltYWdlUGF0aG5hbWUpIHJldHVybiByZWNlaXZlZDtcbiAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHJlY2VpdmVkLnRvU3RyaW5nKCkpO1xuICAgIHVybC5wYXRobmFtZSA9IHRoaXMuaW1hZ2VQYXRobmFtZTtcbiAgICBpZiAocmVzdWx0LnJlc29sdmVkUXVlcnkpIHtcbiAgICAgIHVybC5zZWFyY2ggPSB0b1NlYXJjaChyZXN1bHQucmVzb2x2ZWRRdWVyeSk7XG4gICAgfVxuICAgIHJldHVybiB1cmw7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZGlzcGF0Y2gocmVxdWVzdDogRGlzcGF0Y2hSZXF1ZXN0KTogUHJvbWlzZTxEaXNwYXRjaFJlc3VsdD4ge1xuICAgIC8vIENvcGllZCBiZWNhdXNlIGByZXNvbHZlUm91dGVzYCBpcyBmcmVlIHRvIG11dGF0ZSB3aGF0IGl0IGlzIGhhbmRlZCwgYW5kXG4gICAgLy8gdGhlIGNhbGxlcidzIGhlYWRlcnMgb2JqZWN0IG91dGxpdmVzIHRoaXMgY2FsbC5cbiAgICBjb25zdCByZXF1ZXN0SGVhZGVycyA9IG5ldyBIZWFkZXJzKHJlcXVlc3QuaGVhZGVycyk7XG4gICAgLy8gQSBzZWNvbmQgY29weSwgYXMgdGhlIHJlcXVlc3QgcmVhY2hlZCBgYmVmb3JlTWlkZGxld2FyZWAsIGZvclxuICAgIC8vIHtAbGluayBiZWZvcmVNaWRkbGV3YXJlSGVhZGVyc30uXG4gICAgY29uc3QgcmVjZWl2ZWRIZWFkZXJzID0gbmV3IEhlYWRlcnMocmVxdWVzdC5oZWFkZXJzKTtcbiAgICBjb25zdCB1cmwgPSB0aGlzLndpdGhSb290TG9jYWxlKHJlcXVlc3QudXJsLCByZXF1ZXN0SGVhZGVycyk7XG4gICAgbGV0IG1pZGRsZXdhcmVSZXF1ZXN0SGVhZGVyczogSGVhZGVycyB8IHVuZGVmaW5lZDtcbiAgICBsZXQgbWlkZGxld2FyZVJld3JpdGU6IFVSTCB8IHVuZGVmaW5lZDtcbiAgICBsZXQgbWlkZGxld2FyZVJlc3BvbnNlOiBSZXNwb25zZSB8IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHJlc29sdmVSb3V0ZXMoe1xuICAgICAgdXJsLFxuICAgICAgYnVpbGRJZDogdGhpcy5tYW5pZmVzdC5idWlsZElkLFxuICAgICAgYmFzZVBhdGg6IHRoaXMubWFuaWZlc3QuY29uZmlnLmJhc2VQYXRoLFxuICAgICAgaGVhZGVyczogcmVxdWVzdEhlYWRlcnMsXG4gICAgICByZXF1ZXN0Qm9keTogcmVxdWVzdC5ib2R5LFxuICAgICAgcGF0aG5hbWVzOiB0aGlzLnRhYmxlLnBhdGhuYW1lcyxcbiAgICAgIHJvdXRlczogdGhpcy5yb3V0ZXMsXG4gICAgICBpMThuOiB0aGlzLmkxOG4sXG4gICAgICAvLyBPbmx5IGNhbGxlZCB3aGVuIGEgYG1pZGRsZXdhcmVNYXRjaGVyc2AgZW50cnkgbWF0Y2hlcywgd2hpY2ggb25seSBhXG4gICAgICAvLyBidWlsZCB3aXRoIG1pZGRsZXdhcmUgaGFzLlxuICAgICAgaW52b2tlTWlkZGxld2FyZTogYXN5bmMgKGN0eCkgPT4ge1xuICAgICAgICBjb25zdCB7IHJlc3BvbnNlLCAuLi5taWRkbGV3YXJlIH0gPSBhd2FpdCByZXF1ZXN0Lmludm9rZU1pZGRsZXdhcmUhKHtcbiAgICAgICAgICAuLi5jdHgsXG4gICAgICAgICAgbWV0aG9kOiByZXF1ZXN0Lm1ldGhvZCxcbiAgICAgICAgfSk7XG4gICAgICAgIG1pZGRsZXdhcmVSZXNwb25zZSA9IHJlc3BvbnNlO1xuICAgICAgICAvLyBgcmVzb2x2ZVJvdXRlc2AgZHJvcHMgYE1pZGRsZXdhcmVSZXN1bHQucmVxdWVzdEhlYWRlcnNgIGVudGlyZWx5OiBpdFxuICAgICAgICAvLyBuZWl0aGVyIHJldHVybnMgdGhlbSBub3IgbXV0YXRlcyB0aGUgYGhlYWRlcnNgIHBhc3NlZCBpbi4gQ2FwdHVyaW5nXG4gICAgICAgIC8vIHRoZW0gaGVyZSBpcyB3aGF0IGtlZXBzIGBOZXh0UmVzcG9uc2UubmV4dCh7IHJlcXVlc3Q6IHsgaGVhZGVycyB9IH0pYFxuICAgICAgICAvLyB3b3JraW5nLlxuICAgICAgICBpZiAobWlkZGxld2FyZS5yZXF1ZXN0SGVhZGVycykge1xuICAgICAgICAgIG1pZGRsZXdhcmVSZXF1ZXN0SGVhZGVycyA9IG1pZGRsZXdhcmUucmVxdWVzdEhlYWRlcnM7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ2FwdHVyZWQgZm9yIHRoZSBzYW1lIHJlYXNvbjogYHJlc29sdmVSb3V0ZXNgIHJvdXRlcyB0aGUgcmV3cml0dGVuIFVSTFxuICAgICAgICAvLyBpbnRlcm5hbGx5IGJ1dCBuZXZlciByZXBvcnRzIGl0IGJhY2ssIGFuZCBgL19uZXh0L2ltYWdlYCBpcyBtYXRjaGVkXG4gICAgICAgIC8vIGhlcmUgcmF0aGVyIHRoYW4gYnkgYHJlc29sdmVSb3V0ZXNgIChzZWUgYmVsb3cpLCBzbyB0aGlzIGlzIHRoZSBvbmx5XG4gICAgICAgIC8vIHdheSB0byBzZWUgdGhlIHBhdGggbWlkZGxld2FyZSBhY3R1YWxseSBhc2tlZCBmb3IuXG4gICAgICAgIGlmIChtaWRkbGV3YXJlLnJld3JpdGUpIHtcbiAgICAgICAgICBtaWRkbGV3YXJlUmV3cml0ZSA9IG1pZGRsZXdhcmUucmV3cml0ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWlkZGxld2FyZTtcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCByZXNwb25zZUhlYWRlcnMgPSBuZXcgSGVhZGVycyhyZXN1bHQucmVzb2x2ZWRIZWFkZXJzID8/IHVuZGVmaW5lZCk7XG4gICAgLy8gYEBuZXh0L3JvdXRpbmdgIGVjaG9lcyB0aGUgcmV3cml0ZSBpdCBmb2xsb3dlZCBpbnRvIGByZXNvbHZlZEhlYWRlcnNgO1xuICAgIC8vIE5leHQuanMncyBvd24gcm91dGVyIGNvbnN1bWVzIHRoYXQgaGVhZGVyIHJhdGhlciB0aGFuIHNlbmRpbmcgaXQsIGFuZCBzbyBkb1xuICAgIC8vIHdlIOKAlCBpdCBpcyBhbiBpbnRlcm5hbCByb3V0aW5nIHNpZ25hbCwgYW5kIGZvcndhcmRpbmcgaXQgd291bGQgZXhwb3NlIHRoZVxuICAgIC8vIGFwcCdzIHBvc3QtbWlkZGxld2FyZSBwYXRocyB0byBjbGllbnRzLlxuICAgIHJlc3BvbnNlSGVhZGVycy5kZWxldGUoXCJ4LW1pZGRsZXdhcmUtcmV3cml0ZVwiKTtcbiAgICBjb25zdCBmb3J3YXJkZWRIZWFkZXJzID0gbWlkZGxld2FyZVJlcXVlc3RIZWFkZXJzID8/IHJlcXVlc3RIZWFkZXJzO1xuICAgIGNvbnN0IHN0YXR1cyA9IHJlc3VsdC5zdGF0dXM7XG5cbiAgICBpZiAocmVzdWx0Lm1pZGRsZXdhcmVSZXNwb25kZWQgJiYgbWlkZGxld2FyZVJlc3BvbnNlKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBraW5kOiBcIm1pZGRsZXdhcmUtcmVzcG9uZGVkXCIsXG4gICAgICAgIHJlc3BvbnNlOiBtaWRkbGV3YXJlUmVzcG9uc2UsXG4gICAgICAgIHJlc3BvbnNlSGVhZGVyczogYXdhaXQgdGhpcy5iZWZvcmVNaWRkbGV3YXJlSGVhZGVycyhcbiAgICAgICAgICB1cmwsXG4gICAgICAgICAgcmVjZWl2ZWRIZWFkZXJzLFxuICAgICAgICApLFxuICAgICAgICBzdGF0dXMsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmIChyZXN1bHQuZXh0ZXJuYWxSZXdyaXRlKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBraW5kOiBcImV4dGVybmFsLXJld3JpdGVcIixcbiAgICAgICAgdXJsOiByZXN1bHQuZXh0ZXJuYWxSZXdyaXRlLFxuICAgICAgICByZXF1ZXN0SGVhZGVyczogZm9yd2FyZGVkSGVhZGVycyxcbiAgICAgICAgcmVzcG9uc2VIZWFkZXJzLFxuICAgICAgICBzdGF0dXMsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHJlZGlyZWN0ID0gdG9SZWRpcmVjdChyZXN1bHQsIHJlc3BvbnNlSGVhZGVycyk7XG4gICAgaWYgKHJlZGlyZWN0KSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBraW5kOiBcInJlZGlyZWN0XCIsXG4gICAgICAgIC4uLnJlZGlyZWN0LFxuICAgICAgICBsb2NhdGlvbjogdGhpcy5ub3JtYWxpemVSZWRpcmVjdExvY2F0aW9uKFxuICAgICAgICAgIHJlZGlyZWN0LmxvY2F0aW9uLFxuICAgICAgICAgIHJlcXVlc3QudXJsLFxuICAgICAgICApLFxuICAgICAgICByZXNwb25zZUhlYWRlcnMsXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIEJvdGggYXJlIGtleXMgaW50byBgZW50cnlwb2ludHNgL2BzdGF0aWNGaWxlc2AsIHdoaWNoIG5ldmVyIGNhcnJ5IGFcbiAgICAvLyB0cmFpbGluZyBzbGFzaDsgc2VlIHtAbGluayB3aXRoVHJhaWxpbmdTbGFzaFZhcmlhbnRzfS5cbiAgICBjb25zdCByZXNvbHZlZFBhdGhuYW1lID0gdGhpcy5ub3JtYWxpemVQYXRobmFtZShyZXN1bHQucmVzb2x2ZWRQYXRobmFtZSk7XG4gICAgLy8gSW4gYHBhdGhuYW1lc2AgKHNlZSB7QGxpbmsgYnVpbGRSb3V0aW5nVGFibGV9KSwgc28gaXQgcmVzb2x2ZXMgaW4gdGhlXG4gICAgLy8gZmlsZXN5c3RlbSBwaGFzZTogYWZ0ZXIgbWlkZGxld2FyZSBhbmQgYGJlZm9yZUZpbGVzYCwgYW5kIGJlZm9yZSBhbnlcbiAgICAvLyBkeW5hbWljIHJvdXRlLCB3aGljaCBpcyBgbmV4dCBzdGFydGAncyBvcmRlci4gVW5saXN0ZWQsIGEgcm9vdCBjYXRjaC1hbGxcbiAgICAvLyAoYGFwcC9bLi4uc2x1Z11gKSBvciBhbnkgdHdvLXNlZ21lbnQgZHluYW1pYyByb3V0ZSB0b29rIGV2ZXJ5IGltYWdlXG4gICAgLy8gcmVxdWVzdCBhcyBgc2x1ZzogW1wiX25leHRcIiwgXCJpbWFnZVwiXWAuXG4gICAgaWYgKHJlc29sdmVkUGF0aG5hbWUgPT09IHRoaXMuaW1hZ2VQYXRobmFtZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAga2luZDogXCJpbWFnZS1vcHRpbWl6YXRpb25cIixcbiAgICAgICAgdXJsOiB0aGlzLmltYWdlVXJsKHJlc3VsdCwgbWlkZGxld2FyZVJld3JpdGUgPz8gcmVxdWVzdC51cmwpLFxuICAgICAgICByZXF1ZXN0SGVhZGVyczogZm9yd2FyZGVkSGVhZGVycyxcbiAgICAgICAgcmVzcG9uc2VIZWFkZXJzLFxuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKHJlc29sdmVkUGF0aG5hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3Qgc3RhdGljRmlsZSA9IHRoaXMudGFibGUuc3RhdGljRmlsZXMuZ2V0KHJlc29sdmVkUGF0aG5hbWUpO1xuICAgICAgY29uc3QgYXNTdGF0aWNGaWxlID0gKFxuICAgICAgICBmaWxlOiBTdGF0aWNGaWxlVGFyZ2V0LFxuICAgICAgKTogRGlzcGF0Y2hTdGF0aWNGaWxlUmVzdWx0ID0+ICh7XG4gICAgICAgIGtpbmQ6IFwic3RhdGljLWZpbGVcIixcbiAgICAgICAgcGF0aG5hbWU6IHJlc29sdmVkUGF0aG5hbWUsXG4gICAgICAgIGZpbGVQYXRoOiBmaWxlLmZpbGVQYXRoLFxuICAgICAgICBzb3VyY2U6IGZpbGUuc291cmNlLFxuICAgICAgICByZXF1ZXN0SGVhZGVyczogZm9yd2FyZGVkSGVhZGVycyxcbiAgICAgICAgcmVzcG9uc2VIZWFkZXJzLFxuICAgICAgICBzdGF0dXMsXG4gICAgICB9KTtcbiAgICAgIC8vIEFoZWFkIG9mIHRoZSBlbnRyeXBvaW50cywgd2hpY2ggaXMgYG5leHQgc3RhcnRgJ3Mgb3JkZXI6IGl0cyBmaWxlc3lzdGVtXG4gICAgICAvLyBjaGVjayB0cmllcyBgX25leHQvc3RhdGljYCBhbmQgdGhlbiBgcHVibGljL2AgYmVmb3JlIGFueSBhcHAgb3IgcGFnZVxuICAgICAgLy8gcm91dGUsIHNvIGBwdWJsaWMvcm9ib3RzLnR4dGAgYmVhdHMgYGFwcC9yb2JvdHMudHNgIGFuZFxuICAgICAgLy8gYHB1YmxpYy9mYXZpY29uLmljb2AgYmVhdHMgYGFwcC9mYXZpY29uLmljb2AuXG4gICAgICBpZiAoc3RhdGljRmlsZSAmJiBzdGF0aWNGaWxlLnNvdXJjZSAhPT0gXCJzZXJ2ZXJcIikge1xuICAgICAgICByZXR1cm4gYXNTdGF0aWNGaWxlKHN0YXRpY0ZpbGUpO1xuICAgICAgfVxuICAgICAgY29uc3QgZW50cnlwb2ludCA9IHRoaXMubWFuaWZlc3QuZW50cnlwb2ludHNbcmVzb2x2ZWRQYXRobmFtZV07XG4gICAgICBpZiAoZW50cnlwb2ludCkge1xuICAgICAgICBjb25zdCBxdWVyeSA9IHJlcGFpclJvdXRlUGFyYW1RdWVyeShcbiAgICAgICAgICByZXN1bHQucmVzb2x2ZWRRdWVyeSA/PyB7fSxcbiAgICAgICAgICByZXN1bHQucm91dGVNYXRjaGVzID8/IHt9LFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGtpbmQ6IFwiZW50cnlwb2ludFwiLFxuICAgICAgICAgIGVudHJ5cG9pbnQsXG4gICAgICAgICAgcmVzb2x2ZWRQYXRobmFtZSxcbiAgICAgICAgICAvLyBgaW52b2NhdGlvblRhcmdldGAgaXMgYWx3YXlzIHByZXNlbnQgYWxvbmdzaWRlIGByZXNvbHZlZFBhdGhuYW1lYCBpblxuICAgICAgICAgIC8vIHByYWN0aWNlOyB0aGUgZmFsbGJhY2sga2VlcHMgYSBgbmV4dGAgc2hhcGUgY2hhbmdlIGZyb20gY3Jhc2hpbmcuXG4gICAgICAgICAgaW52b2NhdGlvblRhcmdldDoge1xuICAgICAgICAgICAgcGF0aG5hbWU6XG4gICAgICAgICAgICAgIHRoaXMubm9ybWFsaXplUGF0aG5hbWUocmVzdWx0Lmludm9jYXRpb25UYXJnZXQ/LnBhdGhuYW1lKSA/P1xuICAgICAgICAgICAgICByZXNvbHZlZFBhdGhuYW1lLFxuICAgICAgICAgICAgcXVlcnksXG4gICAgICAgICAgfSxcbiAgICAgICAgICByZXF1ZXN0SGVhZGVyczogZm9yd2FyZGVkSGVhZGVycyxcbiAgICAgICAgICByZXNwb25zZUhlYWRlcnMsXG4gICAgICAgICAgc3RhdHVzLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgaWYgKHN0YXRpY0ZpbGUpIHtcbiAgICAgICAgcmV0dXJuIGFzU3RhdGljRmlsZShzdGF0aWNGaWxlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoc3RhdHVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiB7IGtpbmQ6IFwicmVzcG9uc2VcIiwgc3RhdHVzLCByZXNwb25zZUhlYWRlcnMgfTtcbiAgICB9XG5cbiAgICBjb25zdCByZXNvbHZlZFVybCA9IG1pZGRsZXdhcmVSZXdyaXRlID8/IHJlcXVlc3QudXJsO1xuICAgIHJldHVybiB7XG4gICAgICBraW5kOiBcIm5vdC1mb3VuZFwiLFxuICAgICAgcGF0aG5hbWU6IHJlc29sdmVkUGF0aG5hbWUgPz8gcmVzb2x2ZWRVcmwucGF0aG5hbWUsXG4gICAgICByZXF1ZXN0SGVhZGVyczogZm9yd2FyZGVkSGVhZGVycyxcbiAgICAgIHJlc3BvbnNlSGVhZGVycyxcbiAgICB9O1xuICB9XG59XG5cbi8qKiBBIHN0YXRpYyBmaWxlLCBhcyBkaXNwYXRjaCByZXNvbHZlcyBvbmUuICovXG5pbnRlcmZhY2UgU3RhdGljRmlsZVRhcmdldCB7XG4gIHJlYWRvbmx5IGZpbGVQYXRoOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHNvdXJjZTogU3RhdGljRmlsZVNvdXJjZTtcbn1cblxuLyoqXG4gKiBXaGF0IGRpc3BhdGNoIG1hdGNoZXMgYSByZXF1ZXN0IGFnYWluc3QsIGRlcml2ZWQgb25jZSBmcm9tIHRoZSBtYW5pZmVzdCBhbmRcbiAqIGBwdWJsaWMvYDogd2l0aCBhIGZldyB0aG91c2FuZCBgcHVibGljL2AgZmlsZXMgdGhlIGRlcml2YXRpb24gd291bGQgYmUgbW9zdFxuICogb2YgdGhlIGNvc3Qgb2YgYSBkaXNwYXRjaC5cbiAqL1xuaW50ZXJmYWNlIFJvdXRpbmdUYWJsZSB7XG4gIC8qKlxuICAgKiBFdmVyeSBwYXRobmFtZSBgcmVzb2x2ZVJvdXRlc2AgbWF5IG1hdGNoOiB0aGUgbWFuaWZlc3QncywgZXZlcnkgc3BlbGxpbmcgb2ZcbiAgICogZXZlcnkgc3RhdGljIGZpbGUsIGFuZCDigJQgZm9yIGEgYHRyYWlsaW5nU2xhc2hgIGFwcCDigJQgdGhlIHNsYXNoIHZhcmlhbnRzLlxuICAgKi9cbiAgcmVhZG9ubHkgcGF0aG5hbWVzOiBzdHJpbmdbXTtcbiAgLyoqIEV2ZXJ5IHNwZWxsaW5nIGEgc3RhdGljIGZpbGUgaXMgcmVxdWVzdGVkIGJ5IOKGkiB0aGUgZmlsZS4gKi9cbiAgcmVhZG9ubHkgc3RhdGljRmlsZXM6IFJlYWRvbmx5TWFwPHN0cmluZywgU3RhdGljRmlsZVRhcmdldD47XG59XG5cbi8qKlxuICogQnVpbGQgb3V0cHV0cyBmaXJzdCwgdGhlbiBgcHVibGljL2Agb24gdG9wIG9mIHRoZW0sIGV4Y2VwdCBvdmVyXG4gKiBgX25leHQvc3RhdGljYDogdGhhdCBpcyBgbmV4dCBzdGFydGAncyBwcmVjZWRlbmNlIChzZWVcbiAqIHtAbGluayBEaXNwYXRjaGVyLmRpc3BhdGNofSkuXG4gKlxuICogQSBgcHVibGljL2AgZmlsZSBpcyByZWdpc3RlcmVkIHVuZGVyIGl0cyBwYXRobmFtZSB3aXRoIHRoZSBkZWZhdWx0IGxvY2FsZSBpblxuICogZnJvbnQsIHRvbywgZm9yIGFuIGkxOG4gYXBwLiBgcmVzb2x2ZVJvdXRlc2AgcHV0cyBhIGxvY2FsZSBvbiBldmVyeSBwYXRoXG4gKiBvdXRzaWRlIGAvX25leHQvYCBhbmQgYC9hcGkvYCBiZWZvcmUgaXQgbWF0Y2hlcywgc28gYC90ZXN0LnR4dGAgaXMgbG9va2VkIHVwXG4gKiBhcyBgL2VuLVVTL3Rlc3QudHh0YCBhbmQgbmV2ZXIgbWF0Y2hlZCB0aGUgYmFyZSBrZXk6IG5vIGBwdWJsaWMvYCBmaWxlXG4gKiByZXNvbHZlZCBpbiBhbiBpMThuIGFwcCBhdCBhbGwuIGBuZXh0IHN0YXJ0YCBzdHJpcHMgdGhlIGRlZmF1bHQgbG9jYWxlIOKAlCBhbmRcbiAqIGVhY2ggZG9tYWluJ3Mg4oCUIG9mZiBhIGBwdWJsaWMvYCByZXF1ZXN0IGFuZCBubyBvdGhlciBsb2NhbGUgKGZpbGVzeXN0ZW0uanM6XG4gKiBcImxlZ2FjeSBiZWhhdmlvciBhbGxvd3MgdmlzaXRpbmcgc3RhdGljIGFzc2V0cyB1bmRlciBkZWZhdWx0IGxvY2FsZSBidXQgbm9cbiAqIG90aGVyIGxvY2FsZVwiKSwgd2hpY2ggdGhlc2UgZW50cmllcyByZXByb2R1Y2U6IGAvZW4tVVMvdGVzdC50eHRgIHNlcnZlcyBhbmRcbiAqIGAvZnIvdGVzdC50eHRgIGRvZXMgbm90LlxuICovXG5mdW5jdGlvbiBidWlsZFJvdXRpbmdUYWJsZShcbiAgbWFuaWZlc3Q6IEFkYXB0ZXJNYW5pZmVzdCxcbiAgcHVibGljRmlsZXM6IHJlYWRvbmx5IHN0cmluZ1tdLFxuKTogUm91dGluZ1RhYmxlIHtcbiAgY29uc3QgeyBiYXNlUGF0aCwgdHJhaWxpbmdTbGFzaCB9ID0gbWFuaWZlc3QuY29uZmlnO1xuICBjb25zdCBzdGF0aWNGaWxlcyA9IG5ldyBNYXA8c3RyaW5nLCBTdGF0aWNGaWxlVGFyZ2V0PigpO1xuICBjb25zdCBuZXh0U3RhdGljUHJlZml4ID0gYCR7YmFzZVBhdGh9L19uZXh0L3N0YXRpYy9gO1xuXG4gIGZvciAoY29uc3QgW3BhdGhuYW1lLCBmaWxlUGF0aF0gb2YgT2JqZWN0LmVudHJpZXMobWFuaWZlc3Quc3RhdGljRmlsZXMpKSB7XG4gICAgY29uc3QgdGFyZ2V0OiBTdGF0aWNGaWxlVGFyZ2V0ID0ge1xuICAgICAgZmlsZVBhdGgsXG4gICAgICBzb3VyY2U6IHBhdGhuYW1lLnN0YXJ0c1dpdGgobmV4dFN0YXRpY1ByZWZpeCkgPyBcIm5leHQtc3RhdGljXCIgOiBcInNlcnZlclwiLFxuICAgIH07XG4gICAgLy8gVGhlIGtleSBhcyBOZXh0LmpzIHJlcG9ydGVkIGl0LCBhbmQgdGhlbiBhcyBhIHJlcXVlc3Qgc3BlbGxzIGl0OiBhIGJ1aWxkXG4gICAgLy8gb3V0cHV0J3MgcGF0aG5hbWUgaXMgdGhlIGZpbGUncyBvd24gbmFtZSwgdW5lbmNvZGVkLCBhbmQgdGhlIEhUTUwgdGhhdFxuICAgIC8vIGxvYWRzIGl0IHBlcmNlbnQtZW5jb2RlcyBpdC4gYGFwcC9pc3IvW2lkXS9wYWdlLnRzeGAncyB3ZWJwYWNrIGNodW5rIGlzXG4gICAgLy8gYC9fbmV4dC9zdGF0aWMvY2h1bmtzL2FwcC9pc3IvW2lkXS9wYWdlLTxoYXNoPi5qc2AgaW4gdGhlIG91dHB1dHMgYW5kXG4gICAgLy8gYOKApi9pc3IvJTVCaWQlNUQvcGFnZS08aGFzaD4uanNgIGluIHRoZSBgPHNjcmlwdD5gIHRhZy5cbiAgICBmb3IgKGNvbnN0IHNwZWxsaW5nIG9mIFtwYXRobmFtZSwgLi4ucmVxdWVzdFNwZWxsaW5ncyhwYXRobmFtZSldKSB7XG4gICAgICBpZiAoIXN0YXRpY0ZpbGVzLmhhcyhzcGVsbGluZykpIHtcbiAgICAgICAgc3RhdGljRmlsZXMuc2V0KHNwZWxsaW5nLCB0YXJnZXQpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHB1YmxpY0RpciA9IHB1YmxpY0RpcktleShtYW5pZmVzdCk7XG4gIGNvbnN0IGkxOG4gPSBhc0kxOG4obWFuaWZlc3QuY29uZmlnLmkxOG4pO1xuICBjb25zdCBsb2NhbGVQcmVmaXhlcyA9IFtcbiAgICBcIlwiLFxuICAgIC4uLm5ldyBTZXQoXG4gICAgICBpMThuXG4gICAgICAgID8gW1xuICAgICAgICAgICAgaTE4bi5kZWZhdWx0TG9jYWxlLFxuICAgICAgICAgICAgLi4uKGkxOG4uZG9tYWlucyA/PyBbXSkubWFwKChkb21haW4pID0+IGRvbWFpbi5kZWZhdWx0TG9jYWxlKSxcbiAgICAgICAgICBdLm1hcCgobG9jYWxlKSA9PiBgLyR7bG9jYWxlfWApXG4gICAgICAgIDogW10sXG4gICAgKSxcbiAgXTtcbiAgZm9yIChjb25zdCBmaWxlIG9mIHB1YmxpY0ZpbGVzKSB7XG4gICAgY29uc3QgdGFyZ2V0OiBTdGF0aWNGaWxlVGFyZ2V0ID0ge1xuICAgICAgZmlsZVBhdGg6IGAke3B1YmxpY0Rpcn0vJHtmaWxlfWAsXG4gICAgICBzb3VyY2U6IFwicHVibGljXCIsXG4gICAgfTtcbiAgICBmb3IgKGNvbnN0IHNwZWxsaW5nIG9mIHJlcXVlc3RTcGVsbGluZ3MoYC8ke2ZpbGV9YCkpIHtcbiAgICAgIGZvciAoY29uc3QgcHJlZml4IG9mIGxvY2FsZVByZWZpeGVzKSB7XG4gICAgICAgIGNvbnN0IHBhdGhuYW1lID0gYCR7YmFzZVBhdGh9JHtwcmVmaXh9JHtzcGVsbGluZ31gO1xuICAgICAgICBpZiAoc3RhdGljRmlsZXMuZ2V0KHBhdGhuYW1lKT8uc291cmNlICE9PSBcIm5leHQtc3RhdGljXCIpIHtcbiAgICAgICAgICBzdGF0aWNGaWxlcy5zZXQocGF0aG5hbWUsIHRhcmdldCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBgL19uZXh0L2ltYWdlYCBpcyBub3QgYW4gYWRhcHRlciBvdXRwdXQsIGJ1dCBpdCBpcyBhIGZpbGVzeXN0ZW0gcm91dGUgdG9cbiAgLy8gYG5leHQgc3RhcnRgIChgZmlsZXN5c3RlbS5qc2AgYW5zd2VycyBpdCBhcyBgbmV4dEltYWdlYCksIGFuZCBsaXN0aW5nIGl0IGlzXG4gIC8vIHdoYXQgbGV0cyBpdCByZXNvbHZlIGFoZWFkIG9mIHRoZSBkeW5hbWljIHJvdXRlczsgc2VlXG4gIC8vIHtAbGluayBEaXNwYXRjaGVyLmRpc3BhdGNofS5cbiAgY29uc3QgcGF0aG5hbWVzID0gW1xuICAgIC4uLm5ldyBTZXQoW1xuICAgICAgLi4ubWFuaWZlc3QucGF0aG5hbWVzLFxuICAgICAgLi4uc3RhdGljRmlsZXMua2V5cygpLFxuICAgICAgYCR7YmFzZVBhdGh9L19uZXh0L2ltYWdlYCxcbiAgICBdKSxcbiAgXTtcbiAgcmV0dXJuIHtcbiAgICBwYXRobmFtZXM6IHRyYWlsaW5nU2xhc2ggPyB3aXRoVHJhaWxpbmdTbGFzaFZhcmlhbnRzKHBhdGhuYW1lcykgOiBwYXRobmFtZXMsXG4gICAgc3RhdGljRmlsZXMsXG4gIH07XG59XG5cbi8qKlxuICogVGhlIHdheXMgYSByZXF1ZXN0IHNwZWxscyBhbiB1bmVuY29kZWQgcGF0aCwgZm9yIHRoZSBleGFjdCBtYXRjaFxuICogYEBuZXh0L3JvdXRpbmdgIGRvZXMgYWdhaW5zdCBgcGF0aG5hbWVzYC5cbiAqXG4gKiBUd28sIGJlY2F1c2UgdGhlcmUgYXJlIHR3byB3YXlzIHRvIHdyaXRlIGEgbGluayB0byBgcHVibGljL2ltYWdlcy9sb2dvQDJ4LnBuZ2BcbiAqIGFuZCBhIGJyb3dzZXIgc2VuZHMgZWFjaCBhcyB3cml0dGVuOiBgL2ltYWdlcy9sb2dvQDJ4LnBuZ2AsIHdoaWNoIHRoZSBXSEFUV0dcbiAqIFVSTCBwYXJzZXIgbGVhdmVzIGFsb25lIOKAlCBpdCBvbmx5IGVuY29kZXMgc3BhY2VzLCBxdW90ZXMsIGAjYCwgYD9gLCBgPD5gLFxuICogYGAgYCBgYCwgYHt9YCBhbmQgbm9uLUFTQ0lJIGluIGEgcGF0aCDigJQgYW5kIGAvaW1hZ2VzL2xvZ28lNDAyeC5wbmdgLCB3aGljaCBpc1xuICogYGVuY29kZVVSSUNvbXBvbmVudGAgYSBzZWdtZW50IGF0IGEgdGltZSBhbmQgaXMgaG93IE5leHQuanMga2V5cyBpdHMgb3duXG4gKiBgcHVibGljL2Agc2V0IChgZW5jb2RlVVJJUGF0aGApLiBGb3IgbW9zdCBuYW1lcyB0aGUgdHdvIGFyZSB0aGUgc2FtZSBzdHJpbmc7XG4gKiB0aGV5IGRpZmZlciBmb3IgYEAgKyAmICwgOyA9ICQgOiBbIF1gIGFuZCB0aGUgbGlrZSwgYW5kIGEga2V5IGluIG9ubHkgdGhlXG4gKiBzZWNvbmQgZm9ybSA0MDQnZCBldmVyeSBgbG9nb0AyeC5wbmdgLCBgYysrLnN2Z2AgYW5kIGBpY29uWzFdLnBuZ2AuXG4gKlxuICogYCVgIGlzIGVuY29kZWQgaW4gYm90aCwgc2luY2UgYSBsaXRlcmFsIGAlYCBpbiBhIG5hbWUgY2FuIG9ubHkgYmUgcmVxdWVzdGVkXG4gKiBhcyBgJTI1YDsgc28gYXJlIGA/YCBhbmQgYCNgLCB3aGljaCB3b3VsZCBvdGhlcndpc2UgZW5kIHRoZSBwYXRoLCBhbmQgYFxcYCxcbiAqIHdoaWNoIHRoZSBwYXJzZXIgdHVybnMgaW50byBgL2AuXG4gKi9cbmZ1bmN0aW9uIHJlcXVlc3RTcGVsbGluZ3MocGF0aDogc3RyaW5nKTogc3RyaW5nW10ge1xuICBjb25zdCBzZWdtZW50cyA9IHBhdGguc3BsaXQoXCIvXCIpO1xuICBjb25zdCBlbmNvZGVkID0gc2VnbWVudHMubWFwKGVuY29kZVVSSUNvbXBvbmVudCkuam9pbihcIi9cIik7XG4gIGNvbnN0IHBhcnNlZCA9IG5ldyBVUkwoXG4gICAgc2VnbWVudHNcbiAgICAgIC5tYXAoKHNlZ21lbnQpID0+IHNlZ21lbnQucmVwbGFjZSgvWyU/I1xcXFxdL2csIGVuY29kZVVSSUNvbXBvbmVudCkpXG4gICAgICAuam9pbihcIi9cIiksXG4gICAgXCJodHRwOi8vblwiLFxuICApLnBhdGhuYW1lO1xuICByZXR1cm4gcGFyc2VkID09PSBlbmNvZGVkID8gW2VuY29kZWRdIDogW2VuY29kZWQsIHBhcnNlZF07XG59XG5cbi8qKlxuICogTm9ybWFsaXplIHRoZSB0d28gc2hhcGVzIGByZXNvbHZlUm91dGVzYCByZXBvcnRzIGEgcmVkaXJlY3QgaW4uXG4gKlxuICogYFJlc29sdmVSb3V0ZXNSZXN1bHQucmVkaXJlY3RgIGlzIGRvY3VtZW50ZWQsIGFuZCBhbiBpMThuIGxvY2FsZS1kZXRlY3Rpb24gMzA3XG4gKiBhcnJpdmVzIHRoYXQgd2F5LCBidXQgdGhlIHJlc3Qg4oCUIHRoZSBzbGFzaC1zdHJpcHBpbmcgMzA4LCBhIG1pZGRsZXdhcmVcbiAqIGBOZXh0UmVzcG9uc2UucmVkaXJlY3QoKWAg4oCUIGFycml2ZSBpbnN0ZWFkIGFzIGEgYmFyZSBgc3RhdHVzYCB3aXRoIGBsb2NhdGlvbmBcbiAqIGluIGByZXNvbHZlZEhlYWRlcnNgLiBgbmV4dC5jb25maWdgIGByZWRpcmVjdHMoKWAgdG9vOiB0aGV5IGNvbXBpbGUgdG8gcm91dGVzXG4gKiBjYXJyeWluZyBgaGVhZGVyczogeyBMb2NhdGlvbiB9YCBwbHVzIGBzdGF0dXNgLiBCb3RoIHNoYXBlcyBhcmUgaGFuZGxlZCwgYW5kXG4gKiB7QGxpbmsgRGlzcGF0Y2hlci5ub3JtYWxpemVSZWRpcmVjdExvY2F0aW9ufSB0aGVuIHB1dHMgdGhlIGxvY2F0aW9uIGl0c2VsZiBpblxuICogdGhlIGZvcm0gTmV4dC5qcyBzZW5kcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvUmVkaXJlY3QoXG4gIHJlc3VsdDogUmVzb2x2ZVJvdXRlc1Jlc3VsdCxcbiAgcmVzcG9uc2VIZWFkZXJzOiBIZWFkZXJzLFxuKTogeyBsb2NhdGlvbjogc3RyaW5nOyBzdGF0dXM6IG51bWJlciB9IHwgdW5kZWZpbmVkIHtcbiAgaWYgKHJlc3VsdC5yZWRpcmVjdCkge1xuICAgIHJldHVybiB7XG4gICAgICBsb2NhdGlvbjogcmVzdWx0LnJlZGlyZWN0LnVybC5ocmVmLFxuICAgICAgc3RhdHVzOiByZXN1bHQucmVkaXJlY3Quc3RhdHVzLFxuICAgIH07XG4gIH1cbiAgY29uc3QgbG9jYXRpb24gPSByZXNwb25zZUhlYWRlcnMuZ2V0KFwibG9jYXRpb25cIik7XG4gIGlmIChcbiAgICBsb2NhdGlvbiAhPT0gbnVsbCAmJlxuICAgIHJlc3VsdC5zdGF0dXMgIT09IHVuZGVmaW5lZCAmJlxuICAgIHJlc3VsdC5zdGF0dXMgPj0gMzAwICYmXG4gICAgcmVzdWx0LnN0YXR1cyA8IDQwMFxuICApIHtcbiAgICByZXR1cm4geyBsb2NhdGlvbiwgc3RhdHVzOiByZXN1bHQuc3RhdHVzIH07XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBBZGQgYDxwYXRobmFtZT4vYCBhbG9uZ3NpZGUgZXZlcnkgcm91dGUgcGF0aG5hbWUsIGZvciBhIGB0cmFpbGluZ1NsYXNoYCBhcHAuXG4gKlxuICogYHRyYWlsaW5nU2xhc2g6IHRydWVgIG1ha2VzIGAvYS9gIHRoZSBjYW5vbmljYWwgVVJMIOKAlCBOZXh0LmpzIGNvbXBpbGVzIGFcbiAqIGBwcmlvcml0eWAgMzA4IGZyb20gYC9hYCB0byBgL2EvYCBpbnRvIGByb3V0aW5nLmJlZm9yZU1pZGRsZXdhcmVgLCBhbmQgdGhhdFxuICogcmVkaXJlY3QgaXMgdGhlICpmaXJzdCogdGhpbmcgYHJlc29sdmVSb3V0ZXNgIGFwcGxpZXMuIEJ1dCB0aGUgYnVpbGQncyBvdXRwdXRcbiAqIHBhdGhuYW1lcyBoYXZlIG5vIHRyYWlsaW5nIHNsYXNoIChgL2FgLCBgL2FwaS9yZXZhbGlkYXRlYCksIGFuZFxuICogYEBuZXh0L3JvdXRpbmdgIG1hdGNoZXMgdGhlbSBieSBleGFjdCBzdHJpbmcgZXF1YWxpdHkgd2l0aCBubyBub3JtYWxpemF0aW9uIG9mXG4gKiBpdHMgb3duLiBTbyBldmVyeSBjYW5vbmljYWwgVVJMIGluIHN1Y2ggYW4gYXBwIHJlc29sdmVkIHRvIG5vdGhpbmc6IGJyb3dzZXJzXG4gKiBmb2xsb3dlZCB0aGUgMzA4IHRvIGAvYS9gIGFuZCBnb3QgYSA0MDQsIGFuZCBgZmV0Y2goJy9hcGkvcmV2YWxpZGF0ZScpYCBnb3RcbiAqIHRoZSA0MDQgKnBhZ2UqIOKAlCBtZWFzdXJlZCBhZ2FpbnN0IG5leHQuanMncyBgdGVzdC9lMmUvYXBwLWRpci90cmFpbGluZ3NsYXNoYCxcbiAqIHdoZXJlIDYgb2YgOCBjYXNlcyBmYWlsZWQgdGhpcyB3YXkuIER5bmFtaWMgcm91dGVzIGVzY2FwZWQgaXQgb25seSBiZWNhdXNlXG4gKiB0aGVpciBgc291cmNlUmVnZXhgIGhhcHBlbnMgdG8gZW5kIGluIGAoPzovKT9gLlxuICpcbiAqIE5vcm1hbGl6aW5nIHRoZSByZXF1ZXN0IFVSTCBiZWZvcmUgYHJlc29sdmVSb3V0ZXNgIGluc3RlYWQgd291bGQgYmUgd3Jvbmc6IHRoZVxuICogYWRkLXNsYXNoIHJlZGlyZWN0IG1hdGNoZXMgdGhlICpzbGFzaGxlc3MqIHBhdGgsIHNvIGEgbm9ybWFsaXplZCBgL2EvYCB3b3VsZFxuICogY29tZSBiYWNrIGFzIGEgMzA4IHRvIGAvYS9gIGFuZCBsb29wLiBUZWFjaGluZyB0aGUgbWF0Y2ggYWJvdXQgdGhlIHNsYXNoIGFuZFxuICogbm9ybWFsaXppbmcgaXQgb2ZmIHRoZSAqcmVzdWx0KiAoe0BsaW5rIERpc3BhdGNoZXIubm9ybWFsaXplUGF0aG5hbWV9KSBrZWVwc1xuICogdGhlIHJlZGlyZWN0IGV4YWN0bHkgYXMgTmV4dC5qcyBjb21waWxlZCBpdC5cbiAqXG4gKiBQYXRobmFtZXMgd2hvc2UgbGFzdCBzZWdtZW50IGhhcyBhbiBleHRlbnNpb24gYXJlIHNraXBwZWQ6IHRob3NlIGFyZSBzdGF0aWNcbiAqIGZpbGVzLCBhbmQgTmV4dC5qcyBjb21waWxlcyB0aGUgb3Bwb3NpdGUgcmVkaXJlY3QgZm9yIHRoZW0gKGAveC5qcy9gIOKGkiAzMDhcbiAqIGAveC5qc2ApLCB3aGljaCB0aGlzIG11c3Qgbm90IHNoYWRvdy5cbiAqL1xuZnVuY3Rpb24gd2l0aFRyYWlsaW5nU2xhc2hWYXJpYW50cyhwYXRobmFtZXM6IHN0cmluZ1tdKTogc3RyaW5nW10ge1xuICBjb25zdCB2YXJpYW50czogc3RyaW5nW10gPSBbXTtcbiAgZm9yIChjb25zdCBwYXRobmFtZSBvZiBwYXRobmFtZXMpIHtcbiAgICB2YXJpYW50cy5wdXNoKHBhdGhuYW1lKTtcbiAgICBpZiAocGF0aG5hbWUgIT09IFwiL1wiICYmICEvXFwuW14vXSskLy50ZXN0KHBhdGhuYW1lKSkge1xuICAgICAgdmFyaWFudHMucHVzaChgJHtwYXRobmFtZX0vYCk7XG4gICAgfVxuICB9XG4gIHJldHVybiB2YXJpYW50cztcbn1cblxuLyoqXG4gKiBDb3JyZWN0IHRoZSBgbnh0UGAgcm91dGUgcGFyYW1zIGluIGEgcmVzb2x2ZWQgcXVlcnkgZnJvbSBgcm91dGVNYXRjaGVzYC5cbiAqXG4gKiBgQG5leHQvcm91dGluZ2AgZXhwYW5kcyBhIGR5bmFtaWMgcm91dGUncyBkZXN0aW5hdGlvblxuICogKGAvW2lkXS9baWQyXT9ueHRQaWQ9JG54dFBpZCZueHRQaWQyPSRueHRQaWQyYCkgYnkgbG9vcGluZyBvdmVyIHRoZSBzb3VyY2VcbiAqIHJlZ2V4J3MgbmFtZWQgZ3JvdXBzIGFuZCBkb2luZyBvbmUgZ2xvYmFsIHN0cmluZyByZXBsYWNlIHBlciBncm91cCBuYW1lLiBHcm91cFxuICogbmFtZXMgYXJlIHN1YnN0aXR1dGVkIGluIGluc2VydGlvbiBvcmRlciwgc28gYCRueHRQaWRgIOKAlCBhICpwcmVmaXgqIG9mXG4gKiBgJG54dFBpZDJgIOKAlCBpcyByZXBsYWNlZCBmaXJzdCBhbmQgbGVhdmVzIHRoZSB0cmFpbGluZyBgMmAgYmVoaW5kIGFzIGFcbiAqIGxpdGVyYWw6IGAvYS9iYCByZXNvbHZlcyB3aXRoIGBueHRQaWQyPWEyYCBpbnN0ZWFkIG9mIGBueHRQaWQyPWJgLiBOZXh0LmpzXG4gKiByZWNvdmVycyBgcGFyYW1zYCBmcm9tIGV4YWN0bHkgdGhlc2UgcXVlcnkgdmFsdWVzIChgUm91dGVNb2R1bGUucHJlcGFyZWApLCBzb1xuICogdGhlIHBhZ2UgcmVuZGVycyBgaWQyOiBcImEyXCJgIOKAlCBtZWFzdXJlZCBhZ2FpbnN0XG4gKiBgdGVzdC9lMmUvYXBwLWRpci91c2UtcGFyYW1zYCwgd2hvc2UgZml4dHVyZSBpcyBgYXBwL1tpZF0vW2lkMl0vcGFnZS50c3hgLlxuICpcbiAqIGByb3V0ZU1hdGNoZXNgIGlzIHRoZSByYXcgY2FwdHVyZSBtYXAsIGJlZm9yZSBhbnkgZGVzdGluYXRpb24gZXhwYW5zaW9uLCBzbyBpdFxuICogaXMgdGhlIGF1dGhvcml0eSBmb3IgZXZlcnkgcGFyYW0gaXQgbmFtZXMuIE9ubHkga2V5cyB0aGUgZXhwYW5zaW9uIGFscmVhZHlcbiAqIHByb2R1Y2VkIGFyZSBvdmVyd3JpdHRlbjogYWRkaW5nIG90aGVycyB3b3VsZCBpbnZlbnQgcGFyYW1zIGZvciBhIHJld3JpdGUgdGhhdFxuICogZGVsaWJlcmF0ZWx5IGRyb3BwZWQgdGhlbS5cbiAqXG4gKiBUaGUgc2FtZSBwcmVmaXggY29sbGlzaW9uIHJlYWNoZXMgcG9zaXRpb25hbCBwbGFjZWhvbGRlcnMgKGAkMWAgaW5zaWRlIGAkMTBgLFxuICogc28gYSByb3V0ZSB3aXRoIHRlbiBvciBtb3JlIGNhcHR1cmVzKSwgYW5kIGBuZXh0LmNvbmZpZ2AgYHJld3JpdGVzKClgXG4gKiBkZXN0aW5hdGlvbnMgdGhhdCBpbnRlcnBvbGF0ZSB0aGVpciBvd24gcXVlcnkgdmFsdWVzLiBUaG9zZSBhcmUgbm90IHJvdXRlXG4gKiBwYXJhbXMgYW5kIGFyZSBsZWZ0IGFsb25lIOKAlCB0aGVyZSBpcyBubyBzZWNvbmQgc291cmNlIG9mIHRydXRoIHRvIHJlcGFpciB0aGVtXG4gKiBmcm9tLlxuICpcbiAqIFRoZSBzZWNvbmQgY29ycmVjdGlvbiBpcyB0aGUgb3Bwb3NpdGUgc2hhcGU6IGEgcGFyYW0gdGhlIHJvdXRlICpoYXMqIGJ1dCB0aGVcbiAqIHJlcXVlc3QgZGlkIG5vdCBmaWxsLiBBbiBvcHRpb25hbCBjYXRjaGFsbCdzIGdyb3VwIGlzIHRoZSBvbmx5IG9uZSBhIG1hdGNoIGNhblxuICogbGVhdmUgdW5zZXQg4oCUIGBeL29wdGlvbmFsXFwtY2F0Y2hhbGwoPzovKD88bnh0UHBhcmFtcz4uKz8pKT8oPzovKT8kYCBhZ2FpbnN0XG4gKiBgL29wdGlvbmFsLWNhdGNoYWxsYCDigJQgYW5kIGJvdGggYHJvdXRlTWF0Y2hlc2AgYW5kIHRoZSBleHBhbmRlZCBxdWVyeSBrZWVwIHRoZVxuICoga2V5IHdpdGggbm8gdmFsdWU6IGB7IG54dFBwYXJhbXM6IHVuZGVmaW5lZCB9YCwgd2hpY2ggdGhlIGBAbmV4dC9yb3V0aW5nYCB0eXBlc1xuICogZG8gbm90IGFkbWl0LiBUaGUga2V5IGlzIHdoYXQgbWF0dGVycywgbm90IHRoZSB2YWx1ZS4gYFJvdXRlTW9kdWxlLnByZXBhcmVgXG4gKiByZWNvdmVycyBhIHBhcmFtIGZvciBldmVyeSBgbnh0UGAga2V5IGl0IGZpbmRzLCBzbyBhIGxheW91dCByZWFkaW5nIGBwYXJhbXNgXG4gKiByZW5kZXJzIGEgc2VnbWVudCB0aGF0IHdhcyBuZXZlciByZXF1ZXN0ZWQg4oCUIGFzIGBbXCJ1bmRlZmluZWRcIl1gLCBiZWNhdXNlXG4gKiBgVVJMU2VhcmNoUGFyYW1zLmFwcGVuZGAgc3RyaW5naWZpZXMg4oCUIHdoZXJlIGBuZXh0IHN0YXJ0YCBnaXZlcyBpdCBubyBgcGFyYW1zYFxuICoga2V5IGF0IGFsbC4gTWVhc3VyZWQgYWdhaW5zdCBgdGVzdC9lMmUvYXBwLWRpci9sYXlvdXQtcGFyYW1zYCwgd2hvc2UgZml4dHVyZSBpc1xuICogYGFwcC9vcHRpb25hbC1jYXRjaGFsbC9bWy4uLnBhcmFtc11dYC4gTm8gb3RoZXIgcGFyYW0gc2hhcGUgY2FuIGJlIGxlZ2l0aW1hdGVseVxuICogdW5maWxsZWQg4oCUIGEgcmVxdWlyZWQgc2VnbWVudCBjYXB0dXJlcyBgW14vXSs/YCBhbmQgYSByZXF1aXJlZCBjYXRjaGFsbCBgLis/YCDigJRcbiAqIHNvIGFuIHVuZmlsbGVkIHZhbHVlIGByb3V0ZU1hdGNoZXNgIGRvZXMgbm90IHZvdWNoIGZvciBpcyBhbHdheXMgdGhpcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcGFpclJvdXRlUGFyYW1RdWVyeShcbiAgcXVlcnk6IFJlc29sdmVSb3V0ZXNRdWVyeSxcbiAgcm91dGVNYXRjaGVzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCB1bmRlZmluZWQ+LFxuKTogUmVzb2x2ZVJvdXRlc1F1ZXJ5IHtcbiAgbGV0IHJlcGFpcmVkOiBSZXNvbHZlUm91dGVzUXVlcnkgfCB1bmRlZmluZWQ7XG4gIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHJvdXRlTWF0Y2hlcykpIHtcbiAgICBpZiAoIWtleS5zdGFydHNXaXRoKFwibnh0UFwiKSB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKSBjb250aW51ZTtcbiAgICBpZiAoIShrZXkgaW4gcXVlcnkpIHx8IHF1ZXJ5W2tleV0gPT09IHZhbHVlKSBjb250aW51ZTtcbiAgICByZXBhaXJlZCA/Pz0geyAuLi5xdWVyeSB9O1xuICAgIHJlcGFpcmVkW2tleV0gPSB2YWx1ZTtcbiAgfVxuICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhyZXBhaXJlZCA/PyBxdWVyeSkpIHtcbiAgICBpZiAoIWtleS5zdGFydHNXaXRoKFwibnh0UFwiKSB8fCBpc0ZpbGxlZFBhcmFtKHZhbHVlKSkgY29udGludWU7XG4gICAgaWYgKGlzRmlsbGVkUGFyYW0ocm91dGVNYXRjaGVzW2tleV0pKSBjb250aW51ZTtcbiAgICByZXBhaXJlZCA/Pz0geyAuLi5xdWVyeSB9O1xuICAgIGRlbGV0ZSByZXBhaXJlZFtrZXldO1xuICB9XG4gIHJldHVybiByZXBhaXJlZCA/PyBxdWVyeTtcbn1cblxuLyoqXG4gKiBSb3V0ZSBwYXJhbXMgdG8gaGFuZCBOZXh0LmpzIG91dC1vZi1iYW5kLCBmb3IgdGhlIG9uZSByZXF1ZXN0IHNoYXBlIHRoZSBgbnh0UGBcbiAqIHF1ZXJ5IGNvbnRyYWN0IGNhbm5vdCBjYXJyeTogYSBjYXB0dXJlIGNvbnRhaW5pbmcgYW4gZW5jb2RlZCBgL2AuIGB1bmRlZmluZWRgXG4gKiDigJQgdGhlIGNvbW1vbiBjYXNlIOKAlCBtZWFucyB0aGUgY29udHJhY3QgaXMgbG9zc2xlc3MgYW5kIG5vdGhpbmcgc3BlY2lhbCBpc1xuICogbmVlZGVkLlxuICpcbiAqIFRoZSBjb250cmFjdCBub3JtYWxseSBpcyBsb3NzbGVzcywgd2hpY2ggaXMgd2h5IHtAbGluayBOZXh0anNSdW50aW1lfSBwYXNzZXNcbiAqIHJvdXRlIHBhcmFtcyBhcyBxdWVyeSB2YWx1ZXMgZXZlcnl3aGVyZSBlbHNlLiBCdXQgYFJvdXRlTW9kdWxlLnByZXBhcmVgXG4gKiByZWNvdmVycyB0aGVtIGJ5IHJ1bm5pbmcgYG5vcm1hbGl6ZVF1ZXJ5UGFyYW1zYCDigJQgd2hpY2ggY2FsbHNcbiAqIGBkZWNvZGVRdWVyeVBhdGhQYXJhbWV0ZXJgLCBhICoqc2Vjb25kKiogYGRlY29kZVVSSUNvbXBvbmVudGAsIG9uIGV2ZXJ5XG4gKiBkZS1wcmVmaXhlZCB2YWx1ZSBiZWNhdXNlIFwid2hlbiBkZXBsb3llZCB0byBWZXJjZWwgdGhlIHZhbHVlIG1heSBiZSBlbmNvZGVkXCIg4oCUXG4gKiBhbmQgdGhlbiBgbm9ybWFsaXplRHluYW1pY1JvdXRlUGFyYW1zYCwgd2hpY2ggc3BsaXRzIGEgc3RyaW5nIHJlcGVhdCBwYXJhbSBvblxuICogYC9gIGJlY2F1c2UgXCJxdWVyeSB2YWx1ZXMgZnJvbSB0aGUgcHJveHkgYXJlbid0IGFscmVhZHkgc3BsaXQgaW50byBhcnJheXNcIi5cbiAqIFR3byBkZWNvZGVzIGFuZCBhIHNwbGl0OiBgbnh0UHJlc3Q9Li4lMjUyRi4uJTI1MkZzZXJ2ZXItcmVmZXJlbmNlLW1hbmlmZXN0YFxuICogKHdoYXQgdGhlIGNvbnRyYWN0IGFza3MgZm9yLCBhbmQgd2hhdCB3ZSBzZW5kKSBhcnJpdmVzIGFzIHRoZSB0aHJlZSBwYXJhbXNcbiAqIGBbJy4uJywgJy4uJywgJ3NlcnZlci1yZWZlcmVuY2UtbWFuaWZlc3QnXWAgcmF0aGVyIHRoYW4gdGhlIG9uZSB0aGUgY2xpZW50XG4gKiByZXF1ZXN0ZWQuIFRoZSByZXNvbHZlZCBwYXRobmFtZSBidWlsdCBiYWNrIG91dCBvZiB0aG9zZSBpc1xuICogYC9wYWdlcy1jYWNoZS8uLi8uLi9zZXJ2ZXItcmVmZXJlbmNlLW1hbmlmZXN0YCwgYW5kIGBub3JtYWxpemVQYWdlUGF0aGAgdGhyb3dzXG4gKiBgUmVxdWVzdGVkIGFuZCByZXNvbHZlZCBwYWdlIG1pc21hdGNoYCBvbiBpdCB3aGVuIHRoZSBjYWNoZSBhc2tzIGZvciBhIGtleSDigJRcbiAqIHNvIGEgYF9uZXh0L2RhdGFgIHJlcXVlc3QgZm9yIGEgY2F0Y2gtYWxsIHdob3NlIHNlZ21lbnQgY29udGFpbnMgYCUyRmAgNTAwcy5cbiAqIE1lYXN1cmVkIGFnYWluc3QgYHRlc3QvZTJlL2luY3JlbWVudGFsLWNhY2hlLXBhdGgtdHJhdmVyc2FsYC4gTm8gZW5jb2RpbmcgY2FuXG4gKiBmaXggaXQgZnJvbSB0aGlzIHNpZGU6IHdoYXRldmVyIHN1cnZpdmVzIHR3byBkZWNvZGVzIHN0aWxsIGdldHMgc3BsaXQuXG4gKlxuICogYG5leHQgc3RhcnRgIG5ldmVyIGhpdHMgaXQgYmVjYXVzZSBpdHMgYHJvdXRlci1zZXJ2ZXJgIHNldHNcbiAqIGByZXF1ZXN0TWV0YS5wYXJhbXNgIGluc3RlYWQsIHdoaWNoIGBwcmVwYXJlYCB0YWtlcyBhcy1pc1xuICogKGByb3V0ZS1tb2R1bGUudHNgOiBgZ2V0UmVxdWVzdE1ldGEocmVxLCAncGFyYW1zJylgKSB3aXRoIG5vIGRlY29kZSBhbmQgbm9cbiAqIHNwbGl0LiBUaGF0IGlzIHdoYXQgdGhpcyByZXByb2R1Y2VzIOKAlCBuYXJyb3dseSwgb25seSBmb3IgdGhlIGFmZmVjdGVkXG4gKiByZXF1ZXN0cywgc28gdGhhdCB0aGUgZG9jdW1lbnRlZCBxdWVyeSBjb250cmFjdCBzdGF5cyB0aGUgcGF0aCBmb3IgZXZlcnl0aGluZ1xuICogZWxzZS5cbiAqXG4gKiBUaGUgYG54dFBgIHZhbHVlcyBoYXZlIHRvIGxlYXZlIHRoZSBxdWVyeSBhcyB3ZWxsIGFzIGFycml2ZSBpbiBgcGFyYW1zYC5cbiAqIGBwcmVwYXJlYCBwcmVmZXJzIHRoZSBxdWVyeSBvdmVyIGBwYXJhbXNgIHdoZW4gYm90aCBwYXJzZSBhbmQgYXJlIHRoZSBzYW1lXG4gKiBzaXplLCBzbyBsZWF2aW5nIHRoZW0gaW4gd291bGQganVzdCByZXN0b3JlIHRoZSBzcGxpdC4gRHJvcHBpbmcgdGhlbSBhbHNvXG4gKiBtYXRjaGVzIGBuZXh0IHN0YXJ0YCwgd2hpY2ggaGFzIG5vIGBueHRQYCBxdWVyeSBhdCBhbGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvdXRPZkJhbmRSb3V0ZVBhcmFtcyhcbiAgcXVlcnk6IFJlc29sdmVSb3V0ZXNRdWVyeSxcbiAgcmVzb2x2ZWRQYXRobmFtZTogc3RyaW5nLFxuKTpcbiAgfCB7IHBhcmFtczogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgc3RyaW5nW10+OyBxdWVyeTogUmVzb2x2ZVJvdXRlc1F1ZXJ5IH1cbiAgfCB1bmRlZmluZWQge1xuICBjb25zdCBlbnRyaWVzID0gT2JqZWN0LmVudHJpZXMocXVlcnkpO1xuICBpZiAoXG4gICAgIWVudHJpZXMuc29tZShcbiAgICAgIChba2V5LCB2YWx1ZV0pID0+XG4gICAgICAgIGtleS5zdGFydHNXaXRoKFwibnh0UFwiKSAmJlxuICAgICAgICB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgJiZcbiAgICAgICAgRU5DT0RFRF9QQVRIX0RFTElNSVRFUi50ZXN0KHZhbHVlKSxcbiAgICApXG4gICkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgLy8gV2hpY2ggcGFyYW1zIGFyZSByZXBlYXRzIOKAlCBgWy4uLnJlc3RdYCwgYFtbLi4ucmVzdF1dYCDigJQgZGVjaWRlcyBhcnJheSB2ZXJzdXNcbiAgLy8gc3RyaW5nLCB0aGUgc2FtZSBkaXN0aW5jdGlvbiBgbm9ybWFsaXplRHluYW1pY1JvdXRlUGFyYW1zYCBtYWtlcyBmcm9tIHRoZVxuICAvLyByb3V0ZSdzIG93biBgZ3JvdXBzYC4gYHJlc29sdmVkUGF0aG5hbWVgIGlzIHRoZSBtYXRjaGVkIHJvdXRlLCBicmFja2V0cyBhbmRcbiAgLy8gYWxsLlxuICBjb25zdCByZXBlYXRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIGZvciAoY29uc3QgbWF0Y2ggb2YgcmVzb2x2ZWRQYXRobmFtZS5tYXRjaEFsbCgvXFxbXFxbP1xcLlxcLlxcLihbXlxcXV0rPylcXF1cXF0/L2cpKSB7XG4gICAgcmVwZWF0cy5hZGQobWF0Y2hbMV0pO1xuICB9XG4gIGNvbnN0IHBhcmFtczogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgc3RyaW5nW10+ID0ge307XG4gIGNvbnN0IHJlbWFpbmluZzogUmVzb2x2ZVJvdXRlc1F1ZXJ5ID0ge307XG4gIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIGVudHJpZXMpIHtcbiAgICBpZiAoIWtleS5zdGFydHNXaXRoKFwibnh0UFwiKSkge1xuICAgICAgcmVtYWluaW5nW2tleV0gPSB2YWx1ZTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICAvLyBBbnl0aGluZyBidXQgYSBmaWxsZWQgc3RyaW5nIGlzIGEgcGFyYW0gd2UgY2Fubm90IHJlc3RhdGUg4oCUIGFuIG9wdGlvbmFsXG4gICAgLy8gY2F0Y2hhbGwgdGhlIHJlcXVlc3QgbGVmdCB1bnNldCwgb3IgYSByZXBlYXRlZCBrZXkuIFJhdGhlciB0aGFuIGhhbmRcbiAgICAvLyBgcHJlcGFyZWAgYSBwYXJhbSBzZXQgdGhhdCBpcyBtaXNzaW5nIG9uZSwgbGVhdmUgdGhlIHdob2xlIHJlcXVlc3Qgb24gdGhlXG4gICAgLy8gcXVlcnkgY29udHJhY3QuXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJzdHJpbmdcIiB8fCB2YWx1ZSA9PT0gXCJcIikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBjb25zdCBuYW1lID0ga2V5LnNsaWNlKFwibnh0UFwiLmxlbmd0aCk7XG4gICAgcGFyYW1zW25hbWVdID0gcmVwZWF0cy5oYXMobmFtZSlcbiAgICAgID8gdmFsdWUuc3BsaXQoXCIvXCIpLm1hcChzYWZlRGVjb2RlKVxuICAgICAgOiBzYWZlRGVjb2RlKHZhbHVlKTtcbiAgfVxuICByZXR1cm4geyBwYXJhbXMsIHF1ZXJ5OiByZW1haW5pbmcgfTtcbn1cblxuLyoqIEFuIGVuY29kZWQgYC9gOiB0aGUgZGVsaW1pdGVyIHRoZSBxdWVyeSBjb250cmFjdCdzIHNwbGl0IHdvdWxkIGNvbnN1bWUuICovXG5jb25zdCBFTkNPREVEX1BBVEhfREVMSU1JVEVSID0gLyUyZi9pO1xuXG4vKiogV2hldGhlciBhIHJvdXRlIHBhcmFtIGNhcnJpZXMgYSBzZWdtZW50LCBhcyBvcHBvc2VkIHRvIGBcIlwiYCBvciBub3RoaW5nLiAqL1xuZnVuY3Rpb24gaXNGaWxsZWRQYXJhbSh2YWx1ZTogUmVzb2x2ZVJvdXRlc1F1ZXJ5VmFsdWUgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpID8gdmFsdWUubGVuZ3RoID4gMCA6IEJvb2xlYW4odmFsdWUpO1xufVxuXG4vKipcbiAqIFRoZSBvcmRlciBuZXh0IGl0c2VsZiB1c2VzLCBpbiBgYmFzZS1zZXJ2ZXIudHNgJ3MgYHJlbmRlckVycm9yVG9SZXNwb25zZWA6XG4gKiB0aGUgc3RhdHVzIHBhZ2UncyBlbnRyeXBvaW50cywgdGhlbiBpdHMgcHJlcmVuZGVyLCB0aGVuIGAvX2Vycm9yYCwgd2hpY2ggaXNcbiAqIHRoZSBidWlsdC1pbiBlcnJvciBwYWdlIHVubGVzcyB0aGUgYXBwIHdyb3RlIGl0cyBvd24uXG4gKlxuICogRm9yIGEgNDA0IHRoZSBlbnRyeXBvaW50cyBhcmUgQXBwIFJvdXRlcidzIGAvX25vdC1mb3VuZGAsIHRoZW4gUGFnZXNcbiAqIFJvdXRlcidzIGAvNDA0YC4gYC80MDRgIGhhcyB0byBjb21lIGJlZm9yZSBgL19lcnJvcmAg4oCUIGl0IGlzIHRoZSBhcHAnc1xuICogKmN1c3RvbSogNDA0LCBhbmQgYC9fZXJyb3JgIGlzIHRoZSBidWlsdC1pbiBcIjQwNDogVGhpcyBwYWdlIGNvdWxkIG5vdCBiZVxuICogZm91bmRcIi4gTWVhc3VyZWQgYWdhaW5zdCBgdGVzdC9lMmUvNDA0LXBhZ2UtYXBwYCwgd2hlcmUgZXZlcnkgVVJMIGdvdCB0aGVcbiAqIGJ1aWx0LWluIHBhZ2UuIEZvciBhIDUwMCBpdCBpcyBgLzUwMGAuXG4gKlxuICogVGhlIHByZXJlbmRlciBpcyBhbG1vc3QgYWx3YXlzIHRoZXJlOiBgbmV4dCBidWlsZGAgZW1pdHMgYDQwNC5odG1sYCB3aGVuZXZlclxuICogYHBhZ2VzL19hcHBgIGhhcyBubyBgZ2V0SW5pdGlhbFByb3BzYCAoYHVzZVN0YXRpY1BhZ2VzNDA0YCksIGZyb20gdGhlIGFwcCdzXG4gKiBgcGFnZXMvNDA0LmpzYCBvciBlbHNlIGZyb20gYF9lcnJvcmAsIGFuZCBgcGFnZXMvNTAwLmpzYCBpcyBhXG4gKiBgU1RBVElDX1NUQVRVU19QQUdFU2AgZW50cnkuIFNvIGl0IHJlYWNoZXMgdXMgYXMgYSBzdGF0aWMgZmlsZSDigJQgdW5kZXIgaTE4blxuICogb25lIHBlciBsb2NhbGUgKGAvZW4tVVMvNDA0YCksIGFuZCBuZXZlciBhIGJhcmUgYC80MDRgIOKAlCBhbmQgYG5leHQgc3RhcnRgXG4gKiBzZXJ2ZXMgaXQgYWhlYWQgb2YgYC9fZXJyb3JgLCB3aGljaCBldmVyeSBQYWdlcyBidWlsZCBoYXMuIFRoZSBwYWdlIGlzIGFuXG4gKiBlbnRyeXBvaW50IG9ubHkgd2hlbiBzb21ldGhpbmcgZm9yY2VzIGEgcGVyLXJlcXVlc3QgcmVuZGVyLCB3aGljaCBhXG4gKiBgZ2V0SW5pdGlhbFByb3BzYCBpbiBgX2FwcGAgZG9lcy5cbiAqXG4gKiBBIDUwMCBpcyBvbmx5IHJlbmRlcmVkIHdoZW4gYW4gZW50cnlwb2ludCAqdGhyb3dzKi4gTmV4dC5qcydzIHBhZ2UgaGFuZGxlcnNcbiAqIGRlbGliZXJhdGVseSByZXRocm93IChcInJldGhyb3cgc28gdGhhdCB3ZSBjYW4gaGFuZGxlIHNlcnZpbmcgZXJyb3IgcGFnZVwiLFxuICogYHBhZ2VzLWhhbmRsZXIudHNgKSwgbGVhdmluZyB0aGUgZXJyb3IgcGFnZSB0byB3aGF0ZXZlciBpcyBob3N0aW5nIHRoZW0g4oCUXG4gKiBtZWFzdXJlZCBhZ2FpbnN0IGB0ZXN0L2UyZS9hc3luYy1tb2R1bGVzYCwgd2hvc2UgYC9tYWtlLWVycm9yYCB0aHJvd3MgaW5cbiAqIGBnZXRTZXJ2ZXJTaWRlUHJvcHNgIGFuZCBleHBlY3RzIHRoZSBhcHAncyBgcGFnZXMvX2Vycm9yYC5cbiAqXG4gKiBBcHBzIHdpdGggbm9uZSBvZiB0aGVzZSBnZXQgbm90aGluZy5cbiAqL1xuZnVuY3Rpb24gc3RhdHVzVGFyZ2V0KFxuICBtYW5pZmVzdDogQWRhcHRlck1hbmlmZXN0LFxuICBzdGF0dXM6IDQwNCB8IDUwMCxcbiAgLyoqIFdoaWNoIGxvY2FsZSdzIHByZXJlbmRlciB0byBsb29rIGZvciwgaW4gYW4gaTE4biBhcHAuICovXG4gIGxvY2FsZTogc3RyaW5nIHwgdW5kZWZpbmVkLFxuKTogU3RhdHVzVGFyZ2V0IHtcbiAgY29uc3QgeyBiYXNlUGF0aCB9ID0gbWFuaWZlc3QuY29uZmlnO1xuICBmb3IgKGNvbnN0IHN1ZmZpeCBvZiBTVEFUVVNfUEFHRV9TVUZGSVhFU1tzdGF0dXNdKSB7XG4gICAgY29uc3QgcGF0aG5hbWUgPSBgJHtiYXNlUGF0aH0ke3N1ZmZpeH1gO1xuICAgIGNvbnN0IGVudHJ5cG9pbnQgPSBtYW5pZmVzdC5lbnRyeXBvaW50c1twYXRobmFtZV07XG4gICAgaWYgKGVudHJ5cG9pbnQpIHtcbiAgICAgIHJldHVybiB7IGtpbmQ6IFwiZW50cnlwb2ludFwiLCBwYXRobmFtZSwgZW50cnlwb2ludCB9O1xuICAgIH1cbiAgfVxuICBjb25zdCBwcmVyZW5kZXJlZCA9IGAke2Jhc2VQYXRofSR7bG9jYWxlID8gYC8ke2xvY2FsZX1gIDogXCJcIn0vJHtzdGF0dXN9YDtcbiAgY29uc3QgZmlsZVBhdGggPSBtYW5pZmVzdC5zdGF0aWNGaWxlc1twcmVyZW5kZXJlZF07XG4gIGlmIChmaWxlUGF0aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIHsga2luZDogXCJzdGF0aWMtZmlsZVwiLCBwYXRobmFtZTogcHJlcmVuZGVyZWQsIGZpbGVQYXRoIH07XG4gIH1cbiAgY29uc3QgZXJyb3JQYXRobmFtZSA9IGAke2Jhc2VQYXRofSR7U1RBVFVTX1BBR0VfU1VGRklYRVMuZmFsbGJhY2t9YDtcbiAgY29uc3QgZXJyb3JFbnRyeXBvaW50ID0gbWFuaWZlc3QuZW50cnlwb2ludHNbZXJyb3JQYXRobmFtZV07XG4gIGlmIChlcnJvckVudHJ5cG9pbnQpIHtcbiAgICByZXR1cm4ge1xuICAgICAga2luZDogXCJlbnRyeXBvaW50XCIsXG4gICAgICBwYXRobmFtZTogZXJyb3JQYXRobmFtZSxcbiAgICAgIGVudHJ5cG9pbnQ6IGVycm9yRW50cnlwb2ludCxcbiAgICB9O1xuICB9XG4gIHJldHVybiB7IGtpbmQ6IFwibm9uZVwiIH07XG59XG5cbi8qKlxuICoge0BsaW5rIHN0YXR1c1RhcmdldH0gZm9yIGV2ZXJ5IGxvY2FsZSwgcmVzb2x2ZWQgb25jZSwgYW5kIGEgbG9va3VwIG9mIHRoZVxuICogcmVxdWVzdCdzOiBpbiBhbiBpMThuIGFwcCwgdGhlIHByZXJlbmRlciBvZiB0aGUgbG9jYWxlIHRoZSBVUkwgaXMgaW5cbiAqIChgL2ZyL25vcGVgIGdldHMgYC9mci80MDRgKSwgYW5kIG90aGVyd2lzZSBvZiB0aGUgZG9tYWluJ3MgZGVmYXVsdCBsb2NhbGUg4oCUXG4gKiB3aGljaCBpcyBob3cgYG5leHQgc3RhcnRgIHBpY2tzIHRoZSBsb2NhbGUgaXQgcmVuZGVycyBhIHN0YXR1cyBwYWdlIGluLiBBXG4gKiByZXF1ZXN0IHdob3NlIFVSTCBjb3VsZCBub3QgYmUgcGFyc2VkLCBgdW5kZWZpbmVkYCwgZ2V0cyB0aGUgZGVmYXVsdFxuICogbG9jYWxlJ3MuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdGF0dXNUYXJnZXRzKFxuICBtYW5pZmVzdDogQWRhcHRlck1hbmlmZXN0LFxuICBzdGF0dXM6IDQwNCB8IDUwMCxcbik6ICh1cmw6IFVSTCB8IHVuZGVmaW5lZCkgPT4gU3RhdHVzVGFyZ2V0IHtcbiAgY29uc3QgaTE4biA9IGFzSTE4bihtYW5pZmVzdC5jb25maWcuaTE4bik7XG4gIGNvbnN0IGZhbGxiYWNrID0gc3RhdHVzVGFyZ2V0KG1hbmlmZXN0LCBzdGF0dXMsIGkxOG4/LmRlZmF1bHRMb2NhbGUpO1xuICBjb25zdCBieUxvY2FsZSA9IG5ldyBNYXAoXG4gICAgKGkxOG4/LmxvY2FsZXMgPz8gW10pLm1hcCgobG9jYWxlKSA9PiBbXG4gICAgICBsb2NhbGUsXG4gICAgICBzdGF0dXNUYXJnZXQobWFuaWZlc3QsIHN0YXR1cywgbG9jYWxlKSxcbiAgICBdKSxcbiAgKTtcbiAgcmV0dXJuICh1cmwpID0+IHtcbiAgICBjb25zdCBsb2NhbGUgPSB1cmwgPyByZXF1ZXN0TG9jYWxlKG1hbmlmZXN0LCB1cmwpIDogdW5kZWZpbmVkO1xuICAgIHJldHVybiAobG9jYWxlICE9PSB1bmRlZmluZWQgJiYgYnlMb2NhbGUuZ2V0KGxvY2FsZSkpIHx8IGZhbGxiYWNrO1xuICB9O1xufVxuXG4vKipcbiAqIFRoZSBsb2NhbGUgYSByZXF1ZXN0J3Mgc3RhdHVzIHBhZ2UgcmVuZGVycyBpbiwgdGhlIHdheSBgbmV4dCBzdGFydGAgcGlja3MgaXQ6XG4gKiB0aGUgbG9jYWxlIHRoZSBVUkwncyBmaXJzdCBzZWdtZW50IG5hbWVzIChjYXNlLWluc2Vuc2l0aXZlbHksIGFzXG4gKiBgbm9ybWFsaXplTG9jYWxlUGF0aGAgbWF0Y2hlcyBpdCksIGFuZCBvdGhlcndpc2UgdGhlIGRvbWFpbidzIGRlZmF1bHQgbG9jYWxlLFxuICogdGhlbiB0aGUgYXBwJ3MuIGB1bmRlZmluZWRgIHdpdGhvdXQgaTE4bi5cbiAqL1xuZnVuY3Rpb24gcmVxdWVzdExvY2FsZShcbiAgbWFuaWZlc3Q6IEFkYXB0ZXJNYW5pZmVzdCxcbiAgdXJsOiBVUkwsXG4pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCBpMThuID0gYXNJMThuKG1hbmlmZXN0LmNvbmZpZy5pMThuKTtcbiAgaWYgKCFpMThuKSByZXR1cm4gdW5kZWZpbmVkO1xuICBjb25zdCBwYXRobmFtZSA9IHdpdGhvdXRQYXRoUHJlZml4KHVybC5wYXRobmFtZSwgbWFuaWZlc3QuY29uZmlnLmJhc2VQYXRoKTtcbiAgY29uc3Qgc2VnbWVudCA9IChwYXRobmFtZS5zcGxpdChcIi9cIilbMV0gPz8gXCJcIikudG9Mb3dlckNhc2UoKTtcbiAgcmV0dXJuIChcbiAgICBpMThuLmxvY2FsZXMuZmluZCgoY2FuZGlkYXRlKSA9PiBjYW5kaWRhdGUudG9Mb3dlckNhc2UoKSA9PT0gc2VnbWVudCkgPz9cbiAgICBkZXRlY3REb21haW5Mb2NhbGUoaTE4bi5kb21haW5zLCB1cmwuaG9zdG5hbWUpPy5kZWZhdWx0TG9jYWxlID8/XG4gICAgaTE4bi5kZWZhdWx0TG9jYWxlXG4gICk7XG59XG4iXX0=
|