@dbx-tools/tunnel 0.6.114 → 0.6.116

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -357,6 +357,12 @@ the cookie, because that request was never going to be gated. So the same runnin
357
357
  app shows the OTP screen to a portr visitor and no login at all to a browser on
358
358
  `localhost` or the platform front door.
359
359
 
360
+ When the hosted login page interrupts a navigation, it carries the original
361
+ same-origin path through the login flow and replaces the page with that path
362
+ after OTP verification. API denials expose the hosted login URL in `loginPath`;
363
+ its `returnTo` query value comes from a same-origin referrer and is normalized
364
+ to an application path, so it cannot become an external redirect.
365
+
360
366
  `POST /api/email/auth/logout` clears the current session and returns
361
367
  `{ ok, redirectTo }`. `GET` on the same path clears the session and answers with
362
368
  a `303` redirect. `logoutRedirectPath` or
package/lib/src/gate.d.ts CHANGED
@@ -107,6 +107,21 @@ export declare const UNAUTHORIZED_BODY: {
107
107
  readonly error: "authentication required";
108
108
  readonly loginPath: "/api/email/auth";
109
109
  };
110
+ /** Restrict a post-login destination to one same-origin application path. */
111
+ export declare function normalizeReturnTo(value: string | undefined): string;
112
+ /** Resolve the page a browser should return to after tunnel authentication. */
113
+ export declare function requestReturnTo(req: IncomingMessage): string;
114
+ /** Build the hosted login URL with a validated same-origin return path. */
115
+ export declare function loginPath(req: IncomingMessage): string;
116
+ /** Build a denied JSON response that preserves the calling page. */
117
+ export declare function unauthorizedBody(req: IncomingMessage): {
118
+ error: typeof UNAUTHORIZED_BODY.error;
119
+ loginPath: string;
120
+ };
121
+ /** Return the validated destination carried by a hosted login URL. */
122
+ export declare function loginReturnTo(req: IncomingMessage): string;
123
+ /** Whether this request asks for the hosted login document itself. */
124
+ export declare function wantsHostedLogin(req: IncomingMessage): boolean;
110
125
  /**
111
126
  * Whether a denied request is a top-level BROWSER NAVIGATION that should be
112
127
  * answered with the hosted login page rather than a 401.
package/lib/src/gate.js CHANGED
@@ -196,6 +196,56 @@ export const UNAUTHORIZED_BODY = {
196
196
  error: "authentication required",
197
197
  loginPath: AUTH_PREFIX,
198
198
  };
199
+ /** Restrict a post-login destination to one same-origin application path. */
200
+ export function normalizeReturnTo(value) {
201
+ const candidate = value?.trim();
202
+ if (!candidate?.startsWith("/") || candidate.startsWith("//") || candidate.includes("\\")) {
203
+ return "/";
204
+ }
205
+ const parsed = new URL(candidate, "http://app.local");
206
+ return `${parsed.pathname}${parsed.search}${parsed.hash}`;
207
+ }
208
+ /** Resolve the page a browser should return to after tunnel authentication. */
209
+ export function requestReturnTo(req) {
210
+ if (wantsLoginPage(req)) {
211
+ const originalUrl = req.originalUrl;
212
+ return normalizeReturnTo(originalUrl || req.url);
213
+ }
214
+ const referer = String(req.headers.referer ?? "").trim();
215
+ if (!referer)
216
+ return "/";
217
+ try {
218
+ const parsed = new URL(referer);
219
+ const host = String(req.headers.host ?? "").toLowerCase();
220
+ if (parsed.host.toLowerCase() !== host)
221
+ return "/";
222
+ return normalizeReturnTo(`${parsed.pathname}${parsed.search}${parsed.hash}`);
223
+ }
224
+ catch {
225
+ return "/";
226
+ }
227
+ }
228
+ /** Build the hosted login URL with a validated same-origin return path. */
229
+ export function loginPath(req) {
230
+ return `${AUTH_PREFIX}?returnTo=${encodeURIComponent(requestReturnTo(req))}`;
231
+ }
232
+ /** Build a denied JSON response that preserves the calling page. */
233
+ export function unauthorizedBody(req) {
234
+ return { ...UNAUTHORIZED_BODY, loginPath: loginPath(req) };
235
+ }
236
+ /** Return the validated destination carried by a hosted login URL. */
237
+ export function loginReturnTo(req) {
238
+ const url = new URL(req.url ?? AUTH_PREFIX, "http://app.local");
239
+ return normalizeReturnTo(url.searchParams.get("returnTo") ?? "/");
240
+ }
241
+ /** Whether this request asks for the hosted login document itself. */
242
+ export function wantsHostedLogin(req) {
243
+ const method = (req.method ?? "GET").toUpperCase();
244
+ if (method !== "GET" && method !== "HEAD")
245
+ return false;
246
+ const path = (req.url ?? "/").split("?")[0] ?? "/";
247
+ return path === AUTH_PREFIX && String(req.headers.accept ?? "").includes("text/html");
248
+ }
199
249
  /**
200
250
  * Whether a denied request is a top-level BROWSER NAVIGATION that should be
201
251
  * answered with the hosted login page rather than a 401.
@@ -243,6 +293,16 @@ export function mountGate(opts, _addRoute, addMiddleware) {
243
293
  }
244
294
  return;
245
295
  }
296
+ if (wantsHostedLogin(req)) {
297
+ res
298
+ .status(200)
299
+ .type("html")
300
+ .send(loginPageHtml({
301
+ brandName: brandName ?? "Databricks App",
302
+ returnTo: loginReturnTo(req),
303
+ }));
304
+ return;
305
+ }
246
306
  await sendWebResponse(res, await gate.handler(await webRequest(req)));
247
307
  });
248
308
  addMiddleware(AUTH_PREFIX, authHandler);
@@ -250,13 +310,21 @@ export function mountGate(opts, _addRoute, addMiddleware) {
250
310
  const gateMiddleware = (async (req, res, next) => {
251
311
  const action = await gateRequest(req, { gate, publicDomain, headerPolicy, gatePaths });
252
312
  if (action === "deny" && wantsLoginPage(req)) {
253
- res.status(401).type("html").send(loginPageHtml({ brandName: brandName ?? "Databricks App" }));
313
+ res
314
+ .status(401)
315
+ .type("html")
316
+ .send(loginPageHtml({
317
+ brandName: brandName ?? "Databricks App",
318
+ returnTo: requestReturnTo(req),
319
+ }));
254
320
  }
255
- else if (action === "deny")
256
- res.status(401).json(UNAUTHORIZED_BODY);
257
- else
321
+ else if (action === "deny") {
322
+ res.status(401).json(unauthorizedBody(req));
323
+ }
324
+ else {
258
325
  next();
326
+ }
259
327
  });
260
328
  addMiddleware("/", gateMiddleware);
261
329
  }
262
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2F0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9nYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBR0gsT0FBTyxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUVwRCxPQUFPLEVBQUUsY0FBYyxFQUFxQixNQUFNLGNBQWMsQ0FBQztBQUNqRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFHaEQsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztBQU96QyxNQUFNLENBQUMsTUFBTSxXQUFXLEdBQUcsaUJBQWlCLENBQUM7QUE4QjdDOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsWUFBWSxDQUMxQixHQUFvQixFQUNwQixZQUFvRDtJQUVwRCxJQUFJLENBQUMsWUFBWTtRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ2hDLE1BQU0sSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xFLE1BQU0sT0FBTyxHQUFHLE9BQU8sWUFBWSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDO0lBQ2pGLE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsSUFBSSxLQUFLLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMvRSxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsUUFBUSxDQUFDLEdBQW9CO0lBQzNDLE1BQU0sU0FBUyxH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QyxDQUFDO0FBQ3JDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFRoZSB0dW5uZWwncyBpbi1hcHAgQVVUSCBHQVRFIC0gRXhwcmVzcyBtaWRkbGV3YXJlICsgbG9naW4gcm91dGVzIHRoZVxuICoge0BsaW5rIEF1dGhHYXRlUGx1Z2lufSByZWdpc3RlcnMgb24gdGhlIGFwcCdzIE9XTiBzZXJ2ZXIgdmlhIGB0aGlzLmNvbnRleHRgLlxuICpcbiAqIFRoZSBnYXRlIGlzIE1JRERMRVdBUkUsIG5vdCBhIHJldmVyc2UgcHJveHkgLSB0aGUgYXBwIGlzIHRoZSBwcm9jZXNzLCBzbyB0aGVyZSBpc1xuICogbm90aGluZyB0byBmb3J3YXJkIHRvLiBJdCBlaXRoZXIgc2hvcnQtY2lyY3VpdHMgKDQwMSwgb3IgYW5zd2VycyB0aGUgb3BlbiBsb2dpblxuICogcm91dGVzKSBvciBjYWxscyBgbmV4dCgpYCB0byBsZXQgdGhlIGFwcCdzIHJlYWwgaGFuZGxlcnMgcnVuLiBJdCBpcyB0aGVcbiAqIFwic3RhbmRzIGluIGZvciBBcHBLaXQgYXV0aFwiIHBhdGg6XG4gKiBhIHBvcnRyIGNhbGxlciBhdXRoZW50aWNhdGVzIHdpdGggQmV0dGVyIEF1dGggT1RQIG9yIGEgcGFzc2tleSwgYW5kIG9uXG4gKiBzdWNjZXNzIHRoZSBnYXRlIGluamVjdHMgdGhlIGlkZW50aXR5IGhlYWRlcnMgQXBwS2l0IHJlYWRzLlxuICpcbiAqIFdISUNIIFRSQUZGSUMgSVMgR0FURUQgLSB0aGUgYEhvc3RgIGhlYWRlciwgbm90IHRoZSBzb2NrZXQuIHBvcnRyJ3MgY2xpZW50XG4gKiBmb3J3YXJkcyB3aXRoIEdvJ3MgYGh0dHB1dGlsLk5ld1NpbmdsZUhvc3RSZXZlcnNlUHJveHlgIGFuZCBhIGBEaXJlY3RvcmAgdGhhdFxuICogUFJFU0VSVkVTIHRoZSBvcmlnaW5hbCBgSG9zdGAsIHNvIHR1bm5lbCByZXF1ZXN0cyBhcnJpdmUgd2l0aFxuICogYEhvc3Q6IDxzdWJkb21haW4+LjxzZXJ2ZXI+YCAodGhlIHB1YmxpYyBkb21haW4pLiBBIGxvY2FsIHByb2Nlc3MgaGl0dGluZyB0aGVcbiAqIGFwcCBkaXJlY3RseSBzZW5kcyBgSG9zdDogMTI3LjAuMC4xOjxwb3J0PmAgLyBgbG9jYWxob3N0YC4gU28gT05MWSByZXF1ZXN0cyB3aG9zZVxuICogYEhvc3RgIG1hdGNoZXMgdGhlIGNvbmZpZ3VyZWQgcHVibGljIGRvbWFpbiBhcmUgZ2F0ZWQ7IHRoZSBwbGF0Zm9ybSBmcm9udCBkb29yXG4gKiBhbmQgYW55IG90aGVyIGxvY2FsIGNsaWVudCBwYXNzIHRocm91Z2ggdW50b3VjaGVkLiBUaGVyZSBpcyBubyBwb3J0ci1pbmplY3RlZFxuICogaWRlbnRpZnlpbmcgaGVhZGVyIGFuZCBubyBUQ1Avc291cmNlLUlQIHNpZ25hbCB0byB1c2UgaW5zdGVhZCAodGhlIGNsaWVudCBkaWFsc1xuICogdGhlIHRhcmdldCBvdmVyIHBsYWluIGxvb3BiYWNrKS5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBJbmNvbWluZ01lc3NhZ2UgfSBmcm9tIFwibm9kZTpodHRwXCI7XG5pbXBvcnQgeyBsb2csIHRva2VuIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB0eXBlIHsgUmVxdWVzdEhhbmRsZXIsIFJlc3BvbnNlIH0gZnJvbSBcImV4cHJlc3NcIjtcbmltcG9ydCB7IHRvSGVhZGVyUG9saWN5LCB0eXBlIEhlYWRlclBvbGljeSB9IGZyb20gXCIuL2hlYWRlcnMudHNcIjtcbmltcG9ydCB7IGxvZ2luUGFnZUh0bWwgfSBmcm9tIFwiLi9sb2dpbi1wYWdlLnRzXCI7XG5pbXBvcnQgdHlwZSB7IEF1dGhHYXRlQXBpIH0gZnJvbSBcIi4vcGx1Z2luLnRzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJ0dW5uZWw6Z2F0ZVwiKTtcblxudHlwZSBXZWJSZXF1ZXN0SW5wdXQgPSBJbmNvbWluZ01lc3NhZ2UgJiB7XG4gIGJvZHk/OiB1bmtub3duO1xuICBvcmlnaW5hbFVybD86IHN0cmluZztcbn07XG5cbmV4cG9ydCBjb25zdCBBVVRIX1BSRUZJWCA9IFwiL2FwaS9lbWFpbC9hdXRoXCI7XG5cbi8qKiBPcHRpb25zIGZvciB7QGxpbmsgbW91bnRHYXRlfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2F0ZU9wdGlvbnMge1xuICAvKiogVGhlIGluLXByb2Nlc3MgZ2F0ZSBBUEkgKHNlc3Npb24vcmVxdWVzdC92ZXJpZnkvc3RhdHVzKS4gKi9cbiAgZ2F0ZTogQXV0aEdhdGVBcGk7XG4gIC8qKlxuICAgKiBUaGUgcHVibGljIGA8c3ViZG9tYWluPi48c2VydmVyPmAgdGhhdCBpZGVudGlmaWVzIHBvcnRyIHRyYWZmaWMgYnkgYEhvc3RgLlxuICAgKiBXaGVuIGFic2VudCwgbm8gcmVxdWVzdCBpcyBldmVyIGNsYXNzaWZpZWQgYXMgdHVubmVsIHRyYWZmaWMgYW5kIHRoZSBnYXRlIGlzXG4gICAqIGluZXJ0IChldmVyeXRoaW5nIHBhc3NlcyB0aHJvdWdoKSAtIGEgdHVubmVsIHdpdGggbm8gcHVibGljIGRvbWFpbiBnYXRlc1xuICAgKiBub3RoaW5nLlxuICAgKi9cbiAgcHVibGljRG9tYWluPzogc3RyaW5nIHwgcmVhZG9ubHkgc3RyaW5nW107XG4gIC8qKlxuICAgKiBFeHRyYSBgeC1gIHJlcXVlc3QgaGVhZGVycyB0dW5uZWwgdHJhZmZpYyBtYXkgZm9yd2FyZCAodW5pb25lZCB3aXRoIHRoZVxuICAgKiBidWlsdC1pbiBhbGxvdy1saXN0KS4gRXZlcnkgb3RoZXIgYHgtYCBoZWFkZXIgaXMgc3RyaXBwZWQgZnJvbSB0dW5uZWwgdHJhZmZpYy5cbiAgICovXG4gIGZvcndhcmRIZWFkZXJzPzogcmVhZG9ubHkgc3RyaW5nW107XG4gIC8qKlxuICAgKiBQYXRoIHByZWZpeGVzIHRoYXQgcmVxdWlyZSBhIHZhbGlkIHNlc3Npb24sIGJleW9uZCB0aGUgYnVpbHQtaW4gYC9hcGkvYC5cbiAgICogVGhlIGRlZmF1bHQgZ2F0aW5nIG1vZGVsIGFzc3VtZXMgYSBzZWxmLXByb3RlY3RpbmcgU1BBOiBzdGF0aWMgbG9hZHMgZnJlZWx5XG4gICAqIHNvIHRoZSBhcHAgY2FuIHJlbmRlciwgYW5kIG9ubHkgYC9hcGkvKmAgaXMgZ2F0ZWQuIEFuIGFwcCB3aG9zZSBwcml2aWxlZ2VkXG4gICAqIHN1cmZhY2UgaXMgTk9UIHVuZGVyIGAvYXBpL2AgKGUuZy4gYSBXZWJTb2NrZXQgYXQgYC93c2ApIGxpc3RzIHRob3NlIHByZWZpeGVzXG4gICAqIGhlcmUgc28gdGhleSBhcmUgZ2F0ZWQgdG9vLiBMb2dpbiByb3V0ZXMgKGBBVVRIX1BSRUZJWGApIGFyZSBhbHdheXMgb3Blbi5cbiAgICovXG4gIGdhdGVQYXRocz86IHJlYWRvbmx5IHN0cmluZ1tdO1xuICAvKiogUHJvZHVjdCBuYW1lIGRpc3BsYXllZCBieSB0aGUgaG9zdGVkIGxvZ2luIHBhZ2UuICovXG4gIGJyYW5kTmFtZT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBUcnVlIHdoZW4gdGhlIHJlcXVlc3QncyBgSG9zdGAgaXMgb25lIG9mIHRoZSB0dW5uZWwncyBwdWJsaWMgZG9tYWlucyAtIGkuZS4gaXRcbiAqIGNhbWUgaW4gb3ZlciBQb3J0ciBvciBGUlAuIENhc2UtaW5zZW5zaXRpdmU7IHRoZSBvcHRpb25hbCBgOnBvcnRgIGlzIGlnbm9yZWQuXG4gKiBXaGVuIG5vIHB1YmxpYyBkb21haW4gaXMgY29uZmlndXJlZCwgbm90aGluZyBpcyB0dW5uZWwgdHJhZmZpYy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVHVubmVsSG9zdChcbiAgcmVxOiBJbmNvbWluZ01lc3NhZ2UsXG4gIHB1YmxpY0RvbWFpbjogc3RyaW5nIHwgcmVhZG9ubHkgc3RyaW5nW10gfCB1bmRlZmluZWQsXG4pOiBib29sZWFuIHtcbiAgaWYgKCFwdWJsaWNEb21haW4pIHJldHVybiBmYWxzZTtcbiAgY29uc3QgaG9zdCA9IChyZXEuaGVhZGVycy5ob3N0ID8/IFwiXCIpLnRvTG93ZXJDYXNlKCkuc3BsaXQoXCI6XCIpWzBdO1xuICBjb25zdCBkb21haW5zID0gdHlwZW9mIHB1YmxpY0RvbWFpbiA9PT0gXCJzdHJpbmdcIiA/IFtwdWJsaWNEb21haW5dIDogcHVibGljRG9tYWluO1xuICByZXR1cm4gZG9tYWlucy5zb21lKChkb21haW4pID0+IGhvc3QgPT09IGRvbWFpbi50b0xvd2VyQ2FzZSgpLnNwbGl0KFwiOlwiKVswXSk7XG59XG5cbi8qKlxuICogQ2xpZW50IElQIGZvciByYXRlLWxpbWl0aW5nOiB0aGUgUklHSFRNT1NUIGB4LWZvcndhcmRlZC1mb3JgIGVudHJ5ICh0aGUgdmFsdWVcbiAqIHRoZSBuZWFyZXN0IHRydXN0ZWQgaG9wIC0gcG9ydHIgLSB3cm90ZSksIGVsc2UgdGhlIHNvY2tldCBhZGRyZXNzLiBSZWFkaW5nIHRoZVxuICogcmlnaHRtb3N0LCBub3QgdGhlIGxlZnRtb3N0LCBzdG9wcyBhIGNhbGxlciBtaW50aW5nIGEgZnJlc2ggcmF0ZS1saW1pdCBidWNrZXQgYnlcbiAqIHZhcnlpbmcgdGhlIGhlYWRlci4gQ2FsbGVkIGJlZm9yZSB7QGxpbmsgc3RyaXBIZWFkZXJzfS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsaWVudElwKHJlcTogSW5jb21pbmdNZXNzYWdlKTogc3RyaW5nIHtcbiAgY29uc3QgZm9yd2FyZGVkID0gcmVxLmhlYWRlcnNbXCJ4LWZvcndhcmRlZC1mb3JcIl07XG4gIGNvbnN0IGNoYWluID0gKEFycmF5LmlzQXJyYXkoZm9yd2FyZGVkKSA/IGZvcndhcmRlZC5qb2luKFwiLFwiKSA6IChmb3J3YXJkZWQgPz8gXCJcIikpXG4gICAgLnNwbGl0KFwiLFwiKVxuICAgIC5tYXAoKGVudHJ5KSA9PiBlbnRyeS50cmltKCkpXG4gICAgLmZpbHRlcihCb29sZWFuKTtcbiAgcmV0dXJuIGNoYWluLmF0KC0xKSA/PyByZXEuc29ja2V0LnJlbW90ZUFkZHJlc3MgPz8gXCJ1bmtub3duXCI7XG59XG5cbi8qKlxuICogUmVtb3ZlIHRoZSBnYXRlJ3Mgc2Vzc2lvbiBjb29raWUgZnJvbSB0aGUgYENvb2tpZWAgaGVhZGVyIGJlZm9yZSB0aGUgYXBwJ3NcbiAqIGhhbmRsZXJzIHJ1biwgc28gdGhlIGFwcCBuZXZlciBzZWVzIGBkYnhfYXV0aGAgKGl0IGlzIHRoZSBnYXRlJ3MgY29uY2VybikuXG4gKiBQcmVzZXJ2ZXMgb3RoZXIgY29va2llczsgZGVsZXRlcyB0aGUgaGVhZGVyIHdoZW4gaXQgYmVjb21lcyBlbXB0eS5cbiAqL1xuZnVuY3Rpb24gc3RyaXBTZXNzaW9uQ29va2llKHJlcTogSW5jb21pbmdNZXNzYWdlKTogdm9pZCB7XG4gIGNvbnN0IHJhdyA9IHJlcS5oZWFkZXJzLmNvb2tpZTtcbiAgaWYgKCFyYXcpIHJldHVybjtcbiAgY29uc3Qga2VwdCA9IHJhd1xuICAgIC5zcGxpdChcIjtcIilcbiAgICAubWFwKChjKSA9PiBjLnRyaW0oKSlcbiAgICAuZmlsdGVyKChjKSA9PiBjICYmICFjLnN0YXJ0c1dpdGgoXCJkYngtdG9vbHMtYXV0aD1cIikgJiYgIWMuc3RhcnRzV2l0aChcImRieC10b29scy1wYXNza2V5PVwiKSk7XG4gIGlmIChrZXB0Lmxlbmd0aCkgcmVxLmhlYWRlcnMuY29va2llID0ga2VwdC5qb2luKFwiOyBcIik7XG4gIGVsc2UgZGVsZXRlIHJlcS5oZWFkZXJzLmNvb2tpZTtcbn1cblxuLyoqXG4gKiBQcmVzZW50IGEgcGFzc3dvcmRsZXNzLWF1dGhlbnRpY2F0ZWQgY2FsbGVyIHRvIHRoZSBhcHAgdGhlIFNBTUUgd2F5IGEgcGxhdGZvcm0gZnJvbnRcbiAqIGRvb3IgZG9lczogc2V0IHRoZSBmcm9udC1kb29yIGlkZW50aXR5IGhlYWRlcnMgdG8gdGhlIHZlcmlmaWVkIGFkZHJlc3MgKEFwcEtpdFxuICogcmVhZHMge0BsaW5rIHRva2VuLlVTRVJfSURfSEVBREVSfSBmb3IgdGhlIE9CTyB1c2VyIGlkKSwgc28gdGhlIGFwcCBuZWVkcyBub1xuICogZ2F0ZS1zcGVjaWZpYyBjb2RlIHBhdGguXG4gKlxuICogV2hhdCB0aGUgZ2F0ZSBDQU5OT1Qgc2V0IGlzIHtAbGluayB0b2tlbi5BQ0NFU1NfVE9LRU5fSEVBREVSfTogYW4gYXV0aCBzZXNzaW9uXG4gKiBwcm92ZXMgYW4gZW1haWwsIG5vdCBwb3NzZXNzaW9uIG9mIGEgRGF0YWJyaWNrcyBjcmVkZW50aWFsLiBJdHMgYWJzZW5jZSBpcyB3aGF0XG4gKiBgQGRieC10b29scy9hcHBraXRgJ3MgYGlkZW50aXR5OiBcImF1dG9cImAgZGV0ZWN0cywgc28gYSBnYXRlZCByZXF1ZXN0IHJ1bnMgYXMgdGhlXG4gKiBhcHAgc2VydmljZSBwcmluY2lwYWwgaW5zdGVhZCBvZiB0aHJvd2luZy5cbiAqL1xuZnVuY3Rpb24gaW5qZWN0SWRlbnRpdHkocmVxOiBJbmNvbWluZ01lc3NhZ2UsIGVtYWlsOiBzdHJpbmcpOiB2b2lkIHtcbiAgcmVxLmhlYWRlcnNbdG9rZW4uVVNFUl9JRF9IRUFERVJdID0gZW1haWw7XG4gIHJlcS5oZWFkZXJzW3Rva2VuLlVTRVJfRU1BSUxfSEVBREVSXSA9IGVtYWlsO1xufVxuXG4vKiogUmVhZCB0aGUgcmF3IHJlcXVlc3QgYm9keSBhcyB0ZXh0IChBcHBLaXQgcGFyc2VzIEpTT04sIGJ1dCB0aGUgZ2F0ZSByb3V0ZXNcbiAqIGFyZSBtb3VudGVkIGJlZm9yZSB0aGF0IHJ1bnMgZm9yIHR1bm5lbCB0cmFmZmljLCBzbyByZWFkIGRlZmVuc2l2ZWx5KS4gKi9cbmZ1bmN0aW9uIHJlYWRCb2R5KHJlcTogV2ViUmVxdWVzdElucHV0KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgLy8gQXBwS2l0J3MganNvbiBib2R5LXBhcnNlciBtYXkgaGF2ZSBhbHJlYWR5IHBvcHVsYXRlZCByZXEuYm9keTsgcHJlZmVyIGl0LlxuICBpZiAocmVxLmJvZHkgIT09IHVuZGVmaW5lZCAmJiByZXEuYm9keSAhPT0gbnVsbCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodHlwZW9mIHJlcS5ib2R5ID09PSBcInN0cmluZ1wiID8gcmVxLmJvZHkgOiBKU09OLnN0cmluZ2lmeShyZXEuYm9keSkpO1xuICB9XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgIGxldCBkYXRhID0gXCJcIjtcbiAgICByZXEub24oXCJkYXRhXCIsIChjaHVuaykgPT4gKGRhdGEgKz0gY2h1bmspKTtcbiAgICByZXEub24oXCJlbmRcIiwgKCkgPT4gcmVzb2x2ZShkYXRhKSk7XG4gICAgcmVxLm9uKFwiZXJyb3JcIiwgKCkgPT4gcmVzb2x2ZShkYXRhKSk7XG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gd2ViSGVhZGVycyhyZXE6IEluY29taW5nTWVzc2FnZSk6IEhlYWRlcnMge1xuICBjb25zdCBoZWFkZXJzID0gbmV3IEhlYWRlcnMoKTtcbiAgZm9yIChjb25zdCBbbmFtZSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHJlcS5oZWFkZXJzKSkge1xuICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgZm9yIChjb25zdCBpdGVtIG9mIHZhbHVlKSBoZWFkZXJzLmFwcGVuZChuYW1lLCBpdGVtKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGhlYWRlcnMuc2V0KG5hbWUsIHZhbHVlKTtcbiAgICB9XG4gIH1cbiAgaGVhZGVycy5zZXQoXCJ4LXJlYWwtaXBcIiwgY2xpZW50SXAocmVxKSk7XG4gIHJldHVybiBoZWFkZXJzO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd2ViUmVxdWVzdChyZXE6IFdlYlJlcXVlc3RJbnB1dCk6IFByb21pc2U8Z2xvYmFsVGhpcy5SZXF1ZXN0PiB7XG4gIGNvbnN0IGhvc3QgPSByZXEuaGVhZGVycy5ob3N0ID8/IFwibG9jYWxob3N0XCI7XG4gIGNvbnN0IGhvc3RuYW1lID0gaG9zdC5zcGxpdChcIjpcIilbMF0/LnRvTG93ZXJDYXNlKCk7XG4gIGNvbnN0IHByb3RvY29sID0gaG9zdG5hbWUgPT09IFwibG9jYWxob3N0XCIgfHwgaG9zdG5hbWUgPT09IFwiMTI3LjAuMC4xXCIgPyBcImh0dHBcIiA6IFwiaHR0cHNcIjtcbiAgY29uc3QgbWV0aG9kID0gKHJlcS5tZXRob2QgPz8gXCJHRVRcIikudG9VcHBlckNhc2UoKTtcbiAgY29uc3QgYm9keSA9IG1ldGhvZCA9PT0gXCJHRVRcIiB8fCBtZXRob2QgPT09IFwiSEVBRFwiID8gdW5kZWZpbmVkIDogYXdhaXQgcmVhZEJvZHkocmVxKTtcbiAgcmV0dXJuIG5ldyBnbG9iYWxUaGlzLlJlcXVlc3QoYCR7cHJvdG9jb2x9Oi8vJHtob3N0fSR7cmVxLm9yaWdpbmFsVXJsIHx8IHJlcS51cmx9YCwge1xuICAgIG1ldGhvZCxcbiAgICBoZWFkZXJzOiB3ZWJIZWFkZXJzKHJlcSksXG4gICAgLi4uKGJvZHkgPyB7IGJvZHkgfSA6IHt9KSxcbiAgfSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZW5kV2ViUmVzcG9uc2UocmVzOiBSZXNwb25zZSwgcmVzcG9uc2U6IGdsb2JhbFRoaXMuUmVzcG9uc2UpOiBQcm9taXNlPHZvaWQ+IHtcbiAgZm9yIChjb25zdCBbbmFtZSwgdmFsdWVdIG9mIHJlc3BvbnNlLmhlYWRlcnMuZW50cmllcygpKSB7XG4gICAgaWYgKG5hbWUudG9Mb3dlckNhc2UoKSAhPT0gXCJzZXQtY29va2llXCIpIHJlcy5zZXRIZWFkZXIobmFtZSwgdmFsdWUpO1xuICB9XG4gIGNvbnN0IGNvb2tpZXMgPSByZXNwb25zZS5oZWFkZXJzLmdldFNldENvb2tpZSgpO1xuICBpZiAoY29va2llcy5sZW5ndGgpIHJlcy5zZXRIZWFkZXIoXCJzZXQtY29va2llXCIsIGNvb2tpZXMpO1xuICBjb25zdCBib2R5ID0gQnVmZmVyLmZyb20oYXdhaXQgcmVzcG9uc2UuYXJyYXlCdWZmZXIoKSk7XG4gIHJlcy5zdGF0dXMocmVzcG9uc2Uuc3RhdHVzKS5zZW5kKGJvZHkpO1xufVxuXG4vKipcbiAqIFdoYXQgdGhlIGNhbGxlciBzaG91bGQgZG8gd2l0aCBhIHJlcXVlc3QsIGZyb20ge0BsaW5rIGdhdGVSZXF1ZXN0fS5cbiAqXG4gKiAgIC0gYHBhc3NgIC0gbm90IHR1bm5lbCB0cmFmZmljLCBvciBhbiBvcGVuIGxvZ2luIHJvdXRlLiBGb3J3YXJkIHVudG91Y2hlZC5cbiAqICAgLSBgYWxsb3dgIC0gdHVubmVsIHRyYWZmaWMgdGhhdCBpcyBhdXRob3JpemVkLiBUaGUgcmVxdWVzdCdzIGhlYWRlcnMgaGF2ZVxuICogICAgIEFMUkVBRFkgYmVlbiByZXdyaXR0ZW4gKHBvbGljeSBhcHBsaWVkLCBpZGVudGl0eSBpbmplY3RlZCwgc2Vzc2lvbiBjb29raWVcbiAqICAgICBzdHJpcHBlZCksIHNvIGZvcndhcmQgaXQgYXMgaXQgbm93IHN0YW5kcy5cbiAqICAgLSBgZGVueWAgLSB0dW5uZWwgdHJhZmZpYyB3aXRoIG5vIHZhbGlkIHNlc3Npb24uIEFuc3dlciBgNDAxYCB3aXRoXG4gKiAgICAge0BsaW5rIEFVVEhfUFJFRklYfSBhcyB0aGUgbG9naW4gcGF0aC5cbiAqL1xuZXhwb3J0IHR5cGUgR2F0ZUFjdGlvbiA9IFwicGFzc1wiIHwgXCJhbGxvd1wiIHwgXCJkZW55XCI7XG5cbi8qKlxuICogVEhFIGdhdGluZyBkZWNpc2lvbiwgZm9yIG9uZSByZXF1ZXN0LCBpbmRlcGVuZGVudCBvZiBob3cgaXQgd2lsbCBiZSBhbnN3ZXJlZC5cbiAqXG4gKiBCb3RoIHBhdGhzIGNhbGwgdGhpczogdGhlIEV4cHJlc3MgbWlkZGxld2FyZSBiZWxvdyAod2hlcmUgdGhlIGFwcCBpcyB0aGVcbiAqIHByb2Nlc3MpIGFuZCBgQGRieC10b29scy9jbGktdHVubmVsYCdzIHJldmVyc2UgcHJveHkgKHdoZXJlIHRoZSBhcHAgaXMgYSBjaGlsZFxuICogcHJvY2VzcyBvbiBhIHByaXZhdGUgcG9ydCkuIEEgZGl2ZXJnZW5jZSBiZXR3ZWVuIHRoZW0gd291bGQgYmUgYSBzZWN1cml0eSBidWdcbiAqIHRoZSBzZWNvbmQgcGF0aCBjb3VsZCBub3QgYmUgdGVzdGVkIGludG8gYWdyZWVtZW50IC0gb25lIHBhdGggZm9yZ2V0dGluZyB0b1xuICogc3RyaXAgYHgtZm9yd2FyZGVkLWFjY2Vzcy10b2tlbmAgaXMgZW5vdWdoIC0gc28gdGhlIGRlY2lzaW9uLCB0aGUgaGVhZGVyXG4gKiByZXdyaXRpbmcsIGFuZCB0aGUgaWRlbnRpdHkgaW5qZWN0aW9uIGxpdmUgaGVyZSBvbmNlIGFuZCB0aGUgdHJhbnNwb3J0cyBvbmx5XG4gKiBkaWZmZXIgaW4gaG93IHRoZXkgV1JJVEUgdGhlIG91dGNvbWUuXG4gKlxuICogTXV0YXRlcyBgcmVxLmhlYWRlcnNgIG9uIHRoZSBgYWxsb3dgL2BwYXNzYC13aXRoLWNvb2tpZSBwYXRocywgd2hpY2ggaXMgZXhhY3RseVxuICogd2hhdCBib3RoIGNhbGxlcnMgd2FudDogRXhwcmVzcyBoYW5kcyB0aGUgc2FtZSBvYmplY3QgdG8gdGhlIGFwcCdzIGhhbmRsZXJzLCBhbmRcbiAqIHRoZSBwcm94eSBmb3J3YXJkcyBpdCB1cHN0cmVhbS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdhdGVSZXF1ZXN0KFxuICByZXE6IEluY29taW5nTWVzc2FnZSxcbiAgb3B0aW9uczogR2F0ZU9wdGlvbnMgJiB7IGhlYWRlclBvbGljeT86IEhlYWRlclBvbGljeSB9LFxuKTogUHJvbWlzZTxHYXRlQWN0aW9uPiB7XG4gIGNvbnN0IHsgZ2F0ZSwgcHVibGljRG9tYWluIH0gPSBvcHRpb25zO1xuICAvLyBOb3QgdHVubmVsIHRyYWZmaWMgKHBsYXRmb3JtIGZyb250IGRvb3IsIG9yIGFueSBvdGhlciBsb2NhbCBjYWxsZXIpOiB0aGVcbiAgLy8gcmVxdWVzdCBpcyBhbHJlYWR5IGF1dGhlbnRpY2F0ZWQsIG9yIGlzIG5vdCBvdXJzIHRvIGdhdGUuXG4gIGlmICghaXNUdW5uZWxIb3N0KHJlcSwgcHVibGljRG9tYWluKSkgcmV0dXJuIFwicGFzc1wiO1xuXG4gIGNvbnN0IHBhdGggPSAocmVxLnVybCA/PyBcIi9cIikuc3BsaXQoXCI/XCIpWzBdID8/IFwiL1wiO1xuICAvLyBUaGUgbG9naW4gZmxvdyBpcyBvcGVuIHNvIHRoZSBicm93c2VyIGNhbiByZW5kZXIgPEF1dGhHYXRlPiBhbmQgc2lnbiBpbi5cbiAgaWYgKHBhdGguc3RhcnRzV2l0aChBVVRIX1BSRUZJWCkpIHJldHVybiBcInBhc3NcIjtcblxuICAvLyBBbnRpLXNwb29mOiBvbmx5IHRoZSBnYXRlIG1heSBhc3NlcnQgaWRlbnRpdHkgb24gdHVubmVsIHRyYWZmaWMuXG4gIGNvbnN0IHBvbGljeSA9IG9wdGlvbnMuaGVhZGVyUG9saWN5ID8/IHRvSGVhZGVyUG9saWN5KG9wdGlvbnMuZm9yd2FyZEhlYWRlcnMpO1xuICBjb25zdCByZW1vdmVkID0gcG9saWN5LmFwcGx5KHJlcS5oZWFkZXJzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KTtcbiAgaWYgKHJlbW92ZWQubGVuZ3RoKSBsb2dnZXIuZGVidWcoXCJzdHJpcHBlZCBpbmJvdW5kIGhlYWRlcnNcIiwgeyByZW1vdmVkIH0pO1xuXG4gIGNvbnN0IGdhdGVQYXRocyA9IG9wdGlvbnMuZ2F0ZVBhdGhzID8/IFtdO1xuICAvLyBBIHBhdGggaXMgZ2F0ZWQgaWYgaXQgaXMgdW5kZXIgYC9hcGkvYCBvciBhbnkgY2FsbGVyLXN1cHBsaWVkIHByZWZpeCAoZS5nLlxuICAvLyBgL3dzYCBmb3IgYSBXZWJTb2NrZXQgYXBwKS5cbiAgY29uc3QgZ2F0ZWQgPVxuICAgIHBhdGguc3RhcnRzV2l0aChcIi9hcGkvXCIpIHx8XG4gICAgZ2F0ZVBhdGhzLnNvbWUoKHByZWZpeCkgPT4gcGF0aCA9PT0gcHJlZml4IHx8IHBhdGguc3RhcnRzV2l0aChgJHtwcmVmaXh9L2ApKTtcblxuICAvLyBBcHAtZ2F0aW5nIG1vZGU6IHdoZW4gYGdhdGVQYXRoc2AgaXMgc2V0IHRoZSBjYWxsZXIgaXMgZnJvbnRpbmcgYSB3aG9sZSBhcHBcbiAgLy8gKG5vdCBhIHNlbGYtcHJvdGVjdGluZyBTUEEpLCBzbyBhbiB1bmF1dGhlbnRpY2F0ZWQgdG9wLWxldmVsIGJyb3dzZXJcbiAgLy8gbmF2aWdhdGlvbiBpcyBkZW5pZWQgdG9vIOKAlCB0aGUgdHJhbnNwb3J0IGFuc3dlcnMgaXQgd2l0aCB0aGUgaG9zdGVkIGxvZ2luXG4gIC8vIHBhZ2UsIHB1dHRpbmcgc2lnbi1pbiBpbiBmcm9udCBvZiB0aGUgYXBwIGluc3RlYWQgb2YgbG9hZGluZyBpdHMgc2hlbGwgd2l0aFxuICAvLyBhIGRlYWQgZ2F0ZWQgcmVxdWVzdC4gTm9uLW5hdmlnYXRpb24gc3RhdGljIChhc3NldHMpIHN0aWxsIGxvYWRzIGZyZWVseSBzb1xuICAvLyB0aGUgbG9naW4gcGFnZSBhbmQgYXBwIGNhbiByZW5kZXIuXG4gIGNvbnN0IGFwcEdhdGluZyA9IGdhdGVQYXRocy5sZW5ndGggPiAwO1xuICBjb25zdCBtdXN0QXV0aCA9IGdhdGVkIHx8IChhcHBHYXRpbmcgJiYgd2FudHNMb2dpblBhZ2UocmVxKSk7XG4gIGlmICghbXVzdEF1dGgpIHtcbiAgICBzdHJpcFNlc3Npb25Db29raWUocmVxKTtcbiAgICByZXR1cm4gXCJwYXNzXCI7XG4gIH1cblxuICAvLyBBIGdhdGVkIHJlcXVlc3QgbmVlZHMgYSB2YWxpZCBCZXR0ZXIgQXV0aCBzZXNzaW9uLlxuICBjb25zdCBlbWFpbCA9IGF3YWl0IGdhdGUuc2Vzc2lvbih3ZWJIZWFkZXJzKHJlcSkpO1xuICBpZiAoIWVtYWlsKSByZXR1cm4gXCJkZW55XCI7XG4gIGluamVjdElkZW50aXR5KHJlcSwgZW1haWwpO1xuICBzdHJpcFNlc3Npb25Db29raWUocmVxKTtcbiAgcmV0dXJuIFwiYWxsb3dcIjtcbn1cblxuLyoqIFRoZSBib2R5IG9mIGEgYGRlbnlgLCBzaGFyZWQgc28gYm90aCBwYXRocyBhbnN3ZXIgYSA0MDEgaWRlbnRpY2FsbHkuICovXG5leHBvcnQgY29uc3QgVU5BVVRIT1JJWkVEX0JPRFkgPSB7XG4gIGVycm9yOiBcImF1dGhlbnRpY2F0aW9uIHJlcXVpcmVkXCIsXG4gIGxvZ2luUGF0aDogQVVUSF9QUkVGSVgsXG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIFdoZXRoZXIgYSBkZW5pZWQgcmVxdWVzdCBpcyBhIHRvcC1sZXZlbCBCUk9XU0VSIE5BVklHQVRJT04gdGhhdCBzaG91bGQgYmVcbiAqIGFuc3dlcmVkIHdpdGggdGhlIGhvc3RlZCBsb2dpbiBwYWdlIHJhdGhlciB0aGFuIGEgNDAxLlxuICpcbiAqIEFuIGFwcCBmcm9udGVkIGJ5IHRoZSBnYXRlICh2aWEgYGdhdGVQYXRoc2ApIG1heSBzZXJ2ZSBpdHMgb3duIEhUTUwgZnJvbSBhblxuICogdW5nYXRlZCBwYXRoIHdoaWxlIGl0cyBwcml2aWxlZ2VkIHN1cmZhY2UgKGAvd3NgLCBgL2FwaWApIGlzIGdhdGVkLiBBIGJyb3dzZXJcbiAqIG5hdmlnYXRpbmcgdG8gaXQgd291bGQgb3RoZXJ3aXNlIGxvYWQgdGhlIGFwcCBzaGVsbCBhbmQgb25seSBzZWUgdGhlIGdhdGVkXG4gKiByZXF1ZXN0IGZhaWwsIHdpdGggbm8gd2F5IHRvIHNpZ24gaW4uIFNlcnZpbmcgdGhlIGxvZ2luIHBhZ2Ugb24gdGhlIG5hdmlnYXRpb25cbiAqIGl0c2VsZiBwdXRzIHNpZ24taW4gaW4gZnJvbnQgb2YgdGhlIGFwcC4gQXBwbGllcyBvbmx5IHRvIEdFVCByZXF1ZXN0cyB0aGF0XG4gKiBhY2NlcHQgSFRNTCBhbmQgYXJlIG5vdCBhc2tpbmcgZm9yIHRoZSBsb2dpbiBBUEkgb3IgYW4gYXNzZXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3YW50c0xvZ2luUGFnZShyZXE6IEluY29taW5nTWVzc2FnZSk6IGJvb2xlYW4ge1xuICBjb25zdCBtZXRob2QgPSAocmVxLm1ldGhvZCA/PyBcIkdFVFwiKS50b1VwcGVyQ2FzZSgpO1xuICBpZiAobWV0aG9kICE9PSBcIkdFVFwiICYmIG1ldGhvZCAhPT0gXCJIRUFEXCIpIHJldHVybiBmYWxzZTtcbiAgY29uc3QgcGF0aCA9IChyZXEudXJsID8/IFwiL1wiKS5zcGxpdChcIj9cIilbMF0gPz8gXCIvXCI7XG4gIGlmIChwYXRoLnN0YXJ0c1dpdGgoQVVUSF9QUkVGSVgpKSByZXR1cm4gZmFsc2U7XG4gIGNvbnN0IGFjY2VwdCA9IFN0cmluZyhyZXEuaGVhZGVycy5hY2NlcHQgPz8gXCJcIik7XG4gIHJldHVybiBhY2NlcHQuaW5jbHVkZXMoXCJ0ZXh0L2h0bWxcIik7XG59XG5cbi8qKlxuICogUmVnaXN0ZXIgdGhlIGxvZ2luIHJvdXRlcyBhbmQgdGhlIGdhdGluZyBtaWRkbGV3YXJlIG9uIHRoZSBhcHAncyBFeHByZXNzXG4gKiBpbnN0YW5jZS4gQ2FsbGVkIGZyb20ge0BsaW5rIEF1dGhHYXRlUGx1Z2lufSB3aXRoIHRoZSByb3V0ZXIgQXBwS2l0IGhhbmRzXG4gKiBgaW5qZWN0Um91dGVzYCwgcGx1cyBgdGhpcy5jb250ZXh0LmFkZE1pZGRsZXdhcmVgIGZvciB0aGUgZ2xvYmFsIGdhdGUuXG4gKlxuICogYGFkZFJvdXRlYC9gYWRkTWlkZGxld2FyZWAgYXJlIHVzZWQgKHZpYSB0aGUgcGFzc2VkIGNhbGxiYWNrcykgYmVjYXVzZSB0aGUgbG9naW5cbiAqIHJvdXRlcyBsaXZlIGF0IGFuIEFCU09MVVRFIHBhdGggKGAvYXBpL2VtYWlsL2F1dGgvKmAsIHRoZSBjbGllbnQncyBjb250cmFjdCksXG4gKiBub3QgdW5kZXIgdGhlIHBsdWdpbidzIGAvYXBpL2F1dGhHYXRlYCBiYXNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbW91bnRHYXRlKFxuICBvcHRzOiBHYXRlT3B0aW9ucyxcbiAgX2FkZFJvdXRlOiAobWV0aG9kOiBcImdldFwiIHwgXCJwb3N0XCIsIHBhdGg6IHN0cmluZywgaGFuZGxlcjogUmVxdWVzdEhhbmRsZXIpID0+IHZvaWQsXG4gIGFkZE1pZGRsZXdhcmU6IChwYXRoOiBzdHJpbmcsIGhhbmRsZXI6IFJlcXVlc3RIYW5kbGVyKSA9PiB2b2lkLFxuKTogdm9pZCB7XG4gIGNvbnN0IHsgZ2F0ZSwgcHVibGljRG9tYWluLCBmb3J3YXJkSGVhZGVycywgZ2F0ZVBhdGhzLCBicmFuZE5hbWUgfSA9IG9wdHM7XG4gIGNvbnN0IGhlYWRlclBvbGljeSA9IHRvSGVhZGVyUG9saWN5KGZvcndhcmRIZWFkZXJzKTtcbiAgbG9nZ2VyLmRlYnVnKFwiZ2F0ZSBtb3VudGVkXCIsIHsgcHVibGljRG9tYWluLCBmb3J3YXJkOiBoZWFkZXJQb2xpY3kucGF0dGVybnMsIGdhdGVQYXRocyB9KTtcblxuICAvLyBCZXR0ZXIgQXV0aCBhbmQgdGhlIGNvbXBhdGliaWxpdHkgcm91dGVzIHNoYXJlIG9uZSBmZXRjaC1jb21wYXRpYmxlXG4gIC8vIGhhbmRsZXIgaW4gYm90aCBob3N0aW5nIG1vZGVzLlxuICBjb25zdCBhdXRoSGFuZGxlciA9IChhc3luYyAocmVxLCByZXMpID0+IHtcbiAgICBpZiAoIWlzVHVubmVsSG9zdChyZXEsIHB1YmxpY0RvbWFpbikpIHtcbiAgICAgIGNvbnN0IHBhdGggPSAocmVxLnVybCA/PyBcIi9cIikuc3BsaXQoXCI/XCIpWzBdID8/IFwiL1wiO1xuICAgICAgaWYgKHBhdGguZW5kc1dpdGgoXCIvc3RhdHVzXCIpKSB7XG4gICAgICAgIHJlcy5zdGF0dXMoMjAwKS5qc29uKHsgYXV0aGVudGljYXRlZDogZmFsc2UsIGVuYWJsZWQ6IGZhbHNlLCBwYXNza2V5c0VuYWJsZWQ6IGZhbHNlIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzLnN0YXR1cyg0MDQpLmpzb24oeyBlcnJvcjogXCJub3QgZm91bmRcIiB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgYXdhaXQgc2VuZFdlYlJlc3BvbnNlKHJlcywgYXdhaXQgZ2F0ZS5oYW5kbGVyKGF3YWl0IHdlYlJlcXVlc3QocmVxKSkpO1xuICB9KSBhcyBSZXF1ZXN0SGFuZGxlcjtcbiAgYWRkTWlkZGxld2FyZShBVVRIX1BSRUZJWCwgYXV0aEhhbmRsZXIpO1xuXG4gIC8vIC0tLSBUaGUgZ2F0ZSBtaWRkbGV3YXJlIChydW5zIGJlZm9yZSBzdGF0aWMgKyB0aGUgYXBwJ3MgL2FwaSBoYW5kbGVycykgLS0tXG5cbiAgY29uc3QgZ2F0ZU1pZGRsZXdhcmUgPSAoYXN5bmMgKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgY29uc3QgYWN0aW9uID0gYXdhaXQgZ2F0ZVJlcXVlc3QocmVxLCB7IGdhdGUsIHB1YmxpY0RvbWFpbiwgaGVhZGVyUG9saWN5LCBnYXRlUGF0aHMgfSk7XG4gICAgaWYgKGFjdGlvbiA9PT0gXCJkZW55XCIgJiYgd2FudHNMb2dpblBhZ2UocmVxKSkge1xuICAgICAgcmVzLnN0YXR1cyg0MDEpLnR5cGUoXCJodG1sXCIpLnNlbmQobG9naW5QYWdlSHRtbCh7IGJyYW5kTmFtZTogYnJhbmROYW1lID8/IFwiRGF0YWJyaWNrcyBBcHBcIiB9KSk7XG4gICAgfSBlbHNlIGlmIChhY3Rpb24gPT09IFwiZGVueVwiKSByZXMuc3RhdHVzKDQwMSkuanNvbihVTkFVVEhPUklaRURfQk9EWSk7XG4gICAgZWxzZSBuZXh0KCk7XG4gIH0pIGFzIFJlcXVlc3RIYW5kbGVyO1xuXG4gIGFkZE1pZGRsZXdhcmUoXCIvXCIsIGdhdGVNaWRkbGV3YXJlKTtcbn1cbiJdfQ==
330
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2F0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9nYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBR0gsT0FBTyxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUVwRCxPQUFPLEVBQUUsY0FBYyxFQUFxQixNQUFNLGNBQWMsQ0FBQztBQUNqRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFHaEQsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztBQU96QyxNQUFNLENBQUMsTUFBTSxXQUFXLEdBQUcsaUJBQWlCLENBQUM7QUE4QjdDOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsWUFBWSxDQUMxQixHQUFvQixFQUNwQixZQUFvRDtJQUVwRCxJQUFJLENBQUMsWUFBWTtRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ2hDLE1BQU0sSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xFLE1BQU0sT0FBTyxHQUFHLE9BQU8sWUFBWSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDO0lBQ2pGLE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsSUFBSSxLQUFLLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMvRSxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsUUFBUSxDQUFDLEdBQW9CO0lBQzNDLE1BQU0sU0FBUyxH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R0FBRyxNQUFNLFdBQVcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZGLElBQUksTUFBTSxLQUFLLE1BQU0sSUFBSSxjQUFjLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM3QyxHQUFHO2lCQUNBLE1BQU0sQ0FBQyxHQUFHLENBQUM7aUJBQ1gsSUFBSSxDQUFDLE1BQU0sQ0FBQztpQkFDWixJQUFJLENBQ0gsYUFBYSxDQUFDO2dCQUNaLFNBQVMsRUFBRSxTQUFTLElBQUksZ0JBQWdCO2dCQUN4QyxRQUFRLEVBQUUsZUFBZSxDQUFDLEdBQUcsQ0FBQzthQUMvQixDQUFDLENBQ0gsQ0FBQztRQUNOLENBQUM7YUFBTSxJQUFJLE1BQU0sS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUM3QixHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzlDLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxFQUFFLENBQUM7UUFDVCxDQUFDO0lBQ0gsQ0FBQyxDQUFtQixDQUFDO0lBRXJCLGFBQWEsQ0FBQyxHQUFHLEVBQUUsY0FBYyxDQUFDLENBQUM7QUFDckMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhlIHR1bm5lbCdzIGluLWFwcCBBVVRIIEdBVEUgLSBFeHByZXNzIG1pZGRsZXdhcmUgKyBsb2dpbiByb3V0ZXMgdGhlXG4gKiB7QGxpbmsgQXV0aEdhdGVQbHVnaW59IHJlZ2lzdGVycyBvbiB0aGUgYXBwJ3MgT1dOIHNlcnZlciB2aWEgYHRoaXMuY29udGV4dGAuXG4gKlxuICogVGhlIGdhdGUgaXMgTUlERExFV0FSRSwgbm90IGEgcmV2ZXJzZSBwcm94eSAtIHRoZSBhcHAgaXMgdGhlIHByb2Nlc3MsIHNvIHRoZXJlIGlzXG4gKiBub3RoaW5nIHRvIGZvcndhcmQgdG8uIEl0IGVpdGhlciBzaG9ydC1jaXJjdWl0cyAoNDAxLCBvciBhbnN3ZXJzIHRoZSBvcGVuIGxvZ2luXG4gKiByb3V0ZXMpIG9yIGNhbGxzIGBuZXh0KClgIHRvIGxldCB0aGUgYXBwJ3MgcmVhbCBoYW5kbGVycyBydW4uIEl0IGlzIHRoZVxuICogXCJzdGFuZHMgaW4gZm9yIEFwcEtpdCBhdXRoXCIgcGF0aDpcbiAqIGEgcG9ydHIgY2FsbGVyIGF1dGhlbnRpY2F0ZXMgd2l0aCBCZXR0ZXIgQXV0aCBPVFAgb3IgYSBwYXNza2V5LCBhbmQgb25cbiAqIHN1Y2Nlc3MgdGhlIGdhdGUgaW5qZWN0cyB0aGUgaWRlbnRpdHkgaGVhZGVycyBBcHBLaXQgcmVhZHMuXG4gKlxuICogV0hJQ0ggVFJBRkZJQyBJUyBHQVRFRCAtIHRoZSBgSG9zdGAgaGVhZGVyLCBub3QgdGhlIHNvY2tldC4gcG9ydHIncyBjbGllbnRcbiAqIGZvcndhcmRzIHdpdGggR28ncyBgaHR0cHV0aWwuTmV3U2luZ2xlSG9zdFJldmVyc2VQcm94eWAgYW5kIGEgYERpcmVjdG9yYCB0aGF0XG4gKiBQUkVTRVJWRVMgdGhlIG9yaWdpbmFsIGBIb3N0YCwgc28gdHVubmVsIHJlcXVlc3RzIGFycml2ZSB3aXRoXG4gKiBgSG9zdDogPHN1YmRvbWFpbj4uPHNlcnZlcj5gICh0aGUgcHVibGljIGRvbWFpbikuIEEgbG9jYWwgcHJvY2VzcyBoaXR0aW5nIHRoZVxuICogYXBwIGRpcmVjdGx5IHNlbmRzIGBIb3N0OiAxMjcuMC4wLjE6PHBvcnQ+YCAvIGBsb2NhbGhvc3RgLiBTbyBPTkxZIHJlcXVlc3RzIHdob3NlXG4gKiBgSG9zdGAgbWF0Y2hlcyB0aGUgY29uZmlndXJlZCBwdWJsaWMgZG9tYWluIGFyZSBnYXRlZDsgdGhlIHBsYXRmb3JtIGZyb250IGRvb3JcbiAqIGFuZCBhbnkgb3RoZXIgbG9jYWwgY2xpZW50IHBhc3MgdGhyb3VnaCB1bnRvdWNoZWQuIFRoZXJlIGlzIG5vIHBvcnRyLWluamVjdGVkXG4gKiBpZGVudGlmeWluZyBoZWFkZXIgYW5kIG5vIFRDUC9zb3VyY2UtSVAgc2lnbmFsIHRvIHVzZSBpbnN0ZWFkICh0aGUgY2xpZW50IGRpYWxzXG4gKiB0aGUgdGFyZ2V0IG92ZXIgcGxhaW4gbG9vcGJhY2spLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgdHlwZSB7IEluY29taW5nTWVzc2FnZSB9IGZyb20gXCJub2RlOmh0dHBcIjtcbmltcG9ydCB7IGxvZywgdG9rZW4gfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHR5cGUgeyBSZXF1ZXN0SGFuZGxlciwgUmVzcG9uc2UgfSBmcm9tIFwiZXhwcmVzc1wiO1xuaW1wb3J0IHsgdG9IZWFkZXJQb2xpY3ksIHR5cGUgSGVhZGVyUG9saWN5IH0gZnJvbSBcIi4vaGVhZGVycy50c1wiO1xuaW1wb3J0IHsgbG9naW5QYWdlSHRtbCB9IGZyb20gXCIuL2xvZ2luLXBhZ2UudHNcIjtcbmltcG9ydCB0eXBlIHsgQXV0aEdhdGVBcGkgfSBmcm9tIFwiLi9wbHVnaW4udHNcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcInR1bm5lbDpnYXRlXCIpO1xuXG50eXBlIFdlYlJlcXVlc3RJbnB1dCA9IEluY29taW5nTWVzc2FnZSAmIHtcbiAgYm9keT86IHVua25vd247XG4gIG9yaWdpbmFsVXJsPzogc3RyaW5nO1xufTtcblxuZXhwb3J0IGNvbnN0IEFVVEhfUFJFRklYID0gXCIvYXBpL2VtYWlsL2F1dGhcIjtcblxuLyoqIE9wdGlvbnMgZm9yIHtAbGluayBtb3VudEdhdGV9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBHYXRlT3B0aW9ucyB7XG4gIC8qKiBUaGUgaW4tcHJvY2VzcyBnYXRlIEFQSSAoc2Vzc2lvbi9yZXF1ZXN0L3ZlcmlmeS9zdGF0dXMpLiAqL1xuICBnYXRlOiBBdXRoR2F0ZUFwaTtcbiAgLyoqXG4gICAqIFRoZSBwdWJsaWMgYDxzdWJkb21haW4+LjxzZXJ2ZXI+YCB0aGF0IGlkZW50aWZpZXMgcG9ydHIgdHJhZmZpYyBieSBgSG9zdGAuXG4gICAqIFdoZW4gYWJzZW50LCBubyByZXF1ZXN0IGlzIGV2ZXIgY2xhc3NpZmllZCBhcyB0dW5uZWwgdHJhZmZpYyBhbmQgdGhlIGdhdGUgaXNcbiAgICogaW5lcnQgKGV2ZXJ5dGhpbmcgcGFzc2VzIHRocm91Z2gpIC0gYSB0dW5uZWwgd2l0aCBubyBwdWJsaWMgZG9tYWluIGdhdGVzXG4gICAqIG5vdGhpbmcuXG4gICAqL1xuICBwdWJsaWNEb21haW4/OiBzdHJpbmcgfCByZWFkb25seSBzdHJpbmdbXTtcbiAgLyoqXG4gICAqIEV4dHJhIGB4LWAgcmVxdWVzdCBoZWFkZXJzIHR1bm5lbCB0cmFmZmljIG1heSBmb3J3YXJkICh1bmlvbmVkIHdpdGggdGhlXG4gICAqIGJ1aWx0LWluIGFsbG93LWxpc3QpLiBFdmVyeSBvdGhlciBgeC1gIGhlYWRlciBpcyBzdHJpcHBlZCBmcm9tIHR1bm5lbCB0cmFmZmljLlxuICAgKi9cbiAgZm9yd2FyZEhlYWRlcnM/OiByZWFkb25seSBzdHJpbmdbXTtcbiAgLyoqXG4gICAqIFBhdGggcHJlZml4ZXMgdGhhdCByZXF1aXJlIGEgdmFsaWQgc2Vzc2lvbiwgYmV5b25kIHRoZSBidWlsdC1pbiBgL2FwaS9gLlxuICAgKiBUaGUgZGVmYXVsdCBnYXRpbmcgbW9kZWwgYXNzdW1lcyBhIHNlbGYtcHJvdGVjdGluZyBTUEE6IHN0YXRpYyBsb2FkcyBmcmVlbHlcbiAgICogc28gdGhlIGFwcCBjYW4gcmVuZGVyLCBhbmQgb25seSBgL2FwaS8qYCBpcyBnYXRlZC4gQW4gYXBwIHdob3NlIHByaXZpbGVnZWRcbiAgICogc3VyZmFjZSBpcyBOT1QgdW5kZXIgYC9hcGkvYCAoZS5nLiBhIFdlYlNvY2tldCBhdCBgL3dzYCkgbGlzdHMgdGhvc2UgcHJlZml4ZXNcbiAgICogaGVyZSBzbyB0aGV5IGFyZSBnYXRlZCB0b28uIExvZ2luIHJvdXRlcyAoYEFVVEhfUFJFRklYYCkgYXJlIGFsd2F5cyBvcGVuLlxuICAgKi9cbiAgZ2F0ZVBhdGhzPzogcmVhZG9ubHkgc3RyaW5nW107XG4gIC8qKiBQcm9kdWN0IG5hbWUgZGlzcGxheWVkIGJ5IHRoZSBob3N0ZWQgbG9naW4gcGFnZS4gKi9cbiAgYnJhbmROYW1lPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRydWUgd2hlbiB0aGUgcmVxdWVzdCdzIGBIb3N0YCBpcyBvbmUgb2YgdGhlIHR1bm5lbCdzIHB1YmxpYyBkb21haW5zIC0gaS5lLiBpdFxuICogY2FtZSBpbiBvdmVyIFBvcnRyIG9yIEZSUC4gQ2FzZS1pbnNlbnNpdGl2ZTsgdGhlIG9wdGlvbmFsIGA6cG9ydGAgaXMgaWdub3JlZC5cbiAqIFdoZW4gbm8gcHVibGljIGRvbWFpbiBpcyBjb25maWd1cmVkLCBub3RoaW5nIGlzIHR1bm5lbCB0cmFmZmljLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNUdW5uZWxIb3N0KFxuICByZXE6IEluY29taW5nTWVzc2FnZSxcbiAgcHVibGljRG9tYWluOiBzdHJpbmcgfCByZWFkb25seSBzdHJpbmdbXSB8IHVuZGVmaW5lZCxcbik6IGJvb2xlYW4ge1xuICBpZiAoIXB1YmxpY0RvbWFpbikgcmV0dXJuIGZhbHNlO1xuICBjb25zdCBob3N0ID0gKHJlcS5oZWFkZXJzLmhvc3QgPz8gXCJcIikudG9Mb3dlckNhc2UoKS5zcGxpdChcIjpcIilbMF07XG4gIGNvbnN0IGRvbWFpbnMgPSB0eXBlb2YgcHVibGljRG9tYWluID09PSBcInN0cmluZ1wiID8gW3B1YmxpY0RvbWFpbl0gOiBwdWJsaWNEb21haW47XG4gIHJldHVybiBkb21haW5zLnNvbWUoKGRvbWFpbikgPT4gaG9zdCA9PT0gZG9tYWluLnRvTG93ZXJDYXNlKCkuc3BsaXQoXCI6XCIpWzBdKTtcbn1cblxuLyoqXG4gKiBDbGllbnQgSVAgZm9yIHJhdGUtbGltaXRpbmc6IHRoZSBSSUdIVE1PU1QgYHgtZm9yd2FyZGVkLWZvcmAgZW50cnkgKHRoZSB2YWx1ZVxuICogdGhlIG5lYXJlc3QgdHJ1c3RlZCBob3AgLSBwb3J0ciAtIHdyb3RlKSwgZWxzZSB0aGUgc29ja2V0IGFkZHJlc3MuIFJlYWRpbmcgdGhlXG4gKiByaWdodG1vc3QsIG5vdCB0aGUgbGVmdG1vc3QsIHN0b3BzIGEgY2FsbGVyIG1pbnRpbmcgYSBmcmVzaCByYXRlLWxpbWl0IGJ1Y2tldCBieVxuICogdmFyeWluZyB0aGUgaGVhZGVyLiBDYWxsZWQgYmVmb3JlIHtAbGluayBzdHJpcEhlYWRlcnN9LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xpZW50SXAocmVxOiBJbmNvbWluZ01lc3NhZ2UpOiBzdHJpbmcge1xuICBjb25zdCBmb3J3YXJkZWQgPSByZXEuaGVhZGVyc1tcIngtZm9yd2FyZGVkLWZvclwiXTtcbiAgY29uc3QgY2hhaW4gPSAoQXJyYXkuaXNBcnJheShmb3J3YXJkZWQpID8gZm9yd2FyZGVkLmpvaW4oXCIsXCIpIDogKGZvcndhcmRlZCA/PyBcIlwiKSlcbiAgICAuc3BsaXQoXCIsXCIpXG4gICAgLm1hcCgoZW50cnkpID0+IGVudHJ5LnRyaW0oKSlcbiAgICAuZmlsdGVyKEJvb2xlYW4pO1xuICByZXR1cm4gY2hhaW4uYXQoLTEpID8/IHJlcS5zb2NrZXQucmVtb3RlQWRkcmVzcyA/PyBcInVua25vd25cIjtcbn1cblxuLyoqXG4gKiBSZW1vdmUgdGhlIGdhdGUncyBzZXNzaW9uIGNvb2tpZSBmcm9tIHRoZSBgQ29va2llYCBoZWFkZXIgYmVmb3JlIHRoZSBhcHAnc1xuICogaGFuZGxlcnMgcnVuLCBzbyB0aGUgYXBwIG5ldmVyIHNlZXMgYGRieF9hdXRoYCAoaXQgaXMgdGhlIGdhdGUncyBjb25jZXJuKS5cbiAqIFByZXNlcnZlcyBvdGhlciBjb29raWVzOyBkZWxldGVzIHRoZSBoZWFkZXIgd2hlbiBpdCBiZWNvbWVzIGVtcHR5LlxuICovXG5mdW5jdGlvbiBzdHJpcFNlc3Npb25Db29raWUocmVxOiBJbmNvbWluZ01lc3NhZ2UpOiB2b2lkIHtcbiAgY29uc3QgcmF3ID0gcmVxLmhlYWRlcnMuY29va2llO1xuICBpZiAoIXJhdykgcmV0dXJuO1xuICBjb25zdCBrZXB0ID0gcmF3XG4gICAgLnNwbGl0KFwiO1wiKVxuICAgIC5tYXAoKGMpID0+IGMudHJpbSgpKVxuICAgIC5maWx0ZXIoKGMpID0+IGMgJiYgIWMuc3RhcnRzV2l0aChcImRieC10b29scy1hdXRoPVwiKSAmJiAhYy5zdGFydHNXaXRoKFwiZGJ4LXRvb2xzLXBhc3NrZXk9XCIpKTtcbiAgaWYgKGtlcHQubGVuZ3RoKSByZXEuaGVhZGVycy5jb29raWUgPSBrZXB0LmpvaW4oXCI7IFwiKTtcbiAgZWxzZSBkZWxldGUgcmVxLmhlYWRlcnMuY29va2llO1xufVxuXG4vKipcbiAqIFByZXNlbnQgYSBwYXNzd29yZGxlc3MtYXV0aGVudGljYXRlZCBjYWxsZXIgdG8gdGhlIGFwcCB0aGUgU0FNRSB3YXkgYSBwbGF0Zm9ybSBmcm9udFxuICogZG9vciBkb2VzOiBzZXQgdGhlIGZyb250LWRvb3IgaWRlbnRpdHkgaGVhZGVycyB0byB0aGUgdmVyaWZpZWQgYWRkcmVzcyAoQXBwS2l0XG4gKiByZWFkcyB7QGxpbmsgdG9rZW4uVVNFUl9JRF9IRUFERVJ9IGZvciB0aGUgT0JPIHVzZXIgaWQpLCBzbyB0aGUgYXBwIG5lZWRzIG5vXG4gKiBnYXRlLXNwZWNpZmljIGNvZGUgcGF0aC5cbiAqXG4gKiBXaGF0IHRoZSBnYXRlIENBTk5PVCBzZXQgaXMge0BsaW5rIHRva2VuLkFDQ0VTU19UT0tFTl9IRUFERVJ9OiBhbiBhdXRoIHNlc3Npb25cbiAqIHByb3ZlcyBhbiBlbWFpbCwgbm90IHBvc3Nlc3Npb24gb2YgYSBEYXRhYnJpY2tzIGNyZWRlbnRpYWwuIEl0cyBhYnNlbmNlIGlzIHdoYXRcbiAqIGBAZGJ4LXRvb2xzL2FwcGtpdGAncyBgaWRlbnRpdHk6IFwiYXV0b1wiYCBkZXRlY3RzLCBzbyBhIGdhdGVkIHJlcXVlc3QgcnVucyBhcyB0aGVcbiAqIGFwcCBzZXJ2aWNlIHByaW5jaXBhbCBpbnN0ZWFkIG9mIHRocm93aW5nLlxuICovXG5mdW5jdGlvbiBpbmplY3RJZGVudGl0eShyZXE6IEluY29taW5nTWVzc2FnZSwgZW1haWw6IHN0cmluZyk6IHZvaWQge1xuICByZXEuaGVhZGVyc1t0b2tlbi5VU0VSX0lEX0hFQURFUl0gPSBlbWFpbDtcbiAgcmVxLmhlYWRlcnNbdG9rZW4uVVNFUl9FTUFJTF9IRUFERVJdID0gZW1haWw7XG59XG5cbi8qKiBSZWFkIHRoZSByYXcgcmVxdWVzdCBib2R5IGFzIHRleHQgKEFwcEtpdCBwYXJzZXMgSlNPTiwgYnV0IHRoZSBnYXRlIHJvdXRlc1xuICogYXJlIG1vdW50ZWQgYmVmb3JlIHRoYXQgcnVucyBmb3IgdHVubmVsIHRyYWZmaWMsIHNvIHJlYWQgZGVmZW5zaXZlbHkpLiAqL1xuZnVuY3Rpb24gcmVhZEJvZHkocmVxOiBXZWJSZXF1ZXN0SW5wdXQpOiBQcm9taXNlPHN0cmluZz4ge1xuICAvLyBBcHBLaXQncyBqc29uIGJvZHktcGFyc2VyIG1heSBoYXZlIGFscmVhZHkgcG9wdWxhdGVkIHJlcS5ib2R5OyBwcmVmZXIgaXQuXG4gIGlmIChyZXEuYm9keSAhPT0gdW5kZWZpbmVkICYmIHJlcS5ib2R5ICE9PSBudWxsKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0eXBlb2YgcmVxLmJvZHkgPT09IFwic3RyaW5nXCIgPyByZXEuYm9keSA6IEpTT04uc3RyaW5naWZ5KHJlcS5ib2R5KSk7XG4gIH1cbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgbGV0IGRhdGEgPSBcIlwiO1xuICAgIHJlcS5vbihcImRhdGFcIiwgKGNodW5rKSA9PiAoZGF0YSArPSBjaHVuaykpO1xuICAgIHJlcS5vbihcImVuZFwiLCAoKSA9PiByZXNvbHZlKGRhdGEpKTtcbiAgICByZXEub24oXCJlcnJvclwiLCAoKSA9PiByZXNvbHZlKGRhdGEpKTtcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3ZWJIZWFkZXJzKHJlcTogSW5jb21pbmdNZXNzYWdlKTogSGVhZGVycyB7XG4gIGNvbnN0IGhlYWRlcnMgPSBuZXcgSGVhZGVycygpO1xuICBmb3IgKGNvbnN0IFtuYW1lLCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMocmVxLmhlYWRlcnMpKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgdmFsdWUpIGhlYWRlcnMuYXBwZW5kKG5hbWUsIGl0ZW0pO1xuICAgIH0gZWxzZSBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaGVhZGVycy5zZXQobmFtZSwgdmFsdWUpO1xuICAgIH1cbiAgfVxuICBoZWFkZXJzLnNldChcIngtcmVhbC1pcFwiLCBjbGllbnRJcChyZXEpKTtcbiAgcmV0dXJuIGhlYWRlcnM7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3ZWJSZXF1ZXN0KHJlcTogV2ViUmVxdWVzdElucHV0KTogUHJvbWlzZTxnbG9iYWxUaGlzLlJlcXVlc3Q+IHtcbiAgY29uc3QgaG9zdCA9IHJlcS5oZWFkZXJzLmhvc3QgPz8gXCJsb2NhbGhvc3RcIjtcbiAgY29uc3QgaG9zdG5hbWUgPSBob3N0LnNwbGl0KFwiOlwiKVswXT8udG9Mb3dlckNhc2UoKTtcbiAgY29uc3QgcHJvdG9jb2wgPSBob3N0bmFtZSA9PT0gXCJsb2NhbGhvc3RcIiB8fCBob3N0bmFtZSA9PT0gXCIxMjcuMC4wLjFcIiA/IFwiaHR0cFwiIDogXCJodHRwc1wiO1xuICBjb25zdCBtZXRob2QgPSAocmVxLm1ldGhvZCA/PyBcIkdFVFwiKS50b1VwcGVyQ2FzZSgpO1xuICBjb25zdCBib2R5ID0gbWV0aG9kID09PSBcIkdFVFwiIHx8IG1ldGhvZCA9PT0gXCJIRUFEXCIgPyB1bmRlZmluZWQgOiBhd2FpdCByZWFkQm9keShyZXEpO1xuICByZXR1cm4gbmV3IGdsb2JhbFRoaXMuUmVxdWVzdChgJHtwcm90b2NvbH06Ly8ke2hvc3R9JHtyZXEub3JpZ2luYWxVcmwgfHwgcmVxLnVybH1gLCB7XG4gICAgbWV0aG9kLFxuICAgIGhlYWRlcnM6IHdlYkhlYWRlcnMocmVxKSxcbiAgICAuLi4oYm9keSA/IHsgYm9keSB9IDoge30pLFxuICB9KTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlbmRXZWJSZXNwb25zZShyZXM6IFJlc3BvbnNlLCByZXNwb25zZTogZ2xvYmFsVGhpcy5SZXNwb25zZSk6IFByb21pc2U8dm9pZD4ge1xuICBmb3IgKGNvbnN0IFtuYW1lLCB2YWx1ZV0gb2YgcmVzcG9uc2UuaGVhZGVycy5lbnRyaWVzKCkpIHtcbiAgICBpZiAobmFtZS50b0xvd2VyQ2FzZSgpICE9PSBcInNldC1jb29raWVcIikgcmVzLnNldEhlYWRlcihuYW1lLCB2YWx1ZSk7XG4gIH1cbiAgY29uc3QgY29va2llcyA9IHJlc3BvbnNlLmhlYWRlcnMuZ2V0U2V0Q29va2llKCk7XG4gIGlmIChjb29raWVzLmxlbmd0aCkgcmVzLnNldEhlYWRlcihcInNldC1jb29raWVcIiwgY29va2llcyk7XG4gIGNvbnN0IGJvZHkgPSBCdWZmZXIuZnJvbShhd2FpdCByZXNwb25zZS5hcnJheUJ1ZmZlcigpKTtcbiAgcmVzLnN0YXR1cyhyZXNwb25zZS5zdGF0dXMpLnNlbmQoYm9keSk7XG59XG5cbi8qKlxuICogV2hhdCB0aGUgY2FsbGVyIHNob3VsZCBkbyB3aXRoIGEgcmVxdWVzdCwgZnJvbSB7QGxpbmsgZ2F0ZVJlcXVlc3R9LlxuICpcbiAqICAgLSBgcGFzc2AgLSBub3QgdHVubmVsIHRyYWZmaWMsIG9yIGFuIG9wZW4gbG9naW4gcm91dGUuIEZvcndhcmQgdW50b3VjaGVkLlxuICogICAtIGBhbGxvd2AgLSB0dW5uZWwgdHJhZmZpYyB0aGF0IGlzIGF1dGhvcml6ZWQuIFRoZSByZXF1ZXN0J3MgaGVhZGVycyBoYXZlXG4gKiAgICAgQUxSRUFEWSBiZWVuIHJld3JpdHRlbiAocG9saWN5IGFwcGxpZWQsIGlkZW50aXR5IGluamVjdGVkLCBzZXNzaW9uIGNvb2tpZVxuICogICAgIHN0cmlwcGVkKSwgc28gZm9yd2FyZCBpdCBhcyBpdCBub3cgc3RhbmRzLlxuICogICAtIGBkZW55YCAtIHR1bm5lbCB0cmFmZmljIHdpdGggbm8gdmFsaWQgc2Vzc2lvbi4gQW5zd2VyIGA0MDFgIHdpdGhcbiAqICAgICB7QGxpbmsgQVVUSF9QUkVGSVh9IGFzIHRoZSBsb2dpbiBwYXRoLlxuICovXG5leHBvcnQgdHlwZSBHYXRlQWN0aW9uID0gXCJwYXNzXCIgfCBcImFsbG93XCIgfCBcImRlbnlcIjtcblxuLyoqXG4gKiBUSEUgZ2F0aW5nIGRlY2lzaW9uLCBmb3Igb25lIHJlcXVlc3QsIGluZGVwZW5kZW50IG9mIGhvdyBpdCB3aWxsIGJlIGFuc3dlcmVkLlxuICpcbiAqIEJvdGggcGF0aHMgY2FsbCB0aGlzOiB0aGUgRXhwcmVzcyBtaWRkbGV3YXJlIGJlbG93ICh3aGVyZSB0aGUgYXBwIGlzIHRoZVxuICogcHJvY2VzcykgYW5kIGBAZGJ4LXRvb2xzL2NsaS10dW5uZWxgJ3MgcmV2ZXJzZSBwcm94eSAod2hlcmUgdGhlIGFwcCBpcyBhIGNoaWxkXG4gKiBwcm9jZXNzIG9uIGEgcHJpdmF0ZSBwb3J0KS4gQSBkaXZlcmdlbmNlIGJldHdlZW4gdGhlbSB3b3VsZCBiZSBhIHNlY3VyaXR5IGJ1Z1xuICogdGhlIHNlY29uZCBwYXRoIGNvdWxkIG5vdCBiZSB0ZXN0ZWQgaW50byBhZ3JlZW1lbnQgLSBvbmUgcGF0aCBmb3JnZXR0aW5nIHRvXG4gKiBzdHJpcCBgeC1mb3J3YXJkZWQtYWNjZXNzLXRva2VuYCBpcyBlbm91Z2ggLSBzbyB0aGUgZGVjaXNpb24sIHRoZSBoZWFkZXJcbiAqIHJld3JpdGluZywgYW5kIHRoZSBpZGVudGl0eSBpbmplY3Rpb24gbGl2ZSBoZXJlIG9uY2UgYW5kIHRoZSB0cmFuc3BvcnRzIG9ubHlcbiAqIGRpZmZlciBpbiBob3cgdGhleSBXUklURSB0aGUgb3V0Y29tZS5cbiAqXG4gKiBNdXRhdGVzIGByZXEuaGVhZGVyc2Agb24gdGhlIGBhbGxvd2AvYHBhc3NgLXdpdGgtY29va2llIHBhdGhzLCB3aGljaCBpcyBleGFjdGx5XG4gKiB3aGF0IGJvdGggY2FsbGVycyB3YW50OiBFeHByZXNzIGhhbmRzIHRoZSBzYW1lIG9iamVjdCB0byB0aGUgYXBwJ3MgaGFuZGxlcnMsIGFuZFxuICogdGhlIHByb3h5IGZvcndhcmRzIGl0IHVwc3RyZWFtLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2F0ZVJlcXVlc3QoXG4gIHJlcTogSW5jb21pbmdNZXNzYWdlLFxuICBvcHRpb25zOiBHYXRlT3B0aW9ucyAmIHsgaGVhZGVyUG9saWN5PzogSGVhZGVyUG9saWN5IH0sXG4pOiBQcm9taXNlPEdhdGVBY3Rpb24+IHtcbiAgY29uc3QgeyBnYXRlLCBwdWJsaWNEb21haW4gfSA9IG9wdGlvbnM7XG4gIC8vIE5vdCB0dW5uZWwgdHJhZmZpYyAocGxhdGZvcm0gZnJvbnQgZG9vciwgb3IgYW55IG90aGVyIGxvY2FsIGNhbGxlcik6IHRoZVxuICAvLyByZXF1ZXN0IGlzIGFscmVhZHkgYXV0aGVudGljYXRlZCwgb3IgaXMgbm90IG91cnMgdG8gZ2F0ZS5cbiAgaWYgKCFpc1R1bm5lbEhvc3QocmVxLCBwdWJsaWNEb21haW4pKSByZXR1cm4gXCJwYXNzXCI7XG5cbiAgY29uc3QgcGF0aCA9IChyZXEudXJsID8/IFwiL1wiKS5zcGxpdChcIj9cIilbMF0gPz8gXCIvXCI7XG4gIC8vIFRoZSBsb2dpbiBmbG93IGlzIG9wZW4gc28gdGhlIGJyb3dzZXIgY2FuIHJlbmRlciA8QXV0aEdhdGU+IGFuZCBzaWduIGluLlxuICBpZiAocGF0aC5zdGFydHNXaXRoKEFVVEhfUFJFRklYKSkgcmV0dXJuIFwicGFzc1wiO1xuXG4gIC8vIEFudGktc3Bvb2Y6IG9ubHkgdGhlIGdhdGUgbWF5IGFzc2VydCBpZGVudGl0eSBvbiB0dW5uZWwgdHJhZmZpYy5cbiAgY29uc3QgcG9saWN5ID0gb3B0aW9ucy5oZWFkZXJQb2xpY3kgPz8gdG9IZWFkZXJQb2xpY3kob3B0aW9ucy5mb3J3YXJkSGVhZGVycyk7XG4gIGNvbnN0IHJlbW92ZWQgPSBwb2xpY3kuYXBwbHkocmVxLmhlYWRlcnMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pO1xuICBpZiAocmVtb3ZlZC5sZW5ndGgpIGxvZ2dlci5kZWJ1ZyhcInN0cmlwcGVkIGluYm91bmQgaGVhZGVyc1wiLCB7IHJlbW92ZWQgfSk7XG5cbiAgY29uc3QgZ2F0ZVBhdGhzID0gb3B0aW9ucy5nYXRlUGF0aHMgPz8gW107XG4gIC8vIEEgcGF0aCBpcyBnYXRlZCBpZiBpdCBpcyB1bmRlciBgL2FwaS9gIG9yIGFueSBjYWxsZXItc3VwcGxpZWQgcHJlZml4IChlLmcuXG4gIC8vIGAvd3NgIGZvciBhIFdlYlNvY2tldCBhcHApLlxuICBjb25zdCBnYXRlZCA9XG4gICAgcGF0aC5zdGFydHNXaXRoKFwiL2FwaS9cIikgfHxcbiAgICBnYXRlUGF0aHMuc29tZSgocHJlZml4KSA9PiBwYXRoID09PSBwcmVmaXggfHwgcGF0aC5zdGFydHNXaXRoKGAke3ByZWZpeH0vYCkpO1xuXG4gIC8vIEFwcC1nYXRpbmcgbW9kZTogd2hlbiBgZ2F0ZVBhdGhzYCBpcyBzZXQgdGhlIGNhbGxlciBpcyBmcm9udGluZyBhIHdob2xlIGFwcFxuICAvLyAobm90IGEgc2VsZi1wcm90ZWN0aW5nIFNQQSksIHNvIGFuIHVuYXV0aGVudGljYXRlZCB0b3AtbGV2ZWwgYnJvd3NlclxuICAvLyBuYXZpZ2F0aW9uIGlzIGRlbmllZCB0b28g4oCUIHRoZSB0cmFuc3BvcnQgYW5zd2VycyBpdCB3aXRoIHRoZSBob3N0ZWQgbG9naW5cbiAgLy8gcGFnZSwgcHV0dGluZyBzaWduLWluIGluIGZyb250IG9mIHRoZSBhcHAgaW5zdGVhZCBvZiBsb2FkaW5nIGl0cyBzaGVsbCB3aXRoXG4gIC8vIGEgZGVhZCBnYXRlZCByZXF1ZXN0LiBOb24tbmF2aWdhdGlvbiBzdGF0aWMgKGFzc2V0cykgc3RpbGwgbG9hZHMgZnJlZWx5IHNvXG4gIC8vIHRoZSBsb2dpbiBwYWdlIGFuZCBhcHAgY2FuIHJlbmRlci5cbiAgY29uc3QgYXBwR2F0aW5nID0gZ2F0ZVBhdGhzLmxlbmd0aCA+IDA7XG4gIGNvbnN0IG11c3RBdXRoID0gZ2F0ZWQgfHwgKGFwcEdhdGluZyAmJiB3YW50c0xvZ2luUGFnZShyZXEpKTtcbiAgaWYgKCFtdXN0QXV0aCkge1xuICAgIHN0cmlwU2Vzc2lvbkNvb2tpZShyZXEpO1xuICAgIHJldHVybiBcInBhc3NcIjtcbiAgfVxuXG4gIC8vIEEgZ2F0ZWQgcmVxdWVzdCBuZWVkcyBhIHZhbGlkIEJldHRlciBBdXRoIHNlc3Npb24uXG4gIGNvbnN0IGVtYWlsID0gYXdhaXQgZ2F0ZS5zZXNzaW9uKHdlYkhlYWRlcnMocmVxKSk7XG4gIGlmICghZW1haWwpIHJldHVybiBcImRlbnlcIjtcbiAgaW5qZWN0SWRlbnRpdHkocmVxLCBlbWFpbCk7XG4gIHN0cmlwU2Vzc2lvbkNvb2tpZShyZXEpO1xuICByZXR1cm4gXCJhbGxvd1wiO1xufVxuXG4vKiogVGhlIGJvZHkgb2YgYSBgZGVueWAsIHNoYXJlZCBzbyBib3RoIHBhdGhzIGFuc3dlciBhIDQwMSBpZGVudGljYWxseS4gKi9cbmV4cG9ydCBjb25zdCBVTkFVVEhPUklaRURfQk9EWSA9IHtcbiAgZXJyb3I6IFwiYXV0aGVudGljYXRpb24gcmVxdWlyZWRcIixcbiAgbG9naW5QYXRoOiBBVVRIX1BSRUZJWCxcbn0gYXMgY29uc3Q7XG5cbi8qKiBSZXN0cmljdCBhIHBvc3QtbG9naW4gZGVzdGluYXRpb24gdG8gb25lIHNhbWUtb3JpZ2luIGFwcGxpY2F0aW9uIHBhdGguICovXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplUmV0dXJuVG8odmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gIGNvbnN0IGNhbmRpZGF0ZSA9IHZhbHVlPy50cmltKCk7XG4gIGlmICghY2FuZGlkYXRlPy5zdGFydHNXaXRoKFwiL1wiKSB8fCBjYW5kaWRhdGUuc3RhcnRzV2l0aChcIi8vXCIpIHx8IGNhbmRpZGF0ZS5pbmNsdWRlcyhcIlxcXFxcIikpIHtcbiAgICByZXR1cm4gXCIvXCI7XG4gIH1cbiAgY29uc3QgcGFyc2VkID0gbmV3IFVSTChjYW5kaWRhdGUsIFwiaHR0cDovL2FwcC5sb2NhbFwiKTtcbiAgcmV0dXJuIGAke3BhcnNlZC5wYXRobmFtZX0ke3BhcnNlZC5zZWFyY2h9JHtwYXJzZWQuaGFzaH1gO1xufVxuXG4vKiogUmVzb2x2ZSB0aGUgcGFnZSBhIGJyb3dzZXIgc2hvdWxkIHJldHVybiB0byBhZnRlciB0dW5uZWwgYXV0aGVudGljYXRpb24uICovXG5leHBvcnQgZnVuY3Rpb24gcmVxdWVzdFJldHVyblRvKHJlcTogSW5jb21pbmdNZXNzYWdlKTogc3RyaW5nIHtcbiAgaWYgKHdhbnRzTG9naW5QYWdlKHJlcSkpIHtcbiAgICBjb25zdCBvcmlnaW5hbFVybCA9IChyZXEgYXMgSW5jb21pbmdNZXNzYWdlICYgeyBvcmlnaW5hbFVybD86IHN0cmluZyB9KS5vcmlnaW5hbFVybDtcbiAgICByZXR1cm4gbm9ybWFsaXplUmV0dXJuVG8ob3JpZ2luYWxVcmwgfHwgcmVxLnVybCk7XG4gIH1cbiAgY29uc3QgcmVmZXJlciA9IFN0cmluZyhyZXEuaGVhZGVycy5yZWZlcmVyID8/IFwiXCIpLnRyaW0oKTtcbiAgaWYgKCFyZWZlcmVyKSByZXR1cm4gXCIvXCI7XG4gIHRyeSB7XG4gICAgY29uc3QgcGFyc2VkID0gbmV3IFVSTChyZWZlcmVyKTtcbiAgICBjb25zdCBob3N0ID0gU3RyaW5nKHJlcS5oZWFkZXJzLmhvc3QgPz8gXCJcIikudG9Mb3dlckNhc2UoKTtcbiAgICBpZiAocGFyc2VkLmhvc3QudG9Mb3dlckNhc2UoKSAhPT0gaG9zdCkgcmV0dXJuIFwiL1wiO1xuICAgIHJldHVybiBub3JtYWxpemVSZXR1cm5UbyhgJHtwYXJzZWQucGF0aG5hbWV9JHtwYXJzZWQuc2VhcmNofSR7cGFyc2VkLmhhc2h9YCk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBcIi9cIjtcbiAgfVxufVxuXG4vKiogQnVpbGQgdGhlIGhvc3RlZCBsb2dpbiBVUkwgd2l0aCBhIHZhbGlkYXRlZCBzYW1lLW9yaWdpbiByZXR1cm4gcGF0aC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsb2dpblBhdGgocmVxOiBJbmNvbWluZ01lc3NhZ2UpOiBzdHJpbmcge1xuICByZXR1cm4gYCR7QVVUSF9QUkVGSVh9P3JldHVyblRvPSR7ZW5jb2RlVVJJQ29tcG9uZW50KHJlcXVlc3RSZXR1cm5UbyhyZXEpKX1gO1xufVxuXG4vKiogQnVpbGQgYSBkZW5pZWQgSlNPTiByZXNwb25zZSB0aGF0IHByZXNlcnZlcyB0aGUgY2FsbGluZyBwYWdlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVuYXV0aG9yaXplZEJvZHkocmVxOiBJbmNvbWluZ01lc3NhZ2UpOiB7XG4gIGVycm9yOiB0eXBlb2YgVU5BVVRIT1JJWkVEX0JPRFkuZXJyb3I7XG4gIGxvZ2luUGF0aDogc3RyaW5nO1xufSB7XG4gIHJldHVybiB7IC4uLlVOQVVUSE9SSVpFRF9CT0RZLCBsb2dpblBhdGg6IGxvZ2luUGF0aChyZXEpIH07XG59XG5cbi8qKiBSZXR1cm4gdGhlIHZhbGlkYXRlZCBkZXN0aW5hdGlvbiBjYXJyaWVkIGJ5IGEgaG9zdGVkIGxvZ2luIFVSTC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsb2dpblJldHVyblRvKHJlcTogSW5jb21pbmdNZXNzYWdlKTogc3RyaW5nIHtcbiAgY29uc3QgdXJsID0gbmV3IFVSTChyZXEudXJsID8/IEFVVEhfUFJFRklYLCBcImh0dHA6Ly9hcHAubG9jYWxcIik7XG4gIHJldHVybiBub3JtYWxpemVSZXR1cm5Ubyh1cmwuc2VhcmNoUGFyYW1zLmdldChcInJldHVyblRvXCIpID8/IFwiL1wiKTtcbn1cblxuLyoqIFdoZXRoZXIgdGhpcyByZXF1ZXN0IGFza3MgZm9yIHRoZSBob3N0ZWQgbG9naW4gZG9jdW1lbnQgaXRzZWxmLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdhbnRzSG9zdGVkTG9naW4ocmVxOiBJbmNvbWluZ01lc3NhZ2UpOiBib29sZWFuIHtcbiAgY29uc3QgbWV0aG9kID0gKHJlcS5tZXRob2QgPz8gXCJHRVRcIikudG9VcHBlckNhc2UoKTtcbiAgaWYgKG1ldGhvZCAhPT0gXCJHRVRcIiAmJiBtZXRob2QgIT09IFwiSEVBRFwiKSByZXR1cm4gZmFsc2U7XG4gIGNvbnN0IHBhdGggPSAocmVxLnVybCA/PyBcIi9cIikuc3BsaXQoXCI/XCIpWzBdID8/IFwiL1wiO1xuICByZXR1cm4gcGF0aCA9PT0gQVVUSF9QUkVGSVggJiYgU3RyaW5nKHJlcS5oZWFkZXJzLmFjY2VwdCA/PyBcIlwiKS5pbmNsdWRlcyhcInRleHQvaHRtbFwiKTtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIGEgZGVuaWVkIHJlcXVlc3QgaXMgYSB0b3AtbGV2ZWwgQlJPV1NFUiBOQVZJR0FUSU9OIHRoYXQgc2hvdWxkIGJlXG4gKiBhbnN3ZXJlZCB3aXRoIHRoZSBob3N0ZWQgbG9naW4gcGFnZSByYXRoZXIgdGhhbiBhIDQwMS5cbiAqXG4gKiBBbiBhcHAgZnJvbnRlZCBieSB0aGUgZ2F0ZSAodmlhIGBnYXRlUGF0aHNgKSBtYXkgc2VydmUgaXRzIG93biBIVE1MIGZyb20gYW5cbiAqIHVuZ2F0ZWQgcGF0aCB3aGlsZSBpdHMgcHJpdmlsZWdlZCBzdXJmYWNlIChgL3dzYCwgYC9hcGlgKSBpcyBnYXRlZC4gQSBicm93c2VyXG4gKiBuYXZpZ2F0aW5nIHRvIGl0IHdvdWxkIG90aGVyd2lzZSBsb2FkIHRoZSBhcHAgc2hlbGwgYW5kIG9ubHkgc2VlIHRoZSBnYXRlZFxuICogcmVxdWVzdCBmYWlsLCB3aXRoIG5vIHdheSB0byBzaWduIGluLiBTZXJ2aW5nIHRoZSBsb2dpbiBwYWdlIG9uIHRoZSBuYXZpZ2F0aW9uXG4gKiBpdHNlbGYgcHV0cyBzaWduLWluIGluIGZyb250IG9mIHRoZSBhcHAuIEFwcGxpZXMgb25seSB0byBHRVQgcmVxdWVzdHMgdGhhdFxuICogYWNjZXB0IEhUTUwgYW5kIGFyZSBub3QgYXNraW5nIGZvciB0aGUgbG9naW4gQVBJIG9yIGFuIGFzc2V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gd2FudHNMb2dpblBhZ2UocmVxOiBJbmNvbWluZ01lc3NhZ2UpOiBib29sZWFuIHtcbiAgY29uc3QgbWV0aG9kID0gKHJlcS5tZXRob2QgPz8gXCJHRVRcIikudG9VcHBlckNhc2UoKTtcbiAgaWYgKG1ldGhvZCAhPT0gXCJHRVRcIiAmJiBtZXRob2QgIT09IFwiSEVBRFwiKSByZXR1cm4gZmFsc2U7XG4gIGNvbnN0IHBhdGggPSAocmVxLnVybCA/PyBcIi9cIikuc3BsaXQoXCI/XCIpWzBdID8/IFwiL1wiO1xuICBpZiAocGF0aC5zdGFydHNXaXRoKEFVVEhfUFJFRklYKSkgcmV0dXJuIGZhbHNlO1xuICBjb25zdCBhY2NlcHQgPSBTdHJpbmcocmVxLmhlYWRlcnMuYWNjZXB0ID8/IFwiXCIpO1xuICByZXR1cm4gYWNjZXB0LmluY2x1ZGVzKFwidGV4dC9odG1sXCIpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVyIHRoZSBsb2dpbiByb3V0ZXMgYW5kIHRoZSBnYXRpbmcgbWlkZGxld2FyZSBvbiB0aGUgYXBwJ3MgRXhwcmVzc1xuICogaW5zdGFuY2UuIENhbGxlZCBmcm9tIHtAbGluayBBdXRoR2F0ZVBsdWdpbn0gd2l0aCB0aGUgcm91dGVyIEFwcEtpdCBoYW5kc1xuICogYGluamVjdFJvdXRlc2AsIHBsdXMgYHRoaXMuY29udGV4dC5hZGRNaWRkbGV3YXJlYCBmb3IgdGhlIGdsb2JhbCBnYXRlLlxuICpcbiAqIGBhZGRSb3V0ZWAvYGFkZE1pZGRsZXdhcmVgIGFyZSB1c2VkICh2aWEgdGhlIHBhc3NlZCBjYWxsYmFja3MpIGJlY2F1c2UgdGhlIGxvZ2luXG4gKiByb3V0ZXMgbGl2ZSBhdCBhbiBBQlNPTFVURSBwYXRoIChgL2FwaS9lbWFpbC9hdXRoLypgLCB0aGUgY2xpZW50J3MgY29udHJhY3QpLFxuICogbm90IHVuZGVyIHRoZSBwbHVnaW4ncyBgL2FwaS9hdXRoR2F0ZWAgYmFzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1vdW50R2F0ZShcbiAgb3B0czogR2F0ZU9wdGlvbnMsXG4gIF9hZGRSb3V0ZTogKG1ldGhvZDogXCJnZXRcIiB8IFwicG9zdFwiLCBwYXRoOiBzdHJpbmcsIGhhbmRsZXI6IFJlcXVlc3RIYW5kbGVyKSA9PiB2b2lkLFxuICBhZGRNaWRkbGV3YXJlOiAocGF0aDogc3RyaW5nLCBoYW5kbGVyOiBSZXF1ZXN0SGFuZGxlcikgPT4gdm9pZCxcbik6IHZvaWQge1xuICBjb25zdCB7IGdhdGUsIHB1YmxpY0RvbWFpbiwgZm9yd2FyZEhlYWRlcnMsIGdhdGVQYXRocywgYnJhbmROYW1lIH0gPSBvcHRzO1xuICBjb25zdCBoZWFkZXJQb2xpY3kgPSB0b0hlYWRlclBvbGljeShmb3J3YXJkSGVhZGVycyk7XG4gIGxvZ2dlci5kZWJ1ZyhcImdhdGUgbW91bnRlZFwiLCB7IHB1YmxpY0RvbWFpbiwgZm9yd2FyZDogaGVhZGVyUG9saWN5LnBhdHRlcm5zLCBnYXRlUGF0aHMgfSk7XG5cbiAgLy8gQmV0dGVyIEF1dGggYW5kIHRoZSBjb21wYXRpYmlsaXR5IHJvdXRlcyBzaGFyZSBvbmUgZmV0Y2gtY29tcGF0aWJsZVxuICAvLyBoYW5kbGVyIGluIGJvdGggaG9zdGluZyBtb2Rlcy5cbiAgY29uc3QgYXV0aEhhbmRsZXIgPSAoYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgaWYgKCFpc1R1bm5lbEhvc3QocmVxLCBwdWJsaWNEb21haW4pKSB7XG4gICAgICBjb25zdCBwYXRoID0gKHJlcS51cmwgPz8gXCIvXCIpLnNwbGl0KFwiP1wiKVswXSA/PyBcIi9cIjtcbiAgICAgIGlmIChwYXRoLmVuZHNXaXRoKFwiL3N0YXR1c1wiKSkge1xuICAgICAgICByZXMuc3RhdHVzKDIwMCkuanNvbih7IGF1dGhlbnRpY2F0ZWQ6IGZhbHNlLCBlbmFibGVkOiBmYWxzZSwgcGFzc2tleXNFbmFibGVkOiBmYWxzZSB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlcy5zdGF0dXMoNDA0KS5qc29uKHsgZXJyb3I6IFwibm90IGZvdW5kXCIgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh3YW50c0hvc3RlZExvZ2luKHJlcSkpIHtcbiAgICAgIHJlc1xuICAgICAgICAuc3RhdHVzKDIwMClcbiAgICAgICAgLnR5cGUoXCJodG1sXCIpXG4gICAgICAgIC5zZW5kKFxuICAgICAgICAgIGxvZ2luUGFnZUh0bWwoe1xuICAgICAgICAgICAgYnJhbmROYW1lOiBicmFuZE5hbWUgPz8gXCJEYXRhYnJpY2tzIEFwcFwiLFxuICAgICAgICAgICAgcmV0dXJuVG86IGxvZ2luUmV0dXJuVG8ocmVxKSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgYXdhaXQgc2VuZFdlYlJlc3BvbnNlKHJlcywgYXdhaXQgZ2F0ZS5oYW5kbGVyKGF3YWl0IHdlYlJlcXVlc3QocmVxKSkpO1xuICB9KSBhcyBSZXF1ZXN0SGFuZGxlcjtcbiAgYWRkTWlkZGxld2FyZShBVVRIX1BSRUZJWCwgYXV0aEhhbmRsZXIpO1xuXG4gIC8vIC0tLSBUaGUgZ2F0ZSBtaWRkbGV3YXJlIChydW5zIGJlZm9yZSBzdGF0aWMgKyB0aGUgYXBwJ3MgL2FwaSBoYW5kbGVycykgLS0tXG5cbiAgY29uc3QgZ2F0ZU1pZGRsZXdhcmUgPSAoYXN5bmMgKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgY29uc3QgYWN0aW9uID0gYXdhaXQgZ2F0ZVJlcXVlc3QocmVxLCB7IGdhdGUsIHB1YmxpY0RvbWFpbiwgaGVhZGVyUG9saWN5LCBnYXRlUGF0aHMgfSk7XG4gICAgaWYgKGFjdGlvbiA9PT0gXCJkZW55XCIgJiYgd2FudHNMb2dpblBhZ2UocmVxKSkge1xuICAgICAgcmVzXG4gICAgICAgIC5zdGF0dXMoNDAxKVxuICAgICAgICAudHlwZShcImh0bWxcIilcbiAgICAgICAgLnNlbmQoXG4gICAgICAgICAgbG9naW5QYWdlSHRtbCh7XG4gICAgICAgICAgICBicmFuZE5hbWU6IGJyYW5kTmFtZSA/PyBcIkRhdGFicmlja3MgQXBwXCIsXG4gICAgICAgICAgICByZXR1cm5UbzogcmVxdWVzdFJldHVyblRvKHJlcSksXG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgfSBlbHNlIGlmIChhY3Rpb24gPT09IFwiZGVueVwiKSB7XG4gICAgICByZXMuc3RhdHVzKDQwMSkuanNvbih1bmF1dGhvcml6ZWRCb2R5KHJlcSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXh0KCk7XG4gICAgfVxuICB9KSBhcyBSZXF1ZXN0SGFuZGxlcjtcblxuICBhZGRNaWRkbGV3YXJlKFwiL1wiLCBnYXRlTWlkZGxld2FyZSk7XG59XG4iXX0=
@@ -16,6 +16,8 @@
16
16
  export interface LoginPageOptions {
17
17
  /** Product/brand name shown in the heading. */
