UNPKG

77.9 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));
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));
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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QUssSUFBSSxlQUFBLG1CQUFtQixFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxJQUFJLG1CQUFZLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzNJLENBQUMsQ0FBQyxzQkFBc0IsQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sQ0FBQyxLQUFLLElBQUksZUFBQSxtQkFBbUIsQ0FBQyxDQUFDO1FBQ3RGLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFiZSwwQkFBVyxjQWExQixDQUFBO0FBQ0wsQ0FBQyxFQXpnQmdCLGNBQWMsR0FBZCxzQkFBYyxLQUFkLHNCQUFjLFFBeWdCOUI7QUFFRCxnQ0FBMkI7QUFFM0Isa0JBQWUsY0FBYyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5zdGFsbGVyIH0gZnJvbSBcIkB4bWNsL2luc3RhbGxlclwiO1xuaW1wb3J0IHsgZG93bmxvYWRGaWxlSWZBYnNlbnRXb3JrLCBkb3dubG9hZEZpbGVXb3JrIH0gZnJvbSBcIkB4bWNsL25ldFwiO1xuaW1wb3J0IFRhc2sgZnJvbSBcIkB4bWNsL3Rhc2tcIjtcbmltcG9ydCBVbnppcCBmcm9tIFwiQHhtY2wvdW56aXBcIjtcbmltcG9ydCB7IE1pbmVjcmFmdEZvbGRlciwgTWluZWNyYWZ0TG9jYXRpb24sIEphdmFFeGVjdXRvciwgdmZzIH0gZnJvbSBcIkB4bWNsL3V0aWxcIjtcbmltcG9ydCB7IFZlcnNpb24gfSBmcm9tIFwiQHhtY2wvdmVyc2lvblwiO1xuaW1wb3J0IHsgZGVsaW1pdGVyLCBqb2luIH0gZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IFJlYWRhYmxlIH0gZnJvbSBcInN0cmVhbVwiO1xuXG5hc3luYyBmdW5jdGlvbiBmaW5kTWFpbkNsYXNzKGxpYjogc3RyaW5nKSB7XG4gICAgY29uc3QgemlwID0gYXdhaXQgVW56aXAub3BlbihsaWIsIHsgbGF6eUVudHJpZXM6IHRydWUgfSk7XG4gICAgY29uc3QgW21hbmlmZXN0XSA9IGF3YWl0IHppcC5maWx0ZXJFbnRyaWVzKFtcIk1FVEEtSU5GL01BTklGRVNULk1GXCJdKTtcbiAgICBsZXQgbWFpbkNsYXNzOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgaWYgKG1hbmlmZXN0KSB7XG4gICAgICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCB6aXAucmVhZEVudHJ5KG1hbmlmZXN0KS50aGVuKChiKSA9PiBiLnRvU3RyaW5nKCkpO1xuICAgICAgICBjb25zdCBtYWluQ2xhc3NQYWlyID0gY29udGVudC5zcGxpdChcIlxcblwiKS5tYXAoKGwpID0+IGwuc3BsaXQoXCI6IFwiKSkuZmlsdGVyKChhcnIpID0+IGFyclswXSA9PT0gXCJNYWluLUNsYXNzXCIpWzBdO1xuICAgICAgICBpZiAobWFpbkNsYXNzUGFpcikge1xuICAgICAgICAgICAgbWFpbkNsYXNzID0gbWFpbkNsYXNzUGFpclsxXS50cmltKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgemlwLmNsb3NlKCk7XG4gICAgcmV0dXJuIG1haW5DbGFzcztcbn1cblxuLyoqXG4gKiBUaGUgZm9yZ2UgaW5zdGFsbGVyIE1vZHVsZSB0byBpbnN0YWxsIGZvcmdlIHRvIHRoZSBnYW1lXG4gKi9cbmV4cG9ydCBuYW1lc3BhY2UgRm9yZ2VJbnN0YWxsZXIge1xuICAgIC8qKlxuICAgICAqIFRoZSBmb3JnZSB2ZXJzaW9uIG1ldGFkYXRhIHRvIGRvd25sb2FkIGEgZm9yZ2VcbiAgICAgKi9cbiAgICBleHBvcnQgaW50ZXJmYWNlIFZlcnNpb25NZXRhIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoZSBpbnN0YWxsZXIgaW5mb1xuICAgICAgICAgKi9cbiAgICAgICAgaW5zdGFsbGVyOiB7XG4gICAgICAgICAgICBtZDU6IHN0cmluZztcbiAgICAgICAgICAgIHNoYTE6IHN0cmluZztcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogVGhlIHVybCBwYXRoIHRvIGNvbmNhdCB3aXRoIGZvcmdlIG1hdmVuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHBhdGg6IHN0cmluZztcbiAgICAgICAgfTtcbiAgICAgICAgdW5pdmVyc2FsOiB7XG4gICAgICAgICAgICBtZDU6IHN0cmluZztcbiAgICAgICAgICAgIHNoYTE6IHN0cmluZztcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogVGhlIHVybCBwYXRoIHRvIGNvbmNhdCB3aXRoIGZvcmdlIG1hdmVuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHBhdGg6IHN0cmluZztcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoZSBtaW5lY3JhZnQgdmVyc2lvblxuICAgICAgICAgKi9cbiAgICAgICAgbWN2ZXJzaW9uOiBzdHJpbmc7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgZm9yZ2UgdmVyc2lvbiAod2l0aG91dCBtaW5lY3JhZnQgdmVyc2lvbilcbiAgICAgICAgICovXG4gICAgICAgIHZlcnNpb246IHN0cmluZztcbiAgICB9XG5cbiAgICBleHBvcnQgY29uc3QgREVGQVVMVF9GT1JHRV9NQVZFTiA9IFwiaHR0cDovL2ZpbGVzLm1pbmVjcmFmdGZvcmdlLm5ldFwiO1xuXG4gICAgZXhwb3J0IGludGVyZmFjZSBJbnN0YWxsUHJvZmlsZSB7XG4gICAgICAgIHNwZWM6IG51bWJlcjtcbiAgICAgICAgcHJvZmlsZTogc3RyaW5nO1xuICAgICAgICB2ZXJzaW9uOiBzdHJpbmc7XG4gICAgICAgIGpzb246IHN0cmluZztcbiAgICAgICAgcGF0aDogc3RyaW5nO1xuICAgICAgICBtaW5lY3JhZnQ6IHN0cmluZztcbiAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgW2tleTogc3RyaW5nXToge1xuICAgICAgICAgICAgICAgIGNsaWVudDogc3RyaW5nLFxuICAgICAgICAgICAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgICAgcHJvY2Vzc29yczogQXJyYXk8e1xuICAgICAgICAgICAgamFyOiBzdHJpbmcsXG4gICAgICAgICAgICBjbGFzc3BhdGg6IHN0cmluZ1tdLFxuICAgICAgICAgICAgYXJnczogc3RyaW5nW10sXG4gICAgICAgICAgICBvdXRwdXRzPzoge1xuICAgICAgICAgICAgICAgIFtrZXk6IHN0cmluZ106IHN0cmluZyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0+O1xuICAgICAgICBsaWJyYXJpZXM6IFZlcnNpb24uTm9ybWFsTGlicmFyeVtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBmb3JnZSBkaWFnbm9zaXMgcmVwb3J0LiBJdCBtYXkgaGF2ZSBzb21lIGludGVyc2VjdGlvbiB3aXRoIGBWZXJzaW9uLkRpYWdub3Npc2AuXG4gICAgICovXG4gICAgZXhwb3J0IGludGVyZmFjZSBEaWFnbm9zaXMge1xuICAgICAgICAvKipcbiAgICAgICAgICogV2hlbiB0aGlzIGZsYWcgaXMgdHJ1ZSwgcGxlYXNlIHJlaW5zdGFsbCB0b3RhbGx5XG4gICAgICAgICAqL1xuICAgICAgICBiYWRJbnN0YWxsOiBib29sZWFuO1xuICAgICAgICAvKipcbiAgICAgICAgICogV2hlbiBvbmx5IHRoaXMgaXMgbm90IGVtcHR5XG4gICAgICAgICAqL1xuICAgICAgICBiYWRQcm9jZXNzZWRGaWxlczogQXJyYXk8SW5zdGFsbFByb2ZpbGVbXCJwcm9jZXNzb3JzXCJdW251bWJlcl0+O1xuICAgICAgICBiYWRWZXJzaW9uSnNvbjogYm9vbGVhbjtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdoZW4gdGhpcyBpcyBub3QgZW1wdHksIHBsZWFzZSB1c2UgYHBvc3RQcm9jZXNzSW5zdGFsbFByb2ZpbGVgXG4gICAgICAgICAqL1xuICAgICAgICBtaXNzaW5nSW5zdGFsbERlcGVuZGVuY2llczogVmVyc2lvbi5Ob3JtYWxMaWJyYXJ5W107XG5cbiAgICAgICAgbWlzc2luZ0JpbnBhdGNoOiBib29sZWFuO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBbHQgZm9yIGJhZFByb2Nlc3NlZEZpbGVzXG4gICAgICAgICAqL1xuICAgICAgICBtaXNzaW5nU3JnSmFyOiBib29sZWFuO1xuICAgICAgICAvKipcbiAgICAgICAgICogQWx0IGZvciBiYWRQcm9jZXNzZWRGaWxlc1xuICAgICAgICAgKi9cbiAgICAgICAgbWlzc2luZ01pbmVjcmFmdEV4dHJhSmFyOiBib29sZWFuO1xuICAgICAgICAvKipcbiAgICAgICAgICogQWx0IGZvciBiYWRQcm9jZXNzZWRGaWxlc1xuICAgICAgICAgKi9cbiAgICAgICAgbWlzc2luZ0ZvcmdlUGF0Y2hlc0phcjogYm9vbGVhbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEaWFnbm9zZSBmb3Igc3BlY2lmaWMgZm9yZ2UgdmVyc2lvbi4gTWFqb3JseSBmb3IgdGhlIGN1cnJlbnQgaW5zdGFsbGVyIGZvcmdlLiAobWN2ZXJzaW9uID49IDEuMTMpXG4gICAgICpcbiAgICAgKiBEb24ndCB1c2UgdGhpcyB3aXRoIHRoZSB2ZXJzaW9uIGxlc3MgdGhhbiAxLjEzXG4gICAgICogQHBhcmFtIHZlcnNpb25PclByb2ZpbGUgSWYgdGhlIHZlcnNpb24gc3RyaW5nIHByZXNlbnQsIGl0IHdpbGwgdHJ5IHRvIGZpbmQgdGhlIGluc3RhbGxlciBwcm9maWxlIHVuZGVyIHZlcnNpb24gZm9sZGVyLiBPdGhlcndpc2UgaXQgd2lsbCB1c2UgcHJlc2VudGVkIGluc3RhbGxlciBwcm9maWxlIHRvIGRpYWdub3NlXG4gICAgICogQHBhcmFtIG1pbmVjcmFmdCBUaGUgbWluZWNyYWZ0IGxvY2F0aW9uLlxuICAgICAqL1xuICAgIGV4cG9ydCBhc3luYyBmdW5jdGlvbiBkaWFnbm9zZUZvcmdlVmVyc2lvbih2ZXJzaW9uT3JQcm9maWxlOiBzdHJpbmcgfCBJbnN0YWxsUHJvZmlsZSwgbWluZWNyYWZ0OiBNaW5lY3JhZnRMb2NhdGlvbik6IFByb21pc2U8RGlhZ25vc2lzPiB7XG4gICAgICAgIGNvbnN0IHZlcnNpb24gPSB0eXBlb2YgdmVyc2lvbk9yUHJvZmlsZSA9PT0gXCJzdHJpbmdcIiA/IHZlcnNpb25PclByb2ZpbGUgOiB2ZXJzaW9uT3JQcm9maWxlLnZlcnNpb247XG4gICAgICAgIGNvbnN0IG1jID0gTWluZWNyYWZ0Rm9sZGVyLmZyb20obWluZWNyYWZ0KTtcbiAgICAgICAgY29uc3QgdmVyUm9vdCA9IG1jLmdldFZlcnNpb25Sb290KHZlcnNpb24pO1xuICAgICAgICBjb25zdCB2ZXJzaW9uSnNvblBhdGggPSBtYy5nZXRWZXJzaW9uSnNvbih2ZXJzaW9uKTtcblxuICAgICAgICBjb25zdCBkaWFnOiBEaWFnbm9zaXMgPSB7XG4gICAgICAgICAgICBiYWRQcm9jZXNzZWRGaWxlczogW10sXG4gICAgICAgICAgICBtaXNzaW5nSW5zdGFsbERlcGVuZGVuY2llczogW10sXG4gICAgICAgICAgICBiYWRWZXJzaW9uSnNvbjogZmFsc2UsXG4gICAgICAgICAgICBtaXNzaW5nQmlucGF0Y2g6IGZhbHNlLFxuICAgICAgICAgICAgYmFkSW5zdGFsbDogZmFsc2UsXG4gICAgICAgICAgICBtaXNzaW5nU3JnSmFyOiBmYWxzZSxcbiAgICAgICAgICAgIG1pc3NpbmdNaW5lY3JhZnRFeHRyYUphcjogZmFsc2UsXG4gICAgICAgICAgICBtaXNzaW5nRm9yZ2VQYXRjaGVzSmFyOiBmYWxzZSxcbiAgICAgICAgfTtcblxuICAgICAgICBsZXQgcHJvZjogSW5zdGFsbFByb2ZpbGUgfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmICh0eXBlb2YgdmVyc2lvbk9yUHJvZmlsZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgY29uc3QgaW5zdGFsbFByb2ZQYXRoID0gam9pbih2ZXJSb290LCBcImluc3RhbGxfcHJvZmlsZS5qc29uXCIpO1xuICAgICAgICAgICAgaWYgKGF3YWl0IHZmcy5leGlzdHMoaW5zdGFsbFByb2ZQYXRoKSkge1xuICAgICAgICAgICAgICAgIHByb2YgPSBKU09OLnBhcnNlKGF3YWl0IHZmcy5yZWFkRmlsZShpbnN0YWxsUHJvZlBhdGgpLnRoZW4oKGIpID0+IGIudG9TdHJpbmcoKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJvZiA9IHZlcnNpb25PclByb2ZpbGU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHByb2YpIHtcbiAgICAgICAgICAgIGNvbnN0IHByb2Nlc3NlZFByb2ZpbGUgPSBwb3N0UHJvY2Vzc0luc3RhbGxQcm9maWxlKG1jLCBwcm9mKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcHJvYyBvZiBwcm9jZXNzZWRQcm9maWxlLnByb2Nlc3NvcnMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJvYy5vdXRwdXRzKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBiYWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBmaWxlIGluIHByb2Mub3V0cHV0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEgYXdhaXQgdmZzLnZhbGlkYXRlU2hhMShmaWxlLCBwcm9jLm91dHB1dHNbZmlsZV0ucmVwbGFjZSgvJy9nLCBcIlwiKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChiYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpYWcuYmFkUHJvY2Vzc2VkRmlsZXMucHVzaChwcm9jKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGlmIHdlIGhhdmUgdG8gcHJvY2VzcyBmaWxlLCB3ZSBoYXZlIHRvIGNoZWNrIGlmIHRoZSBmb3JnZSBkZXBzIGFyZSByZWFkeVxuICAgICAgICAgICAgaWYgKGRpYWcuYmFkUHJvY2Vzc2VkRmlsZXMubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbGliVmFsaWRNYXNrID0gYXdhaXQgUHJvbWlzZS5hbGwocHJvY2Vzc2VkUHJvZmlsZS5saWJyYXJpZXMubWFwKGFzeW5jIChsaWIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYXJ0aWZhY3QgPSBsaWIuZG93bmxvYWRzLmFydGlmYWN0O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBsaWJQYXRoID0gbWMuZ2V0TGlicmFyeUJ5UGF0aChhcnRpZmFjdC5wYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGF3YWl0IHZmcy5leGlzdHMobGliUGF0aCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhcnRpZmFjdC5zaGExID8gdmZzLnZhbGlkYXRlU2hhMShsaWJQYXRoLCBhcnRpZmFjdC5zaGExKSA6IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICBjb25zdCBtaXNzaW5nTGlicmFyaWVzID0gcHJvY2Vzc2VkUHJvZmlsZS5saWJyYXJpZXMuZmlsdGVyKChfLCBpKSA9PiAhbGliVmFsaWRNYXNrW2ldKTtcbiAgICAgICAgICAgICAgICBkaWFnLm1pc3NpbmdJbnN0YWxsRGVwZW5kZW5jaWVzLnB1c2goLi4ubWlzc2luZ0xpYnJhcmllcyk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCB2YWxpZENsaWVudCA9IGF3YWl0IHZmcy5zdGF0KHByb2Nlc3NlZFByb2ZpbGUuZGF0YS5CSU5QQVRDSC5jbGllbnQpLnRoZW4oKHMpID0+IHMuc2l6ZSAhPT0gMCkuY2F0Y2goKF8pID0+IGZhbHNlKTtcbiAgICAgICAgICAgICAgICBpZiAoIXZhbGlkQ2xpZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGRpYWcubWlzc2luZ0JpbnBhdGNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgZGlhZy5iYWRJbnN0YWxsID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGF3YWl0IHZmcy5leGlzdHModmVyc2lvbkpzb25QYXRoKSkge1xuICAgICAgICAgICAgY29uc3QgdmVyc2lvbkpTT046IFZlcnNpb24gPSBKU09OLnBhcnNlKGF3YWl0IHZmcy5yZWFkRmlsZSh2ZXJzaW9uSnNvblBhdGgpLnRoZW4oKGIpID0+IGIudG9TdHJpbmcoKSkpO1xuICAgICAgICAgICAgaWYgKHZlcnNpb25KU09OLmFyZ3VtZW50cyAmJiB2ZXJzaW9uSlNPTi5hcmd1bWVudHMuZ2FtZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFyZ3MgPSB2ZXJzaW9uSlNPTi5hcmd1bWVudHMuZ2FtZTtcbiAgICAgICAgICAgICAgICBjb25zdCBmb3JnZVZlcnNpb24gPSBhcmdzLmluZGV4T2YoXCItLWZtbC5mb3JnZVZlcnNpb25cIikgKyAxO1xuICAgICAgICAgICAgICAgIGNvbnN0IG1jVmVyc2lvbiA9IGFyZ3MuaW5kZXhPZihcIi0tZm1sLm1jVmVyc2lvblwiKSArIDE7XG4gICAgICAgICAgICAgICAgY29uc3QgbWNwVmVyc2lvbiA9IGFyZ3MuaW5kZXhPZihcIi0tZm1sLm1jcFZlcnNpb25cIikgKyAxO1xuICAgICAgICAgICAgICAgIGlmICghZm9yZ2VWZXJzaW9uIHx8ICFtY1ZlcnNpb24gfHwgIW1jcFZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgZGlhZy5iYWRWZXJzaW9uSnNvbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGRpYWcuYmFkSW5zdGFsbCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3JnUGF0aCA9IG1jLmdldExpYnJhcnlCeVBhdGgoYG5ldC9taW5lY3JhZnQvY2xpZW50LyR7bWNWZXJzaW9ufS0ke21jcFZlcnNpb259L2NsaWVudC0ke21jVmVyc2lvbn0tJHttY3BWZXJzaW9ufS1zcmcuamFyYCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4dHJhUGF0aCA9IG1jLmdldExpYnJhcnlCeVBhdGgoYG5ldC9taW5lY3JhZnQvY2xpZW50LyR7bWNWZXJzaW9ufS9jbGllbnQtJHttY1ZlcnNpb259LWV4dHJhLmphcmApO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBmb3JnZVBhdGNoUGF0aCA9IG1jLmdldExpYnJhcnlCeVBhdGgoYG5ldC9taW5lY3JhZnRmb3JnZS9mb3JnZS8ke21jVmVyc2lvbn0tJHtmb3JnZVZlcnNpb259L2ZvcmdlLSR7bWNWZXJzaW9ufS0ke2ZvcmdlVmVyc2lvbn0tY2xpZW50LmphcmApO1xuICAgICAgICAgICAgICAgICAgICBkaWFnLm1pc3NpbmdTcmdKYXIgPSBhd2FpdCB2ZnMubWlzc2luZyhzcmdQYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgZGlhZy5taXNzaW5nTWluZWNyYWZ0RXh0cmFKYXIgPSBhd2FpdCB2ZnMubWlzc2luZyhleHRyYVBhdGgpO1xuICAgICAgICAgICAgICAgICAgICBkaWFnLm1pc3NpbmdGb3JnZVBhdGNoZXNKYXIgPSBhd2FpdCB2ZnMubWlzc2luZyhmb3JnZVBhdGNoUGF0aCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkaWFnLmJhZFZlcnNpb25Kc29uID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBkaWFnLmJhZEluc3RhbGwgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGlhZy5iYWRWZXJzaW9uSnNvbiA9IHRydWU7XG4gICAgICAgICAgICBkaWFnLmJhZEluc3RhbGwgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGRpYWc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUG9zdCBwcm9jZXNzaW5nIGZ1bmN0aW9uIGZvciBuZXcgZm9yZ2UgaW5zdGFsbGVyIChtY3ZlcnNpb24gPj0gMS4xMykuIFlvdSBjYW4gdXNlIHRoaXMgd2l0aCBgRm9yZ2VJbnN0YWxsZXIuZGlhZ25vc2VgLlxuICAgICAqXG4gICAgICogQHBhcmFtIG1jIFRoZSBtaW5lY3JhZnQgbG9jYXRpb25cbiAgICAgKiBAcGFyYW0gcHJvYyBUaGUgcHJvY2Vzc29yXG4gICAgICogQHBhcmFtIGphdmEgVGhlIGphdmEgZXhlY3V0b3JcbiAgICAgKi9cbiAgICBleHBvcnQgYXN5bmMgZnVuY3Rpb24gcG9zdFByb2Nlc3MobWM6IE1pbmVjcmFmdEZvbGRlciwgcHJvYzogSW5zdGFsbFByb2ZpbGVbXCJwcm9jZXNzb3JzXCJdW251bWJlcl0sIGphdmE6IEphdmFFeGVjdXRvcikge1xuICAgICAgICBjb25zdCBqYXJSZWFsUGF0aCA9IG1jLmdldExpYnJhcnlCeVBhdGgoVmVyc2lvbi5nZXRMaWJyYXJ5SW5mbyhwcm9jLmphcikucGF0aCk7XG4gICAgICAgIGNvbnN0IG1haW5DbGFzcyA9IGF3YWl0IGZpbmRNYWluQ2xhc3MoamFyUmVhbFBhdGgpO1xuICAgICAgICBpZiAoIW1haW5DbGFzcykgeyB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBmaW5kIG1haW4gY2xhc3MgZm9yIHByb2Nlc3NvciAke3Byb2MuamFyfS5gKTsgfVxuICAgICAgICBjb25zdCBjcCA9IFsuLi5wcm9jLmNsYXNzcGF0aCwgcHJvYy5qYXJdLm1hcChWZXJzaW9uLmdldExpYnJhcnlJbmZvKS5tYXAoKHApID0+IG1jLmdldExpYnJhcnlCeVBhdGgocC5wYXRoKSkuam9pbihkZWxpbWl0ZXIpO1xuICAgICAgICBjb25zdCBjbWQgPSBbXCItY3BcIiwgY3AsIG1haW5DbGFzcywgLi4ucHJvYy5hcmdzXTtcbiAgICAgICAgYXdhaXQgamF2YShjbWQpO1xuICAgICAgICBsZXQgZmFpbGVkID0gZmFsc2U7XG4gICAgICAgIGlmIChwcm9jLm91dHB1dHMpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgZmlsZSBpbiBwcm9jLm91dHB1dHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoISBhd2FpdCB2ZnMudmFsaWRhdGVTaGExKGZpbGUsIHByb2Mub3V0cHV0c1tmaWxlXS5yZXBsYWNlKC8nL2csIFwiXCIpKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBGYWlsIHRvIHByb2Nlc3MgJHtwcm9jLmphcn0gQCAke2ZpbGV9IHNpbmNlIGl0cyB2YWxpZGF0aW9uIGZhaWxlZC5gKTtcbiAgICAgICAgICAgICAgICAgICAgZmFpbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZhaWxlZCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihgSmF2YSBhcmd1bWVudHM6ICR7SlNPTi5zdHJpbmdpZnkoY21kKX1gKTtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkZhaWwgdG8gcHJvY2VzcyBwb3N0IHByb2Nlc3Npbmcgc2luY2UgaXRzIHZhbGlkYXRpb24gZmFpbGVkLlwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBvc3RQcm9jZXNzSW5zdGFsbFByb2ZpbGUobWM6IE1pbmVjcmFmdEZvbGRlciwgaW5zdGFsbFByb2ZpbGU6IEluc3RhbGxQcm9maWxlKSB7XG4gICAgICAgIGZ1bmN0aW9uIHByb2Nlc3NWYWx1ZSh2OiBzdHJpbmcpIHtcbiAgICAgICAgICAgIGlmICh2Lm1hdGNoKC9eXFxbLitcXF0kL2cpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0SWQgPSB2LnN1YnN0cmluZygxLCB2Lmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgIHJldHVybiBtYy5nZXRMaWJyYXJ5QnlQYXRoKFZlcnNpb24uZ2V0TGlicmFyeUluZm8odGFyZ2V0SWQpLnBhdGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHY7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gcHJvY2Vzc01hcHBpbmcoZGF0YTogSW5zdGFsbFByb2ZpbGVbXCJkYXRhXCJdLCBtOiBzdHJpbmcpIHtcbiAgICAgICAgICAgIG0gPSBwcm9jZXNzVmFsdWUobSk7XG4gICAgICAgICAgICBpZiAobS5tYXRjaCgvXnsuK30kL2cpKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qga2V5ID0gbS5zdWJzdHJpbmcoMSwgbS5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgICAgICBtID0gZGF0YVtrZXldLmNsaWVudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHByb2ZpbGU6IEluc3RhbGxQcm9maWxlID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShpbnN0YWxsUHJvZmlsZSkpO1xuICAgICAgICBwcm9maWxlLmRhdGEuTUlORUNSQUZUX0pBUiA9IHtcbiAgICAgICAgICAgIGNsaWVudDogbWMuZ2V0VmVyc2lvbkphcihwcm9maWxlLm1pbmVjcmFmdCksXG4gICAgICAgICAgICBzZXJ2ZXI6IFwiXCIsXG4gICAgICAgIH07XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHByb2ZpbGUuZGF0YSkge1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBwcm9maWxlLmRhdGFba2V5XTtcbiAgICAgICAgICAgIHZhbHVlLmNsaWVudCA9IHByb2Nlc3NWYWx1ZSh2YWx1ZS5jbGllbnQpO1xuICAgICAgICAgICAgdmFsdWUuc2VydmVyID0gcHJvY2Vzc1ZhbHVlKHZhbHVlLnNlcnZlcik7XG5cbiAgICAgICAgICAgIGlmIChrZXkgPT09IFwiQklOUEFUQ0hcIikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZlclJvb3QgPSBtYy5nZXRWZXJzaW9uUm9vdChwcm9maWxlLnZlcnNpb24pO1xuICAgICAgICAgICAgICAgIHZhbHVlLmNsaWVudCA9IGpvaW4odmVyUm9vdCwgdmFsdWUuY2xpZW50KTtcbiAgICAgICAgICAgICAgICB2YWx1ZS5zZXJ2ZXIgPSBqb2luKHZlclJvb3QsIHZhbHVlLnNlcnZlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBwcm9jIG9mIHByb2ZpbGUucHJvY2Vzc29ycykge1xuICAgICAgICAgICAgcHJvYy5hcmdzID0gcHJvYy5hcmdzLm1hcCgoYSkgPT4gcHJvY2Vzc01hcHBpbmcocHJvZmlsZS5kYXRhLCBhKSk7XG4gICAgICAgICAgICBpZiAocHJvYy5vdXRwdXRzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVwbGFjZWRPdXRwdXQ6IEluc3RhbGxQcm9maWxlW1wicHJvY2Vzc29yc1wiXVswXVtcIm91dHB1dHNcIl0gPSB7fTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBwcm9jLm91dHB1dHMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVwbGFjZWRPdXRwdXRbcHJvY2Vzc01hcHBpbmcocHJvZmlsZS5kYXRhLCBrZXkpXSA9IHByb2Nlc3NNYXBwaW5nKHByb2ZpbGUuZGF0YSwgcHJvYy5vdXRwdXRzW2tleV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwcm9jLm91dHB1dHMgPSByZXBsYWNlZE91dHB1dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwcm9maWxlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluc3RhbGwgZm9yIGZvcmdlIGluc3RhbGxlciBzdGVwIDIgYW5kIDMuXG4gICAgICogQHBhcmFtIHZlcnNpb24gVGhlIHZlcnNpb24gc3RyaW5nIG9yIGluc3RhbGxlciBwcm9maWxlXG4gICAgICogQHBhcmFtIG1pbmVjcmFmdCBUaGUgbWluZWNyYWZ0IGxvY2F0aW9uXG4gICAgICovXG4gICAgZXhwb3J0IGZ1bmN0aW9uIGluc3RhbGxCeUluc3RhbGxlclBhcnRpYWxUYXNrKHZlcnNpb246IHN0cmluZyB8IEluc3RhbGxQcm9maWxlLCBtaW5lY3JhZnQ6IE1pbmVjcmFmdExvY2F0aW9uLCBvcHRpb246IHtcbiAgICAgICAgamF2YT86IEphdmFFeGVjdXRvcixcbiAgICB9ICYgSW5zdGFsbGVyLkxpYnJhcnlPcHRpb24gPSB7fSkge1xuICAgICAgICByZXR1cm4gYXN5bmMgZnVuY3Rpb24gaW5zdGFsbEZvcmdlKGNvbnRleHQ6IFRhc2suQ29udGV4dCkge1xuICAgICAgICAgICAgY29uc3QgbWMgPSBNaW5lY3JhZnRGb2xkZXIuZnJvbShtaW5lY3JhZnQpO1xuICAgICAgICAgICAgbGV0IHByb2Y6IEluc3RhbGxQcm9maWxlO1xuICAgICAgICAgICAgbGV0IHZlcjogVmVyc2lvbjtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdmVyc2lvbiA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZlcnNpb25Sb290ID0gbWMuZ2V0VmVyc2lvblJvb3QodmVyc2lvbik7XG4gICAgICAgICAgICAgICAgcHJvZiA9IGF3YWl0IHZmcy5yZWFkRmlsZShqb2luKHZlcnNpb25Sb290LCBcImluc3RhbGxfcHJvZmlsZS5qc29uXCIpKS50aGVuKChiKSA9PiBiLnRvU3RyaW5nKCkpLnRoZW4oSlNPTi5wYXJzZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHByb2YgPSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmVyID0gYXdhaXQgdmZzLnJlYWRGaWxlKG1jLmdldFZlcnNpb25Kc29uKHByb2YudmVyc2lvbikpLnRoZW4oKGIpID0+IGIudG9TdHJpbmcoKSkudGhlbihKU09OLnBhcnNlKTtcbiAgICAgICAgICAgIGF3YWl0IGluc3RhbGxCeUluc3RhbGxlclBhcnRpYWxXb3JrKG1jLCBwcm9mLCB2ZXIsIG9wdGlvbi5qYXZhIHx8IEphdmFFeGVjdXRvci5jcmVhdGVTaW1wbGUoXCJqYXZhXCIpLCBvcHRpb24pKGNvbnRleHQpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluc3RhbGwgZm9yIGZvcmdlIGluc3RhbGxlciBzdGVwIDIgYW5kIDMuXG4gICAgICogQHBhcmFtIHZlcnNpb24gVGhlIHZlcnNpb24gc3RyaW5nIG9yIGluc3RhbGxlciBwcm9maWxlXG4gICAgICogQHBhcmFtIG1pbmVjcmFmdCBUaGUgbWluZWNyYWZ0IGxvY2F0aW9uXG4gICAgICovXG4gICAgZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGluc3RhbGxCeUluc3RhbGxlclBhcnRpYWwodmVyc2lvbjogc3RyaW5nIHwgSW5zdGFsbFByb2ZpbGUsIG1pbmVjcmFmdDogTWluZWNyYWZ0TG9jYXRpb24sIG9wdGlvbjoge1xuICAgICAgICBqYXZhPzogSmF2YUV4ZWN1dG9yLFxuICAgIH0gJiBJbnN0YWxsZXIuTGlicmFyeU9wdGlvbiA9IHt9KSB7XG4gICAgICAgIHJldHVybiBUYXNrLmV4ZWN1dGUoaW5zdGFsbEJ5SW5zdGFsbGVyUGFydGlhbFRhc2sodmVyc2lvbiwgbWluZWNyYWZ0LCBvcHRpb24pKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpbnN0YWxsQnlJbnN0YWxsZXJQYXJ0aWFsV29yayhtYzogTWluZWNyYWZ0Rm9sZGVyLCBwcm9maWxlOiBJbnN0YWxsUHJvZmlsZSwgdmVyc2lvbkpzb246IFZlcnNpb24sIGphdmE6IEphdmFFeGVjdXRvciwgaW5zdGFsbExpYk9wdGlvbjogSW5zdGFsbGVyLkxpYnJhcnlPcHRpb24pIHtcbiAgICAgICAgcmV0dXJuIGFzeW5jIChjb250ZXh0OiBUYXNrLkNvbnRleHQpID0+IHtcbiAgICAgICAgICAgIHByb2ZpbGUgPSBwb3N0UHJvY2Vzc0luc3RhbGxQcm9maWxlKG1jLCBwcm9maWxlKTtcblxuICAgICAgICAgICAgY29uc3QgcGFyc2VkTGlicyA9IFZlcnNpb24ucmVzb2x2ZUxpYnJhcmllcyhbLi4ucHJvZmlsZS5saWJyYXJpZXMsIC4uLnZlcnNpb25Kc29uLmxpYnJhcmllc10pO1xuICAgICAgICAgICAgYXdhaXQgY29udGV4dC5leGVjdXRlKEluc3RhbGxlci5pbnN0YWxsTGlicmFyaWVzRGlyZWN0VGFzayhwYXJzZWRMaWJzLCBtYywge1xuICAgICAgICAgICAgICAgIC4uLmluc3RhbGxMaWJPcHRpb24sXG4gICAgICAgICAgICAgICAgbGlicmFyeUhvc3Q6IGluc3RhbGxMaWJPcHRpb24ubGlicmFyeUhvc3QgPyAobCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAobC5hcnRpZmFjdElkID09PSBcImZvcmdlXCIgJiYgbC5ncm91cElkID09PSBcIm5ldC5taW5lY3JhZnRmb3JnZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYGZpbGU6Ly8ke21jLmdldExpYnJhcnlCeVBhdGgobC5wYXRoKX1gO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnN0YWxsTGliT3B0aW9uLmxpYnJhcnlIb3N0IShsKTtcbiAgICAgICAgICAgICAgICB9IDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgfSkpO1xuXG4gICAgICAgICAgICBhd2FpdCBjb250ZXh0LmV4ZWN1dGUoYXN5bmMgZnVuY3Rpb24gcG9zdFByb2Nlc3NpbmcoY3R4KSB7XG4gICAgICAgICAgICAgICAgY3R4LnVwZGF0ZSgwLCBwcm9maWxlLnByb2Nlc3NvcnMubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICBsZXQgaSA9IDA7XG4gICAgICAgICAgICAgICAgY29uc3QgZXJyczogRXJyb3JbXSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcHJvYyBvZiBwcm9maWxlLnByb2Nlc3NvcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHBvc3RQcm9jZXNzKG1jLCBwcm9jLCBqYXZhKTtcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJycy5wdXNoKGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGN0eC51cGRhdGUoaSArPSAxLCBwcm9maWxlLnByb2Nlc3NvcnMubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaSArPSAxO1xuICAgICAgICAgICAgICAgIGN0eC51cGRhdGUoaSwgcHJvZmlsZS5wcm9jZXNzb3JzLmxlbmd0aCk7XG5cbiAgICAgICAgICAgICAgICBpZiAoZXJycy5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmFpbCB0byBwb3N0IHByb2Nlc3NpbmdcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5zdGFsbEJ5SW5zdGFsbGVyVGFzayh2ZXJzaW9uOiBWZXJzaW9uTWV0YSwgbWluZWNyYWZ0OiBNaW5lY3JhZnRMb2NhdGlvbiwgbWF2ZW46IHN0cmluZywgaW5zdGFsbExpYk9wdGlvbjogSW5zdGFsbGVyLkxpYnJhcnlPcHRpb24sIGphdmE6IEphdmFFeGVjdXRvcikge1xuICAgICAgICByZXR1cm4gYXN5bmMgZnVuY3Rpb24gaW5zdGFsbEZvcmdlKGNvbnRleHQ6IFRhc2suQ29udGV4dCkge1xuICAgICAgICAgICAgY29uc3QgbWMgPSBNaW5lY3JhZnRGb2xkZXIuZnJvbShtaW5lY3JhZnQpO1xuXG4gICAgICAgICAgICBjb25zdCBmb3JnZVZlcnNpb24gPSBgJHt2ZXJzaW9uLm1jdmVyc2lvbn0tJHt2ZXJzaW9uLnZlcnNpb259YDtcbiAgICAgICAgICAgIGNvbnN0IGluc3RhbGxlclVSTCA9IGAke21hdmVufSR7dmVyc2lvbi5pbnN0YWxsZXIucGF0aH1gO1xuICAgICAgICAgICAgY29uc3QgaW5zdGFsbGVyVVJMRmFsbGJhY2sgPSBgJHttYXZlbn0vbWF2ZW4vbmV0L21pbmVjcmFmdGZvcmdlL2ZvcmdlLyR7Zm9yZ2VWZXJzaW9ufS9mb3JnZS0ke2ZvcmdlVmVyc2lvbn0taW5zdGFsbGVyLmphcmA7XG4gICAgICAgICAgICBjb25zdCBpbnN0YWxsSmFyID0gbWMuZ2V0TGlicmFyeUJ5UGF0aCh2ZXJzaW9uLmluc3RhbGxlci5wYXRoLnN1YnN0cmluZyh2ZXJzaW9uLmluc3RhbGxlci5wYXRoLnN1YnN0cmluZygxKS5pbmRleE9mKFwiL1wiKSArIDEpKTtcblxuICAgICAgICAgICAgbGV0IHZlcnNpb25JZDogc3RyaW5nO1xuICAgICAgICAgICAgbGV0IHByb2ZpbGUhOiBJbnN0YWxsUHJvZmlsZTtcbiAgICAgICAgICAgIGxldCB2ZXJzaW9uSnNvbiE6IFZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRvd25sb2FkSW5zdGFsbGVyVGFzayhpbnN0YWxsZXI6IHN0cmluZywgZGVzdDogc3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFzeW5jIGZ1bmN0aW9uIGRvd25sb2FkSW5zdGFsbGVyKGN0eDogVGFzay5Db250ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGRvd25sb2FkRmlsZUlmQWJzZW50V29yayh7XG4gICAgICAgICAgICAgICAgICAgICAgICB1cmw6IGluc3RhbGxlcixcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RpbmF0aW9uOiBkZXN0LFxuICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2tzdW06IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNoOiB2ZXJzaW9uLmluc3RhbGxlci5zaGExLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsZ29yaXRobTogXCJzaGExXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB9KShjdHgpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmZzLmNyZWF0ZVJlYWRTdHJlYW0oZGVzdCkucGlwZShVbnppcC5jcmVhdGVQYXJzZVN0cmVhbSh7IGxhenlFbnRyaWVzOiB0cnVlIH0pKS53YWl0KCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NWZXJzaW9uKHppcDogVW56aXAuWmlwRmlsZSwgaW5zdGFsbFByb2ZpbGVFbnRyeTogVW56aXAuRW50cnksIHZlcnNpb25FbnRyeTogVW56aXAuRW50cnksIGNsaWVudERhdGFFbnRyeTogVW56aXAuRW50cnkpIHtcbiAgICAgICAgICAgICAgICBwcm9maWxlID0gYXdhaXQgemlwLnJlYWRFbnRyeShpbnN0YWxsUHJvZmlsZUVudHJ5KS50aGVuKChiKSA9PiBiLnRvU3RyaW5nKCkpLnRoZW4oSlNPTi5wYXJzZSk7XG4gICAgICAgICAgICAgICAgdmVyc2lvbkpzb24gPSBhd2FpdCB6aXAucmVhZEVudHJ5KHZlcnNpb25FbnRyeSkudGhlbigoYikgPT4gYi50b1N0cmluZygpKS50aGVuKEpTT04ucGFyc2UpO1xuICAgICAgICAgICAgICAgIHZlcnNpb25JZCA9IHZlcnNpb25Kc29uLmlkO1xuXG4gICAgICAgICAgICAgICAgY29uc3Qgcm9vdFBhdGggPSBtYy5nZXRWZXJzaW9uUm9vdCh2ZXJzaW9uSnNvbi5pZCk7XG4gICAgICAgICAgICAgICAgY29uc3QganNvblBhdGggPSBqb2luKHJvb3RQYXRoLCBgJHt2ZXJzaW9uSnNvbi5pZH0uanNvbmApO1xuICAgICAgICAgICAgICAgIGNvbnN0IGluc3RhbGxKc29uUGF0aCA9IGpvaW4ocm9vdFBhdGgsIFwiaW5zdGFsbF9wcm9maWxlLmpzb25cIik7XG4gICAgICAgICAgICAgICAgY29uc3QgY2xpZW50RGF0YVBhdGggPSBqb2luKHJvb3RQYXRoLCBwcm9maWxlLmRhdGEuQklOUEFUQ0guY2xpZW50KTtcblxuICAgICAgICAgICAgICAgIGF3YWl0IHZmcy5lbnN1cmVGaWxlKGpzb25QYXRoKTtcbiAgICAgICAgICAgICAgICBhd2FpdCB2ZnMud3JpdGVGaWxlKGluc3RhbGxKc29uUGF0aCwgSlNPTi5zdHJpbmdpZnkocHJvZmlsZSkpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHZmcy53cml0ZUZpbGUoanNvblBhdGgsIEpTT04uc3RyaW5naWZ5KHZlcnNpb25Kc29uKSk7XG5cbiAgICAgICAgICAgICAgICBhd2FpdCB2ZnMuZW5zdXJlRmlsZShjbGllbnREYXRhUGF0aCk7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtID0gYXdhaXQgemlwLm9wZW5FbnRyeShjbGllbnREYXRhRW50cnkpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHZmcy53YWl0U3RyZWFtKHN0cmVhbS5waXBlKHZmcy5jcmVhdGVXcml0ZVN0cmVhbShjbGllbnREYXRhUGF0aCkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NFeHRyYWN0TGlicmFyeShzdHJlYW06IFJlYWRhYmxlLCBwOiBzdHJpbmcpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmaWxlID0gbWMuZ2V0TGlicmFyeUJ5UGF0aChwLnN1YnN0cmluZyhwLmluZGV4T2YoXCIvXCIpICsgMSkpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHZmcy5lbnN1cmVGaWxlKGZpbGUpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHZmcy53YWl0U3RyZWFtKHN0cmVhbS5waXBlKHZmcy5jcmVhdGVXcml0ZVN0cmVhbShmaWxlKSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGxldCB6aXA6IFVuemlwLkxhenlaaXBGaWxlO1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHppcCA9IGF3YWl0IGNvbnRleHQuZXhlY3V0ZShkb3dubG9hZEluc3RhbGxlclRhc2soaW5zdGFsbGVyVVJMLCBpbnN0YWxsSmFyKSk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgICAgICAgIHppcCA9IGF3YWl0IGNvbnRleHQuZXhlY3V0ZShkb3dubG9hZEluc3RhbGxlclRhc2soaW5zdGFsbGVyVVJMRmFsbGJhY2ssIGluc3RhbGxKYXIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBbZm9yZ2VFbnRyeSwgZm9yZ2VVbml2ZXJzYWxFbnRyeSwgY2xpZW50RGF0YUVudHJ5LCBpbnN0YWxsUHJvZmlsZUVudHJ5LCB2ZXJzaW9uRW50cnldID0gYXdhaXQgemlwLmZpbHRlckVudHJpZXMoW1xuICAgICAgICAgICAgICAgICAgICBgbWF2ZW4vbmV0L21pbmVjcmFmdGZvcmdlL2ZvcmdlLyR7Zm9yZ2VWZXJzaW9ufS9mb3JnZS0ke2ZvcmdlVmVyc2lvbn0uamFyYCxcbiAgICAgICAgICAgICAgICAgICAgYG1hdmVuL25ldC9taW5lY3JhZnRmb3JnZS9mb3JnZS8ke2ZvcmdlVmVyc2lvbn0vZm9yZ2UtJHtmb3JnZVZlcnNpb259LXVuaXZlcnNhbC5qYXJgLFxuICAgICAgICAgICAgICAgICAgICBcImRhdGEvY2xpZW50Lmx6bWFcIixcbiAgICAgICAgICAgICAgICAgICAgXCJpbnN0YWxsX3Byb2ZpbGUuanNvblwiLFxuICAgICAgICAgICAgICAgICAgICBcInZlcnNpb24uanNvblwiXG4gICAgICAgICAgICAgICAgXSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWZvcmdlRW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTWlzc2luZyBmb3JnZSBqYXIgZW50cnlcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghZm9yZ2VVbml2ZXJzYWxFbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJNaXNzaW5nIGZvcmdlIHVuaXZlcnNhbCBlbnRyeVwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCFpbnN0YWxsUHJvZmlsZUVudHJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk1pc3NpbmcgaW5zdGFsbCBwcm9maWxlXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIXZlcnNpb25FbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJNaXNzaW5nIHZlcnNpb24gZW50cnlcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgYXdhaXQgcHJvY2Vzc0V4dHJhY3RMaWJyYXJ5KGF3YWl0IHppcC5vcGVuRW50cnkoZm9yZ2VFbnRyeSksIGZvcmdlRW50cnkuZmlsZU5hbWUpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHByb2Nlc3NFeHRyYWN0TGlicmFyeShhd2FpdCB6aXAub3BlbkVudHJ5KGZvcmdlVW5pdmVyc2FsRW50cnkpLCBmb3JnZVVuaXZlcnNhbEVudHJ5LmZpbGVOYW1lKTtcbiAgICAgICAgICAgICAgICBhd2FpdCBwcm9jZXNzVmVyc2lvbih6aXAsIGluc3RhbGxQcm9maWxlRW50cnksIHZlcnNpb25FbnRyeSwgY2xpZW50RGF0YUVudHJ5KTtcblxuICAgICAgICAgICAgICAgIGF3YWl0IGluc3RhbGxCeUluc3RhbGxlclBhcnRpYWxXb3JrKG1jLCBwcm9maWxlLCB2ZXJzaW9uSnNvbiwgamF2YSwgaW5zdGFsbExpYk9wdGlvbikoY29udGV4dCk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdmVyc2lvbklkITtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBDYW5ub3QgaW5zdGFsbCBmb3JnZSBieSBpbnN0YWxsZXIgJHt2ZXJzaW9uLnZlcnNpb259YCk7XG4gICAgICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpbnN0YWxsQnlVbml2ZXJzYWxUYXNrKHZlcnNpb246IFZlcnNpb25NZXRhLCBtaW5lY3JhZnQ6IE1pbmVjcmFmdExvY2F0aW9uLCBtYXZlbjogc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBhc3luYyBmdW5jdGlvbiBpbnN0YWxsRm9yZ2UoY29udGV4dDogVGFzay5Db250ZXh0KSB7XG4gICAgICAgICAgICBjb25zdCBtYyA9IE1pbmVjcmFmdEZvbGRlci5mcm9tKG1pbmVjcmFmdCk7XG4gICAgICAgICAgICBjb25zdCBmb3JnZVZlcnNpb24gPSBgJHt2ZXJzaW9uLm1jdmVyc2lvbn0tJHt2ZXJzaW9uLnZlcnNpb259YDtcbiAgICAgICAgICAgIGNvbnN0IHBhdGhzID0gdmVyc2lvbi51bml2ZXJzYWwucGF0aC5zcGxpdChcIi9cIik7XG4gICAgICAgICAgICBjb25zdCByZWFsRm9yZ2VWZXJzaW9uID0gcGF0aHNbcGF0aHMubGVuZ3RoIC0gMl07XG4gICAgICAgICAgICBjb25zdCBqYXJQYXRoID0gbWMuZ2V0TGlicmFyeUJ5UGF0aChgbmV0L21pbmVjcmFmdGZvcmdlL2ZvcmdlLyR7cmVhbEZvcmdlVmVyc2lvbn0vZm9yZ2UtJHtyZWFsRm9yZ2VWZXJzaW9ufS5qYXJgKTtcbiAgICAgICAgICAgIGxldCBmdWxsVmVyc2lvbjogc3RyaW5nO1xuICAgICAgICAgICAgbGV0IHJlYWxKYXJQYXRoOiBzdHJpbmc7XG5cbiAgICAgICAgICAgIGNvbnN0IHVuaXZlcnNhbFVSTEZhbGxiYWNrID0gYCR7bWF2ZW59L21hdmVuL25ldC9taW5lY3JhZnRmb3JnZS9mb3JnZS8ke2ZvcmdlVmVyc2lvbn0vZm9yZ2UtJHtmb3JnZVZlcnNpb259LXVuaXZlcnNhbC5qYXJgO1xuICAgICAgICAgICAgY29uc3QgdW5pdmVyc2FsVVJMID0gYCR7bWF2ZW59JHt2ZXJzaW9uLnVuaXZlcnNhbC5wYXRofWA7XG5cbiAgICAgICAgICAgIGF3YWl0IGNvbnRleHQuZXhlY3V0ZShhc3luYyBmdW5jdGlvbiBpbnN0YWxsRm9yZ2VKYXIoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGF3YWl0IHZmcy5leGlzdHMoamFyUGF0aCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsaWQgPSBhd2FpdCB2ZnMudmFsaWRhdGUoamFyUGF0aCwgeyBhbGdvcml0aG06IFwibWQ1XCIsIGhhc2g6IHZlcnNpb24udW5pdmVyc2FsLm1kNSB9LCB7IGFsZ29yaXRobTogXCJzaGExXCIsIGhhc2g6IHZlcnNpb24udW5pdmVyc2FsLnNoYTEgfSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2YWxpZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGRvd25sb2FkSmFyKGN0eDogVGFzay5Db250ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkb3dubG9hZEZpbGVXb3JrKHsgdXJsOiB1bml2ZXJzYWxVUkwsIGRlc3RpbmF0aW9uOiBqYXJQYXRoIH0pKGN0eCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGF3YWl0IGNvbnRleHQuZXhlY3V0ZShkb3dubG9hZEphcik7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgYXdhaXQgY29udGV4dC5leGVjdXRlKGFzeW5jIGZ1bmN0aW9uIGluc3RhbGxGb3JnZUpzb24oKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgemlwID0gYXdhaXQgVW56aXAub3BlbihqYXJQYXRoLCB7IGxhenlFbnRyaWVzOiB0cnVlIH0pO1xuICAgICAgICAgICAgICAgIGNvbnN0IFt2ZXJzaW9uRW50cnldID0gYXdhaXQgemlwLmZpbHRlckVudHJpZXMoW1widmVyc2lvbi5qc29uXCJdKTtcblxuICAgICAgICAgICAgICAgIGlmICh2ZXJzaW9uRW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYnVmID0gYXdhaXQgemlwLnJlYWRFbnRyeSh2ZXJzaW9uRW50cnkpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByYXcgPSBKU09OLnBhcnNlKGJ1Zi50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaWQgPSByYXcuaWQ7XG4gICAgICAgICAgICAgICAgICAgIGZ1bGxWZXJzaW9uID0gaWQ7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJvb3RQYXRoID0gbWMuZ2V0VmVyc2lvblJvb3QoZnVsbFZlcnNpb24pO1xuICAgICAgICAgICAgICAgICAgICByZWFsSmFyUGF0aCA9IG1jLmdldExpYnJhcnlCeVBhdGgoVmVyc2lvbi5nZXRMaWJyYXJ5SW5mbyhyYXcubGlicmFyaWVzLmZpbmQoKGw6IGFueSkgPT4gbC5uYW1lLnN0YXJ0c1dpdGgoXCJuZXQubWluZWNyYWZ0Zm9yZ2U6Zm9yZ2VcIikpKS5wYXRoKTtcblxuICAgICAgICAgICAgICAgICAgICBhd2FpdCB2ZnMuZW5zdXJlRGlyKHJvb3RQYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QganNvblBhdGggPSBqb2luKHJvb3RQYXRoLCBgJHtpZH0uanNvbmApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoYXdhaXQgdmZzLm1pc3NpbmcoanNvblBhdGgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB2ZnMud3JpdGVGaWxlKGpzb25QYXRoLCBidWYpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgaW5zdGFsbCBmb3JnZSBqc29uIGZvciAke3ZlcnNpb24udmVyc2lvbn0gc2luY2UgdGhlIHZlcnNpb24ganNvbiBpcyBtaXNzaW5nIWApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAocmVhbEphclBhdGghICE9PSBqYXJQYXRoKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgdmZzLmVuc3VyZUZpbGUocmVhbEphclBhdGghKTtcbiAgICAgICAgICAgICAgICBhd2FpdCB2ZnMuY29weUZpbGUoamFyUGF0aCwgcmVhbEphclBhdGghKTtcbiAgICAgICAgICAgICAgICBhd2FpdCB2ZnMudW5saW5rKGphclBhdGgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gZnVsbFZlcnNpb24hO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluc3RhbGwgZm9yZ2UgdG8gdGFyZ2V0IGxvY2F0aW9uLlxuICAgICAqIEluc3RhbGxhdGlvbiB0YXNrIGZvciBmb3JnZSB3aXRoIG1jdmVyc2lvbiA+PSAxLjEzIHJlcXVpcmVzIGphdmEgaW5zdGFsbGVkIG9uIHlvdXIgcGMuXG4gICAgICogQHBhcmFtIHZlcnNpb24gVGhlIGZvcmdlIHZlcnNpb24gbWV0YVxuICAgICAqL1xuICAgIGV4cG9ydCBmdW5jdGlvbiBpbnN0YWxsKHZlcnNpb246IFZlcnNpb25NZXRhLCBtaW5lY3JhZnQ6IE1pbmVjcmFmdExvY2F0aW9uLCBvcHRpb24/OiB7XG4gICAgICAgIG1hdmVuPzogc3RyaW5nLFxuICAgICAgICBqYXZhPzogSmF2YUV4ZWN1dG9yLFxuICAgIH0pIHtcbiAgICAgICAgcmV0dXJuIFRhc2suZXhlY3V0ZShpbnN0YWxsVGFzayh2ZXJzaW9uLCBtaW5lY3JhZnQsIG9wdGlvbikpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluc3RhbGwgZm9yZ2UgdG8gdGFyZ2V0IGxvY2F0aW9uLlxuICAgICAqIEluc3RhbGxhdGlvbiB0YXNrIGZvciBmb3JnZSB3aXRoIG1jdmVyc2lvbiA+PSAxLjEzIHJlcXVpcmVzIGphdmEgaW5zdGFsbGVkIG9uIHlvdXIgcGMuXG4gICAgICogQHBhcmFtIHZlcnNpb24gVGhlIGZvcmdlIHZlcnNpb24gbWV0YVxuICAgICAqL1xuICAgIGV4cG9ydCBmdW5jdGlvbiBpbnN0YWxsVGFzayh2ZXJzaW9uOiBWZXJzaW9uTWV0YSwgbWluZWNyYWZ0OiBNaW5lY3JhZnRMb2NhdGlvbiwgb3B0aW9uOiB7XG4gICAgICAgIG1hdmVuPzogc3RyaW5nLFxuICAgICAgICBqYXZhPzogSmF2YUV4ZWN1dG9yLFxuICAgIH0gJiBJbnN0YWxsZXIuTGlicmFyeU9wdGlvbiA9IHt9KTogVGFzazxzdHJpbmc+IHtcbiAgICAgICAgbGV0IGJ5SW5zdGFsbGVyID0gdHJ1ZTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IG1pbm9yVmVyc2lvbiA9IE51bWJlci5wYXJzZUludCh2ZXJzaW9uLm1jdmVyc2lvbi5zcGxpdChcIi5cIilbMV0sIDEwKTtcbiAgICAgICAgICAgIGJ5SW5zdGFsbGVyID0gbWlub3JWZXJzaW9uID49IDEzO1xuICAgICAgICB9IGNhdGNoIHsgfVxuICAgICAgICBjb25zdCB3b3JrID0gYnlJbnN0YWxsZXJcbiAgICAgICAgICAgID8gaW5zdGFsbEJ5SW5zdGFsbGVyVGFzayh2ZXJzaW9uLCBtaW5lY3JhZnQsIG9wdGlvbi5tYXZlbiB8fCBERUZBVUxUX0ZPUkdFX01BVkVOLCBvcHRpb24sIG9wdGlvbi5qYXZhIHx8IEphdmFFeGVjdXRvci5jcmVhdGVTaW1wbGUoXCJqYXZhXCIpKVxuICAgICAgICAgICAgOiBpbnN0YWxsQnlVbml2ZXJzYWxUYXNrKHZlcnNpb24sIG1pbmVjcmFmdCwgb3B0aW9uLm1hdmVuIHx8IERFRkFVTFRfRk9SR0VfTUFWRU4pO1xuICAgICAgICByZXR1cm4gd29yaztcbiAgICB9XG59XG5cbmV4cG9ydCAqIGZyb20gXCIuL2Zvcmdld2ViXCI7XG5cbmV4cG9ydCBkZWZhdWx0IEZvcmdlSW5zdGFsbGVyO1xuIl19
\No newline at end of file