sliftutils 1.7.88 → 1.7.89

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 (125) hide show
  1. package/.claude/settings.local.json +3 -1
  2. package/dist/treeSummary.ts.cache +2 -2
  3. package/index.d.ts +674 -295
  4. package/misc/dist/environment.ts.cache +2 -2
  5. package/misc/dist/getSecret.ts.cache +2 -2
  6. package/misc/dist/strings.ts.cache +2 -2
  7. package/misc/dist/zip.ts.cache +2 -2
  8. package/misc/https/dist/certs.ts.cache +2 -2
  9. package/misc/https/dist/cloudflareHelpers.ts.cache +2 -2
  10. package/misc/https/dist/dns.ts.cache +2 -2
  11. package/misc/https/dist/hostServer.ts.cache +49 -21
  12. package/misc/https/dist/hostsFile.ts.cache +82 -0
  13. package/misc/https/dist/httpsCerts.ts.cache +2 -2
  14. package/misc/https/dist/persistentLocalStorage.ts.cache +2 -2
  15. package/misc/https/hostServer.d.ts +6 -2
  16. package/misc/https/hostServer.ts +52 -19
  17. package/misc/https/hostsFile.d.ts +7 -0
  18. package/misc/https/hostsFile.ts +66 -0
  19. package/package.json +1 -1
  20. package/render-utils/dist/observer.tsx.cache +2 -2
  21. package/storage/ArchivesDisk.d.ts +3 -6
  22. package/storage/ArchivesDisk.ts +26 -2
  23. package/storage/BulkDatabase2/BulkDatabaseReader.ts +1 -1
  24. package/storage/BulkDatabase2/dist/BulkDatabaseBase.ts.cache +2 -2
  25. package/storage/BulkDatabase2/dist/BulkDatabaseFormat.ts.cache +2 -2
  26. package/storage/BulkDatabase2/dist/BulkDatabaseMerge.ts.cache +2 -2
  27. package/storage/BulkDatabase2/dist/BulkDatabaseReader.ts.cache +3 -3
  28. package/storage/BulkDatabase2/dist/LoadedIndex.ts.cache +2 -2
  29. package/storage/BulkDatabase2/dist/WriteOverlay.ts.cache +2 -2
  30. package/storage/BulkDatabase2/dist/blockCache.ts.cache +2 -2
  31. package/storage/BulkDatabase2/dist/mergeLock.ts.cache +2 -2
  32. package/storage/BulkDatabase2/dist/mergeMarkers.ts.cache +2 -2
  33. package/storage/BulkDatabase2/dist/streamLog.ts.cache +2 -2
  34. package/storage/BulkDatabase2/dist/syncClient.ts.cache +2 -2
  35. package/storage/IArchives.d.ts +37 -24
  36. package/storage/IArchives.ts +47 -62
  37. package/storage/LogMap.d.ts +56 -0
  38. package/storage/LogMap.ts +220 -0
  39. package/storage/archiveHelpers.d.ts +36 -0
  40. package/storage/archiveHelpers.ts +103 -0
  41. package/storage/backblaze.d.ts +7 -12
  42. package/storage/backblaze.ts +53 -48
  43. package/storage/dist/ArchivesDisk.ts.cache +28 -2
  44. package/storage/dist/FileFolderAPI.tsx.cache +2 -2
  45. package/storage/dist/IArchives.ts.cache +16 -52
  46. package/storage/dist/IndexedDBFileFolderAPI.ts.cache +2 -2
  47. package/storage/dist/JSONStorage.ts.cache +2 -2
  48. package/storage/dist/LogMap.ts.cache +212 -0
  49. package/storage/dist/PendingManager.tsx.cache +2 -2
  50. package/storage/dist/TransactionStorage.ts.cache +2 -2
  51. package/storage/dist/backblaze.ts.cache +58 -44
  52. package/storage/dist/fileSystemPointer.ts.cache +2 -2
  53. package/storage/dist/remoteFileStorage.ts.cache +2 -2
  54. package/storage/remoteStorage/ArchivesDelayed.d.ts +66 -0
  55. package/storage/remoteStorage/ArchivesDelayed.ts +237 -0
  56. package/storage/remoteStorage/ArchivesRemote.d.ts +5 -6
  57. package/storage/remoteStorage/ArchivesRemote.ts +26 -5
  58. package/storage/remoteStorage/ArchivesUrl.d.ts +2 -5
  59. package/storage/remoteStorage/ArchivesUrl.ts +2 -2
  60. package/storage/remoteStorage/accessPage.tsx +12 -0
  61. package/storage/remoteStorage/blobStore.d.ts +162 -189
  62. package/storage/remoteStorage/blobStore.ts +495 -952
  63. package/storage/remoteStorage/bucketDisk.d.ts +24 -3
  64. package/storage/remoteStorage/bucketDisk.ts +56 -22
  65. package/storage/remoteStorage/certTrustModal.d.ts +1 -0
  66. package/storage/remoteStorage/certTrustModal.tsx +48 -0
  67. package/storage/remoteStorage/cliArgs.d.ts +2 -0
  68. package/storage/remoteStorage/cliArgs.ts +5 -0
  69. package/storage/remoteStorage/createArchives.d.ts +8 -7
  70. package/storage/remoteStorage/createArchives.ts +65 -26
  71. package/storage/remoteStorage/deployTakeover.ts +1 -1
  72. package/storage/remoteStorage/dist/ArchivesDelayed.ts.cache +220 -0
  73. package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +25 -5
  74. package/storage/remoteStorage/dist/ArchivesUrl.ts.cache +3 -3
  75. package/storage/remoteStorage/dist/accessPage.tsx.cache +13 -3
  76. package/storage/remoteStorage/dist/accessStats.ts.cache +2 -2
  77. package/storage/remoteStorage/dist/blobStore.ts.cache +483 -965
  78. package/storage/remoteStorage/dist/bucketDisk.ts.cache +60 -29
  79. package/storage/remoteStorage/dist/certTrustModal.tsx.cache +55 -0
  80. package/storage/remoteStorage/dist/cliArgs.ts.cache +9 -4
  81. package/storage/remoteStorage/dist/createArchives.ts.cache +63 -26
  82. package/storage/remoteStorage/dist/deployTakeover.ts.cache +5 -5
  83. package/storage/remoteStorage/dist/intermediateManagement.ts.cache +286 -0
  84. package/storage/remoteStorage/dist/intermediateSources.ts.cache +2 -2
  85. package/storage/remoteStorage/dist/remoteConfig.ts.cache +122 -56
  86. package/storage/remoteStorage/dist/serverConfig.ts.cache +4 -4
  87. package/storage/remoteStorage/dist/sourceWrapper.ts.cache +7 -11
  88. package/storage/remoteStorage/dist/sourcesList.ts.cache +3 -6
  89. package/storage/remoteStorage/dist/storageClientController.ts.cache +2 -2
  90. package/storage/remoteStorage/dist/storageController.ts.cache +27 -12
  91. package/storage/remoteStorage/dist/storageServer.ts.cache +27 -7
  92. package/storage/remoteStorage/dist/storageServerCli.ts.cache +7 -3
  93. package/storage/remoteStorage/dist/storageServerState.ts.cache +133 -696
  94. package/storage/remoteStorage/dist/storeConfig.ts.cache +52 -0
  95. package/storage/remoteStorage/dist/storePlan.ts.cache +110 -81
  96. package/storage/remoteStorage/dist/storeSources.ts.cache +51 -0
  97. package/storage/remoteStorage/dist/storeSync.ts.cache +650 -0
  98. package/storage/remoteStorage/dist/validation.ts.cache +14 -4
  99. package/storage/remoteStorage/intermediateManagement.d.ts +12 -0
  100. package/storage/remoteStorage/intermediateManagement.ts +264 -0
  101. package/storage/remoteStorage/remoteConfig.d.ts +32 -0
  102. package/storage/remoteStorage/remoteConfig.ts +115 -50
  103. package/storage/remoteStorage/serverConfig.d.ts +1 -1
  104. package/storage/remoteStorage/serverConfig.ts +1 -1
  105. package/storage/remoteStorage/sourceWrapper.ts +4 -8
  106. package/storage/remoteStorage/sourcesList.d.ts +0 -2
  107. package/storage/remoteStorage/sourcesList.ts +0 -3
  108. package/storage/remoteStorage/spec.md +18 -4
  109. package/storage/remoteStorage/storageController.d.ts +10 -0
  110. package/storage/remoteStorage/storageController.ts +29 -16
  111. package/storage/remoteStorage/storageServer.d.ts +2 -0
  112. package/storage/remoteStorage/storageServer.ts +28 -4
  113. package/storage/remoteStorage/storageServerCli.ts +5 -1
  114. package/storage/remoteStorage/storageServerState.d.ts +34 -21
  115. package/storage/remoteStorage/storageServerState.ts +147 -662
  116. package/storage/remoteStorage/storeConfig.d.ts +30 -0
  117. package/storage/remoteStorage/storeConfig.ts +62 -0
  118. package/storage/remoteStorage/storePlan.d.ts +29 -17
  119. package/storage/remoteStorage/storePlan.ts +112 -85
  120. package/storage/remoteStorage/storeSources.d.ts +11 -0
  121. package/storage/remoteStorage/storeSources.ts +47 -0
  122. package/storage/remoteStorage/storeSync.d.ts +53 -0
  123. package/storage/remoteStorage/storeSync.ts +632 -0
  124. package/storage/remoteStorage/validation.d.ts +2 -0
  125. package/storage/remoteStorage/validation.ts +10 -0
@@ -1,36 +1,14 @@
1
- "use strict"; var console = (function shimConsole() { let baseConsole = globalThis.console; if (typeof window !== "undefined") return baseConsole; let name = __filename.replaceAll("\\", "/").split("/").pop(); let dirName = __dirname.replaceAll("\\", "/").split("/").pop(); let context = { __FILE__: __filename, __DIR__: __dirname, __NAME__: name, __DIRNAME__: dirName }; let newConsole = { ...baseConsole }; for (let shim of ["log", "info", "warn", "error"]) { newConsole[shim] = (...args) => { args.push(context); baseConsole[shim](...args); }; } newConsole.__context = context; return newConsole; })(); "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
4
- };
1
+ "use strict";
5
2
  Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
6
- //exports.getLocalArchives = exports.clearAccountWriteStats = exports.listAccountBuckets = exports.activateBucket = exports.getActiveBucket = exports.startIntermediateMaintenance = exports.rebuildAllLoadedBuckets = exports.getActiveBucketKeys = exports.queueRoutingConfigWrite = exports.getLoadedBucket = exports.resolveSourceArchives = exports.bucketIndexTotals = exports.bucketSyncStatus = exports.getBucketConfig = exports.readBucketInternal = exports.findBucketStore = exports.requireBucket = void 0;
7
- const path_1 = __importDefault(require("path"));
8
- const fs_1 = __importDefault(require("fs"));
9
- const caching_1 = require("socket-function/src/caching");
10
- const misc_1 = require("socket-function/src/misc");
11
- const batching_1 = require("socket-function/src/batching");
12
- const ArchivesDisk_1 = require("../ArchivesDisk");
3
+ //exports.clearAccountWriteStats = exports.listAccountBuckets = exports.activateBucket = exports.getActiveBucket = exports.getActiveBucketKeys = exports.writeRoutingConfig = exports.reloadBucket = exports.getLoadedBucket = exports.getStore = exports.resolveSourceArchives = exports.getBucketStates = exports.bucketIndexTotals = exports.bucketSyncStatus = exports.getBucketConfig = exports.readBucketInternal = exports.findBucketStore = exports.requireBucket = void 0;
13
4
  const blobStore_1 = require("./blobStore");
14
- const IArchives_1 = require("../IArchives");
15
5
  const remoteConfig_1 = require("./remoteConfig");
16
- const intermediateSources_1 = require("./intermediateSources");
17
- const deployTakeover_1 = require("./deployTakeover");
18
- const createArchives_1 = require("./createArchives");
6
+ const storeSources_1 = require("./storeSources");
19
7
  const storageController_1 = require("./storageController");
20
8
  const serverConfig_1 = require("./serverConfig");
21
9
  const bucketDisk_1 = require("./bucketDisk");
10
+ const intermediateManagement_1 = require("./intermediateManagement");
22
11
  const storePlan_1 = require("./storePlan");
23
- /** JSON with sorted object keys and undefined-valued keys dropped, so two configs that mean the same thing compare equal regardless of key order or which side serialized them. */
24
- function stableStringify(value) {
25
- if (!value || typeof value !== "object")
26
- return JSON.stringify(value);
27
- if (Array.isArray(value)) {
28
- return `[${value.map(x => stableStringify(x)).join(",")}]`;
29
- }
30
- let entries = Object.entries(value).filter(x => x[1] !== undefined);
31
- (0, misc_1.sort)(entries, x => x[0]);
32
- return `{${entries.map(([key, child]) => `${JSON.stringify(key)}:${stableStringify(child)}`).join(",")}}`;
33
- }
34
12
  /** The loaded bucket, loading it (which instantiates its stores and starts their synchronization) if needed. A bucket that does not exist on this server throws - callers never see undefined buckets. */
35
13
  async function requireBucket(account, bucketName) {
36
14
  let bucket = await getLoadedBucket(account, bucketName);
@@ -40,23 +18,24 @@ async function requireBucket(account, bucketName) {
40
18
  return bucket;
41
19
  }
42
20
  exports.requireBucket = requireBucket;
43
- /** The stable identity of a source config for matching: everything EXCEPT the valid window, and with an intermediate resolved back to the source it was split out of. The window drifts (a switchover splits one window in two around an intermediate, then rejoins it), so a caller and this server routinely disagree on it - matching on it would wrongly reject the request. An intermediate is a transient alt-port view of another source, so it must resolve to THAT source (config.intermediate holds its url + the intermediate flag is dropped), or a request naming the intermediate would fail to match once the intermediate has rejoined and its entry is gone. The route stays in the identity (it selects the store/folder). */
44
- function sourceMatchKey(config) {
45
- let url = config.intermediate || config.url;
46
- return stableStringify({ ...config, url, intermediate: undefined, validWindow: undefined });
47
- }
48
- /** The store serving a request: the config entry the CLIENT selected, matched against the bucket's own entries by identity EXCLUDING the valid window (see sourceMatchKey). The selection never validates - the store's own window/route checks throw if the caller is stale - so honoring a window mismatch here is exactly right. Throws when nothing matches, listing what is available. */
21
+ /** The store serving a request: the one the client's selected entry NAMES. Nothing else is compared - not the window, not the route, not the flags - because the name is what says which storage this is, and everything else is policy the store itself applies to the request. A client a config version behind on some flag therefore still reaches the right store, which is the whole point of naming it. */
49
22
  async function findBucketStore(account, bucketName, sourceConfig) {
50
23
  let bucket = await requireBucket(account, bucketName);
51
24
  if (!sourceConfig) {
52
- throw new Error(`No remote source configuration was provided for bucket ${account}/${bucketName}: every request must say which configured source it selected. Available: ${JSON.stringify(bucket.selfEntries)}`);
25
+ throw new Error(`No remote source configuration was provided for bucket ${account}/${bucketName}: every request must say which configured source it selected. This server has: ${JSON.stringify(bucket.stores.map(x => x.name))}`);
53
26
  }
54
- let wanted = sourceMatchKey(sourceConfig);
55
- for (let s of bucket.stores) {
56
- if (s.entries.some(e => sourceMatchKey(e) === wanted))
57
- return s;
27
+ let store = bucket.stores.find(x => x.name === sourceConfig.name);
28
+ if (store)
29
+ return store;
30
+ // The loaded bucket is a snapshot of the disk from when it loaded; a store created since (a new name in a rewritten routing config) is on the disk but not in the snapshot, so a miss re-reads the disk once before it is believed
31
+ let previousNames = bucket.stores.map(x => x.name);
32
+ let reloaded = await reloadBucket(account, bucketName);
33
+ store = reloaded === null || reloaded === void 0 ? void 0 : reloaded.stores.find(x => x.name === sourceConfig.name);
34
+ if (store) {
35
+ console.log(`Reloaded bucket ${account}/${bucketName} to find store ${JSON.stringify(sourceConfig.name)}: its stores changed from ${JSON.stringify(previousNames)} to ${JSON.stringify(reloaded === null || reloaded === void 0 ? void 0 : reloaded.stores.map(x => x.name))}`);
36
+ return store;
58
37
  }
59
- throw new Error(`No source on this server matches the requested remote configuration for bucket ${account}/${bucketName}. Requested: ${JSON.stringify(sourceConfig)}. Available: ${JSON.stringify(bucket.selfEntries)}`);
38
+ throw new Error(`This server has no store named ${JSON.stringify(sourceConfig.name)} for bucket ${account}/${bucketName} (it has: ${JSON.stringify((reloaded || bucket).stores.map(x => x.name))}). Requested: ${JSON.stringify(sourceConfig)}`);
60
39
  }
61
40
  exports.findBucketStore = findBucketStore;
62
41
  /** Internal (store-to-store) reads skip store selection entirely: the caller is another store whose index says this MACHINE holds the bytes - the persisted holder identity is just a URL, which cannot name a store. Whichever store's folder has the newest copy answers. */
@@ -73,15 +52,12 @@ async function readBucketInternal(account, bucketName, config) {
73
52
  }
74
53
  exports.readBucketInternal = readBucketInternal;
75
54
  function getBucketConfig(bucket) {
76
- var _a, _b;
77
55
  let index = { fileCount: 0, byteCount: 0 };
78
56
  let indexSources = [];
79
57
  let syncing = [];
80
58
  let readerDiskLimit;
81
59
  for (let s of bucket.stores) {
82
- let progress = (_b = (_a = s.store).getSyncProgress) === null || _b === void 0 ? void 0 : _b.call(_a);
83
- if (!progress)
84
- continue;
60
+ let progress = s.store.getSyncProgress();
85
61
  index.fileCount += progress.index.fileCount;
86
62
  index.byteCount += progress.index.byteCount;
87
63
  indexSources.push(...progress.sources);
@@ -89,8 +65,8 @@ function getBucketConfig(bucket) {
89
65
  readerDiskLimit = readerDiskLimit || progress.readerDiskLimit;
90
66
  }
91
67
  return {
92
- // Native change-feed support = the stores keep an index (rawDisk buckets emulate getChangesAfter2 with a full listing) - clients use this to pick their scan cadence
93
- supportsChangesAfter: bucket.stores.some(s => s.store instanceof blobStore_1.BlobStore),
68
+ // Every store is index-backed, so the change feed is always native
69
+ supportsChangesAfter: true,
94
70
  remoteConfig: bucket.routing,
95
71
  index,
96
72
  indexSources,
@@ -100,17 +76,7 @@ function getBucketConfig(bucket) {
100
76
  }
101
77
  exports.getBucketConfig = getBucketConfig;
102
78
  async function bucketSyncStatus(bucket) {
103
- let supported = bucket.stores.filter(s => s.store.getSyncStatus);
104
- if (!supported.length) {
105
- throw new Error(`Bucket ${bucket.account}/${bucket.bucketName} does not support getSyncStatus (rawDisk buckets have no synchronization)`);
106
- }
107
- let statuses = await Promise.all(supported.map(async (s) => {
108
- let getSyncStatus = s.store.getSyncStatus;
109
- if (!getSyncStatus) {
110
- throw new Error(`getSyncStatus disappeared from a store for ${bucket.account}/${bucket.bucketName}`);
111
- }
112
- return await getSyncStatus.call(s.store);
113
- }));
79
+ let statuses = await Promise.all(bucket.stores.map(s => s.store.getSyncStatus()));
114
80
  return {
115
81
  allScansComplete: statuses.every(x => x.allScansComplete),
116
82
  indexSize: statuses.reduce((sum, x) => sum + x.indexSize, 0),
@@ -119,16 +85,7 @@ async function bucketSyncStatus(bucket) {
119
85
  }
120
86
  exports.bucketSyncStatus = bucketSyncStatus;
121
87
  async function bucketIndexTotals(bucket) {
122
- let supported = bucket.stores.filter(s => s.store.computeIndexTotals);
123
- if (!supported.length)
124
- return undefined;
125
- let totals = await Promise.all(supported.map(async (s) => {
126
- let computeIndexTotals = s.store.computeIndexTotals;
127
- if (!computeIndexTotals) {
128
- throw new Error(`computeIndexTotals disappeared from a store for ${bucket.account}/${bucket.bucketName}`);
129
- }
130
- return await computeIndexTotals.call(s.store);
131
- }));
88
+ let totals = await Promise.all(bucket.stores.map(s => s.store.computeIndexTotals()));
132
89
  return {
133
90
  fileCount: totals.reduce((sum, x) => sum + x.fileCount, 0),
134
91
  byteCount: totals.reduce((sum, x) => sum + x.byteCount, 0),
@@ -137,407 +94,132 @@ async function bucketIndexTotals(bucket) {
137
94
  }
138
95
  exports.bucketIndexTotals = bucketIndexTotals;
139
96
  const buckets = new Map();
140
- const MAX_REBUILD_TIMER_DELAY = 2 ** 31 - 1;
141
- const REBUILD_BOUNDARY_BUFFER = 1000;
142
- function scheduleWindowBoundaryRebuild(loaded) {
143
- var _a, _b;
144
- let now = Date.now();
145
- let boundaries = loaded.selfEntries.flatMap(x => x.validWindow).filter(t => t > now);
146
- if (!boundaries.length)
147
- return;
148
- let nextBoundary = Math.min(...boundaries);
149
- let key = `${loaded.account}/${loaded.bucketName}`;
150
- let timer = setTimeout(() => {
151
- void (async () => {
152
- let current = await buckets.get(key);
153
- if (current !== loaded)
154
- return;
155
- if (Date.now() < nextBoundary) {
156
- scheduleWindowBoundaryRebuild(loaded);
157
- return;
158
- }
159
- await scheduleRoutingReload(loaded.account, loaded.bucketName, { force: true, reason: "a valid window boundary passed" });
160
- })();
161
- }, Math.min(nextBoundary - now + REBUILD_BOUNDARY_BUFFER, MAX_REBUILD_TIMER_DELAY));
162
- (_b = (_a = timer).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
163
- }
164
- const BOUNDARY_SCAN_OFFSETS = [-30 * 1000, 2 * 1000, 30 * 1000];
165
- const BOUNDARY_SCAN_LOOKBACK = blobStore_1.DEFAULT_FAST_WRITE_DELAY + blobStore_1.WINDOW_END_FLUSH_MARGIN;
166
- const STARTUP_BOUNDARY_SCAN_DELAY = 30 * 1000;
167
- const scheduledBoundaryScans = new Set();
168
- const boundaryScansRunning = new Set();
169
- function scheduleBoundaryScans(loaded) {
170
- var _a, _b;
171
- let key = `${loaded.account}/${loaded.bucketName}`;
172
- let now = Date.now();
173
- let starts = new Set();
174
- for (let self of loaded.selfEntries) {
175
- let start = self.validWindow[0];
176
- if (start > now && start < Number.MAX_SAFE_INTEGER) {
177
- starts.add(start);
178
- }
179
- }
180
- for (let self of loaded.selfEntries) {
181
- let [start, end] = self.validWindow;
182
- if (!(start <= now && now < end) || start <= 0)
183
- continue;
184
- if (now - start > BOUNDARY_SCAN_LOOKBACK)
185
- continue;
186
- let scheduleKey = `${key}|${start}|startup`;
187
- if (scheduledBoundaryScans.has(scheduleKey))
188
- continue;
189
- scheduledBoundaryScans.add(scheduleKey);
190
- let timer = setTimeout(() => {
191
- void runBoundaryScan(key, start, STARTUP_BOUNDARY_SCAN_DELAY, "startup+30s").catch((e) => { var _a; return console.error(`Boundary scan for bucket ${key} failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`); });
192
- }, STARTUP_BOUNDARY_SCAN_DELAY);
193
- (_b = (_a = timer).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
194
- }
195
- for (let start of starts) {
196
- for (let offset of BOUNDARY_SCAN_OFFSETS) {
197
- let at = start + offset;
198
- if (at <= now)
199
- continue;
200
- let scheduleKey = `${key}|${start}|${offset}`;
201
- if (scheduledBoundaryScans.has(scheduleKey))
202
- continue;
203
- scheduledBoundaryScans.add(scheduleKey);
204
- let arm = () => {
205
- var _a, _b;
206
- let timer = setTimeout(() => {
207
- if (Date.now() < at) {
208
- arm();
209
- return;
210
- }
211
- void runBoundaryScan(key, start, offset).catch((e) => { var _a; return console.error(`Boundary scan for bucket ${key} failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`); });
212
- }, Math.min(at - Date.now(), MAX_REBUILD_TIMER_DELAY));
213
- (_b = (_a = timer).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
214
- };
215
- arm();
216
- }
217
- }
218
- }
219
- async function runBoundaryScan(bucketKey, windowStart, offset, offsetLabel) {
220
- var _a;
221
- let label = `bucket ${bucketKey}, window starting ${new Date(windowStart).toISOString()}, offset ${offsetLabel || `${offset / 1000}s`}`;
222
- if (boundaryScansRunning.has(bucketKey)) {
223
- console.log(`Skipping boundary scan (${label}): the previous boundary scan is still running`);
224
- return;
225
- }
226
- boundaryScansRunning.add(bucketKey);
227
- try {
228
- let loaded = await buckets.get(bucketKey);
229
- if (!loaded)
230
- return;
231
- let effective = loaded.routing;
232
- let selfIndexes = (0, storePlan_1.findSelfIndexes)(effective, loaded.account, loaded.bucketName);
233
- let selfIndexSet = new Set(selfIndexes);
234
- let selves = selfIndexes.map(i => effective.sources[i]).filter(x => x.validWindow[0] === windowStart);
235
- if (!selves.length)
236
- return;
237
- let prevTime = windowStart - 1;
238
- // Everything is per-store: each self entry's route has its own store, and that store's disk/remote boundary pulls only concern its own route slice
239
- let needDiskScan = new Set();
240
- let remoteOwners = new Map();
241
- for (let self of selves) {
242
- let selfRoute = self.route || IArchives_1.FULL_ROUTE;
243
- let selfStore = loaded.stores.find(x => x.routeKey === JSON.stringify(selfRoute));
244
- if (!selfStore || !(selfStore.store instanceof blobStore_1.BlobStore))
245
- continue;
246
- let idx = effective.sources.indexOf(self);
247
- let shadowed = false;
248
- for (let j = 0; j < idx; j++) {
249
- let other = effective.sources[j];
250
- if (typeof other === "string")
251
- continue;
252
- let [ws, we] = other.validWindow;
253
- if (!(ws <= windowStart && windowStart < we))
254
- continue;
255
- let r = other.route || IArchives_1.FULL_ROUTE;
256
- if (r[0] <= selfRoute[0] && selfRoute[1] <= r[1]) {
257
- shadowed = true;
258
- break;
259
- }
260
- }
261
- if (shadowed)
262
- continue;
263
- let uncovered = [[selfRoute[0], selfRoute[1]]];
264
- for (let j = 0; j < effective.sources.length && uncovered.length; j++) {
265
- let other = effective.sources[j];
266
- if (typeof other === "string")
267
- continue;
268
- let [ws, we] = other.validWindow;
269
- if (!(ws <= prevTime && prevTime < we))
270
- continue;
271
- let r = other.route || IArchives_1.FULL_ROUTE;
272
- let remaining = [];
273
- let claimed;
274
- for (let u of uncovered) {
275
- let inter = (0, remoteConfig_1.routeIntersection)(u, r);
276
- if (!inter) {
277
- remaining.push(u);
278
- continue;
279
- }
280
- claimed = claimed && [Math.min(claimed[0], inter[0]), Math.max(claimed[1], inter[1])] || inter;
281
- if (u[0] < inter[0])
282
- remaining.push([u[0], inter[0]]);
283
- if (inter[1] < u[1])
284
- remaining.push([inter[1], u[1]]);
285
- }
286
- uncovered = remaining;
287
- if (!claimed)
288
- continue;
289
- if (selfIndexSet.has(j)) {
290
- needDiskScan.add(selfStore);
291
- }
292
- else {
293
- let owners = remoteOwners.get(selfStore);
294
- if (!owners) {
295
- owners = new Map();
296
- remoteOwners.set(selfStore, owners);
297
- }
298
- let existing = owners.get(j);
299
- owners.set(j, existing && [Math.min(existing[0], claimed[0]), Math.max(existing[1], claimed[1])] || claimed);
300
- }
301
- }
302
- }
303
- if (!needDiskScan.size && !remoteOwners.size)
304
- return;
305
- console.log(`Boundary scan (${label}): diskScans=${needDiskScan.size}, stores with remote previous-window owners: ${remoteOwners.size}`);
306
- for (let selfStore of needDiskScan) {
307
- if (selfStore.store instanceof blobStore_1.BlobStore) {
308
- await selfStore.store.rescanBase();
309
- }
310
- }
311
- let since = windowStart - BOUNDARY_SCAN_LOOKBACK;
312
- for (let [selfStore, owners] of remoteOwners) {
313
- if (!(selfStore.store instanceof blobStore_1.BlobStore))
314
- continue;
315
- for (let [sourceIndex, route] of owners) {
316
- let ownerSource = effective.sources[sourceIndex];
317
- if (typeof ownerSource === "string")
318
- continue;
319
- try {
320
- await selfStore.store.boundaryScanRemote((0, createArchives_1.createApiArchives)(ownerSource), { since, route });
321
- }
322
- catch (e) {
323
- console.error(`Boundary scan (${label}) of previous-window owner (source index ${sourceIndex}) failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
324
- }
325
- }
326
- }
327
- }
328
- finally {
329
- boundaryScansRunning.delete(bucketKey);
330
- }
97
+ // The resolved ones, for the code that walks buckets rather than asking for one (see getBucketStates)
98
+ const loadedBuckets = new Map();
99
+ /** The bucket states currently in memory - what the switchover machinery walks. Only what is loaded: loading a bucket starts its synchronization, and a bucket nothing has touched has no in-flight writes to hand over anyway. */
100
+ function getBucketStates() {
101
+ return [...loadedBuckets.values()];
331
102
  }
103
+ exports.getBucketStates = getBucketStates;
332
104
  const resolvedSourceArchives = new Map();
333
105
  /** A cached IArchives for a persisted source identity: a routing URL (hosted/backblaze) or a disk folder path - the form BlobStore's sources list stores. Configuration (valid windows, routes) decides WHEN a source should be used; for reading bytes the index says a source holds, the URL alone is enough - even for sources no longer in any config. */
334
106
  function resolveSourceArchives(url) {
335
107
  let existing = resolvedSourceArchives.get(url);
336
108
  if (existing)
337
109
  return existing;
338
- let archives;
110
+ let sourceConfig;
339
111
  if (url.startsWith("https://")) {
340
112
  // The config is fabricated from the bare URL and can never exact-match a server's entries - which is fine, because holder reads are internal reads, and internal reads never select a store (see readBucketInternal)
341
- archives = (0, createArchives_1.createApiArchives)((0, remoteConfig_1.normalizeSource)(url));
342
- }
343
- else {
344
- archives = new ArchivesDisk_1.ArchivesDisk(url);
113
+ sourceConfig = (0, remoteConfig_1.normalizeSource)(url);
345
114
  }
115
+ let archives = (0, storeSources_1.createStoreSource)({ sourceConfig, folder: url });
346
116
  resolvedSourceArchives.set(url, archives);
347
117
  return archives;
348
118
  }
349
119
  exports.resolveSourceArchives = resolveSourceArchives;
350
- function sourceIdentity(sourceConfig) {
120
+ /** What an index entry records as the holder of its bytes (see ArchivesSource.url), so it must name the endpoint FOREVER. An intermediate is a switchover's temporary alternate port onto another source, and that port is gone for good once its window passes - so it is recorded as the source it was split out of, which holds the same bucket and outlives it. */
121
+ function sourcePersistentUrl(sourceConfig, folder) {
351
122
  if (!sourceConfig)
352
- return "disk";
353
- return JSON.stringify({ ...sourceConfig, validWindow: undefined, route: undefined });
354
- }
355
- function buildStore(account, bucketName, planStore) {
356
- let folder = (0, bucketDisk_1.getBucketFolder)(account, bucketName, planStore.route);
357
- if (planStore.rawDisk) {
358
- return new blobStore_1.RawDiskStore(new ArchivesDisk_1.ArchivesDisk(folder));
359
- }
360
- let sources = planStore.sourceSpecs.map(spec => {
361
- var _a, _b;
362
- return ({
363
- source: spec.sourceConfig && (0, createArchives_1.createApiArchives)(spec.sourceConfig) || new ArchivesDisk_1.ArchivesDisk(folder),
364
- url: ((_a = spec.sourceConfig) === null || _a === void 0 ? void 0 : _a.url) || folder,
365
- validWindows: spec.validWindows,
366
- route: spec.route,
367
- noFullSync: spec.noFullSync,
368
- intermediate: (_b = spec.sourceConfig) === null || _b === void 0 ? void 0 : _b.intermediate,
369
- sourceConfig: spec.sourceConfig,
370
- identity: sourceIdentity(spec.sourceConfig),
371
- });
372
- });
373
- return new blobStore_1.BlobStore(folder, sources, {
374
- readerDiskLimit: planStore.readerDiskLimit,
123
+ return folder;
124
+ return sourceConfig.intermediate || sourceConfig.url;
125
+ }
126
+ /** The fast-write policy this store writes under: its own configuration decides it (fast/writeDelay are OUR settings, not the peer's), and each source then holds writes for as long as sourceWriteDelay says. */
127
+ /**
128
+ * Every store this process runs, by folder - which IS the store's identity: account, name, bucket.
129
+ * A store is made once, configures itself from the routing config it holds, and stays; nothing here
130
+ * decides what it is, only that it exists.
131
+ */
132
+ const stores = new Map();
133
+ function getStore(account, bucketName, name) {
134
+ let folder = (0, bucketDisk_1.getBucketFolder)(name, account, bucketName);
135
+ let existing = stores.get(folder);
136
+ if (existing)
137
+ return existing;
138
+ let store = new blobStore_1.BlobStore(folder, name, {
139
+ // Which entries in ITS routing config are this server's copy of it
140
+ isSelf: source => (0, storePlan_1.isSelfSource)(source, account, bucketName),
141
+ createSource: config => (0, storeSources_1.createStoreSource)({ sourceConfig: config.sourceConfig, folder, writeDelay: config.writeDelay }),
142
+ applySource: (source, sourceConfig, writeDelay) => (0, storeSources_1.applySourceConfig)(source, sourceConfig, writeDelay),
375
143
  onWriteCounted: (kind, bytes) => countBucketWrite(`${account}/${bucketName}`, kind, bytes),
376
144
  resolveSourceUrl: resolveSourceArchives,
377
- entries: planStore.entries,
378
145
  });
379
- }
380
- function buildBucket(account, bucketName, routing, plan) {
381
- if (!plan) {
382
- plan = (0, storePlan_1.computeStorePlan)(account, bucketName, routing);
383
- }
384
- let { selfEntries, self } = plan;
385
- if (!self) {
386
- console.log(`This server is not in the routing config for bucket ${account}/${bucketName}: no longer synchronizing, valid window treated as [0, 0] (fast writes flush immediately), disk data kept and served`);
387
- }
388
- let stores = plan.stores.map(planStore => ({
389
- routeKey: planStore.routeKey,
390
- route: planStore.route,
391
- entries: planStore.entries,
392
- folder: (0, bucketDisk_1.getBucketFolder)(account, bucketName, planStore.route),
393
- store: buildStore(account, bucketName, planStore),
146
+ stores.set(folder, store);
147
+ // Lazy init would leave a store nothing has touched sitting inert - no index loaded, no config applied, nothing synchronizing - while its folder is full of files
148
+ void store.init().catch((e) => { var _a; return console.error(`Initializing store ${JSON.stringify(name)} of bucket ${account}/${bucketName} failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`); });
149
+ return store;
150
+ }
151
+ exports.getStore = getStore;
152
+ /** The bucket as this server has it: the stores whose folders exist, plus whatever the newest of their configs says about us. Names come from the DISK, not from the config - a store we hold keeps being served whether or not the current config still mentions it. */
153
+ function buildBucket(account, bucketName, names, routing) {
154
+ let plan = routing && (0, storePlan_1.planSelfStores)(account, bucketName, routing) || undefined;
155
+ let entriesByName = new Map();
156
+ for (let selfStore of (plan === null || plan === void 0 ? void 0 : plan.stores) || []) {
157
+ entriesByName.set(selfStore.name, selfStore.entries);
158
+ }
159
+ // Each store reads its own copy of the config and decides what it is - see BlobStore.applyRoutingConfig. Nothing here configures anything.
160
+ let stores = names.map(name => ({
161
+ name,
162
+ entries: entriesByName.get(name) || [],
163
+ folder: (0, bucketDisk_1.getBucketFolder)(name, account, bucketName),
164
+ store: getStore(account, bucketName, name),
394
165
  }));
395
- let loaded = { account, bucketName, routing, routingJSON: JSON.stringify(routing), selfEntries, self, stores, structureKey: plan.structureKey };
396
- scheduleWindowBoundaryRebuild(loaded);
397
- scheduleBoundaryScans(loaded);
398
- // A loaded bucket must actually be running: each store's init loads its index and starts its source synchronization, and it is lazy, so without this a bucket nothing has read from or written to sits inert - reporting no data and no syncing while its disk is full of files.
399
- for (let s of stores) {
400
- if (s.store instanceof blobStore_1.BlobStore) {
401
- let store = s.store;
402
- void store.init().catch((e) => { var _a; return console.error(`Initializing the store for bucket ${account}/${bucketName} (route ${s.routeKey}) failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`); });
403
- }
404
- }
166
+ let loaded = { account, bucketName, routing, selfEntries: (plan === null || plan === void 0 ? void 0 : plan.selfEntries) || [], self: plan === null || plan === void 0 ? void 0 : plan.self, stores };
167
+ loadedBuckets.set(`${account}/${bucketName}`, loaded);
168
+ (0, intermediateManagement_1.scheduleBoundaryWork)(loaded);
405
169
  return loaded;
406
170
  }
171
+ // A bucket exists here when it has at least one store folder - the disk IS the record. Its config is the newest copy among those stores; with none at all it has no config yet, which is a perfectly good state for a store nobody has configured.
407
172
  async function loadBucket(account, bucketName) {
408
- let routing = await (0, bucketDisk_1.readRoutingFromDisk)(account, bucketName);
409
- if (!routing)
173
+ let folders = await (0, bucketDisk_1.listBucketStoreFolders)(account, bucketName);
174
+ if (!folders.length)
410
175
  return undefined;
411
- return buildBucket(account, bucketName, routing);
176
+ let routing = await (0, bucketDisk_1.readRoutingFromDisk)(account, bucketName);
177
+ return buildBucket(account, bucketName, folders.map(x => x.name), routing);
412
178
  }
413
179
  function getLoadedBucket(account, bucketName) {
414
180
  let key = `${account}/${bucketName}`;
415
- let loaded = buckets.get(key);
416
- if (!loaded) {
417
- loaded = loadBucket(account, bucketName);
418
- buckets.set(key, loaded);
419
- void loaded.then(bucket => {
420
- if (!bucket && buckets.get(key) === loaded) {
421
- buckets.delete(key);
422
- }
423
- }, () => {
424
- if (buckets.get(key) === loaded) {
425
- buckets.delete(key);
426
- }
427
- });
428
- }
429
- return loaded;
181
+ return buckets.get(key) || reloadBucket(account, bucketName);
430
182
  }
431
183
  exports.getLoadedBucket = getLoadedBucket;
432
- const routingReloads = new Map();
433
- function scheduleRoutingReload(account, bucketName, config) {
184
+ /** Re-reads the bucket off the disk, replacing the cached snapshot: what a routing-config write calls, because that write can CREATE a store (a new name gets a new folder) and the snapshot would keep answering with the stores it saw at load time. Existing stores are reused (getStore caches by folder), so this only picks up folder changes - it never restarts a store. */
185
+ async function reloadBucket(account, bucketName) {
434
186
  let key = `${account}/${bucketName}`;
435
- let next = (routingReloads.get(key) || Promise.resolve())
436
- .then(() => checkRoutingChanged(account, bucketName, config))
437
- .catch(e => console.error(`Reloading routing config for bucket ${key} failed:`, e));
438
- routingReloads.set(key, next);
439
- return next;
440
- }
441
- async function checkRoutingChanged(account, bucketName, config) {
442
- let key = `${account}/${bucketName}`;
443
- let loaded = await buckets.get(key);
444
- if (!loaded)
445
- return;
446
- let routing = await (0, bucketDisk_1.readRoutingFromDisk)(account, bucketName);
447
- if (!routing)
448
- return;
449
- if (!(config === null || config === void 0 ? void 0 : config.force) && JSON.stringify(routing) === loaded.routingJSON)
450
- return;
451
- let reason = (config === null || config === void 0 ? void 0 : config.force) && (config.reason || "forced") || "routing config changed";
452
- let plan = (0, storePlan_1.computeStorePlan)(account, bucketName, routing);
453
- if (plan.structureKey === loaded.structureKey) {
454
- console.log(`Applying the routing config to the running stores for bucket ${key} (${reason})`);
455
- for (let planStore of plan.stores) {
456
- let live = loaded.stores.find(x => x.routeKey === planStore.routeKey);
457
- // structureKey equality means the store set (routes, rawDisk, limits) is unchanged, so every plan store has its live twin
458
- if (!live || !(live.store instanceof blobStore_1.BlobStore))
459
- continue;
460
- let storeFolder = live.folder;
461
- live.store.updateSources(planStore.sourceSpecs.map(spec => {
462
- const sourceConfig = spec.sourceConfig;
463
- if (!sourceConfig) {
464
- return { identity: sourceIdentity(undefined), url: storeFolder, validWindows: spec.validWindows, create: () => new ArchivesDisk_1.ArchivesDisk(storeFolder) };
465
- }
466
- return {
467
- identity: sourceIdentity(sourceConfig),
468
- url: sourceConfig.url,
469
- validWindows: spec.validWindows,
470
- route: spec.route,
471
- noFullSync: spec.noFullSync,
472
- intermediate: sourceConfig.intermediate,
473
- sourceConfig,
474
- create: () => (0, createArchives_1.createApiArchives)(sourceConfig),
475
- };
476
- }), planStore.entries);
477
- live.entries = planStore.entries;
187
+ let loaded = loadBucket(account, bucketName);
188
+ buckets.set(key, loaded);
189
+ void loaded.then(bucket => {
190
+ if (!bucket && buckets.get(key) === loaded) {
191
+ buckets.delete(key);
478
192
  }
479
- loaded.routing = routing;
480
- loaded.routingJSON = JSON.stringify(routing);
481
- loaded.selfEntries = plan.selfEntries;
482
- loaded.self = plan.self;
483
- scheduleWindowBoundaryRebuild(loaded);
484
- scheduleBoundaryScans(loaded);
485
- (0, storageController_1.broadcastRoutingChanged)();
486
- return;
487
- }
488
- console.log(`Rebuilding the stores for bucket ${key} (${reason}): structure changed from ${loaded.structureKey} to ${plan.structureKey}`);
489
- for (let s of loaded.stores) {
490
- if (s.store instanceof blobStore_1.BlobStore) {
491
- await s.store.dispose();
193
+ }, () => {
194
+ if (buckets.get(key) === loaded) {
195
+ buckets.delete(key);
492
196
  }
493
- }
494
- buckets.set(key, Promise.resolve(buildBucket(account, bucketName, routing, plan)));
495
- (0, storageController_1.broadcastRoutingChanged)();
496
- }
497
- const routingWrites = new Map();
498
- /** The routing-config write path - the ONE write that cannot go through a store (it is what CREATES the bucket and its stores). Serialized per bucket: concurrent config writes would race the version check. */
499
- async function queueRoutingConfigWrite(account, bucketName, data, config) {
197
+ });
198
+ return await loaded;
199
+ }
200
+ exports.reloadBucket = reloadBucket;
201
+ /**
202
+ * Writing the routing config is a write like any other: it goes into a store, and the store applies
203
+ * it to itself and lets its peers pull it. The only thing that happens here is picking WHICH store,
204
+ * because the writer names a source and a source names a store.
205
+ *
206
+ * In-flight switchover windows are re-injected first (see intermediateManagement): an operator's
207
+ * config knows nothing about a switchover that is happening right now, and writing it as-is would
208
+ * cancel it mid-flight.
209
+ */
210
+ async function writeRoutingConfig(account, bucketName, name, data, config) {
211
+ var _a;
500
212
  (0, serverConfig_1.assertWritesAllowed)();
501
- let key = `${account}/${bucketName}`;
502
- let run = (routingWrites.get(key) || Promise.resolve()).then(() => writeRoutingConfig(account, bucketName, data, config));
503
- routingWrites.set(key, run.then(() => { }, () => { }));
504
- return await run;
505
- }
506
- exports.queueRoutingConfigWrite = queueRoutingConfigWrite;
507
- async function writeRoutingConfig(account, bucketName, data, config) {
508
- let key = `${account}/${bucketName}`;
213
+ let store = getStore(account, bucketName, name);
509
214
  let incoming = (0, remoteConfig_1.parseRoutingData)(data);
510
- let loaded = await getLoadedBucket(account, bucketName);
511
- if (!loaded) {
512
- await resolveSourceArchives((0, bucketDisk_1.getBucketFolder)(account, bucketName)).set(remoteConfig_1.ROUTING_FILE, data, { lastModified: config === null || config === void 0 ? void 0 : config.lastModified });
513
- buckets.set(key, Promise.resolve(buildBucket(account, bucketName, incoming)));
514
- (0, storageController_1.broadcastRoutingChanged)();
515
- console.log(`Created bucket ${key}`);
516
- return;
517
- }
518
- if (JSON.stringify(incoming) !== loaded.routingJSON && (0, remoteConfig_1.getConfigVersion)(incoming) <= (0, remoteConfig_1.getConfigVersion)(loaded.routing)) {
519
- let message = `Cannot update routing config for bucket ${key}: the new config differs from the current one but its version (${(0, remoteConfig_1.getConfigVersion)(incoming)}) is not greater than the current version (${(0, remoteConfig_1.getConfigVersion)(loaded.routing)}). Increment the version to update it. Current: ${loaded.routingJSON}. Attempted: ${JSON.stringify(incoming)}`;
520
- console.error(message);
521
- throw new Error(message);
522
- }
523
- let stored = incoming;
524
- let reinjected = 0;
525
- for (let intermediate of (0, intermediateSources_1.getIntermediateSources)((0, intermediateSources_1.expireIntermediateSources)(loaded.routing, Date.now()))) {
526
- stored = (0, intermediateSources_1.injectIntermediateSource)(stored, {
527
- splitUrl: intermediate.intermediate || intermediate.url,
528
- intermediateUrl: intermediate.url,
529
- start: intermediate.validWindow[0],
530
- end: intermediate.validWindow[1],
531
- });
532
- reinjected++;
533
- }
534
- if (JSON.stringify(stored) !== JSON.stringify(incoming)) {
535
- console.log(`Re-injected ${reinjected} in-flight switchover windows into the incoming routing config for bucket ${key} (version ${(0, remoteConfig_1.getConfigVersion)(incoming)})`);
536
- }
537
- // Written straight into the plain bucket folder: the routing file defines the per-route stores, so it never flows through them
538
- await resolveSourceArchives((0, bucketDisk_1.getBucketFolder)(account, bucketName)).set(remoteConfig_1.ROUTING_FILE, Buffer.from((0, remoteConfig_1.serializeRemoteConfig)(stored)), { lastModified: config === null || config === void 0 ? void 0 : config.lastModified });
539
- await scheduleRoutingReload(account, bucketName);
215
+ let current = (_a = (await getLoadedBucket(account, bucketName))) === null || _a === void 0 ? void 0 : _a.routing;
216
+ let stored = (0, intermediateManagement_1.reinjectIntermediates)(current, incoming);
217
+ await store.set({ path: remoteConfig_1.ROUTING_FILE, data: Buffer.from((0, remoteConfig_1.serializeRemoteConfig)(stored)), lastModified: config === null || config === void 0 ? void 0 : config.lastModified });
218
+ // The write may have CREATED the store (a new name gets a new folder), and the loaded bucket is a snapshot of the disk - so it is re-read, or every data write naming the new store is rejected until a restart
219
+ await reloadBucket(account, bucketName);
220
+ (0, storageController_1.broadcastRoutingChanged)();
540
221
  }
222
+ exports.writeRoutingConfig = writeRoutingConfig;
541
223
  /** Which buckets this process currently has loaded - what a deploy successor asks its predecessor for, so it activates exactly the buckets that are actually in use. */
542
224
  function getActiveBucketKeys() {
543
225
  return [...buckets.keys()].map(key => {
@@ -546,151 +228,11 @@ function getActiveBucketKeys() {
546
228
  });
547
229
  }
548
230
  exports.getActiveBucketKeys = getActiveBucketKeys;
549
- async function rebuildAllLoadedBuckets() {
550
- for (let key of [...buckets.keys()]) {
551
- let slash = key.indexOf("/");
552
- await scheduleRoutingReload(key.slice(0, slash), key.slice(slash + 1), { force: true, reason: "all loaded buckets were asked to rebuild" });
553
- }
554
- }
555
- exports.rebuildAllLoadedBuckets = rebuildAllLoadedBuckets;
556
- const OWN_CONFIG_WRITE_THROTTLE = 30 * 1000;
557
- const INTERMEDIATE_MAINTAIN_INTERVAL = 60 * 1000;
558
- // Per bucket, not global: a switchover has to write every bucket's windows at once, and a shared throttle would let only one bucket through per interval
559
- const lastOwnConfigWrite = new Map();
560
- async function writeOwnRoutingConfig(loaded, updated, reason) {
561
- let key = `${loaded.account}/${loaded.bucketName}`;
562
- let sinceLast = Date.now() - (lastOwnConfigWrite.get(key) || 0);
563
- if (sinceLast < OWN_CONFIG_WRITE_THROTTLE) {
564
- console.log(`Not writing our own routing config update for bucket ${key} (${reason}): the last one was ${sinceLast}ms ago, under the ${OWN_CONFIG_WRITE_THROTTLE}ms throttle. Retrying on the next maintenance pass. Wanted: ${JSON.stringify(updated)}`);
565
- return;
566
- }
567
- lastOwnConfigWrite.set(key, Date.now());
568
- let version = (0, intermediateSources_1.nextIntermediateVersion)((0, remoteConfig_1.getConfigVersion)(loaded.routing));
569
- let next = { ...updated, version };
570
- console.log(`Writing ${remoteConfig_1.ROUTING_FILE} for bucket ${key} (${reason}), version ${(0, remoteConfig_1.getConfigVersion)(loaded.routing)} -> ${version}: ${JSON.stringify(next)}`);
571
- let data = Buffer.from((0, remoteConfig_1.serializeRemoteConfig)(next));
572
- await queueRoutingConfigWrite(loaded.account, loaded.bucketName, data);
573
- await propagateRoutingConfig(loaded, next, data);
574
- }
575
- async function propagateRoutingConfig(loaded, next, data) {
576
- var _a;
577
- let targets = new Map();
578
- for (let source of [...loaded.routing.sources, ...next.sources]) {
579
- if (typeof source === "string" || source.intermediate)
580
- continue;
581
- if (source.type === "remote") {
582
- let parsed = (0, remoteConfig_1.parseHostedUrl)(source.url);
583
- if (parsed.account !== loaded.account || parsed.bucketName !== loaded.bucketName)
584
- continue;
585
- }
586
- if (targets.has(source.url))
587
- continue;
588
- targets.set(source.url, source);
589
- }
590
- for (let [url, source] of targets) {
591
- try {
592
- await (0, createArchives_1.createApiArchives)(source).set(remoteConfig_1.ROUTING_FILE, data);
593
- console.log(`Wrote ${remoteConfig_1.ROUTING_FILE} for bucket ${loaded.account}/${loaded.bucketName} to ${url}`);
594
- }
595
- catch (e) {
596
- console.error(`Propagating our routing config update to ${url} failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
597
- }
598
- }
599
- }
600
- async function maintainIntermediates() {
601
- let { domain, port } = (0, serverConfig_1.getStorageServerConfig)();
602
- let takeover = (0, deployTakeover_1.getTakeoverIntermediate)();
603
- let written = [];
604
- let alreadyCorrect = [];
605
- let notOurs = [];
606
- // ONLY buckets already in memory. A switchover must never load a bucket: loading starts its synchronization, and buckets nothing has touched (legacy ones especially) have no writes to hand off in the first place. One that does get used mid-switchover loads on that access, and the next pass gives it its window.
607
- let keys = [...buckets.keys()];
608
- for (let key of keys) {
609
- let loadedPromise = buckets.get(key);
610
- if (!loadedPromise)
611
- continue;
612
- let loaded = await loadedPromise.catch(() => undefined);
613
- if (!loaded)
614
- continue;
615
- let expired = (0, intermediateSources_1.expireIntermediateSources)(loaded.routing, Date.now());
616
- if (JSON.stringify(expired) !== JSON.stringify(loaded.routing)) {
617
- await writeOwnRoutingConfig(loaded, expired, `switchover windows expired more than ${intermediateSources_1.INTERMEDIATE_EXPIRE_GRACE / 1000}s ago`);
618
- written.push(key);
619
- continue;
620
- }
621
- if (!takeover)
622
- continue;
623
- let mainUrl = loaded.routing.sources.find(x => {
624
- if (typeof x === "string" || x.type !== "remote" || x.intermediate)
625
- return false;
626
- let parsed = (0, remoteConfig_1.parseHostedUrl)(x.url);
627
- return parsed.address === domain && parsed.port === port;
628
- });
629
- if (!mainUrl) {
630
- notOurs.push(key);
631
- continue;
632
- }
633
- let injected = (0, intermediateSources_1.injectIntermediateSource)(loaded.routing, {
634
- splitUrl: mainUrl.url,
635
- intermediateUrl: (0, remoteConfig_1.replaceHostedUrlPort)(mainUrl.url, takeover.altPort),
636
- start: takeover.start,
637
- end: takeover.end,
638
- });
639
- if (JSON.stringify(injected) === JSON.stringify(loaded.routing)) {
640
- alreadyCorrect.push(key);
641
- continue;
642
- }
643
- await writeOwnRoutingConfig(loaded, injected, `we are a deploy successor: writes route to our alternate port ${takeover.altPort} from ${new Date(takeover.start).toISOString()} until our predecessor is killed at ${new Date(takeover.end).toISOString()}`);
644
- written.push(key);
645
- }
646
- if (!takeover)
647
- return;
648
- if (!keys.length) {
649
- console.log(`No active buckets, so no config files to write the intermediate into (a bucket is only active once something uses it)`);
650
- return;
651
- }
652
- if (!written.length) {
653
- console.log(`Wrote no config files: of ${keys.length} active buckets, ${alreadyCorrect.length} already contain the intermediate and ${notOurs.length} are not hosted by us`);
654
- }
655
- }
656
- /** Our predecessor still holds the main port and has been serving all along, so it - not us - knows which buckets are in use. We activate exactly those, which is what makes their config files get the intermediate; nothing else on disk is touched. */
657
- async function activatePredecessorBuckets() {
658
- var _a, _b;
659
- let { domain, port } = (0, serverConfig_1.getStorageServerConfig)();
660
- let url = `https://${domain}:${port}`;
661
- let keys;
662
- try {
663
- keys = await (0, createArchives_1.listServerActiveBucketKeys)({ url });
664
- }
665
- catch (e) {
666
- console.error(`Could not ask our predecessor on ${url} which buckets are active, so only buckets used on this process get the intermediate: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
667
- return;
668
- }
669
- if (!keys.length) {
670
- console.log(`Our predecessor on ${url} has no active buckets, so there are no config files to write the intermediate into`);
671
- return;
672
- }
673
- console.log(`Our predecessor on ${url} has ${keys.length} active buckets, activating them here so their config files get the intermediate: ${keys.map(x => `${x.account}/${x.bucketName}`).join(", ")}`);
674
- for (let { account, bucketName } of keys) {
675
- try {
676
- await getLoadedBucket(account, bucketName);
677
- }
678
- catch (e) {
679
- console.error(`Activating bucket ${account}/${bucketName} (active on our predecessor) failed: ${(_b = e.stack) !== null && _b !== void 0 ? _b : e}`);
680
- }
681
- }
682
- }
683
- /** Started by deployTakeover once we are actually a deploy successor listening on an alternate port. Until then there are no switchover windows to write or expire, so nothing polls. */
684
- exports.startIntermediateMaintenance = (0, caching_1.lazy)(() => {
685
- void (async () => {
686
- await activatePredecessorBuckets();
687
- await maintainIntermediates();
688
- })().catch((e) => { var _a; return console.error(`Writing the intermediate into the config files failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`); });
689
- (0, batching_1.runInfinitePoll)(INTERMEDIATE_MAINTAIN_INTERVAL, maintainIntermediates);
690
- });
691
231
  function toActiveBucketInfo(loaded) {
232
+ var _a;
692
233
  return {
693
- folder: (0, bucketDisk_1.getBucketFolder)(loaded.account, loaded.bucketName),
234
+ // One of its stores' folders - a bucket no longer has a folder of its own, it has one per store
235
+ folder: ((_a = loaded.stores[0]) === null || _a === void 0 ? void 0 : _a.folder) || "",
694
236
  routing: loaded.routing,
695
237
  selfEntries: loaded.selfEntries,
696
238
  self: loaded.self,
@@ -731,13 +273,11 @@ async function activateBucket(account, bucketName) {
731
273
  return `Bucket ${key} failed to load on this server: ${String((_a = e.stack) !== null && _a !== void 0 ? _a : e).slice(0, 500)}`;
732
274
  }
733
275
  if (!loaded) {
734
- return `Bucket ${key} does not exist on this server (no routing file in ${(0, bucketDisk_1.getBucketFolder)(account, bucketName)})`;
276
+ return `Bucket ${key} does not exist on this server (it has no store folders under ${(0, bucketDisk_1.getBucketFolder)("<name>", account, bucketName)})`;
735
277
  }
736
278
  // Wait for the indexes to load, so the totals we return are the real ones rather than zeroes from stores that have not read their index yet. The source scans keep running in the background.
737
279
  for (let s of loaded.stores) {
738
- if (s.store instanceof blobStore_1.BlobStore) {
739
- await s.store.init();
740
- }
280
+ await s.store.init();
741
281
  }
742
282
  if (!wasLoaded) {
743
283
  console.log(`Activated bucket ${key} on request: it is now loaded and synchronizing`);
@@ -757,21 +297,20 @@ async function listAccountBuckets(account) {
757
297
  timings.set(name, (timings.get(name) || 0) + (Date.now() - began));
758
298
  }
759
299
  }
760
- let accountFolder = path_1.default.join((0, serverConfig_1.getStorageServerConfig)().folder, "buckets2", account);
761
- let names;
762
- try {
763
- names = await timed("readdir", () => fs_1.default.promises.readdir(accountFolder));
764
- }
765
- catch (_a) {
766
- return [];
300
+ // The disk is the record: a bucket exists here when it has at least one store folder, and several names for one bucket are still one bucket
301
+ let folders = await timed("readdir", () => (0, bucketDisk_1.listAccountStoreFolders)(account));
302
+ let byBucket = new Map();
303
+ for (let store of folders) {
304
+ if (byBucket.has(store.bucketName))
305
+ continue;
306
+ byBucket.set(store.bucketName, store.folder);
767
307
  }
768
- // Per-route folders (bucketName-route-<start>-<end>) belong to the same bucket as the plain folder - collapse them so one bucket lists once
769
- names = [...new Set(names.map(x => x.replace(/-route-[\d.]+-[\d.]+$/, "")))];
308
+ let names = [...byBucket.keys()];
770
309
  try {
771
310
  return await Promise.all(names.map(async (bucketName) => {
772
311
  var _a, _b;
773
312
  let key = `${account}/${bucketName}`;
774
- let folder = (0, bucketDisk_1.getBucketFolder)(account, bucketName);
313
+ let folder = byBucket.get(bucketName) || "";
775
314
  let base = { bucketName, active: false, folder };
776
315
  base.disk = await timed("statfs", () => (0, bucketDisk_1.getDiskInfo)(folder)).catch((e) => {
777
316
  var _a;
@@ -792,11 +331,10 @@ async function listAccountBuckets(account) {
792
331
  }
793
332
  }
794
333
  try {
795
- const data = await timed("readRoutingFile", () => (0, bucketDisk_1.readRoutingFile)(folder));
796
- if (!data) {
797
- return { ...base, error: `No routing file (${remoteConfig_1.ROUTING_FILE})` };
334
+ const parsed = await timed("readRoutingFile", () => (0, bucketDisk_1.readRoutingFromDisk)(account, bucketName));
335
+ if (!parsed) {
336
+ return { ...base, error: `No routing file (${remoteConfig_1.ROUTING_FILE}) in any of its stores` };
798
337
  }
799
- let parsed = await timed("parseRouting", async () => (0, remoteConfig_1.parseRoutingData)(data));
800
338
  return { ...base, config: { remoteConfig: parsed } };
801
339
  }
802
340
  catch (e) {
@@ -848,106 +386,5 @@ function clearAccountWriteStats(account) {
848
386
  return cleared;
849
387
  }
850
388
  exports.clearAccountWriteStats = clearAccountWriteStats;
851
- const LARGE_FILE_PART_SIZE = 8 * 1024 * 1024;
852
- // Wraps a locally hosted bucket in the IArchives interface, so code written against IArchives (the chain, sync sources, holder reads) talks to it directly instead of becoming a network client to ourselves.
853
- class BucketIArchivesWrapper {
854
- constructor(account, bucketName, sourceConfig) {
855
- this.account = account;
856
- this.bucketName = bucketName;
857
- this.sourceConfig = sourceConfig;
858
- }
859
- findStore() {
860
- return findBucketStore(this.account, this.bucketName, this.sourceConfig);
861
- }
862
- getDebugName() {
863
- return `localBucket account ${this.account} bucket ${this.bucketName} route ${JSON.stringify(this.sourceConfig.route || IArchives_1.FULL_ROUTE)}`;
864
- }
865
- async get(fileName, config) {
866
- let result = await this.get2(fileName, config);
867
- return result && result.data || undefined;
868
- }
869
- async get2(fileName, config) {
870
- if (fileName === remoteConfig_1.ROUTING_FILE) {
871
- return await (0, bucketDisk_1.getRoutingFileResult)(this.account, this.bucketName);
872
- }
873
- if (config === null || config === void 0 ? void 0 : config.internal) {
874
- return await readBucketInternal(this.account, this.bucketName, { path: fileName, range: config.range, includeTombstones: config.includeTombstones });
875
- }
876
- return await (await this.findStore()).store.get2({ path: fileName, ...config });
877
- }
878
- async set(fileName, data, config) {
879
- (0, serverConfig_1.assertWritesAllowed)();
880
- if (fileName === remoteConfig_1.ROUTING_FILE) {
881
- await queueRoutingConfigWrite(this.account, this.bucketName, data, config);
882
- return fileName;
883
- }
884
- await (await this.findStore()).store.set({ ...config, path: fileName, data });
885
- return fileName;
886
- }
887
- async del(fileName, config) {
888
- (0, serverConfig_1.assertWritesAllowed)();
889
- await (await this.findStore()).store.del({ path: fileName, ...config });
890
- }
891
- async setLargeFile(config) {
892
- (0, serverConfig_1.assertWritesAllowed)();
893
- let store = (await this.findStore()).store;
894
- let id = await store.startLargeUpload({ path: config.path, lastModified: config.lastModified });
895
- try {
896
- while (true) {
897
- let data = await config.getNextData();
898
- if (!data)
899
- break;
900
- for (let offset = 0; offset < data.length; offset += LARGE_FILE_PART_SIZE) {
901
- await store.appendLargeUpload({ id, data: data.subarray(offset, offset + LARGE_FILE_PART_SIZE) });
902
- }
903
- }
904
- await store.finishLargeUpload({ id, path: config.path, lastModified: config.lastModified });
905
- }
906
- catch (e) {
907
- await store.cancelLargeUpload({ id });
908
- throw e;
909
- }
910
- }
911
- async getInfo(fileName, config) {
912
- if (fileName === remoteConfig_1.ROUTING_FILE) {
913
- let result = await (0, bucketDisk_1.getRoutingFileResult)(this.account, this.bucketName);
914
- return result && { writeTime: result.writeTime, size: result.size } || undefined;
915
- }
916
- return await (await this.findStore()).store.getInfo({ path: fileName, ...config });
917
- }
918
- async findInfo(prefix, config) {
919
- return await (await this.findStore()).store.findInfo({ prefix, ...config });
920
- }
921
- async find(prefix, config) {
922
- return (await this.findInfo(prefix, config)).map(x => x.path);
923
- }
924
- async getURL(filePath) {
925
- let { domain, port } = (0, serverConfig_1.getStorageServerConfig)();
926
- return (0, remoteConfig_1.buildFileUrl)(`https://${domain}:${port}/file/${encodeURIComponent(this.account)}/${encodeURIComponent(this.bucketName)}`, filePath);
927
- }
928
- async getConfig() {
929
- return getBucketConfig(await requireBucket(this.account, this.bucketName));
930
- }
931
- async hasWriteAccess() {
932
- return true;
933
- }
934
- async getChangesAfter2(config) {
935
- return await (await this.findStore()).store.getChangesAfter2(config);
936
- }
937
- async getSyncStatus() {
938
- return await bucketSyncStatus(await requireBucket(this.account, this.bucketName));
939
- }
940
- }
941
- const localArchives = new Map();
942
- function getLocalArchives(account, bucketName, sourceConfig) {
943
- let key = `${account}/${bucketName}|${stableStringify(sourceConfig)}`;
944
- let existing = localArchives.get(key);
945
- if (existing)
946
- return existing;
947
- let archives = new BucketIArchivesWrapper(account, bucketName, sourceConfig);
948
- localArchives.set(key, archives);
949
- return archives;
950
- }
951
- exports.getLocalArchives = getLocalArchives;
952
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmFnZVNlcnZlclN0YXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3RvcmFnZVNlcnZlclN0YXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLGdEQUF3QjtBQUN4Qiw0Q0FBb0I7QUFDcEIseURBQW1EO0FBQ25ELG1EQUFnRDtBQUNoRCwyREFBK0Q7QUFDL0Qsa0RBQStDO0FBQy9DLDJDQUF1SDtBQUN2SCw0Q0FHc0I7QUFDdEIsaURBQWlNO0FBQ2pNLCtEQUF3SztBQUN4SyxxREFBMkQ7QUFDM0QscURBQWlGO0FBQ2pGLDJEQUE4RDtBQUM5RCxpREFBNkU7QUFDN0UsNkNBQXdJO0FBQ3hJLDJDQUF3RztBQTBCeEcsbUxBQW1MO0FBQ25MLFNBQVMsZUFBZSxDQUFDLEtBQWM7SUFDbkMsSUFBSSxDQUFDLEtBQUssSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRO1FBQUUsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3RFLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3ZCLE9BQU8sSUFBSSxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUM7SUFDL0QsQ0FBQztJQUNELElBQUksT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBZ0MsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxTQUFTLENBQUMsQ0FBQztJQUMvRixJQUFBLFdBQUksRUFBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6QixPQUFPLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksZUFBZSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQztBQUM5RyxDQUFDO0FBRUQsME1BQTBNO0FBQ25NLEtBQUssVUFBVSxhQUFhLENBQUMsT0FBZSxFQUFFLFVBQWtCO0lBQ25FLElBQUksTUFBTSxHQUFHLE1BQU0sZUFBZSxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQztJQUN4RCxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDVixNQUFNLElBQUksS0FBSyxDQUFDLFVBQVUsT0FBTyxJQUFJLFVBQVUsK0RBQStELElBQUksQ0FBQyxTQUFTLENBQUMsMkJBQVksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQ2hLLENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNsQixDQUFDO0FBTkQsc0NBTUM7QUFFRCxndEJBQWd0QjtBQUNodEIsU0FBUyxjQUFjLENBQUMsTUFBb0I7SUFDeEMsSUFBSSxHQUFHLEdBQUcsTUFBTSxDQUFDLFlBQVksSUFBSSxNQUFNLENBQUMsR0FBRyxDQUFDO0lBQzVDLE9BQU8sZUFBZSxDQUFDLEVBQUUsR0FBRyxNQUFNLEVBQUUsR0FBRyxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUM7QUFDaEcsQ0FBQztBQUVELCtYQUErWDtBQUN4WCxLQUFLLFVBQVUsZUFBZSxDQUFDLE9BQWUsRUFBRSxVQUFrQixFQUFFLFlBQXNDO0lBQzdHLElBQUksTUFBTSxHQUFHLE1BQU0sYUFBYSxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQztJQUN0RCxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDaEIsTUFBTSxJQUFJLEtBQUssQ0FBQywwREFBMEQsT0FBTyxJQUFJLFVBQVUsNEVBQTRFLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNyTixDQUFDO0lBQ0QsSUFBSSxNQUFNLEdBQUcsY0FBYyxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQzFDLEtBQUssSUFBSSxDQUFDLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLEtBQUssTUFBTSxDQUFDO1lBQUUsT0FBTyxDQUFDLENBQUM7SUFDcEUsQ0FBQztJQUNELE1BQU0sSUFBSSxLQUFLLENBQUMsa0ZBQWtGLE9BQU8sSUFBSSxVQUFVLGdCQUFnQixJQUFJLENBQUMsU0FBUyxDQUFDLFlBQVksQ0FBQyxnQkFBZ0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQzdOLENBQUM7QUFWRCwwQ0FVQztBQUVELCtRQUErUTtBQUN4USxLQUFLLFVBQVUsa0JBQWtCLENBQUMsT0FBZSxFQUFFLFVBQWtCLEVBQUUsTUFBNkY7SUFDdkssSUFBSSxNQUFNLEdBQUcsTUFBTSxhQUFhLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3RELElBQUksT0FBTyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxLQUFLLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxDQUFDLGlCQUFpQixFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvSyxJQUFJLElBQW1FLENBQUM7SUFDeEUsS0FBSyxJQUFJLE1BQU0sSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUN6QixJQUFJLE1BQU0sSUFBSSxDQUFDLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDekQsSUFBSSxHQUFHLE1BQU0sQ0FBQztRQUNsQixDQUFDO0lBQ0wsQ0FBQztJQUNELE9BQU8sSUFBSSxDQUFDO0FBQ2hCLENBQUM7QUFWRCxnREFVQztBQUVELFNBQWdCLGVBQWUsQ0FBQyxNQUFtQjs7SUFDL0MsSUFBSSxLQUFLLEdBQUcsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUUsQ0FBQztJQUMzQyxJQUFJLFlBQVksR0FBa0UsRUFBRSxDQUFDO0lBQ3JGLElBQUksT0FBTyxHQUFtQixFQUFFLENBQUM7SUFDakMsSUFBSSxlQUFtQyxDQUFDO0lBQ3hDLEtBQUssSUFBSSxDQUFDLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzFCLElBQUksUUFBUSxHQUFHLE1BQUEsTUFBQSxDQUFDLENBQUMsS0FBSyxFQUFDLGVBQWUsa0RBQUksQ0FBQztRQUMzQyxJQUFJLENBQUMsUUFBUTtZQUFFLFNBQVM7UUFDeEIsS0FBSyxDQUFDLFNBQVMsSUFBSSxRQUFRLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQztRQUM1QyxLQUFLLENBQUMsU0FBUyxJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDO1FBQzVDLFlBQVksQ0FBQyxJQUFJLENBQUMsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDdkMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNsQyxlQUFlLEdBQUcsZUFBZSxJQUFJLFFBQVEsQ0FBQyxlQUFlLENBQUM7SUFDbEUsQ0FBQztJQUNELE9BQU87UUFDSCxxS0FBcUs7UUFDckssb0JBQW9CLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxZQUFZLHFCQUFTLENBQUM7UUFDM0UsWUFBWSxFQUFFLE1BQU0sQ0FBQyxPQUFPO1FBQzVCLEtBQUs7UUFDTCxZQUFZO1FBQ1osZUFBZTtRQUNmLE9BQU87S0FDVixDQUFDO0FBQ04sQ0FBQztBQXZCRCwwQ0F1QkM7QUFFTSxLQUFLLFVBQVUsZ0JBQWdCLENBQUMsTUFBbUI7SUFDdEQsSUFBSSxTQUFTLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ2pFLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDcEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLE1BQU0sQ0FBQyxPQUFPLElBQUksTUFBTSxDQUFDLFVBQVUsMkVBQTJFLENBQUMsQ0FBQztJQUM5SSxDQUFDO0lBQ0QsSUFBSSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFDLENBQUMsRUFBQyxFQUFFO1FBQ3JELElBQUksYUFBYSxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDO1FBQzFDLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLDhDQUE4QyxNQUFNLENBQUMsT0FBTyxJQUFJLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBQ3pHLENBQUM7UUFDRCxPQUFPLE1BQU0sYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDN0MsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNKLE9BQU87UUFDSCxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDO1FBQ3pELFNBQVMsRUFBRSxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDO1FBQzVELE9BQU8sRUFBRSxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztLQUM1QyxDQUFDO0FBQ04sQ0FBQztBQWpCRCw0Q0FpQkM7QUFFTSxLQUFLLFVBQVUsaUJBQWlCLENBQUMsTUFBbUI7SUFDdkQsSUFBSSxTQUFTLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLENBQUM7SUFDdEUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDeEMsSUFBSSxNQUFNLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFDLENBQUMsRUFBQyxFQUFFO1FBQ25ELElBQUksa0JBQWtCLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQztRQUNwRCxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUN0QixNQUFNLElBQUksS0FBSyxDQUFDLG1EQUFtRCxNQUFNLENBQUMsT0FBTyxJQUFJLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBQzlHLENBQUM7UUFDRCxPQUFPLE1BQU0sa0JBQWtCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNsRCxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ0osT0FBTztRQUNILFNBQVMsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDO1FBQzFELFNBQVMsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDO1FBQzFELE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztLQUMxQyxDQUFDO0FBQ04sQ0FBQztBQWZELDhDQWVDO0FBRUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQTRDLENBQUM7QUFFcEUsTUFBTSx1QkFBdUIsR0FBRyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztBQUM1QyxNQUFNLHVCQUF1QixHQUFHLElBQUksQ0FBQztBQUVyQyxTQUFTLDZCQUE2QixDQUFDLE1BQW1COztJQUN0RCxJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDckIsSUFBSSxVQUFVLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQ3JGLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTTtRQUFFLE9BQU87SUFDL0IsSUFBSSxZQUFZLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDO0lBQzNDLElBQUksR0FBRyxHQUFHLEdBQUcsTUFBTSxDQUFDLE9BQU8sSUFBSSxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDbkQsSUFBSSxLQUFLLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRTtRQUN4QixLQUFLLENBQUMsS0FBSyxJQUFJLEVBQUU7WUFDYixJQUFJLE9BQU8sR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDckMsSUFBSSxPQUFPLEtBQUssTUFBTTtnQkFBRSxPQUFPO1lBQy9CLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLFlBQVksRUFBRSxDQUFDO2dCQUM1Qiw2QkFBNkIsQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDdEMsT0FBTztZQUNYLENBQUM7WUFDRCxNQUFNLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLFVBQVUsRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLGdDQUFnQyxFQUFFLENBQUMsQ0FBQztRQUM5SCxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ1QsQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxHQUFHLEdBQUcsR0FBRyx1QkFBdUIsRUFBRSx1QkFBdUIsQ0FBQyxDQUFDLENBQUM7SUFDcEYsTUFBQSxNQUFDLEtBQWdDLEVBQUMsS0FBSyxrREFBSSxDQUFDO0FBQ2hELENBQUM7QUFFRCxNQUFNLHFCQUFxQixHQUFHLENBQUMsQ0FBQyxFQUFFLEdBQUcsSUFBSSxFQUFFLENBQUMsR0FBRyxJQUFJLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0FBQ2hFLE1BQU0sc0JBQXNCLEdBQUcsb0NBQXdCLEdBQUcsbUNBQXVCLENBQUM7QUFDbEYsTUFBTSwyQkFBMkIsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBRTlDLE1BQU0sc0JBQXNCLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztBQUNqRCxNQUFNLG9CQUFvQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7QUFFL0MsU0FBUyxxQkFBcUIsQ0FBQyxNQUFtQjs7SUFDOUMsSUFBSSxHQUFHLEdBQUcsR0FBRyxNQUFNLENBQUMsT0FBTyxJQUFJLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUNuRCxJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDckIsSUFBSSxNQUFNLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUMvQixLQUFLLElBQUksSUFBSSxJQUFJLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNsQyxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2hDLElBQUksS0FBSyxHQUFHLEdBQUcsSUFBSSxLQUFLLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDakQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN0QixDQUFDO0lBQ0wsQ0FBQztJQUNELEtBQUssSUFBSSxJQUFJLElBQUksTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ2xDLElBQUksQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUNwQyxJQUFJLENBQUMsQ0FBQyxLQUFLLElBQUksR0FBRyxJQUFJLEdBQUcsR0FBRyxHQUFHLENBQUMsSUFBSSxLQUFLLElBQUksQ0FBQztZQUFFLFNBQVM7UUFDekQsSUFBSSxHQUFHLEdBQUcsS0FBSyxHQUFHLHNCQUFzQjtZQUFFLFNBQVM7UUFDbkQsSUFBSSxXQUFXLEdBQUcsR0FBRyxHQUFHLElBQUksS0FBSyxVQUFVLENBQUM7UUFDNUMsSUFBSSxzQkFBc0IsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDO1lBQUUsU0FBUztRQUN0RCxzQkFBc0IsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDeEMsSUFBSSxLQUFLLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUN4QixLQUFLLGVBQWUsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLDJCQUEyQixFQUFFLGFBQWEsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQVEsRUFBRSxFQUFFLFdBQUMsT0FBQSxPQUFPLENBQUMsS0FBSyxDQUFDLDRCQUE0QixHQUFHLFlBQVksTUFBQSxDQUFDLENBQUMsS0FBSyxtQ0FBSSxDQUFDLEVBQUUsQ0FBQyxDQUFBLEVBQUEsQ0FBQyxDQUFDO1FBQy9LLENBQUMsRUFBRSwyQkFBMkIsQ0FBQyxDQUFDO1FBQ2hDLE1BQUEsTUFBQyxLQUFnQyxFQUFDLEtBQUssa0RBQUksQ0FBQztJQUNoRCxDQUFDO0lBQ0QsS0FBSyxJQUFJLEtBQUssSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUN2QixLQUFLLElBQUksTUFBTSxJQUFJLHFCQUFxQixFQUFFLENBQUM7WUFDdkMsSUFBSSxFQUFFLEdBQUcsS0FBSyxHQUFHLE1BQU0sQ0FBQztZQUN4QixJQUFJLEVBQUUsSUFBSSxHQUFHO2dCQUFFLFNBQVM7WUFDeEIsSUFBSSxXQUFXLEdBQUcsR0FBRyxHQUFHLElBQUksS0FBSyxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQzlDLElBQUksc0JBQXNCLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQztnQkFBRSxTQUFTO1lBQ3RELHNCQUFzQixDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN4QyxJQUFJLEdBQUcsR0FBRyxHQUFHLEVBQUU7O2dCQUNYLElBQUksS0FBSyxHQUFHLFVBQVUsQ0FBQyxHQUFHLEVBQUU7b0JBQ3hCLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO3dCQUNsQixHQUFHLEVBQUUsQ0FBQzt3QkFDTixPQUFPO29CQUNYLENBQUM7b0JBQ0QsS0FBSyxlQUFlLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFRLEVBQUUsRUFBRSxXQUFDLE9BQUEsT0FBTyxDQUFDLEtBQUssQ0FBQyw0QkFBNEIsR0FBRyxZQUFZLE1BQUEsQ0FBQyxDQUFDLEtBQUssbUNBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQSxFQUFBLENBQUMsQ0FBQztnQkFDM0ksQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsRUFBRSx1QkFBdUIsQ0FBQyxDQUFDLENBQUM7Z0JBQ3ZELE1BQUEsTUFBQyxLQUFnQyxFQUFDLEtBQUssa0RBQUksQ0FBQztZQUNoRCxDQUFDLENBQUM7WUFDRixHQUFHLEVBQUUsQ0FBQztRQUNWLENBQUM7SUFDTCxDQUFDO0FBQ0wsQ0FBQztBQUVELEtBQUssVUFBVSxlQUFlLENBQUMsU0FBaUIsRUFBRSxXQUFtQixFQUFFLE1BQWMsRUFBRSxXQUFvQjs7SUFDdkcsSUFBSSxLQUFLLEdBQUcsVUFBVSxTQUFTLHFCQUFxQixJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxXQUFXLEVBQUUsWUFBWSxXQUFXLElBQUksR0FBRyxNQUFNLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUN4SSxJQUFJLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1FBQ3RDLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLEtBQUssZ0RBQWdELENBQUMsQ0FBQztRQUM5RixPQUFPO0lBQ1gsQ0FBQztJQUNELG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNwQyxJQUFJLENBQUM7UUFDRCxJQUFJLE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDMUMsSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPO1FBQ3BCLElBQUksU0FBUyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUM7UUFDL0IsSUFBSSxXQUFXLEdBQUcsSUFBQSwyQkFBZSxFQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNoRixJQUFJLFlBQVksR0FBRyxJQUFJLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUN4QyxJQUFJLE1BQU0sR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQWlCLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxLQUFLLFdBQVcsQ0FBQyxDQUFDO1FBQ3RILElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTTtZQUFFLE9BQU87UUFDM0IsSUFBSSxRQUFRLEdBQUcsV0FBVyxHQUFHLENBQUMsQ0FBQztRQUMvQixtSkFBbUo7UUFDbkosSUFBSSxZQUFZLEdBQUcsSUFBSSxHQUFHLEVBQWUsQ0FBQztRQUMxQyxJQUFJLFlBQVksR0FBRyxJQUFJLEdBQUcsRUFBOEMsQ0FBQztRQUN6RSxLQUFLLElBQUksSUFBSSxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ3RCLElBQUksU0FBUyxHQUFHLElBQUksQ0FBQyxLQUFLLElBQUksc0JBQVUsQ0FBQztZQUN6QyxJQUFJLFNBQVMsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO1lBQ2xGLElBQUksQ0FBQyxTQUFTLElBQUksQ0FBQyxDQUFDLFNBQVMsQ0FBQyxLQUFLLFlBQVkscUJBQVMsQ0FBQztnQkFBRSxTQUFTO1lBQ3BFLElBQUksR0FBRyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzFDLElBQUksUUFBUSxHQUFHLEtBQUssQ0FBQztZQUNyQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQzNCLElBQUksS0FBSyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2pDLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUTtvQkFBRSxTQUFTO2dCQUN4QyxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUM7Z0JBQ2pDLElBQUksQ0FBQyxDQUFDLEVBQUUsSUFBSSxXQUFXLElBQUksV0FBVyxHQUFHLEVBQUUsQ0FBQztvQkFBRSxTQUFTO2dCQUN2RCxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSyxJQUFJLHNCQUFVLENBQUM7Z0JBQ2xDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7b0JBQy9DLFFBQVEsR0FBRyxJQUFJLENBQUM7b0JBQ2hCLE1BQU07Z0JBQ1YsQ0FBQztZQUNMLENBQUM7WUFDRCxJQUFJLFFBQVE7Z0JBQUUsU0FBUztZQUN2QixJQUFJLFNBQVMsR0FBdUIsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ25FLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLE1BQU0sSUFBSSxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQ3BFLElBQUksS0FBSyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2pDLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUTtvQkFBRSxTQUFTO2dCQUN4QyxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUM7Z0JBQ2pDLElBQUksQ0FBQyxDQUFDLEVBQUUsSUFBSSxRQUFRLElBQUksUUFBUSxHQUFHLEVBQUUsQ0FBQztvQkFBRSxTQUFTO2dCQUNqRCxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSyxJQUFJLHNCQUFVLENBQUM7Z0JBQ2xDLElBQUksU0FBUyxHQUF1QixFQUFFLENBQUM7Z0JBQ3ZDLElBQUksT0FBcUMsQ0FBQztnQkFDMUMsS0FBSyxJQUFJLENBQUMsSUFBSSxTQUFTLEVBQUUsQ0FBQztvQkFDdEIsSUFBSSxLQUFLLEdBQUcsSUFBQSxnQ0FBaUIsRUFBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7b0JBQ3BDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQzt3QkFDVCxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO3dCQUNsQixTQUFTO29CQUNiLENBQUM7b0JBQ0QsT0FBTyxHQUFHLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFxQixJQUFJLEtBQUssQ0FBQztvQkFDbkgsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQzt3QkFBRSxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQ3RELElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7d0JBQUUsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUMxRCxDQUFDO2dCQUNELFNBQVMsR0FBRyxTQUFTLENBQUM7Z0JBQ3RCLElBQUksQ0FBQyxPQUFPO29CQUFFLFNBQVM7Z0JBQ3ZCLElBQUksWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO29CQUN0QixZQUFZLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUNoQyxDQUFDO3FCQUFNLENBQUM7b0JBQ0osSUFBSSxNQUFNLEdBQUcsWUFBWSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztvQkFDekMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO3dCQUNWLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO3dCQUNuQixZQUFZLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQztvQkFDeEMsQ0FBQztvQkFDRCxJQUFJLFFBQVEsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUM3QixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxRQUFRLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBcUIsSUFBSSxPQUFPLENBQUMsQ0FBQztnQkFDckksQ0FBQztZQUNMLENBQUM7UUFDTCxDQUFDO1FBQ0QsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSTtZQUFFLE9BQU87UUFDckQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsS0FBSyxnQkFBZ0IsWUFBWSxDQUFDLElBQUksZ0RBQWdELFlBQVksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3pJLEtBQUssSUFBSSxTQUFTLElBQUksWUFBWSxFQUFFLENBQUM7WUFDakMsSUFBSSxTQUFTLENBQUMsS0FBSyxZQUFZLHFCQUFTLEVBQUUsQ0FBQztnQkFDdkMsTUFBTSxTQUFTLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3ZDLENBQUM7UUFDTCxDQUFDO1FBQ0QsSUFBSSxLQUFLLEdBQUcsV0FBVyxHQUFHLHNCQUFzQixDQUFDO1FBQ2pELEtBQUssSUFBSSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsSUFBSSxZQUFZLEVBQUUsQ0FBQztZQUMzQyxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUMsS0FBSyxZQUFZLHFCQUFTLENBQUM7Z0JBQUUsU0FBUztZQUN0RCxLQUFLLElBQUksQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLElBQUksTUFBTSxFQUFFLENBQUM7Z0JBQ3RDLElBQUksV0FBVyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQ2pELElBQUksT0FBTyxXQUFXLEtBQUssUUFBUTtvQkFBRSxTQUFTO2dCQUM5QyxJQUFJLENBQUM7b0JBQ0QsTUFBTSxTQUFTLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLElBQUEsa0NBQWlCLEVBQUMsV0FBVyxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztnQkFDL0YsQ0FBQztnQkFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO29CQUNULE9BQU8sQ0FBQyxLQUFLLENBQUMsa0JBQWtCLEtBQUssNENBQTRDLFdBQVcsYUFBYSxNQUFDLENBQVcsQ0FBQyxLQUFLLG1DQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ3hJLENBQUM7WUFDTCxDQUFDO1FBQ0wsQ0FBQztJQUNMLENBQUM7WUFBUyxDQUFDO1FBQ1Asb0JBQW9CLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzNDLENBQUM7QUFDTCxDQUFDO0FBRUQsTUFBTSxzQkFBc0IsR0FBRyxJQUFJLEdBQUcsRUFBcUIsQ0FBQztBQUM1RCw4VkFBOFY7QUFDOVYsU0FBZ0IscUJBQXFCLENBQUMsR0FBVztJQUM3QyxJQUFJLFFBQVEsR0FBRyxzQkFBc0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDL0MsSUFBSSxRQUFRO1FBQUUsT0FBTyxRQUFRLENBQUM7SUFDOUIsSUFBSSxRQUFtQixDQUFDO0lBQ3hCLElBQUksR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQzdCLHFOQUFxTjtRQUNyTixRQUFRLEdBQUcsSUFBQSxrQ0FBaUIsRUFBQyxJQUFBLDhCQUFlLEVBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN2RCxDQUFDO1NBQU0sQ0FBQztRQUNKLFFBQVEsR0FBRyxJQUFJLDJCQUFZLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUNELHNCQUFzQixDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDMUMsT0FBTyxRQUFRLENBQUM7QUFDcEIsQ0FBQztBQVpELHNEQVlDO0FBRUQsU0FBUyxjQUFjLENBQUMsWUFBc0M7SUFDMUQsSUFBSSxDQUFDLFlBQVk7UUFBRSxPQUFPLE1BQU0sQ0FBQztJQUNqQyxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxHQUFHLFlBQVksRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO0FBQ3pGLENBQUM7QUFFRCxTQUFTLFVBQVUsQ0FBQyxPQUFlLEVBQUUsVUFBa0IsRUFBRSxTQUF5QjtJQUM5RSxJQUFJLE1BQU0sR0FBRyxJQUFBLDRCQUFlLEVBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDbkUsSUFBSSxTQUFTLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDcEIsT0FBTyxJQUFJLHdCQUFZLENBQUMsSUFBSSwyQkFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDdEQsQ0FBQztJQUNELElBQUksT0FBTyxHQUFxQixTQUFTLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRTs7UUFBQyxPQUFBLENBQUM7WUFDL0QsTUFBTSxFQUFFLElBQUksQ0FBQyxZQUFZLElBQUksSUFBQSxrQ0FBaUIsRUFBQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksSUFBSSwyQkFBWSxDQUFDLE1BQU0sQ0FBQztZQUM3RixHQUFHLEVBQUUsQ0FBQSxNQUFBLElBQUksQ0FBQyxZQUFZLDBDQUFFLEdBQUcsS0FBSSxNQUFNO1lBQ3JDLFlBQVksRUFBRSxJQUFJLENBQUMsWUFBWTtZQUMvQixLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUs7WUFDakIsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVO1lBQzNCLFlBQVksRUFBRSxNQUFBLElBQUksQ0FBQyxZQUFZLDBDQUFFLFlBQVk7WUFDN0MsWUFBWSxFQUFFLElBQUksQ0FBQyxZQUFZO1lBQy9CLFFBQVEsRUFBRSxjQUFjLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQztTQUM5QyxDQUFDLENBQUE7S0FBQSxDQUFDLENBQUM7SUFDSixPQUFPLElBQUkscUJBQVMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFO1FBQ2xDLGVBQWUsRUFBRSxTQUFTLENBQUMsZUFBZTtRQUMxQyxjQUFjLEVBQUUsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLE9BQU8sSUFBSSxVQUFVLEVBQUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDO1FBQzFGLGdCQUFnQixFQUFFLHFCQUFxQjtRQUN2QyxPQUFPLEVBQUUsU0FBUyxDQUFDLE9BQU87S0FDN0IsQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQUVELFNBQVMsV0FBVyxDQUFDLE9BQWUsRUFBRSxVQUFrQixFQUFFLE9BQXFCLEVBQUUsSUFBZ0I7SUFDN0YsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ1IsSUFBSSxHQUFHLElBQUEsNEJBQWdCLEVBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUMxRCxDQUFDO0lBQ0QsSUFBSSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUM7SUFDakMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ1IsT0FBTyxDQUFDLEdBQUcsQ0FBQyx1REFBdUQsT0FBTyxJQUFJLFVBQVUsc0hBQXNILENBQUMsQ0FBQztJQUNwTixDQUFDO0lBQ0QsSUFBSSxNQUFNLEdBQWtCLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN0RCxRQUFRLEVBQUUsU0FBUyxDQUFDLFFBQVE7UUFDNUIsS0FBSyxFQUFFLFNBQVMsQ0FBQyxLQUFLO1FBQ3RCLE9BQU8sRUFBRSxTQUFTLENBQUMsT0FBTztRQUMxQixNQUFNLEVBQUUsSUFBQSw0QkFBZSxFQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsU0FBUyxDQUFDLEtBQUssQ0FBQztRQUM3RCxLQUFLLEVBQUUsVUFBVSxDQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsU0FBUyxDQUFDO0tBQ3BELENBQUMsQ0FBQyxDQUFDO0lBQ0osSUFBSSxNQUFNLEdBQWdCLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsV0FBVyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUM3Siw2QkFBNkIsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN0QyxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM5QixpUkFBaVI7SUFDalIsS0FBSyxJQUFJLENBQUMsSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUNuQixJQUFJLENBQUMsQ0FBQyxLQUFLLFlBQVkscUJBQVMsRUFBRSxDQUFDO1lBQy9CLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUM7WUFDcEIsS0FBSyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUSxFQUFFLEVBQUUsV0FBQyxPQUFBLE9BQU8sQ0FBQyxLQUFLLENBQUMscUNBQXFDLE9BQU8sSUFBSSxVQUFVLFdBQVcsQ0FBQyxDQUFDLFFBQVEsYUFBYSxNQUFBLENBQUMsQ0FBQyxLQUFLLG1DQUFJLENBQUMsRUFBRSxDQUFDLENBQUEsRUFBQSxDQUFDLENBQUM7UUFDckssQ0FBQztJQUNMLENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNsQixDQUFDO0FBRUQsS0FBSyxVQUFVLFVBQVUsQ0FBQyxPQUFlLEVBQUUsVUFBa0I7SUFDekQsSUFBSSxPQUFPLEdBQUcsTUFBTSxJQUFBLGdDQUFtQixFQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQztJQUM3RCxJQUFJLENBQUMsT0FBTztRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQy9CLE9BQU8sV0FBVyxDQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFDckQsQ0FBQztBQUVELFNBQWdCLGVBQWUsQ0FBQyxPQUFlLEVBQUUsVUFBa0I7SUFDL0QsSUFBSSxHQUFHLEdBQUcsR0FBRyxPQUFPLElBQUksVUFBVSxFQUFFLENBQUM7SUFDckMsSUFBSSxNQUFNLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM5QixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDVixNQUFNLEdBQUcsVUFBVSxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQztRQUN6QyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUN6QixLQUFLLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDdEIsSUFBSSxDQUFDLE1BQU0sSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxLQUFLLE1BQU0sRUFBRSxDQUFDO2dCQUN6QyxPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3hCLENBQUM7UUFDTCxDQUFDLEVBQUUsR0FBRyxFQUFFO1lBQ0osSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxLQUFLLE1BQU0sRUFBRSxDQUFDO2dCQUM5QixPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3hCLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNsQixDQUFDO0FBakJELDBDQWlCQztBQUVELE1BQU0sY0FBYyxHQUFHLElBQUksR0FBRyxFQUF5QixDQUFDO0FBQ3hELFNBQVMscUJBQXFCLENBQUMsT0FBZSxFQUFFLFVBQWtCLEVBQUUsTUFBNkM7SUFDN0csSUFBSSxHQUFHLEdBQUcsR0FBRyxPQUFPLElBQUksVUFBVSxFQUFFLENBQUM7SUFDckMsSUFBSSxJQUFJLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUNwRCxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsbUJBQW1CLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQztTQUM1RCxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLHVDQUF1QyxHQUFHLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hGLGNBQWMsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQzlCLE9BQU8sSUFBSSxDQUFDO0FBQ2hCLENBQUM7QUFFRCxLQUFLLFVBQVUsbUJBQW1CLENBQUMsT0FBZSxFQUFFLFVBQWtCLEVBQUUsTUFBNkM7SUFDakgsSUFBSSxHQUFHLEdBQUcsR0FBRyxPQUFPLElBQUksVUFBVSxFQUFFLENBQUM7SUFDckMsSUFBSSxNQUFNLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3BDLElBQUksQ0FBQyxNQUFNO1FBQUUsT0FBTztJQUNwQixJQUFJLE9BQU8sR0FBRyxNQUFNLElBQUEsZ0NBQW1CLEVBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQzdELElBQUksQ0FBQyxPQUFPO1FBQUUsT0FBTztJQUNyQixJQUFJLENBQUMsQ0FBQSxNQUFNLGFBQU4sTUFBTSx1QkFBTixNQUFNLENBQUUsS0FBSyxDQUFBLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsS0FBSyxNQUFNLENBQUMsV0FBVztRQUFFLE9BQU87SUFDN0UsSUFBSSxNQUFNLEdBQUcsQ0FBQSxNQUFNLGFBQU4sTUFBTSx1QkFBTixNQUFNLENBQUUsS0FBSyxLQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sSUFBSSxRQUFRLENBQUMsSUFBSSx3QkFBd0IsQ0FBQztJQUN0RixJQUFJLElBQUksR0FBRyxJQUFBLDRCQUFnQixFQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDMUQsSUFBSSxJQUFJLENBQUMsWUFBWSxLQUFLLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUM1QyxPQUFPLENBQUMsR0FBRyxDQUFDLGdFQUFnRSxHQUFHLEtBQUssTUFBTSxHQUFHLENBQUMsQ0FBQztRQUMvRixLQUFLLElBQUksU0FBUyxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNoQyxJQUFJLElBQUksR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLEtBQUssU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3RFLDBIQUEwSDtZQUMxSCxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxZQUFZLHFCQUFTLENBQUM7Z0JBQUUsU0FBUztZQUMxRCxJQUFJLFdBQVcsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO1lBQzlCLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFO2dCQUN0RCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO2dCQUN2QyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7b0JBQ2hCLE9BQU8sRUFBRSxRQUFRLEVBQUUsY0FBYyxDQUFDLFNBQVMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLElBQUksQ0FBQyxZQUFZLEVBQUUsTUFBTSxFQUFFLEdBQWMsRUFBRSxDQUFDLElBQUksMkJBQVksQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO2dCQUM5SixDQUFDO2dCQUNELE9BQU87b0JBQ0gsUUFBUSxFQUFFLGNBQWMsQ0FBQyxZQUFZLENBQUM7b0JBQ3RDLEdBQUcsRUFBRSxZQUFZLENBQUMsR0FBRztvQkFDckIsWUFBWSxFQUFFLElBQUksQ0FBQyxZQUFZO29CQUMvQixLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUs7b0JBQ2pCLFVBQVUsRUFBRSxJQUFJLENBQUMsVUFBVTtvQkFDM0IsWUFBWSxFQUFFLFlBQVksQ0FBQyxZQUFZO29CQUN2QyxZQUFZO29CQUNaLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFBLGtDQUFpQixFQUFDLFlBQVksQ0FBQztpQkFDaEQsQ0FBQztZQUNOLENBQUMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN2QixJQUFJLENBQUMsT0FBTyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUM7UUFDckMsQ0FBQztRQUNELE1BQU0sQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3pCLE1BQU0sQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUM3QyxNQUFNLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7UUFDdEMsTUFBTSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBQ3hCLDZCQUE2QixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzlCLElBQUEsMkNBQXVCLEdBQUUsQ0FBQztRQUMxQixPQUFPO0lBQ1gsQ0FBQztJQUNELE9BQU8sQ0FBQyxHQUFHLENBQUMsb0NBQW9DLEdBQUcsS0FBSyxNQUFNLDZCQUE2QixNQUFNLENBQUMsWUFBWSxPQUFPLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO0lBQzFJLEtBQUssSUFBSSxDQUFDLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxDQUFDLEtBQUssWUFBWSxxQkFBUyxFQUFFLENBQUM7WUFDL0IsTUFBTSxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQzVCLENBQUM7SUFDTCxDQUFDO0lBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ25GLElBQUEsMkNBQXVCLEdBQUUsQ0FBQztBQUM5QixDQUFDO0FBRUQsTUFBTSxhQUFhLEdBQUcsSUFBSSxHQUFHLEVBQXlCLENBQUM7QUFFdkQsaU5BQWlOO0FBQzFNLEtBQUssVUFBVSx1QkFBdUIsQ0FBQyxPQUFlLEVBQUUsVUFBa0IsRUFBRSxJQUFZLEVBQUUsTUFBa0M7SUFDL0gsSUFBQSxrQ0FBbUIsR0FBRSxDQUFDO0lBQ3RCLElBQUksR0FBRyxHQUFHLEdBQUcsT0FBTyxJQUFJLFVBQVUsRUFBRSxDQUFDO0lBQ3JDLElBQUksR0FBRyxHQUFHLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsa0JBQWtCLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUMxSCxhQUFhLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZELE9BQU8sTUFBTSxHQUFHLENBQUM7QUFDckIsQ0FBQztBQU5ELDBEQU1DO0FBRUQsS0FBSyxVQUFVLGtCQUFrQixDQUFDLE9BQWUsRUFBRSxVQUFrQixFQUFFLElBQVksRUFBRSxNQUFrQztJQUNuSCxJQUFJLEdBQUcsR0FBRyxHQUFHLE9BQU8sSUFBSSxVQUFVLEVBQUUsQ0FBQztJQUNyQyxJQUFJLFFBQVEsR0FBRyxJQUFBLCtCQUFnQixFQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3RDLElBQUksTUFBTSxHQUFHLE1BQU0sZUFBZSxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQztJQUN4RCxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDVixNQUFNLHFCQUFxQixDQUFDLElBQUEsNEJBQWUsRUFBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsMkJBQVksRUFBRSxJQUFJLEVBQUUsRUFBRSxZQUFZLEVBQUUsTUFBTSxhQUFOLE1BQU0sdUJBQU4sTUFBTSxDQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7UUFDbEksT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDOUUsSUFBQSwyQ0FBdUIsR0FBRSxDQUFDO1FBQzFCLE9BQU8sQ0FBQyxHQUFHLENBQUMsa0JBQWtCLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDckMsT0FBTztJQUNYLENBQUM7SUFDRCxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLEtBQUssTUFBTSxDQUFDLFdBQVcsSUFBSSxJQUFBLCtCQUFnQixFQUFDLFFBQVEsQ0FBQyxJQUFJLElBQUEsK0JBQWdCLEVBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDcEgsSUFBSSxPQUFPLEdBQUcsMkNBQTJDLEdBQUcsa0VBQWtFLElBQUEsK0JBQWdCLEVBQUMsUUFBUSxDQUFDLDhDQUE4QyxJQUFBLCtCQUFnQixFQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsbURBQW1ELE1BQU0sQ0FBQyxXQUFXLGdCQUFnQixJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7UUFDdFYsT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN2QixNQUFNLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzdCLENBQUM7SUFDRCxJQUFJLE1BQU0sR0FBRyxRQUFRLENBQUM7SUFDdEIsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO0lBQ25CLEtBQUssSUFBSSxZQUFZLElBQUksSUFBQSw0Q0FBc0IsRUFBQyxJQUFBLCtDQUF5QixFQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3JHLE1BQU0sR0FBRyxJQUFBLDhDQUF3QixFQUFDLE1BQU0sRUFBRTtZQUN0QyxRQUFRLEVBQUUsWUFBWSxDQUFDLFlBQVksSUFBSSxZQUFZLENBQUMsR0FBRztZQUN2RCxlQUFlLEVBQUUsWUFBWSxDQUFDLEdBQUc7WUFDakMsS0FBSyxFQUFFLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO1lBQ2xDLEdBQUcsRUFBRSxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztTQUNuQyxDQUFDLENBQUM7UUFDSCxVQUFVLEVBQUUsQ0FBQztJQUNqQixDQUFDO0lBQ0QsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQUN0RCxPQUFPLENBQUMsR0FBRyxDQUFDLGVBQWUsVUFBVSw2RUFBNkUsR0FBRyxhQUFhLElBQUEsK0JBQWdCLEVBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3JLLENBQUM7SUFDRCwrSEFBK0g7SUFDL0gsTUFBTSxxQkFBcUIsQ0FBQyxJQUFBLDRCQUFlLEVBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLDJCQUFZLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFBLG9DQUFxQixFQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsRUFBRSxZQUFZLEVBQUUsTUFBTSxhQUFOLE1BQU0sdUJBQU4sTUFBTSxDQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7SUFDeEssTUFBTSxxQkFBcUIsQ0FBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUM7QUFDckQsQ0FBQztBQUVELHdLQUF3SztBQUN4SyxTQUFnQixtQkFBbUI7SUFDL0IsT0FBTyxDQUFDLEdBQUcsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1FBQ2pDLElBQUksS0FBSyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDN0IsT0FBTyxFQUFFLE9BQU8sRUFBRSxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsRUFBRSxVQUFVLEVBQUUsR0FBRyxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUM5RSxDQUFDLENBQUMsQ0FBQztBQUNQLENBQUM7QUFMRCxrREFLQztBQUVNLEtBQUssVUFBVSx1QkFBdUI7SUFDekMsS0FBSyxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUNsQyxJQUFJLEtBQUssR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzdCLE1BQU0scUJBQXFCLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsR0FBRyxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSwwQ0FBMEMsRUFBRSxDQUFDLENBQUM7SUFDaEosQ0FBQztBQUNMLENBQUM7QUFMRCwwREFLQztBQUVELE1BQU0seUJBQXlCLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUM1QyxNQUFNLDhCQUE4QixHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFDakQseUpBQXlKO0FBQ3pKLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7QUFFckQsS0FBSyxVQUFVLHFCQUFxQixDQUFDLE1BQW1CLEVBQUUsT0FBcUIsRUFBRSxNQUFjO0lBQzNGLElBQUksR0FBRyxHQUFHLEdBQUcsTUFBTSxDQUFDLE9BQU8sSUFBSSxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDbkQsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ2hFLElBQUksU0FBUyxHQUFHLHlCQUF5QixFQUFFLENBQUM7UUFDeEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3REFBd0QsR0FBRyxLQUFLLE1BQU0sdUJBQXVCLFNBQVMscUJBQXFCLHlCQUF5QiwrREFBK0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDMVAsT0FBTztJQUNYLENBQUM7SUFDRCxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQ3hDLElBQUksT0FBTyxHQUFHLElBQUEsNkNBQXVCLEVBQUMsSUFBQSwrQkFBZ0IsRUFBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUN4RSxJQUFJLElBQUksR0FBaUIsRUFBRSxHQUFHLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQztJQUNqRCxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsMkJBQVksZUFBZSxHQUFHLEtBQUssTUFBTSxjQUFjLElBQUEsK0JBQWdCLEVBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLE9BQU8sS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN6SixJQUFJLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUEsb0NBQXFCLEVBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNwRCxNQUFNLHVCQUF1QixDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUN2RSxNQUFNLHNCQUFzQixDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDckQsQ0FBQztBQUVELEtBQUssVUFBVSxzQkFBc0IsQ0FBQyxNQUFtQixFQUFFLElBQWtCLEVBQUUsSUFBWTs7SUFDdkYsSUFBSSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQXdCLENBQUM7SUFDOUMsS0FBSyxJQUFJLE1BQU0sSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUM5RCxJQUFJLE9BQU8sTUFBTSxLQUFLLFFBQVEsSUFBSSxNQUFNLENBQUMsWUFBWTtZQUFFLFNBQVM7UUFDaEUsSUFBSSxNQUFNLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQzNCLElBQUksTUFBTSxHQUFHLElBQUEsNkJBQWMsRUFBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDeEMsSUFBSSxNQUFNLENBQUMsT0FBTyxLQUFLLE1BQU0sQ0FBQyxPQUFPLElBQUksTUFBTSxDQUFDLFVBQVUsS0FBSyxNQUFNLENBQUMsVUFBVTtnQkFBRSxTQUFTO1FBQy9GLENBQUM7UUFDRCxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQztZQUFFLFNBQVM7UUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFDRCxLQUFLLElBQUksQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLElBQUksT0FBTyxFQUFFLENBQUM7UUFDaEMsSUFBSSxDQUFDO1lBQ0QsTUFBTSxJQUFBLGtDQUFpQixFQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQywyQkFBWSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ3hELE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUywyQkFBWSxlQUFlLE1BQU0sQ0FBQyxPQUFPLElBQUksTUFBTSxDQUFDLFVBQVUsT0FBTyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQ3JHLENBQUM7UUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ1QsT0FBTyxDQUFDLEtBQUssQ0FBQyw0Q0FBNEMsR0FBRyxZQUFZLE1BQUMsQ0FBVyxDQUFDLEtBQUssbUNBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN4RyxDQUFDO0lBQ0wsQ0FBQztBQUNMLENBQUM7QUFFRCxLQUFLLFVBQVUscUJBQXFCO0lBQ2hDLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsSUFBQSxxQ0FBc0IsR0FBRSxDQUFDO0lBQ2hELElBQUksUUFBUSxHQUFHLElBQUEsd0NBQXVCLEdBQUUsQ0FBQztJQUN6QyxJQUFJLE9BQU8sR0FBYSxFQUFFLENBQUM7SUFDM0IsSUFBSSxjQUFjLEdBQWEsRUFBRSxDQUFDO0lBQ2xDLElBQUksT0FBTyxHQUFhLEVBQUUsQ0FBQztJQUMzQix3VEFBd1Q7SUFDeFQsSUFBSSxJQUFJLEdBQUcsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQy9CLEtBQUssSUFBSSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7UUFDbkIsSUFBSSxhQUFhLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNyQyxJQUFJLENBQUMsYUFBYTtZQUFFLFNBQVM7UUFDN0IsSUFBSSxNQUFNLEdBQUcsTUFBTSxhQUFhLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3hELElBQUksQ0FBQyxNQUFNO1lBQUUsU0FBUztRQUN0QixJQUFJLE9BQU8sR0FBRyxJQUFBLCtDQUF5QixFQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDcEUsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxLQUFLLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDN0QsTUFBTSxxQkFBcUIsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLHdDQUF3QywrQ0FBeUIsR0FBRyxJQUFJLE9BQU8sQ0FBQyxDQUFDO1lBQzlILE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDbEIsU0FBUztRQUNiLENBQUM7UUFDRCxJQUFJLENBQUMsUUFBUTtZQUFFLFNBQVM7UUFDeEIsSUFBSSxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQzFDLElBQUksT0FBTyxDQUFDLEtBQUssUUFBUSxJQUFJLENBQUMsQ0FBQyxJQUFJLEtBQUssUUFBUSxJQUFJLENBQUMsQ0FBQyxZQUFZO2dCQUFFLE9BQU8sS0FBSyxDQUFDO1lBQ2pGLElBQUksTUFBTSxHQUFHLElBQUEsNkJBQWMsRUFBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDbkMsT0FBTyxNQUFNLENBQUMsT0FBTyxLQUFLLE1BQU0sSUFBSSxNQUFNLENBQUMsSUFBSSxLQUFLLElBQUksQ0FBQztRQUM3RCxDQUFDLENBQTZCLENBQUM7UUFDL0IsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ1gsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNsQixTQUFTO1FBQ2IsQ0FBQztRQUNELElBQUksUUFBUSxHQUFHLElBQUEsOENBQXdCLEVBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRTtZQUNwRCxRQUFRLEVBQUUsT0FBTyxDQUFDLEdBQUc7WUFDckIsZUFBZSxFQUFFLElBQUEsbUNBQW9CLEVBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsT0FBTyxDQUFDO1lBQ3BFLEtBQUssRUFBRSxRQUFRLENBQUMsS0FBSztZQUNyQixHQUFHLEVBQUUsUUFBUSxDQUFDLEdBQUc7U0FDcEIsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxLQUFLLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDOUQsY0FBYyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN6QixTQUFTO1FBQ2IsQ0FBQztRQUNELE1BQU0scUJBQXFCLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxpRUFBaUUsUUFBUSxDQUFDLE9BQU8sU0FBUyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsV0FBVyxFQUFFLHVDQUF1QyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQzdQLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdEIsQ0FBQztJQUNELElBQUksQ0FBQyxRQUFRO1FBQUUsT0FBTztJQUN0QixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2YsT0FBTyxDQUFDLEdBQUcsQ0FBQyx1SEFBdUgsQ0FBQyxDQUFDO1FBQ3JJLE9BQU87SUFDWCxDQUFDO0lBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNsQixPQUFPLENBQUMsR0FBRyxDQUFDLDZCQUE2QixJQUFJLENBQUMsTUFBTSxvQkFBb0IsY0FBYyxDQUFDLE1BQU0seUNBQXlDLE9BQU8sQ0FBQyxNQUFNLHVCQUF1QixDQUFDLENBQUM7SUFDakwsQ0FBQztBQUNMLENBQUM7QUFFRCwwUEFBMFA7QUFDMVAsS0FBSyxVQUFVLDBCQUEwQjs7SUFDckMsSUFBSSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxJQUFBLHFDQUFzQixHQUFFLENBQUM7SUFDaEQsSUFBSSxHQUFHLEdBQUcsV0FBVyxNQUFNLElBQUksSUFBSSxFQUFFLENBQUM7SUFDdEMsSUFBSSxJQUErQyxDQUFDO0lBQ3BELElBQUksQ0FBQztRQUNELElBQUksR0FBRyxNQUFNLElBQUEsMkNBQTBCLEVBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ1QsT0FBTyxDQUFDLEtBQUssQ0FBQyxvQ0FBb0MsR0FBRyx5RkFBeUYsTUFBQyxDQUFXLENBQUMsS0FBSyxtQ0FBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3pLLE9BQU87SUFDWCxDQUFDO0lBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNmLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0JBQXNCLEdBQUcscUZBQXFGLENBQUMsQ0FBQztRQUM1SCxPQUFPO0lBQ1gsQ0FBQztJQUNELE9BQU8sQ0FBQyxHQUFHLENBQUMsc0JBQXNCLEdBQUcsUUFBUSxJQUFJLENBQUMsTUFBTSxxRkFBcUYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sSUFBSSxDQUFDLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3pNLEtBQUssSUFBSSxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUN2QyxJQUFJLENBQUM7WUFDRCxNQUFNLGVBQWUsQ0FBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDL0MsQ0FBQztRQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDVCxPQUFPLENBQUMsS0FBSyxDQUFDLHFCQUFxQixPQUFPLElBQUksVUFBVSx3Q0FBd0MsTUFBQyxDQUFXLENBQUMsS0FBSyxtQ0FBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQy9ILENBQUM7SUFDTCxDQUFDO0FBQ0wsQ0FBQztBQUVELHlMQUF5TDtBQUM1SyxRQUFBLDRCQUE0QixHQUFHLElBQUEsY0FBSSxFQUFDLEdBQUcsRUFBRTtJQUNsRCxLQUFLLENBQUMsS0FBSyxJQUFJLEVBQUU7UUFDYixNQUFNLDBCQUEwQixFQUFFLENBQUM7UUFDbkMsTUFBTSxxQkFBcUIsRUFBRSxDQUFDO0lBQ2xDLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUSxFQUFFLEVBQUUsV0FBQyxPQUFBLE9BQU8sQ0FBQyxLQUFLLENBQUMsMERBQTBELE1BQUEsQ0FBQyxDQUFDLEtBQUssbUNBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQSxFQUFBLENBQUMsQ0FBQztJQUNsSCxJQUFBLDBCQUFlLEVBQUMsOEJBQThCLEVBQUUscUJBQXFCLENBQUMsQ0FBQztBQUMzRSxDQUFDLENBQUMsQ0FBQztBQXlCSCxTQUFTLGtCQUFrQixDQUFDLE1BQW1CO0lBQzNDLE9BQU87UUFDSCxNQUFNLEVBQUUsSUFBQSw0QkFBZSxFQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLFVBQVUsQ0FBQztRQUMxRCxPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU87UUFDdkIsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXO1FBQy9CLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSTtRQUNqQixNQUFNLEVBQUUsZUFBZSxDQUFDLE1BQU0sQ0FBQztLQUNsQyxDQUFDO0FBQ04sQ0FBQztBQUVELGtSQUFrUjtBQUMzUSxLQUFLLFVBQVUsZUFBZSxDQUFDLE9BQWUsRUFBRSxVQUFrQjs7SUFDckUsSUFBSSxHQUFHLEdBQUcsR0FBRyxPQUFPLElBQUksVUFBVSxFQUFFLENBQUM7SUFDckMsSUFBSSxhQUFhLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNyQyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDakIsT0FBTyxVQUFVLEdBQUcsbUZBQW1GLENBQUM7SUFDNUcsQ0FBQztJQUNELElBQUksTUFBK0IsQ0FBQztJQUNwQyxJQUFJLENBQUM7UUFDRCxNQUFNLEdBQUcsTUFBTSxhQUFhLENBQUM7SUFDakMsQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDVCxPQUFPLFVBQVUsR0FBRyxtQ0FBbUMsTUFBTSxDQUFDLE1BQUMsQ0FBVyxDQUFDLEtBQUssbUNBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDO0lBQzNHLENBQUM7SUFDRCxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDVixPQUFPLFVBQVUsR0FBRyxnQ0FBZ0MsQ0FBQztJQUN6RCxDQUFDO0lBQ0QsT0FBTyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUN0QyxDQUFDO0FBaEJELDBDQWdCQztBQUVELHNXQUFzVztBQUMvVixLQUFLLFVBQVUsY0FBYyxDQUFDLE9BQWUsRUFBRSxVQUFrQjs7SUFDcEUsSUFBSSxHQUFHLEdBQUcsR0FBRyxPQUFPLElBQUksVUFBVSxFQUFFLENBQUM7SUFDckMsSUFBSSxTQUFTLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqQyxJQUFJLE1BQStCLENBQUM7SUFDcEMsSUFBSSxDQUFDO1FBQ0QsTUFBTSxHQUFHLE1BQU0sZUFBZSxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQztJQUN4RCxDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNULE9BQU8sVUFBVSxHQUFHLG1DQUFtQyxNQUFNLENBQUMsTUFBQyxDQUFXLENBQUMsS0FBSyxtQ0FBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUM7SUFDM0csQ0FBQztJQUNELElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNWLE9BQU8sVUFBVSxHQUFHLHNEQUFzRCxJQUFBLDRCQUFlLEVBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxHQUFHLENBQUM7SUFDdEgsQ0FBQztJQUNELDhMQUE4TDtJQUM5TCxLQUFLLElBQUksQ0FBQyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUMxQixJQUFJLENBQUMsQ0FBQyxLQUFLLFlBQVkscUJBQVMsRUFBRSxDQUFDO1lBQy9CLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN6QixDQUFDO0lBQ0wsQ0FBQztJQUNELElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNiLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLEdBQUcsaURBQWlELENBQUMsQ0FBQztJQUMxRixDQUFDO0lBQ0QsT0FBTyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUN0QyxDQUFDO0FBdEJELHdDQXNCQztBQUVNLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUFlO0lBQ3BELElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUN2QixJQUFJLE9BQU8sR0FBRyxJQUFJLEdBQUcsRUFBa0IsQ0FBQztJQUN4QyxLQUFLLFVBQVUsS0FBSyxDQUFJLElBQVksRUFBRSxHQUFxQjtRQUN2RCxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDdkIsSUFBSSxDQUFDO1lBQ0QsT0FBTyxNQUFNLEdBQUcsRUFBRSxDQUFDO1FBQ3ZCLENBQUM7Z0JBQVMsQ0FBQztZQUNQLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ3ZFLENBQUM7SUFDTCxDQUFDO0lBQ0QsSUFBSSxhQUFhLEdBQUcsY0FBSSxDQUFDLElBQUksQ0FBQyxJQUFBLHFDQUFzQixHQUFFLENBQUMsTUFBTSxFQUFFLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNwRixJQUFJLEtBQWUsQ0FBQztJQUNwQixJQUFJLENBQUM7UUFDRCxLQUFLLEdBQUcsTUFBTSxLQUFLLENBQUMsU0FBUyxFQUFFLEdBQUcsRUFBRSxDQUFDLFlBQUUsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDN0UsQ0FBQztJQUFDLFdBQU0sQ0FBQztRQUNMLE9BQU8sRUFBRSxDQUFDO0lBQ2QsQ0FBQztJQUNELDRJQUE0STtJQUM1SSxLQUFLLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLHVCQUF1QixFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzdFLElBQUksQ0FBQztRQUNELE9BQU8sTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFDLFVBQVUsRUFBQyxFQUFFOztZQUNsRCxJQUFJLEdBQUcsR0FBRyxHQUFHLE9BQU8sSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNyQyxJQUFJLE1BQU0sR0FBRyxJQUFBLDRCQUFlLEVBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBQ2xELElBQUksSUFBSSxHQUFxQixFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxDQUFDO1lBQ25FLElBQUksQ0FBQyxJQUFJLEdBQUcsTUFBTSxLQUFLLENBQUMsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUEsd0JBQVcsRUFBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQVEsRUFBRSxFQUFFOztnQkFDNUUsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLENBQUMsTUFBQSxDQUFDLENBQUMsS0FBSyxtQ0FBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO2dCQUNwRCxPQUFPLFNBQVMsQ0FBQztZQUNyQixDQUFDLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxVQUFVLEdBQUcsbUJBQW1CLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDM0MsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN2QyxJQUFJLGFBQWEsRUFBRSxDQUFDO2dCQUNoQixJQUFJLENBQUM7b0JBQ0QsSUFBSSxNQUFNLEdBQUcsTUFBTSxLQUFLLENBQUMsYUFBYSxFQUFFLEdBQUcsRUFBRSxDQUFDLGFBQWEsQ0FBQyxDQUFDO29CQUM3RCxJQUFJLE1BQU0sRUFBRSxDQUFDO3dCQUNULE9BQU8sRUFBRSxHQUFHLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxlQUFlLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztvQkFDdEUsQ0FBQztnQkFDTCxDQUFDO2dCQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7b0JBQ1QsT0FBTyxFQUFFLEdBQUcsSUFBSSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxNQUFDLENBQVcsQ0FBQyxLQUFLLG1DQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDM0YsQ0FBQztZQUNMLENBQUM7WUFDRCxJQUFJLENBQUM7Z0JBQ0QsTUFBTSxJQUFJLEdBQUcsTUFBTSxLQUFLLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBQSw0QkFBZSxFQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7Z0JBQzNFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztvQkFDUixPQUFPLEVBQUUsR0FBRyxJQUFJLEVBQUUsS0FBSyxFQUFFLG9CQUFvQiwyQkFBWSxHQUFHLEVBQUUsQ0FBQztnQkFDbkUsQ0FBQztnQkFDRCxJQUFJLE1BQU0sR0FBRyxNQUFNLEtBQUssQ0FBQyxjQUFjLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQyxJQUFBLCtCQUFnQixFQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQzdFLE9BQU8sRUFBRSxHQUFHLElBQUksRUFBRSxNQUFNLEVBQUUsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQztZQUN6RCxDQUFDO1lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDVCxPQUFPLEVBQUUsR0FBRyxJQUFJLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxNQUFDLENBQVcsQ0FBQyxLQUFLLG1DQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM3RSxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNSLENBQUM7WUFBUyxDQUFDO1FBQ1Asb0dBQW9HO1FBQ3BHLElBQUksS0FBSyxHQUFHLENBQUMsR0FBRyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxJQUFJLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDM0UsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsT0FBTyxVQUFVLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxLQUFLLFVBQVUsS0FBSyxDQUFDLE1BQU0sYUFBYSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQ3JILENBQUM7QUFDTCxDQUFDO0FBekRELGdEQXlEQztBQVVELFNBQVMsZUFBZTtJQUNwQixPQUFPLEVBQUUsY0FBYyxFQUFFLENBQUMsRUFBRSxhQUFhLEVBQUUsQ0FBQyxFQUFFLGFBQWEsRUFBRSxDQUFDLEVBQUUsWUFBWSxFQUFFLENBQUMsRUFBRSxDQUFDO0FBQ3RGLENBQUM7QUFFRCwySkFBMko7QUFDM0osTUFBTSxVQUFVLEdBQUcsSUFBSSxHQUFHLEVBQTRCLENBQUM7QUFFdkQsU0FBUyxnQkFBZ0IsQ0FBQyxHQUFXLEVBQUUsSUFBNEIsRUFBRSxLQUFhO0lBQzlFLElBQUksS0FBSyxHQUFHLFVBQVUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDaEMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ1QsS0FBSyxHQUFHLGVBQWUsRUFBRSxDQUFDO1FBQzFCLFVBQVUsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQy9CLENBQUM7SUFDRCxJQUFJLElBQUksS0FBSyxVQUFVLEVBQUUsQ0FBQztRQUN0QixLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDdkIsS0FBSyxDQUFDLGFBQWEsSUFBSSxLQUFLLENBQUM7SUFDakMsQ0FBQztTQUFNLENBQUM7UUFDSixLQUFLLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDdEIsS0FBSyxDQUFDLFlBQVksSUFBSSxLQUFLLENBQUM7SUFDaEMsQ0FBQztBQUNMLENBQUM7QUFFRCxTQUFTLG1CQUFtQixDQUFDLEdBQVc7SUFDcEMsT0FBTyxVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLGVBQWUsRUFBRSxDQUFDO0FBQ3BELENBQUM7QUFFRCxrRUFBa0U7QUFDbEUsU0FBZ0Isc0JBQXNCLENBQUMsT0FBZTtJQUNsRCxJQUFJLE1BQU0sR0FBRyxHQUFHLE9BQU8sR0FBRyxDQUFDO0lBQzNCLElBQUksT0FBTyxHQUFHLENBQUMsQ0FBQztJQUNoQixLQUFLLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxVQUFVLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO1FBQ3JDLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQztZQUFFLFNBQVM7UUFDdEMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN2QixPQUFPLEVBQUUsQ0FBQztJQUNkLENBQUM7SUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLG1DQUFtQyxPQUFPLHVCQUF1QixPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQ3hGLE9BQU8sT0FBTyxDQUFDO0FBQ25CLENBQUM7QUFWRCx3REFVQztBQUVELE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFFN0MsOE1BQThNO0FBQzlNLE1BQU0sc0JBQXNCO0lBQ3hCLFlBQW9CLE9BQWUsRUFBVSxVQUFrQixFQUFVLFlBQTBCO1FBQS9FLFlBQU8sR0FBUCxPQUFPLENBQVE7UUFBVSxlQUFVLEdBQVYsVUFBVSxDQUFRO1FBQVUsaUJBQVksR0FBWixZQUFZLENBQWM7SUFBSSxDQUFDO0lBRWhHLFNBQVM7UUFDYixPQUFPLGVBQWUsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQzdFLENBQUM7SUFFTSxZQUFZO1FBQ2YsT0FBTyx1QkFBdUIsSUFBSSxDQUFDLE9BQU8sV0FBVyxJQUFJLENBQUMsVUFBVSxVQUFVLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLElBQUksc0JBQVUsQ0FBQyxFQUFFLENBQUM7SUFDMUksQ0FBQztJQUNNLEtBQUssQ0FBQyxHQUFHLENBQUMsUUFBZ0IsRUFBRSxNQUFrQjtRQUNqRCxJQUFJLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQy9DLE9BQU8sTUFBTSxJQUFJLE1BQU0sQ0FBQyxJQUFJLElBQUksU0FBUyxDQUFDO0lBQzlDLENBQUM7SUFDTSxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQWdCLEVBQUUsTUFBa0I7UUFDbEQsSUFBSSxRQUFRLEtBQUssMkJBQVksRUFBRSxDQUFDO1lBQzVCLE9BQU8sTUFBTSxJQUFBLGlDQUFvQixFQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3JFLENBQUM7UUFDRCxJQUFJLE1BQU0sYUFBTixNQUFNLHVCQUFOLE1BQU0sQ0FBRSxRQUFRLEVBQUUsQ0FBQztZQUNuQixPQUFPLE1BQU0sa0JBQWtCLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxDQUFDO1FBQ3pKLENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEdBQUcsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUNwRixDQUFDO0lBQ00sS0FBSyxDQUFDLEdBQUcsQ0FBQyxRQUFnQixFQUFFLElBQVksRUFBRSxNQUFrQjtRQUMvRCxJQUFBLGtDQUFtQixHQUFFLENBQUM7UUFDdEIsSUFBSSxRQUFRLEtBQUssMkJBQVksRUFBRSxDQUFDO1lBQzVCLE1BQU0sdUJBQXVCLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQztZQUMzRSxPQUFPLFFBQVEsQ0FBQztRQUNwQixDQUFDO1FBQ0QsTUFBTSxDQUFDLE1BQU0sSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUcsTUFBTSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUM5RSxPQUFPLFFBQVEsQ0FBQztJQUNwQixDQUFDO0lBQ00sS0FBSyxDQUFDLEdBQUcsQ0FBQyxRQUFnQixFQUFFLE1BQWtCO1FBQ2pELElBQUEsa0NBQW1CLEdBQUUsQ0FBQztRQUN0QixNQUFNLENBQUMsTUFBTSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDLENBQUM7SUFDNUUsQ0FBQztJQUNNLEtBQUssQ0FBQyxZQUFZLENBQUMsTUFBMkY7UUFDakgsSUFBQSxrQ0FBbUIsR0FBRSxDQUFDO1FBQ3RCLElBQUksS0FBSyxHQUFHLENBQUMsTUFBTSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUM7UUFDM0MsSUFBSSxFQUFFLEdBQUcsTUFBTSxLQUFLLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBRSxZQUFZLEVBQUUsTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUM7UUFDaEcsSUFBSSxDQUFDO1lBQ0QsT0FBTyxJQUFJLEVBQUUsQ0FBQztnQkFDVixJQUFJLElBQUksR0FBRyxNQUFNLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDdEMsSUFBSSxDQUFDLElBQUk7b0JBQUUsTUFBTTtnQkFDakIsS0FBSyxJQUFJLE1BQU0sR0FBRyxDQUFDLEVBQUUsTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsTUFBTSxJQUFJLG9CQUFvQixFQUFFLENBQUM7b0JBQ3hFLE1BQU0sS0FBSyxDQUFDLGlCQUFpQixDQUFDLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxNQUFNLEdBQUcsb0JBQW9CLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ3RHLENBQUM7WUFDTCxDQUFDO1lBQ0QsTUFBTSxLQUFLLENBQUMsaUJBQWlCLENBQUMsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsWUFBWSxFQUFFLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO1FBQ2hHLENBQUM7UUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ1QsTUFBTSxLQUFLLENBQUMsaUJBQWlCLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ3RDLE1BQU0sQ0FBQyxDQUFDO1FBQ1osQ0FBQztJQUNMLENBQUM7SUFDTSxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQWdCLEVBQUUsTUFBc0I7UUFDekQsSUFBSSxRQUFRLEtBQUssMkJBQVksRUFBRSxDQUFDO1lBQzVCLElBQUksTUFBTSxHQUFHLE1BQU0sSUFBQSxpQ0FBb0IsRUFBQyxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUN2RSxPQUFPLE1BQU0sSUFBSSxFQUFFLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxFQUFFLElBQUksU0FBUyxDQUFDO1FBQ3JGLENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEdBQUcsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUN2RixDQUFDO0lBQ00sS0FBSyxDQUFDLFFBQVEsQ0FBQyxNQUFjLEVBQUUsTUFBbUI7UUFDckQsT0FBTyxNQUFNLENBQUMsTUFBTSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEVBQUUsTUFBTSxFQUFFLEdBQUcsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUNoRixDQUFDO0lBQ00sS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFjLEVBQUUsTUFBbUI7UUFDakQsT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbEUsQ0FBQztJQUNNLEtBQUssQ0FBQyxNQUFNLENBQUMsUUFBZ0I7UUFDaEMsSUFBSSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxJQUFBLHFDQUFzQixHQUFFLENBQUM7UUFDaEQsT0FBTyxJQUFBLDJCQUFZLEVBQUMsV0FBVyxNQUFNLElBQUksSUFBSSxTQUFTLGtCQUFrQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUMvSSxDQUFDO0lBQ00sS0FBSyxDQUFDLFNBQVM7UUFDbEIsT0FBTyxlQUFlLENBQUMsTUFBTSxhQUFhLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUMvRSxDQUFDO0lBQ00sS0FBSyxDQUFDLGNBQWM7UUFDdkIsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUNNLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxNQUEwQjtRQUNwRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN6RSxDQUFDO0lBQ00sS0FBSyxDQUFDLGFBQWE7UUFDdEIsT0FBTyxNQUFNLGdCQUFnQixDQUFDLE1BQU0sYUFBYSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFDdEYsQ0FBQztDQUNKO0FBRUQsTUFBTSxhQUFhLEdBQUcsSUFBSSxHQUFHLEVBQXFCLENBQUM7QUFDbkQsU0FBZ0IsZ0JBQWdCLENBQUMsT0FBZSxFQUFFLFVBQWtCLEVBQUUsWUFBMEI7SUFDNUYsSUFBSSxHQUFHLEdBQUcsR0FBRyxPQUFPLElBQUksVUFBVSxJQUFJLGVBQWUsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO0lBQ3RFLElBQUksUUFBUSxHQUFHLGFBQWEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdEMsSUFBSSxRQUFRO1FBQUUsT0FBTyxRQUFRLENBQUM7SUFDOUIsSUFBSSxRQUFRLEdBQUcsSUFBSSxzQkFBc0IsQ0FBQyxPQUFPLEVBQUUsVUFBVSxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQzdFLGFBQWEsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ2pDLE9BQU8sUUFBUSxDQUFDO0FBQ3BCLENBQUM7QUFQRCw0Q0FPQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgeyBsYXp5IH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvY2FjaGluZ1wiO1xuaW1wb3J0IHsgc29ydCB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL21pc2NcIjtcbmltcG9ydCB7IHJ1bkluZmluaXRlUG9sbCB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL2JhdGNoaW5nXCI7XG5pbXBvcnQgeyBBcmNoaXZlc0Rpc2sgfSBmcm9tIFwiLi4vQXJjaGl2ZXNEaXNrXCI7XG5pbXBvcnQgeyBCbG9iU3RvcmUsIFJhd0Rpc2tTdG9yZSwgSUJ1Y2tldFN0b3JlLCBERUZBVUxUX0ZBU1RfV1JJVEVfREVMQVksIFdJTkRPV19FTkRfRkxVU0hfTUFSR0lOIH0gZnJvbSBcIi4vYmxvYlN0b3JlXCI7XG5pbXBvcnQge1xuICAgIFJlbW90ZUNvbmZpZywgSG9zdGVkQ29uZmlnLCBTb3VyY2VDb25maWcsIElBcmNoaXZlcywgQXJjaGl2ZXNTb3VyY2UsIEFyY2hpdmVzQ29uZmlnLCBBcmNoaXZlc1N5bmNTdGF0dXMsXG4gICAgQXJjaGl2ZUZpbGVJbmZvLCBDaGFuZ2VzQWZ0ZXJDb25maWcsIERlbENvbmZpZywgRmluZENvbmZpZywgR2V0Q29uZmlnLCBHZXRJbmZvQ29uZmlnLCBTZXRDb25maWcsIFN5bmNBY3Rpdml0eSwgRlVMTF9ST1VURSxcbn0gZnJvbSBcIi4uL0lBcmNoaXZlc1wiO1xuaW1wb3J0IHsgUk9VVElOR19GSUxFLCBwYXJzZVJvdXRpbmdEYXRhLCBzZXJpYWxpemVSZW1vdGVDb25maWcsIHBhcnNlSG9zdGVkVXJsLCByZXBsYWNlSG9zdGVkVXJsUG9ydCwgYnVpbGRGaWxlVXJsLCBnZXRDb25maWdWZXJzaW9uLCByb3V0ZUludGVyc2VjdGlvbiwgbm9ybWFsaXplU291cmNlIH0gZnJvbSBcIi4vcmVtb3RlQ29uZmlnXCI7XG5pbXBvcnQgeyBpbmplY3RJbnRlcm1lZGlhdGVTb3VyY2UsIGV4cGlyZUludGVybWVkaWF0ZVNvdXJjZXMsIGdldEludGVybWVkaWF0ZVNvdXJjZXMsIG5leHRJbnRlcm1lZGlhdGVWZXJzaW9uLCBJTlRFUk1FRElBVEVfRVhQSVJFX0dSQUNFIH0gZnJvbSBcIi4vaW50ZXJtZWRpYXRlU291cmNlc1wiO1xuaW1wb3J0IHsgZ2V0VGFrZW92ZXJJbnRlcm1lZGlhdGUgfSBmcm9tIFwiLi9kZXBsb3lUYWtlb3ZlclwiO1xuaW1wb3J0IHsgY3JlYXRlQXBpQXJjaGl2ZXMsIGxpc3RTZXJ2ZXJBY3RpdmVCdWNrZXRLZXlzIH0gZnJvbSBcIi4vY3JlYXRlQXJjaGl2ZXNcIjtcbmltcG9ydCB7IGJyb2FkY2FzdFJvdXRpbmdDaGFuZ2VkIH0gZnJvbSBcIi4vc3RvcmFnZUNvbnRyb2xsZXJcIjtcbmltcG9ydCB7IGdldFN0b3JhZ2VTZXJ2ZXJDb25maWcsIGFzc2VydFdyaXRlc0FsbG93ZWQgfSBmcm9tIFwiLi9zZXJ2ZXJDb25maWdcIjtcbmltcG9ydCB7IGdldEJ1Y2tldEZvbGRlciwgcmVhZFJvdXRpbmdGaWxlLCByZWFkUm91dGluZ0Zyb21EaXNrLCBnZXRSb3V0aW5nRmlsZVJlc3VsdCwgZ2V0RGlza0luZm8sIEJ1Y2tldERpc2tJbmZvIH0gZnJvbSBcIi4vYnVja2V0RGlza1wiO1xuaW1wb3J0IHsgY29tcHV0ZVN0b3JlUGxhbiwgZmluZFNlbGZJbmRleGVzLCBTdG9yZVBsYW4sIFN0b3JlUGxhblN0b3JlLCBTZWxmU3VtbWFyeSB9IGZyb20gXCIuL3N0b3JlUGxhblwiO1xuXG4vLyBUaGUgc3RvcmFnZSBzZXJ2ZXIncyBidWNrZXQgbGlmZWN5Y2xlOiB0aGUgbWFwIG9mIGxvYWRlZCBidWNrZXRzIChlYWNoID0gaXRzIHJvdXRpbmcgY29uZmlnICsgb25lIEJsb2JTdG9yZSBwZXIgcm91dGUpLCBrZWVwaW5nIHRoZW0gY3VycmVudCAocm91dGluZyByZWxvYWRzLCB3aW5kb3ctYm91bmRhcnkgcmVidWlsZHMsIGJvdW5kYXJ5IHNjYW5zKSwgd3JpdGluZy9wcm9wYWdhdGluZyByb3V0aW5nIGNvbmZpZ3MsIGRlcGxveS1zd2l0Y2hvdmVyIG1haW50ZW5hbmNlLCBhbmQgdGhlIHNlcnZlci1sZXZlbCBidWNrZXQgbGlzdGluZ3MuIFN0b3JlIHNlbGVjdGlvbiAoc291cmNlQ29uZmlnIC0+IHN0b3JlKSBsaXZlcyBoZXJlIHRvbywgYXMgZmluZEJ1Y2tldFN0b3JlLlxuXG5leHBvcnQgdHlwZSBMb2FkZWRTdG9yZSA9IHtcbiAgICAvLyBKU09OIG9mIHRoZSByb3V0ZSAoRlVMTF9ST1VURSB3aGVuIGFic2VudCkgLSB0aGUgT05FIHJvdXRlIHRoaXMgc3RvcmUgc2VydmVzXG4gICAgcm91dGVLZXk6IHN0cmluZztcbiAgICByb3V0ZT86IFtudW1iZXIsIG51bWJlcl07XG4gICAgLy8gVGhlIGV4YWN0IHNlbGYgZW50cmllcyB0aGlzIHN0b3JlIHNlcnZlcyAoc2FtZSByb3V0ZSwgZGlmZmVyZW50IHZhbGlkIHdpbmRvd3MpLiBFbXB0eSB3aGVuIHdlIGFyZSBub3QgaW4gdGhlIGNvbmZpZyBidXQgc3RpbGwgc2VydmUgb3VyIGRpc2sgZGF0YS5cbiAgICBlbnRyaWVzOiBIb3N0ZWRDb25maWdbXTtcbiAgICBmb2xkZXI6IHN0cmluZztcbiAgICBzdG9yZTogSUJ1Y2tldFN0b3JlO1xufTtcblxuLy8gQSBidWNrZXQgbG9hZGVkIG9uIHRoaXMgc2VydmVyOiBpdHMgcm91dGluZyBjb25maWcgYW5kIGl0cyBwZXItcm91dGUgc3RvcmVzLiBQdXJlIGRhdGEgLSB0aGUgc3RvcmVzIHRoZW1zZWx2ZXMgZG8gdGhlIHdvcmsuXG5leHBvcnQgdHlwZSBCdWNrZXRTdGF0ZSA9IHtcbiAgICBhY2NvdW50OiBzdHJpbmc7XG4gICAgYnVja2V0TmFtZTogc3RyaW5nO1xuICAgIHJvdXRpbmc6IFJlbW90ZUNvbmZpZztcbiAgICByb3V0aW5nSlNPTjogc3RyaW5nO1xuICAgIHNlbGZFbnRyaWVzOiBIb3N0ZWRDb25maWdbXTtcbiAgICBzZWxmOiBTZWxmU3VtbWFyeSB8IHVuZGVmaW5lZDtcbiAgICBzdG9yZXM6IExvYWRlZFN0b3JlW107XG4gICAgc3RydWN0dXJlS2V5OiBzdHJpbmc7XG59O1xuXG4vKiogSlNPTiB3aXRoIHNvcnRlZCBvYmplY3Qga2V5cyBhbmQgdW5kZWZpbmVkLXZhbHVlZCBrZXlzIGRyb3BwZWQsIHNvIHR3byBjb25maWdzIHRoYXQgbWVhbiB0aGUgc2FtZSB0aGluZyBjb21wYXJlIGVxdWFsIHJlZ2FyZGxlc3Mgb2Yga2V5IG9yZGVyIG9yIHdoaWNoIHNpZGUgc2VyaWFsaXplZCB0aGVtLiAqL1xuZnVuY3Rpb24gc3RhYmxlU3RyaW5naWZ5KHZhbHVlOiB1bmtub3duKTogc3RyaW5nIHtcbiAgICBpZiAoIXZhbHVlIHx8IHR5cGVvZiB2YWx1ZSAhPT0gXCJvYmplY3RcIikgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIGBbJHt2YWx1ZS5tYXAoeCA9PiBzdGFibGVTdHJpbmdpZnkoeCkpLmpvaW4oXCIsXCIpfV1gO1xuICAgIH1cbiAgICBsZXQgZW50cmllcyA9IE9iamVjdC5lbnRyaWVzKHZhbHVlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KS5maWx0ZXIoeCA9PiB4WzFdICE9PSB1bmRlZmluZWQpO1xuICAgIHNvcnQoZW50cmllcywgeCA9PiB4WzBdKTtcbiAgICByZXR1cm4gYHske2VudHJpZXMubWFwKChba2V5LCBjaGlsZF0pID0+IGAke0pTT04uc3RyaW5naWZ5KGtleSl9OiR7c3RhYmxlU3RyaW5naWZ5KGNoaWxkKX1gKS5qb2luKFwiLFwiKX19YDtcbn1cblxuLyoqIFRoZSBsb2FkZWQgYnVja2V0LCBsb2FkaW5nIGl0ICh3aGljaCBpbnN0YW50aWF0ZXMgaXRzIHN0b3JlcyBhbmQgc3RhcnRzIHRoZWlyIHN5bmNocm9uaXphdGlvbikgaWYgbmVlZGVkLiBBIGJ1Y2tldCB0aGF0IGRvZXMgbm90IGV4aXN0IG9uIHRoaXMgc2VydmVyIHRocm93cyAtIGNhbGxlcnMgbmV2ZXIgc2VlIHVuZGVmaW5lZCBidWNrZXRzLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlcXVpcmVCdWNrZXQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPEJ1Y2tldFN0YXRlPiB7XG4gICAgbGV0IGJ1Y2tldCA9IGF3YWl0IGdldExvYWRlZEJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBpZiAoIWJ1Y2tldCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEJ1Y2tldCAke2FjY291bnR9LyR7YnVja2V0TmFtZX0gZG9lcyBub3QgZXhpc3Qgb24gdGhpcyBzZXJ2ZXIuIFdyaXRlIGl0cyByb3V0aW5nIGNvbmZpZyB0byAke0pTT04uc3RyaW5naWZ5KFJPVVRJTkdfRklMRSl9IHRvIGNyZWF0ZSBpdC5gKTtcbiAgICB9XG4gICAgcmV0dXJuIGJ1Y2tldDtcbn1cblxuLyoqIFRoZSBzdGFibGUgaWRlbnRpdHkgb2YgYSBzb3VyY2UgY29uZmlnIGZvciBtYXRjaGluZzogZXZlcnl0aGluZyBFWENFUFQgdGhlIHZhbGlkIHdpbmRvdywgYW5kIHdpdGggYW4gaW50ZXJtZWRpYXRlIHJlc29sdmVkIGJhY2sgdG8gdGhlIHNvdXJjZSBpdCB3YXMgc3BsaXQgb3V0IG9mLiBUaGUgd2luZG93IGRyaWZ0cyAoYSBzd2l0Y2hvdmVyIHNwbGl0cyBvbmUgd2luZG93IGluIHR3byBhcm91bmQgYW4gaW50ZXJtZWRpYXRlLCB0aGVuIHJlam9pbnMgaXQpLCBzbyBhIGNhbGxlciBhbmQgdGhpcyBzZXJ2ZXIgcm91dGluZWx5IGRpc2FncmVlIG9uIGl0IC0gbWF0Y2hpbmcgb24gaXQgd291bGQgd3JvbmdseSByZWplY3QgdGhlIHJlcXVlc3QuIEFuIGludGVybWVkaWF0ZSBpcyBhIHRyYW5zaWVudCBhbHQtcG9ydCB2aWV3IG9mIGFub3RoZXIgc291cmNlLCBzbyBpdCBtdXN0IHJlc29sdmUgdG8gVEhBVCBzb3VyY2UgKGNvbmZpZy5pbnRlcm1lZGlhdGUgaG9sZHMgaXRzIHVybCArIHRoZSBpbnRlcm1lZGlhdGUgZmxhZyBpcyBkcm9wcGVkKSwgb3IgYSByZXF1ZXN0IG5hbWluZyB0aGUgaW50ZXJtZWRpYXRlIHdvdWxkIGZhaWwgdG8gbWF0Y2ggb25jZSB0aGUgaW50ZXJtZWRpYXRlIGhhcyByZWpvaW5lZCBhbmQgaXRzIGVudHJ5IGlzIGdvbmUuIFRoZSByb3V0ZSBzdGF5cyBpbiB0aGUgaWRlbnRpdHkgKGl0IHNlbGVjdHMgdGhlIHN0b3JlL2ZvbGRlcikuICovXG5mdW5jdGlvbiBzb3VyY2VNYXRjaEtleShjb25maWc6IFNvdXJjZUNvbmZpZyk6IHN0cmluZyB7XG4gICAgbGV0IHVybCA9IGNvbmZpZy5pbnRlcm1lZGlhdGUgfHwgY29uZmlnLnVybDtcbiAgICByZXR1cm4gc3RhYmxlU3RyaW5naWZ5KHsgLi4uY29uZmlnLCB1cmwsIGludGVybWVkaWF0ZTogdW5kZWZpbmVkLCB2YWxpZFdpbmRvdzogdW5kZWZpbmVkIH0pO1xufVxuXG4vKiogVGhlIHN0b3JlIHNlcnZpbmcgYSByZXF1ZXN0OiB0aGUgY29uZmlnIGVudHJ5IHRoZSBDTElFTlQgc2VsZWN0ZWQsIG1hdGNoZWQgYWdhaW5zdCB0aGUgYnVja2V0J3Mgb3duIGVudHJpZXMgYnkgaWRlbnRpdHkgRVhDTFVESU5HIHRoZSB2YWxpZCB3aW5kb3cgKHNlZSBzb3VyY2VNYXRjaEtleSkuIFRoZSBzZWxlY3Rpb24gbmV2ZXIgdmFsaWRhdGVzIC0gdGhlIHN0b3JlJ3Mgb3duIHdpbmRvdy9yb3V0ZSBjaGVja3MgdGhyb3cgaWYgdGhlIGNhbGxlciBpcyBzdGFsZSAtIHNvIGhvbm9yaW5nIGEgd2luZG93IG1pc21hdGNoIGhlcmUgaXMgZXhhY3RseSByaWdodC4gVGhyb3dzIHdoZW4gbm90aGluZyBtYXRjaGVzLCBsaXN0aW5nIHdoYXQgaXMgYXZhaWxhYmxlLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZpbmRCdWNrZXRTdG9yZShhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgc291cmNlQ29uZmlnOiBTb3VyY2VDb25maWcgfCB1bmRlZmluZWQpOiBQcm9taXNlPExvYWRlZFN0b3JlPiB7XG4gICAgbGV0IGJ1Y2tldCA9IGF3YWl0IHJlcXVpcmVCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgaWYgKCFzb3VyY2VDb25maWcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyByZW1vdGUgc291cmNlIGNvbmZpZ3VyYXRpb24gd2FzIHByb3ZpZGVkIGZvciBidWNrZXQgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9OiBldmVyeSByZXF1ZXN0IG11c3Qgc2F5IHdoaWNoIGNvbmZpZ3VyZWQgc291cmNlIGl0IHNlbGVjdGVkLiBBdmFpbGFibGU6ICR7SlNPTi5zdHJpbmdpZnkoYnVja2V0LnNlbGZFbnRyaWVzKX1gKTtcbiAgICB9XG4gICAgbGV0IHdhbnRlZCA9IHNvdXJjZU1hdGNoS2V5KHNvdXJjZUNvbmZpZyk7XG4gICAgZm9yIChsZXQgcyBvZiBidWNrZXQuc3RvcmVzKSB7XG4gICAgICAgIGlmIChzLmVudHJpZXMuc29tZShlID0+IHNvdXJjZU1hdGNoS2V5KGUpID09PSB3YW50ZWQpKSByZXR1cm4gcztcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKGBObyBzb3VyY2Ugb24gdGhpcyBzZXJ2ZXIgbWF0Y2hlcyB0aGUgcmVxdWVzdGVkIHJlbW90ZSBjb25maWd1cmF0aW9uIGZvciBidWNrZXQgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9LiBSZXF1ZXN0ZWQ6ICR7SlNPTi5zdHJpbmdpZnkoc291cmNlQ29uZmlnKX0uIEF2YWlsYWJsZTogJHtKU09OLnN0cmluZ2lmeShidWNrZXQuc2VsZkVudHJpZXMpfWApO1xufVxuXG4vKiogSW50ZXJuYWwgKHN0b3JlLXRvLXN0b3JlKSByZWFkcyBza2lwIHN0b3JlIHNlbGVjdGlvbiBlbnRpcmVseTogdGhlIGNhbGxlciBpcyBhbm90aGVyIHN0b3JlIHdob3NlIGluZGV4IHNheXMgdGhpcyBNQUNISU5FIGhvbGRzIHRoZSBieXRlcyAtIHRoZSBwZXJzaXN0ZWQgaG9sZGVyIGlkZW50aXR5IGlzIGp1c3QgYSBVUkwsIHdoaWNoIGNhbm5vdCBuYW1lIGEgc3RvcmUuIFdoaWNoZXZlciBzdG9yZSdzIGZvbGRlciBoYXMgdGhlIG5ld2VzdCBjb3B5IGFuc3dlcnMuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZEJ1Y2tldEludGVybmFsKGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nLCBjb25maWc6IHsgcGF0aDogc3RyaW5nOyByYW5nZT86IHsgc3RhcnQ6IG51bWJlcjsgZW5kOiBudW1iZXIgfTsgaW5jbHVkZVRvbWJzdG9uZXM/OiBib29sZWFuIH0pOiBQcm9taXNlPHsgZGF0YTogQnVmZmVyOyB3cml0ZVRpbWU6IG51bWJlcjsgc2l6ZTogbnVtYmVyIH0gfCB1bmRlZmluZWQ+IHtcbiAgICBsZXQgYnVja2V0ID0gYXdhaXQgcmVxdWlyZUJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBsZXQgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKGJ1Y2tldC5zdG9yZXMubWFwKHMgPT4gcy5zdG9yZS5nZXQyKHsgcGF0aDogY29uZmlnLnBhdGgsIHJhbmdlOiBjb25maWcucmFuZ2UsIGluY2x1ZGVUb21ic3RvbmVzOiBjb25maWcuaW5jbHVkZVRvbWJzdG9uZXMsIGludGVybmFsOiB0cnVlIH0pKSk7XG4gICAgbGV0IGJlc3Q6IHsgZGF0YTogQnVmZmVyOyB3cml0ZVRpbWU6IG51bWJlcjsgc2l6ZTogbnVtYmVyIH0gfCB1bmRlZmluZWQ7XG4gICAgZm9yIChsZXQgcmVzdWx0IG9mIHJlc3VsdHMpIHtcbiAgICAgICAgaWYgKHJlc3VsdCAmJiAoIWJlc3QgfHwgcmVzdWx0LndyaXRlVGltZSA+IGJlc3Qud3JpdGVUaW1lKSkge1xuICAgICAgICAgICAgYmVzdCA9IHJlc3VsdDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYmVzdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEJ1Y2tldENvbmZpZyhidWNrZXQ6IEJ1Y2tldFN0YXRlKTogQXJjaGl2ZXNDb25maWcge1xuICAgIGxldCBpbmRleCA9IHsgZmlsZUNvdW50OiAwLCBieXRlQ291bnQ6IDAgfTtcbiAgICBsZXQgaW5kZXhTb3VyY2VzOiB7IGRlYnVnTmFtZTogc3RyaW5nOyBmaWxlQ291bnQ6IG51bWJlcjsgYnl0ZUNvdW50OiBudW1iZXIgfVtdID0gW107XG4gICAgbGV0IHN5bmNpbmc6IFN5bmNBY3Rpdml0eVtdID0gW107XG4gICAgbGV0IHJlYWRlckRpc2tMaW1pdDogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICAgIGZvciAobGV0IHMgb2YgYnVja2V0LnN0b3Jlcykge1xuICAgICAgICBsZXQgcHJvZ3Jlc3MgPSBzLnN0b3JlLmdldFN5bmNQcm9ncmVzcz8uKCk7XG4gICAgICAgIGlmICghcHJvZ3Jlc3MpIGNvbnRpbnVlO1xuICAgICAgICBpbmRleC5maWxlQ291bnQgKz0gcHJvZ3Jlc3MuaW5kZXguZmlsZUNvdW50O1xuICAgICAgICBpbmRleC5ieXRlQ291bnQgKz0gcHJvZ3Jlc3MuaW5kZXguYnl0ZUNvdW50O1xuICAgICAgICBpbmRleFNvdXJjZXMucHVzaCguLi5wcm9ncmVzcy5zb3VyY2VzKTtcbiAgICAgICAgc3luY2luZy5wdXNoKC4uLnByb2dyZXNzLnN5bmNpbmcpO1xuICAgICAgICByZWFkZXJEaXNrTGltaXQgPSByZWFkZXJEaXNrTGltaXQgfHwgcHJvZ3Jlc3MucmVhZGVyRGlza0xpbWl0O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICAvLyBOYXRpdmUgY2hhbmdlLWZlZWQgc3VwcG9ydCA9IHRoZSBzdG9yZXMga2VlcCBhbiBpbmRleCAocmF3RGlzayBidWNrZXRzIGVtdWxhdGUgZ2V0Q2hhbmdlc0FmdGVyMiB3aXRoIGEgZnVsbCBsaXN0aW5nKSAtIGNsaWVudHMgdXNlIHRoaXMgdG8gcGljayB0aGVpciBzY2FuIGNhZGVuY2VcbiAgICAgICAgc3VwcG9ydHNDaGFuZ2VzQWZ0ZXI6IGJ1Y2tldC5zdG9yZXMuc29tZShzID0+IHMuc3RvcmUgaW5zdGFuY2VvZiBCbG9iU3RvcmUpLFxuICAgICAgICByZW1vdGVDb25maWc6IGJ1Y2tldC5yb3V0aW5nLFxuICAgICAgICBpbmRleCxcbiAgICAgICAgaW5kZXhTb3VyY2VzLFxuICAgICAgICByZWFkZXJEaXNrTGltaXQsXG4gICAgICAgIHN5bmNpbmcsXG4gICAgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJ1Y2tldFN5bmNTdGF0dXMoYnVja2V0OiBCdWNrZXRTdGF0ZSk6IFByb21pc2U8QXJjaGl2ZXNTeW5jU3RhdHVzPiB7XG4gICAgbGV0IHN1cHBvcnRlZCA9IGJ1Y2tldC5zdG9yZXMuZmlsdGVyKHMgPT4gcy5zdG9yZS5nZXRTeW5jU3RhdHVzKTtcbiAgICBpZiAoIXN1cHBvcnRlZC5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBCdWNrZXQgJHtidWNrZXQuYWNjb3VudH0vJHtidWNrZXQuYnVja2V0TmFtZX0gZG9lcyBub3Qgc3VwcG9ydCBnZXRTeW5jU3RhdHVzIChyYXdEaXNrIGJ1Y2tldHMgaGF2ZSBubyBzeW5jaHJvbml6YXRpb24pYCk7XG4gICAgfVxuICAgIGxldCBzdGF0dXNlcyA9IGF3YWl0IFByb21pc2UuYWxsKHN1cHBvcnRlZC5tYXAoYXN5bmMgcyA9PiB7XG4gICAgICAgIGxldCBnZXRTeW5jU3RhdHVzID0gcy5zdG9yZS5nZXRTeW5jU3RhdHVzO1xuICAgICAgICBpZiAoIWdldFN5bmNTdGF0dXMpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgZ2V0U3luY1N0YXR1cyBkaXNhcHBlYXJlZCBmcm9tIGEgc3RvcmUgZm9yICR7YnVja2V0LmFjY291bnR9LyR7YnVja2V0LmJ1Y2tldE5hbWV9YCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGF3YWl0IGdldFN5bmNTdGF0dXMuY2FsbChzLnN0b3JlKTtcbiAgICB9KSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgYWxsU2NhbnNDb21wbGV0ZTogc3RhdHVzZXMuZXZlcnkoeCA9PiB4LmFsbFNjYW5zQ29tcGxldGUpLFxuICAgICAgICBpbmRleFNpemU6IHN0YXR1c2VzLnJlZHVjZSgoc3VtLCB4KSA9PiBzdW0gKyB4LmluZGV4U2l6ZSwgMCksXG4gICAgICAgIHNvdXJjZXM6IHN0YXR1c2VzLmZsYXRNYXAoeCA9PiB4LnNvdXJjZXMpLFxuICAgIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBidWNrZXRJbmRleFRvdGFscyhidWNrZXQ6IEJ1Y2tldFN0YXRlKTogUHJvbWlzZTx7IGZpbGVDb3VudDogbnVtYmVyOyBieXRlQ291bnQ6IG51bWJlcjsgc291cmNlczogeyBkZWJ1Z05hbWU6IHN0cmluZzsgZmlsZUNvdW50OiBudW1iZXI7IGJ5dGVDb3VudDogbnVtYmVyIH1bXSB9IHwgdW5kZWZpbmVkPiB7XG4gICAgbGV0IHN1cHBvcnRlZCA9IGJ1Y2tldC5zdG9yZXMuZmlsdGVyKHMgPT4gcy5zdG9yZS5jb21wdXRlSW5kZXhUb3RhbHMpO1xuICAgIGlmICghc3VwcG9ydGVkLmxlbmd0aCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBsZXQgdG90YWxzID0gYXdhaXQgUHJvbWlzZS5hbGwoc3VwcG9ydGVkLm1hcChhc3luYyBzID0+IHtcbiAgICAgICAgbGV0IGNvbXB1dGVJbmRleFRvdGFscyA9IHMuc3RvcmUuY29tcHV0ZUluZGV4VG90YWxzO1xuICAgICAgICBpZiAoIWNvbXB1dGVJbmRleFRvdGFscykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjb21wdXRlSW5kZXhUb3RhbHMgZGlzYXBwZWFyZWQgZnJvbSBhIHN0b3JlIGZvciAke2J1Y2tldC5hY2NvdW50fS8ke2J1Y2tldC5idWNrZXROYW1lfWApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhd2FpdCBjb21wdXRlSW5kZXhUb3RhbHMuY2FsbChzLnN0b3JlKTtcbiAgICB9KSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZmlsZUNvdW50OiB0b3RhbHMucmVkdWNlKChzdW0sIHgpID0+IHN1bSArIHguZmlsZUNvdW50LCAwKSxcbiAgICAgICAgYnl0ZUNvdW50OiB0b3RhbHMucmVkdWNlKChzdW0sIHgpID0+IHN1bSArIHguYnl0ZUNvdW50LCAwKSxcbiAgICAgICAgc291cmNlczogdG90YWxzLmZsYXRNYXAoeCA9PiB4LnNvdXJjZXMpLFxuICAgIH07XG59XG5cbmNvbnN0IGJ1Y2tldHMgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZTxCdWNrZXRTdGF0ZSB8IHVuZGVmaW5lZD4+KCk7XG5cbmNvbnN0IE1BWF9SRUJVSUxEX1RJTUVSX0RFTEFZID0gMiAqKiAzMSAtIDE7XG5jb25zdCBSRUJVSUxEX0JPVU5EQVJZX0JVRkZFUiA9IDEwMDA7XG5cbmZ1bmN0aW9uIHNjaGVkdWxlV2luZG93Qm91bmRhcnlSZWJ1aWxkKGxvYWRlZDogQnVja2V0U3RhdGUpOiB2b2lkIHtcbiAgICBsZXQgbm93ID0gRGF0ZS5ub3coKTtcbiAgICBsZXQgYm91bmRhcmllcyA9IGxvYWRlZC5zZWxmRW50cmllcy5mbGF0TWFwKHggPT4geC52YWxpZFdpbmRvdykuZmlsdGVyKHQgPT4gdCA+IG5vdyk7XG4gICAgaWYgKCFib3VuZGFyaWVzLmxlbmd0aCkgcmV0dXJuO1xuICAgIGxldCBuZXh0Qm91bmRhcnkgPSBNYXRoLm1pbiguLi5ib3VuZGFyaWVzKTtcbiAgICBsZXQga2V5ID0gYCR7bG9hZGVkLmFjY291bnR9LyR7bG9hZGVkLmJ1Y2tldE5hbWV9YDtcbiAgICBsZXQgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgdm9pZCAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgbGV0IGN1cnJlbnQgPSBhd2FpdCBidWNrZXRzLmdldChrZXkpO1xuICAgICAgICAgICAgaWYgKGN1cnJlbnQgIT09IGxvYWRlZCkgcmV0dXJuO1xuICAgICAgICAgICAgaWYgKERhdGUubm93KCkgPCBuZXh0Qm91bmRhcnkpIHtcbiAgICAgICAgICAgICAgICBzY2hlZHVsZVdpbmRvd0JvdW5kYXJ5UmVidWlsZChsb2FkZWQpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGF3YWl0IHNjaGVkdWxlUm91dGluZ1JlbG9hZChsb2FkZWQuYWNjb3VudCwgbG9hZGVkLmJ1Y2tldE5hbWUsIHsgZm9yY2U6IHRydWUsIHJlYXNvbjogXCJhIHZhbGlkIHdpbmRvdyBib3VuZGFyeSBwYXNzZWRcIiB9KTtcbiAgICAgICAgfSkoKTtcbiAgICB9LCBNYXRoLm1pbihuZXh0Qm91bmRhcnkgLSBub3cgKyBSRUJVSUxEX0JPVU5EQVJZX0JVRkZFUiwgTUFYX1JFQlVJTERfVElNRVJfREVMQVkpKTtcbiAgICAodGltZXIgYXMgeyB1bnJlZj86ICgpID0+IHZvaWQgfSkudW5yZWY/LigpO1xufVxuXG5jb25zdCBCT1VOREFSWV9TQ0FOX09GRlNFVFMgPSBbLTMwICogMTAwMCwgMiAqIDEwMDAsIDMwICogMTAwMF07XG5jb25zdCBCT1VOREFSWV9TQ0FOX0xPT0tCQUNLID0gREVGQVVMVF9GQVNUX1dSSVRFX0RFTEFZICsgV0lORE9XX0VORF9GTFVTSF9NQVJHSU47XG5jb25zdCBTVEFSVFVQX0JPVU5EQVJZX1NDQU5fREVMQVkgPSAzMCAqIDEwMDA7XG5cbmNvbnN0IHNjaGVkdWxlZEJvdW5kYXJ5U2NhbnMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbmNvbnN0IGJvdW5kYXJ5U2NhbnNSdW5uaW5nID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbmZ1bmN0aW9uIHNjaGVkdWxlQm91bmRhcnlTY2Fucyhsb2FkZWQ6IEJ1Y2tldFN0YXRlKTogdm9pZCB7XG4gICAgbGV0IGtleSA9IGAke2xvYWRlZC5hY2NvdW50fS8ke2xvYWRlZC5idWNrZXROYW1lfWA7XG4gICAgbGV0IG5vdyA9IERhdGUubm93KCk7XG4gICAgbGV0IHN0YXJ0cyA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuICAgIGZvciAobGV0IHNlbGYgb2YgbG9hZGVkLnNlbGZFbnRyaWVzKSB7XG4gICAgICAgIGxldCBzdGFydCA9IHNlbGYudmFsaWRXaW5kb3dbMF07XG4gICAgICAgIGlmIChzdGFydCA+IG5vdyAmJiBzdGFydCA8IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSKSB7XG4gICAgICAgICAgICBzdGFydHMuYWRkKHN0YXJ0KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKGxldCBzZWxmIG9mIGxvYWRlZC5zZWxmRW50cmllcykge1xuICAgICAgICBsZXQgW3N0YXJ0LCBlbmRdID0gc2VsZi52YWxpZFdpbmRvdztcbiAgICAgICAgaWYgKCEoc3RhcnQgPD0gbm93ICYmIG5vdyA8IGVuZCkgfHwgc3RhcnQgPD0gMCkgY29udGludWU7XG4gICAgICAgIGlmIChub3cgLSBzdGFydCA+IEJPVU5EQVJZX1NDQU5fTE9PS0JBQ0spIGNvbnRpbnVlO1xuICAgICAgICBsZXQgc2NoZWR1bGVLZXkgPSBgJHtrZXl9fCR7c3RhcnR9fHN0YXJ0dXBgO1xuICAgICAgICBpZiAoc2NoZWR1bGVkQm91bmRhcnlTY2Fucy5oYXMoc2NoZWR1bGVLZXkpKSBjb250aW51ZTtcbiAgICAgICAgc2NoZWR1bGVkQm91bmRhcnlTY2Fucy5hZGQoc2NoZWR1bGVLZXkpO1xuICAgICAgICBsZXQgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHZvaWQgcnVuQm91bmRhcnlTY2FuKGtleSwgc3RhcnQsIFNUQVJUVVBfQk9VTkRBUllfU0NBTl9ERUxBWSwgXCJzdGFydHVwKzMwc1wiKS5jYXRjaCgoZTogRXJyb3IpID0+IGNvbnNvbGUuZXJyb3IoYEJvdW5kYXJ5IHNjYW4gZm9yIGJ1Y2tldCAke2tleX0gZmFpbGVkOiAke2Uuc3RhY2sgPz8gZX1gKSk7XG4gICAgICAgIH0sIFNUQVJUVVBfQk9VTkRBUllfU0NBTl9ERUxBWSk7XG4gICAgICAgICh0aW1lciBhcyB7IHVucmVmPzogKCkgPT4gdm9pZCB9KS51bnJlZj8uKCk7XG4gICAgfVxuICAgIGZvciAobGV0IHN0YXJ0IG9mIHN0YXJ0cykge1xuICAgICAgICBmb3IgKGxldCBvZmZzZXQgb2YgQk9VTkRBUllfU0NBTl9PRkZTRVRTKSB7XG4gICAgICAgICAgICBsZXQgYXQgPSBzdGFydCArIG9mZnNldDtcbiAgICAgICAgICAgIGlmIChhdCA8PSBub3cpIGNvbnRpbnVlO1xuICAgICAgICAgICAgbGV0IHNjaGVkdWxlS2V5ID0gYCR7a2V5fXwke3N0YXJ0fXwke29mZnNldH1gO1xuICAgICAgICAgICAgaWYgKHNjaGVkdWxlZEJvdW5kYXJ5U2NhbnMuaGFzKHNjaGVkdWxlS2V5KSkgY29udGludWU7XG4gICAgICAgICAgICBzY2hlZHVsZWRCb3VuZGFyeVNjYW5zLmFkZChzY2hlZHVsZUtleSk7XG4gICAgICAgICAgICBsZXQgYXJtID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGxldCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoRGF0ZS5ub3coKSA8IGF0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcm0oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2b2lkIHJ1bkJvdW5kYXJ5U2NhbihrZXksIHN0YXJ0LCBvZmZzZXQpLmNhdGNoKChlOiBFcnJvcikgPT4gY29uc29sZS5lcnJvcihgQm91bmRhcnkgc2NhbiBmb3IgYnVja2V0ICR7a2V5fSBmYWlsZWQ6ICR7ZS5zdGFjayA/PyBlfWApKTtcbiAgICAgICAgICAgICAgICB9LCBNYXRoLm1pbihhdCAtIERhdGUubm93KCksIE1BWF9SRUJVSUxEX1RJTUVSX0RFTEFZKSk7XG4gICAgICAgICAgICAgICAgKHRpbWVyIGFzIHsgdW5yZWY/OiAoKSA9PiB2b2lkIH0pLnVucmVmPy4oKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBhcm0oKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcnVuQm91bmRhcnlTY2FuKGJ1Y2tldEtleTogc3RyaW5nLCB3aW5kb3dTdGFydDogbnVtYmVyLCBvZmZzZXQ6IG51bWJlciwgb2Zmc2V0TGFiZWw/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsZXQgbGFiZWwgPSBgYnVja2V0ICR7YnVja2V0S2V5fSwgd2luZG93IHN0YXJ0aW5nICR7bmV3IERhdGUod2luZG93U3RhcnQpLnRvSVNPU3RyaW5nKCl9LCBvZmZzZXQgJHtvZmZzZXRMYWJlbCB8fCBgJHtvZmZzZXQgLyAxMDAwfXNgfWA7XG4gICAgaWYgKGJvdW5kYXJ5U2NhbnNSdW5uaW5nLmhhcyhidWNrZXRLZXkpKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBTa2lwcGluZyBib3VuZGFyeSBzY2FuICgke2xhYmVsfSk6IHRoZSBwcmV2aW91cyBib3VuZGFyeSBzY2FuIGlzIHN0aWxsIHJ1bm5pbmdgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBib3VuZGFyeVNjYW5zUnVubmluZy5hZGQoYnVja2V0S2V5KTtcbiAgICB0cnkge1xuICAgICAgICBsZXQgbG9hZGVkID0gYXdhaXQgYnVja2V0cy5nZXQoYnVja2V0S2V5KTtcbiAgICAgICAgaWYgKCFsb2FkZWQpIHJldHVybjtcbiAgICAgICAgbGV0IGVmZmVjdGl2ZSA9IGxvYWRlZC5yb3V0aW5nO1xuICAgICAgICBsZXQgc2VsZkluZGV4ZXMgPSBmaW5kU2VsZkluZGV4ZXMoZWZmZWN0aXZlLCBsb2FkZWQuYWNjb3VudCwgbG9hZGVkLmJ1Y2tldE5hbWUpO1xuICAgICAgICBsZXQgc2VsZkluZGV4U2V0ID0gbmV3IFNldChzZWxmSW5kZXhlcyk7XG4gICAgICAgIGxldCBzZWx2ZXMgPSBzZWxmSW5kZXhlcy5tYXAoaSA9PiBlZmZlY3RpdmUuc291cmNlc1tpXSBhcyBIb3N0ZWRDb25maWcpLmZpbHRlcih4ID0+IHgudmFsaWRXaW5kb3dbMF0gPT09IHdpbmRvd1N0YXJ0KTtcbiAgICAgICAgaWYgKCFzZWx2ZXMubGVuZ3RoKSByZXR1cm47XG4gICAgICAgIGxldCBwcmV2VGltZSA9IHdpbmRvd1N0YXJ0IC0gMTtcbiAgICAgICAgLy8gRXZlcnl0aGluZyBpcyBwZXItc3RvcmU6IGVhY2ggc2VsZiBlbnRyeSdzIHJvdXRlIGhhcyBpdHMgb3duIHN0b3JlLCBhbmQgdGhhdCBzdG9yZSdzIGRpc2svcmVtb3RlIGJvdW5kYXJ5IHB1bGxzIG9ubHkgY29uY2VybiBpdHMgb3duIHJvdXRlIHNsaWNlXG4gICAgICAgIGxldCBuZWVkRGlza1NjYW4gPSBuZXcgU2V0PExvYWRlZFN0b3JlPigpO1xuICAgICAgICBsZXQgcmVtb3RlT3duZXJzID0gbmV3IE1hcDxMb2FkZWRTdG9yZSwgTWFwPG51bWJlciwgW251bWJlciwgbnVtYmVyXT4+KCk7XG4gICAgICAgIGZvciAobGV0IHNlbGYgb2Ygc2VsdmVzKSB7XG4gICAgICAgICAgICBsZXQgc2VsZlJvdXRlID0gc2VsZi5yb3V0ZSB8fCBGVUxMX1JPVVRFO1xuICAgICAgICAgICAgbGV0IHNlbGZTdG9yZSA9IGxvYWRlZC5zdG9yZXMuZmluZCh4ID0+IHgucm91dGVLZXkgPT09IEpTT04uc3RyaW5naWZ5KHNlbGZSb3V0ZSkpO1xuICAgICAgICAgICAgaWYgKCFzZWxmU3RvcmUgfHwgIShzZWxmU3RvcmUuc3RvcmUgaW5zdGFuY2VvZiBCbG9iU3RvcmUpKSBjb250aW51ZTtcbiAgICAgICAgICAgIGxldCBpZHggPSBlZmZlY3RpdmUuc291cmNlcy5pbmRleE9mKHNlbGYpO1xuICAgICAgICAgICAgbGV0IHNoYWRvd2VkID0gZmFsc2U7XG4gICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGlkeDsgaisrKSB7XG4gICAgICAgICAgICAgICAgbGV0IG90aGVyID0gZWZmZWN0aXZlLnNvdXJjZXNbal07XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvdGhlciA9PT0gXCJzdHJpbmdcIikgY29udGludWU7XG4gICAgICAgICAgICAgICAgbGV0IFt3cywgd2VdID0gb3RoZXIudmFsaWRXaW5kb3c7XG4gICAgICAgICAgICAgICAgaWYgKCEod3MgPD0gd2luZG93U3RhcnQgJiYgd2luZG93U3RhcnQgPCB3ZSkpIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGxldCByID0gb3RoZXIucm91dGUgfHwgRlVMTF9ST1VURTtcbiAgICAgICAgICAgICAgICBpZiAoclswXSA8PSBzZWxmUm91dGVbMF0gJiYgc2VsZlJvdXRlWzFdIDw9IHJbMV0pIHtcbiAgICAgICAgICAgICAgICAgICAgc2hhZG93ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2hhZG93ZWQpIGNvbnRpbnVlO1xuICAgICAgICAgICAgbGV0IHVuY292ZXJlZDogW251bWJlciwgbnVtYmVyXVtdID0gW1tzZWxmUm91dGVbMF0sIHNlbGZSb3V0ZVsxXV1dO1xuICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBlZmZlY3RpdmUuc291cmNlcy5sZW5ndGggJiYgdW5jb3ZlcmVkLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgbGV0IG90aGVyID0gZWZmZWN0aXZlLnNvdXJjZXNbal07XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvdGhlciA9PT0gXCJzdHJpbmdcIikgY29udGludWU7XG4gICAgICAgICAgICAgICAgbGV0IFt3cywgd2VdID0gb3RoZXIudmFsaWRXaW5kb3c7XG4gICAgICAgICAgICAgICAgaWYgKCEod3MgPD0gcHJldlRpbWUgJiYgcHJldlRpbWUgPCB3ZSkpIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGxldCByID0gb3RoZXIucm91dGUgfHwgRlVMTF9ST1VURTtcbiAgICAgICAgICAgICAgICBsZXQgcmVtYWluaW5nOiBbbnVtYmVyLCBudW1iZXJdW10gPSBbXTtcbiAgICAgICAgICAgICAgICBsZXQgY2xhaW1lZDogW251bWJlciwgbnVtYmVyXSB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB1IG9mIHVuY292ZXJlZCkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgaW50ZXIgPSByb3V0ZUludGVyc2VjdGlvbih1LCByKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpbnRlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtYWluaW5nLnB1c2godSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjbGFpbWVkID0gY2xhaW1lZCAmJiBbTWF0aC5taW4oY2xhaW1lZFswXSwgaW50ZXJbMF0pLCBNYXRoLm1heChjbGFpbWVkWzFdLCBpbnRlclsxXSldIGFzIFtudW1iZXIsIG51bWJlcl0gfHwgaW50ZXI7XG4gICAgICAgICAgICAgICAgICAgIGlmICh1WzBdIDwgaW50ZXJbMF0pIHJlbWFpbmluZy5wdXNoKFt1WzBdLCBpbnRlclswXV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW50ZXJbMV0gPCB1WzFdKSByZW1haW5pbmcucHVzaChbaW50ZXJbMV0sIHVbMV1dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdW5jb3ZlcmVkID0gcmVtYWluaW5nO1xuICAgICAgICAgICAgICAgIGlmICghY2xhaW1lZCkgY29udGludWU7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGZJbmRleFNldC5oYXMoaikpIHtcbiAgICAgICAgICAgICAgICAgICAgbmVlZERpc2tTY2FuLmFkZChzZWxmU3RvcmUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvd25lcnMgPSByZW1vdGVPd25lcnMuZ2V0KHNlbGZTdG9yZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghb3duZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvd25lcnMgPSBuZXcgTWFwKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdGVPd25lcnMuc2V0KHNlbGZTdG9yZSwgb3duZXJzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBsZXQgZXhpc3RpbmcgPSBvd25lcnMuZ2V0KGopO1xuICAgICAgICAgICAgICAgICAgICBvd25lcnMuc2V0KGosIGV4aXN0aW5nICYmIFtNYXRoLm1pbihleGlzdGluZ1swXSwgY2xhaW1lZFswXSksIE1hdGgubWF4KGV4aXN0aW5nWzFdLCBjbGFpbWVkWzFdKV0gYXMgW251bWJlciwgbnVtYmVyXSB8fCBjbGFpbWVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFuZWVkRGlza1NjYW4uc2l6ZSAmJiAhcmVtb3RlT3duZXJzLnNpemUpIHJldHVybjtcbiAgICAgICAgY29uc29sZS5sb2coYEJvdW5kYXJ5IHNjYW4gKCR7bGFiZWx9KTogZGlza1NjYW5zPSR7bmVlZERpc2tTY2FuLnNpemV9LCBzdG9yZXMgd2l0aCByZW1vdGUgcHJldmlvdXMtd2luZG93IG93bmVyczogJHtyZW1vdGVPd25lcnMuc2l6ZX1gKTtcbiAgICAgICAgZm9yIChsZXQgc2VsZlN0b3JlIG9mIG5lZWREaXNrU2Nhbikge1xuICAgICAgICAgICAgaWYgKHNlbGZTdG9yZS5zdG9yZSBpbnN0YW5jZW9mIEJsb2JTdG9yZSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHNlbGZTdG9yZS5zdG9yZS5yZXNjYW5CYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHNpbmNlID0gd2luZG93U3RhcnQgLSBCT1VOREFSWV9TQ0FOX0xPT0tCQUNLO1xuICAgICAgICBmb3IgKGxldCBbc2VsZlN0b3JlLCBvd25lcnNdIG9mIHJlbW90ZU93bmVycykge1xuICAgICAgICAgICAgaWYgKCEoc2VsZlN0b3JlLnN0b3JlIGluc3RhbmNlb2YgQmxvYlN0b3JlKSkgY29udGludWU7XG4gICAgICAgICAgICBmb3IgKGxldCBbc291cmNlSW5kZXgsIHJvdXRlXSBvZiBvd25lcnMpIHtcbiAgICAgICAgICAgICAgICBsZXQgb3duZXJTb3VyY2UgPSBlZmZlY3RpdmUuc291cmNlc1tzb3VyY2VJbmRleF07XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvd25lclNvdXJjZSA9PT0gXCJzdHJpbmdcIikgY29udGludWU7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgc2VsZlN0b3JlLnN0b3JlLmJvdW5kYXJ5U2NhblJlbW90ZShjcmVhdGVBcGlBcmNoaXZlcyhvd25lclNvdXJjZSksIHsgc2luY2UsIHJvdXRlIH0pO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgQm91bmRhcnkgc2NhbiAoJHtsYWJlbH0pIG9mIHByZXZpb3VzLXdpbmRvdyBvd25lciAoc291cmNlIGluZGV4ICR7c291cmNlSW5kZXh9KSBmYWlsZWQ6ICR7KGUgYXMgRXJyb3IpLnN0YWNrID8/IGV9YCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYm91bmRhcnlTY2Fuc1J1bm5pbmcuZGVsZXRlKGJ1Y2tldEtleSk7XG4gICAgfVxufVxuXG5jb25zdCByZXNvbHZlZFNvdXJjZUFyY2hpdmVzID0gbmV3IE1hcDxzdHJpbmcsIElBcmNoaXZlcz4oKTtcbi8qKiBBIGNhY2hlZCBJQXJjaGl2ZXMgZm9yIGEgcGVyc2lzdGVkIHNvdXJjZSBpZGVudGl0eTogYSByb3V0aW5nIFVSTCAoaG9zdGVkL2JhY2tibGF6ZSkgb3IgYSBkaXNrIGZvbGRlciBwYXRoIC0gdGhlIGZvcm0gQmxvYlN0b3JlJ3Mgc291cmNlcyBsaXN0IHN0b3Jlcy4gQ29uZmlndXJhdGlvbiAodmFsaWQgd2luZG93cywgcm91dGVzKSBkZWNpZGVzIFdIRU4gYSBzb3VyY2Ugc2hvdWxkIGJlIHVzZWQ7IGZvciByZWFkaW5nIGJ5dGVzIHRoZSBpbmRleCBzYXlzIGEgc291cmNlIGhvbGRzLCB0aGUgVVJMIGFsb25lIGlzIGVub3VnaCAtIGV2ZW4gZm9yIHNvdXJjZXMgbm8gbG9uZ2VyIGluIGFueSBjb25maWcuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZVNvdXJjZUFyY2hpdmVzKHVybDogc3RyaW5nKTogSUFyY2hpdmVzIHtcbiAgICBsZXQgZXhpc3RpbmcgPSByZXNvbHZlZFNvdXJjZUFyY2hpdmVzLmdldCh1cmwpO1xuICAgIGlmIChleGlzdGluZykgcmV0dXJuIGV4aXN0aW5nO1xuICAgIGxldCBhcmNoaXZlczogSUFyY2hpdmVzO1xuICAgIGlmICh1cmwuc3RhcnRzV2l0aChcImh0dHBzOi8vXCIpKSB7XG4gICAgICAgIC8vIFRoZSBjb25maWcgaXMgZmFicmljYXRlZCBmcm9tIHRoZSBiYXJlIFVSTCBhbmQgY2FuIG5ldmVyIGV4YWN0LW1hdGNoIGEgc2VydmVyJ3MgZW50cmllcyAtIHdoaWNoIGlzIGZpbmUsIGJlY2F1c2UgaG9sZGVyIHJlYWRzIGFyZSBpbnRlcm5hbCByZWFkcywgYW5kIGludGVybmFsIHJlYWRzIG5ldmVyIHNlbGVjdCBhIHN0b3JlIChzZWUgcmVhZEJ1Y2tldEludGVybmFsKVxuICAgICAgICBhcmNoaXZlcyA9IGNyZWF0ZUFwaUFyY2hpdmVzKG5vcm1hbGl6ZVNvdXJjZSh1cmwpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBhcmNoaXZlcyA9IG5ldyBBcmNoaXZlc0Rpc2sodXJsKTtcbiAgICB9XG4gICAgcmVzb2x2ZWRTb3VyY2VBcmNoaXZlcy5zZXQodXJsLCBhcmNoaXZlcyk7XG4gICAgcmV0dXJuIGFyY2hpdmVzO1xufVxuXG5mdW5jdGlvbiBzb3VyY2VJZGVudGl0eShzb3VyY2VDb25maWc6IFNvdXJjZUNvbmZpZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gICAgaWYgKCFzb3VyY2VDb25maWcpIHJldHVybiBcImRpc2tcIjtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoeyAuLi5zb3VyY2VDb25maWcsIHZhbGlkV2luZG93OiB1bmRlZmluZWQsIHJvdXRlOiB1bmRlZmluZWQgfSk7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkU3RvcmUoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcsIHBsYW5TdG9yZTogU3RvcmVQbGFuU3RvcmUpOiBJQnVja2V0U3RvcmUge1xuICAgIGxldCBmb2xkZXIgPSBnZXRCdWNrZXRGb2xkZXIoYWNjb3VudCwgYnVja2V0TmFtZSwgcGxhblN0b3JlLnJvdXRlKTtcbiAgICBpZiAocGxhblN0b3JlLnJhd0Rpc2spIHtcbiAgICAgICAgcmV0dXJuIG5ldyBSYXdEaXNrU3RvcmUobmV3IEFyY2hpdmVzRGlzayhmb2xkZXIpKTtcbiAgICB9XG4gICAgbGV0IHNvdXJjZXM6IEFyY2hpdmVzU291cmNlW10gPSBwbGFuU3RvcmUuc291cmNlU3BlY3MubWFwKHNwZWMgPT4gKHtcbiAgICAgICAgc291cmNlOiBzcGVjLnNvdXJjZUNvbmZpZyAmJiBjcmVhdGVBcGlBcmNoaXZlcyhzcGVjLnNvdXJjZUNvbmZpZykgfHwgbmV3IEFyY2hpdmVzRGlzayhmb2xkZXIpLFxuICAgICAgICB1cmw6IHNwZWMuc291cmNlQ29uZmlnPy51cmwgfHwgZm9sZGVyLFxuICAgICAgICB2YWxpZFdpbmRvd3M6IHNwZWMudmFsaWRXaW5kb3dzLFxuICAgICAgICByb3V0ZTogc3BlYy5yb3V0ZSxcbiAgICAgICAgbm9GdWxsU3luYzogc3BlYy5ub0Z1bGxTeW5jLFxuICAgICAgICBpbnRlcm1lZGlhdGU6IHNwZWMuc291cmNlQ29uZmlnPy5pbnRlcm1lZGlhdGUsXG4gICAgICAgIHNvdXJjZUNvbmZpZzogc3BlYy5zb3VyY2VDb25maWcsXG4gICAgICAgIGlkZW50aXR5OiBzb3VyY2VJZGVudGl0eShzcGVjLnNvdXJjZUNvbmZpZyksXG4gICAgfSkpO1xuICAgIHJldHVybiBuZXcgQmxvYlN0b3JlKGZvbGRlciwgc291cmNlcywge1xuICAgICAgICByZWFkZXJEaXNrTGltaXQ6IHBsYW5TdG9yZS5yZWFkZXJEaXNrTGltaXQsXG4gICAgICAgIG9uV3JpdGVDb3VudGVkOiAoa2luZCwgYnl0ZXMpID0+IGNvdW50QnVja2V0V3JpdGUoYCR7YWNjb3VudH0vJHtidWNrZXROYW1lfWAsIGtpbmQsIGJ5dGVzKSxcbiAgICAgICAgcmVzb2x2ZVNvdXJjZVVybDogcmVzb2x2ZVNvdXJjZUFyY2hpdmVzLFxuICAgICAgICBlbnRyaWVzOiBwbGFuU3RvcmUuZW50cmllcyxcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gYnVpbGRCdWNrZXQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcsIHJvdXRpbmc6IFJlbW90ZUNvbmZpZywgcGxhbj86IFN0b3JlUGxhbik6IEJ1Y2tldFN0YXRlIHtcbiAgICBpZiAoIXBsYW4pIHtcbiAgICAgICAgcGxhbiA9IGNvbXB1dGVTdG9yZVBsYW4oYWNjb3VudCwgYnVja2V0TmFtZSwgcm91dGluZyk7XG4gICAgfVxuICAgIGxldCB7IHNlbGZFbnRyaWVzLCBzZWxmIH0gPSBwbGFuO1xuICAgIGlmICghc2VsZikge1xuICAgICAgICBjb25zb2xlLmxvZyhgVGhpcyBzZXJ2ZXIgaXMgbm90IGluIHRoZSByb3V0aW5nIGNvbmZpZyBmb3IgYnVja2V0ICR7YWNjb3VudH0vJHtidWNrZXROYW1lfTogbm8gbG9uZ2VyIHN5bmNocm9uaXppbmcsIHZhbGlkIHdpbmRvdyB0cmVhdGVkIGFzIFswLCAwXSAoZmFzdCB3cml0ZXMgZmx1c2ggaW1tZWRpYXRlbHkpLCBkaXNrIGRhdGEga2VwdCBhbmQgc2VydmVkYCk7XG4gICAgfVxuICAgIGxldCBzdG9yZXM6IExvYWRlZFN0b3JlW10gPSBwbGFuLnN0b3Jlcy5tYXAocGxhblN0b3JlID0+ICh7XG4gICAgICAgIHJvdXRlS2V5OiBwbGFuU3RvcmUucm91dGVLZXksXG4gICAgICAgIHJvdXRlOiBwbGFuU3RvcmUucm91dGUsXG4gICAgICAgIGVudHJpZXM6IHBsYW5TdG9yZS5lbnRyaWVzLFxuICAgICAgICBmb2xkZXI6IGdldEJ1Y2tldEZvbGRlcihhY2NvdW50LCBidWNrZXROYW1lLCBwbGFuU3RvcmUucm91dGUpLFxuICAgICAgICBzdG9yZTogYnVpbGRTdG9yZShhY2NvdW50LCBidWNrZXROYW1lLCBwbGFuU3RvcmUpLFxuICAgIH0pKTtcbiAgICBsZXQgbG9hZGVkOiBCdWNrZXRTdGF0ZSA9IHsgYWNjb3VudCwgYnVja2V0TmFtZSwgcm91dGluZywgcm91dGluZ0pTT046IEpTT04uc3RyaW5naWZ5KHJvdXRpbmcpLCBzZWxmRW50cmllcywgc2VsZiwgc3RvcmVzLCBzdHJ1Y3R1cmVLZXk6IHBsYW4uc3RydWN0dXJlS2V5IH07XG4gICAgc2NoZWR1bGVXaW5kb3dCb3VuZGFyeVJlYnVpbGQobG9hZGVkKTtcbiAgICBzY2hlZHVsZUJvdW5kYXJ5U2NhbnMobG9hZGVkKTtcbiAgICAvLyBBIGxvYWRlZCBidWNrZXQgbXVzdCBhY3R1YWxseSBiZSBydW5uaW5nOiBlYWNoIHN0b3JlJ3MgaW5pdCBsb2FkcyBpdHMgaW5kZXggYW5kIHN0YXJ0cyBpdHMgc291cmNlIHN5bmNocm9uaXphdGlvbiwgYW5kIGl0IGlzIGxhenksIHNvIHdpdGhvdXQgdGhpcyBhIGJ1Y2tldCBub3RoaW5nIGhhcyByZWFkIGZyb20gb3Igd3JpdHRlbiB0byBzaXRzIGluZXJ0IC0gcmVwb3J0aW5nIG5vIGRhdGEgYW5kIG5vIHN5bmNpbmcgd2hpbGUgaXRzIGRpc2sgaXMgZnVsbCBvZiBmaWxlcy5cbiAgICBmb3IgKGxldCBzIG9mIHN0b3Jlcykge1xuICAgICAgICBpZiAocy5zdG9yZSBpbnN0YW5jZW9mIEJsb2JTdG9yZSkge1xuICAgICAgICAgICAgbGV0IHN0b3JlID0gcy5zdG9yZTtcbiAgICAgICAgICAgIHZvaWQgc3RvcmUuaW5pdCgpLmNhdGNoKChlOiBFcnJvcikgPT4gY29uc29sZS5lcnJvcihgSW5pdGlhbGl6aW5nIHRoZSBzdG9yZSBmb3IgYnVja2V0ICR7YWNjb3VudH0vJHtidWNrZXROYW1lfSAocm91dGUgJHtzLnJvdXRlS2V5fSkgZmFpbGVkOiAke2Uuc3RhY2sgPz8gZX1gKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGxvYWRlZDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbG9hZEJ1Y2tldChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8QnVja2V0U3RhdGUgfCB1bmRlZmluZWQ+IHtcbiAgICBsZXQgcm91dGluZyA9IGF3YWl0IHJlYWRSb3V0aW5nRnJvbURpc2soYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgaWYgKCFyb3V0aW5nKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiBidWlsZEJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lLCByb3V0aW5nKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldExvYWRlZEJ1Y2tldChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8QnVja2V0U3RhdGUgfCB1bmRlZmluZWQ+IHtcbiAgICBsZXQga2V5ID0gYCR7YWNjb3VudH0vJHtidWNrZXROYW1lfWA7XG4gICAgbGV0IGxvYWRlZCA9IGJ1Y2tldHMuZ2V0KGtleSk7XG4gICAgaWYgKCFsb2FkZWQpIHtcbiAgICAgICAgbG9hZGVkID0gbG9hZEJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICAgICAgYnVja2V0cy5zZXQoa2V5LCBsb2FkZWQpO1xuICAgICAgICB2b2lkIGxvYWRlZC50aGVuKGJ1Y2tldCA9PiB7XG4gICAgICAgICAgICBpZiAoIWJ1Y2tldCAmJiBidWNrZXRzLmdldChrZXkpID09PSBsb2FkZWQpIHtcbiAgICAgICAgICAgICAgICBidWNrZXRzLmRlbGV0ZShrZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoYnVja2V0cy5nZXQoa2V5KSA9PT0gbG9hZGVkKSB7XG4gICAgICAgICAgICAgICAgYnVja2V0cy5kZWxldGUoa2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBsb2FkZWQ7XG59XG5cbmNvbnN0IHJvdXRpbmdSZWxvYWRzID0gbmV3IE1hcDxzdHJpbmcsIFByb21pc2U8dm9pZD4+KCk7XG5mdW5jdGlvbiBzY2hlZHVsZVJvdXRpbmdSZWxvYWQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcsIGNvbmZpZz86IHsgZm9yY2U/OiBib29sZWFuOyByZWFzb24/OiBzdHJpbmcgfSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxldCBrZXkgPSBgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9YDtcbiAgICBsZXQgbmV4dCA9IChyb3V0aW5nUmVsb2Fkcy5nZXQoa2V5KSB8fCBQcm9taXNlLnJlc29sdmUoKSlcbiAgICAgICAgLnRoZW4oKCkgPT4gY2hlY2tSb3V0aW5nQ2hhbmdlZChhY2NvdW50LCBidWNrZXROYW1lLCBjb25maWcpKVxuICAgICAgICAuY2F0Y2goZSA9PiBjb25zb2xlLmVycm9yKGBSZWxvYWRpbmcgcm91dGluZyBjb25maWcgZm9yIGJ1Y2tldCAke2tleX0gZmFpbGVkOmAsIGUpKTtcbiAgICByb3V0aW5nUmVsb2Fkcy5zZXQoa2V5LCBuZXh0KTtcbiAgICByZXR1cm4gbmV4dDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY2hlY2tSb3V0aW5nQ2hhbmdlZChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgY29uZmlnPzogeyBmb3JjZT86IGJvb2xlYW47IHJlYXNvbj86IHN0cmluZyB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IGtleSA9IGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gO1xuICAgIGxldCBsb2FkZWQgPSBhd2FpdCBidWNrZXRzLmdldChrZXkpO1xuICAgIGlmICghbG9hZGVkKSByZXR1cm47XG4gICAgbGV0IHJvdXRpbmcgPSBhd2FpdCByZWFkUm91dGluZ0Zyb21EaXNrKGFjY291bnQsIGJ1Y2tldE5hbWUpO1xuICAgIGlmICghcm91dGluZykgcmV0dXJuO1xuICAgIGlmICghY29uZmlnPy5mb3JjZSAmJiBKU09OLnN0cmluZ2lmeShyb3V0aW5nKSA9PT0gbG9hZGVkLnJvdXRpbmdKU09OKSByZXR1cm47XG4gICAgbGV0IHJlYXNvbiA9IGNvbmZpZz8uZm9yY2UgJiYgKGNvbmZpZy5yZWFzb24gfHwgXCJmb3JjZWRcIikgfHwgXCJyb3V0aW5nIGNvbmZpZyBjaGFuZ2VkXCI7XG4gICAgbGV0IHBsYW4gPSBjb21wdXRlU3RvcmVQbGFuKGFjY291bnQsIGJ1Y2tldE5hbWUsIHJvdXRpbmcpO1xuICAgIGlmIChwbGFuLnN0cnVjdHVyZUtleSA9PT0gbG9hZGVkLnN0cnVjdHVyZUtleSkge1xuICAgICAgICBjb25zb2xlLmxvZyhgQXBwbHlpbmcgdGhlIHJvdXRpbmcgY29uZmlnIHRvIHRoZSBydW5uaW5nIHN0b3JlcyBmb3IgYnVja2V0ICR7a2V5fSAoJHtyZWFzb259KWApO1xuICAgICAgICBmb3IgKGxldCBwbGFuU3RvcmUgb2YgcGxhbi5zdG9yZXMpIHtcbiAgICAgICAgICAgIGxldCBsaXZlID0gbG9hZGVkLnN0b3Jlcy5maW5kKHggPT4geC5yb3V0ZUtleSA9PT0gcGxhblN0b3JlLnJvdXRlS2V5KTtcbiAgICAgICAgICAgIC8vIHN0cnVjdHVyZUtleSBlcXVhbGl0eSBtZWFucyB0aGUgc3RvcmUgc2V0IChyb3V0ZXMsIHJhd0Rpc2ssIGxpbWl0cykgaXMgdW5jaGFuZ2VkLCBzbyBldmVyeSBwbGFuIHN0b3JlIGhhcyBpdHMgbGl2ZSB0d2luXG4gICAgICAgICAgICBpZiAoIWxpdmUgfHwgIShsaXZlLnN0b3JlIGluc3RhbmNlb2YgQmxvYlN0b3JlKSkgY29udGludWU7XG4gICAgICAgICAgICBsZXQgc3RvcmVGb2xkZXIgPSBsaXZlLmZvbGRlcjtcbiAgICAgICAgICAgIGxpdmUuc3RvcmUudXBkYXRlU291cmNlcyhwbGFuU3RvcmUuc291cmNlU3BlY3MubWFwKHNwZWMgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZUNvbmZpZyA9IHNwZWMuc291cmNlQ29uZmlnO1xuICAgICAgICAgICAgICAgIGlmICghc291cmNlQ29uZmlnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7IGlkZW50aXR5OiBzb3VyY2VJZGVudGl0eSh1bmRlZmluZWQpLCB1cmw6IHN0b3JlRm9sZGVyLCB2YWxpZFdpbmRvd3M6IHNwZWMudmFsaWRXaW5kb3dzLCBjcmVhdGU6ICgpOiBJQXJjaGl2ZXMgPT4gbmV3IEFyY2hpdmVzRGlzayhzdG9yZUZvbGRlcikgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgaWRlbnRpdHk6IHNvdXJjZUlkZW50aXR5KHNvdXJjZUNvbmZpZyksXG4gICAgICAgICAgICAgICAgICAgIHVybDogc291cmNlQ29uZmlnLnVybCxcbiAgICAgICAgICAgICAgICAgICAgdmFsaWRXaW5kb3dzOiBzcGVjLnZhbGlkV2luZG93cyxcbiAgICAgICAgICAgICAgICAgICAgcm91dGU6IHNwZWMucm91dGUsXG4gICAgICAgICAgICAgICAgICAgIG5vRnVsbFN5bmM6IHNwZWMubm9GdWxsU3luYyxcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJtZWRpYXRlOiBzb3VyY2VDb25maWcuaW50ZXJtZWRpYXRlLFxuICAgICAgICAgICAgICAgICAgICBzb3VyY2VDb25maWcsXG4gICAgICAgICAgICAgICAgICAgIGNyZWF0ZTogKCkgPT4gY3JlYXRlQXBpQXJjaGl2ZXMoc291cmNlQ29uZmlnKSxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSksIHBsYW5TdG9yZS5lbnRyaWVzKTtcbiAgICAgICAgICAgIGxpdmUuZW50cmllcyA9IHBsYW5TdG9yZS5lbnRyaWVzO1xuICAgICAgICB9XG4gICAgICAgIGxvYWRlZC5yb3V0aW5nID0gcm91dGluZztcbiAgICAgICAgbG9hZGVkLnJvdXRpbmdKU09OID0gSlNPTi5zdHJpbmdpZnkocm91dGluZyk7XG4gICAgICAgIGxvYWRlZC5zZWxmRW50cmllcyA9IHBsYW4uc2VsZkVudHJpZXM7XG4gICAgICAgIGxvYWRlZC5zZWxmID0gcGxhbi5zZWxmO1xuICAgICAgICBzY2hlZHVsZVdpbmRvd0JvdW5kYXJ5UmVidWlsZChsb2FkZWQpO1xuICAgICAgICBzY2hlZHVsZUJvdW5kYXJ5U2NhbnMobG9hZGVkKTtcbiAgICAgICAgYnJvYWRjYXN0Um91dGluZ0NoYW5nZWQoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZyhgUmVidWlsZGluZyB0aGUgc3RvcmVzIGZvciBidWNrZXQgJHtrZXl9ICgke3JlYXNvbn0pOiBzdHJ1Y3R1cmUgY2hhbmdlZCBmcm9tICR7bG9hZGVkLnN0cnVjdHVyZUtleX0gdG8gJHtwbGFuLnN0cnVjdHVyZUtleX1gKTtcbiAgICBmb3IgKGxldCBzIG9mIGxvYWRlZC5zdG9yZXMpIHtcbiAgICAgICAgaWYgKHMuc3RvcmUgaW5zdGFuY2VvZiBCbG9iU3RvcmUpIHtcbiAgICAgICAgICAgIGF3YWl0IHMuc3RvcmUuZGlzcG9zZSgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGJ1Y2tldHMuc2V0KGtleSwgUHJvbWlzZS5yZXNvbHZlKGJ1aWxkQnVja2V0KGFjY291bnQsIGJ1Y2tldE5hbWUsIHJvdXRpbmcsIHBsYW4pKSk7XG4gICAgYnJvYWRjYXN0Um91dGluZ0NoYW5nZWQoKTtcbn1cblxuY29uc3Qgcm91dGluZ1dyaXRlcyA9IG5ldyBNYXA8c3RyaW5nLCBQcm9taXNlPHZvaWQ+PigpO1xuXG4vKiogVGhlIHJvdXRpbmctY29uZmlnIHdyaXRlIHBhdGggLSB0aGUgT05FIHdyaXRlIHRoYXQgY2Fubm90IGdvIHRocm91Z2ggYSBzdG9yZSAoaXQgaXMgd2hhdCBDUkVBVEVTIHRoZSBidWNrZXQgYW5kIGl0cyBzdG9yZXMpLiBTZXJpYWxpemVkIHBlciBidWNrZXQ6IGNvbmN1cnJlbnQgY29uZmlnIHdyaXRlcyB3b3VsZCByYWNlIHRoZSB2ZXJzaW9uIGNoZWNrLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHF1ZXVlUm91dGluZ0NvbmZpZ1dyaXRlKGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nLCBkYXRhOiBCdWZmZXIsIGNvbmZpZz86IHsgbGFzdE1vZGlmaWVkPzogbnVtYmVyIH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhc3NlcnRXcml0ZXNBbGxvd2VkKCk7XG4gICAgbGV0IGtleSA9IGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gO1xuICAgIGxldCBydW4gPSAocm91dGluZ1dyaXRlcy5nZXQoa2V5KSB8fCBQcm9taXNlLnJlc29sdmUoKSkudGhlbigoKSA9PiB3cml0ZVJvdXRpbmdDb25maWcoYWNjb3VudCwgYnVja2V0TmFtZSwgZGF0YSwgY29uZmlnKSk7XG4gICAgcm91dGluZ1dyaXRlcy5zZXQoa2V5LCBydW4udGhlbigoKSA9PiB7IH0sICgpID0+IHsgfSkpO1xuICAgIHJldHVybiBhd2FpdCBydW47XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHdyaXRlUm91dGluZ0NvbmZpZyhhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgZGF0YTogQnVmZmVyLCBjb25maWc/OiB7IGxhc3RNb2RpZmllZD86IG51bWJlciB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IGtleSA9IGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gO1xuICAgIGxldCBpbmNvbWluZyA9IHBhcnNlUm91dGluZ0RhdGEoZGF0YSk7XG4gICAgbGV0IGxvYWRlZCA9IGF3YWl0IGdldExvYWRlZEJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBpZiAoIWxvYWRlZCkge1xuICAgICAgICBhd2FpdCByZXNvbHZlU291cmNlQXJjaGl2ZXMoZ2V0QnVja2V0Rm9sZGVyKGFjY291bnQsIGJ1Y2tldE5hbWUpKS5zZXQoUk9VVElOR19GSUxFLCBkYXRhLCB7IGxhc3RNb2RpZmllZDogY29uZmlnPy5sYXN0TW9kaWZpZWQgfSk7XG4gICAgICAgIGJ1Y2tldHMuc2V0KGtleSwgUHJvbWlzZS5yZXNvbHZlKGJ1aWxkQnVja2V0KGFjY291bnQsIGJ1Y2tldE5hbWUsIGluY29taW5nKSkpO1xuICAgICAgICBicm9hZGNhc3RSb3V0aW5nQ2hhbmdlZCgpO1xuICAgICAgICBjb25zb2xlLmxvZyhgQ3JlYXRlZCBidWNrZXQgJHtrZXl9YCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKEpTT04uc3RyaW5naWZ5KGluY29taW5nKSAhPT0gbG9hZGVkLnJvdXRpbmdKU09OICYmIGdldENvbmZpZ1ZlcnNpb24oaW5jb21pbmcpIDw9IGdldENvbmZpZ1ZlcnNpb24obG9hZGVkLnJvdXRpbmcpKSB7XG4gICAgICAgIGxldCBtZXNzYWdlID0gYENhbm5vdCB1cGRhdGUgcm91dGluZyBjb25maWcgZm9yIGJ1Y2tldCAke2tleX06IHRoZSBuZXcgY29uZmlnIGRpZmZlcnMgZnJvbSB0aGUgY3VycmVudCBvbmUgYnV0IGl0cyB2ZXJzaW9uICgke2dldENvbmZpZ1ZlcnNpb24oaW5jb21pbmcpfSkgaXMgbm90IGdyZWF0ZXIgdGhhbiB0aGUgY3VycmVudCB2ZXJzaW9uICgke2dldENvbmZpZ1ZlcnNpb24obG9hZGVkLnJvdXRpbmcpfSkuIEluY3JlbWVudCB0aGUgdmVyc2lvbiB0byB1cGRhdGUgaXQuIEN1cnJlbnQ6ICR7bG9hZGVkLnJvdXRpbmdKU09OfS4gQXR0ZW1wdGVkOiAke0pTT04uc3RyaW5naWZ5KGluY29taW5nKX1gO1xuICAgICAgICBjb25zb2xlLmVycm9yKG1lc3NhZ2UpO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgfVxuICAgIGxldCBzdG9yZWQgPSBpbmNvbWluZztcbiAgICBsZXQgcmVpbmplY3RlZCA9IDA7XG4gICAgZm9yIChsZXQgaW50ZXJtZWRpYXRlIG9mIGdldEludGVybWVkaWF0ZVNvdXJjZXMoZXhwaXJlSW50ZXJtZWRpYXRlU291cmNlcyhsb2FkZWQucm91dGluZywgRGF0ZS5ub3coKSkpKSB7XG4gICAgICAgIHN0b3JlZCA9IGluamVjdEludGVybWVkaWF0ZVNvdXJjZShzdG9yZWQsIHtcbiAgICAgICAgICAgIHNwbGl0VXJsOiBpbnRlcm1lZGlhdGUuaW50ZXJtZWRpYXRlIHx8IGludGVybWVkaWF0ZS51cmwsXG4gICAgICAgICAgICBpbnRlcm1lZGlhdGVVcmw6IGludGVybWVkaWF0ZS51cmwsXG4gICAgICAgICAgICBzdGFydDogaW50ZXJtZWRpYXRlLnZhbGlkV2luZG93WzBdLFxuICAgICAgICAgICAgZW5kOiBpbnRlcm1lZGlhdGUudmFsaWRXaW5kb3dbMV0sXG4gICAgICAgIH0pO1xuICAgICAgICByZWluamVjdGVkKys7XG4gICAgfVxuICAgIGlmIChKU09OLnN0cmluZ2lmeShzdG9yZWQpICE9PSBKU09OLnN0cmluZ2lmeShpbmNvbWluZykpIHtcbiAgICAgICAgY29uc29sZS5sb2coYFJlLWluamVjdGVkICR7cmVpbmplY3RlZH0gaW4tZmxpZ2h0IHN3aXRjaG92ZXIgd2luZG93cyBpbnRvIHRoZSBpbmNvbWluZyByb3V0aW5nIGNvbmZpZyBmb3IgYnVja2V0ICR7a2V5fSAodmVyc2lvbiAke2dldENvbmZpZ1ZlcnNpb24oaW5jb21pbmcpfSlgKTtcbiAgICB9XG4gICAgLy8gV3JpdHRlbiBzdHJhaWdodCBpbnRvIHRoZSBwbGFpbiBidWNrZXQgZm9sZGVyOiB0aGUgcm91dGluZyBmaWxlIGRlZmluZXMgdGhlIHBlci1yb3V0ZSBzdG9yZXMsIHNvIGl0IG5ldmVyIGZsb3dzIHRocm91Z2ggdGhlbVxuICAgIGF3YWl0IHJlc29sdmVTb3VyY2VBcmNoaXZlcyhnZXRCdWNrZXRGb2xkZXIoYWNjb3VudCwgYnVja2V0TmFtZSkpLnNldChST1VUSU5HX0ZJTEUsIEJ1ZmZlci5mcm9tKHNlcmlhbGl6ZVJlbW90ZUNvbmZpZyhzdG9yZWQpKSwgeyBsYXN0TW9kaWZpZWQ6IGNvbmZpZz8ubGFzdE1vZGlmaWVkIH0pO1xuICAgIGF3YWl0IHNjaGVkdWxlUm91dGluZ1JlbG9hZChhY2NvdW50LCBidWNrZXROYW1lKTtcbn1cblxuLyoqIFdoaWNoIGJ1Y2tldHMgdGhpcyBwcm9jZXNzIGN1cnJlbnRseSBoYXMgbG9hZGVkIC0gd2hhdCBhIGRlcGxveSBzdWNjZXNzb3IgYXNrcyBpdHMgcHJlZGVjZXNzb3IgZm9yLCBzbyBpdCBhY3RpdmF0ZXMgZXhhY3RseSB0aGUgYnVja2V0cyB0aGF0IGFyZSBhY3R1YWxseSBpbiB1c2UuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWN0aXZlQnVja2V0S2V5cygpOiB7IGFjY291bnQ6IHN0cmluZzsgYnVja2V0TmFtZTogc3RyaW5nIH1bXSB7XG4gICAgcmV0dXJuIFsuLi5idWNrZXRzLmtleXMoKV0ubWFwKGtleSA9PiB7XG4gICAgICAgIGxldCBzbGFzaCA9IGtleS5pbmRleE9mKFwiL1wiKTtcbiAgICAgICAgcmV0dXJuIHsgYWNjb3VudDoga2V5LnNsaWNlKDAsIHNsYXNoKSwgYnVja2V0TmFtZToga2V5LnNsaWNlKHNsYXNoICsgMSkgfTtcbiAgICB9KTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYnVpbGRBbGxMb2FkZWRCdWNrZXRzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGZvciAobGV0IGtleSBvZiBbLi4uYnVja2V0cy5rZXlzKCldKSB7XG4gICAgICAgIGxldCBzbGFzaCA9IGtleS5pbmRleE9mKFwiL1wiKTtcbiAgICAgICAgYXdhaXQgc2NoZWR1bGVSb3V0aW5nUmVsb2FkKGtleS5zbGljZSgwLCBzbGFzaCksIGtleS5zbGljZShzbGFzaCArIDEpLCB7IGZvcmNlOiB0cnVlLCByZWFzb246IFwiYWxsIGxvYWRlZCBidWNrZXRzIHdlcmUgYXNrZWQgdG8gcmVidWlsZFwiIH0pO1xuICAgIH1cbn1cblxuY29uc3QgT1dOX0NPTkZJR19XUklURV9USFJPVFRMRSA9IDMwICogMTAwMDtcbmNvbnN0IElOVEVSTUVESUFURV9NQUlOVEFJTl9JTlRFUlZBTCA9IDYwICogMTAwMDtcbi8vIFBlciBidWNrZXQsIG5vdCBnbG9iYWw6IGEgc3dpdGNob3ZlciBoYXMgdG8gd3JpdGUgZXZlcnkgYnVja2V0J3Mgd2luZG93cyBhdCBvbmNlLCBhbmQgYSBzaGFyZWQgdGhyb3R0bGUgd291bGQgbGV0IG9ubHkgb25lIGJ1Y2tldCB0aHJvdWdoIHBlciBpbnRlcnZhbFxuY29uc3QgbGFzdE93bkNvbmZpZ1dyaXRlID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcblxuYXN5bmMgZnVuY3Rpb24gd3JpdGVPd25Sb3V0aW5nQ29uZmlnKGxvYWRlZDogQnVja2V0U3RhdGUsIHVwZGF0ZWQ6IFJlbW90ZUNvbmZpZywgcmVhc29uOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsZXQga2V5ID0gYCR7bG9hZGVkLmFjY291bnR9LyR7bG9hZGVkLmJ1Y2tldE5hbWV9YDtcbiAgICBsZXQgc2luY2VMYXN0ID0gRGF0ZS5ub3coKSAtIChsYXN0T3duQ29uZmlnV3JpdGUuZ2V0KGtleSkgfHwgMCk7XG4gICAgaWYgKHNpbmNlTGFzdCA8IE9XTl9DT05GSUdfV1JJVEVfVEhST1RUTEUpIHtcbiAgICAgICAgY29uc29sZS5sb2coYE5vdCB3cml0aW5nIG91ciBvd24gcm91dGluZyBjb25maWcgdXBkYXRlIGZvciBidWNrZXQgJHtrZXl9ICgke3JlYXNvbn0pOiB0aGUgbGFzdCBvbmUgd2FzICR7c2luY2VMYXN0fW1zIGFnbywgdW5kZXIgdGhlICR7T1dOX0NPTkZJR19XUklURV9USFJPVFRMRX1tcyB0aHJvdHRsZS4gUmV0cnlpbmcgb24gdGhlIG5leHQgbWFpbnRlbmFuY2UgcGFzcy4gV2FudGVkOiAke0pTT04uc3RyaW5naWZ5KHVwZGF0ZWQpfWApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxhc3RPd25Db25maWdXcml0ZS5zZXQoa2V5LCBEYXRlLm5vdygpKTtcbiAgICBsZXQgdmVyc2lvbiA9IG5leHRJbnRlcm1lZGlhdGVWZXJzaW9uKGdldENvbmZpZ1ZlcnNpb24obG9hZGVkLnJvdXRpbmcpKTtcbiAgICBsZXQgbmV4dDogUmVtb3RlQ29uZmlnID0geyAuLi51cGRhdGVkLCB2ZXJzaW9uIH07XG4gICAgY29uc29sZS5sb2coYFdyaXRpbmcgJHtST1VUSU5HX0ZJTEV9IGZvciBidWNrZXQgJHtrZXl9ICgke3JlYXNvbn0pLCB2ZXJzaW9uICR7Z2V0Q29uZmlnVmVyc2lvbihsb2FkZWQucm91dGluZyl9IC0+ICR7dmVyc2lvbn06ICR7SlNPTi5zdHJpbmdpZnkobmV4dCl9YCk7XG4gICAgbGV0IGRhdGEgPSBCdWZmZXIuZnJvbShzZXJpYWxpemVSZW1vdGVDb25maWcobmV4dCkpO1xuICAgIGF3YWl0IHF1ZXVlUm91dGluZ0NvbmZpZ1dyaXRlKGxvYWRlZC5hY2NvdW50LCBsb2FkZWQuYnVja2V0TmFtZSwgZGF0YSk7XG4gICAgYXdhaXQgcHJvcGFnYXRlUm91dGluZ0NvbmZpZyhsb2FkZWQsIG5leHQsIGRhdGEpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBwcm9wYWdhdGVSb3V0aW5nQ29uZmlnKGxvYWRlZDogQnVja2V0U3RhdGUsIG5leHQ6IFJlbW90ZUNvbmZpZywgZGF0YTogQnVmZmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IHRhcmdldHMgPSBuZXcgTWFwPHN0cmluZywgU291cmNlQ29uZmlnPigpO1xuICAgIGZvciAobGV0IHNvdXJjZSBvZiBbLi4ubG9hZGVkLnJvdXRpbmcuc291cmNlcywgLi4ubmV4dC5zb3VyY2VzXSkge1xuICAgICAgICBpZiAodHlwZW9mIHNvdXJjZSA9PT0gXCJzdHJpbmdcIiB8fCBzb3VyY2UuaW50ZXJtZWRpYXRlKSBjb250aW51ZTtcbiAgICAgICAgaWYgKHNvdXJjZS50eXBlID09PSBcInJlbW90ZVwiKSB7XG4gICAgICAgICAgICBsZXQgcGFyc2VkID0gcGFyc2VIb3N0ZWRVcmwoc291cmNlLnVybCk7XG4gICAgICAgICAgICBpZiAocGFyc2VkLmFjY291bnQgIT09IGxvYWRlZC5hY2NvdW50IHx8IHBhcnNlZC5idWNrZXROYW1lICE9PSBsb2FkZWQuYnVja2V0TmFtZSkgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRhcmdldHMuaGFzKHNvdXJjZS51cmwpKSBjb250aW51ZTtcbiAgICAgICAgdGFyZ2V0cy5zZXQoc291cmNlLnVybCwgc291cmNlKTtcbiAgICB9XG4gICAgZm9yIChsZXQgW3VybCwgc291cmNlXSBvZiB0YXJnZXRzKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBjcmVhdGVBcGlBcmNoaXZlcyhzb3VyY2UpLnNldChST1VUSU5HX0ZJTEUsIGRhdGEpO1xuICAgICAgICAgICAgY29uc29sZS5sb2coYFdyb3RlICR7Uk9VVElOR19GSUxFfSBmb3IgYnVja2V0ICR7bG9hZGVkLmFjY291bnR9LyR7bG9hZGVkLmJ1Y2tldE5hbWV9IHRvICR7dXJsfWApO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGBQcm9wYWdhdGluZyBvdXIgcm91dGluZyBjb25maWcgdXBkYXRlIHRvICR7dXJsfSBmYWlsZWQ6ICR7KGUgYXMgRXJyb3IpLnN0YWNrID8/IGV9YCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1haW50YWluSW50ZXJtZWRpYXRlcygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsZXQgeyBkb21haW4sIHBvcnQgfSA9IGdldFN0b3JhZ2VTZXJ2ZXJDb25maWcoKTtcbiAgICBsZXQgdGFrZW92ZXIgPSBnZXRUYWtlb3ZlckludGVybWVkaWF0ZSgpO1xuICAgIGxldCB3cml0dGVuOiBzdHJpbmdbXSA9IFtdO1xuICAgIGxldCBhbHJlYWR5Q29ycmVjdDogc3RyaW5nW10gPSBbXTtcbiAgICBsZXQgbm90T3Vyczogc3RyaW5nW10gPSBbXTtcbiAgICAvLyBPTkxZIGJ1Y2tldHMgYWxyZWFkeSBpbiBtZW1vcnkuIEEgc3dpdGNob3ZlciBtdXN0IG5ldmVyIGxvYWQgYSBidWNrZXQ6IGxvYWRpbmcgc3RhcnRzIGl0cyBzeW5jaHJvbml6YXRpb24sIGFuZCBidWNrZXRzIG5vdGhpbmcgaGFzIHRvdWNoZWQgKGxlZ2FjeSBvbmVzIGVzcGVjaWFsbHkpIGhhdmUgbm8gd3JpdGVzIHRvIGhhbmQgb2ZmIGluIHRoZSBmaXJzdCBwbGFjZS4gT25lIHRoYXQgZG9lcyBnZXQgdXNlZCBtaWQtc3dpdGNob3ZlciBsb2FkcyBvbiB0aGF0IGFjY2VzcywgYW5kIHRoZSBuZXh0IHBhc3MgZ2l2ZXMgaXQgaXRzIHdpbmRvdy5cbiAgICBsZXQga2V5cyA9IFsuLi5idWNrZXRzLmtleXMoKV07XG4gICAgZm9yIChsZXQga2V5IG9mIGtleXMpIHtcbiAgICAgICAgbGV0IGxvYWRlZFByb21pc2UgPSBidWNrZXRzLmdldChrZXkpO1xuICAgICAgICBpZiAoIWxvYWRlZFByb21pc2UpIGNvbnRpbnVlO1xuICAgICAgICBsZXQgbG9hZGVkID0gYXdhaXQgbG9hZGVkUHJvbWlzZS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgICAgICBpZiAoIWxvYWRlZCkgY29udGludWU7XG4gICAgICAgIGxldCBleHBpcmVkID0gZXhwaXJlSW50ZXJtZWRpYXRlU291cmNlcyhsb2FkZWQucm91dGluZywgRGF0ZS5ub3coKSk7XG4gICAgICAgIGlmIChKU09OLnN0cmluZ2lmeShleHBpcmVkKSAhPT0gSlNPTi5zdHJpbmdpZnkobG9hZGVkLnJvdXRpbmcpKSB7XG4gICAgICAgICAgICBhd2FpdCB3cml0ZU93blJvdXRpbmdDb25maWcobG9hZGVkLCBleHBpcmVkLCBgc3dpdGNob3ZlciB3aW5kb3dzIGV4cGlyZWQgbW9yZSB0aGFuICR7SU5URVJNRURJQVRFX0VYUElSRV9HUkFDRSAvIDEwMDB9cyBhZ29gKTtcbiAgICAgICAgICAgIHdyaXR0ZW4ucHVzaChrZXkpO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0YWtlb3ZlcikgY29udGludWU7XG4gICAgICAgIGxldCBtYWluVXJsID0gbG9hZGVkLnJvdXRpbmcuc291cmNlcy5maW5kKHggPT4ge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiB4ID09PSBcInN0cmluZ1wiIHx8IHgudHlwZSAhPT0gXCJyZW1vdGVcIiB8fCB4LmludGVybWVkaWF0ZSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgbGV0IHBhcnNlZCA9IHBhcnNlSG9zdGVkVXJsKHgudXJsKTtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZWQuYWRkcmVzcyA9PT0gZG9tYWluICYmIHBhcnNlZC5wb3J0ID09PSBwb3J0O1xuICAgICAgICB9KSBhcyBIb3N0ZWRDb25maWcgfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmICghbWFpblVybCkge1xuICAgICAgICAgICAgbm90T3Vycy5wdXNoKGtleSk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgaW5qZWN0ZWQgPSBpbmplY3RJbnRlcm1lZGlhdGVTb3VyY2UobG9hZGVkLnJvdXRpbmcsIHtcbiAgICAgICAgICAgIHNwbGl0VXJsOiBtYWluVXJsLnVybCxcbiAgICAgICAgICAgIGludGVybWVkaWF0ZVVybDogcmVwbGFjZUhvc3RlZFVybFBvcnQobWFpblVybC51cmwsIHRha2VvdmVyLmFsdFBvcnQpLFxuICAgICAgICAgICAgc3RhcnQ6IHRha2VvdmVyLnN0YXJ0LFxuICAgICAgICAgICAgZW5kOiB0YWtlb3Zlci5lbmQsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoSlNPTi5zdHJpbmdpZnkoaW5qZWN0ZWQpID09PSBKU09OLnN0cmluZ2lmeShsb2FkZWQucm91dGluZykpIHtcbiAgICAgICAgICAgIGFscmVhZHlDb3JyZWN0LnB1c2goa2V5KTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHdyaXRlT3duUm91dGluZ0NvbmZpZyhsb2FkZWQsIGluamVjdGVkLCBgd2UgYXJlIGEgZGVwbG95IHN1Y2Nlc3Nvcjogd3JpdGVzIHJvdXRlIHRvIG91ciBhbHRlcm5hdGUgcG9ydCAke3Rha2VvdmVyLmFsdFBvcnR9IGZyb20gJHtuZXcgRGF0ZSh0YWtlb3Zlci5zdGFydCkudG9JU09TdHJpbmcoKX0gdW50aWwgb3VyIHByZWRlY2Vzc29yIGlzIGtpbGxlZCBhdCAke25ldyBEYXRlKHRha2VvdmVyLmVuZCkudG9JU09TdHJpbmcoKX1gKTtcbiAgICAgICAgd3JpdHRlbi5wdXNoKGtleSk7XG4gICAgfVxuICAgIGlmICghdGFrZW92ZXIpIHJldHVybjtcbiAgICBpZiAoIWtleXMubGVuZ3RoKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBObyBhY3RpdmUgYnVja2V0cywgc28gbm8gY29uZmlnIGZpbGVzIHRvIHdyaXRlIHRoZSBpbnRlcm1lZGlhdGUgaW50byAoYSBidWNrZXQgaXMgb25seSBhY3RpdmUgb25jZSBzb21ldGhpbmcgdXNlcyBpdClgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIXdyaXR0ZW4ubGVuZ3RoKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBXcm90ZSBubyBjb25maWcgZmlsZXM6IG9mICR7a2V5cy5sZW5ndGh9IGFjdGl2ZSBidWNrZXRzLCAke2FscmVhZHlDb3JyZWN0Lmxlbmd0aH0gYWxyZWFkeSBjb250YWluIHRoZSBpbnRlcm1lZGlhdGUgYW5kICR7bm90T3Vycy5sZW5ndGh9IGFyZSBub3QgaG9zdGVkIGJ5IHVzYCk7XG4gICAgfVxufVxuXG4vKiogT3VyIHByZWRlY2Vzc29yIHN0aWxsIGhvbGRzIHRoZSBtYWluIHBvcnQgYW5kIGhhcyBiZWVuIHNlcnZpbmcgYWxsIGFsb25nLCBzbyBpdCAtIG5vdCB1cyAtIGtub3dzIHdoaWNoIGJ1Y2tldHMgYXJlIGluIHVzZS4gV2UgYWN0aXZhdGUgZXhhY3RseSB0aG9zZSwgd2hpY2ggaXMgd2hhdCBtYWtlcyB0aGVpciBjb25maWcgZmlsZXMgZ2V0IHRoZSBpbnRlcm1lZGlhdGU7IG5vdGhpbmcgZWxzZSBvbiBkaXNrIGlzIHRvdWNoZWQuICovXG5hc3luYyBmdW5jdGlvbiBhY3RpdmF0ZVByZWRlY2Vzc29yQnVja2V0cygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsZXQgeyBkb21haW4sIHBvcnQgfSA9IGdldFN0b3JhZ2VTZXJ2ZXJDb25maWcoKTtcbiAgICBsZXQgdXJsID0gYGh0dHBzOi8vJHtkb21haW59OiR7cG9ydH1gO1xuICAgIGxldCBrZXlzOiB7IGFjY291bnQ6IHN0cmluZzsgYnVja2V0TmFtZTogc3RyaW5nIH1bXTtcbiAgICB0cnkge1xuICAgICAgICBrZXlzID0gYXdhaXQgbGlzdFNlcnZlckFjdGl2ZUJ1Y2tldEtleXMoeyB1cmwgfSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBDb3VsZCBub3QgYXNrIG91ciBwcmVkZWNlc3NvciBvbiAke3VybH0gd2hpY2ggYnVja2V0cyBhcmUgYWN0aXZlLCBzbyBvbmx5IGJ1Y2tldHMgdXNlZCBvbiB0aGlzIHByb2Nlc3MgZ2V0IHRoZSBpbnRlcm1lZGlhdGU6ICR7KGUgYXMgRXJyb3IpLnN0YWNrID8/IGV9YCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKCFrZXlzLmxlbmd0aCkge1xuICAgICAgICBjb25zb2xlLmxvZyhgT3VyIHByZWRlY2Vzc29yIG9uICR7dXJsfSBoYXMgbm8gYWN0aXZlIGJ1Y2tldHMsIHNvIHRoZXJlIGFyZSBubyBjb25maWcgZmlsZXMgdG8gd3JpdGUgdGhlIGludGVybWVkaWF0ZSBpbnRvYCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc29sZS5sb2coYE91ciBwcmVkZWNlc3NvciBvbiAke3VybH0gaGFzICR7a2V5cy5sZW5ndGh9IGFjdGl2ZSBidWNrZXRzLCBhY3RpdmF0aW5nIHRoZW0gaGVyZSBzbyB0aGVpciBjb25maWcgZmlsZXMgZ2V0IHRoZSBpbnRlcm1lZGlhdGU6ICR7a2V5cy5tYXAoeCA9PiBgJHt4LmFjY291bnR9LyR7eC5idWNrZXROYW1lfWApLmpvaW4oXCIsIFwiKX1gKTtcbiAgICBmb3IgKGxldCB7IGFjY291bnQsIGJ1Y2tldE5hbWUgfSBvZiBrZXlzKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBnZXRMb2FkZWRCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEFjdGl2YXRpbmcgYnVja2V0ICR7YWNjb3VudH0vJHtidWNrZXROYW1lfSAoYWN0aXZlIG9uIG91ciBwcmVkZWNlc3NvcikgZmFpbGVkOiAkeyhlIGFzIEVycm9yKS5zdGFjayA/PyBlfWApO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKiogU3RhcnRlZCBieSBkZXBsb3lUYWtlb3ZlciBvbmNlIHdlIGFyZSBhY3R1YWxseSBhIGRlcGxveSBzdWNjZXNzb3IgbGlzdGVuaW5nIG9uIGFuIGFsdGVybmF0ZSBwb3J0LiBVbnRpbCB0aGVuIHRoZXJlIGFyZSBubyBzd2l0Y2hvdmVyIHdpbmRvd3MgdG8gd3JpdGUgb3IgZXhwaXJlLCBzbyBub3RoaW5nIHBvbGxzLiAqL1xuZXhwb3J0IGNvbnN0IHN0YXJ0SW50ZXJtZWRpYXRlTWFpbnRlbmFuY2UgPSBsYXp5KCgpID0+IHtcbiAgICB2b2lkIChhc3luYyAoKSA9PiB7XG4gICAgICAgIGF3YWl0IGFjdGl2YXRlUHJlZGVjZXNzb3JCdWNrZXRzKCk7XG4gICAgICAgIGF3YWl0IG1haW50YWluSW50ZXJtZWRpYXRlcygpO1xuICAgIH0pKCkuY2F0Y2goKGU6IEVycm9yKSA9PiBjb25zb2xlLmVycm9yKGBXcml0aW5nIHRoZSBpbnRlcm1lZGlhdGUgaW50byB0aGUgY29uZmlnIGZpbGVzIGZhaWxlZDogJHtlLnN0YWNrID8/IGV9YCkpO1xuICAgIHJ1bkluZmluaXRlUG9sbChJTlRFUk1FRElBVEVfTUFJTlRBSU5fSU5URVJWQUwsIG1haW50YWluSW50ZXJtZWRpYXRlcyk7XG59KTtcblxuZXhwb3J0IHR5cGUgU2VydmVyQnVja2V0SW5mbyA9IHtcbiAgICBidWNrZXROYW1lOiBzdHJpbmc7XG4gICAgYWN0aXZlOiBib29sZWFuO1xuICAgIC8qKiBXaGVyZSB0aGUgYnVja2V0J3MgZGF0YSBsaXZlcyBvbiB0aGlzIHNlcnZlciAqL1xuICAgIGZvbGRlcjogc3RyaW5nO1xuICAgIC8qKiBUaGUgZHJpdmUgdGhhdCBmb2xkZXIgaXMgb24uIEJ1Y2tldHMgc2hhcmluZyBhIGRyaXZlIHJlcG9ydCB0aGUgc2FtZSBudW1iZXJzLiAqL1xuICAgIGRpc2s/OiBCdWNrZXREaXNrSW5mbztcbiAgICBkaXNrRXJyb3I/OiBzdHJpbmc7XG4gICAgd3JpdGVTdGF0cz86IEJ1Y2tldFdyaXRlU3RhdHM7XG4gICAgY29uZmlnPzogQXJjaGl2ZXNDb25maWc7XG4gICAgZXJyb3I/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgdHlwZSBBY3RpdmVCdWNrZXRJbmZvID0ge1xuICAgIGZvbGRlcjogc3RyaW5nO1xuICAgIC8qKiBUaGUgcm91dGluZyBjb25maWcgdGhlIGJ1Y2tldCBpcyBSVU5OSU5HIG9uLCBzdHJhaWdodCBmcm9tIG1lbW9yeSAtIGluY2x1ZGluZyBzd2l0Y2hvdmVyIHdpbmRvd3Mgd3JpdHRlbiBzaW5jZSBpdCBsb2FkZWQgKi9cbiAgICByb3V0aW5nOiBSZW1vdGVDb25maWc7XG4gICAgLyoqIE91ciBvd24gZW50cmllcyBpbiB0aGF0IGNvbmZpZywgYW5kIHRoZWlyIHN1bW1hcml6ZWQgY3VycmVudCByb2xlIChyb3V0ZXMgdW5pb24gKyBmbGFncykgKi9cbiAgICBzZWxmRW50cmllczogSG9zdGVkQ29uZmlnW107XG4gICAgc2VsZj86IFNlbGZTdW1tYXJ5O1xuICAgIGNvbmZpZzogQXJjaGl2ZXNDb25maWc7XG59O1xuXG5mdW5jdGlvbiB0b0FjdGl2ZUJ1Y2tldEluZm8obG9hZGVkOiBCdWNrZXRTdGF0ZSk6IEFjdGl2ZUJ1Y2tldEluZm8ge1xuICAgIHJldHVybiB7XG4gICAgICAgIGZvbGRlcjogZ2V0QnVja2V0Rm9sZGVyKGxvYWRlZC5hY2NvdW50LCBsb2FkZWQuYnVja2V0TmFtZSksXG4gICAgICAgIHJvdXRpbmc6IGxvYWRlZC5yb3V0aW5nLFxuICAgICAgICBzZWxmRW50cmllczogbG9hZGVkLnNlbGZFbnRyaWVzLFxuICAgICAgICBzZWxmOiBsb2FkZWQuc2VsZixcbiAgICAgICAgY29uZmlnOiBnZXRCdWNrZXRDb25maWcobG9hZGVkKSxcbiAgICB9O1xufVxuXG4vKiogVGhlIGxpdmUgaW4tbWVtb3J5IHN0YXRlIG9mIE9ORSBidWNrZXQsIGFuc3dlcmVkIHdpdGhvdXQgdG91Y2hpbmcgdGhlIGRpc2sgKG5vIHJvdXRpbmcgZmlsZSByZWFkLCBubyBzdGF0ZnMsIG5vIHN0b3JlZCB3cml0ZSBzdGF0cykuIFJldHVybnMgYW4gZXJyb3Igc3RyaW5nIHdoZW4gdGhlIGJ1Y2tldCBpcyBub3QgbG9hZGVkIGhlcmUsIHdoaWNoIGlzIHRoZSBub3JtYWwgc3RhdGUgZm9yIGEgYnVja2V0IG5vdGhpbmcgaGFzIGFjY2Vzc2VkIHNpbmNlIHN0YXJ0dXAuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0QWN0aXZlQnVja2V0KGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTxBY3RpdmVCdWNrZXRJbmZvIHwgc3RyaW5nPiB7XG4gICAgbGV0IGtleSA9IGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gO1xuICAgIGxldCBsb2FkZWRQcm9taXNlID0gYnVja2V0cy5nZXQoa2V5KTtcbiAgICBpZiAoIWxvYWRlZFByb21pc2UpIHtcbiAgICAgICAgcmV0dXJuIGBCdWNrZXQgJHtrZXl9IGlzIG5vdCBsb2FkZWQgb24gdGhpcyBzZXJ2ZXIsIHNvIGl0IGhhcyBubyBsaXZlIHN0YXRlIChpdCBsb2FkcyBvbiBmaXJzdCBhY2Nlc3MpYDtcbiAgICB9XG4gICAgbGV0IGxvYWRlZDogQnVja2V0U3RhdGUgfCB1bmRlZmluZWQ7XG4gICAgdHJ5IHtcbiAgICAgICAgbG9hZGVkID0gYXdhaXQgbG9hZGVkUHJvbWlzZTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiBgQnVja2V0ICR7a2V5fSBmYWlsZWQgdG8gbG9hZCBvbiB0aGlzIHNlcnZlcjogJHtTdHJpbmcoKGUgYXMgRXJyb3IpLnN0YWNrID8/IGUpLnNsaWNlKDAsIDUwMCl9YDtcbiAgICB9XG4gICAgaWYgKCFsb2FkZWQpIHtcbiAgICAgICAgcmV0dXJuIGBCdWNrZXQgJHtrZXl9IGRvZXMgbm90IGV4aXN0IG9uIHRoaXMgc2VydmVyYDtcbiAgICB9XG4gICAgcmV0dXJuIHRvQWN0aXZlQnVja2V0SW5mbyhsb2FkZWQpO1xufVxuXG4vKiogTG9hZHMgYSBidWNrZXQgdGhhdCBleGlzdHMgb24gdGhpcyBzZXJ2ZXIncyBkaXNrIGludG8gbWVtb3J5LCB3aGljaCBzdGFydHMgaXRzIHN5bmNocm9uaXphdGlvbiBhbmQgd2luZG93IHRpbWVycywgYW5kIHJldHVybnMgaXRzIGxpdmUgc3RhdGUuIE5vdGhpbmcgaXMgd3JpdHRlbiBhbmQgbm8gb3RoZXIgc2VydmVyIGlzIGNvbnRhY3RlZCAtIHVubGlrZSBidWlsZGluZyBhbiBBcmNoaXZlc0NoYWluIGZvciBpdCwgd2hpY2ggd291bGQgcHJvYmUgZXZlcnkgc291cmNlIGFuZCBjb3VsZCB3cml0ZSB0aGUgcm91dGluZyBjb25maWcuIEFscmVhZHktbG9hZGVkIGJ1Y2tldHMganVzdCByZXR1cm4gdGhlaXIgc3RhdGUuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYWN0aXZhdGVCdWNrZXQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPEFjdGl2ZUJ1Y2tldEluZm8gfCBzdHJpbmc+IHtcbiAgICBsZXQga2V5ID0gYCR7YWNjb3VudH0vJHtidWNrZXROYW1lfWA7XG4gICAgbGV0IHdhc0xvYWRlZCA9IGJ1Y2tldHMuaGFzKGtleSk7XG4gICAgbGV0IGxvYWRlZDogQnVja2V0U3RhdGUgfCB1bmRlZmluZWQ7XG4gICAgdHJ5IHtcbiAgICAgICAgbG9hZGVkID0gYXdhaXQgZ2V0TG9hZGVkQnVja2V0KGFjY291bnQsIGJ1Y2tldE5hbWUpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIGBCdWNrZXQgJHtrZXl9IGZhaWxlZCB0byBsb2FkIG9uIHRoaXMgc2VydmVyOiAke1N0cmluZygoZSBhcyBFcnJvcikuc3RhY2sgPz8gZSkuc2xpY2UoMCwgNTAwKX1gO1xuICAgIH1cbiAgICBpZiAoIWxvYWRlZCkge1xuICAgICAgICByZXR1cm4gYEJ1Y2tldCAke2tleX0gZG9lcyBub3QgZXhpc3Qgb24gdGhpcyBzZXJ2ZXIgKG5vIHJvdXRpbmcgZmlsZSBpbiAke2dldEJ1Y2tldEZvbGRlcihhY2NvdW50LCBidWNrZXROYW1lKX0pYDtcbiAgICB9XG4gICAgLy8gV2FpdCBmb3IgdGhlIGluZGV4ZXMgdG8gbG9hZCwgc28gdGhlIHRvdGFscyB3ZSByZXR1cm4gYXJlIHRoZSByZWFsIG9uZXMgcmF0aGVyIHRoYW4gemVyb2VzIGZyb20gc3RvcmVzIHRoYXQgaGF2ZSBub3QgcmVhZCB0aGVpciBpbmRleCB5ZXQuIFRoZSBzb3VyY2Ugc2NhbnMga2VlcCBydW5uaW5nIGluIHRoZSBiYWNrZ3JvdW5kLlxuICAgIGZvciAobGV0IHMgb2YgbG9hZGVkLnN0b3Jlcykge1xuICAgICAgICBpZiAocy5zdG9yZSBpbnN0YW5jZW9mIEJsb2JTdG9yZSkge1xuICAgICAgICAgICAgYXdhaXQgcy5zdG9yZS5pbml0KCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKCF3YXNMb2FkZWQpIHtcbiAgICAgICAgY29uc29sZS5sb2coYEFjdGl2YXRlZCBidWNrZXQgJHtrZXl9IG9uIHJlcXVlc3Q6IGl0IGlzIG5vdyBsb2FkZWQgYW5kIHN5bmNocm9uaXppbmdgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRvQWN0aXZlQnVja2V0SW5mbyhsb2FkZWQpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbGlzdEFjY291bnRCdWNrZXRzKGFjY291bnQ6IHN0cmluZyk6IFByb21pc2U8U2VydmVyQnVja2V0SW5mb1tdPiB7XG4gICAgbGV0IHN0YXJ0ID0gRGF0ZS5ub3coKTtcbiAgICBsZXQgdGltaW5ncyA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG4gICAgYXN5bmMgZnVuY3Rpb24gdGltZWQ8VD4obmFtZTogc3RyaW5nLCBydW46ICgpID0+IFByb21pc2U8VD4pOiBQcm9taXNlPFQ+IHtcbiAgICAgICAgbGV0IGJlZ2FuID0gRGF0ZS5ub3coKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiBhd2FpdCBydW4oKTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgIHRpbWluZ3Muc2V0KG5hbWUsICh0aW1pbmdzLmdldChuYW1lKSB8fCAwKSArIChEYXRlLm5vdygpIC0gYmVnYW4pKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBsZXQgYWNjb3VudEZvbGRlciA9IHBhdGguam9pbihnZXRTdG9yYWdlU2VydmVyQ29uZmlnKCkuZm9sZGVyLCBcImJ1Y2tldHMyXCIsIGFjY291bnQpO1xuICAgIGxldCBuYW1lczogc3RyaW5nW107XG4gICAgdHJ5IHtcbiAgICAgICAgbmFtZXMgPSBhd2FpdCB0aW1lZChcInJlYWRkaXJcIiwgKCkgPT4gZnMucHJvbWlzZXMucmVhZGRpcihhY2NvdW50Rm9sZGVyKSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgLy8gUGVyLXJvdXRlIGZvbGRlcnMgKGJ1Y2tldE5hbWUtcm91dGUtPHN0YXJ0Pi08ZW5kPikgYmVsb25nIHRvIHRoZSBzYW1lIGJ1Y2tldCBhcyB0aGUgcGxhaW4gZm9sZGVyIC0gY29sbGFwc2UgdGhlbSBzbyBvbmUgYnVja2V0IGxpc3RzIG9uY2VcbiAgICBuYW1lcyA9IFsuLi5uZXcgU2V0KG5hbWVzLm1hcCh4ID0+IHgucmVwbGFjZSgvLXJvdXRlLVtcXGQuXSstW1xcZC5dKyQvLCBcIlwiKSkpXTtcbiAgICB0cnkge1xuICAgICAgICByZXR1cm4gYXdhaXQgUHJvbWlzZS5hbGwobmFtZXMubWFwKGFzeW5jIGJ1Y2tldE5hbWUgPT4ge1xuICAgICAgICAgICAgbGV0IGtleSA9IGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gO1xuICAgICAgICAgICAgbGV0IGZvbGRlciA9IGdldEJ1Y2tldEZvbGRlcihhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICAgICAgICAgIGxldCBiYXNlOiBTZXJ2ZXJCdWNrZXRJbmZvID0geyBidWNrZXROYW1lLCBhY3RpdmU6IGZhbHNlLCBmb2xkZXIgfTtcbiAgICAgICAgICAgIGJhc2UuZGlzayA9IGF3YWl0IHRpbWVkKFwic3RhdGZzXCIsICgpID0+IGdldERpc2tJbmZvKGZvbGRlcikpLmNhdGNoKChlOiBFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGJhc2UuZGlza0Vycm9yID0gU3RyaW5nKGUuc3RhY2sgPz8gZSkuc2xpY2UoMCwgNTAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBiYXNlLndyaXRlU3RhdHMgPSBnZXRCdWNrZXRXcml0ZVN0YXRzKGtleSk7XG4gICAgICAgICAgICBjb25zdCBsb2FkZWRQcm9taXNlID0gYnVja2V0cy5nZXQoa2V5KTtcbiAgICAgICAgICAgIGlmIChsb2FkZWRQcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGxvYWRlZCA9IGF3YWl0IHRpbWVkKFwiYXdhaXRMb2FkZWRcIiwgKCkgPT4gbG9hZGVkUHJvbWlzZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsb2FkZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IC4uLmJhc2UsIGFjdGl2ZTogdHJ1ZSwgY29uZmlnOiBnZXRCdWNrZXRDb25maWcobG9hZGVkKSB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4geyAuLi5iYXNlLCBhY3RpdmU6IHRydWUsIGVycm9yOiBTdHJpbmcoKGUgYXMgRXJyb3IpLnN0YWNrID8/IGUpLnNsaWNlKDAsIDUwMCkgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aW1lZChcInJlYWRSb3V0aW5nRmlsZVwiLCAoKSA9PiByZWFkUm91dGluZ0ZpbGUoZm9sZGVyKSk7XG4gICAgICAgICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7IC4uLmJhc2UsIGVycm9yOiBgTm8gcm91dGluZyBmaWxlICgke1JPVVRJTkdfRklMRX0pYCB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgcGFyc2VkID0gYXdhaXQgdGltZWQoXCJwYXJzZVJvdXRpbmdcIiwgYXN5bmMgKCkgPT4gcGFyc2VSb3V0aW5nRGF0YShkYXRhKSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgLi4uYmFzZSwgY29uZmlnOiB7IHJlbW90ZUNvbmZpZzogcGFyc2VkIH0gfTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyAuLi5iYXNlLCBlcnJvcjogU3RyaW5nKChlIGFzIEVycm9yKS5zdGFjayA/PyBlKS5zbGljZSgwLCA1MDApIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgICAvLyBUaGUgcGFydHMgcnVuIGNvbmN1cnJlbnRseSwgc28gdGhlc2UgYXJlIHN1bW1lZCB3YWxsIHRpbWVzIHBlciBwYXJ0LCBub3QgYSBicmVha2Rvd24gb2YgdGhlIHRvdGFsXG4gICAgICAgIGxldCBwYXJ0cyA9IFsuLi50aW1pbmdzXS5tYXAoKFtuYW1lLCBtc10pID0+IGAke25hbWV9ICR7bXN9bXNgKS5qb2luKFwiLCBcIik7XG4gICAgICAgIGNvbnNvbGUubG9nKGBsaXN0QWNjb3VudEJ1Y2tldHMoJHthY2NvdW50fSkgdG9vayAke0RhdGUubm93KCkgLSBzdGFydH1tcyBmb3IgJHtuYW1lcy5sZW5ndGh9IGJ1Y2tldHM6ICR7cGFydHN9YCk7XG4gICAgfVxufVxuXG5leHBvcnQgdHlwZSBCdWNrZXRXcml0ZVN0YXRzID0ge1xuICAgIC8qKiBFdmVyeSBzZXQgY2FsbCB0aGUgYnVja2V0IGFjY2VwdGVkICovXG4gICAgb3JpZ2luYWxXcml0ZXM6IG51bWJlcjtcbiAgICBvcmlnaW5hbEJ5dGVzOiBudW1iZXI7XG4gICAgLyoqIFdoYXQgYWN0dWFsbHkgcmVhY2hlZCB0aGUgc291cmNlcy4gRmFzdCB3cml0ZXMgY29hbGVzY2UgcmVwZWF0ZWQgd3JpdGVzIHRvIHRoZSBzYW1lIGtleSwgc28gdGhpcyBpcyBsb3dlciB0aGFuIHRoZSBvcmlnaW5hbCBjb3VudHMgKGFuZCBpcyB3aGF0IHRoZSBkaXNrIGFjdHVhbGx5IGRpZCkuICovXG4gICAgZmx1c2hlZFdyaXRlczogbnVtYmVyO1xuICAgIGZsdXNoZWRCeXRlczogbnVtYmVyO1xufTtcbmZ1bmN0aW9uIGVtcHR5V3JpdGVTdGF0cygpOiBCdWNrZXRXcml0ZVN0YXRzIHtcbiAgICByZXR1cm4geyBvcmlnaW5hbFdyaXRlczogMCwgb3JpZ2luYWxCeXRlczogMCwgZmx1c2hlZFdyaXRlczogMCwgZmx1c2hlZEJ5dGVzOiAwIH07XG59XG5cbi8vIEluIG1lbW9yeSBvbmx5OiB0b3RhbHMgc2luY2UgdGhpcyBwcm9jZXNzIHN0YXJ0ZWQgKG9yIHRoZSBsYXN0IGNsZWFyV3JpdGVTdGF0cykuIFBlcnNpc3RpbmcgdGhlbSB0byBkaXNrIHdhcyBtb3JlIG1hY2hpbmVyeSB0aGFuIHRoZSBudW1iZXJzIHdlcmUgd29ydGguXG5jb25zdCB3cml0ZVN0YXRzID0gbmV3IE1hcDxzdHJpbmcsIEJ1Y2tldFdyaXRlU3RhdHM+KCk7XG5cbmZ1bmN0aW9uIGNvdW50QnVja2V0V3JpdGUoa2V5OiBzdHJpbmcsIGtpbmQ6IFwib3JpZ2luYWxcIiB8IFwiZmx1c2hlZFwiLCBieXRlczogbnVtYmVyKTogdm9pZCB7XG4gICAgbGV0IHN0YXRzID0gd3JpdGVTdGF0cy5nZXQoa2V5KTtcbiAgICBpZiAoIXN0YXRzKSB7XG4gICAgICAgIHN0YXRzID0gZW1wdHlXcml0ZVN0YXRzKCk7XG4gICAgICAgIHdyaXRlU3RhdHMuc2V0KGtleSwgc3RhdHMpO1xuICAgIH1cbiAgICBpZiAoa2luZCA9PT0gXCJvcmlnaW5hbFwiKSB7XG4gICAgICAgIHN0YXRzLm9yaWdpbmFsV3JpdGVzKys7XG4gICAgICAgIHN0YXRzLm9yaWdpbmFsQnl0ZXMgKz0gYnl0ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgc3RhdHMuZmx1c2hlZFdyaXRlcysrO1xuICAgICAgICBzdGF0cy5mbHVzaGVkQnl0ZXMgKz0gYnl0ZXM7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBnZXRCdWNrZXRXcml0ZVN0YXRzKGtleTogc3RyaW5nKTogQnVja2V0V3JpdGVTdGF0cyB7XG4gICAgcmV0dXJuIHdyaXRlU3RhdHMuZ2V0KGtleSkgfHwgZW1wdHlXcml0ZVN0YXRzKCk7XG59XG5cbi8qKiBaZXJvZXMgdGhlIHdyaXRlIHN0YXRpc3RpY3Mgb2YgZXZlcnkgYnVja2V0IGluIHRoZSBhY2NvdW50LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsZWFyQWNjb3VudFdyaXRlU3RhdHMoYWNjb3VudDogc3RyaW5nKTogbnVtYmVyIHtcbiAgICBsZXQgcHJlZml4ID0gYCR7YWNjb3VudH0vYDtcbiAgICBsZXQgY2xlYXJlZCA9IDA7XG4gICAgZm9yIChsZXQga2V5IG9mIFsuLi53cml0ZVN0YXRzLmtleXMoKV0pIHtcbiAgICAgICAgaWYgKCFrZXkuc3RhcnRzV2l0aChwcmVmaXgpKSBjb250aW51ZTtcbiAgICAgICAgd3JpdGVTdGF0cy5kZWxldGUoa2V5KTtcbiAgICAgICAgY2xlYXJlZCsrO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZyhgQ2xlYXJlZCB0aGUgd3JpdGUgc3RhdGlzdGljcyBvZiAke2NsZWFyZWR9IGJ1Y2tldHMgaW4gYWNjb3VudCAke2FjY291bnR9YCk7XG4gICAgcmV0dXJuIGNsZWFyZWQ7XG59XG5cbmNvbnN0IExBUkdFX0ZJTEVfUEFSVF9TSVpFID0gOCAqIDEwMjQgKiAxMDI0O1xuXG4vLyBXcmFwcyBhIGxvY2FsbHkgaG9zdGVkIGJ1Y2tldCBpbiB0aGUgSUFyY2hpdmVzIGludGVyZmFjZSwgc28gY29kZSB3cml0dGVuIGFnYWluc3QgSUFyY2hpdmVzICh0aGUgY2hhaW4sIHN5bmMgc291cmNlcywgaG9sZGVyIHJlYWRzKSB0YWxrcyB0byBpdCBkaXJlY3RseSBpbnN0ZWFkIG9mIGJlY29taW5nIGEgbmV0d29yayBjbGllbnQgdG8gb3Vyc2VsdmVzLlxuY2xhc3MgQnVja2V0SUFyY2hpdmVzV3JhcHBlciBpbXBsZW1lbnRzIElBcmNoaXZlcyB7XG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBhY2NvdW50OiBzdHJpbmcsIHByaXZhdGUgYnVja2V0TmFtZTogc3RyaW5nLCBwcml2YXRlIHNvdXJjZUNvbmZpZzogU291cmNlQ29uZmlnKSB7IH1cblxuICAgIHByaXZhdGUgZmluZFN0b3JlKCk6IFByb21pc2U8TG9hZGVkU3RvcmU+IHtcbiAgICAgICAgcmV0dXJuIGZpbmRCdWNrZXRTdG9yZSh0aGlzLmFjY291bnQsIHRoaXMuYnVja2V0TmFtZSwgdGhpcy5zb3VyY2VDb25maWcpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXREZWJ1Z05hbWUoKSB7XG4gICAgICAgIHJldHVybiBgbG9jYWxCdWNrZXQgYWNjb3VudCAke3RoaXMuYWNjb3VudH0gYnVja2V0ICR7dGhpcy5idWNrZXROYW1lfSByb3V0ZSAke0pTT04uc3RyaW5naWZ5KHRoaXMuc291cmNlQ29uZmlnLnJvdXRlIHx8IEZVTExfUk9VVEUpfWA7XG4gICAgfVxuICAgIHB1YmxpYyBhc3luYyBnZXQoZmlsZU5hbWU6IHN0cmluZywgY29uZmlnPzogR2V0Q29uZmlnKTogUHJvbWlzZTxCdWZmZXIgfCB1bmRlZmluZWQ+IHtcbiAgICAgICAgbGV0IHJlc3VsdCA9IGF3YWl0IHRoaXMuZ2V0MihmaWxlTmFtZSwgY29uZmlnKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCAmJiByZXN1bHQuZGF0YSB8fCB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHB1YmxpYyBhc3luYyBnZXQyKGZpbGVOYW1lOiBzdHJpbmcsIGNvbmZpZz86IEdldENvbmZpZyk6IFByb21pc2U8eyBkYXRhOiBCdWZmZXI7IHdyaXRlVGltZTogbnVtYmVyOyBzaXplOiBudW1iZXIgfSB8IHVuZGVmaW5lZD4ge1xuICAgICAgICBpZiAoZmlsZU5hbWUgPT09IFJPVVRJTkdfRklMRSkge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGdldFJvdXRpbmdGaWxlUmVzdWx0KHRoaXMuYWNjb3VudCwgdGhpcy5idWNrZXROYW1lKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY29uZmlnPy5pbnRlcm5hbCkge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHJlYWRCdWNrZXRJbnRlcm5hbCh0aGlzLmFjY291bnQsIHRoaXMuYnVja2V0TmFtZSwgeyBwYXRoOiBmaWxlTmFtZSwgcmFuZ2U6IGNvbmZpZy5yYW5nZSwgaW5jbHVkZVRvbWJzdG9uZXM6IGNvbmZpZy5pbmNsdWRlVG9tYnN0b25lcyB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXdhaXQgKGF3YWl0IHRoaXMuZmluZFN0b3JlKCkpLnN0b3JlLmdldDIoeyBwYXRoOiBmaWxlTmFtZSwgLi4uY29uZmlnIH0pO1xuICAgIH1cbiAgICBwdWJsaWMgYXN5bmMgc2V0KGZpbGVOYW1lOiBzdHJpbmcsIGRhdGE6IEJ1ZmZlciwgY29uZmlnPzogU2V0Q29uZmlnKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgYXNzZXJ0V3JpdGVzQWxsb3dlZCgpO1xuICAgICAgICBpZiAoZmlsZU5hbWUgPT09IFJPVVRJTkdfRklMRSkge1xuICAgICAgICAgICAgYXdhaXQgcXVldWVSb3V0aW5nQ29uZmlnV3JpdGUodGhpcy5hY2NvdW50LCB0aGlzLmJ1Y2tldE5hbWUsIGRhdGEsIGNvbmZpZyk7XG4gICAgICAgICAgICByZXR1cm4gZmlsZU5hbWU7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgKGF3YWl0IHRoaXMuZmluZFN0b3JlKCkpLnN0b3JlLnNldCh7IC4uLmNvbmZpZywgcGF0aDogZmlsZU5hbWUsIGRhdGEgfSk7XG4gICAgICAgIHJldHVybiBmaWxlTmFtZTtcbiAgICB9XG4gICAgcHVibGljIGFzeW5jIGRlbChmaWxlTmFtZTogc3RyaW5nLCBjb25maWc/OiBEZWxDb25maWcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXNzZXJ0V3JpdGVzQWxsb3dlZCgpO1xuICAgICAgICBhd2FpdCAoYXdhaXQgdGhpcy5maW5kU3RvcmUoKSkuc3RvcmUuZGVsKHsgcGF0aDogZmlsZU5hbWUsIC4uLmNvbmZpZyB9KTtcbiAgICB9XG4gICAgcHVibGljIGFzeW5jIHNldExhcmdlRmlsZShjb25maWc6IHsgcGF0aDogc3RyaW5nOyBsYXN0TW9kaWZpZWQ/OiBudW1iZXI7IGdldE5leHREYXRhKCk6IFByb21pc2U8QnVmZmVyIHwgdW5kZWZpbmVkPiB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGFzc2VydFdyaXRlc0FsbG93ZWQoKTtcbiAgICAgICAgbGV0IHN0b3JlID0gKGF3YWl0IHRoaXMuZmluZFN0b3JlKCkpLnN0b3JlO1xuICAgICAgICBsZXQgaWQgPSBhd2FpdCBzdG9yZS5zdGFydExhcmdlVXBsb2FkKHsgcGF0aDogY29uZmlnLnBhdGgsIGxhc3RNb2RpZmllZDogY29uZmlnLmxhc3RNb2RpZmllZCB9KTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICAgICAgbGV0IGRhdGEgPSBhd2FpdCBjb25maWcuZ2V0TmV4dERhdGEoKTtcbiAgICAgICAgICAgICAgICBpZiAoIWRhdGEpIGJyZWFrO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IG9mZnNldCA9IDA7IG9mZnNldCA8IGRhdGEubGVuZ3RoOyBvZmZzZXQgKz0gTEFSR0VfRklMRV9QQVJUX1NJWkUpIHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgc3RvcmUuYXBwZW5kTGFyZ2VVcGxvYWQoeyBpZCwgZGF0YTogZGF0YS5zdWJhcnJheShvZmZzZXQsIG9mZnNldCArIExBUkdFX0ZJTEVfUEFSVF9TSVpFKSB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhd2FpdCBzdG9yZS5maW5pc2hMYXJnZVVwbG9hZCh7IGlkLCBwYXRoOiBjb25maWcucGF0aCwgbGFzdE1vZGlmaWVkOiBjb25maWcubGFzdE1vZGlmaWVkIH0pO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBhd2FpdCBzdG9yZS5jYW5jZWxMYXJnZVVwbG9hZCh7IGlkIH0pO1xuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBwdWJsaWMgYXN5bmMgZ2V0SW5mbyhmaWxlTmFtZTogc3RyaW5nLCBjb25maWc/OiBHZXRJbmZvQ29uZmlnKTogUHJvbWlzZTx7IHdyaXRlVGltZTogbnVtYmVyOyBzaXplOiBudW1iZXIgfSB8IHVuZGVmaW5lZD4ge1xuICAgICAgICBpZiAoZmlsZU5hbWUgPT09IFJPVVRJTkdfRklMRSkge1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IGF3YWl0IGdldFJvdXRpbmdGaWxlUmVzdWx0KHRoaXMuYWNjb3VudCwgdGhpcy5idWNrZXROYW1lKTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQgJiYgeyB3cml0ZVRpbWU6IHJlc3VsdC53cml0ZVRpbWUsIHNpemU6IHJlc3VsdC5zaXplIH0gfHwgdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhd2FpdCAoYXdhaXQgdGhpcy5maW5kU3RvcmUoKSkuc3RvcmUuZ2V0SW5mbyh7IHBhdGg6IGZpbGVOYW1lLCAuLi5jb25maWcgfSk7XG4gICAgfVxuICAgIHB1YmxpYyBhc3luYyBmaW5kSW5mbyhwcmVmaXg6IHN0cmluZywgY29uZmlnPzogRmluZENvbmZpZyk6IFByb21pc2U8QXJjaGl2ZUZpbGVJbmZvW10+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IChhd2FpdCB0aGlzLmZpbmRTdG9yZSgpKS5zdG9yZS5maW5kSW5mbyh7IHByZWZpeCwgLi4uY29uZmlnIH0pO1xuICAgIH1cbiAgICBwdWJsaWMgYXN5bmMgZmluZChwcmVmaXg6IHN0cmluZywgY29uZmlnPzogRmluZENvbmZpZyk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICAgICAgcmV0dXJuIChhd2FpdCB0aGlzLmZpbmRJbmZvKHByZWZpeCwgY29uZmlnKSkubWFwKHggPT4geC5wYXRoKTtcbiAgICB9XG4gICAgcHVibGljIGFzeW5jIGdldFVSTChmaWxlUGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgbGV0IHsgZG9tYWluLCBwb3J0IH0gPSBnZXRTdG9yYWdlU2VydmVyQ29uZmlnKCk7XG4gICAgICAgIHJldHVybiBidWlsZEZpbGVVcmwoYGh0dHBzOi8vJHtkb21haW59OiR7cG9ydH0vZmlsZS8ke2VuY29kZVVSSUNvbXBvbmVudCh0aGlzLmFjY291bnQpfS8ke2VuY29kZVVSSUNvbXBvbmVudCh0aGlzLmJ1Y2tldE5hbWUpfWAsIGZpbGVQYXRoKTtcbiAgICB9XG4gICAgcHVibGljIGFzeW5jIGdldENvbmZpZygpOiBQcm9taXNlPEFyY2hpdmVzQ29uZmlnPiB7XG4gICAgICAgIHJldHVybiBnZXRCdWNrZXRDb25maWcoYXdhaXQgcmVxdWlyZUJ1Y2tldCh0aGlzLmFjY291bnQsIHRoaXMuYnVja2V0TmFtZSkpO1xuICAgIH1cbiAgICBwdWJsaWMgYXN5bmMgaGFzV3JpdGVBY2Nlc3MoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBwdWJsaWMgYXN5bmMgZ2V0Q2hhbmdlc0FmdGVyMihjb25maWc6IENoYW5nZXNBZnRlckNvbmZpZyk6IFByb21pc2U8QXJjaGl2ZUZpbGVJbmZvW10+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IChhd2FpdCB0aGlzLmZpbmRTdG9yZSgpKS5zdG9yZS5nZXRDaGFuZ2VzQWZ0ZXIyKGNvbmZpZyk7XG4gICAgfVxuICAgIHB1YmxpYyBhc3luYyBnZXRTeW5jU3RhdHVzKCk6IFByb21pc2U8QXJjaGl2ZXNTeW5jU3RhdHVzPiB7XG4gICAgICAgIHJldHVybiBhd2FpdCBidWNrZXRTeW5jU3RhdHVzKGF3YWl0IHJlcXVpcmVCdWNrZXQodGhpcy5hY2NvdW50LCB0aGlzLmJ1Y2tldE5hbWUpKTtcbiAgICB9XG59XG5cbmNvbnN0IGxvY2FsQXJjaGl2ZXMgPSBuZXcgTWFwPHN0cmluZywgSUFyY2hpdmVzPigpO1xuZXhwb3J0IGZ1bmN0aW9uIGdldExvY2FsQXJjaGl2ZXMoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcsIHNvdXJjZUNvbmZpZzogU291cmNlQ29uZmlnKTogSUFyY2hpdmVzIHtcbiAgICBsZXQga2V5ID0gYCR7YWNjb3VudH0vJHtidWNrZXROYW1lfXwke3N0YWJsZVN0cmluZ2lmeShzb3VyY2VDb25maWcpfWA7XG4gICAgbGV0IGV4aXN0aW5nID0gbG9jYWxBcmNoaXZlcy5nZXQoa2V5KTtcbiAgICBpZiAoZXhpc3RpbmcpIHJldHVybiBleGlzdGluZztcbiAgICBsZXQgYXJjaGl2ZXMgPSBuZXcgQnVja2V0SUFyY2hpdmVzV3JhcHBlcihhY2NvdW50LCBidWNrZXROYW1lLCBzb3VyY2VDb25maWcpO1xuICAgIGxvY2FsQXJjaGl2ZXMuc2V0KGtleSwgYXJjaGl2ZXMpO1xuICAgIHJldHVybiBhcmNoaXZlcztcbn1cbiJdfQ==
953
- /* _JS_SOURCE_HASH = "dab61171b71c11af9b36c3fccb800e54160c632a865dd3a41a96121cf6bf6b5c"; */
389
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmFnZVNlcnZlclN0YXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3RvcmFnZVNlcnZlclN0YXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLDJDQUF3QztBQUl4QyxpREFBd0c7QUFDeEcsaURBQXNFO0FBQ3RFLDJEQUE4RDtBQUM5RCxpREFBNkU7QUFDN0UsNkNBQWtKO0FBQ2xKLHFFQUF1RjtBQUN2RiwyQ0FBd0U7QUFrQ3hFLDBNQUEwTTtBQUNuTSxLQUFLLFVBQVUsYUFBYSxDQUFDLE9BQWUsRUFBRSxVQUFrQjtJQUNuRSxJQUFJLE1BQU0sR0FBRyxNQUFNLGVBQWUsQ0FBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDeEQsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ1YsTUFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLE9BQU8sSUFBSSxVQUFVLCtEQUErRCxJQUFJLENBQUMsU0FBUyxDQUFDLDJCQUFZLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUNoSyxDQUFDO0lBQ0QsT0FBTyxNQUFNLENBQUM7QUFDbEIsQ0FBQztBQU5ELHNDQU1DO0FBRUQsa1pBQWtaO0FBQzNZLEtBQUssVUFBVSxlQUFlLENBQUMsT0FBZSxFQUFFLFVBQWtCLEVBQUUsWUFBc0M7SUFDN0csSUFBSSxNQUFNLEdBQUcsTUFBTSxhQUFhLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3RELElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNoQixNQUFNLElBQUksS0FBSyxDQUFDLDBEQUEwRCxPQUFPLElBQUksVUFBVSxrRkFBa0YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN2TyxDQUFDO0lBQ0QsSUFBSSxLQUFLLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJ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O0lBQ0QsSUFBSSxJQUFJLEtBQUssVUFBVSxFQUFFLENBQUM7UUFDdEIsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3ZCLEtBQUssQ0FBQyxhQUFhLElBQUksS0FBSyxDQUFDO0lBQ2pDLENBQUM7U0FBTSxDQUFDO1FBQ0osS0FBSyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ3RCLEtBQUssQ0FBQyxZQUFZLElBQUksS0FBSyxDQUFDO0lBQ2hDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxtQkFBbUIsQ0FBQyxHQUFXO0lBQ3BDLE9BQU8sVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxlQUFlLEVBQUUsQ0FBQztBQUNwRCxDQUFDO0FBRUQsa0VBQWtFO0FBQ2xFLFNBQWdCLHNCQUFzQixDQUFDLE9BQWU7SUFDbEQsSUFBSSxNQUFNLEdBQUcsR0FBRyxPQUFPLEdBQUcsQ0FBQztJQUMzQixJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUM7SUFDaEIsS0FBSyxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsVUFBVSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUNyQyxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7WUFBRSxTQUFTO1FBQ3RDLFVBQVUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdkIsT0FBTyxFQUFFLENBQUM7SUFDZCxDQUFDO0lBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsT0FBTyx1QkFBdUIsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUN4RixPQUFPLE9BQU8sQ0FBQztBQUNuQixDQUFDO0FBVkQsd0RBVUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHsgQmxvYlN0b3JlIH0gZnJvbSBcIi4vYmxvYlN0b3JlXCI7XG5pbXBvcnQge1xuICAgIFJlbW90ZUNvbmZpZywgSG9zdGVkQ29uZmlnLCBTb3VyY2VDb25maWcsIElBcmNoaXZlcywgQXJjaGl2ZXNDb25maWcsIEFyY2hpdmVzU3luY1N0YXR1cywgU3luY0FjdGl2aXR5LFxufSBmcm9tIFwiLi4vSUFyY2hpdmVzXCI7XG5pbXBvcnQgeyBST1VUSU5HX0ZJTEUsIHBhcnNlUm91dGluZ0RhdGEsIHNlcmlhbGl6ZVJlbW90ZUNvbmZpZywgbm9ybWFsaXplU291cmNlIH0gZnJvbSBcIi4vcmVtb3RlQ29uZmlnXCI7XG5pbXBvcnQgeyBjcmVhdGVTdG9yZVNvdXJjZSwgYXBwbHlTb3VyY2VDb25maWcgfSBmcm9tIFwiLi9zdG9yZVNvdXJjZXNcIjtcbmltcG9ydCB7IGJyb2FkY2FzdFJvdXRpbmdDaGFuZ2VkIH0gZnJvbSBcIi4vc3RvcmFnZUNvbnRyb2xsZXJcIjtcbmltcG9ydCB7IGdldFN0b3JhZ2VTZXJ2ZXJDb25maWcsIGFzc2VydFdyaXRlc0FsbG93ZWQgfSBmcm9tIFwiLi9zZXJ2ZXJDb25maWdcIjtcbmltcG9ydCB7IGdldEJ1Y2tldEZvbGRlciwgbGlzdEFjY291bnRTdG9yZUZvbGRlcnMsIGxpc3RCdWNrZXRTdG9yZUZvbGRlcnMsIHJlYWRSb3V0aW5nRnJvbURpc2ssIGdldERpc2tJbmZvLCBCdWNrZXREaXNrSW5mbyB9IGZyb20gXCIuL2J1Y2tldERpc2tcIjtcbmltcG9ydCB7IHNjaGVkdWxlQm91bmRhcnlXb3JrLCByZWluamVjdEludGVybWVkaWF0ZXMgfSBmcm9tIFwiLi9pbnRlcm1lZGlhdGVNYW5hZ2VtZW50XCI7XG5pbXBvcnQgeyBwbGFuU2VsZlN0b3JlcywgaXNTZWxmU291cmNlLCBTZWxmU3VtbWFyeSB9IGZyb20gXCIuL3N0b3JlUGxhblwiO1xuXG4vKipcbiAqIFdoYXQgdGhpcyBzZXJ2ZXIgSEFTLCBhcyBvcHBvc2VkIHRvIHdoYXQgYW55IG9mIGl0IGRvZXMuIEZvdXIgdGhpbmdzLCBhbmQgbm90aGluZyBlbHNlOlxuICpcbiAqIC0gdGhlIHN0b3JlcywgYnkgZm9sZGVyIChnZXRTdG9yZSkgLSBtYWRlIG9uY2UsIGFuZCBzZWxmLWNvbmZpZ3VyaW5nIGZyb20gdGhlcmVcbiAqIC0gd2hpY2ggb2YgdGhlbSBhIHJlcXVlc3QgbWVhbnMgKGZpbmRCdWNrZXRTdG9yZSksIHdoaWNoIGlzIG9ubHkgZXZlciBhIG5hbWVcbiAqIC0gd2hhdCBleGlzdHMgb24gZGlzaywgZm9yIGxpc3RpbmdzIGFuZCBmb3IgdGhlIHBhZ2VzIHRoYXQgcmVwb3J0IGl0XG4gKlxuICogSXQgZGVjaWRlcyBub3RoaW5nIGFib3V0IHJvdXRlcywgd2luZG93cyBvciBwZWVycyAtIGEgc3RvcmUgcmVhZHMgaXRzIG93biBjb25maWcgYW5kIHdvcmtzIHRoYXRcbiAqIG91dCBpdHNlbGYgKEJsb2JTdG9yZS5hcHBseVJvdXRpbmdDb25maWcpIC0gYW5kIGl0IHNjaGVkdWxlcyBub3RoaW5nOiBzd2l0Y2hvdmVycyBhbmQgdGhlIGhhbmRvdmVyc1xuICogdGhleSBjYXVzZSBsaXZlIGluIGludGVybWVkaWF0ZU1hbmFnZW1lbnQuXG4gKi9cblxuZXhwb3J0IHR5cGUgTG9hZGVkU3RvcmUgPSB7XG4gICAgLy8gVGhlIG5hbWUgaXRzIGVudHJpZXMgZ2F2ZSBpdCAoc2VlIENvbW1vbkNvbmZpZy5uYW1lKSAtIGl0cyBpZGVudGl0eSBoZXJlLCBpdHMgZm9sZGVyIG9uIGRpc2ssIGFuZCBob3cgYSByZXF1ZXN0IGZpbmRzIGl0XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIC8vIFRoZSBleGFjdCBzZWxmIGVudHJpZXMgdGhpcyBzdG9yZSBzZXJ2ZXMgKHNhbWUgcm91dGUsIGRpZmZlcmVudCB2YWxpZCB3aW5kb3dzKS4gRW1wdHkgd2hlbiB3ZSBhcmUgbm90IGluIHRoZSBjb25maWcgYnV0IHN0aWxsIHNlcnZlIG91ciBkaXNrIGRhdGEuXG4gICAgZW50cmllczogSG9zdGVkQ29uZmlnW107XG4gICAgZm9sZGVyOiBzdHJpbmc7XG4gICAgc3RvcmU6IEJsb2JTdG9yZTtcbn07XG5cbi8vIEEgYnVja2V0IGxvYWRlZCBvbiB0aGlzIHNlcnZlcjogdGhlIHN0b3JlcyBpdCBoYXMgaGVyZSwgYW5kIHdoYXQgdGhlIG5ld2VzdCBvZiB0aGVpciBjb25maWdzIHNheXMgYWJvdXQgdXMuIFB1cmUgZGF0YSAtIHRoZSBzdG9yZXMgdGhlbXNlbHZlcyBkbyB0aGUgd29yaywgaW5jbHVkaW5nIGNvbmZpZ3VyaW5nIHRoZW1zZWx2ZXMuXG5leHBvcnQgdHlwZSBCdWNrZXRTdGF0ZSA9IHtcbiAgICBhY2NvdW50OiBzdHJpbmc7XG4gICAgYnVja2V0TmFtZTogc3RyaW5nO1xuICAgIC8vIFRoZSBuZXdlc3Qgcm91dGluZyBjb25maWcgYW1vbmcgaXRzIHN0b3Jlcywgb3IgYWJzZW50IHdoZW4gbm9uZSBvZiB0aGVtIGhhcyBvbmUgeWV0XG4gICAgcm91dGluZz86IFJlbW90ZUNvbmZpZztcbiAgICBzZWxmRW50cmllczogSG9zdGVkQ29uZmlnW107XG4gICAgc2VsZjogU2VsZlN1bW1hcnkgfCB1bmRlZmluZWQ7XG4gICAgc3RvcmVzOiBMb2FkZWRTdG9yZVtdO1xufTtcblxuLyoqIFRoZSBsb2FkZWQgYnVja2V0LCBsb2FkaW5nIGl0ICh3aGljaCBpbnN0YW50aWF0ZXMgaXRzIHN0b3JlcyBhbmQgc3RhcnRzIHRoZWlyIHN5bmNocm9uaXphdGlvbikgaWYgbmVlZGVkLiBBIGJ1Y2tldCB0aGF0IGRvZXMgbm90IGV4aXN0IG9uIHRoaXMgc2VydmVyIHRocm93cyAtIGNhbGxlcnMgbmV2ZXIgc2VlIHVuZGVmaW5lZCBidWNrZXRzLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlcXVpcmVCdWNrZXQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPEJ1Y2tldFN0YXRlPiB7XG4gICAgbGV0IGJ1Y2tldCA9IGF3YWl0IGdldExvYWRlZEJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBpZiAoIWJ1Y2tldCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEJ1Y2tldCAke2FjY291bnR9LyR7YnVja2V0TmFtZX0gZG9lcyBub3QgZXhpc3Qgb24gdGhpcyBzZXJ2ZXIuIFdyaXRlIGl0cyByb3V0aW5nIGNvbmZpZyB0byAke0pTT04uc3RyaW5naWZ5KFJPVVRJTkdfRklMRSl9IHRvIGNyZWF0ZSBpdC5gKTtcbiAgICB9XG4gICAgcmV0dXJuIGJ1Y2tldDtcbn1cblxuLyoqIFRoZSBzdG9yZSBzZXJ2aW5nIGEgcmVxdWVzdDogdGhlIG9uZSB0aGUgY2xpZW50J3Mgc2VsZWN0ZWQgZW50cnkgTkFNRVMuIE5vdGhpbmcgZWxzZSBpcyBjb21wYXJlZCAtIG5vdCB0aGUgd2luZG93LCBub3QgdGhlIHJvdXRlLCBub3QgdGhlIGZsYWdzIC0gYmVjYXVzZSB0aGUgbmFtZSBpcyB3aGF0IHNheXMgd2hpY2ggc3RvcmFnZSB0aGlzIGlzLCBhbmQgZXZlcnl0aGluZyBlbHNlIGlzIHBvbGljeSB0aGUgc3RvcmUgaXRzZWxmIGFwcGxpZXMgdG8gdGhlIHJlcXVlc3QuIEEgY2xpZW50IGEgY29uZmlnIHZlcnNpb24gYmVoaW5kIG9uIHNvbWUgZmxhZyB0aGVyZWZvcmUgc3RpbGwgcmVhY2hlcyB0aGUgcmlnaHQgc3RvcmUsIHdoaWNoIGlzIHRoZSB3aG9sZSBwb2ludCBvZiBuYW1pbmcgaXQuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmluZEJ1Y2tldFN0b3JlKGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nLCBzb3VyY2VDb25maWc6IFNvdXJjZUNvbmZpZyB8IHVuZGVmaW5lZCk6IFByb21pc2U8TG9hZGVkU3RvcmU+IHtcbiAgICBsZXQgYnVja2V0ID0gYXdhaXQgcmVxdWlyZUJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBpZiAoIXNvdXJjZUNvbmZpZykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIHJlbW90ZSBzb3VyY2UgY29uZmlndXJhdGlvbiB3YXMgcHJvdmlkZWQgZm9yIGJ1Y2tldCAke2FjY291bnR9LyR7YnVja2V0TmFtZX06IGV2ZXJ5IHJlcXVlc3QgbXVzdCBzYXkgd2hpY2ggY29uZmlndXJlZCBzb3VyY2UgaXQgc2VsZWN0ZWQuIFRoaXMgc2VydmVyIGhhczogJHtKU09OLnN0cmluZ2lmeShidWNrZXQuc3RvcmVzLm1hcCh4ID0+IHgubmFtZSkpfWApO1xuICAgIH1cbiAgICBsZXQgc3RvcmUgPSBidWNrZXQuc3RvcmVzLmZpbmQoeCA9PiB4Lm5hbWUgPT09IHNvdXJjZUNvbmZpZy5uYW1lKTtcbiAgICBpZiAoc3RvcmUpIHJldHVybiBzdG9yZTtcbiAgICAvLyBUaGUgbG9hZGVkIGJ1Y2tldCBpcyBhIHNuYXBzaG90IG9mIHRoZSBkaXNrIGZyb20gd2hlbiBpdCBsb2FkZWQ7IGEgc3RvcmUgY3JlYXRlZCBzaW5jZSAoYSBuZXcgbmFtZSBpbiBhIHJld3JpdHRlbiByb3V0aW5nIGNvbmZpZykgaXMgb24gdGhlIGRpc2sgYnV0IG5vdCBpbiB0aGUgc25hcHNob3QsIHNvIGEgbWlzcyByZS1yZWFkcyB0aGUgZGlzayBvbmNlIGJlZm9yZSBpdCBpcyBiZWxpZXZlZFxuICAgIGxldCBwcmV2aW91c05hbWVzID0gYnVja2V0LnN0b3Jlcy5tYXAoeCA9PiB4Lm5hbWUpO1xuICAgIGxldCByZWxvYWRlZCA9IGF3YWl0IHJlbG9hZEJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBzdG9yZSA9IHJlbG9hZGVkPy5zdG9yZXMuZmluZCh4ID0+IHgubmFtZSA9PT0gc291cmNlQ29uZmlnLm5hbWUpO1xuICAgIGlmIChzdG9yZSkge1xuICAgICAgICBjb25zb2xlLmxvZyhgUmVsb2FkZWQgYnVja2V0ICR7YWNjb3VudH0vJHtidWNrZXROYW1lfSB0byBmaW5kIHN0b3JlICR7SlNPTi5zdHJpbmdpZnkoc291cmNlQ29uZmlnLm5hbWUpfTogaXRzIHN0b3JlcyBjaGFuZ2VkIGZyb20gJHtKU09OLnN0cmluZ2lmeShwcmV2aW91c05hbWVzKX0gdG8gJHtKU09OLnN0cmluZ2lmeShyZWxvYWRlZD8uc3RvcmVzLm1hcCh4ID0+IHgubmFtZSkpfWApO1xuICAgICAgICByZXR1cm4gc3RvcmU7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihgVGhpcyBzZXJ2ZXIgaGFzIG5vIHN0b3JlIG5hbWVkICR7SlNPTi5zdHJpbmdpZnkoc291cmNlQ29uZmlnLm5hbWUpfSBmb3IgYnVja2V0ICR7YWNjb3VudH0vJHtidWNrZXROYW1lfSAoaXQgaGFzOiAke0pTT04uc3RyaW5naWZ5KChyZWxvYWRlZCB8fCBidWNrZXQpLnN0b3Jlcy5tYXAoeCA9PiB4Lm5hbWUpKX0pLiBSZXF1ZXN0ZWQ6ICR7SlNPTi5zdHJpbmdpZnkoc291cmNlQ29uZmlnKX1gKTtcbn1cblxuLyoqIEludGVybmFsIChzdG9yZS10by1zdG9yZSkgcmVhZHMgc2tpcCBzdG9yZSBzZWxlY3Rpb24gZW50aXJlbHk6IHRoZSBjYWxsZXIgaXMgYW5vdGhlciBzdG9yZSB3aG9zZSBpbmRleCBzYXlzIHRoaXMgTUFDSElORSBob2xkcyB0aGUgYnl0ZXMgLSB0aGUgcGVyc2lzdGVkIGhvbGRlciBpZGVudGl0eSBpcyBqdXN0IGEgVVJMLCB3aGljaCBjYW5ub3QgbmFtZSBhIHN0b3JlLiBXaGljaGV2ZXIgc3RvcmUncyBmb2xkZXIgaGFzIHRoZSBuZXdlc3QgY29weSBhbnN3ZXJzLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRCdWNrZXRJbnRlcm5hbChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgY29uZmlnOiB7IHBhdGg6IHN0cmluZzsgcmFuZ2U/OiB7IHN0YXJ0OiBudW1iZXI7IGVuZDogbnVtYmVyIH07IGluY2x1ZGVUb21ic3RvbmVzPzogYm9vbGVhbiB9KTogUHJvbWlzZTx7IGRhdGE6IEJ1ZmZlcjsgd3JpdGVUaW1lOiBudW1iZXI7IHNpemU6IG51bWJlciB9IHwgdW5kZWZpbmVkPiB7XG4gICAgbGV0IGJ1Y2tldCA9IGF3YWl0IHJlcXVpcmVCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgbGV0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChidWNrZXQuc3RvcmVzLm1hcChzID0+IHMuc3RvcmUuZ2V0Mih7IHBhdGg6IGNvbmZpZy5wYXRoLCByYW5nZTogY29uZmlnLnJhbmdlLCBpbmNsdWRlVG9tYnN0b25lczogY29uZmlnLmluY2x1ZGVUb21ic3RvbmVzLCBpbnRlcm5hbDogdHJ1ZSB9KSkpO1xuICAgIGxldCBiZXN0OiB7IGRhdGE6IEJ1ZmZlcjsgd3JpdGVUaW1lOiBudW1iZXI7IHNpemU6IG51bWJlciB9IHwgdW5kZWZpbmVkO1xuICAgIGZvciAobGV0IHJlc3VsdCBvZiByZXN1bHRzKSB7XG4gICAgICAgIGlmIChyZXN1bHQgJiYgKCFiZXN0IHx8IHJlc3VsdC53cml0ZVRpbWUgPiBiZXN0LndyaXRlVGltZSkpIHtcbiAgICAgICAgICAgIGJlc3QgPSByZXN1bHQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGJlc3Q7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRCdWNrZXRDb25maWcoYnVja2V0OiBCdWNrZXRTdGF0ZSk6IEFyY2hpdmVzQ29uZmlnIHtcbiAgICBsZXQgaW5kZXggPSB7IGZpbGVDb3VudDogMCwgYnl0ZUNvdW50OiAwIH07XG4gICAgbGV0IGluZGV4U291cmNlczogeyBkZWJ1Z05hbWU6IHN0cmluZzsgZmlsZUNvdW50OiBudW1iZXI7IGJ5dGVDb3VudDogbnVtYmVyIH1bXSA9IFtdO1xuICAgIGxldCBzeW5jaW5nOiBTeW5jQWN0aXZpdHlbXSA9IFtdO1xuICAgIGxldCByZWFkZXJEaXNrTGltaXQ6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICBmb3IgKGxldCBzIG9mIGJ1Y2tldC5zdG9yZXMpIHtcbiAgICAgICAgbGV0IHByb2dyZXNzID0gcy5zdG9yZS5nZXRTeW5jUHJvZ3Jlc3MoKTtcbiAgICAgICAgaW5kZXguZmlsZUNvdW50ICs9IHByb2dyZXNzLmluZGV4LmZpbGVDb3VudDtcbiAgICAgICAgaW5kZXguYnl0ZUNvdW50ICs9IHByb2dyZXNzLmluZGV4LmJ5dGVDb3VudDtcbiAgICAgICAgaW5kZXhTb3VyY2VzLnB1c2goLi4ucHJvZ3Jlc3Muc291cmNlcyk7XG4gICAgICAgIHN5bmNpbmcucHVzaCguLi5wcm9ncmVzcy5zeW5jaW5nKTtcbiAgICAgICAgcmVhZGVyRGlza0xpbWl0ID0gcmVhZGVyRGlza0xpbWl0IHx8IHByb2dyZXNzLnJlYWRlckRpc2tMaW1pdDtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgLy8gRXZlcnkgc3RvcmUgaXMgaW5kZXgtYmFja2VkLCBzbyB0aGUgY2hhbmdlIGZlZWQgaXMgYWx3YXlzIG5hdGl2ZVxuICAgICAgICBzdXBwb3J0c0NoYW5nZXNBZnRlcjogdHJ1ZSxcbiAgICAgICAgcmVtb3RlQ29uZmlnOiBidWNrZXQucm91dGluZyxcbiAgICAgICAgaW5kZXgsXG4gICAgICAgIGluZGV4U291cmNlcyxcbiAgICAgICAgcmVhZGVyRGlza0xpbWl0LFxuICAgICAgICBzeW5jaW5nLFxuICAgIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBidWNrZXRTeW5jU3RhdHVzKGJ1Y2tldDogQnVja2V0U3RhdGUpOiBQcm9taXNlPEFyY2hpdmVzU3luY1N0YXR1cz4ge1xuICAgIGxldCBzdGF0dXNlcyA9IGF3YWl0IFByb21pc2UuYWxsKGJ1Y2tldC5zdG9yZXMubWFwKHMgPT4gcy5zdG9yZS5nZXRTeW5jU3RhdHVzKCkpKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBhbGxTY2Fuc0NvbXBsZXRlOiBzdGF0dXNlcy5ldmVyeSh4ID0+IHguYWxsU2NhbnNDb21wbGV0ZSksXG4gICAgICAgIGluZGV4U2l6ZTogc3RhdHVzZXMucmVkdWNlKChzdW0sIHgpID0+IHN1bSArIHguaW5kZXhTaXplLCAwKSxcbiAgICAgICAgc291cmNlczogc3RhdHVzZXMuZmxhdE1hcCh4ID0+IHguc291cmNlcyksXG4gICAgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJ1Y2tldEluZGV4VG90YWxzKGJ1Y2tldDogQnVja2V0U3RhdGUpOiBQcm9taXNlPHsgZmlsZUNvdW50OiBudW1iZXI7IGJ5dGVDb3VudDogbnVtYmVyOyBzb3VyY2VzOiB7IGRlYnVnTmFtZTogc3RyaW5nOyBmaWxlQ291bnQ6IG51bWJlcjsgYnl0ZUNvdW50OiBudW1iZXIgfVtdIH0+IHtcbiAgICBsZXQgdG90YWxzID0gYXdhaXQgUHJvbWlzZS5hbGwoYnVja2V0LnN0b3Jlcy5tYXAocyA9PiBzLnN0b3JlLmNvbXB1dGVJbmRleFRvdGFscygpKSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZmlsZUNvdW50OiB0b3RhbHMucmVkdWNlKChzdW0sIHgpID0+IHN1bSArIHguZmlsZUNvdW50LCAwKSxcbiAgICAgICAgYnl0ZUNvdW50OiB0b3RhbHMucmVkdWNlKChzdW0sIHgpID0+IHN1bSArIHguYnl0ZUNvdW50LCAwKSxcbiAgICAgICAgc291cmNlczogdG90YWxzLmZsYXRNYXAoeCA9PiB4LnNvdXJjZXMpLFxuICAgIH07XG59XG5cbmNvbnN0IGJ1Y2tldHMgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZTxCdWNrZXRTdGF0ZSB8IHVuZGVmaW5lZD4+KCk7XG4vLyBUaGUgcmVzb2x2ZWQgb25lcywgZm9yIHRoZSBjb2RlIHRoYXQgd2Fsa3MgYnVja2V0cyByYXRoZXIgdGhhbiBhc2tpbmcgZm9yIG9uZSAoc2VlIGdldEJ1Y2tldFN0YXRlcylcbmNvbnN0IGxvYWRlZEJ1Y2tldHMgPSBuZXcgTWFwPHN0cmluZywgQnVja2V0U3RhdGU+KCk7XG5cbi8qKiBUaGUgYnVja2V0IHN0YXRlcyBjdXJyZW50bHkgaW4gbWVtb3J5IC0gd2hhdCB0aGUgc3dpdGNob3ZlciBtYWNoaW5lcnkgd2Fsa3MuIE9ubHkgd2hhdCBpcyBsb2FkZWQ6IGxvYWRpbmcgYSBidWNrZXQgc3RhcnRzIGl0cyBzeW5jaHJvbml6YXRpb24sIGFuZCBhIGJ1Y2tldCBub3RoaW5nIGhhcyB0b3VjaGVkIGhhcyBubyBpbi1mbGlnaHQgd3JpdGVzIHRvIGhhbmQgb3ZlciBhbnl3YXkuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QnVja2V0U3RhdGVzKCk6IEJ1Y2tldFN0YXRlW10ge1xuICAgIHJldHVybiBbLi4ubG9hZGVkQnVja2V0cy52YWx1ZXMoKV07XG59XG5cbmNvbnN0IHJlc29sdmVkU291cmNlQXJjaGl2ZXMgPSBuZXcgTWFwPHN0cmluZywgSUFyY2hpdmVzPigpO1xuLyoqIEEgY2FjaGVkIElBcmNoaXZlcyBmb3IgYSBwZXJzaXN0ZWQgc291cmNlIGlkZW50aXR5OiBhIHJvdXRpbmcgVVJMIChob3N0ZWQvYmFja2JsYXplKSBvciBhIGRpc2sgZm9sZGVyIHBhdGggLSB0aGUgZm9ybSBCbG9iU3RvcmUncyBzb3VyY2VzIGxpc3Qgc3RvcmVzLiBDb25maWd1cmF0aW9uICh2YWxpZCB3aW5kb3dzLCByb3V0ZXMpIGRlY2lkZXMgV0hFTiBhIHNvdXJjZSBzaG91bGQgYmUgdXNlZDsgZm9yIHJlYWRpbmcgYnl0ZXMgdGhlIGluZGV4IHNheXMgYSBzb3VyY2UgaG9sZHMsIHRoZSBVUkwgYWxvbmUgaXMgZW5vdWdoIC0gZXZlbiBmb3Igc291cmNlcyBubyBsb25nZXIgaW4gYW55IGNvbmZpZy4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlU291cmNlQXJjaGl2ZXModXJsOiBzdHJpbmcpOiBJQXJjaGl2ZXMge1xuICAgIGxldCBleGlzdGluZyA9IHJlc29sdmVkU291cmNlQXJjaGl2ZXMuZ2V0KHVybCk7XG4gICAgaWYgKGV4aXN0aW5nKSByZXR1cm4gZXhpc3Rpbmc7XG4gICAgbGV0IHNvdXJjZUNvbmZpZzogU291cmNlQ29uZmlnIHwgdW5kZWZpbmVkO1xuICAgIGlmICh1cmwuc3RhcnRzV2l0aChcImh0dHBzOi8vXCIpKSB7XG4gICAgICAgIC8vIFRoZSBjb25maWcgaXMgZmFicmljYXRlZCBmcm9tIHRoZSBiYXJlIFVSTCBhbmQgY2FuIG5ldmVyIGV4YWN0LW1hdGNoIGEgc2VydmVyJ3MgZW50cmllcyAtIHdoaWNoIGlzIGZpbmUsIGJlY2F1c2UgaG9sZGVyIHJlYWRzIGFyZSBpbnRlcm5hbCByZWFkcywgYW5kIGludGVybmFsIHJlYWRzIG5ldmVyIHNlbGVjdCBhIHN0b3JlIChzZWUgcmVhZEJ1Y2tldEludGVybmFsKVxuICAgICAgICBzb3VyY2VDb25maWcgPSBub3JtYWxpemVTb3VyY2UodXJsKTtcbiAgICB9XG4gICAgbGV0IGFyY2hpdmVzID0gY3JlYXRlU3RvcmVTb3VyY2UoeyBzb3VyY2VDb25maWcsIGZvbGRlcjogdXJsIH0pO1xuICAgIHJlc29sdmVkU291cmNlQXJjaGl2ZXMuc2V0KHVybCwgYXJjaGl2ZXMpO1xuICAgIHJldHVybiBhcmNoaXZlcztcbn1cblxuLyoqIFdoYXQgYW4gaW5kZXggZW50cnkgcmVjb3JkcyBhcyB0aGUgaG9sZGVyIG9mIGl0cyBieXRlcyAoc2VlIEFyY2hpdmVzU291cmNlLnVybCksIHNvIGl0IG11c3QgbmFtZSB0aGUgZW5kcG9pbnQgRk9SRVZFUi4gQW4gaW50ZXJtZWRpYXRlIGlzIGEgc3dpdGNob3ZlcidzIHRlbXBvcmFyeSBhbHRlcm5hdGUgcG9ydCBvbnRvIGFub3RoZXIgc291cmNlLCBhbmQgdGhhdCBwb3J0IGlzIGdvbmUgZm9yIGdvb2Qgb25jZSBpdHMgd2luZG93IHBhc3NlcyAtIHNvIGl0IGlzIHJlY29yZGVkIGFzIHRoZSBzb3VyY2UgaXQgd2FzIHNwbGl0IG91dCBvZiwgd2hpY2ggaG9sZHMgdGhlIHNhbWUgYnVja2V0IGFuZCBvdXRsaXZlcyBpdC4gKi9cbmZ1bmN0aW9uIHNvdXJjZVBlcnNpc3RlbnRVcmwoc291cmNlQ29uZmlnOiBTb3VyY2VDb25maWcgfCB1bmRlZmluZWQsIGZvbGRlcjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZiAoIXNvdXJjZUNvbmZpZykgcmV0dXJuIGZvbGRlcjtcbiAgICByZXR1cm4gc291cmNlQ29uZmlnLmludGVybWVkaWF0ZSB8fCBzb3VyY2VDb25maWcudXJsO1xufVxuXG4vKiogVGhlIGZhc3Qtd3JpdGUgcG9saWN5IHRoaXMgc3RvcmUgd3JpdGVzIHVuZGVyOiBpdHMgb3duIGNvbmZpZ3VyYXRpb24gZGVjaWRlcyBpdCAoZmFzdC93cml0ZURlbGF5IGFyZSBPVVIgc2V0dGluZ3MsIG5vdCB0aGUgcGVlcidzKSwgYW5kIGVhY2ggc291cmNlIHRoZW4gaG9sZHMgd3JpdGVzIGZvciBhcyBsb25nIGFzIHNvdXJjZVdyaXRlRGVsYXkgc2F5cy4gKi9cbi8qKlxuICogRXZlcnkgc3RvcmUgdGhpcyBwcm9jZXNzIHJ1bnMsIGJ5IGZvbGRlciAtIHdoaWNoIElTIHRoZSBzdG9yZSdzIGlkZW50aXR5OiBhY2NvdW50LCBuYW1lLCBidWNrZXQuXG4gKiBBIHN0b3JlIGlzIG1hZGUgb25jZSwgY29uZmlndXJlcyBpdHNlbGYgZnJvbSB0aGUgcm91dGluZyBjb25maWcgaXQgaG9sZHMsIGFuZCBzdGF5czsgbm90aGluZyBoZXJlXG4gKiBkZWNpZGVzIHdoYXQgaXQgaXMsIG9ubHkgdGhhdCBpdCBleGlzdHMuXG4gKi9cbmNvbnN0IHN0b3JlcyA9IG5ldyBNYXA8c3RyaW5nLCBCbG9iU3RvcmU+KCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdG9yZShhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgbmFtZTogc3RyaW5nKTogQmxvYlN0b3JlIHtcbiAgICBsZXQgZm9sZGVyID0gZ2V0QnVja2V0Rm9sZGVyKG5hbWUsIGFjY291bnQsIGJ1Y2tldE5hbWUpO1xuICAgIGxldCBleGlzdGluZyA9IHN0b3Jlcy5nZXQoZm9sZGVyKTtcbiAgICBpZiAoZXhpc3RpbmcpIHJldHVybiBleGlzdGluZztcbiAgICBsZXQgc3RvcmUgPSBuZXcgQmxvYlN0b3JlKGZvbGRlciwgbmFtZSwge1xuICAgICAgICAvLyBXaGljaCBlbnRyaWVzIGluIElUUyByb3V0aW5nIGNvbmZpZyBhcmUgdGhpcyBzZXJ2ZXIncyBjb3B5IG9mIGl0XG4gICAgICAgIGlzU2VsZjogc291cmNlID0+IGlzU2VsZlNvdXJjZShzb3VyY2UsIGFjY291bnQsIGJ1Y2tldE5hbWUpLFxuICAgICAgICBjcmVhdGVTb3VyY2U6IGNvbmZpZyA9PiBjcmVhdGVTdG9yZVNvdXJjZSh7IHNvdXJjZUNvbmZpZzogY29uZmlnLnNvdXJjZUNvbmZpZywgZm9sZGVyLCB3cml0ZURlbGF5OiBjb25maWcud3JpdGVEZWxheSB9KSxcbiAgICAgICAgYXBwbHlTb3VyY2U6IChzb3VyY2UsIHNvdXJjZUNvbmZpZywgd3JpdGVEZWxheSkgPT4gYXBwbHlTb3VyY2VDb25maWcoc291cmNlLCBzb3VyY2VDb25maWcsIHdyaXRlRGVsYXkpLFxuICAgICAgICBvbldyaXRlQ291bnRlZDogKGtpbmQsIGJ5dGVzKSA9PiBjb3VudEJ1Y2tldFdyaXRlKGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gLCBraW5kLCBieXRlcyksXG4gICAgICAgIHJlc29sdmVTb3VyY2VVcmw6IHJlc29sdmVTb3VyY2VBcmNoaXZlcyxcbiAgICB9KTtcbiAgICBzdG9yZXMuc2V0KGZvbGRlciwgc3RvcmUpO1xuICAgIC8vIExhenkgaW5pdCB3b3VsZCBsZWF2ZSBhIHN0b3JlIG5vdGhpbmcgaGFzIHRvdWNoZWQgc2l0dGluZyBpbmVydCAtIG5vIGluZGV4IGxvYWRlZCwgbm8gY29uZmlnIGFwcGxpZWQsIG5vdGhpbmcgc3luY2hyb25pemluZyAtIHdoaWxlIGl0cyBmb2xkZXIgaXMgZnVsbCBvZiBmaWxlc1xuICAgIHZvaWQgc3RvcmUuaW5pdCgpLmNhdGNoKChlOiBFcnJvcikgPT4gY29uc29sZS5lcnJvcihgSW5pdGlhbGl6aW5nIHN0b3JlICR7SlNPTi5zdHJpbmdpZnkobmFtZSl9IG9mIGJ1Y2tldCAke2FjY291bnR9LyR7YnVja2V0TmFtZX0gZmFpbGVkOiAke2Uuc3RhY2sgPz8gZX1gKSk7XG4gICAgcmV0dXJuIHN0b3JlO1xufVxuXG4vKiogVGhlIGJ1Y2tldCBhcyB0aGlzIHNlcnZlciBoYXMgaXQ6IHRoZSBzdG9yZXMgd2hvc2UgZm9sZGVycyBleGlzdCwgcGx1cyB3aGF0ZXZlciB0aGUgbmV3ZXN0IG9mIHRoZWlyIGNvbmZpZ3Mgc2F5cyBhYm91dCB1cy4gTmFtZXMgY29tZSBmcm9tIHRoZSBESVNLLCBub3QgZnJvbSB0aGUgY29uZmlnIC0gYSBzdG9yZSB3ZSBob2xkIGtlZXBzIGJlaW5nIHNlcnZlZCB3aGV0aGVyIG9yIG5vdCB0aGUgY3VycmVudCBjb25maWcgc3RpbGwgbWVudGlvbnMgaXQuICovXG5mdW5jdGlvbiBidWlsZEJ1Y2tldChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgbmFtZXM6IHN0cmluZ1tdLCByb3V0aW5nOiBSZW1vdGVDb25maWcgfCB1bmRlZmluZWQpOiBCdWNrZXRTdGF0ZSB7XG4gICAgbGV0IHBsYW4gPSByb3V0aW5nICYmIHBsYW5TZWxmU3RvcmVzKGFjY291bnQsIGJ1Y2tldE5hbWUsIHJvdXRpbmcpIHx8IHVuZGVmaW5lZDtcbiAgICBsZXQgZW50cmllc0J5TmFtZSA9IG5ldyBNYXA8c3RyaW5nLCBIb3N0ZWRDb25maWdbXT4oKTtcbiAgICBmb3IgKGxldCBzZWxmU3RvcmUgb2YgcGxhbj8uc3RvcmVzIHx8IFtdKSB7XG4gICAgICAgIGVudHJpZXNCeU5hbWUuc2V0KHNlbGZTdG9yZS5uYW1lLCBzZWxmU3RvcmUuZW50cmllcyk7XG4gICAgfVxuICAgIC8vIEVhY2ggc3RvcmUgcmVhZHMgaXRzIG93biBjb3B5IG9mIHRoZSBjb25maWcgYW5kIGRlY2lkZXMgd2hhdCBpdCBpcyAtIHNlZSBCbG9iU3RvcmUuYXBwbHlSb3V0aW5nQ29uZmlnLiBOb3RoaW5nIGhlcmUgY29uZmlndXJlcyBhbnl0aGluZy5cbiAgICBsZXQgc3RvcmVzOiBMb2FkZWRTdG9yZVtdID0gbmFtZXMubWFwKG5hbWUgPT4gKHtcbiAgICAgICAgbmFtZSxcbiAgICAgICAgZW50cmllczogZW50cmllc0J5TmFtZS5nZXQobmFtZSkgfHwgW10sXG4gICAgICAgIGZvbGRlcjogZ2V0QnVja2V0Rm9sZGVyKG5hbWUsIGFjY291bnQsIGJ1Y2tldE5hbWUpLFxuICAgICAgICBzdG9yZTogZ2V0U3RvcmUoYWNjb3VudCwgYnVja2V0TmFtZSwgbmFtZSksXG4gICAgfSkpO1xuICAgIGxldCBsb2FkZWQ6IEJ1Y2tldFN0YXRlID0geyBhY2NvdW50LCBidWNrZXROYW1lLCByb3V0aW5nLCBzZWxmRW50cmllczogcGxhbj8uc2VsZkVudHJpZXMgfHwgW10sIHNlbGY6IHBsYW4/LnNlbGYsIHN0b3JlcyB9O1xuICAgIGxvYWRlZEJ1Y2tldHMuc2V0KGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gLCBsb2FkZWQpO1xuICAgIHNjaGVkdWxlQm91bmRhcnlXb3JrKGxvYWRlZCk7XG4gICAgcmV0dXJuIGxvYWRlZDtcbn1cblxuLy8gQSBidWNrZXQgZXhpc3RzIGhlcmUgd2hlbiBpdCBoYXMgYXQgbGVhc3Qgb25lIHN0b3JlIGZvbGRlciAtIHRoZSBkaXNrIElTIHRoZSByZWNvcmQuIEl0cyBjb25maWcgaXMgdGhlIG5ld2VzdCBjb3B5IGFtb25nIHRob3NlIHN0b3Jlczsgd2l0aCBub25lIGF0IGFsbCBpdCBoYXMgbm8gY29uZmlnIHlldCwgd2hpY2ggaXMgYSBwZXJmZWN0bHkgZ29vZCBzdGF0ZSBmb3IgYSBzdG9yZSBub2JvZHkgaGFzIGNvbmZpZ3VyZWQuXG5hc3luYyBmdW5jdGlvbiBsb2FkQnVja2V0KGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTxCdWNrZXRTdGF0ZSB8IHVuZGVmaW5lZD4ge1xuICAgIGxldCBmb2xkZXJzID0gYXdhaXQgbGlzdEJ1Y2tldFN0b3JlRm9sZGVycyhhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBpZiAoIWZvbGRlcnMubGVuZ3RoKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGxldCByb3V0aW5nID0gYXdhaXQgcmVhZFJvdXRpbmdGcm9tRGlzayhhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICByZXR1cm4gYnVpbGRCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSwgZm9sZGVycy5tYXAoeCA9PiB4Lm5hbWUpLCByb3V0aW5nKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldExvYWRlZEJ1Y2tldChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8QnVja2V0U3RhdGUgfCB1bmRlZmluZWQ+IHtcbiAgICBsZXQga2V5ID0gYCR7YWNjb3VudH0vJHtidWNrZXROYW1lfWA7XG4gICAgcmV0dXJuIGJ1Y2tldHMuZ2V0KGtleSkgfHwgcmVsb2FkQnVja2V0KGFjY291bnQsIGJ1Y2tldE5hbWUpO1xufVxuXG4vKiogUmUtcmVhZHMgdGhlIGJ1Y2tldCBvZmYgdGhlIGRpc2ssIHJlcGxhY2luZyB0aGUgY2FjaGVkIHNuYXBzaG90OiB3aGF0IGEgcm91dGluZy1jb25maWcgd3JpdGUgY2FsbHMsIGJlY2F1c2UgdGhhdCB3cml0ZSBjYW4gQ1JFQVRFIGEgc3RvcmUgKGEgbmV3IG5hbWUgZ2V0cyBhIG5ldyBmb2xkZXIpIGFuZCB0aGUgc25hcHNob3Qgd291bGQga2VlcCBhbnN3ZXJpbmcgd2l0aCB0aGUgc3RvcmVzIGl0IHNhdyBhdCBsb2FkIHRpbWUuIEV4aXN0aW5nIHN0b3JlcyBhcmUgcmV1c2VkIChnZXRTdG9yZSBjYWNoZXMgYnkgZm9sZGVyKSwgc28gdGhpcyBvbmx5IHBpY2tzIHVwIGZvbGRlciBjaGFuZ2VzIC0gaXQgbmV2ZXIgcmVzdGFydHMgYSBzdG9yZS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWxvYWRCdWNrZXQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPEJ1Y2tldFN0YXRlIHwgdW5kZWZpbmVkPiB7XG4gICAgbGV0IGtleSA9IGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gO1xuICAgIGxldCBsb2FkZWQgPSBsb2FkQnVja2V0KGFjY291bnQsIGJ1Y2tldE5hbWUpO1xuICAgIGJ1Y2tldHMuc2V0KGtleSwgbG9hZGVkKTtcbiAgICB2b2lkIGxvYWRlZC50aGVuKGJ1Y2tldCA9PiB7XG4gICAgICAgIGlmICghYnVja2V0ICYmIGJ1Y2tldHMuZ2V0KGtleSkgPT09IGxvYWRlZCkge1xuICAgICAgICAgICAgYnVja2V0cy5kZWxldGUoa2V5KTtcbiAgICAgICAgfVxuICAgIH0sICgpID0+IHtcbiAgICAgICAgaWYgKGJ1Y2tldHMuZ2V0KGtleSkgPT09IGxvYWRlZCkge1xuICAgICAgICAgICAgYnVja2V0cy5kZWxldGUoa2V5KTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBhd2FpdCBsb2FkZWQ7XG59XG5cbi8qKlxuICogV3JpdGluZyB0aGUgcm91dGluZyBjb25maWcgaXMgYSB3cml0ZSBsaWtlIGFueSBvdGhlcjogaXQgZ29lcyBpbnRvIGEgc3RvcmUsIGFuZCB0aGUgc3RvcmUgYXBwbGllc1xuICogaXQgdG8gaXRzZWxmIGFuZCBsZXRzIGl0cyBwZWVycyBwdWxsIGl0LiBUaGUgb25seSB0aGluZyB0aGF0IGhhcHBlbnMgaGVyZSBpcyBwaWNraW5nIFdISUNIIHN0b3JlLFxuICogYmVjYXVzZSB0aGUgd3JpdGVyIG5hbWVzIGEgc291cmNlIGFuZCBhIHNvdXJjZSBuYW1lcyBhIHN0b3JlLlxuICpcbiAqIEluLWZsaWdodCBzd2l0Y2hvdmVyIHdpbmRvd3MgYXJlIHJlLWluamVjdGVkIGZpcnN0IChzZWUgaW50ZXJtZWRpYXRlTWFuYWdlbWVudCk6IGFuIG9wZXJhdG9yJ3NcbiAqIGNvbmZpZyBrbm93cyBub3RoaW5nIGFib3V0IGEgc3dpdGNob3ZlciB0aGF0IGlzIGhhcHBlbmluZyByaWdodCBub3csIGFuZCB3cml0aW5nIGl0IGFzLWlzIHdvdWxkXG4gKiBjYW5jZWwgaXQgbWlkLWZsaWdodC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdyaXRlUm91dGluZ0NvbmZpZyhhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgbmFtZTogc3RyaW5nLCBkYXRhOiBCdWZmZXIsIGNvbmZpZz86IHsgbGFzdE1vZGlmaWVkPzogbnVtYmVyIH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhc3NlcnRXcml0ZXNBbGxvd2VkKCk7XG4gICAgbGV0IHN0b3JlID0gZ2V0U3RvcmUoYWNjb3VudCwgYnVja2V0TmFtZSwgbmFtZSk7XG4gICAgbGV0IGluY29taW5nID0gcGFyc2VSb3V0aW5nRGF0YShkYXRhKTtcbiAgICBsZXQgY3VycmVudCA9IChhd2FpdCBnZXRMb2FkZWRCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSkpPy5yb3V0aW5nO1xuICAgIGxldCBzdG9yZWQgPSByZWluamVjdEludGVybWVkaWF0ZXMoY3VycmVudCwgaW5jb21pbmcpO1xuICAgIGF3YWl0IHN0b3JlLnNldCh7IHBhdGg6IFJPVVRJTkdfRklMRSwgZGF0YTogQnVmZmVyLmZyb20oc2VyaWFsaXplUmVtb3RlQ29uZmlnKHN0b3JlZCkpLCBsYXN0TW9kaWZpZWQ6IGNvbmZpZz8ubGFzdE1vZGlmaWVkIH0pO1xuICAgIC8vIFRoZSB3cml0ZSBtYXkgaGF2ZSBDUkVBVEVEIHRoZSBzdG9yZSAoYSBuZXcgbmFtZSBnZXRzIGEgbmV3IGZvbGRlciksIGFuZCB0aGUgbG9hZGVkIGJ1Y2tldCBpcyBhIHNuYXBzaG90IG9mIHRoZSBkaXNrIC0gc28gaXQgaXMgcmUtcmVhZCwgb3IgZXZlcnkgZGF0YSB3cml0ZSBuYW1pbmcgdGhlIG5ldyBzdG9yZSBpcyByZWplY3RlZCB1bnRpbCBhIHJlc3RhcnRcbiAgICBhd2FpdCByZWxvYWRCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgYnJvYWRjYXN0Um91dGluZ0NoYW5nZWQoKTtcbn1cblxuLyoqIFdoaWNoIGJ1Y2tldHMgdGhpcyBwcm9jZXNzIGN1cnJlbnRseSBoYXMgbG9hZGVkIC0gd2hhdCBhIGRlcGxveSBzdWNjZXNzb3IgYXNrcyBpdHMgcHJlZGVjZXNzb3IgZm9yLCBzbyBpdCBhY3RpdmF0ZXMgZXhhY3RseSB0aGUgYnVja2V0cyB0aGF0IGFyZSBhY3R1YWxseSBpbiB1c2UuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWN0aXZlQnVja2V0S2V5cygpOiB7IGFjY291bnQ6IHN0cmluZzsgYnVja2V0TmFtZTogc3RyaW5nIH1bXSB7XG4gICAgcmV0dXJuIFsuLi5idWNrZXRzLmtleXMoKV0ubWFwKGtleSA9PiB7XG4gICAgICAgIGxldCBzbGFzaCA9IGtleS5pbmRleE9mKFwiL1wiKTtcbiAgICAgICAgcmV0dXJuIHsgYWNjb3VudDoga2V5LnNsaWNlKDAsIHNsYXNoKSwgYnVja2V0TmFtZToga2V5LnNsaWNlKHNsYXNoICsgMSkgfTtcbiAgICB9KTtcbn1cblxuZXhwb3J0IHR5cGUgU2VydmVyQnVja2V0SW5mbyA9IHtcbiAgICBidWNrZXROYW1lOiBzdHJpbmc7XG4gICAgYWN0aXZlOiBib29sZWFuO1xuICAgIC8qKiBXaGVyZSB0aGUgYnVja2V0J3MgZGF0YSBsaXZlcyBvbiB0aGlzIHNlcnZlciAqL1xuICAgIGZvbGRlcjogc3RyaW5nO1xuICAgIC8qKiBUaGUgZHJpdmUgdGhhdCBmb2xkZXIgaXMgb24uIEJ1Y2tldHMgc2hhcmluZyBhIGRyaXZlIHJlcG9ydCB0aGUgc2FtZSBudW1iZXJzLiAqL1xuICAgIGRpc2s/OiBCdWNrZXREaXNrSW5mbztcbiAgICBkaXNrRXJyb3I/OiBzdHJpbmc7XG4gICAgd3JpdGVTdGF0cz86IEJ1Y2tldFdyaXRlU3RhdHM7XG4gICAgY29uZmlnPzogQXJjaGl2ZXNDb25maWc7XG4gICAgZXJyb3I/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgdHlwZSBBY3RpdmVCdWNrZXRJbmZvID0ge1xuICAgIGZvbGRlcjogc3RyaW5nO1xuICAgIC8qKiBUaGUgcm91dGluZyBjb25maWcgdGhlIGJ1Y2tldCBpcyBSVU5OSU5HIG9uLCBzdHJhaWdodCBmcm9tIG1lbW9yeSAtIGluY2x1ZGluZyBzd2l0Y2hvdmVyIHdpbmRvd3Mgd3JpdHRlbiBzaW5jZSBpdCBsb2FkZWQuIEFic2VudCB3aGVuIG5vbmUgb2YgaXRzIHN0b3JlcyBoYXMgb25lIHlldC4gKi9cbiAgICByb3V0aW5nPzogUmVtb3RlQ29uZmlnO1xuICAgIC8qKiBPdXIgb3duIGVudHJpZXMgaW4gdGhhdCBjb25maWcsIGFuZCB0aGVpciBzdW1tYXJpemVkIGN1cnJlbnQgcm9sZSAocm91dGVzIHVuaW9uICsgZmxhZ3MpICovXG4gICAgc2VsZkVudHJpZXM6IEhvc3RlZENvbmZpZ1tdO1xuICAgIHNlbGY/OiBTZWxmU3VtbWFyeTtcbiAgICBjb25maWc6IEFyY2hpdmVzQ29uZmlnO1xufTtcblxuZnVuY3Rpb24gdG9BY3RpdmVCdWNrZXRJbmZvKGxvYWRlZDogQnVja2V0U3RhdGUpOiBBY3RpdmVCdWNrZXRJbmZvIHtcbiAgICByZXR1cm4ge1xuICAgICAgICAvLyBPbmUgb2YgaXRzIHN0b3JlcycgZm9sZGVycyAtIGEgYnVja2V0IG5vIGxvbmdlciBoYXMgYSBmb2xkZXIgb2YgaXRzIG93biwgaXQgaGFzIG9uZSBwZXIgc3RvcmVcbiAgICAgICAgZm9sZGVyOiBsb2FkZWQuc3RvcmVzWzBdPy5mb2xkZXIgfHwgXCJcIixcbiAgICAgICAgcm91dGluZzogbG9hZGVkLnJvdXRpbmcsXG4gICAgICAgIHNlbGZFbnRyaWVzOiBsb2FkZWQuc2VsZkVudHJpZXMsXG4gICAgICAgIHNlbGY6IGxvYWRlZC5zZWxmLFxuICAgICAgICBjb25maWc6IGdldEJ1Y2tldENvbmZpZyhsb2FkZWQpLFxuICAgIH07XG59XG5cbi8qKiBUaGUgbGl2ZSBpbi1tZW1vcnkgc3RhdGUgb2YgT05FIGJ1Y2tldCwgYW5zd2VyZWQgd2l0aG91dCB0b3VjaGluZyB0aGUgZGlzayAobm8gcm91dGluZyBmaWxlIHJlYWQsIG5vIHN0YXRmcywgbm8gc3RvcmVkIHdyaXRlIHN0YXRzKS4gUmV0dXJucyBhbiBlcnJvciBzdHJpbmcgd2hlbiB0aGUgYnVja2V0IGlzIG5vdCBsb2FkZWQgaGVyZSwgd2hpY2ggaXMgdGhlIG5vcm1hbCBzdGF0ZSBmb3IgYSBidWNrZXQgbm90aGluZyBoYXMgYWNjZXNzZWQgc2luY2Ugc3RhcnR1cC4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRBY3RpdmVCdWNrZXQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPEFjdGl2ZUJ1Y2tldEluZm8gfCBzdHJpbmc+IHtcbiAgICBsZXQga2V5ID0gYCR7YWNjb3VudH0vJHtidWNrZXROYW1lfWA7XG4gICAgbGV0IGxvYWRlZFByb21pc2UgPSBidWNrZXRzLmdldChrZXkpO1xuICAgIGlmICghbG9hZGVkUHJvbWlzZSkge1xuICAgICAgICByZXR1cm4gYEJ1Y2tldCAke2tleX0gaXMgbm90IGxvYWRlZCBvbiB0aGlzIHNlcnZlciwgc28gaXQgaGFzIG5vIGxpdmUgc3RhdGUgKGl0IGxvYWRzIG9uIGZpcnN0IGFjY2VzcylgO1xuICAgIH1cbiAgICBsZXQgbG9hZGVkOiBCdWNrZXRTdGF0ZSB8IHVuZGVmaW5lZDtcbiAgICB0cnkge1xuICAgICAgICBsb2FkZWQgPSBhd2FpdCBsb2FkZWRQcm9taXNlO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIGBCdWNrZXQgJHtrZXl9IGZhaWxlZCB0byBsb2FkIG9uIHRoaXMgc2VydmVyOiAke1N0cmluZygoZSBhcyBFcnJvcikuc3RhY2sgPz8gZSkuc2xpY2UoMCwgNTAwKX1gO1xuICAgIH1cbiAgICBpZiAoIWxvYWRlZCkge1xuICAgICAgICByZXR1cm4gYEJ1Y2tldCAke2tleX0gZG9lcyBub3QgZXhpc3Qgb24gdGhpcyBzZXJ2ZXJgO1xuICAgIH1cbiAgICByZXR1cm4gdG9BY3RpdmVCdWNrZXRJbmZvKGxvYWRlZCk7XG59XG5cbi8qKiBMb2FkcyBhIGJ1Y2tldCB0aGF0IGV4aXN0cyBvbiB0aGlzIHNlcnZlcidzIGRpc2sgaW50byBtZW1vcnksIHdoaWNoIHN0YXJ0cyBpdHMgc3luY2hyb25pemF0aW9uIGFuZCB3aW5kb3cgdGltZXJzLCBhbmQgcmV0dXJucyBpdHMgbGl2ZSBzdGF0ZS4gTm90aGluZyBpcyB3cml0dGVuIGFuZCBubyBvdGhlciBzZXJ2ZXIgaXMgY29udGFjdGVkIC0gdW5saWtlIGJ1aWxkaW5nIGFuIEFyY2hpdmVzQ2hhaW4gZm9yIGl0LCB3aGljaCB3b3VsZCBwcm9iZSBldmVyeSBzb3VyY2UgYW5kIGNvdWxkIHdyaXRlIHRoZSByb3V0aW5nIGNvbmZpZy4gQWxyZWFkeS1sb2FkZWQgYnVja2V0cyBqdXN0IHJldHVybiB0aGVpciBzdGF0ZS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhY3RpdmF0ZUJ1Y2tldChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8QWN0aXZlQnVja2V0SW5mbyB8IHN0cmluZz4ge1xuICAgIGxldCBrZXkgPSBgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9YDtcbiAgICBsZXQgd2FzTG9hZGVkID0gYnVja2V0cy5oYXMoa2V5KTtcbiAgICBsZXQgbG9hZGVkOiBCdWNrZXRTdGF0ZSB8IHVuZGVmaW5lZDtcbiAgICB0cnkge1xuICAgICAgICBsb2FkZWQgPSBhd2FpdCBnZXRMb2FkZWRCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gYEJ1Y2tldCAke2tleX0gZmFpbGVkIHRvIGxvYWQgb24gdGhpcyBzZXJ2ZXI6ICR7U3RyaW5nKChlIGFzIEVycm9yKS5zdGFjayA/PyBlKS5zbGljZSgwLCA1MDApfWA7XG4gICAgfVxuICAgIGlmICghbG9hZGVkKSB7XG4gICAgICAgIHJldHVybiBgQnVja2V0ICR7a2V5fSBkb2VzIG5vdCBleGlzdCBvbiB0aGlzIHNlcnZlciAoaXQgaGFzIG5vIHN0b3JlIGZvbGRlcnMgdW5kZXIgJHtnZXRCdWNrZXRGb2xkZXIoXCI8bmFtZT5cIiwgYWNjb3VudCwgYnVja2V0TmFtZSl9KWA7XG4gICAgfVxuICAgIC8vIFdhaXQgZm9yIHRoZSBpbmRleGVzIHRvIGxvYWQsIHNvIHRoZSB0b3RhbHMgd2UgcmV0dXJuIGFyZSB0aGUgcmVhbCBvbmVzIHJhdGhlciB0aGFuIHplcm9lcyBmcm9tIHN0b3JlcyB0aGF0IGhhdmUgbm90IHJlYWQgdGhlaXIgaW5kZXggeWV0LiBUaGUgc291cmNlIHNjYW5zIGtlZXAgcnVubmluZyBpbiB0aGUgYmFja2dyb3VuZC5cbiAgICBmb3IgKGxldCBzIG9mIGxvYWRlZC5zdG9yZXMpIHtcbiAgICAgICAgYXdhaXQgcy5zdG9yZS5pbml0KCk7XG4gICAgfVxuICAgIGlmICghd2FzTG9hZGVkKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBBY3RpdmF0ZWQgYnVja2V0ICR7a2V5fSBvbiByZXF1ZXN0OiBpdCBpcyBub3cgbG9hZGVkIGFuZCBzeW5jaHJvbml6aW5nYCk7XG4gICAgfVxuICAgIHJldHVybiB0b0FjdGl2ZUJ1Y2tldEluZm8obG9hZGVkKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxpc3RBY2NvdW50QnVja2V0cyhhY2NvdW50OiBzdHJpbmcpOiBQcm9taXNlPFNlcnZlckJ1Y2tldEluZm9bXT4ge1xuICAgIGxldCBzdGFydCA9IERhdGUubm93KCk7XG4gICAgbGV0IHRpbWluZ3MgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuICAgIGFzeW5jIGZ1bmN0aW9uIHRpbWVkPFQ+KG5hbWU6IHN0cmluZywgcnVuOiAoKSA9PiBQcm9taXNlPFQ+KTogUHJvbWlzZTxUPiB7XG4gICAgICAgIGxldCBiZWdhbiA9IERhdGUubm93KCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgcnVuKCk7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICB0aW1pbmdzLnNldChuYW1lLCAodGltaW5ncy5nZXQobmFtZSkgfHwgMCkgKyAoRGF0ZS5ub3coKSAtIGJlZ2FuKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gVGhlIGRpc2sgaXMgdGhlIHJlY29yZDogYSBidWNrZXQgZXhpc3RzIGhlcmUgd2hlbiBpdCBoYXMgYXQgbGVhc3Qgb25lIHN0b3JlIGZvbGRlciwgYW5kIHNldmVyYWwgbmFtZXMgZm9yIG9uZSBidWNrZXQgYXJlIHN0aWxsIG9uZSBidWNrZXRcbiAgICBsZXQgZm9sZGVycyA9IGF3YWl0IHRpbWVkKFwicmVhZGRpclwiLCAoKSA9PiBsaXN0QWNjb3VudFN0b3JlRm9sZGVycyhhY2NvdW50KSk7XG4gICAgbGV0IGJ5QnVja2V0ID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcbiAgICBmb3IgKGxldCBzdG9yZSBvZiBmb2xkZXJzKSB7XG4gICAgICAgIGlmIChieUJ1Y2tldC5oYXMoc3RvcmUuYnVja2V0TmFtZSkpIGNvbnRpbnVlO1xuICAgICAgICBieUJ1Y2tldC5zZXQoc3RvcmUuYnVja2V0TmFtZSwgc3RvcmUuZm9sZGVyKTtcbiAgICB9XG4gICAgbGV0IG5hbWVzID0gWy4uLmJ5QnVja2V0LmtleXMoKV07XG4gICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IFByb21pc2UuYWxsKG5hbWVzLm1hcChhc3luYyBidWNrZXROYW1lID0+IHtcbiAgICAgICAgICAgIGxldCBrZXkgPSBgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9YDtcbiAgICAgICAgICAgIGxldCBmb2xkZXIgPSBieUJ1Y2tldC5nZXQoYnVja2V0TmFtZSkgfHwgXCJcIjtcbiAgICAgICAgICAgIGxldCBiYXNlOiBTZXJ2ZXJCdWNrZXRJbmZvID0geyBidWNrZXROYW1lLCBhY3RpdmU6IGZhbHNlLCBmb2xkZXIgfTtcbiAgICAgICAgICAgIGJhc2UuZGlzayA9IGF3YWl0IHRpbWVkKFwic3RhdGZzXCIsICgpID0+IGdldERpc2tJbmZvKGZvbGRlcikpLmNhdGNoKChlOiBFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGJhc2UuZGlza0Vycm9yID0gU3RyaW5nKGUuc3RhY2sgPz8gZSkuc2xpY2UoMCwgNTAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBiYXNlLndyaXRlU3RhdHMgPSBnZXRCdWNrZXRXcml0ZVN0YXRzKGtleSk7XG4gICAgICAgICAgICBjb25zdCBsb2FkZWRQcm9taXNlID0gYnVja2V0cy5nZXQoa2V5KTtcbiAgICAgICAgICAgIGlmIChsb2FkZWRQcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGxvYWRlZCA9IGF3YWl0IHRpbWVkKFwiYXdhaXRMb2FkZWRcIiwgKCkgPT4gbG9hZGVkUHJvbWlzZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsb2FkZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IC4uLmJhc2UsIGFjdGl2ZTogdHJ1ZSwgY29uZmlnOiBnZXRCdWNrZXRDb25maWcobG9hZGVkKSB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4geyAuLi5iYXNlLCBhY3RpdmU6IHRydWUsIGVycm9yOiBTdHJpbmcoKGUgYXMgRXJyb3IpLnN0YWNrID8/IGUpLnNsaWNlKDAsIDUwMCkgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IGF3YWl0IHRpbWVkKFwicmVhZFJvdXRpbmdGaWxlXCIsICgpID0+IHJlYWRSb3V0aW5nRnJvbURpc2soYWNjb3VudCwgYnVja2V0TmFtZSkpO1xuICAgICAgICAgICAgICAgIGlmICghcGFyc2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7IC4uLmJhc2UsIGVycm9yOiBgTm8gcm91dGluZyBmaWxlICgke1JPVVRJTkdfRklMRX0pIGluIGFueSBvZiBpdHMgc3RvcmVzYCB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4geyAuLi5iYXNlLCBjb25maWc6IHsgcmVtb3RlQ29uZmlnOiBwYXJzZWQgfSB9O1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IC4uLmJhc2UsIGVycm9yOiBTdHJpbmcoKGUgYXMgRXJyb3IpLnN0YWNrID8/IGUpLnNsaWNlKDAsIDUwMCkgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICAgIC8vIFRoZSBwYXJ0cyBydW4gY29uY3VycmVudGx5LCBzbyB0aGVzZSBhcmUgc3VtbWVkIHdhbGwgdGltZXMgcGVyIHBhcnQsIG5vdCBhIGJyZWFrZG93biBvZiB0aGUgdG90YWxcbiAgICAgICAgbGV0IHBhcnRzID0gWy4uLnRpbWluZ3NdLm1hcCgoW25hbWUsIG1zXSkgPT4gYCR7bmFtZX0gJHttc31tc2ApLmpvaW4oXCIsIFwiKTtcbiAgICAgICAgY29uc29sZS5sb2coYGxpc3RBY2NvdW50QnVja2V0cygke2FjY291bnR9KSB0b29rICR7RGF0ZS5ub3coKSAtIHN0YXJ0fW1zIGZvciAke25hbWVzLmxlbmd0aH0gYnVja2V0czogJHtwYXJ0c31gKTtcbiAgICB9XG59XG5cbmV4cG9ydCB0eXBlIEJ1Y2tldFdyaXRlU3RhdHMgPSB7XG4gICAgLyoqIEV2ZXJ5IHNldCBjYWxsIHRoZSBidWNrZXQgYWNjZXB0ZWQgKi9cbiAgICBvcmlnaW5hbFdyaXRlczogbnVtYmVyO1xuICAgIG9yaWdpbmFsQnl0ZXM6IG51bWJlcjtcbiAgICAvKiogV2hhdCBhY3R1YWxseSByZWFjaGVkIHRoZSBzb3VyY2VzLiBGYXN0IHdyaXRlcyBjb2FsZXNjZSByZXBlYXRlZCB3cml0ZXMgdG8gdGhlIHNhbWUga2V5LCBzbyB0aGlzIGlzIGxvd2VyIHRoYW4gdGhlIG9yaWdpbmFsIGNvdW50cyAoYW5kIGlzIHdoYXQgdGhlIGRpc2sgYWN0dWFsbHkgZGlkKS4gKi9cbiAgICBmbHVzaGVkV3JpdGVzOiBudW1iZXI7XG4gICAgZmx1c2hlZEJ5dGVzOiBudW1iZXI7XG59O1xuZnVuY3Rpb24gZW1wdHlXcml0ZVN0YXRzKCk6IEJ1Y2tldFdyaXRlU3RhdHMge1xuICAgIHJldHVybiB7IG9yaWdpbmFsV3JpdGVzOiAwLCBvcmlnaW5hbEJ5dGVzOiAwLCBmbHVzaGVkV3JpdGVzOiAwLCBmbHVzaGVkQnl0ZXM6IDAgfTtcbn1cblxuLy8gSW4gbWVtb3J5IG9ubHk6IHRvdGFscyBzaW5jZSB0aGlzIHByb2Nlc3Mgc3RhcnRlZCAob3IgdGhlIGxhc3QgY2xlYXJXcml0ZVN0YXRzKS4gUGVyc2lzdGluZyB0aGVtIHRvIGRpc2sgd2FzIG1vcmUgbWFjaGluZXJ5IHRoYW4gdGhlIG51bWJlcnMgd2VyZSB3b3J0aC5cbmNvbnN0IHdyaXRlU3RhdHMgPSBuZXcgTWFwPHN0cmluZywgQnVja2V0V3JpdGVTdGF0cz4oKTtcblxuZnVuY3Rpb24gY291bnRCdWNrZXRXcml0ZShrZXk6IHN0cmluZywga2luZDogXCJvcmlnaW5hbFwiIHwgXCJmbHVzaGVkXCIsIGJ5dGVzOiBudW1iZXIpOiB2b2lkIHtcbiAgICBsZXQgc3RhdHMgPSB3cml0ZVN0YXRzLmdldChrZXkpO1xuICAgIGlmICghc3RhdHMpIHtcbiAgICAgICAgc3RhdHMgPSBlbXB0eVdyaXRlU3RhdHMoKTtcbiAgICAgICAgd3JpdGVTdGF0cy5zZXQoa2V5LCBzdGF0cyk7XG4gICAgfVxuICAgIGlmIChraW5kID09PSBcIm9yaWdpbmFsXCIpIHtcbiAgICAgICAgc3RhdHMub3JpZ2luYWxXcml0ZXMrKztcbiAgICAgICAgc3RhdHMub3JpZ2luYWxCeXRlcyArPSBieXRlcztcbiAgICB9IGVsc2Uge1xuICAgICAgICBzdGF0cy5mbHVzaGVkV3JpdGVzKys7XG4gICAgICAgIHN0YXRzLmZsdXNoZWRCeXRlcyArPSBieXRlcztcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldEJ1Y2tldFdyaXRlU3RhdHMoa2V5OiBzdHJpbmcpOiBCdWNrZXRXcml0ZVN0YXRzIHtcbiAgICByZXR1cm4gd3JpdGVTdGF0cy5nZXQoa2V5KSB8fCBlbXB0eVdyaXRlU3RhdHMoKTtcbn1cblxuLyoqIFplcm9lcyB0aGUgd3JpdGUgc3RhdGlzdGljcyBvZiBldmVyeSBidWNrZXQgaW4gdGhlIGFjY291bnQuICovXG5leHBvcnQgZnVuY3Rpb24gY2xlYXJBY2NvdW50V3JpdGVTdGF0cyhhY2NvdW50OiBzdHJpbmcpOiBudW1iZXIge1xuICAgIGxldCBwcmVmaXggPSBgJHthY2NvdW50fS9gO1xuICAgIGxldCBjbGVhcmVkID0gMDtcbiAgICBmb3IgKGxldCBrZXkgb2YgWy4uLndyaXRlU3RhdHMua2V5cygpXSkge1xuICAgICAgICBpZiAoIWtleS5zdGFydHNXaXRoKHByZWZpeCkpIGNvbnRpbnVlO1xuICAgICAgICB3cml0ZVN0YXRzLmRlbGV0ZShrZXkpO1xuICAgICAgICBjbGVhcmVkKys7XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKGBDbGVhcmVkIHRoZSB3cml0ZSBzdGF0aXN0aWNzIG9mICR7Y2xlYXJlZH0gYnVja2V0cyBpbiBhY2NvdW50ICR7YWNjb3VudH1gKTtcbiAgICByZXR1cm4gY2xlYXJlZDtcbn1cbiJdfQ==
390
+ /* _JS_SOURCE_HASH = "30e439e150cb478d27dce6c02f954eb14cc1e05bb1d8589b039ef177b3ae996e"; */