@bnsights/bbsf-controls 1.0.179 → 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.
- package/README.md +2 -3
- package/esm2022/lib/controls/FileUpload/FileUpload.component.mjs +439 -1091
- package/fesm2022/bnsights-bbsf-controls.mjs +441 -1093
- package/fesm2022/bnsights-bbsf-controls.mjs.map +1 -1
- package/lib/controls/FileUpload/FileUpload.component.d.ts +14 -123
- package/package.json +2 -2
|
@@ -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,1216 +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.
|
|
18
|
-
constructor(controlContainer,
|
|
17
|
+
static { this.controlContainerstatic = null; }
|
|
18
|
+
constructor(controlContainer, MultipleFileUplaodControlHost, controlUtility, UtilityService, controlValidationService, globalSettings, fileUploadService) {
|
|
19
19
|
this.controlContainer = controlContainer;
|
|
20
|
-
this.
|
|
20
|
+
this.MultipleFileUplaodControlHost = MultipleFileUplaodControlHost;
|
|
21
21
|
this.controlUtility = controlUtility;
|
|
22
|
-
this.
|
|
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.hasClearedRequiredError = false; // Track if required error was already cleared
|
|
33
|
-
this.isSubmitted = false;
|
|
34
26
|
this.OnChange = new EventEmitter();
|
|
35
27
|
this.isUploadComplete = new EventEmitter();
|
|
36
28
|
this.validationMessage = '';
|
|
37
29
|
this.validationCountMessage = '';
|
|
38
|
-
this.hasAnotherDropZoneOver = false;
|
|
39
30
|
this.acceptedType = '';
|
|
40
31
|
this.acceptedTypeArray = [];
|
|
41
32
|
this.toolTipTypeArray = [];
|
|
42
33
|
this.markAllAsTouched = false;
|
|
43
34
|
this.validationRules = [];
|
|
44
|
-
this.
|
|
45
|
-
this.file = null;
|
|
35
|
+
this.validationRulesasync = [];
|
|
46
36
|
this.deletedFiles = [];
|
|
47
|
-
this.subscriptions = new Subscription();
|
|
48
37
|
this.resetError = () => {
|
|
49
38
|
this.controlValidationService.removeGlobalError();
|
|
50
39
|
};
|
|
40
|
+
//External Method
|
|
51
41
|
this.removeRequiredValidation = () => {
|
|
52
42
|
this.controlUtility.removeRequiredValidation(this.fileUploadFormControl, this.validationRules, this.options);
|
|
53
43
|
};
|
|
54
|
-
|
|
55
|
-
this.validationRules = this.validationRules.filter(validator => validator !== Validators.required);
|
|
56
|
-
this.fileUploadFormControl.setValidators(this.validationRules);
|
|
57
|
-
this.fileUploadFormControl.updateValueAndValidity();
|
|
58
|
-
};
|
|
44
|
+
//External Method
|
|
59
45
|
this.addRequiredValidation = () => {
|
|
60
46
|
this.controlUtility.addRequiredValidation(this.fileUploadFormControl, this.validationRules, this.options);
|
|
61
47
|
};
|
|
48
|
+
//External Method
|
|
62
49
|
this.removeCustomValidation = (customValidation) => {
|
|
63
50
|
this.controlUtility.removeCustomValidation(this.fileUploadFormControl, this.validationRules, customValidation);
|
|
64
51
|
};
|
|
52
|
+
//External Method
|
|
65
53
|
this.addCustomValidation = (customValidation) => {
|
|
66
54
|
this.controlUtility.addCustomValidation(this.fileUploadFormControl, this.validationRules, customValidation);
|
|
67
55
|
};
|
|
56
|
+
//External Method
|
|
68
57
|
this.isValid = () => {
|
|
69
58
|
this.controlUtility.isValid(this.fileUploadFormControl);
|
|
70
|
-
return this.fileUploadFormControl.valid;
|
|
71
59
|
};
|
|
72
|
-
FileUploadComponent.
|
|
73
|
-
this.initializeUploader();
|
|
74
|
-
}
|
|
75
|
-
initializeUploader() {
|
|
60
|
+
FileUploadComponent.controlContainerstatic = this.controlContainer;
|
|
76
61
|
this.uploader = new FileUploader({
|
|
77
|
-
disableMultipart: false
|
|
62
|
+
disableMultipart: false // 'DisableMultipart' must be 'true' for formatDataFunction to be called.
|
|
78
63
|
});
|
|
64
|
+
this.hasAnotherDropZoneOver = false;
|
|
79
65
|
}
|
|
80
66
|
ngOnInit() {
|
|
81
|
-
this.initializeModels();
|
|
82
|
-
this.setViewType();
|
|
83
|
-
this.processInitialValue();
|
|
84
|
-
this.setupLabels();
|
|
85
|
-
this.setupFileTypeValidation();
|
|
86
|
-
this.setupFormControl();
|
|
87
|
-
this.setupSubscriptions();
|
|
88
|
-
}
|
|
89
|
-
initializeModels() {
|
|
90
67
|
this.fileUploadModel = new FileUploadModel();
|
|
91
68
|
this.multipleFileUploadModel = new MultipleFileUploadModel();
|
|
92
|
-
|
|
93
|
-
setViewType() {
|
|
94
|
-
if (!this.options.viewType) {
|
|
69
|
+
if (!this.options.viewType)
|
|
95
70
|
this.options.viewType = this.globalSettings.viewType;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
processInitialValue() {
|
|
99
71
|
if (this.options.value == null) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
this.processSingleFileValue();
|
|
107
|
-
}
|
|
108
|
-
this.uploader.queue.forEach((element) => {
|
|
109
|
-
element.progress = this.PROGRESS_COMPLETE;
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
processMultipleFileValue() {
|
|
113
|
-
const files = [];
|
|
114
|
-
this.multipleFileUploadModel.existingFiles = this.options.value.existingFiles;
|
|
115
|
-
this.multipleFileUploadModel.uploadedFiles = [];
|
|
116
|
-
for (const element of this.options.value.existingFiles) {
|
|
117
|
-
const fileLikeObject = this.createFileLikeObject(element);
|
|
118
|
-
files.push(fileLikeObject);
|
|
119
|
-
}
|
|
120
|
-
this.uploader.addToQueue(files);
|
|
121
|
-
}
|
|
122
|
-
processSingleFileValue() {
|
|
123
|
-
const element = this.options.value.file ?? this.options.value;
|
|
124
|
-
const fileLikeObject = this.createFileLikeObject(element);
|
|
125
|
-
this.file = element;
|
|
126
|
-
this.uploader.addToQueue([fileLikeObject]);
|
|
127
|
-
if (!this.options.value.file) {
|
|
128
|
-
this.fileUploadModel = new FileUploadModel();
|
|
129
|
-
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
|
+
}
|
|
130
78
|
}
|
|
131
79
|
else {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
try {
|
|
159
|
-
this.processAcceptedTypes();
|
|
160
|
-
this.buildValidationMessage();
|
|
161
|
-
// Log the processed types for debugging
|
|
162
|
-
console.log('FileUpload: Processed file types:', {
|
|
163
|
-
original: this.options.fileUploadAcceptsTypes,
|
|
164
|
-
processed: this.acceptedTypeArray,
|
|
165
|
-
acceptAttribute: this.acceptedType,
|
|
166
|
-
displayTypes: this.toolTipTypeArray
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
catch (error) {
|
|
170
|
-
console.error('FileUpload: Error processing file types:', error);
|
|
171
|
-
// Fallback to accepting all files if processing fails
|
|
172
|
-
this.acceptedType = '';
|
|
173
|
-
this.acceptedTypeArray = [];
|
|
174
|
-
this.toolTipTypeArray = [];
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
processAcceptedTypes() {
|
|
178
|
-
// Process each file type and extract individual MIME types
|
|
179
|
-
const allMimeTypes = [];
|
|
180
|
-
for (const fileType of this.options.fileUploadAcceptsTypes) {
|
|
181
|
-
if (fileType.includes(',')) {
|
|
182
|
-
// Handle types like ImageTypes that contain multiple MIME types
|
|
183
|
-
const mimeTypes = fileType.split(',').map(type => type.trim());
|
|
184
|
-
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);
|
|
185
104
|
}
|
|
186
105
|
else {
|
|
187
|
-
|
|
188
|
-
|
|
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;
|
|
189
125
|
}
|
|
126
|
+
this.uploader.queue.forEach((element) => {
|
|
127
|
+
element.progress = 100;
|
|
128
|
+
});
|
|
190
129
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
.
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
this.acceptedTypeArray = allMimeTypes.filter(type => type.trim());
|
|
199
|
-
const mimeTypeMap = this.getMimeTypeMap();
|
|
200
|
-
for (const type of this.acceptedTypeArray) {
|
|
201
|
-
const displayType = mimeTypeMap[type];
|
|
202
|
-
if (displayType && !this.toolTipTypeArray.includes(displayType)) {
|
|
203
|
-
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 + ',';
|
|
204
137
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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}) `;
|
|
243
241
|
}
|
|
244
242
|
if (this.options.fileMaxSizeInMB > 0) {
|
|
245
|
-
|
|
243
|
+
this.validationMessage =
|
|
244
|
+
this.validationMessage +
|
|
245
|
+
`<br /> ${this.UtilityService.getResourceValue('FileMaxSizeInMB') + this.options.fileMaxSizeInMB} `;
|
|
246
246
|
}
|
|
247
247
|
if (this.options.minNoOfFiles > 0) {
|
|
248
|
-
|
|
248
|
+
this.validationMessage =
|
|
249
|
+
this.validationMessage +
|
|
250
|
+
`<br /> ${this.UtilityService.getResourceValue('MinFileCountValidationKey') + this.options.minNoOfFiles}`;
|
|
249
251
|
}
|
|
250
252
|
if (this.options.maxNoOfFiles > 0) {
|
|
251
|
-
|
|
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) {
|
|
252
259
|
}
|
|
253
|
-
this.validationMessage = messages.join(' <br/> ');
|
|
254
|
-
}
|
|
255
|
-
setupFormControl() {
|
|
256
260
|
this.group.addControl(this.options.name, new FormControl(''));
|
|
257
|
-
this.fileUploadFormControl = this.group.controls[this.options.name];
|
|
258
|
-
this.
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
setupValidators() {
|
|
264
|
-
if (this.options.customValidation?.length) {
|
|
265
|
-
for (const validation of this.options.customValidation) {
|
|
266
|
-
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);
|
|
267
267
|
}
|
|
268
268
|
}
|
|
269
|
+
if (this.options.isMultipleFile && this.options.maxNoOfFiles > 0) {
|
|
270
|
+
this.validationCountMessage = `${this.UtilityService.getResourceValue('MaxFilesCount')} : ${this.options.maxNoOfFiles}`;
|
|
271
|
+
}
|
|
269
272
|
if (this.options.isRequired) {
|
|
270
273
|
this.validationRules.push(Validators.required);
|
|
271
274
|
}
|
|
272
|
-
}
|
|
273
|
-
setupCountMessage() {
|
|
274
|
-
if (this.options.isMultipleFile && this.options.maxNoOfFiles > 0) {
|
|
275
|
-
this.validationCountMessage = `${this.utilityService.getResourceValue('MaxFilesCount')} : ${this.options.maxNoOfFiles}`;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
applyValidatorsAndState() {
|
|
279
275
|
this.fileUploadFormControl.setValidators(this.validationRules);
|
|
280
|
-
|
|
281
|
-
this.fileUploadFormControl.setAsyncValidators(this.validationRulesAsync);
|
|
282
|
-
}
|
|
276
|
+
this.fileUploadFormControl.setAsyncValidators(this.validationRulesasync);
|
|
283
277
|
if (this.options.isDisabled) {
|
|
284
278
|
this.fileUploadFormControl.disable();
|
|
285
279
|
}
|
|
286
|
-
|
|
287
|
-
setupSubscriptions() {
|
|
288
|
-
this.multipleFileUploadControlHost.ngSubmit.subscribe(() => {
|
|
280
|
+
this.MultipleFileUplaodControlHost.ngSubmit.subscribe((value) => {
|
|
289
281
|
this.group.markAllAsTouched();
|
|
290
282
|
this.markAllAsTouched = true;
|
|
291
283
|
});
|
|
284
|
+
this.fileUploadFormControl.setValue(this.options.value);
|
|
292
285
|
}
|
|
293
286
|
ngAfterViewInit() {
|
|
294
|
-
this.
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
return;
|
|
299
|
-
}
|
|
300
|
-
const element = document.getElementById(this.options.name);
|
|
301
|
-
if (element) {
|
|
302
|
-
for (const attribute of this.options.attributeList) {
|
|
303
|
-
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);
|
|
304
291
|
}
|
|
305
292
|
}
|
|
306
293
|
}
|
|
307
294
|
showGlobalError() {
|
|
308
295
|
this.controlUtility.showGlobalError();
|
|
309
296
|
}
|
|
310
|
-
getErrorValidation(
|
|
297
|
+
getErrorValidation(ErrorList) {
|
|
311
298
|
if (this.markAllAsTouched && this.group.invalid) {
|
|
312
299
|
this.showGlobalError();
|
|
313
300
|
this.markAllAsTouched = false;
|
|
314
301
|
}
|
|
315
|
-
|
|
316
|
-
for (const error of errorList) {
|
|
317
|
-
if (error.key === 'InvalidFiles') {
|
|
318
|
-
return error.value;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
return this.controlUtility.getErrorValidationMassage(errorList, this.group, this.options);
|
|
302
|
+
return this.controlUtility.getErrorValidationMassage(ErrorList, this.group, this.options);
|
|
323
303
|
}
|
|
324
304
|
fileOverAnother(event) {
|
|
325
|
-
this.hasAnotherDropZoneOver =
|
|
305
|
+
this.hasAnotherDropZoneOver = event;
|
|
326
306
|
}
|
|
327
307
|
isHideInput() {
|
|
328
308
|
if (this.options.isMultipleFile) {
|
|
329
|
-
|
|
330
|
-
this.options.maxNoOfFiles
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
}
|
|
334
|
-
onFileChange() {
|
|
335
|
-
this.validateFileConstraints();
|
|
336
|
-
const fileProcessingResult = this.processNewlyAddedFiles();
|
|
337
|
-
this.handleFileValidationResults(fileProcessingResult);
|
|
338
|
-
this.processValidFilesForUpload();
|
|
339
|
-
}
|
|
340
|
-
processNewlyAddedFiles() {
|
|
341
|
-
const addedQueue = this.getNewlyAddedFiles();
|
|
342
|
-
const validationResult = this.validateFilesInQueue(addedQueue);
|
|
343
|
-
return {
|
|
344
|
-
validFiles: addedQueue.filter(file => !validationResult.invalidFiles.includes(file)),
|
|
345
|
-
invalidFiles: validationResult.invalidFiles,
|
|
346
|
-
errors: validationResult.errors
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
getNewlyAddedFiles() {
|
|
350
|
-
return this.uploader.queue.filter((obj) => obj['some']?.lastModified != null);
|
|
351
|
-
}
|
|
352
|
-
validateFilesInQueue(fileQueue) {
|
|
353
|
-
const validationErrors = [];
|
|
354
|
-
const invalidFiles = [];
|
|
355
|
-
const processedDuplicateNames = new Set();
|
|
356
|
-
for (const element of fileQueue) {
|
|
357
|
-
const file = element.file;
|
|
358
|
-
if (!file)
|
|
359
|
-
continue;
|
|
360
|
-
const fileValidation = this.validateSingleFile(file, element, processedDuplicateNames);
|
|
361
|
-
if (!fileValidation.isValid) {
|
|
362
|
-
invalidFiles.push(element);
|
|
363
|
-
validationErrors.push(...fileValidation.errors);
|
|
309
|
+
if (this.options.maxNoOfFiles != null &&
|
|
310
|
+
this.options.maxNoOfFiles > 0 &&
|
|
311
|
+
this.options.maxNoOfFiles == this.uploader.queue.length) {
|
|
312
|
+
return true;
|
|
364
313
|
}
|
|
365
314
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
invalidFiles
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
validateSingleFile(file, element, processedDuplicateNames) {
|
|
373
|
-
const errors = [];
|
|
374
|
-
const sizeValid = this.validateIndividualFileSize(file);
|
|
375
|
-
const typeValid = this.validateIndividualFileType(file);
|
|
376
|
-
const nameValid = this.validateDuplicateFileName(file, element);
|
|
377
|
-
if (!sizeValid) {
|
|
378
|
-
errors.push(this.createFileSizeErrorMessage(file.name));
|
|
379
|
-
}
|
|
380
|
-
if (!typeValid) {
|
|
381
|
-
errors.push(this.createFileTypeErrorMessage(file.name));
|
|
382
|
-
}
|
|
383
|
-
if (!nameValid) {
|
|
384
|
-
const duplicateError = this.createDuplicateFileErrorMessage(file.name, processedDuplicateNames);
|
|
385
|
-
if (duplicateError) {
|
|
386
|
-
errors.push(duplicateError);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
return {
|
|
390
|
-
isValid: sizeValid && typeValid && nameValid,
|
|
391
|
-
errors,
|
|
392
|
-
invalidFiles: []
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
createFileSizeErrorMessage(fileName) {
|
|
396
|
-
return this.utilityService.getResourceValue('FileExceedsMaxSize')
|
|
397
|
-
.replace('{fileName}', fileName)
|
|
398
|
-
.replace('{maxSize}', this.options.fileMaxSizeInMB.toString());
|
|
399
|
-
}
|
|
400
|
-
createFileTypeErrorMessage(fileName) {
|
|
401
|
-
return this.utilityService.getResourceValue('FileTypeNotAccepted')
|
|
402
|
-
.replace('{fileName}', fileName);
|
|
403
|
-
}
|
|
404
|
-
createDuplicateFileErrorMessage(fileName, processedDuplicateNames) {
|
|
405
|
-
const fileNameLower = fileName.toLowerCase();
|
|
406
|
-
if (processedDuplicateNames.has(fileNameLower)) {
|
|
407
|
-
return null;
|
|
408
|
-
}
|
|
409
|
-
processedDuplicateNames.add(fileNameLower);
|
|
410
|
-
let duplicateErrorMsg = this.utilityService.getResourceValue('DuplicateFileName');
|
|
411
|
-
if (!duplicateErrorMsg || duplicateErrorMsg === 'DuplicateFileName') {
|
|
412
|
-
duplicateErrorMsg = `File '{fileName}' already exists. Please choose a different file or rename it.`;
|
|
413
|
-
}
|
|
414
|
-
return duplicateErrorMsg.replace('{fileName}', fileName);
|
|
415
|
-
}
|
|
416
|
-
handleFileValidationResults(result) {
|
|
417
|
-
if (result.invalidFiles.length > 0) {
|
|
418
|
-
this.removeInvalidFiles(result.invalidFiles);
|
|
419
|
-
}
|
|
420
|
-
if (result.errors.length > 0) {
|
|
421
|
-
this.showValidationErrors(result.errors);
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
processValidFilesForUpload() {
|
|
425
|
-
const filesArray = [];
|
|
426
|
-
const validQueue = this.getNewlyAddedFiles();
|
|
427
|
-
for (const element of validQueue) {
|
|
428
|
-
const file = element.file;
|
|
429
|
-
if (!file)
|
|
430
|
-
continue;
|
|
431
|
-
if (this.shouldUseAsyncUpload(element)) {
|
|
432
|
-
this.handleAsyncFileUpload(element, filesArray);
|
|
433
|
-
}
|
|
434
|
-
else {
|
|
435
|
-
this.handleSyncFileUpload(file, filesArray);
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
shouldUseAsyncUpload(element) {
|
|
440
|
-
return this.options.isUploadFileAsync && !element._file['iD_GUID'];
|
|
441
|
-
}
|
|
442
|
-
validateFileConstraints() {
|
|
443
|
-
if (this.options.isMultipleFile) {
|
|
444
|
-
if (!this.validateMinFileCount() || !this.validateMaxFileCount() || !this.validateTotalFileSize()) {
|
|
445
|
-
return false;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
return true;
|
|
449
|
-
}
|
|
450
|
-
validateMinFileCount() {
|
|
451
|
-
if (this.options.minNoOfFiles > 0 && this.options.minNoOfFiles > this.uploader.queue.length) {
|
|
452
|
-
const minFileMsg = this.utilityService.getResourceValue('MinimumFilesRequired')
|
|
453
|
-
.replace('{count}', this.options.minNoOfFiles.toString());
|
|
454
|
-
this.showFileCountError('MinFileCountValidationKey', minFileMsg);
|
|
455
|
-
return false;
|
|
456
|
-
}
|
|
457
|
-
return true;
|
|
458
|
-
}
|
|
459
|
-
validateMaxFileCount() {
|
|
460
|
-
if (this.options.maxNoOfFiles > 0 && this.options.maxNoOfFiles < this.uploader.queue.length) {
|
|
461
|
-
const maxFileMsg = this.utilityService.getResourceValue('MaximumFilesExceeded') ||
|
|
462
|
-
`Maximum {maxCount} files allowed. You have selected {currentCount} files.`;
|
|
463
|
-
const finalMsg = maxFileMsg
|
|
464
|
-
.replace('{maxCount}', this.options.maxNoOfFiles.toString())
|
|
465
|
-
.replace('{currentCount}', this.uploader.queue.length.toString());
|
|
466
|
-
this.showFileCountError('MaxFileCountValidationKey', finalMsg);
|
|
467
|
-
return false;
|
|
468
|
-
}
|
|
469
|
-
return true;
|
|
470
|
-
}
|
|
471
|
-
showFileCountError(errorKey, message) {
|
|
472
|
-
const currentErrors = this.fileUploadFormControl.errors || {};
|
|
473
|
-
// Preserve existing errors and add the new one
|
|
474
|
-
const newErrors = { ...currentErrors };
|
|
475
|
-
newErrors[errorKey] = message;
|
|
476
|
-
this.fileUploadFormControl.setErrors(newErrors);
|
|
477
|
-
this.fileUploadFormControl.markAsTouched();
|
|
478
|
-
// Force the form control to be invalid
|
|
479
|
-
this.fileUploadFormControl.markAsDirty();
|
|
480
|
-
// Ensure the error persists
|
|
481
|
-
this.forceValidationErrorDisplay(errorKey, message);
|
|
482
|
-
}
|
|
483
|
-
forceValidationErrorDisplay(errorKey, message) {
|
|
484
|
-
// Force the validation error to persist by re-applying it after a short delay
|
|
485
|
-
setTimeout(() => {
|
|
486
|
-
const currentErrors = this.fileUploadFormControl.errors || {};
|
|
487
|
-
if (!currentErrors[errorKey]) {
|
|
488
|
-
const newErrors = { ...currentErrors };
|
|
489
|
-
newErrors[errorKey] = message;
|
|
490
|
-
this.fileUploadFormControl.setErrors(newErrors);
|
|
491
|
-
this.fileUploadFormControl.markAsTouched();
|
|
492
|
-
this.fileUploadFormControl.markAsDirty();
|
|
493
|
-
}
|
|
494
|
-
}, 100);
|
|
495
|
-
}
|
|
496
|
-
clearFileCountError(errorKey) {
|
|
497
|
-
const currentErrors = this.fileUploadFormControl.errors;
|
|
498
|
-
if (currentErrors && currentErrors[errorKey]) {
|
|
499
|
-
delete currentErrors[errorKey];
|
|
500
|
-
if (Object.keys(currentErrors).length === 0) {
|
|
501
|
-
this.fileUploadFormControl.setErrors(null);
|
|
502
|
-
}
|
|
503
|
-
else {
|
|
504
|
-
this.fileUploadFormControl.setErrors(currentErrors);
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
validateTotalFileSize() {
|
|
509
|
-
if (this.options.maxSizeForAllFilesInMB > 0) {
|
|
510
|
-
const totalSize = this.uploader.queue.reduce((sum, element) => sum + element.file.size, 0);
|
|
511
|
-
const maxSizeBytes = this.options.maxSizeForAllFilesInMB * this.BYTES_TO_MB;
|
|
512
|
-
if (totalSize > maxSizeBytes) {
|
|
513
|
-
this.showTotalSizeError();
|
|
514
|
-
return false;
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
return true;
|
|
518
|
-
}
|
|
519
|
-
showTotalSizeError() {
|
|
520
|
-
const totalSizeMsg = this.utilityService.getResourceValue('TotalFileSizeExceeded')
|
|
521
|
-
.replace('{maxSize}', this.options.maxSizeForAllFilesInMB.toString());
|
|
522
|
-
const currentErrors = this.fileUploadFormControl.errors || {};
|
|
523
|
-
// Preserve existing errors and add the new one
|
|
524
|
-
const newErrors = { ...currentErrors };
|
|
525
|
-
newErrors['MaxSizeForAllFilesInMB'] = totalSizeMsg;
|
|
526
|
-
this.fileUploadFormControl.setErrors(newErrors);
|
|
527
|
-
this.fileUploadFormControl.markAsTouched();
|
|
528
|
-
// Force the form control to be invalid
|
|
529
|
-
this.fileUploadFormControl.markAsDirty();
|
|
530
|
-
// Ensure the error persists
|
|
531
|
-
this.forceValidationErrorDisplay('MaxSizeForAllFilesInMB', totalSizeMsg);
|
|
532
|
-
}
|
|
533
|
-
validateFileSize(file) {
|
|
534
|
-
const maxFileSize = this.options.fileMaxSizeInMB * this.BYTES_TO_MB;
|
|
535
|
-
if (file.size > maxFileSize) {
|
|
536
|
-
this.setFormControlError('FileMaxSizeInMB', `${this.options.fileMaxSizeInMB}MB`);
|
|
537
|
-
return false;
|
|
538
|
-
}
|
|
539
|
-
return true;
|
|
540
|
-
}
|
|
541
|
-
validateFileType(file) {
|
|
542
|
-
if (this.options.fileUploadAcceptsTypes?.length) {
|
|
543
|
-
const fileType = file.type;
|
|
544
|
-
const isAccepted = this.acceptedTypeArray.some(type => type.toLowerCase() === fileType.toLowerCase());
|
|
545
|
-
if (!isAccepted) {
|
|
546
|
-
this.setFormControlError('ToolTipTypeError', this.toolTipTypeArray);
|
|
547
|
-
return false;
|
|
315
|
+
else {
|
|
316
|
+
if (this.uploader.queue.length > 0) {
|
|
317
|
+
return true;
|
|
548
318
|
}
|
|
549
319
|
}
|
|
550
|
-
return
|
|
551
|
-
}
|
|
552
|
-
validateIndividualFileSize(file) {
|
|
553
|
-
const maxFileSize = this.options.fileMaxSizeInMB * this.BYTES_TO_MB;
|
|
554
|
-
return file.size <= maxFileSize;
|
|
555
|
-
}
|
|
556
|
-
validateIndividualFileType(file) {
|
|
557
|
-
if (!this.options.fileUploadAcceptsTypes?.length) {
|
|
558
|
-
return true;
|
|
559
|
-
}
|
|
560
|
-
const fileType = file.type?.toLowerCase();
|
|
561
|
-
if (!fileType) {
|
|
562
|
-
return false;
|
|
563
|
-
}
|
|
564
|
-
return this.acceptedTypeArray.some(type => type.toLowerCase() === fileType);
|
|
320
|
+
return false;
|
|
565
321
|
}
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
});
|
|
576
|
-
if (duplicateExists) {
|
|
577
|
-
return false;
|
|
578
|
-
}
|
|
579
|
-
if (this.options.value) {
|
|
580
|
-
const uploadedFiles = Array.isArray(this.options.value) ? this.options.value : [this.options.value];
|
|
581
|
-
const duplicateInUploaded = uploadedFiles.some(uploadedFile => {
|
|
582
|
-
const uploadedFileName = uploadedFile?.fileName || uploadedFile?.name;
|
|
583
|
-
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
|
|
584
331
|
});
|
|
585
|
-
|
|
332
|
+
formControl.markAsTouched();
|
|
333
|
+
this.uploader.queue = [];
|
|
334
|
+
return;
|
|
586
335
|
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
const
|
|
592
|
-
|
|
593
|
-
this.
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
showValidationErrors(errors) {
|
|
598
|
-
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 = [];
|
|
599
346
|
return;
|
|
600
|
-
|
|
601
|
-
this.
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
// Preserve existing errors and add the new one
|
|
610
|
-
const newErrors = { ...currentErrors };
|
|
611
|
-
newErrors[errorKey] = errorMessage;
|
|
612
|
-
this.fileUploadFormControl.setErrors(newErrors);
|
|
613
|
-
this.fileUploadFormControl.markAsTouched();
|
|
614
|
-
// Force the form control to be invalid
|
|
615
|
-
this.fileUploadFormControl.markAsDirty();
|
|
616
|
-
// Ensure the error persists
|
|
617
|
-
this.forceValidationErrorDisplay(errorKey, errorMessage);
|
|
618
|
-
}
|
|
619
|
-
clearInvalidFilesError() {
|
|
620
|
-
const currentErrors = this.fileUploadFormControl.errors;
|
|
621
|
-
if (currentErrors && currentErrors['InvalidFiles']) {
|
|
622
|
-
delete currentErrors['InvalidFiles'];
|
|
623
|
-
if (Object.keys(currentErrors).length === 0) {
|
|
624
|
-
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;
|
|
625
356
|
}
|
|
626
|
-
|
|
627
|
-
|
|
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;
|
|
628
366
|
}
|
|
629
367
|
}
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
next: (event) => {
|
|
646
|
-
if (event.type === HttpEventType.UploadProgress) {
|
|
647
|
-
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;
|
|
648
383
|
}
|
|
649
|
-
|
|
650
|
-
this.
|
|
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);
|
|
651
489
|
}
|
|
652
|
-
},
|
|
653
|
-
error: (error) => {
|
|
654
|
-
console.error('Upload failed:', error);
|
|
655
|
-
// Handle upload error - you can add custom error handling here
|
|
656
|
-
}
|
|
657
|
-
});
|
|
658
|
-
// Store subscription for cleanup
|
|
659
|
-
this.subscriptions.add(uploadSubscription);
|
|
660
|
-
}
|
|
661
|
-
handleUploadProgress(element, event) {
|
|
662
|
-
const queueIndex = this.uploader.queue.findIndex((file) => file === element);
|
|
663
|
-
if (queueIndex === -1)
|
|
664
|
-
return;
|
|
665
|
-
const progress = Math.round((100 * event.loaded) / event.total);
|
|
666
|
-
this.uploader.queue[queueIndex].progress =
|
|
667
|
-
progress >= this.PROGRESS_NEAR_COMPLETE ? this.PROGRESS_NEAR_COMPLETE : progress;
|
|
668
|
-
}
|
|
669
|
-
handleUploadComplete(element, event, filesArray) {
|
|
670
|
-
const queueIndex = this.uploader.queue.findIndex((file) => file === element);
|
|
671
|
-
if (queueIndex === -1)
|
|
672
|
-
return;
|
|
673
|
-
this.uploader.queue[queueIndex].progress = this.PROGRESS_COMPLETE;
|
|
674
|
-
const fileID = event.body.val;
|
|
675
|
-
this.updateElementWithFileInfo(element, fileID, event.body.downloadUrl);
|
|
676
|
-
const addedFile = this.createFileDTO(element, fileID, event.body.downloadUrl);
|
|
677
|
-
this.updateFormValue(addedFile, filesArray);
|
|
678
|
-
}
|
|
679
|
-
updateElementWithFileInfo(element, fileID, downloadUrl) {
|
|
680
|
-
element._file['iD_GUID'] = fileID;
|
|
681
|
-
element._file['isNew'] = true;
|
|
682
|
-
if (downloadUrl) {
|
|
683
|
-
element._file['url'] = downloadUrl;
|
|
684
|
-
element.file.url = downloadUrl;
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
createFileDTO(element, fileID, downloadUrl) {
|
|
688
|
-
return {
|
|
689
|
-
iD_GUID: fileID,
|
|
690
|
-
fileName: element._file['name'],
|
|
691
|
-
fileType: element._file['type'],
|
|
692
|
-
isNew: true,
|
|
693
|
-
fileBase64: '',
|
|
694
|
-
fileSizeInMB: element._file.size / this.BYTES_TO_MB,
|
|
695
|
-
nameWithExtension: element._file['name'],
|
|
696
|
-
fullFileURL: downloadUrl || null
|
|
697
|
-
};
|
|
698
|
-
}
|
|
699
|
-
handleSyncFileUpload(file, filesArray) {
|
|
700
|
-
this.trackMemoryUsage(file.size);
|
|
701
|
-
const reader = new FileReader();
|
|
702
|
-
// Store reader reference for cleanup
|
|
703
|
-
const readerRef = reader;
|
|
704
|
-
reader.onload = () => {
|
|
705
|
-
try {
|
|
706
|
-
const existingGUID = this.getExistingFileGUID(file);
|
|
707
|
-
this.updateQueueItemForSync(file);
|
|
708
|
-
const addedFile = this.createSyncFileDTO(file, reader.result, existingGUID);
|
|
709
|
-
this.updateFormValue(addedFile, filesArray);
|
|
710
|
-
this.handlePatchAndEmit();
|
|
711
|
-
}
|
|
712
|
-
finally {
|
|
713
|
-
// Clean up reader
|
|
714
|
-
readerRef.onload = null;
|
|
715
|
-
readerRef.onerror = null;
|
|
716
|
-
readerRef.onabort = null;
|
|
717
490
|
}
|
|
718
|
-
};
|
|
719
|
-
reader.onerror = () => {
|
|
720
|
-
console.error('File reading failed');
|
|
721
|
-
readerRef.onload = null;
|
|
722
|
-
readerRef.onerror = null;
|
|
723
|
-
readerRef.onabort = null;
|
|
724
|
-
};
|
|
725
|
-
reader.readAsDataURL(file.rawFile);
|
|
726
|
-
}
|
|
727
|
-
updateQueueItemForSync(file) {
|
|
728
|
-
const queueItem = this.findQueueItemByFile(file);
|
|
729
|
-
if (queueItem) {
|
|
730
|
-
this.preserveFileReference(queueItem, file);
|
|
731
|
-
queueItem.progress = this.PROGRESS_COMPLETE;
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
findQueueItemByFile(file) {
|
|
735
|
-
return this.uploader.queue.find(item => item.file.name === file.name && item.file.size === file.size);
|
|
736
|
-
}
|
|
737
|
-
preserveFileReference(queueItem, file) {
|
|
738
|
-
queueItem._file.rawFile = file.rawFile;
|
|
739
|
-
queueItem.file.rawFile = file.rawFile;
|
|
740
|
-
}
|
|
741
|
-
createSyncFileDTO(file, readerResult, existingGUID) {
|
|
742
|
-
return {
|
|
743
|
-
fileName: file.name,
|
|
744
|
-
fileType: file.type,
|
|
745
|
-
fileBase64: readerResult.split(',')[1],
|
|
746
|
-
fileSizeInMB: file.size / this.BYTES_TO_MB,
|
|
747
|
-
nameWithExtension: file.name,
|
|
748
|
-
iD_GUID: existingGUID,
|
|
749
|
-
isNew: true,
|
|
750
|
-
fullFileURL: null
|
|
751
|
-
};
|
|
752
|
-
}
|
|
753
|
-
getExistingFileGUID(file) {
|
|
754
|
-
if (!this.options.isMultipleFile && this.file) {
|
|
755
|
-
return this.file.nameWithExtension === file.name ? this.file.iD_GUID : null;
|
|
756
|
-
}
|
|
757
|
-
return null;
|
|
758
|
-
}
|
|
759
|
-
updateFormValue(addedFile, filesArray) {
|
|
760
|
-
if (!this.options.isMultipleFile) {
|
|
761
|
-
this.fileUploadModel = new FileUploadModel();
|
|
762
|
-
this.fileUploadModel.file = addedFile;
|
|
763
|
-
this.updateFormControl(this.fileUploadModel);
|
|
764
|
-
}
|
|
765
|
-
else {
|
|
766
|
-
filesArray.push(addedFile);
|
|
767
|
-
this.multipleFileUploadModel.uploadedFiles = filesArray;
|
|
768
|
-
this.setupMultipleFileModel();
|
|
769
|
-
this.updateFormControl(this.multipleFileUploadModel);
|
|
770
|
-
this.isUploadComplete.emit(true);
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
setupMultipleFileModel() {
|
|
774
|
-
if (this.options.value?.correlationID_GUID == null) {
|
|
775
|
-
this.multipleFileUploadModel.removedFiles = [];
|
|
776
|
-
}
|
|
777
|
-
this.multipleFileUploadModel.correlationID_GUID = this.options.value?.correlationID_GUID;
|
|
778
|
-
}
|
|
779
|
-
updateFormControl(value) {
|
|
780
|
-
this.preserveErrorsAndUpdateValue(value);
|
|
781
|
-
this.options.value = value;
|
|
782
|
-
}
|
|
783
|
-
preserveErrorsAndUpdateValue(value) {
|
|
784
|
-
// If we have a valid file value and haven't cleared the required error yet, remove it
|
|
785
|
-
if (this.hasValidFileValue(value) && !this.hasClearedRequiredError) {
|
|
786
|
-
// Use the custom method that only removes the validator without changing the isRequired option
|
|
787
|
-
// This keeps the asterisk visible while removing the validation logic
|
|
788
|
-
this.removeRequiredValidatorOnly();
|
|
789
|
-
// Mark that we've cleared the required error
|
|
790
|
-
this.hasClearedRequiredError = true;
|
|
791
|
-
}
|
|
792
|
-
// Set the form control value
|
|
793
|
-
this.fileUploadFormControl.setValue(value, { emitEvent: false });
|
|
794
|
-
// Update the form group control value
|
|
795
|
-
this.group.get(this.options.name)?.setValue(value, { emitEvent: false });
|
|
796
|
-
}
|
|
797
|
-
hasValidFileValue(value) {
|
|
798
|
-
if (!value)
|
|
799
|
-
return false;
|
|
800
|
-
if (this.options.isMultipleFile) {
|
|
801
|
-
const multipleValue = value;
|
|
802
|
-
return (multipleValue.uploadedFiles && multipleValue.uploadedFiles.length > 0) ||
|
|
803
|
-
(multipleValue.existingFiles && multipleValue.existingFiles.length > 0);
|
|
804
|
-
}
|
|
805
|
-
else {
|
|
806
|
-
const singleValue = value;
|
|
807
|
-
return singleValue.file && singleValue.file.fileName !== '';
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
handlePatchAndEmit() {
|
|
811
|
-
const originalValue = this.group.get(this.options.name)?.value;
|
|
812
|
-
if (this.options.patchFunction && this.options.patchPath && this.group.get(this.options.name)?.valid) {
|
|
813
|
-
this.controlUtility.patchControlValue(originalValue, this.options.patchFunction, this.options.patchPath);
|
|
814
491
|
}
|
|
815
|
-
this.OnChange.emit(originalValue);
|
|
816
492
|
}
|
|
817
493
|
removeFromControlValue(item) {
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
if (downloadUrl && downloadUrl.startsWith('blob:')) {
|
|
821
|
-
this.cleanupBlobUrl(downloadUrl);
|
|
822
|
-
}
|
|
823
|
-
this.handleAsyncFileDeletion(item);
|
|
824
|
-
if (!this.options.isMultipleFile) {
|
|
825
|
-
this.handleSingleFileRemoval();
|
|
826
|
-
}
|
|
827
|
-
else {
|
|
828
|
-
this.handleMultipleFileRemoval(item);
|
|
829
|
-
}
|
|
830
|
-
this.checkAndClearMaxFileCountValidation();
|
|
831
|
-
}
|
|
832
|
-
handleAsyncFileDeletion(item) {
|
|
833
|
-
if (this.options.isUploadFileAsync &&
|
|
834
|
-
item.progress === this.PROGRESS_COMPLETE &&
|
|
835
|
-
item._file['isNew']) {
|
|
836
|
-
const deleteSubscription = this.fileUploadService.deleteFile(item._file['iD_GUID']).subscribe({
|
|
837
|
-
error: (error) => console.error('Delete failed:', error)
|
|
838
|
-
});
|
|
839
|
-
this.subscriptions.add(deleteSubscription);
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
handleSingleFileRemoval() {
|
|
843
|
-
this.uploader.queue = [];
|
|
844
|
-
this.fileUploadModel = null;
|
|
845
|
-
if (this.options.isRequired) {
|
|
846
|
-
this.fileUploadFormControl.markAsTouched();
|
|
847
|
-
// Use the existing utility function to add required validation back
|
|
848
|
-
this.addRequiredValidation();
|
|
849
|
-
}
|
|
850
|
-
// Reset the flag so required validation can work again
|
|
851
|
-
this.hasClearedRequiredError = false;
|
|
852
|
-
this.group.get(this.options.name)?.setValue(this.fileUploadModel, { emitEvent: false });
|
|
853
|
-
this.options.value = this.fileUploadModel;
|
|
854
|
-
// Re-evaluate all validations after file removal
|
|
855
|
-
this.reEvaluateAllValidations();
|
|
856
|
-
}
|
|
857
|
-
handleMultipleFileRemoval(item) {
|
|
858
|
-
// Clean up blob URL
|
|
859
|
-
const downloadUrl = this.getFileDownloadUrl(item);
|
|
860
|
-
if (downloadUrl && downloadUrl.startsWith('blob:')) {
|
|
861
|
-
this.cleanupBlobUrl(downloadUrl);
|
|
494
|
+
if (this.options.isUploadFileAsync && item.progress == 100 && item._file['isNew']) {
|
|
495
|
+
this.fileUploadService.deleteFile(item._file['iD_GUID']).subscribe((res) => { });
|
|
862
496
|
}
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
this.
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
}
|
|
872
|
-
processFileRemovalFromExisting(item) {
|
|
873
|
-
if (!this.options.value) {
|
|
874
|
-
this.resetDeletedFiles();
|
|
875
|
-
return;
|
|
876
|
-
}
|
|
877
|
-
if (!this.options.value.correlationID_GUID) {
|
|
878
|
-
this.resetDeletedFiles();
|
|
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;
|
|
879
505
|
}
|
|
880
506
|
else {
|
|
881
|
-
this.
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
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 = [];
|
|
511
|
+
}
|
|
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
|
+
}
|
|
907
532
|
}
|
|
908
|
-
const objFileName = obj.nameWithExtension || obj.fileName;
|
|
909
|
-
const objFileSize = obj.fileSizeInMB ? obj.fileSizeInMB * this.BYTES_TO_MB : 0;
|
|
910
|
-
return !(objFileName === itemFileName && Math.abs(objFileSize - itemFileSize) < 1000);
|
|
911
|
-
});
|
|
912
|
-
}
|
|
913
|
-
validateRemainingFiles() {
|
|
914
|
-
if ((!this.multipleFileUploadModel.uploadedFiles ||
|
|
915
|
-
this.multipleFileUploadModel.uploadedFiles.length === 0) &&
|
|
916
|
-
this.options.isRequired) {
|
|
917
|
-
this.fileUploadFormControl.setErrors({
|
|
918
|
-
MinFileCountValidationKey: this.options.minNoOfFiles
|
|
919
|
-
});
|
|
920
|
-
this.fileUploadFormControl.markAsTouched();
|
|
921
|
-
this.addRequiredValidation();
|
|
922
|
-
this.hasClearedRequiredError = false;
|
|
923
|
-
}
|
|
924
|
-
// Re-evaluate all validations after file removal
|
|
925
|
-
this.reEvaluateAllValidations();
|
|
926
|
-
}
|
|
927
|
-
reEvaluateAllValidations() {
|
|
928
|
-
// Clear all existing validation errors first
|
|
929
|
-
this.fileUploadFormControl.setErrors(null);
|
|
930
|
-
// Re-apply required validation if needed
|
|
931
|
-
if (this.options.isRequired) {
|
|
932
|
-
this.addRequiredValidation();
|
|
933
|
-
}
|
|
934
|
-
// Re-validate file count constraints
|
|
935
|
-
this.reValidateFileCountConstraints();
|
|
936
|
-
// Re-validate total file size
|
|
937
|
-
this.reValidateTotalFileSize();
|
|
938
|
-
// Re-validate individual files
|
|
939
|
-
this.reValidateIndividualFiles();
|
|
940
|
-
// Clear validation errors that are no longer applicable
|
|
941
|
-
this.clearObsoleteValidationErrors();
|
|
942
|
-
// Update form control validity
|
|
943
|
-
this.fileUploadFormControl.updateValueAndValidity();
|
|
944
|
-
}
|
|
945
|
-
clearObsoleteValidationErrors() {
|
|
946
|
-
const currentFileCount = this.uploader.queue.length;
|
|
947
|
-
// Clear max file count error if current count is within limit
|
|
948
|
-
if (this.options.maxNoOfFiles > 0 && currentFileCount <= this.options.maxNoOfFiles) {
|
|
949
|
-
this.clearFileCountError('MaxFileCountValidationKey');
|
|
950
|
-
}
|
|
951
|
-
// Clear min file count error if current count meets minimum requirement
|
|
952
|
-
if (this.options.minNoOfFiles > 0 && currentFileCount >= this.options.minNoOfFiles) {
|
|
953
|
-
this.clearFileCountError('MinFileCountValidationKey');
|
|
954
|
-
}
|
|
955
|
-
// Clear total size error if current total size is within limit
|
|
956
|
-
if (this.options.maxSizeForAllFilesInMB > 0) {
|
|
957
|
-
const totalSize = this.uploader.queue.reduce((sum, element) => sum + element.file.size, 0);
|
|
958
|
-
const maxSizeBytes = this.options.maxSizeForAllFilesInMB * this.BYTES_TO_MB;
|
|
959
|
-
if (totalSize <= maxSizeBytes) {
|
|
960
|
-
this.clearFileCountError('MaxSizeForAllFilesInMB');
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
reValidateFileCountConstraints() {
|
|
965
|
-
const currentFileCount = this.uploader.queue.length;
|
|
966
|
-
// Check minimum file count
|
|
967
|
-
if (this.options.minNoOfFiles > 0 && currentFileCount < this.options.minNoOfFiles) {
|
|
968
|
-
const minFileMsg = this.utilityService.getResourceValue('MinimumFilesRequired')
|
|
969
|
-
.replace('{count}', this.options.minNoOfFiles.toString());
|
|
970
|
-
this.showFileCountError('MinFileCountValidationKey', minFileMsg);
|
|
971
|
-
}
|
|
972
|
-
// Check maximum file count
|
|
973
|
-
if (this.options.maxNoOfFiles > 0 && currentFileCount > this.options.maxNoOfFiles) {
|
|
974
|
-
const maxFileMsg = this.utilityService.getResourceValue('MaximumFilesExceeded') ||
|
|
975
|
-
`Maximum {maxCount} files allowed. You have selected {currentCount} files.`;
|
|
976
|
-
const finalMsg = maxFileMsg
|
|
977
|
-
.replace('{maxCount}', this.options.maxNoOfFiles.toString())
|
|
978
|
-
.replace('{currentCount}', currentFileCount.toString());
|
|
979
|
-
this.showFileCountError('MaxFileCountValidationKey', finalMsg);
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
reValidateTotalFileSize() {
|
|
983
|
-
if (this.options.maxSizeForAllFilesInMB > 0) {
|
|
984
|
-
const totalSize = this.uploader.queue.reduce((sum, element) => sum + element.file.size, 0);
|
|
985
|
-
const maxSizeBytes = this.options.maxSizeForAllFilesInMB * this.BYTES_TO_MB;
|
|
986
|
-
if (totalSize > maxSizeBytes) {
|
|
987
|
-
this.showTotalSizeError();
|
|
988
533
|
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
// Re-validate each remaining file for size and type
|
|
993
|
-
for (const element of this.uploader.queue) {
|
|
994
|
-
const file = element.file;
|
|
995
|
-
if (!file)
|
|
996
|
-
continue;
|
|
997
|
-
// Check file size
|
|
998
|
-
if (!this.validateIndividualFileSize(file)) {
|
|
999
|
-
this.setFormControlError('FileMaxSizeInMB', `${this.options.fileMaxSizeInMB}MB`);
|
|
534
|
+
else {
|
|
535
|
+
this.deletedFiles = [];
|
|
536
|
+
this.multipleFileUploadModel.removedFiles = [];
|
|
1000
537
|
}
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
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;
|
|
1004
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;
|
|
1005
556
|
}
|
|
1006
557
|
}
|
|
1007
|
-
updateMultipleFileModel() {
|
|
1008
|
-
this.multipleFileUploadModel.correlationID_GUID = this.options.value?.correlationID_GUID;
|
|
1009
|
-
this.fileUploadFormControl.setValue(this.multipleFileUploadModel, { emitEvent: false });
|
|
1010
|
-
this.group.get(this.options.name)?.setValue(this.multipleFileUploadModel, { emitEvent: false });
|
|
1011
|
-
this.options.value = this.multipleFileUploadModel;
|
|
1012
|
-
}
|
|
1013
558
|
convertSizeToMB(size) {
|
|
1014
559
|
if (size === 0) {
|
|
1015
560
|
return 0;
|
|
1016
561
|
}
|
|
1017
|
-
|
|
1018
|
-
const megabytes = size /
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
return item._file ? item._file.name + item._file.size : index;
|
|
1023
|
-
}
|
|
1024
|
-
shouldShowFileList() {
|
|
1025
|
-
return this.uploader?.queue && this.uploader.queue.length > 0;
|
|
1026
|
-
}
|
|
1027
|
-
isDownloadEnabled() {
|
|
1028
|
-
return true;
|
|
1029
|
-
}
|
|
1030
|
-
isRemoveEnabled() {
|
|
1031
|
-
return !this.options.isReadonly && !this.options.isDisabled;
|
|
1032
|
-
}
|
|
1033
|
-
getFileDownloadUrl(item) {
|
|
1034
|
-
const existingUrl = this.getExistingFileUrl(item);
|
|
1035
|
-
if (existingUrl) {
|
|
1036
|
-
return existingUrl;
|
|
1037
|
-
}
|
|
1038
|
-
return this.createFileUrl(item);
|
|
1039
|
-
}
|
|
1040
|
-
getExistingFileUrl(item) {
|
|
1041
|
-
return item?.file?.url ||
|
|
1042
|
-
item?._file?.url ||
|
|
1043
|
-
item?.url ||
|
|
1044
|
-
item?.file?.rawFile?.url ||
|
|
1045
|
-
item?._file?.rawFile?.url ||
|
|
1046
|
-
null;
|
|
1047
|
-
}
|
|
1048
|
-
createFileUrl(item) {
|
|
1049
|
-
const fileName = this.getFileName(item);
|
|
1050
|
-
const fileType = item?.file?.type || item?._file?.type;
|
|
1051
|
-
const originalFile = item?._file?.rawFile || item?.file?.rawFile;
|
|
1052
|
-
if (originalFile && originalFile instanceof File) {
|
|
1053
|
-
return URL.createObjectURL(originalFile);
|
|
1054
|
-
}
|
|
1055
|
-
const base64Data = typeof originalFile === 'string' ? originalFile : null;
|
|
1056
|
-
if (base64Data && fileName) {
|
|
1057
|
-
return this.createBlobUrlWithFilename(base64Data, fileType, fileName);
|
|
1058
|
-
}
|
|
1059
|
-
const fileId = item?._file?.['iD_GUID'];
|
|
1060
|
-
if (fileId && this.options.isUploadFileAsync) {
|
|
1061
|
-
return this.constructDownloadUrl(fileId, fileName);
|
|
1062
|
-
}
|
|
1063
|
-
return null;
|
|
1064
|
-
}
|
|
1065
|
-
createBlobUrlWithFilename(base64Data, fileType, fileName) {
|
|
1066
|
-
try {
|
|
1067
|
-
const byteCharacters = atob(base64Data);
|
|
1068
|
-
const byteNumbers = new Array(byteCharacters.length);
|
|
1069
|
-
for (let i = 0; i < byteCharacters.length; i++) {
|
|
1070
|
-
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
|
1071
|
-
}
|
|
1072
|
-
const byteArray = new Uint8Array(byteNumbers);
|
|
1073
|
-
const blob = new Blob([byteArray], { type: fileType || 'application/octet-stream' });
|
|
1074
|
-
return URL.createObjectURL(blob);
|
|
1075
|
-
}
|
|
1076
|
-
catch (error) {
|
|
1077
|
-
const errorMsg = this.utilityService.getResourceValue('ErrorCreatingBlobUrl');
|
|
1078
|
-
console.error(errorMsg, error);
|
|
1079
|
-
return `data:${fileType || 'application/octet-stream'};base64,${base64Data}`;
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
constructDownloadUrl(fileId, fileName) {
|
|
1083
|
-
const downloadBaseUrl = this.options.downloadBaseUrl;
|
|
1084
|
-
let url;
|
|
1085
|
-
if (downloadBaseUrl) {
|
|
1086
|
-
url = `${downloadBaseUrl}/${fileId}`;
|
|
1087
|
-
}
|
|
1088
|
-
else {
|
|
1089
|
-
url = `/api/files/download/${fileId}`;
|
|
1090
|
-
}
|
|
1091
|
-
if (fileName) {
|
|
1092
|
-
const separator = url.includes('?') ? '&' : '?';
|
|
1093
|
-
url += `${separator}filename=${encodeURIComponent(fileName)}`;
|
|
1094
|
-
}
|
|
1095
|
-
return url;
|
|
1096
|
-
}
|
|
1097
|
-
getFileName(item) {
|
|
1098
|
-
return item?.file?.name || item?._file?.name || 'file';
|
|
1099
|
-
}
|
|
1100
|
-
downloadFile(item) {
|
|
1101
|
-
const downloadInfo = this.prepareFileDownload(item);
|
|
1102
|
-
if (!downloadInfo.url) {
|
|
1103
|
-
this.handleDownloadError(downloadInfo.fileName);
|
|
1104
|
-
return;
|
|
1105
|
-
}
|
|
1106
|
-
this.executeFileDownload(downloadInfo.url, downloadInfo.fileName);
|
|
1107
|
-
}
|
|
1108
|
-
prepareFileDownload(item) {
|
|
1109
|
-
return {
|
|
1110
|
-
url: this.getFileDownloadUrl(item),
|
|
1111
|
-
fileName: this.getFileName(item)
|
|
1112
|
-
};
|
|
1113
|
-
}
|
|
1114
|
-
handleDownloadError(fileName) {
|
|
1115
|
-
const errorMsg = this.utilityService.getResourceValue('NoDownloadUrlAvailable')
|
|
1116
|
-
.replace('{fileName}', fileName);
|
|
1117
|
-
console.error(errorMsg);
|
|
1118
|
-
}
|
|
1119
|
-
executeFileDownload(url, fileName) {
|
|
1120
|
-
const link = this.createDownloadLink(url, fileName);
|
|
1121
|
-
this.triggerDownload(link);
|
|
1122
|
-
this.cleanupBlobUrl(url);
|
|
1123
|
-
}
|
|
1124
|
-
createDownloadLink(url, fileName) {
|
|
1125
|
-
const link = document.createElement('a');
|
|
1126
|
-
link.href = url;
|
|
1127
|
-
link.download = fileName;
|
|
1128
|
-
link.style.display = 'none';
|
|
1129
|
-
return link;
|
|
1130
|
-
}
|
|
1131
|
-
triggerDownload(link) {
|
|
1132
|
-
document.body.appendChild(link);
|
|
1133
|
-
link.click();
|
|
1134
|
-
document.body.removeChild(link);
|
|
1135
|
-
}
|
|
1136
|
-
cleanupBlobUrl(url) {
|
|
1137
|
-
if (url.startsWith('blob:')) {
|
|
1138
|
-
setTimeout(() => {
|
|
1139
|
-
URL.revokeObjectURL(url);
|
|
1140
|
-
}, 100);
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
trackMemoryUsage(fileSize) {
|
|
1144
|
-
this.currentMemoryUsage += fileSize;
|
|
1145
|
-
// If memory usage exceeds limit, clean up old files
|
|
1146
|
-
if (this.currentMemoryUsage > this.MAX_MEMORY_USAGE) {
|
|
1147
|
-
this.cleanupOldFiles();
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1150
|
-
cleanupOldFiles() {
|
|
1151
|
-
if (this.uploader?.queue && this.uploader.queue.length > 0) {
|
|
1152
|
-
// Remove oldest files to free memory
|
|
1153
|
-
const oldestFile = this.uploader.queue.shift();
|
|
1154
|
-
if (oldestFile) {
|
|
1155
|
-
const url = this.getFileDownloadUrl(oldestFile);
|
|
1156
|
-
if (url && url.startsWith('blob:')) {
|
|
1157
|
-
this.cleanupBlobUrl(url);
|
|
1158
|
-
}
|
|
1159
|
-
this.currentMemoryUsage -= (oldestFile.file?.size || 0);
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
}
|
|
1163
|
-
cleanupEventListeners() {
|
|
1164
|
-
// Clear file input references
|
|
1165
|
-
if (this.fileInput?.nativeElement) {
|
|
1166
|
-
this.fileInput.nativeElement.value = '';
|
|
1167
|
-
}
|
|
1168
|
-
// Clear uploader queue to prevent memory leaks
|
|
1169
|
-
if (this.uploader?.queue) {
|
|
1170
|
-
this.uploader.queue = [];
|
|
1171
|
-
}
|
|
1172
|
-
}
|
|
1173
|
-
cleanupUploaderQueue() {
|
|
1174
|
-
if (this.uploader?.queue) {
|
|
1175
|
-
// Clear all items and their associated resources
|
|
1176
|
-
this.uploader.queue.forEach(item => {
|
|
1177
|
-
// Clean up blob URLs
|
|
1178
|
-
const url = this.getFileDownloadUrl(item);
|
|
1179
|
-
if (url && url.startsWith('blob:')) {
|
|
1180
|
-
this.cleanupBlobUrl(url);
|
|
1181
|
-
}
|
|
1182
|
-
// Clear file references
|
|
1183
|
-
if (item._file) {
|
|
1184
|
-
item._file = null;
|
|
1185
|
-
}
|
|
1186
|
-
if (item.file) {
|
|
1187
|
-
item.file = null;
|
|
1188
|
-
}
|
|
1189
|
-
});
|
|
1190
|
-
// Clear the queue
|
|
1191
|
-
this.uploader.queue = [];
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
ngOnDestroy() {
|
|
1195
|
-
// Clean up subscriptions
|
|
1196
|
-
this.subscriptions.unsubscribe();
|
|
1197
|
-
// Clean up uploader queue
|
|
1198
|
-
this.cleanupUploaderQueue();
|
|
1199
|
-
// Clean up event listeners
|
|
1200
|
-
this.cleanupEventListeners();
|
|
1201
|
-
// Clean up blob URLs
|
|
1202
|
-
if (this.uploader?.queue) {
|
|
1203
|
-
this.uploader.queue.forEach(item => {
|
|
1204
|
-
const url = this.getFileDownloadUrl(item);
|
|
1205
|
-
if (url && url.startsWith('blob:')) {
|
|
1206
|
-
URL.revokeObjectURL(url);
|
|
1207
|
-
}
|
|
1208
|
-
});
|
|
1209
|
-
}
|
|
1210
|
-
}
|
|
1211
|
-
checkAndClearMaxFileCountValidation() {
|
|
1212
|
-
if (!this.options.maxNoOfFiles || this.options.maxNoOfFiles <= 0) {
|
|
1213
|
-
return;
|
|
1214
|
-
}
|
|
1215
|
-
const currentQueueLength = this.uploader.queue.length;
|
|
1216
|
-
if (currentQueueLength <= this.options.maxNoOfFiles) {
|
|
1217
|
-
this.clearFileCountError('MaxFileCountValidationKey');
|
|
1218
|
-
}
|
|
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;
|
|
1219
567
|
}
|
|
1220
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 }); }
|
|
1221
|
-
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" }] }); }
|
|
1222
570
|
}
|
|
1223
571
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileUploadComponent, decorators: [{
|
|
1224
572
|
type: Component,
|
|
1225
|
-
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>" }]
|
|
1226
574
|
}], ctorParameters: () => [{ type: i1.ControlContainer, decorators: [{
|
|
1227
575
|
type: Optional
|
|
1228
576
|
}] }, { type: i1.FormGroupDirective }, { type: i2.ControlUtility }, { type: i3.UtilityService }, { type: i3.ControlValidationService }, { type: i4.GlobalSettings }, { type: i5.FileUploadService }], propDecorators: { fileInput: [{
|
|
@@ -1237,4 +585,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
1237
585
|
}], isUploadComplete: [{
|
|
1238
586
|
type: Output
|
|
1239
587
|
}] } });
|
|
1240
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmlsZVVwbG9hZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9iYnNmLWNvbnRyb2xzL3NyYy9saWIvY29udHJvbHMvRmlsZVVwbG9hZC9GaWxlVXBsb2FkLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Jic2YtY29udHJvbHMvc3JjL2xpYi9jb250cm9scy9GaWxlVXBsb2FkL0ZpbGVVcGxvYWQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFJVCxLQUFLLEVBQ0wsUUFBUSxFQUNSLFNBQVMsRUFFVCxNQUFNLEVBQ04sWUFBWSxFQUNiLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFDTCxXQUFXLEVBQ1gsVUFBVSxFQU1YLE1BQU0sZ0JBQWdCLENBQUM7QUFHeEIsT0FBTyxFQUFFLFlBQVksRUFBaUQsTUFBTSxpQkFBaUIsQ0FBQztBQUM5RixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDdEUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sNkNBQTZDLENBQUM7QUFLdEYsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxNQUFNLENBQUM7Ozs7Ozs7OztBQWdEcEMsTUFBTSxPQUFPLG1CQUFtQjthQUNmLDJCQUFzQixHQUE0QixJQUFJLEFBQWhDLENBQWlDO0lBb0N0RSxZQUNzQixnQkFBa0MsRUFDL0MsNkJBQWlELEVBQ2hELGNBQThCLEVBQy9CLGNBQThCLEVBQzdCLHdCQUFrRCxFQUNsRCxjQUE4QixFQUM5QixpQkFBb0M7UUFOeEIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUMvQyxrQ0FBNkIsR0FBN0IsNkJBQTZCLENBQW9CO1FBQ2hELG1CQUFjLEdBQWQsY0FBYyxDQUFn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SCxDQUFDO0lBRU8sbUNBQW1DO1FBQ3pDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksSUFBSSxDQUFDLEVBQUU7WUFDaEUsT0FBTztTQUNSO1FBRUQsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUM7UUFDdEQsSUFBSSxrQkFBa0IsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRTtZQUNuRCxJQUFJLENBQUMsbUJBQW1CLENBQUMsMkJBQTJCLENBQUMsQ0FBQztTQUN2RDtJQUNILENBQUM7K0dBMzlDVSxtQkFBbUI7bUdBQW5CLG1CQUFtQix3UkMvRWhDLDZsWkFrTk07OzRGRG5JTyxtQkFBbUI7a0JBTC9CLFNBQVM7K0JBQ0UsaUJBQWlCLGNBRWYsS0FBSzs7MEJBd0NkLFFBQVE7d09BM0JnQyxTQUFTO3NCQUFuRCxTQUFTO3VCQUFDLFdBQVcsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBR2hDLEtBQUs7c0JBQWIsS0FBSztnQkFDRyxPQUFPO3NCQUFmLEtBQUs7Z0JBQ0ksUUFBUTtzQkFBakIsTUFBTTtnQkFDRyxnQkFBZ0I7c0JBQXpCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIENvbXBvbmVudCxcclxuICBPbkluaXQsXHJcbiAgQWZ0ZXJWaWV3SW5pdCxcclxuICBPbkRlc3Ryb3ksXHJcbiAgSW5wdXQsXHJcbiAgT3B0aW9uYWwsXHJcbiAgVmlld0NoaWxkLFxyXG4gIEVsZW1lbnRSZWYsXHJcbiAgT3V0cHV0LFxyXG4gIEV2ZW50RW1pdHRlclxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge1xyXG4gIEZvcm1Db250cm9sLFxyXG4gIFZhbGlkYXRvcnMsXHJcbiAgRm9ybUdyb3VwLFxyXG4gIEFic3RyYWN0Q29udHJvbCxcclxuICBDb250cm9sQ29udGFpbmVyLFxyXG4gIEZvcm1Hcm91cERpcmVjdGl2ZSxcclxuICBWYWxpZGF0b3JGblxyXG59IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgRmlsZVVwbG9hZE9wdGlvbnMgfSBmcm9tICcuLi8uLi9TaGFyZWQvTW9kZWxzL0ZpbGVVcGxvYWRPcHRpb25zJztcclxuaW1wb3J0IHsgQ29udHJvbFV0aWxpdHkgfSBmcm9tICcuLi8uLi9TaGFyZWQvc2VydmljZXMvQ29udHJvbFV0aWxpdHknO1xyXG5pbXBvcnQgeyBGaWxlVXBsb2FkZXIsIEZpbGVMaWtlT2JqZWN0LCBGaWxlVXBsb2FkZXJPcHRpb25zLCBGaWxlSXRlbSB9IGZyb20gJ25nMi1maWxlLXVwbG9hZCc7XHJcbmltcG9ydCB7IEZpbGVVcGxvYWRNb2RlbCB9IGZyb20gJy4uLy4uL1NoYXJlZC9Nb2RlbHMvRmlsZVVwbG9hZE1vZGVsJztcclxuaW1wb3J0IHsgTXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwgfSBmcm9tICcuLi8uLi9TaGFyZWQvTW9kZWxzL011bHRpcGxlRmlsZVVwbG9hZE1vZGVsJztcclxuaW1wb3J0IHsgQ29udHJvbFZhbGlkYXRpb25TZXJ2aWNlLCBVdGlsaXR5U2VydmljZSB9IGZyb20gJ0BibnNpZ2h0cy9iYnNmLXV0aWxpdGllcyc7XHJcbmltcG9ydCB7IEdsb2JhbFNldHRpbmdzIH0gZnJvbSAnLi4vLi4vU2hhcmVkL3NlcnZpY2VzL0dsb2JhbFNldHRpbmdzLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBGaWxlRFRPIH0gZnJvbSAnLi4vLi4vU2hhcmVkL01vZGVscy9GaWxlRFRPJztcclxuaW1wb3J0IHsgRmlsZVVwbG9hZFNlcnZpY2UgfSBmcm9tICcuLi8uLi9TaGFyZWQvc2VydmljZXMvZmlsZS11cGxvYWQuc2VydmljZSc7XHJcbmltcG9ydCB7IEh0dHBFdmVudFR5cGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XHJcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xyXG5pbnRlcmZhY2UgRmlsZUl0ZW1FeHRlbmRlZCBleHRlbmRzIEZpbGVJdGVtIHtcclxuICBfZmlsZTogRmlsZUV4dGVuZGVkO1xyXG59XHJcblxyXG5pbnRlcmZhY2UgRmlsZUV4dGVuZGVkIGV4dGVuZHMgRmlsZSB7XHJcbiAgaURfR1VJRD86IHN0cmluZztcclxuICBpc05ldz86IGJvb2xlYW47XHJcbiAgdXJsPzogc3RyaW5nO1xyXG4gIHJhd0ZpbGU/OiBGaWxlO1xyXG59XHJcblxyXG5pbnRlcmZhY2UgRmlsZVZhbGlkYXRpb25SZXN1bHQge1xyXG4gIGlzVmFsaWQ6IGJvb2xlYW47XHJcbiAgZXJyb3JzOiBzdHJpbmdbXTtcclxuICBpbnZhbGlkRmlsZXM6IEZpbGVJdGVtW107XHJcbn1cclxuXHJcbmludGVyZmFjZSBGaWxlUHJvY2Vzc2luZ1Jlc3VsdCB7XHJcbiAgdmFsaWRGaWxlczogRmlsZUl0ZW1bXTtcclxuICBpbnZhbGlkRmlsZXM6IEZpbGVJdGVtW107XHJcbiAgZXJyb3JzOiBzdHJpbmdbXTtcclxufVxyXG5cclxuaW50ZXJmYWNlIERvd25sb2FkSW5mbyB7XHJcbiAgdXJsOiBzdHJpbmcgfCBudWxsO1xyXG4gIGZpbGVOYW1lOiBzdHJpbmc7XHJcbn1cclxuXHJcbmludGVyZmFjZSBVcGxvYWRQcm9ncmVzc0V2ZW50IHtcclxuICBsb2FkZWQ6IG51bWJlcjtcclxuICB0b3RhbDogbnVtYmVyO1xyXG4gIHR5cGU6IG51bWJlcjtcclxufVxyXG5cclxuaW50ZXJmYWNlIFVwbG9hZENvbXBsZXRlRXZlbnQge1xyXG4gIGJvZHk6IHtcclxuICAgIHZhbDogc3RyaW5nO1xyXG4gICAgZG93bmxvYWRVcmw/OiBzdHJpbmc7XHJcbiAgfTtcclxuICB0eXBlOiBudW1iZXI7XHJcbn1cclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnQkJTRi1GaWxlVXBsb2FkJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vRmlsZVVwbG9hZC5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3RhbmRhbG9uZTogZmFsc2VcclxufSlcclxuZXhwb3J0IGNsYXNzIEZpbGVVcGxvYWRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XHJcbiAgcHJpdmF0ZSBzdGF0aWMgY29udHJvbENvbnRhaW5lclN0YXRpYzogQ29udHJvbENvbnRhaW5lciB8IG51bGwgPSBudWxsO1xyXG5cclxuICBwcml2YXRlIHJlYWRvbmx5IEJZVEVTX1RPX01CID0gMTAyNCAqIDEwMjQ7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBQUk9HUkVTU19DT01QTEVURSA9IDEwMDtcclxuICBwcml2YXRlIHJlYWRvbmx5IFBST0dSRVNTX05FQVJfQ09NUExFVEUgPSA5NTtcclxuICBwcml2YXRlIHJlYWRvbmx5IEVSUk9SX0RJU1BMQVlfRFVSQVRJT04gPSA1MDAwO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgTUFYX01FTU9SWV9VU0FHRSA9IDEwMCAqIDEwMjQgKiAxMDI0OyAvLyAxMDBNQiBsaW1pdFxyXG4gIHByaXZhdGUgY3VycmVudE1lbW9yeVVzYWdlID0gMDtcclxuICBwcml2YXRlIGhhc0NsZWFyZWRSZXF1aXJlZEVycm9yID0gZmFsc2U7IC8vIFRyYWNrIGlmIHJlcXVpcmVkIGVycm9yIHdhcyBhbHJlYWR5IGNsZWFyZWRcclxuXHJcbiAgQFZpZXdDaGlsZCgnZmlsZUlucHV0JywgeyBzdGF0aWM6IGZhbHNlIH0pIGZpbGVJbnB1dCE6IEVsZW1lbnRSZWY8SFRNTElucHV0RWxlbWVudD47XHJcblxyXG4gIGlzU3VibWl0dGVkID0gZmFsc2U7XHJcbiAgQElucHV0KCkgZ3JvdXAhOiBGb3JtR3JvdXA7XHJcbiAgQElucHV0KCkgb3B0aW9ucyE6IEZpbGVVcGxvYWRPcHRpb25zO1xyXG4gIEBPdXRwdXQoKSBPbkNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xyXG4gIEBPdXRwdXQoKSBpc1VwbG9hZENvbXBsZXRlID0gbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPigpO1xyXG5cclxuICBmaWxlVXBsb2FkRm9ybUNvbnRyb2whOiBBYnN0cmFjdENvbnRyb2w7XHJcbiAgdmFsaWRhdGlvbk1lc3NhZ2UgPSAnJztcclxuICB2YWxpZGF0aW9uQ291bnRNZXNzYWdlID0gJyc7XHJcbiAgdXBsb2FkZXIhOiBGaWxlVXBsb2FkZXI7XHJcbiAgaGFzQW5vdGhlckRyb3Bab25lT3ZlciA9IGZhbHNlO1xyXG4gIGFjY2VwdGVkVHlwZSA9ICcnO1xyXG4gIGFjY2VwdGVkVHlwZUFycmF5OiBzdHJpbmdbXSA9IFtdO1xyXG4gIHRvb2xUaXBUeXBlQXJyYXk6IHN0cmluZ1tdID0gW107XHJcbiAgZmlsZUxpa2VPYmplY3QhOiBGaWxlTGlrZU9iamVjdDtcclxuICBtYXJrQWxsQXNUb3VjaGVkID0gZmFsc2U7XHJcbiAgdmFsaWRhdGlvblJ1bGVzOiBWYWxpZGF0b3JGbltdID0gW107XHJcbiAgdmFsaWRhdGlvblJ1bGVzQXN5bmM6IFZhbGlkYXRvckZuW10gPSBbXTtcclxuICBmaWxlVXBsb2FkTW9kZWwhOiBGaWxlVXBsb2FkTW9kZWw7XHJcbiAgbXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwhOiBNdWx0aXBsZUZpbGVVcGxvYWRNb2RlbDtcclxuICBmaWxlOiBGaWxlRFRPIHwgbnVsbCA9IG51bGw7XHJcbiAgZGVsZXRlZEZpbGVzOiBGaWxlRFRPW10gPSBbXTtcclxuICBwcml2YXRlIHN1YnNjcmlwdGlvbnMgPSBuZXcgU3Vic2NyaXB0aW9uKCk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgQE9wdGlvbmFsKCkgcHJpdmF0ZSBjb250cm9sQ29udGFpbmVyOiBDb250cm9sQ29udGFpbmVyLFxyXG4gICAgcHVibGljIG11bHRpcGxlRmlsZVVwbG9hZENvbnRyb2xIb3N0OiBGb3JtR3JvdXBEaXJlY3RpdmUsXHJcbiAgICBwcml2YXRlIGNvbnRyb2xVdGlsaXR5OiBDb250cm9sVXRpbGl0eSxcclxuICAgIHB1YmxpYyB1dGlsaXR5U2VydmljZTogVXRpbGl0eVNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGNvbnRyb2xWYWxpZGF0aW9uU2VydmljZTogQ29udHJvbFZhbGlkYXRpb25TZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBnbG9iYWxTZXR0aW5nczogR2xvYmFsU2V0dGluZ3MsXHJcbiAgICBwcml2YXRlIGZpbGVVcGxvYWRTZXJ2aWNlOiBGaWxlVXBsb2FkU2VydmljZVxyXG4gICkge1xyXG4gICAgRmlsZVVwbG9hZENvbXBvbmVudC5jb250cm9sQ29udGFpbmVyU3RhdGljID0gdGhpcy5jb250cm9sQ29udGFpbmVyO1xyXG4gICAgdGhpcy5pbml0aWFsaXplVXBsb2FkZXIoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgaW5pdGlhbGl6ZVVwbG9hZGVyKCk6IHZvaWQge1xyXG4gICAgdGhpcy51cGxvYWRlciA9IG5ldyBGaWxlVXBsb2FkZXIoe1xyXG4gICAgICBkaXNhYmxlTXVsdGlwYXJ0OiBmYWxzZVxyXG4gICAgfSBhcyBGaWxlVXBsb2FkZXJPcHRpb25zKTtcclxuICB9XHJcblxyXG4gIG5nT25Jbml0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5pbml0aWFsaXplTW9kZWxzKCk7XHJcbiAgICB0aGlzLnNldFZpZXdUeXBlKCk7XHJcbiAgICB0aGlzLnByb2Nlc3NJbml0aWFsVmFsdWUoKTtcclxuICAgIHRoaXMuc2V0dXBMYWJlbHMoKTtcclxuICAgIHRoaXMuc2V0dXBGaWxlVHlwZVZhbGlkYXRpb24oKTtcclxuICAgIHRoaXMuc2V0dXBGb3JtQ29udHJvbCgpO1xyXG4gICAgdGhpcy5zZXR1cFN1YnNjcmlwdGlvbnMoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgaW5pdGlhbGl6ZU1vZGVscygpOiB2b2lkIHtcclxuICAgIHRoaXMuZmlsZVVwbG9hZE1vZGVsID0gbmV3IEZpbGVVcGxvYWRNb2RlbCgpO1xyXG4gICAgdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbCA9IG5ldyBNdWx0aXBsZUZpbGVVcGxvYWRNb2RlbCgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzZXRWaWV3VHlwZSgpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5vcHRpb25zLnZpZXdUeXBlKSB7XHJcbiAgICAgIHRoaXMub3B0aW9ucy52aWV3VHlwZSA9IHRoaXMuZ2xvYmFsU2V0dGluZ3Mudmlld1R5cGU7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHByb2Nlc3NJbml0aWFsVmFsdWUoKTogdm9pZCB7XHJcblxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy52YWx1ZSA9PSBudWxsKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5vcHRpb25zLmlzTXVsdGlwbGVGaWxlKSB7XHJcbiAgICAgIHRoaXMucHJvY2Vzc011bHRpcGxlRmlsZVZhbHVlKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnByb2Nlc3NTaW5nbGVGaWxlVmFsdWUoKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnVwbG9hZGVyLnF1ZXVlLmZvckVhY2goKGVsZW1lbnQpID0+IHtcclxuICAgICAgZWxlbWVudC5wcm9ncmVzcyA9IHRoaXMuUFJPR1JFU1NfQ09NUExFVEU7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcHJvY2Vzc011bHRpcGxlRmlsZVZhbHVlKCk6IHZvaWQge1xyXG4gICAgY29uc3QgZmlsZXM6IEZpbGVMaWtlT2JqZWN0W10gPSBbXTtcclxuICAgIHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwuZXhpc3RpbmdGaWxlcyA9IHRoaXMub3B0aW9ucy52YWx1ZS5leGlzdGluZ0ZpbGVzO1xyXG4gICAgdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbC51cGxvYWRlZEZpbGVzID0gW107XHJcblxyXG4gICAgZm9yIChjb25zdCBlbGVtZW50IG9mIHRoaXMub3B0aW9ucy52YWx1ZS5leGlzdGluZ0ZpbGVzKSB7XHJcbiAgICAgIGNvbnN0IGZpbGVMaWtlT2JqZWN0ID0gdGhpcy5jcmVhdGVGaWxlTGlrZU9iamVjdChlbGVtZW50KTtcclxuICAgICAgZmlsZXMucHVzaChmaWxlTGlrZU9iamVjdCk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy51cGxvYWRlci5hZGRUb1F1ZXVlKGZpbGVzIGFzIGFueSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHByb2Nlc3NTaW5nbGVGaWxlVmFsdWUoKTogdm9pZCB7XHJcbiAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5vcHRpb25zLnZhbHVlLmZpbGUgPz8gdGhpcy5vcHRpb25zLnZhbHVlO1xyXG4gICAgY29uc3QgZmlsZUxpa2VPYmplY3QgPSB0aGlzLmNyZWF0ZUZpbGVMaWtlT2JqZWN0KGVsZW1lbnQpO1xyXG4gICAgdGhpcy5maWxlID0gZWxlbWVudDtcclxuICAgIHRoaXMudXBsb2FkZXIuYWRkVG9RdWV1ZShbZmlsZUxpa2VPYmplY3RdIGFzIGFueSk7XHJcblxyXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMudmFsdWUuZmlsZSkge1xyXG4gICAgICB0aGlzLmZpbGVVcGxvYWRNb2RlbCA9IG5ldyBGaWxlVXBsb2FkTW9kZWwoKTtcclxuICAgICAgdGhpcy5maWxlVXBsb2FkTW9kZWwuZmlsZSA9IHRoaXMub3B0aW9ucy52YWx1ZTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuZmlsZVVwbG9hZE1vZGVsID0gdGhpcy5vcHRpb25zLnZhbHVlO1xyXG4gICAgfVxyXG4gICAgdGhpcy5vcHRpb25zLnZhbHVlID0gdGhpcy5maWxlVXBsb2FkTW9kZWw7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNyZWF0ZUZpbGVMaWtlT2JqZWN0KGVsZW1lbnQ6IEZpbGVEVE8pOiBhbnkge1xyXG4gICAgY29uc3QgYnl0ZXMgPSBuZXcgVWludDhBcnJheShlbGVtZW50LmJ5dGVzKTtcclxuICAgIGNvbnN0IGJhc2U2NCA9IGJ0b2EoU3RyaW5nLmZyb21DaGFyQ29kZSguLi5ieXRlcykpO1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgbmFtZTogZWxlbWVudC5uYW1lV2l0aEV4dGVuc2lvbiB8fCBlbGVtZW50LmZpbGVOYW1lLFxyXG4gICAgICB0eXBlOiBlbGVtZW50Lm1pbWVUeXBlIHx8IGVsZW1lbnQuZmlsZVR5cGUsXHJcbiAgICAgIHJhd0ZpbGU6IGJhc2U2NCxcclxuICAgICAgc2l6ZTogZWxlbWVudC5maWxlU2l6ZUluTUIgPyBlbGVtZW50LmZpbGVTaXplSW5NQiAqIHRoaXMuQllURVNfVE9fTUIgOiAwLFxyXG4gICAgICBsYXN0TW9kaWZpZWREYXRlOiBuZXcgRGF0ZSgpLFxyXG4gICAgICB1cmw6IGVsZW1lbnQuZnVsbEZpbGVVUkxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldHVwTGFiZWxzKCk6IHZvaWQge1xyXG5cclxuICAgIGlmICh0aGlzLm9wdGlvbnMubGFiZWxLZXkpIHtcclxuICAgICAgdGhpcy5vcHRpb25zLmxhYmVsVmFsdWUgPSB0aGlzLnV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUodGhpcy5vcHRpb25zLmxhYmVsS2V5KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2V0dXBGaWxlVHlwZVZhbGlkYXRpb24oKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5maWxlVXBsb2FkQWNjZXB0c1R5cGVzPy5sZW5ndGgpIHtcclxuICAgICAgY29uc29sZS53YXJuKCdGaWxlVXBsb2FkOiBObyBmaWxlIHR5cGVzIHNwZWNpZmllZCBpbiBmaWxlVXBsb2FkQWNjZXB0c1R5cGVzJyk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0cnkge1xyXG4gICAgICB0aGlzLnByb2Nlc3NBY2NlcHRlZFR5cGVzKCk7XHJcbiAgICAgIHRoaXMuYnVpbGRWYWxpZGF0aW9uTWVzc2FnZSgpO1xyXG5cclxuICAgICAgLy8gTG9nIHRoZSBwcm9jZXNzZWQgdHlwZXMgZm9yIGRlYnVnZ2luZ1xyXG4gICAgICBjb25zb2xlLmxvZygnRmlsZVVwbG9hZDogUHJvY2Vzc2VkIGZpbGUgdHlwZXM6Jywge1xyXG4gICAgICAgIG9yaWdpbmFsOiB0aGlzLm9wdGlvbnMuZmlsZVVwbG9hZEFjY2VwdHNUeXBlcyxcclxuICAgICAgICBwcm9jZXNzZWQ6IHRoaXMuYWNjZXB0ZWRUeXBlQXJyYXksXHJcbiAgICAgICAgYWNjZXB0QXR0cmlidXRlOiB0aGlzLmFjY2VwdGVkVHlwZSxcclxuICAgICAgICBkaXNwbGF5VHlwZXM6IHRoaXMudG9vbFRpcFR5cGVBcnJheVxyXG4gICAgICB9KTtcclxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZpbGVVcGxvYWQ6IEVycm9yIHByb2Nlc3NpbmcgZmlsZSB0eXBlczonLCBlcnJvcik7XHJcbiAgICAgIC8vIEZhbGxiYWNrIHRvIGFjY2VwdGluZyBhbGwgZmlsZXMgaWYgcHJvY2Vzc2luZyBmYWlsc1xyXG4gICAgICB0aGlzLmFjY2VwdGVkVHlwZSA9ICcnO1xyXG4gICAgICB0aGlzLmFjY2VwdGVkVHlwZUFycmF5ID0gW107XHJcbiAgICAgIHRoaXMudG9vbFRpcFR5cGVBcnJheSA9IFtdO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBwcm9jZXNzQWNjZXB0ZWRUeXBlcygpOiB2b2lkIHtcclxuICAgIC8vIFByb2Nlc3MgZWFjaCBmaWxlIHR5cGUgYW5kIGV4dHJhY3QgaW5kaXZpZHVhbCBNSU1FIHR5cGVzXHJcbiAgICBjb25zdCBhbGxNaW1lVHlwZXM6IHN0cmluZ1tdID0gW107XHJcblxyXG4gICAgZm9yIChjb25zdCBmaWxlVHlwZSBvZiB0aGlzLm9wdGlvbnMuZmlsZVVwbG9hZEFjY2VwdHNUeXBlcykge1xyXG4gICAgICBpZiAoZmlsZVR5cGUuaW5jbHVkZXMoJywnKSkge1xyXG4gICAgICAgIC8vIEhhbmRsZSB0eXBlcyBsaWtlIEltYWdlVHlwZXMgdGhhdCBjb250YWluIG11bHRpcGxlIE1JTUUgdHlwZXNcclxuICAgICAgICBjb25zdCBtaW1lVHlwZXMgPSBmaWxlVHlwZS5zcGxpdCgnLCcpLm1hcCh0eXBlID0+IHR5cGUudHJpbSgpKTtcclxuICAgICAgICBhbGxNaW1lVHlwZXMucHVzaCguLi5taW1lVHlwZXMpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIFNpbmdsZSBNSU1FIHR5cGVcclxuICAgICAgICBhbGxNaW1lVHlwZXMucHVzaChmaWxlVHlwZSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBGaWx0ZXIgb3V0IGVtcHR5IHN0cmluZ3MgYW5kIG5vcm1hbGl6ZSBNSU1FIHR5cGVzXHJcbiAgICBjb25zdCBub3JtYWxpemVkTWltZVR5cGVzID0gYWxsTWltZVR5cGVzXHJcbiAgICAgIC5maWx0ZXIodHlwZSA9PiB0eXBlLnRyaW0oKSlcclxuICAgICAgLm1hcCh0eXBlID0+IHR5cGUudHJpbSgpLnRvTG93ZXJDYXNlKCkpO1xyXG5cclxuICAgIC8vIENyZWF0ZSB0aGUgYWNjZXB0IGF0dHJpYnV0ZSBzdHJpbmcgZm9yIEhUTUwgaW5wdXRcclxuICAgIHRoaXMuYWNjZXB0ZWRUeXBlID0gbm9ybWFsaXplZE1pbWVUeXBlcy5qb2luKCcsJyk7XHJcblxyXG4gICAgLy8gU3RvcmUgdGhlIHByb2Nlc3NlZCBhcnJheSBmb3IgdmFsaWRhdGlvbiAoa2VlcCBvcmlnaW5hbCBjYXNlIGZvciBkaXNwbGF5KVxyXG4gICAgdGhpcy5hY2NlcHRlZFR5cGVBcnJheSA9IGFsbE1pbWVUeXBlcy5maWx0ZXIodHlwZSA9PiB0eXBlLnRyaW0oKSk7XHJcblxyXG4gICAgY29uc3QgbWltZVR5cGVNYXAgPSB0aGlzLmdldE1pbWVUeXBlTWFwKCk7XHJcblxyXG4gICAgZm9yIChjb25zdCB0eXBlIG9mIHRoaXMuYWNjZXB0ZWRUeXBlQXJyYXkpIHtcclxuICAgICAgY29uc3QgZGlzcGxheVR5cGUgPSBtaW1lVHlwZU1hcFt0eXBlXTtcclxuICAgICAgaWYgKGRpc3BsYXlUeXBlICYmICF0aGlzLnRvb2xUaXBUeXBlQXJyYXkuaW5jbHVkZXMoZGlzcGxheVR5cGUpKSB7XHJcbiAgICAgICAgdGhpcy50b29sVGlwVHlwZUFycmF5LnB1c2goZGlzcGxheVR5cGUpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldE1pbWVUeXBlTWFwKCk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgJ2FwcGxpY2F0aW9uL3BkZic6ICdQREYnLFxyXG4gICAgICAnYXBwbGljYXRpb24vbXN3b3JkJzogJ1dvcmQnLFxyXG4gICAgICAnYXBwbGljYXRpb24vdm5kLm9wZW54bWxmb3JtYXRzLW9mZmljZWRvY3VtZW50LndvcmRwcm9jZXNzaW5nbWwuZG9jdW1lbnQnOiAnV29yZCcsXHJcbiAgICAgICdhcHBsaWNhdGlvbi92bmQubXMtZXhjZWwnOiAnRXhjZWwnLFxyXG4gICAgICAnYXBwbGljYXRpb24vdm5kLm9wZW54bWxmb3JtYXRzLW9mZmljZWRvY3VtZW50LnNwcmVhZHNoZWV0bWwuc2hlZXQnOiAnRXhjZWwnLFxyXG4gICAgICAnYXBwbGljYXRpb24vdm5kLm1zLXBvd2VycG9pbnQnOiAnUG93ZXJQb2ludCcsXHJcbiAgICAgICdhcHBsaWNhdGlvbi92bmQub3BlbnhtbGZvcm1hdHMtb2ZmaWNlZG9jdW1lbnQucHJlc2VudGF0aW9ubWwucHJlc2VudGF0aW9uJzogJ1Bvd2VyUG9pbnQnLFxyXG4gICAgICAnaW1hZ2UvcG5nJzogJ1BORycsXHJcbiAgICAgICdpbWFnZS9ibXAnOiAnQk1QJyxcclxuICAgICAgJ2ltYWdlL2pwZWcnOiAnSlBFRycsXHJcbiAgICAgICdpbWFnZS9zdmcreG1sJzogJ1NWRycsXHJcbiAgICAgICdhcHBsaWNhdGlvbi96aXAnOiAnWklQJyxcclxuICAgICAgJ2FwcGxpY2F0aW9uL3gtcmFyLWNvbXByZXNzZWQnOiAnUkFSJyxcclxuICAgICAgJ3ZpZGVvL3dlYm0nOiAnV2ViTScsXHJcbiAgICAgICd2aWRlby9vZ2cnOiAnT0dHJyxcclxuICAgICAgJ3ZpZGVvL21wNCc6ICdNUDQnLFxyXG4gICAgICAndmlkZW8vcXVpY2t0aW1lJzogJ01PVicsXHJcbiAgICAgICd2aWRlby94LW1zdmlkZW8nOiAnQVZJJyxcclxuICAgICAgJ3ZpZGVvL3gtbXMtd212JzogJ1dNVicsXHJcbiAgICAgICd2aWRlby9hdmknOiAnQVZJJyxcclxuICAgICAgJ3ZpZGVvL21wZWcnOiAnTVBFRycsXHJcbiAgICAgICd2aWRlby94LWZsdic6ICdGTFYnLFxyXG4gICAgICAnYXVkaW8vbXBlZyc6ICdNUDMnLFxyXG4gICAgICAndGV4dC9wbGFpbic6ICdUeHQnLFxyXG4gICAgICAndGV4dC94bWwnOiAnWE1MJyxcclxuICAgICAgJ2FwcGxpY2F0aW9uL2pzb24nOiAnSlNPTicsXHJcbiAgICAgICdhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0nOiAnQmluYXJ5JyxcclxuICAgICAgJ2FwcGxpY2F0aW9uL0JOJzogJ0xpY2Vuc2UnXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBidWlsZFZhbGlkYXRpb25NZXNzYWdlKCk6IHZvaWQge1xyXG4gICAgY29uc3QgbWVzc2FnZXM6IHN0cmluZ1tdID0gW107XHJcblxyXG4gICAgaWYgKHRoaXMudG9vbFRpcFR5cGVBcnJheS5sZW5ndGgpIHtcclxuICAgICAgbWVzc2FnZXMucHVzaChgJHt0aGlzLnV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ0V4dGVuc2lvbnMnKX0gKCR7dGhpcy50b29sVGlwVHlwZUFycmF5LmpvaW4oJywgJyl9KWApO1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5maWxlTWF4U2l6ZUluTUIgPiAwKSB7XHJcbiAgICAgIG1lc3NhZ2VzLnB1c2goYCR7dGhpcy51dGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdGaWxlTWF4U2l6ZUluTUInKX0ke3RoaXMub3B0aW9ucy5maWxlTWF4U2l6ZUluTUJ9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5taW5Ob09mRmlsZXMgPiAwKSB7XHJcbiAgICAgIG1lc3NhZ2VzLnB1c2goYCR7dGhpcy51dGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdNaW5GaWxlQ291bnRWYWxpZGF0aW9uS2V5Jyl9JHt0aGlzLm9wdGlvbnMubWluTm9PZkZpbGVzfWApO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLm9wdGlvbnMubWF4Tm9PZkZpbGVzID4gMCkge1xyXG4gICAgICBtZXNzYWdlcy5wdXNoKGAke3RoaXMudXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSgnTWF4RmlsZUNvdW50VmFsaWRhdGlvbktleScpfSR7dGhpcy5vcHRpb25zLm1heE5vT2ZGaWxlc31gKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnZhbGlkYXRpb25NZXNzYWdlID0gbWVzc2FnZXMuam9pbignIDxici8+ICcpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzZXR1cEZvcm1Db250cm9sKCk6IHZvaWQge1xyXG4gICAgdGhpcy5ncm91cC5hZGRDb250cm9sKHRoaXMub3B0aW9ucy5uYW1lLCBuZXcgRm9ybUNvbnRyb2woJycpKTtcclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sID0gdGhpcy5ncm91cC5jb250cm9sc1t0aGlzLm9wdGlvbnMubmFtZV07XHJcblxyXG4gICAgdGhpcy5zZXR1cFZhbGlkYXRvcnMoKTtcclxuICAgIHRoaXMuc2V0dXBDb3VudE1lc3NhZ2UoKTtcclxuICAgIHRoaXMuYXBwbHlWYWxpZGF0b3JzQW5kU3RhdGUoKTtcclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnNldFZhbHVlKHRoaXMub3B0aW9ucy52YWx1ZSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzZXR1cFZhbGlkYXRvcnMoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5vcHRpb25zLmN1c3RvbVZhbGlkYXRpb24/Lmxlbmd0aCkge1xyXG4gICAgICBmb3IgKGNvbnN0IHZhbGlkYXRpb24gb2YgdGhpcy5vcHRpb25zLmN1c3RvbVZhbGlkYXRpb24pIHtcclxuICAgICAgICB0aGlzLnZhbGlkYXRpb25SdWxlcy5wdXNoKHZhbGlkYXRpb24uZnVuY3Rpb25Cb2R5KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLm9wdGlvbnMuaXNSZXF1aXJlZCkge1xyXG4gICAgICB0aGlzLnZhbGlkYXRpb25SdWxlcy5wdXNoKFZhbGlkYXRvcnMucmVxdWlyZWQpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzZXR1cENvdW50TWVzc2FnZSgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLm9wdGlvbnMuaXNNdWx0aXBsZUZpbGUgJiYgdGhpcy5vcHRpb25zLm1heE5vT2ZGaWxlcyA+IDApIHtcclxuICAgICAgdGhpcy52YWxpZGF0aW9uQ291bnRNZXNzYWdlID0gYCR7dGhpcy51dGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdNYXhGaWxlc0NvdW50Jyl9IDogJHt0aGlzLm9wdGlvbnMubWF4Tm9PZkZpbGVzfWA7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGFwcGx5VmFsaWRhdG9yc0FuZFN0YXRlKCk6IHZvaWQge1xyXG4gICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuc2V0VmFsaWRhdG9ycyh0aGlzLnZhbGlkYXRpb25SdWxlcyk7XHJcbiAgICBpZiAodGhpcy52YWxpZGF0aW9uUnVsZXNBc3luYy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnNldEFzeW5jVmFsaWRhdG9ycyh0aGlzLnZhbGlkYXRpb25SdWxlc0FzeW5jIGFzIGFueSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5pc0Rpc2FibGVkKSB7XHJcbiAgICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLmRpc2FibGUoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2V0dXBTdWJzY3JpcHRpb25zKCk6IHZvaWQge1xyXG4gICAgdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRDb250cm9sSG9zdC5uZ1N1Ym1pdC5zdWJzY3JpYmUoKCkgPT4ge1xyXG4gICAgICB0aGlzLmdyb3VwLm1hcmtBbGxBc1RvdWNoZWQoKTtcclxuICAgICAgdGhpcy5tYXJrQWxsQXNUb3VjaGVkID0gdHJ1ZTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5hcHBseUF0dHJpYnV0ZXMoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXBwbHlBdHRyaWJ1dGVzKCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuYXR0cmlidXRlTGlzdD8ubGVuZ3RoKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5vcHRpb25zLm5hbWUpO1xyXG4gICAgaWYgKGVsZW1lbnQpIHtcclxuICAgICAgZm9yIChjb25zdCBhdHRyaWJ1dGUgb2YgdGhpcy5vcHRpb25zLmF0dHJpYnV0ZUxpc3QpIHtcclxuICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZShhdHRyaWJ1dGUua2V5LCBhdHRyaWJ1dGUudmFsdWUpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXNldEVycm9yID0gKCk6IHZvaWQgPT4ge1xyXG4gICAgdGhpcy5jb250cm9sVmFsaWRhdGlvblNlcnZpY2UucmVtb3ZlR2xvYmFsRXJyb3IoKTtcclxuICB9O1xyXG5cclxuICBzaG93R2xvYmFsRXJyb3IoKTogdm9pZCB7XHJcbiAgICB0aGlzLmNvbnRyb2xVdGlsaXR5LnNob3dHbG9iYWxFcnJvcigpO1xyXG4gIH1cclxuXHJcbiAgZ2V0RXJyb3JWYWxpZGF0aW9uKGVycm9yTGlzdDogYW55KTogc3RyaW5nIHtcclxuICAgIGlmICh0aGlzLm1hcmtBbGxBc1RvdWNoZWQgJiYgdGhpcy5ncm91cC5pbnZhbGlkKSB7XHJcbiAgICAgIHRoaXMuc2hvd0dsb2JhbEVycm9yKCk7XHJcbiAgICAgIHRoaXMubWFya0FsbEFzVG91Y2hlZCA9IGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChlcnJvckxpc3QgJiYgZXJyb3JMaXN0Lmxlbmd0aCA+IDApIHtcclxuICAgICAgZm9yIChjb25zdCBlcnJvciBvZiBlcnJvckxpc3QpIHtcclxuICAgICAgICBpZiAoZXJyb3Iua2V5ID09PSAnSW52YWxpZEZpbGVzJykge1xyXG4gICAgICAgICAgcmV0dXJuIGVycm9yLnZhbHVlO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0aGlzLmNvbnRyb2xVdGlsaXR5LmdldEVycm9yVmFsaWRhdGlvbk1hc3NhZ2UoZXJyb3JMaXN0LCB0aGlzLmdyb3VwLCB0aGlzLm9wdGlvbnMpO1xyXG4gIH1cclxuXHJcbiAgZmlsZU92ZXJBbm90aGVyKGV2ZW50OiBhbnkpOiB2b2lkIHtcclxuICAgIHRoaXMuaGFzQW5vdGhlckRyb3Bab25lT3ZlciA9ICEhZXZlbnQ7XHJcbiAgfVxyXG5cclxuICBpc0hpZGVJbnB1dCgpOiBib29sZWFuIHtcclxuICAgIGlmICh0aGlzLm9wdGlvbnMuaXNNdWx0aXBsZUZpbGUpIHtcclxuICAgICAgcmV0dXJuIHRoaXMub3B0aW9ucy5tYXhOb09mRmlsZXMgPiAwICYmXHJcbiAgICAgICAgdGhpcy5vcHRpb25zLm1heE5vT2ZGaWxlcyA9PT0gdGhpcy51cGxvYWRlci5xdWV1ZS5sZW5ndGg7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdGhpcy51cGxvYWRlci5xdWV1ZS5sZW5ndGggPiAwO1xyXG4gIH1cclxuICBvbkZpbGVDaGFuZ2UoKTogdm9pZCB7XHJcbiAgICB0aGlzLnZhbGlkYXRlRmlsZUNvbnN0cmFpbnRzKCk7XHJcblxyXG4gICAgY29uc3QgZmlsZVByb2Nlc3NpbmdSZXN1bHQgPSB0aGlzLnByb2Nlc3NOZXdseUFkZGVkRmlsZXMoKTtcclxuXHJcbiAgICB0aGlzLmhhbmRsZUZpbGVWYWxpZGF0aW9uUmVzdWx0cyhmaWxlUHJvY2Vzc2luZ1Jlc3VsdCk7XHJcblxyXG4gICAgdGhpcy5wcm9jZXNzVmFsaWRGaWxlc0ZvclVwbG9hZCgpO1xyXG5cclxuXHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHByb2Nlc3NOZXdseUFkZGVkRmlsZXMoKTogRmlsZVByb2Nlc3NpbmdSZXN1bHQge1xyXG4gICAgY29uc3QgYWRkZWRRdWV1ZSA9IHRoaXMuZ2V0TmV3bHlBZGRlZEZpbGVzKCk7XHJcbiAgICBjb25zdCB2YWxpZGF0aW9uUmVzdWx0ID0gdGhpcy52YWxpZGF0ZUZpbGVzSW5RdWV1ZShhZGRlZFF1ZXVlKTtcclxuXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICB2YWxpZEZpbGVzOiBhZGRlZFF1ZXVlLmZpbHRlcihmaWxlID0+ICF2YWxpZGF0aW9uUmVzdWx0LmludmFsaWRGaWxlcy5pbmNsdWRlcyhmaWxlKSksXHJcbiAgICAgIGludmFsaWRGaWxlczogdmFsaWRhdGlvblJlc3VsdC5pbnZhbGlkRmlsZXMsXHJcbiAgICAgIGVycm9yczogdmFsaWRhdGlvblJlc3VsdC5lcnJvcnNcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldE5ld2x5QWRkZWRGaWxlcygpOiBGaWxlSXRlbVtdIHtcclxuICAgIHJldHVybiB0aGlzLnVwbG9hZGVyLnF1ZXVlLmZpbHRlcigob2JqKSA9PiBvYmpbJ3NvbWUnXT8ubGFzdE1vZGlmaWVkICE9IG51bGwpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB2YWxpZGF0ZUZpbGVzSW5RdWV1ZShmaWxlUXVldWU6IEZpbGVJdGVtW10pOiBGaWxlVmFsaWRhdGlvblJlc3VsdCB7XHJcbiAgICBjb25zdCB2YWxpZGF0aW9uRXJyb3JzOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgY29uc3QgaW52YWxpZEZpbGVzOiBGaWxlSXRlbVtdID0gW107XHJcbiAgICBjb25zdCBwcm9jZXNzZWREdXBsaWNhdGVOYW1lcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xyXG5cclxuICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBmaWxlUXVldWUpIHtcclxuICAgICAgY29uc3QgZmlsZSA9IGVsZW1lbnQuZmlsZTtcclxuICAgICAgaWYgKCFmaWxlKSBjb250aW51ZTtcclxuXHJcbiAgICAgIGNvbnN0IGZpbGVWYWxpZGF0aW9uID0gdGhpcy52YWxpZGF0ZVNpbmdsZUZpbGUoZmlsZSwgZWxlbWVudCwgcHJvY2Vzc2VkRHVwbGljYXRlTmFtZXMpO1xyXG5cclxuICAgICAgaWYgKCFmaWxlVmFsaWRhdGlvbi5pc1ZhbGlkKSB7XHJcbiAgICAgICAgaW52YWxpZEZpbGVzLnB1c2goZWxlbWVudCk7XHJcbiAgICAgICAgdmFsaWRhdGlvbkVycm9ycy5wdXNoKC4uLmZpbGVWYWxpZGF0aW9uLmVycm9ycyk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBpc1ZhbGlkOiBpbnZhbGlkRmlsZXMubGVuZ3RoID09PSAwLFxyXG4gICAgICBlcnJvcnM6IHZhbGlkYXRpb25FcnJvcnMsXHJcbiAgICAgIGludmFsaWRGaWxlc1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgdmFsaWRhdGVTaW5nbGVGaWxlKGZpbGU6IEZpbGVMaWtlT2JqZWN0LCBlbGVtZW50OiBGaWxlSXRlbSwgcHJvY2Vzc2VkRHVwbGljYXRlTmFtZXM6IFNldDxzdHJpbmc+KTogRmlsZVZhbGlkYXRpb25SZXN1bHQge1xyXG4gICAgY29uc3QgZXJyb3JzOiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICAgIGNvbnN0IHNpemVWYWxpZCA9IHRoaXMudmFsaWRhdGVJbmRpdmlkdWFsRmlsZVNpemUoZmlsZSk7XHJcbiAgICBjb25zdCB0eXBlVmFsaWQgPSB0aGlzLnZhbGlkYXRlSW5kaXZpZHVhbEZpbGVUeXBlKGZpbGUpO1xyXG4gICAgY29uc3QgbmFtZVZhbGlkID0gdGhpcy52YWxpZGF0ZUR1cGxpY2F0ZUZpbGVOYW1lKGZpbGUsIGVsZW1lbnQpO1xyXG5cclxuICAgIGlmICghc2l6ZVZhbGlkKSB7XHJcbiAgICAgIGVycm9ycy5wdXNoKHRoaXMuY3JlYXRlRmlsZVNpemVFcnJvck1lc3NhZ2UoZmlsZS5uYW1lKSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCF0eXBlVmFsaWQpIHtcclxuICAgICAgZXJyb3JzLnB1c2godGhpcy5jcmVhdGVGaWxlVHlwZUVycm9yTWVzc2FnZShmaWxlLm5hbWUpKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoIW5hbWVWYWxpZCkge1xyXG4gICAgICBjb25zdCBkdXBsaWNhdGVFcnJvciA9IHRoaXMuY3JlYXRlRHVwbGljYXRlRmlsZUVycm9yTWVzc2FnZShmaWxlLm5hbWUsIHByb2Nlc3NlZER1cGxpY2F0ZU5hbWVzKTtcclxuICAgICAgaWYgKGR1cGxpY2F0ZUVycm9yKSB7XHJcbiAgICAgICAgZXJyb3JzLnB1c2goZHVwbGljYXRlRXJyb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgaXNWYWxpZDogc2l6ZVZhbGlkICYmIHR5cGVWYWxpZCAmJiBuYW1lVmFsaWQsXHJcbiAgICAgIGVycm9ycyxcclxuICAgICAgaW52YWxpZEZpbGVzOiBbXVxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY3JlYXRlRmlsZVNpemVFcnJvck1lc3NhZ2UoZmlsZU5hbWU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy51dGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdGaWxlRXhjZWVkc01heFNpemUnKVxyXG4gICAgICAucmVwbGFjZSgne2ZpbGVOYW1lfScsIGZpbGVOYW1lKVxyXG4gICAgICAucmVwbGFjZSgne21heFNpemV9JywgdGhpcy5vcHRpb25zLmZpbGVNYXhTaXplSW5NQi50b1N0cmluZygpKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY3JlYXRlRmlsZVR5cGVFcnJvck1lc3NhZ2UoZmlsZU5hbWU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy51dGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdGaWxlVHlwZU5vdEFjY2VwdGVkJylcclxuICAgICAgLnJlcGxhY2UoJ3tmaWxlTmFtZX0nLCBmaWxlTmFtZSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNyZWF0ZUR1cGxpY2F0ZUZpbGVFcnJvck1lc3NhZ2UoZmlsZU5hbWU6IHN0cmluZywgcHJvY2Vzc2VkRHVwbGljYXRlTmFtZXM6IFNldDxzdHJpbmc+KTogc3RyaW5nIHwgbnVsbCB7XHJcbiAgICBjb25zdCBmaWxlTmFtZUxvd2VyID0gZmlsZU5hbWUudG9Mb3dlckNhc2UoKTtcclxuXHJcbiAgICBpZiAocHJvY2Vzc2VkRHVwbGljYXRlTmFtZXMuaGFzKGZpbGVOYW1lTG93ZXIpKSB7XHJcbiAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIHByb2Nlc3NlZER1cGxpY2F0ZU5hbWVzLmFkZChmaWxlTmFtZUxvd2VyKTtcclxuXHJcbiAgICBsZXQgZHVwbGljYXRlRXJyb3JNc2cgPSB0aGlzLnV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ0R1cGxpY2F0ZUZpbGVOYW1lJyk7XHJcblxyXG4gICAgaWYgKCFkdXBsaWNhdGVFcnJvck1zZyB8fCBkdXBsaWNhdGVFcnJvck1zZyA9PT0gJ0R1cGxpY2F0ZUZpbGVOYW1lJykge1xyXG4gICAgICBkdXBsaWNhdGVFcnJvck1zZyA9IGBGaWxlICd7ZmlsZU5hbWV9JyBhbHJlYWR5IGV4aXN0cy4gUGxlYXNlIGNob29zZSBhIGRpZmZlcmVudCBmaWxlIG9yIHJlbmFtZSBpdC5gO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBkdXBsaWNhdGVFcnJvck1zZy5yZXBsYWNlKCd7ZmlsZU5hbWV9JywgZmlsZU5hbWUpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBoYW5kbGVGaWxlVmFsaWRhdGlvblJlc3VsdHMocmVzdWx0OiBGaWxlUHJvY2Vzc2luZ1Jlc3VsdCk6IHZvaWQge1xyXG4gICAgaWYgKHJlc3VsdC5pbnZhbGlkRmlsZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICB0aGlzLnJlbW92ZUludmFsaWRGaWxlcyhyZXN1bHQuaW52YWxpZEZpbGVzKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAocmVzdWx0LmVycm9ycy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIHRoaXMuc2hvd1ZhbGlkYXRpb25FcnJvcnMocmVzdWx0LmVycm9ycyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHByb2Nlc3NWYWxpZEZpbGVzRm9yVXBsb2FkKCk6IHZvaWQge1xyXG4gICAgY29uc3QgZmlsZXNBcnJheTogRmlsZURUT1tdID0gW107XHJcbiAgICBjb25zdCB2YWxpZFF1ZXVlID0gdGhpcy5nZXROZXdseUFkZGVkRmlsZXMoKTtcclxuXHJcbiAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgdmFsaWRRdWV1ZSkge1xyXG4gICAgICBjb25zdCBmaWxlID0gZWxlbWVudC5maWxlO1xyXG4gICAgICBpZiAoIWZpbGUpIGNvbnRpbnVlO1xyXG5cclxuICAgICAgaWYgKHRoaXMuc2hvdWxkVXNlQXN5bmNVcGxvYWQoZWxlbWVudCkpIHtcclxuICAgICAgICB0aGlzLmhhbmRsZUFzeW5jRmlsZVVwbG9hZChlbGVtZW50LCBmaWxlc0FycmF5KTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLmhhbmRsZVN5bmNGaWxlVXBsb2FkKGZpbGUsIGZpbGVzQXJyYXkpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNob3VsZFVzZUFzeW5jVXBsb2FkKGVsZW1lbnQ6IEZpbGVJdGVtKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmlzVXBsb2FkRmlsZUFzeW5jICYmICFlbGVtZW50Ll9maWxlWydpRF9HVUlEJ107XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHZhbGlkYXRlRmlsZUNvbnN0cmFpbnRzKCk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5pc011bHRpcGxlRmlsZSkge1xyXG4gICAgICBpZiAoIXRoaXMudmFsaWRhdGVNaW5GaWxlQ291bnQoKSB8fCAhdGhpcy52YWxpZGF0ZU1heEZpbGVDb3VudCgpIHx8ICF0aGlzLnZhbGlkYXRlVG90YWxGaWxlU2l6ZSgpKSB7XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgdmFsaWRhdGVNaW5GaWxlQ291bnQoKTogYm9vbGVhbiB7XHJcbiAgICBpZiAodGhpcy5vcHRpb25zLm1pbk5vT2ZGaWxlcyA+IDAgJiYgdGhpcy5vcHRpb25zLm1pbk5vT2ZGaWxlcyA+IHRoaXMudXBsb2FkZXIucXVldWUubGVuZ3RoKSB7XHJcbiAgICAgIGNvbnN0IG1pbkZpbGVNc2cgPSB0aGlzLnV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ01pbmltdW1GaWxlc1JlcXVpcmVkJylcclxuICAgICAgICAucmVwbGFjZSgne2NvdW50fScsIHRoaXMub3B0aW9ucy5taW5Ob09mRmlsZXMudG9TdHJpbmcoKSk7XHJcbiAgICAgIHRoaXMuc2hvd0ZpbGVDb3VudEVycm9yKCdNaW5GaWxlQ291bnRWYWxpZGF0aW9uS2V5JywgbWluRmlsZU1zZyk7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICAgIHJldHVybiB0cnVlO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB2YWxpZGF0ZU1heEZpbGVDb3VudCgpOiBib29sZWFuIHtcclxuICAgIGlmICh0aGlzLm9wdGlvbnMubWF4Tm9PZkZpbGVzID4gMCAmJiB0aGlzLm9wdGlvbnMubWF4Tm9PZkZpbGVzIDwgdGhpcy51cGxvYWRlci5xdWV1ZS5sZW5ndGgpIHtcclxuICAgICAgY29uc3QgbWF4RmlsZU1zZyA9IHRoaXMudXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSgnTWF4aW11bUZpbGVzRXhjZWVkZWQnKSB8fFxyXG4gICAgICAgIGBNYXhpbXVtIHttYXhDb3VudH0gZmlsZXMgYWxsb3dlZC4gWW91IGhhdmUgc2VsZWN0ZWQge2N1cnJlbnRDb3VudH0gZmlsZXMuYDtcclxuICAgICAgY29uc3QgZmluYWxNc2cgPSBtYXhGaWxlTXNnXHJcbiAgICAgICAgLnJlcGxhY2UoJ3ttYXhDb3VudH0nLCB0aGlzLm9wdGlvbnMubWF4Tm9PZkZpbGVzLnRvU3RyaW5nKCkpXHJcbiAgICAgICAgLnJlcGxhY2UoJ3tjdXJyZW50Q291bnR9JywgdGhpcy51cGxvYWRlci5xdWV1ZS5sZW5ndGgudG9TdHJpbmcoKSk7XHJcbiAgICAgIHRoaXMuc2hvd0ZpbGVDb3VudEVycm9yKCdNYXhGaWxlQ291bnRWYWxpZGF0aW9uS2V5JywgZmluYWxNc2cpO1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2hvd0ZpbGVDb3VudEVycm9yKGVycm9yS2V5OiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgY29uc3QgY3VycmVudEVycm9ycyA9IHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLmVycm9ycyB8fCB7fTtcclxuXHJcbiAgICAvLyBQcmVzZXJ2ZSBleGlzdGluZyBlcnJvcnMgYW5kIGFkZCB0aGUgbmV3IG9uZVxyXG4gICAgY29uc3QgbmV3RXJyb3JzID0geyAuLi5jdXJyZW50RXJyb3JzIH07XHJcbiAgICBuZXdFcnJvcnNbZXJyb3JLZXldID0gbWVzc2FnZTtcclxuXHJcbiAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5zZXRFcnJvcnMobmV3RXJyb3JzKTtcclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLm1hcmtBc1RvdWNoZWQoKTtcclxuXHJcbiAgICAvLyBGb3JjZSB0aGUgZm9ybSBjb250cm9sIHRvIGJlIGludmFsaWRcclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLm1hcmtBc0RpcnR5KCk7XHJcblxyXG4gICAgLy8gRW5zdXJlIHRoZSBlcnJvciBwZXJzaXN0c1xyXG4gICAgdGhpcy5mb3JjZVZhbGlkYXRpb25FcnJvckRpc3BsYXkoZXJyb3JLZXksIG1lc3NhZ2UpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBmb3JjZVZhbGlkYXRpb25FcnJvckRpc3BsYXkoZXJyb3JLZXk6IHN0cmluZywgbWVzc2FnZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAvLyBGb3JjZSB0aGUgdmFsaWRhdGlvbiBlcnJvciB0byBwZXJzaXN0IGJ5IHJlLWFwcGx5aW5nIGl0IGFmdGVyIGEgc2hvcnQgZGVsYXlcclxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICBjb25zdCBjdXJyZW50RXJyb3JzID0gdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuZXJyb3JzIHx8IHt9O1xyXG4gICAgICBpZiAoIWN1cnJlbnRFcnJvcnNbZXJyb3JLZXldKSB7XHJcbiAgICAgICAgY29uc3QgbmV3RXJyb3JzID0geyAuLi5jdXJyZW50RXJyb3JzIH07XHJcbiAgICAgICAgbmV3RXJyb3JzW2Vycm9yS2V5XSA9IG1lc3NhZ2U7XHJcbiAgICAgICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuc2V0RXJyb3JzKG5ld0Vycm9ycyk7XHJcbiAgICAgICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wubWFya0FzVG91Y2hlZCgpO1xyXG4gICAgICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLm1hcmtBc0RpcnR5KCk7XHJcbiAgICAgIH1cclxuICAgIH0sIDEwMCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNsZWFyRmlsZUNvdW50RXJyb3IoZXJyb3JLZXk6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgY29uc3QgY3VycmVudEVycm9ycyA9IHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLmVycm9ycztcclxuICAgIGlmIChjdXJyZW50RXJyb3JzICYmIGN1cnJlbnRFcnJvcnNbZXJyb3JLZXldKSB7XHJcbiAgICAgIGRlbGV0ZSBjdXJyZW50RXJyb3JzW2Vycm9yS2V5XTtcclxuXHJcbiAgICAgIGlmIChPYmplY3Qua2V5cyhjdXJyZW50RXJyb3JzKS5sZW5ndGggPT09IDApIHtcclxuICAgICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5zZXRFcnJvcnMobnVsbCk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuc2V0RXJyb3JzKGN1cnJlbnRFcnJvcnMpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHZhbGlkYXRlVG90YWxGaWxlU2l6ZSgpOiBib29sZWFuIHtcclxuICAgIGlmICh0aGlzLm9wdGlvbnMubWF4U2l6ZUZvckFsbEZpbGVzSW5NQiA+IDApIHtcclxuICAgICAgY29uc3QgdG90YWxTaXplID0gdGhpcy51cGxvYWRlci5xdWV1ZS5yZWR1Y2UoKHN1bSwgZWxlbWVudCkgPT4gc3VtICsgZWxlbWVudC5maWxlLnNpemUsIDApO1xyXG4gICAgICBjb25zdCBtYXhTaXplQnl0ZXMgPSB0aGlzLm9wdGlvbnMubWF4U2l6ZUZvckFsbEZpbGVzSW5NQiAqIHRoaXMuQllURVNfVE9fTUI7XHJcblxyXG4gICAgICBpZiAodG90YWxTaXplID4gbWF4U2l6ZUJ5dGVzKSB7XHJcbiAgICAgICAgdGhpcy5zaG93VG90YWxTaXplRXJyb3IoKTtcclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiB0cnVlO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzaG93VG90YWxTaXplRXJyb3IoKTogdm9pZCB7XHJcbiAgICBjb25zdCB0b3RhbFNpemVNc2cgPSB0aGlzLnV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ1RvdGFsRmlsZVNpemVFeGNlZWRlZCcpXHJcbiAgICAgIC5yZXBsYWNlKCd7bWF4U2l6ZX0nLCB0aGlzLm9wdGlvbnMubWF4U2l6ZUZvckFsbEZpbGVzSW5NQi50b1N0cmluZygpKTtcclxuXHJcbiAgICBjb25zdCBjdXJyZW50RXJyb3JzID0gdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuZXJyb3JzIHx8IHt9O1xyXG5cclxuICAgIC8vIFByZXNlcnZlIGV4aXN0aW5nIGVycm9ycyBhbmQgYWRkIHRoZSBuZXcgb25lXHJcbiAgICBjb25zdCBuZXdFcnJvcnMgPSB7IC4uLmN1cnJlbnRFcnJvcnMgfTtcclxuICAgIG5ld0Vycm9yc1snTWF4U2l6ZUZvckFsbEZpbGVzSW5NQiddID0gdG90YWxTaXplTXNnO1xyXG5cclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnNldEVycm9ycyhuZXdFcnJvcnMpO1xyXG4gICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wubWFya0FzVG91Y2hlZCgpO1xyXG5cclxuICAgIC8vIEZvcmNlIHRoZSBmb3JtIGNvbnRyb2wgdG8gYmUgaW52YWxpZFxyXG4gICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wubWFya0FzRGlydHkoKTtcclxuXHJcbiAgICAvLyBFbnN1cmUgdGhlIGVycm9yIHBlcnNpc3RzXHJcbiAgICB0aGlzLmZvcmNlVmFsaWRhdGlvbkVycm9yRGlzcGxheSgnTWF4U2l6ZUZvckFsbEZpbGVzSW5NQicsIHRvdGFsU2l6ZU1zZyk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHZhbGlkYXRlRmlsZVNpemUoZmlsZTogRmlsZUxpa2VPYmplY3QpOiBib29sZWFuIHtcclxuICAgIGNvbnN0IG1heEZpbGVTaXplID0gdGhpcy5vcHRpb25zLmZpbGVNYXhTaXplSW5NQiAqIHRoaXMuQllURVNfVE9fTUI7XHJcbiAgICBpZiAoZmlsZS5zaXplID4gbWF4RmlsZVNpemUpIHtcclxuICAgICAgdGhpcy5zZXRGb3JtQ29udHJvbEVycm9yKCdGaWxlTWF4U2l6ZUluTUInLCBgJHt0aGlzLm9wdGlvbnMuZmlsZU1heFNpemVJbk1CfU1CYCk7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICAgIHJldHVybiB0cnVlO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB2YWxpZGF0ZUZpbGVUeXBlKGZpbGU6IEZpbGVMaWtlT2JqZWN0KTogYm9vbGVhbiB7XHJcbiAgICBpZiAodGhpcy5vcHRpb25zLmZpbGVVcGxvYWRBY2NlcHRzVHlwZXM/Lmxlbmd0aCkge1xyXG4gICAgICBjb25zdCBmaWxlVHlwZSA9IGZpbGUudHlwZTtcclxuICAgICAgY29uc3QgaXNBY2NlcHRlZCA9IHRoaXMuYWNjZXB0ZWRUeXBlQXJyYXkuc29tZSh0eXBlID0+XHJcbiAgICAgICAgdHlwZS50b0xvd2VyQ2FzZSgpID09PSBmaWxlVHlwZS50b0xvd2VyQ2FzZSgpXHJcbiAgICAgICk7XHJcblxyXG4gICAgICBpZiAoIWlzQWNjZXB0ZWQpIHtcclxuICAgICAgICB0aGlzLnNldEZvcm1Db250cm9sRXJyb3IoJ1Rvb2xUaXBUeXBlRXJyb3InLCB0aGlzLnRvb2xUaXBUeXBlQXJyYXkpO1xyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRydWU7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHZhbGlkYXRlSW5kaXZpZHVhbEZpbGVTaXplKGZpbGU6IEZpbGVMaWtlT2JqZWN0KTogYm9vbGVhbiB7XHJcbiAgICBjb25zdCBtYXhGaWxlU2l6ZSA9IHRoaXMub3B0aW9ucy5maWxlTWF4U2l6ZUluTUIgKiB0aGlzLkJZVEVTX1RPX01CO1xyXG4gICAgcmV0dXJuIGZpbGUuc2l6ZSA8PSBtYXhGaWxlU2l6ZTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgdmFsaWRhdGVJbmRpdmlkdWFsRmlsZVR5cGUoZmlsZTogRmlsZUxpa2VPYmplY3QpOiBib29sZWFuIHtcclxuICAgIGlmICghdGhpcy5vcHRpb25zLmZpbGVVcGxvYWRBY2NlcHRzVHlwZXM/Lmxlbmd0aCkge1xyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBmaWxlVHlwZSA9IGZpbGUudHlwZT8udG9Mb3dlckNhc2UoKTtcclxuICAgIGlmICghZmlsZVR5cGUpIHtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0aGlzLmFjY2VwdGVkVHlwZUFycmF5LnNvbWUodHlwZSA9PlxyXG4gICAgICB0eXBlLnRvTG93ZXJDYXNlKCkgPT09IGZpbGVUeXBlXHJcbiAgICApO1xyXG4gIH1cclxuXHJcblxyXG4gIHByaXZhdGUgdmFsaWRhdGVEdXBsaWNhdGVGaWxlTmFtZShmaWxlOiBGaWxlTGlrZU9iamVjdCwgY3VycmVudEVsZW1lbnQ6IEZpbGVJdGVtKTogYm9vbGVhbiB7XHJcbiAgICBpZiAoIWZpbGU/Lm5hbWUpIHtcclxuICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgY3VycmVudEZpbGVOYW1lID0gZmlsZS5uYW1lLnRvTG93ZXJDYXNlKCk7XHJcblxyXG4gICAgY29uc3QgZXhpc3RpbmdGaWxlcyA9IHRoaXMudXBsb2FkZXIucXVldWUuZmlsdGVyKGl0ZW0gPT4gaXRlbSAhPT0gY3VycmVudEVsZW1lbnQpO1xyXG4gICAgY29uc3QgZHVwbGljYXRlRXhpc3RzID0gZXhpc3RpbmdGaWxlcy5zb21lKGl0ZW0gPT4ge1xyXG4gICAgICBjb25zdCBleGlzdGluZ0ZpbGVOYW1lID0gaXRlbS5maWxlPy5uYW1lIHx8IGl0ZW0uX2ZpbGU/Lm5hbWU7XHJcbiAgICAgIHJldHVybiBleGlzdGluZ0ZpbGVOYW1lICYmIGV4aXN0aW5nRmlsZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gY3VycmVudEZpbGVOYW1lO1xyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKGR1cGxpY2F0ZUV4aXN0cykge1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy52YWx1ZSkge1xyXG4gICAgICBjb25zdCB1cGxvYWRlZEZpbGVzID0gQXJyYXkuaXNBcnJheSh0aGlzLm9wdGlvbnMudmFsdWUpID8gdGhpcy5vcHRpb25zLnZhbHVlIDogW3RoaXMub3B0aW9ucy52YWx1ZV07XHJcbiAgICAgIGNvbnN0IGR1cGxpY2F0ZUluVXBsb2FkZWQgPSB1cGxvYWRlZEZpbGVzLnNvbWUodXBsb2FkZWRGaWxlID0+IHtcclxuICAgICAgICBjb25zdCB1cGxvYWRlZEZpbGVOYW1lID0gdXBsb2FkZWRGaWxlPy5maWxlTmFtZSB8fCB1cGxvYWRlZEZpbGU/Lm5hbWU7XHJcbiAgICAgICAgcmV0dXJuIHVwbG9hZGVkRmlsZU5hbWUgJiYgdXBsb2FkZWRGaWxlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBjdXJyZW50RmlsZU5hbWU7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgcmV0dXJuICFkdXBsaWNhdGVJblVwbG9hZGVkO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0cnVlO1xyXG4gIH1cclxuXHJcblxyXG5cclxuICBwcml2YXRlIHJlbW92ZUludmFsaWRGaWxlcyhpbnZhbGlkRmlsZXM6IEZpbGVJdGVtW10pOiB2b2lkIHtcclxuICAgIGludmFsaWRGaWxlcy5mb3JFYWNoKGludmFsaWRGaWxlID0+IHtcclxuICAgICAgY29uc3QgaW5kZXggPSB0aGlzLnVwbG9hZGVyLnF1ZXVlLmluZGV4T2YoaW52YWxpZEZpbGUpO1xyXG4gICAgICBpZiAoaW5kZXggPiAtMSkge1xyXG4gICAgICAgIHRoaXMudXBsb2FkZXIucXVldWUuc3BsaWNlKGluZGV4LCAxKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNob3dWYWxpZGF0aW9uRXJyb3JzKGVycm9yczogc3RyaW5nW10pOiB2b2lkIHtcclxuICAgIGlmIChlcnJvcnMubGVuZ3RoID09PSAwKSByZXR1cm47XHJcblxyXG4gICAgY29uc3QgZXJyb3JNZXNzYWdlID0gZXJyb3JzLmpvaW4oJzxici8+Jyk7XHJcblxyXG4gICAgdGhpcy5zZXRWYWxpZGF0aW9uRXJyb3IoJ0ludmFsaWRGaWxlcycsIGVycm9yTWVzc2FnZSk7XHJcblxyXG4gICAgLy8gSW5jcmVhc2UgdGhlIGVycm9yIGRpc3BsYXkgZHVyYXRpb24gdG8gcHJldmVudCBlcnJvcnMgZnJvbSBkaXNhcHBlYXJpbmcgdG9vIHF1aWNrbHlcclxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICB0aGlzLmNsZWFySW52YWxpZEZpbGVzRXJyb3IoKTtcclxuICAgIH0sIHRoaXMuRVJST1JfRElTUExBWV9EVVJBVElPTiAqIDIpOyAvLyBEb3VibGUgdGhlIGR1cmF0aW9uXHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldFZhbGlkYXRpb25FcnJvcihlcnJvcktleTogc3RyaW5nLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgY29uc3QgY3VycmVudEVycm9ycyA9IHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLmVycm9ycyB8fCB7fTtcclxuXHJcbiAgICAvLyBQcmVzZXJ2ZSBleGlzdGluZyBlcnJvcnMgYW5kIGFkZCB0aGUgbmV3IG9uZVxyXG4gICAgY29uc3QgbmV3RXJyb3JzID0geyAuLi5jdXJyZW50RXJyb3JzIH07XHJcbiAgICBuZXdFcnJvcnNbZXJyb3JLZXldID0gZXJyb3JNZXNzYWdlO1xyXG5cclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnNldEVycm9ycyhuZXdFcnJvcnMpO1xyXG4gICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wubWFya0FzVG91Y2hlZCgpO1xyXG5cclxuICAgIC8vIEZvcmNlIHRoZSBmb3JtIGNvbnRyb2wgdG8gYmUgaW52YWxpZFxyXG4gICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wubWFya0FzRGlydHkoKTtcclxuXHJcbiAgICAvLyBFbnN1cmUgdGhlIGVycm9yIHBlcnNpc3RzXHJcbiAgICB0aGlzLmZvcmNlVmFsaWRhdGlvbkVycm9yRGlzcGxheShlcnJvcktleSwgZXJyb3JNZXNzYWdlKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY2xlYXJJbnZhbGlkRmlsZXNFcnJvcigpOiB2b2lkIHtcclxuICAgIGNvbnN0IGN1cnJlbnRFcnJvcnMgPSB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5lcnJvcnM7XHJcbiAgICBpZiAoY3VycmVudEVycm9ycyAmJiBjdXJyZW50RXJyb3JzWydJbnZhbGlkRmlsZXMnXSkge1xyXG4gICAgICBkZWxldGUgY3VycmVudEVycm9yc1snSW52YWxpZEZpbGVzJ107XHJcblxyXG4gICAgICBpZiAoT2JqZWN0LmtleXMoY3VycmVudEVycm9ycykubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuc2V0RXJyb3JzKG51bGwpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnNldEVycm9ycyhjdXJyZW50RXJyb3JzKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzZXRGb3JtQ29udHJvbEVycm9yKGVycm9yS2V5OiBzdHJpbmcsIGVycm9yVmFsdWU6IGFueSk6IHZvaWQge1xyXG4gICAgY29uc3QgY3VycmVudEVycm9ycyA9IHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLmVycm9ycyB8fCB7fTtcclxuXHJcbiAgICAvLyBQcmVzZXJ2ZSBleGlzdGluZyBlcnJvcnMgYW5kIGFkZCB0aGUgbmV3IG9uZVxyXG4gICAgY29uc3QgbmV3RXJyb3JzID0geyAuLi5jdXJyZW50RXJyb3JzIH07XHJcbiAgICBuZXdFcnJvcnNbZXJyb3JLZXldID0gZXJyb3JWYWx1ZTtcclxuXHJcbiAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5zZXRFcnJvcnMobmV3RXJyb3JzKTtcclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLm1hcmtBc1RvdWNoZWQoKTtcclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLm1hcmtBc0RpcnR5KCk7XHJcbiAgICB0aGlzLnVwbG9hZGVyLnF1ZXVlID0gW107XHJcblxyXG4gICAgLy8gRW5zdXJlIHRoZSBlcnJvciBwZXJzaXN0c1xyXG4gICAgdGhpcy5mb3JjZVZhbGlkYXRpb25FcnJvckRpc3BsYXkoZXJyb3JLZXksIGVycm9yVmFsdWUpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBoYW5kbGVBc3luY0ZpbGVVcGxvYWQoZWxlbWVudDogRmlsZUl0ZW0sIGZpbGVzQXJyYXk6IEZpbGVEVE9bXSk6IHZvaWQge1xyXG4gICAgY29uc3QgdXBsb2FkU3Vic2NyaXB0aW9uID0gdGhpcy5maWxlVXBsb2FkU2VydmljZS51cGxvYWRGaWxlKGVsZW1lbnQuX2ZpbGUpLnN1YnNjcmliZSh7XHJcbiAgICAgIG5leHQ6IChldmVudDogYW55KSA9PiB7XHJcbiAgICAgICAgaWYgKGV2ZW50LnR5cGUgPT09IEh0dHBFdmVudFR5cGUuVXBsb2FkUHJvZ3Jlc3MpIHtcclxuICAgICAgICAgIHRoaXMuaGFuZGxlVXBsb2FkUHJvZ3Jlc3MoZWxlbWVudCwgZXZlbnQpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoZXZlbnQudHlwZSA9PT0gSHR0cEV2ZW50VHlwZS5SZXNwb25zZSkge1xyXG4gICAgICAgICAgdGhpcy5oYW5kbGVVcGxvYWRDb21wbGV0ZShlbGVtZW50LCBldmVudCwgZmlsZXNBcnJheSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9LFxyXG4gICAgICBlcnJvcjogKGVycm9yKSA9PiB7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcignVXBsb2FkIGZhaWxlZDonLCBlcnJvcik7XHJcbiAgICAgICAgLy8gSGFuZGxlIHVwbG9hZCBlcnJvciAtIHlvdSBjYW4gYWRkIGN1c3RvbSBlcnJvciBoYW5kbGluZyBoZXJlXHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIC8vIFN0b3JlIHN1YnNjcmlwdGlvbiBmb3IgY2xlYW51cFxyXG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLmFkZCh1cGxvYWRTdWJzY3JpcHRpb24pO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBoYW5kbGVVcGxvYWRQcm9ncmVzcyhlbGVtZW50OiBGaWxlSXRlbSwgZXZlbnQ6IFVwbG9hZFByb2dyZXNzRXZlbnQpOiB2b2lkIHtcclxuICAgIGNvbnN0IHF1ZXVlSW5kZXggPSB0aGlzLnVwbG9hZGVyLnF1ZXVlLmZpbmRJbmRleCgoZmlsZSkgPT4gZmlsZSA9PT0gZWxlbWVudCk7XHJcbiAgICBpZiAocXVldWVJbmRleCA9PT0gLTEpIHJldHVybjtcclxuXHJcbiAgICBjb25zdCBwcm9ncmVzcyA9IE1hdGgucm91bmQoKDEwMCAqIGV2ZW50LmxvYWRlZCkgLyBldmVudC50b3RhbCk7XHJcbiAgICB0aGlzLnVwbG9hZGVyLnF1ZXVlW3F1ZXVlSW5kZXhdLnByb2dyZXNzID1cclxuICAgICAgcHJvZ3Jlc3MgPj0gdGhpcy5QUk9HUkVTU19ORUFSX0NPTVBMRVRFID8gdGhpcy5QUk9HUkVTU19ORUFSX0NPTVBMRVRFIDogcHJvZ3Jlc3M7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGhhbmRsZVVwbG9hZENvbXBsZXRlKGVsZW1lbnQ6IEZpbGVJdGVtLCBldmVudDogVXBsb2FkQ29tcGxldGVFdmVudCwgZmlsZXNBcnJheTogRmlsZURUT1tdKTogdm9pZCB7XHJcbiAgICBjb25zdCBxdWV1ZUluZGV4ID0gdGhpcy51cGxvYWRlci5xdWV1ZS5maW5kSW5kZXgoKGZpbGUpID0+IGZpbGUgPT09IGVsZW1lbnQpO1xyXG4gICAgaWYgKHF1ZXVlSW5kZXggPT09IC0xKSByZXR1cm47XHJcblxyXG4gICAgdGhpcy51cGxvYWRlci5xdWV1ZVtxdWV1ZUluZGV4XS5wcm9ncmVzcyA9IHRoaXMuUFJPR1JFU1NfQ09NUExFVEU7XHJcblxyXG4gICAgY29uc3QgZmlsZUlEID0gZXZlbnQuYm9keS52YWw7XHJcbiAgICB0aGlzLnVwZGF0ZUVsZW1lbnRXaXRoRmlsZUluZm8oZWxlbWVudCwgZmlsZUlELCBldmVudC5ib2R5LmRvd25sb2FkVXJsKTtcclxuXHJcbiAgICBjb25zdCBhZGRlZEZpbGUgPSB0aGlzLmNyZWF0ZUZpbGVEVE8oZWxlbWVudCwgZmlsZUlELCBldmVudC5ib2R5LmRvd25sb2FkVXJsKTtcclxuICAgIHRoaXMudXBkYXRlRm9ybVZhbHVlKGFkZGVkRmlsZSwgZmlsZXNBcnJheSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHVwZGF0ZUVsZW1lbnRXaXRoRmlsZUluZm8oZWxlbWVudDogRmlsZUl0ZW0sIGZpbGVJRDogc3RyaW5nLCBkb3dubG9hZFVybD86IHN0cmluZyk6IHZvaWQge1xyXG4gICAgZWxlbWVudC5fZmlsZVsnaURfR1VJRCddID0gZmlsZUlEO1xyXG4gICAgZWxlbWVudC5fZmlsZVsnaXNOZXcnXSA9IHRydWU7XHJcblxyXG4gICAgaWYgKGRvd25sb2FkVXJsKSB7XHJcbiAgICAgIGVsZW1lbnQuX2ZpbGVbJ3VybCddID0gZG93bmxvYWRVcmw7XHJcbiAgICAgIChlbGVtZW50LmZpbGUgYXMgYW55KS51cmwgPSBkb3dubG9hZFVybDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgY3JlYXRlRmlsZURUTyhlbGVtZW50OiBGaWxlSXRlbSwgZmlsZUlEOiBzdHJpbmcsIGRvd25sb2FkVXJsPzogc3RyaW5nKTogRmlsZURUTyB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBpRF9HVUlEOiBmaWxlSUQsXHJcbiAgICAgIGZpbGVOYW1lOiBlbGVtZW50Ll9maWxlWyduYW1lJ10sXHJcbiAgICAgIGZpbGVUeXBlOiBlbGVtZW50Ll9maWxlWyd0eXBlJ10sXHJcbiAgICAgIGlzTmV3OiB0cnVlLFxyXG4gICAgICBmaWxlQmFzZTY0OiAnJyxcclxuICAgICAgZmlsZVNpemVJbk1COiBlbGVtZW50Ll9maWxlLnNpemUgLyB0aGlzLkJZVEVTX1RPX01CLFxyXG4gICAgICBuYW1lV2l0aEV4dGVuc2lvbjogZWxlbWVudC5fZmlsZVsnbmFtZSddLFxyXG4gICAgICBmdWxsRmlsZVVSTDogZG93bmxvYWRVcmwgfHwgbnVsbFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgaGFuZGxlU3luY0ZpbGVVcGxvYWQoZmlsZTogRmlsZUxpa2VPYmplY3QsIGZpbGVzQXJyYXk6IEZpbGVEVE9bXSk6IHZvaWQge1xyXG4gICAgdGhpcy50cmFja01lbW9yeVVzYWdlKGZpbGUuc2l6ZSk7XHJcbiAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xyXG5cclxuICAgIC8vIFN0b3JlIHJlYWRlciByZWZlcmVuY2UgZm9yIGNsZWFudXBcclxuICAgIGNvbnN0IHJlYWRlclJlZiA9IHJlYWRlcjtcclxuXHJcbiAgICByZWFkZXIub25sb2FkID0gKCkgPT4ge1xyXG4gICAgICB0cnkge1xyXG4gICAgICAgIGNvbnN0IGV4aXN0aW5nR1VJRCA9IHRoaXMuZ2V0RXhpc3RpbmdGaWxlR1VJRChmaWxlKTtcclxuICAgICAgICB0aGlzLnVwZGF0ZVF1ZXVlSXRlbUZvclN5bmMoZmlsZSk7XHJcblxyXG4gICAgICAgIGNvbnN0IGFkZGVkRmlsZSA9IHRoaXMuY3JlYXRlU3luY0ZpbGVEVE8oZmlsZSwgcmVhZGVyLnJlc3VsdCBhcyBzdHJpbmcsIGV4aXN0aW5nR1VJRCk7XHJcbiAgICAgICAgdGhpcy51cGRhdGVGb3JtVmFsdWUoYWRkZWRGaWxlLCBmaWxlc0FycmF5KTtcclxuICAgICAgICB0aGlzLmhhbmRsZVBhdGNoQW5kRW1pdCgpO1xyXG4gICAgICB9IGZpbmFsbHkge1xyXG4gICAgICAgIC8vIENsZWFuIHVwIHJlYWRlclxyXG4gICAgICAgIHJlYWRlclJlZi5vbmxvYWQgPSBudWxsO1xyXG4gICAgICAgIHJlYWRlclJlZi5vbmVycm9yID0gbnVsbDtcclxuICAgICAgICByZWFkZXJSZWYub25hYm9ydCA9IG51bGw7XHJcbiAgICAgIH1cclxuICAgIH07XHJcblxyXG4gICAgcmVhZGVyLm9uZXJyb3IgPSAoKSA9PiB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZpbGUgcmVhZGluZyBmYWlsZWQnKTtcclxuICAgICAgcmVhZGVyUmVmLm9ubG9hZCA9IG51bGw7XHJcbiAgICAgIHJlYWRlclJlZi5vbmVycm9yID0gbnVsbDtcclxuICAgICAgcmVhZGVyUmVmLm9uYWJvcnQgPSBudWxsO1xyXG4gICAgfTtcclxuXHJcbiAgICByZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlLnJhd0ZpbGUgYXMgRmlsZSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHVwZGF0ZVF1ZXVlSXRlbUZvclN5bmMoZmlsZTogRmlsZUxpa2VPYmplY3QpOiB2b2lkIHtcclxuICAgIGNvbnN0IHF1ZXVlSXRlbSA9IHRoaXMuZmluZFF1ZXVlSXRlbUJ5RmlsZShmaWxlKTtcclxuXHJcbiAgICBpZiAocXVldWVJdGVtKSB7XHJcbiAgICAgIHRoaXMucHJlc2VydmVGaWxlUmVmZXJlbmNlKHF1ZXVlSXRlbSwgZmlsZSk7XHJcbiAgICAgIHF1ZXVlSXRlbS5wcm9ncmVzcyA9IHRoaXMuUFJPR1JFU1NfQ09NUExFVEU7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGZpbmRRdWV1ZUl0ZW1CeUZpbGUoZmlsZTogRmlsZUxpa2VPYmplY3QpOiBGaWxlSXRlbSB8IHVuZGVmaW5lZCB7XHJcbiAgICByZXR1cm4gdGhpcy51cGxvYWRlci5xdWV1ZS5maW5kKGl0ZW0gPT5cclxuICAgICAgaXRlbS5maWxlLm5hbWUgPT09IGZpbGUubmFtZSAmJiBpdGVtLmZpbGUuc2l6ZSA9PT0gZmlsZS5zaXplXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBwcmVzZXJ2ZUZpbGVSZWZlcmVuY2UocXVldWVJdGVtOiBGaWxlSXRlbSwgZmlsZTogRmlsZUxpa2VPYmplY3QpOiB2b2lkIHtcclxuICAgIChxdWV1ZUl0ZW0uX2ZpbGUgYXMgYW55KS5yYXdGaWxlID0gZmlsZS5yYXdGaWxlO1xyXG4gICAgKHF1ZXVlSXRlbS5maWxlIGFzIGFueSkucmF3RmlsZSA9IGZpbGUucmF3RmlsZTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY3JlYXRlU3luY0ZpbGVEVE8oZmlsZTogRmlsZUxpa2VPYmplY3QsIHJlYWRlclJlc3VsdDogc3RyaW5nLCBleGlzdGluZ0dVSUQ6IHN0cmluZyB8IG51bGwpOiBGaWxlRFRPIHtcclxuICAgIHJldHVybiB7XHJcbiAgICAgIGZpbGVOYW1lOiBmaWxlLm5hbWUsXHJcbiAgICAgIGZpbGVUeXBlOiBmaWxlLnR5cGUsXHJcbiAgICAgIGZpbGVCYXNlNjQ6IHJlYWRlclJlc3VsdC5zcGxpdCgnLCcpWzFdLFxyXG4gICAgICBmaWxlU2l6ZUluTUI6IGZpbGUuc2l6ZSAvIHRoaXMuQllURVNfVE9fTUIsXHJcbiAgICAgIG5hbWVXaXRoRXh0ZW5zaW9uOiBmaWxlLm5hbWUsXHJcbiAgICAgIGlEX0dVSUQ6IGV4aXN0aW5nR1VJRCxcclxuICAgICAgaXNOZXc6IHRydWUsXHJcbiAgICAgIGZ1bGxGaWxlVVJMOiBudWxsXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZXRFeGlzdGluZ0ZpbGVHVUlEKGZpbGU6IEZpbGVMaWtlT2JqZWN0KTogc3RyaW5nIHwgbnVsbCB7XHJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5pc011bHRpcGxlRmlsZSAmJiB0aGlzLmZpbGUpIHtcclxuICAgICAgcmV0dXJuIHRoaXMuZmlsZS5uYW1lV2l0aEV4dGVuc2lvbiA9PT0gZmlsZS5uYW1lID8gdGhpcy5maWxlLmlEX0dVSUQgOiBudWxsO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHVwZGF0ZUZvcm1WYWx1ZShhZGRlZEZpbGU6IEZpbGVEVE8sIGZpbGVzQXJyYXk6IEZpbGVEVE9bXSk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuaXNNdWx0aXBsZUZpbGUpIHtcclxuICAgICAgdGhpcy5maWxlVXBsb2FkTW9kZWwgPSBuZXcgRmlsZVVwbG9hZE1vZGVsKCk7XHJcbiAgICAgIHRoaXMuZmlsZVVwbG9hZE1vZGVsLmZpbGUgPSBhZGRlZEZpbGU7XHJcbiAgICAgIHRoaXMudXBkYXRlRm9ybUNvbnRyb2wodGhpcy5maWxlVXBsb2FkTW9kZWwpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgZmlsZXNBcnJheS5wdXNoKGFkZGVkRmlsZSk7XHJcbiAgICAgIHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwudXBsb2FkZWRGaWxlcyA9IGZpbGVzQXJyYXk7XHJcbiAgICAgIHRoaXMuc2V0dXBNdWx0aXBsZUZpbGVNb2RlbCgpO1xyXG4gICAgICB0aGlzLnVwZGF0ZUZvcm1Db250cm9sKHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwpO1xyXG4gICAgICB0aGlzLmlzVXBsb2FkQ29tcGxldGUuZW1pdCh0cnVlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2V0dXBNdWx0aXBsZUZpbGVNb2RlbCgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLm9wdGlvbnMudmFsdWU/LmNvcnJlbGF0aW9uSURfR1VJRCA9PSBudWxsKSB7XHJcbiAgICAgIHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwucmVtb3ZlZEZpbGVzID0gW107XHJcbiAgICB9XHJcbiAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLmNvcnJlbGF0aW9uSURfR1VJRCA9IHRoaXMub3B0aW9ucy52YWx1ZT8uY29ycmVsYXRpb25JRF9HVUlEO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB1cGRhdGVGb3JtQ29udHJvbCh2YWx1ZTogRmlsZVVwbG9hZE1vZGVsIHwgTXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwpOiB2b2lkIHtcclxuICAgIHRoaXMucHJlc2VydmVFcnJvcnNBbmRVcGRhdGVWYWx1ZSh2YWx1ZSk7XHJcbiAgICB0aGlzLm9wdGlvbnMudmFsdWUgPSB2YWx1ZTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcHJlc2VydmVFcnJvcnNBbmRVcGRhdGVWYWx1ZSh2YWx1ZTogRmlsZVVwbG9hZE1vZGVsIHwgTXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwpOiB2b2lkIHtcclxuICAgIC8vIElmIHdlIGhhdmUgYSB2YWxpZCBmaWxlIHZhbHVlIGFuZCBoYXZlbid0IGNsZWFyZWQgdGhlIHJlcXVpcmVkIGVycm9yIHlldCwgcmVtb3ZlIGl0XHJcbiAgICBpZiAodGhpcy5oYXNWYWxpZEZpbGVWYWx1ZSh2YWx1ZSkgJiYgIXRoaXMuaGFzQ2xlYXJlZFJlcXVpcmVkRXJyb3IpIHtcclxuICAgICAgLy8gVXNlIHRoZSBjdXN0b20gbWV0aG9kIHRoYXQgb25seSByZW1vdmVzIHRoZSB2YWxpZGF0b3Igd2l0aG91dCBjaGFuZ2luZyB0aGUgaXNSZXF1aXJlZCBvcHRpb25cclxuICAgICAgLy8gVGhpcyBrZWVwcyB0aGUgYXN0ZXJpc2sgdmlzaWJsZSB3aGlsZSByZW1vdmluZyB0aGUgdmFsaWRhdGlvbiBsb2dpY1xyXG4gICAgICB0aGlzLnJlbW92ZVJlcXVpcmVkVmFsaWRhdG9yT25seSgpO1xyXG5cclxuICAgICAgLy8gTWFyayB0aGF0IHdlJ3ZlIGNsZWFyZWQgdGhlIHJlcXVpcmVkIGVycm9yXHJcbiAgICAgIHRoaXMuaGFzQ2xlYXJlZFJlcXVpcmVkRXJyb3IgPSB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFNldCB0aGUgZm9ybSBjb250cm9sIHZhbHVlXHJcbiAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5zZXRWYWx1ZSh2YWx1ZSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xyXG5cclxuICAgIC8vIFVwZGF0ZSB0aGUgZm9ybSBncm91cCBjb250cm9sIHZhbHVlXHJcbiAgICB0aGlzLmdyb3VwLmdldCh0aGlzLm9wdGlvbnMubmFtZSk/LnNldFZhbHVlKHZhbHVlLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XHJcbiAgfVxyXG5cclxuXHJcblxyXG4gIHByaXZhdGUgaGFzVmFsaWRGaWxlVmFsdWUodmFsdWU6IEZpbGVVcGxvYWRNb2RlbCB8IE11bHRpcGxlRmlsZVVwbG9hZE1vZGVsKTogYm9vbGVhbiB7XHJcbiAgICBpZiAoIXZhbHVlKSByZXR1cm4gZmFsc2U7XHJcblxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5pc011bHRpcGxlRmlsZSkge1xyXG4gICAgICBjb25zdCBtdWx0aXBsZVZhbHVlID0gdmFsdWUgYXMgTXVsdGlwbGVGaWxlVXBsb2FkTW9kZWw7XHJcbiAgICAgIHJldHVybiAobXVsdGlwbGVWYWx1ZS51cGxvYWRlZEZpbGVzICYmIG11bHRpcGxlVmFsdWUudXBsb2FkZWRGaWxlcy5sZW5ndGggPiAwKSB8fFxyXG4gICAgICAgIChtdWx0aXBsZVZhbHVlLmV4aXN0aW5nRmlsZXMgJiYgbXVsdGlwbGVWYWx1ZS5leGlzdGluZ0ZpbGVzLmxlbmd0aCA+IDApO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgY29uc3Qgc2luZ2xlVmFsdWUgPSB2YWx1ZSBhcyBGaWxlVXBsb2FkTW9kZWw7XHJcbiAgICAgIHJldHVybiBzaW5nbGVWYWx1ZS5maWxlICYmIHNpbmdsZVZhbHVlLmZpbGUuZmlsZU5hbWUgIT09ICcnO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcbiAgcHJpdmF0ZSBoYW5kbGVQYXRjaEFuZEVtaXQoKTogdm9pZCB7XHJcbiAgICBjb25zdCBvcmlnaW5hbFZhbHVlID0gdGhpcy5ncm91cC5nZXQodGhpcy5vcHRpb25zLm5hbWUpPy52YWx1ZTtcclxuXHJcbiAgICBpZiAodGhpcy5vcHRpb25zLnBhdGNoRnVuY3Rpb24gJiYgdGhpcy5vcHRpb25zLnBhdGNoUGF0aCAmJiB0aGlzLmdyb3VwLmdldCh0aGlzLm9wdGlvbnMubmFtZSk/LnZhbGlkKSB7XHJcbiAgICAgIHRoaXMuY29udHJvbFV0aWxpdHkucGF0Y2hDb250cm9sVmFsdWUoXHJcbiAgICAgICAgb3JpZ2luYWxWYWx1ZSxcclxuICAgICAgICB0aGlzLm9wdGlvbnMucGF0Y2hGdW5jdGlvbixcclxuICAgICAgICB0aGlzLm9wdGlvbnMucGF0Y2hQYXRoXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5PbkNoYW5nZS5lbWl0KG9yaWdpbmFsVmFsdWUpO1xyXG4gIH1cclxuICByZW1vdmVGcm9tQ29udHJvbFZhbHVlKGl0ZW06IEZpbGVJdGVtKTogdm9pZCB7XHJcbiAgICAvLyBDbGVhbiB1cCBibG9iIFVSTCBiZWZvcmUgcmVtb3ZpbmdcclxuICAgIGNvbnN0IGRvd25sb2FkVXJsID0gdGhpcy5nZXRGaWxlRG93bmxvYWRVcmwoaXRlbSk7XHJcbiAgICBpZiAoZG93bmxvYWRVcmwgJiYgZG93bmxvYWRVcmwuc3RhcnRzV2l0aCgnYmxvYjonKSkge1xyXG4gICAgICB0aGlzLmNsZWFudXBCbG9iVXJsKGRvd25sb2FkVXJsKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmhhbmRsZUFzeW5jRmlsZURlbGV0aW9uKGl0ZW0pO1xyXG5cclxuICAgIGlmICghdGhpcy5vcHRpb25zLmlzTXVsdGlwbGVGaWxlKSB7XHJcbiAgICAgIHRoaXMuaGFuZGxlU2luZ2xlRmlsZVJlbW92YWwoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuaGFuZGxlTXVsdGlwbGVGaWxlUmVtb3ZhbChpdGVtKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmNoZWNrQW5kQ2xlYXJNYXhGaWxlQ291bnRWYWxpZGF0aW9uKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGhhbmRsZUFzeW5jRmlsZURlbGV0aW9uKGl0ZW06IEZpbGVJdGVtKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5vcHRpb25zLmlzVXBsb2FkRmlsZUFzeW5jICYmXHJcbiAgICAgIGl0ZW0ucHJvZ3Jlc3MgPT09IHRoaXMuUFJPR1JFU1NfQ09NUExFVEUgJiZcclxuICAgICAgaXRlbS5fZmlsZVsnaXNOZXcnXSkge1xyXG5cclxuICAgICAgY29uc3QgZGVsZXRlU3Vic2NyaXB0aW9uID0gdGhpcy5maWxlVXBsb2FkU2VydmljZS5kZWxldGVGaWxlKGl0ZW0uX2ZpbGVbJ2lEX0dVSUQnXSkuc3Vic2NyaWJlKHtcclxuICAgICAgICBlcnJvcjogKGVycm9yKSA9PiBjb25zb2xlLmVycm9yKCdEZWxldGUgZmFpbGVkOicsIGVycm9yKVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5hZGQoZGVsZXRlU3Vic2NyaXB0aW9uKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgaGFuZGxlU2luZ2xlRmlsZVJlbW92YWwoKTogdm9pZCB7XHJcbiAgICB0aGlzLnVwbG9hZGVyLnF1ZXVlID0gW107XHJcblxyXG4gICAgdGhpcy5maWxlVXBsb2FkTW9kZWwgPSBudWxsIGFzIGFueTtcclxuXHJcbiAgICBpZiAodGhpcy5vcHRpb25zLmlzUmVxdWlyZWQpIHtcclxuICAgICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wubWFya0FzVG91Y2hlZCgpO1xyXG4gICAgICAvLyBVc2UgdGhlIGV4aXN0aW5nIHV0aWxpdHkgZnVuY3Rpb24gdG8gYWRkIHJlcXVpcmVkIHZhbGlkYXRpb24gYmFja1xyXG4gICAgICB0aGlzLmFkZFJlcXVpcmVkVmFsaWRhdGlvbigpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFJlc2V0IHRoZSBmbGFnIHNvIHJlcXVpcmVkIHZhbGlkYXRpb24gY2FuIHdvcmsgYWdhaW5cclxuICAgIHRoaXMuaGFzQ2xlYXJlZFJlcXVpcmVkRXJyb3IgPSBmYWxzZTtcclxuXHJcbiAgICB0aGlzLmdyb3VwLmdldCh0aGlzLm9wdGlvbnMubmFtZSk/LnNldFZhbHVlKHRoaXMuZmlsZVVwbG9hZE1vZGVsLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XHJcbiAgICB0aGlzLm9wdGlvbnMudmFsdWUgPSB0aGlzLmZpbGVVcGxvYWRNb2RlbDtcclxuXHJcbiAgICAvLyBSZS1ldmFsdWF0ZSBhbGwgdmFsaWRhdGlvbnMgYWZ0ZXIgZmlsZSByZW1vdmFsXHJcbiAgICB0aGlzLnJlRXZhbHVhdGVBbGxWYWxpZGF0aW9ucygpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBoYW5kbGVNdWx0aXBsZUZpbGVSZW1vdmFsKGl0ZW06IEZpbGVJdGVtKTogdm9pZCB7XHJcbiAgICAvLyBDbGVhbiB1cCBibG9iIFVSTFxyXG4gICAgY29uc3QgZG93bmxvYWRVcmwgPSB0aGlzLmdldEZpbGVEb3dubG9hZFVybChpdGVtKTtcclxuICAgIGlmIChkb3dubG9hZFVybCAmJiBkb3dubG9hZFVybC5zdGFydHNXaXRoKCdibG9iOicpKSB7XHJcbiAgICAgIHRoaXMuY2xlYW51cEJsb2JVcmwoZG93bmxvYWRVcmwpO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHF1ZXVlSW5kZXggPSB0aGlzLnVwbG9hZGVyLnF1ZXVlLmluZGV4T2YoaXRlbSk7XHJcbiAgICBpZiAocXVldWVJbmRleCA+IC0xKSB7XHJcbiAgICAgIHRoaXMudXBsb2FkZXIucXVldWUuc3BsaWNlKHF1ZXVlSW5kZXgsIDEpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMucHJvY2Vzc0ZpbGVSZW1vdmFsRnJvbUV4aXN0aW5nKGl0ZW0pO1xyXG4gICAgdGhpcy5yZW1vdmVGcm9tVXBsb2FkZWRGaWxlcyhpdGVtKTtcclxuICAgIHRoaXMudmFsaWRhdGVSZW1haW5pbmdGaWxlcygpO1xyXG4gICAgdGhpcy51cGRhdGVNdWx0aXBsZUZpbGVNb2RlbCgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBwcm9jZXNzRmlsZVJlbW92YWxGcm9tRXhpc3RpbmcoaXRlbTogRmlsZUl0ZW0pOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5vcHRpb25zLnZhbHVlKSB7XHJcbiAgICAgIHRoaXMucmVzZXREZWxldGVkRmlsZXMoKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghdGhpcy5vcHRpb25zLnZhbHVlLmNvcnJlbGF0aW9uSURfR1VJRCkge1xyXG4gICAgICB0aGlzLnJlc2V0RGVsZXRlZEZpbGVzKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmhhbmRsZUV4aXN0aW5nRmlsZVJlbW92YWwoaXRlbSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHJlc2V0RGVsZXRlZEZpbGVzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5kZWxldGVkRmlsZXMgPSBbXTtcclxuICAgIHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwucmVtb3ZlZEZpbGVzID0gW107XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGhhbmRsZUV4aXN0aW5nRmlsZVJlbW92YWwoaXRlbTogRmlsZUl0ZW0pOiB2b2lkIHtcclxuICAgIGNvbnN0IGZpbGVOYW1lID0gaXRlbS5maWxlLnJhd0ZpbGUubmFtZTtcclxuICAgIGNvbnN0IGV4aXN0aW5nRmlsZSA9IHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwuZXhpc3RpbmdGaWxlc1xyXG4gICAgICAuZmluZChvYmogPT4gb2JqLm5hbWVXaXRoRXh0ZW5zaW9uID09PSBmaWxlTmFtZSk7XHJcblxyXG4gICAgaWYgKGV4aXN0aW5nRmlsZSAmJiAhdGhpcy5kZWxldGVkRmlsZXMuc29tZShvYmogPT4gb2JqLm5hbWVXaXRoRXh0ZW5zaW9uID09PSBmaWxlTmFtZSkpIHtcclxuICAgICAgdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbC5leGlzdGluZ0ZpbGVzID1cclxuICAgICAgICB0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLmV4aXN0aW5nRmlsZXMuZmlsdGVyKFxyXG4gICAgICAgICAgb2JqID0+IG9iai5uYW1lV2l0aEV4dGVuc2lvbiAhPT0gZmlsZU5hbWVcclxuICAgICAgICApO1xyXG4gICAgICB0aGlzLmRlbGV0ZWRGaWxlcy5wdXNoKGV4aXN0aW5nRmlsZSk7XHJcbiAgICAgIHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwucmVtb3ZlZEZpbGVzLnB1c2goZXhpc3RpbmdGaWxlLmlEX0dVSUQpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSByZW1vdmVGcm9tVXBsb2FkZWRGaWxlcyhpdGVtOiBGaWxlSXRlbSk6IHZvaWQge1xyXG4gICAgY29uc3QgaXRlbUZpbGVOYW1lID0gaXRlbS5fZmlsZS5uYW1lIHx8IGl0ZW0uZmlsZS5uYW1lO1xyXG4gICAgY29uc3QgaXRlbUZpbGVTaXplID0gaXRlbS5fZmlsZS5zaXplIHx8IGl0ZW0uZmlsZS5zaXplO1xyXG4gICAgY29uc3QgaXRlbUdVSUQgPSBpdGVtLl9maWxlWydpRF9HVUlEJ107XHJcblxyXG4gICAgdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbC51cGxvYWRlZEZpbGVzID1cclxuICAgICAgdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbC51cGxvYWRlZEZpbGVzLmZpbHRlcihvYmogPT4ge1xyXG4gICAgICAgIGlmIChpdGVtR1VJRCAmJiBvYmouaURfR1VJRCkge1xyXG4gICAgICAgICAgcmV0dXJuIG9iai5pRF9HVUlEICE9PSBpdGVtR1VJRDtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3Qgb2JqRmlsZU5hbWUgPSBvYmoubmFtZVdpdGhFeHRlbnNpb24gfHwgb2JqLmZpbGVOYW1lO1xyXG4gICAgICAgIGNvbnN0IG9iakZpbGVTaXplID0gb2JqLmZpbGVTaXplSW5NQiA/IG9iai5maWxlU2l6ZUluTUIgKiB0aGlzLkJZVEVTX1RPX01CIDogMDtcclxuXHJcbiAgICAgICAgcmV0dXJuICEob2JqRmlsZU5hbWUgPT09IGl0ZW1GaWxlTmFtZSAmJiBNYXRoLmFicyhvYmpGaWxlU2l6ZSAtIGl0ZW1GaWxlU2l6ZSkgPCAxMDAwKTtcclxuICAgICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHZhbGlkYXRlUmVtYWluaW5nRmlsZXMoKTogdm9pZCB7XHJcbiAgICBpZiAoKCF0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLnVwbG9hZGVkRmlsZXMgfHxcclxuICAgICAgdGhpcy5tdWx0aXBsZUZpbGVVcGxvYWRNb2RlbC51cGxvYWRlZEZpbGVzLmxlbmd0aCA9PT0gMCkgJiZcclxuICAgICAgdGhpcy5vcHRpb25zLmlzUmVxdWlyZWQpIHtcclxuICAgICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wuc2V0RXJyb3JzKHtcclxuICAgICAgICBNaW5GaWxlQ291bnRWYWxpZGF0aW9uS2V5OiB0aGlzLm9wdGlvbnMubWluTm9PZkZpbGVzXHJcbiAgICAgIH0pO1xyXG4gICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5tYXJrQXNUb3VjaGVkKCk7XHJcbiAgICAgIHRoaXMuYWRkUmVxdWlyZWRWYWxpZGF0aW9uKCk7XHJcbiAgICAgIHRoaXMuaGFzQ2xlYXJlZFJlcXVpcmVkRXJyb3IgPSBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBSZS1ldmFsdWF0ZSBhbGwgdmFsaWRhdGlvbnMgYWZ0ZXIgZmlsZSByZW1vdmFsXHJcbiAgICB0aGlzLnJlRXZhbHVhdGVBbGxWYWxpZGF0aW9ucygpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSByZUV2YWx1YXRlQWxsVmFsaWRhdGlvbnMoKTogdm9pZCB7XHJcbiAgICAvLyBDbGVhciBhbGwgZXhpc3RpbmcgdmFsaWRhdGlvbiBlcnJvcnMgZmlyc3RcclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnNldEVycm9ycyhudWxsKTtcclxuXHJcbiAgICAvLyBSZS1hcHBseSByZXF1aXJlZCB2YWxpZGF0aW9uIGlmIG5lZWRlZFxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5pc1JlcXVpcmVkKSB7XHJcbiAgICAgIHRoaXMuYWRkUmVxdWlyZWRWYWxpZGF0aW9uKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmUtdmFsaWRhdGUgZmlsZSBjb3VudCBjb25zdHJhaW50c1xyXG4gICAgdGhpcy5yZVZhbGlkYXRlRmlsZUNvdW50Q29uc3RyYWludHMoKTtcclxuXHJcbiAgICAvLyBSZS12YWxpZGF0ZSB0b3RhbCBmaWxlIHNpemVcclxuICAgIHRoaXMucmVWYWxpZGF0ZVRvdGFsRmlsZVNpemUoKTtcclxuXHJcbiAgICAvLyBSZS12YWxpZGF0ZSBpbmRpdmlkdWFsIGZpbGVzXHJcbiAgICB0aGlzLnJlVmFsaWRhdGVJbmRpdmlkdWFsRmlsZXMoKTtcclxuXHJcbiAgICAvLyBDbGVhciB2YWxpZGF0aW9uIGVycm9ycyB0aGF0IGFyZSBubyBsb25nZXIgYXBwbGljYWJsZVxyXG4gICAgdGhpcy5jbGVhck9ic29sZXRlVmFsaWRhdGlvbkVycm9ycygpO1xyXG5cclxuICAgIC8vIFVwZGF0ZSBmb3JtIGNvbnRyb2wgdmFsaWRpdHlcclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY2xlYXJPYnNvbGV0ZVZhbGlkYXRpb25FcnJvcnMoKTogdm9pZCB7XHJcbiAgICBjb25zdCBjdXJyZW50RmlsZUNvdW50ID0gdGhpcy51cGxvYWRlci5xdWV1ZS5sZW5ndGg7XHJcblxyXG4gICAgLy8gQ2xlYXIgbWF4IGZpbGUgY291bnQgZXJyb3IgaWYgY3VycmVudCBjb3VudCBpcyB3aXRoaW4gbGltaXRcclxuICAgIGlmICh0aGlzLm9wdGlvbnMubWF4Tm9PZkZpbGVzID4gMCAmJiBjdXJyZW50RmlsZUNvdW50IDw9IHRoaXMub3B0aW9ucy5tYXhOb09mRmlsZXMpIHtcclxuICAgICAgdGhpcy5jbGVhckZpbGVDb3VudEVycm9yKCdNYXhGaWxlQ291bnRWYWxpZGF0aW9uS2V5Jyk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ2xlYXIgbWluIGZpbGUgY291bnQgZXJyb3IgaWYgY3VycmVudCBjb3VudCBtZWV0cyBtaW5pbXVtIHJlcXVpcmVtZW50XHJcbiAgICBpZiAodGhpcy5vcHRpb25zLm1pbk5vT2ZGaWxlcyA+IDAgJiYgY3VycmVudEZpbGVDb3VudCA+PSB0aGlzLm9wdGlvbnMubWluTm9PZkZpbGVzKSB7XHJcbiAgICAgIHRoaXMuY2xlYXJGaWxlQ291bnRFcnJvcignTWluRmlsZUNvdW50VmFsaWRhdGlvbktleScpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIENsZWFyIHRvdGFsIHNpemUgZXJyb3IgaWYgY3VycmVudCB0b3RhbCBzaXplIGlzIHdpdGhpbiBsaW1pdFxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5tYXhTaXplRm9yQWxsRmlsZXNJbk1CID4gMCkge1xyXG4gICAgICBjb25zdCB0b3RhbFNpemUgPSB0aGlzLnVwbG9hZGVyLnF1ZXVlLnJlZHVjZSgoc3VtLCBlbGVtZW50KSA9PiBzdW0gKyBlbGVtZW50LmZpbGUuc2l6ZSwgMCk7XHJcbiAgICAgIGNvbnN0IG1heFNpemVCeXRlcyA9IHRoaXMub3B0aW9ucy5tYXhTaXplRm9yQWxsRmlsZXNJbk1CICogdGhpcy5CWVRFU19UT19NQjtcclxuXHJcbiAgICAgIGlmICh0b3RhbFNpemUgPD0gbWF4U2l6ZUJ5dGVzKSB7XHJcbiAgICAgICAgdGhpcy5jbGVhckZpbGVDb3VudEVycm9yKCdNYXhTaXplRm9yQWxsRmlsZXNJbk1CJyk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgcmVWYWxpZGF0ZUZpbGVDb3VudENvbnN0cmFpbnRzKCk6IHZvaWQge1xyXG4gICAgY29uc3QgY3VycmVudEZpbGVDb3VudCA9IHRoaXMudXBsb2FkZXIucXVldWUubGVuZ3RoO1xyXG5cclxuICAgIC8vIENoZWNrIG1pbmltdW0gZmlsZSBjb3VudFxyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5taW5Ob09mRmlsZXMgPiAwICYmIGN1cnJlbnRGaWxlQ291bnQgPCB0aGlzLm9wdGlvbnMubWluTm9PZkZpbGVzKSB7XHJcbiAgICAgIGNvbnN0IG1pbkZpbGVNc2cgPSB0aGlzLnV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ01pbmltdW1GaWxlc1JlcXVpcmVkJylcclxuICAgICAgICAucmVwbGFjZSgne2NvdW50fScsIHRoaXMub3B0aW9ucy5taW5Ob09mRmlsZXMudG9TdHJpbmcoKSk7XHJcbiAgICAgIHRoaXMuc2hvd0ZpbGVDb3VudEVycm9yKCdNaW5GaWxlQ291bnRWYWxpZGF0aW9uS2V5JywgbWluRmlsZU1zZyk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ2hlY2sgbWF4aW11bSBmaWxlIGNvdW50XHJcbiAgICBpZiAodGhpcy5vcHRpb25zLm1heE5vT2ZGaWxlcyA+IDAgJiYgY3VycmVudEZpbGVDb3VudCA+IHRoaXMub3B0aW9ucy5tYXhOb09mRmlsZXMpIHtcclxuICAgICAgY29uc3QgbWF4RmlsZU1zZyA9IHRoaXMudXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSgnTWF4aW11bUZpbGVzRXhjZWVkZWQnKSB8fFxyXG4gICAgICAgIGBNYXhpbXVtIHttYXhDb3VudH0gZmlsZXMgYWxsb3dlZC4gWW91IGhhdmUgc2VsZWN0ZWQge2N1cnJlbnRDb3VudH0gZmlsZXMuYDtcclxuICAgICAgY29uc3QgZmluYWxNc2cgPSBtYXhGaWxlTXNnXHJcbiAgICAgICAgLnJlcGxhY2UoJ3ttYXhDb3VudH0nLCB0aGlzLm9wdGlvbnMubWF4Tm9PZkZpbGVzLnRvU3RyaW5nKCkpXHJcbiAgICAgICAgLnJlcGxhY2UoJ3tjdXJyZW50Q291bnR9JywgY3VycmVudEZpbGVDb3VudC50b1N0cmluZygpKTtcclxuICAgICAgdGhpcy5zaG93RmlsZUNvdW50RXJyb3IoJ01heEZpbGVDb3VudFZhbGlkYXRpb25LZXknLCBmaW5hbE1zZyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHJlVmFsaWRhdGVUb3RhbEZpbGVTaXplKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMub3B0aW9ucy5tYXhTaXplRm9yQWxsRmlsZXNJbk1CID4gMCkge1xyXG4gICAgICBjb25zdCB0b3RhbFNpemUgPSB0aGlzLnVwbG9hZGVyLnF1ZXVlLnJlZHVjZSgoc3VtLCBlbGVtZW50KSA9PiBzdW0gKyBlbGVtZW50LmZpbGUuc2l6ZSwgMCk7XHJcbiAgICAgIGNvbnN0IG1heFNpemVCeXRlcyA9IHRoaXMub3B0aW9ucy5tYXhTaXplRm9yQWxsRmlsZXNJbk1CICogdGhpcy5CWVRFU19UT19NQjtcclxuXHJcbiAgICAgIGlmICh0b3RhbFNpemUgPiBtYXhTaXplQnl0ZXMpIHtcclxuICAgICAgICB0aGlzLnNob3dUb3RhbFNpemVFcnJvcigpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHJlVmFsaWRhdGVJbmRpdmlkdWFsRmlsZXMoKTogdm9pZCB7XHJcbiAgICAvLyBSZS12YWxpZGF0ZSBlYWNoIHJlbWFpbmluZyBmaWxlIGZvciBzaXplIGFuZCB0eXBlXHJcbiAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgdGhpcy51cGxvYWRlci5xdWV1ZSkge1xyXG4gICAgICBjb25zdCBmaWxlID0gZWxlbWVudC5maWxlO1xyXG4gICAgICBpZiAoIWZpbGUpIGNvbnRpbnVlO1xyXG5cclxuICAgICAgLy8gQ2hlY2sgZmlsZSBzaXplXHJcbiAgICAgIGlmICghdGhpcy52YWxpZGF0ZUluZGl2aWR1YWxGaWxlU2l6ZShmaWxlKSkge1xyXG4gICAgICAgIHRoaXMuc2V0Rm9ybUNvbnRyb2xFcnJvcignRmlsZU1heFNpemVJbk1CJywgYCR7dGhpcy5vcHRpb25zLmZpbGVNYXhTaXplSW5NQn1NQmApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBDaGVjayBmaWxlIHR5cGVcclxuICAgICAgaWYgKCF0aGlzLnZhbGlkYXRlSW5kaXZpZHVhbEZpbGVUeXBlKGZpbGUpKSB7XHJcbiAgICAgICAgdGhpcy5zZXRGb3JtQ29udHJvbEVycm9yKCdUb29sVGlwVHlwZUVycm9yJywgdGhpcy50b29sVGlwVHlwZUFycmF5KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB1cGRhdGVNdWx0aXBsZUZpbGVNb2RlbCgpOiB2b2lkIHtcclxuICAgIHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwuY29ycmVsYXRpb25JRF9HVUlEID0gdGhpcy5vcHRpb25zLnZhbHVlPy5jb3JyZWxhdGlvbklEX0dVSUQ7XHJcblxyXG5cclxuXHJcbiAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbC5zZXRWYWx1ZSh0aGlzLm11bHRpcGxlRmlsZVVwbG9hZE1vZGVsLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XHJcbiAgICB0aGlzLmdyb3VwLmdldCh0aGlzLm9wdGlvbnMubmFtZSk/LnNldFZhbHVlKHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWwsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcclxuICAgIHRoaXMub3B0aW9ucy52YWx1ZSA9IHRoaXMubXVsdGlwbGVGaWxlVXBsb2FkTW9kZWw7XHJcbiAgfVxyXG4gIHJlbW92ZVJlcXVpcmVkVmFsaWRhdGlvbiA9ICgpOiB2b2lkID0+IHtcclxuICAgIHRoaXMuY29udHJvbFV0aWxpdHkucmVtb3ZlUmVxdWlyZWRWYWxpZGF0aW9uKFxyXG4gICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbCxcclxuICAgICAgdGhpcy52YWxpZGF0aW9uUnVsZXMsXHJcbiAgICAgIHRoaXMub3B0aW9uc1xyXG4gICAgKTtcclxuICB9O1xyXG5cclxuICByZW1vdmVSZXF1aXJlZFZhbGlkYXRvck9ubHkgPSAoKTogdm9pZCA9PiB7XHJcbiAgICB0aGlzLnZhbGlkYXRpb25SdWxlcyA9IHRoaXMudmFsaWRhdGlvblJ1bGVzLmZpbHRlcih2YWxpZGF0b3IgPT4gdmFsaWRhdG9yICE9PSBWYWxpZGF0b3JzLnJlcXVpcmVkKTtcclxuICAgIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnNldFZhbGlkYXRvcnModGhpcy52YWxpZGF0aW9uUnVsZXMpO1xyXG4gICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSgpO1xyXG4gIH07XHJcblxyXG4gIGFkZFJlcXVpcmVkVmFsaWRhdGlvbiA9ICgpOiB2b2lkID0+IHtcclxuICAgIHRoaXMuY29udHJvbFV0aWxpdHkuYWRkUmVxdWlyZWRWYWxpZGF0aW9uKFxyXG4gICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbCxcclxuICAgICAgdGhpcy52YWxpZGF0aW9uUnVsZXMsXHJcbiAgICAgIHRoaXMub3B0aW9uc1xyXG4gICAgKTtcclxuICB9O1xyXG5cclxuICByZW1vdmVDdXN0b21WYWxpZGF0aW9uID0gKGN1c3RvbVZhbGlkYXRpb246IGFueSk6IHZvaWQgPT4ge1xyXG4gICAgdGhpcy5jb250cm9sVXRpbGl0eS5yZW1vdmVDdXN0b21WYWxpZGF0aW9uKFxyXG4gICAgICB0aGlzLmZpbGVVcGxvYWRGb3JtQ29udHJvbCxcclxuICAgICAgdGhpcy52YWxpZGF0aW9uUnVsZXMsXHJcbiAgICAgIGN1c3RvbVZhbGlkYXRpb25cclxuICAgICk7XHJcbiAgfTtcclxuXHJcbiAgYWRkQ3VzdG9tVmFsaWRhdGlvbiA9IChjdXN0b21WYWxpZGF0aW9uOiBhbnkpOiB2b2lkID0+IHtcclxuICAgIHRoaXMuY29udHJvbFV0aWxpdHkuYWRkQ3VzdG9tVmFsaWRhdGlvbihcclxuICAgICAgdGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wsXHJcbiAgICAgIHRoaXMudmFsaWRhdGlvblJ1bGVzLFxyXG4gICAgICBjdXN0b21WYWxpZGF0aW9uXHJcbiAgICApO1xyXG4gIH07XHJcblxyXG4gIGlzVmFsaWQgPSAoKTogYm9vbGVhbiA9PiB7XHJcbiAgICB0aGlzLmNvbnRyb2xVdGlsaXR5LmlzVmFsaWQodGhpcy5maWxlVXBsb2FkRm9ybUNvbnRyb2wpO1xyXG4gICAgcmV0dXJuIHRoaXMuZmlsZVVwbG9hZEZvcm1Db250cm9sLnZhbGlkO1xyXG4gIH07XHJcbiAgY29udmVydFNpemVUb01CKHNpemU6IG51bWJlcik6IG51bWJlciB7XHJcbiAgICBpZiAoc2l6ZSA9PT0gMCkge1xyXG4gICAgICByZXR1cm4gMDtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBCWVRFU19UT19NQl9BQ0NVUkFURSA9IDEwMjQgKiAxMDI0O1xyXG4gICAgY29uc3QgbWVnYWJ5dGVzID0gc2l6ZSAvIEJZVEVTX1RPX01CX0FDQ1VSQVRFO1xyXG4gICAgcmV0dXJuIE1hdGgucm91bmQobWVnYWJ5dGVzICogMTAwKSAvIDEwMDtcclxuICB9XHJcblxyXG4gIHRyYWNrQnlGdW5jdGlvbihpbmRleDogbnVtYmVyLCBpdGVtOiBGaWxlSXRlbSk6IGFueSB7XHJcbiAgICByZXR1cm4gaXRlbS5fZmlsZSA/IGl0ZW0uX2ZpbGUubmFtZSArIGl0ZW0uX2ZpbGUuc2l6ZSA6IGluZGV4O1xyXG4gIH1cclxuXHJcbiAgc2hvdWxkU2hvd0ZpbGVMaXN0KCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMudXBsb2FkZXI/LnF1ZXVlICYmIHRoaXMudXBsb2FkZXIucXVldWUubGVuZ3RoID4gMDtcclxuICB9XHJcblxyXG4gIGlzRG93bmxvYWRFbmFibGVkKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRydWU7XHJcbiAgfVxyXG5cclxuICBpc1JlbW92ZUVuYWJsZWQoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gIXRoaXMub3B0aW9ucy5pc1JlYWRvbmx5ICYmICF0aGlzLm9wdGlvbnMuaXNEaXNhYmxlZDtcclxuICB9XHJcblxyXG4gIGdldEZpbGVEb3dubG9hZFVybChpdGVtOiBGaWxlSXRlbSk6IHN0cmluZyB8IG51bGwge1xyXG4gICAgY29uc3QgZXhpc3RpbmdVcmwgPSB0aGlzLmdldEV4aXN0aW5nRmlsZVVybChpdGVtKTtcclxuICAgIGlmIChleGlzdGluZ1VybCkge1xyXG4gICAgICByZXR1cm4gZXhpc3RpbmdVcmw7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlRmlsZVVybChpdGVtKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0RXhpc3RpbmdGaWxlVXJsKGl0ZW06IEZpbGVJdGVtKTogc3RyaW5nIHwgbnVsbCB7XHJcbiAgICByZXR1cm4gKGl0ZW0/LmZpbGUgYXMgYW55KT8udXJsIHx8XHJcbiAgICAgIChpdGVtPy5fZmlsZSBhcyBhbnkpPy51cmwgfHxcclxuICAgICAgKGl0ZW0gYXMgYW55KT8udXJsIHx8XHJcbiAgICAgIChpdGVtPy5maWxlIGFzIGFueSk/LnJhd0ZpbGU/LnVybCB8fFxyXG4gICAgICAoaXRlbT8uX2ZpbGUgYXMgYW55KT8ucmF3RmlsZT8udXJsIHx8XHJcbiAgICAgIG51bGw7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNyZWF0ZUZpbGVVcmwoaXRlbTogRmlsZUl0ZW0pOiBzdHJpbmcgfCBudWxsIHtcclxuICAgIGNvbnN0IGZpbGVOYW1lID0gdGhpcy5nZXRGaWxlTmFtZShpdGVtKTtcclxuICAgIGNvbnN0IGZpbGVUeXBlID0gaXRlbT8uZmlsZT8udHlwZSB8fCAoaXRlbT8uX2ZpbGUgYXMgYW55KT8udHlwZTtcclxuXHJcbiAgICBjb25zdCBvcmlnaW5hbEZpbGUgPSAoaXRlbT8uX2ZpbGUgYXMgYW55KT8ucmF3RmlsZSB8fCAoaXRlbT8uZmlsZSBhcyBhbnkpPy5yYXdGaWxlO1xyXG4gICAgaWYgKG9yaWdpbmFsRmlsZSAmJiBvcmlnaW5hbEZpbGUgaW5zdGFuY2VvZiBGaWxlKSB7XHJcbiAgICAgIHJldHVybiBVUkwuY3JlYXRlT2JqZWN0VVJMKG9yaWdpbmFsRmlsZSk7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgYmFzZTY0RGF0YSA9IHR5cGVvZiBvcmlnaW5hbEZpbGUgPT09ICdzdHJpbmcnID8gb3JpZ2luYWxGaWxlIDogbnVsbDtcclxuICAgIGlmIChiYXNlNjREYXRhICYmIGZpbGVOYW1lKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLmNyZWF0ZUJsb2JVcmxXaXRoRmlsZW5hbWUoYmFzZTY0RGF0YSwgZmlsZVR5cGUsIGZpbGVOYW1lKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBmaWxlSWQgPSAoaXRlbT8uX2ZpbGUgYXMgYW55KT8uWydpRF9HVUlEJ107XHJcbiAgICBpZiAoZmlsZUlkICYmIHRoaXMub3B0aW9ucy5pc1VwbG9hZEZpbGVBc3luYykge1xyXG4gICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3REb3dubG9hZFVybChmaWxlSWQsIGZpbGVOYW1lKTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY3JlYXRlQmxvYlVybFdpdGhGaWxlbmFtZShiYXNlNjREYXRhOiBzdHJpbmcsIGZpbGVUeXBlOiBzdHJpbmcsIGZpbGVOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgdHJ5IHtcclxuICAgICAgY29uc3QgYnl0ZUNoYXJhY3RlcnMgPSBhdG9iKGJhc2U2NERhdGEpO1xyXG4gICAgICBjb25zdCBieXRlTnVtYmVycyA9IG5ldyBBcnJheShieXRlQ2hhcmFjdGVycy5sZW5ndGgpO1xyXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJ5dGVDaGFyYWN0ZXJzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgYnl0ZU51bWJlcnNbaV0gPSBieXRlQ2hhcmFjdGVycy5jaGFyQ29kZUF0KGkpO1xyXG4gICAgICB9XHJcbiAgICAgIGNvbnN0IGJ5dGVBcnJheSA9IG5ldyBVaW50OEFycmF5KGJ5dGVOdW1iZXJzKTtcclxuICAgICAgY29uc3QgYmxvYiA9IG5ldyBCbG9iKFtieXRlQXJyYXldLCB7IHR5cGU6IGZpbGVUeXBlIHx8ICdhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0nIH0pO1xyXG5cclxuICAgICAgcmV0dXJuIFVSTC5jcmVhdGVPYmplY3RVUkwoYmxvYik7XHJcbiAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICBjb25zdCBlcnJvck1zZyA9IHRoaXMudXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSgnRXJyb3JDcmVhdGluZ0Jsb2JVcmwnKTtcclxuICAgICAgY29uc29sZS5lcnJvcihlcnJvck1zZywgZXJyb3IpO1xyXG4gICAgICByZXR1cm4gYGRhdGE6JHtmaWxlVHlwZSB8fCAnYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtJ307YmFzZTY0LCR7YmFzZTY0RGF0YX1gO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjb25zdHJ1Y3REb3dubG9hZFVybChmaWxlSWQ6IHN0cmluZywgZmlsZU5hbWU/OiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgZG93bmxvYWRCYXNlVXJsID0gKHRoaXMub3B0aW9ucyBhcyBhbnkpLmRvd25sb2FkQmFzZVVybDtcclxuICAgIGxldCB1cmw6IHN0cmluZztcclxuXHJcbiAgICBpZiAoZG93bmxvYWRCYXNlVXJsKSB7XHJcbiAgICAgIHVybCA9IGAke2Rvd25sb2FkQmFzZVVybH0vJHtmaWxlSWR9YDtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHVybCA9IGAvYXBpL2ZpbGVzL2Rvd25sb2FkLyR7ZmlsZUlkfWA7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGZpbGVOYW1lKSB7XHJcbiAgICAgIGNvbnN0IHNlcGFyYXRvciA9IHVybC5pbmNsdWRlcygnPycpID8gJyYnIDogJz8nO1xyXG4gICAgICB1cmwgKz0gYCR7c2VwYXJhdG9yfWZpbGVuYW1lPSR7ZW5jb2RlVVJJQ29tcG9uZW50KGZpbGVOYW1lKX1gO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB1cmw7XHJcbiAgfVxyXG5cclxuICBnZXRGaWxlTmFtZShpdGVtOiBGaWxlSXRlbSk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gaXRlbT8uZmlsZT8ubmFtZSB8fCAoaXRlbT8uX2ZpbGUgYXMgYW55KT8ubmFtZSB8fCAnZmlsZSc7XHJcbiAgfVxyXG5cclxuICBkb3dubG9hZEZpbGUoaXRlbTogRmlsZUl0ZW0pOiB2b2lkIHtcclxuICAgIGNvbnN0IGRvd25sb2FkSW5mbyA9IHRoaXMucHJlcGFyZUZpbGVEb3dubG9hZChpdGVtKTtcclxuXHJcbiAgICBpZiAoIWRvd25sb2FkSW5mby51cmwpIHtcclxuICAgICAgdGhpcy5oYW5kbGVEb3dubG9hZEVycm9yKGRvd25sb2FkSW5mby5maWxlTmFtZSk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmV4ZWN1dGVGaWxlRG93bmxvYWQoZG93bmxvYWRJbmZvLnVybCwgZG93bmxvYWRJbmZvLmZpbGVOYW1lKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcHJlcGFyZUZpbGVEb3dubG9hZChpdGVtOiBGaWxlSXRlbSk6IERvd25sb2FkSW5mbyB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICB1cmw6IHRoaXMuZ2V0RmlsZURvd25sb2FkVXJsKGl0ZW0pLFxyXG4gICAgICBmaWxlTmFtZTogdGhpcy5nZXRGaWxlTmFtZShpdGVtKVxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgaGFuZGxlRG93bmxvYWRFcnJvcihmaWxlTmFtZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBjb25zdCBlcnJvck1zZyA9IHRoaXMudXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSgnTm9Eb3dubG9hZFVybEF2YWlsYWJsZScpXHJcbiAgICAgIC5yZXBsYWNlKCd7ZmlsZU5hbWV9JywgZmlsZU5hbWUpO1xyXG4gICAgY29uc29sZS5lcnJvcihlcnJvck1zZyk7XHJcblxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBleGVjdXRlRmlsZURvd25sb2FkKHVybDogc3RyaW5nLCBmaWxlTmFtZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBjb25zdCBsaW5rID0gdGhpcy5jcmVhdGVEb3dubG9hZExpbmsodXJsLCBmaWxlTmFtZSk7XHJcbiAgICB0aGlzLnRyaWdnZXJEb3dubG9hZChsaW5rKTtcclxuICAgIHRoaXMuY2xlYW51cEJsb2JVcmwodXJsKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY3JlYXRlRG93bmxvYWRMaW5rKHVybDogc3RyaW5nLCBmaWxlTmFtZTogc3RyaW5nKTogSFRNTEFuY2hvckVsZW1lbnQge1xyXG4gICAgY29uc3QgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcclxuICAgIGxpbmsuaHJlZiA9IHVybDtcclxuICAgIGxpbmsuZG93bmxvYWQgPSBmaWxlTmFtZTtcclxuICAgIGxpbmsuc3R5bGUuZGlzcGxheSA9ICdub25lJztcclxuICAgIHJldHVybiBsaW5rO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB0cmlnZ2VyRG93bmxvYWQobGluazogSFRNTEFuY2hvckVsZW1lbnQpOiB2b2lkIHtcclxuICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQobGluayk7XHJcbiAgICBsaW5rLmNsaWNrKCk7XHJcbiAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGxpbmspO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjbGVhbnVwQmxvYlVybCh1cmw6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgaWYgKHVybC5zdGFydHNXaXRoKCdibG9iOicpKSB7XHJcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgIFVSTC5yZXZva2VPYmplY3RVUkwodXJsKTtcclxuICAgICAgfSwgMTAwKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgdHJhY2tNZW1vcnlVc2FnZShmaWxlU2l6ZTogbnVtYmVyKTogdm9pZCB7XHJcbiAgICB0aGlzLmN1cnJlbnRNZW1vcnlVc2FnZSArPSBmaWxlU2l6ZTtcclxuXHJcbiAgICAvLyBJZiBtZW1vcnkgdXNhZ2UgZXhjZWVkcyBsaW1pdCwgY2xlYW4gdXAgb2xkIGZpbGVzXHJcbiAgICBpZiAodGhpcy5jdXJyZW50TWVtb3J5VXNhZ2UgPiB0aGlzLk1BWF9NRU1PUllfVVNBR0UpIHtcclxuICAgICAgdGhpcy5jbGVhbnVwT2xkRmlsZXMoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgY2xlYW51cE9sZEZpbGVzKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMudXBsb2FkZXI/LnF1ZXVlICYmIHRoaXMudXBsb2FkZXIucXVldWUubGVuZ3RoID4gMCkge1xyXG4gICAgICAvLyBSZW1vdmUgb2xkZXN0IGZpbGVzIHRvIGZyZWUgbWVtb3J5XHJcbiAgICAgIGNvbnN0IG9sZGVzdEZpbGUgPSB0aGlzLnVwbG9hZGVyLnF1ZXVlLnNoaWZ0KCk7XHJcbiAgICAgIGlmIChvbGRlc3RGaWxlKSB7XHJcbiAgICAgICAgY29uc3QgdXJsID0gdGhpcy5nZXRGaWxlRG93bmxvYWRVcmwob2xkZXN0RmlsZSk7XHJcbiAgICAgICAgaWYgKHVybCAmJiB1cmwuc3RhcnRzV2l0aCgnYmxvYjonKSkge1xyXG4gICAgICAgICAgdGhpcy5jbGVhbnVwQmxvYlVybCh1cmwpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLmN1cnJlbnRNZW1vcnlVc2FnZSAtPSAob2xkZXN0RmlsZS5maWxlPy5zaXplIHx8IDApO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNsZWFudXBFdmVudExpc3RlbmVycygpOiB2b2lkIHtcclxuICAgIC8vIENsZWFyIGZpbGUgaW5wdXQgcmVmZXJlbmNlc1xyXG4gICAgaWYgKHRoaXMuZmlsZUlucHV0Py5uYXRpdmVFbGVtZW50KSB7XHJcbiAgICAgIHRoaXMuZmlsZUlucHV0Lm5hdGl2ZUVsZW1lbnQudmFsdWUgPSAnJztcclxuICAgIH1cclxuXHJcbiAgICAvLyBDbGVhciB1cGxvYWRlciBxdWV1ZSB0byBwcmV2ZW50IG1lbW9yeSBsZWFrc1xyXG4gICAgaWYgKHRoaXMudXBsb2FkZXI/LnF1ZXVlKSB7XHJcbiAgICAgIHRoaXMudXBsb2FkZXIucXVldWUgPSBbXTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgY2xlYW51cFVwbG9hZGVyUXVldWUoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy51cGxvYWRlcj8ucXVldWUpIHtcclxuICAgICAgLy8gQ2xlYXIgYWxsIGl0ZW1zIGFuZCB0aGVpciBhc3NvY2lhdGVkIHJlc291cmNlc1xyXG4gICAgICB0aGlzLnVwbG9hZGVyLnF1ZXVlLmZvckVhY2goaXRlbSA9PiB7XHJcbiAgICAgICAgLy8gQ2xlYW4gdXAgYmxvYiBVUkxzXHJcbiAgICAgICAgY29uc3QgdXJsID0gdGhpcy5nZXRGaWxlRG93bmxvYWRVcmwoaXRlbSk7XHJcbiAgICAgICAgaWYgKHVybCAmJiB1cmwuc3RhcnRzV2l0aCgnYmxvYjonKSkge1xyXG4gICAgICAgICAgdGhpcy5jbGVhbnVwQmxvYlVybCh1cmwpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gQ2xlYXIgZmlsZSByZWZlcmVuY2VzXHJcbiAgICAgICAgaWYgKGl0ZW0uX2ZpbGUpIHtcclxuICAgICAgICAgIGl0ZW0uX2ZpbGUgPSBudWxsIGFzIGFueTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGl0ZW0uZmlsZSkge1xyXG4gICAgICAgICAgaXRlbS5maWxlID0gbnVsbCBhcyBhbnk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIC8vIENsZWFyIHRoZSBxdWV1ZVxyXG4gICAgICB0aGlzLnVwbG9hZGVyLnF1ZXVlID0gW107XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIC8vIENsZWFuIHVwIHN1YnNjcmlwdGlvbnNcclxuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy51bnN1YnNjcmliZSgpO1xyXG5cclxuICAgIC8vIENsZWFuIHVwIHVwbG9hZGVyIHF1ZXVlXHJcbiAgICB0aGlzLmNsZWFudXBVcGxvYWRlclF1ZXVlKCk7XHJcblxyXG4gICAgLy8gQ2xlYW4gdXAgZXZlbnQgbGlzdGVuZXJzXHJcbiAgICB0aGlzLmNsZWFudXBFdmVudExpc3RlbmVycygpO1xyXG5cclxuICAgIC8vIENsZWFuIHVwIGJsb2IgVVJMc1xyXG4gICAgaWYgKHRoaXMudXBsb2FkZXI/LnF1ZXVlKSB7XHJcbiAgICAgIHRoaXMudXBsb2FkZXIucXVldWUuZm9yRWFjaChpdGVtID0+IHtcclxuICAgICAgICBjb25zdCB1cmwgPSB0aGlzLmdldEZpbGVEb3dubG9hZFVybChpdGVtKTtcclxuICAgICAgICBpZiAodXJsICYmIHVybC5zdGFydHNXaXRoKCdibG9iOicpKSB7XHJcbiAgICAgICAgICBVUkwucmV2b2tlT2JqZWN0VVJMKHVybCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgY2hlY2tBbmRDbGVhck1heEZpbGVDb3VudFZhbGlkYXRpb24oKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5tYXhOb09mRmlsZXMgfHwgdGhpcy5vcHRpb25zLm1heE5vT2ZGaWxlcyA8PSAwKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBjdXJyZW50UXVldWVMZW5ndGggPSB0aGlzLnVwbG9hZGVyLnF1ZXVlLmxlbmd0aDtcclxuICAgIGlmIChjdXJyZW50UXVldWVMZW5ndGggPD0gdGhpcy5vcHRpb25zLm1heE5vT2ZGaWxlcykge1xyXG4gICAgICB0aGlzLmNsZWFyRmlsZUNvdW50RXJyb3IoJ01heEZpbGVDb3VudFZhbGlkYXRpb25LZXknKTtcclxuICAgIH1cclxuICB9XHJcblxyXG5cclxufVxyXG4iLCI8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cCBiYnNmLWNvbnRyb2wgYmJzZi1maWxlLXVwbG9hZFwiIFtmb3JtR3JvdXBdPVwiZ3JvdXBcIj5cclxuICA8ZGl2IFtuZ0NsYXNzXT1cIm9wdGlvbnMudmlld1R5cGUgPT09IDEgPyAnYmJzZi12ZXJ0aWNhbCcgOiAnYmJzZi1ob3Jpem9udGFsJ1wiPlxyXG4gICAgPCEtLSBMYWJlbCAtLT5cclxuICAgIDxsYWJlbCBbaGlkZGVuXT1cIm9wdGlvbnMuaGlkZUxhYmVsXCIgY2xhc3M9XCJiYnNmLWxhYmVsIHt7IG9wdGlvbnMubGFiZWxFeHRyYUNsYXNzZXMgfX1cIj5cclxuICAgICAge3sgb3B0aW9ucy5sYWJlbFZhbHVlIH19XHJcbiAgICAgIDwhLS0gUmVxdWlyZWQgYXN0ZXJpc2sgLS0+XHJcbiAgICAgIDxzcGFuICpuZ0lmPVwib3B0aW9ucy5pc1JlcXVpcmVkICYmICFvcHRpb25zLmlzUmVhZG9ubHkgJiYgKG9wdGlvbnMuc2hvd0FzdGVyaXNrIHx8IHRydWUpXCJcclxuICAgICAgICBjbGFzcz1cInRleHQtZGFuZ2VyXCI+Kjwvc3Bhbj5cclxuICAgIDwvbGFiZWw+XHJcbiAgICA8IS0tIERyb3Agem9uZSBlbmFibGVkIC0tPlxyXG4gICAgPGRpdiBuZzJGaWxlRHJvcCBjbGFzcz1cImJic2YtaW5wdXQtY29udGFpbmVyIHt7IG9wdGlvbnMuZXh0cmFDbGFzc2VzIH19XCJcclxuICAgICAgKm5nSWY9XCJvcHRpb25zLmlzRHJvcFpvbmUgJiYgIWlzSGlkZUlucHV0KCkgJiYgIW9wdGlvbnMuaXNSZWFkb25seVwiXHJcbiAgICAgIFtuZ0NsYXNzXT1cInsgJ2Fub3RoZXItZmlsZS1vdmVyLWNsYXNzJzogaGFzQW5vdGhlckRyb3Bab25lT3ZlciB9XCIgKG9uRmlsZURyb3ApPVwib25GaWxlQ2hhbmdlKClcIlxyXG4gICAgICAoZmlsZU92ZXIpPVwiZmlsZU92ZXJBbm90aGVyKCRldmVudClcIiBbdXBsb2FkZXJdPVwidXBsb2FkZXJcIiBbYWNjZXB0XT1cImFjY2VwdGVkVHlwZVwiIFtpZF09XCJvcHRpb25zLm5hbWVcIlxyXG4gICAgICBbYXR0ci5tdWx0aXBsZV09XCJvcHRpb25zLmlzTXVsdGlwbGVGaWxlID8gJ211bHRpcGxlJyA6IG51bGxcIlxyXG4gICAgICBbY2xhc3MuaXMtaW52YWxpZF09XCJmaWxlVXBsb2FkRm9ybUNvbnRyb2wuaW52YWxpZCAmJiBmaWxlVXBsb2FkRm9ybUNvbnRyb2wudG91Y2hlZFwiXHJcbiAgICAgIChjbGljayk9XCJmaWxlSW5wdXRDb250cm9sLmNsaWNrKClcIj5cclxuXHJcbiAgICAgIDxkaXYgY2xhc3M9XCJkcm9wem9uZS1sYWJlbFwiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJzdmctYW5kLXZhbGlkYXRpb25cIj5cclxuICAgICAgICAgIDwhLS0gVXBsb2FkIGljb24gLS0+XHJcbiAgICAgICAgICA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB3aWR0aD1cIjcwXCIgaGVpZ2h0PVwiNzBcIiB2aWV3Qm94PVwiMCAwIDcwIDcwXCIgZmlsbD1cIm5vbmVcIj5cclxuICAgICAgICAgICAgPHBhdGggb3BhY2l0eT1cIjAuNFwiXHJcbiAgICAgICAgICAgICAgZD1cIk01OC4zMzMgNDguODMzMkM2MS44OTU3IDQ1Ljg5MDggNjQuMTY2MyA0MS40Mzk3IDY0LjE2NjMgMzYuNDU4M0M2NC4xNjYzIDI3LjU5ODggNTYuOTg0MyAyMC40MTY3IDQ4LjEyNDcgMjAuNDE2N0M0Ny40ODc0IDIwLjQxNjcgNDYuODkxMiAyMC4wODQyIDQ2LjU2NzUgMTkuNTM1MUM0Mi43NjQxIDEzLjA4MDggMzUuNzQxNyA4Ljc1IDI3LjcwOCA4Ljc1QzE1LjYyNjggOC43NSA1LjgzMzAxIDE4LjU0MzggNS44MzMwMSAzMC42MjVDNS44MzMwMSAzNi42NTExIDguMjY5NzQgNDIuMTA4MiAxMi4yMTE2IDQ2LjA2NDRcIlxyXG4gICAgICAgICAgICAgIHN0cm9rZT1cIiM0QjU0ODlcIiBzdHJva2Utd2lkdGg9XCIyXCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIgLz5cclxuICAgICAgICAgICAgPHBhdGggZD1cIk0yMy4zMzMgNDYuNjY2N0wzNC45OTk3IDM1TTM0Ljk5OTcgMzVMNDYuNjY2MyA0Ni42NjY3TTM0Ljk5OTcgMzVWNjEuMjVcIiBzdHJva2U9XCIjNEI1NDg5XCJcclxuICAgICAgICAgICAgICBzdHJva2Utd2lkdGg9XCIyXCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIgLz5cclxuICAgICAgICAgIDwvc3ZnPlxyXG5cclxuICAgICAgICAgIDwhLS0gSW5zdHJ1Y3Rpb24gdGV4dCAtLT5cclxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJiYnNmLXZhbGlkYXRpb24tbXNnIHZhbGlkYXRpb24tbXNnLWhlYWRlciB0ZXh0LWNlbnRlclwiPlxyXG4gICAgICAgICAgICB7eyB1dGlsaXR5U2VydmljZS5nZXRSZXNvdXJjZVZhbHVlKCdEcmFnQW5kRHJvcEhlcmUnKSB9fVxyXG4gICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgPCEtLSBWYWxpZGF0aW9uIG1lc3NhZ2VzIC0tPlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJic2YtdmFsaWRhdGlvbi1tc2cgdGV4dC1jZW50ZXJcIiAqbmdJZj1cInZhbGlkYXRpb25NZXNzYWdlXCIgW2lubmVySFRNTF09XCJ2YWxpZGF0aW9uTWVzc2FnZVwiPlxyXG4gICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJic2YtdmFsaWRhdGlvbi1tc2cgdGV4dC1jZW50ZXIgdGV4dC1kYW5nZXJcIlxyXG4gICAgICAgICAgICAqbmdJZj1cInZhbGlkYXRpb25Db3VudE1lc3NhZ2UgJiYgb3B0aW9ucy5pc011bHRpcGxlRmlsZSAmJiBvcHRpb25zLm1heE5vT2ZGaWxlcyA+IDBcIlxyXG4gICAgICAgICAgICBbaW5uZXJIVE1MXT1cInZhbGlkYXRpb25Db3VudE1lc3NhZ2VcIj5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuXHJcbiAgICAgIDwhLS0gSGlkZGVuIGZpbGUgaW5wdXQgLS0+XHJcbiAgICAgIDxpbnB1dCBuZzJGaWxlU2VsZWN0IFt1cGxvYWRlcl09XCJ1cGxvYWRlclwiIFthY2NlcHRdPVwiYWNjZXB0ZWRUeXBlXCJcclxuICAgICAgICBjbGFzcz1cImZpbGVTZWxlY3RvciBjdXN0b21GaWxlVXBsb2FkUGxhY21lbnQgaGlkZGVuIHYtcmVxdWlyZWQtbXVsdGlwbGVmaWxlcyBkLW5vbmVcIlxyXG4gICAgICAgIFthdHRyLm11bHRpcGxlXT1cIm9wdGlvbnMuaXNNdWx0aXBsZUZpbGUgPyAnbXVsdGlwbGUnIDogbnVsbFwiIG5hbWU9XCJmaWxlXCIgdHlwZT1cImZpbGVcIiBhdXRvY29tcGxldGU9XCJvZmZcIlxyXG4gICAgICAgIChjaGFuZ2UpPVwib25GaWxlQ2hhbmdlKClcIiBbbmdDbGFzc109XCJvcHRpb25zLnZpZXdUeXBlID09PSAxID8gJycgOiAnY29sLW1kLTknXCIgW2lkXT1cIm9wdGlvbnMubmFtZVwiXHJcbiAgICAgICAgI2ZpbGVJbnB1dENvbnRyb2wgW2NsYXNzLmlzLWludmFsaWRdPVwiZmlsZVVwbG9hZEZvcm1Db250cm9sLmludmFsaWQgJiYgZmlsZVVwbG9hZEZvcm1Db250cm9sLnRvdWNoZWRcIiAvPlxyXG4gICAgPC9kaXY+XHJcbiAgICA8IS0tIENsaWNrIHRvIHVwbG9hZCAobm8gZHJvcCB6b25lKSAtLT5cclxuICAgIDxkaXYgY2xhc3M9XCJiYnNmLWlucHV0LWNvbnRhaW5lclwiICpuZ0lmPVwiIW9wdGlvbnMuaXNEcm9wWm9uZSAmJiAhaXNIaWRlSW5wdXQoKSAmJiAhb3B0aW9ucy5pc1JlYWRvbmx5XCJcclxuICAgICAgKGNsaWNrKT1cImZpbGVJbnB1dC5jbGljaygpXCI+XHJcblxyXG4gICAgICA8ZGl2IGNsYXNzPVwiZHJvcHpvbmUtbGFiZWxcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwic3ZnLWFuZC12YWxpZGF0aW9uXCI+XHJcbiAgICAgICAgICA8IS0tIFVwbG9hZCBpY29uIC0tPlxyXG4gICAgICAgICAgPHN2ZyB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgd2lkdGg9XCI3MFwiIGhlaWdodD1cIjcwXCIgdmlld0JveD1cIjAgMCA3MCA3MFwiIGZpbGw9XCJub25lXCI+XHJcbiAgICAgICAgICAgIDxwYXRoIG9wYWNpdHk9XCIwLjRcIlxyXG4gICAgICAgICAgICAgIGQ9XCJNNTguMzMzIDQ4LjgzMzJDNjEuODk1NyA0NS44OTA4IDY0LjE2NjMgNDEuNDM5NyA2NC4xNjYzIDM2LjQ1ODNDNjQuMTY2MyAyNy41OTg4IDU2Ljk4NDMgMjAuNDE2NyA0OC4xMjQ3IDIwLjQxNjdDNDcuNDg3NCAyMC40MTY3IDQ2Ljg5MTIgMjAuMDg0MiA0Ni41Njc1IDE5LjUzNTFDNDIuNzY0MSAxMy4wODA4IDM1Ljc0MTcgOC43NSAyNy43MDggOC43NUMxNS42MjY4IDguNzUgNS44MzMwMSAxOC41NDM4IDUuODMzMDEgMzAuNjI1QzUuODMzMDEgMzYuNjUxMSA4LjI2OTc0IDQyLjEwODIgMTIuMjExNiA0Ni4wNjQ0XCJcclxuICAgICAgICAgICAgICBzdHJva2U9XCIjNEI1NDg5XCIgc3Ryb2tlLXdpZHRoPVwiMlwiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiIC8+XHJcbiAgICAgICAgICAgIDxwYXRoIGQ9XCJNMjMuMzMzIDQ2LjY2NjdMMzQuOTk5NyAzNU0zNC45OTk3IDM1TDQ2LjY2NjMgNDYuNjY2N00zNC45OTk3IDM1VjYxLjI1XCIgc3Ryb2tlPVwiIzRCNTQ4OVwiXHJcbiAgICAgICAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMlwiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiIC8+XHJcbiAgICAgICAgICA8L3N2Zz5cclxuXHJcbiAgICAgICAgICA8IS0tIFVwbG9hZCB0ZXh0IC0tPlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJic2YtdmFsaWRhdGlvbi1tc2cgdGV4dC1jZW50ZXJcIj5cclxuICAgICAgICAgICAge3sgdXRpbGl0eVNlcnZpY2UuZ2V0UmVzb3VyY2VWYWx1ZSgnVXBsb2FkJykgfX1cclxuICAgICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICAgIDwhLS0gVmFsaWRhdGlvbiBtZXNzYWdlcyAtLT5cclxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJiYnNmLXZhbGlkYXRpb24tbXNnIHRleHQtY2VudGVyXCIgKm5nSWY9XCJ2YWxpZGF0aW9uTWVzc2FnZVwiIFtpbm5lckhUTUxdPVwidmFsaWRhdGlvbk1lc3NhZ2VcIj5cclxuICAgICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJiYnNmLXZhbGlkYXRpb24tbXNnIHRleHQtY2VudGVyIHRleHQtZGFuZ2VyXCJcclxuICAgICAgICAgICAgKm5nSWY9XCJ2YWxpZGF0aW9uQ291bnRNZXNzYWdlICYmIG9wdGlvbnMuaXNNdWx0aXBsZUZpbGUgJiYgb3B0aW9ucy5tYXhOb09mRmlsZXMgPiAwXCJcclxuICAgICAgICAgICAgW2lubmVySFRNTF09XCJ2YWxpZGF0aW9uQ291bnRNZXNzYWdlXCI+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcblxyXG4gICAgICA8IS0tIEhpZGRlbiBmaWxlIGlucHV0IC0tPlxyXG4gICAgICA8aW5wdXQgbmcyRmlsZVNlbGVjdCBbdXBsb2FkZXJdPVwidXBsb2FkZXJcIiBbYWNjZXB0XT1cImFjY2VwdGVkVHlwZVwiXHJcbiAgICAgICAgY2xhc3M9XCJmaWxlU2VsZWN0b3IgY3VzdG9tRmlsZVVwbG9hZFBsYWNtZW50IGhpZGRlbiB2LXJlcXVpcmVkLW11bHRpcGxlZmlsZXMgZC1ub25lXCJcclxuICAgICAgICBbYXR0ci5tdWx0aXBsZV09XCJvcHRpb25zLmlzTXVsdGlwbGVGaWxlID8gJ211bHRpcGxlJyA6IG51bGxcIiBuYW1lPVwiZmlsZVwiIHR5cGU9XCJmaWxlXCIgYXV0b2NvbXBsZXRlPVwib2ZmXCJcclxuICAgICAgICAoY2hhbmdlKT1cIm9uRmlsZUNoYW5nZSgpXCIgW25nQ2xhc3NdPVwib3B0aW9ucy52aWV3VHlwZSA9PT0gMSA/ICcnIDogJ2NvbC1tZC05J1wiIFtpZF09XCJvcHRpb25zLm5hbWVcIiAjZmlsZUlucHV0XHJcbiAgICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwiZmlsZVVwbG9hZEZvcm1Db250cm9sLmludmFsaWQgJiYgZmlsZVVwbG9hZEZvcm1Db250cm9sLnRvdWNoZWRcIiAvPlxyXG4gICAgPC9kaXY+XHJcbiAgICA8IS0tIFJlYWQtb25seSBzdGF0ZSB3aXRoIG5vIGZpbGVzIC0tPlxyXG4gICAgPGRpdiAqbmdJZj1cIm9wdGlvbnMuaXNSZWFkb25seSAmJiAoIW9wdGlvbnMudmFsdWUgfHwgKHVwbG9hZGVyLnF1ZXVlICYmIHVwbG9hZGVyLnF1ZXVlLmxlbmd0aCA9PT0gMCkpXCI+XHJcbiAgICAgIDxzcGFuIGNsYXNzPVwicmVhZG9ubHktdmlld1wiPnt7IHV0aWxpdHlTZXJ2aWNlLmdldFJlc291cmNlVmFsdWUoJ05BJykgfX08L3NwYW4+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuICA8IS0tIFVwbG9hZGVkIGZpbGVzIGxpc3QgLS0+XHJcbiAgPGRpdiBjbGFzcz1cInVwbG9hZGVkLWl0ZW1zXCIgKm5nSWY9XCJzaG91bGRTaG93RmlsZUxpc3QoKVwiPlxyXG4gICAgPGRpdiBjbGFzcz1cImJ0bi1ncm91cFwiICpuZ0Zvcj1cImxldCBpdGVtIG9mIHVwbG9hZGVyLnF1ZXVlOyB0cmFja0J5OiB0cmFja0J5RnVuY3Rpb25cIj5cclxuXHJcbiAgICAgIDwhLS0gQXN5bmMgdXBsb2FkIGNvbXBsZXRlZCBmaWxlcyAtLT5cclxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIml0ZW0/LnByb2dyZXNzID09PSAxMDAgJiYgb3B0aW9ucy5pc1VwbG9hZEZpbGVBc3luY1wiPlxyXG4gICAgICAgIDwhLS0gRG93bmxvYWQgbGluayAtIGFsd2F5cyB2aXNpYmxlIC0tPlxyXG4gICAgICAgIDxidXR0b24gKm5nSWY9XCJnZXRGaWxlRG93bmxvYWRVcmwoaXRlbSk7IGVsc2Ugbm9VcmxUZW1wbGF0ZVwiIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgY2xhc3M9XCJidG4tZG93bmxvYWQtZmlsZSBidG4tc20gYnRuLXByb2dyZXNzLXVwbG9hZFwiIChjbGljayk9XCJkb3dubG9hZEZpbGUoaXRlbSlcIlxyXG4gICAgICAgICAgW3RpdGxlXT1cIidEb3dubG9hZCAnICsgZ2V0RmlsZU5hbWUoaXRlbSlcIj5cclxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZmlsZS1uYW1lXCI+e3sgZ2V0RmlsZU5hbWUoaXRlbSkgfX08L3NwYW4+XHJcbiAgICAgICAgPC9idXR0b24+XHJcblxyXG4gICAgICAgIDwhLS0gRmlsZSBuYW1lIGRpc3BsYXkgd2hlbiBubyBVUkwgYXZhaWxhYmxlIC0tPlxyXG4gICAgICAgIDxuZy10ZW1wbGF0ZSAjbm9VcmxUZW1wbGF0ZT5cclxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYnRuLWRvd25sb2FkLWZpbGUgYnRuLXNtIGJ0bi1wcm9ncmVzcy11cGxvYWRcIiBbdGl0bGVdPVwiZ2V0RmlsZU5hbWUoaXRlbSlcIj5cclxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJmaWxlLW5hbWVcIj57eyBnZXRGaWxlTmFtZShpdGVtKSB9fTwvc3Bhbj5cclxuICAgICAgICAgIDwvc3Bhbj5cclxuICAgICAgICA8L25nLXRlbXBsYXRlPlxyXG5cclxuICAgICAgICA8IS0tIFJlbW92ZSBidXR0b24gLSBvbmx5IHNob3cgd2hlbiBub3QgcmVhZG9ubHkgYW5kIG5vdCBkaXNhYmxlZCAtLT5cclxuICAgICAgICA8YnV0dG9uICpuZ0lmPVwiaXNSZW1vdmVFbmFibGVkKClcIiBjbGFzcz1cImJ0biBidG4tZG93bmxvYWQtZmlsZSBidG4tc21cIiB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgIChjbGljayk9XCJpdGVtLnJlbW92ZSgpOyByZW1vdmVGcm9tQ29udHJvbFZhbHVlKGl0ZW0pXCIgW2F0dHIuYXJpYS1sYWJlbF09XCInUmVtb3ZlICcgKyBnZXRGaWxlTmFtZShpdGVtKVwiXHJcbiAgICAgICAgICBbdGl0bGVdPVwiJ1JlbW92ZSAnICsgZ2V0RmlsZU5hbWUoaXRlbSlcIj5cclxuICAgICAgICAgIDwhLS0gRGVsZXRlIGljb24gLS0+XHJcbiAgICAgICAgICA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB3aWR0aD1cIjE0XCIgaGVpZ2h0PVwiMTRcIiB2aWV3Qm94PVwiMCAwIDE0IDE0XCIgZmlsbD1cIm5vbmVcIj5cclxuICAgICAgICAgICAgPHBhdGggb3BhY2l0eT1cIjAuNFwiXHJcbiAgICAgICAgICAgICAgZD1cIk05LjMzMzAxIDMuNzA1ODRWMy4yNjY2M0M5LjMzMzAxIDIuNjUxNjYgOS4zMzMwMSAyLjM0NDE5IDkuMjA1ODcgMi4xMDkzQzkuMDk0MDUgMS45MDI3IDguOTE1NTUgMS43MzQ3MSA4LjY5NjA0IDEuNjI5NDRDOC40NDY0NyAxLjUwOTc3IDguMTE5NzcgMS41MDk3NyA3LjQ2NjM4IDEuNTA5NzdINi41MzMwNUM1Ljg3OTY1IDEuNTA5NzcgNS41NTI5NiAxLjUwOTc3IDUuMzAzMzkgMS42Mjk0NEM1LjA4Mzg3IDEuNzM0NzEgNC45MDUzOSAxLjkwMjcgNC43OTM1NCAyLjEwOTNDNC42NjYzOCAyLjM0NDE5IDQuNjY2MzggMi42NTE2NiA0LjY2NjM4IDMuMjY2NjNWMy43MDU4NFwiXHJcbiAgICAgICAgICAgICAgc3Ryb2tlPVwiI0Q4MzczMVwiIHN0cm9rZS13aWR0aD1cIjEuNVwiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiIC8+XHJcbiAgICAgICAgICAgIDxwYXRoXHJcbiAgICAgICAgICAgICAgZD1cIk0xLjc1IDMuNzA2MDVIMTIuMjVNMTEuMDgzNCAzLjcwNjA1VjkuODU1MUMxMS4wODM0IDEwLjc3NzUgMTEuMDgzNCAxMS4yMzg3IDEwLjg5MjYgMTEuNTkxQzEwLjcyNDggMTEuOTAxIDEwLjQ1NzEgMTIuMTUyOSAxMC4xMjc4IDEyLjMxMDlDOS43NTM0NSAxMi40OTA0IDkuMjYzNDUgMTIuNDkwNCA4LjI4MzM0IDEyLjQ5MDRINS43MTY2NkM0LjczNjU4IDEyLjQ5MDQgNC4yNDY1MyAxMi40OTA0IDMuODcyMTggMTIuMzEwOUMzLjU0MjkgMTIuMTUyOSAzLjI3NTE5IDExLjkwMSAzLjEwNzQxIDExLjU5MUMyLjkxNjY2IDExLjIzODcgMi45MTY2NiAxMC43Nzc1IDIuOTE2NjYgOS44NTUxVjMuNzA2MDVcIlxyXG4gICAgICAgICAgICAgIHN0cm9rZT1cIiNEODM3MzFcIiBzdHJva2Utd2lkdGg9XCIxLjVcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIiAvPlxyXG4gICAgICAgICAgPC9zdmc+XHJcbiAgICAgICAgPC9idXR0b24+XHJcbiAgICAgIDwvbmctY29udGFpbmVyPlxyXG5cclxuICAgICAgPCEtLSBTeW5jIHVwbG9hZCBmaWxlcyAtLT5cclxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFvcHRpb25zLmlzVXBsb2FkRmlsZUFzeW5jXCI+XHJcbiAgICAgICAgPCEtLSBEb3dubG9hZCBsaW5rIC0gYWx3YXlzIHZpc2libGUgLS0+XHJcbiAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLWRvd25sb2FkLWZpbGUgYnRuLXNtXCIgKGNsaWNrKT1cImRvd25sb2FkRmlsZShpdGVtKVwiXHJcbiAgICAgICAgICBbdGl0bGVdPVwiJ0Rvd25sb2FkICcgKyBnZXRGaWxlTmFtZShpdGVtKVwiPlxyXG4gICAgICAgICAgPCEtLSBEb3dubG9hZCBpY29uIC0tPlxyXG4gICAgICAgICAgPHN2ZyB3aWR0aD1cIjI0XCIgaGVpZ2h0PVwiMjRcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgZmlsbD1cIm5vbmVcIiB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCI+XHJcbiAgICAgICAgICAgIDxwYXRoXHJcbiAgICAgICAgICAgICAgZD1cIk0yMSAyMkgzQzIuNCAyMiAyIDIxLjYgMiAyMUMyIDIwLjQgMi40IDIwIDMgMjBIMjFDMjEuNiAyMCAyMiAyMC40IDIyIDIxQzIyIDIxLjYgMjEuNiAyMiAyMSAyMlpNMTMgMTMuNFYzQzEzIDIuNCAxMi42IDIgMTIgMkMxMS40IDIgMTEgMi40IDExIDNWMTMuNEgxM1pcIlxyXG4gICAgICAgICAgICAgIGZpbGw9XCJjdXJyZW50Q29sb3JcIj48L3BhdGg+XHJcbiAgICAgICAgICAgIDxwYXRoIG9wYWNpdHk9XCIwLjNcIiBkPVwiTTcgMTMuNEgxN0wxMi43IDE3LjdDMTIuMyAxOC4xIDExLjcgMTguMSAxMS4zIDE3LjdMNyAxMy40WlwiIGZpbGw9XCJjdXJyZW50Q29sb3JcIj5cclxuICAgICAgICAgICAgPC9wYXRoPlxyXG4gICAgICAgICAgPC9zdmc+XHJcbiAgICAgICAgICA8c3BhbiBjbGFzcz1cImZpbGUtbmFtZVwiPnt7IGdldEZpbGVOYW1lKGl0ZW0pIH19PC9zcGFuPlxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG5cclxuICAgICAgICA8IS0tIFJlbW92ZSBidXR0b24gLSBvbmx5IHNob3cgd2hlbiBub3QgcmVhZG9ubHkgYW5kIG5vdCBkaXNhYmxlZCAtLT5cclxuICAgICAgICA8YnV0dG9uICpuZ0lmPVwiaXNSZW1vdmVFbmFibGVkKClcIiBjbGFzcz1cImJ0biBidG4tZG93bmxvYWQtZmlsZSBidG4tc20gYnRuLWRhbmdlclwiIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgKGNsaWNrKT1cIml0ZW0ucmVtb3ZlKCk7IHJlbW92ZUZyb21Db250cm9sVmFsdWUoaXRlbSlcIiBbYXR0ci5hcmlhLWxhYmVsXT1cIidSZW1vdmUgJyArIGdldEZpbGVOYW1lKGl0ZW0pXCJcclxuICAgICAgICAgIFt0aXRsZV09XCInUmVtb3ZlICcgKyBnZXRGaWxlTmFtZShpdGVtKVwiPlxyXG4gICAgICAgICAgPGkgY2xhc3M9XCJmYSBmYS10aW1lcyBweC0wXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgIDwvZGl2PlxyXG4gIDwvZGl2PlxyXG4gIDwhLS0gRmlsZSB1cGxvYWQgcHJvZ3Jlc3MgaW5kaWNhdG9ycyAtLT5cclxuICA8ZGl2ICpuZ0Zvcj1cImxldCBpdGVtIG9mIHVwbG9hZGVyLnF1ZXVlOyB0cmFja0J5OiB0cmFja0J5RnVuY3Rpb25cIj5cclxuICAgIDxkaXYgY2xhc3M9XCJ1cGxvYWQtaXRlbXNcIiBbbmdDbGFzc109XCJ7ICdtdC00Jzogb3B0aW9ucy5pc011bHRpcGxlRmlsZSB9XCJcclxuICAgICAgKm5nSWY9XCJpdGVtPy5wcm9ncmVzcyA8IDEwMCAmJiBvcHRpb25zLmlzVXBsb2FkRmlsZUFzeW5jICYmICFvcHRpb25zLmlzUmVhZG9ubHlcIj5cclxuXHJcbiAgICAgIDxkaXYgY2xhc3M9XCJ1cGxvYWQtaXRlbXMtdG9vbGJhclwiPlxyXG4gICAgICAgIDxoND57eyBnZXRGaWxlTmFtZShpdGVtKSB9fTwvaDQ+XHJcbiAgICAgICAgPGJ1dHRvbiAqbmdJZj1cImlzUmVtb3ZlRW5hYmxlZCgpXCIgdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuLWNhbmNlbC11cGxvYWRcIlxyXG4gICAgICAgICAgKGNsaWNrKT1cIml0ZW0ucmVtb3ZlKCk7IHJlbW92ZUZyb21Db250cm9sVmFsdWUoaXRlbSlcIlxyXG4gICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCInQ2FuY2VsIHVwbG9hZCBmb3IgJyArIGdldEZpbGVOYW1lKGl0ZW0pXCI+XHJcbiAgICAgICAgICA8IS0tIENhbmNlbCBpY29uIC0tPlxyXG4gICAgICAgICAgPHN2ZyB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgd2lkdGg9XCIxOFwiIGhlaWdodD1cIjE4XCIgdmlld0JveD1cIjAgMCAxOCAxOFwiIGZpbGw9XCJub25lXCI+XHJcbiAgICAgICAgICAgIDxnIGNsaXAtcGF0aD1cInVybCgjY2xpcDBfMTMyNF8xMzIxNilcIj5cclxuICAgICAgICAgICAgICA8cGF0aCBvcGFjaXR5PVwiMC40XCJcclxuICAgICAgICAgICAgICAgIGQ9XCJNOSAxNi41QzEzLjE0MjEgMTYuNSAxNi41IDEzLjE0MjEgMTYuNSA5QzE2LjUgNC44NTc4NiAxMy4xNDIxIDEuNSA5IDEuNUM0Ljg1Nzg2IDEuNSAxLjUgNC44NTc4NiAxLjUgOUMxLjUgMTMuMTQyMSA0Ljg1Nzg2IDE2LjUgOSAxNi41WlwiXHJcbiAgICAgICAgICAgICAgICBzdHJva2U9XCIjREJFMUYwXCIgc3Ryb2tlLXdpZHRoPVwiMlwiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiIC8+XHJcbiAgICAgICAgICAgICAgPHBhdGggZD1cIk0xMS4yNSA2Ljc1TDYuNzUgMTEuMjVNNi43NSA2Ljc1TDExLjI1IDExLjI1XCIgc3Ryb2tlPVwiI0RCRTFGMFwiIHN0cm9rZS13aWR0aD1cIjJcIlxyXG4gICAgICAgICAgICAgICAgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIgLz5cclxuICAgICAgICAgICAgPC9nPlxyXG4gICAgICAgICAgICA8ZGVmcz5cclxuICAgICAgICAgICAgICA8Y2xpcFBhdGggaWQ9XCJjbGlwMF8xMzI0XzEzMjE2XCI+XHJcbiAgICAgICAgICAgICAgICA8cmVjdCB3aWR0aD1cIjE4XCIgaGVpZ2h0PVwiMThcIiBmaWxsPVwid2hpdGVcIiAvPlxyXG4gICAgICAgICAgICAgIDwvY2xpcFBhdGg+XHJcbiAgICAgICAgICAgIDwvZGVmcz5cclxuICAgICAgICAgIDwvc3ZnPlxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8L2Rpdj5cclxuXHJcbiAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzc1wiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1iYXJcIiByb2xlPVwicHJvZ3Jlc3NiYXJcIiBbYXR0ci5hcmlhLXZhbHVlbm93XT1cIml0ZW0/LnByb2dyZXNzXCIgYXJpYS12YWx1ZW1pbj1cIjBcIlxyXG4gICAgICAgICAgYXJpYS12YWx1ZW1heD1cIjEwMFwiIFtjbGFzcy5maWxlLXVwbG9hZGVkXT1cIml0ZW0/LnByb2dyZXNzIDwgMTAwXCIgW3N0eWxlLndpZHRoLiVdPVwiaXRlbT8ucHJvZ3Jlc3NcIlxyXG4gICAgICAgICAgKm5nSWY9XCJpdGVtPy5wcm9ncmVzcyA+IDBcIj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuXHJcbiAgPCEtLSBWYWxpZGF0aW9uIGFuZCBkZXNjcmlwdGlvbiBzZWN0aW9uIC0tPlxyXG4gIDxkaXYgY2xhc3M9XCJzdWJ0ZXh0LWNvbnRhaW5lclwiICpuZ0lmPVwiIW9wdGlvbnMuaXNSZWFkb25seVwiPlxyXG4gICAgPCEtLSBWYWxpZGF0aW9uIG1lc3NhZ2VzIC0tPlxyXG4gICAgPGRpdiBjbGFzcz1cImJic2YtdmFsaWRhdGlvblwiICpuZ0lmPVwiZmlsZVVwbG9hZEZvcm1Db250cm9sLmludmFsaWQgJiYgZmlsZVVwbG9hZEZvcm1Db250cm9sLnRvdWNoZWRcIj5cclxuICAgICAgPHNwYW4gW2lubmVySFRNTF09XCJnZXRFcnJvclZhbGlkYXRpb24oZmlsZVVwbG9hZEZvcm1Db250cm9sLmVycm9ycyB8IGtleXZhbHVlKVwiPjwvc3Bhbj5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIDwhLS0gQ29udHJvbCBkZXNjcmlwdGlvbiAtLT5cclxuICAgIDxkaXYgY2xhc3M9XCJiYnNmLWNvbnRyb2wtZGVzY1wiICpuZ0lmPVwib3B0aW9ucy5sYWJlbERlc2NyaXB0aW9uXCI+XHJcbiAgICAgIHt7IG9wdGlvbnMubGFiZWxEZXNjcmlwdGlvbiB9fVxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPCEtLSBSZXNldCBlcnJvciBzdGF0ZSAtLT5cclxuICAgIDxkaXYgKm5nSWY9XCIoZ3JvdXAudmFsaWQgJiYgZ3JvdXAuZGlydHkgJiYgZ3JvdXAudG91Y2hlZCkgfHwgKGdyb3VwLnVudG91Y2hlZCAmJiBncm91cC5pbnZhbGlkICYmIGdyb3VwLmRpcnR5KVwiPlxyXG4gICAgICB7eyByZXNldEVycm9yKCkgfX1cclxuICAgIDwvZGl2PlxyXG4gIDwvZGl2PlxyXG48L2Rpdj4iXX0=
|
|
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
|