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