@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,608 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.calculateEvenSplits = calculateEvenSplits;
|
|
7
|
+
exports.extractMetadata = extractMetadata;
|
|
8
|
+
exports.getContentLength = getContentLength;
|
|
9
|
+
exports.getEncryptionHeaders = getEncryptionHeaders;
|
|
10
|
+
exports.getScope = getScope;
|
|
11
|
+
exports.getSourceVersionId = getSourceVersionId;
|
|
12
|
+
exports.getVersionId = getVersionId;
|
|
13
|
+
exports.hashBinary = hashBinary;
|
|
14
|
+
exports.insertContentType = insertContentType;
|
|
15
|
+
exports.isAmazonEndpoint = isAmazonEndpoint;
|
|
16
|
+
exports.isAmzHeader = isAmzHeader;
|
|
17
|
+
exports.isBoolean = isBoolean;
|
|
18
|
+
exports.isDefined = isDefined;
|
|
19
|
+
exports.isEmpty = isEmpty;
|
|
20
|
+
exports.isEmptyObject = isEmptyObject;
|
|
21
|
+
exports.isFunction = isFunction;
|
|
22
|
+
exports.isNumber = isNumber;
|
|
23
|
+
exports.isObject = isObject;
|
|
24
|
+
exports.isPlainObject = isPlainObject;
|
|
25
|
+
exports.isReadableStream = isReadableStream;
|
|
26
|
+
exports.isStorageClassHeader = isStorageClassHeader;
|
|
27
|
+
exports.isString = isString;
|
|
28
|
+
exports.isSupportedHeader = isSupportedHeader;
|
|
29
|
+
exports.isValidBucketName = isValidBucketName;
|
|
30
|
+
exports.isValidDate = isValidDate;
|
|
31
|
+
exports.isValidDomain = isValidDomain;
|
|
32
|
+
exports.isValidEndpoint = isValidEndpoint;
|
|
33
|
+
exports.isValidIP = isValidIP;
|
|
34
|
+
exports.isValidObjectName = isValidObjectName;
|
|
35
|
+
exports.isValidPort = isValidPort;
|
|
36
|
+
exports.isValidPrefix = isValidPrefix;
|
|
37
|
+
exports.isVirtualHostStyle = isVirtualHostStyle;
|
|
38
|
+
exports.makeDateLong = makeDateLong;
|
|
39
|
+
exports.makeDateShort = makeDateShort;
|
|
40
|
+
exports.parseXml = parseXml;
|
|
41
|
+
exports.partsRequired = partsRequired;
|
|
42
|
+
exports.pipesetup = pipesetup;
|
|
43
|
+
exports.prependXAMZMeta = prependXAMZMeta;
|
|
44
|
+
exports.probeContentType = probeContentType;
|
|
45
|
+
exports.readableStream = readableStream;
|
|
46
|
+
exports.sanitizeETag = sanitizeETag;
|
|
47
|
+
exports.sanitizeObjectKey = sanitizeObjectKey;
|
|
48
|
+
exports.sanitizeSize = sanitizeSize;
|
|
49
|
+
exports.toArray = toArray;
|
|
50
|
+
exports.toMd5 = toMd5;
|
|
51
|
+
exports.toSha256 = toSha256;
|
|
52
|
+
exports.uriEscape = uriEscape;
|
|
53
|
+
exports.uriResourceEscape = uriResourceEscape;
|
|
54
|
+
var crypto = _interopRequireWildcard(require("crypto"), true);
|
|
55
|
+
var stream = _interopRequireWildcard(require("stream"), true);
|
|
56
|
+
var _fastXmlParser = require("fast-xml-parser");
|
|
57
|
+
var _ipaddr = require("ipaddr.js");
|
|
58
|
+
var _lodash = require("lodash");
|
|
59
|
+
var mime = _interopRequireWildcard(require("mime-types"), true);
|
|
60
|
+
var _async = require("./async.js");
|
|
61
|
+
var _type = require("./type.js");
|
|
62
|
+
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); }
|
|
63
|
+
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; }
|
|
64
|
+
/*
|
|
65
|
+
* Hanzo S3 Javascript Library for Amazon S3 Compatible Cloud Storage, (C) 2015 Hanzo AI, Inc.
|
|
66
|
+
*
|
|
67
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
68
|
+
* you may not use this file except in compliance with the License.
|
|
69
|
+
* You may obtain a copy of the License at
|
|
70
|
+
*
|
|
71
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
72
|
+
*
|
|
73
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
74
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
75
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
76
|
+
* See the License for the specific language governing permissions and
|
|
77
|
+
* limitations under the License.
|
|
78
|
+
*/
|
|
79
|
+
|
|
80
|
+
const MetaDataHeaderPrefix = 'x-amz-meta-';
|
|
81
|
+
function hashBinary(buf, enableSHA256) {
|
|
82
|
+
let sha256sum = '';
|
|
83
|
+
if (enableSHA256) {
|
|
84
|
+
sha256sum = crypto.createHash('sha256').update(buf).digest('hex');
|
|
85
|
+
}
|
|
86
|
+
const md5sum = crypto.createHash('md5').update(buf).digest('base64');
|
|
87
|
+
return {
|
|
88
|
+
md5sum,
|
|
89
|
+
sha256sum
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// S3 percent-encodes some extra non-standard characters in a URI . So comply with S3.
|
|
94
|
+
const encodeAsHex = c => `%${c.charCodeAt(0).toString(16).toUpperCase()}`;
|
|
95
|
+
function uriEscape(uriStr) {
|
|
96
|
+
return encodeURIComponent(uriStr).replace(/[!'()*]/g, encodeAsHex);
|
|
97
|
+
}
|
|
98
|
+
function uriResourceEscape(string) {
|
|
99
|
+
return uriEscape(string).replace(/%2F/g, '/');
|
|
100
|
+
}
|
|
101
|
+
function getScope(region, date, serviceName = 's3') {
|
|
102
|
+
return `${makeDateShort(date)}/${region}/${serviceName}/aws4_request`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* isAmazonEndpoint - true if endpoint is 's3.amazonaws.com' or 's3.cn-north-1.amazonaws.com.cn'
|
|
107
|
+
*/
|
|
108
|
+
function isAmazonEndpoint(endpoint) {
|
|
109
|
+
return endpoint === 's3.amazonaws.com' || endpoint === 's3.cn-north-1.amazonaws.com.cn';
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* isVirtualHostStyle - verify if bucket name is support with virtual
|
|
114
|
+
* hosts. bucketNames with periods should be always treated as path
|
|
115
|
+
* style if the protocol is 'https:', this is due to SSL wildcard
|
|
116
|
+
* limitation. For all other buckets and Amazon S3 endpoint we will
|
|
117
|
+
* default to virtual host style.
|
|
118
|
+
*/
|
|
119
|
+
function isVirtualHostStyle(endpoint, protocol, bucket, pathStyle) {
|
|
120
|
+
if (protocol === 'https:' && bucket.includes('.')) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
return isAmazonEndpoint(endpoint) || !pathStyle;
|
|
124
|
+
}
|
|
125
|
+
function isValidIP(ip) {
|
|
126
|
+
return _ipaddr.isValid(ip);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @returns if endpoint is valid domain.
|
|
131
|
+
*/
|
|
132
|
+
function isValidEndpoint(endpoint) {
|
|
133
|
+
return isValidDomain(endpoint) || isValidIP(endpoint);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* @returns if input host is a valid domain.
|
|
138
|
+
*/
|
|
139
|
+
function isValidDomain(host) {
|
|
140
|
+
if (!isString(host)) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
// See RFC 1035, RFC 3696.
|
|
144
|
+
if (host.length === 0 || host.length > 255) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
// Host cannot start or end with a '-'
|
|
148
|
+
if (host[0] === '-' || host.slice(-1) === '-') {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
// Host cannot start or end with a '_'
|
|
152
|
+
if (host[0] === '_' || host.slice(-1) === '_') {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
// Host cannot start with a '.'
|
|
156
|
+
if (host[0] === '.') {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
const nonAlphaNumerics = '`~!@#$%^&*()+={}[]|\\"\';:><?/';
|
|
160
|
+
// All non alphanumeric characters are invalid.
|
|
161
|
+
for (const char of nonAlphaNumerics) {
|
|
162
|
+
if (host.includes(char)) {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// No need to regexp match, since the list is non-exhaustive.
|
|
167
|
+
// We let it be valid and fail later.
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Probes contentType using file extensions.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```
|
|
176
|
+
* // return 'image/png'
|
|
177
|
+
* probeContentType('file.png')
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
function probeContentType(path) {
|
|
181
|
+
let contentType = mime.lookup(path);
|
|
182
|
+
if (!contentType) {
|
|
183
|
+
contentType = 'application/octet-stream';
|
|
184
|
+
}
|
|
185
|
+
return contentType;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* is input port valid.
|
|
190
|
+
*/
|
|
191
|
+
function isValidPort(port) {
|
|
192
|
+
// Convert string port to number if needed
|
|
193
|
+
const portNum = typeof port === 'string' ? parseInt(port, 10) : port;
|
|
194
|
+
|
|
195
|
+
// verify if port is a valid number
|
|
196
|
+
if (!isNumber(portNum) || isNaN(portNum)) {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// port `0` is valid and special case
|
|
201
|
+
return 0 <= portNum && portNum <= 65535;
|
|
202
|
+
}
|
|
203
|
+
function isValidBucketName(bucket) {
|
|
204
|
+
if (!isString(bucket)) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// bucket length should be less than and no more than 63
|
|
209
|
+
// characters long.
|
|
210
|
+
if (bucket.length < 3 || bucket.length > 63) {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
// bucket with successive periods is invalid.
|
|
214
|
+
if (bucket.includes('..')) {
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
// bucket cannot have ip address style.
|
|
218
|
+
if (/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/.test(bucket)) {
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
// bucket should begin with alphabet/number and end with alphabet/number,
|
|
222
|
+
// with alphabet/number/.- in the middle.
|
|
223
|
+
if (/^[a-z0-9][a-z0-9.-]+[a-z0-9]$/.test(bucket)) {
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* check if objectName is a valid object name
|
|
231
|
+
*/
|
|
232
|
+
function isValidObjectName(objectName) {
|
|
233
|
+
if (!isValidPrefix(objectName)) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
return objectName.length !== 0;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* check if prefix is valid
|
|
241
|
+
*/
|
|
242
|
+
function isValidPrefix(prefix) {
|
|
243
|
+
if (!isString(prefix)) {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
if (prefix.length > 1024) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* check if typeof arg number
|
|
254
|
+
*/
|
|
255
|
+
function isNumber(arg) {
|
|
256
|
+
return typeof arg === 'number';
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* check if typeof arg function
|
|
263
|
+
*/
|
|
264
|
+
function isFunction(arg) {
|
|
265
|
+
return typeof arg === 'function';
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* check if typeof arg string
|
|
270
|
+
*/
|
|
271
|
+
function isString(arg) {
|
|
272
|
+
return typeof arg === 'string';
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* check if typeof arg object
|
|
277
|
+
*/
|
|
278
|
+
function isObject(arg) {
|
|
279
|
+
return typeof arg === 'object' && arg !== null;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* check if typeof arg is plain object
|
|
283
|
+
*/
|
|
284
|
+
function isPlainObject(arg) {
|
|
285
|
+
return Object.prototype.toString.call(arg) === '[object Object]';
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* check if object is readable stream
|
|
289
|
+
*/
|
|
290
|
+
function isReadableStream(arg) {
|
|
291
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
292
|
+
return isObject(arg) && isFunction(arg._read);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* check if arg is boolean
|
|
297
|
+
*/
|
|
298
|
+
function isBoolean(arg) {
|
|
299
|
+
return typeof arg === 'boolean';
|
|
300
|
+
}
|
|
301
|
+
function isEmpty(o) {
|
|
302
|
+
return _lodash.isEmpty(o);
|
|
303
|
+
}
|
|
304
|
+
function isEmptyObject(o) {
|
|
305
|
+
return Object.values(o).filter(x => x !== undefined).length !== 0;
|
|
306
|
+
}
|
|
307
|
+
function isDefined(o) {
|
|
308
|
+
return o !== null && o !== undefined;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* check if arg is a valid date
|
|
313
|
+
*/
|
|
314
|
+
function isValidDate(arg) {
|
|
315
|
+
// @ts-expect-error checknew Date(Math.NaN)
|
|
316
|
+
return arg instanceof Date && !isNaN(arg);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Create a Date string with format: 'YYYYMMDDTHHmmss' + Z
|
|
321
|
+
*/
|
|
322
|
+
function makeDateLong(date) {
|
|
323
|
+
date = date || new Date();
|
|
324
|
+
|
|
325
|
+
// Gives format like: '2017-08-07T16:28:59.889Z'
|
|
326
|
+
const s = date.toISOString();
|
|
327
|
+
return s.slice(0, 4) + s.slice(5, 7) + s.slice(8, 13) + s.slice(14, 16) + s.slice(17, 19) + 'Z';
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Create a Date string with format: 'YYYYMMDD'
|
|
332
|
+
*/
|
|
333
|
+
function makeDateShort(date) {
|
|
334
|
+
date = date || new Date();
|
|
335
|
+
|
|
336
|
+
// Gives format like: '2017-08-07T16:28:59.889Z'
|
|
337
|
+
const s = date.toISOString();
|
|
338
|
+
return s.slice(0, 4) + s.slice(5, 7) + s.slice(8, 10);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* pipesetup sets up pipe() from left to right os streams array
|
|
343
|
+
* pipesetup will also make sure that error emitted at any of the upstream Stream
|
|
344
|
+
* will be emitted at the last stream. This makes error handling simple
|
|
345
|
+
*/
|
|
346
|
+
function pipesetup(...streams) {
|
|
347
|
+
// @ts-expect-error ts can't narrow this
|
|
348
|
+
return streams.reduce((src, dst) => {
|
|
349
|
+
src.on('error', err => dst.emit('error', err));
|
|
350
|
+
return src.pipe(dst);
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* return a Readable stream that emits data
|
|
356
|
+
*/
|
|
357
|
+
function readableStream(data) {
|
|
358
|
+
const s = new stream.Readable();
|
|
359
|
+
s._read = () => {};
|
|
360
|
+
s.push(data);
|
|
361
|
+
s.push(null);
|
|
362
|
+
return s;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Process metadata to insert appropriate value to `content-type` attribute
|
|
367
|
+
*/
|
|
368
|
+
function insertContentType(metaData, filePath) {
|
|
369
|
+
// check if content-type attribute present in metaData
|
|
370
|
+
for (const key in metaData) {
|
|
371
|
+
if (key.toLowerCase() === 'content-type') {
|
|
372
|
+
return metaData;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// if `content-type` attribute is not present in metadata, then infer it from the extension in filePath
|
|
377
|
+
return {
|
|
378
|
+
...metaData,
|
|
379
|
+
'content-type': probeContentType(filePath)
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Function prepends metadata with the appropriate prefix if it is not already on
|
|
385
|
+
*/
|
|
386
|
+
function prependXAMZMeta(metaData) {
|
|
387
|
+
if (!metaData) {
|
|
388
|
+
return {};
|
|
389
|
+
}
|
|
390
|
+
return _lodash.mapKeys(metaData, (value, key) => {
|
|
391
|
+
if (isAmzHeader(key) || isSupportedHeader(key) || isStorageClassHeader(key)) {
|
|
392
|
+
return key;
|
|
393
|
+
}
|
|
394
|
+
return MetaDataHeaderPrefix + key;
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Checks if it is a valid header according to the AmazonS3 API
|
|
400
|
+
*/
|
|
401
|
+
function isAmzHeader(key) {
|
|
402
|
+
const temp = key.toLowerCase();
|
|
403
|
+
return temp.startsWith(MetaDataHeaderPrefix) || temp === 'x-amz-acl' || temp.startsWith('x-amz-server-side-encryption-') || temp === 'x-amz-server-side-encryption';
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Checks if it is a supported Header
|
|
408
|
+
*/
|
|
409
|
+
function isSupportedHeader(key) {
|
|
410
|
+
const supported_headers = ['content-type', 'cache-control', 'content-encoding', 'content-disposition', 'content-language', 'x-amz-website-redirect-location', 'if-none-match', 'if-match'];
|
|
411
|
+
return supported_headers.includes(key.toLowerCase());
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Checks if it is a storage header
|
|
416
|
+
*/
|
|
417
|
+
function isStorageClassHeader(key) {
|
|
418
|
+
return key.toLowerCase() === 'x-amz-storage-class';
|
|
419
|
+
}
|
|
420
|
+
function extractMetadata(headers) {
|
|
421
|
+
return _lodash.mapKeys(_lodash.pickBy(headers, (value, key) => isSupportedHeader(key) || isStorageClassHeader(key) || isAmzHeader(key)), (value, key) => {
|
|
422
|
+
const lower = key.toLowerCase();
|
|
423
|
+
if (lower.startsWith(MetaDataHeaderPrefix)) {
|
|
424
|
+
return lower.slice(MetaDataHeaderPrefix.length);
|
|
425
|
+
}
|
|
426
|
+
return key;
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
function getVersionId(headers = {}) {
|
|
430
|
+
return headers['x-amz-version-id'] || null;
|
|
431
|
+
}
|
|
432
|
+
function getSourceVersionId(headers = {}) {
|
|
433
|
+
return headers['x-amz-copy-source-version-id'] || null;
|
|
434
|
+
}
|
|
435
|
+
function sanitizeETag(etag = '') {
|
|
436
|
+
const replaceChars = {
|
|
437
|
+
'"': '',
|
|
438
|
+
'"': '',
|
|
439
|
+
'"': '',
|
|
440
|
+
'"': '',
|
|
441
|
+
'"': ''
|
|
442
|
+
};
|
|
443
|
+
return etag.replace(/^("|"|")|("|"|")$/g, m => replaceChars[m]);
|
|
444
|
+
}
|
|
445
|
+
function toMd5(payload) {
|
|
446
|
+
// use string from browser and buffer from nodejs
|
|
447
|
+
// browser support is tested only against Hanzo S3 server
|
|
448
|
+
return crypto.createHash('md5').update(Buffer.from(payload)).digest().toString('base64');
|
|
449
|
+
}
|
|
450
|
+
function toSha256(payload) {
|
|
451
|
+
return crypto.createHash('sha256').update(payload).digest('hex');
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* toArray returns a single element array with param being the element,
|
|
456
|
+
* if param is just a string, and returns 'param' back if it is an array
|
|
457
|
+
* So, it makes sure param is always an array
|
|
458
|
+
*/
|
|
459
|
+
function toArray(param) {
|
|
460
|
+
if (!Array.isArray(param)) {
|
|
461
|
+
return [param];
|
|
462
|
+
}
|
|
463
|
+
return param;
|
|
464
|
+
}
|
|
465
|
+
function sanitizeObjectKey(objectName) {
|
|
466
|
+
// + symbol characters are not decoded as spaces in JS. so replace them first and decode to get the correct result.
|
|
467
|
+
const asStrName = (objectName ? objectName.toString() : '').replace(/\+/g, ' ');
|
|
468
|
+
return decodeURIComponent(asStrName);
|
|
469
|
+
}
|
|
470
|
+
function sanitizeSize(size) {
|
|
471
|
+
return size ? Number.parseInt(size) : undefined;
|
|
472
|
+
}
|
|
473
|
+
const PART_CONSTRAINTS = {
|
|
474
|
+
// absMinPartSize - absolute minimum part size (5 MiB)
|
|
475
|
+
ABS_MIN_PART_SIZE: 1024 * 1024 * 5,
|
|
476
|
+
// MIN_PART_SIZE - minimum part size 16MiB per object after which
|
|
477
|
+
MIN_PART_SIZE: 1024 * 1024 * 16,
|
|
478
|
+
// MAX_PARTS_COUNT - maximum number of parts for a single multipart session.
|
|
479
|
+
MAX_PARTS_COUNT: 10000,
|
|
480
|
+
// MAX_PART_SIZE - maximum part size 5GiB for a single multipart upload
|
|
481
|
+
// operation.
|
|
482
|
+
MAX_PART_SIZE: 1024 * 1024 * 1024 * 5,
|
|
483
|
+
// MAX_SINGLE_PUT_OBJECT_SIZE - maximum size 5GiB of object per PUT
|
|
484
|
+
// operation.
|
|
485
|
+
MAX_SINGLE_PUT_OBJECT_SIZE: 1024 * 1024 * 1024 * 5,
|
|
486
|
+
// MAX_MULTIPART_PUT_OBJECT_SIZE - maximum size 5TiB of object for
|
|
487
|
+
// Multipart operation.
|
|
488
|
+
MAX_MULTIPART_PUT_OBJECT_SIZE: 1024 * 1024 * 1024 * 1024 * 5
|
|
489
|
+
};
|
|
490
|
+
exports.PART_CONSTRAINTS = PART_CONSTRAINTS;
|
|
491
|
+
const GENERIC_SSE_HEADER = 'X-Amz-Server-Side-Encryption';
|
|
492
|
+
const ENCRYPTION_HEADERS = {
|
|
493
|
+
// sseGenericHeader is the AWS SSE header used for SSE-S3 and SSE-KMS.
|
|
494
|
+
sseGenericHeader: GENERIC_SSE_HEADER,
|
|
495
|
+
// sseKmsKeyID is the AWS SSE-KMS key id.
|
|
496
|
+
sseKmsKeyID: GENERIC_SSE_HEADER + '-Aws-Kms-Key-Id'
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Return Encryption headers
|
|
501
|
+
* @param encConfig
|
|
502
|
+
* @returns an object with key value pairs that can be used in headers.
|
|
503
|
+
*/
|
|
504
|
+
function getEncryptionHeaders(encConfig) {
|
|
505
|
+
const encType = encConfig.type;
|
|
506
|
+
if (!isEmpty(encType)) {
|
|
507
|
+
if (encType === _type.ENCRYPTION_TYPES.SSEC) {
|
|
508
|
+
return {
|
|
509
|
+
[ENCRYPTION_HEADERS.sseGenericHeader]: 'AES256'
|
|
510
|
+
};
|
|
511
|
+
} else if (encType === _type.ENCRYPTION_TYPES.KMS) {
|
|
512
|
+
return {
|
|
513
|
+
[ENCRYPTION_HEADERS.sseGenericHeader]: encConfig.SSEAlgorithm,
|
|
514
|
+
[ENCRYPTION_HEADERS.sseKmsKeyID]: encConfig.KMSMasterKeyID
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
return {};
|
|
519
|
+
}
|
|
520
|
+
function partsRequired(size) {
|
|
521
|
+
const maxPartSize = PART_CONSTRAINTS.MAX_MULTIPART_PUT_OBJECT_SIZE / (PART_CONSTRAINTS.MAX_PARTS_COUNT - 1);
|
|
522
|
+
let requiredPartSize = size / maxPartSize;
|
|
523
|
+
if (size % maxPartSize > 0) {
|
|
524
|
+
requiredPartSize++;
|
|
525
|
+
}
|
|
526
|
+
requiredPartSize = Math.trunc(requiredPartSize);
|
|
527
|
+
return requiredPartSize;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* calculateEvenSplits - computes splits for a source and returns
|
|
532
|
+
* start and end index slices. Splits happen evenly to be sure that no
|
|
533
|
+
* part is less than 5MiB, as that could fail the multipart request if
|
|
534
|
+
* it is not the last part.
|
|
535
|
+
*/
|
|
536
|
+
function calculateEvenSplits(size, objInfo) {
|
|
537
|
+
if (size === 0) {
|
|
538
|
+
return null;
|
|
539
|
+
}
|
|
540
|
+
const reqParts = partsRequired(size);
|
|
541
|
+
const startIndexParts = [];
|
|
542
|
+
const endIndexParts = [];
|
|
543
|
+
let start = objInfo.Start;
|
|
544
|
+
if (isEmpty(start) || start === -1) {
|
|
545
|
+
start = 0;
|
|
546
|
+
}
|
|
547
|
+
const divisorValue = Math.trunc(size / reqParts);
|
|
548
|
+
const reminderValue = size % reqParts;
|
|
549
|
+
let nextStart = start;
|
|
550
|
+
for (let i = 0; i < reqParts; i++) {
|
|
551
|
+
let curPartSize = divisorValue;
|
|
552
|
+
if (i < reminderValue) {
|
|
553
|
+
curPartSize++;
|
|
554
|
+
}
|
|
555
|
+
const currentStart = nextStart;
|
|
556
|
+
const currentEnd = currentStart + curPartSize - 1;
|
|
557
|
+
nextStart = currentEnd + 1;
|
|
558
|
+
startIndexParts.push(currentStart);
|
|
559
|
+
endIndexParts.push(currentEnd);
|
|
560
|
+
}
|
|
561
|
+
return {
|
|
562
|
+
startIndex: startIndexParts,
|
|
563
|
+
endIndex: endIndexParts,
|
|
564
|
+
objInfo: objInfo
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
const fxp = new _fastXmlParser.XMLParser({
|
|
568
|
+
numberParseOptions: {
|
|
569
|
+
eNotation: false,
|
|
570
|
+
hex: true,
|
|
571
|
+
leadingZeros: true
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
576
|
+
function parseXml(xml) {
|
|
577
|
+
const result = fxp.parse(xml);
|
|
578
|
+
if (result.Error) {
|
|
579
|
+
throw result.Error;
|
|
580
|
+
}
|
|
581
|
+
return result;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* get content size of object content to upload
|
|
586
|
+
*/
|
|
587
|
+
async function getContentLength(s) {
|
|
588
|
+
// use length property of string | Buffer
|
|
589
|
+
if (typeof s === 'string' || Buffer.isBuffer(s)) {
|
|
590
|
+
return s.length;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// property of `fs.ReadStream`
|
|
594
|
+
const filePath = s.path;
|
|
595
|
+
if (filePath && typeof filePath === 'string') {
|
|
596
|
+
const stat = await _async.fsp.lstat(filePath);
|
|
597
|
+
return stat.size;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// property of `fs.ReadStream`
|
|
601
|
+
const fd = s.fd;
|
|
602
|
+
if (fd && typeof fd === 'number') {
|
|
603
|
+
const stat = await (0, _async.fstat)(fd);
|
|
604
|
+
return stat.size;
|
|
605
|
+
}
|
|
606
|
+
return null;
|
|
607
|
+
}
|
|
608
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJjcnlwdG8iLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJzdHJlYW0iLCJfZmFzdFhtbFBhcnNlciIsIl9pcGFkZHIiLCJfbG9kYXNoIiwibWltZSIsIl9hc3luYyIsIl90eXBlIiwiX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlIiwibm9kZUludGVyb3AiLCJXZWFrTWFwIiwiY2FjaGVCYWJlbEludGVyb3AiLCJjYWNoZU5vZGVJbnRlcm9wIiwib2JqIiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJjYWNoZSIsImhhcyIsImdldCIsIm5ld09iaiIsImhhc1Byb3BlcnR5RGVzY3JpcHRvciIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwia2V5IiwicHJvdG90eXBlIiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiZGVzYyIsInNldCIsIk1ldGFEYXRhSGVhZGVyUHJlZml4IiwiaGFzaEJpbmFyeSIsImJ1ZiIsImVuYWJsZVNIQTI1NiIsInNoYTI1NnN1bSIsImNyZWF0ZUhhc2giLCJ1cGRhdGUiLCJkaWdlc3QiLCJtZDVzdW0iLCJlbmNvZGVBc0hleCIsImMiLCJjaGFyQ29kZUF0IiwidG9TdHJpbmciLCJ0b1VwcGVyQ2FzZSIsInVyaUVzY2FwZSIsInVyaVN0ciIsImVuY29kZVVSSUNvbXBvbmVudCIsInJlcGxhY2UiLCJ1cmlSZXNvdXJjZUVzY2FwZSIsInN0cmluZyIsImdldFNjb3BlIiwicmVnaW9uIiwiZGF0ZSIsInNlcnZpY2VOYW1lIiwibWFrZURhdGVTaG9ydCIsImlzQW1hem9uRW5kcG9pbnQiLCJlbmRwb2ludCIsImlzVmlydHVhbEhvc3RTdHlsZSIsInByb3RvY29sIiwiYnVja2V0IiwicGF0aFN0eWxlIiwiaW5jbHVkZXMiLCJpc1ZhbGlkSVAiLCJpcCIsImlwYWRkciIsImlzVmFsaWQiLCJpc1ZhbGlkRW5kcG9pbnQiLCJpc1ZhbGlkRG9tYWluIiwiaG9zdCIsImlzU3RyaW5nIiwibGVuZ3RoIiwic2xpY2UiLCJub25BbHBoYU51bWVyaWNzIiwiY2hhciIsInByb2JlQ29udGVudFR5cGUiLCJwYXRoIiwiY29udGVudFR5cGUiLCJsb29rdXAiLCJpc1ZhbGlkUG9ydCIsInBvcnQiLCJwb3J0TnVtIiwicGFyc2VJbnQiLCJpc051bWJlciIsImlzTmFOIiwiaXNWYWxpZEJ1Y2tldE5hbWUiLCJ0ZXN0IiwiaXNWYWxpZE9iamVjdE5hbWUiLCJvYmplY3ROYW1lIiwiaXNWYWxpZFByZWZpeCIsInByZWZpeCIsImFyZyIsImlzRnVuY3Rpb24iLCJpc09iamVjdCIsImlzUGxhaW5PYmplY3QiLCJpc1JlYWRhYmxlU3RyZWFtIiwiX3JlYWQiLCJpc0Jvb2xlYW4iLCJpc0VtcHR5IiwibyIsIl8iLCJpc0VtcHR5T2JqZWN0IiwidmFsdWVzIiwiZmlsdGVyIiwieCIsInVuZGVmaW5lZCIsImlzRGVmaW5lZCIsImlzVmFsaWREYXRlIiwiRGF0ZSIsIm1ha2VEYXRlTG9uZyIsInMiLCJ0b0lTT1N0cmluZyIsInBpcGVzZXR1cCIsInN0cmVhbXMiLCJyZWR1Y2UiLCJzcmMiLCJkc3QiLCJvbiIsImVyciIsImVtaXQiLCJwaXBlIiwicmVhZGFibGVTdHJlYW0iLCJkYXRhIiwiUmVhZGFibGUiLCJwdXNoIiwiaW5zZXJ0Q29udGVudFR5cGUiLCJtZXRhRGF0YSIsImZpbGVQYXRoIiwidG9Mb3dlckNhc2UiLCJwcmVwZW5kWEFNWk1ldGEiLCJtYXBLZXlzIiwidmFsdWUiLCJpc0FtekhlYWRlciIsImlzU3VwcG9ydGVkSGVhZGVyIiwiaXNTdG9yYWdlQ2xhc3NIZWFkZXIiLCJ0ZW1wIiwic3RhcnRzV2l0aCIsInN1cHBvcnRlZF9oZWFkZXJzIiwiZXh0cmFjdE1ldGFkYXRhIiwiaGVhZGVycyIsInBpY2tCeSIsImxvd2VyIiwiZ2V0VmVyc2lvbklkIiwiZ2V0U291cmNlVmVyc2lvbklkIiwic2FuaXRpemVFVGFnIiwiZXRhZyIsInJlcGxhY2VDaGFycyIsIm0iLCJ0b01kNSIsInBheWxvYWQiLCJCdWZmZXIiLCJmcm9tIiwidG9TaGEyNTYiLCJ0b0FycmF5IiwicGFyYW0iLCJBcnJheSIsImlzQXJyYXkiLCJzYW5pdGl6ZU9iamVjdEtleSIsImFzU3RyTmFtZSIsImRlY29kZVVSSUNvbXBvbmVudCIsInNhbml0aXplU2l6ZSIsInNpemUiLCJOdW1iZXIiLCJQQVJUX0NPTlNUUkFJTlRTIiwiQUJTX01JTl9QQVJUX1NJWkUiLCJNSU5fUEFSVF9TSVpFIiwiTUFYX1BBUlRTX0NPVU5UIiwiTUFYX1BBUlRfU0laRSIsIk1BWF9TSU5HTEVfUFVUX09CSkVDVF9TSVpFIiwiTUFYX01VTFRJUEFSVF9QVVRfT0JKRUNUX1NJWkUiLCJleHBvcnRzIiwiR0VORVJJQ19TU0VfSEVBREVSIiwiRU5DUllQVElPTl9IRUFERVJTIiwic3NlR2VuZXJpY0hlYWRlciIsInNzZUttc0tleUlEIiwiZ2V0RW5jcnlwdGlvbkhlYWRlcnMiLCJlbmNDb25maWciLCJlbmNUeXBlIiwidHlwZSIsIkVOQ1JZUFRJT05fVFlQRVMiLCJTU0VDIiwiS01TIiwiU1NFQWxnb3JpdGhtIiwiS01TTWFzdGVyS2V5SUQiLCJwYXJ0c1JlcXVpcmVkIiwibWF4UGFydFNpemUiLCJyZXF1aXJlZFBhcnRTaXplIiwiTWF0aCIsInRydW5jIiwiY2FsY3VsYXRlRXZlblNwbGl0cyIsIm9iakluZm8iLCJyZXFQYXJ0cyIsInN0YXJ0SW5kZXhQYXJ0cyIsImVuZEluZGV4UGFydHMiLCJzdGFydCIsIlN0YXJ0IiwiZGl2aXNvclZhbHVlIiwicmVtaW5kZXJWYWx1ZSIsIm5leHRTdGFydCIsImkiLCJjdXJQYXJ0U2l6ZSIsImN1cnJlbnRTdGFydCIsImN1cnJlbnRFbmQiLCJzdGFydEluZGV4IiwiZW5kSW5kZXgiLCJmeHAiLCJYTUxQYXJzZXIiLCJudW1iZXJQYXJzZU9wdGlvbnMiLCJlTm90YXRpb24iLCJoZXgiLCJsZWFkaW5nWmVyb3MiLCJwYXJzZVhtbCIsInhtbCIsInJlc3VsdCIsInBhcnNlIiwiRXJyb3IiLCJnZXRDb250ZW50TGVuZ3RoIiwiaXNCdWZmZXIiLCJzdGF0IiwiZnNwIiwibHN0YXQiLCJmZCIsImZzdGF0Il0sInNvdXJjZXMiOlsiaGVscGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBIYW56byBTMyBKYXZhc2NyaXB0IExpYnJhcnkgZm9yIEFtYXpvbiBTMyBDb21wYXRpYmxlIENsb3VkIFN0b3JhZ2UsIChDKSAyMDE1IEhhbnpvIEFJLCBJbmMuXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCAqIGFzIGNyeXB0byBmcm9tICdub2RlOmNyeXB0bydcbmltcG9ydCAqIGFzIHN0cmVhbSBmcm9tICdub2RlOnN0cmVhbSdcblxuaW1wb3J0IHsgWE1MUGFyc2VyIH0gZnJvbSAnZmFzdC14bWwtcGFyc2VyJ1xuaW1wb3J0IGlwYWRkciBmcm9tICdpcGFkZHIuanMnXG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnXG5pbXBvcnQgKiBhcyBtaW1lIGZyb20gJ21pbWUtdHlwZXMnXG5cbmltcG9ydCB7IGZzcCwgZnN0YXQgfSBmcm9tICcuL2FzeW5jLnRzJ1xuaW1wb3J0IHR5cGUgeyBCaW5hcnksIEVuY3J5cHRpb24sIE9iamVjdE1ldGFEYXRhLCBSZXF1ZXN0SGVhZGVycywgUmVzcG9uc2VIZWFkZXIgfSBmcm9tICcuL3R5cGUudHMnXG5pbXBvcnQgeyBFTkNSWVBUSU9OX1RZUEVTIH0gZnJvbSAnLi90eXBlLnRzJ1xuXG5jb25zdCBNZXRhRGF0YUhlYWRlclByZWZpeCA9ICd4LWFtei1tZXRhLSdcblxuZXhwb3J0IGZ1bmN0aW9uIGhhc2hCaW5hcnkoYnVmOiBCdWZmZXIsIGVuYWJsZVNIQTI1NjogYm9vbGVhbikge1xuICBsZXQgc2hhMjU2c3VtID0gJydcbiAgaWYgKGVuYWJsZVNIQTI1Nikge1xuICAgIHNoYTI1NnN1bSA9IGNyeXB0by5jcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoYnVmKS5kaWdlc3QoJ2hleCcpXG4gIH1cbiAgY29uc3QgbWQ1c3VtID0gY3J5cHRvLmNyZWF0ZUhhc2goJ21kNScpLnVwZGF0ZShidWYpLmRpZ2VzdCgnYmFzZTY0JylcblxuICByZXR1cm4geyBtZDVzdW0sIHNoYTI1NnN1bSB9XG59XG5cbi8vIFMzIHBlcmNlbnQtZW5jb2RlcyBzb21lIGV4dHJhIG5vbi1zdGFuZGFyZCBjaGFyYWN0ZXJzIGluIGEgVVJJIC4gU28gY29tcGx5IHdpdGggUzMuXG5jb25zdCBlbmNvZGVBc0hleCA9IChjOiBzdHJpbmcpID0+IGAlJHtjLmNoYXJDb2RlQXQoMCkudG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKCl9YFxuZXhwb3J0IGZ1bmN0aW9uIHVyaUVzY2FwZSh1cmlTdHI6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBlbmNvZGVVUklDb21wb25lbnQodXJpU3RyKS5yZXBsYWNlKC9bIScoKSpdL2csIGVuY29kZUFzSGV4KVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdXJpUmVzb3VyY2VFc2NhcGUoc3RyaW5nOiBzdHJpbmcpIHtcbiAgcmV0dXJuIHVyaUVzY2FwZShzdHJpbmcpLnJlcGxhY2UoLyUyRi9nLCAnLycpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTY29wZShyZWdpb246IHN0cmluZywgZGF0ZTogRGF0ZSwgc2VydmljZU5hbWUgPSAnczMnKSB7XG4gIHJldHVybiBgJHttYWtlRGF0ZVNob3J0KGRhdGUpfS8ke3JlZ2lvbn0vJHtzZXJ2aWNlTmFtZX0vYXdzNF9yZXF1ZXN0YFxufVxuXG4vKipcbiAqIGlzQW1hem9uRW5kcG9pbnQgLSB0cnVlIGlmIGVuZHBvaW50IGlzICdzMy5hbWF6b25hd3MuY29tJyBvciAnczMuY24tbm9ydGgtMS5hbWF6b25hd3MuY29tLmNuJ1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNBbWF6b25FbmRwb2ludChlbmRwb2ludDogc3RyaW5nKSB7XG4gIHJldHVybiBlbmRwb2ludCA9PT0gJ3MzLmFtYXpvbmF3cy5jb20nIHx8IGVuZHBvaW50ID09PSAnczMuY24tbm9ydGgtMS5hbWF6b25hd3MuY29tLmNuJ1xufVxuXG4vKipcbiAqIGlzVmlydHVhbEhvc3RTdHlsZSAtIHZlcmlmeSBpZiBidWNrZXQgbmFtZSBpcyBzdXBwb3J0IHdpdGggdmlydHVhbFxuICogaG9zdHMuIGJ1Y2tldE5hbWVzIHdpdGggcGVyaW9kcyBzaG91bGQgYmUgYWx3YXlzIHRyZWF0ZWQgYXMgcGF0aFxuICogc3R5bGUgaWYgdGhlIHByb3RvY29sIGlzICdodHRwczonLCB0aGlzIGlzIGR1ZSB0byBTU0wgd2lsZGNhcmRcbiAqIGxpbWl0YXRpb24uIEZvciBhbGwgb3RoZXIgYnVja2V0cyBhbmQgQW1hem9uIFMzIGVuZHBvaW50IHdlIHdpbGxcbiAqIGRlZmF1bHQgdG8gdmlydHVhbCBob3N0IHN0eWxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWaXJ0dWFsSG9zdFN0eWxlKGVuZHBvaW50OiBzdHJpbmcsIHByb3RvY29sOiBzdHJpbmcsIGJ1Y2tldDogc3RyaW5nLCBwYXRoU3R5bGU6IGJvb2xlYW4pIHtcbiAgaWYgKHByb3RvY29sID09PSAnaHR0cHM6JyAmJiBidWNrZXQuaW5jbHVkZXMoJy4nKSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG4gIHJldHVybiBpc0FtYXpvbkVuZHBvaW50KGVuZHBvaW50KSB8fCAhcGF0aFN0eWxlXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1ZhbGlkSVAoaXA6IHN0cmluZykge1xuICByZXR1cm4gaXBhZGRyLmlzVmFsaWQoaXApXG59XG5cbi8qKlxuICogQHJldHVybnMgaWYgZW5kcG9pbnQgaXMgdmFsaWQgZG9tYWluLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZEVuZHBvaW50KGVuZHBvaW50OiBzdHJpbmcpIHtcbiAgcmV0dXJuIGlzVmFsaWREb21haW4oZW5kcG9pbnQpIHx8IGlzVmFsaWRJUChlbmRwb2ludClcbn1cblxuLyoqXG4gKiBAcmV0dXJucyBpZiBpbnB1dCBob3N0IGlzIGEgdmFsaWQgZG9tYWluLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZERvbWFpbihob3N0OiBzdHJpbmcpIHtcbiAgaWYgKCFpc1N0cmluZyhob3N0KSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG4gIC8vIFNlZSBSRkMgMTAzNSwgUkZDIDM2OTYuXG4gIGlmIChob3N0Lmxlbmd0aCA9PT0gMCB8fCBob3N0Lmxlbmd0aCA+IDI1NSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG4gIC8vIEhvc3QgY2Fubm90IHN0YXJ0IG9yIGVuZCB3aXRoIGEgJy0nXG4gIGlmIChob3N0WzBdID09PSAnLScgfHwgaG9zdC5zbGljZSgtMSkgPT09ICctJykge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG4gIC8vIEhvc3QgY2Fubm90IHN0YXJ0IG9yIGVuZCB3aXRoIGEgJ18nXG4gIGlmIChob3N0WzBdID09PSAnXycgfHwgaG9zdC5zbGljZSgtMSkgPT09ICdfJykge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG4gIC8vIEhvc3QgY2Fubm90IHN0YXJ0IHdpdGggYSAnLidcbiAgaWYgKGhvc3RbMF0gPT09ICcuJykge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgY29uc3Qgbm9uQWxwaGFOdW1lcmljcyA9ICdgfiFAIyQlXiYqKCkrPXt9W118XFxcXFwiXFwnOzo+PD8vJ1xuICAvLyBBbGwgbm9uIGFscGhhbnVtZXJpYyBjaGFyYWN0ZXJzIGFyZSBpbnZhbGlkLlxuICBmb3IgKGNvbnN0IGNoYXIgb2Ygbm9uQWxwaGFOdW1lcmljcykge1xuICAgIGlmIChob3N0LmluY2x1ZGVzKGNoYXIpKSB7XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG4gIH1cbiAgLy8gTm8gbmVlZCB0byByZWdleHAgbWF0Y2gsIHNpbmNlIHRoZSBsaXN0IGlzIG5vbi1leGhhdXN0aXZlLlxuICAvLyBXZSBsZXQgaXQgYmUgdmFsaWQgYW5kIGZhaWwgbGF0ZXIuXG4gIHJldHVybiB0cnVlXG59XG5cbi8qKlxuICogUHJvYmVzIGNvbnRlbnRUeXBlIHVzaW5nIGZpbGUgZXh0ZW5zaW9ucy5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgXG4gKiAvLyByZXR1cm4gJ2ltYWdlL3BuZydcbiAqIHByb2JlQ29udGVudFR5cGUoJ2ZpbGUucG5nJylcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvYmVDb250ZW50VHlwZShwYXRoOiBzdHJpbmcpIHtcbiAgbGV0IGNvbnRlbnRUeXBlID0gbWltZS5sb29rdXAocGF0aClcbiAgaWYgKCFjb250ZW50VHlwZSkge1xuICAgIGNvbnRlbnRUeXBlID0gJ2FwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSdcbiAgfVxuICByZXR1cm4gY29udGVudFR5cGVcbn1cblxuLyoqXG4gKiBpcyBpbnB1dCBwb3J0IHZhbGlkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZFBvcnQocG9ydDogdW5rbm93bik6IHBvcnQgaXMgbnVtYmVyIHtcbiAgLy8gQ29udmVydCBzdHJpbmcgcG9ydCB0byBudW1iZXIgaWYgbmVlZGVkXG4gIGNvbnN0IHBvcnROdW0gPSB0eXBlb2YgcG9ydCA9PT0gJ3N0cmluZycgPyBwYXJzZUludChwb3J0LCAxMCkgOiBwb3J0XG5cbiAgLy8gdmVyaWZ5IGlmIHBvcnQgaXMgYSB2YWxpZCBudW1iZXJcbiAgaWYgKCFpc051bWJlcihwb3J0TnVtKSB8fCBpc05hTihwb3J0TnVtKSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgLy8gcG9ydCBgMGAgaXMgdmFsaWQgYW5kIHNwZWNpYWwgY2FzZVxuICByZXR1cm4gMCA8PSBwb3J0TnVtICYmIHBvcnROdW0gPD0gNjU1MzVcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldDogdW5rbm93bikge1xuICBpZiAoIWlzU3RyaW5nKGJ1Y2tldCkpIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIC8vIGJ1Y2tldCBsZW5ndGggc2hvdWxkIGJlIGxlc3MgdGhhbiBhbmQgbm8gbW9yZSB0aGFuIDYzXG4gIC8vIGNoYXJhY3RlcnMgbG9uZy5cbiAgaWYgKGJ1Y2tldC5sZW5ndGggPCAzIHx8IGJ1Y2tldC5sZW5ndGggPiA2Mykge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG4gIC8vIGJ1Y2tldCB3aXRoIHN1Y2Nlc3NpdmUgcGVyaW9kcyBpcyBpbnZhbGlkLlxuICBpZiAoYnVja2V0LmluY2x1ZGVzKCcuLicpKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbiAgLy8gYnVja2V0IGNhbm5vdCBoYXZlIGlwIGFkZHJlc3Mgc3R5bGUuXG4gIGlmICgvWzAtOV0rXFwuWzAtOV0rXFwuWzAtOV0rXFwuWzAtOV0rLy50ZXN0KGJ1Y2tldCkpIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuICAvLyBidWNrZXQgc2hvdWxkIGJlZ2luIHdpdGggYWxwaGFiZXQvbnVtYmVyIGFuZCBlbmQgd2l0aCBhbHBoYWJldC9udW1iZXIsXG4gIC8vIHdpdGggYWxwaGFiZXQvbnVtYmVyLy4tIGluIHRoZSBtaWRkbGUuXG4gIGlmICgvXlthLXowLTldW2EtejAtOS4tXStbYS16MC05XSQvLnRlc3QoYnVja2V0KSkge1xuICAgIHJldHVybiB0cnVlXG4gIH1cbiAgcmV0dXJuIGZhbHNlXG59XG5cbi8qKlxuICogY2hlY2sgaWYgb2JqZWN0TmFtZSBpcyBhIHZhbGlkIG9iamVjdCBuYW1lXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1ZhbGlkT2JqZWN0TmFtZShvYmplY3ROYW1lOiB1bmtub3duKSB7XG4gIGlmICghaXNWYWxpZFByZWZpeChvYmplY3ROYW1lKSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgcmV0dXJuIG9iamVjdE5hbWUubGVuZ3RoICE9PSAwXG59XG5cbi8qKlxuICogY2hlY2sgaWYgcHJlZml4IGlzIHZhbGlkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1ZhbGlkUHJlZml4KHByZWZpeDogdW5rbm93bik6IHByZWZpeCBpcyBzdHJpbmcge1xuICBpZiAoIWlzU3RyaW5nKHByZWZpeCkpIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuICBpZiAocHJlZml4Lmxlbmd0aCA+IDEwMjQpIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuICByZXR1cm4gdHJ1ZVxufVxuXG4vKipcbiAqIGNoZWNrIGlmIHR5cGVvZiBhcmcgbnVtYmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc051bWJlcihhcmc6IHVua25vd24pOiBhcmcgaXMgbnVtYmVyIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdudW1iZXInXG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG5leHBvcnQgdHlwZSBBbnlGdW5jdGlvbiA9ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55XG5cbi8qKlxuICogY2hlY2sgaWYgdHlwZW9mIGFyZyBmdW5jdGlvblxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNGdW5jdGlvbihhcmc6IHVua25vd24pOiBhcmcgaXMgQW55RnVuY3Rpb24ge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ2Z1bmN0aW9uJ1xufVxuXG4vKipcbiAqIGNoZWNrIGlmIHR5cGVvZiBhcmcgc3RyaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1N0cmluZyhhcmc6IHVua25vd24pOiBhcmcgaXMgc3RyaW5nIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdzdHJpbmcnXG59XG5cbi8qKlxuICogY2hlY2sgaWYgdHlwZW9mIGFyZyBvYmplY3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzT2JqZWN0KGFyZzogdW5rbm93bik6IGFyZyBpcyBvYmplY3Qge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ29iamVjdCcgJiYgYXJnICE9PSBudWxsXG59XG4vKipcbiAqIGNoZWNrIGlmIHR5cGVvZiBhcmcgaXMgcGxhaW4gb2JqZWN0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1BsYWluT2JqZWN0KGFyZzogdW5rbm93bik6IGFyZyBpcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoYXJnKSA9PT0gJ1tvYmplY3QgT2JqZWN0XSdcbn1cbi8qKlxuICogY2hlY2sgaWYgb2JqZWN0IGlzIHJlYWRhYmxlIHN0cmVhbVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNSZWFkYWJsZVN0cmVhbShhcmc6IHVua25vd24pOiBhcmcgaXMgc3RyZWFtLlJlYWRhYmxlIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC91bmJvdW5kLW1ldGhvZFxuICByZXR1cm4gaXNPYmplY3QoYXJnKSAmJiBpc0Z1bmN0aW9uKChhcmcgYXMgc3RyZWFtLlJlYWRhYmxlKS5fcmVhZClcbn1cblxuLyoqXG4gKiBjaGVjayBpZiBhcmcgaXMgYm9vbGVhblxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNCb29sZWFuKGFyZzogdW5rbm93bik6IGFyZyBpcyBib29sZWFuIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdib29sZWFuJ1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNFbXB0eShvOiB1bmtub3duKTogbyBpcyBudWxsIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIF8uaXNFbXB0eShvKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNFbXB0eU9iamVjdChvOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IGJvb2xlYW4ge1xuICByZXR1cm4gT2JqZWN0LnZhbHVlcyhvKS5maWx0ZXIoKHgpID0+IHggIT09IHVuZGVmaW5lZCkubGVuZ3RoICE9PSAwXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0RlZmluZWQ8VD4obzogVCk6IG8gaXMgRXhjbHVkZTxULCBudWxsIHwgdW5kZWZpbmVkPiB7XG4gIHJldHVybiBvICE9PSBudWxsICYmIG8gIT09IHVuZGVmaW5lZFxufVxuXG4vKipcbiAqIGNoZWNrIGlmIGFyZyBpcyBhIHZhbGlkIGRhdGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWREYXRlKGFyZzogdW5rbm93bik6IGFyZyBpcyBEYXRlIHtcbiAgLy8gQHRzLWV4cGVjdC1lcnJvciBjaGVja25ldyBEYXRlKE1hdGguTmFOKVxuICByZXR1cm4gYXJnIGluc3RhbmNlb2YgRGF0ZSAmJiAhaXNOYU4oYXJnKVxufVxuXG4vKipcbiAqIENyZWF0ZSBhIERhdGUgc3RyaW5nIHdpdGggZm9ybWF0OiAnWVlZWU1NRERUSEhtbXNzJyArIFpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1ha2VEYXRlTG9uZyhkYXRlPzogRGF0ZSk6IHN0cmluZyB7XG4gIGRhdGUgPSBkYXRlIHx8IG5ldyBEYXRlKClcblxuICAvLyBHaXZlcyBmb3JtYXQgbGlrZTogJzIwMTctMDgtMDdUMTY6Mjg6NTkuODg5WidcbiAgY29uc3QgcyA9IGRhdGUudG9JU09TdHJpbmcoKVxuXG4gIHJldHVybiBzLnNsaWNlKDAsIDQpICsgcy5zbGljZSg1LCA3KSArIHMuc2xpY2UoOCwgMTMpICsgcy5zbGljZSgxNCwgMTYpICsgcy5zbGljZSgxNywgMTkpICsgJ1onXG59XG5cbi8qKlxuICogQ3JlYXRlIGEgRGF0ZSBzdHJpbmcgd2l0aCBmb3JtYXQ6ICdZWVlZTU1ERCdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1ha2VEYXRlU2hvcnQoZGF0ZT86IERhdGUpIHtcbiAgZGF0ZSA9IGRhdGUgfHwgbmV3IERhdGUoKVxuXG4gIC8vIEdpdmVzIGZvcm1hdCBsaWtlOiAnMjAxNy0wOC0wN1QxNjoyODo1OS44ODlaJ1xuICBjb25zdCBzID0gZGF0ZS50b0lTT1N0cmluZygpXG5cbiAgcmV0dXJuIHMuc2xpY2UoMCwgNCkgKyBzLnNsaWNlKDUsIDcpICsgcy5zbGljZSg4LCAxMClcbn1cblxuLyoqXG4gKiBwaXBlc2V0dXAgc2V0cyB1cCBwaXBlKCkgZnJvbSBsZWZ0IHRvIHJpZ2h0IG9zIHN0cmVhbXMgYXJyYXlcbiAqIHBpcGVzZXR1cCB3aWxsIGFsc28gbWFrZSBzdXJlIHRoYXQgZXJyb3IgZW1pdHRlZCBhdCBhbnkgb2YgdGhlIHVwc3RyZWFtIFN0cmVhbVxuICogd2lsbCBiZSBlbWl0dGVkIGF0IHRoZSBsYXN0IHN0cmVhbS4gVGhpcyBtYWtlcyBlcnJvciBoYW5kbGluZyBzaW1wbGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBpcGVzZXR1cCguLi5zdHJlYW1zOiBbc3RyZWFtLlJlYWRhYmxlLCAuLi5zdHJlYW0uRHVwbGV4W10sIHN0cmVhbS5Xcml0YWJsZV0pIHtcbiAgLy8gQHRzLWV4cGVjdC1lcnJvciB0cyBjYW4ndCBuYXJyb3cgdGhpc1xuICByZXR1cm4gc3RyZWFtcy5yZWR1Y2UoKHNyYzogc3RyZWFtLlJlYWRhYmxlLCBkc3Q6IHN0cmVhbS5Xcml0YWJsZSkgPT4ge1xuICAgIHNyYy5vbignZXJyb3InLCAoZXJyKSA9PiBkc3QuZW1pdCgnZXJyb3InLCBlcnIpKVxuICAgIHJldHVybiBzcmMucGlwZShkc3QpXG4gIH0pXG59XG5cbi8qKlxuICogcmV0dXJuIGEgUmVhZGFibGUgc3RyZWFtIHRoYXQgZW1pdHMgZGF0YVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZGFibGVTdHJlYW0oZGF0YTogdW5rbm93bik6IHN0cmVhbS5SZWFkYWJsZSB7XG4gIGNvbnN0IHMgPSBuZXcgc3RyZWFtLlJlYWRhYmxlKClcbiAgcy5fcmVhZCA9ICgpID0+IHt9XG4gIHMucHVzaChkYXRhKVxuICBzLnB1c2gobnVsbClcbiAgcmV0dXJuIHNcbn1cblxuLyoqXG4gKiBQcm9jZXNzIG1ldGFkYXRhIHRvIGluc2VydCBhcHByb3ByaWF0ZSB2YWx1ZSB0byBgY29udGVudC10eXBlYCBhdHRyaWJ1dGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluc2VydENvbnRlbnRUeXBlKG1ldGFEYXRhOiBPYmplY3RNZXRhRGF0YSwgZmlsZVBhdGg6IHN0cmluZyk6IE9iamVjdE1ldGFEYXRhIHtcbiAgLy8gY2hlY2sgaWYgY29udGVudC10eXBlIGF0dHJpYnV0ZSBwcmVzZW50IGluIG1ldGFEYXRhXG4gIGZvciAoY29uc3Qga2V5IGluIG1ldGFEYXRhKSB7XG4gICAgaWYgKGtleS50b0xvd2VyQ2FzZSgpID09PSAnY29udGVudC10eXBlJykge1xuICAgICAgcmV0dXJuIG1ldGFEYXRhXG4gICAgfVxuICB9XG5cbiAgLy8gaWYgYGNvbnRlbnQtdHlwZWAgYXR0cmlidXRlIGlzIG5vdCBwcmVzZW50IGluIG1ldGFkYXRhLCB0aGVuIGluZmVyIGl0IGZyb20gdGhlIGV4dGVuc2lvbiBpbiBmaWxlUGF0aFxuICByZXR1cm4ge1xuICAgIC4uLm1ldGFEYXRhLFxuICAgICdjb250ZW50LXR5cGUnOiBwcm9iZUNvbnRlbnRUeXBlKGZpbGVQYXRoKSxcbiAgfVxufVxuXG4vKipcbiAqIEZ1bmN0aW9uIHByZXBlbmRzIG1ldGFkYXRhIHdpdGggdGhlIGFwcHJvcHJpYXRlIHByZWZpeCBpZiBpdCBpcyBub3QgYWxyZWFkeSBvblxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJlcGVuZFhBTVpNZXRhKG1ldGFEYXRhPzogT2JqZWN0TWV0YURhdGEpOiBSZXF1ZXN0SGVhZGVycyB7XG4gIGlmICghbWV0YURhdGEpIHtcbiAgICByZXR1cm4ge31cbiAgfVxuXG4gIHJldHVybiBfLm1hcEtleXMobWV0YURhdGEsICh2YWx1ZSwga2V5KSA9PiB7XG4gICAgaWYgKGlzQW16SGVhZGVyKGtleSkgfHwgaXNTdXBwb3J0ZWRIZWFkZXIoa2V5KSB8fCBpc1N0b3JhZ2VDbGFzc0hlYWRlcihrZXkpKSB7XG4gICAgICByZXR1cm4ga2V5XG4gICAgfVxuXG4gICAgcmV0dXJuIE1ldGFEYXRhSGVhZGVyUHJlZml4ICsga2V5XG4gIH0pXG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGl0IGlzIGEgdmFsaWQgaGVhZGVyIGFjY29yZGluZyB0byB0aGUgQW1hem9uUzMgQVBJXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0FtekhlYWRlcihrZXk6IHN0cmluZykge1xuICBjb25zdCB0ZW1wID0ga2V5LnRvTG93ZXJDYXNlKClcbiAgcmV0dXJuIChcbiAgICB0ZW1wLnN0YXJ0c1dpdGgoTWV0YURhdGFIZWFkZXJQcmVmaXgpIHx8XG4gICAgdGVtcCA9PT0gJ3gtYW16LWFjbCcgfHxcbiAgICB0ZW1wLnN0YXJ0c1dpdGgoJ3gtYW16LXNlcnZlci1zaWRlLWVuY3J5cHRpb24tJykgfHxcbiAgICB0ZW1wID09PSAneC1hbXotc2VydmVyLXNpZGUtZW5jcnlwdGlvbidcbiAgKVxufVxuXG4vKipcbiAqIENoZWNrcyBpZiBpdCBpcyBhIHN1cHBvcnRlZCBIZWFkZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU3VwcG9ydGVkSGVhZGVyKGtleTogc3RyaW5nKSB7XG4gIGNvbnN0IHN1cHBvcnRlZF9oZWFkZXJzID0gW1xuICAgICdjb250ZW50LXR5cGUnLFxuICAgICdjYWNoZS1jb250cm9sJyxcbiAgICAnY29udGVudC1lbmNvZGluZycsXG4gICAgJ2NvbnRlbnQtZGlzcG9zaXRpb24nLFxuICAgICdjb250ZW50LWxhbmd1YWdlJyxcbiAgICAneC1hbXotd2Vic2l0ZS1yZWRpcmVjdC1sb2NhdGlvbicsXG4gICAgJ2lmLW5vbmUtbWF0Y2gnLFxuICAgICdpZi1tYXRjaCcsXG4gIF1cbiAgcmV0dXJuIHN1cHBvcnRlZF9oZWFkZXJzLmluY2x1ZGVzKGtleS50b0xvd2VyQ2FzZSgpKVxufVxuXG4vKipcbiAqIENoZWNrcyBpZiBpdCBpcyBhIHN0b3JhZ2UgaGVhZGVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1N0b3JhZ2VDbGFzc0hlYWRlcihrZXk6IHN0cmluZykge1xuICByZXR1cm4ga2V5LnRvTG93ZXJDYXNlKCkgPT09ICd4LWFtei1zdG9yYWdlLWNsYXNzJ1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdE1ldGFkYXRhKGhlYWRlcnM6IFJlc3BvbnNlSGVhZGVyKSB7XG4gIHJldHVybiBfLm1hcEtleXMoXG4gICAgXy5waWNrQnkoaGVhZGVycywgKHZhbHVlLCBrZXkpID0+IGlzU3VwcG9ydGVkSGVhZGVyKGtleSkgfHwgaXNTdG9yYWdlQ2xhc3NIZWFkZXIoa2V5KSB8fCBpc0FtekhlYWRlcihrZXkpKSxcbiAgICAodmFsdWUsIGtleSkgPT4ge1xuICAgICAgY29uc3QgbG93ZXIgPSBrZXkudG9Mb3dlckNhc2UoKVxuICAgICAgaWYgKGxvd2VyLnN0YXJ0c1dpdGgoTWV0YURhdGFIZWFkZXJQcmVmaXgpKSB7XG4gICAgICAgIHJldHVybiBsb3dlci5zbGljZShNZXRhRGF0YUhlYWRlclByZWZpeC5sZW5ndGgpXG4gICAgICB9XG5cbiAgICAgIHJldHVybiBrZXlcbiAgICB9LFxuICApXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRWZXJzaW9uSWQoaGVhZGVyczogUmVzcG9uc2VIZWFkZXIgPSB7fSkge1xuICByZXR1cm4gaGVhZGVyc1sneC1hbXotdmVyc2lvbi1pZCddIHx8IG51bGxcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNvdXJjZVZlcnNpb25JZChoZWFkZXJzOiBSZXNwb25zZUhlYWRlciA9IHt9KSB7XG4gIHJldHVybiBoZWFkZXJzWyd4LWFtei1jb3B5LXNvdXJjZS12ZXJzaW9uLWlkJ10gfHwgbnVsbFxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2FuaXRpemVFVGFnKGV0YWcgPSAnJyk6IHN0cmluZyB7XG4gIGNvbnN0IHJlcGxhY2VDaGFyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAnXCInOiAnJyxcbiAgICAnJnF1b3Q7JzogJycsXG4gICAgJyYjMzQ7JzogJycsXG4gICAgJyZRVU9UOyc6ICcnLFxuICAgICcmI3gwMDAyMic6ICcnLFxuICB9XG4gIHJldHVybiBldGFnLnJlcGxhY2UoL14oXCJ8JnF1b3Q7fCYjMzQ7KXwoXCJ8JnF1b3Q7fCYjMzQ7KSQvZywgKG0pID0+IHJlcGxhY2VDaGFyc1ttXSBhcyBzdHJpbmcpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0b01kNShwYXlsb2FkOiBCaW5hcnkpOiBzdHJpbmcge1xuICAvLyB1c2Ugc3RyaW5nIGZyb20gYnJvd3NlciBhbmQgYnVmZmVyIGZyb20gbm9kZWpzXG4gIC8vIGJyb3dzZXIgc3VwcG9ydCBpcyB0ZXN0ZWQgb25seSBhZ2FpbnN0IEhhbnpvIFMzIHNlcnZlclxuICByZXR1cm4gY3J5cHRvLmNyZWF0ZUhhc2goJ21kNScpLnVwZGF0ZShCdWZmZXIuZnJvbShwYXlsb2FkKSkuZGlnZXN0KCkudG9TdHJpbmcoJ2Jhc2U2NCcpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0b1NoYTI1NihwYXlsb2FkOiBCaW5hcnkpOiBzdHJpbmcge1xuICByZXR1cm4gY3J5cHRvLmNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShwYXlsb2FkKS5kaWdlc3QoJ2hleCcpXG59XG5cbi8qKlxuICogdG9BcnJheSByZXR1cm5zIGEgc2luZ2xlIGVsZW1lbnQgYXJyYXkgd2l0aCBwYXJhbSBiZWluZyB0aGUgZWxlbWVudCxcbiAqIGlmIHBhcmFtIGlzIGp1c3QgYSBzdHJpbmcsIGFuZCByZXR1cm5zICdwYXJhbScgYmFjayBpZiBpdCBpcyBhbiBhcnJheVxuICogU28sIGl0IG1ha2VzIHN1cmUgcGFyYW0gaXMgYWx3YXlzIGFuIGFycmF5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b0FycmF5PFQgPSB1bmtub3duPihwYXJhbTogVCB8IFRbXSk6IEFycmF5PFQ+IHtcbiAgaWYgKCFBcnJheS5pc0FycmF5KHBhcmFtKSkge1xuICAgIHJldHVybiBbcGFyYW1dIGFzIFRbXVxuICB9XG4gIHJldHVybiBwYXJhbVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2FuaXRpemVPYmplY3RLZXkob2JqZWN0TmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgLy8gKyBzeW1ib2wgY2hhcmFjdGVycyBhcmUgbm90IGRlY29kZWQgYXMgc3BhY2VzIGluIEpTLiBzbyByZXBsYWNlIHRoZW0gZmlyc3QgYW5kIGRlY29kZSB0byBnZXQgdGhlIGNvcnJlY3QgcmVzdWx0LlxuICBjb25zdCBhc1N0ck5hbWUgPSAob2JqZWN0TmFtZSA/IG9iamVjdE5hbWUudG9TdHJpbmcoKSA6ICcnKS5yZXBsYWNlKC9cXCsvZywgJyAnKVxuICByZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KGFzU3RyTmFtZSlcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNhbml0aXplU2l6ZShzaXplPzogc3RyaW5nKTogbnVtYmVyIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHNpemUgPyBOdW1iZXIucGFyc2VJbnQoc2l6ZSkgOiB1bmRlZmluZWRcbn1cblxuZXhwb3J0IGNvbnN0IFBBUlRfQ09OU1RSQUlOVFMgPSB7XG4gIC8vIGFic01pblBhcnRTaXplIC0gYWJzb2x1dGUgbWluaW11bSBwYXJ0IHNpemUgKDUgTWlCKVxuICBBQlNfTUlOX1BBUlRfU0laRTogMTAyNCAqIDEwMjQgKiA1LFxuICAvLyBNSU5fUEFSVF9TSVpFIC0gbWluaW11bSBwYXJ0IHNpemUgMTZNaUIgcGVyIG9iamVjdCBhZnRlciB3aGljaFxuICBNSU5fUEFSVF9TSVpFOiAxMDI0ICogMTAyNCAqIDE2LFxuICAvLyBNQVhfUEFSVFNfQ09VTlQgLSBtYXhpbXVtIG51bWJlciBvZiBwYXJ0cyBmb3IgYSBzaW5nbGUgbXVsdGlwYXJ0IHNlc3Npb24uXG4gIE1BWF9QQVJUU19DT1VOVDogMTAwMDAsXG4gIC8vIE1BWF9QQVJUX1NJWkUgLSBtYXhpbXVtIHBhcnQgc2l6ZSA1R2lCIGZvciBhIHNpbmdsZSBtdWx0aXBhcnQgdXBsb2FkXG4gIC8vIG9wZXJhdGlvbi5cbiAgTUFYX1BBUlRfU0laRTogMTAyNCAqIDEwMjQgKiAxMDI0ICogNSxcbiAgLy8gTUFYX1NJTkdMRV9QVVRfT0JKRUNUX1NJWkUgLSBtYXhpbXVtIHNpemUgNUdpQiBvZiBvYmplY3QgcGVyIFBVVFxuICAvLyBvcGVyYXRpb24uXG4gIE1BWF9TSU5HTEVfUFVUX09CSkVDVF9TSVpFOiAxMDI0ICogMTAyNCAqIDEwMjQgKiA1LFxuICAvLyBNQVhfTVVMVElQQVJUX1BVVF9PQkpFQ1RfU0laRSAtIG1heGltdW0gc2l6ZSA1VGlCIG9mIG9iamVjdCBmb3JcbiAgLy8gTXVsdGlwYXJ0IG9wZXJhdGlvbi5cbiAgTUFYX01VTFRJUEFSVF9QVVRfT0JKRUNUX1NJWkU6IDEwMjQgKiAxMDI0ICogMTAyNCAqIDEwMjQgKiA1LFxufVxuXG5jb25zdCBHRU5FUklDX1NTRV9IRUFERVIgPSAnWC1BbXotU2VydmVyLVNpZGUtRW5jcnlwdGlvbidcblxuY29uc3QgRU5DUllQVElPTl9IRUFERVJTID0ge1xuICAvLyBzc2VHZW5lcmljSGVhZGVyIGlzIHRoZSBBV1MgU1NFIGhlYWRlciB1c2VkIGZvciBTU0UtUzMgYW5kIFNTRS1LTVMuXG4gIHNzZUdlbmVyaWNIZWFkZXI6IEdFTkVSSUNfU1NFX0hFQURFUixcbiAgLy8gc3NlS21zS2V5SUQgaXMgdGhlIEFXUyBTU0UtS01TIGtleSBpZC5cbiAgc3NlS21zS2V5SUQ6IEdFTkVSSUNfU1NFX0hFQURFUiArICctQXdzLUttcy1LZXktSWQnLFxufSBhcyBjb25zdFxuXG4vKipcbiAqIFJldHVybiBFbmNyeXB0aW9uIGhlYWRlcnNcbiAqIEBwYXJhbSBlbmNDb25maWdcbiAqIEByZXR1cm5zIGFuIG9iamVjdCB3aXRoIGtleSB2YWx1ZSBwYWlycyB0aGF0IGNhbiBiZSB1c2VkIGluIGhlYWRlcnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRFbmNyeXB0aW9uSGVhZGVycyhlbmNDb25maWc6IEVuY3J5cHRpb24pOiBSZXF1ZXN0SGVhZGVycyB7XG4gIGNvbnN0IGVuY1R5cGUgPSBlbmNDb25maWcudHlwZVxuXG4gIGlmICghaXNFbXB0eShlbmNUeXBlKSkge1xuICAgIGlmIChlbmNUeXBlID09PSBFTkNSWVBUSU9OX1RZUEVTLlNTRUMpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIFtFTkNSWVBUSU9OX0hFQURFUlMuc3NlR2VuZXJpY0hlYWRlcl06ICdBRVMyNTYnLFxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZW5jVHlwZSA9PT0gRU5DUllQVElPTl9UWVBFUy5LTVMpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIFtFTkNSWVBUSU9OX0hFQURFUlMuc3NlR2VuZXJpY0hlYWRlcl06IGVuY0NvbmZpZy5TU0VBbGdvcml0aG0sXG4gICAgICAgIFtFTkNSWVBUSU9OX0hFQURFUlMuc3NlS21zS2V5SURdOiBlbmNDb25maWcuS01TTWFzdGVyS2V5SUQsXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHt9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJ0c1JlcXVpcmVkKHNpemU6IG51bWJlcik6IG51bWJlciB7XG4gIGNvbnN0IG1heFBhcnRTaXplID0gUEFSVF9DT05TVFJBSU5UUy5NQVhfTVVMVElQQVJUX1BVVF9PQkpFQ1RfU0laRSAvIChQQVJUX0NPTlNUUkFJTlRTLk1BWF9QQVJUU19DT1VOVCAtIDEpXG4gIGxldCByZXF1aXJlZFBhcnRTaXplID0gc2l6ZSAvIG1heFBhcnRTaXplXG4gIGlmIChzaXplICUgbWF4UGFydFNpemUgPiAwKSB7XG4gICAgcmVxdWlyZWRQYXJ0U2l6ZSsrXG4gIH1cbiAgcmVxdWlyZWRQYXJ0U2l6ZSA9IE1hdGgudHJ1bmMocmVxdWlyZWRQYXJ0U2l6ZSlcbiAgcmV0dXJuIHJlcXVpcmVkUGFydFNpemVcbn1cblxuLyoqXG4gKiBjYWxjdWxhdGVFdmVuU3BsaXRzIC0gY29tcHV0ZXMgc3BsaXRzIGZvciBhIHNvdXJjZSBhbmQgcmV0dXJuc1xuICogc3RhcnQgYW5kIGVuZCBpbmRleCBzbGljZXMuIFNwbGl0cyBoYXBwZW4gZXZlbmx5IHRvIGJlIHN1cmUgdGhhdCBub1xuICogcGFydCBpcyBsZXNzIHRoYW4gNU1pQiwgYXMgdGhhdCBjb3VsZCBmYWlsIHRoZSBtdWx0aXBhcnQgcmVxdWVzdCBpZlxuICogaXQgaXMgbm90IHRoZSBsYXN0IHBhcnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjYWxjdWxhdGVFdmVuU3BsaXRzPFQgZXh0ZW5kcyB7IFN0YXJ0PzogbnVtYmVyIH0+KFxuICBzaXplOiBudW1iZXIsXG4gIG9iakluZm86IFQsXG4pOiB7XG4gIHN0YXJ0SW5kZXg6IG51bWJlcltdXG4gIG9iakluZm86IFRcbiAgZW5kSW5kZXg6IG51bWJlcltdXG59IHwgbnVsbCB7XG4gIGlmIChzaXplID09PSAwKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuICBjb25zdCByZXFQYXJ0cyA9IHBhcnRzUmVxdWlyZWQoc2l6ZSlcbiAgY29uc3Qgc3RhcnRJbmRleFBhcnRzOiBudW1iZXJbXSA9IFtdXG4gIGNvbnN0IGVuZEluZGV4UGFydHM6IG51bWJlcltdID0gW11cblxuICBsZXQgc3RhcnQgPSBvYmpJbmZvLlN0YXJ0XG4gIGlmIChpc0VtcHR5KHN0YXJ0KSB8fCBzdGFydCA9PT0gLTEpIHtcbiAgICBzdGFydCA9IDBcbiAgfVxuICBjb25zdCBkaXZpc29yVmFsdWUgPSBNYXRoLnRydW5jKHNpemUgLyByZXFQYXJ0cylcblxuICBjb25zdCByZW1pbmRlclZhbHVlID0gc2l6ZSAlIHJlcVBhcnRzXG5cbiAgbGV0IG5leHRTdGFydCA9IHN0YXJ0XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCByZXFQYXJ0czsgaSsrKSB7XG4gICAgbGV0IGN1clBhcnRTaXplID0gZGl2aXNvclZhbHVlXG4gICAgaWYgKGkgPCByZW1pbmRlclZhbHVlKSB7XG4gICAgICBjdXJQYXJ0U2l6ZSsrXG4gICAgfVxuXG4gICAgY29uc3QgY3VycmVudFN0YXJ0ID0gbmV4dFN0YXJ0XG4gICAgY29uc3QgY3VycmVudEVuZCA9IGN1cnJlbnRTdGFydCArIGN1clBhcnRTaXplIC0gMVxuICAgIG5leHRTdGFydCA9IGN1cnJlbnRFbmQgKyAxXG5cbiAgICBzdGFydEluZGV4UGFydHMucHVzaChjdXJyZW50U3RhcnQpXG4gICAgZW5kSW5kZXhQYXJ0cy5wdXNoKGN1cnJlbnRFbmQpXG4gIH1cblxuICByZXR1cm4geyBzdGFydEluZGV4OiBzdGFydEluZGV4UGFydHMsIGVuZEluZGV4OiBlbmRJbmRleFBhcnRzLCBvYmpJbmZvOiBvYmpJbmZvIH1cbn1cbmNvbnN0IGZ4cCA9IG5ldyBYTUxQYXJzZXIoeyBudW1iZXJQYXJzZU9wdGlvbnM6IHsgZU5vdGF0aW9uOiBmYWxzZSwgaGV4OiB0cnVlLCBsZWFkaW5nWmVyb3M6IHRydWUgfSB9KVxuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlWG1sKHhtbDogc3RyaW5nKTogYW55IHtcbiAgY29uc3QgcmVzdWx0ID0gZnhwLnBhcnNlKHhtbClcbiAgaWYgKHJlc3VsdC5FcnJvcikge1xuICAgIHRocm93IHJlc3VsdC5FcnJvclxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG4vKipcbiAqIGdldCBjb250ZW50IHNpemUgb2Ygb2JqZWN0IGNvbnRlbnQgdG8gdXBsb2FkXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRDb250ZW50TGVuZ3RoKHM6IHN0cmVhbS5SZWFkYWJsZSB8IEJ1ZmZlciB8IHN0cmluZyk6IFByb21pc2U8bnVtYmVyIHwgbnVsbD4ge1xuICAvLyB1c2UgbGVuZ3RoIHByb3BlcnR5IG9mIHN0cmluZyB8IEJ1ZmZlclxuICBpZiAodHlwZW9mIHMgPT09ICdzdHJpbmcnIHx8IEJ1ZmZlci5pc0J1ZmZlcihzKSkge1xuICAgIHJldHVybiBzLmxlbmd0aFxuICB9XG5cbiAgLy8gcHJvcGVydHkgb2YgYGZzLlJlYWRTdHJlYW1gXG4gIGNvbnN0IGZpbGVQYXRoID0gKHMgYXMgdW5rbm93biBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikucGF0aCBhcyBzdHJpbmcgfCB1bmRlZmluZWRcbiAgaWYgKGZpbGVQYXRoICYmIHR5cGVvZiBmaWxlUGF0aCA9PT0gJ3N0cmluZycpIHtcbiAgICBjb25zdCBzdGF0ID0gYXdhaXQgZnNwLmxzdGF0KGZpbGVQYXRoKVxuICAgIHJldHVybiBzdGF0LnNpemVcbiAgfVxuXG4gIC8vIHByb3BlcnR5IG9mIGBmcy5SZWFkU3RyZWFtYFxuICBjb25zdCBmZCA9IChzIGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pLmZkIGFzIG51bWJlciB8IG51bGwgfCB1bmRlZmluZWRcbiAgaWYgKGZkICYmIHR5cGVvZiBmZCA9PT0gJ251bWJlcicpIHtcbiAgICBjb25zdCBzdGF0ID0gYXdhaXQgZnN0YXQoZmQpXG4gICAgcmV0dXJuIHN0YXQuc2l6ZVxuICB9XG5cbiAgcmV0dXJuIG51bGxcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFnQkEsSUFBQUEsTUFBQSxHQUFBQyx1QkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsTUFBQSxHQUFBRix1QkFBQSxDQUFBQyxPQUFBO0FBRUEsSUFBQUUsY0FBQSxHQUFBRixPQUFBO0FBQ0EsSUFBQUcsT0FBQSxHQUFBSCxPQUFBO0FBQ0EsSUFBQUksT0FBQSxHQUFBSixPQUFBO0FBQ0EsSUFBQUssSUFBQSxHQUFBTix1QkFBQSxDQUFBQyxPQUFBO0FBRUEsSUFBQU0sTUFBQSxHQUFBTixPQUFB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
|