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.
Files changed (266) hide show
  1. package/.jsii +2467 -2714
  2. package/.jsii.tabl.json +1 -1
  3. package/API.md +1725 -1909
  4. package/CLAUDE.md +2 -1
  5. package/README.md +429 -130
  6. package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +152 -170
  7. package/assets/lambdas/redeploy-stage/redeploy-stage.lambda/index.js +875 -0
  8. package/docs/adapter-runtime.md +185 -0
  9. package/docs/breaking-changes.md +687 -4
  10. package/docs/caching-guide.md +156 -112
  11. package/docs/cdk-nextjs-cfn-exec-policy.json +2 -1
  12. package/docs/development-guide.md +1 -1
  13. package/docs/harness-coverage.md +598 -0
  14. package/docs/init-cache-deployment.md +32 -1
  15. package/docs/next-build-output-guide.md +30 -20
  16. package/examples/README.md +5 -1
  17. package/lib/adapter/__fixtures__/app-playground-base-path.json +4926 -0
  18. package/lib/adapter/__fixtures__/app-playground.json +4917 -0
  19. package/lib/adapter/__fixtures__/pages-i18n.json +1728 -0
  20. package/lib/adapter/adapter.mjs +1548 -185
  21. package/lib/adapter/adapter.test.js +106 -0
  22. package/lib/adapter/aws-cache-store.d.ts +489 -0
  23. package/lib/adapter/aws-cache-store.js +1004 -0
  24. package/lib/adapter/aws-cache-store.test.d.ts +1 -0
  25. package/lib/adapter/aws-cache-store.test.js +361 -0
  26. package/lib/adapter/build-outputs.d.ts +80 -0
  27. package/lib/adapter/build-outputs.js +852 -0
  28. package/lib/adapter/build-outputs.test.d.ts +1 -0
  29. package/lib/adapter/build-outputs.test.js +861 -0
  30. package/lib/adapter/cache-handler.d.ts +9 -2
  31. package/lib/adapter/cache-handler.js +72 -96
  32. package/lib/adapter/cache-handler.mjs +18956 -17774
  33. package/lib/adapter/cache-handler.test.js +263 -31
  34. package/lib/adapter/cache-kinds.d.ts +32 -0
  35. package/lib/adapter/cache-kinds.js +35 -0
  36. package/lib/adapter/cache-kinds.test.d.ts +1 -0
  37. package/lib/adapter/cache-kinds.test.js +69 -0
  38. package/lib/adapter/cache-utils.d.ts +90 -0
  39. package/lib/adapter/cache-utils.js +199 -4
  40. package/lib/adapter/cache-utils.test.d.ts +1 -0
  41. package/lib/adapter/cache-utils.test.js +179 -0
  42. package/lib/adapter/function-groups.d.ts +215 -0
  43. package/lib/adapter/function-groups.js +1099 -0
  44. package/lib/adapter/function-groups.test.d.ts +1 -0
  45. package/lib/adapter/function-groups.test.js +743 -0
  46. package/lib/adapter/init-cache.d.ts +6 -0
  47. package/lib/adapter/init-cache.js +245 -0
  48. package/lib/adapter/init-cache.test.d.ts +1 -0
  49. package/lib/adapter/init-cache.test.js +137 -0
  50. package/lib/adapter/local-file-cache-handler.d.ts +23 -0
  51. package/lib/adapter/local-file-cache-handler.js +52 -1
  52. package/lib/adapter/memory-cache-handler.d.ts +26 -17
  53. package/lib/adapter/memory-cache-handler.js +32 -50
  54. package/lib/adapter/memory-cache-handler.test.js +105 -85
  55. package/lib/adapter/s3-cache-handler.d.ts +179 -40
  56. package/lib/adapter/s3-cache-handler.js +807 -277
  57. package/lib/adapter/s3-cache-handler.test.js +1186 -31
  58. package/lib/adapter/use-cache-common.d.ts +90 -0
  59. package/lib/adapter/use-cache-common.js +250 -0
  60. package/lib/adapter/use-cache-common.test.d.ts +1 -0
  61. package/lib/adapter/use-cache-common.test.js +646 -0
  62. package/lib/adapter/use-cache-default-handler.d.ts +24 -0
  63. package/lib/adapter/use-cache-default-handler.js +90 -0
  64. package/lib/adapter/use-cache-default-handler.mjs +38645 -0
  65. package/lib/adapter/use-cache-handlers.test.d.ts +1 -0
  66. package/lib/adapter/use-cache-handlers.test.js +349 -0
  67. package/lib/adapter/use-cache-remote-handler.d.ts +26 -0
  68. package/lib/adapter/use-cache-remote-handler.js +186 -0
  69. package/lib/{image-optimization/handler.mjs → adapter/use-cache-remote-handler.mjs} +33572 -38798
  70. package/lib/generated-structs/OptionalNextjsApiProps.d.ts +59 -0
  71. package/lib/generated-structs/OptionalNextjsApiProps.js +3 -0
  72. package/lib/generated-structs/OptionalNextjsCacheProps.d.ts +15 -6
  73. package/lib/generated-structs/OptionalNextjsCacheProps.js +1 -1
  74. package/lib/generated-structs/OptionalNextjsContainersProps.d.ts +25 -11
  75. package/lib/generated-structs/OptionalNextjsContainersProps.js +1 -1
  76. package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +31 -9
  77. package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
  78. package/lib/generated-structs/OptionalNextjsPostDeployProps.d.ts +13 -0
  79. package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
  80. package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +11 -2
  81. package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.js +1 -1
  82. package/lib/index.d.ts +6 -7
  83. package/lib/index.js +2 -4
  84. package/lib/lambdas/post-deploy/post-deploy.lambda.js +3 -2
  85. package/lib/lambdas/post-deploy/prune-cache-bucket.d.ts +7 -3
  86. package/lib/lambdas/post-deploy/prune-cache-bucket.js +57 -71
  87. package/lib/lambdas/post-deploy/prune-cache-bucket.test.d.ts +1 -0
  88. package/lib/lambdas/post-deploy/prune-cache-bucket.test.js +114 -0
  89. package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +1 -0
  90. package/lib/lambdas/post-deploy/prune-revalidation-table.js +23 -31
  91. package/lib/lambdas/post-deploy/prune-revalidation-table.test.d.ts +1 -0
  92. package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +71 -0
  93. package/lib/lambdas/post-deploy/prune-s3.d.ts +19 -3
  94. package/lib/lambdas/post-deploy/prune-s3.js +54 -15
  95. package/lib/lambdas/post-deploy/prune-s3.test.d.ts +1 -0
  96. package/lib/lambdas/post-deploy/prune-s3.test.js +255 -0
  97. package/lib/lambdas/redeploy-stage/redeploy-stage-function.d.ts +13 -0
  98. package/lib/lambdas/redeploy-stage/redeploy-stage-function.js +55 -0
  99. package/lib/lambdas/redeploy-stage/redeploy-stage.d.ts +24 -0
  100. package/lib/lambdas/redeploy-stage/redeploy-stage.js +68 -0
  101. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.d.ts +20 -0
  102. package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.js +24 -0
  103. package/lib/lambdas/redeploy-stage/redeploy-stage.test.d.ts +1 -0
  104. package/lib/lambdas/redeploy-stage/redeploy-stage.test.js +93 -0
  105. package/lib/nextjs-api.d.ts +107 -18
  106. package/lib/nextjs-api.js +349 -39
  107. package/lib/nextjs-api.test.js +582 -1
  108. package/lib/nextjs-build/global-containers.Dockerfile +15 -10
  109. package/lib/nextjs-build/nextjs-build.d.ts +339 -63
  110. package/lib/nextjs-build/nextjs-build.js +684 -327
  111. package/lib/nextjs-build/nextjs-build.test.d.ts +1 -0
  112. package/lib/nextjs-build/nextjs-build.test.js +412 -0
  113. package/lib/nextjs-build/patch-fetch.js +1 -1
  114. package/lib/nextjs-build/patch-fetch.test.js +166 -11
  115. package/lib/nextjs-build/regional-containers.Dockerfile +17 -10
  116. package/lib/nextjs-cache.d.ts +82 -4
  117. package/lib/nextjs-cache.js +186 -10
  118. package/lib/nextjs-cache.test.js +176 -1
  119. package/lib/nextjs-compute/nextjs-compute-base-props.d.ts +21 -8
  120. package/lib/nextjs-compute/nextjs-compute-base-props.js +41 -1
  121. package/lib/nextjs-compute/nextjs-compute-base-props.test.d.ts +1 -0
  122. package/lib/nextjs-compute/nextjs-compute-base-props.test.js +44 -0
  123. package/lib/nextjs-compute/nextjs-containers.d.ts +19 -0
  124. package/lib/nextjs-compute/nextjs-containers.js +57 -20
  125. package/lib/nextjs-compute/nextjs-functions.d.ts +122 -7
  126. package/lib/nextjs-compute/nextjs-functions.js +113 -67
  127. package/lib/nextjs-compute/nextjs-functions.test.d.ts +1 -0
  128. package/lib/nextjs-compute/nextjs-functions.test.js +99 -0
  129. package/lib/nextjs-distribution.d.ts +194 -23
  130. package/lib/nextjs-distribution.js +535 -62
  131. package/lib/nextjs-distribution.test.d.ts +1 -0
  132. package/lib/nextjs-distribution.test.js +697 -0
  133. package/lib/nextjs-post-deploy.d.ts +23 -3
  134. package/lib/nextjs-post-deploy.js +14 -10
  135. package/lib/nextjs-post-deploy.test.d.ts +1 -0
  136. package/lib/nextjs-post-deploy.test.js +34 -0
  137. package/lib/nextjs-static-assets.d.ts +23 -4
  138. package/lib/nextjs-static-assets.js +29 -6
  139. package/lib/nextjs-static-assets.test.js +20 -1
  140. package/lib/root-constructs/nextjs-base-construct.d.ts +105 -45
  141. package/lib/root-constructs/nextjs-base-construct.js +144 -34
  142. package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
  143. package/lib/root-constructs/nextjs-global-containers.js +20 -70
  144. package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
  145. package/lib/root-constructs/nextjs-global-functions.js +52 -69
  146. package/lib/root-constructs/nextjs-regional-containers.d.ts +25 -5
  147. package/lib/root-constructs/nextjs-regional-containers.js +17 -15
  148. package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
  149. package/lib/root-constructs/nextjs-regional-functions.js +8 -25
  150. package/lib/runtime/api-gateway-path.d.ts +34 -0
  151. package/lib/runtime/api-gateway-path.js +71 -0
  152. package/lib/runtime/api-gateway-path.test.d.ts +1 -0
  153. package/lib/runtime/api-gateway-path.test.js +65 -0
  154. package/lib/runtime/case-redirect.d.ts +22 -0
  155. package/lib/runtime/case-redirect.js +63 -0
  156. package/lib/runtime/case-redirect.test.d.ts +1 -0
  157. package/lib/runtime/case-redirect.test.js +32 -0
  158. package/lib/runtime/core.d.ts +234 -0
  159. package/lib/runtime/core.js +1213 -0
  160. package/lib/runtime/core.test.d.ts +1 -0
  161. package/lib/runtime/core.test.js +1678 -0
  162. package/lib/runtime/deployment-root.d.ts +13 -0
  163. package/lib/runtime/deployment-root.js +29 -0
  164. package/lib/runtime/dispatch.d.ts +331 -0
  165. package/lib/runtime/dispatch.js +751 -0
  166. package/lib/runtime/dispatch.test.d.ts +1 -0
  167. package/lib/runtime/dispatch.test.js +853 -0
  168. package/lib/runtime/entrypoints.d.ts +57 -0
  169. package/lib/runtime/entrypoints.js +115 -0
  170. package/lib/runtime/http/abort-signal.d.ts +6 -0
  171. package/lib/runtime/http/abort-signal.js +19 -0
  172. package/lib/runtime/http/abort-signal.test.d.ts +1 -0
  173. package/lib/runtime/http/abort-signal.test.js +49 -0
  174. package/lib/runtime/http/node-server.d.ts +38 -0
  175. package/lib/runtime/http/node-server.js +99 -0
  176. package/lib/runtime/http/node-server.test.d.ts +1 -0
  177. package/lib/runtime/http/node-server.test.js +96 -0
  178. package/lib/runtime/http/node-sink.d.ts +16 -0
  179. package/lib/runtime/http/node-sink.js +48 -0
  180. package/lib/runtime/http/node-sink.test.d.ts +1 -0
  181. package/lib/runtime/http/node-sink.test.js +66 -0
  182. package/lib/runtime/http/request.d.ts +62 -0
  183. package/lib/runtime/http/request.js +134 -0
  184. package/lib/runtime/http/request.test.d.ts +1 -0
  185. package/lib/runtime/http/request.test.js +103 -0
  186. package/lib/runtime/http/response.d.ts +77 -0
  187. package/lib/runtime/http/response.js +229 -0
  188. package/lib/runtime/http/response.test.d.ts +1 -0
  189. package/lib/runtime/http/response.test.js +178 -0
  190. package/lib/runtime/http/sink.d.ts +73 -0
  191. package/lib/runtime/http/sink.js +188 -0
  192. package/lib/runtime/http/sink.test.d.ts +1 -0
  193. package/lib/runtime/http/sink.test.js +257 -0
  194. package/lib/runtime/image-utils.d.ts +78 -0
  195. package/lib/runtime/image-utils.js +129 -0
  196. package/lib/runtime/image-utils.test.d.ts +1 -0
  197. package/lib/runtime/image-utils.test.js +237 -0
  198. package/lib/runtime/image.d.ts +76 -0
  199. package/lib/runtime/image.js +296 -0
  200. package/lib/runtime/image.test.d.ts +1 -0
  201. package/lib/runtime/image.test.js +405 -0
  202. package/lib/runtime/lambda-event.d.ts +4 -0
  203. package/lib/runtime/lambda-event.js +113 -0
  204. package/lib/runtime/lambda-event.test.d.ts +1 -0
  205. package/lib/runtime/lambda-event.test.js +119 -0
  206. package/lib/runtime/lambda.mjs +41595 -0
  207. package/lib/runtime/load-module.d.ts +8 -0
  208. package/lib/runtime/load-module.js +35 -0
  209. package/lib/runtime/manifest.d.ts +215 -0
  210. package/lib/runtime/manifest.js +118 -0
  211. package/lib/runtime/middleware.d.ts +43 -0
  212. package/lib/runtime/middleware.js +113 -0
  213. package/lib/runtime/middleware.test.d.ts +1 -0
  214. package/lib/runtime/middleware.test.js +259 -0
  215. package/lib/runtime/next-modules.d.ts +55 -0
  216. package/lib/runtime/next-modules.js +124 -0
  217. package/lib/runtime/next-modules.test.d.ts +1 -0
  218. package/lib/runtime/next-modules.test.js +34 -0
  219. package/lib/runtime/public-files.d.ts +32 -0
  220. package/lib/runtime/public-files.js +117 -0
  221. package/lib/runtime/public-files.test.d.ts +1 -0
  222. package/lib/runtime/public-files.test.js +97 -0
  223. package/lib/runtime/server.mjs +41588 -0
  224. package/lib/runtime/static-files.d.ts +50 -0
  225. package/lib/runtime/static-files.js +266 -0
  226. package/lib/runtime/static-files.test.d.ts +1 -0
  227. package/lib/runtime/static-files.test.js +118 -0
  228. package/lib/runtime/util.d.ts +28 -0
  229. package/lib/runtime/util.js +79 -0
  230. package/lib/utils/base-path.d.ts +123 -11
  231. package/lib/utils/base-path.js +276 -39
  232. package/lib/utils/base-path.test.js +275 -50
  233. package/lib/utils/get-architecture.d.ts +7 -8
  234. package/lib/utils/get-architecture.js +12 -13
  235. package/lib/utils/zip-directory.d.ts +14 -0
  236. package/lib/utils/zip-directory.js +121 -0
  237. package/lib/utils/zip-directory.test.d.ts +1 -0
  238. package/lib/utils/zip-directory.test.js +99 -0
  239. package/package.json +22 -3
  240. package/scripts/capture-adapter-fixture.mjs +325 -0
  241. package/scripts/e2e-deploy.sh +398 -0
  242. package/scripts/e2e-harness/README.md +707 -0
  243. package/scripts/e2e-harness/app.js +370 -0
  244. package/scripts/e2e-harness/common.sh +249 -0
  245. package/scripts/e2e-harness/screen.mjs +302 -0
  246. package/scripts/e2e-harness/stage-proxy.mjs +145 -0
  247. package/scripts/e2e-harness/type-filters.mjs +47 -0
  248. package/scripts/e2e-logs.sh +75 -0
  249. package/scripts/e2e-offline.sh +91 -0
  250. package/scripts/e2e-sweep.sh +370 -0
  251. package/scripts/e2e-warm.sh +114 -0
  252. package/scripts/zero-config-build.mjs +418 -0
  253. package/docs/1k-concurrent-users-executions.png +0 -0
  254. package/docs/plans/adapter-runtime-release.md +0 -362
  255. package/docs/plans/phase-0-image-function-opt-in.md +0 -295
  256. package/lib/generated-structs/OptionalDockerImageFunctionProps.d.ts +0 -425
  257. package/lib/generated-structs/OptionalDockerImageFunctionProps.js +0 -3
  258. package/lib/image-optimization/handler-utils.d.ts +0 -34
  259. package/lib/image-optimization/handler-utils.js +0 -83
  260. package/lib/image-optimization/handler-utils.test.js +0 -178
  261. package/lib/nextjs-build/functions.Dockerfile +0 -31
  262. package/lib/nextjs-compute/nextjs-image-function.d.ts +0 -53
  263. package/lib/nextjs-compute/nextjs-image-function.js +0 -59
  264. package/lib/utils/experimental-flags.d.ts +0 -24
  265. package/lib/utils/experimental-flags.js +0 -30
  266. /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=