@hanzo/s3 0.6.4 → 8.0.7

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 (119) hide show
  1. package/LICENSE +202 -0
  2. package/MAINTAINERS.md +62 -0
  3. package/README.md +262 -0
  4. package/README_zh_CN.md +192 -0
  5. package/dist/esm/AssumeRoleProvider.d.mts +86 -0
  6. package/dist/esm/AssumeRoleProvider.mjs +183 -0
  7. package/dist/esm/CredentialProvider.d.mts +22 -0
  8. package/dist/esm/CredentialProvider.mjs +48 -0
  9. package/dist/esm/Credentials.d.mts +22 -0
  10. package/dist/esm/Credentials.mjs +38 -0
  11. package/dist/esm/IamAwsProvider.d.mts +27 -0
  12. package/dist/esm/IamAwsProvider.mjs +189 -0
  13. package/dist/esm/errors.d.mts +82 -0
  14. package/dist/esm/errors.mjs +117 -0
  15. package/dist/esm/helpers.d.mts +156 -0
  16. package/dist/esm/helpers.mjs +218 -0
  17. package/dist/esm/internal/async.d.mts +9 -0
  18. package/dist/esm/internal/async.mjs +14 -0
  19. package/dist/esm/internal/callbackify.d.mts +1 -0
  20. package/dist/esm/internal/callbackify.mjs +15 -0
  21. package/dist/esm/internal/client.d.mts +394 -0
  22. package/dist/esm/internal/client.mjs +3007 -0
  23. package/dist/esm/internal/copy-conditions.d.mts +10 -0
  24. package/dist/esm/internal/copy-conditions.mjs +25 -0
  25. package/dist/esm/internal/extensions.d.mts +18 -0
  26. package/dist/esm/internal/extensions.mjs +114 -0
  27. package/dist/esm/internal/helper.d.mts +177 -0
  28. package/dist/esm/internal/helper.mjs +552 -0
  29. package/dist/esm/internal/join-host-port.d.mts +11 -0
  30. package/dist/esm/internal/join-host-port.mjs +23 -0
  31. package/dist/esm/internal/post-policy.d.mts +17 -0
  32. package/dist/esm/internal/post-policy.mjs +98 -0
  33. package/dist/esm/internal/request.d.mts +11 -0
  34. package/dist/esm/internal/request.mjs +75 -0
  35. package/dist/esm/internal/response.d.mts +8 -0
  36. package/dist/esm/internal/response.mjs +16 -0
  37. package/dist/esm/internal/s3-endpoints.d.mts +38 -0
  38. package/dist/esm/internal/s3-endpoints.mjs +68 -0
  39. package/dist/esm/internal/type.d.mts +482 -0
  40. package/dist/esm/internal/type.mjs +30 -0
  41. package/dist/esm/internal/xml-parser.d.mts +93 -0
  42. package/dist/esm/internal/xml-parser.mjs +819 -0
  43. package/dist/esm/notification.d.mts +58 -0
  44. package/dist/esm/notification.mjs +209 -0
  45. package/dist/esm/s3.d.mts +40 -0
  46. package/dist/esm/s3.mjs +86 -0
  47. package/dist/esm/signing.d.mts +5 -0
  48. package/dist/esm/signing.mjs +258 -0
  49. package/dist/main/AssumeRoleProvider.d.ts +86 -0
  50. package/dist/main/AssumeRoleProvider.js +191 -0
  51. package/dist/main/CredentialProvider.d.ts +22 -0
  52. package/dist/main/CredentialProvider.js +55 -0
  53. package/dist/main/Credentials.d.ts +22 -0
  54. package/dist/main/Credentials.js +45 -0
  55. package/dist/main/IamAwsProvider.d.ts +27 -0
  56. package/dist/main/IamAwsProvider.js +198 -0
  57. package/dist/main/errors.d.ts +82 -0
  58. package/dist/main/errors.js +138 -0
  59. package/dist/main/helpers.d.ts +156 -0
  60. package/dist/main/helpers.js +233 -0
  61. package/dist/main/internal/async.d.ts +9 -0
  62. package/dist/main/internal/async.js +24 -0
  63. package/dist/main/internal/callbackify.d.ts +1 -0
  64. package/dist/main/internal/callbackify.js +21 -0
  65. package/dist/main/internal/client.d.ts +394 -0
  66. package/dist/main/internal/client.js +3014 -0
  67. package/dist/main/internal/copy-conditions.d.ts +10 -0
  68. package/dist/main/internal/copy-conditions.js +31 -0
  69. package/dist/main/internal/extensions.d.ts +18 -0
  70. package/dist/main/internal/extensions.js +122 -0
  71. package/dist/main/internal/helper.d.ts +177 -0
  72. package/dist/main/internal/helper.js +608 -0
  73. package/dist/main/internal/join-host-port.d.ts +11 -0
  74. package/dist/main/internal/join-host-port.js +29 -0
  75. package/dist/main/internal/post-policy.d.ts +17 -0
  76. package/dist/main/internal/post-policy.js +107 -0
  77. package/dist/main/internal/request.d.ts +11 -0
  78. package/dist/main/internal/request.js +83 -0
  79. package/dist/main/internal/response.d.ts +8 -0
  80. package/dist/main/internal/response.js +24 -0
  81. package/dist/main/internal/s3-endpoints.d.ts +38 -0
  82. package/dist/main/internal/s3-endpoints.js +73 -0
  83. package/dist/main/internal/type.d.ts +482 -0
  84. package/dist/main/internal/type.js +42 -0
  85. package/dist/main/internal/xml-parser.d.ts +93 -0
  86. package/dist/main/internal/xml-parser.js +849 -0
  87. package/dist/main/notification.d.ts +58 -0
  88. package/dist/main/notification.js +230 -0
  89. package/dist/main/s3.d.ts +40 -0
  90. package/dist/main/s3.js +117 -0
  91. package/dist/main/signing.d.ts +5 -0
  92. package/dist/main/signing.js +269 -0
  93. package/package.json +146 -39
  94. package/src/AssumeRoleProvider.ts +262 -0
  95. package/src/CredentialProvider.ts +54 -0
  96. package/src/Credentials.ts +44 -0
  97. package/src/IamAwsProvider.ts +234 -0
  98. package/src/errors.ts +120 -0
  99. package/src/helpers.ts +354 -0
  100. package/src/internal/async.ts +14 -0
  101. package/src/internal/callbackify.ts +19 -0
  102. package/src/internal/client.ts +3412 -0
  103. package/src/internal/copy-conditions.ts +30 -0
  104. package/src/internal/extensions.ts +140 -0
  105. package/src/internal/helper.ts +606 -0
  106. package/src/internal/join-host-port.ts +23 -0
  107. package/src/internal/post-policy.ts +99 -0
  108. package/src/internal/request.ts +102 -0
  109. package/src/internal/response.ts +26 -0
  110. package/src/internal/s3-endpoints.ts +70 -0
  111. package/src/internal/type.ts +577 -0
  112. package/src/internal/xml-parser.ts +871 -0
  113. package/src/notification.ts +254 -0
  114. package/src/s3.ts +155 -0
  115. package/src/signing.ts +325 -0
  116. package/lib/index.js +0 -450
  117. package/lib/index.js.map +0 -7
  118. package/lib/perfTest.js +0 -91
  119. package/lib/perfTest.js.map +0 -7
@@ -0,0 +1,3007 @@
1
+ import * as crypto from "crypto";
2
+ import * as fs from "fs";
3
+ import * as http from "http";
4
+ import * as https from "https";
5
+ import * as path from "path";
6
+ import * as stream from "stream";
7
+ import * as async from 'async';
8
+ import BlockStream2 from 'block-stream2';
9
+ import { isBrowser } from 'browser-or-node';
10
+ import _ from 'lodash';
11
+ import * as qs from 'query-string';
12
+ import xml2js from 'xml2js';
13
+ import { CredentialProvider } from "../CredentialProvider.mjs";
14
+ import * as errors from "../errors.mjs";
15
+ import { CopyDestinationOptions, CopySourceOptions, DEFAULT_REGION, LEGAL_HOLD_STATUS, PRESIGN_EXPIRY_DAYS_MAX, RETENTION_MODES, RETENTION_VALIDITY_UNITS } from "../helpers.mjs";
16
+ import { NotificationConfig, NotificationPoller } from "../notification.mjs";
17
+ import { postPresignSignatureV4, presignSignatureV4, signV4 } from "../signing.mjs";
18
+ import { fsp, streamPromise } from "./async.mjs";
19
+ import { CopyConditions } from "./copy-conditions.mjs";
20
+ import { Extensions } from "./extensions.mjs";
21
+ import { calculateEvenSplits, extractMetadata, getContentLength, getScope, getSourceVersionId, getVersionId, hashBinary, insertContentType, isAmazonEndpoint, isBoolean, isDefined, isEmpty, isNumber, isObject, isPlainObject, isReadableStream, isString, isValidBucketName, isValidEndpoint, isValidObjectName, isValidPort, isValidPrefix, isVirtualHostStyle, makeDateLong, PART_CONSTRAINTS, partsRequired, prependXAMZMeta, readableStream, sanitizeETag, toMd5, toSha256, uriEscape, uriResourceEscape } from "./helper.mjs";
22
+ import { joinHostPort } from "./join-host-port.mjs";
23
+ import { PostPolicy } from "./post-policy.mjs";
24
+ import { requestWithRetry } from "./request.mjs";
25
+ import { drainResponse, readAsBuffer, readAsString } from "./response.mjs";
26
+ import { getS3Endpoint } from "./s3-endpoints.mjs";
27
+ import { parseBucketNotification, parseCompleteMultipart, parseInitiateMultipart, parseListObjects, parseListObjectsV2, parseObjectLegalHoldConfig, parseSelectObjectContentResponse, uploadPartParser } from "./xml-parser.mjs";
28
+ import * as xmlParsers from "./xml-parser.mjs";
29
+ const xml = new xml2js.Builder({
30
+ renderOpts: {
31
+ pretty: false
32
+ },
33
+ headless: true
34
+ });
35
+
36
+ // will be replaced by bundler.
37
+ const Package = {
38
+ version: "8.0.7" || 'development'
39
+ };
40
+ const requestOptionProperties = ['agent', 'ca', 'cert', 'ciphers', 'clientCertEngine', 'crl', 'dhparam', 'ecdhCurve', 'family', 'honorCipherOrder', 'key', 'passphrase', 'pfx', 'rejectUnauthorized', 'secureOptions', 'secureProtocol', 'servername', 'sessionIdContext'];
41
+ export class TypedClient {
42
+ partSize = 64 * 1024 * 1024;
43
+ maximumPartSize = 5 * 1024 * 1024 * 1024;
44
+ maxObjectSize = 5 * 1024 * 1024 * 1024 * 1024;
45
+ constructor(params) {
46
+ // @ts-expect-error deprecated property
47
+ if (params.secure !== undefined) {
48
+ throw new Error('"secure" option deprecated, "useSSL" should be used instead');
49
+ }
50
+ // Default values if not specified.
51
+ if (params.useSSL === undefined) {
52
+ params.useSSL = true;
53
+ }
54
+ if (!params.port) {
55
+ params.port = 0;
56
+ }
57
+ // Validate input params.
58
+ if (!isValidEndpoint(params.endPoint)) {
59
+ throw new errors.InvalidEndpointError(`Invalid endPoint : ${params.endPoint}`);
60
+ }
61
+ if (!isValidPort(params.port)) {
62
+ throw new errors.InvalidArgumentError(`Invalid port : ${params.port}`);
63
+ }
64
+ if (!isBoolean(params.useSSL)) {
65
+ throw new errors.InvalidArgumentError(`Invalid useSSL flag type : ${params.useSSL}, expected to be of type "boolean"`);
66
+ }
67
+
68
+ // Validate region only if its set.
69
+ if (params.region) {
70
+ if (!isString(params.region)) {
71
+ throw new errors.InvalidArgumentError(`Invalid region : ${params.region}`);
72
+ }
73
+ }
74
+ const host = params.endPoint.toLowerCase();
75
+ let port = params.port;
76
+ let protocol;
77
+ let transport;
78
+ let transportAgent;
79
+ // Validate if configuration is not using SSL
80
+ // for constructing relevant endpoints.
81
+ if (params.useSSL) {
82
+ // Defaults to secure.
83
+ transport = https;
84
+ protocol = 'https:';
85
+ port = port || 443;
86
+ transportAgent = https.globalAgent;
87
+ } else {
88
+ transport = http;
89
+ protocol = 'http:';
90
+ port = port || 80;
91
+ transportAgent = http.globalAgent;
92
+ }
93
+
94
+ // if custom transport is set, use it.
95
+ if (params.transport) {
96
+ if (!isObject(params.transport)) {
97
+ throw new errors.InvalidArgumentError(`Invalid transport type : ${params.transport}, expected to be type "object"`);
98
+ }
99
+ transport = params.transport;
100
+ }
101
+
102
+ // if custom transport agent is set, use it.
103
+ if (params.transportAgent) {
104
+ if (!isObject(params.transportAgent)) {
105
+ throw new errors.InvalidArgumentError(`Invalid transportAgent type: ${params.transportAgent}, expected to be type "object"`);
106
+ }
107
+ transportAgent = params.transportAgent;
108
+ }
109
+
110
+ // User Agent should always following the below style.
111
+ // Please open an issue to discuss any new changes here.
112
+ //
113
+ // HanzoS3 (OS; ARCH) LIB/VER APP/VER
114
+ //
115
+ const libraryComments = `(${process.platform}; ${process.arch})`;
116
+ const libraryAgent = `HanzoS3 ${libraryComments} hanzo-s3/${Package.version}`;
117
+ // User agent block ends.
118
+
119
+ this.transport = transport;
120
+ this.transportAgent = transportAgent;
121
+ this.host = host;
122
+ this.port = port;
123
+ this.protocol = protocol;
124
+ this.userAgent = `${libraryAgent}`;
125
+
126
+ // Default path style is true
127
+ if (params.pathStyle === undefined) {
128
+ this.pathStyle = true;
129
+ } else {
130
+ this.pathStyle = params.pathStyle;
131
+ }
132
+ this.accessKey = params.accessKey ?? '';
133
+ this.secretKey = params.secretKey ?? '';
134
+ this.sessionToken = params.sessionToken;
135
+ this.anonymous = !this.accessKey || !this.secretKey;
136
+ if (params.credentialsProvider) {
137
+ this.anonymous = false;
138
+ this.credentialsProvider = params.credentialsProvider;
139
+ }
140
+ this.regionMap = {};
141
+ if (params.region) {
142
+ this.region = params.region;
143
+ }
144
+ if (params.partSize) {
145
+ this.partSize = params.partSize;
146
+ this.overRidePartSize = true;
147
+ }
148
+ if (this.partSize < 5 * 1024 * 1024) {
149
+ throw new errors.InvalidArgumentError(`Part size should be greater than 5MB`);
150
+ }
151
+ if (this.partSize > 5 * 1024 * 1024 * 1024) {
152
+ throw new errors.InvalidArgumentError(`Part size should be less than 5GB`);
153
+ }
154
+
155
+ // SHA256 is enabled only for authenticated http requests. If the request is authenticated
156
+ // and the connection is https we use x-amz-content-sha256=UNSIGNED-PAYLOAD
157
+ // header for signature calculation.
158
+ this.enableSHA256 = !this.anonymous && !params.useSSL;
159
+ this.s3AccelerateEndpoint = params.s3AccelerateEndpoint || undefined;
160
+ this.reqOptions = {};
161
+ this.clientExtensions = new Extensions(this);
162
+ if (params.retryOptions) {
163
+ if (!isObject(params.retryOptions)) {
164
+ throw new errors.InvalidArgumentError(`Invalid retryOptions type: ${params.retryOptions}, expected to be type "object"`);
165
+ }
166
+ this.retryOptions = params.retryOptions;
167
+ } else {
168
+ this.retryOptions = {
169
+ disableRetry: false
170
+ };
171
+ }
172
+ }
173
+ /**
174
+ * S3 extensions that aren't necessarily present for Amazon S3 compatible storage servers
175
+ */
176
+ get extensions() {
177
+ return this.clientExtensions;
178
+ }
179
+
180
+ /**
181
+ * @param endPoint - valid S3 acceleration end point
182
+ */
183
+ setS3TransferAccelerate(endPoint) {
184
+ this.s3AccelerateEndpoint = endPoint;
185
+ }
186
+
187
+ /**
188
+ * Sets the supported request options.
189
+ */
190
+ setRequestOptions(options) {
191
+ if (!isObject(options)) {
192
+ throw new TypeError('request options should be of type "object"');
193
+ }
194
+ this.reqOptions = _.pick(options, requestOptionProperties);
195
+ }
196
+
197
+ /**
198
+ * This is s3 Specific and does not hold validity in any other Object storage.
199
+ */
200
+ getAccelerateEndPointIfSet(bucketName, objectName) {
201
+ if (!isEmpty(this.s3AccelerateEndpoint) && !isEmpty(bucketName) && !isEmpty(objectName)) {
202
+ // http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html
203
+ // Disable transfer acceleration for non-compliant bucket names.
204
+ if (bucketName.includes('.')) {
205
+ throw new Error(`Transfer Acceleration is not supported for non compliant bucket:${bucketName}`);
206
+ }
207
+ // If transfer acceleration is requested set new host.
208
+ // For more details about enabling transfer acceleration read here.
209
+ // http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html
210
+ return this.s3AccelerateEndpoint;
211
+ }
212
+ return false;
213
+ }
214
+
215
+ /**
216
+ * Set application specific information.
217
+ * Generates User-Agent in the following style.
218
+ * HanzoS3 (OS; ARCH) LIB/VER APP/VER
219
+ */
220
+ setAppInfo(appName, appVersion) {
221
+ if (!isString(appName)) {
222
+ throw new TypeError(`Invalid appName: ${appName}`);
223
+ }
224
+ if (appName.trim() === '') {
225
+ throw new errors.InvalidArgumentError('Input appName cannot be empty.');
226
+ }
227
+ if (!isString(appVersion)) {
228
+ throw new TypeError(`Invalid appVersion: ${appVersion}`);
229
+ }
230
+ if (appVersion.trim() === '') {
231
+ throw new errors.InvalidArgumentError('Input appVersion cannot be empty.');
232
+ }
233
+ this.userAgent = `${this.userAgent} ${appName}/${appVersion}`;
234
+ }
235
+
236
+ /**
237
+ * returns options object that can be used with http.request()
238
+ * Takes care of constructing virtual-host-style or path-style hostname
239
+ */
240
+ getRequestOptions(opts) {
241
+ const method = opts.method;
242
+ const region = opts.region;
243
+ const bucketName = opts.bucketName;
244
+ let objectName = opts.objectName;
245
+ const headers = opts.headers;
246
+ const query = opts.query;
247
+ let reqOptions = {
248
+ method,
249
+ headers: {},
250
+ protocol: this.protocol,
251
+ // If custom transportAgent was supplied earlier, we'll inject it here
252
+ agent: this.transportAgent
253
+ };
254
+
255
+ // Verify if virtual host supported.
256
+ let virtualHostStyle;
257
+ if (bucketName) {
258
+ virtualHostStyle = isVirtualHostStyle(this.host, this.protocol, bucketName, this.pathStyle);
259
+ }
260
+ let path = '/';
261
+ let host = this.host;
262
+ let port;
263
+ if (this.port) {
264
+ port = this.port;
265
+ }
266
+ if (objectName) {
267
+ objectName = uriResourceEscape(objectName);
268
+ }
269
+
270
+ // For Amazon S3 endpoint, get endpoint based on region.
271
+ if (isAmazonEndpoint(host)) {
272
+ const accelerateEndPoint = this.getAccelerateEndPointIfSet(bucketName, objectName);
273
+ if (accelerateEndPoint) {
274
+ host = `${accelerateEndPoint}`;
275
+ } else {
276
+ host = getS3Endpoint(region);
277
+ }
278
+ }
279
+ if (virtualHostStyle && !opts.pathStyle) {
280
+ // For all hosts which support virtual host style, `bucketName`
281
+ // is part of the hostname in the following format:
282
+ //
283
+ // var host = 'bucketName.example.com'
284
+ //
285
+ if (bucketName) {
286
+ host = `${bucketName}.${host}`;
287
+ }
288
+ if (objectName) {
289
+ path = `/${objectName}`;
290
+ }
291
+ } else {
292
+ // For all S3 compatible storage services we will fallback to
293
+ // path style requests, where `bucketName` is part of the URI
294
+ // path.
295
+ if (bucketName) {
296
+ path = `/${bucketName}`;
297
+ }
298
+ if (objectName) {
299
+ path = `/${bucketName}/${objectName}`;
300
+ }
301
+ }
302
+ if (query) {
303
+ path += `?${query}`;
304
+ }
305
+ reqOptions.headers.host = host;
306
+ if (reqOptions.protocol === 'http:' && port !== 80 || reqOptions.protocol === 'https:' && port !== 443) {
307
+ reqOptions.headers.host = joinHostPort(host, port);
308
+ }
309
+ reqOptions.headers['user-agent'] = this.userAgent;
310
+ if (headers) {
311
+ // have all header keys in lower case - to make signing easy
312
+ for (const [k, v] of Object.entries(headers)) {
313
+ reqOptions.headers[k.toLowerCase()] = v;
314
+ }
315
+ }
316
+
317
+ // Use any request option specified in client.setRequestOptions()
318
+ reqOptions = Object.assign({}, this.reqOptions, reqOptions);
319
+ return {
320
+ ...reqOptions,
321
+ headers: _.mapValues(_.pickBy(reqOptions.headers, isDefined), v => v.toString()),
322
+ host,
323
+ port,
324
+ path
325
+ };
326
+ }
327
+ async setCredentialsProvider(credentialsProvider) {
328
+ if (!(credentialsProvider instanceof CredentialProvider)) {
329
+ throw new Error('Unable to get credentials. Expected instance of CredentialProvider');
330
+ }
331
+ this.credentialsProvider = credentialsProvider;
332
+ await this.checkAndRefreshCreds();
333
+ }
334
+ async checkAndRefreshCreds() {
335
+ if (this.credentialsProvider) {
336
+ try {
337
+ const credentialsConf = await this.credentialsProvider.getCredentials();
338
+ this.accessKey = credentialsConf.getAccessKey();
339
+ this.secretKey = credentialsConf.getSecretKey();
340
+ this.sessionToken = credentialsConf.getSessionToken();
341
+ } catch (e) {
342
+ throw new Error(`Unable to get credentials: ${e}`, {
343
+ cause: e
344
+ });
345
+ }
346
+ }
347
+ }
348
+ /**
349
+ * log the request, response, error
350
+ */
351
+ logHTTP(reqOptions, response, err) {
352
+ // if no logStream available return.
353
+ if (!this.logStream) {
354
+ return;
355
+ }
356
+ if (!isObject(reqOptions)) {
357
+ throw new TypeError('reqOptions should be of type "object"');
358
+ }
359
+ if (response && !isReadableStream(response)) {
360
+ throw new TypeError('response should be of type "Stream"');
361
+ }
362
+ if (err && !(err instanceof Error)) {
363
+ throw new TypeError('err should be of type "Error"');
364
+ }
365
+ const logStream = this.logStream;
366
+ const logHeaders = headers => {
367
+ Object.entries(headers).forEach(([k, v]) => {
368
+ if (k == 'authorization') {
369
+ if (isString(v)) {
370
+ const redactor = new RegExp('Signature=([0-9a-f]+)');
371
+ v = v.replace(redactor, 'Signature=**REDACTED**');
372
+ }
373
+ }
374
+ logStream.write(`${k}: ${v}\n`);
375
+ });
376
+ logStream.write('\n');
377
+ };
378
+ logStream.write(`REQUEST: ${reqOptions.method} ${reqOptions.path}\n`);
379
+ logHeaders(reqOptions.headers);
380
+ if (response) {
381
+ this.logStream.write(`RESPONSE: ${response.statusCode}\n`);
382
+ logHeaders(response.headers);
383
+ }
384
+ if (err) {
385
+ logStream.write('ERROR BODY:\n');
386
+ const errJSON = JSON.stringify(err, null, '\t');
387
+ logStream.write(`${errJSON}\n`);
388
+ }
389
+ }
390
+
391
+ /**
392
+ * Enable tracing
393
+ */
394
+ traceOn(stream) {
395
+ if (!stream) {
396
+ stream = process.stdout;
397
+ }
398
+ this.logStream = stream;
399
+ }
400
+
401
+ /**
402
+ * Disable tracing
403
+ */
404
+ traceOff() {
405
+ this.logStream = undefined;
406
+ }
407
+
408
+ /**
409
+ * makeRequest is the primitive used by the apis for making S3 requests.
410
+ * payload can be empty string in case of no payload.
411
+ * statusCode is the expected statusCode. If response.statusCode does not match
412
+ * we parse the XML error and call the callback with the error message.
413
+ *
414
+ * A valid region is passed by the calls - listBuckets, makeBucket and getBucketRegion.
415
+ *
416
+ * @internal
417
+ */
418
+ async makeRequestAsync(options, payload = '', expectedCodes = [200], region = '') {
419
+ if (!isObject(options)) {
420
+ throw new TypeError('options should be of type "object"');
421
+ }
422
+ if (!isString(payload) && !isObject(payload)) {
423
+ // Buffer is of type 'object'
424
+ throw new TypeError('payload should be of type "string" or "Buffer"');
425
+ }
426
+ expectedCodes.forEach(statusCode => {
427
+ if (!isNumber(statusCode)) {
428
+ throw new TypeError('statusCode should be of type "number"');
429
+ }
430
+ });
431
+ if (!isString(region)) {
432
+ throw new TypeError('region should be of type "string"');
433
+ }
434
+ if (!options.headers) {
435
+ options.headers = {};
436
+ }
437
+ if (options.method === 'POST' || options.method === 'PUT' || options.method === 'DELETE') {
438
+ options.headers['content-length'] = payload.length.toString();
439
+ }
440
+ const sha256sum = this.enableSHA256 ? toSha256(payload) : '';
441
+ return this.makeRequestStreamAsync(options, payload, sha256sum, expectedCodes, region);
442
+ }
443
+
444
+ /**
445
+ * new request with promise
446
+ *
447
+ * No need to drain response, response body is not valid
448
+ */
449
+ async makeRequestAsyncOmit(options, payload = '', statusCodes = [200], region = '') {
450
+ const res = await this.makeRequestAsync(options, payload, statusCodes, region);
451
+ await drainResponse(res);
452
+ return res;
453
+ }
454
+
455
+ /**
456
+ * makeRequestStream will be used directly instead of makeRequest in case the payload
457
+ * is available as a stream. for ex. putObject
458
+ *
459
+ * @internal
460
+ */
461
+ async makeRequestStreamAsync(options, body, sha256sum, statusCodes, region) {
462
+ if (!isObject(options)) {
463
+ throw new TypeError('options should be of type "object"');
464
+ }
465
+ if (!(Buffer.isBuffer(body) || typeof body === 'string' || isReadableStream(body))) {
466
+ throw new errors.InvalidArgumentError(`stream should be a Buffer, string or readable Stream, got ${typeof body} instead`);
467
+ }
468
+ if (!isString(sha256sum)) {
469
+ throw new TypeError('sha256sum should be of type "string"');
470
+ }
471
+ statusCodes.forEach(statusCode => {
472
+ if (!isNumber(statusCode)) {
473
+ throw new TypeError('statusCode should be of type "number"');
474
+ }
475
+ });
476
+ if (!isString(region)) {
477
+ throw new TypeError('region should be of type "string"');
478
+ }
479
+ // sha256sum will be empty for anonymous or https requests
480
+ if (!this.enableSHA256 && sha256sum.length !== 0) {
481
+ throw new errors.InvalidArgumentError(`sha256sum expected to be empty for anonymous or https requests`);
482
+ }
483
+ // sha256sum should be valid for non-anonymous http requests.
484
+ if (this.enableSHA256 && sha256sum.length !== 64) {
485
+ throw new errors.InvalidArgumentError(`Invalid sha256sum : ${sha256sum}`);
486
+ }
487
+ await this.checkAndRefreshCreds();
488
+
489
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
490
+ region = region || (await this.getBucketRegionAsync(options.bucketName));
491
+ const reqOptions = this.getRequestOptions({
492
+ ...options,
493
+ region
494
+ });
495
+ if (!this.anonymous) {
496
+ // For non-anonymous https requests sha256sum is 'UNSIGNED-PAYLOAD' for signature calculation.
497
+ if (!this.enableSHA256) {
498
+ sha256sum = 'UNSIGNED-PAYLOAD';
499
+ }
500
+ const date = new Date();
501
+ reqOptions.headers['x-amz-date'] = makeDateLong(date);
502
+ reqOptions.headers['x-amz-content-sha256'] = sha256sum;
503
+ if (this.sessionToken) {
504
+ reqOptions.headers['x-amz-security-token'] = this.sessionToken;
505
+ }
506
+ reqOptions.headers.authorization = signV4(reqOptions, this.accessKey, this.secretKey, region, date, sha256sum);
507
+ }
508
+ const response = await requestWithRetry(this.transport, reqOptions, body, this.retryOptions.disableRetry === true ? 0 : this.retryOptions.maximumRetryCount, this.retryOptions.baseDelayMs, this.retryOptions.maximumDelayMs);
509
+ if (!response.statusCode) {
510
+ throw new Error("BUG: response doesn't have a statusCode");
511
+ }
512
+ if (!statusCodes.includes(response.statusCode)) {
513
+ // For an incorrect region, S3 server always sends back 400.
514
+ // But we will do cache invalidation for all errors so that,
515
+ // in future, if AWS S3 decides to send a different status code or
516
+ // XML error code we will still work fine.
517
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
518
+ delete this.regionMap[options.bucketName];
519
+ const err = await xmlParsers.parseResponseError(response);
520
+ this.logHTTP(reqOptions, response, err);
521
+ throw err;
522
+ }
523
+ this.logHTTP(reqOptions, response);
524
+ return response;
525
+ }
526
+
527
+ /**
528
+ * gets the region of the bucket
529
+ *
530
+ * @param bucketName
531
+ *
532
+ */
533
+ async getBucketRegionAsync(bucketName) {
534
+ if (!isValidBucketName(bucketName)) {
535
+ throw new errors.InvalidBucketNameError(`Invalid bucket name : ${bucketName}`);
536
+ }
537
+
538
+ // Region is set with constructor, return the region right here.
539
+ if (this.region) {
540
+ return this.region;
541
+ }
542
+ const cached = this.regionMap[bucketName];
543
+ if (cached) {
544
+ return cached;
545
+ }
546
+ const extractRegionAsync = async response => {
547
+ const body = await readAsString(response);
548
+ const region = xmlParsers.parseBucketRegion(body) || DEFAULT_REGION;
549
+ this.regionMap[bucketName] = region;
550
+ return region;
551
+ };
552
+ const method = 'GET';
553
+ const query = 'location';
554
+ // `getBucketLocation` behaves differently in following ways for
555
+ // different environments.
556
+ //
557
+ // - For nodejs env we default to path style requests.
558
+ // - For browser env path style requests on buckets yields CORS
559
+ // error. To circumvent this problem we make a virtual host
560
+ // style request signed with 'us-east-1'. This request fails
561
+ // with an error 'AuthorizationHeaderMalformed', additionally
562
+ // the error XML also provides Region of the bucket. To validate
563
+ // this region is proper we retry the same request with the newly
564
+ // obtained region.
565
+ const pathStyle = this.pathStyle && !isBrowser;
566
+ let region;
567
+ try {
568
+ const res = await this.makeRequestAsync({
569
+ method,
570
+ bucketName,
571
+ query,
572
+ pathStyle
573
+ }, '', [200], DEFAULT_REGION);
574
+ return extractRegionAsync(res);
575
+ } catch (e) {
576
+ // make alignment with mc cli
577
+ if (e instanceof errors.S3Error) {
578
+ const errCode = e.code;
579
+ const errRegion = e.region;
580
+ if (errCode === 'AccessDenied' && !errRegion) {
581
+ return DEFAULT_REGION;
582
+ }
583
+ }
584
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
585
+ // @ts-ignore
586
+ if (!(e.name === 'AuthorizationHeaderMalformed')) {
587
+ throw e;
588
+ }
589
+ // @ts-expect-error we set extra properties on error object
590
+ region = e.Region;
591
+ if (!region) {
592
+ throw e;
593
+ }
594
+ }
595
+ const res = await this.makeRequestAsync({
596
+ method,
597
+ bucketName,
598
+ query,
599
+ pathStyle
600
+ }, '', [200], region);
601
+ return await extractRegionAsync(res);
602
+ }
603
+
604
+ /**
605
+ * makeRequest is the primitive used by the apis for making S3 requests.
606
+ * payload can be empty string in case of no payload.
607
+ * statusCode is the expected statusCode. If response.statusCode does not match
608
+ * we parse the XML error and call the callback with the error message.
609
+ * A valid region is passed by the calls - listBuckets, makeBucket and
610
+ * getBucketRegion.
611
+ *
612
+ * @deprecated use `makeRequestAsync` instead
613
+ */
614
+ makeRequest(options, payload = '', expectedCodes = [200], region = '', returnResponse, cb) {
615
+ let prom;
616
+ if (returnResponse) {
617
+ prom = this.makeRequestAsync(options, payload, expectedCodes, region);
618
+ } else {
619
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
620
+ // @ts-expect-error compatible for old behaviour
621
+ prom = this.makeRequestAsyncOmit(options, payload, expectedCodes, region);
622
+ }
623
+ prom.then(result => cb(null, result), err => {
624
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
625
+ // @ts-ignore
626
+ cb(err);
627
+ });
628
+ }
629
+
630
+ /**
631
+ * makeRequestStream will be used directly instead of makeRequest in case the payload
632
+ * is available as a stream. for ex. putObject
633
+ *
634
+ * @deprecated use `makeRequestStreamAsync` instead
635
+ */
636
+ makeRequestStream(options, stream, sha256sum, statusCodes, region, returnResponse, cb) {
637
+ const executor = async () => {
638
+ const res = await this.makeRequestStreamAsync(options, stream, sha256sum, statusCodes, region);
639
+ if (!returnResponse) {
640
+ await drainResponse(res);
641
+ }
642
+ return res;
643
+ };
644
+ executor().then(result => cb(null, result),
645
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
646
+ // @ts-ignore
647
+ err => cb(err));
648
+ }
649
+
650
+ /**
651
+ * @deprecated use `getBucketRegionAsync` instead
652
+ */
653
+ getBucketRegion(bucketName, cb) {
654
+ return this.getBucketRegionAsync(bucketName).then(result => cb(null, result),
655
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
656
+ // @ts-ignore
657
+ err => cb(err));
658
+ }
659
+
660
+ // Bucket operations
661
+
662
+ /**
663
+ * Creates the bucket `bucketName`.
664
+ *
665
+ */
666
+ async makeBucket(bucketName, region = '', makeOpts) {
667
+ if (!isValidBucketName(bucketName)) {
668
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
669
+ }
670
+ // Backward Compatibility
671
+ if (isObject(region)) {
672
+ makeOpts = region;
673
+ region = '';
674
+ }
675
+ if (!isString(region)) {
676
+ throw new TypeError('region should be of type "string"');
677
+ }
678
+ if (makeOpts && !isObject(makeOpts)) {
679
+ throw new TypeError('makeOpts should be of type "object"');
680
+ }
681
+ let payload = '';
682
+
683
+ // Region already set in constructor, validate if
684
+ // caller requested bucket location is same.
685
+ if (region && this.region) {
686
+ if (region !== this.region) {
687
+ throw new errors.InvalidArgumentError(`Configured region ${this.region}, requested ${region}`);
688
+ }
689
+ }
690
+ // sending makeBucket request with XML containing 'us-east-1' fails. For
691
+ // default region server expects the request without body
692
+ if (region && region !== DEFAULT_REGION) {
693
+ payload = xml.buildObject({
694
+ CreateBucketConfiguration: {
695
+ $: {
696
+ xmlns: 'http://s3.amazonaws.com/doc/2006-03-01/'
697
+ },
698
+ LocationConstraint: region
699
+ }
700
+ });
701
+ }
702
+ const method = 'PUT';
703
+ const headers = {};
704
+ if (makeOpts && makeOpts.ObjectLocking) {
705
+ headers['x-amz-bucket-object-lock-enabled'] = true;
706
+ }
707
+
708
+ // For custom region clients default to custom region specified in client constructor
709
+ const finalRegion = this.region || region || DEFAULT_REGION;
710
+ const requestOpt = {
711
+ method,
712
+ bucketName,
713
+ headers
714
+ };
715
+ try {
716
+ await this.makeRequestAsyncOmit(requestOpt, payload, [200], finalRegion);
717
+ } catch (err) {
718
+ if (region === '' || region === DEFAULT_REGION) {
719
+ if (err instanceof errors.S3Error) {
720
+ const errCode = err.code;
721
+ const errRegion = err.region;
722
+ if (errCode === 'AuthorizationHeaderMalformed' && errRegion !== '') {
723
+ // Retry with region returned as part of error
724
+ await this.makeRequestAsyncOmit(requestOpt, payload, [200], errCode);
725
+ }
726
+ }
727
+ }
728
+ throw err;
729
+ }
730
+ }
731
+
732
+ /**
733
+ * To check if a bucket already exists.
734
+ */
735
+ async bucketExists(bucketName) {
736
+ if (!isValidBucketName(bucketName)) {
737
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
738
+ }
739
+ const method = 'HEAD';
740
+ try {
741
+ await this.makeRequestAsyncOmit({
742
+ method,
743
+ bucketName
744
+ });
745
+ } catch (err) {
746
+ // @ts-ignore
747
+ if (err.code === 'NoSuchBucket' || err.code === 'NotFound') {
748
+ return false;
749
+ }
750
+ throw err;
751
+ }
752
+ return true;
753
+ }
754
+
755
+ /**
756
+ * @deprecated use promise style API
757
+ */
758
+
759
+ async removeBucket(bucketName) {
760
+ if (!isValidBucketName(bucketName)) {
761
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
762
+ }
763
+ const method = 'DELETE';
764
+ await this.makeRequestAsyncOmit({
765
+ method,
766
+ bucketName
767
+ }, '', [204]);
768
+ delete this.regionMap[bucketName];
769
+ }
770
+
771
+ /**
772
+ * Callback is called with readable stream of the object content.
773
+ */
774
+ async getObject(bucketName, objectName, getOpts) {
775
+ if (!isValidBucketName(bucketName)) {
776
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
777
+ }
778
+ if (!isValidObjectName(objectName)) {
779
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
780
+ }
781
+ return this.getPartialObject(bucketName, objectName, 0, 0, getOpts);
782
+ }
783
+
784
+ /**
785
+ * Callback is called with readable stream of the partial object content.
786
+ * @param bucketName
787
+ * @param objectName
788
+ * @param offset
789
+ * @param length - length of the object that will be read in the stream (optional, if not specified we read the rest of the file from the offset)
790
+ * @param getOpts
791
+ */
792
+ async getPartialObject(bucketName, objectName, offset, length = 0, getOpts) {
793
+ if (!isValidBucketName(bucketName)) {
794
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
795
+ }
796
+ if (!isValidObjectName(objectName)) {
797
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
798
+ }
799
+ if (!isNumber(offset)) {
800
+ throw new TypeError('offset should be of type "number"');
801
+ }
802
+ if (!isNumber(length)) {
803
+ throw new TypeError('length should be of type "number"');
804
+ }
805
+ let range = '';
806
+ if (offset || length) {
807
+ if (offset) {
808
+ range = `bytes=${+offset}-`;
809
+ } else {
810
+ range = 'bytes=0-';
811
+ offset = 0;
812
+ }
813
+ if (length) {
814
+ range += `${+length + offset - 1}`;
815
+ }
816
+ }
817
+ let query = '';
818
+ let headers = {
819
+ ...(range !== '' && {
820
+ range
821
+ })
822
+ };
823
+ if (getOpts) {
824
+ const sseHeaders = {
825
+ ...(getOpts.SSECustomerAlgorithm && {
826
+ 'X-Amz-Server-Side-Encryption-Customer-Algorithm': getOpts.SSECustomerAlgorithm
827
+ }),
828
+ ...(getOpts.SSECustomerKey && {
829
+ 'X-Amz-Server-Side-Encryption-Customer-Key': getOpts.SSECustomerKey
830
+ }),
831
+ ...(getOpts.SSECustomerKeyMD5 && {
832
+ 'X-Amz-Server-Side-Encryption-Customer-Key-MD5': getOpts.SSECustomerKeyMD5
833
+ })
834
+ };
835
+ query = qs.stringify(getOpts);
836
+ headers = {
837
+ ...prependXAMZMeta(sseHeaders),
838
+ ...headers
839
+ };
840
+ }
841
+ const expectedStatusCodes = [200];
842
+ if (range) {
843
+ expectedStatusCodes.push(206);
844
+ }
845
+ const method = 'GET';
846
+ return await this.makeRequestAsync({
847
+ method,
848
+ bucketName,
849
+ objectName,
850
+ headers,
851
+ query
852
+ }, '', expectedStatusCodes);
853
+ }
854
+
855
+ /**
856
+ * download object content to a file.
857
+ * This method will create a temp file named `${filename}.${base64(etag)}.part.s3` when downloading.
858
+ *
859
+ * @param bucketName - name of the bucket
860
+ * @param objectName - name of the object
861
+ * @param filePath - path to which the object data will be written to
862
+ * @param getOpts - Optional object get option
863
+ */
864
+ async fGetObject(bucketName, objectName, filePath, getOpts) {
865
+ // Input validation.
866
+ if (!isValidBucketName(bucketName)) {
867
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
868
+ }
869
+ if (!isValidObjectName(objectName)) {
870
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
871
+ }
872
+ if (!isString(filePath)) {
873
+ throw new TypeError('filePath should be of type "string"');
874
+ }
875
+ const downloadToTmpFile = async () => {
876
+ let partFileStream;
877
+ const objStat = await this.statObject(bucketName, objectName, getOpts);
878
+ const encodedEtag = Buffer.from(objStat.etag).toString('base64');
879
+ const partFile = `${filePath}.${encodedEtag}.part.s3`;
880
+ await fsp.mkdir(path.dirname(filePath), {
881
+ recursive: true
882
+ });
883
+ let offset = 0;
884
+ try {
885
+ const stats = await fsp.stat(partFile);
886
+ if (objStat.size === stats.size) {
887
+ return partFile;
888
+ }
889
+ offset = stats.size;
890
+ partFileStream = fs.createWriteStream(partFile, {
891
+ flags: 'a'
892
+ });
893
+ } catch (e) {
894
+ if (e instanceof Error && e.code === 'ENOENT') {
895
+ // file not exist
896
+ partFileStream = fs.createWriteStream(partFile, {
897
+ flags: 'w'
898
+ });
899
+ } else {
900
+ // other error, maybe access deny
901
+ throw e;
902
+ }
903
+ }
904
+ const downloadStream = await this.getPartialObject(bucketName, objectName, offset, 0, getOpts);
905
+ await streamPromise.pipeline(downloadStream, partFileStream);
906
+ const stats = await fsp.stat(partFile);
907
+ if (stats.size === objStat.size) {
908
+ return partFile;
909
+ }
910
+ throw new Error('Size mismatch between downloaded file and the object');
911
+ };
912
+ const partFile = await downloadToTmpFile();
913
+ await fsp.rename(partFile, filePath);
914
+ }
915
+
916
+ /**
917
+ * Stat information of the object.
918
+ */
919
+ async statObject(bucketName, objectName, statOpts) {
920
+ const statOptDef = statOpts || {};
921
+ if (!isValidBucketName(bucketName)) {
922
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
923
+ }
924
+ if (!isValidObjectName(objectName)) {
925
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
926
+ }
927
+ if (!isObject(statOptDef)) {
928
+ throw new errors.InvalidArgumentError('statOpts should be of type "object"');
929
+ }
930
+ const query = qs.stringify(statOptDef);
931
+ const method = 'HEAD';
932
+ const res = await this.makeRequestAsyncOmit({
933
+ method,
934
+ bucketName,
935
+ objectName,
936
+ query
937
+ });
938
+ return {
939
+ size: parseInt(res.headers['content-length']),
940
+ metaData: extractMetadata(res.headers),
941
+ lastModified: new Date(res.headers['last-modified']),
942
+ versionId: getVersionId(res.headers),
943
+ etag: sanitizeETag(res.headers.etag)
944
+ };
945
+ }
946
+ async removeObject(bucketName, objectName, removeOpts) {
947
+ if (!isValidBucketName(bucketName)) {
948
+ throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
949
+ }
950
+ if (!isValidObjectName(objectName)) {
951
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
952
+ }
953
+ if (removeOpts && !isObject(removeOpts)) {
954
+ throw new errors.InvalidArgumentError('removeOpts should be of type "object"');
955
+ }
956
+ const method = 'DELETE';
957
+ const headers = {};
958
+ if (removeOpts !== null && removeOpts !== void 0 && removeOpts.governanceBypass) {
959
+ headers['X-Amz-Bypass-Governance-Retention'] = true;
960
+ }
961
+ if (removeOpts !== null && removeOpts !== void 0 && removeOpts.forceDelete) {
962
+ headers['x-force-delete'] = true;
963
+ }
964
+ const queryParams = {};
965
+ if (removeOpts !== null && removeOpts !== void 0 && removeOpts.versionId) {
966
+ queryParams.versionId = `${removeOpts.versionId}`;
967
+ }
968
+ const query = qs.stringify(queryParams);
969
+ await this.makeRequestAsyncOmit({
970
+ method,
971
+ bucketName,
972
+ objectName,
973
+ headers,
974
+ query
975
+ }, '', [200, 204]);
976
+ }
977
+
978
+ // Calls implemented below are related to multipart.
979
+
980
+ listIncompleteUploads(bucket, prefix, recursive) {
981
+ if (prefix === undefined) {
982
+ prefix = '';
983
+ }
984
+ if (recursive === undefined) {
985
+ recursive = false;
986
+ }
987
+ if (!isValidBucketName(bucket)) {
988
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucket);
989
+ }
990
+ if (!isValidPrefix(prefix)) {
991
+ throw new errors.InvalidPrefixError(`Invalid prefix : ${prefix}`);
992
+ }
993
+ if (!isBoolean(recursive)) {
994
+ throw new TypeError('recursive should be of type "boolean"');
995
+ }
996
+ const delimiter = recursive ? '' : '/';
997
+ let keyMarker = '';
998
+ let uploadIdMarker = '';
999
+ const uploads = [];
1000
+ let ended = false;
1001
+
1002
+ // TODO: refactor this with async/await and `stream.Readable.from`
1003
+ const readStream = new stream.Readable({
1004
+ objectMode: true
1005
+ });
1006
+ readStream._read = () => {
1007
+ // push one upload info per _read()
1008
+ if (uploads.length) {
1009
+ return readStream.push(uploads.shift());
1010
+ }
1011
+ if (ended) {
1012
+ return readStream.push(null);
1013
+ }
1014
+ this.listIncompleteUploadsQuery(bucket, prefix, keyMarker, uploadIdMarker, delimiter).then(result => {
1015
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1016
+ // @ts-ignore
1017
+ result.prefixes.forEach(prefix => uploads.push(prefix));
1018
+ async.eachSeries(result.uploads, (upload, cb) => {
1019
+ // for each incomplete upload add the sizes of its uploaded parts
1020
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1021
+ // @ts-ignore
1022
+ this.listParts(bucket, upload.key, upload.uploadId).then(parts => {
1023
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1024
+ // @ts-ignore
1025
+ upload.size = parts.reduce((acc, item) => acc + item.size, 0);
1026
+ uploads.push(upload);
1027
+ cb();
1028
+ }, err => cb(err));
1029
+ }, err => {
1030
+ if (err) {
1031
+ readStream.emit('error', err);
1032
+ return;
1033
+ }
1034
+ if (result.isTruncated) {
1035
+ keyMarker = result.nextKeyMarker;
1036
+ uploadIdMarker = result.nextUploadIdMarker;
1037
+ } else {
1038
+ ended = true;
1039
+ }
1040
+
1041
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1042
+ // @ts-ignore
1043
+ readStream._read();
1044
+ });
1045
+ }, e => {
1046
+ readStream.emit('error', e);
1047
+ });
1048
+ };
1049
+ return readStream;
1050
+ }
1051
+
1052
+ /**
1053
+ * Called by listIncompleteUploads to fetch a batch of incomplete uploads.
1054
+ */
1055
+ async listIncompleteUploadsQuery(bucketName, prefix, keyMarker, uploadIdMarker, delimiter) {
1056
+ if (!isValidBucketName(bucketName)) {
1057
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1058
+ }
1059
+ if (!isString(prefix)) {
1060
+ throw new TypeError('prefix should be of type "string"');
1061
+ }
1062
+ if (!isString(keyMarker)) {
1063
+ throw new TypeError('keyMarker should be of type "string"');
1064
+ }
1065
+ if (!isString(uploadIdMarker)) {
1066
+ throw new TypeError('uploadIdMarker should be of type "string"');
1067
+ }
1068
+ if (!isString(delimiter)) {
1069
+ throw new TypeError('delimiter should be of type "string"');
1070
+ }
1071
+ const queries = [];
1072
+ queries.push(`prefix=${uriEscape(prefix)}`);
1073
+ queries.push(`delimiter=${uriEscape(delimiter)}`);
1074
+ if (keyMarker) {
1075
+ queries.push(`key-marker=${uriEscape(keyMarker)}`);
1076
+ }
1077
+ if (uploadIdMarker) {
1078
+ queries.push(`upload-id-marker=${uploadIdMarker}`);
1079
+ }
1080
+ const maxUploads = 1000;
1081
+ queries.push(`max-uploads=${maxUploads}`);
1082
+ queries.sort();
1083
+ queries.unshift('uploads');
1084
+ let query = '';
1085
+ if (queries.length > 0) {
1086
+ query = `${queries.join('&')}`;
1087
+ }
1088
+ const method = 'GET';
1089
+ const res = await this.makeRequestAsync({
1090
+ method,
1091
+ bucketName,
1092
+ query
1093
+ });
1094
+ const body = await readAsString(res);
1095
+ return xmlParsers.parseListMultipart(body);
1096
+ }
1097
+
1098
+ /**
1099
+ * Initiate a new multipart upload.
1100
+ * @internal
1101
+ */
1102
+ async initiateNewMultipartUpload(bucketName, objectName, headers) {
1103
+ if (!isValidBucketName(bucketName)) {
1104
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1105
+ }
1106
+ if (!isValidObjectName(objectName)) {
1107
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
1108
+ }
1109
+ if (!isObject(headers)) {
1110
+ throw new errors.InvalidObjectNameError('contentType should be of type "object"');
1111
+ }
1112
+ const method = 'POST';
1113
+ const query = 'uploads';
1114
+ const res = await this.makeRequestAsync({
1115
+ method,
1116
+ bucketName,
1117
+ objectName,
1118
+ query,
1119
+ headers
1120
+ });
1121
+ const body = await readAsBuffer(res);
1122
+ return parseInitiateMultipart(body.toString());
1123
+ }
1124
+
1125
+ /**
1126
+ * Internal Method to abort a multipart upload request in case of any errors.
1127
+ *
1128
+ * @param bucketName - Bucket Name
1129
+ * @param objectName - Object Name
1130
+ * @param uploadId - id of a multipart upload to cancel during compose object sequence.
1131
+ */
1132
+ async abortMultipartUpload(bucketName, objectName, uploadId) {
1133
+ const method = 'DELETE';
1134
+ const query = `uploadId=${uploadId}`;
1135
+ const requestOptions = {
1136
+ method,
1137
+ bucketName,
1138
+ objectName: objectName,
1139
+ query
1140
+ };
1141
+ await this.makeRequestAsyncOmit(requestOptions, '', [204]);
1142
+ }
1143
+ async findUploadId(bucketName, objectName) {
1144
+ var _latestUpload;
1145
+ if (!isValidBucketName(bucketName)) {
1146
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1147
+ }
1148
+ if (!isValidObjectName(objectName)) {
1149
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
1150
+ }
1151
+ let latestUpload;
1152
+ let keyMarker = '';
1153
+ let uploadIdMarker = '';
1154
+ for (;;) {
1155
+ const result = await this.listIncompleteUploadsQuery(bucketName, objectName, keyMarker, uploadIdMarker, '');
1156
+ for (const upload of result.uploads) {
1157
+ if (upload.key === objectName) {
1158
+ if (!latestUpload || upload.initiated.getTime() > latestUpload.initiated.getTime()) {
1159
+ latestUpload = upload;
1160
+ }
1161
+ }
1162
+ }
1163
+ if (result.isTruncated) {
1164
+ keyMarker = result.nextKeyMarker;
1165
+ uploadIdMarker = result.nextUploadIdMarker;
1166
+ continue;
1167
+ }
1168
+ break;
1169
+ }
1170
+ return (_latestUpload = latestUpload) === null || _latestUpload === void 0 ? void 0 : _latestUpload.uploadId;
1171
+ }
1172
+
1173
+ /**
1174
+ * this call will aggregate the parts on the server into a single object.
1175
+ */
1176
+ async completeMultipartUpload(bucketName, objectName, uploadId, etags) {
1177
+ if (!isValidBucketName(bucketName)) {
1178
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1179
+ }
1180
+ if (!isValidObjectName(objectName)) {
1181
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
1182
+ }
1183
+ if (!isString(uploadId)) {
1184
+ throw new TypeError('uploadId should be of type "string"');
1185
+ }
1186
+ if (!isObject(etags)) {
1187
+ throw new TypeError('etags should be of type "Array"');
1188
+ }
1189
+ if (!uploadId) {
1190
+ throw new errors.InvalidArgumentError('uploadId cannot be empty');
1191
+ }
1192
+ const method = 'POST';
1193
+ const query = `uploadId=${uriEscape(uploadId)}`;
1194
+ const builder = new xml2js.Builder();
1195
+ const payload = builder.buildObject({
1196
+ CompleteMultipartUpload: {
1197
+ $: {
1198
+ xmlns: 'http://s3.amazonaws.com/doc/2006-03-01/'
1199
+ },
1200
+ Part: etags.map(etag => {
1201
+ return {
1202
+ PartNumber: etag.part,
1203
+ ETag: etag.etag
1204
+ };
1205
+ })
1206
+ }
1207
+ });
1208
+ const res = await this.makeRequestAsync({
1209
+ method,
1210
+ bucketName,
1211
+ objectName,
1212
+ query
1213
+ }, payload);
1214
+ const body = await readAsBuffer(res);
1215
+ const result = parseCompleteMultipart(body.toString());
1216
+ if (!result) {
1217
+ throw new Error('BUG: failed to parse server response');
1218
+ }
1219
+ if (result.errCode) {
1220
+ // Multipart Complete API returns an error XML after a 200 http status
1221
+ throw new errors.S3Error(result.errMessage);
1222
+ }
1223
+ return {
1224
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1225
+ // @ts-ignore
1226
+ etag: result.etag,
1227
+ versionId: getVersionId(res.headers)
1228
+ };
1229
+ }
1230
+
1231
+ /**
1232
+ * Get part-info of all parts of an incomplete upload specified by uploadId.
1233
+ */
1234
+ async listParts(bucketName, objectName, uploadId) {
1235
+ if (!isValidBucketName(bucketName)) {
1236
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1237
+ }
1238
+ if (!isValidObjectName(objectName)) {
1239
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
1240
+ }
1241
+ if (!isString(uploadId)) {
1242
+ throw new TypeError('uploadId should be of type "string"');
1243
+ }
1244
+ if (!uploadId) {
1245
+ throw new errors.InvalidArgumentError('uploadId cannot be empty');
1246
+ }
1247
+ const parts = [];
1248
+ let marker = 0;
1249
+ let result;
1250
+ do {
1251
+ result = await this.listPartsQuery(bucketName, objectName, uploadId, marker);
1252
+ marker = result.marker;
1253
+ parts.push(...result.parts);
1254
+ } while (result.isTruncated);
1255
+ return parts;
1256
+ }
1257
+
1258
+ /**
1259
+ * Called by listParts to fetch a batch of part-info
1260
+ */
1261
+ async listPartsQuery(bucketName, objectName, uploadId, marker) {
1262
+ if (!isValidBucketName(bucketName)) {
1263
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1264
+ }
1265
+ if (!isValidObjectName(objectName)) {
1266
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
1267
+ }
1268
+ if (!isString(uploadId)) {
1269
+ throw new TypeError('uploadId should be of type "string"');
1270
+ }
1271
+ if (!isNumber(marker)) {
1272
+ throw new TypeError('marker should be of type "number"');
1273
+ }
1274
+ if (!uploadId) {
1275
+ throw new errors.InvalidArgumentError('uploadId cannot be empty');
1276
+ }
1277
+ let query = `uploadId=${uriEscape(uploadId)}`;
1278
+ if (marker) {
1279
+ query += `&part-number-marker=${marker}`;
1280
+ }
1281
+ const method = 'GET';
1282
+ const res = await this.makeRequestAsync({
1283
+ method,
1284
+ bucketName,
1285
+ objectName,
1286
+ query
1287
+ });
1288
+ return xmlParsers.parseListParts(await readAsString(res));
1289
+ }
1290
+ async listBuckets() {
1291
+ const method = 'GET';
1292
+ const regionConf = this.region || DEFAULT_REGION;
1293
+ const httpRes = await this.makeRequestAsync({
1294
+ method
1295
+ }, '', [200], regionConf);
1296
+ const xmlResult = await readAsString(httpRes);
1297
+ return xmlParsers.parseListBucket(xmlResult);
1298
+ }
1299
+
1300
+ /**
1301
+ * Calculate part size given the object size. Part size will be atleast this.partSize
1302
+ */
1303
+ calculatePartSize(size) {
1304
+ if (!isNumber(size)) {
1305
+ throw new TypeError('size should be of type "number"');
1306
+ }
1307
+ if (size > this.maxObjectSize) {
1308
+ throw new TypeError(`size should not be more than ${this.maxObjectSize}`);
1309
+ }
1310
+ if (this.overRidePartSize) {
1311
+ return this.partSize;
1312
+ }
1313
+ let partSize = this.partSize;
1314
+ for (;;) {
1315
+ // while(true) {...} throws linting error.
1316
+ // If partSize is big enough to accomodate the object size, then use it.
1317
+ if (partSize * 10000 > size) {
1318
+ return partSize;
1319
+ }
1320
+ // Try part sizes as 64MB, 80MB, 96MB etc.
1321
+ partSize += 16 * 1024 * 1024;
1322
+ }
1323
+ }
1324
+
1325
+ /**
1326
+ * Uploads the object using contents from a file
1327
+ */
1328
+ async fPutObject(bucketName, objectName, filePath, metaData) {
1329
+ if (!isValidBucketName(bucketName)) {
1330
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1331
+ }
1332
+ if (!isValidObjectName(objectName)) {
1333
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
1334
+ }
1335
+ if (!isString(filePath)) {
1336
+ throw new TypeError('filePath should be of type "string"');
1337
+ }
1338
+ if (metaData && !isObject(metaData)) {
1339
+ throw new TypeError('metaData should be of type "object"');
1340
+ }
1341
+
1342
+ // Inserts correct `content-type` attribute based on metaData and filePath
1343
+ metaData = insertContentType(metaData || {}, filePath);
1344
+ const stat = await fsp.stat(filePath);
1345
+ return await this.putObject(bucketName, objectName, fs.createReadStream(filePath), stat.size, metaData);
1346
+ }
1347
+
1348
+ /**
1349
+ * Uploading a stream, "Buffer" or "string".
1350
+ * It's recommended to pass `size` argument with stream.
1351
+ */
1352
+ async putObject(bucketName, objectName, stream, size, metaData) {
1353
+ if (!isValidBucketName(bucketName)) {
1354
+ throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
1355
+ }
1356
+ if (!isValidObjectName(objectName)) {
1357
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
1358
+ }
1359
+
1360
+ // We'll need to shift arguments to the left because of metaData
1361
+ // and size being optional.
1362
+ if (isObject(size)) {
1363
+ metaData = size;
1364
+ }
1365
+ // Ensures Metadata has appropriate prefix for A3 API
1366
+ const headers = prependXAMZMeta(metaData);
1367
+ if (typeof stream === 'string' || stream instanceof Buffer) {
1368
+ // Adapts the non-stream interface into a stream.
1369
+ size = stream.length;
1370
+ stream = readableStream(stream);
1371
+ } else if (!isReadableStream(stream)) {
1372
+ throw new TypeError('third argument should be of type "stream.Readable" or "Buffer" or "string"');
1373
+ }
1374
+ if (isNumber(size) && size < 0) {
1375
+ throw new errors.InvalidArgumentError(`size cannot be negative, given size: ${size}`);
1376
+ }
1377
+
1378
+ // Get the part size and forward that to the BlockStream. Default to the
1379
+ // largest block size possible if necessary.
1380
+ if (!isNumber(size)) {
1381
+ size = this.maxObjectSize;
1382
+ }
1383
+
1384
+ // Get the part size and forward that to the BlockStream. Default to the
1385
+ // largest block size possible if necessary.
1386
+ if (size === undefined) {
1387
+ const statSize = await getContentLength(stream);
1388
+ if (statSize !== null) {
1389
+ size = statSize;
1390
+ }
1391
+ }
1392
+ if (!isNumber(size)) {
1393
+ // Backward compatibility
1394
+ size = this.maxObjectSize;
1395
+ }
1396
+ if (size === 0) {
1397
+ return this.uploadBuffer(bucketName, objectName, headers, Buffer.from(''));
1398
+ }
1399
+ const partSize = this.calculatePartSize(size);
1400
+ if (typeof stream === 'string' || Buffer.isBuffer(stream) || size <= partSize) {
1401
+ const buf = isReadableStream(stream) ? await readAsBuffer(stream) : Buffer.from(stream);
1402
+ return this.uploadBuffer(bucketName, objectName, headers, buf);
1403
+ }
1404
+ return this.uploadStream(bucketName, objectName, headers, stream, partSize);
1405
+ }
1406
+
1407
+ /**
1408
+ * method to upload buffer in one call
1409
+ * @private
1410
+ */
1411
+ async uploadBuffer(bucketName, objectName, headers, buf) {
1412
+ const {
1413
+ md5sum,
1414
+ sha256sum
1415
+ } = hashBinary(buf, this.enableSHA256);
1416
+ headers['Content-Length'] = buf.length;
1417
+ if (!this.enableSHA256) {
1418
+ headers['Content-MD5'] = md5sum;
1419
+ }
1420
+ const res = await this.makeRequestStreamAsync({
1421
+ method: 'PUT',
1422
+ bucketName,
1423
+ objectName,
1424
+ headers
1425
+ }, buf, sha256sum, [200], '');
1426
+ await drainResponse(res);
1427
+ return {
1428
+ etag: sanitizeETag(res.headers.etag),
1429
+ versionId: getVersionId(res.headers)
1430
+ };
1431
+ }
1432
+
1433
+ /**
1434
+ * upload stream with MultipartUpload
1435
+ * @private
1436
+ */
1437
+ async uploadStream(bucketName, objectName, headers, body, partSize) {
1438
+ // A map of the previously uploaded chunks, for resuming a file upload. This
1439
+ // will be null if we aren't resuming an upload.
1440
+ const oldParts = {};
1441
+
1442
+ // Keep track of the etags for aggregating the chunks together later. Each
1443
+ // etag represents a single chunk of the file.
1444
+ const eTags = [];
1445
+ const previousUploadId = await this.findUploadId(bucketName, objectName);
1446
+ let uploadId;
1447
+ if (!previousUploadId) {
1448
+ uploadId = await this.initiateNewMultipartUpload(bucketName, objectName, headers);
1449
+ } else {
1450
+ uploadId = previousUploadId;
1451
+ const oldTags = await this.listParts(bucketName, objectName, previousUploadId);
1452
+ oldTags.forEach(e => {
1453
+ oldParts[e.part] = e;
1454
+ });
1455
+ }
1456
+ const chunkier = new BlockStream2({
1457
+ size: partSize,
1458
+ zeroPadding: false
1459
+ });
1460
+
1461
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1462
+ const [_, o] = await Promise.all([new Promise((resolve, reject) => {
1463
+ body.pipe(chunkier).on('error', reject);
1464
+ chunkier.on('end', resolve).on('error', reject);
1465
+ }), (async () => {
1466
+ let partNumber = 1;
1467
+ for await (const chunk of chunkier) {
1468
+ const md5 = crypto.createHash('md5').update(chunk).digest();
1469
+ const oldPart = oldParts[partNumber];
1470
+ if (oldPart) {
1471
+ if (oldPart.etag === md5.toString('hex')) {
1472
+ eTags.push({
1473
+ part: partNumber,
1474
+ etag: oldPart.etag
1475
+ });
1476
+ partNumber++;
1477
+ continue;
1478
+ }
1479
+ }
1480
+ partNumber++;
1481
+
1482
+ // now start to upload missing part
1483
+ const options = {
1484
+ method: 'PUT',
1485
+ query: qs.stringify({
1486
+ partNumber,
1487
+ uploadId
1488
+ }),
1489
+ headers: {
1490
+ 'Content-Length': chunk.length,
1491
+ 'Content-MD5': md5.toString('base64')
1492
+ },
1493
+ bucketName,
1494
+ objectName
1495
+ };
1496
+ const response = await this.makeRequestAsyncOmit(options, chunk);
1497
+ let etag = response.headers.etag;
1498
+ if (etag) {
1499
+ etag = etag.replace(/^"/, '').replace(/"$/, '');
1500
+ } else {
1501
+ etag = '';
1502
+ }
1503
+ eTags.push({
1504
+ part: partNumber,
1505
+ etag
1506
+ });
1507
+ }
1508
+ return await this.completeMultipartUpload(bucketName, objectName, uploadId, eTags);
1509
+ })()]);
1510
+ return o;
1511
+ }
1512
+ async removeBucketReplication(bucketName) {
1513
+ if (!isValidBucketName(bucketName)) {
1514
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1515
+ }
1516
+ const method = 'DELETE';
1517
+ const query = 'replication';
1518
+ await this.makeRequestAsyncOmit({
1519
+ method,
1520
+ bucketName,
1521
+ query
1522
+ }, '', [200, 204], '');
1523
+ }
1524
+ async setBucketReplication(bucketName, replicationConfig) {
1525
+ if (!isValidBucketName(bucketName)) {
1526
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1527
+ }
1528
+ if (!isObject(replicationConfig)) {
1529
+ throw new errors.InvalidArgumentError('replicationConfig should be of type "object"');
1530
+ } else {
1531
+ if (_.isEmpty(replicationConfig.role)) {
1532
+ throw new errors.InvalidArgumentError('Role cannot be empty');
1533
+ } else if (replicationConfig.role && !isString(replicationConfig.role)) {
1534
+ throw new errors.InvalidArgumentError('Invalid value for role', replicationConfig.role);
1535
+ }
1536
+ if (_.isEmpty(replicationConfig.rules)) {
1537
+ throw new errors.InvalidArgumentError('Minimum one replication rule must be specified');
1538
+ }
1539
+ }
1540
+ const method = 'PUT';
1541
+ const query = 'replication';
1542
+ const headers = {};
1543
+ const replicationParamsConfig = {
1544
+ ReplicationConfiguration: {
1545
+ Role: replicationConfig.role,
1546
+ Rule: replicationConfig.rules
1547
+ }
1548
+ };
1549
+ const builder = new xml2js.Builder({
1550
+ renderOpts: {
1551
+ pretty: false
1552
+ },
1553
+ headless: true
1554
+ });
1555
+ const payload = builder.buildObject(replicationParamsConfig);
1556
+ headers['Content-MD5'] = toMd5(payload);
1557
+ await this.makeRequestAsyncOmit({
1558
+ method,
1559
+ bucketName,
1560
+ query,
1561
+ headers
1562
+ }, payload);
1563
+ }
1564
+ async getBucketReplication(bucketName) {
1565
+ if (!isValidBucketName(bucketName)) {
1566
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1567
+ }
1568
+ const method = 'GET';
1569
+ const query = 'replication';
1570
+ const httpRes = await this.makeRequestAsync({
1571
+ method,
1572
+ bucketName,
1573
+ query
1574
+ }, '', [200, 204]);
1575
+ const xmlResult = await readAsString(httpRes);
1576
+ return xmlParsers.parseReplicationConfig(xmlResult);
1577
+ }
1578
+ async getObjectLegalHold(bucketName, objectName, getOpts) {
1579
+ if (!isValidBucketName(bucketName)) {
1580
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1581
+ }
1582
+ if (!isValidObjectName(objectName)) {
1583
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
1584
+ }
1585
+ if (getOpts) {
1586
+ if (!isObject(getOpts)) {
1587
+ throw new TypeError('getOpts should be of type "Object"');
1588
+ } else if (Object.keys(getOpts).length > 0 && getOpts.versionId && !isString(getOpts.versionId)) {
1589
+ throw new TypeError('versionId should be of type string.:', getOpts.versionId);
1590
+ }
1591
+ }
1592
+ const method = 'GET';
1593
+ let query = 'legal-hold';
1594
+ if (getOpts !== null && getOpts !== void 0 && getOpts.versionId) {
1595
+ query += `&versionId=${getOpts.versionId}`;
1596
+ }
1597
+ const httpRes = await this.makeRequestAsync({
1598
+ method,
1599
+ bucketName,
1600
+ objectName,
1601
+ query
1602
+ }, '', [200]);
1603
+ const strRes = await readAsString(httpRes);
1604
+ return parseObjectLegalHoldConfig(strRes);
1605
+ }
1606
+ async setObjectLegalHold(bucketName, objectName, setOpts = {
1607
+ status: LEGAL_HOLD_STATUS.ENABLED
1608
+ }) {
1609
+ if (!isValidBucketName(bucketName)) {
1610
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1611
+ }
1612
+ if (!isValidObjectName(objectName)) {
1613
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
1614
+ }
1615
+ if (!isObject(setOpts)) {
1616
+ throw new TypeError('setOpts should be of type "Object"');
1617
+ } else {
1618
+ if (![LEGAL_HOLD_STATUS.ENABLED, LEGAL_HOLD_STATUS.DISABLED].includes(setOpts === null || setOpts === void 0 ? void 0 : setOpts.status)) {
1619
+ throw new TypeError('Invalid status: ' + setOpts.status);
1620
+ }
1621
+ if (setOpts.versionId && !setOpts.versionId.length) {
1622
+ throw new TypeError('versionId should be of type string.:' + setOpts.versionId);
1623
+ }
1624
+ }
1625
+ const method = 'PUT';
1626
+ let query = 'legal-hold';
1627
+ if (setOpts.versionId) {
1628
+ query += `&versionId=${setOpts.versionId}`;
1629
+ }
1630
+ const config = {
1631
+ Status: setOpts.status
1632
+ };
1633
+ const builder = new xml2js.Builder({
1634
+ rootName: 'LegalHold',
1635
+ renderOpts: {
1636
+ pretty: false
1637
+ },
1638
+ headless: true
1639
+ });
1640
+ const payload = builder.buildObject(config);
1641
+ const headers = {};
1642
+ headers['Content-MD5'] = toMd5(payload);
1643
+ await this.makeRequestAsyncOmit({
1644
+ method,
1645
+ bucketName,
1646
+ objectName,
1647
+ query,
1648
+ headers
1649
+ }, payload);
1650
+ }
1651
+
1652
+ /**
1653
+ * Get Tags associated with a Bucket
1654
+ */
1655
+ async getBucketTagging(bucketName) {
1656
+ if (!isValidBucketName(bucketName)) {
1657
+ throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
1658
+ }
1659
+ const method = 'GET';
1660
+ const query = 'tagging';
1661
+ const requestOptions = {
1662
+ method,
1663
+ bucketName,
1664
+ query
1665
+ };
1666
+ const response = await this.makeRequestAsync(requestOptions);
1667
+ const body = await readAsString(response);
1668
+ return xmlParsers.parseTagging(body);
1669
+ }
1670
+
1671
+ /**
1672
+ * Get the tags associated with a bucket OR an object
1673
+ */
1674
+ async getObjectTagging(bucketName, objectName, getOpts) {
1675
+ const method = 'GET';
1676
+ let query = 'tagging';
1677
+ if (!isValidBucketName(bucketName)) {
1678
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1679
+ }
1680
+ if (!isValidObjectName(objectName)) {
1681
+ throw new errors.InvalidBucketNameError('Invalid object name: ' + objectName);
1682
+ }
1683
+ if (getOpts && !isObject(getOpts)) {
1684
+ throw new errors.InvalidArgumentError('getOpts should be of type "object"');
1685
+ }
1686
+ if (getOpts && getOpts.versionId) {
1687
+ query = `${query}&versionId=${getOpts.versionId}`;
1688
+ }
1689
+ const requestOptions = {
1690
+ method,
1691
+ bucketName,
1692
+ query
1693
+ };
1694
+ if (objectName) {
1695
+ requestOptions['objectName'] = objectName;
1696
+ }
1697
+ const response = await this.makeRequestAsync(requestOptions);
1698
+ const body = await readAsString(response);
1699
+ return xmlParsers.parseTagging(body);
1700
+ }
1701
+
1702
+ /**
1703
+ * Set the policy on a bucket or an object prefix.
1704
+ */
1705
+ async setBucketPolicy(bucketName, policy) {
1706
+ // Validate arguments.
1707
+ if (!isValidBucketName(bucketName)) {
1708
+ throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
1709
+ }
1710
+ if (!isString(policy)) {
1711
+ throw new errors.InvalidBucketPolicyError(`Invalid bucket policy: ${policy} - must be "string"`);
1712
+ }
1713
+ const query = 'policy';
1714
+ let method = 'DELETE';
1715
+ if (policy) {
1716
+ method = 'PUT';
1717
+ }
1718
+ await this.makeRequestAsyncOmit({
1719
+ method,
1720
+ bucketName,
1721
+ query
1722
+ }, policy, [204], '');
1723
+ }
1724
+
1725
+ /**
1726
+ * Get the policy on a bucket or an object prefix.
1727
+ */
1728
+ async getBucketPolicy(bucketName) {
1729
+ // Validate arguments.
1730
+ if (!isValidBucketName(bucketName)) {
1731
+ throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
1732
+ }
1733
+ const method = 'GET';
1734
+ const query = 'policy';
1735
+ const res = await this.makeRequestAsync({
1736
+ method,
1737
+ bucketName,
1738
+ query
1739
+ });
1740
+ return await readAsString(res);
1741
+ }
1742
+ async putObjectRetention(bucketName, objectName, retentionOpts = {}) {
1743
+ if (!isValidBucketName(bucketName)) {
1744
+ throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
1745
+ }
1746
+ if (!isValidObjectName(objectName)) {
1747
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
1748
+ }
1749
+ if (!isObject(retentionOpts)) {
1750
+ throw new errors.InvalidArgumentError('retentionOpts should be of type "object"');
1751
+ } else {
1752
+ if (retentionOpts.governanceBypass && !isBoolean(retentionOpts.governanceBypass)) {
1753
+ throw new errors.InvalidArgumentError(`Invalid value for governanceBypass: ${retentionOpts.governanceBypass}`);
1754
+ }
1755
+ if (retentionOpts.mode && ![RETENTION_MODES.COMPLIANCE, RETENTION_MODES.GOVERNANCE].includes(retentionOpts.mode)) {
1756
+ throw new errors.InvalidArgumentError(`Invalid object retention mode: ${retentionOpts.mode}`);
1757
+ }
1758
+ if (retentionOpts.retainUntilDate && !isString(retentionOpts.retainUntilDate)) {
1759
+ throw new errors.InvalidArgumentError(`Invalid value for retainUntilDate: ${retentionOpts.retainUntilDate}`);
1760
+ }
1761
+ if (retentionOpts.versionId && !isString(retentionOpts.versionId)) {
1762
+ throw new errors.InvalidArgumentError(`Invalid value for versionId: ${retentionOpts.versionId}`);
1763
+ }
1764
+ }
1765
+ const method = 'PUT';
1766
+ let query = 'retention';
1767
+ const headers = {};
1768
+ if (retentionOpts.governanceBypass) {
1769
+ headers['X-Amz-Bypass-Governance-Retention'] = true;
1770
+ }
1771
+ const builder = new xml2js.Builder({
1772
+ rootName: 'Retention',
1773
+ renderOpts: {
1774
+ pretty: false
1775
+ },
1776
+ headless: true
1777
+ });
1778
+ const params = {};
1779
+ if (retentionOpts.mode) {
1780
+ params.Mode = retentionOpts.mode;
1781
+ }
1782
+ if (retentionOpts.retainUntilDate) {
1783
+ params.RetainUntilDate = retentionOpts.retainUntilDate;
1784
+ }
1785
+ if (retentionOpts.versionId) {
1786
+ query += `&versionId=${retentionOpts.versionId}`;
1787
+ }
1788
+ const payload = builder.buildObject(params);
1789
+ headers['Content-MD5'] = toMd5(payload);
1790
+ await this.makeRequestAsyncOmit({
1791
+ method,
1792
+ bucketName,
1793
+ objectName,
1794
+ query,
1795
+ headers
1796
+ }, payload, [200, 204]);
1797
+ }
1798
+ async getObjectLockConfig(bucketName) {
1799
+ if (!isValidBucketName(bucketName)) {
1800
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1801
+ }
1802
+ const method = 'GET';
1803
+ const query = 'object-lock';
1804
+ const httpRes = await this.makeRequestAsync({
1805
+ method,
1806
+ bucketName,
1807
+ query
1808
+ });
1809
+ const xmlResult = await readAsString(httpRes);
1810
+ return xmlParsers.parseObjectLockConfig(xmlResult);
1811
+ }
1812
+ async setObjectLockConfig(bucketName, lockConfigOpts) {
1813
+ const retentionModes = [RETENTION_MODES.COMPLIANCE, RETENTION_MODES.GOVERNANCE];
1814
+ const validUnits = [RETENTION_VALIDITY_UNITS.DAYS, RETENTION_VALIDITY_UNITS.YEARS];
1815
+ if (!isValidBucketName(bucketName)) {
1816
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1817
+ }
1818
+ if (lockConfigOpts.mode && !retentionModes.includes(lockConfigOpts.mode)) {
1819
+ throw new TypeError(`lockConfigOpts.mode should be one of ${retentionModes}`);
1820
+ }
1821
+ if (lockConfigOpts.unit && !validUnits.includes(lockConfigOpts.unit)) {
1822
+ throw new TypeError(`lockConfigOpts.unit should be one of ${validUnits}`);
1823
+ }
1824
+ if (lockConfigOpts.validity && !isNumber(lockConfigOpts.validity)) {
1825
+ throw new TypeError(`lockConfigOpts.validity should be a number`);
1826
+ }
1827
+ const method = 'PUT';
1828
+ const query = 'object-lock';
1829
+ const config = {
1830
+ ObjectLockEnabled: 'Enabled'
1831
+ };
1832
+ const configKeys = Object.keys(lockConfigOpts);
1833
+ const isAllKeysSet = ['unit', 'mode', 'validity'].every(lck => configKeys.includes(lck));
1834
+ // Check if keys are present and all keys are present.
1835
+ if (configKeys.length > 0) {
1836
+ if (!isAllKeysSet) {
1837
+ throw new TypeError(`lockConfigOpts.mode,lockConfigOpts.unit,lockConfigOpts.validity all the properties should be specified.`);
1838
+ } else {
1839
+ config.Rule = {
1840
+ DefaultRetention: {}
1841
+ };
1842
+ if (lockConfigOpts.mode) {
1843
+ config.Rule.DefaultRetention.Mode = lockConfigOpts.mode;
1844
+ }
1845
+ if (lockConfigOpts.unit === RETENTION_VALIDITY_UNITS.DAYS) {
1846
+ config.Rule.DefaultRetention.Days = lockConfigOpts.validity;
1847
+ } else if (lockConfigOpts.unit === RETENTION_VALIDITY_UNITS.YEARS) {
1848
+ config.Rule.DefaultRetention.Years = lockConfigOpts.validity;
1849
+ }
1850
+ }
1851
+ }
1852
+ const builder = new xml2js.Builder({
1853
+ rootName: 'ObjectLockConfiguration',
1854
+ renderOpts: {
1855
+ pretty: false
1856
+ },
1857
+ headless: true
1858
+ });
1859
+ const payload = builder.buildObject(config);
1860
+ const headers = {};
1861
+ headers['Content-MD5'] = toMd5(payload);
1862
+ await this.makeRequestAsyncOmit({
1863
+ method,
1864
+ bucketName,
1865
+ query,
1866
+ headers
1867
+ }, payload);
1868
+ }
1869
+ async getBucketVersioning(bucketName) {
1870
+ if (!isValidBucketName(bucketName)) {
1871
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1872
+ }
1873
+ const method = 'GET';
1874
+ const query = 'versioning';
1875
+ const httpRes = await this.makeRequestAsync({
1876
+ method,
1877
+ bucketName,
1878
+ query
1879
+ });
1880
+ const xmlResult = await readAsString(httpRes);
1881
+ return await xmlParsers.parseBucketVersioningConfig(xmlResult);
1882
+ }
1883
+ async setBucketVersioning(bucketName, versionConfig) {
1884
+ if (!isValidBucketName(bucketName)) {
1885
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1886
+ }
1887
+ if (!Object.keys(versionConfig).length) {
1888
+ throw new errors.InvalidArgumentError('versionConfig should be of type "object"');
1889
+ }
1890
+ const method = 'PUT';
1891
+ const query = 'versioning';
1892
+ const builder = new xml2js.Builder({
1893
+ rootName: 'VersioningConfiguration',
1894
+ renderOpts: {
1895
+ pretty: false
1896
+ },
1897
+ headless: true
1898
+ });
1899
+ const payload = builder.buildObject(versionConfig);
1900
+ await this.makeRequestAsyncOmit({
1901
+ method,
1902
+ bucketName,
1903
+ query
1904
+ }, payload);
1905
+ }
1906
+ async setTagging(taggingParams) {
1907
+ const {
1908
+ bucketName,
1909
+ objectName,
1910
+ tags,
1911
+ putOpts
1912
+ } = taggingParams;
1913
+ const method = 'PUT';
1914
+ let query = 'tagging';
1915
+ if (putOpts && putOpts !== null && putOpts !== void 0 && putOpts.versionId) {
1916
+ query = `${query}&versionId=${putOpts.versionId}`;
1917
+ }
1918
+ const tagsList = [];
1919
+ for (const [key, value] of Object.entries(tags)) {
1920
+ tagsList.push({
1921
+ Key: key,
1922
+ Value: value
1923
+ });
1924
+ }
1925
+ const taggingConfig = {
1926
+ Tagging: {
1927
+ TagSet: {
1928
+ Tag: tagsList
1929
+ }
1930
+ }
1931
+ };
1932
+ const headers = {};
1933
+ const builder = new xml2js.Builder({
1934
+ headless: true,
1935
+ renderOpts: {
1936
+ pretty: false
1937
+ }
1938
+ });
1939
+ const payloadBuf = Buffer.from(builder.buildObject(taggingConfig));
1940
+ const requestOptions = {
1941
+ method,
1942
+ bucketName,
1943
+ query,
1944
+ headers,
1945
+ ...(objectName && {
1946
+ objectName: objectName
1947
+ })
1948
+ };
1949
+ headers['Content-MD5'] = toMd5(payloadBuf);
1950
+ await this.makeRequestAsyncOmit(requestOptions, payloadBuf);
1951
+ }
1952
+ async removeTagging({
1953
+ bucketName,
1954
+ objectName,
1955
+ removeOpts
1956
+ }) {
1957
+ const method = 'DELETE';
1958
+ let query = 'tagging';
1959
+ if (removeOpts && Object.keys(removeOpts).length && removeOpts.versionId) {
1960
+ query = `${query}&versionId=${removeOpts.versionId}`;
1961
+ }
1962
+ const requestOptions = {
1963
+ method,
1964
+ bucketName,
1965
+ objectName,
1966
+ query
1967
+ };
1968
+ if (objectName) {
1969
+ requestOptions['objectName'] = objectName;
1970
+ }
1971
+ await this.makeRequestAsync(requestOptions, '', [200, 204]);
1972
+ }
1973
+ async setBucketTagging(bucketName, tags) {
1974
+ if (!isValidBucketName(bucketName)) {
1975
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1976
+ }
1977
+ if (!isPlainObject(tags)) {
1978
+ throw new errors.InvalidArgumentError('tags should be of type "object"');
1979
+ }
1980
+ if (Object.keys(tags).length > 10) {
1981
+ throw new errors.InvalidArgumentError('maximum tags allowed is 10"');
1982
+ }
1983
+ await this.setTagging({
1984
+ bucketName,
1985
+ tags
1986
+ });
1987
+ }
1988
+ async removeBucketTagging(bucketName) {
1989
+ if (!isValidBucketName(bucketName)) {
1990
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1991
+ }
1992
+ await this.removeTagging({
1993
+ bucketName
1994
+ });
1995
+ }
1996
+ async setObjectTagging(bucketName, objectName, tags, putOpts) {
1997
+ if (!isValidBucketName(bucketName)) {
1998
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
1999
+ }
2000
+ if (!isValidObjectName(objectName)) {
2001
+ throw new errors.InvalidBucketNameError('Invalid object name: ' + objectName);
2002
+ }
2003
+ if (!isPlainObject(tags)) {
2004
+ throw new errors.InvalidArgumentError('tags should be of type "object"');
2005
+ }
2006
+ if (Object.keys(tags).length > 10) {
2007
+ throw new errors.InvalidArgumentError('Maximum tags allowed is 10"');
2008
+ }
2009
+ await this.setTagging({
2010
+ bucketName,
2011
+ objectName,
2012
+ tags,
2013
+ putOpts
2014
+ });
2015
+ }
2016
+ async removeObjectTagging(bucketName, objectName, removeOpts) {
2017
+ if (!isValidBucketName(bucketName)) {
2018
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
2019
+ }
2020
+ if (!isValidObjectName(objectName)) {
2021
+ throw new errors.InvalidBucketNameError('Invalid object name: ' + objectName);
2022
+ }
2023
+ if (removeOpts && Object.keys(removeOpts).length && !isObject(removeOpts)) {
2024
+ throw new errors.InvalidArgumentError('removeOpts should be of type "object"');
2025
+ }
2026
+ await this.removeTagging({
2027
+ bucketName,
2028
+ objectName,
2029
+ removeOpts
2030
+ });
2031
+ }
2032
+ async selectObjectContent(bucketName, objectName, selectOpts) {
2033
+ if (!isValidBucketName(bucketName)) {
2034
+ throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
2035
+ }
2036
+ if (!isValidObjectName(objectName)) {
2037
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
2038
+ }
2039
+ if (!_.isEmpty(selectOpts)) {
2040
+ if (!isString(selectOpts.expression)) {
2041
+ throw new TypeError('sqlExpression should be of type "string"');
2042
+ }
2043
+ if (!_.isEmpty(selectOpts.inputSerialization)) {
2044
+ if (!isObject(selectOpts.inputSerialization)) {
2045
+ throw new TypeError('inputSerialization should be of type "object"');
2046
+ }
2047
+ } else {
2048
+ throw new TypeError('inputSerialization is required');
2049
+ }
2050
+ if (!_.isEmpty(selectOpts.outputSerialization)) {
2051
+ if (!isObject(selectOpts.outputSerialization)) {
2052
+ throw new TypeError('outputSerialization should be of type "object"');
2053
+ }
2054
+ } else {
2055
+ throw new TypeError('outputSerialization is required');
2056
+ }
2057
+ } else {
2058
+ throw new TypeError('valid select configuration is required');
2059
+ }
2060
+ const method = 'POST';
2061
+ const query = `select&select-type=2`;
2062
+ const config = [{
2063
+ Expression: selectOpts.expression
2064
+ }, {
2065
+ ExpressionType: selectOpts.expressionType || 'SQL'
2066
+ }, {
2067
+ InputSerialization: [selectOpts.inputSerialization]
2068
+ }, {
2069
+ OutputSerialization: [selectOpts.outputSerialization]
2070
+ }];
2071
+
2072
+ // Optional
2073
+ if (selectOpts.requestProgress) {
2074
+ config.push({
2075
+ RequestProgress: selectOpts === null || selectOpts === void 0 ? void 0 : selectOpts.requestProgress
2076
+ });
2077
+ }
2078
+ // Optional
2079
+ if (selectOpts.scanRange) {
2080
+ config.push({
2081
+ ScanRange: selectOpts.scanRange
2082
+ });
2083
+ }
2084
+ const builder = new xml2js.Builder({
2085
+ rootName: 'SelectObjectContentRequest',
2086
+ renderOpts: {
2087
+ pretty: false
2088
+ },
2089
+ headless: true
2090
+ });
2091
+ const payload = builder.buildObject(config);
2092
+ const res = await this.makeRequestAsync({
2093
+ method,
2094
+ bucketName,
2095
+ objectName,
2096
+ query
2097
+ }, payload);
2098
+ const body = await readAsBuffer(res);
2099
+ return parseSelectObjectContentResponse(body);
2100
+ }
2101
+ async applyBucketLifecycle(bucketName, policyConfig) {
2102
+ const method = 'PUT';
2103
+ const query = 'lifecycle';
2104
+ const headers = {};
2105
+ const builder = new xml2js.Builder({
2106
+ rootName: 'LifecycleConfiguration',
2107
+ headless: true,
2108
+ renderOpts: {
2109
+ pretty: false
2110
+ }
2111
+ });
2112
+ const payload = builder.buildObject(policyConfig);
2113
+ headers['Content-MD5'] = toMd5(payload);
2114
+ await this.makeRequestAsyncOmit({
2115
+ method,
2116
+ bucketName,
2117
+ query,
2118
+ headers
2119
+ }, payload);
2120
+ }
2121
+ async removeBucketLifecycle(bucketName) {
2122
+ if (!isValidBucketName(bucketName)) {
2123
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
2124
+ }
2125
+ const method = 'DELETE';
2126
+ const query = 'lifecycle';
2127
+ await this.makeRequestAsyncOmit({
2128
+ method,
2129
+ bucketName,
2130
+ query
2131
+ }, '', [204]);
2132
+ }
2133
+ async setBucketLifecycle(bucketName, lifeCycleConfig) {
2134
+ if (!isValidBucketName(bucketName)) {
2135
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
2136
+ }
2137
+ if (_.isEmpty(lifeCycleConfig)) {
2138
+ await this.removeBucketLifecycle(bucketName);
2139
+ } else {
2140
+ await this.applyBucketLifecycle(bucketName, lifeCycleConfig);
2141
+ }
2142
+ }
2143
+ async getBucketLifecycle(bucketName) {
2144
+ if (!isValidBucketName(bucketName)) {
2145
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
2146
+ }
2147
+ const method = 'GET';
2148
+ const query = 'lifecycle';
2149
+ const res = await this.makeRequestAsync({
2150
+ method,
2151
+ bucketName,
2152
+ query
2153
+ });
2154
+ const body = await readAsString(res);
2155
+ return xmlParsers.parseLifecycleConfig(body);
2156
+ }
2157
+ async setBucketEncryption(bucketName, encryptionConfig) {
2158
+ if (!isValidBucketName(bucketName)) {
2159
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
2160
+ }
2161
+ if (!_.isEmpty(encryptionConfig) && encryptionConfig.Rule.length > 1) {
2162
+ throw new errors.InvalidArgumentError('Invalid Rule length. Only one rule is allowed.: ' + encryptionConfig.Rule);
2163
+ }
2164
+ let encryptionObj = encryptionConfig;
2165
+ if (_.isEmpty(encryptionConfig)) {
2166
+ encryptionObj = {
2167
+ // Default Hanzo S3 Server Supported Rule
2168
+ Rule: [{
2169
+ ApplyServerSideEncryptionByDefault: {
2170
+ SSEAlgorithm: 'AES256'
2171
+ }
2172
+ }]
2173
+ };
2174
+ }
2175
+ const method = 'PUT';
2176
+ const query = 'encryption';
2177
+ const builder = new xml2js.Builder({
2178
+ rootName: 'ServerSideEncryptionConfiguration',
2179
+ renderOpts: {
2180
+ pretty: false
2181
+ },
2182
+ headless: true
2183
+ });
2184
+ const payload = builder.buildObject(encryptionObj);
2185
+ const headers = {};
2186
+ headers['Content-MD5'] = toMd5(payload);
2187
+ await this.makeRequestAsyncOmit({
2188
+ method,
2189
+ bucketName,
2190
+ query,
2191
+ headers
2192
+ }, payload);
2193
+ }
2194
+ async getBucketEncryption(bucketName) {
2195
+ if (!isValidBucketName(bucketName)) {
2196
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
2197
+ }
2198
+ const method = 'GET';
2199
+ const query = 'encryption';
2200
+ const res = await this.makeRequestAsync({
2201
+ method,
2202
+ bucketName,
2203
+ query
2204
+ });
2205
+ const body = await readAsString(res);
2206
+ return xmlParsers.parseBucketEncryptionConfig(body);
2207
+ }
2208
+ async removeBucketEncryption(bucketName) {
2209
+ if (!isValidBucketName(bucketName)) {
2210
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
2211
+ }
2212
+ const method = 'DELETE';
2213
+ const query = 'encryption';
2214
+ await this.makeRequestAsyncOmit({
2215
+ method,
2216
+ bucketName,
2217
+ query
2218
+ }, '', [204]);
2219
+ }
2220
+ async getObjectRetention(bucketName, objectName, getOpts) {
2221
+ if (!isValidBucketName(bucketName)) {
2222
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
2223
+ }
2224
+ if (!isValidObjectName(objectName)) {
2225
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
2226
+ }
2227
+ if (getOpts && !isObject(getOpts)) {
2228
+ throw new errors.InvalidArgumentError('getOpts should be of type "object"');
2229
+ } else if (getOpts !== null && getOpts !== void 0 && getOpts.versionId && !isString(getOpts.versionId)) {
2230
+ throw new errors.InvalidArgumentError('versionId should be of type "string"');
2231
+ }
2232
+ const method = 'GET';
2233
+ let query = 'retention';
2234
+ if (getOpts !== null && getOpts !== void 0 && getOpts.versionId) {
2235
+ query += `&versionId=${getOpts.versionId}`;
2236
+ }
2237
+ const res = await this.makeRequestAsync({
2238
+ method,
2239
+ bucketName,
2240
+ objectName,
2241
+ query
2242
+ });
2243
+ const body = await readAsString(res);
2244
+ return xmlParsers.parseObjectRetentionConfig(body);
2245
+ }
2246
+ async removeObjects(bucketName, objectsList) {
2247
+ if (!isValidBucketName(bucketName)) {
2248
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
2249
+ }
2250
+ if (!Array.isArray(objectsList)) {
2251
+ throw new errors.InvalidArgumentError('objectsList should be a list');
2252
+ }
2253
+ const runDeleteObjects = async batch => {
2254
+ const delObjects = batch.map(value => {
2255
+ return isObject(value) ? {
2256
+ Key: value.name,
2257
+ VersionId: value.versionId
2258
+ } : {
2259
+ Key: value
2260
+ };
2261
+ });
2262
+ const remObjects = {
2263
+ Delete: {
2264
+ Quiet: true,
2265
+ Object: delObjects
2266
+ }
2267
+ };
2268
+ const payload = Buffer.from(new xml2js.Builder({
2269
+ headless: true
2270
+ }).buildObject(remObjects));
2271
+ const headers = {
2272
+ 'Content-MD5': toMd5(payload)
2273
+ };
2274
+ const res = await this.makeRequestAsync({
2275
+ method: 'POST',
2276
+ bucketName,
2277
+ query: 'delete',
2278
+ headers
2279
+ }, payload);
2280
+ const body = await readAsString(res);
2281
+ return xmlParsers.removeObjectsParser(body);
2282
+ };
2283
+ const maxEntries = 1000; // max entries accepted in server for DeleteMultipleObjects API.
2284
+ // Client side batching
2285
+ const batches = [];
2286
+ for (let i = 0; i < objectsList.length; i += maxEntries) {
2287
+ batches.push(objectsList.slice(i, i + maxEntries));
2288
+ }
2289
+ const batchResults = await Promise.all(batches.map(runDeleteObjects));
2290
+ return batchResults.flat();
2291
+ }
2292
+ async removeIncompleteUpload(bucketName, objectName) {
2293
+ if (!isValidBucketName(bucketName)) {
2294
+ throw new errors.IsValidBucketNameError('Invalid bucket name: ' + bucketName);
2295
+ }
2296
+ if (!isValidObjectName(objectName)) {
2297
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
2298
+ }
2299
+ const removeUploadId = await this.findUploadId(bucketName, objectName);
2300
+ const method = 'DELETE';
2301
+ const query = `uploadId=${removeUploadId}`;
2302
+ await this.makeRequestAsyncOmit({
2303
+ method,
2304
+ bucketName,
2305
+ objectName,
2306
+ query
2307
+ }, '', [204]);
2308
+ }
2309
+ async copyObjectV1(targetBucketName, targetObjectName, sourceBucketNameAndObjectName, conditions) {
2310
+ if (typeof conditions == 'function') {
2311
+ conditions = null;
2312
+ }
2313
+ if (!isValidBucketName(targetBucketName)) {
2314
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + targetBucketName);
2315
+ }
2316
+ if (!isValidObjectName(targetObjectName)) {
2317
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${targetObjectName}`);
2318
+ }
2319
+ if (!isString(sourceBucketNameAndObjectName)) {
2320
+ throw new TypeError('sourceBucketNameAndObjectName should be of type "string"');
2321
+ }
2322
+ if (sourceBucketNameAndObjectName === '') {
2323
+ throw new errors.InvalidPrefixError(`Empty source prefix`);
2324
+ }
2325
+ if (conditions != null && !(conditions instanceof CopyConditions)) {
2326
+ throw new TypeError('conditions should be of type "CopyConditions"');
2327
+ }
2328
+ const headers = {};
2329
+ headers['x-amz-copy-source'] = uriResourceEscape(sourceBucketNameAndObjectName);
2330
+ if (conditions) {
2331
+ if (conditions.modified !== '') {
2332
+ headers['x-amz-copy-source-if-modified-since'] = conditions.modified;
2333
+ }
2334
+ if (conditions.unmodified !== '') {
2335
+ headers['x-amz-copy-source-if-unmodified-since'] = conditions.unmodified;
2336
+ }
2337
+ if (conditions.matchETag !== '') {
2338
+ headers['x-amz-copy-source-if-match'] = conditions.matchETag;
2339
+ }
2340
+ if (conditions.matchETagExcept !== '') {
2341
+ headers['x-amz-copy-source-if-none-match'] = conditions.matchETagExcept;
2342
+ }
2343
+ }
2344
+ const method = 'PUT';
2345
+ const res = await this.makeRequestAsync({
2346
+ method,
2347
+ bucketName: targetBucketName,
2348
+ objectName: targetObjectName,
2349
+ headers
2350
+ });
2351
+ const body = await readAsString(res);
2352
+ return xmlParsers.parseCopyObject(body);
2353
+ }
2354
+ async copyObjectV2(sourceConfig, destConfig) {
2355
+ if (!(sourceConfig instanceof CopySourceOptions)) {
2356
+ throw new errors.InvalidArgumentError('sourceConfig should of type CopySourceOptions ');
2357
+ }
2358
+ if (!(destConfig instanceof CopyDestinationOptions)) {
2359
+ throw new errors.InvalidArgumentError('destConfig should of type CopyDestinationOptions ');
2360
+ }
2361
+ if (!destConfig.validate()) {
2362
+ return Promise.reject();
2363
+ }
2364
+ if (!destConfig.validate()) {
2365
+ return Promise.reject();
2366
+ }
2367
+ const headers = Object.assign({}, sourceConfig.getHeaders(), destConfig.getHeaders());
2368
+ const bucketName = destConfig.Bucket;
2369
+ const objectName = destConfig.Object;
2370
+ const method = 'PUT';
2371
+ const res = await this.makeRequestAsync({
2372
+ method,
2373
+ bucketName,
2374
+ objectName,
2375
+ headers
2376
+ });
2377
+ const body = await readAsString(res);
2378
+ const copyRes = xmlParsers.parseCopyObject(body);
2379
+ const resHeaders = res.headers;
2380
+ const sizeHeaderValue = resHeaders && resHeaders['content-length'];
2381
+ const size = typeof sizeHeaderValue === 'number' ? sizeHeaderValue : undefined;
2382
+ return {
2383
+ Bucket: destConfig.Bucket,
2384
+ Key: destConfig.Object,
2385
+ LastModified: copyRes.lastModified,
2386
+ MetaData: extractMetadata(resHeaders),
2387
+ VersionId: getVersionId(resHeaders),
2388
+ SourceVersionId: getSourceVersionId(resHeaders),
2389
+ Etag: sanitizeETag(resHeaders.etag),
2390
+ Size: size
2391
+ };
2392
+ }
2393
+ async copyObject(...allArgs) {
2394
+ if (typeof allArgs[0] === 'string') {
2395
+ const [targetBucketName, targetObjectName, sourceBucketNameAndObjectName, conditions] = allArgs;
2396
+ return await this.copyObjectV1(targetBucketName, targetObjectName, sourceBucketNameAndObjectName, conditions);
2397
+ }
2398
+ const [source, dest] = allArgs;
2399
+ return await this.copyObjectV2(source, dest);
2400
+ }
2401
+ async uploadPart(partConfig, payload) {
2402
+ const {
2403
+ bucketName,
2404
+ objectName,
2405
+ uploadID,
2406
+ partNumber,
2407
+ headers
2408
+ } = partConfig;
2409
+ const method = 'PUT';
2410
+ const query = `uploadId=${uploadID}&partNumber=${partNumber}`;
2411
+ const requestOptions = {
2412
+ method,
2413
+ bucketName,
2414
+ objectName: objectName,
2415
+ query,
2416
+ headers
2417
+ };
2418
+ const res = await this.makeRequestAsync(requestOptions, payload);
2419
+ const body = await readAsString(res);
2420
+ const partRes = uploadPartParser(body);
2421
+ const partEtagVal = sanitizeETag(res.headers.etag) || sanitizeETag(partRes.ETag);
2422
+ return {
2423
+ etag: partEtagVal,
2424
+ key: objectName,
2425
+ part: partNumber
2426
+ };
2427
+ }
2428
+ async composeObject(destObjConfig, sourceObjList, {
2429
+ maxConcurrency = 10
2430
+ } = {}) {
2431
+ const sourceFilesLength = sourceObjList.length;
2432
+ if (!Array.isArray(sourceObjList)) {
2433
+ throw new errors.InvalidArgumentError('sourceConfig should an array of CopySourceOptions ');
2434
+ }
2435
+ if (!(destObjConfig instanceof CopyDestinationOptions)) {
2436
+ throw new errors.InvalidArgumentError('destConfig should of type CopyDestinationOptions ');
2437
+ }
2438
+ if (sourceFilesLength < 1 || sourceFilesLength > PART_CONSTRAINTS.MAX_PARTS_COUNT) {
2439
+ throw new errors.InvalidArgumentError(`"There must be as least one and up to ${PART_CONSTRAINTS.MAX_PARTS_COUNT} source objects.`);
2440
+ }
2441
+ for (let i = 0; i < sourceFilesLength; i++) {
2442
+ const sObj = sourceObjList[i];
2443
+ if (!sObj.validate()) {
2444
+ return false;
2445
+ }
2446
+ }
2447
+ if (!destObjConfig.validate()) {
2448
+ return false;
2449
+ }
2450
+ const getStatOptions = srcConfig => {
2451
+ let statOpts = {};
2452
+ if (!_.isEmpty(srcConfig.VersionID)) {
2453
+ statOpts = {
2454
+ versionId: srcConfig.VersionID
2455
+ };
2456
+ }
2457
+ return statOpts;
2458
+ };
2459
+ const srcObjectSizes = [];
2460
+ let totalSize = 0;
2461
+ let totalParts = 0;
2462
+ const sourceObjStats = sourceObjList.map(srcItem => this.statObject(srcItem.Bucket, srcItem.Object, getStatOptions(srcItem)));
2463
+ const srcObjectInfos = await Promise.all(sourceObjStats);
2464
+ const validatedStats = srcObjectInfos.map((resItemStat, index) => {
2465
+ const srcConfig = sourceObjList[index];
2466
+ let srcCopySize = resItemStat.size;
2467
+ // Check if a segment is specified, and if so, is the
2468
+ // segment within object bounds?
2469
+ if (srcConfig && srcConfig.MatchRange) {
2470
+ // Since range is specified,
2471
+ // 0 <= src.srcStart <= src.srcEnd
2472
+ // so only invalid case to check is:
2473
+ const srcStart = srcConfig.Start;
2474
+ const srcEnd = srcConfig.End;
2475
+ if (srcEnd >= srcCopySize || srcStart < 0) {
2476
+ throw new errors.InvalidArgumentError(`CopySrcOptions ${index} has invalid segment-to-copy [${srcStart}, ${srcEnd}] (size is ${srcCopySize})`);
2477
+ }
2478
+ srcCopySize = srcEnd - srcStart + 1;
2479
+ }
2480
+
2481
+ // Only the last source may be less than `absMinPartSize`
2482
+ if (srcCopySize < PART_CONSTRAINTS.ABS_MIN_PART_SIZE && index < sourceFilesLength - 1) {
2483
+ throw new errors.InvalidArgumentError(`CopySrcOptions ${index} is too small (${srcCopySize}) and it is not the last part.`);
2484
+ }
2485
+
2486
+ // Is data to copy too large?
2487
+ totalSize += srcCopySize;
2488
+ if (totalSize > PART_CONSTRAINTS.MAX_MULTIPART_PUT_OBJECT_SIZE) {
2489
+ throw new errors.InvalidArgumentError(`Cannot compose an object of size ${totalSize} (> 5TiB)`);
2490
+ }
2491
+
2492
+ // record source size
2493
+ srcObjectSizes[index] = srcCopySize;
2494
+
2495
+ // calculate parts needed for current source
2496
+ totalParts += partsRequired(srcCopySize);
2497
+ // Do we need more parts than we are allowed?
2498
+ if (totalParts > PART_CONSTRAINTS.MAX_PARTS_COUNT) {
2499
+ throw new errors.InvalidArgumentError(`Your proposed compose object requires more than ${PART_CONSTRAINTS.MAX_PARTS_COUNT} parts`);
2500
+ }
2501
+ return resItemStat;
2502
+ });
2503
+ if (totalParts === 1 && totalSize <= PART_CONSTRAINTS.MAX_PART_SIZE || totalSize === 0) {
2504
+ return await this.copyObject(sourceObjList[0], destObjConfig); // use copyObjectV2
2505
+ }
2506
+
2507
+ // preserve etag to avoid modification of object while copying.
2508
+ for (let i = 0; i < sourceFilesLength; i++) {
2509
+ ;
2510
+ sourceObjList[i].MatchETag = validatedStats[i].etag;
2511
+ }
2512
+ const splitPartSizeList = validatedStats.map((resItemStat, idx) => {
2513
+ return calculateEvenSplits(srcObjectSizes[idx], sourceObjList[idx]);
2514
+ });
2515
+ const getUploadPartConfigList = uploadId => {
2516
+ const uploadPartConfigList = [];
2517
+ splitPartSizeList.forEach((splitSize, splitIndex) => {
2518
+ if (splitSize) {
2519
+ const {
2520
+ startIndex: startIdx,
2521
+ endIndex: endIdx,
2522
+ objInfo: objConfig
2523
+ } = splitSize;
2524
+ const partIndex = splitIndex + 1; // part index starts from 1.
2525
+ const totalUploads = Array.from(startIdx);
2526
+ const headers = sourceObjList[splitIndex].getHeaders();
2527
+ totalUploads.forEach((splitStart, upldCtrIdx) => {
2528
+ const splitEnd = endIdx[upldCtrIdx];
2529
+ const sourceObj = `${objConfig.Bucket}/${objConfig.Object}`;
2530
+ headers['x-amz-copy-source'] = `${sourceObj}`;
2531
+ headers['x-amz-copy-source-range'] = `bytes=${splitStart}-${splitEnd}`;
2532
+ const uploadPartConfig = {
2533
+ bucketName: destObjConfig.Bucket,
2534
+ objectName: destObjConfig.Object,
2535
+ uploadID: uploadId,
2536
+ partNumber: partIndex,
2537
+ headers: headers,
2538
+ sourceObj: sourceObj
2539
+ };
2540
+ uploadPartConfigList.push(uploadPartConfig);
2541
+ });
2542
+ }
2543
+ });
2544
+ return uploadPartConfigList;
2545
+ };
2546
+ const uploadAllParts = async uploadList => {
2547
+ const partUploads = [];
2548
+
2549
+ // Process upload parts in batches to avoid too many concurrent requests
2550
+ for (const batch of _.chunk(uploadList, maxConcurrency)) {
2551
+ const batchResults = await Promise.all(batch.map(item => this.uploadPart(item)));
2552
+ partUploads.push(...batchResults);
2553
+ }
2554
+
2555
+ // Process results here if needed
2556
+ return partUploads;
2557
+ };
2558
+ const performUploadParts = async uploadId => {
2559
+ const uploadList = getUploadPartConfigList(uploadId);
2560
+ const partsRes = await uploadAllParts(uploadList);
2561
+ return partsRes.map(partCopy => ({
2562
+ etag: partCopy.etag,
2563
+ part: partCopy.part
2564
+ }));
2565
+ };
2566
+ const newUploadHeaders = destObjConfig.getHeaders();
2567
+ const uploadId = await this.initiateNewMultipartUpload(destObjConfig.Bucket, destObjConfig.Object, newUploadHeaders);
2568
+ try {
2569
+ const partsDone = await performUploadParts(uploadId);
2570
+ return await this.completeMultipartUpload(destObjConfig.Bucket, destObjConfig.Object, uploadId, partsDone);
2571
+ } catch (err) {
2572
+ return await this.abortMultipartUpload(destObjConfig.Bucket, destObjConfig.Object, uploadId);
2573
+ }
2574
+ }
2575
+ async presignedUrl(method, bucketName, objectName, expires, reqParams, requestDate) {
2576
+ var _requestDate;
2577
+ if (this.anonymous) {
2578
+ throw new errors.AnonymousRequestError(`Presigned ${method} url cannot be generated for anonymous requests`);
2579
+ }
2580
+ if (!expires) {
2581
+ expires = PRESIGN_EXPIRY_DAYS_MAX;
2582
+ }
2583
+ if (!reqParams) {
2584
+ reqParams = {};
2585
+ }
2586
+ if (!requestDate) {
2587
+ requestDate = new Date();
2588
+ }
2589
+
2590
+ // Type assertions
2591
+ if (expires && typeof expires !== 'number') {
2592
+ throw new TypeError('expires should be of type "number"');
2593
+ }
2594
+ if (reqParams && typeof reqParams !== 'object') {
2595
+ throw new TypeError('reqParams should be of type "object"');
2596
+ }
2597
+ if (requestDate && !(requestDate instanceof Date) || requestDate && isNaN((_requestDate = requestDate) === null || _requestDate === void 0 ? void 0 : _requestDate.getTime())) {
2598
+ throw new TypeError('requestDate should be of type "Date" and valid');
2599
+ }
2600
+ const query = reqParams ? qs.stringify(reqParams) : undefined;
2601
+ try {
2602
+ const region = await this.getBucketRegionAsync(bucketName);
2603
+ await this.checkAndRefreshCreds();
2604
+ const reqOptions = this.getRequestOptions({
2605
+ method,
2606
+ region,
2607
+ bucketName,
2608
+ objectName,
2609
+ query
2610
+ });
2611
+ return presignSignatureV4(reqOptions, this.accessKey, this.secretKey, this.sessionToken, region, requestDate, expires);
2612
+ } catch (err) {
2613
+ if (err instanceof errors.InvalidBucketNameError) {
2614
+ throw new errors.InvalidArgumentError(`Unable to get bucket region for ${bucketName}.`);
2615
+ }
2616
+ throw err;
2617
+ }
2618
+ }
2619
+ async presignedGetObject(bucketName, objectName, expires, respHeaders, requestDate) {
2620
+ if (!isValidBucketName(bucketName)) {
2621
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
2622
+ }
2623
+ if (!isValidObjectName(objectName)) {
2624
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
2625
+ }
2626
+ const validRespHeaders = ['response-content-type', 'response-content-language', 'response-expires', 'response-cache-control', 'response-content-disposition', 'response-content-encoding'];
2627
+ validRespHeaders.forEach(header => {
2628
+ // @ts-ignore
2629
+ if (respHeaders !== undefined && respHeaders[header] !== undefined && !isString(respHeaders[header])) {
2630
+ throw new TypeError(`response header ${header} should be of type "string"`);
2631
+ }
2632
+ });
2633
+ return this.presignedUrl('GET', bucketName, objectName, expires, respHeaders, requestDate);
2634
+ }
2635
+ async presignedPutObject(bucketName, objectName, expires) {
2636
+ if (!isValidBucketName(bucketName)) {
2637
+ throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
2638
+ }
2639
+ if (!isValidObjectName(objectName)) {
2640
+ throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
2641
+ }
2642
+ return this.presignedUrl('PUT', bucketName, objectName, expires);
2643
+ }
2644
+ newPostPolicy() {
2645
+ return new PostPolicy();
2646
+ }
2647
+ async presignedPostPolicy(postPolicy) {
2648
+ if (this.anonymous) {
2649
+ throw new errors.AnonymousRequestError('Presigned POST policy cannot be generated for anonymous requests');
2650
+ }
2651
+ if (!isObject(postPolicy)) {
2652
+ throw new TypeError('postPolicy should be of type "object"');
2653
+ }
2654
+ const bucketName = postPolicy.formData.bucket;
2655
+ try {
2656
+ const region = await this.getBucketRegionAsync(bucketName);
2657
+ const date = new Date();
2658
+ const dateStr = makeDateLong(date);
2659
+ await this.checkAndRefreshCreds();
2660
+ if (!postPolicy.policy.expiration) {
2661
+ // 'expiration' is mandatory field for S3.
2662
+ // Set default expiration date of 7 days.
2663
+ const expires = new Date();
2664
+ expires.setSeconds(PRESIGN_EXPIRY_DAYS_MAX);
2665
+ postPolicy.setExpires(expires);
2666
+ }
2667
+ postPolicy.policy.conditions.push(['eq', '$x-amz-date', dateStr]);
2668
+ postPolicy.formData['x-amz-date'] = dateStr;
2669
+ postPolicy.policy.conditions.push(['eq', '$x-amz-algorithm', 'AWS4-HMAC-SHA256']);
2670
+ postPolicy.formData['x-amz-algorithm'] = 'AWS4-HMAC-SHA256';
2671
+ postPolicy.policy.conditions.push(['eq', '$x-amz-credential', this.accessKey + '/' + getScope(region, date)]);
2672
+ postPolicy.formData['x-amz-credential'] = this.accessKey + '/' + getScope(region, date);
2673
+ if (this.sessionToken) {
2674
+ postPolicy.policy.conditions.push(['eq', '$x-amz-security-token', this.sessionToken]);
2675
+ postPolicy.formData['x-amz-security-token'] = this.sessionToken;
2676
+ }
2677
+ const policyBase64 = Buffer.from(JSON.stringify(postPolicy.policy)).toString('base64');
2678
+ postPolicy.formData.policy = policyBase64;
2679
+ postPolicy.formData['x-amz-signature'] = postPresignSignatureV4(region, date, this.secretKey, policyBase64);
2680
+ const opts = {
2681
+ region: region,
2682
+ bucketName: bucketName,
2683
+ method: 'POST'
2684
+ };
2685
+ const reqOptions = this.getRequestOptions(opts);
2686
+ const portStr = this.port == 80 || this.port === 443 ? '' : `:${this.port.toString()}`;
2687
+ const urlStr = `${reqOptions.protocol}//${reqOptions.host}${portStr}${reqOptions.path}`;
2688
+ return {
2689
+ postURL: urlStr,
2690
+ formData: postPolicy.formData
2691
+ };
2692
+ } catch (err) {
2693
+ if (err instanceof errors.InvalidBucketNameError) {
2694
+ throw new errors.InvalidArgumentError(`Unable to get bucket region for ${bucketName}.`);
2695
+ }
2696
+ throw err;
2697
+ }
2698
+ }
2699
+ // list a batch of objects
2700
+ async listObjectsQuery(bucketName, prefix, marker, listQueryOpts) {
2701
+ if (!isValidBucketName(bucketName)) {
2702
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
2703
+ }
2704
+ if (!isString(prefix)) {
2705
+ throw new TypeError('prefix should be of type "string"');
2706
+ }
2707
+ if (marker && !isString(marker)) {
2708
+ throw new TypeError('marker should be of type "string"');
2709
+ }
2710
+ if (listQueryOpts && !isObject(listQueryOpts)) {
2711
+ throw new TypeError('listQueryOpts should be of type "object"');
2712
+ }
2713
+ let {
2714
+ Delimiter,
2715
+ MaxKeys,
2716
+ IncludeVersion,
2717
+ versionIdMarker,
2718
+ keyMarker
2719
+ } = listQueryOpts;
2720
+ if (!isString(Delimiter)) {
2721
+ throw new TypeError('Delimiter should be of type "string"');
2722
+ }
2723
+ if (!isNumber(MaxKeys)) {
2724
+ throw new TypeError('MaxKeys should be of type "number"');
2725
+ }
2726
+ const queries = [];
2727
+ // escape every value in query string, except maxKeys
2728
+ queries.push(`prefix=${uriEscape(prefix)}`);
2729
+ queries.push(`delimiter=${uriEscape(Delimiter)}`);
2730
+ queries.push(`encoding-type=url`);
2731
+ if (IncludeVersion) {
2732
+ queries.push(`versions`);
2733
+ }
2734
+ if (IncludeVersion) {
2735
+ // v1 version listing..
2736
+ if (keyMarker) {
2737
+ queries.push(`key-marker=${keyMarker}`);
2738
+ }
2739
+ if (versionIdMarker) {
2740
+ queries.push(`version-id-marker=${versionIdMarker}`);
2741
+ }
2742
+ } else if (marker) {
2743
+ marker = uriEscape(marker);
2744
+ queries.push(`marker=${marker}`);
2745
+ }
2746
+
2747
+ // no need to escape maxKeys
2748
+ if (MaxKeys) {
2749
+ if (MaxKeys >= 1000) {
2750
+ MaxKeys = 1000;
2751
+ }
2752
+ queries.push(`max-keys=${MaxKeys}`);
2753
+ }
2754
+ queries.sort();
2755
+ let query = '';
2756
+ if (queries.length > 0) {
2757
+ query = `${queries.join('&')}`;
2758
+ }
2759
+ const method = 'GET';
2760
+ const res = await this.makeRequestAsync({
2761
+ method,
2762
+ bucketName,
2763
+ query
2764
+ });
2765
+ const body = await readAsString(res);
2766
+ const listQryList = parseListObjects(body);
2767
+ return listQryList;
2768
+ }
2769
+ listObjects(bucketName, prefix, recursive, listOpts) {
2770
+ if (prefix === undefined) {
2771
+ prefix = '';
2772
+ }
2773
+ if (recursive === undefined) {
2774
+ recursive = false;
2775
+ }
2776
+ if (!isValidBucketName(bucketName)) {
2777
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
2778
+ }
2779
+ if (!isValidPrefix(prefix)) {
2780
+ throw new errors.InvalidPrefixError(`Invalid prefix : ${prefix}`);
2781
+ }
2782
+ if (!isString(prefix)) {
2783
+ throw new TypeError('prefix should be of type "string"');
2784
+ }
2785
+ if (!isBoolean(recursive)) {
2786
+ throw new TypeError('recursive should be of type "boolean"');
2787
+ }
2788
+ if (listOpts && !isObject(listOpts)) {
2789
+ throw new TypeError('listOpts should be of type "object"');
2790
+ }
2791
+ let marker = '';
2792
+ let keyMarker = '';
2793
+ let versionIdMarker = '';
2794
+ let objects = [];
2795
+ let ended = false;
2796
+ const readStream = new stream.Readable({
2797
+ objectMode: true
2798
+ });
2799
+ readStream._read = async () => {
2800
+ // push one object per _read()
2801
+ if (objects.length) {
2802
+ readStream.push(objects.shift());
2803
+ return;
2804
+ }
2805
+ if (ended) {
2806
+ return readStream.push(null);
2807
+ }
2808
+ try {
2809
+ const listQueryOpts = {
2810
+ Delimiter: recursive ? '' : '/',
2811
+ // if recursive is false set delimiter to '/'
2812
+ MaxKeys: 1000,
2813
+ IncludeVersion: listOpts === null || listOpts === void 0 ? void 0 : listOpts.IncludeVersion,
2814
+ // version listing specific options
2815
+ keyMarker: keyMarker,
2816
+ versionIdMarker: versionIdMarker
2817
+ };
2818
+ const result = await this.listObjectsQuery(bucketName, prefix, marker, listQueryOpts);
2819
+ if (result.isTruncated) {
2820
+ marker = result.nextMarker || undefined;
2821
+ if (result.keyMarker) {
2822
+ keyMarker = result.keyMarker;
2823
+ }
2824
+ if (result.versionIdMarker) {
2825
+ versionIdMarker = result.versionIdMarker;
2826
+ }
2827
+ } else {
2828
+ ended = true;
2829
+ }
2830
+ if (result.objects) {
2831
+ objects = result.objects;
2832
+ }
2833
+ // @ts-ignore
2834
+ readStream._read();
2835
+ } catch (err) {
2836
+ readStream.emit('error', err);
2837
+ }
2838
+ };
2839
+ return readStream;
2840
+ }
2841
+ async listObjectsV2Query(bucketName, prefix, continuationToken, delimiter, maxKeys, startAfter) {
2842
+ if (!isValidBucketName(bucketName)) {
2843
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
2844
+ }
2845
+ if (!isString(prefix)) {
2846
+ throw new TypeError('prefix should be of type "string"');
2847
+ }
2848
+ if (!isString(continuationToken)) {
2849
+ throw new TypeError('continuationToken should be of type "string"');
2850
+ }
2851
+ if (!isString(delimiter)) {
2852
+ throw new TypeError('delimiter should be of type "string"');
2853
+ }
2854
+ if (!isNumber(maxKeys)) {
2855
+ throw new TypeError('maxKeys should be of type "number"');
2856
+ }
2857
+ if (!isString(startAfter)) {
2858
+ throw new TypeError('startAfter should be of type "string"');
2859
+ }
2860
+ const queries = [];
2861
+ queries.push(`list-type=2`);
2862
+ queries.push(`encoding-type=url`);
2863
+ queries.push(`prefix=${uriEscape(prefix)}`);
2864
+ queries.push(`delimiter=${uriEscape(delimiter)}`);
2865
+ if (continuationToken) {
2866
+ queries.push(`continuation-token=${uriEscape(continuationToken)}`);
2867
+ }
2868
+ if (startAfter) {
2869
+ queries.push(`start-after=${uriEscape(startAfter)}`);
2870
+ }
2871
+ if (maxKeys) {
2872
+ if (maxKeys >= 1000) {
2873
+ maxKeys = 1000;
2874
+ }
2875
+ queries.push(`max-keys=${maxKeys}`);
2876
+ }
2877
+ queries.sort();
2878
+ let query = '';
2879
+ if (queries.length > 0) {
2880
+ query = `${queries.join('&')}`;
2881
+ }
2882
+ const method = 'GET';
2883
+ const res = await this.makeRequestAsync({
2884
+ method,
2885
+ bucketName,
2886
+ query
2887
+ });
2888
+ const body = await readAsString(res);
2889
+ return parseListObjectsV2(body);
2890
+ }
2891
+ listObjectsV2(bucketName, prefix, recursive, startAfter) {
2892
+ if (prefix === undefined) {
2893
+ prefix = '';
2894
+ }
2895
+ if (recursive === undefined) {
2896
+ recursive = false;
2897
+ }
2898
+ if (startAfter === undefined) {
2899
+ startAfter = '';
2900
+ }
2901
+ if (!isValidBucketName(bucketName)) {
2902
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
2903
+ }
2904
+ if (!isValidPrefix(prefix)) {
2905
+ throw new errors.InvalidPrefixError(`Invalid prefix : ${prefix}`);
2906
+ }
2907
+ if (!isString(prefix)) {
2908
+ throw new TypeError('prefix should be of type "string"');
2909
+ }
2910
+ if (!isBoolean(recursive)) {
2911
+ throw new TypeError('recursive should be of type "boolean"');
2912
+ }
2913
+ if (!isString(startAfter)) {
2914
+ throw new TypeError('startAfter should be of type "string"');
2915
+ }
2916
+ const delimiter = recursive ? '' : '/';
2917
+ const prefixStr = prefix;
2918
+ const startAfterStr = startAfter;
2919
+ let continuationToken = '';
2920
+ let objects = [];
2921
+ let ended = false;
2922
+ const readStream = new stream.Readable({
2923
+ objectMode: true
2924
+ });
2925
+ readStream._read = async () => {
2926
+ if (objects.length) {
2927
+ readStream.push(objects.shift());
2928
+ return;
2929
+ }
2930
+ if (ended) {
2931
+ return readStream.push(null);
2932
+ }
2933
+ try {
2934
+ const result = await this.listObjectsV2Query(bucketName, prefixStr, continuationToken, delimiter, 1000, startAfterStr);
2935
+ if (result.isTruncated) {
2936
+ continuationToken = result.nextContinuationToken;
2937
+ } else {
2938
+ ended = true;
2939
+ }
2940
+ objects = result.objects;
2941
+ // @ts-ignore
2942
+ readStream._read();
2943
+ } catch (err) {
2944
+ readStream.emit('error', err);
2945
+ }
2946
+ };
2947
+ return readStream;
2948
+ }
2949
+ async setBucketNotification(bucketName, config) {
2950
+ if (!isValidBucketName(bucketName)) {
2951
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
2952
+ }
2953
+ if (!isObject(config)) {
2954
+ throw new TypeError('notification config should be of type "Object"');
2955
+ }
2956
+ const method = 'PUT';
2957
+ const query = 'notification';
2958
+ const builder = new xml2js.Builder({
2959
+ rootName: 'NotificationConfiguration',
2960
+ renderOpts: {
2961
+ pretty: false
2962
+ },
2963
+ headless: true
2964
+ });
2965
+ const payload = builder.buildObject(config);
2966
+ await this.makeRequestAsyncOmit({
2967
+ method,
2968
+ bucketName,
2969
+ query
2970
+ }, payload);
2971
+ }
2972
+ async removeAllBucketNotification(bucketName) {
2973
+ await this.setBucketNotification(bucketName, new NotificationConfig());
2974
+ }
2975
+ async getBucketNotification(bucketName) {
2976
+ if (!isValidBucketName(bucketName)) {
2977
+ throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
2978
+ }
2979
+ const method = 'GET';
2980
+ const query = 'notification';
2981
+ const res = await this.makeRequestAsync({
2982
+ method,
2983
+ bucketName,
2984
+ query
2985
+ });
2986
+ const body = await readAsString(res);
2987
+ return parseBucketNotification(body);
2988
+ }
2989
+ listenBucketNotification(bucketName, prefix, suffix, events) {
2990
+ if (!isValidBucketName(bucketName)) {
2991
+ throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
2992
+ }
2993
+ if (!isString(prefix)) {
2994
+ throw new TypeError('prefix must be of type string');
2995
+ }
2996
+ if (!isString(suffix)) {
2997
+ throw new TypeError('suffix must be of type string');
2998
+ }
2999
+ if (!Array.isArray(events)) {
3000
+ throw new TypeError('events must be of type Array');
3001
+ }
3002
+ const listener = new NotificationPoller(this, bucketName, prefix, suffix, events);
3003
+ listener.start();
3004
+ return listener;
3005
+ }
3006
+ }
3007
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJjcnlwdG8iLCJmcyIsImh0dHAiLCJodHRwcyIsInBhdGgiLCJzdHJlYW0iLCJhc3luYyIsIkJsb2NrU3RyZWFtMiIsImlzQnJvd3NlciIsIl8iLCJxcyIsInhtbDJqcyIsIkNyZWRlbnRpYWxQcm92aWRlciIsImVycm9ycyIsIkNvcHlEZXN0aW5hdGlvbk9wdGlvbnMiLCJDb3B5U291cmNlT3B0aW9ucyIsIkRFRkFVTFRfUkVHSU9OIiwiTEVHQUxfSE9MRF9TVEFUVVMiLCJQUkVTSUdOX0VYUElSWV9EQVlTX01BWCIsIlJFVEVOVElPTl9NT0RFUyIsIlJFVEVOVElPTl9WQUxJRElUWV9VTklUUyIsIk5vdGlmaWNhdGlvbkNvbmZpZyIsIk5vdGlmaWNhdGlvblBvbGxlciIsInBvc3RQcmVzaWduU2lnbmF0dXJlVjQiLCJwcmVzaWduU2lnbmF0dXJlVjQiLCJzaWduVjQiLCJmc3AiLCJzdHJlYW1Qcm9taXNlIiwiQ29weUNvbmRpdGlvbnMiLCJFeHRlbnNpb25zIiwiY2FsY3VsYXRlRXZlblNwbGl0cyIsImV4dHJhY3RNZXRhZGF0YSIsImdldENvbnRlbnRMZW5ndGgiLCJnZXRTY29wZSIsImdldFNvdXJjZVZlcnNpb25JZCIsImdldFZlcnNpb25JZCIsImhhc2hCaW5hcnkiLCJpbnNlcnRDb250ZW50VHlwZSIsImlzQW1hem9uRW5kcG9pbnQiLCJpc0Jvb2xlYW4iLCJpc0RlZmluZWQiLCJpc0VtcHR5IiwiaXNOdW1iZXIiLCJpc09iamVjdCIsImlzUGxhaW5PYmplY3QiLCJpc1JlYWRhYmxlU3RyZWFtIiwiaXNTdHJpbmciLCJpc1ZhbGlkQnVja2V0TmFtZSIsImlzVmFsaWRFbmRwb2ludCIsImlzVmFsaWRPYmplY3ROYW1lIiwiaXNWYWxpZFBvcnQiLCJpc1ZhbGlkUHJlZml4IiwiaXNWaXJ0dWFsSG9zdFN0eWxlIiwibWFrZURhdGVMb25nIiwiUEFSVF9DT05TVFJBSU5UUyIsInBhcnRzUmVxdWlyZWQiLCJwcmVwZW5kWEFNWk1ldGEiLCJyZWFkYWJsZVN0cmVhbSIsInNhbml0aXplRVRhZyIsInRvTWQ1IiwidG9TaGEyNTYiLCJ1cmlFc2NhcGUiLCJ1cmlSZXNvdXJjZUVzY2FwZSIsImpvaW5Ib3N0UG9ydCIsIlBvc3RQb2xpY3kiLCJyZXF1ZXN0V2l0aFJldHJ5IiwiZHJhaW5SZXNwb25zZSIsInJlYWRBc0J1ZmZlciIsInJlYWRBc1N0cmluZyIsImdldFMzRW5kcG9pbnQiLCJwYXJzZUJ1Y2tldE5vdGlmaWNhdGlvbiIsInBhcnNlQ29tcGxldGVNdWx0aXBhcnQiLCJwYXJzZUluaXRpYXRlTXVsdGlwYXJ0IiwicGFyc2VMaXN0T2JqZWN0cyIsInBhcnNlTGlzdE9iamVjdHNWMiIsInBhcnNlT2JqZWN0TGVnYWxIb2xkQ29uZmlnIiwicGFyc2VTZWxlY3RPYmplY3RDb250ZW50UmVzcG9uc2UiLCJ1cGxvYWRQYXJ0UGFyc2VyIiwieG1sUGFyc2VycyIsInhtbCIsIkJ1aWxkZXIiLCJyZW5kZXJPcHRzIiwicHJldHR5IiwiaGVhZGxlc3MiLCJQYWNrYWdlIiwidmVyc2lvbiIsInJlcXVlc3RPcHRpb25Qcm9wZXJ0aWVzIiwiVHlwZWRDbGllbnQiLCJwYXJ0U2l6ZSIsIm1heGltdW1QYXJ0U2l6ZSIsIm1heE9iamVjdFNpemUiLCJjb25zdHJ1Y3RvciIsInBhcmFtcyIsInNlY3VyZSIsInVuZGVmaW5lZCIsIkVycm9yIiwidXNlU1NMIiwicG9ydCIsImVuZFBvaW50IiwiSW52YWxpZEVuZHBvaW50RXJyb3IiLCJJbnZhbGlkQXJndW1lbnRFcnJvciIsInJlZ2lvbiIsImhvc3QiLCJ0b0xvd2VyQ2FzZSIsInByb3RvY29sIiwidHJhbnNwb3J0IiwidHJhbnNwb3J0QWdlbnQiLCJnbG9iYWxBZ2VudCIsImxpYnJhcnlDb21tZW50cyIsInByb2Nlc3MiLCJwbGF0Zm9ybSIsImFyY2giLCJsaWJyYXJ5QWdlbnQiLCJ1c2VyQWdlbnQiLCJwYXRoU3R5bGUiLCJhY2Nlc3NLZXkiLCJzZWNyZXRLZXkiLCJzZXNzaW9uVG9rZW4iLCJhbm9ueW1vdXMiLCJjcmVkZW50aWFsc1Byb3ZpZGVyIiwicmVnaW9uTWFwIiwib3ZlclJpZGVQYXJ0U2l6ZSIsImVuYWJsZVNIQTI1NiIsInMzQWNjZWxlcmF0ZUVuZHBvaW50IiwicmVxT3B0aW9ucyIsImNsaWVudEV4dGVuc2lvbnMiLCJyZXRyeU9wdGlvbnMiLCJkaXNhYmxlUmV0cnkiLCJleHRlbnNpb25zIiwic2V0UzNUcmFuc2ZlckFjY2VsZXJhdGUiLCJzZXRSZXF1ZXN0T3B0aW9ucyIsIm9wdGlvbnMiLCJUeXBlRXJyb3IiLCJwaWNrIiwiZ2V0QWNjZWxlcmF0ZUVuZFBvaW50SWZTZXQiLCJidWNrZXROYW1lIiwib2JqZWN0TmFtZSIsImluY2x1ZGVzIiwic2V0QXBwSW5mbyIsImFwcE5hbWUiLCJhcHBWZXJzaW9uIiwidHJpbSIsImdldFJlcXVlc3RPcHRpb25zIiwib3B0cyIsIm1ldGhvZCIsImhlYWRlcnMiLCJxdWVyeSIsImFnZW50IiwidmlydHVhbEhvc3RTdHlsZSIsImFjY2VsZXJhdGVFbmRQb2ludCIsImsiLCJ2IiwiT2JqZWN0IiwiZW50cmllcyIsImFzc2lnbiIsIm1hcFZhbHVlcyIsInBpY2tCeSIsInRvU3RyaW5nIiwic2V0Q3JlZGVudGlhbHNQcm92aWRlciIsImNoZWNrQW5kUmVmcmVzaENyZWRzIiwiY3JlZGVudGlhbHNDb25mIiwiZ2V0Q3JlZGVudGlhbHMiLCJnZXRBY2Nlc3NLZXkiLCJnZXRTZWNyZXRLZXkiLCJnZXRTZXNzaW9uVG9rZW4iLCJlIiwiY2F1c2UiLCJsb2dIVFRQIiwicmVzcG9uc2UiLCJlcnIiLCJsb2dTdHJlYW0iLCJsb2dIZWFkZXJzIiwiZm9yRWFjaCIsInJlZGFjdG9yIiwiUmVnRXhwIiwicmVwbGFjZSIsIndyaXRlIiwic3RhdHVzQ29kZSIsImVyckpTT04iLCJKU09OIiwic3RyaW5naWZ5IiwidHJhY2VPbiIsInN0ZG91dCIsInRyYWNlT2ZmIiwibWFrZVJlcXVlc3RBc3luYyIsInBheWxvYWQiLCJleHBlY3RlZENvZGVzIiwibGVuZ3RoIiwic2hhMjU2c3VtIiwibWFrZVJlcXVlc3RTdHJlYW1Bc3luYyIsIm1ha2VSZXF1ZXN0QXN5bmNPbWl0Iiwic3RhdHVzQ29kZXMiLCJyZXMiLCJib2R5IiwiQnVmZmVyIiwiaXNCdWZmZXIiLCJnZXRCdWNrZXRSZWdpb25Bc3luYyIsImRhdGUiLCJEYXRlIiwiYXV0aG9yaXphdGlvbiIsIm1heGltdW1SZXRyeUNvdW50IiwiYmFzZURlbGF5TXMiLCJtYXhpbXVtRGVsYXlNcyIsInBhcnNlUmVzcG9uc2VFcnJvciIsIkludmFsaWRCdWNrZXROYW1lRXJyb3IiLCJjYWNoZWQiLCJleHRyYWN0UmVnaW9uQXN5bmMiLCJwYXJzZUJ1Y2tldFJlZ2lvbiIsIlMzRXJyb3IiLCJlcnJDb2RlIiwiY29kZSIsImVyclJlZ2lvbiIsIm5hbWUiLCJSZWdpb24iLCJtYWtlUmVxdWVzdCIsInJldHVyblJlc3BvbnNlIiwiY2IiLCJwcm9tIiwidGhlbiIsInJlc3VsdCIsIm1ha2VSZXF1ZXN0U3RyZWFtIiwiZXhlY3V0b3IiLCJnZXRCdWNrZXRSZWdpb24iLCJtYWtlQnVja2V0IiwibWFrZU9wdHMiLCJidWlsZE9iamVjdCIsIkNyZWF0ZUJ1Y2tldENvbmZpZ3VyYXRpb24iLCIkIiwieG1sbnMiLCJMb2NhdGlvbkNvbnN0cmFpbnQiLCJPYmplY3RMb2NraW5nIiwiZmluYWxSZWdpb24iLCJyZXF1ZXN0T3B0IiwiYnVja2V0RXhpc3RzIiwicmVtb3ZlQnVja2V0IiwiZ2V0T2JqZWN0IiwiZ2V0T3B0cyIsIkludmFsaWRPYmplY3ROYW1lRXJyb3IiLCJnZXRQYXJ0aWFsT2JqZWN0Iiwib2Zmc2V0IiwicmFuZ2UiLCJzc2VIZWFkZXJzIiwiU1NFQ3VzdG9tZXJBbGdvcml0aG0iLCJTU0VDdXN0b21lcktleSIsIlNTRUN1c3RvbWVyS2V5TUQ1IiwiZXhwZWN0ZWRTdGF0dXNDb2RlcyIsInB1c2giLCJmR2V0T2JqZWN0IiwiZmlsZVBhdGgiLCJkb3dubG9hZFRvVG1wRmlsZSIsInBhcnRGaWxlU3RyZWFtIiwib2JqU3RhdCIsInN0YXRPYmplY3QiLCJlbmNvZGVkRXRhZyIsImZyb20iLCJldGFnIiwicGFydEZpbGUiLCJta2RpciIsImRpcm5hbWUiLCJyZWN1cnNpdmUiLCJzdGF0cyIsInN0YXQiLCJzaXplIiwiY3JlYXRlV3JpdGVTdHJlYW0iLCJmbGFncyIsImRvd25sb2FkU3RyZWFtIiwicGlwZWxpbmUiLCJyZW5hbWUiLCJzdGF0T3B0cyIsInN0YXRPcHREZWYiLCJwYXJzZUludCIsIm1ldGFEYXRhIiwibGFzdE1vZGlmaWVkIiwidmVyc2lvbklkIiwicmVtb3ZlT2JqZWN0IiwicmVtb3ZlT3B0cyIsImdvdmVybmFuY2VCeXBhc3MiLCJmb3JjZURlbGV0ZSIsInF1ZXJ5UGFyYW1zIiwibGlzdEluY29tcGxldGVVcGxvYWRzIiwiYnVja2V0IiwicHJlZml4IiwiSW52YWxpZFByZWZpeEVycm9yIiwiZGVsaW1pdGVyIiwia2V5TWFya2VyIiwidXBsb2FkSWRNYXJrZXIiLCJ1cGxvYWRzIiwiZW5kZWQiLCJyZWFkU3RyZWFtIiwiUmVhZGFibGUiLCJvYmplY3RNb2RlIiwiX3JlYWQiLCJzaGlmdCIsImxpc3RJbmNvbXBsZXRlVXBsb2Fkc1F1ZXJ5IiwicHJlZml4ZXMiLCJlYWNoU2VyaWVzIiwidXBsb2FkIiwibGlzdFBhcnRzIiwia2V5IiwidXBsb2FkSWQiLCJwYXJ0cyIsInJlZHVjZSIsImFjYyIsIml0ZW0iLCJlbWl0IiwiaXNUcnVuY2F0ZWQiLCJuZXh0S2V5TWFya2VyIiwibmV4dFVwbG9hZElkTWFya2VyIiwicXVlcmllcyIsIm1heFVwbG9hZHMiLCJzb3J0IiwidW5zaGlmdCIsImpvaW4iLCJwYXJzZUxpc3RNdWx0aXBhcnQiLCJpbml0aWF0ZU5ld011bHRpcGFydFVwbG9hZCIsImFib3J0TXVsdGlwYXJ0VXBsb2FkIiwicmVxdWVzdE9wdGlvbnMiLCJmaW5kVXBsb2FkSWQiLCJfbGF0ZXN0VXBsb2FkIiwibGF0ZXN0VXBsb2FkIiwiaW5pdGlhdGVkIiwiZ2V0VGltZSIsImNvbXBsZXRlTXVsdGlwYXJ0VXBsb2FkIiwiZXRhZ3MiLCJidWlsZGVyIiwiQ29tcGxldGVNdWx0aXBhcnRVcGxvYWQiLCJQYXJ0IiwibWFwIiwiUGFydE51bWJlciIsInBhcnQiLCJFVGFnIiwiZXJyTWVzc2FnZSIsIm1hcmtlciIsImxpc3RQYXJ0c1F1ZXJ5IiwicGFyc2VMaXN0UGFydHMiLCJsaXN0QnVja2V0cyIsInJlZ2lvbkNvbmYiLCJodHRwUmVzIiwieG1sUmVzdWx0IiwicGFyc2VMaXN0QnVja2V0IiwiY2FsY3VsYXRlUGFydFNpemUiLCJmUHV0T2JqZWN0IiwicHV0T2JqZWN0IiwiY3JlYXRlUmVhZFN0cmVhbSIsInN0YXRTaXplIiwidXBsb2FkQnVmZmVyIiwiYnVmIiwidXBsb2FkU3RyZWFtIiwibWQ1c3VtIiwib2xkUGFydHMiLCJlVGFncyIsInByZXZpb3VzVXBsb2FkSWQiLCJvbGRUYWdzIiwiY2h1bmtpZXIiLCJ6ZXJvUGFkZGluZyIsIm8iLCJQcm9taXNlIiwiYWxsIiwicmVzb2x2ZSIsInJlamVjdCIsInBpcGUiLCJvbiIsInBhcnROdW1iZXIiLCJjaHVuayIsIm1kNSIsImNyZWF0ZUhhc2giLCJ1cGRhdGUiLCJkaWdlc3QiLCJvbGRQYXJ0IiwicmVtb3ZlQnVja2V0UmVwbGljYXRpb24iLCJzZXRCdWNrZXRSZXBsaWNhdGlvbiIsInJlcGxpY2F0aW9uQ29uZmlnIiwicm9sZSIsInJ1bGVzIiwicmVwbGljYXRpb25QYXJhbXNDb25maWciLCJSZXBsaWNhdGlvbkNvbmZpZ3VyYXRpb24iLCJSb2xlIiwiUnVsZSIsImdldEJ1Y2tldFJlcGxpY2F0aW9uIiwicGFyc2VSZXBsaWNhdGlvbkNvbmZpZyIsImdldE9iamVjdExlZ2FsSG9sZCIsImtleXMiLCJzdHJSZXMiLCJzZXRPYmplY3RMZWdhbEhvbGQiLCJzZXRPcHRzIiwic3RhdHVzIiwiRU5BQkxFRCIsIkRJU0FCTEVEIiwiY29uZmlnIiwiU3RhdHVzIiwicm9vdE5hbWUiLCJnZXRCdWNrZXRUYWdnaW5nIiwicGFyc2VUYWdnaW5nIiwiZ2V0T2JqZWN0VGFnZ2luZyIsInNldEJ1Y2tldFBvbGljeSIsInBvbGljeSIsIkludmFsaWRCdWNrZXRQb2xpY3lFcnJvciIsImdldEJ1Y2tldFBvbGljeSIsInB1dE9iamVjdFJldGVudGlvbiIsInJldGVudGlvbk9wdHMiLCJtb2RlIiwiQ09NUExJQU5DRSIsIkdPVkVSTkFOQ0UiLCJyZXRhaW5VbnRpbERhdGUiLCJNb2RlIiwiUmV0YWluVW50aWxEYXRlIiwiZ2V0T2JqZWN0TG9ja0NvbmZpZyIsInBhcnNlT2JqZWN0TG9ja0NvbmZpZyIsInNldE9iamVjdExvY2tDb25maWciLCJsb2NrQ29uZmlnT3B0cyIsInJldGVudGlvbk1vZGVzIiwidmFsaWRVbml0cyIsIkRBWVMiLCJZRUFSUyIsInVuaXQiLCJ2YWxpZGl0eSIsIk9iamVjdExvY2tFbmFibGVkIiwiY29uZmlnS2V5cyIsImlzQWxsS2V5c1NldCIsImV2ZXJ5IiwibGNrIiwiRGVmYXVsdFJldGVudGlvbiIsIkRheXMiLCJZZWFycyIsImdldEJ1Y2tldFZlcnNpb25pbmciLCJwYXJzZUJ1Y2tldFZlcnNpb25pbmdDb25maWciLCJzZXRCdWNrZXRWZXJzaW9uaW5nIiwidmVyc2lvbkNvbmZpZyIsInNldFRhZ2dpbmciLCJ0YWdnaW5nUGFyYW1zIiwidGFncyIsInB1dE9wdHMiLCJ0YWdzTGlzdCIsInZhbHVlIiwiS2V5IiwiVmFsdWUiLCJ0YWdnaW5nQ29uZmlnIiwiVGFnZ2luZyIsIlRhZ1NldCIsIlRhZyIsInBheWxvYWRCdWYiLCJyZW1vdmVUYWdnaW5nIiwic2V0QnVja2V0VGFnZ2luZyIsInJlbW92ZUJ1Y2tldFRhZ2dpbmciLCJzZXRPYmplY3RUYWdnaW5nIiwicmVtb3ZlT2JqZWN0VGFnZ2luZyIsInNlbGVjdE9iamVjdENvbnRlbnQiLCJzZWxlY3RPcHRzIiwiZXhwcmVzc2lvbiIsImlucHV0U2VyaWFsaXphdGlvbiIsIm91dHB1dFNlcmlhbGl6YXRpb24iLCJFeHByZXNzaW9uIiwiRXhwcmVzc2lvblR5cGUiLCJleHByZXNzaW9uVHlwZSIsIklucHV0U2VyaWFsaXphdGlvbiIsIk91dHB1dFNlcmlhbGl6YXRpb24iLCJyZXF1ZXN0UHJvZ3Jlc3MiLCJSZXF1ZXN0UHJvZ3Jlc3MiLCJzY2FuUmFuZ2UiLCJTY2FuUmFuZ2UiLCJhcHBseUJ1Y2tldExpZmVjeWNsZSIsInBvbGljeUNvbmZpZyIsInJlbW92ZUJ1Y2tldExpZmVjeWNsZSIsInNldEJ1Y2tldExpZmVjeWNsZSIsImxpZmVDeWNsZUNvbmZpZyIsImdldEJ1Y2tldExpZmVjeWNsZSIsInBhcnNlTGlmZWN5Y2xlQ29uZmlnIiwic2V0QnVja2V0RW5jcnlwdGlvbiIsImVuY3J5cHRpb25Db25maWciLCJlbmNyeXB0aW9uT2JqIiwiQXBwbHlTZXJ2ZXJTaWRlRW5jcnlwdGlvbkJ5RGVmYXVsdCIsIlNTRUFsZ29yaXRobSIsImdldEJ1Y2tldEVuY3J5cHRpb24iLCJwYXJzZUJ1Y2tldEVuY3J5cHRpb25Db25maWciLCJyZW1vdmVCdWNrZXRFbmNyeXB0aW9uIiwiZ2V0T2JqZWN0UmV0ZW50aW9uIiwicGFyc2VPYmplY3RSZXRlbnRpb25Db25maWciLCJyZW1vdmVPYmplY3RzIiwib2JqZWN0c0xpc3QiLCJBcnJheSIsImlzQXJyYXkiLCJydW5EZWxldGVPYmplY3RzIiwiYmF0Y2giLCJkZWxPYmplY3RzIiwiVmVyc2lvbklkIiwicmVtT2JqZWN0cyIsIkRlbGV0ZSIsIlF1aWV0IiwicmVtb3ZlT2JqZWN0c1BhcnNlciIsIm1heEVudHJpZXMiLCJiYXRjaGVzIiwiaSIsInNsaWNlIiwiYmF0Y2hSZXN1bHRzIiwiZmxhdCIsInJlbW92ZUluY29tcGxldGVVcGxvYWQiLCJJc1ZhbGlkQnVja2V0TmFtZUVycm9yIiwicmVtb3ZlVXBsb2FkSWQiLCJjb3B5T2JqZWN0VjEiLCJ0YXJnZXRCdWNrZXROYW1lIiwidGFyZ2V0T2JqZWN0TmFtZSIsInNvdXJjZUJ1Y2tldE5hbWVBbmRPYmplY3ROYW1lIiwiY29uZGl0aW9ucyIsIm1vZGlmaWVkIiwidW5tb2RpZmllZCIsIm1hdGNoRVRhZyIsIm1hdGNoRVRhZ0V4Y2VwdCIsInBhcnNlQ29weU9iamVjdCIsImNvcHlPYmplY3RWMiIsInNvdXJjZUNvbmZpZyIsImRlc3RDb25maWciLCJ2YWxpZGF0ZSIsImdldEhlYWRlcnMiLCJCdWNrZXQiLCJjb3B5UmVzIiwicmVzSGVhZGVycyIsInNpemVIZWFkZXJWYWx1ZSIsIkxhc3RNb2RpZmllZCIsIk1ldGFEYXRhIiwiU291cmNlVmVyc2lvbklkIiwiRXRhZyIsIlNpemUiLCJjb3B5T2JqZWN0IiwiYWxsQXJncyIsInNvdXJjZSIsImRlc3QiLCJ1cGxvYWRQYXJ0IiwicGFydENvbmZpZyIsInVwbG9hZElEIiwicGFydFJlcyIsInBhcnRFdGFnVmFsIiwiY29tcG9zZU9iamVjdCIsImRlc3RPYmpDb25maWciLCJzb3VyY2VPYmpMaXN0IiwibWF4Q29uY3VycmVuY3kiLCJzb3VyY2VGaWxlc0xlbmd0aCIsIk1BWF9QQVJUU19DT1VOVCIsInNPYmoiLCJnZXRTdGF0T3B0aW9ucyIsInNyY0NvbmZpZyIsIlZlcnNpb25JRCIsInNyY09iamVjdFNpemVzIiwidG90YWxTaXplIiwidG90YWxQYXJ0cyIsInNvdXJjZU9ialN0YXRzIiwic3JjSXRlbSIsInNyY09iamVjdEluZm9zIiwidmFsaWRhdGVkU3RhdHMiLCJyZXNJdGVtU3RhdCIsImluZGV4Iiwic3JjQ29weVNpemUiLCJNYXRjaFJhbmdlIiwic3JjU3RhcnQiLCJTdGFydCIsInNyY0VuZCIsIkVuZCIsIkFCU19NSU5fUEFSVF9TSVpFIiwiTUFYX01VTFRJUEFSVF9QVVRfT0JKRUNUX1NJWkUiLCJNQVhfUEFSVF9TSVpFIiwiTWF0Y2hFVGFnIiwic3BsaXRQYXJ0U2l6ZUxpc3QiLCJpZHgiLCJnZXRVcGxvYWRQYXJ0Q29uZmlnTGlzdCIsInVwbG9hZFBhcnRDb25maWdMaXN0Iiwic3BsaXRTaXplIiwic3BsaXRJbmRleCIsInN0YXJ0SW5kZXgiLCJzdGFydElkeCIsImVuZEluZGV4IiwiZW5kSWR4Iiwib2JqSW5mbyIsIm9iakNvbmZpZyIsInBhcnRJbmRleCIsInRvdGFsVXBsb2FkcyIsInNwbGl0U3RhcnQiLCJ1cGxkQ3RySWR4Iiwic3BsaXRFbmQiLCJzb3VyY2VPYmoiLCJ1cGxvYWRQYXJ0Q29uZmlnIiwidXBsb2FkQWxsUGFydHMiLCJ1cGxvYWRMaXN0IiwicGFydFVwbG9hZHMiLCJwZXJmb3JtVXBsb2FkUGFydHMiLCJwYXJ0c1JlcyIsInBhcnRDb3B5IiwibmV3VXBsb2FkSGVhZGVycyIsInBhcnRzRG9uZSIsInByZXNpZ25lZFVybCIsImV4cGlyZXMiLCJyZXFQYXJhbXMiLCJyZXF1ZXN0RGF0ZSIsIl9yZXF1ZXN0RGF0ZSIsIkFub255bW91c1JlcXVlc3RFcnJvciIsImlzTmFOIiwicHJlc2lnbmVkR2V0T2JqZWN0IiwicmVzcEhlYWRlcnMiLCJ2YWxpZFJlc3BIZWFkZXJzIiwiaGVhZGVyIiwicHJlc2lnbmVkUHV0T2JqZWN0IiwibmV3UG9zdFBvbGljeSIsInByZXNpZ25lZFBvc3RQb2xpY3kiLCJwb3N0UG9saWN5IiwiZm9ybURhdGEiLCJkYXRlU3RyIiwiZXhwaXJhdGlvbiIsInNldFNlY29uZHMiLCJzZXRFeHBpcmVzIiwicG9saWN5QmFzZTY0IiwicG9ydFN0ciIsInVybFN0ciIsInBvc3RVUkwiLCJsaXN0T2JqZWN0c1F1ZXJ5IiwibGlzdFF1ZXJ5T3B0cyIsIkRlbGltaXRlciIsIk1heEtleXMiLCJJbmNsdWRlVmVyc2lvbiIsInZlcnNpb25JZE1hcmtlciIsImxpc3RRcnlMaXN0IiwibGlzdE9iamVjdHMiLCJsaXN0T3B0cyIsIm9iamVjdHMiLCJuZXh0TWFya2VyIiwibGlzdE9iamVjdHNWMlF1ZXJ5IiwiY29udGludWF0aW9uVG9rZW4iLCJtYXhLZXlzIiwic3RhcnRBZnRlciIsImxpc3RPYmplY3RzVjIiLCJwcmVmaXhTdHIiLCJzdGFydEFmdGVyU3RyIiwibmV4dENvbnRpbnVhdGlvblRva2VuIiwic2V0QnVja2V0Tm90aWZpY2F0aW9uIiwicmVtb3ZlQWxsQnVja2V0Tm90aWZpY2F0aW9uIiwiZ2V0QnVja2V0Tm90aWZpY2F0aW9uIiwibGlzdGVuQnVja2V0Tm90aWZpY2F0aW9uIiwic3VmZml4IiwiZXZlbnRzIiwibGlzdGVuZXIiLCJzdGFydCJdLCJzb3VyY2VzIjpbImNsaWVudC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjcnlwdG8gZnJvbSAnbm9kZTpjcnlwdG8nXG5pbXBvcnQgKiBhcyBmcyBmcm9tICdub2RlOmZzJ1xuaW1wb3J0IHR5cGUgeyBJbmNvbWluZ0h0dHBIZWFkZXJzIH0gZnJvbSAnbm9kZTpodHRwJ1xuaW1wb3J0ICogYXMgaHR0cCBmcm9tICdub2RlOmh0dHAnXG5pbXBvcnQgKiBhcyBodHRwcyBmcm9tICdub2RlOmh0dHBzJ1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdub2RlOnBhdGgnXG5pbXBvcnQgKiBhcyBzdHJlYW0gZnJvbSAnbm9kZTpzdHJlYW0nXG5cbmltcG9ydCAqIGFzIGFzeW5jIGZyb20gJ2FzeW5jJ1xuaW1wb3J0IEJsb2NrU3RyZWFtMiBmcm9tICdibG9jay1zdHJlYW0yJ1xuaW1wb3J0IHsgaXNCcm93c2VyIH0gZnJvbSAnYnJvd3Nlci1vci1ub2RlJ1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJ1xuaW1wb3J0ICogYXMgcXMgZnJvbSAncXVlcnktc3RyaW5nJ1xuaW1wb3J0IHhtbDJqcyBmcm9tICd4bWwyanMnXG5cbmltcG9ydCB7IENyZWRlbnRpYWxQcm92aWRlciB9IGZyb20gJy4uL0NyZWRlbnRpYWxQcm92aWRlci50cydcbmltcG9ydCAqIGFzIGVycm9ycyBmcm9tICcuLi9lcnJvcnMudHMnXG5pbXBvcnQgdHlwZSB7IFNlbGVjdFJlc3VsdHMgfSBmcm9tICcuLi9oZWxwZXJzLnRzJ1xuaW1wb3J0IHtcbiAgQ29weURlc3RpbmF0aW9uT3B0aW9ucyxcbiAgQ29weVNvdXJjZU9wdGlvbnMsXG4gIERFRkFVTFRfUkVHSU9OLFxuICBMRUdBTF9IT0xEX1NUQVRVUyxcbiAgUFJFU0lHTl9FWFBJUllfREFZU19NQVgsXG4gIFJFVEVOVElPTl9NT0RFUyxcbiAgUkVURU5USU9OX1ZBTElESVRZX1VOSVRTLFxufSBmcm9tICcuLi9oZWxwZXJzLnRzJ1xuaW1wb3J0IHR5cGUgeyBOb3RpZmljYXRpb25FdmVudCB9IGZyb20gJy4uL25vdGlmaWNhdGlvbi50cydcbmltcG9ydCB7IE5vdGlmaWNhdGlvbkNvbmZpZywgTm90aWZpY2F0aW9uUG9sbGVyIH0gZnJvbSAnLi4vbm90aWZpY2F0aW9uLnRzJ1xuaW1wb3J0IHsgcG9zdFByZXNpZ25TaWduYXR1cmVWNCwgcHJlc2lnblNpZ25hdHVyZVY0LCBzaWduVjQgfSBmcm9tICcuLi9zaWduaW5nLnRzJ1xuaW1wb3J0IHsgZnNwLCBzdHJlYW1Qcm9taXNlIH0gZnJvbSAnLi9hc3luYy50cydcbmltcG9ydCB7IENvcHlDb25kaXRpb25zIH0gZnJvbSAnLi9jb3B5LWNvbmRpdGlvbnMudHMnXG5pbXBvcnQgeyBFeHRlbnNpb25zIH0gZnJvbSAnLi9leHRlbnNpb25zLnRzJ1xuaW1wb3J0IHtcbiAgY2FsY3VsYXRlRXZlblNwbGl0cyxcbiAgZXh0cmFjdE1ldGFkYXRhLFxuICBnZXRDb250ZW50TGVuZ3RoLFxuICBnZXRTY29wZSxcbiAgZ2V0U291cmNlVmVyc2lvbklkLFxuICBnZXRWZXJzaW9uSWQsXG4gIGhhc2hCaW5hcnksXG4gIGluc2VydENvbnRlbnRUeXBlLFxuICBpc0FtYXpvbkVuZHBvaW50LFxuICBpc0Jvb2xlYW4sXG4gIGlzRGVmaW5lZCxcbiAgaXNFbXB0eSxcbiAgaXNOdW1iZXIsXG4gIGlzT2JqZWN0LFxuICBpc1BsYWluT2JqZWN0LFxuICBpc1JlYWRhYmxlU3RyZWFtLFxuICBpc1N0cmluZyxcbiAgaXNWYWxpZEJ1Y2tldE5hbWUsXG4gIGlzVmFsaWRFbmRwb2ludCxcbiAgaXNWYWxpZE9iamVjdE5hbWUsXG4gIGlzVmFsaWRQb3J0LFxuICBpc1ZhbGlkUHJlZml4LFxuICBpc1ZpcnR1YWxIb3N0U3R5bGUsXG4gIG1ha2VEYXRlTG9uZyxcbiAgUEFSVF9DT05TVFJBSU5UUyxcbiAgcGFydHNSZXF1aXJlZCxcbiAgcHJlcGVuZFhBTVpNZXRhLFxuICByZWFkYWJsZVN0cmVhbSxcbiAgc2FuaXRpemVFVGFnLFxuICB0b01kNSxcbiAgdG9TaGEyNTYsXG4gIHVyaUVzY2FwZSxcbiAgdXJpUmVzb3VyY2VFc2NhcGUsXG59IGZyb20gJy4vaGVscGVyLnRzJ1xuaW1wb3J0IHsgam9pbkhvc3RQb3J0IH0gZnJvbSAnLi9qb2luLWhvc3QtcG9ydC50cydcbmltcG9ydCB7IFBvc3RQb2xpY3kgfSBmcm9tICcuL3Bvc3QtcG9saWN5LnRzJ1xuaW1wb3J0IHsgcmVxdWVzdFdpdGhSZXRyeSB9IGZyb20gJy4vcmVxdWVzdC50cydcbmltcG9ydCB7IGRyYWluUmVzcG9uc2UsIHJlYWRBc0J1ZmZlciwgcmVhZEFzU3RyaW5nIH0gZnJvbSAnLi9yZXNwb25zZS50cydcbmltcG9ydCB0eXBlIHsgUmVnaW9uIH0gZnJvbSAnLi9zMy1lbmRwb2ludHMudHMnXG5pbXBvcnQgeyBnZXRTM0VuZHBvaW50IH0gZnJvbSAnLi9zMy1lbmRwb2ludHMudHMnXG5pbXBvcnQgdHlwZSB7XG4gIEJpbmFyeSxcbiAgQnVja2V0SXRlbSxcbiAgQnVja2V0SXRlbUZyb21MaXN0LFxuICBCdWNrZXRJdGVtU3RhdCxcbiAgQnVja2V0U3RyZWFtLFxuICBCdWNrZXRWZXJzaW9uaW5nQ29uZmlndXJhdGlvbixcbiAgQ29weU9iamVjdFBhcmFtcyxcbiAgQ29weU9iamVjdFJlc3VsdCxcbiAgQ29weU9iamVjdFJlc3VsdFYyLFxuICBFbmNyeXB0aW9uQ29uZmlnLFxuICBHZXRPYmplY3RMZWdhbEhvbGRPcHRpb25zLFxuICBHZXRPYmplY3RPcHRzLFxuICBHZXRPYmplY3RSZXRlbnRpb25PcHRzLFxuICBJbmNvbXBsZXRlVXBsb2FkZWRCdWNrZXRJdGVtLFxuICBJUmVxdWVzdCxcbiAgSXRlbUJ1Y2tldE1ldGFkYXRhLFxuICBMaWZlY3ljbGVDb25maWcsXG4gIExpZmVDeWNsZUNvbmZpZ1BhcmFtLFxuICBMaXN0T2JqZWN0UXVlcnlPcHRzLFxuICBMaXN0T2JqZWN0UXVlcnlSZXMsXG4gIExpc3RPYmplY3RWMlJlcyxcbiAgTm90aWZpY2F0aW9uQ29uZmlnUmVzdWx0LFxuICBPYmplY3RJbmZvLFxuICBPYmplY3RMb2NrQ29uZmlnUGFyYW0sXG4gIE9iamVjdExvY2tJbmZvLFxuICBPYmplY3RNZXRhRGF0YSxcbiAgT2JqZWN0UmV0ZW50aW9uSW5mbyxcbiAgUG9zdFBvbGljeVJlc3VsdCxcbiAgUHJlU2lnblJlcXVlc3RQYXJhbXMsXG4gIFB1dE9iamVjdExlZ2FsSG9sZE9wdGlvbnMsXG4gIFB1dFRhZ2dpbmdQYXJhbXMsXG4gIFJlbW92ZU9iamVjdHNQYXJhbSxcbiAgUmVtb3ZlT2JqZWN0c1JlcXVlc3RFbnRyeSxcbiAgUmVtb3ZlT2JqZWN0c1Jlc3BvbnNlLFxuICBSZW1vdmVUYWdnaW5nUGFyYW1zLFxuICBSZXBsaWNhdGlvbkNvbmZpZyxcbiAgUmVwbGljYXRpb25Db25maWdPcHRzLFxuICBSZXF1ZXN0SGVhZGVycyxcbiAgUmVzcG9uc2VIZWFkZXIsXG4gIFJlc3VsdENhbGxiYWNrLFxuICBSZXRlbnRpb24sXG4gIFNlbGVjdE9wdGlvbnMsXG4gIFN0YXRPYmplY3RPcHRzLFxuICBUYWcsXG4gIFRhZ2dpbmdPcHRzLFxuICBUYWdzLFxuICBUcmFuc3BvcnQsXG4gIFVwbG9hZGVkT2JqZWN0SW5mbyxcbiAgVXBsb2FkUGFydENvbmZpZyxcbn0gZnJvbSAnLi90eXBlLnRzJ1xuaW1wb3J0IHR5cGUgeyBMaXN0TXVsdGlwYXJ0UmVzdWx0LCBVcGxvYWRlZFBhcnQgfSBmcm9tICcuL3htbC1wYXJzZXIudHMnXG5pbXBvcnQge1xuICBwYXJzZUJ1Y2tldE5vdGlmaWNhdGlvbixcbiAgcGFyc2VDb21wbGV0ZU11bHRpcGFydCxcbiAgcGFyc2VJbml0aWF0ZU11bHRpcGFydCxcbiAgcGFyc2VMaXN0T2JqZWN0cyxcbiAgcGFyc2VMaXN0T2JqZWN0c1YyLFxuICBwYXJzZU9iamVjdExlZ2FsSG9sZENvbmZpZyxcbiAgcGFyc2VTZWxlY3RPYmplY3RDb250ZW50UmVzcG9uc2UsXG4gIHVwbG9hZFBhcnRQYXJzZXIsXG59IGZyb20gJy4veG1sLXBhcnNlci50cydcbmltcG9ydCAqIGFzIHhtbFBhcnNlcnMgZnJvbSAnLi94bWwtcGFyc2VyLnRzJ1xuXG5jb25zdCB4bWwgPSBuZXcgeG1sMmpzLkJ1aWxkZXIoeyByZW5kZXJPcHRzOiB7IHByZXR0eTogZmFsc2UgfSwgaGVhZGxlc3M6IHRydWUgfSlcblxuLy8gd2lsbCBiZSByZXBsYWNlZCBieSBidW5kbGVyLlxuY29uc3QgUGFja2FnZSA9IHsgdmVyc2lvbjogcHJvY2Vzcy5lbnYuSEFOWk9TM19KU19QQUNLQUdFX1ZFUlNJT04gfHwgJ2RldmVsb3BtZW50JyB9XG5cbmNvbnN0IHJlcXVlc3RPcHRpb25Qcm9wZXJ0aWVzID0gW1xuICAnYWdlbnQnLFxuICAnY2EnLFxuICAnY2VydCcsXG4gICdjaXBoZXJzJyxcbiAgJ2NsaWVudENlcnRFbmdpbmUnLFxuICAnY3JsJyxcbiAgJ2RocGFyYW0nLFxuICAnZWNkaEN1cnZlJyxcbiAgJ2ZhbWlseScsXG4gICdob25vckNpcGhlck9yZGVyJyxcbiAgJ2tleScsXG4gICdwYXNzcGhyYXNlJyxcbiAgJ3BmeCcsXG4gICdyZWplY3RVbmF1dGhvcml6ZWQnLFxuICAnc2VjdXJlT3B0aW9ucycsXG4gICdzZWN1cmVQcm90b2NvbCcsXG4gICdzZXJ2ZXJuYW1lJyxcbiAgJ3Nlc3Npb25JZENvbnRleHQnLFxuXSBhcyBjb25zdFxuXG5leHBvcnQgaW50ZXJmYWNlIFJldHJ5T3B0aW9ucyB7XG4gIC8qKlxuICAgKiBJZiB0aGlzIHNldCB0byB0cnVlLCBpdCB3aWxsIHRha2UgcHJlY2VkZW5jZSBvdmVyIGFsbCBvdGhlciByZXRyeSBvcHRpb25zLlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgZGlzYWJsZVJldHJ5PzogYm9vbGVhblxuICAvKipcbiAgICogVGhlIG1heGltdW0gYW1vdW50IG9mIHJldHJpZXMgZm9yIGEgcmVxdWVzdC5cbiAgICogQGRlZmF1bHQgMVxuICAgKi9cbiAgbWF4aW11bVJldHJ5Q291bnQ/OiBudW1iZXJcbiAgLyoqXG4gICAqIFRoZSBtaW5pbXVtIGR1cmF0aW9uIChpbiBtaWxsaXNlY29uZHMpIGZvciB0aGUgZXhwb25lbnRpYWwgYmFja29mZiBhbGdvcml0aG0uXG4gICAqIEBkZWZhdWx0IDEwMFxuICAgKi9cbiAgYmFzZURlbGF5TXM/OiBudW1iZXJcbiAgLyoqXG4gICAqIFRoZSBtYXhpbXVtIGR1cmF0aW9uIChpbiBtaWxsaXNlY29uZHMpIGZvciB0aGUgZXhwb25lbnRpYWwgYmFja29mZiBhbGdvcml0aG0uXG4gICAqIEBkZWZhdWx0IDYwMDAwXG4gICAqL1xuICBtYXhpbXVtRGVsYXlNcz86IG51bWJlclxufVxuXG5leHBvcnQgaW50ZXJmYWNlIENsaWVudE9wdGlvbnMge1xuICBlbmRQb2ludDogc3RyaW5nXG4gIGFjY2Vzc0tleT86IHN0cmluZ1xuICBzZWNyZXRLZXk/OiBzdHJpbmdcbiAgdXNlU1NMPzogYm9vbGVhblxuICBwb3J0PzogbnVtYmVyXG4gIHJlZ2lvbj86IFJlZ2lvblxuICB0cmFuc3BvcnQ/OiBUcmFuc3BvcnRcbiAgc2Vzc2lvblRva2VuPzogc3RyaW5nXG4gIHBhcnRTaXplPzogbnVtYmVyXG4gIHBhdGhTdHlsZT86IGJvb2xlYW5cbiAgY3JlZGVudGlhbHNQcm92aWRlcj86IENyZWRlbnRpYWxQcm92aWRlclxuICBzM0FjY2VsZXJhdGVFbmRwb2ludD86IHN0cmluZ1xuICB0cmFuc3BvcnRBZ2VudD86IGh0dHAuQWdlbnRcbiAgcmV0cnlPcHRpb25zPzogUmV0cnlPcHRpb25zXG59XG5cbmV4cG9ydCB0eXBlIFJlcXVlc3RPcHRpb24gPSBQYXJ0aWFsPElSZXF1ZXN0PiAmIHtcbiAgbWV0aG9kOiBzdHJpbmdcbiAgYnVja2V0TmFtZT86IHN0cmluZ1xuICBvYmplY3ROYW1lPzogc3RyaW5nXG4gIHF1ZXJ5Pzogc3RyaW5nXG4gIHBhdGhTdHlsZT86IGJvb2xlYW5cbn1cblxuZXhwb3J0IHR5cGUgTm9SZXN1bHRDYWxsYmFjayA9IChlcnJvcjogdW5rbm93bikgPT4gdm9pZFxuXG5leHBvcnQgaW50ZXJmYWNlIE1ha2VCdWNrZXRPcHQge1xuICBPYmplY3RMb2NraW5nPzogYm9vbGVhblxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlbW92ZU9wdGlvbnMge1xuICB2ZXJzaW9uSWQ/OiBzdHJpbmdcbiAgZ292ZXJuYW5jZUJ5cGFzcz86IGJvb2xlYW5cbiAgZm9yY2VEZWxldGU/OiBib29sZWFuXG59XG5cbnR5cGUgUGFydCA9IHtcbiAgcGFydDogbnVtYmVyXG4gIGV0YWc6IHN0cmluZ1xufVxuXG5leHBvcnQgY2xhc3MgVHlwZWRDbGllbnQge1xuICBwcm90ZWN0ZWQgdHJhbnNwb3J0OiBUcmFuc3BvcnRcbiAgcHJvdGVjdGVkIGhvc3Q6IHN0cmluZ1xuICBwcm90ZWN0ZWQgcG9ydDogbnVtYmVyXG4gIHByb3RlY3RlZCBwcm90b2NvbDogc3RyaW5nXG4gIHByb3RlY3RlZCBhY2Nlc3NLZXk6IHN0cmluZ1xuICBwcm90ZWN0ZWQgc2VjcmV0S2V5OiBzdHJpbmdcbiAgcHJvdGVjdGVkIHNlc3Npb25Ub2tlbj86IHN0cmluZ1xuICBwcm90ZWN0ZWQgdXNlckFnZW50OiBzdHJpbmdcbiAgcHJvdGVjdGVkIGFub255bW91czogYm9vbGVhblxuICBwcm90ZWN0ZWQgcGF0aFN0eWxlOiBib29sZWFuXG4gIHByb3RlY3RlZCByZWdpb25NYXA6IFJlY29yZDxzdHJpbmcsIHN0cmluZz5cbiAgcHVibGljIHJlZ2lvbj86IHN0cmluZ1xuICBwcm90ZWN0ZWQgY3JlZGVudGlhbHNQcm92aWRlcj86IENyZWRlbnRpYWxQcm92aWRlclxuICBwYXJ0U2l6ZTogbnVtYmVyID0gNjQgKiAxMDI0ICogMTAyNFxuICBwcm90ZWN0ZWQgb3ZlclJpZGVQYXJ0U2l6ZT86IGJvb2xlYW5cbiAgcHJvdGVjdGVkIHJldHJ5T3B0aW9uczogUmV0cnlPcHRpb25zXG5cbiAgcHJvdGVjdGVkIG1heGltdW1QYXJ0U2l6ZSA9IDUgKiAxMDI0ICogMTAyNCAqIDEwMjRcbiAgcHJvdGVjdGVkIG1heE9iamVjdFNpemUgPSA1ICogMTAyNCAqIDEwMjQgKiAxMDI0ICogMTAyNFxuICBwdWJsaWMgZW5hYmxlU0hBMjU2OiBib29sZWFuXG4gIHByb3RlY3RlZCBzM0FjY2VsZXJhdGVFbmRwb2ludD86IHN0cmluZ1xuICBwcm90ZWN0ZWQgcmVxT3B0aW9uczogUmVjb3JkPHN0cmluZywgdW5rbm93bj5cblxuICBwcm90ZWN0ZWQgdHJhbnNwb3J0QWdlbnQ6IGh0dHAuQWdlbnRcbiAgcHJpdmF0ZSByZWFkb25seSBjbGllbnRFeHRlbnNpb25zOiBFeHRlbnNpb25zXG5cbiAgY29uc3RydWN0b3IocGFyYW1zOiBDbGllbnRPcHRpb25zKSB7XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciBkZXByZWNhdGVkIHByb3BlcnR5XG4gICAgaWYgKHBhcmFtcy5zZWN1cmUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcInNlY3VyZVwiIG9wdGlvbiBkZXByZWNhdGVkLCBcInVzZVNTTFwiIHNob3VsZCBiZSB1c2VkIGluc3RlYWQnKVxuICAgIH1cbiAgICAvLyBEZWZhdWx0IHZhbHVlcyBpZiBub3Qgc3BlY2lmaWVkLlxuICAgIGlmIChwYXJhbXMudXNlU1NMID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHBhcmFtcy51c2VTU0wgPSB0cnVlXG4gICAgfVxuICAgIGlmICghcGFyYW1zLnBvcnQpIHtcbiAgICAgIHBhcmFtcy5wb3J0ID0gMFxuICAgIH1cbiAgICAvLyBWYWxpZGF0ZSBpbnB1dCBwYXJhbXMuXG4gICAgaWYgKCFpc1ZhbGlkRW5kcG9pbnQocGFyYW1zLmVuZFBvaW50KSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkRW5kcG9pbnRFcnJvcihgSW52YWxpZCBlbmRQb2ludCA6ICR7cGFyYW1zLmVuZFBvaW50fWApXG4gICAgfVxuICAgIGlmICghaXNWYWxpZFBvcnQocGFyYW1zLnBvcnQpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKGBJbnZhbGlkIHBvcnQgOiAke3BhcmFtcy5wb3J0fWApXG4gICAgfVxuICAgIGlmICghaXNCb29sZWFuKHBhcmFtcy51c2VTU0wpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKFxuICAgICAgICBgSW52YWxpZCB1c2VTU0wgZmxhZyB0eXBlIDogJHtwYXJhbXMudXNlU1NMfSwgZXhwZWN0ZWQgdG8gYmUgb2YgdHlwZSBcImJvb2xlYW5cImAsXG4gICAgICApXG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgcmVnaW9uIG9ubHkgaWYgaXRzIHNldC5cbiAgICBpZiAocGFyYW1zLnJlZ2lvbikge1xuICAgICAgaWYgKCFpc1N0cmluZyhwYXJhbXMucmVnaW9uKSkge1xuICAgICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKGBJbnZhbGlkIHJlZ2lvbiA6ICR7cGFyYW1zLnJlZ2lvbn1gKVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGhvc3QgPSBwYXJhbXMuZW5kUG9pbnQudG9Mb3dlckNhc2UoKVxuICAgIGxldCBwb3J0ID0gcGFyYW1zLnBvcnRcbiAgICBsZXQgcHJvdG9jb2w6IHN0cmluZ1xuICAgIGxldCB0cmFuc3BvcnRcbiAgICBsZXQgdHJhbnNwb3J0QWdlbnQ6IGh0dHAuQWdlbnRcbiAgICAvLyBWYWxpZGF0ZSBpZiBjb25maWd1cmF0aW9uIGlzIG5vdCB1c2luZyBTU0xcbiAgICAvLyBmb3IgY29uc3RydWN0aW5nIHJlbGV2YW50IGVuZHBvaW50cy5cbiAgICBpZiAocGFyYW1zLnVzZVNTTCkge1xuICAgICAgLy8gRGVmYXVsdHMgdG8gc2VjdXJlLlxuICAgICAgdHJhbnNwb3J0ID0gaHR0cHNcbiAgICAgIHByb3RvY29sID0gJ2h0dHBzOidcbiAgICAgIHBvcnQgPSBwb3J0IHx8IDQ0M1xuICAgICAgdHJhbnNwb3J0QWdlbnQgPSBodHRwcy5nbG9iYWxBZ2VudFxuICAgIH0gZWxzZSB7XG4gICAgICB0cmFuc3BvcnQgPSBodHRwXG4gICAgICBwcm90b2NvbCA9ICdodHRwOidcbiAgICAgIHBvcnQgPSBwb3J0IHx8IDgwXG4gICAgICB0cmFuc3BvcnRBZ2VudCA9IGh0dHAuZ2xvYmFsQWdlbnRcbiAgICB9XG5cbiAgICAvLyBpZiBjdXN0b20gdHJhbnNwb3J0IGlzIHNldCwgdXNlIGl0LlxuICAgIGlmIChwYXJhbXMudHJhbnNwb3J0KSB7XG4gICAgICBpZiAoIWlzT2JqZWN0KHBhcmFtcy50cmFuc3BvcnQpKSB7XG4gICAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoXG4gICAgICAgICAgYEludmFsaWQgdHJhbnNwb3J0IHR5cGUgOiAke3BhcmFtcy50cmFuc3BvcnR9LCBleHBlY3RlZCB0byBiZSB0eXBlIFwib2JqZWN0XCJgLFxuICAgICAgICApXG4gICAgICB9XG4gICAgICB0cmFuc3BvcnQgPSBwYXJhbXMudHJhbnNwb3J0XG4gICAgfVxuXG4gICAgLy8gaWYgY3VzdG9tIHRyYW5zcG9ydCBhZ2VudCBpcyBzZXQsIHVzZSBpdC5cbiAgICBpZiAocGFyYW1zLnRyYW5zcG9ydEFnZW50KSB7XG4gICAgICBpZiAoIWlzT2JqZWN0KHBhcmFtcy50cmFuc3BvcnRBZ2VudCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihcbiAgICAgICAgICBgSW52YWxpZCB0cmFuc3BvcnRBZ2VudCB0eXBlOiAke3BhcmFtcy50cmFuc3BvcnRBZ2VudH0sIGV4cGVjdGVkIHRvIGJlIHR5cGUgXCJvYmplY3RcImAsXG4gICAgICAgIClcbiAgICAgIH1cblxuICAgICAgdHJhbnNwb3J0QWdlbnQgPSBwYXJhbXMudHJhbnNwb3J0QWdlbnRcbiAgICB9XG5cbiAgICAvLyBVc2VyIEFnZW50IHNob3VsZCBhbHdheXMgZm9sbG93aW5nIHRoZSBiZWxvdyBzdHlsZS5cbiAgICAvLyBQbGVhc2Ugb3BlbiBhbiBpc3N1ZSB0byBkaXNjdXNzIGFueSBuZXcgY2hhbmdlcyBoZXJlLlxuICAgIC8vXG4gICAgLy8gICAgICAgSGFuem9TMyAoT1M7IEFSQ0gpIExJQi9WRVIgQVBQL1ZFUlxuICAgIC8vXG4gICAgY29uc3QgbGlicmFyeUNvbW1lbnRzID0gYCgke3Byb2Nlc3MucGxhdGZvcm19OyAke3Byb2Nlc3MuYXJjaH0pYFxuICAgIGNvbnN0IGxpYnJhcnlBZ2VudCA9IGBIYW56b1MzICR7bGlicmFyeUNvbW1lbnRzfSBoYW56by1zMy8ke1BhY2thZ2UudmVyc2lvbn1gXG4gICAgLy8gVXNlciBhZ2VudCBibG9jayBlbmRzLlxuXG4gICAgdGhpcy50cmFuc3BvcnQgPSB0cmFuc3BvcnRcbiAgICB0aGlzLnRyYW5zcG9ydEFnZW50ID0gdHJhbnNwb3J0QWdlbnRcbiAgICB0aGlzLmhvc3QgPSBob3N0XG4gICAgdGhpcy5wb3J0ID0gcG9ydFxuICAgIHRoaXMucHJvdG9jb2wgPSBwcm90b2NvbFxuICAgIHRoaXMudXNlckFnZW50ID0gYCR7bGlicmFyeUFnZW50fWBcblxuICAgIC8vIERlZmF1bHQgcGF0aCBzdHlsZSBpcyB0cnVlXG4gICAgaWYgKHBhcmFtcy5wYXRoU3R5bGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5wYXRoU3R5bGUgPSB0cnVlXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucGF0aFN0eWxlID0gcGFyYW1zLnBhdGhTdHlsZVxuICAgIH1cblxuICAgIHRoaXMuYWNjZXNzS2V5ID0gcGFyYW1zLmFjY2Vzc0tleSA/PyAnJ1xuICAgIHRoaXMuc2VjcmV0S2V5ID0gcGFyYW1zLnNlY3JldEtleSA/PyAnJ1xuICAgIHRoaXMuc2Vzc2lvblRva2VuID0gcGFyYW1zLnNlc3Npb25Ub2tlblxuICAgIHRoaXMuYW5vbnltb3VzID0gIXRoaXMuYWNjZXNzS2V5IHx8ICF0aGlzLnNlY3JldEtleVxuXG4gICAgaWYgKHBhcmFtcy5jcmVkZW50aWFsc1Byb3ZpZGVyKSB7XG4gICAgICB0aGlzLmFub255bW91cyA9IGZhbHNlXG4gICAgICB0aGlzLmNyZWRlbnRpYWxzUHJvdmlkZXIgPSBwYXJhbXMuY3JlZGVudGlhbHNQcm92aWRlclxuICAgIH1cblxuICAgIHRoaXMucmVnaW9uTWFwID0ge31cbiAgICBpZiAocGFyYW1zLnJlZ2lvbikge1xuICAgICAgdGhpcy5yZWdpb24gPSBwYXJhbXMucmVnaW9uXG4gICAgfVxuXG4gICAgaWYgKHBhcmFtcy5wYXJ0U2l6ZSkge1xuICAgICAgdGhpcy5wYXJ0U2l6ZSA9IHBhcmFtcy5wYXJ0U2l6ZVxuICAgICAgdGhpcy5vdmVyUmlkZVBhcnRTaXplID0gdHJ1ZVxuICAgIH1cbiAgICBpZiAodGhpcy5wYXJ0U2l6ZSA8IDUgKiAxMDI0ICogMTAyNCkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihgUGFydCBzaXplIHNob3VsZCBiZSBncmVhdGVyIHRoYW4gNU1CYClcbiAgICB9XG4gICAgaWYgKHRoaXMucGFydFNpemUgPiA1ICogMTAyNCAqIDEwMjQgKiAxMDI0KSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKGBQYXJ0IHNpemUgc2hvdWxkIGJlIGxlc3MgdGhhbiA1R0JgKVxuICAgIH1cblxuICAgIC8vIFNIQTI1NiBpcyBlbmFibGVkIG9ubHkgZm9yIGF1dGhlbnRpY2F0ZWQgaHR0cCByZXF1ZXN0cy4gSWYgdGhlIHJlcXVlc3QgaXMgYXV0aGVudGljYXRlZFxuICAgIC8vIGFuZCB0aGUgY29ubmVjdGlvbiBpcyBodHRwcyB3ZSB1c2UgeC1hbXotY29udGVudC1zaGEyNTY9VU5TSUdORUQtUEFZTE9BRFxuICAgIC8vIGhlYWRlciBmb3Igc2lnbmF0dXJlIGNhbGN1bGF0aW9uLlxuICAgIHRoaXMuZW5hYmxlU0hBMjU2ID0gIXRoaXMuYW5vbnltb3VzICYmICFwYXJhbXMudXNlU1NMXG5cbiAgICB0aGlzLnMzQWNjZWxlcmF0ZUVuZHBvaW50ID0gcGFyYW1zLnMzQWNjZWxlcmF0ZUVuZHBvaW50IHx8IHVuZGVmaW5lZFxuICAgIHRoaXMucmVxT3B0aW9ucyA9IHt9XG4gICAgdGhpcy5jbGllbnRFeHRlbnNpb25zID0gbmV3IEV4dGVuc2lvbnModGhpcylcblxuICAgIGlmIChwYXJhbXMucmV0cnlPcHRpb25zKSB7XG4gICAgICBpZiAoIWlzT2JqZWN0KHBhcmFtcy5yZXRyeU9wdGlvbnMpKSB7XG4gICAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoXG4gICAgICAgICAgYEludmFsaWQgcmV0cnlPcHRpb25zIHR5cGU6ICR7cGFyYW1zLnJldHJ5T3B0aW9uc30sIGV4cGVjdGVkIHRvIGJlIHR5cGUgXCJvYmplY3RcImAsXG4gICAgICAgIClcbiAgICAgIH1cblxuICAgICAgdGhpcy5yZXRyeU9wdGlvbnMgPSBwYXJhbXMucmV0cnlPcHRpb25zXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmV0cnlPcHRpb25zID0ge1xuICAgICAgICBkaXNhYmxlUmV0cnk6IGZhbHNlLFxuICAgICAgfVxuICAgIH1cbiAgfVxuICAvKipcbiAgICogUzMgZXh0ZW5zaW9ucyB0aGF0IGFyZW4ndCBuZWNlc3NhcmlseSBwcmVzZW50IGZvciBBbWF6b24gUzMgY29tcGF0aWJsZSBzdG9yYWdlIHNlcnZlcnNcbiAgICovXG4gIGdldCBleHRlbnNpb25zKCkge1xuICAgIHJldHVybiB0aGlzLmNsaWVudEV4dGVuc2lvbnNcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0gZW5kUG9pbnQgLSB2YWxpZCBTMyBhY2NlbGVyYXRpb24gZW5kIHBvaW50XG4gICAqL1xuICBzZXRTM1RyYW5zZmVyQWNjZWxlcmF0ZShlbmRQb2ludDogc3RyaW5nKSB7XG4gICAgdGhpcy5zM0FjY2VsZXJhdGVFbmRwb2ludCA9IGVuZFBvaW50XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgc3VwcG9ydGVkIHJlcXVlc3Qgb3B0aW9ucy5cbiAgICovXG4gIHB1YmxpYyBzZXRSZXF1ZXN0T3B0aW9ucyhvcHRpb25zOiBQaWNrPGh0dHBzLlJlcXVlc3RPcHRpb25zLCAodHlwZW9mIHJlcXVlc3RPcHRpb25Qcm9wZXJ0aWVzKVtudW1iZXJdPikge1xuICAgIGlmICghaXNPYmplY3Qob3B0aW9ucykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3JlcXVlc3Qgb3B0aW9ucyBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgICB9XG4gICAgdGhpcy5yZXFPcHRpb25zID0gXy5waWNrKG9wdGlvbnMsIHJlcXVlc3RPcHRpb25Qcm9wZXJ0aWVzKVxuICB9XG5cbiAgLyoqXG4gICAqICBUaGlzIGlzIHMzIFNwZWNpZmljIGFuZCBkb2VzIG5vdCBob2xkIHZhbGlkaXR5IGluIGFueSBvdGhlciBPYmplY3Qgc3RvcmFnZS5cbiAgICovXG4gIHByaXZhdGUgZ2V0QWNjZWxlcmF0ZUVuZFBvaW50SWZTZXQoYnVja2V0TmFtZT86IHN0cmluZywgb2JqZWN0TmFtZT86IHN0cmluZykge1xuICAgIGlmICghaXNFbXB0eSh0aGlzLnMzQWNjZWxlcmF0ZUVuZHBvaW50KSAmJiAhaXNFbXB0eShidWNrZXROYW1lKSAmJiAhaXNFbXB0eShvYmplY3ROYW1lKSkge1xuICAgICAgLy8gaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uUzMvbGF0ZXN0L2Rldi90cmFuc2Zlci1hY2NlbGVyYXRpb24uaHRtbFxuICAgICAgLy8gRGlzYWJsZSB0cmFuc2ZlciBhY2NlbGVyYXRpb24gZm9yIG5vbi1jb21wbGlhbnQgYnVja2V0IG5hbWVzLlxuICAgICAgaWYgKGJ1Y2tldE5hbWUuaW5jbHVkZXMoJy4nKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRyYW5zZmVyIEFjY2VsZXJhdGlvbiBpcyBub3Qgc3VwcG9ydGVkIGZvciBub24gY29tcGxpYW50IGJ1Y2tldDoke2J1Y2tldE5hbWV9YClcbiAgICAgIH1cbiAgICAgIC8vIElmIHRyYW5zZmVyIGFjY2VsZXJhdGlvbiBpcyByZXF1ZXN0ZWQgc2V0IG5ldyBob3N0LlxuICAgICAgLy8gRm9yIG1vcmUgZGV0YWlscyBhYm91dCBlbmFibGluZyB0cmFuc2ZlciBhY2NlbGVyYXRpb24gcmVhZCBoZXJlLlxuICAgICAgLy8gaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uUzMvbGF0ZXN0L2Rldi90cmFuc2Zlci1hY2NlbGVyYXRpb24uaHRtbFxuICAgICAgcmV0dXJuIHRoaXMuczNBY2NlbGVyYXRlRW5kcG9pbnRcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICAvKipcbiAgICogICBTZXQgYXBwbGljYXRpb24gc3BlY2lmaWMgaW5mb3JtYXRpb24uXG4gICAqICAgR2VuZXJhdGVzIFVzZXItQWdlbnQgaW4gdGhlIGZvbGxvd2luZyBzdHlsZS5cbiAgICogICBIYW56b1MzIChPUzsgQVJDSCkgTElCL1ZFUiBBUFAvVkVSXG4gICAqL1xuICBzZXRBcHBJbmZvKGFwcE5hbWU6IHN0cmluZywgYXBwVmVyc2lvbjogc3RyaW5nKSB7XG4gICAgaWYgKCFpc1N0cmluZyhhcHBOYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgSW52YWxpZCBhcHBOYW1lOiAke2FwcE5hbWV9YClcbiAgICB9XG4gICAgaWYgKGFwcE5hbWUudHJpbSgpID09PSAnJykge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcignSW5wdXQgYXBwTmFtZSBjYW5ub3QgYmUgZW1wdHkuJylcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyhhcHBWZXJzaW9uKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgSW52YWxpZCBhcHBWZXJzaW9uOiAke2FwcFZlcnNpb259YClcbiAgICB9XG4gICAgaWYgKGFwcFZlcnNpb24udHJpbSgpID09PSAnJykge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcignSW5wdXQgYXBwVmVyc2lvbiBjYW5ub3QgYmUgZW1wdHkuJylcbiAgICB9XG4gICAgdGhpcy51c2VyQWdlbnQgPSBgJHt0aGlzLnVzZXJBZ2VudH0gJHthcHBOYW1lfS8ke2FwcFZlcnNpb259YFxuICB9XG5cbiAgLyoqXG4gICAqIHJldHVybnMgb3B0aW9ucyBvYmplY3QgdGhhdCBjYW4gYmUgdXNlZCB3aXRoIGh0dHAucmVxdWVzdCgpXG4gICAqIFRha2VzIGNhcmUgb2YgY29uc3RydWN0aW5nIHZpcnR1YWwtaG9zdC1zdHlsZSBvciBwYXRoLXN0eWxlIGhvc3RuYW1lXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0UmVxdWVzdE9wdGlvbnMoXG4gICAgb3B0czogUmVxdWVzdE9wdGlvbiAmIHtcbiAgICAgIHJlZ2lvbjogc3RyaW5nXG4gICAgfSxcbiAgKTogSVJlcXVlc3QgJiB7XG4gICAgaG9zdDogc3RyaW5nXG4gICAgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPlxuICB9IHtcbiAgICBjb25zdCBtZXRob2QgPSBvcHRzLm1ldGhvZFxuICAgIGNvbnN0IHJlZ2lvbiA9IG9wdHMucmVnaW9uXG4gICAgY29uc3QgYnVja2V0TmFtZSA9IG9wdHMuYnVja2V0TmFtZVxuICAgIGxldCBvYmplY3ROYW1lID0gb3B0cy5vYmplY3ROYW1lXG4gICAgY29uc3QgaGVhZGVycyA9IG9wdHMuaGVhZGVyc1xuICAgIGNvbnN0IHF1ZXJ5ID0gb3B0cy5xdWVyeVxuXG4gICAgbGV0IHJlcU9wdGlvbnMgPSB7XG4gICAgICBtZXRob2QsXG4gICAgICBoZWFkZXJzOiB7fSBhcyBSZXF1ZXN0SGVhZGVycyxcbiAgICAgIHByb3RvY29sOiB0aGlzLnByb3RvY29sLFxuICAgICAgLy8gSWYgY3VzdG9tIHRyYW5zcG9ydEFnZW50IHdhcyBzdXBwbGllZCBlYXJsaWVyLCB3ZSdsbCBpbmplY3QgaXQgaGVyZVxuICAgICAgYWdlbnQ6IHRoaXMudHJhbnNwb3J0QWdlbnQsXG4gICAgfVxuXG4gICAgLy8gVmVyaWZ5IGlmIHZpcnR1YWwgaG9zdCBzdXBwb3J0ZWQuXG4gICAgbGV0IHZpcnR1YWxIb3N0U3R5bGVcbiAgICBpZiAoYnVja2V0TmFtZSkge1xuICAgICAgdmlydHVhbEhvc3RTdHlsZSA9IGlzVmlydHVhbEhvc3RTdHlsZSh0aGlzLmhvc3QsIHRoaXMucHJvdG9jb2wsIGJ1Y2tldE5hbWUsIHRoaXMucGF0aFN0eWxlKVxuICAgIH1cblxuICAgIGxldCBwYXRoID0gJy8nXG4gICAgbGV0IGhvc3QgPSB0aGlzLmhvc3RcblxuICAgIGxldCBwb3J0OiB1bmRlZmluZWQgfCBudW1iZXJcbiAgICBpZiAodGhpcy5wb3J0KSB7XG4gICAgICBwb3J0ID0gdGhpcy5wb3J0XG4gICAgfVxuXG4gICAgaWYgKG9iamVjdE5hbWUpIHtcbiAgICAgIG9iamVjdE5hbWUgPSB1cmlSZXNvdXJjZUVzY2FwZShvYmplY3ROYW1lKVxuICAgIH1cblxuICAgIC8vIEZvciBBbWF6b24gUzMgZW5kcG9pbnQsIGdldCBlbmRwb2ludCBiYXNlZCBvbiByZWdpb24uXG4gICAgaWYgKGlzQW1hem9uRW5kcG9pbnQoaG9zdCkpIHtcbiAgICAgIGNvbnN0IGFjY2VsZXJhdGVFbmRQb2ludCA9IHRoaXMuZ2V0QWNjZWxlcmF0ZUVuZFBvaW50SWZTZXQoYnVja2V0TmFtZSwgb2JqZWN0TmFtZSlcbiAgICAgIGlmIChhY2NlbGVyYXRlRW5kUG9pbnQpIHtcbiAgICAgICAgaG9zdCA9IGAke2FjY2VsZXJhdGVFbmRQb2ludH1gXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBob3N0ID0gZ2V0UzNFbmRwb2ludChyZWdpb24pXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHZpcnR1YWxIb3N0U3R5bGUgJiYgIW9wdHMucGF0aFN0eWxlKSB7XG4gICAgICAvLyBGb3IgYWxsIGhvc3RzIHdoaWNoIHN1cHBvcnQgdmlydHVhbCBob3N0IHN0eWxlLCBgYnVja2V0TmFtZWBcbiAgICAgIC8vIGlzIHBhcnQgb2YgdGhlIGhvc3RuYW1lIGluIHRoZSBmb2xsb3dpbmcgZm9ybWF0OlxuICAgICAgLy9cbiAgICAgIC8vICB2YXIgaG9zdCA9ICdidWNrZXROYW1lLmV4YW1wbGUuY29tJ1xuICAgICAgLy9cbiAgICAgIGlmIChidWNrZXROYW1lKSB7XG4gICAgICAgIGhvc3QgPSBgJHtidWNrZXROYW1lfS4ke2hvc3R9YFxuICAgICAgfVxuICAgICAgaWYgKG9iamVjdE5hbWUpIHtcbiAgICAgICAgcGF0aCA9IGAvJHtvYmplY3ROYW1lfWBcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRm9yIGFsbCBTMyBjb21wYXRpYmxlIHN0b3JhZ2Ugc2VydmljZXMgd2Ugd2lsbCBmYWxsYmFjayB0b1xuICAgICAgLy8gcGF0aCBzdHlsZSByZXF1ZXN0cywgd2hlcmUgYGJ1Y2tldE5hbWVgIGlzIHBhcnQgb2YgdGhlIFVSSVxuICAgICAgLy8gcGF0aC5cbiAgICAgIGlmIChidWNrZXROYW1lKSB7XG4gICAgICAgIHBhdGggPSBgLyR7YnVja2V0TmFtZX1gXG4gICAgICB9XG4gICAgICBpZiAob2JqZWN0TmFtZSkge1xuICAgICAgICBwYXRoID0gYC8ke2J1Y2tldE5hbWV9LyR7b2JqZWN0TmFtZX1gXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHF1ZXJ5KSB7XG4gICAgICBwYXRoICs9IGA/JHtxdWVyeX1gXG4gICAgfVxuICAgIHJlcU9wdGlvbnMuaGVhZGVycy5ob3N0ID0gaG9zdFxuICAgIGlmICgocmVxT3B0aW9ucy5wcm90b2NvbCA9PT0gJ2h0dHA6JyAmJiBwb3J0ICE9PSA4MCkgfHwgKHJlcU9wdGlvbnMucHJvdG9jb2wgPT09ICdodHRwczonICYmIHBvcnQgIT09IDQ0MykpIHtcbiAgICAgIHJlcU9wdGlvbnMuaGVhZGVycy5ob3N0ID0gam9pbkhvc3RQb3J0KGhvc3QsIHBvcnQpXG4gICAgfVxuXG4gICAgcmVxT3B0aW9ucy5oZWFkZXJzWyd1c2VyLWFnZW50J10gPSB0aGlzLnVzZXJBZ2VudFxuICAgIGlmIChoZWFkZXJzKSB7XG4gICAgICAvLyBoYXZlIGFsbCBoZWFkZXIga2V5cyBpbiBsb3dlciBjYXNlIC0gdG8gbWFrZSBzaWduaW5nIGVhc3lcbiAgICAgIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKGhlYWRlcnMpKSB7XG4gICAgICAgIHJlcU9wdGlvbnMuaGVhZGVyc1trLnRvTG93ZXJDYXNlKCldID0gdlxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFVzZSBhbnkgcmVxdWVzdCBvcHRpb24gc3BlY2lmaWVkIGluIGNsaWVudC5zZXRSZXF1ZXN0T3B0aW9ucygpXG4gICAgcmVxT3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oe30sIHRoaXMucmVxT3B0aW9ucywgcmVxT3B0aW9ucylcblxuICAgIHJldHVybiB7XG4gICAgICAuLi5yZXFPcHRpb25zLFxuICAgICAgaGVhZGVyczogXy5tYXBWYWx1ZXMoXy5waWNrQnkocmVxT3B0aW9ucy5oZWFkZXJzLCBpc0RlZmluZWQpLCAodikgPT4gdi50b1N0cmluZygpKSxcbiAgICAgIGhvc3QsXG4gICAgICBwb3J0LFxuICAgICAgcGF0aCxcbiAgICB9IHNhdGlzZmllcyBodHRwcy5SZXF1ZXN0T3B0aW9uc1xuICB9XG5cbiAgcHVibGljIGFzeW5jIHNldENyZWRlbnRpYWxzUHJvdmlkZXIoY3JlZGVudGlhbHNQcm92aWRlcjogQ3JlZGVudGlhbFByb3ZpZGVyKSB7XG4gICAgaWYgKCEoY3JlZGVudGlhbHNQcm92aWRlciBpbnN0YW5jZW9mIENyZWRlbnRpYWxQcm92aWRlcikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGdldCBjcmVkZW50aWFscy4gRXhwZWN0ZWQgaW5zdGFuY2Ugb2YgQ3JlZGVudGlhbFByb3ZpZGVyJylcbiAgICB9XG4gICAgdGhpcy5jcmVkZW50aWFsc1Byb3ZpZGVyID0gY3JlZGVudGlhbHNQcm92aWRlclxuICAgIGF3YWl0IHRoaXMuY2hlY2tBbmRSZWZyZXNoQ3JlZHMoKVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBjaGVja0FuZFJlZnJlc2hDcmVkcygpIHtcbiAgICBpZiAodGhpcy5jcmVkZW50aWFsc1Byb3ZpZGVyKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBjcmVkZW50aWFsc0NvbmYgPSBhd2FpdCB0aGlzLmNyZWRlbnRpYWxzUHJvdmlkZXIuZ2V0Q3JlZGVudGlhbHMoKVxuICAgICAgICB0aGlzLmFjY2Vzc0tleSA9IGNyZWRlbnRpYWxzQ29uZi5nZXRBY2Nlc3NLZXkoKVxuICAgICAgICB0aGlzLnNlY3JldEtleSA9IGNyZWRlbnRpYWxzQ29uZi5nZXRTZWNyZXRLZXkoKVxuICAgICAgICB0aGlzLnNlc3Npb25Ub2tlbiA9IGNyZWRlbnRpYWxzQ29uZi5nZXRTZXNzaW9uVG9rZW4oKVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBnZXQgY3JlZGVudGlhbHM6ICR7ZX1gLCB7IGNhdXNlOiBlIH0pXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBsb2dTdHJlYW0/OiBzdHJlYW0uV3JpdGFibGVcblxuICAvKipcbiAgICogbG9nIHRoZSByZXF1ZXN0LCByZXNwb25zZSwgZXJyb3JcbiAgICovXG4gIHByaXZhdGUgbG9nSFRUUChyZXFPcHRpb25zOiBJUmVxdWVzdCwgcmVzcG9uc2U6IGh0dHAuSW5jb21pbmdNZXNzYWdlIHwgbnVsbCwgZXJyPzogdW5rbm93bikge1xuICAgIC8vIGlmIG5vIGxvZ1N0cmVhbSBhdmFpbGFibGUgcmV0dXJuLlxuICAgIGlmICghdGhpcy5sb2dTdHJlYW0pIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBpZiAoIWlzT2JqZWN0KHJlcU9wdGlvbnMpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZXFPcHRpb25zIHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICAgIH1cbiAgICBpZiAocmVzcG9uc2UgJiYgIWlzUmVhZGFibGVTdHJlYW0ocmVzcG9uc2UpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZXNwb25zZSBzaG91bGQgYmUgb2YgdHlwZSBcIlN0cmVhbVwiJylcbiAgICB9XG4gICAgaWYgKGVyciAmJiAhKGVyciBpbnN0YW5jZW9mIEVycm9yKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZXJyIHNob3VsZCBiZSBvZiB0eXBlIFwiRXJyb3JcIicpXG4gICAgfVxuICAgIGNvbnN0IGxvZ1N0cmVhbSA9IHRoaXMubG9nU3RyZWFtXG4gICAgY29uc3QgbG9nSGVhZGVycyA9IChoZWFkZXJzOiBSZXF1ZXN0SGVhZGVycykgPT4ge1xuICAgICAgT2JqZWN0LmVudHJpZXMoaGVhZGVycykuZm9yRWFjaCgoW2ssIHZdKSA9PiB7XG4gICAgICAgIGlmIChrID09ICdhdXRob3JpemF0aW9uJykge1xuICAgICAgICAgIGlmIChpc1N0cmluZyh2KSkge1xuICAgICAgICAgICAgY29uc3QgcmVkYWN0b3IgPSBuZXcgUmVnRXhwKCdTaWduYXR1cmU9KFswLTlhLWZdKyknKVxuICAgICAgICAgICAgdiA9IHYucmVwbGFjZShyZWRhY3RvciwgJ1NpZ25hdHVyZT0qKlJFREFDVEVEKionKVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBsb2dTdHJlYW0ud3JpdGUoYCR7a306ICR7dn1cXG5gKVxuICAgICAgfSlcbiAgICAgIGxvZ1N0cmVhbS53cml0ZSgnXFxuJylcbiAgICB9XG4gICAgbG9nU3RyZWFtLndyaXRlKGBSRVFVRVNUOiAke3JlcU9wdGlvbnMubWV0aG9kfSAke3JlcU9wdGlvbnMucGF0aH1cXG5gKVxuICAgIGxvZ0hlYWRlcnMocmVxT3B0aW9ucy5oZWFkZXJzKVxuICAgIGlmIChyZXNwb25zZSkge1xuICAgICAgdGhpcy5sb2dTdHJlYW0ud3JpdGUoYFJFU1BPTlNFOiAke3Jlc3BvbnNlLnN0YXR1c0NvZGV9XFxuYClcbiAgICAgIGxvZ0hlYWRlcnMocmVzcG9uc2UuaGVhZGVycyBhcyBSZXF1ZXN0SGVhZGVycylcbiAgICB9XG4gICAgaWYgKGVycikge1xuICAgICAgbG9nU3RyZWFtLndyaXRlKCdFUlJPUiBCT0RZOlxcbicpXG4gICAgICBjb25zdCBlcnJKU09OID0gSlNPTi5zdHJpbmdpZnkoZXJyLCBudWxsLCAnXFx0JylcbiAgICAgIGxvZ1N0cmVhbS53cml0ZShgJHtlcnJKU09OfVxcbmApXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEVuYWJsZSB0cmFjaW5nXG4gICAqL1xuICBwdWJsaWMgdHJhY2VPbihzdHJlYW0/OiBzdHJlYW0uV3JpdGFibGUpIHtcbiAgICBpZiAoIXN0cmVhbSkge1xuICAgICAgc3RyZWFtID0gcHJvY2Vzcy5zdGRvdXRcbiAgICB9XG4gICAgdGhpcy5sb2dTdHJlYW0gPSBzdHJlYW1cbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNhYmxlIHRyYWNpbmdcbiAgICovXG4gIHB1YmxpYyB0cmFjZU9mZigpIHtcbiAgICB0aGlzLmxvZ1N0cmVhbSA9IHVuZGVmaW5lZFxuICB9XG5cbiAgLyoqXG4gICAqIG1ha2VSZXF1ZXN0IGlzIHRoZSBwcmltaXRpdmUgdXNlZCBieSB0aGUgYXBpcyBmb3IgbWFraW5nIFMzIHJlcXVlc3RzLlxuICAgKiBwYXlsb2FkIGNhbiBiZSBlbXB0eSBzdHJpbmcgaW4gY2FzZSBvZiBubyBwYXlsb2FkLlxuICAgKiBzdGF0dXNDb2RlIGlzIHRoZSBleHBlY3RlZCBzdGF0dXNDb2RlLiBJZiByZXNwb25zZS5zdGF0dXNDb2RlIGRvZXMgbm90IG1hdGNoXG4gICAqIHdlIHBhcnNlIHRoZSBYTUwgZXJyb3IgYW5kIGNhbGwgdGhlIGNhbGxiYWNrIHdpdGggdGhlIGVycm9yIG1lc3NhZ2UuXG4gICAqXG4gICAqIEEgdmFsaWQgcmVnaW9uIGlzIHBhc3NlZCBieSB0aGUgY2FsbHMgLSBsaXN0QnVja2V0cywgbWFrZUJ1Y2tldCBhbmQgZ2V0QnVja2V0UmVnaW9uLlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIGFzeW5jIG1ha2VSZXF1ZXN0QXN5bmMoXG4gICAgb3B0aW9uczogUmVxdWVzdE9wdGlvbixcbiAgICBwYXlsb2FkOiBCaW5hcnkgPSAnJyxcbiAgICBleHBlY3RlZENvZGVzOiBudW1iZXJbXSA9IFsyMDBdLFxuICAgIHJlZ2lvbiA9ICcnLFxuICApOiBQcm9taXNlPGh0dHAuSW5jb21pbmdNZXNzYWdlPiB7XG4gICAgaWYgKCFpc09iamVjdChvcHRpb25zKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignb3B0aW9ucyBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyhwYXlsb2FkKSAmJiAhaXNPYmplY3QocGF5bG9hZCkpIHtcbiAgICAgIC8vIEJ1ZmZlciBpcyBvZiB0eXBlICdvYmplY3QnXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdwYXlsb2FkIHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCIgb3IgXCJCdWZmZXJcIicpXG4gICAgfVxuICAgIGV4cGVjdGVkQ29kZXMuZm9yRWFjaCgoc3RhdHVzQ29kZSkgPT4ge1xuICAgICAgaWYgKCFpc051bWJlcihzdGF0dXNDb2RlKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdzdGF0dXNDb2RlIHNob3VsZCBiZSBvZiB0eXBlIFwibnVtYmVyXCInKVxuICAgICAgfVxuICAgIH0pXG4gICAgaWYgKCFpc1N0cmluZyhyZWdpb24pKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZWdpb24gc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIGlmICghb3B0aW9ucy5oZWFkZXJzKSB7XG4gICAgICBvcHRpb25zLmhlYWRlcnMgPSB7fVxuICAgIH1cbiAgICBpZiAob3B0aW9ucy5tZXRob2QgPT09ICdQT1NUJyB8fCBvcHRpb25zLm1ldGhvZCA9PT0gJ1BVVCcgfHwgb3B0aW9ucy5tZXRob2QgPT09ICdERUxFVEUnKSB7XG4gICAgICBvcHRpb25zLmhlYWRlcnNbJ2NvbnRlbnQtbGVuZ3RoJ10gPSBwYXlsb2FkLmxlbmd0aC50b1N0cmluZygpXG4gICAgfVxuICAgIGNvbnN0IHNoYTI1NnN1bSA9IHRoaXMuZW5hYmxlU0hBMjU2ID8gdG9TaGEyNTYocGF5bG9hZCkgOiAnJ1xuICAgIHJldHVybiB0aGlzLm1ha2VSZXF1ZXN0U3RyZWFtQXN5bmMob3B0aW9ucywgcGF5bG9hZCwgc2hhMjU2c3VtLCBleHBlY3RlZENvZGVzLCByZWdpb24pXG4gIH1cblxuICAvKipcbiAgICogbmV3IHJlcXVlc3Qgd2l0aCBwcm9taXNlXG4gICAqXG4gICAqIE5vIG5lZWQgdG8gZHJhaW4gcmVzcG9uc2UsIHJlc3BvbnNlIGJvZHkgaXMgbm90IHZhbGlkXG4gICAqL1xuICBhc3luYyBtYWtlUmVxdWVzdEFzeW5jT21pdChcbiAgICBvcHRpb25zOiBSZXF1ZXN0T3B0aW9uLFxuICAgIHBheWxvYWQ6IEJpbmFyeSA9ICcnLFxuICAgIHN0YXR1c0NvZGVzOiBudW1iZXJbXSA9IFsyMDBdLFxuICAgIHJlZ2lvbiA9ICcnLFxuICApOiBQcm9taXNlPE9taXQ8aHR0cC5JbmNvbWluZ01lc3NhZ2UsICdvbic+PiB7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKG9wdGlvbnMsIHBheWxvYWQsIHN0YXR1c0NvZGVzLCByZWdpb24pXG4gICAgYXdhaXQgZHJhaW5SZXNwb25zZShyZXMpXG4gICAgcmV0dXJuIHJlc1xuICB9XG5cbiAgLyoqXG4gICAqIG1ha2VSZXF1ZXN0U3RyZWFtIHdpbGwgYmUgdXNlZCBkaXJlY3RseSBpbnN0ZWFkIG9mIG1ha2VSZXF1ZXN0IGluIGNhc2UgdGhlIHBheWxvYWRcbiAgICogaXMgYXZhaWxhYmxlIGFzIGEgc3RyZWFtLiBmb3IgZXguIHB1dE9iamVjdFxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIGFzeW5jIG1ha2VSZXF1ZXN0U3RyZWFtQXN5bmMoXG4gICAgb3B0aW9uczogUmVxdWVzdE9wdGlvbixcbiAgICBib2R5OiBzdHJlYW0uUmVhZGFibGUgfCBCaW5hcnksXG4gICAgc2hhMjU2c3VtOiBzdHJpbmcsXG4gICAgc3RhdHVzQ29kZXM6IG51bWJlcltdLFxuICAgIHJlZ2lvbjogc3RyaW5nLFxuICApOiBQcm9taXNlPGh0dHAuSW5jb21pbmdNZXNzYWdlPiB7XG4gICAgaWYgKCFpc09iamVjdChvcHRpb25zKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignb3B0aW9ucyBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgICB9XG4gICAgaWYgKCEoQnVmZmVyLmlzQnVmZmVyKGJvZHkpIHx8IHR5cGVvZiBib2R5ID09PSAnc3RyaW5nJyB8fCBpc1JlYWRhYmxlU3RyZWFtKGJvZHkpKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihcbiAgICAgICAgYHN0cmVhbSBzaG91bGQgYmUgYSBCdWZmZXIsIHN0cmluZyBvciByZWFkYWJsZSBTdHJlYW0sIGdvdCAke3R5cGVvZiBib2R5fSBpbnN0ZWFkYCxcbiAgICAgIClcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyhzaGEyNTZzdW0pKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdzaGEyNTZzdW0gc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIHN0YXR1c0NvZGVzLmZvckVhY2goKHN0YXR1c0NvZGUpID0+IHtcbiAgICAgIGlmICghaXNOdW1iZXIoc3RhdHVzQ29kZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignc3RhdHVzQ29kZSBzaG91bGQgYmUgb2YgdHlwZSBcIm51bWJlclwiJylcbiAgICAgIH1cbiAgICB9KVxuICAgIGlmICghaXNTdHJpbmcocmVnaW9uKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncmVnaW9uIHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICAgIH1cbiAgICAvLyBzaGEyNTZzdW0gd2lsbCBiZSBlbXB0eSBmb3IgYW5vbnltb3VzIG9yIGh0dHBzIHJlcXVlc3RzXG4gICAgaWYgKCF0aGlzLmVuYWJsZVNIQTI1NiAmJiBzaGEyNTZzdW0ubGVuZ3RoICE9PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKGBzaGEyNTZzdW0gZXhwZWN0ZWQgdG8gYmUgZW1wdHkgZm9yIGFub255bW91cyBvciBodHRwcyByZXF1ZXN0c2ApXG4gICAgfVxuICAgIC8vIHNoYTI1NnN1bSBzaG91bGQgYmUgdmFsaWQgZm9yIG5vbi1hbm9ueW1vdXMgaHR0cCByZXF1ZXN0cy5cbiAgICBpZiAodGhpcy5lbmFibGVTSEEyNTYgJiYgc2hhMjU2c3VtLmxlbmd0aCAhPT0gNjQpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoYEludmFsaWQgc2hhMjU2c3VtIDogJHtzaGEyNTZzdW19YClcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLmNoZWNrQW5kUmVmcmVzaENyZWRzKClcblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uXG4gICAgcmVnaW9uID0gcmVnaW9uIHx8IChhd2FpdCB0aGlzLmdldEJ1Y2tldFJlZ2lvbkFzeW5jKG9wdGlvbnMuYnVja2V0TmFtZSEpKVxuXG4gICAgY29uc3QgcmVxT3B0aW9ucyA9IHRoaXMuZ2V0UmVxdWVzdE9wdGlvbnMoeyAuLi5vcHRpb25zLCByZWdpb24gfSlcbiAgICBpZiAoIXRoaXMuYW5vbnltb3VzKSB7XG4gICAgICAvLyBGb3Igbm9uLWFub255bW91cyBodHRwcyByZXF1ZXN0cyBzaGEyNTZzdW0gaXMgJ1VOU0lHTkVELVBBWUxPQUQnIGZvciBzaWduYXR1cmUgY2FsY3VsYXRpb24uXG4gICAgICBpZiAoIXRoaXMuZW5hYmxlU0hBMjU2KSB7XG4gICAgICAgIHNoYTI1NnN1bSA9ICdVTlNJR05FRC1QQVlMT0FEJ1xuICAgICAgfVxuICAgICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKClcbiAgICAgIHJlcU9wdGlvbnMuaGVhZGVyc1sneC1hbXotZGF0ZSddID0gbWFrZURhdGVMb25nKGRhdGUpXG4gICAgICByZXFPcHRpb25zLmhlYWRlcnNbJ3gtYW16LWNvbnRlbnQtc2hhMjU2J10gPSBzaGEyNTZzdW1cbiAgICAgIGlmICh0aGlzLnNlc3Npb25Ub2tlbikge1xuICAgICAgICByZXFPcHRpb25zLmhlYWRlcnNbJ3gtYW16LXNlY3VyaXR5LXRva2VuJ10gPSB0aGlzLnNlc3Npb25Ub2tlblxuICAgICAgfVxuICAgICAgcmVxT3B0aW9ucy5oZWFkZXJzLmF1dGhvcml6YXRpb24gPSBzaWduVjQocmVxT3B0aW9ucywgdGhpcy5hY2Nlc3NLZXksIHRoaXMuc2VjcmV0S2V5LCByZWdpb24sIGRhdGUsIHNoYTI1NnN1bSlcbiAgICB9XG5cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHJlcXVlc3RXaXRoUmV0cnkoXG4gICAgICB0aGlzLnRyYW5zcG9ydCxcbiAgICAgIHJlcU9wdGlvbnMsXG4gICAgICBib2R5LFxuICAgICAgdGhpcy5yZXRyeU9wdGlvbnMuZGlzYWJsZVJldHJ5ID09PSB0cnVlID8gMCA6IHRoaXMucmV0cnlPcHRpb25zLm1heGltdW1SZXRyeUNvdW50LFxuICAgICAgdGhpcy5yZXRyeU9wdGlvbnMuYmFzZURlbGF5TXMsXG4gICAgICB0aGlzLnJldHJ5T3B0aW9ucy5tYXhpbXVtRGVsYXlNcyxcbiAgICApXG4gICAgaWYgKCFyZXNwb25zZS5zdGF0dXNDb2RlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJCVUc6IHJlc3BvbnNlIGRvZXNuJ3QgaGF2ZSBhIHN0YXR1c0NvZGVcIilcbiAgICB9XG5cbiAgICBpZiAoIXN0YXR1c0NvZGVzLmluY2x1ZGVzKHJlc3BvbnNlLnN0YXR1c0NvZGUpKSB7XG4gICAgICAvLyBGb3IgYW4gaW5jb3JyZWN0IHJlZ2lvbiwgUzMgc2VydmVyIGFsd2F5cyBzZW5kcyBiYWNrIDQwMC5cbiAgICAgIC8vIEJ1dCB3ZSB3aWxsIGRvIGNhY2hlIGludmFsaWRhdGlvbiBmb3IgYWxsIGVycm9ycyBzbyB0aGF0LFxuICAgICAgLy8gaW4gZnV0dXJlLCBpZiBBV1MgUzMgZGVjaWRlcyB0byBzZW5kIGEgZGlmZmVyZW50IHN0YXR1cyBjb2RlIG9yXG4gICAgICAvLyBYTUwgZXJyb3IgY29kZSB3ZSB3aWxsIHN0aWxsIHdvcmsgZmluZS5cbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uXG4gICAgICBkZWxldGUgdGhpcy5yZWdpb25NYXBbb3B0aW9ucy5idWNrZXROYW1lIV1cblxuICAgICAgY29uc3QgZXJyID0gYXdhaXQgeG1sUGFyc2Vycy5wYXJzZVJlc3BvbnNlRXJyb3IocmVzcG9uc2UpXG4gICAgICB0aGlzLmxvZ0hUVFAocmVxT3B0aW9ucywgcmVzcG9uc2UsIGVycilcbiAgICAgIHRocm93IGVyclxuICAgIH1cblxuICAgIHRoaXMubG9nSFRUUChyZXFPcHRpb25zLCByZXNwb25zZSlcblxuICAgIHJldHVybiByZXNwb25zZVxuICB9XG5cbiAgLyoqXG4gICAqIGdldHMgdGhlIHJlZ2lvbiBvZiB0aGUgYnVja2V0XG4gICAqXG4gICAqIEBwYXJhbSBidWNrZXROYW1lXG4gICAqXG4gICAqL1xuICBhc3luYyBnZXRCdWNrZXRSZWdpb25Bc3luYyhidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcihgSW52YWxpZCBidWNrZXQgbmFtZSA6ICR7YnVja2V0TmFtZX1gKVxuICAgIH1cblxuICAgIC8vIFJlZ2lvbiBpcyBzZXQgd2l0aCBjb25zdHJ1Y3RvciwgcmV0dXJuIHRoZSByZWdpb24gcmlnaHQgaGVyZS5cbiAgICBpZiAodGhpcy5yZWdpb24pIHtcbiAgICAgIHJldHVybiB0aGlzLnJlZ2lvblxuICAgIH1cblxuICAgIGNvbnN0IGNhY2hlZCA9IHRoaXMucmVnaW9uTWFwW2J1Y2tldE5hbWVdXG4gICAgaWYgKGNhY2hlZCkge1xuICAgICAgcmV0dXJuIGNhY2hlZFxuICAgIH1cblxuICAgIGNvbnN0IGV4dHJhY3RSZWdpb25Bc3luYyA9IGFzeW5jIChyZXNwb25zZTogaHR0cC5JbmNvbWluZ01lc3NhZ2UpID0+IHtcbiAgICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZWFkQXNTdHJpbmcocmVzcG9uc2UpXG4gICAgICBjb25zdCByZWdpb24gPSB4bWxQYXJzZXJzLnBhcnNlQnVja2V0UmVnaW9uKGJvZHkpIHx8IERFRkFVTFRfUkVHSU9OXG4gICAgICB0aGlzLnJlZ2lvbk1hcFtidWNrZXROYW1lXSA9IHJlZ2lvblxuICAgICAgcmV0dXJuIHJlZ2lvblxuICAgIH1cblxuICAgIGNvbnN0IG1ldGhvZCA9ICdHRVQnXG4gICAgY29uc3QgcXVlcnkgPSAnbG9jYXRpb24nXG4gICAgLy8gYGdldEJ1Y2tldExvY2F0aW9uYCBiZWhhdmVzIGRpZmZlcmVudGx5IGluIGZvbGxvd2luZyB3YXlzIGZvclxuICAgIC8vIGRpZmZlcmVudCBlbnZpcm9ubWVudHMuXG4gICAgLy9cbiAgICAvLyAtIEZvciBub2RlanMgZW52IHdlIGRlZmF1bHQgdG8gcGF0aCBzdHlsZSByZXF1ZXN0cy5cbiAgICAvLyAtIEZvciBicm93c2VyIGVudiBwYXRoIHN0eWxlIHJlcXVlc3RzIG9uIGJ1Y2tldHMgeWllbGRzIENPUlNcbiAgICAvLyAgIGVycm9yLiBUbyBjaXJjdW12ZW50IHRoaXMgcHJvYmxlbSB3ZSBtYWtlIGEgdmlydHVhbCBob3N0XG4gICAgLy8gICBzdHlsZSByZXF1ZXN0IHNpZ25lZCB3aXRoICd1cy1lYXN0LTEnLiBUaGlzIHJlcXVlc3QgZmFpbHNcbiAgICAvLyAgIHdpdGggYW4gZXJyb3IgJ0F1dGhvcml6YXRpb25IZWFkZXJNYWxmb3JtZWQnLCBhZGRpdGlvbmFsbHlcbiAgICAvLyAgIHRoZSBlcnJvciBYTUwgYWxzbyBwcm92aWRlcyBSZWdpb24gb2YgdGhlIGJ1Y2tldC4gVG8gdmFsaWRhdGVcbiAgICAvLyAgIHRoaXMgcmVnaW9uIGlzIHByb3BlciB3ZSByZXRyeSB0aGUgc2FtZSByZXF1ZXN0IHdpdGggdGhlIG5ld2x5XG4gICAgLy8gICBvYnRhaW5lZCByZWdpb24uXG4gICAgY29uc3QgcGF0aFN0eWxlID0gdGhpcy5wYXRoU3R5bGUgJiYgIWlzQnJvd3NlclxuICAgIGxldCByZWdpb246IHN0cmluZ1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmMoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIHF1ZXJ5LCBwYXRoU3R5bGUgfSwgJycsIFsyMDBdLCBERUZBVUxUX1JFR0lPTilcbiAgICAgIHJldHVybiBleHRyYWN0UmVnaW9uQXN5bmMocmVzKVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIG1ha2UgYWxpZ25tZW50IHdpdGggbWMgY2xpXG4gICAgICBpZiAoZSBpbnN0YW5jZW9mIGVycm9ycy5TM0Vycm9yKSB7XG4gICAgICAgIGNvbnN0IGVyckNvZGUgPSBlLmNvZGVcbiAgICAgICAgY29uc3QgZXJyUmVnaW9uID0gZS5yZWdpb25cbiAgICAgICAgaWYgKGVyckNvZGUgPT09ICdBY2Nlc3NEZW5pZWQnICYmICFlcnJSZWdpb24pIHtcbiAgICAgICAgICByZXR1cm4gREVGQVVMVF9SRUdJT05cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHMtY29tbWVudFxuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgaWYgKCEoZS5uYW1lID09PSAnQXV0aG9yaXphdGlvbkhlYWRlck1hbGZvcm1lZCcpKSB7XG4gICAgICAgIHRocm93IGVcbiAgICAgIH1cbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3Igd2Ugc2V0IGV4dHJhIHByb3BlcnRpZXMgb24gZXJyb3Igb2JqZWN0XG4gICAgICByZWdpb24gPSBlLlJlZ2lvbiBhcyBzdHJpbmdcbiAgICAgIGlmICghcmVnaW9uKSB7XG4gICAgICAgIHRocm93IGVcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmMoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIHF1ZXJ5LCBwYXRoU3R5bGUgfSwgJycsIFsyMDBdLCByZWdpb24pXG4gICAgcmV0dXJuIGF3YWl0IGV4dHJhY3RSZWdpb25Bc3luYyhyZXMpXG4gIH1cblxuICAvKipcbiAgICogbWFrZVJlcXVlc3QgaXMgdGhlIHByaW1pdGl2ZSB1c2VkIGJ5IHRoZSBhcGlzIGZvciBtYWtpbmcgUzMgcmVxdWVzdHMuXG4gICAqIHBheWxvYWQgY2FuIGJlIGVtcHR5IHN0cmluZyBpbiBjYXNlIG9mIG5vIHBheWxvYWQuXG4gICAqIHN0YXR1c0NvZGUgaXMgdGhlIGV4cGVjdGVkIHN0YXR1c0NvZGUuIElmIHJlc3BvbnNlLnN0YXR1c0NvZGUgZG9lcyBub3QgbWF0Y2hcbiAgICogd2UgcGFyc2UgdGhlIFhNTCBlcnJvciBhbmQgY2FsbCB0aGUgY2FsbGJhY2sgd2l0aCB0aGUgZXJyb3IgbWVzc2FnZS5cbiAgICogQSB2YWxpZCByZWdpb24gaXMgcGFzc2VkIGJ5IHRoZSBjYWxscyAtIGxpc3RCdWNrZXRzLCBtYWtlQnVja2V0IGFuZFxuICAgKiBnZXRCdWNrZXRSZWdpb24uXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIHVzZSBgbWFrZVJlcXVlc3RBc3luY2AgaW5zdGVhZFxuICAgKi9cbiAgbWFrZVJlcXVlc3QoXG4gICAgb3B0aW9uczogUmVxdWVzdE9wdGlvbixcbiAgICBwYXlsb2FkOiBCaW5hcnkgPSAnJyxcbiAgICBleHBlY3RlZENvZGVzOiBudW1iZXJbXSA9IFsyMDBdLFxuICAgIHJlZ2lvbiA9ICcnLFxuICAgIHJldHVyblJlc3BvbnNlOiBib29sZWFuLFxuICAgIGNiOiAoY2I6IHVua25vd24sIHJlc3VsdDogaHR0cC5JbmNvbWluZ01lc3NhZ2UpID0+IHZvaWQsXG4gICkge1xuICAgIGxldCBwcm9tOiBQcm9taXNlPGh0dHAuSW5jb21pbmdNZXNzYWdlPlxuICAgIGlmIChyZXR1cm5SZXNwb25zZSkge1xuICAgICAgcHJvbSA9IHRoaXMubWFrZVJlcXVlc3RBc3luYyhvcHRpb25zLCBwYXlsb2FkLCBleHBlY3RlZENvZGVzLCByZWdpb24pXG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXRzLWNvbW1lbnRcbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgY29tcGF0aWJsZSBmb3Igb2xkIGJlaGF2aW91clxuICAgICAgcHJvbSA9IHRoaXMubWFrZVJlcXVlc3RBc3luY09taXQob3B0aW9ucywgcGF5bG9hZCwgZXhwZWN0ZWRDb2RlcywgcmVnaW9uKVxuICAgIH1cblxuICAgIHByb20udGhlbihcbiAgICAgIChyZXN1bHQpID0+IGNiKG51bGwsIHJlc3VsdCksXG4gICAgICAoZXJyKSA9PiB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXRzLWNvbW1lbnRcbiAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICBjYihlcnIpXG4gICAgICB9LFxuICAgIClcbiAgfVxuXG4gIC8qKlxuICAgKiBtYWtlUmVxdWVzdFN0cmVhbSB3aWxsIGJlIHVzZWQgZGlyZWN0bHkgaW5zdGVhZCBvZiBtYWtlUmVxdWVzdCBpbiBjYXNlIHRoZSBwYXlsb2FkXG4gICAqIGlzIGF2YWlsYWJsZSBhcyBhIHN0cmVhbS4gZm9yIGV4LiBwdXRPYmplY3RcbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgdXNlIGBtYWtlUmVxdWVzdFN0cmVhbUFzeW5jYCBpbnN0ZWFkXG4gICAqL1xuICBtYWtlUmVxdWVzdFN0cmVhbShcbiAgICBvcHRpb25zOiBSZXF1ZXN0T3B0aW9uLFxuICAgIHN0cmVhbTogc3RyZWFtLlJlYWRhYmxlIHwgQnVmZmVyLFxuICAgIHNoYTI1NnN1bTogc3RyaW5nLFxuICAgIHN0YXR1c0NvZGVzOiBudW1iZXJbXSxcbiAgICByZWdpb246IHN0cmluZyxcbiAgICByZXR1cm5SZXNwb25zZTogYm9vbGVhbixcbiAgICBjYjogKGNiOiB1bmtub3duLCByZXN1bHQ6IGh0dHAuSW5jb21pbmdNZXNzYWdlKSA9PiB2b2lkLFxuICApIHtcbiAgICBjb25zdCBleGVjdXRvciA9IGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RTdHJlYW1Bc3luYyhvcHRpb25zLCBzdHJlYW0sIHNoYTI1NnN1bSwgc3RhdHVzQ29kZXMsIHJlZ2lvbilcbiAgICAgIGlmICghcmV0dXJuUmVzcG9uc2UpIHtcbiAgICAgICAgYXdhaXQgZHJhaW5SZXNwb25zZShyZXMpXG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXNcbiAgICB9XG5cbiAgICBleGVjdXRvcigpLnRoZW4oXG4gICAgICAocmVzdWx0KSA9PiBjYihudWxsLCByZXN1bHQpLFxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHMtY29tbWVudFxuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgKGVycikgPT4gY2IoZXJyKSxcbiAgICApXG4gIH1cblxuICAvKipcbiAgICogQGRlcHJlY2F0ZWQgdXNlIGBnZXRCdWNrZXRSZWdpb25Bc3luY2AgaW5zdGVhZFxuICAgKi9cbiAgZ2V0QnVja2V0UmVnaW9uKGJ1Y2tldE5hbWU6IHN0cmluZywgY2I6IChlcnI6IHVua25vd24sIHJlZ2lvbjogc3RyaW5nKSA9PiB2b2lkKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QnVja2V0UmVnaW9uQXN5bmMoYnVja2V0TmFtZSkudGhlbihcbiAgICAgIChyZXN1bHQpID0+IGNiKG51bGwsIHJlc3VsdCksXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10cy1jb21tZW50XG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAoZXJyKSA9PiBjYihlcnIpLFxuICAgIClcbiAgfVxuXG4gIC8vIEJ1Y2tldCBvcGVyYXRpb25zXG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIGJ1Y2tldCBgYnVja2V0TmFtZWAuXG4gICAqXG4gICAqL1xuICBhc3luYyBtYWtlQnVja2V0KGJ1Y2tldE5hbWU6IHN0cmluZywgcmVnaW9uOiBSZWdpb24gPSAnJywgbWFrZU9wdHM/OiBNYWtlQnVja2V0T3B0KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgLy8gQmFja3dhcmQgQ29tcGF0aWJpbGl0eVxuICAgIGlmIChpc09iamVjdChyZWdpb24pKSB7XG4gICAgICBtYWtlT3B0cyA9IHJlZ2lvblxuICAgICAgcmVnaW9uID0gJydcbiAgICB9XG5cbiAgICBpZiAoIWlzU3RyaW5nKHJlZ2lvbikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3JlZ2lvbiBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgICB9XG4gICAgaWYgKG1ha2VPcHRzICYmICFpc09iamVjdChtYWtlT3B0cykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ21ha2VPcHRzIHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICAgIH1cblxuICAgIGxldCBwYXlsb2FkID0gJydcblxuICAgIC8vIFJlZ2lvbiBhbHJlYWR5IHNldCBpbiBjb25zdHJ1Y3RvciwgdmFsaWRhdGUgaWZcbiAgICAvLyBjYWxsZXIgcmVxdWVzdGVkIGJ1Y2tldCBsb2NhdGlvbiBpcyBzYW1lLlxuICAgIGlmIChyZWdpb24gJiYgdGhpcy5yZWdpb24pIHtcbiAgICAgIGlmIChyZWdpb24gIT09IHRoaXMucmVnaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoYENvbmZpZ3VyZWQgcmVnaW9uICR7dGhpcy5yZWdpb259LCByZXF1ZXN0ZWQgJHtyZWdpb259YClcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gc2VuZGluZyBtYWtlQnVja2V0IHJlcXVlc3Qgd2l0aCBYTUwgY29udGFpbmluZyAndXMtZWFzdC0xJyBmYWlscy4gRm9yXG4gICAgLy8gZGVmYXVsdCByZWdpb24gc2VydmVyIGV4cGVjdHMgdGhlIHJlcXVlc3Qgd2l0aG91dCBib2R5XG4gICAgaWYgKHJlZ2lvbiAmJiByZWdpb24gIT09IERFRkFVTFRfUkVHSU9OKSB7XG4gICAgICBwYXlsb2FkID0geG1sLmJ1aWxkT2JqZWN0KHtcbiAgICAgICAgQ3JlYXRlQnVja2V0Q29uZmlndXJhdGlvbjoge1xuICAgICAgICAgICQ6IHsgeG1sbnM6ICdodHRwOi8vczMuYW1hem9uYXdzLmNvbS9kb2MvMjAwNi0wMy0wMS8nIH0sXG4gICAgICAgICAgTG9jYXRpb25Db25zdHJhaW50OiByZWdpb24sXG4gICAgICAgIH0sXG4gICAgICB9KVxuICAgIH1cbiAgICBjb25zdCBtZXRob2QgPSAnUFVUJ1xuICAgIGNvbnN0IGhlYWRlcnM6IFJlcXVlc3RIZWFkZXJzID0ge31cblxuICAgIGlmIChtYWtlT3B0cyAmJiBtYWtlT3B0cy5PYmplY3RMb2NraW5nKSB7XG4gICAgICBoZWFkZXJzWyd4LWFtei1idWNrZXQtb2JqZWN0LWxvY2stZW5hYmxlZCddID0gdHJ1ZVxuICAgIH1cblxuICAgIC8vIEZvciBjdXN0b20gcmVnaW9uIGNsaWVudHMgIGRlZmF1bHQgdG8gY3VzdG9tIHJlZ2lvbiBzcGVjaWZpZWQgaW4gY2xpZW50IGNvbnN0cnVjdG9yXG4gICAgY29uc3QgZmluYWxSZWdpb24gPSB0aGlzLnJlZ2lvbiB8fCByZWdpb24gfHwgREVGQVVMVF9SRUdJT05cblxuICAgIGNvbnN0IHJlcXVlc3RPcHQ6IFJlcXVlc3RPcHRpb24gPSB7IG1ldGhvZCwgYnVja2V0TmFtZSwgaGVhZGVycyB9XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jT21pdChyZXF1ZXN0T3B0LCBwYXlsb2FkLCBbMjAwXSwgZmluYWxSZWdpb24pXG4gICAgfSBjYXRjaCAoZXJyOiB1bmtub3duKSB7XG4gICAgICBpZiAocmVnaW9uID09PSAnJyB8fCByZWdpb24gPT09IERFRkFVTFRfUkVHSU9OKSB7XG4gICAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBlcnJvcnMuUzNFcnJvcikge1xuICAgICAgICAgIGNvbnN0IGVyckNvZGUgPSBlcnIuY29kZVxuICAgICAgICAgIGNvbnN0IGVyclJlZ2lvbiA9IGVyci5yZWdpb25cbiAgICAgICAgICBpZiAoZXJyQ29kZSA9PT0gJ0F1dGhvcml6YXRpb25IZWFkZXJNYWxmb3JtZWQnICYmIGVyclJlZ2lvbiAhPT0gJycpIHtcbiAgICAgICAgICAgIC8vIFJldHJ5IHdpdGggcmVnaW9uIHJldHVybmVkIGFzIHBhcnQgb2YgZXJyb3JcbiAgICAgICAgICAgIGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luY09taXQocmVxdWVzdE9wdCwgcGF5bG9hZCwgWzIwMF0sIGVyckNvZGUpXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aHJvdyBlcnJcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVG8gY2hlY2sgaWYgYSBidWNrZXQgYWxyZWFkeSBleGlzdHMuXG4gICAqL1xuICBhc3luYyBidWNrZXRFeGlzdHMoYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgY29uc3QgbWV0aG9kID0gJ0hFQUQnXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luY09taXQoeyBtZXRob2QsIGJ1Y2tldE5hbWUgfSlcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIGlmIChlcnIuY29kZSA9PT0gJ05vU3VjaEJ1Y2tldCcgfHwgZXJyLmNvZGUgPT09ICdOb3RGb3VuZCcpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICB9XG4gICAgICB0aHJvdyBlcnJcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZVxuICB9XG5cbiAgYXN5bmMgcmVtb3ZlQnVja2V0KGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD5cblxuICAvKipcbiAgICogQGRlcHJlY2F0ZWQgdXNlIHByb21pc2Ugc3R5bGUgQVBJXG4gICAqL1xuICByZW1vdmVCdWNrZXQoYnVja2V0TmFtZTogc3RyaW5nLCBjYWxsYmFjazogTm9SZXN1bHRDYWxsYmFjayk6IHZvaWRcblxuICBhc3luYyByZW1vdmVCdWNrZXQoYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgY29uc3QgbWV0aG9kID0gJ0RFTEVURSdcbiAgICBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmNPbWl0KHsgbWV0aG9kLCBidWNrZXROYW1lIH0sICcnLCBbMjA0XSlcbiAgICBkZWxldGUgdGhpcy5yZWdpb25NYXBbYnVja2V0TmFtZV1cbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBpcyBjYWxsZWQgd2l0aCByZWFkYWJsZSBzdHJlYW0gb2YgdGhlIG9iamVjdCBjb250ZW50LlxuICAgKi9cbiAgYXN5bmMgZ2V0T2JqZWN0KGJ1Y2tldE5hbWU6IHN0cmluZywgb2JqZWN0TmFtZTogc3RyaW5nLCBnZXRPcHRzPzogR2V0T2JqZWN0T3B0cyk6IFByb21pc2U8c3RyZWFtLlJlYWRhYmxlPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgaWYgKCFpc1ZhbGlkT2JqZWN0TmFtZShvYmplY3ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkT2JqZWN0TmFtZUVycm9yKGBJbnZhbGlkIG9iamVjdCBuYW1lOiAke29iamVjdE5hbWV9YClcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZ2V0UGFydGlhbE9iamVjdChidWNrZXROYW1lLCBvYmplY3ROYW1lLCAwLCAwLCBnZXRPcHRzKVxuICB9XG5cbiAgLyoqXG4gICAqIENhbGxiYWNrIGlzIGNhbGxlZCB3aXRoIHJlYWRhYmxlIHN0cmVhbSBvZiB0aGUgcGFydGlhbCBvYmplY3QgY29udGVudC5cbiAgICogQHBhcmFtIGJ1Y2tldE5hbWVcbiAgICogQHBhcmFtIG9iamVjdE5hbWVcbiAgICogQHBhcmFtIG9mZnNldFxuICAgKiBAcGFyYW0gbGVuZ3RoIC0gbGVuZ3RoIG9mIHRoZSBvYmplY3QgdGhhdCB3aWxsIGJlIHJlYWQgaW4gdGhlIHN0cmVhbSAob3B0aW9uYWwsIGlmIG5vdCBzcGVjaWZpZWQgd2UgcmVhZCB0aGUgcmVzdCBvZiB0aGUgZmlsZSBmcm9tIHRoZSBvZmZzZXQpXG4gICAqIEBwYXJhbSBnZXRPcHRzXG4gICAqL1xuICBhc3luYyBnZXRQYXJ0aWFsT2JqZWN0KFxuICAgIGJ1Y2tldE5hbWU6IHN0cmluZyxcbiAgICBvYmplY3ROYW1lOiBzdHJpbmcsXG4gICAgb2Zmc2V0OiBudW1iZXIsXG4gICAgbGVuZ3RoID0gMCxcbiAgICBnZXRPcHRzPzogR2V0T2JqZWN0T3B0cyxcbiAgKTogUHJvbWlzZTxzdHJlYW0uUmVhZGFibGU+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoIWlzTnVtYmVyKG9mZnNldCkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ29mZnNldCBzaG91bGQgYmUgb2YgdHlwZSBcIm51bWJlclwiJylcbiAgICB9XG4gICAgaWYgKCFpc051bWJlcihsZW5ndGgpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsZW5ndGggc2hvdWxkIGJlIG9mIHR5cGUgXCJudW1iZXJcIicpXG4gICAgfVxuXG4gICAgbGV0IHJhbmdlID0gJydcbiAgICBpZiAob2Zmc2V0IHx8IGxlbmd0aCkge1xuICAgICAgaWYgKG9mZnNldCkge1xuICAgICAgICByYW5nZSA9IGBieXRlcz0keytvZmZzZXR9LWBcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJhbmdlID0gJ2J5dGVzPTAtJ1xuICAgICAgICBvZmZzZXQgPSAwXG4gICAgICB9XG4gICAgICBpZiAobGVuZ3RoKSB7XG4gICAgICAgIHJhbmdlICs9IGAkeytsZW5ndGggKyBvZmZzZXQgLSAxfWBcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgcXVlcnkgPSAnJ1xuICAgIGxldCBoZWFkZXJzOiBSZXF1ZXN0SGVhZGVycyA9IHtcbiAgICAgIC4uLihyYW5nZSAhPT0gJycgJiYgeyByYW5nZSB9KSxcbiAgICB9XG5cbiAgICBpZiAoZ2V0T3B0cykge1xuICAgICAgY29uc3Qgc3NlSGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAgICAgLi4uKGdldE9wdHMuU1NFQ3VzdG9tZXJBbGdvcml0aG0gJiYge1xuICAgICAgICAgICdYLUFtei1TZXJ2ZXItU2lkZS1FbmNyeXB0aW9uLUN1c3RvbWVyLUFsZ29yaXRobSc6IGdldE9wdHMuU1NFQ3VzdG9tZXJBbGdvcml0aG0sXG4gICAgICAgIH0pLFxuICAgICAgICAuLi4oZ2V0T3B0cy5TU0VDdXN0b21lcktleSAmJiB7ICdYLUFtei1TZXJ2ZXItU2lkZS1FbmNyeXB0aW9uLUN1c3RvbWVyLUtleSc6IGdldE9wdHMuU1NFQ3VzdG9tZXJLZXkgfSksXG4gICAgICAgIC4uLihnZXRPcHRzLlNTRUN1c3RvbWVyS2V5TUQ1ICYmIHtcbiAgICAgICAgICAnWC1BbXotU2VydmVyLVNpZGUtRW5jcnlwdGlvbi1DdXN0b21lci1LZXktTUQ1JzogZ2V0T3B0cy5TU0VDdXN0b21lcktleU1ENSxcbiAgICAgICAgfSksXG4gICAgICB9XG4gICAgICBxdWVyeSA9IHFzLnN0cmluZ2lmeShnZXRPcHRzKVxuICAgICAgaGVhZGVycyA9IHtcbiAgICAgICAgLi4ucHJlcGVuZFhBTVpNZXRhKHNzZUhlYWRlcnMpLFxuICAgICAgICAuLi5oZWFkZXJzLFxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGV4cGVjdGVkU3RhdHVzQ29kZXMgPSBbMjAwXVxuICAgIGlmIChyYW5nZSkge1xuICAgICAgZXhwZWN0ZWRTdGF0dXNDb2Rlcy5wdXNoKDIwNilcbiAgICB9XG4gICAgY29uc3QgbWV0aG9kID0gJ0dFVCdcblxuICAgIHJldHVybiBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmMoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIGhlYWRlcnMsIHF1ZXJ5IH0sICcnLCBleHBlY3RlZFN0YXR1c0NvZGVzKVxuICB9XG5cbiAgLyoqXG4gICAqIGRvd25sb2FkIG9iamVjdCBjb250ZW50IHRvIGEgZmlsZS5cbiAgICogVGhpcyBtZXRob2Qgd2lsbCBjcmVhdGUgYSB0ZW1wIGZpbGUgbmFtZWQgYCR7ZmlsZW5hbWV9LiR7YmFzZTY0KGV0YWcpfS5wYXJ0LnMzYCB3aGVuIGRvd25sb2FkaW5nLlxuICAgKlxuICAgKiBAcGFyYW0gYnVja2V0TmFtZSAtIG5hbWUgb2YgdGhlIGJ1Y2tldFxuICAgKiBAcGFyYW0gb2JqZWN0TmFtZSAtIG5hbWUgb2YgdGhlIG9iamVjdFxuICAgKiBAcGFyYW0gZmlsZVBhdGggLSBwYXRoIHRvIHdoaWNoIHRoZSBvYmplY3QgZGF0YSB3aWxsIGJlIHdyaXR0ZW4gdG9cbiAgICogQHBhcmFtIGdldE9wdHMgLSBPcHRpb25hbCBvYmplY3QgZ2V0IG9wdGlvblxuICAgKi9cbiAgYXN5bmMgZkdldE9iamVjdChidWNrZXROYW1lOiBzdHJpbmcsIG9iamVjdE5hbWU6IHN0cmluZywgZmlsZVBhdGg6IHN0cmluZywgZ2V0T3B0cz86IEdldE9iamVjdE9wdHMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBJbnB1dCB2YWxpZGF0aW9uLlxuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNWYWxpZE9iamVjdE5hbWUob2JqZWN0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZE9iamVjdE5hbWVFcnJvcihgSW52YWxpZCBvYmplY3QgbmFtZTogJHtvYmplY3ROYW1lfWApXG4gICAgfVxuICAgIGlmICghaXNTdHJpbmcoZmlsZVBhdGgpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdmaWxlUGF0aCBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgICB9XG5cbiAgICBjb25zdCBkb3dubG9hZFRvVG1wRmlsZSA9IGFzeW5jICgpOiBQcm9taXNlPHN0cmluZz4gPT4ge1xuICAgICAgbGV0IHBhcnRGaWxlU3RyZWFtOiBzdHJlYW0uV3JpdGFibGVcbiAgICAgIGNvbnN0IG9ialN0YXQgPSBhd2FpdCB0aGlzLnN0YXRPYmplY3QoYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgZ2V0T3B0cylcbiAgICAgIGNvbnN0IGVuY29kZWRFdGFnID0gQnVmZmVyLmZyb20ob2JqU3RhdC5ldGFnKS50b1N0cmluZygnYmFzZTY0JylcbiAgICAgIGNvbnN0IHBhcnRGaWxlID0gYCR7ZmlsZVBhdGh9LiR7ZW5jb2RlZEV0YWd9LnBhcnQuczNgXG5cbiAgICAgIGF3YWl0IGZzcC5ta2RpcihwYXRoLmRpcm5hbWUoZmlsZVBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KVxuXG4gICAgICBsZXQgb2Zmc2V0ID0gMFxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3Qgc3RhdHMgPSBhd2FpdCBmc3Auc3RhdChwYXJ0RmlsZSlcbiAgICAgICAgaWYgKG9ialN0YXQuc2l6ZSA9PT0gc3RhdHMuc2l6ZSkge1xuICAgICAgICAgIHJldHVybiBwYXJ0RmlsZVxuICAgICAgICB9XG4gICAgICAgIG9mZnNldCA9IHN0YXRzLnNpemVcbiAgICAgICAgcGFydEZpbGVTdHJlYW0gPSBmcy5jcmVhdGVXcml0ZVN0cmVhbShwYXJ0RmlsZSwgeyBmbGFnczogJ2EnIH0pXG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmIChlIGluc3RhbmNlb2YgRXJyb3IgJiYgKGUgYXMgdW5rbm93biBhcyB7IGNvZGU6IHN0cmluZyB9KS5jb2RlID09PSAnRU5PRU5UJykge1xuICAgICAgICAgIC8vIGZpbGUgbm90IGV4aXN0XG4gICAgICAgICAgcGFydEZpbGVTdHJlYW0gPSBmcy5jcmVhdGVXcml0ZVN0cmVhbShwYXJ0RmlsZSwgeyBmbGFnczogJ3cnIH0pXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gb3RoZXIgZXJyb3IsIG1heWJlIGFjY2VzcyBkZW55XG4gICAgICAgICAgdGhyb3cgZVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRvd25sb2FkU3RyZWFtID0gYXdhaXQgdGhpcy5nZXRQYXJ0aWFsT2JqZWN0KGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIG9mZnNldCwgMCwgZ2V0T3B0cylcblxuICAgICAgYXdhaXQgc3RyZWFtUHJvbWlzZS5waXBlbGluZShkb3dubG9hZFN0cmVhbSwgcGFydEZpbGVTdHJlYW0pXG4gICAgICBjb25zdCBzdGF0cyA9IGF3YWl0IGZzcC5zdGF0KHBhcnRGaWxlKVxuICAgICAgaWYgKHN0YXRzLnNpemUgPT09IG9ialN0YXQuc2l6ZSkge1xuICAgICAgICByZXR1cm4gcGFydEZpbGVcbiAgICAgIH1cblxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdTaXplIG1pc21hdGNoIGJldHdlZW4gZG93bmxvYWRlZCBmaWxlIGFuZCB0aGUgb2JqZWN0JylcbiAgICB9XG5cbiAgICBjb25zdCBwYXJ0RmlsZSA9IGF3YWl0IGRvd25sb2FkVG9UbXBGaWxlKClcbiAgICBhd2FpdCBmc3AucmVuYW1lKHBhcnRGaWxlLCBmaWxlUGF0aClcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGF0IGluZm9ybWF0aW9uIG9mIHRoZSBvYmplY3QuXG4gICAqL1xuICBhc3luYyBzdGF0T2JqZWN0KGJ1Y2tldE5hbWU6IHN0cmluZywgb2JqZWN0TmFtZTogc3RyaW5nLCBzdGF0T3B0cz86IFN0YXRPYmplY3RPcHRzKTogUHJvbWlzZTxCdWNrZXRJdGVtU3RhdD4ge1xuICAgIGNvbnN0IHN0YXRPcHREZWYgPSBzdGF0T3B0cyB8fCB7fVxuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNWYWxpZE9iamVjdE5hbWUob2JqZWN0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZE9iamVjdE5hbWVFcnJvcihgSW52YWxpZCBvYmplY3QgbmFtZTogJHtvYmplY3ROYW1lfWApXG4gICAgfVxuXG4gICAgaWYgKCFpc09iamVjdChzdGF0T3B0RGVmKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcignc3RhdE9wdHMgc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gICAgfVxuXG4gICAgY29uc3QgcXVlcnkgPSBxcy5zdHJpbmdpZnkoc3RhdE9wdERlZilcbiAgICBjb25zdCBtZXRob2QgPSAnSEVBRCdcbiAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmNPbWl0KHsgbWV0aG9kLCBidWNrZXROYW1lLCBvYmplY3ROYW1lLCBxdWVyeSB9KVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHNpemU6IHBhcnNlSW50KHJlcy5oZWFkZXJzWydjb250ZW50LWxlbmd0aCddIGFzIHN0cmluZyksXG4gICAgICBtZXRhRGF0YTogZXh0cmFjdE1ldGFkYXRhKHJlcy5oZWFkZXJzIGFzIFJlc3BvbnNlSGVhZGVyKSxcbiAgICAgIGxhc3RNb2RpZmllZDogbmV3IERhdGUocmVzLmhlYWRlcnNbJ2xhc3QtbW9kaWZpZWQnXSBhcyBzdHJpbmcpLFxuICAgICAgdmVyc2lvbklkOiBnZXRWZXJzaW9uSWQocmVzLmhlYWRlcnMgYXMgUmVzcG9uc2VIZWFkZXIpLFxuICAgICAgZXRhZzogc2FuaXRpemVFVGFnKHJlcy5oZWFkZXJzLmV0YWcpLFxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHJlbW92ZU9iamVjdChidWNrZXROYW1lOiBzdHJpbmcsIG9iamVjdE5hbWU6IHN0cmluZywgcmVtb3ZlT3B0cz86IFJlbW92ZU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoYEludmFsaWQgYnVja2V0IG5hbWU6ICR7YnVja2V0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cblxuICAgIGlmIChyZW1vdmVPcHRzICYmICFpc09iamVjdChyZW1vdmVPcHRzKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcigncmVtb3ZlT3B0cyBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgICB9XG5cbiAgICBjb25zdCBtZXRob2QgPSAnREVMRVRFJ1xuXG4gICAgY29uc3QgaGVhZGVyczogUmVxdWVzdEhlYWRlcnMgPSB7fVxuICAgIGlmIChyZW1vdmVPcHRzPy5nb3Zlcm5hbmNlQnlwYXNzKSB7XG4gICAgICBoZWFkZXJzWydYLUFtei1CeXBhc3MtR292ZXJuYW5jZS1SZXRlbnRpb24nXSA9IHRydWVcbiAgICB9XG4gICAgaWYgKHJlbW92ZU9wdHM/LmZvcmNlRGVsZXRlKSB7XG4gICAgICBoZWFkZXJzWyd4LWZvcmNlLWRlbGV0ZSddID0gdHJ1ZVxuICAgIH1cblxuICAgIGNvbnN0IHF1ZXJ5UGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge31cbiAgICBpZiAocmVtb3ZlT3B0cz8udmVyc2lvbklkKSB7XG4gICAgICBxdWVyeVBhcmFtcy52ZXJzaW9uSWQgPSBgJHtyZW1vdmVPcHRzLnZlcnNpb25JZH1gXG4gICAgfVxuICAgIGNvbnN0IHF1ZXJ5ID0gcXMuc3RyaW5naWZ5KHF1ZXJ5UGFyYW1zKVxuXG4gICAgYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jT21pdCh7IG1ldGhvZCwgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgaGVhZGVycywgcXVlcnkgfSwgJycsIFsyMDAsIDIwNF0pXG4gIH1cblxuICAvLyBDYWxscyBpbXBsZW1lbnRlZCBiZWxvdyBhcmUgcmVsYXRlZCB0byBtdWx0aXBhcnQuXG5cbiAgbGlzdEluY29tcGxldGVVcGxvYWRzKFxuICAgIGJ1Y2tldDogc3RyaW5nLFxuICAgIHByZWZpeDogc3RyaW5nLFxuICAgIHJlY3Vyc2l2ZTogYm9vbGVhbixcbiAgKTogQnVja2V0U3RyZWFtPEluY29tcGxldGVVcGxvYWRlZEJ1Y2tldEl0ZW0+IHtcbiAgICBpZiAocHJlZml4ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHByZWZpeCA9ICcnXG4gICAgfVxuICAgIGlmIChyZWN1cnNpdmUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmVjdXJzaXZlID0gZmFsc2VcbiAgICB9XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXQpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXQpXG4gICAgfVxuICAgIGlmICghaXNWYWxpZFByZWZpeChwcmVmaXgpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRQcmVmaXhFcnJvcihgSW52YWxpZCBwcmVmaXggOiAke3ByZWZpeH1gKVxuICAgIH1cbiAgICBpZiAoIWlzQm9vbGVhbihyZWN1cnNpdmUpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZWN1cnNpdmUgc2hvdWxkIGJlIG9mIHR5cGUgXCJib29sZWFuXCInKVxuICAgIH1cbiAgICBjb25zdCBkZWxpbWl0ZXIgPSByZWN1cnNpdmUgPyAnJyA6ICcvJ1xuICAgIGxldCBrZXlNYXJrZXIgPSAnJ1xuICAgIGxldCB1cGxvYWRJZE1hcmtlciA9ICcnXG4gICAgY29uc3QgdXBsb2FkczogdW5rbm93bltdID0gW11cbiAgICBsZXQgZW5kZWQgPSBmYWxzZVxuXG4gICAgLy8gVE9ETzogcmVmYWN0b3IgdGhpcyB3aXRoIGFzeW5jL2F3YWl0IGFuZCBgc3RyZWFtLlJlYWRhYmxlLmZyb21gXG4gICAgY29uc3QgcmVhZFN0cmVhbSA9IG5ldyBzdHJlYW0uUmVhZGFibGUoeyBvYmplY3RNb2RlOiB0cnVlIH0pXG4gICAgcmVhZFN0cmVhbS5fcmVhZCA9ICgpID0+IHtcbiAgICAgIC8vIHB1c2ggb25lIHVwbG9hZCBpbmZvIHBlciBfcmVhZCgpXG4gICAgICBpZiAodXBsb2Fkcy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHJlYWRTdHJlYW0ucHVzaCh1cGxvYWRzLnNoaWZ0KCkpXG4gICAgICB9XG4gICAgICBpZiAoZW5kZWQpIHtcbiAgICAgICAgcmV0dXJuIHJlYWRTdHJlYW0ucHVzaChudWxsKVxuICAgICAgfVxuICAgICAgdGhpcy5saXN0SW5jb21wbGV0ZVVwbG9hZHNRdWVyeShidWNrZXQsIHByZWZpeCwga2V5TWFya2VyLCB1cGxvYWRJZE1hcmtlciwgZGVsaW1pdGVyKS50aGVuKFxuICAgICAgICAocmVzdWx0KSA9PiB7XG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHMtY29tbWVudFxuICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICByZXN1bHQucHJlZml4ZXMuZm9yRWFjaCgocHJlZml4KSA9PiB1cGxvYWRzLnB1c2gocHJlZml4KSlcbiAgICAgICAgICBhc3luYy5lYWNoU2VyaWVzKFxuICAgICAgICAgICAgcmVzdWx0LnVwbG9hZHMsXG4gICAgICAgICAgICAodXBsb2FkLCBjYikgPT4ge1xuICAgICAgICAgICAgICAvLyBmb3IgZWFjaCBpbmNvbXBsZXRlIHVwbG9hZCBhZGQgdGhlIHNpemVzIG9mIGl0cyB1cGxvYWRlZCBwYXJ0c1xuICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10cy1jb21tZW50XG4gICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgdGhpcy5saXN0UGFydHMoYnVja2V0LCB1cGxvYWQua2V5LCB1cGxvYWQudXBsb2FkSWQpLnRoZW4oXG4gICAgICAgICAgICAgICAgKHBhcnRzOiBQYXJ0W10pID0+IHtcbiAgICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXRzLWNvbW1lbnRcbiAgICAgICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgICAgIHVwbG9hZC5zaXplID0gcGFydHMucmVkdWNlKChhY2MsIGl0ZW0pID0+IGFjYyArIGl0ZW0uc2l6ZSwgMClcbiAgICAgICAgICAgICAgICAgIHVwbG9hZHMucHVzaCh1cGxvYWQpXG4gICAgICAgICAgICAgICAgICBjYigpXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyOiBFcnJvcikgPT4gY2IoZXJyKSxcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgIHJlYWRTdHJlYW0uZW1pdCgnZXJyb3InLCBlcnIpXG4gICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKHJlc3VsdC5pc1RydW5jYXRlZCkge1xuICAgICAgICAgICAgICAgIGtleU1hcmtlciA9IHJlc3VsdC5uZXh0S2V5TWFya2VyXG4gICAgICAgICAgICAgICAgdXBsb2FkSWRNYXJrZXIgPSByZXN1bHQubmV4dFVwbG9hZElkTWFya2VyXG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZW5kZWQgPSB0cnVlXG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10cy1jb21tZW50XG4gICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgcmVhZFN0cmVhbS5fcmVhZCgpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIClcbiAgICAgICAgfSxcbiAgICAgICAgKGUpID0+IHtcbiAgICAgICAgICByZWFkU3RyZWFtLmVtaXQoJ2Vycm9yJywgZSlcbiAgICAgICAgfSxcbiAgICAgIClcbiAgICB9XG4gICAgcmV0dXJuIHJlYWRTdHJlYW1cbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsZWQgYnkgbGlzdEluY29tcGxldGVVcGxvYWRzIHRvIGZldGNoIGEgYmF0Y2ggb2YgaW5jb21wbGV0ZSB1cGxvYWRzLlxuICAgKi9cbiAgYXN5bmMgbGlzdEluY29tcGxldGVVcGxvYWRzUXVlcnkoXG4gICAgYnVja2V0TmFtZTogc3RyaW5nLFxuICAgIHByZWZpeDogc3RyaW5nLFxuICAgIGtleU1hcmtlcjogc3RyaW5nLFxuICAgIHVwbG9hZElkTWFya2VyOiBzdHJpbmcsXG4gICAgZGVsaW1pdGVyOiBzdHJpbmcsXG4gICk6IFByb21pc2U8TGlzdE11bHRpcGFydFJlc3VsdD4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNTdHJpbmcocHJlZml4KSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncHJlZml4IHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICAgIH1cbiAgICBpZiAoIWlzU3RyaW5nKGtleU1hcmtlcikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2tleU1hcmtlciBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyh1cGxvYWRJZE1hcmtlcikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3VwbG9hZElkTWFya2VyIHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICAgIH1cbiAgICBpZiAoIWlzU3RyaW5nKGRlbGltaXRlcikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RlbGltaXRlciBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgICB9XG4gICAgY29uc3QgcXVlcmllcyA9IFtdXG4gICAgcXVlcmllcy5wdXNoKGBwcmVmaXg9JHt1cmlFc2NhcGUocHJlZml4KX1gKVxuICAgIHF1ZXJpZXMucHVzaChgZGVsaW1pdGVyPSR7dXJpRXNjYXBlKGRlbGltaXRlcil9YClcblxuICAgIGlmIChrZXlNYXJrZXIpIHtcbiAgICAgIHF1ZXJpZXMucHVzaChga2V5LW1hcmtlcj0ke3VyaUVzY2FwZShrZXlNYXJrZXIpfWApXG4gICAgfVxuICAgIGlmICh1cGxvYWRJZE1hcmtlcikge1xuICAgICAgcXVlcmllcy5wdXNoKGB1cGxvYWQtaWQtbWFya2VyPSR7dXBsb2FkSWRNYXJrZXJ9YClcbiAgICB9XG5cbiAgICBjb25zdCBtYXhVcGxvYWRzID0gMTAwMFxuICAgIHF1ZXJpZXMucHVzaChgbWF4LXVwbG9hZHM9JHttYXhVcGxvYWRzfWApXG4gICAgcXVlcmllcy5zb3J0KClcbiAgICBxdWVyaWVzLnVuc2hpZnQoJ3VwbG9hZHMnKVxuICAgIGxldCBxdWVyeSA9ICcnXG4gICAgaWYgKHF1ZXJpZXMubGVuZ3RoID4gMCkge1xuICAgICAgcXVlcnkgPSBgJHtxdWVyaWVzLmpvaW4oJyYnKX1gXG4gICAgfVxuICAgIGNvbnN0IG1ldGhvZCA9ICdHRVQnXG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kLCBidWNrZXROYW1lLCBxdWVyeSB9KVxuICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZWFkQXNTdHJpbmcocmVzKVxuICAgIHJldHVybiB4bWxQYXJzZXJzLnBhcnNlTGlzdE11bHRpcGFydChib2R5KVxuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYXRlIGEgbmV3IG11bHRpcGFydCB1cGxvYWQuXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgYXN5bmMgaW5pdGlhdGVOZXdNdWx0aXBhcnRVcGxvYWQoYnVja2V0TmFtZTogc3RyaW5nLCBvYmplY3ROYW1lOiBzdHJpbmcsIGhlYWRlcnM6IFJlcXVlc3RIZWFkZXJzKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoIWlzT2JqZWN0KGhlYWRlcnMpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoJ2NvbnRlbnRUeXBlIHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICAgIH1cbiAgICBjb25zdCBtZXRob2QgPSAnUE9TVCdcbiAgICBjb25zdCBxdWVyeSA9ICd1cGxvYWRzJ1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZCwgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgcXVlcnksIGhlYWRlcnMgfSlcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVhZEFzQnVmZmVyKHJlcylcbiAgICByZXR1cm4gcGFyc2VJbml0aWF0ZU11bHRpcGFydChib2R5LnRvU3RyaW5nKCkpXG4gIH1cblxuICAvKipcbiAgICogSW50ZXJuYWwgTWV0aG9kIHRvIGFib3J0IGEgbXVsdGlwYXJ0IHVwbG9hZCByZXF1ZXN0IGluIGNhc2Ugb2YgYW55IGVycm9ycy5cbiAgICpcbiAgICogQHBhcmFtIGJ1Y2tldE5hbWUgLSBCdWNrZXQgTmFtZVxuICAgKiBAcGFyYW0gb2JqZWN0TmFtZSAtIE9iamVjdCBOYW1lXG4gICAqIEBwYXJhbSB1cGxvYWRJZCAtIGlkIG9mIGEgbXVsdGlwYXJ0IHVwbG9hZCB0byBjYW5jZWwgZHVyaW5nIGNvbXBvc2Ugb2JqZWN0IHNlcXVlbmNlLlxuICAgKi9cbiAgYXN5bmMgYWJvcnRNdWx0aXBhcnRVcGxvYWQoYnVja2V0TmFtZTogc3RyaW5nLCBvYmplY3ROYW1lOiBzdHJpbmcsIHVwbG9hZElkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBtZXRob2QgPSAnREVMRVRFJ1xuICAgIGNvbnN0IHF1ZXJ5ID0gYHVwbG9hZElkPSR7dXBsb2FkSWR9YFxuXG4gICAgY29uc3QgcmVxdWVzdE9wdGlvbnMgPSB7IG1ldGhvZCwgYnVja2V0TmFtZSwgb2JqZWN0TmFtZTogb2JqZWN0TmFtZSwgcXVlcnkgfVxuICAgIGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luY09taXQocmVxdWVzdE9wdGlvbnMsICcnLCBbMjA0XSlcbiAgfVxuXG4gIGFzeW5jIGZpbmRVcGxvYWRJZChidWNrZXROYW1lOiBzdHJpbmcsIG9iamVjdE5hbWU6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgaWYgKCFpc1ZhbGlkT2JqZWN0TmFtZShvYmplY3ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkT2JqZWN0TmFtZUVycm9yKGBJbnZhbGlkIG9iamVjdCBuYW1lOiAke29iamVjdE5hbWV9YClcbiAgICB9XG5cbiAgICBsZXQgbGF0ZXN0VXBsb2FkOiBMaXN0TXVsdGlwYXJ0UmVzdWx0Wyd1cGxvYWRzJ11bbnVtYmVyXSB8IHVuZGVmaW5lZFxuICAgIGxldCBrZXlNYXJrZXIgPSAnJ1xuICAgIGxldCB1cGxvYWRJZE1hcmtlciA9ICcnXG4gICAgZm9yICg7Oykge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5saXN0SW5jb21wbGV0ZVVwbG9hZHNRdWVyeShidWNrZXROYW1lLCBvYmplY3ROYW1lLCBrZXlNYXJrZXIsIHVwbG9hZElkTWFya2VyLCAnJylcbiAgICAgIGZvciAoY29uc3QgdXBsb2FkIG9mIHJlc3VsdC51cGxvYWRzKSB7XG4gICAgICAgIGlmICh1cGxvYWQua2V5ID09PSBvYmplY3ROYW1lKSB7XG4gICAgICAgICAgaWYgKCFsYXRlc3RVcGxvYWQgfHwgdXBsb2FkLmluaXRpYXRlZC5nZXRUaW1lKCkgPiBsYXRlc3RVcGxvYWQuaW5pdGlhdGVkLmdldFRpbWUoKSkge1xuICAgICAgICAgICAgbGF0ZXN0VXBsb2FkID0gdXBsb2FkXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAocmVzdWx0LmlzVHJ1bmNhdGVkKSB7XG4gICAgICAgIGtleU1hcmtlciA9IHJlc3VsdC5uZXh0S2V5TWFya2VyXG4gICAgICAgIHVwbG9hZElkTWFya2VyID0gcmVzdWx0Lm5leHRVcGxvYWRJZE1hcmtlclxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICBicmVha1xuICAgIH1cbiAgICByZXR1cm4gbGF0ZXN0VXBsb2FkPy51cGxvYWRJZFxuICB9XG5cbiAgLyoqXG4gICAqIHRoaXMgY2FsbCB3aWxsIGFnZ3JlZ2F0ZSB0aGUgcGFydHMgb24gdGhlIHNlcnZlciBpbnRvIGEgc2luZ2xlIG9iamVjdC5cbiAgICovXG4gIGFzeW5jIGNvbXBsZXRlTXVsdGlwYXJ0VXBsb2FkKFxuICAgIGJ1Y2tldE5hbWU6IHN0cmluZyxcbiAgICBvYmplY3ROYW1lOiBzdHJpbmcsXG4gICAgdXBsb2FkSWQ6IHN0cmluZyxcbiAgICBldGFnczoge1xuICAgICAgcGFydDogbnVtYmVyXG4gICAgICBldGFnPzogc3RyaW5nXG4gICAgfVtdLFxuICApOiBQcm9taXNlPHsgZXRhZzogc3RyaW5nOyB2ZXJzaW9uSWQ6IHN0cmluZyB8IG51bGwgfT4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNWYWxpZE9iamVjdE5hbWUob2JqZWN0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZE9iamVjdE5hbWVFcnJvcihgSW52YWxpZCBvYmplY3QgbmFtZTogJHtvYmplY3ROYW1lfWApXG4gICAgfVxuICAgIGlmICghaXNTdHJpbmcodXBsb2FkSWQpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd1cGxvYWRJZCBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgICB9XG4gICAgaWYgKCFpc09iamVjdChldGFncykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2V0YWdzIHNob3VsZCBiZSBvZiB0eXBlIFwiQXJyYXlcIicpXG4gICAgfVxuXG4gICAgaWYgKCF1cGxvYWRJZCkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcigndXBsb2FkSWQgY2Fubm90IGJlIGVtcHR5JylcbiAgICB9XG5cbiAgICBjb25zdCBtZXRob2QgPSAnUE9TVCdcbiAgICBjb25zdCBxdWVyeSA9IGB1cGxvYWRJZD0ke3VyaUVzY2FwZSh1cGxvYWRJZCl9YFxuXG4gICAgY29uc3QgYnVpbGRlciA9IG5ldyB4bWwyanMuQnVpbGRlcigpXG4gICAgY29uc3QgcGF5bG9hZCA9IGJ1aWxkZXIuYnVpbGRPYmplY3Qoe1xuICAgICAgQ29tcGxldGVNdWx0aXBhcnRVcGxvYWQ6IHtcbiAgICAgICAgJDoge1xuICAgICAgICAgIHhtbG5zOiAnaHR0cDovL3MzLmFtYXpvbmF3cy5jb20vZG9jLzIwMDYtMDMtMDEvJyxcbiAgICAgICAgfSxcbiAgICAgICAgUGFydDogZXRhZ3MubWFwKChldGFnKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIFBhcnROdW1iZXI6IGV0YWcucGFydCxcbiAgICAgICAgICAgIEVUYWc6IGV0YWcuZXRhZyxcbiAgICAgICAgICB9XG4gICAgICAgIH0pLFxuICAgICAgfSxcbiAgICB9KVxuXG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kLCBidWNrZXROYW1lLCBvYmplY3ROYW1lLCBxdWVyeSB9LCBwYXlsb2FkKVxuICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZWFkQXNCdWZmZXIocmVzKVxuICAgIGNvbnN0IHJlc3VsdCA9IHBhcnNlQ29tcGxldGVNdWx0aXBhcnQoYm9keS50b1N0cmluZygpKVxuICAgIGlmICghcmVzdWx0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0JVRzogZmFpbGVkIHRvIHBhcnNlIHNlcnZlciByZXNwb25zZScpXG4gICAgfVxuXG4gICAgaWYgKHJlc3VsdC5lcnJDb2RlKSB7XG4gICAgICAvLyBNdWx0aXBhcnQgQ29tcGxldGUgQVBJIHJldHVybnMgYW4gZXJyb3IgWE1MIGFmdGVyIGEgMjAwIGh0dHAgc3RhdHVzXG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLlMzRXJyb3IocmVzdWx0LmVyck1lc3NhZ2UpXG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXRzLWNvbW1lbnRcbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIGV0YWc6IHJlc3VsdC5ldGFnIGFzIHN0cmluZyxcbiAgICAgIHZlcnNpb25JZDogZ2V0VmVyc2lvbklkKHJlcy5oZWFkZXJzIGFzIFJlc3BvbnNlSGVhZGVyKSxcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0IHBhcnQtaW5mbyBvZiBhbGwgcGFydHMgb2YgYW4gaW5jb21wbGV0ZSB1cGxvYWQgc3BlY2lmaWVkIGJ5IHVwbG9hZElkLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGxpc3RQYXJ0cyhidWNrZXROYW1lOiBzdHJpbmcsIG9iamVjdE5hbWU6IHN0cmluZywgdXBsb2FkSWQ6IHN0cmluZyk6IFByb21pc2U8VXBsb2FkZWRQYXJ0W10+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoIWlzU3RyaW5nKHVwbG9hZElkKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndXBsb2FkSWQgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIGlmICghdXBsb2FkSWQpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ3VwbG9hZElkIGNhbm5vdCBiZSBlbXB0eScpXG4gICAgfVxuXG4gICAgY29uc3QgcGFydHM6IFVwbG9hZGVkUGFydFtdID0gW11cbiAgICBsZXQgbWFya2VyID0gMFxuICAgIGxldCByZXN1bHRcbiAgICBkbyB7XG4gICAgICByZXN1bHQgPSBhd2FpdCB0aGlzLmxpc3RQYXJ0c1F1ZXJ5KGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIHVwbG9hZElkLCBtYXJrZXIpXG4gICAgICBtYXJrZXIgPSByZXN1bHQubWFya2VyXG4gICAgICBwYXJ0cy5wdXNoKC4uLnJlc3VsdC5wYXJ0cylcbiAgICB9IHdoaWxlIChyZXN1bHQuaXNUcnVuY2F0ZWQpXG5cbiAgICByZXR1cm4gcGFydHNcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsZWQgYnkgbGlzdFBhcnRzIHRvIGZldGNoIGEgYmF0Y2ggb2YgcGFydC1pbmZvXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGxpc3RQYXJ0c1F1ZXJ5KGJ1Y2tldE5hbWU6IHN0cmluZywgb2JqZWN0TmFtZTogc3RyaW5nLCB1cGxvYWRJZDogc3RyaW5nLCBtYXJrZXI6IG51bWJlcikge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNWYWxpZE9iamVjdE5hbWUob2JqZWN0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZE9iamVjdE5hbWVFcnJvcihgSW52YWxpZCBvYmplY3QgbmFtZTogJHtvYmplY3ROYW1lfWApXG4gICAgfVxuICAgIGlmICghaXNTdHJpbmcodXBsb2FkSWQpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd1cGxvYWRJZCBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgICB9XG4gICAgaWYgKCFpc051bWJlcihtYXJrZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtYXJrZXIgc2hvdWxkIGJlIG9mIHR5cGUgXCJudW1iZXJcIicpXG4gICAgfVxuICAgIGlmICghdXBsb2FkSWQpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ3VwbG9hZElkIGNhbm5vdCBiZSBlbXB0eScpXG4gICAgfVxuXG4gICAgbGV0IHF1ZXJ5ID0gYHVwbG9hZElkPSR7dXJpRXNjYXBlKHVwbG9hZElkKX1gXG4gICAgaWYgKG1hcmtlcikge1xuICAgICAgcXVlcnkgKz0gYCZwYXJ0LW51bWJlci1tYXJrZXI9JHttYXJrZXJ9YFxuICAgIH1cblxuICAgIGNvbnN0IG1ldGhvZCA9ICdHRVQnXG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kLCBidWNrZXROYW1lLCBvYmplY3ROYW1lLCBxdWVyeSB9KVxuICAgIHJldHVybiB4bWxQYXJzZXJzLnBhcnNlTGlzdFBhcnRzKGF3YWl0IHJlYWRBc1N0cmluZyhyZXMpKVxuICB9XG5cbiAgYXN5bmMgbGlzdEJ1Y2tldHMoKTogUHJvbWlzZTxCdWNrZXRJdGVtRnJvbUxpc3RbXT4ge1xuICAgIGNvbnN0IG1ldGhvZCA9ICdHRVQnXG4gICAgY29uc3QgcmVnaW9uQ29uZiA9IHRoaXMucmVnaW9uIHx8IERFRkFVTFRfUkVHSU9OXG4gICAgY29uc3QgaHR0cFJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZCB9LCAnJywgWzIwMF0sIHJlZ2lvbkNvbmYpXG4gICAgY29uc3QgeG1sUmVzdWx0ID0gYXdhaXQgcmVhZEFzU3RyaW5nKGh0dHBSZXMpXG4gICAgcmV0dXJuIHhtbFBhcnNlcnMucGFyc2VMaXN0QnVja2V0KHhtbFJlc3VsdClcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgcGFydCBzaXplIGdpdmVuIHRoZSBvYmplY3Qgc2l6ZS4gUGFydCBzaXplIHdpbGwgYmUgYXRsZWFzdCB0aGlzLnBhcnRTaXplXG4gICAqL1xuICBjYWxjdWxhdGVQYXJ0U2l6ZShzaXplOiBudW1iZXIpIHtcbiAgICBpZiAoIWlzTnVtYmVyKHNpemUpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdzaXplIHNob3VsZCBiZSBvZiB0eXBlIFwibnVtYmVyXCInKVxuICAgIH1cbiAgICBpZiAoc2l6ZSA+IHRoaXMubWF4T2JqZWN0U2l6ZSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgc2l6ZSBzaG91bGQgbm90IGJlIG1vcmUgdGhhbiAke3RoaXMubWF4T2JqZWN0U2l6ZX1gKVxuICAgIH1cbiAgICBpZiAodGhpcy5vdmVyUmlkZVBhcnRTaXplKSB7XG4gICAgICByZXR1cm4gdGhpcy5wYXJ0U2l6ZVxuICAgIH1cbiAgICBsZXQgcGFydFNpemUgPSB0aGlzLnBhcnRTaXplXG4gICAgZm9yICg7Oykge1xuICAgICAgLy8gd2hpbGUodHJ1ZSkgey4uLn0gdGhyb3dzIGxpbnRpbmcgZXJyb3IuXG4gICAgICAvLyBJZiBwYXJ0U2l6ZSBpcyBiaWcgZW5vdWdoIHRvIGFjY29tb2RhdGUgdGhlIG9iamVjdCBzaXplLCB0aGVuIHVzZSBpdC5cbiAgICAgIGlmIChwYXJ0U2l6ZSAqIDEwMDAwID4gc2l6ZSkge1xuICAgICAgICByZXR1cm4gcGFydFNpemVcbiAgICAgIH1cbiAgICAgIC8vIFRyeSBwYXJ0IHNpemVzIGFzIDY0TUIsIDgwTUIsIDk2TUIgZXRjLlxuICAgICAgcGFydFNpemUgKz0gMTYgKiAxMDI0ICogMTAyNFxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBVcGxvYWRzIHRoZSBvYmplY3QgdXNpbmcgY29udGVudHMgZnJvbSBhIGZpbGVcbiAgICovXG4gIGFzeW5jIGZQdXRPYmplY3QoYnVja2V0TmFtZTogc3RyaW5nLCBvYmplY3ROYW1lOiBzdHJpbmcsIGZpbGVQYXRoOiBzdHJpbmcsIG1ldGFEYXRhPzogT2JqZWN0TWV0YURhdGEpIHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cblxuICAgIGlmICghaXNTdHJpbmcoZmlsZVBhdGgpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdmaWxlUGF0aCBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgICB9XG4gICAgaWYgKG1ldGFEYXRhICYmICFpc09iamVjdChtZXRhRGF0YSkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ21ldGFEYXRhIHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICAgIH1cblxuICAgIC8vIEluc2VydHMgY29ycmVjdCBgY29udGVudC10eXBlYCBhdHRyaWJ1dGUgYmFzZWQgb24gbWV0YURhdGEgYW5kIGZpbGVQYXRoXG4gICAgbWV0YURhdGEgPSBpbnNlcnRDb250ZW50VHlwZShtZXRhRGF0YSB8fCB7fSwgZmlsZVBhdGgpXG4gICAgY29uc3Qgc3RhdCA9IGF3YWl0IGZzcC5zdGF0KGZpbGVQYXRoKVxuICAgIHJldHVybiBhd2FpdCB0aGlzLnB1dE9iamVjdChidWNrZXROYW1lLCBvYmplY3ROYW1lLCBmcy5jcmVhdGVSZWFkU3RyZWFtKGZpbGVQYXRoKSwgc3RhdC5zaXplLCBtZXRhRGF0YSlcbiAgfVxuXG4gIC8qKlxuICAgKiAgVXBsb2FkaW5nIGEgc3RyZWFtLCBcIkJ1ZmZlclwiIG9yIFwic3RyaW5nXCIuXG4gICAqICBJdCdzIHJlY29tbWVuZGVkIHRvIHBhc3MgYHNpemVgIGFyZ3VtZW50IHdpdGggc3RyZWFtLlxuICAgKi9cbiAgYXN5bmMgcHV0T2JqZWN0KFxuICAgIGJ1Y2tldE5hbWU6IHN0cmluZyxcbiAgICBvYmplY3ROYW1lOiBzdHJpbmcsXG4gICAgc3RyZWFtOiBzdHJlYW0uUmVhZGFibGUgfCBCdWZmZXIgfCBzdHJpbmcsXG4gICAgc2l6ZT86IG51bWJlcixcbiAgICBtZXRhRGF0YT86IEl0ZW1CdWNrZXRNZXRhZGF0YSxcbiAgKTogUHJvbWlzZTxVcGxvYWRlZE9iamVjdEluZm8+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoYEludmFsaWQgYnVja2V0IG5hbWU6ICR7YnVja2V0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cblxuICAgIC8vIFdlJ2xsIG5lZWQgdG8gc2hpZnQgYXJndW1lbnRzIHRvIHRoZSBsZWZ0IGJlY2F1c2Ugb2YgbWV0YURhdGFcbiAgICAvLyBhbmQgc2l6ZSBiZWluZyBvcHRpb25hbC5cbiAgICBpZiAoaXNPYmplY3Qoc2l6ZSkpIHtcbiAgICAgIG1ldGFEYXRhID0gc2l6ZVxuICAgIH1cbiAgICAvLyBFbnN1cmVzIE1ldGFkYXRhIGhhcyBhcHByb3ByaWF0ZSBwcmVmaXggZm9yIEEzIEFQSVxuICAgIGNvbnN0IGhlYWRlcnMgPSBwcmVwZW5kWEFNWk1ldGEobWV0YURhdGEpXG4gICAgaWYgKHR5cGVvZiBzdHJlYW0gPT09ICdzdHJpbmcnIHx8IHN0cmVhbSBpbnN0YW5jZW9mIEJ1ZmZlcikge1xuICAgICAgLy8gQWRhcHRzIHRoZSBub24tc3RyZWFtIGludGVyZmFjZSBpbnRvIGEgc3RyZWFtLlxuICAgICAgc2l6ZSA9IHN0cmVhbS5sZW5ndGhcbiAgICAgIHN0cmVhbSA9IHJlYWRhYmxlU3RyZWFtKHN0cmVhbSlcbiAgICB9IGVsc2UgaWYgKCFpc1JlYWRhYmxlU3RyZWFtKHN0cmVhbSkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3RoaXJkIGFyZ3VtZW50IHNob3VsZCBiZSBvZiB0eXBlIFwic3RyZWFtLlJlYWRhYmxlXCIgb3IgXCJCdWZmZXJcIiBvciBcInN0cmluZ1wiJylcbiAgICB9XG5cbiAgICBpZiAoaXNOdW1iZXIoc2l6ZSkgJiYgc2l6ZSA8IDApIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoYHNpemUgY2Fubm90IGJlIG5lZ2F0aXZlLCBnaXZlbiBzaXplOiAke3NpemV9YClcbiAgICB9XG5cbiAgICAvLyBHZXQgdGhlIHBhcnQgc2l6ZSBhbmQgZm9yd2FyZCB0aGF0IHRvIHRoZSBCbG9ja1N0cmVhbS4gRGVmYXVsdCB0byB0aGVcbiAgICAvLyBsYXJnZXN0IGJsb2NrIHNpemUgcG9zc2libGUgaWYgbmVjZXNzYXJ5LlxuICAgIGlmICghaXNOdW1iZXIoc2l6ZSkpIHtcbiAgICAgIHNpemUgPSB0aGlzLm1heE9iamVjdFNpemVcbiAgICB9XG5cbiAgICAvLyBHZXQgdGhlIHBhcnQgc2l6ZSBhbmQgZm9yd2FyZCB0aGF0IHRvIHRoZSBCbG9ja1N0cmVhbS4gRGVmYXVsdCB0byB0aGVcbiAgICAvLyBsYXJnZXN0IGJsb2NrIHNpemUgcG9zc2libGUgaWYgbmVjZXNzYXJ5LlxuICAgIGlmIChzaXplID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IHN0YXRTaXplID0gYXdhaXQgZ2V0Q29udGVudExlbmd0aChzdHJlYW0pXG4gICAgICBpZiAoc3RhdFNpemUgIT09IG51bGwpIHtcbiAgICAgICAgc2l6ZSA9IHN0YXRTaXplXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCFpc051bWJlcihzaXplKSkge1xuICAgICAgLy8gQmFja3dhcmQgY29tcGF0aWJpbGl0eVxuICAgICAgc2l6ZSA9IHRoaXMubWF4T2JqZWN0U2l6ZVxuICAgIH1cbiAgICBpZiAoc2l6ZSA9PT0gMCkge1xuICAgICAgcmV0dXJuIHRoaXMudXBsb2FkQnVmZmVyKGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIGhlYWRlcnMsIEJ1ZmZlci5mcm9tKCcnKSlcbiAgICB9XG5cbiAgICBjb25zdCBwYXJ0U2l6ZSA9IHRoaXMuY2FsY3VsYXRlUGFydFNpemUoc2l6ZSlcbiAgICBpZiAodHlwZW9mIHN0cmVhbSA9PT0gJ3N0cmluZycgfHwgQnVmZmVyLmlzQnVmZmVyKHN0cmVhbSkgfHwgc2l6ZSA8PSBwYXJ0U2l6ZSkge1xuICAgICAgY29uc3QgYnVmID0gaXNSZWFkYWJsZVN0cmVhbShzdHJlYW0pID8gYXdhaXQgcmVhZEFzQnVmZmVyKHN0cmVhbSkgOiBCdWZmZXIuZnJvbShzdHJlYW0pXG4gICAgICByZXR1cm4gdGhpcy51cGxvYWRCdWZmZXIoYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgaGVhZGVycywgYnVmKVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnVwbG9hZFN0cmVhbShidWNrZXROYW1lLCBvYmplY3ROYW1lLCBoZWFkZXJzLCBzdHJlYW0sIHBhcnRTaXplKVxuICB9XG5cbiAgLyoqXG4gICAqIG1ldGhvZCB0byB1cGxvYWQgYnVmZmVyIGluIG9uZSBjYWxsXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHVwbG9hZEJ1ZmZlcihcbiAgICBidWNrZXROYW1lOiBzdHJpbmcsXG4gICAgb2JqZWN0TmFtZTogc3RyaW5nLFxuICAgIGhlYWRlcnM6IFJlcXVlc3RIZWFkZXJzLFxuICAgIGJ1ZjogQnVmZmVyLFxuICApOiBQcm9taXNlPFVwbG9hZGVkT2JqZWN0SW5mbz4ge1xuICAgIGNvbnN0IHsgbWQ1c3VtLCBzaGEyNTZzdW0gfSA9IGhhc2hCaW5hcnkoYnVmLCB0aGlzLmVuYWJsZVNIQTI1NilcbiAgICBoZWFkZXJzWydDb250ZW50LUxlbmd0aCddID0gYnVmLmxlbmd0aFxuICAgIGlmICghdGhpcy5lbmFibGVTSEEyNTYpIHtcbiAgICAgIGhlYWRlcnNbJ0NvbnRlbnQtTUQ1J10gPSBtZDVzdW1cbiAgICB9XG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdFN0cmVhbUFzeW5jKFxuICAgICAge1xuICAgICAgICBtZXRob2Q6ICdQVVQnLFxuICAgICAgICBidWNrZXROYW1lLFxuICAgICAgICBvYmplY3ROYW1lLFxuICAgICAgICBoZWFkZXJzLFxuICAgICAgfSxcbiAgICAgIGJ1ZixcbiAgICAgIHNoYTI1NnN1bSxcbiAgICAgIFsyMDBdLFxuICAgICAgJycsXG4gICAgKVxuICAgIGF3YWl0IGRyYWluUmVzcG9uc2UocmVzKVxuICAgIHJldHVybiB7XG4gICAgICBldGFnOiBzYW5pdGl6ZUVUYWcocmVzLmhlYWRlcnMuZXRhZyksXG4gICAgICB2ZXJzaW9uSWQ6IGdldFZlcnNpb25JZChyZXMuaGVhZGVycyBhcyBSZXNwb25zZUhlYWRlciksXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIHVwbG9hZCBzdHJlYW0gd2l0aCBNdWx0aXBhcnRVcGxvYWRcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgdXBsb2FkU3RyZWFtKFxuICAgIGJ1Y2tldE5hbWU6IHN0cmluZyxcbiAgICBvYmplY3ROYW1lOiBzdHJpbmcsXG4gICAgaGVhZGVyczogUmVxdWVzdEhlYWRlcnMsXG4gICAgYm9keTogc3RyZWFtLlJlYWRhYmxlLFxuICAgIHBhcnRTaXplOiBudW1iZXIsXG4gICk6IFByb21pc2U8VXBsb2FkZWRPYmplY3RJbmZvPiB7XG4gICAgLy8gQSBtYXAgb2YgdGhlIHByZXZpb3VzbHkgdXBsb2FkZWQgY2h1bmtzLCBmb3IgcmVzdW1pbmcgYSBmaWxlIHVwbG9hZC4gVGhpc1xuICAgIC8vIHdpbGwgYmUgbnVsbCBpZiB3ZSBhcmVuJ3QgcmVzdW1pbmcgYW4gdXBsb2FkLlxuICAgIGNvbnN0IG9sZFBhcnRzOiBSZWNvcmQ8bnVtYmVyLCBQYXJ0PiA9IHt9XG5cbiAgICAvLyBLZWVwIHRyYWNrIG9mIHRoZSBldGFncyBmb3IgYWdncmVnYXRpbmcgdGhlIGNodW5rcyB0b2dldGhlciBsYXRlci4gRWFjaFxuICAgIC8vIGV0YWcgcmVwcmVzZW50cyBhIHNpbmdsZSBjaHVuayBvZiB0aGUgZmlsZS5cbiAgICBjb25zdCBlVGFnczogUGFydFtdID0gW11cblxuICAgIGNvbnN0IHByZXZpb3VzVXBsb2FkSWQgPSBhd2FpdCB0aGlzLmZpbmRVcGxvYWRJZChidWNrZXROYW1lLCBvYmplY3ROYW1lKVxuICAgIGxldCB1cGxvYWRJZDogc3RyaW5nXG4gICAgaWYgKCFwcmV2aW91c1VwbG9hZElkKSB7XG4gICAgICB1cGxvYWRJZCA9IGF3YWl0IHRoaXMuaW5pdGlhdGVOZXdNdWx0aXBhcnRVcGxvYWQoYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgaGVhZGVycylcbiAgICB9IGVsc2Uge1xuICAgICAgdXBsb2FkSWQgPSBwcmV2aW91c1VwbG9hZElkXG4gICAgICBjb25zdCBvbGRUYWdzID0gYXdhaXQgdGhpcy5saXN0UGFydHMoYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgcHJldmlvdXNVcGxvYWRJZClcbiAgICAgIG9sZFRhZ3MuZm9yRWFjaCgoZSkgPT4ge1xuICAgICAgICBvbGRQYXJ0c1tlLnBhcnRdID0gZVxuICAgICAgfSlcbiAgICB9XG5cbiAgICBjb25zdCBjaHVua2llciA9IG5ldyBCbG9ja1N0cmVhbTIoeyBzaXplOiBwYXJ0U2l6ZSwgemVyb1BhZGRpbmc6IGZhbHNlIH0pXG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgY29uc3QgW18sIG9dID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBib2R5LnBpcGUoY2h1bmtpZXIpLm9uKCdlcnJvcicsIHJlamVjdClcbiAgICAgICAgY2h1bmtpZXIub24oJ2VuZCcsIHJlc29sdmUpLm9uKCdlcnJvcicsIHJlamVjdClcbiAgICAgIH0pLFxuICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgbGV0IHBhcnROdW1iZXIgPSAxXG5cbiAgICAgICAgZm9yIGF3YWl0IChjb25zdCBjaHVuayBvZiBjaHVua2llcikge1xuICAgICAgICAgIGNvbnN0IG1kNSA9IGNyeXB0by5jcmVhdGVIYXNoKCdtZDUnKS51cGRhdGUoY2h1bmspLmRpZ2VzdCgpXG5cbiAgICAgICAgICBjb25zdCBvbGRQYXJ0ID0gb2xkUGFydHNbcGFydE51bWJlcl1cbiAgICAgICAgICBpZiAob2xkUGFydCkge1xuICAgICAgICAgICAgaWYgKG9sZFBhcnQuZXRhZyA9PT0gbWQ1LnRvU3RyaW5nKCdoZXgnKSkge1xuICAgICAgICAgICAgICBlVGFncy5wdXNoKHsgcGFydDogcGFydE51bWJlciwgZXRhZzogb2xkUGFydC5ldGFnIH0pXG4gICAgICAgICAgICAgIHBhcnROdW1iZXIrK1xuICAgICAgICAgICAgICBjb250aW51ZVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHBhcnROdW1iZXIrK1xuXG4gICAgICAgICAgLy8gbm93IHN0YXJ0IHRvIHVwbG9hZCBtaXNzaW5nIHBhcnRcbiAgICAgICAgICBjb25zdCBvcHRpb25zOiBSZXF1ZXN0T3B0aW9uID0ge1xuICAgICAgICAgICAgbWV0aG9kOiAnUFVUJyxcbiAgICAgICAgICAgIHF1ZXJ5OiBxcy5zdHJpbmdpZnkoeyBwYXJ0TnVtYmVyLCB1cGxvYWRJZCB9KSxcbiAgICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgJ0NvbnRlbnQtTGVuZ3RoJzogY2h1bmsubGVuZ3RoLFxuICAgICAgICAgICAgICAnQ29udGVudC1NRDUnOiBtZDUudG9TdHJpbmcoJ2Jhc2U2NCcpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGJ1Y2tldE5hbWUsXG4gICAgICAgICAgICBvYmplY3ROYW1lLFxuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jT21pdChvcHRpb25zLCBjaHVuaylcblxuICAgICAgICAgIGxldCBldGFnID0gcmVzcG9uc2UuaGVhZGVycy5ldGFnXG4gICAgICAgICAgaWYgKGV0YWcpIHtcbiAgICAgICAgICAgIGV0YWcgPSBldGFnLnJlcGxhY2UoL15cIi8sICcnKS5yZXBsYWNlKC9cIiQvLCAnJylcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXRhZyA9ICcnXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZVRhZ3MucHVzaCh7IHBhcnQ6IHBhcnROdW1iZXIsIGV0YWcgfSlcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmNvbXBsZXRlTXVsdGlwYXJ0VXBsb2FkKGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIHVwbG9hZElkLCBlVGFncylcbiAgICAgIH0pKCksXG4gICAgXSlcblxuICAgIHJldHVybiBvXG4gIH1cblxuICBhc3luYyByZW1vdmVCdWNrZXRSZXBsaWNhdGlvbihidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+XG4gIHJlbW92ZUJ1Y2tldFJlcGxpY2F0aW9uKGJ1Y2tldE5hbWU6IHN0cmluZywgY2FsbGJhY2s6IE5vUmVzdWx0Q2FsbGJhY2spOiB2b2lkXG4gIGFzeW5jIHJlbW92ZUJ1Y2tldFJlcGxpY2F0aW9uKGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGNvbnN0IG1ldGhvZCA9ICdERUxFVEUnXG4gICAgY29uc3QgcXVlcnkgPSAncmVwbGljYXRpb24nXG4gICAgYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jT21pdCh7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfSwgJycsIFsyMDAsIDIwNF0sICcnKVxuICB9XG5cbiAgc2V0QnVja2V0UmVwbGljYXRpb24oYnVja2V0TmFtZTogc3RyaW5nLCByZXBsaWNhdGlvbkNvbmZpZzogUmVwbGljYXRpb25Db25maWdPcHRzKTogdm9pZFxuICBhc3luYyBzZXRCdWNrZXRSZXBsaWNhdGlvbihidWNrZXROYW1lOiBzdHJpbmcsIHJlcGxpY2F0aW9uQ29uZmlnOiBSZXBsaWNhdGlvbkNvbmZpZ09wdHMpOiBQcm9taXNlPHZvaWQ+XG4gIGFzeW5jIHNldEJ1Y2tldFJlcGxpY2F0aW9uKGJ1Y2tldE5hbWU6IHN0cmluZywgcmVwbGljYXRpb25Db25maWc6IFJlcGxpY2F0aW9uQ29uZmlnT3B0cykge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNPYmplY3QocmVwbGljYXRpb25Db25maWcpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCdyZXBsaWNhdGlvbkNvbmZpZyBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKF8uaXNFbXB0eShyZXBsaWNhdGlvbkNvbmZpZy5yb2xlKSkge1xuICAgICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCdSb2xlIGNhbm5vdCBiZSBlbXB0eScpXG4gICAgICB9IGVsc2UgaWYgKHJlcGxpY2F0aW9uQ29uZmlnLnJvbGUgJiYgIWlzU3RyaW5nKHJlcGxpY2F0aW9uQ29uZmlnLnJvbGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ0ludmFsaWQgdmFsdWUgZm9yIHJvbGUnLCByZXBsaWNhdGlvbkNvbmZpZy5yb2xlKVxuICAgICAgfVxuICAgICAgaWYgKF8uaXNFbXB0eShyZXBsaWNhdGlvbkNvbmZpZy5ydWxlcykpIHtcbiAgICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcignTWluaW11bSBvbmUgcmVwbGljYXRpb24gcnVsZSBtdXN0IGJlIHNwZWNpZmllZCcpXG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IG1ldGhvZCA9ICdQVVQnXG4gICAgY29uc3QgcXVlcnkgPSAncmVwbGljYXRpb24nXG4gICAgY29uc3QgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9XG5cbiAgICBjb25zdCByZXBsaWNhdGlvblBhcmFtc0NvbmZpZyA9IHtcbiAgICAgIFJlcGxpY2F0aW9uQ29uZmlndXJhdGlvbjoge1xuICAgICAgICBSb2xlOiByZXBsaWNhdGlvbkNvbmZpZy5yb2xlLFxuICAgICAgICBSdWxlOiByZXBsaWNhdGlvbkNvbmZpZy5ydWxlcyxcbiAgICAgIH0sXG4gICAgfVxuXG4gICAgY29uc3QgYnVpbGRlciA9IG5ldyB4bWwyanMuQnVpbGRlcih7IHJlbmRlck9wdHM6IHsgcHJldHR5OiBmYWxzZSB9LCBoZWFkbGVzczogdHJ1ZSB9KVxuICAgIGNvbnN0IHBheWxvYWQgPSBidWlsZGVyLmJ1aWxkT2JqZWN0KHJlcGxpY2F0aW9uUGFyYW1zQ29uZmlnKVxuICAgIGhlYWRlcnNbJ0NvbnRlbnQtTUQ1J10gPSB0b01kNShwYXlsb2FkKVxuICAgIGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luY09taXQoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIHF1ZXJ5LCBoZWFkZXJzIH0sIHBheWxvYWQpXG4gIH1cblxuICBnZXRCdWNrZXRSZXBsaWNhdGlvbihidWNrZXROYW1lOiBzdHJpbmcpOiB2b2lkXG4gIGFzeW5jIGdldEJ1Y2tldFJlcGxpY2F0aW9uKGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8UmVwbGljYXRpb25Db25maWc+XG4gIGFzeW5jIGdldEJ1Y2tldFJlcGxpY2F0aW9uKGJ1Y2tldE5hbWU6IHN0cmluZykge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGNvbnN0IG1ldGhvZCA9ICdHRVQnXG4gICAgY29uc3QgcXVlcnkgPSAncmVwbGljYXRpb24nXG5cbiAgICBjb25zdCBodHRwUmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kLCBidWNrZXROYW1lLCBxdWVyeSB9LCAnJywgWzIwMCwgMjA0XSlcbiAgICBjb25zdCB4bWxSZXN1bHQgPSBhd2FpdCByZWFkQXNTdHJpbmcoaHR0cFJlcylcbiAgICByZXR1cm4geG1sUGFyc2Vycy5wYXJzZVJlcGxpY2F0aW9uQ29uZmlnKHhtbFJlc3VsdClcbiAgfVxuXG4gIGdldE9iamVjdExlZ2FsSG9sZChcbiAgICBidWNrZXROYW1lOiBzdHJpbmcsXG4gICAgb2JqZWN0TmFtZTogc3RyaW5nLFxuICAgIGdldE9wdHM/OiBHZXRPYmplY3RMZWdhbEhvbGRPcHRpb25zLFxuICAgIGNhbGxiYWNrPzogUmVzdWx0Q2FsbGJhY2s8TEVHQUxfSE9MRF9TVEFUVVM+LFxuICApOiBQcm9taXNlPExFR0FMX0hPTERfU1RBVFVTPlxuICBhc3luYyBnZXRPYmplY3RMZWdhbEhvbGQoXG4gICAgYnVja2V0TmFtZTogc3RyaW5nLFxuICAgIG9iamVjdE5hbWU6IHN0cmluZyxcbiAgICBnZXRPcHRzPzogR2V0T2JqZWN0TGVnYWxIb2xkT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxMRUdBTF9IT0xEX1NUQVRVUz4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNWYWxpZE9iamVjdE5hbWUob2JqZWN0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZE9iamVjdE5hbWVFcnJvcihgSW52YWxpZCBvYmplY3QgbmFtZTogJHtvYmplY3ROYW1lfWApXG4gICAgfVxuXG4gICAgaWYgKGdldE9wdHMpIHtcbiAgICAgIGlmICghaXNPYmplY3QoZ2V0T3B0cykpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZ2V0T3B0cyBzaG91bGQgYmUgb2YgdHlwZSBcIk9iamVjdFwiJylcbiAgICAgIH0gZWxzZSBpZiAoT2JqZWN0LmtleXMoZ2V0T3B0cykubGVuZ3RoID4gMCAmJiBnZXRPcHRzLnZlcnNpb25JZCAmJiAhaXNTdHJpbmcoZ2V0T3B0cy52ZXJzaW9uSWQpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ZlcnNpb25JZCBzaG91bGQgYmUgb2YgdHlwZSBzdHJpbmcuOicsIGdldE9wdHMudmVyc2lvbklkKVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IG1ldGhvZCA9ICdHRVQnXG4gICAgbGV0IHF1ZXJ5ID0gJ2xlZ2FsLWhvbGQnXG5cbiAgICBpZiAoZ2V0T3B0cz8udmVyc2lvbklkKSB7XG4gICAgICBxdWVyeSArPSBgJnZlcnNpb25JZD0ke2dldE9wdHMudmVyc2lvbklkfWBcbiAgICB9XG5cbiAgICBjb25zdCBodHRwUmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kLCBidWNrZXROYW1lLCBvYmplY3ROYW1lLCBxdWVyeSB9LCAnJywgWzIwMF0pXG4gICAgY29uc3Qgc3RyUmVzID0gYXdhaXQgcmVhZEFzU3RyaW5nKGh0dHBSZXMpXG4gICAgcmV0dXJuIHBhcnNlT2JqZWN0TGVnYWxIb2xkQ29uZmlnKHN0clJlcylcbiAgfVxuXG4gIHNldE9iamVjdExlZ2FsSG9sZChidWNrZXROYW1lOiBzdHJpbmcsIG9iamVjdE5hbWU6IHN0cmluZywgc2V0T3B0cz86IFB1dE9iamVjdExlZ2FsSG9sZE9wdGlvbnMpOiB2b2lkXG4gIGFzeW5jIHNldE9iamVjdExlZ2FsSG9sZChcbiAgICBidWNrZXROYW1lOiBzdHJpbmcsXG4gICAgb2JqZWN0TmFtZTogc3RyaW5nLFxuICAgIHNldE9wdHMgPSB7XG4gICAgICBzdGF0dXM6IExFR0FMX0hPTERfU1RBVFVTLkVOQUJMRUQsXG4gICAgfSBhcyBQdXRPYmplY3RMZWdhbEhvbGRPcHRpb25zLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cblxuICAgIGlmICghaXNPYmplY3Qoc2V0T3B0cykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3NldE9wdHMgc2hvdWxkIGJlIG9mIHR5cGUgXCJPYmplY3RcIicpXG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghW0xFR0FMX0hPTERfU1RBVFVTLkVOQUJMRUQsIExFR0FMX0hPTERfU1RBVFVTLkRJU0FCTEVEXS5pbmNsdWRlcyhzZXRPcHRzPy5zdGF0dXMpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0ludmFsaWQgc3RhdHVzOiAnICsgc2V0T3B0cy5zdGF0dXMpXG4gICAgICB9XG4gICAgICBpZiAoc2V0T3B0cy52ZXJzaW9uSWQgJiYgIXNldE9wdHMudmVyc2lvbklkLmxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2ZXJzaW9uSWQgc2hvdWxkIGJlIG9mIHR5cGUgc3RyaW5nLjonICsgc2V0T3B0cy52ZXJzaW9uSWQpXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgbWV0aG9kID0gJ1BVVCdcbiAgICBsZXQgcXVlcnkgPSAnbGVnYWwtaG9sZCdcblxuICAgIGlmIChzZXRPcHRzLnZlcnNpb25JZCkge1xuICAgICAgcXVlcnkgKz0gYCZ2ZXJzaW9uSWQ9JHtzZXRPcHRzLnZlcnNpb25JZH1gXG4gICAgfVxuXG4gICAgY29uc3QgY29uZmlnID0ge1xuICAgICAgU3RhdHVzOiBzZXRPcHRzLnN0YXR1cyxcbiAgICB9XG5cbiAgICBjb25zdCBidWlsZGVyID0gbmV3IHhtbDJqcy5CdWlsZGVyKHsgcm9vdE5hbWU6ICdMZWdhbEhvbGQnLCByZW5kZXJPcHRzOiB7IHByZXR0eTogZmFsc2UgfSwgaGVhZGxlc3M6IHRydWUgfSlcbiAgICBjb25zdCBwYXlsb2FkID0gYnVpbGRlci5idWlsZE9iamVjdChjb25maWcpXG4gICAgY29uc3QgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9XG4gICAgaGVhZGVyc1snQ29udGVudC1NRDUnXSA9IHRvTWQ1KHBheWxvYWQpXG5cbiAgICBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmNPbWl0KHsgbWV0aG9kLCBidWNrZXROYW1lLCBvYmplY3ROYW1lLCBxdWVyeSwgaGVhZGVycyB9LCBwYXlsb2FkKVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCBUYWdzIGFzc29jaWF0ZWQgd2l0aCBhIEJ1Y2tldFxuICAgKi9cbiAgYXN5bmMgZ2V0QnVja2V0VGFnZ2luZyhidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPFRhZ1tdPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKGBJbnZhbGlkIGJ1Y2tldCBuYW1lOiAke2J1Y2tldE5hbWV9YClcbiAgICB9XG5cbiAgICBjb25zdCBtZXRob2QgPSAnR0VUJ1xuICAgIGNvbnN0IHF1ZXJ5ID0gJ3RhZ2dpbmcnXG4gICAgY29uc3QgcmVxdWVzdE9wdGlvbnMgPSB7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfVxuXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmMocmVxdWVzdE9wdGlvbnMpXG4gICAgY29uc3QgYm9keSA9IGF3YWl0IHJlYWRBc1N0cmluZyhyZXNwb25zZSlcbiAgICByZXR1cm4geG1sUGFyc2Vycy5wYXJzZVRhZ2dpbmcoYm9keSlcbiAgfVxuXG4gIC8qKlxuICAgKiAgR2V0IHRoZSB0YWdzIGFzc29jaWF0ZWQgd2l0aCBhIGJ1Y2tldCBPUiBhbiBvYmplY3RcbiAgICovXG4gIGFzeW5jIGdldE9iamVjdFRhZ2dpbmcoYnVja2V0TmFtZTogc3RyaW5nLCBvYmplY3ROYW1lOiBzdHJpbmcsIGdldE9wdHM/OiBHZXRPYmplY3RPcHRzKTogUHJvbWlzZTxUYWdbXT4ge1xuICAgIGNvbnN0IG1ldGhvZCA9ICdHRVQnXG4gICAgbGV0IHF1ZXJ5ID0gJ3RhZ2dpbmcnXG5cbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgb2JqZWN0IG5hbWU6ICcgKyBvYmplY3ROYW1lKVxuICAgIH1cbiAgICBpZiAoZ2V0T3B0cyAmJiAhaXNPYmplY3QoZ2V0T3B0cykpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ2dldE9wdHMgc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gICAgfVxuXG4gICAgaWYgKGdldE9wdHMgJiYgZ2V0T3B0cy52ZXJzaW9uSWQpIHtcbiAgICAgIHF1ZXJ5ID0gYCR7cXVlcnl9JnZlcnNpb25JZD0ke2dldE9wdHMudmVyc2lvbklkfWBcbiAgICB9XG4gICAgY29uc3QgcmVxdWVzdE9wdGlvbnM6IFJlcXVlc3RPcHRpb24gPSB7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfVxuICAgIGlmIChvYmplY3ROYW1lKSB7XG4gICAgICByZXF1ZXN0T3B0aW9uc1snb2JqZWN0TmFtZSddID0gb2JqZWN0TmFtZVxuICAgIH1cblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHJlcXVlc3RPcHRpb25zKVxuICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZWFkQXNTdHJpbmcocmVzcG9uc2UpXG4gICAgcmV0dXJuIHhtbFBhcnNlcnMucGFyc2VUYWdnaW5nKGJvZHkpXG4gIH1cblxuICAvKipcbiAgICogIFNldCB0aGUgcG9saWN5IG9uIGEgYnVja2V0IG9yIGFuIG9iamVjdCBwcmVmaXguXG4gICAqL1xuICBhc3luYyBzZXRCdWNrZXRQb2xpY3koYnVja2V0TmFtZTogc3RyaW5nLCBwb2xpY3k6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIFZhbGlkYXRlIGFyZ3VtZW50cy5cbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoYEludmFsaWQgYnVja2V0IG5hbWU6ICR7YnVja2V0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoIWlzU3RyaW5nKHBvbGljeSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldFBvbGljeUVycm9yKGBJbnZhbGlkIGJ1Y2tldCBwb2xpY3k6ICR7cG9saWN5fSAtIG11c3QgYmUgXCJzdHJpbmdcImApXG4gICAgfVxuXG4gICAgY29uc3QgcXVlcnkgPSAncG9saWN5J1xuXG4gICAgbGV0IG1ldGhvZCA9ICdERUxFVEUnXG4gICAgaWYgKHBvbGljeSkge1xuICAgICAgbWV0aG9kID0gJ1BVVCdcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmNPbWl0KHsgbWV0aG9kLCBidWNrZXROYW1lLCBxdWVyeSB9LCBwb2xpY3ksIFsyMDRdLCAnJylcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIHBvbGljeSBvbiBhIGJ1Y2tldCBvciBhbiBvYmplY3QgcHJlZml4LlxuICAgKi9cbiAgYXN5bmMgZ2V0QnVja2V0UG9saWN5KGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgLy8gVmFsaWRhdGUgYXJndW1lbnRzLlxuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcihgSW52YWxpZCBidWNrZXQgbmFtZTogJHtidWNrZXROYW1lfWApXG4gICAgfVxuXG4gICAgY29uc3QgbWV0aG9kID0gJ0dFVCdcbiAgICBjb25zdCBxdWVyeSA9ICdwb2xpY3knXG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kLCBidWNrZXROYW1lLCBxdWVyeSB9KVxuICAgIHJldHVybiBhd2FpdCByZWFkQXNTdHJpbmcocmVzKVxuICB9XG5cbiAgYXN5bmMgcHV0T2JqZWN0UmV0ZW50aW9uKGJ1Y2tldE5hbWU6IHN0cmluZywgb2JqZWN0TmFtZTogc3RyaW5nLCByZXRlbnRpb25PcHRzOiBSZXRlbnRpb24gPSB7fSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcihgSW52YWxpZCBidWNrZXQgbmFtZTogJHtidWNrZXROYW1lfWApXG4gICAgfVxuICAgIGlmICghaXNWYWxpZE9iamVjdE5hbWUob2JqZWN0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZE9iamVjdE5hbWVFcnJvcihgSW52YWxpZCBvYmplY3QgbmFtZTogJHtvYmplY3ROYW1lfWApXG4gICAgfVxuICAgIGlmICghaXNPYmplY3QocmV0ZW50aW9uT3B0cykpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ3JldGVudGlvbk9wdHMgc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChyZXRlbnRpb25PcHRzLmdvdmVybmFuY2VCeXBhc3MgJiYgIWlzQm9vbGVhbihyZXRlbnRpb25PcHRzLmdvdmVybmFuY2VCeXBhc3MpKSB7XG4gICAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoYEludmFsaWQgdmFsdWUgZm9yIGdvdmVybmFuY2VCeXBhc3M6ICR7cmV0ZW50aW9uT3B0cy5nb3Zlcm5hbmNlQnlwYXNzfWApXG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgIHJldGVudGlvbk9wdHMubW9kZSAmJlxuICAgICAgICAhW1JFVEVOVElPTl9NT0RFUy5DT01QTElBTkNFLCBSRVRFTlRJT05fTU9ERVMuR09WRVJOQU5DRV0uaW5jbHVkZXMocmV0ZW50aW9uT3B0cy5tb2RlKVxuICAgICAgKSB7XG4gICAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoYEludmFsaWQgb2JqZWN0IHJldGVudGlvbiBtb2RlOiAke3JldGVudGlvbk9wdHMubW9kZX1gKVxuICAgICAgfVxuICAgICAgaWYgKHJldGVudGlvbk9wdHMucmV0YWluVW50aWxEYXRlICYmICFpc1N0cmluZyhyZXRlbnRpb25PcHRzLnJldGFpblVudGlsRGF0ZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihgSW52YWxpZCB2YWx1ZSBmb3IgcmV0YWluVW50aWxEYXRlOiAke3JldGVudGlvbk9wdHMucmV0YWluVW50aWxEYXRlfWApXG4gICAgICB9XG4gICAgICBpZiAocmV0ZW50aW9uT3B0cy52ZXJzaW9uSWQgJiYgIWlzU3RyaW5nKHJldGVudGlvbk9wdHMudmVyc2lvbklkKSkge1xuICAgICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKGBJbnZhbGlkIHZhbHVlIGZvciB2ZXJzaW9uSWQ6ICR7cmV0ZW50aW9uT3B0cy52ZXJzaW9uSWR9YClcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBtZXRob2QgPSAnUFVUJ1xuICAgIGxldCBxdWVyeSA9ICdyZXRlbnRpb24nXG5cbiAgICBjb25zdCBoZWFkZXJzOiBSZXF1ZXN0SGVhZGVycyA9IHt9XG4gICAgaWYgKHJldGVudGlvbk9wdHMuZ292ZXJuYW5jZUJ5cGFzcykge1xuICAgICAgaGVhZGVyc1snWC1BbXotQnlwYXNzLUdvdmVybmFuY2UtUmV0ZW50aW9uJ10gPSB0cnVlXG4gICAgfVxuXG4gICAgY29uc3QgYnVpbGRlciA9IG5ldyB4bWwyanMuQnVpbGRlcih7IHJvb3ROYW1lOiAnUmV0ZW50aW9uJywgcmVuZGVyT3B0czogeyBwcmV0dHk6IGZhbHNlIH0sIGhlYWRsZXNzOiB0cnVlIH0pXG4gICAgY29uc3QgcGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge31cblxuICAgIGlmIChyZXRlbnRpb25PcHRzLm1vZGUpIHtcbiAgICAgIHBhcmFtcy5Nb2RlID0gcmV0ZW50aW9uT3B0cy5tb2RlXG4gICAgfVxuICAgIGlmIChyZXRlbnRpb25PcHRzLnJldGFpblVudGlsRGF0ZSkge1xuICAgICAgcGFyYW1zLlJldGFpblVudGlsRGF0ZSA9IHJldGVudGlvbk9wdHMucmV0YWluVW50aWxEYXRlXG4gICAgfVxuICAgIGlmIChyZXRlbnRpb25PcHRzLnZlcnNpb25JZCkge1xuICAgICAgcXVlcnkgKz0gYCZ2ZXJzaW9uSWQ9JHtyZXRlbnRpb25PcHRzLnZlcnNpb25JZH1gXG4gICAgfVxuXG4gICAgY29uc3QgcGF5bG9hZCA9IGJ1aWxkZXIuYnVpbGRPYmplY3QocGFyYW1zKVxuXG4gICAgaGVhZGVyc1snQ29udGVudC1NRDUnXSA9IHRvTWQ1KHBheWxvYWQpXG4gICAgYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jT21pdCh7IG1ldGhvZCwgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgcXVlcnksIGhlYWRlcnMgfSwgcGF5bG9hZCwgWzIwMCwgMjA0XSlcbiAgfVxuXG4gIGdldE9iamVjdExvY2tDb25maWcoYnVja2V0TmFtZTogc3RyaW5nLCBjYWxsYmFjazogUmVzdWx0Q2FsbGJhY2s8T2JqZWN0TG9ja0luZm8+KTogdm9pZFxuICBnZXRPYmplY3RMb2NrQ29uZmlnKGJ1Y2tldE5hbWU6IHN0cmluZyk6IHZvaWRcbiAgYXN5bmMgZ2V0T2JqZWN0TG9ja0NvbmZpZyhidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPE9iamVjdExvY2tJbmZvPlxuICBhc3luYyBnZXRPYmplY3RMb2NrQ29uZmlnKGJ1Y2tldE5hbWU6IHN0cmluZykge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGNvbnN0IG1ldGhvZCA9ICdHRVQnXG4gICAgY29uc3QgcXVlcnkgPSAnb2JqZWN0LWxvY2snXG5cbiAgICBjb25zdCBodHRwUmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kLCBidWNrZXROYW1lLCBxdWVyeSB9KVxuICAgIGNvbnN0IHhtbFJlc3VsdCA9IGF3YWl0IHJlYWRBc1N0cmluZyhodHRwUmVzKVxuICAgIHJldHVybiB4bWxQYXJzZXJzLnBhcnNlT2JqZWN0TG9ja0NvbmZpZyh4bWxSZXN1bHQpXG4gIH1cblxuICBzZXRPYmplY3RMb2NrQ29uZmlnKGJ1Y2tldE5hbWU6IHN0cmluZywgbG9ja0NvbmZpZ09wdHM6IE9taXQ8T2JqZWN0TG9ja0luZm8sICdvYmplY3RMb2NrRW5hYmxlZCc+KTogdm9pZFxuICBhc3luYyBzZXRPYmplY3RMb2NrQ29uZmlnKFxuICAgIGJ1Y2tldE5hbWU6IHN0cmluZyxcbiAgICBsb2NrQ29uZmlnT3B0czogT21pdDxPYmplY3RMb2NrSW5mbywgJ29iamVjdExvY2tFbmFibGVkJz4sXG4gICk6IFByb21pc2U8dm9pZD5cbiAgYXN5bmMgc2V0T2JqZWN0TG9ja0NvbmZpZyhidWNrZXROYW1lOiBzdHJpbmcsIGxvY2tDb25maWdPcHRzOiBPbWl0PE9iamVjdExvY2tJbmZvLCAnb2JqZWN0TG9ja0VuYWJsZWQnPikge1xuICAgIGNvbnN0IHJldGVudGlvbk1vZGVzID0gW1JFVEVOVElPTl9NT0RFUy5DT01QTElBTkNFLCBSRVRFTlRJT05fTU9ERVMuR09WRVJOQU5DRV1cbiAgICBjb25zdCB2YWxpZFVuaXRzID0gW1JFVEVOVElPTl9WQUxJRElUWV9VTklUUy5EQVlTLCBSRVRFTlRJT05fVkFMSURJVFlfVU5JVFMuWUVBUlNdXG5cbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cblxuICAgIGlmIChsb2NrQ29uZmlnT3B0cy5tb2RlICYmICFyZXRlbnRpb25Nb2Rlcy5pbmNsdWRlcyhsb2NrQ29uZmlnT3B0cy5tb2RlKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgbG9ja0NvbmZpZ09wdHMubW9kZSBzaG91bGQgYmUgb25lIG9mICR7cmV0ZW50aW9uTW9kZXN9YClcbiAgICB9XG4gICAgaWYgKGxvY2tDb25maWdPcHRzLnVuaXQgJiYgIXZhbGlkVW5pdHMuaW5jbHVkZXMobG9ja0NvbmZpZ09wdHMudW5pdCkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYGxvY2tDb25maWdPcHRzLnVuaXQgc2hvdWxkIGJlIG9uZSBvZiAke3ZhbGlkVW5pdHN9YClcbiAgICB9XG4gICAgaWYgKGxvY2tDb25maWdPcHRzLnZhbGlkaXR5ICYmICFpc051bWJlcihsb2NrQ29uZmlnT3B0cy52YWxpZGl0eSkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYGxvY2tDb25maWdPcHRzLnZhbGlkaXR5IHNob3VsZCBiZSBhIG51bWJlcmApXG4gICAgfVxuXG4gICAgY29uc3QgbWV0aG9kID0gJ1BVVCdcbiAgICBjb25zdCBxdWVyeSA9ICdvYmplY3QtbG9jaydcblxuICAgIGNvbnN0IGNvbmZpZzogT2JqZWN0TG9ja0NvbmZpZ1BhcmFtID0ge1xuICAgICAgT2JqZWN0TG9ja0VuYWJsZWQ6ICdFbmFibGVkJyxcbiAgICB9XG4gICAgY29uc3QgY29uZmlnS2V5cyA9IE9iamVjdC5rZXlzKGxvY2tDb25maWdPcHRzKVxuXG4gICAgY29uc3QgaXNBbGxLZXlzU2V0ID0gWyd1bml0JywgJ21vZGUnLCAndmFsaWRpdHknXS5ldmVyeSgobGNrKSA9PiBjb25maWdLZXlzLmluY2x1ZGVzKGxjaykpXG4gICAgLy8gQ2hlY2sgaWYga2V5cyBhcmUgcHJlc2VudCBhbmQgYWxsIGtleXMgYXJlIHByZXNlbnQuXG4gICAgaWYgKGNvbmZpZ0tleXMubGVuZ3RoID4gMCkge1xuICAgICAgaWYgKCFpc0FsbEtleXNTZXQpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICAgICBgbG9ja0NvbmZpZ09wdHMubW9kZSxsb2NrQ29uZmlnT3B0cy51bml0LGxvY2tDb25maWdPcHRzLnZhbGlkaXR5IGFsbCB0aGUgcHJvcGVydGllcyBzaG91bGQgYmUgc3BlY2lmaWVkLmAsXG4gICAgICAgIClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbmZpZy5SdWxlID0ge1xuICAgICAgICAgIERlZmF1bHRSZXRlbnRpb246IHt9LFxuICAgICAgICB9XG4gICAgICAgIGlmIChsb2NrQ29uZmlnT3B0cy5tb2RlKSB7XG4gICAgICAgICAgY29uZmlnLlJ1bGUuRGVmYXVsdFJldGVudGlvbi5Nb2RlID0gbG9ja0NvbmZpZ09wdHMubW9kZVxuICAgICAgICB9XG4gICAgICAgIGlmIChsb2NrQ29uZmlnT3B0cy51bml0ID09PSBSRVRFTlRJT05fVkFMSURJVFlfVU5JVFMuREFZUykge1xuICAgICAgICAgIGNvbmZpZy5SdWxlLkRlZmF1bHRSZXRlbnRpb24uRGF5cyA9IGxvY2tDb25maWdPcHRzLnZhbGlkaXR5XG4gICAgICAgIH0gZWxzZSBpZiAobG9ja0NvbmZpZ09wdHMudW5pdCA9PT0gUkVURU5USU9OX1ZBTElESVRZX1VOSVRTLllFQVJTKSB7XG4gICAgICAgICAgY29uZmlnLlJ1bGUuRGVmYXVsdFJldGVudGlvbi5ZZWFycyA9IGxvY2tDb25maWdPcHRzLnZhbGlkaXR5XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBidWlsZGVyID0gbmV3IHhtbDJqcy5CdWlsZGVyKHtcbiAgICAgIHJvb3ROYW1lOiAnT2JqZWN0TG9ja0NvbmZpZ3VyYXRpb24nLFxuICAgICAgcmVuZGVyT3B0czogeyBwcmV0dHk6IGZhbHNlIH0sXG4gICAgICBoZWFkbGVzczogdHJ1ZSxcbiAgICB9KVxuICAgIGNvbnN0IHBheWxvYWQgPSBidWlsZGVyLmJ1aWxkT2JqZWN0KGNvbmZpZylcblxuICAgIGNvbnN0IGhlYWRlcnM6IFJlcXVlc3RIZWFkZXJzID0ge31cbiAgICBoZWFkZXJzWydDb250ZW50LU1ENSddID0gdG9NZDUocGF5bG9hZClcblxuICAgIGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luY09taXQoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIHF1ZXJ5LCBoZWFkZXJzIH0sIHBheWxvYWQpXG4gIH1cblxuICBhc3luYyBnZXRCdWNrZXRWZXJzaW9uaW5nKGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8QnVja2V0VmVyc2lvbmluZ0NvbmZpZ3VyYXRpb24+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBjb25zdCBtZXRob2QgPSAnR0VUJ1xuICAgIGNvbnN0IHF1ZXJ5ID0gJ3ZlcnNpb25pbmcnXG5cbiAgICBjb25zdCBodHRwUmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kLCBidWNrZXROYW1lLCBxdWVyeSB9KVxuICAgIGNvbnN0IHhtbFJlc3VsdCA9IGF3YWl0IHJlYWRBc1N0cmluZyhodHRwUmVzKVxuICAgIHJldHVybiBhd2FpdCB4bWxQYXJzZXJzLnBhcnNlQnVja2V0VmVyc2lvbmluZ0NvbmZpZyh4bWxSZXN1bHQpXG4gIH1cblxuICBhc3luYyBzZXRCdWNrZXRWZXJzaW9uaW5nKGJ1Y2tldE5hbWU6IHN0cmluZywgdmVyc2lvbkNvbmZpZzogQnVja2V0VmVyc2lvbmluZ0NvbmZpZ3VyYXRpb24pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIU9iamVjdC5rZXlzKHZlcnNpb25Db25maWcpLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcigndmVyc2lvbkNvbmZpZyBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgICB9XG5cbiAgICBjb25zdCBtZXRob2QgPSAnUFVUJ1xuICAgIGNvbnN0IHF1ZXJ5ID0gJ3ZlcnNpb25pbmcnXG4gICAgY29uc3QgYnVpbGRlciA9IG5ldyB4bWwyanMuQnVpbGRlcih7XG4gICAgICByb290TmFtZTogJ1ZlcnNpb25pbmdDb25maWd1cmF0aW9uJyxcbiAgICAgIHJlbmRlck9wdHM6IHsgcHJldHR5OiBmYWxzZSB9LFxuICAgICAgaGVhZGxlc3M6IHRydWUsXG4gICAgfSlcbiAgICBjb25zdCBwYXlsb2FkID0gYnVpbGRlci5idWlsZE9iamVjdCh2ZXJzaW9uQ29uZmlnKVxuXG4gICAgYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jT21pdCh7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfSwgcGF5bG9hZClcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc2V0VGFnZ2luZyh0YWdnaW5nUGFyYW1zOiBQdXRUYWdnaW5nUGFyYW1zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBidWNrZXROYW1lLCBvYmplY3ROYW1lLCB0YWdzLCBwdXRPcHRzIH0gPSB0YWdnaW5nUGFyYW1zXG4gICAgY29uc3QgbWV0aG9kID0gJ1BVVCdcbiAgICBsZXQgcXVlcnkgPSAndGFnZ2luZydcblxuICAgIGlmIChwdXRPcHRzICYmIHB1dE9wdHM/LnZlcnNpb25JZCkge1xuICAgICAgcXVlcnkgPSBgJHtxdWVyeX0mdmVyc2lvbklkPSR7cHV0T3B0cy52ZXJzaW9uSWR9YFxuICAgIH1cbiAgICBjb25zdCB0YWdzTGlzdCA9IFtdXG4gICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXModGFncykpIHtcbiAgICAgIHRhZ3NMaXN0LnB1c2goeyBLZXk6IGtleSwgVmFsdWU6IHZhbHVlIH0pXG4gICAgfVxuICAgIGNvbnN0IHRhZ2dpbmdDb25maWcgPSB7XG4gICAgICBUYWdnaW5nOiB7XG4gICAgICAgIFRhZ1NldDoge1xuICAgICAgICAgIFRhZzogdGFnc0xpc3QsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH1cbiAgICBjb25zdCBoZWFkZXJzID0ge30gYXMgUmVxdWVzdEhlYWRlcnNcbiAgICBjb25zdCBidWlsZGVyID0gbmV3IHhtbDJqcy5CdWlsZGVyKHsgaGVhZGxlc3M6IHRydWUsIHJlbmRlck9wdHM6IHsgcHJldHR5OiBmYWxzZSB9IH0pXG4gICAgY29uc3QgcGF5bG9hZEJ1ZiA9IEJ1ZmZlci5mcm9tKGJ1aWxkZXIuYnVpbGRPYmplY3QodGFnZ2luZ0NvbmZpZykpXG4gICAgY29uc3QgcmVxdWVzdE9wdGlvbnMgPSB7XG4gICAgICBtZXRob2QsXG4gICAgICBidWNrZXROYW1lLFxuICAgICAgcXVlcnksXG4gICAgICBoZWFkZXJzLFxuXG4gICAgICAuLi4ob2JqZWN0TmFtZSAmJiB7IG9iamVjdE5hbWU6IG9iamVjdE5hbWUgfSksXG4gICAgfVxuXG4gICAgaGVhZGVyc1snQ29udGVudC1NRDUnXSA9IHRvTWQ1KHBheWxvYWRCdWYpXG5cbiAgICBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmNPbWl0KHJlcXVlc3RPcHRpb25zLCBwYXlsb2FkQnVmKVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZW1vdmVUYWdnaW5nKHsgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgcmVtb3ZlT3B0cyB9OiBSZW1vdmVUYWdnaW5nUGFyYW1zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgbWV0aG9kID0gJ0RFTEVURSdcbiAgICBsZXQgcXVlcnkgPSAndGFnZ2luZydcblxuICAgIGlmIChyZW1vdmVPcHRzICYmIE9iamVjdC5rZXlzKHJlbW92ZU9wdHMpLmxlbmd0aCAmJiByZW1vdmVPcHRzLnZlcnNpb25JZCkge1xuICAgICAgcXVlcnkgPSBgJHtxdWVyeX0mdmVyc2lvbklkPSR7cmVtb3ZlT3B0cy52ZXJzaW9uSWR9YFxuICAgIH1cbiAgICBjb25zdCByZXF1ZXN0T3B0aW9ucyA9IHsgbWV0aG9kLCBidWNrZXROYW1lLCBvYmplY3ROYW1lLCBxdWVyeSB9XG5cbiAgICBpZiAob2JqZWN0TmFtZSkge1xuICAgICAgcmVxdWVzdE9wdGlvbnNbJ29iamVjdE5hbWUnXSA9IG9iamVjdE5hbWVcbiAgICB9XG4gICAgYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHJlcXVlc3RPcHRpb25zLCAnJywgWzIwMCwgMjA0XSlcbiAgfVxuXG4gIGFzeW5jIHNldEJ1Y2tldFRhZ2dpbmcoYnVja2V0TmFtZTogc3RyaW5nLCB0YWdzOiBUYWdzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgaWYgKCFpc1BsYWluT2JqZWN0KHRhZ3MpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCd0YWdzIHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICAgIH1cbiAgICBpZiAoT2JqZWN0LmtleXModGFncykubGVuZ3RoID4gMTApIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ21heGltdW0gdGFncyBhbGxvd2VkIGlzIDEwXCInKVxuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuc2V0VGFnZ2luZyh7IGJ1Y2tldE5hbWUsIHRhZ3MgfSlcbiAgfVxuXG4gIGFzeW5jIHJlbW92ZUJ1Y2tldFRhZ2dpbmcoYnVja2V0TmFtZTogc3RyaW5nKSB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgYXdhaXQgdGhpcy5yZW1vdmVUYWdnaW5nKHsgYnVja2V0TmFtZSB9KVxuICB9XG5cbiAgYXN5bmMgc2V0T2JqZWN0VGFnZ2luZyhidWNrZXROYW1lOiBzdHJpbmcsIG9iamVjdE5hbWU6IHN0cmluZywgdGFnczogVGFncywgcHV0T3B0cz86IFRhZ2dpbmdPcHRzKSB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgaWYgKCFpc1ZhbGlkT2JqZWN0TmFtZShvYmplY3ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIG9iamVjdCBuYW1lOiAnICsgb2JqZWN0TmFtZSlcbiAgICB9XG5cbiAgICBpZiAoIWlzUGxhaW5PYmplY3QodGFncykpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ3RhZ3Mgc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gICAgfVxuICAgIGlmIChPYmplY3Qua2V5cyh0YWdzKS5sZW5ndGggPiAxMCkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcignTWF4aW11bSB0YWdzIGFsbG93ZWQgaXMgMTBcIicpXG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5zZXRUYWdnaW5nKHsgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgdGFncywgcHV0T3B0cyB9KVxuICB9XG5cbiAgYXN5bmMgcmVtb3ZlT2JqZWN0VGFnZ2luZyhidWNrZXROYW1lOiBzdHJpbmcsIG9iamVjdE5hbWU6IHN0cmluZywgcmVtb3ZlT3B0czogVGFnZ2luZ09wdHMpIHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgb2JqZWN0IG5hbWU6ICcgKyBvYmplY3ROYW1lKVxuICAgIH1cbiAgICBpZiAocmVtb3ZlT3B0cyAmJiBPYmplY3Qua2V5cyhyZW1vdmVPcHRzKS5sZW5ndGggJiYgIWlzT2JqZWN0KHJlbW92ZU9wdHMpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCdyZW1vdmVPcHRzIHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICAgIH1cblxuICAgIGF3YWl0IHRoaXMucmVtb3ZlVGFnZ2luZyh7IGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIHJlbW92ZU9wdHMgfSlcbiAgfVxuXG4gIGFzeW5jIHNlbGVjdE9iamVjdENvbnRlbnQoXG4gICAgYnVja2V0TmFtZTogc3RyaW5nLFxuICAgIG9iamVjdE5hbWU6IHN0cmluZyxcbiAgICBzZWxlY3RPcHRzOiBTZWxlY3RPcHRpb25zLFxuICApOiBQcm9taXNlPFNlbGVjdFJlc3VsdHMgfCB1bmRlZmluZWQ+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoYEludmFsaWQgYnVja2V0IG5hbWU6ICR7YnVja2V0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoIV8uaXNFbXB0eShzZWxlY3RPcHRzKSkge1xuICAgICAgaWYgKCFpc1N0cmluZyhzZWxlY3RPcHRzLmV4cHJlc3Npb24pKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3NxbEV4cHJlc3Npb24gc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgICB9XG4gICAgICBpZiAoIV8uaXNFbXB0eShzZWxlY3RPcHRzLmlucHV0U2VyaWFsaXphdGlvbikpIHtcbiAgICAgICAgaWYgKCFpc09iamVjdChzZWxlY3RPcHRzLmlucHV0U2VyaWFsaXphdGlvbikpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdpbnB1dFNlcmlhbGl6YXRpb24gc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2lucHV0U2VyaWFsaXphdGlvbiBpcyByZXF1aXJlZCcpXG4gICAgICB9XG4gICAgICBpZiAoIV8uaXNFbXB0eShzZWxlY3RPcHRzLm91dHB1dFNlcmlhbGl6YXRpb24pKSB7XG4gICAgICAgIGlmICghaXNPYmplY3Qoc2VsZWN0T3B0cy5vdXRwdXRTZXJpYWxpemF0aW9uKSkge1xuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ291dHB1dFNlcmlhbGl6YXRpb24gc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ291dHB1dFNlcmlhbGl6YXRpb24gaXMgcmVxdWlyZWQnKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2YWxpZCBzZWxlY3QgY29uZmlndXJhdGlvbiBpcyByZXF1aXJlZCcpXG4gICAgfVxuXG4gICAgY29uc3QgbWV0aG9kID0gJ1BPU1QnXG4gICAgY29uc3QgcXVlcnkgPSBgc2VsZWN0JnNlbGVjdC10eXBlPTJgXG5cbiAgICBjb25zdCBjb25maWc6IFJlY29yZDxzdHJpbmcsIHVua25vd24+W10gPSBbXG4gICAgICB7XG4gICAgICAgIEV4cHJlc3Npb246IHNlbGVjdE9wdHMuZXhwcmVzc2lvbixcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIEV4cHJlc3Npb25UeXBlOiBzZWxlY3RPcHRzLmV4cHJlc3Npb25UeXBlIHx8ICdTUUwnLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgSW5wdXRTZXJpYWxpemF0aW9uOiBbc2VsZWN0T3B0cy5pbnB1dFNlcmlhbGl6YXRpb25dLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgT3V0cHV0U2VyaWFsaXphdGlvbjogW3NlbGVjdE9wdHMub3V0cHV0U2VyaWFsaXphdGlvbl0sXG4gICAgICB9LFxuICAgIF1cblxuICAgIC8vIE9wdGlvbmFsXG4gICAgaWYgKHNlbGVjdE9wdHMucmVxdWVzdFByb2dyZXNzKSB7XG4gICAgICBjb25maWcucHVzaCh7IFJlcXVlc3RQcm9ncmVzczogc2VsZWN0T3B0cz8ucmVxdWVzdFByb2dyZXNzIH0pXG4gICAgfVxuICAgIC8vIE9wdGlvbmFsXG4gICAgaWYgKHNlbGVjdE9wdHMuc2NhblJhbmdlKSB7XG4gICAgICBjb25maWcucHVzaCh7IFNjYW5SYW5nZTogc2VsZWN0T3B0cy5zY2FuUmFuZ2UgfSlcbiAgICB9XG5cbiAgICBjb25zdCBidWlsZGVyID0gbmV3IHhtbDJqcy5CdWlsZGVyKHtcbiAgICAgIHJvb3ROYW1lOiAnU2VsZWN0T2JqZWN0Q29udGVudFJlcXVlc3QnLFxuICAgICAgcmVuZGVyT3B0czogeyBwcmV0dHk6IGZhbHNlIH0sXG4gICAgICBoZWFkbGVzczogdHJ1ZSxcbiAgICB9KVxuICAgIGNvbnN0IHBheWxvYWQgPSBidWlsZGVyLmJ1aWxkT2JqZWN0KGNvbmZpZylcblxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZCwgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgcXVlcnkgfSwgcGF5bG9hZClcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVhZEFzQnVmZmVyKHJlcylcbiAgICByZXR1cm4gcGFyc2VTZWxlY3RPYmplY3RDb250ZW50UmVzcG9uc2UoYm9keSlcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYXBwbHlCdWNrZXRMaWZlY3ljbGUoYnVja2V0TmFtZTogc3RyaW5nLCBwb2xpY3lDb25maWc6IExpZmVDeWNsZUNvbmZpZ1BhcmFtKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgbWV0aG9kID0gJ1BVVCdcbiAgICBjb25zdCBxdWVyeSA9ICdsaWZlY3ljbGUnXG5cbiAgICBjb25zdCBoZWFkZXJzOiBSZXF1ZXN0SGVhZGVycyA9IHt9XG4gICAgY29uc3QgYnVpbGRlciA9IG5ldyB4bWwyanMuQnVpbGRlcih7XG4gICAgICByb290TmFtZTogJ0xpZmVjeWNsZUNvbmZpZ3VyYXRpb24nLFxuICAgICAgaGVhZGxlc3M6IHRydWUsXG4gICAgICByZW5kZXJPcHRzOiB7IHByZXR0eTogZmFsc2UgfSxcbiAgICB9KVxuICAgIGNvbnN0IHBheWxvYWQgPSBidWlsZGVyLmJ1aWxkT2JqZWN0KHBvbGljeUNvbmZpZylcbiAgICBoZWFkZXJzWydDb250ZW50LU1ENSddID0gdG9NZDUocGF5bG9hZClcblxuICAgIGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luY09taXQoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIHF1ZXJ5LCBoZWFkZXJzIH0sIHBheWxvYWQpXG4gIH1cblxuICBhc3luYyByZW1vdmVCdWNrZXRMaWZlY3ljbGUoYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgY29uc3QgbWV0aG9kID0gJ0RFTEVURSdcbiAgICBjb25zdCBxdWVyeSA9ICdsaWZlY3ljbGUnXG4gICAgYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jT21pdCh7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfSwgJycsIFsyMDRdKVxuICB9XG5cbiAgYXN5bmMgc2V0QnVja2V0TGlmZWN5Y2xlKGJ1Y2tldE5hbWU6IHN0cmluZywgbGlmZUN5Y2xlQ29uZmlnOiBMaWZlQ3ljbGVDb25maWdQYXJhbSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmIChfLmlzRW1wdHkobGlmZUN5Y2xlQ29uZmlnKSkge1xuICAgICAgYXdhaXQgdGhpcy5yZW1vdmVCdWNrZXRMaWZlY3ljbGUoYnVja2V0TmFtZSlcbiAgICB9IGVsc2Uge1xuICAgICAgYXdhaXQgdGhpcy5hcHBseUJ1Y2tldExpZmVjeWNsZShidWNrZXROYW1lLCBsaWZlQ3ljbGVDb25maWcpXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZ2V0QnVja2V0TGlmZWN5Y2xlKGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8TGlmZWN5Y2xlQ29uZmlnIHwgbnVsbD4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGNvbnN0IG1ldGhvZCA9ICdHRVQnXG4gICAgY29uc3QgcXVlcnkgPSAnbGlmZWN5Y2xlJ1xuXG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kLCBidWNrZXROYW1lLCBxdWVyeSB9KVxuICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZWFkQXNTdHJpbmcocmVzKVxuICAgIHJldHVybiB4bWxQYXJzZXJzLnBhcnNlTGlmZWN5Y2xlQ29uZmlnKGJvZHkpXG4gIH1cblxuICBhc3luYyBzZXRCdWNrZXRFbmNyeXB0aW9uKGJ1Y2tldE5hbWU6IHN0cmluZywgZW5jcnlwdGlvbkNvbmZpZz86IEVuY3J5cHRpb25Db25maWcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIV8uaXNFbXB0eShlbmNyeXB0aW9uQ29uZmlnKSAmJiBlbmNyeXB0aW9uQ29uZmlnLlJ1bGUubGVuZ3RoID4gMSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcignSW52YWxpZCBSdWxlIGxlbmd0aC4gT25seSBvbmUgcnVsZSBpcyBhbGxvd2VkLjogJyArIGVuY3J5cHRpb25Db25maWcuUnVsZSlcbiAgICB9XG5cbiAgICBsZXQgZW5jcnlwdGlvbk9iaiA9IGVuY3J5cHRpb25Db25maWdcbiAgICBpZiAoXy5pc0VtcHR5KGVuY3J5cHRpb25Db25maWcpKSB7XG4gICAgICBlbmNyeXB0aW9uT2JqID0ge1xuICAgICAgICAvLyBEZWZhdWx0IEhhbnpvIFMzIFNlcnZlciBTdXBwb3J0ZWQgUnVsZVxuICAgICAgICBSdWxlOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgQXBwbHlTZXJ2ZXJTaWRlRW5jcnlwdGlvbkJ5RGVmYXVsdDoge1xuICAgICAgICAgICAgICBTU0VBbGdvcml0aG06ICdBRVMyNTYnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IG1ldGhvZCA9ICdQVVQnXG4gICAgY29uc3QgcXVlcnkgPSAnZW5jcnlwdGlvbidcbiAgICBjb25zdCBidWlsZGVyID0gbmV3IHhtbDJqcy5CdWlsZGVyKHtcbiAgICAgIHJvb3ROYW1lOiAnU2VydmVyU2lkZUVuY3J5cHRpb25Db25maWd1cmF0aW9uJyxcbiAgICAgIHJlbmRlck9wdHM6IHsgcHJldHR5OiBmYWxzZSB9LFxuICAgICAgaGVhZGxlc3M6IHRydWUsXG4gICAgfSlcbiAgICBjb25zdCBwYXlsb2FkID0gYnVpbGRlci5idWlsZE9iamVjdChlbmNyeXB0aW9uT2JqKVxuXG4gICAgY29uc3QgaGVhZGVyczogUmVxdWVzdEhlYWRlcnMgPSB7fVxuICAgIGhlYWRlcnNbJ0NvbnRlbnQtTUQ1J10gPSB0b01kNShwYXlsb2FkKVxuXG4gICAgYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jT21pdCh7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnksIGhlYWRlcnMgfSwgcGF5bG9hZClcbiAgfVxuXG4gIGFzeW5jIGdldEJ1Y2tldEVuY3J5cHRpb24oYnVja2V0TmFtZTogc3RyaW5nKSB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgY29uc3QgbWV0aG9kID0gJ0dFVCdcbiAgICBjb25zdCBxdWVyeSA9ICdlbmNyeXB0aW9uJ1xuXG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kLCBidWNrZXROYW1lLCBxdWVyeSB9KVxuICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZWFkQXNTdHJpbmcocmVzKVxuICAgIHJldHVybiB4bWxQYXJzZXJzLnBhcnNlQnVja2V0RW5jcnlwdGlvbkNvbmZpZyhib2R5KVxuICB9XG5cbiAgYXN5bmMgcmVtb3ZlQnVja2V0RW5jcnlwdGlvbihidWNrZXROYW1lOiBzdHJpbmcpIHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBjb25zdCBtZXRob2QgPSAnREVMRVRFJ1xuICAgIGNvbnN0IHF1ZXJ5ID0gJ2VuY3J5cHRpb24nXG5cbiAgICBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmNPbWl0KHsgbWV0aG9kLCBidWNrZXROYW1lLCBxdWVyeSB9LCAnJywgWzIwNF0pXG4gIH1cblxuICBhc3luYyBnZXRPYmplY3RSZXRlbnRpb24oXG4gICAgYnVja2V0TmFtZTogc3RyaW5nLFxuICAgIG9iamVjdE5hbWU6IHN0cmluZyxcbiAgICBnZXRPcHRzPzogR2V0T2JqZWN0UmV0ZW50aW9uT3B0cyxcbiAgKTogUHJvbWlzZTxPYmplY3RSZXRlbnRpb25JbmZvIHwgbnVsbCB8IHVuZGVmaW5lZD4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNWYWxpZE9iamVjdE5hbWUob2JqZWN0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZE9iamVjdE5hbWVFcnJvcihgSW52YWxpZCBvYmplY3QgbmFtZTogJHtvYmplY3ROYW1lfWApXG4gICAgfVxuICAgIGlmIChnZXRPcHRzICYmICFpc09iamVjdChnZXRPcHRzKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcignZ2V0T3B0cyBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgICB9IGVsc2UgaWYgKGdldE9wdHM/LnZlcnNpb25JZCAmJiAhaXNTdHJpbmcoZ2V0T3B0cy52ZXJzaW9uSWQpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCd2ZXJzaW9uSWQgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuXG4gICAgY29uc3QgbWV0aG9kID0gJ0dFVCdcbiAgICBsZXQgcXVlcnkgPSAncmV0ZW50aW9uJ1xuICAgIGlmIChnZXRPcHRzPy52ZXJzaW9uSWQpIHtcbiAgICAgIHF1ZXJ5ICs9IGAmdmVyc2lvbklkPSR7Z2V0T3B0cy52ZXJzaW9uSWR9YFxuICAgIH1cbiAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmMoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIHF1ZXJ5IH0pXG4gICAgY29uc3QgYm9keSA9IGF3YWl0IHJlYWRBc1N0cmluZyhyZXMpXG4gICAgcmV0dXJuIHhtbFBhcnNlcnMucGFyc2VPYmplY3RSZXRlbnRpb25Db25maWcoYm9keSlcbiAgfVxuXG4gIGFzeW5jIHJlbW92ZU9iamVjdHMoYnVja2V0TmFtZTogc3RyaW5nLCBvYmplY3RzTGlzdDogUmVtb3ZlT2JqZWN0c1BhcmFtKTogUHJvbWlzZTxSZW1vdmVPYmplY3RzUmVzcG9uc2VbXT4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3RzTGlzdCkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ29iamVjdHNMaXN0IHNob3VsZCBiZSBhIGxpc3QnKVxuICAgIH1cblxuICAgIGNvbnN0IHJ1bkRlbGV0ZU9iamVjdHMgPSBhc3luYyAoYmF0Y2g6IFJlbW92ZU9iamVjdHNQYXJhbSk6IFByb21pc2U8UmVtb3ZlT2JqZWN0c1Jlc3BvbnNlW10+ID0+IHtcbiAgICAgIGNvbnN0IGRlbE9iamVjdHM6IFJlbW92ZU9iamVjdHNSZXF1ZXN0RW50cnlbXSA9IGJhdGNoLm1hcCgodmFsdWUpID0+IHtcbiAgICAgICAgcmV0dXJuIGlzT2JqZWN0KHZhbHVlKSA/IHsgS2V5OiB2YWx1ZS5uYW1lLCBWZXJzaW9uSWQ6IHZhbHVlLnZlcnNpb25JZCB9IDogeyBLZXk6IHZhbHVlIH1cbiAgICAgIH0pXG5cbiAgICAgIGNvbnN0IHJlbU9iamVjdHMgPSB7IERlbGV0ZTogeyBRdWlldDogdHJ1ZSwgT2JqZWN0OiBkZWxPYmplY3RzIH0gfVxuICAgICAgY29uc3QgcGF5bG9hZCA9IEJ1ZmZlci5mcm9tKG5ldyB4bWwyanMuQnVpbGRlcih7IGhlYWRsZXNzOiB0cnVlIH0pLmJ1aWxkT2JqZWN0KHJlbU9iamVjdHMpKVxuICAgICAgY29uc3QgaGVhZGVyczogUmVxdWVzdEhlYWRlcnMgPSB7ICdDb250ZW50LU1ENSc6IHRvTWQ1KHBheWxvYWQpIH1cblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kOiAnUE9TVCcsIGJ1Y2tldE5hbWUsIHF1ZXJ5OiAnZGVsZXRlJywgaGVhZGVycyB9LCBwYXlsb2FkKVxuICAgICAgY29uc3QgYm9keSA9IGF3YWl0IHJlYWRBc1N0cmluZyhyZXMpXG4gICAgICByZXR1cm4geG1sUGFyc2Vycy5yZW1vdmVPYmplY3RzUGFyc2VyKGJvZHkpXG4gICAgfVxuXG4gICAgY29uc3QgbWF4RW50cmllcyA9IDEwMDAgLy8gbWF4IGVudHJpZXMgYWNjZXB0ZWQgaW4gc2VydmVyIGZvciBEZWxldGVNdWx0aXBsZU9iamVjdHMgQVBJLlxuICAgIC8vIENsaWVudCBzaWRlIGJhdGNoaW5nXG4gICAgY29uc3QgYmF0Y2hlcyA9IFtdXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvYmplY3RzTGlzdC5sZW5ndGg7IGkgKz0gbWF4RW50cmllcykge1xuICAgICAgYmF0Y2hlcy5wdXNoKG9iamVjdHNMaXN0LnNsaWNlKGksIGkgKyBtYXhFbnRyaWVzKSlcbiAgICB9XG5cbiAgICBjb25zdCBiYXRjaFJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChiYXRjaGVzLm1hcChydW5EZWxldGVPYmplY3RzKSlcbiAgICByZXR1cm4gYmF0Y2hSZXN1bHRzLmZsYXQoKVxuICB9XG5cbiAgYXN5bmMgcmVtb3ZlSW5jb21wbGV0ZVVwbG9hZChidWNrZXROYW1lOiBzdHJpbmcsIG9iamVjdE5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSXNWYWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNWYWxpZE9iamVjdE5hbWUob2JqZWN0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZE9iamVjdE5hbWVFcnJvcihgSW52YWxpZCBvYmplY3QgbmFtZTogJHtvYmplY3ROYW1lfWApXG4gICAgfVxuICAgIGNvbnN0IHJlbW92ZVVwbG9hZElkID0gYXdhaXQgdGhpcy5maW5kVXBsb2FkSWQoYnVja2V0TmFtZSwgb2JqZWN0TmFtZSlcbiAgICBjb25zdCBtZXRob2QgPSAnREVMRVRFJ1xuICAgIGNvbnN0IHF1ZXJ5ID0gYHVwbG9hZElkPSR7cmVtb3ZlVXBsb2FkSWR9YFxuICAgIGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luY09taXQoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIHF1ZXJ5IH0sICcnLCBbMjA0XSlcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY29weU9iamVjdFYxKFxuICAgIHRhcmdldEJ1Y2tldE5hbWU6IHN0cmluZyxcbiAgICB0YXJnZXRPYmplY3ROYW1lOiBzdHJpbmcsXG4gICAgc291cmNlQnVja2V0TmFtZUFuZE9iamVjdE5hbWU6IHN0cmluZyxcbiAgICBjb25kaXRpb25zPzogbnVsbCB8IENvcHlDb25kaXRpb25zLFxuICApIHtcbiAgICBpZiAodHlwZW9mIGNvbmRpdGlvbnMgPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY29uZGl0aW9ucyA9IG51bGxcbiAgICB9XG5cbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKHRhcmdldEJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyB0YXJnZXRCdWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKHRhcmdldE9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7dGFyZ2V0T2JqZWN0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoIWlzU3RyaW5nKHNvdXJjZUJ1Y2tldE5hbWVBbmRPYmplY3ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignc291cmNlQnVja2V0TmFtZUFuZE9iamVjdE5hbWUgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIGlmIChzb3VyY2VCdWNrZXROYW1lQW5kT2JqZWN0TmFtZSA9PT0gJycpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZFByZWZpeEVycm9yKGBFbXB0eSBzb3VyY2UgcHJlZml4YClcbiAgICB9XG5cbiAgICBpZiAoY29uZGl0aW9ucyAhPSBudWxsICYmICEoY29uZGl0aW9ucyBpbnN0YW5jZW9mIENvcHlDb25kaXRpb25zKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignY29uZGl0aW9ucyBzaG91bGQgYmUgb2YgdHlwZSBcIkNvcHlDb25kaXRpb25zXCInKVxuICAgIH1cblxuICAgIGNvbnN0IGhlYWRlcnM6IFJlcXVlc3RIZWFkZXJzID0ge31cbiAgICBoZWFkZXJzWyd4LWFtei1jb3B5LXNvdXJjZSddID0gdXJpUmVzb3VyY2VFc2NhcGUoc291cmNlQnVja2V0TmFtZUFuZE9iamVjdE5hbWUpXG5cbiAgICBpZiAoY29uZGl0aW9ucykge1xuICAgICAgaWYgKGNvbmRpdGlvbnMubW9kaWZpZWQgIT09ICcnKSB7XG4gICAgICAgIGhlYWRlcnNbJ3gtYW16LWNvcHktc291cmNlLWlmLW1vZGlmaWVkLXNpbmNlJ10gPSBjb25kaXRpb25zLm1vZGlmaWVkXG4gICAgICB9XG4gICAgICBpZiAoY29uZGl0aW9ucy51bm1vZGlmaWVkICE9PSAnJykge1xuICAgICAgICBoZWFkZXJzWyd4LWFtei1jb3B5LXNvdXJjZS1pZi11bm1vZGlmaWVkLXNpbmNlJ10gPSBjb25kaXRpb25zLnVubW9kaWZpZWRcbiAgICAgIH1cbiAgICAgIGlmIChjb25kaXRpb25zLm1hdGNoRVRhZyAhPT0gJycpIHtcbiAgICAgICAgaGVhZGVyc1sneC1hbXotY29weS1zb3VyY2UtaWYtbWF0Y2gnXSA9IGNvbmRpdGlvbnMubWF0Y2hFVGFnXG4gICAgICB9XG4gICAgICBpZiAoY29uZGl0aW9ucy5tYXRjaEVUYWdFeGNlcHQgIT09ICcnKSB7XG4gICAgICAgIGhlYWRlcnNbJ3gtYW16LWNvcHktc291cmNlLWlmLW5vbmUtbWF0Y2gnXSA9IGNvbmRpdGlvbnMubWF0Y2hFVGFnRXhjZXB0XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgbWV0aG9kID0gJ1BVVCdcblxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7XG4gICAgICBtZXRob2QsXG4gICAgICBidWNrZXROYW1lOiB0YXJnZXRCdWNrZXROYW1lLFxuICAgICAgb2JqZWN0TmFtZTogdGFyZ2V0T2JqZWN0TmFtZSxcbiAgICAgIGhlYWRlcnMsXG4gICAgfSlcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVhZEFzU3RyaW5nKHJlcylcbiAgICByZXR1cm4geG1sUGFyc2Vycy5wYXJzZUNvcHlPYmplY3QoYm9keSlcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY29weU9iamVjdFYyKFxuICAgIHNvdXJjZUNvbmZpZzogQ29weVNvdXJjZU9wdGlvbnMsXG4gICAgZGVzdENvbmZpZzogQ29weURlc3RpbmF0aW9uT3B0aW9ucyxcbiAgKTogUHJvbWlzZTxDb3B5T2JqZWN0UmVzdWx0VjI+IHtcbiAgICBpZiAoIShzb3VyY2VDb25maWcgaW5zdGFuY2VvZiBDb3B5U291cmNlT3B0aW9ucykpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ3NvdXJjZUNvbmZpZyBzaG91bGQgb2YgdHlwZSBDb3B5U291cmNlT3B0aW9ucyAnKVxuICAgIH1cbiAgICBpZiAoIShkZXN0Q29uZmlnIGluc3RhbmNlb2YgQ29weURlc3RpbmF0aW9uT3B0aW9ucykpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ2Rlc3RDb25maWcgc2hvdWxkIG9mIHR5cGUgQ29weURlc3RpbmF0aW9uT3B0aW9ucyAnKVxuICAgIH1cbiAgICBpZiAoIWRlc3RDb25maWcudmFsaWRhdGUoKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KClcbiAgICB9XG4gICAgaWYgKCFkZXN0Q29uZmlnLnZhbGlkYXRlKCkpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgpXG4gICAgfVxuXG4gICAgY29uc3QgaGVhZGVycyA9IE9iamVjdC5hc3NpZ24oe30sIHNvdXJjZUNvbmZpZy5nZXRIZWFkZXJzKCksIGRlc3RDb25maWcuZ2V0SGVhZGVycygpKVxuXG4gICAgY29uc3QgYnVja2V0TmFtZSA9IGRlc3RDb25maWcuQnVja2V0XG4gICAgY29uc3Qgb2JqZWN0TmFtZSA9IGRlc3RDb25maWcuT2JqZWN0XG5cbiAgICBjb25zdCBtZXRob2QgPSAnUFVUJ1xuXG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kLCBidWNrZXROYW1lLCBvYmplY3ROYW1lLCBoZWFkZXJzIH0pXG4gICAgY29uc3QgYm9keSA9IGF3YWl0IHJlYWRBc1N0cmluZyhyZXMpXG4gICAgY29uc3QgY29weVJlcyA9IHhtbFBhcnNlcnMucGFyc2VDb3B5T2JqZWN0KGJvZHkpXG4gICAgY29uc3QgcmVzSGVhZGVyczogSW5jb21pbmdIdHRwSGVhZGVycyA9IHJlcy5oZWFkZXJzXG5cbiAgICBjb25zdCBzaXplSGVhZGVyVmFsdWUgPSByZXNIZWFkZXJzICYmIHJlc0hlYWRlcnNbJ2NvbnRlbnQtbGVuZ3RoJ11cbiAgICBjb25zdCBzaXplID0gdHlwZW9mIHNpemVIZWFkZXJWYWx1ZSA9PT0gJ251bWJlcicgPyBzaXplSGVhZGVyVmFsdWUgOiB1bmRlZmluZWRcblxuICAgIHJldHVybiB7XG4gICAgICBCdWNrZXQ6IGRlc3RDb25maWcuQnVja2V0LFxuICAgICAgS2V5OiBkZXN0Q29uZmlnLk9iamVjdCxcbiAgICAgIExhc3RNb2RpZmllZDogY29weVJlcy5sYXN0TW9kaWZpZWQsXG4gICAgICBNZXRhRGF0YTogZXh0cmFjdE1ldGFkYXRhKHJlc0hlYWRlcnMgYXMgUmVzcG9uc2VIZWFkZXIpLFxuICAgICAgVmVyc2lvbklkOiBnZXRWZXJzaW9uSWQocmVzSGVhZGVycyBhcyBSZXNwb25zZUhlYWRlciksXG4gICAgICBTb3VyY2VWZXJzaW9uSWQ6IGdldFNvdXJjZVZlcnNpb25JZChyZXNIZWFkZXJzIGFzIFJlc3BvbnNlSGVhZGVyKSxcbiAgICAgIEV0YWc6IHNhbml0aXplRVRhZyhyZXNIZWFkZXJzLmV0YWcpLFxuICAgICAgU2l6ZTogc2l6ZSxcbiAgICB9XG4gIH1cblxuICBhc3luYyBjb3B5T2JqZWN0KHNvdXJjZTogQ29weVNvdXJjZU9wdGlvbnMsIGRlc3Q6IENvcHlEZXN0aW5hdGlvbk9wdGlvbnMpOiBQcm9taXNlPENvcHlPYmplY3RSZXN1bHQ+XG4gIGFzeW5jIGNvcHlPYmplY3QoXG4gICAgdGFyZ2V0QnVja2V0TmFtZTogc3RyaW5nLFxuICAgIHRhcmdldE9iamVjdE5hbWU6IHN0cmluZyxcbiAgICBzb3VyY2VCdWNrZXROYW1lQW5kT2JqZWN0TmFtZTogc3RyaW5nLFxuICAgIGNvbmRpdGlvbnM/OiBDb3B5Q29uZGl0aW9ucyxcbiAgKTogUHJvbWlzZTxDb3B5T2JqZWN0UmVzdWx0PlxuICBhc3luYyBjb3B5T2JqZWN0KC4uLmFsbEFyZ3M6IENvcHlPYmplY3RQYXJhbXMpOiBQcm9taXNlPENvcHlPYmplY3RSZXN1bHQ+IHtcbiAgICBpZiAodHlwZW9mIGFsbEFyZ3NbMF0gPT09ICdzdHJpbmcnKSB7XG4gICAgICBjb25zdCBbdGFyZ2V0QnVja2V0TmFtZSwgdGFyZ2V0T2JqZWN0TmFtZSwgc291cmNlQnVja2V0TmFtZUFuZE9iamVjdE5hbWUsIGNvbmRpdGlvbnNdID0gYWxsQXJncyBhcyBbXG4gICAgICAgIHN0cmluZyxcbiAgICAgICAgc3RyaW5nLFxuICAgICAgICBzdHJpbmcsXG4gICAgICAgIENvcHlDb25kaXRpb25zPyxcbiAgICAgIF1cbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLmNvcHlPYmplY3RWMSh0YXJnZXRCdWNrZXROYW1lLCB0YXJnZXRPYmplY3ROYW1lLCBzb3VyY2VCdWNrZXROYW1lQW5kT2JqZWN0TmFtZSwgY29uZGl0aW9ucylcbiAgICB9XG4gICAgY29uc3QgW3NvdXJjZSwgZGVzdF0gPSBhbGxBcmdzIGFzIFtDb3B5U291cmNlT3B0aW9ucywgQ29weURlc3RpbmF0aW9uT3B0aW9uc11cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5jb3B5T2JqZWN0VjIoc291cmNlLCBkZXN0KVxuICB9XG5cbiAgYXN5bmMgdXBsb2FkUGFydChcbiAgICBwYXJ0Q29uZmlnOiB7XG4gICAgICBidWNrZXROYW1lOiBzdHJpbmdcbiAgICAgIG9iamVjdE5hbWU6IHN0cmluZ1xuICAgICAgdXBsb2FkSUQ6IHN0cmluZ1xuICAgICAgcGFydE51bWJlcjogbnVtYmVyXG4gICAgICBoZWFkZXJzOiBSZXF1ZXN0SGVhZGVyc1xuICAgIH0sXG4gICAgcGF5bG9hZD86IEJpbmFyeSxcbiAgKSB7XG4gICAgY29uc3QgeyBidWNrZXROYW1lLCBvYmplY3ROYW1lLCB1cGxvYWRJRCwgcGFydE51bWJlciwgaGVhZGVycyB9ID0gcGFydENvbmZpZ1xuXG4gICAgY29uc3QgbWV0aG9kID0gJ1BVVCdcbiAgICBjb25zdCBxdWVyeSA9IGB1cGxvYWRJZD0ke3VwbG9hZElEfSZwYXJ0TnVtYmVyPSR7cGFydE51bWJlcn1gXG4gICAgY29uc3QgcmVxdWVzdE9wdGlvbnMgPSB7IG1ldGhvZCwgYnVja2V0TmFtZSwgb2JqZWN0TmFtZTogb2JqZWN0TmFtZSwgcXVlcnksIGhlYWRlcnMgfVxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyhyZXF1ZXN0T3B0aW9ucywgcGF5bG9hZClcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVhZEFzU3RyaW5nKHJlcylcbiAgICBjb25zdCBwYXJ0UmVzID0gdXBsb2FkUGFydFBhcnNlcihib2R5KVxuICAgIGNvbnN0IHBhcnRFdGFnVmFsID0gc2FuaXRpemVFVGFnKHJlcy5oZWFkZXJzLmV0YWcpIHx8IHNhbml0aXplRVRhZyhwYXJ0UmVzLkVUYWcpXG4gICAgcmV0dXJuIHtcbiAgICAgIGV0YWc6IHBhcnRFdGFnVmFsLFxuICAgICAga2V5OiBvYmplY3ROYW1lLFxuICAgICAgcGFydDogcGFydE51bWJlcixcbiAgICB9XG4gIH1cblxuICBhc3luYyBjb21wb3NlT2JqZWN0KFxuICAgIGRlc3RPYmpDb25maWc6IENvcHlEZXN0aW5hdGlvbk9wdGlvbnMsXG4gICAgc291cmNlT2JqTGlzdDogQ29weVNvdXJjZU9wdGlvbnNbXSxcbiAgICB7IG1heENvbmN1cnJlbmN5ID0gMTAgfSA9IHt9LFxuICApOiBQcm9taXNlPGJvb2xlYW4gfCB7IGV0YWc6IHN0cmluZzsgdmVyc2lvbklkOiBzdHJpbmcgfCBudWxsIH0gfCBQcm9taXNlPHZvaWQ+IHwgQ29weU9iamVjdFJlc3VsdD4ge1xuICAgIGNvbnN0IHNvdXJjZUZpbGVzTGVuZ3RoID0gc291cmNlT2JqTGlzdC5sZW5ndGhcblxuICAgIGlmICghQXJyYXkuaXNBcnJheShzb3VyY2VPYmpMaXN0KSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcignc291cmNlQ29uZmlnIHNob3VsZCBhbiBhcnJheSBvZiBDb3B5U291cmNlT3B0aW9ucyAnKVxuICAgIH1cbiAgICBpZiAoIShkZXN0T2JqQ29uZmlnIGluc3RhbmNlb2YgQ29weURlc3RpbmF0aW9uT3B0aW9ucykpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ2Rlc3RDb25maWcgc2hvdWxkIG9mIHR5cGUgQ29weURlc3RpbmF0aW9uT3B0aW9ucyAnKVxuICAgIH1cblxuICAgIGlmIChzb3VyY2VGaWxlc0xlbmd0aCA8IDEgfHwgc291cmNlRmlsZXNMZW5ndGggPiBQQVJUX0NPTlNUUkFJTlRTLk1BWF9QQVJUU19DT1VOVCkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihcbiAgICAgICAgYFwiVGhlcmUgbXVzdCBiZSBhcyBsZWFzdCBvbmUgYW5kIHVwIHRvICR7UEFSVF9DT05TVFJBSU5UUy5NQVhfUEFSVFNfQ09VTlR9IHNvdXJjZSBvYmplY3RzLmAsXG4gICAgICApXG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzb3VyY2VGaWxlc0xlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBzT2JqID0gc291cmNlT2JqTGlzdFtpXSBhcyBDb3B5U291cmNlT3B0aW9uc1xuICAgICAgaWYgKCFzT2JqLnZhbGlkYXRlKCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCEoZGVzdE9iakNvbmZpZyBhcyBDb3B5RGVzdGluYXRpb25PcHRpb25zKS52YWxpZGF0ZSgpKSB7XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG5cbiAgICBjb25zdCBnZXRTdGF0T3B0aW9ucyA9IChzcmNDb25maWc6IENvcHlTb3VyY2VPcHRpb25zKSA9PiB7XG4gICAgICBsZXQgc3RhdE9wdHMgPSB7fVxuICAgICAgaWYgKCFfLmlzRW1wdHkoc3JjQ29uZmlnLlZlcnNpb25JRCkpIHtcbiAgICAgICAgc3RhdE9wdHMgPSB7XG4gICAgICAgICAgdmVyc2lvbklkOiBzcmNDb25maWcuVmVyc2lvbklELFxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gc3RhdE9wdHNcbiAgICB9XG4gICAgY29uc3Qgc3JjT2JqZWN0U2l6ZXM6IG51bWJlcltdID0gW11cbiAgICBsZXQgdG90YWxTaXplID0gMFxuICAgIGxldCB0b3RhbFBhcnRzID0gMFxuXG4gICAgY29uc3Qgc291cmNlT2JqU3RhdHMgPSBzb3VyY2VPYmpMaXN0Lm1hcCgoc3JjSXRlbSkgPT5cbiAgICAgIHRoaXMuc3RhdE9iamVjdChzcmNJdGVtLkJ1Y2tldCwgc3JjSXRlbS5PYmplY3QsIGdldFN0YXRPcHRpb25zKHNyY0l0ZW0pKSxcbiAgICApXG5cbiAgICBjb25zdCBzcmNPYmplY3RJbmZvcyA9IGF3YWl0IFByb21pc2UuYWxsKHNvdXJjZU9ialN0YXRzKVxuXG4gICAgY29uc3QgdmFsaWRhdGVkU3RhdHMgPSBzcmNPYmplY3RJbmZvcy5tYXAoKHJlc0l0ZW1TdGF0LCBpbmRleCkgPT4ge1xuICAgICAgY29uc3Qgc3JjQ29uZmlnOiBDb3B5U291cmNlT3B0aW9ucyB8IHVuZGVmaW5lZCA9IHNvdXJjZU9iakxpc3RbaW5kZXhdXG5cbiAgICAgIGxldCBzcmNDb3B5U2l6ZSA9IHJlc0l0ZW1TdGF0LnNpemVcbiAgICAgIC8vIENoZWNrIGlmIGEgc2VnbWVudCBpcyBzcGVjaWZpZWQsIGFuZCBpZiBzbywgaXMgdGhlXG4gICAgICAvLyBzZWdtZW50IHdpdGhpbiBvYmplY3QgYm91bmRzP1xuICAgICAgaWYgKHNyY0NvbmZpZyAmJiBzcmNDb25maWcuTWF0Y2hSYW5nZSkge1xuICAgICAgICAvLyBTaW5jZSByYW5nZSBpcyBzcGVjaWZpZWQsXG4gICAgICAgIC8vICAgIDAgPD0gc3JjLnNyY1N0YXJ0IDw9IHNyYy5zcmNFbmRcbiAgICAgICAgLy8gc28gb25seSBpbnZhbGlkIGNhc2UgdG8gY2hlY2sgaXM6XG4gICAgICAgIGNvbnN0IHNyY1N0YXJ0ID0gc3JjQ29uZmlnLlN0YXJ0XG4gICAgICAgIGNvbnN0IHNyY0VuZCA9IHNyY0NvbmZpZy5FbmRcbiAgICAgICAgaWYgKHNyY0VuZCA+PSBzcmNDb3B5U2l6ZSB8fCBzcmNTdGFydCA8IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKFxuICAgICAgICAgICAgYENvcHlTcmNPcHRpb25zICR7aW5kZXh9IGhhcyBpbnZhbGlkIHNlZ21lbnQtdG8tY29weSBbJHtzcmNTdGFydH0sICR7c3JjRW5kfV0gKHNpemUgaXMgJHtzcmNDb3B5U2l6ZX0pYCxcbiAgICAgICAgICApXG4gICAgICAgIH1cbiAgICAgICAgc3JjQ29weVNpemUgPSBzcmNFbmQgLSBzcmNTdGFydCArIDFcbiAgICAgIH1cblxuICAgICAgLy8gT25seSB0aGUgbGFzdCBzb3VyY2UgbWF5IGJlIGxlc3MgdGhhbiBgYWJzTWluUGFydFNpemVgXG4gICAgICBpZiAoc3JjQ29weVNpemUgPCBQQVJUX0NPTlNUUkFJTlRTLkFCU19NSU5fUEFSVF9TSVpFICYmIGluZGV4IDwgc291cmNlRmlsZXNMZW5ndGggLSAxKSB7XG4gICAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoXG4gICAgICAgICAgYENvcHlTcmNPcHRpb25zICR7aW5kZXh9IGlzIHRvbyBzbWFsbCAoJHtzcmNDb3B5U2l6ZX0pIGFuZCBpdCBpcyBub3QgdGhlIGxhc3QgcGFydC5gLFxuICAgICAgICApXG4gICAgICB9XG5cbiAgICAgIC8vIElzIGRhdGEgdG8gY29weSB0b28gbGFyZ2U/XG4gICAgICB0b3RhbFNpemUgKz0gc3JjQ29weVNpemVcbiAgICAgIGlmICh0b3RhbFNpemUgPiBQQVJUX0NPTlNUUkFJTlRTLk1BWF9NVUxUSVBBUlRfUFVUX09CSkVDVF9TSVpFKSB7XG4gICAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoYENhbm5vdCBjb21wb3NlIGFuIG9iamVjdCBvZiBzaXplICR7dG90YWxTaXplfSAoPiA1VGlCKWApXG4gICAgICB9XG5cbiAgICAgIC8vIHJlY29yZCBzb3VyY2Ugc2l6ZVxuICAgICAgc3JjT2JqZWN0U2l6ZXNbaW5kZXhdID0gc3JjQ29weVNpemVcblxuICAgICAgLy8gY2FsY3VsYXRlIHBhcnRzIG5lZWRlZCBmb3IgY3VycmVudCBzb3VyY2VcbiAgICAgIHRvdGFsUGFydHMgKz0gcGFydHNSZXF1aXJlZChzcmNDb3B5U2l6ZSlcbiAgICAgIC8vIERvIHdlIG5lZWQgbW9yZSBwYXJ0cyB0aGFuIHdlIGFyZSBhbGxvd2VkP1xuICAgICAgaWYgKHRvdGFsUGFydHMgPiBQQVJUX0NPTlNUUkFJTlRTLk1BWF9QQVJUU19DT1VOVCkge1xuICAgICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKFxuICAgICAgICAgIGBZb3VyIHByb3Bvc2VkIGNvbXBvc2Ugb2JqZWN0IHJlcXVpcmVzIG1vcmUgdGhhbiAke1BBUlRfQ09OU1RSQUlOVFMuTUFYX1BBUlRTX0NPVU5UfSBwYXJ0c2AsXG4gICAgICAgIClcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlc0l0ZW1TdGF0XG4gICAgfSlcblxuICAgIGlmICgodG90YWxQYXJ0cyA9PT0gMSAmJiB0b3RhbFNpemUgPD0gUEFSVF9DT05TVFJBSU5UUy5NQVhfUEFSVF9TSVpFKSB8fCB0b3RhbFNpemUgPT09IDApIHtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLmNvcHlPYmplY3Qoc291cmNlT2JqTGlzdFswXSBhcyBDb3B5U291cmNlT3B0aW9ucywgZGVzdE9iakNvbmZpZykgLy8gdXNlIGNvcHlPYmplY3RWMlxuICAgIH1cblxuICAgIC8vIHByZXNlcnZlIGV0YWcgdG8gYXZvaWQgbW9kaWZpY2F0aW9uIG9mIG9iamVjdCB3aGlsZSBjb3B5aW5nLlxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc291cmNlRmlsZXNMZW5ndGg7IGkrKykge1xuICAgICAgOyhzb3VyY2VPYmpMaXN0W2ldIGFzIENvcHlTb3VyY2VPcHRpb25zKS5NYXRjaEVUYWcgPSAodmFsaWRhdGVkU3RhdHNbaV0gYXMgQnVja2V0SXRlbVN0YXQpLmV0YWdcbiAgICB9XG5cbiAgICBjb25zdCBzcGxpdFBhcnRTaXplTGlzdCA9IHZhbGlkYXRlZFN0YXRzLm1hcCgocmVzSXRlbVN0YXQsIGlkeCkgPT4ge1xuICAgICAgcmV0dXJuIGNhbGN1bGF0ZUV2ZW5TcGxpdHMoc3JjT2JqZWN0U2l6ZXNbaWR4XSBhcyBudW1iZXIsIHNvdXJjZU9iakxpc3RbaWR4XSBhcyBDb3B5U291cmNlT3B0aW9ucylcbiAgICB9KVxuXG4gICAgY29uc3QgZ2V0VXBsb2FkUGFydENvbmZpZ0xpc3QgPSAodXBsb2FkSWQ6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgdXBsb2FkUGFydENvbmZpZ0xpc3Q6IFVwbG9hZFBhcnRDb25maWdbXSA9IFtdXG5cbiAgICAgIHNwbGl0UGFydFNpemVMaXN0LmZvckVhY2goKHNwbGl0U2l6ZSwgc3BsaXRJbmRleDogbnVtYmVyKSA9PiB7XG4gICAgICAgIGlmIChzcGxpdFNpemUpIHtcbiAgICAgICAgICBjb25zdCB7IHN0YXJ0SW5kZXg6IHN0YXJ0SWR4LCBlbmRJbmRleDogZW5kSWR4LCBvYmpJbmZvOiBvYmpDb25maWcgfSA9IHNwbGl0U2l6ZVxuXG4gICAgICAgICAgY29uc3QgcGFydEluZGV4ID0gc3BsaXRJbmRleCArIDEgLy8gcGFydCBpbmRleCBzdGFydHMgZnJvbSAxLlxuICAgICAgICAgIGNvbnN0IHRvdGFsVXBsb2FkcyA9IEFycmF5LmZyb20oc3RhcnRJZHgpXG5cbiAgICAgICAgICBjb25zdCBoZWFkZXJzID0gKHNvdXJjZU9iakxpc3Rbc3BsaXRJbmRleF0gYXMgQ29weVNvdXJjZU9wdGlvbnMpLmdldEhlYWRlcnMoKVxuXG4gICAgICAgICAgdG90YWxVcGxvYWRzLmZvckVhY2goKHNwbGl0U3RhcnQsIHVwbGRDdHJJZHgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHNwbGl0RW5kID0gZW5kSWR4W3VwbGRDdHJJZHhdXG5cbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZU9iaiA9IGAke29iakNvbmZpZy5CdWNrZXR9LyR7b2JqQ29uZmlnLk9iamVjdH1gXG4gICAgICAgICAgICBoZWFkZXJzWyd4LWFtei1jb3B5LXNvdXJjZSddID0gYCR7c291cmNlT2JqfWBcbiAgICAgICAgICAgIGhlYWRlcnNbJ3gtYW16LWNvcHktc291cmNlLXJhbmdlJ10gPSBgYnl0ZXM9JHtzcGxpdFN0YXJ0fS0ke3NwbGl0RW5kfWBcblxuICAgICAgICAgICAgY29uc3QgdXBsb2FkUGFydENvbmZpZyA9IHtcbiAgICAgICAgICAgICAgYnVja2V0TmFtZTogZGVzdE9iakNvbmZpZy5CdWNrZXQsXG4gICAgICAgICAgICAgIG9iamVjdE5hbWU6IGRlc3RPYmpDb25maWcuT2JqZWN0LFxuICAgICAgICAgICAgICB1cGxvYWRJRDogdXBsb2FkSWQsXG4gICAgICAgICAgICAgIHBhcnROdW1iZXI6IHBhcnRJbmRleCxcbiAgICAgICAgICAgICAgaGVhZGVyczogaGVhZGVycyxcbiAgICAgICAgICAgICAgc291cmNlT2JqOiBzb3VyY2VPYmosXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHVwbG9hZFBhcnRDb25maWdMaXN0LnB1c2godXBsb2FkUGFydENvbmZpZylcbiAgICAgICAgICB9KVxuICAgICAgICB9XG4gICAgICB9KVxuXG4gICAgICByZXR1cm4gdXBsb2FkUGFydENvbmZpZ0xpc3RcbiAgICB9XG5cbiAgICBjb25zdCB1cGxvYWRBbGxQYXJ0cyA9IGFzeW5jICh1cGxvYWRMaXN0OiBVcGxvYWRQYXJ0Q29uZmlnW10pID0+IHtcbiAgICAgIGNvbnN0IHBhcnRVcGxvYWRzOiBBd2FpdGVkPFJldHVyblR5cGU8dHlwZW9mIHRoaXMudXBsb2FkUGFydD4+W10gPSBbXVxuXG4gICAgICAvLyBQcm9jZXNzIHVwbG9hZCBwYXJ0cyBpbiBiYXRjaGVzIHRvIGF2b2lkIHRvbyBtYW55IGNvbmN1cnJlbnQgcmVxdWVzdHNcbiAgICAgIGZvciAoY29uc3QgYmF0Y2ggb2YgXy5jaHVuayh1cGxvYWRMaXN0LCBtYXhDb25jdXJyZW5jeSkpIHtcbiAgICAgICAgY29uc3QgYmF0Y2hSZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoYmF0Y2gubWFwKChpdGVtKSA9PiB0aGlzLnVwbG9hZFBhcnQoaXRlbSkpKVxuXG4gICAgICAgIHBhcnRVcGxvYWRzLnB1c2goLi4uYmF0Y2hSZXN1bHRzKVxuICAgICAgfVxuXG4gICAgICAvLyBQcm9jZXNzIHJlc3VsdHMgaGVyZSBpZiBuZWVkZWRcbiAgICAgIHJldHVybiBwYXJ0VXBsb2Fkc1xuICAgIH1cblxuICAgIGNvbnN0IHBlcmZvcm1VcGxvYWRQYXJ0cyA9IGFzeW5jICh1cGxvYWRJZDogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCB1cGxvYWRMaXN0ID0gZ2V0VXBsb2FkUGFydENvbmZpZ0xpc3QodXBsb2FkSWQpXG4gICAgICBjb25zdCBwYXJ0c1JlcyA9IGF3YWl0IHVwbG9hZEFsbFBhcnRzKHVwbG9hZExpc3QpXG4gICAgICByZXR1cm4gcGFydHNSZXMubWFwKChwYXJ0Q29weSkgPT4gKHsgZXRhZzogcGFydENvcHkuZXRhZywgcGFydDogcGFydENvcHkucGFydCB9KSlcbiAgICB9XG5cbiAgICBjb25zdCBuZXdVcGxvYWRIZWFkZXJzID0gZGVzdE9iakNvbmZpZy5nZXRIZWFkZXJzKClcblxuICAgIGNvbnN0IHVwbG9hZElkID0gYXdhaXQgdGhpcy5pbml0aWF0ZU5ld011bHRpcGFydFVwbG9hZChkZXN0T2JqQ29uZmlnLkJ1Y2tldCwgZGVzdE9iakNvbmZpZy5PYmplY3QsIG5ld1VwbG9hZEhlYWRlcnMpXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHBhcnRzRG9uZSA9IGF3YWl0IHBlcmZvcm1VcGxvYWRQYXJ0cyh1cGxvYWRJZClcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLmNvbXBsZXRlTXVsdGlwYXJ0VXBsb2FkKGRlc3RPYmpDb25maWcuQnVja2V0LCBkZXN0T2JqQ29uZmlnLk9iamVjdCwgdXBsb2FkSWQsIHBhcnRzRG9uZSlcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLmFib3J0TXVsdGlwYXJ0VXBsb2FkKGRlc3RPYmpDb25maWcuQnVja2V0LCBkZXN0T2JqQ29uZmlnLk9iamVjdCwgdXBsb2FkSWQpXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgcHJlc2lnbmVkVXJsKFxuICAgIG1ldGhvZDogc3RyaW5nLFxuICAgIGJ1Y2tldE5hbWU6IHN0cmluZyxcbiAgICBvYmplY3ROYW1lOiBzdHJpbmcsXG4gICAgZXhwaXJlcz86IG51bWJlciB8IFByZVNpZ25SZXF1ZXN0UGFyYW1zIHwgdW5kZWZpbmVkLFxuICAgIHJlcVBhcmFtcz86IFByZVNpZ25SZXF1ZXN0UGFyYW1zIHwgRGF0ZSxcbiAgICByZXF1ZXN0RGF0ZT86IERhdGUsXG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgaWYgKHRoaXMuYW5vbnltb3VzKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkFub255bW91c1JlcXVlc3RFcnJvcihgUHJlc2lnbmVkICR7bWV0aG9kfSB1cmwgY2Fubm90IGJlIGdlbmVyYXRlZCBmb3IgYW5vbnltb3VzIHJlcXVlc3RzYClcbiAgICB9XG5cbiAgICBpZiAoIWV4cGlyZXMpIHtcbiAgICAgIGV4cGlyZXMgPSBQUkVTSUdOX0VYUElSWV9EQVlTX01BWFxuICAgIH1cbiAgICBpZiAoIXJlcVBhcmFtcykge1xuICAgICAgcmVxUGFyYW1zID0ge31cbiAgICB9XG4gICAgaWYgKCFyZXF1ZXN0RGF0ZSkge1xuICAgICAgcmVxdWVzdERhdGUgPSBuZXcgRGF0ZSgpXG4gICAgfVxuXG4gICAgLy8gVHlwZSBhc3NlcnRpb25zXG4gICAgaWYgKGV4cGlyZXMgJiYgdHlwZW9mIGV4cGlyZXMgIT09ICdudW1iZXInKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdleHBpcmVzIHNob3VsZCBiZSBvZiB0eXBlIFwibnVtYmVyXCInKVxuICAgIH1cbiAgICBpZiAocmVxUGFyYW1zICYmIHR5cGVvZiByZXFQYXJhbXMgIT09ICdvYmplY3QnKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZXFQYXJhbXMgc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gICAgfVxuICAgIGlmICgocmVxdWVzdERhdGUgJiYgIShyZXF1ZXN0RGF0ZSBpbnN0YW5jZW9mIERhdGUpKSB8fCAocmVxdWVzdERhdGUgJiYgaXNOYU4ocmVxdWVzdERhdGU/LmdldFRpbWUoKSkpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZXF1ZXN0RGF0ZSBzaG91bGQgYmUgb2YgdHlwZSBcIkRhdGVcIiBhbmQgdmFsaWQnKVxuICAgIH1cblxuICAgIGNvbnN0IHF1ZXJ5ID0gcmVxUGFyYW1zID8gcXMuc3RyaW5naWZ5KHJlcVBhcmFtcykgOiB1bmRlZmluZWRcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZWdpb24gPSBhd2FpdCB0aGlzLmdldEJ1Y2tldFJlZ2lvbkFzeW5jKGJ1Y2tldE5hbWUpXG4gICAgICBhd2FpdCB0aGlzLmNoZWNrQW5kUmVmcmVzaENyZWRzKClcbiAgICAgIGNvbnN0IHJlcU9wdGlvbnMgPSB0aGlzLmdldFJlcXVlc3RPcHRpb25zKHsgbWV0aG9kLCByZWdpb24sIGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIHF1ZXJ5IH0pXG5cbiAgICAgIHJldHVybiBwcmVzaWduU2lnbmF0dXJlVjQoXG4gICAgICAgIHJlcU9wdGlvbnMsXG4gICAgICAgIHRoaXMuYWNjZXNzS2V5LFxuICAgICAgICB0aGlzLnNlY3JldEtleSxcbiAgICAgICAgdGhpcy5zZXNzaW9uVG9rZW4sXG4gICAgICAgIHJlZ2lvbixcbiAgICAgICAgcmVxdWVzdERhdGUsXG4gICAgICAgIGV4cGlyZXMsXG4gICAgICApXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAoZXJyIGluc3RhbmNlb2YgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihgVW5hYmxlIHRvIGdldCBidWNrZXQgcmVnaW9uIGZvciAke2J1Y2tldE5hbWV9LmApXG4gICAgICB9XG5cbiAgICAgIHRocm93IGVyclxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHByZXNpZ25lZEdldE9iamVjdChcbiAgICBidWNrZXROYW1lOiBzdHJpbmcsXG4gICAgb2JqZWN0TmFtZTogc3RyaW5nLFxuICAgIGV4cGlyZXM/OiBudW1iZXIsXG4gICAgcmVzcEhlYWRlcnM/OiBQcmVTaWduUmVxdWVzdFBhcmFtcyB8IERhdGUsXG4gICAgcmVxdWVzdERhdGU/OiBEYXRlLFxuICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNWYWxpZE9iamVjdE5hbWUob2JqZWN0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZE9iamVjdE5hbWVFcnJvcihgSW52YWxpZCBvYmplY3QgbmFtZTogJHtvYmplY3ROYW1lfWApXG4gICAgfVxuXG4gICAgY29uc3QgdmFsaWRSZXNwSGVhZGVycyA9IFtcbiAgICAgICdyZXNwb25zZS1jb250ZW50LXR5cGUnLFxuICAgICAgJ3Jlc3BvbnNlLWNvbnRlbnQtbGFuZ3VhZ2UnLFxuICAgICAgJ3Jlc3BvbnNlLWV4cGlyZXMnLFxuICAgICAgJ3Jlc3BvbnNlLWNhY2hlLWNvbnRyb2wnLFxuICAgICAgJ3Jlc3BvbnNlLWNvbnRlbnQtZGlzcG9zaXRpb24nLFxuICAgICAgJ3Jlc3BvbnNlLWNvbnRlbnQtZW5jb2RpbmcnLFxuICAgIF1cbiAgICB2YWxpZFJlc3BIZWFkZXJzLmZvckVhY2goKGhlYWRlcikgPT4ge1xuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgaWYgKHJlc3BIZWFkZXJzICE9PSB1bmRlZmluZWQgJiYgcmVzcEhlYWRlcnNbaGVhZGVyXSAhPT0gdW5kZWZpbmVkICYmICFpc1N0cmluZyhyZXNwSGVhZGVyc1toZWFkZXJdKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGByZXNwb25zZSBoZWFkZXIgJHtoZWFkZXJ9IHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCJgKVxuICAgICAgfVxuICAgIH0pXG4gICAgcmV0dXJuIHRoaXMucHJlc2lnbmVkVXJsKCdHRVQnLCBidWNrZXROYW1lLCBvYmplY3ROYW1lLCBleHBpcmVzLCByZXNwSGVhZGVycywgcmVxdWVzdERhdGUpXG4gIH1cblxuICBhc3luYyBwcmVzaWduZWRQdXRPYmplY3QoYnVja2V0TmFtZTogc3RyaW5nLCBvYmplY3ROYW1lOiBzdHJpbmcsIGV4cGlyZXM/OiBudW1iZXIpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcihgSW52YWxpZCBidWNrZXQgbmFtZTogJHtidWNrZXROYW1lfWApXG4gICAgfVxuICAgIGlmICghaXNWYWxpZE9iamVjdE5hbWUob2JqZWN0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZE9iamVjdE5hbWVFcnJvcihgSW52YWxpZCBvYmplY3QgbmFtZTogJHtvYmplY3ROYW1lfWApXG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucHJlc2lnbmVkVXJsKCdQVVQnLCBidWNrZXROYW1lLCBvYmplY3ROYW1lLCBleHBpcmVzKVxuICB9XG5cbiAgbmV3UG9zdFBvbGljeSgpOiBQb3N0UG9saWN5IHtcbiAgICByZXR1cm4gbmV3IFBvc3RQb2xpY3koKVxuICB9XG5cbiAgYXN5bmMgcHJlc2lnbmVkUG9zdFBvbGljeShwb3N0UG9saWN5OiBQb3N0UG9saWN5KTogUHJvbWlzZTxQb3N0UG9saWN5UmVzdWx0PiB7XG4gICAgaWYgKHRoaXMuYW5vbnltb3VzKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkFub255bW91c1JlcXVlc3RFcnJvcignUHJlc2lnbmVkIFBPU1QgcG9saWN5IGNhbm5vdCBiZSBnZW5lcmF0ZWQgZm9yIGFub255bW91cyByZXF1ZXN0cycpXG4gICAgfVxuICAgIGlmICghaXNPYmplY3QocG9zdFBvbGljeSkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3Bvc3RQb2xpY3kgc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gICAgfVxuICAgIGNvbnN0IGJ1Y2tldE5hbWUgPSBwb3N0UG9saWN5LmZvcm1EYXRhLmJ1Y2tldCBhcyBzdHJpbmdcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVnaW9uID0gYXdhaXQgdGhpcy5nZXRCdWNrZXRSZWdpb25Bc3luYyhidWNrZXROYW1lKVxuXG4gICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoKVxuICAgICAgY29uc3QgZGF0ZVN0ciA9IG1ha2VEYXRlTG9uZyhkYXRlKVxuICAgICAgYXdhaXQgdGhpcy5jaGVja0FuZFJlZnJlc2hDcmVkcygpXG5cbiAgICAgIGlmICghcG9zdFBvbGljeS5wb2xpY3kuZXhwaXJhdGlvbikge1xuICAgICAgICAvLyAnZXhwaXJhdGlvbicgaXMgbWFuZGF0b3J5IGZpZWxkIGZvciBTMy5cbiAgICAgICAgLy8gU2V0IGRlZmF1bHQgZXhwaXJhdGlvbiBkYXRlIG9mIDcgZGF5cy5cbiAgICAgICAgY29uc3QgZXhwaXJlcyA9IG5ldyBEYXRlKClcbiAgICAgICAgZXhwaXJlcy5zZXRTZWNvbmRzKFBSRVNJR05fRVhQSVJZX0RBWVNfTUFYKVxuICAgICAgICBwb3N0UG9saWN5LnNldEV4cGlyZXMoZXhwaXJlcylcbiAgICAgIH1cblxuICAgICAgcG9zdFBvbGljeS5wb2xpY3kuY29uZGl0aW9ucy5wdXNoKFsnZXEnLCAnJHgtYW16LWRhdGUnLCBkYXRlU3RyXSlcbiAgICAgIHBvc3RQb2xpY3kuZm9ybURhdGFbJ3gtYW16LWRhdGUnXSA9IGRhdGVTdHJcblxuICAgICAgcG9zdFBvbGljeS5wb2xpY3kuY29uZGl0aW9ucy5wdXNoKFsnZXEnLCAnJHgtYW16LWFsZ29yaXRobScsICdBV1M0LUhNQUMtU0hBMjU2J10pXG4gICAgICBwb3N0UG9saWN5LmZvcm1EYXRhWyd4LWFtei1hbGdvcml0aG0nXSA9ICdBV1M0LUhNQUMtU0hBMjU2J1xuXG4gICAgICBwb3N0UG9saWN5LnBvbGljeS5jb25kaXRpb25zLnB1c2goWydlcScsICckeC1hbXotY3JlZGVudGlhbCcsIHRoaXMuYWNjZXNzS2V5ICsgJy8nICsgZ2V0U2NvcGUocmVnaW9uLCBkYXRlKV0pXG4gICAgICBwb3N0UG9saWN5LmZvcm1EYXRhWyd4LWFtei1jcmVkZW50aWFsJ10gPSB0aGlzLmFjY2Vzc0tleSArICcvJyArIGdldFNjb3BlKHJlZ2lvbiwgZGF0ZSlcblxuICAgICAgaWYgKHRoaXMuc2Vzc2lvblRva2VuKSB7XG4gICAgICAgIHBvc3RQb2xpY3kucG9saWN5LmNvbmRpdGlvbnMucHVzaChbJ2VxJywgJyR4LWFtei1zZWN1cml0eS10b2tlbicsIHRoaXMuc2Vzc2lvblRva2VuXSlcbiAgICAgICAgcG9zdFBvbGljeS5mb3JtRGF0YVsneC1hbXotc2VjdXJpdHktdG9rZW4nXSA9IHRoaXMuc2Vzc2lvblRva2VuXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHBvbGljeUJhc2U2NCA9IEJ1ZmZlci5mcm9tKEpTT04uc3RyaW5naWZ5KHBvc3RQb2xpY3kucG9saWN5KSkudG9TdHJpbmcoJ2Jhc2U2NCcpXG5cbiAgICAgIHBvc3RQb2xpY3kuZm9ybURhdGEucG9saWN5ID0gcG9saWN5QmFzZTY0XG5cbiAgICAgIHBvc3RQb2xpY3kuZm9ybURhdGFbJ3gtYW16LXNpZ25hdHVyZSddID0gcG9zdFByZXNpZ25TaWduYXR1cmVWNChyZWdpb24sIGRhdGUsIHRoaXMuc2VjcmV0S2V5LCBwb2xpY3lCYXNlNjQpXG4gICAgICBjb25zdCBvcHRzID0ge1xuICAgICAgICByZWdpb246IHJlZ2lvbixcbiAgICAgICAgYnVja2V0TmFtZTogYnVja2V0TmFtZSxcbiAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICB9XG4gICAgICBjb25zdCByZXFPcHRpb25zID0gdGhpcy5nZXRSZXF1ZXN0T3B0aW9ucyhvcHRzKVxuICAgICAgY29uc3QgcG9ydFN0ciA9IHRoaXMucG9ydCA9PSA4MCB8fCB0aGlzLnBvcnQgPT09IDQ0MyA/ICcnIDogYDoke3RoaXMucG9ydC50b1N0cmluZygpfWBcbiAgICAgIGNvbnN0IHVybFN0ciA9IGAke3JlcU9wdGlvbnMucHJvdG9jb2x9Ly8ke3JlcU9wdGlvbnMuaG9zdH0ke3BvcnRTdHJ9JHtyZXFPcHRpb25zLnBhdGh9YFxuICAgICAgcmV0dXJuIHsgcG9zdFVSTDogdXJsU3RyLCBmb3JtRGF0YTogcG9zdFBvbGljeS5mb3JtRGF0YSB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAoZXJyIGluc3RhbmNlb2YgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihgVW5hYmxlIHRvIGdldCBidWNrZXQgcmVnaW9uIGZvciAke2J1Y2tldE5hbWV9LmApXG4gICAgICB9XG5cbiAgICAgIHRocm93IGVyclxuICAgIH1cbiAgfVxuICAvLyBsaXN0IGEgYmF0Y2ggb2Ygb2JqZWN0c1xuICBhc3luYyBsaXN0T2JqZWN0c1F1ZXJ5KGJ1Y2tldE5hbWU6IHN0cmluZywgcHJlZml4Pzogc3RyaW5nLCBtYXJrZXI/OiBzdHJpbmcsIGxpc3RRdWVyeU9wdHM/OiBMaXN0T2JqZWN0UXVlcnlPcHRzKSB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyhwcmVmaXgpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdwcmVmaXggc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIGlmIChtYXJrZXIgJiYgIWlzU3RyaW5nKG1hcmtlcikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ21hcmtlciBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgICB9XG5cbiAgICBpZiAobGlzdFF1ZXJ5T3B0cyAmJiAhaXNPYmplY3QobGlzdFF1ZXJ5T3B0cykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2xpc3RRdWVyeU9wdHMgc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gICAgfVxuICAgIGxldCB7IERlbGltaXRlciwgTWF4S2V5cywgSW5jbHVkZVZlcnNpb24sIHZlcnNpb25JZE1hcmtlciwga2V5TWFya2VyIH0gPSBsaXN0UXVlcnlPcHRzIGFzIExpc3RPYmplY3RRdWVyeU9wdHNcblxuICAgIGlmICghaXNTdHJpbmcoRGVsaW1pdGVyKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignRGVsaW1pdGVyIHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICAgIH1cbiAgICBpZiAoIWlzTnVtYmVyKE1heEtleXMpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdNYXhLZXlzIHNob3VsZCBiZSBvZiB0eXBlIFwibnVtYmVyXCInKVxuICAgIH1cblxuICAgIGNvbnN0IHF1ZXJpZXMgPSBbXVxuICAgIC8vIGVzY2FwZSBldmVyeSB2YWx1ZSBpbiBxdWVyeSBzdHJpbmcsIGV4Y2VwdCBtYXhLZXlzXG4gICAgcXVlcmllcy5wdXNoKGBwcmVmaXg9JHt1cmlFc2NhcGUocHJlZml4KX1gKVxuICAgIHF1ZXJpZXMucHVzaChgZGVsaW1pdGVyPSR7dXJpRXNjYXBlKERlbGltaXRlcil9YClcbiAgICBxdWVyaWVzLnB1c2goYGVuY29kaW5nLXR5cGU9dXJsYClcblxuICAgIGlmIChJbmNsdWRlVmVyc2lvbikge1xuICAgICAgcXVlcmllcy5wdXNoKGB2ZXJzaW9uc2ApXG4gICAgfVxuXG4gICAgaWYgKEluY2x1ZGVWZXJzaW9uKSB7XG4gICAgICAvLyB2MSB2ZXJzaW9uIGxpc3RpbmcuLlxuICAgICAgaWYgKGtleU1hcmtlcikge1xuICAgICAgICBxdWVyaWVzLnB1c2goYGtleS1tYXJrZXI9JHtrZXlNYXJrZXJ9YClcbiAgICAgIH1cbiAgICAgIGlmICh2ZXJzaW9uSWRNYXJrZXIpIHtcbiAgICAgICAgcXVlcmllcy5wdXNoKGB2ZXJzaW9uLWlkLW1hcmtlcj0ke3ZlcnNpb25JZE1hcmtlcn1gKVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAobWFya2VyKSB7XG4gICAgICBtYXJrZXIgPSB1cmlFc2NhcGUobWFya2VyKVxuICAgICAgcXVlcmllcy5wdXNoKGBtYXJrZXI9JHttYXJrZXJ9YClcbiAgICB9XG5cbiAgICAvLyBubyBuZWVkIHRvIGVzY2FwZSBtYXhLZXlzXG4gICAgaWYgKE1heEtleXMpIHtcbiAgICAgIGlmIChNYXhLZXlzID49IDEwMDApIHtcbiAgICAgICAgTWF4S2V5cyA9IDEwMDBcbiAgICAgIH1cbiAgICAgIHF1ZXJpZXMucHVzaChgbWF4LWtleXM9JHtNYXhLZXlzfWApXG4gICAgfVxuICAgIHF1ZXJpZXMuc29ydCgpXG4gICAgbGV0IHF1ZXJ5ID0gJydcbiAgICBpZiAocXVlcmllcy5sZW5ndGggPiAwKSB7XG4gICAgICBxdWVyeSA9IGAke3F1ZXJpZXMuam9pbignJicpfWBcbiAgICB9XG5cbiAgICBjb25zdCBtZXRob2QgPSAnR0VUJ1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfSlcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVhZEFzU3RyaW5nKHJlcylcbiAgICBjb25zdCBsaXN0UXJ5TGlzdCA9IHBhcnNlTGlzdE9iamVjdHMoYm9keSlcbiAgICByZXR1cm4gbGlzdFFyeUxpc3RcbiAgfVxuXG4gIGxpc3RPYmplY3RzKFxuICAgIGJ1Y2tldE5hbWU6IHN0cmluZyxcbiAgICBwcmVmaXg/OiBzdHJpbmcsXG4gICAgcmVjdXJzaXZlPzogYm9vbGVhbixcbiAgICBsaXN0T3B0cz86IExpc3RPYmplY3RRdWVyeU9wdHMgfCB1bmRlZmluZWQsXG4gICk6IEJ1Y2tldFN0cmVhbTxPYmplY3RJbmZvPiB7XG4gICAgaWYgKHByZWZpeCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcmVmaXggPSAnJ1xuICAgIH1cbiAgICBpZiAocmVjdXJzaXZlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJlY3Vyc2l2ZSA9IGZhbHNlXG4gICAgfVxuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNWYWxpZFByZWZpeChwcmVmaXgpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRQcmVmaXhFcnJvcihgSW52YWxpZCBwcmVmaXggOiAke3ByZWZpeH1gKVxuICAgIH1cbiAgICBpZiAoIWlzU3RyaW5nKHByZWZpeCkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ByZWZpeCBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgICB9XG4gICAgaWYgKCFpc0Jvb2xlYW4ocmVjdXJzaXZlKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncmVjdXJzaXZlIHNob3VsZCBiZSBvZiB0eXBlIFwiYm9vbGVhblwiJylcbiAgICB9XG4gICAgaWYgKGxpc3RPcHRzICYmICFpc09iamVjdChsaXN0T3B0cykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2xpc3RPcHRzIHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICAgIH1cbiAgICBsZXQgbWFya2VyOiBzdHJpbmcgfCB1bmRlZmluZWQgPSAnJ1xuICAgIGxldCBrZXlNYXJrZXI6IHN0cmluZyB8IHVuZGVmaW5lZCA9ICcnXG4gICAgbGV0IHZlcnNpb25JZE1hcmtlcjogc3RyaW5nIHwgdW5kZWZpbmVkID0gJydcbiAgICBsZXQgb2JqZWN0czogT2JqZWN0SW5mb1tdID0gW11cbiAgICBsZXQgZW5kZWQgPSBmYWxzZVxuICAgIGNvbnN0IHJlYWRTdHJlYW06IHN0cmVhbS5SZWFkYWJsZSA9IG5ldyBzdHJlYW0uUmVhZGFibGUoeyBvYmplY3RNb2RlOiB0cnVlIH0pXG4gICAgcmVhZFN0cmVhbS5fcmVhZCA9IGFzeW5jICgpID0+IHtcbiAgICAgIC8vIHB1c2ggb25lIG9iamVjdCBwZXIgX3JlYWQoKVxuICAgICAgaWYgKG9iamVjdHMubGVuZ3RoKSB7XG4gICAgICAgIHJlYWRTdHJlYW0ucHVzaChvYmplY3RzLnNoaWZ0KCkpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgICAgaWYgKGVuZGVkKSB7XG4gICAgICAgIHJldHVybiByZWFkU3RyZWFtLnB1c2gobnVsbClcbiAgICAgIH1cblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgbGlzdFF1ZXJ5T3B0cyA9IHtcbiAgICAgICAgICBEZWxpbWl0ZXI6IHJlY3Vyc2l2ZSA/ICcnIDogJy8nLCAvLyBpZiByZWN1cnNpdmUgaXMgZmFsc2Ugc2V0IGRlbGltaXRlciB0byAnLydcbiAgICAgICAgICBNYXhLZXlzOiAxMDAwLFxuICAgICAgICAgIEluY2x1ZGVWZXJzaW9uOiBsaXN0T3B0cz8uSW5jbHVkZVZlcnNpb24sXG4gICAgICAgICAgLy8gdmVyc2lvbiBsaXN0aW5nIHNwZWNpZmljIG9wdGlvbnNcbiAgICAgICAgICBrZXlNYXJrZXI6IGtleU1hcmtlcixcbiAgICAgICAgICB2ZXJzaW9uSWRNYXJrZXI6IHZlcnNpb25JZE1hcmtlcixcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc3VsdDogTGlzdE9iamVjdFF1ZXJ5UmVzID0gYXdhaXQgdGhpcy5saXN0T2JqZWN0c1F1ZXJ5KGJ1Y2tldE5hbWUsIHByZWZpeCwgbWFya2VyLCBsaXN0UXVlcnlPcHRzKVxuICAgICAgICBpZiAocmVzdWx0LmlzVHJ1bmNhdGVkKSB7XG4gICAgICAgICAgbWFya2VyID0gcmVzdWx0Lm5leHRNYXJrZXIgfHwgdW5kZWZpbmVkXG4gICAgICAgICAgaWYgKHJlc3VsdC5rZXlNYXJrZXIpIHtcbiAgICAgICAgICAgIGtleU1hcmtlciA9IHJlc3VsdC5rZXlNYXJrZXJcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHJlc3VsdC52ZXJzaW9uSWRNYXJrZXIpIHtcbiAgICAgICAgICAgIHZlcnNpb25JZE1hcmtlciA9IHJlc3VsdC52ZXJzaW9uSWRNYXJrZXJcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZW5kZWQgPSB0cnVlXG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlc3VsdC5vYmplY3RzKSB7XG4gICAgICAgICAgb2JqZWN0cyA9IHJlc3VsdC5vYmplY3RzXG4gICAgICAgIH1cbiAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICByZWFkU3RyZWFtLl9yZWFkKClcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICByZWFkU3RyZWFtLmVtaXQoJ2Vycm9yJywgZXJyKVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVhZFN0cmVhbVxuICB9XG5cbiAgYXN5bmMgbGlzdE9iamVjdHNWMlF1ZXJ5KFxuICAgIGJ1Y2tldE5hbWU6IHN0cmluZyxcbiAgICBwcmVmaXg6IHN0cmluZyxcbiAgICBjb250aW51YXRpb25Ub2tlbjogc3RyaW5nLFxuICAgIGRlbGltaXRlcjogc3RyaW5nLFxuICAgIG1heEtleXM6IG51bWJlcixcbiAgICBzdGFydEFmdGVyOiBzdHJpbmcsXG4gICk6IFByb21pc2U8TGlzdE9iamVjdFYyUmVzPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyhwcmVmaXgpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdwcmVmaXggc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIGlmICghaXNTdHJpbmcoY29udGludWF0aW9uVG9rZW4pKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdjb250aW51YXRpb25Ub2tlbiBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyhkZWxpbWl0ZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkZWxpbWl0ZXIgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIGlmICghaXNOdW1iZXIobWF4S2V5cykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ21heEtleXMgc2hvdWxkIGJlIG9mIHR5cGUgXCJudW1iZXJcIicpXG4gICAgfVxuICAgIGlmICghaXNTdHJpbmcoc3RhcnRBZnRlcikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3N0YXJ0QWZ0ZXIgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuXG4gICAgY29uc3QgcXVlcmllcyA9IFtdXG4gICAgcXVlcmllcy5wdXNoKGBsaXN0LXR5cGU9MmApXG4gICAgcXVlcmllcy5wdXNoKGBlbmNvZGluZy10eXBlPXVybGApXG4gICAgcXVlcmllcy5wdXNoKGBwcmVmaXg9JHt1cmlFc2NhcGUocHJlZml4KX1gKVxuICAgIHF1ZXJpZXMucHVzaChgZGVsaW1pdGVyPSR7dXJpRXNjYXBlKGRlbGltaXRlcil9YClcblxuICAgIGlmIChjb250aW51YXRpb25Ub2tlbikge1xuICAgICAgcXVlcmllcy5wdXNoKGBjb250aW51YXRpb24tdG9rZW49JHt1cmlFc2NhcGUoY29udGludWF0aW9uVG9rZW4pfWApXG4gICAgfVxuICAgIGlmIChzdGFydEFmdGVyKSB7XG4gICAgICBxdWVyaWVzLnB1c2goYHN0YXJ0LWFmdGVyPSR7dXJpRXNjYXBlKHN0YXJ0QWZ0ZXIpfWApXG4gICAgfVxuICAgIGlmIChtYXhLZXlzKSB7XG4gICAgICBpZiAobWF4S2V5cyA+PSAxMDAwKSB7XG4gICAgICAgIG1heEtleXMgPSAxMDAwXG4gICAgICB9XG4gICAgICBxdWVyaWVzLnB1c2goYG1heC1rZXlzPSR7bWF4S2V5c31gKVxuICAgIH1cbiAgICBxdWVyaWVzLnNvcnQoKVxuICAgIGxldCBxdWVyeSA9ICcnXG4gICAgaWYgKHF1ZXJpZXMubGVuZ3RoID4gMCkge1xuICAgICAgcXVlcnkgPSBgJHtxdWVyaWVzLmpvaW4oJyYnKX1gXG4gICAgfVxuXG4gICAgY29uc3QgbWV0aG9kID0gJ0dFVCdcbiAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmMoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIHF1ZXJ5IH0pXG4gICAgY29uc3QgYm9keSA9IGF3YWl0IHJlYWRBc1N0cmluZyhyZXMpXG4gICAgcmV0dXJuIHBhcnNlTGlzdE9iamVjdHNWMihib2R5KVxuICB9XG5cbiAgbGlzdE9iamVjdHNWMihcbiAgICBidWNrZXROYW1lOiBzdHJpbmcsXG4gICAgcHJlZml4Pzogc3RyaW5nLFxuICAgIHJlY3Vyc2l2ZT86IGJvb2xlYW4sXG4gICAgc3RhcnRBZnRlcj86IHN0cmluZyxcbiAgKTogQnVja2V0U3RyZWFtPEJ1Y2tldEl0ZW0+IHtcbiAgICBpZiAocHJlZml4ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHByZWZpeCA9ICcnXG4gICAgfVxuICAgIGlmIChyZWN1cnNpdmUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmVjdXJzaXZlID0gZmFsc2VcbiAgICB9XG4gICAgaWYgKHN0YXJ0QWZ0ZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgc3RhcnRBZnRlciA9ICcnXG4gICAgfVxuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNWYWxpZFByZWZpeChwcmVmaXgpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRQcmVmaXhFcnJvcihgSW52YWxpZCBwcmVmaXggOiAke3ByZWZpeH1gKVxuICAgIH1cbiAgICBpZiAoIWlzU3RyaW5nKHByZWZpeCkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ByZWZpeCBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgICB9XG4gICAgaWYgKCFpc0Jvb2xlYW4ocmVjdXJzaXZlKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncmVjdXJzaXZlIHNob3VsZCBiZSBvZiB0eXBlIFwiYm9vbGVhblwiJylcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyhzdGFydEFmdGVyKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignc3RhcnRBZnRlciBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgICB9XG5cbiAgICBjb25zdCBkZWxpbWl0ZXIgPSByZWN1cnNpdmUgPyAnJyA6ICcvJ1xuICAgIGNvbnN0IHByZWZpeFN0ciA9IHByZWZpeFxuICAgIGNvbnN0IHN0YXJ0QWZ0ZXJTdHIgPSBzdGFydEFmdGVyXG4gICAgbGV0IGNvbnRpbnVhdGlvblRva2VuID0gJydcbiAgICBsZXQgb2JqZWN0czogQnVja2V0SXRlbVtdID0gW11cbiAgICBsZXQgZW5kZWQgPSBmYWxzZVxuICAgIGNvbnN0IHJlYWRTdHJlYW06IHN0cmVhbS5SZWFkYWJsZSA9IG5ldyBzdHJlYW0uUmVhZGFibGUoeyBvYmplY3RNb2RlOiB0cnVlIH0pXG4gICAgcmVhZFN0cmVhbS5fcmVhZCA9IGFzeW5jICgpID0+IHtcbiAgICAgIGlmIChvYmplY3RzLmxlbmd0aCkge1xuICAgICAgICByZWFkU3RyZWFtLnB1c2gob2JqZWN0cy5zaGlmdCgpKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICAgIGlmIChlbmRlZCkge1xuICAgICAgICByZXR1cm4gcmVhZFN0cmVhbS5wdXNoKG51bGwpXG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMubGlzdE9iamVjdHNWMlF1ZXJ5KFxuICAgICAgICAgIGJ1Y2tldE5hbWUsXG4gICAgICAgICAgcHJlZml4U3RyLFxuICAgICAgICAgIGNvbnRpbnVhdGlvblRva2VuLFxuICAgICAgICAgIGRlbGltaXRlcixcbiAgICAgICAgICAxMDAwLFxuICAgICAgICAgIHN0YXJ0QWZ0ZXJTdHIsXG4gICAgICAgIClcbiAgICAgICAgaWYgKHJlc3VsdC5pc1RydW5jYXRlZCkge1xuICAgICAgICAgIGNvbnRpbnVhdGlvblRva2VuID0gcmVzdWx0Lm5leHRDb250aW51YXRpb25Ub2tlblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVuZGVkID0gdHJ1ZVxuICAgICAgICB9XG4gICAgICAgIG9iamVjdHMgPSByZXN1bHQub2JqZWN0c1xuICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgIHJlYWRTdHJlYW0uX3JlYWQoKVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHJlYWRTdHJlYW0uZW1pdCgnZXJyb3InLCBlcnIpXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZWFkU3RyZWFtXG4gIH1cblxuICBhc3luYyBzZXRCdWNrZXROb3RpZmljYXRpb24oYnVja2V0TmFtZTogc3RyaW5nLCBjb25maWc6IE5vdGlmaWNhdGlvbkNvbmZpZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNPYmplY3QoY29uZmlnKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbm90aWZpY2F0aW9uIGNvbmZpZyBzaG91bGQgYmUgb2YgdHlwZSBcIk9iamVjdFwiJylcbiAgICB9XG4gICAgY29uc3QgbWV0aG9kID0gJ1BVVCdcbiAgICBjb25zdCBxdWVyeSA9ICdub3RpZmljYXRpb24nXG4gICAgY29uc3QgYnVpbGRlciA9IG5ldyB4bWwyanMuQnVpbGRlcih7XG4gICAgICByb290TmFtZTogJ05vdGlmaWNhdGlvbkNvbmZpZ3VyYXRpb24nLFxuICAgICAgcmVuZGVyT3B0czogeyBwcmV0dHk6IGZhbHNlIH0sXG4gICAgICBoZWFkbGVzczogdHJ1ZSxcbiAgICB9KVxuICAgIGNvbnN0IHBheWxvYWQgPSBidWlsZGVyLmJ1aWxkT2JqZWN0KGNvbmZpZylcbiAgICBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmNPbWl0KHsgbWV0aG9kLCBidWNrZXROYW1lLCBxdWVyeSB9LCBwYXlsb2FkKVxuICB9XG5cbiAgYXN5bmMgcmVtb3ZlQWxsQnVja2V0Tm90aWZpY2F0aW9uKGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuc2V0QnVja2V0Tm90aWZpY2F0aW9uKGJ1Y2tldE5hbWUsIG5ldyBOb3RpZmljYXRpb25Db25maWcoKSlcbiAgfVxuXG4gIGFzeW5jIGdldEJ1Y2tldE5vdGlmaWNhdGlvbihidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPE5vdGlmaWNhdGlvbkNvbmZpZ1Jlc3VsdD4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGNvbnN0IG1ldGhvZCA9ICdHRVQnXG4gICAgY29uc3QgcXVlcnkgPSAnbm90aWZpY2F0aW9uJ1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfSlcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVhZEFzU3RyaW5nKHJlcylcbiAgICByZXR1cm4gcGFyc2VCdWNrZXROb3RpZmljYXRpb24oYm9keSlcbiAgfVxuXG4gIGxpc3RlbkJ1Y2tldE5vdGlmaWNhdGlvbihcbiAgICBidWNrZXROYW1lOiBzdHJpbmcsXG4gICAgcHJlZml4OiBzdHJpbmcsXG4gICAgc3VmZml4OiBzdHJpbmcsXG4gICAgZXZlbnRzOiBOb3RpZmljYXRpb25FdmVudFtdLFxuICApOiBOb3RpZmljYXRpb25Qb2xsZXIge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcihgSW52YWxpZCBidWNrZXQgbmFtZTogJHtidWNrZXROYW1lfWApXG4gICAgfVxuICAgIGlmICghaXNTdHJpbmcocHJlZml4KSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncHJlZml4IG11c3QgYmUgb2YgdHlwZSBzdHJpbmcnKVxuICAgIH1cbiAgICBpZiAoIWlzU3RyaW5nKHN1ZmZpeCkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3N1ZmZpeCBtdXN0IGJlIG9mIHR5cGUgc3RyaW5nJylcbiAgICB9XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGV2ZW50cykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2V2ZW50cyBtdXN0IGJlIG9mIHR5cGUgQXJyYXknKVxuICAgIH1cbiAgICBjb25zdCBsaXN0ZW5lciA9IG5ldyBOb3RpZmljYXRpb25Qb2xsZXIodGhpcywgYnVja2V0TmFtZSwgcHJlZml4LCBzdWZmaXgsIGV2ZW50cylcbiAgICBsaXN0ZW5lci5zdGFydCgpXG4gICAgcmV0dXJuIGxpc3RlbmVyXG4gIH1cbn1cbiJdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLQSxNQUFNO0FBQ2xCLE9BQU8sS0FBS0MsRUFBRTtBQUVkLE9BQU8sS0FBS0MsSUFBSTtBQUNoQixPQUFPLEtBQUtDLEtBQUs7QUFDakIsT0FBTyxLQUFLQyxJQUFJO0FBQ2hCLE9BQU8sS0FBS0MsTUFBTTtBQUVsQixPQUFPLEtBQUtDLEtBQUssTUFBTSxPQUFPO0FBQzlCLE9BQU9DLFlBQVksTUFBTSxlQUFlO0FBQ3hDLFNBQVNDLFNBQVMsUUFBUSxpQkFBaUI7QUFDM0MsT0FBT0MsQ0FBQyxNQUFNLFFBQVE7QUFDdEIsT0FBTyxLQUFLQyxFQUFFLE1BQU0sY0FBYztBQUNsQyxPQUFPQyxNQUFNLE1BQU0sUUFBUTtBQUUzQixTQUFTQyxrQkFBa0IsUUFBUSwyQkFBMEI7QUFDN0QsT0FBTyxLQUFLQyxNQUFNLE1BQU0sZUFBYztBQUV0QyxTQUNFQyxzQkFBc0IsRUFDdEJDLGlCQUFpQixFQUNqQkMsY0FBYyxFQUNkQyxpQkFBaUIsRUFDakJDLHVCQUF1QixFQUN2QkMsZUFBZSxFQUNmQyx3QkFBd0IsUUFDbkIsZ0JBQWU7QUFFdEIsU0FBU0Msa0JBQWtCLEVBQUVDLGtCQUFrQixRQUFRLHFCQUFvQjtBQUMzRSxTQUFTQyxzQkFBc0IsRUFBRUMsa0JBQWtCLEVBQUVDLE1BQU0sUUFBUSxnQkFBZTtBQUNsRixTQUFTQyxHQUFHLEVBQUVDLGFBQWEsUUFBUSxhQUFZO0FBQy9DLFNBQVNDLGNBQWMsUUFBUSx1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