@aws-cdk/aws-glue-alpha 2.95.0-alpha.0 → 2.96.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +982 -374
- package/.jsii.tabl.json.gz +0 -0
- package/.warnings.jsii.js +104 -4
- package/README.md +36 -14
- package/lib/code.js +3 -3
- package/lib/connection.js +2 -2
- package/lib/data-format.js +5 -5
- package/lib/data-quality-ruleset.js +2 -2
- package/lib/database.js +1 -1
- package/lib/external-table.d.ts +62 -0
- package/lib/external-table.js +132 -0
- package/lib/index.d.ts +4 -1
- package/lib/index.js +5 -2
- package/lib/job-executable.js +4 -4
- package/lib/job.js +2 -2
- package/lib/s3-table.d.ts +122 -0
- package/lib/s3-table.js +224 -0
- package/lib/schema.js +1 -1
- package/lib/security-configuration.js +1 -1
- package/lib/storage-parameter.js +1 -1
- package/lib/{table.d.ts → table-base.d.ts} +11 -112
- package/lib/table-base.js +188 -0
- package/lib/table-deprecated.d.ts +10 -0
- package/lib/table-deprecated.js +17 -0
- package/package.json +8 -8
- package/lib/table.js +0 -384
package/lib/table.js
DELETED
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var _a;
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.Table = exports.TableEncryption = void 0;
|
|
5
|
-
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
|
|
6
|
-
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
7
|
-
const aws_glue_1 = require("aws-cdk-lib/aws-glue");
|
|
8
|
-
const iam = require("aws-cdk-lib/aws-iam");
|
|
9
|
-
const kms = require("aws-cdk-lib/aws-kms");
|
|
10
|
-
const s3 = require("aws-cdk-lib/aws-s3");
|
|
11
|
-
const core_1 = require("aws-cdk-lib/core");
|
|
12
|
-
const cr = require("aws-cdk-lib/custom-resources");
|
|
13
|
-
/**
|
|
14
|
-
* Encryption options for a Table.
|
|
15
|
-
*
|
|
16
|
-
* @see https://docs.aws.amazon.com/athena/latest/ug/encryption.html
|
|
17
|
-
*/
|
|
18
|
-
var TableEncryption;
|
|
19
|
-
(function (TableEncryption) {
|
|
20
|
-
/**
|
|
21
|
-
* Server side encryption (SSE) with an Amazon S3-managed key.
|
|
22
|
-
*
|
|
23
|
-
* @see https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingServerSideEncryption.html
|
|
24
|
-
*/
|
|
25
|
-
TableEncryption["S3_MANAGED"] = "SSE-S3";
|
|
26
|
-
/**
|
|
27
|
-
* Server-side encryption (SSE) with an AWS KMS key managed by the account owner.
|
|
28
|
-
*
|
|
29
|
-
* @see https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingKMSEncryption.html
|
|
30
|
-
*/
|
|
31
|
-
TableEncryption["KMS"] = "SSE-KMS";
|
|
32
|
-
/**
|
|
33
|
-
* Server-side encryption (SSE) with an AWS KMS key managed by the KMS service.
|
|
34
|
-
*/
|
|
35
|
-
TableEncryption["KMS_MANAGED"] = "SSE-KMS-MANAGED";
|
|
36
|
-
/**
|
|
37
|
-
* Client-side encryption (CSE) with an AWS KMS key managed by the account owner.
|
|
38
|
-
*
|
|
39
|
-
* @see https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingClientSideEncryption.html
|
|
40
|
-
*/
|
|
41
|
-
TableEncryption["CLIENT_SIDE_KMS"] = "CSE-KMS";
|
|
42
|
-
})(TableEncryption || (exports.TableEncryption = TableEncryption = {}));
|
|
43
|
-
/**
|
|
44
|
-
* A Glue table.
|
|
45
|
-
*/
|
|
46
|
-
class Table extends core_1.Resource {
|
|
47
|
-
static fromTableArn(scope, id, tableArn) {
|
|
48
|
-
const tableName = core_1.Fn.select(1, core_1.Fn.split('/', core_1.Stack.of(scope).splitArn(tableArn, core_1.ArnFormat.SLASH_RESOURCE_NAME).resourceName));
|
|
49
|
-
return Table.fromTableAttributes(scope, id, {
|
|
50
|
-
tableArn,
|
|
51
|
-
tableName,
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Creates a Table construct that represents an external table.
|
|
56
|
-
*
|
|
57
|
-
* @param scope The scope creating construct (usually `this`).
|
|
58
|
-
* @param id The construct's id.
|
|
59
|
-
* @param attrs Import attributes
|
|
60
|
-
*/
|
|
61
|
-
static fromTableAttributes(scope, id, attrs) {
|
|
62
|
-
try {
|
|
63
|
-
jsiiDeprecationWarnings._aws_cdk_aws_glue_alpha_TableAttributes(attrs);
|
|
64
|
-
}
|
|
65
|
-
catch (error) {
|
|
66
|
-
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
67
|
-
Error.captureStackTrace(error, this.fromTableAttributes);
|
|
68
|
-
}
|
|
69
|
-
throw error;
|
|
70
|
-
}
|
|
71
|
-
class Import extends core_1.Resource {
|
|
72
|
-
constructor() {
|
|
73
|
-
super(...arguments);
|
|
74
|
-
this.tableArn = attrs.tableArn;
|
|
75
|
-
this.tableName = attrs.tableName;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return new Import(scope, id);
|
|
79
|
-
}
|
|
80
|
-
constructor(scope, id, props) {
|
|
81
|
-
super(scope, id, {
|
|
82
|
-
physicalName: props.tableName ??
|
|
83
|
-
core_1.Lazy.string({
|
|
84
|
-
produce: () => core_1.Names.uniqueResourceName(this, {}).toLowerCase(),
|
|
85
|
-
}),
|
|
86
|
-
});
|
|
87
|
-
/**
|
|
88
|
-
* Partition indexes must be created one at a time. To avoid
|
|
89
|
-
* race conditions, we store the resource and add dependencies
|
|
90
|
-
* each time a new partition index is created.
|
|
91
|
-
*/
|
|
92
|
-
this.partitionIndexCustomResources = [];
|
|
93
|
-
try {
|
|
94
|
-
jsiiDeprecationWarnings._aws_cdk_aws_glue_alpha_TableProps(props);
|
|
95
|
-
}
|
|
96
|
-
catch (error) {
|
|
97
|
-
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
98
|
-
Error.captureStackTrace(error, Table);
|
|
99
|
-
}
|
|
100
|
-
throw error;
|
|
101
|
-
}
|
|
102
|
-
this.database = props.database;
|
|
103
|
-
this.dataFormat = props.dataFormat;
|
|
104
|
-
this.s3Prefix = props.s3Prefix ?? '';
|
|
105
|
-
validateSchema(props.columns, props.partitionKeys);
|
|
106
|
-
this.columns = props.columns;
|
|
107
|
-
this.partitionKeys = props.partitionKeys;
|
|
108
|
-
this.storageParameters = props.storageParameters;
|
|
109
|
-
this.compressed = props.compressed ?? false;
|
|
110
|
-
const { bucket, encryption, encryptionKey } = createBucket(this, props);
|
|
111
|
-
this.bucket = bucket;
|
|
112
|
-
this.encryption = encryption;
|
|
113
|
-
this.encryptionKey = encryptionKey;
|
|
114
|
-
const tableResource = new aws_glue_1.CfnTable(this, 'Table', {
|
|
115
|
-
catalogId: props.database.catalogId,
|
|
116
|
-
databaseName: props.database.databaseName,
|
|
117
|
-
tableInput: {
|
|
118
|
-
name: this.physicalName,
|
|
119
|
-
description: props.description || `${this.physicalName} generated by CDK`,
|
|
120
|
-
partitionKeys: renderColumns(props.partitionKeys),
|
|
121
|
-
parameters: {
|
|
122
|
-
'classification': props.dataFormat.classificationString?.value,
|
|
123
|
-
'has_encrypted_data': true,
|
|
124
|
-
'partition_filtering.enabled': props.enablePartitionFiltering,
|
|
125
|
-
},
|
|
126
|
-
storageDescriptor: {
|
|
127
|
-
location: `s3://${this.bucket.bucketName}/${this.s3Prefix}`,
|
|
128
|
-
compressed: this.compressed,
|
|
129
|
-
storedAsSubDirectories: props.storedAsSubDirectories ?? false,
|
|
130
|
-
columns: renderColumns(props.columns),
|
|
131
|
-
inputFormat: props.dataFormat.inputFormat.className,
|
|
132
|
-
outputFormat: props.dataFormat.outputFormat.className,
|
|
133
|
-
serdeInfo: {
|
|
134
|
-
serializationLibrary: props.dataFormat.serializationLibrary.className,
|
|
135
|
-
},
|
|
136
|
-
parameters: props.storageParameters ? props.storageParameters.reduce((acc, param) => {
|
|
137
|
-
if (param.key in acc) {
|
|
138
|
-
throw new Error(`Duplicate storage parameter key: ${param.key}`);
|
|
139
|
-
}
|
|
140
|
-
const key = param.key;
|
|
141
|
-
acc[key] = param.value;
|
|
142
|
-
return acc;
|
|
143
|
-
}, {}) : undefined,
|
|
144
|
-
},
|
|
145
|
-
tableType: 'EXTERNAL_TABLE',
|
|
146
|
-
},
|
|
147
|
-
});
|
|
148
|
-
this.tableName = this.getResourceNameAttribute(tableResource.ref);
|
|
149
|
-
this.tableArn = this.stack.formatArn({
|
|
150
|
-
service: 'glue',
|
|
151
|
-
resource: 'table',
|
|
152
|
-
resourceName: `${this.database.databaseName}/${this.tableName}`,
|
|
153
|
-
});
|
|
154
|
-
this.node.defaultChild = tableResource;
|
|
155
|
-
// Partition index creation relies on created table.
|
|
156
|
-
if (props.partitionIndexes) {
|
|
157
|
-
this.partitionIndexes = props.partitionIndexes;
|
|
158
|
-
this.partitionIndexes.forEach((index) => this.addPartitionIndex(index));
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Add a partition index to the table. You can have a maximum of 3 partition
|
|
163
|
-
* indexes to a table. Partition index keys must be a subset of the table's
|
|
164
|
-
* partition keys.
|
|
165
|
-
*
|
|
166
|
-
* @see https://docs.aws.amazon.com/glue/latest/dg/partition-indexes.html
|
|
167
|
-
*/
|
|
168
|
-
addPartitionIndex(index) {
|
|
169
|
-
try {
|
|
170
|
-
jsiiDeprecationWarnings._aws_cdk_aws_glue_alpha_PartitionIndex(index);
|
|
171
|
-
}
|
|
172
|
-
catch (error) {
|
|
173
|
-
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
174
|
-
Error.captureStackTrace(error, this.addPartitionIndex);
|
|
175
|
-
}
|
|
176
|
-
throw error;
|
|
177
|
-
}
|
|
178
|
-
const numPartitions = this.partitionIndexCustomResources.length;
|
|
179
|
-
if (numPartitions >= 3) {
|
|
180
|
-
throw new Error('Maximum number of partition indexes allowed is 3');
|
|
181
|
-
}
|
|
182
|
-
this.validatePartitionIndex(index);
|
|
183
|
-
const indexName = index.indexName ?? this.generateIndexName(index.keyNames);
|
|
184
|
-
const partitionIndexCustomResource = new cr.AwsCustomResource(this, `partition-index-${indexName}`, {
|
|
185
|
-
onCreate: {
|
|
186
|
-
service: 'Glue',
|
|
187
|
-
action: 'createPartitionIndex',
|
|
188
|
-
parameters: {
|
|
189
|
-
DatabaseName: this.database.databaseName,
|
|
190
|
-
TableName: this.tableName,
|
|
191
|
-
PartitionIndex: {
|
|
192
|
-
IndexName: indexName,
|
|
193
|
-
Keys: index.keyNames,
|
|
194
|
-
},
|
|
195
|
-
},
|
|
196
|
-
physicalResourceId: cr.PhysicalResourceId.of(indexName),
|
|
197
|
-
},
|
|
198
|
-
policy: cr.AwsCustomResourcePolicy.fromSdkCalls({
|
|
199
|
-
resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE,
|
|
200
|
-
}),
|
|
201
|
-
// APIs are available in 2.1055.0
|
|
202
|
-
installLatestAwsSdk: false,
|
|
203
|
-
});
|
|
204
|
-
this.grantToUnderlyingResources(partitionIndexCustomResource, ['glue:UpdateTable']);
|
|
205
|
-
// Depend on previous partition index if possible, to avoid race condition
|
|
206
|
-
if (numPartitions > 0) {
|
|
207
|
-
this.partitionIndexCustomResources[numPartitions - 1].node.addDependency(partitionIndexCustomResource);
|
|
208
|
-
}
|
|
209
|
-
this.partitionIndexCustomResources.push(partitionIndexCustomResource);
|
|
210
|
-
}
|
|
211
|
-
generateIndexName(keys) {
|
|
212
|
-
const prefix = keys.join('-') + '-';
|
|
213
|
-
const uniqueId = core_1.Names.uniqueId(this);
|
|
214
|
-
const maxIndexLength = 80; // arbitrarily specified
|
|
215
|
-
const startIndex = Math.max(0, uniqueId.length - (maxIndexLength - prefix.length));
|
|
216
|
-
return prefix + uniqueId.substring(startIndex);
|
|
217
|
-
}
|
|
218
|
-
validatePartitionIndex(index) {
|
|
219
|
-
if (index.indexName !== undefined && (index.indexName.length < 1 || index.indexName.length > 255)) {
|
|
220
|
-
throw new Error(`Index name must be between 1 and 255 characters, but got ${index.indexName.length}`);
|
|
221
|
-
}
|
|
222
|
-
if (!this.partitionKeys || this.partitionKeys.length === 0) {
|
|
223
|
-
throw new Error('The table must have partition keys to create a partition index');
|
|
224
|
-
}
|
|
225
|
-
const keyNames = this.partitionKeys.map(pk => pk.name);
|
|
226
|
-
if (!index.keyNames.every(k => keyNames.includes(k))) {
|
|
227
|
-
throw new Error(`All index keys must also be partition keys. Got ${index.keyNames} but partition key names are ${keyNames}`);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Grant read permissions to the table and the underlying data stored in S3 to an IAM principal.
|
|
232
|
-
*
|
|
233
|
-
* @param grantee the principal
|
|
234
|
-
*/
|
|
235
|
-
grantRead(grantee) {
|
|
236
|
-
const ret = this.grant(grantee, readPermissions);
|
|
237
|
-
if (this.encryptionKey && this.encryption === TableEncryption.CLIENT_SIDE_KMS) {
|
|
238
|
-
this.encryptionKey.grantDecrypt(grantee);
|
|
239
|
-
}
|
|
240
|
-
this.bucket.grantRead(grantee, this.getS3PrefixForGrant());
|
|
241
|
-
return ret;
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Grant write permissions to the table and the underlying data stored in S3 to an IAM principal.
|
|
245
|
-
*
|
|
246
|
-
* @param grantee the principal
|
|
247
|
-
*/
|
|
248
|
-
grantWrite(grantee) {
|
|
249
|
-
const ret = this.grant(grantee, writePermissions);
|
|
250
|
-
if (this.encryptionKey && this.encryption === TableEncryption.CLIENT_SIDE_KMS) {
|
|
251
|
-
this.encryptionKey.grantEncrypt(grantee);
|
|
252
|
-
}
|
|
253
|
-
this.bucket.grantWrite(grantee, this.getS3PrefixForGrant());
|
|
254
|
-
return ret;
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Grant read and write permissions to the table and the underlying data stored in S3 to an IAM principal.
|
|
258
|
-
*
|
|
259
|
-
* @param grantee the principal
|
|
260
|
-
*/
|
|
261
|
-
grantReadWrite(grantee) {
|
|
262
|
-
const ret = this.grant(grantee, [...readPermissions, ...writePermissions]);
|
|
263
|
-
if (this.encryptionKey && this.encryption === TableEncryption.CLIENT_SIDE_KMS) {
|
|
264
|
-
this.encryptionKey.grantEncryptDecrypt(grantee);
|
|
265
|
-
}
|
|
266
|
-
this.bucket.grantReadWrite(grantee, this.getS3PrefixForGrant());
|
|
267
|
-
return ret;
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* Grant the given identity custom permissions.
|
|
271
|
-
*/
|
|
272
|
-
grant(grantee, actions) {
|
|
273
|
-
return iam.Grant.addToPrincipal({
|
|
274
|
-
grantee,
|
|
275
|
-
resourceArns: [this.tableArn],
|
|
276
|
-
actions,
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* Grant the given identity custom permissions to ALL underlying resources of the table.
|
|
281
|
-
* Permissions will be granted to the catalog, the database, and the table.
|
|
282
|
-
*/
|
|
283
|
-
grantToUnderlyingResources(grantee, actions) {
|
|
284
|
-
return iam.Grant.addToPrincipal({
|
|
285
|
-
grantee,
|
|
286
|
-
resourceArns: [
|
|
287
|
-
this.tableArn,
|
|
288
|
-
this.database.catalogArn,
|
|
289
|
-
this.database.databaseArn,
|
|
290
|
-
],
|
|
291
|
-
actions,
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
getS3PrefixForGrant() {
|
|
295
|
-
return this.s3Prefix + '*';
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
exports.Table = Table;
|
|
299
|
-
_a = JSII_RTTI_SYMBOL_1;
|
|
300
|
-
Table[_a] = { fqn: "@aws-cdk/aws-glue-alpha.Table", version: "2.95.0-alpha.0" };
|
|
301
|
-
function validateSchema(columns, partitionKeys) {
|
|
302
|
-
if (columns.length === 0) {
|
|
303
|
-
throw new Error('you must specify at least one column for the table');
|
|
304
|
-
}
|
|
305
|
-
// Check there is at least one column and no duplicated column names or partition keys.
|
|
306
|
-
const names = new Set();
|
|
307
|
-
(columns.concat(partitionKeys || [])).forEach(column => {
|
|
308
|
-
if (names.has(column.name)) {
|
|
309
|
-
throw new Error(`column names and partition keys must be unique, but \'${column.name}\' is duplicated`);
|
|
310
|
-
}
|
|
311
|
-
names.add(column.name);
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
// map TableEncryption to bucket's SSE configuration (s3.BucketEncryption)
|
|
315
|
-
const encryptionMappings = {
|
|
316
|
-
[TableEncryption.S3_MANAGED]: s3.BucketEncryption.S3_MANAGED,
|
|
317
|
-
[TableEncryption.KMS_MANAGED]: s3.BucketEncryption.KMS_MANAGED,
|
|
318
|
-
[TableEncryption.KMS]: s3.BucketEncryption.KMS,
|
|
319
|
-
[TableEncryption.CLIENT_SIDE_KMS]: s3.BucketEncryption.S3_MANAGED,
|
|
320
|
-
};
|
|
321
|
-
// create the bucket to store a table's data depending on the `encryption` and `encryptionKey` properties.
|
|
322
|
-
function createBucket(table, props) {
|
|
323
|
-
let bucket = props.bucket;
|
|
324
|
-
if (bucket && (props.encryption !== undefined && props.encryption !== TableEncryption.CLIENT_SIDE_KMS)) {
|
|
325
|
-
throw new Error('you can not specify encryption settings if you also provide a bucket');
|
|
326
|
-
}
|
|
327
|
-
const encryption = props.encryption || TableEncryption.S3_MANAGED;
|
|
328
|
-
let encryptionKey;
|
|
329
|
-
if (encryption === TableEncryption.CLIENT_SIDE_KMS && props.encryptionKey === undefined) {
|
|
330
|
-
// CSE-KMS should behave the same as SSE-KMS - use the provided key or create one automatically
|
|
331
|
-
// Since Bucket only knows about SSE, we repeat the logic for CSE-KMS at the Table level.
|
|
332
|
-
encryptionKey = new kms.Key(table, 'Key');
|
|
333
|
-
}
|
|
334
|
-
else {
|
|
335
|
-
encryptionKey = props.encryptionKey;
|
|
336
|
-
}
|
|
337
|
-
// create the bucket if none was provided
|
|
338
|
-
if (!bucket) {
|
|
339
|
-
if (encryption === TableEncryption.CLIENT_SIDE_KMS) {
|
|
340
|
-
bucket = new s3.Bucket(table, 'Bucket');
|
|
341
|
-
}
|
|
342
|
-
else {
|
|
343
|
-
bucket = new s3.Bucket(table, 'Bucket', {
|
|
344
|
-
encryption: encryptionMappings[encryption],
|
|
345
|
-
encryptionKey,
|
|
346
|
-
});
|
|
347
|
-
encryptionKey = bucket.encryptionKey;
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
return {
|
|
351
|
-
bucket,
|
|
352
|
-
encryption,
|
|
353
|
-
encryptionKey,
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
const readPermissions = [
|
|
357
|
-
'glue:BatchGetPartition',
|
|
358
|
-
'glue:GetPartition',
|
|
359
|
-
'glue:GetPartitions',
|
|
360
|
-
'glue:GetTable',
|
|
361
|
-
'glue:GetTables',
|
|
362
|
-
'glue:GetTableVersion',
|
|
363
|
-
'glue:GetTableVersions',
|
|
364
|
-
];
|
|
365
|
-
const writePermissions = [
|
|
366
|
-
'glue:BatchCreatePartition',
|
|
367
|
-
'glue:BatchDeletePartition',
|
|
368
|
-
'glue:CreatePartition',
|
|
369
|
-
'glue:DeletePartition',
|
|
370
|
-
'glue:UpdatePartition',
|
|
371
|
-
];
|
|
372
|
-
function renderColumns(columns) {
|
|
373
|
-
if (columns === undefined) {
|
|
374
|
-
return undefined;
|
|
375
|
-
}
|
|
376
|
-
return columns.map(column => {
|
|
377
|
-
return {
|
|
378
|
-
name: column.name,
|
|
379
|
-
type: column.type.inputString,
|
|
380
|
-
comment: column.comment,
|
|
381
|
-
};
|
|
382
|
-
});
|
|
383
|
-
}
|
|
384
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0YWJsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxtREFBZ0Q7QUFDaEQsMkNBQTJDO0FBQzNDLDJDQUEyQztBQUMzQyx5Q0FBeUM7QUFDekMsMkNBQTBGO0FBQzFGLG1EQUFtRDtBQXNDbkQ7Ozs7R0FJRztBQUNILElBQVksZUEwQlg7QUExQkQsV0FBWSxlQUFlO0lBQ3pCOzs7O09BSUc7SUFDSCx3Q0FBcUIsQ0FBQTtJQUVyQjs7OztPQUlHO0lBQ0gsa0NBQWUsQ0FBQTtJQUVmOztPQUVHO0lBQ0gsa0RBQStCLENBQUE7SUFFL0I7Ozs7T0FJRztJQUNILDhDQUEyQixDQUFBO0FBQzdCLENBQUMsRUExQlcsZUFBZSwrQkFBZixlQUFlLFFBMEIxQjtBQW1KRDs7R0FFRztBQUNILE1BQWEsS0FBTSxTQUFRLGVBQVE7SUFFMUIsTUFBTSxDQUFDLFlBQVksQ0FBQyxLQUFnQixFQUFFLEVBQVUsRUFBRSxRQUFnQjtRQUN2RSxNQUFNLFNBQVMsR0FBRyxTQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxTQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxZQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsZ0JBQVMsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLFlBQWEsQ0FBQyxDQUFDLENBQUM7UUFFL0gsT0FBTyxLQUFLLENBQUMsbUJBQW1CLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUMxQyxRQUFRO1lBQ1IsU0FBUztTQUNWLENBQUMsQ0FBQztLQUNKO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksTUFBTSxDQUFDLG1CQUFtQixDQUFDLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXNCOzs7Ozs7Ozs7O1FBQ3BGLE1BQU0sTUFBTyxTQUFRLGVBQVE7WUFBN0I7O2dCQUNrQixhQUFRLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQztnQkFDMUIsY0FBUyxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUM7WUFDOUMsQ0FBQztTQUFBO1FBRUQsT0FBTyxJQUFJLE1BQU0sQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7S0FDOUI7SUEwRUQsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFpQjtRQUN6RCxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUNmLFlBQVksRUFBRSxLQUFLLENBQUMsU0FBUztnQkFDM0IsV0FBSSxDQUFDLE1BQU0sQ0FBQztvQkFDVixPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsWUFBSyxDQUFDLGtCQUFrQixDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxXQUFXLEVBQUU7aUJBQ2hFLENBQUM7U0FDTCxDQUFDLENBQUM7UUFiTDs7OztXQUlHO1FBQ0ssa0NBQTZCLEdBQXdCLEVBQUUsQ0FBQzs7Ozs7OytDQWpHckQsS0FBSzs7OztRQTJHZCxJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUM7UUFDL0IsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUMsVUFBVSxDQUFDO1FBQ25DLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFFBQVEsSUFBSSxFQUFFLENBQUM7UUFFckMsY0FBYyxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ25ELElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQztRQUM3QixJQUFJLENBQUMsYUFBYSxHQUFHLEtBQUssQ0FBQyxhQUFhLENBQUM7UUFDekMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQztRQUVqRCxJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQyxVQUFVLElBQUksS0FBSyxDQUFDO1FBQzVDLE1BQU0sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLGFBQWEsRUFBRSxHQUFHLFlBQVksQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDeEUsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7UUFDN0IsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUM7UUFFbkMsTUFBTSxhQUFhLEdBQUcsSUFBSSxtQkFBUSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUU7WUFDaEQsU0FBUyxFQUFFLEtBQUssQ0FBQyxRQUFRLENBQUMsU0FBUztZQUVuQyxZQUFZLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxZQUFZO1lBRXpDLFVBQVUsRUFBRTtnQkFDVixJQUFJLEVBQUUsSUFBSSxDQUFDLFlBQVk7Z0JBQ3ZCLFdBQVcsRUFBRSxLQUFLLENBQUMsV0FBVyxJQUFJLEdBQUcsSUFBSSxDQUFDLFlBQVksbUJBQW1CO2dCQUV6RSxhQUFhLEVBQUUsYUFBYSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUM7Z0JBRWpELFVBQVUsRUFBRTtvQkFDVixnQkFBZ0IsRUFBRSxLQUFLLENBQUMsVUFBVSxDQUFDLG9CQUFvQixFQUFFLEtBQUs7b0JBQzlELG9CQUFvQixFQUFFLElBQUk7b0JBQzFCLDZCQUE2QixFQUFFLEtBQUssQ0FBQyx3QkFBd0I7aUJBQzlEO2dCQUNELGlCQUFpQixFQUFFO29CQUNqQixRQUFRLEVBQUUsUUFBUSxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO29CQUMzRCxVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVU7b0JBQzNCLHNCQUFzQixFQUFFLEtBQUssQ0FBQyxzQkFBc0IsSUFBSSxLQUFLO29CQUM3RCxPQUFPLEVBQUUsYUFBYSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUM7b0JBQ3JDLFdBQVcsRUFBRSxLQUFLLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxTQUFTO29CQUNuRCxZQUFZLEVBQUUsS0FBSyxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsU0FBUztvQkFDckQsU0FBUyxFQUFFO3dCQUNULG9CQUFvQixFQUFFLEtBQUssQ0FBQyxVQUFVLENBQUMsb0JBQW9CLENBQUMsU0FBUztxQkFDdEU7b0JBQ0QsVUFBVSxFQUFFLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsRUFBRTt3QkFDbEYsSUFBSSxLQUFLLENBQUMsR0FBRyxJQUFJLEdBQUcsRUFBRTs0QkFDcEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQ0FBb0MsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7eUJBQ2xFO3dCQUNELE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUM7d0JBQ3RCLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDO3dCQUN2QixPQUFPLEdBQUcsQ0FBQztvQkFDYixDQUFDLEVBQUUsRUFBK0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTO2lCQUNoRDtnQkFFRCxTQUFTLEVBQUUsZ0JBQWdCO2FBQzVCO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsd0JBQXdCLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ2xFLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUM7WUFDbkMsT0FBTyxFQUFFLE1BQU07WUFDZixRQUFRLEVBQUUsT0FBTztZQUNqQixZQUFZLEVBQUUsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFO1NBQ2hFLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxHQUFHLGFBQWEsQ0FBQztRQUV2QyxvREFBb0Q7UUFDcEQsSUFBSSxLQUFLLENBQUMsZ0JBQWdCLEVBQUU7WUFDMUIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQztZQUMvQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztTQUN6RTtLQUNGO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksaUJBQWlCLENBQUMsS0FBcUI7Ozs7Ozs7Ozs7UUFDNUMsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLDZCQUE2QixDQUFDLE1BQU0sQ0FBQztRQUNoRSxJQUFJLGFBQWEsSUFBSSxDQUFDLEVBQUU7WUFDdEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxrREFBa0QsQ0FBQyxDQUFDO1NBQ3JFO1FBQ0QsSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRW5DLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM1RSxNQUFNLDRCQUE0QixHQUFHLElBQUksRUFBRSxDQUFDLGlCQUFpQixDQUFDLElBQUksRUFBRSxtQkFBbUIsU0FBUyxFQUFFLEVBQUU7WUFDbEcsUUFBUSxFQUFFO2dCQUNSLE9BQU8sRUFBRSxNQUFNO2dCQUNmLE1BQU0sRUFBRSxzQkFBc0I7Z0JBQzlCLFVBQVUsRUFBRTtvQkFDVixZQUFZLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZO29CQUN4QyxTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7b0JBQ3pCLGNBQWMsRUFBRTt3QkFDZCxTQUFTLEVBQUUsU0FBUzt3QkFDcEIsSUFBSSxFQUFFLEtBQUssQ0FBQyxRQUFRO3FCQUNyQjtpQkFDRjtnQkFDRCxrQkFBa0IsRUFBRSxFQUFFLENBQUMsa0JBQWtCLENBQUMsRUFBRSxDQUMxQyxTQUFTLENBQ1Y7YUFDRjtZQUNELE1BQU0sRUFBRSxFQUFFLENBQUMsdUJBQXVCLENBQUMsWUFBWSxDQUFDO2dCQUM5QyxTQUFTLEVBQUUsRUFBRSxDQUFDLHVCQUF1QixDQUFDLFlBQVk7YUFDbkQsQ0FBQztZQUNGLGlDQUFpQztZQUNqQyxtQkFBbUIsRUFBRSxLQUFLO1NBQzNCLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQywwQkFBMEIsQ0FBQyw0QkFBNEIsRUFBRSxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQztRQUVwRiwwRUFBMEU7UUFDMUUsSUFBSSxhQUFhLEdBQUcsQ0FBQyxFQUFFO1lBQ3JCLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxhQUFhLEdBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO1NBQ3RHO1FBQ0QsSUFBSSxDQUFDLDZCQUE2QixDQUFDLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO0tBQ3ZFO0lBRU8saUJBQWlCLENBQUMsSUFBYztRQUN0QyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEdBQUcsQ0FBQztRQUNwQyxNQUFNLFFBQVEsR0FBRyxZQUFLLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3RDLE1BQU0sY0FBYyxHQUFHLEVBQUUsQ0FBQyxDQUFDLHdCQUF3QjtRQUNuRCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQ25GLE9BQU8sTUFBTSxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLENBQUM7S0FDaEQ7SUFFTyxzQkFBc0IsQ0FBQyxLQUFxQjtRQUNsRCxJQUFJLEtBQUssQ0FBQyxTQUFTLEtBQUssU0FBUyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLEtBQUssQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLEdBQUcsQ0FBQyxFQUFFO1lBQ2pHLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELEtBQUssQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztTQUN2RztRQUNELElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUMxRCxNQUFNLElBQUksS0FBSyxDQUFDLGdFQUFnRSxDQUFDLENBQUM7U0FDbkY7UUFDRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2RCxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDcEQsTUFBTSxJQUFJLEtBQUssQ0FBQyxtREFBbUQsS0FBSyxDQUFDLFFBQVEsZ0NBQWdDLFFBQVEsRUFBRSxDQUFDLENBQUM7U0FDOUg7S0FDRjtJQUVEOzs7O09BSUc7SUFDSSxTQUFTLENBQUMsT0FBdUI7UUFDdEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsZUFBZSxDQUFDLENBQUM7UUFDakQsSUFBSSxJQUFJLENBQUMsYUFBYSxJQUFJLElBQUksQ0FBQyxVQUFVLEtBQUssZUFBZSxDQUFDLGVBQWUsRUFBRTtZQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1NBQUU7UUFDNUgsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLENBQUM7UUFDM0QsT0FBTyxHQUFHLENBQUM7S0FDWjtJQUVEOzs7O09BSUc7SUFDSSxVQUFVLENBQUMsT0FBdUI7UUFDdkMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztRQUNsRCxJQUFJLElBQUksQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxlQUFlLENBQUMsZUFBZSxFQUFFO1lBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7U0FBRTtRQUM1SCxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUMsQ0FBQztRQUM1RCxPQUFPLEdBQUcsQ0FBQztLQUNaO0lBRUQ7Ozs7T0FJRztJQUNJLGNBQWMsQ0FBQyxPQUF1QjtRQUMzQyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsZUFBZSxFQUFFLEdBQUcsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO1FBQzNFLElBQUksSUFBSSxDQUFDLGFBQWEsSUFBSSxJQUFJLENBQUMsVUFBVSxLQUFLLGVBQWUsQ0FBQyxlQUFlLEVBQUU7WUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1NBQUU7UUFDbkksSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLENBQUM7UUFDaEUsT0FBTyxHQUFHLENBQUM7S0FDWjtJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLE9BQXVCLEVBQUUsT0FBaUI7UUFDckQsT0FBTyxHQUFHLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQztZQUM5QixPQUFPO1lBQ1AsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQztZQUM3QixPQUFPO1NBQ1IsQ0FBQyxDQUFDO0tBQ0o7SUFFRDs7O09BR0c7SUFDSSwwQkFBMEIsQ0FBQyxPQUF1QixFQUFFLE9BQWlCO1FBQzFFLE9BQU8sR0FBRyxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUM7WUFDOUIsT0FBTztZQUNQLFlBQVksRUFBRTtnQkFDWixJQUFJLENBQUMsUUFBUTtnQkFDYixJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVU7Z0JBQ3hCLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVzthQUMxQjtZQUNELE9BQU87U0FDUixDQUFDLENBQUM7S0FDSjtJQUVPLG1CQUFtQjtRQUN6QixPQUFPLElBQUksQ0FBQyxRQUFRLEdBQUcsR0FBRyxDQUFDO0tBQzVCOztBQXJUSCxzQkFzVEM7OztBQUVELFNBQVMsY0FBYyxDQUFDLE9BQWlCLEVBQUUsYUFBd0I7SUFDakUsSUFBSSxPQUFPLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtRQUN4QixNQUFNLElBQUksS0FBSyxDQUFDLG9EQUFvRCxDQUFDLENBQUM7S0FDdkU7SUFDRCx1RkFBdUY7SUFDdkYsTUFBTSxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUNoQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsYUFBYSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFO1FBQ3JELElBQUksS0FBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyx5REFBeUQsTUFBTSxDQUFDLElBQUksa0JBQWtCLENBQUMsQ0FBQztTQUN6RztRQUNELEtBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3pCLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELDBFQUEwRTtBQUMxRSxNQUFNLGtCQUFrQixHQUFHO0lBQ3pCLENBQUMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxVQUFVO0lBQzVELENBQUMsZUFBZSxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFXO0lBQzlELENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHO0lBQzlDLENBQUMsZUFBZSxDQUFDLGVBQWUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxVQUFVO0NBQ2xFLENBQUM7QUFFRiwwR0FBMEc7QUFDMUcsU0FBUyxZQUFZLENBQUMsS0FBWSxFQUFFLEtBQWlCO0lBQ25ELElBQUksTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7SUFFMUIsSUFBSSxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxLQUFLLFNBQVMsSUFBSSxLQUFLLENBQUMsVUFBVSxLQUFLLGVBQWUsQ0FBQyxlQUFlLENBQUMsRUFBRTtRQUN0RyxNQUFNLElBQUksS0FBSyxDQUFDLHNFQUFzRSxDQUFDLENBQUM7S0FDekY7SUFFRCxNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsVUFBVSxJQUFJLGVBQWUsQ0FBQyxVQUFVLENBQUM7SUFFbEUsSUFBSSxhQUFtQyxDQUFDO0lBQ3hDLElBQUksVUFBVSxLQUFLLGVBQWUsQ0FBQyxlQUFlLElBQUksS0FBSyxDQUFDLGFBQWEsS0FBSyxTQUFTLEVBQUU7UUFDdkYsK0ZBQStGO1FBQy9GLHlGQUF5RjtRQUN6RixhQUFhLEdBQUcsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztLQUMzQztTQUFNO1FBQ0wsYUFBYSxHQUFHLEtBQUssQ0FBQyxhQUFhLENBQUM7S0FDckM7SUFFRCx5Q0FBeUM7SUFDekMsSUFBSSxDQUFDLE1BQU0sRUFBRTtRQUNYLElBQUksVUFBVSxLQUFLLGVBQWUsQ0FBQyxlQUFlLEVBQUU7WUFDbEQsTUFBTSxHQUFHLElBQUksRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7U0FDekM7YUFBTTtZQUNMLE1BQU0sR0FBRyxJQUFJLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRTtnQkFDdEMsVUFBVSxFQUFFLGtCQUFrQixDQUFDLFVBQVUsQ0FBQztnQkFDMUMsYUFBYTthQUNkLENBQUMsQ0FBQztZQUNILGFBQWEsR0FBRyxNQUFNLENBQUMsYUFBYSxDQUFDO1NBQ3RDO0tBQ0Y7SUFFRCxPQUFPO1FBQ0wsTUFBTTtRQUNOLFVBQVU7UUFDVixhQUFhO0tBQ2QsQ0FBQztBQUNKLENBQUM7QUFFRCxNQUFNLGVBQWUsR0FBRztJQUN0Qix3QkFBd0I7SUFDeEIsbUJBQW1CO0lBQ25CLG9CQUFvQjtJQUNwQixlQUFlO0lBQ2YsZ0JBQWdCO0lBQ2hCLHNCQUFzQjtJQUN0Qix1QkFBdUI7Q0FDeEIsQ0FBQztBQUVGLE1BQU0sZ0JBQWdCLEdBQUc7SUFDdkIsMkJBQTJCO0lBQzNCLDJCQUEyQjtJQUMzQixzQkFBc0I7SUFDdEIsc0JBQXNCO0lBQ3RCLHNCQUFzQjtDQUN2QixDQUFDO0FBRUYsU0FBUyxhQUFhLENBQUMsT0FBZ0M7SUFDckQsSUFBSSxPQUFPLEtBQUssU0FBUyxFQUFFO1FBQ3pCLE9BQU8sU0FBUyxDQUFDO0tBQ2xCO0lBQ0QsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFO1FBQzFCLE9BQU87WUFDTCxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUk7WUFDakIsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVztZQUM3QixPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU87U0FDeEIsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENmblRhYmxlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWdsdWUnO1xuaW1wb3J0ICogYXMgaWFtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0ICogYXMga21zIGZyb20gJ2F3cy1jZGstbGliL2F3cy1rbXMnO1xuaW1wb3J0ICogYXMgczMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzJztcbmltcG9ydCB7IEFybkZvcm1hdCwgRm4sIElSZXNvdXJjZSwgTGF6eSwgTmFtZXMsIFJlc291cmNlLCBTdGFjayB9IGZyb20gJ2F3cy1jZGstbGliL2NvcmUnO1xuaW1wb3J0ICogYXMgY3IgZnJvbSAnYXdzLWNkay1saWIvY3VzdG9tLXJlc291cmNlcyc7XG5pbXBvcnQgeyBBd3NDdXN0b21SZXNvdXJjZSB9IGZyb20gJ2F3cy1jZGstbGliL2N1c3RvbS1yZXNvdXJjZXMnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBEYXRhRm9ybWF0IH0gZnJvbSAnLi9kYXRhLWZvcm1hdCc7XG5pbXBvcnQgeyBJRGF0YWJhc2UgfSBmcm9tICcuL2RhdGFiYXNlJztcbmltcG9ydCB7IENvbHVtbiB9IGZyb20gJy4vc2NoZW1hJztcbmltcG9ydCB7IFN0b3JhZ2VQYXJhbWV0ZXIgfSBmcm9tICcuL3N0b3JhZ2UtcGFyYW1ldGVyJztcblxuLyoqXG4gKiBQcm9wZXJ0aWVzIG9mIGEgUGFydGl0aW9uIEluZGV4LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFBhcnRpdGlvbkluZGV4IHtcbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBwYXJ0aXRpb24gaW5kZXguXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gYSBuYW1lIHdpbGwgYmUgZ2VuZXJhdGVkIGZvciB5b3UuXG4gICAqL1xuICByZWFkb25seSBpbmRleE5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBwYXJ0aXRpb24ga2V5IG5hbWVzIHRoYXQgY29tcHJpc2UgdGhlIHBhcnRpdGlvblxuICAgKiBpbmRleC4gVGhlIG5hbWVzIG11c3QgY29ycmVzcG9uZCB0byBhIG5hbWUgaW4gdGhlXG4gICAqIHRhYmxlJ3MgcGFydGl0aW9uIGtleXMuXG4gICAqL1xuICByZWFkb25seSBrZXlOYW1lczogc3RyaW5nW107XG59XG5leHBvcnQgaW50ZXJmYWNlIElUYWJsZSBleHRlbmRzIElSZXNvdXJjZSB7XG4gIC8qKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICByZWFkb25seSB0YWJsZUFybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICByZWFkb25seSB0YWJsZU5hbWU6IHN0cmluZztcbn1cblxuLyoqXG4gKiBFbmNyeXB0aW9uIG9wdGlvbnMgZm9yIGEgVGFibGUuXG4gKlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXRoZW5hL2xhdGVzdC91Zy9lbmNyeXB0aW9uLmh0bWxcbiAqL1xuZXhwb3J0IGVudW0gVGFibGVFbmNyeXB0aW9uIHtcbiAgLyoqXG4gICAqIFNlcnZlciBzaWRlIGVuY3J5cHRpb24gKFNTRSkgd2l0aCBhbiBBbWF6b24gUzMtbWFuYWdlZCBrZXkuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvblMzL2xhdGVzdC9kZXYvVXNpbmdTZXJ2ZXJTaWRlRW5jcnlwdGlvbi5odG1sXG4gICAqL1xuICBTM19NQU5BR0VEID0gJ1NTRS1TMycsXG5cbiAgLyoqXG4gICAqIFNlcnZlci1zaWRlIGVuY3J5cHRpb24gKFNTRSkgd2l0aCBhbiBBV1MgS01TIGtleSBtYW5hZ2VkIGJ5IHRoZSBhY2NvdW50IG93bmVyLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25TMy9sYXRlc3QvZGV2L1VzaW5nS01TRW5jcnlwdGlvbi5odG1sXG4gICAqL1xuICBLTVMgPSAnU1NFLUtNUycsXG5cbiAgLyoqXG4gICAqIFNlcnZlci1zaWRlIGVuY3J5cHRpb24gKFNTRSkgd2l0aCBhbiBBV1MgS01TIGtleSBtYW5hZ2VkIGJ5IHRoZSBLTVMgc2VydmljZS5cbiAgICovXG4gIEtNU19NQU5BR0VEID0gJ1NTRS1LTVMtTUFOQUdFRCcsXG5cbiAgLyoqXG4gICAqIENsaWVudC1zaWRlIGVuY3J5cHRpb24gKENTRSkgd2l0aCBhbiBBV1MgS01TIGtleSBtYW5hZ2VkIGJ5IHRoZSBhY2NvdW50IG93bmVyLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25TMy9sYXRlc3QvZGV2L1VzaW5nQ2xpZW50U2lkZUVuY3J5cHRpb24uaHRtbFxuICAgKi9cbiAgQ0xJRU5UX1NJREVfS01TID0gJ0NTRS1LTVMnXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGFibGVBdHRyaWJ1dGVzIHtcbiAgcmVhZG9ubHkgdGFibGVBcm46IHN0cmluZztcbiAgcmVhZG9ubHkgdGFibGVOYW1lOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGFibGVQcm9wcyB7XG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSB0YWJsZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBnZW5lcmF0ZWQgYnkgQ0RLLlxuICAgKi9cbiAgcmVhZG9ubHkgdGFibGVOYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEZXNjcmlwdGlvbiBvZiB0aGUgdGFibGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IGdlbmVyYXRlZFxuICAgKi9cbiAgcmVhZG9ubHkgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIERhdGFiYXNlIGluIHdoaWNoIHRvIHN0b3JlIHRoZSB0YWJsZS5cbiAgICovXG4gIHJlYWRvbmx5IGRhdGFiYXNlOiBJRGF0YWJhc2U7XG5cbiAgLyoqXG4gICAqIFMzIGJ1Y2tldCBpbiB3aGljaCB0byBzdG9yZSBkYXRhLlxuICAgKlxuICAgKiBAZGVmYXVsdCBvbmUgaXMgY3JlYXRlZCBmb3IgeW91XG4gICAqL1xuICByZWFkb25seSBidWNrZXQ/OiBzMy5JQnVja2V0O1xuXG4gIC8qKlxuICAgKiBTMyBwcmVmaXggdW5kZXIgd2hpY2ggdGFibGUgb2JqZWN0cyBhcmUgc3RvcmVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIHByZWZpeC4gVGhlIGRhdGEgd2lsbCBiZSBzdG9yZWQgdW5kZXIgdGhlIHJvb3Qgb2YgdGhlIGJ1Y2tldC5cbiAgICovXG4gIHJlYWRvbmx5IHMzUHJlZml4Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDb2x1bW5zIG9mIHRoZSB0YWJsZS5cbiAgICovXG4gIHJlYWRvbmx5IGNvbHVtbnM6IENvbHVtbltdO1xuXG4gIC8qKlxuICAgKiBQYXJ0aXRpb24gY29sdW1ucyBvZiB0aGUgdGFibGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IHRhYmxlIGlzIG5vdCBwYXJ0aXRpb25lZFxuICAgKi9cbiAgcmVhZG9ubHkgcGFydGl0aW9uS2V5cz86IENvbHVtbltdO1xuXG4gIC8qKlxuICAgKiBQYXJ0aXRpb24gaW5kZXhlcyBvbiB0aGUgdGFibGUuIEEgbWF4aW11bSBvZiAzIGluZGV4ZXNcbiAgICogYXJlIGFsbG93ZWQgb24gYSB0YWJsZS4gS2V5cyBpbiB0aGUgaW5kZXggbXVzdCBiZSBwYXJ0XG4gICAqIG9mIHRoZSB0YWJsZSdzIHBhcnRpdGlvbiBrZXlzLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0YWJsZSBoYXMgbm8gcGFydGl0aW9uIGluZGV4ZXNcbiAgICovXG4gIHJlYWRvbmx5IHBhcnRpdGlvbkluZGV4ZXM/OiBQYXJ0aXRpb25JbmRleFtdO1xuXG4gIC8qKlxuICAgKiBTdG9yYWdlIHR5cGUgb2YgdGhlIHRhYmxlJ3MgZGF0YS5cbiAgICovXG4gIHJlYWRvbmx5IGRhdGFGb3JtYXQ6IERhdGFGb3JtYXQ7XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyB3aGV0aGVyIHRoZSB0YWJsZSdzIGRhdGEgaXMgY29tcHJlc3NlZCBvciBub3QuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBjb21wcmVzc2VkPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIGtpbmQgb2YgZW5jcnlwdGlvbiB0byBzZWN1cmUgdGhlIGRhdGEgd2l0aC5cbiAgICpcbiAgICogWW91IGNhbiBvbmx5IHByb3ZpZGUgdGhpcyBvcHRpb24gaWYgeW91IGFyZSBub3QgZXhwbGljaXRseSBwYXNzaW5nIGluIGEgYnVja2V0LlxuICAgKlxuICAgKiBJZiB5b3UgY2hvb3NlIGBTU0UtS01TYCwgeW91ICpjYW4qIHByb3ZpZGUgYW4gdW4tbWFuYWdlZCBLTVMga2V5IHdpdGggYGVuY3J5cHRpb25LZXlgLlxuICAgKiBJZiB5b3UgY2hvb3NlIGBDU0UtS01TYCwgeW91ICptdXN0KiBwcm92aWRlIGFuIHVuLW1hbmFnZWQgS01TIGtleSB3aXRoIGBlbmNyeXB0aW9uS2V5YC5cbiAgICpcbiAgICogQGRlZmF1bHQgQnVja2V0RW5jcnlwdGlvbi5TM19NQU5BR0VEXG4gICAqL1xuICByZWFkb25seSBlbmNyeXB0aW9uPzogVGFibGVFbmNyeXB0aW9uO1xuXG4gIC8qKlxuICAgKiBFeHRlcm5hbCBLTVMga2V5IHRvIHVzZSBmb3IgYnVja2V0IGVuY3J5cHRpb24uXG4gICAqXG4gICAqIFRoZSBgZW5jcnlwdGlvbmAgcHJvcGVydHkgbXVzdCBiZSBgU1NFLUtNU2Agb3IgYENTRS1LTVNgLlxuICAgKlxuICAgKiBAZGVmYXVsdCBrZXkgaXMgbWFuYWdlZCBieSBLTVMuXG4gICAqL1xuICByZWFkb25seSBlbmNyeXB0aW9uS2V5Pzoga21zLklLZXk7XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyB3aGV0aGVyIHRoZSB0YWJsZSBkYXRhIGlzIHN0b3JlZCBpbiBzdWJkaXJlY3Rvcmllcy5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IHN0b3JlZEFzU3ViRGlyZWN0b3JpZXM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBFbmFibGVzIHBhcnRpdGlvbiBmaWx0ZXJpbmcuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2F0aGVuYS9sYXRlc3QvdWcvZ2x1ZS1iZXN0LXByYWN0aWNlcy5odG1sI2dsdWUtYmVzdC1wcmFjdGljZXMtcGFydGl0aW9uLWluZGV4XG4gICAqXG4gICAqIEBkZWZhdWx0IC0gVGhlIHBhcmFtZXRlciBpcyBub3QgZGVmaW5lZFxuICAgKi9cbiAgcmVhZG9ubHkgZW5hYmxlUGFydGl0aW9uRmlsdGVyaW5nPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIHVzZXItc3VwcGxpZWQgcHJvcGVydGllcyBmb3IgdGhlIGRlc2NyaXB0aW9uIG9mIHRoZSBwaHlzaWNhbCBzdG9yYWdlIG9mIHRoaXMgdGFibGUuIFRoZXNlIHByb3BlcnRpZXMgaGVscCBkZXNjcmliZSB0aGUgZm9ybWF0IG9mIHRoZSBkYXRhIHRoYXQgaXMgc3RvcmVkIHdpdGhpbiB0aGUgY3Jhd2xlZCBkYXRhIHNvdXJjZXMuXG4gICAqXG4gICAqIFRoZSBrZXkvdmFsdWUgcGFpcnMgdGhhdCBhcmUgYWxsb3dlZCB0byBiZSBzdWJtaXR0ZWQgYXJlIG5vdCBsaW1pdGVkLCBob3dldmVyIHRoZWlyIGZ1bmN0aW9uYWxpdHkgaXMgbm90IGd1YXJhbnRlZWQuXG4gICAqXG4gICAqIFNvbWUga2V5cyB3aWxsIGJlIGF1dG8tcG9wdWxhdGVkIGJ5IGdsdWUgY3Jhd2xlcnMsIGhvd2V2ZXIsIHlvdSBjYW4gb3ZlcnJpZGUgdGhlbSBieSBzcGVjaWZ5aW5nIHRoZSBrZXkgYW5kIHZhbHVlIGluIHRoaXMgcHJvcGVydHkuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2dsdWUvbGF0ZXN0L2RnL3RhYmxlLXByb3BlcnRpZXMtY3Jhd2xlci5odG1sXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL3JlZHNoaWZ0L2xhdGVzdC9kZy9yX0NSRUFURV9FWFRFUk5BTF9UQUJMRS5odG1sI3JfQ1JFQVRFX0VYVEVSTkFMX1RBQkxFLXBhcmFtZXRlcnMgLSB1bmRlciBfXCJUQUJMRSBQUk9QRVJUSUVTXCJfXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqICAgIGRlY2xhcmUgY29uc3QgZ2x1ZURhdGFiYXNlOiBnbHVlLklEYXRhYmFzZTtcbiAgICogICAgY29uc3QgdGFibGUgPSBuZXcgZ2x1ZS5UYWJsZSh0aGlzLCAnVGFibGUnLCB7XG4gICAqICAgICAgc3RvcmFnZVBhcmFtZXRlcnM6IFtcbiAgICogICAgICAgICAgZ2x1ZS5TdG9yYWdlUGFyYW1ldGVyLnNraXBIZWFkZXJMaW5lQ291bnQoMSksXG4gICAqICAgICAgICAgIGdsdWUuU3RvcmFnZVBhcmFtZXRlci5jb21wcmVzc2lvblR5cGUoZ2x1ZS5Db21wcmVzc2lvblR5cGUuR1pJUCksXG4gICAqICAgICAgICAgIGdsdWUuU3RvcmFnZVBhcmFtZXRlci5jdXN0b20oJ2ZvbycsICdiYXInKSwgLy8gV2lsbCBoYXZlIG5vIGVmZmVjdFxuICAgKiAgICAgICAgICBnbHVlLlN0b3JhZ2VQYXJhbWV0ZXIuY3VzdG9tKCdzZXBhcmF0b3JDaGFyJywgJywnKSwgLy8gV2lsbCBkZXNjcmliZSB0aGUgc2VwYXJhdG9yIGNoYXIgdXNlZCBpbiB0aGUgZGF0YVxuICAgKiAgICAgICAgICBnbHVlLlN0b3JhZ2VQYXJhbWV0ZXIuY3VzdG9tKGdsdWUuU3RvcmFnZVBhcmFtZXRlcnMuV1JJVEVfUEFSQUxMRUwsICdvZmYnKSxcbiAgICogICAgICBdLFxuICAgKiAgICAgIC8vIC4uLlxuICAgKiAgICAgIGRhdGFiYXNlOiBnbHVlRGF0YWJhc2UsXG4gICAqICAgICAgY29sdW1uczogW3tcbiAgICogICAgICAgICAgbmFtZTogJ2NvbDEnLFxuICAgKiAgICAgICAgICB0eXBlOiBnbHVlLlNjaGVtYS5TVFJJTkcsXG4gICAqICAgICAgfV0sXG4gICAqICAgICAgZGF0YUZvcm1hdDogZ2x1ZS5EYXRhRm9ybWF0LkNTVixcbiAgICogICAgfSk7XG4gICAqXG4gICAqIEBkZWZhdWx0IC0gVGhlIHBhcmFtZXRlciBpcyBub3QgZGVmaW5lZFxuICAgKi9cbiAgcmVhZG9ubHkgc3RvcmFnZVBhcmFtZXRlcnM/OiBTdG9yYWdlUGFyYW1ldGVyW107XG59XG5cbi8qKlxuICogQSBHbHVlIHRhYmxlLlxuICovXG5leHBvcnQgY2xhc3MgVGFibGUgZXh0ZW5kcyBSZXNvdXJjZSBpbXBsZW1lbnRzIElUYWJsZSB7XG5cbiAgcHVibGljIHN0YXRpYyBmcm9tVGFibGVBcm4oc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgdGFibGVBcm46IHN0cmluZyk6IElUYWJsZSB7XG4gICAgY29uc3QgdGFibGVOYW1lID0gRm4uc2VsZWN0KDEsIEZuLnNwbGl0KCcvJywgU3RhY2sub2Yoc2NvcGUpLnNwbGl0QXJuKHRhYmxlQXJuLCBBcm5Gb3JtYXQuU0xBU0hfUkVTT1VSQ0VfTkFNRSkucmVzb3VyY2VOYW1lISkpO1xuXG4gICAgcmV0dXJuIFRhYmxlLmZyb21UYWJsZUF0dHJpYnV0ZXMoc2NvcGUsIGlkLCB7XG4gICAgICB0YWJsZUFybixcbiAgICAgIHRhYmxlTmFtZSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgVGFibGUgY29uc3RydWN0IHRoYXQgcmVwcmVzZW50cyBhbiBleHRlcm5hbCB0YWJsZS5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIFRoZSBzY29wZSBjcmVhdGluZyBjb25zdHJ1Y3QgKHVzdWFsbHkgYHRoaXNgKS5cbiAgICogQHBhcmFtIGlkIFRoZSBjb25zdHJ1Y3QncyBpZC5cbiAgICogQHBhcmFtIGF0dHJzIEltcG9ydCBhdHRyaWJ1dGVzXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21UYWJsZUF0dHJpYnV0ZXMoc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgYXR0cnM6IFRhYmxlQXR0cmlidXRlcyk6IElUYWJsZSB7XG4gICAgY2xhc3MgSW1wb3J0IGV4dGVuZHMgUmVzb3VyY2UgaW1wbGVtZW50cyBJVGFibGUge1xuICAgICAgcHVibGljIHJlYWRvbmx5IHRhYmxlQXJuID0gYXR0cnMudGFibGVBcm47XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgdGFibGVOYW1lID0gYXR0cnMudGFibGVOYW1lO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgSW1wb3J0KHNjb3BlLCBpZCk7XG4gIH1cblxuICAvKipcbiAgICogRGF0YWJhc2UgdGhpcyB0YWJsZSBiZWxvbmdzIHRvLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGRhdGFiYXNlOiBJRGF0YWJhc2U7XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyB3aGV0aGVyIHRoZSB0YWJsZSdzIGRhdGEgaXMgY29tcHJlc3NlZCBvciBub3QuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgY29tcHJlc3NlZDogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIHR5cGUgb2YgZW5jcnlwdGlvbiBlbmFibGVkIGZvciB0aGUgdGFibGUuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgZW5jcnlwdGlvbjogVGFibGVFbmNyeXB0aW9uO1xuXG4gIC8qKlxuICAgKiBUaGUgS01TIGtleSB1c2VkIHRvIHNlY3VyZSB0aGUgZGF0YSBpZiBgZW5jcnlwdGlvbmAgaXMgc2V0IHRvIGBDU0UtS01TYCBvciBgU1NFLUtNU2AuIE90aGVyd2lzZSwgYHVuZGVmaW5lZGAuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgZW5jcnlwdGlvbktleT86IGttcy5JS2V5O1xuXG4gIC8qKlxuICAgKiBTMyBidWNrZXQgaW4gd2hpY2ggdGhlIHRhYmxlJ3MgZGF0YSByZXNpZGVzLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGJ1Y2tldDogczMuSUJ1Y2tldDtcblxuICAvKipcbiAgICogUzMgS2V5IFByZWZpeCB1bmRlciB3aGljaCB0aGlzIHRhYmxlJ3MgZmlsZXMgYXJlIHN0b3JlZCBpbiBTMy5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBzM1ByZWZpeDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoaXMgdGFibGUuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgdGFibGVOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFSTiBvZiB0aGlzIHRhYmxlLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHRhYmxlQXJuOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEZvcm1hdCBvZiB0aGlzIHRhYmxlJ3MgZGF0YSBmaWxlcy5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBkYXRhRm9ybWF0OiBEYXRhRm9ybWF0O1xuXG4gIC8qKlxuICAgKiBUaGlzIHRhYmxlJ3MgY29sdW1ucy5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBjb2x1bW5zOiBDb2x1bW5bXTtcblxuICAvKipcbiAgICogVGhpcyB0YWJsZSdzIHBhcnRpdGlvbiBrZXlzIGlmIHRoZSB0YWJsZSBpcyBwYXJ0aXRpb25lZC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBwYXJ0aXRpb25LZXlzPzogQ29sdW1uW107XG5cbiAgLyoqXG4gICAqIFRoaXMgdGFibGUncyBwYXJ0aXRpb24gaW5kZXhlcy5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBwYXJ0aXRpb25JbmRleGVzPzogUGFydGl0aW9uSW5kZXhbXTtcblxuICAvKipcbiAgICogVGhlIHRhYmxlcycgc3RvcmFnZSBkZXNjcmlwdG9yIHByb3BlcnRpZXMuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgc3RvcmFnZVBhcmFtZXRlcnM/OiBTdG9yYWdlUGFyYW1ldGVyW107XG5cbiAgLyoqXG4gICAqIFBhcnRpdGlvbiBpbmRleGVzIG11c3QgYmUgY3JlYXRlZCBvbmUgYXQgYSB0aW1lLiBUbyBhdm9pZFxuICAgKiByYWNlIGNvbmRpdGlvbnMsIHdlIHN0b3JlIHRoZSByZXNvdXJjZSBhbmQgYWRkIGRlcGVuZGVuY2llc1xuICAgKiBlYWNoIHRpbWUgYSBuZXcgcGFydGl0aW9uIGluZGV4IGlzIGNyZWF0ZWQuXG4gICAqL1xuICBwcml2YXRlIHBhcnRpdGlvbkluZGV4Q3VzdG9tUmVzb3VyY2VzOiBBd3NDdXN0b21SZXNvdXJjZVtdID0gW107XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFRhYmxlUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHtcbiAgICAgIHBoeXNpY2FsTmFtZTogcHJvcHMudGFibGVOYW1lID8/XG4gICAgICAgIExhenkuc3RyaW5nKHtcbiAgICAgICAgICBwcm9kdWNlOiAoKSA9PiBOYW1lcy51bmlxdWVSZXNvdXJjZU5hbWUodGhpcywge30pLnRvTG93ZXJDYXNlKCksXG4gICAgICAgIH0pLFxuICAgIH0pO1xuXG4gICAgdGhpcy5kYXRhYmFzZSA9IHByb3BzLmRhdGFiYXNlO1xuICAgIHRoaXMuZGF0YUZvcm1hdCA9IHByb3BzLmRhdGFGb3JtYXQ7XG4gICAgdGhpcy5zM1ByZWZpeCA9IHByb3BzLnMzUHJlZml4ID8/ICcnO1xuXG4gICAgdmFsaWRhdGVTY2hlbWEocHJvcHMuY29sdW1ucywgcHJvcHMucGFydGl0aW9uS2V5cyk7XG4gICAgdGhpcy5jb2x1bW5zID0gcHJvcHMuY29sdW1ucztcbiAgICB0aGlzLnBhcnRpdGlvbktleXMgPSBwcm9wcy5wYXJ0aXRpb25LZXlzO1xuICAgIHRoaXMuc3RvcmFnZVBhcmFtZXRlcnMgPSBwcm9wcy5zdG9yYWdlUGFyYW1ldGVycztcblxuICAgIHRoaXMuY29tcHJlc3NlZCA9IHByb3BzLmNvbXByZXNzZWQgPz8gZmFsc2U7XG4gICAgY29uc3QgeyBidWNrZXQsIGVuY3J5cHRpb24sIGVuY3J5cHRpb25LZXkgfSA9IGNyZWF0ZUJ1Y2tldCh0aGlzLCBwcm9wcyk7XG4gICAgdGhpcy5idWNrZXQgPSBidWNrZXQ7XG4gICAgdGhpcy5lbmNyeXB0aW9uID0gZW5jcnlwdGlvbjtcbiAgICB0aGlzLmVuY3J5cHRpb25LZXkgPSBlbmNyeXB0aW9uS2V5O1xuXG4gICAgY29uc3QgdGFibGVSZXNvdXJjZSA9IG5ldyBDZm5UYWJsZSh0aGlzLCAnVGFibGUnLCB7XG4gICAgICBjYXRhbG9nSWQ6IHByb3BzLmRhdGFiYXNlLmNhdGFsb2dJZCxcblxuICAgICAgZGF0YWJhc2VOYW1lOiBwcm9wcy5kYXRhYmFzZS5kYXRhYmFzZU5hbWUsXG5cbiAgICAgIHRhYmxlSW5wdXQ6IHtcbiAgICAgICAgbmFtZTogdGhpcy5waHlzaWNhbE5hbWUsXG4gICAgICAgIGRlc2NyaXB0aW9uOiBwcm9wcy5kZXNjcmlwdGlvbiB8fCBgJHt0aGlzLnBoeXNpY2FsTmFtZX0gZ2VuZXJhdGVkIGJ5IENES2AsXG5cbiAgICAgICAgcGFydGl0aW9uS2V5czogcmVuZGVyQ29sdW1ucyhwcm9wcy5wYXJ0aXRpb25LZXlzKSxcblxuICAgICAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICAgICAgJ2NsYXNzaWZpY2F0aW9uJzogcHJvcHMuZGF0YUZvcm1hdC5jbGFzc2lmaWNhdGlvblN0cmluZz8udmFsdWUsXG4gICAgICAgICAgJ2hhc19lbmNyeXB0ZWRfZGF0YSc6IHRydWUsXG4gICAgICAgICAgJ3BhcnRpdGlvbl9maWx0ZXJpbmcuZW5hYmxlZCc6IHByb3BzLmVuYWJsZVBhcnRpdGlvbkZpbHRlcmluZyxcbiAgICAgICAgfSxcbiAgICAgICAgc3RvcmFnZURlc2NyaXB0b3I6IHtcbiAgICAgICAgICBsb2NhdGlvbjogYHMzOi8vJHt0aGlzLmJ1Y2tldC5idWNrZXROYW1lfS8ke3RoaXMuczNQcmVmaXh9YCxcbiAgICAgICAgICBjb21wcmVzc2VkOiB0aGlzLmNvbXByZXNzZWQsXG4gICAgICAgICAgc3RvcmVkQXNTdWJEaXJlY3RvcmllczogcHJvcHMuc3RvcmVkQXNTdWJEaXJlY3RvcmllcyA/PyBmYWxzZSxcbiAgICAgICAgICBjb2x1bW5zOiByZW5kZXJDb2x1bW5zKHByb3BzLmNvbHVtbnMpLFxuICAgICAgICAgIGlucHV0Rm9ybWF0OiBwcm9wcy5kYXRhRm9ybWF0LmlucHV0Rm9ybWF0LmNsYXNzTmFtZSxcbiAgICAgICAgICBvdXRwdXRGb3JtYXQ6IHByb3BzLmRhdGFGb3JtYXQub3V0cHV0Rm9ybWF0LmNsYXNzTmFtZSxcbiAgICAgICAgICBzZXJkZUluZm86IHtcbiAgICAgICAgICAgIHNlcmlhbGl6YXRpb25MaWJyYXJ5OiBwcm9wcy5kYXRhRm9ybWF0LnNlcmlhbGl6YXRpb25MaWJyYXJ5LmNsYXNzTmFtZSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHBhcmFtZXRlcnM6IHByb3BzLnN0b3JhZ2VQYXJhbWV0ZXJzID8gcHJvcHMuc3RvcmFnZVBhcmFtZXRlcnMucmVkdWNlKChhY2MsIHBhcmFtKSA9PiB7XG4gICAgICAgICAgICBpZiAocGFyYW0ua2V5IGluIGFjYykge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYER1cGxpY2F0ZSBzdG9yYWdlIHBhcmFtZXRlciBrZXk6ICR7cGFyYW0ua2V5fWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qga2V5ID0gcGFyYW0ua2V5O1xuICAgICAgICAgICAgYWNjW2tleV0gPSBwYXJhbS52YWx1ZTtcbiAgICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgICAgfSwge30gYXMgeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSkgOiB1bmRlZmluZWQsXG4gICAgICAgIH0sXG5cbiAgICAgICAgdGFibGVUeXBlOiAnRVhURVJOQUxfVEFCTEUnLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIHRoaXMudGFibGVOYW1lID0gdGhpcy5nZXRSZXNvdXJjZU5hbWVBdHRyaWJ1dGUodGFibGVSZXNvdXJjZS5yZWYpO1xuICAgIHRoaXMudGFibGVBcm4gPSB0aGlzLnN0YWNrLmZvcm1hdEFybih7XG4gICAgICBzZXJ2aWNlOiAnZ2x1ZScsXG4gICAgICByZXNvdXJjZTogJ3RhYmxlJyxcbiAgICAgIHJlc291cmNlTmFtZTogYCR7dGhpcy5kYXRhYmFzZS5kYXRhYmFzZU5hbWV9LyR7dGhpcy50YWJsZU5hbWV9YCxcbiAgICB9KTtcbiAgICB0aGlzLm5vZGUuZGVmYXVsdENoaWxkID0gdGFibGVSZXNvdXJjZTtcblxuICAgIC8vIFBhcnRpdGlvbiBpbmRleCBjcmVhdGlvbiByZWxpZXMgb24gY3JlYXRlZCB0YWJsZS5cbiAgICBpZiAocHJvcHMucGFydGl0aW9uSW5kZXhlcykge1xuICAgICAgdGhpcy5wYXJ0aXRpb25JbmRleGVzID0gcHJvcHMucGFydGl0aW9uSW5kZXhlcztcbiAgICAgIHRoaXMucGFydGl0aW9uSW5kZXhlcy5mb3JFYWNoKChpbmRleCkgPT4gdGhpcy5hZGRQYXJ0aXRpb25JbmRleChpbmRleCkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBwYXJ0aXRpb24gaW5kZXggdG8gdGhlIHRhYmxlLiBZb3UgY2FuIGhhdmUgYSBtYXhpbXVtIG9mIDMgcGFydGl0aW9uXG4gICAqIGluZGV4ZXMgdG8gYSB0YWJsZS4gUGFydGl0aW9uIGluZGV4IGtleXMgbXVzdCBiZSBhIHN1YnNldCBvZiB0aGUgdGFibGUnc1xuICAgKiBwYXJ0aXRpb24ga2V5cy5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZ2x1ZS9sYXRlc3QvZGcvcGFydGl0aW9uLWluZGV4ZXMuaHRtbFxuICAgKi9cbiAgcHVibGljIGFkZFBhcnRpdGlvbkluZGV4KGluZGV4OiBQYXJ0aXRpb25JbmRleCkge1xuICAgIGNvbnN0IG51bVBhcnRpdGlvbnMgPSB0aGlzLnBhcnRpdGlvbkluZGV4Q3VzdG9tUmVzb3VyY2VzLmxlbmd0aDtcbiAgICBpZiAobnVtUGFydGl0aW9ucyA+PSAzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ01heGltdW0gbnVtYmVyIG9mIHBhcnRpdGlvbiBpbmRleGVzIGFsbG93ZWQgaXMgMycpO1xuICAgIH1cbiAgICB0aGlzLnZhbGlkYXRlUGFydGl0aW9uSW5kZXgoaW5kZXgpO1xuXG4gICAgY29uc3QgaW5kZXhOYW1lID0gaW5kZXguaW5kZXhOYW1lID8/IHRoaXMuZ2VuZXJhdGVJbmRleE5hbWUoaW5kZXgua2V5TmFtZXMpO1xuICAgIGNvbnN0IHBhcnRpdGlvbkluZGV4Q3VzdG9tUmVzb3VyY2UgPSBuZXcgY3IuQXdzQ3VzdG9tUmVzb3VyY2UodGhpcywgYHBhcnRpdGlvbi1pbmRleC0ke2luZGV4TmFtZX1gLCB7XG4gICAgICBvbkNyZWF0ZToge1xuICAgICAgICBzZXJ2aWNlOiAnR2x1ZScsXG4gICAgICAgIGFjdGlvbjogJ2NyZWF0ZVBhcnRpdGlvbkluZGV4JyxcbiAgICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAgIERhdGFiYXNlTmFtZTogdGhpcy5kYXRhYmFzZS5kYXRhYmFzZU5hbWUsXG4gICAgICAgICAgVGFibGVOYW1lOiB0aGlzLnRhYmxlTmFtZSxcbiAgICAgICAgICBQYXJ0aXRpb25JbmRleDoge1xuICAgICAgICAgICAgSW5kZXhOYW1lOiBpbmRleE5hbWUsXG4gICAgICAgICAgICBLZXlzOiBpbmRleC5rZXlOYW1lcyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBwaHlzaWNhbFJlc291cmNlSWQ6IGNyLlBoeXNpY2FsUmVzb3VyY2VJZC5vZihcbiAgICAgICAgICBpbmRleE5hbWUsXG4gICAgICAgICksXG4gICAgICB9LFxuICAgICAgcG9saWN5OiBjci5Bd3NDdXN0b21SZXNvdXJjZVBvbGljeS5mcm9tU2RrQ2FsbHMoe1xuICAgICAgICByZXNvdXJjZXM6IGNyLkF3c0N1c3RvbVJlc291cmNlUG9saWN5LkFOWV9SRVNPVVJDRSxcbiAgICAgIH0pLFxuICAgICAgLy8gQVBJcyBhcmUgYXZhaWxhYmxlIGluIDIuMTA1NS4wXG4gICAgICBpbnN0YWxsTGF0ZXN0QXdzU2RrOiBmYWxzZSxcbiAgICB9KTtcbiAgICB0aGlzLmdyYW50VG9VbmRlcmx5aW5nUmVzb3VyY2VzKHBhcnRpdGlvbkluZGV4Q3VzdG9tUmVzb3VyY2UsIFsnZ2x1ZTpVcGRhdGVUYWJsZSddKTtcblxuICAgIC8vIERlcGVuZCBvbiBwcmV2aW91cyBwYXJ0aXRpb24gaW5kZXggaWYgcG9zc2libGUsIHRvIGF2b2lkIHJhY2UgY29uZGl0aW9uXG4gICAgaWYgKG51bVBhcnRpdGlvbnMgPiAwKSB7XG4gICAgICB0aGlzLnBhcnRpdGlvbkluZGV4Q3VzdG9tUmVzb3VyY2VzW251bVBhcnRpdGlvbnMtMV0ubm9kZS5hZGREZXBlbmRlbmN5KHBhcnRpdGlvbkluZGV4Q3VzdG9tUmVzb3VyY2UpO1xuICAgIH1cbiAgICB0aGlzLnBhcnRpdGlvbkluZGV4Q3VzdG9tUmVzb3VyY2VzLnB1c2gocGFydGl0aW9uSW5kZXhDdXN0b21SZXNvdXJjZSk7XG4gIH1cblxuICBwcml2YXRlIGdlbmVyYXRlSW5kZXhOYW1lKGtleXM6IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgICBjb25zdCBwcmVmaXggPSBrZXlzLmpvaW4oJy0nKSArICctJztcbiAgICBjb25zdCB1bmlxdWVJZCA9IE5hbWVzLnVuaXF1ZUlkKHRoaXMpO1xuICAgIGNvbnN0IG1heEluZGV4TGVuZ3RoID0gODA7IC8vIGFyYml0cmFyaWx5IHNwZWNpZmllZFxuICAgIGNvbnN0IHN0YXJ0SW5kZXggPSBNYXRoLm1heCgwLCB1bmlxdWVJZC5sZW5ndGggLSAobWF4SW5kZXhMZW5ndGggLSBwcmVmaXgubGVuZ3RoKSk7XG4gICAgcmV0dXJuIHByZWZpeCArIHVuaXF1ZUlkLnN1YnN0cmluZyhzdGFydEluZGV4KTtcbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVQYXJ0aXRpb25JbmRleChpbmRleDogUGFydGl0aW9uSW5kZXgpIHtcbiAgICBpZiAoaW5kZXguaW5kZXhOYW1lICE9PSB1bmRlZmluZWQgJiYgKGluZGV4LmluZGV4TmFtZS5sZW5ndGggPCAxIHx8IGluZGV4LmluZGV4TmFtZS5sZW5ndGggPiAyNTUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEluZGV4IG5hbWUgbXVzdCBiZSBiZXR3ZWVuIDEgYW5kIDI1NSBjaGFyYWN0ZXJzLCBidXQgZ290ICR7aW5kZXguaW5kZXhOYW1lLmxlbmd0aH1gKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLnBhcnRpdGlvbktleXMgfHwgdGhpcy5wYXJ0aXRpb25LZXlzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgdGFibGUgbXVzdCBoYXZlIHBhcnRpdGlvbiBrZXlzIHRvIGNyZWF0ZSBhIHBhcnRpdGlvbiBpbmRleCcpO1xuICAgIH1cbiAgICBjb25zdCBrZXlOYW1lcyA9IHRoaXMucGFydGl0aW9uS2V5cy5tYXAocGsgPT4gcGsubmFtZSk7XG4gICAgaWYgKCFpbmRleC5rZXlOYW1lcy5ldmVyeShrID0+IGtleU5hbWVzLmluY2x1ZGVzKGspKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBBbGwgaW5kZXgga2V5cyBtdXN0IGFsc28gYmUgcGFydGl0aW9uIGtleXMuIEdvdCAke2luZGV4LmtleU5hbWVzfSBidXQgcGFydGl0aW9uIGtleSBuYW1lcyBhcmUgJHtrZXlOYW1lc31gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR3JhbnQgcmVhZCBwZXJtaXNzaW9ucyB0byB0aGUgdGFibGUgYW5kIHRoZSB1bmRlcmx5aW5nIGRhdGEgc3RvcmVkIGluIFMzIHRvIGFuIElBTSBwcmluY2lwYWwuXG4gICAqXG4gICAqIEBwYXJhbSBncmFudGVlIHRoZSBwcmluY2lwYWxcbiAgICovXG4gIHB1YmxpYyBncmFudFJlYWQoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQge1xuICAgIGNvbnN0IHJldCA9IHRoaXMuZ3JhbnQoZ3JhbnRlZSwgcmVhZFBlcm1pc3Npb25zKTtcbiAgICBpZiAodGhpcy5lbmNyeXB0aW9uS2V5ICYmIHRoaXMuZW5jcnlwdGlvbiA9PT0gVGFibGVFbmNyeXB0aW9uLkNMSUVOVF9TSURFX0tNUykgeyB0aGlzLmVuY3J5cHRpb25LZXkuZ3JhbnREZWNyeXB0KGdyYW50ZWUpOyB9XG4gICAgdGhpcy5idWNrZXQuZ3JhbnRSZWFkKGdyYW50ZWUsIHRoaXMuZ2V0UzNQcmVmaXhGb3JHcmFudCgpKTtcbiAgICByZXR1cm4gcmV0O1xuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50IHdyaXRlIHBlcm1pc3Npb25zIHRvIHRoZSB0YWJsZSBhbmQgdGhlIHVuZGVybHlpbmcgZGF0YSBzdG9yZWQgaW4gUzMgdG8gYW4gSUFNIHByaW5jaXBhbC5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgdGhlIHByaW5jaXBhbFxuICAgKi9cbiAgcHVibGljIGdyYW50V3JpdGUoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQge1xuICAgIGNvbnN0IHJldCA9IHRoaXMuZ3JhbnQoZ3JhbnRlZSwgd3JpdGVQZXJtaXNzaW9ucyk7XG4gICAgaWYgKHRoaXMuZW5jcnlwdGlvbktleSAmJiB0aGlzLmVuY3J5cHRpb24gPT09IFRhYmxlRW5jcnlwdGlvbi5DTElFTlRfU0lERV9LTVMpIHsgdGhpcy5lbmNyeXB0aW9uS2V5LmdyYW50RW5jcnlwdChncmFudGVlKTsgfVxuICAgIHRoaXMuYnVja2V0LmdyYW50V3JpdGUoZ3JhbnRlZSwgdGhpcy5nZXRTM1ByZWZpeEZvckdyYW50KCkpO1xuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnQgcmVhZCBhbmQgd3JpdGUgcGVybWlzc2lvbnMgdG8gdGhlIHRhYmxlIGFuZCB0aGUgdW5kZXJseWluZyBkYXRhIHN0b3JlZCBpbiBTMyB0byBhbiBJQU0gcHJpbmNpcGFsLlxuICAgKlxuICAgKiBAcGFyYW0gZ3JhbnRlZSB0aGUgcHJpbmNpcGFsXG4gICAqL1xuICBwdWJsaWMgZ3JhbnRSZWFkV3JpdGUoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQge1xuICAgIGNvbnN0IHJldCA9IHRoaXMuZ3JhbnQoZ3JhbnRlZSwgWy4uLnJlYWRQZXJtaXNzaW9ucywgLi4ud3JpdGVQZXJtaXNzaW9uc10pO1xuICAgIGlmICh0aGlzLmVuY3J5cHRpb25LZXkgJiYgdGhpcy5lbmNyeXB0aW9uID09PSBUYWJsZUVuY3J5cHRpb24uQ0xJRU5UX1NJREVfS01TKSB7IHRoaXMuZW5jcnlwdGlvbktleS5ncmFudEVuY3J5cHREZWNyeXB0KGdyYW50ZWUpOyB9XG4gICAgdGhpcy5idWNrZXQuZ3JhbnRSZWFkV3JpdGUoZ3JhbnRlZSwgdGhpcy5nZXRTM1ByZWZpeEZvckdyYW50KCkpO1xuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnQgdGhlIGdpdmVuIGlkZW50aXR5IGN1c3RvbSBwZXJtaXNzaW9ucy5cbiAgICovXG4gIHB1YmxpYyBncmFudChncmFudGVlOiBpYW0uSUdyYW50YWJsZSwgYWN0aW9uczogc3RyaW5nW10pIHtcbiAgICByZXR1cm4gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsKHtcbiAgICAgIGdyYW50ZWUsXG4gICAgICByZXNvdXJjZUFybnM6IFt0aGlzLnRhYmxlQXJuXSxcbiAgICAgIGFjdGlvbnMsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnQgdGhlIGdpdmVuIGlkZW50aXR5IGN1c3RvbSBwZXJtaXNzaW9ucyB0byBBTEwgdW5kZXJseWluZyByZXNvdXJjZXMgb2YgdGhlIHRhYmxlLlxuICAgKiBQZXJtaXNzaW9ucyB3aWxsIGJlIGdyYW50ZWQgdG8gdGhlIGNhdGFsb2csIHRoZSBkYXRhYmFzZSwgYW5kIHRoZSB0YWJsZS5cbiAgICovXG4gIHB1YmxpYyBncmFudFRvVW5kZXJseWluZ1Jlc291cmNlcyhncmFudGVlOiBpYW0uSUdyYW50YWJsZSwgYWN0aW9uczogc3RyaW5nW10pIHtcbiAgICByZXR1cm4gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsKHtcbiAgICAgIGdyYW50ZWUsXG4gICAgICByZXNvdXJjZUFybnM6IFtcbiAgICAgICAgdGhpcy50YWJsZUFybixcbiAgICAgICAgdGhpcy5kYXRhYmFzZS5jYXRhbG9nQXJuLFxuICAgICAgICB0aGlzLmRhdGFiYXNlLmRhdGFiYXNlQXJuLFxuICAgICAgXSxcbiAgICAgIGFjdGlvbnMsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGdldFMzUHJlZml4Rm9yR3JhbnQoKSB7XG4gICAgcmV0dXJuIHRoaXMuczNQcmVmaXggKyAnKic7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVTY2hlbWEoY29sdW1uczogQ29sdW1uW10sIHBhcnRpdGlvbktleXM/OiBDb2x1bW5bXSk6IHZvaWQge1xuICBpZiAoY29sdW1ucy5sZW5ndGggPT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3lvdSBtdXN0IHNwZWNpZnkgYXQgbGVhc3Qgb25lIGNvbHVtbiBmb3IgdGhlIHRhYmxlJyk7XG4gIH1cbiAgLy8gQ2hlY2sgdGhlcmUgaXMgYXQgbGVhc3Qgb25lIGNvbHVtbiBhbmQgbm8gZHVwbGljYXRlZCBjb2x1bW4gbmFtZXMgb3IgcGFydGl0aW9uIGtleXMuXG4gIGNvbnN0IG5hbWVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIChjb2x1bW5zLmNvbmNhdChwYXJ0aXRpb25LZXlzIHx8IFtdKSkuZm9yRWFjaChjb2x1bW4gPT4ge1xuICAgIGlmIChuYW1lcy5oYXMoY29sdW1uLm5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGNvbHVtbiBuYW1lcyBhbmQgcGFydGl0aW9uIGtleXMgbXVzdCBiZSB1bmlxdWUsIGJ1dCBcXCcke2NvbHVtbi5uYW1lfVxcJyBpcyBkdXBsaWNhdGVkYCk7XG4gICAgfVxuICAgIG5hbWVzLmFkZChjb2x1bW4ubmFtZSk7XG4gIH0pO1xufVxuXG4vLyBtYXAgVGFibGVFbmNyeXB0aW9uIHRvIGJ1Y2tldCdzIFNTRSBjb25maWd1cmF0aW9uIChzMy5CdWNrZXRFbmNyeXB0aW9uKVxuY29uc3QgZW5jcnlwdGlvbk1hcHBpbmdzID0ge1xuICBbVGFibGVFbmNyeXB0aW9uLlMzX01BTkFHRURdOiBzMy5CdWNrZXRFbmNyeXB0aW9uLlMzX01BTkFHRUQsXG4gIFtUYWJsZUVuY3J5cHRpb24uS01TX01BTkFHRURdOiBzMy5CdWNrZXRFbmNyeXB0aW9uLktNU19NQU5BR0VELFxuICBbVGFibGVFbmNyeXB0aW9uLktNU106IHMzLkJ1Y2tldEVuY3J5cHRpb24uS01TLFxuICBbVGFibGVFbmNyeXB0aW9uLkNMSUVOVF9TSURFX0tNU106IHMzLkJ1Y2tldEVuY3J5cHRpb24uUzNfTUFOQUdFRCxcbn07XG5cbi8vIGNyZWF0ZSB0aGUgYnVja2V0IHRvIHN0b3JlIGEgdGFibGUncyBkYXRhIGRlcGVuZGluZyBvbiB0aGUgYGVuY3J5cHRpb25gIGFuZCBgZW5jcnlwdGlvbktleWAgcHJvcGVydGllcy5cbmZ1bmN0aW9uIGNyZWF0ZUJ1Y2tldCh0YWJsZTogVGFibGUsIHByb3BzOiBUYWJsZVByb3BzKSB7XG4gIGxldCBidWNrZXQgPSBwcm9wcy5idWNrZXQ7XG5cbiAgaWYgKGJ1Y2tldCAmJiAocHJvcHMuZW5jcnlwdGlvbiAhPT0gdW5kZWZpbmVkICYmIHByb3BzLmVuY3J5cHRpb24gIT09IFRhYmxlRW5jcnlwdGlvbi5DTElFTlRfU0lERV9LTVMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd5b3UgY2FuIG5vdCBzcGVjaWZ5IGVuY3J5cHRpb24gc2V0dGluZ3MgaWYgeW91IGFsc28gcHJvdmlkZSBhIGJ1Y2tldCcpO1xuICB9XG5cbiAgY29uc3QgZW5jcnlwdGlvbiA9IHByb3BzLmVuY3J5cHRpb24gfHwgVGFibGVFbmNyeXB0aW9uLlMzX01BTkFHRUQ7XG5cbiAgbGV0IGVuY3J5cHRpb25LZXk6IGttcy5JS2V5IHwgdW5kZWZpbmVkO1xuICBpZiAoZW5jcnlwdGlvbiA9PT0gVGFibGVFbmNyeXB0aW9uLkNMSUVOVF9TSURFX0tNUyAmJiBwcm9wcy5lbmNyeXB0aW9uS2V5ID09PSB1bmRlZmluZWQpIHtcbiAgICAvLyBDU0UtS01TIHNob3VsZCBiZWhhdmUgdGhlIHNhbWUgYXMgU1NFLUtNUyAtIHVzZSB0aGUgcHJvdmlkZWQga2V5IG9yIGNyZWF0ZSBvbmUgYXV0b21hdGljYWxseVxuICAgIC8vIFNpbmNlIEJ1Y2tldCBvbmx5IGtub3dzIGFib3V0IFNTRSwgd2UgcmVwZWF0IHRoZSBsb2dpYyBmb3IgQ1NFLUtNUyBhdCB0aGUgVGFibGUgbGV2ZWwuXG4gICAgZW5jcnlwdGlvbktleSA9IG5ldyBrbXMuS2V5KHRhYmxlLCAnS2V5Jyk7XG4gIH0gZWxzZSB7XG4gICAgZW5jcnlwdGlvbktleSA9IHByb3BzLmVuY3J5cHRpb25LZXk7XG4gIH1cblxuICAvLyBjcmVhdGUgdGhlIGJ1Y2tldCBpZiBub25lIHdhcyBwcm92aWRlZFxuICBpZiAoIWJ1Y2tldCkge1xuICAgIGlmIChlbmNyeXB0aW9uID09PSBUYWJsZUVuY3J5cHRpb24uQ0xJRU5UX1NJREVfS01TKSB7XG4gICAgICBidWNrZXQgPSBuZXcgczMuQnVja2V0KHRhYmxlLCAnQnVja2V0Jyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGJ1Y2tldCA9IG5ldyBzMy5CdWNrZXQodGFibGUsICdCdWNrZXQnLCB7XG4gICAgICAgIGVuY3J5cHRpb246IGVuY3J5cHRpb25NYXBwaW5nc1tlbmNyeXB0aW9uXSxcbiAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgIH0pO1xuICAgICAgZW5jcnlwdGlvbktleSA9IGJ1Y2tldC5lbmNyeXB0aW9uS2V5O1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgYnVja2V0LFxuICAgIGVuY3J5cHRpb24sXG4gICAgZW5jcnlwdGlvbktleSxcbiAgfTtcbn1cblxuY29uc3QgcmVhZFBlcm1pc3Npb25zID0gW1xuICAnZ2x1ZTpCYXRjaEdldFBhcnRpdGlvbicsXG4gICdnbHVlOkdldFBhcnRpdGlvbicsXG4gICdnbHVlOkdldFBhcnRpdGlvbnMnLFxuICAnZ2x1ZTpHZXRUYWJsZScsXG4gICdnbHVlOkdldFRhYmxlcycsXG4gICdnbHVlOkdldFRhYmxlVmVyc2lvbicsXG4gICdnbHVlOkdldFRhYmxlVmVyc2lvbnMnLFxuXTtcblxuY29uc3Qgd3JpdGVQZXJtaXNzaW9ucyA9IFtcbiAgJ2dsdWU6QmF0Y2hDcmVhdGVQYXJ0aXRpb24nLFxuICAnZ2x1ZTpCYXRjaERlbGV0ZVBhcnRpdGlvbicsXG4gICdnbHVlOkNyZWF0ZVBhcnRpdGlvbicsXG4gICdnbHVlOkRlbGV0ZVBhcnRpdGlvbicsXG4gICdnbHVlOlVwZGF0ZVBhcnRpdGlvbicsXG5dO1xuXG5mdW5jdGlvbiByZW5kZXJDb2x1bW5zKGNvbHVtbnM/OiBBcnJheTxDb2x1bW4gfCBDb2x1bW4+KSB7XG4gIGlmIChjb2x1bW5zID09PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIHJldHVybiBjb2x1bW5zLm1hcChjb2x1bW4gPT4ge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiBjb2x1bW4ubmFtZSxcbiAgICAgIHR5cGU6IGNvbHVtbi50eXBlLmlucHV0U3RyaW5nLFxuICAgICAgY29tbWVudDogY29sdW1uLmNvbW1lbnQsXG4gICAgfTtcbiAgfSk7XG59XG4iXX0=
|