@decaf-ts/decoration 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +200 -108
  2. package/dist/decoration.cjs +312 -165
  3. package/dist/decoration.esm.cjs +310 -166
  4. package/lib/constants.cjs +23 -30
  5. package/lib/constants.d.ts +22 -29
  6. package/lib/decoration/Decoration.cjs +55 -57
  7. package/lib/decoration/Decoration.d.ts +59 -61
  8. package/lib/decoration/index.cjs +5 -1
  9. package/lib/decoration/index.d.ts +4 -0
  10. package/lib/decoration/types.cjs +1 -1
  11. package/lib/decoration/types.d.ts +34 -49
  12. package/lib/decorators.cjs +103 -25
  13. package/lib/decorators.d.ts +82 -25
  14. package/lib/esm/constants.d.ts +22 -29
  15. package/lib/esm/constants.js +23 -30
  16. package/lib/esm/decoration/Decoration.d.ts +59 -61
  17. package/lib/esm/decoration/Decoration.js +55 -57
  18. package/lib/esm/decoration/index.d.ts +4 -0
  19. package/lib/esm/decoration/index.js +5 -1
  20. package/lib/esm/decoration/types.d.ts +34 -49
  21. package/lib/esm/decoration/types.js +1 -1
  22. package/lib/esm/decorators.d.ts +82 -25
  23. package/lib/esm/decorators.js +101 -26
  24. package/lib/esm/index.d.ts +4 -5
  25. package/lib/esm/index.js +5 -6
  26. package/lib/esm/metadata/Metadata.d.ts +108 -51
  27. package/lib/esm/metadata/Metadata.js +130 -51
  28. package/lib/esm/metadata/index.d.ts +4 -0
  29. package/lib/esm/metadata/index.js +5 -1
  30. package/lib/esm/metadata/types.d.ts +22 -6
  31. package/lib/esm/metadata/types.js +1 -1
  32. package/lib/index.cjs +5 -6
  33. package/lib/index.d.ts +4 -5
  34. package/lib/metadata/Metadata.cjs +130 -51
  35. package/lib/metadata/Metadata.d.ts +108 -51
  36. package/lib/metadata/index.cjs +5 -1
  37. package/lib/metadata/index.d.ts +4 -0
  38. package/lib/metadata/types.cjs +1 -1
  39. package/lib/metadata/types.d.ts +22 -6
  40. package/package.json +10 -3
@@ -5,62 +5,55 @@
5
5
  })(this, (function (exports) { 'use strict';
6
6
 
7
7
  /**
8
- * @description Default flavour identifier for the decorator system
9
- * @summary Defines the default flavour used by the Decoration class when no specific flavour is provided.
10
- * This constant is used throughout the library as the fallback flavour for decorators.
8
+ * @description Default flavour identifier for the decorator system.
9
+ * @summary Defines the default flavour used by the Decoration class when no specific flavour is provided. This constant is used throughout the library as the fallback flavour for decorators.
11
10
  * @const DefaultFlavour
12
11
  * @memberOf module:decoration
13
12
  */
14
13
  const DefaultFlavour = "decaf";
15
14
  /**
16
- * @description Character used to split nested metadata keys
17
- * @summary The delimiter used by the metadata store to traverse nested object paths when reading/writing values.
15
+ * @description Character used to split nested metadata keys.
16
+ * @summary Defines the delimiter the metadata store uses to traverse nested object paths when reading or writing values.
18
17
  * @const ObjectKeySplitter
19
18
  * @memberOf module:decoration
20
19
  */
21
20
  const ObjectKeySplitter = ".";
22
21
  /**
23
- * @description Enum containing metadata keys used for reflection in the model system
24
- * @summary Defines the various Model keys used for reflection and metadata storage.
25
- * These keys are used throughout the library to store and retrieve metadata about models,
26
- * their properties, and their behavior.
27
- * @readonly
22
+ * @description Metadata token registry for the decoration system.
23
+ * @summary Enumerates the keys used during reflection and metadata storage for classes, properties, methods, descriptions, and registered libraries.
28
24
  * @enum {string}
29
25
  * @readonly
26
+ * @const DecorationKeys
30
27
  * @memberOf module:decoration
31
28
  */
32
29
  exports.DecorationKeys = void 0;
33
30
  (function (DecorationKeys) {
31
+ /** @description Storage bucket for decoration-aware library registrations. */
34
32
  DecorationKeys["LIBRARIES"] = "libraries";
35
- /** Storage key used on the constructor to mirror runtime metadata */
33
+ /** @description Storage key mirrored on constructors that holds runtime metadata. */
36
34
  DecorationKeys["REFLECT"] = "__decaf";
37
- /** Map of model property keys to their reflected design types */
35
+ /** @description Container of reflected property metadata for a model. */
38
36
  DecorationKeys["PROPERTIES"] = "properties";
39
- /** Map of model method keys to their reflected design params and return types */
37
+ /** @description Container of reflected method metadata for a model. */
40
38
  DecorationKeys["METHODS"] = "methods";
41
- /** Key under which the model's constructor is stored */
39
+ /** @description Key under which the model constructor reference is persisted. */
42
40
  DecorationKeys["CLASS"] = "class";
43
- /** Container of human-friendly descriptions per class and property */
41
+ /** @description Human-readable descriptions for classes and members. */
44
42
  DecorationKeys["DESCRIPTION"] = "description";
45
- /** Reflect metadata key for design time type of a property */
43
+ /** @description Storage slot tracking the original constructor when overridden. */
44
+ DecorationKeys["CONSTRUCTOR"] = "constructor";
45
+ /** @description Collected parameter metadata for configured decorators. */
46
+ DecorationKeys["PARAMETERS"] = "parameters";
47
+ /** @description Reflect metadata key for a property's design type. */
46
48
  DecorationKeys["DESIGN_TYPE"] = "design:type";
47
- /** Reflect metadata key for constructor parameter types */
49
+ /** @description Reflect metadata key for recorded constructor parameter types. */
48
50
  DecorationKeys["DESIGN_PARAMS"] = "design:paramtypes";
49
- /** Reflect metadata key for method return type */
51
+ /** @description Reflect metadata key for a method's return type. */
50
52
  DecorationKeys["DESIGN_RETURN"] = "design:returntype";
51
53
  })(exports.DecorationKeys || (exports.DecorationKeys = {}));
52
54
  /**
53
- * @description Typedef for the default metadata object shape
54
- * @summary Describes the minimal structure persisted for a model before any metadata is recorded.
55
- * @template M
56
- * @typedef {object} DefaultMetadataType<M>
57
- * @property {Record<string, Constructor | undefined>} properties - Mapping of property names to their design types
58
- * @memberOf module:decoration
59
- */
60
- /**
61
- * @description Default metadata instance
62
- * @summary Concrete default metadata object used when initializing metadata for a model
63
- * @type {DefaultMetadataType<any>}
55
+ * @description Default metadata instance.
56
+ * @summary Provides the default metadata shape used when initializing new metadata entries for a model.
64
57
  * @const DefaultMetadata
65
58
  * @memberOf module:decoration
66
59
  */
@@ -69,12 +62,12 @@
69
62
  };
70
63
 
71
64
  /**
72
- * @description Retrieves a nested value from an object given a path
73
- * @summary Walks an object structure using a splitter-delimited path and returns the value at that location or undefined if any key is missing.
74
- * @param {Record<string, any>} obj The object to traverse
75
- * @param {string} path The path to the desired value (e.g., "a.b.c")
76
- * @param {string} [splitter=ObjectKeySplitter] The delimiter used to split the path
77
- * @return {*} The resolved value at the given path or undefined if not found
65
+ * @description Retrieves a nested value from an object given a path.
66
+ * @summary Walks an object structure using a splitter-delimited path and returns the value at that location or `undefined` if any key is missing.
67
+ * @param {Record<string, any>} obj Object to traverse for the lookup.
68
+ * @param {string} path Splitter-delimited path to the desired value (e.g., "a.b.c").
69
+ * @param {string} [splitter=ObjectKeySplitter] Delimiter used to separate the path segments.
70
+ * @return {any|undefined} Value resolved at the given path or `undefined` when not found.
78
71
  * @function getValueBySplitter
79
72
  * @mermaid
80
73
  * sequenceDiagram
@@ -105,12 +98,12 @@
105
98
  return current;
106
99
  }
107
100
  /**
108
- * @description Sets a nested value on an object given a path
101
+ * @description Sets a nested value on an object given a path.
109
102
  * @summary Traverses or creates intermediate objects following a splitter-delimited path and assigns the provided value at the destination key.
110
- * @param {Record<string, any>} obj The object to mutate
111
- * @param {string} path The destination path (e.g., "a.b.c")
112
- * @param {*} value The value to set at the destination
113
- * @param {string} [splitter=ObjectKeySplitter] The delimiter used to split the path
103
+ * @param {Record<string, any>} obj Object to mutate while drilling into nested keys.
104
+ * @param {string} path Splitter-delimited destination path (e.g., "a.b.c").
105
+ * @param {any} value Value to set at the destination node.
106
+ * @param {string} [splitter=ObjectKeySplitter] Delimiter used to separate the path segments.
114
107
  * @return {void}
115
108
  * @function setValueBySplitter
116
109
  * @mermaid
@@ -148,10 +141,11 @@
148
141
  current[lastKey] = value;
149
142
  }
150
143
  /**
151
- * @description Centralized runtime metadata store bound to constructors
144
+ * @description Centralized runtime metadata store bound to constructors.
152
145
  * @summary Provides utilities to read and write structured metadata for classes and their members, with optional mirroring onto the constructor via a well-known symbol key. Supports nested key paths using a configurable splitter and offers both instance and static APIs.
153
- * @template M The model type the metadata belongs to
154
- * @template META Extends BasicMetadata<M> representing the metadata structure
146
+ * @template M The model type the metadata belongs to.
147
+ * @template META Extends BasicMetadata<M> representing the metadata structure.
148
+ * @param {string} [flavour=DefaultFlavour] Optional flavour identifier applied when instantiating helper builders.
155
149
  * @class
156
150
  * @example
157
151
  * // Define and read metadata for a class
@@ -191,10 +185,10 @@
191
185
  static { this.mirror = true; }
192
186
  constructor() { }
193
187
  /**
194
- * @description Lists known property keys for a model
188
+ * @description Lists known property keys for a model.
195
189
  * @summary Reads the metadata entry and returns the names of properties that have recorded type information.
196
- * @param {Constructor} model The target constructor
197
- * @return {string[]|undefined} Array of property names or undefined if no metadata exists
190
+ * @param {Constructor} model Target constructor whose property metadata should be inspected.
191
+ * @return {string[]|undefined} Array of property names or `undefined` if no metadata exists.
198
192
  */
199
193
  static properties(model) {
200
194
  const meta = this.get(model);
@@ -203,10 +197,10 @@
203
197
  return Object.keys(meta.properties);
204
198
  }
205
199
  /**
206
- * @description Lists known methods for a model
207
- * @summary Reads the metadata entry and returns the names of models that have recorded type information.
208
- * @param {Constructor} model The target constructor
209
- * @return {string[]|undefined} Array of property names or undefined if no metadata exists
200
+ * @description Lists known methods for a model.
201
+ * @summary Reads the metadata entry and returns the method names that have recorded signature metadata for the provided constructor.
202
+ * @param {Constructor} model Target constructor whose method metadata should be inspected.
203
+ * @return {string[]|undefined} Array of method names or `undefined` if no metadata exists.
210
204
  */
211
205
  static methods(model) {
212
206
  const meta = this.get(model, exports.DecorationKeys.METHODS);
@@ -215,81 +209,133 @@
215
209
  return Object.keys(meta);
216
210
  }
217
211
  /**
218
- * @description Retrieves a human-readable description for a class or a property
212
+ * @description Retrieves a human-readable description for a class or a property.
219
213
  * @summary Looks up the description stored under the metadata "description" map. If a property key is provided, returns the property's description; otherwise returns the class description.
220
214
  * @template M
221
- * @param {Constructor<M>} model The target constructor whose description is being retrieved
222
- * @param {string} [prop] Optional property key for which to fetch the description
223
- * @return {string|undefined} The description text if present, otherwise undefined
215
+ * @param {Constructor<M>} model Target constructor whose description is being retrieved.
216
+ * @param {string} [prop] Optional property key (typed as `keyof M`) for which to fetch the description.
217
+ * @return {string|undefined} Description text if present, otherwise `undefined`.
224
218
  */
225
219
  static description(model, prop) {
226
220
  return this.get(model, [exports.DecorationKeys.DESCRIPTION, prop ? prop : exports.DecorationKeys.CLASS].join(this.splitter));
227
221
  }
228
222
  /**
229
- * @description Retrieves the recorded params for a method
230
- * @summary Reads the metadata entry under "methods.<prop>.design:params" to return the arguments for the iven method.
231
- * @param {Constructor} model The target constructor
232
- * @param {string} prop The method name
233
- * @return {any[] | undefined} The argument types of the method or undefined if not available
223
+ * @description Retrieves the recorded params for a method.
224
+ * @summary Reads the metadata entry under `methods.<prop>.design:paramtypes` to return the parameter constructors for the given method.
225
+ * @template M
226
+ * @param {Constructor<M>} model Target constructor owning the method metadata.
227
+ * @param {string} prop Method name whose parameters should be fetched.
228
+ * @return {any[]|undefined} Array of constructor references describing each parameter or `undefined` when not available.
234
229
  */
235
230
  static params(model, prop) {
236
231
  return this.get(model, [exports.DecorationKeys.METHODS, prop, exports.DecorationKeys.DESIGN_PARAMS].join(this.splitter));
237
232
  }
238
233
  /**
239
- * @description Retrieves the recorded return type for a method
240
- * @summary Reads the metadata entry under "methods.<prop>.design:return" to return the return type for the given method.
241
- * @param {Constructor} model The target constructor
242
- * @param {string} prop The method name
243
- * @return {any|undefined} The return type of the method or undefined if not available
234
+ * @description Retrieves a single recorded parameter type for a method.
235
+ * @summary Looks up the parameter metadata for the provided index, enforcing bounds and returning the constructor reference for that argument.
236
+ * @template M
237
+ * @param {Constructor<M>} model Target constructor owning the method metadata.
238
+ * @param {string} prop Method name whose parameter should be returned.
239
+ * @param {number} index Zero-based index of the desired parameter metadata.
240
+ * @return {any|undefined} Constructor reference for the parameter or `undefined` if not recorded.
241
+ */
242
+ static param(model, prop, index) {
243
+ const params = this.params(model, prop);
244
+ if (!params)
245
+ return undefined;
246
+ if (index > params.length - 1)
247
+ throw new Error(`Parameter index ${index} out of range for ${String(prop)}`);
248
+ return params[index];
249
+ }
250
+ /**
251
+ * @description Retrieves the recorded return type for a method.
252
+ * @summary Reads the metadata entry under `methods.<prop>.design:returntype` to return the return type for the given method.
253
+ * @template M
254
+ * @param {Constructor<M>} model Target constructor whose method metadata should be inspected.
255
+ * @param {string} prop Method name whose return type should be fetched.
256
+ * @return {any|undefined} Constructor reference for the return type or `undefined` when not available.
244
257
  */
245
258
  static return(model, prop) {
246
259
  return this.get(model, [exports.DecorationKeys.METHODS, prop, exports.DecorationKeys.DESIGN_RETURN].join(this.splitter));
247
260
  }
248
261
  /**
249
- * @description Retrieves the recorded design type for a property
250
- * @summary Reads the metadata entry under "properties.<prop>" to return the constructor recorded for the given property name.
251
- * @param {Constructor} model The target constructor
252
- * @param {string} prop The property name whose type should be returned
253
- * @return {Constructor|undefined} The constructor reference of the property type or undefined if not available
262
+ * @description Retrieves the recorded design type for a property.
263
+ * @summary Reads the metadata entry under `properties.<prop>` to return the constructor recorded for the given property name.
264
+ * @param {Constructor} model Target constructor whose property metadata should be inspected.
265
+ * @param {string} prop Property name whose type metadata should be returned.
266
+ * @return {Constructor|undefined} Constructor reference for the property type or `undefined` if not available.
254
267
  */
255
268
  static type(model, prop) {
256
269
  return this.get(model, [exports.DecorationKeys.PROPERTIES, prop].join(this.splitter));
257
270
  }
258
271
  /**
259
- * @description Retrieves metadata for a model or a specific key within it
272
+ * @description Resolves the canonical constructor associated with the provided model handle.
273
+ * @summary Returns the stored constructor reference when the provided model is a proxy or reduced value. Falls back to the original model when no constructor metadata has been recorded yet.
274
+ * @template M
275
+ * @param {Constructor<M>} model Model used when recording metadata.
276
+ * @return {Constructor<M>|undefined} Canonical constructor if stored, otherwise `undefined`.
277
+ */
278
+ static constr(model) {
279
+ return this.get(model, exports.DecorationKeys.CONSTRUCTOR);
280
+ }
281
+ /**
282
+ * @description Retrieves metadata for a model or a specific key within it.
260
283
  * @summary When called with a constructor only, returns the entire metadata object associated with the model. When a key path is provided, returns the value stored at that nested key.
261
284
  * @template M
262
285
  * @template META
263
- * @param {Constructor<M> | string} model The target constructor used to locate the metadata record
264
- * @param {string} [key] Optional nested key path to fetch a specific value
265
- * @return {META|*|undefined} The metadata object, the value at the key path, or undefined if nothing exists
286
+ * @param {Constructor<M>|string} model Target constructor used to locate the metadata record or a pre-resolved symbol identifier.
287
+ * @param {string} [key] Optional nested key path to fetch a specific value.
288
+ * @return {META|*|undefined} Metadata object, the value at the key path, or `undefined` if nothing exists.
266
289
  */
267
290
  static get(model, key) {
291
+ if (key !== exports.DecorationKeys.CONSTRUCTOR)
292
+ model = this.constr(model) || model;
268
293
  const symbol = Symbol.for(model.toString());
269
294
  return this.innerGet(symbol, key);
270
295
  }
296
+ /**
297
+ * @description Retrieves metadata stored under a symbol key.
298
+ * @summary Internal helper that resolves and optionally drills into the in-memory metadata map for the provided symbol and key path.
299
+ * @param {symbol} symbol Symbol representing the metadata bucket.
300
+ * @param {string|symbol} [key] Optional nested key referencing a specific metadata entry.
301
+ * @return {any} Stored metadata object or value for the provided key, or `undefined` when absent.
302
+ */
271
303
  static innerGet(symbol, key) {
272
304
  if (!this._metadata[symbol])
273
305
  return undefined;
274
306
  if (!key)
275
307
  return this._metadata[symbol];
276
- return getValueBySplitter(this._metadata[symbol], key, this.splitter);
308
+ if (typeof key === "string")
309
+ return getValueBySplitter(this._metadata[symbol], key, this.splitter);
310
+ return this._metadata[symbol][key];
277
311
  }
312
+ /**
313
+ * @description Writes metadata under a symbol key.
314
+ * @summary Internal helper that ensures the metadata bucket exists for the provided symbol and persists the given value, drilling into nested structures when the key is a string path.
315
+ * @param {symbol} symbol Symbol representing the metadata bucket.
316
+ * @param {string|symbol} key Nested key path or direct symbol under which to store the metadata value.
317
+ * @param {any} value Value persisted in the metadata store.
318
+ * @return {void}
319
+ */
278
320
  static innerSet(symbol, key, value) {
279
321
  if (!this._metadata[symbol])
280
322
  this._metadata[symbol] = {};
281
- setValueBySplitter(this._metadata[symbol], key, value, this.splitter);
323
+ if (typeof key === "string")
324
+ return setValueBySplitter(this._metadata[symbol], key, value, this.splitter);
325
+ this._metadata[symbol][key] = value;
282
326
  }
283
327
  /**
284
- * @description Writes a metadata value at a given nested key path
328
+ * @description Writes a metadata value at a given nested key path.
285
329
  * @summary Ensures the metadata record exists for the constructor, mirrors it on the constructor when enabled, and sets the provided value on the nested key path using the configured splitter.
286
330
  * @template M
287
- * @param {Constructor<M> | string} model The target constructor to which the metadata belongs
288
- * @param {string} key The nested key path at which to store the value
289
- * @param {*} value The value to store in the metadata
331
+ * @param {Constructor<M>|string} model Target constructor to which the metadata belongs or a direct identifier string.
332
+ * @param {string} key Nested key path at which to store the value.
333
+ * @param {any} value Value to store in the metadata.
290
334
  * @return {void}
291
335
  */
292
336
  static set(model, key, value) {
337
+ if (typeof model !== "string")
338
+ model = this.constr(model) || model;
293
339
  const symbol = Symbol.for(model.toString());
294
340
  this.innerSet(symbol, key, value);
295
341
  if (Metadata.mirror &&
@@ -302,6 +348,14 @@
302
348
  });
303
349
  }
304
350
  }
351
+ /**
352
+ * @description Registers a decoration-aware library and its version.
353
+ * @summary Stores the version string for an integrating library under the shared libraries metadata symbol, preventing duplicate registrations for the same library identifier.
354
+ * @param {string} library Package name or identifier to register.
355
+ * @param {string} version Semantic version string associated with the library.
356
+ * @return {void}
357
+ * @throws {Error} If the library has already been registered.
358
+ */
305
359
  static registerLibrary(library, version) {
306
360
  const symbol = Symbol.for(exports.DecorationKeys.LIBRARIES);
307
361
  const lib = this.innerGet(symbol, library);
@@ -309,13 +363,31 @@
309
363
  throw new Error(`Library already ${library} registered with version ${version}`);
310
364
  this.innerSet(symbol, library, version);
311
365
  }
366
+ /**
367
+ * @description Lists registered decoration-aware libraries.
368
+ * @summary Returns the in-memory map of library identifiers to semantic versions that have been registered with the Decoration metadata store.
369
+ * @return {Record<string, string>} Map of registered library identifiers to their version strings.
370
+ */
371
+ static libraries() {
372
+ const symbol = Symbol.for(exports.DecorationKeys.LIBRARIES);
373
+ return this.innerGet(symbol) || {};
374
+ }
375
+ /**
376
+ * @description Joins path segments using the current splitter.
377
+ * @summary Constructs a nested metadata key by concatenating string segments with the configured splitter for use with the metadata store.
378
+ * @param {...string} strs Key segments to join into a full metadata path.
379
+ * @return {string} Splitter-joined metadata key.
380
+ */
381
+ static key(...strs) {
382
+ return strs.join(this.splitter);
383
+ }
312
384
  }
313
385
 
314
386
  /**
315
- * @description Default resolver that returns the current default flavour
316
- * @summary Resolves the flavour for a given target by always returning the library's DefaultFlavour value.
317
- * @param {object} target The target object being decorated
318
- * @return {string} The resolved flavour identifier
387
+ * @description Default resolver that returns the current default flavour.
388
+ * @summary Resolves the flavour for a given target by always returning the library's `DefaultFlavour` value.
389
+ * @param {object} target Target object being decorated.
390
+ * @return {string} Resolved flavour identifier.
319
391
  * @function defaultFlavourResolver
320
392
  * @memberOf module:decoration
321
393
  */
@@ -324,13 +396,10 @@
324
396
  return DefaultFlavour;
325
397
  }
326
398
  /**
327
- * @description A decorator management class that handles flavoured decorators
328
- * @summary The Decoration class provides a builder pattern for creating and managing decorators with different flavours.
329
- * It supports registering, extending, and applying decorators with context-aware flavour resolution.
330
- * The class implements a fluent interface for defining, extending, and applying decorators with different flavours,
331
- * allowing for framework-specific decorator implementations while maintaining a consistent API.
332
- * @template T Type of the decorator (ClassDecorator | PropertyDecorator | MethodDecorator)
333
- * @param {string} [flavour] Optional flavour parameter for the decorator context
399
+ * @description A decorator management class that handles flavoured decorators.
400
+ * @summary The Decoration class provides a builder pattern for creating and managing decorators with different flavours. It supports registering, extending, and applying decorators with context-aware flavour resolution, allowing framework-specific implementations while maintaining a consistent API.
401
+ * @template T Type of the decorator (ClassDecorator | PropertyDecorator | MethodDecorator).
402
+ * @param {string} [flavour=DefaultFlavour] Optional flavour parameter for the decorator context.
334
403
  * @class
335
404
  * @example
336
405
  * ```typescript
@@ -367,34 +436,34 @@
367
436
  */
