sliftutils 1.7.128 → 1.7.129

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 (51) hide show
  1. package/bin/addmachine.js +9 -0
  2. package/bin/machineclient.js +9 -0
  3. package/bin/machineserver.js +10 -0
  4. package/index.d.ts +15 -0
  5. package/misc/dist/ownIPs.ts.cache +43 -0
  6. package/misc/dist/strings.ts.cache +2 -2
  7. package/misc/https/dist/certs.ts.cache +2 -2
  8. package/misc/https/dist/persistentLocalStorage.ts.cache +2 -2
  9. package/misc/ownIPs.d.ts +11 -0
  10. package/misc/ownIPs.ts +34 -0
  11. package/package.json +9 -3
  12. package/security/authorizedKeys/authorizedKeys.ts +34 -0
  13. package/security/authorizedKeys/daemon/authLog.ts +12 -5
  14. package/security/authorizedKeys/daemon/changes.ts +16 -1
  15. package/security/authorizedKeys/daemon/daemon.ts +43 -34
  16. package/security/authorizedKeys/daemon/dist/changes.ts.cache +40 -0
  17. package/security/authorizedKeys/daemon/dist/git.ts.cache +121 -0
  18. package/security/authorizedKeys/daemon/dist/notify.ts.cache +39 -0
  19. package/security/authorizedKeys/daemon/dist/paths.ts.cache +29 -0
  20. package/security/authorizedKeys/daemon/dist/repoFiles.ts.cache +114 -0
  21. package/security/authorizedKeys/daemon/dist/revocation.ts.cache +0 -0
  22. package/security/authorizedKeys/daemon/dist/sessions.ts.cache +147 -0
  23. package/security/authorizedKeys/daemon/dist/state.ts.cache +74 -0
  24. package/security/authorizedKeys/daemon/dist/trust.ts.cache +295 -0
  25. package/security/authorizedKeys/daemon/notify.ts +8 -2
  26. package/security/authorizedKeys/daemon/repoFiles.ts +118 -0
  27. package/security/authorizedKeys/daemon/revocation.ts +0 -0
  28. package/security/authorizedKeys/daemon/rootKeys.ts +77 -10
  29. package/security/authorizedKeys/daemon/state.ts +25 -7
  30. package/security/authorizedKeys/daemon/trust.ts +37 -16
  31. package/security/authorizedKeys/daemon/userKeys.ts +5 -4
  32. package/security/authorizedKeys/dist/authorizedKeys.ts.cache +37 -3
  33. package/security/authorizedKeys/dist/revokeSource.ts.cache +17 -4
  34. package/security/authorizedKeys/dist/sources.ts.cache +52 -8
  35. package/security/authorizedKeys/dist/unrevoke.ts.cache +113 -17
  36. package/security/authorizedKeys/secureSSH.ts +39 -21
  37. package/security/authorizedKeys/unrevoke.ts +159 -8
  38. package/security/helpers/dist/remoteSSH.ts.cache +19 -9
  39. package/security/machines/addMachine.ts +83 -0
  40. package/security/machines/dist/addMachine.ts.cache +88 -0
  41. package/security/machines/dist/identity.ts.cache +176 -0
  42. package/security/machines/dist/machines.ts.cache +322 -0
  43. package/security/machines/dist/trustClient.ts.cache +48 -0
  44. package/security/machines/dist/trustState.ts.cache +57 -0
  45. package/security/machines/identity.ts +199 -0
  46. package/security/machines/machines.ts +355 -0
  47. package/security/machines/trustClient.ts +51 -0
  48. package/security/machines/trustServer.ts +85 -0
  49. package/security/machines/trustState.ts +53 -0
  50. package/security/notifications/discord.ts +14 -5
  51. package/security/notifications/dist/discord.ts.cache +17 -8
