@bnsights/bbsf-controls 1.0.180 → 1.0.181

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.
@@ -4,7 +4,6 @@ import { FileUploader } from 'ng2-file-upload';
4
4
  import { FileUploadModel } from '../../Shared/Models/FileUploadModel';
5
5
  import { MultipleFileUploadModel } from '../../Shared/Models/MultipleFileUploadModel';
6
6
  import { HttpEventType } from '@angular/common/http';
7
- import { Subscription } from 'rxjs';
8
7
  import * as i0 from "@angular/core";
9
8
  import * as i1 from "@angular/forms";
10
9
  import * as i2 from "../../Shared/services/ControlUtility";
@@ -13,1070 +12,565 @@ import * as i4 from "../../Shared/services/GlobalSettings.service";
13
12
  import * as i5 from "../../Shared/services/file-upload.service";
14
13
  import * as i6 from "@angular/common";
15
14
  import * as i7 from "ng2-file-upload";
15
+ import * as i8 from "ngx-intl-tel-input";
16
16
  export class FileUploadComponent {
17
- static { this.controlContainerStatic = null; }
18
- constructor(controlContainer, multipleFileUploadControlHost, controlUtility, utilityService, controlValidationService, globalSettings, fileUploadService) {
17
+ static { this.controlContainerstatic = null; }
18
+ constructor(controlContainer, MultipleFileUplaodControlHost, controlUtility, UtilityService, controlValidationService, globalSettings, fileUploadService) {
19
19
  this.controlContainer = controlContainer;
20
- this.multipleFileUploadControlHost = multipleFileUploadControlHost;
20
+ this.MultipleFileUplaodControlHost = MultipleFileUplaodControlHost;
21
21
  this.controlUtility = controlUtility;
22
- this.utilityService = utilityService;
22
+ this.UtilityService = UtilityService;
23
23
  this.controlValidationService = controlValidationService;
24
24
  this.globalSettings = globalSettings;
25
25
  this.fileUploadService = fileUploadService;
26
- this.BYTES_TO_MB = 1024 * 1024;
27
- this.PROGRESS_COMPLETE = 100;
28
- this.PROGRESS_NEAR_COMPLETE = 95;
29
- this.ERROR_DISPLAY_DURATION = 5000;
30
- this.MAX_MEMORY_USAGE = 100 * 1024 * 1024; // 100MB limit
31
- this.currentMemoryUsage = 0;
32
- this.isSubmitted = false;
33
26
  this.OnChange = new EventEmitter();
34
27
  this.isUploadComplete = new EventEmitter();
35
28
  this.validationMessage = '';
36
29
  this.validationCountMessage = '';
37
- this.hasAnotherDropZoneOver = false;
38
30
  this.acceptedType = '';
39
31
  this.acceptedTypeArray = [];
40
32
  this.toolTipTypeArray = [];
41
33
  this.markAllAsTouched = false;
42
34
  this.validationRules = [];
43
- this.validationRulesAsync = [];
44
- this.file = null;
35
+ this.validationRulesasync = [];
45
36
  this.deletedFiles = [];
46
- this.subscriptions = new Subscription();
47
37
  this.resetError = () => {
48
38
  this.controlValidationService.removeGlobalError();
49
39
  };
40
+ //External Method
50
41
  this.removeRequiredValidation = () => {
51
42
  this.controlUtility.removeRequiredValidation(this.fileUploadFormControl, this.validationRules, this.options);
52
43
  };
44
+ //External Method
53
45
  this.addRequiredValidation = () => {
54
46
  this.controlUtility.addRequiredValidation(this.fileUploadFormControl, this.validationRules, this.options);
55
47
  };
48
+ //External Method
56
49
  this.removeCustomValidation = (customValidation) => {
57
50
  this.controlUtility.removeCustomValidation(this.fileUploadFormControl, this.validationRules, customValidation);
58
51
  };
52
+ //External Method
59
53
  this.addCustomValidation = (customValidation) => {
60
54
  this.controlUtility.addCustomValidation(this.fileUploadFormControl, this.validationRules, customValidation);
61
55
  };
56
+ //External Method
62
57
  this.isValid = () => {
63
58
  this.controlUtility.isValid(this.fileUploadFormControl);
64
- return this.fileUploadFormControl.valid;
65
59
  };
66
- FileUploadComponent.controlContainerStatic = this.controlContainer;
67
- this.initializeUploader();
68
- }
69
- initializeUploader() {
60
+ FileUploadComponent.controlContainerstatic = this.controlContainer;
70
61
  this.uploader = new FileUploader({
71
- disableMultipart: false
62
+ disableMultipart: false // 'DisableMultipart' must be 'true' for formatDataFunction to be called.
72
63
  });
64
+ this.hasAnotherDropZoneOver = false;
73
65
  }
74
66
  ngOnInit() {
75
- this.initializeModels();
76
- this.setViewType();
77
- this.processInitialValue();
78
- this.setupLabels();
79
- this.setupFileTypeValidation();
80
- this.setupFormControl();
81
- this.setupSubscriptions();
82
- }
83
- initializeModels() {
84
67
  this.fileUploadModel = new FileUploadModel();
85
68
  this.multipleFileUploadModel = new MultipleFileUploadModel();
86
- }
87
- setViewType() {
88
- if (!this.options.viewType) {
69
+ if (!this.options.viewType)
89
70
  this.options.viewType = this.globalSettings.viewType;
90
- }
91
- }
92
- processInitialValue() {
93
71
  if (this.options.value == null) {
94
- return;
95
- }
96
- if (this.options.isMultipleFile) {
97
- this.processMultipleFileValue();
98
- }
99
- else {
100
- this.processSingleFileValue();
101
- }
102
- this.uploader.queue.forEach((element) => {
103
- element.progress = this.PROGRESS_COMPLETE;
104
- });
105
- }
106
- processMultipleFileValue() {
107
- const files = [];
108
- this.multipleFileUploadModel.existingFiles = this.options.value.existingFiles;
109
- this.multipleFileUploadModel.uploadedFiles = [];
110
- for (const element of this.options.value.existingFiles) {
111
- const fileLikeObject = this.createFileLikeObject(element);
112
- files.push(fileLikeObject);
113
- }
114
- this.uploader.addToQueue(files);
115
- }
116
- processSingleFileValue() {
117
- const element = this.options.value.file ?? this.options.value;
118
- const fileLikeObject = this.createFileLikeObject(element);
119
- this.file = element;
120
- this.uploader.addToQueue([fileLikeObject]);
121
- if (!this.options.value.file) {
122
- this.fileUploadModel = new FileUploadModel();
123
- this.fileUploadModel.file = this.options.value;
72
+ if (this.options.isMultipleFile == true) {
73
+ //this.options.Value=this.multipleFileUploadModel
74
+ }
75
+ else {
76
+ // this.options.Value=this.fileUploadModel
77
+ }
124
78
  }
125
79
  else {
126
- this.fileUploadModel = this.options.value;
127
- }
128
- this.options.value = this.fileUploadModel;
129
- }
130
- createFileLikeObject(element) {
131
- const bytes = new Uint8Array(element.bytes);
132
- const base64 = btoa(String.fromCharCode(...bytes));
133
- return {
134
- name: element.nameWithExtension || element.fileName,
135
- type: element.mimeType || element.fileType,
136
- rawFile: base64,
137
- size: element.fileSizeInMB ? element.fileSizeInMB * this.BYTES_TO_MB : 0,
138
- lastModifiedDate: new Date(),
139
- url: element.fullFileURL
140
- };
141
- }
142
- setupLabels() {
143
- if (this.options.labelKey) {
144
- this.options.labelValue = this.utilityService.getResourceValue(this.options.labelKey);
145
- }
146
- }
147
- setupFileTypeValidation() {
148
- if (!this.options.fileUploadAcceptsTypes?.length) {
149
- console.warn('FileUpload: No file types specified in fileUploadAcceptsTypes');
150
- return;
151
- }
152
- try {
153
- this.processAcceptedTypes();
154
- this.buildValidationMessage();
155
- // Log the processed types for debugging
156
- console.log('FileUpload: Processed file types:', {
157
- original: this.options.fileUploadAcceptsTypes,
158
- processed: this.acceptedTypeArray,
159
- acceptAttribute: this.acceptedType,
160
- displayTypes: this.toolTipTypeArray
161
- });
162
- }
163
- catch (error) {
164
- console.error('FileUpload: Error processing file types:', error);
165
- // Fallback to accepting all files if processing fails
166
- this.acceptedType = '';
167
- this.acceptedTypeArray = [];
168
- this.toolTipTypeArray = [];
169
- }
170
- }
171
- processAcceptedTypes() {
172
- // Process each file type and extract individual MIME types
173
- const allMimeTypes = [];
174
- for (const fileType of this.options.fileUploadAcceptsTypes) {
175
- if (fileType.includes(',')) {
176
- // Handle types like ImageTypes that contain multiple MIME types
177
- const mimeTypes = fileType.split(',').map(type => type.trim());
178
- allMimeTypes.push(...mimeTypes);
80
+ if (this.options.isMultipleFile == true) {
81
+ let files = [];
82
+ this.multipleFileUploadModel.existingFiles = this.options.value.existingFiles;
83
+ this.multipleFileUploadModel.uploadedFiles = [];
84
+ for (let index = 0; index < this.options.value.existingFiles.length; index++) {
85
+ const element = this.options.value.existingFiles[index];
86
+ var bytes = new Uint8Array(element.bytes);
87
+ var base64 = btoa(String.fromCharCode(null, bytes));
88
+ this.fileLikeObject = {
89
+ name: element.nameWithExtension,
90
+ type: element.mimeType,
91
+ rawFile: base64
92
+ };
93
+ // let blob: any;
94
+ // blob = new Blob(['']) as any;
95
+ // blob.name = element.FileName;
96
+ // blob.lastModifiedDate = null;
97
+ // blob.webkitRelativePath = '';
98
+ let file = this.fileLikeObject;
99
+ file.url = element.fileURL;
100
+ files.push(file);
101
+ }
102
+ this.uploader.addToQueue(files);
103
+ console.log(this.uploader.queue);
179
104
  }
180
105
  else {
181
- // Single MIME type
182
- allMimeTypes.push(fileType);
106
+ const element = this.options.value.file ?? this.options.value;
107
+ var bytes = new Uint8Array(element.bytes);
108
+ var base64 = btoa(String.fromCharCode(null, bytes));
109
+ this.fileLikeObject = {
110
+ name: element.nameWithExtension,
111
+ type: element.mimeType,
112
+ rawFile: base64
113
+ };
114
+ this.file = element;
115
+ let file = this.fileLikeObject;
116
+ file.url = element.fileURL;
117
+ this.uploader.addToQueue([file]);
118
+ if (!this.options.value.file) {
119
+ this.fileUploadModel = new FileUploadModel();
120
+ this.fileUploadModel.file = this.options.value;
121
+ }
122
+ else
123
+ this.fileUploadModel = this.options.value;
124
+ this.options.value = this.fileUploadModel;
183
125
  }
126
+ this.uploader.queue.forEach((element) => {
127
+ element.progress = 100;
128
+ });
184
129
  }
185
- // Filter out empty strings and normalize MIME types
186
- const normalizedMimeTypes = allMimeTypes
187
- .filter(type => type.trim())
188
- .map(type => type.trim().toLowerCase());
189
- // Create the accept attribute string for HTML input
190
- this.acceptedType = normalizedMimeTypes.join(',');
191
- // Store the processed array for validation (keep original case for display)
192
- this.acceptedTypeArray = allMimeTypes.filter(type => type.trim());
193
- const mimeTypeMap = this.getMimeTypeMap();
194
- for (const type of this.acceptedTypeArray) {
195
- const displayType = mimeTypeMap[type];
196
- if (displayType && !this.toolTipTypeArray.includes(displayType)) {
197
- this.toolTipTypeArray.push(displayType);
130
+ if (this.options.labelKey != null && this.options.labelKey != '')
131
+ this.options.labelValue = this.UtilityService.getResourceValue(this.options.labelKey);
132
+ if (this.options.fileUploadAcceptsTypes != null &&
133
+ this.options.fileUploadAcceptsTypes.length > 0) {
134
+ for (let index = 0; index < this.options.fileUploadAcceptsTypes.length; index++) {
135
+ const Type = this.options.fileUploadAcceptsTypes[index];
136
+ this.acceptedType = this.acceptedType + Type + ',';
198
137
  }
199
- }
200
- }
201
- getMimeTypeMap() {
202
- return {
203
- 'application/pdf': 'PDF',
204
- 'application/msword': 'Word',
205
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'Word',
206
- 'application/vnd.ms-excel': 'Excel',
207
- 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'Excel',
208
- 'application/vnd.ms-powerpoint': 'PowerPoint',
209
- 'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'PowerPoint',
210
- 'image/png': 'PNG',
211
- 'image/bmp': 'BMP',
212
- 'image/jpeg': 'JPEG',
213
- 'image/svg+xml': 'SVG',
214
- 'application/zip': 'ZIP',
215
- 'application/x-rar-compressed': 'RAR',
216
- 'video/webm': 'WebM',
217
- 'video/ogg': 'OGG',
218
- 'video/mp4': 'MP4',
219
- 'video/quicktime': 'MOV',
220
- 'video/x-msvideo': 'AVI',
221
- 'video/x-ms-wmv': 'WMV',
222
- 'video/avi': 'AVI',
223
- 'video/mpeg': 'MPEG',
224
- 'video/x-flv': 'FLV',
225
- 'audio/mpeg': 'MP3',
226
- 'text/plain': 'Txt',
227
- 'text/xml': 'XML',
228
- 'application/json': 'JSON',
229
- 'application/octet-stream': 'Binary',
230
- 'application/BN': 'License'
231
- };
232
- }
233
- buildValidationMessage() {
234
- const messages = [];
235
- if (this.toolTipTypeArray.length) {
236
- messages.push(`${this.utilityService.getResourceValue('Extensions')} (${this.toolTipTypeArray.join(', ')})`);
138
+ this.acceptedTypeArray = this.acceptedType.split(',');
139
+ this.acceptedTypeArray = this.acceptedTypeArray.filter((value) => value != '');
140
+ for (let index = 0; index < this.acceptedTypeArray.length; index++) {
141
+ const element = this.acceptedTypeArray[index];
142
+ for (let index = 0; index < this.acceptedTypeArray.length; index++) {
143
+ const element = this.acceptedTypeArray[index];
144
+ switch (element) {
145
+ case 'application/pdf':
146
+ if (!this.toolTipTypeArray.includes('PDF'))
147
+ this.toolTipTypeArray.push('PDF');
148
+ break;
149
+ case 'application/msword':
150
+ if (!this.toolTipTypeArray.includes('Word'))
151
+ this.toolTipTypeArray.push('Word');
152
+ break;
153
+ case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
154
+ if (!this.toolTipTypeArray.includes('Word'))
155
+ this.toolTipTypeArray.push('Word');
156
+ break;
157
+ case 'application/vnd.ms-excel':
158
+ if (!this.toolTipTypeArray.includes('Excel'))
159
+ this.toolTipTypeArray.push('Excel');
160
+ break;
161
+ case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
162
+ if (!this.toolTipTypeArray.includes('Excel'))
163
+ this.toolTipTypeArray.push('Excel');
164
+ break;
165
+ case 'application/vnd.ms-powerpoint':
166
+ if (!this.toolTipTypeArray.includes('PowerPoint'))
167
+ this.toolTipTypeArray.push('PowerPoint');
168
+ break;
169
+ case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
170
+ if (!this.toolTipTypeArray.includes('PowerPoint'))
171
+ this.toolTipTypeArray.push('PowerPoint');
172
+ break;
173
+ case 'image/png':
174
+ if (!this.toolTipTypeArray.includes('PNG'))
175
+ this.toolTipTypeArray.push('PNG');
176
+ break;
177
+ case 'image/bmp':
178
+ if (!this.toolTipTypeArray.includes('BMP'))
179
+ this.toolTipTypeArray.push('BMP');
180
+ break;
181
+ case 'image/jpeg':
182
+ if (!this.toolTipTypeArray.includes('JPEG'))
183
+ this.toolTipTypeArray.push('JPEG');
184
+ break;
185
+ case 'application/zip':
186
+ if (!this.toolTipTypeArray.includes('ZIP'))
187
+ this.toolTipTypeArray.push('ZIP');
188
+ break;
189
+ case 'application/x-rar-compressed':
190
+ if (!this.toolTipTypeArray.includes('RAR'))
191
+ this.toolTipTypeArray.push('RAR');
192
+ break;
193
+ case 'video/mp4':
194
+ if (!this.toolTipTypeArray.includes('MP4'))
195
+ this.toolTipTypeArray.push('MP4');
196
+ break;
197
+ case 'video/avi':
198
+ if (!this.toolTipTypeArray.includes('AVI'))
199
+ this.toolTipTypeArray.push('AVI');
200
+ break;
201
+ case 'video/quicktime':
202
+ if (!this.toolTipTypeArray.includes('MOV'))
203
+ this.toolTipTypeArray.push('MOV');
204
+ break;
205
+ case 'video/mpeg':
206
+ if (!this.toolTipTypeArray.includes('MPEG'))
207
+ this.toolTipTypeArray.push('MPEG');
208
+ break;
209
+ case 'audio/mpeg':
210
+ if (!this.toolTipTypeArray.includes('MP3'))
211
+ this.toolTipTypeArray.push('MP3');
212
+ break;
213
+ case 'video/x-flv':
214
+ if (!this.toolTipTypeArray.includes('FLV'))
215
+ this.toolTipTypeArray.push('FLV');
216
+ break;
217
+ case 'video/x-ms-wmv':
218
+ if (!this.toolTipTypeArray.includes('WMV'))
219
+ this.toolTipTypeArray.push('WMV');
220
+ break;
221
+ case 'image/svg+xml':
222
+ if (!this.toolTipTypeArray.includes('SVG'))
223
+ this.toolTipTypeArray.push('SVG');
224
+ break;
225
+ case 'text/plain':
226
+ if (!this.toolTipTypeArray.includes('Txt'))
227
+ this.toolTipTypeArray.push('Txt');
228
+ break;
229
+ case 'application/BN':
230
+ if (!this.toolTipTypeArray.includes('License'))
231
+ this.toolTipTypeArray.push('License');
232
+ break;
233
+ default:
234
+ break;
235
+ }
236
+ }
237
+ }
238
+ this.validationMessage =
239
+ this.validationMessage +
240
+ `${this.UtilityService.getResourceValue('Extensions')} (${this.toolTipTypeArray}) `;
237
241
  }
238
242
  if (this.options.fileMaxSizeInMB > 0) {
239
- messages.push(`${this.utilityService.getResourceValue('FileMaxSizeInMB')}${this.options.fileMaxSizeInMB}`);
243
+ this.validationMessage =
244
+ this.validationMessage +
245
+ `<br /> ${this.UtilityService.getResourceValue('FileMaxSizeInMB') + this.options.fileMaxSizeInMB} `;
240
246
  }
241
247
  if (this.options.minNoOfFiles > 0) {
242
- messages.push(`${this.utilityService.getResourceValue('MinFileCountValidationKey')}${this.options.minNoOfFiles}`);
248
+ this.validationMessage =
249
+ this.validationMessage +
250
+ `<br /> ${this.UtilityService.getResourceValue('MinFileCountValidationKey') + this.options.minNoOfFiles}`;
243
251
  }
244
252
  if (this.options.maxNoOfFiles > 0) {
245
- messages.push(`${this.utilityService.getResourceValue('MaxFileCountValidationKey')}${this.options.maxNoOfFiles}`);
253
+ this.validationMessage =
254
+ this.validationMessage +
255
+ `<br /> ${this.UtilityService.getResourceValue('MaxFileCountValidationKey') + this.options.maxNoOfFiles}`;
256
+ }
257
+ if (this.options.fileUploadAcceptsTypes != null &&
258
+ this.options.fileUploadAcceptsTypes.length > 0) {
246
259
  }
247
- this.validationMessage = messages.join(' <br/> ');
248
- }
249
- setupFormControl() {
250
260
  this.group.addControl(this.options.name, new FormControl(''));
251
- this.fileUploadFormControl = this.group.controls[this.options.name];
252
- this.setupValidators();
253
- this.setupCountMessage();
254
- this.applyValidatorsAndState();
255
- this.fileUploadFormControl.setValue(this.options.value, { emitEvent: false });
256
- }
257
- setupValidators() {
258
- if (this.options.customValidation?.length) {
259
- for (const validation of this.options.customValidation) {
260
- this.validationRules.push(validation.functionBody);
261
+ this.fileUploadFormControl = this.group.controls[this.options.name]; // new FormControl('',validationRules);
262
+ if (this.options.customValidation.length > 0) {
263
+ let Validations = this.options.customValidation;
264
+ for (let index = 0; index < Validations.length; index++) {
265
+ const Validation = Validations[index];
266
+ this.validationRules.push(Validation.functionBody);
261
267
  }
262
268
  }
269
+ if (this.options.isMultipleFile && this.options.maxNoOfFiles > 0) {
270
+ this.validationCountMessage = `${this.UtilityService.getResourceValue('MaxFilesCount')} : ${this.options.maxNoOfFiles}`;
271
+ }
263
272
  if (this.options.isRequired) {
264
273
  this.validationRules.push(Validators.required);
265
274
  }
266
- }
267
- setupCountMessage() {
268
- if (this.options.isMultipleFile && this.options.maxNoOfFiles > 0) {
269
- this.validationCountMessage = `${this.utilityService.getResourceValue('MaxFilesCount')} : ${this.options.maxNoOfFiles}`;
270
- }
271
- }
272
- applyValidatorsAndState() {
273
275
  this.fileUploadFormControl.setValidators(this.validationRules);
274
- if (this.validationRulesAsync.length > 0) {
275
- this.fileUploadFormControl.setAsyncValidators(this.validationRulesAsync);
276
- }
276
+ this.fileUploadFormControl.setAsyncValidators(this.validationRulesasync);
277
277
  if (this.options.isDisabled) {
278
278
  this.fileUploadFormControl.disable();
279
279
  }
280
- }
281
- setupSubscriptions() {
282
- this.multipleFileUploadControlHost.ngSubmit.subscribe(() => {
280
+ this.MultipleFileUplaodControlHost.ngSubmit.subscribe((value) => {
283
281
  this.group.markAllAsTouched();
284
282
  this.markAllAsTouched = true;
285
283
  });
284
+ this.fileUploadFormControl.setValue(this.options.value);
286
285
  }
287
286
  ngAfterViewInit() {
288
- this.applyAttributes();
289
- }
290
- applyAttributes() {
291
- if (!this.options.attributeList?.length) {
292
- return;
293
- }
294
- const element = document.getElementById(this.options.name);
295
- if (element) {
296
- for (const attribute of this.options.attributeList) {
297
- element.setAttribute(attribute.key, attribute.value);
287
+ if (this.options.attributeList != null) {
288
+ var element = document.getElementById(this.options.name);
289
+ for (let index = 0; index < this.options.attributeList.length; index++) {
290
+ element.setAttribute(this.options.attributeList[index].key, this.options.attributeList[index].value);
298
291
  }
299
292
  }
300
293
  }
301
294
  showGlobalError() {
302
295
  this.controlUtility.showGlobalError();
303
296
  }
304
- getErrorValidation(errorList) {
297
+ getErrorValidation(ErrorList) {
305
298
  if (this.markAllAsTouched && this.group.invalid) {
306
299
  this.showGlobalError();
307
300
  this.markAllAsTouched = false;
308
301
  }
309
- if (errorList && errorList.length > 0) {
310
- for (const error of errorList) {
311
- if (error.key === 'InvalidFiles') {
312
- return error.value;
313
- }
314
- }
315
- }
316
- return this.controlUtility.getErrorValidationMassage(errorList, this.group, this.options);
302
+ return this.controlUtility.getErrorValidationMassage(ErrorList, this.group, this.options);
317
303
  }
318
304
  fileOverAnother(event) {
319
- this.hasAnotherDropZoneOver = !!event;
305
+ this.hasAnotherDropZoneOver = event;
320
306
  }
321
307
  isHideInput() {
322
308
  if (this.options.isMultipleFile) {
323
- return this.options.maxNoOfFiles > 0 &&
324
- this.options.maxNoOfFiles === this.uploader.queue.length;
325
- }
326
- return this.uploader.queue.length > 0;
327
- }
328
- onFileChange() {
329
- this.validateFileConstraints();
330
- const fileProcessingResult = this.processNewlyAddedFiles();
331
- this.handleFileValidationResults(fileProcessingResult);
332
- this.processValidFilesForUpload();
333
- }
334
- processNewlyAddedFiles() {
335
- const addedQueue = this.getNewlyAddedFiles();
336
- const validationResult = this.validateFilesInQueue(addedQueue);
337
- return {
338
- validFiles: addedQueue.filter(file => !validationResult.invalidFiles.includes(file)),
339
- invalidFiles: validationResult.invalidFiles,
340
- errors: validationResult.errors
341
- };
342
- }
343
- getNewlyAddedFiles() {
344
- return this.uploader.queue.filter((obj) => obj['some']?.lastModified != null);
345
- }
346
- validateFilesInQueue(fileQueue) {
347
- const validationErrors = [];
348
- const invalidFiles = [];
349
- const processedDuplicateNames = new Set();
350
- for (const element of fileQueue) {
351
- const file = element.file;
352
- if (!file)
353
- continue;
354
- const fileValidation = this.validateSingleFile(file, element, processedDuplicateNames);
355
- if (!fileValidation.isValid) {
356
- invalidFiles.push(element);
357
- validationErrors.push(...fileValidation.errors);
358
- }
359
- }
360
- return {
361
- isValid: invalidFiles.length === 0,
362
- errors: validationErrors,
363
- invalidFiles
364
- };
365
- }
366
- validateSingleFile(file, element, processedDuplicateNames) {
367
- const errors = [];
368
- const sizeValid = this.validateIndividualFileSize(file);
369
- const typeValid = this.validateIndividualFileType(file);
370
- const nameValid = this.validateDuplicateFileName(file, element);
371
- if (!sizeValid) {
372
- errors.push(this.createFileSizeErrorMessage(file.name));
373
- }
374
- if (!typeValid) {
375
- errors.push(this.createFileTypeErrorMessage(file.name));
376
- }
377
- if (!nameValid) {
378
- const duplicateError = this.createDuplicateFileErrorMessage(file.name, processedDuplicateNames);
379
- if (duplicateError) {
380
- errors.push(duplicateError);
381
- }
382
- }
383
- return {
384
- isValid: sizeValid && typeValid && nameValid,
385
- errors,
386
- invalidFiles: []
387
- };
388
- }
389
- createFileSizeErrorMessage(fileName) {
390
- return this.utilityService.getResourceValue('FileExceedsMaxSize')
391
- .replace('{fileName}', fileName)
392
- .replace('{maxSize}', this.options.fileMaxSizeInMB.toString());
393
- }
394
- createFileTypeErrorMessage(fileName) {
395
- return this.utilityService.getResourceValue('FileTypeNotAccepted')
396
- .replace('{fileName}', fileName);
397
- }
398
- createDuplicateFileErrorMessage(fileName, processedDuplicateNames) {
399
- const fileNameLower = fileName.toLowerCase();
400
- if (processedDuplicateNames.has(fileNameLower)) {
401
- return null;
402
- }
403
- processedDuplicateNames.add(fileNameLower);
404
- let duplicateErrorMsg = this.utilityService.getResourceValue('DuplicateFileName');
405
- if (!duplicateErrorMsg || duplicateErrorMsg === 'DuplicateFileName') {
406
- duplicateErrorMsg = `File '{fileName}' already exists. Please choose a different file or rename it.`;
407
- }
408
- return duplicateErrorMsg.replace('{fileName}', fileName);
409
- }
410
- handleFileValidationResults(result) {
411
- if (result.invalidFiles.length > 0) {
412
- this.removeInvalidFiles(result.invalidFiles);
413
- }
414
- if (result.errors.length > 0) {
415
- this.showValidationErrors(result.errors);
416
- }
417
- }
418
- processValidFilesForUpload() {
419
- const filesArray = [];
420
- const validQueue = this.getNewlyAddedFiles();
421
- for (const element of validQueue) {
422
- const file = element.file;
423
- if (!file)
424
- continue;
425
- if (this.shouldUseAsyncUpload(element)) {
426
- this.handleAsyncFileUpload(element, filesArray);
427
- }
428
- else {
429
- this.handleSyncFileUpload(file, filesArray);
430
- }
431
- }
432
- }
433
- shouldUseAsyncUpload(element) {
434
- return this.options.isUploadFileAsync && !element._file['iD_GUID'];
435
- }
436
- validateFileConstraints() {
437
- if (this.options.isMultipleFile) {
438
- if (!this.validateMinFileCount() || !this.validateMaxFileCount() || !this.validateTotalFileSize()) {
439
- return false;
309
+ if (this.options.maxNoOfFiles != null &&
310
+ this.options.maxNoOfFiles > 0 &&
311
+ this.options.maxNoOfFiles == this.uploader.queue.length) {
312
+ return true;
440
313
  }
441
314
  }
442
- return true;
443
- }
444
- validateMinFileCount() {
445
- if (this.options.minNoOfFiles > 0 && this.options.minNoOfFiles > this.uploader.queue.length) {
446
- const minFileMsg = this.utilityService.getResourceValue('MinimumFilesRequired')
447
- .replace('{count}', this.options.minNoOfFiles.toString());
448
- this.showFileCountError('MinFileCountValidationKey', minFileMsg);
449
- return false;
450
- }
451
- return true;
452
- }
453
- validateMaxFileCount() {
454
- if (this.options.maxNoOfFiles > 0 && this.options.maxNoOfFiles < this.uploader.queue.length) {
455
- const maxFileMsg = this.utilityService.getResourceValue('MaximumFilesExceeded') ||
456
- `Maximum {maxCount} files allowed. You have selected {currentCount} files.`;
457
- const finalMsg = maxFileMsg
458
- .replace('{maxCount}', this.options.maxNoOfFiles.toString())
459
- .replace('{currentCount}', this.uploader.queue.length.toString());
460
- this.showFileCountError('MaxFileCountValidationKey', finalMsg);
461
- return false;
462
- }
463
- return true;
464
- }
465
- showFileCountError(errorKey, message) {
466
- const currentErrors = this.fileUploadFormControl.errors || {};
467
- currentErrors[errorKey] = message;
468
- this.fileUploadFormControl.setErrors(currentErrors);
469
- this.fileUploadFormControl.markAsTouched();
470
- }
471
- clearFileCountError(errorKey) {
472
- const currentErrors = this.fileUploadFormControl.errors;
473
- if (currentErrors && currentErrors[errorKey]) {
474
- delete currentErrors[errorKey];
475
- if (Object.keys(currentErrors).length === 0) {
476
- this.fileUploadFormControl.setErrors(null);
477
- }
478
- else {
479
- this.fileUploadFormControl.setErrors(currentErrors);
480
- }
481
- }
482
- }
483
- validateTotalFileSize() {
484
- if (this.options.maxSizeForAllFilesInMB > 0) {
485
- const totalSize = this.uploader.queue.reduce((sum, element) => sum + element.file.size, 0);
486
- const maxSizeBytes = this.options.maxSizeForAllFilesInMB * this.BYTES_TO_MB;
487
- if (totalSize > maxSizeBytes) {
488
- this.showTotalSizeError();
489
- return false;
490
- }
491
- }
492
- return true;
493
- }
494
- showTotalSizeError() {
495
- const totalSizeMsg = this.utilityService.getResourceValue('TotalFileSizeExceeded')
496
- .replace('{maxSize}', this.options.maxSizeForAllFilesInMB.toString());
497
- const currentErrors = this.fileUploadFormControl.errors || {};
498
- currentErrors['MaxSizeForAllFilesInMB'] = totalSizeMsg;
499
- this.fileUploadFormControl.setErrors(currentErrors);
500
- this.fileUploadFormControl.markAsTouched();
501
- }
502
- validateFileSize(file) {
503
- const maxFileSize = this.options.fileMaxSizeInMB * this.BYTES_TO_MB;
504
- if (file.size > maxFileSize) {
505
- this.setFormControlError('FileMaxSizeInMB', `${this.options.fileMaxSizeInMB}MB`);
506
- return false;
507
- }
508
- return true;
509
- }
510
- validateFileType(file) {
511
- if (this.options.fileUploadAcceptsTypes?.length) {
512
- const fileType = file.type;
513
- const isAccepted = this.acceptedTypeArray.some(type => type.toLowerCase() === fileType.toLowerCase());
514
- if (!isAccepted) {
515
- this.setFormControlError('ToolTipTypeError', this.toolTipTypeArray);
516
- return false;
315
+ else {
316
+ if (this.uploader.queue.length > 0) {
317
+ return true;
517
318
  }
518
319
  }
519
- return true;
520
- }
521
- validateIndividualFileSize(file) {
522
- const maxFileSize = this.options.fileMaxSizeInMB * this.BYTES_TO_MB;
523
- return file.size <= maxFileSize;
524
- }
525
- validateIndividualFileType(file) {
526
- if (!this.options.fileUploadAcceptsTypes?.length) {
527
- return true;
528
- }
529
- const fileType = file.type?.toLowerCase();
530
- if (!fileType) {
531
- return false;
532
- }
533
- return this.acceptedTypeArray.some(type => type.toLowerCase() === fileType);
320
+ return false;
534
321
  }
535
- validateDuplicateFileName(file, currentElement) {
536
- if (!file?.name) {
537
- return true;
538
- }
539
- const currentFileName = file.name.toLowerCase();
540
- const existingFiles = this.uploader.queue.filter(item => item !== currentElement);
541
- const duplicateExists = existingFiles.some(item => {
542
- const existingFileName = item.file?.name || item._file?.name;
543
- return existingFileName && existingFileName.toLowerCase() === currentFileName;
544
- });
545
- if (duplicateExists) {
546
- return false;
547
- }
548
- if (this.options.value) {
549
- const uploadedFiles = Array.isArray(this.options.value) ? this.options.value : [this.options.value];
550
- const duplicateInUploaded = uploadedFiles.some(uploadedFile => {
551
- const uploadedFileName = uploadedFile?.fileName || uploadedFile?.name;
552
- return uploadedFileName && uploadedFileName.toLowerCase() === currentFileName;
322
+ onFileChange() {
323
+ let FilesArray = [];
324
+ if (this.options.isMultipleFile &&
325
+ this.options.minNoOfFiles != null &&
326
+ this.options.minNoOfFiles > 0 &&
327
+ this.options.minNoOfFiles > this.uploader.queue.length) {
328
+ const formControl = this.fileUploadFormControl;
329
+ formControl.setErrors({
330
+ MinFileCountValidationKey: this.options.minNoOfFiles
553
331
  });
554
- return !duplicateInUploaded;
332
+ formControl.markAsTouched();
333
+ this.uploader.queue = [];
334
+ return;
555
335
  }
556
- return true;
557
- }
558
- removeInvalidFiles(invalidFiles) {
559
- invalidFiles.forEach(invalidFile => {
560
- const index = this.uploader.queue.indexOf(invalidFile);
561
- if (index > -1) {
562
- this.uploader.queue.splice(index, 1);
563
- }
564
- });
565
- }
566
- showValidationErrors(errors) {
567
- if (errors.length === 0)
336
+ if (this.options.isMultipleFile &&
337
+ this.options.maxNoOfFiles != null &&
338
+ this.options.maxNoOfFiles > 0 &&
339
+ this.options.maxNoOfFiles < this.uploader.queue.length) {
340
+ const formControl = this.fileUploadFormControl;
341
+ formControl.setErrors({
342
+ MaxFileCountValidationKey: this.options.maxNoOfFiles
343
+ });
344
+ formControl.markAsTouched();
345
+ this.uploader.queue = [];
568
346
  return;
569
- const errorMessage = errors.join('<br/>');
570
- this.setValidationError('InvalidFiles', errorMessage);
571
- setTimeout(() => {
572
- this.clearInvalidFilesError();
573
- }, this.ERROR_DISPLAY_DURATION);
574
- }
575
- setValidationError(errorKey, errorMessage) {
576
- const currentErrors = this.fileUploadFormControl.errors || {};
577
- currentErrors[errorKey] = errorMessage;
578
- this.fileUploadFormControl.setErrors(currentErrors);
579
- this.fileUploadFormControl.markAsTouched();
580
- }
581
- clearInvalidFilesError() {
582
- const currentErrors = this.fileUploadFormControl.errors;
583
- if (currentErrors && currentErrors['InvalidFiles']) {
584
- delete currentErrors['InvalidFiles'];
585
- if (Object.keys(currentErrors).length === 0) {
586
- this.fileUploadFormControl.setErrors(null);
347
+ }
348
+ if (this.options.isMultipleFile &&
349
+ this.options.maxSizeForAllFilesInMB != null &&
350
+ this.options.maxSizeForAllFilesInMB > 0) {
351
+ let AllSizeFile = 0;
352
+ for (let index = 0; index < this.uploader.queue.length; index++) {
353
+ const element = this.uploader.queue[index];
354
+ const file = element.file;
355
+ AllSizeFile = AllSizeFile + file.size;
587
356
  }
588
- else {
589
- this.fileUploadFormControl.setErrors(currentErrors);
357
+ const MaxSizeForAllFiles = this.options.maxSizeForAllFilesInMB * 1000 * 1000;
358
+ if (AllSizeFile > MaxSizeForAllFiles) {
359
+ const formControl = this.fileUploadFormControl;
360
+ formControl.setErrors({
361
+ MaxSizeForAllFilesInMB: this.options.maxSizeForAllFilesInMB + 'MB'
362
+ });
363
+ formControl.markAsTouched();
364
+ this.uploader.queue = [];
365
+ return;
590
366
  }
591
367
  }
592
- }
593
- setFormControlError(errorKey, errorValue) {
594
- this.fileUploadFormControl.setErrors({ [errorKey]: errorValue });
595
- this.fileUploadFormControl.markAsTouched();
596
- this.uploader.queue = [];
597
- }
598
- handleAsyncFileUpload(element, filesArray) {
599
- const uploadSubscription = this.fileUploadService.uploadFile(element._file).subscribe({
600
- next: (event) => {
601
- if (event.type === HttpEventType.UploadProgress) {
602
- this.handleUploadProgress(element, event);
368
+ let AddedQueue = this.uploader.queue.filter((obj) => obj['some'].lastModified != null);
369
+ for (let index = 0; index < AddedQueue.length; index++) {
370
+ const element = AddedQueue[index];
371
+ const file = element.file;
372
+ const maxFileSize = this.options.fileMaxSizeInMB * 1000 * 1000;
373
+ if (file) {
374
+ const fileType = file.type;
375
+ if (file.size > maxFileSize) {
376
+ const formControl = this.fileUploadFormControl;
377
+ formControl.setErrors({
378
+ FileMaxSizeInMB: this.options.fileMaxSizeInMB + 'M'
379
+ });
380
+ formControl.markAsTouched();
381
+ this.uploader.queue = [];
382
+ return;
603
383
  }
604
- else if (event.type === HttpEventType.Response) {
605
- this.handleUploadComplete(element, event, filesArray);
384
+ if (this.options.fileUploadAcceptsTypes != null &&
385
+ this.options.fileUploadAcceptsTypes.length > 0 &&
386
+ !(this.acceptedTypeArray.includes(fileType.toUpperCase()) ||
387
+ this.acceptedTypeArray.includes(fileType.toLowerCase()))) {
388
+ const formControl = this.fileUploadFormControl;
389
+ formControl.setErrors({ ToolTipTypeError: this.toolTipTypeArray });
390
+ formControl.markAsTouched();
391
+ this.uploader.queue = [];
392
+ return;
393
+ }
394
+ if (this.options.isUploadFileAsync && !element._file['iD_GUID']) {
395
+ this.fileUploadService.uploadFile(element._file).subscribe({
396
+ next: (event) => {
397
+ let queueIndex = this.uploader.queue.findIndex((file) => file == element);
398
+ if (event.type === HttpEventType.UploadProgress) {
399
+ let value = Math.round((100 * event.loaded) / event.total);
400
+ this.uploader.queue[queueIndex].progress = value >= 95 ? 95 : value;
401
+ }
402
+ else if (event.type === HttpEventType.Response) {
403
+ this.uploader.queue[queueIndex].progress = 100;
404
+ let fileID = event.body.val;
405
+ this.uploader.queue[queueIndex]._file['iD_GUID'] = fileID;
406
+ this.uploader.queue[queueIndex]._file['isNew'] = true;
407
+ let AddedFile = {
408
+ iD_GUID: fileID,
409
+ fileName: this.uploader.queue[queueIndex]._file['name'],
410
+ fileType: this.uploader.queue[queueIndex]._file['type'],
411
+ isNew: true
412
+ };
413
+ if (this.options.isMultipleFile == false) {
414
+ this.fileUploadModel = new FileUploadModel();
415
+ this.fileUploadModel.file = AddedFile;
416
+ this.fileUploadFormControl.setValue(this.fileUploadModel);
417
+ this.group.get(this.options.name).setValue(this.fileUploadModel);
418
+ //Use this line to enable two way binding.
419
+ this.options.value = this.fileUploadModel;
420
+ }
421
+ else {
422
+ FilesArray.push(AddedFile);
423
+ this.multipleFileUploadModel.uploadedFiles = FilesArray;
424
+ if (this.options.value != null && this.options.value != undefined) {
425
+ if (this.options.value.correlationID_GUID == null) {
426
+ this.multipleFileUploadModel.removedFiles = [];
427
+ }
428
+ }
429
+ this.multipleFileUploadModel.correlationID_GUID =
430
+ this.options.value?.correlationID_GUID;
431
+ this.fileUploadFormControl.setValue(this.multipleFileUploadModel);
432
+ this.group.get(this.options.name).setValue(this.multipleFileUploadModel);
433
+ //Use this line to enable two way binding.
434
+ this.options.value = this.multipleFileUploadModel;
435
+ this.isUploadComplete.emit(true);
436
+ }
437
+ }
438
+ }
439
+ });
440
+ }
441
+ else {
442
+ let reader = new FileReader();
443
+ let fileObject = file.rawFile;
444
+ reader.readAsDataURL(fileObject);
445
+ reader.onload = () => {
446
+ let existingID_GUID = null;
447
+ if (!this.options.isMultipleFile && this.file)
448
+ existingID_GUID = this.file.NameWithExtension == file.name ? this.file.iD_GUID : null;
449
+ let AddedFile = {
450
+ fileName: file.name,
451
+ fileType: file.type,
452
+ fileBase64: reader.result.toString().split(',')[1],
453
+ fileSizeInMB: file.size / 1000 / 1000,
454
+ nameWithExtension: file.name,
455
+ iD_GUID: existingID_GUID,
456
+ isNew: true
457
+ };
458
+ if (this.options.isMultipleFile == false) {
459
+ this.fileUploadModel = new FileUploadModel();
460
+ this.fileUploadModel.file = AddedFile;
461
+ this.fileUploadFormControl.setValue(this.fileUploadModel);
462
+ this.group.get(this.options.name).setValue(this.fileUploadModel);
463
+ //Use this line to enable two way binding.
464
+ this.options.value = this.fileUploadModel;
465
+ }
466
+ else {
467
+ FilesArray.push(AddedFile);
468
+ this.multipleFileUploadModel.uploadedFiles = FilesArray;
469
+ if (this.options.value != null && this.options.value != undefined) {
470
+ if (this.options.value.correlationID_GUID == null) {
471
+ this.multipleFileUploadModel.removedFiles = [];
472
+ }
473
+ }
474
+ this.multipleFileUploadModel.correlationID_GUID =
475
+ this.options.value?.correlationID_GUID;
476
+ this.fileUploadFormControl.setValue(this.multipleFileUploadModel);
477
+ this.group.get(this.options.name).setValue(this.multipleFileUploadModel);
478
+ //Use this line to enable two way binding.
479
+ this.options.value = this.multipleFileUploadModel;
480
+ }
481
+ };
482
+ let originalValue = this.group.get(this.options.name).value;
483
+ if (this.options.patchFunction &&
484
+ this.options.patchPath &&
485
+ this.group.get(this.options.name).valid) {
486
+ this.controlUtility.patchControlValue(originalValue, this.options.patchFunction, this.options.patchPath);
487
+ }
488
+ this.OnChange.emit(originalValue);
606
489
  }
607
- },
608
- error: (error) => {
609
- console.error('Upload failed:', error);
610
- // Handle upload error - you can add custom error handling here
611
- }
612
- });
613
- // Store subscription for cleanup
614
- this.subscriptions.add(uploadSubscription);
615
- }
616
- handleUploadProgress(element, event) {
617
- const queueIndex = this.uploader.queue.findIndex((file) => file === element);
618
- if (queueIndex === -1)
619
- return;
620
- const progress = Math.round((100 * event.loaded) / event.total);
621
- this.uploader.queue[queueIndex].progress =
622
- progress >= this.PROGRESS_NEAR_COMPLETE ? this.PROGRESS_NEAR_COMPLETE : progress;
623
- }
624
- handleUploadComplete(element, event, filesArray) {
625
- const queueIndex = this.uploader.queue.findIndex((file) => file === element);
626
- if (queueIndex === -1)
627
- return;
628
- this.uploader.queue[queueIndex].progress = this.PROGRESS_COMPLETE;
629
- const fileID = event.body.val;
630
- this.updateElementWithFileInfo(element, fileID, event.body.downloadUrl);
631
- const addedFile = this.createFileDTO(element, fileID, event.body.downloadUrl);
632
- this.updateFormValue(addedFile, filesArray);
633
- }
634
- updateElementWithFileInfo(element, fileID, downloadUrl) {
635
- element._file['iD_GUID'] = fileID;
636
- element._file['isNew'] = true;
637
- if (downloadUrl) {
638
- element._file['url'] = downloadUrl;
639
- element.file.url = downloadUrl;
640
- }
641
- }
642
- createFileDTO(element, fileID, downloadUrl) {
643
- return {
644
- iD_GUID: fileID,
645
- fileName: element._file['name'],
646
- fileType: element._file['type'],
647
- isNew: true,
648
- fileBase64: '',
649
- fileSizeInMB: element._file.size / this.BYTES_TO_MB,
650
- nameWithExtension: element._file['name'],
651
- fullFileURL: downloadUrl || null
652
- };
653
- }
654
- handleSyncFileUpload(file, filesArray) {
655
- this.trackMemoryUsage(file.size);
656
- const reader = new FileReader();
657
- // Store reader reference for cleanup
658
- const readerRef = reader;
659
- reader.onload = () => {
660
- try {
661
- const existingGUID = this.getExistingFileGUID(file);
662
- this.updateQueueItemForSync(file);
663
- const addedFile = this.createSyncFileDTO(file, reader.result, existingGUID);
664
- this.updateFormValue(addedFile, filesArray);
665
- this.handlePatchAndEmit();
666
- }
667
- finally {
668
- // Clean up reader
669
- readerRef.onload = null;
670
- readerRef.onerror = null;
671
- readerRef.onabort = null;
672
490
  }
673
- };
674
- reader.onerror = () => {
675
- console.error('File reading failed');
676
- readerRef.onload = null;
677
- readerRef.onerror = null;
678
- readerRef.onabort = null;
679
- };
680
- reader.readAsDataURL(file.rawFile);
681
- }
682
- updateQueueItemForSync(file) {
683
- const queueItem = this.findQueueItemByFile(file);
684
- if (queueItem) {
685
- this.preserveFileReference(queueItem, file);
686
- queueItem.progress = this.PROGRESS_COMPLETE;
687
- }
688
- }
689
- findQueueItemByFile(file) {
690
- return this.uploader.queue.find(item => item.file.name === file.name && item.file.size === file.size);
691
- }
692
- preserveFileReference(queueItem, file) {
693
- queueItem._file.rawFile = file.rawFile;
694
- queueItem.file.rawFile = file.rawFile;
695
- }
696
- createSyncFileDTO(file, readerResult, existingGUID) {
697
- return {
698
- fileName: file.name,
699
- fileType: file.type,
700
- fileBase64: readerResult.split(',')[1],
701
- fileSizeInMB: file.size / this.BYTES_TO_MB,
702
- nameWithExtension: file.name,
703
- iD_GUID: existingGUID,
704
- isNew: true,
705
- fullFileURL: null
706
- };
707
- }
708
- getExistingFileGUID(file) {
709
- if (!this.options.isMultipleFile && this.file) {
710
- return this.file.nameWithExtension === file.name ? this.file.iD_GUID : null;
711
- }
712
- return null;
713
- }
714
- updateFormValue(addedFile, filesArray) {
715
- if (!this.options.isMultipleFile) {
716
- this.fileUploadModel = new FileUploadModel();
717
- this.fileUploadModel.file = addedFile;
718
- this.updateFormControl(this.fileUploadModel);
719
- }
720
- else {
721
- filesArray.push(addedFile);
722
- this.multipleFileUploadModel.uploadedFiles = filesArray;
723
- this.setupMultipleFileModel();
724
- this.updateFormControl(this.multipleFileUploadModel);
725
- this.isUploadComplete.emit(true);
726
- }
727
- }
728
- setupMultipleFileModel() {
729
- if (this.options.value?.correlationID_GUID == null) {
730
- this.multipleFileUploadModel.removedFiles = [];
731
491
  }
732
- this.multipleFileUploadModel.correlationID_GUID = this.options.value?.correlationID_GUID;
733
- }
734
- updateFormControl(value) {
735
- this.preserveErrorsAndUpdateValue(value);
736
- this.options.value = value;
737
- }
738
- preserveErrorsAndUpdateValue(value) {
739
- const currentErrors = this.fileUploadFormControl.errors;
740
- this.fileUploadFormControl.setValue(value, { emitEvent: false });
741
- this.group.get(this.options.name)?.setValue(value, { emitEvent: false });
742
- if (currentErrors) {
743
- this.fileUploadFormControl.setErrors(currentErrors);
744
- }
745
- }
746
- handlePatchAndEmit() {
747
- const originalValue = this.group.get(this.options.name)?.value;
748
- if (this.options.patchFunction && this.options.patchPath && this.group.get(this.options.name)?.valid) {
749
- this.controlUtility.patchControlValue(originalValue, this.options.patchFunction, this.options.patchPath);
750
- }
751
- this.OnChange.emit(originalValue);
752
492
  }
753
493
  removeFromControlValue(item) {
754
- // Clean up blob URL before removing
755
- const downloadUrl = this.getFileDownloadUrl(item);
756
- if (downloadUrl && downloadUrl.startsWith('blob:')) {
757
- this.cleanupBlobUrl(downloadUrl);
758
- }
759
- this.handleAsyncFileDeletion(item);
760
- if (!this.options.isMultipleFile) {
761
- this.handleSingleFileRemoval();
762
- }
763
- else {
764
- this.handleMultipleFileRemoval(item);
765
- }
766
- this.checkAndClearMaxFileCountValidation();
767
- }
768
- handleAsyncFileDeletion(item) {
769
- if (this.options.isUploadFileAsync &&
770
- item.progress === this.PROGRESS_COMPLETE &&
771
- item._file['isNew']) {
772
- const deleteSubscription = this.fileUploadService.deleteFile(item._file['iD_GUID']).subscribe({
773
- error: (error) => console.error('Delete failed:', error)
774
- });
775
- this.subscriptions.add(deleteSubscription);
776
- }
777
- }
778
- handleSingleFileRemoval() {
779
- this.uploader.queue = [];
780
- this.fileUploadModel = null;
781
- if (this.options.isRequired) {
782
- this.fileUploadFormControl.markAsTouched();
783
- }
784
- const currentErrors = this.fileUploadFormControl.errors;
785
- this.group.get(this.options.name)?.setValue(this.fileUploadModel, { emitEvent: false });
786
- if (currentErrors) {
787
- this.fileUploadFormControl.setErrors(currentErrors);
788
- }
789
- this.options.value = this.fileUploadModel;
790
- }
791
- handleMultipleFileRemoval(item) {
792
- // Clean up blob URL
793
- const downloadUrl = this.getFileDownloadUrl(item);
794
- if (downloadUrl && downloadUrl.startsWith('blob:')) {
795
- this.cleanupBlobUrl(downloadUrl);
796
- }
797
- const queueIndex = this.uploader.queue.indexOf(item);
798
- if (queueIndex > -1) {
799
- this.uploader.queue.splice(queueIndex, 1);
800
- }
801
- this.processFileRemovalFromExisting(item);
802
- this.removeFromUploadedFiles(item);
803
- this.validateRemainingFiles();
804
- this.updateMultipleFileModel();
805
- }
806
- processFileRemovalFromExisting(item) {
807
- if (!this.options.value) {
808
- this.resetDeletedFiles();
809
- return;
810
- }
811
- if (!this.options.value.correlationID_GUID) {
812
- this.resetDeletedFiles();
494
+ if (this.options.isUploadFileAsync && item.progress == 100 && item._file['isNew']) {
495
+ this.fileUploadService.deleteFile(item._file['iD_GUID']).subscribe((res) => { });
496
+ }
497
+ if (this.options.isMultipleFile == false) {
498
+ this.fileUploadModel = null;
499
+ if (this.options.isRequired == true) {
500
+ this.fileUploadFormControl.markAsTouched();
501
+ this.fileUploadFormControl.invalid;
502
+ }
503
+ this.group.get(this.options.name).setValue(this.fileUploadModel);
504
+ this.options.value = this.fileUploadModel;
813
505
  }
814
506
  else {
815
- this.handleExistingFileRemoval(item);
816
- }
817
- }
818
- resetDeletedFiles() {
819
- this.deletedFiles = [];
820
- this.multipleFileUploadModel.removedFiles = [];
821
- }
822
- handleExistingFileRemoval(item) {
823
- const fileName = item.file.rawFile.name;
824
- const existingFile = this.multipleFileUploadModel.existingFiles
825
- .find(obj => obj.nameWithExtension === fileName);
826
- if (existingFile && !this.deletedFiles.some(obj => obj.nameWithExtension === fileName)) {
827
- this.multipleFileUploadModel.existingFiles =
828
- this.multipleFileUploadModel.existingFiles.filter(obj => obj.nameWithExtension !== fileName);
829
- this.deletedFiles.push(existingFile);
830
- this.multipleFileUploadModel.removedFiles.push(existingFile.iD_GUID);
831
- }
832
- }
833
- removeFromUploadedFiles(item) {
834
- const itemFileName = item._file.name || item.file.name;
835
- const itemFileSize = item._file.size || item.file.size;
836
- const itemGUID = item._file['iD_GUID'];
837
- this.multipleFileUploadModel.uploadedFiles =
838
- this.multipleFileUploadModel.uploadedFiles.filter(obj => {
839
- if (itemGUID && obj.iD_GUID) {
840
- return obj.iD_GUID !== itemGUID;
507
+ if (this.options.value != null && this.options.value != undefined) {
508
+ if (this.options.value.correlationID_GUID == null) {
509
+ this.deletedFiles = [];
510
+ this.multipleFileUploadModel.removedFiles = [];
841
511
  }
842
- const objFileName = obj.nameWithExtension || obj.fileName;
843
- const objFileSize = obj.fileSizeInMB ? obj.fileSizeInMB * this.BYTES_TO_MB : 0;
844
- return !(objFileName === itemFileName && Math.abs(objFileSize - itemFileSize) < 1000);
845
- });
846
- }
847
- validateRemainingFiles() {
848
- if ((!this.multipleFileUploadModel.uploadedFiles ||
849
- this.multipleFileUploadModel.uploadedFiles.length === 0) &&
850
- this.options.isRequired) {
851
- this.fileUploadFormControl.setErrors({
852
- MinFileCountValidationKey: this.options.minNoOfFiles
853
- });
854
- this.fileUploadFormControl.markAsTouched();
855
- }
856
- }
857
- updateMultipleFileModel() {
858
- this.multipleFileUploadModel.correlationID_GUID = this.options.value?.correlationID_GUID;
859
- const currentErrors = this.fileUploadFormControl.errors;
860
- this.fileUploadFormControl.setValue(this.multipleFileUploadModel, { emitEvent: false });
861
- this.group.get(this.options.name)?.setValue(this.multipleFileUploadModel, { emitEvent: false });
862
- this.options.value = this.multipleFileUploadModel;
863
- if (currentErrors) {
864
- this.fileUploadFormControl.setErrors(currentErrors);
512
+ else {
513
+ if (this.multipleFileUploadModel.removedFiles.length == 0) {
514
+ let FileObject = item.file.rawFile;
515
+ let DeletedItem = this.multipleFileUploadModel.existingFiles.filter((obj) => obj.nameWithExtension == FileObject.name)[0];
516
+ this.multipleFileUploadModel.existingFiles =
517
+ this.multipleFileUploadModel.existingFiles.filter((obj) => obj.nameWithExtension != FileObject.name);
518
+ this.deletedFiles.push(DeletedItem);
519
+ this.multipleFileUploadModel.removedFiles.push(DeletedItem.iD_GUID);
520
+ }
521
+ else {
522
+ let FileObject = item.file.rawFile;
523
+ let deletedList = this.deletedFiles.filter((obj) => obj.nameWithExtension == FileObject.name);
524
+ if (deletedList.length == 0 || deletedList == undefined) {
525
+ let DeletedItem = this.multipleFileUploadModel.existingFiles.filter((obj) => obj.nameWithExtension == FileObject.name)[0];
526
+ this.multipleFileUploadModel.existingFiles =
527
+ this.multipleFileUploadModel.existingFiles.filter((obj) => obj.nameWithExtension != FileObject.name);
528
+ this.deletedFiles.push(DeletedItem);
529
+ this.multipleFileUploadModel.removedFiles.push(DeletedItem.iD_GUID);
530
+ }
531
+ }
532
+ }
533
+ }
534
+ else {
535
+ this.deletedFiles = [];
536
+ this.multipleFileUploadModel.removedFiles = [];
537
+ }
538
+ this.multipleFileUploadModel.uploadedFiles =
539
+ this.multipleFileUploadModel.uploadedFiles.filter((obj) => (obj.nameWithExtension && obj.nameWithExtension != item._file.name) ||
540
+ obj.iD_GUID != item._file['iD_GUID']);
541
+ if ((this.multipleFileUploadModel.uploadedFiles == null ||
542
+ this.multipleFileUploadModel.uploadedFiles.length == 0) &&
543
+ this.options.isRequired) {
544
+ const formControl = this.fileUploadFormControl;
545
+ formControl.setErrors({
546
+ MinFileCountValidationKey: this.options.minNoOfFiles
547
+ });
548
+ this.fileUploadFormControl.markAsTouched();
549
+ this.fileUploadFormControl.invalid;
550
+ }
551
+ this.multipleFileUploadModel.correlationID_GUID = this.options.value?.correlationID_GUID;
552
+ this.fileUploadFormControl.setValue(this.multipleFileUploadModel);
553
+ this.group.get(this.options.name).setValue(this.multipleFileUploadModel);
554
+ //Use this line to enable two way binding.
555
+ this.options.value = this.multipleFileUploadModel;
865
556
  }
866
557
  }
867
558
  convertSizeToMB(size) {
868
559
  if (size === 0) {
869
560
  return 0;
870
561
  }
871
- const BYTES_TO_MB_ACCURATE = 1024 * 1024;
872
- const megabytes = size / BYTES_TO_MB_ACCURATE;
873
- return Math.round(megabytes * 100) / 100;
874
- }
875
- trackByFunction(index, item) {
876
- return item._file ? item._file.name + item._file.size : index;
877
- }
878
- shouldShowFileList() {
879
- return this.uploader?.queue && this.uploader.queue.length > 0;
880
- }
881
- isDownloadEnabled() {
882
- return true;
883
- }
884
- isRemoveEnabled() {
885
- return !this.options.isReadonly && !this.options.isDisabled;
886
- }
887
- getFileDownloadUrl(item) {
888
- const existingUrl = this.getExistingFileUrl(item);
889
- if (existingUrl) {
890
- return existingUrl;
891
- }
892
- return this.createFileUrl(item);
893
- }
894
- getExistingFileUrl(item) {
895
- return item?.file?.url ||
896
- item?._file?.url ||
897
- item?.url ||
898
- item?.file?.rawFile?.url ||
899
- item?._file?.rawFile?.url ||
900
- null;
901
- }
902
- createFileUrl(item) {
903
- const fileName = this.getFileName(item);
904
- const fileType = item?.file?.type || item?._file?.type;
905
- const originalFile = item?._file?.rawFile || item?.file?.rawFile;
906
- if (originalFile && originalFile instanceof File) {
907
- return URL.createObjectURL(originalFile);
908
- }
909
- const base64Data = typeof originalFile === 'string' ? originalFile : null;
910
- if (base64Data && fileName) {
911
- return this.createBlobUrlWithFilename(base64Data, fileType, fileName);
912
- }
913
- const fileId = item?._file?.['iD_GUID'];
914
- if (fileId && this.options.isUploadFileAsync) {
915
- return this.constructDownloadUrl(fileId, fileName);
916
- }
917
- return null;
918
- }
919
- createBlobUrlWithFilename(base64Data, fileType, fileName) {
920
- try {
921
- const byteCharacters = atob(base64Data);
922
- const byteNumbers = new Array(byteCharacters.length);
923
- for (let i = 0; i < byteCharacters.length; i++) {
924
- byteNumbers[i] = byteCharacters.charCodeAt(i);
925
- }
926
- const byteArray = new Uint8Array(byteNumbers);
927
- const blob = new Blob([byteArray], { type: fileType || 'application/octet-stream' });
928
- return URL.createObjectURL(blob);
929
- }
930
- catch (error) {
931
- const errorMsg = this.utilityService.getResourceValue('ErrorCreatingBlobUrl');
932
- console.error(errorMsg, error);
933
- return `data:${fileType || 'application/octet-stream'};base64,${base64Data}`;
934
- }
935
- }
936
- constructDownloadUrl(fileId, fileName) {
937
- const downloadBaseUrl = this.options.downloadBaseUrl;
938
- let url;
939
- if (downloadBaseUrl) {
940
- url = `${downloadBaseUrl}/${fileId}`;
941
- }
942
- else {
943
- url = `/api/files/download/${fileId}`;
944
- }
945
- if (fileName) {
946
- const separator = url.includes('?') ? '&' : '?';
947
- url += `${separator}filename=${encodeURIComponent(fileName)}`;
948
- }
949
- return url;
950
- }
951
- getFileName(item) {
952
- return item?.file?.name || item?._file?.name || 'file';
953
- }
954
- downloadFile(item) {
955
- const downloadInfo = this.prepareFileDownload(item);
956
- if (!downloadInfo.url) {
957
- this.handleDownloadError(downloadInfo.fileName);
958
- return;
959
- }
960
- this.executeFileDownload(downloadInfo.url, downloadInfo.fileName);
961
- }
962
- prepareFileDownload(item) {
963
- return {
964
- url: this.getFileDownloadUrl(item),
965
- fileName: this.getFileName(item)
966
- };
967
- }
968
- handleDownloadError(fileName) {
969
- const errorMsg = this.utilityService.getResourceValue('NoDownloadUrlAvailable')
970
- .replace('{fileName}', fileName);
971
- console.error(errorMsg);
972
- }
973
- executeFileDownload(url, fileName) {
974
- const link = this.createDownloadLink(url, fileName);
975
- this.triggerDownload(link);
976
- this.cleanupBlobUrl(url);
977
- }
978
- createDownloadLink(url, fileName) {
979
- const link = document.createElement('a');
980
- link.href = url;
981
- link.download = fileName;
982
- link.style.display = 'none';
983
- return link;
984
- }
985
- triggerDownload(link) {
986
- document.body.appendChild(link);
987
- link.click();
988
- document.body.removeChild(link);
989
- }
990
- cleanupBlobUrl(url) {
991
- if (url.startsWith('blob:')) {
992
- setTimeout(() => {
993
- URL.revokeObjectURL(url);
994
- }, 100);
995
- }
996
- }
997
- trackMemoryUsage(fileSize) {
998
- this.currentMemoryUsage += fileSize;
999
- // If memory usage exceeds limit, clean up old files
1000
- if (this.currentMemoryUsage > this.MAX_MEMORY_USAGE) {
1001
- this.cleanupOldFiles();
1002
- }
1003
- }
1004
- cleanupOldFiles() {
1005
- if (this.uploader?.queue && this.uploader.queue.length > 0) {
1006
- // Remove oldest files to free memory
1007
- const oldestFile = this.uploader.queue.shift();
1008
- if (oldestFile) {
1009
- const url = this.getFileDownloadUrl(oldestFile);
1010
- if (url && url.startsWith('blob:')) {
1011
- this.cleanupBlobUrl(url);
1012
- }
1013
- this.currentMemoryUsage -= (oldestFile.file?.size || 0);
1014
- }
1015
- }
1016
- }
1017
- cleanupEventListeners() {
1018
- // Clear file input references
1019
- if (this.fileInput?.nativeElement) {
1020
- this.fileInput.nativeElement.value = '';
1021
- }
1022
- // Clear uploader queue to prevent memory leaks
1023
- if (this.uploader?.queue) {
1024
- this.uploader.queue = [];
1025
- }
1026
- }
1027
- cleanupUploaderQueue() {
1028
- if (this.uploader?.queue) {
1029
- // Clear all items and their associated resources
1030
- this.uploader.queue.forEach(item => {
1031
- // Clean up blob URLs
1032
- const url = this.getFileDownloadUrl(item);
1033
- if (url && url.startsWith('blob:')) {
1034
- this.cleanupBlobUrl(url);
1035
- }
1036
- // Clear file references
1037
- if (item._file) {
1038
- item._file = null;
1039
- }
1040
- if (item.file) {
1041
- item.file = null;
1042
- }
1043
- });
1044
- // Clear the queue
1045
- this.uploader.queue = [];
1046
- }
1047
- }
1048
- ngOnDestroy() {
1049
- // Clean up subscriptions
1050
- this.subscriptions.unsubscribe();
1051
- // Clean up uploader queue
1052
- this.cleanupUploaderQueue();
1053
- // Clean up event listeners
1054
- this.cleanupEventListeners();
1055
- // Clean up blob URLs
1056
- if (this.uploader?.queue) {
1057
- this.uploader.queue.forEach(item => {
1058
- const url = this.getFileDownloadUrl(item);
1059
- if (url && url.startsWith('blob:')) {
1060
- URL.revokeObjectURL(url);
1061
- }
1062
- });
1063
- }
1064
- }
1065
- checkAndClearMaxFileCountValidation() {
1066
- if (!this.options.maxNoOfFiles || this.options.maxNoOfFiles <= 0) {
1067
- return;
1068
- }
1069
- const currentQueueLength = this.uploader.queue.length;
1070
- if (currentQueueLength <= this.options.maxNoOfFiles) {
1071
- this.clearFileCountError('MaxFileCountValidationKey');
1072
- }
562
+ // Convert size to megabytes
563
+ const megabytes = size / (1024 * 1024);
564
+ // Round to two decimal places
565
+ const roundedMegabytes = Math.round(megabytes * 100) / 100;
566
+ return roundedMegabytes;
1073
567
  }
1074
568
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileUploadComponent, deps: [{ token: i1.ControlContainer, optional: true }, { token: i1.FormGroupDirective }, { token: i2.ControlUtility }, { token: i3.UtilityService }, { token: i3.ControlValidationService }, { token: i4.GlobalSettings }, { token: i5.FileUploadService }], target: i0.ɵɵFactoryTarget.Component }); }
1075
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FileUploadComponent, selector: "BBSF-FileUpload", inputs: { group: "group", options: "options" }, outputs: { OnChange: "OnChange", isUploadComplete: "isUploadComplete" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], ngImport: i0, template: "<div class=\"form-group bbsf-control bbsf-file-upload\" [formGroup]=\"group\">\r\n <div [ngClass]=\"options.viewType === 1 ? 'bbsf-vertical' : 'bbsf-horizontal'\">\r\n <!-- Label -->\r\n <label [hidden]=\"options.hideLabel\" class=\"bbsf-label {{ options.labelExtraClasses }}\">\r\n {{ options.labelValue }}\r\n <!-- Required asterisk -->\r\n <span *ngIf=\"options.isRequired && !options.isReadonly && (options.showAsterisk || true)\"\r\n class=\"text-danger\">*</span>\r\n </label>\r\n <!-- Drop zone enabled -->\r\n <div ng2FileDrop class=\"bbsf-input-container {{ options.extraClasses }}\"\r\n *ngIf=\"options.isDropZone && !isHideInput() && !options.isReadonly\"\r\n [ngClass]=\"{ 'another-file-over-class': hasAnotherDropZoneOver }\" (onFileDrop)=\"onFileChange()\"\r\n (fileOver)=\"fileOverAnother($event)\" [uploader]=\"uploader\" [accept]=\"acceptedType\" [id]=\"options.name\"\r\n [attr.multiple]=\"options.isMultipleFile ? 'multiple' : null\"\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\"\r\n (click)=\"fileInputControl.click()\">\r\n\r\n <div class=\"dropzone-label\">\r\n <div class=\"svg-and-validation\">\r\n <!-- Upload icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"70\" height=\"70\" viewBox=\"0 0 70 70\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M58.333 48.8332C61.8957 45.8908 64.1663 41.4397 64.1663 36.4583C64.1663 27.5988 56.9843 20.4167 48.1247 20.4167C47.4874 20.4167 46.8912 20.0842 46.5675 19.5351C42.7641 13.0808 35.7417 8.75 27.708 8.75C15.6268 8.75 5.83301 18.5438 5.83301 30.625C5.83301 36.6511 8.26974 42.1082 12.2116 46.0644\"\r\n stroke=\"#4B5489\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M23.333 46.6667L34.9997 35M34.9997 35L46.6663 46.6667M34.9997 35V61.25\" stroke=\"#4B5489\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n\r\n <!-- Instruction text -->\r\n <div class=\"bbsf-validation-msg validation-msg-header text-center\">\r\n {{ utilityService.getResourceValue('DragAndDropHere') }}\r\n </div>\r\n\r\n <!-- Validation messages -->\r\n <div class=\"bbsf-validation-msg text-center\" *ngIf=\"validationMessage\" [innerHTML]=\"validationMessage\">\r\n </div>\r\n\r\n <div class=\"bbsf-validation-msg text-center text-danger\"\r\n *ngIf=\"validationCountMessage && options.isMultipleFile && options.maxNoOfFiles > 0\"\r\n [innerHTML]=\"validationCountMessage\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden file input -->\r\n <input ng2FileSelect [uploader]=\"uploader\" [accept]=\"acceptedType\"\r\n class=\"fileSelector customFileUploadPlacment hidden v-required-multiplefiles d-none\"\r\n [attr.multiple]=\"options.isMultipleFile ? 'multiple' : null\" name=\"file\" type=\"file\" autocomplete=\"off\"\r\n (change)=\"onFileChange()\" [ngClass]=\"options.viewType === 1 ? '' : 'col-md-9'\" [id]=\"options.name\"\r\n #fileInputControl [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\" />\r\n </div>\r\n <!-- Click to upload (no drop zone) -->\r\n <div class=\"bbsf-input-container\" *ngIf=\"!options.isDropZone && !isHideInput() && !options.isReadonly\"\r\n (click)=\"fileInput.click()\">\r\n\r\n <div class=\"dropzone-label\">\r\n <div class=\"svg-and-validation\">\r\n <!-- Upload icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"70\" height=\"70\" viewBox=\"0 0 70 70\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M58.333 48.8332C61.8957 45.8908 64.1663 41.4397 64.1663 36.4583C64.1663 27.5988 56.9843 20.4167 48.1247 20.4167C47.4874 20.4167 46.8912 20.0842 46.5675 19.5351C42.7641 13.0808 35.7417 8.75 27.708 8.75C15.6268 8.75 5.83301 18.5438 5.83301 30.625C5.83301 36.6511 8.26974 42.1082 12.2116 46.0644\"\r\n stroke=\"#4B5489\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M23.333 46.6667L34.9997 35M34.9997 35L46.6663 46.6667M34.9997 35V61.25\" stroke=\"#4B5489\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n\r\n <!-- Upload text -->\r\n <div class=\"bbsf-validation-msg text-center\">\r\n {{ utilityService.getResourceValue('Upload') }}\r\n </div>\r\n\r\n <!-- Validation messages -->\r\n <div class=\"bbsf-validation-msg text-center\" *ngIf=\"validationMessage\" [innerHTML]=\"validationMessage\">\r\n </div>\r\n\r\n <div class=\"bbsf-validation-msg text-center text-danger\"\r\n *ngIf=\"validationCountMessage && options.isMultipleFile && options.maxNoOfFiles > 0\"\r\n [innerHTML]=\"validationCountMessage\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden file input -->\r\n <input ng2FileSelect [uploader]=\"uploader\" [accept]=\"acceptedType\"\r\n class=\"fileSelector customFileUploadPlacment hidden v-required-multiplefiles d-none\"\r\n [attr.multiple]=\"options.isMultipleFile ? 'multiple' : null\" name=\"file\" type=\"file\" autocomplete=\"off\"\r\n (change)=\"onFileChange()\" [ngClass]=\"options.viewType === 1 ? '' : 'col-md-9'\" [id]=\"options.name\" #fileInput\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\" />\r\n </div>\r\n <!-- Read-only state with no files -->\r\n <div *ngIf=\"options.isReadonly && (!options.value || (uploader.queue && uploader.queue.length === 0))\">\r\n <span class=\"readonly-view\">{{ utilityService.getResourceValue('NA') }}</span>\r\n </div>\r\n </div>\r\n <!-- Uploaded files list -->\r\n <div class=\"uploaded-items\" *ngIf=\"shouldShowFileList()\">\r\n <div class=\"btn-group\" *ngFor=\"let item of uploader.queue; trackBy: trackByFunction\">\r\n\r\n <!-- Async upload completed files -->\r\n <ng-container *ngIf=\"item?.progress === 100 && options.isUploadFileAsync\">\r\n <!-- Download link - always visible -->\r\n <button *ngIf=\"getFileDownloadUrl(item); else noUrlTemplate\" type=\"button\"\r\n class=\"btn-download-file btn-sm btn-progress-upload\" (click)=\"downloadFile(item)\"\r\n [title]=\"'Download ' + getFileName(item)\">\r\n <span class=\"file-name\">{{ getFileName(item) }}</span>\r\n </button>\r\n\r\n <!-- File name display when no URL available -->\r\n <ng-template #noUrlTemplate>\r\n <span class=\"btn-download-file btn-sm btn-progress-upload\" [title]=\"getFileName(item)\">\r\n <span class=\"file-name\">{{ getFileName(item) }}</span>\r\n </span>\r\n </ng-template>\r\n\r\n <!-- Remove button - only show when not readonly and not disabled -->\r\n <button *ngIf=\"isRemoveEnabled()\" class=\"btn btn-download-file btn-sm\" type=\"button\"\r\n (click)=\"item.remove(); removeFromControlValue(item)\" [attr.aria-label]=\"'Remove ' + getFileName(item)\"\r\n [title]=\"'Remove ' + getFileName(item)\">\r\n <!-- Delete icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M9.33301 3.70584V3.26663C9.33301 2.65166 9.33301 2.34419 9.20587 2.1093C9.09405 1.9027 8.91555 1.73471 8.69604 1.62944C8.44647 1.50977 8.11977 1.50977 7.46638 1.50977H6.53305C5.87965 1.50977 5.55296 1.50977 5.30339 1.62944C5.08387 1.73471 4.90539 1.9027 4.79354 2.1093C4.66638 2.34419 4.66638 2.65166 4.66638 3.26663V3.70584\"\r\n stroke=\"#D83731\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path\r\n d=\"M1.75 3.70605H12.25M11.0834 3.70605V9.8551C11.0834 10.7775 11.0834 11.2387 10.8926 11.591C10.7248 11.901 10.4571 12.1529 10.1278 12.3109C9.75345 12.4904 9.26345 12.4904 8.28334 12.4904H5.71666C4.73658 12.4904 4.24653 12.4904 3.87218 12.3109C3.5429 12.1529 3.27519 11.901 3.10741 11.591C2.91666 11.2387 2.91666 10.7775 2.91666 9.8551V3.70605\"\r\n stroke=\"#D83731\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n </ng-container>\r\n\r\n <!-- Sync upload files -->\r\n <ng-container *ngIf=\"!options.isUploadFileAsync\">\r\n <!-- Download link - always visible -->\r\n <button type=\"button\" class=\"btn btn-download-file btn-sm\" (click)=\"downloadFile(item)\"\r\n [title]=\"'Download ' + getFileName(item)\">\r\n <!-- Download icon -->\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path\r\n d=\"M21 22H3C2.4 22 2 21.6 2 21C2 20.4 2.4 20 3 20H21C21.6 20 22 20.4 22 21C22 21.6 21.6 22 21 22ZM13 13.4V3C13 2.4 12.6 2 12 2C11.4 2 11 2.4 11 3V13.4H13Z\"\r\n fill=\"currentColor\"></path>\r\n <path opacity=\"0.3\" d=\"M7 13.4H17L12.7 17.7C12.3 18.1 11.7 18.1 11.3 17.7L7 13.4Z\" fill=\"currentColor\">\r\n </path>\r\n </svg>\r\n <span class=\"file-name\">{{ getFileName(item) }}</span>\r\n </button>\r\n\r\n <!-- Remove button - only show when not readonly and not disabled -->\r\n <button *ngIf=\"isRemoveEnabled()\" class=\"btn btn-download-file btn-sm btn-danger\" type=\"button\"\r\n (click)=\"item.remove(); removeFromControlValue(item)\" [attr.aria-label]=\"'Remove ' + getFileName(item)\"\r\n [title]=\"'Remove ' + getFileName(item)\">\r\n <i class=\"fa fa-times px-0\" aria-hidden=\"true\"></i>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <!-- File upload progress indicators -->\r\n <div *ngFor=\"let item of uploader.queue; trackBy: trackByFunction\">\r\n <div class=\"upload-items\" [ngClass]=\"{ 'mt-4': options.isMultipleFile }\"\r\n *ngIf=\"item?.progress < 100 && options.isUploadFileAsync && !options.isReadonly\">\r\n\r\n <div class=\"upload-items-toolbar\">\r\n <h4>{{ getFileName(item) }}</h4>\r\n <button *ngIf=\"isRemoveEnabled()\" type=\"button\" class=\"btn-cancel-upload\"\r\n (click)=\"item.remove(); removeFromControlValue(item)\"\r\n [attr.aria-label]=\"'Cancel upload for ' + getFileName(item)\">\r\n <!-- Cancel icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\">\r\n <g clip-path=\"url(#clip0_1324_13216)\">\r\n <path opacity=\"0.4\"\r\n d=\"M9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5Z\"\r\n stroke=\"#DBE1F0\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M11.25 6.75L6.75 11.25M6.75 6.75L11.25 11.25\" stroke=\"#DBE1F0\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </g>\r\n <defs>\r\n <clipPath id=\"clip0_1324_13216\">\r\n <rect width=\"18\" height=\"18\" fill=\"white\" />\r\n </clipPath>\r\n </defs>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"progress\">\r\n <div class=\"progress-bar\" role=\"progressbar\" [attr.aria-valuenow]=\"item?.progress\" aria-valuemin=\"0\"\r\n aria-valuemax=\"100\" [class.file-uploaded]=\"item?.progress < 100\" [style.width.%]=\"item?.progress\"\r\n *ngIf=\"item?.progress > 0\">\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Validation and description section -->\r\n <div class=\"subtext-container\" *ngIf=\"!options.isReadonly\">\r\n <!-- Validation messages -->\r\n <div class=\"bbsf-validation\" *ngIf=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\">\r\n <span [innerHTML]=\"getErrorValidation(fileUploadFormControl.errors | keyvalue)\"></span>\r\n </div>\r\n\r\n <!-- Control description -->\r\n <div class=\"bbsf-control-desc\" *ngIf=\"options.labelDescription\">\r\n {{ options.labelDescription }}\r\n </div>\r\n\r\n <!-- Reset error state -->\r\n <div *ngIf=\"(group.valid && group.dirty && group.touched) || (group.untouched && group.invalid && group.dirty)\">\r\n {{ resetError() }}\r\n </div>\r\n </div>\r\n</div>", dependencies: [{ kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i7.FileDropDirective, selector: "[ng2FileDrop]", inputs: ["uploader"], outputs: ["fileOver", "onFileDrop"] }, { kind: "directive", type: i7.FileSelectDirective, selector: "[ng2FileSelect]", inputs: ["uploader"], outputs: ["onFileSelected"] }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "pipe", type: i6.KeyValuePipe, name: "keyvalue" }] }); }
569
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FileUploadComponent, selector: "BBSF-FileUpload", inputs: { group: "group", options: "options" }, outputs: { OnChange: "OnChange", isUploadComplete: "isUploadComplete" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], ngImport: i0, template: "<div class=\"form-group bbsf-control bbsf-file-upload\" [formGroup]=\"group\">\r\n <div [ngClass]=\"options.viewType == 1 ? 'bbsf-vertical' : 'bbsf-horizontal'\">\r\n <!--label-->\r\n <label [hidden]=\"options.hideLabel\" class=\"bbsf-label {{ options.labelExtraClasses }}\">\r\n {{ options.labelValue }}\r\n <!--Asterisk-->\r\n <span *ngIf=\"((options.showAsterisk && options.isRequired) || options.isRequired) && !options.isReadonly\"\r\n class=\"text-danger\">*</span>\r\n </label>\r\n <!--Allow dropZone-->\r\n <div ng2FileDrop class=\"bbsf-input-container {{ options.extraClasses }}\"\r\n *ngIf=\"options.isDropZone && !(options.isMultipleFile == false && uploader.queue.length > 0) && !options.isReadonly\"\r\n [ngClass]=\"{ 'another-file-over-class': hasAnotherDropZoneOver }\" (onFileDrop)=\"onFileChange()\"\r\n (fileOver)=\"fileOverAnother($event)\" [uploader]=\"uploader\" [accept]=\"acceptedType\" id=\"{{ options.name }}\"\r\n multiple=\"{{ options.isMultipleFile ? 'multiple' : '' }}\" aria-describedby=\"email-error\" aria-invalid=\"true\"\r\n type=\"file\" #fileInput [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\"\r\n (click)=\"fileInputControl.click()\">\r\n <div class=\"dropzone-label\">\r\n <div class=\"svg-and-validation\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"70\" height=\"70\" viewBox=\"0 0 70 70\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M58.333 48.8332C61.8957 45.8908 64.1663 41.4397 64.1663 36.4583C64.1663 27.5988 56.9843 20.4167 48.1247 20.4167C47.4874 20.4167 46.8912 20.0842 46.5675 19.5351C42.7641 13.0808 35.7417 8.75 27.708 8.75C15.6268 8.75 5.83301 18.5438 5.83301 30.625C5.83301 36.6511 8.26974 42.1082 12.2116 46.0644\"\r\n stroke=\"#4B5489\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M23.333 46.6667L34.9997 35M34.9997 35L46.6663 46.6667M34.9997 35V61.25\" stroke=\"#4B5489\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n <!--Validation text-->\r\n <div class=\"bbsf-validation-msg validation-msg-header text-center\">\r\n {{ UtilityService.getResourceValue('DragAndDropHere') }}\r\n </div>\r\n <div class=\"bbsf-validation-msg text-center\" *ngIf=\"validationMessage\" [innerHTML]=\"validationMessage\"></div>\r\n <div class=\"bbsf-validation-msg ng-star-inserted text-center text-danger\"\r\n *ngIf=\"validationCountMessage && options.isMultipleFile && options.maxNoOfFiles > 0\"\r\n [innerHTML]=\"validationCountMessage\"></div>\r\n </div>\r\n </div>\r\n <input ng2FileSelect [uploader]=\"uploader\" [accept]=\"acceptedType\"\r\n class=\"fileSelector customFileUploadPlacment hidden v-required-multiplefiles d-none\"\r\n multiple=\"{{ options.isMultipleFile ? 'multiple' : '' }}\" name=\"file\" type=\"file\" value=\"\" autocomplete=\"off\"\r\n (change)=\"onFileChange()\" [ngClass]=\"options.viewType == 1 ? '' : 'col-md-9'\" id=\"{{ options.name }}\"\r\n aria-describedby=\"email-error\" aria-invalid=\"true\" formControlName=\"{{ options.name }}\" #fileInputControl\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\" />\r\n </div>\r\n <!--Not allowed dropZone-->\r\n <div class=\"bbsf-input-container\" *ngIf=\"!options.isDropZone && !isHideInput() && !options.isReadonly\"\r\n (click)=\"fileInput.click()\">\r\n <div class=\"dropzone-label\">\r\n <div class=\"svg-and-validation\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"70\" height=\"70\" viewBox=\"0 0 70 70\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M58.333 48.8332C61.8957 45.8908 64.1663 41.4397 64.1663 36.4583C64.1663 27.5988 56.9843 20.4167 48.1247 20.4167C47.4874 20.4167 46.8912 20.0842 46.5675 19.5351C42.7641 13.0808 35.7417 8.75 27.708 8.75C15.6268 8.75 5.83301 18.5438 5.83301 30.625C5.83301 36.6511 8.26974 42.1082 12.2116 46.0644\"\r\n stroke=\"#4B5489\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M23.333 46.6667L34.9997 35M34.9997 35L46.6663 46.6667M34.9997 35V61.25\" stroke=\"#4B5489\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n <!--Validation text-->\r\n <div class=\"bbsf-validation-msg text-center\">{{ UtilityService.getResourceValue('Upload') }}</div>\r\n <div class=\"bbsf-validation-msg text-center\" *ngIf=\"validationMessage\" [innerHTML]=\"validationMessage\"></div>\r\n <div class=\"bbsf-validation-msg ng-star-inserted text-center text-danger\"\r\n *ngIf=\"validationCountMessage && options.isMultipleFile && options.maxNoOfFiles > 0\"\r\n [innerHTML]=\"validationCountMessage\"></div>\r\n </div>\r\n </div>\r\n <input ng2FileSelect [uploader]=\"uploader\" [accept]=\"acceptedType\"\r\n class=\"fileSelector customFileUploadPlacment hidden v-required-multiplefiles d-none\"\r\n multiple=\"{{ options.isMultipleFile ? 'multiple' : '' }}\" name=\"file\" type=\"file\" value=\"\" autocomplete=\"off\"\r\n (change)=\"onFileChange()\" [ngClass]=\"options.viewType == 1 ? '' : 'col-md-9'\" id=\"{{ options.name }}\"\r\n aria-describedby=\"email-error\" aria-invalid=\"true\" formControlName=\"{{ options.name }}\" #fileInput\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\" />\r\n </div>\r\n <!-- readonly -->\r\n <div *ngIf=\"options.isReadonly && !options.value\">\r\n <span class=\"readonly-view\">{{ UtilityService.getResourceValue('NA') }}</span>\r\n </div>\r\n </div>\r\n <!--items uploaded-->\r\n <div class=\"uploaded-items\">\r\n <div class=\"btn-group\" *ngFor=\"let item of uploader.queue\">\r\n <ng-container *ngIf=\"item?.progress == 100 && options.isUploadFileAsync\">\r\n <a *ngIf=\"item?.file?.rawFile['url']\" href=\"{{ item?.file?.rawFile['url'] }}\"\r\n class=\"btn-download-file btn-sm btn-progress-upload\" download>\r\n <span class=\"file-name\">{{ item?.file?.name }}</span>\r\n </a>\r\n <a *ngIf=\"item?.file?.rawFile['url'] == null\" class=\"btn-download-file btn-sm btn-progress-upload\">\r\n <span class=\"file-name\">{{ item?.file?.name }}</span>\r\n </a>\r\n <button *ngIf=\"!options.isReadonly\" class=\"btn btn-download-file btn-sm\"\r\n (click)=\"item.remove(); removeFromControlValue(item)\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M9.33301 3.70584V3.26663C9.33301 2.65166 9.33301 2.34419 9.20587 2.1093C9.09405 1.9027 8.91555 1.73471 8.69604 1.62944C8.44647 1.50977 8.11977 1.50977 7.46638 1.50977H6.53305C5.87965 1.50977 5.55296 1.50977 5.30339 1.62944C5.08387 1.73471 4.90539 1.9027 4.79354 2.1093C4.66638 2.34419 4.66638 2.65166 4.66638 3.26663V3.70584\"\r\n stroke=\"#D83731\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path\r\n d=\"M1.75 3.70605H12.25M11.0834 3.70605V9.8551C11.0834 10.7775 11.0834 11.2387 10.8926 11.591C10.7248 11.901 10.4571 12.1529 10.1278 12.3109C9.75345 12.4904 9.26345 12.4904 8.28334 12.4904H5.71666C4.73658 12.4904 4.24653 12.4904 3.87218 12.3109C3.5429 12.1529 3.27519 11.901 3.10741 11.591C2.91666 11.2387 2.91666 10.7775 2.91666 9.8551V3.70605\"\r\n stroke=\"#D83731\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n </ng-container>\r\n <ng-container *ngIf=\"!options.isUploadFileAsync\">\r\n <a href=\"{{ item?.file?.rawFile['url'] }}\" class=\"btn btn-download-file btn-sm\" download>\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path\r\n d=\"M21 22H3C2.4 22 2 21.6 2 21C2 20.4 2.4 20 3 20H21C21.6 20 22 20.4 22 21C22 21.6 21.6 22 21 22ZM13 13.4V3C13 2.4 12.6 2 12 2C11.4 2 11 2.4 11 3V13.4H13Z\"\r\n fill=\"currentColor\"></path>\r\n <path opacity=\"0.3\" d=\"M7 13.4H17L12.7 17.7C12.3 18.1 11.7 18.1 11.3 17.7L7 13.4Z\" fill=\"currentColor\">\r\n </path>\r\n </svg>\r\n <span class=\"file-name\">{{ item?.file?.name }}</span>\r\n </a>\r\n <button *ngIf=\"!options.isReadonly\" class=\"btn btn-download-file btn-sm btn-danger\"\r\n (click)=\"item.remove(); removeFromControlValue(item)\">\r\n <i class=\"fa fa-times px-0\"></i>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <!--progress bar file upload-->\r\n <div *ngFor=\"let item of uploader.queue\">\r\n <div class=\"upload-items\" [ngClass]=\"{ 'mt-4': options.isMultipleFile == true }\"\r\n *ngIf=\"item?.progress < 100 && options.isUploadFileAsync\">\r\n <div class=\"upload-items-toolbar\">\r\n <h4>{{ item?.file?.name }}</h4>\r\n <span (click)=\"item.remove(); removeFromControlValue(item)\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\">\r\n <g clip-path=\"url(#clip0_1324_13216)\">\r\n <path opacity=\"0.4\"\r\n d=\"M9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5Z\"\r\n stroke=\"#DBE1F0\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M11.25 6.75L6.75 11.25M6.75 6.75L11.25 11.25\" stroke=\"#DBE1F0\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </g>\r\n <defs>\r\n <clipPath id=\"clip0_1324_13216\">\r\n <rect width=\"18\" height=\"18\" fill=\"white\" />\r\n </clipPath>\r\n </defs>\r\n </svg>\r\n </span>\r\n </div>\r\n <div class=\"progress\">\r\n <div class=\"progress-bar\" role=\"progressbar\" aria-valuenow=\"70\" aria-valuemin=\"0\" aria-valuemax=\"100\"\r\n [class.file-uploaded]=\"item?.progress < 100\" [style.width.%]=\"item?.progress\" *ngIf=\"item?.progress > 0\">\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"subtext-container\" *ngIf=\"!options.isReadonly\">\r\n <!-- required text-->\r\n <div class=\"bbsf-validation\" *ngIf=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\">\r\n {{ getErrorValidation(fileUploadFormControl.errors | keyvalue) }}\r\n </div>\r\n <!-- LabelDescription-->\r\n <div class=\"bbsf-control-desc\" *ngIf=\"options.labelDescription != null\">{{ options.labelDescription }}</div>\r\n <div *ngIf=\"(group.valid && group.dirty && group.touched) || (group.untouched && group.invalid && group.dirty)\">\r\n {{ resetError() }}\r\n </div>\r\n </div>\r\n</div>", dependencies: [{ kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i7.FileDropDirective, selector: "[ng2FileDrop]", inputs: ["uploader"], outputs: ["fileOver", "onFileDrop"] }, { kind: "directive", type: i7.FileSelectDirective, selector: "[ng2FileSelect]", inputs: ["uploader"], outputs: ["onFileSelected"] }, { kind: "directive", type: i8.NativeElementInjectorDirective, selector: "[ngModel], [formControl], [formControlName]" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: i6.KeyValuePipe, name: "keyvalue" }] }); }
1076
570
  }
1077
571
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileUploadComponent, decorators: [{
1078
572
  type: Component,
1079
- args: [{ selector: 'BBSF-FileUpload', standalone: false, template: "<div class=\"form-group bbsf-control bbsf-file-upload\" [formGroup]=\"group\">\r\n <div [ngClass]=\"options.viewType === 1 ? 'bbsf-vertical' : 'bbsf-horizontal'\">\r\n <!-- Label -->\r\n <label [hidden]=\"options.hideLabel\" class=\"bbsf-label {{ options.labelExtraClasses }}\">\r\n {{ options.labelValue }}\r\n <!-- Required asterisk -->\r\n <span *ngIf=\"options.isRequired && !options.isReadonly && (options.showAsterisk || true)\"\r\n class=\"text-danger\">*</span>\r\n </label>\r\n <!-- Drop zone enabled -->\r\n <div ng2FileDrop class=\"bbsf-input-container {{ options.extraClasses }}\"\r\n *ngIf=\"options.isDropZone && !isHideInput() && !options.isReadonly\"\r\n [ngClass]=\"{ 'another-file-over-class': hasAnotherDropZoneOver }\" (onFileDrop)=\"onFileChange()\"\r\n (fileOver)=\"fileOverAnother($event)\" [uploader]=\"uploader\" [accept]=\"acceptedType\" [id]=\"options.name\"\r\n [attr.multiple]=\"options.isMultipleFile ? 'multiple' : null\"\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\"\r\n (click)=\"fileInputControl.click()\">\r\n\r\n <div class=\"dropzone-label\">\r\n <div class=\"svg-and-validation\">\r\n <!-- Upload icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"70\" height=\"70\" viewBox=\"0 0 70 70\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M58.333 48.8332C61.8957 45.8908 64.1663 41.4397 64.1663 36.4583C64.1663 27.5988 56.9843 20.4167 48.1247 20.4167C47.4874 20.4167 46.8912 20.0842 46.5675 19.5351C42.7641 13.0808 35.7417 8.75 27.708 8.75C15.6268 8.75 5.83301 18.5438 5.83301 30.625C5.83301 36.6511 8.26974 42.1082 12.2116 46.0644\"\r\n stroke=\"#4B5489\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M23.333 46.6667L34.9997 35M34.9997 35L46.6663 46.6667M34.9997 35V61.25\" stroke=\"#4B5489\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n\r\n <!-- Instruction text -->\r\n <div class=\"bbsf-validation-msg validation-msg-header text-center\">\r\n {{ utilityService.getResourceValue('DragAndDropHere') }}\r\n </div>\r\n\r\n <!-- Validation messages -->\r\n <div class=\"bbsf-validation-msg text-center\" *ngIf=\"validationMessage\" [innerHTML]=\"validationMessage\">\r\n </div>\r\n\r\n <div class=\"bbsf-validation-msg text-center text-danger\"\r\n *ngIf=\"validationCountMessage && options.isMultipleFile && options.maxNoOfFiles > 0\"\r\n [innerHTML]=\"validationCountMessage\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden file input -->\r\n <input ng2FileSelect [uploader]=\"uploader\" [accept]=\"acceptedType\"\r\n class=\"fileSelector customFileUploadPlacment hidden v-required-multiplefiles d-none\"\r\n [attr.multiple]=\"options.isMultipleFile ? 'multiple' : null\" name=\"file\" type=\"file\" autocomplete=\"off\"\r\n (change)=\"onFileChange()\" [ngClass]=\"options.viewType === 1 ? '' : 'col-md-9'\" [id]=\"options.name\"\r\n #fileInputControl [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\" />\r\n </div>\r\n <!-- Click to upload (no drop zone) -->\r\n <div class=\"bbsf-input-container\" *ngIf=\"!options.isDropZone && !isHideInput() && !options.isReadonly\"\r\n (click)=\"fileInput.click()\">\r\n\r\n <div class=\"dropzone-label\">\r\n <div class=\"svg-and-validation\">\r\n <!-- Upload icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"70\" height=\"70\" viewBox=\"0 0 70 70\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M58.333 48.8332C61.8957 45.8908 64.1663 41.4397 64.1663 36.4583C64.1663 27.5988 56.9843 20.4167 48.1247 20.4167C47.4874 20.4167 46.8912 20.0842 46.5675 19.5351C42.7641 13.0808 35.7417 8.75 27.708 8.75C15.6268 8.75 5.83301 18.5438 5.83301 30.625C5.83301 36.6511 8.26974 42.1082 12.2116 46.0644\"\r\n stroke=\"#4B5489\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M23.333 46.6667L34.9997 35M34.9997 35L46.6663 46.6667M34.9997 35V61.25\" stroke=\"#4B5489\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n\r\n <!-- Upload text -->\r\n <div class=\"bbsf-validation-msg text-center\">\r\n {{ utilityService.getResourceValue('Upload') }}\r\n </div>\r\n\r\n <!-- Validation messages -->\r\n <div class=\"bbsf-validation-msg text-center\" *ngIf=\"validationMessage\" [innerHTML]=\"validationMessage\">\r\n </div>\r\n\r\n <div class=\"bbsf-validation-msg text-center text-danger\"\r\n *ngIf=\"validationCountMessage && options.isMultipleFile && options.maxNoOfFiles > 0\"\r\n [innerHTML]=\"validationCountMessage\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden file input -->\r\n <input ng2FileSelect [uploader]=\"uploader\" [accept]=\"acceptedType\"\r\n class=\"fileSelector customFileUploadPlacment hidden v-required-multiplefiles d-none\"\r\n [attr.multiple]=\"options.isMultipleFile ? 'multiple' : null\" name=\"file\" type=\"file\" autocomplete=\"off\"\r\n (change)=\"onFileChange()\" [ngClass]=\"options.viewType === 1 ? '' : 'col-md-9'\" [id]=\"options.name\" #fileInput\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\" />\r\n </div>\r\n <!-- Read-only state with no files -->\r\n <div *ngIf=\"options.isReadonly && (!options.value || (uploader.queue && uploader.queue.length === 0))\">\r\n <span class=\"readonly-view\">{{ utilityService.getResourceValue('NA') }}</span>\r\n </div>\r\n </div>\r\n <!-- Uploaded files list -->\r\n <div class=\"uploaded-items\" *ngIf=\"shouldShowFileList()\">\r\n <div class=\"btn-group\" *ngFor=\"let item of uploader.queue; trackBy: trackByFunction\">\r\n\r\n <!-- Async upload completed files -->\r\n <ng-container *ngIf=\"item?.progress === 100 && options.isUploadFileAsync\">\r\n <!-- Download link - always visible -->\r\n <button *ngIf=\"getFileDownloadUrl(item); else noUrlTemplate\" type=\"button\"\r\n class=\"btn-download-file btn-sm btn-progress-upload\" (click)=\"downloadFile(item)\"\r\n [title]=\"'Download ' + getFileName(item)\">\r\n <span class=\"file-name\">{{ getFileName(item) }}</span>\r\n </button>\r\n\r\n <!-- File name display when no URL available -->\r\n <ng-template #noUrlTemplate>\r\n <span class=\"btn-download-file btn-sm btn-progress-upload\" [title]=\"getFileName(item)\">\r\n <span class=\"file-name\">{{ getFileName(item) }}</span>\r\n </span>\r\n </ng-template>\r\n\r\n <!-- Remove button - only show when not readonly and not disabled -->\r\n <button *ngIf=\"isRemoveEnabled()\" class=\"btn btn-download-file btn-sm\" type=\"button\"\r\n (click)=\"item.remove(); removeFromControlValue(item)\" [attr.aria-label]=\"'Remove ' + getFileName(item)\"\r\n [title]=\"'Remove ' + getFileName(item)\">\r\n <!-- Delete icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M9.33301 3.70584V3.26663C9.33301 2.65166 9.33301 2.34419 9.20587 2.1093C9.09405 1.9027 8.91555 1.73471 8.69604 1.62944C8.44647 1.50977 8.11977 1.50977 7.46638 1.50977H6.53305C5.87965 1.50977 5.55296 1.50977 5.30339 1.62944C5.08387 1.73471 4.90539 1.9027 4.79354 2.1093C4.66638 2.34419 4.66638 2.65166 4.66638 3.26663V3.70584\"\r\n stroke=\"#D83731\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path\r\n d=\"M1.75 3.70605H12.25M11.0834 3.70605V9.8551C11.0834 10.7775 11.0834 11.2387 10.8926 11.591C10.7248 11.901 10.4571 12.1529 10.1278 12.3109C9.75345 12.4904 9.26345 12.4904 8.28334 12.4904H5.71666C4.73658 12.4904 4.24653 12.4904 3.87218 12.3109C3.5429 12.1529 3.27519 11.901 3.10741 11.591C2.91666 11.2387 2.91666 10.7775 2.91666 9.8551V3.70605\"\r\n stroke=\"#D83731\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n </ng-container>\r\n\r\n <!-- Sync upload files -->\r\n <ng-container *ngIf=\"!options.isUploadFileAsync\">\r\n <!-- Download link - always visible -->\r\n <button type=\"button\" class=\"btn btn-download-file btn-sm\" (click)=\"downloadFile(item)\"\r\n [title]=\"'Download ' + getFileName(item)\">\r\n <!-- Download icon -->\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path\r\n d=\"M21 22H3C2.4 22 2 21.6 2 21C2 20.4 2.4 20 3 20H21C21.6 20 22 20.4 22 21C22 21.6 21.6 22 21 22ZM13 13.4V3C13 2.4 12.6 2 12 2C11.4 2 11 2.4 11 3V13.4H13Z\"\r\n fill=\"currentColor\"></path>\r\n <path opacity=\"0.3\" d=\"M7 13.4H17L12.7 17.7C12.3 18.1 11.7 18.1 11.3 17.7L7 13.4Z\" fill=\"currentColor\">\r\n </path>\r\n </svg>\r\n <span class=\"file-name\">{{ getFileName(item) }}</span>\r\n </button>\r\n\r\n <!-- Remove button - only show when not readonly and not disabled -->\r\n <button *ngIf=\"isRemoveEnabled()\" class=\"btn btn-download-file btn-sm btn-danger\" type=\"button\"\r\n (click)=\"item.remove(); removeFromControlValue(item)\" [attr.aria-label]=\"'Remove ' + getFileName(item)\"\r\n [title]=\"'Remove ' + getFileName(item)\">\r\n <i class=\"fa fa-times px-0\" aria-hidden=\"true\"></i>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <!-- File upload progress indicators -->\r\n <div *ngFor=\"let item of uploader.queue; trackBy: trackByFunction\">\r\n <div class=\"upload-items\" [ngClass]=\"{ 'mt-4': options.isMultipleFile }\"\r\n *ngIf=\"item?.progress < 100 && options.isUploadFileAsync && !options.isReadonly\">\r\n\r\n <div class=\"upload-items-toolbar\">\r\n <h4>{{ getFileName(item) }}</h4>\r\n <button *ngIf=\"isRemoveEnabled()\" type=\"button\" class=\"btn-cancel-upload\"\r\n (click)=\"item.remove(); removeFromControlValue(item)\"\r\n [attr.aria-label]=\"'Cancel upload for ' + getFileName(item)\">\r\n <!-- Cancel icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\">\r\n <g clip-path=\"url(#clip0_1324_13216)\">\r\n <path opacity=\"0.4\"\r\n d=\"M9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5Z\"\r\n stroke=\"#DBE1F0\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M11.25 6.75L6.75 11.25M6.75 6.75L11.25 11.25\" stroke=\"#DBE1F0\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </g>\r\n <defs>\r\n <clipPath id=\"clip0_1324_13216\">\r\n <rect width=\"18\" height=\"18\" fill=\"white\" />\r\n </clipPath>\r\n </defs>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"progress\">\r\n <div class=\"progress-bar\" role=\"progressbar\" [attr.aria-valuenow]=\"item?.progress\" aria-valuemin=\"0\"\r\n aria-valuemax=\"100\" [class.file-uploaded]=\"item?.progress < 100\" [style.width.%]=\"item?.progress\"\r\n *ngIf=\"item?.progress > 0\">\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Validation and description section -->\r\n <div class=\"subtext-container\" *ngIf=\"!options.isReadonly\">\r\n <!-- Validation messages -->\r\n <div class=\"bbsf-validation\" *ngIf=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\">\r\n <span [innerHTML]=\"getErrorValidation(fileUploadFormControl.errors | keyvalue)\"></span>\r\n </div>\r\n\r\n <!-- Control description -->\r\n <div class=\"bbsf-control-desc\" *ngIf=\"options.labelDescription\">\r\n {{ options.labelDescription }}\r\n </div>\r\n\r\n <!-- Reset error state -->\r\n <div *ngIf=\"(group.valid && group.dirty && group.touched) || (group.untouched && group.invalid && group.dirty)\">\r\n {{ resetError() }}\r\n </div>\r\n </div>\r\n</div>" }]
573
+ args: [{ selector: 'BBSF-FileUpload', standalone: false, template: "<div class=\"form-group bbsf-control bbsf-file-upload\" [formGroup]=\"group\">\r\n <div [ngClass]=\"options.viewType == 1 ? 'bbsf-vertical' : 'bbsf-horizontal'\">\r\n <!--label-->\r\n <label [hidden]=\"options.hideLabel\" class=\"bbsf-label {{ options.labelExtraClasses }}\">\r\n {{ options.labelValue }}\r\n <!--Asterisk-->\r\n <span *ngIf=\"((options.showAsterisk && options.isRequired) || options.isRequired) && !options.isReadonly\"\r\n class=\"text-danger\">*</span>\r\n </label>\r\n <!--Allow dropZone-->\r\n <div ng2FileDrop class=\"bbsf-input-container {{ options.extraClasses }}\"\r\n *ngIf=\"options.isDropZone && !(options.isMultipleFile == false && uploader.queue.length > 0) && !options.isReadonly\"\r\n [ngClass]=\"{ 'another-file-over-class': hasAnotherDropZoneOver }\" (onFileDrop)=\"onFileChange()\"\r\n (fileOver)=\"fileOverAnother($event)\" [uploader]=\"uploader\" [accept]=\"acceptedType\" id=\"{{ options.name }}\"\r\n multiple=\"{{ options.isMultipleFile ? 'multiple' : '' }}\" aria-describedby=\"email-error\" aria-invalid=\"true\"\r\n type=\"file\" #fileInput [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\"\r\n (click)=\"fileInputControl.click()\">\r\n <div class=\"dropzone-label\">\r\n <div class=\"svg-and-validation\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"70\" height=\"70\" viewBox=\"0 0 70 70\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M58.333 48.8332C61.8957 45.8908 64.1663 41.4397 64.1663 36.4583C64.1663 27.5988 56.9843 20.4167 48.1247 20.4167C47.4874 20.4167 46.8912 20.0842 46.5675 19.5351C42.7641 13.0808 35.7417 8.75 27.708 8.75C15.6268 8.75 5.83301 18.5438 5.83301 30.625C5.83301 36.6511 8.26974 42.1082 12.2116 46.0644\"\r\n stroke=\"#4B5489\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M23.333 46.6667L34.9997 35M34.9997 35L46.6663 46.6667M34.9997 35V61.25\" stroke=\"#4B5489\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n <!--Validation text-->\r\n <div class=\"bbsf-validation-msg validation-msg-header text-center\">\r\n {{ UtilityService.getResourceValue('DragAndDropHere') }}\r\n </div>\r\n <div class=\"bbsf-validation-msg text-center\" *ngIf=\"validationMessage\" [innerHTML]=\"validationMessage\"></div>\r\n <div class=\"bbsf-validation-msg ng-star-inserted text-center text-danger\"\r\n *ngIf=\"validationCountMessage && options.isMultipleFile && options.maxNoOfFiles > 0\"\r\n [innerHTML]=\"validationCountMessage\"></div>\r\n </div>\r\n </div>\r\n <input ng2FileSelect [uploader]=\"uploader\" [accept]=\"acceptedType\"\r\n class=\"fileSelector customFileUploadPlacment hidden v-required-multiplefiles d-none\"\r\n multiple=\"{{ options.isMultipleFile ? 'multiple' : '' }}\" name=\"file\" type=\"file\" value=\"\" autocomplete=\"off\"\r\n (change)=\"onFileChange()\" [ngClass]=\"options.viewType == 1 ? '' : 'col-md-9'\" id=\"{{ options.name }}\"\r\n aria-describedby=\"email-error\" aria-invalid=\"true\" formControlName=\"{{ options.name }}\" #fileInputControl\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\" />\r\n </div>\r\n <!--Not allowed dropZone-->\r\n <div class=\"bbsf-input-container\" *ngIf=\"!options.isDropZone && !isHideInput() && !options.isReadonly\"\r\n (click)=\"fileInput.click()\">\r\n <div class=\"dropzone-label\">\r\n <div class=\"svg-and-validation\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"70\" height=\"70\" viewBox=\"0 0 70 70\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M58.333 48.8332C61.8957 45.8908 64.1663 41.4397 64.1663 36.4583C64.1663 27.5988 56.9843 20.4167 48.1247 20.4167C47.4874 20.4167 46.8912 20.0842 46.5675 19.5351C42.7641 13.0808 35.7417 8.75 27.708 8.75C15.6268 8.75 5.83301 18.5438 5.83301 30.625C5.83301 36.6511 8.26974 42.1082 12.2116 46.0644\"\r\n stroke=\"#4B5489\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M23.333 46.6667L34.9997 35M34.9997 35L46.6663 46.6667M34.9997 35V61.25\" stroke=\"#4B5489\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n <!--Validation text-->\r\n <div class=\"bbsf-validation-msg text-center\">{{ UtilityService.getResourceValue('Upload') }}</div>\r\n <div class=\"bbsf-validation-msg text-center\" *ngIf=\"validationMessage\" [innerHTML]=\"validationMessage\"></div>\r\n <div class=\"bbsf-validation-msg ng-star-inserted text-center text-danger\"\r\n *ngIf=\"validationCountMessage && options.isMultipleFile && options.maxNoOfFiles > 0\"\r\n [innerHTML]=\"validationCountMessage\"></div>\r\n </div>\r\n </div>\r\n <input ng2FileSelect [uploader]=\"uploader\" [accept]=\"acceptedType\"\r\n class=\"fileSelector customFileUploadPlacment hidden v-required-multiplefiles d-none\"\r\n multiple=\"{{ options.isMultipleFile ? 'multiple' : '' }}\" name=\"file\" type=\"file\" value=\"\" autocomplete=\"off\"\r\n (change)=\"onFileChange()\" [ngClass]=\"options.viewType == 1 ? '' : 'col-md-9'\" id=\"{{ options.name }}\"\r\n aria-describedby=\"email-error\" aria-invalid=\"true\" formControlName=\"{{ options.name }}\" #fileInput\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\" />\r\n </div>\r\n <!-- readonly -->\r\n <div *ngIf=\"options.isReadonly && !options.value\">\r\n <span class=\"readonly-view\">{{ UtilityService.getResourceValue('NA') }}</span>\r\n </div>\r\n </div>\r\n <!--items uploaded-->\r\n <div class=\"uploaded-items\">\r\n <div class=\"btn-group\" *ngFor=\"let item of uploader.queue\">\r\n <ng-container *ngIf=\"item?.progress == 100 && options.isUploadFileAsync\">\r\n <a *ngIf=\"item?.file?.rawFile['url']\" href=\"{{ item?.file?.rawFile['url'] }}\"\r\n class=\"btn-download-file btn-sm btn-progress-upload\" download>\r\n <span class=\"file-name\">{{ item?.file?.name }}</span>\r\n </a>\r\n <a *ngIf=\"item?.file?.rawFile['url'] == null\" class=\"btn-download-file btn-sm btn-progress-upload\">\r\n <span class=\"file-name\">{{ item?.file?.name }}</span>\r\n </a>\r\n <button *ngIf=\"!options.isReadonly\" class=\"btn btn-download-file btn-sm\"\r\n (click)=\"item.remove(); removeFromControlValue(item)\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M9.33301 3.70584V3.26663C9.33301 2.65166 9.33301 2.34419 9.20587 2.1093C9.09405 1.9027 8.91555 1.73471 8.69604 1.62944C8.44647 1.50977 8.11977 1.50977 7.46638 1.50977H6.53305C5.87965 1.50977 5.55296 1.50977 5.30339 1.62944C5.08387 1.73471 4.90539 1.9027 4.79354 2.1093C4.66638 2.34419 4.66638 2.65166 4.66638 3.26663V3.70584\"\r\n stroke=\"#D83731\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path\r\n d=\"M1.75 3.70605H12.25M11.0834 3.70605V9.8551C11.0834 10.7775 11.0834 11.2387 10.8926 11.591C10.7248 11.901 10.4571 12.1529 10.1278 12.3109C9.75345 12.4904 9.26345 12.4904 8.28334 12.4904H5.71666C4.73658 12.4904 4.24653 12.4904 3.87218 12.3109C3.5429 12.1529 3.27519 11.901 3.10741 11.591C2.91666 11.2387 2.91666 10.7775 2.91666 9.8551V3.70605\"\r\n stroke=\"#D83731\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n </ng-container>\r\n <ng-container *ngIf=\"!options.isUploadFileAsync\">\r\n <a href=\"{{ item?.file?.rawFile['url'] }}\" class=\"btn btn-download-file btn-sm\" download>\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path\r\n d=\"M21 22H3C2.4 22 2 21.6 2 21C2 20.4 2.4 20 3 20H21C21.6 20 22 20.4 22 21C22 21.6 21.6 22 21 22ZM13 13.4V3C13 2.4 12.6 2 12 2C11.4 2 11 2.4 11 3V13.4H13Z\"\r\n fill=\"currentColor\"></path>\r\n <path opacity=\"0.3\" d=\"M7 13.4H17L12.7 17.7C12.3 18.1 11.7 18.1 11.3 17.7L7 13.4Z\" fill=\"currentColor\">\r\n </path>\r\n </svg>\r\n <span class=\"file-name\">{{ item?.file?.name }}</span>\r\n </a>\r\n <button *ngIf=\"!options.isReadonly\" class=\"btn btn-download-file btn-sm btn-danger\"\r\n (click)=\"item.remove(); removeFromControlValue(item)\">\r\n <i class=\"fa fa-times px-0\"></i>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <!--progress bar file upload-->\r\n <div *ngFor=\"let item of uploader.queue\">\r\n <div class=\"upload-items\" [ngClass]=\"{ 'mt-4': options.isMultipleFile == true }\"\r\n *ngIf=\"item?.progress < 100 && options.isUploadFileAsync\">\r\n <div class=\"upload-items-toolbar\">\r\n <h4>{{ item?.file?.name }}</h4>\r\n <span (click)=\"item.remove(); removeFromControlValue(item)\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\">\r\n <g clip-path=\"url(#clip0_1324_13216)\">\r\n <path opacity=\"0.4\"\r\n d=\"M9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5Z\"\r\n stroke=\"#DBE1F0\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M11.25 6.75L6.75 11.25M6.75 6.75L11.25 11.25\" stroke=\"#DBE1F0\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </g>\r\n <defs>\r\n <clipPath id=\"clip0_1324_13216\">\r\n <rect width=\"18\" height=\"18\" fill=\"white\" />\r\n </clipPath>\r\n </defs>\r\n </svg>\r\n </span>\r\n </div>\r\n <div class=\"progress\">\r\n <div class=\"progress-bar\" role=\"progressbar\" aria-valuenow=\"70\" aria-valuemin=\"0\" aria-valuemax=\"100\"\r\n [class.file-uploaded]=\"item?.progress < 100\" [style.width.%]=\"item?.progress\" *ngIf=\"item?.progress > 0\">\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"subtext-container\" *ngIf=\"!options.isReadonly\">\r\n <!-- required text-->\r\n <div class=\"bbsf-validation\" *ngIf=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\">\r\n {{ getErrorValidation(fileUploadFormControl.errors | keyvalue) }}\r\n </div>\r\n <!-- LabelDescription-->\r\n <div class=\"bbsf-control-desc\" *ngIf=\"options.labelDescription != null\">{{ options.labelDescription }}</div>\r\n <div *ngIf=\"(group.valid && group.dirty && group.touched) || (group.untouched && group.invalid && group.dirty)\">\r\n {{ resetError() }}\r\n </div>\r\n </div>\r\n</div>" }]
1080
574
  }], ctorParameters: () => [{ type: i1.ControlContainer, decorators: [{
1081
575
  type: Optional
1082
576
  }] }, { type: i1.FormGroupDirective }, { type: i2.ControlUtility }, { type: i3.UtilityService }, { type: i3.ControlValidationService }, { type: i4.GlobalSettings }, { type: i5.FileUploadService }], propDecorators: { fileInput: [{
@@ -1091,4 +585,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
1091
585
  }], isUploadComplete: [{
1092
586
  type: Output
1093
587
  }] } });
1094
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmlsZVVwbG9hZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9iYnNmLWNvbnRyb2xzL3NyYy9saWIvY29udHJvbHMvRmlsZVVwbG9hZC9GaWxlVXBsb2FkLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Jic2YtY29udHJvbHMvc3JjL2xpYi9jb250cm9scy9GaWxlVXBsb2FkL0ZpbGVVcGxvYWQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFJVCxLQUFLLEVBQ0wsUUFBUSxFQUNSLFNBQVMsRUFFVCxNQUFNLEVBQ04sWUFBWSxFQUNiLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFDTCxXQUFXLEVBQ1gsVUFBVSxFQU1YLE1BQU0sZ0JBQWdCLENBQUM7QUFHeEIsT0FBTyxFQUFFLFlBQVksRUFBaUQsTUFBTSxpQkFBaUIsQ0FBQztBQUM5RixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDdEUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sNkNBQTZDLENBQUM7QUFLdEYsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxNQUFNLENBQUM7Ozs7Ozs7OztBQWdEcEMsTUFBTSxPQUFPLG1CQUFtQjthQUNmLDJCQUFzQixHQUE0QixJQUFJLEFBQWhDLENBQWlDO0lBbUN0RSxZQUNzQixnQkFBa0MsRUFDL0MsNkJBQWlELEVBQ2hELGNBQThCLEVBQy9CLGNBQThCLEVBQzdCLHdCQUFrRCxFQUNsRCxjQUE4QixFQUM5QixpQkFBb0M7UUFOeEIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUMvQyxrQ0FBNkIsR0FBN0IsNkJBQTZCLENBQW9CO1FBQ2hELG1CQUFjLEdBQWQsY0FBYyxDQUFn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dUJBQUMsV0FBVyxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFHaEMsS0FBSztzQkFBYixLQUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSztnQkFDSSxRQUFRO3NCQUFqQixNQUFNO2dCQUNHLGdCQUFnQjtzQkFBekIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgQ29tcG9uZW50LFxyXG4gIE9uSW5pdCxcclxuICBBZnRlclZpZXdJbml0LFxyXG4gIE9uRGVzdHJveSxcclxuICBJbnB1dCxcclxuICBPcHRpb25hbCxcclxuICBWaWV3Q2hpbGQsXHJcbiAgRWxlbWVudFJlZixcclxuICBPdXRwdXQsXHJcbiAgRXZlbnRFbWl0dGVyXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7XHJcbiAgRm9ybUNvbnRyb2wsXHJcbiAgVmFsaWRhdG9ycyxcclxuICBGb3JtR3JvdXAsXHJcbiAgQWJzdHJhY3RDb250cm9sLFxyXG4gIENvbnRyb2xDb250YWluZXIsXHJcbiAgRm9ybUdyb3VwRGlyZWN0aXZlLFxyXG4gIFZhbGlkYXRvckZuXHJcbn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgeyBGaWxlVXBsb2FkT3B0aW9ucyB9IGZyb20gJy4uLy4uL1NoYXJlZC9Nb2RlbHMvRmlsZVVwbG9hZE9wdGlvbnMnO1xyXG5pbXBvcnQgeyBDb250cm9sVXRpbGl0eSB9IGZyb20gJy4uLy4uL1NoYXJlZC9zZXJ2aWNlcy9Db250cm9sVXRpbGl0eSc7XHJcbmltcG9ydCB7IEZpbGVVcGxvYWRlciwgRmlsZUxpa2VPYmplY3QsIEZpbGVVcGxvYWRlck9wdGlvbnMsIEZpbGVJdGVtIH0gZnJvbSAnbmcyLWZpbGUtdXBsb2FkJztcclxuaW1wb3J0IHsgRmlsZVVwbG9hZE1vZGVsIH0gZnJvbSAnLi4vLi4vU2hhcmVkL01vZGVscy9GaWxlVXBsb2FkTW9kZWwnO1xyXG5pbXBvcnQgeyBNdWx0aXBsZUZpbGVVcGxvYWRNb2RlbCB9IGZyb20gJy4uLy4uL1NoYXJlZC9Nb2RlbHMvTXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwnO1xyXG5pbXBvcnQgeyBDb250cm9sVmFsaWRhdGlvblNlcnZpY2UsIFV0aWxpdHlTZXJ2aWNlIH0gZnJvbSAnQGJuc2lnaHRzL2Jic2YtdXRpbGl0aWVzJztcclxuaW1wb3J0IHsgR2xvYmFsU2V0dGluZ3MgfSBmcm9tICcuLi8uLi9TaGFyZWQvc2VydmljZXMvR2xvYmFsU2V0dGluZ3Muc2VydmljZSc7XHJcbmltcG9ydCB7IEZpbGVEVE8gfSBmcm9tICcuLi8uLi9TaGFyZWQvTW9kZWxzL0ZpbGVEVE8nO1xyXG5pbXBvcnQgeyBGaWxlVXBsb2FkU2VydmljZSB9IGZyb20gJy4uLy4uL1NoYXJlZC9zZXJ2aWNlcy9maWxlLXVwbG9hZC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgSHR0cEV2ZW50VHlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcclxuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XHJcbmludGVyZmFjZSBGaWxlSXRlbUV4dGVuZGVkIGV4dGVuZHMgRmlsZUl0ZW0ge1xyXG4gIF9maWxlOiBGaWxlRXh0ZW5kZWQ7XHJcbn1cclxuXHJcbmludGVyZmFjZSBGaWxlRXh0ZW5kZWQgZXh0ZW5kcyBGaWxlIHtcclxuICBpRF9HVUlEPzogc3RyaW5nO1xyXG4gIGlzTmV3PzogYm9vbGVhbjtcclxuICB1cmw/OiBzdHJpbmc7XHJcbiAgcmF3RmlsZT86IEZpbGU7XHJcbn1cclxuXHJcbmludGVyZmFjZSBGaWxlVmFsaWRhdGlvblJlc3VsdCB7XHJcbiAgaXNWYWxpZDogYm9vbGVhbjtcclxuICBlcnJvcnM6IHN0cmluZ1tdO1xyXG4gIGludmFsaWRGaWxlczogRmlsZUl0ZW1bXTtcclxufVxyXG5cclxuaW50ZXJmYWNlIEZpbGVQcm9jZXNzaW5nUmVzdWx0IHtcclxuICB2YWxpZEZpbGVzOiBGaWxlSXRlbVtdO1xyXG4gIGludmFsaWRGaWxlczogRmlsZUl0ZW1bXTtcclxuICBlcnJvcnM6IHN0cmluZ1tdO1xyXG59XHJcblxyXG5pbnRlcmZhY2UgRG93bmxvYWRJbmZvIHtcclxuICB1cmw6IHN0cmluZyB8IG51bGw7XHJcbiAgZmlsZU5hbWU6IHN0cmluZztcclxufVxyXG5cclxuaW50ZXJmYWNlIFVwbG9hZFByb2dyZXNzRXZlbnQge1xyXG4gIGxvYWRlZDogbnVtYmVyO1xyXG4gIHRvdGFsOiBudW1iZXI7XHJcbiAgdHlwZTogbnVtYmVyO1xyXG59XHJcblxyXG5pbnRlcmZhY2UgVXBsb2FkQ29tcGxldGVFdmVudCB7XHJcbiAgYm9keToge1xyXG4gICAgdmFsOiBzdHJpbmc7XHJcbiAgICBkb3dubG9hZFVybD86IHN0cmluZztcclxuICB9O1xyXG4gIHR5cGU6IG51bWJlcjtcclxufVxyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdCQlNGLUZpbGVVcGxvYWQnLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9GaWxlVXBsb2FkLmNvbXBvbmVudC5odG1sJyxcclxuICBzdGFuZGFsb25lOiBmYWxzZVxyXG59KVxyXG5leHBvcnQgY2xhc3MgRmlsZVVwbG9hZENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcclxuICBwcml2YXRlIHN0YXRpYyBjb250cm9sQ29udGFpbmVyU3RhdGljOiBDb250cm9sQ29udGFpbmVyIHwgbnVsbCA9IG51bGw7XHJcblxyXG4gIHByaXZhdGUgcmVhZG9ubHkgQllURVNfVE9fTUIgPSAxMDI0ICogMTAyNDtcclxuICBwcml2YXRlIHJlYWRvbmx5IFBST0dSRVNTX0NPTVBMRVRFID0gMTAwO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgUFJPR1JFU1NfTkVBUl9DT01QTEVURSA9IDk1O1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgRVJST1JfRElTUExBWV9EVVJBVElPTiA9IDUwMDA7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBNQVhfTUVNT1JZX1VTQUdFID0gMTAwICogMTAyNCAqIDEwMjQ7IC8vIDEwME1CIGxpbWl0XHJcbiAgcHJpdmF0ZSBjdXJyZW50TWVtb3J5VXNhZ2UgPSAwO1xyXG5cclxuICBAVmlld0NoaWxkKCdmaWxlSW5wdXQnLCB7IHN0YXRpYzogZmFsc2UgfSkgZmlsZUlucHV0ITogRWxlbWVudFJlZjxIVE1MSW5wdXRFbGVtZW50PjtcclxuXHJcbiAgaXNTdWJtaXR0ZWQgPSBmYWxzZTtcclxuICBASW5wdXQoKSBncm91cCE6IEZvcm1Hcm91cDtcclxuICBASW5wdXQoKSBvcHRpb25zITogRmlsZVVwbG9hZE9wdGlvbnM7XHJcbiAgQE91dHB1dCgpIE9uQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcbiAgQE91dHB1dCgpIGlzVXBsb2FkQ29tcGxldGUgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7XHJcblxyXG4gIGZpbGVVcGxvYWRGb3JtQ29udHJvbCE6IEFic3RyYWN0Q29udHJvbDtcclxuICB2YWxpZGF0aW9uTWVzc2FnZSA9ICcnO1xyXG4gIHZhbGlkYXRpb25Db3VudE1lc3NhZ2UgPSAnJztcclxuICB1cGxvYWRlciE6IEZpbGVVcGxvYWRlcjtcclxuICBoYXNBbm90aGVyRHJvcFpvbmVPdmVyID0gZmFsc2U7XHJcbiAgYWNjZXB0ZWRUeXBlID0gJyc7XHJcbiAgYWNjZXB0ZWRUeXBlQXJyYXk6IHN0cmluZ1tdID0gW107XHJcbiAgdG9vbFRpcFR5cGVBcnJheTogc3RyaW5nW10gPSBbXTtcclxuICBmaWxlTGlrZU9iamVjdCE6IEZpbGVMaWtlT2JqZWN0O1xyXG4gIG1hcmtBbGxBc1RvdWNoZWQgPSBmYWxzZTtcclxuICB2YWxpZGF0aW9uUnVsZXM6IFZhbGlkYXRvckZuW10gPSBbXTtcclxuICB2YWxpZGF0aW9uUnVsZXNBc3luYzogVmFsaWRhdG9yRm5bXSA9IFtdO1xyXG4gIGZpbGVVcGxvYWRNb2RlbCE6IEZpbGVVcGxvYWRNb2RlbDtcclxuICBtdWx0aXBsZUZpbGVVcGxvYWRNb2RlbCE6IE11bHRpcGxlRmlsZVVwbG9hZE1vZGVsO1xyXG4gIGZpbGU6IEZpbGVEVE8gfCBudWxsID0gbnVsbDtcclxuICBkZWxldGVkRmlsZXM6IEZpbGVEVE9bXSA9IFtdO1xyXG4gIHByaXZhdGUgc3Vic2NyaXB0aW9ucyA9IG5ldyBTdWJzY3JpcHRpb24oKTtcclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBAT3B0aW9uYWwoKSBwcml2YXRlIGNvbnRyb2xDb250YWluZXI6IENvbnRyb2xDb250YWluZXIsXHJcbiAgICBwdWJsaWMgbXVsdGlwbGVGaWxlVXBsb2FkQ29udHJvbEhvc3Q6IEZvcm1Hcm91cERpcmVjdGl2ZSxcclxuICAgIHByaXZhdGUgY29udHJvbFV0aWxpdHk6IENvbnRyb2xVdGlsaXR5LFxyXG4gICAgcHVibGljIHV0aWxpdHlTZXJ2aWNlOiBVdGlsaXR5U2VydmljZSxcclxuICAgIHByaXZhdGUgY29udHJvbFZhbGlkYXRpb25TZXJ2aWNlOiBDb250cm9sVmFsaWRhdGlvblNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGdsb2JhbFNldHRpbmdzOiBHbG9iYWxTZXR0aW5ncyxcclxuICAgIHByaXZhdGUgZmlsZVVwbG9hZFNlcnZpY2U6IEZpbGVVcGxvYWRTZXJ2aWNlXHJcbiAgKSB7XHJcbiAgICBGaWxlVXBsb2FkQ29tcG9uZW50LmNvbnRyb2xDb250YWluZXJTdGF0aWMgPSB0aGlzLmNvbnRyb2xDb250YWluZXI7XHJcbiAgICB0aGlzLmluaXRpYWxpemVVcGxvYWRlcigpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBpbml0aWFsaXplVXBsb2FkZXIoKTogdm9pZCB7XHJcbiAgICB0aGlzLnVwbG9hZGVyID0gbmV3IEZpbGVVcGxvYWRlcih7XHJcbiAgICAgIGRpc2FibGVNdWx0aXBhcnQ6IGZhbHNlXHJcbiAgICB9IGFzIEZpbGVVcGxvYWRlck9wdGlvbnMpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkluaXQoKTogdm9pZCB7XHJcbiAgICB0aGlzLmluaXRpYWxpemVNb2RlbHMoKTtcclxuICAgIHRoaXMuc2V0Vmlld1R5cGUoKTtcclxuICAgIHRoaXMucHJvY2Vzc0luaXRpYWxWYWx1ZSgpO1xyXG4gICAgdGhpcy5zZXR1cExhYmVscygpO1xyXG4gICAgdGhpcy5zZXR1cEZpbGVUeXBlVmFsaWRhdGlvbigpO1xyXG4gICAgdGhpcy5zZXR1cEZvcm1Db250cm9sKCk7XHJcbiAgICB0aGlzLnNldHVwU3Vic2NyaXB0aW9ucygpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBpbml0aWFsaXplTW9kZWxzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5maWxlVXBsb2FkTW9kZWwgPSBuZXcgRmlsZVVwbG9hZE1vZGVsKCk7XHJcbiAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsID0gbmV3IE11bHRpcGxlRmlsZVVwbG9hZE1vZGVsKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldFZpZXdUeXBlKCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMudmlld1R5cGUpIHtcclxuICAgICAgdGhpcy5vcHRpb25zLnZpZXdUeXBlID0gdGhpcy5nbG9iYWxTZXR0aW5ncy52aWV3VHlwZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgcHJvY2Vzc0luaXRpYWxWYWx1ZSgpOiB2b2lkIHtcclxuXHJcbiAgICBpZiAodGhpcy5vcHRpb25zLnZhbHVlID09IG51bGwpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLm9wdGlvbnMuaXNNdWx0aXBsZUZpbGUpIHtcclxuICAgICAgdGhpcy5wcm9jZXNzTXVsdGlwbGVGaWxlVmFsdWUoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMucHJvY2Vzc1NpbmdsZUZpbGVWYWx1ZSgpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMudXBsb2FkZXIucXVldWUuZm9yRWFjaCgoZWxlbWVudCkgPT4ge1xyXG4gICAgICBlbGVtZW50LnByb2dyZXNzID0gdGhpcy5QUk9HUkVTU19DT01QTEVURTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBwcm9jZXNzTXVsdGlwbGVGaWxlVmFsdWUoKTogdm9pZCB7XHJcbiAgICBjb25zdCBmaWxlczogRmlsZUxpa2VPYmplY3RbXSA9IFtdO1xyXG4gICAgdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbC5leGlzdGluZ0ZpbGVzID0gdGhpcy5vcHRpb25zLnZhbHVlLmV4aXN0aW5nRmlsZXM7XHJcbiAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLnVwbG9hZGVkRmlsZXMgPSBbXTtcclxuXHJcbiAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgdGhpcy5vcHRpb25zLnZhbHVlLmV4aXN0aW5nRmlsZXMpIHtcclxuICAgICAgY29uc3QgZmlsZUxpa2VPYmplY3QgPSB0aGlzLmNyZWF0ZUZpbGVMaWtlT2JqZWN0KGVsZW1lbnQpO1xyXG4gICAgICBmaWxlcy5wdXNoKGZpbGVMaWtlT2JqZWN0KTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnVwbG9hZGVyLmFkZFRvUXVldWUoZmlsZXMgYXMgYW55KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcHJvY2Vzc1NpbmdsZUZpbGVWYWx1ZSgpOiB2b2lkIHtcclxuICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLm9wdGlvbnMudmFsdWUuZmlsZSA/PyB0aGlzLm9wdGlvbnMudmFsdWU7XHJcbiAgICBjb25zdCBmaWxlTGlrZU9iamVjdCA9IHRoaXMuY3JlYXRlRmlsZUxpa2VPYmplY3QoZWxlbWVudCk7XHJcbiAgICB0aGlzLmZpbGUgPSBlbGVtZW50O1xyXG4gICAgdGhpcy51cGxvYWRlci5hZGRUb1F1ZXVlKFtmaWxlTGlrZU9iamVjdF0gYXMgYW55KTtcclxuXHJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy52YWx1ZS5maWxlKSB7XHJcbiAgICAgIHRoaXMuZmlsZVVwbG9hZE1vZGVsID0gbmV3IEZpbGVVcGxvYWRNb2RlbCgpO1xyXG4gICAgICB0aGlzLmZpbGVVcGxvYWRNb2RlbC5maWxlID0gdGhpcy5vcHRpb25zLnZhbHVlO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5maWxlVXBsb2FkTW9kZWwgPSB0aGlzLm9wdGlvbnMudmFsdWU7XHJcbiAgICB9XHJcbiAgICB0aGlzLm9wdGlvbnMudmFsdWUgPSB0aGlzLmZpbGVVcGxvYWRNb2RlbDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY3JlYXRlRmlsZUxpa2VPYmplY3QoZWxlbWVudDogRmlsZURUTyk6IGFueSB7XHJcbiAgICBjb25zdCBieXRlcyA9IG5ldyBVaW50OEFycmF5KGVsZW1lbnQuYnl0ZXMpO1xyXG4gICAgY29uc3QgYmFzZTY0ID0gYnRvYShTdHJpbmcuZnJvbUNoYXJDb2RlKC4uLmJ5dGVzKSk7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBuYW1lOiBlbGVtZW50Lm5hbWVXaXRoRXh0ZW5zaW9uIHx8IGVsZW1lbnQuZmlsZU5hbWUsXHJcbiAgICAgIHR5cGU6IGVsZW1lbnQubWltZVR5cGUgfHwgZWxlbWVudC5maWxlVHlwZSxcclxuICAgICAgcmF3RmlsZTogYmFzZTY0LFxyXG4gICAgICBzaXplOiBlbGVtZW50LmZpbGVTaXplSW5NQiA/IGVsZW1lbnQuZmlsZVNpemVJbk1CICogdGhpcy5CWVRFU19UT19NQiA6IDAsXHJcbiAgICAgIGxhc3RNb2RpZmllZERhdGU6IG5ldyBEYXRlKCksXHJcbiAgICAgIHVybDogZWxlbWVudC5mdWxsRmlsZVVSTFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2V0dXBMYWJlbHMoKTogdm9pZCB7XHJcblxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5sYWJlbEtleSkge1xyXG4gICAgICB0aGlzLm9wdGlvbnMubGFiZWxWYWx1ZSA9IHRoaXMudXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSh0aGlzLm9wdGlvbnMubGFiZWxLZXkpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzZXR1cEZpbGVUeXBlVmFsaWRhdGlvbigpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5vcHRpb25zLmZpbGVVcGxvYWRBY2NlcHRzVHlwZXM/Lmxlbmd0aCkge1xyXG4gICAgICBjb25zb2xlLndhcm4oJ0ZpbGVVcGxvYWQ6IE5vIGZpbGUgdHlwZXMgc3BlY2lmaWVkIGluIGZpbGVVcGxvYWRBY2NlcHRzVHlwZXMnKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIHRyeSB7XHJcbiAgICAgIHRoaXMucHJvY2Vzc0FjY2VwdGVkVHlwZXMoKTtcclxuICAgICAgdGhpcy5idWlsZFZhbGlkYXRpb25NZXNzYWdlKCk7XHJcblxyXG4gICAgICAvLyBMb2cgdGhlIHByb2Nlc3NlZCB0eXBlcyBmb3IgZGVidWdnaW5nXHJcbiAgICAgIGNvbnNvbGUubG9nKCdGaWxlVXBsb2FkOiBQcm9jZXNzZWQgZmlsZSB0eXBlczonLCB7XHJcbiAgICAgICAgb3JpZ2luYWw6IHRoaXMub3B0aW9ucy5maWxlVXBsb2FkQWNjZXB0c1R5cGVzLFxyXG4gICAgICAgIHByb2Nlc3NlZDogdGhpcy5hY2NlcHRlZFR5cGVBcnJheSxcclxuICAgICAgICBhY2NlcHRBdHRyaWJ1dGU6IHRoaXMuYWNjZXB0ZWRUeXBlLFxyXG4gICAgICAgIGRpc3BsYXlUeXBlczogdGhpcy50b29sVGlwVHlwZUFycmF5XHJcbiAgICAgIH0pO1xyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgY29uc29sZS5lcnJvcignRmlsZVVwbG9hZDogRXJyb3IgcHJvY2Vzc2luZyBmaWxlIHR5cGVzOicsIGVycm9yKTtcclxuICAgICAgLy8gRmFsbGJhY2sgdG8gYWNjZXB0aW5nIGFsbCBmaWxlcyBpZiBwcm9jZXNzaW5nIGZhaWxzXHJcbiAgICAgIHRoaXMuYWNjZXB0ZWRUeXBlID0gJyc7XHJcbiAgICAgIHRoaXMuYWNjZXB0ZWRUeXBlQXJyYXkgPSBbXTtcclxuICAgICAgdGhpcy50b29sVGlwVHlwZUFycmF5ID0gW107XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHByb2Nlc3NBY2NlcHRlZFR5cGVzKCk6IHZvaWQge1xyXG4gICAgLy8gUHJvY2VzcyBlYWNoIGZpbGUgdHlwZSBhbmQgZXh0cmFjdCBpbmRpdmlkdWFsIE1JTUUgdHlwZXNcclxuICAgIGNvbnN0IGFsbE1pbWVUeXBlczogc3RyaW5nW10gPSBbXTtcclxuXHJcbiAgICBmb3IgKGNvbnN0IGZpbGVUeXBlIG9mIHRoaXMub3B0aW9ucy5maWxlVXBsb2FkQWNjZXB0c1R5cGVzKSB7XHJcbiAgICAgIGlmIChmaWxlVHlwZS5pbmNsdWRlcygnLCcpKSB7XHJcbiAgICAgICAgLy8gSGFuZGxlIHR5cGVzIGxpa2UgSW1hZ2VUeXBlcyB0aGF0IGNvbnRhaW4gbXVsdGlwbGUgTUlNRSB0eXBlc1xyXG4gICAgICAgIGNvbnN0IG1pbWVUeXBlcyA9IGZpbGVUeXBlLnNwbGl0KCcsJykubWFwKHR5cGUgPT4gdHlwZS50cmltKCkpO1xyXG4gICAgICAgIGFsbE1pbWVUeXBlcy5wdXNoKC4uLm1pbWVUeXBlcyk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8gU2luZ2xlIE1JTUUgdHlwZVxyXG4gICAgICAgIGFsbE1pbWVUeXBlcy5wdXNoKGZpbGVUeXBlKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIEZpbHRlciBvdXQgZW1wdHkgc3RyaW5ncyBhbmQgbm9ybWFsaXplIE1JTUUgdHlwZXNcclxuICAgIGNvbnN0IG5vcm1hbGl6ZWRNaW1lVHlwZXMgPSBhbGxNaW1lVHlwZXNcclxuICAgICAgLmZpbHRlcih0eXBlID0+IHR5cGUudHJpbSgpKVxyXG4gICAgICAubWFwKHR5cGUgPT4gdHlwZS50cmltKCkudG9Mb3dlckNhc2UoKSk7XHJcblxyXG4gICAgLy8gQ3JlYXRlIHRoZSBhY2NlcHQgYXR0cmlidXRlIHN0cmluZyBmb3IgSFRNTCBpbnB1dFxyXG4gICAgdGhpcy5hY2NlcHRlZFR5cGUgPSBub3JtYWxpemVkTWltZVR5cGVzLmpvaW4oJywnKTtcclxuXHJcbiAgICAvLyBTdG9yZSB0aGUgcHJvY2Vzc2VkIGFycmF5IGZvciB2YWxpZGF0aW9uIChrZWVwIG9yaWdpbmFsIGNhc2UgZm9yIGRpc3BsYXkpXHJcbiAgICB0aGlzLmFjY2VwdGVkVHlwZUFycmF5ID0gYWxsTWltZVR5cGVzLmZpbHRlcih0eXBlID0+IHR5cGUudHJpbSgpKTtcclxuXHJcbiAgICBjb25zdCBtaW1lVHlwZU1hcCA9IHRoaXMuZ2V0TWltZVR5cGVNYXAoKTtcclxuXHJcbiAgICBmb3IgKGNvbnN0IHR5cGUgb2YgdGhpcy5hY2NlcHRlZFR5cGVBcnJheSkge1xyXG4gICAgICBjb25zdCBkaXNwbGF5VHlwZSA9IG1pbWVUeXBlTWFwW3R5cGVdO1xyXG4gICAgICBpZiAoZGlzcGxheVR5cGUgJiYgIXRoaXMudG9vbFRpcFR5cGVBcnJheS5pbmNsdWRlcyhkaXNwbGF5VHlwZSkpIHtcclxuICAgICAgICB0aGlzLnRvb2xUaXBUeXBlQXJyYXkucHVzaChkaXNwbGF5VHlwZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0TWltZVR5cGVNYXAoKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAnYXBwbGljYXRpb24vcGRmJzogJ1BERicsXHJcbiAgICAgICdhcHBsaWNhdGlvbi9tc3dvcmQnOiAnV29yZCcsXHJcbiAgICAgICdhcHBsaWNhdGlvbi92bmQub3BlbnhtbGZvcm1hdHMtb2ZmaWNlZG9jdW1lbnQud29yZHByb2Nlc3NpbmdtbC5kb2N1bWVudCc6ICdXb3JkJyxcclxuICAgICAgJ2FwcGxpY2F0aW9uL3ZuZC5tcy1leGNlbCc6ICdFeGNlbCcsXHJcbiAgICAgICdhcHBsaWNhdGlvbi92bmQub3BlbnhtbGZvcm1hdHMtb2ZmaWNlZG9jdW1lbnQuc3ByZWFkc2hlZXRtbC5zaGVldCc6ICdFeGNlbCcsXHJcbiAgICAgICdhcHBsaWNhdGlvbi92bmQubXMtcG93ZXJwb2ludCc6ICdQb3dlclBvaW50JyxcclxuICAgICAgJ2FwcGxpY2F0aW9uL3ZuZC5vcGVueG1sZm9ybWF0cy1vZmZpY2Vkb2N1bWVudC5wcmVzZW50YXRpb25tbC5wcmVzZW50YXRpb24nOiAnUG93ZXJQb2ludCcsXHJcbiAgICAgICdpbWFnZS9wbmcnOiAnUE5HJyxcclxuICAgICAgJ2ltYWdlL2JtcCc6ICdCTVAnLFxyXG4gICAgICAnaW1hZ2UvanBlZyc6ICdKUEVHJyxcclxuICAgICAgJ2ltYWdlL3N2Zyt4bWwnOiAnU1ZHJyxcclxuICAgICAgJ2FwcGxpY2F0aW9uL3ppcCc6ICdaSVAnLFxyXG4gICAgICAnYXBwbGljYXRpb24veC1yYXItY29tcHJlc3NlZCc6ICdSQVInLFxyXG4gICAgICAndmlkZW8vd2VibSc6ICdXZWJNJyxcclxuICAgICAgJ3ZpZGVvL29nZyc6ICdPR0cnLFxyXG4gICAgICAndmlkZW8vbXA0JzogJ01QNCcsXHJcbiAgICAgICd2aWRlby9xdWlja3RpbWUnOiAnTU9WJyxcclxuICAgICAgJ3ZpZGVvL3gtbXN2aWRlbyc6ICdBVkknLFxyXG4gICAgICAndmlkZW8veC1tcy13bXYnOiAnV01WJyxcclxuICAgICAgJ3ZpZGVvL2F2aSc6ICdBVkknLFxyXG4gICAgICAndmlkZW8vbXBlZyc6ICdNUEVHJyxcclxuICAgICAgJ3ZpZGVvL3gtZmx2JzogJ0ZMVicsXHJcbiAgICAgICdhdWRpby9tcGVnJzogJ01QMycsXHJcbiAgICAgICd0ZXh0L3BsYWluJzogJ1R4dCcsXHJcbiAgICAgICd0ZXh0L3htbCc6ICdYTUwnLFxyXG4gICAgICAnYXBwbGljYXRpb24vanNvbic6ICdKU09OJyxcclxuICAgICAgJ2FwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSc6ICdCaW5hcnknLFxyXG4gICAgICAnYXBwbGljYXRpb24vQk4nOiAnTGljZW5zZSdcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGJ1aWxkVmFsaWRhdGlvbk1lc3NhZ2UoKTogdm9pZCB7XHJcbiAgICBjb25zdCBtZXNzYWdlczogc3RyaW5nW10gPSBbXTtcclxuXHJcbiAgICBpZiAodGhpcy50b29sVGlwVHlwZUFycmF5Lmxlbmd0aCkge1xyXG4gICAgICBtZXNzYWdlcy5wdXNoKGAke3RoaXMudXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSgnRXh0ZW5zaW9ucycpfSAoJHt0aGlzLnRvb2xUaXBUeXBlQXJyYXkuam9pbignLCAnKX0pYCk7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5vcHRpb25zLmZpbGVNYXhTaXplSW5NQiA+IDApIHtcclxuICAgICAgbWVzc2FnZXMucHVzaChgJHt0aGlzLnV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ0ZpbGVNYXhTaXplSW5NQicpfSR7dGhpcy5vcHRpb25zLmZpbGVNYXhTaXplSW5NQn1gKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5vcHRpb25zLm1pbk5vT2ZGaWxlcyA+IDApIHtcclxuICAgICAgbWVzc2FnZXMucHVzaChgJHt0aGlzLnV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ01pbkZpbGVDb3VudFZhbGlkYXRpb25LZXknKX0ke3RoaXMub3B0aW9ucy5taW5Ob09mRmlsZXN9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5tYXhOb09mRmlsZXMgPiAwKSB7XHJcbiAgICAgIG1lc3NhZ2VzLnB1c2goYCR7dGhpcy51dGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdNYXhGaWxlQ291bnRWYWxpZGF0aW9uS2V5Jyl9JHt0aGlzLm9wdGlvbnMubWF4Tm9PZkZpbGVzfWApO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMudmFsaWRhdGlvbk1lc3NhZ2UgPSBtZXNzYWdlcy5qb2luKCcgPGJyLz4gJyk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldHVwRm9ybUNvbnRyb2woKTogdm9pZCB7XHJcbiAgICB0aGlzLmdyb3VwLmFkZENvbnRyb2wodGhpcy5vcHRpb25zLm5hbWUsIG5ldyBGb3JtQ29udHJvbCgnJykpO1xyXG4gICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wgPSB0aGlzLmdyb3VwLmNvbnRyb2xzW3RoaXMub3B0aW9ucy5uYW1lXTtcclxuXHJcbiAgICB0aGlzLnNldHVwVmFsaWRhdG9ycygpO1xyXG4gICAgdGhpcy5zZXR1cENvdW50TWVzc2FnZSgpO1xyXG4gICAgdGhpcy5hcHBseVZhbGlkYXRvcnNBbmRTdGF0ZSgpO1xyXG4gICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuc2V0VmFsdWUodGhpcy5vcHRpb25zLnZhbHVlLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldHVwVmFsaWRhdG9ycygpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLm9wdGlvbnMuY3VzdG9tVmFsaWRhdGlvbj8ubGVuZ3RoKSB7XHJcbiAgICAgIGZvciAoY29uc3QgdmFsaWRhdGlvbiBvZiB0aGlzLm9wdGlvbnMuY3VzdG9tVmFsaWRhdGlvbikge1xyXG4gICAgICAgIHRoaXMudmFsaWRhdGlvblJ1bGVzLnB1c2godmFsaWRhdGlvbi5mdW5jdGlvbkJvZHkpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5pc1JlcXVpcmVkKSB7XHJcbiAgICAgIHRoaXMudmFsaWRhdGlvblJ1bGVzLnB1c2goVmFsaWRhdG9ycy5yZXF1aXJlZCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldHVwQ291bnRNZXNzYWdlKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5pc011bHRpcGxlRmlsZSAmJiB0aGlzLm9wdGlvbnMubWF4Tm9PZkZpbGVzID4gMCkge1xyXG4gICAgICB0aGlzLnZhbGlkYXRpb25Db3VudE1lc3NhZ2UgPSBgJHt0aGlzLnV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ01heEZpbGVzQ291bnQnKX0gOiAke3RoaXMub3B0aW9ucy5tYXhOb09mRmlsZXN9YDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXBwbHlWYWxpZGF0b3JzQW5kU3RhdGUoKTogdm9pZCB7XHJcbiAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5zZXRWYWxpZGF0b3JzKHRoaXMudmFsaWRhdGlvblJ1bGVzKTtcclxuICAgIGlmICh0aGlzLnZhbGlkYXRpb25SdWxlc0FzeW5jLmxlbmd0aCA+IDApIHtcclxuICAgICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuc2V0QXN5bmNWYWxpZGF0b3JzKHRoaXMudmFsaWRhdGlvblJ1bGVzQXN5bmMgYXMgYW55KTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5vcHRpb25zLmlzRGlzYWJsZWQpIHtcclxuICAgICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuZGlzYWJsZSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzZXR1cFN1YnNjcmlwdGlvbnMoKTogdm9pZCB7XHJcbiAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZENvbnRyb2xIb3N0Lm5nU3VibWl0LnN1YnNjcmliZSgoKSA9PiB7XHJcbiAgICAgIHRoaXMuZ3JvdXAubWFya0FsbEFzVG91Y2hlZCgpO1xyXG4gICAgICB0aGlzLm1hcmtBbGxBc1RvdWNoZWQgPSB0cnVlO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XHJcbiAgICB0aGlzLmFwcGx5QXR0cmlidXRlcygpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhcHBseUF0dHJpYnV0ZXMoKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5hdHRyaWJ1dGVMaXN0Py5sZW5ndGgpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLm9wdGlvbnMubmFtZSk7XHJcbiAgICBpZiAoZWxlbWVudCkge1xyXG4gICAgICBmb3IgKGNvbnN0IGF0dHJpYnV0ZSBvZiB0aGlzLm9wdGlvbnMuYXR0cmlidXRlTGlzdCkge1xyXG4gICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKGF0dHJpYnV0ZS5rZXksIGF0dHJpYnV0ZS52YWx1ZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHJlc2V0RXJyb3IgPSAoKTogdm9pZCA9PiB7XHJcbiAgICB0aGlzLmNvbnRyb2xWYWxpZGF0aW9uU2VydmljZS5yZW1vdmVHbG9iYWxFcnJvcigpO1xyXG4gIH07XHJcblxyXG4gIHNob3dHbG9iYWxFcnJvcigpOiB2b2lkIHtcclxuICAgIHRoaXMuY29udHJvbFV0aWxpdHkuc2hvd0dsb2JhbEVycm9yKCk7XHJcbiAgfVxyXG5cclxuICBnZXRFcnJvclZhbGlkYXRpb24oZXJyb3JMaXN0OiBhbnkpOiBzdHJpbmcge1xyXG4gICAgaWYgKHRoaXMubWFya0FsbEFzVG91Y2hlZCAmJiB0aGlzLmdyb3VwLmludmFsaWQpIHtcclxuICAgICAgdGhpcy5zaG93R2xvYmFsRXJyb3IoKTtcclxuICAgICAgdGhpcy5tYXJrQWxsQXNUb3VjaGVkID0gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGVycm9yTGlzdCAmJiBlcnJvckxpc3QubGVuZ3RoID4gMCkge1xyXG4gICAgICBmb3IgKGNvbnN0IGVycm9yIG9mIGVycm9yTGlzdCkge1xyXG4gICAgICAgIGlmIChlcnJvci5rZXkgPT09ICdJbnZhbGlkRmlsZXMnKSB7XHJcbiAgICAgICAgICByZXR1cm4gZXJyb3IudmFsdWU7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuY29udHJvbFV0aWxpdHkuZ2V0RXJyb3JWYWxpZGF0aW9uTWFzc2FnZShlcnJvckxpc3QsIHRoaXMuZ3JvdXAsIHRoaXMub3B0aW9ucyk7XHJcbiAgfVxyXG5cclxuICBmaWxlT3ZlckFub3RoZXIoZXZlbnQ6IGFueSk6IHZvaWQge1xyXG4gICAgdGhpcy5oYXNBbm90aGVyRHJvcFpvbmVPdmVyID0gISFldmVudDtcclxuICB9XHJcblxyXG4gIGlzSGlkZUlucHV0KCk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5pc011bHRpcGxlRmlsZSkge1xyXG4gICAgICByZXR1cm4gdGhpcy5vcHRpb25zLm1heE5vT2ZGaWxlcyA+IDAgJiZcclxuICAgICAgICB0aGlzLm9wdGlvbnMubWF4Tm9PZkZpbGVzID09PSB0aGlzLnVwbG9hZGVyLnF1ZXVlLmxlbmd0aDtcclxuICAgIH1cclxuICAgIHJldHVybiB0aGlzLnVwbG9hZGVyLnF1ZXVlLmxlbmd0aCA+IDA7XHJcbiAgfVxyXG4gIG9uRmlsZUNoYW5nZSgpOiB2b2lkIHtcclxuICAgIHRoaXMudmFsaWRhdGVGaWxlQ29uc3RyYWludHMoKTtcclxuXHJcbiAgICBjb25zdCBmaWxlUHJvY2Vzc2luZ1Jlc3VsdCA9IHRoaXMucHJvY2Vzc05ld2x5QWRkZWRGaWxlcygpO1xyXG5cclxuICAgIHRoaXMuaGFuZGxlRmlsZVZhbGlkYXRpb25SZXN1bHRzKGZpbGVQcm9jZXNzaW5nUmVzdWx0KTtcclxuXHJcbiAgICB0aGlzLnByb2Nlc3NWYWxpZEZpbGVzRm9yVXBsb2FkKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHByb2Nlc3NOZXdseUFkZGVkRmlsZXMoKTogRmlsZVByb2Nlc3NpbmdSZXN1bHQge1xyXG4gICAgY29uc3QgYWRkZWRRdWV1ZSA9IHRoaXMuZ2V0TmV3bHlBZGRlZEZpbGVzKCk7XHJcbiAgICBjb25zdCB2YWxpZGF0aW9uUmVzdWx0ID0gdGhpcy52YWxpZGF0ZUZpbGVzSW5RdWV1ZShhZGRlZFF1ZXVlKTtcclxuXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICB2YWxpZEZpbGVzOiBhZGRlZFF1ZXVlLmZpbHRlcihmaWxlID0+ICF2YWxpZGF0aW9uUmVzdWx0LmludmFsaWRGaWxlcy5pbmNsdWRlcyhmaWxlKSksXHJcbiAgICAgIGludmFsaWRGaWxlczogdmFsaWRhdGlvblJlc3VsdC5pbnZhbGlkRmlsZXMsXHJcbiAgICAgIGVycm9yczogdmFsaWRhdGlvblJlc3VsdC5lcnJvcnNcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldE5ld2x5QWRkZWRGaWxlcygpOiBGaWxlSXRlbVtdIHtcclxuICAgIHJldHVybiB0aGlzLnVwbG9hZGVyLnF1ZXVlLmZpbHRlcigob2JqKSA9PiBvYmpbJ3NvbWUnXT8ubGFzdE1vZGlmaWVkICE9IG51bGwpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB2YWxpZGF0ZUZpbGVzSW5RdWV1ZShmaWxlUXVldWU6IEZpbGVJdGVtW10pOiBGaWxlVmFsaWRhdGlvblJlc3VsdCB7XHJcbiAgICBjb25zdCB2YWxpZGF0aW9uRXJyb3JzOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgY29uc3QgaW52YWxpZEZpbGVzOiBGaWxlSXRlbVtdID0gW107XHJcbiAgICBjb25zdCBwcm9jZXNzZWREdXBsaWNhdGVOYW1lcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xyXG5cclxuICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBmaWxlUXVldWUpIHtcclxuICAgICAgY29uc3QgZmlsZSA9IGVsZW1lbnQuZmlsZTtcclxuICAgICAgaWYgKCFmaWxlKSBjb250aW51ZTtcclxuXHJcbiAgICAgIGNvbnN0IGZpbGVWYWxpZGF0aW9uID0gdGhpcy52YWxpZGF0ZVNpbmdsZUZpbGUoZmlsZSwgZWxlbWVudCwgcHJvY2Vzc2VkRHVwbGljYXRlTmFtZXMpO1xyXG5cclxuICAgICAgaWYgKCFmaWxlVmFsaWRhdGlvbi5pc1ZhbGlkKSB7XHJcbiAgICAgICAgaW52YWxpZEZpbGVzLnB1c2goZWxlbWVudCk7XHJcbiAgICAgICAgdmFsaWRhdGlvbkVycm9ycy5wdXNoKC4uLmZpbGVWYWxpZGF0aW9uLmVycm9ycyk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBpc1ZhbGlkOiBpbnZhbGlkRmlsZXMubGVuZ3RoID09PSAwLFxyXG4gICAgICBlcnJvcnM6IHZhbGlkYXRpb25FcnJvcnMsXHJcbiAgICAgIGludmFsaWRGaWxlc1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgdmFsaWRhdGVTaW5nbGVGaWxlKGZpbGU6IEZpbGVMaWtlT2JqZWN0LCBlbGVtZW50OiBGaWxlSXRlbSwgcHJvY2Vzc2VkRHVwbGljYXRlTmFtZXM6IFNldDxzdHJpbmc+KTogRmlsZVZhbGlkYXRpb25SZXN1bHQge1xyXG4gICAgY29uc3QgZXJyb3JzOiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICAgIGNvbnN0IHNpemVWYWxpZCA9IHRoaXMudmFsaWRhdGVJbmRpdmlkdWFsRmlsZVNpemUoZmlsZSk7XHJcbiAgICBjb25zdCB0eXBlVmFsaWQgPSB0aGlzLnZhbGlkYXRlSW5kaXZpZHVhbEZpbGVUeXBlKGZpbGUpO1xyXG4gICAgY29uc3QgbmFtZVZhbGlkID0gdGhpcy52YWxpZGF0ZUR1cGxpY2F0ZUZpbGVOYW1lKGZpbGUsIGVsZW1lbnQpO1xyXG5cclxuICAgIGlmICghc2l6ZVZhbGlkKSB7XHJcbiAgICAgIGVycm9ycy5wdXNoKHRoaXMuY3JlYXRlRmlsZVNpemVFcnJvck1lc3NhZ2UoZmlsZS5uYW1lKSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCF0eXBlVmFsaWQpIHtcclxuICAgICAgZXJyb3JzLnB1c2godGhpcy5jcmVhdGVGaWxlVHlwZUVycm9yTWVzc2FnZShmaWxlLm5hbWUpKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoIW5hbWVWYWxpZCkge1xyXG4gICAgICBjb25zdCBkdXBsaWNhdGVFcnJvciA9IHRoaXMuY3JlYXRlRHVwbGljYXRlRmlsZUVycm9yTWVzc2FnZShmaWxlLm5hbWUsIHByb2Nlc3NlZER1cGxpY2F0ZU5hbWVzKTtcclxuICAgICAgaWYgKGR1cGxpY2F0ZUVycm9yKSB7XHJcbiAgICAgICAgZXJyb3JzLnB1c2goZHVwbGljYXRlRXJyb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgaXNWYWxpZDogc2l6ZVZhbGlkICYmIHR5cGVWYWxpZCAmJiBuYW1lVmFsaWQsXHJcbiAgICAgIGVycm9ycyxcclxuICAgICAgaW52YWxpZEZpbGVzOiBbXVxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY3JlYXRlRmlsZVNpemVFcnJvck1lc3NhZ2UoZmlsZU5hbWU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy51dGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdGaWxlRXhjZWVkc01heFNpemUnKVxyXG4gICAgICAucmVwbGFjZSgne2ZpbGVOYW1lfScsIGZpbGVOYW1lKVxyXG4gICAgICAucmVwbGFjZSgne21heFNpemV9JywgdGhpcy5vcHRpb25zLmZpbGVNYXhTaXplSW5NQi50b1N0cmluZygpKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY3JlYXRlRmlsZVR5cGVFcnJvck1lc3NhZ2UoZmlsZU5hbWU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy51dGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdGaWxlVHlwZU5vdEFjY2VwdGVkJylcclxuICAgICAgLnJlcGxhY2UoJ3tmaWxlTmFtZX0nLCBmaWxlTmFtZSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNyZWF0ZUR1cGxpY2F0ZUZpbGVFcnJvck1lc3NhZ2UoZmlsZU5hbWU6IHN0cmluZywgcHJvY2Vzc2VkRHVwbGljYXRlTmFtZXM6IFNldDxzdHJpbmc+KTogc3RyaW5nIHwgbnVsbCB7XHJcbiAgICBjb25zdCBmaWxlTmFtZUxvd2VyID0gZmlsZU5hbWUudG9Mb3dlckNhc2UoKTtcclxuXHJcbiAgICBpZiAocHJvY2Vzc2VkRHVwbGljYXRlTmFtZXMuaGFzKGZpbGVOYW1lTG93ZXIpKSB7XHJcbiAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIHByb2Nlc3NlZER1cGxpY2F0ZU5hbWVzLmFkZChmaWxlTmFtZUxvd2VyKTtcclxuXHJcbiAgICBsZXQgZHVwbGljYXRlRXJyb3JNc2cgPSB0aGlzLnV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ0R1cGxpY2F0ZUZpbGVOYW1lJyk7XHJcblxyXG4gICAgaWYgKCFkdXBsaWNhdGVFcnJvck1zZyB8fCBkdXBsaWNhdGVFcnJvck1zZyA9PT0gJ0R1cGxpY2F0ZUZpbGVOYW1lJykge1xyXG4gICAgICBkdXBsaWNhdGVFcnJvck1zZyA9IGBGaWxlICd7ZmlsZU5hbWV9JyBhbHJlYWR5IGV4aXN0cy4gUGxlYXNlIGNob29zZSBhIGRpZmZlcmVudCBmaWxlIG9yIHJlbmFtZSBpdC5gO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBkdXBsaWNhdGVFcnJvck1zZy5yZXBsYWNlKCd7ZmlsZU5hbWV9JywgZmlsZU5hbWUpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBoYW5kbGVGaWxlVmFsaWRhdGlvblJlc3VsdHMocmVzdWx0OiBGaWxlUHJvY2Vzc2luZ1Jlc3VsdCk6IHZvaWQge1xyXG4gICAgaWYgKHJlc3VsdC5pbnZhbGlkRmlsZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICB0aGlzLnJlbW92ZUludmFsaWRGaWxlcyhyZXN1bHQuaW52YWxpZEZpbGVzKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAocmVzdWx0LmVycm9ycy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIHRoaXMuc2hvd1ZhbGlkYXRpb25FcnJvcnMocmVzdWx0LmVycm9ycyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHByb2Nlc3NWYWxpZEZpbGVzRm9yVXBsb2FkKCk6IHZvaWQge1xyXG4gICAgY29uc3QgZmlsZXNBcnJheTogRmlsZURUT1tdID0gW107XHJcbiAgICBjb25zdCB2YWxpZFF1ZXVlID0gdGhpcy5nZXROZXdseUFkZGVkRmlsZXMoKTtcclxuXHJcbiAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgdmFsaWRRdWV1ZSkge1xyXG4gICAgICBjb25zdCBmaWxlID0gZWxlbWVudC5maWxlO1xyXG4gICAgICBpZiAoIWZpbGUpIGNvbnRpbnVlO1xyXG5cclxuICAgICAgaWYgKHRoaXMuc2hvdWxkVXNlQXN5bmNVcGxvYWQoZWxlbWVudCkpIHtcclxuICAgICAgICB0aGlzLmhhbmRsZUFzeW5jRmlsZVVwbG9hZChlbGVtZW50LCBmaWxlc0FycmF5KTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLmhhbmRsZVN5bmNGaWxlVXBsb2FkKGZpbGUsIGZpbGVzQXJyYXkpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNob3VsZFVzZUFzeW5jVXBsb2FkKGVsZW1lbnQ6IEZpbGVJdGVtKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmlzVXBsb2FkRmlsZUFzeW5jICYmICFlbGVtZW50Ll9maWxlWydpRF9HVUlEJ107XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHZhbGlkYXRlRmlsZUNvbnN0cmFpbnRzKCk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5pc011bHRpcGxlRmlsZSkge1xyXG4gICAgICBpZiAoIXRoaXMudmFsaWRhdGVNaW5GaWxlQ291bnQoKSB8fCAhdGhpcy52YWxpZGF0ZU1heEZpbGVDb3VudCgpIHx8ICF0aGlzLnZhbGlkYXRlVG90YWxGaWxlU2l6ZSgpKSB7XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgdmFsaWRhdGVNaW5GaWxlQ291bnQoKTogYm9vbGVhbiB7XHJcbiAgICBpZiAodGhpcy5vcHRpb25zLm1pbk5vT2ZGaWxlcyA+IDAgJiYgdGhpcy5vcHRpb25zLm1pbk5vT2ZGaWxlcyA+IHRoaXMudXBsb2FkZXIucXVldWUubGVuZ3RoKSB7XHJcbiAgICAgIGNvbnN0IG1pbkZpbGVNc2cgPSB0aGlzLnV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ01pbmltdW1GaWxlc1JlcXVpcmVkJylcclxuICAgICAgICAucmVwbGFjZSgne2NvdW50fScsIHRoaXMub3B0aW9ucy5taW5Ob09mRmlsZXMudG9TdHJpbmcoKSk7XHJcbiAgICAgIHRoaXMuc2hvd0ZpbGVDb3VudEVycm9yKCdNaW5GaWxlQ291bnRWYWxpZGF0aW9uS2V5JywgbWluRmlsZU1zZyk7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICAgIHJldHVybiB0cnVlO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB2YWxpZGF0ZU1heEZpbGVDb3VudCgpOiBib29sZWFuIHtcclxuICAgIGlmICh0aGlzLm9wdGlvbnMubWF4Tm9PZkZpbGVzID4gMCAmJiB0aGlzLm9wdGlvbnMubWF4Tm9PZkZpbGVzIDwgdGhpcy51cGxvYWRlci5xdWV1ZS5sZW5ndGgpIHtcclxuICAgICAgY29uc3QgbWF4RmlsZU1zZyA9IHRoaXMudXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSgnTWF4aW11bUZpbGVzRXhjZWVkZWQnKSB8fFxyXG4gICAgICAgIGBNYXhpbXVtIHttYXhDb3VudH0gZmlsZXMgYWxsb3dlZC4gWW91IGhhdmUgc2VsZWN0ZWQge2N1cnJlbnRDb3VudH0gZmlsZXMuYDtcclxuICAgICAgY29uc3QgZmluYWxNc2cgPSBtYXhGaWxlTXNnXHJcbiAgICAgICAgLnJlcGxhY2UoJ3ttYXhDb3VudH0nLCB0aGlzLm9wdGlvbnMubWF4Tm9PZkZpbGVzLnRvU3RyaW5nKCkpXHJcbiAgICAgICAgLnJlcGxhY2UoJ3tjdXJyZW50Q291bnR9JywgdGhpcy51cGxvYWRlci5xdWV1ZS5sZW5ndGgudG9TdHJpbmcoKSk7XHJcbiAgICAgIHRoaXMuc2hvd0ZpbGVDb3VudEVycm9yKCdNYXhGaWxlQ291bnRWYWxpZGF0aW9uS2V5JywgZmluYWxNc2cpO1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2hvd0ZpbGVDb3VudEVycm9yKGVycm9yS2V5OiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgY29uc3QgY3VycmVudEVycm9ycyA9IHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLmVycm9ycyB8fCB7fTtcclxuICAgIGN1cnJlbnRFcnJvcnNbZXJyb3JLZXldID0gbWVzc2FnZTtcclxuXHJcbiAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5zZXRFcnJvcnMoY3VycmVudEVycm9ycyk7XHJcbiAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5tYXJrQXNUb3VjaGVkKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNsZWFyRmlsZUNvdW50RXJyb3IoZXJyb3JLZXk6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgY29uc3QgY3VycmVudEVycm9ycyA9IHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLmVycm9ycztcclxuICAgIGlmIChjdXJyZW50RXJyb3JzICYmIGN1cnJlbnRFcnJvcnNbZXJyb3JLZXldKSB7XHJcbiAgICAgIGRlbGV0ZSBjdXJyZW50RXJyb3JzW2Vycm9yS2V5XTtcclxuXHJcbiAgICAgIGlmIChPYmplY3Qua2V5cyhjdXJyZW50RXJyb3JzKS5sZW5ndGggPT09IDApIHtcclxuICAgICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5zZXRFcnJvcnMobnVsbCk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuc2V0RXJyb3JzKGN1cnJlbnRFcnJvcnMpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHZhbGlkYXRlVG90YWxGaWxlU2l6ZSgpOiBib29sZWFuIHtcclxuICAgIGlmICh0aGlzLm9wdGlvbnMubWF4U2l6ZUZvckFsbEZpbGVzSW5NQiA+IDApIHtcclxuICAgICAgY29uc3QgdG90YWxTaXplID0gdGhpcy51cGxvYWRlci5xdWV1ZS5yZWR1Y2UoKHN1bSwgZWxlbWVudCkgPT4gc3VtICsgZWxlbWVudC5maWxlLnNpemUsIDApO1xyXG4gICAgICBjb25zdCBtYXhTaXplQnl0ZXMgPSB0aGlzLm9wdGlvbnMubWF4U2l6ZUZvckFsbEZpbGVzSW5NQiAqIHRoaXMuQllURVNfVE9fTUI7XHJcblxyXG4gICAgICBpZiAodG90YWxTaXplID4gbWF4U2l6ZUJ5dGVzKSB7XHJcbiAgICAgICAgdGhpcy5zaG93VG90YWxTaXplRXJyb3IoKTtcclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiB0cnVlO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzaG93VG90YWxTaXplRXJyb3IoKTogdm9pZCB7XHJcbiAgICBjb25zdCB0b3RhbFNpemVNc2cgPSB0aGlzLnV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ1RvdGFsRmlsZVNpemVFeGNlZWRlZCcpXHJcbiAgICAgIC5yZXBsYWNlKCd7bWF4U2l6ZX0nLCB0aGlzLm9wdGlvbnMubWF4U2l6ZUZvckFsbEZpbGVzSW5NQi50b1N0cmluZygpKTtcclxuXHJcbiAgICBjb25zdCBjdXJyZW50RXJyb3JzID0gdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuZXJyb3JzIHx8IHt9O1xyXG4gICAgY3VycmVudEVycm9yc1snTWF4U2l6ZUZvckFsbEZpbGVzSW5NQiddID0gdG90YWxTaXplTXNnO1xyXG5cclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnNldEVycm9ycyhjdXJyZW50RXJyb3JzKTtcclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLm1hcmtBc1RvdWNoZWQoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgdmFsaWRhdGVGaWxlU2l6ZShmaWxlOiBGaWxlTGlrZU9iamVjdCk6IGJvb2xlYW4ge1xyXG4gICAgY29uc3QgbWF4RmlsZVNpemUgPSB0aGlzLm9wdGlvbnMuZmlsZU1heFNpemVJbk1CICogdGhpcy5CWVRFU19UT19NQjtcclxuICAgIGlmIChmaWxlLnNpemUgPiBtYXhGaWxlU2l6ZSkge1xyXG4gICAgICB0aGlzLnNldEZvcm1Db250cm9sRXJyb3IoJ0ZpbGVNYXhTaXplSW5NQicsIGAke3RoaXMub3B0aW9ucy5maWxlTWF4U2l6ZUluTUJ9TUJgKTtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRydWU7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHZhbGlkYXRlRmlsZVR5cGUoZmlsZTogRmlsZUxpa2VPYmplY3QpOiBib29sZWFuIHtcclxuICAgIGlmICh0aGlzLm9wdGlvbnMuZmlsZVVwbG9hZEFjY2VwdHNUeXBlcz8ubGVuZ3RoKSB7XHJcbiAgICAgIGNvbnN0IGZpbGVUeXBlID0gZmlsZS50eXBlO1xyXG4gICAgICBjb25zdCBpc0FjY2VwdGVkID0gdGhpcy5hY2NlcHRlZFR5cGVBcnJheS5zb21lKHR5cGUgPT5cclxuICAgICAgICB0eXBlLnRvTG93ZXJDYXNlKCkgPT09IGZpbGVUeXBlLnRvTG93ZXJDYXNlKClcclxuICAgICAgKTtcclxuXHJcbiAgICAgIGlmICghaXNBY2NlcHRlZCkge1xyXG4gICAgICAgIHRoaXMuc2V0Rm9ybUNvbnRyb2xFcnJvcignVG9vbFRpcFR5cGVFcnJvcicsIHRoaXMudG9vbFRpcFR5cGVBcnJheSk7XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgdmFsaWRhdGVJbmRpdmlkdWFsRmlsZVNpemUoZmlsZTogRmlsZUxpa2VPYmplY3QpOiBib29sZWFuIHtcclxuICAgIGNvbnN0IG1heEZpbGVTaXplID0gdGhpcy5vcHRpb25zLmZpbGVNYXhTaXplSW5NQiAqIHRoaXMuQllURVNfVE9fTUI7XHJcbiAgICByZXR1cm4gZmlsZS5zaXplIDw9IG1heEZpbGVTaXplO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB2YWxpZGF0ZUluZGl2aWR1YWxGaWxlVHlwZShmaWxlOiBGaWxlTGlrZU9iamVjdCk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuZmlsZVVwbG9hZEFjY2VwdHNUeXBlcz8ubGVuZ3RoKSB7XHJcbiAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGZpbGVUeXBlID0gZmlsZS50eXBlPy50b0xvd2VyQ2FzZSgpO1xyXG4gICAgaWYgKCFmaWxlVHlwZSkge1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuYWNjZXB0ZWRUeXBlQXJyYXkuc29tZSh0eXBlID0+XHJcbiAgICAgIHR5cGUudG9Mb3dlckNhc2UoKSA9PT0gZmlsZVR5cGVcclxuICAgICk7XHJcbiAgfVxyXG5cclxuXHJcbiAgcHJpdmF0ZSB2YWxpZGF0ZUR1cGxpY2F0ZUZpbGVOYW1lKGZpbGU6IEZpbGVMaWtlT2JqZWN0LCBjdXJyZW50RWxlbWVudDogRmlsZUl0ZW0pOiBib29sZWFuIHtcclxuICAgIGlmICghZmlsZT8ubmFtZSkge1xyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBjdXJyZW50RmlsZU5hbWUgPSBmaWxlLm5hbWUudG9Mb3dlckNhc2UoKTtcclxuXHJcbiAgICBjb25zdCBleGlzdGluZ0ZpbGVzID0gdGhpcy51cGxvYWRlci5xdWV1ZS5maWx0ZXIoaXRlbSA9PiBpdGVtICE9PSBjdXJyZW50RWxlbWVudCk7XHJcbiAgICBjb25zdCBkdXBsaWNhdGVFeGlzdHMgPSBleGlzdGluZ0ZpbGVzLnNvbWUoaXRlbSA9PiB7XHJcbiAgICAgIGNvbnN0IGV4aXN0aW5nRmlsZU5hbWUgPSBpdGVtLmZpbGU/Lm5hbWUgfHwgaXRlbS5fZmlsZT8ubmFtZTtcclxuICAgICAgcmV0dXJuIGV4aXN0aW5nRmlsZU5hbWUgJiYgZXhpc3RpbmdGaWxlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBjdXJyZW50RmlsZU5hbWU7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAoZHVwbGljYXRlRXhpc3RzKSB7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5vcHRpb25zLnZhbHVlKSB7XHJcbiAgICAgIGNvbnN0IHVwbG9hZGVkRmlsZXMgPSBBcnJheS5pc0FycmF5KHRoaXMub3B0aW9ucy52YWx1ZSkgPyB0aGlzLm9wdGlvbnMudmFsdWUgOiBbdGhpcy5vcHRpb25zLnZhbHVlXTtcclxuICAgICAgY29uc3QgZHVwbGljYXRlSW5VcGxvYWRlZCA9IHVwbG9hZGVkRmlsZXMuc29tZSh1cGxvYWRlZEZpbGUgPT4ge1xyXG4gICAgICAgIGNvbnN0IHVwbG9hZGVkRmlsZU5hbWUgPSB1cGxvYWRlZEZpbGU/LmZpbGVOYW1lIHx8IHVwbG9hZGVkRmlsZT8ubmFtZTtcclxuICAgICAgICByZXR1cm4gdXBsb2FkZWRGaWxlTmFtZSAmJiB1cGxvYWRlZEZpbGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IGN1cnJlbnRGaWxlTmFtZTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgICByZXR1cm4gIWR1cGxpY2F0ZUluVXBsb2FkZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRydWU7XHJcbiAgfVxyXG5cclxuXHJcblxyXG4gIHByaXZhdGUgcmVtb3ZlSW52YWxpZEZpbGVzKGludmFsaWRGaWxlczogRmlsZUl0ZW1bXSk6IHZvaWQge1xyXG4gICAgaW52YWxpZEZpbGVzLmZvckVhY2goaW52YWxpZEZpbGUgPT4ge1xyXG4gICAgICBjb25zdCBpbmRleCA9IHRoaXMudXBsb2FkZXIucXVldWUuaW5kZXhPZihpbnZhbGlkRmlsZSk7XHJcbiAgICAgIGlmIChpbmRleCA+IC0xKSB7XHJcbiAgICAgICAgdGhpcy51cGxvYWRlci5xdWV1ZS5zcGxpY2UoaW5kZXgsIDEpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2hvd1ZhbGlkYXRpb25FcnJvcnMoZXJyb3JzOiBzdHJpbmdbXSk6IHZvaWQge1xyXG4gICAgaWYgKGVycm9ycy5sZW5ndGggPT09IDApIHJldHVybjtcclxuXHJcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBlcnJvcnMuam9pbignPGJyLz4nKTtcclxuXHJcbiAgICB0aGlzLnNldFZhbGlkYXRpb25FcnJvcignSW52YWxpZEZpbGVzJywgZXJyb3JNZXNzYWdlKTtcclxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICB0aGlzLmNsZWFySW52YWxpZEZpbGVzRXJyb3IoKTtcclxuICAgIH0sIHRoaXMuRVJST1JfRElTUExBWV9EVVJBVElPTik7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldFZhbGlkYXRpb25FcnJvcihlcnJvcktleTogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgY29uc3QgY3VycmVudEVycm9ycyA9IHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLmVycm9ycyB8fCB7fTtcclxuICAgIGN1cnJlbnRFcnJvcnNbZXJyb3JLZXldID0gZXJyb3JNZXNzYWdlO1xyXG5cclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnNldEVycm9ycyhjdXJyZW50RXJyb3JzKTtcclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLm1hcmtBc1RvdWNoZWQoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY2xlYXJJbnZhbGlkRmlsZXNFcnJvcigpOiB2b2lkIHtcclxuICAgIGNvbnN0IGN1cnJlbnRFcnJvcnMgPSB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5lcnJvcnM7XHJcbiAgICBpZiAoY3VycmVudEVycm9ycyAmJiBjdXJyZW50RXJyb3JzWydJbnZhbGlkRmlsZXMnXSkge1xyXG4gICAgICBkZWxldGUgY3VycmVudEVycm9yc1snSW52YWxpZEZpbGVzJ107XHJcblxyXG4gICAgICBpZiAoT2JqZWN0LmtleXMoY3VycmVudEVycm9ycykubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuc2V0RXJyb3JzKG51bGwpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnNldEVycm9ycyhjdXJyZW50RXJyb3JzKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzZXRGb3JtQ29udHJvbEVycm9yKGVycm9yS2V5OiBzdHJpbmcsIGVycm9yVmFsdWU6IGFueSk6IHZvaWQge1xyXG4gICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuc2V0RXJyb3JzKHsgW2Vycm9yS2V5XTogZXJyb3JWYWx1ZSB9KTtcclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLm1hcmtBc1RvdWNoZWQoKTtcclxuICAgIHRoaXMudXBsb2FkZXIucXVldWUgPSBbXTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgaGFuZGxlQXN5bmNGaWxlVXBsb2FkKGVsZW1lbnQ6IEZpbGVJdGVtLCBmaWxlc0FycmF5OiBGaWxlRFRPW10pOiB2b2lkIHtcclxuICAgIGNvbnN0IHVwbG9hZFN1YnNjcmlwdGlvbiA9IHRoaXMuZmlsZVVwbG9hZFNlcnZpY2UudXBsb2FkRmlsZShlbGVtZW50Ll9maWxlKS5zdWJzY3JpYmUoe1xyXG4gICAgICBuZXh0OiAoZXZlbnQ6IGFueSkgPT4ge1xyXG4gICAgICAgIGlmIChldmVudC50eXBlID09PSBIdHRwRXZlbnRUeXBlLlVwbG9hZFByb2dyZXNzKSB7XHJcbiAgICAgICAgICB0aGlzLmhhbmRsZVVwbG9hZFByb2dyZXNzKGVsZW1lbnQsIGV2ZW50KTtcclxuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50LnR5cGUgPT09IEh0dHBFdmVudFR5cGUuUmVzcG9uc2UpIHtcclxuICAgICAgICAgIHRoaXMuaGFuZGxlVXBsb2FkQ29tcGxldGUoZWxlbWVudCwgZXZlbnQsIGZpbGVzQXJyYXkpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSxcclxuICAgICAgZXJyb3I6IChlcnJvcikgPT4ge1xyXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ1VwbG9hZCBmYWlsZWQ6JywgZXJyb3IpO1xyXG4gICAgICAgIC8vIEhhbmRsZSB1cGxvYWQgZXJyb3IgLSB5b3UgY2FuIGFkZCBjdXN0b20gZXJyb3IgaGFuZGxpbmcgaGVyZVxyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICAvLyBTdG9yZSBzdWJzY3JpcHRpb24gZm9yIGNsZWFudXBcclxuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5hZGQodXBsb2FkU3Vic2NyaXB0aW9uKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgaGFuZGxlVXBsb2FkUHJvZ3Jlc3MoZWxlbWVudDogRmlsZUl0ZW0sIGV2ZW50OiBVcGxvYWRQcm9ncmVzc0V2ZW50KTogdm9pZCB7XHJcbiAgICBjb25zdCBxdWV1ZUluZGV4ID0gdGhpcy51cGxvYWRlci5xdWV1ZS5maW5kSW5kZXgoKGZpbGUpID0+IGZpbGUgPT09IGVsZW1lbnQpO1xyXG4gICAgaWYgKHF1ZXVlSW5kZXggPT09IC0xKSByZXR1cm47XHJcblxyXG4gICAgY29uc3QgcHJvZ3Jlc3MgPSBNYXRoLnJvdW5kKCgxMDAgKiBldmVudC5sb2FkZWQpIC8gZXZlbnQudG90YWwpO1xyXG4gICAgdGhpcy51cGxvYWRlci5xdWV1ZVtxdWV1ZUluZGV4XS5wcm9ncmVzcyA9XHJcbiAgICAgIHByb2dyZXNzID49IHRoaXMuUFJPR1JFU1NfTkVBUl9DT01QTEVURSA/IHRoaXMuUFJPR1JFU1NfTkVBUl9DT01QTEVURSA6IHByb2dyZXNzO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBoYW5kbGVVcGxvYWRDb21wbGV0ZShlbGVtZW50OiBGaWxlSXRlbSwgZXZlbnQ6IFVwbG9hZENvbXBsZXRlRXZlbnQsIGZpbGVzQXJyYXk6IEZpbGVEVE9bXSk6IHZvaWQge1xyXG4gICAgY29uc3QgcXVldWVJbmRleCA9IHRoaXMudXBsb2FkZXIucXVldWUuZmluZEluZGV4KChmaWxlKSA9PiBmaWxlID09PSBlbGVtZW50KTtcclxuICAgIGlmIChxdWV1ZUluZGV4ID09PSAtMSkgcmV0dXJuO1xyXG5cclxuICAgIHRoaXMudXBsb2FkZXIucXVldWVbcXVldWVJbmRleF0ucHJvZ3Jlc3MgPSB0aGlzLlBST0dSRVNTX0NPTVBMRVRFO1xyXG5cclxuICAgIGNvbnN0IGZpbGVJRCA9IGV2ZW50LmJvZHkudmFsO1xyXG4gICAgdGhpcy51cGRhdGVFbGVtZW50V2l0aEZpbGVJbmZvKGVsZW1lbnQsIGZpbGVJRCwgZXZlbnQuYm9keS5kb3dubG9hZFVybCk7XHJcblxyXG4gICAgY29uc3QgYWRkZWRGaWxlID0gdGhpcy5jcmVhdGVGaWxlRFRPKGVsZW1lbnQsIGZpbGVJRCwgZXZlbnQuYm9keS5kb3dubG9hZFVybCk7XHJcbiAgICB0aGlzLnVwZGF0ZUZvcm1WYWx1ZShhZGRlZEZpbGUsIGZpbGVzQXJyYXkpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB1cGRhdGVFbGVtZW50V2l0aEZpbGVJbmZvKGVsZW1lbnQ6IEZpbGVJdGVtLCBmaWxlSUQ6IHN0cmluZywgZG93bmxvYWRVcmw/OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGVsZW1lbnQuX2ZpbGVbJ2lEX0dVSUQnXSA9IGZpbGVJRDtcclxuICAgIGVsZW1lbnQuX2ZpbGVbJ2lzTmV3J10gPSB0cnVlO1xyXG5cclxuICAgIGlmIChkb3dubG9hZFVybCkge1xyXG4gICAgICBlbGVtZW50Ll9maWxlWyd1cmwnXSA9IGRvd25sb2FkVXJsO1xyXG4gICAgICAoZWxlbWVudC5maWxlIGFzIGFueSkudXJsID0gZG93bmxvYWRVcmw7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNyZWF0ZUZpbGVEVE8oZWxlbWVudDogRmlsZUl0ZW0sIGZpbGVJRDogc3RyaW5nLCBkb3dubG9hZFVybD86IHN0cmluZyk6IEZpbGVEVE8ge1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgaURfR1VJRDogZmlsZUlELFxyXG4gICAgICBmaWxlTmFtZTogZWxlbWVudC5fZmlsZVsnbmFtZSddLFxyXG4gICAgICBmaWxlVHlwZTogZWxlbWVudC5fZmlsZVsndHlwZSddLFxyXG4gICAgICBpc05ldzogdHJ1ZSxcclxuICAgICAgZmlsZUJhc2U2NDogJycsXHJcbiAgICAgIGZpbGVTaXplSW5NQjogZWxlbWVudC5fZmlsZS5zaXplIC8gdGhpcy5CWVRFU19UT19NQixcclxuICAgICAgbmFtZVdpdGhFeHRlbnNpb246IGVsZW1lbnQuX2ZpbGVbJ25hbWUnXSxcclxuICAgICAgZnVsbEZpbGVVUkw6IGRvd25sb2FkVXJsIHx8IG51bGxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGhhbmRsZVN5bmNGaWxlVXBsb2FkKGZpbGU6IEZpbGVMaWtlT2JqZWN0LCBmaWxlc0FycmF5OiBGaWxlRFRPW10pOiB2b2lkIHtcclxuICAgIHRoaXMudHJhY2tNZW1vcnlVc2FnZShmaWxlLnNpemUpO1xyXG4gICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcclxuXHJcbiAgICAvLyBTdG9yZSByZWFkZXIgcmVmZXJlbmNlIGZvciBjbGVhbnVwXHJcbiAgICBjb25zdCByZWFkZXJSZWYgPSByZWFkZXI7XHJcblxyXG4gICAgcmVhZGVyLm9ubG9hZCA9ICgpID0+IHtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBjb25zdCBleGlzdGluZ0dVSUQgPSB0aGlzLmdldEV4aXN0aW5nRmlsZUdVSUQoZmlsZSk7XHJcbiAgICAgICAgdGhpcy51cGRhdGVRdWV1ZUl0ZW1Gb3JTeW5jKGZpbGUpO1xyXG5cclxuICAgICAgICBjb25zdCBhZGRlZEZpbGUgPSB0aGlzLmNyZWF0ZVN5bmNGaWxlRFRPKGZpbGUsIHJlYWRlci5yZXN1bHQgYXMgc3RyaW5nLCBleGlzdGluZ0dVSUQpO1xyXG4gICAgICAgIHRoaXMudXBkYXRlRm9ybVZhbHVlKGFkZGVkRmlsZSwgZmlsZXNBcnJheSk7XHJcbiAgICAgICAgdGhpcy5oYW5kbGVQYXRjaEFuZEVtaXQoKTtcclxuICAgICAgfSBmaW5hbGx5IHtcclxuICAgICAgICAvLyBDbGVhbiB1cCByZWFkZXJcclxuICAgICAgICByZWFkZXJSZWYub25sb2FkID0gbnVsbDtcclxuICAgICAgICByZWFkZXJSZWYub25lcnJvciA9IG51bGw7XHJcbiAgICAgICAgcmVhZGVyUmVmLm9uYWJvcnQgPSBudWxsO1xyXG4gICAgICB9XHJcbiAgICB9O1xyXG5cclxuICAgIHJlYWRlci5vbmVycm9yID0gKCkgPT4ge1xyXG4gICAgICBjb25zb2xlLmVycm9yKCdGaWxlIHJlYWRpbmcgZmFpbGVkJyk7XHJcbiAgICAgIHJlYWRlclJlZi5vbmxvYWQgPSBudWxsO1xyXG4gICAgICByZWFkZXJSZWYub25lcnJvciA9IG51bGw7XHJcbiAgICAgIHJlYWRlclJlZi5vbmFib3J0ID0gbnVsbDtcclxuICAgIH07XHJcblxyXG4gICAgcmVhZGVyLnJlYWRBc0RhdGFVUkwoZmlsZS5yYXdGaWxlIGFzIEZpbGUpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB1cGRhdGVRdWV1ZUl0ZW1Gb3JTeW5jKGZpbGU6IEZpbGVMaWtlT2JqZWN0KTogdm9pZCB7XHJcbiAgICBjb25zdCBxdWV1ZUl0ZW0gPSB0aGlzLmZpbmRRdWV1ZUl0ZW1CeUZpbGUoZmlsZSk7XHJcblxyXG4gICAgaWYgKHF1ZXVlSXRlbSkge1xyXG4gICAgICB0aGlzLnByZXNlcnZlRmlsZVJlZmVyZW5jZShxdWV1ZUl0ZW0sIGZpbGUpO1xyXG4gICAgICBxdWV1ZUl0ZW0ucHJvZ3Jlc3MgPSB0aGlzLlBST0dSRVNTX0NPTVBMRVRFO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBmaW5kUXVldWVJdGVtQnlGaWxlKGZpbGU6IEZpbGVMaWtlT2JqZWN0KTogRmlsZUl0ZW0gfCB1bmRlZmluZWQge1xyXG4gICAgcmV0dXJuIHRoaXMudXBsb2FkZXIucXVldWUuZmluZChpdGVtID0+XHJcbiAgICAgIGl0ZW0uZmlsZS5uYW1lID09PSBmaWxlLm5hbWUgJiYgaXRlbS5maWxlLnNpemUgPT09IGZpbGUuc2l6ZVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcHJlc2VydmVGaWxlUmVmZXJlbmNlKHF1ZXVlSXRlbTogRmlsZUl0ZW0sIGZpbGU6IEZpbGVMaWtlT2JqZWN0KTogdm9pZCB7XHJcbiAgICAocXVldWVJdGVtLl9maWxlIGFzIGFueSkucmF3RmlsZSA9IGZpbGUucmF3RmlsZTtcclxuICAgIChxdWV1ZUl0ZW0uZmlsZSBhcyBhbnkpLnJhd0ZpbGUgPSBmaWxlLnJhd0ZpbGU7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNyZWF0ZVN5bmNGaWxlRFRPKGZpbGU6IEZpbGVMaWtlT2JqZWN0LCByZWFkZXJSZXN1bHQ6IHN0cmluZywgZXhpc3RpbmdHVUlEOiBzdHJpbmcgfCBudWxsKTogRmlsZURUTyB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBmaWxlTmFtZTogZmlsZS5uYW1lLFxyXG4gICAgICBmaWxlVHlwZTogZmlsZS50eXBlLFxyXG4gICAgICBmaWxlQmFzZTY0OiByZWFkZXJSZXN1bHQuc3BsaXQoJywnKVsxXSxcclxuICAgICAgZmlsZVNpemVJbk1COiBmaWxlLnNpemUgLyB0aGlzLkJZVEVTX1RPX01CLFxyXG4gICAgICBuYW1lV2l0aEV4dGVuc2lvbjogZmlsZS5uYW1lLFxyXG4gICAgICBpRF9HVUlEOiBleGlzdGluZ0dVSUQsXHJcbiAgICAgIGlzTmV3OiB0cnVlLFxyXG4gICAgICBmdWxsRmlsZVVSTDogbnVsbFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0RXhpc3RpbmdGaWxlR1VJRChmaWxlOiBGaWxlTGlrZU9iamVjdCk6IHN0cmluZyB8IG51bGwge1xyXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuaXNNdWx0aXBsZUZpbGUgJiYgdGhpcy5maWxlKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLmZpbGUubmFtZVdpdGhFeHRlbnNpb24gPT09IGZpbGUubmFtZSA/IHRoaXMuZmlsZS5pRF9HVUlEIDogbnVsbDtcclxuICAgIH1cclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB1cGRhdGVGb3JtVmFsdWUoYWRkZWRGaWxlOiBGaWxlRFRPLCBmaWxlc0FycmF5OiBGaWxlRFRPW10pOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5vcHRpb25zLmlzTXVsdGlwbGVGaWxlKSB7XHJcbiAgICAgIHRoaXMuZmlsZVVwbG9hZE1vZGVsID0gbmV3IEZpbGVVcGxvYWRNb2RlbCgpO1xyXG4gICAgICB0aGlzLmZpbGVVcGxvYWRNb2RlbC5maWxlID0gYWRkZWRGaWxlO1xyXG4gICAgICB0aGlzLnVwZGF0ZUZvcm1Db250cm9sKHRoaXMuZmlsZVVwbG9hZE1vZGVsKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGZpbGVzQXJyYXkucHVzaChhZGRlZEZpbGUpO1xyXG4gICAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLnVwbG9hZGVkRmlsZXMgPSBmaWxlc0FycmF5O1xyXG4gICAgICB0aGlzLnNldHVwTXVsdGlwbGVGaWxlTW9kZWwoKTtcclxuICAgICAgdGhpcy51cGRhdGVGb3JtQ29udHJvbCh0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsKTtcclxuICAgICAgdGhpcy5pc1VwbG9hZENvbXBsZXRlLmVtaXQodHJ1ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldHVwTXVsdGlwbGVGaWxlTW9kZWwoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5vcHRpb25zLnZhbHVlPy5jb3JyZWxhdGlvbklEX0dVSUQgPT0gbnVsbCkge1xyXG4gICAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLnJlbW92ZWRGaWxlcyA9IFtdO1xyXG4gICAgfVxyXG4gICAgdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbC5jb3JyZWxhdGlvbklEX0dVSUQgPSB0aGlzLm9wdGlvbnMudmFsdWU/LmNvcnJlbGF0aW9uSURfR1VJRDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgdXBkYXRlRm9ybUNvbnRyb2wodmFsdWU6IEZpbGVVcGxvYWRNb2RlbCB8IE11bHRpcGxlRmlsZVVwbG9hZE1vZGVsKTogdm9pZCB7XHJcbiAgICB0aGlzLnByZXNlcnZlRXJyb3JzQW5kVXBkYXRlVmFsdWUodmFsdWUpO1xyXG4gICAgdGhpcy5vcHRpb25zLnZhbHVlID0gdmFsdWU7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHByZXNlcnZlRXJyb3JzQW5kVXBkYXRlVmFsdWUodmFsdWU6IEZpbGVVcGxvYWRNb2RlbCB8IE11bHRpcGxlRmlsZVVwbG9hZE1vZGVsKTogdm9pZCB7XHJcbiAgICBjb25zdCBjdXJyZW50RXJyb3JzID0gdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuZXJyb3JzO1xyXG5cclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnNldFZhbHVlKHZhbHVlLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XHJcbiAgICB0aGlzLmdyb3VwLmdldCh0aGlzLm9wdGlvbnMubmFtZSk/LnNldFZhbHVlKHZhbHVlLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XHJcbiAgICBpZiAoY3VycmVudEVycm9ycykge1xyXG4gICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5zZXRFcnJvcnMoY3VycmVudEVycm9ycyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGhhbmRsZVBhdGNoQW5kRW1pdCgpOiB2b2lkIHtcclxuICAgIGNvbnN0IG9yaWdpbmFsVmFsdWUgPSB0aGlzLmdyb3VwLmdldCh0aGlzLm9wdGlvbnMubmFtZSk/LnZhbHVlO1xyXG5cclxuICAgIGlmICh0aGlzLm9wdGlvbnMucGF0Y2hGdW5jdGlvbiAmJiB0aGlzLm9wdGlvbnMucGF0Y2hQYXRoICYmIHRoaXMuZ3JvdXAuZ2V0KHRoaXMub3B0aW9ucy5uYW1lKT8udmFsaWQpIHtcclxuICAgICAgdGhpcy5jb250cm9sVXRpbGl0eS5wYXRjaENvbnRyb2xWYWx1ZShcclxuICAgICAgICBvcmlnaW5hbFZhbHVlLFxyXG4gICAgICAgIHRoaXMub3B0aW9ucy5wYXRjaEZ1bmN0aW9uLFxyXG4gICAgICAgIHRoaXMub3B0aW9ucy5wYXRjaFBhdGhcclxuICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLk9uQ2hhbmdlLmVtaXQob3JpZ2luYWxWYWx1ZSk7XHJcbiAgfVxyXG4gIHJlbW92ZUZyb21Db250cm9sVmFsdWUoaXRlbTogRmlsZUl0ZW0pOiB2b2lkIHtcclxuICAgIC8vIENsZWFuIHVwIGJsb2IgVVJMIGJlZm9yZSByZW1vdmluZ1xyXG4gICAgY29uc3QgZG93bmxvYWRVcmwgPSB0aGlzLmdldEZpbGVEb3dubG9hZFVybChpdGVtKTtcclxuICAgIGlmIChkb3dubG9hZFVybCAmJiBkb3dubG9hZFVybC5zdGFydHNXaXRoKCdibG9iOicpKSB7XHJcbiAgICAgIHRoaXMuY2xlYW51cEJsb2JVcmwoZG93bmxvYWRVcmwpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuaGFuZGxlQXN5bmNGaWxlRGVsZXRpb24oaXRlbSk7XHJcblxyXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuaXNNdWx0aXBsZUZpbGUpIHtcclxuICAgICAgdGhpcy5oYW5kbGVTaW5nbGVGaWxlUmVtb3ZhbCgpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5oYW5kbGVNdWx0aXBsZUZpbGVSZW1vdmFsKGl0ZW0pO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuY2hlY2tBbmRDbGVhck1heEZpbGVDb3VudFZhbGlkYXRpb24oKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgaGFuZGxlQXN5bmNGaWxlRGVsZXRpb24oaXRlbTogRmlsZUl0ZW0pOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLm9wdGlvbnMuaXNVcGxvYWRGaWxlQXN5bmMgJiZcclxuICAgICAgaXRlbS5wcm9ncmVzcyA9PT0gdGhpcy5QUk9HUkVTU19DT01QTEVURSAmJlxyXG4gICAgICBpdGVtLl9maWxlWydpc05ldyddKSB7XHJcblxyXG4gICAgICBjb25zdCBkZWxldGVTdWJzY3JpcHRpb24gPSB0aGlzLmZpbGVVcGxvYWRTZXJ2aWNlLmRlbGV0ZUZpbGUoaXRlbS5fZmlsZVsnaURfR1VJRCddKS5zdWJzY3JpYmUoe1xyXG4gICAgICAgIGVycm9yOiAoZXJyb3IpID0+IGNvbnNvbGUuZXJyb3IoJ0RlbGV0ZSBmYWlsZWQ6JywgZXJyb3IpXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLmFkZChkZWxldGVTdWJzY3JpcHRpb24pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBoYW5kbGVTaW5nbGVGaWxlUmVtb3ZhbCgpOiB2b2lkIHtcclxuICAgIHRoaXMudXBsb2FkZXIucXVldWUgPSBbXTtcclxuXHJcbiAgICB0aGlzLmZpbGVVcGxvYWRNb2RlbCA9IG51bGwgYXMgYW55O1xyXG5cclxuICAgIGlmICh0aGlzLm9wdGlvbnMuaXNSZXF1aXJlZCkge1xyXG4gICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5tYXJrQXNUb3VjaGVkKCk7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgY3VycmVudEVycm9ycyA9IHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLmVycm9ycztcclxuXHJcbiAgICB0aGlzLmdyb3VwLmdldCh0aGlzLm9wdGlvbnMubmFtZSk/LnNldFZhbHVlKHRoaXMuZmlsZVVwbG9hZE1vZGVsLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XHJcbiAgICBpZiAoY3VycmVudEVycm9ycykge1xyXG4gICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5zZXRFcnJvcnMoY3VycmVudEVycm9ycyk7XHJcbiAgICB9XHJcbiAgICB0aGlzLm9wdGlvbnMudmFsdWUgPSB0aGlzLmZpbGVVcGxvYWRNb2RlbDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgaGFuZGxlTXVsdGlwbGVGaWxlUmVtb3ZhbChpdGVtOiBGaWxlSXRlbSk6IHZvaWQge1xyXG4gICAgLy8gQ2xlYW4gdXAgYmxvYiBVUkxcclxuICAgIGNvbnN0IGRvd25sb2FkVXJsID0gdGhpcy5nZXRGaWxlRG93bmxvYWRVcmwoaXRlbSk7XHJcbiAgICBpZiAoZG93bmxvYWRVcmwgJiYgZG93bmxvYWRVcmwuc3RhcnRzV2l0aCgnYmxvYjonKSkge1xyXG4gICAgICB0aGlzLmNsZWFudXBCbG9iVXJsKGRvd25sb2FkVXJsKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBxdWV1ZUluZGV4ID0gdGhpcy51cGxvYWRlci5xdWV1ZS5pbmRleE9mKGl0ZW0pO1xyXG4gICAgaWYgKHF1ZXVlSW5kZXggPiAtMSkge1xyXG4gICAgICB0aGlzLnVwbG9hZGVyLnF1ZXVlLnNwbGljZShxdWV1ZUluZGV4LCAxKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnByb2Nlc3NGaWxlUmVtb3ZhbEZyb21FeGlzdGluZyhpdGVtKTtcclxuICAgIHRoaXMucmVtb3ZlRnJvbVVwbG9hZGVkRmlsZXMoaXRlbSk7XHJcbiAgICB0aGlzLnZhbGlkYXRlUmVtYWluaW5nRmlsZXMoKTtcclxuICAgIHRoaXMudXBkYXRlTXVsdGlwbGVGaWxlTW9kZWwoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcHJvY2Vzc0ZpbGVSZW1vdmFsRnJvbUV4aXN0aW5nKGl0ZW06IEZpbGVJdGVtKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy52YWx1ZSkge1xyXG4gICAgICB0aGlzLnJlc2V0RGVsZXRlZEZpbGVzKCk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy52YWx1ZS5jb3JyZWxhdGlvbklEX0dVSUQpIHtcclxuICAgICAgdGhpcy5yZXNldERlbGV0ZWRGaWxlcygpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5oYW5kbGVFeGlzdGluZ0ZpbGVSZW1vdmFsKGl0ZW0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSByZXNldERlbGV0ZWRGaWxlcygpOiB2b2lkIHtcclxuICAgIHRoaXMuZGVsZXRlZEZpbGVzID0gW107XHJcbiAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLnJlbW92ZWRGaWxlcyA9IFtdO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBoYW5kbGVFeGlzdGluZ0ZpbGVSZW1vdmFsKGl0ZW06IEZpbGVJdGVtKTogdm9pZCB7XHJcbiAgICBjb25zdCBmaWxlTmFtZSA9IGl0ZW0uZmlsZS5yYXdGaWxlLm5hbWU7XHJcbiAgICBjb25zdCBleGlzdGluZ0ZpbGUgPSB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLmV4aXN0aW5nRmlsZXNcclxuICAgICAgLmZpbmQob2JqID0+IG9iai5uYW1lV2l0aEV4dGVuc2lvbiA9PT0gZmlsZU5hbWUpO1xyXG5cclxuICAgIGlmIChleGlzdGluZ0ZpbGUgJiYgIXRoaXMuZGVsZXRlZEZpbGVzLnNvbWUob2JqID0+IG9iai5uYW1lV2l0aEV4dGVuc2lvbiA9PT0gZmlsZU5hbWUpKSB7XHJcbiAgICAgIHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwuZXhpc3RpbmdGaWxlcyA9XHJcbiAgICAgICAgdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbC5leGlzdGluZ0ZpbGVzLmZpbHRlcihcclxuICAgICAgICAgIG9iaiA9PiBvYmoubmFtZVdpdGhFeHRlbnNpb24gIT09IGZpbGVOYW1lXHJcbiAgICAgICAgKTtcclxuICAgICAgdGhpcy5kZWxldGVkRmlsZXMucHVzaChleGlzdGluZ0ZpbGUpO1xyXG4gICAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLnJlbW92ZWRGaWxlcy5wdXNoKGV4aXN0aW5nRmlsZS5pRF9HVUlEKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgcmVtb3ZlRnJvbVVwbG9hZGVkRmlsZXMoaXRlbTogRmlsZUl0ZW0pOiB2b2lkIHtcclxuICAgIGNvbnN0IGl0ZW1GaWxlTmFtZSA9IGl0ZW0uX2ZpbGUubmFtZSB8fCBpdGVtLmZpbGUubmFtZTtcclxuICAgIGNvbnN0IGl0ZW1GaWxlU2l6ZSA9IGl0ZW0uX2ZpbGUuc2l6ZSB8fCBpdGVtLmZpbGUuc2l6ZTtcclxuICAgIGNvbnN0IGl0ZW1HVUlEID0gaXRlbS5fZmlsZVsnaURfR1VJRCddO1xyXG5cclxuICAgIHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwudXBsb2FkZWRGaWxlcyA9XHJcbiAgICAgIHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwudXBsb2FkZWRGaWxlcy5maWx0ZXIob2JqID0+IHtcclxuICAgICAgICBpZiAoaXRlbUdVSUQgJiYgb2JqLmlEX0dVSUQpIHtcclxuICAgICAgICAgIHJldHVybiBvYmouaURfR1VJRCAhPT0gaXRlbUdVSUQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IG9iakZpbGVOYW1lID0gb2JqLm5hbWVXaXRoRXh0ZW5zaW9uIHx8IG9iai5maWxlTmFtZTtcclxuICAgICAgICBjb25zdCBvYmpGaWxlU2l6ZSA9IG9iai5maWxlU2l6ZUluTUIgPyBvYmouZmlsZVNpemVJbk1CICogdGhpcy5CWVRFU19UT19NQiA6IDA7XHJcblxyXG4gICAgICAgIHJldHVybiAhKG9iakZpbGVOYW1lID09PSBpdGVtRmlsZU5hbWUgJiYgTWF0aC5hYnMob2JqRmlsZVNpemUgLSBpdGVtRmlsZVNpemUpIDwgMTAwMCk7XHJcbiAgICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB2YWxpZGF0ZVJlbWFpbmluZ0ZpbGVzKCk6IHZvaWQge1xyXG4gICAgaWYgKCghdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbC51cGxvYWRlZEZpbGVzIHx8XHJcbiAgICAgIHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwudXBsb2FkZWRGaWxlcy5sZW5ndGggPT09IDApICYmXHJcbiAgICAgIHRoaXMub3B0aW9ucy5pc1JlcXVpcmVkKSB7XHJcbiAgICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnNldEVycm9ycyh7XHJcbiAgICAgICAgTWluRmlsZUNvdW50VmFsaWRhdGlvbktleTogdGhpcy5vcHRpb25zLm1pbk5vT2ZGaWxlc1xyXG4gICAgICB9KTtcclxuICAgICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wubWFya0FzVG91Y2hlZCgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB1cGRhdGVNdWx0aXBsZUZpbGVNb2RlbCgpOiB2b2lkIHtcclxuICAgIHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwuY29ycmVsYXRpb25JRF9HVUlEID0gdGhpcy5vcHRpb25zLnZhbHVlPy5jb3JyZWxhdGlvbklEX0dVSUQ7XHJcblxyXG4gICAgY29uc3QgY3VycmVudEVycm9ycyA9IHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLmVycm9ycztcclxuXHJcbiAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5zZXRWYWx1ZSh0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XHJcbiAgICB0aGlzLmdyb3VwLmdldCh0aGlzLm9wdGlvbnMubmFtZSk/LnNldFZhbHVlKHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcclxuICAgIHRoaXMub3B0aW9ucy52YWx1ZSA9IHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWw7XHJcbiAgICBpZiAoY3VycmVudEVycm9ycykge1xyXG4gICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5zZXRFcnJvcnMoY3VycmVudEVycm9ycyk7XHJcbiAgICB9XHJcbiAgfVxyXG4gIHJlbW92ZVJlcXVpcmVkVmFsaWRhdGlvbiA9ICgpOiB2b2lkID0+IHtcclxuICAgIHRoaXMuY29udHJvbFV0aWxpdHkucmVtb3ZlUmVxdWlyZWRWYWxpZGF0aW9uKFxyXG4gICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbCxcclxuICAgICAgdGhpcy52YWxpZGF0aW9uUnVsZXMsXHJcbiAgICAgIHRoaXMub3B0aW9uc1xyXG4gICAgKTtcclxuICB9O1xyXG5cclxuICBhZGRSZXF1aXJlZFZhbGlkYXRpb24gPSAoKTogdm9pZCA9PiB7XHJcbiAgICB0aGlzLmNvbnRyb2xVdGlsaXR5LmFkZFJlcXVpcmVkVmFsaWRhdGlvbihcclxuICAgICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wsXHJcbiAgICAgIHRoaXMudmFsaWRhdGlvblJ1bGVzLFxyXG4gICAgICB0aGlzLm9wdGlvbnNcclxuICAgICk7XHJcbiAgfTtcclxuXHJcbiAgcmVtb3ZlQ3VzdG9tVmFsaWRhdGlvbiA9IChjdXN0b21WYWxpZGF0aW9uOiBhbnkpOiB2b2lkID0+IHtcclxuICAgIHRoaXMuY29udHJvbFV0aWxpdHkucmVtb3ZlQ3VzdG9tVmFsaWRhdGlvbihcclxuICAgICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wsXHJcbiAgICAgIHRoaXMudmFsaWRhdGlvblJ1bGVzLFxyXG4gICAgICBjdXN0b21WYWxpZGF0aW9uXHJcbiAgICApO1xyXG4gIH07XHJcblxyXG4gIGFkZEN1c3RvbVZhbGlkYXRpb24gPSAoY3VzdG9tVmFsaWRhdGlvbjogYW55KTogdm9pZCA9PiB7XHJcbiAgICB0aGlzLmNvbnRyb2xVdGlsaXR5LmFkZEN1c3RvbVZhbGlkYXRpb24oXHJcbiAgICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLFxyXG4gICAgICB0aGlzLnZhbGlkYXRpb25SdWxlcyxcclxuICAgICAgY3VzdG9tVmFsaWRhdGlvblxyXG4gICAgKTtcclxuICB9O1xyXG5cclxuICBpc1ZhbGlkID0gKCk6IGJvb2xlYW4gPT4ge1xyXG4gICAgdGhpcy5jb250cm9sVXRpbGl0eS5pc1ZhbGlkKHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sKTtcclxuICAgIHJldHVybiB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC52YWxpZDtcclxuICB9O1xyXG4gIGNvbnZlcnRTaXplVG9NQihzaXplOiBudW1iZXIpOiBudW1iZXIge1xyXG4gICAgaWYgKHNpemUgPT09IDApIHtcclxuICAgICAgcmV0dXJuIDA7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgQllURVNfVE9fTUJfQUNDVVJBVEUgPSAxMDI0ICogMTAyNDtcclxuICAgIGNvbnN0IG1lZ2FieXRlcyA9IHNpemUgLyBCWVRFU19UT19NQl9BQ0NVUkFURTtcclxuICAgIHJldHVybiBNYXRoLnJvdW5kKG1lZ2FieXRlcyAqIDEwMCkgLyAxMDA7XHJcbiAgfVxyXG5cclxuICB0cmFja0J5RnVuY3Rpb24oaW5kZXg6IG51bWJlciwgaXRlbTogRmlsZUl0ZW0pOiBhbnkge1xyXG4gICAgcmV0dXJuIGl0ZW0uX2ZpbGUgPyBpdGVtLl9maWxlLm5hbWUgKyBpdGVtLl9maWxlLnNpemUgOiBpbmRleDtcclxuICB9XHJcblxyXG4gIHNob3VsZFNob3dGaWxlTGlzdCgpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLnVwbG9hZGVyPy5xdWV1ZSAmJiB0aGlzLnVwbG9hZGVyLnF1ZXVlLmxlbmd0aCA+IDA7XHJcbiAgfVxyXG5cclxuICBpc0Rvd25sb2FkRW5hYmxlZCgpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0cnVlO1xyXG4gIH1cclxuXHJcbiAgaXNSZW1vdmVFbmFibGVkKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuICF0aGlzLm9wdGlvbnMuaXNSZWFkb25seSAmJiAhdGhpcy5vcHRpb25zLmlzRGlzYWJsZWQ7XHJcbiAgfVxyXG5cclxuICBnZXRGaWxlRG93bmxvYWRVcmwoaXRlbTogRmlsZUl0ZW0pOiBzdHJpbmcgfCBudWxsIHtcclxuICAgIGNvbnN0IGV4aXN0aW5nVXJsID0gdGhpcy5nZXRFeGlzdGluZ0ZpbGVVcmwoaXRlbSk7XHJcbiAgICBpZiAoZXhpc3RpbmdVcmwpIHtcclxuICAgICAgcmV0dXJuIGV4aXN0aW5nVXJsO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0aGlzLmNyZWF0ZUZpbGVVcmwoaXRlbSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldEV4aXN0aW5nRmlsZVVybChpdGVtOiBGaWxlSXRlbSk6IHN0cmluZyB8IG51bGwge1xyXG4gICAgcmV0dXJuIChpdGVtPy5maWxlIGFzIGFueSk/LnVybCB8fFxyXG4gICAgICAoaXRlbT8uX2ZpbGUgYXMgYW55KT8udXJsIHx8XHJcbiAgICAgIChpdGVtIGFzIGFueSk/LnVybCB8fFxyXG4gICAgICAoaXRlbT8uZmlsZSBhcyBhbnkpPy5yYXdGaWxlPy51cmwgfHxcclxuICAgICAgKGl0ZW0/Ll9maWxlIGFzIGFueSk/LnJhd0ZpbGU/LnVybCB8fFxyXG4gICAgICBudWxsO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjcmVhdGVGaWxlVXJsKGl0ZW06IEZpbGVJdGVtKTogc3RyaW5nIHwgbnVsbCB7XHJcbiAgICBjb25zdCBmaWxlTmFtZSA9IHRoaXMuZ2V0RmlsZU5hbWUoaXRlbSk7XHJcbiAgICBjb25zdCBmaWxlVHlwZSA9IGl0ZW0/LmZpbGU/LnR5cGUgfHwgKGl0ZW0/Ll9maWxlIGFzIGFueSk/LnR5cGU7XHJcblxyXG4gICAgY29uc3Qgb3JpZ2luYWxGaWxlID0gKGl0ZW0/Ll9maWxlIGFzIGFueSk/LnJhd0ZpbGUgfHwgKGl0ZW0/LmZpbGUgYXMgYW55KT8ucmF3RmlsZTtcclxuICAgIGlmIChvcmlnaW5hbEZpbGUgJiYgb3JpZ2luYWxGaWxlIGluc3RhbmNlb2YgRmlsZSkge1xyXG4gICAgICByZXR1cm4gVVJMLmNyZWF0ZU9iamVjdFVSTChvcmlnaW5hbEZpbGUpO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGJhc2U2NERhdGEgPSB0eXBlb2Ygb3JpZ2luYWxGaWxlID09PSAnc3RyaW5nJyA/IG9yaWdpbmFsRmlsZSA6IG51bGw7XHJcbiAgICBpZiAoYmFzZTY0RGF0YSAmJiBmaWxlTmFtZSkge1xyXG4gICAgICByZXR1cm4gdGhpcy5jcmVhdGVCbG9iVXJsV2l0aEZpbGVuYW1lKGJhc2U2NERhdGEsIGZpbGVUeXBlLCBmaWxlTmFtZSk7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgZmlsZUlkID0gKGl0ZW0/Ll9maWxlIGFzIGFueSk/LlsnaURfR1VJRCddO1xyXG4gICAgaWYgKGZpbGVJZCAmJiB0aGlzLm9wdGlvbnMuaXNVcGxvYWRGaWxlQXN5bmMpIHtcclxuICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0RG93bmxvYWRVcmwoZmlsZUlkLCBmaWxlTmFtZSk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNyZWF0ZUJsb2JVcmxXaXRoRmlsZW5hbWUoYmFzZTY0RGF0YTogc3RyaW5nLCBmaWxlVHlwZTogc3RyaW5nLCBmaWxlTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIHRyeSB7XHJcbiAgICAgIGNvbnN0IGJ5dGVDaGFyYWN0ZXJzID0gYXRvYihiYXNlNjREYXRhKTtcclxuICAgICAgY29uc3QgYnl0ZU51bWJlcnMgPSBuZXcgQXJyYXkoYnl0ZUNoYXJhY3RlcnMubGVuZ3RoKTtcclxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBieXRlQ2hhcmFjdGVycy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIGJ5dGVOdW1iZXJzW2ldID0gYnl0ZUNoYXJhY3RlcnMuY2hhckNvZGVBdChpKTtcclxuICAgICAgfVxyXG4gICAgICBjb25zdCBieXRlQXJyYXkgPSBuZXcgVWludDhBcnJheShieXRlTnVtYmVycyk7XHJcbiAgICAgIGNvbnN0IGJsb2IgPSBuZXcgQmxvYihbYnl0ZUFycmF5XSwgeyB0eXBlOiBmaWxlVHlwZSB8fCAnYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtJyB9KTtcclxuXHJcbiAgICAgIHJldHVybiBVUkwuY3JlYXRlT2JqZWN0VVJMKGJsb2IpO1xyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgY29uc3QgZXJyb3JNc2cgPSB0aGlzLnV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ0Vycm9yQ3JlYXRpbmdCbG9iVXJsJyk7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3JNc2csIGVycm9yKTtcclxuICAgICAgcmV0dXJuIGBkYXRhOiR7ZmlsZVR5cGUgfHwgJ2FwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSd9O2Jhc2U2NCwke2Jhc2U2NERhdGF9YDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgY29uc3RydWN0RG93bmxvYWRVcmwoZmlsZUlkOiBzdHJpbmcsIGZpbGVOYW1lPzogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGRvd25sb2FkQmFzZVVybCA9ICh0aGlzLm9wdGlvbnMgYXMgYW55KS5kb3dubG9hZEJhc2VVcmw7XHJcbiAgICBsZXQgdXJsOiBzdHJpbmc7XHJcblxyXG4gICAgaWYgKGRvd25sb2FkQmFzZVVybCkge1xyXG4gICAgICB1cmwgPSBgJHtkb3dubG9hZEJhc2VVcmx9LyR7ZmlsZUlkfWA7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB1cmwgPSBgL2FwaS9maWxlcy9kb3dubG9hZC8ke2ZpbGVJZH1gO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChmaWxlTmFtZSkge1xyXG4gICAgICBjb25zdCBzZXBhcmF0b3IgPSB1cmwuaW5jbHVkZXMoJz8nKSA/ICcmJyA6ICc/JztcclxuICAgICAgdXJsICs9IGAke3NlcGFyYXRvcn1maWxlbmFtZT0ke2VuY29kZVVSSUNvbXBvbmVudChmaWxlTmFtZSl9YDtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdXJsO1xyXG4gIH1cclxuXHJcbiAgZ2V0RmlsZU5hbWUoaXRlbTogRmlsZUl0ZW0pOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIGl0ZW0/LmZpbGU/Lm5hbWUgfHwgKGl0ZW0/Ll9maWxlIGFzIGFueSk/Lm5hbWUgfHwgJ2ZpbGUnO1xyXG4gIH1cclxuXHJcbiAgZG93bmxvYWRGaWxlKGl0ZW06IEZpbGVJdGVtKTogdm9pZCB7XHJcbiAgICBjb25zdCBkb3dubG9hZEluZm8gPSB0aGlzLnByZXBhcmVGaWxlRG93bmxvYWQoaXRlbSk7XHJcblxyXG4gICAgaWYgKCFkb3dubG9hZEluZm8udXJsKSB7XHJcbiAgICAgIHRoaXMuaGFuZGxlRG93bmxvYWRFcnJvcihkb3dubG9hZEluZm8uZmlsZU5hbWUpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5leGVjdXRlRmlsZURvd25sb2FkKGRvd25sb2FkSW5mby51cmwsIGRvd25sb2FkSW5mby5maWxlTmFtZSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHByZXBhcmVGaWxlRG93bmxvYWQoaXRlbTogRmlsZUl0ZW0pOiBEb3dubG9hZEluZm8ge1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgdXJsOiB0aGlzLmdldEZpbGVEb3dubG9hZFVybChpdGVtKSxcclxuICAgICAgZmlsZU5hbWU6IHRoaXMuZ2V0RmlsZU5hbWUoaXRlbSlcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGhhbmRsZURvd25sb2FkRXJyb3IoZmlsZU5hbWU6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgY29uc3QgZXJyb3JNc2cgPSB0aGlzLnV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ05vRG93bmxvYWRVcmxBdmFpbGFibGUnKVxyXG4gICAgICAucmVwbGFjZSgne2ZpbGVOYW1lfScsIGZpbGVOYW1lKTtcclxuICAgIGNvbnNvbGUuZXJyb3IoZXJyb3JNc2cpO1xyXG5cclxuICB9XHJcblxyXG4gIHByaXZhdGUgZXhlY3V0ZUZpbGVEb3dubG9hZCh1cmw6IHN0cmluZywgZmlsZU5hbWU6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgY29uc3QgbGluayA9IHRoaXMuY3JlYXRlRG93bmxvYWRMaW5rKHVybCwgZmlsZU5hbWUpO1xyXG4gICAgdGhpcy50cmlnZ2VyRG93bmxvYWQobGluayk7XHJcbiAgICB0aGlzLmNsZWFudXBCbG9iVXJsKHVybCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNyZWF0ZURvd25sb2FkTGluayh1cmw6IHN0cmluZywgZmlsZU5hbWU6IHN0cmluZyk6IEhUTUxBbmNob3JFbGVtZW50IHtcclxuICAgIGNvbnN0IGxpbmsgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XHJcbiAgICBsaW5rLmhyZWYgPSB1cmw7XHJcbiAgICBsaW5rLmRvd25sb2FkID0gZmlsZU5hbWU7XHJcbiAgICBsaW5rLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XHJcbiAgICByZXR1cm4gbGluaztcclxuICB9XHJcblxyXG4gIHByaXZhdGUgdHJpZ2dlckRvd25sb2FkKGxpbms6IEhUTUxBbmNob3JFbGVtZW50KTogdm9pZCB7XHJcbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGxpbmspO1xyXG4gICAgbGluay5jbGljaygpO1xyXG4gICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChsaW5rKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY2xlYW51cEJsb2JVcmwodXJsOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmICh1cmwuc3RhcnRzV2l0aCgnYmxvYjonKSkge1xyXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICBVUkwucmV2b2tlT2JqZWN0VVJMKHVybCk7XHJcbiAgICAgIH0sIDEwMCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHRyYWNrTWVtb3J5VXNhZ2UoZmlsZVNpemU6IG51bWJlcik6IHZvaWQge1xyXG4gICAgdGhpcy5jdXJyZW50TWVtb3J5VXNhZ2UgKz0gZmlsZVNpemU7XHJcblxyXG4gICAgLy8gSWYgbWVtb3J5IHVzYWdlIGV4Y2VlZHMgbGltaXQsIGNsZWFuIHVwIG9sZCBmaWxlc1xyXG4gICAgaWYgKHRoaXMuY3VycmVudE1lbW9yeVVzYWdlID4gdGhpcy5NQVhfTUVNT1JZX1VTQUdFKSB7XHJcbiAgICAgIHRoaXMuY2xlYW51cE9sZEZpbGVzKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNsZWFudXBPbGRGaWxlcygpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnVwbG9hZGVyPy5xdWV1ZSAmJiB0aGlzLnVwbG9hZGVyLnF1ZXVlLmxlbmd0aCA+IDApIHtcclxuICAgICAgLy8gUmVtb3ZlIG9sZGVzdCBmaWxlcyB0byBmcmVlIG1lbW9yeVxyXG4gICAgICBjb25zdCBvbGRlc3RGaWxlID0gdGhpcy51cGxvYWRlci5xdWV1ZS5zaGlmdCgpO1xyXG4gICAgICBpZiAob2xkZXN0RmlsZSkge1xyXG4gICAgICAgIGNvbnN0IHVybCA9IHRoaXMuZ2V0RmlsZURvd25sb2FkVXJsKG9sZGVzdEZpbGUpO1xyXG4gICAgICAgIGlmICh1cmwgJiYgdXJsLnN0YXJ0c1dpdGgoJ2Jsb2I6JykpIHtcclxuICAgICAgICAgIHRoaXMuY2xlYW51cEJsb2JVcmwodXJsKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5jdXJyZW50TWVtb3J5VXNhZ2UgLT0gKG9sZGVzdEZpbGUuZmlsZT8uc2l6ZSB8fCAwKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjbGVhbnVwRXZlbnRMaXN0ZW5lcnMoKTogdm9pZCB7XHJcbiAgICAvLyBDbGVhciBmaWxlIGlucHV0IHJlZmVyZW5jZXNcclxuICAgIGlmICh0aGlzLmZpbGVJbnB1dD8ubmF0aXZlRWxlbWVudCkge1xyXG4gICAgICB0aGlzLmZpbGVJbnB1dC5uYXRpdmVFbGVtZW50LnZhbHVlID0gJyc7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ2xlYXIgdXBsb2FkZXIgcXVldWUgdG8gcHJldmVudCBtZW1vcnkgbGVha3NcclxuICAgIGlmICh0aGlzLnVwbG9hZGVyPy5xdWV1ZSkge1xyXG4gICAgICB0aGlzLnVwbG9hZGVyLnF1ZXVlID0gW107XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNsZWFudXBVcGxvYWRlclF1ZXVlKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMudXBsb2FkZXI/LnF1ZXVlKSB7XHJcbiAgICAgIC8vIENsZWFyIGFsbCBpdGVtcyBhbmQgdGhlaXIgYXNzb2NpYXRlZCByZXNvdXJjZXNcclxuICAgICAgdGhpcy51cGxvYWRlci5xdWV1ZS5mb3JFYWNoKGl0ZW0gPT4ge1xyXG4gICAgICAgIC8vIENsZWFuIHVwIGJsb2IgVVJMc1xyXG4gICAgICAgIGNvbnN0IHVybCA9IHRoaXMuZ2V0RmlsZURvd25sb2FkVXJsKGl0ZW0pO1xyXG4gICAgICAgIGlmICh1cmwgJiYgdXJsLnN0YXJ0c1dpdGgoJ2Jsb2I6JykpIHtcclxuICAgICAgICAgIHRoaXMuY2xlYW51cEJsb2JVcmwodXJsKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIENsZWFyIGZpbGUgcmVmZXJlbmNlc1xyXG4gICAgICAgIGlmIChpdGVtLl9maWxlKSB7XHJcbiAgICAgICAgICBpdGVtLl9maWxlID0gbnVsbCBhcyBhbnk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChpdGVtLmZpbGUpIHtcclxuICAgICAgICAgIGl0ZW0uZmlsZSA9IG51bGwgYXMgYW55O1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICAvLyBDbGVhciB0aGUgcXVldWVcclxuICAgICAgdGhpcy51cGxvYWRlci5xdWV1ZSA9IFtdO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICAvLyBDbGVhbiB1cCBzdWJzY3JpcHRpb25zXHJcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMudW5zdWJzY3JpYmUoKTtcclxuXHJcbiAgICAvLyBDbGVhbiB1cCB1cGxvYWRlciBxdWV1ZVxyXG4gICAgdGhpcy5jbGVhbnVwVXBsb2FkZXJRdWV1ZSgpO1xyXG5cclxuICAgIC8vIENsZWFuIHVwIGV2ZW50IGxpc3RlbmVyc1xyXG4gICAgdGhpcy5jbGVhbnVwRXZlbnRMaXN0ZW5lcnMoKTtcclxuXHJcbiAgICAvLyBDbGVhbiB1cCBibG9iIFVSTHNcclxuICAgIGlmICh0aGlzLnVwbG9hZGVyPy5xdWV1ZSkge1xyXG4gICAgICB0aGlzLnVwbG9hZGVyLnF1ZXVlLmZvckVhY2goaXRlbSA9PiB7XHJcbiAgICAgICAgY29uc3QgdXJsID0gdGhpcy5nZXRGaWxlRG93bmxvYWRVcmwoaXRlbSk7XHJcbiAgICAgICAgaWYgKHVybCAmJiB1cmwuc3RhcnRzV2l0aCgnYmxvYjonKSkge1xyXG4gICAgICAgICAgVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNoZWNrQW5kQ2xlYXJNYXhGaWxlQ291bnRWYWxpZGF0aW9uKCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMubWF4Tm9PZkZpbGVzIHx8IHRoaXMub3B0aW9ucy5tYXhOb09mRmlsZXMgPD0gMCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgY3VycmVudFF1ZXVlTGVuZ3RoID0gdGhpcy51cGxvYWRlci5xdWV1ZS5sZW5ndGg7XHJcbiAgICBpZiAoY3VycmVudFF1ZXVlTGVuZ3RoIDw9IHRoaXMub3B0aW9ucy5tYXhOb09mRmlsZXMpIHtcclxuICAgICAgdGhpcy5jbGVhckZpbGVDb3VudEVycm9yKCdNYXhGaWxlQ291bnRWYWxpZGF0aW9uS2V5Jyk7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiIsIjxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwIGJic2YtY29udHJvbCBiYnNmLWZpbGUtdXBsb2FkXCIgW2Zvcm1Hcm91cF09XCJncm91cFwiPlxyXG4gIDxkaXYgW25nQ2xhc3NdPVwib3B0aW9ucy52aWV3VHlwZSA9PT0gMSA/ICdiYnNmLXZlcnRpY2FsJyA6ICdiYnNmLWhvcml6b250YWwnXCI+XHJcbiAgICA8IS0tIExhYmVsIC0tPlxyXG4gICAgPGxhYmVsIFtoaWRkZW5dPVwib3B0aW9ucy5oaWRlTGFiZWxcIiBjbGFzcz1cImJic2YtbGFiZWwge3sgb3B0aW9ucy5sYWJlbEV4dHJhQ2xhc3NlcyB9fVwiPlxyXG4gICAgICB7eyBvcHRpb25zLmxhYmVsVmFsdWUgfX1cclxuICAgICAgPCEtLSBSZXF1aXJlZCBhc3RlcmlzayAtLT5cclxuICAgICAgPHNwYW4gKm5nSWY9XCJvcHRpb25zLmlzUmVxdWlyZWQgJiYgIW9wdGlvbnMuaXNSZWFkb25seSAmJiAob3B0aW9ucy5zaG93QXN0ZXJpc2sgfHwgdHJ1ZSlcIlxyXG4gICAgICAgIGNsYXNzPVwidGV4dC1kYW5nZXJcIj4qPC9zcGFuPlxyXG4gICAgPC9sYWJlbD5cclxuICAgIDwhLS0gRHJvcCB6b25lIGVuYWJsZWQgLS0+XHJcbiAgICA8ZGl2IG5nMkZpbGVEcm9wIGNsYXNzPVwiYmJzZi1pbnB1dC1jb250YWluZXIge3sgb3B0aW9ucy5leHRyYUNsYXNzZXMgfX1cIlxyXG4gICAgICAqbmdJZj1cIm9wdGlvbnMuaXNEcm9wWm9uZSAmJiAhaXNIaWRlSW5wdXQoKSAmJiAhb3B0aW9ucy5pc1JlYWRvbmx5XCJcclxuICAgICAgW25nQ2xhc3NdPVwieyAnYW5vdGhlci1maWxlLW92ZXItY2xhc3MnOiBoYXNBbm90aGVyRHJvcFpvbmVPdmVyIH1cIiAob25GaWxlRHJvcCk9XCJvbkZpbGVDaGFuZ2UoKVwiXHJcbiAgICAgIChmaWxlT3Zlcik9XCJmaWxlT3ZlckFub3RoZXIoJGV2ZW50KVwiIFt1cGxvYWRlcl09XCJ1cGxvYWRlclwiIFthY2NlcHRdPVwiYWNjZXB0ZWRUeXBlXCIgW2lkXT1cIm9wdGlvbnMubmFtZVwiXHJcbiAgICAgIFthdHRyLm11bHRpcGxlXT1cIm9wdGlvbnMuaXNNdWx0aXBsZUZpbGUgPyAnbXVsdGlwbGUnIDogbnVsbFwiXHJcbiAgICAgIFtjbGFzcy5pcy1pbnZhbGlkXT1cImZpbGVVcGxvYWRGb3JtQ29udHJvbC5pbnZhbGlkICYmIGZpbGVVcGxvYWRGb3JtQ29udHJvbC50b3VjaGVkXCJcclxuICAgICAgKGNsaWNrKT1cImZpbGVJbnB1dENvbnRyb2wuY2xpY2soKVwiPlxyXG5cclxuICAgICAgPGRpdiBjbGFzcz1cImRyb3B6b25lLWxhYmVsXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInN2Zy1hbmQtdmFsaWRhdGlvblwiPlxyXG4gICAgICAgICAgPCEtLSBVcGxvYWQgaWNvbiAtLT5cclxuICAgICAgICAgIDxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHdpZHRoPVwiNzBcIiBoZWlnaHQ9XCI3MFwiIHZpZXdCb3g9XCIwIDAgNzAgNzBcIiBmaWxsPVwibm9uZVwiPlxyXG4gICAgICAgICAgICA8cGF0aCBvcGFjaXR5PVwiMC40XCJcclxuICAgICAgICAgICAgICBkPVwiTTU4LjMzMyA0OC44MzMyQzYxLjg5NTcgNDUuODkwOCA2NC4xNjYzIDQxLjQzOTcgNjQuMTY2MyAzNi40NTgzQzY0LjE2NjMgMjcuNTk4OCA1Ni45ODQzIDIwLjQxNjcgNDguMTI0NyAyMC40MTY3QzQ3LjQ4NzQgMjAuNDE2NyA0Ni44OTEyIDIwLjA4NDIgNDYuNTY3NSAxOS41MzUxQzQyLjc2NDEgMTMuMDgwOCAzNS43NDE3IDguNzUgMjcuNzA4IDguNzVDMTUuNjI2OCA4Ljc1IDUuODMzMDEgMTguNTQzOCA1LjgzMzAxIDMwLjYyNUM1LjgzMzAxIDM2LjY1MTEgOC4yNjk3NCA0Mi4xMDgyIDEyLjIxMTYgNDYuMDY0NFwiXHJcbiAgICAgICAgICAgICAgc3Ryb2tlPVwiIzRCNTQ4OVwiIHN0cm9rZS13aWR0aD1cIjJcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIiAvPlxyXG4gICAgICAgICAgICA8cGF0aCBkPVwiTTIzLjMzMyA0Ni42NjY3TDM0Ljk5OTcgMzVNMzQuOTk5NyAzNUw0Ni42NjYzIDQ2LjY2NjdNMzQuOTk5NyAzNVY2MS4yNVwiIHN0cm9rZT1cIiM0QjU0ODlcIlxyXG4gICAgICAgICAgICAgIHN0cm9rZS13aWR0aD1cIjJcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIiAvPlxyXG4gICAgICAgICAgPC9zdmc+XHJcblxyXG4gICAgICAgICAgPCEtLSBJbnN0cnVjdGlvbiB0ZXh0IC0tPlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJic2YtdmFsaWRhdGlvbi1tc2cgdmFsaWRhdGlvbi1tc2ctaGVhZGVyIHRleHQtY2VudGVyXCI+XHJcbiAgICAgICAgICAgIHt7IHV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ0RyYWdBbmREcm9wSGVyZScpIH19XHJcbiAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICA8IS0tIFZhbGlkYXRpb24gbWVzc2FnZXMgLS0+XHJcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiYmJzZi12YWxpZGF0aW9uLW1zZyB0ZXh0LWNlbnRlclwiICpuZ0lmPVwidmFsaWRhdGlvbk1lc3NhZ2VcIiBbaW5uZXJIVE1MXT1cInZhbGlkYXRpb25NZXNzYWdlXCI+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiYmJzZi12YWxpZGF0aW9uLW1zZyB0ZXh0LWNlbnRlciB0ZXh0LWRhbmdlclwiXHJcbiAgICAgICAgICAgICpuZ0lmPVwidmFsaWRhdGlvbkNvdW50TWVzc2FnZSAmJiBvcHRpb25zLmlzTXVsdGlwbGVGaWxlICYmIG9wdGlvbnMubWF4Tm9PZkZpbGVzID4gMFwiXHJcbiAgICAgICAgICAgIFtpbm5lckhUTUxdPVwidmFsaWRhdGlvbkNvdW50TWVzc2FnZVwiPlxyXG4gICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgPCEtLSBIaWRkZW4gZmlsZSBpbnB1dCAtLT5cclxuICAgICAgPGlucHV0IG5nMkZpbGVTZWxlY3QgW3VwbG9hZGVyXT1cInVwbG9hZGVyXCIgW2FjY2VwdF09XCJhY2NlcHRlZFR5cGVcIlxyXG4gICAgICAgIGNsYXNzPVwiZmlsZVNlbGVjdG9yIGN1c3RvbUZpbGVVcGxvYWRQbGFjbWVudCBoaWRkZW4gdi1yZXF1aXJlZC1tdWx0aXBsZWZpbGVzIGQtbm9uZVwiXHJcbiAgICAgICAgW2F0dHIubXVsdGlwbGVdPVwib3B0aW9ucy5pc011bHRpcGxlRmlsZSA/ICdtdWx0aXBsZScgOiBudWxsXCIgbmFtZT1cImZpbGVcIiB0eXBlPVwiZmlsZVwiIGF1dG9jb21wbGV0ZT1cIm9mZlwiXHJcbiAgICAgICAgKGNoYW5nZSk9XCJvbkZpbGVDaGFuZ2UoKVwiIFtuZ0NsYXNzXT1cIm9wdGlvbnMudmlld1R5cGUgPT09IDEgPyAnJyA6ICdjb2wtbWQtOSdcIiBbaWRdPVwib3B0aW9ucy5uYW1lXCJcclxuICAgICAgICAjZmlsZUlucHV0Q29udHJvbCBbY2xhc3MuaXMtaW52YWxpZF09XCJmaWxlVXBsb2FkRm9ybUNvbnRyb2wuaW52YWxpZCAmJiBmaWxlVXBsb2FkRm9ybUNvbnRyb2wudG91Y2hlZFwiIC8+XHJcbiAgICA8L2Rpdj5cclxuICAgIDwhLS0gQ2xpY2sgdG8gdXBsb2FkIChubyBkcm9wIHpvbmUpIC0tPlxyXG4gICAgPGRpdiBjbGFzcz1cImJic2YtaW5wdXQtY29udGFpbmVyXCIgKm5nSWY9XCIhb3B0aW9ucy5pc0Ryb3Bab25lICYmICFpc0hpZGVJbnB1dCgpICYmICFvcHRpb25zLmlzUmVhZG9ubHlcIlxyXG4gICAgICAoY2xpY2spPVwiZmlsZUlucHV0LmNsaWNrKClcIj5cclxuXHJcbiAgICAgIDxkaXYgY2xhc3M9XCJkcm9wem9uZS1sYWJlbFwiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJzdmctYW5kLXZhbGlkYXRpb25cIj5cclxuICAgICAgICAgIDwhLS0gVXBsb2FkIGljb24gLS0+XHJcbiAgICAgICAgICA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB3aWR0aD1cIjcwXCIgaGVpZ2h0PVwiNzBcIiB2aWV3Qm94PVwiMCAwIDcwIDcwXCIgZmlsbD1cIm5vbmVcIj5cclxuICAgICAgICAgICAgPHBhdGggb3BhY2l0eT1cIjAuNFwiXHJcbiAgICAgICAgICAgICAgZD1cIk01OC4zMzMgNDguODMzMkM2MS44OTU3IDQ1Ljg5MDggNjQuMTY2MyA0MS40Mzk3IDY0LjE2NjMgMzYuNDU4M0M2NC4xNjYzIDI3LjU5ODggNTYuOTg0MyAyMC40MTY3IDQ4LjEyNDcgMjAuNDE2N0M0Ny40ODc0IDIwLjQxNjcgNDYuODkxMiAyMC4wODQyIDQ2LjU2NzUgMTkuNTM1MUM0Mi43NjQxIDEzLjA4MDggMzUuNzQxNyA4Ljc1IDI3LjcwOCA4Ljc1QzE1LjYyNjggOC43NSA1LjgzMzAxIDE4LjU0MzggNS44MzMwMSAzMC42MjVDNS44MzMwMSAzNi42NTExIDguMjY5NzQgNDIuMTA4MiAxMi4yMTE2IDQ2LjA2NDRcIlxyXG4gICAgICAgICAgICAgIHN0cm9rZT1cIiM0QjU0ODlcIiBzdHJva2Utd2lkdGg9XCIyXCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIgLz5cclxuICAgICAgICAgICAgPHBhdGggZD1cIk0yMy4zMzMgNDYuNjY2N0wzNC45OTk3IDM1TTM0Ljk5OTcgMzVMNDYuNjY2MyA0Ni42NjY3TTM0Ljk5OTcgMzVWNjEuMjVcIiBzdHJva2U9XCIjNEI1NDg5XCJcclxuICAgICAgICAgICAgICBzdHJva2Utd2lkdGg9XCIyXCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIgLz5cclxuICAgICAgICAgIDwvc3ZnPlxyXG5cclxuICAgICAgICAgIDwhLS0gVXBsb2FkIHRleHQgLS0+XHJcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiYmJzZi12YWxpZGF0aW9uLW1zZyB0ZXh0LWNlbnRlclwiPlxyXG4gICAgICAgICAgICB7eyB1dGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdVcGxvYWQnKSB9fVxyXG4gICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgPCEtLSBWYWxpZGF0aW9uIG1lc3NhZ2VzIC0tPlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJic2YtdmFsaWRhdGlvbi1tc2cgdGV4dC1jZW50ZXJcIiAqbmdJZj1cInZhbGlkYXRpb25NZXNzYWdlXCIgW2lubmVySFRNTF09XCJ2YWxpZGF0aW9uTWVzc2FnZVwiPlxyXG4gICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJic2YtdmFsaWRhdGlvbi1tc2cgdGV4dC1jZW50ZXIgdGV4dC1kYW5nZXJcIlxyXG4gICAgICAgICAgICAqbmdJZj1cInZhbGlkYXRpb25Db3VudE1lc3NhZ2UgJiYgb3B0aW9ucy5pc011bHRpcGxlRmlsZSAmJiBvcHRpb25zLm1heE5vT2ZGaWxlcyA+IDBcIlxyXG4gICAgICAgICAgICBbaW5uZXJIVE1MXT1cInZhbGlkYXRpb25Db3VudE1lc3NhZ2VcIj5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuXHJcbiAgICAgIDwhLS0gSGlkZGVuIGZpbGUgaW5wdXQgLS0+XHJcbiAgICAgIDxpbnB1dCBuZzJGaWxlU2VsZWN0IFt1cGxvYWRlcl09XCJ1cGxvYWRlclwiIFthY2NlcHRdPVwiYWNjZXB0ZWRUeXBlXCJcclxuICAgICAgICBjbGFzcz1cImZpbGVTZWxlY3RvciBjdXN0b21GaWxlVXBsb2FkUGxhY21lbnQgaGlkZGVuIHYtcmVxdWlyZWQtbXVsdGlwbGVmaWxlcyBkLW5vbmVcIlxyXG4gICAgICAgIFthdHRyLm11bHRpcGxlXT1cIm9wdGlvbnMuaXNNdWx0aXBsZUZpbGUgPyAnbXVsdGlwbGUnIDogbnVsbFwiIG5hbWU9XCJmaWxlXCIgdHlwZT1cImZpbGVcIiBhdXRvY29tcGxldGU9XCJvZmZcIlxyXG4gICAgICAgIChjaGFuZ2UpPVwib25GaWxlQ2hhbmdlKClcIiBbbmdDbGFzc109XCJvcHRpb25zLnZpZXdUeXBlID09PSAxID8gJycgOiAnY29sLW1kLTknXCIgW2lkXT1cIm9wdGlvbnMubmFtZVwiICNmaWxlSW5wdXRcclxuICAgICAgICBbY2xhc3MuaXMtaW52YWxpZF09XCJmaWxlVXBsb2FkRm9ybUNvbnRyb2wuaW52YWxpZCAmJiBmaWxlVXBsb2FkRm9ybUNvbnRyb2wudG91Y2hlZFwiIC8+XHJcbiAgICA8L2Rpdj5cclxuICAgIDwhLS0gUmVhZC1vbmx5IHN0YXRlIHdpdGggbm8gZmlsZXMgLS0+XHJcbiAgICA8ZGl2ICpuZ0lmPVwib3B0aW9ucy5pc1JlYWRvbmx5ICYmICghb3B0aW9ucy52YWx1ZSB8fCAodXBsb2FkZXIucXVldWUgJiYgdXBsb2FkZXIucXVldWUubGVuZ3RoID09PSAwKSlcIj5cclxuICAgICAgPHNwYW4gY2xhc3M9XCJyZWFkb25seS12aWV3XCI+e3sgdXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSgnTkEnKSB9fTwvc3Bhbj5cclxuICAgIDwvZGl2PlxyXG4gIDwvZGl2PlxyXG4gIDwhLS0gVXBsb2FkZWQgZmlsZXMgbGlzdCAtLT5cclxuICA8ZGl2IGNsYXNzPVwidXBsb2FkZWQtaXRlbXNcIiAqbmdJZj1cInNob3VsZFNob3dGaWxlTGlzdCgpXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwiYnRuLWdyb3VwXCIgKm5nRm9yPVwibGV0IGl0ZW0gb2YgdXBsb2FkZXIucXVldWU7IHRyYWNrQnk6IHRyYWNrQnlGdW5jdGlvblwiPlxyXG5cclxuICAgICAgPCEtLSBBc3luYyB1cGxvYWQgY29tcGxldGVkIGZpbGVzIC0tPlxyXG4gICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiaXRlbT8ucHJvZ3Jlc3MgPT09IDEwMCAmJiBvcHRpb25zLmlzVXBsb2FkRmlsZUFzeW5jXCI+XHJcbiAgICAgICAgPCEtLSBEb3dubG9hZCBsaW5rIC0gYWx3YXlzIHZpc2libGUgLS0+XHJcbiAgICAgICAgPGJ1dHRvbiAqbmdJZj1cImdldEZpbGVEb3dubG9hZFVybChpdGVtKTsgZWxzZSBub1VybFRlbXBsYXRlXCIgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICBjbGFzcz1cImJ0bi1kb3dubG9hZC1maWxlIGJ0bi1zbSBidG4tcHJvZ3Jlc3MtdXBsb2FkXCIgKGNsaWNrKT1cImRvd25sb2FkRmlsZShpdGVtKVwiXHJcbiAgICAgICAgICBbdGl0bGVdPVwiJ0Rvd25sb2FkICcgKyBnZXRGaWxlTmFtZShpdGVtKVwiPlxyXG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJmaWxlLW5hbWVcIj57eyBnZXRGaWxlTmFtZShpdGVtKSB9fTwvc3Bhbj5cclxuICAgICAgICA8L2J1dHRvbj5cclxuXHJcbiAgICAgICAgPCEtLSBGaWxlIG5hbWUgZGlzcGxheSB3aGVuIG5vIFVSTCBhdmFpbGFibGUgLS0+XHJcbiAgICAgICAgPG5nLXRlbXBsYXRlICNub1VybFRlbXBsYXRlPlxyXG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJidG4tZG93bmxvYWQtZmlsZSBidG4tc20gYnRuLXByb2dyZXNzLXVwbG9hZFwiIFt0aXRsZV09XCJnZXRGaWxlTmFtZShpdGVtKVwiPlxyXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImZpbGUtbmFtZVwiPnt7IGdldEZpbGVOYW1lKGl0ZW0pIH19PC9zcGFuPlxyXG4gICAgICAgICAgPC9zcGFuPlxyXG4gICAgICAgIDwvbmctdGVtcGxhdGU+XHJcblxyXG4gICAgICAgIDwhLS0gUmVtb3ZlIGJ1dHRvbiAtIG9ubHkgc2hvdyB3aGVuIG5vdCByZWFkb25seSBhbmQgbm90IGRpc2FibGVkIC0tPlxyXG4gICAgICAgIDxidXR0b24gKm5nSWY9XCJpc1JlbW92ZUVuYWJsZWQoKVwiIGNsYXNzPVwiYnRuIGJ0bi1kb3dubG9hZC1maWxlIGJ0bi1zbVwiIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgKGNsaWNrKT1cIml0ZW0ucmVtb3ZlKCk7IHJlbW92ZUZyb21Db250cm9sVmFsdWUoaXRlbSlcIiBbYXR0ci5hcmlhLWxhYmVsXT1cIidSZW1vdmUgJyArIGdldEZpbGVOYW1lKGl0ZW0pXCJcclxuICAgICAgICAgIFt0aXRsZV09XCInUmVtb3ZlICcgKyBnZXRGaWxlTmFtZShpdGVtKVwiPlxyXG4gICAgICAgICAgPCEtLSBEZWxldGUgaWNvbiAtLT5cclxuICAgICAgICAgIDxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHdpZHRoPVwiMTRcIiBoZWlnaHQ9XCIxNFwiIHZpZXdCb3g9XCIwIDAgMTQgMTRcIiBmaWxsPVwibm9uZVwiPlxyXG4gICAgICAgICAgICA8cGF0aCBvcGFjaXR5PVwiMC40XCJcclxuICAgICAgICAgICAgICBkPVwiTTkuMzMzMDEgMy43MDU4NFYzLjI2NjYzQzkuMzMzMDEgMi42NTE2NiA5LjMzMzAxIDIuMzQ0MTkgOS4yMDU4NyAyLjEwOTNDOS4wOTQwNSAxLjkwMjcgOC45MTU1NSAxLjczNDcxIDguNjk2MDQgMS42Mjk0NEM4LjQ0NjQ3IDEuNTA5NzcgOC4xMTk3NyAxLjUwOTc3IDcuNDY2MzggMS41MDk3N0g2LjUzMzA1QzUuODc5NjUgMS41MDk3NyA1LjU1Mjk2IDEuNTA5NzcgNS4zMDMzOSAxLjYyOTQ0QzUuMDgzODcgMS43MzQ3MSA0LjkwNTM5IDEuOTAyNyA0Ljc5MzU0IDIuMTA5M0M0LjY2NjM4IDIuMzQ0MTkgNC42NjYzOCAyLjY1MTY2IDQuNjY2MzggMy4yNjY2M1YzLjcwNTg0XCJcclxuICAgICAgICAgICAgICBzdHJva2U9XCIjRDgzNzMxXCIgc3Ryb2tlLXdpZHRoPVwiMS41XCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIgLz5cclxuICAgICAgICAgICAgPHBhdGhcclxuICAgICAgICAgICAgICBkPVwiTTEuNzUgMy43MDYwNUgxMi4yNU0xMS4wODM0IDMuNzA2MDVWOS44NTUxQzExLjA4MzQgMTAuNzc3NSAxMS4wODM0IDExLjIzODcgMTAuODkyNiAxMS41OTFDMTAuNzI0OCAxMS45MDEgMTAuNDU3MSAxMi4xNTI5IDEwLjEyNzggMTIuMzEwOUM5Ljc1MzQ1IDEyLjQ5MDQgOS4yNjM0NSAxMi40OTA0IDguMjgzMzQgMTIuNDkwNEg1LjcxNjY2QzQuNzM2NTggMTIuNDkwNCA0LjI0NjUzIDEyLjQ5MDQgMy44NzIxOCAxMi4zMTA5QzMuNTQyOSAxMi4xNTI5IDMuMjc1MTkgMTEuOTAxIDMuMTA3NDEgMTEuNTkxQzIuOTE2NjYgMTEuMjM4NyAyLjkxNjY2IDEwLjc3NzUgMi45MTY2NiA5Ljg1NTFWMy43MDYwNVwiXHJcbiAgICAgICAgICAgICAgc3Ryb2tlPVwiI0Q4MzczMVwiIHN0cm9rZS13aWR0aD1cIjEuNVwiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiIC8+XHJcbiAgICAgICAgICA8L3N2Zz5cclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgPC9uZy1jb250YWluZXI+XHJcblxyXG4gICAgICA8IS0tIFN5bmMgdXBsb2FkIGZpbGVzIC0tPlxyXG4gICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIW9wdGlvbnMuaXNVcGxvYWRGaWxlQXN5bmNcIj5cclxuICAgICAgICA8IS0tIERvd25sb2FkIGxpbmsgLSBhbHdheXMgdmlzaWJsZSAtLT5cclxuICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tZG93bmxvYWQtZmlsZSBidG4tc21cIiAoY2xpY2spPVwiZG93bmxvYWRGaWxlKGl0ZW0pXCJcclxuICAgICAgICAgIFt0aXRsZV09XCInRG93bmxvYWQgJyArIGdldEZpbGVOYW1lKGl0ZW0pXCI+XHJcbiAgICAgICAgICA8IS0tIERvd25sb2FkIGljb24gLS0+XHJcbiAgICAgICAgICA8c3ZnIHdpZHRoPVwiMjRcIiBoZWlnaHQ9XCIyNFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwibm9uZVwiIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIj5cclxuICAgICAgICAgICAgPHBhdGhcclxuICAgICAgICAgICAgICBkPVwiTTIxIDIySDNDMi40IDIyIDIgMjEuNiAyIDIxQzIgMjAuNCAyLjQgMjAgMyAyMEgyMUMyMS42IDIwIDIyIDIwLjQgMjIgMjFDMjIgMjEuNiAyMS42IDIyIDIxIDIyWk0xMyAxMy40VjNDMTMgMi40IDEyLjYgMiAxMiAyQzExLjQgMiAxMSAyLjQgMTEgM1YxMy40SDEzWlwiXHJcbiAgICAgICAgICAgICAgZmlsbD1cImN1cnJlbnRDb2xvclwiPjwvcGF0aD5cclxuICAgICAgICAgICAgPHBhdGggb3BhY2l0eT1cIjAuM1wiIGQ9XCJNNyAxMy40SDE3TDEyLjcgMTcuN0MxMi4zIDE4LjEgMTEuNyAxOC4xIDExLjMgMTcuN0w3IDEzLjRaXCIgZmlsbD1cImN1cnJlbnRDb2xvclwiPlxyXG4gICAgICAgICAgICA8L3BhdGg+XHJcbiAgICAgICAgICA8L3N2Zz5cclxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZmlsZS1uYW1lXCI+e3sgZ2V0RmlsZU5hbWUoaXRlbSkgfX08L3NwYW4+XHJcbiAgICAgICAgPC9idXR0b24+XHJcblxyXG4gICAgICAgIDwhLS0gUmVtb3ZlIGJ1dHRvbiAtIG9ubHkgc2hvdyB3aGVuIG5vdCByZWFkb25seSBhbmQgbm90IGRpc2FibGVkIC0tPlxyXG4gICAgICAgIDxidXR0b24gKm5nSWY9XCJpc1JlbW92ZUVuYWJsZWQoKVwiIGNsYXNzPVwiYnRuIGJ0bi1kb3dubG9hZC1maWxlIGJ0bi1zbSBidG4tZGFuZ2VyXCIgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAoY2xpY2spPVwiaXRlbS5yZW1vdmUoKTsgcmVtb3ZlRnJvbUNvbnRyb2xWYWx1ZShpdGVtKVwiIFthdHRyLmFyaWEtbGFiZWxdPVwiJ1JlbW92ZSAnICsgZ2V0RmlsZU5hbWUoaXRlbSlcIlxyXG4gICAgICAgICAgW3RpdGxlXT1cIidSZW1vdmUgJyArIGdldEZpbGVOYW1lKGl0ZW0pXCI+XHJcbiAgICAgICAgICA8aSBjbGFzcz1cImZhIGZhLXRpbWVzIHB4LTBcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XHJcbiAgICAgICAgPC9idXR0b24+XHJcbiAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcbiAgPCEtLSBGaWxlIHVwbG9hZCBwcm9ncmVzcyBpbmRpY2F0b3JzIC0tPlxyXG4gIDxkaXYgKm5nRm9yPVwibGV0IGl0ZW0gb2YgdXBsb2FkZXIucXVldWU7IHRyYWNrQnk6IHRyYWNrQnlGdW5jdGlvblwiPlxyXG4gICAgPGRpdiBjbGFzcz1cInVwbG9hZC1pdGVtc1wiIFtuZ0NsYXNzXT1cInsgJ210LTQnOiBvcHRpb25zLmlzTXVsdGlwbGVGaWxlIH1cIlxyXG4gICAgICAqbmdJZj1cIml0ZW0/LnByb2dyZXNzIDwgMTAwICYmIG9wdGlvbnMuaXNVcGxvYWRGaWxlQXN5bmMgJiYgIW9wdGlvbnMuaXNSZWFkb25seVwiPlxyXG5cclxuICAgICAgPGRpdiBjbGFzcz1cInVwbG9hZC1pdGVtcy10b29sYmFyXCI+XHJcbiAgICAgICAgPGg0Pnt7IGdldEZpbGVOYW1lKGl0ZW0pIH19PC9oND5cclxuICAgICAgICA8YnV0dG9uICpuZ0lmPVwiaXNSZW1vdmVFbmFibGVkKClcIiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4tY2FuY2VsLXVwbG9hZFwiXHJcbiAgICAgICAgICAoY2xpY2spPVwiaXRlbS5yZW1vdmUoKTsgcmVtb3ZlRnJvbUNvbnRyb2xWYWx1ZShpdGVtKVwiXHJcbiAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidDYW5jZWwgdXBsb2FkIGZvciAnICsgZ2V0RmlsZU5hbWUoaXRlbSlcIj5cclxuICAgICAgICAgIDwhLS0gQ2FuY2VsIGljb24gLS0+XHJcbiAgICAgICAgICA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB3aWR0aD1cIjE4XCIgaGVpZ2h0PVwiMThcIiB2aWV3Qm94PVwiMCAwIDE4IDE4XCIgZmlsbD1cIm5vbmVcIj5cclxuICAgICAgICAgICAgPGcgY2xpcC1wYXRoPVwidXJsKCNjbGlwMF8xMzI0XzEzMjE2KVwiPlxyXG4gICAgICAgICAgICAgIDxwYXRoIG9wYWNpdHk9XCIwLjRcIlxyXG4gICAgICAgICAgICAgICAgZD1cIk05IDE2LjVDMTMuMTQyMSAxNi41IDE2LjUgMTMuMTQyMSAxNi41IDlDMTYuNSA0Ljg1Nzg2IDEzLjE0MjEgMS41IDkgMS41QzQuODU3ODYgMS41IDEuNSA0Ljg1Nzg2IDEuNSA5QzEuNSAxMy4xNDIxIDQuODU3ODYgMTYuNSA5IDE2LjVaXCJcclxuICAgICAgICAgICAgICAgIHN0cm9rZT1cIiNEQkUxRjBcIiBzdHJva2Utd2lkdGg9XCIyXCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIgLz5cclxuICAgICAgICAgICAgICA8cGF0aCBkPVwiTTExLjI1IDYuNzVMNi43NSAxMS4yNU02Ljc1IDYuNzVMMTEuMjUgMTEuMjVcIiBzdHJva2U9XCIjREJFMUYwXCIgc3Ryb2tlLXdpZHRoPVwiMlwiXHJcbiAgICAgICAgICAgICAgICBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIiAvPlxyXG4gICAgICAgICAgICA8L2c+XHJcbiAgICAgICAgICAgIDxkZWZzPlxyXG4gICAgICAgICAgICAgIDxjbGlwUGF0aCBpZD1cImNsaXAwXzEzMjRfMTMyMTZcIj5cclxuICAgICAgICAgICAgICAgIDxyZWN0IHdpZHRoPVwiMThcIiBoZWlnaHQ9XCIxOFwiIGZpbGw9XCJ3aGl0ZVwiIC8+XHJcbiAgICAgICAgICAgICAgPC9jbGlwUGF0aD5cclxuICAgICAgICAgICAgPC9kZWZzPlxyXG4gICAgICAgICAgPC9zdmc+XHJcbiAgICAgICAgPC9idXR0b24+XHJcbiAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgPGRpdiBjbGFzcz1cInByb2dyZXNzXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInByb2dyZXNzLWJhclwiIHJvbGU9XCJwcm9ncmVzc2JhclwiIFthdHRyLmFyaWEtdmFsdWVub3ddPVwiaXRlbT8ucHJvZ3Jlc3NcIiBhcmlhLXZhbHVlbWluPVwiMFwiXHJcbiAgICAgICAgICBhcmlhLXZhbHVlbWF4PVwiMTAwXCIgW2NsYXNzLmZpbGUtdXBsb2FkZWRdPVwiaXRlbT8ucHJvZ3Jlc3MgPCAxMDBcIiBbc3R5bGUud2lkdGguJV09XCJpdGVtPy5wcm9ncmVzc1wiXHJcbiAgICAgICAgICAqbmdJZj1cIml0ZW0/LnByb2dyZXNzID4gMFwiPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG4gIDwvZGl2PlxyXG5cclxuICA8IS0tIFZhbGlkYXRpb24gYW5kIGRlc2NyaXB0aW9uIHNlY3Rpb24gLS0+XHJcbiAgPGRpdiBjbGFzcz1cInN1YnRleHQtY29udGFpbmVyXCIgKm5nSWY9XCIhb3B0aW9ucy5pc1JlYWRvbmx5XCI+XHJcbiAgICA8IS0tIFZhbGlkYXRpb24gbWVzc2FnZXMgLS0+XHJcbiAgICA8ZGl2IGNsYXNzPVwiYmJzZi12YWxpZGF0aW9uXCIgKm5nSWY9XCJmaWxlVXBsb2FkRm9ybUNvbnRyb2wuaW52YWxpZCAmJiBmaWxlVXBsb2FkRm9ybUNvbnRyb2wudG91Y2hlZFwiPlxyXG4gICAgICA8c3BhbiBbaW5uZXJIVE1MXT1cImdldEVycm9yVmFsaWRhdGlvbihmaWxlVXBsb2FkRm9ybUNvbnRyb2wuZXJyb3JzIHwga2V5dmFsdWUpXCI+PC9zcGFuPlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPCEtLSBDb250cm9sIGRlc2NyaXB0aW9uIC0tPlxyXG4gICAgPGRpdiBjbGFzcz1cImJic2YtY29udHJvbC1kZXNjXCIgKm5nSWY9XCJvcHRpb25zLmxhYmVsRGVzY3JpcHRpb25cIj5cclxuICAgICAge3sgb3B0aW9ucy5sYWJlbERlc2NyaXB0aW9uIH19XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8IS0tIFJlc2V0IGVycm9yIHN0YXRlIC0tPlxyXG4gICAgPGRpdiAqbmdJZj1cIihncm91cC52YWxpZCAmJiBncm91cC5kaXJ0eSAmJiBncm91cC50b3VjaGVkKSB8fCAoZ3JvdXAudW50b3VjaGVkICYmIGdyb3VwLmludmFsaWQgJiYgZ3JvdXAuZGlydHkpXCI+XHJcbiAgICAgIHt7IHJlc2V0RXJyb3IoKSB9fVxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcbjwvZGl2PiJdfQ==
588
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmlsZVVwbG9hZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9iYnNmLWNvbnRyb2xzL3NyYy9saWIvY29udHJvbHMvRmlsZVVwbG9hZC9GaWxlVXBsb2FkLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Jic2YtY29udHJvbHMvc3JjL2xpYi9jb250cm9scy9GaWxlVXBsb2FkL0ZpbGVVcGxvYWQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFFTSxLQUFLLEVBQ3BCLFFBQVEsRUFDUixTQUFTLEVBRVQsTUFBTSxFQUNOLFlBQVksRUFDYixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQ0wsV0FBVyxFQUNYLFVBQVUsRUFLWCxNQUFNLGdCQUFnQixDQUFDO0FBR3hCLE9BQU8sRUFBRSxZQUFZLEVBQWlELE1BQU0saUJBQWlCLENBQUM7QUFDOUYsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLDZDQUE2QyxDQUFDO0FBS3RGLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQzs7Ozs7Ozs7OztBQVFyRCxNQUFNLE9BQU8sbUJBQW1CO2FBQ3ZCLDJCQUFzQixHQUFHLElBQUksQUFBUCxDQUFRO0lBMkJyQyxZQUNzQixnQkFBa0MsRUFDL0MsNkJBQWlELEVBQ2hELGNBQThCLEVBQy9CLGNBQThCLEVBQzdCLHdCQUFrRCxFQUNsRCxjQUE4QixFQUM5QixpQkFBb0M7UUFOeEIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUMvQyxrQ0FBNkIsR0FBN0IsNkJBQTZCLENBQW9CO1FBQ2hELG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQUMvQixtQkFBYyxHQUFkLGNBQWMsQ0FBZ0I7UUFDN0IsNkJBQXdC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T25Jbml0LFxyXG4gIEFmdGVyVmlld0luaXQsIElucHV0LFxyXG4gIE9wdGlvbmFsLFxyXG4gIFZpZXdDaGlsZCxcclxuICBFbGVtZW50UmVmLFxyXG4gIE91dHB1dCxcclxuICBFdmVudEVtaXR0ZXJcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHtcclxuICBGb3JtQ29udHJvbCxcclxuICBWYWxpZGF0b3JzLFxyXG4gIEZvcm1Hcm91cCxcclxuICBBYnN0cmFjdENvbnRyb2wsXHJcbiAgQ29udHJvbENvbnRhaW5lcixcclxuICBGb3JtR3JvdXBEaXJlY3RpdmVcclxufSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcbmltcG9ydCB7IEZpbGVVcGxvYWRPcHRpb25zIH0gZnJvbSAnLi4vLi4vU2hhcmVkL01vZGVscy9GaWxlVXBsb2FkT3B0aW9ucyc7XHJcbmltcG9ydCB7IENvbnRyb2xVdGlsaXR5IH0gZnJvbSAnLi4vLi4vU2hhcmVkL3NlcnZpY2VzL0NvbnRyb2xVdGlsaXR5JztcclxuaW1wb3J0IHsgRmlsZVVwbG9hZGVyLCBGaWxlTGlrZU9iamVjdCwgRmlsZVVwbG9hZGVyT3B0aW9ucywgRmlsZUl0ZW0gfSBmcm9tICduZzItZmlsZS11cGxvYWQnO1xyXG5pbXBvcnQgeyBGaWxlVXBsb2FkTW9kZWwgfSBmcm9tICcuLi8uLi9TaGFyZWQvTW9kZWxzL0ZpbGVVcGxvYWRNb2RlbCc7XHJcbmltcG9ydCB7IE11bHRpcGxlRmlsZVVwbG9hZE1vZGVsIH0gZnJvbSAnLi4vLi4vU2hhcmVkL01vZGVscy9NdWx0aXBsZUZpbGVVcGxvYWRNb2RlbCc7XHJcbmltcG9ydCB7IENvbnRyb2xWYWxpZGF0aW9uU2VydmljZSwgVXRpbGl0eVNlcnZpY2UgfSBmcm9tICdAYm5zaWdodHMvYmJzZi11dGlsaXRpZXMnO1xyXG5pbXBvcnQgeyBHbG9iYWxTZXR0aW5ncyB9IGZyb20gJy4uLy4uL1NoYXJlZC9zZXJ2aWNlcy9HbG9iYWxTZXR0aW5ncy5zZXJ2aWNlJztcclxuaW1wb3J0IHsgRmlsZURUTyB9IGZyb20gJy4uLy4uL1NoYXJlZC9Nb2RlbHMvRmlsZURUTyc7XHJcbmltcG9ydCB7IEZpbGVVcGxvYWRTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vU2hhcmVkL3NlcnZpY2VzL2ZpbGUtdXBsb2FkLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBIdHRwRXZlbnRUeXBlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xyXG5cclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnQkJTRi1GaWxlVXBsb2FkJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vRmlsZVVwbG9hZC5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3RhbmRhbG9uZTogZmFsc2VcclxufSlcclxuZXhwb3J0IGNsYXNzIEZpbGVVcGxvYWRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQge1xyXG4gIHN0YXRpYyBjb250cm9sQ29udGFpbmVyc3RhdGljID0gbnVsbDtcclxuXHJcbiAgQFZpZXdDaGlsZCgnZmlsZUlucHV0JywgeyBzdGF0aWM6IGZhbHNlIH0pIGZpbGVJbnB1dDogRWxlbWVudFJlZjtcclxuXHJcbiAgaXNTdWJtaXR0ZWQ6IGJvb2xlYW47XHJcbiAgQElucHV0KCkgZ3JvdXA6IEZvcm1Hcm91cDtcclxuICBASW5wdXQoKSBvcHRpb25zOiBGaWxlVXBsb2FkT3B0aW9ucztcclxuICBAT3V0cHV0KCkgT25DaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcbiAgQE91dHB1dCgpIGlzVXBsb2FkQ29tcGxldGUgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcblxyXG4gIGZpbGVVcGxvYWRGb3JtQ29udHJvbDogQWJzdHJhY3RDb250cm9sO1xyXG4gIHZhbGlkYXRpb25NZXNzYWdlID0gJyc7XHJcbiAgdmFsaWRhdGlvbkNvdW50TWVzc2FnZSA9ICcnO1xyXG4gIHVwbG9hZGVyOiBGaWxlVXBsb2FkZXI7XHJcbiAgaGFzQW5vdGhlckRyb3Bab25lT3ZlcjogYm9vbGVhbjtcclxuICBhY2NlcHRlZFR5cGU6IHN0cmluZyA9ICcnO1xyXG4gIGFjY2VwdGVkVHlwZUFycmF5OiBzdHJpbmdbXSA9IFtdO1xyXG4gIHRvb2xUaXBUeXBlQXJyYXk6IHN0cmluZ1tdID0gW107XHJcbiAgZmlsZUxpa2VPYmplY3Q6IEZpbGVMaWtlT2JqZWN0O1xyXG4gIG1hcmtBbGxBc1RvdWNoZWQ6IGJvb2xlYW4gPSBmYWxzZTtcclxuICB2YWxpZGF0aW9uUnVsZXMgPSBbXTtcclxuICB2YWxpZGF0aW9uUnVsZXNhc3luYyA9IFtdO1xyXG4gIGZpbGVVcGxvYWRNb2RlbDogRmlsZVVwbG9hZE1vZGVsO1xyXG4gIG11bHRpcGxlRmlsZVVwbG9hZE1vZGVsOiBNdWx0aXBsZUZpbGVVcGxvYWRNb2RlbDtcclxuICBmaWxlOiBhbnk7XHJcbiAgZGVsZXRlZEZpbGVzOiBGaWxlRFRPW10gPSBbXTtcclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBAT3B0aW9uYWwoKSBwcml2YXRlIGNvbnRyb2xDb250YWluZXI6IENvbnRyb2xDb250YWluZXIsXHJcbiAgICBwdWJsaWMgTXVsdGlwbGVGaWxlVXBsYW9kQ29udHJvbEhvc3Q6IEZvcm1Hcm91cERpcmVjdGl2ZSxcclxuICAgIHByaXZhdGUgY29udHJvbFV0aWxpdHk6IENvbnRyb2xVdGlsaXR5LFxyXG4gICAgcHVibGljIFV0aWxpdHlTZXJ2aWNlOiBVdGlsaXR5U2VydmljZSxcclxuICAgIHByaXZhdGUgY29udHJvbFZhbGlkYXRpb25TZXJ2aWNlOiBDb250cm9sVmFsaWRhdGlvblNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGdsb2JhbFNldHRpbmdzOiBHbG9iYWxTZXR0aW5ncyxcclxuICAgIHByaXZhdGUgZmlsZVVwbG9hZFNlcnZpY2U6IEZpbGVVcGxvYWRTZXJ2aWNlXHJcbiAgKSB7XHJcbiAgICBGaWxlVXBsb2FkQ29tcG9uZW50LmNvbnRyb2xDb250YWluZXJzdGF0aWMgPSB0aGlzLmNvbnRyb2xDb250YWluZXI7XHJcbiAgICB0aGlzLnVwbG9hZGVyID0gbmV3IEZpbGVVcGxvYWRlcih7XHJcbiAgICAgIGRpc2FibGVNdWx0aXBhcnQ6IGZhbHNlIC8vICdEaXNhYmxlTXVsdGlwYXJ0JyBtdXN0IGJlICd0cnVlJyBmb3IgZm9ybWF0RGF0YUZ1bmN0aW9uIHRvIGJlIGNhbGxlZC5cclxuICAgIH0gYXMgRmlsZVVwbG9hZGVyT3B0aW9ucyk7XHJcbiAgICB0aGlzLmhhc0Fub3RoZXJEcm9wWm9uZU92ZXIgPSBmYWxzZTtcclxuICB9XHJcblxyXG4gIG5nT25Jbml0KCkge1xyXG4gICAgdGhpcy5maWxlVXBsb2FkTW9kZWwgPSBuZXcgRmlsZVVwbG9hZE1vZGVsKCk7XHJcbiAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsID0gbmV3IE11bHRpcGxlRmlsZVVwbG9hZE1vZGVsKCk7XHJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy52aWV3VHlwZSkgdGhpcy5vcHRpb25zLnZpZXdUeXBlID0gdGhpcy5nbG9iYWxTZXR0aW5ncy52aWV3VHlwZTtcclxuXHJcbiAgICBpZiAodGhpcy5vcHRpb25zLnZhbHVlID09IG51bGwpIHtcclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy5pc011bHRpcGxlRmlsZSA9PSB0cnVlKSB7XHJcbiAgICAgICAgLy90aGlzLm9wdGlvbnMuVmFsdWU9dGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbFxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIHRoaXMub3B0aW9ucy5WYWx1ZT10aGlzLmZpbGVVcGxvYWRNb2RlbFxyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLmlzTXVsdGlwbGVGaWxlID09IHRydWUpIHtcclxuICAgICAgICBsZXQgZmlsZXM6IGFueVtdID0gW107XHJcbiAgICAgICAgdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbC5leGlzdGluZ0ZpbGVzID0gdGhpcy5vcHRpb25zLnZhbHVlLmV4aXN0aW5nRmlsZXM7XHJcbiAgICAgICAgdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbC51cGxvYWRlZEZpbGVzID0gW107XHJcbiAgICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHRoaXMub3B0aW9ucy52YWx1ZS5leGlzdGluZ0ZpbGVzLmxlbmd0aDsgaW5kZXgrKykge1xyXG4gICAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMub3B0aW9ucy52YWx1ZS5leGlzdGluZ0ZpbGVzW2luZGV4XTtcclxuICAgICAgICAgIHZhciBieXRlcyA9IG5ldyBVaW50OEFycmF5KGVsZW1lbnQuYnl0ZXMpIGFzIGFueTtcclxuICAgICAgICAgIHZhciBiYXNlNjQgPSBidG9hKFN0cmluZy5mcm9tQ2hhckNvZGUobnVsbCwgYnl0ZXMpKTtcclxuICAgICAgICAgIHRoaXMuZmlsZUxpa2VPYmplY3QgPSA8RmlsZUxpa2VPYmplY3Q+e1xyXG4gICAgICAgICAgICBuYW1lOiBlbGVtZW50Lm5hbWVXaXRoRXh0ZW5zaW9uLFxyXG4gICAgICAgICAgICB0eXBlOiBlbGVtZW50Lm1pbWVUeXBlLFxyXG4gICAgICAgICAgICByYXdGaWxlOiA8YW55PmJhc2U2NFxyXG4gICAgICAgICAgfTtcclxuICAgICAgICAgIC8vIGxldCBibG9iOiBhbnk7XHJcbiAgICAgICAgICAvLyBibG9iID0gbmV3IEJsb2IoWycnXSkgYXMgYW55O1xyXG4gICAgICAgICAgLy8gYmxvYi5uYW1lID0gZWxlbWVudC5GaWxlTmFtZTtcclxuICAgICAgICAgIC8vIGJsb2IubGFzdE1vZGlmaWVkRGF0ZSA9IG51bGw7XHJcbiAgICAgICAgICAvLyBibG9iLndlYmtpdFJlbGF0aXZlUGF0aCA9ICcnO1xyXG4gICAgICAgICAgbGV0IGZpbGUgPSB0aGlzLmZpbGVMaWtlT2JqZWN0IGFzIGFueTtcclxuICAgICAgICAgIGZpbGUudXJsID0gZWxlbWVudC5maWxlVVJMO1xyXG4gICAgICAgICAgZmlsZXMucHVzaChmaWxlKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy51cGxvYWRlci5hZGRUb1F1ZXVlKGZpbGVzKTtcclxuICAgICAgICBjb25zb2xlLmxvZyh0aGlzLnVwbG9hZGVyLnF1ZXVlKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5vcHRpb25zLnZhbHVlLmZpbGUgPz8gdGhpcy5vcHRpb25zLnZhbHVlO1xyXG4gICAgICAgIHZhciBieXRlcyA9IG5ldyBVaW50OEFycmF5KGVsZW1lbnQuYnl0ZXMpIGFzIGFueTtcclxuICAgICAgICB2YXIgYmFzZTY0ID0gYnRvYShTdHJpbmcuZnJvbUNoYXJDb2RlKG51bGwsIGJ5dGVzKSk7XHJcbiAgICAgICAgdGhpcy5maWxlTGlrZU9iamVjdCA9IDxGaWxlTGlrZU9iamVjdD57XHJcbiAgICAgICAgICBuYW1lOiBlbGVtZW50Lm5hbWVXaXRoRXh0ZW5zaW9uLFxyXG4gICAgICAgICAgdHlwZTogZWxlbWVudC5taW1lVHlwZSxcclxuICAgICAgICAgIHJhd0ZpbGU6IDxhbnk+YmFzZTY0XHJcbiAgICAgICAgfTtcclxuICAgICAgICB0aGlzLmZpbGUgPSBlbGVtZW50O1xyXG4gICAgICAgIGxldCBmaWxlID0gdGhpcy5maWxlTGlrZU9iamVjdCBhcyBhbnk7XHJcbiAgICAgICAgZmlsZS51cmwgPSBlbGVtZW50LmZpbGVVUkw7XHJcbiAgICAgICAgdGhpcy51cGxvYWRlci5hZGRUb1F1ZXVlKFtmaWxlXSk7XHJcbiAgICAgICAgaWYgKCF0aGlzLm9wdGlvbnMudmFsdWUuZmlsZSkge1xyXG4gICAgICAgICAgdGhpcy5maWxlVXBsb2FkTW9kZWwgPSBuZXcgRmlsZVVwbG9hZE1vZGVsKCk7XHJcbiAgICAgICAgICB0aGlzLmZpbGVVcGxvYWRNb2RlbC5maWxlID0gdGhpcy5vcHRpb25zLnZhbHVlO1xyXG4gICAgICAgIH0gZWxzZSB0aGlzLmZpbGVVcGxvYWRNb2RlbCA9IHRoaXMub3B0aW9ucy52YWx1ZTtcclxuICAgICAgICB0aGlzLm9wdGlvbnMudmFsdWUgPSB0aGlzLmZpbGVVcGxvYWRNb2RlbDtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLnVwbG9hZGVyLnF1ZXVlLmZvckVhY2goKGVsZW1lbnQpID0+IHtcclxuICAgICAgICBlbGVtZW50LnByb2dyZXNzID0gMTAwO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5vcHRpb25zLmxhYmVsS2V5ICE9IG51bGwgJiYgdGhpcy5vcHRpb25zLmxhYmVsS2V5ICE9ICcnKVxyXG4gICAgICB0aGlzLm9wdGlvbnMubGFiZWxWYWx1ZSA9IHRoaXMuVXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSh0aGlzLm9wdGlvbnMubGFiZWxLZXkpO1xyXG5cclxuICAgIGlmIChcclxuICAgICAgdGhpcy5vcHRpb25zLmZpbGVVcGxvYWRBY2NlcHRzVHlwZXMgIT0gbnVsbCAmJlxyXG4gICAgICB0aGlzLm9wdGlvbnMuZmlsZVVwbG9hZEFjY2VwdHNUeXBlcy5sZW5ndGggPiAwXHJcbiAgICApIHtcclxuICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHRoaXMub3B0aW9ucy5maWxlVXBsb2FkQWNjZXB0c1R5cGVzLmxlbmd0aDsgaW5kZXgrKykge1xyXG4gICAgICAgIGNvbnN0IFR5cGUgPSB0aGlzLm9wdGlvbnMuZmlsZVVwbG9hZEFjY2VwdHNUeXBlc1tpbmRleF07XHJcbiAgICAgICAgdGhpcy5hY2NlcHRlZFR5cGUgPSB0aGlzLmFjY2VwdGVkVHlwZSArIFR5cGUgKyAnLCc7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5hY2NlcHRlZFR5cGVBcnJheSA9IHRoaXMuYWNjZXB0ZWRUeXBlLnNwbGl0KCcsJyk7XHJcbiAgICAgIHRoaXMuYWNjZXB0ZWRUeXBlQXJyYXkgPSB0aGlzLmFjY2VwdGVkVHlwZUFycmF5LmZpbHRlcigodmFsdWUpID0+IHZhbHVlICE9ICcnKTtcclxuICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHRoaXMuYWNjZXB0ZWRUeXBlQXJyYXkubGVuZ3RoOyBpbmRleCsrKSB7XHJcbiAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuYWNjZXB0ZWRUeXBlQXJyYXlbaW5kZXhdO1xyXG4gICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCB0aGlzLmFjY2VwdGVkVHlwZUFycmF5Lmxlbmd0aDsgaW5kZXgrKykge1xyXG4gICAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuYWNjZXB0ZWRUeXBlQXJyYXlbaW5kZXhdO1xyXG4gICAgICAgICAgc3dpdGNoIChlbGVtZW50KSB7XHJcbiAgICAgICAgICAgIGNhc2UgJ2FwcGxpY2F0aW9uL3BkZic6XHJcbiAgICAgICAgICAgICAgaWYgKCF0aGlzLnRvb2xUaXBUeXBlQXJyYXkuaW5jbHVkZXMoJ1BERicpKSB0aGlzLnRvb2xUaXBUeXBlQXJyYXkucHVzaCgnUERGJyk7XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIGNhc2UgJ2FwcGxpY2F0aW9uL21zd29yZCc6XHJcbiAgICAgICAgICAgICAgaWYgKCF0aGlzLnRvb2xUaXBUeXBlQXJyYXkuaW5jbHVkZXMoJ1dvcmQnKSkgdGhpcy50b29sVGlwVHlwZUFycmF5LnB1c2goJ1dvcmQnKTtcclxuICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSAnYXBwbGljYXRpb24vdm5kLm9wZW54bWxmb3JtYXRzLW9mZmljZWRvY3VtZW50LndvcmRwcm9jZXNzaW5nbWwuZG9jdW1lbnQnOlxyXG4gICAgICAgICAgICAgIGlmICghdGhpcy50b29sVGlwVHlwZUFycmF5LmluY2x1ZGVzKCdXb3JkJykpIHRoaXMudG9vbFRpcFR5cGVBcnJheS5wdXNoKCdXb3JkJyk7XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIGNhc2UgJ2FwcGxpY2F0aW9uL3ZuZC5tcy1leGNlbCc6XHJcbiAgICAgICAgICAgICAgaWYgKCF0aGlzLnRvb2xUaXBUeXBlQXJyYXkuaW5jbHVkZXMoJ0V4Y2VsJykpIHRoaXMudG9vbFRpcFR5cGVBcnJheS5wdXNoKCdFeGNlbCcpO1xyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlICdhcHBsaWNhdGlvbi92bmQub3BlbnhtbGZvcm1hdHMtb2ZmaWNlZG9jdW1lbnQuc3ByZWFkc2hlZXRtbC5zaGVldCc6XHJcbiAgICAgICAgICAgICAgaWYgKCF0aGlzLnRvb2xUaXBUeXBlQXJyYXkuaW5jbHVkZXMoJ0V4Y2VsJykpIHRoaXMudG9vbFRpcFR5cGVBcnJheS5wdXNoKCdFeGNlbCcpO1xyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlICdhcHBsaWNhdGlvbi92bmQubXMtcG93ZXJwb2ludCc6XHJcbiAgICAgICAgICAgICAgaWYgKCF0aGlzLnRvb2xUaXBUeXBlQXJyYXkuaW5jbHVkZXMoJ1Bvd2VyUG9pbnQnKSlcclxuICAgICAgICAgICAgICAgIHRoaXMudG9vbFRpcFR5cGVBcnJheS5wdXNoKCdQb3dlclBvaW50Jyk7XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIGNhc2UgJ2FwcGxpY2F0aW9uL3ZuZC5vcGVueG1sZm9ybWF0cy1vZmZpY2Vkb2N1bWVudC5wcmVzZW50YXRpb25tbC5wcmVzZW50YXRpb24nOlxyXG4gICAgICAgICAgICAgIGlmICghdGhpcy50b29sVGlwVHlwZUFycmF5LmluY2x1ZGVzKCdQb3dlclBvaW50JykpXHJcbiAgICAgICAgICAgICAgICB0aGlzLnRvb2xUaXBUeXBlQXJyYXkucHVzaCgnUG93ZXJQb2ludCcpO1xyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlICdpbWFnZS9wbmcnOlxyXG4gICAgICAgICAgICAgIGlmICghdGhpcy50b29sVGlwVHlwZUFycmF5LmluY2x1ZGVzKCdQTkcnKSkgdGhpcy50b29sVGlwVHlwZUFycmF5LnB1c2goJ1BORycpO1xyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlICdpbWFnZS9ibXAnOlxyXG4gICAgICAgICAgICAgIGlmICghdGhpcy50b29sVGlwVHlwZUFycmF5LmluY2x1ZGVzKCdCTVAnKSkgdGhpcy50b29sVGlwVHlwZUFycmF5LnB1c2goJ0JNUCcpO1xyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlICdpbWFnZS9qcGVnJzpcclxuICAgICAgICAgICAgICBpZiAoIXRoaXMudG9vbFRpcFR5cGVBcnJheS5pbmNsdWRlcygnSlBFRycpKSB0aGlzLnRvb2xUaXBUeXBlQXJyYXkucHVzaCgnSlBFRycpO1xyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlICdhcHBsaWNhdGlvbi96aXAnOlxyXG4gICAgICAgICAgICAgIGlmICghdGhpcy50b29sVGlwVHlwZUFycmF5LmluY2x1ZGVzKCdaSVAnKSkgdGhpcy50b29sVGlwVHlwZUFycmF5LnB1c2goJ1pJUCcpO1xyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlICdhcHBsaWNhdGlvbi94LXJhci1jb21wcmVzc2VkJzpcclxuICAgICAgICAgICAgICBpZiAoIXRoaXMudG9vbFRpcFR5cGVBcnJheS5pbmNsdWRlcygnUkFSJykpIHRoaXMudG9vbFRpcFR5cGVBcnJheS5wdXNoKCdSQVInKTtcclxuICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSAndmlkZW8vbXA0JzpcclxuICAgICAgICAgICAgICBpZiAoIXRoaXMudG9vbFRpcFR5cGVBcnJheS5pbmNsdWRlcygnTVA0JykpIHRoaXMudG9vbFRpcFR5cGVBcnJheS5wdXNoKCdNUDQnKTtcclxuICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSAndmlkZW8vYXZpJzpcclxuICAgICAgICAgICAgICBpZiAoIXRoaXMudG9vbFRpcFR5cGVBcnJheS5pbmNsdWRlcygnQVZJJykpIHRoaXMudG9vbFRpcFR5cGVBcnJheS5wdXNoKCdBVkknKTtcclxuICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSAndmlkZW8vcXVpY2t0aW1lJzpcclxuICAgICAgICAgICAgICBpZiAoIXRoaXMudG9vbFRpcFR5cGVBcnJheS5pbmNsdWRlcygnTU9WJykpIHRoaXMudG9vbFRpcFR5cGVBcnJheS5wdXNoKCdNT1YnKTtcclxuICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSAndmlkZW8vbXBlZyc6XHJcbiAgICAgICAgICAgICAgaWYgKCF0aGlzLnRvb2xUaXBUeXBlQXJyYXkuaW5jbHVkZXMoJ01QRUcnKSkgdGhpcy50b29sVGlwVHlwZUFycmF5LnB1c2goJ01QRUcnKTtcclxuICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSAnYXVkaW8vbXBlZyc6XHJcbiAgICAgICAgICAgICAgaWYgKCF0aGlzLnRvb2xUaXBUeXBlQXJyYXkuaW5jbHVkZXMoJ01QMycpKSB0aGlzLnRvb2xUaXBUeXBlQXJyYXkucHVzaCgnTVAzJyk7XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIGNhc2UgJ3ZpZGVvL3gtZmx2JzpcclxuICAgICAgICAgICAgICBpZiAoIXRoaXMudG9vbFRpcFR5cGVBcnJheS5pbmNsdWRlcygnRkxWJykpIHRoaXMudG9vbFRpcFR5cGVBcnJheS5wdXNoKCdGTFYnKTtcclxuICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSAndmlkZW8veC1tcy13bXYnOlxyXG4gICAgICAgICAgICAgIGlmICghdGhpcy50b29sVGlwVHlwZUFycmF5LmluY2x1ZGVzKCdXTVYnKSkgdGhpcy50b29sVGlwVHlwZUFycmF5LnB1c2goJ1dNVicpO1xyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlICdpbWFnZS9zdmcreG1sJzpcclxuICAgICAgICAgICAgICBpZiAoIXRoaXMudG9vbFRpcFR5cGVBcnJheS5pbmNsdWRlcygnU1ZHJykpIHRoaXMudG9vbFRpcFR5cGVBcnJheS5wdXNoKCdTVkcnKTtcclxuICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSAndGV4dC9wbGFpbic6XHJcbiAgICAgICAgICAgICAgaWYgKCF0aGlzLnRvb2xUaXBUeXBlQXJyYXkuaW5jbHVkZXMoJ1R4dCcpKSB0aGlzLnRvb2xUaXBUeXBlQXJyYXkucHVzaCgnVHh0Jyk7XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIGNhc2UgJ2FwcGxpY2F0aW9uL0JOJzpcclxuICAgICAgICAgICAgICBpZiAoIXRoaXMudG9vbFRpcFR5cGVBcnJheS5pbmNsdWRlcygnTGljZW5zZScpKSB0aGlzLnRvb2xUaXBUeXBlQXJyYXkucHVzaCgnTGljZW5zZScpO1xyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICB0aGlzLnZhbGlkYXRpb25NZXNzYWdlID1cclxuICAgICAgICB0aGlzLnZhbGlkYXRpb25NZXNzYWdlICtcclxuICAgICAgICBgJHt0aGlzLlV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ0V4dGVuc2lvbnMnKX0gKCR7dGhpcy50b29sVGlwVHlwZUFycmF5fSkgYDtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLm9wdGlvbnMuZmlsZU1heFNpemVJbk1CID4gMCkge1xyXG4gICAgICB0aGlzLnZhbGlkYXRpb25NZXNzYWdlID1cclxuICAgICAgICB0aGlzLnZhbGlkYXRpb25NZXNzYWdlICtcclxuICAgICAgICBgPGJyIC8+ICAke3RoaXMuVXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSgnRmlsZU1heFNpemVJbk1CJykgKyB0aGlzLm9wdGlvbnMuZmlsZU1heFNpemVJbk1CfSBgO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLm9wdGlvbnMubWluTm9PZkZpbGVzID4gMCkge1xyXG4gICAgICB0aGlzLnZhbGlkYXRpb25NZXNzYWdlID1cclxuICAgICAgICB0aGlzLnZhbGlkYXRpb25NZXNzYWdlICtcclxuICAgICAgICBgPGJyIC8+ICR7dGhpcy5VdGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdNaW5GaWxlQ291bnRWYWxpZGF0aW9uS2V5JykgKyB0aGlzLm9wdGlvbnMubWluTm9PZkZpbGVzfWA7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5vcHRpb25zLm1heE5vT2ZGaWxlcyA+IDApIHtcclxuICAgICAgdGhpcy52YWxpZGF0aW9uTWVzc2FnZSA9XHJcbiAgICAgICAgdGhpcy52YWxpZGF0aW9uTWVzc2FnZSArXHJcbiAgICAgICAgYDxiciAvPiAke3RoaXMuVXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSgnTWF4RmlsZUNvdW50VmFsaWRhdGlvbktleScpICsgdGhpcy5vcHRpb25zLm1heE5vT2ZGaWxlc31gO1xyXG4gICAgfVxyXG5cclxuXHJcbiAgICBpZiAoXHJcbiAgICAgIHRoaXMub3B0aW9ucy5maWxlVXBsb2FkQWNjZXB0c1R5cGVzICE9IG51bGwgJiZcclxuICAgICAgdGhpcy5vcHRpb25zLmZpbGVVcGxvYWRBY2NlcHRzVHlwZXMubGVuZ3RoID4gMFxyXG4gICAgKSB7XHJcbiAgICB9XHJcbiAgICB0aGlzLmdyb3VwLmFkZENvbnRyb2wodGhpcy5vcHRpb25zLm5hbWUsIG5ldyBGb3JtQ29udHJvbCgnJykpO1xyXG4gICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wgPSB0aGlzLmdyb3VwLmNvbnRyb2xzW3RoaXMub3B0aW9ucy5uYW1lXTsgLy8gIG5ldyBGb3JtQ29udHJvbCgnJyx2YWxpZGF0aW9uUnVsZXMpO1xyXG5cclxuICAgIGlmICh0aGlzLm9wdGlvbnMuY3VzdG9tVmFsaWRhdGlvbi5sZW5ndGggPiAwKSB7XHJcbiAgICAgIGxldCBWYWxpZGF0aW9ucyA9IHRoaXMub3B0aW9ucy5jdXN0b21WYWxpZGF0aW9uO1xyXG4gICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgVmFsaWRhdGlvbnMubGVuZ3RoOyBpbmRleCsrKSB7XHJcbiAgICAgICAgY29uc3QgVmFsaWRhdGlvbiA9IFZhbGlkYXRpb25zW2luZGV4XTtcclxuICAgICAgICB0aGlzLnZhbGlkYXRpb25SdWxlcy5wdXNoKFZhbGlkYXRpb24uZnVuY3Rpb25Cb2R5KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLm9wdGlvbnMuaXNNdWx0aXBsZUZpbGUgJiYgdGhpcy5vcHRpb25zLm1heE5vT2ZGaWxlcyA+IDApIHtcclxuICAgICAgdGhpcy52YWxpZGF0aW9uQ291bnRNZXNzYWdlID0gYCR7dGhpcy5VdGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdNYXhGaWxlc0NvdW50Jyl9IDogJHt0aGlzLm9wdGlvbnMubWF4Tm9PZkZpbGVzfWA7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5vcHRpb25zLmlzUmVxdWlyZWQpIHtcclxuICAgICAgdGhpcy52YWxpZGF0aW9uUnVsZXMucHVzaChWYWxpZGF0b3JzLnJlcXVpcmVkKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5zZXRWYWxpZGF0b3JzKHRoaXMudmFsaWRhdGlvblJ1bGVzKTtcclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnNldEFzeW5jVmFsaWRhdG9ycyh0aGlzLnZhbGlkYXRpb25SdWxlc2FzeW5jKTtcclxuICAgIGlmICh0aGlzLm9wdGlvbnMuaXNEaXNhYmxlZCkge1xyXG4gICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5kaXNhYmxlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5NdWx0aXBsZUZpbGVVcGxhb2RDb250cm9sSG9zdC5uZ1N1Ym1pdC5zdWJzY3JpYmUoKHZhbHVlKSA9PiB7XHJcbiAgICAgIHRoaXMuZ3JvdXAubWFya0FsbEFzVG91Y2hlZCgpO1xyXG4gICAgICB0aGlzLm1hcmtBbGxBc1RvdWNoZWQgPSB0cnVlO1xyXG4gICAgfSk7XHJcblxyXG4gICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuc2V0VmFsdWUodGhpcy5vcHRpb25zLnZhbHVlKTtcclxuICB9XHJcblxyXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLm9wdGlvbnMuYXR0cmlidXRlTGlzdCAhPSBudWxsKSB7XHJcbiAgICAgIHZhciBlbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5vcHRpb25zLm5hbWUpO1xyXG4gICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgdGhpcy5vcHRpb25zLmF0dHJpYnV0ZUxpc3QubGVuZ3RoOyBpbmRleCsrKSB7XHJcbiAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoXHJcbiAgICAgICAgICB0aGlzLm9wdGlvbnMuYXR0cmlidXRlTGlzdFtpbmRleF0ua2V5LFxyXG4gICAgICAgICAgdGhpcy5vcHRpb25zLmF0dHJpYnV0ZUxpc3RbaW5kZXhdLnZhbHVlXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcmVzZXRFcnJvciA9ICgpID0+IHtcclxuICAgIHRoaXMuY29udHJvbFZhbGlkYXRpb25TZXJ2aWNlLnJlbW92ZUdsb2JhbEVycm9yKCk7XHJcbiAgfTtcclxuXHJcbiAgc2hvd0dsb2JhbEVycm9yKCkge1xyXG4gICAgdGhpcy5jb250cm9sVXRpbGl0eS5zaG93R2xvYmFsRXJyb3IoKTtcclxuICB9XHJcblxyXG4gIGdldEVycm9yVmFsaWRhdGlvbihFcnJvckxpc3QpIHtcclxuICAgIGlmICh0aGlzLm1hcmtBbGxBc1RvdWNoZWQgJiYgdGhpcy5ncm91cC5pbnZhbGlkKSB7XHJcbiAgICAgIHRoaXMuc2hvd0dsb2JhbEVycm9yKCk7XHJcbiAgICAgIHRoaXMubWFya0FsbEFzVG91Y2hlZCA9IGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0aGlzLmNvbnRyb2xVdGlsaXR5LmdldEVycm9yVmFsaWRhdGlvbk1hc3NhZ2UoRXJyb3JMaXN0LCB0aGlzLmdyb3VwLCB0aGlzLm9wdGlvbnMpO1xyXG4gIH1cclxuXHJcbiAgZmlsZU92ZXJBbm90aGVyKGV2ZW50OiBhbnkpOiB2b2lkIHtcclxuICAgIHRoaXMuaGFzQW5vdGhlckRyb3Bab25lT3ZlciA9IGV2ZW50O1xyXG4gIH1cclxuICBpc0hpZGVJbnB1dCgpIHtcclxuICAgIGlmICh0aGlzLm9wdGlvbnMuaXNNdWx0aXBsZUZpbGUpIHtcclxuICAgICAgaWYgKFxyXG4gICAgICAgIHRoaXMub3B0aW9ucy5tYXhOb09mRmlsZXMgIT0gbnVsbCAmJlxyXG4gICAgICAgIHRoaXMub3B0aW9ucy5tYXhOb09mRmlsZXMgPiAwICYmXHJcbiAgICAgICAgdGhpcy5vcHRpb25zLm1heE5vT2ZGaWxlcyA9PSB0aGlzLnVwbG9hZGVyLnF1ZXVlLmxlbmd0aFxyXG4gICAgICApIHtcclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaWYgKHRoaXMudXBsb2FkZXIucXVldWUubGVuZ3RoID4gMCkge1xyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG4gIG9uRmlsZUNoYW5nZSgpIHtcclxuICAgIGxldCBGaWxlc0FycmF5OiBGaWxlRFRPW10gPSBbXTtcclxuICAgIGlmIChcclxuICAgICAgdGhpcy5vcHRpb25zLmlzTXVsdGlwbGVGaWxlICYmXHJcbiAgICAgIHRoaXMub3B0aW9ucy5taW5Ob09mRmlsZXMgIT0gbnVsbCAmJlxyXG4gICAgICB0aGlzLm9wdGlvbnMubWluTm9PZkZpbGVzID4gMCAmJlxyXG4gICAgICB0aGlzLm9wdGlvbnMubWluTm9PZkZpbGVzID4gdGhpcy51cGxvYWRlci5xdWV1ZS5sZW5ndGhcclxuICAgICkge1xyXG4gICAgICBjb25zdCBmb3JtQ29udHJvbCA9IHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sO1xyXG4gICAgICBmb3JtQ29udHJvbC5zZXRFcnJvcnMoe1xyXG4gICAgICAgIE1pbkZpbGVDb3VudFZhbGlkYXRpb25LZXk6IHRoaXMub3B0aW9ucy5taW5Ob09mRmlsZXNcclxuICAgICAgfSk7XHJcbiAgICAgIGZvcm1Db250cm9sLm1hcmtBc1RvdWNoZWQoKTtcclxuICAgICAgdGhpcy51cGxvYWRlci5xdWV1ZSA9IFtdO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKFxyXG4gICAgICB0aGlzLm9wdGlvbnMuaXNNdWx0aXBsZUZpbGUgJiZcclxuICAgICAgdGhpcy5vcHRpb25zLm1heE5vT2ZGaWxlcyAhPSBudWxsICYmXHJcbiAgICAgIHRoaXMub3B0aW9ucy5tYXhOb09mRmlsZXMgPiAwICYmXHJcbiAgICAgIHRoaXMub3B0aW9ucy5tYXhOb09mRmlsZXMgPCB0aGlzLnVwbG9hZGVyLnF1ZXVlLmxlbmd0aFxyXG4gICAgKSB7XHJcbiAgICAgIGNvbnN0IGZvcm1Db250cm9sID0gdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2w7XHJcbiAgICAgIGZvcm1Db250cm9sLnNldEVycm9ycyh7XHJcbiAgICAgICAgTWF4RmlsZUNvdW50VmFsaWRhdGlvbktleTogdGhpcy5vcHRpb25zLm1heE5vT2ZGaWxlc1xyXG4gICAgICB9KTtcclxuICAgICAgZm9ybUNvbnRyb2wubWFya0FzVG91Y2hlZCgpO1xyXG4gICAgICB0aGlzLnVwbG9hZGVyLnF1ZXVlID0gW107XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoXHJcbiAgICAgIHRoaXMub3B0aW9ucy5pc011bHRpcGxlRmlsZSAmJlxyXG4gICAgICB0aGlzLm9wdGlvbnMubWF4U2l6ZUZvckFsbEZpbGVzSW5NQiAhPSBudWxsICYmXHJcbiAgICAgIHRoaXMub3B0aW9ucy5tYXhTaXplRm9yQWxsRmlsZXNJbk1CID4gMFxyXG4gICAgKSB7XHJcbiAgICAgIGxldCBBbGxTaXplRmlsZSA9IDA7XHJcbiAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCB0aGlzLnVwbG9hZGVyLnF1ZXVlLmxlbmd0aDsgaW5kZXgrKykge1xyXG4gICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLnVwbG9hZGVyLnF1ZXVlW2luZGV4XTtcclxuICAgICAgICBjb25zdCBmaWxlID0gZWxlbWVudC5maWxlO1xyXG4gICAgICAgIEFsbFNpemVGaWxlID0gQWxsU2l6ZUZpbGUgKyBmaWxlLnNpemU7XHJcbiAgICAgIH1cclxuICAgICAgY29uc3QgTWF4U2l6ZUZvckFsbEZpbGVzID0gdGhpcy5vcHRpb25zLm1heFNpemVGb3JBbGxGaWxlc0luTUIgKiAxMDAwICogMTAwMDtcclxuICAgICAgaWYgKEFsbFNpemVGaWxlID4gTWF4U2l6ZUZvckFsbEZpbGVzKSB7XHJcbiAgICAgICAgY29uc3QgZm9ybUNvbnRyb2wgPSB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbDtcclxuICAgICAgICBmb3JtQ29udHJvbC5zZXRFcnJvcnMoe1xyXG4gICAgICAgICAgTWF4U2l6ZUZvckFsbEZpbGVzSW5NQjogdGhpcy5vcHRpb25zLm1heFNpemVGb3JBbGxGaWxlc0luTUIgKyAnTUInXHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgZm9ybUNvbnRyb2wubWFya0FzVG91Y2hlZCgpO1xyXG4gICAgICAgIHRoaXMudXBsb2FkZXIucXVldWUgPSBbXTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGxldCBBZGRlZFF1ZXVlID0gdGhpcy51cGxvYWRlci5xdWV1ZS5maWx0ZXIoKG9iaikgPT4gb2JqWydzb21lJ10ubGFzdE1vZGlmaWVkICE9IG51bGwpO1xyXG5cclxuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBBZGRlZFF1ZXVlLmxlbmd0aDsgaW5kZXgrKykge1xyXG4gICAgICBjb25zdCBlbGVtZW50ID0gQWRkZWRRdWV1ZVtpbmRleF07XHJcbiAgICAgIGNvbnN0IGZpbGUgPSBlbGVtZW50LmZpbGU7XHJcbiAgICAgIGNvbnN0IG1heEZpbGVTaXplID0gdGhpcy5vcHRpb25zLmZpbGVNYXhTaXplSW5NQiAqIDEwMDAgKiAxMDAwO1xyXG4gICAgICBpZiAoZmlsZSkge1xyXG4gICAgICAgIGNvbnN0IGZpbGVUeXBlID0gZmlsZS50eXBlO1xyXG4gICAgICAgIGlmIChmaWxlLnNpemUgPiBtYXhGaWxlU2l6ZSkge1xyXG4gICAgICAgICAgY29uc3QgZm9ybUNvbnRyb2wgPSB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbDtcclxuICAgICAgICAgIGZvcm1Db250cm9sLnNldEVycm9ycyh7XHJcbiAgICAgICAgICAgIEZpbGVNYXhTaXplSW5NQjogdGhpcy5vcHRpb25zLmZpbGVNYXhTaXplSW5NQiArICdNJ1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgICBmb3JtQ29udHJvbC5tYXJrQXNUb3VjaGVkKCk7XHJcbiAgICAgICAgICB0aGlzLnVwbG9hZGVyLnF1ZXVlID0gW107XHJcbiAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChcclxuICAgICAgICAgIHRoaXMub3B0aW9ucy5maWxlVXBsb2FkQWNjZXB0c1R5cGVzICE9IG51bGwgJiZcclxuICAgICAgICAgIHRoaXMub3B0aW9ucy5maWxlVXBsb2FkQWNjZXB0c1R5cGVzLmxlbmd0aCA+IDAgJiZcclxuICAgICAgICAgICEoXHJcbiAgICAgICAgICAgIHRoaXMuYWNjZXB0ZWRUeXBlQXJyYXkuaW5jbHVkZXMoZmlsZVR5cGUudG9VcHBlckNhc2UoKSkgfHxcclxuICAgICAgICAgICAgdGhpcy5hY2NlcHRlZFR5cGVBcnJheS5pbmNsdWRlcyhmaWxlVHlwZS50b0xvd2VyQ2FzZSgpKVxyXG4gICAgICAgICAgKVxyXG4gICAgICAgICkge1xyXG4gICAgICAgICAgY29uc3QgZm9ybUNvbnRyb2wgPSB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbDtcclxuICAgICAgICAgIGZvcm1Db250cm9sLnNldEVycm9ycyh7IFRvb2xUaXBUeXBlRXJyb3I6IHRoaXMudG9vbFRpcFR5cGVBcnJheSB9KTtcclxuICAgICAgICAgIGZvcm1Db250cm9sLm1hcmtBc1RvdWNoZWQoKTtcclxuICAgICAgICAgIHRoaXMudXBsb2FkZXIucXVldWUgPSBbXTtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5pc1VwbG9hZEZpbGVBc3luYyAmJiAhZWxlbWVudC5fZmlsZVsnaURfR1VJRCddKSB7XHJcbiAgICAgICAgICB0aGlzLmZpbGVVcGxvYWRTZXJ2aWNlLnVwbG9hZEZpbGUoZWxlbWVudC5fZmlsZSkuc3Vic2NyaWJlKHtcclxuICAgICAgICAgICAgbmV4dDogKGV2ZW50OiBhbnkpID0+IHtcclxuICAgICAgICAgICAgICBsZXQgcXVldWVJbmRleCA9IHRoaXMudXBsb2FkZXIucXVldWUuZmluZEluZGV4KChmaWxlKSA9PiBmaWxlID09IGVsZW1lbnQpO1xyXG4gICAgICAgICAgICAgIGlmIChldmVudC50eXBlID09PSBIdHRwRXZlbnRUeXBlLlVwbG9hZFByb2dyZXNzKSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgdmFsdWUgPSBNYXRoLnJvdW5kKCgxMDAgKiBldmVudC5sb2FkZWQpIC8gZXZlbnQudG90YWwpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy51cGxvYWRlci5xdWV1ZVtxdWV1ZUluZGV4XS5wcm9ncmVzcyA9IHZhbHVlID49IDk1ID8gOTUgOiB2YWx1ZTtcclxuICAgICAgICAgICAgICB9IGVsc2UgaWYgKGV2ZW50LnR5cGUgPT09IEh0dHBFdmVudFR5cGUuUmVzcG9uc2UpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMudXBsb2FkZXIucXVldWVbcXVldWVJbmRleF0ucHJvZ3Jlc3MgPSAxMDA7XHJcbiAgICAgICAgICAgICAgICBsZXQgZmlsZUlEID0gZXZlbnQuYm9keS52YWwgYXMgYW55O1xyXG4gICAgICAgICAgICAgICAgdGhpcy51cGxvYWRlci5xdWV1ZVtxdWV1ZUluZGV4XS5fZmlsZVsnaURfR1VJRCddID0gZmlsZUlEO1xyXG4gICAgICAgICAgICAgICAgdGhpcy51cGxvYWRlci5xdWV1ZVtxdWV1ZUluZGV4XS5fZmlsZVsnaXNOZXcnXSA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICBsZXQgQWRkZWRGaWxlID0gPEZpbGVEVE8+e1xyXG4gICAgICAgICAgICAgICAgICBpRF9HVUlEOiBmaWxlSUQsXHJcbiAgICAgICAgICAgICAgICAgIGZpbGVOYW1lOiB0aGlzLnVwbG9hZGVyLnF1ZXVlW3F1ZXVlSW5kZXhdLl9maWxlWyduYW1lJ10sXHJcbiAgICAgICAgICAgICAgICAgIGZpbGVUeXBlOiB0aGlzLnVwbG9hZGVyLnF1ZXVlW3F1ZXVlSW5kZXhdLl9maWxlWyd0eXBlJ10sXHJcbiAgICAgICAgICAgICAgICAgIGlzTmV3OiB0cnVlXHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5pc011bHRpcGxlRmlsZSA9PSBmYWxzZSkge1xyXG4gICAgICAgICAgICAgICAgICB0aGlzLmZpbGVVcGxvYWRNb2RlbCA9IG5ldyBGaWxlVXBsb2FkTW9kZWwoKTtcclxuICAgICAgICAgICAgICAgICAgdGhpcy5maWxlVXBsb2FkTW9kZWwuZmlsZSA9IEFkZGVkRmlsZTtcclxuICAgICAgICAgICAgICAgICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuc2V0VmFsdWUodGhpcy5maWxlVXBsb2FkTW9kZWwpO1xyXG4gICAgICAgICAgICAgICAgICB0aGlzLmdyb3VwLmdldCh0aGlzLm9wdGlvbnMubmFtZSkuc2V0VmFsdWUodGhpcy5maWxlVXBsb2FkTW9kZWwpO1xyXG4gICAgICAgICAgICAgICAgICAvL1VzZSB0aGlzIGxpbmUgdG8gZW5hYmxlIHR3byB3YXkgYmluZGluZy5cclxuICAgICAgICAgICAgICAgICAgdGhpcy5vcHRpb25zLnZhbHVlID0gdGhpcy5maWxlVXBsb2FkTW9kZWw7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICBGaWxlc0FycmF5LnB1c2goQWRkZWRGaWxlKTtcclxuICAgICAgICAgICAgICAgICAgdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbC51cGxvYWRlZEZpbGVzID0gRmlsZXNBcnJheTtcclxuICAgICAgICAgICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy52YWx1ZSAhPSBudWxsICYmIHRoaXMub3B0aW9ucy52YWx1ZSAhPSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLnZhbHVlLmNvcnJlbGF0aW9uSURfR1VJRCA9PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLnJlbW92ZWRGaWxlcyA9IFtdO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLmNvcnJlbGF0aW9uSURfR1VJRCA9XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcHRpb25zLnZhbHVlPy5jb3JyZWxhdGlvbklEX0dVSUQ7XHJcbiAgICAgICAgICAgICAgICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnNldFZhbHVlKHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwpO1xyXG4gICAgICAgICAgICAgICAgICB0aGlzLmdyb3VwLmdldCh0aGlzLm9wdGlvbnMubmFtZSkuc2V0VmFsdWUodGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbCk7XHJcbiAgICAgICAgICAgICAgICAgIC8vVXNlIHRoaXMgbGluZSB0byBlbmFibGUgdHdvIHdheSBiaW5kaW5nLlxyXG4gICAgICAgICAgICAgICAgICB0aGlzLm9wdGlvbnMudmFsdWUgPSB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsO1xyXG4gICAgICAgICAgICAgICAgICB0aGlzLmlzVXBsb2FkQ29tcGxldGUuZW1pdCh0cnVlKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBsZXQgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcclxuICAgICAgICAgIGxldCBmaWxlT2JqZWN0ID0gZmlsZS5yYXdGaWxlIGFzIGFueTtcclxuICAgICAgICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGZpbGVPYmplY3QpO1xyXG4gICAgICAgICAgcmVhZGVyLm9ubG9hZCA9ICgpID0+IHtcclxuICAgICAgICAgICAgbGV0IGV4aXN0aW5nSURfR1VJRCA9IG51bGw7XHJcblxyXG4gICAgICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5pc011bHRpcGxlRmlsZSAmJiB0aGlzLmZpbGUpXHJcbiAgICAgICAgICAgICAgZXhpc3RpbmdJRF9HVUlEID0gdGhpcy5maWxlLk5hbWVXaXRoRXh0ZW5zaW9uID09IGZpbGUubmFtZSA/IHRoaXMuZmlsZS5pRF9HVUlEIDogbnVsbDtcclxuXHJcbiAgICAgICAgICAgIGxldCBBZGRlZEZpbGU6IEZpbGVEVE8gPSB7XHJcbiAgICAgICAgICAgICAgZmlsZU5hbWU6IGZpbGUubmFtZSxcclxuICAgICAgICAgICAgICBmaWxlVHlwZTogZmlsZS50eXBlLFxyXG4gICAgICAgICAgICAgIGZpbGVCYXNlNjQ6IHJlYWRlci5yZXN1bHQudG9TdHJpbmcoKS5zcGxpdCgnLCcpWzFdLFxyXG4gICAgICAgICAgICAgIGZpbGVTaXplSW5NQjogZmlsZS5zaXplIC8gMTAwMCAvIDEwMDAsXHJcbiAgICAgICAgICAgICAgbmFtZVdpdGhFeHRlbnNpb246IGZpbGUubmFtZSxcclxuICAgICAgICAgICAgICBpRF9HVUlEOiBleGlzdGluZ0lEX0dVSUQsXHJcbiAgICAgICAgICAgICAgaXNOZXc6IHRydWVcclxuICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMuaXNNdWx0aXBsZUZpbGUgPT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgICB0aGlzLmZpbGVVcGxvYWRNb2RlbCA9IG5ldyBGaWxlVXBsb2FkTW9kZWwoKTtcclxuICAgICAgICAgICAgICB0aGlzLmZpbGVVcGxvYWRNb2RlbC5maWxlID0gQWRkZWRGaWxlO1xyXG5cclxuICAgICAgICAgICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5zZXRWYWx1ZSh0aGlzLmZpbGVVcGxvYWRNb2RlbCk7XHJcbiAgICAgICAgICAgICAgdGhpcy5ncm91cC5nZXQodGhpcy5vcHRpb25zLm5hbWUpLnNldFZhbHVlKHRoaXMuZmlsZVVwbG9hZE1vZGVsKTtcclxuICAgICAgICAgICAgICAvL1VzZSB0aGlzIGxpbmUgdG8gZW5hYmxlIHR3byB3YXkgYmluZGluZy5cclxuICAgICAgICAgICAgICB0aGlzLm9wdGlvbnMudmFsdWUgPSB0aGlzLmZpbGVVcGxvYWRNb2RlbDtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICBGaWxlc0FycmF5LnB1c2goQWRkZWRGaWxlKTtcclxuICAgICAgICAgICAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLnVwbG9hZGVkRmlsZXMgPSBGaWxlc0FycmF5O1xyXG4gICAgICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMudmFsdWUgIT0gbnVsbCAmJiB0aGlzLm9wdGlvbnMudmFsdWUgIT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLnZhbHVlLmNvcnJlbGF0aW9uSURfR1VJRCA9PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICAgIHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwucmVtb3ZlZEZpbGVzID0gW107XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwuY29ycmVsYXRpb25JRF9HVUlEID1cclxuICAgICAgICAgICAgICAgIHRoaXMub3B0aW9ucy52YWx1ZT8uY29ycmVsYXRpb25JRF9HVUlEO1xyXG5cclxuICAgICAgICAgICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5zZXRWYWx1ZSh0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsKTtcclxuXHJcbiAgICAgICAgICAgICAgdGhpcy5ncm91cC5nZXQodGhpcy5vcHRpb25zLm5hbWUpLnNldFZhbHVlKHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwpO1xyXG4gICAgICAgICAgICAgIC8vVXNlIHRoaXMgbGluZSB0byBlbmFibGUgdHdvIHdheSBiaW5kaW5nLlxyXG4gICAgICAgICAgICAgIHRoaXMub3B0aW9ucy52YWx1ZSA9IHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWw7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH07XHJcbiAgICAgICAgICBsZXQgb3JpZ2luYWxWYWx1ZSA9IHRoaXMuZ3JvdXAuZ2V0KHRoaXMub3B0aW9ucy5uYW1lKS52YWx1ZTtcclxuICAgICAgICAgIGlmIChcclxuICAgICAgICAgICAgdGhpcy5vcHRpb25zLnBhdGNoRnVuY3Rpb24gJiZcclxuICAgICAgICAgICAgdGhpcy5vcHRpb25zLnBhdGNoUGF0aCAmJlxyXG4gICAgICAgICAgICB0aGlzLmdyb3VwLmdldCh0aGlzLm9wdGlvbnMubmFtZSkudmFsaWRcclxuICAgICAgICAgICkge1xyXG4gICAgICAgICAgICB0aGlzLmNvbnRyb2xVdGlsaXR5LnBhdGNoQ29udHJvbFZhbHVlKFxyXG4gICAgICAgICAgICAgIG9yaWdpbmFsVmFsdWUsXHJcbiAgICAgICAgICAgICAgdGhpcy5vcHRpb25zLnBhdGNoRnVuY3Rpb24sXHJcbiAgICAgICAgICAgICAgdGhpcy5vcHRpb25zLnBhdGNoUGF0aFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgdGhpcy5PbkNoYW5nZS5lbWl0KG9yaWdpbmFsVmFsdWUpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuICByZW1vdmVGcm9tQ29udHJvbFZhbHVlKGl0ZW06IEZpbGVJdGVtKSB7XHJcbiAgICBpZiAodGhpcy5vcHRpb25zLmlzVXBsb2FkRmlsZUFzeW5jICYmIGl0ZW0ucHJvZ3Jlc3MgPT0gMTAwICYmIGl0ZW0uX2ZpbGVbJ2lzTmV3J10pIHtcclxuICAgICAgdGhpcy5maWxlVXBsb2FkU2VydmljZS5kZWxldGVGaWxlKGl0ZW0uX2ZpbGVbJ2lEX0dVSUQnXSkuc3Vic2NyaWJlKChyZXMpID0+IHsgfSk7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5vcHRpb25zLmlzTXVsdGlwbGVGaWxlID09IGZhbHNlKSB7XHJcbiAgICAgIHRoaXMuZmlsZVVwbG9hZE1vZGVsID0gbnVsbDtcclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy5pc1JlcXVpcmVkID09IHRydWUpIHtcclxuICAgICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5tYXJrQXNUb3VjaGVkKCk7XHJcbiAgICAgICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuaW52YWxpZDtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLmdyb3VwLmdldCh0aGlzLm9wdGlvbnMubmFtZSkuc2V0VmFsdWUodGhpcy5maWxlVXBsb2FkTW9kZWwpO1xyXG4gICAgICB0aGlzLm9wdGlvbnMudmFsdWUgPSB0aGlzLmZpbGVVcGxvYWRNb2RlbDtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMudmFsdWUgIT0gbnVsbCAmJiB0aGlzLm9wdGlvbnMudmFsdWUgIT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy52YWx1ZS5jb3JyZWxhdGlvbklEX0dVSUQgPT0gbnVsbCkge1xyXG4gICAgICAgICAgdGhpcy5kZWxldGVkRmlsZXMgPSBbXTtcclxuICAgICAgICAgIHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwucmVtb3ZlZEZpbGVzID0gW107XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGlmICh0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLnJlbW92ZWRGaWxlcy5sZW5ndGggPT0gMCkge1xyXG4gICAgICAgICAgICBsZXQgRmlsZU9iamVjdCA9IGl0ZW0uZmlsZS5yYXdGaWxlO1xyXG4gICAgICAgICAgICBsZXQgRGVsZXRlZEl0ZW0gPSB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLmV4aXN0aW5nRmlsZXMuZmlsdGVyKFxyXG4gICAgICAgICAgICAgIChvYmopID0+IG9iai5uYW1lV2l0aEV4dGVuc2lvbiA9PSBGaWxlT2JqZWN0Lm5hbWVcclxuICAgICAgICAgICAgKVswXTtcclxuICAgICAgICAgICAgdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbC5leGlzdGluZ0ZpbGVzID1cclxuICAgICAgICAgICAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLmV4aXN0aW5nRmlsZXMuZmlsdGVyKFxyXG4gICAgICAgICAgICAgICAgKG9iaikgPT4gb2JqLm5hbWVXaXRoRXh0ZW5zaW9uICE9IEZpbGVPYmplY3QubmFtZVxyXG4gICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIHRoaXMuZGVsZXRlZEZpbGVzLnB1c2goRGVsZXRlZEl0ZW0pO1xyXG4gICAgICAgICAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLnJlbW92ZWRGaWxlcy5wdXNoKERlbGV0ZWRJdGVtLmlEX0dVSUQpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgbGV0IEZpbGVPYmplY3QgPSBpdGVtLmZpbGUucmF3RmlsZTtcclxuICAgICAgICAgICAgbGV0IGRlbGV0ZWRMaXN0ID0gdGhpcy5kZWxldGVkRmlsZXMuZmlsdGVyKFxyXG4gICAgICAgICAgICAgIChvYmopID0+IG9iai5uYW1lV2l0aEV4dGVuc2lvbiA9PSBGaWxlT2JqZWN0Lm5hbWVcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgaWYgKGRlbGV0ZWRMaXN0Lmxlbmd0aCA9PSAwIHx8IGRlbGV0ZWRMaXN0ID09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgIGxldCBEZWxldGVkSXRlbSA9IHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwuZXhpc3RpbmdGaWxlcy5maWx0ZXIoXHJcbiAgICAgICAgICAgICAgICAob2JqKSA9PiBvYmoubmFtZVdpdGhFeHRlbnNpb24gPT0gRmlsZU9iamVjdC5uYW1lXHJcbiAgICAgICAgICAgICAgKVswXTtcclxuICAgICAgICAgICAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLmV4aXN0aW5nRmlsZXMgPVxyXG4gICAgICAgICAgICAgICAgdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbC5leGlzdGluZ0ZpbGVzLmZpbHRlcihcclxuICAgICAgICAgICAgICAgICAgKG9iaikgPT4gb2JqLm5hbWVXaXRoRXh0ZW5zaW9uICE9IEZpbGVPYmplY3QubmFtZVxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICB0aGlzLmRlbGV0ZWRGaWxlcy5wdXNoKERlbGV0ZWRJdGVtKTtcclxuICAgICAgICAgICAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLnJlbW92ZWRGaWxlcy5wdXNoKERlbGV0ZWRJdGVtLmlEX0dVSUQpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuZGVsZXRlZEZpbGVzID0gW107XHJcbiAgICAgICAgdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbC5yZW1vdmVkRmlsZXMgPSBbXTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLnVwbG9hZGVkRmlsZXMgPVxyXG4gICAgICAgIHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwudXBsb2FkZWRGaWxlcy5maWx0ZXIoXHJcbiAgICAgICAgICAob2JqKSA9PlxyXG4gICAgICAgICAgICAob2JqLm5hbWVXaXRoRXh0ZW5zaW9uICYmIG9iai5uYW1lV2l0aEV4dGVuc2lvbiAhPSBpdGVtLl9maWxlLm5hbWUpIHx8XHJcbiAgICAgICAgICAgIG9iai5pRF9HVUlEICE9IGl0ZW0uX2ZpbGVbJ2lEX0dVSUQnXVxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICBpZiAoXHJcbiAgICAgICAgKHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwudXBsb2FkZWRGaWxlcyA9PSBudWxsIHx8XHJcbiAgICAgICAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLnVwbG9hZGVkRmlsZXMubGVuZ3RoID09IDApICYmXHJcbiAgICAgICAgdGhpcy5vcHRpb25zLmlzUmVxdWlyZWRcclxuICAgICAgKSB7XHJcbiAgICAgICAgY29uc3QgZm9ybUNvbnRyb2wgPSB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbDtcclxuICAgICAgICBmb3JtQ29udHJvbC5zZXRFcnJvcnMoe1xyXG4gICAgICAgICAgTWluRmlsZUNvdW50VmFsaWRhdGlvbktleTogdGhpcy5vcHRpb25zLm1pbk5vT2ZGaWxlc1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLm1hcmtBc1RvdWNoZWQoKTtcclxuICAgICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5pbnZhbGlkO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwuY29ycmVsYXRpb25JRF9HVUlEID0gdGhpcy5vcHRpb25zLnZhbHVlPy5jb3JyZWxhdGlvbklEX0dVSUQ7XHJcbiAgICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnNldFZhbHVlKHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwpO1xyXG4gICAgICB0aGlzLmdyb3VwLmdldCh0aGlzLm9wdGlvbnMubmFtZSkuc2V0VmFsdWUodGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbCk7XHJcbiAgICAgIC8vVXNlIHRoaXMgbGluZSB0byBlbmFibGUgdHdvIHdheSBiaW5kaW5nLlxyXG4gICAgICB0aGlzLm9wdGlvbnMudmFsdWUgPSB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsO1xyXG4gICAgfVxyXG4gIH1cclxuICAvL0V4dGVybmFsIE1ldGhvZFxyXG4gIHJlbW92ZVJlcXVpcmVkVmFsaWRhdGlvbiA9ICgpID0+IHtcclxuICAgIHRoaXMuY29udHJvbFV0aWxpdHkucmVtb3ZlUmVxdWlyZWRWYWxpZGF0aW9uKFxyXG4gICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbCxcclxuICAgICAgdGhpcy52YWxpZGF0aW9uUnVsZXMsXHJcbiAgICAgIHRoaXMub3B0aW9uc1xyXG4gICAgKTtcclxuICB9O1xyXG4gIC8vRXh0ZXJuYWwgTWV0aG9kXHJcbiAgYWRkUmVxdWlyZWRWYWxpZGF0aW9uID0gKCkgPT4ge1xyXG4gICAgdGhpcy5jb250cm9sVXRpbGl0eS5hZGRSZXF1aXJlZFZhbGlkYXRpb24oXHJcbiAgICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLFxyXG4gICAgICB0aGlzLnZhbGlkYXRpb25SdWxlcyxcclxuICAgICAgdGhpcy5vcHRpb25zXHJcbiAgICApO1xyXG4gIH07XHJcblxyXG4gIC8vRXh0ZXJuYWwgTWV0aG9kXHJcbiAgcmVtb3ZlQ3VzdG9tVmFsaWRhdGlvbiA9IChjdXN0b21WYWxpZGF0aW9uKSA9PiB7XHJcbiAgICB0aGlzLmNvbnRyb2xVdGlsaXR5LnJlbW92ZUN1c3RvbVZhbGlkYXRpb24oXHJcbiAgICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLFxyXG4gICAgICB0aGlzLnZhbGlkYXRpb25SdWxlcyxcclxuICAgICAgY3VzdG9tVmFsaWRhdGlvblxyXG4gICAgKTtcclxuICB9O1xyXG4gIC8vRXh0ZXJuYWwgTWV0aG9kXHJcbiAgYWRkQ3VzdG9tVmFsaWRhdGlvbiA9IChjdXN0b21WYWxpZGF0aW9uKSA9PiB7XHJcbiAgICB0aGlzLmNvbnRyb2xVdGlsaXR5LmFkZEN1c3RvbVZhbGlkYXRpb24oXHJcbiAgICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLFxyXG4gICAgICB0aGlzLnZhbGlkYXRpb25SdWxlcyxcclxuICAgICAgY3VzdG9tVmFsaWRhdGlvblxyXG4gICAgKTtcclxuICB9O1xyXG4gIC8vRXh0ZXJuYWwgTWV0aG9kXHJcbiAgaXNWYWxpZCA9ICgpID0+IHtcclxuICAgIHRoaXMuY29udHJvbFV0aWxpdHkuaXNWYWxpZCh0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbCk7XHJcbiAgfTtcclxuICBjb252ZXJ0U2l6ZVRvTUIoc2l6ZTogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgIGlmIChzaXplID09PSAwKSB7XHJcbiAgICAgIHJldHVybiAwO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIENvbnZlcnQgc2l6ZSB0byBtZWdhYnl0ZXNcclxuICAgIGNvbnN0IG1lZ2FieXRlcyA9IHNpemUgLyAoMTAyNCAqIDEwMjQpO1xyXG5cclxuICAgIC8vIFJvdW5kIHRvIHR3byBkZWNpbWFsIHBsYWNlc1xyXG4gICAgY29uc3Qgcm91bmRlZE1lZ2FieXRlcyA9IE1hdGgucm91bmQobWVnYWJ5dGVzICogMTAwKSAvIDEwMDtcclxuXHJcbiAgICByZXR1cm4gcm91bmRlZE1lZ2FieXRlcztcclxuICB9XHJcbn0iLCI8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cCBiYnNmLWNvbnRyb2wgYmJzZi1maWxlLXVwbG9hZFwiIFtmb3JtR3JvdXBdPVwiZ3JvdXBcIj5cclxuICA8ZGl2IFtuZ0NsYXNzXT1cIm9wdGlvbnMudmlld1R5cGUgPT0gMSA/ICdiYnNmLXZlcnRpY2FsJyA6ICdiYnNmLWhvcml6b250YWwnXCI+XHJcbiAgICA8IS0tbGFiZWwtLT5cclxuICAgIDxsYWJlbCBbaGlkZGVuXT1cIm9wdGlvbnMuaGlkZUxhYmVsXCIgY2xhc3M9XCJiYnNmLWxhYmVsIHt7IG9wdGlvbnMubGFiZWxFeHRyYUNsYXNzZXMgfX1cIj5cclxuICAgICAge3sgb3B0aW9ucy5sYWJlbFZhbHVlIH19XHJcbiAgICAgIDwhLS1Bc3Rlcmlzay0tPlxyXG4gICAgICA8c3BhbiAqbmdJZj1cIigob3B0aW9ucy5zaG93QXN0ZXJpc2sgJiYgb3B0aW9ucy5pc1JlcXVpcmVkKSB8fCBvcHRpb25zLmlzUmVxdWlyZWQpICYmICFvcHRpb25zLmlzUmVhZG9ubHlcIlxyXG4gICAgICAgIGNsYXNzPVwidGV4dC1kYW5nZXJcIj4qPC9zcGFuPlxyXG4gICAgPC9sYWJlbD5cclxuICAgIDwhLS1BbGxvdyBkcm9wWm9uZS0tPlxyXG4gICAgPGRpdiBuZzJGaWxlRHJvcCBjbGFzcz1cImJic2YtaW5wdXQtY29udGFpbmVyIHt7IG9wdGlvbnMuZXh0cmFDbGFzc2VzIH19XCJcclxuICAgICAgKm5nSWY9XCJvcHRpb25zLmlzRHJvcFpvbmUgJiYgIShvcHRpb25zLmlzTXVsdGlwbGVGaWxlID09IGZhbHNlICYmIHVwbG9hZGVyLnF1ZXVlLmxlbmd0aCA+IDApICYmICFvcHRpb25zLmlzUmVhZG9ubHlcIlxyXG4gICAgICBbbmdDbGFzc109XCJ7ICdhbm90aGVyLWZpbGUtb3Zlci1jbGFzcyc6IGhhc0Fub3RoZXJEcm9wWm9uZU92ZXIgfVwiIChvbkZpbGVEcm9wKT1cIm9uRmlsZUNoYW5nZSgpXCJcclxuICAgICAgKGZpbGVPdmVyKT1cImZpbGVPdmVyQW5vdGhlcigkZXZlbnQpXCIgW3VwbG9hZGVyXT1cInVwbG9hZGVyXCIgW2FjY2VwdF09XCJhY2NlcHRlZFR5cGVcIiBpZD1cInt7IG9wdGlvbnMubmFtZSB9fVwiXHJcbiAgICAgIG11bHRpcGxlPVwie3sgb3B0aW9ucy5pc011bHRpcGxlRmlsZSA/ICdtdWx0aXBsZScgOiAnJyB9fVwiIGFyaWEtZGVzY3JpYmVkYnk9XCJlbWFpbC1lcnJvclwiIGFyaWEtaW52YWxpZD1cInRydWVcIlxyXG4gICAgICB0eXBlPVwiZmlsZVwiICNmaWxlSW5wdXQgW2NsYXNzLmlzLWludmFsaWRdPVwiZmlsZVVwbG9hZEZvcm1Db250cm9sLmludmFsaWQgJiYgZmlsZVVwbG9hZEZvcm1Db250cm9sLnRvdWNoZWRcIlxyXG4gICAgICAoY2xpY2spPVwiZmlsZUlucHV0Q29udHJvbC5jbGljaygpXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJkcm9wem9uZS1sYWJlbFwiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJzdmctYW5kLXZhbGlkYXRpb25cIj5cclxuICAgICAgICAgIDxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHdpZHRoPVwiNzBcIiBoZWlnaHQ9XCI3MFwiIHZpZXdCb3g9XCIwIDAgNzAgNzBcIiBmaWxsPVwibm9uZVwiPlxyXG4gICAgICAgICAgICA8cGF0aCBvcGFjaXR5PVwiMC40XCJcclxuICAgICAgICAgICAgICBkPVwiTTU4LjMzMyA0OC44MzMyQzYxLjg5NTcgNDUuODkwOCA2NC4xNjYzIDQxLjQzOTcgNjQuMTY2MyAzNi40NTgzQzY0LjE2NjMgMjcuNTk4OCA1Ni45ODQzIDIwLjQxNjcgNDguMTI0NyAyMC40MTY3QzQ3LjQ4NzQgMjAuNDE2NyA0Ni44OTEyIDIwLjA4NDIgNDYuNTY3NSAxOS41MzUxQzQyLjc2NDEgMTMuMDgwOCAzNS43NDE3IDguNzUgMjcuNzA4IDguNzVDMTUuNjI2OCA4Ljc1IDUuODMzMDEgMTguNTQzOCA1LjgzMzAxIDMwLjYyNUM1LjgzMzAxIDM2LjY1MTEgOC4yNjk3NCA0Mi4xMDgyIDEyLjIxMTYgNDYuMDY0NFwiXHJcbiAgICAgICAgICAgICAgc3Ryb2tlPVwiIzRCNTQ4OVwiIHN0cm9rZS13aWR0aD1cIjJcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIiAvPlxyXG4gICAgICAgICAgICA8cGF0aCBkPVwiTTIzLjMzMyA0Ni42NjY3TDM0Ljk5OTcgMzVNMzQuOTk5NyAzNUw0Ni42NjYzIDQ2LjY2NjdNMzQuOTk5NyAzNVY2MS4yNVwiIHN0cm9rZT1cIiM0QjU0ODlcIlxyXG4gICAgICAgICAgICAgIHN0cm9rZS13aWR0aD1cIjJcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIiAvPlxyXG4gICAgICAgICAgPC9zdmc+XHJcbiAgICAgICAgICA8IS0tVmFsaWRhdGlvbiB0ZXh0LS0+XHJcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiYmJzZi12YWxpZGF0aW9uLW1zZyB2YWxpZGF0aW9uLW1zZy1oZWFkZXIgdGV4dC1jZW50ZXJcIj5cclxuICAgICAgICAgICAge3sgVXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSgnRHJhZ0FuZERyb3BIZXJlJykgfX1cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJic2YtdmFsaWRhdGlvbi1tc2cgdGV4dC1jZW50ZXJcIiAqbmdJZj1cInZhbGlkYXRpb25NZXNzYWdlXCIgW2lubmVySFRNTF09XCJ2YWxpZGF0aW9uTWVzc2FnZVwiPjwvZGl2PlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJic2YtdmFsaWRhdGlvbi1tc2cgbmctc3Rhci1pbnNlcnRlZCB0ZXh0LWNlbnRlciB0ZXh0LWRhbmdlclwiXHJcbiAgICAgICAgICAgICpuZ0lmPVwidmFsaWRhdGlvbkNvdW50TWVzc2FnZSAmJiBvcHRpb25zLmlzTXVsdGlwbGVGaWxlICYmIG9wdGlvbnMubWF4Tm9PZkZpbGVzID4gMFwiXHJcbiAgICAgICAgICAgIFtpbm5lckhUTUxdPVwidmFsaWRhdGlvbkNvdW50TWVzc2FnZVwiPjwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGlucHV0IG5nMkZpbGVTZWxlY3QgW3VwbG9hZGVyXT1cInVwbG9hZGVyXCIgW2FjY2VwdF09XCJhY2NlcHRlZFR5cGVcIlxyXG4gICAgICAgIGNsYXNzPVwiZmlsZVNlbGVjdG9yIGN1c3RvbUZpbGVVcGxvYWRQbGFjbWVudCBoaWRkZW4gdi1yZXF1aXJlZC1tdWx0aXBsZWZpbGVzIGQtbm9uZVwiXHJcbiAgICAgICAgbXVsdGlwbGU9XCJ7eyBvcHRpb25zLmlzTXVsdGlwbGVGaWxlID8gJ211bHRpcGxlJyA6ICcnIH19XCIgbmFtZT1cImZpbGVcIiB0eXBlPVwiZmlsZVwiIHZhbHVlPVwiXCIgYXV0b2NvbXBsZXRlPVwib2ZmXCJcclxuICAgICAgICAoY2hhbmdlKT1cIm9uRmlsZUNoYW5nZSgpXCIgW25nQ2xhc3NdPVwib3B0aW9ucy52aWV3VHlwZSA9PSAxID8gJycgOiAnY29sLW1kLTknXCIgaWQ9XCJ7eyBvcHRpb25zLm5hbWUgfX1cIlxyXG4gICAgICAgIGFyaWEtZGVzY3JpYmVkYnk9XCJlbWFpbC1lcnJvclwiIGFyaWEtaW52YWxpZD1cInRydWVcIiBmb3JtQ29udHJvbE5hbWU9XCJ7eyBvcHRpb25zLm5hbWUgfX1cIiAjZmlsZUlucHV0Q29udHJvbFxyXG4gICAgICAgIFtjbGFzcy5pcy1pbnZhbGlkXT1cImZpbGVVcGxvYWRGb3JtQ29udHJvbC5pbnZhbGlkICYmIGZpbGVVcGxvYWRGb3JtQ29udHJvbC50b3VjaGVkXCIgLz5cclxuICAgIDwvZGl2PlxyXG4gICAgPCEtLU5vdCBhbGxvd2VkIGRyb3Bab25lLS0+XHJcbiAgICA8ZGl2IGNsYXNzPVwiYmJzZi1pbnB1dC1jb250YWluZXJcIiAqbmdJZj1cIiFvcHRpb25zLmlzRHJvcFpvbmUgJiYgIWlzSGlkZUlucHV0KCkgJiYgIW9wdGlvbnMuaXNSZWFkb25seVwiXHJcbiAgICAgIChjbGljayk9XCJmaWxlSW5wdXQuY2xpY2soKVwiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiZHJvcHpvbmUtbGFiZWxcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwic3ZnLWFuZC12YWxpZGF0aW9uXCI+XHJcbiAgICAgICAgICA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB3aWR0aD1cIjcwXCIgaGVpZ2h0PVwiNzBcIiB2aWV3Qm94PVwiMCAwIDcwIDcwXCIgZmlsbD1cIm5vbmVcIj5cclxuICAgICAgICAgICAgPHBhdGggb3BhY2l0eT1cIjAuNFwiXHJcbiAgICAgICAgICAgICAgZD1cIk01OC4zMzMgNDguODMzMkM2MS44OTU3IDQ1Ljg5MDggNjQuMTY2MyA0MS40Mzk3IDY0LjE2NjMgMzYuNDU4M0M2NC4xNjYzIDI3LjU5ODggNTYuOTg0MyAyMC40MTY3IDQ4LjEyNDcgMjAuNDE2N0M0Ny40ODc0IDIwLjQxNjcgNDYuODkxMiAyMC4wODQyIDQ2LjU2NzUgMTkuNTM1MUM0Mi43NjQxIDEzLjA4MDggMzUuNzQxNyA4Ljc1IDI3LjcwOCA4Ljc1QzE1LjYyNjggOC43NSA1LjgzMzAxIDE4LjU0MzggNS44MzMwMSAzMC42MjVDNS44MzMwMSAzNi42NTExIDguMjY5NzQgNDIuMTA4MiAxMi4yMTE2IDQ2LjA2NDRcIlxyXG4gICAgICAgICAgICAgIHN0cm9rZT1cIiM0QjU0ODlcIiBzdHJva2Utd2lkdGg9XCIyXCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIgLz5cclxuICAgICAgICAgICAgPHBhdGggZD1cIk0yMy4zMzMgNDYuNjY2N0wzNC45OTk3IDM1TTM0Ljk5OTcgMzVMNDYuNjY2MyA0Ni42NjY3TTM0Ljk5OTcgMzVWNjEuMjVcIiBzdHJva2U9XCIjNEI1NDg5XCJcclxuICAgICAgICAgICAgICBzdHJva2Utd2lkdGg9XCIyXCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIgLz5cclxuICAgICAgICAgIDwvc3ZnPlxyXG4gICAgICAgICAgPCEtLVZhbGlkYXRpb24gdGV4dC0tPlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJic2YtdmFsaWRhdGlvbi1tc2cgdGV4dC1jZW50ZXJcIj57eyBVdGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdVcGxvYWQnKSB9fTwvZGl2PlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJic2YtdmFsaWRhdGlvbi1tc2cgdGV4dC1jZW50ZXJcIiAqbmdJZj1cInZhbGlkYXRpb25NZXNzYWdlXCIgW2lubmVySFRNTF09XCJ2YWxpZGF0aW9uTWVzc2FnZVwiPjwvZGl2PlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJic2YtdmFsaWRhdGlvbi1tc2cgbmctc3Rhci1pbnNlcnRlZCB0ZXh0LWNlbnRlciB0ZXh0LWRhbmdlclwiXHJcbiAgICAgICAgICAgICpuZ0lmPVwidmFsaWRhdGlvbkNvdW50TWVzc2FnZSAmJiBvcHRpb25zLmlzTXVsdGlwbGVGaWxlICYmIG9wdGlvbnMubWF4Tm9PZkZpbGVzID4gMFwiXHJcbiAgICAgICAgICAgIFtpbm5lckhUTUxdPVwidmFsaWRhdGlvbkNvdW50TWVzc2FnZVwiPjwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGlucHV0IG5nMkZpbGVTZWxlY3QgW3VwbG9hZGVyXT1cInVwbG9hZGVyXCIgW2FjY2VwdF09XCJhY2NlcHRlZFR5cGVcIlxyXG4gICAgICAgIGNsYXNzPVwiZmlsZVNlbGVjdG9yIGN1c3RvbUZpbGVVcGxvYWRQbGFjbWVudCBoaWRkZW4gdi1yZXF1aXJlZC1tdWx0aXBsZWZpbGVzIGQtbm9uZVwiXHJcbiAgICAgICAgbXVsdGlwbGU9XCJ7eyBvcHRpb25zLmlzTXVsdGlwbGVGaWxlID8gJ211bHRpcGxlJyA6ICcnIH19XCIgbmFtZT1cImZpbGVcIiB0eXBlPVwiZmlsZVwiIHZhbHVlPVwiXCIgYXV0b2NvbXBsZXRlPVwib2ZmXCJcclxuICAgICAgICAoY2hhbmdlKT1cIm9uRmlsZUNoYW5nZSgpXCIgW25nQ2xhc3NdPVwib3B0aW9ucy52aWV3VHlwZSA9PSAxID8gJycgOiAnY29sLW1kLTknXCIgaWQ9XCJ7eyBvcHRpb25zLm5hbWUgfX1cIlxyXG4gICAgICAgIGFyaWEtZGVzY3JpYmVkYnk9XCJlbWFpbC1lcnJvclwiIGFyaWEtaW52YWxpZD1cInRydWVcIiBmb3JtQ29udHJvbE5hbWU9XCJ7eyBvcHRpb25zLm5hbWUgfX1cIiAjZmlsZUlucHV0XHJcbiAgICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwiZmlsZVVwbG9hZEZvcm1Db250cm9sLmludmFsaWQgJiYgZmlsZVVwbG9hZEZvcm1Db250cm9sLnRvdWNoZWRcIiAvPlxyXG4gICAgPC9kaXY+XHJcbiAgICA8IS0tIHJlYWRvbmx5IC0tPlxyXG4gICAgPGRpdiAqbmdJZj1cIm9wdGlvbnMuaXNSZWFkb25seSAmJiAhb3B0aW9ucy52YWx1ZVwiPlxyXG4gICAgICA8c3BhbiBjbGFzcz1cInJlYWRvbmx5LXZpZXdcIj57eyBVdGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdOQScpIH19PC9zcGFuPlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcbiAgPCEtLWl0ZW1zIHVwbG9hZGVkLS0+XHJcbiAgPGRpdiBjbGFzcz1cInVwbG9hZGVkLWl0ZW1zXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwiYnRuLWdyb3VwXCIgKm5nRm9yPVwibGV0IGl0ZW0gb2YgdXBsb2FkZXIucXVldWVcIj5cclxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIml0ZW0/LnByb2dyZXNzID09IDEwMCAmJiBvcHRpb25zLmlzVXBsb2FkRmlsZUFzeW5jXCI+XHJcbiAgICAgICAgPGEgKm5nSWY9XCJpdGVtPy5maWxlPy5yYXdGaWxlWyd1cmwnXVwiIGhyZWY9XCJ7eyBpdGVtPy5maWxlPy5yYXdGaWxlWyd1cmwnXSB9fVwiXHJcbiAgICAgICAgICBjbGFzcz1cImJ0bi1kb3dubG9hZC1maWxlIGJ0bi1zbSBidG4tcHJvZ3Jlc3MtdXBsb2FkXCIgZG93bmxvYWQ+XHJcbiAgICAgICAgICA8c3BhbiBjbGFzcz1cImZpbGUtbmFtZVwiPnt7IGl0ZW0/LmZpbGU/Lm5hbWUgfX08L3NwYW4+XHJcbiAgICAgICAgPC9hPlxyXG4gICAgICAgIDxhICpuZ0lmPVwiaXRlbT8uZmlsZT8ucmF3RmlsZVsndXJsJ10gPT0gbnVsbFwiIGNsYXNzPVwiYnRuLWRvd25sb2FkLWZpbGUgYnRuLXNtIGJ0bi1wcm9ncmVzcy11cGxvYWRcIj5cclxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZmlsZS1uYW1lXCI+e3sgaXRlbT8uZmlsZT8ubmFtZSB9fTwvc3Bhbj5cclxuICAgICAgICA8L2E+XHJcbiAgICAgICAgPGJ1dHRvbiAqbmdJZj1cIiFvcHRpb25zLmlzUmVhZG9ubHlcIiBjbGFzcz1cImJ0biBidG4tZG93bmxvYWQtZmlsZSBidG4tc21cIlxyXG4gICAgICAgICAgKGNsaWNrKT1cIml0ZW0ucmVtb3ZlKCk7IHJlbW92ZUZyb21Db250cm9sVmFsdWUoaXRlbSlcIj5cclxuICAgICAgICAgIDxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHdpZHRoPVwiMTRcIiBoZWlnaHQ9XCIxNFwiIHZpZXdCb3g9XCIwIDAgMTQgMTRcIiBmaWxsPVwibm9uZVwiPlxyXG4gICAgICAgICAgICA8cGF0aCBvcGFjaXR5PVwiMC40XCJcclxuICAgICAgICAgICAgICBkPVwiTTkuMzMzMDEgMy43MDU4NFYzLjI2NjYzQzkuMzMzMDEgMi42NTE2NiA5LjMzMzAxIDIuMzQ0MTkgOS4yMDU4NyAyLjEwOTNDOS4wOTQwNSAxLjkwMjcgOC45MTU1NSAxLjczNDcxIDguNjk2MDQgMS42Mjk0NEM4LjQ0NjQ3IDEuNTA5NzcgOC4xMTk3NyAxLjUwOTc3IDcuNDY2MzggMS41MDk3N0g2LjUzMzA1QzUuODc5NjUgMS41MDk3NyA1LjU1Mjk2IDEuNTA5NzcgNS4zMDMzOSAxLjYyOTQ0QzUuMDgzODcgMS43MzQ3MSA0LjkwNTM5IDEuOTAyNyA0Ljc5MzU0IDIuMTA5M0M0LjY2NjM4IDIuMzQ0MTkgNC42NjYzOCAyLjY1MTY2IDQuNjY2MzggMy4yNjY2M1YzLjcwNTg0XCJcclxuICAgICAgICAgICAgICBzdHJva2U9XCIjRDgzNzMxXCIgc3Ryb2tlLXdpZHRoPVwiMS41XCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIgLz5cclxuICAgICAgICAgICAgPHBhdGhcclxuICAgICAgICAgICAgICBkPVwiTTEuNzUgMy43MDYwNUgxMi4yNU0xMS4wODM0IDMuNzA2MDVWOS44NTUxQzExLjA4MzQgMTAuNzc3NSAxMS4wODM0IDExLjIzODcgMTAuODkyNiAxMS41OTFDMTAuNzI0OCAxMS45MDEgMTAuNDU3MSAxMi4xNTI5IDEwLjEyNzggMTIuMzEwOUM5Ljc1MzQ1IDEyLjQ5MDQgOS4yNjM0NSAxMi40OTA0IDguMjgzMzQgMTIuNDkwNEg1LjcxNjY2QzQuNzM2NTggMTIuNDkwNCA0LjI0NjUzIDEyLjQ5MDQgMy44NzIxOCAxMi4zMTA5QzMuNTQyOSAxMi4xNTI5IDMuMjc1MTkgMTEuOTAxIDMuMTA3NDEgMTEuNTkxQzIuOTE2NjYgMTEuMjM4NyAyLjkxNjY2IDEwLjc3NzUgMi45MTY2NiA5Ljg1NTFWMy43MDYwNVwiXHJcbiAgICAgICAgICAgICAgc3Ryb2tlPVwiI0Q4MzczMVwiIHN0cm9rZS13aWR0aD1cIjEuNVwiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiIC8+XHJcbiAgICAgICAgICA8L3N2Zz5cclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIhb3B0aW9ucy5pc1VwbG9hZEZpbGVBc3luY1wiPlxyXG4gICAgICAgIDxhIGhyZWY9XCJ7eyBpdGVtPy5maWxlPy5yYXdGaWxlWyd1cmwnXSB9fVwiIGNsYXNzPVwiYnRuIGJ0bi1kb3dubG9hZC1maWxlIGJ0bi1zbVwiIGRvd25sb2FkPlxyXG4gICAgICAgICAgPHN2ZyB3aWR0aD1cIjI0XCIgaGVpZ2h0PVwiMjRcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgZmlsbD1cIm5vbmVcIiB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCI+XHJcbiAgICAgICAgICAgIDxwYXRoXHJcbiAgICAgICAgICAgICAgZD1cIk0yMSAyMkgzQzIuNCAyMiAyIDIxLjYgMiAyMUMyIDIwLjQgMi40IDIwIDMgMjBIMjFDMjEuNiAyMCAyMiAyMC40IDIyIDIxQzIyIDIxLjYgMjEuNiAyMiAyMSAyMlpNMTMgMTMuNFYzQzEzIDIuNCAxMi42IDIgMTIgMkMxMS40IDIgMTEgMi40IDExIDNWMTMuNEgxM1pcIlxyXG4gICAgICAgICAgICAgIGZpbGw9XCJjdXJyZW50Q29sb3JcIj48L3BhdGg+XHJcbiAgICAgICAgICAgIDxwYXRoIG9wYWNpdHk9XCIwLjNcIiBkPVwiTTcgMTMuNEgxN0wxMi43IDE3LjdDMTIuMyAxOC4xIDExLjcgMTguMSAxMS4zIDE3LjdMNyAxMy40WlwiIGZpbGw9XCJjdXJyZW50Q29sb3JcIj5cclxuICAgICAgICAgICAgPC9wYXRoPlxyXG4gICAgICAgICAgPC9zdmc+XHJcbiAgICAgICAgICA8c3BhbiBjbGFzcz1cImZpbGUtbmFtZVwiPnt7IGl0ZW0/LmZpbGU/Lm5hbWUgfX08L3NwYW4+XHJcbiAgICAgICAgPC9hPlxyXG4gICAgICAgIDxidXR0b24gKm5nSWY9XCIhb3B0aW9ucy5pc1JlYWRvbmx5XCIgY2xhc3M9XCJidG4gYnRuLWRvd25sb2FkLWZpbGUgYnRuLXNtIGJ0bi1kYW5nZXJcIlxyXG4gICAgICAgICAgKGNsaWNrKT1cIml0ZW0ucmVtb3ZlKCk7IHJlbW92ZUZyb21Db250cm9sVmFsdWUoaXRlbSlcIj5cclxuICAgICAgICAgIDxpIGNsYXNzPVwiZmEgZmEtdGltZXMgcHgtMFwiPjwvaT5cclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuICA8IS0tcHJvZ3Jlc3MgYmFyIGZpbGUgdXBsb2FkLS0+XHJcbiAgPGRpdiAqbmdGb3I9XCJsZXQgaXRlbSBvZiB1cGxvYWRlci5xdWV1ZVwiPlxyXG4gICAgPGRpdiBjbGFzcz1cInVwbG9hZC1pdGVtc1wiIFtuZ0NsYXNzXT1cInsgJ210LTQnOiBvcHRpb25zLmlzTXVsdGlwbGVGaWxlID09IHRydWUgfVwiXHJcbiAgICAgICpuZ0lmPVwiaXRlbT8ucHJvZ3Jlc3MgPCAxMDAgJiYgb3B0aW9ucy5pc1VwbG9hZEZpbGVBc3luY1wiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwidXBsb2FkLWl0ZW1zLXRvb2xiYXJcIj5cclxuICAgICAgICA8aDQ+e3sgaXRlbT8uZmlsZT8ubmFtZSB9fTwvaDQ+XHJcbiAgICAgICAgPHNwYW4gKGNsaWNrKT1cIml0ZW0ucmVtb3ZlKCk7IHJlbW92ZUZyb21Db250cm9sVmFsdWUoaXRlbSlcIj5cclxuICAgICAgICAgIDxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHdpZHRoPVwiMThcIiBoZWlnaHQ9XCIxOFwiIHZpZXdCb3g9XCIwIDAgMTggMThcIiBmaWxsPVwibm9uZVwiPlxyXG4gICAgICAgICAgICA8ZyBjbGlwLXBhdGg9XCJ1cmwoI2NsaXAwXzEzMjRfMTMyMTYpXCI+XHJcbiAgICAgICAgICAgICAgPHBhdGggb3BhY2l0eT1cIjAuNFwiXHJcbiAgICAgICAgICAgICAgICBkPVwiTTkgMTYuNUMxMy4xNDIxIDE2LjUgMTYuNSAxMy4xNDIxIDE2LjUgOUMxNi41IDQuODU3ODYgMTMuMTQyMSAxLjUgOSAxLjVDNC44NTc4NiAxLjUgMS41IDQuODU3ODYgMS41IDlDMS41IDEzLjE0MjEgNC44NTc4NiAxNi41IDkgMTYuNVpcIlxyXG4gICAgICAgICAgICAgICAgc3Ryb2tlPVwiI0RCRTFGMFwiIHN0cm9rZS13aWR0aD1cIjJcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIiAvPlxyXG4gICAgICAgICAgICAgIDxwYXRoIGQ9XCJNMTEuMjUgNi43NUw2Ljc1IDExLjI1TTYuNzUgNi43NUwxMS4yNSAxMS4yNVwiIHN0cm9rZT1cIiNEQkUxRjBcIiBzdHJva2Utd2lkdGg9XCIyXCJcclxuICAgICAgICAgICAgICAgIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiIC8+XHJcbiAgICAgICAgICAgIDwvZz5cclxuICAgICAgICAgICAgPGRlZnM+XHJcbiAgICAgICAgICAgICAgPGNsaXBQYXRoIGlkPVwiY2xpcDBfMTMyNF8xMzIxNlwiPlxyXG4gICAgICAgICAgICAgICAgPHJlY3Qgd2lkdGg9XCIxOFwiIGhlaWdodD1cIjE4XCIgZmlsbD1cIndoaXRlXCIgLz5cclxuICAgICAgICAgICAgICA8L2NsaXBQYXRoPlxyXG4gICAgICAgICAgICA8L2RlZnM+XHJcbiAgICAgICAgICA8L3N2Zz5cclxuICAgICAgICA8L3NwYW4+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgICA8ZGl2IGNsYXNzPVwicHJvZ3Jlc3NcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwicHJvZ3Jlc3MtYmFyXCIgcm9sZT1cInByb2dyZXNzYmFyXCIgYXJpYS12YWx1ZW5vdz1cIjcwXCIgYXJpYS12YWx1ZW1pbj1cIjBcIiBhcmlhLXZhbHVlbWF4PVwiMTAwXCJcclxuICAgICAgICAgIFtjbGFzcy5maWxlLXVwbG9hZGVkXT1cIml0ZW0/LnByb2dyZXNzIDwgMTAwXCIgW3N0eWxlLndpZHRoLiVdPVwiaXRlbT8ucHJvZ3Jlc3NcIiAqbmdJZj1cIml0ZW0/LnByb2dyZXNzID4gMFwiPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG4gIDwvZGl2PlxyXG5cclxuICA8ZGl2IGNsYXNzPVwic3VidGV4dC1jb250YWluZXJcIiAqbmdJZj1cIiFvcHRpb25zLmlzUmVhZG9ubHlcIj5cclxuICAgIDwhLS0gcmVxdWlyZWQgdGV4dC0tPlxyXG4gICAgPGRpdiBjbGFzcz1cImJic2YtdmFsaWRhdGlvblwiICpuZ0lmPVwiZmlsZVVwbG9hZEZvcm1Db250cm9sLmludmFsaWQgJiYgZmlsZVVwbG9hZEZvcm1Db250cm9sLnRvdWNoZWRcIj5cclxuICAgICAge3sgZ2V0RXJyb3JWYWxpZGF0aW9uKGZpbGVVcGxvYWRGb3JtQ29udHJvbC5lcnJvcnMgfCBrZXl2YWx1ZSkgfX1cclxuICAgIDwvZGl2PlxyXG4gICAgPCEtLSBMYWJlbERlc2NyaXB0aW9uLS0+XHJcbiAgICA8ZGl2IGNsYXNzPVwiYmJzZi1jb250cm9sLWRlc2NcIiAqbmdJZj1cIm9wdGlvbnMubGFiZWxEZXNjcmlwdGlvbiAhPSBudWxsXCI+e3sgb3B0aW9ucy5sYWJlbERlc2NyaXB0aW9uIH19PC9kaXY+XHJcbiAgICA8ZGl2ICpuZ0lmPVwiKGdyb3VwLnZhbGlkICYmIGdyb3VwLmRpcnR5ICYmIGdyb3VwLnRvdWNoZWQpIHx8IChncm91cC51bnRvdWNoZWQgJiYgZ3JvdXAuaW52YWxpZCAmJiBncm91cC5kaXJ0eSlcIj5cclxuICAgICAge3sgcmVzZXRFcnJvcigpIH19XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuPC9kaXY+Il19