@ng-formworks/core 18.5.1 → 19.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/fesm2022/ng-formworks-core.mjs +130 -110
- package/fesm2022/ng-formworks-core.mjs.map +1 -1
- package/package.json +3 -3
- package/esm2022/lib/framework-library/framework-library.service.mjs +0 -172
- package/esm2022/lib/framework-library/framework.mjs +0 -15
- package/esm2022/lib/framework-library/no-framework.component.mjs +0 -17
- package/esm2022/lib/framework-library/no-framework.module.mjs +0 -27
- package/esm2022/lib/framework-library/no.framework.mjs +0 -19
- package/esm2022/lib/json-schema-form.component.mjs +0 -759
- package/esm2022/lib/json-schema-form.module.mjs +0 -26
- package/esm2022/lib/json-schema-form.service.mjs +0 -695
- package/esm2022/lib/locale/de-validation-messages.mjs +0 -60
- package/esm2022/lib/locale/en-validation-messages.mjs +0 -60
- package/esm2022/lib/locale/es-validation-messages.mjs +0 -57
- package/esm2022/lib/locale/fr-validation-messages.mjs +0 -60
- package/esm2022/lib/locale/index.mjs +0 -8
- package/esm2022/lib/locale/it-validation-messages.mjs +0 -60
- package/esm2022/lib/locale/pt-validation-messages.mjs +0 -60
- package/esm2022/lib/locale/zh-validation-messages.mjs +0 -60
- package/esm2022/lib/shared/convert-schema-to-draft6.function.mjs +0 -300
- package/esm2022/lib/shared/form-group.functions.mjs +0 -444
- package/esm2022/lib/shared/format-regex.constants.mjs +0 -54
- package/esm2022/lib/shared/index.mjs +0 -12
- package/esm2022/lib/shared/json-schema.functions.mjs +0 -784
- package/esm2022/lib/shared/json.validators.mjs +0 -884
- package/esm2022/lib/shared/jsonpointer.functions.mjs +0 -1026
- package/esm2022/lib/shared/layout.functions.mjs +0 -1158
- package/esm2022/lib/shared/merge-schemas.function.mjs +0 -345
- package/esm2022/lib/shared/utility.functions.mjs +0 -380
- package/esm2022/lib/shared/validator.functions.mjs +0 -584
- package/esm2022/lib/widget-library/add-reference.component.mjs +0 -58
- package/esm2022/lib/widget-library/button.component.mjs +0 -69
- package/esm2022/lib/widget-library/checkbox.component.mjs +0 -102
- package/esm2022/lib/widget-library/checkboxes.component.mjs +0 -145
- package/esm2022/lib/widget-library/file.component.mjs +0 -32
- package/esm2022/lib/widget-library/hidden.component.mjs +0 -51
- package/esm2022/lib/widget-library/index.mjs +0 -55
- package/esm2022/lib/widget-library/input.component.mjs +0 -116
- package/esm2022/lib/widget-library/message.component.mjs +0 -35
- package/esm2022/lib/widget-library/none.component.mjs +0 -20
- package/esm2022/lib/widget-library/number.component.mjs +0 -120
- package/esm2022/lib/widget-library/one-of.component.mjs +0 -32
- package/esm2022/lib/widget-library/orderable.directive.mjs +0 -120
- package/esm2022/lib/widget-library/radios.component.mjs +0 -151
- package/esm2022/lib/widget-library/root.component.mjs +0 -73
- package/esm2022/lib/widget-library/section.component.mjs +0 -196
- package/esm2022/lib/widget-library/select-framework.component.mjs +0 -44
- package/esm2022/lib/widget-library/select-widget.component.mjs +0 -42
- package/esm2022/lib/widget-library/select.component.mjs +0 -147
- package/esm2022/lib/widget-library/submit.component.mjs +0 -79
- package/esm2022/lib/widget-library/tab.component.mjs +0 -38
- package/esm2022/lib/widget-library/tabs.component.mjs +0 -106
- package/esm2022/lib/widget-library/template.component.mjs +0 -43
- package/esm2022/lib/widget-library/textarea.component.mjs +0 -101
- package/esm2022/lib/widget-library/widget-library.module.mjs +0 -42
- package/esm2022/lib/widget-library/widget-library.service.mjs +0 -226
- package/esm2022/ng-formworks-core.mjs +0 -5
- package/esm2022/public_api.mjs +0 -13
|
@@ -1,884 +0,0 @@
|
|
|
1
|
-
import isEqual from 'lodash/isEqual';
|
|
2
|
-
import { _executeAsyncValidators, _executeValidators, _mergeErrors, _mergeObjects, getType, hasValue, isArray, isBoolean, isDefined, isEmpty, isNumber, isString, isType, toJavaScriptType, toObservable, xor } from './validator.functions';
|
|
3
|
-
import { forEachCopy } from './utility.functions';
|
|
4
|
-
import { forkJoin } from 'rxjs';
|
|
5
|
-
import { jsonSchemaFormatTests } from './format-regex.constants';
|
|
6
|
-
import { map } from 'rxjs/operators';
|
|
7
|
-
/**
|
|
8
|
-
* 'JsonValidators' class
|
|
9
|
-
*
|
|
10
|
-
* Provides an extended set of validators to be used by form controls,
|
|
11
|
-
* compatible with standard JSON Schema validation options.
|
|
12
|
-
* http://json-schema.org/latest/json-schema-validation.html
|
|
13
|
-
*
|
|
14
|
-
* Note: This library is designed as a drop-in replacement for the Angular
|
|
15
|
-
* Validators library, and except for one small breaking change to the 'pattern'
|
|
16
|
-
* validator (described below) it can even be imported as a substitute, like so:
|
|
17
|
-
*
|
|
18
|
-
* import { JsonValidators as Validators } from 'json-validators';
|
|
19
|
-
*
|
|
20
|
-
* and it should work with existing code as a complete replacement.
|
|
21
|
-
*
|
|
22
|
-
* The one exception is the 'pattern' validator, which has been changed to
|
|
23
|
-
* matche partial values by default (the standard 'pattern' validator wrapped
|
|
24
|
-
* all patterns in '^' and '$', forcing them to always match an entire value).
|
|
25
|
-
* However, the old behavior can be restored by simply adding '^' and '$'
|
|
26
|
-
* around your patterns, or by passing an optional second parameter of TRUE.
|
|
27
|
-
* This change is to make the 'pattern' validator match the behavior of a
|
|
28
|
-
* JSON Schema pattern, which allows partial matches, rather than the behavior
|
|
29
|
-
* of an HTML input control pattern, which does not.
|
|
30
|
-
*
|
|
31
|
-
* This library replaces Angular's validators and combination functions
|
|
32
|
-
* with the following validators and transformation functions:
|
|
33
|
-
*
|
|
34
|
-
* Validators:
|
|
35
|
-
* For all formControls: required (*), type, enum, const
|
|
36
|
-
* For text formControls: minLength (*), maxLength (*), pattern (*), format
|
|
37
|
-
* For numeric formControls: maximum, exclusiveMaximum,
|
|
38
|
-
* minimum, exclusiveMinimum, multipleOf
|
|
39
|
-
* For formGroup objects: minProperties, maxProperties, dependencies
|
|
40
|
-
* For formArray arrays: minItems, maxItems, uniqueItems, contains
|
|
41
|
-
* Not used by JSON Schema: min (*), max (*), requiredTrue (*), email (*)
|
|
42
|
-
* (Validators originally included with Angular are maked with (*).)
|
|
43
|
-
*
|
|
44
|
-
* NOTE / TODO: The dependencies validator is not complete.
|
|
45
|
-
* NOTE / TODO: The contains validator is not complete.
|
|
46
|
-
*
|
|
47
|
-
* Validators not used by JSON Schema (but included for compatibility)
|
|
48
|
-
* and their JSON Schema equivalents:
|
|
49
|
-
*
|
|
50
|
-
* Angular validator | JSON Schema equivalent
|
|
51
|
-
* ------------------|-----------------------
|
|
52
|
-
* min(number) | minimum(number)
|
|
53
|
-
* max(number) | maximum(number)
|
|
54
|
-
* requiredTrue() | const(true)
|
|
55
|
-
* email() | format('email')
|
|
56
|
-
*
|
|
57
|
-
* Validator transformation functions:
|
|
58
|
-
* composeAnyOf, composeOneOf, composeAllOf, composeNot
|
|
59
|
-
* (Angular's original combination funciton, 'compose', is also included for
|
|
60
|
-
* backward compatibility, though it is functionally equivalent to composeAllOf,
|
|
61
|
-
* asside from its more generic error message.)
|
|
62
|
-
*
|
|
63
|
-
* All validators have also been extended to accept an optional second argument
|
|
64
|
-
* which, if passed a TRUE value, causes the validator to perform the opposite
|
|
65
|
-
* of its original finction. (This is used internally to enable 'not' and
|
|
66
|
-
* 'composeOneOf' to function and return useful error messages.)
|
|
67
|
-
*
|
|
68
|
-
* The 'required' validator has also been overloaded so that if called with
|
|
69
|
-
* a boolean parameter (or no parameters) it returns the original validator
|
|
70
|
-
* function (rather than executing it). However, if it is called with an
|
|
71
|
-
* AbstractControl parameter (as was previously required), it behaves
|
|
72
|
-
* exactly as before.
|
|
73
|
-
*
|
|
74
|
-
* This enables all validators (including 'required') to be constructed in
|
|
75
|
-
* exactly the same way, so they can be automatically applied using the
|
|
76
|
-
* equivalent key names and values taken directly from a JSON Schema.
|
|
77
|
-
*
|
|
78
|
-
* This source code is partially derived from Angular,
|
|
79
|
-
* which is Copyright (c) 2014-2017 Google, Inc.
|
|
80
|
-
* Use of this source code is therefore governed by the same MIT-style license
|
|
81
|
-
* that can be found in the LICENSE file at https://angular.io/license
|
|
82
|
-
*
|
|
83
|
-
* Original Angular Validators:
|
|
84
|
-
* https://github.com/angular/angular/blob/master/packages/forms/src/validators.ts
|
|
85
|
-
*/
|
|
86
|
-
export class JsonValidators {
|
|
87
|
-
static required(input) {
|
|
88
|
-
if (input === undefined) {
|
|
89
|
-
input = true;
|
|
90
|
-
}
|
|
91
|
-
switch (input) {
|
|
92
|
-
case true: // Return required function (do not execute it yet)
|
|
93
|
-
return (control, invert = false) => {
|
|
94
|
-
if (invert) {
|
|
95
|
-
return null;
|
|
96
|
-
} // if not required, always return valid
|
|
97
|
-
return hasValue(control.value) ? null : { 'required': true };
|
|
98
|
-
};
|
|
99
|
-
case false: // Do nothing (if field is not required, it is always valid)
|
|
100
|
-
return JsonValidators.nullValidator;
|
|
101
|
-
default: // Execute required function
|
|
102
|
-
return hasValue(input.value) ? null : { 'required': true };
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* 'type' validator
|
|
107
|
-
*
|
|
108
|
-
* Requires a control to only accept values of a specified type,
|
|
109
|
-
* or one of an array of types.
|
|
110
|
-
*
|
|
111
|
-
* Note: SchemaPrimitiveType = 'string'|'number'|'integer'|'boolean'|'null'
|
|
112
|
-
*
|
|
113
|
-
* // {SchemaPrimitiveType|SchemaPrimitiveType[]} type - type(s) to accept
|
|
114
|
-
* // {IValidatorFn}
|
|
115
|
-
*/
|
|
116
|
-
static type(requiredType) {
|
|
117
|
-
if (!hasValue(requiredType)) {
|
|
118
|
-
return JsonValidators.nullValidator;
|
|
119
|
-
}
|
|
120
|
-
return (control, invert = false) => {
|
|
121
|
-
if (isEmpty(control.value)) {
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
const currentValue = control.value;
|
|
125
|
-
const isValid = isArray(requiredType) ?
|
|
126
|
-
requiredType.some(type => isType(currentValue, type)) :
|
|
127
|
-
isType(currentValue, requiredType);
|
|
128
|
-
return xor(isValid, invert) ?
|
|
129
|
-
null : { 'type': { requiredType, currentValue } };
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* 'enum' validator
|
|
134
|
-
*
|
|
135
|
-
* Requires a control to have a value from an enumerated list of values.
|
|
136
|
-
*
|
|
137
|
-
* Converts types as needed to allow string inputs to still correctly
|
|
138
|
-
* match number, boolean, and null enum values.
|
|
139
|
-
*
|
|
140
|
-
* // {any[]} allowedValues - array of acceptable values
|
|
141
|
-
* // {IValidatorFn}
|
|
142
|
-
*/
|
|
143
|
-
static enum(allowedValues) {
|
|
144
|
-
if (!isArray(allowedValues)) {
|
|
145
|
-
return JsonValidators.nullValidator;
|
|
146
|
-
}
|
|
147
|
-
return (control, invert = false) => {
|
|
148
|
-
if (isEmpty(control.value)) {
|
|
149
|
-
return null;
|
|
150
|
-
}
|
|
151
|
-
const currentValue = control.value;
|
|
152
|
-
const isEqualVal = (enumValue, inputValue) => enumValue === inputValue ||
|
|
153
|
-
(isNumber(enumValue) && +inputValue === +enumValue) ||
|
|
154
|
-
(isBoolean(enumValue, 'strict') &&
|
|
155
|
-
toJavaScriptType(inputValue, 'boolean') === enumValue) ||
|
|
156
|
-
(enumValue === null && !hasValue(inputValue)) ||
|
|
157
|
-
isEqual(enumValue, inputValue);
|
|
158
|
-
const isValid = isArray(currentValue) ?
|
|
159
|
-
currentValue.every(inputValue => allowedValues.some(enumValue => isEqualVal(enumValue, inputValue))) :
|
|
160
|
-
allowedValues.some(enumValue => isEqualVal(enumValue, currentValue));
|
|
161
|
-
return xor(isValid, invert) ?
|
|
162
|
-
null : { 'enum': { allowedValues, currentValue } };
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* 'const' validator
|
|
167
|
-
*
|
|
168
|
-
* Requires a control to have a specific value.
|
|
169
|
-
*
|
|
170
|
-
* Converts types as needed to allow string inputs to still correctly
|
|
171
|
-
* match number, boolean, and null values.
|
|
172
|
-
*
|
|
173
|
-
* TODO: modify to work with objects
|
|
174
|
-
*
|
|
175
|
-
* // {any[]} requiredValue - required value
|
|
176
|
-
* // {IValidatorFn}
|
|
177
|
-
*/
|
|
178
|
-
static const(requiredValue) {
|
|
179
|
-
if (!hasValue(requiredValue)) {
|
|
180
|
-
return JsonValidators.nullValidator;
|
|
181
|
-
}
|
|
182
|
-
return (control, invert = false) => {
|
|
183
|
-
if (isEmpty(control.value)) {
|
|
184
|
-
return null;
|
|
185
|
-
}
|
|
186
|
-
const currentValue = control.value;
|
|
187
|
-
const isEqualVal = (constValue, inputValue) => constValue === inputValue ||
|
|
188
|
-
isNumber(constValue) && +inputValue === +constValue ||
|
|
189
|
-
isBoolean(constValue, 'strict') &&
|
|
190
|
-
toJavaScriptType(inputValue, 'boolean') === constValue ||
|
|
191
|
-
constValue === null && !hasValue(inputValue);
|
|
192
|
-
const isValid = isEqualVal(requiredValue, currentValue);
|
|
193
|
-
return xor(isValid, invert) ?
|
|
194
|
-
null : { 'const': { requiredValue, currentValue } };
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* 'minLength' validator
|
|
199
|
-
*
|
|
200
|
-
* Requires a control's text value to be greater than a specified length.
|
|
201
|
-
*
|
|
202
|
-
* // {number} minimumLength - minimum allowed string length
|
|
203
|
-
* // {boolean = false} invert - instead return error object only if valid
|
|
204
|
-
* // {IValidatorFn}
|
|
205
|
-
*/
|
|
206
|
-
static minLength(minimumLength) {
|
|
207
|
-
if (!hasValue(minimumLength)) {
|
|
208
|
-
return JsonValidators.nullValidator;
|
|
209
|
-
}
|
|
210
|
-
return (control, invert = false) => {
|
|
211
|
-
if (isEmpty(control.value)) {
|
|
212
|
-
return null;
|
|
213
|
-
}
|
|
214
|
-
const currentLength = isString(control.value) ? control.value.length : 0;
|
|
215
|
-
const isValid = currentLength >= minimumLength;
|
|
216
|
-
return xor(isValid, invert) ?
|
|
217
|
-
null : { 'minLength': { minimumLength, currentLength } };
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* 'maxLength' validator
|
|
222
|
-
*
|
|
223
|
-
* Requires a control's text value to be less than a specified length.
|
|
224
|
-
*
|
|
225
|
-
* // {number} maximumLength - maximum allowed string length
|
|
226
|
-
* // {boolean = false} invert - instead return error object only if valid
|
|
227
|
-
* // {IValidatorFn}
|
|
228
|
-
*/
|
|
229
|
-
static maxLength(maximumLength) {
|
|
230
|
-
if (!hasValue(maximumLength)) {
|
|
231
|
-
return JsonValidators.nullValidator;
|
|
232
|
-
}
|
|
233
|
-
return (control, invert = false) => {
|
|
234
|
-
const currentLength = isString(control.value) ? control.value.length : 0;
|
|
235
|
-
const isValid = currentLength <= maximumLength;
|
|
236
|
-
return xor(isValid, invert) ?
|
|
237
|
-
null : { 'maxLength': { maximumLength, currentLength } };
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* 'pattern' validator
|
|
242
|
-
*
|
|
243
|
-
* Note: NOT the same as Angular's default pattern validator.
|
|
244
|
-
*
|
|
245
|
-
* Requires a control's value to match a specified regular expression pattern.
|
|
246
|
-
*
|
|
247
|
-
* This validator changes the behavior of default pattern validator
|
|
248
|
-
* by replacing RegExp(`^${pattern}$`) with RegExp(`${pattern}`),
|
|
249
|
-
* which allows for partial matches.
|
|
250
|
-
*
|
|
251
|
-
* To return to the default funcitonality, and match the entire string,
|
|
252
|
-
* pass TRUE as the optional second parameter.
|
|
253
|
-
*
|
|
254
|
-
* // {string} pattern - regular expression pattern
|
|
255
|
-
* // {boolean = false} wholeString - match whole value string?
|
|
256
|
-
* // {IValidatorFn}
|
|
257
|
-
*/
|
|
258
|
-
static pattern(pattern, wholeString = false) {
|
|
259
|
-
if (!hasValue(pattern)) {
|
|
260
|
-
return JsonValidators.nullValidator;
|
|
261
|
-
}
|
|
262
|
-
return (control, invert = false) => {
|
|
263
|
-
if (isEmpty(control.value)) {
|
|
264
|
-
return null;
|
|
265
|
-
}
|
|
266
|
-
let regex;
|
|
267
|
-
let requiredPattern;
|
|
268
|
-
if (typeof pattern === 'string') {
|
|
269
|
-
requiredPattern = (wholeString) ? `^${pattern}$` : pattern;
|
|
270
|
-
regex = new RegExp(requiredPattern);
|
|
271
|
-
}
|
|
272
|
-
else {
|
|
273
|
-
requiredPattern = pattern.toString();
|
|
274
|
-
regex = pattern;
|
|
275
|
-
}
|
|
276
|
-
const currentValue = control.value;
|
|
277
|
-
const isValid = isString(currentValue) ? regex.test(currentValue) : false;
|
|
278
|
-
return xor(isValid, invert) ?
|
|
279
|
-
null : { 'pattern': { requiredPattern, currentValue } };
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* 'format' validator
|
|
284
|
-
*
|
|
285
|
-
* Requires a control to have a value of a certain format.
|
|
286
|
-
*
|
|
287
|
-
* This validator currently checks the following formsts:
|
|
288
|
-
* date, time, date-time, email, hostname, ipv4, ipv6,
|
|
289
|
-
* uri, uri-reference, uri-template, url, uuid, color,
|
|
290
|
-
* json-pointer, relative-json-pointer, regex
|
|
291
|
-
*
|
|
292
|
-
* Fast format regular expressions copied from AJV:
|
|
293
|
-
* https://github.com/epoberezkin/ajv/blob/master/lib/compile/formats.js
|
|
294
|
-
*
|
|
295
|
-
* // {JsonSchemaFormatNames} requiredFormat - format to check
|
|
296
|
-
* // {IValidatorFn}
|
|
297
|
-
*/
|
|
298
|
-
static format(requiredFormat) {
|
|
299
|
-
if (!hasValue(requiredFormat)) {
|
|
300
|
-
return JsonValidators.nullValidator;
|
|
301
|
-
}
|
|
302
|
-
return (control, invert = false) => {
|
|
303
|
-
if (isEmpty(control.value)) {
|
|
304
|
-
return null;
|
|
305
|
-
}
|
|
306
|
-
let isValid;
|
|
307
|
-
const currentValue = control.value;
|
|
308
|
-
if (isString(currentValue)) {
|
|
309
|
-
const formatTest = jsonSchemaFormatTests[requiredFormat];
|
|
310
|
-
if (typeof formatTest === 'object') {
|
|
311
|
-
isValid = formatTest.test(currentValue);
|
|
312
|
-
}
|
|
313
|
-
else if (typeof formatTest === 'function') {
|
|
314
|
-
isValid = formatTest(currentValue);
|
|
315
|
-
}
|
|
316
|
-
else {
|
|
317
|
-
console.error(`format validator error: "${requiredFormat}" is not a recognized format.`);
|
|
318
|
-
isValid = true;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
else {
|
|
322
|
-
// Allow JavaScript Date objects
|
|
323
|
-
isValid = ['date', 'time', 'date-time'].includes(requiredFormat) &&
|
|
324
|
-
Object.prototype.toString.call(currentValue) === '[object Date]';
|
|
325
|
-
}
|
|
326
|
-
return xor(isValid, invert) ?
|
|
327
|
-
null : { 'format': { requiredFormat, currentValue } };
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* 'minimum' validator
|
|
332
|
-
*
|
|
333
|
-
* Requires a control's numeric value to be greater than or equal to
|
|
334
|
-
* a minimum amount.
|
|
335
|
-
*
|
|
336
|
-
* Any non-numeric value is also valid (according to the HTML forms spec,
|
|
337
|
-
* a non-numeric value doesn't have a minimum).
|
|
338
|
-
* https://www.w3.org/TR/html5/forms.html#attr-input-max
|
|
339
|
-
*
|
|
340
|
-
* // {number} minimum - minimum allowed value
|
|
341
|
-
* // {IValidatorFn}
|
|
342
|
-
*/
|
|
343
|
-
static minimum(minimumValue) {
|
|
344
|
-
if (!hasValue(minimumValue)) {
|
|
345
|
-
return JsonValidators.nullValidator;
|
|
346
|
-
}
|
|
347
|
-
return (control, invert = false) => {
|
|
348
|
-
if (isEmpty(control.value)) {
|
|
349
|
-
return null;
|
|
350
|
-
}
|
|
351
|
-
const currentValue = control.value;
|
|
352
|
-
const isValid = !isNumber(currentValue) || currentValue >= minimumValue;
|
|
353
|
-
return xor(isValid, invert) ?
|
|
354
|
-
null : { 'minimum': { minimumValue, currentValue } };
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
/**
|
|
358
|
-
* 'exclusiveMinimum' validator
|
|
359
|
-
*
|
|
360
|
-
* Requires a control's numeric value to be less than a maximum amount.
|
|
361
|
-
*
|
|
362
|
-
* Any non-numeric value is also valid (according to the HTML forms spec,
|
|
363
|
-
* a non-numeric value doesn't have a maximum).
|
|
364
|
-
* https://www.w3.org/TR/html5/forms.html#attr-input-max
|
|
365
|
-
*
|
|
366
|
-
* // {number} exclusiveMinimumValue - maximum allowed value
|
|
367
|
-
* // {IValidatorFn}
|
|
368
|
-
*/
|
|
369
|
-
static exclusiveMinimum(exclusiveMinimumValue) {
|
|
370
|
-
if (!hasValue(exclusiveMinimumValue)) {
|
|
371
|
-
return JsonValidators.nullValidator;
|
|
372
|
-
}
|
|
373
|
-
return (control, invert = false) => {
|
|
374
|
-
if (isEmpty(control.value)) {
|
|
375
|
-
return null;
|
|
376
|
-
}
|
|
377
|
-
const currentValue = control.value;
|
|
378
|
-
const isValid = !isNumber(currentValue) || +currentValue < exclusiveMinimumValue;
|
|
379
|
-
return xor(isValid, invert) ?
|
|
380
|
-
null : { 'exclusiveMinimum': { exclusiveMinimumValue, currentValue } };
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
/**
|
|
384
|
-
* 'maximum' validator
|
|
385
|
-
*
|
|
386
|
-
* Requires a control's numeric value to be less than or equal to
|
|
387
|
-
* a maximum amount.
|
|
388
|
-
*
|
|
389
|
-
* Any non-numeric value is also valid (according to the HTML forms spec,
|
|
390
|
-
* a non-numeric value doesn't have a maximum).
|
|
391
|
-
* https://www.w3.org/TR/html5/forms.html#attr-input-max
|
|
392
|
-
*
|
|
393
|
-
* // {number} maximumValue - maximum allowed value
|
|
394
|
-
* // {IValidatorFn}
|
|
395
|
-
*/
|
|
396
|
-
static maximum(maximumValue) {
|
|
397
|
-
if (!hasValue(maximumValue)) {
|
|
398
|
-
return JsonValidators.nullValidator;
|
|
399
|
-
}
|
|
400
|
-
return (control, invert = false) => {
|
|
401
|
-
if (isEmpty(control.value)) {
|
|
402
|
-
return null;
|
|
403
|
-
}
|
|
404
|
-
const currentValue = control.value;
|
|
405
|
-
const isValid = !isNumber(currentValue) || +currentValue <= maximumValue;
|
|
406
|
-
return xor(isValid, invert) ?
|
|
407
|
-
null : { 'maximum': { maximumValue, currentValue } };
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
|
-
/**
|
|
411
|
-
* 'exclusiveMaximum' validator
|
|
412
|
-
*
|
|
413
|
-
* Requires a control's numeric value to be less than a maximum amount.
|
|
414
|
-
*
|
|
415
|
-
* Any non-numeric value is also valid (according to the HTML forms spec,
|
|
416
|
-
* a non-numeric value doesn't have a maximum).
|
|
417
|
-
* https://www.w3.org/TR/html5/forms.html#attr-input-max
|
|
418
|
-
*
|
|
419
|
-
* // {number} exclusiveMaximumValue - maximum allowed value
|
|
420
|
-
* // {IValidatorFn}
|
|
421
|
-
*/
|
|
422
|
-
static exclusiveMaximum(exclusiveMaximumValue) {
|
|
423
|
-
if (!hasValue(exclusiveMaximumValue)) {
|
|
424
|
-
return JsonValidators.nullValidator;
|
|
425
|
-
}
|
|
426
|
-
return (control, invert = false) => {
|
|
427
|
-
if (isEmpty(control.value)) {
|
|
428
|
-
return null;
|
|
429
|
-
}
|
|
430
|
-
const currentValue = control.value;
|
|
431
|
-
const isValid = !isNumber(currentValue) || +currentValue < exclusiveMaximumValue;
|
|
432
|
-
return xor(isValid, invert) ?
|
|
433
|
-
null : { 'exclusiveMaximum': { exclusiveMaximumValue, currentValue } };
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
/**
|
|
437
|
-
* 'multipleOf' validator
|
|
438
|
-
*
|
|
439
|
-
* Requires a control to have a numeric value that is a multiple
|
|
440
|
-
* of a specified number.
|
|
441
|
-
*
|
|
442
|
-
* // {number} multipleOfValue - number value must be a multiple of
|
|
443
|
-
* // {IValidatorFn}
|
|
444
|
-
*/
|
|
445
|
-
static multipleOf(multipleOfValue) {
|
|
446
|
-
if (!hasValue(multipleOfValue)) {
|
|
447
|
-
return JsonValidators.nullValidator;
|
|
448
|
-
}
|
|
449
|
-
return (control, invert = false) => {
|
|
450
|
-
if (isEmpty(control.value)) {
|
|
451
|
-
return null;
|
|
452
|
-
}
|
|
453
|
-
const currentValue = control.value;
|
|
454
|
-
const isValid = isNumber(currentValue) &&
|
|
455
|
-
currentValue % multipleOfValue === 0;
|
|
456
|
-
return xor(isValid, invert) ?
|
|
457
|
-
null : { 'multipleOf': { multipleOfValue, currentValue } };
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
/**
|
|
461
|
-
* 'minProperties' validator
|
|
462
|
-
*
|
|
463
|
-
* Requires a form group to have a minimum number of properties (i.e. have
|
|
464
|
-
* values entered in a minimum number of controls within the group).
|
|
465
|
-
*
|
|
466
|
-
* // {number} minimumProperties - minimum number of properties allowed
|
|
467
|
-
* // {IValidatorFn}
|
|
468
|
-
*/
|
|
469
|
-
static minProperties(minimumProperties) {
|
|
470
|
-
if (!hasValue(minimumProperties)) {
|
|
471
|
-
return JsonValidators.nullValidator;
|
|
472
|
-
}
|
|
473
|
-
return (control, invert = false) => {
|
|
474
|
-
if (isEmpty(control.value)) {
|
|
475
|
-
return null;
|
|
476
|
-
}
|
|
477
|
-
const currentProperties = Object.keys(control.value).length || 0;
|
|
478
|
-
const isValid = currentProperties >= minimumProperties;
|
|
479
|
-
return xor(isValid, invert) ?
|
|
480
|
-
null : { 'minProperties': { minimumProperties, currentProperties } };
|
|
481
|
-
};
|
|
482
|
-
}
|
|
483
|
-
/**
|
|
484
|
-
* 'maxProperties' validator
|
|
485
|
-
*
|
|
486
|
-
* Requires a form group to have a maximum number of properties (i.e. have
|
|
487
|
-
* values entered in a maximum number of controls within the group).
|
|
488
|
-
*
|
|
489
|
-
* Note: Has no effect if the form group does not contain more than the
|
|
490
|
-
* maximum number of controls.
|
|
491
|
-
*
|
|
492
|
-
* // {number} maximumProperties - maximum number of properties allowed
|
|
493
|
-
* // {IValidatorFn}
|
|
494
|
-
*/
|
|
495
|
-
static maxProperties(maximumProperties) {
|
|
496
|
-
if (!hasValue(maximumProperties)) {
|
|
497
|
-
return JsonValidators.nullValidator;
|
|
498
|
-
}
|
|
499
|
-
return (control, invert = false) => {
|
|
500
|
-
const currentProperties = Object.keys(control.value).length || 0;
|
|
501
|
-
const isValid = currentProperties <= maximumProperties;
|
|
502
|
-
return xor(isValid, invert) ?
|
|
503
|
-
null : { 'maxProperties': { maximumProperties, currentProperties } };
|
|
504
|
-
};
|
|
505
|
-
}
|
|
506
|
-
/**
|
|
507
|
-
* 'dependencies' validator
|
|
508
|
-
*
|
|
509
|
-
* Requires the controls in a form group to meet additional validation
|
|
510
|
-
* criteria, depending on the values of other controls in the group.
|
|
511
|
-
*
|
|
512
|
-
* Examples:
|
|
513
|
-
* https://spacetelescope.github.io/understanding-json-schema/reference/object.html#dependencies
|
|
514
|
-
*
|
|
515
|
-
* // {any} dependencies - required dependencies
|
|
516
|
-
* // {IValidatorFn}
|
|
517
|
-
*/
|
|
518
|
-
static dependencies(dependencies) {
|
|
519
|
-
if (getType(dependencies) !== 'object' || isEmpty(dependencies)) {
|
|
520
|
-
return JsonValidators.nullValidator;
|
|
521
|
-
}
|
|
522
|
-
return (control, invert = false) => {
|
|
523
|
-
if (isEmpty(control.value)) {
|
|
524
|
-
return null;
|
|
525
|
-
}
|
|
526
|
-
const allErrors = _mergeObjects(forEachCopy(dependencies, (value, requiringField) => {
|
|
527
|
-
if (!hasValue(control.value[requiringField])) {
|
|
528
|
-
return null;
|
|
529
|
-
}
|
|
530
|
-
let requiringFieldErrors = {};
|
|
531
|
-
let requiredFields;
|
|
532
|
-
let properties = {};
|
|
533
|
-
if (getType(dependencies[requiringField]) === 'array') {
|
|
534
|
-
requiredFields = dependencies[requiringField];
|
|
535
|
-
}
|
|
536
|
-
else if (getType(dependencies[requiringField]) === 'object') {
|
|
537
|
-
requiredFields = dependencies[requiringField]['required'] || [];
|
|
538
|
-
properties = dependencies[requiringField]['properties'] || {};
|
|
539
|
-
}
|
|
540
|
-
// Validate property dependencies
|
|
541
|
-
for (const requiredField of requiredFields) {
|
|
542
|
-
if (xor(!hasValue(control.value[requiredField]), invert)) {
|
|
543
|
-
requiringFieldErrors[requiredField] = { 'required': true };
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
// Validate schema dependencies
|
|
547
|
-
requiringFieldErrors = _mergeObjects(requiringFieldErrors, forEachCopy(properties, (requirements, requiredField) => {
|
|
548
|
-
const requiredFieldErrors = _mergeObjects(forEachCopy(requirements, (requirement, parameter) => {
|
|
549
|
-
let validator = null;
|
|
550
|
-
if (requirement === 'maximum' || requirement === 'minimum') {
|
|
551
|
-
const exclusive = !!requirements['exclusiveM' + requirement.slice(1)];
|
|
552
|
-
validator = JsonValidators[requirement](parameter, exclusive);
|
|
553
|
-
}
|
|
554
|
-
else if (typeof JsonValidators[requirement] === 'function') {
|
|
555
|
-
validator = JsonValidators[requirement](parameter);
|
|
556
|
-
}
|
|
557
|
-
return !isDefined(validator) ?
|
|
558
|
-
null : validator(control.value[requiredField]);
|
|
559
|
-
}));
|
|
560
|
-
return isEmpty(requiredFieldErrors) ?
|
|
561
|
-
null : { [requiredField]: requiredFieldErrors };
|
|
562
|
-
}));
|
|
563
|
-
return isEmpty(requiringFieldErrors) ?
|
|
564
|
-
null : { [requiringField]: requiringFieldErrors };
|
|
565
|
-
}));
|
|
566
|
-
return isEmpty(allErrors) ? null : allErrors;
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
/**
|
|
570
|
-
* 'minItems' validator
|
|
571
|
-
*
|
|
572
|
-
* Requires a form array to have a minimum number of values.
|
|
573
|
-
*
|
|
574
|
-
* // {number} minimumItems - minimum number of items allowed
|
|
575
|
-
* // {IValidatorFn}
|
|
576
|
-
*/
|
|
577
|
-
static minItems(minimumItems) {
|
|
578
|
-
if (!hasValue(minimumItems)) {
|
|
579
|
-
return JsonValidators.nullValidator;
|
|
580
|
-
}
|
|
581
|
-
return (control, invert = false) => {
|
|
582
|
-
if (isEmpty(control.value)) {
|
|
583
|
-
return null;
|
|
584
|
-
}
|
|
585
|
-
const currentItems = isArray(control.value) ? control.value.length : 0;
|
|
586
|
-
const isValid = currentItems >= minimumItems;
|
|
587
|
-
return xor(isValid, invert) ?
|
|
588
|
-
null : { 'minItems': { minimumItems, currentItems } };
|
|
589
|
-
};
|
|
590
|
-
}
|
|
591
|
-
/**
|
|
592
|
-
* 'maxItems' validator
|
|
593
|
-
*
|
|
594
|
-
* Requires a form array to have a maximum number of values.
|
|
595
|
-
*
|
|
596
|
-
* // {number} maximumItems - maximum number of items allowed
|
|
597
|
-
* // {IValidatorFn}
|
|
598
|
-
*/
|
|
599
|
-
static maxItems(maximumItems) {
|
|
600
|
-
if (!hasValue(maximumItems)) {
|
|
601
|
-
return JsonValidators.nullValidator;
|
|
602
|
-
}
|
|
603
|
-
return (control, invert = false) => {
|
|
604
|
-
const currentItems = isArray(control.value) ? control.value.length : 0;
|
|
605
|
-
const isValid = currentItems <= maximumItems;
|
|
606
|
-
return xor(isValid, invert) ?
|
|
607
|
-
null : { 'maxItems': { maximumItems, currentItems } };
|
|
608
|
-
};
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* 'uniqueItems' validator
|
|
612
|
-
*
|
|
613
|
-
* Requires values in a form array to be unique.
|
|
614
|
-
*
|
|
615
|
-
* // {boolean = true} unique? - true to validate, false to disable
|
|
616
|
-
* // {IValidatorFn}
|
|
617
|
-
*/
|
|
618
|
-
static uniqueItems(unique = true) {
|
|
619
|
-
if (!unique) {
|
|
620
|
-
return JsonValidators.nullValidator;
|
|
621
|
-
}
|
|
622
|
-
return (control, invert = false) => {
|
|
623
|
-
if (isEmpty(control.value)) {
|
|
624
|
-
return null;
|
|
625
|
-
}
|
|
626
|
-
const sorted = control.value.slice().sort();
|
|
627
|
-
const duplicateItems = [];
|
|
628
|
-
for (let i = 1; i < sorted.length; i++) {
|
|
629
|
-
if (sorted[i - 1] === sorted[i] && duplicateItems.includes(sorted[i])) {
|
|
630
|
-
duplicateItems.push(sorted[i]);
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
const isValid = !duplicateItems.length;
|
|
634
|
-
return xor(isValid, invert) ?
|
|
635
|
-
null : { 'uniqueItems': { duplicateItems } };
|
|
636
|
-
};
|
|
637
|
-
}
|
|
638
|
-
/**
|
|
639
|
-
* 'contains' validator
|
|
640
|
-
*
|
|
641
|
-
* TODO: Complete this validator
|
|
642
|
-
*
|
|
643
|
-
* Requires values in a form array to be unique.
|
|
644
|
-
*
|
|
645
|
-
* // {boolean = true} unique? - true to validate, false to disable
|
|
646
|
-
* // {IValidatorFn}
|
|
647
|
-
*/
|
|
648
|
-
static contains(requiredItem = true) {
|
|
649
|
-
if (!requiredItem) {
|
|
650
|
-
return JsonValidators.nullValidator;
|
|
651
|
-
}
|
|
652
|
-
return (control, invert = false) => {
|
|
653
|
-
if (isEmpty(control.value) || !isArray(control.value)) {
|
|
654
|
-
return null;
|
|
655
|
-
}
|
|
656
|
-
const currentItems = control.value;
|
|
657
|
-
// const isValid = currentItems.some(item =>
|
|
658
|
-
//
|
|
659
|
-
// );
|
|
660
|
-
const isValid = true;
|
|
661
|
-
return xor(isValid, invert) ?
|
|
662
|
-
null : { 'contains': { requiredItem, currentItems } };
|
|
663
|
-
};
|
|
664
|
-
}
|
|
665
|
-
/**
|
|
666
|
-
* No-op validator. Included for backward compatibility.
|
|
667
|
-
*/
|
|
668
|
-
static nullValidator(control) {
|
|
669
|
-
return null;
|
|
670
|
-
}
|
|
671
|
-
/**
|
|
672
|
-
* Validator transformation functions:
|
|
673
|
-
* composeAnyOf, composeOneOf, composeAllOf, composeNot,
|
|
674
|
-
* compose, composeAsync
|
|
675
|
-
*
|
|
676
|
-
* TODO: Add composeAnyOfAsync, composeOneOfAsync,
|
|
677
|
-
* composeAllOfAsync, composeNotAsync
|
|
678
|
-
*/
|
|
679
|
-
/**
|
|
680
|
-
* 'composeAnyOf' validator combination function
|
|
681
|
-
*
|
|
682
|
-
* Accepts an array of validators and returns a single validator that
|
|
683
|
-
* evaluates to valid if any one or more of the submitted validators are
|
|
684
|
-
* valid. If every validator is invalid, it returns combined errors from
|
|
685
|
-
* all validators.
|
|
686
|
-
*
|
|
687
|
-
* // {IValidatorFn[]} validators - array of validators to combine
|
|
688
|
-
* // {IValidatorFn} - single combined validator function
|
|
689
|
-
*/
|
|
690
|
-
static composeAnyOf(validators) {
|
|
691
|
-
if (!validators) {
|
|
692
|
-
return null;
|
|
693
|
-
}
|
|
694
|
-
const presentValidators = validators.filter(isDefined);
|
|
695
|
-
if (presentValidators.length === 0) {
|
|
696
|
-
return null;
|
|
697
|
-
}
|
|
698
|
-
return (control, invert = false) => {
|
|
699
|
-
const arrayOfErrors = _executeValidators(control, presentValidators, invert).filter(isDefined);
|
|
700
|
-
const isValid = validators.length > arrayOfErrors.length;
|
|
701
|
-
return xor(isValid, invert) ?
|
|
702
|
-
null : _mergeObjects(...arrayOfErrors, { 'anyOf': !invert });
|
|
703
|
-
};
|
|
704
|
-
}
|
|
705
|
-
/**
|
|
706
|
-
* 'composeOneOf' validator combination function
|
|
707
|
-
*
|
|
708
|
-
* Accepts an array of validators and returns a single validator that
|
|
709
|
-
* evaluates to valid only if exactly one of the submitted validators
|
|
710
|
-
* is valid. Otherwise returns combined information from all validators,
|
|
711
|
-
* both valid and invalid.
|
|
712
|
-
*
|
|
713
|
-
* // {IValidatorFn[]} validators - array of validators to combine
|
|
714
|
-
* // {IValidatorFn} - single combined validator function
|
|
715
|
-
*/
|
|
716
|
-
static composeOneOf(validators) {
|
|
717
|
-
if (!validators) {
|
|
718
|
-
return null;
|
|
719
|
-
}
|
|
720
|
-
const presentValidators = validators.filter(isDefined);
|
|
721
|
-
if (presentValidators.length === 0) {
|
|
722
|
-
return null;
|
|
723
|
-
}
|
|
724
|
-
return (control, invert = false) => {
|
|
725
|
-
const arrayOfErrors = _executeValidators(control, presentValidators);
|
|
726
|
-
const validControls = validators.length - arrayOfErrors.filter(isDefined).length;
|
|
727
|
-
const isValid = validControls === 1;
|
|
728
|
-
if (xor(isValid, invert)) {
|
|
729
|
-
return null;
|
|
730
|
-
}
|
|
731
|
-
const arrayOfValids = _executeValidators(control, presentValidators, invert);
|
|
732
|
-
return _mergeObjects(...arrayOfErrors, ...arrayOfValids, { 'oneOf': !invert });
|
|
733
|
-
};
|
|
734
|
-
}
|
|
735
|
-
/**
|
|
736
|
-
* 'composeAllOf' validator combination function
|
|
737
|
-
*
|
|
738
|
-
* Accepts an array of validators and returns a single validator that
|
|
739
|
-
* evaluates to valid only if all the submitted validators are individually
|
|
740
|
-
* valid. Otherwise it returns combined errors from all invalid validators.
|
|
741
|
-
*
|
|
742
|
-
* // {IValidatorFn[]} validators - array of validators to combine
|
|
743
|
-
* // {IValidatorFn} - single combined validator function
|
|
744
|
-
*/
|
|
745
|
-
static composeAllOf(validators) {
|
|
746
|
-
if (!validators) {
|
|
747
|
-
return null;
|
|
748
|
-
}
|
|
749
|
-
const presentValidators = validators.filter(isDefined);
|
|
750
|
-
if (presentValidators.length === 0) {
|
|
751
|
-
return null;
|
|
752
|
-
}
|
|
753
|
-
return (control, invert = false) => {
|
|
754
|
-
const combinedErrors = _mergeErrors(_executeValidators(control, presentValidators, invert));
|
|
755
|
-
const isValid = combinedErrors === null;
|
|
756
|
-
return (xor(isValid, invert)) ?
|
|
757
|
-
null : _mergeObjects(combinedErrors, { 'allOf': !invert });
|
|
758
|
-
};
|
|
759
|
-
}
|
|
760
|
-
/**
|
|
761
|
-
* 'composeNot' validator inversion function
|
|
762
|
-
*
|
|
763
|
-
* Accepts a single validator function and inverts its result.
|
|
764
|
-
* Returns valid if the submitted validator is invalid, and
|
|
765
|
-
* returns invalid if the submitted validator is valid.
|
|
766
|
-
* (Note: this function can itself be inverted
|
|
767
|
-
* - e.g. composeNot(composeNot(validator)) -
|
|
768
|
-
* but this can be confusing and is therefore not recommended.)
|
|
769
|
-
*
|
|
770
|
-
* // {IValidatorFn[]} validators - validator(s) to invert
|
|
771
|
-
* // {IValidatorFn} - new validator function that returns opposite result
|
|
772
|
-
*/
|
|
773
|
-
static composeNot(validator) {
|
|
774
|
-
if (!validator) {
|
|
775
|
-
return null;
|
|
776
|
-
}
|
|
777
|
-
return (control, invert = false) => {
|
|
778
|
-
if (isEmpty(control.value)) {
|
|
779
|
-
return null;
|
|
780
|
-
}
|
|
781
|
-
const error = validator(control, !invert);
|
|
782
|
-
const isValid = error === null;
|
|
783
|
-
return (xor(isValid, invert)) ?
|
|
784
|
-
null : _mergeObjects(error, { 'not': !invert });
|
|
785
|
-
};
|
|
786
|
-
}
|
|
787
|
-
/**
|
|
788
|
-
* 'compose' validator combination function
|
|
789
|
-
*
|
|
790
|
-
* // {IValidatorFn[]} validators - array of validators to combine
|
|
791
|
-
* // {IValidatorFn} - single combined validator function
|
|
792
|
-
*/
|
|
793
|
-
static compose(validators) {
|
|
794
|
-
if (!validators) {
|
|
795
|
-
return null;
|
|
796
|
-
}
|
|
797
|
-
const presentValidators = validators.filter(isDefined);
|
|
798
|
-
if (presentValidators.length === 0) {
|
|
799
|
-
return null;
|
|
800
|
-
}
|
|
801
|
-
return (control, invert = false) => _mergeErrors(_executeValidators(control, presentValidators, invert));
|
|
802
|
-
}
|
|
803
|
-
/**
|
|
804
|
-
* 'composeAsync' async validator combination function
|
|
805
|
-
*
|
|
806
|
-
* // {AsyncIValidatorFn[]} async validators - array of async validators
|
|
807
|
-
* // {AsyncIValidatorFn} - single combined async validator function
|
|
808
|
-
*/
|
|
809
|
-
static composeAsync(validators) {
|
|
810
|
-
if (!validators) {
|
|
811
|
-
return null;
|
|
812
|
-
}
|
|
813
|
-
const presentValidators = validators.filter(isDefined);
|
|
814
|
-
if (presentValidators.length === 0) {
|
|
815
|
-
return null;
|
|
816
|
-
}
|
|
817
|
-
return (control) => {
|
|
818
|
-
const observables = _executeAsyncValidators(control, presentValidators).map(toObservable);
|
|
819
|
-
return map.call(forkJoin(observables), _mergeErrors);
|
|
820
|
-
};
|
|
821
|
-
}
|
|
822
|
-
// Additional angular validators (not used by Angualr JSON Schema Form)
|
|
823
|
-
// From https://github.com/angular/angular/blob/master/packages/forms/src/validators.ts
|
|
824
|
-
/**
|
|
825
|
-
* Validator that requires controls to have a value greater than a number.
|
|
826
|
-
*/
|
|
827
|
-
static min(min) {
|
|
828
|
-
if (!hasValue(min)) {
|
|
829
|
-
return JsonValidators.nullValidator;
|
|
830
|
-
}
|
|
831
|
-
return (control) => {
|
|
832
|
-
// don't validate empty values to allow optional controls
|
|
833
|
-
if (isEmpty(control.value) || isEmpty(min)) {
|
|
834
|
-
return null;
|
|
835
|
-
}
|
|
836
|
-
const value = parseFloat(control.value);
|
|
837
|
-
const actual = control.value;
|
|
838
|
-
// Controls with NaN values after parsing should be treated as not having a
|
|
839
|
-
// minimum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-min
|
|
840
|
-
return isNaN(value) || value >= min ? null : { 'min': { min, actual } };
|
|
841
|
-
};
|
|
842
|
-
}
|
|
843
|
-
/**
|
|
844
|
-
* Validator that requires controls to have a value less than a number.
|
|
845
|
-
*/
|
|
846
|
-
static max(max) {
|
|
847
|
-
if (!hasValue(max)) {
|
|
848
|
-
return JsonValidators.nullValidator;
|
|
849
|
-
}
|
|
850
|
-
return (control) => {
|
|
851
|
-
// don't validate empty values to allow optional controls
|
|
852
|
-
if (isEmpty(control.value) || isEmpty(max)) {
|
|
853
|
-
return null;
|
|
854
|
-
}
|
|
855
|
-
const value = parseFloat(control.value);
|
|
856
|
-
const actual = control.value;
|
|
857
|
-
// Controls with NaN values after parsing should be treated as not having a
|
|
858
|
-
// maximum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-max
|
|
859
|
-
return isNaN(value) || value <= max ? null : { 'max': { max, actual } };
|
|
860
|
-
};
|
|
861
|
-
}
|
|
862
|
-
/**
|
|
863
|
-
* Validator that requires control value to be true.
|
|
864
|
-
*/
|
|
865
|
-
static requiredTrue(control) {
|
|
866
|
-
if (!control) {
|
|
867
|
-
return JsonValidators.nullValidator;
|
|
868
|
-
}
|
|
869
|
-
return control.value === true ? null : { 'required': true };
|
|
870
|
-
}
|
|
871
|
-
/**
|
|
872
|
-
* Validator that performs email validation.
|
|
873
|
-
*/
|
|
874
|
-
static email(control) {
|
|
875
|
-
if (!control) {
|
|
876
|
-
return JsonValidators.nullValidator;
|
|
877
|
-
}
|
|
878
|
-
const EMAIL_REGEXP =
|
|
879
|
-
// tslint:disable-next-line:max-line-length
|
|
880
|
-
/^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/;
|
|
881
|
-
return EMAIL_REGEXP.test(control.value) ? null : { 'email': true };
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianNvbi52YWxpZGF0b3JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctZm9ybXdvcmtzLWNvcmUvc3JjL2xpYi9zaGFyZWQvanNvbi52YWxpZGF0b3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sT0FBTyxNQUFNLGdCQUFnQixDQUFDO0FBQ3JDLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsa0JBQWtCLEVBQ2xCLFlBQVksRUFDWixhQUFhLEVBRWIsT0FBTyxFQUNQLFFBQVEsRUFDUixPQUFPLEVBQ1AsU0FBUyxFQUNULFNBQVMsRUFDVCxPQUFPLEVBQ1AsUUFBUSxFQUNSLFFBQVEsRUFDUixNQUFNLEVBR04sZ0JBQWdCLEVBQ2hCLFlBQVksRUFDWixHQUFHLEVBQ0YsTUFBTSx1QkFBdUIsQ0FBQztBQUVqQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDbEQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNoQyxPQUFPLEVBQXlCLHFCQUFxQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDeEYsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBSXJDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E4RUc7QUFDSCxNQUFNLE9BQU8sY0FBYztJQXNDekIsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUErQjtRQUM3QyxJQUFJLEtBQUssS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7UUFBQyxDQUFDO1FBQzFDLFFBQVEsS0FBSyxFQUFFLENBQUM7WUFDZCxLQUFLLElBQUksRUFBRSxtREFBbUQ7Z0JBQzVELE9BQU8sQ0FBQyxPQUF3QixFQUFFLE1BQU0sR0FBRyxLQUFLLEVBQXlCLEVBQUU7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TSxNQUFNLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQztZQUM3QiwyRUFBMkU7WUFDM0UsMEZBQTBGO1lBQzFGLE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQztRQUMxRSxDQUFDLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNLENBQUMsWUFBWSxDQUFDLE9BQXdCO1FBQzFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUFDLE9BQU8sY0FBYyxDQUFDLGFBQWEsQ0FBQztRQUFDLENBQUM7UUFDdEQsT0FBTyxPQUFPLENBQUMsS0FBSyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUM5RCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQXdCO1FBQ25DLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUFDLE9BQU8sY0FBYyxDQUFDLGFBQWEsQ0FBQztRQUFDLENBQUM7UUFDdEQsTUFBTSxZQUFZO1FBQ2hCLDJDQUEyQztRQUMzQyw0TEFBNEwsQ0FBQztRQUMvTCxPQUFPLFlBQVksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDO0lBQ3JFLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBpc0VxdWFsIGZyb20gJ2xvZGFzaC9pc0VxdWFsJztcclxuaW1wb3J0IHtcclxuICBfZXhlY3V0ZUFzeW5jVmFsaWRhdG9ycyxcclxuICBfZXhlY3V0ZVZhbGlkYXRvcnMsXHJcbiAgX21lcmdlRXJyb3JzLFxyXG4gIF9tZXJnZU9iamVjdHMsXHJcbiAgQXN5bmNJVmFsaWRhdG9yRm4sXHJcbiAgZ2V0VHlwZSxcclxuICBoYXNWYWx1ZSxcclxuICBpc0FycmF5LFxyXG4gIGlzQm9vbGVhbixcclxuICBpc0RlZmluZWQsXHJcbiAgaXNFbXB0eSxcclxuICBpc051bWJlcixcclxuICBpc1N0cmluZyxcclxuICBpc1R5cGUsXHJcbiAgSVZhbGlkYXRvckZuLFxyXG4gIFNjaGVtYVByaW1pdGl2ZVR5cGUsXHJcbiAgdG9KYXZhU2NyaXB0VHlwZSxcclxuICB0b09ic2VydmFibGUsXHJcbiAgeG9yXHJcbiAgfSBmcm9tICcuL3ZhbGlkYXRvci5mdW5jdGlvbnMnO1xyXG5pbXBvcnQgeyBBYnN0cmFjdENvbnRyb2wsIFZhbGlkYXRpb25FcnJvcnMsIFZhbGlkYXRvckZuIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgeyBmb3JFYWNoQ29weSB9IGZyb20gJy4vdXRpbGl0eS5mdW5jdGlvbnMnO1xyXG5pbXBvcnQgeyBmb3JrSm9pbiB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBKc29uU2NoZW1hRm9ybWF0TmFtZXMsIGpzb25TY2hlbWFGb3JtYXRUZXN0cyB9IGZyb20gJy4vZm9ybWF0LXJlZ2V4LmNvbnN0YW50cyc7XHJcbmltcG9ydCB7IG1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuXHJcblxyXG5cclxuLyoqXHJcbiAqICdKc29uVmFsaWRhdG9ycycgY2xhc3NcclxuICpcclxuICogUHJvdmlkZXMgYW4gZXh0ZW5kZWQgc2V0IG9mIHZhbGlkYXRvcnMgdG8gYmUgdXNlZCBieSBmb3JtIGNvbnRyb2xzLFxyXG4gKiBjb21wYXRpYmxlIHdpdGggc3RhbmRhcmQgSlNPTiBTY2hlbWEgdmFsaWRhdGlvbiBvcHRpb25zLlxyXG4gKiBodHRwOi8vanNvbi1zY2hlbWEub3JnL2xhdGVzdC9qc29uLXNjaGVtYS12YWxpZGF0aW9uLmh0bWxcclxuICpcclxuICogTm90ZTogVGhpcyBsaWJyYXJ5IGlzIGRlc2lnbmVkIGFzIGEgZHJvcC1pbiByZXBsYWNlbWVudCBmb3IgdGhlIEFuZ3VsYXJcclxuICogVmFsaWRhdG9ycyBsaWJyYXJ5LCBhbmQgZXhjZXB0IGZvciBvbmUgc21hbGwgYnJlYWtpbmcgY2hhbmdlIHRvIHRoZSAncGF0dGVybidcclxuICogdmFsaWRhdG9yIChkZXNjcmliZWQgYmVsb3cpIGl0IGNhbiBldmVuIGJlIGltcG9ydGVkIGFzIGEgc3Vic3RpdHV0ZSwgbGlrZSBzbzpcclxuICpcclxuICogICBpbXBvcnQgeyBKc29uVmFsaWRhdG9ycyBhcyBWYWxpZGF0b3JzIH0gZnJvbSAnanNvbi12YWxpZGF0b3JzJztcclxuICpcclxuICogYW5kIGl0IHNob3VsZCB3b3JrIHdpdGggZXhpc3RpbmcgY29kZSBhcyBhIGNvbXBsZXRlIHJlcGxhY2VtZW50LlxyXG4gKlxyXG4gKiBUaGUgb25lIGV4Y2VwdGlvbiBpcyB0aGUgJ3BhdHRlcm4nIHZhbGlkYXRvciwgd2hpY2ggaGFzIGJlZW4gY2hhbmdlZCB0b1xyXG4gKiBtYXRjaGUgcGFydGlhbCB2YWx1ZXMgYnkgZGVmYXVsdCAodGhlIHN0YW5kYXJkICdwYXR0ZXJuJyB2YWxpZGF0b3Igd3JhcHBlZFxyXG4gKiBhbGwgcGF0dGVybnMgaW4gJ14nIGFuZCAnJCcsIGZvcmNpbmcgdGhlbSB0byBhbHdheXMgbWF0Y2ggYW4gZW50aXJlIHZhbHVlKS5cclxuICogSG93ZXZlciwgdGhlIG9sZCBiZWhhdmlvciBjYW4gYmUgcmVzdG9yZWQgYnkgc2ltcGx5IGFkZGluZyAnXicgYW5kICckJ1xyXG4gKiBhcm91bmQgeW91ciBwYXR0ZXJucywgb3IgYnkgcGFzc2luZyBhbiBvcHRpb25hbCBzZWNvbmQgcGFyYW1ldGVyIG9mIFRSVUUuXHJcbiAqIFRoaXMgY2hhbmdlIGlzIHRvIG1ha2UgdGhlICdwYXR0ZXJuJyB2YWxpZGF0b3IgbWF0Y2ggdGhlIGJlaGF2aW9yIG9mIGFcclxuICogSlNPTiBTY2hlbWEgcGF0dGVybiwgd2hpY2ggYWxsb3dzIHBhcnRpYWwgbWF0Y2hlcywgcmF0aGVyIHRoYW4gdGhlIGJlaGF2aW9yXHJcbiAqIG9mIGFuIEhUTUwgaW5wdXQgY29udHJvbCBwYXR0ZXJuLCB3aGljaCBkb2VzIG5vdC5cclxuICpcclxuICogVGhpcyBsaWJyYXJ5IHJlcGxhY2VzIEFuZ3VsYXIncyB2YWxpZGF0b3JzIGFuZCBjb21iaW5hdGlvbiBmdW5jdGlvbnNcclxuICogd2l0aCB0aGUgZm9sbG93aW5nIHZhbGlkYXRvcnMgYW5kIHRyYW5zZm9ybWF0aW9uIGZ1bmN0aW9uczpcclxuICpcclxuICogVmFsaWRhdG9yczpcclxuICogICBGb3IgYWxsIGZvcm1Db250cm9sczogICAgIHJlcXVpcmVkICgqKSwgdHlwZSwgZW51bSwgY29uc3RcclxuICogICBGb3IgdGV4dCBmb3JtQ29udHJvbHM6ICAgIG1pbkxlbmd0aCAoKiksIG1heExlbmd0aCAoKiksIHBhdHRlcm4gKCopLCBmb3JtYXRcclxuICogICBGb3IgbnVtZXJpYyBmb3JtQ29udHJvbHM6IG1heGltdW0sIGV4Y2x1c2l2ZU1heGltdW0sXHJcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5pbXVtLCBleGNsdXNpdmVNaW5pbXVtLCBtdWx0aXBsZU9mXHJcbiAqICAgRm9yIGZvcm1Hcm91cCBvYmplY3RzOiAgICBtaW5Qcm9wZXJ0aWVzLCBtYXhQcm9wZXJ0aWVzLCBkZXBlbmRlbmNpZXNcclxuICogICBGb3IgZm9ybUFycmF5IGFycmF5czogICAgIG1pbkl0ZW1zLCBtYXhJdGVtcywgdW5pcXVlSXRlbXMsIGNvbnRhaW5zXHJcbiAqICAgTm90IHVzZWQgYnkgSlNPTiBTY2hlbWE6ICBtaW4gKCopLCBtYXggKCopLCByZXF1aXJlZFRydWUgKCopLCBlbWFpbCAoKilcclxuICogKFZhbGlkYXRvcnMgb3JpZ2luYWxseSBpbmNsdWRlZCB3aXRoIEFuZ3VsYXIgYXJlIG1ha2VkIHdpdGggKCopLilcclxuICpcclxuICogTk9URSAvIFRPRE86IFRoZSBkZXBlbmRlbmNpZXMgdmFsaWRhdG9yIGlzIG5vdCBjb21wbGV0ZS5cclxuICogTk9URSAvIFRPRE86IFRoZSBjb250YWlucyB2YWxpZGF0b3IgaXMgbm90IGNvbXBsZXRlLlxyXG4gKlxyXG4gKiBWYWxpZGF0b3JzIG5vdCB1c2VkIGJ5IEpTT04gU2NoZW1hIChidXQgaW5jbHVkZWQgZm9yIGNvbXBhdGliaWxpdHkpXHJcbiAqIGFuZCB0aGVpciBKU09OIFNjaGVtYSBlcXVpdmFsZW50czpcclxuICpcclxuICogICBBbmd1bGFyIHZhbGlkYXRvciB8IEpTT04gU2NoZW1hIGVxdWl2YWxlbnRcclxuICogICAtLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICogICAgIG1pbihudW1iZXIpICAgICB8ICAgbWluaW11bShudW1iZXIpXHJcbiAqICAgICBtYXgobnVtYmVyKSAgICAgfCAgIG1heGltdW0obnVtYmVyKVxyXG4gKiAgICAgcmVxdWlyZWRUcnVlKCkgIHwgICBjb25zdCh0cnVlKVxyXG4gKiAgICAgZW1haWwoKSAgICAgICAgIHwgICBmb3JtYXQoJ2VtYWlsJylcclxuICpcclxuICogVmFsaWRhdG9yIHRyYW5zZm9ybWF0aW9uIGZ1bmN0aW9uczpcclxuICogICBjb21wb3NlQW55T2YsIGNvbXBvc2VPbmVPZiwgY29tcG9zZUFsbE9mLCBjb21wb3NlTm90XHJcbiAqIChBbmd1bGFyJ3Mgb3JpZ2luYWwgY29tYmluYXRpb24gZnVuY2l0b24sICdjb21wb3NlJywgaXMgYWxzbyBpbmNsdWRlZCBmb3JcclxuICogYmFja3dhcmQgY29tcGF0aWJpbGl0eSwgdGhvdWdoIGl0IGlzIGZ1bmN0aW9uYWxseSBlcXVpdmFsZW50IHRvIGNvbXBvc2VBbGxPZixcclxuICogYXNzaWRlIGZyb20gaXRzIG1vcmUgZ2VuZXJpYyBlcnJvciBtZXNzYWdlLilcclxuICpcclxuICogQWxsIHZhbGlkYXRvcnMgaGF2ZSBhbHNvIGJlZW4gZXh0ZW5kZWQgdG8gYWNjZXB0IGFuIG9wdGlvbmFsIHNlY29uZCBhcmd1bWVudFxyXG4gKiB3aGljaCwgaWYgcGFzc2VkIGEgVFJVRSB2YWx1ZSwgY2F1c2VzIHRoZSB2YWxpZGF0b3IgdG8gcGVyZm9ybSB0aGUgb3Bwb3NpdGVcclxuICogb2YgaXRzIG9yaWdpbmFsIGZpbmN0aW9uLiAoVGhpcyBpcyB1c2VkIGludGVybmFsbHkgdG8gZW5hYmxlICdub3QnIGFuZFxyXG4gKiAnY29tcG9zZU9uZU9mJyB0byBmdW5jdGlvbiBhbmQgcmV0dXJuIHVzZWZ1bCBlcnJvciBtZXNzYWdlcy4pXHJcbiAqXHJcbiAqIFRoZSAncmVxdWlyZWQnIHZhbGlkYXRvciBoYXMgYWxzbyBiZWVuIG92ZXJsb2FkZWQgc28gdGhhdCBpZiBjYWxsZWQgd2l0aFxyXG4gKiBhIGJvb2xlYW4gcGFyYW1ldGVyIChvciBubyBwYXJhbWV0ZXJzKSBpdCByZXR1cm5zIHRoZSBvcmlnaW5hbCB2YWxpZGF0b3JcclxuICogZnVuY3Rpb24gKHJhdGhlciB0aGFuIGV4ZWN1dGluZyBpdCkuIEhvd2V2ZXIsIGlmIGl0IGlzIGNhbGxlZCB3aXRoIGFuXHJcbiAqIEFic3RyYWN0Q29udHJvbCBwYXJhbWV0ZXIgKGFzIHdhcyBwcmV2aW91c2x5IHJlcXVpcmVkKSwgaXQgYmVoYXZlc1xyXG4gKiBleGFjdGx5IGFzIGJlZm9yZS5cclxuICpcclxuICogVGhpcyBlbmFibGVzIGFsbCB2YWxpZGF0b3JzIChpbmNsdWRpbmcgJ3JlcXVpcmVkJykgdG8gYmUgY29uc3RydWN0ZWQgaW5cclxuICogZXhhY3RseSB0aGUgc2FtZSB3YXksIHNvIHRoZXkgY2FuIGJlIGF1dG9tYXRpY2FsbHkgYXBwbGllZCB1c2luZyB0aGVcclxuICogZXF1aXZhbGVudCBrZXkgbmFtZXMgYW5kIHZhbHVlcyB0YWtlbiBkaXJlY3RseSBmcm9tIGEgSlNPTiBTY2hlbWEuXHJcbiAqXHJcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgcGFydGlhbGx5IGRlcml2ZWQgZnJvbSBBbmd1bGFyLFxyXG4gKiB3aGljaCBpcyBDb3B5cmlnaHQgKGMpIDIwMTQtMjAxNyBHb29nbGUsIEluYy5cclxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgdGhlcmVmb3JlIGdvdmVybmVkIGJ5IHRoZSBzYW1lIE1JVC1zdHlsZSBsaWNlbnNlXHJcbiAqIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcclxuICpcclxuICogT3JpZ2luYWwgQW5ndWxhciBWYWxpZGF0b3JzOlxyXG4gKiBodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9hbmd1bGFyL2Jsb2IvbWFzdGVyL3BhY2thZ2VzL2Zvcm1zL3NyYy92YWxpZGF0b3JzLnRzXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgSnNvblZhbGlkYXRvcnMge1xyXG5cclxuICAvKipcclxuICAgKiBWYWxpZGF0b3IgZnVuY3Rpb25zOlxyXG4gICAqXHJcbiAgICogRm9yIGFsbCBmb3JtQ29udHJvbHM6ICAgICByZXF1aXJlZCwgdHlwZSwgZW51bSwgY29uc3RcclxuICAgKiBGb3IgdGV4dCBmb3JtQ29udHJvbHM6ICAgIG1pbkxlbmd0aCwgbWF4TGVuZ3RoLCBwYXR0ZXJuLCBmb3JtYXRcclxuICAgKiBGb3IgbnVtZXJpYyBmb3JtQ29udHJvbHM6IG1heGltdW0sIGV4Y2x1c2l2ZU1heGltdW0sXHJcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5pbXVtLCBleGNsdXNpdmVNaW5pbXVtLCBtdWx0aXBsZU9mXHJcbiAgICogRm9yIGZvcm1Hcm91cCBvYmplY3RzOiAgICBtaW5Qcm9wZXJ0aWVzLCBtYXhQcm9wZXJ0aWVzLCBkZXBlbmRlbmNpZXNcclxuICAgKiBGb3IgZm9ybUFycmF5IGFycmF5czogICAgIG1pbkl0ZW1zLCBtYXhJdGVtcywgdW5pcXVlSXRlbXMsIGNvbnRhaW5zXHJcbiAgICpcclxuICAgKiBUT0RPOiBmaW5pc2ggZGVwZW5kZW5jaWVzIHZhbGlkYXRvclxyXG4gICAqL1xyXG5cclxuICAvKipcclxuICAgKiAncmVxdWlyZWQnIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogVGhpcyB2YWxpZGF0b3IgaXMgb3ZlcmxvYWRlZCwgY29tcGFyZWQgdG8gdGhlIGRlZmF1bHQgcmVxdWlyZWQgdmFsaWRhdG9yLlxyXG4gICAqIElmIGNhbGxlZCB3aXRoIG5vIHBhcmFtZXRlcnMsIG9yIFRSVUUsIHRoaXMgdmFsaWRhdG9yIHJldHVybnMgdGhlXHJcbiAgICogJ3JlcXVpcmVkJyB2YWxpZGF0b3IgZnVuY3Rpb24gKHJhdGhlciB0aGFuIGV4ZWN1dGluZyBpdCkuIFRoaXMgbWF0Y2hlc1xyXG4gICAqIHRoZSBiZWhhdmlvciBvZiBhbGwgb3RoZXIgdmFsaWRhdG9ycyBpbiB0aGlzIGxpYnJhcnkuXHJcbiAgICpcclxuICAgKiBJZiB0aGlzIHZhbGlkYXRvciBpcyBjYWxsZWQgd2l0aCBhbiBBYnN0cmFjdENvbnRyb2wgcGFyYW1ldGVyXHJcbiAgICogKGFzIHdhcyBwcmV2aW91c2x5IHJlcXVpcmVkKSBpdCBiZWhhdmVzIHRoZSBzYW1lIGFzIEFuZ3VsYXIncyBkZWZhdWx0XHJcbiAgICogcmVxdWlyZWQgdmFsaWRhdG9yLCBhbmQgcmV0dXJucyBhbiBlcnJvciBpZiB0aGUgY29udHJvbCBpcyBlbXB0eS5cclxuICAgKlxyXG4gICAqIE9sZCBiZWhhdmlvcjogKGlmIGlucHV0IHR5cGUgPSBBYnN0cmFjdENvbnRyb2wpXHJcbiAgICogLy8ge0Fic3RyYWN0Q29udHJvbH0gY29udHJvbCAtIHJlcXVpcmVkIGNvbnRyb2xcclxuICAgKiAvLyB7e1trZXk6IHN0cmluZ106IGJvb2xlYW59fSAtIHJldHVybnMgZXJyb3IgbWVzc2FnZSBpZiBubyBpbnB1dFxyXG4gICAqXHJcbiAgICogTmV3IGJlaGF2aW9yOiAoaWYgbm8gaW5wdXQsIG9yIGlucHV0IHR5cGUgPSBib29sZWFuKVxyXG4gICAqIC8vIHtib29sZWFuID0gdHJ1ZX0gcmVxdWlyZWQ/IC0gdHJ1ZSB0byB2YWxpZGF0ZSwgZmFsc2UgdG8gZGlzYWJsZVxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59IC0gcmV0dXJucyB0aGUgJ3JlcXVpcmVkJyB2YWxpZGF0b3IgZnVuY3Rpb24gaXRzZWxmXHJcbiAgICovXHJcbiAgc3RhdGljIHJlcXVpcmVkKGlucHV0OiBBYnN0cmFjdENvbnRyb2wpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGw7XHJcbiAgc3RhdGljIHJlcXVpcmVkKGlucHV0PzogYm9vbGVhbik6IElWYWxpZGF0b3JGbjtcclxuXHJcbiAgc3RhdGljIHJlcXVpcmVkKGlucHV0PzogQWJzdHJhY3RDb250cm9sfGJvb2xlYW4pOiBWYWxpZGF0aW9uRXJyb3JzfG51bGx8SVZhbGlkYXRvckZuIHtcclxuICAgIGlmIChpbnB1dCA9PT0gdW5kZWZpbmVkKSB7IGlucHV0ID0gdHJ1ZTsgfVxyXG4gICAgc3dpdGNoIChpbnB1dCkge1xyXG4gICAgICBjYXNlIHRydWU6IC8vIFJldHVybiByZXF1aXJlZCBmdW5jdGlvbiAoZG8gbm90IGV4ZWN1dGUgaXQgeWV0KVxyXG4gICAgICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbnZlcnQgPSBmYWxzZSk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PiB7XHJcbiAgICAgICAgICBpZiAoaW52ZXJ0KSB7IHJldHVybiBudWxsOyB9IC8vIGlmIG5vdCByZXF1aXJlZCwgYWx3YXlzIHJldHVybiB2YWxpZFxyXG4gICAgICAgICAgcmV0dXJuIGhhc1ZhbHVlKGNvbnRyb2wudmFsdWUpID8gbnVsbCA6IHsgJ3JlcXVpcmVkJzogdHJ1ZSB9O1xyXG4gICAgICAgIH07XHJcbiAgICAgIGNhc2UgZmFsc2U6IC8vIERvIG5vdGhpbmcgKGlmIGZpZWxkIGlzIG5vdCByZXF1aXJlZCwgaXQgaXMgYWx3YXlzIHZhbGlkKVxyXG4gICAgICAgIHJldHVybiBKc29uVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yO1xyXG4gICAgICBkZWZhdWx0OiAvLyBFeGVjdXRlIHJlcXVpcmVkIGZ1bmN0aW9uXHJcbiAgICAgICAgcmV0dXJuIGhhc1ZhbHVlKCg8QWJzdHJhY3RDb250cm9sPmlucHV0KS52YWx1ZSkgPyBudWxsIDogeyAncmVxdWlyZWQnOiB0cnVlIH07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAndHlwZScgdmFsaWRhdG9yXHJcbiAgICpcclxuICAgKiBSZXF1aXJlcyBhIGNvbnRyb2wgdG8gb25seSBhY2NlcHQgdmFsdWVzIG9mIGEgc3BlY2lmaWVkIHR5cGUsXHJcbiAgICogb3Igb25lIG9mIGFuIGFycmF5IG9mIHR5cGVzLlxyXG4gICAqXHJcbiAgICogTm90ZTogU2NoZW1hUHJpbWl0aXZlVHlwZSA9ICdzdHJpbmcnfCdudW1iZXInfCdpbnRlZ2VyJ3wnYm9vbGVhbid8J251bGwnXHJcbiAgICpcclxuICAgKiAvLyB7U2NoZW1hUHJpbWl0aXZlVHlwZXxTY2hlbWFQcmltaXRpdmVUeXBlW119IHR5cGUgLSB0eXBlKHMpIHRvIGFjY2VwdFxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59XHJcbiAgICovXHJcbiAgc3RhdGljIHR5cGUocmVxdWlyZWRUeXBlOiBTY2hlbWFQcmltaXRpdmVUeXBlfFNjaGVtYVByaW1pdGl2ZVR5cGVbXSk6IElWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoIWhhc1ZhbHVlKHJlcXVpcmVkVHlwZSkpIHsgcmV0dXJuIEpzb25WYWxpZGF0b3JzLm51bGxWYWxpZGF0b3I7IH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbnZlcnQgPSBmYWxzZSk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PiB7XHJcbiAgICAgIGlmIChpc0VtcHR5KGNvbnRyb2wudmFsdWUpKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICAgIGNvbnN0IGN1cnJlbnRWYWx1ZTogYW55ID0gY29udHJvbC52YWx1ZTtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9IGlzQXJyYXkocmVxdWlyZWRUeXBlKSA/XHJcbiAgICAgICAgKDxTY2hlbWFQcmltaXRpdmVUeXBlW10+cmVxdWlyZWRUeXBlKS5zb21lKHR5cGUgPT4gaXNUeXBlKGN1cnJlbnRWYWx1ZSwgdHlwZSkpIDpcclxuICAgICAgICBpc1R5cGUoY3VycmVudFZhbHVlLCA8U2NoZW1hUHJpbWl0aXZlVHlwZT5yZXF1aXJlZFR5cGUpO1xyXG4gICAgICByZXR1cm4geG9yKGlzVmFsaWQsIGludmVydCkgP1xyXG4gICAgICAgIG51bGwgOiB7ICd0eXBlJzogeyByZXF1aXJlZFR5cGUsIGN1cnJlbnRWYWx1ZSB9IH07XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2VudW0nIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogUmVxdWlyZXMgYSBjb250cm9sIHRvIGhhdmUgYSB2YWx1ZSBmcm9tIGFuIGVudW1lcmF0ZWQgbGlzdCBvZiB2YWx1ZXMuXHJcbiAgICpcclxuICAgKiBDb252ZXJ0cyB0eXBlcyBhcyBuZWVkZWQgdG8gYWxsb3cgc3RyaW5nIGlucHV0cyB0byBzdGlsbCBjb3JyZWN0bHlcclxuICAgKiBtYXRjaCBudW1iZXIsIGJvb2xlYW4sIGFuZCBudWxsIGVudW0gdmFsdWVzLlxyXG4gICAqXHJcbiAgICogLy8ge2FueVtdfSBhbGxvd2VkVmFsdWVzIC0gYXJyYXkgb2YgYWNjZXB0YWJsZSB2YWx1ZXNcclxuICAgKiAvLyB7SVZhbGlkYXRvckZufVxyXG4gICAqL1xyXG4gIHN0YXRpYyBlbnVtKGFsbG93ZWRWYWx1ZXM6IGFueVtdKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaXNBcnJheShhbGxvd2VkVmFsdWVzKSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgaWYgKGlzRW1wdHkoY29udHJvbC52YWx1ZSkpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgY29uc3QgY3VycmVudFZhbHVlOiBhbnkgPSBjb250cm9sLnZhbHVlO1xyXG4gICAgICBjb25zdCBpc0VxdWFsVmFsID0gKGVudW1WYWx1ZSwgaW5wdXRWYWx1ZSkgPT5cclxuICAgICAgICBlbnVtVmFsdWUgPT09IGlucHV0VmFsdWUgfHxcclxuICAgICAgICAoaXNOdW1iZXIoZW51bVZhbHVlKSAmJiAraW5wdXRWYWx1ZSA9PT0gK2VudW1WYWx1ZSkgfHxcclxuICAgICAgICAoaXNCb29sZWFuKGVudW1WYWx1ZSwgJ3N0cmljdCcpICYmXHJcbiAgICAgICAgICB0b0phdmFTY3JpcHRUeXBlKGlucHV0VmFsdWUsICdib29sZWFuJykgPT09IGVudW1WYWx1ZSkgfHxcclxuICAgICAgICAoZW51bVZhbHVlID09PSBudWxsICYmICFoYXNWYWx1ZShpbnB1dFZhbHVlKSkgfHxcclxuICAgICAgICBpc0VxdWFsKGVudW1WYWx1ZSwgaW5wdXRWYWx1ZSk7XHJcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSBpc0FycmF5KGN1cnJlbnRWYWx1ZSkgP1xyXG4gICAgICAgIGN1cnJlbnRWYWx1ZS5ldmVyeShpbnB1dFZhbHVlID0+IGFsbG93ZWRWYWx1ZXMuc29tZShlbnVtVmFsdWUgPT5cclxuICAgICAgICAgIGlzRXF1YWxWYWwoZW51bVZhbHVlLCBpbnB1dFZhbHVlKVxyXG4gICAgICAgICkpIDpcclxuICAgICAgICBhbGxvd2VkVmFsdWVzLnNvbWUoZW51bVZhbHVlID0+IGlzRXF1YWxWYWwoZW51bVZhbHVlLCBjdXJyZW50VmFsdWUpKTtcclxuICAgICAgcmV0dXJuIHhvcihpc1ZhbGlkLCBpbnZlcnQpID9cclxuICAgICAgICBudWxsIDogeyAnZW51bSc6IHsgYWxsb3dlZFZhbHVlcywgY3VycmVudFZhbHVlIH0gfTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnY29uc3QnIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogUmVxdWlyZXMgYSBjb250cm9sIHRvIGhhdmUgYSBzcGVjaWZpYyB2YWx1ZS5cclxuICAgKlxyXG4gICAqIENvbnZlcnRzIHR5cGVzIGFzIG5lZWRlZCB0byBhbGxvdyBzdHJpbmcgaW5wdXRzIHRvIHN0aWxsIGNvcnJlY3RseVxyXG4gICAqIG1hdGNoIG51bWJlciwgYm9vbGVhbiwgYW5kIG51bGwgdmFsdWVzLlxyXG4gICAqXHJcbiAgICogVE9ETzogbW9kaWZ5IHRvIHdvcmsgd2l0aCBvYmplY3RzXHJcbiAgICpcclxuICAgKiAvLyB7YW55W119IHJlcXVpcmVkVmFsdWUgLSByZXF1aXJlZCB2YWx1ZVxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59XHJcbiAgICovXHJcbiAgc3RhdGljIGNvbnN0KHJlcXVpcmVkVmFsdWU6IGFueSk6IElWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoIWhhc1ZhbHVlKHJlcXVpcmVkVmFsdWUpKSB7IHJldHVybiBKc29uVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yOyB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgaW52ZXJ0ID0gZmFsc2UpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT4ge1xyXG4gICAgICBpZiAoaXNFbXB0eShjb250cm9sLnZhbHVlKSkgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgICBjb25zdCBjdXJyZW50VmFsdWU6IGFueSA9IGNvbnRyb2wudmFsdWU7XHJcbiAgICAgIGNvbnN0IGlzRXF1YWxWYWwgPSAoY29uc3RWYWx1ZSwgaW5wdXRWYWx1ZSkgPT5cclxuICAgICAgICBjb25zdFZhbHVlID09PSBpbnB1dFZhbHVlIHx8XHJcbiAgICAgICAgaXNOdW1iZXIoY29uc3RWYWx1ZSkgJiYgK2lucHV0VmFsdWUgPT09ICtjb25zdFZhbHVlIHx8XHJcbiAgICAgICAgaXNCb29sZWFuKGNvbnN0VmFsdWUsICdzdHJpY3QnKSAmJlxyXG4gICAgICAgICAgdG9KYXZhU2NyaXB0VHlwZShpbnB1dFZhbHVlLCAnYm9vbGVhbicpID09PSBjb25zdFZhbHVlIHx8XHJcbiAgICAgICAgY29uc3RWYWx1ZSA9PT0gbnVsbCAmJiAhaGFzVmFsdWUoaW5wdXRWYWx1ZSk7XHJcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSBpc0VxdWFsVmFsKHJlcXVpcmVkVmFsdWUsIGN1cnJlbnRWYWx1ZSk7XHJcbiAgICAgIHJldHVybiB4b3IoaXNWYWxpZCwgaW52ZXJ0KSA/XHJcbiAgICAgICAgbnVsbCA6IHsgJ2NvbnN0JzogeyByZXF1aXJlZFZhbHVlLCBjdXJyZW50VmFsdWUgfSB9O1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdtaW5MZW5ndGgnIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogUmVxdWlyZXMgYSBjb250cm9sJ3MgdGV4dCB2YWx1ZSB0byBiZSBncmVhdGVyIHRoYW4gYSBzcGVjaWZpZWQgbGVuZ3RoLlxyXG4gICAqXHJcbiAgICogLy8ge251bWJlcn0gbWluaW11bUxlbmd0aCAtIG1pbmltdW0gYWxsb3dlZCBzdHJpbmcgbGVuZ3RoXHJcbiAgICogLy8ge2Jvb2xlYW4gPSBmYWxzZX0gaW52ZXJ0IC0gaW5zdGVhZCByZXR1cm4gZXJyb3Igb2JqZWN0IG9ubHkgaWYgdmFsaWRcclxuICAgKiAvLyB7SVZhbGlkYXRvckZufVxyXG4gICAqL1xyXG4gIHN0YXRpYyBtaW5MZW5ndGgobWluaW11bUxlbmd0aDogbnVtYmVyKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUobWluaW11bUxlbmd0aCkpIHsgcmV0dXJuIEpzb25WYWxpZGF0b3JzLm51bGxWYWxpZGF0b3I7IH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbnZlcnQgPSBmYWxzZSk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PiB7XHJcbiAgICAgIGlmIChpc0VtcHR5KGNvbnRyb2wudmFsdWUpKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICAgIGNvbnN0IGN1cnJlbnRMZW5ndGggPSBpc1N0cmluZyhjb250cm9sLnZhbHVlKSA/IGNvbnRyb2wudmFsdWUubGVuZ3RoIDogMDtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9IGN1cnJlbnRMZW5ndGggPj0gbWluaW11bUxlbmd0aDtcclxuICAgICAgcmV0dXJuIHhvcihpc1ZhbGlkLCBpbnZlcnQpID9cclxuICAgICAgICBudWxsIDogeyAnbWluTGVuZ3RoJzogeyBtaW5pbXVtTGVuZ3RoLCBjdXJyZW50TGVuZ3RoIH0gfTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnbWF4TGVuZ3RoJyB2YWxpZGF0b3JcclxuICAgKlxyXG4gICAqIFJlcXVpcmVzIGEgY29udHJvbCdzIHRleHQgdmFsdWUgdG8gYmUgbGVzcyB0aGFuIGEgc3BlY2lmaWVkIGxlbmd0aC5cclxuICAgKlxyXG4gICAqIC8vIHtudW1iZXJ9IG1heGltdW1MZW5ndGggLSBtYXhpbXVtIGFsbG93ZWQgc3RyaW5nIGxlbmd0aFxyXG4gICAqIC8vIHtib29sZWFuID0gZmFsc2V9IGludmVydCAtIGluc3RlYWQgcmV0dXJuIGVycm9yIG9iamVjdCBvbmx5IGlmIHZhbGlkXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn1cclxuICAgKi9cclxuICBzdGF0aWMgbWF4TGVuZ3RoKG1heGltdW1MZW5ndGg6IG51bWJlcik6IElWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoIWhhc1ZhbHVlKG1heGltdW1MZW5ndGgpKSB7IHJldHVybiBKc29uVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yOyB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgaW52ZXJ0ID0gZmFsc2UpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT4ge1xyXG4gICAgICBjb25zdCBjdXJyZW50TGVuZ3RoID0gaXNTdHJpbmcoY29udHJvbC52YWx1ZSkgPyBjb250cm9sLnZhbHVlLmxlbmd0aCA6IDA7XHJcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSBjdXJyZW50TGVuZ3RoIDw9IG1heGltdW1MZW5ndGg7XHJcbiAgICAgIHJldHVybiB4b3IoaXNWYWxpZCwgaW52ZXJ0KSA/XHJcbiAgICAgICAgbnVsbCA6IHsgJ21heExlbmd0aCc6IHsgbWF4aW11bUxlbmd0aCwgY3VycmVudExlbmd0aCB9IH07XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ3BhdHRlcm4nIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogTm90ZTogTk9UIHRoZSBzYW1lIGFzIEFuZ3VsYXIncyBkZWZhdWx0IHBhdHRlcm4gdmFsaWRhdG9yLlxyXG4gICAqXHJcbiAgICogUmVxdWlyZXMgYSBjb250cm9sJ3MgdmFsdWUgdG8gbWF0Y2ggYSBzcGVjaWZpZWQgcmVndWxhciBleHByZXNzaW9uIHBhdHRlcm4uXHJcbiAgICpcclxuICAgKiBUaGlzIHZhbGlkYXRvciBjaGFuZ2VzIHRoZSBiZWhhdmlvciBvZiBkZWZhdWx0IHBhdHRlcm4gdmFsaWRhdG9yXHJcbiAgICogYnkgcmVwbGFjaW5nIFJlZ0V4cChgXiR7cGF0dGVybn0kYCkgd2l0aCBSZWdFeHAoYCR7cGF0dGVybn1gKSxcclxuICAgKiB3aGljaCBhbGxvd3MgZm9yIHBhcnRpYWwgbWF0Y2hlcy5cclxuICAgKlxyXG4gICAqIFRvIHJldHVybiB0byB0aGUgZGVmYXVsdCBmdW5jaXRvbmFsaXR5LCBhbmQgbWF0Y2ggdGhlIGVudGlyZSBzdHJpbmcsXHJcbiAgICogcGFzcyBUUlVFIGFzIHRoZSBvcHRpb25hbCBzZWNvbmQgcGFyYW1ldGVyLlxyXG4gICAqXHJcbiAgICogLy8ge3N0cmluZ30gcGF0dGVybiAtIHJlZ3VsYXIgZXhwcmVzc2lvbiBwYXR0ZXJuXHJcbiAgICogLy8ge2Jvb2xlYW4gPSBmYWxzZX0gd2hvbGVTdHJpbmcgLSBtYXRjaCB3aG9sZSB2YWx1ZSBzdHJpbmc/XHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn1cclxuICAgKi9cclxuICBzdGF0aWMgcGF0dGVybihwYXR0ZXJuOiBzdHJpbmd8UmVnRXhwLCB3aG9sZVN0cmluZyA9IGZhbHNlKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUocGF0dGVybikpIHsgcmV0dXJuIEpzb25WYWxpZGF0b3JzLm51bGxWYWxpZGF0b3I7IH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbnZlcnQgPSBmYWxzZSk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PiB7XHJcbiAgICAgIGlmIChpc0VtcHR5KGNvbnRyb2wudmFsdWUpKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICAgIGxldCByZWdleDogUmVnRXhwO1xyXG4gICAgICBsZXQgcmVxdWlyZWRQYXR0ZXJuOiBzdHJpbmc7XHJcbiAgICAgIGlmICh0eXBlb2YgcGF0dGVybiA9PT0gJ3N0cmluZycpIHtcclxuICAgICAgICByZXF1aXJlZFBhdHRlcm4gPSAod2hvbGVTdHJpbmcpID8gYF4ke3BhdHRlcm59JGAgOiBwYXR0ZXJuO1xyXG4gICAgICAgIHJlZ2V4ID0gbmV3IFJlZ0V4cChyZXF1aXJlZFBhdHRlcm4pO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJlcXVpcmVkUGF0dGVybiA9IHBhdHRlcm4udG9TdHJpbmcoKTtcclxuICAgICAgICByZWdleCA9IHBhdHRlcm47XHJcbiAgICAgIH1cclxuICAgICAgY29uc3QgY3VycmVudFZhbHVlOiBzdHJpbmcgPSBjb250cm9sLnZhbHVlO1xyXG4gICAgICBjb25zdCBpc1ZhbGlkID0gaXNTdHJpbmcoY3VycmVudFZhbHVlKSA/IHJlZ2V4LnRlc3QoY3VycmVudFZhbHVlKSA6IGZhbHNlO1xyXG4gICAgICByZXR1cm4geG9yKGlzVmFsaWQsIGludmVydCkgP1xyXG4gICAgICAgIG51bGwgOiB7ICdwYXR0ZXJuJzogeyByZXF1aXJlZFBhdHRlcm4sIGN1cnJlbnRWYWx1ZSB9IH07XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2Zvcm1hdCcgdmFsaWRhdG9yXHJcbiAgICpcclxuICAgKiBSZXF1aXJlcyBhIGNvbnRyb2wgdG8gaGF2ZSBhIHZhbHVlIG9mIGEgY2VydGFpbiBmb3JtYXQuXHJcbiAgICpcclxuICAgKiBUaGlzIHZhbGlkYXRvciBjdXJyZW50bHkgY2hlY2tzIHRoZSBmb2xsb3dpbmcgZm9ybXN0czpcclxuICAgKiAgIGRhdGUsIHRpbWUsIGRhdGUtdGltZSwgZW1haWwsIGhvc3RuYW1lLCBpcHY0LCBpcHY2LFxyXG4gICAqICAgdXJpLCB1cmktcmVmZXJlbmNlLCB1cmktdGVtcGxhdGUsIHVybCwgdXVpZCwgY29sb3IsXHJcbiAgICogICBqc29uLXBvaW50ZXIsIHJlbGF0aXZlLWpzb24tcG9pbnRlciwgcmVnZXhcclxuICAgKlxyXG4gICAqIEZhc3QgZm9ybWF0IHJlZ3VsYXIgZXhwcmVzc2lvbnMgY29waWVkIGZyb20gQUpWOlxyXG4gICAqIGh0dHBzOi8vZ2l0aHViLmNvbS9lcG9iZXJlemtpbi9hanYvYmxvYi9tYXN0ZXIvbGliL2NvbXBpbGUvZm9ybWF0cy5qc1xyXG4gICAqXHJcbiAgICogLy8ge0pzb25TY2hlbWFGb3JtYXROYW1lc30gcmVxdWlyZWRGb3JtYXQgLSBmb3JtYXQgdG8gY2hlY2tcclxuICAgKiAvLyB7SVZhbGlkYXRvckZufVxyXG4gICAqL1xyXG4gIHN0YXRpYyBmb3JtYXQocmVxdWlyZWRGb3JtYXQ6IEpzb25TY2hlbWFGb3JtYXROYW1lcyk6IElWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoIWhhc1ZhbHVlKHJlcXVpcmVkRm9ybWF0KSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgaWYgKGlzRW1wdHkoY29udHJvbC52YWx1ZSkpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgbGV0IGlzVmFsaWQ6IGJvb2xlYW47XHJcbiAgICAgIGNvbnN0IGN1cnJlbnRWYWx1ZTogc3RyaW5nfERhdGUgPSBjb250cm9sLnZhbHVlO1xyXG4gICAgICBpZiAoaXNTdHJpbmcoY3VycmVudFZhbHVlKSkge1xyXG4gICAgICAgIGNvbnN0IGZvcm1hdFRlc3Q6IEZ1bmN0aW9ufFJlZ0V4cCA9IGpzb25TY2hlbWFGb3JtYXRUZXN0c1tyZXF1aXJlZEZvcm1hdF07XHJcbiAgICAgICAgaWYgKHR5cGVvZiBmb3JtYXRUZXN0ID09PSAnb2JqZWN0Jykge1xyXG4gICAgICAgICAgaXNWYWxpZCA9ICg8UmVnRXhwPmZvcm1hdFRlc3QpLnRlc3QoPHN0cmluZz5jdXJyZW50VmFsdWUpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGZvcm1hdFRlc3QgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgICAgIGlzVmFsaWQgPSAoPEZ1bmN0aW9uPmZvcm1hdFRlc3QpKDxzdHJpbmc+Y3VycmVudFZhbHVlKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgY29uc29sZS5lcnJvcihgZm9ybWF0IHZhbGlkYXRvciBlcnJvcjogXCIke3JlcXVpcmVkRm9ybWF0fVwiIGlzIG5vdCBhIHJlY29nbml6ZWQgZm9ybWF0LmApO1xyXG4gICAgICAgICAgaXNWYWxpZCA9IHRydWU7XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIEFsbG93IEphdmFTY3JpcHQgRGF0ZSBvYmplY3RzXHJcbiAgICAgICAgaXNWYWxpZCA9IFsnZGF0ZScsICd0aW1lJywgJ2RhdGUtdGltZSddLmluY2x1ZGVzKHJlcXVpcmVkRm9ybWF0KSAmJlxyXG4gICAgICAgICAgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGN1cnJlbnRWYWx1ZSkgPT09ICdbb2JqZWN0IERhdGVdJztcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4geG9yKGlzVmFsaWQsIGludmVydCkgP1xyXG4gICAgICAgIG51bGwgOiB7ICdmb3JtYXQnOiB7IHJlcXVpcmVkRm9ybWF0LCBjdXJyZW50VmFsdWUgfSB9O1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdtaW5pbXVtJyB2YWxpZGF0b3JcclxuICAgKlxyXG4gICAqIFJlcXVpcmVzIGEgY29udHJvbCdzIG51bWVyaWMgdmFsdWUgdG8gYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvXHJcbiAgICogYSBtaW5pbXVtIGFtb3VudC5cclxuICAgKlxyXG4gICAqIEFueSBub24tbnVtZXJpYyB2YWx1ZSBpcyBhbHNvIHZhbGlkIChhY2NvcmRpbmcgdG8gdGhlIEhUTUwgZm9ybXMgc3BlYyxcclxuICAgKiBhIG5vbi1udW1lcmljIHZhbHVlIGRvZXNuJ3QgaGF2ZSBhIG1pbmltdW0pLlxyXG4gICAqIGh0dHBzOi8vd3d3LnczLm9yZy9UUi9odG1sNS9mb3Jtcy5odG1sI2F0dHItaW5wdXQtbWF4XHJcbiAgICpcclxuICAgKiAvLyB7bnVtYmVyfSBtaW5pbXVtIC0gbWluaW11bSBhbGxvd2VkIHZhbHVlXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn1cclxuICAgKi9cclxuICBzdGF0aWMgbWluaW11bShtaW5pbXVtVmFsdWU6IG51bWJlcik6IElWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoIWhhc1ZhbHVlKG1pbmltdW1WYWx1ZSkpIHsgcmV0dXJuIEpzb25WYWxpZGF0b3JzLm51bGxWYWxpZGF0b3I7IH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbnZlcnQgPSBmYWxzZSk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PiB7XHJcbiAgICAgIGlmIChpc0VtcHR5KGNvbnRyb2wudmFsdWUpKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICAgIGNvbnN0IGN1cnJlbnRWYWx1ZSA9IGNvbnRyb2wudmFsdWU7XHJcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSAhaXNOdW1iZXIoY3VycmVudFZhbHVlKSB8fCBjdXJyZW50VmFsdWUgPj0gbWluaW11bVZhbHVlO1xyXG4gICAgICByZXR1cm4geG9yKGlzVmFsaWQsIGludmVydCkgP1xyXG4gICAgICAgIG51bGwgOiB7ICdtaW5pbXVtJzogeyBtaW5pbXVtVmFsdWUsIGN1cnJlbnRWYWx1ZSB9IH07XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2V4Y2x1c2l2ZU1pbmltdW0nIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogUmVxdWlyZXMgYSBjb250cm9sJ3MgbnVtZXJpYyB2YWx1ZSB0byBiZSBsZXNzIHRoYW4gYSBtYXhpbXVtIGFtb3VudC5cclxuICAgKlxyXG4gICAqIEFueSBub24tbnVtZXJpYyB2YWx1ZSBpcyBhbHNvIHZhbGlkIChhY2NvcmRpbmcgdG8gdGhlIEhUTUwgZm9ybXMgc3BlYyxcclxuICAgKiBhIG5vbi1udW1lcmljIHZhbHVlIGRvZXNuJ3QgaGF2ZSBhIG1heGltdW0pLlxyXG4gICAqIGh0dHBzOi8vd3d3LnczLm9yZy9UUi9odG1sNS9mb3Jtcy5odG1sI2F0dHItaW5wdXQtbWF4XHJcbiAgICpcclxuICAgKiAvLyB7bnVtYmVyfSBleGNsdXNpdmVNaW5pbXVtVmFsdWUgLSBtYXhpbXVtIGFsbG93ZWQgdmFsdWVcclxuICAgKiAvLyB7SVZhbGlkYXRvckZufVxyXG4gICAqL1xyXG4gIHN0YXRpYyBleGNsdXNpdmVNaW5pbXVtKGV4Y2x1c2l2ZU1pbmltdW1WYWx1ZTogbnVtYmVyKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUoZXhjbHVzaXZlTWluaW11bVZhbHVlKSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgaWYgKGlzRW1wdHkoY29udHJvbC52YWx1ZSkpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgY29uc3QgY3VycmVudFZhbHVlID0gY29udHJvbC52YWx1ZTtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9ICFpc051bWJlcihjdXJyZW50VmFsdWUpIHx8ICtjdXJyZW50VmFsdWUgPCBleGNsdXNpdmVNaW5pbXVtVmFsdWU7XHJcbiAgICAgIHJldHVybiB4b3IoaXNWYWxpZCwgaW52ZXJ0KSA/XHJcbiAgICAgICAgbnVsbCA6IHsgJ2V4Y2x1c2l2ZU1pbmltdW0nOiB7IGV4Y2x1c2l2ZU1pbmltdW1WYWx1ZSwgY3VycmVudFZhbHVlIH0gfTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnbWF4aW11bScgdmFsaWRhdG9yXHJcbiAgICpcclxuICAgKiBSZXF1aXJlcyBhIGNvbnRyb2wncyBudW1lcmljIHZhbHVlIHRvIGJlIGxlc3MgdGhhbiBvciBlcXVhbCB0b1xyXG4gICAqIGEgbWF4aW11bSBhbW91bnQuXHJcbiAgICpcclxuICAgKiBBbnkgbm9uLW51bWVyaWMgdmFsdWUgaXMgYWxzbyB2YWxpZCAoYWNjb3JkaW5nIHRvIHRoZSBIVE1MIGZvcm1zIHNwZWMsXHJcbiAgICogYSBub24tbnVtZXJpYyB2YWx1ZSBkb2Vzbid0IGhhdmUgYSBtYXhpbXVtKS5cclxuICAgKiBodHRwczovL3d3dy53My5vcmcvVFIvaHRtbDUvZm9ybXMuaHRtbCNhdHRyLWlucHV0LW1heFxyXG4gICAqXHJcbiAgICogLy8ge251bWJlcn0gbWF4aW11bVZhbHVlIC0gbWF4aW11bSBhbGxvd2VkIHZhbHVlXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn1cclxuICAgKi9cclxuICBzdGF0aWMgbWF4aW11bShtYXhpbXVtVmFsdWU6IG51bWJlcik6IElWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoIWhhc1ZhbHVlKG1heGltdW1WYWx1ZSkpIHsgcmV0dXJuIEpzb25WYWxpZGF0b3JzLm51bGxWYWxpZGF0b3I7IH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbnZlcnQgPSBmYWxzZSk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PiB7XHJcbiAgICAgIGlmIChpc0VtcHR5KGNvbnRyb2wudmFsdWUpKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICAgIGNvbnN0IGN1cnJlbnRWYWx1ZSA9IGNvbnRyb2wudmFsdWU7XHJcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSAhaXNOdW1iZXIoY3VycmVudFZhbHVlKSB8fCArY3VycmVudFZhbHVlIDw9IG1heGltdW1WYWx1ZTtcclxuICAgICAgcmV0dXJuIHhvcihpc1ZhbGlkLCBpbnZlcnQpID9cclxuICAgICAgICBudWxsIDogeyAnbWF4aW11bSc6IHsgbWF4aW11bVZhbHVlLCBjdXJyZW50VmFsdWUgfSB9O1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdleGNsdXNpdmVNYXhpbXVtJyB2YWxpZGF0b3JcclxuICAgKlxyXG4gICAqIFJlcXVpcmVzIGEgY29udHJvbCdzIG51bWVyaWMgdmFsdWUgdG8gYmUgbGVzcyB0aGFuIGEgbWF4aW11bSBhbW91bnQuXHJcbiAgICpcclxuICAgKiBBbnkgbm9uLW51bWVyaWMgdmFsdWUgaXMgYWxzbyB2YWxpZCAoYWNjb3JkaW5nIHRvIHRoZSBIVE1MIGZvcm1zIHNwZWMsXHJcbiAgICogYSBub24tbnVtZXJpYyB2YWx1ZSBkb2Vzbid0IGhhdmUgYSBtYXhpbXVtKS5cclxuICAgKiBodHRwczovL3d3dy53My5vcmcvVFIvaHRtbDUvZm9ybXMuaHRtbCNhdHRyLWlucHV0LW1heFxyXG4gICAqXHJcbiAgICogLy8ge251bWJlcn0gZXhjbHVzaXZlTWF4aW11bVZhbHVlIC0gbWF4aW11bSBhbGxvd2VkIHZhbHVlXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn1cclxuICAgKi9cclxuICBzdGF0aWMgZXhjbHVzaXZlTWF4aW11bShleGNsdXNpdmVNYXhpbXVtVmFsdWU6IG51bWJlcik6IElWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoIWhhc1ZhbHVlKGV4Y2x1c2l2ZU1heGltdW1WYWx1ZSkpIHsgcmV0dXJuIEpzb25WYWxpZGF0b3JzLm51bGxWYWxpZGF0b3I7IH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbnZlcnQgPSBmYWxzZSk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PiB7XHJcbiAgICAgIGlmIChpc0VtcHR5KGNvbnRyb2wudmFsdWUpKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICAgIGNvbnN0IGN1cnJlbnRWYWx1ZSA9IGNvbnRyb2wudmFsdWU7XHJcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSAhaXNOdW1iZXIoY3VycmVudFZhbHVlKSB8fCArY3VycmVudFZhbHVlIDwgZXhjbHVzaXZlTWF4aW11bVZhbHVlO1xyXG4gICAgICByZXR1cm4geG9yKGlzVmFsaWQsIGludmVydCkgP1xyXG4gICAgICAgIG51bGwgOiB7ICdleGNsdXNpdmVNYXhpbXVtJzogeyBleGNsdXNpdmVNYXhpbXVtVmFsdWUsIGN1cnJlbnRWYWx1ZSB9IH07XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ211bHRpcGxlT2YnIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogUmVxdWlyZXMgYSBjb250cm9sIHRvIGhhdmUgYSBudW1lcmljIHZhbHVlIHRoYXQgaXMgYSBtdWx0aXBsZVxyXG4gICAqIG9mIGEgc3BlY2lmaWVkIG51bWJlci5cclxuICAgKlxyXG4gICAqIC8vIHtudW1iZXJ9IG11bHRpcGxlT2ZWYWx1ZSAtIG51bWJlciB2YWx1ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2ZcclxuICAgKiAvLyB7SVZhbGlkYXRvckZufVxyXG4gICAqL1xyXG4gIHN0YXRpYyBtdWx0aXBsZU9mKG11bHRpcGxlT2ZWYWx1ZTogbnVtYmVyKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUobXVsdGlwbGVPZlZhbHVlKSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgaWYgKGlzRW1wdHkoY29udHJvbC52YWx1ZSkpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgY29uc3QgY3VycmVudFZhbHVlID0gY29udHJvbC52YWx1ZTtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9IGlzTnVtYmVyKGN1cnJlbnRWYWx1ZSkgJiZcclxuICAgICAgICBjdXJyZW50VmFsdWUgJSBtdWx0aXBsZU9mVmFsdWUgPT09IDA7XHJcbiAgICAgIHJldHVybiB4b3IoaXNWYWxpZCwgaW52ZXJ0KSA/XHJcbiAgICAgICAgbnVsbCA6IHsgJ211bHRpcGxlT2YnOiB7IG11bHRpcGxlT2ZWYWx1ZSwgY3VycmVudFZhbHVlIH0gfTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnbWluUHJvcGVydGllcycgdmFsaWRhdG9yXHJcbiAgICpcclxuICAgKiBSZXF1aXJlcyBhIGZvcm0gZ3JvdXAgdG8gaGF2ZSBhIG1pbmltdW0gbnVtYmVyIG9mIHByb3BlcnRpZXMgKGkuZS4gaGF2ZVxyXG4gICAqIHZhbHVlcyBlbnRlcmVkIGluIGEgbWluaW11bSBudW1iZXIgb2YgY29udHJvbHMgd2l0aGluIHRoZSBncm91cCkuXHJcbiAgICpcclxuICAgKiAvLyB7bnVtYmVyfSBtaW5pbXVtUHJvcGVydGllcyAtIG1pbmltdW0gbnVtYmVyIG9mIHByb3BlcnRpZXMgYWxsb3dlZFxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59XHJcbiAgICovXHJcbiAgc3RhdGljIG1pblByb3BlcnRpZXMobWluaW11bVByb3BlcnRpZXM6IG51bWJlcik6IElWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoIWhhc1ZhbHVlKG1pbmltdW1Qcm9wZXJ0aWVzKSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgaWYgKGlzRW1wdHkoY29udHJvbC52YWx1ZSkpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgY29uc3QgY3VycmVudFByb3BlcnRpZXMgPSBPYmplY3Qua2V5cyhjb250cm9sLnZhbHVlKS5sZW5ndGggfHwgMDtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9IGN1cnJlbnRQcm9wZXJ0aWVzID49IG1pbmltdW1Qcm9wZXJ0aWVzO1xyXG4gICAgICByZXR1cm4geG9yKGlzVmFsaWQsIGludmVydCkgP1xyXG4gICAgICAgIG51bGwgOiB7ICdtaW5Qcm9wZXJ0aWVzJzogeyBtaW5pbXVtUHJvcGVydGllcywgY3VycmVudFByb3BlcnRpZXMgfSB9O1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdtYXhQcm9wZXJ0aWVzJyB2YWxpZGF0b3JcclxuICAgKlxyXG4gICAqIFJlcXVpcmVzIGEgZm9ybSBncm91cCB0byBoYXZlIGEgbWF4aW11bSBudW1iZXIgb2YgcHJvcGVydGllcyAoaS5lLiBoYXZlXHJcbiAgICogdmFsdWVzIGVudGVyZWQgaW4gYSBtYXhpbXVtIG51bWJlciBvZiBjb250cm9scyB3aXRoaW4gdGhlIGdyb3VwKS5cclxuICAgKlxyXG4gICAqIE5vdGU6IEhhcyBubyBlZmZlY3QgaWYgdGhlIGZvcm0gZ3JvdXAgZG9lcyBub3QgY29udGFpbiBtb3JlIHRoYW4gdGhlXHJcbiAgICogbWF4aW11bSBudW1iZXIgb2YgY29udHJvbHMuXHJcbiAgICpcclxuICAgKiAvLyB7bnVtYmVyfSBtYXhpbXVtUHJvcGVydGllcyAtIG1heGltdW0gbnVtYmVyIG9mIHByb3BlcnRpZXMgYWxsb3dlZFxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59XHJcbiAgICovXHJcbiAgc3RhdGljIG1heFByb3BlcnRpZXMobWF4aW11bVByb3BlcnRpZXM6IG51bWJlcik6IElWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoIWhhc1ZhbHVlKG1heGltdW1Qcm9wZXJ0aWVzKSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgY29uc3QgY3VycmVudFByb3BlcnRpZXMgPSBPYmplY3Qua2V5cyhjb250cm9sLnZhbHVlKS5sZW5ndGggfHwgMDtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9IGN1cnJlbnRQcm9wZXJ0aWVzIDw9IG1heGltdW1Qcm9wZXJ0aWVzO1xyXG4gICAgICByZXR1cm4geG9yKGlzVmFsaWQsIGludmVydCkgP1xyXG4gICAgICAgIG51bGwgOiB7ICdtYXhQcm9wZXJ0aWVzJzogeyBtYXhpbXVtUHJvcGVydGllcywgY3VycmVudFByb3BlcnRpZXMgfSB9O1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdkZXBlbmRlbmNpZXMnIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogUmVxdWlyZXMgdGhlIGNvbnRyb2xzIGluIGEgZm9ybSBncm91cCB0byBtZWV0IGFkZGl0aW9uYWwgdmFsaWRhdGlvblxyXG4gICAqIGNyaXRlcmlhLCBkZXBlbmRpbmcgb24gdGhlIHZhbHVlcyBvZiBvdGhlciBjb250cm9scyBpbiB0aGUgZ3JvdXAuXHJcbiAgICpcclxuICAgKiBFeGFtcGxlczpcclxuICAgKiBodHRwczovL3NwYWNldGVsZXNjb3BlLmdpdGh1Yi5pby91bmRlcnN0YW5kaW5nLWpzb24tc2NoZW1hL3JlZmVyZW5jZS9vYmplY3QuaHRtbCNkZXBlbmRlbmNpZXNcclxuICAgKlxyXG4gICAqIC8vIHthbnl9IGRlcGVuZGVuY2llcyAtIHJlcXVpcmVkIGRlcGVuZGVuY2llc1xyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59XHJcbiAgICovXHJcbiAgc3RhdGljIGRlcGVuZGVuY2llcyhkZXBlbmRlbmNpZXM6IGFueSk6IElWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoZ2V0VHlwZShkZXBlbmRlbmNpZXMpICE9PSAnb2JqZWN0JyB8fCBpc0VtcHR5KGRlcGVuZGVuY2llcykpIHtcclxuICAgICAgcmV0dXJuIEpzb25WYWxpZGF0b3JzLm51bGxWYWxpZGF0b3I7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgaW52ZXJ0ID0gZmFsc2UpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT4ge1xyXG4gICAgICBpZiAoaXNFbXB0eShjb250cm9sLnZhbHVlKSkgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgICBjb25zdCBhbGxFcnJvcnMgPSBfbWVyZ2VPYmplY3RzKFxyXG4gICAgICAgIGZvckVhY2hDb3B5KGRlcGVuZGVuY2llcywgKHZhbHVlLCByZXF1aXJpbmdGaWVsZCkgPT4ge1xyXG4gICAgICAgICAgaWYgKCFoYXNWYWx1ZShjb250cm9sLnZhbHVlW3JlcXVpcmluZ0ZpZWxkXSkpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgICAgIGxldCByZXF1aXJpbmdGaWVsZEVycm9yczogVmFsaWRhdGlvbkVycm9ycyA9IHsgfTtcclxuICAgICAgICAgIGxldCByZXF1aXJlZEZpZWxkczogc3RyaW5nW107XHJcbiAgICAgICAgICBsZXQgcHJvcGVydGllczogVmFsaWRhdGlvbkVycm9ycyA9IHsgfTtcclxuICAgICAgICAgIGlmIChnZXRUeXBlKGRlcGVuZGVuY2llc1tyZXF1aXJpbmdGaWVsZF0pID09PSAnYXJyYXknKSB7XHJcbiAgICAgICAgICAgIHJlcXVpcmVkRmllbGRzID0gZGVwZW5kZW5jaWVzW3JlcXVpcmluZ0ZpZWxkXTtcclxuICAgICAgICAgIH0gZWxzZSBpZiAoZ2V0VHlwZShkZXBlbmRlbmNpZXNbcmVxdWlyaW5nRmllbGRdKSA9PT0gJ29iamVjdCcpIHtcclxuICAgICAgICAgICAgcmVxdWlyZWRGaWVsZHMgPSBkZXBlbmRlbmNpZXNbcmVxdWlyaW5nRmllbGRdWydyZXF1aXJlZCddIHx8IFtdO1xyXG4gICAgICAgICAgICBwcm9wZXJ0aWVzID0gZGVwZW5kZW5jaWVzW3JlcXVpcmluZ0ZpZWxkXVsncHJvcGVydGllcyddIHx8IHsgfTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAvLyBWYWxpZGF0ZSBwcm9wZXJ0eSBkZXBlbmRlbmNpZXNcclxuICAgICAgICAgIGZvciAoY29uc3QgcmVxdWlyZWRGaWVsZCBvZiByZXF1aXJlZEZpZWxkcykge1xyXG4gICAgICAgICAgICBpZiAoeG9yKCFoYXNWYWx1ZShjb250cm9sLnZhbHVlW3JlcXVpcmVkRmllbGRdKSwgaW52ZXJ0KSkge1xyXG4gICAgICAgICAgICAgIHJlcXVpcmluZ0ZpZWxkRXJyb3JzW3JlcXVpcmVkRmllbGRdID0geyAncmVxdWlyZWQnOiB0cnVlIH07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAvLyBWYWxpZGF0ZSBzY2hlbWEgZGVwZW5kZW5jaWVzXHJcbiAgICAgICAgICByZXF1aXJpbmdGaWVsZEVycm9ycyA9IF9tZXJnZU9iamVjdHMocmVxdWlyaW5nRmllbGRFcnJvcnMsXHJcbiAgICAgICAgICAgIGZvckVhY2hDb3B5KHByb3BlcnRpZXMsIChyZXF1aXJlbWVudHMsIHJlcXVpcmVkRmllbGQpID0+IHtcclxuICAgICAgICAgICAgICBjb25zdCByZXF1aXJlZEZpZWxkRXJyb3JzID0gX21lcmdlT2JqZWN0cyhcclxuICAgICAgICAgICAgICAgIGZvckVhY2hDb3B5KHJlcXVpcmVtZW50cywgKHJlcXVpcmVtZW50LCBwYXJhbWV0ZXIpID0+IHtcclxuICAgICAgICAgICAgICAgICAgbGV0IHZhbGlkYXRvcjogSVZhbGlkYXRvckZuID0gbnVsbDtcclxuICAgICAgICAgICAgICAgICAgaWYgKHJlcXVpcmVtZW50ID09PSAnbWF4aW11bScgfHwgcmVxdWlyZW1lbnQgPT09ICdtaW5pbXVtJykge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4Y2x1c2l2ZSA9ICEhcmVxdWlyZW1lbnRzWydleGNsdXNpdmVNJyArIHJlcXVpcmVtZW50LnNsaWNlKDEpXTtcclxuICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3IgPSBKc29uVmFsaWRhdG9yc1tyZXF1aXJlbWVudF0ocGFyYW1ldGVyLCBleGNsdXNpdmUpO1xyXG4gICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBKc29uVmFsaWRhdG9yc1tyZXF1aXJlbWVudF0gPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YWxpZGF0b3IgPSBKc29uVmFsaWRhdG9yc1tyZXF1aXJlbWVudF0ocGFyYW1ldGVyKTtcclxuICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICByZXR1cm4gIWlzRGVmaW5lZCh2YWxpZGF0b3IpID9cclxuICAgICAgICAgICAgICAgICAgICBudWxsIDogdmFsaWRhdG9yKGNvbnRyb2wudmFsdWVbcmVxdWlyZWRGaWVsZF0pO1xyXG4gICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgIHJldHVybiBpc0VtcHR5KHJlcXVpcmVkRmllbGRFcnJvcnMpID9cclxuICAgICAgICAgICAgICAgIG51bGwgOiB7IFtyZXF1aXJlZEZpZWxkXTogcmVxdWlyZWRGaWVsZEVycm9ycyB9O1xyXG4gICAgICAgICAgICB9KVxyXG4gICAgICAgICAgKTtcclxuICAgICAgICAgIHJldHVybiBpc0VtcHR5KHJlcXVpcmluZ0ZpZWxkRXJyb3JzKSA/XHJcbiAgICAgICAgICAgIG51bGwgOiB7IFtyZXF1aXJpbmdGaWVsZF06IHJlcXVpcmluZ0ZpZWxkRXJyb3JzIH07XHJcbiAgICAgICAgfSlcclxuICAgICAgKTtcclxuICAgICAgcmV0dXJuIGlzRW1wdHkoYWxsRXJyb3JzKSA/IG51bGwgOiBhbGxFcnJvcnM7XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ21pbkl0ZW1zJyB2YWxpZGF0b3JcclxuICAgKlxyXG4gICAqIFJlcXVpcmVzIGEgZm9ybSBhcnJheSB0byBoYXZlIGEgbWluaW11bSBudW1iZXIgb2YgdmFsdWVzLlxyXG4gICAqXHJcbiAgICogLy8ge251bWJlcn0gbWluaW11bUl0ZW1zIC0gbWluaW11bSBudW1iZXIgb2YgaXRlbXMgYWxsb3dlZFxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59XHJcbiAgICovXHJcbiAgc3RhdGljIG1pbkl0ZW1zKG1pbmltdW1JdGVtczogbnVtYmVyKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUobWluaW11bUl0ZW1zKSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgaWYgKGlzRW1wdHkoY29udHJvbC52YWx1ZSkpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgICAgY29uc3QgY3VycmVudEl0ZW1zID0gaXNBcnJheShjb250cm9sLnZhbHVlKSA/IGNvbnRyb2wudmFsdWUubGVuZ3RoIDogMDtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9IGN1cnJlbnRJdGVtcyA+PSBtaW5pbXVtSXRlbXM7XHJcbiAgICAgIHJldHVybiB4b3IoaXNWYWxpZCwgaW52ZXJ0KSA/XHJcbiAgICAgICAgbnVsbCA6IHsgJ21pbkl0ZW1zJzogeyBtaW5pbXVtSXRlbXMsIGN1cnJlbnRJdGVtcyB9IH07XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ21heEl0ZW1zJyB2YWxpZGF0b3JcclxuICAgKlxyXG4gICAqIFJlcXVpcmVzIGEgZm9ybSBhcnJheSB0byBoYXZlIGEgbWF4aW11bSBudW1iZXIgb2YgdmFsdWVzLlxyXG4gICAqXHJcbiAgICogLy8ge251bWJlcn0gbWF4aW11bUl0ZW1zIC0gbWF4aW11bSBudW1iZXIgb2YgaXRlbXMgYWxsb3dlZFxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59XHJcbiAgICovXHJcbiAgc3RhdGljIG1heEl0ZW1zKG1heGltdW1JdGVtczogbnVtYmVyKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUobWF4aW11bUl0ZW1zKSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgY29uc3QgY3VycmVudEl0ZW1zID0gaXNBcnJheShjb250cm9sLnZhbHVlKSA/IGNvbnRyb2wudmFsdWUubGVuZ3RoIDogMDtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9IGN1cnJlbnRJdGVtcyA8PSBtYXhpbXVtSXRlbXM7XHJcbiAgICAgIHJldHVybiB4b3IoaXNWYWxpZCwgaW52ZXJ0KSA/XHJcbiAgICAgICAgbnVsbCA6IHsgJ21heEl0ZW1zJzogeyBtYXhpbXVtSXRlbXMsIGN1cnJlbnRJdGVtcyB9IH07XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ3VuaXF1ZUl0ZW1zJyB2YWxpZGF0b3JcclxuICAgKlxyXG4gICAqIFJlcXVpcmVzIHZhbHVlcyBpbiBhIGZvcm0gYXJyYXkgdG8gYmUgdW5pcXVlLlxyXG4gICAqXHJcbiAgICogLy8ge2Jvb2xlYW4gPSB0cnVlfSB1bmlxdWU/IC0gdHJ1ZSB0byB2YWxpZGF0ZSwgZmFsc2UgdG8gZGlzYWJsZVxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59XHJcbiAgICovXHJcbiAgc3RhdGljIHVuaXF1ZUl0ZW1zKHVuaXF1ZSA9IHRydWUpOiBJVmFsaWRhdG9yRm4ge1xyXG4gICAgaWYgKCF1bmlxdWUpIHsgcmV0dXJuIEpzb25WYWxpZGF0b3JzLm51bGxWYWxpZGF0b3I7IH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbnZlcnQgPSBmYWxzZSk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PiB7XHJcbiAgICAgIGlmIChpc0VtcHR5KGNvbnRyb2wudmFsdWUpKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICAgIGNvbnN0IHNvcnRlZDogYW55W10gPSBjb250cm9sLnZhbHVlLnNsaWNlKCkuc29ydCgpO1xyXG4gICAgICBjb25zdCBkdXBsaWNhdGVJdGVtcyA9IFtdO1xyXG4gICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHNvcnRlZC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIGlmIChzb3J0ZWRbaSAtIDFdID09PSBzb3J0ZWRbaV0gJiYgZHVwbGljYXRlSXRlbXMuaW5jbHVkZXMoc29ydGVkW2ldKSkge1xyXG4gICAgICAgICAgZHVwbGljYXRlSXRlbXMucHVzaChzb3J0ZWRbaV0pO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBjb25zdCBpc1ZhbGlkID0gIWR1cGxpY2F0ZUl0ZW1zLmxlbmd0aDtcclxuICAgICAgcmV0dXJuIHhvcihpc1ZhbGlkLCBpbnZlcnQpID9cclxuICAgICAgICBudWxsIDogeyAndW5pcXVlSXRlbXMnOiB7IGR1cGxpY2F0ZUl0ZW1zIH0gfTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnY29udGFpbnMnIHZhbGlkYXRvclxyXG4gICAqXHJcbiAgICogVE9ETzogQ29tcGxldGUgdGhpcyB2YWxpZGF0b3JcclxuICAgKlxyXG4gICAqIFJlcXVpcmVzIHZhbHVlcyBpbiBhIGZvcm0gYXJyYXkgdG8gYmUgdW5pcXVlLlxyXG4gICAqXHJcbiAgICogLy8ge2Jvb2xlYW4gPSB0cnVlfSB1bmlxdWU/IC0gdHJ1ZSB0byB2YWxpZGF0ZSwgZmFsc2UgdG8gZGlzYWJsZVxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59XHJcbiAgICovXHJcbiAgc3RhdGljIGNvbnRhaW5zKHJlcXVpcmVkSXRlbSA9IHRydWUpOiBJVmFsaWRhdG9yRm4ge1xyXG4gICAgaWYgKCFyZXF1aXJlZEl0ZW0pIHsgcmV0dXJuIEpzb25WYWxpZGF0b3JzLm51bGxWYWxpZGF0b3I7IH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbnZlcnQgPSBmYWxzZSk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PiB7XHJcbiAgICAgIGlmIChpc0VtcHR5KGNvbnRyb2wudmFsdWUpIHx8ICFpc0FycmF5KGNvbnRyb2wudmFsdWUpKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICAgIGNvbnN0IGN1cnJlbnRJdGVtcyA9IGNvbnRyb2wudmFsdWU7XHJcbiAgICAgIC8vIGNvbnN0IGlzVmFsaWQgPSBjdXJyZW50SXRlbXMuc29tZShpdGVtID0+XHJcbiAgICAgIC8vXHJcbiAgICAgIC8vICk7XHJcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSB0cnVlO1xyXG4gICAgICByZXR1cm4geG9yKGlzVmFsaWQsIGludmVydCkgP1xyXG4gICAgICAgIG51bGwgOiB7ICdjb250YWlucyc6IHsgcmVxdWlyZWRJdGVtLCBjdXJyZW50SXRlbXMgfSB9O1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE5vLW9wIHZhbGlkYXRvci4gSW5jbHVkZWQgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkuXHJcbiAgICovXHJcbiAgc3RhdGljIG51bGxWYWxpZGF0b3IoY29udHJvbDogQWJzdHJhY3RDb250cm9sKTogVmFsaWRhdGlvbkVycm9yc3xudWxsIHtcclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVmFsaWRhdG9yIHRyYW5zZm9ybWF0aW9uIGZ1bmN0aW9uczpcclxuICAgKiBjb21wb3NlQW55T2YsIGNvbXBvc2VPbmVPZiwgY29tcG9zZUFsbE9mLCBjb21wb3NlTm90LFxyXG4gICAqIGNvbXBvc2UsIGNvbXBvc2VBc3luY1xyXG4gICAqXHJcbiAgICogVE9ETzogQWRkIGNvbXBvc2VBbnlPZkFzeW5jLCBjb21wb3NlT25lT2ZBc3luYyxcclxuICAgKiAgICAgICAgICAgY29tcG9zZUFsbE9mQXN5bmMsIGNvbXBvc2VOb3RBc3luY1xyXG4gICAqL1xyXG5cclxuICAvKipcclxuICAgKiAnY29tcG9zZUFueU9mJyB2YWxpZGF0b3IgY29tYmluYXRpb24gZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIEFjY2VwdHMgYW4gYXJyYXkgb2YgdmFsaWRhdG9ycyBhbmQgcmV0dXJucyBhIHNpbmdsZSB2YWxpZGF0b3IgdGhhdFxyXG4gICAqIGV2YWx1YXRlcyB0byB2YWxpZCBpZiBhbnkgb25lIG9yIG1vcmUgb2YgdGhlIHN1Ym1pdHRlZCB2YWxpZGF0b3JzIGFyZVxyXG4gICAqIHZhbGlkLiBJZiBldmVyeSB2YWxpZGF0b3IgaXMgaW52YWxpZCwgaXQgcmV0dXJucyBjb21iaW5lZCBlcnJvcnMgZnJvbVxyXG4gICAqIGFsbCB2YWxpZGF0b3JzLlxyXG4gICAqXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbltdfSB2YWxpZGF0b3JzIC0gYXJyYXkgb2YgdmFsaWRhdG9ycyB0byBjb21iaW5lXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn0gLSBzaW5nbGUgY29tYmluZWQgdmFsaWRhdG9yIGZ1bmN0aW9uXHJcbiAgICovXHJcbiAgc3RhdGljIGNvbXBvc2VBbnlPZih2YWxpZGF0b3JzOiBJVmFsaWRhdG9yRm5bXSk6IElWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoIXZhbGlkYXRvcnMpIHsgcmV0dXJuIG51bGw7IH1cclxuICAgIGNvbnN0IHByZXNlbnRWYWxpZGF0b3JzID0gdmFsaWRhdG9ycy5maWx0ZXIoaXNEZWZpbmVkKTtcclxuICAgIGlmIChwcmVzZW50VmFsaWRhdG9ycy5sZW5ndGggPT09IDApIHsgcmV0dXJuIG51bGw7IH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbnZlcnQgPSBmYWxzZSk6IFZhbGlkYXRpb25FcnJvcnN8bnVsbCA9PiB7XHJcbiAgICAgIGNvbnN0IGFycmF5T2ZFcnJvcnMgPVxyXG4gICAgICAgIF9leGVjdXRlVmFsaWRhdG9ycyhjb250cm9sLCBwcmVzZW50VmFsaWRhdG9ycywgaW52ZXJ0KS5maWx0ZXIoaXNEZWZpbmVkKTtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9IHZhbGlkYXRvcnMubGVuZ3RoID4gYXJyYXlPZkVycm9ycy5sZW5ndGg7XHJcbiAgICAgIHJldHVybiB4b3IoaXNWYWxpZCwgaW52ZXJ0KSA/XHJcbiAgICAgICAgbnVsbCA6IF9tZXJnZU9iamVjdHMoLi4uYXJyYXlPZkVycm9ycywgeyAnYW55T2YnOiAhaW52ZXJ0IH0pO1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdjb21wb3NlT25lT2YnIHZhbGlkYXRvciBjb21iaW5hdGlvbiBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogQWNjZXB0cyBhbiBhcnJheSBvZiB2YWxpZGF0b3JzIGFuZCByZXR1cm5zIGEgc2luZ2xlIHZhbGlkYXRvciB0aGF0XHJcbiAgICogZXZhbHVhdGVzIHRvIHZhbGlkIG9ubHkgaWYgZXhhY3RseSBvbmUgb2YgdGhlIHN1Ym1pdHRlZCB2YWxpZGF0b3JzXHJcbiAgICogaXMgdmFsaWQuIE90aGVyd2lzZSByZXR1cm5zIGNvbWJpbmVkIGluZm9ybWF0aW9uIGZyb20gYWxsIHZhbGlkYXRvcnMsXHJcbiAgICogYm90aCB2YWxpZCBhbmQgaW52YWxpZC5cclxuICAgKlxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm5bXX0gdmFsaWRhdG9ycyAtIGFycmF5IG9mIHZhbGlkYXRvcnMgdG8gY29tYmluZVxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm59IC0gc2luZ2xlIGNvbWJpbmVkIHZhbGlkYXRvciBmdW5jdGlvblxyXG4gICAqL1xyXG4gIHN0YXRpYyBjb21wb3NlT25lT2YodmFsaWRhdG9yczogSVZhbGlkYXRvckZuW10pOiBJVmFsaWRhdG9yRm4ge1xyXG4gICAgaWYgKCF2YWxpZGF0b3JzKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICBjb25zdCBwcmVzZW50VmFsaWRhdG9ycyA9IHZhbGlkYXRvcnMuZmlsdGVyKGlzRGVmaW5lZCk7XHJcbiAgICBpZiAocHJlc2VudFZhbGlkYXRvcnMubGVuZ3RoID09PSAwKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgaW52ZXJ0ID0gZmFsc2UpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT4ge1xyXG4gICAgICBjb25zdCBhcnJheU9mRXJyb3JzID1cclxuICAgICAgICBfZXhlY3V0ZVZhbGlkYXRvcnMoY29udHJvbCwgcHJlc2VudFZhbGlkYXRvcnMpO1xyXG4gICAgICBjb25zdCB2YWxpZENvbnRyb2xzID1cclxuICAgICAgICB2YWxpZGF0b3JzLmxlbmd0aCAtIGFycmF5T2ZFcnJvcnMuZmlsdGVyKGlzRGVmaW5lZCkubGVuZ3RoO1xyXG4gICAgICBjb25zdCBpc1ZhbGlkID0gdmFsaWRDb250cm9scyA9PT0gMTtcclxuICAgICAgaWYgKHhvcihpc1ZhbGlkLCBpbnZlcnQpKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICAgIGNvbnN0IGFycmF5T2ZWYWxpZHMgPVxyXG4gICAgICAgIF9leGVjdXRlVmFsaWRhdG9ycyhjb250cm9sLCBwcmVzZW50VmFsaWRhdG9ycywgaW52ZXJ0KTtcclxuICAgICAgcmV0dXJuIF9tZXJnZU9iamVjdHMoLi4uYXJyYXlPZkVycm9ycywgLi4uYXJyYXlPZlZhbGlkcywgeyAnb25lT2YnOiAhaW52ZXJ0IH0pO1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdjb21wb3NlQWxsT2YnIHZhbGlkYXRvciBjb21iaW5hdGlvbiBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogQWNjZXB0cyBhbiBhcnJheSBvZiB2YWxpZGF0b3JzIGFuZCByZXR1cm5zIGEgc2luZ2xlIHZhbGlkYXRvciB0aGF0XHJcbiAgICogZXZhbHVhdGVzIHRvIHZhbGlkIG9ubHkgaWYgYWxsIHRoZSBzdWJtaXR0ZWQgdmFsaWRhdG9ycyBhcmUgaW5kaXZpZHVhbGx5XHJcbiAgICogdmFsaWQuIE90aGVyd2lzZSBpdCByZXR1cm5zIGNvbWJpbmVkIGVycm9ycyBmcm9tIGFsbCBpbnZhbGlkIHZhbGlkYXRvcnMuXHJcbiAgICpcclxuICAgKiAvLyB7SVZhbGlkYXRvckZuW119IHZhbGlkYXRvcnMgLSBhcnJheSBvZiB2YWxpZGF0b3JzIHRvIGNvbWJpbmVcclxuICAgKiAvLyB7SVZhbGlkYXRvckZufSAtIHNpbmdsZSBjb21iaW5lZCB2YWxpZGF0b3IgZnVuY3Rpb25cclxuICAgKi9cclxuICBzdGF0aWMgY29tcG9zZUFsbE9mKHZhbGlkYXRvcnM6IElWYWxpZGF0b3JGbltdKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghdmFsaWRhdG9ycykgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgY29uc3QgcHJlc2VudFZhbGlkYXRvcnMgPSB2YWxpZGF0b3JzLmZpbHRlcihpc0RlZmluZWQpO1xyXG4gICAgaWYgKHByZXNlbnRWYWxpZGF0b3JzLmxlbmd0aCA9PT0gMCkgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIGludmVydCA9IGZhbHNlKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgY29uc3QgY29tYmluZWRFcnJvcnMgPSBfbWVyZ2VFcnJvcnMoXHJcbiAgICAgICAgX2V4ZWN1dGVWYWxpZGF0b3JzKGNvbnRyb2wsIHByZXNlbnRWYWxpZGF0b3JzLCBpbnZlcnQpXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSBjb21iaW5lZEVycm9ycyA9PT0gbnVsbDtcclxuICAgICAgcmV0dXJuICh4b3IoaXNWYWxpZCwgaW52ZXJ0KSkgP1xyXG4gICAgICAgIG51bGwgOiBfbWVyZ2VPYmplY3RzKGNvbWJpbmVkRXJyb3JzLCB7ICdhbGxPZic6ICFpbnZlcnQgfSk7XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2NvbXBvc2VOb3QnIHZhbGlkYXRvciBpbnZlcnNpb24gZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIEFjY2VwdHMgYSBzaW5nbGUgdmFsaWRhdG9yIGZ1bmN0aW9uIGFuZCBpbnZlcnRzIGl0cyByZXN1bHQuXHJcbiAgICogUmV0dXJucyB2YWxpZCBpZiB0aGUgc3VibWl0dGVkIHZhbGlkYXRvciBpcyBpbnZhbGlkLCBhbmRcclxuICAgKiByZXR1cm5zIGludmFsaWQgaWYgdGhlIHN1Ym1pdHRlZCB2YWxpZGF0b3IgaXMgdmFsaWQuXHJcbiAgICogKE5vdGU6IHRoaXMgZnVuY3Rpb24gY2FuIGl0c2VsZiBiZSBpbnZlcnRlZFxyXG4gICAqICAgLSBlLmcuIGNvbXBvc2VOb3QoY29tcG9zZU5vdCh2YWxpZGF0b3IpKSAtXHJcbiAgICogICBidXQgdGhpcyBjYW4gYmUgY29uZnVzaW5nIGFuZCBpcyB0aGVyZWZvcmUgbm90IHJlY29tbWVuZGVkLilcclxuICAgKlxyXG4gICAqIC8vIHtJVmFsaWRhdG9yRm5bXX0gdmFsaWRhdG9ycyAtIHZhbGlkYXRvcihzKSB0byBpbnZlcnRcclxuICAgKiAvLyB7SVZhbGlkYXRvckZufSAtIG5ldyB2YWxpZGF0b3IgZnVuY3Rpb24gdGhhdCByZXR1cm5zIG9wcG9zaXRlIHJlc3VsdFxyXG4gICAqL1xyXG4gIHN0YXRpYyBjb21wb3NlTm90KHZhbGlkYXRvcjogSVZhbGlkYXRvckZuKTogSVZhbGlkYXRvckZuIHtcclxuICAgIGlmICghdmFsaWRhdG9yKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgaW52ZXJ0ID0gZmFsc2UpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT4ge1xyXG4gICAgICBpZiAoaXNFbXB0eShjb250cm9sLnZhbHVlKSkgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgICBjb25zdCBlcnJvciA9IHZhbGlkYXRvcihjb250cm9sLCAhaW52ZXJ0KTtcclxuICAgICAgY29uc3QgaXNWYWxpZCA9IGVycm9yID09PSBudWxsO1xyXG4gICAgICByZXR1cm4gKHhvcihpc1ZhbGlkLCBpbnZlcnQpKSA/XHJcbiAgICAgICAgbnVsbCA6IF9tZXJnZU9iamVjdHMoZXJyb3IsIHsgJ25vdCc6ICFpbnZlcnQgfSk7XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2NvbXBvc2UnIHZhbGlkYXRvciBjb21iaW5hdGlvbiBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbltdfSB2YWxpZGF0b3JzIC0gYXJyYXkgb2YgdmFsaWRhdG9ycyB0byBjb21iaW5lXHJcbiAgICogLy8ge0lWYWxpZGF0b3JGbn0gLSBzaW5nbGUgY29tYmluZWQgdmFsaWRhdG9yIGZ1bmN0aW9uXHJcbiAgICovXHJcbiAgc3RhdGljIGNvbXBvc2UodmFsaWRhdG9yczogSVZhbGlkYXRvckZuW10pOiBJVmFsaWRhdG9yRm4ge1xyXG4gICAgaWYgKCF2YWxpZGF0b3JzKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICBjb25zdCBwcmVzZW50VmFsaWRhdG9ycyA9IHZhbGlkYXRvcnMuZmlsdGVyKGlzRGVmaW5lZCk7XHJcbiAgICBpZiAocHJlc2VudFZhbGlkYXRvcnMubGVuZ3RoID09PSAwKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgaW52ZXJ0ID0gZmFsc2UpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT5cclxuICAgICAgX21lcmdlRXJyb3JzKF9leGVjdXRlVmFsaWRhdG9ycyhjb250cm9sLCBwcmVzZW50VmFsaWRhdG9ycywgaW52ZXJ0KSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnY29tcG9zZUFzeW5jJyBhc3luYyB2YWxpZGF0b3IgY29tYmluYXRpb24gZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIC8vIHtBc3luY0lWYWxpZGF0b3JGbltdfSBhc3luYyB2YWxpZGF0b3JzIC0gYXJyYXkgb2YgYXN5bmMgdmFsaWRhdG9yc1xyXG4gICAqIC8vIHtBc3luY0lWYWxpZGF0b3JGbn0gLSBzaW5nbGUgY29tYmluZWQgYXN5bmMgdmFsaWRhdG9yIGZ1bmN0aW9uXHJcbiAgICovXHJcbiAgc3RhdGljIGNvbXBvc2VBc3luYyh2YWxpZGF0b3JzOiBBc3luY0lWYWxpZGF0b3JGbltdKTogQXN5bmNJVmFsaWRhdG9yRm4ge1xyXG4gICAgaWYgKCF2YWxpZGF0b3JzKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICBjb25zdCBwcmVzZW50VmFsaWRhdG9ycyA9IHZhbGlkYXRvcnMuZmlsdGVyKGlzRGVmaW5lZCk7XHJcbiAgICBpZiAocHJlc2VudFZhbGlkYXRvcnMubGVuZ3RoID09PSAwKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCkgPT4ge1xyXG4gICAgICBjb25zdCBvYnNlcnZhYmxlcyA9XHJcbiAgICAgICAgX2V4ZWN1dGVBc3luY1ZhbGlkYXRvcnMoY29udHJvbCwgcHJlc2VudFZhbGlkYXRvcnMpLm1hcCh0b09ic2VydmFibGUpO1xyXG4gICAgICByZXR1cm4gbWFwLmNhbGwoZm9ya0pvaW4ob2JzZXJ2YWJsZXMpLCBfbWVyZ2VFcnJvcnMpO1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8vIEFkZGl0aW9uYWwgYW5ndWxhciB2YWxpZGF0b3JzIChub3QgdXNlZCBieSBBbmd1YWxyIEpTT04gU2NoZW1hIEZvcm0pXHJcbiAgLy8gRnJvbSBodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9hbmd1bGFyL2Jsb2IvbWFzdGVyL3BhY2thZ2VzL2Zvcm1zL3NyYy92YWxpZGF0b3JzLnRzXHJcblxyXG4gIC8qKlxyXG4gICAqIFZhbGlkYXRvciB0aGF0IHJlcXVpcmVzIGNvbnRyb2xzIHRvIGhhdmUgYSB2YWx1ZSBncmVhdGVyIHRoYW4gYSBudW1iZXIuXHJcbiAgICovXHJcbiAgc3RhdGljIG1pbihtaW46IG51bWJlcik6IFZhbGlkYXRvckZuIHtcclxuICAgIGlmICghaGFzVmFsdWUobWluKSkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwgPT4ge1xyXG4gICAgICAvLyBkb24ndCB2YWxpZGF0ZSBlbXB0eSB2YWx1ZXMgdG8gYWxsb3cgb3B0aW9uYWwgY29udHJvbHNcclxuICAgICAgaWYgKGlzRW1wdHkoY29udHJvbC52YWx1ZSkgfHwgaXNFbXB0eShtaW4pKSB7IHJldHVybiBudWxsOyB9XHJcbiAgICAgIGNvbnN0IHZhbHVlID0gcGFyc2VGbG9hdChjb250cm9sLnZhbHVlKTtcclxuICAgICAgY29uc3QgYWN0dWFsID0gY29udHJvbC52YWx1ZTtcclxuICAgICAgLy8gQ29udHJvbHMgd2l0aCBOYU4gdmFsdWVzIGFmdGVyIHBhcnNpbmcgc2hvdWxkIGJlIHRyZWF0ZWQgYXMgbm90IGhhdmluZyBhXHJcbiAgICAgIC8vIG1pbmltdW0sIHBlciB0aGUgSFRNTCBmb3JtcyBzcGVjOiBodHRwczovL3d3dy53My5vcmcvVFIvaHRtbDUvZm9ybXMuaHRtbCNhdHRyLWlucHV0LW1pblxyXG4gICAgICByZXR1cm4gaXNOYU4odmFsdWUpIHx8IHZhbHVlID49IG1pbiA/IG51bGwgOiB7ICdtaW4nOiB7IG1pbiwgYWN0dWFsIH0gfTtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBWYWxpZGF0b3IgdGhhdCByZXF1aXJlcyBjb250cm9scyB0byBoYXZlIGEgdmFsdWUgbGVzcyB0aGFuIGEgbnVtYmVyLlxyXG4gICAqL1xyXG4gIHN0YXRpYyBtYXgobWF4OiBudW1iZXIpOiBWYWxpZGF0b3JGbiB7XHJcbiAgICBpZiAoIWhhc1ZhbHVlKG1heCkpIHsgcmV0dXJuIEpzb25WYWxpZGF0b3JzLm51bGxWYWxpZGF0b3I7IH1cclxuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sKTogVmFsaWRhdGlvbkVycm9yc3xudWxsID0+IHtcclxuICAgICAgLy8gZG9uJ3QgdmFsaWRhdGUgZW1wdHkgdmFsdWVzIHRvIGFsbG93IG9wdGlvbmFsIGNvbnRyb2xzXHJcbiAgICAgIGlmIChpc0VtcHR5KGNvbnRyb2wudmFsdWUpIHx8IGlzRW1wdHkobWF4KSkgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgICBjb25zdCB2YWx1ZSA9IHBhcnNlRmxvYXQoY29udHJvbC52YWx1ZSk7XHJcbiAgICAgIGNvbnN0IGFjdHVhbCA9IGNvbnRyb2wudmFsdWU7XHJcbiAgICAgIC8vIENvbnRyb2xzIHdpdGggTmFOIHZhbHVlcyBhZnRlciBwYXJzaW5nIHNob3VsZCBiZSB0cmVhdGVkIGFzIG5vdCBoYXZpbmcgYVxyXG4gICAgICAvLyBtYXhpbXVtLCBwZXIgdGhlIEhUTUwgZm9ybXMgc3BlYzogaHR0cHM6Ly93d3cudzMub3JnL1RSL2h0bWw1L2Zvcm1zLmh0bWwjYXR0ci1pbnB1dC1tYXhcclxuICAgICAgcmV0dXJuIGlzTmFOKHZhbHVlKSB8fCB2YWx1ZSA8PSBtYXggPyBudWxsIDogeyAnbWF4JzogeyBtYXgsIGFjdHVhbCB9IH07XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVmFsaWRhdG9yIHRoYXQgcmVxdWlyZXMgY29udHJvbCB2YWx1ZSB0byBiZSB0cnVlLlxyXG4gICAqL1xyXG4gIHN0YXRpYyByZXF1aXJlZFRydWUoY29udHJvbDogQWJzdHJhY3RDb250cm9sKTogVmFsaWRhdGlvbkVycm9yc3xudWxsIHtcclxuICAgIGlmICghY29udHJvbCkgeyByZXR1cm4gSnNvblZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjsgfVxyXG4gICAgcmV0dXJuIGNvbnRyb2wudmFsdWUgPT09IHRydWUgPyBudWxsIDogeyAncmVxdWlyZWQnOiB0cnVlIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBWYWxpZGF0b3IgdGhhdCBwZXJmb3JtcyBlbWFpbCB2YWxpZGF0aW9uLlxyXG4gICAqL1xyXG4gIHN0YXRpYyBlbWFpbChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiBWYWxpZGF0aW9uRXJyb3JzfG51bGwge1xyXG4gICAgaWYgKCFjb250cm9sKSB7IHJldHVybiBKc29uVmFsaWRhdG9ycy5udWxsVmFsaWRhdG9yOyB9XHJcbiAgICBjb25zdCBFTUFJTF9SRUdFWFAgPVxyXG4gICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bWF4LWxpbmUtbGVuZ3RoXHJcbiAgICAgIC9eKD89LnsxLDI1NH0kKSg/PS57MSw2NH1AKVstISMkJSYnKisvMC05PT9BLVpeX2BhLXp7fH1+XSsoXFwuWy0hIyQlJicqKy8wLTk9P0EtWl5fYGEtent8fX5dKykqQFtBLVphLXowLTldKFtBLVphLXowLTktXXswLDYxfVtBLVphLXowLTldKT8oXFwuW0EtWmEtejAtOV0oW0EtWmEtejAtOS1dezAsNjF9W0EtWmEtejAtOV0pPykqJC87XHJcbiAgICByZXR1cm4gRU1BSUxfUkVHRVhQLnRlc3QoY29udHJvbC52YWx1ZSkgPyBudWxsIDogeyAnZW1haWwnOiB0cnVlIH07XHJcbiAgfVxyXG59XHJcbiJdfQ==
|