UNPKG

78 kBJavaScriptView Raw
1"use strict";
2function __export(m) {
3 for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
4}
5var __importDefault = (this && this.__importDefault) || function (mod) {
6 return (mod && mod.__esModule) ? mod : { "default": mod };
7};
8Object.defineProperty(exports, "__esModule", { value: true });
9const installer_1 = require("@xmcl/installer");
10const net_1 = require("@xmcl/net");
11const task_1 = __importDefault(require("@xmcl/task"));
12const unzip_1 = __importDefault(require("@xmcl/unzip"));
13const util_1 = require("@xmcl/util");
14const version_1 = require("@xmcl/version");
15const path_1 = require("path");
16async function findMainClass(lib) {
17 const zip = await unzip_1.default.open(lib, { lazyEntries: true });
18 const [manifest] = await zip.filterEntries(["META-INF/MANIFEST.MF"]);
19 let mainClass;
20 if (manifest) {
21 const content = await zip.readEntry(manifest).then((b) => b.toString());
22 const mainClassPair = content.split("\n").map((l) => l.split(": ")).filter((arr) => arr[0] === "Main-Class")[0];
23 if (mainClassPair) {
24 mainClass = mainClassPair[1].trim();
25 }
26 }
27 zip.close();
28 return mainClass;
29}
30/**
31 * The forge installer Module to install forge to the game
32 */
33var ForgeInstaller;
34(function (ForgeInstaller) {
35 ForgeInstaller.DEFAULT_FORGE_MAVEN = "http://files.minecraftforge.net";
36 /**
37 * Diagnose for specific forge version. Majorly for the current installer forge. (mcversion >= 1.13)
38 *
39 * Don't use this with the version less than 1.13
40 * @param versionOrProfile If the version string present, it will try to find the installer profile under version folder. Otherwise it will use presented installer profile to diagnose
41 * @param minecraft The minecraft location.
42 */
43 async function diagnoseForgeVersion(versionOrProfile, minecraft) {
44 const version = typeof versionOrProfile === "string" ? versionOrProfile : versionOrProfile.version;
45 const mc = util_1.MinecraftFolder.from(minecraft);
46 const verRoot = mc.getVersionRoot(version);
47 const versionJsonPath = mc.getVersionJson(version);
48 const diag = {
49 badProcessedFiles: [],
50 missingInstallDependencies: [],
51 badVersionJson: false,
52 missingBinpatch: false,
53 badInstall: false,
54 missingSrgJar: false,
55 missingMinecraftExtraJar: false,
56 missingForgePatchesJar: false,
57 };
58 let prof;
59 if (typeof versionOrProfile === "string") {
60 const installProfPath = path_1.join(verRoot, "install_profile.json");
61 if (await util_1.vfs.exists(installProfPath)) {
62 prof = JSON.parse(await util_1.vfs.readFile(installProfPath).then((b) => b.toString()));
63 }
64 }
65 else {
66 prof = versionOrProfile;
67 }
68 if (prof) {
69 const processedProfile = postProcessInstallProfile(mc, prof);
70 for (const proc of processedProfile.processors) {
71 if (proc.outputs) {
72 let bad = false;
73 for (const file in proc.outputs) {
74 if (!await util_1.vfs.validateSha1(file, proc.outputs[file].replace(/'/g, ""))) {
75 bad = true;
76 break;
77 }
78 }
79 if (bad) {
80 diag.badProcessedFiles.push(proc);
81 }
82 }
83 }
84 // if we have to process file, we have to check if the forge deps are ready
85 if (diag.badProcessedFiles.length !== 0) {
86 const libValidMask = await Promise.all(processedProfile.libraries.map(async (lib) => {
87 const artifact = lib.downloads.artifact;
88 const libPath = mc.getLibraryByPath(artifact.path);
89 if (await util_1.vfs.exists(libPath)) {
90 return artifact.sha1 ? util_1.vfs.validateSha1(libPath, artifact.sha1) : true;
91 }
92 return false;
93 }));
94 const missingLibraries = processedProfile.libraries.filter((_, i) => !libValidMask[i]);
95 diag.missingInstallDependencies.push(...missingLibraries);
96 const validClient = await util_1.vfs.stat(processedProfile.data.BINPATCH.client).then((s) => s.size !== 0).catch((_) => false);
97 if (!validClient) {
98 diag.missingBinpatch = true;
99 diag.badInstall = true;
100 }
101 }
102 }
103 if (await util_1.vfs.exists(versionJsonPath)) {
104 const versionJSON = JSON.parse(await util_1.vfs.readFile(versionJsonPath).then((b) => b.toString()));
105 if (versionJSON.arguments && versionJSON.arguments.game) {
106 const args = versionJSON.arguments.game;
107 const forgeVersion = args.indexOf("--fml.forgeVersion") + 1;
108 const mcVersion = args.indexOf("--fml.mcVersion") + 1;
109 const mcpVersion = args.indexOf("--fml.mcpVersion") + 1;
110 if (!forgeVersion || !mcVersion || !mcpVersion) {
111 diag.badVersionJson = true;
112 diag.badInstall = true;
113 }
114 else {
115 const srgPath = mc.getLibraryByPath(`net/minecraft/client/${mcVersion}-${mcpVersion}/client-${mcVersion}-${mcpVersion}-srg.jar`);
116 const extraPath = mc.getLibraryByPath(`net/minecraft/client/${mcVersion}/client-${mcVersion}-extra.jar`);
117 const forgePatchPath = mc.getLibraryByPath(`net/minecraftforge/forge/${mcVersion}-${forgeVersion}/forge-${mcVersion}-${forgeVersion}-client.jar`);
118 diag.missingSrgJar = await util_1.vfs.missing(srgPath);
119 diag.missingMinecraftExtraJar = await util_1.vfs.missing(extraPath);
120 diag.missingForgePatchesJar = await util_1.vfs.missing(forgePatchPath);
121 }
122 }
123 else {
124 diag.badVersionJson = true;
125 diag.badInstall = true;
126 }
127 }
128 else {
129 diag.badVersionJson = true;
130 diag.badInstall = true;
131 }
132 return diag;
133 }
134 ForgeInstaller.diagnoseForgeVersion = diagnoseForgeVersion;
135 /**
136 * Post processing function for new forge installer (mcversion >= 1.13). You can use this with `ForgeInstaller.diagnose`.
137 *
138 * @param mc The minecraft location
139 * @param proc The processor
140 * @param java The java executor
141 */
142 async function postProcess(mc, proc, java) {
143 const jarRealPath = mc.getLibraryByPath(version_1.Version.getLibraryInfo(proc.jar).path);
144 const mainClass = await findMainClass(jarRealPath);
145 if (!mainClass) {
146 throw new Error(`Cannot find main class for processor ${proc.jar}.`);
147 }
148 const cp = [...proc.classpath, proc.jar].map(version_1.Version.getLibraryInfo).map((p) => mc.getLibraryByPath(p.path)).join(path_1.delimiter);
149 const cmd = ["-cp", cp, mainClass, ...proc.args];
150 await java(cmd);
151 let failed = false;
152 if (proc.outputs) {
153 for (const file in proc.outputs) {
154 if (!await util_1.vfs.validateSha1(file, proc.outputs[file].replace(/'/g, ""))) {
155 console.error(`Fail to process ${proc.jar} @ ${file} since its validation failed.`);
156 failed = true;
157 }
158 }
159 }
160 if (failed) {
161 console.error(`Java arguments: ${JSON.stringify(cmd)}`);
162 throw new Error("Fail to process post processing since its validation failed.");
163 }
164 }
165 ForgeInstaller.postProcess = postProcess;
166 function postProcessInstallProfile(mc, installProfile) {
167 function processValue(v) {
168 if (v.match(/^\[.+\]$/g)) {
169 const targetId = v.substring(1, v.length - 1);
170 return mc.getLibraryByPath(version_1.Version.getLibraryInfo(targetId).path);
171 }
172 return v;
173 }
174 function processMapping(data, m) {
175 m = processValue(m);
176 if (m.match(/^{.+}$/g)) {
177 const key = m.substring(1, m.length - 1);
178 m = data[key].client;
179 }
180 return m;
181 }
182 const profile = JSON.parse(JSON.stringify(installProfile));
183 profile.data.MINECRAFT_JAR = {
184 client: mc.getVersionJar(profile.minecraft),
185 server: "",
186 };
187 for (const key in profile.data) {
188 const value = profile.data[key];
189 value.client = processValue(value.client);
190 value.server = processValue(value.server);
191 if (key === "BINPATCH") {
192 const verRoot = mc.getVersionRoot(profile.version);
193 value.client = path_1.join(verRoot, value.client);
194 value.server = path_1.join(verRoot, value.server);
195 }
196 }
197 for (const proc of profile.processors) {
198 proc.args = proc.args.map((a) => processMapping(profile.data, a));
199 if (proc.outputs) {
200 const replacedOutput = {};
201 for (const key in proc.outputs) {
202 replacedOutput[processMapping(profile.data, key)] = processMapping(profile.data, proc.outputs[key]);
203 }
204 proc.outputs = replacedOutput;
205 }
206 }
207 return profile;
208 }
209 /**
210 * Install for forge installer step 2 and 3.
211 * @param version The version string or installer profile
212 * @param minecraft The minecraft location
213 */
214 function installByInstallerPartialTask(version, minecraft, option = {}) {
215 return async function installForge(context) {
216 const mc = util_1.MinecraftFolder.from(minecraft);
217 let prof;
218 let ver;
219 if (typeof version === "string") {
220 const versionRoot = mc.getVersionRoot(version);
221 prof = await util_1.vfs.readFile(path_1.join(versionRoot, "install_profile.json")).then((b) => b.toString()).then(JSON.parse);
222 }
223 else {
224 prof = version;
225 }
226 ver = await util_1.vfs.readFile(mc.getVersionJson(prof.version)).then((b) => b.toString()).then(JSON.parse);
227 await installByInstallerPartialWork(mc, prof, ver, option.java || util_1.JavaExecutor.createSimple("java"), option)(context);
228 };
229 }
230 ForgeInstaller.installByInstallerPartialTask = installByInstallerPartialTask;
231 /**
232 * Install for forge installer step 2 and 3.
233 * @param version The version string or installer profile
234 * @param minecraft The minecraft location
235 */
236 async function installByInstallerPartial(version, minecraft, option = {}) {
237 return task_1.default.execute(installByInstallerPartialTask(version, minecraft, option)).wait();
238 }
239 ForgeInstaller.installByInstallerPartial = installByInstallerPartial;
240 function installByInstallerPartialWork(mc, profile, versionJson, java, installLibOption) {
241 return async (context) => {
242 profile = postProcessInstallProfile(mc, profile);
243 const parsedLibs = version_1.Version.resolveLibraries([...profile.libraries, ...versionJson.libraries]);
244 await context.execute(installer_1.Installer.installLibrariesDirectTask(parsedLibs, mc, {
245 ...installLibOption,
246 libraryHost: installLibOption.libraryHost ? (l) => {
247 if (l.artifactId === "forge" && l.groupId === "net.minecraftforge") {
248 return `file://${mc.getLibraryByPath(l.path)}`;
249 }
250 return installLibOption.libraryHost(l);
251 } : undefined,
252 }));
253 await context.execute(async function postProcessing(ctx) {
254 ctx.update(0, profile.processors.length);
255 let i = 0;
256 const errs = [];
257 for (const proc of profile.processors) {
258 try {
259 await postProcess(mc, proc, java);
260 }
261 catch (e) {
262 errs.push(e);
263 }
264 ctx.update(i += 1, profile.processors.length);
265 }
266 i += 1;
267 ctx.update(i, profile.processors.length);
268 if (errs.length !== 0) {
269 throw new Error("Fail to post processing");
270 }
271 });
272 };
273 }
274 function installByInstallerTask(version, minecraft, maven, installLibOption, java) {
275 return async function installForge(context) {
276 const mc = util_1.MinecraftFolder.from(minecraft);
277 const forgeVersion = `${version.mcversion}-${version.version}`;
278 const installerURL = `${maven}${version.installer.path}`;
279 const installerURLFallback = `${maven}/maven/net/minecraftforge/forge/${forgeVersion}/forge-${forgeVersion}-installer.jar`;
280 const installJar = mc.getLibraryByPath(version.installer.path.substring(version.installer.path.substring(1).indexOf("/") + 1));
281 let versionId;
282 let profile;
283 let versionJson;
284 function downloadInstallerTask(installer, dest) {
285 return async function downloadInstaller(ctx) {
286 await net_1.downloadFileIfAbsentWork({
287 url: installer,
288 destination: dest,
289 checksum: {
290 hash: version.installer.sha1,
291 algorithm: "sha1",
292 },
293 })(ctx);
294 return util_1.vfs.createReadStream(dest).pipe(unzip_1.default.createParseStream({ lazyEntries: true })).wait();
295 };
296 }
297 async function processVersion(zip, installProfileEntry, versionEntry, clientDataEntry) {
298 profile = await zip.readEntry(installProfileEntry).then((b) => b.toString()).then(JSON.parse);
299 versionJson = await zip.readEntry(versionEntry).then((b) => b.toString()).then(JSON.parse);
300 versionId = versionJson.id;
301 const rootPath = mc.getVersionRoot(versionJson.id);
302 const jsonPath = path_1.join(rootPath, `${versionJson.id}.json`);
303 const installJsonPath = path_1.join(rootPath, "install_profile.json");
304 const clientDataPath = path_1.join(rootPath, profile.data.BINPATCH.client);
305 await util_1.vfs.ensureFile(jsonPath);
306 await util_1.vfs.writeFile(installJsonPath, JSON.stringify(profile));
307 await util_1.vfs.writeFile(jsonPath, JSON.stringify(versionJson));
308 await util_1.vfs.ensureFile(clientDataPath);
309 const stream = await zip.openEntry(clientDataEntry);
310 await util_1.vfs.waitStream(stream.pipe(util_1.vfs.createWriteStream(clientDataPath)));
311 }
312 async function processExtractLibrary(stream, p) {
313 const file = mc.getLibraryByPath(p.substring(p.indexOf("/") + 1));
314 await util_1.vfs.ensureFile(file);
315 await util_1.vfs.waitStream(stream.pipe(util_1.vfs.createWriteStream(file)));
316 }
317 try {
318 let zip;
319 try {
320 zip = await context.execute(downloadInstallerTask(installerURL, installJar));
321 }
322 catch (_a) {
323 zip = await context.execute(downloadInstallerTask(installerURLFallback, installJar));
324 }
325 const [forgeEntry, forgeUniversalEntry, clientDataEntry, installProfileEntry, versionEntry] = await zip.filterEntries([
326 `maven/net/minecraftforge/forge/${forgeVersion}/forge-${forgeVersion}.jar`,
327 `maven/net/minecraftforge/forge/${forgeVersion}/forge-${forgeVersion}-universal.jar`,
328 "data/client.lzma",
329 "install_profile.json",
330 "version.json"
331 ]);
332 if (!forgeEntry) {
333 throw new Error("Missing forge jar entry");
334 }
335 if (!forgeUniversalEntry) {
336 throw new Error("Missing forge universal entry");
337 }
338 if (!installProfileEntry) {
339 throw new Error("Missing install profile");
340 }
341 if (!versionEntry) {
342 throw new Error("Missing version entry");
343 }
344 await processExtractLibrary(await zip.openEntry(forgeEntry), forgeEntry.fileName);
345 await processExtractLibrary(await zip.openEntry(forgeUniversalEntry), forgeUniversalEntry.fileName);
346 await processVersion(zip, installProfileEntry, versionEntry, clientDataEntry);
347 await installByInstallerPartialWork(mc, profile, versionJson, java, installLibOption)(context);
348 return versionId;
349 }
350 catch (e) {
351 console.error(`Cannot install forge by installer ${version.version}`);
352 throw e;
353 }
354 };
355 }
356 function installByUniversalTask(version, minecraft, maven) {
357 return async function installForge(context) {
358 const mc = util_1.MinecraftFolder.from(minecraft);
359 const forgeVersion = `${version.mcversion}-${version.version}`;
360 const paths = version.universal.path.split("/");
361 const realForgeVersion = paths[paths.length - 2];
362 const jarPath = mc.getLibraryByPath(`net/minecraftforge/forge/${realForgeVersion}/forge-${realForgeVersion}.jar`);
363 let fullVersion;
364 let realJarPath;
365 const universalURLFallback = `${maven}/maven/net/minecraftforge/forge/${forgeVersion}/forge-${forgeVersion}-universal.jar`;
366 const universalURL = `${maven}${version.universal.path}`;
367 await context.execute(async function installForgeJar() {
368 if (await util_1.vfs.exists(jarPath)) {
369 const valid = await util_1.vfs.validate(jarPath, { algorithm: "md5", hash: version.universal.md5 }, { algorithm: "sha1", hash: version.universal.sha1 });
370 if (valid) {
371 return;
372 }
373 }
374 function downloadJar(ctx) {
375 return net_1.downloadFileWork({ url: universalURL, destination: jarPath })(ctx);
376 }
377 await context.execute(downloadJar);
378 });
379 await context.execute(async function installForgeJson() {
380 const zip = await unzip_1.default.open(jarPath, { lazyEntries: true });
381 const [versionEntry] = await zip.filterEntries(["version.json"]);
382 if (versionEntry) {
383 const buf = await zip.readEntry(versionEntry);
384 const raw = JSON.parse(buf.toString());
385 const id = raw.id;
386 fullVersion = id;
387 const rootPath = mc.getVersionRoot(fullVersion);
388 realJarPath = mc.getLibraryByPath(version_1.Version.getLibraryInfo(raw.libraries.find((l) => l.name.startsWith("net.minecraftforge:forge"))).path);
389 await util_1.vfs.ensureDir(rootPath);
390 const jsonPath = path_1.join(rootPath, `${id}.json`);
391 if (await util_1.vfs.missing(jsonPath)) {
392 await util_1.vfs.writeFile(jsonPath, buf);
393 }
394 }
395 else {
396 throw new Error(`Cannot install forge json for ${version.version} since the version json is missing!`);
397 }
398 });
399 if (realJarPath !== jarPath) {
400 await util_1.vfs.ensureFile(realJarPath);
401 await util_1.vfs.copyFile(jarPath, realJarPath);
402 await util_1.vfs.unlink(jarPath);
403 }
404 return fullVersion;
405 };
406 }
407 /**
408 * Install forge to target location.
409 * Installation task for forge with mcversion >= 1.13 requires java installed on your pc.
410 * @param version The forge version meta
411 */
412 function install(version, minecraft, option) {
413 return task_1.default.execute(installTask(version, minecraft, option)).wait();
414 }
415 ForgeInstaller.install = install;
416 /**
417 * Install forge to target location.
418 * Installation task for forge with mcversion >= 1.13 requires java installed on your pc.
419 * @param version The forge version meta
420 */
421 function installTask(version, minecraft, option = {}) {
422 let byInstaller = true;
423 try {
424 const minorVersion = Number.parseInt(version.mcversion.split(".")[1], 10);
425 byInstaller = minorVersion >= 13;
426 }
427 catch (_a) { }
428 const work = byInstaller
429 ? installByInstallerTask(version, minecraft, option.maven || ForgeInstaller.DEFAULT_FORGE_MAVEN, option, option.java || util_1.JavaExecutor.createSimple("java"))
430 : installByUniversalTask(version, minecraft, option.maven || ForgeInstaller.DEFAULT_FORGE_MAVEN);
431 return work;
432 }
433 ForgeInstaller.installTask = installTask;
434})(ForgeInstaller = exports.ForgeInstaller || (exports.ForgeInstaller = {}));
435__export(require("./forgeweb"));
436exports.default = ForgeInstaller;
437//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQUFBLCtDQUE0QztBQUM1QyxtQ0FBdUU7QUFDdkUsc0RBQThCO0FBQzlCLHdEQUFnQztBQUNoQyxxQ0FBbUY7QUFDbkYsMkNBQXdDO0FBQ3hDLCtCQUF1QztBQUd2QyxLQUFLLFVBQVUsYUFBYSxDQUFDLEdBQVc7SUFDcEMsTUFBTSxHQUFHLEdBQUcsTUFBTSxlQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3pELE1BQU0sQ0FBQyxRQUFRLENBQUMsR0FBRyxNQUFNLEdBQUcsQ0FBQyxhQUFhLENBQUMsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUM7SUFDckUsSUFBSSxTQUE2QixDQUFDO0lBQ2xDLElBQUksUUFBUSxFQUFFO1FBQ1YsTUFBTSxPQUFPLEdBQUcsTUFBTSxHQUFHLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDeEUsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNoSCxJQUFJLGFBQWEsRUFBRTtZQUNmLFNBQVMsR0FBRyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDdkM7S0FDSjtJQUNELEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FB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QU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLEtBQUssSUFBSSxlQUFBLG1CQUFtQixFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxJQUFJLG1CQUFZLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzNJLENBQUMsQ0FBQyxzQkFBc0IsQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sQ0FBQyxLQUFLLElBQUksZUFBQSxtQkFBbUIsQ0FBQyxDQUFDO1FBQ3RGLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFiZSwwQkFBVyxjQWExQixDQUFBO0FBQ0wsQ0FBQyxFQXpnQmdCLGNBQWMsR0FBZCxzQkFBYyxLQUFkLHNCQUFjLFFBeWdCOUI7QUFFRCxnQ0FBMkI7QUFFM0Isa0JBQWUsY0FBYyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5zdGFsbGVyIH0gZnJvbSBcIkB4bWNsL2luc3RhbGxlclwiO1xuaW1wb3J0IHsgZG93bmxvYWRGaWxlSWZBYnNlbnRXb3JrLCBkb3dubG9hZEZpbGVXb3JrIH0gZnJvbSBcIkB4bWNsL25ldFwiO1xuaW1wb3J0IFRhc2sgZnJvbSBcIkB4bWNsL3Rhc2tcIjtcbmltcG9ydCBVbnppcCBmcm9tIFwiQHhtY2wvdW56aXBcIjtcbmltcG9ydCB7IE1pbmVjcmFmdEZvbGRlciwgTWluZWNyYWZ0TG9jYXRpb24sIEphdmFFeGVjdXRvciwgdmZzIH0gZnJvbSBcIkB4bWNsL3V0aWxcIjtcbmltcG9ydCB7IFZlcnNpb24gfSBmcm9tIFwiQHhtY2wvdmVyc2lvblwiO1xuaW1wb3J0IHsgZGVsaW1pdGVyLCBqb2luIH0gZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IFJlYWRhYmxlIH0gZnJvbSBcInN0cmVhbVwiO1xuXG5hc3luYyBmdW5jdGlvbiBmaW5kTWFpbkNsYXNzKGxpYjogc3RyaW5nKSB7XG4gICAgY29uc3QgemlwID0gYXdhaXQgVW56aXAub3BlbihsaWIsIHsgbGF6eUVudHJpZXM6IHRydWUgfSk7XG4gICAgY29uc3QgW21hbmlmZXN0XSA9IGF3YWl0IHppcC5maWx0ZXJFbnRyaWVzKFtcIk1FVEEtSU5GL01BTklGRVNULk1GXCJdKTtcbiAgICBsZXQgbWFpbkNsYXNzOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgaWYgKG1hbmlmZXN0KSB7XG4gICAgICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCB6aXAucmVhZEVudHJ5KG1hbmlmZXN0KS50aGVuKChiKSA9PiBiLnRvU3RyaW5nKCkpO1xuICAgICAgICBjb25zdCBtYWluQ2xhc3NQYWlyID0gY29udGVudC5zcGxpdChcIlxcblwiKS5tYXAoKGwpID0+IGwuc3BsaXQoXCI6IFwiKSkuZmlsdGVyKChhcnIpID0+IGFyclswXSA9PT0gXCJNYWluLUNsYXNzXCIpWzBdO1xuICAgICAgICBpZiAobWFpbkNsYXNzUGFpcikge1xuICAgICAgICAgICAgbWFpbkNsYXNzID0gbWFpbkNsYXNzUGFpclsxXS50cmltKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgemlwLmNsb3NlKCk7XG4gICAgcmV0dXJuIG1haW5DbGFzcztcbn1cblxuLyoqXG4gKiBUaGUgZm9yZ2UgaW5zdGFsbGVyIE1vZHVsZSB0byBpbnN0YWxsIGZvcmdlIHRvIHRoZSBnYW1lXG4gKi9cbmV4cG9ydCBuYW1lc3BhY2UgRm9yZ2VJbnN0YWxsZXIge1xuICAgIC8qKlxuICAgICAqIFRoZSBmb3JnZSB2ZXJzaW9uIG1ldGFkYXRhIHRvIGRvd25sb2FkIGEgZm9yZ2VcbiAgICAgKi9cbiAgICBleHBvcnQgaW50ZXJmYWNlIFZlcnNpb25NZXRhIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoZSBpbnN0YWxsZXIgaW5mb1xuICAgICAgICAgKi9cbiAgICAgICAgaW5zdGFsbGVyOiB7XG4gICAgICAgICAgICBtZDU6IHN0cmluZztcbiAgICAgICAgICAgIHNoYTE6IHN0cmluZztcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogVGhlIHVybCBwYXRoIHRvIGNvbmNhdCB3aXRoIGZvcmdlIG1hdmVuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHBhdGg6IHN0cmluZztcbiAgICAgICAgfTtcbiAgICAgICAgdW5pdmVyc2FsOiB7XG4gICAgICAgICAgICBtZDU6IHN0cmluZztcbiAgICAgICAgICAgIHNoYTE6IHN0cmluZztcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogVGhlIHVybCBwYXRoIHRvIGNvbmNhdCB3aXRoIGZvcmdlIG1hdmVuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHBhdGg6IHN0cmluZztcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoZSBtaW5lY3JhZnQgdmVyc2lvblxuICAgICAgICAgKi9cbiAgICAgICAgbWN2ZXJzaW9uOiBzdHJpbmc7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgZm9yZ2UgdmVyc2lvbiAod2l0aG91dCBtaW5lY3JhZnQgdmVyc2lvbilcbiAgICAgICAgICovXG4gICAgICAgIHZlcnNpb246IHN0cmluZztcbiAgICB9XG5cbiAgICBleHBvcnQgY29uc3QgREVGQVVMVF9GT1JHRV9NQVZFTiA9IFwiaHR0cDovL2ZpbGVzLm1pbmVjcmFmdGZvcmdlLm5ldFwiO1xuXG4gICAgZXhwb3J0IGludGVyZmFjZSBJbnN0YWxsUHJvZmlsZSB7XG4gICAgICAgIHNwZWM6IG51bWJlcjtcbiAgICAgICAgcHJvZmlsZTogc3RyaW5nO1xuICAgICAgICB2ZXJzaW9uOiBzdHJpbmc7XG4gICAgICAgIGpzb246IHN0cmluZztcbiAgICAgICAgcGF0aDogc3RyaW5nO1xuICAgICAgICBtaW5lY3JhZnQ6IHN0cmluZztcbiAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgW2tleTogc3RyaW5nXToge1xuICAgICAgICAgICAgICAgIGNsaWVudDogc3RyaW5nLFxuICAgICAgICAgICAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgICAgcHJvY2Vzc29yczogQXJyYXk8e1xuICAgICAgICAgICAgamFyOiBzdHJpbmcsXG4gICAgICAgICAgICBjbGFzc3BhdGg6IHN0cmluZ1tdLFxuICAgICAgICAgICAgYXJnczogc3RyaW5nW10sXG4gICAgICAgICAgICBvdXRwdXRzPzoge1xuICAgICAgICAgICAgICAgIFtrZXk6IHN0cmluZ106IHN0cmluZyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0+O1xuICAgICAgICBsaWJyYXJpZXM6IFZlcnNpb24uTm9ybWFsTGlicmFyeVtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBmb3JnZSBkaWFnbm9zaXMgcmVwb3J0LiBJdCBtYXkgaGF2ZSBzb21lIGludGVyc2VjdGlvbiB3aXRoIGBWZXJzaW9uLkRpYWdub3Npc2AuXG4gICAgICovXG4gICAgZXhwb3J0IGludGVyZmFjZSBEaWFnbm9zaXMge1xuICAgICAgICAvKipcbiAgICAgICAgICogV2hlbiB0aGlzIGZsYWcgaXMgdHJ1ZSwgcGxlYXNlIHJlaW5zdGFsbCB0b3RhbGx5XG4gICAgICAgICAqL1xuICAgICAgICBiYWRJbnN0YWxsOiBib29sZWFuO1xuICAgICAgICAvKipcbiAgICAgICAgICogV2hlbiBvbmx5IHRoaXMgaXMgbm90IGVtcHR5XG4gICAgICAgICAqL1xuICAgICAgICBiYWRQcm9jZXNzZWRGaWxlczogQXJyYXk8SW5zdGFsbFByb2ZpbGVbXCJwcm9jZXNzb3JzXCJdW251bWJlcl0+O1xuICAgICAgICBiYWRWZXJzaW9uSnNvbjogYm9vbGVhbjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdoZW4gdGhpcyBpcyBub3QgZW1wdHksIHBsZWFzZSB1c2UgYHBvc3RQcm9jZXNzSW5zdGFsbFByb2ZpbGVgXG4gICAgICAgICAqL1xuICAgICAgICBtaXNzaW5nSW5zdGFsbERlcGVuZGVuY2llczogVmVyc2lvbi5Ob3JtYWxMaWJyYXJ5W107XG5cbiAgICAgICAgbWlzc2luZ0JpbnBhdGNoOiBib29sZWFuO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBbHQgZm9yIGJhZFByb2Nlc3NlZEZpbGVzXG4gICAgICAgICAqL1xuICAgICAgICBtaXNzaW5nU3JnSmFyOiBib29sZWFuO1xuICAgICAgICAvKipcbiAgICAgICAgICogQWx0IGZvciBiYWRQcm9jZXNzZWRGaWxlc1xuICAgICAgICAgKi9cbiAgICAgICAgbWlzc2luZ01pbmVjcmFmdEV4dHJhSmFyOiBib29sZWFuO1xuICAgICAgICAvKipcbiAgICAgICAgICogQWx0IGZvciBiYWRQcm9jZXNzZWRGaWxlc1xuICAgICAgICAgKi9cbiAgICAgICAgbWlzc2luZ0ZvcmdlUGF0Y2hlc0phcjogYm9vbGVhbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEaWFnbm9zZSBmb3Igc3BlY2lmaWMgZm9yZ2UgdmVyc2lvbi4gTWFqb3JseSBmb3IgdGhlIGN1cnJlbnQgaW5zdGFsbGVyIGZvcmdlLiAobWN2ZXJzaW9uID49IDEuMTMpXG4gICAgICpcbiAgICAgKiBEb24ndCB1c2UgdGhpcyB3aXRoIHRoZSB2ZXJzaW9uIGxlc3MgdGhhbiAxLjEzXG4gICAgICogQHBhcmFtIHZlcnNpb25PclByb2ZpbGUgSWYgdGhlIHZlcnNpb24gc3RyaW5nIHByZXNlbnQsIGl0IHdpbGwgdHJ5IHRvIGZpbmQgdGhlIGluc3RhbGxlciBwcm9maWxlIHVuZGVyIHZlcnNpb24gZm9sZGVyLiBPdGhlcndpc2UgaXQgd2lsbCB1c2UgcHJlc2VudGVkIGluc3RhbGxlciBwcm9maWxlIHRvIGRpYWdub3NlXG4gICAgICogQHBhcmFtIG1pbmVjcmFmdCBUaGUgbWluZWNyYWZ0IGxvY2F0aW9uLlxuICAgICAqL1xuICAgIGV4cG9ydCBhc3luYyBmdW5jdGlvbiBkaWFnbm9zZUZvcmdlVmVyc2lvbih2ZXJzaW9uT3JQcm9maWxlOiBzdHJpbmcgfCBJbnN0YWxsUHJvZmlsZSwgbWluZWNyYWZ0OiBNaW5lY3JhZnRMb2NhdGlvbik6IFByb21pc2U8RGlhZ25vc2lzPiB7XG4gICAgICAgIGNvbnN0IHZlcnNpb24gPSB0eXBlb2YgdmVyc2lvbk9yUHJvZmlsZSA9PT0gXCJzdHJpbmdcIiA/IHZlcnNpb25PclByb2ZpbGUgOiB2ZXJzaW9uT3JQcm9maWxlLnZlcnNpb247XG4gICAgICAgIGNvbnN0IG1jID0gTWluZWNyYWZ0Rm9sZGVyLmZyb20obWluZWNyYWZ0KTtcbiAgICAgICAgY29uc3QgdmVyUm9vdCA9IG1jLmdldFZlcnNpb25Sb290KHZlcnNpb24pO1xuICAgICAgICBjb25zdCB2ZXJzaW9uSnNvblBhdGggPSBtYy5nZXRWZXJzaW9uSnNvbih2ZXJzaW9uKTtcblxuICAgICAgICBjb25zdCBkaWFnOiBEaWFnbm9zaXMgPSB7XG4gICAgICAgICAgICBiYWRQcm9jZXNzZWRGaWxlczogW10sXG4gICAgICAgICAgICBtaXNzaW5nSW5zdGFsbERlcGVuZGVuY2llczogW10sXG4gICAgICAgICAgICBiYWRWZXJzaW9uSnNvbjogZmFsc2UsXG4gICAgICAgICAgICBtaXNzaW5nQmlucGF0Y2g6IGZhbHNlLFxuICAgICAgICAgICAgYmFkSW5zdGFsbDogZmFsc2UsXG4gICAgICAgICAgICBtaXNzaW5nU3JnSmFyOiBmYWxzZSxcbiAgICAgICAgICAgIG1pc3NpbmdNaW5lY3JhZnRFeHRyYUphcjogZmFsc2UsXG4gICAgICAgICAgICBtaXNzaW5nRm9yZ2VQYXRjaGVzSmFyOiBmYWxzZSxcbiAgICAgICAgfTtcblxuICAgICAgICBsZXQgcHJvZjogSW5zdGFsbFByb2ZpbGUgfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmICh0eXBlb2YgdmVyc2lvbk9yUHJvZmlsZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgY29uc3QgaW5zdGFsbFByb2ZQYXRoID0gam9pbih2ZXJSb290LCBcImluc3RhbGxfcHJvZmlsZS5qc29uXCIpO1xuICAgICAgICAgICAgaWYgKGF3YWl0IHZmcy5leGlzdHMoaW5zdGFsbFByb2ZQYXRoKSkge1xuICAgICAgICAgICAgICAgIHByb2YgPSBKU09OLnBhcnNlKGF3YWl0IHZmcy5yZWFkRmlsZShpbnN0YWxsUHJvZlBhdGgpLnRoZW4oKGIpID0+IGIudG9TdHJpbmcoKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJvZiA9IHZlcnNpb25PclByb2ZpbGU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHByb2YpIHtcbiAgICAgICAgICAgIGNvbnN0IHByb2Nlc3NlZFByb2ZpbGUgPSBwb3N0UHJvY2Vzc0luc3RhbGxQcm9maWxlKG1jLCBwcm9mKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcHJvYyBvZiBwcm9jZXNzZWRQcm9maWxlLnByb2Nlc3NvcnMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJvYy5vdXRwdXRzKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBiYWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBmaWxlIGluIHByb2Mub3V0cHV0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEgYXdhaXQgdmZzLnZhbGlkYXRlU2hhMShmaWxlLCBwcm9jLm91dHB1dHNbZmlsZV0ucmVwbGFjZSgvJy9nLCBcIlwiKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChiYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpYWcuYmFkUHJvY2Vzc2VkRmlsZXMucHVzaChwcm9jKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGlmIHdlIGhhdmUgdG8gcHJvY2VzcyBmaWxlLCB3ZSBoYXZlIHRvIGNoZWNrIGlmIHRoZSBmb3JnZSBkZXBzIGFyZSByZWFkeVxuICAgICAgICAgICAgaWYgKGRpYWcuYmFkUHJvY2Vzc2VkRmlsZXMubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbGliVmFsaWRNYXNrID0gYXdhaXQgUHJvbWlzZS5hbGwocHJvY2Vzc2VkUHJvZmlsZS5saWJyYXJpZXMubWFwKGFzeW5jIChsaWIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYXJ0aWZhY3QgPSBsaWIuZG93bmxvYWRzLmFydGlmYWN0O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBsaWJQYXRoID0gbWMuZ2V0TGlicmFyeUJ5UGF0aChhcnRpZmFjdC5wYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGF3YWl0IHZmcy5leGlzdHMobGliUGF0aCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhcnRpZmFjdC5zaGExID8gdmZzLnZhbGlkYXRlU2hhMShsaWJQYXRoLCBhcnRpZmFjdC5zaGExKSA6IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICBjb25zdCBtaXNzaW5nTGlicmFyaWVzID0gcHJvY2Vzc2VkUHJvZmlsZS5saWJyYXJpZXMuZmlsdGVyKChfLCBpKSA9PiAhbGliVmFsaWRNYXNrW2ldKTtcbiAgICAgICAgICAgICAgICBkaWFnLm1pc3NpbmdJbnN0YWxsRGVwZW5kZW5jaWVzLnB1c2goLi4ubWlzc2luZ0xpYnJhcmllcyk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCB2YWxpZENsaWVudCA9IGF3YWl0IHZmcy5zdGF0KHByb2Nlc3NlZFByb2ZpbGUuZGF0YS5CSU5QQVRDSC5jbGllbnQpLnRoZW4oKHMpID0+IHMuc2l6ZSAhPT0gMCkuY2F0Y2goKF8pID0+IGZhbHNlKTtcbiAgICAgICAgICAgICAgICBpZiAoIXZhbGlkQ2xpZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGRpYWcubWlzc2luZ0JpbnBhdGNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgZGlhZy5iYWRJbnN0YWxsID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGF3YWl0IHZmcy5leGlzdHModmVyc2lvbkpzb25QYXRoKSkge1xuICAgICAgICAgICAgY29uc3QgdmVyc2lvbkpTT046IFZlcnNpb24gPSBKU09OLnBhcnNlKGF3YWl0IHZmcy5yZWFkRmlsZSh2ZXJzaW9uSnNvblBhdGgpLnRoZW4oKGIpID0+IGIudG9TdHJpbmcoKSkpO1xuICAgICAgICAgICAgaWYgKHZlcnNpb25KU09OLmFyZ3VtZW50cyAmJiB2ZXJzaW9uSlNPTi5hcmd1bWVudHMuZ2FtZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFyZ3MgPSB2ZXJzaW9uSlNPTi5hcmd1bWVudHMuZ2FtZTtcbiAgICAgICAgICAgICAgICBjb25zdCBmb3JnZVZlcnNpb24gPSBhcmdzLmluZGV4T2YoXCItLWZtbC5mb3JnZVZlcnNpb25cIikgKyAxO1xuICAgICAgICAgICAgICAgIGNvbnN0IG1jVmVyc2lvbiA9IGFyZ3MuaW5kZXhPZihcIi0tZm1sLm1jVmVyc2lvblwiKSArIDE7XG4gICAgICAgICAgICAgICAgY29uc3QgbWNwVmVyc2lvbiA9IGFyZ3MuaW5kZXhPZihcIi0tZm1sLm1jcFZlcnNpb25cIikgKyAxO1xuICAgICAgICAgICAgICAgIGlmICghZm9yZ2VWZXJzaW9uIHx8ICFtY1ZlcnNpb24gfHwgIW1jcFZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgZGlhZy5iYWRWZXJzaW9uSnNvbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGRpYWcuYmFkSW5zdGFsbCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3JnUGF0aCA9IG1jLmdldExpYnJhcnlCeVBhdGgoYG5ldC9taW5lY3JhZnQvY2xpZW50LyR7bWNWZXJzaW9ufS0ke21jcFZlcnNpb259L2NsaWVudC0ke21jVmVyc2lvbn0tJHttY3BWZXJzaW9ufS1zcmcuamFyYCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4dHJhUGF0aCA9IG1jLmdldExpYnJhcnlCeVBhdGgoYG5ldC9taW5lY3JhZnQvY2xpZW50LyR7bWNWZXJzaW9ufS9jbGllbnQtJHttY1ZlcnNpb259LWV4dHJhLmphcmApO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBmb3JnZVBhdGNoUGF0aCA9IG1jLmdldExpYnJhcnlCeVBhdGgoYG5ldC9taW5lY3JhZnRmb3JnZS9mb3JnZS8ke21jVmVyc2lvbn0tJHtmb3JnZVZlcnNpb259L2ZvcmdlLSR7bWNWZXJzaW9ufS0ke2ZvcmdlVmVyc2lvbn0tY2xpZW50LmphcmApO1xuICAgICAgICAgICAgICAgICAgICBkaWFnLm1pc3NpbmdTcmdKYXIgPSBhd2FpdCB2ZnMubWlzc2luZyhzcmdQYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgZGlhZy5taXNzaW5nTWluZWNyYWZ0RXh0cmFKYXIgPSBhd2FpdCB2ZnMubWlzc2luZyhleHRyYVBhdGgpO1xuICAgICAgICAgICAgICAgICAgICBkaWFnLm1pc3NpbmdGb3JnZVBhdGNoZXNKYXIgPSBhd2FpdCB2ZnMubWlzc2luZyhmb3JnZVBhdGNoUGF0aCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkaWFnLmJhZFZlcnNpb25Kc29uID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBkaWFnLmJhZEluc3RhbGwgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGlhZy5iYWRWZXJzaW9uSnNvbiA9IHRydWU7XG4gICAgICAgICAgICBkaWFnLmJhZEluc3RhbGwgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGRpYWc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUG9zdCBwcm9jZXNzaW5nIGZ1bmN0aW9uIGZvciBuZXcgZm9yZ2UgaW5zdGFsbGVyIChtY3ZlcnNpb24gPj0gMS4xMykuIFlvdSBjYW4gdXNlIHRoaXMgd2l0aCBgRm9yZ2VJbnN0YWxsZXIuZGlhZ25vc2VgLlxuICAgICAqXG4gICAgICogQHBhcmFtIG1jIFRoZSBtaW5lY3JhZnQgbG9jYXRpb25cbiAgICAgKiBAcGFyYW0gcHJvYyBUaGUgcHJvY2Vzc29yXG4gICAgICogQHBhcmFtIGphdmEgVGhlIGphdmEgZXhlY3V0b3JcbiAgICAgKi9cbiAgICBleHBvcnQgYXN5bmMgZnVuY3Rpb24gcG9zdFByb2Nlc3MobWM6IE1pbmVjcmFmdEZvbGRlciwgcHJvYzogSW5zdGFsbFByb2ZpbGVbXCJwcm9jZXNzb3JzXCJdW251bWJlcl0sIGphdmE6IEphdmFFeGVjdXRvcikge1xuICAgICAgICBjb25zdCBqYXJSZWFsUGF0aCA9IG1jLmdldExpYnJhcnlCeVBhdGgoVmVyc2lvbi5nZXRMaWJyYXJ5SW5mbyhwcm9jLmphcikucGF0aCk7XG4gICAgICAgIGNvbnN0IG1haW5DbGFzcyA9IGF3YWl0IGZpbmRNYWluQ2xhc3MoamFyUmVhbFBhdGgpO1xuICAgICAgICBpZiAoIW1haW5DbGFzcykgeyB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBmaW5kIG1haW4gY2xhc3MgZm9yIHByb2Nlc3NvciAke3Byb2MuamFyfS5gKTsgfVxuICAgICAgICBjb25zdCBjcCA9IFsuLi5wcm9jLmNsYXNzcGF0aCwgcHJvYy5qYXJdLm1hcChWZXJzaW9uLmdldExpYnJhcnlJbmZvKS5tYXAoKHApID0+IG1jLmdldExpYnJhcnlCeVBhdGgocC5wYXRoKSkuam9pbihkZWxpbWl0ZXIpO1xuICAgICAgICBjb25zdCBjbWQgPSBbXCItY3BcIiwgY3AsIG1haW5DbGFzcywgLi4ucHJvYy5hcmdzXTtcbiAgICAgICAgYXdhaXQgamF2YShjbWQpO1xuICAgICAgICBsZXQgZmFpbGVkID0gZmFsc2U7XG4gICAgICAgIGlmIChwcm9jLm91dHB1dHMpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgZmlsZSBpbiBwcm9jLm91dHB1dHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoISBhd2FpdCB2ZnMudmFsaWRhdGVTaGExKGZpbGUsIHByb2Mub3V0cHV0c1tmaWxlXS5yZXBsYWNlKC8nL2csIFwiXCIpKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBGYWlsIHRvIHByb2Nlc3MgJHtwcm9jLmphcn0gQCAke2ZpbGV9IHNpbmNlIGl0cyB2YWxpZGF0aW9uIGZhaWxlZC5gKTtcbiAgICAgICAgICAgICAgICAgICAgZmFpbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZhaWxlZCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihgSmF2YSBhcmd1bWVudHM6ICR7SlNPTi5zdHJpbmdpZnkoY21kKX1gKTtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkZhaWwgdG8gcHJvY2VzcyBwb3N0IHByb2Nlc3Npbmcgc2luY2UgaXRzIHZhbGlkYXRpb24gZmFpbGVkLlwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBvc3RQcm9jZXNzSW5zdGFsbFByb2ZpbGUobWM6IE1pbmVjcmFmdEZvbGRlciwgaW5zdGFsbFByb2ZpbGU6IEluc3RhbGxQcm9maWxlKSB7XG4gICAgICAgIGZ1bmN0aW9uIHByb2Nlc3NWYWx1ZSh2OiBzdHJpbmcpIHtcbiAgICAgICAgICAgIGlmICh2Lm1hdGNoKC9eXFxbLitcXF0kL2cpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0SWQgPSB2LnN1YnN0cmluZygxLCB2Lmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgIHJldHVybiBtYy5nZXRMaWJyYXJ5QnlQYXRoKFZlcnNpb24uZ2V0TGlicmFyeUluZm8odGFyZ2V0SWQpLnBhdGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHY7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gcHJvY2Vzc01hcHBpbmcoZGF0YTogSW5zdGFsbFByb2ZpbGVbXCJkYXRhXCJdLCBtOiBzdHJpbmcpIHtcbiAgICAgICAgICAgIG0gPSBwcm9jZXNzVmFsdWUobSk7XG4gICAgICAgICAgICBpZiAobS5tYXRjaCgvXnsuK30kL2cpKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qga2V5ID0gbS5zdWJzdHJpbmcoMSwgbS5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgICAgICBtID0gZGF0YVtrZXldLmNsaWVudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHByb2ZpbGU6IEluc3RhbGxQcm9maWxlID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShpbnN0YWxsUHJvZmlsZSkpO1xuICAgICAgICBwcm9maWxlLmRhdGEuTUlORUNSQUZUX0pBUiA9IHtcbiAgICAgICAgICAgIGNsaWVudDogbWMuZ2V0VmVyc2lvbkphcihwcm9maWxlLm1pbmVjcmFmdCksXG4gICAgICAgICAgICBzZXJ2ZXI6IFwiXCIsXG4gICAgICAgIH07XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHByb2ZpbGUuZGF0YSkge1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBwcm9maWxlLmRhdGFba2V5XTtcbiAgICAgICAgICAgIHZhbHVlLmNsaWVudCA9IHByb2Nlc3NWYWx1ZSh2YWx1ZS5jbGllbnQpO1xuICAgICAgICAgICAgdmFsdWUuc2VydmVyID0gcHJvY2Vzc1ZhbHVlKHZhbHVlLnNlcnZlcik7XG5cbiAgICAgICAgICAgIGlmIChrZXkgPT09IFwiQklOUEFUQ0hcIikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZlclJvb3QgPSBtYy5nZXRWZXJzaW9uUm9vdChwcm9maWxlLnZlcnNpb24pO1xuICAgICAgICAgICAgICAgIHZhbHVlLmNsaWVudCA9IGpvaW4odmVyUm9vdCwgdmFsdWUuY2xpZW50KTtcbiAgICAgICAgICAgICAgICB2YWx1ZS5zZXJ2ZXIgPSBqb2luKHZlclJvb3QsIHZhbHVlLnNlcnZlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBwcm9jIG9mIHByb2ZpbGUucHJvY2Vzc29ycykge1xuICAgICAgICAgICAgcHJvYy5hcmdzID0gcHJvYy5hcmdzLm1hcCgoYSkgPT4gcHJvY2Vzc01hcHBpbmcocHJvZmlsZS5kYXRhLCBhKSk7XG4gICAgICAgICAgICBpZiAocHJvYy5vdXRwdXRzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVwbGFjZWRPdXRwdXQ6IEluc3RhbGxQcm9maWxlW1wicHJvY2Vzc29yc1wiXVswXVtcIm91dHB1dHNcIl0gPSB7fTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBwcm9jLm91dHB1dHMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVwbGFjZWRPdXRwdXRbcHJvY2Vzc01hcHBpbmcocHJvZmlsZS5kYXRhLCBrZXkpXSA9IHByb2Nlc3NNYXBwaW5nKHByb2ZpbGUuZGF0YSwgcHJvYy5vdXRwdXRzW2tleV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwcm9jLm91dHB1dHMgPSByZXBsYWNlZE91dHB1dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwcm9maWxlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluc3RhbGwgZm9yIGZvcmdlIGluc3RhbGxlciBzdGVwIDIgYW5kIDMuXG4gICAgICogQHBhcmFtIHZlcnNpb24gVGhlIHZlcnNpb24gc3RyaW5nIG9yIGluc3RhbGxlciBwcm9maWxlXG4gICAgICogQHBhcmFtIG1pbmVjcmFmdCBUaGUgbWluZWNyYWZ0IGxvY2F0aW9uXG4gICAgICovXG4gICAgZXhwb3J0IGZ1bmN0aW9uIGluc3RhbGxCeUluc3RhbGxlclBhcnRpYWxUYXNrKHZlcnNpb246IHN0cmluZyB8IEluc3RhbGxQcm9maWxlLCBtaW5lY3JhZnQ6IE1pbmVjcmFmdExvY2F0aW9uLCBvcHRpb246IHtcbiAgICAgICAgamF2YT86IEphdmFFeGVjdXRvcixcbiAgICB9ICYgSW5zdGFsbGVyLkxpYnJhcnlPcHRpb24gPSB7fSkge1xuICAgICAgICByZXR1cm4gYXN5bmMgZnVuY3Rpb24gaW5zdGFsbEZvcmdlKGNvbnRleHQ6IFRhc2suQ29udGV4dCkge1xuICAgICAgICAgICAgY29uc3QgbWMgPSBNaW5lY3JhZnRGb2xkZXIuZnJvbShtaW5lY3JhZnQpO1xuICAgICAgICAgICAgbGV0IHByb2Y6IEluc3RhbGxQcm9maWxlO1xuICAgICAgICAgICAgbGV0IHZlcjogVmVyc2lvbjtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdmVyc2lvbiA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZlcnNpb25Sb290ID0gbWMuZ2V0VmVyc2lvblJvb3QodmVyc2lvbik7XG4gICAgICAgICAgICAgICAgcHJvZiA9IGF3YWl0IHZmcy5yZWFkRmlsZShqb2luKHZlcnNpb25Sb290LCBcImluc3RhbGxfcHJvZmlsZS5qc29uXCIpKS50aGVuKChiKSA9PiBiLnRvU3RyaW5nKCkpLnRoZW4oSlNPTi5wYXJzZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHByb2YgPSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmVyID0gYXdhaXQgdmZzLnJlYWRGaWxlKG1jLmdldFZlcnNpb25Kc29uKHByb2YudmVyc2lvbikpLnRoZW4oKGIpID0+IGIudG9TdHJpbmcoKSkudGhlbihKU09OLnBhcnNlKTtcbiAgICAgICAgICAgIGF3YWl0IGluc3RhbGxCeUluc3RhbGxlclBhcnRpYWxXb3JrKG1jLCBwcm9mLCB2ZXIsIG9wdGlvbi5qYXZhIHx8IEphdmFFeGVjdXRvci5jcmVhdGVTaW1wbGUoXCJqYXZhXCIpLCBvcHRpb24pKGNvbnRleHQpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluc3RhbGwgZm9yIGZvcmdlIGluc3RhbGxlciBzdGVwIDIgYW5kIDMuXG4gICAgICogQHBhcmFtIHZlcnNpb24gVGhlIHZlcnNpb24gc3RyaW5nIG9yIGluc3RhbGxlciBwcm9maWxlXG4gICAgICogQHBhcmFtIG1pbmVjcmFmdCBUaGUgbWluZWNyYWZ0IGxvY2F0aW9uXG4gICAgICovXG4gICAgZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGluc3RhbGxCeUluc3RhbGxlclBhcnRpYWwodmVyc2lvbjogc3RyaW5nIHwgSW5zdGFsbFByb2ZpbGUsIG1pbmVjcmFmdDogTWluZWNyYWZ0TG9jYXRpb24sIG9wdGlvbjoge1xuICAgICAgICBqYXZhPzogSmF2YUV4ZWN1dG9yLFxuICAgIH0gJiBJbnN0YWxsZXIuTGlicmFyeU9wdGlvbiA9IHt9KSB7XG4gICAgICAgIHJldHVybiBUYXNrLmV4ZWN1dGUoaW5zdGFsbEJ5SW5zdGFsbGVyUGFydGlhbFRhc2sodmVyc2lvbiwgbWluZWNyYWZ0LCBvcHRpb24pKS53YWl0KCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5zdGFsbEJ5SW5zdGFsbGVyUGFydGlhbFdvcmsobWM6IE1pbmVjcmFmdEZvbGRlciwgcHJvZmlsZTogSW5zdGFsbFByb2ZpbGUsIHZlcnNpb25Kc29uOiBWZXJzaW9uLCBqYXZhOiBKYXZhRXhlY3V0b3IsIGluc3RhbGxMaWJPcHRpb246IEluc3RhbGxlci5MaWJyYXJ5T3B0aW9uKSB7XG4gICAgICAgIHJldHVybiBhc3luYyAoY29udGV4dDogVGFzay5Db250ZXh0KSA9PiB7XG4gICAgICAgICAgICBwcm9maWxlID0gcG9zdFByb2Nlc3NJbnN0YWxsUHJvZmlsZShtYywgcHJvZmlsZSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHBhcnNlZExpYnMgPSBWZXJzaW9uLnJlc29sdmVMaWJyYXJpZXMoWy4uLnByb2ZpbGUubGlicmFyaWVzLCAuLi52ZXJzaW9uSnNvbi5saWJyYXJpZXNdKTtcbiAgICAgICAgICAgIGF3YWl0IGNvbnRleHQuZXhlY3V0ZShJbnN0YWxsZXIuaW5zdGFsbExpYnJhcmllc0RpcmVjdFRhc2socGFyc2VkTGlicywgbWMsIHtcbiAgICAgICAgICAgICAgICAuLi5pbnN0YWxsTGliT3B0aW9uLFxuICAgICAgICAgICAgICAgIGxpYnJhcnlIb3N0OiBpbnN0YWxsTGliT3B0aW9uLmxpYnJhcnlIb3N0ID8gKGwpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGwuYXJ0aWZhY3RJZCA9PT0gXCJmb3JnZVwiICYmIGwuZ3JvdXBJZCA9PT0gXCJuZXQubWluZWNyYWZ0Zm9yZ2VcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGBmaWxlOi8vJHttYy5nZXRMaWJyYXJ5QnlQYXRoKGwucGF0aCl9YDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zdGFsbExpYk9wdGlvbi5saWJyYXJ5SG9zdCEobCk7XG4gICAgICAgICAgICAgICAgfSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIH0pKTtcblxuICAgICAgICAgICAgYXdhaXQgY29udGV4dC5leGVjdXRlKGFzeW5jIGZ1bmN0aW9uIHBvc3RQcm9jZXNzaW5nKGN0eCkge1xuICAgICAgICAgICAgICAgIGN0eC51cGRhdGUoMCwgcHJvZmlsZS5wcm9jZXNzb3JzLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgbGV0IGkgPSAwO1xuICAgICAgICAgICAgICAgIGNvbnN0IGVycnM6IEVycm9yW10gPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHByb2Mgb2YgcHJvZmlsZS5wcm9jZXNzb3JzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBwb3N0UHJvY2VzcyhtYywgcHJvYywgamF2YSk7XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycnMucHVzaChlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjdHgudXBkYXRlKGkgKz0gMSwgcHJvZmlsZS5wcm9jZXNzb3JzLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGkgKz0gMTtcbiAgICAgICAgICAgICAgICBjdHgudXBkYXRlKGksIHByb2ZpbGUucHJvY2Vzc29ycy5sZW5ndGgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGVycnMubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkZhaWwgdG8gcG9zdCBwcm9jZXNzaW5nXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGluc3RhbGxCeUluc3RhbGxlclRhc2sodmVyc2lvbjogVmVyc2lvbk1ldGEsIG1pbmVjcmFmdDogTWluZWNyYWZ0TG9jYXRpb24sIG1hdmVuOiBzdHJpbmcsIGluc3RhbGxMaWJPcHRpb246IEluc3RhbGxlci5MaWJyYXJ5T3B0aW9uLCBqYXZhOiBKYXZhRXhlY3V0b3IpIHtcbiAgICAgICAgcmV0dXJuIGFzeW5jIGZ1bmN0aW9uIGluc3RhbGxGb3JnZShjb250ZXh0OiBUYXNrLkNvbnRleHQpIHtcbiAgICAgICAgICAgIGNvbnN0IG1jID0gTWluZWNyYWZ0Rm9sZGVyLmZyb20obWluZWNyYWZ0KTtcblxuICAgICAgICAgICAgY29uc3QgZm9yZ2VWZXJzaW9uID0gYCR7dmVyc2lvbi5tY3ZlcnNpb259LSR7dmVyc2lvbi52ZXJzaW9ufWA7XG4gICAgICAgICAgICBjb25zdCBpbnN0YWxsZXJVUkwgPSBgJHttYXZlbn0ke3ZlcnNpb24uaW5zdGFsbGVyLnBhdGh9YDtcbiAgICAgICAgICAgIGNvbnN0IGluc3RhbGxlclVSTEZhbGxiYWNrID0gYCR7bWF2ZW59L21hdmVuL25ldC9taW5lY3JhZnRmb3JnZS9mb3JnZS8ke2ZvcmdlVmVyc2lvbn0vZm9yZ2UtJHtmb3JnZVZlcnNpb259LWluc3RhbGxlci5qYXJgO1xuICAgICAgICAgICAgY29uc3QgaW5zdGFsbEphciA9IG1jLmdldExpYnJhcnlCeVBhdGgodmVyc2lvbi5pbnN0YWxsZXIucGF0aC5zdWJzdHJpbmcodmVyc2lvbi5pbnN0YWxsZXIucGF0aC5zdWJzdHJpbmcoMSkuaW5kZXhPZihcIi9cIikgKyAxKSk7XG5cbiAgICAgICAgICAgIGxldCB2ZXJzaW9uSWQ6IHN0cmluZztcbiAgICAgICAgICAgIGxldCBwcm9maWxlITogSW5zdGFsbFByb2ZpbGU7XG4gICAgICAgICAgICBsZXQgdmVyc2lvbkpzb24hOiBWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb3dubG9hZEluc3RhbGxlclRhc2soaW5zdGFsbGVyOiBzdHJpbmcsIGRlc3Q6IHN0cmluZykge1xuICAgICAgICAgICAgICAgIHJldHVybiBhc3luYyBmdW5jdGlvbiBkb3dubG9hZEluc3RhbGxlcihjdHg6IFRhc2suQ29udGV4dCkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBkb3dubG9hZEZpbGVJZkFic2VudFdvcmsoe1xuICAgICAgICAgICAgICAgICAgICAgICAgdXJsOiBpbnN0YWxsZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0aW5hdGlvbjogZGVzdCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrc3VtOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzaDogdmVyc2lvbi5pbnN0YWxsZXIuc2hhMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGdvcml0aG06IFwic2hhMVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgfSkoY3R4KTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZmcy5jcmVhdGVSZWFkU3RyZWFtKGRlc3QpLnBpcGUoVW56aXAuY3JlYXRlUGFyc2VTdHJlYW0oeyBsYXp5RW50cmllczogdHJ1ZSB9KSkud2FpdCgpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhc3luYyBmdW5jdGlvbiBwcm9jZXNzVmVyc2lvbih6aXA6IFVuemlwLlppcEZpbGUsIGluc3RhbGxQcm9maWxlRW50cnk6IFVuemlwLkVudHJ5LCB2ZXJzaW9uRW50cnk6IFVuemlwLkVudHJ5LCBjbGllbnREYXRhRW50cnk6IFVuemlwLkVudHJ5KSB7XG4gICAgICAgICAgICAgICAgcHJvZmlsZSA9IGF3YWl0IHppcC5yZWFkRW50cnkoaW5zdGFsbFByb2ZpbGVFbnRyeSkudGhlbigoYikgPT4gYi50b1N0cmluZygpKS50aGVuKEpTT04ucGFyc2UpO1xuICAgICAgICAgICAgICAgIHZlcnNpb25Kc29uID0gYXdhaXQgemlwLnJlYWRFbnRyeSh2ZXJzaW9uRW50cnkpLnRoZW4oKGIpID0+IGIudG9TdHJpbmcoKSkudGhlbihKU09OLnBhcnNlKTtcbiAgICAgICAgICAgICAgICB2ZXJzaW9uSWQgPSB2ZXJzaW9uSnNvbi5pZDtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHJvb3RQYXRoID0gbWMuZ2V0VmVyc2lvblJvb3QodmVyc2lvbkpzb24uaWQpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGpzb25QYXRoID0gam9pbihyb290UGF0aCwgYCR7dmVyc2lvbkpzb24uaWR9Lmpzb25gKTtcbiAgICAgICAgICAgICAgICBjb25zdCBpbnN0YWxsSnNvblBhdGggPSBqb2luKHJvb3RQYXRoLCBcImluc3RhbGxfcHJvZmlsZS5qc29uXCIpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNsaWVudERhdGFQYXRoID0gam9pbihyb290UGF0aCwgcHJvZmlsZS5kYXRhLkJJTlBBVENILmNsaWVudCk7XG5cbiAgICAgICAgICAgICAgICBhd2FpdCB2ZnMuZW5zdXJlRmlsZShqc29uUGF0aCk7XG4gICAgICAgICAgICAgICAgYXdhaXQgdmZzLndyaXRlRmlsZShpbnN0YWxsSnNvblBhdGgsIEpTT04uc3RyaW5naWZ5KHByb2ZpbGUpKTtcbiAgICAgICAgICAgICAgICBhd2FpdCB2ZnMud3JpdGVGaWxlKGpzb25QYXRoLCBKU09OLnN0cmluZ2lmeSh2ZXJzaW9uSnNvbikpO1xuXG4gICAgICAgICAgICAgICAgYXdhaXQgdmZzLmVuc3VyZUZpbGUoY2xpZW50RGF0YVBhdGgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGF3YWl0IHppcC5vcGVuRW50cnkoY2xpZW50RGF0YUVudHJ5KTtcbiAgICAgICAgICAgICAgICBhd2FpdCB2ZnMud2FpdFN0cmVhbShzdHJlYW0ucGlwZSh2ZnMuY3JlYXRlV3JpdGVTdHJlYW0oY2xpZW50RGF0YVBhdGgpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhc3luYyBmdW5jdGlvbiBwcm9jZXNzRXh0cmFjdExpYnJhcnkoc3RyZWFtOiBSZWFkYWJsZSwgcDogc3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZmlsZSA9IG1jLmdldExpYnJhcnlCeVBhdGgocC5zdWJzdHJpbmcocC5pbmRleE9mKFwiL1wiKSArIDEpKTtcbiAgICAgICAgICAgICAgICBhd2FpdCB2ZnMuZW5zdXJlRmlsZShmaWxlKTtcbiAgICAgICAgICAgICAgICBhd2FpdCB2ZnMud2FpdFN0cmVhbShzdHJlYW0ucGlwZSh2ZnMuY3JlYXRlV3JpdGVTdHJlYW0oZmlsZSkpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBsZXQgemlwOiBVbnppcC5MYXp5WmlwRmlsZTtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICB6aXAgPSBhd2FpdCBjb250ZXh0LmV4ZWN1dGUoZG93bmxvYWRJbnN0YWxsZXJUYXNrKGluc3RhbGxlclVSTCwgaW5zdGFsbEphcikpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgICAgICAgICB6aXAgPSBhd2FpdCBjb250ZXh0LmV4ZWN1dGUoZG93bmxvYWRJbnN0YWxsZXJUYXNrKGluc3RhbGxlclVSTEZhbGxiYWNrLCBpbnN0YWxsSmFyKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3QgW2ZvcmdlRW50cnksIGZvcmdlVW5pdmVyc2FsRW50cnksIGNsaWVudERhdGFFbnRyeSwgaW5zdGFsbFByb2ZpbGVFbnRyeSwgdmVyc2lvbkVudHJ5XSA9IGF3YWl0IHppcC5maWx0ZXJFbnRyaWVzKFtcbiAgICAgICAgICAgICAgICAgICAgYG1hdmVuL25ldC9taW5lY3JhZnRmb3JnZS9mb3JnZS8ke2ZvcmdlVmVyc2lvbn0vZm9yZ2UtJHtmb3JnZVZlcnNpb259LmphcmAsXG4gICAgICAgICAgICAgICAgICAgIGBtYXZlbi9uZXQvbWluZWNyYWZ0Zm9yZ2UvZm9yZ2UvJHtmb3JnZVZlcnNpb259L2ZvcmdlLSR7Zm9yZ2VWZXJzaW9ufS11bml2ZXJzYWwuamFyYCxcbiAgICAgICAgICAgICAgICAgICAgXCJkYXRhL2NsaWVudC5sem1hXCIsXG4gICAgICAgICAgICAgICAgICAgIFwiaW5zdGFsbF9wcm9maWxlLmpzb25cIixcbiAgICAgICAgICAgICAgICAgICAgXCJ2ZXJzaW9uLmpzb25cIlxuICAgICAgICAgICAgICAgIF0pO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFmb3JnZUVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk1pc3NpbmcgZm9yZ2UgamFyIGVudHJ5XCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIWZvcmdlVW5pdmVyc2FsRW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTWlzc2luZyBmb3JnZSB1bml2ZXJzYWwgZW50cnlcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghaW5zdGFsbFByb2ZpbGVFbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJNaXNzaW5nIGluc3RhbGwgcHJvZmlsZVwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCF2ZXJzaW9uRW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTWlzc2luZyB2ZXJzaW9uIGVudHJ5XCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGF3YWl0IHByb2Nlc3NFeHRyYWN0TGlicmFyeShhd2FpdCB6aXAub3BlbkVudHJ5KGZvcmdlRW50cnkpLCBmb3JnZUVudHJ5LmZpbGVOYW1lKTtcbiAgICAgICAgICAgICAgICBhd2FpdCBwcm9jZXNzRXh0cmFjdExpYnJhcnkoYXdhaXQgemlwLm9wZW5FbnRyeShmb3JnZVVuaXZlcnNhbEVudHJ5KSwgZm9yZ2VVbml2ZXJzYWxFbnRyeS5maWxlTmFtZSk7XG4gICAgICAgICAgICAgICAgYXdhaXQgcHJvY2Vzc1ZlcnNpb24oemlwLCBpbnN0YWxsUHJvZmlsZUVudHJ5LCB2ZXJzaW9uRW50cnksIGNsaWVudERhdGFFbnRyeSk7XG5cbiAgICAgICAgICAgICAgICBhd2FpdCBpbnN0YWxsQnlJbnN0YWxsZXJQYXJ0aWFsV29yayhtYywgcHJvZmlsZSwgdmVyc2lvbkpzb24sIGphdmEsIGluc3RhbGxMaWJPcHRpb24pKGNvbnRleHQpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHZlcnNpb25JZCE7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgQ2Fubm90IGluc3RhbGwgZm9yZ2UgYnkgaW5zdGFsbGVyICR7dmVyc2lvbi52ZXJzaW9ufWApO1xuICAgICAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5zdGFsbEJ5VW5pdmVyc2FsVGFzayh2ZXJzaW9uOiBWZXJzaW9uTWV0YSwgbWluZWNyYWZ0OiBNaW5lY3JhZnRMb2NhdGlvbiwgbWF2ZW46IHN0cmluZykge1xuICAgICAgICByZXR1cm4gYXN5bmMgZnVuY3Rpb24gaW5zdGFsbEZvcmdlKGNvbnRleHQ6IFRhc2suQ29udGV4dCkge1xuICAgICAgICAgICAgY29uc3QgbWMgPSBNaW5lY3JhZnRGb2xkZXIuZnJvbShtaW5lY3JhZnQpO1xuICAgICAgICAgICAgY29uc3QgZm9yZ2VWZXJzaW9uID0gYCR7dmVyc2lvbi5tY3ZlcnNpb259LSR7dmVyc2lvbi52ZXJzaW9ufWA7XG4gICAgICAgICAgICBjb25zdCBwYXRocyA9IHZlcnNpb24udW5pdmVyc2FsLnBhdGguc3BsaXQoXCIvXCIpO1xuICAgICAgICAgICAgY29uc3QgcmVhbEZvcmdlVmVyc2lvbiA9IHBhdGhzW3BhdGhzLmxlbmd0aCAtIDJdO1xuICAgICAgICAgICAgY29uc3QgamFyUGF0aCA9IG1jLmdldExpYnJhcnlCeVBhdGgoYG5ldC9taW5lY3JhZnRmb3JnZS9mb3JnZS8ke3JlYWxGb3JnZVZlcnNpb259L2ZvcmdlLSR7cmVhbEZvcmdlVmVyc2lvbn0uamFyYCk7XG4gICAgICAgICAgICBsZXQgZnVsbFZlcnNpb246IHN0cmluZztcbiAgICAgICAgICAgIGxldCByZWFsSmFyUGF0aDogc3RyaW5nO1xuXG4gICAgICAgICAgICBjb25zdCB1bml2ZXJzYWxVUkxGYWxsYmFjayA9IGAke21hdmVufS9tYXZlbi9uZXQvbWluZWNyYWZ0Zm9yZ2UvZm9yZ2UvJHtmb3JnZVZlcnNpb259L2ZvcmdlLSR7Zm9yZ2VWZXJzaW9ufS11bml2ZXJzYWwuamFyYDtcbiAgICAgICAgICAgIGNvbnN0IHVuaXZlcnNhbFVSTCA9IGAke21hdmVufSR7dmVyc2lvbi51bml2ZXJzYWwucGF0aH1gO1xuXG4gICAgICAgICAgICBhd2FpdCBjb250ZXh0LmV4ZWN1dGUoYXN5bmMgZnVuY3Rpb24gaW5zdGFsbEZvcmdlSmFyKCkge1xuICAgICAgICAgICAgICAgIGlmIChhd2FpdCB2ZnMuZXhpc3RzKGphclBhdGgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbGlkID0gYXdhaXQgdmZzLnZhbGlkYXRlKGphclBhdGgsIHsgYWxnb3JpdGhtOiBcIm1kNVwiLCBoYXNoOiB2ZXJzaW9uLnVuaXZlcnNhbC5tZDUgfSwgeyBhbGdvcml0aG06IFwic2hhMVwiLCBoYXNoOiB2ZXJzaW9uLnVuaXZlcnNhbC5zaGExIH0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBkb3dubG9hZEphcihjdHg6IFRhc2suQ29udGV4dCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG93bmxvYWRGaWxlV29yayh7IHVybDogdW5pdmVyc2FsVVJMLCBkZXN0aW5hdGlvbjogamFyUGF0aCB9KShjdHgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhd2FpdCBjb250ZXh0LmV4ZWN1dGUoZG93bmxvYWRKYXIpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGF3YWl0IGNvbnRleHQuZXhlY3V0ZShhc3luYyBmdW5jdGlvbiBpbnN0YWxsRm9yZ2VKc29uKCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHppcCA9IGF3YWl0IFVuemlwLm9wZW4oamFyUGF0aCwgeyBsYXp5RW50cmllczogdHJ1ZSB9KTtcbiAgICAgICAgICAgICAgICBjb25zdCBbdmVyc2lvbkVudHJ5XSA9IGF3YWl0IHppcC5maWx0ZXJFbnRyaWVzKFtcInZlcnNpb24uanNvblwiXSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvbkVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGJ1ZiA9IGF3YWl0IHppcC5yZWFkRW50cnkodmVyc2lvbkVudHJ5KTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmF3ID0gSlNPTi5wYXJzZShidWYudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGlkID0gcmF3LmlkO1xuICAgICAgICAgICAgICAgICAgICBmdWxsVmVyc2lvbiA9IGlkO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByb290UGF0aCA9IG1jLmdldFZlcnNpb25Sb290KGZ1bGxWZXJzaW9uKTtcbiAgICAgICAgICAgICAgICAgICAgcmVhbEphclBhdGggPSBtYy5nZXRMaWJyYXJ5QnlQYXRoKFZlcnNpb24uZ2V0TGlicmFyeUluZm8ocmF3LmxpYnJhcmllcy5maW5kKChsOiBhbnkpID0+IGwubmFtZS5zdGFydHNXaXRoKFwibmV0Lm1pbmVjcmFmdGZvcmdlOmZvcmdlXCIpKSkucGF0aCk7XG5cbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdmZzLmVuc3VyZURpcihyb290UGF0aCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGpzb25QYXRoID0gam9pbihyb290UGF0aCwgYCR7aWR9Lmpzb25gKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGF3YWl0IHZmcy5taXNzaW5nKGpzb25QYXRoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdmZzLndyaXRlRmlsZShqc29uUGF0aCwgYnVmKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGluc3RhbGwgZm9yZ2UganNvbiBmb3IgJHt2ZXJzaW9uLnZlcnNpb259IHNpbmNlIHRoZSB2ZXJzaW9uIGpzb24gaXMgbWlzc2luZyFgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKHJlYWxKYXJQYXRoISAhPT0gamFyUGF0aCkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHZmcy5lbnN1cmVGaWxlKHJlYWxKYXJQYXRoISk7XG4gICAgICAgICAgICAgICAgYXdhaXQgdmZzLmNvcHlGaWxlKGphclBhdGgsIHJlYWxKYXJQYXRoISk7XG4gICAgICAgICAgICAgICAgYXdhaXQgdmZzLnVubGluayhqYXJQYXRoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGZ1bGxWZXJzaW9uITtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnN0YWxsIGZvcmdlIHRvIHRhcmdldCBsb2NhdGlvbi5cbiAgICAgKiBJbnN0YWxsYXRpb24gdGFzayBmb3IgZm9yZ2Ugd2l0aCBtY3ZlcnNpb24gPj0gMS4xMyByZXF1aXJlcyBqYXZhIGluc3RhbGxlZCBvbiB5b3VyIHBjLlxuICAgICAqIEBwYXJhbSB2ZXJzaW9uIFRoZSBmb3JnZSB2ZXJzaW9uIG1ldGFcbiAgICAgKi9cbiAgICBleHBvcnQgZnVuY3Rpb24gaW5zdGFsbCh2ZXJzaW9uOiBWZXJzaW9uTWV0YSwgbWluZWNyYWZ0OiBNaW5lY3JhZnRMb2NhdGlvbiwgb3B0aW9uPzoge1xuICAgICAgICBtYXZlbj86IHN0cmluZyxcbiAgICAgICAgamF2YT86IEphdmFFeGVjdXRvcixcbiAgICB9KSB7XG4gICAgICAgIHJldHVybiBUYXNrLmV4ZWN1dGUoaW5zdGFsbFRhc2sodmVyc2lvbiwgbWluZWNyYWZ0LCBvcHRpb24pKS53YWl0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5zdGFsbCBmb3JnZSB0byB0YXJnZXQgbG9jYXRpb24uXG4gICAgICogSW5zdGFsbGF0aW9uIHRhc2sgZm9yIGZvcmdlIHdpdGggbWN2ZXJzaW9uID49IDEuMTMgcmVxdWlyZXMgamF2YSBpbnN0YWxsZWQgb24geW91ciBwYy5cbiAgICAgKiBAcGFyYW0gdmVyc2lvbiBUaGUgZm9yZ2UgdmVyc2lvbiBtZXRhXG4gICAgICovXG4gICAgZXhwb3J0IGZ1bmN0aW9uIGluc3RhbGxUYXNrKHZlcnNpb246IFZlcnNpb25NZXRhLCBtaW5lY3JhZnQ6IE1pbmVjcmFmdExvY2F0aW9uLCBvcHRpb246IHtcbiAgICAgICAgbWF2ZW4/OiBzdHJpbmcsXG4gICAgICAgIGphdmE/OiBKYXZhRXhlY3V0b3IsXG4gICAgfSAmIEluc3RhbGxlci5MaWJyYXJ5T3B0aW9uID0ge30pOiBUYXNrPHN0cmluZz4ge1xuICAgICAgICBsZXQgYnlJbnN0YWxsZXIgPSB0cnVlO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgbWlub3JWZXJzaW9uID0gTnVtYmVyLnBhcnNlSW50KHZlcnNpb24ubWN2ZXJzaW9uLnNwbGl0KFwiLlwiKVsxXSwgMTApO1xuICAgICAgICAgICAgYnlJbnN0YWxsZXIgPSBtaW5vclZlcnNpb24gPj0gMTM7XG4gICAgICAgIH0gY2F0Y2ggeyB9XG4gICAgICAgIGNvbnN0IHdvcmsgPSBieUluc3RhbGxlclxuICAgICAgICAgICAgPyBpbnN0YWxsQnlJbnN0YWxsZXJUYXNrKHZlcnNpb24sIG1pbmVjcmFmdCwgb3B0aW9uLm1hdmVuIHx8IERFRkFVTFRfRk9SR0VfTUFWRU4sIG9wdGlvbiwgb3B0aW9uLmphdmEgfHwgSmF2YUV4ZWN1dG9yLmNyZWF0ZVNpbXBsZShcImphdmFcIikpXG4gICAgICAgICAgICA6IGluc3RhbGxCeVVuaXZlcnNhbFRhc2sodmVyc2lvbiwgbWluZWNyYWZ0LCBvcHRpb24ubWF2ZW4gfHwgREVGQVVMVF9GT1JHRV9NQVZFTik7XG4gICAgICAgIHJldHVybiB3b3JrO1xuICAgIH1cbn1cblxuZXhwb3J0ICogZnJvbSBcIi4vZm9yZ2V3ZWJcIjtcblxuZXhwb3J0IGRlZmF1bHQgRm9yZ2VJbnN0YWxsZXI7XG4iXX0=
\No newline at end of file