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.
- package/bin/addmachine.js +9 -0
- package/bin/machineclient.js +9 -0
- package/bin/machineserver.js +10 -0
- package/index.d.ts +15 -0
- package/misc/dist/ownIPs.ts.cache +43 -0
- package/misc/dist/strings.ts.cache +2 -2
- package/misc/https/dist/certs.ts.cache +2 -2
- package/misc/https/dist/persistentLocalStorage.ts.cache +2 -2
- package/misc/ownIPs.d.ts +11 -0
- package/misc/ownIPs.ts +34 -0
- package/package.json +9 -3
- package/security/authorizedKeys/authorizedKeys.ts +34 -0
- package/security/authorizedKeys/daemon/authLog.ts +12 -5
- package/security/authorizedKeys/daemon/changes.ts +16 -1
- package/security/authorizedKeys/daemon/daemon.ts +43 -34
- package/security/authorizedKeys/daemon/dist/changes.ts.cache +40 -0
- package/security/authorizedKeys/daemon/dist/git.ts.cache +121 -0
- package/security/authorizedKeys/daemon/dist/notify.ts.cache +39 -0
- package/security/authorizedKeys/daemon/dist/paths.ts.cache +29 -0
- package/security/authorizedKeys/daemon/dist/repoFiles.ts.cache +114 -0
- package/security/authorizedKeys/daemon/dist/revocation.ts.cache +0 -0
- package/security/authorizedKeys/daemon/dist/sessions.ts.cache +147 -0
- package/security/authorizedKeys/daemon/dist/state.ts.cache +74 -0
- package/security/authorizedKeys/daemon/dist/trust.ts.cache +295 -0
- package/security/authorizedKeys/daemon/notify.ts +8 -2
- package/security/authorizedKeys/daemon/repoFiles.ts +118 -0
- package/security/authorizedKeys/daemon/revocation.ts +0 -0
- package/security/authorizedKeys/daemon/rootKeys.ts +77 -10
- package/security/authorizedKeys/daemon/state.ts +25 -7
- package/security/authorizedKeys/daemon/trust.ts +37 -16
- package/security/authorizedKeys/daemon/userKeys.ts +5 -4
- package/security/authorizedKeys/dist/authorizedKeys.ts.cache +37 -3
- package/security/authorizedKeys/dist/revokeSource.ts.cache +17 -4
- package/security/authorizedKeys/dist/sources.ts.cache +52 -8
- package/security/authorizedKeys/dist/unrevoke.ts.cache +113 -17
- package/security/authorizedKeys/secureSSH.ts +39 -21
- package/security/authorizedKeys/unrevoke.ts +159 -8
- package/security/helpers/dist/remoteSSH.ts.cache +19 -9
- package/security/machines/addMachine.ts +83 -0
- package/security/machines/dist/addMachine.ts.cache +88 -0
- package/security/machines/dist/identity.ts.cache +176 -0
- package/security/machines/dist/machines.ts.cache +322 -0
- package/security/machines/dist/trustClient.ts.cache +48 -0
- package/security/machines/dist/trustState.ts.cache +57 -0
- package/security/machines/identity.ts +199 -0
- package/security/machines/machines.ts +355 -0
- package/security/machines/trustClient.ts +51 -0
- package/security/machines/trustServer.ts +85 -0
- package/security/machines/trustState.ts +53 -0
- package/security/notifications/discord.ts +14 -5
- 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
|
-
|
|
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**:
|
|
153
|
-
+ `
|
|
154
|
-
+ `
|
|
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
|
-
|
|
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**:
|
|
143
|
-
+ `
|
|
144
|
-
+ `
|
|
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 = "
|
|
205
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlzY29yZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImRpc2NvcmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsMkRBQTZCO0FBRTdCLHNIQUFzSDtBQUN0SCxrR0FBa0c7QUFDbEcsOENBQThDO0FBRWpDLFFBQUEseUJBQXlCLEdBQUcsaUNBQWlDLENBQUM7QUFDM0UsTUFBTSxzQkFBc0IsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUM3QyxNQUFNLHNCQUFzQixHQUFHO0lBQzNCLG1DQUFtQztJQUNuQyxzQ0FBc0M7SUFDdEMsMENBQTBDO0NBQzdDLENBQUM7QUFDRixNQUFNLHFCQUFxQixHQUFHLElBQUksQ0FBQztBQUNuQyxNQUFNLHFCQUFxQixHQUFHLEdBQUcsQ0FBQztBQUNsQyxNQUFNLGlCQUFpQixHQUFHLENBQUMsQ0FBQztBQUM1QixNQUFNLHNCQUFzQixHQUFHLENBQUMsQ0FBQztBQUNqQyxNQUFNLHVCQUF1QixHQUFHLENBQUMsR0FBRyxJQUFJLENBQUM7QUFFekMsSUFBSSxpQkFJUyxDQUFDO0FBRWQsc0ZBQXNGO0FBQ3RGLDRDQUE0QztBQUM1QyxJQUFJLFNBQVMsR0FBcUIsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO0FBRXBEO3NDQUNzQztBQUN0QyxTQUFnQixnQkFBZ0IsQ0FBQyxNQUFnRDtJQUM3RSxJQUFJLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxHQUFHLE1BQU0sQ0FBQztJQUN0QyxJQUFJLEtBQUssR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN4RyxJQUFJLFVBQVUsR0FBRyxL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Q29udGVudCI6WyJpbXBvcnQgZnMgZnJvbSBcImZzL3Byb21pc2VzXCI7XG5cbi8vIFBPUlRFRCBDT0RFOiBzZWN1cml0eS9hdXRob3JpemVkS2V5cy9kYWVtb24vcG9ydHNlY3VyZURhZW1vbi5qcyBlbWJlZHMgYSBoYW5kIHBvcnQgb2YgdGhpcyBmaWxlIGluIHBsYWluIEpTLCBzbyB0aGVcbi8vIGRhZW1vbiBjYW4gcnVuIHdpdGggbm8gZGVwZW5kZW5jaWVzLiBUaGUgdHdvIGFyZSBleHBlY3RlZCB0byBiZWhhdmUgaWRlbnRpY2FsbHkgLSBpZiB5b3UgY2hhbmdlXG4vLyBvbmUsIG1ha2UgdGhlIG1hdGNoaW5nIGNoYW5nZSBpbiB0aGUgb3RoZXIuXG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX1dFQkhPT0tfRklMRV9QQVRIID0gXCIvZXRjL3BvcnRzZWN1cmUvZGlzY29yZC13ZWJob29rXCI7XG5jb25zdCBERUZBVUxUX0NIRUNLX0lOVEVSVkFMID0gNSAqIDYwICogMTAwMDtcbmNvbnN0IFZBTElEX1dFQkhPT0tfUFJFRklYRVMgPSBbXG4gICAgXCJodHRwczovL2Rpc2NvcmQuY29tL2FwaS93ZWJob29rcy9cIixcbiAgICBcImh0dHBzOi8vZGlzY29yZGFwcC5jb20vYXBpL3dlYmhvb2tzL1wiLFxuICAgIFwiaHR0cHM6Ly9jYW5hcnkuZGlzY29yZC5jb20vYXBpL3dlYmhvb2tzL1wiLFxuXTtcbmNvbnN0IERJU0NPUkRfTUVTU0FHRV9MSU1JVCA9IDIwMDA7XG5jb25zdCBNQVhfRVJST1JfQk9EWV9MRU5HVEggPSA1MDA7XG5jb25zdCBNQVhfU0VORF9BVFRFTVBUUyA9IDM7XG5jb25zdCBSRURBQ1RFRF9UT0tFTl9WSVNJQkxFID0gODtcbmNvbnN0IERFRkFVTFRfUkFURV9MSU1JVF9XQUlUID0gMiAqIDEwMDA7XG5cbmxldCBub3RpZmljYXRpb25TdGF0ZToge1xuICAgIGZpbGVQYXRoOiBzdHJpbmc7XG4gICAgd2ViaG9va1VSTDogc3RyaW5nO1xuICAgIGNoZWNrVGltZXI6IE5vZGVKUy5UaW1lb3V0O1xufSB8IHVuZGVmaW5lZDtcblxuLy8gRGlzY29yZCB3ZWJob29rcyBhcmUgcmF0ZSBsaW1pdGVkIChyb3VnaGx5IDUgcmVxdWVzdHMgcGVyIDIgc2Vjb25kcyksIHNvIGV2ZXJ5IHNlbmRcbi8vIGdvZXMgdGhyb3VnaCBvbmUgY2hhaW4gaW5zdGVhZCBvZiByYWNpbmcuXG5sZXQgc2VuZENoYWluOiBQcm9taXNlPHVua25vd24+ID0gUHJvbWlzZS5yZXNvbHZlKCk7XG5cbi8qKiBQdWxscyB0aGUgd2ViaG9vayBVUkwgb3V0IG9mIHdlYmhvb2sgZmlsZSBjb250ZW50cy4gYHNvdXJjZU5hbWVgIG9ubHkgYXBwZWFycyBpbiBlcnJvcnMsIHNvXG4gICAgY2FsbGVycyBjYW4gbmFtZSBhIHJlbW90ZSBwYXRoLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlV2ViaG9va0ZpbGUoY29uZmlnOiB7IGNvbnRlbnRzOiBzdHJpbmc7IHNvdXJjZU5hbWU6IHN0cmluZyB9KSB7XG4gICAgbGV0IHsgY29udGVudHMsIHNvdXJjZU5hbWUgfSA9IGNvbmZpZztcbiAgICBsZXQgbGluZXMgPSBjb250ZW50cy5zcGxpdChcIlxcblwiKS5tYXAobGluZSA9PiBsaW5lLnRyaW0oKSkuZmlsdGVyKGxpbmUgPT4gbGluZSAmJiAhbGluZS5zdGFydHNXaXRoKFwiI1wiKSk7XG4gICAgbGV0IHdlYmhvb2tVUkwgPSBsaW5lc1swXTtcbiAgICBpZiAoIXdlYmhvb2tVUkwpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBhIERpc2NvcmQgd2ViaG9vayBVUkwgaW4gJHtzb3VyY2VOYW1lfSwgdGhlIGZpbGUgaGFzIG5vIHVzYWJsZSBsaW5lc2ApO1xuICAgIH1cbiAgICBpZiAoIVZBTElEX1dFQkhPT0tfUFJFRklYRVMuc29tZShwcmVmaXggPT4gd2ViaG9va1VSTC5zdGFydHNXaXRoKHByZWZpeCkpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBFeHBlY3RlZCBhIERpc2NvcmQgd2ViaG9vayBVUkwgc3RhcnRpbmcgd2l0aCBvbmUgb2YgJHtWQUxJRF9XRUJIT09LX1BSRUZJWEVTLmpvaW4oXCIsIFwiKX0sIGBcbiAgICAgICAgICAgICsgYHdhcyAke3dlYmhvb2tVUkwuc2xpY2UoMCwgTUFYX0VSUk9SX0JPRFlfTEVOR1RIKX0gKGluICR7c291cmNlTmFtZX0pYFxuICAgICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gd2ViaG9va1VSTDtcbn1cblxuLyoqIEtlZXBzIHRoZSBpZCBhbmQgYm90aCBlbmRzIG9mIHRoZSB0b2tlbiwgc28gYSByZWFkZXIgY2FuIGNvbmZpcm0gd2hpY2ggd2ViaG9vayByZXBsYWNlZCB0aGVpcnNcbiAgICB3aXRob3V0IHJlY2VpdmluZyBvbmUgdGhleSBjb3VsZCBwb3N0IHRvLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZGFjdFdlYmhvb2tVUkwod2ViaG9va1VSTDogc3RyaW5nKSB7XG4gICAgbGV0IHNlcGFyYXRvckluZGV4ID0gd2ViaG9va1VSTC5sYXN0SW5kZXhPZihcIi9cIik7XG4gICAgbGV0IGJhc2UgPSB3ZWJob29rVVJMLnNsaWNlKDAsIHNlcGFyYXRvckluZGV4ICsgMSk7XG4gICAgbGV0IHRva2VuID0gd2ViaG9va1VSTC5zbGljZShzZXBhcmF0b3JJbmRleCArIDEpO1xuICAgIGlmICh0b2tlbi5sZW5ndGggPD0gUkVEQUNURURfVE9LRU5fVklTSUJMRSAqIDIpIHtcbiAgICAgICAgLy8gVG9vIHNob3J0IHRvIHNob3cgYm90aCBlbmRzIHdpdGhvdXQgZ2l2aW5nIGF3YXkgdGhlIHdob2xlIHRva2VuLlxuICAgICAgICByZXR1cm4gYCR7YmFzZX0ke3Rva2VuLnNsaWNlKDAsIFJFREFDVEVEX1RPS0VOX1ZJU0lCTEUpfS4uLmA7XG4gICAgfVxuICAgIHJldHVybiBgJHtiYXNlfSR7dG9rZW4uc2xpY2UoMCwgUkVEQUNURURfVE9LRU5fVklTSUJMRSl9Li4uJHt0b2tlbi5zbGljZSgtUkVEQUNURURfVE9LRU5fVklTSUJMRSl9YDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdFdlYmhvb2tGaWxlKHdlYmhvb2tVUkw6IHN0cmluZykge1xuICAgIHJldHVybiBgIyBwb3J0c2VjdXJlIERpc2NvcmQgd2ViaG9vay4gRmlyc3Qgbm9uLWNvbW1lbnQgbGluZSBpcyB1c2VkLlxcbiR7d2ViaG9va1VSTH1cXG5gO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZWFkV2ViaG9va0ZpbGUoZmlsZVBhdGg6IHN0cmluZykge1xuICAgIGxldCBjb250ZW50cztcbiAgICB0cnkge1xuICAgICAgICBjb250ZW50cyA9IGF3YWl0IGZzLnJlYWRGaWxlKGZpbGVQYXRoLCBcInV0ZjhcIik7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGEgcmVhZGFibGUgRGlzY29yZCB3ZWJob29rIGZpbGUgYXQgJHtmaWxlUGF0aH0sICR7ZX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHBhcnNlV2ViaG9va0ZpbGUoeyBjb250ZW50cywgc291cmNlTmFtZTogZmlsZVBhdGggfSk7XG59XG5cbi8qKiBXaGVuIHRoZSBtZXNzYWdlIHdhcyBzZW50LCBpbiB0aGUgc2VuZGluZyBtYWNoaW5lJ3Mgb3duIHRpbWUgem9uZS4gRGlzY29yZCBzaG93cyB3aGVuIGl0XG4gICAgcmVjZWl2ZWQgc29tZXRoaW5nLCB3aGljaCBpcyBub3QgdGhlIHNhbWUgdGhpbmcgd2hlbiBhIG1hY2hpbmUgaGFzIGJlZW4gb2ZmbGluZSBvciBhIHNlbmQgaGFzXG4gICAgYmVlbiByZXRyaWVkLCBhbmQgdGhlIHpvbmUgbWF0dGVycyB3aGVuIHRoZSBtYWNoaW5lcyBhcmUgbm90IGFsbCBpbiBvbmUgcGxhY2UuICovXG5leHBvcnQgZnVuY3Rpb24gbWVzc2FnZVRpbWVzdGFtcChub3c6IERhdGUpIHtcbiAgICBsZXQgZGF0ZSA9IG5vdy50b0xvY2FsZURhdGVTdHJpbmcoXCJlbi1DQVwiKTtcbiAgICBsZXQgdGltZSA9IG5vdy50b0xvY2FsZVRpbWVTdHJpbmcoXCJlbi1VU1wiLCB7XG4gICAgICAgIGhvdXI6IFwiMi1kaWdpdFwiLFxuICAgICAgICBtaW51dGU6IFwiMi1kaWdpdFwiLFxuICAgICAgICBzZWNvbmQ6IFwiMi1kaWdpdFwiLFxuICAgICAgICBob3VyMTI6IHRydWUsXG4gICAgICAgIHRpbWVab25lTmFtZTogXCJzaG9ydFwiLFxuICAgIH0pO1xuICAgIHJldHVybiBgJHtkYXRlfSAke3RpbWV9YDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcG9zdFRvV2ViaG9vayh3ZWJob29rVVJMOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZykge1xuICAgIC8vIFN0YW1wZWQgb25jZSByYXRoZXIgdGhhbiBwZXIgYXR0ZW1wdCwgc28gYSByZXRyeSBzYXlzIHdoZW4gdGhlIHRoaW5nIGhhcHBlbmVkIHJhdGhlciB0aGFuXG4gICAgLy8gd2hlbiB3ZSBsYXN0IG1hbmFnZWQgdG8gZ2V0IGl0IG91dC4gQXQgdGhlIGVuZCwgYmVjYXVzZSB0aGUgZmlyc3QgbGluZSBvZiBhIG1lc3NhZ2UgaXMgdGhlXG4gICAgLy8gbm90aWZpY2F0aW9uIHByZXZpZXcgYW5kIGEgdGltZXN0YW1wIHRoZXJlIHdvdWxkIHNwZW5kIGl0IHNheWluZyBub3RoaW5nLlxuICAgIGxldCBjb250ZW50ID0gYCR7bWVzc2FnZX0gwrcgXFxgJHttZXNzYWdlVGltZXN0YW1wKG5ldyBEYXRlKCkpfVxcYGA7XG4gICAgaWYgKGNvbnRlbnQubGVuZ3RoID4gRElTQ09SRF9NRVNTQUdFX0xJTUlUKSB7XG4gICAgICAgIGNvbnRlbnQgPSBjb250ZW50LnNsaWNlKDAsIERJU0NPUkRfTUVTU0FHRV9MSU1JVCAtIDMpICsgXCIuLi5cIjtcbiAgICB9XG4gICAgZm9yIChsZXQgYXR0ZW1wdCA9IDE7IGF0dGVtcHQgPD0gTUFYX1NFTkRfQVRURU1QVFM7IGF0dGVtcHQrKykge1xuICAgICAgICBsZXQgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh3ZWJob29rVVJMLCB7XG4gICAgICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICAgICAgaGVhZGVyczogeyBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiB9LFxuICAgICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyBjb250ZW50IH0pLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHJlc3BvbnNlLm9rKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGJvZHkgPSAoYXdhaXQgcmVzcG9uc2UudGV4dCgpKS5zbGljZSgwLCBNQVhfRVJST1JfQk9EWV9MRU5HVEgpO1xuICAgICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSA0MjkgJiYgYXR0ZW1wdCA8IE1BWF9TRU5EX0FUVEVNUFRTKSB7XG4gICAgICAgICAgICBsZXQgcmV0cnlBZnRlciA9IE51bWJlcihyZXNwb25zZS5oZWFkZXJzLmdldChcInJldHJ5LWFmdGVyXCIpKTtcbiAgICAgICAgICAgIGxldCB3YWl0VGltZSA9IHJldHJ5QWZ0ZXIgJiYgcmV0cnlBZnRlciAqIDEwMDAgfHwgREVGQVVMVF9SQVRFX0xJTUlUX1dBSVQ7XG4gICAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgd2FpdFRpbWUpKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBFeHBlY3RlZCBhIDJ4eCByZXNwb25zZSBmcm9tIHRoZSBEaXNjb3JkIHdlYmhvb2ssIHdhcyAke3Jlc3BvbnNlLnN0YXR1c30gJHtyZXNwb25zZS5zdGF0dXNUZXh0fSwgYm9keSAke2JvZHl9YFxuICAgICAgICApO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcXVldWVTZW5kKHdlYmhvb2tVUkw6IHN0cmluZywgbWVzc2FnZTogc3RyaW5nKSB7XG4gICAgbGV0IHNlbmQgPSAoKSA9PiBwb3N0VG9XZWJob29rKHdlYmhvb2tVUkwsIG1lc3NhZ2UpO1xuICAgIGxldCByZXN1bHQgPSBzZW5kQ2hhaW4udGhlbihzZW5kLCBzZW5kKTtcbiAgICBzZW5kQ2hhaW4gPSByZXN1bHQuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKiogU2VuZHMgdG8gYW4gZXhwbGljaXQgd2ViaG9vayBVUkwsIGZvciB0b29saW5nIHRoYXQgYWN0cyBvbiBhIHdlYmhvb2sgYmVmb3JlIChvciBpbnN0ZWFkIG9mKVxuICAgIGNvbmZpZ3VyZURpc2NvcmROb3RpZmljYXRpb25zIC0gc2V0dXAsIG1pZ3JhdGlvbnMsIGNvbm5lY3Rpdml0eSBjaGVja3MuICovXG5leHBvcnQgZnVuY3Rpb24gc2VuZFRvV2ViaG9va1VSTChjb25maWc6IHsgd2ViaG9va1VSTDogc3RyaW5nOyBtZXNzYWdlOiBzdHJpbmcgfSkge1xuICAgIHJldHVybiBxdWV1ZVNlbmQoY29uZmlnLndlYmhvb2tVUkwsIGNvbmZpZy5tZXNzYWdlKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY2hlY2tXZWJob29rRmlsZUNoYW5nZWQoKSB7XG4gICAgbGV0IHN0YXRlID0gbm90aWZpY2F0aW9uU3RhdGU7XG4gICAgaWYgKCFzdGF0ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBuZXdXZWJob29rVVJMO1xuICAgIHRyeSB7XG4gICAgICAgIG5ld1dlYmhvb2tVUkwgPSBhd2FpdCByZWFkV2ViaG9va0ZpbGUoc3RhdGUuZmlsZVBhdGgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihgcG9ydHNlY3VyZTogRGlzY29yZCB3ZWJob29rIGZpbGUgaXMgbm8gbG9uZ2VyIHJlYWRhYmxlLCBzdGlsbCB1c2luZyB0aGUgbG9hZGVkIHdlYmhvb2suICR7ZX1gKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAobmV3V2ViaG9va1VSTCA9PT0gc3RhdGUud2ViaG9va1VSTCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIFdhcm4gdGhlIG9sZCBjaGFubmVsIGZpcnN0LCB3aXRoIHRoZSBuZXcgd2ViaG9vayByZWRhY3RlZCwgc28gYSBzdG9sZW4gb2xkIHdlYmhvb2sgZG9lcyBub3RcbiAgICAvLyBoYW5kIHRoZSBhdHRhY2tlciBhIHVzYWJsZSBuZXcgb25lLlxuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHF1ZXVlU2VuZChcbiAgICAgICAgICAgIHN0YXRlLndlYmhvb2tVUkwsXG4gICAgICAgICAgICBgKipwb3J0c2VjdXJlKio6ICoqTk9USUZJQ0FUSU9OUyBBUkUgTU9WSU5HIFRPIEFOT1RIRVIgQ0hBTk5FTCoqYFxuICAgICAgICAgICAgKyBgXFxuXFxuVGhpcyBjaGFubmVsIHN0b3BzIHJlY2VpdmluZyB0aGVtIG5vdy4gSWYgdGhhdCB3YXMgbm90IHlvdSwgc29tZWJvZHkgd2l0aCBhY2Nlc3NgXG4gICAgICAgICAgICArIGAgdG8gdGhpcyBtYWNoaW5lIGp1c3QgcmVkaXJlY3RlZCBpdHMgYWxlcnRzLmBcbiAgICAgICAgICAgICsgYFxcblxcbm5ldyB3ZWJob29rOiBcXGAke3JlZGFjdFdlYmhvb2tVUkwobmV3V2ViaG9va1VSTCl9XFxgYFxuICAgICAgICAgICAgKyBgXFxuc2V0IGluOiBcXGAke3N0YXRlLmZpbGVQYXRofVxcYGBcbiAgICAgICAgKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYHBvcnRzZWN1cmU6IGZhaWxlZCB0byB3YXJuIHRoZSBvbGQgRGlzY29yZCB3ZWJob29rIGFib3V0IHRoZSBjaGFuZ2UuICR7ZX1gKTtcbiAgICB9XG4gICAgc3RhdGUud2ViaG9va1VSTCA9IG5ld1dlYmhvb2tVUkw7XG59XG5cbi8qKiBNdXN0IGJlIGNhbGxlZCBvbmNlIG9uIHN0YXJ0dXAsIGJlZm9yZSBhbnkgbm90aWZpY2F0aW9uIGlzIHNlbnQuIEFib3J0cyB0aGUgcHJvY2VzcyBpZiB0aGVcbiAgICB3ZWJob29rIGZpbGUgaXMgbWlzc2luZyBvciBpbnZhbGlkLCB0aGVuIHJlLWNoZWNrcyB0aGUgZmlsZSBvbiBhbiBpbnRlcnZhbCBhbmQgd2FybnMgdGhlIG9sZFxuICAgIHdlYmhvb2sgd2hlbmV2ZXIgaXQgY2hhbmdlcy4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjb25maWd1cmVEaXNjb3JkTm90aWZpY2F0aW9ucyhjb25maWc/OiB7XG4gICAgZmlsZVBhdGg/OiBzdHJpbmc7XG4gICAgY2hlY2tJbnRlcnZhbD86IG51bWJlcjtcbn0pIHtcbiAgICBpZiAobm90aWZpY2F0aW9uU3RhdGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBjb25maWd1cmVEaXNjb3JkTm90aWZpY2F0aW9ucyB0byBiZSBjYWxsZWQgb25jZSwgd2FzIGNhbGxlZCBhZ2FpbiAoYWxyZWFkeSB1c2luZyAke25vdGlmaWNhdGlvblN0YXRlLmZpbGVQYXRofSlgKTtcbiAgICB9XG4gICAgbGV0IGZpbGVQYXRoID0gY29uZmlnPy5maWxlUGF0aCB8fCBERUZBVUxUX1dFQkhPT0tfRklMRV9QQVRIO1xuICAgIGxldCBjaGVja0ludGVydmFsID0gY29uZmlnPy5jaGVja0ludGVydmFsIHx8IERFRkFVTFRfQ0hFQ0tfSU5URVJWQUw7XG4gICAgbGV0IHdlYmhvb2tVUkw7XG4gICAgdHJ5IHtcbiAgICAgICAgd2ViaG9va1VSTCA9IGF3YWl0IHJlYWRXZWJob29rRmlsZShmaWxlUGF0aCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBwb3J0c2VjdXJlOiByZWZ1c2luZyB0byBzdGFydCB3aXRob3V0IGEgdmFsaWQgRGlzY29yZCB3ZWJob29rIGZpbGUuXFxuJHtlfWApO1xuICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuICAgIGxldCBjaGVja1RpbWVyID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICBjaGVja1dlYmhvb2tGaWxlQ2hhbmdlZCgpLmNhdGNoKGUgPT4gY29uc29sZS5lcnJvcihgcG9ydHNlY3VyZTogRGlzY29yZCB3ZWJob29rIGZpbGUgY2hlY2sgZmFpbGVkLiAke2V9YCkpO1xuICAgIH0sIGNoZWNrSW50ZXJ2YWwpO1xuICAgIC8vIFRoZSBjaGVjayBzaG91bGQgbmV2ZXIgYmUgdGhlIHJlYXNvbiB0aGUgcHJvY2VzcyBzdGF5cyBhbGl2ZS5cbiAgICBjaGVja1RpbWVyLnVucmVmKCk7XG4gICAgbm90aWZpY2F0aW9uU3RhdGUgPSB7IGZpbGVQYXRoLCB3ZWJob29rVVJMLCBjaGVja1RpbWVyIH07XG4gICAgcmV0dXJuIHsgZmlsZVBhdGgsIGNoZWNrSW50ZXJ2YWwgfTtcbn1cblxuLy8gRE8gTk9UIGFkZCBuZXcgY2FsbHMgdG8gdGhpcy4gRXZlcnkgbWVzc2FnZSBnb2VzIHRvIGEgcmVhbCBEaXNjb3JkIHNlcnZlciBzb21lb25lIHJlYWRzLCBzbyBhXG4vLyBub3RpZmljYXRpb24gaXMgb25seSBldmVyIGFkZGVkIHdoZW4gdGhlIHVzZXIgZXhwbGljaXRseSBhc2tzIGZvciB0aGF0IHNwZWNpZmljIGNhc2UuIFN0YXJ0dXAsXG4vLyBzdWNjZXNzLCBlcnJvcnMsIHJldHJpZXMgYW5kIHJlY292ZXJpZXMgYWxsIGJlbG9uZyBpbiBhIGxvZyBpbnN0ZWFkLlxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlbmREaXNjb3JkTm90aWZpY2F0aW9uKG1lc3NhZ2U6IHN0cmluZykge1xuICAgIGxldCBzdGF0ZSA9IG5vdGlmaWNhdGlvblN0YXRlO1xuICAgIGlmICghc3RhdGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBjb25maWd1cmVEaXNjb3JkTm90aWZpY2F0aW9ucyB0byBiZSBjYWxsZWQgYmVmb3JlIHNlbmRpbmcsIHdhcyBjYWxsZWQgd2l0aCBtZXNzYWdlICR7bWVzc2FnZS5zbGljZSgwLCBNQVhfRVJST1JfQk9EWV9MRU5HVEgpfWApO1xuICAgIH1cbiAgICBhd2FpdCBxdWV1ZVNlbmQoc3RhdGUud2ViaG9va1VSTCwgbWVzc2FnZSk7XG59XG5cbi8qKiBXaGV0aGVyIG5vdGlmaWNhdGlvbnMgYXJlIHNldCB1cCBpbiB0aGlzIHByb2Nlc3MuIEZvciBjb2RlIHRoYXQgbWF5IHJ1biBvdXRzaWRlIHRoZSBkYWVtb24sXG4gICAgd2hlcmUgc2VuZGluZyBpcyB3b3J0aCBkb2luZyBpZiBpdCBjYW4gYmUgYW5kIG5vdCB3b3J0aCBmYWlsaW5nIG92ZXIgaWYgaXQgY2Fubm90LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFyZURpc2NvcmROb3RpZmljYXRpb25zQ29uZmlndXJlZCgpIHtcbiAgICByZXR1cm4gISFub3RpZmljYXRpb25TdGF0ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0b3BEaXNjb3JkTm90aWZpY2F0aW9ucygpIHtcbiAgICBpZiAoIW5vdGlmaWNhdGlvblN0YXRlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY2xlYXJJbnRlcnZhbChub3RpZmljYXRpb25TdGF0ZS5jaGVja1RpbWVyKTtcbiAgICBub3RpZmljYXRpb25TdGF0ZSA9IHVuZGVmaW5lZDtcbn1cbiJdfQ==
|
|
206
|
+
/* _JS_SOURCE_HASH = "abb6e0b243d1d85cb4a3599020263d0b3164ce4bf2aef2aa81489e304cd43b4c"; */
|