semantifold 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/README.md +11 -5
  2. package/bin/semantifold.js +6 -0
  3. package/build/bin/semantifold.d.ts +3 -0
  4. package/build/bin/semantifold.d.ts.map +1 -0
  5. package/build/bin/semantifold.js +5 -0
  6. package/build/index.d.ts +9 -0
  7. package/build/index.d.ts.map +1 -1
  8. package/build/index.js +10 -1
  9. package/build/src/artifact-path.d.ts +16 -0
  10. package/build/src/artifact-path.d.ts.map +1 -1
  11. package/build/src/artifact-path.js +29 -3
  12. package/build/src/backends/c-check.d.ts +7 -0
  13. package/build/src/backends/c-check.d.ts.map +1 -0
  14. package/build/src/backends/c-check.js +65 -0
  15. package/build/src/backends/check-plan.d.ts +96 -0
  16. package/build/src/backends/check-plan.d.ts.map +1 -0
  17. package/build/src/backends/check-plan.js +135 -0
  18. package/build/src/backends/cpp-check.d.ts +7 -0
  19. package/build/src/backends/cpp-check.d.ts.map +1 -0
  20. package/build/src/backends/cpp-check.js +59 -0
  21. package/build/src/backends/csharp-check.d.ts +7 -0
  22. package/build/src/backends/csharp-check.d.ts.map +1 -0
  23. package/build/src/backends/csharp-check.js +125 -0
  24. package/build/src/backends/csharp.d.ts +1 -0
  25. package/build/src/backends/csharp.d.ts.map +1 -1
  26. package/build/src/backends/csharp.js +5 -4
  27. package/build/src/backends/dart-check.d.ts +7 -0
  28. package/build/src/backends/dart-check.d.ts.map +1 -0
  29. package/build/src/backends/dart-check.js +103 -0
  30. package/build/src/backends/dart.d.ts +2 -0
  31. package/build/src/backends/dart.d.ts.map +1 -1
  32. package/build/src/backends/dart.js +5 -5
  33. package/build/src/backends/go-check.d.ts +7 -0
  34. package/build/src/backends/go-check.d.ts.map +1 -0
  35. package/build/src/backends/go-check.js +77 -0
  36. package/build/src/backends/go.d.ts +1 -0
  37. package/build/src/backends/go.d.ts.map +1 -1
  38. package/build/src/backends/go.js +3 -3
  39. package/build/src/backends/java-check.d.ts +21 -0
  40. package/build/src/backends/java-check.d.ts.map +1 -0
  41. package/build/src/backends/java-check.js +73 -0
  42. package/build/src/backends/javascript-check.d.ts +7 -0
  43. package/build/src/backends/javascript-check.d.ts.map +1 -0
  44. package/build/src/backends/javascript-check.js +29 -0
  45. package/build/src/backends/kotlin-check.d.ts +7 -0
  46. package/build/src/backends/kotlin-check.d.ts.map +1 -0
  47. package/build/src/backends/kotlin-check.js +31 -0
  48. package/build/src/backends/php-check.d.ts +7 -0
  49. package/build/src/backends/php-check.d.ts.map +1 -0
  50. package/build/src/backends/php-check.js +21 -0
  51. package/build/src/backends/program.d.ts +7 -0
  52. package/build/src/backends/program.d.ts.map +1 -1
  53. package/build/src/backends/program.js +16 -1
  54. package/build/src/backends/python-check.d.ts +7 -0
  55. package/build/src/backends/python-check.d.ts.map +1 -0
  56. package/build/src/backends/python-check.js +28 -0
  57. package/build/src/backends/ruby-check.d.ts +7 -0
  58. package/build/src/backends/ruby-check.d.ts.map +1 -0
  59. package/build/src/backends/ruby-check.js +21 -0
  60. package/build/src/backends/rust-check.d.ts +7 -0
  61. package/build/src/backends/rust-check.d.ts.map +1 -0
  62. package/build/src/backends/rust-check.js +65 -0
  63. package/build/src/backends/swift-check.d.ts +7 -0
  64. package/build/src/backends/swift-check.d.ts.map +1 -0
  65. package/build/src/backends/swift-check.js +77 -0
  66. package/build/src/backends/typescript-check.d.ts +7 -0
  67. package/build/src/backends/typescript-check.d.ts.map +1 -0
  68. package/build/src/backends/typescript-check.js +33 -0
  69. package/build/src/backends/zig-check.d.ts +7 -0
  70. package/build/src/backends/zig-check.d.ts.map +1 -0
  71. package/build/src/backends/zig-check.js +70 -0
  72. package/build/src/diagnostic.d.ts +13 -1
  73. package/build/src/diagnostic.d.ts.map +1 -1
  74. package/build/src/diagnostic.js +14 -2
  75. package/build/src/frontends/program.d.ts +6 -0
  76. package/build/src/frontends/program.d.ts.map +1 -1
  77. package/build/src/frontends/program.js +9 -1
  78. package/build/src/language-registry.d.ts +54 -0
  79. package/build/src/language-registry.d.ts.map +1 -1
  80. package/build/src/language-registry.js +107 -5
  81. package/build/src/project-build.d.ts +172 -0
  82. package/build/src/project-build.d.ts.map +1 -0
  83. package/build/src/project-build.js +320 -0
  84. package/build/src/project-cli.d.ts +40 -0
  85. package/build/src/project-cli.d.ts.map +1 -0
  86. package/build/src/project-cli.js +145 -0
  87. package/build/src/project-manifest.d.ts +148 -0
  88. package/build/src/project-manifest.d.ts.map +1 -0
  89. package/build/src/project-manifest.js +432 -0
  90. package/build/src/project-reporter.d.ts +81 -0
  91. package/build/src/project-reporter.d.ts.map +1 -0
  92. package/build/src/project-reporter.js +293 -0
  93. package/build/src/project-snapshot.d.ts +129 -0
  94. package/build/src/project-snapshot.d.ts.map +1 -0
  95. package/build/src/project-snapshot.js +362 -0
  96. package/build/src/project-watch-reporter.d.ts +125 -0
  97. package/build/src/project-watch-reporter.d.ts.map +1 -0
  98. package/build/src/project-watch-reporter.js +280 -0
  99. package/build/src/project-watch.d.ts +133 -0
  100. package/build/src/project-watch.d.ts.map +1 -0
  101. package/build/src/project-watch.js +839 -0
  102. package/build/src/publication.d.ts +218 -0
  103. package/build/src/publication.d.ts.map +1 -0
  104. package/build/src/publication.js +1832 -0
  105. package/build/src/semantic/types.d.ts +613 -0
  106. package/build/src/semantic/types.d.ts.map +1 -1
  107. package/build/src/semantic/types.js +163 -1
  108. package/build/src/subprocess.d.ts +8 -0
  109. package/build/src/subprocess.d.ts.map +1 -1
  110. package/build/src/subprocess.js +50 -9
  111. package/build/src/target-check.d.ts +52 -0
  112. package/build/src/target-check.d.ts.map +1 -0
  113. package/build/src/target-check.js +796 -0
  114. package/build/src/toolchains.d.ts.map +1 -1
  115. package/build/src/toolchains.js +3 -3
  116. package/docs/architecture.md +3 -1
  117. package/docs/c.md +4 -0
  118. package/docs/cpp.md +4 -0
  119. package/docs/dart.md +4 -0
  120. package/docs/generated-artifact-publication.md +98 -0
  121. package/docs/kotlin.md +2 -2
  122. package/docs/language-support.md +29 -3
  123. package/docs/project-build-cli.md +147 -0
  124. package/docs/project-watch.md +60 -0
  125. package/docs/rust.md +4 -0
  126. package/docs/swift.md +2 -0
  127. package/docs/testing.md +70 -3
  128. package/docs/watch-build-pipeline.md +42 -26
  129. package/docs/zig.md +2 -0
  130. package/examples/jsdoc-java-watch/expected-output.txt +3 -0
  131. package/examples/jsdoc-java-watch/semantifold.json +23 -0
  132. package/examples/jsdoc-java-watch/src/main.js +21 -0
  133. package/index.js +9 -0
  134. package/package.json +6 -1
  135. package/src/artifact-path.js +31 -2
  136. package/src/backends/c-check.js +80 -0
  137. package/src/backends/check-plan.js +147 -0
  138. package/src/backends/cpp-check.js +73 -0
  139. package/src/backends/csharp-check.js +139 -0
  140. package/src/backends/csharp.js +4 -3
  141. package/src/backends/dart-check.js +117 -0
  142. package/src/backends/dart.js +4 -4
  143. package/src/backends/go-check.js +89 -0
  144. package/src/backends/go.js +2 -2
  145. package/src/backends/java-check.js +77 -0
  146. package/src/backends/javascript-check.js +33 -0
  147. package/src/backends/kotlin-check.js +41 -0
  148. package/src/backends/php-check.js +23 -0
  149. package/src/backends/program.js +17 -0
  150. package/src/backends/python-check.js +30 -0
  151. package/src/backends/ruby-check.js +23 -0
  152. package/src/backends/rust-check.js +78 -0
  153. package/src/backends/swift-check.js +89 -0
  154. package/src/backends/typescript-check.js +37 -0
  155. package/src/backends/zig-check.js +81 -0
  156. package/src/diagnostic.js +9 -1
  157. package/src/frontends/program.js +9 -0
  158. package/src/language-registry.js +113 -4
  159. package/src/project-build.js +353 -0
  160. package/src/project-cli.js +155 -0
  161. package/src/project-manifest.js +479 -0
  162. package/src/project-reporter.js +320 -0
  163. package/src/project-snapshot.js +403 -0
  164. package/src/project-watch-reporter.js +303 -0
  165. package/src/project-watch.js +870 -0
  166. package/src/publication.js +2071 -0
  167. package/src/semantic/types.js +184 -0
  168. package/src/subprocess.js +49 -8
  169. package/src/target-check.js +844 -0
  170. package/src/toolchains.js +3 -2
  171. package/tsconfig.json +1 -1
@@ -0,0 +1,1832 @@
1
+ // @ts-check
2
+ import { createHash, randomUUID } from "node:crypto";
3
+ import { constants } from "node:fs";
4
+ import { lstat, mkdir, open, readFile, readdir, realpath, rename, rm } from "node:fs/promises";
5
+ import path from "node:path";
6
+ import { findPortableArtifactPathConflict, isSafeArtifactPath } from "./artifact-path.js";
7
+ import { createGeneratedArtifactSet } from "./artifacts.js";
8
+ import { finalizeByteMapping } from "./binary-mapping.js";
9
+ import { SemantifoldDiagnostic } from "./diagnostic.js";
10
+ import { finalizeMapping, toSourceMapV3 } from "./mapping.js";
11
+ const activePointerName = "active-generation.json";
12
+ const generationsName = "generations";
13
+ const journalName = ".semantifold-publication-journal";
14
+ const identityPattern = /^[a-z][a-z0-9-]*$/u;
15
+ const generationPattern = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;
16
+ const buildRolePattern = /^[a-z][a-z0-9-]*$/u;
17
+ const mediaTypePattern = /^[A-Za-z0-9!#$&^_.+-]+\/[A-Za-z0-9!#$&^_.+-]+(?:;[\u0020-\u007e]+)?$/u;
18
+ const targetRoles = new Set(["application", "binary", "text"]);
19
+ const publicationBoundaries = new Set([
20
+ "after-stage",
21
+ "before-pointer-replace",
22
+ "after-pointer-replace",
23
+ "before-cleanup",
24
+ "before-journal-remove"
25
+ ]);
26
+ /** @type {WeakMap<GeneratedArtifactPublisher, {boundary: string, error: Error}>} */
27
+ const injectedPublicationFailures = new WeakMap();
28
+ /** @type {WeakMap<GeneratedArtifactPublisher, (operation: string) => void>} */
29
+ const publicationFilesystemObservers = new WeakMap();
30
+ /** @type {WeakMap<GeneratedArtifactPublisher, (() => Promise<void> | void)[]>} */
31
+ const publicationCommitGuards = new WeakMap();
32
+ /**
33
+ * Queues one internal caller-owned currentness guard for the publisher's next transaction.
34
+ * The guard runs after every validator closes and immediately before the active-pointer commit.
35
+ * This helper is intentionally not part of the package root API.
36
+ * @param {GeneratedArtifactPublisher} publisher - Publisher instance.
37
+ * @param {() => Promise<void> | void} guard - Exact pre-commit guard.
38
+ * @returns {void}
39
+ */
40
+ export function guardNextPublicationCommit(publisher, guard) {
41
+ if (!(publisher instanceof GeneratedArtifactPublisher) || typeof guard != "function") {
42
+ throw new TypeError("Invalid publication commit guard.");
43
+ }
44
+ const queued = publicationCommitGuards.get(publisher) ?? [];
45
+ queued.push(guard);
46
+ publicationCommitGuards.set(publisher, queued);
47
+ }
48
+ /**
49
+ * Installs one internal, one-shot deterministic failure used by real-filesystem interruption specs.
50
+ * This helper is intentionally not part of the package root API.
51
+ * @param {GeneratedArtifactPublisher} publisher - Publisher instance.
52
+ * @param {"after-stage" | "before-pointer-replace" | "after-pointer-replace" | "before-cleanup" | "before-journal-remove"} boundary - Exact lifecycle boundary.
53
+ * @param {Error} error - Injected failure.
54
+ * @returns {void}
55
+ */
56
+ export function injectPublicationFailure(publisher, boundary, error) {
57
+ if (!(publisher instanceof GeneratedArtifactPublisher) || !publicationBoundaries.has(boundary) || !(error instanceof Error)) {
58
+ throw new TypeError("Invalid publication failure injection.");
59
+ }
60
+ injectedPublicationFailures.set(publisher, { boundary, error });
61
+ }
62
+ /**
63
+ * Installs an internal deterministic filesystem-operation observer for durability specs.
64
+ * This helper is intentionally not part of the package root API.
65
+ * @param {GeneratedArtifactPublisher} publisher - Publisher instance.
66
+ * @param {(operation: string) => void} observer - Synchronous operation observer.
67
+ * @returns {void}
68
+ */
69
+ export function observePublicationFilesystem(publisher, observer) {
70
+ if (!(publisher instanceof GeneratedArtifactPublisher) || typeof observer != "function") {
71
+ throw new TypeError("Invalid publication filesystem observer.");
72
+ }
73
+ publicationFilesystemObservers.set(publisher, observer);
74
+ }
75
+ /**
76
+ * Owns transactional publication in one dedicated directory beneath a canonical project root.
77
+ */
78
+ export class GeneratedArtifactPublisher {
79
+ /** @type {string} */
80
+ #projectId;
81
+ /** @type {string} */
82
+ #projectRoot;
83
+ /** @type {string} */
84
+ #publicationRoot;
85
+ /** @type {readonly string[]} */
86
+ #sourceRoots;
87
+ /** @type {readonly string[]} */
88
+ #sourceFiles;
89
+ /** @type {Promise<void>} */
90
+ #publicationTail = Promise.resolve();
91
+ /**
92
+ * Creates a project-scoped publisher without touching the filesystem.
93
+ * @param {object} options - Publisher identity and owned paths.
94
+ * @param {string} options.projectId - Stable lowercase project identity.
95
+ * @param {string} options.projectRoot - Canonical absolute project root.
96
+ * @param {string} options.publicationRoot - Canonical absolute publisher-owned directory beneath the project root.
97
+ * @param {readonly string[]} [options.sourceRoots] - Canonical absolute project source directories kept disjoint from publication.
98
+ * @param {readonly string[]} [options.sourceFiles] - Canonical absolute project source files kept disjoint from publication.
99
+ */
100
+ constructor(options) {
101
+ if (!isPlainObject(options)) {
102
+ publicationFailure("INVALID_PUBLICATION_REQUEST", "publication", "Publisher options must be a plain object.");
103
+ }
104
+ const { projectId, projectRoot, publicationRoot, sourceFiles = [], sourceRoots = [] } = options;
105
+ if (!identityPattern.test(projectId ?? "")) {
106
+ publicationFailure("INVALID_PUBLICATION_REQUEST", "publication", "Project identity must be a stable lowercase ID.");
107
+ }
108
+ if (!isCanonicalAbsolutePath(projectRoot) || !isCanonicalAbsolutePath(publicationRoot) ||
109
+ !isStrictPathDescendant(projectRoot, publicationRoot)) {
110
+ publicationFailure("INVALID_PUBLICATION_ROOT", projectId, "Project and publication roots must be canonical absolute paths with publication strictly beneath the project root.");
111
+ }
112
+ if (!isDenseArray(sourceRoots) || !isDenseArray(sourceFiles) || sourceRoots.length + sourceFiles.length == 0) {
113
+ publicationFailure("INVALID_PUBLICATION_ROOT", projectId, "Publisher requires canonical absolute source directories or source files.");
114
+ }
115
+ /** @type {string[]} */
116
+ const validatedSourceRoots = [];
117
+ for (let index = 0; index < sourceRoots.length; index += 1) {
118
+ const sourceRoot = sourceRoots[index];
119
+ if (!isCanonicalAbsolutePath(sourceRoot)) {
120
+ publicationFailure("INVALID_PUBLICATION_ROOT", projectId, "Source roots must be a non-empty array of canonical absolute paths.");
121
+ }
122
+ if (!isPathWithin(projectRoot, sourceRoot)) {
123
+ publicationFailure("INVALID_PUBLICATION_ROOT", projectId, "Source roots must remain within the canonical project root.");
124
+ }
125
+ if (pathsOverlap(publicationRoot, sourceRoot)) {
126
+ publicationFailure("PUBLICATION_SOURCE_OVERLAP", projectId, "Publication root and source roots must be disjoint.");
127
+ }
128
+ validatedSourceRoots.push(sourceRoot);
129
+ }
130
+ /** @type {string[]} */
131
+ const validatedSourceFiles = [];
132
+ for (let index = 0; index < sourceFiles.length; index += 1) {
133
+ const sourceFile = sourceFiles[index];
134
+ if (!isCanonicalAbsolutePath(sourceFile) || !isPathWithin(projectRoot, sourceFile)) {
135
+ publicationFailure("INVALID_PUBLICATION_ROOT", projectId, "Source files must be canonical absolute paths within the project root.");
136
+ }
137
+ if (pathsOverlap(publicationRoot, sourceFile)) {
138
+ publicationFailure("PUBLICATION_SOURCE_OVERLAP", projectId, "Publication root and source files must be disjoint.");
139
+ }
140
+ validatedSourceFiles.push(sourceFile);
141
+ }
142
+ this.#projectId = projectId;
143
+ this.#projectRoot = projectRoot;
144
+ this.#publicationRoot = publicationRoot;
145
+ this.#sourceRoots = Object.freeze(validatedSourceRoots);
146
+ this.#sourceFiles = Object.freeze(validatedSourceFiles);
147
+ }
148
+ /**
149
+ * Stages, validates, and publishes one complete immutable project generation.
150
+ * Calls on one publisher instance are serialized in invocation order.
151
+ * @param {import("./semantic/types.js").PublicationRequest} request - Complete publication request.
152
+ * @param {import("./semantic/types.js").PublicationOptions} [options] - Transaction lifecycle controls.
153
+ * @returns {Promise<import("./semantic/types.js").PublishedGeneration>} Committed immutable snapshot.
154
+ */
155
+ publish(request, options = {}) {
156
+ const signal = validatePublicationOptions(options, this.#projectId);
157
+ const queuedGuards = publicationCommitGuards.get(this);
158
+ const commitGuard = queuedGuards?.shift();
159
+ if (queuedGuards?.length == 0)
160
+ publicationCommitGuards.delete(this);
161
+ /** @type {(value: import("./semantic/types.js").PublishedGeneration) => void} */
162
+ let resolveResult;
163
+ /** @type {(reason?: unknown) => void} */
164
+ let rejectResult;
165
+ const result = new Promise((resolve, reject) => {
166
+ resolveResult = resolve;
167
+ rejectResult = reject;
168
+ });
169
+ const operation = this.#publicationTail.then(async () => {
170
+ try {
171
+ resolveResult(await this.#publish(request, signal, commitGuard));
172
+ }
173
+ catch (error) {
174
+ rejectResult(error);
175
+ }
176
+ });
177
+ this.#publicationTail = operation.catch(() => { });
178
+ return result;
179
+ }
180
+ /**
181
+ * Resolves the active pointer exactly once and verifies the referenced immutable generation.
182
+ * @returns {Promise<import("./semantic/types.js").PublishedGeneration>} Verified pointer-once snapshot.
183
+ */
184
+ async resolveActive() {
185
+ await this.#prepareRoot();
186
+ const pointerPath = path.join(this.#publicationRoot, activePointerName);
187
+ const pointer = await readActivePointer(pointerPath, this.#projectId, false);
188
+ if (!pointer)
189
+ publicationFailure("ACTIVE_GENERATION_MISSING", this.#projectId, "No active generation has been published.");
190
+ const generation = await verifyPublishedGeneration(this.#publicationRoot, this.#projectId, pointer, false);
191
+ const cleanupPending = await hasCommittedCleanupJournal(this.#publicationRoot, this.#projectId, pointer.generationId);
192
+ return publishedGeneration(this.#publicationRoot, generation.manifest, cleanupPending);
193
+ }
194
+ /**
195
+ * Performs one serialized publication.
196
+ * @param {import("./semantic/types.js").PublicationRequest} request - Complete request.
197
+ * @param {AbortSignal | undefined} signal - Optional transaction cancellation authority.
198
+ * @param {(() => Promise<void> | void) | undefined} commitGuard - Optional currentness guard.
199
+ * @returns {Promise<import("./semantic/types.js").PublishedGeneration>} Publication result.
200
+ */
201
+ async #publish(request, signal, commitGuard) {
202
+ const validated = validatePublicationRequest(request, this.#projectId);
203
+ assertPublicationActive(signal, this.#projectId);
204
+ await this.#prepareRoot();
205
+ await reconcilePublication(this.#publicationRoot, this.#projectId, this);
206
+ await verifyAtomicReplacement(this.#publicationRoot, this.#projectId);
207
+ await validateExistingPointer(this.#publicationRoot, this.#projectId);
208
+ const generationPath = path.join(this.#publicationRoot, generationsName, validated.generationId);
209
+ const manifestPath = path.join(generationPath, "manifest.json");
210
+ const tempPointerName = `.active-generation.${validated.generationId}.tmp`;
211
+ const tempPointerPath = path.join(this.#publicationRoot, tempPointerName);
212
+ const journalPath = path.join(this.#publicationRoot, journalName, `${validated.generationId}.json`);
213
+ const retainedGeneration = await optionalStatus(generationPath, this.#projectId, "retained generation") !== null;
214
+ let committed = false;
215
+ let journalCreated = false;
216
+ let generationCreated = false;
217
+ let tempPointerCreated = false;
218
+ let failureCode = "PUBLICATION_STAGE_WRITE_FAILED";
219
+ /** @type {import("./semantic/types.js").GenerationManifest | null} */
220
+ let manifest = null;
221
+ /** @type {Buffer | null} */
222
+ let manifestBytes = null;
223
+ try {
224
+ await assertAbsent(tempPointerPath, "PUBLICATION_UNOWNED_CONFLICT", this.#projectId, "Temporary active pointer path is already owned or ambiguous.");
225
+ await assertAbsent(journalPath, "PUBLICATION_UNOWNED_CONFLICT", this.#projectId, "Publication journal identity is already owned or ambiguous.");
226
+ if (retainedGeneration) {
227
+ const retained = await verifyRetainedGeneration(generationPath, validated, this.#projectId);
228
+ manifest = retained.manifest;
229
+ manifestBytes = retained.manifestBytes;
230
+ }
231
+ const journal = retainedGeneration
232
+ ? {
233
+ generationId: validated.generationId,
234
+ operation: "reactivate",
235
+ projectId: this.#projectId,
236
+ schema: "SemantifoldPublicationJournal",
237
+ tempPointer: tempPointerName,
238
+ version: 2
239
+ }
240
+ : {
241
+ generationId: validated.generationId,
242
+ projectId: this.#projectId,
243
+ schema: "SemantifoldPublicationJournal",
244
+ tempPointer: tempPointerName,
245
+ version: 1
246
+ };
247
+ await writeSyncedFile(journalPath, serializeJson(journal), "wx");
248
+ journalCreated = true;
249
+ await syncDirectory(path.dirname(journalPath));
250
+ if (!retainedGeneration) {
251
+ await mkdir(generationPath, { mode: 0o700 });
252
+ generationCreated = true;
253
+ await syncDirectory(path.dirname(generationPath));
254
+ /** @type {import("./semantic/types.js").GenerationTargetManifest[]} */
255
+ const targetManifests = [];
256
+ for (const target of validated.targets) {
257
+ targetManifests.push(await stageTarget(generationPath, target, this.#projectId));
258
+ }
259
+ const manifestCandidate = /** @type {import("./semantic/types.js").GenerationManifest} */ ({
260
+ generationId: validated.generationId,
261
+ projectId: this.#projectId,
262
+ schema: /** @type {const} */ ("SemantifoldGenerationManifest"),
263
+ targets: targetManifests,
264
+ version: /** @type {const} */ (1)
265
+ });
266
+ manifestBytes = serializeJson(manifestCandidate);
267
+ manifest = validateGenerationManifest(JSON.parse(manifestBytes.toString("utf8")), this.#projectId, validated.generationId);
268
+ await writeSyncedFile(manifestPath, manifestBytes, "wx");
269
+ await syncTreeDirectories(generationPath);
270
+ await verifyManifestFiles(generationPath, manifest, this.#projectId);
271
+ }
272
+ if (manifest === null || manifestBytes === null) {
273
+ publicationFailure("PUBLICATION_STAGE_WRITE_FAILED", this.#projectId, "Candidate generation manifest could not be prepared.");
274
+ }
275
+ reachPublicationBoundary(this, "after-stage");
276
+ failureCode = "PUBLICATION_POINTER_FAILED";
277
+ const pointer = {
278
+ generationId: validated.generationId,
279
+ manifestHash: sha256(manifestBytes),
280
+ projectId: this.#projectId,
281
+ schema: "SemantifoldActiveGeneration",
282
+ version: 1
283
+ };
284
+ await writeSyncedFile(tempPointerPath, serializeJson(pointer), "wx", () => {
285
+ tempPointerCreated = true;
286
+ });
287
+ reachPublicationBoundary(this, "before-pointer-replace");
288
+ await commitGuard?.();
289
+ assertPublicationActive(signal, this.#projectId);
290
+ await rename(tempPointerPath, path.join(this.#publicationRoot, activePointerName));
291
+ tempPointerCreated = false;
292
+ committed = true;
293
+ reachPublicationBoundary(this, "after-pointer-replace");
294
+ await syncDirectory(this.#publicationRoot);
295
+ let cleanupPending = false;
296
+ try {
297
+ reachPublicationBoundary(this, "before-cleanup");
298
+ await removeJournalOwnedState({
299
+ journalPath,
300
+ projectId: this.#projectId,
301
+ publicationRoot: this.#publicationRoot,
302
+ publisher: this
303
+ });
304
+ }
305
+ catch (_error) {
306
+ cleanupPending = true;
307
+ }
308
+ return publishedGeneration(this.#publicationRoot, deepFreeze(manifest), cleanupPending);
309
+ }
310
+ catch (error) {
311
+ if (!committed) {
312
+ try {
313
+ await removeJournalOwnedState({
314
+ ...(generationCreated ? { candidatePath: generationPath } : {}),
315
+ ...(journalCreated ? { journalPath } : {}),
316
+ projectId: this.#projectId,
317
+ publicationRoot: this.#publicationRoot,
318
+ publisher: this,
319
+ ...(tempPointerCreated ? { temporaryPointerPath: tempPointerPath } : {})
320
+ });
321
+ }
322
+ catch (cleanupError) {
323
+ if (cleanupError instanceof SemantifoldDiagnostic)
324
+ throw cleanupError;
325
+ publicationFailure("PUBLICATION_RECOVERY_FAILED", this.#projectId, "Failed publication left state that requires recovery.", cleanupError);
326
+ }
327
+ }
328
+ if (error instanceof SemantifoldDiagnostic)
329
+ throw error;
330
+ publicationFailure(failureCode, this.#projectId, committed
331
+ ? "Active generation changed, but durable pointer publication did not complete."
332
+ : "Candidate generation could not be staged.", error);
333
+ }
334
+ }
335
+ /**
336
+ * Creates and validates owned root directories and source-root separation.
337
+ * @returns {Promise<void>} Completion.
338
+ */
339
+ async #prepareRoot() {
340
+ await ensureDirectoryWithoutSymlinks(this.#projectRoot, false, this.#projectId);
341
+ await ensureDirectoryWithoutSymlinks(this.#publicationRoot, true, this.#projectId);
342
+ let exactProject;
343
+ let exactPublication;
344
+ try {
345
+ exactProject = await realpath(this.#projectRoot);
346
+ exactPublication = await realpath(this.#publicationRoot);
347
+ }
348
+ catch (error) {
349
+ publicationFailure("INVALID_PUBLICATION_ROOT", this.#projectId, "Publication root could not be resolved safely.", error);
350
+ }
351
+ if (!isStrictPathDescendant(exactProject, exactPublication)) {
352
+ publicationFailure("INVALID_PUBLICATION_ROOT", this.#projectId, "Publication root must resolve strictly beneath the project root.");
353
+ }
354
+ for (const sourceRoot of this.#sourceRoots) {
355
+ await ensureDirectoryWithoutSymlinks(sourceRoot, false, this.#projectId);
356
+ let exactSource;
357
+ try {
358
+ exactSource = await realpath(sourceRoot);
359
+ }
360
+ catch (error) {
361
+ publicationFailure("INVALID_PUBLICATION_ROOT", this.#projectId, "Source root could not be resolved safely.", error);
362
+ }
363
+ if (!isPathWithin(exactProject, exactSource)) {
364
+ publicationFailure("INVALID_PUBLICATION_ROOT", this.#projectId, "Source roots must resolve within the project root.");
365
+ }
366
+ if (pathsOverlap(exactPublication, exactSource)) {
367
+ publicationFailure("PUBLICATION_SOURCE_OVERLAP", this.#projectId, "Publication root and source roots resolve to overlapping paths.");
368
+ }
369
+ }
370
+ for (const sourceFile of this.#sourceFiles) {
371
+ await ensureDirectoryWithoutSymlinks(path.dirname(sourceFile), false, this.#projectId);
372
+ let status;
373
+ let exactSource;
374
+ try {
375
+ status = await lstat(sourceFile);
376
+ exactSource = await realpath(sourceFile);
377
+ }
378
+ catch (error) {
379
+ publicationFailure("INVALID_PUBLICATION_ROOT", this.#projectId, "Source file could not be resolved safely.", error);
380
+ }
381
+ if (status.isSymbolicLink()) {
382
+ publicationFailure("PUBLICATION_SYMLINK_TRAVERSAL", this.#projectId, "Source file traversal encountered a symbolic link.");
383
+ }
384
+ if (!status.isFile() || exactSource != sourceFile || !isPathWithin(exactProject, exactSource)) {
385
+ publicationFailure("INVALID_PUBLICATION_ROOT", this.#projectId, "Source files must resolve to real regular files within the project root.");
386
+ }
387
+ if (pathsOverlap(exactPublication, exactSource)) {
388
+ publicationFailure("PUBLICATION_SOURCE_OVERLAP", this.#projectId, "Publication root and source files resolve to overlapping paths.");
389
+ }
390
+ }
391
+ await ensureOwnedDirectory(path.join(this.#publicationRoot, generationsName), this.#projectId);
392
+ await ensureOwnedDirectory(path.join(this.#publicationRoot, journalName), this.#projectId);
393
+ }
394
+ }
395
+ /**
396
+ * Validates and snapshots transaction lifecycle controls before publication is queued.
397
+ * @param {unknown} options - Candidate options.
398
+ * @param {string} projectId - Project diagnostic identity.
399
+ * @returns {AbortSignal | undefined} Optional cancellation signal.
400
+ */
401
+ function validatePublicationOptions(options, projectId) {
402
+ if (!isPlainObject(options) || Object.keys(options).some(key => key != "signal") ||
403
+ options.signal !== undefined && !(options.signal instanceof AbortSignal)) {
404
+ publicationFailure("INVALID_PUBLICATION_REQUEST", projectId, "Publication options require only an optional AbortSignal.");
405
+ }
406
+ return /** @type {AbortSignal | undefined} */ (options.signal);
407
+ }
408
+ /**
409
+ * Rejects cancellation before the atomic active-pointer commit begins.
410
+ * @param {AbortSignal | undefined} signal - Optional transaction cancellation authority.
411
+ * @param {string} projectId - Project diagnostic identity.
412
+ * @returns {void}
413
+ */
414
+ function assertPublicationActive(signal, projectId) {
415
+ if (signal?.aborted) {
416
+ publicationFailure("PUBLICATION_CANCELLED", projectId, "Publication was cancelled before the active generation pointer commit.");
417
+ }
418
+ }
419
+ /**
420
+ * Throws and consumes a configured internal failure at an exact lifecycle boundary.
421
+ * @param {GeneratedArtifactPublisher} publisher - Active publisher.
422
+ * @param {string} boundary - Reached boundary.
423
+ * @returns {void}
424
+ */
425
+ function reachPublicationBoundary(publisher, boundary) {
426
+ const injection = injectedPublicationFailures.get(publisher);
427
+ if (injection?.boundary == boundary) {
428
+ injectedPublicationFailures.delete(publisher);
429
+ throw injection.error;
430
+ }
431
+ }
432
+ /**
433
+ * Reports one completed filesystem operation to the internal deterministic seam.
434
+ * @param {GeneratedArtifactPublisher} publisher - Active publisher.
435
+ * @param {string} operation - Completed operation.
436
+ * @returns {void}
437
+ */
438
+ function observePublicationFilesystemOperation(publisher, operation) {
439
+ publicationFilesystemObservers.get(publisher)?.(operation);
440
+ }
441
+ /**
442
+ * Reconciles only candidates and temporary pointers whose ownership is proven by a strict journal.
443
+ * The active pointer remains the sole commit authority.
444
+ * @param {string} publicationRoot - Publication root.
445
+ * @param {string} projectId - Project identity.
446
+ * @param {GeneratedArtifactPublisher} publisher - Active publisher.
447
+ * @returns {Promise<void>} Completion.
448
+ */
449
+ async function reconcilePublication(publicationRoot, projectId, publisher) {
450
+ const journals = await readPublicationJournals(publicationRoot, projectId);
451
+ if (journals.length == 0)
452
+ return;
453
+ const pointer = await readActivePointer(path.join(publicationRoot, activePointerName), projectId, true);
454
+ if (pointer)
455
+ await verifyPublishedGeneration(publicationRoot, projectId, pointer, true);
456
+ for (const { journal, journalPath } of journals) {
457
+ const candidatePath = ownedPath(path.join(publicationRoot, generationsName), journal.generationId, projectId);
458
+ const temporaryPointerPath = path.join(publicationRoot, journal.tempPointer);
459
+ const committed = pointer?.generationId == journal.generationId;
460
+ const candidateOwned = journal.version == 1;
461
+ if (candidateOwned && !committed) {
462
+ const candidateStatus = await optionalStatus(candidatePath, projectId, "candidate generation");
463
+ if (candidateStatus) {
464
+ if (!candidateStatus.isDirectory() || candidateStatus.isSymbolicLink()) {
465
+ publicationFailure("PUBLICATION_RECOVERY_FAILED", projectId, "Journal-owned candidate is not a real directory.");
466
+ }
467
+ }
468
+ }
469
+ const temporaryStatus = await optionalStatus(temporaryPointerPath, projectId, "temporary pointer");
470
+ if (temporaryStatus) {
471
+ if (!temporaryStatus.isFile() || temporaryStatus.isSymbolicLink()) {
472
+ publicationFailure("PUBLICATION_RECOVERY_FAILED", projectId, "Journal-owned temporary pointer is not a regular file.");
473
+ }
474
+ }
475
+ await removeJournalOwnedState({
476
+ ...(candidateOwned && !committed ? { candidatePath } : {}),
477
+ journalPath,
478
+ projectId,
479
+ publicationRoot,
480
+ publisher,
481
+ temporaryPointerPath
482
+ });
483
+ }
484
+ }
485
+ /**
486
+ * Reads and validates every recovery journal without changing publication state.
487
+ * @param {string} publicationRoot - Publication root.
488
+ * @param {string} projectId - Project identity.
489
+ * @returns {Promise<readonly {journal: PublicationJournal, journalPath: string}[]>} Ordered journals.
490
+ */
491
+ async function readPublicationJournals(publicationRoot, projectId) {
492
+ const journalDirectory = path.join(publicationRoot, journalName);
493
+ let entries;
494
+ try {
495
+ entries = await readdir(journalDirectory);
496
+ }
497
+ catch (error) {
498
+ publicationFailure("PUBLICATION_RECOVERY_FAILED", projectId, "Publication journal directory could not be inspected.", error);
499
+ }
500
+ entries.sort(compareStrings);
501
+ /** @type {{journal: PublicationJournal, journalPath: string}[]} */
502
+ const journals = [];
503
+ for (const entry of entries) {
504
+ if (!entry.endsWith(".json") || !generationPattern.test(entry.slice(0, -5))) {
505
+ publicationFailure("PUBLICATION_RECOVERY_FAILED", projectId, "Publication journal contains an unrecognized entry.");
506
+ }
507
+ const journalPath = path.join(journalDirectory, entry);
508
+ let journal;
509
+ try {
510
+ const status = await lstat(journalPath);
511
+ if (!status.isFile() || status.isSymbolicLink()) {
512
+ publicationFailure("PUBLICATION_RECOVERY_FAILED", projectId, "Publication journal entry must be a regular file.");
513
+ }
514
+ journal = JSON.parse(await readFile(journalPath, "utf8"));
515
+ }
516
+ catch (error) {
517
+ if (error instanceof SemantifoldDiagnostic)
518
+ throw error;
519
+ publicationFailure("PUBLICATION_RECOVERY_FAILED", projectId, "Publication journal entry is not valid JSON.", error);
520
+ }
521
+ if (!isPublicationJournal(journal) || journal.projectId != projectId || `${journal.generationId}.json` != entry) {
522
+ publicationFailure("PUBLICATION_RECOVERY_FAILED", projectId, "Publication journal entry does not match the versioned project contract.");
523
+ }
524
+ journals.push({ journal, journalPath });
525
+ }
526
+ return Object.freeze(journals);
527
+ }
528
+ /**
529
+ * Reports committed cleanup state while failing closed on every journal entry.
530
+ * @param {string} publicationRoot - Publication root.
531
+ * @param {string} projectId - Project identity.
532
+ * @param {string} generationId - Pointer-selected generation identity.
533
+ * @returns {Promise<boolean>} Whether committed cleanup remains.
534
+ */
535
+ async function hasCommittedCleanupJournal(publicationRoot, projectId, generationId) {
536
+ const journals = await readPublicationJournals(publicationRoot, projectId);
537
+ return journals.some(({ journal }) => journal.generationId == generationId);
538
+ }
539
+ /**
540
+ * Removes proven journal-owned state and durably synchronizes each parent before discarding its ownership proof.
541
+ * @param {object} options - Exact cleanup state.
542
+ * @param {string} [options.candidatePath] - Proven candidate generation path.
543
+ * @param {string} [options.temporaryPointerPath] - Proven temporary pointer path.
544
+ * @param {string} [options.journalPath] - Ownership journal path.
545
+ * @param {string} options.projectId - Project identity.
546
+ * @param {string} options.publicationRoot - Publication root.
547
+ * @param {GeneratedArtifactPublisher} options.publisher - Active publisher.
548
+ * @returns {Promise<void>} Completion.
549
+ */
550
+ async function removeJournalOwnedState({ candidatePath, journalPath, projectId, publicationRoot, publisher, temporaryPointerPath }) {
551
+ try {
552
+ if (candidatePath) {
553
+ await rm(candidatePath, { force: true, recursive: true });
554
+ observePublicationFilesystemOperation(publisher, "remove-candidate");
555
+ await syncDirectory(path.join(publicationRoot, generationsName));
556
+ observePublicationFilesystemOperation(publisher, "sync-candidate-parent");
557
+ }
558
+ if (temporaryPointerPath) {
559
+ await rm(temporaryPointerPath, { force: true });
560
+ observePublicationFilesystemOperation(publisher, "remove-temporary-pointer");
561
+ await syncDirectory(publicationRoot);
562
+ observePublicationFilesystemOperation(publisher, "sync-temporary-pointer-parent");
563
+ }
564
+ if (journalPath) {
565
+ reachPublicationBoundary(publisher, "before-journal-remove");
566
+ await rm(journalPath);
567
+ observePublicationFilesystemOperation(publisher, "remove-journal");
568
+ await syncDirectory(path.dirname(journalPath));
569
+ observePublicationFilesystemOperation(publisher, "sync-journal-parent");
570
+ }
571
+ }
572
+ catch (error) {
573
+ if (error instanceof SemantifoldDiagnostic)
574
+ throw error;
575
+ publicationFailure("PUBLICATION_RECOVERY_FAILED", projectId, "Journal-owned publication state could not be durably reconciled.", error);
576
+ }
577
+ }
578
+ /**
579
+ * Reads optional metadata without following symbolic links.
580
+ * @param {string} filename - Exact owned path.
581
+ * @param {string} projectId - Project identity.
582
+ * @param {string} subject - Stable subject description.
583
+ * @returns {Promise<import("node:fs").Stats | null>} Status or absence.
584
+ */
585
+ async function optionalStatus(filename, projectId, subject) {
586
+ try {
587
+ return await lstat(filename);
588
+ }
589
+ catch (error) {
590
+ if (isErrorCode(error, "ENOENT"))
591
+ return null;
592
+ publicationFailure("PUBLICATION_RECOVERY_FAILED", projectId, `Journal-owned ${subject} could not be inspected.`, error);
593
+ }
594
+ }
595
+ /**
596
+ * Validates and snapshots one publication request before staging.
597
+ * @param {unknown} request - Request candidate.
598
+ * @param {string} projectId - Project diagnostic identity.
599
+ * @returns {ValidatedPublicationRequest} Validated request.
600
+ */
601
+ function validatePublicationRequest(request, projectId) {
602
+ if (!isPlainObject(request)) {
603
+ publicationFailure("INVALID_PUBLICATION_REQUEST", projectId, "Publication requires a unique generation ID and a non-empty ordered target array.");
604
+ }
605
+ const generationId = request.generationId;
606
+ const requestedTargets = request.targets;
607
+ if (typeof generationId != "string" || !generationPattern.test(generationId) ||
608
+ !isDenseArray(requestedTargets) || requestedTargets.length == 0) {
609
+ publicationFailure("INVALID_PUBLICATION_REQUEST", projectId, "Publication requires a unique generation ID and a non-empty ordered target array.");
610
+ }
611
+ /** @type {ValidatedPublicationTarget[]} */
612
+ const targets = [];
613
+ const targetIds = new Set();
614
+ /** @type {string[]} */
615
+ const projections = [];
616
+ /** @type {string[]} */
617
+ const completeArtifactPaths = [];
618
+ for (let index = 0; index < requestedTargets.length; index += 1) {
619
+ const target = requestedTargets[index];
620
+ if (!isPlainObject(target)) {
621
+ publicationFailure("INVALID_PUBLICATION_REQUEST", projectId, `Target ${index} requires a stable lowercase identity.`);
622
+ }
623
+ const targetId = target.id;
624
+ const role = target.role;
625
+ const sourceProjection = target.sourceProjection;
626
+ const buildProjection = target.buildProjection;
627
+ const artifactSetCandidate = target.artifactSet;
628
+ const validatorsCandidate = target.validators;
629
+ if (typeof targetId != "string" || !identityPattern.test(targetId)) {
630
+ publicationFailure("INVALID_PUBLICATION_REQUEST", projectId, `Target ${index} requires a stable lowercase identity.`);
631
+ }
632
+ if (typeof role != "string" || !targetRoles.has(role)) {
633
+ publicationFailure("INVALID_PUBLICATION_REQUEST", projectId, `Target '${targetId}' requires an explicit language-neutral role.`);
634
+ }
635
+ if (targetIds.has(targetId)) {
636
+ publicationFailure("PUBLICATION_PATH_COLLISION", projectId, `Duplicate target identity '${targetId}'.`);
637
+ }
638
+ targetIds.add(targetId);
639
+ if (!isSafeArtifactPath(sourceProjection) || !isSafeArtifactPath(buildProjection)) {
640
+ publicationFailure("INVALID_PUBLICATION_PROJECTION", projectId, `Target '${targetId}' requires canonical relative source and build projections.`);
641
+ }
642
+ projections.push(sourceProjection, buildProjection);
643
+ let artifactSet;
644
+ try {
645
+ artifactSet = createGeneratedArtifactSet(artifactSetCandidate);
646
+ }
647
+ catch (error) {
648
+ publicationFailure("INVALID_PUBLICATION_REQUEST", projectId, `Target '${targetId}' does not contain a valid generated artifact set.`, error);
649
+ }
650
+ const validators = validatorsCandidate === undefined ? [] : validatorsCandidate;
651
+ if (!isDenseArray(validators)) {
652
+ publicationFailure("INVALID_PUBLICATION_REQUEST", projectId, `Target '${targetId}' validators must be a dense function array.`);
653
+ }
654
+ /** @type {import("./semantic/types.js").PublicationValidator[]} */
655
+ const validatedValidators = [];
656
+ for (let validatorIndex = 0; validatorIndex < validators.length; validatorIndex += 1) {
657
+ const validator = validators[validatorIndex];
658
+ if (typeof validator != "function") {
659
+ publicationFailure("INVALID_PUBLICATION_REQUEST", projectId, `Target '${targetId}' validators must be a dense function array.`);
660
+ }
661
+ validatedValidators.push(/** @type {import("./semantic/types.js").PublicationValidator} */ (validator));
662
+ }
663
+ const artifactConflict = findPortableArtifactPathConflict(artifactSet.artifacts.map(({ path: artifactPath }) => artifactPath));
664
+ if (artifactConflict) {
665
+ publicationFailure("PUBLICATION_PATH_COLLISION", projectId, `Target '${targetId}' artifact paths have a portable ${artifactConflict.kind} conflict.`);
666
+ }
667
+ for (const artifact of artifactSet.artifacts) {
668
+ completeArtifactPaths.push(`${sourceProjection}/${artifact.path}`);
669
+ }
670
+ targets.push(Object.freeze({
671
+ artifactSet,
672
+ buildProjection,
673
+ id: targetId,
674
+ role: /** @type {import("./semantic/types.js").PublicationTargetRole} */ (role),
675
+ sourceProjection,
676
+ validators: Object.freeze(validatedValidators)
677
+ }));
678
+ }
679
+ const projectionConflict = findPortableArtifactPathConflict(projections);
680
+ if (projectionConflict) {
681
+ publicationFailure("PUBLICATION_PROJECTION_OVERLAP", projectId, "Target source/build projections must be distinct and non-nested under portable comparison.");
682
+ }
683
+ if (findPortableArtifactPathConflict([...projections, "manifest.json"])) {
684
+ publicationFailure("INVALID_PUBLICATION_PROJECTION", projectId, "Target source/build projections must not overlap the generation manifest path.");
685
+ }
686
+ const artifactConflict = findPortableArtifactPathConflict(completeArtifactPaths);
687
+ if (artifactConflict) {
688
+ publicationFailure("PUBLICATION_PATH_COLLISION", projectId, "Projected artifact paths collide under portable comparison.");
689
+ }
690
+ return { generationId, targets: Object.freeze(targets) };
691
+ }
692
+ /**
693
+ * Verifies that one retained immutable generation exactly represents a validator-free request.
694
+ * The retained directory is never modified or removed on either success or failure.
695
+ * @param {string} generationPath - Existing generation path.
696
+ * @param {ValidatedPublicationRequest} request - Validated candidate request.
697
+ * @param {string} projectId - Project diagnostic identity.
698
+ * @returns {Promise<{manifest: import("./semantic/types.js").GenerationManifest, manifestBytes: Buffer}>} Exact retained manifest.
699
+ */
700
+ async function verifyRetainedGeneration(generationPath, request, projectId) {
701
+ if (request.targets.some(target => target.validators.length != 0)) {
702
+ publicationFailure("PUBLICATION_UNOWNED_CONFLICT", projectId, "Retained generations can be reactivated only for exact validator-free candidates.");
703
+ }
704
+ const targetManifests = request.targets.map(target => Object.freeze({
705
+ artifacts: Object.freeze(target.artifactSet.artifacts.map(artifact => describeGeneratedArtifact(artifact).manifest)),
706
+ buildArtifacts: Object.freeze([]),
707
+ id: target.id,
708
+ ...(target.artifactSet.metadata === undefined ? {} : { metadata: target.artifactSet.metadata }),
709
+ projections: Object.freeze({ build: target.buildProjection, source: target.sourceProjection }),
710
+ role: target.role,
711
+ target: target.artifactSet.target
712
+ }));
713
+ const candidate = {
714
+ generationId: request.generationId,
715
+ projectId,
716
+ schema: "SemantifoldGenerationManifest",
717
+ targets: targetManifests,
718
+ version: 1
719
+ };
720
+ const expectedBytes = serializeJson(candidate);
721
+ const manifest = validateGenerationManifest(JSON.parse(expectedBytes.toString("utf8")), projectId, request.generationId);
722
+ let manifestBytes;
723
+ try {
724
+ manifestBytes = await readAndSyncRegularFile(path.join(generationPath, "manifest.json"), projectId, "MALFORMED_GENERATION_MANIFEST", "Retained generation manifest must be a regular file.");
725
+ if (!manifestBytes.equals(expectedBytes)) {
726
+ publicationFailure("PUBLICATION_UNOWNED_CONFLICT", projectId, "Retained generation does not exactly match the requested candidate.");
727
+ }
728
+ await verifyManifestFiles(generationPath, manifest, projectId);
729
+ }
730
+ catch (error) {
731
+ if (error instanceof SemantifoldDiagnostic && error.code == "PUBLICATION_UNOWNED_CONFLICT")
732
+ throw error;
733
+ publicationFailure("PUBLICATION_UNOWNED_CONFLICT", projectId, "Retained generation could not be verified as the exact requested candidate.", error);
734
+ }
735
+ return { manifest, manifestBytes };
736
+ }
737
+ /**
738
+ * Stages one validated target and invokes its ordered validators.
739
+ * @param {string} generationPath - Candidate generation path.
740
+ * @param {ValidatedPublicationTarget} target - Validated target.
741
+ * @param {string} projectId - Project diagnostic identity.
742
+ * @returns {Promise<import("./semantic/types.js").GenerationTargetManifest>} Target manifest.
743
+ */
744
+ async function stageTarget(generationPath, target, projectId) {
745
+ const sourcePath = ownedPath(generationPath, target.sourceProjection, projectId);
746
+ const buildPath = ownedPath(generationPath, target.buildProjection, projectId);
747
+ await mkdir(sourcePath, { mode: 0o700, recursive: true });
748
+ await mkdir(buildPath, { mode: 0o700, recursive: true });
749
+ /** @type {import("./semantic/types.js").GenerationArtifactManifest[]} */
750
+ const artifacts = [];
751
+ for (const artifact of target.artifactSet.artifacts) {
752
+ const filename = ownedPath(sourcePath, artifact.path, projectId);
753
+ const described = describeGeneratedArtifact(artifact);
754
+ await mkdir(path.dirname(filename), { mode: 0o700, recursive: true });
755
+ try {
756
+ await writeSyncedFile(filename, described.bytes, "wx");
757
+ }
758
+ catch (error) {
759
+ if (error instanceof SemantifoldDiagnostic)
760
+ throw error;
761
+ publicationFailure("PUBLICATION_STAGE_WRITE_FAILED", projectId, `Generated artifact '${artifact.path}' could not be staged.`, error);
762
+ }
763
+ artifacts.push(described.manifest);
764
+ }
765
+ /** @type {import("./semantic/types.js").PublicationBuildArtifactInput[]} */
766
+ const buildDescriptors = [];
767
+ const context = Object.freeze({ buildPath, sourcePath, targetId: target.id });
768
+ for (let index = 0; index < target.validators.length; index += 1) {
769
+ let produced;
770
+ try {
771
+ produced = await target.validators[index](context);
772
+ }
773
+ catch (error) {
774
+ publicationFailure("PUBLICATION_VALIDATION_FAILED", projectId, `Validator ${index} failed for target '${target.id}'.`, error);
775
+ }
776
+ if (produced === undefined)
777
+ continue;
778
+ if (!isDenseArray(produced)) {
779
+ publicationFailure("PUBLICATION_VALIDATION_FAILED", projectId, `Validator ${index} returned invalid build-artifact metadata for target '${target.id}'.`);
780
+ }
781
+ for (const descriptor of produced) {
782
+ buildDescriptors.push(validateBuildArtifactDescriptor(descriptor, target.id, projectId));
783
+ }
784
+ }
785
+ const descriptorConflict = findPortableArtifactPathConflict(buildDescriptors.map(({ path: artifactPath }) => artifactPath));
786
+ if (descriptorConflict) {
787
+ publicationFailure("PUBLICATION_PATH_COLLISION", projectId, `Target '${target.id}' build artifacts have a portable ${descriptorConflict.kind} conflict.`);
788
+ }
789
+ const stagedBuildFiles = await listRegularFiles(buildPath, projectId);
790
+ const declared = new Set(buildDescriptors.map(({ path: artifactPath }) => artifactPath));
791
+ if (stagedBuildFiles.length != declared.size || stagedBuildFiles.some(filename => !declared.has(filename))) {
792
+ publicationFailure("PUBLICATION_VALIDATION_FAILED", projectId, `Target '${target.id}' validators must declare every staged build artifact exactly once.`);
793
+ }
794
+ /** @type {import("./semantic/types.js").GenerationBuildArtifactManifest[]} */
795
+ const finalizedBuildArtifacts = [];
796
+ for (const descriptor of buildDescriptors) {
797
+ const bytes = await readAndSyncRegularFile(ownedPath(buildPath, descriptor.path, projectId), projectId, "PUBLICATION_STAGE_HASH_MISMATCH", `Build artifact '${descriptor.path}' is not a stable regular file.`);
798
+ finalizedBuildArtifacts.push(Object.freeze({
799
+ byteLength: bytes.byteLength,
800
+ hash: Object.freeze({ algorithm: /** @type {const} */ ("sha256"), value: sha256(bytes) }),
801
+ mediaType: descriptor.mediaType,
802
+ path: descriptor.path,
803
+ role: descriptor.role
804
+ }));
805
+ }
806
+ return Object.freeze({
807
+ artifacts: Object.freeze(artifacts),
808
+ buildArtifacts: Object.freeze(finalizedBuildArtifacts),
809
+ id: target.id,
810
+ ...(target.artifactSet.metadata === undefined ? {} : { metadata: target.artifactSet.metadata }),
811
+ projections: Object.freeze({ build: target.buildProjection, source: target.sourceProjection }),
812
+ role: target.role,
813
+ target: target.artifactSet.target
814
+ });
815
+ }
816
+ /**
817
+ * Derives exact staged bytes and their deterministic generation-manifest record.
818
+ * @param {import("./semantic/types.js").GeneratedSetArtifact} artifact - Validated generated artifact.
819
+ * @returns {{bytes: Buffer, manifest: import("./semantic/types.js").GenerationArtifactManifest}} Bytes and manifest record.
820
+ */
821
+ function describeGeneratedArtifact(artifact) {
822
+ const bytes = artifact.contentKind == "text"
823
+ ? Buffer.from(/** @type {string} */ (artifact.content), "utf8")
824
+ : Buffer.from(/** @type {Uint8Array} */ (artifact.content));
825
+ return {
826
+ bytes,
827
+ manifest: Object.freeze({
828
+ byteLength: bytes.byteLength,
829
+ contentKind: artifact.contentKind,
830
+ hash: Object.freeze({ algorithm: /** @type {const} */ ("sha256"), value: sha256(bytes) }),
831
+ mediaType: artifact.mediaType,
832
+ path: artifact.path,
833
+ provenance: artifact.provenance,
834
+ role: artifact.role
835
+ })
836
+ };
837
+ }
838
+ /**
839
+ * Validates validator/compiler output metadata.
840
+ * @param {unknown} descriptor - Metadata candidate.
841
+ * @param {string} targetId - Target identity.
842
+ * @param {string} projectId - Project diagnostic identity.
843
+ * @returns {import("./semantic/types.js").PublicationBuildArtifactInput} Validated metadata.
844
+ */
845
+ function validateBuildArtifactDescriptor(descriptor, targetId, projectId) {
846
+ if (!isPlainObject(descriptor) || !hasExactKeys(descriptor, ["mediaType", "path", "role"])) {
847
+ publicationFailure("PUBLICATION_VALIDATION_FAILED", projectId, `Target '${targetId}' validator returned invalid build-artifact metadata.`);
848
+ }
849
+ const descriptorPath = descriptor.path;
850
+ const mediaType = descriptor.mediaType;
851
+ const role = descriptor.role;
852
+ if (!isSafeArtifactPath(descriptorPath) || typeof mediaType != "string" ||
853
+ !mediaTypePattern.test(mediaType) || /[\r\n]/u.test(mediaType) ||
854
+ typeof role != "string" || !buildRolePattern.test(role)) {
855
+ publicationFailure("PUBLICATION_VALIDATION_FAILED", projectId, `Target '${targetId}' validator returned invalid build-artifact metadata.`);
856
+ }
857
+ return Object.freeze({ mediaType, path: descriptorPath, role });
858
+ }
859
+ /**
860
+ * Verifies every manifest reference and staged byte before pointer reachability.
861
+ * @param {string} generationPath - Candidate generation path.
862
+ * @param {import("./semantic/types.js").GenerationManifest} manifest - Candidate manifest.
863
+ * @param {string} projectId - Project diagnostic identity.
864
+ * @returns {Promise<void>} Completion.
865
+ */
866
+ async function verifyManifestFiles(generationPath, manifest, projectId) {
867
+ for (const target of manifest.targets) {
868
+ const sourcePath = ownedPath(generationPath, target.projections.source, projectId);
869
+ const buildPath = ownedPath(generationPath, target.projections.build, projectId);
870
+ const sourceFiles = await listRegularFiles(sourcePath, projectId);
871
+ if (sourceFiles.length != target.artifacts.length ||
872
+ sourceFiles.some(filename => !target.artifacts.some(artifact => artifact.path == filename))) {
873
+ publicationFailure("PUBLICATION_STAGE_HASH_MISMATCH", projectId, `Target '${target.id}' generated-source files do not match its manifest.`);
874
+ }
875
+ for (const artifact of target.artifacts) {
876
+ await verifyManifestFile(sourcePath, artifact, projectId);
877
+ }
878
+ const buildFiles = await listRegularFiles(buildPath, projectId);
879
+ if (buildFiles.length != target.buildArtifacts.length ||
880
+ buildFiles.some(filename => !target.buildArtifacts.some(artifact => artifact.path == filename))) {
881
+ publicationFailure("PUBLICATION_STAGE_HASH_MISMATCH", projectId, `Target '${target.id}' build files do not match its manifest.`);
882
+ }
883
+ for (const artifact of target.buildArtifacts) {
884
+ await verifyManifestFile(buildPath, artifact, projectId);
885
+ }
886
+ try {
887
+ const artifacts = [];
888
+ for (const artifact of target.artifacts) {
889
+ const bytes = await readAndSyncRegularFile(ownedPath(sourcePath, artifact.path, projectId), projectId, "PUBLICATION_STAGE_HASH_MISMATCH", `Manifest artifact '${artifact.path}' is not a stable regular file.`);
890
+ let content;
891
+ if (artifact.contentKind == "text") {
892
+ try {
893
+ content = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
894
+ }
895
+ catch (error) {
896
+ publicationFailure("MALFORMED_GENERATION_MANIFEST", projectId, `Text artifact '${artifact.path}' is not valid UTF-8.`, error);
897
+ }
898
+ }
899
+ else
900
+ content = new Uint8Array(bytes);
901
+ artifacts.push({
902
+ content,
903
+ contentKind: artifact.contentKind,
904
+ mediaType: artifact.mediaType,
905
+ ownership: /** @type {const} */ ("generated"),
906
+ path: artifact.path,
907
+ provenance: rehydrateProvenance(artifact.provenance, projectId),
908
+ role: artifact.role
909
+ });
910
+ }
911
+ createGeneratedArtifactSet({
912
+ artifacts,
913
+ ...(target.metadata === undefined ? {} : { metadata: target.metadata }),
914
+ target: target.target
915
+ });
916
+ }
917
+ catch (error) {
918
+ if (error instanceof SemantifoldDiagnostic && error.code == "MALFORMED_GENERATION_MANIFEST")
919
+ throw error;
920
+ publicationFailure("MALFORMED_GENERATION_MANIFEST", projectId, `Target '${target.id}' artifact provenance does not match its staged bytes.`, error);
921
+ }
922
+ }
923
+ await verifyGenerationInventory(generationPath, manifest, projectId);
924
+ }
925
+ /**
926
+ * Restores JSON-omitted optional mapping fields and verifies persisted mapping projections.
927
+ * @param {import("./semantic/types.js").ArtifactProvenance} provenance - Persisted provenance.
928
+ * @param {string} projectId - Project identity.
929
+ * @returns {import("./semantic/types.js").ArtifactProvenance} Canonical provenance.
930
+ */
931
+ function rehydrateProvenance(provenance, projectId) {
932
+ if (provenance.kind == "text") {
933
+ const mapping = finalizeMapping(provenance.mapping);
934
+ const sourceMap = toSourceMapV3(mapping);
935
+ const jsonSourceMap = JSON.parse(JSON.stringify(sourceMap));
936
+ if (!sameJsonValue(jsonSourceMap, provenance.sourceMap)) {
937
+ publicationFailure("MALFORMED_GENERATION_MANIFEST", projectId, "Persisted Source Map projection contradicts its rich mapping.");
938
+ }
939
+ return Object.freeze({
940
+ kind: /** @type {const} */ ("text"),
941
+ mapping,
942
+ sourceMap,
943
+ ...(provenance.sourceMapFilename === undefined ? {} : { sourceMapFilename: provenance.sourceMapFilename })
944
+ });
945
+ }
946
+ if (provenance.kind == "bytes") {
947
+ return Object.freeze({ kind: /** @type {const} */ ("bytes"), mapping: finalizeByteMapping(provenance.mapping) });
948
+ }
949
+ return provenance;
950
+ }
951
+ /**
952
+ * Verifies one referenced file.
953
+ * @param {string} projectionPath - Owning projection path.
954
+ * @param {{byteLength: number, hash: import("./semantic/types.js").GenerationContentHash, path: string}} artifact - Manifest record.
955
+ * @param {string} projectId - Project diagnostic identity.
956
+ * @returns {Promise<Buffer>} Exact verified bytes.
957
+ */
958
+ async function verifyManifestFile(projectionPath, artifact, projectId) {
959
+ const bytes = await readAndSyncRegularFile(ownedPath(projectionPath, artifact.path, projectId), projectId, "PUBLICATION_STAGE_HASH_MISMATCH", `Manifest artifact '${artifact.path}' is not a stable regular file.`);
960
+ if (bytes.byteLength != artifact.byteLength || sha256(bytes) != artifact.hash.value) {
961
+ publicationFailure("PUBLICATION_STAGE_HASH_MISMATCH", projectId, `Manifest artifact '${artifact.path}' bytes do not match its recorded hash.`);
962
+ }
963
+ return bytes;
964
+ }
965
+ /**
966
+ * Validates an existing active pointer before a new candidate is staged.
967
+ * @param {string} publicationRoot - Publication root.
968
+ * @param {string} projectId - Project identity.
969
+ * @returns {Promise<void>} Completion.
970
+ */
971
+ async function validateExistingPointer(publicationRoot, projectId) {
972
+ const pointerPath = path.join(publicationRoot, activePointerName);
973
+ const pointer = await readActivePointer(pointerPath, projectId, true);
974
+ if (pointer)
975
+ await verifyPublishedGeneration(publicationRoot, projectId, pointer, false);
976
+ }
977
+ /**
978
+ * Reads and strictly validates one active pointer.
979
+ * @param {string} pointerPath - Pointer filename.
980
+ * @param {string} projectId - Expected project identity.
981
+ * @param {boolean} optional - Whether absence is allowed.
982
+ * @returns {Promise<ActivePointer | null>} Pointer or absent value.
983
+ */
984
+ async function readActivePointer(pointerPath, projectId, optional) {
985
+ let pointerBytes;
986
+ try {
987
+ const status = await lstat(pointerPath);
988
+ if (!status.isFile() || status.isSymbolicLink()) {
989
+ publicationFailure("MALFORMED_ACTIVE_GENERATION", projectId, "Active-generation pointer must be a regular file.");
990
+ }
991
+ pointerBytes = await readFile(pointerPath);
992
+ }
993
+ catch (error) {
994
+ if (optional && isErrorCode(error, "ENOENT"))
995
+ return null;
996
+ if (error instanceof SemantifoldDiagnostic)
997
+ throw error;
998
+ publicationFailure(optional ? "MALFORMED_ACTIVE_GENERATION" : "ACTIVE_GENERATION_MISSING", projectId, optional ? "Active-generation pointer could not be read." : "No active generation has been published.", error);
999
+ }
1000
+ let value;
1001
+ try {
1002
+ value = JSON.parse(pointerBytes.toString("utf8"));
1003
+ }
1004
+ catch (error) {
1005
+ publicationFailure("MALFORMED_ACTIVE_GENERATION", projectId, "Active-generation pointer is not valid JSON.", error);
1006
+ }
1007
+ if (!isActivePointer(value) || value.projectId != projectId) {
1008
+ publicationFailure("MALFORMED_ACTIVE_GENERATION", projectId, "Active-generation pointer does not match the versioned project contract.");
1009
+ }
1010
+ return value;
1011
+ }
1012
+ /**
1013
+ * Verifies a pointer-selected generation without consulting the pointer again.
1014
+ * @param {string} publicationRoot - Publication root.
1015
+ * @param {string} projectId - Project identity.
1016
+ * @param {ActivePointer} pointer - Pointer snapshot.
1017
+ * @param {boolean} cleanupPending - Recovery state.
1018
+ * @returns {Promise<import("./semantic/types.js").PublishedGeneration>} Verified generation.
1019
+ */
1020
+ async function verifyPublishedGeneration(publicationRoot, projectId, pointer, cleanupPending) {
1021
+ const generationPath = ownedPath(path.join(publicationRoot, generationsName), pointer.generationId, projectId);
1022
+ const manifestPath = path.join(generationPath, "manifest.json");
1023
+ let manifestBytes;
1024
+ try {
1025
+ manifestBytes = await readAndSyncRegularFile(manifestPath, projectId, "MALFORMED_GENERATION_MANIFEST", "Generation manifest must be a regular file.");
1026
+ }
1027
+ catch (error) {
1028
+ if (error instanceof SemantifoldDiagnostic)
1029
+ throw error;
1030
+ publicationFailure("MALFORMED_GENERATION_MANIFEST", projectId, "Generation manifest could not be read.", error);
1031
+ }
1032
+ if (sha256(manifestBytes) != pointer.manifestHash) {
1033
+ publicationFailure("MALFORMED_GENERATION_MANIFEST", projectId, "Generation manifest hash does not match the active pointer.");
1034
+ }
1035
+ let value;
1036
+ try {
1037
+ value = JSON.parse(manifestBytes.toString("utf8"));
1038
+ }
1039
+ catch (error) {
1040
+ publicationFailure("MALFORMED_GENERATION_MANIFEST", projectId, "Generation manifest is not valid JSON.", error);
1041
+ }
1042
+ const manifest = validateGenerationManifest(value, projectId, pointer.generationId);
1043
+ await verifyManifestFiles(generationPath, manifest, projectId);
1044
+ return publishedGeneration(publicationRoot, manifest, cleanupPending);
1045
+ }
1046
+ /**
1047
+ * Strictly validates a persisted generation manifest.
1048
+ * @param {unknown} value - Parsed manifest value.
1049
+ * @param {string} projectId - Expected project identity.
1050
+ * @param {string} generationId - Expected generation identity.
1051
+ * @returns {import("./semantic/types.js").GenerationManifest} Frozen manifest.
1052
+ */
1053
+ function validateGenerationManifest(value, projectId, generationId) {
1054
+ if (!isPlainObject(value) || !hasExactKeys(value, ["generationId", "projectId", "schema", "targets", "version"]) ||
1055
+ value.schema != "SemantifoldGenerationManifest" || value.version != 1 || value.projectId != projectId ||
1056
+ value.generationId != generationId || !isDenseArray(value.targets) || value.targets.length == 0) {
1057
+ publicationFailure("MALFORMED_GENERATION_MANIFEST", projectId, "Generation manifest does not match the versioned project contract.");
1058
+ }
1059
+ /** @type {import("./semantic/types.js").GenerationTargetManifest[]} */
1060
+ const targets = [];
1061
+ /** @type {string[]} */
1062
+ const projections = [];
1063
+ const ids = new Set();
1064
+ for (const target of value.targets) {
1065
+ const targetKeys = target && typeof target == "object" && "metadata" in target
1066
+ ? ["artifacts", "buildArtifacts", "id", "metadata", "projections", "role", "target"]
1067
+ : ["artifacts", "buildArtifacts", "id", "projections", "role", "target"];
1068
+ if (!isPlainObject(target) || !hasExactKeys(target, targetKeys) ||
1069
+ !identityPattern.test(typeof target.id == "string" ? target.id : "") || ids.has(target.id) ||
1070
+ typeof target.role != "string" || !targetRoles.has(target.role) ||
1071
+ typeof target.target != "string" || !identityPattern.test(target.target) ||
1072
+ !isPlainObject(target.projections) || !hasExactKeys(target.projections, ["build", "source"]) ||
1073
+ !isSafeArtifactPath(target.projections.source) || !isSafeArtifactPath(target.projections.build) ||
1074
+ !isDenseArray(target.artifacts) || target.artifacts.length == 0 || !isDenseArray(target.buildArtifacts)) {
1075
+ publicationFailure("MALFORMED_GENERATION_MANIFEST", projectId, "Generation manifest contains an invalid target record.");
1076
+ }
1077
+ const targetId = /** @type {string} */ (target.id);
1078
+ ids.add(targetId);
1079
+ projections.push(target.projections.source, target.projections.build);
1080
+ const artifacts = target.artifacts.map(artifact => validatePersistedArtifact(artifact, true, projectId));
1081
+ const buildArtifacts = target.buildArtifacts.map(artifact => validatePersistedArtifact(artifact, false, projectId));
1082
+ if (findPortableArtifactPathConflict(artifacts.map(({ path: artifactPath }) => artifactPath)) ||
1083
+ findPortableArtifactPathConflict(buildArtifacts.map(({ path: artifactPath }) => artifactPath))) {
1084
+ publicationFailure("MALFORMED_GENERATION_MANIFEST", projectId, "Generation manifest contains colliding artifact paths.");
1085
+ }
1086
+ targets.push(Object.freeze({
1087
+ artifacts: Object.freeze(/** @type {import("./semantic/types.js").GenerationArtifactManifest[]} */ (artifacts)),
1088
+ buildArtifacts: Object.freeze(/** @type {import("./semantic/types.js").GenerationBuildArtifactManifest[]} */ (buildArtifacts)),
1089
+ id: targetId,
1090
+ ...(target.metadata === undefined ? {} : { metadata: deepFreeze(/** @type {Record<string, unknown>} */ (target.metadata)) }),
1091
+ projections: Object.freeze({ build: target.projections.build, source: target.projections.source }),
1092
+ role: /** @type {import("./semantic/types.js").PublicationTargetRole} */ (target.role),
1093
+ target: target.target
1094
+ }));
1095
+ }
1096
+ if (findPortableArtifactPathConflict(projections) ||
1097
+ findPortableArtifactPathConflict([...projections, "manifest.json"])) {
1098
+ publicationFailure("MALFORMED_GENERATION_MANIFEST", projectId, "Generation manifest contains overlapping projections.");
1099
+ }
1100
+ return Object.freeze({
1101
+ generationId,
1102
+ projectId,
1103
+ schema: /** @type {const} */ ("SemantifoldGenerationManifest"),
1104
+ targets: Object.freeze(targets),
1105
+ version: /** @type {const} */ (1)
1106
+ });
1107
+ }
1108
+ /**
1109
+ * Validates one persisted artifact record.
1110
+ * @param {unknown} value - Record candidate.
1111
+ * @param {boolean} generated - Whether this is a generated-source artifact.
1112
+ * @param {string} projectId - Project identity.
1113
+ * @returns {import("./semantic/types.js").GenerationArtifactManifest | import("./semantic/types.js").GenerationBuildArtifactManifest} Frozen record.
1114
+ */
1115
+ function validatePersistedArtifact(value, generated, projectId) {
1116
+ const keys = generated
1117
+ ? ["byteLength", "contentKind", "hash", "mediaType", "path", "provenance", "role"]
1118
+ : ["byteLength", "hash", "mediaType", "path", "role"];
1119
+ if (!isPlainObject(value) || !hasExactKeys(value, keys) || !isSafeArtifactPath(value.path) ||
1120
+ typeof value.byteLength != "number" || !Number.isSafeInteger(value.byteLength) || value.byteLength < 0 || typeof value.mediaType != "string" ||
1121
+ !mediaTypePattern.test(value.mediaType) || typeof value.role != "string" ||
1122
+ !(generated ? ["entry", "source", "manifest", "support", "mapping", "resource", "loader"].includes(value.role) :
1123
+ buildRolePattern.test(value.role)) ||
1124
+ (generated && value.contentKind != "text" && value.contentKind != "binary") ||
1125
+ (generated && !isPlainObject(value.provenance)) ||
1126
+ !isPlainObject(value.hash) || !hasExactKeys(value.hash, ["algorithm", "value"]) || value.hash.algorithm != "sha256" ||
1127
+ typeof value.hash.value != "string" || !/^[a-f0-9]{64}$/u.test(value.hash.value)) {
1128
+ publicationFailure("MALFORMED_GENERATION_MANIFEST", projectId, "Generation manifest contains an invalid artifact record.");
1129
+ }
1130
+ return Object.freeze(/** @type {import("./semantic/types.js").GenerationArtifactManifest | import("./semantic/types.js").GenerationBuildArtifactManifest} */ ({
1131
+ byteLength: value.byteLength,
1132
+ ...(generated ? { contentKind: value.contentKind } : {}),
1133
+ hash: Object.freeze({ algorithm: /** @type {const} */ ("sha256"), value: value.hash.value }),
1134
+ mediaType: value.mediaType,
1135
+ path: value.path,
1136
+ ...(generated ? { provenance: deepFreeze(/** @type {import("./semantic/types.js").ArtifactProvenance} */ (value.provenance)) } : {}),
1137
+ role: value.role
1138
+ }));
1139
+ }
1140
+ /**
1141
+ * Constructs a frozen resolved-generation result.
1142
+ * @param {string} publicationRoot - Publication root.
1143
+ * @param {import("./semantic/types.js").GenerationManifest} manifest - Verified manifest.
1144
+ * @param {boolean} cleanupPending - Whether cleanup remains.
1145
+ * @returns {import("./semantic/types.js").PublishedGeneration} Frozen result.
1146
+ */
1147
+ function publishedGeneration(publicationRoot, manifest, cleanupPending) {
1148
+ const generationPath = path.join(publicationRoot, generationsName, manifest.generationId);
1149
+ const targets = manifest.targets.map(target => Object.freeze({
1150
+ buildPath: path.join(generationPath, target.projections.build),
1151
+ id: target.id,
1152
+ role: target.role,
1153
+ sourcePath: path.join(generationPath, target.projections.source)
1154
+ }));
1155
+ return Object.freeze({
1156
+ cleanupPending,
1157
+ generationId: manifest.generationId,
1158
+ generationPath,
1159
+ manifest,
1160
+ manifestPath: path.join(generationPath, "manifest.json"),
1161
+ targets: Object.freeze(targets)
1162
+ });
1163
+ }
1164
+ /**
1165
+ * Probes the exact same-directory regular-file replacement primitive used by the active pointer.
1166
+ * @param {string} publicationRoot - Publication root.
1167
+ * @param {string} projectId - Project identity.
1168
+ * @returns {Promise<void>} Completion.
1169
+ */
1170
+ async function verifyAtomicReplacement(publicationRoot, projectId) {
1171
+ const identity = randomUUID();
1172
+ const source = path.join(publicationRoot, `.semantifold-atomic-${identity}.source`);
1173
+ const destination = path.join(publicationRoot, `.semantifold-atomic-${identity}.destination`);
1174
+ const expected = Buffer.from("candidate\n");
1175
+ let sourceCreated = false;
1176
+ let destinationCreated = false;
1177
+ try {
1178
+ await writeSyncedFile(source, Buffer.from("candidate\n"), "wx");
1179
+ sourceCreated = true;
1180
+ await writeSyncedFile(destination, Buffer.from("previous\n"), "wx");
1181
+ destinationCreated = true;
1182
+ await rename(source, destination);
1183
+ sourceCreated = false;
1184
+ await syncDirectory(publicationRoot);
1185
+ const destinationStatus = await lstat(destination);
1186
+ const replaced = await readFile(destination);
1187
+ if (!destinationStatus.isFile() || destinationStatus.isSymbolicLink() || !replaced.equals(expected)) {
1188
+ publicationFailure("PUBLICATION_ATOMIC_REPLACE_UNSUPPORTED", projectId, "Filesystem did not provide same-directory regular-file replacement.");
1189
+ }
1190
+ try {
1191
+ await lstat(source);
1192
+ publicationFailure("PUBLICATION_ATOMIC_REPLACE_UNSUPPORTED", projectId, "Filesystem did not remove the replaced temporary name atomically.");
1193
+ }
1194
+ catch (error) {
1195
+ if (!isErrorCode(error, "ENOENT"))
1196
+ throw error;
1197
+ }
1198
+ }
1199
+ catch (error) {
1200
+ if (error instanceof SemantifoldDiagnostic)
1201
+ throw error;
1202
+ publicationFailure("PUBLICATION_ATOMIC_REPLACE_UNSUPPORTED", projectId, "Filesystem did not provide same-directory regular-file replacement.", error);
1203
+ }
1204
+ finally {
1205
+ await Promise.allSettled([
1206
+ ...(sourceCreated ? [rm(source, { force: true })] : []),
1207
+ ...(destinationCreated ? [rm(destination, { force: true })] : [])
1208
+ ]);
1209
+ }
1210
+ }
1211
+ /**
1212
+ * Writes and synchronizes one newly owned file.
1213
+ * @param {string} filename - Exact filename.
1214
+ * @param {Uint8Array} bytes - Exact bytes.
1215
+ * @param {"wx"} flag - Exclusive creation mode.
1216
+ * @param {() => void} [onCreated] - Called immediately after exclusive creation succeeds.
1217
+ * @returns {Promise<void>} Completion.
1218
+ */
1219
+ async function writeSyncedFile(filename, bytes, flag, onCreated) {
1220
+ const handle = await open(filename, flag, 0o600);
1221
+ onCreated?.();
1222
+ /** @type {unknown} */
1223
+ let failure;
1224
+ try {
1225
+ await handle.writeFile(bytes);
1226
+ await handle.sync();
1227
+ }
1228
+ catch (error) {
1229
+ failure = error;
1230
+ }
1231
+ finally {
1232
+ try {
1233
+ await handle.close();
1234
+ }
1235
+ catch (error) {
1236
+ if (failure === undefined)
1237
+ failure = error;
1238
+ }
1239
+ }
1240
+ if (failure !== undefined) {
1241
+ await rm(filename, { force: true }).catch(() => { });
1242
+ throw failure;
1243
+ }
1244
+ }
1245
+ /**
1246
+ * Reads and synchronizes one regular non-symlink file.
1247
+ * @param {string} filename - Exact filename.
1248
+ * @param {string} projectId - Project identity.
1249
+ * @param {string} code - Failure code.
1250
+ * @param {string} message - Stable failure detail.
1251
+ * @returns {Promise<Buffer>} Exact bytes.
1252
+ */
1253
+ async function readAndSyncRegularFile(filename, projectId, code, message) {
1254
+ try {
1255
+ const status = await lstat(filename);
1256
+ if (!status.isFile() || status.isSymbolicLink())
1257
+ publicationFailure(code, projectId, message);
1258
+ assertRegularFileImmutability(status, new Set(), projectId);
1259
+ const handle = await open(filename, constants.O_RDONLY);
1260
+ try {
1261
+ const bytes = await handle.readFile();
1262
+ await handle.sync();
1263
+ return bytes;
1264
+ }
1265
+ finally {
1266
+ await handle.close();
1267
+ }
1268
+ }
1269
+ catch (error) {
1270
+ if (error instanceof SemantifoldDiagnostic)
1271
+ throw error;
1272
+ publicationFailure(code, projectId, message, error);
1273
+ }
1274
+ }
1275
+ /**
1276
+ * Lists every regular file beneath one projection and rejects symlinks or special nodes.
1277
+ * @param {string} directory - Projection root.
1278
+ * @param {string} projectId - Project identity.
1279
+ * @returns {Promise<string[]>} Sorted relative POSIX paths.
1280
+ */
1281
+ async function listRegularFiles(directory, projectId) {
1282
+ /** @type {string[]} */
1283
+ const files = [];
1284
+ const identities = new Set();
1285
+ try {
1286
+ await visit(directory, "");
1287
+ }
1288
+ catch (error) {
1289
+ if (error instanceof SemantifoldDiagnostic)
1290
+ throw error;
1291
+ publicationFailure("PUBLICATION_GENERATION_VERIFICATION_FAILED", projectId, "Immutable generation filesystem inventory could not be verified.", error);
1292
+ }
1293
+ return files.sort(compareStrings);
1294
+ /**
1295
+ * Visits one owned directory.
1296
+ * @param {string} current - Exact directory.
1297
+ * @param {string} relative - Projection-relative path.
1298
+ * @returns {Promise<void>} Completion.
1299
+ */
1300
+ async function visit(current, relative) {
1301
+ await assertRealInventoryDirectory(current, projectId);
1302
+ const entries = await readdir(current);
1303
+ entries.sort(compareStrings);
1304
+ for (const entry of entries) {
1305
+ const childRelative = relative.length == 0 ? entry : `${relative}/${entry}`;
1306
+ if (!isSafeArtifactPath(childRelative)) {
1307
+ publicationFailure("INVALID_PUBLICATION_PROJECTION", projectId, "Validator output contains a non-canonical relative path.");
1308
+ }
1309
+ const child = path.join(current, entry);
1310
+ const status = await lstat(child);
1311
+ if (status.isSymbolicLink()) {
1312
+ publicationFailure("PUBLICATION_SYMLINK_TRAVERSAL", projectId, "Candidate generation contains a symbolic link.");
1313
+ }
1314
+ if (status.isDirectory())
1315
+ await visit(child, childRelative);
1316
+ else if (status.isFile()) {
1317
+ assertRegularFileImmutability(status, identities, projectId);
1318
+ files.push(childRelative);
1319
+ }
1320
+ else
1321
+ publicationFailure("PUBLICATION_GENERATION_INVENTORY_MISMATCH", projectId, "Immutable generation contains an undeclared filesystem entry.");
1322
+ }
1323
+ }
1324
+ }
1325
+ /**
1326
+ * Verifies that the manifest describes every directory and regular file in the immutable generation.
1327
+ * @param {string} generationPath - Exact generation root.
1328
+ * @param {import("./semantic/types.js").GenerationManifest} manifest - Verified manifest.
1329
+ * @param {string} projectId - Project identity.
1330
+ * @returns {Promise<void>} Completion.
1331
+ */
1332
+ async function verifyGenerationInventory(generationPath, manifest, projectId) {
1333
+ const expectedFiles = new Set(["manifest.json"]);
1334
+ const expectedDirectories = new Set();
1335
+ for (const target of manifest.targets) {
1336
+ addExpectedDirectory(target.projections.source);
1337
+ addExpectedDirectory(target.projections.build);
1338
+ for (const artifact of target.artifacts) {
1339
+ addExpectedFile(`${target.projections.source}/${artifact.path}`);
1340
+ }
1341
+ for (const artifact of target.buildArtifacts) {
1342
+ addExpectedFile(`${target.projections.build}/${artifact.path}`);
1343
+ }
1344
+ }
1345
+ /** @type {Set<string>} */
1346
+ const observedFiles = new Set();
1347
+ /** @type {Set<string>} */
1348
+ const observedDirectories = new Set();
1349
+ const identities = new Set();
1350
+ try {
1351
+ await visit(generationPath, "");
1352
+ }
1353
+ catch (error) {
1354
+ if (error instanceof SemantifoldDiagnostic)
1355
+ throw error;
1356
+ publicationFailure("PUBLICATION_GENERATION_VERIFICATION_FAILED", projectId, "Immutable generation filesystem inventory could not be verified.", error);
1357
+ }
1358
+ if (!sameStringSet(expectedFiles, observedFiles) || !sameStringSet(expectedDirectories, observedDirectories)) {
1359
+ publicationFailure("PUBLICATION_GENERATION_INVENTORY_MISMATCH", projectId, "Immutable generation contains an undeclared filesystem entry.");
1360
+ }
1361
+ /**
1362
+ * Adds one expected directory and each generation-relative parent.
1363
+ * @param {string} relative - POSIX-style generation-relative directory.
1364
+ * @returns {void}
1365
+ */
1366
+ function addExpectedDirectory(relative) {
1367
+ const parts = relative.split("/");
1368
+ for (let index = 1; index <= parts.length; index += 1) {
1369
+ expectedDirectories.add(parts.slice(0, index).join("/"));
1370
+ }
1371
+ }
1372
+ /**
1373
+ * Adds one expected regular file and its parent directories.
1374
+ * @param {string} relative - POSIX-style generation-relative filename.
1375
+ * @returns {void}
1376
+ */
1377
+ function addExpectedFile(relative) {
1378
+ expectedFiles.add(relative);
1379
+ const separator = relative.lastIndexOf("/");
1380
+ if (separator >= 0)
1381
+ addExpectedDirectory(relative.slice(0, separator));
1382
+ }
1383
+ /**
1384
+ * Visits every entry in one generation directory without following links.
1385
+ * @param {string} current - Exact directory.
1386
+ * @param {string} relative - Generation-relative directory.
1387
+ * @returns {Promise<void>} Completion.
1388
+ */
1389
+ async function visit(current, relative) {
1390
+ await assertRealInventoryDirectory(current, projectId);
1391
+ const entries = await readdir(current);
1392
+ entries.sort(compareStrings);
1393
+ for (const entry of entries) {
1394
+ const childRelative = relative.length == 0 ? entry : `${relative}/${entry}`;
1395
+ if (!isSafeArtifactPath(childRelative)) {
1396
+ publicationFailure("PUBLICATION_GENERATION_INVENTORY_MISMATCH", projectId, "Immutable generation contains an undeclared filesystem entry.");
1397
+ }
1398
+ const child = path.join(current, entry);
1399
+ const status = await lstat(child);
1400
+ if (status.isSymbolicLink()) {
1401
+ publicationFailure("PUBLICATION_SYMLINK_TRAVERSAL", projectId, "Candidate generation contains a symbolic link.");
1402
+ }
1403
+ if (status.isDirectory()) {
1404
+ observedDirectories.add(childRelative);
1405
+ await visit(child, childRelative);
1406
+ }
1407
+ else if (status.isFile()) {
1408
+ assertRegularFileImmutability(status, identities, projectId);
1409
+ observedFiles.add(childRelative);
1410
+ }
1411
+ else {
1412
+ publicationFailure("PUBLICATION_GENERATION_INVENTORY_MISMATCH", projectId, "Immutable generation contains an undeclared filesystem entry.");
1413
+ }
1414
+ }
1415
+ }
1416
+ }
1417
+ /**
1418
+ * Verifies one inventory traversal root without following symbolic links.
1419
+ * @param {string} directory - Exact directory about to be read.
1420
+ * @param {string} projectId - Project identity.
1421
+ * @returns {Promise<void>} Completion.
1422
+ */
1423
+ async function assertRealInventoryDirectory(directory, projectId) {
1424
+ const status = await lstat(directory);
1425
+ if (status.isSymbolicLink()) {
1426
+ publicationFailure("PUBLICATION_SYMLINK_TRAVERSAL", projectId, "Candidate generation contains a symbolic link.");
1427
+ }
1428
+ if (!status.isDirectory()) {
1429
+ publicationFailure("PUBLICATION_GENERATION_INVENTORY_MISMATCH", projectId, "Immutable generation contains an undeclared filesystem entry.");
1430
+ }
1431
+ }
1432
+ /**
1433
+ * Rejects external hard links and duplicate stable file identities.
1434
+ * @param {import("node:fs").Stats} status - Regular-file status.
1435
+ * @param {Set<string>} identities - Previously observed device/inode identities.
1436
+ * @param {string} projectId - Project identity.
1437
+ * @returns {void}
1438
+ */
1439
+ function assertRegularFileImmutability(status, identities, projectId) {
1440
+ if (status.nlink > 1) {
1441
+ publicationFailure("PUBLICATION_HARD_LINK", projectId, "Immutable generation files must not have external hard links.");
1442
+ }
1443
+ const identity = stableFileIdentity(status);
1444
+ if (identity !== null) {
1445
+ if (identities.has(identity)) {
1446
+ publicationFailure("PUBLICATION_HARD_LINK", projectId, "Immutable generation files must have unique filesystem identities.");
1447
+ }
1448
+ identities.add(identity);
1449
+ }
1450
+ }
1451
+ /**
1452
+ * Returns a stable device/inode identity only where the host reports one.
1453
+ * @param {import("node:fs").Stats} status - File status.
1454
+ * @returns {string | null} Identity or unavailable.
1455
+ */
1456
+ function stableFileIdentity(status) {
1457
+ if ((typeof status.dev != "number" && typeof status.dev != "bigint") ||
1458
+ (typeof status.ino != "number" && typeof status.ino != "bigint") || status.ino == 0)
1459
+ return null;
1460
+ return `${String(status.dev)}:${String(status.ino)}`;
1461
+ }
1462
+ /**
1463
+ * Compares two string sets exactly.
1464
+ * @param {Set<string>} left - First set.
1465
+ * @param {Set<string>} right - Second set.
1466
+ * @returns {boolean} Equality.
1467
+ */
1468
+ function sameStringSet(left, right) {
1469
+ return left.size == right.size && [...left].every(value => right.has(value));
1470
+ }
1471
+ /**
1472
+ * Synchronizes every directory in a staged tree from leaves to root.
1473
+ * @param {string} root - Tree root.
1474
+ * @returns {Promise<void>} Completion.
1475
+ */
1476
+ async function syncTreeDirectories(root) {
1477
+ const entries = await readdir(root, { withFileTypes: true });
1478
+ for (const entry of entries) {
1479
+ if (entry.isDirectory() && !entry.isSymbolicLink())
1480
+ await syncTreeDirectories(path.join(root, entry.name));
1481
+ }
1482
+ await syncDirectory(root);
1483
+ }
1484
+ /**
1485
+ * Synchronizes one directory entry set.
1486
+ * @param {string} directory - Directory path.
1487
+ * @returns {Promise<void>} Completion.
1488
+ */
1489
+ async function syncDirectory(directory) {
1490
+ const handle = await open(directory, constants.O_RDONLY);
1491
+ try {
1492
+ await handle.sync();
1493
+ }
1494
+ finally {
1495
+ await handle.close();
1496
+ }
1497
+ }
1498
+ /**
1499
+ * Ensures every existing path component is a real directory and optionally creates missing components.
1500
+ * @param {string} directory - Canonical absolute directory.
1501
+ * @param {boolean} create - Whether missing components may be created.
1502
+ * @param {string} projectId - Project identity.
1503
+ * @returns {Promise<void>} Completion.
1504
+ */
1505
+ async function ensureDirectoryWithoutSymlinks(directory, create, projectId) {
1506
+ const parsed = path.parse(directory);
1507
+ const relative = directory.slice(parsed.root.length);
1508
+ const parts = relative.split(path.sep).filter(Boolean);
1509
+ let current = parsed.root;
1510
+ for (const part of parts) {
1511
+ current = path.join(current, part);
1512
+ try {
1513
+ const status = await lstat(current);
1514
+ if (status.isSymbolicLink()) {
1515
+ publicationFailure("PUBLICATION_SYMLINK_TRAVERSAL", projectId, "Owned path traversal encountered a symbolic link.");
1516
+ }
1517
+ if (!status.isDirectory()) {
1518
+ publicationFailure("INVALID_PUBLICATION_ROOT", projectId, "Owned root path contains a non-directory component.");
1519
+ }
1520
+ }
1521
+ catch (error) {
1522
+ if (!isErrorCode(error, "ENOENT")) {
1523
+ if (error instanceof SemantifoldDiagnostic)
1524
+ throw error;
1525
+ publicationFailure("INVALID_PUBLICATION_ROOT", projectId, "Owned root path could not be validated.", error);
1526
+ }
1527
+ if (!create) {
1528
+ publicationFailure("INVALID_PUBLICATION_ROOT", projectId, "Source root must exist as a real directory.", error);
1529
+ }
1530
+ try {
1531
+ await mkdir(current, { mode: 0o700 });
1532
+ }
1533
+ catch (mkdirError) {
1534
+ publicationFailure("INVALID_PUBLICATION_ROOT", projectId, "Publication root could not be created safely.", mkdirError);
1535
+ }
1536
+ }
1537
+ }
1538
+ }
1539
+ /**
1540
+ * Ensures one reserved publisher directory is neither a symlink nor an unowned file.
1541
+ * @param {string} directory - Reserved directory.
1542
+ * @param {string} projectId - Project identity.
1543
+ * @returns {Promise<void>} Completion.
1544
+ */
1545
+ async function ensureOwnedDirectory(directory, projectId) {
1546
+ try {
1547
+ await mkdir(directory, { mode: 0o700 });
1548
+ }
1549
+ catch (error) {
1550
+ if (!isErrorCode(error, "EEXIST")) {
1551
+ publicationFailure("PUBLICATION_STAGE_WRITE_FAILED", projectId, "Publisher-owned directory could not be created.", error);
1552
+ }
1553
+ }
1554
+ let status;
1555
+ try {
1556
+ status = await lstat(directory);
1557
+ }
1558
+ catch (error) {
1559
+ publicationFailure("PUBLICATION_STAGE_WRITE_FAILED", projectId, "Reserved publisher path could not be inspected.", error);
1560
+ }
1561
+ if (!status.isDirectory() || status.isSymbolicLink()) {
1562
+ publicationFailure(status.isSymbolicLink() ? "PUBLICATION_SYMLINK_TRAVERSAL" : "PUBLICATION_UNOWNED_CONFLICT", projectId, "Reserved publisher path is not an owned real directory.");
1563
+ }
1564
+ }
1565
+ /**
1566
+ * Ensures an owned path has no pre-existing entry.
1567
+ * @param {string} filename - Exact path.
1568
+ * @param {string} code - Diagnostic code.
1569
+ * @param {string} projectId - Project identity.
1570
+ * @param {string} message - Stable failure detail.
1571
+ * @returns {Promise<void>} Completion.
1572
+ */
1573
+ async function assertAbsent(filename, code, projectId, message) {
1574
+ try {
1575
+ await lstat(filename);
1576
+ publicationFailure(code, projectId, message);
1577
+ }
1578
+ catch (error) {
1579
+ if (isErrorCode(error, "ENOENT"))
1580
+ return;
1581
+ if (error instanceof SemantifoldDiagnostic)
1582
+ throw error;
1583
+ publicationFailure(code, projectId, message, error);
1584
+ }
1585
+ }
1586
+ /**
1587
+ * Resolves a validated relative path under an owned root and rejects escape.
1588
+ * @param {string} root - Owned root.
1589
+ * @param {string} relative - Validated relative POSIX path.
1590
+ * @param {string} projectId - Project identity.
1591
+ * @returns {string} Exact owned path.
1592
+ */
1593
+ function ownedPath(root, relative, projectId) {
1594
+ const resolved = path.resolve(root, ...relative.split("/"));
1595
+ const child = path.relative(root, resolved);
1596
+ if (child.length == 0 || child == ".." || child.startsWith(`..${path.sep}`) || path.isAbsolute(child)) {
1597
+ publicationFailure("PUBLICATION_PATH_ESCAPE", projectId, "Resolved publication path escaped its owned root.");
1598
+ }
1599
+ return resolved;
1600
+ }
1601
+ /**
1602
+ * Checks a canonical non-root absolute path without filesystem access.
1603
+ * @param {unknown} value - Path candidate.
1604
+ * @returns {value is string} Whether the path is canonical.
1605
+ */
1606
+ function isCanonicalAbsolutePath(value) {
1607
+ return isCanonicalAbsolutePathForPath(value, path);
1608
+ }
1609
+ /**
1610
+ * Checks one absolute path using the supplied host path semantics.
1611
+ * This helper is intentionally not part of the package root API.
1612
+ * @param {unknown} value - Path candidate.
1613
+ * @param {typeof path.posix | typeof path.win32} hostPath - Host-native path implementation.
1614
+ * @returns {value is string} Whether the path is canonical for that host.
1615
+ */
1616
+ export function isCanonicalAbsolutePathForPath(value, hostPath) {
1617
+ const separatorAlias = hostPath.sep == "/" ? "\\" : "/";
1618
+ return typeof value == "string" && value.length > 0 && !value.includes("\0") && !value.includes(separatorAlias) &&
1619
+ hostPath.isAbsolute(value) && value != hostPath.parse(value).root && hostPath.normalize(value) == value &&
1620
+ hostPath.resolve(value) == value;
1621
+ }
1622
+ /**
1623
+ * Checks conservative portable overlap between absolute paths.
1624
+ * @param {string} left - First path.
1625
+ * @param {string} right - Second path.
1626
+ * @returns {boolean} Whether either contains the other.
1627
+ */
1628
+ function pathsOverlap(left, right) {
1629
+ const leftKey = left.toLowerCase();
1630
+ const rightKey = right.toLowerCase();
1631
+ return leftKey == rightKey || leftKey.startsWith(`${rightKey}${path.sep}`) || rightKey.startsWith(`${leftKey}${path.sep}`);
1632
+ }
1633
+ /**
1634
+ * Checks whether a path is equal to or nested beneath one canonical root.
1635
+ * @param {string} root - Canonical root.
1636
+ * @param {string} candidate - Canonical candidate.
1637
+ * @returns {boolean} Whether the candidate is within the root.
1638
+ */
1639
+ function isPathWithin(root, candidate) {
1640
+ const relative = path.relative(root, candidate);
1641
+ return relative.length == 0 || (relative != ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative));
1642
+ }
1643
+ /**
1644
+ * Checks whether a path is strictly nested beneath one canonical root.
1645
+ * @param {string} root - Canonical root.
1646
+ * @param {string} candidate - Canonical candidate.
1647
+ * @returns {boolean} Whether the candidate is a strict descendant.
1648
+ */
1649
+ function isStrictPathDescendant(root, candidate) {
1650
+ return isPathWithin(root, candidate) && path.relative(root, candidate).length > 0;
1651
+ }
1652
+ /**
1653
+ * Serializes stable generated JSON with one trailing LF.
1654
+ * @param {unknown} value - JSON value.
1655
+ * @returns {Buffer} UTF-8 bytes.
1656
+ */
1657
+ function serializeJson(value) {
1658
+ return Buffer.from(`${JSON.stringify(value, null, 2)}\n`, "utf8");
1659
+ }
1660
+ /**
1661
+ * Hashes exact bytes with SHA-256.
1662
+ * @param {Uint8Array} bytes - Exact bytes.
1663
+ * @returns {string} Lowercase hexadecimal hash.
1664
+ */
1665
+ function sha256(bytes) {
1666
+ return createHash("sha256").update(bytes).digest("hex");
1667
+ }
1668
+ /**
1669
+ * Deeply freezes a parsed JSON value.
1670
+ * @template T
1671
+ * @param {T} value - JSON value.
1672
+ * @returns {T} Frozen value.
1673
+ */
1674
+ function deepFreeze(value) {
1675
+ if (typeof value == "object" && value != null) {
1676
+ for (const child of Object.values(value))
1677
+ deepFreeze(child);
1678
+ Object.freeze(value);
1679
+ }
1680
+ return value;
1681
+ }
1682
+ /**
1683
+ * Compares detached JSON values without depending on object-key order.
1684
+ * @param {unknown} left - First JSON value.
1685
+ * @param {unknown} right - Second JSON value.
1686
+ * @returns {boolean} Whether the values are structurally equal.
1687
+ */
1688
+ function sameJsonValue(left, right) {
1689
+ if (left === right)
1690
+ return true;
1691
+ if (Array.isArray(left) || Array.isArray(right)) {
1692
+ return Array.isArray(left) && Array.isArray(right) && left.length == right.length &&
1693
+ left.every((entry, index) => sameJsonValue(entry, right[index]));
1694
+ }
1695
+ if (!isPlainObject(left) || !isPlainObject(right))
1696
+ return false;
1697
+ const leftKeys = Object.keys(left);
1698
+ const rightKeys = Object.keys(right);
1699
+ return leftKeys.length == rightKeys.length &&
1700
+ leftKeys.every(key => Object.hasOwn(right, key) && sameJsonValue(left[key], right[key]));
1701
+ }
1702
+ /**
1703
+ * Checks an active-pointer value.
1704
+ * @param {unknown} value - Parsed value.
1705
+ * @returns {value is ActivePointer} Whether the value is strict and versioned.
1706
+ */
1707
+ function isActivePointer(value) {
1708
+ return isPlainObject(value) && hasExactKeys(value, ["generationId", "manifestHash", "projectId", "schema", "version"]) &&
1709
+ value.schema == "SemantifoldActiveGeneration" && value.version == 1 &&
1710
+ typeof value.projectId == "string" && identityPattern.test(value.projectId) &&
1711
+ typeof value.generationId == "string" && generationPattern.test(value.generationId) &&
1712
+ typeof value.manifestHash == "string" && /^[a-f0-9]{64}$/u.test(value.manifestHash);
1713
+ }
1714
+ /**
1715
+ * Checks a recovery-journal value.
1716
+ * @param {unknown} value - Parsed value.
1717
+ * @returns {value is PublicationJournal} Whether the value is strict and versioned.
1718
+ */
1719
+ function isPublicationJournal(value) {
1720
+ if (!isPlainObject(value) || value.schema != "SemantifoldPublicationJournal" ||
1721
+ typeof value.projectId != "string" || !identityPattern.test(value.projectId) ||
1722
+ typeof value.generationId != "string" || !generationPattern.test(value.generationId) ||
1723
+ value.tempPointer != `.active-generation.${value.generationId}.tmp`)
1724
+ return false;
1725
+ return value.version == 1 && hasExactKeys(value, ["generationId", "projectId", "schema", "tempPointer", "version"]) ||
1726
+ value.version == 2 && value.operation == "reactivate" &&
1727
+ hasExactKeys(value, ["generationId", "operation", "projectId", "schema", "tempPointer", "version"]);
1728
+ }
1729
+ /**
1730
+ * Checks an ordinary object with exactly the expected enumerable string keys.
1731
+ * @param {Record<string, unknown>} value - Object candidate.
1732
+ * @param {readonly string[]} keys - Sorted expected keys.
1733
+ * @returns {boolean} Whether keys match exactly.
1734
+ */
1735
+ function hasExactKeys(value, keys) {
1736
+ const actual = Object.keys(value).sort(compareStrings);
1737
+ return actual.length == keys.length && actual.every((key, index) => key == keys[index]);
1738
+ }
1739
+ /**
1740
+ * Checks for an ordinary string-keyed object.
1741
+ * @param {unknown} value - Candidate value.
1742
+ * @returns {value is Record<string, unknown>} Whether the value is plain.
1743
+ */
1744
+ function isPlainObject(value) {
1745
+ return typeof value == "object" && value != null && !Array.isArray(value) && Object.getPrototypeOf(value) == Object.prototype;
1746
+ }
1747
+ /**
1748
+ * Checks for a dense ordinary array.
1749
+ * @param {unknown} value - Candidate value.
1750
+ * @returns {value is unknown[]} Whether the value is dense.
1751
+ */
1752
+ function isDenseArray(value) {
1753
+ if (!Array.isArray(value))
1754
+ return false;
1755
+ const indexedKeys = Object.keys(value).filter(key => /^(?:0|[1-9][0-9]*)$/u.test(key));
1756
+ return indexedKeys.length == value.length;
1757
+ }
1758
+ /**
1759
+ * Compares strings by Unicode code unit.
1760
+ * @param {string} left - First string.
1761
+ * @param {string} right - Second string.
1762
+ * @returns {number} Ordering.
1763
+ */
1764
+ function compareStrings(left, right) {
1765
+ return left < right ? -1 : left > right ? 1 : 0;
1766
+ }
1767
+ /**
1768
+ * Checks a narrowed filesystem error code.
1769
+ * @param {unknown} error - Opaque error.
1770
+ * @param {string} code - Expected code.
1771
+ * @returns {boolean} Whether the code matches.
1772
+ */
1773
+ function isErrorCode(error, code) {
1774
+ return error instanceof Error && "code" in error && error.code == code;
1775
+ }
1776
+ /**
1777
+ * Throws one stable publication diagnostic without embedding host paths or raw filesystem messages.
1778
+ * @param {string} code - Stable diagnostic code.
1779
+ * @param {string} projectId - Project identity.
1780
+ * @param {string} message - Stable detail.
1781
+ * @param {unknown} [error] - Preserved cause.
1782
+ * @returns {never} Always throws.
1783
+ */
1784
+ function publicationFailure(code, projectId, message, error) {
1785
+ throw new SemantifoldDiagnostic({
1786
+ cause: error instanceof Error ? error : undefined,
1787
+ code,
1788
+ language: projectId,
1789
+ message
1790
+ });
1791
+ }
1792
+ /**
1793
+ * @typedef ValidatedPublicationTarget
1794
+ * @property {string} id - Target identity.
1795
+ * @property {import("./semantic/types.js").GeneratedArtifactSet} artifactSet - Detached artifact set.
1796
+ * @property {string} sourceProjection - Source projection.
1797
+ * @property {string} buildProjection - Build projection.
1798
+ * @property {import("./semantic/types.js").PublicationTargetRole} role - Language-neutral target role.
1799
+ * @property {readonly import("./semantic/types.js").PublicationValidator[]} validators - Ordered validators.
1800
+ */
1801
+ /**
1802
+ * @typedef ValidatedPublicationRequest
1803
+ * @property {string} generationId - Snapshotted generation identity.
1804
+ * @property {readonly ValidatedPublicationTarget[]} targets - Snapshotted ordered targets.
1805
+ */
1806
+ /**
1807
+ * @typedef ActivePointer
1808
+ * @property {"SemantifoldActiveGeneration"} schema - Schema discriminator.
1809
+ * @property {1} version - Schema version.
1810
+ * @property {string} projectId - Project identity.
1811
+ * @property {string} generationId - Generation identity.
1812
+ * @property {string} manifestHash - SHA-256 generation-manifest hash.
1813
+ */
1814
+ /**
1815
+ * @typedef CandidatePublicationJournal
1816
+ * @property {"SemantifoldPublicationJournal"} schema - Schema discriminator.
1817
+ * @property {1} version - Schema version.
1818
+ * @property {string} projectId - Project identity.
1819
+ * @property {string} generationId - Candidate generation identity.
1820
+ * @property {string} tempPointer - Owned sibling temporary-pointer filename.
1821
+ */
1822
+ /**
1823
+ * @typedef ReactivationPublicationJournal
1824
+ * @property {"SemantifoldPublicationJournal"} schema - Schema discriminator.
1825
+ * @property {2} version - Schema version.
1826
+ * @property {"reactivate"} operation - Retained-generation activation without candidate ownership.
1827
+ * @property {string} projectId - Project identity.
1828
+ * @property {string} generationId - Retained generation identity.
1829
+ * @property {string} tempPointer - Owned sibling temporary-pointer filename.
1830
+ */
1831
+ /** @typedef {CandidatePublicationJournal | ReactivationPublicationJournal} PublicationJournal */
1832
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHVibGljYXRpb24uanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sRUFBQyxVQUFVLEVBQUUsVUFBVSxFQUFDLE1BQU0sYUFBYSxDQUFBO0FBQ2xELE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxTQUFTLENBQUE7QUFDakMsT0FBTyxFQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQTtBQUM1RixPQUFPLElBQUksTUFBTSxXQUFXLENBQUE7QUFDNUIsT0FBTyxFQUFDLGdDQUFnQyxFQUFFLGtCQUFrQixFQUFDLE1BQU0sb0JBQW9CLENBQUE7QUFDdkYsT0FBTyxFQUFDLDBCQUEwQixFQUFDLE1BQU0sZ0JBQWdCLENBQUE7QUFDekQsT0FBTyxFQUFDLG1CQUFtQixFQUFDLE1BQU0scUJBQXFCLENBQUE7QUFDdkQsT0FBTyxFQUFDLHFCQUFxQixFQUFDLE1BQU0saUJBQWlCLENBQUE7QUFDckQsT0FBTyxFQUFDLGVBQWUsRUFBRSxhQUFhLEVBQUMsTUFBTSxjQUFjLENBQUE7QUFFM0QsTUFBTSxpQkFBaUIsR0FBRyx3QkFBd0IsQ0FBQTtBQUNsRCxNQUFNLGVBQWUsR0FBRyxhQUFhLENBQUE7QUFDckMsTUFBTSxXQUFXLEdBQUcsa0NBQWtDLENBQUE7QUFDdEQsTUFBTSxlQUFlLEdBQUcsb0JBQW9CLENBQUE7QUFDNUMsTUFBTSxpQkFBaUIsR0FBRyxxQ0FBcUMsQ0FBQTtBQUMvRCxNQUFNLGdCQUFnQixHQUFHLG9CQUFvQixDQUFBO0FBQzdDLE1BQU0sZ0JBQWdCLEdBQUcsdUVBQXVFLENBQUE7QUFDaEcsTUFBTSxXQUFXLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxhQUFhLEVBQUUsUUFBUSxFQUFF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cUIsQ0FBQztRQUM5QixLQUFLLEVBQUUsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxTQUFTO1FBQ2pELElBQUk7UUFDSixRQUFRLEVBQUUsU0FBUztRQUNuQixPQUFPO0tBQ1IsQ0FBQyxDQUFBO0FBQ0osQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBRUg7Ozs7R0FJRztBQUVIOzs7Ozs7O0dBT0c7QUFFSDs7Ozs7OztHQU9HO0FBRUg7Ozs7Ozs7O0dBUUc7QUFFSCxpR0FBaUciLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHtjcmVhdGVIYXNoLCByYW5kb21VVUlEfSBmcm9tIFwibm9kZTpjcnlwdG9cIlxuaW1wb3J0IHtjb25zdGFudHN9IGZyb20gXCJub2RlOmZzXCJcbmltcG9ydCB7bHN0YXQsIG1rZGlyLCBvcGVuLCByZWFkRmlsZSwgcmVhZGRpciwgcmVhbHBhdGgsIHJlbmFtZSwgcm19IGZyb20gXCJub2RlOmZzL3Byb21pc2VzXCJcbmltcG9ydCBwYXRoIGZyb20gXCJub2RlOnBhdGhcIlxuaW1wb3J0IHtmaW5kUG9ydGFibGVBcnRpZmFjdFBhdGhDb25mbGljdCwgaXNTYWZlQXJ0aWZhY3RQYXRofSBmcm9tIFwiLi9hcnRpZmFjdC1wYXRoLmpzXCJcbmltcG9ydCB7Y3JlYXRlR2VuZXJhdGVkQXJ0aWZhY3RTZXR9IGZyb20gXCIuL2FydGlmYWN0cy5qc1wiXG5pbXBvcnQge2ZpbmFsaXplQnl0ZU1hcHBpbmd9IGZyb20gXCIuL2JpbmFyeS1tYXBwaW5nLmpzXCJcbmltcG9ydCB7U2VtYW50aWZvbGREaWFnbm9zdGljfSBmcm9tIFwiLi9kaWFnbm9zdGljLmpzXCJcbmltcG9ydCB7ZmluYWxpemVNYXBwaW5nLCB0b1NvdXJjZU1hcFYzfSBmcm9tIFwiLi9tYXBwaW5nLmpzXCJcblxuY29uc3QgYWN0aXZlUG9pbnRlck5hbWUgPSBcImFjdGl2ZS1nZW5lcmF0aW9uLmpzb25cIlxuY29uc3QgZ2VuZXJhdGlvbnNOYW1lID0gXCJnZW5lcmF0aW9uc1wiXG5jb25zdCBqb3VybmFsTmFtZSA9IFwiLnNlbWFudGlmb2xkLXB1YmxpY2F0aW9uLWpvdXJuYWxcIlxuY29uc3QgaWRlbnRpdHlQYXR0ZXJuID0gL15bYS16XVthLXowLTktXSokL3VcbmNvbnN0IGdlbmVyYXRpb25QYXR0ZXJuID0gL15bQS1aYS16MC05XVtBLVphLXowLTkuXy1dezAsMTI3fSQvdVxuY29uc3QgYnVpbGRSb2xlUGF0dGVybiA9IC9eW2Etel1bYS16MC05LV0qJC91XG5jb25zdCBtZWRpYVR5cGVQYXR0ZXJuID0gL15bQS1aYS16MC05ISMkJl5fListXStcXC9bQS1aYS16MC05ISMkJl5fListXSsoPzo7W1xcdTAwMjAtXFx1MDA3ZV0rKT8kL3VcbmNvbnN0IHRhcmdldFJvbGVzID0gbmV3IFNldChbXCJhcHBsaWNhdGlvblwiLCBcImJpbmFyeVwiLCBcInRleHRcIl0pXG5jb25zdCBwdWJsaWNhdGlvbkJvdW5kYXJpZXMgPSBuZXcgU2V0KFtcbiAgXCJhZnRlci1zdGFnZVwiLFxuICBcImJlZm9yZS1wb2ludGVyLXJlcGxhY2VcIixcbiAgXCJhZnRlci1wb2ludGVyLXJlcGxhY2VcIixcbiAgXCJiZWZvcmUtY2xlYW51cFwiLFxuICBcImJlZm9yZS1qb3VybmFsLXJlbW92ZVwiXG5dKVxuLyoqIEB0eXBlIHtXZWFrTWFwPEdlbmVyYXRlZEFydGlmYWN0UHVibGlzaGVyLCB7Ym91bmRhcnk6IHN0cmluZywgZXJyb3I6IEVycm9yfT59ICovXG5jb25zdCBpbmplY3RlZFB1YmxpY2F0aW9uRmFpbHVyZXMgPSBuZXcgV2Vha01hcCgpXG4vKiogQHR5cGUge1dlYWtNYXA8R2VuZXJhdGVkQXJ0aWZhY3RQdWJsaXNoZXIsIChvcGVyYXRpb246IHN0cmluZykgPT4gdm9pZD59ICovXG5jb25zdCBwdWJsaWNhdGlvbkZpbGVzeXN0ZW1PYnNlcnZlcnMgPSBuZXcgV2Vha01hcCgpXG4vKiogQHR5cGUge1dlYWtNYXA8R2VuZXJhdGVkQXJ0aWZhY3RQdWJsaXNoZXIsICgoKSA9PiBQcm9taXNlPHZvaWQ+IHwgdm9pZClbXT59ICovXG5jb25zdCBwdWJsaWNhdGlvbkNvbW1pdEd1YXJkcyA9IG5ldyBXZWFrTWFwKClcblxuLyoqXG4gKiBRdWV1ZXMgb25lIGludGVybmFsIGNhbGxlci1vd25lZCBjdXJyZW50bmVzcyBndWFyZCBmb3IgdGhlIHB1Ymxpc2hlcidzIG5leHQgdHJhbnNhY3Rpb24uXG4gKiBUaGUgZ3VhcmQgcnVucyBhZnRlciBldmVyeSB2YWxpZGF0b3IgY2xvc2VzIGFuZCBpbW1lZGlhdGVseSBiZWZvcmUgdGhlIGFjdGl2ZS1wb2ludGVyIGNvbW1pdC5cbiAqIFRoaXMgaGVscGVyIGlzIGludGVudGlvbmFsbHkgbm90IHBhcnQgb2YgdGhlIHBhY2thZ2Ugcm9vdCBBUEkuXG4gKiBAcGFyYW0ge0dlbmVyYXRlZEFydGlmYWN0UHVibGlzaGVyfSBwdWJsaXNoZXIgLSBQdWJsaXNoZXIgaW5zdGFuY2UuXG4gKiBAcGFyYW0geygpID0+IFByb21pc2U8dm9pZD4gfCB2b2lkfSBndWFyZCAtIEV4YWN0IHByZS1jb21taXQgZ3VhcmQuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGd1YXJkTmV4dFB1YmxpY2F0aW9uQ29tbWl0KHB1Ymxpc2hlciwgZ3VhcmQpIHtcbiAgaWYgKCEocHVibGlzaGVyIGluc3RhbmNlb2YgR2VuZXJhdGVkQXJ0aWZhY3RQdWJsaXNoZXIpIHx8IHR5cGVvZiBndWFyZCAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiSW52YWxpZCBwdWJsaWNhdGlvbiBjb21taXQgZ3VhcmQuXCIpXG4gIH1cbiAgY29uc3QgcXVldWVkID0gcHVibGljYXRpb25Db21taXRHdWFyZHMuZ2V0KHB1Ymxpc2hlcikgPz8gW11cblxuICBxdWV1ZWQucHVzaChndWFyZClcbiAgcHVibGljYXRpb25Db21taXRHdWFyZHMuc2V0KHB1Ymxpc2hlciwgcXVldWVkKVxufVxuXG4vKipcbiAqIEluc3RhbGxzIG9uZSBpbnRlcm5hbCwgb25lLXNob3QgZGV0ZXJtaW5pc3RpYyBmYWlsdXJlIHVzZWQgYnkgcmVhbC1maWxlc3lzdGVtIGludGVycnVwdGlvbiBzcGVjcy5cbiAqIFRoaXMgaGVscGVyIGlzIGludGVudGlvbmFsbHkgbm90IHBhcnQgb2YgdGhlIHBhY2thZ2Ugcm9vdCBBUEkuXG4gKiBAcGFyYW0ge0dlbmVyYXRlZEFydGlmYWN0UHVibGlzaGVyfSBwdWJsaXNoZXIgLSBQdWJsaXNoZXIgaW5zdGFuY2UuXG4gKiBAcGFyYW0ge1wiYWZ0ZXItc3RhZ2VcIiB8IFwiYmVmb3JlLXBvaW50ZXItcmVwbGFjZVwiIHwgXCJhZnRlci1wb2ludGVyLXJlcGxhY2VcIiB8IFwiYmVmb3JlLWNsZWFudXBcIiB8IFwiYmVmb3JlLWpvdXJuYWwtcmVtb3ZlXCJ9IGJvdW5kYXJ5IC0gRXhhY3QgbGlmZWN5Y2xlIGJvdW5kYXJ5LlxuICogQHBhcmFtIHtFcnJvcn0gZXJyb3IgLSBJbmplY3RlZCBmYWlsdXJlLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmplY3RQdWJsaWNhdGlvbkZhaWx1cmUocHVibGlzaGVyLCBib3VuZGFyeSwgZXJyb3IpIHtcbiAgaWYgKCEocHVibGlzaGVyIGluc3RhbmNlb2YgR2VuZXJhdGVkQXJ0aWZhY3RQdWJsaXNoZXIpIHx8ICFwdWJsaWNhdGlvbkJvdW5kYXJpZXMuaGFzKGJvdW5kYXJ5KSB8fCAhKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgcHVibGljYXRpb24gZmFpbHVyZSBpbmplY3Rpb24uXCIpXG4gIH1cbiAgaW5qZWN0ZWRQdWJsaWNhdGlvbkZhaWx1cmVzLnNldChwdWJsaXNoZXIsIHtib3VuZGFyeSwgZXJyb3J9KVxufVxuXG4vKipcbiAqIEluc3RhbGxzIGFuIGludGVybmFsIGRldGVybWluaXN0aWMgZmlsZXN5c3RlbS1vcGVyYXRpb24gb2JzZXJ2ZXIgZm9yIGR1cmFiaWxpdHkgc3BlY3MuXG4gKiBUaGlzIGhlbHBlciBpcyBpbnRlbnRpb25hbGx5IG5vdCBwYXJ0IG9mIHRoZSBwYWNrYWdlIHJvb3QgQVBJLlxuICogQHBhcmFtIHtHZW5lcmF0ZWRBcnRpZmFjdFB1Ymxpc2hlcn0gcHVibGlzaGVyIC0gUHVibGlzaGVyIGluc3RhbmNlLlxuICogQHBhcmFtIHsob3BlcmF0aW9uOiBzdHJpbmcpID0+IHZvaWR9IG9ic2VydmVyIC0gU3luY2hyb25vdXMgb3BlcmF0aW9uIG9ic2VydmVyLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvYnNlcnZlUHVibGljYXRpb25GaWxlc3lzdGVtKHB1Ymxpc2hlciwgb2JzZXJ2ZXIpIHtcbiAgaWYgKCEocHVibGlzaGVyIGluc3RhbmNlb2YgR2VuZXJhdGVkQXJ0aWZhY3RQdWJsaXNoZXIpIHx8IHR5cGVvZiBvYnNlcnZlciAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiSW52YWxpZCBwdWJsaWNhdGlvbiBmaWxlc3lzdGVtIG9ic2VydmVyLlwiKVxuICB9XG4gIHB1YmxpY2F0aW9uRmlsZXN5c3RlbU9ic2VydmVycy5zZXQocHVibGlzaGVyLCBvYnNlcnZlcilcbn1cblxuLyoqXG4gKiBPd25zIHRyYW5zYWN0aW9uYWwgcHVibGljYXRpb24gaW4gb25lIGRlZGljYXRlZCBkaXJlY3RvcnkgYmVuZWF0aCBhIGNhbm9uaWNhbCBwcm9qZWN0IHJvb3QuXG4gKi9cbmV4cG9ydCBjbGFzcyBHZW5lcmF0ZWRBcnRpZmFjdFB1Ymxpc2hlciB7XG4gIC8qKiBAdHlwZSB7c3RyaW5nfSAqL1xuICAjcHJvamVjdElkXG4gIC8qKiBAdHlwZSB7c3RyaW5nfSAqL1xuICAjcHJvamVjdFJvb3RcbiAgLyoqIEB0eXBlIHtzdHJpbmd9ICovXG4gICNwdWJsaWNhdGlvblJvb3RcbiAgLyoqIEB0eXBlIHtyZWFkb25seSBzdHJpbmdbXX0gKi9cbiAgI3NvdXJjZVJvb3RzXG4gIC8qKiBAdHlwZSB7cmVhZG9ubHkgc3RyaW5nW119ICovXG4gICNzb3VyY2VGaWxlc1xuICAvKiogQHR5cGUge1Byb21pc2U8dm9pZD59ICovXG4gICNwdWJsaWNhdGlvblRhaWwgPSBQcm9taXNlLnJlc29sdmUoKVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgcHJvamVjdC1zY29wZWQgcHVibGlzaGVyIHdpdGhvdXQgdG91Y2hpbmcgdGhlIGZpbGVzeXN0ZW0uXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zIC0gUHVibGlzaGVyIGlkZW50aXR5IGFuZCBvd25lZCBwYXRocy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMucHJvamVjdElkIC0gU3RhYmxlIGxvd2VyY2FzZSBwcm9qZWN0IGlkZW50aXR5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5wcm9qZWN0Um9vdCAtIENhbm9uaWNhbCBhYnNvbHV0ZSBwcm9qZWN0IHJvb3QuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLnB1YmxpY2F0aW9uUm9vdCAtIENhbm9uaWNhbCBhYnNvbHV0ZSBwdWJsaXNoZXItb3duZWQgZGlyZWN0b3J5IGJlbmVhdGggdGhlIHByb2plY3Qgcm9vdC5cbiAgICogQHBhcmFtIHtyZWFkb25seSBzdHJpbmdbXX0gW29wdGlvbnMuc291cmNlUm9vdHNdIC0gQ2Fub25pY2FsIGFic29sdXRlIHByb2plY3Qgc291cmNlIGRpcmVjdG9yaWVzIGtlcHQgZGlzam9pbnQgZnJvbSBwdWJsaWNhdGlvbi5cbiAgICogQHBhcmFtIHtyZWFkb25seSBzdHJpbmdbXX0gW29wdGlvbnMuc291cmNlRmlsZXNdIC0gQ2Fub25pY2FsIGFic29sdXRlIHByb2plY3Qgc291cmNlIGZpbGVzIGtlcHQgZGlzam9pbnQgZnJvbSBwdWJsaWNhdGlvbi5cbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICBpZiAoIWlzUGxhaW5PYmplY3Qob3B0aW9ucykpIHtcbiAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIklOVkFMSURfUFVCTElDQVRJT05fUkVRVUVTVFwiLCBcInB1YmxpY2F0aW9uXCIsIFwiUHVibGlzaGVyIG9wdGlvbnMgbXVzdCBiZSBhIHBsYWluIG9iamVjdC5cIilcbiAgICB9XG4gICAgY29uc3Qge3Byb2plY3RJZCwgcHJvamVjdFJvb3QsIHB1YmxpY2F0aW9uUm9vdCwgc291cmNlRmlsZXMgPSBbXSwgc291cmNlUm9vdHMgPSBbXX0gPSBvcHRpb25zXG5cbiAgICBpZiAoIWlkZW50aXR5UGF0dGVybi50ZXN0KHByb2plY3RJZCA/PyBcIlwiKSkge1xuICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiSU5WQUxJRF9QVUJMSUNBVElPTl9SRVFVRVNUXCIsIFwicHVibGljYXRpb25cIiwgXCJQcm9qZWN0IGlkZW50aXR5IG11c3QgYmUgYSBzdGFibGUgbG93ZXJjYXNlIElELlwiKVxuICAgIH1cbiAgICBpZiAoIWlzQ2Fub25pY2FsQWJzb2x1dGVQYXRoKHByb2plY3RSb290KSB8fCAhaXNDYW5vbmljYWxBYnNvbHV0ZVBhdGgocHVibGljYXRpb25Sb290KSB8fFxuICAgICAgIWlzU3RyaWN0UGF0aERlc2NlbmRhbnQocHJvamVjdFJvb3QsIHB1YmxpY2F0aW9uUm9vdCkpIHtcbiAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIklOVkFMSURfUFVCTElDQVRJT05fUk9PVFwiLCBwcm9qZWN0SWQsXG4gICAgICAgIFwiUHJvamVjdCBhbmQgcHVibGljYXRpb24gcm9vdHMgbXVzdCBiZSBjYW5vbmljYWwgYWJzb2x1dGUgcGF0aHMgd2l0aCBwdWJsaWNhdGlvbiBzdHJpY3RseSBiZW5lYXRoIHRoZSBwcm9qZWN0IHJvb3QuXCIpXG4gICAgfVxuICAgIGlmICghaXNEZW5zZUFycmF5KHNvdXJjZVJvb3RzKSB8fCAhaXNEZW5zZUFycmF5KHNvdXJjZUZpbGVzKSB8fCBzb3VyY2VSb290cy5sZW5ndGggKyBzb3VyY2VGaWxlcy5sZW5ndGggPT0gMCkge1xuICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiSU5WQUxJRF9QVUJMSUNBVElPTl9ST09UXCIsIHByb2plY3RJZCxcbiAgICAgICAgXCJQdWJsaXNoZXIgcmVxdWlyZXMgY2Fub25pY2FsIGFic29sdXRlIHNvdXJjZSBkaXJlY3RvcmllcyBvciBzb3VyY2UgZmlsZXMuXCIpXG4gICAgfVxuICAgIC8qKiBAdHlwZSB7c3RyaW5nW119ICovXG4gICAgY29uc3QgdmFsaWRhdGVkU291cmNlUm9vdHMgPSBbXVxuXG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHNvdXJjZVJvb3RzLmxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgICAgY29uc3Qgc291cmNlUm9vdCA9IHNvdXJjZVJvb3RzW2luZGV4XVxuXG4gICAgICBpZiAoIWlzQ2Fub25pY2FsQWJzb2x1dGVQYXRoKHNvdXJjZVJvb3QpKSB7XG4gICAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIklOVkFMSURfUFVCTElDQVRJT05fUk9PVFwiLCBwcm9qZWN0SWQsXG4gICAgICAgICAgXCJTb3VyY2Ugcm9vdHMgbXVzdCBiZSBhIG5vbi1lbXB0eSBhcnJheSBvZiBjYW5vbmljYWwgYWJzb2x1dGUgcGF0aHMuXCIpXG4gICAgICB9XG4gICAgICBpZiAoIWlzUGF0aFdpdGhpbihwcm9qZWN0Um9vdCwgc291cmNlUm9vdCkpIHtcbiAgICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiSU5WQUxJRF9QVUJMSUNBVElPTl9ST09UXCIsIHByb2plY3RJZCxcbiAgICAgICAgICBcIlNvdXJjZSByb290cyBtdXN0IHJlbWFpbiB3aXRoaW4gdGhlIGNhbm9uaWNhbCBwcm9qZWN0IHJvb3QuXCIpXG4gICAgICB9XG4gICAgICBpZiAocGF0aHNPdmVybGFwKHB1YmxpY2F0aW9uUm9vdCwgc291cmNlUm9vdCkpIHtcbiAgICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fU09VUkNFX09WRVJMQVBcIiwgcHJvamVjdElkLFxuICAgICAgICAgIFwiUHVibGljYXRpb24gcm9vdCBhbmQgc291cmNlIHJvb3RzIG11c3QgYmUgZGlzam9pbnQuXCIpXG4gICAgICB9XG4gICAgICB2YWxpZGF0ZWRTb3VyY2VSb290cy5wdXNoKHNvdXJjZVJvb3QpXG4gICAgfVxuICAgIC8qKiBAdHlwZSB7c3RyaW5nW119ICovXG4gICAgY29uc3QgdmFsaWRhdGVkU291cmNlRmlsZXMgPSBbXVxuXG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHNvdXJjZUZpbGVzLmxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgICAgY29uc3Qgc291cmNlRmlsZSA9IHNvdXJjZUZpbGVzW2luZGV4XVxuXG4gICAgICBpZiAoIWlzQ2Fub25pY2FsQWJzb2x1dGVQYXRoKHNvdXJjZUZpbGUpIHx8ICFpc1BhdGhXaXRoaW4ocHJvamVjdFJvb3QsIHNvdXJjZUZpbGUpKSB7XG4gICAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIklOVkFMSURfUFVCTElDQVRJT05fUk9PVFwiLCBwcm9qZWN0SWQsXG4gICAgICAgICAgXCJTb3VyY2UgZmlsZXMgbXVzdCBiZSBjYW5vbmljYWwgYWJzb2x1dGUgcGF0aHMgd2l0aGluIHRoZSBwcm9qZWN0IHJvb3QuXCIpXG4gICAgICB9XG4gICAgICBpZiAocGF0aHNPdmVybGFwKHB1YmxpY2F0aW9uUm9vdCwgc291cmNlRmlsZSkpIHtcbiAgICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fU09VUkNFX09WRVJMQVBcIiwgcHJvamVjdElkLFxuICAgICAgICAgIFwiUHVibGljYXRpb24gcm9vdCBhbmQgc291cmNlIGZpbGVzIG11c3QgYmUgZGlzam9pbnQuXCIpXG4gICAgICB9XG4gICAgICB2YWxpZGF0ZWRTb3VyY2VGaWxlcy5wdXNoKHNvdXJjZUZpbGUpXG4gICAgfVxuXG4gICAgdGhpcy4jcHJvamVjdElkID0gcHJvamVjdElkXG4gICAgdGhpcy4jcHJvamVjdFJvb3QgPSBwcm9qZWN0Um9vdFxuICAgIHRoaXMuI3B1YmxpY2F0aW9uUm9vdCA9IHB1YmxpY2F0aW9uUm9vdFxuICAgIHRoaXMuI3NvdXJjZVJvb3RzID0gT2JqZWN0LmZyZWV6ZSh2YWxpZGF0ZWRTb3VyY2VSb290cylcbiAgICB0aGlzLiNzb3VyY2VGaWxlcyA9IE9iamVjdC5mcmVlemUodmFsaWRhdGVkU291cmNlRmlsZXMpXG4gIH1cblxuICAvKipcbiAgICogU3RhZ2VzLCB2YWxpZGF0ZXMsIGFuZCBwdWJsaXNoZXMgb25lIGNvbXBsZXRlIGltbXV0YWJsZSBwcm9qZWN0IGdlbmVyYXRpb24uXG4gICAqIENhbGxzIG9uIG9uZSBwdWJsaXNoZXIgaW5zdGFuY2UgYXJlIHNlcmlhbGl6ZWQgaW4gaW52b2NhdGlvbiBvcmRlci5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlB1YmxpY2F0aW9uUmVxdWVzdH0gcmVxdWVzdCAtIENvbXBsZXRlIHB1YmxpY2F0aW9uIHJlcXVlc3QuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5QdWJsaWNhdGlvbk9wdGlvbnN9IFtvcHRpb25zXSAtIFRyYW5zYWN0aW9uIGxpZmVjeWNsZSBjb250cm9scy5cbiAgICogQHJldHVybnMge1Byb21pc2U8aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5QdWJsaXNoZWRHZW5lcmF0aW9uPn0gQ29tbWl0dGVkIGltbXV0YWJsZSBzbmFwc2hvdC5cbiAgICovXG4gIHB1Ymxpc2gocmVxdWVzdCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3Qgc2lnbmFsID0gdmFsaWRhdGVQdWJsaWNhdGlvbk9wdGlvbnMob3B0aW9ucywgdGhpcy4jcHJvamVjdElkKVxuICAgIGNvbnN0IHF1ZXVlZEd1YXJkcyA9IHB1YmxpY2F0aW9uQ29tbWl0R3VhcmRzLmdldCh0aGlzKVxuICAgIGNvbnN0IGNvbW1pdEd1YXJkID0gcXVldWVkR3VhcmRzPy5zaGlmdCgpXG5cbiAgICBpZiAocXVldWVkR3VhcmRzPy5sZW5ndGggPT0gMCkgcHVibGljYXRpb25Db21taXRHdWFyZHMuZGVsZXRlKHRoaXMpXG4gICAgLyoqIEB0eXBlIHsodmFsdWU6IGltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuUHVibGlzaGVkR2VuZXJhdGlvbikgPT4gdm9pZH0gKi9cbiAgICBsZXQgcmVzb2x2ZVJlc3VsdFxuICAgIC8qKiBAdHlwZSB7KHJlYXNvbj86IHVua25vd24pID0+IHZvaWR9ICovXG4gICAgbGV0IHJlamVjdFJlc3VsdFxuICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHJlc29sdmVSZXN1bHQgPSByZXNvbHZlXG4gICAgICByZWplY3RSZXN1bHQgPSByZWplY3RcbiAgICB9KVxuICAgIGNvbnN0IG9wZXJhdGlvbiA9IHRoaXMuI3B1YmxpY2F0aW9uVGFpbC50aGVuKGFzeW5jICgpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJlc29sdmVSZXN1bHQoYXdhaXQgdGhpcy4jcHVibGlzaChyZXF1ZXN0LCBzaWduYWwsIGNvbW1pdEd1YXJkKSlcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHJlamVjdFJlc3VsdChlcnJvcilcbiAgICAgIH1cbiAgICB9KVxuXG4gICAgdGhpcy4jcHVibGljYXRpb25UYWlsID0gb3BlcmF0aW9uLmNhdGNoKCgpID0+IHt9KVxuXG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmVzIHRoZSBhY3RpdmUgcG9pbnRlciBleGFjdGx5IG9uY2UgYW5kIHZlcmlmaWVzIHRoZSByZWZlcmVuY2VkIGltbXV0YWJsZSBnZW5lcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlB1Ymxpc2hlZEdlbmVyYXRpb24+fSBWZXJpZmllZCBwb2ludGVyLW9uY2Ugc25hcHNob3QuXG4gICAqL1xuICBhc3luYyByZXNvbHZlQWN0aXZlKCkge1xuICAgIGF3YWl0IHRoaXMuI3ByZXBhcmVSb290KClcbiAgICBjb25zdCBwb2ludGVyUGF0aCA9IHBhdGguam9pbih0aGlzLiNwdWJsaWNhdGlvblJvb3QsIGFjdGl2ZVBvaW50ZXJOYW1lKVxuICAgIGNvbnN0IHBvaW50ZXIgPSBhd2FpdCByZWFkQWN0aXZlUG9pbnRlcihwb2ludGVyUGF0aCwgdGhpcy4jcHJvamVjdElkLCBmYWxzZSlcblxuICAgIGlmICghcG9pbnRlcikgcHVibGljYXRpb25GYWlsdXJlKFwiQUNUSVZFX0dFTkVSQVRJT05fTUlTU0lOR1wiLCB0aGlzLiNwcm9qZWN0SWQsIFwiTm8gYWN0aXZlIGdlbmVyYXRpb24gaGFzIGJlZW4gcHVibGlzaGVkLlwiKVxuICAgIGNvbnN0IGdlbmVyYXRpb24gPSBhd2FpdCB2ZXJpZnlQdWJsaXNoZWRHZW5lcmF0aW9uKHRoaXMuI3B1YmxpY2F0aW9uUm9vdCwgdGhpcy4jcHJvamVjdElkLCBwb2ludGVyLCBmYWxzZSlcbiAgICBjb25zdCBjbGVhbnVwUGVuZGluZyA9IGF3YWl0IGhhc0NvbW1pdHRlZENsZWFudXBKb3VybmFsKHRoaXMuI3B1YmxpY2F0aW9uUm9vdCwgdGhpcy4jcHJvamVjdElkLCBwb2ludGVyLmdlbmVyYXRpb25JZClcblxuICAgIHJldHVybiBwdWJsaXNoZWRHZW5lcmF0aW9uKHRoaXMuI3B1YmxpY2F0aW9uUm9vdCwgZ2VuZXJhdGlvbi5tYW5pZmVzdCwgY2xlYW51cFBlbmRpbmcpXG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybXMgb25lIHNlcmlhbGl6ZWQgcHVibGljYXRpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5QdWJsaWNhdGlvblJlcXVlc3R9IHJlcXVlc3QgLSBDb21wbGV0ZSByZXF1ZXN0LlxuICAgKiBAcGFyYW0ge0Fib3J0U2lnbmFsIHwgdW5kZWZpbmVkfSBzaWduYWwgLSBPcHRpb25hbCB0cmFuc2FjdGlvbiBjYW5jZWxsYXRpb24gYXV0aG9yaXR5LlxuICAgKiBAcGFyYW0geygoKSA9PiBQcm9taXNlPHZvaWQ+IHwgdm9pZCkgfCB1bmRlZmluZWR9IGNvbW1pdEd1YXJkIC0gT3B0aW9uYWwgY3VycmVudG5lc3MgZ3VhcmQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPGltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuUHVibGlzaGVkR2VuZXJhdGlvbj59IFB1YmxpY2F0aW9uIHJlc3VsdC5cbiAgICovXG4gIGFzeW5jICNwdWJsaXNoKHJlcXVlc3QsIHNpZ25hbCwgY29tbWl0R3VhcmQpIHtcbiAgICBjb25zdCB2YWxpZGF0ZWQgPSB2YWxpZGF0ZVB1YmxpY2F0aW9uUmVxdWVzdChyZXF1ZXN0LCB0aGlzLiNwcm9qZWN0SWQpXG5cbiAgICBhc3NlcnRQdWJsaWNhdGlvbkFjdGl2ZShzaWduYWwsIHRoaXMuI3Byb2plY3RJZClcbiAgICBhd2FpdCB0aGlzLiNwcmVwYXJlUm9vdCgpXG4gICAgYXdhaXQgcmVjb25jaWxlUHVibGljYXRpb24odGhpcy4jcHVibGljYXRpb25Sb290LCB0aGlzLiNwcm9qZWN0SWQsIHRoaXMpXG4gICAgYXdhaXQgdmVyaWZ5QXRvbWljUmVwbGFjZW1lbnQodGhpcy4jcHVibGljYXRpb25Sb290LCB0aGlzLiNwcm9qZWN0SWQpXG4gICAgYXdhaXQgdmFsaWRhdGVFeGlzdGluZ1BvaW50ZXIodGhpcy4jcHVibGljYXRpb25Sb290LCB0aGlzLiNwcm9qZWN0SWQpXG5cbiAgICBjb25zdCBnZW5lcmF0aW9uUGF0aCA9IHBhdGguam9pbih0aGlzLiNwdWJsaWNhdGlvblJvb3QsIGdlbmVyYXRpb25zTmFtZSwgdmFsaWRhdGVkLmdlbmVyYXRpb25JZClcbiAgICBjb25zdCBtYW5pZmVzdFBhdGggPSBwYXRoLmpvaW4oZ2VuZXJhdGlvblBhdGgsIFwibWFuaWZlc3QuanNvblwiKVxuICAgIGNvbnN0IHRlbXBQb2ludGVyTmFtZSA9IGAuYWN0aXZlLWdlbmVyYXRpb24uJHt2YWxpZGF0ZWQuZ2VuZXJhdGlvbklkfS50bXBgXG4gICAgY29uc3QgdGVtcFBvaW50ZXJQYXRoID0gcGF0aC5qb2luKHRoaXMuI3B1YmxpY2F0aW9uUm9vdCwgdGVtcFBvaW50ZXJOYW1lKVxuICAgIGNvbnN0IGpvdXJuYWxQYXRoID0gcGF0aC5qb2luKHRoaXMuI3B1YmxpY2F0aW9uUm9vdCwgam91cm5hbE5hbWUsIGAke3ZhbGlkYXRlZC5nZW5lcmF0aW9uSWR9Lmpzb25gKVxuICAgIGNvbnN0IHJldGFpbmVkR2VuZXJhdGlvbiA9IGF3YWl0IG9wdGlvbmFsU3RhdHVzKGdlbmVyYXRpb25QYXRoLCB0aGlzLiNwcm9qZWN0SWQsIFwicmV0YWluZWQgZ2VuZXJhdGlvblwiKSAhPT0gbnVsbFxuICAgIGxldCBjb21taXR0ZWQgPSBmYWxzZVxuICAgIGxldCBqb3VybmFsQ3JlYXRlZCA9IGZhbHNlXG4gICAgbGV0IGdlbmVyYXRpb25DcmVhdGVkID0gZmFsc2VcbiAgICBsZXQgdGVtcFBvaW50ZXJDcmVhdGVkID0gZmFsc2VcbiAgICBsZXQgZmFpbHVyZUNvZGUgPSBcIlBVQkxJQ0FUSU9OX1NUQUdFX1dSSVRFX0ZBSUxFRFwiXG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRpb25NYW5pZmVzdCB8IG51bGx9ICovXG4gICAgbGV0IG1hbmlmZXN0ID0gbnVsbFxuICAgIC8qKiBAdHlwZSB7QnVmZmVyIHwgbnVsbH0gKi9cbiAgICBsZXQgbWFuaWZlc3RCeXRlcyA9IG51bGxcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBhc3NlcnRBYnNlbnQodGVtcFBvaW50ZXJQYXRoLCBcIlBVQkxJQ0FUSU9OX1VOT1dORURfQ09ORkxJQ1RcIiwgdGhpcy4jcHJvamVjdElkLFxuICAgICAgICBcIlRlbXBvcmFyeSBhY3RpdmUgcG9pbnRlciBwYXRoIGlzIGFscmVhZHkgb3duZWQgb3IgYW1iaWd1b3VzLlwiKVxuICAgICAgYXdhaXQgYXNzZXJ0QWJzZW50KGpvdXJuYWxQYXRoLCBcIlBVQkxJQ0FUSU9OX1VOT1dORURfQ09ORkxJQ1RcIiwgdGhpcy4jcHJvamVjdElkLFxuICAgICAgICBcIlB1YmxpY2F0aW9uIGpvdXJuYWwgaWRlbnRpdHkgaXMgYWxyZWFkeSBvd25lZCBvciBhbWJpZ3VvdXMuXCIpXG4gICAgICBpZiAocmV0YWluZWRHZW5lcmF0aW9uKSB7XG4gICAgICAgIGNvbnN0IHJldGFpbmVkID0gYXdhaXQgdmVyaWZ5UmV0YWluZWRHZW5lcmF0aW9uKGdlbmVyYXRpb25QYXRoLCB2YWxpZGF0ZWQsIHRoaXMuI3Byb2plY3RJZClcblxuICAgICAgICBtYW5pZmVzdCA9IHJldGFpbmVkLm1hbmlmZXN0XG4gICAgICAgIG1hbmlmZXN0Qnl0ZXMgPSByZXRhaW5lZC5tYW5pZmVzdEJ5dGVzXG4gICAgICB9XG4gICAgICBjb25zdCBqb3VybmFsID0gcmV0YWluZWRHZW5lcmF0aW9uXG4gICAgICAgID8ge1xuICAgICAgICAgICAgZ2VuZXJhdGlvbklkOiB2YWxpZGF0ZWQuZ2VuZXJhdGlvbklkLFxuICAgICAgICAgICAgb3BlcmF0aW9uOiBcInJlYWN0aXZhdGVcIixcbiAgICAgICAgICAgIHByb2plY3RJZDogdGhpcy4jcHJvamVjdElkLFxuICAgICAgICAgICAgc2NoZW1hOiBcIlNlbWFudGlmb2xkUHVibGljYXRpb25Kb3VybmFsXCIsXG4gICAgICAgICAgICB0ZW1wUG9pbnRlcjogdGVtcFBvaW50ZXJOYW1lLFxuICAgICAgICAgICAgdmVyc2lvbjogMlxuICAgICAgICAgIH1cbiAgICAgICAgOiB7XG4gICAgICAgICAgICBnZW5lcmF0aW9uSWQ6IHZhbGlkYXRlZC5nZW5lcmF0aW9uSWQsXG4gICAgICAgICAgICBwcm9qZWN0SWQ6IHRoaXMuI3Byb2plY3RJZCxcbiAgICAgICAgICAgIHNjaGVtYTogXCJTZW1hbnRpZm9sZFB1YmxpY2F0aW9uSm91cm5hbFwiLFxuICAgICAgICAgICAgdGVtcFBvaW50ZXI6IHRlbXBQb2ludGVyTmFtZSxcbiAgICAgICAgICAgIHZlcnNpb246IDFcbiAgICAgICAgICB9XG5cbiAgICAgIGF3YWl0IHdyaXRlU3luY2VkRmlsZShqb3VybmFsUGF0aCwgc2VyaWFsaXplSnNvbihqb3VybmFsKSwgXCJ3eFwiKVxuICAgICAgam91cm5hbENyZWF0ZWQgPSB0cnVlXG4gICAgICBhd2FpdCBzeW5jRGlyZWN0b3J5KHBhdGguZGlybmFtZShqb3VybmFsUGF0aCkpXG4gICAgICBpZiAoIXJldGFpbmVkR2VuZXJhdGlvbikge1xuICAgICAgICBhd2FpdCBta2RpcihnZW5lcmF0aW9uUGF0aCwge21vZGU6IDBvNzAwfSlcbiAgICAgICAgZ2VuZXJhdGlvbkNyZWF0ZWQgPSB0cnVlXG4gICAgICAgIGF3YWl0IHN5bmNEaXJlY3RvcnkocGF0aC5kaXJuYW1lKGdlbmVyYXRpb25QYXRoKSlcblxuICAgICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGlvblRhcmdldE1hbmlmZXN0W119ICovXG4gICAgICAgIGNvbnN0IHRhcmdldE1hbmlmZXN0cyA9IFtdXG5cbiAgICAgICAgZm9yIChjb25zdCB0YXJnZXQgb2YgdmFsaWRhdGVkLnRhcmdldHMpIHtcbiAgICAgICAgICB0YXJnZXRNYW5pZmVzdHMucHVzaChhd2FpdCBzdGFnZVRhcmdldChnZW5lcmF0aW9uUGF0aCwgdGFyZ2V0LCB0aGlzLiNwcm9qZWN0SWQpKVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG1hbmlmZXN0Q2FuZGlkYXRlID0gLyoqIEB0eXBlIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRpb25NYW5pZmVzdH0gKi8gKHtcbiAgICAgICAgICBnZW5lcmF0aW9uSWQ6IHZhbGlkYXRlZC5nZW5lcmF0aW9uSWQsXG4gICAgICAgICAgcHJvamVjdElkOiB0aGlzLiNwcm9qZWN0SWQsXG4gICAgICAgICAgc2NoZW1hOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJTZW1hbnRpZm9sZEdlbmVyYXRpb25NYW5pZmVzdFwiKSxcbiAgICAgICAgICB0YXJnZXRzOiB0YXJnZXRNYW5pZmVzdHMsXG4gICAgICAgICAgdmVyc2lvbjogLyoqIEB0eXBlIHtjb25zdH0gKi8gKDEpXG4gICAgICAgIH0pXG5cbiAgICAgICAgbWFuaWZlc3RCeXRlcyA9IHNlcmlhbGl6ZUpzb24obWFuaWZlc3RDYW5kaWRhdGUpXG4gICAgICAgIG1hbmlmZXN0ID0gdmFsaWRhdGVHZW5lcmF0aW9uTWFuaWZlc3QoSlNPTi5wYXJzZShtYW5pZmVzdEJ5dGVzLnRvU3RyaW5nKFwidXRmOFwiKSksIHRoaXMuI3Byb2plY3RJZCxcbiAgICAgICAgICB2YWxpZGF0ZWQuZ2VuZXJhdGlvbklkKVxuXG4gICAgICAgIGF3YWl0IHdyaXRlU3luY2VkRmlsZShtYW5pZmVzdFBhdGgsIG1hbmlmZXN0Qnl0ZXMsIFwid3hcIilcbiAgICAgICAgYXdhaXQgc3luY1RyZWVEaXJlY3RvcmllcyhnZW5lcmF0aW9uUGF0aClcbiAgICAgICAgYXdhaXQgdmVyaWZ5TWFuaWZlc3RGaWxlcyhnZW5lcmF0aW9uUGF0aCwgbWFuaWZlc3QsIHRoaXMuI3Byb2plY3RJZClcbiAgICAgIH1cbiAgICAgIGlmIChtYW5pZmVzdCA9PT0gbnVsbCB8fCBtYW5pZmVzdEJ5dGVzID09PSBudWxsKSB7XG4gICAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX1NUQUdFX1dSSVRFX0ZBSUxFRFwiLCB0aGlzLiNwcm9qZWN0SWQsXG4gICAgICAgICAgXCJDYW5kaWRhdGUgZ2VuZXJhdGlvbiBtYW5pZmVzdCBjb3VsZCBub3QgYmUgcHJlcGFyZWQuXCIpXG4gICAgICB9XG4gICAgICByZWFjaFB1YmxpY2F0aW9uQm91bmRhcnkodGhpcywgXCJhZnRlci1zdGFnZVwiKVxuICAgICAgZmFpbHVyZUNvZGUgPSBcIlBVQkxJQ0FUSU9OX1BPSU5URVJfRkFJTEVEXCJcblxuICAgICAgY29uc3QgcG9pbnRlciA9IHtcbiAgICAgICAgZ2VuZXJhdGlvbklkOiB2YWxpZGF0ZWQuZ2VuZXJhdGlvbklkLFxuICAgICAgICBtYW5pZmVzdEhhc2g6IHNoYTI1NihtYW5pZmVzdEJ5dGVzKSxcbiAgICAgICAgcHJvamVjdElkOiB0aGlzLiNwcm9qZWN0SWQsXG4gICAgICAgIHNjaGVtYTogXCJTZW1hbnRpZm9sZEFjdGl2ZUdlbmVyYXRpb25cIixcbiAgICAgICAgdmVyc2lvbjogMVxuICAgICAgfVxuXG4gICAgICBhd2FpdCB3cml0ZVN5bmNlZEZpbGUodGVtcFBvaW50ZXJQYXRoLCBzZXJpYWxpemVKc29uKHBvaW50ZXIpLCBcInd4XCIsICgpID0+IHtcbiAgICAgICAgdGVtcFBvaW50ZXJDcmVhdGVkID0gdHJ1ZVxuICAgICAgfSlcbiAgICAgIHJlYWNoUHVibGljYXRpb25Cb3VuZGFyeSh0aGlzLCBcImJlZm9yZS1wb2ludGVyLXJlcGxhY2VcIilcbiAgICAgIGF3YWl0IGNvbW1pdEd1YXJkPy4oKVxuICAgICAgYXNzZXJ0UHVibGljYXRpb25BY3RpdmUoc2lnbmFsLCB0aGlzLiNwcm9qZWN0SWQpXG4gICAgICBhd2FpdCByZW5hbWUodGVtcFBvaW50ZXJQYXRoLCBwYXRoLmpvaW4odGhpcy4jcHVibGljYXRpb25Sb290LCBhY3RpdmVQb2ludGVyTmFtZSkpXG4gICAgICB0ZW1wUG9pbnRlckNyZWF0ZWQgPSBmYWxzZVxuICAgICAgY29tbWl0dGVkID0gdHJ1ZVxuICAgICAgcmVhY2hQdWJsaWNhdGlvbkJvdW5kYXJ5KHRoaXMsIFwiYWZ0ZXItcG9pbnRlci1yZXBsYWNlXCIpXG4gICAgICBhd2FpdCBzeW5jRGlyZWN0b3J5KHRoaXMuI3B1YmxpY2F0aW9uUm9vdClcblxuICAgICAgbGV0IGNsZWFudXBQZW5kaW5nID0gZmFsc2VcblxuICAgICAgdHJ5IHtcbiAgICAgICAgcmVhY2hQdWJsaWNhdGlvbkJvdW5kYXJ5KHRoaXMsIFwiYmVmb3JlLWNsZWFudXBcIilcbiAgICAgICAgYXdhaXQgcmVtb3ZlSm91cm5hbE93bmVkU3RhdGUoe1xuICAgICAgICAgIGpvdXJuYWxQYXRoLFxuICAgICAgICAgIHByb2plY3RJZDogdGhpcy4jcHJvamVjdElkLFxuICAgICAgICAgIHB1YmxpY2F0aW9uUm9vdDogdGhpcy4jcHVibGljYXRpb25Sb290LFxuICAgICAgICAgIHB1Ymxpc2hlcjogdGhpc1xuICAgICAgICB9KVxuICAgICAgfSBjYXRjaCAoX2Vycm9yKSB7XG4gICAgICAgIGNsZWFudXBQZW5kaW5nID0gdHJ1ZVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gcHVibGlzaGVkR2VuZXJhdGlvbih0aGlzLiNwdWJsaWNhdGlvblJvb3QsIGRlZXBGcmVlemUobWFuaWZlc3QpLCBjbGVhbnVwUGVuZGluZylcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKCFjb21taXR0ZWQpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCByZW1vdmVKb3VybmFsT3duZWRTdGF0ZSh7XG4gICAgICAgICAgICAuLi4oZ2VuZXJhdGlvbkNyZWF0ZWQgPyB7Y2FuZGlkYXRlUGF0aDogZ2VuZXJhdGlvblBhdGh9IDoge30pLFxuICAgICAgICAgICAgLi4uKGpvdXJuYWxDcmVhdGVkID8ge2pvdXJuYWxQYXRofSA6IHt9KSxcbiAgICAgICAgICAgIHByb2plY3RJZDogdGhpcy4jcHJvamVjdElkLFxuICAgICAgICAgICAgcHVibGljYXRpb25Sb290OiB0aGlzLiNwdWJsaWNhdGlvblJvb3QsXG4gICAgICAgICAgICBwdWJsaXNoZXI6IHRoaXMsXG4gICAgICAgICAgICAuLi4odGVtcFBvaW50ZXJDcmVhdGVkID8ge3RlbXBvcmFyeVBvaW50ZXJQYXRoOiB0ZW1wUG9pbnRlclBhdGh9IDoge30pXG4gICAgICAgICAgfSlcbiAgICAgICAgfSBjYXRjaCAoY2xlYW51cEVycm9yKSB7XG4gICAgICAgICAgaWYgKGNsZWFudXBFcnJvciBpbnN0YW5jZW9mIFNlbWFudGlmb2xkRGlhZ25vc3RpYykgdGhyb3cgY2xlYW51cEVycm9yXG4gICAgICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fUkVDT1ZFUllfRkFJTEVEXCIsIHRoaXMuI3Byb2plY3RJZCxcbiAgICAgICAgICAgIFwiRmFpbGVkIHB1YmxpY2F0aW9uIGxlZnQgc3RhdGUgdGhhdCByZXF1aXJlcyByZWNvdmVyeS5cIiwgY2xlYW51cEVycm9yKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBTZW1hbnRpZm9sZERpYWdub3N0aWMpIHRocm93IGVycm9yXG5cbiAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShmYWlsdXJlQ29kZSwgdGhpcy4jcHJvamVjdElkLFxuICAgICAgICBjb21taXR0ZWRcbiAgICAgICAgICA/IFwiQWN0aXZlIGdlbmVyYXRpb24gY2hhbmdlZCwgYnV0IGR1cmFibGUgcG9pbnRlciBwdWJsaWNhdGlvbiBkaWQgbm90IGNvbXBsZXRlLlwiXG4gICAgICAgICAgOiBcIkNhbmRpZGF0ZSBnZW5lcmF0aW9uIGNvdWxkIG5vdCBiZSBzdGFnZWQuXCIsIGVycm9yKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuZCB2YWxpZGF0ZXMgb3duZWQgcm9vdCBkaXJlY3RvcmllcyBhbmQgc291cmNlLXJvb3Qgc2VwYXJhdGlvbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IENvbXBsZXRpb24uXG4gICAqL1xuICBhc3luYyAjcHJlcGFyZVJvb3QoKSB7XG4gICAgYXdhaXQgZW5zdXJlRGlyZWN0b3J5V2l0aG91dFN5bWxpbmtzKHRoaXMuI3Byb2plY3RSb290LCBmYWxzZSwgdGhpcy4jcHJvamVjdElkKVxuICAgIGF3YWl0IGVuc3VyZURpcmVjdG9yeVdpdGhvdXRTeW1saW5rcyh0aGlzLiNwdWJsaWNhdGlvblJvb3QsIHRydWUsIHRoaXMuI3Byb2plY3RJZClcbiAgICBsZXQgZXhhY3RQcm9qZWN0XG4gICAgbGV0IGV4YWN0UHVibGljYXRpb25cblxuICAgIHRyeSB7XG4gICAgICBleGFjdFByb2plY3QgPSBhd2FpdCByZWFscGF0aCh0aGlzLiNwcm9qZWN0Um9vdClcbiAgICAgIGV4YWN0UHVibGljYXRpb24gPSBhd2FpdCByZWFscGF0aCh0aGlzLiNwdWJsaWNhdGlvblJvb3QpXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIklOVkFMSURfUFVCTElDQVRJT05fUk9PVFwiLCB0aGlzLiNwcm9qZWN0SWQsXG4gICAgICAgIFwiUHVibGljYXRpb24gcm9vdCBjb3VsZCBub3QgYmUgcmVzb2x2ZWQgc2FmZWx5LlwiLCBlcnJvcilcbiAgICB9XG4gICAgaWYgKCFpc1N0cmljdFBhdGhEZXNjZW5kYW50KGV4YWN0UHJvamVjdCwgZXhhY3RQdWJsaWNhdGlvbikpIHtcbiAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIklOVkFMSURfUFVCTElDQVRJT05fUk9PVFwiLCB0aGlzLiNwcm9qZWN0SWQsXG4gICAgICAgIFwiUHVibGljYXRpb24gcm9vdCBtdXN0IHJlc29sdmUgc3RyaWN0bHkgYmVuZWF0aCB0aGUgcHJvamVjdCByb290LlwiKVxuICAgIH1cbiAgICBmb3IgKGNvbnN0IHNvdXJjZVJvb3Qgb2YgdGhpcy4jc291cmNlUm9vdHMpIHtcbiAgICAgIGF3YWl0IGVuc3VyZURpcmVjdG9yeVdpdGhvdXRTeW1saW5rcyhzb3VyY2VSb290LCBmYWxzZSwgdGhpcy4jcHJvamVjdElkKVxuICAgICAgbGV0IGV4YWN0U291cmNlXG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGV4YWN0U291cmNlID0gYXdhaXQgcmVhbHBhdGgoc291cmNlUm9vdClcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIklOVkFMSURfUFVCTElDQVRJT05fUk9PVFwiLCB0aGlzLiNwcm9qZWN0SWQsXG4gICAgICAgICAgXCJTb3VyY2Ugcm9vdCBjb3VsZCBub3QgYmUgcmVzb2x2ZWQgc2FmZWx5LlwiLCBlcnJvcilcbiAgICAgIH1cblxuICAgICAgaWYgKCFpc1BhdGhXaXRoaW4oZXhhY3RQcm9qZWN0LCBleGFjdFNvdXJjZSkpIHtcbiAgICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiSU5WQUxJRF9QVUJMSUNBVElPTl9ST09UXCIsIHRoaXMuI3Byb2plY3RJZCxcbiAgICAgICAgICBcIlNvdXJjZSByb290cyBtdXN0IHJlc29sdmUgd2l0aGluIHRoZSBwcm9qZWN0IHJvb3QuXCIpXG4gICAgICB9XG4gICAgICBpZiAocGF0aHNPdmVybGFwKGV4YWN0UHVibGljYXRpb24sIGV4YWN0U291cmNlKSkge1xuICAgICAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9TT1VSQ0VfT1ZFUkxBUFwiLCB0aGlzLiNwcm9qZWN0SWQsXG4gICAgICAgICAgXCJQdWJsaWNhdGlvbiByb290IGFuZCBzb3VyY2Ugcm9vdHMgcmVzb2x2ZSB0byBvdmVybGFwcGluZyBwYXRocy5cIilcbiAgICAgIH1cbiAgICB9XG4gICAgZm9yIChjb25zdCBzb3VyY2VGaWxlIG9mIHRoaXMuI3NvdXJjZUZpbGVzKSB7XG4gICAgICBhd2FpdCBlbnN1cmVEaXJlY3RvcnlXaXRob3V0U3ltbGlua3MocGF0aC5kaXJuYW1lKHNvdXJjZUZpbGUpLCBmYWxzZSwgdGhpcy4jcHJvamVjdElkKVxuICAgICAgbGV0IHN0YXR1c1xuICAgICAgbGV0IGV4YWN0U291cmNlXG5cbiAgICAgIHRyeSB7XG4gICAgICAgIHN0YXR1cyA9IGF3YWl0IGxzdGF0KHNvdXJjZUZpbGUpXG4gICAgICAgIGV4YWN0U291cmNlID0gYXdhaXQgcmVhbHBhdGgoc291cmNlRmlsZSlcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIklOVkFMSURfUFVCTElDQVRJT05fUk9PVFwiLCB0aGlzLiNwcm9qZWN0SWQsXG4gICAgICAgICAgXCJTb3VyY2UgZmlsZSBjb3VsZCBub3QgYmUgcmVzb2x2ZWQgc2FmZWx5LlwiLCBlcnJvcilcbiAgICAgIH1cbiAgICAgIGlmIChzdGF0dXMuaXNTeW1ib2xpY0xpbmsoKSkge1xuICAgICAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9TWU1MSU5LX1RSQVZFUlNBTFwiLCB0aGlzLiNwcm9qZWN0SWQsXG4gICAgICAgICAgXCJTb3VyY2UgZmlsZSB0cmF2ZXJzYWwgZW5jb3VudGVyZWQgYSBzeW1ib2xpYyBsaW5rLlwiKVxuICAgICAgfVxuICAgICAgaWYgKCFzdGF0dXMuaXNGaWxlKCkgfHwgZXhhY3RTb3VyY2UgIT0gc291cmNlRmlsZSB8fCAhaXNQYXRoV2l0aGluKGV4YWN0UHJvamVjdCwgZXhhY3RTb3VyY2UpKSB7XG4gICAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIklOVkFMSURfUFVCTElDQVRJT05fUk9PVFwiLCB0aGlzLiNwcm9qZWN0SWQsXG4gICAgICAgICAgXCJTb3VyY2UgZmlsZXMgbXVzdCByZXNvbHZlIHRvIHJlYWwgcmVndWxhciBmaWxlcyB3aXRoaW4gdGhlIHByb2plY3Qgcm9vdC5cIilcbiAgICAgIH1cbiAgICAgIGlmIChwYXRoc092ZXJsYXAoZXhhY3RQdWJsaWNhdGlvbiwgZXhhY3RTb3VyY2UpKSB7XG4gICAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX1NPVVJDRV9PVkVSTEFQXCIsIHRoaXMuI3Byb2plY3RJZCxcbiAgICAgICAgICBcIlB1YmxpY2F0aW9uIHJvb3QgYW5kIHNvdXJjZSBmaWxlcyByZXNvbHZlIHRvIG92ZXJsYXBwaW5nIHBhdGhzLlwiKVxuICAgICAgfVxuICAgIH1cbiAgICBhd2FpdCBlbnN1cmVPd25lZERpcmVjdG9yeShwYXRoLmpvaW4odGhpcy4jcHVibGljYXRpb25Sb290LCBnZW5lcmF0aW9uc05hbWUpLCB0aGlzLiNwcm9qZWN0SWQpXG4gICAgYXdhaXQgZW5zdXJlT3duZWREaXJlY3RvcnkocGF0aC5qb2luKHRoaXMuI3B1YmxpY2F0aW9uUm9vdCwgam91cm5hbE5hbWUpLCB0aGlzLiNwcm9qZWN0SWQpXG4gIH1cbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgYW5kIHNuYXBzaG90cyB0cmFuc2FjdGlvbiBsaWZlY3ljbGUgY29udHJvbHMgYmVmb3JlIHB1YmxpY2F0aW9uIGlzIHF1ZXVlZC5cbiAqIEBwYXJhbSB7dW5rbm93bn0gb3B0aW9ucyAtIENhbmRpZGF0ZSBvcHRpb25zLlxuICogQHBhcmFtIHtzdHJpbmd9IHByb2plY3RJZCAtIFByb2plY3QgZGlhZ25vc3RpYyBpZGVudGl0eS5cbiAqIEByZXR1cm5zIHtBYm9ydFNpZ25hbCB8IHVuZGVmaW5lZH0gT3B0aW9uYWwgY2FuY2VsbGF0aW9uIHNpZ25hbC5cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVQdWJsaWNhdGlvbk9wdGlvbnMob3B0aW9ucywgcHJvamVjdElkKSB7XG4gIGlmICghaXNQbGFpbk9iamVjdChvcHRpb25zKSB8fCBPYmplY3Qua2V5cyhvcHRpb25zKS5zb21lKGtleSA9PiBrZXkgIT0gXCJzaWduYWxcIikgfHxcbiAgICBvcHRpb25zLnNpZ25hbCAhPT0gdW5kZWZpbmVkICYmICEob3B0aW9ucy5zaWduYWwgaW5zdGFuY2VvZiBBYm9ydFNpZ25hbCkpIHtcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJJTlZBTElEX1BVQkxJQ0FUSU9OX1JFUVVFU1RcIiwgcHJvamVjdElkLFxuICAgICAgXCJQdWJsaWNhdGlvbiBvcHRpb25zIHJlcXVpcmUgb25seSBhbiBvcHRpb25hbCBBYm9ydFNpZ25hbC5cIilcbiAgfVxuXG4gIHJldHVybiAvKiogQHR5cGUge0Fib3J0U2lnbmFsIHwgdW5kZWZpbmVkfSAqLyAob3B0aW9ucy5zaWduYWwpXG59XG5cbi8qKlxuICogUmVqZWN0cyBjYW5jZWxsYXRpb24gYmVmb3JlIHRoZSBhdG9taWMgYWN0aXZlLXBvaW50ZXIgY29tbWl0IGJlZ2lucy5cbiAqIEBwYXJhbSB7QWJvcnRTaWduYWwgfCB1bmRlZmluZWR9IHNpZ25hbCAtIE9wdGlvbmFsIHRyYW5zYWN0aW9uIGNhbmNlbGxhdGlvbiBhdXRob3JpdHkuXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvamVjdElkIC0gUHJvamVjdCBkaWFnbm9zdGljIGlkZW50aXR5LlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGFzc2VydFB1YmxpY2F0aW9uQWN0aXZlKHNpZ25hbCwgcHJvamVjdElkKSB7XG4gIGlmIChzaWduYWw/LmFib3J0ZWQpIHtcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9DQU5DRUxMRURcIiwgcHJvamVjdElkLFxuICAgICAgXCJQdWJsaWNhdGlvbiB3YXMgY2FuY2VsbGVkIGJlZm9yZSB0aGUgYWN0aXZlIGdlbmVyYXRpb24gcG9pbnRlciBjb21taXQuXCIpXG4gIH1cbn1cblxuLyoqXG4gKiBUaHJvd3MgYW5kIGNvbnN1bWVzIGEgY29uZmlndXJlZCBpbnRlcm5hbCBmYWlsdXJlIGF0IGFuIGV4YWN0IGxpZmVjeWNsZSBib3VuZGFyeS5cbiAqIEBwYXJhbSB7R2VuZXJhdGVkQXJ0aWZhY3RQdWJsaXNoZXJ9IHB1Ymxpc2hlciAtIEFjdGl2ZSBwdWJsaXNoZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gYm91bmRhcnkgLSBSZWFjaGVkIGJvdW5kYXJ5LlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHJlYWNoUHVibGljYXRpb25Cb3VuZGFyeShwdWJsaXNoZXIsIGJvdW5kYXJ5KSB7XG4gIGNvbnN0IGluamVjdGlvbiA9IGluamVjdGVkUHVibGljYXRpb25GYWlsdXJlcy5nZXQocHVibGlzaGVyKVxuXG4gIGlmIChpbmplY3Rpb24/LmJvdW5kYXJ5ID09IGJvdW5kYXJ5KSB7XG4gICAgaW5qZWN0ZWRQdWJsaWNhdGlvbkZhaWx1cmVzLmRlbGV0ZShwdWJsaXNoZXIpXG4gICAgdGhyb3cgaW5qZWN0aW9uLmVycm9yXG4gIH1cbn1cblxuLyoqXG4gKiBSZXBvcnRzIG9uZSBjb21wbGV0ZWQgZmlsZXN5c3RlbSBvcGVyYXRpb24gdG8gdGhlIGludGVybmFsIGRldGVybWluaXN0aWMgc2VhbS5cbiAqIEBwYXJhbSB7R2VuZXJhdGVkQXJ0aWZhY3RQdWJsaXNoZXJ9IHB1Ymxpc2hlciAtIEFjdGl2ZSBwdWJsaXNoZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gb3BlcmF0aW9uIC0gQ29tcGxldGVkIG9wZXJhdGlvbi5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiBvYnNlcnZlUHVibGljYXRpb25GaWxlc3lzdGVtT3BlcmF0aW9uKHB1Ymxpc2hlciwgb3BlcmF0aW9uKSB7XG4gIHB1YmxpY2F0aW9uRmlsZXN5c3RlbU9ic2VydmVycy5nZXQocHVibGlzaGVyKT8uKG9wZXJhdGlvbilcbn1cblxuLyoqXG4gKiBSZWNvbmNpbGVzIG9ubHkgY2FuZGlkYXRlcyBhbmQgdGVtcG9yYXJ5IHBvaW50ZXJzIHdob3NlIG93bmVyc2hpcCBpcyBwcm92ZW4gYnkgYSBzdHJpY3Qgam91cm5hbC5cbiAqIFRoZSBhY3RpdmUgcG9pbnRlciByZW1haW5zIHRoZSBzb2xlIGNvbW1pdCBhdXRob3JpdHkuXG4gKiBAcGFyYW0ge3N0cmluZ30gcHVibGljYXRpb25Sb290IC0gUHVibGljYXRpb24gcm9vdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9qZWN0SWQgLSBQcm9qZWN0IGlkZW50aXR5LlxuICogQHBhcmFtIHtHZW5lcmF0ZWRBcnRpZmFjdFB1Ymxpc2hlcn0gcHVibGlzaGVyIC0gQWN0aXZlIHB1Ymxpc2hlci5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBDb21wbGV0aW9uLlxuICovXG5hc3luYyBmdW5jdGlvbiByZWNvbmNpbGVQdWJsaWNhdGlvbihwdWJsaWNhdGlvblJvb3QsIHByb2plY3RJZCwgcHVibGlzaGVyKSB7XG4gIGNvbnN0IGpvdXJuYWxzID0gYXdhaXQgcmVhZFB1YmxpY2F0aW9uSm91cm5hbHMocHVibGljYXRpb25Sb290LCBwcm9qZWN0SWQpXG5cbiAgaWYgKGpvdXJuYWxzLmxlbmd0aCA9PSAwKSByZXR1cm5cbiAgY29uc3QgcG9pbnRlciA9IGF3YWl0IHJlYWRBY3RpdmVQb2ludGVyKHBhdGguam9pbihwdWJsaWNhdGlvblJvb3QsIGFjdGl2ZVBvaW50ZXJOYW1lKSwgcHJvamVjdElkLCB0cnVlKVxuXG4gIGlmIChwb2ludGVyKSBhd2FpdCB2ZXJpZnlQdWJsaXNoZWRHZW5lcmF0aW9uKHB1YmxpY2F0aW9uUm9vdCwgcHJvamVjdElkLCBwb2ludGVyLCB0cnVlKVxuICBmb3IgKGNvbnN0IHtqb3VybmFsLCBqb3VybmFsUGF0aH0gb2Ygam91cm5hbHMpIHtcbiAgICBjb25zdCBjYW5kaWRhdGVQYXRoID0gb3duZWRQYXRoKHBhdGguam9pbihwdWJsaWNhdGlvblJvb3QsIGdlbmVyYXRpb25zTmFtZSksIGpvdXJuYWwuZ2VuZXJhdGlvbklkLCBwcm9qZWN0SWQpXG4gICAgY29uc3QgdGVtcG9yYXJ5UG9pbnRlclBhdGggPSBwYXRoLmpvaW4ocHVibGljYXRpb25Sb290LCBqb3VybmFsLnRlbXBQb2ludGVyKVxuICAgIGNvbnN0IGNvbW1pdHRlZCA9IHBvaW50ZXI/LmdlbmVyYXRpb25JZCA9PSBqb3VybmFsLmdlbmVyYXRpb25JZFxuICAgIGNvbnN0IGNhbmRpZGF0ZU93bmVkID0gam91cm5hbC52ZXJzaW9uID09IDFcblxuICAgIGlmIChjYW5kaWRhdGVPd25lZCAmJiAhY29tbWl0dGVkKSB7XG4gICAgICBjb25zdCBjYW5kaWRhdGVTdGF0dXMgPSBhd2FpdCBvcHRpb25hbFN0YXR1cyhjYW5kaWRhdGVQYXRoLCBwcm9qZWN0SWQsIFwiY2FuZGlkYXRlIGdlbmVyYXRpb25cIilcblxuICAgICAgaWYgKGNhbmRpZGF0ZVN0YXR1cykge1xuICAgICAgICBpZiAoIWNhbmRpZGF0ZVN0YXR1cy5pc0RpcmVjdG9yeSgpIHx8IGNhbmRpZGF0ZVN0YXR1cy5pc1N5bWJvbGljTGluaygpKSB7XG4gICAgICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fUkVDT1ZFUllfRkFJTEVEXCIsIHByb2plY3RJZCxcbiAgICAgICAgICAgIFwiSm91cm5hbC1vd25lZCBjYW5kaWRhdGUgaXMgbm90IGEgcmVhbCBkaXJlY3RvcnkuXCIpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgdGVtcG9yYXJ5U3RhdHVzID0gYXdhaXQgb3B0aW9uYWxTdGF0dXModGVtcG9yYXJ5UG9pbnRlclBhdGgsIHByb2plY3RJZCwgXCJ0ZW1wb3JhcnkgcG9pbnRlclwiKVxuXG4gICAgaWYgKHRlbXBvcmFyeVN0YXR1cykge1xuICAgICAgaWYgKCF0ZW1wb3JhcnlTdGF0dXMuaXNGaWxlKCkgfHwgdGVtcG9yYXJ5U3RhdHVzLmlzU3ltYm9saWNMaW5rKCkpIHtcbiAgICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fUkVDT1ZFUllfRkFJTEVEXCIsIHByb2plY3RJZCxcbiAgICAgICAgICBcIkpvdXJuYWwtb3duZWQgdGVtcG9yYXJ5IHBvaW50ZXIgaXMgbm90IGEgcmVndWxhciBmaWxlLlwiKVxuICAgICAgfVxuICAgIH1cbiAgICBhd2FpdCByZW1vdmVKb3VybmFsT3duZWRTdGF0ZSh7XG4gICAgICAuLi4oY2FuZGlkYXRlT3duZWQgJiYgIWNvbW1pdHRlZCA/IHtjYW5kaWRhdGVQYXRofSA6IHt9KSxcbiAgICAgIGpvdXJuYWxQYXRoLFxuICAgICAgcHJvamVjdElkLFxuICAgICAgcHVibGljYXRpb25Sb290LFxuICAgICAgcHVibGlzaGVyLFxuICAgICAgdGVtcG9yYXJ5UG9pbnRlclBhdGhcbiAgICB9KVxuICB9XG59XG5cbi8qKlxuICogUmVhZHMgYW5kIHZhbGlkYXRlcyBldmVyeSByZWNvdmVyeSBqb3VybmFsIHdpdGhvdXQgY2hhbmdpbmcgcHVibGljYXRpb24gc3RhdGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gcHVibGljYXRpb25Sb290IC0gUHVibGljYXRpb24gcm9vdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9qZWN0SWQgLSBQcm9qZWN0IGlkZW50aXR5LlxuICogQHJldHVybnMge1Byb21pc2U8cmVhZG9ubHkge2pvdXJuYWw6IFB1YmxpY2F0aW9uSm91cm5hbCwgam91cm5hbFBhdGg6IHN0cmluZ31bXT59IE9yZGVyZWQgam91cm5hbHMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlYWRQdWJsaWNhdGlvbkpvdXJuYWxzKHB1YmxpY2F0aW9uUm9vdCwgcHJvamVjdElkKSB7XG4gIGNvbnN0IGpvdXJuYWxEaXJlY3RvcnkgPSBwYXRoLmpvaW4ocHVibGljYXRpb25Sb290LCBqb3VybmFsTmFtZSlcbiAgbGV0IGVudHJpZXNcblxuICB0cnkge1xuICAgIGVudHJpZXMgPSBhd2FpdCByZWFkZGlyKGpvdXJuYWxEaXJlY3RvcnkpXG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fUkVDT1ZFUllfRkFJTEVEXCIsIHByb2plY3RJZCxcbiAgICAgIFwiUHVibGljYXRpb24gam91cm5hbCBkaXJlY3RvcnkgY291bGQgbm90IGJlIGluc3BlY3RlZC5cIiwgZXJyb3IpXG4gIH1cbiAgZW50cmllcy5zb3J0KGNvbXBhcmVTdHJpbmdzKVxuICAvKiogQHR5cGUge3tqb3VybmFsOiBQdWJsaWNhdGlvbkpvdXJuYWwsIGpvdXJuYWxQYXRoOiBzdHJpbmd9W119ICovXG4gIGNvbnN0IGpvdXJuYWxzID0gW11cblxuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICBpZiAoIWVudHJ5LmVuZHNXaXRoKFwiLmpzb25cIikgfHwgIWdlbmVyYXRpb25QYXR0ZXJuLnRlc3QoZW50cnkuc2xpY2UoMCwgLTUpKSkge1xuICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fUkVDT1ZFUllfRkFJTEVEXCIsIHByb2plY3RJZCxcbiAgICAgICAgXCJQdWJsaWNhdGlvbiBqb3VybmFsIGNvbnRhaW5zIGFuIHVucmVjb2duaXplZCBlbnRyeS5cIilcbiAgICB9XG4gICAgY29uc3Qgam91cm5hbFBhdGggPSBwYXRoLmpvaW4oam91cm5hbERpcmVjdG9yeSwgZW50cnkpXG4gICAgbGV0IGpvdXJuYWxcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBzdGF0dXMgPSBhd2FpdCBsc3RhdChqb3VybmFsUGF0aClcblxuICAgICAgaWYgKCFzdGF0dXMuaXNGaWxlKCkgfHwgc3RhdHVzLmlzU3ltYm9saWNMaW5rKCkpIHtcbiAgICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fUkVDT1ZFUllfRkFJTEVEXCIsIHByb2plY3RJZCxcbiAgICAgICAgICBcIlB1YmxpY2F0aW9uIGpvdXJuYWwgZW50cnkgbXVzdCBiZSBhIHJlZ3VsYXIgZmlsZS5cIilcbiAgICAgIH1cbiAgICAgIGpvdXJuYWwgPSBKU09OLnBhcnNlKGF3YWl0IHJlYWRGaWxlKGpvdXJuYWxQYXRoLCBcInV0ZjhcIikpXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFNlbWFudGlmb2xkRGlhZ25vc3RpYykgdGhyb3cgZXJyb3JcbiAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX1JFQ09WRVJZX0ZBSUxFRFwiLCBwcm9qZWN0SWQsXG4gICAgICAgIFwiUHVibGljYXRpb24gam91cm5hbCBlbnRyeSBpcyBub3QgdmFsaWQgSlNPTi5cIiwgZXJyb3IpXG4gICAgfVxuICAgIGlmICghaXNQdWJsaWNhdGlvbkpvdXJuYWwoam91cm5hbCkgfHwgam91cm5hbC5wcm9qZWN0SWQgIT0gcHJvamVjdElkIHx8IGAke2pvdXJuYWwuZ2VuZXJhdGlvbklkfS5qc29uYCAhPSBlbnRyeSkge1xuICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fUkVDT1ZFUllfRkFJTEVEXCIsIHByb2plY3RJZCxcbiAgICAgICAgXCJQdWJsaWNhdGlvbiBqb3VybmFsIGVudHJ5IGRvZXMgbm90IG1hdGNoIHRoZSB2ZXJzaW9uZWQgcHJvamVjdCBjb250cmFjdC5cIilcbiAgICB9XG4gICAgam91cm5hbHMucHVzaCh7am91cm5hbCwgam91cm5hbFBhdGh9KVxuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUoam91cm5hbHMpXG59XG5cbi8qKlxuICogUmVwb3J0cyBjb21taXR0ZWQgY2xlYW51cCBzdGF0ZSB3aGlsZSBmYWlsaW5nIGNsb3NlZCBvbiBldmVyeSBqb3VybmFsIGVudHJ5LlxuICogQHBhcmFtIHtzdHJpbmd9IHB1YmxpY2F0aW9uUm9vdCAtIFB1YmxpY2F0aW9uIHJvb3QuXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvamVjdElkIC0gUHJvamVjdCBpZGVudGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBnZW5lcmF0aW9uSWQgLSBQb2ludGVyLXNlbGVjdGVkIGdlbmVyYXRpb24gaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxib29sZWFuPn0gV2hldGhlciBjb21taXR0ZWQgY2xlYW51cCByZW1haW5zLlxuICovXG5hc3luYyBmdW5jdGlvbiBoYXNDb21taXR0ZWRDbGVhbnVwSm91cm5hbChwdWJsaWNhdGlvblJvb3QsIHByb2plY3RJZCwgZ2VuZXJhdGlvbklkKSB7XG4gIGNvbnN0IGpvdXJuYWxzID0gYXdhaXQgcmVhZFB1YmxpY2F0aW9uSm91cm5hbHMocHVibGljYXRpb25Sb290LCBwcm9qZWN0SWQpXG5cbiAgcmV0dXJuIGpvdXJuYWxzLnNvbWUoKHtqb3VybmFsfSkgPT4gam91cm5hbC5nZW5lcmF0aW9uSWQgPT0gZ2VuZXJhdGlvbklkKVxufVxuXG4vKipcbiAqIFJlbW92ZXMgcHJvdmVuIGpvdXJuYWwtb3duZWQgc3RhdGUgYW5kIGR1cmFibHkgc3luY2hyb25pemVzIGVhY2ggcGFyZW50IGJlZm9yZSBkaXNjYXJkaW5nIGl0cyBvd25lcnNoaXAgcHJvb2YuXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0aW9ucyAtIEV4YWN0IGNsZWFudXAgc3RhdGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gW29wdGlvbnMuY2FuZGlkYXRlUGF0aF0gLSBQcm92ZW4gY2FuZGlkYXRlIGdlbmVyYXRpb24gcGF0aC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0aW9ucy50ZW1wb3JhcnlQb2ludGVyUGF0aF0gLSBQcm92ZW4gdGVtcG9yYXJ5IHBvaW50ZXIgcGF0aC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0aW9ucy5qb3VybmFsUGF0aF0gLSBPd25lcnNoaXAgam91cm5hbCBwYXRoLlxuICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMucHJvamVjdElkIC0gUHJvamVjdCBpZGVudGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLnB1YmxpY2F0aW9uUm9vdCAtIFB1YmxpY2F0aW9uIHJvb3QuXG4gKiBAcGFyYW0ge0dlbmVyYXRlZEFydGlmYWN0UHVibGlzaGVyfSBvcHRpb25zLnB1Ymxpc2hlciAtIEFjdGl2ZSBwdWJsaXNoZXIuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQ29tcGxldGlvbi5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVtb3ZlSm91cm5hbE93bmVkU3RhdGUoe2NhbmRpZGF0ZVBhdGgsIGpvdXJuYWxQYXRoLCBwcm9qZWN0SWQsIHB1YmxpY2F0aW9uUm9vdCwgcHVibGlzaGVyLCB0ZW1wb3JhcnlQb2ludGVyUGF0aH0pIHtcbiAgdHJ5IHtcbiAgICBpZiAoY2FuZGlkYXRlUGF0aCkge1xuICAgICAgYXdhaXQgcm0oY2FuZGlkYXRlUGF0aCwge2ZvcmNlOiB0cnVlLCByZWN1cnNpdmU6IHRydWV9KVxuICAgICAgb2JzZXJ2ZVB1YmxpY2F0aW9uRmlsZXN5c3RlbU9wZXJhdGlvbihwdWJsaXNoZXIsIFwicmVtb3ZlLWNhbmRpZGF0ZVwiKVxuICAgICAgYXdhaXQgc3luY0RpcmVjdG9yeShwYXRoLmpvaW4ocHVibGljYXRpb25Sb290LCBnZW5lcmF0aW9uc05hbWUpKVxuICAgICAgb2JzZXJ2ZVB1YmxpY2F0aW9uRmlsZXN5c3RlbU9wZXJhdGlvbihwdWJsaXNoZXIsIFwic3luYy1jYW5kaWRhdGUtcGFyZW50XCIpXG4gICAgfVxuICAgIGlmICh0ZW1wb3JhcnlQb2ludGVyUGF0aCkge1xuICAgICAgYXdhaXQgcm0odGVtcG9yYXJ5UG9pbnRlclBhdGgsIHtmb3JjZTogdHJ1ZX0pXG4gICAgICBvYnNlcnZlUHVibGljYXRpb25GaWxlc3lzdGVtT3BlcmF0aW9uKHB1Ymxpc2hlciwgXCJyZW1vdmUtdGVtcG9yYXJ5LXBvaW50ZXJcIilcbiAgICAgIGF3YWl0IHN5bmNEaXJlY3RvcnkocHVibGljYXRpb25Sb290KVxuICAgICAgb2JzZXJ2ZVB1YmxpY2F0aW9uRmlsZXN5c3RlbU9wZXJhdGlvbihwdWJsaXNoZXIsIFwic3luYy10ZW1wb3JhcnktcG9pbnRlci1wYXJlbnRcIilcbiAgICB9XG4gICAgaWYgKGpvdXJuYWxQYXRoKSB7XG4gICAgICByZWFjaFB1YmxpY2F0aW9uQm91bmRhcnkocHVibGlzaGVyLCBcImJlZm9yZS1qb3VybmFsLXJlbW92ZVwiKVxuICAgICAgYXdhaXQgcm0oam91cm5hbFBhdGgpXG4gICAgICBvYnNlcnZlUHVibGljYXRpb25GaWxlc3lzdGVtT3BlcmF0aW9uKHB1Ymxpc2hlciwgXCJyZW1vdmUtam91cm5hbFwiKVxuICAgICAgYXdhaXQgc3luY0RpcmVjdG9yeShwYXRoLmRpcm5hbWUoam91cm5hbFBhdGgpKVxuICAgICAgb2JzZXJ2ZVB1YmxpY2F0aW9uRmlsZXN5c3RlbU9wZXJhdGlvbihwdWJsaXNoZXIsIFwic3luYy1qb3VybmFsLXBhcmVudFwiKVxuICAgIH1cbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBTZW1hbnRpZm9sZERpYWdub3N0aWMpIHRocm93IGVycm9yXG4gICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fUkVDT1ZFUllfRkFJTEVEXCIsIHByb2plY3RJZCxcbiAgICAgIFwiSm91cm5hbC1vd25lZCBwdWJsaWNhdGlvbiBzdGF0ZSBjb3VsZCBub3QgYmUgZHVyYWJseSByZWNvbmNpbGVkLlwiLCBlcnJvcilcbiAgfVxufVxuXG4vKipcbiAqIFJlYWRzIG9wdGlvbmFsIG1ldGFkYXRhIHdpdGhvdXQgZm9sbG93aW5nIHN5bWJvbGljIGxpbmtzLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gRXhhY3Qgb3duZWQgcGF0aC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9qZWN0SWQgLSBQcm9qZWN0IGlkZW50aXR5LlxuICogQHBhcmFtIHtzdHJpbmd9IHN1YmplY3QgLSBTdGFibGUgc3ViamVjdCBkZXNjcmlwdGlvbi5cbiAqIEByZXR1cm5zIHtQcm9taXNlPGltcG9ydChcIm5vZGU6ZnNcIikuU3RhdHMgfCBudWxsPn0gU3RhdHVzIG9yIGFic2VuY2UuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIG9wdGlvbmFsU3RhdHVzKGZpbGVuYW1lLCBwcm9qZWN0SWQsIHN1YmplY3QpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgbHN0YXQoZmlsZW5hbWUpXG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKGlzRXJyb3JDb2RlKGVycm9yLCBcIkVOT0VOVFwiKSkgcmV0dXJuIG51bGxcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9SRUNPVkVSWV9GQUlMRURcIiwgcHJvamVjdElkLFxuICAgICAgYEpvdXJuYWwtb3duZWQgJHtzdWJqZWN0fSBjb3VsZCBub3QgYmUgaW5zcGVjdGVkLmAsIGVycm9yKVxuICB9XG59XG5cbi8qKlxuICogVmFsaWRhdGVzIGFuZCBzbmFwc2hvdHMgb25lIHB1YmxpY2F0aW9uIHJlcXVlc3QgYmVmb3JlIHN0YWdpbmcuXG4gKiBAcGFyYW0ge3Vua25vd259IHJlcXVlc3QgLSBSZXF1ZXN0IGNhbmRpZGF0ZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9qZWN0SWQgLSBQcm9qZWN0IGRpYWdub3N0aWMgaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7VmFsaWRhdGVkUHVibGljYXRpb25SZXF1ZXN0fSBWYWxpZGF0ZWQgcmVxdWVzdC5cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVQdWJsaWNhdGlvblJlcXVlc3QocmVxdWVzdCwgcHJvamVjdElkKSB7XG4gIGlmICghaXNQbGFpbk9iamVjdChyZXF1ZXN0KSkge1xuICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIklOVkFMSURfUFVCTElDQVRJT05fUkVRVUVTVFwiLCBwcm9qZWN0SWQsXG4gICAgICBcIlB1YmxpY2F0aW9uIHJlcXVpcmVzIGEgdW5pcXVlIGdlbmVyYXRpb24gSUQgYW5kIGEgbm9uLWVtcHR5IG9yZGVyZWQgdGFyZ2V0IGFycmF5LlwiKVxuICB9XG4gIGNvbnN0IGdlbmVyYXRpb25JZCA9IHJlcXVlc3QuZ2VuZXJhdGlvbklkXG4gIGNvbnN0IHJlcXVlc3RlZFRhcmdldHMgPSByZXF1ZXN0LnRhcmdldHNcblxuICBpZiAodHlwZW9mIGdlbmVyYXRpb25JZCAhPSBcInN0cmluZ1wiIHx8ICFnZW5lcmF0aW9uUGF0dGVybi50ZXN0KGdlbmVyYXRpb25JZCkgfHxcbiAgICAhaXNEZW5zZUFycmF5KHJlcXVlc3RlZFRhcmdldHMpIHx8IHJlcXVlc3RlZFRhcmdldHMubGVuZ3RoID09IDApIHtcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJJTlZBTElEX1BVQkxJQ0FUSU9OX1JFUVVFU1RcIiwgcHJvamVjdElkLFxuICAgICAgXCJQdWJsaWNhdGlvbiByZXF1aXJlcyBhIHVuaXF1ZSBnZW5lcmF0aW9uIElEIGFuZCBhIG5vbi1lbXB0eSBvcmRlcmVkIHRhcmdldCBhcnJheS5cIilcbiAgfVxuICAvKiogQHR5cGUge1ZhbGlkYXRlZFB1YmxpY2F0aW9uVGFyZ2V0W119ICovXG4gIGNvbnN0IHRhcmdldHMgPSBbXVxuICBjb25zdCB0YXJnZXRJZHMgPSBuZXcgU2V0KClcbiAgLyoqIEB0eXBlIHtzdHJpbmdbXX0gKi9cbiAgY29uc3QgcHJvamVjdGlvbnMgPSBbXVxuICAvKiogQHR5cGUge3N0cmluZ1tdfSAqL1xuICBjb25zdCBjb21wbGV0ZUFydGlmYWN0UGF0aHMgPSBbXVxuXG4gIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCByZXF1ZXN0ZWRUYXJnZXRzLmxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgIGNvbnN0IHRhcmdldCA9IHJlcXVlc3RlZFRhcmdldHNbaW5kZXhdXG5cbiAgICBpZiAoIWlzUGxhaW5PYmplY3QodGFyZ2V0KSkge1xuICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiSU5WQUxJRF9QVUJMSUNBVElPTl9SRVFVRVNUXCIsIHByb2plY3RJZCxcbiAgICAgICAgYFRhcmdldCAke2luZGV4fSByZXF1aXJlcyBhIHN0YWJsZSBsb3dlcmNhc2UgaWRlbnRpdHkuYClcbiAgICB9XG4gICAgY29uc3QgdGFyZ2V0SWQgPSB0YXJnZXQuaWRcbiAgICBjb25zdCByb2xlID0gdGFyZ2V0LnJvbGVcbiAgICBjb25zdCBzb3VyY2VQcm9qZWN0aW9uID0gdGFyZ2V0LnNvdXJjZVByb2plY3Rpb25cbiAgICBjb25zdCBidWlsZFByb2plY3Rpb24gPSB0YXJnZXQuYnVpbGRQcm9qZWN0aW9uXG4gICAgY29uc3QgYXJ0aWZhY3RTZXRDYW5kaWRhdGUgPSB0YXJnZXQuYXJ0aWZhY3RTZXRcbiAgICBjb25zdCB2YWxpZGF0b3JzQ2FuZGlkYXRlID0gdGFyZ2V0LnZhbGlkYXRvcnNcblxuICAgIGlmICh0eXBlb2YgdGFyZ2V0SWQgIT0gXCJzdHJpbmdcIiB8fCAhaWRlbnRpdHlQYXR0ZXJuLnRlc3QodGFyZ2V0SWQpKSB7XG4gICAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJJTlZBTElEX1BVQkxJQ0FUSU9OX1JFUVVFU1RcIiwgcHJvamVjdElkLFxuICAgICAgICBgVGFyZ2V0ICR7aW5kZXh9IHJlcXVpcmVzIGEgc3RhYmxlIGxvd2VyY2FzZSBpZGVudGl0eS5gKVxuICAgIH1cbiAgICBpZiAodHlwZW9mIHJvbGUgIT0gXCJzdHJpbmdcIiB8fCAhdGFyZ2V0Um9sZXMuaGFzKHJvbGUpKSB7XG4gICAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJJTlZBTElEX1BVQkxJQ0FUSU9OX1JFUVVFU1RcIiwgcHJvamVjdElkLFxuICAgICAgICBgVGFyZ2V0ICcke3RhcmdldElkfScgcmVxdWlyZXMgYW4gZXhwbGljaXQgbGFuZ3VhZ2UtbmV1dHJhbCByb2xlLmApXG4gICAgfVxuXG4gICAgaWYgKHRhcmdldElkcy5oYXModGFyZ2V0SWQpKSB7XG4gICAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9QQVRIX0NPTExJU0lPTlwiLCBwcm9qZWN0SWQsIGBEdXBsaWNhdGUgdGFyZ2V0IGlkZW50aXR5ICcke3RhcmdldElkfScuYClcbiAgICB9XG4gICAgdGFyZ2V0SWRzLmFkZCh0YXJnZXRJZClcbiAgICBpZiAoIWlzU2FmZUFydGlmYWN0UGF0aChzb3VyY2VQcm9qZWN0aW9uKSB8fCAhaXNTYWZlQXJ0aWZhY3RQYXRoKGJ1aWxkUHJvamVjdGlvbikpIHtcbiAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIklOVkFMSURfUFVCTElDQVRJT05fUFJPSkVDVElPTlwiLCBwcm9qZWN0SWQsXG4gICAgICAgIGBUYXJnZXQgJyR7dGFyZ2V0SWR9JyByZXF1aXJlcyBjYW5vbmljYWwgcmVsYXRpdmUgc291cmNlIGFuZCBidWlsZCBwcm9qZWN0aW9ucy5gKVxuICAgIH1cbiAgICBwcm9qZWN0aW9ucy5wdXNoKHNvdXJjZVByb2plY3Rpb24sIGJ1aWxkUHJvamVjdGlvbilcbiAgICBsZXQgYXJ0aWZhY3RTZXRcblxuICAgIHRyeSB7XG4gICAgICBhcnRpZmFjdFNldCA9IGNyZWF0ZUdlbmVyYXRlZEFydGlmYWN0U2V0KGFydGlmYWN0U2V0Q2FuZGlkYXRlKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJJTlZBTElEX1BVQkxJQ0FUSU9OX1JFUVVFU1RcIiwgcHJvamVjdElkLFxuICAgICAgICBgVGFyZ2V0ICcke3RhcmdldElkfScgZG9lcyBub3QgY29udGFpbiBhIHZhbGlkIGdlbmVyYXRlZCBhcnRpZmFjdCBzZXQuYCwgZXJyb3IpXG4gICAgfVxuICAgIGNvbnN0IHZhbGlkYXRvcnMgPSB2YWxpZGF0b3JzQ2FuZGlkYXRlID09PSB1bmRlZmluZWQgPyBbXSA6IHZhbGlkYXRvcnNDYW5kaWRhdGVcblxuICAgIGlmICghaXNEZW5zZUFycmF5KHZhbGlkYXRvcnMpKSB7XG4gICAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJJTlZBTElEX1BVQkxJQ0FUSU9OX1JFUVVFU1RcIiwgcHJvamVjdElkLFxuICAgICAgICBgVGFyZ2V0ICcke3RhcmdldElkfScgdmFsaWRhdG9ycyBtdXN0IGJlIGEgZGVuc2UgZnVuY3Rpb24gYXJyYXkuYClcbiAgICB9XG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlB1YmxpY2F0aW9uVmFsaWRhdG9yW119ICovXG4gICAgY29uc3QgdmFsaWRhdGVkVmFsaWRhdG9ycyA9IFtdXG5cbiAgICBmb3IgKGxldCB2YWxpZGF0b3JJbmRleCA9IDA7IHZhbGlkYXRvckluZGV4IDwgdmFsaWRhdG9ycy5sZW5ndGg7IHZhbGlkYXRvckluZGV4ICs9IDEpIHtcbiAgICAgIGNvbnN0IHZhbGlkYXRvciA9IHZhbGlkYXRvcnNbdmFsaWRhdG9ySW5kZXhdXG5cbiAgICAgIGlmICh0eXBlb2YgdmFsaWRhdG9yICE9IFwiZnVuY3Rpb25cIikge1xuICAgICAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJJTlZBTElEX1BVQkxJQ0FUSU9OX1JFUVVFU1RcIiwgcHJvamVjdElkLFxuICAgICAgICAgIGBUYXJnZXQgJyR7dGFyZ2V0SWR9JyB2YWxpZGF0b3JzIG11c3QgYmUgYSBkZW5zZSBmdW5jdGlvbiBhcnJheS5gKVxuICAgICAgfVxuICAgICAgdmFsaWRhdGVkVmFsaWRhdG9ycy5wdXNoKC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5QdWJsaWNhdGlvblZhbGlkYXRvcn0gKi8gKHZhbGlkYXRvcikpXG4gICAgfVxuICAgIGNvbnN0IGFydGlmYWN0Q29uZmxpY3QgPSBmaW5kUG9ydGFibGVBcnRpZmFjdFBhdGhDb25mbGljdChhcnRpZmFjdFNldC5hcnRpZmFjdHMubWFwKCh7cGF0aDogYXJ0aWZhY3RQYXRofSkgPT4gYXJ0aWZhY3RQYXRoKSlcblxuICAgIGlmIChhcnRpZmFjdENvbmZsaWN0KSB7XG4gICAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9QQVRIX0NPTExJU0lPTlwiLCBwcm9qZWN0SWQsXG4gICAgICAgIGBUYXJnZXQgJyR7dGFyZ2V0SWR9JyBhcnRpZmFjdCBwYXRocyBoYXZlIGEgcG9ydGFibGUgJHthcnRpZmFjdENvbmZsaWN0LmtpbmR9IGNvbmZsaWN0LmApXG4gICAgfVxuICAgIGZvciAoY29uc3QgYXJ0aWZhY3Qgb2YgYXJ0aWZhY3RTZXQuYXJ0aWZhY3RzKSB7XG4gICAgICBjb21wbGV0ZUFydGlmYWN0UGF0aHMucHVzaChgJHtzb3VyY2VQcm9qZWN0aW9ufS8ke2FydGlmYWN0LnBhdGh9YClcbiAgICB9XG4gICAgdGFyZ2V0cy5wdXNoKE9iamVjdC5mcmVlemUoe1xuICAgICAgYXJ0aWZhY3RTZXQsXG4gICAgICBidWlsZFByb2plY3Rpb24sXG4gICAgICBpZDogdGFyZ2V0SWQsXG4gICAgICByb2xlOiAvKiogQHR5cGUge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuUHVibGljYXRpb25UYXJnZXRSb2xlfSAqLyAocm9sZSksXG4gICAgICBzb3VyY2VQcm9qZWN0aW9uLFxuICAgICAgdmFsaWRhdG9yczogT2JqZWN0LmZyZWV6ZSh2YWxpZGF0ZWRWYWxpZGF0b3JzKVxuICAgIH0pKVxuICB9XG4gIGNvbnN0IHByb2plY3Rpb25Db25mbGljdCA9IGZpbmRQb3J0YWJsZUFydGlmYWN0UGF0aENvbmZsaWN0KHByb2plY3Rpb25zKVxuXG4gIGlmIChwcm9qZWN0aW9uQ29uZmxpY3QpIHtcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9QUk9KRUNUSU9OX09WRVJMQVBcIiwgcHJvamVjdElkLFxuICAgICAgXCJUYXJnZXQgc291cmNlL2J1aWxkIHByb2plY3Rpb25zIG11c3QgYmUgZGlzdGluY3QgYW5kIG5vbi1uZXN0ZWQgdW5kZXIgcG9ydGFibGUgY29tcGFyaXNvbi5cIilcbiAgfVxuICBpZiAoZmluZFBvcnRhYmxlQXJ0aWZhY3RQYXRoQ29uZmxpY3QoWy4uLnByb2plY3Rpb25zLCBcIm1hbmlmZXN0Lmpzb25cIl0pKSB7XG4gICAgcHVibGljYXRpb25GYWlsdXJlKFwiSU5WQUxJRF9QVUJMSUNBVElPTl9QUk9KRUNUSU9OXCIsIHByb2plY3RJZCxcbiAgICAgIFwiVGFyZ2V0IHNvdXJjZS9idWlsZCBwcm9qZWN0aW9ucyBtdXN0IG5vdCBvdmVybGFwIHRoZSBnZW5lcmF0aW9uIG1hbmlmZXN0IHBhdGguXCIpXG4gIH1cbiAgY29uc3QgYXJ0aWZhY3RDb25mbGljdCA9IGZpbmRQb3J0YWJsZUFydGlmYWN0UGF0aENvbmZsaWN0KGNvbXBsZXRlQXJ0aWZhY3RQYXRocylcblxuICBpZiAoYXJ0aWZhY3RDb25mbGljdCkge1xuICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX1BBVEhfQ09MTElTSU9OXCIsIHByb2plY3RJZCxcbiAgICAgIFwiUHJvamVjdGVkIGFydGlmYWN0IHBhdGhzIGNvbGxpZGUgdW5kZXIgcG9ydGFibGUgY29tcGFyaXNvbi5cIilcbiAgfVxuXG4gIHJldHVybiB7Z2VuZXJhdGlvbklkLCB0YXJnZXRzOiBPYmplY3QuZnJlZXplKHRhcmdldHMpfVxufVxuXG4vKipcbiAqIFZlcmlmaWVzIHRoYXQgb25lIHJldGFpbmVkIGltbXV0YWJsZSBnZW5lcmF0aW9uIGV4YWN0bHkgcmVwcmVzZW50cyBhIHZhbGlkYXRvci1mcmVlIHJlcXVlc3QuXG4gKiBUaGUgcmV0YWluZWQgZGlyZWN0b3J5IGlzIG5ldmVyIG1vZGlmaWVkIG9yIHJlbW92ZWQgb24gZWl0aGVyIHN1Y2Nlc3Mgb3IgZmFpbHVyZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBnZW5lcmF0aW9uUGF0aCAtIEV4aXN0aW5nIGdlbmVyYXRpb24gcGF0aC5cbiAqIEBwYXJhbSB7VmFsaWRhdGVkUHVibGljYXRpb25SZXF1ZXN0fSByZXF1ZXN0IC0gVmFsaWRhdGVkIGNhbmRpZGF0ZSByZXF1ZXN0LlxuICogQHBhcmFtIHtzdHJpbmd9IHByb2plY3RJZCAtIFByb2plY3QgZGlhZ25vc3RpYyBpZGVudGl0eS5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHttYW5pZmVzdDogaW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5HZW5lcmF0aW9uTWFuaWZlc3QsIG1hbmlmZXN0Qnl0ZXM6IEJ1ZmZlcn0+fSBFeGFjdCByZXRhaW5lZCBtYW5pZmVzdC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gdmVyaWZ5UmV0YWluZWRHZW5lcmF0aW9uKGdlbmVyYXRpb25QYXRoLCByZXF1ZXN0LCBwcm9qZWN0SWQpIHtcbiAgaWYgKHJlcXVlc3QudGFyZ2V0cy5zb21lKHRhcmdldCA9PiB0YXJnZXQudmFsaWRhdG9ycy5sZW5ndGggIT0gMCkpIHtcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9VTk9XTkVEX0NPTkZMSUNUXCIsIHByb2plY3RJZCxcbiAgICAgIFwiUmV0YWluZWQgZ2VuZXJhdGlvbnMgY2FuIGJlIHJlYWN0aXZhdGVkIG9ubHkgZm9yIGV4YWN0IHZhbGlkYXRvci1mcmVlIGNhbmRpZGF0ZXMuXCIpXG4gIH1cbiAgY29uc3QgdGFyZ2V0TWFuaWZlc3RzID0gcmVxdWVzdC50YXJnZXRzLm1hcCh0YXJnZXQgPT4gT2JqZWN0LmZyZWV6ZSh7XG4gICAgYXJ0aWZhY3RzOiBPYmplY3QuZnJlZXplKHRhcmdldC5hcnRpZmFjdFNldC5hcnRpZmFjdHMubWFwKGFydGlmYWN0ID0+IGRlc2NyaWJlR2VuZXJhdGVkQXJ0aWZhY3QoYXJ0aWZhY3QpLm1hbmlmZXN0KSksXG4gICAgYnVpbGRBcnRpZmFjdHM6IE9iamVjdC5mcmVlemUoW10pLFxuICAgIGlkOiB0YXJnZXQuaWQsXG4gICAgLi4uKHRhcmdldC5hcnRpZmFjdFNldC5tZXRhZGF0YSA9PT0gdW5kZWZpbmVkID8ge30gOiB7bWV0YWRhdGE6IHRhcmdldC5hcnRpZmFjdFNldC5tZXRhZGF0YX0pLFxuICAgIHByb2plY3Rpb25zOiBPYmplY3QuZnJlZXplKHtidWlsZDogdGFyZ2V0LmJ1aWxkUHJvamVjdGlvbiwgc291cmNlOiB0YXJnZXQuc291cmNlUHJvamVjdGlvbn0pLFxuICAgIHJvbGU6IHRhcmdldC5yb2xlLFxuICAgIHRhcmdldDogdGFyZ2V0LmFydGlmYWN0U2V0LnRhcmdldFxuICB9KSlcbiAgY29uc3QgY2FuZGlkYXRlID0ge1xuICAgIGdlbmVyYXRpb25JZDogcmVxdWVzdC5nZW5lcmF0aW9uSWQsXG4gICAgcHJvamVjdElkLFxuICAgIHNjaGVtYTogXCJTZW1hbnRpZm9sZEdlbmVyYXRpb25NYW5pZmVzdFwiLFxuICAgIHRhcmdldHM6IHRhcmdldE1hbmlmZXN0cyxcbiAgICB2ZXJzaW9uOiAxXG4gIH1cbiAgY29uc3QgZXhwZWN0ZWRCeXRlcyA9IHNlcmlhbGl6ZUpzb24oY2FuZGlkYXRlKVxuICBjb25zdCBtYW5pZmVzdCA9IHZhbGlkYXRlR2VuZXJhdGlvbk1hbmlmZXN0KEpTT04ucGFyc2UoZXhwZWN0ZWRCeXRlcy50b1N0cmluZyhcInV0ZjhcIikpLCBwcm9qZWN0SWQsIHJlcXVlc3QuZ2VuZXJhdGlvbklkKVxuICBsZXQgbWFuaWZlc3RCeXRlc1xuXG4gIHRyeSB7XG4gICAgbWFuaWZlc3RCeXRlcyA9IGF3YWl0IHJlYWRBbmRTeW5jUmVndWxhckZpbGUocGF0aC5qb2luKGdlbmVyYXRpb25QYXRoLCBcIm1hbmlmZXN0Lmpzb25cIiksIHByb2plY3RJZCxcbiAgICAgIFwiTUFMRk9STUVEX0dFTkVSQVRJT05fTUFOSUZFU1RcIiwgXCJSZXRhaW5lZCBnZW5lcmF0aW9uIG1hbmlmZXN0IG11c3QgYmUgYSByZWd1bGFyIGZpbGUuXCIpXG4gICAgaWYgKCFtYW5pZmVzdEJ5dGVzLmVxdWFscyhleHBlY3RlZEJ5dGVzKSkge1xuICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fVU5PV05FRF9DT05GTElDVFwiLCBwcm9qZWN0SWQsXG4gICAgICAgIFwiUmV0YWluZWQgZ2VuZXJhdGlvbiBkb2VzIG5vdCBleGFjdGx5IG1hdGNoIHRoZSByZXF1ZXN0ZWQgY2FuZGlkYXRlLlwiKVxuICAgIH1cbiAgICBhd2FpdCB2ZXJpZnlNYW5pZmVzdEZpbGVzKGdlbmVyYXRpb25QYXRoLCBtYW5pZmVzdCwgcHJvamVjdElkKVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFNlbWFudGlmb2xkRGlhZ25vc3RpYyAmJiBlcnJvci5jb2RlID09IFwiUFVCTElDQVRJT05fVU5PV05FRF9DT05GTElDVFwiKSB0aHJvdyBlcnJvclxuICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX1VOT1dORURfQ09ORkxJQ1RcIiwgcHJvamVjdElkLFxuICAgICAgXCJSZXRhaW5lZCBnZW5lcmF0aW9uIGNvdWxkIG5vdCBiZSB2ZXJpZmllZCBhcyB0aGUgZXhhY3QgcmVxdWVzdGVkIGNhbmRpZGF0ZS5cIiwgZXJyb3IpXG4gIH1cblxuICByZXR1cm4ge21hbmlmZXN0LCBtYW5pZmVzdEJ5dGVzfVxufVxuXG4vKipcbiAqIFN0YWdlcyBvbmUgdmFsaWRhdGVkIHRhcmdldCBhbmQgaW52b2tlcyBpdHMgb3JkZXJlZCB2YWxpZGF0b3JzLlxuICogQHBhcmFtIHtzdHJpbmd9IGdlbmVyYXRpb25QYXRoIC0gQ2FuZGlkYXRlIGdlbmVyYXRpb24gcGF0aC5cbiAqIEBwYXJhbSB7VmFsaWRhdGVkUHVibGljYXRpb25UYXJnZXR9IHRhcmdldCAtIFZhbGlkYXRlZCB0YXJnZXQuXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvamVjdElkIC0gUHJvamVjdCBkaWFnbm9zdGljIGlkZW50aXR5LlxuICogQHJldHVybnMge1Byb21pc2U8aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5HZW5lcmF0aW9uVGFyZ2V0TWFuaWZlc3Q+fSBUYXJnZXQgbWFuaWZlc3QuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHN0YWdlVGFyZ2V0KGdlbmVyYXRpb25QYXRoLCB0YXJnZXQsIHByb2plY3RJZCkge1xuICBjb25zdCBzb3VyY2VQYXRoID0gb3duZWRQYXRoKGdlbmVyYXRpb25QYXRoLCB0YXJnZXQuc291cmNlUHJvamVjdGlvbiwgcHJvamVjdElkKVxuICBjb25zdCBidWlsZFBhdGggPSBvd25lZFBhdGgoZ2VuZXJhdGlvblBhdGgsIHRhcmdldC5idWlsZFByb2plY3Rpb24sIHByb2plY3RJZClcblxuICBhd2FpdCBta2Rpcihzb3VyY2VQYXRoLCB7bW9kZTogMG83MDAsIHJlY3Vyc2l2ZTogdHJ1ZX0pXG4gIGF3YWl0IG1rZGlyKGJ1aWxkUGF0aCwge21vZGU6IDBvNzAwLCByZWN1cnNpdmU6IHRydWV9KVxuICAvKiogQHR5cGUge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGlvbkFydGlmYWN0TWFuaWZlc3RbXX0gKi9cbiAgY29uc3QgYXJ0aWZhY3RzID0gW11cblxuICBmb3IgKGNvbnN0IGFydGlmYWN0IG9mIHRhcmdldC5hcnRpZmFjdFNldC5hcnRpZmFjdHMpIHtcbiAgICBjb25zdCBmaWxlbmFtZSA9IG93bmVkUGF0aChzb3VyY2VQYXRoLCBhcnRpZmFjdC5wYXRoLCBwcm9qZWN0SWQpXG4gICAgY29uc3QgZGVzY3JpYmVkID0gZGVzY3JpYmVHZW5lcmF0ZWRBcnRpZmFjdChhcnRpZmFjdClcblxuICAgIGF3YWl0IG1rZGlyKHBhdGguZGlybmFtZShmaWxlbmFtZSksIHttb2RlOiAwbzcwMCwgcmVjdXJzaXZlOiB0cnVlfSlcbiAgICB0cnkge1xuICAgICAgYXdhaXQgd3JpdGVTeW5jZWRGaWxlKGZpbGVuYW1lLCBkZXNjcmliZWQuYnl0ZXMsIFwid3hcIilcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgU2VtYW50aWZvbGREaWFnbm9zdGljKSB0aHJvdyBlcnJvclxuICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fU1RBR0VfV1JJVEVfRkFJTEVEXCIsIHByb2plY3RJZCxcbiAgICAgICAgYEdlbmVyYXRlZCBhcnRpZmFjdCAnJHthcnRpZmFjdC5wYXRofScgY291bGQgbm90IGJlIHN0YWdlZC5gLCBlcnJvcilcbiAgICB9XG4gICAgYXJ0aWZhY3RzLnB1c2goZGVzY3JpYmVkLm1hbmlmZXN0KVxuICB9XG5cbiAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlB1YmxpY2F0aW9uQnVpbGRBcnRpZmFjdElucHV0W119ICovXG4gIGNvbnN0IGJ1aWxkRGVzY3JpcHRvcnMgPSBbXVxuICBjb25zdCBjb250ZXh0ID0gT2JqZWN0LmZyZWV6ZSh7YnVpbGRQYXRoLCBzb3VyY2VQYXRoLCB0YXJnZXRJZDogdGFyZ2V0LmlkfSlcblxuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgdGFyZ2V0LnZhbGlkYXRvcnMubGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgbGV0IHByb2R1Y2VkXG5cbiAgICB0cnkge1xuICAgICAgcHJvZHVjZWQgPSBhd2FpdCB0YXJnZXQudmFsaWRhdG9yc1tpbmRleF0oY29udGV4dClcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fVkFMSURBVElPTl9GQUlMRURcIiwgcHJvamVjdElkLFxuICAgICAgICBgVmFsaWRhdG9yICR7aW5kZXh9IGZhaWxlZCBmb3IgdGFyZ2V0ICcke3RhcmdldC5pZH0nLmAsIGVycm9yKVxuICAgIH1cbiAgICBpZiAocHJvZHVjZWQgPT09IHVuZGVmaW5lZCkgY29udGludWVcbiAgICBpZiAoIWlzRGVuc2VBcnJheShwcm9kdWNlZCkpIHtcbiAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX1ZBTElEQVRJT05fRkFJTEVEXCIsIHByb2plY3RJZCxcbiAgICAgICAgYFZhbGlkYXRvciAke2luZGV4fSByZXR1cm5lZCBpbnZhbGlkIGJ1aWxkLWFydGlmYWN0IG1ldGFkYXRhIGZvciB0YXJnZXQgJyR7dGFyZ2V0LmlkfScuYClcbiAgICB9XG4gICAgZm9yIChjb25zdCBkZXNjcmlwdG9yIG9mIHByb2R1Y2VkKSB7XG4gICAgICBidWlsZERlc2NyaXB0b3JzLnB1c2godmFsaWRhdGVCdWlsZEFydGlmYWN0RGVzY3JpcHRvcihkZXNjcmlwdG9yLCB0YXJnZXQuaWQsIHByb2plY3RJZCkpXG4gICAgfVxuICB9XG5cbiAgY29uc3QgZGVzY3JpcHRvckNvbmZsaWN0ID0gZmluZFBvcnRhYmxlQXJ0aWZhY3RQYXRoQ29uZmxpY3QoYnVpbGREZXNjcmlwdG9ycy5tYXAoKHtwYXRoOiBhcnRpZmFjdFBhdGh9KSA9PiBhcnRpZmFjdFBhdGgpKVxuXG4gIGlmIChkZXNjcmlwdG9yQ29uZmxpY3QpIHtcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9QQVRIX0NPTExJU0lPTlwiLCBwcm9qZWN0SWQsXG4gICAgICBgVGFyZ2V0ICcke3RhcmdldC5pZH0nIGJ1aWxkIGFydGlmYWN0cyBoYXZlIGEgcG9ydGFibGUgJHtkZXNjcmlwdG9yQ29uZmxpY3Qua2luZH0gY29uZmxpY3QuYClcbiAgfVxuICBjb25zdCBzdGFnZWRCdWlsZEZpbGVzID0gYXdhaXQgbGlzdFJlZ3VsYXJGaWxlcyhidWlsZFBhdGgsIHByb2plY3RJZClcbiAgY29uc3QgZGVjbGFyZWQgPSBuZXcgU2V0KGJ1aWxkRGVzY3JpcHRvcnMubWFwKCh7cGF0aDogYXJ0aWZhY3RQYXRofSkgPT4gYXJ0aWZhY3RQYXRoKSlcblxuICBpZiAoc3RhZ2VkQnVpbGRGaWxlcy5sZW5ndGggIT0gZGVjbGFyZWQuc2l6ZSB8fCBzdGFnZWRCdWlsZEZpbGVzLnNvbWUoZmlsZW5hbWUgPT4gIWRlY2xhcmVkLmhhcyhmaWxlbmFtZSkpKSB7XG4gICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fVkFMSURBVElPTl9GQUlMRURcIiwgcHJvamVjdElkLFxuICAgICAgYFRhcmdldCAnJHt0YXJnZXQuaWR9JyB2YWxpZGF0b3JzIG11c3QgZGVjbGFyZSBldmVyeSBzdGFnZWQgYnVpbGQgYXJ0aWZhY3QgZXhhY3RseSBvbmNlLmApXG4gIH1cbiAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRpb25CdWlsZEFydGlmYWN0TWFuaWZlc3RbXX0gKi9cbiAgY29uc3QgZmluYWxpemVkQnVpbGRBcnRpZmFjdHMgPSBbXVxuXG4gIGZvciAoY29uc3QgZGVzY3JpcHRvciBvZiBidWlsZERlc2NyaXB0b3JzKSB7XG4gICAgY29uc3QgYnl0ZXMgPSBhd2FpdCByZWFkQW5kU3luY1JlZ3VsYXJGaWxlKG93bmVkUGF0aChidWlsZFBhdGgsIGRlc2NyaXB0b3IucGF0aCwgcHJvamVjdElkKSwgcHJvamVjdElkLFxuICAgICAgXCJQVUJMSUNBVElPTl9TVEFHRV9IQVNIX01JU01BVENIXCIsIGBCdWlsZCBhcnRpZmFjdCAnJHtkZXNjcmlwdG9yLnBhdGh9JyBpcyBub3QgYSBzdGFibGUgcmVndWxhciBmaWxlLmApXG5cbiAgICBmaW5hbGl6ZWRCdWlsZEFydGlmYWN0cy5wdXNoKE9iamVjdC5mcmVlemUoe1xuICAgICAgYnl0ZUxlbmd0aDogYnl0ZXMuYnl0ZUxlbmd0aCxcbiAgICAgIGhhc2g6IE9iamVjdC5mcmVlemUoe2FsZ29yaXRobTogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwic2hhMjU2XCIpLCB2YWx1ZTogc2hhMjU2KGJ5dGVzKX0pLFxuICAgICAgbWVkaWFUeXBlOiBkZXNjcmlwdG9yLm1lZGlhVHlwZSxcbiAgICAgIHBhdGg6IGRlc2NyaXB0b3IucGF0aCxcbiAgICAgIHJvbGU6IGRlc2NyaXB0b3Iucm9sZVxuICAgIH0pKVxuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUoe1xuICAgIGFydGlmYWN0czogT2JqZWN0LmZyZWV6ZShhcnRpZmFjdHMpLFxuICAgIGJ1aWxkQXJ0aWZhY3RzOiBPYmplY3QuZnJlZXplKGZpbmFsaXplZEJ1aWxkQXJ0aWZhY3RzKSxcbiAgICBpZDogdGFyZ2V0LmlkLFxuICAgIC4uLih0YXJnZXQuYXJ0aWZhY3RTZXQubWV0YWRhdGEgPT09IHVuZGVmaW5lZCA/IHt9IDoge21ldGFkYXRhOiB0YXJnZXQuYXJ0aWZhY3RTZXQubWV0YWRhdGF9KSxcbiAgICBwcm9qZWN0aW9uczogT2JqZWN0LmZyZWV6ZSh7YnVpbGQ6IHRhcmdldC5idWlsZFByb2plY3Rpb24sIHNvdXJjZTogdGFyZ2V0LnNvdXJjZVByb2plY3Rpb259KSxcbiAgICByb2xlOiB0YXJnZXQucm9sZSxcbiAgICB0YXJnZXQ6IHRhcmdldC5hcnRpZmFjdFNldC50YXJnZXRcbiAgfSlcbn1cblxuLyoqXG4gKiBEZXJpdmVzIGV4YWN0IHN0YWdlZCBieXRlcyBhbmQgdGhlaXIgZGV0ZXJtaW5pc3RpYyBnZW5lcmF0aW9uLW1hbmlmZXN0IHJlY29yZC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5HZW5lcmF0ZWRTZXRBcnRpZmFjdH0gYXJ0aWZhY3QgLSBWYWxpZGF0ZWQgZ2VuZXJhdGVkIGFydGlmYWN0LlxuICogQHJldHVybnMge3tieXRlczogQnVmZmVyLCBtYW5pZmVzdDogaW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5HZW5lcmF0aW9uQXJ0aWZhY3RNYW5pZmVzdH19IEJ5dGVzIGFuZCBtYW5pZmVzdCByZWNvcmQuXG4gKi9cbmZ1bmN0aW9uIGRlc2NyaWJlR2VuZXJhdGVkQXJ0aWZhY3QoYXJ0aWZhY3QpIHtcbiAgY29uc3QgYnl0ZXMgPSBhcnRpZmFjdC5jb250ZW50S2luZCA9PSBcInRleHRcIlxuICAgID8gQnVmZmVyLmZyb20oLyoqIEB0eXBlIHtzdHJpbmd9ICovIChhcnRpZmFjdC5jb250ZW50KSwgXCJ1dGY4XCIpXG4gICAgOiBCdWZmZXIuZnJvbSgvKiogQHR5cGUge1VpbnQ4QXJyYXl9ICovIChhcnRpZmFjdC5jb250ZW50KSlcblxuICByZXR1cm4ge1xuICAgIGJ5dGVzLFxuICAgIG1hbmlmZXN0OiBPYmplY3QuZnJlZXplKHtcbiAgICAgIGJ5dGVMZW5ndGg6IGJ5dGVzLmJ5dGVMZW5ndGgsXG4gICAgICBjb250ZW50S2luZDogYXJ0aWZhY3QuY29udGVudEtpbmQsXG4gICAgICBoYXNoOiBPYmplY3QuZnJlZXplKHthbGdvcml0aG06IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcInNoYTI1NlwiKSwgdmFsdWU6IHNoYTI1NihieXRlcyl9KSxcbiAgICAgIG1lZGlhVHlwZTogYXJ0aWZhY3QubWVkaWFUeXBlLFxuICAgICAgcGF0aDogYXJ0aWZhY3QucGF0aCxcbiAgICAgIHByb3ZlbmFuY2U6IGFydGlmYWN0LnByb3ZlbmFuY2UsXG4gICAgICByb2xlOiBhcnRpZmFjdC5yb2xlXG4gICAgfSlcbiAgfVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyB2YWxpZGF0b3IvY29tcGlsZXIgb3V0cHV0IG1ldGFkYXRhLlxuICogQHBhcmFtIHt1bmtub3dufSBkZXNjcmlwdG9yIC0gTWV0YWRhdGEgY2FuZGlkYXRlLlxuICogQHBhcmFtIHtzdHJpbmd9IHRhcmdldElkIC0gVGFyZ2V0IGlkZW50aXR5LlxuICogQHBhcmFtIHtzdHJpbmd9IHByb2plY3RJZCAtIFByb2plY3QgZGlhZ25vc3RpYyBpZGVudGl0eS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlB1YmxpY2F0aW9uQnVpbGRBcnRpZmFjdElucHV0fSBWYWxpZGF0ZWQgbWV0YWRhdGEuXG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlQnVpbGRBcnRpZmFjdERlc2NyaXB0b3IoZGVzY3JpcHRvciwgdGFyZ2V0SWQsIHByb2plY3RJZCkge1xuICBpZiAoIWlzUGxhaW5PYmplY3QoZGVzY3JpcHRvcikgfHwgIWhhc0V4YWN0S2V5cyhkZXNjcmlwdG9yLCBbXCJtZWRpYVR5cGVcIiwgXCJwYXRoXCIsIFwicm9sZVwiXSkpIHtcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9WQUxJREFUSU9OX0ZBSUxFRFwiLCBwcm9qZWN0SWQsXG4gICAgICBgVGFyZ2V0ICcke3RhcmdldElkfScgdmFsaWRhdG9yIHJldHVybmVkIGludmFsaWQgYnVpbGQtYXJ0aWZhY3QgbWV0YWRhdGEuYClcbiAgfVxuICBjb25zdCBkZXNjcmlwdG9yUGF0aCA9IGRlc2NyaXB0b3IucGF0aFxuICBjb25zdCBtZWRpYVR5cGUgPSBkZXNjcmlwdG9yLm1lZGlhVHlwZVxuICBjb25zdCByb2xlID0gZGVzY3JpcHRvci5yb2xlXG5cbiAgaWYgKCFpc1NhZmVBcnRpZmFjdFBhdGgoZGVzY3JpcHRvclBhdGgpIHx8IHR5cGVvZiBtZWRpYVR5cGUgIT0gXCJzdHJpbmdcIiB8fFxuICAgICFtZWRpYVR5cGVQYXR0ZXJuLnRlc3QobWVkaWFUeXBlKSB8fCAvW1xcclxcbl0vdS50ZXN0KG1lZGlhVHlwZSkgfHxcbiAgICB0eXBlb2Ygcm9sZSAhPSBcInN0cmluZ1wiIHx8ICFidWlsZFJvbGVQYXR0ZXJuLnRlc3Qocm9sZSkpIHtcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9WQUxJREFUSU9OX0ZBSUxFRFwiLCBwcm9qZWN0SWQsXG4gICAgICBgVGFyZ2V0ICcke3RhcmdldElkfScgdmFsaWRhdG9yIHJldHVybmVkIGludmFsaWQgYnVpbGQtYXJ0aWZhY3QgbWV0YWRhdGEuYClcbiAgfVxuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKHttZWRpYVR5cGUsIHBhdGg6IGRlc2NyaXB0b3JQYXRoLCByb2xlfSlcbn1cblxuLyoqXG4gKiBWZXJpZmllcyBldmVyeSBtYW5pZmVzdCByZWZlcmVuY2UgYW5kIHN0YWdlZCBieXRlIGJlZm9yZSBwb2ludGVyIHJlYWNoYWJpbGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBnZW5lcmF0aW9uUGF0aCAtIENhbmRpZGF0ZSBnZW5lcmF0aW9uIHBhdGguXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGlvbk1hbmlmZXN0fSBtYW5pZmVzdCAtIENhbmRpZGF0ZSBtYW5pZmVzdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9qZWN0SWQgLSBQcm9qZWN0IGRpYWdub3N0aWMgaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQ29tcGxldGlvbi5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gdmVyaWZ5TWFuaWZlc3RGaWxlcyhnZW5lcmF0aW9uUGF0aCwgbWFuaWZlc3QsIHByb2plY3RJZCkge1xuICBmb3IgKGNvbnN0IHRhcmdldCBvZiBtYW5pZmVzdC50YXJnZXRzKSB7XG4gICAgY29uc3Qgc291cmNlUGF0aCA9IG93bmVkUGF0aChnZW5lcmF0aW9uUGF0aCwgdGFyZ2V0LnByb2plY3Rpb25zLnNvdXJjZSwgcHJvamVjdElkKVxuICAgIGNvbnN0IGJ1aWxkUGF0aCA9IG93bmVkUGF0aChnZW5lcmF0aW9uUGF0aCwgdGFyZ2V0LnByb2plY3Rpb25zLmJ1aWxkLCBwcm9qZWN0SWQpXG4gICAgY29uc3Qgc291cmNlRmlsZXMgPSBhd2FpdCBsaXN0UmVndWxhckZpbGVzKHNvdXJjZVBhdGgsIHByb2plY3RJZClcblxuICAgIGlmIChzb3VyY2VGaWxlcy5sZW5ndGggIT0gdGFyZ2V0LmFydGlmYWN0cy5sZW5ndGggfHxcbiAgICAgIHNvdXJjZUZpbGVzLnNvbWUoZmlsZW5hbWUgPT4gIXRhcmdldC5hcnRpZmFjdHMuc29tZShhcnRpZmFjdCA9PiBhcnRpZmFjdC5wYXRoID09IGZpbGVuYW1lKSkpIHtcbiAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX1NUQUdFX0hBU0hfTUlTTUFUQ0hcIiwgcHJvamVjdElkLFxuICAgICAgICBgVGFyZ2V0ICcke3RhcmdldC5pZH0nIGdlbmVyYXRlZC1zb3VyY2UgZmlsZXMgZG8gbm90IG1hdGNoIGl0cyBtYW5pZmVzdC5gKVxuICAgIH1cbiAgICBmb3IgKGNvbnN0IGFydGlmYWN0IG9mIHRhcmdldC5hcnRpZmFjdHMpIHtcbiAgICAgIGF3YWl0IHZlcmlmeU1hbmlmZXN0RmlsZShzb3VyY2VQYXRoLCBhcnRpZmFjdCwgcHJvamVjdElkKVxuICAgIH1cbiAgICBjb25zdCBidWlsZEZpbGVzID0gYXdhaXQgbGlzdFJlZ3VsYXJGaWxlcyhidWlsZFBhdGgsIHByb2plY3RJZClcblxuICAgIGlmIChidWlsZEZpbGVzLmxlbmd0aCAhPSB0YXJnZXQuYnVpbGRBcnRpZmFjdHMubGVuZ3RoIHx8XG4gICAgICBidWlsZEZpbGVzLnNvbWUoZmlsZW5hbWUgPT4gIXRhcmdldC5idWlsZEFydGlmYWN0cy5zb21lKGFydGlmYWN0ID0+IGFydGlmYWN0LnBhdGggPT0gZmlsZW5hbWUpKSkge1xuICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fU1RBR0VfSEFTSF9NSVNNQVRDSFwiLCBwcm9qZWN0SWQsXG4gICAgICAgIGBUYXJnZXQgJyR7dGFyZ2V0LmlkfScgYnVpbGQgZmlsZXMgZG8gbm90IG1hdGNoIGl0cyBtYW5pZmVzdC5gKVxuICAgIH1cbiAgICBmb3IgKGNvbnN0IGFydGlmYWN0IG9mIHRhcmdldC5idWlsZEFydGlmYWN0cykge1xuICAgICAgYXdhaXQgdmVyaWZ5TWFuaWZlc3RGaWxlKGJ1aWxkUGF0aCwgYXJ0aWZhY3QsIHByb2plY3RJZClcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGFydGlmYWN0cyA9IFtdXG5cbiAgICAgIGZvciAoY29uc3QgYXJ0aWZhY3Qgb2YgdGFyZ2V0LmFydGlmYWN0cykge1xuICAgICAgICBjb25zdCBieXRlcyA9IGF3YWl0IHJlYWRBbmRTeW5jUmVndWxhckZpbGUob3duZWRQYXRoKHNvdXJjZVBhdGgsIGFydGlmYWN0LnBhdGgsIHByb2plY3RJZCksIHByb2plY3RJZCxcbiAgICAgICAgICBcIlBVQkxJQ0FUSU9OX1NUQUdFX0hBU0hfTUlTTUFUQ0hcIiwgYE1hbmlmZXN0IGFydGlmYWN0ICcke2FydGlmYWN0LnBhdGh9JyBpcyBub3QgYSBzdGFibGUgcmVndWxhciBmaWxlLmApXG4gICAgICAgIGxldCBjb250ZW50XG5cbiAgICAgICAgaWYgKGFydGlmYWN0LmNvbnRlbnRLaW5kID09IFwidGV4dFwiKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnRlbnQgPSBuZXcgVGV4dERlY29kZXIoXCJ1dGYtOFwiLCB7ZmF0YWw6IHRydWV9KS5kZWNvZGUoYnl0ZXMpXG4gICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIk1BTEZPUk1FRF9HRU5FUkFUSU9OX01BTklGRVNUXCIsIHByb2plY3RJZCxcbiAgICAgICAgICAgICAgYFRleHQgYXJ0aWZhY3QgJyR7YXJ0aWZhY3QucGF0aH0nIGlzIG5vdCB2YWxpZCBVVEYtOC5gLCBlcnJvcilcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBjb250ZW50ID0gbmV3IFVpbnQ4QXJyYXkoYnl0ZXMpXG4gICAgICAgIGFydGlmYWN0cy5wdXNoKHtcbiAgICAgICAgICBjb250ZW50LFxuICAgICAgICAgIGNvbnRlbnRLaW5kOiBhcnRpZmFjdC5jb250ZW50S2luZCxcbiAgICAgICAgICBtZWRpYVR5cGU6IGFydGlmYWN0Lm1lZGlhVHlwZSxcbiAgICAgICAgICBvd25lcnNoaXA6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcImdlbmVyYXRlZFwiKSxcbiAgICAgICAgICBwYXRoOiBhcnRpZmFjdC5wYXRoLFxuICAgICAgICAgIHByb3ZlbmFuY2U6IHJlaHlkcmF0ZVByb3ZlbmFuY2UoYXJ0aWZhY3QucHJvdmVuYW5jZSwgcHJvamVjdElkKSxcbiAgICAgICAgICByb2xlOiBhcnRpZmFjdC5yb2xlXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgICBjcmVhdGVHZW5lcmF0ZWRBcnRpZmFjdFNldCh7XG4gICAgICAgIGFydGlmYWN0cyxcbiAgICAgICAgLi4uKHRhcmdldC5tZXRhZGF0YSA9PT0gdW5kZWZpbmVkID8ge30gOiB7bWV0YWRhdGE6IHRhcmdldC5tZXRhZGF0YX0pLFxuICAgICAgICB0YXJnZXQ6IHRhcmdldC50YXJnZXRcbiAgICAgIH0pXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFNlbWFudGlmb2xkRGlhZ25vc3RpYyAmJiBlcnJvci5jb2RlID09IFwiTUFMRk9STUVEX0dFTkVSQVRJT05fTUFOSUZFU1RcIikgdGhyb3cgZXJyb3JcbiAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIk1BTEZPUk1FRF9HRU5FUkFUSU9OX01BTklGRVNUXCIsIHByb2plY3RJZCxcbiAgICAgICAgYFRhcmdldCAnJHt0YXJnZXQuaWR9JyBhcnRpZmFjdCBwcm92ZW5hbmNlIGRvZXMgbm90IG1hdGNoIGl0cyBzdGFnZWQgYnl0ZXMuYCwgZXJyb3IpXG4gICAgfVxuICB9XG4gIGF3YWl0IHZlcmlmeUdlbmVyYXRpb25JbnZlbnRvcnkoZ2VuZXJhdGlvblBhdGgsIG1hbmlmZXN0LCBwcm9qZWN0SWQpXG59XG5cbi8qKlxuICogUmVzdG9yZXMgSlNPTi1vbWl0dGVkIG9wdGlvbmFsIG1hcHBpbmcgZmllbGRzIGFuZCB2ZXJpZmllcyBwZXJzaXN0ZWQgbWFwcGluZyBwcm9qZWN0aW9ucy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5BcnRpZmFjdFByb3ZlbmFuY2V9IHByb3ZlbmFuY2UgLSBQZXJzaXN0ZWQgcHJvdmVuYW5jZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9qZWN0SWQgLSBQcm9qZWN0IGlkZW50aXR5LlxuICogQHJldHVybnMge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuQXJ0aWZhY3RQcm92ZW5hbmNlfSBDYW5vbmljYWwgcHJvdmVuYW5jZS5cbiAqL1xuZnVuY3Rpb24gcmVoeWRyYXRlUHJvdmVuYW5jZShwcm92ZW5hbmNlLCBwcm9qZWN0SWQpIHtcbiAgaWYgKHByb3ZlbmFuY2Uua2luZCA9PSBcInRleHRcIikge1xuICAgIGNvbnN0IG1hcHBpbmcgPSBmaW5hbGl6ZU1hcHBpbmcocHJvdmVuYW5jZS5tYXBwaW5nKVxuICAgIGNvbnN0IHNvdXJjZU1hcCA9IHRvU291cmNlTWFwVjMobWFwcGluZylcbiAgICBjb25zdCBqc29uU291cmNlTWFwID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShzb3VyY2VNYXApKVxuXG4gICAgaWYgKCFzYW1lSnNvblZhbHVlKGpzb25Tb3VyY2VNYXAsIHByb3ZlbmFuY2Uuc291cmNlTWFwKSkge1xuICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiTUFMRk9STUVEX0dFTkVSQVRJT05fTUFOSUZFU1RcIiwgcHJvamVjdElkLFxuICAgICAgICBcIlBlcnNpc3RlZCBTb3VyY2UgTWFwIHByb2plY3Rpb24gY29udHJhZGljdHMgaXRzIHJpY2ggbWFwcGluZy5cIilcbiAgICB9XG5cbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG4gICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJ0ZXh0XCIpLFxuICAgICAgbWFwcGluZyxcbiAgICAgIHNvdXJjZU1hcCxcbiAgICAgIC4uLihwcm92ZW5hbmNlLnNvdXJjZU1hcEZpbGVuYW1lID09PSB1bmRlZmluZWQgPyB7fSA6IHtzb3VyY2VNYXBGaWxlbmFtZTogcHJvdmVuYW5jZS5zb3VyY2VNYXBGaWxlbmFtZX0pXG4gICAgfSlcbiAgfVxuICBpZiAocHJvdmVuYW5jZS5raW5kID09IFwiYnl0ZXNcIikge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKHtraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJieXRlc1wiKSwgbWFwcGluZzogZmluYWxpemVCeXRlTWFwcGluZyhwcm92ZW5hbmNlLm1hcHBpbmcpfSlcbiAgfVxuXG4gIHJldHVybiBwcm92ZW5hbmNlXG59XG5cbi8qKlxuICogVmVyaWZpZXMgb25lIHJlZmVyZW5jZWQgZmlsZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9qZWN0aW9uUGF0aCAtIE93bmluZyBwcm9qZWN0aW9uIHBhdGguXG4gKiBAcGFyYW0ge3tieXRlTGVuZ3RoOiBudW1iZXIsIGhhc2g6IGltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGlvbkNvbnRlbnRIYXNoLCBwYXRoOiBzdHJpbmd9fSBhcnRpZmFjdCAtIE1hbmlmZXN0IHJlY29yZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9qZWN0SWQgLSBQcm9qZWN0IGRpYWdub3N0aWMgaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxCdWZmZXI+fSBFeGFjdCB2ZXJpZmllZCBieXRlcy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gdmVyaWZ5TWFuaWZlc3RGaWxlKHByb2plY3Rpb25QYXRoLCBhcnRpZmFjdCwgcHJvamVjdElkKSB7XG4gIGNvbnN0IGJ5dGVzID0gYXdhaXQgcmVhZEFuZFN5bmNSZWd1bGFyRmlsZShvd25lZFBhdGgocHJvamVjdGlvblBhdGgsIGFydGlmYWN0LnBhdGgsIHByb2plY3RJZCksIHByb2plY3RJZCxcbiAgICBcIlBVQkxJQ0FUSU9OX1NUQUdFX0hBU0hfTUlTTUFUQ0hcIiwgYE1hbmlmZXN0IGFydGlmYWN0ICcke2FydGlmYWN0LnBhdGh9JyBpcyBub3QgYSBzdGFibGUgcmVndWxhciBmaWxlLmApXG5cbiAgaWYgKGJ5dGVzLmJ5dGVMZW5ndGggIT0gYXJ0aWZhY3QuYnl0ZUxlbmd0aCB8fCBzaGEyNTYoYnl0ZXMpICE9IGFydGlmYWN0Lmhhc2gudmFsdWUpIHtcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9TVEFHRV9IQVNIX01JU01BVENIXCIsIHByb2plY3RJZCxcbiAgICAgIGBNYW5pZmVzdCBhcnRpZmFjdCAnJHthcnRpZmFjdC5wYXRofScgYnl0ZXMgZG8gbm90IG1hdGNoIGl0cyByZWNvcmRlZCBoYXNoLmApXG4gIH1cblxuICByZXR1cm4gYnl0ZXNcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgYW4gZXhpc3RpbmcgYWN0aXZlIHBvaW50ZXIgYmVmb3JlIGEgbmV3IGNhbmRpZGF0ZSBpcyBzdGFnZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gcHVibGljYXRpb25Sb290IC0gUHVibGljYXRpb24gcm9vdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9qZWN0SWQgLSBQcm9qZWN0IGlkZW50aXR5LlxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IENvbXBsZXRpb24uXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHZhbGlkYXRlRXhpc3RpbmdQb2ludGVyKHB1YmxpY2F0aW9uUm9vdCwgcHJvamVjdElkKSB7XG4gIGNvbnN0IHBvaW50ZXJQYXRoID0gcGF0aC5qb2luKHB1YmxpY2F0aW9uUm9vdCwgYWN0aXZlUG9pbnRlck5hbWUpXG4gIGNvbnN0IHBvaW50ZXIgPSBhd2FpdCByZWFkQWN0aXZlUG9pbnRlcihwb2ludGVyUGF0aCwgcHJvamVjdElkLCB0cnVlKVxuXG4gIGlmIChwb2ludGVyKSBhd2FpdCB2ZXJpZnlQdWJsaXNoZWRHZW5lcmF0aW9uKHB1YmxpY2F0aW9uUm9vdCwgcHJvamVjdElkLCBwb2ludGVyLCBmYWxzZSlcbn1cblxuLyoqXG4gKiBSZWFkcyBhbmQgc3RyaWN0bHkgdmFsaWRhdGVzIG9uZSBhY3RpdmUgcG9pbnRlci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwb2ludGVyUGF0aCAtIFBvaW50ZXIgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvamVjdElkIC0gRXhwZWN0ZWQgcHJvamVjdCBpZGVudGl0eS5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0aW9uYWwgLSBXaGV0aGVyIGFic2VuY2UgaXMgYWxsb3dlZC5cbiAqIEByZXR1cm5zIHtQcm9taXNlPEFjdGl2ZVBvaW50ZXIgfCBudWxsPn0gUG9pbnRlciBvciBhYnNlbnQgdmFsdWUuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlYWRBY3RpdmVQb2ludGVyKHBvaW50ZXJQYXRoLCBwcm9qZWN0SWQsIG9wdGlvbmFsKSB7XG4gIGxldCBwb2ludGVyQnl0ZXNcblxuICB0cnkge1xuICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IGxzdGF0KHBvaW50ZXJQYXRoKVxuXG4gICAgaWYgKCFzdGF0dXMuaXNGaWxlKCkgfHwgc3RhdHVzLmlzU3ltYm9saWNMaW5rKCkpIHtcbiAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIk1BTEZPUk1FRF9BQ1RJVkVfR0VORVJBVElPTlwiLCBwcm9qZWN0SWQsXG4gICAgICAgIFwiQWN0aXZlLWdlbmVyYXRpb24gcG9pbnRlciBtdXN0IGJlIGEgcmVndWxhciBmaWxlLlwiKVxuICAgIH1cbiAgICBwb2ludGVyQnl0ZXMgPSBhd2FpdCByZWFkRmlsZShwb2ludGVyUGF0aClcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAob3B0aW9uYWwgJiYgaXNFcnJvckNvZGUoZXJyb3IsIFwiRU5PRU5UXCIpKSByZXR1cm4gbnVsbFxuICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFNlbWFudGlmb2xkRGlhZ25vc3RpYykgdGhyb3cgZXJyb3JcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUob3B0aW9uYWwgPyBcIk1BTEZPUk1FRF9BQ1RJVkVfR0VORVJBVElPTlwiIDogXCJBQ1RJVkVfR0VORVJBVElPTl9NSVNTSU5HXCIsIHByb2plY3RJZCxcbiAgICAgIG9wdGlvbmFsID8gXCJBY3RpdmUtZ2VuZXJhdGlvbiBwb2ludGVyIGNvdWxkIG5vdCBiZSByZWFkLlwiIDogXCJObyBhY3RpdmUgZ2VuZXJhdGlvbiBoYXMgYmVlbiBwdWJsaXNoZWQuXCIsIGVycm9yKVxuICB9XG4gIGxldCB2YWx1ZVxuXG4gIHRyeSB7XG4gICAgdmFsdWUgPSBKU09OLnBhcnNlKHBvaW50ZXJCeXRlcy50b1N0cmluZyhcInV0ZjhcIikpXG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcHVibGljYXRpb25GYWlsdXJlKFwiTUFMRk9STUVEX0FDVElWRV9HRU5FUkFUSU9OXCIsIHByb2plY3RJZCxcbiAgICAgIFwiQWN0aXZlLWdlbmVyYXRpb24gcG9pbnRlciBpcyBub3QgdmFsaWQgSlNPTi5cIiwgZXJyb3IpXG4gIH1cbiAgaWYgKCFpc0FjdGl2ZVBvaW50ZXIodmFsdWUpIHx8IHZhbHVlLnByb2plY3RJZCAhPSBwcm9qZWN0SWQpIHtcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJNQUxGT1JNRURfQUNUSVZFX0dFTkVSQVRJT05cIiwgcHJvamVjdElkLFxuICAgICAgXCJBY3RpdmUtZ2VuZXJhdGlvbiBwb2ludGVyIGRvZXMgbm90IG1hdGNoIHRoZSB2ZXJzaW9uZWQgcHJvamVjdCBjb250cmFjdC5cIilcbiAgfVxuXG4gIHJldHVybiB2YWx1ZVxufVxuXG4vKipcbiAqIFZlcmlmaWVzIGEgcG9pbnRlci1zZWxlY3RlZCBnZW5lcmF0aW9uIHdpdGhvdXQgY29uc3VsdGluZyB0aGUgcG9pbnRlciBhZ2Fpbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwdWJsaWNhdGlvblJvb3QgLSBQdWJsaWNhdGlvbiByb290LlxuICogQHBhcmFtIHtzdHJpbmd9IHByb2plY3RJZCAtIFByb2plY3QgaWRlbnRpdHkuXG4gKiBAcGFyYW0ge0FjdGl2ZVBvaW50ZXJ9IHBvaW50ZXIgLSBQb2ludGVyIHNuYXBzaG90LlxuICogQHBhcmFtIHtib29sZWFufSBjbGVhbnVwUGVuZGluZyAtIFJlY292ZXJ5IHN0YXRlLlxuICogQHJldHVybnMge1Byb21pc2U8aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5QdWJsaXNoZWRHZW5lcmF0aW9uPn0gVmVyaWZpZWQgZ2VuZXJhdGlvbi5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gdmVyaWZ5UHVibGlzaGVkR2VuZXJhdGlvbihwdWJsaWNhdGlvblJvb3QsIHByb2plY3RJZCwgcG9pbnRlciwgY2xlYW51cFBlbmRpbmcpIHtcbiAgY29uc3QgZ2VuZXJhdGlvblBhdGggPSBvd25lZFBhdGgocGF0aC5qb2luKHB1YmxpY2F0aW9uUm9vdCwgZ2VuZXJhdGlvbnNOYW1lKSwgcG9pbnRlci5nZW5lcmF0aW9uSWQsIHByb2plY3RJZClcbiAgY29uc3QgbWFuaWZlc3RQYXRoID0gcGF0aC5qb2luKGdlbmVyYXRpb25QYXRoLCBcIm1hbmlmZXN0Lmpzb25cIilcbiAgbGV0IG1hbmlmZXN0Qnl0ZXNcblxuICB0cnkge1xuICAgIG1hbmlmZXN0Qnl0ZXMgPSBhd2FpdCByZWFkQW5kU3luY1JlZ3VsYXJGaWxlKG1hbmlmZXN0UGF0aCwgcHJvamVjdElkLCBcIk1BTEZPUk1FRF9HRU5FUkFUSU9OX01BTklGRVNUXCIsXG4gICAgICBcIkdlbmVyYXRpb24gbWFuaWZlc3QgbXVzdCBiZSBhIHJlZ3VsYXIgZmlsZS5cIilcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBTZW1hbnRpZm9sZERpYWdub3N0aWMpIHRocm93IGVycm9yXG4gICAgcHVibGljYXRpb25GYWlsdXJlKFwiTUFMRk9STUVEX0dFTkVSQVRJT05fTUFOSUZFU1RcIiwgcHJvamVjdElkLFxuICAgICAgXCJHZW5lcmF0aW9uIG1hbmlmZXN0IGNvdWxkIG5vdCBiZSByZWFkLlwiLCBlcnJvcilcbiAgfVxuICBpZiAoc2hhMjU2KG1hbmlmZXN0Qnl0ZXMpICE9IHBvaW50ZXIubWFuaWZlc3RIYXNoKSB7XG4gICAgcHVibGljYXRpb25GYWlsdXJlKFwiTUFMRk9STUVEX0dFTkVSQVRJT05fTUFOSUZFU1RcIiwgcHJvamVjdElkLFxuICAgICAgXCJHZW5lcmF0aW9uIG1hbmlmZXN0IGhhc2ggZG9lcyBub3QgbWF0Y2ggdGhlIGFjdGl2ZSBwb2ludGVyLlwiKVxuICB9XG4gIGxldCB2YWx1ZVxuXG4gIHRyeSB7XG4gICAgdmFsdWUgPSBKU09OLnBhcnNlKG1hbmlmZXN0Qnl0ZXMudG9TdHJpbmcoXCJ1dGY4XCIpKVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIk1BTEZPUk1FRF9HRU5FUkFUSU9OX01BTklGRVNUXCIsIHByb2plY3RJZCxcbiAgICAgIFwiR2VuZXJhdGlvbiBtYW5pZmVzdCBpcyBub3QgdmFsaWQgSlNPTi5cIiwgZXJyb3IpXG4gIH1cbiAgY29uc3QgbWFuaWZlc3QgPSB2YWxpZGF0ZUdlbmVyYXRpb25NYW5pZmVzdCh2YWx1ZSwgcHJvamVjdElkLCBwb2ludGVyLmdlbmVyYXRpb25JZClcblxuICBhd2FpdCB2ZXJpZnlNYW5pZmVzdEZpbGVzKGdlbmVyYXRpb25QYXRoLCBtYW5pZmVzdCwgcHJvamVjdElkKVxuXG4gIHJldHVybiBwdWJsaXNoZWRHZW5lcmF0aW9uKHB1YmxpY2F0aW9uUm9vdCwgbWFuaWZlc3QsIGNsZWFudXBQZW5kaW5nKVxufVxuXG4vKipcbiAqIFN0cmljdGx5IHZhbGlkYXRlcyBhIHBlcnNpc3RlZCBnZW5lcmF0aW9uIG1hbmlmZXN0LlxuICogQHBhcmFtIHt1bmtub3dufSB2YWx1ZSAtIFBhcnNlZCBtYW5pZmVzdCB2YWx1ZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9qZWN0SWQgLSBFeHBlY3RlZCBwcm9qZWN0IGlkZW50aXR5LlxuICogQHBhcmFtIHtzdHJpbmd9IGdlbmVyYXRpb25JZCAtIEV4cGVjdGVkIGdlbmVyYXRpb24gaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5HZW5lcmF0aW9uTWFuaWZlc3R9IEZyb3plbiBtYW5pZmVzdC5cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVHZW5lcmF0aW9uTWFuaWZlc3QodmFsdWUsIHByb2plY3RJZCwgZ2VuZXJhdGlvbklkKSB7XG4gIGlmICghaXNQbGFpbk9iamVjdCh2YWx1ZSkgfHwgIWhhc0V4YWN0S2V5cyh2YWx1ZSwgW1wiZ2VuZXJhdGlvbklkXCIsIFwicHJvamVjdElkXCIsIFwic2NoZW1hXCIsIFwidGFyZ2V0c1wiLCBcInZlcnNpb25cIl0pIHx8XG4gICAgdmFsdWUuc2NoZW1hICE9IFwiU2VtYW50aWZvbGRHZW5lcmF0aW9uTWFuaWZlc3RcIiB8fCB2YWx1ZS52ZXJzaW9uICE9IDEgfHwgdmFsdWUucHJvamVjdElkICE9IHByb2plY3RJZCB8fFxuICAgIHZhbHVlLmdlbmVyYXRpb25JZCAhPSBnZW5lcmF0aW9uSWQgfHwgIWlzRGVuc2VBcnJheSh2YWx1ZS50YXJnZXRzKSB8fCB2YWx1ZS50YXJnZXRzLmxlbmd0aCA9PSAwKSB7XG4gICAgcHVibGljYXRpb25GYWlsdXJlKFwiTUFMRk9STUVEX0dFTkVSQVRJT05fTUFOSUZFU1RcIiwgcHJvamVjdElkLFxuICAgICAgXCJHZW5lcmF0aW9uIG1hbmlmZXN0IGRvZXMgbm90IG1hdGNoIHRoZSB2ZXJzaW9uZWQgcHJvamVjdCBjb250cmFjdC5cIilcbiAgfVxuICAvKiogQHR5cGUge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGlvblRhcmdldE1hbmlmZXN0W119ICovXG4gIGNvbnN0IHRhcmdldHMgPSBbXVxuICAvKiogQHR5cGUge3N0cmluZ1tdfSAqL1xuICBjb25zdCBwcm9qZWN0aW9ucyA9IFtdXG4gIGNvbnN0IGlkcyA9IG5ldyBTZXQoKVxuXG4gIGZvciAoY29uc3QgdGFyZ2V0IG9mIHZhbHVlLnRhcmdldHMpIHtcbiAgICBjb25zdCB0YXJnZXRLZXlzID0gdGFyZ2V0ICYmIHR5cGVvZiB0YXJnZXQgPT0gXCJvYmplY3RcIiAmJiBcIm1ldGFkYXRhXCIgaW4gdGFyZ2V0XG4gICAgICA/IFtcImFydGlmYWN0c1wiLCBcImJ1aWxkQXJ0aWZhY3RzXCIsIFwiaWRcIiwgXCJtZXRhZGF0YVwiLCBcInByb2plY3Rpb25zXCIsIFwicm9sZVwiLCBcInRhcmdldFwiXVxuICAgICAgOiBbXCJhcnRpZmFjdHNcIiwgXCJidWlsZEFydGlmYWN0c1wiLCBcImlkXCIsIFwicHJvamVjdGlvbnNcIiwgXCJyb2xlXCIsIFwidGFyZ2V0XCJdXG5cbiAgICBpZiAoIWlzUGxhaW5PYmplY3QodGFyZ2V0KSB8fCAhaGFzRXhhY3RLZXlzKHRhcmdldCwgdGFyZ2V0S2V5cykgfHxcbiAgICAgICFpZGVudGl0eVBhdHRlcm4udGVzdCh0eXBlb2YgdGFyZ2V0LmlkID09IFwic3RyaW5nXCIgPyB0YXJnZXQuaWQgOiBcIlwiKSB8fCBpZHMuaGFzKHRhcmdldC5pZCkgfHxcbiAgICAgIHR5cGVvZiB0YXJnZXQucm9sZSAhPSBcInN0cmluZ1wiIHx8ICF0YXJnZXRSb2xlcy5oYXModGFyZ2V0LnJvbGUpIHx8XG4gICAgICB0eXBlb2YgdGFyZ2V0LnRhcmdldCAhPSBcInN0cmluZ1wiIHx8ICFpZGVudGl0eVBhdHRlcm4udGVzdCh0YXJnZXQudGFyZ2V0KSB8fFxuICAgICAgIWlzUGxhaW5PYmplY3QodGFyZ2V0LnByb2plY3Rpb25zKSB8fCAhaGFzRXhhY3RLZXlzKHRhcmdldC5wcm9qZWN0aW9ucywgW1wiYnVpbGRcIiwgXCJzb3VyY2VcIl0pIHx8XG4gICAgICAhaXNTYWZlQXJ0aWZhY3RQYXRoKHRhcmdldC5wcm9qZWN0aW9ucy5zb3VyY2UpIHx8ICFpc1NhZmVBcnRpZmFjdFBhdGgodGFyZ2V0LnByb2plY3Rpb25zLmJ1aWxkKSB8fFxuICAgICAgIWlzRGVuc2VBcnJheSh0YXJnZXQuYXJ0aWZhY3RzKSB8fCB0YXJnZXQuYXJ0aWZhY3RzLmxlbmd0aCA9PSAwIHx8ICFpc0RlbnNlQXJyYXkodGFyZ2V0LmJ1aWxkQXJ0aWZhY3RzKSkge1xuICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiTUFMRk9STUVEX0dFTkVSQVRJT05fTUFOSUZFU1RcIiwgcHJvamVjdElkLFxuICAgICAgICBcIkdlbmVyYXRpb24gbWFuaWZlc3QgY29udGFpbnMgYW4gaW52YWxpZCB0YXJnZXQgcmVjb3JkLlwiKVxuICAgIH1cbiAgICBjb25zdCB0YXJnZXRJZCA9IC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAodGFyZ2V0LmlkKVxuXG4gICAgaWRzLmFkZCh0YXJnZXRJZClcbiAgICBwcm9qZWN0aW9ucy5wdXNoKHRhcmdldC5wcm9qZWN0aW9ucy5zb3VyY2UsIHRhcmdldC5wcm9qZWN0aW9ucy5idWlsZClcbiAgICBjb25zdCBhcnRpZmFjdHMgPSB0YXJnZXQuYXJ0aWZhY3RzLm1hcChhcnRpZmFjdCA9PiB2YWxpZGF0ZVBlcnNpc3RlZEFydGlmYWN0KGFydGlmYWN0LCB0cnVlLCBwcm9qZWN0SWQpKVxuICAgIGNvbnN0IGJ1aWxkQXJ0aWZhY3RzID0gdGFyZ2V0LmJ1aWxkQXJ0aWZhY3RzLm1hcChhcnRpZmFjdCA9PiB2YWxpZGF0ZVBlcnNpc3RlZEFydGlmYWN0KGFydGlmYWN0LCBmYWxzZSwgcHJvamVjdElkKSlcblxuICAgIGlmIChmaW5kUG9ydGFibGVBcnRpZmFjdFBhdGhDb25mbGljdChhcnRpZmFjdHMubWFwKCh7cGF0aDogYXJ0aWZhY3RQYXRofSkgPT4gYXJ0aWZhY3RQYXRoKSkgfHxcbiAgICAgIGZpbmRQb3J0YWJsZUFydGlmYWN0UGF0aENvbmZsaWN0KGJ1aWxkQXJ0aWZhY3RzLm1hcCgoe3BhdGg6IGFydGlmYWN0UGF0aH0pID0+IGFydGlmYWN0UGF0aCkpKSB7XG4gICAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJNQUxGT1JNRURfR0VORVJBVElPTl9NQU5JRkVTVFwiLCBwcm9qZWN0SWQsXG4gICAgICAgIFwiR2VuZXJhdGlvbiBtYW5pZmVzdCBjb250YWlucyBjb2xsaWRpbmcgYXJ0aWZhY3QgcGF0aHMuXCIpXG4gICAgfVxuICAgIHRhcmdldHMucHVzaChPYmplY3QuZnJlZXplKHtcbiAgICAgIGFydGlmYWN0czogT2JqZWN0LmZyZWV6ZSgvKiogQHR5cGUge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGlvbkFydGlmYWN0TWFuaWZlc3RbXX0gKi8gKGFydGlmYWN0cykpLFxuICAgICAgYnVpbGRBcnRpZmFjdHM6IE9iamVjdC5mcmVlemUoLyoqIEB0eXBlIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRpb25CdWlsZEFydGlmYWN0TWFuaWZlc3RbXX0gKi8gKGJ1aWxkQXJ0aWZhY3RzKSksXG4gICAgICBpZDogdGFyZ2V0SWQsXG4gICAgICAuLi4odGFyZ2V0Lm1ldGFkYXRhID09PSB1bmRlZmluZWQgPyB7fSA6IHttZXRhZGF0YTogZGVlcEZyZWV6ZSgvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIHVua25vd24+fSAqLyAodGFyZ2V0Lm1ldGFkYXRhKSl9KSxcbiAgICAgIHByb2plY3Rpb25zOiBPYmplY3QuZnJlZXplKHtidWlsZDogdGFyZ2V0LnByb2plY3Rpb25zLmJ1aWxkLCBzb3VyY2U6IHRhcmdldC5wcm9qZWN0aW9ucy5zb3VyY2V9KSxcbiAgICAgIHJvbGU6IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5QdWJsaWNhdGlvblRhcmdldFJvbGV9ICovICh0YXJnZXQucm9sZSksXG4gICAgICB0YXJnZXQ6IHRhcmdldC50YXJnZXRcbiAgICB9KSlcbiAgfVxuICBpZiAoZmluZFBvcnRhYmxlQXJ0aWZhY3RQYXRoQ29uZmxpY3QocHJvamVjdGlvbnMpIHx8XG4gICAgZmluZFBvcnRhYmxlQXJ0aWZhY3RQYXRoQ29uZmxpY3QoWy4uLnByb2plY3Rpb25zLCBcIm1hbmlmZXN0Lmpzb25cIl0pKSB7XG4gICAgcHVibGljYXRpb25GYWlsdXJlKFwiTUFMRk9STUVEX0dFTkVSQVRJT05fTUFOSUZFU1RcIiwgcHJvamVjdElkLFxuICAgICAgXCJHZW5lcmF0aW9uIG1hbmlmZXN0IGNvbnRhaW5zIG92ZXJsYXBwaW5nIHByb2plY3Rpb25zLlwiKVxuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUoe1xuICAgIGdlbmVyYXRpb25JZCxcbiAgICBwcm9qZWN0SWQsXG4gICAgc2NoZW1hOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJTZW1hbnRpZm9sZEdlbmVyYXRpb25NYW5pZmVzdFwiKSxcbiAgICB0YXJnZXRzOiBPYmplY3QuZnJlZXplKHRhcmdldHMpLFxuICAgIHZlcnNpb246IC8qKiBAdHlwZSB7Y29uc3R9ICovICgxKVxuICB9KVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyBvbmUgcGVyc2lzdGVkIGFydGlmYWN0IHJlY29yZC5cbiAqIEBwYXJhbSB7dW5rbm93bn0gdmFsdWUgLSBSZWNvcmQgY2FuZGlkYXRlLlxuICogQHBhcmFtIHtib29sZWFufSBnZW5lcmF0ZWQgLSBXaGV0aGVyIHRoaXMgaXMgYSBnZW5lcmF0ZWQtc291cmNlIGFydGlmYWN0LlxuICogQHBhcmFtIHtzdHJpbmd9IHByb2plY3RJZCAtIFByb2plY3QgaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5HZW5lcmF0aW9uQXJ0aWZhY3RNYW5pZmVzdCB8IGltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGlvbkJ1aWxkQXJ0aWZhY3RNYW5pZmVzdH0gRnJvemVuIHJlY29yZC5cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVQZXJzaXN0ZWRBcnRpZmFjdCh2YWx1ZSwgZ2VuZXJhdGVkLCBwcm9qZWN0SWQpIHtcbiAgY29uc3Qga2V5cyA9IGdlbmVyYXRlZFxuICAgID8gW1wiYnl0ZUxlbmd0aFwiLCBcImNvbnRlbnRLaW5kXCIsIFwiaGFzaFwiLCBcIm1lZGlhVHlwZVwiLCBcInBhdGhcIiwgXCJwcm92ZW5hbmNlXCIsIFwicm9sZVwiXVxuICAgIDogW1wiYnl0ZUxlbmd0aFwiLCBcImhhc2hcIiwgXCJtZWRpYVR5cGVcIiwgXCJwYXRoXCIsIFwicm9sZVwiXVxuXG4gIGlmICghaXNQbGFpbk9iamVjdCh2YWx1ZSkgfHwgIWhhc0V4YWN0S2V5cyh2YWx1ZSwga2V5cykgfHwgIWlzU2FmZUFydGlmYWN0UGF0aCh2YWx1ZS5wYXRoKSB8fFxuICAgIHR5cGVvZiB2YWx1ZS5ieXRlTGVuZ3RoICE9IFwibnVtYmVyXCIgfHwgIU51bWJlci5pc1NhZmVJbnRlZ2VyKHZhbHVlLmJ5dGVMZW5ndGgpIHx8IHZhbHVlLmJ5dGVMZW5ndGggPCAwIHx8IHR5cGVvZiB2YWx1ZS5tZWRpYVR5cGUgIT0gXCJzdHJpbmdcIiB8fFxuICAgICFtZWRpYVR5cGVQYXR0ZXJuLnRlc3QodmFsdWUubWVkaWFUeXBlKSB8fCB0eXBlb2YgdmFsdWUucm9sZSAhPSBcInN0cmluZ1wiIHx8XG4gICAgIShnZW5lcmF0ZWQgPyBbXCJlbnRyeVwiLCBcInNvdXJjZVwiLCBcIm1hbmlmZXN0XCIsIFwic3VwcG9ydFwiLCBcIm1hcHBpbmdcIiwgXCJyZXNvdXJjZVwiLCBcImxvYWRlclwiXS5pbmNsdWRlcyh2YWx1ZS5yb2xlKSA6XG4gICAgICBidWlsZFJvbGVQYXR0ZXJuLnRlc3QodmFsdWUucm9sZSkpIHx8XG4gICAgKGdlbmVyYXRlZCAmJiB2YWx1ZS5jb250ZW50S2luZCAhPSBcInRleHRcIiAmJiB2YWx1ZS5jb250ZW50S2luZCAhPSBcImJpbmFyeVwiKSB8fFxuICAgIChnZW5lcmF0ZWQgJiYgIWlzUGxhaW5PYmplY3QodmFsdWUucHJvdmVuYW5jZSkpIHx8XG4gICAgIWlzUGxhaW5PYmplY3QodmFsdWUuaGFzaCkgfHwgIWhhc0V4YWN0S2V5cyh2YWx1ZS5oYXNoLCBbXCJhbGdvcml0aG1cIiwgXCJ2YWx1ZVwiXSkgfHwgdmFsdWUuaGFzaC5hbGdvcml0aG0gIT0gXCJzaGEyNTZcIiB8fFxuICAgIHR5cGVvZiB2YWx1ZS5oYXNoLnZhbHVlICE9IFwic3RyaW5nXCIgfHwgIS9eW2EtZjAtOV17NjR9JC91LnRlc3QodmFsdWUuaGFzaC52YWx1ZSkpIHtcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJNQUxGT1JNRURfR0VORVJBVElPTl9NQU5JRkVTVFwiLCBwcm9qZWN0SWQsXG4gICAgICBcIkdlbmVyYXRpb24gbWFuaWZlc3QgY29udGFpbnMgYW4gaW52YWxpZCBhcnRpZmFjdCByZWNvcmQuXCIpXG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZSgvKiogQHR5cGUge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGlvbkFydGlmYWN0TWFuaWZlc3QgfCBpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLkdlbmVyYXRpb25CdWlsZEFydGlmYWN0TWFuaWZlc3R9ICovICh7XG4gICAgYnl0ZUxlbmd0aDogdmFsdWUuYnl0ZUxlbmd0aCxcbiAgICAuLi4oZ2VuZXJhdGVkID8ge2NvbnRlbnRLaW5kOiB2YWx1ZS5jb250ZW50S2luZH0gOiB7fSksXG4gICAgaGFzaDogT2JqZWN0LmZyZWV6ZSh7YWxnb3JpdGhtOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJzaGEyNTZcIiksIHZhbHVlOiB2YWx1ZS5oYXNoLnZhbHVlfSksXG4gICAgbWVkaWFUeXBlOiB2YWx1ZS5tZWRpYVR5cGUsXG4gICAgcGF0aDogdmFsdWUucGF0aCxcbiAgICAuLi4oZ2VuZXJhdGVkID8ge3Byb3ZlbmFuY2U6IGRlZXBGcmVlemUoLyoqIEB0eXBlIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLkFydGlmYWN0UHJvdmVuYW5jZX0gKi8gKHZhbHVlLnByb3ZlbmFuY2UpKX0gOiB7fSksXG4gICAgcm9sZTogdmFsdWUucm9sZVxuICB9KSlcbn1cblxuLyoqXG4gKiBDb25zdHJ1Y3RzIGEgZnJvemVuIHJlc29sdmVkLWdlbmVyYXRpb24gcmVzdWx0LlxuICogQHBhcmFtIHtzdHJpbmd9IHB1YmxpY2F0aW9uUm9vdCAtIFB1YmxpY2F0aW9uIHJvb3QuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGlvbk1hbmlmZXN0fSBtYW5pZmVzdCAtIFZlcmlmaWVkIG1hbmlmZXN0LlxuICogQHBhcmFtIHtib29sZWFufSBjbGVhbnVwUGVuZGluZyAtIFdoZXRoZXIgY2xlYW51cCByZW1haW5zLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuUHVibGlzaGVkR2VuZXJhdGlvbn0gRnJvemVuIHJlc3VsdC5cbiAqL1xuZnVuY3Rpb24gcHVibGlzaGVkR2VuZXJhdGlvbihwdWJsaWNhdGlvblJvb3QsIG1hbmlmZXN0LCBjbGVhbnVwUGVuZGluZykge1xuICBjb25zdCBnZW5lcmF0aW9uUGF0aCA9IHBhdGguam9pbihwdWJsaWNhdGlvblJvb3QsIGdlbmVyYXRpb25zTmFtZSwgbWFuaWZlc3QuZ2VuZXJhdGlvbklkKVxuICBjb25zdCB0YXJnZXRzID0gbWFuaWZlc3QudGFyZ2V0cy5tYXAodGFyZ2V0ID0+IE9iamVjdC5mcmVlemUoe1xuICAgIGJ1aWxkUGF0aDogcGF0aC5qb2luKGdlbmVyYXRpb25QYXRoLCB0YXJnZXQucHJvamVjdGlvbnMuYnVpbGQpLFxuICAgIGlkOiB0YXJnZXQuaWQsXG4gICAgcm9sZTogdGFyZ2V0LnJvbGUsXG4gICAgc291cmNlUGF0aDogcGF0aC5qb2luKGdlbmVyYXRpb25QYXRoLCB0YXJnZXQucHJvamVjdGlvbnMuc291cmNlKVxuICB9KSlcblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG4gICAgY2xlYW51cFBlbmRpbmcsXG4gICAgZ2VuZXJhdGlvbklkOiBtYW5pZmVzdC5nZW5lcmF0aW9uSWQsXG4gICAgZ2VuZXJhdGlvblBhdGgsXG4gICAgbWFuaWZlc3QsXG4gICAgbWFuaWZlc3RQYXRoOiBwYXRoLmpvaW4oZ2VuZXJhdGlvblBhdGgsIFwibWFuaWZlc3QuanNvblwiKSxcbiAgICB0YXJnZXRzOiBPYmplY3QuZnJlZXplKHRhcmdldHMpXG4gIH0pXG59XG5cbi8qKlxuICogUHJvYmVzIHRoZSBleGFjdCBzYW1lLWRpcmVjdG9yeSByZWd1bGFyLWZpbGUgcmVwbGFjZW1lbnQgcHJpbWl0aXZlIHVzZWQgYnkgdGhlIGFjdGl2ZSBwb2ludGVyLlxuICogQHBhcmFtIHtzdHJpbmd9IHB1YmxpY2F0aW9uUm9vdCAtIFB1YmxpY2F0aW9uIHJvb3QuXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvamVjdElkIC0gUHJvamVjdCBpZGVudGl0eS5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBDb21wbGV0aW9uLlxuICovXG5hc3luYyBmdW5jdGlvbiB2ZXJpZnlBdG9taWNSZXBsYWNlbWVudChwdWJsaWNhdGlvblJvb3QsIHByb2plY3RJZCkge1xuICBjb25zdCBpZGVudGl0eSA9IHJhbmRvbVVVSUQoKVxuICBjb25zdCBzb3VyY2UgPSBwYXRoLmpvaW4ocHVibGljYXRpb25Sb290LCBgLnNlbWFudGlmb2xkLWF0b21pYy0ke2lkZW50aXR5fS5zb3VyY2VgKVxuICBjb25zdCBkZXN0aW5hdGlvbiA9IHBhdGguam9pbihwdWJsaWNhdGlvblJvb3QsIGAuc2VtYW50aWZvbGQtYXRvbWljLSR7aWRlbnRpdHl9LmRlc3RpbmF0aW9uYClcbiAgY29uc3QgZXhwZWN0ZWQgPSBCdWZmZXIuZnJvbShcImNhbmRpZGF0ZVxcblwiKVxuICBsZXQgc291cmNlQ3JlYXRlZCA9IGZhbHNlXG4gIGxldCBkZXN0aW5hdGlvbkNyZWF0ZWQgPSBmYWxzZVxuXG4gIHRyeSB7XG4gICAgYXdhaXQgd3JpdGVTeW5jZWRGaWxlKHNvdXJjZSwgQnVmZmVyLmZyb20oXCJjYW5kaWRhdGVcXG5cIiksIFwid3hcIilcbiAgICBzb3VyY2VDcmVhdGVkID0gdHJ1ZVxuICAgIGF3YWl0IHdyaXRlU3luY2VkRmlsZShkZXN0aW5hdGlvbiwgQnVmZmVyLmZyb20oXCJwcmV2aW91c1xcblwiKSwgXCJ3eFwiKVxuICAgIGRlc3RpbmF0aW9uQ3JlYXRlZCA9IHRydWVcbiAgICBhd2FpdCByZW5hbWUoc291cmNlLCBkZXN0aW5hdGlvbilcbiAgICBzb3VyY2VDcmVhdGVkID0gZmFsc2VcbiAgICBhd2FpdCBzeW5jRGlyZWN0b3J5KHB1YmxpY2F0aW9uUm9vdClcbiAgICBjb25zdCBkZXN0aW5hdGlvblN0YXR1cyA9IGF3YWl0IGxzdGF0KGRlc3RpbmF0aW9uKVxuICAgIGNvbnN0IHJlcGxhY2VkID0gYXdhaXQgcmVhZEZpbGUoZGVzdGluYXRpb24pXG5cbiAgICBpZiAoIWRlc3RpbmF0aW9uU3RhdHVzLmlzRmlsZSgpIHx8IGRlc3RpbmF0aW9uU3RhdHVzLmlzU3ltYm9saWNMaW5rKCkgfHwgIXJlcGxhY2VkLmVxdWFscyhleHBlY3RlZCkpIHtcbiAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX0FUT01JQ19SRVBMQUNFX1VOU1VQUE9SVEVEXCIsIHByb2plY3RJZCxcbiAgICAgICAgXCJGaWxlc3lzdGVtIGRpZCBub3QgcHJvdmlkZSBzYW1lLWRpcmVjdG9yeSByZWd1bGFyLWZpbGUgcmVwbGFjZW1lbnQuXCIpXG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBsc3RhdChzb3VyY2UpXG4gICAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9BVE9NSUNfUkVQTEFDRV9VTlNVUFBPUlRFRFwiLCBwcm9qZWN0SWQsXG4gICAgICAgIFwiRmlsZXN5c3RlbSBkaWQgbm90IHJlbW92ZSB0aGUgcmVwbGFjZWQgdGVtcG9yYXJ5IG5hbWUgYXRvbWljYWxseS5cIilcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKCFpc0Vycm9yQ29kZShlcnJvciwgXCJFTk9FTlRcIikpIHRocm93IGVycm9yXG4gICAgfVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFNlbWFudGlmb2xkRGlhZ25vc3RpYykgdGhyb3cgZXJyb3JcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9BVE9NSUNfUkVQTEFDRV9VTlNVUFBPUlRFRFwiLCBwcm9qZWN0SWQsXG4gICAgICBcIkZpbGVzeXN0ZW0gZGlkIG5vdCBwcm92aWRlIHNhbWUtZGlyZWN0b3J5IHJlZ3VsYXItZmlsZSByZXBsYWNlbWVudC5cIiwgZXJyb3IpXG4gIH0gZmluYWxseSB7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFtcbiAgICAgIC4uLihzb3VyY2VDcmVhdGVkID8gW3JtKHNvdXJjZSwge2ZvcmNlOiB0cnVlfSldIDogW10pLFxuICAgICAgLi4uKGRlc3RpbmF0aW9uQ3JlYXRlZCA/IFtybShkZXN0aW5hdGlvbiwge2ZvcmNlOiB0cnVlfSldIDogW10pXG4gICAgXSlcbiAgfVxufVxuXG4vKipcbiAqIFdyaXRlcyBhbmQgc3luY2hyb25pemVzIG9uZSBuZXdseSBvd25lZCBmaWxlLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gRXhhY3QgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IGJ5dGVzIC0gRXhhY3QgYnl0ZXMuXG4gKiBAcGFyYW0ge1wid3hcIn0gZmxhZyAtIEV4Y2x1c2l2ZSBjcmVhdGlvbiBtb2RlLlxuICogQHBhcmFtIHsoKSA9PiB2b2lkfSBbb25DcmVhdGVkXSAtIENhbGxlZCBpbW1lZGlhdGVseSBhZnRlciBleGNsdXNpdmUgY3JlYXRpb24gc3VjY2VlZHMuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQ29tcGxldGlvbi5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gd3JpdGVTeW5jZWRGaWxlKGZpbGVuYW1lLCBieXRlcywgZmxhZywgb25DcmVhdGVkKSB7XG4gIGNvbnN0IGhhbmRsZSA9IGF3YWl0IG9wZW4oZmlsZW5hbWUsIGZsYWcsIDBvNjAwKVxuXG4gIG9uQ3JlYXRlZD8uKClcbiAgLyoqIEB0eXBlIHt1bmtub3dufSAqL1xuICBsZXQgZmFpbHVyZVxuXG4gIHRyeSB7XG4gICAgYXdhaXQgaGFuZGxlLndyaXRlRmlsZShieXRlcylcbiAgICBhd2FpdCBoYW5kbGUuc3luYygpXG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgZmFpbHVyZSA9IGVycm9yXG4gIH0gZmluYWxseSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGhhbmRsZS5jbG9zZSgpXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChmYWlsdXJlID09PSB1bmRlZmluZWQpIGZhaWx1cmUgPSBlcnJvclxuICAgIH1cbiAgfVxuICBpZiAoZmFpbHVyZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgYXdhaXQgcm0oZmlsZW5hbWUsIHtmb3JjZTogdHJ1ZX0pLmNhdGNoKCgpID0+IHt9KVxuICAgIHRocm93IGZhaWx1cmVcbiAgfVxufVxuXG4vKipcbiAqIFJlYWRzIGFuZCBzeW5jaHJvbml6ZXMgb25lIHJlZ3VsYXIgbm9uLXN5bWxpbmsgZmlsZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIEV4YWN0IGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHByb2plY3RJZCAtIFByb2plY3QgaWRlbnRpdHkuXG4gKiBAcGFyYW0ge3N0cmluZ30gY29kZSAtIEZhaWx1cmUgY29kZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gU3RhYmxlIGZhaWx1cmUgZGV0YWlsLlxuICogQHJldHVybnMge1Byb21pc2U8QnVmZmVyPn0gRXhhY3QgYnl0ZXMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlYWRBbmRTeW5jUmVndWxhckZpbGUoZmlsZW5hbWUsIHByb2plY3RJZCwgY29kZSwgbWVzc2FnZSkge1xuICB0cnkge1xuICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IGxzdGF0KGZpbGVuYW1lKVxuXG4gICAgaWYgKCFzdGF0dXMuaXNGaWxlKCkgfHwgc3RhdHVzLmlzU3ltYm9saWNMaW5rKCkpIHB1YmxpY2F0aW9uRmFpbHVyZShjb2RlLCBwcm9qZWN0SWQsIG1lc3NhZ2UpXG4gICAgYXNzZXJ0UmVndWxhckZpbGVJbW11dGFiaWxpdHkoc3RhdHVzLCBuZXcgU2V0KCksIHByb2plY3RJZClcbiAgICBjb25zdCBoYW5kbGUgPSBhd2FpdCBvcGVuKGZpbGVuYW1lLCBjb25zdGFudHMuT19SRE9OTFkpXG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgYnl0ZXMgPSBhd2FpdCBoYW5kbGUucmVhZEZpbGUoKVxuXG4gICAgICBhd2FpdCBoYW5kbGUuc3luYygpXG5cbiAgICAgIHJldHVybiBieXRlc1xuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCBoYW5kbGUuY2xvc2UoKVxuICAgIH1cbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBTZW1hbnRpZm9sZERpYWdub3N0aWMpIHRocm93IGVycm9yXG4gICAgcHVibGljYXRpb25GYWlsdXJlKGNvZGUsIHByb2plY3RJZCwgbWVzc2FnZSwgZXJyb3IpXG4gIH1cbn1cblxuLyoqXG4gKiBMaXN0cyBldmVyeSByZWd1bGFyIGZpbGUgYmVuZWF0aCBvbmUgcHJvamVjdGlvbiBhbmQgcmVqZWN0cyBzeW1saW5rcyBvciBzcGVjaWFsIG5vZGVzLlxuICogQHBhcmFtIHtzdHJpbmd9IGRpcmVjdG9yeSAtIFByb2plY3Rpb24gcm9vdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9qZWN0SWQgLSBQcm9qZWN0IGlkZW50aXR5LlxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nW10+fSBTb3J0ZWQgcmVsYXRpdmUgUE9TSVggcGF0aHMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGxpc3RSZWd1bGFyRmlsZXMoZGlyZWN0b3J5LCBwcm9qZWN0SWQpIHtcbiAgLyoqIEB0eXBlIHtzdHJpbmdbXX0gKi9cbiAgY29uc3QgZmlsZXMgPSBbXVxuICBjb25zdCBpZGVudGl0aWVzID0gbmV3IFNldCgpXG5cbiAgdHJ5IHtcbiAgICBhd2FpdCB2aXNpdChkaXJlY3RvcnksIFwiXCIpXG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKGVycm9yIGluc3RhbmNlb2YgU2VtYW50aWZvbGREaWFnbm9zdGljKSB0aHJvdyBlcnJvclxuICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX0dFTkVSQVRJT05fVkVSSUZJQ0FUSU9OX0ZBSUxFRFwiLCBwcm9qZWN0SWQsXG4gICAgICBcIkltbXV0YWJsZSBnZW5lcmF0aW9uIGZpbGVzeXN0ZW0gaW52ZW50b3J5IGNvdWxkIG5vdCBiZSB2ZXJpZmllZC5cIiwgZXJyb3IpXG4gIH1cblxuICByZXR1cm4gZmlsZXMuc29ydChjb21wYXJlU3RyaW5ncylcblxuICAvKipcbiAgICogVmlzaXRzIG9uZSBvd25lZCBkaXJlY3RvcnkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjdXJyZW50IC0gRXhhY3QgZGlyZWN0b3J5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcmVsYXRpdmUgLSBQcm9qZWN0aW9uLXJlbGF0aXZlIHBhdGguXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBDb21wbGV0aW9uLlxuICAgKi9cbiAgYXN5bmMgZnVuY3Rpb24gdmlzaXQoY3VycmVudCwgcmVsYXRpdmUpIHtcbiAgICBhd2FpdCBhc3NlcnRSZWFsSW52ZW50b3J5RGlyZWN0b3J5KGN1cnJlbnQsIHByb2plY3RJZClcbiAgICBjb25zdCBlbnRyaWVzID0gYXdhaXQgcmVhZGRpcihjdXJyZW50KVxuXG4gICAgZW50cmllcy5zb3J0KGNvbXBhcmVTdHJpbmdzKVxuICAgIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgICAgY29uc3QgY2hpbGRSZWxhdGl2ZSA9IHJlbGF0aXZlLmxlbmd0aCA9PSAwID8gZW50cnkgOiBgJHtyZWxhdGl2ZX0vJHtlbnRyeX1gXG5cbiAgICAgIGlmICghaXNTYWZlQXJ0aWZhY3RQYXRoKGNoaWxkUmVsYXRpdmUpKSB7XG4gICAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIklOVkFMSURfUFVCTElDQVRJT05fUFJPSkVDVElPTlwiLCBwcm9qZWN0SWQsXG4gICAgICAgICAgXCJWYWxpZGF0b3Igb3V0cHV0IGNvbnRhaW5zIGEgbm9uLWNhbm9uaWNhbCByZWxhdGl2ZSBwYXRoLlwiKVxuICAgICAgfVxuICAgICAgY29uc3QgY2hpbGQgPSBwYXRoLmpvaW4oY3VycmVudCwgZW50cnkpXG4gICAgICBjb25zdCBzdGF0dXMgPSBhd2FpdCBsc3RhdChjaGlsZClcblxuICAgICAgaWYgKHN0YXR1cy5pc1N5bWJvbGljTGluaygpKSB7XG4gICAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX1NZTUxJTktfVFJBVkVSU0FMXCIsIHByb2plY3RJZCxcbiAgICAgICAgICBcIkNhbmRpZGF0ZSBnZW5lcmF0aW9uIGNvbnRhaW5zIGEgc3ltYm9saWMgbGluay5cIilcbiAgICAgIH1cbiAgICAgIGlmIChzdGF0dXMuaXNEaXJlY3RvcnkoKSkgYXdhaXQgdmlzaXQoY2hpbGQsIGNoaWxkUmVsYXRpdmUpXG4gICAgICBlbHNlIGlmIChzdGF0dXMuaXNGaWxlKCkpIHtcbiAgICAgICAgYXNzZXJ0UmVndWxhckZpbGVJbW11dGFiaWxpdHkoc3RhdHVzLCBpZGVudGl0aWVzLCBwcm9qZWN0SWQpXG4gICAgICAgIGZpbGVzLnB1c2goY2hpbGRSZWxhdGl2ZSlcbiAgICAgIH0gZWxzZSBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9HRU5FUkFUSU9OX0lOVkVOVE9SWV9NSVNNQVRDSFwiLCBwcm9qZWN0SWQsXG4gICAgICAgIFwiSW1tdXRhYmxlIGdlbmVyYXRpb24gY29udGFpbnMgYW4gdW5kZWNsYXJlZCBmaWxlc3lzdGVtIGVudHJ5LlwiKVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFZlcmlmaWVzIHRoYXQgdGhlIG1hbmlmZXN0IGRlc2NyaWJlcyBldmVyeSBkaXJlY3RvcnkgYW5kIHJlZ3VsYXIgZmlsZSBpbiB0aGUgaW1tdXRhYmxlIGdlbmVyYXRpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gZ2VuZXJhdGlvblBhdGggLSBFeGFjdCBnZW5lcmF0aW9uIHJvb3QuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGlvbk1hbmlmZXN0fSBtYW5pZmVzdCAtIFZlcmlmaWVkIG1hbmlmZXN0LlxuICogQHBhcmFtIHtzdHJpbmd9IHByb2plY3RJZCAtIFByb2plY3QgaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQ29tcGxldGlvbi5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gdmVyaWZ5R2VuZXJhdGlvbkludmVudG9yeShnZW5lcmF0aW9uUGF0aCwgbWFuaWZlc3QsIHByb2plY3RJZCkge1xuICBjb25zdCBleHBlY3RlZEZpbGVzID0gbmV3IFNldChbXCJtYW5pZmVzdC5qc29uXCJdKVxuICBjb25zdCBleHBlY3RlZERpcmVjdG9yaWVzID0gbmV3IFNldCgpXG5cbiAgZm9yIChjb25zdCB0YXJnZXQgb2YgbWFuaWZlc3QudGFyZ2V0cykge1xuICAgIGFkZEV4cGVjdGVkRGlyZWN0b3J5KHRhcmdldC5wcm9qZWN0aW9ucy5zb3VyY2UpXG4gICAgYWRkRXhwZWN0ZWREaXJlY3RvcnkodGFyZ2V0LnByb2plY3Rpb25zLmJ1aWxkKVxuICAgIGZvciAoY29uc3QgYXJ0aWZhY3Qgb2YgdGFyZ2V0LmFydGlmYWN0cykge1xuICAgICAgYWRkRXhwZWN0ZWRGaWxlKGAke3RhcmdldC5wcm9qZWN0aW9ucy5zb3VyY2V9LyR7YXJ0aWZhY3QucGF0aH1gKVxuICAgIH1cbiAgICBmb3IgKGNvbnN0IGFydGlmYWN0IG9mIHRhcmdldC5idWlsZEFydGlmYWN0cykge1xuICAgICAgYWRkRXhwZWN0ZWRGaWxlKGAke3RhcmdldC5wcm9qZWN0aW9ucy5idWlsZH0vJHthcnRpZmFjdC5wYXRofWApXG4gICAgfVxuICB9XG4gIC8qKiBAdHlwZSB7U2V0PHN0cmluZz59ICovXG4gIGNvbnN0IG9ic2VydmVkRmlsZXMgPSBuZXcgU2V0KClcbiAgLyoqIEB0eXBlIHtTZXQ8c3RyaW5nPn0gKi9cbiAgY29uc3Qgb2JzZXJ2ZWREaXJlY3RvcmllcyA9IG5ldyBTZXQoKVxuICBjb25zdCBpZGVudGl0aWVzID0gbmV3IFNldCgpXG5cbiAgdHJ5IHtcbiAgICBhd2FpdCB2aXNpdChnZW5lcmF0aW9uUGF0aCwgXCJcIilcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBTZW1hbnRpZm9sZERpYWdub3N0aWMpIHRocm93IGVycm9yXG4gICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fR0VORVJBVElPTl9WRVJJRklDQVRJT05fRkFJTEVEXCIsIHByb2plY3RJZCxcbiAgICAgIFwiSW1tdXRhYmxlIGdlbmVyYXRpb24gZmlsZXN5c3RlbSBpbnZlbnRvcnkgY291bGQgbm90IGJlIHZlcmlmaWVkLlwiLCBlcnJvcilcbiAgfVxuICBpZiAoIXNhbWVTdHJpbmdTZXQoZXhwZWN0ZWRGaWxlcywgb2JzZXJ2ZWRGaWxlcykgfHwgIXNhbWVTdHJpbmdTZXQoZXhwZWN0ZWREaXJlY3Rvcmllcywgb2JzZXJ2ZWREaXJlY3RvcmllcykpIHtcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9HRU5FUkFUSU9OX0lOVkVOVE9SWV9NSVNNQVRDSFwiLCBwcm9qZWN0SWQsXG4gICAgICBcIkltbXV0YWJsZSBnZW5lcmF0aW9uIGNvbnRhaW5zIGFuIHVuZGVjbGFyZWQgZmlsZXN5c3RlbSBlbnRyeS5cIilcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIG9uZSBleHBlY3RlZCBkaXJlY3RvcnkgYW5kIGVhY2ggZ2VuZXJhdGlvbi1yZWxhdGl2ZSBwYXJlbnQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSByZWxhdGl2ZSAtIFBPU0lYLXN0eWxlIGdlbmVyYXRpb24tcmVsYXRpdmUgZGlyZWN0b3J5LlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIGZ1bmN0aW9uIGFkZEV4cGVjdGVkRGlyZWN0b3J5KHJlbGF0aXZlKSB7XG4gICAgY29uc3QgcGFydHMgPSByZWxhdGl2ZS5zcGxpdChcIi9cIilcblxuICAgIGZvciAobGV0IGluZGV4ID0gMTsgaW5kZXggPD0gcGFydHMubGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgICBleHBlY3RlZERpcmVjdG9yaWVzLmFkZChwYXJ0cy5zbGljZSgwLCBpbmRleCkuam9pbihcIi9cIikpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgb25lIGV4cGVjdGVkIHJlZ3VsYXIgZmlsZSBhbmQgaXRzIHBhcmVudCBkaXJlY3Rvcmllcy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHJlbGF0aXZlIC0gUE9TSVgtc3R5bGUgZ2VuZXJhdGlvbi1yZWxhdGl2ZSBmaWxlbmFtZS5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBmdW5jdGlvbiBhZGRFeHBlY3RlZEZpbGUocmVsYXRpdmUpIHtcbiAgICBleHBlY3RlZEZpbGVzLmFkZChyZWxhdGl2ZSlcbiAgICBjb25zdCBzZXBhcmF0b3IgPSByZWxhdGl2ZS5sYXN0SW5kZXhPZihcIi9cIilcblxuICAgIGlmIChzZXBhcmF0b3IgPj0gMCkgYWRkRXhwZWN0ZWREaXJlY3RvcnkocmVsYXRpdmUuc2xpY2UoMCwgc2VwYXJhdG9yKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBWaXNpdHMgZXZlcnkgZW50cnkgaW4gb25lIGdlbmVyYXRpb24gZGlyZWN0b3J5IHdpdGhvdXQgZm9sbG93aW5nIGxpbmtzLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gY3VycmVudCAtIEV4YWN0IGRpcmVjdG9yeS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHJlbGF0aXZlIC0gR2VuZXJhdGlvbi1yZWxhdGl2ZSBkaXJlY3RvcnkuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBDb21wbGV0aW9uLlxuICAgKi9cbiAgYXN5bmMgZnVuY3Rpb24gdmlzaXQoY3VycmVudCwgcmVsYXRpdmUpIHtcbiAgICBhd2FpdCBhc3NlcnRSZWFsSW52ZW50b3J5RGlyZWN0b3J5KGN1cnJlbnQsIHByb2plY3RJZClcbiAgICBjb25zdCBlbnRyaWVzID0gYXdhaXQgcmVhZGRpcihjdXJyZW50KVxuXG4gICAgZW50cmllcy5zb3J0KGNvbXBhcmVTdHJpbmdzKVxuICAgIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgICAgY29uc3QgY2hpbGRSZWxhdGl2ZSA9IHJlbGF0aXZlLmxlbmd0aCA9PSAwID8gZW50cnkgOiBgJHtyZWxhdGl2ZX0vJHtlbnRyeX1gXG5cbiAgICAgIGlmICghaXNTYWZlQXJ0aWZhY3RQYXRoKGNoaWxkUmVsYXRpdmUpKSB7XG4gICAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX0dFTkVSQVRJT05fSU5WRU5UT1JZX01JU01BVENIXCIsIHByb2plY3RJZCxcbiAgICAgICAgICBcIkltbXV0YWJsZSBnZW5lcmF0aW9uIGNvbnRhaW5zIGFuIHVuZGVjbGFyZWQgZmlsZXN5c3RlbSBlbnRyeS5cIilcbiAgICAgIH1cbiAgICAgIGNvbnN0IGNoaWxkID0gcGF0aC5qb2luKGN1cnJlbnQsIGVudHJ5KVxuICAgICAgY29uc3Qgc3RhdHVzID0gYXdhaXQgbHN0YXQoY2hpbGQpXG5cbiAgICAgIGlmIChzdGF0dXMuaXNTeW1ib2xpY0xpbmsoKSkge1xuICAgICAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9TWU1MSU5LX1RSQVZFUlNBTFwiLCBwcm9qZWN0SWQsXG4gICAgICAgICAgXCJDYW5kaWRhdGUgZ2VuZXJhdGlvbiBjb250YWlucyBhIHN5bWJvbGljIGxpbmsuXCIpXG4gICAgICB9XG4gICAgICBpZiAoc3RhdHVzLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgb2JzZXJ2ZWREaXJlY3Rvcmllcy5hZGQoY2hpbGRSZWxhdGl2ZSlcbiAgICAgICAgYXdhaXQgdmlzaXQoY2hpbGQsIGNoaWxkUmVsYXRpdmUpXG4gICAgICB9IGVsc2UgaWYgKHN0YXR1cy5pc0ZpbGUoKSkge1xuICAgICAgICBhc3NlcnRSZWd1bGFyRmlsZUltbXV0YWJpbGl0eShzdGF0dXMsIGlkZW50aXRpZXMsIHByb2plY3RJZClcbiAgICAgICAgb2JzZXJ2ZWRGaWxlcy5hZGQoY2hpbGRSZWxhdGl2ZSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX0dFTkVSQVRJT05fSU5WRU5UT1JZX01JU01BVENIXCIsIHByb2plY3RJZCxcbiAgICAgICAgICBcIkltbXV0YWJsZSBnZW5lcmF0aW9uIGNvbnRhaW5zIGFuIHVuZGVjbGFyZWQgZmlsZXN5c3RlbSBlbnRyeS5cIilcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBWZXJpZmllcyBvbmUgaW52ZW50b3J5IHRyYXZlcnNhbCByb290IHdpdGhvdXQgZm9sbG93aW5nIHN5bWJvbGljIGxpbmtzLlxuICogQHBhcmFtIHtzdHJpbmd9IGRpcmVjdG9yeSAtIEV4YWN0IGRpcmVjdG9yeSBhYm91dCB0byBiZSByZWFkLlxuICogQHBhcmFtIHtzdHJpbmd9IHByb2plY3RJZCAtIFByb2plY3QgaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQ29tcGxldGlvbi5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gYXNzZXJ0UmVhbEludmVudG9yeURpcmVjdG9yeShkaXJlY3RvcnksIHByb2plY3RJZCkge1xuICBjb25zdCBzdGF0dXMgPSBhd2FpdCBsc3RhdChkaXJlY3RvcnkpXG5cbiAgaWYgKHN0YXR1cy5pc1N5bWJvbGljTGluaygpKSB7XG4gICAgcHVibGljYXRpb25GYWlsdXJlKFwiUFVCTElDQVRJT05fU1lNTElOS19UUkFWRVJTQUxcIiwgcHJvamVjdElkLFxuICAgICAgXCJDYW5kaWRhdGUgZ2VuZXJhdGlvbiBjb250YWlucyBhIHN5bWJvbGljIGxpbmsuXCIpXG4gIH1cbiAgaWYgKCFzdGF0dXMuaXNEaXJlY3RvcnkoKSkge1xuICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX0dFTkVSQVRJT05fSU5WRU5UT1JZX01JU01BVENIXCIsIHByb2plY3RJZCxcbiAgICAgIFwiSW1tdXRhYmxlIGdlbmVyYXRpb24gY29udGFpbnMgYW4gdW5kZWNsYXJlZCBmaWxlc3lzdGVtIGVudHJ5LlwiKVxuICB9XG59XG5cbi8qKlxuICogUmVqZWN0cyBleHRlcm5hbCBoYXJkIGxpbmtzIGFuZCBkdXBsaWNhdGUgc3RhYmxlIGZpbGUgaWRlbnRpdGllcy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwibm9kZTpmc1wiKS5TdGF0c30gc3RhdHVzIC0gUmVndWxhci1maWxlIHN0YXR1cy5cbiAqIEBwYXJhbSB7U2V0PHN0cmluZz59IGlkZW50aXRpZXMgLSBQcmV2aW91c2x5IG9ic2VydmVkIGRldmljZS9pbm9kZSBpZGVudGl0aWVzLlxuICogQHBhcmFtIHtzdHJpbmd9IHByb2plY3RJZCAtIFByb2plY3QgaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gYXNzZXJ0UmVndWxhckZpbGVJbW11dGFiaWxpdHkoc3RhdHVzLCBpZGVudGl0aWVzLCBwcm9qZWN0SWQpIHtcbiAgaWYgKHN0YXR1cy5ubGluayA+IDEpIHtcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9IQVJEX0xJTktcIiwgcHJvamVjdElkLFxuICAgICAgXCJJbW11dGFibGUgZ2VuZXJhdGlvbiBmaWxlcyBtdXN0IG5vdCBoYXZlIGV4dGVybmFsIGhhcmQgbGlua3MuXCIpXG4gIH1cbiAgY29uc3QgaWRlbnRpdHkgPSBzdGFibGVGaWxlSWRlbnRpdHkoc3RhdHVzKVxuXG4gIGlmIChpZGVudGl0eSAhPT0gbnVsbCkge1xuICAgIGlmIChpZGVudGl0aWVzLmhhcyhpZGVudGl0eSkpIHtcbiAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX0hBUkRfTElOS1wiLCBwcm9qZWN0SWQsXG4gICAgICAgIFwiSW1tdXRhYmxlIGdlbmVyYXRpb24gZmlsZXMgbXVzdCBoYXZlIHVuaXF1ZSBmaWxlc3lzdGVtIGlkZW50aXRpZXMuXCIpXG4gICAgfVxuICAgIGlkZW50aXRpZXMuYWRkKGlkZW50aXR5KVxuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyBhIHN0YWJsZSBkZXZpY2UvaW5vZGUgaWRlbnRpdHkgb25seSB3aGVyZSB0aGUgaG9zdCByZXBvcnRzIG9uZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwibm9kZTpmc1wiKS5TdGF0c30gc3RhdHVzIC0gRmlsZSBzdGF0dXMuXG4gKiBAcmV0dXJucyB7c3RyaW5nIHwgbnVsbH0gSWRlbnRpdHkgb3IgdW5hdmFpbGFibGUuXG4gKi9cbmZ1bmN0aW9uIHN0YWJsZUZpbGVJZGVudGl0eShzdGF0dXMpIHtcbiAgaWYgKCh0eXBlb2Ygc3RhdHVzLmRldiAhPSBcIm51bWJlclwiICYmIHR5cGVvZiBzdGF0dXMuZGV2ICE9IFwiYmlnaW50XCIpIHx8XG4gICAgKHR5cGVvZiBzdGF0dXMuaW5vICE9IFwibnVtYmVyXCIgJiYgdHlwZW9mIHN0YXR1cy5pbm8gIT0gXCJiaWdpbnRcIikgfHwgc3RhdHVzLmlubyA9PSAwKSByZXR1cm4gbnVsbFxuXG4gIHJldHVybiBgJHtTdHJpbmcoc3RhdHVzLmRldil9OiR7U3RyaW5nKHN0YXR1cy5pbm8pfWBcbn1cblxuLyoqXG4gKiBDb21wYXJlcyB0d28gc3RyaW5nIHNldHMgZXhhY3RseS5cbiAqIEBwYXJhbSB7U2V0PHN0cmluZz59IGxlZnQgLSBGaXJzdCBzZXQuXG4gKiBAcGFyYW0ge1NldDxzdHJpbmc+fSByaWdodCAtIFNlY29uZCBzZXQuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gRXF1YWxpdHkuXG4gKi9cbmZ1bmN0aW9uIHNhbWVTdHJpbmdTZXQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuc2l6ZSA9PSByaWdodC5zaXplICYmIFsuLi5sZWZ0XS5ldmVyeSh2YWx1ZSA9PiByaWdodC5oYXModmFsdWUpKVxufVxuXG4vKipcbiAqIFN5bmNocm9uaXplcyBldmVyeSBkaXJlY3RvcnkgaW4gYSBzdGFnZWQgdHJlZSBmcm9tIGxlYXZlcyB0byByb290LlxuICogQHBhcmFtIHtzdHJpbmd9IHJvb3QgLSBUcmVlIHJvb3QuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQ29tcGxldGlvbi5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gc3luY1RyZWVEaXJlY3Rvcmllcyhyb290KSB7XG4gIGNvbnN0IGVudHJpZXMgPSBhd2FpdCByZWFkZGlyKHJvb3QsIHt3aXRoRmlsZVR5cGVzOiB0cnVlfSlcblxuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICBpZiAoZW50cnkuaXNEaXJlY3RvcnkoKSAmJiAhZW50cnkuaXNTeW1ib2xpY0xpbmsoKSkgYXdhaXQgc3luY1RyZWVEaXJlY3RvcmllcyhwYXRoLmpvaW4ocm9vdCwgZW50cnkubmFtZSkpXG4gIH1cbiAgYXdhaXQgc3luY0RpcmVjdG9yeShyb290KVxufVxuXG4vKipcbiAqIFN5bmNocm9uaXplcyBvbmUgZGlyZWN0b3J5IGVudHJ5IHNldC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkaXJlY3RvcnkgLSBEaXJlY3RvcnkgcGF0aC5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBDb21wbGV0aW9uLlxuICovXG5hc3luYyBmdW5jdGlvbiBzeW5jRGlyZWN0b3J5KGRpcmVjdG9yeSkge1xuICBjb25zdCBoYW5kbGUgPSBhd2FpdCBvcGVuKGRpcmVjdG9yeSwgY29uc3RhbnRzLk9fUkRPTkxZKVxuXG4gIHRyeSB7XG4gICAgYXdhaXQgaGFuZGxlLnN5bmMoKVxuICB9IGZpbmFsbHkge1xuICAgIGF3YWl0IGhhbmRsZS5jbG9zZSgpXG4gIH1cbn1cblxuLyoqXG4gKiBFbnN1cmVzIGV2ZXJ5IGV4aXN0aW5nIHBhdGggY29tcG9uZW50IGlzIGEgcmVhbCBkaXJlY3RvcnkgYW5kIG9wdGlvbmFsbHkgY3JlYXRlcyBtaXNzaW5nIGNvbXBvbmVudHMuXG4gKiBAcGFyYW0ge3N0cmluZ30gZGlyZWN0b3J5IC0gQ2Fub25pY2FsIGFic29sdXRlIGRpcmVjdG9yeS5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gY3JlYXRlIC0gV2hldGhlciBtaXNzaW5nIGNvbXBvbmVudHMgbWF5IGJlIGNyZWF0ZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvamVjdElkIC0gUHJvamVjdCBpZGVudGl0eS5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBDb21wbGV0aW9uLlxuICovXG5hc3luYyBmdW5jdGlvbiBlbnN1cmVEaXJlY3RvcnlXaXRob3V0U3ltbGlua3MoZGlyZWN0b3J5LCBjcmVhdGUsIHByb2plY3RJZCkge1xuICBjb25zdCBwYXJzZWQgPSBwYXRoLnBhcnNlKGRpcmVjdG9yeSlcbiAgY29uc3QgcmVsYXRpdmUgPSBkaXJlY3Rvcnkuc2xpY2UocGFyc2VkLnJvb3QubGVuZ3RoKVxuICBjb25zdCBwYXJ0cyA9IHJlbGF0aXZlLnNwbGl0KHBhdGguc2VwKS5maWx0ZXIoQm9vbGVhbilcbiAgbGV0IGN1cnJlbnQgPSBwYXJzZWQucm9vdFxuXG4gIGZvciAoY29uc3QgcGFydCBvZiBwYXJ0cykge1xuICAgIGN1cnJlbnQgPSBwYXRoLmpvaW4oY3VycmVudCwgcGFydClcbiAgICB0cnkge1xuICAgICAgY29uc3Qgc3RhdHVzID0gYXdhaXQgbHN0YXQoY3VycmVudClcblxuICAgICAgaWYgKHN0YXR1cy5pc1N5bWJvbGljTGluaygpKSB7XG4gICAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX1NZTUxJTktfVFJBVkVSU0FMXCIsIHByb2plY3RJZCxcbiAgICAgICAgICBcIk93bmVkIHBhdGggdHJhdmVyc2FsIGVuY291bnRlcmVkIGEgc3ltYm9saWMgbGluay5cIilcbiAgICAgIH1cbiAgICAgIGlmICghc3RhdHVzLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgcHVibGljYXRpb25GYWlsdXJlKFwiSU5WQUxJRF9QVUJMSUNBVElPTl9ST09UXCIsIHByb2plY3RJZCxcbiAgICAgICAgICBcIk93bmVkIHJvb3QgcGF0aCBjb250YWlucyBhIG5vbi1kaXJlY3RvcnkgY29tcG9uZW50LlwiKVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoIWlzRXJyb3JDb2RlKGVycm9yLCBcIkVOT0VOVFwiKSkge1xuICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBTZW1hbnRpZm9sZERpYWdub3N0aWMpIHRocm93IGVycm9yXG4gICAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIklOVkFMSURfUFVCTElDQVRJT05fUk9PVFwiLCBwcm9qZWN0SWQsXG4gICAgICAgICAgXCJPd25lZCByb290IHBhdGggY291bGQgbm90IGJlIHZhbGlkYXRlZC5cIiwgZXJyb3IpXG4gICAgICB9XG4gICAgICBpZiAoIWNyZWF0ZSkge1xuICAgICAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJJTlZBTElEX1BVQkxJQ0FUSU9OX1JPT1RcIiwgcHJvamVjdElkLFxuICAgICAgICAgIFwiU291cmNlIHJvb3QgbXVzdCBleGlzdCBhcyBhIHJlYWwgZGlyZWN0b3J5LlwiLCBlcnJvcilcbiAgICAgIH1cbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IG1rZGlyKGN1cnJlbnQsIHttb2RlOiAwbzcwMH0pXG4gICAgICB9IGNhdGNoIChta2RpckVycm9yKSB7XG4gICAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIklOVkFMSURfUFVCTElDQVRJT05fUk9PVFwiLCBwcm9qZWN0SWQsXG4gICAgICAgICAgXCJQdWJsaWNhdGlvbiByb290IGNvdWxkIG5vdCBiZSBjcmVhdGVkIHNhZmVseS5cIiwgbWtkaXJFcnJvcilcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBFbnN1cmVzIG9uZSByZXNlcnZlZCBwdWJsaXNoZXIgZGlyZWN0b3J5IGlzIG5laXRoZXIgYSBzeW1saW5rIG5vciBhbiB1bm93bmVkIGZpbGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZGlyZWN0b3J5IC0gUmVzZXJ2ZWQgZGlyZWN0b3J5LlxuICogQHBhcmFtIHtzdHJpbmd9IHByb2plY3RJZCAtIFByb2plY3QgaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQ29tcGxldGlvbi5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZW5zdXJlT3duZWREaXJlY3RvcnkoZGlyZWN0b3J5LCBwcm9qZWN0SWQpIHtcbiAgdHJ5IHtcbiAgICBhd2FpdCBta2RpcihkaXJlY3RvcnksIHttb2RlOiAwbzcwMH0pXG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKCFpc0Vycm9yQ29kZShlcnJvciwgXCJFRVhJU1RcIikpIHtcbiAgICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX1NUQUdFX1dSSVRFX0ZBSUxFRFwiLCBwcm9qZWN0SWQsXG4gICAgICAgIFwiUHVibGlzaGVyLW93bmVkIGRpcmVjdG9yeSBjb3VsZCBub3QgYmUgY3JlYXRlZC5cIiwgZXJyb3IpXG4gICAgfVxuICB9XG4gIGxldCBzdGF0dXNcblxuICB0cnkge1xuICAgIHN0YXR1cyA9IGF3YWl0IGxzdGF0KGRpcmVjdG9yeSlcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoXCJQVUJMSUNBVElPTl9TVEFHRV9XUklURV9GQUlMRURcIiwgcHJvamVjdElkLFxuICAgICAgXCJSZXNlcnZlZCBwdWJsaXNoZXIgcGF0aCBjb3VsZCBub3QgYmUgaW5zcGVjdGVkLlwiLCBlcnJvcilcbiAgfVxuXG4gIGlmICghc3RhdHVzLmlzRGlyZWN0b3J5KCkgfHwgc3RhdHVzLmlzU3ltYm9saWNMaW5rKCkpIHtcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoc3RhdHVzLmlzU3ltYm9saWNMaW5rKCkgPyBcIlBVQkxJQ0FUSU9OX1NZTUxJTktfVFJBVkVSU0FMXCIgOiBcIlBVQkxJQ0FUSU9OX1VOT1dORURfQ09ORkxJQ1RcIixcbiAgICAgIHByb2plY3RJZCwgXCJSZXNlcnZlZCBwdWJsaXNoZXIgcGF0aCBpcyBub3QgYW4gb3duZWQgcmVhbCBkaXJlY3RvcnkuXCIpXG4gIH1cbn1cblxuLyoqXG4gKiBFbnN1cmVzIGFuIG93bmVkIHBhdGggaGFzIG5vIHByZS1leGlzdGluZyBlbnRyeS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIEV4YWN0IHBhdGguXG4gKiBAcGFyYW0ge3N0cmluZ30gY29kZSAtIERpYWdub3N0aWMgY29kZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9qZWN0SWQgLSBQcm9qZWN0IGlkZW50aXR5LlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBTdGFibGUgZmFpbHVyZSBkZXRhaWwuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQ29tcGxldGlvbi5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gYXNzZXJ0QWJzZW50KGZpbGVuYW1lLCBjb2RlLCBwcm9qZWN0SWQsIG1lc3NhZ2UpIHtcbiAgdHJ5IHtcbiAgICBhd2FpdCBsc3RhdChmaWxlbmFtZSlcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoY29kZSwgcHJvamVjdElkLCBtZXNzYWdlKVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGlmIChpc0Vycm9yQ29kZShlcnJvciwgXCJFTk9FTlRcIikpIHJldHVyblxuICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFNlbWFudGlmb2xkRGlhZ25vc3RpYykgdGhyb3cgZXJyb3JcbiAgICBwdWJsaWNhdGlvbkZhaWx1cmUoY29kZSwgcHJvamVjdElkLCBtZXNzYWdlLCBlcnJvcilcbiAgfVxufVxuXG4vKipcbiAqIFJlc29sdmVzIGEgdmFsaWRhdGVkIHJlbGF0aXZlIHBhdGggdW5kZXIgYW4gb3duZWQgcm9vdCBhbmQgcmVqZWN0cyBlc2NhcGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gcm9vdCAtIE93bmVkIHJvb3QuXG4gKiBAcGFyYW0ge3N0cmluZ30gcmVsYXRpdmUgLSBWYWxpZGF0ZWQgcmVsYXRpdmUgUE9TSVggcGF0aC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9qZWN0SWQgLSBQcm9qZWN0IGlkZW50aXR5LlxuICogQHJldHVybnMge3N0cmluZ30gRXhhY3Qgb3duZWQgcGF0aC5cbiAqL1xuZnVuY3Rpb24gb3duZWRQYXRoKHJvb3QsIHJlbGF0aXZlLCBwcm9qZWN0SWQpIHtcbiAgY29uc3QgcmVzb2x2ZWQgPSBwYXRoLnJlc29sdmUocm9vdCwgLi4ucmVsYXRpdmUuc3BsaXQoXCIvXCIpKVxuICBjb25zdCBjaGlsZCA9IHBhdGgucmVsYXRpdmUocm9vdCwgcmVzb2x2ZWQpXG5cbiAgaWYgKGNoaWxkLmxlbmd0aCA9PSAwIHx8IGNoaWxkID09IFwiLi5cIiB8fCBjaGlsZC5zdGFydHNXaXRoKGAuLiR7cGF0aC5zZXB9YCkgfHwgcGF0aC5pc0Fic29sdXRlKGNoaWxkKSkge1xuICAgIHB1YmxpY2F0aW9uRmFpbHVyZShcIlBVQkxJQ0FUSU9OX1BBVEhfRVNDQVBFXCIsIHByb2plY3RJZCxcbiAgICAgIFwiUmVzb2x2ZWQgcHVibGljYXRpb24gcGF0aCBlc2NhcGVkIGl0cyBvd25lZCByb290LlwiKVxuICB9XG5cbiAgcmV0dXJuIHJlc29sdmVkXG59XG5cbi8qKlxuICogQ2hlY2tzIGEgY2Fub25pY2FsIG5vbi1yb290IGFic29sdXRlIHBhdGggd2l0aG91dCBmaWxlc3lzdGVtIGFjY2Vzcy5cbiAqIEBwYXJhbSB7dW5rbm93bn0gdmFsdWUgLSBQYXRoIGNhbmRpZGF0ZS5cbiAqIEByZXR1cm5zIHt2YWx1ZSBpcyBzdHJpbmd9IFdoZXRoZXIgdGhlIHBhdGggaXMgY2Fub25pY2FsLlxuICovXG5mdW5jdGlvbiBpc0Nhbm9uaWNhbEFic29sdXRlUGF0aCh2YWx1ZSkge1xuICByZXR1cm4gaXNDYW5vbmljYWxBYnNvbHV0ZVBhdGhGb3JQYXRoKHZhbHVlLCBwYXRoKVxufVxuXG4vKipcbiAqIENoZWNrcyBvbmUgYWJzb2x1dGUgcGF0aCB1c2luZyB0aGUgc3VwcGxpZWQgaG9zdCBwYXRoIHNlbWFudGljcy5cbiAqIFRoaXMgaGVscGVyIGlzIGludGVudGlvbmFsbHkgbm90IHBhcnQgb2YgdGhlIHBhY2thZ2Ugcm9vdCBBUEkuXG4gKiBAcGFyYW0ge3Vua25vd259IHZhbHVlIC0gUGF0aCBjYW5kaWRhdGUuXG4gKiBAcGFyYW0ge3R5cGVvZiBwYXRoLnBvc2l4IHwgdHlwZW9mIHBhdGgud2luMzJ9IGhvc3RQYXRoIC0gSG9zdC1uYXRpdmUgcGF0aCBpbXBsZW1lbnRhdGlvbi5cbiAqIEByZXR1cm5zIHt2YWx1ZSBpcyBzdHJpbmd9IFdoZXRoZXIgdGhlIHBhdGggaXMgY2Fub25pY2FsIGZvciB0aGF0IGhvc3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0Nhbm9uaWNhbEFic29sdXRlUGF0aEZvclBhdGgodmFsdWUsIGhvc3RQYXRoKSB7XG4gIGNvbnN0IHNlcGFyYXRvckFsaWFzID0gaG9zdFBhdGguc2VwID09IFwiL1wiID8gXCJcXFxcXCIgOiBcIi9cIlxuXG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gXCJzdHJpbmdcIiAmJiB2YWx1ZS5sZW5ndGggPiAwICYmICF2YWx1ZS5pbmNsdWRlcyhcIlxcMFwiKSAmJiAhdmFsdWUuaW5jbHVkZXMoc2VwYXJhdG9yQWxpYXMpICYmXG4gICAgaG9zdFBhdGguaXNBYnNvbHV0ZSh2YWx1ZSkgJiYgdmFsdWUgIT0gaG9zdFBhdGgucGFyc2UodmFsdWUpLnJvb3QgJiYgaG9zdFBhdGgubm9ybWFsaXplKHZhbHVlKSA9PSB2YWx1ZSAmJlxuICAgIGhvc3RQYXRoLnJlc29sdmUodmFsdWUpID09IHZhbHVlXG59XG5cbi8qKlxuICogQ2hlY2tzIGNvbnNlcnZhdGl2ZSBwb3J0YWJsZSBvdmVybGFwIGJldHdlZW4gYWJzb2x1dGUgcGF0aHMuXG4gKiBAcGFyYW0ge3N0cmluZ30gbGVmdCAtIEZpcnN0IHBhdGguXG4gKiBAcGFyYW0ge3N0cmluZ30gcmlnaHQgLSBTZWNvbmQgcGF0aC5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIGVpdGhlciBjb250YWlucyB0aGUgb3RoZXIuXG4gKi9cbmZ1bmN0aW9uIHBhdGhzT3ZlcmxhcChsZWZ0LCByaWdodCkge1xuICBjb25zdCBsZWZ0S2V5ID0gbGVmdC50b0xvd2VyQ2FzZSgpXG4gIGNvbnN0IHJpZ2h0S2V5ID0gcmlnaHQudG9Mb3dlckNhc2UoKVxuXG4gIHJldHVybiBsZWZ0S2V5ID09IHJpZ2h0S2V5IHx8IGxlZnRLZXkuc3RhcnRzV2l0aChgJHtyaWdodEtleX0ke3BhdGguc2VwfWApIHx8IHJpZ2h0S2V5LnN0YXJ0c1dpdGgoYCR7bGVmdEtleX0ke3BhdGguc2VwfWApXG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBwYXRoIGlzIGVxdWFsIHRvIG9yIG5lc3RlZCBiZW5lYXRoIG9uZSBjYW5vbmljYWwgcm9vdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSByb290IC0gQ2Fub25pY2FsIHJvb3QuXG4gKiBAcGFyYW0ge3N0cmluZ30gY2FuZGlkYXRlIC0gQ2Fub25pY2FsIGNhbmRpZGF0ZS5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIHRoZSBjYW5kaWRhdGUgaXMgd2l0aGluIHRoZSByb290LlxuICovXG5mdW5jdGlvbiBpc1BhdGhXaXRoaW4ocm9vdCwgY2FuZGlkYXRlKSB7XG4gIGNvbnN0IHJlbGF0aXZlID0gcGF0aC5yZWxhdGl2ZShyb290LCBjYW5kaWRhdGUpXG5cbiAgcmV0dXJuIHJlbGF0aXZlLmxlbmd0aCA9PSAwIHx8IChyZWxhdGl2ZSAhPSBcIi4uXCIgJiYgIXJlbGF0aXZlLnN0YXJ0c1dpdGgoYC4uJHtwYXRoLnNlcH1gKSAmJiAhcGF0aC5pc0Fic29sdXRlKHJlbGF0aXZlKSlcbn1cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciBhIHBhdGggaXMgc3RyaWN0bHkgbmVzdGVkIGJlbmVhdGggb25lIGNhbm9uaWNhbCByb290LlxuICogQHBhcmFtIHtzdHJpbmd9IHJvb3QgLSBDYW5vbmljYWwgcm9vdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjYW5kaWRhdGUgLSBDYW5vbmljYWwgY2FuZGlkYXRlLlxuICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgdGhlIGNhbmRpZGF0ZSBpcyBhIHN0cmljdCBkZXNjZW5kYW50LlxuICovXG5mdW5jdGlvbiBpc1N0cmljdFBhdGhEZXNjZW5kYW50KHJvb3QsIGNhbmRpZGF0ZSkge1xuICByZXR1cm4gaXNQYXRoV2l0aGluKHJvb3QsIGNhbmRpZGF0ZSkgJiYgcGF0aC5yZWxhdGl2ZShyb290LCBjYW5kaWRhdGUpLmxlbmd0aCA+IDBcbn1cblxuLyoqXG4gKiBTZXJpYWxpemVzIHN0YWJsZSBnZW5lcmF0ZWQgSlNPTiB3aXRoIG9uZSB0cmFpbGluZyBMRi5cbiAqIEBwYXJhbSB7dW5rbm93bn0gdmFsdWUgLSBKU09OIHZhbHVlLlxuICogQHJldHVybnMge0J1ZmZlcn0gVVRGLTggYnl0ZXMuXG4gKi9cbmZ1bmN0aW9uIHNlcmlhbGl6ZUpzb24odmFsdWUpIHtcbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKGAke0pTT04uc3RyaW5naWZ5KHZhbHVlLCBudWxsLCAyKX1cXG5gLCBcInV0ZjhcIilcbn1cblxuLyoqXG4gKiBIYXNoZXMgZXhhY3QgYnl0ZXMgd2l0aCBTSEEtMjU2LlxuICogQHBhcmFtIHtVaW50OEFycmF5fSBieXRlcyAtIEV4YWN0IGJ5dGVzLlxuICogQHJldHVybnMge3N0cmluZ30gTG93ZXJjYXNlIGhleGFkZWNpbWFsIGhhc2guXG4gKi9cbmZ1bmN0aW9uIHNoYTI1NihieXRlcykge1xuICByZXR1cm4gY3JlYXRlSGFzaChcInNoYTI1NlwiKS51cGRhdGUoYnl0ZXMpLmRpZ2VzdChcImhleFwiKVxufVxuXG4vKipcbiAqIERlZXBseSBmcmVlemVzIGEgcGFyc2VkIEpTT04gdmFsdWUuXG4gKiBAdGVtcGxhdGUgVFxuICogQHBhcmFtIHtUfSB2YWx1ZSAtIEpTT04gdmFsdWUuXG4gKiBAcmV0dXJucyB7VH0gRnJvemVuIHZhbHVlLlxuICovXG5mdW5jdGlvbiBkZWVwRnJlZXplKHZhbHVlKSB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT0gXCJvYmplY3RcIiAmJiB2YWx1ZSAhPSBudWxsKSB7XG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiBPYmplY3QudmFsdWVzKHZhbHVlKSkgZGVlcEZyZWV6ZShjaGlsZClcbiAgICBPYmplY3QuZnJlZXplKHZhbHVlKVxuICB9XG5cbiAgcmV0dXJuIHZhbHVlXG59XG5cbi8qKlxuICogQ29tcGFyZXMgZGV0YWNoZWQgSlNPTiB2YWx1ZXMgd2l0aG91dCBkZXBlbmRpbmcgb24gb2JqZWN0LWtleSBvcmRlci5cbiAqIEBwYXJhbSB7dW5rbm93bn0gbGVmdCAtIEZpcnN0IEpTT04gdmFsdWUuXG4gKiBAcGFyYW0ge3Vua25vd259IHJpZ2h0IC0gU2Vjb25kIEpTT04gdmFsdWUuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgdmFsdWVzIGFyZSBzdHJ1Y3R1cmFsbHkgZXF1YWwuXG4gKi9cbmZ1bmN0aW9uIHNhbWVKc29uVmFsdWUobGVmdCwgcmlnaHQpIHtcbiAgaWYgKGxlZnQgPT09IHJpZ2h0KSByZXR1cm4gdHJ1ZVxuICBpZiAoQXJyYXkuaXNBcnJheShsZWZ0KSB8fCBBcnJheS5pc0FycmF5KHJpZ2h0KSkge1xuICAgIHJldHVybiBBcnJheS5pc0FycmF5KGxlZnQpICYmIEFycmF5LmlzQXJyYXkocmlnaHQpICYmIGxlZnQubGVuZ3RoID09IHJpZ2h0Lmxlbmd0aCAmJlxuICAgICAgbGVmdC5ldmVyeSgoZW50cnksIGluZGV4KSA9PiBzYW1lSnNvblZhbHVlKGVudHJ5LCByaWdodFtpbmRleF0pKVxuICB9XG4gIGlmICghaXNQbGFpbk9iamVjdChsZWZ0KSB8fCAhaXNQbGFpbk9iamVjdChyaWdodCkpIHJldHVybiBmYWxzZVxuICBjb25zdCBsZWZ0S2V5cyA9IE9iamVjdC5rZXlzKGxlZnQpXG4gIGNvbnN0IHJpZ2h0S2V5cyA9IE9iamVjdC5rZXlzKHJpZ2h0KVxuXG4gIHJldHVybiBsZWZ0S2V5cy5sZW5ndGggPT0gcmlnaHRLZXlzLmxlbmd0aCAmJlxuICAgIGxlZnRLZXlzLmV2ZXJ5KGtleSA9PiBPYmplY3QuaGFzT3duKHJpZ2h0LCBrZXkpICYmIHNhbWVKc29uVmFsdWUobGVmdFtrZXldLCByaWdodFtrZXldKSlcbn1cblxuLyoqXG4gKiBDaGVja3MgYW4gYWN0aXZlLXBvaW50ZXIgdmFsdWUuXG4gKiBAcGFyYW0ge3Vua25vd259IHZhbHVlIC0gUGFyc2VkIHZhbHVlLlxuICogQHJldHVybnMge3ZhbHVlIGlzIEFjdGl2ZVBvaW50ZXJ9IFdoZXRoZXIgdGhlIHZhbHVlIGlzIHN0cmljdCBhbmQgdmVyc2lvbmVkLlxuICovXG5mdW5jdGlvbiBpc0FjdGl2ZVBvaW50ZXIodmFsdWUpIHtcbiAgcmV0dXJuIGlzUGxhaW5PYmplY3QodmFsdWUpICYmIGhhc0V4YWN0S2V5cyh2YWx1ZSwgW1wiZ2VuZXJhdGlvbklkXCIsIFwibWFuaWZlc3RIYXNoXCIsIFwicHJvamVjdElkXCIsIFwic2NoZW1hXCIsIFwidmVyc2lvblwiXSkgJiZcbiAgICB2YWx1ZS5zY2hlbWEgPT0gXCJTZW1hbnRpZm9sZEFjdGl2ZUdlbmVyYXRpb25cIiAmJiB2YWx1ZS52ZXJzaW9uID09IDEgJiZcbiAgICB0eXBlb2YgdmFsdWUucHJvamVjdElkID09IFwic3RyaW5nXCIgJiYgaWRlbnRpdHlQYXR0ZXJuLnRlc3QodmFsdWUucHJvamVjdElkKSAmJlxuICAgIHR5cGVvZiB2YWx1ZS5nZW5lcmF0aW9uSWQgPT0gXCJzdHJpbmdcIiAmJiBnZW5lcmF0aW9uUGF0dGVybi50ZXN0KHZhbHVlLmdlbmVyYXRpb25JZCkgJiZcbiAgICB0eXBlb2YgdmFsdWUubWFuaWZlc3RIYXNoID09IFwic3RyaW5nXCIgJiYgL15bYS1mMC05XXs2NH0kL3UudGVzdCh2YWx1ZS5tYW5pZmVzdEhhc2gpXG59XG5cbi8qKlxuICogQ2hlY2tzIGEgcmVjb3Zlcnktam91cm5hbCB2YWx1ZS5cbiAqIEBwYXJhbSB7dW5rbm93bn0gdmFsdWUgLSBQYXJzZWQgdmFsdWUuXG4gKiBAcmV0dXJucyB7dmFsdWUgaXMgUHVibGljYXRpb25Kb3VybmFsfSBXaGV0aGVyIHRoZSB2YWx1ZSBpcyBzdHJpY3QgYW5kIHZlcnNpb25lZC5cbiAqL1xuZnVuY3Rpb24gaXNQdWJsaWNhdGlvbkpvdXJuYWwodmFsdWUpIHtcbiAgaWYgKCFpc1BsYWluT2JqZWN0KHZhbHVlKSB8fCB2YWx1ZS5zY2hlbWEgIT0gXCJTZW1hbnRpZm9sZFB1YmxpY2F0aW9uSm91cm5hbFwiIHx8XG4gICAgdHlwZW9mIHZhbHVlLnByb2plY3RJZCAhPSBcInN0cmluZ1wiIHx8ICFpZGVudGl0eVBhdHRlcm4udGVzdCh2YWx1ZS5wcm9qZWN0SWQpIHx8XG4gICAgdHlwZW9mIHZhbHVlLmdlbmVyYXRpb25JZCAhPSBcInN0cmluZ1wiIHx8ICFnZW5lcmF0aW9uUGF0dGVybi50ZXN0KHZhbHVlLmdlbmVyYXRpb25JZCkgfHxcbiAgICB2YWx1ZS50ZW1wUG9pbnRlciAhPSBgLmFjdGl2ZS1nZW5lcmF0aW9uLiR7dmFsdWUuZ2VuZXJhdGlvbklkfS50bXBgKSByZXR1cm4gZmFsc2VcblxuICByZXR1cm4gdmFsdWUudmVyc2lvbiA9PSAxICYmIGhhc0V4YWN0S2V5cyh2YWx1ZSwgW1wiZ2VuZXJhdGlvbklkXCIsIFwicHJvamVjdElkXCIsIFwic2NoZW1hXCIsIFwidGVtcFBvaW50ZXJcIiwgXCJ2ZXJzaW9uXCJdKSB8fFxuICAgIHZhbHVlLnZlcnNpb24gPT0gMiAmJiB2YWx1ZS5vcGVyYXRpb24gPT0gXCJyZWFjdGl2YXRlXCIgJiZcbiAgICAgIGhhc0V4YWN0S2V5cyh2YWx1ZSwgW1wiZ2VuZXJhdGlvbklkXCIsIFwib3BlcmF0aW9uXCIsIFwicHJvamVjdElkXCIsIFwic2NoZW1hXCIsIFwidGVtcFBvaW50ZXJcIiwgXCJ2ZXJzaW9uXCJdKVxufVxuXG4vKipcbiAqIENoZWNrcyBhbiBvcmRpbmFyeSBvYmplY3Qgd2l0aCBleGFjdGx5IHRoZSBleHBlY3RlZCBlbnVtZXJhYmxlIHN0cmluZyBrZXlzLlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gdmFsdWUgLSBPYmplY3QgY2FuZGlkYXRlLlxuICogQHBhcmFtIHtyZWFkb25seSBzdHJpbmdbXX0ga2V5cyAtIFNvcnRlZCBleHBlY3RlZCBrZXlzLlxuICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIga2V5cyBtYXRjaCBleGFjdGx5LlxuICovXG5mdW5jdGlvbiBoYXNFeGFjdEtleXModmFsdWUsIGtleXMpIHtcbiAgY29uc3QgYWN0dWFsID0gT2JqZWN0LmtleXModmFsdWUpLnNvcnQoY29tcGFyZVN0cmluZ3MpXG5cbiAgcmV0dXJuIGFjdHVhbC5sZW5ndGggPT0ga2V5cy5sZW5ndGggJiYgYWN0dWFsLmV2ZXJ5KChrZXksIGluZGV4KSA9PiBrZXkgPT0ga2V5c1tpbmRleF0pXG59XG5cbi8qKlxuICogQ2hlY2tzIGZvciBhbiBvcmRpbmFyeSBzdHJpbmcta2V5ZWQgb2JqZWN0LlxuICogQHBhcmFtIHt1bmtub3dufSB2YWx1ZSAtIENhbmRpZGF0ZSB2YWx1ZS5cbiAqIEByZXR1cm5zIHt2YWx1ZSBpcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gV2hldGhlciB0aGUgdmFsdWUgaXMgcGxhaW4uXG4gKi9cbmZ1bmN0aW9uIGlzUGxhaW5PYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSBcIm9iamVjdFwiICYmIHZhbHVlICE9IG51bGwgJiYgIUFycmF5LmlzQXJyYXkodmFsdWUpICYmIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSkgPT0gT2JqZWN0LnByb3RvdHlwZVxufVxuXG4vKipcbiAqIENoZWNrcyBmb3IgYSBkZW5zZSBvcmRpbmFyeSBhcnJheS5cbiAqIEBwYXJhbSB7dW5rbm93bn0gdmFsdWUgLSBDYW5kaWRhdGUgdmFsdWUuXG4gKiBAcmV0dXJucyB7dmFsdWUgaXMgdW5rbm93bltdfSBXaGV0aGVyIHRoZSB2YWx1ZSBpcyBkZW5zZS5cbiAqL1xuZnVuY3Rpb24gaXNEZW5zZUFycmF5KHZhbHVlKSB7XG4gIGlmICghQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHJldHVybiBmYWxzZVxuICBjb25zdCBpbmRleGVkS2V5cyA9IE9iamVjdC5rZXlzKHZhbHVlKS5maWx0ZXIoa2V5ID0+IC9eKD86MHxbMS05XVswLTldKikkL3UudGVzdChrZXkpKVxuXG4gIHJldHVybiBpbmRleGVkS2V5cy5sZW5ndGggPT0gdmFsdWUubGVuZ3RoXG59XG5cbi8qKlxuICogQ29tcGFyZXMgc3RyaW5ncyBieSBVbmljb2RlIGNvZGUgdW5pdC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBsZWZ0IC0gRmlyc3Qgc3RyaW5nLlxuICogQHBhcmFtIHtzdHJpbmd9IHJpZ2h0IC0gU2Vjb25kIHN0cmluZy5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IE9yZGVyaW5nLlxuICovXG5mdW5jdGlvbiBjb21wYXJlU3RyaW5ncyhsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8IHJpZ2h0ID8gLTEgOiBsZWZ0ID4gcmlnaHQgPyAxIDogMFxufVxuXG4vKipcbiAqIENoZWNrcyBhIG5hcnJvd2VkIGZpbGVzeXN0ZW0gZXJyb3IgY29kZS5cbiAqIEBwYXJhbSB7dW5rbm93bn0gZXJyb3IgLSBPcGFxdWUgZXJyb3IuXG4gKiBAcGFyYW0ge3N0cmluZ30gY29kZSAtIEV4cGVjdGVkIGNvZGUuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgY29kZSBtYXRjaGVzLlxuICovXG5mdW5jdGlvbiBpc0Vycm9yQ29kZShlcnJvciwgY29kZSkge1xuICByZXR1cm4gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciAmJiBcImNvZGVcIiBpbiBlcnJvciAmJiBlcnJvci5jb2RlID09IGNvZGVcbn1cblxuLyoqXG4gKiBUaHJvd3Mgb25lIHN0YWJsZSBwdWJsaWNhdGlvbiBkaWFnbm9zdGljIHdpdGhvdXQgZW1iZWRkaW5nIGhvc3QgcGF0aHMgb3IgcmF3IGZpbGVzeXN0ZW0gbWVzc2FnZXMuXG4gKiBAcGFyYW0ge3N0cmluZ30gY29kZSAtIFN0YWJsZSBkaWFnbm9zdGljIGNvZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvamVjdElkIC0gUHJvamVjdCBpZGVudGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gU3RhYmxlIGRldGFpbC5cbiAqIEBwYXJhbSB7dW5rbm93bn0gW2Vycm9yXSAtIFByZXNlcnZlZCBjYXVzZS5cbiAqIEByZXR1cm5zIHtuZXZlcn0gQWx3YXlzIHRocm93cy5cbiAqL1xuZnVuY3Rpb24gcHVibGljYXRpb25GYWlsdXJlKGNvZGUsIHByb2plY3RJZCwgbWVzc2FnZSwgZXJyb3IpIHtcbiAgdGhyb3cgbmV3IFNlbWFudGlmb2xkRGlhZ25vc3RpYyh7XG4gICAgY2F1c2U6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IHVuZGVmaW5lZCxcbiAgICBjb2RlLFxuICAgIGxhbmd1YWdlOiBwcm9qZWN0SWQsXG4gICAgbWVzc2FnZVxuICB9KVxufVxuXG4vKipcbiAqIEB0eXBlZGVmIFZhbGlkYXRlZFB1YmxpY2F0aW9uVGFyZ2V0XG4gKiBAcHJvcGVydHkge3N0cmluZ30gaWQgLSBUYXJnZXQgaWRlbnRpdHkuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuR2VuZXJhdGVkQXJ0aWZhY3RTZXR9IGFydGlmYWN0U2V0IC0gRGV0YWNoZWQgYXJ0aWZhY3Qgc2V0LlxuICogQHByb3BlcnR5IHtzdHJpbmd9IHNvdXJjZVByb2plY3Rpb24gLSBTb3VyY2UgcHJvamVjdGlvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBidWlsZFByb2plY3Rpb24gLSBCdWlsZCBwcm9qZWN0aW9uLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlB1YmxpY2F0aW9uVGFyZ2V0Um9sZX0gcm9sZSAtIExhbmd1YWdlLW5ldXRyYWwgdGFyZ2V0IHJvbGUuXG4gKiBAcHJvcGVydHkge3JlYWRvbmx5IGltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuUHVibGljYXRpb25WYWxpZGF0b3JbXX0gdmFsaWRhdG9ycyAtIE9yZGVyZWQgdmFsaWRhdG9ycy5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIFZhbGlkYXRlZFB1YmxpY2F0aW9uUmVxdWVzdFxuICogQHByb3BlcnR5IHtzdHJpbmd9IGdlbmVyYXRpb25JZCAtIFNuYXBzaG90dGVkIGdlbmVyYXRpb24gaWRlbnRpdHkuXG4gKiBAcHJvcGVydHkge3JlYWRvbmx5IFZhbGlkYXRlZFB1YmxpY2F0aW9uVGFyZ2V0W119IHRhcmdldHMgLSBTbmFwc2hvdHRlZCBvcmRlcmVkIHRhcmdldHMuXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiBBY3RpdmVQb2ludGVyXG4gKiBAcHJvcGVydHkge1wiU2VtYW50aWZvbGRBY3RpdmVHZW5lcmF0aW9uXCJ9IHNjaGVtYSAtIFNjaGVtYSBkaXNjcmltaW5hdG9yLlxuICogQHByb3BlcnR5IHsxfSB2ZXJzaW9uIC0gU2NoZW1hIHZlcnNpb24uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gcHJvamVjdElkIC0gUHJvamVjdCBpZGVudGl0eS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBnZW5lcmF0aW9uSWQgLSBHZW5lcmF0aW9uIGlkZW50aXR5LlxuICogQHByb3BlcnR5IHtzdHJpbmd9IG1hbmlmZXN0SGFzaCAtIFNIQS0yNTYgZ2VuZXJhdGlvbi1tYW5pZmVzdCBoYXNoLlxuICovXG5cbi8qKlxuICogQHR5cGVkZWYgQ2FuZGlkYXRlUHVibGljYXRpb25Kb3VybmFsXG4gKiBAcHJvcGVydHkge1wiU2VtYW50aWZvbGRQdWJsaWNhdGlvbkpvdXJuYWxcIn0gc2NoZW1hIC0gU2NoZW1hIGRpc2NyaW1pbmF0b3IuXG4gKiBAcHJvcGVydHkgezF9IHZlcnNpb24gLSBTY2hlbWEgdmVyc2lvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBwcm9qZWN0SWQgLSBQcm9qZWN0IGlkZW50aXR5LlxuICogQHByb3BlcnR5IHtzdHJpbmd9IGdlbmVyYXRpb25JZCAtIENhbmRpZGF0ZSBnZW5lcmF0aW9uIGlkZW50aXR5LlxuICogQHByb3BlcnR5IHtzdHJpbmd9IHRlbXBQb2ludGVyIC0gT3duZWQgc2libGluZyB0ZW1wb3JhcnktcG9pbnRlciBmaWxlbmFtZS5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIFJlYWN0aXZhdGlvblB1YmxpY2F0aW9uSm91cm5hbFxuICogQHByb3BlcnR5IHtcIlNlbWFudGlmb2xkUHVibGljYXRpb25Kb3VybmFsXCJ9IHNjaGVtYSAtIFNjaGVtYSBkaXNjcmltaW5hdG9yLlxuICogQHByb3BlcnR5IHsyfSB2ZXJzaW9uIC0gU2NoZW1hIHZlcnNpb24uXG4gKiBAcHJvcGVydHkge1wicmVhY3RpdmF0ZVwifSBvcGVyYXRpb24gLSBSZXRhaW5lZC1nZW5lcmF0aW9uIGFjdGl2YXRpb24gd2l0aG91dCBjYW5kaWRhdGUgb3duZXJzaGlwLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IHByb2plY3RJZCAtIFByb2plY3QgaWRlbnRpdHkuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gZ2VuZXJhdGlvbklkIC0gUmV0YWluZWQgZ2VuZXJhdGlvbiBpZGVudGl0eS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB0ZW1wUG9pbnRlciAtIE93bmVkIHNpYmxpbmcgdGVtcG9yYXJ5LXBvaW50ZXIgZmlsZW5hbWUuXG4gKi9cblxuLyoqIEB0eXBlZGVmIHtDYW5kaWRhdGVQdWJsaWNhdGlvbkpvdXJuYWwgfCBSZWFjdGl2YXRpb25QdWJsaWNhdGlvbkpvdXJuYWx9IFB1YmxpY2F0aW9uSm91cm5hbCAqL1xuIl19