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