368
437
  class Decoration {
369
438
  /**
370
- * @description Static map of registered decorators
371
- * @summary Stores all registered decorators organized by key and flavour
439
+ * @description Static map of registered decorators.
440
+ * @summary Stores all registered decorators organised by key and flavour.
372
441
  */
373
442
  static { this.decorators = {}; }
374
443
  /**
375
- * @description Function to resolve flavour from a target
376
- * @summary Resolver function that determines the appropriate flavour for a given target
444
+ * @description Function to resolve flavour from a target.
445
+ * @summary Resolver function that determines the appropriate flavour for a given target.
377
446
  */
378
447
  static { this.flavourResolver = defaultFlavourResolver; }
379
448
  constructor(flavour = DefaultFlavour) {
380
449
  this.flavour = flavour;
381
450
  }
382
451
  /**
383
- * @description Sets the key for the decoration builder
384
- * @summary Initializes a new decoration chain with the specified key
385
- * @param {string} key The identifier for the decorator
386
- * @return {DecorationBuilderMid} Builder instance for method chaining
452
+ * @description Sets the key for the decoration builder.
453
+ * @summary Initialises a new decoration chain with the specified key.
454
+ * @param {string} key Identifier for the decorator.
455
+ * @return {DecorationBuilderMid} Builder instance for method chaining.
387
456
  */
388
457
  for(key) {
389
458
  this.key = key;
390
459
  return this;
391
460
  }
392
461
  /**
393
- * @description Adds decorators to the current context
394
- * @summary Internal method to add decorators with addon support
395
- * @param {boolean} [addon=false] Whether the decorators are addons
396
- * @param decorators Array of decorators
397
- * @return {this} Current instance for chaining
462
+ * @description Adds decorators to the current context.
463
+ * @summary Internal method to add decorators with addon support.
464
+ * @param {boolean} [addon=false] Indicates whether the decorators are additive extras.
465
+ * @param {...DecoratorData} decorators Decorators to register for the configured key.
466
+ * @return {this} Current instance for chaining.
398
467
  */
399
468
  decorate(addon = false, ...decorators) {
400
469
  if (!this.key)
@@ -412,10 +481,10 @@
412
481
  return this;
413
482
  }
414
483
  /**
415
- * @description Defines the base decorators
416
- * @summary Sets the primary decorators for the current context
417
- * @param decorators Decorators to define
418
- * @return Builder instance for finishing the chain
484
+ * @description Defines the base decorators.
485
+ * @summary Sets the primary decorators for the current context.
486
+ * @param {...DecoratorData} decorators Decorators to define.
487
+ * @return {DecorationBuilderEnd} Builder instance for finishing the chain (also implements DecorationBuilderBuild).
419
488
  */
420
489
  define(...decorators) {
421
490
  if (decorators.find((d) => typeof d === "object") &&
@@ -424,10 +493,10 @@
424
493
  return this.decorate(false, ...decorators);
425
494
  }
426
495
  /**
427
- * @description Extends existing decorators
428
- * @summary Adds additional decorators to the current context
429
- * @param decorators Additional decorators
430
- * @return {DecorationBuilderBuild} Builder instance for building the decorator
496
+ * @description Extends existing decorators.
497
+ * @summary Adds additional decorators to the current context.
498
+ * @param {...DecoratorData} decorators Additional decorators to register as addons.
499
+ * @return {DecorationBuilderBuild} Builder instance for building the decorator.
431
500
  */
432
501
  extend(...decorators) {
433
502
  if (decorators.find((d) => typeof d === "object") &&
@@ -436,12 +505,11 @@
436
505
  return this.decorate(true, ...decorators);
437
506
  }
438
507
  /**
439
- * @description Factory that creates a context-aware decorator for a key/flavour
440
- * @summary Produces a decorator function bound to the provided key and flavour. The resulting decorator resolves the actual
441
- * decorators to apply at invocation time based on the target's resolved flavour and the registered base and extra decorators.
442
- * @param {string} key The decoration key used to look up registered decorators
443
- * @param {string} [f=DefaultFlavour] Optional explicit flavour to bind the factory to
444
- * @return {function(object, any, TypedPropertyDescriptor<any>): any} A decorator function that applies the resolved decorators
508
+ * @description Factory that creates a context-aware decorator for a key/flavour.
509
+ * @summary Produces a decorator function bound to the provided key and flavour. The resulting decorator resolves the actual decorators to apply at invocation time based on the target's resolved flavour and the registered base and extra decorators.
510
+ * @param {string} key Decoration key used to look up registered decorators.
511
+ * @param {string} [f=DefaultFlavour] Explicit flavour to bind the factory to.
512
+ * @return {ClassDecorator|MethodDecorator|PropertyDecorator|ParameterDecorator} Decorator function that applies the resolved decorators.
445
513
  * @mermaid
446
514
  * sequenceDiagram
447
515
  * participant U as User Code
@@ -506,9 +574,9 @@
506
574
  return contextDecorator;
507
575
  }
508
576
  /**
509
- * @description Creates the final decorator function
510
- * @summary Builds and returns the decorator factory function
511
- * @return {function(any, any?, TypedPropertyDescriptor?): any} The generated decorator function
577
+ * @description Creates the final decorator function.
578
+ * @summary Builds and returns the decorator factory function.
579
+ * @return {ClassDecorator|MethodDecorator|PropertyDecorator|ParameterDecorator} Generated decorator function ready for application.
512
580
  */
513
581
  apply() {
514
582
  if (!this.key)
@@ -517,12 +585,13 @@
517
585
  return this.decoratorFactory(this.key, this.flavour);
518
586
  }
519
587
  /**
520
- * @description Registers decorators for a specific key and flavour
521
- * @summary Internal method to store decorators in the static registry
522
- * @param {string} key Decorator key
523
- * @param {string} flavour Decorator flavour
524
- * @param [decorators] Primary decorators
525
- * @param [extras] Additional decorators
588
+ * @description Registers decorators for a specific key and flavour.
589
+ * @summary Internal method to store decorators in the static registry.
590
+ * @param {string} key Decorator key.
591
+ * @param {string} flavour Decorator flavour.
592
+ * @param {Set<DecoratorData>} [decorators] Primary decorators registered for the key.
593
+ * @param {Set<DecoratorData>} [extras] Additional decorators registered as flavour-specific addons.
594
+ * @return {void}
526
595
  */
527
596
  static register(key, flavour, decorators, extras) {
528
597
  if (!key) {
@@ -542,27 +611,28 @@
542
611
  Decoration.decorators[key][flavour].extras = extras;
543
612
  }
544
613
  /**
545
- * @description Sets the global flavour resolver
546
- * @summary Configures the function used to determine decorator flavours
547
- * @param {FlavourResolver} resolver Function to resolve flavours
614
+ * @description Sets the global flavour resolver.
615
+ * @summary Configures the function used to determine decorator flavours.
616
+ * @param {FlavourResolver} resolver Function to resolve flavours.
617
+ * @return {void}
548
618
  */
549
619
  static setFlavourResolver(resolver) {
550
620
  Decoration.flavourResolver = resolver;
551
621
  }
552
622
  /**
553
- * @description Convenience static entry to start a decoration builder
623
+ * @description Convenience static entry to start a decoration builder.
554
624
  * @summary Creates a new Decoration instance and initiates the builder chain with the provided key.
555
- * @param {string} key The decoration key to configure
556
- * @return {DecorationBuilderMid} A builder instance for chaining definitions
625
+ * @param {string} key Decoration key to configure.
626
+ * @return {DecorationBuilderMid} Builder instance for chaining definitions.
557
627
  */
558
628
  static for(key) {
559
629
  return new Decoration().for(key);
560
630
  }
561
631
  /**
562
- * @description Starts a builder for a specific flavour
632
+ * @description Starts a builder for a specific flavour.
563
633
  * @summary Convenience method to begin a Decoration builder chain bound to the given flavour identifier, allowing registration of flavour-specific decorators.
564
- * @param {string} flavour The flavour name to bind to the builder
565
- * @return {DecorationBuilderStart} A builder start interface to continue configuration
634
+ * @param {string} flavour Flavour name to bind to the builder.
635
+ * @return {DecorationBuilderStart} Builder start interface to continue configuration.
566
636
  */
567
637
  static flavouredAs(flavour) {
568
638
  return new Decoration(flavour);
@@ -570,11 +640,11 @@
570
640
  }
571
641
 
572
642
  /**
573
- * @description Assigns arbitrary metadata to a target using a string key
574
- * @summary Decorator factory that stores a key/value pair in the central Metadata store for the provided class or member.
575
- * @param {string} key The metadata key to associate with the target
576
- * @param {*} value The metadata value to store under the given key
577
- * @return A decorator that writes the metadata when applied
643
+ * @description Assigns arbitrary metadata to a target using a string key.
644
+ * @summary Decorator factory that stores a key/value pair in the central metadata store for the provided class or member.
645
+ * @param {string} key Metadata key to associate with the target.
646
+ * @param {any} value Metadata value to store under the given key.
647
+ * @return {ClassDecorator|MethodDecorator|PropertyDecorator|ParameterDecorator} Decorator that writes the metadata when applied.
578
648
  * @function metadata
579
649
  * @category Decorators
580
650
  */
@@ -586,30 +656,93 @@
586
656
  };
587
657
  }
588
658
  /**
589
- * @description Captures and stores a property's design type
590
- * @summary Decorator factory that reads the reflected design:type for a property and registers it in the Metadata store under the properties map.
591
- * @return A decorator that records the property's type metadata when applied
659
+ * @description Captures and stores a property's design type.
660
+ * @summary Decorator factory that reads the reflected `design:type` for a property and registers it in the metadata store under the properties map.
661
+ * @return {PropertyDecorator} Decorator that records the property's type metadata when applied.
592
662
  * @function prop
593
663
  * @category Property Decorators
594
664
  */
595
665
  function prop() {
596
666
  return function prop(model, prop) {
597
667
  const designType = Reflect.getOwnMetadata(exports.DecorationKeys.DESIGN_TYPE, model, prop);
598
- return metadata(`${exports.DecorationKeys.PROPERTIES}.${prop}`, designType)(model, prop);
668
+ return metadata(Metadata.key(exports.DecorationKeys.PROPERTIES, prop), designType)(model, prop);
669
+ };
670
+ }
671
+ /**
672
+ * @description Captures a single parameter type for the decorated method.
673
+ * @summary Decorator factory that ensures the method metadata is initialised and stores the reflected parameter constructor at the provided index.
674
+ * @return {ParameterDecorator} Decorator that records the parameter type when applied.
675
+ * @function param
676
+ * @category Parameter Decorators
677
+ * @mermaid
678
+ * sequenceDiagram
679
+ * participant U as User Code
680
+ * participant P as param()
681
+ * participant M as Metadata
682
+ * U->>P: param()(target, key, index)
683
+ * P->>U: method()(target, key, descriptor)
684
+ * P->>M: params(constructor, key)
685
+ * M-->>P: parameter constructors[]
686
+ * P->>M: set(methods.key.index, constructor)
687
+ * P-->>U: parameter recorded
688
+ */
689
+ function param() {
690
+ return function param(model, prop, index) {
691
+ if (!prop)
692
+ throw new Error(`The @param decorator can only be applied to methods`);
693
+ method()(model, prop, Object.getOwnPropertyDescriptor(model, prop));
694
+ const paramTpes = Metadata.params(model.constructor, prop);
695
+ if (!paramTpes)
696
+ throw new Error(`Missing parameter types for ${String(prop)}`);
697
+ if (index >= paramTpes.length)
698
+ throw new Error(`Parameter index ${index} out of range for ${String(prop)}`);
699
+ metadata(Metadata.key(exports.DecorationKeys.METHODS, prop, index.toString()), paramTpes[index])(model, prop);
599
700
  };
600
701
  }
702
+ /**
703
+ * @description Extends a parameter decorator with additional metadata.
704
+ * @summary Applies the default `param()` decorator and augments the stored metadata with an arbitrary key/value pair.
705
+ * @param {string} key Metadata key to associate with the parameter.
706
+ * @param {any} value Metadata value persisted under the given key.
707
+ * @return {ParameterDecorator} Decorator that records both the parameter design type and additional metadata.
708
+ * @function paramMetadata
709
+ * @category Parameter Decorators
710
+ */
711
+ function paramMetadata(key, value) {
712
+ return function paramMetadata(target, prop, index) {
713
+ return apply(param(), metadata(Metadata.key(exports.DecorationKeys.METHODS, prop, key), value))(target, prop, index);
714
+ };
715
+ }
716
+ /**
717
+ * @description Records method design-time metadata.
718
+ * @summary Decorator factory that captures a method's reflected parameter and return types, storing them under the appropriate metadata keys so they can be inspected at runtime.
719
+ * @return {MethodDecorator} Decorator that persists the method's signature information into the metadata store when applied.
720
+ * @function method
721
+ * @mermaid
722
+ * sequenceDiagram
723
+ * participant U as User Code
724
+ * participant F as method()
725
+ * participant M as Metadata
726
+ * U->>F: method()(target, key, descriptor)
727
+ * F->>U: Reflect.getOwnMetadata(design:paramtypes)
728
+ * F->>U: Reflect.getOwnMetadata(design:returntype)
729
+ * F->>M: set(methods.key.design:paramtypes, params)
730
+ * F->>M: set(methods.key.design:returntype, returnType)
731
+ * F-->>U: decorated function
732
+ * @category Method Decorators
733
+ */
601
734
  function method() {
602
735
  return function method(obj, prop, descriptor) {
603
736
  const designParams = Reflect.getOwnMetadata(exports.DecorationKeys.DESIGN_PARAMS, obj, prop);
604
737
  const designReturn = Reflect.getOwnMetadata(exports.DecorationKeys.DESIGN_RETURN, obj, prop);
605
- return apply(metadata(`${exports.DecorationKeys.METHODS}.${prop}.${exports.DecorationKeys.DESIGN_PARAMS}`, designParams), metadata(`${exports.DecorationKeys.METHODS}.${prop}.${exports.DecorationKeys.DESIGN_RETURN}`, designReturn))(obj, prop, descriptor);
738
+ return apply(metadata(Metadata.key(exports.DecorationKeys.METHODS, prop, exports.DecorationKeys.DESIGN_PARAMS), designParams), metadata(Metadata.key(exports.DecorationKeys.METHODS, prop, exports.DecorationKeys.DESIGN_RETURN), designReturn))(obj, prop, descriptor);
606
739
  };
607
740
  }
608
741
  /**
609
- * @description Decorator factory that applies multiple decorators to a single target
610
- * @summary Creates a composite decorator that applies multiple decorators in sequence, correctly handling class, method, and property decorators.
611
- * @param {Array<ClassDecorator | MethodDecorator | PropertyDecorator>} decorators - Array of decorators to apply
612
- * @return {Function} A decorator function that applies all provided decorators to the target
742
+ * @description Decorator factory that applies multiple decorators to a single target.
743
+ * @summary Creates a composite decorator that applies multiple decorators in sequence, correctly handling class, method, property, and parameter decorators.
744
+ * @param {Array<ClassDecorator|MethodDecorator|PropertyDecorator|ParameterDecorator>} decorators Collection of decorators to apply.
745
+ * @return {ClassDecorator|MethodDecorator|PropertyDecorator|ParameterDecorator} Decorator function that applies all provided decorators to the target.
613
746
  * @function apply
614
747
  * @mermaid
615
748
  * sequenceDiagram
@@ -636,11 +769,11 @@
636
769
  };
637
770
  }
638
771
  /**
639
- * @description Creates a property metadata decorator
640
- * @summary Convenience factory that combines metadata(key, value) and prop() to both set an arbitrary metadata key and record the property's design type.
641
- * @param {string} key The metadata key to set for the property
642
- * @param {*} value The metadata value to associate with the key
643
- * @return A decorator that sets the metadata and captures the property's type
772
+ * @description Creates a property metadata decorator.
773
+ * @summary Convenience factory that combines `metadata(key, value)` and `prop()` to both set an arbitrary metadata key and record the property's design type.
774
+ * @param {string} key Metadata key to set for the property.
775
+ * @param {any} value Metadata value to associate with the key.
776
+ * @return {PropertyDecorator} Decorator that sets the metadata and captures the property's type.
644
777
  * @function propMetadata
645
778
  * @category Property Decorators
646
779
  */
@@ -648,10 +781,22 @@
648
781
  return apply(metadata(key, value), prop());
649
782
  }
650
783
  /**
651
- * @description Attaches a human-readable description to a class or member
652
- * @summary Decorator factory that stores a textual description in the Metadata store under the appropriate description key for a class or its property.
653
- * @param {string} desc The descriptive text to associate with the class or property
654
- * @return A decorator that records the description when applied
784
+ * @description Creates a method metadata decorator.
785
+ * @summary Convenience factory that combines `metadata(key, value)` and `method()` to both set an arbitrary metadata key and record the method's design return and param types.
786
+ * @param {string} key Metadata key to set for the property.
787
+ * @param {any} value Metadata value to associate with the key.
788
+ * @return {PropertyDecorator} Decorator that sets the metadata and captures the property's type.
789
+ * @function methodMetadata
790
+ * @category Method Decorators
791
+ */
792
+ function methodMetadata(key, value) {
793
+ return apply(metadata(key, value), method());
794
+ }
795
+ /**
796
+ * @description Attaches a human-readable description to a class or member.
797
+ * @summary Decorator factory that stores a textual description in the metadata store under the appropriate description key for a class or its property.
798
+ * @param {string} desc Descriptive text to associate with the class or property.
799
+ * @return {ClassDecorator|MethodDecorator|PropertyDecorator} Decorator that records the description when applied.
655
800
  * @function description
656
801
  * @category Decorators
657
802
  */
@@ -660,18 +805,17 @@
660
805
  return metadata([
661
806
  exports.DecorationKeys.DESCRIPTION,
662
807
  prop ? prop.toString() : exports.DecorationKeys.CLASS,
663
- ].join(ObjectKeySplitter), desc)(original, prop, descriptor);
808
+ ].join(Metadata.splitter), desc)(original, prop, descriptor);
664
809
  };
665
810
  }
666
811
 
667
812
  /**
668
- * @description Root entry point for the decoration module
669
- * @summary Aggregates and re-exports the public API of the decoration library, including core classes like {@link Decoration}, utility decorators, metadata helpers, and constants. This module is the primary import surface for consumers and exposes:
813
+ * @description Root entry point for the decoration module.
814
+ * @summary Aggregates and re-exports the public API of the decoration library, including {@link Decoration}, decorator utilities from {@link module:decoration|./decorators}, {@link Metadata}, and shared constants such as {@link DecorationKeys} and {@link DefaultFlavour}. This is the primary import surface for consumers and exposes:
670
815
  * - Core builder: {@link Decoration}
671
- * - Decorator utilities: {@link module:decoration | decorators in ./decorators}
816
+ * - Decorator utilities: {@link module:decoration|decorators in ./decorators}
672
817
  * - Metadata utilities: {@link Metadata}
673
818
  * - Constants and enums: {@link DecorationKeys}, {@link DefaultFlavour}
674
- *
675
819
  * @module decoration
676
820
  */
677
821
  /**
@@ -680,7 +824,7 @@
680
824
  * @const VERSION
681
825
  * @memberOf module:decoration
682
826
  */
683
- const VERSION = "0.0.6";
827
+ const VERSION = "0.0.8";
684
828
  Metadata.registerLibrary("@decaf-ts/decoration", VERSION);
685
829
 
686
830
  exports.Decoration = Decoration;
@@ -694,9 +838,12 @@
694
838
  exports.getValueBySplitter = getValueBySplitter;
695
839
  exports.metadata = metadata;
696
840
  exports.method = method;
841
+ exports.methodMetadata = methodMetadata;
842
+ exports.param = param;
843
+ exports.paramMetadata = paramMetadata;
697
844
  exports.prop = prop;
698
845
  exports.propMetadata = propMetadata;
699
846
  exports.setValueBySplitter = setValueBySplitter;
700
847
 
701
848
  }));