@@ -0,0 +1,85 @@
1
+ import http from "http";
2
+ import { verifyTrustPacket } from "./identity";
3
+ import { isMachineAccepted } from "./machines";
4
+
5
+ // A demonstration of machine trust, and the smallest thing that exercises it end to end: a client
6
+ // proves which machine it is, and this answers whether that machine is trusted from the address it
7
+ // is actually talking from.
8
+ //
9
+ // Plain http on purpose. Nothing here is secret - the packet proves who the client is by signature
10
+ // rather than by the channel, and the answer is a yes or no about a machine the caller already
11
+ // knows the id of.
12
+ const DEFAULT_PORT = 47812;
13
+ const TRUST_PATH = "/trusted";
14
+ const MAX_BODY_LENGTH = 64 * 1024;
15
+
16
+ /** The address the client is actually talking from. Not read from anything the client sent,
17
+ because that is the one half of the pair it must not get to choose. */
18
+ function addressOf(request: http.IncomingMessage) {
19
+ let address = request.socket.remoteAddress || "";
20
+ // Node reports IPv4 over a dual stack socket this way.
21
+ return address.replace(/^::ffff:/, "");
22
+ }
23
+
24
+ async function readBody(request: http.IncomingMessage) {
25
+ let chunks: Buffer[] = [];
26
+ let length = 0;
27
+ for await (let chunk of request) {
28
+ length += chunk.length;
29
+ if (length > MAX_BODY_LENGTH) {
30
+ throw new Error(`Expected at most ${MAX_BODY_LENGTH} bytes, was more`);
31
+ }
32
+ chunks.push(chunk);
33
+ }
34
+ return Buffer.concat(chunks).toString("utf8");
35
+ }
36
+
37
+ export function startTrustServer(config: { port: number }) {
38
+ let server = http.createServer((request, response) => {
39
+ let answer = async () => {
40
+ if (request.url !== TRUST_PATH) {
41
+ return { status: 404, body: { error: `POST a trust packet to ${TRUST_PATH}` } };
42
+ }
43
+ let packet = JSON.parse(await readBody(request));
44
+ let ip = addressOf(request);
45
+ let verified = verifyTrustPacket(packet);
46
+ if (!verified.valid) {
47
+ // Not a rejection of the machine, a packet that does not prove anything about one.
48
+ return { status: 400, body: { trusted: false, ip, reason: verified.problem } };
49
+ }
50
+ let trusted = await isMachineAccepted({ machineId: packet.machineId, ip });
51
+ return {
52
+ status: 200,
53
+ body: {
54
+ trusted,
55
+ machineId: packet.machineId,
56
+ ip,
57
+ reason: trusted && "" || "that machine is not trusted from that address",
58
+ },
59
+ };
60
+ };
61
+ answer().then(result => {
62
+ console.log(`${request.method} ${request.url} from ${addressOf(request)}: ${JSON.stringify(result.body)}`);
63
+ response.writeHead(result.status, { "Content-Type": "application/json" });
64
+ response.end(JSON.stringify(result.body, undefined, 4));
65
+ }).catch(e => {
66
+ console.log(`${request.method} ${request.url} from ${addressOf(request)} failed. ${e}`);
67
+ response.writeHead(500, { "Content-Type": "application/json" });
68
+ response.end(JSON.stringify({ trusted: false, error: `${e}` }, undefined, 4));
69
+ });
70
+ });
71
+ server.listen(config.port);
72
+ return server;
73
+ }
74
+
75
+ export async function main() {
76
+ let port = Number(process.argv[2] || DEFAULT_PORT);
77
+ if (!Number.isFinite(port)) {
78
+ throw new Error(`Usage: yarn machineserver [port]`);
79
+ }
80
+ startTrustServer({ port });
81
+ console.log(`Answering trust checks on http://0.0.0.0:${port}${TRUST_PATH}`);
82
+ console.log(`A client asks with: yarn machineclient http://<this machine>:${port}`);
83
+ // Left running. Nothing else to do here, the server is the program.
84
+ await new Promise(() => { });
85
+ }
@@ -0,0 +1,53 @@
1
+ import fs from "fs/promises";
2
+ import path from "path";
3
+ import { UNREVOKE_DELAY } from "../authorizedKeys/daemon/paths";
4
+ import { keysDir } from "../authorizedKeys/sources";
5
+ import { messageTimestamp } from "../notifications/discord";
6
+
7
+ // When this machine first saw each unrevoke, by unrevoke id.
8
+ //
9
+ // The same rule the ssh keys get, for the same reason: an unrevoke waits an hour before it counts,
10
+ // so a signing key that was itself stolen cannot instantly undo the revocation that shut it out.
11
+ // Counted from when we first saw it, never from a time the file states - whoever wrote the file
12
+ // chooses that, and would choose an hour ago.
13
+ //
14
+ // On disk, because a check runs in whatever process happens to be asking. Measuring from process
15
+ // start would restart the hour on every request and the unrevoke would never arrive. Kept beside
16
+ // the repo keys rather than in the daemon's state, because this has to work on a machine with no
17
+ // daemon, which is most of them.
18
+ const FIRST_SEEN_FILE = "machine-unrevokes.json";
19
+
20
+ function firstSeenPath() {
21
+ return path.join(keysDir(), FIRST_SEEN_FILE);
22
+ }
23
+
24
+ async function readFirstSeen(): Promise<{ [unrevokeId: string]: number }> {
25
+ try {
26
+ return JSON.parse(await fs.readFile(firstSeenPath(), "utf8"));
27
+ } catch (e) {
28
+ // Never written, or unreadable. Either way nothing has been seen before now.
29
+ return {};
30
+ }
31
+ }
32
+
33
+ /** Whether an unrevoke has waited out its hour, recording the first sighting if this is one.
34
+
35
+ Returns false the first time, which is the point: seeing an unrevoke is not the same as
36
+ honouring it. */
37
+ export async function unrevokeInEffect(unrevokeId: string) {
38
+ let firstSeen = await readFirstSeen();
39
+ let seenAt = firstSeen[unrevokeId];
40
+ if (!seenAt) {
41
+ seenAt = Date.now();
42
+ firstSeen[unrevokeId] = seenAt;
43
+ await fs.mkdir(path.dirname(firstSeenPath()), { recursive: true, mode: 0o700 });
44
+ await fs.writeFile(firstSeenPath(), JSON.stringify(firstSeen, undefined, 4) + "\n");
45
+ }
46
+ if (Date.now() - seenAt < UNREVOKE_DELAY) {
47
+ console.log(
48
+ `Holding the unrevoke ${unrevokeId} until ${messageTimestamp(new Date(seenAt + UNREVOKE_DELAY))}`
49
+ );
50
+ return false;
51
+ }
52
+ return true;
53
+ }
@@ -89,8 +89,9 @@ export function messageTimestamp(now: Date) {
89
89
 
90
90
  async function postToWebhook(webhookURL: string, message: string) {
91
91
  // Stamped once rather than per attempt, so a retry says when the thing happened rather than
92
- // when we last managed to get it out.
93
- let content = `\`${messageTimestamp(new Date())}\` ${message}`;
92
+ // when we last managed to get it out. At the end, because the first line of a message is the
93
+ // notification preview and a timestamp there would spend it saying nothing.
94
+ let content = `${message} · \`${messageTimestamp(new Date())}\``;
94
95
  if (content.length > DISCORD_MESSAGE_LIMIT) {
95
96
  content = content.slice(0, DISCORD_MESSAGE_LIMIT - 3) + "...";
96
97
  }
@@ -149,9 +150,11 @@ async function checkWebhookFileChanged() {
149
150
  try {
150
151
  await queueSend(
151
152
  state.webhookURL,
152
- `**portsecure**: the Discord webhook in \`${state.filePath}\` changed to`
153
- + ` \`${redactWebhookURL(newWebhookURL)}\`.`
154
- + ` Notifications are moving to the new webhook and this channel will stop receiving them.`
153
+ `**portsecure**: **NOTIFICATIONS ARE MOVING TO ANOTHER CHANNEL**`
154
+ + `\n\nThis channel stops receiving them now. If that was not you, somebody with access`
155
+ + ` to this machine just redirected its alerts.`
156
+ + `\n\nnew webhook: \`${redactWebhookURL(newWebhookURL)}\``
157
+ + `\nset in: \`${state.filePath}\``
155
158
  );
156
159
  } catch (e) {
157
160
  console.error(`portsecure: failed to warn the old Discord webhook about the change. ${e}`);
@@ -198,6 +201,12 @@ export async function sendDiscordNotification(message: string) {
198
201
  await queueSend(state.webhookURL, message);
199
202
  }
200
203
 
204
+ /** Whether notifications are set up in this process. For code that may run outside the daemon,
205
+ where sending is worth doing if it can be and not worth failing over if it cannot. */
206
+ export function areDiscordNotificationsConfigured() {
207
+ return !!notificationState;
208
+ }
209
+
201
210
  export function stopDiscordNotifications() {
202
211
  if (!notificationState) {
203
212
  return;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
6
- //exports.stopDiscordNotifications = exports.sendDiscordNotification = exports.configureDiscordNotifications = exports.sendToWebhookURL = exports.messageTimestamp = exports.formatWebhookFile = exports.redactWebhookURL = exports.parseWebhookFile = exports.DEFAULT_WEBHOOK_FILE_PATH = void 0;
6
+ //exports.stopDiscordNotifications = exports.areDiscordNotificationsConfigured = exports.sendDiscordNotification = exports.configureDiscordNotifications = exports.sendToWebhookURL = exports.messageTimestamp = exports.formatWebhookFile = exports.redactWebhookURL = exports.parseWebhookFile = exports.DEFAULT_WEBHOOK_FILE_PATH = void 0;
7
7
  const promises_1 = __importDefault(require("fs/promises"));
8
8
  // PORTED CODE: security/authorizedKeys/daemon/portsecureDaemon.js embeds a hand port of this file in plain JS, so the
9
9
  // daemon can run with no dependencies. The two are expected to behave identically - if you change
@@ -84,8 +84,9 @@ function messageTimestamp(now) {
84
84
  exports.messageTimestamp = messageTimestamp;
85
85
  async function postToWebhook(webhookURL, message) {
86
86
  // Stamped once rather than per attempt, so a retry says when the thing happened rather than
87
- // when we last managed to get it out.
88
- let content = `\`${messageTimestamp(new Date())}\` ${message}`;
87
+ // when we last managed to get it out. At the end, because the first line of a message is the
88
+ // notification preview and a timestamp there would spend it saying nothing.
89
+ let content = `${message} · \`${messageTimestamp(new Date())}\``;
89
90
  if (content.length > DISCORD_MESSAGE_LIMIT) {
90
91
  content = content.slice(0, DISCORD_MESSAGE_LIMIT - 3) + "...";
91
92
  }
@@ -139,9 +140,11 @@ async function checkWebhookFileChanged() {
139
140
  // Warn the old channel first, with the new webhook redacted, so a stolen old webhook does not
140
141
  // hand the attacker a usable new one.
141
142
  try {
142
- await queueSend(state.webhookURL, `**portsecure**: the Discord webhook in \`${state.filePath}\` changed to`
143
- + ` \`${redactWebhookURL(newWebhookURL)}\`.`
144
- + ` Notifications are moving to the new webhook and this channel will stop receiving them.`);
143
+ await queueSend(state.webhookURL, `**portsecure**: **NOTIFICATIONS ARE MOVING TO ANOTHER CHANNEL**`
144
+ + `\n\nThis channel stops receiving them now. If that was not you, somebody with access`
145
+ + ` to this machine just redirected its alerts.`
146
+ + `\n\nnew webhook: \`${redactWebhookURL(newWebhookURL)}\``
147
+ + `\nset in: \`${state.filePath}\``);
145
148
  }
146
149
  catch (e) {
147
150
  console.error(`portsecure: failed to warn the old Discord webhook about the change. ${e}`);
@@ -185,6 +188,12 @@ async function sendDiscordNotification(message) {
185
188
  await queueSend(state.webhookURL, message);
186
189
  }
187
190
  exports.sendDiscordNotification = sendDiscordNotification;
191
+ /** Whether notifications are set up in this process. For code that may run outside the daemon,
192
+ where sending is worth doing if it can be and not worth failing over if it cannot. */
193
+ function areDiscordNotificationsConfigured() {
194
+ return !!notificationState;
195
+ }
196
+ exports.areDiscordNotificationsConfigured = areDiscordNotificationsConfigured;
188
197
  function stopDiscordNotifications() {
189
198
  if (!notificationState) {
190
199
  return;
@@ -193,5 +202,5 @@ function stopDiscordNotifications() {
193
202
  notificationState = undefined;
194
203
  }
195
204
  exports.stopDiscordNotifications = stopDiscordNotifications;
196
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlzY29yZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImRpc2NvcmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsMkRBQTZCO0FBRTdCLHNIQUFzSDtBQUN0SCxrR0FBa0c7QUFDbEcsOENBQThDO0FBRWpDLFFBQUEseUJBQXlCLEdBQUcsaUNBQWlDLENBQUM7QUFDM0UsTUFBTSxzQkFBc0IsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUM3QyxNQUFNLHNCQUFzQixHQUFHO0lBQzNCLG1DQUFtQztJQUNuQyxzQ0FBc0M7SUFDdEMsMENBQTBDO0NBQzdDLENBQUM7QUFDRixNQUFNLHFCQUFxQixHQUFHLElBQUksQ0FBQztBQUNuQyxNQUFNLHFCQUFxQixHQUFHLEdBQUcsQ0FBQztBQUNsQyxNQUFNLGlCQUFpQixHQUFHLENBQUMsQ0FBQztBQUM1QixNQUFNLHNCQUFzQixHQUFHLENBQUMsQ0FBQztBQUNqQyxNQUFNLHVCQUF1QixHQUFHLENBQUMsR0FBRyxJQUFJLENBQUM7QUFFekMsSUFBSSxpQkFJUyxDQUFDO0FBRWQsc0ZBQXNGO0FBQ3RGLDRDQUE0QztBQUM1QyxJQUFJLFNBQVMsR0FBcUIsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO0FBRXBEO3NDQUNzQztBQUN0QyxTQUFnQixnQkFBZ0IsQ0FBQyxNQUFnRDtJQUM3RSxJQUFJLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxHQUFHLE1BQU0sQ0FBQztJQUN0QyxJQUFJLEtBQUssR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN4RyxJQUFJLFVBQVUsR0FBRyxL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RUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsa0RBQWtELENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMvRyxDQUFDLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDbEIsZ0VBQWdFO0lBQ2hFLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNuQixpQkFBaUIsR0FBRyxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLENBQUM7SUFDekQsT0FBTyxFQUFFLFFBQVEsRUFBRSxhQUFhLEVBQUUsQ0FBQztBQUN2QyxDQUFDO0FBdkJELHNFQXVCQztBQUVELGdHQUFnRztBQUNoRyxpR0FBaUc7QUFDakcsdUVBQXVFO0FBQ2hFLEtBQUssVUFBVSx1QkFBdUIsQ0FBQyxPQUFlO0lBQ3pELElBQUksS0FBSyxHQUFHLGlCQUFpQixDQUFDO0lBQzlCLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNULE1BQU0sSUFBSSxLQUFLLENBQUMsK0ZBQStGLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLHFCQUFxQixDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzlKLENBQUM7SUFDRCxNQUFNLFNBQVMsQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQy9DLENBQUM7QUFORCwwREFNQztBQUVELFNBQWdCLHdCQUF3QjtJQUNwQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUNyQixPQUFPO0lBQ1gsQ0FBQztJQUNELGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUM1QyxpQkFBaUIsR0FBRyxTQUFTLENBQUM7QUFDbEMsQ0FBQztBQU5ELDREQU1DIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGZzIGZyb20gXCJmcy9wcm9taXNlc1wiO1xuXG4vLyBQT1JURUQgQ09ERTogc2VjdXJpdHkvYXV0aG9yaXplZEtleXMvZGFlbW9uL3BvcnRzZWN1cmVEYWVtb24uanMgZW1iZWRzIGEgaGFuZCBwb3J0IG9mIHRoaXMgZmlsZSBpbiBwbGFpbiBKUywgc28gdGhlXG4vLyBkYWVtb24gY2FuIHJ1biB3aXRoIG5vIGRlcGVuZGVuY2llcy4gVGhlIHR3byBhcmUgZXhwZWN0ZWQgdG8gYmVoYXZlIGlkZW50aWNhbGx5IC0gaWYgeW91IGNoYW5nZVxuLy8gb25lLCBtYWtlIHRoZSBtYXRjaGluZyBjaGFuZ2UgaW4gdGhlIG90aGVyLlxuXG5leHBvcnQgY29uc3QgREVGQVVMVF9XRUJIT09LX0ZJTEVfUEFUSCA9IFwiL2V0Yy9wb3J0c2VjdXJlL2Rpc2NvcmQtd2ViaG9va1wiO1xuY29uc3QgREVGQVVMVF9DSEVDS19JTlRFUlZBTCA9IDUgKiA2MCAqIDEwMDA7XG5jb25zdCBWQUxJRF9XRUJIT09LX1BSRUZJWEVTID0gW1xuICAgIFwiaHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvXCIsXG4gICAgXCJodHRwczovL2Rpc2NvcmRhcHAuY29tL2FwaS93ZWJob29rcy9cIixcbiAgICBcImh0dHBzOi8vY2FuYXJ5LmRpc2NvcmQuY29tL2FwaS93ZWJob29rcy9cIixcbl07XG5jb25zdCBESVNDT1JEX01FU1NBR0VfTElNSVQgPSAyMDAwO1xuY29uc3QgTUFYX0VSUk9SX0JPRFlfTEVOR1RIID0gNTAwO1xuY29uc3QgTUFYX1NFTkRfQVRURU1QVFMgPSAzO1xuY29uc3QgUkVEQUNURURfVE9LRU5fVklTSUJMRSA9IDg7XG5jb25zdCBERUZBVUxUX1JBVEVfTElNSVRfV0FJVCA9IDIgKiAxMDAwO1xuXG5sZXQgbm90aWZpY2F0aW9uU3RhdGU6IHtcbiAgICBmaWxlUGF0aDogc3RyaW5nO1xuICAgIHdlYmhvb2tVUkw6IHN0cmluZztcbiAgICBjaGVja1RpbWVyOiBOb2RlSlMuVGltZW91dDtcbn0gfCB1bmRlZmluZWQ7XG5cbi8vIERpc2NvcmQgd2ViaG9va3MgYXJlIHJhdGUgbGltaXRlZCAocm91Z2hseSA1IHJlcXVlc3RzIHBlciAyIHNlY29uZHMpLCBzbyBldmVyeSBzZW5kXG4vLyBnb2VzIHRocm91Z2ggb25lIGNoYWluIGluc3RlYWQgb2YgcmFjaW5nLlxubGV0IHNlbmRDaGFpbjogUHJvbWlzZTx1bmtub3duPiA9IFByb21pc2UucmVzb2x2ZSgpO1xuXG4vKiogUHVsbHMgdGhlIHdlYmhvb2sgVVJMIG91dCBvZiB3ZWJob29rIGZpbGUgY29udGVudHMuIGBzb3VyY2VOYW1lYCBvbmx5IGFwcGVhcnMgaW4gZXJyb3JzLCBzb1xuICAgIGNhbGxlcnMgY2FuIG5hbWUgYSByZW1vdGUgcGF0aC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVdlYmhvb2tGaWxlKGNvbmZpZzogeyBjb250ZW50czogc3RyaW5nOyBzb3VyY2VOYW1lOiBzdHJpbmcgfSkge1xuICAgIGxldCB7IGNvbnRlbnRzLCBzb3VyY2VOYW1lIH0gPSBjb25maWc7XG4gICAgbGV0IGxpbmVzID0gY29udGVudHMuc3BsaXQoXCJcXG5cIikubWFwKGxpbmUgPT4gbGluZS50cmltKCkpLmZpbHRlcihsaW5lID0+IGxpbmUgJiYgIWxpbmUuc3RhcnRzV2l0aChcIiNcIikpO1xuICAgIGxldCB3ZWJob29rVVJMID0gbGluZXNbMF07XG4gICAgaWYgKCF3ZWJob29rVVJMKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgYSBEaXNjb3JkIHdlYmhvb2sgVVJMIGluICR7c291cmNlTmFtZX0sIHRoZSBmaWxlIGhhcyBubyB1c2FibGUgbGluZXNgKTtcbiAgICB9XG4gICAgaWYgKCFWQUxJRF9XRUJIT09LX1BSRUZJWEVTLnNvbWUocHJlZml4ID0+IHdlYmhvb2tVUkwuc3RhcnRzV2l0aChwcmVmaXgpKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgRXhwZWN0ZWQgYSBEaXNjb3JkIHdlYmhvb2sgVVJMIHN0YXJ0aW5nIHdpdGggb25lIG9mICR7VkFMSURfV0VCSE9PS19QUkVGSVhFUy5qb2luKFwiLCBcIil9LCBgXG4gICAgICAgICAgICArIGB3YXMgJHt3ZWJob29rVVJMLnNsaWNlKDAsIE1BWF9FUlJPUl9CT0RZX0xFTkdUSCl9IChpbiAke3NvdXJjZU5hbWV9KWBcbiAgICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHdlYmhvb2tVUkw7XG59XG5cbi8qKiBLZWVwcyB0aGUgaWQgYW5kIGJvdGggZW5kcyBvZiB0aGUgdG9rZW4sIHNvIGEgcmVhZGVyIGNhbiBjb25maXJtIHdoaWNoIHdlYmhvb2sgcmVwbGFjZWQgdGhlaXJzXG4gICAgd2l0aG91dCByZWNlaXZpbmcgb25lIHRoZXkgY291bGQgcG9zdCB0by4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWRhY3RXZWJob29rVVJMKHdlYmhvb2tVUkw6IHN0cmluZykge1xuICAgIGxldCBzZXBhcmF0b3JJbmRleCA9IHdlYmhvb2tVUkwubGFzdEluZGV4T2YoXCIvXCIpO1xuICAgIGxldCBiYXNlID0gd2ViaG9va1VSTC5zbGljZSgwLCBzZXBhcmF0b3JJbmRleCArIDEpO1xuICAgIGxldCB0b2tlbiA9IHdlYmhvb2tVUkwuc2xpY2Uoc2VwYXJhdG9ySW5kZXggKyAxKTtcbiAgICBpZiAodG9rZW4ubGVuZ3RoIDw9IFJFREFDVEVEX1RPS0VOX1ZJU0lCTEUgKiAyKSB7XG4gICAgICAgIC8vIFRvbyBzaG9ydCB0byBzaG93IGJvdGggZW5kcyB3aXRob3V0IGdpdmluZyBhd2F5IHRoZSB3aG9sZSB0b2tlbi5cbiAgICAgICAgcmV0dXJuIGAke2Jhc2V9JHt0b2tlbi5zbGljZSgwLCBSRURBQ1RFRF9UT0tFTl9WSVNJQkxFKX0uLi5gO1xuICAgIH1cbiAgICByZXR1cm4gYCR7YmFzZX0ke3Rva2VuLnNsaWNlKDAsIFJFREFDVEVEX1RPS0VOX1ZJU0lCTEUpfS4uLiR7dG9rZW4uc2xpY2UoLVJFREFDVEVEX1RPS0VOX1ZJU0lCTEUpfWA7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXRXZWJob29rRmlsZSh3ZWJob29rVVJMOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gYCMgcG9ydHNlY3VyZSBEaXNjb3JkIHdlYmhvb2suIEZpcnN0IG5vbi1jb21tZW50IGxpbmUgaXMgdXNlZC5cXG4ke3dlYmhvb2tVUkx9XFxuYDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVhZFdlYmhvb2tGaWxlKGZpbGVQYXRoOiBzdHJpbmcpIHtcbiAgICBsZXQgY29udGVudHM7XG4gICAgdHJ5IHtcbiAgICAgICAgY29udGVudHMgPSBhd2FpdCBmcy5yZWFkRmlsZShmaWxlUGF0aCwgXCJ1dGY4XCIpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBhIHJlYWRhYmxlIERpc2NvcmQgd2ViaG9vayBmaWxlIGF0ICR7ZmlsZVBhdGh9LCAke2V9YCk7XG4gICAgfVxuICAgIHJldHVybiBwYXJzZVdlYmhvb2tGaWxlKHsgY29udGVudHMsIHNvdXJjZU5hbWU6IGZpbGVQYXRoIH0pO1xufVxuXG4vKiogV2hlbiB0aGUgbWVzc2FnZSB3YXMgc2VudCwgaW4gdGhlIHNlbmRpbmcgbWFjaGluZSdzIG93biB0aW1lIHpvbmUuIERpc2NvcmQgc2hvd3Mgd2hlbiBpdFxuICAgIHJlY2VpdmVkIHNvbWV0aGluZywgd2hpY2ggaXMgbm90IHRoZSBzYW1lIHRoaW5nIHdoZW4gYSBtYWNoaW5lIGhhcyBiZWVuIG9mZmxpbmUgb3IgYSBzZW5kIGhhc1xuICAgIGJlZW4gcmV0cmllZCwgYW5kIHRoZSB6b25lIG1hdHRlcnMgd2hlbiB0aGUgbWFjaGluZXMgYXJlIG5vdCBhbGwgaW4gb25lIHBsYWNlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1lc3NhZ2VUaW1lc3RhbXAobm93OiBEYXRlKSB7XG4gICAgbGV0IGRhdGUgPSBub3cudG9Mb2NhbGVEYXRlU3RyaW5nKFwiZW4tQ0FcIik7XG4gICAgbGV0IHRpbWUgPSBub3cudG9Mb2NhbGVUaW1lU3RyaW5nKFwiZW4tVVNcIiwge1xuICAgICAgICBob3VyOiBcIjItZGlnaXRcIixcbiAgICAgICAgbWludXRlOiBcIjItZGlnaXRcIixcbiAgICAgICAgc2Vjb25kOiBcIjItZGlnaXRcIixcbiAgICAgICAgaG91cjEyOiB0cnVlLFxuICAgICAgICB0aW1lWm9uZU5hbWU6IFwic2hvcnRcIixcbiAgICB9KTtcbiAgICByZXR1cm4gYCR7ZGF0ZX0gJHt0aW1lfWA7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHBvc3RUb1dlYmhvb2sod2ViaG9va1VSTDogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICAvLyBTdGFtcGVkIG9uY2UgcmF0aGVyIHRoYW4gcGVyIGF0dGVtcHQsIHNvIGEgcmV0cnkgc2F5cyB3aGVuIHRoZSB0aGluZyBoYXBwZW5lZCByYXRoZXIgdGhhblxuICAgIC8vIHdoZW4gd2UgbGFzdCBtYW5hZ2VkIHRvIGdldCBpdCBvdXQuXG4gICAgbGV0IGNvbnRlbnQgPSBgXFxgJHttZXNzYWdlVGltZXN0YW1wKG5ldyBEYXRlKCkpfVxcYCAke21lc3NhZ2V9YDtcbiAgICBpZiAoY29udGVudC5sZW5ndGggPiBESVNDT1JEX01FU1NBR0VfTElNSVQpIHtcbiAgICAgICAgY29udGVudCA9IGNvbnRlbnQuc2xpY2UoMCwgRElTQ09SRF9NRVNTQUdFX0xJTUlUIC0gMykgKyBcIi4uLlwiO1xuICAgIH1cbiAgICBmb3IgKGxldCBhdHRlbXB0ID0gMTsgYXR0ZW1wdCA8PSBNQVhfU0VORF9BVFRFTVBUUzsgYXR0ZW1wdCsrKSB7XG4gICAgICAgIGxldCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHdlYmhvb2tVUkwsIHtcbiAgICAgICAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICAgICAgICBoZWFkZXJzOiB7IFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiIH0sXG4gICAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7IGNvbnRlbnQgfSksXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAocmVzcG9uc2Uub2spIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBsZXQgYm9keSA9IChhd2FpdCByZXNwb25zZS50ZXh0KCkpLnNsaWNlKDAsIE1BWF9FUlJPUl9CT0RZX0xFTkdUSCk7XG4gICAgICAgIGlmIChyZXNwb25zZS5zdGF0dXMgPT09IDQyOSAmJiBhdHRlbXB0IDwgTUFYX1NFTkRfQVRURU1QVFMpIHtcbiAgICAgICAgICAgIGxldCByZXRyeUFmdGVyID0gTnVtYmVyKHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwicmV0cnktYWZ0ZXJcIikpO1xuICAgICAgICAgICAgbGV0IHdhaXRUaW1lID0gcmV0cnlBZnRlciAmJiByZXRyeUFmdGVyICogMTAwMCB8fCBERUZBVUxUX1JBVEVfTElNSVRfV0FJVDtcbiAgICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCB3YWl0VGltZSkpO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYEV4cGVjdGVkIGEgMnh4IHJlc3BvbnNlIGZyb20gdGhlIERpc2NvcmQgd2ViaG9vaywgd2FzICR7cmVzcG9uc2Uuc3RhdHVzfSAke3Jlc3BvbnNlLnN0YXR1c1RleHR9LCBib2R5ICR7Ym9keX1gXG4gICAgICAgICk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBxdWV1ZVNlbmQod2ViaG9va1VSTDogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICBsZXQgc2VuZCA9ICgpID0+IHBvc3RUb1dlYmhvb2sod2ViaG9va1VSTCwgbWVzc2FnZSk7XG4gICAgbGV0IHJlc3VsdCA9IHNlbmRDaGFpbi50aGVuKHNlbmQsIHNlbmQpO1xuICAgIHNlbmRDaGFpbiA9IHJlc3VsdC5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKiBTZW5kcyB0byBhbiBleHBsaWNpdCB3ZWJob29rIFVSTCwgZm9yIHRvb2xpbmcgdGhhdCBhY3RzIG9uIGEgd2ViaG9vayBiZWZvcmUgKG9yIGluc3RlYWQgb2YpXG4gICAgY29uZmlndXJlRGlzY29yZE5vdGlmaWNhdGlvbnMgLSBzZXR1cCwgbWlncmF0aW9ucywgY29ubmVjdGl2aXR5IGNoZWNrcy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZW5kVG9XZWJob29rVVJMKGNvbmZpZzogeyB3ZWJob29rVVJMOiBzdHJpbmc7IG1lc3NhZ2U6IHN0cmluZyB9KSB7XG4gICAgcmV0dXJuIHF1ZXVlU2VuZChjb25maWcud2ViaG9va1VSTCwgY29uZmlnLm1lc3NhZ2UpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBjaGVja1dlYmhvb2tGaWxlQ2hhbmdlZCgpIHtcbiAgICBsZXQgc3RhdGUgPSBub3RpZmljYXRpb25TdGF0ZTtcbiAgICBpZiAoIXN0YXRlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGV0IG5ld1dlYmhvb2tVUkw7XG4gICAgdHJ5IHtcbiAgICAgICAgbmV3V2ViaG9va1VSTCA9IGF3YWl0IHJlYWRXZWJob29rRmlsZShzdGF0ZS5maWxlUGF0aCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBwb3J0c2VjdXJlOiBEaXNjb3JkIHdlYmhvb2sgZmlsZSBpcyBubyBsb25nZXIgcmVhZGFibGUsIHN0aWxsIHVzaW5nIHRoZSBsb2FkZWQgd2ViaG9vay4gJHtlfWApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChuZXdXZWJob29rVVJMID09PSBzdGF0ZS53ZWJob29rVVJMKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gV2FybiB0aGUgb2xkIGNoYW5uZWwgZmlyc3QsIHdpdGggdGhlIG5ldyB3ZWJob29rIHJlZGFjdGVkLCBzbyBhIHN0b2xlbiBvbGQgd2ViaG9vayBkb2VzIG5vdFxuICAgIC8vIGhhbmQgdGhlIGF0dGFja2VyIGEgdXNhYmxlIG5ldyBvbmUuXG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgcXVldWVTZW5kKFxuICAgICAgICAgICAgc3RhdGUud2ViaG9va1VSTCxcbiAgICAgICAgICAgIGAqKnBvcnRzZWN1cmUqKjogdGhlIERpc2NvcmQgd2ViaG9vayBpbiBcXGAke3N0YXRlLmZpbGVQYXRofVxcYCBjaGFuZ2VkIHRvYFxuICAgICAgICAgICAgKyBgIFxcYCR7cmVkYWN0V2ViaG9va1VSTChuZXdXZWJob29rVVJMKX1cXGAuYFxuICAgICAgICAgICAgKyBgIE5vdGlmaWNhdGlvbnMgYXJlIG1vdmluZyB0byB0aGUgbmV3IHdlYmhvb2sgYW5kIHRoaXMgY2hhbm5lbCB3aWxsIHN0b3AgcmVjZWl2aW5nIHRoZW0uYFxuICAgICAgICApO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihgcG9ydHNlY3VyZTogZmFpbGVkIHRvIHdhcm4gdGhlIG9sZCBEaXNjb3JkIHdlYmhvb2sgYWJvdXQgdGhlIGNoYW5nZS4gJHtlfWApO1xuICAgIH1cbiAgICBzdGF0ZS53ZWJob29rVVJMID0gbmV3V2ViaG9va1VSTDtcbn1cblxuLyoqIE11c3QgYmUgY2FsbGVkIG9uY2Ugb24gc3RhcnR1cCwgYmVmb3JlIGFueSBub3RpZmljYXRpb24gaXMgc2VudC4gQWJvcnRzIHRoZSBwcm9jZXNzIGlmIHRoZVxuICAgIHdlYmhvb2sgZmlsZSBpcyBtaXNzaW5nIG9yIGludmFsaWQsIHRoZW4gcmUtY2hlY2tzIHRoZSBmaWxlIG9uIGFuIGludGVydmFsIGFuZCB3YXJucyB0aGUgb2xkXG4gICAgd2ViaG9vayB3aGVuZXZlciBpdCBjaGFuZ2VzLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNvbmZpZ3VyZURpc2NvcmROb3RpZmljYXRpb25zKGNvbmZpZz86IHtcbiAgICBmaWxlUGF0aD86IHN0cmluZztcbiAgICBjaGVja0ludGVydmFsPzogbnVtYmVyO1xufSkge1xuICAgIGlmIChub3RpZmljYXRpb25TdGF0ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGNvbmZpZ3VyZURpc2NvcmROb3RpZmljYXRpb25zIHRvIGJlIGNhbGxlZCBvbmNlLCB3YXMgY2FsbGVkIGFnYWluIChhbHJlYWR5IHVzaW5nICR7bm90aWZpY2F0aW9uU3RhdGUuZmlsZVBhdGh9KWApO1xuICAgIH1cbiAgICBsZXQgZmlsZVBhdGggPSBjb25maWc/LmZpbGVQYXRoIHx8IERFRkFVTFRfV0VCSE9PS19GSUxFX1BBVEg7XG4gICAgbGV0IGNoZWNrSW50ZXJ2YWwgPSBjb25maWc/LmNoZWNrSW50ZXJ2YWwgfHwgREVGQVVMVF9DSEVDS19JTlRFUlZBTDtcbiAgICBsZXQgd2ViaG9va1VSTDtcbiAgICB0cnkge1xuICAgICAgICB3ZWJob29rVVJMID0gYXdhaXQgcmVhZFdlYmhvb2tGaWxlKGZpbGVQYXRoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYHBvcnRzZWN1cmU6IHJlZnVzaW5nIHRvIHN0YXJ0IHdpdGhvdXQgYSB2YWxpZCBEaXNjb3JkIHdlYmhvb2sgZmlsZS5cXG4ke2V9YCk7XG4gICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICB9XG4gICAgbGV0IGNoZWNrVGltZXIgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgIGNoZWNrV2ViaG9va0ZpbGVDaGFuZ2VkKCkuY2F0Y2goZSA9PiBjb25zb2xlLmVycm9yKGBwb3J0c2VjdXJlOiBEaXNjb3JkIHdlYmhvb2sgZmlsZSBjaGVjayBmYWlsZWQuICR7ZX1gKSk7XG4gICAgfSwgY2hlY2tJbnRlcnZhbCk7XG4gICAgLy8gVGhlIGNoZWNrIHNob3VsZCBuZXZlciBiZSB0aGUgcmVhc29uIHRoZSBwcm9jZXNzIHN0YXlzIGFsaXZlLlxuICAgIGNoZWNrVGltZXIudW5yZWYoKTtcbiAgICBub3RpZmljYXRpb25TdGF0ZSA9IHsgZmlsZVBhdGgsIHdlYmhvb2tVUkwsIGNoZWNrVGltZXIgfTtcbiAgICByZXR1cm4geyBmaWxlUGF0aCwgY2hlY2tJbnRlcnZhbCB9O1xufVxuXG4vLyBETyBOT1QgYWRkIG5ldyBjYWxscyB0byB0aGlzLiBFdmVyeSBtZXNzYWdlIGdvZXMgdG8gYSByZWFsIERpc2NvcmQgc2VydmVyIHNvbWVvbmUgcmVhZHMsIHNvIGFcbi8vIG5vdGlmaWNhdGlvbiBpcyBvbmx5IGV2ZXIgYWRkZWQgd2hlbiB0aGUgdXNlciBleHBsaWNpdGx5IGFza3MgZm9yIHRoYXQgc3BlY2lmaWMgY2FzZS4gU3RhcnR1cCxcbi8vIHN1Y2Nlc3MsIGVycm9ycywgcmV0cmllcyBhbmQgcmVjb3ZlcmllcyBhbGwgYmVsb25nIGluIGEgbG9nIGluc3RlYWQuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VuZERpc2NvcmROb3RpZmljYXRpb24obWVzc2FnZTogc3RyaW5nKSB7XG4gICAgbGV0IHN0YXRlID0gbm90aWZpY2F0aW9uU3RhdGU7XG4gICAgaWYgKCFzdGF0ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGNvbmZpZ3VyZURpc2NvcmROb3RpZmljYXRpb25zIHRvIGJlIGNhbGxlZCBiZWZvcmUgc2VuZGluZywgd2FzIGNhbGxlZCB3aXRoIG1lc3NhZ2UgJHttZXNzYWdlLnNsaWNlKDAsIE1BWF9FUlJPUl9CT0RZX0xFTkdUSCl9YCk7XG4gICAgfVxuICAgIGF3YWl0IHF1ZXVlU2VuZChzdGF0ZS53ZWJob29rVVJMLCBtZXNzYWdlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0b3BEaXNjb3JkTm90aWZpY2F0aW9ucygpIHtcbiAgICBpZiAoIW5vdGlmaWNhdGlvblN0YXRlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY2xlYXJJbnRlcnZhbChub3RpZmljYXRpb25TdGF0ZS5jaGVja1RpbWVyKTtcbiAgICBub3RpZmljYXRpb25TdGF0ZSA9IHVuZGVmaW5lZDtcbn1cbiJdfQ==
197
- /* _JS_SOURCE_HASH = "be450922cec9e8a268e2a78f817bfedb88063a0b59db5b1a954d81c96169543a"; */
205
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlzY29yZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImRpc2NvcmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsMkRBQTZCO0FBRTdCLHNIQUFzSDtBQUN0SCxrR0FBa0c7QUFDbEcsOENBQThDO0FBRWpDLFFBQUEseUJBQXlCLEdBQUcsaUNBQWlDLENBQUM7QUFDM0UsTUFBTSxzQkFBc0IsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUM3QyxNQUFNLHNCQUFzQixHQUFHO0lBQzNCLG1DQUFtQztJQUNuQyxzQ0FBc0M7SUFDdEMsMENBQTBDO0NBQzdDLENBQUM7QUFDRixNQUFNLHFCQUFxQixHQUFHLElBQUksQ0FBQztBQUNuQyxNQUFNLHFCQUFxQixHQUFHLEdBQUcsQ0FBQztBQUNsQyxNQUFNLGlCQUFpQixHQUFHLENBQUMsQ0FBQztBQUM1QixNQUFNLHNCQUFzQixHQUFHLENBQUMsQ0FBQztBQUNqQyxNQUFNLHVCQUF1QixHQUFHLENBQUMsR0FBRyxJQUFJLENBQUM7QUFFekMsSUFBSSxpQkFJUyxDQUFDO0FBRWQsc0ZBQXNGO0FBQ3RGLDRDQUE0QztBQUM1QyxJQUFJLFNBQVMsR0FBcUIsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO0FBRXBEO3NDQUNzQztBQUN0QyxTQUFnQixnQkFBZ0IsQ0FBQyxNQUFnRDtJQUM3RSxJQUFJLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxHQUFHLE1BQU0sQ0FBQztJQUN0QyxJQUFJLEtBQUssR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN4RyxJQUFJLFVBQVUsR0FBRyxL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Q29udGVudCI6WyJpbXBvcnQgZnMgZnJvbSBcImZzL3Byb21pc2VzXCI7XG5cbi8vIFBPUlRFRCBDT0RFOiBzZWN1cml0eS9hdXRob3JpemVkS2V5cy9kYWVtb24vcG9ydHNlY3VyZURhZW1vbi5qcyBlbWJlZHMgYSBoYW5kIHBvcnQgb2YgdGhpcyBmaWxlIGluIHBsYWluIEpTLCBzbyB0aGVcbi8vIGRhZW1vbiBjYW4gcnVuIHdpdGggbm8gZGVwZW5kZW5jaWVzLiBUaGUgdHdvIGFyZSBleHBlY3RlZCB0byBiZWhhdmUgaWRlbnRpY2FsbHkgLSBpZiB5b3UgY2hhbmdlXG4vLyBvbmUsIG1ha2UgdGhlIG1hdGNoaW5nIGNoYW5nZSBpbiB0aGUgb3RoZXIuXG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX1dFQkhPT0tfRklMRV9QQVRIID0gXCIvZXRjL3BvcnRzZWN1cmUvZGlzY29yZC13ZWJob29rXCI7XG5jb25zdCBERUZBVUxUX0NIRUNLX0lOVEVSVkFMID0gNSAqIDYwICogMTAwMDtcbmNvbnN0IFZBTElEX1dFQkhPT0tfUFJFRklYRVMgPSBbXG4gICAgXCJodHRwczovL2Rpc2NvcmQuY29tL2FwaS93ZWJob29rcy9cIixcbiAgICBcImh0dHBzOi8vZGlzY29yZGFwcC5jb20vYXBpL3dlYmhvb2tzL1wiLFxuICAgIFwiaHR0cHM6Ly9jYW5hcnkuZGlzY29yZC5jb20vYXBpL3dlYmhvb2tzL1wiLFxuXTtcbmNvbnN0IERJU0NPUkRfTUVTU0FHRV9MSU1JVCA9IDIwMDA7XG5jb25zdCBNQVhfRVJST1JfQk9EWV9MRU5HVEggPSA1MDA7XG5jb25zdCBNQVhfU0VORF9BVFRFTVBUUyA9IDM7XG5jb25zdCBSRURBQ1RFRF9UT0tFTl9WSVNJQkxFID0gODtcbmNvbnN0IERFRkFVTFRfUkFURV9MSU1JVF9XQUlUID0gMiAqIDEwMDA7XG5cbmxldCBub3RpZmljYXRpb25TdGF0ZToge1xuICAgIGZpbGVQYXRoOiBzdHJpbmc7XG4gICAgd2ViaG9va1VSTDogc3RyaW5nO1xuICAgIGNoZWNrVGltZXI6IE5vZGVKUy5UaW1lb3V0O1xufSB8IHVuZGVmaW5lZDtcblxuLy8gRGlzY29yZCB3ZWJob29rcyBhcmUgcmF0ZSBsaW1pdGVkIChyb3VnaGx5IDUgcmVxdWVzdHMgcGVyIDIgc2Vjb25kcyksIHNvIGV2ZXJ5IHNlbmRcbi8vIGdvZXMgdGhyb3VnaCBvbmUgY2hhaW4gaW5zdGVhZCBvZiByYWNpbmcuXG5sZXQgc2VuZENoYWluOiBQcm9taXNlPHVua25vd24+ID0gUHJvbWlzZS5yZXNvbHZlKCk7XG5cbi8qKiBQdWxscyB0aGUgd2ViaG9vayBVUkwgb3V0IG9mIHdlYmhvb2sgZmlsZSBjb250ZW50cy4gYHNvdXJjZU5hbWVgIG9ubHkgYXBwZWFycyBpbiBlcnJvcnMsIHNvXG4gICAgY2FsbGVycyBjYW4gbmFtZSBhIHJlbW90ZSBwYXRoLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlV2ViaG9va0ZpbGUoY29uZmlnOiB7IGNvbnRlbnRzOiBzdHJpbmc7IHNvdXJjZU5hbWU6IHN0cmluZyB9KSB7XG4gICAgbGV0IHsgY29udGVudHMsIHNvdXJjZU5hbWUgfSA9IGNvbmZpZztcbiAgICBsZXQgbGluZXMgPSBjb250ZW50cy5zcGxpdChcIlxcblwiKS5tYXAobGluZSA9PiBsaW5lLnRyaW0oKSkuZmlsdGVyKGxpbmUgPT4gbGluZSAmJiAhbGluZS5zdGFydHNXaXRoKFwiI1wiKSk7XG4gICAgbGV0IHdlYmhvb2tVUkwgPSBsaW5lc1swXTtcbiAgICBpZiAoIXdlYmhvb2tVUkwpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBhIERpc2NvcmQgd2ViaG9vayBVUkwgaW4gJHtzb3VyY2VOYW1lfSwgdGhlIGZpbGUgaGFzIG5vIHVzYWJsZSBsaW5lc2ApO1xuICAgIH1cbiAgICBpZiAoIVZBTElEX1dFQkhPT0tfUFJFRklYRVMuc29tZShwcmVmaXggPT4gd2ViaG9va1VSTC5zdGFydHNXaXRoKHByZWZpeCkpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBFeHBlY3RlZCBhIERpc2NvcmQgd2ViaG9vayBVUkwgc3RhcnRpbmcgd2l0aCBvbmUgb2YgJHtWQUxJRF9XRUJIT09LX1BSRUZJWEVTLmpvaW4oXCIsIFwiKX0sIGBcbiAgICAgICAgICAgICsgYHdhcyAke3dlYmhvb2tVUkwuc2xpY2UoMCwgTUFYX0VSUk9SX0JPRFlfTEVOR1RIKX0gKGluICR7c291cmNlTmFtZX0pYFxuICAgICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gd2ViaG9va1VSTDtcbn1cblxuLyoqIEtlZXBzIHRoZSBpZCBhbmQgYm90aCBlbmRzIG9mIHRoZSB0b2tlbiwgc28gYSByZWFkZXIgY2FuIGNvbmZpcm0gd2hpY2ggd2ViaG9vayByZXBsYWNlZCB0aGVpcnNcbiAgICB3aXRob3V0IHJlY2VpdmluZyBvbmUgdGhleSBjb3VsZCBwb3N0IHRvLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZGFjdFdlYmhvb2tVUkwod2ViaG9va1VSTDogc3RyaW5nKSB7XG4gICAgbGV0IHNlcGFyYXRvckluZGV4ID0gd2ViaG9va1VSTC5sYXN0SW5kZXhPZihcIi9cIik7XG4gICAgbGV0IGJhc2UgPSB3ZWJob29rVVJMLnNsaWNlKDAsIHNlcGFyYXRvckluZGV4ICsgMSk7XG4gICAgbGV0IHRva2VuID0gd2ViaG9va1VSTC5zbGljZShzZXBhcmF0b3JJbmRleCArIDEpO1xuICAgIGlmICh0b2tlbi5sZW5ndGggPD0gUkVEQUNURURfVE9LRU5fVklTSUJMRSAqIDIpIHtcbiAgICAgICAgLy8gVG9vIHNob3J0IHRvIHNob3cgYm90aCBlbmRzIHdpdGhvdXQgZ2l2aW5nIGF3YXkgdGhlIHdob2xlIHRva2VuLlxuICAgICAgICByZXR1cm4gYCR7YmFzZX0ke3Rva2VuLnNsaWNlKDAsIFJFREFDVEVEX1RPS0VOX1ZJU0lCTEUpfS4uLmA7XG4gICAgfVxuICAgIHJldHVybiBgJHtiYXNlfSR7dG9rZW4uc2xpY2UoMCwgUkVEQUNURURfVE9LRU5fVklTSUJMRSl9Li4uJHt0b2tlbi5zbGljZSgtUkVEQUNURURfVE9LRU5fVklTSUJMRSl9YDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdFdlYmhvb2tGaWxlKHdlYmhvb2tVUkw6IHN0cmluZykge1xuICAgIHJldHVybiBgIyBwb3J0c2VjdXJlIERpc2NvcmQgd2ViaG9vay4gRmlyc3Qgbm9uLWNvbW1lbnQgbGluZSBpcyB1c2VkLlxcbiR7d2ViaG9va1VSTH1cXG5gO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZWFkV2ViaG9va0ZpbGUoZmlsZVBhdGg6IHN0cmluZykge1xuICAgIGxldCBjb250ZW50cztcbiAgICB0cnkge1xuICAgICAgICBjb250ZW50cyA9IGF3YWl0IGZzLnJlYWRGaWxlKGZpbGVQYXRoLCBcInV0ZjhcIik7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGEgcmVhZGFibGUgRGlzY29yZCB3ZWJob29rIGZpbGUgYXQgJHtmaWxlUGF0aH0sICR7ZX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHBhcnNlV2ViaG9va0ZpbGUoeyBjb250ZW50cywgc291cmNlTmFtZTogZmlsZVBhdGggfSk7XG59XG5cbi8qKiBXaGVuIHRoZSBtZXNzYWdlIHdhcyBzZW50LCBpbiB0aGUgc2VuZGluZyBtYWNoaW5lJ3Mgb3duIHRpbWUgem9uZS4gRGlzY29yZCBzaG93cyB3aGVuIGl0XG4gICAgcmVjZWl2ZWQgc29tZXRoaW5nLCB3aGljaCBpcyBub3QgdGhlIHNhbWUgdGhpbmcgd2hlbiBhIG1hY2hpbmUgaGFzIGJlZW4gb2ZmbGluZSBvciBhIHNlbmQgaGFzXG4gICAgYmVlbiByZXRyaWVkLCBhbmQgdGhlIHpvbmUgbWF0dGVycyB3aGVuIHRoZSBtYWNoaW5lcyBhcmUgbm90IGFsbCBpbiBvbmUgcGxhY2UuICovXG5leHBvcnQgZnVuY3Rpb24gbWVzc2FnZVRpbWVzdGFtcChub3c6IERhdGUpIHtcbiAgICBsZXQgZGF0ZSA9IG5vdy50b0xvY2FsZURhdGVTdHJpbmcoXCJlbi1DQVwiKTtcbiAgICBsZXQgdGltZSA9IG5vdy50b0xvY2FsZVRpbWVTdHJpbmcoXCJlbi1VU1wiLCB7XG4gICAgICAgIGhvdXI6IFwiMi1kaWdpdFwiLFxuICAgICAgICBtaW51dGU6IFwiMi1kaWdpdFwiLFxuICAgICAgICBzZWNvbmQ6IFwiMi1kaWdpdFwiLFxuICAgICAgICBob3VyMTI6IHRydWUsXG4gICAgICAgIHRpbWVab25lTmFtZTogXCJzaG9ydFwiLFxuICAgIH0pO1xuICAgIHJldHVybiBgJHtkYXRlfSAke3RpbWV9YDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcG9zdFRvV2ViaG9vayh3ZWJob29rVVJMOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZykge1xuICAgIC8vIFN0YW1wZWQgb25jZSByYXRoZXIgdGhhbiBwZXIgYXR0ZW1wdCwgc28gYSByZXRyeSBzYXlzIHdoZW4gdGhlIHRoaW5nIGhhcHBlbmVkIHJhdGhlciB0aGFuXG4gICAgLy8gd2hlbiB3ZSBsYXN0IG1hbmFnZWQgdG8gZ2V0IGl0IG91dC4gQXQgdGhlIGVuZCwgYmVjYXVzZSB0aGUgZmlyc3QgbGluZSBvZiBhIG1lc3NhZ2UgaXMgdGhlXG4gICAgLy8gbm90aWZpY2F0aW9uIHByZXZpZXcgYW5kIGEgdGltZXN0YW1wIHRoZXJlIHdvdWxkIHNwZW5kIGl0IHNheWluZyBub3RoaW5nLlxuICAgIGxldCBjb250ZW50ID0gYCR7bWVzc2FnZX0gwrcgXFxgJHttZXNzYWdlVGltZXN0YW1wKG5ldyBEYXRlKCkpfVxcYGA7XG4gICAgaWYgKGNvbnRlbnQubGVuZ3RoID4gRElTQ09SRF9NRVNTQUdFX0xJTUlUKSB7XG4gICAgICAgIGNvbnRlbnQgPSBjb250ZW50LnNsaWNlKDAsIERJU0NPUkRfTUVTU0FHRV9MSU1JVCAtIDMpICsgXCIuLi5cIjtcbiAgICB9XG4gICAgZm9yIChsZXQgYXR0ZW1wdCA9IDE7IGF0dGVtcHQgPD0gTUFYX1NFTkRfQVRURU1QVFM7IGF0dGVtcHQrKykge1xuICAgICAgICBsZXQgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh3ZWJob29rVVJMLCB7XG4gICAgICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICAgICAgaGVhZGVyczogeyBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiB9LFxuICAgICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyBjb250ZW50IH0pLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHJlc3BvbnNlLm9rKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGJvZHkgPSAoYXdhaXQgcmVzcG9uc2UudGV4dCgpKS5zbGljZSgwLCBNQVhfRVJST1JfQk9EWV9MRU5HVEgpO1xuICAgICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSA0MjkgJiYgYXR0ZW1wdCA8IE1BWF9TRU5EX0FUVEVNUFRTKSB7XG4gICAgICAgICAgICBsZXQgcmV0cnlBZnRlciA9IE51bWJlcihyZXNwb25zZS5oZWFkZXJzLmdldChcInJldHJ5LWFmdGVyXCIpKTtcbiAgICAgICAgICAgIGxldCB3YWl0VGltZSA9IHJldHJ5QWZ0ZXIgJiYgcmV0cnlBZnRlciAqIDEwMDAgfHwgREVGQVVMVF9SQVRFX0xJTUlUX1dBSVQ7XG4gICAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgd2FpdFRpbWUpKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBFeHBlY3RlZCBhIDJ4eCByZXNwb25zZSBmcm9tIHRoZSBEaXNjb3JkIHdlYmhvb2ssIHdhcyAke3Jlc3BvbnNlLnN0YXR1c30gJHtyZXNwb25zZS5zdGF0dXNUZXh0fSwgYm9keSAke2JvZHl9YFxuICAgICAgICApO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcXVldWVTZW5kKHdlYmhvb2tVUkw6IHN0cmluZywgbWVzc2FnZTogc3RyaW5nKSB7XG4gICAgbGV0IHNlbmQgPSAoKSA9PiBwb3N0VG9XZWJob29rKHdlYmhvb2tVUkwsIG1lc3NhZ2UpO1xuICAgIGxldCByZXN1bHQgPSBzZW5kQ2hhaW4udGhlbihzZW5kLCBzZW5kKTtcbiAgICBzZW5kQ2hhaW4gPSByZXN1bHQuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKiogU2VuZHMgdG8gYW4gZXhwbGljaXQgd2ViaG9vayBVUkwsIGZvciB0b29saW5nIHRoYXQgYWN0cyBvbiBhIHdlYmhvb2sgYmVmb3JlIChvciBpbnN0ZWFkIG9mKVxuICAgIGNvbmZpZ3VyZURpc2NvcmROb3RpZmljYXRpb25zIC0gc2V0dXAsIG1pZ3JhdGlvbnMsIGNvbm5lY3Rpdml0eSBjaGVja3MuICovXG5leHBvcnQgZnVuY3Rpb24gc2VuZFRvV2ViaG9va1VSTChjb25maWc6IHsgd2ViaG9va1VSTDogc3RyaW5nOyBtZXNzYWdlOiBzdHJpbmcgfSkge1xuICAgIHJldHVybiBxdWV1ZVNlbmQoY29uZmlnLndlYmhvb2tVUkwsIGNvbmZpZy5tZXNzYWdlKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY2hlY2tXZWJob29rRmlsZUNoYW5nZWQoKSB7XG4gICAgbGV0IHN0YXRlID0gbm90aWZpY2F0aW9uU3RhdGU7XG4gICAgaWYgKCFzdGF0ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBuZXdXZWJob29rVVJMO1xuICAgIHRyeSB7XG4gICAgICAgIG5ld1dlYmhvb2tVUkwgPSBhd2FpdCByZWFkV2ViaG9va0ZpbGUoc3RhdGUuZmlsZVBhdGgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihgcG9ydHNlY3VyZTogRGlzY29yZCB3ZWJob29rIGZpbGUgaXMgbm8gbG9uZ2VyIHJlYWRhYmxlLCBzdGlsbCB1c2luZyB0aGUgbG9hZGVkIHdlYmhvb2suICR7ZX1gKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAobmV3V2ViaG9va1VSTCA9PT0gc3RhdGUud2ViaG9va1VSTCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIFdhcm4gdGhlIG9sZCBjaGFubmVsIGZpcnN0LCB3aXRoIHRoZSBuZXcgd2ViaG9vayByZWRhY3RlZCwgc28gYSBzdG9sZW4gb2xkIHdlYmhvb2sgZG9lcyBub3RcbiAgICAvLyBoYW5kIHRoZSBhdHRhY2tlciBhIHVzYWJsZSBuZXcgb25lLlxuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHF1ZXVlU2VuZChcbiAgICAgICAgICAgIHN0YXRlLndlYmhvb2tVUkwsXG4gICAgICAgICAgICBgKipwb3J0c2VjdXJlKio6ICoqTk9USUZJQ0FUSU9OUyBBUkUgTU9WSU5HIFRPIEFOT1RIRVIgQ0hBTk5FTCoqYFxuICAgICAgICAgICAgKyBgXFxuXFxuVGhpcyBjaGFubmVsIHN0b3BzIHJlY2VpdmluZyB0aGVtIG5vdy4gSWYgdGhhdCB3YXMgbm90IHlvdSwgc29tZWJvZHkgd2l0aCBhY2Nlc3NgXG4gICAgICAgICAgICArIGAgdG8gdGhpcyBtYWNoaW5lIGp1c3QgcmVkaXJlY3RlZCBpdHMgYWxlcnRzLmBcbiAgICAgICAgICAgICsgYFxcblxcbm5ldyB3ZWJob29rOiBcXGAke3JlZGFjdFdlYmhvb2tVUkwobmV3V2ViaG9va1VSTCl9XFxgYFxuICAgICAgICAgICAgKyBgXFxuc2V0IGluOiBcXGAke3N0YXRlLmZpbGVQYXRofVxcYGBcbiAgICAgICAgKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYHBvcnRzZWN1cmU6IGZhaWxlZCB0byB3YXJuIHRoZSBvbGQgRGlzY29yZCB3ZWJob29rIGFib3V0IHRoZSBjaGFuZ2UuICR7ZX1gKTtcbiAgICB9XG4gICAgc3RhdGUud2ViaG9va1VSTCA9IG5ld1dlYmhvb2tVUkw7XG59XG5cbi8qKiBNdXN0IGJlIGNhbGxlZCBvbmNlIG9uIHN0YXJ0dXAsIGJlZm9yZSBhbnkgbm90aWZpY2F0aW9uIGlzIHNlbnQuIEFib3J0cyB0aGUgcHJvY2VzcyBpZiB0aGVcbiAgICB3ZWJob29rIGZpbGUgaXMgbWlzc2luZyBvciBpbnZhbGlkLCB0aGVuIHJlLWNoZWNrcyB0aGUgZmlsZSBvbiBhbiBpbnRlcnZhbCBhbmQgd2FybnMgdGhlIG9sZFxuICAgIHdlYmhvb2sgd2hlbmV2ZXIgaXQgY2hhbmdlcy4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjb25maWd1cmVEaXNjb3JkTm90aWZpY2F0aW9ucyhjb25maWc/OiB7XG4gICAgZmlsZVBhdGg/OiBzdHJpbmc7XG4gICAgY2hlY2tJbnRlcnZhbD86IG51bWJlcjtcbn0pIHtcbiAgICBpZiAobm90aWZpY2F0aW9uU3RhdGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBjb25maWd1cmVEaXNjb3JkTm90aWZpY2F0aW9ucyB0byBiZSBjYWxsZWQgb25jZSwgd2FzIGNhbGxlZCBhZ2FpbiAoYWxyZWFkeSB1c2luZyAke25vdGlmaWNhdGlvblN0YXRlLmZpbGVQYXRofSlgKTtcbiAgICB9XG4gICAgbGV0IGZpbGVQYXRoID0gY29uZmlnPy5maWxlUGF0aCB8fCBERUZBVUxUX1dFQkhPT0tfRklMRV9QQVRIO1xuICAgIGxldCBjaGVja0ludGVydmFsID0gY29uZmlnPy5jaGVja0ludGVydmFsIHx8IERFRkFVTFRfQ0hFQ0tfSU5URVJWQUw7XG4gICAgbGV0IHdlYmhvb2tVUkw7XG4gICAgdHJ5IHtcbiAgICAgICAgd2ViaG9va1VSTCA9IGF3YWl0IHJlYWRXZWJob29rRmlsZShmaWxlUGF0aCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBwb3J0c2VjdXJlOiByZWZ1c2luZyB0byBzdGFydCB3aXRob3V0IGEgdmFsaWQgRGlzY29yZCB3ZWJob29rIGZpbGUuXFxuJHtlfWApO1xuICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuICAgIGxldCBjaGVja1RpbWVyID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICBjaGVja1dlYmhvb2tGaWxlQ2hhbmdlZCgpLmNhdGNoKGUgPT4gY29uc29sZS5lcnJvcihgcG9ydHNlY3VyZTogRGlzY29yZCB3ZWJob29rIGZpbGUgY2hlY2sgZmFpbGVkLiAke2V9YCkpO1xuICAgIH0sIGNoZWNrSW50ZXJ2YWwpO1xuICAgIC8vIFRoZSBjaGVjayBzaG91bGQgbmV2ZXIgYmUgdGhlIHJlYXNvbiB0aGUgcHJvY2VzcyBzdGF5cyBhbGl2ZS5cbiAgICBjaGVja1RpbWVyLnVucmVmKCk7XG4gICAgbm90aWZpY2F0aW9uU3RhdGUgPSB7IGZpbGVQYXRoLCB3ZWJob29rVVJMLCBjaGVja1RpbWVyIH07XG4gICAgcmV0dXJuIHsgZmlsZVBhdGgsIGNoZWNrSW50ZXJ2YWwgfTtcbn1cblxuLy8gRE8gTk9UIGFkZCBuZXcgY2FsbHMgdG8gdGhpcy4gRXZlcnkgbWVzc2FnZSBnb2VzIHRvIGEgcmVhbCBEaXNjb3JkIHNlcnZlciBzb21lb25lIHJlYWRzLCBzbyBhXG4vLyBub3RpZmljYXRpb24gaXMgb25seSBldmVyIGFkZGVkIHdoZW4gdGhlIHVzZXIgZXhwbGljaXRseSBhc2tzIGZvciB0aGF0IHNwZWNpZmljIGNhc2UuIFN0YXJ0dXAsXG4vLyBzdWNjZXNzLCBlcnJvcnMsIHJldHJpZXMgYW5kIHJlY292ZXJpZXMgYWxsIGJlbG9uZyBpbiBhIGxvZyBpbnN0ZWFkLlxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlbmREaXNjb3JkTm90aWZpY2F0aW9uKG1lc3NhZ2U6IHN0cmluZykge1xuICAgIGxldCBzdGF0ZSA9IG5vdGlmaWNhdGlvblN0YXRlO1xuICAgIGlmICghc3RhdGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBjb25maWd1cmVEaXNjb3JkTm90aWZpY2F0aW9ucyB0byBiZSBjYWxsZWQgYmVmb3JlIHNlbmRpbmcsIHdhcyBjYWxsZWQgd2l0aCBtZXNzYWdlICR7bWVzc2FnZS5zbGljZSgwLCBNQVhfRVJST1JfQk9EWV9MRU5HVEgpfWApO1xuICAgIH1cbiAgICBhd2FpdCBxdWV1ZVNlbmQoc3RhdGUud2ViaG9va1VSTCwgbWVzc2FnZSk7XG59XG5cbi8qKiBXaGV0aGVyIG5vdGlmaWNhdGlvbnMgYXJlIHNldCB1cCBpbiB0aGlzIHByb2Nlc3MuIEZvciBjb2RlIHRoYXQgbWF5IHJ1biBvdXRzaWRlIHRoZSBkYWVtb24sXG4gICAgd2hlcmUgc2VuZGluZyBpcyB3b3J0aCBkb2luZyBpZiBpdCBjYW4gYmUgYW5kIG5vdCB3b3J0aCBmYWlsaW5nIG92ZXIgaWYgaXQgY2Fubm90LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFyZURpc2NvcmROb3RpZmljYXRpb25zQ29uZmlndXJlZCgpIHtcbiAgICByZXR1cm4gISFub3RpZmljYXRpb25TdGF0ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0b3BEaXNjb3JkTm90aWZpY2F0aW9ucygpIHtcbiAgICBpZiAoIW5vdGlmaWNhdGlvblN0YXRlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY2xlYXJJbnRlcnZhbChub3RpZmljYXRpb25TdGF0ZS5jaGVja1RpbWVyKTtcbiAgICBub3RpZmljYXRpb25TdGF0ZSA9IHVuZGVmaW5lZDtcbn1cbiJdfQ==
206
+ /* _JS_SOURCE_HASH = "abb6e0b243d1d85cb4a3599020263d0b3164ce4bf2aef2aa81489e304cd43b4c"; */