18
18
  brandName: string;
19
+ /** Validated same-origin path loaded after authentication succeeds. */
20
+ returnTo: string;
19
21
  }
20
22
  /** The login page HTML for a `text/html` request to a gated path with no session. */
21
23
  export declare function loginPageHtml(options: LoginPageOptions): string;
@@ -17,9 +17,8 @@ import { AUTH_PREFIX } from "./gate.js";
17
17
  /** The login page HTML for a `text/html` request to a gated path with no session. */
18
18
  export function loginPageHtml(options) {
19
19
  const brand = escapeHtml(options.brandName);
20
- // AUTH_PREFIX is a fixed constant, not user input, but JSON-encode it so the
21
- // inlined script is always valid regardless of its value.
22
- const prefix = JSON.stringify(AUTH_PREFIX);
20
+ const prefix = jsonForInlineScript(AUTH_PREFIX);
21
+ const returnTo = jsonForInlineScript(options.returnTo);
23
22
  return `<!doctype html>
24
23
  <html lang="en">
25
24
  <head>
@@ -99,6 +98,11 @@ export function loginPageHtml(options) {
99
98
  <script>
100
99
  (function () {
101
100
  var PREFIX = ${prefix};
101
+ var RETURN_TO = ${returnTo};
102
+ // An in-place login can preserve browser-only hash state that never reached the server.
103
+ if (window.location.pathname !== PREFIX) {
104
+ RETURN_TO = window.location.pathname + window.location.search + window.location.hash;
105
+ }
102
106
  var emailForm = document.getElementById("email-form");
103
107
  var codeForm = document.getElementById("code-form");
104
108
  var emailInput = document.getElementById("email");
@@ -172,9 +176,7 @@ export function loginPageHtml(options) {
172
176
  });
173
177
  if (r.ok) {
174
178
  say("Signed in. Loading…");
175
- // The session cookie is set; reload so the now-authenticated request
176
- // reaches the app.
177
- window.location.reload();
179
+ window.location.replace(RETURN_TO);
178
180
  } else {
179
181
  say(errorText(r.data, "That code was not accepted. Try again."), true);
180
182
  submit.disabled = false;
@@ -207,4 +209,13 @@ const HTML_ESCAPES = {
207
209
  function escapeHtml(value) {
208
210
  return value.replace(/[&<>"']/g, (ch) => HTML_ESCAPES[ch] ?? ch);
209
211
  }
210
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9naW4tcGFnZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9sb2dpbi1wYWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBRUgsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQU94QyxxRkFBcUY7QUFDckYsTUFBTSxVQUFVLGFBQWEsQ0FBQyxPQUF5QjtJQUNyRCxNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzVDLDZFQUE2RTtJQUM3RSwwREFBMEQ7SUFDMUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUMzQyxPQUFPOzs7OzttQkFLVSxLQUFLOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzttRUErQzJDLEtBQUs7Ozs7O3FCQUtuRCxLQUFLOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7aUJBcUJULE1BQU07Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7UUFpR2YsQ0FBQztBQUNULENBQUM7QUFFRCxNQUFNLFlBQVksR0FBMkI7SUFDM0MsR0FBRyxFQUFFLE9BQU87SUFDWixHQUFHLEVBQUUsTUFBTTtJQUNYLEdBQUcsRUFBRSxNQUFNO0lBQ1gsR0FBRyxFQUFFLFFBQVE7SUFDYixHQUFHLEVBQUUsT0FBTztDQUNiLENBQUM7QUFFRixTQUFTLFVBQVUsQ0FBQyxLQUFhO0lBQy9CLE9BQU8sS0FBSyxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztBQUNuRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBBIHNlbGYtY29udGFpbmVkIEhUTUwgbG9naW4gcGFnZSB0aGUgdHVubmVsIHNlcnZlcyBpbiBmcm9udCBvZiBhbiBhcHAgdGhhdFxuICogZG9lcyBub3QgZW1iZWQgdGhlIGA8QXV0aEdhdGU+YCBSZWFjdCBjb21wb25lbnQgKGUuZy4gYSBXZWJTb2NrZXQgYXBwIGZyb250ZWRcbiAqIGJ5IHRoZSBDTEkgcHJveHkpLlxuICpcbiAqIEl0IHNwZWFrcyB0aGUgc2FtZSBjb21wYXRpYmlsaXR5IGVuZHBvaW50cyB1bmRlciB7QGxpbmsgQVVUSF9QUkVGSVh9IHRoYXQgdGhlXG4gKiBSZWFjdCBjbGllbnQgdXNlcyDigJQgYFBPU1QgL3JlcXVlc3RgIHRvIGVtYWlsIGEgY29kZSwgYFBPU1QgL3ZlcmlmeWAgdG9cbiAqIGV4Y2hhbmdlIGl0IGZvciB0aGUgYGRieC10b29scy1hdXRoYCBzZXNzaW9uIGNvb2tpZSDigJQgd2l0aCBwbGFpbiBgZmV0Y2hgLCBub1xuICogYnVpbGQgc3RlcCBhbmQgbm8gZGVwZW5kZW5jeS4gUGFzc2tleXMgYXJlIGludGVudGlvbmFsbHkgb21pdHRlZDogdGhlIFdlYkF1dGhuXG4gKiBjZXJlbW9ueSBuZWVkcyB0aGUgYmV0dGVyLWF1dGggY2xpZW50IGxpYnJhcnksIHNvIHBhc3NrZXkgZW5yb2xsbWVudCBoYXBwZW5zXG4gKiBpbnNpZGUgdGhlIGFwcCBhZnRlciB0aGlzIGVtYWlsLU9UUCBzaWduLWluLiBPbiBzdWNjZXNzIHRoZSBwYWdlIHJlbG9hZHMsIGFuZFxuICogdGhlIG5vdy1hdXRoZW50aWNhdGVkIHJlcXVlc3QgcmVhY2hlcyB0aGUgYXBwLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBBVVRIX1BSRUZJWCB9IGZyb20gXCIuL2dhdGUudHNcIjtcblxuZXhwb3J0IGludGVyZmFjZSBMb2dpblBhZ2VPcHRpb25zIHtcbiAgLyoqIFByb2R1Y3QvYnJhbmQgbmFtZSBzaG93biBpbiB0aGUgaGVhZGluZy4gKi9cbiAgYnJhbmROYW1lOiBzdHJpbmc7XG59XG5cbi8qKiBUaGUgbG9naW4gcGFnZSBIVE1MIGZvciBhIGB0ZXh0L2h0bWxgIHJlcXVlc3QgdG8gYSBnYXRlZCBwYXRoIHdpdGggbm8gc2Vzc2lvbi4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsb2dpblBhZ2VIdG1sKG9wdGlvbnM6IExvZ2luUGFnZU9wdGlvbnMpOiBzdHJpbmcge1xuICBjb25zdCBicmFuZCA9IGVzY2FwZUh0bWwob3B0aW9ucy5icmFuZE5hbWUpO1xuICAvLyBBVVRIX1BSRUZJWCBpcyBhIGZpeGVkIGNvbnN0YW50LCBub3QgdXNlciBpbnB1dCwgYnV0IEpTT04tZW5jb2RlIGl0IHNvIHRoZVxuICAvLyBpbmxpbmVkIHNjcmlwdCBpcyBhbHdheXMgdmFsaWQgcmVnYXJkbGVzcyBvZiBpdHMgdmFsdWUuXG4gIGNvbnN0IHByZWZpeCA9IEpTT04uc3RyaW5naWZ5KEFVVEhfUFJFRklYKTtcbiAgcmV0dXJuIGA8IWRvY3R5cGUgaHRtbD5cbjxodG1sIGxhbmc9XCJlblwiPlxuPGhlYWQ+XG48bWV0YSBjaGFyc2V0PVwidXRmLThcIj5cbjxtZXRhIG5hbWU9XCJ2aWV3cG9ydFwiIGNvbnRlbnQ9XCJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MVwiPlxuPHRpdGxlPlNpZ24gaW4g4oCUICR7YnJhbmR9PC90aXRsZT5cbjxzdHlsZT5cbiAgOnJvb3Qge1xuICAgIGNvbG9yLXNjaGVtZTogbGlnaHQgZGFyaztcbiAgICAtLWJnOiAjZmZmZmZmOyAtLWZnOiAjMWIxYjFmOyAtLW11dGVkOiAjNmI3MjgwOyAtLWJvcmRlcjogI2Q5ZGNlMTtcbiAgICAtLWFjY2VudDogI0ZGMzYyMTsgLS1hY2NlbnQtZmc6ICNmZmZmZmY7IC0tZXJyb3I6ICNjNTIyMWY7IC0tZmllbGQ6ICNmZmZmZmY7XG4gIH1cbiAgQG1lZGlhIChwcmVmZXJzLWNvbG9yLXNjaGVtZTogZGFyaykge1xuICAgIDpyb290IHtcbiAgICAgIC0tYmc6ICMxNjE4MWQ7IC0tZmc6ICNlOGU2ZGY7IC0tbXV0ZWQ6ICM5YWEwYWE7IC0tYm9yZGVyOiAjMmMyZjM2O1xuICAgICAgLS1hY2NlbnQ6ICNGRjVBNDY7IC0tYWNjZW50LWZnOiAjMGIwZjE5OyAtLWVycm9yOiAjZmY2YjYwOyAtLWZpZWxkOiAjMWUyMTI4O1xuICAgIH1cbiAgfVxuICAqIHsgYm94LXNpemluZzogYm9yZGVyLWJveDsgfVxuICBib2R5IHtcbiAgICBtYXJnaW46IDA7IG1pbi1oZWlnaHQ6IDEwMHZoOyBkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyOyBiYWNrZ3JvdW5kOiB2YXIoLS1iZyk7IGNvbG9yOiB2YXIoLS1mZyk7XG4gICAgZm9udC1mYW1pbHk6IHN5c3RlbS11aSwgLWFwcGxlLXN5c3RlbSwgXCJTZWdvZSBVSVwiLCBzYW5zLXNlcmlmOyBwYWRkaW5nOiAyNHB4O1xuICB9XG4gIC5jYXJkIHtcbiAgICB3aWR0aDogMTAwJTsgbWF4LXdpZHRoOiAzNjBweDsgYm9yZGVyOiAxcHggc29saWQgdmFyKC0tYm9yZGVyKTtcbiAgICBib3JkZXItcmFkaXVzOiAxNHB4OyBwYWRkaW5nOiAyOHB4OyBiYWNrZ3JvdW5kOiB2YXIoLS1iZyk7XG4gIH1cbiAgLmxvZ28geyB3aWR0aDogNDBweDsgaGVpZ2h0OiA0MHB4OyBkaXNwbGF5OiBibG9jazsgbWFyZ2luOiAwIDAgMTRweDsgfVxuICBoMSB7IGZvbnQtc2l6ZTogMThweDsgbWFyZ2luOiAwIDAgNHB4OyB9XG4gIHAuc3ViIHsgbWFyZ2luOiAwIDAgMjBweDsgY29sb3I6IHZhcigtLW11dGVkKTsgZm9udC1zaXplOiAxM3B4OyB9XG4gIGxhYmVsIHsgZGlzcGxheTogYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgY29sb3I6IHZhcigtLW11dGVkKTsgbWFyZ2luOiAwIDAgNnB4OyB9XG4gIGlucHV0IHtcbiAgICB3aWR0aDogMTAwJTsgcGFkZGluZzogMTBweCAxMnB4OyBmb250LXNpemU6IDE1cHg7IGJvcmRlci1yYWRpdXM6IDlweDtcbiAgICBib3JkZXI6IDFweCBzb2xpZCB2YXIoLS1ib3JkZXIpOyBiYWNrZ3JvdW5kOiB2YXIoLS1maWVsZCk7IGNvbG9yOiB2YXIoLS1mZyk7XG4gIH1cbiAgaW5wdXQ6Zm9jdXMgeyBvdXRsaW5lOiAycHggc29saWQgdmFyKC0tYWNjZW50KTsgb3V0bGluZS1vZmZzZXQ6IC0xcHg7IH1cbiAgYnV0dG9uIHtcbiAgICB3aWR0aDogMTAwJTsgbWFyZ2luLXRvcDogMTZweDsgcGFkZGluZzogMTBweCAxMnB4OyBmb250LXNpemU6IDE1cHg7XG4gICAgZm9udC13ZWlnaHQ6IDYwMDsgYm9yZGVyOiAwOyBib3JkZXItcmFkaXVzOiA5cHg7IGJhY2tncm91bmQ6IHZhcigtLWFjY2VudCk7XG4gICAgY29sb3I6IHZhcigtLWFjY2VudC1mZyk7IGN1cnNvcjogcG9pbnRlcjtcbiAgfVxuICBidXR0b246ZGlzYWJsZWQgeyBvcGFjaXR5OiAwLjY7IGN1cnNvcjogZGVmYXVsdDsgfVxuICAubXNnIHsgbWFyZ2luLXRvcDogMTRweDsgZm9udC1zaXplOiAxM3B4OyBtaW4taGVpZ2h0OiAxOHB4OyB9XG4gIC5tc2cuZXJyb3IgeyBjb2xvcjogdmFyKC0tZXJyb3IpOyB9XG4gIC5oaWRkZW4geyBkaXNwbGF5OiBub25lOyB9XG4gIC5iYWNrIHsgYmFja2dyb3VuZDogbm9uZTsgY29sb3I6IHZhcigtLW11dGVkKTsgZm9udC13ZWlnaHQ6IDQwMDsgbWFyZ2luLXRvcDogOHB4OyB9XG48L3N0eWxlPlxuPC9oZWFkPlxuPGJvZHk+XG4gIDxtYWluIGNsYXNzPVwiY2FyZFwiPlxuICAgIDwhLS0gZGJ4LnRvb2xzIHBpeGVsLWJyaWNrIFwic3RhY2hlXCIgbWFyayAoTGF2YSBwYWxldHRlKSwgbWF0Y2hpbmcgdGhlIEthbm5hIFVJIGxvZ28uIC0tPlxuICAgIDxzdmcgY2xhc3M9XCJsb2dvXCIgdmlld0JveD1cIjAgMCA2NCA2NFwiIHJvbGU9XCJpbWdcIiBhcmlhLWxhYmVsPVwiJHticmFuZH1cIiBzaGFwZS1yZW5kZXJpbmc9XCJjcmlzcEVkZ2VzXCI+XG4gICAgICA8cmVjdCB4PVwiMTlcIiB5PVwiMjBcIiB3aWR0aD1cIjhcIiBoZWlnaHQ9XCI4XCIgcng9XCIxXCIgZmlsbD1cIiNGRjM2MjFcIi8+PHJlY3QgeD1cIjM3XCIgeT1cIjIwXCIgd2lkdGg9XCI4XCIgaGVpZ2h0PVwiOFwiIHJ4PVwiMVwiIGZpbGw9XCIjRkYzNjIxXCIvPlxuICAgICAgPHJlY3QgeD1cIjFcIiB5PVwiMjlcIiB3aWR0aD1cIjhcIiBoZWlnaHQ9XCI4XCIgcng9XCIxXCIgZmlsbD1cIiNEOTJEMThcIi8+PHJlY3QgeD1cIjEwXCIgeT1cIjI5XCIgd2lkdGg9XCI4XCIgaGVpZ2h0PVwiOFwiIHJ4PVwiMVwiIGZpbGw9XCIjRkYzNjIxXCIvPjxyZWN0IHg9XCIxOVwiIHk9XCIyOVwiIHdpZHRoPVwiOFwiIGhlaWdodD1cIjhcIiByeD1cIjFcIiBmaWxsPVwiI0ZGNUE0NlwiLz48cmVjdCB4PVwiMjhcIiB5PVwiMjlcIiB3aWR0aD1cIjhcIiBoZWlnaHQ9XCI4XCIgcng9XCIxXCIgZmlsbD1cIiNGRjg5NzRcIi8+PHJlY3QgeD1cIjM3XCIgeT1cIjI5XCIgd2lkdGg9XCI4XCIgaGVpZ2h0PVwiOFwiIHJ4PVwiMVwiIGZpbGw9XCIjRkY1QTQ2XCIvPjxyZWN0IHg9XCI0NlwiIHk9XCIyOVwiIHdpZHRoPVwiOFwiIGhlaWdodD1cIjhcIiByeD1cIjFcIiBmaWxsPVwiI0ZGMzYyMVwiLz48cmVjdCB4PVwiNTVcIiB5PVwiMjlcIiB3aWR0aD1cIjhcIiBoZWlnaHQ9XCI4XCIgcng9XCIxXCIgZmlsbD1cIiNEOTJEMThcIi8+XG4gICAgICA8cmVjdCB4PVwiMTBcIiB5PVwiMzhcIiB3aWR0aD1cIjhcIiBoZWlnaHQ9XCI4XCIgcng9XCIxXCIgZmlsbD1cIiNGRjM2MjFcIi8+PHJlY3QgeD1cIjQ2XCIgeT1cIjM4XCIgd2lkdGg9XCI4XCIgaGVpZ2h0PVwiOFwiIHJ4PVwiMVwiIGZpbGw9XCIjRkYzNjIxXCIvPlxuICAgIDwvc3ZnPlxuICAgIDxoMT5TaWduIGluIHRvICR7YnJhbmR9PC9oMT5cbiAgICA8cCBjbGFzcz1cInN1YlwiPkVudGVyIHlvdXIgZW1haWwgdG8gcmVjZWl2ZSBhIG9uZS10aW1lIGNvZGUuPC9wPlxuXG4gICAgPGZvcm0gaWQ9XCJlbWFpbC1mb3JtXCI+XG4gICAgICA8bGFiZWwgZm9yPVwiZW1haWxcIj5FbWFpbDwvbGFiZWw+XG4gICAgICA8aW5wdXQgaWQ9XCJlbWFpbFwiIG5hbWU9XCJlbWFpbFwiIHR5cGU9XCJlbWFpbFwiIGF1dG9jb21wbGV0ZT1cImVtYWlsXCIgcmVxdWlyZWQgYXV0b2ZvY3VzPlxuICAgICAgPGJ1dHRvbiBpZD1cImVtYWlsLXN1Ym1pdFwiIHR5cGU9XCJzdWJtaXRcIj5TZW5kIGNvZGU8L2J1dHRvbj5cbiAgICA8L2Zvcm0+XG5cbiAgICA8Zm9ybSBpZD1cImNvZGUtZm9ybVwiIGNsYXNzPVwiaGlkZGVuXCI+XG4gICAgICA8bGFiZWwgZm9yPVwiY29kZVwiPlZlcmlmaWNhdGlvbiBjb2RlPC9sYWJlbD5cbiAgICAgIDxpbnB1dCBpZD1cImNvZGVcIiBuYW1lPVwiY29kZVwiIGlucHV0bW9kZT1cIm51bWVyaWNcIiBhdXRvY29tcGxldGU9XCJvbmUtdGltZS1jb2RlXCIgcmVxdWlyZWQ+XG4gICAgICA8YnV0dG9uIGlkPVwiY29kZS1zdWJtaXRcIiB0eXBlPVwic3VibWl0XCI+VmVyaWZ5PC9idXR0b24+XG4gICAgICA8YnV0dG9uIGlkPVwiYmFja1wiIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJhY2tcIj5Vc2UgYSBkaWZmZXJlbnQgZW1haWw8L2J1dHRvbj5cbiAgICA8L2Zvcm0+XG5cbiAgICA8ZGl2IGlkPVwibXNnXCIgY2xhc3M9XCJtc2dcIiByb2xlPVwic3RhdHVzXCIgYXJpYS1saXZlPVwicG9saXRlXCI+PC9kaXY+XG4gIDwvbWFpbj5cblxuPHNjcmlwdD5cbihmdW5jdGlvbiAoKSB7XG4gIHZhciBQUkVGSVggPSAke3ByZWZpeH07XG4gIHZhciBlbWFpbEZvcm0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcImVtYWlsLWZvcm1cIik7XG4gIHZhciBjb2RlRm9ybSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiY29kZS1mb3JtXCIpO1xuICB2YXIgZW1haWxJbnB1dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiZW1haWxcIik7XG4gIHZhciBjb2RlSW5wdXQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcImNvZGVcIik7XG4gIHZhciBiYWNrID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJiYWNrXCIpO1xuICB2YXIgbXNnID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJtc2dcIik7XG4gIHZhciBlbWFpbCA9IFwiXCI7XG5cbiAgZnVuY3Rpb24gc2F5KHRleHQsIGlzRXJyb3IpIHtcbiAgICBtc2cudGV4dENvbnRlbnQgPSB0ZXh0IHx8IFwiXCI7XG4gICAgbXNnLmNsYXNzTmFtZSA9IFwibXNnXCIgKyAoaXNFcnJvciA/IFwiIGVycm9yXCIgOiBcIlwiKTtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIHBvc3QocGF0aCwgYm9keSkge1xuICAgIHZhciByZXMgPSBhd2FpdCBmZXRjaChQUkVGSVggKyBwYXRoLCB7XG4gICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgY3JlZGVudGlhbHM6IFwiaW5jbHVkZVwiLFxuICAgICAgaGVhZGVyczogeyBcImNvbnRlbnQtdHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiB9LFxuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoYm9keSksXG4gICAgfSk7XG4gICAgdmFyIGRhdGEgPSB7fTtcbiAgICB0cnkgeyBkYXRhID0gYXdhaXQgcmVzLmpzb24oKTsgfSBjYXRjaCAoX2UpIHsgLyogbm9uLUpTT04gKi8gfVxuICAgIHJldHVybiB7IG9rOiByZXMub2ssIHN0YXR1czogcmVzLnN0YXR1cywgZGF0YTogZGF0YSB9O1xuICB9XG5cbiAgZnVuY3Rpb24gZXJyb3JUZXh0KGRhdGEsIGZhbGxiYWNrKSB7XG4gICAgLy8gYmV0dGVyLWF1dGggZXJyb3Igc2hhcGU6IHsgbWVzc2FnZSB9IG9yIHsgZXJyb3I6IHsgbWVzc2FnZSB9IH0uXG4gICAgaWYgKGRhdGEgJiYgZGF0YS5lcnJvciAmJiBkYXRhLmVycm9yLm1lc3NhZ2UpIHJldHVybiBkYXRhLmVycm9yLm1lc3NhZ2U7XG4gICAgaWYgKGRhdGEgJiYgZGF0YS5tZXNzYWdlKSByZXR1cm4gZGF0YS5tZXNzYWdlO1xuICAgIHJldHVybiBmYWxsYmFjaztcbiAgfVxuXG4gIGVtYWlsRm9ybS5hZGRFdmVudExpc3RlbmVyKFwic3VibWl0XCIsIGFzeW5jIGZ1bmN0aW9uIChlKSB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGVtYWlsID0gZW1haWxJbnB1dC52YWx1ZS50cmltKCk7XG4gICAgaWYgKCFlbWFpbCkgcmV0dXJuO1xuICAgIHZhciBzdWJtaXQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcImVtYWlsLXN1Ym1pdFwiKTtcbiAgICBzdWJtaXQuZGlzYWJsZWQgPSB0cnVlO1xuICAgIHNheShcIlNlbmRpbmfigKZcIik7XG4gICAgdHJ5IHtcbiAgICAgIC8vIGJldHRlci1hdXRoIGVtYWlsT1RQIG5hdGl2ZSBlbmRwb2ludC5cbiAgICAgIHZhciByID0gYXdhaXQgcG9zdChcIi9lbWFpbC1vdHAvc2VuZC12ZXJpZmljYXRpb24tb3RwXCIsIHsgZW1haWw6IGVtYWlsLCB0eXBlOiBcInNpZ24taW5cIiB9KTtcbiAgICAgIGlmIChyLm9rKSB7XG4gICAgICAgIGVtYWlsRm9ybS5jbGFzc0xpc3QuYWRkKFwiaGlkZGVuXCIpO1xuICAgICAgICBjb2RlRm9ybS5jbGFzc0xpc3QucmVtb3ZlKFwiaGlkZGVuXCIpO1xuICAgICAgICBjb2RlSW5wdXQuZm9jdXMoKTtcbiAgICAgICAgc2F5KFwiV2UgZW1haWxlZCBhIGNvZGUgdG8gXCIgKyBlbWFpbCArIFwiLlwiKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNheShlcnJvclRleHQoci5kYXRhLCBcIkNvdWxkIG5vdCBzZW5kIGEgY29kZS4gQ2hlY2sgdGhlIGFkZHJlc3MgYW5kIHRyeSBhZ2Fpbi5cIiksIHRydWUpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKF9lKSB7XG4gICAgICBzYXkoXCJOZXR3b3JrIGVycm9yLiBUcnkgYWdhaW4uXCIsIHRydWUpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBzdWJtaXQuZGlzYWJsZWQgPSBmYWxzZTtcbiAgICB9XG4gIH0pO1xuXG4gIGNvZGVGb3JtLmFkZEV2ZW50TGlzdGVuZXIoXCJzdWJtaXRcIiwgYXN5bmMgZnVuY3Rpb24gKGUpIHtcbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgdmFyIGNvZGUgPSBjb2RlSW5wdXQudmFsdWUudHJpbSgpO1xuICAgIGlmICghY29kZSkgcmV0dXJuO1xuICAgIHZhciBzdWJtaXQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcImNvZGUtc3VibWl0XCIpO1xuICAgIHN1Ym1pdC5kaXNhYmxlZCA9IHRydWU7XG4gICAgc2F5KFwiVmVyaWZ5aW5n4oCmXCIpO1xuICAgIHRyeSB7XG4gICAgICAvLyBiZXR0ZXItYXV0aCBzaWduLWluIHdpdGggdGhlIE9UUDsgc2V0cyB0aGUgc2Vzc2lvbiBjb29raWUgb24gc3VjY2Vzcy5cbiAgICAgIHZhciByID0gYXdhaXQgcG9zdChcIi9zaWduLWluL2VtYWlsLW90cFwiLCB7XG4gICAgICAgIGVtYWlsOiBlbWFpbCxcbiAgICAgICAgb3RwOiBjb2RlLFxuICAgICAgICBuYW1lOiBlbWFpbC5zcGxpdChcIkBcIilbMF0sXG4gICAgICB9KTtcbiAgICAgIGlmIChyLm9rKSB7XG4gICAgICAgIHNheShcIlNpZ25lZCBpbi4gTG9hZGluZ+KAplwiKTtcbiAgICAgICAgLy8gVGhlIHNlc3Npb24gY29va2llIGlzIHNldDsgcmVsb2FkIHNvIHRoZSBub3ctYXV0aGVudGljYXRlZCByZXF1ZXN0XG4gICAgICAgIC8vIHJlYWNoZXMgdGhlIGFwcC5cbiAgICAgICAgd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2F5KGVycm9yVGV4dChyLmRhdGEsIFwiVGhhdCBjb2RlIHdhcyBub3QgYWNjZXB0ZWQuIFRyeSBhZ2Fpbi5cIiksIHRydWUpO1xuICAgICAgICBzdWJtaXQuZGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChfZSkge1xuICAgICAgc2F5KFwiTmV0d29yayBlcnJvci4gVHJ5IGFnYWluLlwiLCB0cnVlKTtcbiAgICAgIHN1Ym1pdC5kaXNhYmxlZCA9IGZhbHNlO1xuICAgIH1cbiAgfSk7XG5cbiAgYmFjay5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgZnVuY3Rpb24gKCkge1xuICAgIGNvZGVGb3JtLmNsYXNzTGlzdC5hZGQoXCJoaWRkZW5cIik7XG4gICAgZW1haWxGb3JtLmNsYXNzTGlzdC5yZW1vdmUoXCJoaWRkZW5cIik7XG4gICAgY29kZUlucHV0LnZhbHVlID0gXCJcIjtcbiAgICBzYXkoXCJcIik7XG4gICAgZW1haWxJbnB1dC5mb2N1cygpO1xuICB9KTtcbn0pKCk7XG48L3NjcmlwdD5cbjwvYm9keT5cbjwvaHRtbD5gO1xufVxuXG5jb25zdCBIVE1MX0VTQ0FQRVM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gIFwiJlwiOiBcIiZhbXA7XCIsXG4gIFwiPFwiOiBcIiZsdDtcIixcbiAgXCI+XCI6IFwiJmd0O1wiLFxuICAnXCInOiBcIiZxdW90O1wiLFxuICBcIidcIjogXCImIzM5O1wiLFxufTtcblxuZnVuY3Rpb24gZXNjYXBlSHRtbCh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHZhbHVlLnJlcGxhY2UoL1smPD5cIiddL2csIChjaCkgPT4gSFRNTF9FU0NBUEVTW2NoXSA/PyBjaCk7XG59XG4iXX0=
212
+ /** Encode a string literal without allowing it to terminate the surrounding script. */
213
+ function jsonForInlineScript(value) {
214
+ return JSON.stringify(value)
215
+ .replaceAll("<", "\\u003c")
216
+ .replaceAll(">", "\\u003e")
217
+ .replaceAll("&", "\\u0026")
218
+ .replaceAll("\u2028", "\\u2028")
219
+ .replaceAll("\u2029", "\\u2029");
220
+ }
221
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9naW4tcGFnZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9sb2dpbi1wYWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBRUgsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQVN4QyxxRkFBcUY7QUFDckYsTUFBTSxVQUFVLGFBQWEsQ0FBQyxPQUF5QjtJQUNyRCxNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzVDLE1BQU0sTUFBTSxHQUFHLG1CQUFtQixDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ2hELE1BQU0sUUFBUSxHQUFHLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN2RCxPQUFPOzs7OzttQkFLVSxLQUFLOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzttRUErQzJDLEtBQUs7Ozs7O3FCQUtuRCxLQUFLOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7aUJBcUJULE1BQU07b0JBQ0gsUUFBUTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O1FBbUdwQixDQUFDO0FBQ1QsQ0FBQztBQUVELE1BQU0sWUFBWSxHQUEyQjtJQUMzQyxHQUFHLEVBQUUsT0FBTztJQUNaLEdBQUcsRUFBRSxNQUFNO0lBQ1gsR0FBRyxFQUFFLE1BQU07SUFDWCxHQUFHLEVBQUUsUUFBUTtJQUNiLEdBQUcsRUFBRSxPQUFPO0NBQ2IsQ0FBQztBQUVGLFNBQVMsVUFBVSxDQUFDLEtBQWE7SUFDL0IsT0FBTyxLQUFLLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQ25FLENBQUM7QUFFRCx1RkFBdUY7QUFDdkYsU0FBUyxtQkFBbUIsQ0FBQyxLQUFhO0lBQ3hDLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUM7U0FDekIsVUFBVSxDQUFDLEdBQUcsRUFBRSxTQUFTLENBQUM7U0FDMUIsVUFBVSxDQUFDLEdBQUcsRUFBRSxTQUFTLENBQUM7U0FDMUIsVUFBVSxDQUFDLEdBQUcsRUFBRSxTQUFTLENBQUM7U0FDMUIsVUFBVSxDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUM7U0FDL0IsVUFBVSxDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsQ0FBQztBQUNyQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBBIHNlbGYtY29udGFpbmVkIEhUTUwgbG9naW4gcGFnZSB0aGUgdHVubmVsIHNlcnZlcyBpbiBmcm9udCBvZiBhbiBhcHAgdGhhdFxuICogZG9lcyBub3QgZW1iZWQgdGhlIGA8QXV0aEdhdGU+YCBSZWFjdCBjb21wb25lbnQgKGUuZy4gYSBXZWJTb2NrZXQgYXBwIGZyb250ZWRcbiAqIGJ5IHRoZSBDTEkgcHJveHkpLlxuICpcbiAqIEl0IHNwZWFrcyB0aGUgc2FtZSBjb21wYXRpYmlsaXR5IGVuZHBvaW50cyB1bmRlciB7QGxpbmsgQVVUSF9QUkVGSVh9IHRoYXQgdGhlXG4gKiBSZWFjdCBjbGllbnQgdXNlcyDigJQgYFBPU1QgL3JlcXVlc3RgIHRvIGVtYWlsIGEgY29kZSwgYFBPU1QgL3ZlcmlmeWAgdG9cbiAqIGV4Y2hhbmdlIGl0IGZvciB0aGUgYGRieC10b29scy1hdXRoYCBzZXNzaW9uIGNvb2tpZSDigJQgd2l0aCBwbGFpbiBgZmV0Y2hgLCBub1xuICogYnVpbGQgc3RlcCBhbmQgbm8gZGVwZW5kZW5jeS4gUGFzc2tleXMgYXJlIGludGVudGlvbmFsbHkgb21pdHRlZDogdGhlIFdlYkF1dGhuXG4gKiBjZXJlbW9ueSBuZWVkcyB0aGUgYmV0dGVyLWF1dGggY2xpZW50IGxpYnJhcnksIHNvIHBhc3NrZXkgZW5yb2xsbWVudCBoYXBwZW5zXG4gKiBpbnNpZGUgdGhlIGFwcCBhZnRlciB0aGlzIGVtYWlsLU9UUCBzaWduLWluLiBPbiBzdWNjZXNzIHRoZSBwYWdlIHJlbG9hZHMsIGFuZFxuICogdGhlIG5vdy1hdXRoZW50aWNhdGVkIHJlcXVlc3QgcmVhY2hlcyB0aGUgYXBwLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBBVVRIX1BSRUZJWCB9IGZyb20gXCIuL2dhdGUudHNcIjtcblxuZXhwb3J0IGludGVyZmFjZSBMb2dpblBhZ2VPcHRpb25zIHtcbiAgLyoqIFByb2R1Y3QvYnJhbmQgbmFtZSBzaG93biBpbiB0aGUgaGVhZGluZy4gKi9cbiAgYnJhbmROYW1lOiBzdHJpbmc7XG4gIC8qKiBWYWxpZGF0ZWQgc2FtZS1vcmlnaW4gcGF0aCBsb2FkZWQgYWZ0ZXIgYXV0aGVudGljYXRpb24gc3VjY2VlZHMuICovXG4gIHJldHVyblRvOiBzdHJpbmc7XG59XG5cbi8qKiBUaGUgbG9naW4gcGFnZSBIVE1MIGZvciBhIGB0ZXh0L2h0bWxgIHJlcXVlc3QgdG8gYSBnYXRlZCBwYXRoIHdpdGggbm8gc2Vzc2lvbi4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsb2dpblBhZ2VIdG1sKG9wdGlvbnM6IExvZ2luUGFnZU9wdGlvbnMpOiBzdHJpbmcge1xuICBjb25zdCBicmFuZCA9IGVzY2FwZUh0bWwob3B0aW9ucy5icmFuZE5hbWUpO1xuICBjb25zdCBwcmVmaXggPSBqc29uRm9ySW5saW5lU2NyaXB0KEFVVEhfUFJFRklYKTtcbiAgY29uc3QgcmV0dXJuVG8gPSBqc29uRm9ySW5saW5lU2NyaXB0KG9wdGlvbnMucmV0dXJuVG8pO1xuICByZXR1cm4gYDwhZG9jdHlwZSBodG1sPlxuPGh0bWwgbGFuZz1cImVuXCI+XG48aGVhZD5cbjxtZXRhIGNoYXJzZXQ9XCJ1dGYtOFwiPlxuPG1ldGEgbmFtZT1cInZpZXdwb3J0XCIgY29udGVudD1cIndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xXCI+XG48dGl0bGU+U2lnbiBpbiDigJQgJHticmFuZH08L3RpdGxlPlxuPHN0eWxlPlxuICA6cm9vdCB7XG4gICAgY29sb3Itc2NoZW1lOiBsaWdodCBkYXJrO1xuICAgIC0tYmc6ICNmZmZmZmY7IC0tZmc6ICMxYjFiMWY7IC0tbXV0ZWQ6ICM2YjcyODA7IC0tYm9yZGVyOiAjZDlkY2UxO1xuICAgIC0tYWNjZW50OiAjRkYzNjIxOyAtLWFjY2VudC1mZzogI2ZmZmZmZjsgLS1lcnJvcjogI2M1MjIxZjsgLS1maWVsZDogI2ZmZmZmZjtcbiAgfVxuICBAbWVkaWEgKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKSB7XG4gICAgOnJvb3Qge1xuICAgICAgLS1iZzogIzE2MTgxZDsgLS1mZzogI2U4ZTZkZjsgLS1tdXRlZDogIzlhYTBhYTsgLS1ib3JkZXI6ICMyYzJmMzY7XG4gICAgICAtLWFjY2VudDogI0ZGNUE0NjsgLS1hY2NlbnQtZmc6ICMwYjBmMTk7IC0tZXJyb3I6ICNmZjZiNjA7IC0tZmllbGQ6ICMxZTIxMjg7XG4gICAgfVxuICB9XG4gICogeyBib3gtc2l6aW5nOiBib3JkZXItYm94OyB9XG4gIGJvZHkge1xuICAgIG1hcmdpbjogMDsgbWluLWhlaWdodDogMTAwdmg7IGRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7IGJhY2tncm91bmQ6IHZhcigtLWJnKTsgY29sb3I6IHZhcigtLWZnKTtcbiAgICBmb250LWZhbWlseTogc3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBcIlNlZ29lIFVJXCIsIHNhbnMtc2VyaWY7IHBhZGRpbmc6IDI0cHg7XG4gIH1cbiAgLmNhcmQge1xuICAgIHdpZHRoOiAxMDAlOyBtYXgtd2lkdGg6IDM2MHB4OyBib3JkZXI6IDFweCBzb2xpZCB2YXIoLS1ib3JkZXIpO1xuICAgIGJvcmRlci1yYWRpdXM6IDE0cHg7IHBhZGRpbmc6IDI4cHg7IGJhY2tncm91bmQ6IHZhcigtLWJnKTtcbiAgfVxuICAubG9nbyB7IHdpZHRoOiA0MHB4OyBoZWlnaHQ6IDQwcHg7IGRpc3BsYXk6IGJsb2NrOyBtYXJnaW46IDAgMCAxNHB4OyB9XG4gIGgxIHsgZm9udC1zaXplOiAxOHB4OyBtYXJnaW46IDAgMCA0cHg7IH1cbiAgcC5zdWIgeyBtYXJnaW46IDAgMCAyMHB4OyBjb2xvcjogdmFyKC0tbXV0ZWQpOyBmb250LXNpemU6IDEzcHg7IH1cbiAgbGFiZWwgeyBkaXNwbGF5OiBibG9jazsgZm9udC1zaXplOiAxMnB4OyBjb2xvcjogdmFyKC0tbXV0ZWQpOyBtYXJnaW46IDAgMCA2cHg7IH1cbiAgaW5wdXQge1xuICAgIHdpZHRoOiAxMDAlOyBwYWRkaW5nOiAxMHB4IDEycHg7IGZvbnQtc2l6ZTogMTVweDsgYm9yZGVyLXJhZGl1czogOXB4O1xuICAgIGJvcmRlcjogMXB4IHNvbGlkIHZhcigtLWJvcmRlcik7IGJhY2tncm91bmQ6IHZhcigtLWZpZWxkKTsgY29sb3I6IHZhcigtLWZnKTtcbiAgfVxuICBpbnB1dDpmb2N1cyB7IG91dGxpbmU6IDJweCBzb2xpZCB2YXIoLS1hY2NlbnQpOyBvdXRsaW5lLW9mZnNldDogLTFweDsgfVxuICBidXR0b24ge1xuICAgIHdpZHRoOiAxMDAlOyBtYXJnaW4tdG9wOiAxNnB4OyBwYWRkaW5nOiAxMHB4IDEycHg7IGZvbnQtc2l6ZTogMTVweDtcbiAgICBmb250LXdlaWdodDogNjAwOyBib3JkZXI6IDA7IGJvcmRlci1yYWRpdXM6IDlweDsgYmFja2dyb3VuZDogdmFyKC0tYWNjZW50KTtcbiAgICBjb2xvcjogdmFyKC0tYWNjZW50LWZnKTsgY3Vyc29yOiBwb2ludGVyO1xuICB9XG4gIGJ1dHRvbjpkaXNhYmxlZCB7IG9wYWNpdHk6IDAuNjsgY3Vyc29yOiBkZWZhdWx0OyB9XG4gIC5tc2cgeyBtYXJnaW4tdG9wOiAxNHB4OyBmb250LXNpemU6IDEzcHg7IG1pbi1oZWlnaHQ6IDE4cHg7IH1cbiAgLm1zZy5lcnJvciB7IGNvbG9yOiB2YXIoLS1lcnJvcik7IH1cbiAgLmhpZGRlbiB7IGRpc3BsYXk6IG5vbmU7IH1cbiAgLmJhY2sgeyBiYWNrZ3JvdW5kOiBub25lOyBjb2xvcjogdmFyKC0tbXV0ZWQpOyBmb250LXdlaWdodDogNDAwOyBtYXJnaW4tdG9wOiA4cHg7IH1cbjwvc3R5bGU+XG48L2hlYWQ+XG48Ym9keT5cbiAgPG1haW4gY2xhc3M9XCJjYXJkXCI+XG4gICAgPCEtLSBkYngudG9vbHMgcGl4ZWwtYnJpY2sgXCJzdGFjaGVcIiBtYXJrIChMYXZhIHBhbGV0dGUpLCBtYXRjaGluZyB0aGUgS2FubmEgVUkgbG9nby4gLS0+XG4gICAgPHN2ZyBjbGFzcz1cImxvZ29cIiB2aWV3Qm94PVwiMCAwIDY0IDY0XCIgcm9sZT1cImltZ1wiIGFyaWEtbGFiZWw9XCIke2JyYW5kfVwiIHNoYXBlLXJlbmRlcmluZz1cImNyaXNwRWRnZXNcIj5cbiAgICAgIDxyZWN0IHg9XCIxOVwiIHk9XCIyMFwiIHdpZHRoPVwiOFwiIGhlaWdodD1cIjhcIiByeD1cIjFcIiBmaWxsPVwiI0ZGMzYyMVwiLz48cmVjdCB4PVwiMzdcIiB5PVwiMjBcIiB3aWR0aD1cIjhcIiBoZWlnaHQ9XCI4XCIgcng9XCIxXCIgZmlsbD1cIiNGRjM2MjFcIi8+XG4gICAgICA8cmVjdCB4PVwiMVwiIHk9XCIyOVwiIHdpZHRoPVwiOFwiIGhlaWdodD1cIjhcIiByeD1cIjFcIiBmaWxsPVwiI0Q5MkQxOFwiLz48cmVjdCB4PVwiMTBcIiB5PVwiMjlcIiB3aWR0aD1cIjhcIiBoZWlnaHQ9XCI4XCIgcng9XCIxXCIgZmlsbD1cIiNGRjM2MjFcIi8+PHJlY3QgeD1cIjE5XCIgeT1cIjI5XCIgd2lkdGg9XCI4XCIgaGVpZ2h0PVwiOFwiIHJ4PVwiMVwiIGZpbGw9XCIjRkY1QTQ2XCIvPjxyZWN0IHg9XCIyOFwiIHk9XCIyOVwiIHdpZHRoPVwiOFwiIGhlaWdodD1cIjhcIiByeD1cIjFcIiBmaWxsPVwiI0ZGODk3NFwiLz48cmVjdCB4PVwiMzdcIiB5PVwiMjlcIiB3aWR0aD1cIjhcIiBoZWlnaHQ9XCI4XCIgcng9XCIxXCIgZmlsbD1cIiNGRjVBNDZcIi8+PHJlY3QgeD1cIjQ2XCIgeT1cIjI5XCIgd2lkdGg9XCI4XCIgaGVpZ2h0PVwiOFwiIHJ4PVwiMVwiIGZpbGw9XCIjRkYzNjIxXCIvPjxyZWN0IHg9XCI1NVwiIHk9XCIyOVwiIHdpZHRoPVwiOFwiIGhlaWdodD1cIjhcIiByeD1cIjFcIiBmaWxsPVwiI0Q5MkQxOFwiLz5cbiAgICAgIDxyZWN0IHg9XCIxMFwiIHk9XCIzOFwiIHdpZHRoPVwiOFwiIGhlaWdodD1cIjhcIiByeD1cIjFcIiBmaWxsPVwiI0ZGMzYyMVwiLz48cmVjdCB4PVwiNDZcIiB5PVwiMzhcIiB3aWR0aD1cIjhcIiBoZWlnaHQ9XCI4XCIgcng9XCIxXCIgZmlsbD1cIiNGRjM2MjFcIi8+XG4gICAgPC9zdmc+XG4gICAgPGgxPlNpZ24gaW4gdG8gJHticmFuZH08L2gxPlxuICAgIDxwIGNsYXNzPVwic3ViXCI+RW50ZXIgeW91ciBlbWFpbCB0byByZWNlaXZlIGEgb25lLXRpbWUgY29kZS48L3A+XG5cbiAgICA8Zm9ybSBpZD1cImVtYWlsLWZvcm1cIj5cbiAgICAgIDxsYWJlbCBmb3I9XCJlbWFpbFwiPkVtYWlsPC9sYWJlbD5cbiAgICAgIDxpbnB1dCBpZD1cImVtYWlsXCIgbmFtZT1cImVtYWlsXCIgdHlwZT1cImVtYWlsXCIgYXV0b2NvbXBsZXRlPVwiZW1haWxcIiByZXF1aXJlZCBhdXRvZm9jdXM+XG4gICAgICA8YnV0dG9uIGlkPVwiZW1haWwtc3VibWl0XCIgdHlwZT1cInN1Ym1pdFwiPlNlbmQgY29kZTwvYnV0dG9uPlxuICAgIDwvZm9ybT5cblxuICAgIDxmb3JtIGlkPVwiY29kZS1mb3JtXCIgY2xhc3M9XCJoaWRkZW5cIj5cbiAgICAgIDxsYWJlbCBmb3I9XCJjb2RlXCI+VmVyaWZpY2F0aW9uIGNvZGU8L2xhYmVsPlxuICAgICAgPGlucHV0IGlkPVwiY29kZVwiIG5hbWU9XCJjb2RlXCIgaW5wdXRtb2RlPVwibnVtZXJpY1wiIGF1dG9jb21wbGV0ZT1cIm9uZS10aW1lLWNvZGVcIiByZXF1aXJlZD5cbiAgICAgIDxidXR0b24gaWQ9XCJjb2RlLXN1Ym1pdFwiIHR5cGU9XCJzdWJtaXRcIj5WZXJpZnk8L2J1dHRvbj5cbiAgICAgIDxidXR0b24gaWQ9XCJiYWNrXCIgdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYmFja1wiPlVzZSBhIGRpZmZlcmVudCBlbWFpbDwvYnV0dG9uPlxuICAgIDwvZm9ybT5cblxuICAgIDxkaXYgaWQ9XCJtc2dcIiBjbGFzcz1cIm1zZ1wiIHJvbGU9XCJzdGF0dXNcIiBhcmlhLWxpdmU9XCJwb2xpdGVcIj48L2Rpdj5cbiAgPC9tYWluPlxuXG48c2NyaXB0PlxuKGZ1bmN0aW9uICgpIHtcbiAgdmFyIFBSRUZJWCA9ICR7cHJlZml4fTtcbiAgdmFyIFJFVFVSTl9UTyA9ICR7cmV0dXJuVG99O1xuICAvLyBBbiBpbi1wbGFjZSBsb2dpbiBjYW4gcHJlc2VydmUgYnJvd3Nlci1vbmx5IGhhc2ggc3RhdGUgdGhhdCBuZXZlciByZWFjaGVkIHRoZSBzZXJ2ZXIuXG4gIGlmICh3aW5kb3cubG9jYXRpb24ucGF0aG5hbWUgIT09IFBSRUZJWCkge1xuICAgIFJFVFVSTl9UTyA9IHdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZSArIHdpbmRvdy5sb2NhdGlvbi5zZWFyY2ggKyB3aW5kb3cubG9jYXRpb24uaGFzaDtcbiAgfVxuICB2YXIgZW1haWxGb3JtID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJlbWFpbC1mb3JtXCIpO1xuICB2YXIgY29kZUZvcm0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcImNvZGUtZm9ybVwiKTtcbiAgdmFyIGVtYWlsSW5wdXQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcImVtYWlsXCIpO1xuICB2YXIgY29kZUlucHV0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJjb2RlXCIpO1xuICB2YXIgYmFjayA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiYmFja1wiKTtcbiAgdmFyIG1zZyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwibXNnXCIpO1xuICB2YXIgZW1haWwgPSBcIlwiO1xuXG4gIGZ1bmN0aW9uIHNheSh0ZXh0LCBpc0Vycm9yKSB7XG4gICAgbXNnLnRleHRDb250ZW50ID0gdGV4dCB8fCBcIlwiO1xuICAgIG1zZy5jbGFzc05hbWUgPSBcIm1zZ1wiICsgKGlzRXJyb3IgPyBcIiBlcnJvclwiIDogXCJcIik7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBwb3N0KHBhdGgsIGJvZHkpIHtcbiAgICB2YXIgcmVzID0gYXdhaXQgZmV0Y2goUFJFRklYICsgcGF0aCwge1xuICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgIGNyZWRlbnRpYWxzOiBcImluY2x1ZGVcIixcbiAgICAgIGhlYWRlcnM6IHsgXCJjb250ZW50LXR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIgfSxcbiAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KGJvZHkpLFxuICAgIH0pO1xuICAgIHZhciBkYXRhID0ge307XG4gICAgdHJ5IHsgZGF0YSA9IGF3YWl0IHJlcy5qc29uKCk7IH0gY2F0Y2ggKF9lKSB7IC8qIG5vbi1KU09OICovIH1cbiAgICByZXR1cm4geyBvazogcmVzLm9rLCBzdGF0dXM6IHJlcy5zdGF0dXMsIGRhdGE6IGRhdGEgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGVycm9yVGV4dChkYXRhLCBmYWxsYmFjaykge1xuICAgIC8vIGJldHRlci1hdXRoIGVycm9yIHNoYXBlOiB7IG1lc3NhZ2UgfSBvciB7IGVycm9yOiB7IG1lc3NhZ2UgfSB9LlxuICAgIGlmIChkYXRhICYmIGRhdGEuZXJyb3IgJiYgZGF0YS5lcnJvci5tZXNzYWdlKSByZXR1cm4gZGF0YS5lcnJvci5tZXNzYWdlO1xuICAgIGlmIChkYXRhICYmIGRhdGEubWVzc2FnZSkgcmV0dXJuIGRhdGEubWVzc2FnZTtcbiAgICByZXR1cm4gZmFsbGJhY2s7XG4gIH1cblxuICBlbWFpbEZvcm0uYWRkRXZlbnRMaXN0ZW5lcihcInN1Ym1pdFwiLCBhc3luYyBmdW5jdGlvbiAoZSkge1xuICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICBlbWFpbCA9IGVtYWlsSW5wdXQudmFsdWUudHJpbSgpO1xuICAgIGlmICghZW1haWwpIHJldHVybjtcbiAgICB2YXIgc3VibWl0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJlbWFpbC1zdWJtaXRcIik7XG4gICAgc3VibWl0LmRpc2FibGVkID0gdHJ1ZTtcbiAgICBzYXkoXCJTZW5kaW5n4oCmXCIpO1xuICAgIHRyeSB7XG4gICAgICAvLyBiZXR0ZXItYXV0aCBlbWFpbE9UUCBuYXRpdmUgZW5kcG9pbnQuXG4gICAgICB2YXIgciA9IGF3YWl0IHBvc3QoXCIvZW1haWwtb3RwL3NlbmQtdmVyaWZpY2F0aW9uLW90cFwiLCB7IGVtYWlsOiBlbWFpbCwgdHlwZTogXCJzaWduLWluXCIgfSk7XG4gICAgICBpZiAoci5vaykge1xuICAgICAgICBlbWFpbEZvcm0uY2xhc3NMaXN0LmFkZChcImhpZGRlblwiKTtcbiAgICAgICAgY29kZUZvcm0uY2xhc3NMaXN0LnJlbW92ZShcImhpZGRlblwiKTtcbiAgICAgICAgY29kZUlucHV0LmZvY3VzKCk7XG4gICAgICAgIHNheShcIldlIGVtYWlsZWQgYSBjb2RlIHRvIFwiICsgZW1haWwgKyBcIi5cIik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzYXkoZXJyb3JUZXh0KHIuZGF0YSwgXCJDb3VsZCBub3Qgc2VuZCBhIGNvZGUuIENoZWNrIHRoZSBhZGRyZXNzIGFuZCB0cnkgYWdhaW4uXCIpLCB0cnVlKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChfZSkge1xuICAgICAgc2F5KFwiTmV0d29yayBlcnJvci4gVHJ5IGFnYWluLlwiLCB0cnVlKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgc3VibWl0LmRpc2FibGVkID0gZmFsc2U7XG4gICAgfVxuICB9KTtcblxuICBjb2RlRm9ybS5hZGRFdmVudExpc3RlbmVyKFwic3VibWl0XCIsIGFzeW5jIGZ1bmN0aW9uIChlKSB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHZhciBjb2RlID0gY29kZUlucHV0LnZhbHVlLnRyaW0oKTtcbiAgICBpZiAoIWNvZGUpIHJldHVybjtcbiAgICB2YXIgc3VibWl0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJjb2RlLXN1Ym1pdFwiKTtcbiAgICBzdWJtaXQuZGlzYWJsZWQgPSB0cnVlO1xuICAgIHNheShcIlZlcmlmeWluZ+KAplwiKTtcbiAgICB0cnkge1xuICAgICAgLy8gYmV0dGVyLWF1dGggc2lnbi1pbiB3aXRoIHRoZSBPVFA7IHNldHMgdGhlIHNlc3Npb24gY29va2llIG9uIHN1Y2Nlc3MuXG4gICAgICB2YXIgciA9IGF3YWl0IHBvc3QoXCIvc2lnbi1pbi9lbWFpbC1vdHBcIiwge1xuICAgICAgICBlbWFpbDogZW1haWwsXG4gICAgICAgIG90cDogY29kZSxcbiAgICAgICAgbmFtZTogZW1haWwuc3BsaXQoXCJAXCIpWzBdLFxuICAgICAgfSk7XG4gICAgICBpZiAoci5vaykge1xuICAgICAgICBzYXkoXCJTaWduZWQgaW4uIExvYWRpbmfigKZcIik7XG4gICAgICAgIHdpbmRvdy5sb2NhdGlvbi5yZXBsYWNlKFJFVFVSTl9UTyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzYXkoZXJyb3JUZXh0KHIuZGF0YSwgXCJUaGF0IGNvZGUgd2FzIG5vdCBhY2NlcHRlZC4gVHJ5IGFnYWluLlwiKSwgdHJ1ZSk7XG4gICAgICAgIHN1Ym1pdC5kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKF9lKSB7XG4gICAgICBzYXkoXCJOZXR3b3JrIGVycm9yLiBUcnkgYWdhaW4uXCIsIHRydWUpO1xuICAgICAgc3VibWl0LmRpc2FibGVkID0gZmFsc2U7XG4gICAgfVxuICB9KTtcblxuICBiYWNrLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBmdW5jdGlvbiAoKSB7XG4gICAgY29kZUZvcm0uY2xhc3NMaXN0LmFkZChcImhpZGRlblwiKTtcbiAgICBlbWFpbEZvcm0uY2xhc3NMaXN0LnJlbW92ZShcImhpZGRlblwiKTtcbiAgICBjb2RlSW5wdXQudmFsdWUgPSBcIlwiO1xuICAgIHNheShcIlwiKTtcbiAgICBlbWFpbElucHV0LmZvY3VzKCk7XG4gIH0pO1xufSkoKTtcbjwvc2NyaXB0PlxuPC9ib2R5PlxuPC9odG1sPmA7XG59XG5cbmNvbnN0IEhUTUxfRVNDQVBFUzogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgXCImXCI6IFwiJmFtcDtcIixcbiAgXCI8XCI6IFwiJmx0O1wiLFxuICBcIj5cIjogXCImZ3Q7XCIsXG4gICdcIic6IFwiJnF1b3Q7XCIsXG4gIFwiJ1wiOiBcIiYjMzk7XCIsXG59O1xuXG5mdW5jdGlvbiBlc2NhcGVIdG1sKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gdmFsdWUucmVwbGFjZSgvWyY8PlwiJ10vZywgKGNoKSA9PiBIVE1MX0VTQ0FQRVNbY2hdID8/IGNoKTtcbn1cblxuLyoqIEVuY29kZSBhIHN0cmluZyBsaXRlcmFsIHdpdGhvdXQgYWxsb3dpbmcgaXQgdG8gdGVybWluYXRlIHRoZSBzdXJyb3VuZGluZyBzY3JpcHQuICovXG5mdW5jdGlvbiBqc29uRm9ySW5saW5lU2NyaXB0KHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodmFsdWUpXG4gICAgLnJlcGxhY2VBbGwoXCI8XCIsIFwiXFxcXHUwMDNjXCIpXG4gICAgLnJlcGxhY2VBbGwoXCI+XCIsIFwiXFxcXHUwMDNlXCIpXG4gICAgLnJlcGxhY2VBbGwoXCImXCIsIFwiXFxcXHUwMDI2XCIpXG4gICAgLnJlcGxhY2VBbGwoXCJcXHUyMDI4XCIsIFwiXFxcXHUyMDI4XCIpXG4gICAgLnJlcGxhY2VBbGwoXCJcXHUyMDI5XCIsIFwiXFxcXHUyMDI5XCIpO1xufVxuIl19
package/package.json CHANGED
@@ -18,21 +18,21 @@
18
18
  "projen": "projen"
19
19
  },
20
20
  "devDependencies": {
21
- "@dbx-tools/email": "0.6.114",
21
+ "@dbx-tools/email": "0.6.116",
22
22
  "@types/bun": "^1.3.14",
23
23
  "@types/node": "^24.6.0",
24
24
  "typescript": "^5.9.3"
25
25
  },
26
26
  "peerDependencies": {
27
- "@dbx-tools/email": "0.6.114"
27
+ "@dbx-tools/email": "0.6.116"
28
28
  },
29
29
  "dependencies": {
30
30
  "@databricks/appkit": "^0.60.0",
31
- "@dbx-tools/appkit": "0.6.114",
32
- "@dbx-tools/auth": "0.6.114",
33
- "@dbx-tools/core": "0.6.114",
34
- "@dbx-tools/shared-auth": "0.6.114",
35
- "@dbx-tools/shared-core": "0.6.114",
31
+ "@dbx-tools/appkit": "0.6.116",
32
+ "@dbx-tools/auth": "0.6.116",
33
+ "@dbx-tools/core": "0.6.116",
34
+ "@dbx-tools/shared-auth": "0.6.116",
35
+ "@dbx-tools/shared-core": "0.6.116",
36
36
  "http-proxy-3": "^1.23.1"
37
37
  },
38
38
  "main": "./lib/index.js",
@@ -49,7 +49,7 @@
49
49
  "./package.json": "./package.json"
50
50
  }
51
51
  },
52
- "version": "0.6.114",
52
+ "version": "0.6.116",
53
53
  "types": "./lib/index.d.ts",
54
54
  "type": "module",
55
55
  "exports": {
package/src/gate.ts CHANGED
@@ -258,6 +258,61 @@ export const UNAUTHORIZED_BODY = {
258
258
  loginPath: AUTH_PREFIX,
259
259
  } as const;
260
260
 
261
+ /** Restrict a post-login destination to one same-origin application path. */
262
+ export function normalizeReturnTo(value: string | undefined): string {
263
+ const candidate = value?.trim();
264
+ if (!candidate?.startsWith("/") || candidate.startsWith("//") || candidate.includes("\\")) {
265
+ return "/";
266
+ }
267
+ const parsed = new URL(candidate, "http://app.local");
268
+ return `${parsed.pathname}${parsed.search}${parsed.hash}`;
269
+ }
270
+
271
+ /** Resolve the page a browser should return to after tunnel authentication. */
272
+ export function requestReturnTo(req: IncomingMessage): string {
273
+ if (wantsLoginPage(req)) {
274
+ const originalUrl = (req as IncomingMessage & { originalUrl?: string }).originalUrl;
275
+ return normalizeReturnTo(originalUrl || req.url);
276
+ }
277
+ const referer = String(req.headers.referer ?? "").trim();
278
+ if (!referer) return "/";
279
+ try {
280
+ const parsed = new URL(referer);
281
+ const host = String(req.headers.host ?? "").toLowerCase();
282
+ if (parsed.host.toLowerCase() !== host) return "/";
283
+ return normalizeReturnTo(`${parsed.pathname}${parsed.search}${parsed.hash}`);
284
+ } catch {
285
+ return "/";
286
+ }
287
+ }
288
+
289
+ /** Build the hosted login URL with a validated same-origin return path. */
290
+ export function loginPath(req: IncomingMessage): string {
291
+ return `${AUTH_PREFIX}?returnTo=${encodeURIComponent(requestReturnTo(req))}`;
292
+ }
293
+
294
+ /** Build a denied JSON response that preserves the calling page. */
295
+ export function unauthorizedBody(req: IncomingMessage): {
296
+ error: typeof UNAUTHORIZED_BODY.error;
297
+ loginPath: string;
298
+ } {
299
+ return { ...UNAUTHORIZED_BODY, loginPath: loginPath(req) };
300
+ }
301
+
302
+ /** Return the validated destination carried by a hosted login URL. */
303
+ export function loginReturnTo(req: IncomingMessage): string {
304
+ const url = new URL(req.url ?? AUTH_PREFIX, "http://app.local");
305
+ return normalizeReturnTo(url.searchParams.get("returnTo") ?? "/");
306
+ }
307
+
308
+ /** Whether this request asks for the hosted login document itself. */
309
+ export function wantsHostedLogin(req: IncomingMessage): boolean {
310
+ const method = (req.method ?? "GET").toUpperCase();
311
+ if (method !== "GET" && method !== "HEAD") return false;
312
+ const path = (req.url ?? "/").split("?")[0] ?? "/";
313
+ return path === AUTH_PREFIX && String(req.headers.accept ?? "").includes("text/html");
314
+ }
315
+
261
316
  /**
262
317
  * Whether a denied request is a top-level BROWSER NAVIGATION that should be
263
318
  * answered with the hosted login page rather than a 401.
@@ -308,6 +363,18 @@ export function mountGate(
308
363
  }
309
364
  return;
310
365
  }
366
+ if (wantsHostedLogin(req)) {
367
+ res
368
+ .status(200)
369
+ .type("html")
370
+ .send(
371
+ loginPageHtml({
372
+ brandName: brandName ?? "Databricks App",
373
+ returnTo: loginReturnTo(req),
374
+ }),
375
+ );
376
+ return;
377
+ }
311
378
  await sendWebResponse(res, await gate.handler(await webRequest(req)));
312
379
  }) as RequestHandler;
313
380
  addMiddleware(AUTH_PREFIX, authHandler);
@@ -317,9 +384,20 @@ export function mountGate(
317
384
  const gateMiddleware = (async (req, res, next) => {
318
385
  const action = await gateRequest(req, { gate, publicDomain, headerPolicy, gatePaths });
319
386
  if (action === "deny" && wantsLoginPage(req)) {
320
- res.status(401).type("html").send(loginPageHtml({ brandName: brandName ?? "Databricks App" }));
321
- } else if (action === "deny") res.status(401).json(UNAUTHORIZED_BODY);
322
- else next();
387
+ res
388
+ .status(401)
389
+ .type("html")
390
+ .send(
391
+ loginPageHtml({
392
+ brandName: brandName ?? "Databricks App",
393
+ returnTo: requestReturnTo(req),
394
+ }),
395
+ );
396
+ } else if (action === "deny") {
397
+ res.status(401).json(unauthorizedBody(req));
398
+ } else {
399
+ next();
400
+ }
323
401
  }) as RequestHandler;
324
402
 
325
403
  addMiddleware("/", gateMiddleware);
package/src/login-page.ts CHANGED
@@ -19,14 +19,15 @@ import { AUTH_PREFIX } from "./gate.ts";
19
19
  export interface LoginPageOptions {
20
20
  /** Product/brand name shown in the heading. */
21
21
  brandName: string;
22
+ /** Validated same-origin path loaded after authentication succeeds. */
23
+ returnTo: string;
22
24
  }
23
25
 
24
26
  /** The login page HTML for a `text/html` request to a gated path with no session. */
25
27
  export function loginPageHtml(options: LoginPageOptions): string {
26
28
  const brand = escapeHtml(options.brandName);
27
- // AUTH_PREFIX is a fixed constant, not user input, but JSON-encode it so the
28
- // inlined script is always valid regardless of its value.
29
- const prefix = JSON.stringify(AUTH_PREFIX);
29
+ const prefix = jsonForInlineScript(AUTH_PREFIX);
30
+ const returnTo = jsonForInlineScript(options.returnTo);
30
31
  return `<!doctype html>
31
32
  <html lang="en">
32
33
  <head>
@@ -106,6 +107,11 @@ export function loginPageHtml(options: LoginPageOptions): string {
106
107
  <script>
107
108
  (function () {
108
109
  var PREFIX = ${prefix};
110
+ var RETURN_TO = ${returnTo};
111
+ // An in-place login can preserve browser-only hash state that never reached the server.
112
+ if (window.location.pathname !== PREFIX) {
113
+ RETURN_TO = window.location.pathname + window.location.search + window.location.hash;
114
+ }
109
115
  var emailForm = document.getElementById("email-form");
110
116
  var codeForm = document.getElementById("code-form");
111
117
  var emailInput = document.getElementById("email");
@@ -179,9 +185,7 @@ export function loginPageHtml(options: LoginPageOptions): string {
179
185
  });
180
186
  if (r.ok) {
181
187
  say("Signed in. Loading…");
182
- // The session cookie is set; reload so the now-authenticated request
183
- // reaches the app.
184
- window.location.reload();
188
+ window.location.replace(RETURN_TO);
185
189
  } else {
186
190
  say(errorText(r.data, "That code was not accepted. Try again."), true);
187
191
  submit.disabled = false;
@@ -216,3 +220,13 @@ const HTML_ESCAPES: Record<string, string> = {
216
220
  function escapeHtml(value: string): string {
217
221
  return value.replace(/[&<>"']/g, (ch) => HTML_ESCAPES[ch] ?? ch);
218
222
  }
223
+
224
+ /** Encode a string literal without allowing it to terminate the surrounding script. */
225
+ function jsonForInlineScript(value: string): string {
226
+ return JSON.stringify(value)
227
+ .replaceAll("<", "\\u003c")
228
+ .replaceAll(">", "\\u003e")
229
+ .replaceAll("&", "\\u0026")
230
+ .replaceAll("\u2028", "\\u2028")
231
+ .replaceAll("\u2029", "\\u2029");
232
+ }