702
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVjb3JhdGlvbi5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb25zdGFudHMudHMiLCIuLi9zcmMvbWV0YWRhdGEvTWV0YWRhdGEudHMiLCIuLi9zcmMvZGVjb3JhdGlvbi9EZWNvcmF0aW9uLnRzIiwiLi4vc3JjL2RlY29yYXRvcnMudHMiLCIuLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQmFzaWNNZXRhZGF0YSB9IGZyb20gXCIuL21ldGFkYXRhL3R5cGVzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmF1bHQgZmxhdm91ciBpZGVudGlmaWVyIGZvciB0aGUgZGVjb3JhdG9yIHN5c3RlbVxuICogQHN1bW1hcnkgRGVmaW5lcyB0aGUgZGVmYXVsdCBmbGF2b3VyIHVzZWQgYnkgdGhlIERlY29yYXRpb24gY2xhc3Mgd2hlbiBubyBzcGVjaWZpYyBmbGF2b3VyIGlzIHByb3ZpZGVkLlxuICogVGhpcyBjb25zdGFudCBpcyB1c2VkIHRocm91Z2hvdXQgdGhlIGxpYnJhcnkgYXMgdGhlIGZhbGxiYWNrIGZsYXZvdXIgZm9yIGRlY29yYXRvcnMuXG4gKiBAY29uc3QgRGVmYXVsdEZsYXZvdXJcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdGlvblxuICovXG5leHBvcnQgY29uc3QgRGVmYXVsdEZsYXZvdXIgPSBcImRlY2FmXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENoYXJhY3RlciB1c2VkIHRvIHNwbGl0IG5lc3RlZCBtZXRhZGF0YSBrZXlzXG4gKiBAc3VtbWFyeSBUaGUgZGVsaW1pdGVyIHVzZWQgYnkgdGhlIG1ldGFkYXRhIHN0b3JlIHRvIHRyYXZlcnNlIG5lc3RlZCBvYmplY3QgcGF0aHMgd2hlbiByZWFkaW5nL3dyaXRpbmcgdmFsdWVzLlxuICogQGNvbnN0IE9iamVjdEtleVNwbGl0dGVyXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuZXhwb3J0IGNvbnN0IE9iamVjdEtleVNwbGl0dGVyID0gXCIuXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVudW0gY29udGFpbmluZyBtZXRhZGF0YSBrZXlzIHVzZWQgZm9yIHJlZmxlY3Rpb24gaW4gdGhlIG1vZGVsIHN5c3RlbVxuICogQHN1bW1hcnkgRGVmaW5lcyB0aGUgdmFyaW91cyBNb2RlbCBrZXlzIHVzZWQgZm9yIHJlZmxlY3Rpb24gYW5kIG1ldGFkYXRhIHN0b3JhZ2UuXG4gKiBUaGVzZSBrZXlzIGFyZSB1c2VkIHRocm91Z2hvdXQgdGhlIGxpYnJhcnkgdG8gc3RvcmUgYW5kIHJldHJpZXZlIG1ldGFkYXRhIGFib3V0IG1vZGVscyxcbiAqIHRoZWlyIHByb3BlcnRpZXMsIGFuZCB0aGVpciBiZWhhdmlvci5cbiAqIEByZWFkb25seVxuICogQGVudW0ge3N0cmluZ31cbiAqIEByZWFkb25seVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCBlbnVtIERlY29yYXRpb25LZXlzIHtcbiAgTElCUkFSSUVTID0gXCJsaWJyYXJpZXNcIixcbiAgLyoqIFN0b3JhZ2Uga2V5IHVzZWQgb24gdGhlIGNvbnN0cnVjdG9yIHRvIG1pcnJvciBydW50aW1lIG1ldGFkYXRhICovXG4gIFJFRkxFQ1QgPSBgX18ke0RlZmF1bHRGbGF2b3VyfWAsXG4gIC8qKiBNYXAgb2YgbW9kZWwgcHJvcGVydHkga2V5cyB0byB0aGVpciByZWZsZWN0ZWQgZGVzaWduIHR5cGVzICovXG4gIFBST1BFUlRJRVMgPSBcInByb3BlcnRpZXNcIixcbiAgLyoqIE1hcCBvZiBtb2RlbCBtZXRob2Qga2V5cyB0byB0aGVpciByZWZsZWN0ZWQgZGVzaWduIHBhcmFtcyBhbmQgcmV0dXJuIHR5cGVzICovXG4gIE1FVEhPRFMgPSBcIm1ldGhvZHNcIixcbiAgLyoqIEtleSB1bmRlciB3aGljaCB0aGUgbW9kZWwncyBjb25zdHJ1Y3RvciBpcyBzdG9yZWQgKi9cbiAgQ0xBU1MgPSBcImNsYXNzXCIsXG4gIC8qKiBDb250YWluZXIgb2YgaHVtYW4tZnJpZW5kbHkgZGVzY3JpcHRpb25zIHBlciBjbGFzcyBhbmQgcHJvcGVydHkgKi9cbiAgREVTQ1JJUFRJT04gPSBcImRlc2NyaXB0aW9uXCIsXG4gIC8qKiBSZWZsZWN0IG1ldGFkYXRhIGtleSBmb3IgZGVzaWduIHRpbWUgdHlwZSBvZiBhIHByb3BlcnR5ICovXG4gIERFU0lHTl9UWVBFID0gXCJkZXNpZ246dHlwZVwiLFxuICAvKiogUmVmbGVjdCBtZXRhZGF0YSBrZXkgZm9yIGNvbnN0cnVjdG9yIHBhcmFtZXRlciB0eXBlcyAqL1xuICBERVNJR05fUEFSQU1TID0gXCJkZXNpZ246cGFyYW10eXBlc1wiLFxuICAvKiogUmVmbGVjdCBtZXRhZGF0YSBrZXkgZm9yIG1ldGhvZCByZXR1cm4gdHlwZSAqL1xuICBERVNJR05fUkVUVVJOID0gXCJkZXNpZ246cmV0dXJudHlwZVwiLFxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBUeXBlZGVmIGZvciB0aGUgZGVmYXVsdCBtZXRhZGF0YSBvYmplY3Qgc2hhcGVcbiAqIEBzdW1tYXJ5IERlc2NyaWJlcyB0aGUgbWluaW1hbCBzdHJ1Y3R1cmUgcGVyc2lzdGVkIGZvciBhIG1vZGVsIGJlZm9yZSBhbnkgbWV0YWRhdGEgaXMgcmVjb3JkZWQuXG4gKiBAdGVtcGxhdGUgTVxuICogQHR5cGVkZWYge29iamVjdH0gRGVmYXVsdE1ldGFkYXRhVHlwZTxNPlxuICogQHByb3BlcnR5IHtSZWNvcmQ8c3RyaW5nLCBDb25zdHJ1Y3RvciB8IHVuZGVmaW5lZD59IHByb3BlcnRpZXMgLSBNYXBwaW5nIG9mIHByb3BlcnR5IG5hbWVzIHRvIHRoZWlyIGRlc2lnbiB0eXBlc1xuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVmYXVsdCBtZXRhZGF0YSBpbnN0YW5jZVxuICogQHN1bW1hcnkgQ29uY3JldGUgZGVmYXVsdCBtZXRhZGF0YSBvYmplY3QgdXNlZCB3aGVuIGluaXRpYWxpemluZyBtZXRhZGF0YSBmb3IgYSBtb2RlbFxuICogQHR5cGUge0RlZmF1bHRNZXRhZGF0YVR5cGU8YW55Pn1cbiAqIEBjb25zdCBEZWZhdWx0TWV0YWRhdGFcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdGlvblxuICovXG5leHBvcnQgY29uc3QgRGVmYXVsdE1ldGFkYXRhOiBCYXNpY01ldGFkYXRhPGFueT4gPSB7XG4gIFtEZWNvcmF0aW9uS2V5cy5QUk9QRVJUSUVTXTogW10sXG59IGFzIHVua25vd24gYXMgQmFzaWNNZXRhZGF0YTxhbnk+O1xuIiwiaW1wb3J0IHsgQmFzaWNNZXRhZGF0YSwgQ29uc3RydWN0b3IgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgRGVjb3JhdGlvbktleXMsIE9iamVjdEtleVNwbGl0dGVyIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuaW1wb3J0IFwicmVmbGVjdC1tZXRhZGF0YVwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYSBuZXN0ZWQgdmFsdWUgZnJvbSBhbiBvYmplY3QgZ2l2ZW4gYSBwYXRoXG4gKiBAc3VtbWFyeSBXYWxrcyBhbiBvYmplY3Qgc3RydWN0dXJlIHVzaW5nIGEgc3BsaXR0ZXItZGVsaW1pdGVkIHBhdGggYW5kIHJldHVybnMgdGhlIHZhbHVlIGF0IHRoYXQgbG9jYXRpb24gb3IgdW5kZWZpbmVkIGlmIGFueSBrZXkgaXMgbWlzc2luZy5cbiAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gb2JqIFRoZSBvYmplY3QgdG8gdHJhdmVyc2VcbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIFRoZSBwYXRoIHRvIHRoZSBkZXNpcmVkIHZhbHVlIChlLmcuLCBcImEuYi5jXCIpXG4gKiBAcGFyYW0ge3N0cmluZ30gW3NwbGl0dGVyPU9iamVjdEtleVNwbGl0dGVyXSBUaGUgZGVsaW1pdGVyIHVzZWQgdG8gc3BsaXQgdGhlIHBhdGhcbiAqIEByZXR1cm4geyp9IFRoZSByZXNvbHZlZCB2YWx1ZSBhdCB0aGUgZ2l2ZW4gcGF0aCBvciB1bmRlZmluZWQgaWYgbm90IGZvdW5kXG4gKiBAZnVuY3Rpb24gZ2V0VmFsdWVCeVNwbGl0dGVyXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEMgYXMgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IEYgYXMgZ2V0VmFsdWVCeVNwbGl0dGVyXG4gKiAgIHBhcnRpY2lwYW50IE8gYXMgT2JqZWN0XG4gKiAgIEMtPj5GOiAob2JqLCBwYXRoLCBzcGxpdHRlcilcbiAqICAgRi0+PkY6IHNwbGl0IHBhdGggaW50byBrZXlzXG4gKiAgIGxvb3AgZm9yIGVhY2gga2V5XG4gKiAgICAgRi0+Pk86IGFjY2VzcyBjdXJyZW50W2tleV1cbiAqICAgICBhbHQgbWlzc2luZyBvciBudWxsaXNoXG4gKiAgICAgICBGLS0+PkM6IHJldHVybiB1bmRlZmluZWRcbiAqICAgICBlbmRcbiAqICAgZW5kXG4gKiAgIEYtLT4+QzogcmV0dXJuIGZpbmFsIHZhbHVlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFZhbHVlQnlTcGxpdHRlcihcbiAgb2JqOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICBwYXRoOiBzdHJpbmcsXG4gIHNwbGl0dGVyOiBzdHJpbmcgPSBPYmplY3RLZXlTcGxpdHRlclxuKTogYW55IHtcbiAgY29uc3Qga2V5cyA9IHBhdGguc3BsaXQoc3BsaXR0ZXIpO1xuICBsZXQgY3VycmVudCA9IG9iajtcblxuICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgaWYgKFxuICAgICAgY3VycmVudCA9PT0gbnVsbCB8fFxuICAgICAgY3VycmVudCA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGN1cnJlbnQsIGtleSlcbiAgICApXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGN1cnJlbnQgPSBjdXJyZW50W2tleV07XG4gIH1cblxuICByZXR1cm4gY3VycmVudDtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU2V0cyBhIG5lc3RlZCB2YWx1ZSBvbiBhbiBvYmplY3QgZ2l2ZW4gYSBwYXRoXG4gKiBAc3VtbWFyeSBUcmF2ZXJzZXMgb3IgY3JlYXRlcyBpbnRlcm1lZGlhdGUgb2JqZWN0cyBmb2xsb3dpbmcgYSBzcGxpdHRlci1kZWxpbWl0ZWQgcGF0aCBhbmQgYXNzaWducyB0aGUgcHJvdmlkZWQgdmFsdWUgYXQgdGhlIGRlc3RpbmF0aW9uIGtleS5cbiAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gb2JqIFRoZSBvYmplY3QgdG8gbXV0YXRlXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCBUaGUgZGVzdGluYXRpb24gcGF0aCAoZS5nLiwgXCJhLmIuY1wiKVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0IGF0IHRoZSBkZXN0aW5hdGlvblxuICogQHBhcmFtIHtzdHJpbmd9IFtzcGxpdHRlcj1PYmplY3RLZXlTcGxpdHRlcl0gVGhlIGRlbGltaXRlciB1c2VkIHRvIHNwbGl0IHRoZSBwYXRoXG4gKiBAcmV0dXJuIHt2b2lkfVxuICogQGZ1bmN0aW9uIHNldFZhbHVlQnlTcGxpdHRlclxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDIGFzIENhbGxlclxuICogICBwYXJ0aWNpcGFudCBGIGFzIHNldFZhbHVlQnlTcGxpdHRlclxuICogICBwYXJ0aWNpcGFudCBPIGFzIE9iamVjdFxuICogICBDLT4+RjogKG9iaiwgcGF0aCwgdmFsdWUsIHNwbGl0dGVyKVxuICogICBGLT4+Rjogc3BsaXQgcGF0aCBpbnRvIGtleXNcbiAqICAgbG9vcCBmb3IgZWFjaCBrZXlcbiAqICAgICBhbHQga2V5IG1pc3NpbmdcbiAqICAgICAgIEYtPj5POiBjcmVhdGUgaW50ZXJtZWRpYXRlIG9iamVjdFxuICogICAgIGVsc2Uga2V5IGV4aXN0c1xuICogICAgICAgRi0+Pk86IGRlc2NlbmQgaW50byBleGlzdGluZyBvYmplY3RcbiAqICAgICBlbmRcbiAqICAgZW5kXG4gKiAgIEYtLT4+Qzogdm9pZFxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRWYWx1ZUJ5U3BsaXR0ZXIoXG4gIG9iajogUmVjb3JkPHN0cmluZywgYW55PixcbiAgcGF0aDogc3RyaW5nLFxuICB2YWx1ZTogYW55LFxuICBzcGxpdHRlciA9IE9iamVjdEtleVNwbGl0dGVyXG4pOiB2b2lkIHtcbiAgY29uc3Qga2V5cyA9IHBhdGguc3BsaXQoc3BsaXR0ZXIpLmZpbHRlcigoaykgPT4gay5sZW5ndGggPiAwKTtcbiAgaWYgKGtleXMubGVuZ3RoID09PSAwKSByZXR1cm47XG5cbiAgbGV0IGN1cnJlbnQ6IFJlY29yZDxhbnksIGFueT4gPSBvYmo7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgIGNvbnN0IGtleSA9IGtleXNbaV07XG4gICAgaWYgKFxuICAgICAgY3VycmVudFtrZXldID09PSB1bmRlZmluZWQgfHxcbiAgICAgIGN1cnJlbnRba2V5XSA9PT0gbnVsbCB8fFxuICAgICAgdHlwZW9mIGN1cnJlbnRba2V5XSAhPT0gXCJvYmplY3RcIlxuICAgICkge1xuICAgICAgY3VycmVudFtrZXldID0ge307XG4gICAgfVxuICAgIGN1cnJlbnQgPSBjdXJyZW50W2tleV07XG4gIH1cblxuICBjb25zdCBsYXN0S2V5ID0ga2V5c1trZXlzLmxlbmd0aCAtIDFdO1xuICBjdXJyZW50W2xhc3RLZXldID0gdmFsdWU7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENlbnRyYWxpemVkIHJ1bnRpbWUgbWV0YWRhdGEgc3RvcmUgYm91bmQgdG8gY29uc3RydWN0b3JzXG4gKiBAc3VtbWFyeSBQcm92aWRlcyB1dGlsaXRpZXMgdG8gcmVhZCBhbmQgd3JpdGUgc3RydWN0dXJlZCBtZXRhZGF0YSBmb3IgY2xhc3NlcyBhbmQgdGhlaXIgbWVtYmVycywgd2l0aCBvcHRpb25hbCBtaXJyb3Jpbmcgb250byB0aGUgY29uc3RydWN0b3IgdmlhIGEgd2VsbC1rbm93biBzeW1ib2wga2V5LiBTdXBwb3J0cyBuZXN0ZWQga2V5IHBhdGhzIHVzaW5nIGEgY29uZmlndXJhYmxlIHNwbGl0dGVyIGFuZCBvZmZlcnMgYm90aCBpbnN0YW5jZSBhbmQgc3RhdGljIEFQSXMuXG4gKiBAdGVtcGxhdGUgTSBUaGUgbW9kZWwgdHlwZSB0aGUgbWV0YWRhdGEgYmVsb25ncyB0b1xuICogQHRlbXBsYXRlIE1FVEEgRXh0ZW5kcyBCYXNpY01ldGFkYXRhPE0+IHJlcHJlc2VudGluZyB0aGUgbWV0YWRhdGEgc3RydWN0dXJlXG4gKiBAY2xhc3NcbiAqIEBleGFtcGxlXG4gKiAvLyBEZWZpbmUgYW5kIHJlYWQgbWV0YWRhdGEgZm9yIGEgY2xhc3NcbiAqIGNsYXNzIFVzZXIgeyBuYW1lITogc3RyaW5nIH1cbiAqIE1ldGFkYXRhLnNldChVc2VyLCBcImRlc2NyaXB0aW9uLmNsYXNzXCIsIFwiQSB1c2VyIG1vZGVsXCIpO1xuICogTWV0YWRhdGEuc2V0KFVzZXIsIFwicHJvcGVydGllcy5uYW1lXCIsIFN0cmluZyk7XG4gKiBjb25zdCBkZXNjID0gTWV0YWRhdGEuZ2V0KFVzZXIsIFwiZGVzY3JpcHRpb24uY2xhc3NcIik7IC8vIFwiQSB1c2VyIG1vZGVsXCJcbiAqIGNvbnN0IHR5cGUgPSBNZXRhZGF0YS50eXBlKFVzZXIsIFwibmFtZVwiKTsgLy8gU3RyaW5nXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEMgYXMgQ29uc3RydWN0b3JcbiAqICAgcGFydGljaXBhbnQgUyBhcyBNZXRhZGF0YSAoc3RhdGljKVxuICogICBDLT4+Uzogc2V0KFVzZXIsIFwicHJvcGVydGllcy5uYW1lXCIsIFN0cmluZylcbiAqICAgQy0+PlM6IGdldChVc2VyLCBcInByb3BlcnRpZXMubmFtZVwiKVxuICogICBTLS0+PkM6IFN0cmluZ1xuICovXG5leHBvcnQgY2xhc3MgTWV0YWRhdGEge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEluLW1lbW9yeSBzdG9yYWdlIG9mIG1ldGFkYXRhIGJ5IGNvbnN0cnVjdG9yIHN5bWJvbFxuICAgKiBAc3VtbWFyeSBNYXBzIGEgU3ltYm9sIGRlcml2ZWQgZnJvbSB0aGUgY29uc3RydWN0b3IgdG8gaXRzIG1ldGFkYXRhIG9iamVjdCwgZW5hYmxpbmcgZWZmaWNpZW50IGxvb2t1cC5cbiAgICovXG4gIHByaXZhdGUgc3RhdGljIF9tZXRhZGF0YTogUmVjb3JkPHN5bWJvbCwgYW55PiA9IHt9O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUGF0aCBkZWxpbWl0ZXIgZm9yIG5lc3RlZCBtZXRhZGF0YSBrZXlzXG4gICAqIEBzdW1tYXJ5IFVzZWQgYnkgZ2V0L3NldCBvcGVyYXRpb25zIHRvIG5hdmlnYXRlIG5lc3RlZCBzdHJ1Y3R1cmVzLCBkZWZhdWx0cyB0byBPYmplY3RLZXlTcGxpdHRlci5cbiAgICovXG4gIHN0YXRpYyBzcGxpdHRlciA9IE9iamVjdEtleVNwbGl0dGVyO1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFN5bWJvbCBrZXkgdXNlZCB0byBtaXJyb3IgbWV0YWRhdGEgb24gdGhlIGNvbnN0cnVjdG9yXG4gICAqIEBzdW1tYXJ5IFdoZW4gbWlycm9yaW5nIGlzIGVuYWJsZWQsIHRoZSBtZXRhZGF0YSBvYmplY3QgaXMgZGVmaW5lZCBvbiB0aGUgY29uc3RydWN0b3IgdW5kZXIgdGhpcyBub24tZW51bWVyYWJsZSBrZXkuXG4gICAqL1xuICBzdGF0aWMgYmFzZUtleSA9IERlY29yYXRpb25LZXlzLlJFRkxFQ1Q7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29udHJvbHMgd2hldGhlciBtZXRhZGF0YSBpcyBtaXJyb3JlZCBvbnRvIHRoZSBjb25zdHJ1Y3RvclxuICAgKiBAc3VtbWFyeSBXaGVuIHRydWUsIHRoZSBtZXRhZGF0YSBvYmplY3QgaXMgZGVmaW5lZCBvbiB0aGUgY29uc3RydWN0b3IgdW5kZXIgdGhlIG5vbi1lbnVtZXJhYmxlIGJhc2VLZXkuXG4gICAqL1xuICBzdGF0aWMgbWlycm9yOiBib29sZWFuID0gdHJ1ZTtcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKCkge31cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExpc3RzIGtub3duIHByb3BlcnR5IGtleXMgZm9yIGEgbW9kZWxcbiAgICogQHN1bW1hcnkgUmVhZHMgdGhlIG1ldGFkYXRhIGVudHJ5IGFuZCByZXR1cm5zIHRoZSBuYW1lcyBvZiBwcm9wZXJ0aWVzIHRoYXQgaGF2ZSByZWNvcmRlZCB0eXBlIGluZm9ybWF0aW9uLlxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yfSBtb2RlbCBUaGUgdGFyZ2V0IGNvbnN0cnVjdG9yXG4gICAqIEByZXR1cm4ge3N0cmluZ1tdfHVuZGVmaW5lZH0gQXJyYXkgb2YgcHJvcGVydHkgbmFtZXMgb3IgdW5kZWZpbmVkIGlmIG5vIG1ldGFkYXRhIGV4aXN0c1xuICAgKi9cbiAgc3RhdGljIHByb3BlcnRpZXMobW9kZWw6IENvbnN0cnVjdG9yKTogc3RyaW5nW10gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IG1ldGEgPSB0aGlzLmdldChtb2RlbCk7XG4gICAgaWYgKCFtZXRhKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiBPYmplY3Qua2V5cyhtZXRhLnByb3BlcnRpZXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMaXN0cyBrbm93biBtZXRob2RzIGZvciBhIG1vZGVsXG4gICAqIEBzdW1tYXJ5IFJlYWRzIHRoZSBtZXRhZGF0YSBlbnRyeSBhbmQgcmV0dXJucyB0aGUgbmFtZXMgb2YgbW9kZWxzIHRoYXQgaGF2ZSByZWNvcmRlZCB0eXBlIGluZm9ybWF0aW9uLlxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yfSBtb2RlbCBUaGUgdGFyZ2V0IGNvbnN0cnVjdG9yXG4gICAqIEByZXR1cm4ge3N0cmluZ1tdfHVuZGVmaW5lZH0gQXJyYXkgb2YgcHJvcGVydHkgbmFtZXMgb3IgdW5kZWZpbmVkIGlmIG5vIG1ldGFkYXRhIGV4aXN0c1xuICAgKi9cbiAgc3RhdGljIG1ldGhvZHMobW9kZWw6IENvbnN0cnVjdG9yKTogc3RyaW5nW10gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IG1ldGEgPSB0aGlzLmdldChtb2RlbCwgRGVjb3JhdGlvbktleXMuTUVUSE9EUyk7XG4gICAgaWYgKCFtZXRhKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiBPYmplY3Qua2V5cyhtZXRhKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGEgaHVtYW4tcmVhZGFibGUgZGVzY3JpcHRpb24gZm9yIGEgY2xhc3Mgb3IgYSBwcm9wZXJ0eVxuICAgKiBAc3VtbWFyeSBMb29rcyB1cCB0aGUgZGVzY3JpcHRpb24gc3RvcmVkIHVuZGVyIHRoZSBtZXRhZGF0YSBcImRlc2NyaXB0aW9uXCIgbWFwLiBJZiBhIHByb3BlcnR5IGtleSBpcyBwcm92aWRlZCwgcmV0dXJucyB0aGUgcHJvcGVydHkncyBkZXNjcmlwdGlvbjsgb3RoZXJ3aXNlIHJldHVybnMgdGhlIGNsYXNzIGRlc2NyaXB0aW9uLlxuICAgKiBAdGVtcGxhdGUgTVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCBUaGUgdGFyZ2V0IGNvbnN0cnVjdG9yIHdob3NlIGRlc2NyaXB0aW9uIGlzIGJlaW5nIHJldHJpZXZlZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3Byb3BdIE9wdGlvbmFsIHByb3BlcnR5IGtleSBmb3Igd2hpY2ggdG8gZmV0Y2ggdGhlIGRlc2NyaXB0aW9uXG4gICAqIEByZXR1cm4ge3N0cmluZ3x1bmRlZmluZWR9IFRoZSBkZXNjcmlwdGlvbiB0ZXh0IGlmIHByZXNlbnQsIG90aGVyd2lzZSB1bmRlZmluZWRcbiAgICovXG4gIHN0YXRpYyBkZXNjcmlwdGlvbjxNPihcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8TT4sXG4gICAgcHJvcD86IGtleW9mIE1cbiAgKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5nZXQoXG4gICAgICBtb2RlbCxcbiAgICAgIFtEZWNvcmF0aW9uS2V5cy5ERVNDUklQVElPTiwgcHJvcCA/IHByb3AgOiBEZWNvcmF0aW9uS2V5cy5DTEFTU10uam9pbihcbiAgICAgICAgdGhpcy5zcGxpdHRlclxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyB0aGUgcmVjb3JkZWQgcGFyYW1zIGZvciBhIG1ldGhvZFxuICAgKiBAc3VtbWFyeSBSZWFkcyB0aGUgbWV0YWRhdGEgZW50cnkgdW5kZXIgXCJtZXRob2RzLjxwcm9wPi5kZXNpZ246cGFyYW1zXCIgdG8gcmV0dXJuIHRoZSBhcmd1bWVudHMgZm9yIHRoZSBpdmVuIG1ldGhvZC5cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3Rvcn0gbW9kZWwgVGhlIHRhcmdldCBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcCBUaGUgbWV0aG9kIG5hbWVcbiAgICogQHJldHVybiB7YW55W10gfCB1bmRlZmluZWR9IFRoZSBhcmd1bWVudCB0eXBlcyBvZiB0aGUgbWV0aG9kIG9yIHVuZGVmaW5lZCBpZiBub3QgYXZhaWxhYmxlXG4gICAqL1xuICBzdGF0aWMgcGFyYW1zPE0+KG1vZGVsOiBDb25zdHJ1Y3RvcjxNPiwgcHJvcDogc3RyaW5nKTogYW55W10gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLmdldChcbiAgICAgIG1vZGVsLFxuICAgICAgW0RlY29yYXRpb25LZXlzLk1FVEhPRFMsIHByb3AsIERlY29yYXRpb25LZXlzLkRFU0lHTl9QQVJBTVNdLmpvaW4oXG4gICAgICAgIHRoaXMuc3BsaXR0ZXJcbiAgICAgIClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgdGhlIHJlY29yZGVkIHJldHVybiB0eXBlIGZvciBhIG1ldGhvZFxuICAgKiBAc3VtbWFyeSBSZWFkcyB0aGUgbWV0YWRhdGEgZW50cnkgdW5kZXIgXCJtZXRob2RzLjxwcm9wPi5kZXNpZ246cmV0dXJuXCIgdG8gcmV0dXJuIHRoZSByZXR1cm4gdHlwZSBmb3IgdGhlIGdpdmVuIG1ldGhvZC5cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3Rvcn0gbW9kZWwgVGhlIHRhcmdldCBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcCBUaGUgbWV0aG9kIG5hbWVcbiAgICogQHJldHVybiB7YW55fHVuZGVmaW5lZH0gVGhlIHJldHVybiB0eXBlIG9mIHRoZSBtZXRob2Qgb3IgdW5kZWZpbmVkIGlmIG5vdCBhdmFpbGFibGVcbiAgICovXG4gIHN0YXRpYyByZXR1cm48TT4obW9kZWw6IENvbnN0cnVjdG9yPE0+LCBwcm9wOiBzdHJpbmcpOiBhbnkgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLmdldChcbiAgICAgIG1vZGVsLFxuICAgICAgW0RlY29yYXRpb25LZXlzLk1FVEhPRFMsIHByb3AsIERlY29yYXRpb25LZXlzLkRFU0lHTl9SRVRVUk5dLmpvaW4oXG4gICAgICAgIHRoaXMuc3BsaXR0ZXJcbiAgICAgIClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgdGhlIHJlY29yZGVkIGRlc2lnbiB0eXBlIGZvciBhIHByb3BlcnR5XG4gICAqIEBzdW1tYXJ5IFJlYWRzIHRoZSBtZXRhZGF0YSBlbnRyeSB1bmRlciBcInByb3BlcnRpZXMuPHByb3A+XCIgdG8gcmV0dXJuIHRoZSBjb25zdHJ1Y3RvciByZWNvcmRlZCBmb3IgdGhlIGdpdmVuIHByb3BlcnR5IG5hbWUuXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3J9IG1vZGVsIFRoZSB0YXJnZXQgY29uc3RydWN0b3JcbiAgICogQHBhcmFtIHtzdHJpbmd9IHByb3AgVGhlIHByb3BlcnR5IG5hbWUgd2hvc2UgdHlwZSBzaG91bGQgYmUgcmV0dXJuZWRcbiAgICogQHJldHVybiB7Q29uc3RydWN0b3J8dW5kZWZpbmVkfSBUaGUgY29uc3RydWN0b3IgcmVmZXJlbmNlIG9mIHRoZSBwcm9wZXJ0eSB0eXBlIG9yIHVuZGVmaW5lZCBpZiBub3QgYXZhaWxhYmxlXG4gICAqL1xuICBzdGF0aWMgdHlwZShtb2RlbDogQ29uc3RydWN0b3IsIHByb3A6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmdldChcbiAgICAgIG1vZGVsLFxuICAgICAgW0RlY29yYXRpb25LZXlzLlBST1BFUlRJRVMsIHByb3BdLmpvaW4odGhpcy5zcGxpdHRlcilcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgbWV0YWRhdGEgZm9yIGEgbW9kZWwgb3IgYSBzcGVjaWZpYyBrZXkgd2l0aGluIGl0XG4gICAqIEBzdW1tYXJ5IFdoZW4gY2FsbGVkIHdpdGggYSBjb25zdHJ1Y3RvciBvbmx5LCByZXR1cm5zIHRoZSBlbnRpcmUgbWV0YWRhdGEgb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGUgbW9kZWwuIFdoZW4gYSBrZXkgcGF0aCBpcyBwcm92aWRlZCwgcmV0dXJucyB0aGUgdmFsdWUgc3RvcmVkIGF0IHRoYXQgbmVzdGVkIGtleS5cbiAgICogQHRlbXBsYXRlIE1cbiAgICogQHRlbXBsYXRlIE1FVEFcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgVGhlIHRhcmdldCBjb25zdHJ1Y3RvciB1c2VkIHRvIGxvY2F0ZSB0aGUgbWV0YWRhdGEgcmVjb3JkXG4gICAqIEByZXR1cm4ge01FVEF8dW5kZWZpbmVkfSBUaGUgbWV0YWRhdGEgb2JqZWN0LCB0aGUgdmFsdWUgYXQgdGhlIGtleSBwYXRoLCBvciB1bmRlZmluZWQgaWYgbm90aGluZyBleGlzdHNcbiAgICovXG4gIHN0YXRpYyBnZXQ8TSwgTUVUQSBleHRlbmRzIEJhc2ljTWV0YWRhdGE8TT4gPSBCYXNpY01ldGFkYXRhPE0+PihcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8TT5cbiAgKTogTUVUQSB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgbWV0YWRhdGEgZm9yIGEgbW9kZWwgb3IgYSBzcGVjaWZpYyBrZXkgd2l0aGluIGl0XG4gICAqIEBzdW1tYXJ5IFdoZW4gY2FsbGVkIHdpdGggYSBjb25zdHJ1Y3RvciBvbmx5LCByZXR1cm5zIHRoZSBlbnRpcmUgbWV0YWRhdGEgb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGUgbW9kZWwuIFdoZW4gYSBrZXkgcGF0aCBpcyBwcm92aWRlZCwgcmV0dXJucyB0aGUgdmFsdWUgc3RvcmVkIGF0IHRoYXQgbmVzdGVkIGtleS5cbiAgICogQHRlbXBsYXRlIE1cbiAgICogQHRlbXBsYXRlIE1FVEFcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgVGhlIHRhcmdldCBjb25zdHJ1Y3RvciB1c2VkIHRvIGxvY2F0ZSB0aGUgbWV0YWRhdGEgcmVjb3JkXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgbmVzdGVkIGtleSBwYXRoIHRvIGZldGNoIGEgc3BlY2lmaWMgdmFsdWVcbiAgICogQHJldHVybiB7TUVUQXwqfHVuZGVmaW5lZH0gVGhlIG1ldGFkYXRhIG9iamVjdCwgdGhlIHZhbHVlIGF0IHRoZSBrZXkgcGF0aCwgb3IgdW5kZWZpbmVkIGlmIG5vdGhpbmcgZXhpc3RzXG4gICAqL1xuICBzdGF0aWMgZ2V0KG1vZGVsOiBDb25zdHJ1Y3Rvciwga2V5OiBzdHJpbmcpOiBhbnk7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIG1ldGFkYXRhIGZvciBhIG1vZGVsIG9yIGEgc3BlY2lmaWMga2V5IHdpdGhpbiBpdFxuICAgKiBAc3VtbWFyeSBXaGVuIGNhbGxlZCB3aXRoIGEgY29uc3RydWN0b3Igb25seSwgcmV0dXJucyB0aGUgZW50aXJlIG1ldGFkYXRhIG9iamVjdCBhc3NvY2lhdGVkIHdpdGggdGhlIG1vZGVsLiBXaGVuIGEga2V5IHBhdGggaXMgcHJvdmlkZWQsIHJldHVybnMgdGhlIHZhbHVlIHN0b3JlZCBhdCB0aGF0IG5lc3RlZCBrZXkuXG4gICAqIEB0ZW1wbGF0ZSBNXG4gICAqIEB0ZW1wbGF0ZSBNRVRBXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT4gfCBzdHJpbmd9IG1vZGVsIFRoZSB0YXJnZXQgY29uc3RydWN0b3IgdXNlZCB0byBsb2NhdGUgdGhlIG1ldGFkYXRhIHJlY29yZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2tleV0gT3B0aW9uYWwgbmVzdGVkIGtleSBwYXRoIHRvIGZldGNoIGEgc3BlY2lmaWMgdmFsdWVcbiAgICogQHJldHVybiB7TUVUQXwqfHVuZGVmaW5lZH0gVGhlIG1ldGFkYXRhIG9iamVjdCwgdGhlIHZhbHVlIGF0IHRoZSBrZXkgcGF0aCwgb3IgdW5kZWZpbmVkIGlmIG5vdGhpbmcgZXhpc3RzXG4gICAqL1xuICBzdGF0aWMgZ2V0KG1vZGVsOiBDb25zdHJ1Y3Rvciwga2V5Pzogc3RyaW5nKSB7XG4gICAgY29uc3Qgc3ltYm9sID0gU3ltYm9sLmZvcihtb2RlbC50b1N0cmluZygpKTtcbiAgICByZXR1cm4gdGhpcy5pbm5lckdldChzeW1ib2wsIGtleSk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBpbm5lckdldChzeW1ib2w6IHN5bWJvbCwga2V5Pzogc3RyaW5nKSB7XG4gICAgaWYgKCF0aGlzLl9tZXRhZGF0YVtzeW1ib2xdKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmICgha2V5KSByZXR1cm4gdGhpcy5fbWV0YWRhdGFbc3ltYm9sXTtcbiAgICByZXR1cm4gZ2V0VmFsdWVCeVNwbGl0dGVyKHRoaXMuX21ldGFkYXRhW3N5bWJvbF0sIGtleSwgdGhpcy5zcGxpdHRlcik7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBpbm5lclNldChzeW1ib2w6IHN5bWJvbCwga2V5OiBzdHJpbmcsIHZhbHVlOiBhbnkpIHtcbiAgICBpZiAoIXRoaXMuX21ldGFkYXRhW3N5bWJvbF0pIHRoaXMuX21ldGFkYXRhW3N5bWJvbF0gPSB7fSBhcyBhbnk7XG4gICAgc2V0VmFsdWVCeVNwbGl0dGVyKHRoaXMuX21ldGFkYXRhW3N5bWJvbF0sIGtleSwgdmFsdWUsIHRoaXMuc3BsaXR0ZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBXcml0ZXMgYSBtZXRhZGF0YSB2YWx1ZSBhdCBhIGdpdmVuIG5lc3RlZCBrZXkgcGF0aFxuICAgKiBAc3VtbWFyeSBFbnN1cmVzIHRoZSBtZXRhZGF0YSByZWNvcmQgZXhpc3RzIGZvciB0aGUgY29uc3RydWN0b3IsIG1pcnJvcnMgaXQgb24gdGhlIGNvbnN0cnVjdG9yIHdoZW4gZW5hYmxlZCwgYW5kIHNldHMgdGhlIHByb3ZpZGVkIHZhbHVlIG9uIHRoZSBuZXN0ZWQga2V5IHBhdGggdXNpbmcgdGhlIGNvbmZpZ3VyZWQgc3BsaXR0ZXIuXG4gICAqIEB0ZW1wbGF0ZSBNXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT4gfCBzdHJpbmd9IG1vZGVsIFRoZSB0YXJnZXQgY29uc3RydWN0b3IgdG8gd2hpY2ggdGhlIG1ldGFkYXRhIGJlbG9uZ3NcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUgbmVzdGVkIGtleSBwYXRoIGF0IHdoaWNoIHRvIHN0b3JlIHRoZSB2YWx1ZVxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzdG9yZSBpbiB0aGUgbWV0YWRhdGFcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIHN0YXRpYyBzZXQobW9kZWw6IENvbnN0cnVjdG9yIHwgc3RyaW5nLCBrZXk6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgIGNvbnN0IHN5bWJvbCA9IFN5bWJvbC5mb3IobW9kZWwudG9TdHJpbmcoKSk7XG4gICAgdGhpcy5pbm5lclNldChzeW1ib2wsIGtleSwgdmFsdWUpO1xuICAgIGlmIChcbiAgICAgIE1ldGFkYXRhLm1pcnJvciAmJlxuICAgICAgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb2RlbCwgdGhpcy5iYXNlS2V5KVxuICAgICkge1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG1vZGVsLCB0aGlzLmJhc2VLZXksIHtcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgICAgdmFsdWU6IHRoaXMuX21ldGFkYXRhW3N5bWJvbF0sXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgcmVnaXN0ZXJMaWJyYXJ5KGxpYnJhcnk6IHN0cmluZywgdmVyc2lvbjogc3RyaW5nKSB7XG4gICAgY29uc3Qgc3ltYm9sID0gU3ltYm9sLmZvcihEZWNvcmF0aW9uS2V5cy5MSUJSQVJJRVMpO1xuICAgIGNvbnN0IGxpYiA9IHRoaXMuaW5uZXJHZXQoc3ltYm9sLCBsaWJyYXJ5KTtcbiAgICBpZiAobGliKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgTGlicmFyeSBhbHJlYWR5ICR7bGlicmFyeX0gcmVnaXN0ZXJlZCB3aXRoIHZlcnNpb24gJHt2ZXJzaW9ufWBcbiAgICAgICk7XG4gICAgdGhpcy5pbm5lclNldChzeW1ib2wsIGxpYnJhcnksIHZlcnNpb24pO1xuICB9XG59XG4iLCJpbXBvcnQge1xuICBEZWNvcmF0aW9uQnVpbGRlckJ1aWxkLFxuICBEZWNvcmF0aW9uQnVpbGRlckVuZCxcbiAgRGVjb3JhdGlvbkJ1aWxkZXJNaWQsXG4gIERlY29yYXRpb25CdWlsZGVyU3RhcnQsXG4gIEZsYXZvdXJSZXNvbHZlcixcbiAgSURlY29yYXRpb25CdWlsZGVyLFxufSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgRGVmYXVsdEZsYXZvdXIgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmF1bHQgcmVzb2x2ZXIgdGhhdCByZXR1cm5zIHRoZSBjdXJyZW50IGRlZmF1bHQgZmxhdm91clxuICogQHN1bW1hcnkgUmVzb2x2ZXMgdGhlIGZsYXZvdXIgZm9yIGEgZ2l2ZW4gdGFyZ2V0IGJ5IGFsd2F5cyByZXR1cm5pbmcgdGhlIGxpYnJhcnkncyBEZWZhdWx0Rmxhdm91ciB2YWx1ZS5cbiAqIEBwYXJhbSB7b2JqZWN0fSB0YXJnZXQgVGhlIHRhcmdldCBvYmplY3QgYmVpbmcgZGVjb3JhdGVkXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSByZXNvbHZlZCBmbGF2b3VyIGlkZW50aWZpZXJcbiAqIEBmdW5jdGlvbiBkZWZhdWx0Rmxhdm91clJlc29sdmVyXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuZnVuY3Rpb24gZGVmYXVsdEZsYXZvdXJSZXNvbHZlcih0YXJnZXQ6IG9iamVjdCkge1xuICByZXR1cm4gRGVmYXVsdEZsYXZvdXI7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFVuaW9uIHR5cGUgY292ZXJpbmcgc3VwcG9ydGVkIGRlY29yYXRvciBraW5kc1xuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhbnkgb2YgdGhlIHN0YW5kYXJkIFR5cGVTY3JpcHQgZGVjb3JhdG9yIHNpZ25hdHVyZXMgKGNsYXNzLCBwcm9wZXJ0eSwgb3IgbWV0aG9kKSwgZW5hYmxpbmcgZmxleGlibGUgcmVnaXN0cmF0aW9uIGFuZCBhcHBsaWNhdGlvbiB3aXRoaW4gdGhlIERlY29yYXRpb24gc3lzdGVtLlxuICogQHRlbXBsYXRlIFRcbiAqIEB0eXBlRGVmIERlY29yYXRvclR5cGVzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuZXhwb3J0IHR5cGUgRGVjb3JhdG9yVHlwZXMgPVxuICB8IENsYXNzRGVjb3JhdG9yXG4gIHwgUHJvcGVydHlEZWNvcmF0b3JcbiAgfCBNZXRob2REZWNvcmF0b3I7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFR5cGUgZGVmaW5pdGlvbiBmb3IgYSBkZWNvcmF0b3IgZmFjdG9yeSBmdW5jdGlvblxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhIGZ1bmN0aW9uIHRoYXQgYWNjZXB0cyBhcmJpdHJhcnkgYXJndW1lbnRzIGFuZCByZXR1cm5zIGEgY29uY3JldGUgZGVjb3JhdG9yIGZ1bmN0aW9uIHRvIGJlIGFwcGxpZWQgdG8gYSB0YXJnZXQuXG4gKiBAdGVtcGxhdGUgQVxuICogQHR5cGVEZWYgRGVjb3JhdG9yRmFjdG9yeVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCB0eXBlIERlY29yYXRvckZhY3RvcnkgPSAoLi4uYXJnczogYW55W10pID0+IERlY29yYXRvclR5cGVzO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBcmd1bWVudCBidW5kbGUgZm9yIGEgZGVjb3JhdG9yIGZhY3RvcnlcbiAqIEBzdW1tYXJ5IE9iamVjdCBmb3JtIHVzZWQgdG8gZGVmZXIgZGVjb3JhdG9yIGNyZWF0aW9uLCBjYXJyeWluZyBib3RoIHRoZSBmYWN0b3J5IGZ1bmN0aW9uIGFuZCBpdHMgYXJndW1lbnQgbGlzdCB0byBiZSBpbnZva2VkIGxhdGVyIGR1cmluZyBhcHBsaWNhdGlvbi5cbiAqIEB0eXBlRGVmIERlY29yYXRvckZhY3RvcnlBcmdzXG4gKiBAcHJvcGVydHkge0RlY29yYXRvckZhY3Rvcnl9IGRlY29yYXRvciBUaGUgZmFjdG9yeSBmdW5jdGlvbiB0aGF0IHByb2R1Y2VzIGEgZGVjb3JhdG9yIHdoZW4gaW52b2tlZFxuICogQHByb3BlcnR5IHthbnlbXX0gYXJncyBsaXN0IG9mIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBkZWNvcmF0b3IgZmFjdG9yeVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCB0eXBlIERlY29yYXRvckZhY3RvcnlBcmdzID0ge1xuICBkZWNvcmF0b3I6IERlY29yYXRvckZhY3Rvcnk7XG4gIGFyZ3M6IGFueVtdO1xufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gVW5pb24gdGhhdCByZXByZXNlbnRzIGVpdGhlciBhIHJlYWR5LXRvLWFwcGx5IGRlY29yYXRvciBvciBhIGZhY3Rvcnkgd2l0aCBhcmd1bWVudHNcbiAqIEBzdW1tYXJ5IEFsbG93cyByZWdpc3RlcmluZyBkZWNvcmF0b3JzIGluIHR3byBmb3JtczogYXMgZGlyZWN0IGRlY29yYXRvciBmdW5jdGlvbnMgb3IgYXMgZGVmZXJyZWQgZmFjdG9yaWVzIHBhaXJlZCB3aXRoIHRoZWlyIGFyZ3VtZW50IGxpc3RzIGZvciBsYXRlciBpbnN0YW50aWF0aW9uLlxuICogQHR5cGVEZWYgRGVjb3JhdG9yRGF0YVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCB0eXBlIERlY29yYXRvckRhdGEgPSBEZWNvcmF0b3JUeXBlcyB8IERlY29yYXRvckZhY3RvcnlBcmdzO1xuLyoqXG4gKiBAZGVzY3JpcHRpb24gQSBkZWNvcmF0b3IgbWFuYWdlbWVudCBjbGFzcyB0aGF0IGhhbmRsZXMgZmxhdm91cmVkIGRlY29yYXRvcnNcbiAqIEBzdW1tYXJ5IFRoZSBEZWNvcmF0aW9uIGNsYXNzIHByb3ZpZGVzIGEgYnVpbGRlciBwYXR0ZXJuIGZvciBjcmVhdGluZyBhbmQgbWFuYWdpbmcgZGVjb3JhdG9ycyB3aXRoIGRpZmZlcmVudCBmbGF2b3Vycy5cbiAqIEl0IHN1cHBvcnRzIHJlZ2lzdGVyaW5nLCBleHRlbmRpbmcsIGFuZCBhcHBseWluZyBkZWNvcmF0b3JzIHdpdGggY29udGV4dC1hd2FyZSBmbGF2b3VyIHJlc29sdXRpb24uXG4gKiBUaGUgY2xhc3MgaW1wbGVtZW50cyBhIGZsdWVudCBpbnRlcmZhY2UgZm9yIGRlZmluaW5nLCBleHRlbmRpbmcsIGFuZCBhcHBseWluZyBkZWNvcmF0b3JzIHdpdGggZGlmZmVyZW50IGZsYXZvdXJzLFxuICogYWxsb3dpbmcgZm9yIGZyYW1ld29yay1zcGVjaWZpYyBkZWNvcmF0b3IgaW1wbGVtZW50YXRpb25zIHdoaWxlIG1haW50YWluaW5nIGEgY29uc2lzdGVudCBBUEkuXG4gKiBAdGVtcGxhdGUgVCBUeXBlIG9mIHRoZSBkZWNvcmF0b3IgKENsYXNzRGVjb3JhdG9yIHwgUHJvcGVydHlEZWNvcmF0b3IgfCBNZXRob2REZWNvcmF0b3IpXG4gKiBAcGFyYW0ge3N0cmluZ30gW2ZsYXZvdXJdIE9wdGlvbmFsIGZsYXZvdXIgcGFyYW1ldGVyIGZvciB0aGUgZGVjb3JhdG9yIGNvbnRleHRcbiAqIEBjbGFzc1xuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIENyZWF0ZSBhIG5ldyBkZWNvcmF0aW9uIGZvciAnY29tcG9uZW50JyB3aXRoIGRlZmF1bHQgZmxhdm91clxuICogY29uc3QgY29tcG9uZW50RGVjb3JhdG9yID0gbmV3IERlY29yYXRpb24oKVxuICogICAuZm9yKCdjb21wb25lbnQnKVxuICogICAuZGVmaW5lKGN1c3RvbUNvbXBvbmVudERlY29yYXRvcik7XG4gKlxuICogLy8gQ3JlYXRlIGEgZmxhdm91cmVkIGRlY29yYXRpb25cbiAqIGNvbnN0IHZ1ZUNvbXBvbmVudCA9IG5ldyBEZWNvcmF0aW9uKCd2dWUnKVxuICogICAuZm9yKCdjb21wb25lbnQnKVxuICogICAuZGVmaW5lKHZ1ZUNvbXBvbmVudERlY29yYXRvcik7XG4gKlxuICogLy8gQXBwbHkgdGhlIGRlY29yYXRpb25cbiAqIEBjb21wb25lbnREZWNvcmF0b3JcbiAqIGNsYXNzIE15Q29tcG9uZW50IHt9XG4gKiBgYGBcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQyBhcyBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgRCBhcyBEZWNvcmF0aW9uXG4gKiAgIHBhcnRpY2lwYW50IFIgYXMgRmxhdm91clJlc29sdmVyXG4gKiAgIHBhcnRpY2lwYW50IEYgYXMgRGVjb3JhdG9yRmFjdG9yeVxuICpcbiAqICAgQy0+PkQ6IG5ldyBEZWNvcmF0aW9uKGZsYXZvdXIpXG4gKiAgIEMtPj5EOiBmb3Ioa2V5KVxuICogICBDLT4+RDogZGVmaW5lKGRlY29yYXRvcnMpXG4gKiAgIEQtPj5EOiByZWdpc3RlcihrZXksIGZsYXZvdXIsIGRlY29yYXRvcnMpXG4gKiAgIEQtPj5GOiBkZWNvcmF0b3JGYWN0b3J5KGtleSwgZmxhdm91cilcbiAqICAgRi0+PlI6IHJlc29sdmUodGFyZ2V0KVxuICogICBSLS0+PkY6IHJlc29sdmVkIGZsYXZvdXJcbiAqICAgRi0+PkY6IGFwcGx5IGRlY29yYXRvcnNcbiAqICAgRi0tPj5DOiBkZWNvcmF0ZWQgdGFyZ2V0XG4gKi9cbmV4cG9ydCBjbGFzcyBEZWNvcmF0aW9uIGltcGxlbWVudHMgSURlY29yYXRpb25CdWlsZGVyIHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTdGF0aWMgbWFwIG9mIHJlZ2lzdGVyZWQgZGVjb3JhdG9yc1xuICAgKiBAc3VtbWFyeSBTdG9yZXMgYWxsIHJlZ2lzdGVyZWQgZGVjb3JhdG9ycyBvcmdhbml6ZWQgYnkga2V5IGFuZCBmbGF2b3VyXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBkZWNvcmF0b3JzOiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIFJlY29yZDxcbiAgICAgIHN0cmluZyxcbiAgICAgIHtcbiAgICAgICAgZGVjb3JhdG9ycz86IFNldDxEZWNvcmF0b3JEYXRhPjtcbiAgICAgICAgZXh0cmFzPzogU2V0PERlY29yYXRvckRhdGE+O1xuICAgICAgfVxuICAgID5cbiAgPiA9IHt9O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRnVuY3Rpb24gdG8gcmVzb2x2ZSBmbGF2b3VyIGZyb20gYSB0YXJnZXRcbiAgICogQHN1bW1hcnkgUmVzb2x2ZXIgZnVuY3Rpb24gdGhhdCBkZXRlcm1pbmVzIHRoZSBhcHByb3ByaWF0ZSBmbGF2b3VyIGZvciBhIGdpdmVuIHRhcmdldFxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZmxhdm91clJlc29sdmVyOiBGbGF2b3VyUmVzb2x2ZXIgPSBkZWZhdWx0Rmxhdm91clJlc29sdmVyO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0IG9mIGRlY29yYXRvcnMgZm9yIHRoZSBjdXJyZW50IGNvbnRleHRcbiAgICovXG4gIHByaXZhdGUgZGVjb3JhdG9ycz86IFNldDxEZWNvcmF0b3JEYXRhPjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldCBvZiBhZGRpdGlvbmFsIGRlY29yYXRvcnNcbiAgICovXG4gIHByaXZhdGUgZXh0cmFzPzogU2V0PERlY29yYXRvckRhdGE+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3VycmVudCBkZWNvcmF0b3Iga2V5XG4gICAqL1xuICBwcml2YXRlIGtleT86IHN0cmluZztcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGZsYXZvdXI6IHN0cmluZyA9IERlZmF1bHRGbGF2b3VyKSB7fVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUga2V5IGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXG4gICAqIEBzdW1tYXJ5IEluaXRpYWxpemVzIGEgbmV3IGRlY29yYXRpb24gY2hhaW4gd2l0aCB0aGUgc3BlY2lmaWVkIGtleVxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBpZGVudGlmaWVyIGZvciB0aGUgZGVjb3JhdG9yXG4gICAqIEByZXR1cm4ge0RlY29yYXRpb25CdWlsZGVyTWlkfSBCdWlsZGVyIGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmdcbiAgICovXG4gIGZvcihrZXk6IHN0cmluZyk6IERlY29yYXRpb25CdWlsZGVyTWlkIHtcbiAgICB0aGlzLmtleSA9IGtleTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQWRkcyBkZWNvcmF0b3JzIHRvIHRoZSBjdXJyZW50IGNvbnRleHRcbiAgICogQHN1bW1hcnkgSW50ZXJuYWwgbWV0aG9kIHRvIGFkZCBkZWNvcmF0b3JzIHdpdGggYWRkb24gc3VwcG9ydFxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFthZGRvbj1mYWxzZV0gV2hldGhlciB0aGUgZGVjb3JhdG9ycyBhcmUgYWRkb25zXG4gICAqIEBwYXJhbSBkZWNvcmF0b3JzIEFycmF5IG9mIGRlY29yYXRvcnNcbiAgICogQHJldHVybiB7dGhpc30gQ3VycmVudCBpbnN0YW5jZSBmb3IgY2hhaW5pbmdcbiAgICovXG4gIHByaXZhdGUgZGVjb3JhdGUoXG4gICAgYWRkb246IGJvb2xlYW4gPSBmYWxzZSxcbiAgICAuLi5kZWNvcmF0b3JzOiBEZWNvcmF0b3JEYXRhW11cbiAgKTogdGhpcyB7XG4gICAgaWYgKCF0aGlzLmtleSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihcImtleSBtdXN0IGJlIHByb3ZpZGVkIGJlZm9yZSBkZWNvcmF0b3JzIGNhbiBiZSBhZGRlZFwiKTtcbiAgICBpZiAoXG4gICAgICAoIWRlY29yYXRvcnMgfHwgIWRlY29yYXRvcnMubGVuZ3RoKSAmJlxuICAgICAgIWFkZG9uICYmXG4gICAgICB0aGlzLmZsYXZvdXIgIT09IERlZmF1bHRGbGF2b3VyXG4gICAgKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIk11c3QgcHJvdmlkZSBvdmVycmlkZXMgb3IgYWRkb25zIHRvIG92ZXJyaWRlIG9yIGV4dGVuZCBkZWNhZidzIGRlY29yYXRvcnNcIlxuICAgICAgKTtcbiAgICBpZiAodGhpcy5mbGF2b3VyID09PSBEZWZhdWx0Rmxhdm91ciAmJiBhZGRvbilcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkRlZmF1bHQgZmxhdm91ciBjYW5ub3QgYmUgZXh0ZW5kZWRcIik7XG5cbiAgICB0aGlzW2FkZG9uID8gXCJleHRyYXNcIiA6IFwiZGVjb3JhdG9yc1wiXSA9IG5ldyBTZXQoW1xuICAgICAgLi4uKHRoaXNbYWRkb24gPyBcImV4dHJhc1wiIDogXCJkZWNvcmF0b3JzXCJdIHx8IG5ldyBTZXQoKSkudmFsdWVzKCksXG4gICAgICAuLi5kZWNvcmF0b3JzLFxuICAgIF0pO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlZmluZXMgdGhlIGJhc2UgZGVjb3JhdG9yc1xuICAgKiBAc3VtbWFyeSBTZXRzIHRoZSBwcmltYXJ5IGRlY29yYXRvcnMgZm9yIHRoZSBjdXJyZW50IGNvbnRleHRcbiAgICogQHBhcmFtIGRlY29yYXRvcnMgRGVjb3JhdG9ycyB0byBkZWZpbmVcbiAgICogQHJldHVybiBCdWlsZGVyIGluc3RhbmNlIGZvciBmaW5pc2hpbmcgdGhlIGNoYWluXG4gICAqL1xuICBkZWZpbmUoXG4gICAgLi4uZGVjb3JhdG9yczogRGVjb3JhdG9yRGF0YVtdXG4gICk6IERlY29yYXRpb25CdWlsZGVyRW5kICYgRGVjb3JhdGlvbkJ1aWxkZXJCdWlsZCB7XG4gICAgaWYgKFxuICAgICAgZGVjb3JhdG9ycy5maW5kKChkKSA9PiB0eXBlb2YgZCA9PT0gXCJvYmplY3RcIikgJiZcbiAgICAgIGRlY29yYXRvcnMubGVuZ3RoICE9PSAxXG4gICAgKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgV2hlbiB1c2luZyBhbiBvdmVycmlkYWJsZSBkZWNvcmF0b3IsIG9ubHkgb25lIGlzIGFsbG93ZWRgXG4gICAgICApO1xuICAgIHJldHVybiB0aGlzLmRlY29yYXRlKGZhbHNlLCAuLi5kZWNvcmF0b3JzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXh0ZW5kcyBleGlzdGluZyBkZWNvcmF0b3JzXG4gICAqIEBzdW1tYXJ5IEFkZHMgYWRkaXRpb25hbCBkZWNvcmF0b3JzIHRvIHRoZSBjdXJyZW50IGNvbnRleHRcbiAgICogQHBhcmFtIGRlY29yYXRvcnMgQWRkaXRpb25hbCBkZWNvcmF0b3JzXG4gICAqIEByZXR1cm4ge0RlY29yYXRpb25CdWlsZGVyQnVpbGR9IEJ1aWxkZXIgaW5zdGFuY2UgZm9yIGJ1aWxkaW5nIHRoZSBkZWNvcmF0b3JcbiAgICovXG4gIGV4dGVuZCguLi5kZWNvcmF0b3JzOiBEZWNvcmF0b3JEYXRhW10pOiBEZWNvcmF0aW9uQnVpbGRlckJ1aWxkIHtcbiAgICBpZiAoXG4gICAgICBkZWNvcmF0b3JzLmZpbmQoKGQpID0+IHR5cGVvZiBkID09PSBcIm9iamVjdFwiKSAmJlxuICAgICAgZGVjb3JhdG9ycy5sZW5ndGggIT09IDFcbiAgICApXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBXaGVuIGV4dGVuZGluZyB1c2luZyBhbiBvdmVycmlkYWJsZSBkZWNvcmF0b3IsIG9ubHkgb25lIGlzIGFsbG93ZWRgXG4gICAgICApO1xuICAgIHJldHVybiB0aGlzLmRlY29yYXRlKHRydWUsIC4uLmRlY29yYXRvcnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBGYWN0b3J5IHRoYXQgY3JlYXRlcyBhIGNvbnRleHQtYXdhcmUgZGVjb3JhdG9yIGZvciBhIGtleS9mbGF2b3VyXG4gICAqIEBzdW1tYXJ5IFByb2R1Y2VzIGEgZGVjb3JhdG9yIGZ1bmN0aW9uIGJvdW5kIHRvIHRoZSBwcm92aWRlZCBrZXkgYW5kIGZsYXZvdXIuIFRoZSByZXN1bHRpbmcgZGVjb3JhdG9yIHJlc29sdmVzIHRoZSBhY3R1YWxcbiAgICogZGVjb3JhdG9ycyB0byBhcHBseSBhdCBpbnZvY2F0aW9uIHRpbWUgYmFzZWQgb24gdGhlIHRhcmdldCdzIHJlc29sdmVkIGZsYXZvdXIgYW5kIHRoZSByZWdpc3RlcmVkIGJhc2UgYW5kIGV4dHJhIGRlY29yYXRvcnMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGRlY29yYXRpb24ga2V5IHVzZWQgdG8gbG9vayB1cCByZWdpc3RlcmVkIGRlY29yYXRvcnNcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtmPURlZmF1bHRGbGF2b3VyXSBPcHRpb25hbCBleHBsaWNpdCBmbGF2b3VyIHRvIGJpbmQgdGhlIGZhY3RvcnkgdG9cbiAgICogQHJldHVybiB7ZnVuY3Rpb24ob2JqZWN0LCBhbnksIFR5cGVkUHJvcGVydHlEZXNjcmlwdG9yPGFueT4pOiBhbnl9IEEgZGVjb3JhdG9yIGZ1bmN0aW9uIHRoYXQgYXBwbGllcyB0aGUgcmVzb2x2ZWQgZGVjb3JhdG9yc1xuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBVIGFzIFVzZXIgQ29kZVxuICAgKiAgIHBhcnRpY2lwYW50IEIgYXMgRGVjb3JhdGlvbiAoYnVpbGRlcilcbiAgICogICBwYXJ0aWNpcGFudCBGIGFzIGRlY29yYXRvckZhY3Rvcnkoa2V5LCBmKVxuICAgKiAgIHBhcnRpY2lwYW50IFIgYXMgZmxhdm91clJlc29sdmVyXG4gICAqICAgcGFydGljaXBhbnQgQSBhcyBBcHBsaWVkIERlY29yYXRvcnNcbiAgICogICBVLT4+QjogZGVmaW5lKCkvZXh0ZW5kKCkgYW5kIGFwcGx5KClcbiAgICogICBCLT4+RjogY3JlYXRlIGNvbnRleHQgZGVjb3JhdG9yXG4gICAqICAgRi0+PlI6IHJlc29sdmUodGFyZ2V0KVxuICAgKiAgIFItLT4+RjogZmxhdm91clxuICAgKiAgIEYtPj5BOiBjb2xsZWN0IGJhc2UgKyBleHRyYXNcbiAgICogICBsb29wIGVhY2ggZGVjb3JhdG9yXG4gICAqICAgICBBLT4+VTogaW52b2tlIGRlY29yYXRvcih0YXJnZXQsIGtleT8sIGRlc2M/KVxuICAgKiAgIGVuZFxuICAgKi9cbiAgcHJvdGVjdGVkIGRlY29yYXRvckZhY3Rvcnkoa2V5OiBzdHJpbmcsIGY6IHN0cmluZyA9IERlZmF1bHRGbGF2b3VyKSB7XG4gICAgZnVuY3Rpb24gY29udGV4dERlY29yYXRvcihcbiAgICAgIHRhcmdldDogb2JqZWN0LFxuICAgICAgcHJvcGVydHlLZXk/OiBhbnksXG4gICAgICBkZXNjcmlwdG9yPzogVHlwZWRQcm9wZXJ0eURlc2NyaXB0b3I8YW55PlxuICAgICkge1xuICAgICAgY29uc3QgZmxhdm91ciA9IERlY29yYXRpb24uZmxhdm91clJlc29sdmVyKHRhcmdldCk7XG4gICAgICBjb25zdCBjYWNoZSA9IERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldO1xuICAgICAgbGV0IGRlY29yYXRvcnM7XG4gICAgICBjb25zdCBleHRyYXMgPSBjYWNoZVtmbGF2b3VyXVxuICAgICAgICA/IGNhY2hlW2ZsYXZvdXJdLmV4dHJhc1xuICAgICAgICA6IGNhY2hlW0RlZmF1bHRGbGF2b3VyXS5leHRyYXM7XG5cbiAgICAgIGlmIChcbiAgICAgICAgY2FjaGUgJiZcbiAgICAgICAgY2FjaGVbZmxhdm91cl0gJiZcbiAgICAgICAgY2FjaGVbZmxhdm91cl0uZGVjb3JhdG9ycyAmJlxuICAgICAgICBjYWNoZVtmbGF2b3VyXS5kZWNvcmF0b3JzLnNpemVcbiAgICAgICkge1xuICAgICAgICBkZWNvcmF0b3JzID0gY2FjaGVbZmxhdm91cl0uZGVjb3JhdG9ycztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlY29yYXRvcnMgPSBjYWNoZVtEZWZhdWx0Rmxhdm91cl0uZGVjb3JhdG9ycztcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGVjb3JhdG9yQXJncyA9IFtcbiAgICAgICAgLi4uKGNhY2hlW0RlZmF1bHRGbGF2b3VyXSBhcyBhbnkpLmRlY29yYXRvcnMudmFsdWVzKCksXG4gICAgICBdLnJlZHVjZSgoYWNjdW06IFJlY29yZDxudW1iZXIsIGFueT4sIGUsIGkpID0+IHtcbiAgICAgICAgaWYgKGUuYXJncykgYWNjdW1baV0gPSBlLmFyZ3M7XG4gICAgICAgIHJldHVybiBhY2N1bTtcbiAgICAgIH0sIHt9KTtcblxuICAgICAgY29uc3QgdG9BcHBseSA9IFtcbiAgICAgICAgLi4uKGRlY29yYXRvcnMgPyBkZWNvcmF0b3JzLnZhbHVlcygpIDogW10pLFxuICAgICAgICAuLi4oZXh0cmFzID8gZXh0cmFzLnZhbHVlcygpIDogW10pLFxuICAgICAgXTtcblxuICAgICAgcmV0dXJuIHRvQXBwbHkucmVkdWNlKFxuICAgICAgICAoXywgZCkgPT4ge1xuICAgICAgICAgIHN3aXRjaCAodHlwZW9mIGQpIHtcbiAgICAgICAgICAgIGNhc2UgXCJvYmplY3RcIjoge1xuICAgICAgICAgICAgICBjb25zdCB7IGRlY29yYXRvciB9ID0gZCBhcyBEZWNvcmF0b3JGYWN0b3J5QXJncztcblxuICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIGRlY29yYXRvciguLi4oT2JqZWN0LnZhbHVlcyhkZWNvcmF0b3JBcmdzKVswXSB8fCBbXSkpIGFzIGFueVxuICAgICAgICAgICAgICApKHRhcmdldCwgcHJvcGVydHlLZXksIGRlc2NyaXB0b3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FzZSBcImZ1bmN0aW9uXCI6XG4gICAgICAgICAgICAgIHJldHVybiAoZCBhcyBhbnkpKHRhcmdldCwgcHJvcGVydHlLZXksIGRlc2NyaXB0b3IpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmV4cGVjdGVkIGRlY29yYXRvciB0eXBlOiAke3R5cGVvZiBkfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgeyB0YXJnZXQsIHByb3BlcnR5S2V5LCBkZXNjcmlwdG9yIH1cbiAgICAgICk7XG4gICAgfVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb250ZXh0RGVjb3JhdG9yLCBcIm5hbWVcIiwge1xuICAgICAgdmFsdWU6IFtmLCBrZXldLmpvaW4oXCJfZGVjb3JhdG9yX2Zvcl9cIiksXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgfSk7XG4gICAgcmV0dXJuIGNvbnRleHREZWNvcmF0b3I7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgdGhlIGZpbmFsIGRlY29yYXRvciBmdW5jdGlvblxuICAgKiBAc3VtbWFyeSBCdWlsZHMgYW5kIHJldHVybnMgdGhlIGRlY29yYXRvciBmYWN0b3J5IGZ1bmN0aW9uXG4gICAqIEByZXR1cm4ge2Z1bmN0aW9uKGFueSwgYW55PywgVHlwZWRQcm9wZXJ0eURlc2NyaXB0b3I/KTogYW55fSBUaGUgZ2VuZXJhdGVkIGRlY29yYXRvciBmdW5jdGlvblxuICAgKi9cbiAgYXBwbHkoKTogKFxuICAgIHRhcmdldDogYW55LFxuICAgIHByb3BlcnR5S2V5PzogYW55LFxuICAgIGRlc2NyaXB0b3I/OiBUeXBlZFByb3BlcnR5RGVzY3JpcHRvcjxhbnk+XG4gICkgPT4gYW55IHtcbiAgICBpZiAoIXRoaXMua2V5KVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8ga2V5IHByb3ZpZGVkIGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXCIpO1xuICAgIERlY29yYXRpb24ucmVnaXN0ZXIoXG4gICAgICB0aGlzLmtleSxcbiAgICAgIHRoaXMuZmxhdm91cixcbiAgICAgIHRoaXMuZGVjb3JhdG9ycyB8fCBuZXcgU2V0KCksXG4gICAgICB0aGlzLmV4dHJhc1xuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuZGVjb3JhdG9yRmFjdG9yeSh0aGlzLmtleSwgdGhpcy5mbGF2b3VyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVnaXN0ZXJzIGRlY29yYXRvcnMgZm9yIGEgc3BlY2lmaWMga2V5IGFuZCBmbGF2b3VyXG4gICAqIEBzdW1tYXJ5IEludGVybmFsIG1ldGhvZCB0byBzdG9yZSBkZWNvcmF0b3JzIGluIHRoZSBzdGF0aWMgcmVnaXN0cnlcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBEZWNvcmF0b3Iga2V5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmbGF2b3VyIERlY29yYXRvciBmbGF2b3VyXG4gICAqIEBwYXJhbSBbZGVjb3JhdG9yc10gUHJpbWFyeSBkZWNvcmF0b3JzXG4gICAqIEBwYXJhbSBbZXh0cmFzXSBBZGRpdGlvbmFsIGRlY29yYXRvcnNcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHJlZ2lzdGVyKFxuICAgIGtleTogc3RyaW5nLFxuICAgIGZsYXZvdXI6IHN0cmluZyxcbiAgICBkZWNvcmF0b3JzPzogU2V0PERlY29yYXRvckRhdGE+LFxuICAgIGV4dHJhcz86IFNldDxEZWNvcmF0b3JEYXRhPlxuICApIHtcbiAgICBpZiAoIWtleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8ga2V5IHByb3ZpZGVkIGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXCIpO1xuICAgIH1cbiAgICBpZiAoIWRlY29yYXRvcnMpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBkZWNvcmF0b3JzIHByb3ZpZGVkIGZvciB0aGUgZGVjb3JhdGlvbiBidWlsZGVyXCIpO1xuICAgIGlmICghZmxhdm91cilcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGZsYXZvdXIgcHJvdmlkZWQgZm9yIHRoZSBkZWNvcmF0aW9uIGJ1aWxkZXJcIik7XG5cbiAgICBpZiAoIURlY29yYXRpb24uZGVjb3JhdG9yc1trZXldKSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XSA9IHt9O1xuICAgIGlmICghRGVjb3JhdGlvbi5kZWNvcmF0b3JzW2tleV1bZmxhdm91cl0pXG4gICAgICBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXSA9IHt9O1xuICAgIGlmIChkZWNvcmF0b3JzKSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXS5kZWNvcmF0b3JzID0gZGVjb3JhdG9ycztcbiAgICBpZiAoZXh0cmFzKSBEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXS5leHRyYXMgPSBleHRyYXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIGdsb2JhbCBmbGF2b3VyIHJlc29sdmVyXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIGZ1bmN0aW9uIHVzZWQgdG8gZGV0ZXJtaW5lIGRlY29yYXRvciBmbGF2b3Vyc1xuICAgKiBAcGFyYW0ge0ZsYXZvdXJSZXNvbHZlcn0gcmVzb2x2ZXIgRnVuY3Rpb24gdG8gcmVzb2x2ZSBmbGF2b3Vyc1xuICAgKi9cbiAgc3RhdGljIHNldEZsYXZvdXJSZXNvbHZlcihyZXNvbHZlcjogRmxhdm91clJlc29sdmVyKSB7XG4gICAgRGVjb3JhdGlvbi5mbGF2b3VyUmVzb2x2ZXIgPSByZXNvbHZlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29udmVuaWVuY2Ugc3RhdGljIGVudHJ5IHRvIHN0YXJ0IGEgZGVjb3JhdGlvbiBidWlsZGVyXG4gICAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBuZXcgRGVjb3JhdGlvbiBpbnN0YW5jZSBhbmQgaW5pdGlhdGVzIHRoZSBidWlsZGVyIGNoYWluIHdpdGggdGhlIHByb3ZpZGVkIGtleS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUgZGVjb3JhdGlvbiBrZXkgdG8gY29uZmlndXJlXG4gICAqIEByZXR1cm4ge0RlY29yYXRpb25CdWlsZGVyTWlkfSBBIGJ1aWxkZXIgaW5zdGFuY2UgZm9yIGNoYWluaW5nIGRlZmluaXRpb25zXG4gICAqL1xuICBzdGF0aWMgZm9yKGtleTogc3RyaW5nKTogRGVjb3JhdGlvbkJ1aWxkZXJNaWQge1xuICAgIHJldHVybiBuZXcgRGVjb3JhdGlvbigpLmZvcihrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTdGFydHMgYSBidWlsZGVyIGZvciBhIHNwZWNpZmljIGZsYXZvdXJcbiAgICogQHN1bW1hcnkgQ29udmVuaWVuY2UgbWV0aG9kIHRvIGJlZ2luIGEgRGVjb3JhdGlvbiBidWlsZGVyIGNoYWluIGJvdW5kIHRvIHRoZSBnaXZlbiBmbGF2b3VyIGlkZW50aWZpZXIsIGFsbG93aW5nIHJlZ2lzdHJhdGlvbiBvZiBmbGF2b3VyLXNwZWNpZmljIGRlY29yYXRvcnMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmbGF2b3VyIFRoZSBmbGF2b3VyIG5hbWUgdG8gYmluZCB0byB0aGUgYnVpbGRlclxuICAgKiBAcmV0dXJuIHtEZWNvcmF0aW9uQnVpbGRlclN0YXJ0fSBBIGJ1aWxkZXIgc3RhcnQgaW50ZXJmYWNlIHRvIGNvbnRpbnVlIGNvbmZpZ3VyYXRpb25cbiAgICovXG4gIHN0YXRpYyBmbGF2b3VyZWRBcyhmbGF2b3VyOiBzdHJpbmcpOiBEZWNvcmF0aW9uQnVpbGRlclN0YXJ0IHtcbiAgICByZXR1cm4gbmV3IERlY29yYXRpb24oZmxhdm91cik7XG4gIH1cbn1cbiIsImltcG9ydCB7IE1ldGFkYXRhIH0gZnJvbSBcIi4vbWV0YWRhdGEvTWV0YWRhdGFcIjtcbmltcG9ydCB7IERlY29yYXRpb25LZXlzLCBPYmplY3RLZXlTcGxpdHRlciB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBc3NpZ25zIGFyYml0cmFyeSBtZXRhZGF0YSB0byBhIHRhcmdldCB1c2luZyBhIHN0cmluZyBrZXlcbiAqIEBzdW1tYXJ5IERlY29yYXRvciBmYWN0b3J5IHRoYXQgc3RvcmVzIGEga2V5L3ZhbHVlIHBhaXIgaW4gdGhlIGNlbnRyYWwgTWV0YWRhdGEgc3RvcmUgZm9yIHRoZSBwcm92aWRlZCBjbGFzcyBvciBtZW1iZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBtZXRhZGF0YSBrZXkgdG8gYXNzb2NpYXRlIHdpdGggdGhlIHRhcmdldFxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgbWV0YWRhdGEgdmFsdWUgdG8gc3RvcmUgdW5kZXIgdGhlIGdpdmVuIGtleVxuICogQHJldHVybiBBIGRlY29yYXRvciB0aGF0IHdyaXRlcyB0aGUgbWV0YWRhdGEgd2hlbiBhcHBsaWVkXG4gKiBAZnVuY3Rpb24gbWV0YWRhdGFcbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXRhZGF0YShrZXk6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICByZXR1cm4gZnVuY3Rpb24gbWV0YWRhdGEoXG4gICAgbW9kZWw6IGFueSxcblxuICAgIHByb3A/OiBhbnksXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIGRlc2NyaXB0b3I/OiBQcm9wZXJ0eURlc2NyaXB0b3JcbiAgKSB7XG4gICAgTWV0YWRhdGEuc2V0KHByb3AgPyBtb2RlbC5jb25zdHJ1Y3RvciA6IG1vZGVsLCBrZXksIHZhbHVlKTtcbiAgfTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ2FwdHVyZXMgYW5kIHN0b3JlcyBhIHByb3BlcnR5J3MgZGVzaWduIHR5cGVcbiAqIEBzdW1tYXJ5IERlY29yYXRvciBmYWN0b3J5IHRoYXQgcmVhZHMgdGhlIHJlZmxlY3RlZCBkZXNpZ246dHlwZSBmb3IgYSBwcm9wZXJ0eSBhbmQgcmVnaXN0ZXJzIGl0IGluIHRoZSBNZXRhZGF0YSBzdG9yZSB1bmRlciB0aGUgcHJvcGVydGllcyBtYXAuXG4gKiBAcmV0dXJuIEEgZGVjb3JhdG9yIHRoYXQgcmVjb3JkcyB0aGUgcHJvcGVydHkncyB0eXBlIG1ldGFkYXRhIHdoZW4gYXBwbGllZFxuICogQGZ1bmN0aW9uIHByb3BcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcm9wKCkge1xuICByZXR1cm4gZnVuY3Rpb24gcHJvcChtb2RlbDogb2JqZWN0LCBwcm9wOiBhbnkpIHtcbiAgICBjb25zdCBkZXNpZ25UeXBlID0gUmVmbGVjdC5nZXRPd25NZXRhZGF0YShcbiAgICAgIERlY29yYXRpb25LZXlzLkRFU0lHTl9UWVBFLFxuICAgICAgbW9kZWwsXG4gICAgICBwcm9wXG4gICAgKTtcbiAgICByZXR1cm4gbWV0YWRhdGEoYCR7RGVjb3JhdGlvbktleXMuUFJPUEVSVElFU30uJHtwcm9wfWAsIGRlc2lnblR5cGUpKFxuICAgICAgbW9kZWwsXG4gICAgICBwcm9wXG4gICAgKTtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1ldGhvZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIG1ldGhvZChvYmo6IGFueSwgcHJvcDogYW55LCBkZXNjcmlwdG9yOiBhbnkpIHtcbiAgICBjb25zdCBkZXNpZ25QYXJhbXMgPSBSZWZsZWN0LmdldE93bk1ldGFkYXRhKFxuICAgICAgRGVjb3JhdGlvbktleXMuREVTSUdOX1BBUkFNUyxcbiAgICAgIG9iaixcbiAgICAgIHByb3BcbiAgICApO1xuICAgIGNvbnN0IGRlc2lnblJldHVybiA9IFJlZmxlY3QuZ2V0T3duTWV0YWRhdGEoXG4gICAgICBEZWNvcmF0aW9uS2V5cy5ERVNJR05fUkVUVVJOLFxuICAgICAgb2JqLFxuICAgICAgcHJvcFxuICAgICk7XG4gICAgcmV0dXJuIGFwcGx5KFxuICAgICAgbWV0YWRhdGEoXG4gICAgICAgIGAke0RlY29yYXRpb25LZXlzLk1FVEhPRFN9LiR7cHJvcH0uJHtEZWNvcmF0aW9uS2V5cy5ERVNJR05fUEFSQU1TfWAsXG4gICAgICAgIGRlc2lnblBhcmFtc1xuICAgICAgKSxcbiAgICAgIG1ldGFkYXRhKFxuICAgICAgICBgJHtEZWNvcmF0aW9uS2V5cy5NRVRIT0RTfS4ke3Byb3B9LiR7RGVjb3JhdGlvbktleXMuREVTSUdOX1JFVFVSTn1gLFxuICAgICAgICBkZXNpZ25SZXR1cm5cbiAgICAgIClcbiAgICApKG9iaiwgcHJvcCwgZGVzY3JpcHRvcik7XG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlY29yYXRvciBmYWN0b3J5IHRoYXQgYXBwbGllcyBtdWx0aXBsZSBkZWNvcmF0b3JzIHRvIGEgc2luZ2xlIHRhcmdldFxuICogQHN1bW1hcnkgQ3JlYXRlcyBhIGNvbXBvc2l0ZSBkZWNvcmF0b3IgdGhhdCBhcHBsaWVzIG11bHRpcGxlIGRlY29yYXRvcnMgaW4gc2VxdWVuY2UsIGNvcnJlY3RseSBoYW5kbGluZyBjbGFzcywgbWV0aG9kLCBhbmQgcHJvcGVydHkgZGVjb3JhdG9ycy5cbiAqIEBwYXJhbSB7QXJyYXk8Q2xhc3NEZWNvcmF0b3IgfCBNZXRob2REZWNvcmF0b3IgfCBQcm9wZXJ0eURlY29yYXRvcj59IGRlY29yYXRvcnMgLSBBcnJheSBvZiBkZWNvcmF0b3JzIHRvIGFwcGx5XG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBkZWNvcmF0b3IgZnVuY3Rpb24gdGhhdCBhcHBsaWVzIGFsbCBwcm92aWRlZCBkZWNvcmF0b3JzIHRvIHRoZSB0YXJnZXRcbiAqIEBmdW5jdGlvbiBhcHBseVxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBVIGFzIFVzZXIgQ29kZVxuICogICBwYXJ0aWNpcGFudCBBIGFzIGFwcGx5KC4uLmRlY29yYXRvcnMpXG4gKiAgIHBhcnRpY2lwYW50IEQgYXMgRGVjb3JhdG9yXG4gKiAgIFUtPj5BOiBnZXQgZGVjb3JhdG9yKC4uLmRlY29yYXRvcnMpXG4gKiAgIEEtPj5VOiByZXR1cm5zICh0YXJnZXQsIGtleT8sIGRlc2M/KSA9PiB2b2lkXG4gKiAgIFUtPj5BOiBpbnZva2Ugb24gdGFyZ2V0XG4gKiAgIGxvb3AgZm9yIGVhY2ggZGVjb3JhdG9yXG4gKiAgICAgQS0+PkQ6IGludm9rZSBhcHByb3ByaWF0ZSBkZWNvcmF0b3IgdHlwZVxuICogICBlbmRcbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseShcbiAgLi4uZGVjb3JhdG9yczogQXJyYXk8Q2xhc3NEZWNvcmF0b3IgfCBNZXRob2REZWNvcmF0b3IgfCBQcm9wZXJ0eURlY29yYXRvcj5cbikge1xuICByZXR1cm4gKFxuICAgIHRhcmdldDogb2JqZWN0LFxuICAgIHByb3BlcnR5S2V5Pzogc3RyaW5nIHwgc3ltYm9sIHwgdW5rbm93bixcbiAgICBkZXNjcmlwdG9yPzogUHJvcGVydHlEZXNjcmlwdG9yXG4gICkgPT4ge1xuICAgIGZvciAoY29uc3QgZGVjb3JhdG9yIG9mIGRlY29yYXRvcnMpIHtcbiAgICAgIGlmICh0YXJnZXQgaW5zdGFuY2VvZiBGdW5jdGlvbiAmJiAhZGVzY3JpcHRvcikge1xuICAgICAgICAoZGVjb3JhdG9yIGFzIENsYXNzRGVjb3JhdG9yKSh0YXJnZXQpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIChkZWNvcmF0b3IgYXMgTWV0aG9kRGVjb3JhdG9yIHwgUHJvcGVydHlEZWNvcmF0b3IpKFxuICAgICAgICB0YXJnZXQsXG4gICAgICAgIHByb3BlcnR5S2V5IGFzIHN0cmluZyB8IHN5bWJvbCxcbiAgICAgICAgZGVzY3JpcHRvciBhcyBUeXBlZFByb3BlcnR5RGVzY3JpcHRvcjx1bmtub3duPlxuICAgICAgKTtcbiAgICB9XG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBwcm9wZXJ0eSBtZXRhZGF0YSBkZWNvcmF0b3JcbiAqIEBzdW1tYXJ5IENvbnZlbmllbmNlIGZhY3RvcnkgdGhhdCBjb21iaW5lcyBtZXRhZGF0YShrZXksIHZhbHVlKSBhbmQgcHJvcCgpIHRvIGJvdGggc2V0IGFuIGFyYml0cmFyeSBtZXRhZGF0YSBrZXkgYW5kIHJlY29yZCB0aGUgcHJvcGVydHkncyBkZXNpZ24gdHlwZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIG1ldGFkYXRhIGtleSB0byBzZXQgZm9yIHRoZSBwcm9wZXJ0eVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgbWV0YWRhdGEgdmFsdWUgdG8gYXNzb2NpYXRlIHdpdGggdGhlIGtleVxuICogQHJldHVybiBBIGRlY29yYXRvciB0aGF0IHNldHMgdGhlIG1ldGFkYXRhIGFuZCBjYXB0dXJlcyB0aGUgcHJvcGVydHkncyB0eXBlXG4gKiBAZnVuY3Rpb24gcHJvcE1ldGFkYXRhXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvcE1ldGFkYXRhKGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XG4gIHJldHVybiBhcHBseShtZXRhZGF0YShrZXksIHZhbHVlKSwgcHJvcCgpKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQXR0YWNoZXMgYSBodW1hbi1yZWFkYWJsZSBkZXNjcmlwdGlvbiB0byBhIGNsYXNzIG9yIG1lbWJlclxuICogQHN1bW1hcnkgRGVjb3JhdG9yIGZhY3RvcnkgdGhhdCBzdG9yZXMgYSB0ZXh0dWFsIGRlc2NyaXB0aW9uIGluIHRoZSBNZXRhZGF0YSBzdG9yZSB1bmRlciB0aGUgYXBwcm9wcmlhdGUgZGVzY3JpcHRpb24ga2V5IGZvciBhIGNsYXNzIG9yIGl0cyBwcm9wZXJ0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkZXNjIFRoZSBkZXNjcmlwdGl2ZSB0ZXh0IHRvIGFzc29jaWF0ZSB3aXRoIHRoZSBjbGFzcyBvciBwcm9wZXJ0eVxuICogQHJldHVybiBBIGRlY29yYXRvciB0aGF0IHJlY29yZHMgdGhlIGRlc2NyaXB0aW9uIHdoZW4gYXBwbGllZFxuICogQGZ1bmN0aW9uIGRlc2NyaXB0aW9uXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZGVzY3JpcHRpb24oZGVzYzogc3RyaW5nKSB7XG4gIHJldHVybiBmdW5jdGlvbiBkZXNjcmlwdGlvbihvcmlnaW5hbDogYW55LCBwcm9wPzogYW55LCBkZXNjcmlwdG9yPzogYW55KSB7XG4gICAgcmV0dXJuIG1ldGFkYXRhKFxuICAgICAgW1xuICAgICAgICBEZWNvcmF0aW9uS2V5cy5ERVNDUklQVElPTixcbiAgICAgICAgcHJvcCA/IHByb3AudG9TdHJpbmcoKSA6IERlY29yYXRpb25LZXlzLkNMQVNTLFxuICAgICAgXS5qb2luKE9iamVjdEtleVNwbGl0dGVyKSxcbiAgICAgIGRlc2NcbiAgICApKG9yaWdpbmFsLCBwcm9wLCBkZXNjcmlwdG9yKTtcbiAgfTtcbn1cbiIsIi8qKlxuICogQGRlc2NyaXB0aW9uIFJvb3QgZW50cnkgcG9pbnQgZm9yIHRoZSBkZWNvcmF0aW9uIG1vZHVsZVxuICogQHN1bW1hcnkgQWdncmVnYXRlcyBhbmQgcmUtZXhwb3J0cyB0aGUgcHVibGljIEFQSSBvZiB0aGUgZGVjb3JhdGlvbiBsaWJyYXJ5LCBpbmNsdWRpbmcgY29yZSBjbGFzc2VzIGxpa2Uge0BsaW5rIERlY29yYXRpb259LCB1dGlsaXR5IGRlY29yYXRvcnMsIG1ldGFkYXRhIGhlbHBlcnMsIGFuZCBjb25zdGFudHMuIFRoaXMgbW9kdWxlIGlzIHRoZSBwcmltYXJ5IGltcG9ydCBzdXJmYWNlIGZvciBjb25zdW1lcnMgYW5kIGV4cG9zZXM6XG4gKiAtIENvcmUgYnVpbGRlcjoge0BsaW5rIERlY29yYXRpb259XG4gKiAtIERlY29yYXRvciB1dGlsaXRpZXM6IHtAbGluayBtb2R1bGU6ZGVjb3JhdGlvbiB8IGRlY29yYXRvcnMgaW4gLi9kZWNvcmF0b3JzfVxuICogLSBNZXRhZGF0YSB1dGlsaXRpZXM6IHtAbGluayBNZXRhZGF0YX1cbiAqIC0gQ29uc3RhbnRzIGFuZCBlbnVtczoge0BsaW5rIERlY29yYXRpb25LZXlzfSwge0BsaW5rIERlZmF1bHRGbGF2b3VyfVxuICpcbiAqIEBtb2R1bGUgZGVjb3JhdGlvblxuICovXG5cbmltcG9ydCB7IE1ldGFkYXRhIH0gZnJvbSBcIi4vbWV0YWRhdGEvaW5kZXhcIjtcblxuZXhwb3J0ICogZnJvbSBcIi4vZGVjb3JhdGlvblwiO1xuZXhwb3J0ICogZnJvbSBcIi4vbWV0YWRhdGFcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vZGVjb3JhdG9yc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDdXJyZW50IHZlcnNpb24gb2YgdGhlIHJlZmxlY3Rpb24gcGFja2FnZVxuICogQHN1bW1hcnkgU3RvcmVzIHRoZSBzZW1hbnRpYyB2ZXJzaW9uIG51bWJlciBvZiB0aGUgcGFja2FnZVxuICogQGNvbnN0IFZFUlNJT05cbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdGlvblxuICovXG5leHBvcnQgY29uc3QgVkVSU0lPTiA9IFwiIyNWRVJTSU9OIyNcIjtcblxuTWV0YWRhdGEucmVnaXN0ZXJMaWJyYXJ5KFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIiwgVkVSU0lPTik7XG4iXSwibmFtZXMiOlsiRGVjb3JhdGlvbktleXMiXSwibWFwcGluZ3MiOiI7Ozs7OztJQUVBOzs7Ozs7SUFNRztBQUNJLFVBQU0sY0FBYyxHQUFHO0lBRTlCOzs7OztJQUtHO0FBQ0ksVUFBTSxpQkFBaUIsR0FBRztJQUVqQzs7Ozs7Ozs7O0lBU0c7QUFDU0E7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
849
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVjb3JhdGlvbi5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb25zdGFudHMudHMiLCIuLi9zcmMvbWV0YWRhdGEvTWV0YWRhdGEudHMiLCIuLi9zcmMvZGVjb3JhdGlvbi9EZWNvcmF0aW9uLnRzIiwiLi4vc3JjL2RlY29yYXRvcnMudHMiLCIuLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQmFzaWNNZXRhZGF0YSB9IGZyb20gXCIuL21ldGFkYXRhL3R5cGVzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmF1bHQgZmxhdm91ciBpZGVudGlmaWVyIGZvciB0aGUgZGVjb3JhdG9yIHN5c3RlbS5cbiAqIEBzdW1tYXJ5IERlZmluZXMgdGhlIGRlZmF1bHQgZmxhdm91ciB1c2VkIGJ5IHRoZSBEZWNvcmF0aW9uIGNsYXNzIHdoZW4gbm8gc3BlY2lmaWMgZmxhdm91ciBpcyBwcm92aWRlZC4gVGhpcyBjb25zdGFudCBpcyB1c2VkIHRocm91Z2hvdXQgdGhlIGxpYnJhcnkgYXMgdGhlIGZhbGxiYWNrIGZsYXZvdXIgZm9yIGRlY29yYXRvcnMuXG4gKiBAY29uc3QgRGVmYXVsdEZsYXZvdXJcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdGlvblxuICovXG5leHBvcnQgY29uc3QgRGVmYXVsdEZsYXZvdXIgPSBcImRlY2FmXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENoYXJhY3RlciB1c2VkIHRvIHNwbGl0IG5lc3RlZCBtZXRhZGF0YSBrZXlzLlxuICogQHN1bW1hcnkgRGVmaW5lcyB0aGUgZGVsaW1pdGVyIHRoZSBtZXRhZGF0YSBzdG9yZSB1c2VzIHRvIHRyYXZlcnNlIG5lc3RlZCBvYmplY3QgcGF0aHMgd2hlbiByZWFkaW5nIG9yIHdyaXRpbmcgdmFsdWVzLlxuICogQGNvbnN0IE9iamVjdEtleVNwbGl0dGVyXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuZXhwb3J0IGNvbnN0IE9iamVjdEtleVNwbGl0dGVyID0gXCIuXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE1ldGFkYXRhIHRva2VuIHJlZ2lzdHJ5IGZvciB0aGUgZGVjb3JhdGlvbiBzeXN0ZW0uXG4gKiBAc3VtbWFyeSBFbnVtZXJhdGVzIHRoZSBrZXlzIHVzZWQgZHVyaW5nIHJlZmxlY3Rpb24gYW5kIG1ldGFkYXRhIHN0b3JhZ2UgZm9yIGNsYXNzZXMsIHByb3BlcnRpZXMsIG1ldGhvZHMsIGRlc2NyaXB0aW9ucywgYW5kIHJlZ2lzdGVyZWQgbGlicmFyaWVzLlxuICogQGVudW0ge3N0cmluZ31cbiAqIEByZWFkb25seVxuICogQGNvbnN0IERlY29yYXRpb25LZXlzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuZXhwb3J0IGVudW0gRGVjb3JhdGlvbktleXMge1xuICAvKiogQGRlc2NyaXB0aW9uIFN0b3JhZ2UgYnVja2V0IGZvciBkZWNvcmF0aW9uLWF3YXJlIGxpYnJhcnkgcmVnaXN0cmF0aW9ucy4gKi9cbiAgTElCUkFSSUVTID0gXCJsaWJyYXJpZXNcIixcbiAgLyoqIEBkZXNjcmlwdGlvbiBTdG9yYWdlIGtleSBtaXJyb3JlZCBvbiBjb25zdHJ1Y3RvcnMgdGhhdCBob2xkcyBydW50aW1lIG1ldGFkYXRhLiAqL1xuICBSRUZMRUNUID0gYF9fJHtEZWZhdWx0Rmxhdm91cn1gLFxuICAvKiogQGRlc2NyaXB0aW9uIENvbnRhaW5lciBvZiByZWZsZWN0ZWQgcHJvcGVydHkgbWV0YWRhdGEgZm9yIGEgbW9kZWwuICovXG4gIFBST1BFUlRJRVMgPSBcInByb3BlcnRpZXNcIixcbiAgLyoqIEBkZXNjcmlwdGlvbiBDb250YWluZXIgb2YgcmVmbGVjdGVkIG1ldGhvZCBtZXRhZGF0YSBmb3IgYSBtb2RlbC4gKi9cbiAgTUVUSE9EUyA9IFwibWV0aG9kc1wiLFxuICAvKiogQGRlc2NyaXB0aW9uIEtleSB1bmRlciB3aGljaCB0aGUgbW9kZWwgY29uc3RydWN0b3IgcmVmZXJlbmNlIGlzIHBlcnNpc3RlZC4gKi9cbiAgQ0xBU1MgPSBcImNsYXNzXCIsXG4gIC8qKiBAZGVzY3JpcHRpb24gSHVtYW4tcmVhZGFibGUgZGVzY3JpcHRpb25zIGZvciBjbGFzc2VzIGFuZCBtZW1iZXJzLiAqL1xuICBERVNDUklQVElPTiA9IFwiZGVzY3JpcHRpb25cIixcbiAgLyoqIEBkZXNjcmlwdGlvbiBTdG9yYWdlIHNsb3QgdHJhY2tpbmcgdGhlIG9yaWdpbmFsIGNvbnN0cnVjdG9yIHdoZW4gb3ZlcnJpZGRlbi4gKi9cbiAgQ09OU1RSVUNUT1IgPSBcImNvbnN0cnVjdG9yXCIsXG4gIC8qKiBAZGVzY3JpcHRpb24gQ29sbGVjdGVkIHBhcmFtZXRlciBtZXRhZGF0YSBmb3IgY29uZmlndXJlZCBkZWNvcmF0b3JzLiAqL1xuICBQQVJBTUVURVJTID0gXCJwYXJhbWV0ZXJzXCIsXG4gIC8qKiBAZGVzY3JpcHRpb24gUmVmbGVjdCBtZXRhZGF0YSBrZXkgZm9yIGEgcHJvcGVydHkncyBkZXNpZ24gdHlwZS4gKi9cbiAgREVTSUdOX1RZUEUgPSBcImRlc2lnbjp0eXBlXCIsXG4gIC8qKiBAZGVzY3JpcHRpb24gUmVmbGVjdCBtZXRhZGF0YSBrZXkgZm9yIHJlY29yZGVkIGNvbnN0cnVjdG9yIHBhcmFtZXRlciB0eXBlcy4gKi9cbiAgREVTSUdOX1BBUkFNUyA9IFwiZGVzaWduOnBhcmFtdHlwZXNcIixcbiAgLyoqIEBkZXNjcmlwdGlvbiBSZWZsZWN0IG1ldGFkYXRhIGtleSBmb3IgYSBtZXRob2QncyByZXR1cm4gdHlwZS4gKi9cbiAgREVTSUdOX1JFVFVSTiA9IFwiZGVzaWduOnJldHVybnR5cGVcIixcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVmYXVsdCBtZXRhZGF0YSBpbnN0YW5jZS5cbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIHRoZSBkZWZhdWx0IG1ldGFkYXRhIHNoYXBlIHVzZWQgd2hlbiBpbml0aWFsaXppbmcgbmV3IG1ldGFkYXRhIGVudHJpZXMgZm9yIGEgbW9kZWwuXG4gKiBAY29uc3QgRGVmYXVsdE1ldGFkYXRhXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuZXhwb3J0IGNvbnN0IERlZmF1bHRNZXRhZGF0YTogQmFzaWNNZXRhZGF0YTxhbnk+ID0ge1xuICBbRGVjb3JhdGlvbktleXMuUFJPUEVSVElFU106IFtdLFxufSBhcyB1bmtub3duIGFzIEJhc2ljTWV0YWRhdGE8YW55PjtcbiIsImltcG9ydCB7IEJhc2ljTWV0YWRhdGEsIENvbnN0cnVjdG9yIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IERlY29yYXRpb25LZXlzLCBPYmplY3RLZXlTcGxpdHRlciB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcbmltcG9ydCBcInJlZmxlY3QtbWV0YWRhdGFcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGEgbmVzdGVkIHZhbHVlIGZyb20gYW4gb2JqZWN0IGdpdmVuIGEgcGF0aC5cbiAqIEBzdW1tYXJ5IFdhbGtzIGFuIG9iamVjdCBzdHJ1Y3R1cmUgdXNpbmcgYSBzcGxpdHRlci1kZWxpbWl0ZWQgcGF0aCBhbmQgcmV0dXJucyB0aGUgdmFsdWUgYXQgdGhhdCBsb2NhdGlvbiBvciBgdW5kZWZpbmVkYCBpZiBhbnkga2V5IGlzIG1pc3NpbmcuXG4gKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IG9iaiBPYmplY3QgdG8gdHJhdmVyc2UgZm9yIHRoZSBsb29rdXAuXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCBTcGxpdHRlci1kZWxpbWl0ZWQgcGF0aCB0byB0aGUgZGVzaXJlZCB2YWx1ZSAoZS5nLiwgXCJhLmIuY1wiKS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbc3BsaXR0ZXI9T2JqZWN0S2V5U3BsaXR0ZXJdIERlbGltaXRlciB1c2VkIHRvIHNlcGFyYXRlIHRoZSBwYXRoIHNlZ21lbnRzLlxuICogQHJldHVybiB7YW55fHVuZGVmaW5lZH0gVmFsdWUgcmVzb2x2ZWQgYXQgdGhlIGdpdmVuIHBhdGggb3IgYHVuZGVmaW5lZGAgd2hlbiBub3QgZm91bmQuXG4gKiBAZnVuY3Rpb24gZ2V0VmFsdWVCeVNwbGl0dGVyXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEMgYXMgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IEYgYXMgZ2V0VmFsdWVCeVNwbGl0dGVyXG4gKiAgIHBhcnRpY2lwYW50IE8gYXMgT2JqZWN0XG4gKiAgIEMtPj5GOiAob2JqLCBwYXRoLCBzcGxpdHRlcilcbiAqICAgRi0+PkY6IHNwbGl0IHBhdGggaW50byBrZXlzXG4gKiAgIGxvb3AgZm9yIGVhY2gga2V5XG4gKiAgICAgRi0+Pk86IGFjY2VzcyBjdXJyZW50W2tleV1cbiAqICAgICBhbHQgbWlzc2luZyBvciBudWxsaXNoXG4gKiAgICAgICBGLS0+PkM6IHJldHVybiB1bmRlZmluZWRcbiAqICAgICBlbmRcbiAqICAgZW5kXG4gKiAgIEYtLT4+QzogcmV0dXJuIGZpbmFsIHZhbHVlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFZhbHVlQnlTcGxpdHRlcihcbiAgb2JqOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICBwYXRoOiBzdHJpbmcsXG4gIHNwbGl0dGVyOiBzdHJpbmcgPSBPYmplY3RLZXlTcGxpdHRlclxuKTogYW55IHtcbiAgY29uc3Qga2V5cyA9IHBhdGguc3BsaXQoc3BsaXR0ZXIpO1xuICBsZXQgY3VycmVudCA9IG9iajtcblxuICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgaWYgKFxuICAgICAgY3VycmVudCA9PT0gbnVsbCB8fFxuICAgICAgY3VycmVudCA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGN1cnJlbnQsIGtleSlcbiAgICApXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGN1cnJlbnQgPSBjdXJyZW50W2tleV07XG4gIH1cblxuICByZXR1cm4gY3VycmVudDtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU2V0cyBhIG5lc3RlZCB2YWx1ZSBvbiBhbiBvYmplY3QgZ2l2ZW4gYSBwYXRoLlxuICogQHN1bW1hcnkgVHJhdmVyc2VzIG9yIGNyZWF0ZXMgaW50ZXJtZWRpYXRlIG9iamVjdHMgZm9sbG93aW5nIGEgc3BsaXR0ZXItZGVsaW1pdGVkIHBhdGggYW5kIGFzc2lnbnMgdGhlIHByb3ZpZGVkIHZhbHVlIGF0IHRoZSBkZXN0aW5hdGlvbiBrZXkuXG4gKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IG9iaiBPYmplY3QgdG8gbXV0YXRlIHdoaWxlIGRyaWxsaW5nIGludG8gbmVzdGVkIGtleXMuXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCBTcGxpdHRlci1kZWxpbWl0ZWQgZGVzdGluYXRpb24gcGF0aCAoZS5nLiwgXCJhLmIuY1wiKS5cbiAqIEBwYXJhbSB7YW55fSB2YWx1ZSBWYWx1ZSB0byBzZXQgYXQgdGhlIGRlc3RpbmF0aW9uIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gW3NwbGl0dGVyPU9iamVjdEtleVNwbGl0dGVyXSBEZWxpbWl0ZXIgdXNlZCB0byBzZXBhcmF0ZSB0aGUgcGF0aCBzZWdtZW50cy5cbiAqIEByZXR1cm4ge3ZvaWR9XG4gKiBAZnVuY3Rpb24gc2V0VmFsdWVCeVNwbGl0dGVyXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEMgYXMgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IEYgYXMgc2V0VmFsdWVCeVNwbGl0dGVyXG4gKiAgIHBhcnRpY2lwYW50IE8gYXMgT2JqZWN0XG4gKiAgIEMtPj5GOiAob2JqLCBwYXRoLCB2YWx1ZSwgc3BsaXR0ZXIpXG4gKiAgIEYtPj5GOiBzcGxpdCBwYXRoIGludG8ga2V5c1xuICogICBsb29wIGZvciBlYWNoIGtleVxuICogICAgIGFsdCBrZXkgbWlzc2luZ1xuICogICAgICAgRi0+Pk86IGNyZWF0ZSBpbnRlcm1lZGlhdGUgb2JqZWN0XG4gKiAgICAgZWxzZSBrZXkgZXhpc3RzXG4gKiAgICAgICBGLT4+TzogZGVzY2VuZCBpbnRvIGV4aXN0aW5nIG9iamVjdFxuICogICAgIGVuZFxuICogICBlbmRcbiAqICAgRi0tPj5DOiB2b2lkXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldFZhbHVlQnlTcGxpdHRlcihcbiAgb2JqOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICBwYXRoOiBzdHJpbmcsXG4gIHZhbHVlOiBhbnksXG4gIHNwbGl0dGVyID0gT2JqZWN0S2V5U3BsaXR0ZXJcbik6IHZvaWQge1xuICBjb25zdCBrZXlzID0gcGF0aC5zcGxpdChzcGxpdHRlcikuZmlsdGVyKChrKSA9PiBrLmxlbmd0aCA+IDApO1xuICBpZiAoa2V5cy5sZW5ndGggPT09IDApIHJldHVybjtcblxuICBsZXQgY3VycmVudDogUmVjb3JkPGFueSwgYW55PiA9IG9iajtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGtleXMubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgY29uc3Qga2V5ID0ga2V5c1tpXTtcbiAgICBpZiAoXG4gICAgICBjdXJyZW50W2tleV0gPT09IHVuZGVmaW5lZCB8fFxuICAgICAgY3VycmVudFtrZXldID09PSBudWxsIHx8XG4gICAgICB0eXBlb2YgY3VycmVudFtrZXldICE9PSBcIm9iamVjdFwiXG4gICAgKSB7XG4gICAgICBjdXJyZW50W2tleV0gPSB7fTtcbiAgICB9XG4gICAgY3VycmVudCA9IGN1cnJlbnRba2V5XTtcbiAgfVxuXG4gIGNvbnN0IGxhc3RLZXkgPSBrZXlzW2tleXMubGVuZ3RoIC0gMV07XG4gIGN1cnJlbnRbbGFzdEtleV0gPSB2YWx1ZTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ2VudHJhbGl6ZWQgcnVudGltZSBtZXRhZGF0YSBzdG9yZSBib3VuZCB0byBjb25zdHJ1Y3RvcnMuXG4gKiBAc3VtbWFyeSBQcm92aWRlcyB1dGlsaXRpZXMgdG8gcmVhZCBhbmQgd3JpdGUgc3RydWN0dXJlZCBtZXRhZGF0YSBmb3IgY2xhc3NlcyBhbmQgdGhlaXIgbWVtYmVycywgd2l0aCBvcHRpb25hbCBtaXJyb3Jpbmcgb250byB0aGUgY29uc3RydWN0b3IgdmlhIGEgd2VsbC1rbm93biBzeW1ib2wga2V5LiBTdXBwb3J0cyBuZXN0ZWQga2V5IHBhdGhzIHVzaW5nIGEgY29uZmlndXJhYmxlIHNwbGl0dGVyIGFuZCBvZmZlcnMgYm90aCBpbnN0YW5jZSBhbmQgc3RhdGljIEFQSXMuXG4gKiBAdGVtcGxhdGUgTSBUaGUgbW9kZWwgdHlwZSB0aGUgbWV0YWRhdGEgYmVsb25ncyB0by5cbiAqIEB0ZW1wbGF0ZSBNRVRBIEV4dGVuZHMgQmFzaWNNZXRhZGF0YTxNPiByZXByZXNlbnRpbmcgdGhlIG1ldGFkYXRhIHN0cnVjdHVyZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbZmxhdm91cj1EZWZhdWx0Rmxhdm91cl0gT3B0aW9uYWwgZmxhdm91ciBpZGVudGlmaWVyIGFwcGxpZWQgd2hlbiBpbnN0YW50aWF0aW5nIGhlbHBlciBidWlsZGVycy5cbiAqIEBjbGFzc1xuICogQGV4YW1wbGVcbiAqIC8vIERlZmluZSBhbmQgcmVhZCBtZXRhZGF0YSBmb3IgYSBjbGFzc1xuICogY2xhc3MgVXNlciB7IG5hbWUhOiBzdHJpbmcgfVxuICogTWV0YWRhdGEuc2V0KFVzZXIsIFwiZGVzY3JpcHRpb24uY2xhc3NcIiwgXCJBIHVzZXIgbW9kZWxcIik7XG4gKiBNZXRhZGF0YS5zZXQoVXNlciwgXCJwcm9wZXJ0aWVzLm5hbWVcIiwgU3RyaW5nKTtcbiAqIGNvbnN0IGRlc2MgPSBNZXRhZGF0YS5nZXQoVXNlciwgXCJkZXNjcmlwdGlvbi5jbGFzc1wiKTsgLy8gXCJBIHVzZXIgbW9kZWxcIlxuICogY29uc3QgdHlwZSA9IE1ldGFkYXRhLnR5cGUoVXNlciwgXCJuYW1lXCIpOyAvLyBTdHJpbmdcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQyBhcyBDb25zdHJ1Y3RvclxuICogICBwYXJ0aWNpcGFudCBTIGFzIE1ldGFkYXRhIChzdGF0aWMpXG4gKiAgIEMtPj5TOiBzZXQoVXNlciwgXCJwcm9wZXJ0aWVzLm5hbWVcIiwgU3RyaW5nKVxuICogICBDLT4+UzogZ2V0KFVzZXIsIFwicHJvcGVydGllcy5uYW1lXCIpXG4gKiAgIFMtLT4+QzogU3RyaW5nXG4gKi9cbmV4cG9ydCBjbGFzcyBNZXRhZGF0YSB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSW4tbWVtb3J5IHN0b3JhZ2Ugb2YgbWV0YWRhdGEgYnkgY29uc3RydWN0b3Igc3ltYm9sXG4gICAqIEBzdW1tYXJ5IE1hcHMgYSBTeW1ib2wgZGVyaXZlZCBmcm9tIHRoZSBjb25zdHJ1Y3RvciB0byBpdHMgbWV0YWRhdGEgb2JqZWN0LCBlbmFibGluZyBlZmZpY2llbnQgbG9va3VwLlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgX21ldGFkYXRhOiBSZWNvcmQ8c3ltYm9sLCBhbnk+ID0ge307XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQYXRoIGRlbGltaXRlciBmb3IgbmVzdGVkIG1ldGFkYXRhIGtleXNcbiAgICogQHN1bW1hcnkgVXNlZCBieSBnZXQvc2V0IG9wZXJhdGlvbnMgdG8gbmF2aWdhdGUgbmVzdGVkIHN0cnVjdHVyZXMsIGRlZmF1bHRzIHRvIE9iamVjdEtleVNwbGl0dGVyLlxuICAgKi9cbiAgc3RhdGljIHNwbGl0dGVyID0gT2JqZWN0S2V5U3BsaXR0ZXI7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3ltYm9sIGtleSB1c2VkIHRvIG1pcnJvciBtZXRhZGF0YSBvbiB0aGUgY29uc3RydWN0b3JcbiAgICogQHN1bW1hcnkgV2hlbiBtaXJyb3JpbmcgaXMgZW5hYmxlZCwgdGhlIG1ldGFkYXRhIG9iamVjdCBpcyBkZWZpbmVkIG9uIHRoZSBjb25zdHJ1Y3RvciB1bmRlciB0aGlzIG5vbi1lbnVtZXJhYmxlIGtleS5cbiAgICovXG4gIHN0YXRpYyBiYXNlS2V5ID0gRGVjb3JhdGlvbktleXMuUkVGTEVDVDtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDb250cm9scyB3aGV0aGVyIG1ldGFkYXRhIGlzIG1pcnJvcmVkIG9udG8gdGhlIGNvbnN0cnVjdG9yXG4gICAqIEBzdW1tYXJ5IFdoZW4gdHJ1ZSwgdGhlIG1ldGFkYXRhIG9iamVjdCBpcyBkZWZpbmVkIG9uIHRoZSBjb25zdHJ1Y3RvciB1bmRlciB0aGUgbm9uLWVudW1lcmFibGUgYmFzZUtleS5cbiAgICovXG4gIHN0YXRpYyBtaXJyb3I6IGJvb2xlYW4gPSB0cnVlO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoKSB7fVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTGlzdHMga25vd24gcHJvcGVydHkga2V5cyBmb3IgYSBtb2RlbC5cbiAgICogQHN1bW1hcnkgUmVhZHMgdGhlIG1ldGFkYXRhIGVudHJ5IGFuZCByZXR1cm5zIHRoZSBuYW1lcyBvZiBwcm9wZXJ0aWVzIHRoYXQgaGF2ZSByZWNvcmRlZCB0eXBlIGluZm9ybWF0aW9uLlxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yfSBtb2RlbCBUYXJnZXQgY29uc3RydWN0b3Igd2hvc2UgcHJvcGVydHkgbWV0YWRhdGEgc2hvdWxkIGJlIGluc3BlY3RlZC5cbiAgICogQHJldHVybiB7c3RyaW5nW118dW5kZWZpbmVkfSBBcnJheSBvZiBwcm9wZXJ0eSBuYW1lcyBvciBgdW5kZWZpbmVkYCBpZiBubyBtZXRhZGF0YSBleGlzdHMuXG4gICAqL1xuICBzdGF0aWMgcHJvcGVydGllcyhtb2RlbDogQ29uc3RydWN0b3IpOiBzdHJpbmdbXSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgbWV0YSA9IHRoaXMuZ2V0KG1vZGVsKTtcbiAgICBpZiAoIW1ldGEpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKG1ldGEucHJvcGVydGllcyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExpc3RzIGtub3duIG1ldGhvZHMgZm9yIGEgbW9kZWwuXG4gICAqIEBzdW1tYXJ5IFJlYWRzIHRoZSBtZXRhZGF0YSBlbnRyeSBhbmQgcmV0dXJucyB0aGUgbWV0aG9kIG5hbWVzIHRoYXQgaGF2ZSByZWNvcmRlZCBzaWduYXR1cmUgbWV0YWRhdGEgZm9yIHRoZSBwcm92aWRlZCBjb25zdHJ1Y3Rvci5cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3Rvcn0gbW9kZWwgVGFyZ2V0IGNvbnN0cnVjdG9yIHdob3NlIG1ldGhvZCBtZXRhZGF0YSBzaG91bGQgYmUgaW5zcGVjdGVkLlxuICAgKiBAcmV0dXJuIHtzdHJpbmdbXXx1bmRlZmluZWR9IEFycmF5IG9mIG1ldGhvZCBuYW1lcyBvciBgdW5kZWZpbmVkYCBpZiBubyBtZXRhZGF0YSBleGlzdHMuXG4gICAqL1xuICBzdGF0aWMgbWV0aG9kcyhtb2RlbDogQ29uc3RydWN0b3IpOiBzdHJpbmdbXSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgbWV0YSA9IHRoaXMuZ2V0KG1vZGVsLCBEZWNvcmF0aW9uS2V5cy5NRVRIT0RTKTtcbiAgICBpZiAoIW1ldGEpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKG1ldGEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYSBodW1hbi1yZWFkYWJsZSBkZXNjcmlwdGlvbiBmb3IgYSBjbGFzcyBvciBhIHByb3BlcnR5LlxuICAgKiBAc3VtbWFyeSBMb29rcyB1cCB0aGUgZGVzY3JpcHRpb24gc3RvcmVkIHVuZGVyIHRoZSBtZXRhZGF0YSBcImRlc2NyaXB0aW9uXCIgbWFwLiBJZiBhIHByb3BlcnR5IGtleSBpcyBwcm92aWRlZCwgcmV0dXJucyB0aGUgcHJvcGVydHkncyBkZXNjcmlwdGlvbjsgb3RoZXJ3aXNlIHJldHVybnMgdGhlIGNsYXNzIGRlc2NyaXB0aW9uLlxuICAgKiBAdGVtcGxhdGUgTVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCBUYXJnZXQgY29uc3RydWN0b3Igd2hvc2UgZGVzY3JpcHRpb24gaXMgYmVpbmcgcmV0cmlldmVkLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3Byb3BdIE9wdGlvbmFsIHByb3BlcnR5IGtleSAodHlwZWQgYXMgYGtleW9mIE1gKSBmb3Igd2hpY2ggdG8gZmV0Y2ggdGhlIGRlc2NyaXB0aW9uLlxuICAgKiBAcmV0dXJuIHtzdHJpbmd8dW5kZWZpbmVkfSBEZXNjcmlwdGlvbiB0ZXh0IGlmIHByZXNlbnQsIG90aGVyd2lzZSBgdW5kZWZpbmVkYC5cbiAgICovXG4gIHN0YXRpYyBkZXNjcmlwdGlvbjxNPihcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8TT4sXG4gICAgcHJvcD86IGtleW9mIE1cbiAgKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5nZXQoXG4gICAgICBtb2RlbCxcbiAgICAgIFtEZWNvcmF0aW9uS2V5cy5ERVNDUklQVElPTiwgcHJvcCA/IHByb3AgOiBEZWNvcmF0aW9uS2V5cy5DTEFTU10uam9pbihcbiAgICAgICAgdGhpcy5zcGxpdHRlclxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyB0aGUgcmVjb3JkZWQgcGFyYW1zIGZvciBhIG1ldGhvZC5cbiAgICogQHN1bW1hcnkgUmVhZHMgdGhlIG1ldGFkYXRhIGVudHJ5IHVuZGVyIGBtZXRob2RzLjxwcm9wPi5kZXNpZ246cGFyYW10eXBlc2AgdG8gcmV0dXJuIHRoZSBwYXJhbWV0ZXIgY29uc3RydWN0b3JzIGZvciB0aGUgZ2l2ZW4gbWV0aG9kLlxuICAgKiBAdGVtcGxhdGUgTVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCBUYXJnZXQgY29uc3RydWN0b3Igb3duaW5nIHRoZSBtZXRob2QgbWV0YWRhdGEuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wIE1ldGhvZCBuYW1lIHdob3NlIHBhcmFtZXRlcnMgc2hvdWxkIGJlIGZldGNoZWQuXG4gICAqIEByZXR1cm4ge2FueVtdfHVuZGVmaW5lZH0gQXJyYXkgb2YgY29uc3RydWN0b3IgcmVmZXJlbmNlcyBkZXNjcmliaW5nIGVhY2ggcGFyYW1ldGVyIG9yIGB1bmRlZmluZWRgIHdoZW4gbm90IGF2YWlsYWJsZS5cbiAgICovXG4gIHN0YXRpYyBwYXJhbXM8TT4obW9kZWw6IENvbnN0cnVjdG9yPE0+LCBwcm9wOiBzdHJpbmcpOiBhbnlbXSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KFxuICAgICAgbW9kZWwsXG4gICAgICBbRGVjb3JhdGlvbktleXMuTUVUSE9EUywgcHJvcCwgRGVjb3JhdGlvbktleXMuREVTSUdOX1BBUkFNU10uam9pbihcbiAgICAgICAgdGhpcy5zcGxpdHRlclxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhIHNpbmdsZSByZWNvcmRlZCBwYXJhbWV0ZXIgdHlwZSBmb3IgYSBtZXRob2QuXG4gICAqIEBzdW1tYXJ5IExvb2tzIHVwIHRoZSBwYXJhbWV0ZXIgbWV0YWRhdGEgZm9yIHRoZSBwcm92aWRlZCBpbmRleCwgZW5mb3JjaW5nIGJvdW5kcyBhbmQgcmV0dXJuaW5nIHRoZSBjb25zdHJ1Y3RvciByZWZlcmVuY2UgZm9yIHRoYXQgYXJndW1lbnQuXG4gICAqIEB0ZW1wbGF0ZSBNXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IG1vZGVsIFRhcmdldCBjb25zdHJ1Y3RvciBvd25pbmcgdGhlIG1ldGhvZCBtZXRhZGF0YS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHByb3AgTWV0aG9kIG5hbWUgd2hvc2UgcGFyYW1ldGVyIHNob3VsZCBiZSByZXR1cm5lZC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGluZGV4IFplcm8tYmFzZWQgaW5kZXggb2YgdGhlIGRlc2lyZWQgcGFyYW1ldGVyIG1ldGFkYXRhLlxuICAgKiBAcmV0dXJuIHthbnl8dW5kZWZpbmVkfSBDb25zdHJ1Y3RvciByZWZlcmVuY2UgZm9yIHRoZSBwYXJhbWV0ZXIgb3IgYHVuZGVmaW5lZGAgaWYgbm90IHJlY29yZGVkLlxuICAgKi9cbiAgc3RhdGljIHBhcmFtPE0+KFxuICAgIG1vZGVsOiBDb25zdHJ1Y3RvcjxNPixcbiAgICBwcm9wOiBzdHJpbmcsXG4gICAgaW5kZXg6IG51bWJlclxuICApOiBhbnkgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHBhcmFtcyA9IHRoaXMucGFyYW1zKG1vZGVsLCBwcm9wKTtcbiAgICBpZiAoIXBhcmFtcykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBpZiAoaW5kZXggPiBwYXJhbXMubGVuZ3RoIC0gMSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFBhcmFtZXRlciBpbmRleCAke2luZGV4fSBvdXQgb2YgcmFuZ2UgZm9yICR7U3RyaW5nKHByb3ApfWBcbiAgICAgICk7XG4gICAgcmV0dXJuIHBhcmFtc1tpbmRleF07XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyB0aGUgcmVjb3JkZWQgcmV0dXJuIHR5cGUgZm9yIGEgbWV0aG9kLlxuICAgKiBAc3VtbWFyeSBSZWFkcyB0aGUgbWV0YWRhdGEgZW50cnkgdW5kZXIgYG1ldGhvZHMuPHByb3A+LmRlc2lnbjpyZXR1cm50eXBlYCB0byByZXR1cm4gdGhlIHJldHVybiB0eXBlIGZvciB0aGUgZ2l2ZW4gbWV0aG9kLlxuICAgKiBAdGVtcGxhdGUgTVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBtb2RlbCBUYXJnZXQgY29uc3RydWN0b3Igd2hvc2UgbWV0aG9kIG1ldGFkYXRhIHNob3VsZCBiZSBpbnNwZWN0ZWQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wIE1ldGhvZCBuYW1lIHdob3NlIHJldHVybiB0eXBlIHNob3VsZCBiZSBmZXRjaGVkLlxuICAgKiBAcmV0dXJuIHthbnl8dW5kZWZpbmVkfSBDb25zdHJ1Y3RvciByZWZlcmVuY2UgZm9yIHRoZSByZXR1cm4gdHlwZSBvciBgdW5kZWZpbmVkYCB3aGVuIG5vdCBhdmFpbGFibGUuXG4gICAqL1xuICBzdGF0aWMgcmV0dXJuPE0+KG1vZGVsOiBDb25zdHJ1Y3RvcjxNPiwgcHJvcDogc3RyaW5nKTogYW55IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5nZXQoXG4gICAgICBtb2RlbCxcbiAgICAgIFtEZWNvcmF0aW9uS2V5cy5NRVRIT0RTLCBwcm9wLCBEZWNvcmF0aW9uS2V5cy5ERVNJR05fUkVUVVJOXS5qb2luKFxuICAgICAgICB0aGlzLnNwbGl0dGVyXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIHRoZSByZWNvcmRlZCBkZXNpZ24gdHlwZSBmb3IgYSBwcm9wZXJ0eS5cbiAgICogQHN1bW1hcnkgUmVhZHMgdGhlIG1ldGFkYXRhIGVudHJ5IHVuZGVyIGBwcm9wZXJ0aWVzLjxwcm9wPmAgdG8gcmV0dXJuIHRoZSBjb25zdHJ1Y3RvciByZWNvcmRlZCBmb3IgdGhlIGdpdmVuIHByb3BlcnR5IG5hbWUuXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3J9IG1vZGVsIFRhcmdldCBjb25zdHJ1Y3RvciB3aG9zZSBwcm9wZXJ0eSBtZXRhZGF0YSBzaG91bGQgYmUgaW5zcGVjdGVkLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcCBQcm9wZXJ0eSBuYW1lIHdob3NlIHR5cGUgbWV0YWRhdGEgc2hvdWxkIGJlIHJldHVybmVkLlxuICAgKiBAcmV0dXJuIHtDb25zdHJ1Y3Rvcnx1bmRlZmluZWR9IENvbnN0cnVjdG9yIHJlZmVyZW5jZSBmb3IgdGhlIHByb3BlcnR5IHR5cGUgb3IgYHVuZGVmaW5lZGAgaWYgbm90IGF2YWlsYWJsZS5cbiAgICovXG4gIHN0YXRpYyB0eXBlKG1vZGVsOiBDb25zdHJ1Y3RvciwgcHJvcDogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KFxuICAgICAgbW9kZWwsXG4gICAgICBbRGVjb3JhdGlvbktleXMuUFJPUEVSVElFUywgcHJvcF0uam9pbih0aGlzLnNwbGl0dGVyKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlc29sdmVzIHRoZSBjYW5vbmljYWwgY29uc3RydWN0b3IgYXNzb2NpYXRlZCB3aXRoIHRoZSBwcm92aWRlZCBtb2RlbCBoYW5kbGUuXG4gICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIHN0b3JlZCBjb25zdHJ1Y3RvciByZWZlcmVuY2Ugd2hlbiB0aGUgcHJvdmlkZWQgbW9kZWwgaXMgYSBwcm94eSBvciByZWR1Y2VkIHZhbHVlLiBGYWxscyBiYWNrIHRvIHRoZSBvcmlnaW5hbCBtb2RlbCB3aGVuIG5vIGNvbnN0cnVjdG9yIG1ldGFkYXRhIGhhcyBiZWVuIHJlY29yZGVkIHlldC5cbiAgICogQHRlbXBsYXRlIE1cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgTW9kZWwgdXNlZCB3aGVuIHJlY29yZGluZyBtZXRhZGF0YS5cbiAgICogQHJldHVybiB7Q29uc3RydWN0b3I8TT58dW5kZWZpbmVkfSBDYW5vbmljYWwgY29uc3RydWN0b3IgaWYgc3RvcmVkLCBvdGhlcndpc2UgYHVuZGVmaW5lZGAuXG4gICAqL1xuICBzdGF0aWMgY29uc3RyPE0+KG1vZGVsOiBDb25zdHJ1Y3RvcjxNPikge1xuICAgIHJldHVybiB0aGlzLmdldChtb2RlbCwgRGVjb3JhdGlvbktleXMuQ09OU1RSVUNUT1IpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgbWV0YWRhdGEgZm9yIGEgbW9kZWwgb3IgYSBzcGVjaWZpYyBrZXkgd2l0aGluIGl0LlxuICAgKiBAc3VtbWFyeSBXaGVuIGNhbGxlZCB3aXRoIGEgY29uc3RydWN0b3Igb25seSwgcmV0dXJucyB0aGUgZW50aXJlIG1ldGFkYXRhIG9iamVjdCBhc3NvY2lhdGVkIHdpdGggdGhlIG1vZGVsLiBXaGVuIGEga2V5IHBhdGggaXMgcHJvdmlkZWQsIHJldHVybnMgdGhlIHZhbHVlIHN0b3JlZCBhdCB0aGF0IG5lc3RlZCBrZXkuXG4gICAqIEB0ZW1wbGF0ZSBNXG4gICAqIEB0ZW1wbGF0ZSBNRVRBXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IG1vZGVsIFRhcmdldCBjb25zdHJ1Y3RvciB1c2VkIHRvIGxvY2F0ZSB0aGUgbWV0YWRhdGEgcmVjb3JkLlxuICAgKiBAcmV0dXJuIHtNRVRBfHVuZGVmaW5lZH0gTWV0YWRhdGEgb2JqZWN0LCB0aGUgdmFsdWUgYXQgdGhlIGtleSBwYXRoLCBvciBgdW5kZWZpbmVkYCBpZiBub3RoaW5nIGV4aXN0cy5cbiAgICovXG4gIHN0YXRpYyBnZXQ8TSwgTUVUQSBleHRlbmRzIEJhc2ljTWV0YWRhdGE8TT4gPSBCYXNpY01ldGFkYXRhPE0+PihcbiAgICBtb2RlbDogQ29uc3RydWN0b3I8TT5cbiAgKTogTUVUQSB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgbWV0YWRhdGEgZm9yIGEgbW9kZWwgb3IgYSBzcGVjaWZpYyBrZXkgd2l0aGluIGl0LlxuICAgKiBAc3VtbWFyeSBXaGVuIGNhbGxlZCB3aXRoIGEgY29uc3RydWN0b3Igb25seSwgcmV0dXJucyB0aGUgZW50aXJlIG1ldGFkYXRhIG9iamVjdCBhc3NvY2lhdGVkIHdpdGggdGhlIG1vZGVsLiBXaGVuIGEga2V5IHBhdGggaXMgcHJvdmlkZWQsIHJldHVybnMgdGhlIHZhbHVlIHN0b3JlZCBhdCB0aGF0IG5lc3RlZCBrZXkuXG4gICAqIEB0ZW1wbGF0ZSBNXG4gICAqIEB0ZW1wbGF0ZSBNRVRBXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IG1vZGVsIFRhcmdldCBjb25zdHJ1Y3RvciB1c2VkIHRvIGxvY2F0ZSB0aGUgbWV0YWRhdGEgcmVjb3JkLlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IE5lc3RlZCBrZXkgcGF0aCB0byBmZXRjaCBhIHNwZWNpZmljIHZhbHVlLlxuICAgKiBAcmV0dXJuIHtNRVRBfCp8dW5kZWZpbmVkfSBNZXRhZGF0YSBvYmplY3QsIHRoZSB2YWx1ZSBhdCB0aGUga2V5IHBhdGgsIG9yIGB1bmRlZmluZWRgIGlmIG5vdGhpbmcgZXhpc3RzLlxuICAgKi9cbiAgc3RhdGljIGdldChtb2RlbDogQ29uc3RydWN0b3IsIGtleTogc3RyaW5nKTogYW55O1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBtZXRhZGF0YSBmb3IgYSBtb2RlbCBvciBhIHNwZWNpZmljIGtleSB3aXRoaW4gaXQuXG4gICAqIEBzdW1tYXJ5IFdoZW4gY2FsbGVkIHdpdGggYSBjb25zdHJ1Y3RvciBvbmx5LCByZXR1cm5zIHRoZSBlbnRpcmUgbWV0YWRhdGEgb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGUgbW9kZWwuIFdoZW4gYSBrZXkgcGF0aCBpcyBwcm92aWRlZCwgcmV0dXJucyB0aGUgdmFsdWUgc3RvcmVkIGF0IHRoYXQgbmVzdGVkIGtleS5cbiAgICogQHRlbXBsYXRlIE1cbiAgICogQHRlbXBsYXRlIE1FVEFcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPnxzdHJpbmd9IG1vZGVsIFRhcmdldCBjb25zdHJ1Y3RvciB1c2VkIHRvIGxvY2F0ZSB0aGUgbWV0YWRhdGEgcmVjb3JkIG9yIGEgcHJlLXJlc29sdmVkIHN5bWJvbCBpZGVudGlmaWVyLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2tleV0gT3B0aW9uYWwgbmVzdGVkIGtleSBwYXRoIHRvIGZldGNoIGEgc3BlY2lmaWMgdmFsdWUuXG4gICAqIEByZXR1cm4ge01FVEF8Knx1bmRlZmluZWR9IE1ldGFkYXRhIG9iamVjdCwgdGhlIHZhbHVlIGF0IHRoZSBrZXkgcGF0aCwgb3IgYHVuZGVmaW5lZGAgaWYgbm90aGluZyBleGlzdHMuXG4gICAqL1xuICBzdGF0aWMgZ2V0KG1vZGVsOiBDb25zdHJ1Y3Rvciwga2V5Pzogc3RyaW5nKSB7XG4gICAgaWYgKGtleSAhPT0gRGVjb3JhdGlvbktleXMuQ09OU1RSVUNUT1IpIG1vZGVsID0gdGhpcy5jb25zdHIobW9kZWwpIHx8IG1vZGVsO1xuICAgIGNvbnN0IHN5bWJvbCA9IFN5bWJvbC5mb3IobW9kZWwudG9TdHJpbmcoKSk7XG4gICAgcmV0dXJuIHRoaXMuaW5uZXJHZXQoc3ltYm9sLCBrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgbWV0YWRhdGEgc3RvcmVkIHVuZGVyIGEgc3ltYm9sIGtleS5cbiAgICogQHN1bW1hcnkgSW50ZXJuYWwgaGVscGVyIHRoYXQgcmVzb2x2ZXMgYW5kIG9wdGlvbmFsbHkgZHJpbGxzIGludG8gdGhlIGluLW1lbW9yeSBtZXRhZGF0YSBtYXAgZm9yIHRoZSBwcm92aWRlZCBzeW1ib2wgYW5kIGtleSBwYXRoLlxuICAgKiBAcGFyYW0ge3N5bWJvbH0gc3ltYm9sIFN5bWJvbCByZXByZXNlbnRpbmcgdGhlIG1ldGFkYXRhIGJ1Y2tldC5cbiAgICogQHBhcmFtIHtzdHJpbmd8c3ltYm9sfSBba2V5XSBPcHRpb25hbCBuZXN0ZWQga2V5IHJlZmVyZW5jaW5nIGEgc3BlY2lmaWMgbWV0YWRhdGEgZW50cnkuXG4gICAqIEByZXR1cm4ge2FueX0gU3RvcmVkIG1ldGFkYXRhIG9iamVjdCBvciB2YWx1ZSBmb3IgdGhlIHByb3ZpZGVkIGtleSwgb3IgYHVuZGVmaW5lZGAgd2hlbiBhYnNlbnQuXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBpbm5lckdldChzeW1ib2w6IHN5bWJvbCwga2V5Pzogc3RyaW5nIHwgc3ltYm9sKSB7XG4gICAgaWYgKCF0aGlzLl9tZXRhZGF0YVtzeW1ib2xdKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmICgha2V5KSByZXR1cm4gdGhpcy5fbWV0YWRhdGFbc3ltYm9sXTtcbiAgICBpZiAodHlwZW9mIGtleSA9PT0gXCJzdHJpbmdcIilcbiAgICAgIHJldHVybiBnZXRWYWx1ZUJ5U3BsaXR0ZXIodGhpcy5fbWV0YWRhdGFbc3ltYm9sXSwga2V5LCB0aGlzLnNwbGl0dGVyKTtcbiAgICByZXR1cm4gdGhpcy5fbWV0YWRhdGFbc3ltYm9sXVtrZXldO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBXcml0ZXMgbWV0YWRhdGEgdW5kZXIgYSBzeW1ib2wga2V5LlxuICAgKiBAc3VtbWFyeSBJbnRlcm5hbCBoZWxwZXIgdGhhdCBlbnN1cmVzIHRoZSBtZXRhZGF0YSBidWNrZXQgZXhpc3RzIGZvciB0aGUgcHJvdmlkZWQgc3ltYm9sIGFuZCBwZXJzaXN0cyB0aGUgZ2l2ZW4gdmFsdWUsIGRyaWxsaW5nIGludG8gbmVzdGVkIHN0cnVjdHVyZXMgd2hlbiB0aGUga2V5IGlzIGEgc3RyaW5nIHBhdGguXG4gICAqIEBwYXJhbSB7c3ltYm9sfSBzeW1ib2wgU3ltYm9sIHJlcHJlc2VudGluZyB0aGUgbWV0YWRhdGEgYnVja2V0LlxuICAgKiBAcGFyYW0ge3N0cmluZ3xzeW1ib2x9IGtleSBOZXN0ZWQga2V5IHBhdGggb3IgZGlyZWN0IHN5bWJvbCB1bmRlciB3aGljaCB0byBzdG9yZSB0aGUgbWV0YWRhdGEgdmFsdWUuXG4gICAqIEBwYXJhbSB7YW55fSB2YWx1ZSBWYWx1ZSBwZXJzaXN0ZWQgaW4gdGhlIG1ldGFkYXRhIHN0b3JlLlxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgaW5uZXJTZXQoc3ltYm9sOiBzeW1ib2wsIGtleTogc3RyaW5nIHwgc3ltYm9sLCB2YWx1ZTogYW55KSB7XG4gICAgaWYgKCF0aGlzLl9tZXRhZGF0YVtzeW1ib2xdKSB0aGlzLl9tZXRhZGF0YVtzeW1ib2xdID0ge30gYXMgYW55O1xuICAgIGlmICh0eXBlb2Yga2V5ID09PSBcInN0cmluZ1wiKVxuICAgICAgcmV0dXJuIHNldFZhbHVlQnlTcGxpdHRlcihcbiAgICAgICAgdGhpcy5fbWV0YWRhdGFbc3ltYm9sXSxcbiAgICAgICAga2V5LFxuICAgICAgICB2YWx1ZSxcbiAgICAgICAgdGhpcy5zcGxpdHRlclxuICAgICAgKTtcbiAgICB0aGlzLl9tZXRhZGF0YVtzeW1ib2xdW2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gV3JpdGVzIGEgbWV0YWRhdGEgdmFsdWUgYXQgYSBnaXZlbiBuZXN0ZWQga2V5IHBhdGguXG4gICAqIEBzdW1tYXJ5IEVuc3VyZXMgdGhlIG1ldGFkYXRhIHJlY29yZCBleGlzdHMgZm9yIHRoZSBjb25zdHJ1Y3RvciwgbWlycm9ycyBpdCBvbiB0aGUgY29uc3RydWN0b3Igd2hlbiBlbmFibGVkLCBhbmQgc2V0cyB0aGUgcHJvdmlkZWQgdmFsdWUgb24gdGhlIG5lc3RlZCBrZXkgcGF0aCB1c2luZyB0aGUgY29uZmlndXJlZCBzcGxpdHRlci5cbiAgICogQHRlbXBsYXRlIE1cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPnxzdHJpbmd9IG1vZGVsIFRhcmdldCBjb25zdHJ1Y3RvciB0byB3aGljaCB0aGUgbWV0YWRhdGEgYmVsb25ncyBvciBhIGRpcmVjdCBpZGVudGlmaWVyIHN0cmluZy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBOZXN0ZWQga2V5IHBhdGggYXQgd2hpY2ggdG8gc3RvcmUgdGhlIHZhbHVlLlxuICAgKiBAcGFyYW0ge2FueX0gdmFsdWUgVmFsdWUgdG8gc3RvcmUgaW4gdGhlIG1ldGFkYXRhLlxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgc3RhdGljIHNldChtb2RlbDogQ29uc3RydWN0b3IgfCBzdHJpbmcsIGtleTogc3RyaW5nLCB2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgaWYgKHR5cGVvZiBtb2RlbCAhPT0gXCJzdHJpbmdcIikgbW9kZWwgPSB0aGlzLmNvbnN0cihtb2RlbCkgfHwgbW9kZWw7XG4gICAgY29uc3Qgc3ltYm9sID0gU3ltYm9sLmZvcihtb2RlbC50b1N0cmluZygpKTtcbiAgICB0aGlzLmlubmVyU2V0KHN5bWJvbCwga2V5LCB2YWx1ZSk7XG4gICAgaWYgKFxuICAgICAgTWV0YWRhdGEubWlycm9yICYmXG4gICAgICAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1vZGVsLCB0aGlzLmJhc2VLZXkpXG4gICAgKSB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobW9kZWwsIHRoaXMuYmFzZUtleSwge1xuICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiBmYWxzZSxcbiAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgICB2YWx1ZTogdGhpcy5fbWV0YWRhdGFbc3ltYm9sXSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVnaXN0ZXJzIGEgZGVjb3JhdGlvbi1hd2FyZSBsaWJyYXJ5IGFuZCBpdHMgdmVyc2lvbi5cbiAgICogQHN1bW1hcnkgU3RvcmVzIHRoZSB2ZXJzaW9uIHN0cmluZyBmb3IgYW4gaW50ZWdyYXRpbmcgbGlicmFyeSB1bmRlciB0aGUgc2hhcmVkIGxpYnJhcmllcyBtZXRhZGF0YSBzeW1ib2wsIHByZXZlbnRpbmcgZHVwbGljYXRlIHJlZ2lzdHJhdGlvbnMgZm9yIHRoZSBzYW1lIGxpYnJhcnkgaWRlbnRpZmllci5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGxpYnJhcnkgUGFja2FnZSBuYW1lIG9yIGlkZW50aWZpZXIgdG8gcmVnaXN0ZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB2ZXJzaW9uIFNlbWFudGljIHZlcnNpb24gc3RyaW5nIGFzc29jaWF0ZWQgd2l0aCB0aGUgbGlicmFyeS5cbiAgICogQHJldHVybiB7dm9pZH1cbiAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBsaWJyYXJ5IGhhcyBhbHJlYWR5IGJlZW4gcmVnaXN0ZXJlZC5cbiAgICovXG4gIHN0YXRpYyByZWdpc3RlckxpYnJhcnkobGlicmFyeTogc3RyaW5nLCB2ZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zdCBzeW1ib2wgPSBTeW1ib2wuZm9yKERlY29yYXRpb25LZXlzLkxJQlJBUklFUyk7XG4gICAgY29uc3QgbGliID0gdGhpcy5pbm5lckdldChzeW1ib2wsIGxpYnJhcnkpO1xuICAgIGlmIChsaWIpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBMaWJyYXJ5IGFscmVhZHkgJHtsaWJyYXJ5fSByZWdpc3RlcmVkIHdpdGggdmVyc2lvbiAke3ZlcnNpb259YFxuICAgICAgKTtcbiAgICB0aGlzLmlubmVyU2V0KHN5bWJvbCwgbGlicmFyeSwgdmVyc2lvbik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExpc3RzIHJlZ2lzdGVyZWQgZGVjb3JhdGlvbi1hd2FyZSBsaWJyYXJpZXMuXG4gICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIGluLW1lbW9yeSBtYXAgb2YgbGlicmFyeSBpZGVudGlmaWVycyB0byBzZW1hbnRpYyB2ZXJzaW9ucyB0aGF0IGhhdmUgYmVlbiByZWdpc3RlcmVkIHdpdGggdGhlIERlY29yYXRpb24gbWV0YWRhdGEgc3RvcmUuXG4gICAqIEByZXR1cm4ge1JlY29yZDxzdHJpbmcsIHN0cmluZz59IE1hcCBvZiByZWdpc3RlcmVkIGxpYnJhcnkgaWRlbnRpZmllcnMgdG8gdGhlaXIgdmVyc2lvbiBzdHJpbmdzLlxuICAgKi9cbiAgc3RhdGljIGxpYnJhcmllcygpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgICBjb25zdCBzeW1ib2wgPSBTeW1ib2wuZm9yKERlY29yYXRpb25LZXlzLkxJQlJBUklFUyk7XG4gICAgcmV0dXJuIHRoaXMuaW5uZXJHZXQoc3ltYm9sKSB8fCB7fTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSm9pbnMgcGF0aCBzZWdtZW50cyB1c2luZyB0aGUgY3VycmVudCBzcGxpdHRlci5cbiAgICogQHN1bW1hcnkgQ29uc3RydWN0cyBhIG5lc3RlZCBtZXRhZGF0YSBrZXkgYnkgY29uY2F0ZW5hdGluZyBzdHJpbmcgc2VnbWVudHMgd2l0aCB0aGUgY29uZmlndXJlZCBzcGxpdHRlciBmb3IgdXNlIHdpdGggdGhlIG1ldGFkYXRhIHN0b3JlLlxuICAgKiBAcGFyYW0gey4uLnN0cmluZ30gc3RycyBLZXkgc2VnbWVudHMgdG8gam9pbiBpbnRvIGEgZnVsbCBtZXRhZGF0YSBwYXRoLlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IFNwbGl0dGVyLWpvaW5lZCBtZXRhZGF0YSBrZXkuXG4gICAqL1xuICBzdGF0aWMga2V5KC4uLnN0cnM6IHN0cmluZ1tdKSB7XG4gICAgcmV0dXJuIHN0cnMuam9pbih0aGlzLnNwbGl0dGVyKTtcbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgRGVjb3JhdGlvbkJ1aWxkZXJCdWlsZCxcbiAgRGVjb3JhdGlvbkJ1aWxkZXJFbmQsXG4gIERlY29yYXRpb25CdWlsZGVyTWlkLFxuICBEZWNvcmF0aW9uQnVpbGRlclN0YXJ0LFxuICBGbGF2b3VyUmVzb2x2ZXIsXG4gIElEZWNvcmF0aW9uQnVpbGRlcixcbn0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IERlZmF1bHRGbGF2b3VyIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZhdWx0IHJlc29sdmVyIHRoYXQgcmV0dXJucyB0aGUgY3VycmVudCBkZWZhdWx0IGZsYXZvdXIuXG4gKiBAc3VtbWFyeSBSZXNvbHZlcyB0aGUgZmxhdm91ciBmb3IgYSBnaXZlbiB0YXJnZXQgYnkgYWx3YXlzIHJldHVybmluZyB0aGUgbGlicmFyeSdzIGBEZWZhdWx0Rmxhdm91cmAgdmFsdWUuXG4gKiBAcGFyYW0ge29iamVjdH0gdGFyZ2V0IFRhcmdldCBvYmplY3QgYmVpbmcgZGVjb3JhdGVkLlxuICogQHJldHVybiB7c3RyaW5nfSBSZXNvbHZlZCBmbGF2b3VyIGlkZW50aWZpZXIuXG4gKiBAZnVuY3Rpb24gZGVmYXVsdEZsYXZvdXJSZXNvbHZlclxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbmZ1bmN0aW9uIGRlZmF1bHRGbGF2b3VyUmVzb2x2ZXIodGFyZ2V0OiBvYmplY3QpIHtcbiAgcmV0dXJuIERlZmF1bHRGbGF2b3VyO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBVbmlvbiB0eXBlIGNvdmVyaW5nIHN1cHBvcnRlZCBkZWNvcmF0b3Iga2luZHMuXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGFueSBvZiB0aGUgc3RhbmRhcmQgVHlwZVNjcmlwdCBkZWNvcmF0b3Igc2lnbmF0dXJlcyAoY2xhc3MsIHByb3BlcnR5LCBvciBtZXRob2QpLCBlbmFibGluZyBmbGV4aWJsZSByZWdpc3RyYXRpb24gYW5kIGFwcGxpY2F0aW9uIHdpdGhpbiB0aGUgRGVjb3JhdGlvbiBzeXN0ZW0uXG4gKiBAdGVtcGxhdGUgVFxuICogQHR5cGVEZWYgRGVjb3JhdG9yVHlwZXNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdGlvblxuICovXG5leHBvcnQgdHlwZSBEZWNvcmF0b3JUeXBlcyA9XG4gIHwgQ2xhc3NEZWNvcmF0b3JcbiAgfCBQcm9wZXJ0eURlY29yYXRvclxuICB8IE1ldGhvZERlY29yYXRvcjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gVHlwZSBkZWZpbml0aW9uIGZvciBhIGRlY29yYXRvciBmYWN0b3J5IGZ1bmN0aW9uLlxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhIGZ1bmN0aW9uIHRoYXQgYWNjZXB0cyBhcmJpdHJhcnkgYXJndW1lbnRzIGFuZCByZXR1cm5zIGEgY29uY3JldGUgZGVjb3JhdG9yIGZ1bmN0aW9uIHRvIGJlIGFwcGxpZWQgdG8gYSB0YXJnZXQuXG4gKiBAdGVtcGxhdGUgQVxuICogQHR5cGVEZWYgRGVjb3JhdG9yRmFjdG9yeVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCB0eXBlIERlY29yYXRvckZhY3RvcnkgPSAoLi4uYXJnczogYW55W10pID0+IERlY29yYXRvclR5cGVzO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBcmd1bWVudCBidW5kbGUgZm9yIGEgZGVjb3JhdG9yIGZhY3RvcnkuXG4gKiBAc3VtbWFyeSBPYmplY3QgZm9ybSB1c2VkIHRvIGRlZmVyIGRlY29yYXRvciBjcmVhdGlvbiwgY2FycnlpbmcgYm90aCB0aGUgZmFjdG9yeSBmdW5jdGlvbiBhbmQgaXRzIGFyZ3VtZW50IGxpc3QgdG8gYmUgaW52b2tlZCBsYXRlciBkdXJpbmcgYXBwbGljYXRpb24uXG4gKiBAdHlwZURlZiBEZWNvcmF0b3JGYWN0b3J5QXJnc1xuICogQHByb3BlcnR5IHtEZWNvcmF0b3JGYWN0b3J5fSBkZWNvcmF0b3IgRmFjdG9yeSBmdW5jdGlvbiB0aGF0IHByb2R1Y2VzIGEgZGVjb3JhdG9yIHdoZW4gaW52b2tlZC5cbiAqIEBwcm9wZXJ0eSB7YW55W119IGFyZ3MgTGlzdCBvZiBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgZGVjb3JhdG9yIGZhY3RvcnkuXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuZXhwb3J0IHR5cGUgRGVjb3JhdG9yRmFjdG9yeUFyZ3MgPSB7XG4gIGRlY29yYXRvcjogRGVjb3JhdG9yRmFjdG9yeTtcbiAgYXJnczogYW55W107XG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBVbmlvbiB0aGF0IHJlcHJlc2VudHMgZWl0aGVyIGEgcmVhZHktdG8tYXBwbHkgZGVjb3JhdG9yIG9yIGEgZmFjdG9yeSB3aXRoIGFyZ3VtZW50cy5cbiAqIEBzdW1tYXJ5IEFsbG93cyByZWdpc3RlcmluZyBkZWNvcmF0b3JzIGluIHR3byBmb3JtczogYXMgZGlyZWN0IGRlY29yYXRvciBmdW5jdGlvbnMgb3IgYXMgZGVmZXJyZWQgZmFjdG9yaWVzIHBhaXJlZCB3aXRoIHRoZWlyIGFyZ3VtZW50IGxpc3RzIGZvciBsYXRlciBpbnN0YW50aWF0aW9uLlxuICogQHR5cGVEZWYgRGVjb3JhdG9yRGF0YVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0aW9uXG4gKi9cbmV4cG9ydCB0eXBlIERlY29yYXRvckRhdGEgPSBEZWNvcmF0b3JUeXBlcyB8IERlY29yYXRvckZhY3RvcnlBcmdzO1xuLyoqXG4gKiBAZGVzY3JpcHRpb24gQSBkZWNvcmF0b3IgbWFuYWdlbWVudCBjbGFzcyB0aGF0IGhhbmRsZXMgZmxhdm91cmVkIGRlY29yYXRvcnMuXG4gKiBAc3VtbWFyeSBUaGUgRGVjb3JhdGlvbiBjbGFzcyBwcm92aWRlcyBhIGJ1aWxkZXIgcGF0dGVybiBmb3IgY3JlYXRpbmcgYW5kIG1hbmFnaW5nIGRlY29yYXRvcnMgd2l0aCBkaWZmZXJlbnQgZmxhdm91cnMuIEl0IHN1cHBvcnRzIHJlZ2lzdGVyaW5nLCBleHRlbmRpbmcsIGFuZCBhcHBseWluZyBkZWNvcmF0b3JzIHdpdGggY29udGV4dC1hd2FyZSBmbGF2b3VyIHJlc29sdXRpb24sIGFsbG93aW5nIGZyYW1ld29yay1zcGVjaWZpYyBpbXBsZW1lbnRhdGlvbnMgd2hpbGUgbWFpbnRhaW5pbmcgYSBjb25zaXN0ZW50IEFQSS5cbiAqIEB0ZW1wbGF0ZSBUIFR5cGUgb2YgdGhlIGRlY29yYXRvciAoQ2xhc3NEZWNvcmF0b3IgfCBQcm9wZXJ0eURlY29yYXRvciB8IE1ldGhvZERlY29yYXRvcikuXG4gKiBAcGFyYW0ge3N0cmluZ30gW2ZsYXZvdXI9RGVmYXVsdEZsYXZvdXJdIE9wdGlvbmFsIGZsYXZvdXIgcGFyYW1ldGVyIGZvciB0aGUgZGVjb3JhdG9yIGNvbnRleHQuXG4gKiBAY2xhc3NcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBDcmVhdGUgYSBuZXcgZGVjb3JhdGlvbiBmb3IgJ2NvbXBvbmVudCcgd2l0aCBkZWZhdWx0IGZsYXZvdXJcbiAqIGNvbnN0IGNvbXBvbmVudERlY29yYXRvciA9IG5ldyBEZWNvcmF0aW9uKClcbiAqICAgLmZvcignY29tcG9uZW50JylcbiAqICAgLmRlZmluZShjdXN0b21Db21wb25lbnREZWNvcmF0b3IpO1xuICpcbiAqIC8vIENyZWF0ZSBhIGZsYXZvdXJlZCBkZWNvcmF0aW9uXG4gKiBjb25zdCB2dWVDb21wb25lbnQgPSBuZXcgRGVjb3JhdGlvbigndnVlJylcbiAqICAgLmZvcignY29tcG9uZW50JylcbiAqICAgLmRlZmluZSh2dWVDb21wb25lbnREZWNvcmF0b3IpO1xuICpcbiAqIC8vIEFwcGx5IHRoZSBkZWNvcmF0aW9uXG4gKiBAY29tcG9uZW50RGVjb3JhdG9yXG4gKiBjbGFzcyBNeUNvbXBvbmVudCB7fVxuICogYGBgXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEMgYXMgQ2xpZW50XG4gKiAgIHBhcnRpY2lwYW50IEQgYXMgRGVjb3JhdGlvblxuICogICBwYXJ0aWNpcGFudCBSIGFzIEZsYXZvdXJSZXNvbHZlclxuICogICBwYXJ0aWNpcGFudCBGIGFzIERlY29yYXRvckZhY3RvcnlcbiAqXG4gKiAgIEMtPj5EOiBuZXcgRGVjb3JhdGlvbihmbGF2b3VyKVxuICogICBDLT4+RDogZm9yKGtleSlcbiAqICAgQy0+PkQ6IGRlZmluZShkZWNvcmF0b3JzKVxuICogICBELT4+RDogcmVnaXN0ZXIoa2V5LCBmbGF2b3VyLCBkZWNvcmF0b3JzKVxuICogICBELT4+RjogZGVjb3JhdG9yRmFjdG9yeShrZXksIGZsYXZvdXIpXG4gKiAgIEYtPj5SOiByZXNvbHZlKHRhcmdldClcbiAqICAgUi0tPj5GOiByZXNvbHZlZCBmbGF2b3VyXG4gKiAgIEYtPj5GOiBhcHBseSBkZWNvcmF0b3JzXG4gKiAgIEYtLT4+QzogZGVjb3JhdGVkIHRhcmdldFxuICovXG5leHBvcnQgY2xhc3MgRGVjb3JhdGlvbiBpbXBsZW1lbnRzIElEZWNvcmF0aW9uQnVpbGRlciB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3RhdGljIG1hcCBvZiByZWdpc3RlcmVkIGRlY29yYXRvcnMuXG4gICAqIEBzdW1tYXJ5IFN0b3JlcyBhbGwgcmVnaXN0ZXJlZCBkZWNvcmF0b3JzIG9yZ2FuaXNlZCBieSBrZXkgYW5kIGZsYXZvdXIuXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBkZWNvcmF0b3JzOiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIFJlY29yZDxcbiAgICAgIHN0cmluZyxcbiAgICAgIHtcbiAgICAgICAgZGVjb3JhdG9ycz86IFNldDxEZWNvcmF0b3JEYXRhPjtcbiAgICAgICAgZXh0cmFzPzogU2V0PERlY29yYXRvckRhdGE+O1xuICAgICAgfVxuICAgID5cbiAgPiA9IHt9O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRnVuY3Rpb24gdG8gcmVzb2x2ZSBmbGF2b3VyIGZyb20gYSB0YXJnZXQuXG4gICAqIEBzdW1tYXJ5IFJlc29sdmVyIGZ1bmN0aW9uIHRoYXQgZGV0ZXJtaW5lcyB0aGUgYXBwcm9wcmlhdGUgZmxhdm91ciBmb3IgYSBnaXZlbiB0YXJnZXQuXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBmbGF2b3VyUmVzb2x2ZXI6IEZsYXZvdXJSZXNvbHZlciA9IGRlZmF1bHRGbGF2b3VyUmVzb2x2ZXI7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXQgb2YgZGVjb3JhdG9ycyBmb3IgdGhlIGN1cnJlbnQgY29udGV4dC5cbiAgICovXG4gIHByaXZhdGUgZGVjb3JhdG9ycz86IFNldDxEZWNvcmF0b3JEYXRhPjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldCBvZiBhZGRpdGlvbmFsIGRlY29yYXRvcnMuXG4gICAqL1xuICBwcml2YXRlIGV4dHJhcz86IFNldDxEZWNvcmF0b3JEYXRhPjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEN1cnJlbnQgZGVjb3JhdG9yIGtleS5cbiAgICovXG4gIHByaXZhdGUga2V5Pzogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZmxhdm91cjogc3RyaW5nID0gRGVmYXVsdEZsYXZvdXIpIHt9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBrZXkgZm9yIHRoZSBkZWNvcmF0aW9uIGJ1aWxkZXIuXG4gICAqIEBzdW1tYXJ5IEluaXRpYWxpc2VzIGEgbmV3IGRlY29yYXRpb24gY2hhaW4gd2l0aCB0aGUgc3BlY2lmaWVkIGtleS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBJZGVudGlmaWVyIGZvciB0aGUgZGVjb3JhdG9yLlxuICAgKiBAcmV0dXJuIHtEZWNvcmF0aW9uQnVpbGRlck1pZH0gQnVpbGRlciBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgZm9yKGtleTogc3RyaW5nKTogRGVjb3JhdGlvbkJ1aWxkZXJNaWQge1xuICAgIHRoaXMua2V5ID0ga2V5O1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBZGRzIGRlY29yYXRvcnMgdG8gdGhlIGN1cnJlbnQgY29udGV4dC5cbiAgICogQHN1bW1hcnkgSW50ZXJuYWwgbWV0aG9kIHRvIGFkZCBkZWNvcmF0b3JzIHdpdGggYWRkb24gc3VwcG9ydC5cbiAgICogQHBhcmFtIHtib29sZWFufSBbYWRkb249ZmFsc2VdIEluZGljYXRlcyB3aGV0aGVyIHRoZSBkZWNvcmF0b3JzIGFyZSBhZGRpdGl2ZSBleHRyYXMuXG4gICAqIEBwYXJhbSB7Li4uRGVjb3JhdG9yRGF0YX0gZGVjb3JhdG9ycyBEZWNvcmF0b3JzIHRvIHJlZ2lzdGVyIGZvciB0aGUgY29uZmlndXJlZCBrZXkuXG4gICAqIEByZXR1cm4ge3RoaXN9IEN1cnJlbnQgaW5zdGFuY2UgZm9yIGNoYWluaW5nLlxuICAgKi9cbiAgcHJpdmF0ZSBkZWNvcmF0ZShcbiAgICBhZGRvbjogYm9vbGVhbiA9IGZhbHNlLFxuICAgIC4uLmRlY29yYXRvcnM6IERlY29yYXRvckRhdGFbXVxuICApOiB0aGlzIHtcbiAgICBpZiAoIXRoaXMua2V5KVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwia2V5IG11c3QgYmUgcHJvdmlkZWQgYmVmb3JlIGRlY29yYXRvcnMgY2FuIGJlIGFkZGVkXCIpO1xuICAgIGlmIChcbiAgICAgICghZGVjb3JhdG9ycyB8fCAhZGVjb3JhdG9ycy5sZW5ndGgpICYmXG4gICAgICAhYWRkb24gJiZcbiAgICAgIHRoaXMuZmxhdm91ciAhPT0gRGVmYXVsdEZsYXZvdXJcbiAgICApXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiTXVzdCBwcm92aWRlIG92ZXJyaWRlcyBvciBhZGRvbnMgdG8gb3ZlcnJpZGUgb3IgZXh0ZW5kIGRlY2FmJ3MgZGVjb3JhdG9yc1wiXG4gICAgICApO1xuICAgIGlmICh0aGlzLmZsYXZvdXIgPT09IERlZmF1bHRGbGF2b3VyICYmIGFkZG9uKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRGVmYXVsdCBmbGF2b3VyIGNhbm5vdCBiZSBleHRlbmRlZFwiKTtcblxuICAgIHRoaXNbYWRkb24gPyBcImV4dHJhc1wiIDogXCJkZWNvcmF0b3JzXCJdID0gbmV3IFNldChbXG4gICAgICAuLi4odGhpc1thZGRvbiA/IFwiZXh0cmFzXCIgOiBcImRlY29yYXRvcnNcIl0gfHwgbmV3IFNldCgpKS52YWx1ZXMoKSxcbiAgICAgIC4uLmRlY29yYXRvcnMsXG4gICAgXSk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGVmaW5lcyB0aGUgYmFzZSBkZWNvcmF0b3JzLlxuICAgKiBAc3VtbWFyeSBTZXRzIHRoZSBwcmltYXJ5IGRlY29yYXRvcnMgZm9yIHRoZSBjdXJyZW50IGNvbnRleHQuXG4gICAqIEBwYXJhbSB7Li4uRGVjb3JhdG9yRGF0YX0gZGVjb3JhdG9ycyBEZWNvcmF0b3JzIHRvIGRlZmluZS5cbiAgICogQHJldHVybiB7RGVjb3JhdGlvbkJ1aWxkZXJFbmR9IEJ1aWxkZXIgaW5zdGFuY2UgZm9yIGZpbmlzaGluZyB0aGUgY2hhaW4gKGFsc28gaW1wbGVtZW50cyBEZWNvcmF0aW9uQnVpbGRlckJ1aWxkKS5cbiAgICovXG4gIGRlZmluZShcbiAgICAuLi5kZWNvcmF0b3JzOiBEZWNvcmF0b3JEYXRhW11cbiAgKTogRGVjb3JhdGlvbkJ1aWxkZXJFbmQgJiBEZWNvcmF0aW9uQnVpbGRlckJ1aWxkIHtcbiAgICBpZiAoXG4gICAgICBkZWNvcmF0b3JzLmZpbmQoKGQpID0+IHR5cGVvZiBkID09PSBcIm9iamVjdFwiKSAmJlxuICAgICAgZGVjb3JhdG9ycy5sZW5ndGggIT09IDFcbiAgICApXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBXaGVuIHVzaW5nIGFuIG92ZXJyaWRhYmxlIGRlY29yYXRvciwgb25seSBvbmUgaXMgYWxsb3dlZGBcbiAgICAgICk7XG4gICAgcmV0dXJuIHRoaXMuZGVjb3JhdGUoZmFsc2UsIC4uLmRlY29yYXRvcnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBFeHRlbmRzIGV4aXN0aW5nIGRlY29yYXRvcnMuXG4gICAqIEBzdW1tYXJ5IEFkZHMgYWRkaXRpb25hbCBkZWNvcmF0b3JzIHRvIHRoZSBjdXJyZW50IGNvbnRleHQuXG4gICAqIEBwYXJhbSB7Li4uRGVjb3JhdG9yRGF0YX0gZGVjb3JhdG9ycyBBZGRpdGlvbmFsIGRlY29yYXRvcnMgdG8gcmVnaXN0ZXIgYXMgYWRkb25zLlxuICAgKiBAcmV0dXJuIHtEZWNvcmF0aW9uQnVpbGRlckJ1aWxkfSBCdWlsZGVyIGluc3RhbmNlIGZvciBidWlsZGluZyB0aGUgZGVjb3JhdG9yLlxuICAgKi9cbiAgZXh0ZW5kKC4uLmRlY29yYXRvcnM6IERlY29yYXRvckRhdGFbXSk6IERlY29yYXRpb25CdWlsZGVyQnVpbGQge1xuICAgIGlmIChcbiAgICAgIGRlY29yYXRvcnMuZmluZCgoZCkgPT4gdHlwZW9mIGQgPT09IFwib2JqZWN0XCIpICYmXG4gICAgICBkZWNvcmF0b3JzLmxlbmd0aCAhPT0gMVxuICAgIClcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFdoZW4gZXh0ZW5kaW5nIHVzaW5nIGFuIG92ZXJyaWRhYmxlIGRlY29yYXRvciwgb25seSBvbmUgaXMgYWxsb3dlZGBcbiAgICAgICk7XG4gICAgcmV0dXJuIHRoaXMuZGVjb3JhdGUodHJ1ZSwgLi4uZGVjb3JhdG9ycyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEZhY3RvcnkgdGhhdCBjcmVhdGVzIGEgY29udGV4dC1hd2FyZSBkZWNvcmF0b3IgZm9yIGEga2V5L2ZsYXZvdXIuXG4gICAqIEBzdW1tYXJ5IFByb2R1Y2VzIGEgZGVjb3JhdG9yIGZ1bmN0aW9uIGJvdW5kIHRvIHRoZSBwcm92aWRlZCBrZXkgYW5kIGZsYXZvdXIuIFRoZSByZXN1bHRpbmcgZGVjb3JhdG9yIHJlc29sdmVzIHRoZSBhY3R1YWwgZGVjb3JhdG9ycyB0byBhcHBseSBhdCBpbnZvY2F0aW9uIHRpbWUgYmFzZWQgb24gdGhlIHRhcmdldCdzIHJlc29sdmVkIGZsYXZvdXIgYW5kIHRoZSByZWdpc3RlcmVkIGJhc2UgYW5kIGV4dHJhIGRlY29yYXRvcnMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgRGVjb3JhdGlvbiBrZXkgdXNlZCB0byBsb29rIHVwIHJlZ2lzdGVyZWQgZGVjb3JhdG9ycy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtmPURlZmF1bHRGbGF2b3VyXSBFeHBsaWNpdCBmbGF2b3VyIHRvIGJpbmQgdGhlIGZhY3RvcnkgdG8uXG4gICAqIEByZXR1cm4ge0NsYXNzRGVjb3JhdG9yfE1ldGhvZERlY29yYXRvcnxQcm9wZXJ0eURlY29yYXRvcnxQYXJhbWV0ZXJEZWNvcmF0b3J9IERlY29yYXRvciBmdW5jdGlvbiB0aGF0IGFwcGxpZXMgdGhlIHJlc29sdmVkIGRlY29yYXRvcnMuXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IFUgYXMgVXNlciBDb2RlXG4gICAqICAgcGFydGljaXBhbnQgQiBhcyBEZWNvcmF0aW9uIChidWlsZGVyKVxuICAgKiAgIHBhcnRpY2lwYW50IEYgYXMgZGVjb3JhdG9yRmFjdG9yeShrZXksIGYpXG4gICAqICAgcGFydGljaXBhbnQgUiBhcyBmbGF2b3VyUmVzb2x2ZXJcbiAgICogICBwYXJ0aWNpcGFudCBBIGFzIEFwcGxpZWQgRGVjb3JhdG9yc1xuICAgKiAgIFUtPj5COiBkZWZpbmUoKS9leHRlbmQoKSBhbmQgYXBwbHkoKVxuICAgKiAgIEItPj5GOiBjcmVhdGUgY29udGV4dCBkZWNvcmF0b3JcbiAgICogICBGLT4+UjogcmVzb2x2ZSh0YXJnZXQpXG4gICAqICAgUi0tPj5GOiBmbGF2b3VyXG4gICAqICAgRi0+PkE6IGNvbGxlY3QgYmFzZSArIGV4dHJhc1xuICAgKiAgIGxvb3AgZWFjaCBkZWNvcmF0b3JcbiAgICogICAgIEEtPj5VOiBpbnZva2UgZGVjb3JhdG9yKHRhcmdldCwga2V5PywgZGVzYz8pXG4gICAqICAgZW5kXG4gICAqL1xuICBwcm90ZWN0ZWQgZGVjb3JhdG9yRmFjdG9yeShrZXk6IHN0cmluZywgZjogc3RyaW5nID0gRGVmYXVsdEZsYXZvdXIpIHtcbiAgICBmdW5jdGlvbiBjb250ZXh0RGVjb3JhdG9yKFxuICAgICAgdGFyZ2V0OiBvYmplY3QsXG4gICAgICBwcm9wZXJ0eUtleT86IGFueSxcbiAgICAgIGRlc2NyaXB0b3I/OiBUeXBlZFByb3BlcnR5RGVzY3JpcHRvcjxhbnk+XG4gICAgKSB7XG4gICAgICBjb25zdCBmbGF2b3VyID0gRGVjb3JhdGlvbi5mbGF2b3VyUmVzb2x2ZXIodGFyZ2V0KTtcbiAgICAgIGNvbnN0IGNhY2hlID0gRGVjb3JhdGlvbi5kZWNvcmF0b3JzW2tleV07XG4gICAgICBsZXQgZGVjb3JhdG9ycztcbiAgICAgIGNvbnN0IGV4dHJhcyA9IGNhY2hlW2ZsYXZvdXJdXG4gICAgICAgID8gY2FjaGVbZmxhdm91cl0uZXh0cmFzXG4gICAgICAgIDogY2FjaGVbRGVmYXVsdEZsYXZvdXJdLmV4dHJhcztcblxuICAgICAgaWYgKFxuICAgICAgICBjYWNoZSAmJlxuICAgICAgICBjYWNoZVtmbGF2b3VyXSAmJlxuICAgICAgICBjYWNoZVtmbGF2b3VyXS5kZWNvcmF0b3JzICYmXG4gICAgICAgIGNhY2hlW2ZsYXZvdXJdLmRlY29yYXRvcnMuc2l6ZVxuICAgICAgKSB7XG4gICAgICAgIGRlY29yYXRvcnMgPSBjYWNoZVtmbGF2b3VyXS5kZWNvcmF0b3JzO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGVjb3JhdG9ycyA9IGNhY2hlW0RlZmF1bHRGbGF2b3VyXS5kZWNvcmF0b3JzO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBkZWNvcmF0b3JBcmdzID0gW1xuICAgICAgICAuLi4oY2FjaGVbRGVmYXVsdEZsYXZvdXJdIGFzIGFueSkuZGVjb3JhdG9ycy52YWx1ZXMoKSxcbiAgICAgIF0ucmVkdWNlKChhY2N1bTogUmVjb3JkPG51bWJlciwgYW55PiwgZSwgaSkgPT4ge1xuICAgICAgICBpZiAoZS5hcmdzKSBhY2N1bVtpXSA9IGUuYXJncztcbiAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgfSwge30pO1xuXG4gICAgICBjb25zdCB0b0FwcGx5ID0gW1xuICAgICAgICAuLi4oZGVjb3JhdG9ycyA/IGRlY29yYXRvcnMudmFsdWVzKCkgOiBbXSksXG4gICAgICAgIC4uLihleHRyYXMgPyBleHRyYXMudmFsdWVzKCkgOiBbXSksXG4gICAgICBdO1xuXG4gICAgICByZXR1cm4gdG9BcHBseS5yZWR1Y2UoXG4gICAgICAgIChfLCBkKSA9PiB7XG4gICAgICAgICAgc3dpdGNoICh0eXBlb2YgZCkge1xuICAgICAgICAgICAgY2FzZSBcIm9iamVjdFwiOiB7XG4gICAgICAgICAgICAgIGNvbnN0IHsgZGVjb3JhdG9yIH0gPSBkIGFzIERlY29yYXRvckZhY3RvcnlBcmdzO1xuXG4gICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgZGVjb3JhdG9yKC4uLihPYmplY3QudmFsdWVzKGRlY29yYXRvckFyZ3MpWzBdIHx8IFtdKSkgYXMgYW55XG4gICAgICAgICAgICAgICkodGFyZ2V0LCBwcm9wZXJ0eUtleSwgZGVzY3JpcHRvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXNlIFwiZnVuY3Rpb25cIjpcbiAgICAgICAgICAgICAgcmV0dXJuIChkIGFzIGFueSkodGFyZ2V0LCBwcm9wZXJ0eUtleSwgZGVzY3JpcHRvcik7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuZXhwZWN0ZWQgZGVjb3JhdG9yIHR5cGU6ICR7dHlwZW9mIGR9YCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICB7IHRhcmdldCwgcHJvcGVydHlLZXksIGRlc2NyaXB0b3IgfVxuICAgICAgKTtcbiAgICB9XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGNvbnRleHREZWNvcmF0b3IsIFwibmFtZVwiLCB7XG4gICAgICB2YWx1ZTogW2YsIGtleV0uam9pbihcIl9kZWNvcmF0b3JfZm9yX1wiKSxcbiAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICB9KTtcbiAgICByZXR1cm4gY29udGV4dERlY29yYXRvcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyB0aGUgZmluYWwgZGVjb3JhdG9yIGZ1bmN0aW9uLlxuICAgKiBAc3VtbWFyeSBCdWlsZHMgYW5kIHJldHVybnMgdGhlIGRlY29yYXRvciBmYWN0b3J5IGZ1bmN0aW9uLlxuICAgKiBAcmV0dXJuIHtDbGFzc0RlY29yYXRvcnxNZXRob2REZWNvcmF0b3J8UHJvcGVydHlEZWNvcmF0b3J8UGFyYW1ldGVyRGVjb3JhdG9yfSBHZW5lcmF0ZWQgZGVjb3JhdG9yIGZ1bmN0aW9uIHJlYWR5IGZvciBhcHBsaWNhdGlvbi5cbiAgICovXG4gIGFwcGx5KCk6IChcbiAgICB0YXJnZXQ6IGFueSxcbiAgICBwcm9wZXJ0eUtleT86IGFueSxcbiAgICBkZXNjcmlwdG9yPzogVHlwZWRQcm9wZXJ0eURlc2NyaXB0b3I8YW55PlxuICApID0+IGFueSB7XG4gICAgaWYgKCF0aGlzLmtleSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGtleSBwcm92aWRlZCBmb3IgdGhlIGRlY29yYXRpb24gYnVpbGRlclwiKTtcbiAgICBEZWNvcmF0aW9uLnJlZ2lzdGVyKFxuICAgICAgdGhpcy5rZXksXG4gICAgICB0aGlzLmZsYXZvdXIsXG4gICAgICB0aGlzLmRlY29yYXRvcnMgfHwgbmV3IFNldCgpLFxuICAgICAgdGhpcy5leHRyYXNcbiAgICApO1xuICAgIHJldHVybiB0aGlzLmRlY29yYXRvckZhY3RvcnkodGhpcy5rZXksIHRoaXMuZmxhdm91cik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlZ2lzdGVycyBkZWNvcmF0b3JzIGZvciBhIHNwZWNpZmljIGtleSBhbmQgZmxhdm91ci5cbiAgICogQHN1bW1hcnkgSW50ZXJuYWwgbWV0aG9kIHRvIHN0b3JlIGRlY29yYXRvcnMgaW4gdGhlIHN0YXRpYyByZWdpc3RyeS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBEZWNvcmF0b3Iga2V5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gZmxhdm91ciBEZWNvcmF0b3IgZmxhdm91ci5cbiAgICogQHBhcmFtIHtTZXQ8RGVjb3JhdG9yRGF0YT59IFtkZWNvcmF0b3JzXSBQcmltYXJ5IGRlY29yYXRvcnMgcmVnaXN0ZXJlZCBmb3IgdGhlIGtleS5cbiAgICogQHBhcmFtIHtTZXQ8RGVjb3JhdG9yRGF0YT59IFtleHRyYXNdIEFkZGl0aW9uYWwgZGVjb3JhdG9ycyByZWdpc3RlcmVkIGFzIGZsYXZvdXItc3BlY2lmaWMgYWRkb25zLlxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgcmVnaXN0ZXIoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgZmxhdm91cjogc3RyaW5nLFxuICAgIGRlY29yYXRvcnM/OiBTZXQ8RGVjb3JhdG9yRGF0YT4sXG4gICAgZXh0cmFzPzogU2V0PERlY29yYXRvckRhdGE+XG4gICkge1xuICAgIGlmICgha2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBrZXkgcHJvdmlkZWQgZm9yIHRoZSBkZWNvcmF0aW9uIGJ1aWxkZXJcIik7XG4gICAgfVxuICAgIGlmICghZGVjb3JhdG9ycylcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGRlY29yYXRvcnMgcHJvdmlkZWQgZm9yIHRoZSBkZWNvcmF0aW9uIGJ1aWxkZXJcIik7XG4gICAgaWYgKCFmbGF2b3VyKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gZmxhdm91ciBwcm92aWRlZCBmb3IgdGhlIGRlY29yYXRpb24gYnVpbGRlclwiKTtcblxuICAgIGlmICghRGVjb3JhdGlvbi5kZWNvcmF0b3JzW2tleV0pIERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldID0ge307XG4gICAgaWYgKCFEZWNvcmF0aW9uLmRlY29yYXRvcnNba2V5XVtmbGF2b3VyXSlcbiAgICAgIERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldW2ZsYXZvdXJdID0ge307XG4gICAgaWYgKGRlY29yYXRvcnMpIERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldW2ZsYXZvdXJdLmRlY29yYXRvcnMgPSBkZWNvcmF0b3JzO1xuICAgIGlmIChleHRyYXMpIERlY29yYXRpb24uZGVjb3JhdG9yc1trZXldW2ZsYXZvdXJdLmV4dHJhcyA9IGV4dHJhcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgZ2xvYmFsIGZsYXZvdXIgcmVzb2x2ZXIuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIGZ1bmN0aW9uIHVzZWQgdG8gZGV0ZXJtaW5lIGRlY29yYXRvciBmbGF2b3Vycy5cbiAgICogQHBhcmFtIHtGbGF2b3VyUmVzb2x2ZXJ9IHJlc29sdmVyIEZ1bmN0aW9uIHRvIHJlc29sdmUgZmxhdm91cnMuXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBzdGF0aWMgc2V0Rmxhdm91clJlc29sdmVyKHJlc29sdmVyOiBGbGF2b3VyUmVzb2x2ZXIpIHtcbiAgICBEZWNvcmF0aW9uLmZsYXZvdXJSZXNvbHZlciA9IHJlc29sdmVyO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDb252ZW5pZW5jZSBzdGF0aWMgZW50cnkgdG8gc3RhcnQgYSBkZWNvcmF0aW9uIGJ1aWxkZXIuXG4gICAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBuZXcgRGVjb3JhdGlvbiBpbnN0YW5jZSBhbmQgaW5pdGlhdGVzIHRoZSBidWlsZGVyIGNoYWluIHdpdGggdGhlIHByb3ZpZGVkIGtleS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBEZWNvcmF0aW9uIGtleSB0byBjb25maWd1cmUuXG4gICAqIEByZXR1cm4ge0RlY29yYXRpb25CdWlsZGVyTWlkfSBCdWlsZGVyIGluc3RhbmNlIGZvciBjaGFpbmluZyBkZWZpbml0aW9ucy5cbiAgICovXG4gIHN0YXRpYyBmb3Ioa2V5OiBzdHJpbmcpOiBEZWNvcmF0aW9uQnVpbGRlck1pZCB7XG4gICAgcmV0dXJuIG5ldyBEZWNvcmF0aW9uKCkuZm9yKGtleSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFN0YXJ0cyBhIGJ1aWxkZXIgZm9yIGEgc3BlY2lmaWMgZmxhdm91ci5cbiAgICogQHN1bW1hcnkgQ29udmVuaWVuY2UgbWV0aG9kIHRvIGJlZ2luIGEgRGVjb3JhdGlvbiBidWlsZGVyIGNoYWluIGJvdW5kIHRvIHRoZSBnaXZlbiBmbGF2b3VyIGlkZW50aWZpZXIsIGFsbG93aW5nIHJlZ2lzdHJhdGlvbiBvZiBmbGF2b3VyLXNwZWNpZmljIGRlY29yYXRvcnMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmbGF2b3VyIEZsYXZvdXIgbmFtZSB0byBiaW5kIHRvIHRoZSBidWlsZGVyLlxuICAgKiBAcmV0dXJuIHtEZWNvcmF0aW9uQnVpbGRlclN0YXJ0fSBCdWlsZGVyIHN0YXJ0IGludGVyZmFjZSB0byBjb250aW51ZSBjb25maWd1cmF0aW9uLlxuICAgKi9cbiAgc3RhdGljIGZsYXZvdXJlZEFzKGZsYXZvdXI6IHN0cmluZyk6IERlY29yYXRpb25CdWlsZGVyU3RhcnQge1xuICAgIHJldHVybiBuZXcgRGVjb3JhdGlvbihmbGF2b3VyKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgTWV0YWRhdGEgfSBmcm9tIFwiLi9tZXRhZGF0YS9NZXRhZGF0YVwiO1xuaW1wb3J0IHsgRGVjb3JhdGlvbktleXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQXNzaWducyBhcmJpdHJhcnkgbWV0YWRhdGEgdG8gYSB0YXJnZXQgdXNpbmcgYSBzdHJpbmcga2V5LlxuICogQHN1bW1hcnkgRGVjb3JhdG9yIGZhY3RvcnkgdGhhdCBzdG9yZXMgYSBrZXkvdmFsdWUgcGFpciBpbiB0aGUgY2VudHJhbCBtZXRhZGF0YSBzdG9yZSBmb3IgdGhlIHByb3ZpZGVkIGNsYXNzIG9yIG1lbWJlci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgTWV0YWRhdGEga2V5IHRvIGFzc29jaWF0ZSB3aXRoIHRoZSB0YXJnZXQuXG4gKiBAcGFyYW0ge2FueX0gdmFsdWUgTWV0YWRhdGEgdmFsdWUgdG8gc3RvcmUgdW5kZXIgdGhlIGdpdmVuIGtleS5cbiAqIEByZXR1cm4ge0NsYXNzRGVjb3JhdG9yfE1ldGhvZERlY29yYXRvcnxQcm9wZXJ0eURlY29yYXRvcnxQYXJhbWV0ZXJEZWNvcmF0b3J9IERlY29yYXRvciB0aGF0IHdyaXRlcyB0aGUgbWV0YWRhdGEgd2hlbiBhcHBsaWVkLlxuICogQGZ1bmN0aW9uIG1ldGFkYXRhXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gbWV0YWRhdGEoa2V5OiBzdHJpbmcsIHZhbHVlOiBhbnkpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIG1ldGFkYXRhKFxuICAgIG1vZGVsOiBhbnksXG5cbiAgICBwcm9wPzogYW55LFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICBkZXNjcmlwdG9yPzogUHJvcGVydHlEZXNjcmlwdG9yIHwgbnVtYmVyXG4gICkge1xuICAgIE1ldGFkYXRhLnNldChwcm9wID8gbW9kZWwuY29uc3RydWN0b3IgOiBtb2RlbCwga2V5LCB2YWx1ZSk7XG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENhcHR1cmVzIGFuZCBzdG9yZXMgYSBwcm9wZXJ0eSdzIGRlc2lnbiB0eXBlLlxuICogQHN1bW1hcnkgRGVjb3JhdG9yIGZhY3RvcnkgdGhhdCByZWFkcyB0aGUgcmVmbGVjdGVkIGBkZXNpZ246dHlwZWAgZm9yIGEgcHJvcGVydHkgYW5kIHJlZ2lzdGVycyBpdCBpbiB0aGUgbWV0YWRhdGEgc3RvcmUgdW5kZXIgdGhlIHByb3BlcnRpZXMgbWFwLlxuICogQHJldHVybiB7UHJvcGVydHlEZWNvcmF0b3J9IERlY29yYXRvciB0aGF0IHJlY29yZHMgdGhlIHByb3BlcnR5J3MgdHlwZSBtZXRhZGF0YSB3aGVuIGFwcGxpZWQuXG4gKiBAZnVuY3Rpb24gcHJvcFxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb3AoKSB7XG4gIHJldHVybiBmdW5jdGlvbiBwcm9wKG1vZGVsOiBvYmplY3QsIHByb3A6IGFueSkge1xuICAgIGNvbnN0IGRlc2lnblR5cGUgPSBSZWZsZWN0LmdldE93bk1ldGFkYXRhKFxuICAgICAgRGVjb3JhdGlvbktleXMuREVTSUdOX1RZUEUsXG4gICAgICBtb2RlbCxcbiAgICAgIHByb3BcbiAgICApO1xuICAgIHJldHVybiBtZXRhZGF0YShNZXRhZGF0YS5rZXkoRGVjb3JhdGlvbktleXMuUFJPUEVSVElFUywgcHJvcCksIGRlc2lnblR5cGUpKFxuICAgICAgbW9kZWwsXG4gICAgICBwcm9wXG4gICAgKTtcbiAgfTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ2FwdHVyZXMgYSBzaW5nbGUgcGFyYW1ldGVyIHR5cGUgZm9yIHRoZSBkZWNvcmF0ZWQgbWV0aG9kLlxuICogQHN1bW1hcnkgRGVjb3JhdG9yIGZhY3RvcnkgdGhhdCBlbnN1cmVzIHRoZSBtZXRob2QgbWV0YWRhdGEgaXMgaW5pdGlhbGlzZWQgYW5kIHN0b3JlcyB0aGUgcmVmbGVjdGVkIHBhcmFtZXRlciBjb25zdHJ1Y3RvciBhdCB0aGUgcHJvdmlkZWQgaW5kZXguXG4gKiBAcmV0dXJuIHtQYXJhbWV0ZXJEZWNvcmF0b3J9IERlY29yYXRvciB0aGF0IHJlY29yZHMgdGhlIHBhcmFtZXRlciB0eXBlIHdoZW4gYXBwbGllZC5cbiAqIEBmdW5jdGlvbiBwYXJhbVxuICogQGNhdGVnb3J5IFBhcmFtZXRlciBEZWNvcmF0b3JzXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IFUgYXMgVXNlciBDb2RlXG4gKiAgIHBhcnRpY2lwYW50IFAgYXMgcGFyYW0oKVxuICogICBwYXJ0aWNpcGFudCBNIGFzIE1ldGFkYXRhXG4gKiAgIFUtPj5QOiBwYXJhbSgpKHRhcmdldCwga2V5LCBpbmRleClcbiAqICAgUC0+PlU6IG1ldGhvZCgpKHRhcmdldCwga2V5LCBkZXNjcmlwdG9yKVxuICogICBQLT4+TTogcGFyYW1zKGNvbnN0cnVjdG9yLCBrZXkpXG4gKiAgIE0tLT4+UDogcGFyYW1ldGVyIGNvbnN0cnVjdG9yc1tdXG4gKiAgIFAtPj5NOiBzZXQobWV0aG9kcy5rZXkuaW5kZXgsIGNvbnN0cnVjdG9yKVxuICogICBQLS0+PlU6IHBhcmFtZXRlciByZWNvcmRlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyYW0oKSB7XG4gIHJldHVybiBmdW5jdGlvbiBwYXJhbShcbiAgICBtb2RlbDogb2JqZWN0LFxuICAgIHByb3A6IHN0cmluZyB8IHN5bWJvbCB8IHVuZGVmaW5lZCxcbiAgICBpbmRleDogbnVtYmVyXG4gICkge1xuICAgIGlmICghcHJvcClcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGhlIEBwYXJhbSBkZWNvcmF0b3IgY2FuIG9ubHkgYmUgYXBwbGllZCB0byBtZXRob2RzYCk7XG4gICAgbWV0aG9kKCkobW9kZWwsIHByb3AsIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobW9kZWwsIHByb3ApKTtcbiAgICBjb25zdCBwYXJhbVRwZXMgPSBNZXRhZGF0YS5wYXJhbXMobW9kZWwuY29uc3RydWN0b3IgYXMgYW55LCBwcm9wIGFzIHN0cmluZyk7XG4gICAgaWYgKCFwYXJhbVRwZXMpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE1pc3NpbmcgcGFyYW1ldGVyIHR5cGVzIGZvciAke1N0cmluZyhwcm9wKX1gKTtcbiAgICBpZiAoaW5kZXggPj0gcGFyYW1UcGVzLmxlbmd0aClcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFBhcmFtZXRlciBpbmRleCAke2luZGV4fSBvdXQgb2YgcmFuZ2UgZm9yICR7U3RyaW5nKHByb3ApfWBcbiAgICAgICk7XG4gICAgbWV0YWRhdGEoXG4gICAgICBNZXRhZGF0YS5rZXkoRGVjb3JhdGlvbktleXMuTUVUSE9EUywgcHJvcCBhcyBzdHJpbmcsIGluZGV4LnRvU3RyaW5nKCkpLFxuICAgICAgcGFyYW1UcGVzW2luZGV4XVxuICAgICkobW9kZWwsIHByb3ApO1xuICB9O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFeHRlbmRzIGEgcGFyYW1ldGVyIGRlY29yYXRvciB3aXRoIGFkZGl0aW9uYWwgbWV0YWRhdGEuXG4gKiBAc3VtbWFyeSBBcHBsaWVzIHRoZSBkZWZhdWx0IGBwYXJhbSgpYCBkZWNvcmF0b3IgYW5kIGF1Z21lbnRzIHRoZSBzdG9yZWQgbWV0YWRhdGEgd2l0aCBhbiBhcmJpdHJhcnkga2V5L3ZhbHVlIHBhaXIuXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IE1ldGFkYXRhIGtleSB0byBhc3NvY2lhdGUgd2l0aCB0aGUgcGFyYW1ldGVyLlxuICogQHBhcmFtIHthbnl9IHZhbHVlIE1ldGFkYXRhIHZhbHVlIHBlcnNpc3RlZCB1bmRlciB0aGUgZ2l2ZW4ga2V5LlxuICogQHJldHVybiB7UGFyYW1ldGVyRGVjb3JhdG9yfSBEZWNvcmF0b3IgdGhhdCByZWNvcmRzIGJvdGggdGhlIHBhcmFtZXRlciBkZXNpZ24gdHlwZSBhbmQgYWRkaXRpb25hbCBtZXRhZGF0YS5cbiAqIEBmdW5jdGlvbiBwYXJhbU1ldGFkYXRhXG4gKiBAY2F0ZWdvcnkgUGFyYW1ldGVyIERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcmFtTWV0YWRhdGEoa2V5OiBzdHJpbmcsIHZhbHVlOiBhbnkpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIHBhcmFtTWV0YWRhdGEodGFyZ2V0OiBhbnksIHByb3A6IGFueSwgaW5kZXg6IG51bWJlcikge1xuICAgIHJldHVybiBhcHBseShcbiAgICAgIHBhcmFtKCksXG4gICAgICBtZXRhZGF0YShNZXRhZGF0YS5rZXkoRGVjb3JhdGlvbktleXMuTUVUSE9EUywgcHJvcCwga2V5KSwgdmFsdWUpXG4gICAgKSh0YXJnZXQsIHByb3AsIGluZGV4KTtcbiAgfTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVjb3JkcyBtZXRob2QgZGVzaWduLXRpbWUgbWV0YWRhdGEuXG4gKiBAc3VtbWFyeSBEZWNvcmF0b3IgZmFjdG9yeSB0aGF0IGNhcHR1cmVzIGEgbWV0aG9kJ3MgcmVmbGVjdGVkIHBhcmFtZXRlciBhbmQgcmV0dXJuIHR5cGVzLCBzdG9yaW5nIHRoZW0gdW5kZXIgdGhlIGFwcHJvcHJpYXRlIG1ldGFkYXRhIGtleXMgc28gdGhleSBjYW4gYmUgaW5zcGVjdGVkIGF0IHJ1bnRpbWUuXG4gKiBAcmV0dXJuIHtNZXRob2REZWNvcmF0b3J9IERlY29yYXRvciB0aGF0IHBlcnNpc3RzIHRoZSBtZXRob2QncyBzaWduYXR1cmUgaW5mb3JtYXRpb24gaW50byB0aGUgbWV0YWRhdGEgc3RvcmUgd2hlbiBhcHBsaWVkLlxuICogQGZ1bmN0aW9uIG1ldGhvZFxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBVIGFzIFVzZXIgQ29kZVxuICogICBwYXJ0aWNpcGFudCBGIGFzIG1ldGhvZCgpXG4gKiAgIHBhcnRpY2lwYW50IE0gYXMgTWV0YWRhdGFcbiAqICAgVS0+PkY6IG1ldGhvZCgpKHRhcmdldCwga2V5LCBkZXNjcmlwdG9yKVxuICogICBGLT4+VTogUmVmbGVjdC5nZXRPd25NZXRhZGF0YShkZXNpZ246cGFyYW10eXBlcylcbiAqICAgRi0+PlU6IFJlZmxlY3QuZ2V0T3duTWV0YWRhdGEoZGVzaWduOnJldHVybnR5cGUpXG4gKiAgIEYtPj5NOiBzZXQobWV0aG9kcy5rZXkuZGVzaWduOnBhcmFtdHlwZXMsIHBhcmFtcylcbiAqICAgRi0+Pk06IHNldChtZXRob2RzLmtleS5kZXNpZ246cmV0dXJudHlwZSwgcmV0dXJuVHlwZSlcbiAqICAgRi0tPj5VOiBkZWNvcmF0ZWQgZnVuY3Rpb25cbiAqIEBjYXRlZ29yeSBNZXRob2QgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gbWV0aG9kKCkge1xuICByZXR1cm4gZnVuY3Rpb24gbWV0aG9kKG9iajogYW55LCBwcm9wPzogYW55LCBkZXNjcmlwdG9yPzogYW55KSB7XG4gICAgY29uc3QgZGVzaWduUGFyYW1zID0gUmVmbGVjdC5nZXRPd25NZXRhZGF0YShcbiAgICAgIERlY29yYXRpb25LZXlzLkRFU0lHTl9QQVJBTVMsXG4gICAgICBvYmosXG4gICAgICBwcm9wXG4gICAgKTtcbiAgICBjb25zdCBkZXNpZ25SZXR1cm4gPSBSZWZsZWN0LmdldE93bk1ldGFkYXRhKFxuICAgICAgRGVjb3JhdGlvbktleXMuREVTSUdOX1JFVFVSTixcbiAgICAgIG9iaixcbiAgICAgIHByb3BcbiAgICApO1xuICAgIHJldHVybiBhcHBseShcbiAgICAgIG1ldGFkYXRhKFxuICAgICAgICBNZXRhZGF0YS5rZXkoXG4gICAgICAgICAgRGVjb3JhdGlvbktleXMuTUVUSE9EUyxcbiAgICAgICAgICBwcm9wLFxuICAgICAgICAgIERlY29yYXRpb25LZXlzLkRFU0lHTl9QQVJBTVNcbiAgICAgICAgKSxcbiAgICAgICAgZGVzaWduUGFyYW1zXG4gICAgICApLFxuICAgICAgbWV0YWRhdGEoXG4gICAgICAgIE1ldGFkYXRhLmtleShcbiAgICAgICAgICBEZWNvcmF0aW9uS2V5cy5NRVRIT0RTLFxuICAgICAgICAgIHByb3AsXG4gICAgICAgICAgRGVjb3JhdGlvbktleXMuREVTSUdOX1JFVFVSTlxuICAgICAgICApLFxuICAgICAgICBkZXNpZ25SZXR1cm5cbiAgICAgIClcbiAgICApKG9iaiwgcHJvcCwgZGVzY3JpcHRvcik7XG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlY29yYXRvciBmYWN0b3J5IHRoYXQgYXBwbGllcyBtdWx0aXBsZSBkZWNvcmF0b3JzIHRvIGEgc2luZ2xlIHRhcmdldC5cbiAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBjb21wb3NpdGUgZGVjb3JhdG9yIHRoYXQgYXBwbGllcyBtdWx0aXBsZSBkZWNvcmF0b3JzIGluIHNlcXVlbmNlLCBjb3JyZWN0bHkgaGFuZGxpbmcgY2xhc3MsIG1ldGhvZCwgcHJvcGVydHksIGFuZCBwYXJhbWV0ZXIgZGVjb3JhdG9ycy5cbiAqIEBwYXJhbSB7QXJyYXk8Q2xhc3NEZWNvcmF0b3J8TWV0aG9kRGVjb3JhdG9yfFByb3BlcnR5RGVjb3JhdG9yfFBhcmFtZXRlckRlY29yYXRvcj59IGRlY29yYXRvcnMgQ29sbGVjdGlvbiBvZiBkZWNvcmF0b3JzIHRvIGFwcGx5LlxuICogQHJldHVybiB7Q2xhc3NEZWNvcmF0b3J8TWV0aG9kRGVjb3JhdG9yfFByb3BlcnR5RGVjb3JhdG9yfFBhcmFtZXRlckRlY29yYXRvcn0gRGVjb3JhdG9yIGZ1bmN0aW9uIHRoYXQgYXBwbGllcyBhbGwgcHJvdmlkZWQgZGVjb3JhdG9ycyB0byB0aGUgdGFyZ2V0LlxuICogQGZ1bmN0aW9uIGFwcGx5XG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IFUgYXMgVXNlciBDb2RlXG4gKiAgIHBhcnRpY2lwYW50IEEgYXMgYXBwbHkoLi4uZGVjb3JhdG9ycylcbiAqICAgcGFydGljaXBhbnQgRCBhcyBEZWNvcmF0b3JcbiAqICAgVS0+PkE6IGdldCBkZWNvcmF0b3IoLi4uZGVjb3JhdG9ycylcbiAqICAgQS0+PlU6IHJldHVybnMgKHRhcmdldCwga2V5PywgZGVzYz8pID0+IHZvaWRcbiAqICAgVS0+PkE6IGludm9rZSBvbiB0YXJnZXRcbiAqICAgbG9vcCBmb3IgZWFjaCBkZWNvcmF0b3JcbiAqICAgICBBLT4+RDogaW52b2tlIGFwcHJvcHJpYXRlIGRlY29yYXRvciB0eXBlXG4gKiAgIGVuZFxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5KFxuICAuLi5kZWNvcmF0b3JzOiBBcnJheTxcbiAgICBDbGFzc0RlY29yYXRvciB8IE1ldGhvZERlY29yYXRvciB8IFByb3BlcnR5RGVjb3JhdG9yIHwgUGFyYW1ldGVyRGVjb3JhdG9yXG4gID5cbikge1xuICByZXR1cm4gKFxuICAgIHRhcmdldDogb2JqZWN0LFxuICAgIHByb3BlcnR5S2V5Pzogc3RyaW5nIHwgc3ltYm9sIHwgdW5rbm93bixcbiAgICBkZXNjcmlwdG9yPzogUHJvcGVydHlEZXNjcmlwdG9yIHwgbnVtYmVyXG4gICkgPT4ge1xuICAgIGZvciAoY29uc3QgZGVjb3JhdG9yIG9mIGRlY29yYXRvcnMpIHtcbiAgICAgIGlmICh0YXJnZXQgaW5zdGFuY2VvZiBGdW5jdGlvbiAmJiAhZGVzY3JpcHRvcikge1xuICAgICAgICAoZGVjb3JhdG9yIGFzIENsYXNzRGVjb3JhdG9yKSh0YXJnZXQpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIChkZWNvcmF0b3IgYXMgTWV0aG9kRGVjb3JhdG9yIHwgUHJvcGVydHlEZWNvcmF0b3IpKFxuICAgICAgICB0YXJnZXQsXG4gICAgICAgIHByb3BlcnR5S2V5IGFzIHN0cmluZyB8IHN5bWJvbCxcbiAgICAgICAgZGVzY3JpcHRvciBhcyBUeXBlZFByb3BlcnR5RGVzY3JpcHRvcjx1bmtub3duPlxuICAgICAgKTtcbiAgICB9XG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBwcm9wZXJ0eSBtZXRhZGF0YSBkZWNvcmF0b3IuXG4gKiBAc3VtbWFyeSBDb252ZW5pZW5jZSBmYWN0b3J5IHRoYXQgY29tYmluZXMgYG1ldGFkYXRhKGtleSwgdmFsdWUpYCBhbmQgYHByb3AoKWAgdG8gYm90aCBzZXQgYW4gYXJiaXRyYXJ5IG1ldGFkYXRhIGtleSBhbmQgcmVjb3JkIHRoZSBwcm9wZXJ0eSdzIGRlc2lnbiB0eXBlLlxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBNZXRhZGF0YSBrZXkgdG8gc2V0IGZvciB0aGUgcHJvcGVydHkuXG4gKiBAcGFyYW0ge2FueX0gdmFsdWUgTWV0YWRhdGEgdmFsdWUgdG8gYXNzb2NpYXRlIHdpdGggdGhlIGtleS5cbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBEZWNvcmF0b3IgdGhhdCBzZXRzIHRoZSBtZXRhZGF0YSBhbmQgY2FwdHVyZXMgdGhlIHByb3BlcnR5J3MgdHlwZS5cbiAqIEBmdW5jdGlvbiBwcm9wTWV0YWRhdGFcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcm9wTWV0YWRhdGEoa2V5OiBzdHJpbmcsIHZhbHVlOiBhbnkpIHtcbiAgcmV0dXJuIGFwcGx5KG1ldGFkYXRhKGtleSwgdmFsdWUpLCBwcm9wKCkpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbWV0aG9kIG1ldGFkYXRhIGRlY29yYXRvci5cbiAqIEBzdW1tYXJ5IENvbnZlbmllbmNlIGZhY3RvcnkgdGhhdCBjb21iaW5lcyBgbWV0YWRhdGEoa2V5LCB2YWx1ZSlgIGFuZCBgbWV0aG9kKClgIHRvIGJvdGggc2V0IGFuIGFyYml0cmFyeSBtZXRhZGF0YSBrZXkgYW5kIHJlY29yZCB0aGUgbWV0aG9kJ3MgZGVzaWduIHJldHVybiBhbmQgcGFyYW0gdHlwZXMuXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IE1ldGFkYXRhIGtleSB0byBzZXQgZm9yIHRoZSBwcm9wZXJ0eS5cbiAqIEBwYXJhbSB7YW55fSB2YWx1ZSBNZXRhZGF0YSB2YWx1ZSB0byBhc3NvY2lhdGUgd2l0aCB0aGUga2V5LlxuICogQHJldHVybiB7UHJvcGVydHlEZWNvcmF0b3J9IERlY29yYXRvciB0aGF0IHNldHMgdGhlIG1ldGFkYXRhIGFuZCBjYXB0dXJlcyB0aGUgcHJvcGVydHkncyB0eXBlLlxuICogQGZ1bmN0aW9uIG1ldGhvZE1ldGFkYXRhXG4gKiBAY2F0ZWdvcnkgTWV0aG9kIERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1ldGhvZE1ldGFkYXRhKGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XG4gIHJldHVybiBhcHBseShtZXRhZGF0YShrZXksIHZhbHVlKSwgbWV0aG9kKCkpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBdHRhY2hlcyBhIGh1bWFuLXJlYWRhYmxlIGRlc2NyaXB0aW9uIHRvIGEgY2xhc3Mgb3IgbWVtYmVyLlxuICogQHN1bW1hcnkgRGVjb3JhdG9yIGZhY3RvcnkgdGhhdCBzdG9yZXMgYSB0ZXh0dWFsIGRlc2NyaXB0aW9uIGluIHRoZSBtZXRhZGF0YSBzdG9yZSB1bmRlciB0aGUgYXBwcm9wcmlhdGUgZGVzY3JpcHRpb24ga2V5IGZvciBhIGNsYXNzIG9yIGl0cyBwcm9wZXJ0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkZXNjIERlc2NyaXB0aXZlIHRleHQgdG8gYXNzb2NpYXRlIHdpdGggdGhlIGNsYXNzIG9yIHByb3BlcnR5LlxuICogQHJldHVybiB7Q2xhc3NEZWNvcmF0b3J8TWV0aG9kRGVjb3JhdG9yfFByb3BlcnR5RGVjb3JhdG9yfSBEZWNvcmF0b3IgdGhhdCByZWNvcmRzIHRoZSBkZXNjcmlwdGlvbiB3aGVuIGFwcGxpZWQuXG4gKiBAZnVuY3Rpb24gZGVzY3JpcHRpb25cbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZXNjcmlwdGlvbihkZXNjOiBzdHJpbmcpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIGRlc2NyaXB0aW9uKG9yaWdpbmFsOiBhbnksIHByb3A/OiBhbnksIGRlc2NyaXB0b3I/OiBhbnkpIHtcbiAgICByZXR1cm4gbWV0YWRhdGEoXG4gICAgICBbXG4gICAgICAgIERlY29yYXRpb25LZXlzLkRFU0NSSVBUSU9OLFxuICAgICAgICBwcm9wID8gcHJvcC50b1N0cmluZygpIDogRGVjb3JhdGlvbktleXMuQ0xBU1MsXG4gICAgICBdLmpvaW4oTWV0YWRhdGEuc3BsaXR0ZXIpLFxuICAgICAgZGVzY1xuICAgICkob3JpZ2luYWwsIHByb3AsIGRlc2NyaXB0b3IpO1xuICB9O1xufVxuIiwiLyoqXG4gKiBAZGVzY3JpcHRpb24gUm9vdCBlbnRyeSBwb2ludCBmb3IgdGhlIGRlY29yYXRpb24gbW9kdWxlLlxuICogQHN1bW1hcnkgQWdncmVnYXRlcyBhbmQgcmUtZXhwb3J0cyB0aGUgcHVibGljIEFQSSBvZiB0aGUgZGVjb3JhdGlvbiBsaWJyYXJ5LCBpbmNsdWRpbmcge0BsaW5rIERlY29yYXRpb259LCBkZWNvcmF0b3IgdXRpbGl0aWVzIGZyb20ge0BsaW5rIG1vZHVsZTpkZWNvcmF0aW9ufC4vZGVjb3JhdG9yc30sIHtAbGluayBNZXRhZGF0YX0sIGFuZCBzaGFyZWQgY29uc3RhbnRzIHN1Y2ggYXMge0BsaW5rIERlY29yYXRpb25LZXlzfSBhbmQge0BsaW5rIERlZmF1bHRGbGF2b3VyfS4gVGhpcyBpcyB0aGUgcHJpbWFyeSBpbXBvcnQgc3VyZmFjZSBmb3IgY29uc3VtZXJzIGFuZCBleHBvc2VzOlxuICogLSBDb3JlIGJ1aWxkZXI6IHtAbGluayBEZWNvcmF0aW9ufVxuICogLSBEZWNvcmF0b3IgdXRpbGl0aWVzOiB7QGxpbmsgbW9kdWxlOmRlY29yYXRpb258ZGVjb3JhdG9ycyBpbiAuL2RlY29yYXRvcnN9XG4gKiAtIE1ldGFkYXRhIHV0aWxpdGllczoge0BsaW5rIE1ldGFkYXRhfVxuICogLSBDb25zdGFudHMgYW5kIGVudW1zOiB7QGxpbmsgRGVjb3JhdGlvbktleXN9LCB7QGxpbmsgRGVmYXVsdEZsYXZvdXJ9XG4gKiBAbW9kdWxlIGRlY29yYXRpb25cbiAqL1xuXG5pbXBvcnQgeyBNZXRhZGF0YSB9IGZyb20gXCIuL21ldGFkYXRhL2luZGV4XCI7XG5cbmV4cG9ydCAqIGZyb20gXCIuL2RlY29yYXRpb25cIjtcbmV4cG9ydCAqIGZyb20gXCIuL21ldGFkYXRhXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2RlY29yYXRvcnNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ3VycmVudCB2ZXJzaW9uIG9mIHRoZSByZWZsZWN0aW9uIHBhY2thZ2VcbiAqIEBzdW1tYXJ5IFN0b3JlcyB0aGUgc2VtYW50aWMgdmVyc2lvbiBudW1iZXIgb2YgdGhlIHBhY2thZ2VcbiAqIEBjb25zdCBWRVJTSU9OXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRpb25cbiAqL1xuZXhwb3J0IGNvbnN0IFZFUlNJT04gPSBcIiMjVkVSU0lPTiMjXCI7XG5cbk1ldGFkYXRhLnJlZ2lzdGVyTGlicmFyeShcIkBkZWNhZi10cy9kZWNvcmF0aW9uXCIsIFZFUlNJT04pO1xuIl0sIm5hbWVzIjpbIkRlY29yYXRpb25LZXlzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7SUFFQTs7Ozs7SUFLRztBQUNJLFVBQU0sY0FBYyxHQUFHO0lBRTlCOzs7OztJQUtHO0FBQ0ksVUFBTSxpQkFBaUIsR0FBRztJQUVqQzs7Ozs7OztJQU9HO0FBQ1NBO0lBQVosQ0FBQSxVQUFZLGNBQWMsRUFBQTs7SUFFeEIsSUFBQSxjQUFBLENBQUEsV0FBQSxDQUFBLEdBQUEsV0FBdUI7O0lBRXZCLElBQUEsY0FBQSxDQUFBLFNBQUEsQ0FBQSxHQUFBLFNBQStCOztJQUUvQixJQUFBLGNBQUEsQ0FBQSxZQUFBLENBQUEsR0FBQSxZQUF5Qjs7SUFFekIsSUFBQSxjQUFBLENBQUEsU0FBQSxDQUFBLEdBQUEsU0FBbUI7O0lBRW5CLElBQUEsY0FBQSxDQUFBLE9BQUEsQ0FBQSxHQUFBLE9BQWU7O0lBRWYsSUFBQSxjQUFBLENBQUEsYUFBQSxDQUFBLEdBQUEsYUFBMkI7O0lBRTNCLElBQUEsY0FBQSxDQUFBLGFBQUEsQ0FBQSxHQUFBLGFBQTJCOztJQUUzQixJQUFBLGNBQUEsQ0FBQSxZQUFB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