mmhglobal-dynamicform 2.42.0 → 2.43.0

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.
@@ -3,11 +3,11 @@ import { Component, ViewChild } from "@angular/core";
3
3
  /********** Ionic **********/
4
4
  /********** Plugin **********/
5
5
  // import { environment } from "src/environments/environment";
6
- import { take } from 'rxjs/operators';
7
- import { HttpEventType } from '@angular/common/http';
6
+ import { HttpEventType } from "@angular/common/http";
7
+ import { take } from "rxjs/operators";
8
8
  /********** Component & Service **********/
9
9
  import { InputFieldBase } from "../components/inputfieldbase.component";
10
- import { ZComponentHelper, UploadMetaData, AttachmentConfig } from "mmhglobal-zcore";
10
+ import { AttachmentConfig, UploadMetaData, ZComponentHelper, } from "mmhglobal-zcore";
11
11
  import * as i0 from "@angular/core";
12
12
  import * as i1 from "../services/zcomponent.service";
13
13
  import * as i2 from "mmhglobal-zcore";
@@ -17,24 +17,6 @@ import * as i5 from "@angular/common";
17
17
  export class MyFileInfo {
18
18
  }
19
19
  export class ZuploadComponent extends InputFieldBase {
20
- // zModelValue = [{
21
- // name: "RXJS 01.png",
22
- // size: 128753,
23
- // uid: "c96e234d-af61-4587-adcc-3b400ddef884"
24
- // }];
25
- // fieldElement = [{
26
- // Name: 'FileUploadList',
27
- // Type: 'zupload',
28
- // Value: 'FileUploadList',
29
- // SelectionOptions: ['jpg', 'jpeg', 'png', 'bmp', 'pdf'],
30
- // UploadMetaData: 'group.UploadMetaData',
31
- // AutoUpload: false,
32
- // AllowRemove: true,
33
- // Multiple: false,
34
- // OnSuccess: 'group.onSuccess()',
35
- // DivClass: "col-md-12 col-md-6",
36
- // Visible: true
37
- // }];
38
20
  constructor(componentService, authService, compressImage, zcoreService, ngZone, sharePointService, alertService) {
39
21
  super(componentService);
40
22
  this.componentService = componentService;
@@ -44,6 +26,7 @@ export class ZuploadComponent extends InputFieldBase {
44
26
  this.ngZone = ngZone;
45
27
  this.sharePointService = sharePointService;
46
28
  this.alertService = alertService;
29
+ // NOTE: Naming: `uid` array actually stores preview UIDs. Consider renaming to `previewUids` in future (not changed to preserve API).
47
30
  this.uploadAttachmentUrl = null;
48
31
  this.uploadSaveUrl = "/Attachment/Chunk_Upload_Save"; // should represent an actual API endpoint
49
32
  this.uploadRemoveUrl = "/Attachment/Chunk_Upload_Remove"; // should represent an actual API endpoint
@@ -51,9 +34,9 @@ export class ZuploadComponent extends InputFieldBase {
51
34
  this.getImageUrl = "/Attachment/getImage"; // GET method
52
35
  this.isAutoUpload = false;
53
36
  this.isMultiple = false;
37
+ this.showFileList = true;
54
38
  this.imagePreviews = [];
55
39
  this.uid = [];
56
- this.showFileList = true;
57
40
  this.fileList = [];
58
41
  this.restrictions = {
59
42
  minFileSize: 1,
@@ -78,74 +61,132 @@ export class ZuploadComponent extends InputFieldBase {
78
61
  size: 102400,
79
62
  maxAutoRetries: 3,
80
63
  };
81
- this.uploadAttachmentUrl = this.zcoreService.normalizeUrl(this.zcoreService.getEnvironment().uploadAttachmentUrl);
82
- this.uploadSaveUrl = this.uploadAttachmentUrl + this.uploadSaveUrl;
83
- this.uploadRemoveUrl = this.uploadAttachmentUrl + this.uploadRemoveUrl;
64
+ const env = this.zcoreService.getEnvironment();
65
+ const normalized = this.zcoreService.normalizeUrl(env?.uploadAttachmentUrl);
66
+ this.uploadAttachmentUrl = normalized ?? null;
67
+ if (this.uploadAttachmentUrl) {
68
+ this.uploadSaveUrl = this.uploadAttachmentUrl + this.uploadSaveUrl;
69
+ this.uploadRemoveUrl = this.uploadAttachmentUrl + this.uploadRemoveUrl;
70
+ }
71
+ else {
72
+ // Safer logging: avoid silent null URLs that break uploads
73
+ // NOTE: This indicates a configuration issue.
74
+ console.warn(`[ZuploadComponent] uploadAttachmentUrl is empty. Upload endpoints may be invalid.`, { uploadAttachmentUrl: env?.uploadAttachmentUrl });
75
+ }
76
+ this.defaultUploadSaveUrl = this.uploadSaveUrl;
77
+ this.defaultUploadRemoveUrl = this.uploadRemoveUrl;
84
78
  }
79
+ /**
80
+ * Angular lifecycle hook - initializes restrictions and upload behavior from field config.
81
+ */
85
82
  ngOnInit() {
86
83
  super.setupInnerField();
87
- // this.group['UploadMetaData'] = new UploadMetaData(null, '15', 'SO-No-1234', 'SaleOrder');
88
- // this.uploadSaveUrl = uploadAttachmentUrl + this.uploadSaveUrl;
89
- // this.uploadRemoveUrl = uploadAttachmentUrl + this.uploadRemoveUrl;
90
- if (this.data.SelectOptions && !this.data.AllowedFileExtension) {
84
+ // Allowed extensions:
85
+ // - If SelectOptions present and AllowedFileExtension not present, override
86
+ // - Else if AllowedFileExtension present and SelectOptions absent, append
87
+ // NOTE: Keep original behavior; it may allow duplicates, but prevents unexpected restriction loss.
88
+ if (this.data?.SelectOptions && !this.data?.AllowedFileExtension) {
91
89
  this.restrictions.allowedExtensions = this.data.SelectOptions;
92
90
  }
93
- else if (!this.data.SelectOptions && this.data.AllowedFileExtension) {
91
+ else if (!this.data?.SelectOptions && this.data?.AllowedFileExtension) {
94
92
  this.restrictions.allowedExtensions = this.restrictions.allowedExtensions.concat(this.data.AllowedFileExtension);
95
93
  }
96
- if (this.data.MinFileSize) {
94
+ if (typeof this.data?.MinFileSize === "number" && this.data.MinFileSize >= 0) {
97
95
  this.restrictions.minFileSize = this.data.MinFileSize;
98
96
  }
99
- if (this.data.MaxFileSize) {
97
+ if (typeof this.data?.MaxFileSize === "number" && this.data.MaxFileSize >= 0) {
100
98
  this.restrictions.maxFileSize = this.data.MaxFileSize;
101
99
  }
102
- this.isAutoUpload = this.data.AutoUpload || false;
103
- if (!this.data.AllowRemove) {
100
+ this.isAutoUpload = Boolean(this.data?.AutoUpload);
101
+ // If remove is not allowed, Kendo upload expects empty URL to hide remove request.
102
+ if (this.data && this.data.AllowRemove === false) {
104
103
  this.uploadRemoveUrl = "";
105
104
  }
106
- if (this.data.Multiple) {
107
- this.isMultiple = this.data.Multiple;
108
- }
109
- this.componentProperties.style.style6 = this.componentProperties.style.style6 || "margin: 5px; border: 1px solid gray;";
105
+ this.isMultiple = Boolean(this.data?.Multiple);
106
+ // Ensure style6 exists (legacy styling hook).
107
+ this.componentProperties.style.style6 =
108
+ this.componentProperties.style.style6 || "margin: 5px; border: 1px solid gray;";
110
109
  }
110
+ /**
111
+ * Kendo Upload success callback for both upload and remove.
112
+ * Keeps zModel in sync and emits ZComponent output events.
113
+ */
111
114
  onSuccess(e) {
112
- // angular kendo upload didn't filter away Sent event for remove, so we have to handle it here
113
- // upload progress not required for removal, thus it's also removed
114
- // @ts-ignore
115
- if (e.operation === "remove" && (e.response.type === HttpEventType.Sent || e.response.type === HttpEventType.UploadProgress)) {
115
+ // Angular Kendo Upload emits "Sent" and "UploadProgress" for remove; ignore them to avoid double-handling.
116
+ // @ts-ignore - Kendo types for response differ by runtime usage
117
+ const responseType = e?.response?.type;
118
+ if (e?.operation === "remove" &&
119
+ (responseType === HttpEventType.Sent || responseType === HttpEventType.UploadProgress)) {
120
+ return;
121
+ }
122
+ const modelKey = this.data?.Value;
123
+ if (!modelKey) {
124
+ console.warn(`[ZuploadComponent] onSuccess skipped: missing data.Value.`, { event: e });
116
125
  return;
117
126
  }
118
- if (!Array.isArray(this.group.zModel[this.data.Value])) {
119
- this.group.zModel[this.data.Value] = [];
127
+ if (!this.group?.zModel) {
128
+ console.warn(`[ZuploadComponent] onSuccess skipped: missing group.zModel.`, { event: e });
129
+ return;
120
130
  }
121
- const file = e.files[0];
122
- const existingFileIndex = this.group.zModel[this.data.Value].findIndex(f => f.name === file.name && f.uid === file.uid);
131
+ if (!Array.isArray(this.group.zModel[modelKey])) {
132
+ this.group.zModel[modelKey] = [];
133
+ }
134
+ const file = e?.files?.[0] ?? undefined;
135
+ if (!file) {
136
+ console.warn(`[ZuploadComponent] onSuccess: no file found in event.`, { event: e });
137
+ return;
138
+ }
139
+ const existingFileIndex = this.group.zModel[modelKey].findIndex((f) => f?.name === file.name && f?.uid === file.uid);
123
140
  if (e.operation === "upload") {
124
- // console.log('upload Success: ', e);
125
- //sharepoint required to read data from fileUid and attachment able to get data from fileUid too.
126
- file.myUid = e.response?.body?.fileUid ?? file.uid;
127
- delete file['httpSubscription'];
141
+ // SharePoint and Attachment use fileUid (server) for later operations.
142
+ // Prefer fileUid if provided; fallback to file.uid
143
+ // @ts-ignore - body shape is runtime-dependent
144
+ file.myUid = e?.response?.body?.fileUid ?? file.uid;
145
+ // Clean up internal subscription data to avoid circular structures
146
+ // NOTE: This relies on Kendo attaching internal fields; safe delete.
147
+ delete file["httpSubscription"];
128
148
  if (existingFileIndex !== -1) {
129
- this.group.zModel[this.data.Value][existingFileIndex] = file;
149
+ this.group.zModel[modelKey][existingFileIndex] = file;
130
150
  }
131
151
  else {
132
- this.group.zModel[this.data.Value].push(file);
152
+ this.group.zModel[modelKey].push(file);
133
153
  }
154
+ console.info(`[ZuploadComponent] Upload succeeded.`, {
155
+ name: file.name,
156
+ uid: file.uid,
157
+ myUid: file.myUid,
158
+ });
134
159
  }
135
160
  else if (e.operation === "remove") {
136
161
  if (existingFileIndex !== -1) {
137
- this.group.zModel[this.data.Value].splice(existingFileIndex, 1);
162
+ this.group.zModel[modelKey].splice(existingFileIndex, 1);
138
163
  }
164
+ console.info(`[ZuploadComponent] Remove succeeded.`, {
165
+ name: file.name,
166
+ uid: file.uid,
167
+ myUid: file.myUid,
168
+ });
169
+ }
170
+ else {
171
+ // Unknown operation, preserve behavior but log for diagnostics.
172
+ console.debug(`[ZuploadComponent] onSuccess received unsupported operation.`, { operation: e.operation, event: e });
139
173
  }
140
- ZComponentHelper.setComponentModelValue(this.data, this.group.zModel[this.data.Value], this.group);
141
- this.group.subject.next({
174
+ ZComponentHelper.setComponentModelValue(this.data, this.group.zModel[modelKey], this.group);
175
+ this.group.subject?.next({
142
176
  type: "zupload-onSuccess",
143
- target: this.data.OnSuccess,
177
+ target: this.data?.OnSuccess,
144
178
  event: e,
145
- data: { value: e.files[0], field: this.data },
179
+ data: { value: file, field: this.data },
146
180
  });
147
181
  }
182
+ /**
183
+ * Normalize and enrich image compression config with byte-based thresholds.
184
+ */
148
185
  compressionConfigHandler(imgConfig) {
186
+ if (!imgConfig) {
187
+ // NOTE: keep function safe for unexpected null; returns as-is
188
+ return imgConfig;
189
+ }
149
190
  if (imgConfig.FileSizeMaxSize) {
150
191
  imgConfig.FileSizeMaxSizeByte = this.convertSizeToByte(imgConfig.FileSizeMaxSize);
151
192
  }
@@ -157,79 +198,114 @@ export class ZuploadComponent extends InputFieldBase {
157
198
  }
158
199
  return imgConfig;
159
200
  }
201
+ /**
202
+ * Convert string size values like "10KB", "2 MB", "1gb", "1024" into bytes.
203
+ * If unit is omitted, bytes are assumed.
204
+ *
205
+ * @param sizeString Human readable size string.
206
+ * @returns Size in bytes. Returns 0 if parsing fails.
207
+ */
160
208
  convertSizeToByte(sizeString) {
161
- let _tempFileSizeMaxSize = 0;
209
+ if (!sizeString || typeof sizeString !== "string") {
210
+ return 0;
211
+ }
212
+ // Remove all spaces
213
+ const raw = sizeString.replace(/ /g, "").trim();
214
+ if (!raw) {
215
+ return 0;
216
+ }
217
+ let parsedValue = 0;
162
218
  let sizeByByte = 0;
163
- let sizeType = 'b';
164
- // remove all space
165
- const _tempFileSize = sizeString.replace(/ /g, '');
166
- // check last char is alphabetic
167
- const lastChar = _tempFileSize.substr(_tempFileSize.length - 1);
168
- if (isNaN(parseFloat(lastChar))) {
169
- const secLastChar = _tempFileSize.substr(_tempFileSize.length - 2).slice(0, -1);
170
- if (isNaN(parseFloat(secLastChar))) {
171
- // check last 2nd char is alphabetic
172
- sizeType = secLastChar + sizeType;
173
- _tempFileSizeMaxSize = parseFloat(_tempFileSize.slice(0, -2));
219
+ let sizeType = "b";
220
+ // Check last char is alphabetic
221
+ const lastChar = raw.substring(raw.length - 1);
222
+ const lastCharIsNumber = !Number.isNaN(Number.parseFloat(lastChar));
223
+ if (!lastCharIsNumber) {
224
+ const secondLastChar = raw.substring(raw.length - 2).slice(0, -1);
225
+ const secondLastIsNumber = !Number.isNaN(Number.parseFloat(secondLastChar));
226
+ if (!secondLastIsNumber) {
227
+ // Last 2nd char is also alphabetic (e.g. "MB", "GB")
228
+ sizeType = `${secondLastChar}${sizeType}`;
229
+ parsedValue = Number.parseFloat(raw.slice(0, -2));
174
230
  }
175
231
  else {
176
- _tempFileSizeMaxSize = parseFloat(_tempFileSize.slice(0, -1));
232
+ parsedValue = Number.parseFloat(raw.slice(0, -1));
233
+ }
234
+ // If parsing failed, return 0 (SonarQube safe behavior)
235
+ if (Number.isNaN(parsedValue) || parsedValue < 0) {
236
+ console.warn(`[ZuploadComponent] convertSizeToByte: invalid size value.`, { sizeString });
237
+ return 0;
177
238
  }
178
239
  switch (sizeType.toLowerCase()) {
179
240
  case "b":
180
- sizeByByte = _tempFileSizeMaxSize;
241
+ sizeByByte = parsedValue;
181
242
  break;
182
243
  case "kb":
183
- sizeByByte = _tempFileSizeMaxSize * 1024;
244
+ sizeByByte = parsedValue * 1024;
184
245
  break;
185
246
  case "mb":
186
- sizeByByte = _tempFileSizeMaxSize * 1048576;
247
+ sizeByByte = parsedValue * 1048576;
187
248
  break;
188
249
  case "gb":
189
- sizeByByte = _tempFileSizeMaxSize * 1073741824;
250
+ sizeByByte = parsedValue * 1073741824;
251
+ break;
252
+ default:
253
+ // Unknown unit => treat as bytes for backward compatibility
254
+ console.warn(`[ZuploadComponent] convertSizeToByte: unknown unit, defaulting to bytes.`, {
255
+ sizeString,
256
+ unit: sizeType,
257
+ });
258
+ sizeByByte = parsedValue;
190
259
  break;
191
260
  }
192
261
  }
193
262
  else {
194
- // default using bytes if no size type
195
- sizeByByte = parseFloat(_tempFileSize);
263
+ // Default using bytes if no size type
264
+ const n = Number.parseFloat(raw);
265
+ if (Number.isNaN(n) || n < 0) {
266
+ console.warn(`[ZuploadComponent] convertSizeToByte: invalid numeric bytes value.`, { sizeString });
267
+ return 0;
268
+ }
269
+ sizeByByte = n;
196
270
  }
197
271
  return sizeByByte;
198
272
  }
273
+ /**
274
+ * Kendo Upload upload event: validates files, builds image previews, injects metadata and auth header.
275
+ */
199
276
  uploadEventHandler(e) {
277
+ if (!e?.files?.length) {
278
+ console.warn(`[ZuploadComponent] uploadEventHandler: no files in UploadEvent.`);
279
+ return;
280
+ }
200
281
  // Image Preview
201
- const me = this;
202
282
  e.files.forEach((file) => {
203
- if (!me.isValidUploadedFile(me, file)) {
283
+ if (!this.isValidUploadedFile(file)) {
204
284
  e.preventDefault();
205
285
  return;
206
286
  }
207
- else {
208
- if (file.rawFile && file.rawFile.type.includes("image")) {
209
- if (!file.validationErrors) {
210
- const reader = new FileReader();
211
- reader.onload = function (ev) {
212
- if (me.data.EnableImagePreview) {
213
- if (!me.uid.includes(file.uid)) {
214
- me.uid.push(file.uid);
215
- me.imagePreviews.push({ ...file, src: reader.result });
216
- }
217
- }
218
- };
219
- reader.readAsDataURL(file.rawFile);
287
+ if (file?.rawFile?.type?.includes("image") && !file.validationErrors) {
288
+ const reader = new FileReader();
289
+ reader.onload = () => {
290
+ if (this.data?.EnableImagePreview) {
291
+ if (!this.uid.includes(file.uid)) {
292
+ this.uid.push(file.uid);
293
+ this.imagePreviews.push({ ...file, src: reader.result });
294
+ }
220
295
  }
221
- }
296
+ };
297
+ reader.readAsDataURL(file.rawFile);
222
298
  }
223
299
  });
224
300
  // Add metadata to the upload event
225
- let additional = ZComponentHelper.getGroupEvalValue.call(this, this.data.UploadMetaData);
301
+ let additional = ZComponentHelper.getGroupEvalValue.call(this, this.data?.UploadMetaData);
226
302
  if (!(additional instanceof UploadMetaData)) {
227
- console.error("UploadMetaData defined at " + this.data.UploadMetaData + " is invalid: ", additional);
303
+ console.warn(`[ZuploadComponent] Invalid UploadMetaData at "${this.data?.UploadMetaData}". Fallback to default metadata.`, additional);
228
304
  additional = new UploadMetaData(null, "0");
229
305
  }
230
306
  //#region sharepoint
231
- let attachmentInfo = this.sharePointService.getAttachmentInfo(this.data["DownloadFileConfig"]);
232
- //add tagging into metadata
307
+ const attachmentInfo = this.sharePointService.getAttachmentInfo(this.data?.["DownloadFileConfig"]);
308
+ // Add tagging into metadata
233
309
  if (attachmentInfo) {
234
310
  if (attachmentInfo.tag) {
235
311
  const tag = this.sharePointService.generateTagging(this.group, attachmentInfo.tag);
@@ -240,155 +316,270 @@ export class ZuploadComponent extends InputFieldBase {
240
316
  additional[AttachmentConfig.isSaveToSharePoint] = attachmentInfo.isSaveToSharePoint;
241
317
  }
242
318
  //#endregion
243
- const str = JSON.stringify(additional);
244
- e.data = { additional: str, };
245
- e.headers = e.headers.append("Authorization", "Bearer " + this.authService.e1AccessToken);
319
+ additional[AttachmentConfig.projectCode] = this.data?.ProjectCode;
320
+ additional[AttachmentConfig.moduleCode] = this.data?.ModuleCode;
321
+ const payload = JSON.stringify(additional);
322
+ e.data = { additional: payload };
323
+ // NOTE: Potentially unsafe: assumes token is always present. Keep behavior but add clearer logging.
324
+ const token = this.authService?.e1AccessToken;
325
+ if (!token) {
326
+ console.warn(`[ZuploadComponent] Missing e1AccessToken. Upload may fail due to authorization.`);
327
+ }
328
+ e.headers = e.headers.append("Authorization", `Bearer ${token ?? ""}`);
246
329
  }
330
+ /**
331
+ * Kendo Upload remove event: updates component memory, fires project event if defined,
332
+ * otherwise attaches required payload and authorization headers.
333
+ */
247
334
  onRemove(e) {
248
- // remove file from component memory
249
- const index = this.fileList.findIndex((item) => item.uid === e.files[0].uid);
335
+ const file = e?.files?.[0];
336
+ if (!file) {
337
+ console.warn(`[ZuploadComponent] onRemove: no file found in RemoveEvent.`, { event: e });
338
+ return;
339
+ }
340
+ // Remove file from component memory (for SelectFileOnly flow)
341
+ const index = this.fileList.findIndex((item) => item.uid === file.uid);
250
342
  if (index >= 0) {
251
343
  this.fileList.splice(index, 1);
252
- this.group['zupload_' + this.data.Value] = this.fileList;
344
+ this.group[`zupload_${this.data?.Value}`] = this.fileList;
253
345
  }
254
- if (this.data['FileRemovedEvent']) {
255
- this.group.subject.next({
346
+ const removedEvent = this.data?.["FileRemovedEvent"];
347
+ if (removedEvent) {
348
+ this.group.subject?.next({
256
349
  type: "zupload-fileRemovedEvent",
257
- target: this.data['FileRemovedEvent'],
258
- data: e
350
+ target: removedEvent,
351
+ data: e,
259
352
  });
353
+ return;
260
354
  }
261
- else {
262
- const myFile = e.files[0];
263
- // console.log('remove done: ', e);
264
- e.data = {
265
- id: myFile.myUid,
266
- };
267
- e.headers = e.headers.append("Authorization", "Bearer " + this.authService.e1AccessToken);
268
- if (this.data.EnableImagePreview) {
269
- e.files.forEach((file) => {
270
- this.imagePreviews = this.imagePreviews.filter(f => f.uid !== file.uid);
271
- });
272
- }
355
+ const myFile = file;
356
+ // Attach remove payload
357
+ e.data = { id: myFile.myUid };
358
+ const token = this.authService?.e1AccessToken;
359
+ if (!token) {
360
+ console.warn(`[ZuploadComponent] Missing e1AccessToken. Remove may fail due to authorization.`);
273
361
  }
274
- }
275
- onChange(file) {
276
- if (this.data['FileChangedEvent']) {
277
- this.group.subject.next({
278
- type: "zupload-fileChangedEvent",
279
- target: this.data['FileChangedEvent'],
280
- data: file
362
+ e.headers = e.headers.append("Authorization", `Bearer ${token ?? ""}`);
363
+ // Remove preview if enabled
364
+ if (this.data?.EnableImagePreview) {
365
+ e.files.forEach((f) => {
366
+ this.imagePreviews = this.imagePreviews.filter((p) => p?.["uid"] !== f.uid);
281
367
  });
282
368
  }
369
+ console.info(`[ZuploadComponent] Remove requested.`, { name: myFile.name, uid: myFile.uid, myUid: myFile.myUid });
370
+ }
371
+ /**
372
+ * Kendo Upload change event handler. Emits project event if configured.
373
+ */
374
+ onChange(files) {
375
+ const changedEvent = this.data?.["FileChangedEvent"];
376
+ if (!changedEvent) {
377
+ return;
378
+ }
379
+ this.group.subject?.next({
380
+ type: "zupload-fileChangedEvent",
381
+ target: changedEvent,
382
+ data: files,
383
+ });
283
384
  }
284
- isValidUploadedFile(me, file) {
285
- const fileSize = file.rawFile.size;
286
- const fileExtension = file.rawFile.name.split('.').pop().toLowerCase();
287
- // Check if file size and extension are valid
288
- if (fileSize > me.restrictions.maxFileSize || !me.restrictions.allowedExtensions.includes(fileExtension)) {
289
- let errorMessage = 'Error: ';
290
- if (!me.restrictions.allowedExtensions.includes(fileExtension)) {
291
- errorMessage = `Invalid file type. Allowed types are: ${me.restrictions.allowedExtensions.join(', ')}.`;
385
+ /**
386
+ * Validate a selected/uploaded file against configured restrictions (size + extension).
387
+ *
388
+ * @param file Kendo FileInfo
389
+ * @returns true if file passes restrictions, otherwise false (and shows alert).
390
+ */
391
+ isValidUploadedFile(file) {
392
+ const rawFile = file?.rawFile;
393
+ if (!rawFile) {
394
+ // NOTE: Kendo can provide FileInfo without rawFile in some events. Preserve behavior: treat as invalid.
395
+ console.warn(`[ZuploadComponent] File validation failed: rawFile is missing.`, { file });
396
+ this.alertService.showOkay("Failed to upload", "File is not available for upload.", ["col-4"]);
397
+ return false;
398
+ }
399
+ const fileSize = rawFile.size ?? 0;
400
+ // Keep original behavior: uses last segment after dot.
401
+ // NOTE: Potentially unsafe for files without extension; will result in empty extension.
402
+ const fileExtension = (rawFile.name?.split(".").pop() ?? "").toLowerCase();
403
+ const max = this.restrictions?.maxFileSize ?? 0;
404
+ const allowed = this.restrictions?.allowedExtensions ?? [];
405
+ const isExtensionAllowed = allowed.includes(fileExtension);
406
+ const isSizeAllowed = fileSize <= max;
407
+ if (!isExtensionAllowed || !isSizeAllowed) {
408
+ let errorMessage = "Error:";
409
+ if (!isExtensionAllowed) {
410
+ errorMessage = `Invalid file type "${fileExtension || "unknown"}". Allowed types: ${allowed.join(", ")}.`;
292
411
  }
293
- else if (fileSize > me.restrictions.maxFileSize) {
294
- errorMessage = `File size cannot exceeds ${me.formatFileSize(me.restrictions.maxFileSize)}.`;
412
+ else if (!isSizeAllowed) {
413
+ errorMessage = `File size cannot exceed ${this.formatFileSize(max)}.`;
295
414
  }
296
- me.alertService.showOkay('Failed to upload', errorMessage, ['col-4']);
415
+ console.warn(`[ZuploadComponent] File rejected by restrictions.`, {
416
+ name: rawFile.name,
417
+ size: fileSize,
418
+ extension: fileExtension,
419
+ maxAllowedBytes: max,
420
+ allowedExtensions: allowed,
421
+ });
422
+ this.alertService.showOkay("Failed to upload", errorMessage, ["col-4"]);
297
423
  return false;
298
424
  }
299
425
  return true;
300
426
  }
427
+ /**
428
+ * Kendo Upload select event handler:
429
+ * - Handles SharePoint endpoint switching
430
+ * - Supports SelectFileOnly mode (read file content into memory and emit event)
431
+ * - Supports image compression when AutoUpload is false
432
+ */
301
433
  selectEventHandler(e) {
302
- const me = this;
434
+ if (!e?.files?.length) {
435
+ console.warn(`[ZuploadComponent] selectEventHandler: no files in SelectEvent.`);
436
+ return;
437
+ }
438
+ // Reset to default every selection to avoid SharePoint URL "sticking" permanently.
439
+ this.uploadSaveUrl = this.defaultUploadSaveUrl;
440
+ this.uploadRemoveUrl = this.defaultUploadRemoveUrl;
303
441
  //#region sharepoint
304
- const attachmentInfo = this.sharePointService.getAttachmentInfo(this.data["DownloadFileConfig"]);
442
+ const attachmentInfo = this.sharePointService.getAttachmentInfo(this.data?.["DownloadFileConfig"]);
305
443
  // Change uploadSaveUrl if saving to SharePoint
306
- if (attachmentInfo && attachmentInfo.isSaveToSharePoint && attachmentInfo.siteName) {
307
- const attachmentSourceUrl = this.zcoreService.getEnvironment().attachmentSourceUrl;
308
- this.uploadSaveUrl = attachmentSourceUrl + '/Chunk_Upload_Save';
444
+ if (attachmentInfo?.isSaveToSharePoint && attachmentInfo.siteName) {
445
+ const attachmentSourceUrl = this.zcoreService.getEnvironment()?.attachmentSourceUrl;
446
+ if (attachmentSourceUrl) {
447
+ this.uploadSaveUrl = `${attachmentSourceUrl}/Chunk_Upload_Save`;
448
+ console.info(`[ZuploadComponent] Upload endpoint switched to SharePoint mode.`, { uploadSaveUrl: this.uploadSaveUrl });
449
+ }
450
+ else {
451
+ console.warn(`[ZuploadComponent] attachmentSourceUrl is missing. Cannot switch to SharePoint upload endpoint.`);
452
+ }
309
453
  }
310
454
  //#endregion
311
- if (this.data['SelectFileOnly']) {
455
+ if (this.data?.["SelectFileOnly"]) {
312
456
  // Append all files to component memory
313
- e.files.forEach(async (file) => {
314
- if (me.isValidUploadedFile(me, file)) {
315
- if (file.rawFile) {
316
- const reader = new FileReader();
317
- reader.onload = function (ev) {
318
- // Clone the data and also add the read file to the object
319
- const fileData = Object.assign({}, file);
320
- fileData['file'] = ev.target["result"];
321
- // Push to component fileList
322
- me.fileList.push(fileData);
323
- me.group['zupload_' + me.data.Value] = me.fileList;
324
- if (me.data['FileSelectedEvent']) {
325
- // Call the project event
326
- me.group.subject.next({
327
- type: "zupload-fileSelectedEvent",
328
- target: me.data['FileSelectedEvent'],
329
- data: me.fileList
330
- });
331
- }
332
- };
333
- await reader.readAsDataURL(file.rawFile);
334
- }
457
+ e.files.forEach((file) => {
458
+ if (!this.isValidUploadedFile(file)) {
459
+ e.preventDefault();
460
+ return;
335
461
  }
336
- else {
462
+ if (!file.rawFile) {
337
463
  e.preventDefault();
464
+ return;
338
465
  }
466
+ const reader = new FileReader();
467
+ reader.onload = (ev) => {
468
+ // Clone the data and also add the read file to the object
469
+ const fileData = {
470
+ ...file,
471
+ file: ev?.target?.result ?? null,
472
+ };
473
+ fileData["file"] = ev?.target?.result;
474
+ // Push to component fileList
475
+ this.fileList.push(fileData);
476
+ this.group[`zupload_${this.data?.Value}`] = this.fileList;
477
+ const selectedEvent = this.data?.["FileSelectedEvent"];
478
+ if (selectedEvent) {
479
+ this.group.subject?.next({
480
+ type: "zupload-fileSelectedEvent",
481
+ target: selectedEvent,
482
+ data: this.fileList,
483
+ });
484
+ }
485
+ };
486
+ reader.onerror = () => {
487
+ console.warn(`[ZuploadComponent] Failed to read file as base64.`, {
488
+ name: file.rawFile?.name,
489
+ uid: file.uid,
490
+ error: reader.error,
491
+ });
492
+ };
493
+ reader.readAsDataURL(file.rawFile);
339
494
  });
495
+ return;
340
496
  }
341
- else {
342
- // Only workable for Auto Upload = false
343
- if (!this.data.AutoUpload) {
344
- // Compression for image file
345
- const imageCompressionEnabled = this.data.Compression ? true : false;
346
- //Check if Image Compression is enabled.
347
- if (imageCompressionEnabled === true) {
348
- e.files.forEach((file) => {
349
- if (me.isValidUploadedFile(me, file)) {
350
- // Compress only if it is an image file
351
- if (file.rawFile && file.rawFile.type.includes("image")) {
352
- if (!file.validationErrors) {
353
- const imgConfig = this.compressionConfigHandler(this.data.Compression);
354
- if (file.size > imgConfig.FileSizeMinSizeByte) {
355
- me.compressImage.compress(file.rawFile, imgConfig) //Pass in parameter to set the Compression Options
356
- .pipe(take(1))
357
- .subscribe(compressFile => {
358
- this.ngZone.run(() => {
359
- file.rawFile = compressFile;
360
- file.size = compressFile.size;
361
- // Push to component fileList
362
- me.fileList.push(Object.assign({}, file));
363
- const reader = new FileReader();
364
- reader.readAsDataURL(file.rawFile);
365
- });
366
- console.log(`Compressed file size: ${(file.rawFile.size / 1024).toFixed(2)}KB`);
367
- });
368
- } // file size check
369
- } // validationErrors check
370
- } // file type check
371
- }
372
- else {
373
- e.preventDefault();
374
- }
375
- }); // loop each file
376
- } // imagecompression check
377
- // add to group scope
378
- me.group['zupload_' + me.data.Value] = e.files;
379
- }
497
+ // Only workable for Auto Upload = false
498
+ if (this.data?.AutoUpload) {
499
+ return;
500
+ }
501
+ // Compression for image file
502
+ const imageCompressionEnabled = Boolean(this.data?.Compression);
503
+ // Check if Image Compression is enabled.
504
+ if (imageCompressionEnabled) {
505
+ e.files.forEach((file) => {
506
+ if (!this.isValidUploadedFile(file)) {
507
+ e.preventDefault();
508
+ return;
509
+ }
510
+ // Compress only if it is an image file
511
+ if (!file?.rawFile?.type?.includes("image") || file.validationErrors) {
512
+ return;
513
+ }
514
+ const imgConfig = this.compressionConfigHandler(this.data.Compression);
515
+ const minBytes = imgConfig?.FileSizeMinSizeByte ?? 0;
516
+ // Original behavior: only compress if file size > minBytes
517
+ if (file.size <= minBytes) {
518
+ return;
519
+ }
520
+ this.compressImage
521
+ .compress(file.rawFile, imgConfig) // Pass in parameter to set the Compression Options
522
+ .pipe(take(1))
523
+ .subscribe({
524
+ next: (compressFile) => {
525
+ this.ngZone.run(() => {
526
+ file.rawFile = compressFile;
527
+ file.size = compressFile.size;
528
+ // Push to component fileList (kept as original intent)
529
+ const fileData = { ...file };
530
+ this.fileList.push(fileData);
531
+ // Keep original: read to data URL (side effect)
532
+ const reader = new FileReader();
533
+ reader.readAsDataURL(file.rawFile);
534
+ });
535
+ console.info(`[ZuploadComponent] Image compressed successfully.`, {
536
+ name: file?.rawFile?.name,
537
+ newSizeKB: Number((file.rawFile.size / 1024).toFixed(2)),
538
+ });
539
+ },
540
+ error: (err) => {
541
+ // Preserve flow (do not block selection), but provide clearer diagnostic
542
+ console.error(`[ZuploadComponent] Image compression failed. Upload will continue with original file.`, {
543
+ name: file?.rawFile?.name,
544
+ error: err,
545
+ });
546
+ },
547
+ });
548
+ });
380
549
  }
550
+ // Add to group scope (original behavior: store selected files)
551
+ this.group[`zupload_${this.data?.Value}`] = e.files;
381
552
  }
553
+ /**
554
+ * Clears UI-selected files and syncs group state.
555
+ * NOTE: Original behavior sets group value to fileList (not empty); preserved.
556
+ */
382
557
  clearFiles() {
558
+ if (!this.uploadComponent) {
559
+ console.warn(`[ZuploadComponent] clearFiles: uploadComponent is not ready.`);
560
+ return;
561
+ }
383
562
  this.uploadComponent.clearFiles();
384
- this.group['zupload_' + this.data.Value] = this.fileList;
563
+ this.group[`zupload_${this.data?.Value}`] = this.fileList;
564
+ console.info(`[ZuploadComponent] Files cleared from UI.`, {
565
+ storedFileListCount: this.fileList.length,
566
+ });
385
567
  }
568
+ /**
569
+ * Format bytes into human-readable string.
570
+ *
571
+ * @param bytes Raw byte size
572
+ * @returns Formatted file size string (e.g. "12.5MB")
573
+ */
386
574
  formatFileSize(bytes) {
387
- const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
388
- if (bytes === 0)
389
- return '0 Byte';
575
+ const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
576
+ if (!Number.isFinite(bytes) || bytes <= 0) {
577
+ return "0 Byte";
578
+ }
390
579
  const i = Math.floor(Math.log(bytes) / Math.log(1024));
391
- return parseFloat((bytes / Math.pow(1024, i)).toFixed(2)) + sizes[i];
580
+ const value = bytes / Math.pow(1024, i);
581
+ // NOTE: Original output had no space between number and unit; preserved.
582
+ return `${Number.parseFloat(value.toFixed(2))}${sizes[i]}`;
392
583
  }
393
584
  }
394
585
  ZuploadComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: ZuploadComponent, deps: [{ token: i1.ZComponentService }, { token: i2.AuthService }, { token: i2.CompressImageService }, { token: i2.ZCoreService }, { token: i0.NgZone }, { token: i2.SharePointService }, { token: i2.AlertService }], target: i0.ɵɵFactoryTarget.Component });
@@ -398,6 +589,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.3", ngImpor
398
589
  args: [{ selector: "app-zupload", template: "<div [formGroup]=\"form\" class=\"zupload-container e1tag-style\" [style]=\"componentProperties.style.style\">\r\n <kendo-upload\r\n *ngIf=\"!data.SelectFileOnly\"\r\n #uploadComponent\r\n [id]=\"data.Value\"\r\n [autoUpload]=\"isAutoUpload\"\r\n [saveUrl]=\"uploadSaveUrl\"\r\n [removeUrl]=\"uploadRemoveUrl\"\r\n [restrictions]=\"restrictions\"\r\n [multiple]=\"isMultiple\"\r\n [chunkable]=\"chunkSettings\"\r\n [showFileList]=\"showFileList\"\r\n (select)=\"selectEventHandler($event)\"\r\n (remove)=\"onRemove($event)\"\r\n (success)=\"onSuccess($event)\"\r\n (upload)=\"uploadEventHandler($event)\"\r\n [style]=\"componentProperties.style.style1\"\r\n class=\"e1tag-style1\">\r\n </kendo-upload>\r\n\r\n <kendo-fileselect\r\n *ngIf=\"data.SelectFileOnly\"\r\n #uploadComponent\r\n [id]=\"data.Value\"\r\n (select)=\"selectEventHandler($event)\"\r\n (remove)=\"onRemove($event)\"\r\n [formControlName]=\"data.Value\"\r\n (valueChange)=\"onChange($event)\" \r\n [restrictions]=\"restrictions\"\r\n [style]=\"componentProperties.style.style1\"\r\n class=\"e1tag-style1\">\r\n </kendo-fileselect>\r\n\r\n <div\r\n *ngIf=\"imagePreviews.length\"\r\n class=\"image-preview-container e1tag-style2\"\r\n [style]=\"componentProperties.style.style2\">\r\n <div\r\n class=\"label-container e1tag-style3\"\r\n [style]=\"componentProperties.style.style3\">\r\n Image Preview:\r\n </div>\r\n <div\r\n class=\"image-container e1tag-style4\"\r\n [style]=\"componentProperties.style.style4\">\r\n <img\r\n *ngFor=\"let image of imagePreviews\"\r\n [src]=\"image.src\"\r\n alt=\"image preview\"\r\n height=\"100\"\r\n class=\"e1tag-style5\"\r\n [style]=\"componentProperties.style.style5\" />\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".image-preview-container{border:1px solid rgba(0,0,0,.08)}.image-preview-container>.label-container{margin:5px}\n"] }]
399
590
  }], ctorParameters: function () { return [{ type: i1.ZComponentService }, { type: i2.AuthService }, { type: i2.CompressImageService }, { type: i2.ZCoreService }, { type: i0.NgZone }, { type: i2.SharePointService }, { type: i2.AlertService }]; }, propDecorators: { uploadComponent: [{
400
591
  type: ViewChild,
401
- args: ["uploadComponent"]
592
+ args: ["uploadComponent", { static: false }]
402
593
  }] } });
403
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoienVwbG9hZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9tbWhnbG9iYWwtZHluYW1pY2Zvcm0vc3JjL2xpYi96dXBsb2FkL3p1cGxvYWQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbW1oZ2xvYmFsLWR5bmFtaWNmb3JtL3NyYy9saWIvenVwbG9hZC96dXBsb2FkLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtCQUErQjtBQUMvQixPQUFPLEVBQUUsU0FBUyxFQUFrQixTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFckUsNkJBQTZCO0FBRTdCLDhCQUE4QjtBQUM5Qiw4REFBOEQ7QUFDOUQsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3RDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUdyRCwyQ0FBMkM7QUFDM0MsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBRXhFLE9BQU8sRUFFTyxnQkFBZ0IsRUFBeUIsY0FBYyxFQUE2QyxnQkFBZ0IsRUFDakksTUFBTSxpQkFBaUIsQ0FBQzs7Ozs7OztBQUV6QixNQUFNLE9BQU8sVUFBVTtDQUl0QjtBQVNELE1BQU0sT0FBTyxnQkFBaUIsU0FBUSxjQUFjO0lBd0NsRCxtQkFBbUI7SUFDbkIseUJBQXlCO0lBQ3pCLGtCQUFrQjtJQUNsQixnREFBZ0Q7SUFDaEQsTUFBTTtJQUVOLG9CQUFvQjtJQUNwQiw0QkFBNEI7SUFDNUIscUJBQXFCO0lBQ3JCLDZCQUE2QjtJQUM3Qiw0REFBNEQ7SUFDNUQsNENBQTRDO0lBQzVDLHVCQUF1QjtJQUN2Qix1QkFBdUI7SUFDdkIscUJBQXFCO0lBQ3JCLG9DQUFvQztJQUNwQyxvQ0FBb0M7SUFDcEMsa0JBQWtCO0lBQ2xCLE1BQU07SUFFTixZQUNTLGdCQUFtQyxFQUNsQyxX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QUksS0FBSyxLQUFLLENBQUM7WUFBRSxPQUFPLFFBQVEsQ0FBQztRQUNqQyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ3ZELE9BQU8sVUFBVSxDQUFDLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZFLENBQUM7OzZHQXZiVSxnQkFBZ0I7aUdBQWhCLGdCQUFnQiw4TENoQzdCLHUyREF1REE7MkZEdkJhLGdCQUFnQjtrQkFONUIsU0FBUzsrQkFDRSxhQUFhO2dSQU1PLGVBQWU7c0JBQTVDLFNBQVM7dUJBQUMsaUJBQWlCIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKiogQW5ndWxhciAqKioqKioqKioqL1xyXG5pbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgTmdab25lLCBWaWV3Q2hpbGQgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xyXG5cclxuLyoqKioqKioqKiogSW9uaWMgKioqKioqKioqKi9cclxuXHJcbi8qKioqKioqKioqIFBsdWdpbiAqKioqKioqKioqL1xyXG4vLyBpbXBvcnQgeyBlbnZpcm9ubWVudCB9IGZyb20gXCJzcmMvZW52aXJvbm1lbnRzL2Vudmlyb25tZW50XCI7XHJcbmltcG9ydCB7IHRha2UgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcbmltcG9ydCB7IEh0dHBFdmVudFR5cGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XHJcbmltcG9ydCB7IEZpbGVJbmZvLCBTdWNjZXNzRXZlbnQsIFJlbW92ZUV2ZW50LCBVcGxvYWRFdmVudCwgRmlsZVJlc3RyaWN0aW9ucywgQ2h1bmtTZXR0aW5ncywgU2VsZWN0RXZlbnQsIFVwbG9hZENvbXBvbmVudCB9IGZyb20gXCJAcHJvZ3Jlc3Mva2VuZG8tYW5ndWxhci11cGxvYWRcIjtcclxuXHJcbi8qKioqKioqKioqIENvbXBvbmVudCAmIFNlcnZpY2UgKioqKioqKioqKi9cclxuaW1wb3J0IHsgSW5wdXRGaWVsZEJhc2UgfSBmcm9tIFwiLi4vY29tcG9uZW50cy9pbnB1dGZpZWxkYmFzZS5jb21wb25lbnRcIjtcclxuaW1wb3J0IHsgWkNvbXBvbmVudFNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvemNvbXBvbmVudC5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7XHJcbiAgQXV0aFNlcnZpY2UsIFpDb3JlU2VydmljZSwgQ29tcHJlc3NJbWFnZVNlcnZpY2UsIEFsZXJ0U2VydmljZSxcclxuICBaQ29tcG9uZW50LCBaQ29tcG9uZW50SGVscGVyLCBaQ29tcG9uZW50T3V0cHV0RXZlbnQsIFVwbG9hZE1ldGFEYXRhLCBJbWFnZUNvbXByZXNzaW9uQ29uZmlnLCBTaGFyZVBvaW50U2VydmljZSwgQXR0YWNobWVudENvbmZpZywgQXR0YWNobWVudFxyXG59IGZyb20gXCJtbWhnbG9iYWwtemNvcmVcIjtcclxuXHJcbmV4cG9ydCBjbGFzcyBNeUZpbGVJbmZvIGltcGxlbWVudHMgRmlsZUluZm8ge1xyXG4gIG5hbWU6IHN0cmluZztcclxuICB1aWQ/OiBzdHJpbmc7XHJcbiAgbXlVaWQ/OiBzdHJpbmc7XHJcbn1cclxuXHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogXCJhcHAtenVwbG9hZFwiLFxyXG4gIHRlbXBsYXRlVXJsOiBcIi4venVwbG9hZC5jb21wb25lbnQuaHRtbFwiLFxyXG4gIHN0eWxlVXJsczogW1wiLi96dXBsb2FkLmNvbXBvbmVudC5zY3NzXCJdLFxyXG59KVxyXG5cclxuZXhwb3J0IGNsYXNzIFp1cGxvYWRDb21wb25lbnQgZXh0ZW5kcyBJbnB1dEZpZWxkQmFzZSBpbXBsZW1lbnRzIFpDb21wb25lbnQsIE9uSW5pdCB7XHJcbiAgQFZpZXdDaGlsZChcInVwbG9hZENvbXBvbmVudFwiKSB1cGxvYWRDb21wb25lbnQ6IFVwbG9hZENvbXBvbmVudDtcclxuXHJcbiAgdXBsb2FkQXR0YWNobWVudFVybDogc3RyaW5nID0gbnVsbDtcclxuICB1cGxvYWRTYXZlVXJsID0gXCIvQXR0YWNobWVudC9DaHVua19VcGxvYWRfU2F2ZVwiOyAvLyBzaG91bGQgcmVwcmVzZW50IGFuIGFjdHVhbCBBUEkgZW5kcG9pbnRcclxuICB1cGxvYWRSZW1vdmVVcmwgPSBcIi9BdHRhY2htZW50L0NodW5rX1VwbG9hZF9SZW1vdmVcIjsgLy8gc2hvdWxkIHJlcHJlc2VudCBhbiBhY3R1YWwgQVBJIGVuZHBvaW50XHJcbiAgZG93bmxvYWRGaWxlVXJsID0gXCIvQXR0YWNobWVudC9kb3dubG9hZEZpbGVcIjtcclxuICBnZXRJbWFnZVVybCA9IFwiL0F0dGFjaG1lbnQvZ2V0SW1hZ2VcIjsgLy8gR0VUIG1ldGhvZFxyXG4gIGlzQXV0b1VwbG9hZCA9IGZhbHNlO1xyXG4gIGlzTXVsdGlwbGUgPSBmYWxzZTtcclxuICBpbWFnZVByZXZpZXdzOiBhbnlbXSA9IFtdO1xyXG4gIHVpZDogc3RyaW5nW10gPSBbXTtcclxuICBzaG93RmlsZUxpc3QgPSB0cnVlO1xyXG4gIGZpbGVMaXN0OiBhbnlbXSA9IFtdO1xyXG5cclxuICBwdWJsaWMgcmVzdHJpY3Rpb25zOiBGaWxlUmVzdHJpY3Rpb25zID0ge1xyXG4gICAgbWluRmlsZVNpemU6IDEsXHJcbiAgICBtYXhGaWxlU2l6ZTogNDE5NDMwNCxcclxuICAgIGFsbG93ZWRFeHRlbnNpb25zOiBbXHJcbiAgICAgIFwianBnXCIsXHJcbiAgICAgIFwianBlZ1wiLFxyXG4gICAgICBcInBuZ1wiLFxyXG4gICAgICBcImJtcFwiLFxyXG4gICAgICBcInBkZlwiLFxyXG4gICAgICBcInR4dFwiLFxyXG4gICAgICBcImRvY3hcIixcclxuICAgICAgXCJkb2NcIixcclxuICAgICAgXCJ4bHN4XCIsXHJcbiAgICAgIFwieGxzXCIsXHJcbiAgICAgIFwicHB0XCIsXHJcbiAgICAgIFwicHB0eFwiLFxyXG4gICAgICBcImNzdlwiLFxyXG4gICAgXSxcclxuICB9O1xyXG5cclxuICBwdWJsaWMgY2h1bmtTZXR0aW5nczogQ2h1bmtTZXR0aW5ncyA9IHtcclxuICAgIHNpemU6IDEwMjQwMCxcclxuICAgIG1heEF1dG9SZXRyaWVzOiAzLFxyXG4gIH07XHJcblxyXG4gIC8vIHpNb2RlbFZhbHVlID0gW3tcclxuICAvLyAgIG5hbWU6IFwiUlhKUyAwMS5wbmdcIixcclxuICAvLyAgIHNpemU6IDEyODc1MyxcclxuICAvLyAgIHVpZDogXCJjOTZlMjM0ZC1hZjYxLTQ1ODctYWRjYy0zYjQwMGRkZWY4ODRcIlxyXG4gIC8vIH1dO1xyXG5cclxuICAvLyBmaWVsZEVsZW1lbnQgPSBbe1xyXG4gIC8vICAgTmFtZTogJ0ZpbGVVcGxvYWRMaXN0JyxcclxuICAvLyAgIFR5cGU6ICd6dXBsb2FkJyxcclxuICAvLyAgIFZhbHVlOiAnRmlsZVVwbG9hZExpc3QnLFxyXG4gIC8vICAgU2VsZWN0aW9uT3B0aW9uczogWydqcGcnLCAnanBlZycsICdwbmcnLCAnYm1wJywgJ3BkZiddLFxyXG4gIC8vICAgVXBsb2FkTWV0YURhdGE6ICdncm91cC5VcGxvYWRNZXRhRGF0YScsXHJcbiAgLy8gICBBdXRvVXBsb2FkOiBmYWxzZSxcclxuICAvLyAgIEFsbG93UmVtb3ZlOiB0cnVlLFxyXG4gIC8vICAgTXVsdGlwbGU6IGZhbHNlLFxyXG4gIC8vICAgT25TdWNjZXNzOiAnZ3JvdXAub25TdWNjZXNzKCknLFxyXG4gIC8vICAgRGl2Q2xhc3M6IFwiY29sLW1kLTEyIGNvbC1tZC02XCIsXHJcbiAgLy8gICBWaXNpYmxlOiB0cnVlXHJcbiAgLy8gfV07XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHVibGljIGNvbXBvbmVudFNlcnZpY2U6IFpDb21wb25lbnRTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBhdXRoU2VydmljZTogQXV0aFNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGNvbXByZXNzSW1hZ2U6IENvbXByZXNzSW1hZ2VTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSB6Y29yZVNlcnZpY2U6IFpDb3JlU2VydmljZSxcclxuICAgIHByaXZhdGUgbmdab25lOiBOZ1pvbmUsXHJcbiAgICBwcml2YXRlIHNoYXJlUG9pbnRTZXJ2aWNlOiBTaGFyZVBvaW50U2VydmljZSxcclxuICAgIHByaXZhdGUgYWxlcnRTZXJ2aWNlOiBBbGVydFNlcnZpY2VcclxuICApIHtcclxuICAgIHN1cGVyKGNvbXBvbmVudFNlcnZpY2UpO1xyXG4gICAgdGhpcy51cGxvYWRBdHRhY2htZW50VXJsID0gIHRoaXMuemNvcmVTZXJ2aWNlLm5vcm1hbGl6ZVVybCh0aGlzLnpjb3JlU2VydmljZS5nZXRFbnZpcm9ubWVudCgpLnVwbG9hZEF0dGFjaG1lbnRVcmwpO1xyXG4gICAgdGhpcy51cGxvYWRTYXZlVXJsID0gdGhpcy51cGxvYWRBdHRhY2htZW50VXJsICsgdGhpcy51cGxvYWRTYXZlVXJsO1xyXG4gICAgdGhpcy51cGxvYWRSZW1vdmVVcmwgPSB0aGlzLnVwbG9hZEF0dGFjaG1lbnRVcmwgKyB0aGlzLnVwbG9hZFJlbW92ZVVybDtcclxuICB9XHJcblxyXG4gIG5nT25Jbml0KCkge1xyXG4gICAgc3VwZXIuc2V0dXBJbm5lckZpZWxkKCk7XHJcbiAgICAvLyB0aGlzLmdyb3VwWydVcGxvYWRNZXRhRGF0YSddID0gbmV3IFVwbG9hZE1ldGFEYXRhKG51bGwsICcxNScsICdTTy1Oby0xMjM0JywgJ1NhbGVPcmRlcicpO1xyXG5cclxuXHJcbiAgICAvLyB0aGlzLnVwbG9hZFNhdmVVcmwgPSB1cGxvYWRBdHRhY2htZW50VXJsICsgdGhpcy51cGxvYWRTYXZlVXJsO1xyXG4gICAgLy8gdGhpcy51cGxvYWRSZW1vdmVVcmwgPSB1cGxvYWRBdHRhY2htZW50VXJsICsgdGhpcy51cGxvYWRSZW1vdmVVcmw7XHJcblxyXG4gICAgaWYgKHRoaXMuZGF0YS5TZWxlY3RPcHRpb25zICYmICF0aGlzLmRhdGEuQWxsb3dlZEZpbGVFeHRlbnNpb24pIHtcclxuICAgICAgdGhpcy5yZXN0cmljdGlvbnMuYWxsb3dlZEV4dGVuc2lvbnMgPSAodGhpcy5kYXRhLlNlbGVjdE9wdGlvbnMgYXMgdW5rbm93bikgYXMgc3RyaW5nW107XHJcbiAgICB9XHJcbiAgICBlbHNlIGlmICghdGhpcy5kYXRhLlNlbGVjdE9wdGlvbnMgJiYgdGhpcy5kYXRhLkFsbG93ZWRGaWxlRXh0ZW5zaW9uKSB7XHJcbiAgICAgIHRoaXMucmVzdHJpY3Rpb25zLmFsbG93ZWRFeHRlbnNpb25zID0gdGhpcy5yZXN0cmljdGlvbnMuYWxsb3dlZEV4dGVuc2lvbnMuY29uY2F0KHRoaXMuZGF0YS5BbGxvd2VkRmlsZUV4dGVuc2lvbik7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuZGF0YS5NaW5GaWxlU2l6ZSkge1xyXG4gICAgICB0aGlzLnJlc3RyaWN0aW9ucy5taW5GaWxlU2l6ZSA9IHRoaXMuZGF0YS5NaW5GaWxlU2l6ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5kYXRhLk1heEZpbGVTaXplKSB7XHJcbiAgICAgIHRoaXMucmVzdHJpY3Rpb25zLm1heEZpbGVTaXplID0gdGhpcy5kYXRhLk1heEZpbGVTaXplO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuaXNBdXRvVXBsb2FkID0gdGhpcy5kYXRhLkF1dG9VcGxvYWQgfHwgZmFsc2U7XHJcblxyXG4gICAgaWYgKCF0aGlzLmRhdGEuQWxsb3dSZW1vdmUpIHtcclxuICAgICAgdGhpcy51cGxvYWRSZW1vdmVVcmwgPSBcIlwiO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmRhdGEuTXVsdGlwbGUpIHtcclxuICAgICAgdGhpcy5pc011bHRpcGxlID0gdGhpcy5kYXRhLk11bHRpcGxlO1xyXG4gICAgfVxyXG4gICAgIFxyXG4gICAgdGhpcy5jb21wb25lbnRQcm9wZXJ0aWVzLnN0eWxlLnN0eWxlNiA9IHRoaXMuY29tcG9uZW50UHJvcGVydGllcy5zdHlsZS5zdHlsZTYgfHwgXCJtYXJnaW46IDVweDsgYm9yZGVyOiAxcHggc29saWQgZ3JheTtcIjtcclxuICB9XHJcblxyXG4gIG9uU3VjY2VzcyhlOiBTdWNjZXNzRXZlbnQpOiB2b2lkIHtcclxuICAgIC8vIGFuZ3VsYXIga2VuZG8gdXBsb2FkIGRpZG4ndCBmaWx0ZXIgYXdheSBTZW50IGV2ZW50IGZvciByZW1vdmUsIHNvIHdlIGhhdmUgdG8gaGFuZGxlIGl0IGhlcmVcclxuICAgIC8vIHVwbG9hZCBwcm9ncmVzcyBub3QgcmVxdWlyZWQgZm9yIHJlbW92YWwsIHRodXMgaXQncyBhbHNvIHJlbW92ZWRcclxuICAgIC8vIEB0cy1pZ25vcmVcclxuICAgIGlmIChlLm9wZXJhdGlvbiA9PT0gXCJyZW1vdmVcIiAmJiAoZS5yZXNwb25zZS50eXBlID09PSBIdHRwRXZlbnRUeXBlLlNlbnQgfHwgZS5yZXNwb25zZS50eXBlID09PSBIdHRwRXZlbnRUeXBlLlVwbG9hZFByb2dyZXNzKSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHRoaXMuZ3JvdXAuek1vZGVsW3RoaXMuZGF0YS5WYWx1ZV0pKSB7XHJcbiAgICAgIHRoaXMuZ3JvdXAuek1vZGVsW3RoaXMuZGF0YS5WYWx1ZV0gPSBbXTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBmaWxlID0gZS5maWxlc1swXSBhcyBNeUZpbGVJbmZvO1xyXG4gICAgY29uc3QgZXhpc3RpbmdGaWxlSW5kZXggPSB0aGlzLmdyb3VwLnpNb2RlbFt0aGlzLmRhdGEuVmFsdWVdLmZpbmRJbmRleChmID0+IGYubmFtZSA9PT0gZmlsZS5uYW1lICYmIGYudWlkID09PSBmaWxlLnVpZCk7XHJcbiAgICBpZiAoZS5vcGVyYXRpb24gPT09IFwidXBsb2FkXCIpIHtcclxuICAgICAgLy8gY29uc29sZS5sb2coJ3VwbG9hZCBTdWNjZXNzOiAnLCBlKTtcclxuICAgICAgLy9zaGFyZXBvaW50IHJlcXVpcmVkIHRvIHJlYWQgZGF0YSBmcm9tIGZpbGVVaWQgYW5kIGF0dGFjaG1lbnQgYWJsZSB0byBnZXQgZGF0YSBmcm9tIGZpbGVVaWQgdG9vLlxyXG4gICAgICBmaWxlLm15VWlkID0gZS5yZXNwb25zZT8uYm9keT8uZmlsZVVpZCA/PyBmaWxlLnVpZDtcclxuICAgICAgZGVsZXRlIGZpbGVbJ2h0dHBTdWJzY3JpcHRpb24nXTtcclxuXHJcbiAgICAgIGlmIChleGlzdGluZ0ZpbGVJbmRleCAhPT0gLTEpIHtcclxuICAgICAgICB0aGlzLmdyb3VwLnpNb2RlbFt0aGlzLmRhdGEuVmFsdWVdW2V4aXN0aW5nRmlsZUluZGV4XSA9IGZpbGU7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy5ncm91cC56TW9kZWxbdGhpcy5kYXRhLlZhbHVlXS5wdXNoKGZpbGUpO1xyXG4gICAgICB9XHJcblxyXG4gICAgfSBlbHNlIGlmIChlLm9wZXJhdGlvbiA9PT0gXCJyZW1vdmVcIikge1xyXG4gICAgICBpZiAoZXhpc3RpbmdGaWxlSW5kZXggIT09IC0xKSB7XHJcbiAgICAgICAgdGhpcy5ncm91cC56TW9kZWxbdGhpcy5kYXRhLlZhbHVlXS5zcGxpY2UoZXhpc3RpbmdGaWxlSW5kZXgsIDEpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgWkNvbXBvbmVudEhlbHBlci5zZXRDb21wb25lbnRNb2RlbFZhbHVlKHRoaXMuZGF0YSwgdGhpcy5ncm91cC56TW9kZWxbdGhpcy5kYXRhLlZhbHVlXSwgdGhpcy5ncm91cCk7XHJcbiAgICB0aGlzLmdyb3VwLnN1YmplY3QubmV4dCh7XHJcbiAgICAgIHR5cGU6IFwienVwbG9hZC1vblN1Y2Nlc3NcIixcclxuICAgICAgdGFyZ2V0OiB0aGlzLmRhdGEuT25TdWNjZXNzLFxyXG4gICAgICBldmVudDogZSxcclxuICAgICAgZGF0YTogeyB2YWx1ZTogZS5maWxlc1swXSwgZmllbGQ6IHRoaXMuZGF0YSB9LFxyXG4gICAgfSBhcyBaQ29tcG9uZW50T3V0cHV0RXZlbnQpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjb21wcmVzc2lvbkNvbmZpZ0hhbmRsZXIoaW1nQ29uZmlnOiBJbWFnZUNvbXByZXNzaW9uQ29uZmlnKTogSW1hZ2VDb21wcmVzc2lvbkNvbmZpZyB7XHJcbiAgICBpZiAoaW1nQ29uZmlnLkZpbGVTaXplTWF4U2l6ZSkge1xyXG4gICAgICBpbWdDb25maWcuRmlsZVNpemVNYXhTaXplQnl0ZSA9IHRoaXMuY29udmVydFNpemVUb0J5dGUoaW1nQ29uZmlnLkZpbGVTaXplTWF4U2l6ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGltZ0NvbmZpZy5GaWxlU2l6ZU1pblNpemUpIHtcclxuICAgICAgaW1nQ29uZmlnLkZpbGVTaXplTWluU2l6ZUJ5dGUgPSB0aGlzLmNvbnZlcnRTaXplVG9CeXRlKGltZ0NvbmZpZy5GaWxlU2l6ZU1pblNpemUpO1xyXG4gICAgfVxyXG4gICAgZWxzZSB7XHJcbiAgICAgIGltZ0NvbmZpZy5GaWxlU2l6ZU1pblNpemVCeXRlID0gMDtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gaW1nQ29uZmlnO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjb252ZXJ0U2l6ZVRvQnl0ZShzaXplU3RyaW5nOiBzdHJpbmcpOiBudW1iZXIge1xyXG4gICAgbGV0IF90ZW1wRmlsZVNpemVNYXhTaXplOiBudW1iZXIgPSAwO1xyXG4gICAgbGV0IHNpemVCeUJ5dGU6IG51bWJlciA9IDA7XHJcbiAgICBsZXQgc2l6ZVR5cGUgPSAnYic7XHJcblxyXG4gICAgLy8gcmVtb3ZlIGFsbCBzcGFjZVxyXG4gICAgY29uc3QgX3RlbXBGaWxlU2l6ZSA9IHNpemVTdHJpbmcucmVwbGFjZSgvIC9nLCAnJyk7XHJcblxyXG4gICAgLy8gY2hlY2sgbGFzdCBjaGFyIGlzIGFscGhhYmV0aWNcclxuICAgIGNvbnN0IGxhc3RDaGFyID0gX3RlbXBGaWxlU2l6ZS5zdWJzdHIoX3RlbXBGaWxlU2l6ZS5sZW5ndGggLSAxKTtcclxuICAgIGlmIChpc05hTihwYXJzZUZsb2F0KGxhc3RDaGFyKSkpIHtcclxuICAgICAgY29uc3Qgc2VjTGFzdENoYXIgPSBfdGVtcEZpbGVTaXplLnN1YnN0cihfdGVtcEZpbGVTaXplLmxlbmd0aCAtIDIpLnNsaWNlKDAsIC0xKTtcclxuXHJcbiAgICAgIGlmIChpc05hTihwYXJzZUZsb2F0KHNlY0xhc3RDaGFyKSkpIHtcclxuICAgICAgICAvLyBjaGVjayBsYXN0IDJuZCBjaGFyIGlzIGFscGhhYmV0aWNcclxuICAgICAgICBzaXplVHlwZSA9IHNlY0xhc3RDaGFyICsgc2l6ZVR5cGU7XHJcbiAgICAgICAgX3RlbXBGaWxlU2l6ZU1heFNpemUgPSBwYXJzZUZsb2F0KF90ZW1wRmlsZVNpemUuc2xpY2UoMCwgLTIpKTtcclxuICAgICAgfVxyXG4gICAgICBlbHNlIHtcclxuICAgICAgICBfdGVtcEZpbGVTaXplTWF4U2l6ZSA9IHBhcnNlRmxvYXQoX3RlbXBGaWxlU2l6ZS5zbGljZSgwLCAtMSkpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBzd2l0Y2ggKHNpemVUeXBlLnRvTG93ZXJDYXNlKCkpIHtcclxuICAgICAgICBjYXNlIFwiYlwiOlxyXG4gICAgICAgICAgc2l6ZUJ5Qnl0ZSA9IF90ZW1wRmlsZVNpemVNYXhTaXplXHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlIFwia2JcIjpcclxuICAgICAgICAgIHNpemVCeUJ5dGUgPSBfdGVtcEZpbGVTaXplTWF4U2l6ZSAqIDEwMjRcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgXCJtYlwiOlxyXG4gICAgICAgICAgc2l6ZUJ5Qnl0ZSA9IF90ZW1wRmlsZVNpemVNYXhTaXplICogMTA0ODU3NlxyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgY2FzZSBcImdiXCI6XHJcbiAgICAgICAgICBzaXplQnlCeXRlID0gX3RlbXBGaWxlU2l6ZU1heFNpemUgKiAxMDczNzQxODI0XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgZWxzZSB7XHJcbiAgICAgIC8vIGRlZmF1bHQgdXNpbmcgYnl0ZXMgaWYgbm8gc2l6ZSB0eXBlXHJcbiAgICAgIHNpemVCeUJ5dGUgPSBwYXJzZUZsb2F0KF90ZW1wRmlsZVNpemUpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBzaXplQnlCeXRlO1xyXG4gIH1cclxuXHJcbiAgdXBsb2FkRXZlbnRIYW5kbGVyKGU6IFVwbG9hZEV2ZW50KSB7XHJcbiAgICAvLyBJbWFnZSBQcmV2aWV3XHJcbiAgICBjb25zdCBtZSA9IHRoaXM7XHJcblxyXG4gICAgZS5maWxlcy5mb3JFYWNoKChmaWxlOiBGaWxlSW5mbykgPT4ge1xyXG4gICAgICBpZiAoIW1lLmlzVmFsaWRVcGxvYWRlZEZpbGUobWUsIGZpbGUpKSB7XHJcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgICBlbHNlIHtcclxuICAgICAgICBpZiAoZmlsZS5yYXdGaWxlICYmIGZpbGUucmF3RmlsZS50eXBlLmluY2x1ZGVzKFwiaW1hZ2VcIikpIHtcclxuICAgICAgICAgIGlmICghZmlsZS52YWxpZGF0aW9uRXJyb3JzKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XHJcbiAgICAgICAgICAgIHJlYWRlci5vbmxvYWQgPSBmdW5jdGlvbiAoZXYpIHtcclxuICAgICAgICAgICAgICBpZiAobWUuZGF0YS5FbmFibGVJbWFnZVByZXZpZXcpIHtcclxuICAgICAgICAgICAgICAgIGlmICghbWUudWlkLmluY2x1ZGVzKGZpbGUudWlkKSkge1xyXG4gICAgICAgICAgICAgICAgICBtZS51aWQucHVzaChmaWxlLnVpZCk7XHJcbiAgICAgICAgICAgICAgICAgIG1lLmltYWdlUHJldmlld3MucHVzaCh7IC4uLmZpbGUsIHNyYzogPHN0cmluZz5yZWFkZXIucmVzdWx0IH0pO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlLnJhd0ZpbGUpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gQWRkIG1ldGFkYXRhIHRvIHRoZSB1cGxvYWQgZXZlbnRcclxuICAgIGxldCBhZGRpdGlvbmFsOiBVcGxvYWRNZXRhRGF0YSA9IFpDb21wb25lbnRIZWxwZXIuZ2V0R3JvdXBFdmFsVmFsdWUuY2FsbCh0aGlzLCB0aGlzLmRhdGEuVXBsb2FkTWV0YURhdGEpO1xyXG5cclxuICAgIGlmICghKGFkZGl0aW9uYWwgaW5zdGFuY2VvZiBVcGxvYWRNZXRhRGF0YSkpIHtcclxuICAgICAgY29uc29sZS5lcnJvcihcIlVwbG9hZE1ldGFEYXRhIGRlZmluZWQgYXQgXCIgKyB0aGlzLmRhdGEuVXBsb2FkTWV0YURhdGEgKyBcIiBpcyBpbnZhbGlkOiBcIiwgYWRkaXRpb25hbCk7XHJcbiAgICAgIGFkZGl0aW9uYWwgPSBuZXcgVXBsb2FkTWV0YURhdGEobnVsbCwgXCIwXCIpO1xyXG4gICAgfVxyXG5cclxuXHJcbiAgICAvLyNyZWdpb24gc2hhcmVwb2ludFxyXG4gICAgbGV0IGF0dGFjaG1lbnRJbmZvOiBBdHRhY2htZW50ID0gdGhpcy5zaGFyZVBvaW50U2VydmljZS5nZXRBdHRhY2htZW50SW5mbyh0aGlzLmRhdGFbXCJEb3dubG9hZEZpbGVDb25maWdcIl0pO1xyXG5cclxuICAgIC8vYWRkIHRhZ2dpbmcgaW50byBtZXRhZGF0YVxyXG4gICAgaWYgKGF0dGFjaG1lbnRJbmZvKSB7XHJcbiAgICAgIGlmIChhdHRhY2htZW50SW5mby50YWcpIHtcclxuICAgICAgICBjb25zdCB0YWcgPSB0aGlzLnNoYXJlUG9pbnRTZXJ2aWNlLmdlbmVyYXRlVGFnZ2luZyh0aGlzLmdyb3VwLCBhdHRhY2htZW50SW5mby50YWcpO1xyXG4gICAgICAgIGFkZGl0aW9uYWxbQXR0YWNobWVudENvbmZpZy50YWddID0gdGFnO1xyXG4gICAgICB9XHJcbiAgICAgIGFkZGl0aW9uYWxbQXR0YWNobWVudENvbmZpZy5zaXRlTmFtZV0gPSBhdHRhY2htZW50SW5mby5zaXRlTmFtZTtcclxuICAgICAgYWRkaXRpb25hbFtBdHRhY2htZW50Q29uZmlnLmRvY3VtZW50TGlicmFyeU5hbWVdID0gYXR0YWNobWVudEluZm8uZG9jdW1lbnRMaWJyYXJ5TmFtZTtcclxuICAgICAgYWRkaXRpb25hbFtBdHRhY2htZW50Q29uZmlnLmlzU2F2ZVRvU2hhcmVQb2ludF0gPSBhdHRhY2htZW50SW5mby5pc1NhdmVUb1NoYXJlUG9pbnQ7XHJcbiAgICB9XHJcbiAgICAvLyNlbmRyZWdpb25cclxuXHJcbiAgICBjb25zdCBzdHIgPSBKU09OLnN0cmluZ2lmeShhZGRpdGlvbmFsKTtcclxuXHJcbiAgICBlLmRhdGEgPSB7IGFkZGl0aW9uYWw6IHN0ciwgfTtcclxuICAgIGUuaGVhZGVycyA9IGUuaGVhZGVycy5hcHBlbmQoXCJBdXRob3JpemF0aW9uXCIsIFwiQmVhcmVyIFwiICsgdGhpcy5hdXRoU2VydmljZS5lMUFjY2Vzc1Rva2VuKTtcclxuICB9XHJcblxyXG4gIG9uUmVtb3ZlKGU6IFJlbW92ZUV2ZW50KTogdm9pZCB7XHJcbiAgICAvLyByZW1vdmUgZmlsZSBmcm9tIGNvbXBvbmVudCBtZW1vcnlcclxuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5maWxlTGlzdC5maW5kSW5kZXgoXHJcbiAgICAgIChpdGVtKSA9PiBpdGVtLnVpZCA9PT0gZS5maWxlc1swXS51aWRcclxuICAgICk7XHJcblxyXG4gICAgaWYgKGluZGV4ID49IDApIHtcclxuICAgICAgdGhpcy5maWxlTGlzdC5zcGxpY2UoaW5kZXgsIDEpO1xyXG4gICAgICB0aGlzLmdyb3VwWyd6dXBsb2FkXycgKyB0aGlzLmRhdGEuVmFsdWVdID0gdGhpcy5maWxlTGlzdDtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5kYXRhWydGaWxlUmVtb3ZlZEV2ZW50J10pIHtcclxuICAgICAgdGhpcy5ncm91cC5zdWJqZWN0Lm5leHQoe1xyXG4gICAgICAgIHR5cGU6IFwienVwbG9hZC1maWxlUmVtb3ZlZEV2ZW50XCIsXHJcbiAgICAgICAgdGFyZ2V0OiB0aGlzLmRhdGFbJ0ZpbGVSZW1vdmVkRXZlbnQnXSxcclxuICAgICAgICBkYXRhOiBlXHJcbiAgICAgIH0gYXMgWkNvbXBvbmVudE91dHB1dEV2ZW50KTtcclxuICAgIH1cclxuICAgIGVsc2Uge1xyXG4gICAgICBjb25zdCBteUZpbGU6IE15RmlsZUluZm8gPSBlLmZpbGVzWzBdIGFzIE15RmlsZUluZm87XHJcblxyXG4gICAgICAvLyBjb25zb2xlLmxvZygncmVtb3ZlIGRvbmU6ICcsIGUpO1xyXG4gICAgICBlLmRhdGEgPSB7XHJcbiAgICAgICAgaWQ6IG15RmlsZS5teVVpZCxcclxuICAgICAgfTtcclxuICAgICAgZS5oZWFkZXJzID0gZS5oZWFkZXJzLmFwcGVuZChcclxuICAgICAgICBcIkF1dGhvcml6YXRpb25cIixcclxuICAgICAgICBcIkJlYXJlciBcIiArIHRoaXMuYXV0aFNlcnZpY2UuZTFBY2Nlc3NUb2tlblxyXG4gICAgICApO1xyXG5cclxuICAgICAgaWYgKHRoaXMuZGF0YS5FbmFibGVJbWFnZVByZXZpZXcpIHtcclxuICAgICAgICBlLmZpbGVzLmZvckVhY2goKGZpbGU6IEZpbGVJbmZvKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLmltYWdlUHJldmlld3MgPSB0aGlzLmltYWdlUHJldmlld3MuZmlsdGVyKGYgPT4gZi51aWQgIT09IGZpbGUudWlkKTtcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25DaGFuZ2UoZmlsZTogRmlsZUluZm9bXSk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuZGF0YVsnRmlsZUNoYW5nZWRFdmVudCddKSB7XHJcbiAgICAgIHRoaXMuZ3JvdXAuc3ViamVjdC5uZXh0KHtcclxuICAgICAgICB0eXBlOiBcInp1cGxvYWQtZmlsZUNoYW5nZWRFdmVudFwiLFxyXG4gICAgICAgIHRhcmdldDogdGhpcy5kYXRhWydGaWxlQ2hhbmdlZEV2ZW50J10sXHJcbiAgICAgICAgZGF0YTogZmlsZVxyXG4gICAgICB9IGFzIFpDb21wb25lbnRPdXRwdXRFdmVudCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGlzVmFsaWRVcGxvYWRlZEZpbGUobWU6IGFueSwgZmlsZTogRmlsZUluZm8pOiBib29sZWFuIHtcclxuICAgIGNvbnN0IGZpbGVTaXplID0gZmlsZS5yYXdGaWxlLnNpemU7XHJcbiAgICBjb25zdCBmaWxlRXh0ZW5zaW9uID0gZmlsZS5yYXdGaWxlLm5hbWUuc3BsaXQoJy4nKS5wb3AoKS50b0xvd2VyQ2FzZSgpO1xyXG5cclxuICAgIC8vIENoZWNrIGlmIGZpbGUgc2l6ZSBhbmQgZXh0ZW5zaW9uIGFyZSB2YWxpZFxyXG4gICAgaWYgKGZpbGVTaXplID4gbWUucmVzdHJpY3Rpb25zLm1heEZpbGVTaXplIHx8ICFtZS5yZXN0cmljdGlvbnMuYWxsb3dlZEV4dGVuc2lvbnMuaW5jbHVkZXMoZmlsZUV4dGVuc2lvbikpIHtcclxuICAgICAgbGV0IGVycm9yTWVzc2FnZSA9ICdFcnJvcjogJztcclxuICAgICAgaWYgKCFtZS5yZXN0cmljdGlvbnMuYWxsb3dlZEV4dGVuc2lvbnMuaW5jbHVkZXMoZmlsZUV4dGVuc2lvbikpIHtcclxuICAgICAgICBlcnJvck1lc3NhZ2UgPSBgSW52YWxpZCBmaWxlIHR5cGUuIEFsbG93ZWQgdHlwZXMgYXJlOiAke21lLnJlc3RyaWN0aW9ucy5hbGxvd2VkRXh0ZW5zaW9ucy5qb2luKCcsICcpfS5gO1xyXG4gICAgICB9XHJcbiAgICAgIGVsc2UgaWYgKGZpbGVTaXplID4gbWUucmVzdHJpY3Rpb25zLm1heEZpbGVTaXplKSB7XHJcbiAgICAgICAgZXJyb3JNZXNzYWdlID0gYEZpbGUgc2l6ZSBjYW5ub3QgZXhjZWVkcyAke21lLmZvcm1hdEZpbGVTaXplKG1lLnJlc3RyaWN0aW9ucy5tYXhGaWxlU2l6ZSl9LmA7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIG1lLmFsZXJ0U2VydmljZS5zaG93T2theSgnRmFpbGVkIHRvIHVwbG9hZCcsIGVycm9yTWVzc2FnZSwgWydjb2wtNCddKTtcclxuXHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9XHJcblxyXG4gIHNlbGVjdEV2ZW50SGFuZGxlcihlOiBTZWxlY3RFdmVudCkge1xyXG4gICAgY29uc3QgbWUgPSB0aGlzO1xyXG5cclxuICAgIC8vI3JlZ2lvbiBzaGFyZXBvaW50XHJcbiAgICBjb25zdCBhdHRhY2htZW50SW5mbzogQXR0YWNobWVudCA9IHRoaXMuc2hhcmVQb2ludFNlcnZpY2UuZ2V0QXR0YWNobWVudEluZm8odGhpcy5kYXRhW1wiRG93bmxvYWRGaWxlQ29uZmlnXCJdKTtcclxuICAgIC8vIENoYW5nZSB1cGxvYWRTYXZlVXJsIGlmIHNhdmluZyB0byBTaGFyZVBvaW50XHJcbiAgICBpZiAoYXR0YWNobWVudEluZm8gJiYgYXR0YWNobWVudEluZm8uaXNTYXZlVG9TaGFyZVBvaW50ICYmIGF0dGFjaG1lbnRJbmZvLnNpdGVOYW1lKSB7XHJcbiAgICAgIGNvbnN0IGF0dGFjaG1lbnRTb3VyY2VVcmwgPSB0aGlzLnpjb3JlU2VydmljZS5nZXRFbnZpcm9ubWVudCgpLmF0dGFjaG1lbnRTb3VyY2VVcmw7XHJcbiAgICAgIHRoaXMudXBsb2FkU2F2ZVVybCA9IGF0dGFjaG1lbnRTb3VyY2VVcmwgKyAnL0NodW5rX1VwbG9hZF9TYXZlJztcclxuICAgIH1cclxuICAgIC8vI2VuZHJlZ2lvblxyXG5cclxuICAgIGlmICh0aGlzLmRhdGFbJ1NlbGVjdEZpbGVPbmx5J10pIHtcclxuICAgICAgLy8gQXBwZW5kIGFsbCBmaWxlcyB0byBjb21wb25lbnQgbWVtb3J5XHJcbiAgICAgIGUuZmlsZXMuZm9yRWFjaChhc3luYyAoZmlsZTogRmlsZUluZm8pID0+IHtcclxuICAgICAgICBpZiAobWUuaXNWYWxpZFVwbG9hZGVkRmlsZShtZSwgZmlsZSkpIHtcclxuICAgICAgICAgIGlmIChmaWxlLnJhd0ZpbGUpIHtcclxuICAgICAgICAgICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcclxuICAgICAgICAgICAgcmVhZGVyLm9ubG9hZCA9IGZ1bmN0aW9uIChldikge1xyXG4gICAgICAgICAgICAgIC8vIENsb25lIHRoZSBkYXRhIGFuZCBhbHNvIGFkZCB0aGUgcmVhZCBmaWxlIHRvIHRoZSBvYmplY3RcclxuICAgICAgICAgICAgICBjb25zdCBmaWxlRGF0YSA9IE9iamVjdC5hc3NpZ24oe30sIGZpbGUpO1xyXG4gICAgICAgICAgICAgIGZpbGVEYXRhWydmaWxlJ10gPSBldi50YXJnZXRbXCJyZXN1bHRcIl07XHJcblxyXG4gICAgICAgICAgICAgIC8vIFB1c2ggdG8gY29tcG9uZW50IGZpbGVMaXN0XHJcbiAgICAgICAgICAgICAgbWUuZmlsZUxpc3QucHVzaChmaWxlRGF0YSk7XHJcbiAgICAgICAgICAgICAgbWUuZ3JvdXBbJ3p1cGxvYWRfJyArIG1lLmRhdGEuVmFsdWVdID0gbWUuZmlsZUxpc3Q7XHJcblxyXG4gICAgICAgICAgICAgIGlmIChtZS5kYXRhWydGaWxlU2VsZWN0ZWRFdmVudCddKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBDYWxsIHRoZSBwcm9qZWN0IGV2ZW50XHJcbiAgICAgICAgICAgICAgICBtZS5ncm91cC5zdWJqZWN0Lm5leHQoe1xyXG4gICAgICAgICAgICAgICAgICB0eXBlOiBcInp1cGxvYWQtZmlsZVNlbGVjdGVkRXZlbnRcIixcclxuICAgICAgICAgICAgICAgICAgdGFyZ2V0OiBtZS5kYXRhWydGaWxlU2VsZWN0ZWRFdmVudCddLFxyXG4gICAgICAgICAgICAgICAgICBkYXRhOiBtZS5maWxlTGlzdFxyXG4gICAgICAgICAgICAgICAgfSBhcyBaQ29tcG9uZW50T3V0cHV0RXZlbnQpO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgYXdhaXQgcmVhZGVyLnJlYWRBc0RhdGFVUkwoZmlsZS5yYXdGaWxlKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgIH1cclxuICAgIGVsc2Uge1xyXG4gICAgICAvLyBPbmx5IHdvcmthYmxlIGZvciBBdXRvIFVwbG9hZCA9IGZhbHNlXHJcbiAgICAgIGlmICghdGhpcy5kYXRhLkF1dG9VcGxvYWQpIHtcclxuICAgICAgICAvLyBDb21wcmVzc2lvbiBmb3IgaW1hZ2UgZmlsZVxyXG4gICAgICAgIGNvbnN0IGltYWdlQ29tcHJlc3Npb25FbmFibGVkID0gdGhpcy5kYXRhLkNvbXByZXNzaW9uID8gdHJ1ZSA6IGZhbHNlO1xyXG5cclxuICAgICAgICAvL0NoZWNrIGlmIEltYWdlIENvbXByZXNzaW9uIGlzIGVuYWJsZWQuXHJcbiAgICAgICAgaWYgKGltYWdlQ29tcHJlc3Npb25FbmFibGVkID09PSB0cnVlKSB7XHJcbiAgICAgICAgICBlLmZpbGVzLmZvckVhY2goKGZpbGU6IEZpbGVJbmZvKSA9PiB7XHJcbiAgICAgICAgICAgIGlmIChtZS5pc1ZhbGlkVXBsb2FkZWRGaWxlKG1lLCBmaWxlKSkge1xyXG4gICAgICAgICAgICAgIC8vIENvbXByZXNzIG9ubHkgaWYgaXQgaXMgYW4gaW1hZ2UgZmlsZVxyXG4gICAgICAgICAgICAgIGlmIChmaWxlLnJhd0ZpbGUgJiYgZmlsZS5yYXdGaWxlLnR5cGUuaW5jbHVkZXMoXCJpbWFnZVwiKSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFmaWxlLnZhbGlkYXRpb25FcnJvcnMpIHtcclxuICAgICAgICAgICAgICAgICAgY29uc3QgaW1nQ29uZmlnID0gdGhpcy5jb21wcmVzc2lvbkNvbmZpZ0hhbmRsZXIodGhpcy5kYXRhLkNvbXByZXNzaW9uKTtcclxuICAgICAgICAgICAgICAgICAgaWYgKGZpbGUuc2l6ZSA+IGltZ0NvbmZpZy5GaWxlU2l6ZU1pblNpemVCeXRlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbWUuY29tcHJlc3NJbWFnZS5jb21wcmVzcyhmaWxlLnJhd0ZpbGUsIGltZ0NvbmZpZykgIC8vUGFzcyBpbiBwYXJhbWV0ZXIgdG8gc2V0IHRoZSBDb21wcmVzc2lvbiBPcHRpb25zXHJcbiAgICAgICAgICAgICAgICAgICAgICAucGlwZSh0YWtlKDEpKVxyXG4gICAgICAgICAgICAgICAgICAgICAgLnN1YnNjcmliZShjb21wcmVzc0ZpbGUgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGUucmF3RmlsZSA9IGNvbXByZXNzRmlsZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlLnNpemUgPSBjb21wcmVzc0ZpbGUuc2l6ZTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUHVzaCB0byBjb21wb25lbnQgZmlsZUxpc3RcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBtZS5maWxlTGlzdC5wdXNoKE9iamVjdC5hc3NpZ24oe30sIGZpbGUpKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlLnJhd0ZpbGUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coYENvbXByZXNzZWQgZmlsZSBzaXplOiAkeyhmaWxlLnJhd0ZpbGUuc2l6ZSAvIDEwMjQpLnRvRml4ZWQoMil9S0JgKTtcclxuICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICB9IC8vIGZpbGUgc2l6ZSBjaGVja1xyXG4gICAgICAgICAgICAgICAgfSAvLyB2YWxpZGF0aW9uRXJyb3JzIGNoZWNrXHJcbiAgICAgICAgICAgICAgfSAvLyBmaWxlIHR5cGUgY2hlY2tcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0pIC8vIGxvb3AgZWFjaCBmaWxlXHJcbiAgICAgICAgfSAvLyBpbWFnZWNvbXByZXNzaW9uIGNoZWNrXHJcblxyXG4gICAgICAgIC8vIGFkZCB0byBncm91cCBzY29wZVxyXG4gICAgICAgIG1lLmdyb3VwWyd6dXBsb2FkXycgKyBtZS5kYXRhLlZhbHVlXSA9IGUuZmlsZXM7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNsZWFyRmlsZXMoKSB7XHJcbiAgICB0aGlzLnVwbG9hZENvbXBvbmVudC5jbGVhckZpbGVzKCk7XHJcbiAgICB0aGlzLmdyb3VwWyd6dXBsb2FkXycgKyB0aGlzLmRhdGEuVmFsdWVdID0gdGhpcy5maWxlTGlzdDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZm9ybWF0RmlsZVNpemUoYnl0ZXM6IG51bWJlcik6IHN0cmluZyB7XHJcbiAgICBjb25zdCBzaXplcyA9IFsnQnl0ZXMnLCAnS0InLCAnTUInLCAnR0InLCAnVEInXTtcclxuICAgIGlmIChieXRlcyA9PT0gMCkgcmV0dXJuICcwIEJ5dGUnO1xyXG4gICAgY29uc3QgaSA9IE1hdGguZmxvb3IoTWF0aC5sb2coYnl0ZXMpIC8gTWF0aC5sb2coMTAyNCkpO1xyXG4gICAgcmV0dXJuIHBhcnNlRmxvYXQoKGJ5dGVzIC8gTWF0aC5wb3coMTAyNCwgaSkpLnRvRml4ZWQoMikpICsgc2l6ZXNbaV07XHJcbiAgfVxyXG59XHJcbiIsIjxkaXYgW2Zvcm1Hcm91cF09XCJmb3JtXCIgY2xhc3M9XCJ6dXBsb2FkLWNvbnRhaW5lciBlMXRhZy1zdHlsZVwiIFtzdHlsZV09XCJjb21wb25lbnRQcm9wZXJ0aWVzLnN0eWxlLnN0eWxlXCI+XHJcbiAgPGtlbmRvLXVwbG9hZFxyXG4gICAgKm5nSWY9XCIhZGF0YS5TZWxlY3RGaWxlT25seVwiXHJcbiAgICAjdXBsb2FkQ29tcG9uZW50XHJcbiAgICBbaWRdPVwiZGF0YS5WYWx1ZVwiXHJcbiAgICBbYXV0b1VwbG9hZF09XCJpc0F1dG9VcGxvYWRcIlxyXG4gICAgW3NhdmVVcmxdPVwidXBsb2FkU2F2ZVVybFwiXHJcbiAgICBbcmVtb3ZlVXJsXT1cInVwbG9hZFJlbW92ZVVybFwiXHJcbiAgICBbcmVzdHJpY3Rpb25zXT1cInJlc3RyaWN0aW9uc1wiXHJcbiAgICBbbXVsdGlwbGVdPVwiaXNNdWx0aXBsZVwiXHJcbiAgICBbY2h1bmthYmxlXT1cImNodW5rU2V0dGluZ3NcIlxyXG4gICAgW3Nob3dGaWxlTGlzdF09XCJzaG93RmlsZUxpc3RcIlxyXG4gICAgKHNlbGVjdCk9XCJzZWxlY3RFdmVudEhhbmRsZXIoJGV2ZW50KVwiXHJcbiAgICAocmVtb3ZlKT1cIm9uUmVtb3ZlKCRldmVudClcIlxyXG4gICAgKHN1Y2Nlc3MpPVwib25TdWNjZXNzKCRldmVudClcIlxyXG4gICAgKHVwbG9hZCk9XCJ1cGxvYWRFdmVudEhhbmRsZXIoJGV2ZW50KVwiXHJcbiAgICBbc3R5bGVdPVwiY29tcG9uZW50UHJvcGVydGllcy5zdHlsZS5zdHlsZTFcIlxyXG4gICAgY2xhc3M9XCJlMXRhZy1zdHlsZTFcIj5cclxuICA8L2tlbmRvLXVwbG9hZD5cclxuXHJcbiAgPGtlbmRvLWZpbGVzZWxlY3RcclxuICAgICpuZ0lmPVwiZGF0YS5TZWxlY3RGaWxlT25seVwiXHJcbiAgICAjdXBsb2FkQ29tcG9uZW50XHJcbiAgICBbaWRdPVwiZGF0YS5WYWx1ZVwiXHJcbiAgICAoc2VsZWN0KT1cInNlbGVjdEV2ZW50SGFuZGxlcigkZXZlbnQpXCJcclxuICAgIChyZW1vdmUpPVwib25SZW1vdmUoJGV2ZW50KVwiXHJcbiAgICBbZm9ybUNvbnRyb2xOYW1lXT1cImRhdGEuVmFsdWVcIlxyXG4gICAgKHZhbHVlQ2hhbmdlKT1cIm9uQ2hhbmdlKCRldmVudClcIiBcclxuICAgIFtyZXN0cmljdGlvbnNdPVwicmVzdHJpY3Rpb25zXCJcclxuICAgIFtzdHlsZV09XCJjb21wb25lbnRQcm9wZXJ0aWVzLnN0eWxlLnN0eWxlMVwiXHJcbiAgICBjbGFzcz1cImUxdGFnLXN0eWxlMVwiPlxyXG4gIDwva2VuZG8tZmlsZXNlbGVjdD5cclxuXHJcbiAgPGRpdlxyXG4gICAgKm5nSWY9XCJpbWFnZVByZXZpZXdzLmxlbmd0aFwiXHJcbiAgICBjbGFzcz1cImltYWdlLXByZXZpZXctY29udGFpbmVyIGUxdGFnLXN0eWxlMlwiXHJcbiAgICBbc3R5bGVdPVwiY29tcG9uZW50UHJvcGVydGllcy5zdHlsZS5zdHlsZTJcIj5cclxuICAgIDxkaXZcclxuICAgICAgY2xhc3M9XCJsYWJlbC1jb250YWluZXIgZTF0YWctc3R5bGUzXCJcclxuICAgICAgW3N0eWxlXT1cImNvbXBvbmVudFByb3BlcnRpZXMuc3R5bGUuc3R5bGUzXCI+XHJcbiAgICAgIEltYWdlIFByZXZpZXc6XHJcbiAgICA8L2Rpdj5cclxuICAgIDxkaXZcclxuICAgICAgY2xhc3M9XCJpbWFnZS1jb250YWluZXIgZTF0YWctc3R5bGU0XCJcclxuICAgICAgW3N0eWxlXT1cImNvbXBvbmVudFByb3BlcnRpZXMuc3R5bGUuc3R5bGU0XCI+XHJcbiAgICAgIDxpbWdcclxuICAgICAgICAqbmdGb3I9XCJsZXQgaW1hZ2Ugb2YgaW1hZ2VQcmV2aWV3c1wiXHJcbiAgICAgICAgW3NyY109XCJpbWFnZS5zcmNcIlxyXG4gICAgICAgIGFsdD1cImltYWdlIHByZXZpZXdcIlxyXG4gICAgICAgIGhlaWdodD1cIjEwMFwiXHJcbiAgICAgICAgY2xhc3M9XCJlMXRhZy1zdHlsZTVcIlxyXG4gICAgICAgIFtzdHlsZV09XCJjb21wb25lbnRQcm9wZXJ0aWVzLnN0eWxlLnN0eWxlNVwiIC8+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcbiJdfQ==
594
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoienVwbG9hZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9tbWhnbG9iYWwtZHluYW1pY2Zvcm0vc3JjL2xpYi96dXBsb2FkL3p1cGxvYWQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbW1oZ2xvYmFsLWR5bmFtaWNmb3JtL3NyYy9saWIvenVwbG9hZC96dXBsb2FkLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtCQUErQjtBQUMvQixPQUFPLEVBQUUsU0FBUyxFQUFrQixTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFckUsNkJBQTZCO0FBRTdCLDhCQUE4QjtBQUM5Qiw4REFBOEQ7QUFDOUQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQVl0QywyQ0FBMkM7QUFDM0MsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBRXhFLE9BQU8sRUFHTCxnQkFBZ0IsRUFLaEIsY0FBYyxFQUVkLGdCQUFnQixHQUdqQixNQUFNLGlCQUFpQixDQUFDOzs7Ozs7O0FBY3pCLE1BQU0sT0FBTyxVQUFVO0NBU3RCO0FBT0QsTUFBTSxPQUFPLGdCQUFpQixTQUFRLGNBQWM7SUErQ2xELFlBQ2tCLGdCQUFtQyxFQUNsQyxXQUF3QixFQUN4QixhQUFtQyxFQUNuQyxZQUEwQixFQUMxQixNQUFjLEVBQ2QsaUJBQW9DLEVBQ3BDLFlBQTBCO1FBRTNDLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBUlIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFtQjtRQUNsQyxnQkFBVyxHQUFYLFdBQVcsQ0FBYTtRQUN4QixrQkFBYSxHQUFiLGFBQWEsQ0FBc0I7UUFDbkMsaUJBQVksR0FBWixZQUFZLENBQWM7UUFDMUIsV0FBTSxHQUFOLE1B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TUFBTSxLQUFLLEdBQUcsS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRXhDLHlFQUF5RTtRQUN6RSxPQUFPLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDN0QsQ0FBQzs7NkdBL3BCVSxnQkFBZ0I7aUdBQWhCLGdCQUFnQiw4TENsRTdCLHUyREF1REE7MkZEV2EsZ0JBQWdCO2tCQUw1QixTQUFTOytCQUNFLGFBQWE7Z1JBTWhCLGVBQWU7c0JBRHJCLFNBQVM7dUJBQUMsaUJBQWlCLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKiogQW5ndWxhciAqKioqKioqKioqL1xyXG5pbXBvcnQgeyBDb21wb25lbnQsIE5nWm9uZSwgT25Jbml0LCBWaWV3Q2hpbGQgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xyXG5cclxuLyoqKioqKioqKiogSW9uaWMgKioqKioqKioqKi9cclxuXHJcbi8qKioqKioqKioqIFBsdWdpbiAqKioqKioqKioqL1xyXG4vLyBpbXBvcnQgeyBlbnZpcm9ubWVudCB9IGZyb20gXCJzcmMvZW52aXJvbm1lbnRzL2Vudmlyb25tZW50XCI7XHJcbmltcG9ydCB7IEh0dHBFdmVudFR5cGUgfSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uL2h0dHBcIjtcclxuaW1wb3J0IHsgdGFrZSB9IGZyb20gXCJyeGpzL29wZXJhdG9yc1wiO1xyXG5pbXBvcnQge1xyXG4gIENodW5rU2V0dGluZ3MsXHJcbiAgRmlsZUluZm8sXHJcbiAgRmlsZVJlc3RyaWN0aW9ucyxcclxuICBSZW1vdmVFdmVudCxcclxuICBTZWxlY3RFdmVudCxcclxuICBTdWNjZXNzRXZlbnQsXHJcbiAgVXBsb2FkQ29tcG9uZW50LFxyXG4gIFVwbG9hZEV2ZW50LFxyXG59IGZyb20gXCJAcHJvZ3Jlc3Mva2VuZG8tYW5ndWxhci11cGxvYWRcIjtcclxuXHJcbi8qKioqKioqKioqIENvbXBvbmVudCAmIFNlcnZpY2UgKioqKioqKioqKi9cclxuaW1wb3J0IHsgSW5wdXRGaWVsZEJhc2UgfSBmcm9tIFwiLi4vY29tcG9uZW50cy9pbnB1dGZpZWxkYmFzZS5jb21wb25lbnRcIjtcclxuaW1wb3J0IHsgWkNvbXBvbmVudFNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZXMvemNvbXBvbmVudC5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7XHJcbiAgQWxlcnRTZXJ2aWNlLFxyXG4gIEF0dGFjaG1lbnQsXHJcbiAgQXR0YWNobWVudENvbmZpZyxcclxuICBBdXRoU2VydmljZSxcclxuICBDb21wcmVzc0ltYWdlU2VydmljZSxcclxuICBJbWFnZUNvbXByZXNzaW9uQ29uZmlnLFxyXG4gIFNoYXJlUG9pbnRTZXJ2aWNlLFxyXG4gIFVwbG9hZE1ldGFEYXRhLFxyXG4gIFpDb21wb25lbnQsXHJcbiAgWkNvbXBvbmVudEhlbHBlcixcclxuICBaQ29tcG9uZW50T3V0cHV0RXZlbnQsXHJcbiAgWkNvcmVTZXJ2aWNlLFxyXG59IGZyb20gXCJtbWhnbG9iYWwtemNvcmVcIjtcclxuIFxyXG4vKipcclxuICogS2VuZG8gRmlsZUluZm8gKyBvcHRpb25hbCBiYXNlNjQgcGF5bG9hZCAodXNlZCBieSBTZWxlY3RGaWxlT25seSBtb2RlKS5cclxuICogTk9URTogS2VlcHMgcnVudGltZSBiZWhhdmlvciB0aGUgc2FtZTsgb25seSBpbXByb3ZlcyB0eXBlIHNhZmV0eS5cclxuICovXHJcbnR5cGUgU2VsZWN0ZWRGaWxlRGF0YSA9IEZpbGVJbmZvICYge1xyXG4gIC8qKlxyXG4gICAqIEJhc2U2NCBEYXRhIFVSTCBvciBBcnJheUJ1ZmZlciBmcm9tIEZpbGVSZWFkZXIuXHJcbiAgICogUHJlc2VudCBvbmx5IHdoZW4gU2VsZWN0RmlsZU9ubHkgcmVhZHMgZmlsZSBjb250ZW50IGludG8gbWVtb3J5LlxyXG4gICAqL1xyXG4gIGZpbGU/OiBzdHJpbmcgfCBBcnJheUJ1ZmZlciB8IG51bGw7XHJcbn07XHJcblxyXG5leHBvcnQgY2xhc3MgTXlGaWxlSW5mbyBpbXBsZW1lbnRzIEZpbGVJbmZvIHtcclxuICBwdWJsaWMgbmFtZSE6IHN0cmluZztcclxuICBwdWJsaWMgdWlkPzogc3RyaW5nO1xyXG5cclxuICAvKipcclxuICAgKiBTZXJ2ZXIgb3IgYXBwbGljYXRpb24tZGVmaW5lZCBVSUQgdXNlZCBmb3IgcmVtb3ZlL2Rvd25sb2FkIG9wZXJhdGlvbnMuXHJcbiAgICogKFNldCBmcm9tIEFQSSByZXNwb25zZSBmaWxlVWlkIHdoZW4gdXBsb2FkIHN1Y2NlZWRzKVxyXG4gICAqL1xyXG4gIHB1YmxpYyBteVVpZD86IHN0cmluZztcclxufVxyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6IFwiYXBwLXp1cGxvYWRcIixcclxuICB0ZW1wbGF0ZVVybDogXCIuL3p1cGxvYWQuY29tcG9uZW50Lmh0bWxcIixcclxuICBzdHlsZVVybHM6IFtcIi4venVwbG9hZC5jb21wb25lbnQuc2Nzc1wiXSxcclxufSlcclxuZXhwb3J0IGNsYXNzIFp1cGxvYWRDb21wb25lbnQgZXh0ZW5kcyBJbnB1dEZpZWxkQmFzZSBpbXBsZW1lbnRzIFpDb21wb25lbnQsIE9uSW5pdCB7XHJcbiAgQFZpZXdDaGlsZChcInVwbG9hZENvbXBvbmVudFwiLCB7IHN0YXRpYzogZmFsc2UgfSlcclxuICBwdWJsaWMgdXBsb2FkQ29tcG9uZW50ITogVXBsb2FkQ29tcG9uZW50O1xyXG4gIFxyXG4gIHByaXZhdGUgcmVhZG9ubHkgZGVmYXVsdFVwbG9hZFNhdmVVcmw6IHN0cmluZztcclxuICBwcml2YXRlIHJlYWRvbmx5IGRlZmF1bHRVcGxvYWRSZW1vdmVVcmw6IHN0cmluZztcclxuXHJcbiAgLy8gTk9URTogTmFtaW5nOiBgdWlkYCBhcnJheSBhY3R1YWxseSBzdG9yZXMgcHJldmlldyBVSURzLiBDb25zaWRlciByZW5hbWluZyB0byBgcHJldmlld1VpZHNgIGluIGZ1dHVyZSAobm90IGNoYW5nZWQgdG8gcHJlc2VydmUgQVBJKS5cclxuICBwdWJsaWMgdXBsb2FkQXR0YWNobWVudFVybDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XHJcbiAgcHVibGljIHVwbG9hZFNhdmVVcmwgPSBcIi9BdHRhY2htZW50L0NodW5rX1VwbG9hZF9TYXZlXCI7IC8vIHNob3VsZCByZXByZXNlbnQgYW4gYWN0dWFsIEFQSSBlbmRwb2ludFxyXG4gIHB1YmxpYyB1cGxvYWRSZW1vdmVVcmwgPSBcIi9BdHRhY2htZW50L0NodW5rX1VwbG9hZF9SZW1vdmVcIjsgLy8gc2hvdWxkIHJlcHJlc2VudCBhbiBhY3R1YWwgQVBJIGVuZHBvaW50XHJcbiAgcHVibGljIHJlYWRvbmx5IGRvd25sb2FkRmlsZVVybCA9IFwiL0F0dGFjaG1lbnQvZG93bmxvYWRGaWxlXCI7XHJcbiAgcHVibGljIHJlYWRvbmx5IGdldEltYWdlVXJsID0gXCIvQXR0YWNobWVudC9nZXRJbWFnZVwiOyAvLyBHRVQgbWV0aG9kXHJcblxyXG4gIHB1YmxpYyBpc0F1dG9VcGxvYWQgPSBmYWxzZTtcclxuICBwdWJsaWMgaXNNdWx0aXBsZSA9IGZhbHNlO1xyXG4gIHB1YmxpYyBzaG93RmlsZUxpc3QgPSB0cnVlO1xyXG5cclxuICBwdWJsaWMgaW1hZ2VQcmV2aWV3czogQXJyYXk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+ID0gW107XHJcbiAgcHVibGljIHVpZDogc3RyaW5nW10gPSBbXTtcclxuICBwdWJsaWMgZmlsZUxpc3Q6IFNlbGVjdGVkRmlsZURhdGFbXSA9IFtdO1xyXG5cclxuICBwdWJsaWMgcmVzdHJpY3Rpb25zOiBGaWxlUmVzdHJpY3Rpb25zID0ge1xyXG4gICAgbWluRmlsZVNpemU6IDEsXHJcbiAgICBtYXhGaWxlU2l6ZTogNDE5NDMwNCxcclxuICAgIGFsbG93ZWRFeHRlbnNpb25zOiBbXHJcbiAgICAgIFwianBnXCIsXHJcbiAgICAgIFwianBlZ1wiLFxyXG4gICAgICBcInBuZ1wiLFxyXG4gICAgICBcImJtcFwiLFxyXG4gICAgICBcInBkZlwiLFxyXG4gICAgICBcInR4dFwiLFxyXG4gICAgICBcImRvY3hcIixcclxuICAgICAgXCJkb2NcIixcclxuICAgICAgXCJ4bHN4XCIsXHJcbiAgICAgIFwieGxzXCIsXHJcbiAgICAgIFwicHB0XCIsXHJcbiAgICAgIFwicHB0eFwiLFxyXG4gICAgICBcImNzdlwiLFxyXG4gICAgXSxcclxuICB9O1xyXG5cclxuICBwdWJsaWMgcmVhZG9ubHkgY2h1bmtTZXR0aW5nczogQ2h1bmtTZXR0aW5ncyA9IHtcclxuICAgIHNpemU6IDEwMjQwMCxcclxuICAgIG1heEF1dG9SZXRyaWVzOiAzLFxyXG4gIH07XHJcblxyXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihcclxuICAgIHB1YmxpYyByZWFkb25seSBjb21wb25lbnRTZXJ2aWNlOiBaQ29tcG9uZW50U2VydmljZSxcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgYXV0aFNlcnZpY2U6IEF1dGhTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBjb21wcmVzc0ltYWdlOiBDb21wcmVzc0ltYWdlU2VydmljZSxcclxuICAgIHByaXZhdGUgcmVhZG9ubHkgemNvcmVTZXJ2aWNlOiBaQ29yZVNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IG5nWm9uZTogTmdab25lLFxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBzaGFyZVBvaW50U2VydmljZTogU2hhcmVQb2ludFNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IGFsZXJ0U2VydmljZTogQWxlcnRTZXJ2aWNlXHJcbiAgKSB7XHJcbiAgICBzdXBlcihjb21wb25lbnRTZXJ2aWNlKTtcclxuXHJcbiAgICBjb25zdCBlbnYgPSB0aGlzLnpjb3JlU2VydmljZS5nZXRFbnZpcm9ubWVudCgpO1xyXG4gICAgY29uc3Qgbm9ybWFsaXplZCA9IHRoaXMuemNvcmVTZXJ2aWNlLm5vcm1hbGl6ZVVybChlbnY/LnVwbG9hZEF0dGFjaG1lbnRVcmwpO1xyXG5cclxuICAgIHRoaXMudXBsb2FkQXR0YWNobWVudFVybCA9IG5vcm1hbGl6ZWQgPz8gbnVsbDtcclxuICAgIGlmICh0aGlzLnVwbG9hZEF0dGFjaG1lbnRVcmwpIHtcclxuICAgICAgdGhpcy51cGxvYWRTYXZlVXJsID0gdGhpcy51cGxvYWRBdHRhY2htZW50VXJsICsgdGhpcy51cGxvYWRTYXZlVXJsO1xyXG4gICAgICB0aGlzLnVwbG9hZFJlbW92ZVVybCA9IHRoaXMudXBsb2FkQXR0YWNobWVudFVybCArIHRoaXMudXBsb2FkUmVtb3ZlVXJsO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gU2FmZXIgbG9nZ2luZzogYXZvaWQgc2lsZW50IG51bGwgVVJMcyB0aGF0IGJyZWFrIHVwbG9hZHNcclxuICAgICAgLy8gTk9URTogVGhpcyBpbmRpY2F0ZXMgYSBjb25maWd1cmF0aW9uIGlzc3VlLlxyXG4gICAgICBjb25zb2xlLndhcm4oXHJcbiAgICAgICAgYFtadXBsb2FkQ29tcG9uZW50XSB1cGxvYWRBdHRhY2htZW50VXJsIGlzIGVtcHR5LiBVcGxvYWQgZW5kcG9pbnRzIG1heSBiZSBpbnZhbGlkLmAsXHJcbiAgICAgICAgeyB1cGxvYWRBdHRhY2htZW50VXJsOiBlbnY/LnVwbG9hZEF0dGFjaG1lbnRVcmwgfVxyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuZGVmYXVsdFVwbG9hZFNhdmVVcmwgPSB0aGlzLnVwbG9hZFNhdmVVcmw7XHJcbiAgICB0aGlzLmRlZmF1bHRVcGxvYWRSZW1vdmVVcmwgPSB0aGlzLnVwbG9hZFJlbW92ZVVybDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFuZ3VsYXIgbGlmZWN5Y2xlIGhvb2sgLSBpbml0aWFsaXplcyByZXN0cmljdGlvbnMgYW5kIHVwbG9hZCBiZWhhdmlvciBmcm9tIGZpZWxkIGNvbmZpZy5cclxuICAgKi9cclxuICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XHJcbiAgICBzdXBlci5zZXR1cElubmVyRmllbGQoKTtcclxuXHJcbiAgICAvLyBBbGxvd2VkIGV4dGVuc2lvbnM6XHJcbiAgICAvLyAtIElmIFNlbGVjdE9wdGlvbnMgcHJlc2VudCBhbmQgQWxsb3dlZEZpbGVFeHRlbnNpb24gbm90IHByZXNlbnQsIG92ZXJyaWRlXHJcbiAgICAvLyAtIEVsc2UgaWYgQWxsb3dlZEZpbGVFeHRlbnNpb24gcHJlc2VudCBhbmQgU2VsZWN0T3B0aW9ucyBhYnNlbnQsIGFwcGVuZFxyXG4gICAgLy8gTk9URTogS2VlcCBvcmlnaW5hbCBiZWhhdmlvcjsgaXQgbWF5IGFsbG93IGR1cGxpY2F0ZXMsIGJ1dCBwcmV2ZW50cyB1bmV4cGVjdGVkIHJlc3RyaWN0aW9uIGxvc3MuXHJcbiAgICBpZiAodGhpcy5kYXRhPy5TZWxlY3RPcHRpb25zICYmICF0aGlzLmRhdGE/LkFsbG93ZWRGaWxlRXh0ZW5zaW9uKSB7XHJcbiAgICAgIHRoaXMucmVzdHJpY3Rpb25zLmFsbG93ZWRFeHRlbnNpb25zID0gKHRoaXMuZGF0YS5TZWxlY3RPcHRpb25zIGFzIHVua25vd24pIGFzIHN0cmluZ1tdO1xyXG4gICAgfSBlbHNlIGlmICghdGhpcy5kYXRhPy5TZWxlY3RPcHRpb25zICYmIHRoaXMuZGF0YT8uQWxsb3dlZEZpbGVFeHRlbnNpb24pIHtcclxuICAgICAgdGhpcy5yZXN0cmljdGlvbnMuYWxsb3dlZEV4dGVuc2lvbnMgPSB0aGlzLnJlc3RyaWN0aW9ucy5hbGxvd2VkRXh0ZW5zaW9ucy5jb25jYXQodGhpcy5kYXRhLkFsbG93ZWRGaWxlRXh0ZW5zaW9uKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodHlwZW9mIHRoaXMuZGF0YT8uTWluRmlsZVNpemUgPT09IFwibnVtYmVyXCIgJiYgdGhpcy5kYXRhLk1pbkZpbGVTaXplID49IDApIHtcclxuICAgICAgdGhpcy5yZXN0cmljdGlvbnMubWluRmlsZVNpemUgPSB0aGlzLmRhdGEuTWluRmlsZVNpemU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGVvZiB0aGlzLmRhdGE/Lk1heEZpbGVTaXplID09PSBcIm51bWJlclwiICYmIHRoaXMuZGF0YS5NYXhGaWxlU2l6ZSA+PSAwKSB7XHJcbiAgICAgIHRoaXMucmVzdHJpY3Rpb25zLm1heEZpbGVTaXplID0gdGhpcy5kYXRhLk1heEZpbGVTaXplO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuaXNBdXRvVXBsb2FkID0gQm9vbGVhbih0aGlzLmRhdGE/LkF1dG9VcGxvYWQpO1xyXG5cclxuICAgIC8vIElmIHJlbW92ZSBpcyBub3QgYWxsb3dlZCwgS2VuZG8gdXBsb2FkIGV4cGVjdHMgZW1wdHkgVVJMIHRvIGhpZGUgcmVtb3ZlIHJlcXVlc3QuXHJcbiAgICBpZiAodGhpcy5kYXRhICYmIHRoaXMuZGF0YS5BbGxvd1JlbW92ZSA9PT0gZmFsc2UpIHtcclxuICAgICAgdGhpcy51cGxvYWRSZW1vdmVVcmwgPSBcIlwiO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuaXNNdWx0aXBsZSA9IEJvb2xlYW4odGhpcy5kYXRhPy5NdWx0aXBsZSk7XHJcblxyXG4gICAgLy8gRW5zdXJlIHN0eWxlNiBleGlzdHMgKGxlZ2FjeSBzdHlsaW5nIGhvb2spLlxyXG4gICAgdGhpcy5jb21wb25lbnRQcm9wZXJ0aWVzLnN0eWxlLnN0eWxlNiA9XHJcbiAgICAgIHRoaXMuY29tcG9uZW50UHJvcGVydGllcy5zdHlsZS5zdHlsZTYgfHwgXCJtYXJnaW46IDVweDsgYm9yZGVyOiAxcHggc29saWQgZ3JheTtcIjtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEtlbmRvIFVwbG9hZCBzdWNjZXNzIGNhbGxiYWNrIGZvciBib3RoIHVwbG9hZCBhbmQgcmVtb3ZlLlxyXG4gICAqIEtlZXBzIHpNb2RlbCBpbiBzeW5jIGFuZCBlbWl0cyBaQ29tcG9uZW50IG91dHB1dCBldmVudHMuXHJcbiAgICovXHJcbiAgcHVibGljIG9uU3VjY2VzcyhlOiBTdWNjZXNzRXZlbnQpOiB2b2lkIHtcclxuICAgIC8vIEFuZ3VsYXIgS2VuZG8gVXBsb2FkIGVtaXRzIFwiU2VudFwiIGFuZCBcIlVwbG9hZFByb2dyZXNzXCIgZm9yIHJlbW92ZTsgaWdub3JlIHRoZW0gdG8gYXZvaWQgZG91YmxlLWhhbmRsaW5nLlxyXG4gICAgLy8gQHRzLWlnbm9yZSAtIEtlbmRvIHR5cGVzIGZvciByZXNwb25zZSBkaWZmZXIgYnkgcnVudGltZSB1c2FnZVxyXG4gICAgY29uc3QgcmVzcG9uc2VUeXBlOiBudW1iZXIgfCB1bmRlZmluZWQgPSBlPy5yZXNwb25zZT8udHlwZTtcclxuICAgIGlmIChcclxuICAgICAgZT8ub3BlcmF0aW9uID09PSBcInJlbW92ZVwiICYmXHJcbiAgICAgIChyZXNwb25zZVR5cGUgPT09IEh0dHBFdmVudFR5cGUuU2VudCB8fCByZXNwb25zZVR5cGUgPT09IEh0dHBFdmVudFR5cGUuVXBsb2FkUHJvZ3Jlc3MpXHJcbiAgICApIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IG1vZGVsS2V5ID0gdGhpcy5kYXRhPy5WYWx1ZTtcclxuICAgIGlmICghbW9kZWxLZXkpIHtcclxuICAgICAgY29uc29sZS53YXJuKGBbWnVwbG9hZENvbXBvbmVudF0gb25TdWNjZXNzIHNraXBwZWQ6IG1pc3NpbmcgZGF0YS5WYWx1ZS5gLCB7IGV2ZW50OiBlIH0pO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCF0aGlzLmdyb3VwPy56TW9kZWwpIHtcclxuICAgICAgY29uc29sZS53YXJuKGBbWnVwbG9hZENvbXBvbmVudF0gb25TdWNjZXNzIHNraXBwZWQ6IG1pc3NpbmcgZ3JvdXAuek1vZGVsLmAsIHsgZXZlbnQ6IGUgfSk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodGhpcy5ncm91cC56TW9kZWxbbW9kZWxLZXldKSkge1xyXG4gICAgICB0aGlzLmdyb3VwLnpNb2RlbFttb2RlbEtleV0gPSBbXTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBmaWxlID0gKGU/LmZpbGVzPy5bMF0gYXMgTXlGaWxlSW5mbyB8IHVuZGVmaW5lZCkgPz8gdW5kZWZpbmVkO1xyXG4gICAgaWYgKCFmaWxlKSB7XHJcbiAgICAgIGNvbnNvbGUud2FybihgW1p1cGxvYWRDb21wb25lbnRdIG9uU3VjY2Vzczogbm8gZmlsZSBmb3VuZCBpbiBldmVudC5gLCB7IGV2ZW50OiBlIH0pO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgZXhpc3RpbmdGaWxlSW5kZXggPSB0aGlzLmdyb3VwLnpNb2RlbFttb2RlbEtleV0uZmluZEluZGV4KFxyXG4gICAgICAoZjogTXlGaWxlSW5mbykgPT4gZj8ubmFtZSA9PT0gZmlsZS5uYW1lICYmIGY/LnVpZCA9PT0gZmlsZS51aWRcclxuICAgICk7XHJcblxyXG4gICAgaWYgKGUub3BlcmF0aW9uID09PSBcInVwbG9hZFwiKSB7XHJcbiAgICAgIC8vIFNoYXJlUG9pbnQgYW5kIEF0dGFjaG1lbnQgdXNlIGZpbGVVaWQgKHNlcnZlcikgZm9yIGxhdGVyIG9wZXJhdGlvbnMuXHJcbiAgICAgIC8vIFByZWZlciBmaWxlVWlkIGlmIHByb3ZpZGVkOyBmYWxsYmFjayB0byBmaWxlLnVpZFxyXG4gICAgICAvLyBAdHMtaWdub3JlIC0gYm9keSBzaGFwZSBpcyBydW50aW1lLWRlcGVuZGVudFxyXG4gICAgICBmaWxlLm15VWlkID0gZT8ucmVzcG9uc2U/LmJvZHk/LmZpbGVVaWQgPz8gZmlsZS51aWQ7XHJcblxyXG4gICAgICAvLyBDbGVhbiB1cCBpbnRlcm5hbCBzdWJzY3JpcHRpb24gZGF0YSB0byBhdm9pZCBjaXJjdWxhciBzdHJ1Y3R1cmVzXHJcbiAgICAgIC8vIE5PVEU6IFRoaXMgcmVsaWVzIG9uIEtlbmRvIGF0dGFjaGluZyBpbnRlcm5hbCBmaWVsZHM7IHNhZmUgZGVsZXRlLlxyXG4gICAgICBkZWxldGUgKGZpbGUgYXMgdW5rbm93biBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPilbXCJodHRwU3Vic2NyaXB0aW9uXCJdO1xyXG5cclxuICAgICAgaWYgKGV4aXN0aW5nRmlsZUluZGV4ICE9PSAtMSkge1xyXG4gICAgICAgIHRoaXMuZ3JvdXAuek1vZGVsW21vZGVsS2V5XVtleGlzdGluZ0ZpbGVJbmRleF0gPSBmaWxlO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuZ3JvdXAuek1vZGVsW21vZGVsS2V5XS5wdXNoKGZpbGUpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zb2xlLmluZm8oYFtadXBsb2FkQ29tcG9uZW50XSBVcGxvYWQgc3VjY2VlZGVkLmAsIHtcclxuICAgICAgICBuYW1lOiBmaWxlLm5hbWUsXHJcbiAgICAgICAgdWlkOiBmaWxlLnVpZCxcclxuICAgICAgICBteVVpZDogZmlsZS5teVVpZCxcclxuICAgICAgfSk7XHJcbiAgICB9IGVsc2UgaWYgKGUub3BlcmF0aW9uID09PSBcInJlbW92ZVwiKSB7XHJcbiAgICAgIGlmIChleGlzdGluZ0ZpbGVJbmRleCAhPT0gLTEpIHtcclxuICAgICAgICB0aGlzLmdyb3VwLnpNb2RlbFttb2RlbEtleV0uc3BsaWNlKGV4aXN0aW5nRmlsZUluZGV4LCAxKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgY29uc29sZS5pbmZvKGBbWnVwbG9hZENvbXBvbmVudF0gUmVtb3ZlIHN1Y2NlZWRlZC5gLCB7XHJcbiAgICAgICAgbmFtZTogZmlsZS5uYW1lLFxyXG4gICAgICAgIHVpZDogZmlsZS51aWQsXHJcbiAgICAgICAgbXlVaWQ6IGZpbGUubXlVaWQsXHJcbiAgICAgIH0pO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gVW5rbm93biBvcGVyYXRpb24sIHByZXNlcnZlIGJlaGF2aW9yIGJ1dCBsb2cgZm9yIGRpYWdub3N0aWNzLlxyXG4gICAgICBjb25zb2xlLmRlYnVnKGBbWnVwbG9hZENvbXBvbmVudF0gb25TdWNjZXNzIHJlY2VpdmVkIHVuc3VwcG9ydGVkIG9wZXJhdGlvbi5gLCB7IG9wZXJhdGlvbjogZS5vcGVyYXRpb24sIGV2ZW50OiBlIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIFpDb21wb25lbnRIZWxwZXIuc2V0Q29tcG9uZW50TW9kZWxWYWx1ZSh0aGlzLmRhdGEsIHRoaXMuZ3JvdXAuek1vZGVsW21vZGVsS2V5XSwgdGhpcy5ncm91cCk7XHJcblxyXG4gICAgdGhpcy5ncm91cC5zdWJqZWN0Py5uZXh0KHtcclxuICAgICAgdHlwZTogXCJ6dXBsb2FkLW9uU3VjY2Vzc1wiLFxyXG4gICAgICB0YXJnZXQ6IHRoaXMuZGF0YT8uT25TdWNjZXNzLFxyXG4gICAgICBldmVudDogZSxcclxuICAgICAgZGF0YTogeyB2YWx1ZTogZmlsZSwgZmllbGQ6IHRoaXMuZGF0YSB9LFxyXG4gICAgfSBhcyBaQ29tcG9uZW50T3V0cHV0RXZlbnQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTm9ybWFsaXplIGFuZCBlbnJpY2ggaW1hZ2UgY29tcHJlc3Npb24gY29uZmlnIHdpdGggYnl0ZS1iYXNlZCB0aHJlc2hvbGRzLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgY29tcHJlc3Npb25Db25maWdIYW5kbGVyKGltZ0NvbmZpZzogSW1hZ2VDb21wcmVzc2lvbkNvbmZpZyk6IEltYWdlQ29tcHJlc3Npb25Db25maWcge1xyXG4gICAgaWYgKCFpbWdDb25maWcpIHtcclxuICAgICAgLy8gTk9URToga2VlcCBmdW5jdGlvbiBzYWZlIGZvciB1bmV4cGVjdGVkIG51bGw7IHJldHVybnMgYXMtaXNcclxuICAgICAgcmV0dXJuIGltZ0NvbmZpZztcclxuICAgIH1cclxuXHJcbiAgICBpZiAoaW1nQ29uZmlnLkZpbGVTaXplTWF4U2l6ZSkge1xyXG4gICAgICBpbWdDb25maWcuRmlsZVNpemVNYXhTaXplQnl0ZSA9IHRoaXMuY29udmVydFNpemVUb0J5dGUoaW1nQ29uZmlnLkZpbGVTaXplTWF4U2l6ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGltZ0NvbmZpZy5GaWxlU2l6ZU1pblNpemUpIHtcclxuICAgICAgaW1nQ29uZmlnLkZpbGVTaXplTWluU2l6ZUJ5dGUgPSB0aGlzLmNvbnZlcnRTaXplVG9CeXRlKGltZ0NvbmZpZy5GaWxlU2l6ZU1pblNpemUpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaW1nQ29uZmlnLkZpbGVTaXplTWluU2l6ZUJ5dGUgPSAwO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBpbWdDb25maWc7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDb252ZXJ0IHN0cmluZyBzaXplIHZhbHVlcyBsaWtlIFwiMTBLQlwiLCBcIjIgTUJcIiwgXCIxZ2JcIiwgXCIxMDI0XCIgaW50byBieXRlcy5cclxuICAgKiBJZiB1bml0IGlzIG9taXR0ZWQsIGJ5dGVzIGFyZSBhc3N1bWVkLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHNpemVTdHJpbmcgSHVtYW4gcmVhZGFibGUgc2l6ZSBzdHJpbmcuXHJcbiAgICogQHJldHVybnMgU2l6ZSBpbiBieXRlcy4gUmV0dXJucyAwIGlmIHBhcnNpbmcgZmFpbHMuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBjb252ZXJ0U2l6ZVRvQnl0ZShzaXplU3RyaW5nOiBzdHJpbmcpOiBudW1iZXIge1xyXG4gICAgaWYgKCFzaXplU3RyaW5nIHx8IHR5cGVvZiBzaXplU3RyaW5nICE9PSBcInN0cmluZ1wiKSB7XHJcbiAgICAgIHJldHVybiAwO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFJlbW92ZSBhbGwgc3BhY2VzXHJcbiAgICBjb25zdCByYXcgPSBzaXplU3RyaW5nLnJlcGxhY2UoLyAvZywgXCJcIikudHJpbSgpO1xyXG4gICAgaWYgKCFyYXcpIHtcclxuICAgICAgcmV0dXJuIDA7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHBhcnNlZFZhbHVlID0gMDtcclxuICAgIGxldCBzaXplQnlCeXRlID0gMDtcclxuICAgIGxldCBzaXplVHlwZSA9IFwiYlwiO1xyXG5cclxuICAgIC8vIENoZWNrIGxhc3QgY2hhciBpcyBhbHBoYWJldGljXHJcbiAgICBjb25zdCBsYXN0Q2hhciA9IHJhdy5zdWJzdHJpbmcocmF3Lmxlbmd0aCAtIDEpO1xyXG4gICAgY29uc3QgbGFzdENoYXJJc051bWJlciA9ICFOdW1iZXIuaXNOYU4oTnVtYmVyLnBhcnNlRmxvYXQobGFzdENoYXIpKTtcclxuXHJcbiAgICBpZiAoIWxhc3RDaGFySXNOdW1iZXIpIHtcclxuICAgICAgY29uc3Qgc2Vjb25kTGFzdENoYXIgPSByYXcuc3Vic3RyaW5nKHJhdy5sZW5ndGggLSAyKS5zbGljZSgwLCAtMSk7XHJcbiAgICAgIGNvbnN0IHNlY29uZExhc3RJc051bWJlciA9ICFOdW1iZXIuaXNOYU4oTnVtYmVyLnBhcnNlRmxvYXQoc2Vjb25kTGFzdENoYXIpKTtcclxuXHJcbiAgICAgIGlmICghc2Vjb25kTGFzdElzTnVtYmVyKSB7XHJcbiAgICAgICAgLy8gTGFzdCAybmQgY2hhciBpcyBhbHNvIGFscGhhYmV0aWMgKGUuZy4gXCJNQlwiLCBcIkdCXCIpXHJcbiAgICAgICAgc2l6ZVR5cGUgPSBgJHtzZWNvbmRMYXN0Q2hhcn0ke3NpemVUeXBlfWA7XHJcbiAgICAgICAgcGFyc2VkVmFsdWUgPSBOdW1iZXIucGFyc2VGbG9hdChyYXcuc2xpY2UoMCwgLTIpKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBwYXJzZWRWYWx1ZSA9IE51bWJlci5wYXJzZUZsb2F0KHJhdy5zbGljZSgwLCAtMSkpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBJZiBwYXJzaW5nIGZhaWxlZCwgcmV0dXJuIDAgKFNvbmFyUXViZSBzYWZlIGJlaGF2aW9yKVxyXG4gICAgICBpZiAoTnVtYmVyLmlzTmFOKHBhcnNlZFZhbHVlKSB8fCBwYXJzZWRWYWx1ZSA8IDApIHtcclxuICAgICAgICBjb25zb2xlLndhcm4oYFtadXBsb2FkQ29tcG9uZW50XSBjb252ZXJ0U2l6ZVRvQnl0ZTogaW52YWxpZCBzaXplIHZhbHVlLmAsIHsgc2l6ZVN0cmluZyB9KTtcclxuICAgICAgICByZXR1cm4gMDtcclxuICAgICAgfVxyXG5cclxuICAgICAgc3dpdGNoIChzaXplVHlwZS50b0xvd2VyQ2FzZSgpKSB7XHJcbiAgICAgICAgY2FzZSBcImJcIjpcclxuICAgICAgICAgIHNpemVCeUJ5dGUgPSBwYXJzZWRWYWx1ZTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgXCJrYlwiOlxyXG4gICAgICAgICAgc2l6ZUJ5Qnl0ZSA9IHBhcnNlZFZhbHVlICogMTAyNDtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgXCJtYlwiOlxyXG4gICAgICAgICAgc2l6ZUJ5Qnl0ZSA9IHBhcnNlZFZhbHVlICogMV8wNDhfNTc2O1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgY2FzZSBcImdiXCI6XHJcbiAgICAgICAgICBzaXplQnlCeXRlID0gcGFyc2VkVmFsdWUgKiAxXzA3M183NDFfODI0O1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgIC8vIFVua25vd24gdW5pdCA9PiB0cmVhdCBhcyBieXRlcyBmb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eVxyXG4gICAgICAgICAgY29uc29sZS53YXJuKGBbWnVwbG9hZENvbXBvbmVudF0gY29udmVydFNpemVUb0J5dGU6IHVua25vd24gdW5pdCwgZGVmYXVsdGluZyB0byBieXRlcy5gLCB7XHJcbiAgICAgICAgICAgIHNpemVTdHJpbmcsXHJcbiAgICAgICAgICAgIHVuaXQ6IHNpemVUeXBlLFxyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgICBzaXplQnlCeXRlID0gcGFyc2VkVmFsdWU7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gRGVmYXVsdCB1c2luZyBieXRlcyBpZiBubyBzaXplIHR5cGVcclxuICAgICAgY29uc3QgbiA9IE51bWJlci5wYXJzZUZsb2F0KHJhdyk7XHJcbiAgICAgIGlmIChOdW1iZXIuaXNOYU4obikgfHwgbiA8IDApIHtcclxuICAgICAgICBjb25zb2xlLndhcm4oYFtadXBsb2FkQ29tcG9uZW50XSBjb252ZXJ0U2l6ZVRvQnl0ZTogaW52YWxpZCBudW1lcmljIGJ5dGVzIHZhbHVlLmAsIHsgc2l6ZVN0cmluZyB9KTtcclxuICAgICAgICByZXR1cm4gMDtcclxuICAgICAgfVxyXG4gICAgICBzaXplQnlCeXRlID0gbjtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gc2l6ZUJ5Qnl0ZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEtlbmRvIFVwbG9hZCB1cGxvYWQgZXZlbnQ6IHZhbGlkYXRlcyBmaWxlcywgYnVpbGRzIGltYWdlIHByZXZpZXdzLCBpbmplY3RzIG1ldGFkYXRhIGFuZCBhdXRoIGhlYWRlci5cclxuICAgKi9cclxuICBwdWJsaWMgdXBsb2FkRXZlbnRIYW5kbGVyKGU6IFVwbG9hZEV2ZW50KTogdm9pZCB7XHJcbiAgICBpZiAoIWU/LmZpbGVzPy5sZW5ndGgpIHtcclxuICAgICAgY29uc29sZS53YXJuKGBbWnVwbG9hZENvbXBvbmVudF0gdXBsb2FkRXZlbnRIYW5kbGVyOiBubyBmaWxlcyBpbiBVcGxvYWRFdmVudC5gKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEltYWdlIFByZXZpZXdcclxuICAgIGUuZmlsZXMuZm9yRWFjaCgoZmlsZTogRmlsZUluZm8pID0+IHtcclxuICAgICAgaWYgKCF0aGlzLmlzVmFsaWRVcGxvYWRlZEZpbGUoZmlsZSkpIHtcclxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoZmlsZT8ucmF3RmlsZT8udHlwZT8uaW5jbHVkZXMoXCJpbWFnZVwiKSAmJiAhZmlsZS52YWxpZGF0aW9uRXJyb3JzKSB7XHJcbiAgICAgICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcclxuICAgICAgICByZWFkZXIub25sb2FkID0gKCkgPT4ge1xyXG4gICAgICAgICAgaWYgKHRoaXMuZGF0YT8uRW5hYmxlSW1hZ2VQcmV2aWV3KSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy51aWQuaW5jbHVkZXMoZmlsZS51aWQpKSB7XHJcbiAgICAgICAgICAgICAgdGhpcy51aWQucHVzaChmaWxlLnVpZCk7XHJcbiAgICAgICAgICAgICAgdGhpcy5pbWFnZVByZXZpZXdzLnB1c2goeyAuLi5maWxlLCBzcmM6IHJlYWRlci5yZXN1bHQgYXMgc3RyaW5nIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuICAgICAgICByZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlLnJhd0ZpbGUpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICAvLyBBZGQgbWV0YWRhdGEgdG8gdGhlIHVwbG9hZCBldmVudFxyXG4gICAgbGV0IGFkZGl0aW9uYWw6IFVwbG9hZE1ldGFEYXRhID0gWkNvbXBvbmVudEhlbHBlci5nZXRHcm91cEV2YWxWYWx1ZS5jYWxsKHRoaXMsIHRoaXMuZGF0YT8uVXBsb2FkTWV0YURhdGEpO1xyXG5cclxuICAgIGlmICghKGFkZGl0aW9uYWwgaW5zdGFuY2VvZiBVcGxvYWRNZXRhRGF0YSkpIHtcclxuICAgICAgY29uc29sZS53YXJuKFxyXG4gICAgICAgIGBbWnVwbG9hZENvbXBvbmVudF0gSW52YWxpZCBVcGxvYWRNZXRhRGF0YSBhdCBcIiR7dGhpcy5kYXRhPy5VcGxvYWRNZXRhRGF0YX1cIi4gRmFsbGJhY2sgdG8gZGVmYXVsdCBtZXRhZGF0YS5gLFxyXG4gICAgICAgIGFkZGl0aW9uYWxcclxuICAgICAgKTtcclxuICAgICAgYWRkaXRpb25hbCA9IG5ldyBVcGxvYWRNZXRhRGF0YShudWxsLCBcIjBcIik7XHJcbiAgICB9XHJcblxyXG4gICAgLy8jcmVnaW9uIHNoYXJlcG9pbnRcclxuICAgIGNvbnN0IGF0dGFjaG1lbnRJbmZvOiBBdHRhY2htZW50IHwgbnVsbCA9IHRoaXMuc2hhcmVQb2ludFNlcnZpY2UuZ2V0QXR0YWNobWVudEluZm8odGhpcy5kYXRhPy5bXCJEb3dubG9hZEZpbGVDb25maWdcIl0pO1xyXG5cclxuICAgIC8vIEFkZCB0YWdnaW5nIGludG8gbWV0YWRhdGFcclxuICAgIGlmIChhdHRhY2htZW50SW5mbykge1xyXG4gICAgICBpZiAoYXR0YWNobWVudEluZm8udGFnKSB7XHJcbiAgICAgICAgY29uc3QgdGFnID0gdGhpcy5zaGFyZVBvaW50U2VydmljZS5nZW5lcmF0ZVRhZ2dpbmcodGhpcy5ncm91cCwgYXR0YWNobWVudEluZm8udGFnKTtcclxuICAgICAgICAoYWRkaXRpb25hbCBhcyB1bmtub3duIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KVtBdHRhY2htZW50Q29uZmlnLnRhZ10gPSB0YWc7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIChhZGRpdGlvbmFsIGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW0F0dGFjaG1lbnRDb25maWcuc2l0ZU5hbWVdID0gYXR0YWNobWVudEluZm8uc2l0ZU5hbWU7XHJcbiAgICAgIChhZGRpdGlvbmFsIGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW0F0dGFjaG1lbnRDb25maWcuZG9jdW1lbnRMaWJyYXJ5TmFtZV0gPSBhdHRhY2htZW50SW5mby5kb2N1bWVudExpYnJhcnlOYW1lO1xyXG4gICAgICAoYWRkaXRpb25hbCBhcyB1bmtub3duIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KVtBdHRhY2htZW50Q29uZmlnLmlzU2F2ZVRvU2hhcmVQb2ludF0gPSBhdHRhY2htZW50SW5mby5pc1NhdmVUb1NoYXJlUG9pbnQ7XHJcbiAgICB9XHJcbiAgICAvLyNlbmRyZWdpb25cclxuICBcclxuICAgIChhZGRpdGlvbmFsIGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW0F0dGFjaG1lbnRDb25maWcucHJvamVjdENvZGVdID0gdGhpcy5kYXRhPy5Qcm9qZWN0Q29kZTtcclxuICAgIChhZGRpdGlvbmFsIGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW0F0dGFjaG1lbnRDb25maWcubW9kdWxlQ29kZV0gPSB0aGlzLmRhdGE/Lk1vZHVsZUNvZGU7XHJcbiAgICBcclxuICAgIGNvbnN0IHBheWxvYWQgPSBKU09OLnN0cmluZ2lmeShhZGRpdGlvbmFsKTtcclxuICAgIGUuZGF0YSA9IHsgYWRkaXRpb25hbDogcGF5bG9hZCB9O1xyXG5cclxuICAgIC8vIE5PVEU6IFBvdGVudGlhbGx5IHVuc2FmZTogYXNzdW1lcyB0b2tlbiBpcyBhbHdheXMgcHJlc2VudC4gS2VlcCBiZWhhdmlvciBidXQgYWRkIGNsZWFyZXIgbG9nZ2luZy5cclxuICAgIGNvbnN0IHRva2VuID0gdGhpcy5hdXRoU2VydmljZT8uZTFBY2Nlc3NUb2tlbjtcclxuICAgIGlmICghdG9rZW4pIHtcclxuICAgICAgY29uc29sZS53YXJuKGBbWnVwbG9hZENvbXBvbmVudF0gTWlzc2luZyBlMUFjY2Vzc1Rva2VuLiBVcGxvYWQgbWF5IGZhaWwgZHVlIHRvIGF1dGhvcml6YXRpb24uYCk7XHJcbiAgICB9XHJcbiAgICBlLmhlYWRlcnMgPSBlLmhlYWRlcnMuYXBwZW5kKFwiQXV0aG9yaXphdGlvblwiLCBgQmVhcmVyICR7dG9rZW4gPz8gXCJcIn1gKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEtlbmRvIFVwbG9hZCByZW1vdmUgZXZlbnQ6IHVwZGF0ZXMgY29tcG9uZW50IG1lbW9yeSwgZmlyZXMgcHJvamVjdCBldmVudCBpZiBkZWZpbmVkLFxyXG4gICAqIG90aGVyd2lzZSBhdHRhY2hlcyByZXF1aXJlZCBwYXlsb2FkIGFuZCBhdXRob3JpemF0aW9uIGhlYWRlcnMuXHJcbiAgICovXHJcbiAgcHVibGljIG9uUmVtb3ZlKGU6IFJlbW92ZUV2ZW50KTogdm9pZCB7XHJcbiAgICBjb25zdCBmaWxlID0gZT8uZmlsZXM/LlswXTtcclxuICAgIGlmICghZmlsZSkge1xyXG4gICAgICBjb25zb2xlLndhcm4oYFtadXBsb2FkQ29tcG9uZW50XSBvblJlbW92ZTogbm8gZmlsZSBmb3VuZCBpbiBSZW1vdmVFdmVudC5gLCB7IGV2ZW50OiBlIH0pO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmVtb3ZlIGZpbGUgZnJvbSBjb21wb25lbnQgbWVtb3J5IChmb3IgU2VsZWN0RmlsZU9ubHkgZmxvdylcclxuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5maWxlTGlzdC5maW5kSW5kZXgoKGl0ZW0pID0+IGl0ZW0udWlkID09PSBmaWxlLnVpZCk7XHJcbiAgICBpZiAoaW5kZXggPj0gMCkge1xyXG4gICAgICB0aGlzLmZpbGVMaXN0LnNwbGljZShpbmRleCwgMSk7XHJcbiAgICAgIHRoaXMuZ3JvdXBbYHp1cGxvYWRfJHt0aGlzLmRhdGE/LlZhbHVlfWBdID0gdGhpcy5maWxlTGlzdDtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCByZW1vdmVkRXZlbnQgPSB0aGlzLmRhdGE/LltcIkZpbGVSZW1vdmVkRXZlbnRcIl07XHJcbiAgICBpZiAocmVtb3ZlZEV2ZW50KSB7XHJcbiAgICAgIHRoaXMuZ3JvdXAuc3ViamVjdD8ubmV4dCh7XHJcbiAgICAgICAgdHlwZTogXCJ6dXBsb2FkLWZpbGVSZW1vdmVkRXZlbnRcIixcclxuICAgICAgICB0YXJnZXQ6IHJlbW92ZWRFdmVudCxcclxuICAgICAgICBkYXRhOiBlLFxyXG4gICAgICB9IGFzIFpDb21wb25lbnRPdXRwdXRFdmVudCk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBteUZpbGUgPSBmaWxlIGFzIE15RmlsZUluZm87XHJcblxyXG4gICAgLy8gQXR0YWNoIHJlbW92ZSBwYXlsb2FkXHJcbiAgICBlLmRhdGEgPSB7IGlkOiBteUZpbGUubXlVaWQgfTtcclxuXHJcbiAgICBjb25zdCB0b2tlbiA9IHRoaXMuYXV0aFNlcnZpY2U/LmUxQWNjZXNzVG9rZW47XHJcbiAgICBpZiAoIXRva2VuKSB7XHJcbiAgICAgIGNvbnNvbGUud2FybihgW1p1cGxvYWRDb21wb25lbnRdIE1pc3NpbmcgZTFBY2Nlc3NUb2tlbi4gUmVtb3ZlIG1heSBmYWlsIGR1ZSB0byBhdXRob3JpemF0aW9uLmApO1xyXG4gICAgfVxyXG5cclxuICAgIGUuaGVhZGVycyA9IGUuaGVhZGVycy5hcHBlbmQoXCJBdXRob3JpemF0aW9uXCIsIGBCZWFyZXIgJHt0b2tlbiA/PyBcIlwifWApO1xyXG5cclxuICAgIC8vIFJlbW92ZSBwcmV2aWV3IGlmIGVuYWJsZWRcclxuICAgIGlmICh0aGlzLmRhdGE/LkVuYWJsZUltYWdlUHJldmlldykge1xyXG4gICAgICBlLmZpbGVzLmZvckVhY2goKGY6IEZpbGVJbmZvKSA9PiB7XHJcbiAgICAgICAgdGhpcy5pbWFnZVByZXZpZXdzID0gdGhpcy5pbWFnZVByZXZpZXdzLmZpbHRlcigocCkgPT4gcD8uW1widWlkXCJdICE9PSBmLnVpZCk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnNvbGUuaW5mbyhgW1p1cGxvYWRDb21wb25lbnRdIFJlbW92ZSByZXF1ZXN0ZWQuYCwgeyBuYW1lOiBteUZpbGUubmFtZSwgdWlkOiBteUZpbGUudWlkLCBteVVpZDogbXlGaWxlLm15VWlkIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogS2VuZG8gVXBsb2FkIGNoYW5nZSBldmVudCBoYW5kbGVyLiBFbWl0cyBwcm9qZWN0IGV2ZW50IGlmIGNvbmZpZ3VyZWQuXHJcbiAgICovXHJcbiAgcHVibGljIG9uQ2hhbmdlKGZpbGVzOiBGaWxlSW5mb1tdKTogdm9pZCB7XHJcbiAgICBjb25zdCBjaGFuZ2VkRXZlbnQgPSB0aGlzLmRhdGE/LltcIkZpbGVDaGFuZ2VkRXZlbnRcIl07XHJcbiAgICBpZiAoIWNoYW5nZWRFdmVudCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5ncm91cC5zdWJqZWN0Py5uZXh0KHtcclxuICAgICAgdHlwZTogXCJ6dXBsb2FkLWZpbGVDaGFuZ2VkRXZlbnRcIixcclxuICAgICAgdGFyZ2V0OiBjaGFuZ2VkRXZlbnQsXHJcbiAgICAgIGRhdGE6IGZpbGVzLFxyXG4gICAgfSBhcyBaQ29tcG9uZW50T3V0cHV0RXZlbnQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVmFsaWRhdGUgYSBzZWxlY3RlZC91cGxvYWRlZCBmaWxlIGFnYWluc3QgY29uZmlndXJlZCByZXN0cmljdGlvbnMgKHNpemUgKyBleHRlbnNpb24pLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIGZpbGUgS2VuZG8gRmlsZUluZm9cclxuICAgKiBAcmV0dXJucyB0cnVlIGlmIGZpbGUgcGFzc2VzIHJlc3RyaWN0aW9ucywgb3RoZXJ3aXNlIGZhbHNlIChhbmQgc2hvd3MgYWxlcnQpLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgaXNWYWxpZFVwbG9hZGVkRmlsZShmaWxlOiBGaWxlSW5mbyk6IGJvb2xlYW4ge1xyXG4gICAgY29uc3QgcmF3RmlsZSA9IGZpbGU/LnJhd0ZpbGU7XHJcbiAgICBpZiAoIXJhd0ZpbGUpIHtcclxuICAgICAgLy8gTk9URTogS2VuZG8gY2FuIHByb3ZpZGUgRmlsZUluZm8gd2l0aG91dCByYXdGaWxlIGluIHNvbWUgZXZlbnRzLiBQcmVzZXJ2ZSBiZWhhdmlvcjogdHJlYXQgYXMgaW52YWxpZC5cclxuICAgICAgY29uc29sZS53YXJuKGBbWnVwbG9hZENvbXBvbmVudF0gRmlsZSB2YWxpZGF0aW9uIGZhaWxlZDogcmF3RmlsZSBpcyBtaXNzaW5nLmAsIHsgZmlsZSB9KTtcclxuICAgICAgdGhpcy5hbGVydFNlcnZpY2Uuc2hvd09rYXkoXCJGYWlsZWQgdG8gdXBsb2FkXCIsIFwiRmlsZSBpcyBub3QgYXZhaWxhYmxlIGZvciB1cGxvYWQuXCIsIFtcImNvbC00XCJdKTtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGZpbGVTaXplID0gcmF3RmlsZS5zaXplID8/IDA7XHJcblxyXG4gICAgLy8gS2VlcCBvcmlnaW5hbCBiZWhhdmlvcjogdXNlcyBsYXN0IHNlZ21lbnQgYWZ0ZXIgZG90LlxyXG4gICAgLy8gTk9URTogUG90ZW50aWFsbHkgdW5zYWZlIGZvciBmaWxlcyB3aXRob3V0IGV4dGVuc2lvbjsgd2lsbCByZXN1bHQgaW4gZW1wdHkgZXh0ZW5zaW9uLlxyXG4gICAgY29uc3QgZmlsZUV4dGVuc2lvbiA9IChyYXdGaWxlLm5hbWU/LnNwbGl0KFwiLlwiKS5wb3AoKSA/PyBcIlwiKS50b0xvd2VyQ2FzZSgpO1xyXG5cclxuICAgIGNvbnN0IG1heCA9IHRoaXMucmVzdHJpY3Rpb25zPy5tYXhGaWxlU2l6ZSA/PyAwO1xyXG4gICAgY29uc3QgYWxsb3dlZCA9IHRoaXMucmVzdHJpY3Rpb25zPy5hbGxvd2VkRXh0ZW5zaW9ucyA/PyBbXTtcclxuXHJcbiAgICBjb25zdCBpc0V4dGVuc2lvbkFsbG93ZWQgPSBhbGxvd2VkLmluY2x1ZGVzKGZpbGVFeHRlbnNpb24pO1xyXG4gICAgY29uc3QgaXNTaXplQWxsb3dlZCA9IGZpbGVTaXplIDw9IG1heDtcclxuXHJcbiAgICBpZiAoIWlzRXh0ZW5zaW9uQWxsb3dlZCB8fCAhaXNTaXplQWxsb3dlZCkge1xyXG4gICAgICBsZXQgZXJyb3JNZXNzYWdlID0gXCJFcnJvcjpcIjtcclxuICAgICAgaWYgKCFpc0V4dGVuc2lvbkFsbG93ZWQpIHtcclxuICAgICAgICBlcnJvck1lc3NhZ2UgPSBgSW52YWxpZCBmaWxlIHR5cGUgXCIke2ZpbGVFeHRlbnNpb24gfHwgXCJ1bmtub3duXCJ9XCIuIEFsbG93ZWQgdHlwZXM6ICR7YWxsb3dlZC5qb2luKFwiLCBcIil9LmA7XHJcbiAgICAgIH0gZWxzZSBpZiAoIWlzU2l6ZUFsbG93ZWQpIHtcclxuICAgICAgICBlcnJvck1lc3NhZ2UgPSBgRmlsZSBzaXplIGNhbm5vdCBleGNlZWQgJHt0aGlzLmZvcm1hdEZpbGVTaXplKG1heCl9LmA7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnNvbGUud2FybihgW1p1cGxvYWRDb21wb25lbnRdIEZpbGUgcmVqZWN0ZWQgYnkgcmVzdHJpY3Rpb25zLmAsIHtcclxuICAgICAgICBuYW1lOiByYXdGaWxlLm5hbWUsXHJcbiAgICAgICAgc2l6ZTogZmlsZVNpemUsXHJcbiAgICAgICAgZXh0ZW5zaW9uOiBmaWxlRXh0ZW5zaW9uLFxyXG4gICAgICAgIG1heEFsbG93ZWRCeXRlczogbWF4LFxyXG4gICAgICAgIGFsbG93ZWRFeHRlbnNpb25zOiBhbGxvd2VkLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRoaXMuYWxlcnRTZXJ2aWNlLnNob3dPa2F5KFwiRmFpbGVkIHRvIHVwbG9hZFwiLCBlcnJvck1lc3NhZ2UsIFtcImNvbC00XCJdKTtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0cnVlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogS2VuZG8gVXBsb2FkIHNlbGVjdCBldmVudCBoYW5kbGVyOlxyXG4gICAqIC0gSGFuZGxlcyBTaGFyZVBvaW50IGVuZHBvaW50IHN3aXRjaGluZ1xyXG4gICAqIC0gU3VwcG9ydHMgU2VsZWN0RmlsZU9ubHkgbW9kZSAocmVhZCBmaWxlIGNvbnRlbnQgaW50byBtZW1vcnkgYW5kIGVtaXQgZXZlbnQpXHJcbiAgICogLSBTdXBwb3J0cyBpbWFnZSBjb21wcmVzc2lvbiB3aGVuIEF1dG9VcGxvYWQgaXMgZmFsc2VcclxuICAgKi9cclxuICBwdWJsaWMgc2VsZWN0RXZlbnRIYW5kbGVyKGU6IFNlbGVjdEV2ZW50KTogdm9pZCB7XHJcbiAgICBpZiAoIWU/LmZpbGVzPy5sZW5ndGgpIHtcclxuICAgICAgY29uc29sZS53YXJuKGBbWnVwbG9hZENvbXBvbmVudF0gc2VsZWN0RXZlbnRIYW5kbGVyOiBubyBmaWxlcyBpbiBTZWxlY3RFdmVudC5gKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgLy8gUmVzZXQgdG8gZGVmYXVsdCBldmVyeSBzZWxlY3Rpb24gdG8gYXZvaWQgU2hhcmVQb2ludCBVUkwgXCJzdGlja2luZ1wiIHBlcm1hbmVudGx5LlxyXG4gICAgdGhpcy51cGxvYWRTYXZlVXJsID0gdGhpcy5kZWZhdWx0VXBsb2FkU2F2ZVVybDtcclxuICAgIHRoaXMudXBsb2FkUmVtb3ZlVXJsID0gdGhpcy5kZWZhdWx0VXBsb2FkUmVtb3ZlVXJsO1xyXG5cclxuICAgIC8vI3JlZ2lvbiBzaGFyZXBvaW50XHJcbiAgICBjb25zdCBhdHRhY2htZW50SW5mbzogQXR0YWNobWVudCB8IG51bGwgPSB0aGlzLnNoYXJlUG9pbnRTZXJ2aWNlLmdldEF0dGFjaG1lbnRJbmZvKHRoaXMuZGF0YT8uW1wiRG93bmxvYWRGaWxlQ29uZmlnXCJdKTtcclxuICAgIC8vIENoYW5nZSB1cGxvYWRTYXZlVXJsIGlmIHNhdmluZyB0byBTaGFyZVBvaW50XHJcbiAgICBpZiAoYXR0YWNobWVudEluZm8/LmlzU2F2ZVRvU2hhcmVQb2ludCAmJiBhdHRhY2htZW50SW5mby5zaXRlTmFtZSkge1xyXG4gICAgICBjb25zdCBhdHRhY2htZW50U291cmNlVXJsID0gdGhpcy56Y29yZVNlcnZpY2UuZ2V0RW52aXJvbm1lbnQoKT8uYXR0YWNobWVudFNvdXJjZVVybDtcclxuICAgICAgaWYgKGF0dGFjaG1lbnRTb3VyY2VVcmwpIHtcclxuICAgICAgICB0aGlzLnVwbG9hZFNhdmVVcmwgPSBgJHthdHRhY2htZW50U291cmNlVXJsfS9DaHVua19VcGxvYWRfU2F2ZWA7XHJcbiAgICAgICAgY29uc29sZS5pbmZvKGBbWnVwbG9hZENvbXBvbmVudF0gVXBsb2FkIGVuZHBvaW50IHN3aXRjaGVkIHRvIFNoYXJlUG9pbnQgbW9kZS5gLCB7IHVwbG9hZFNhdmVVcmw6IHRoaXMudXBsb2FkU2F2ZVVybCB9KTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBjb25zb2xlLndhcm4oYFtadXBsb2FkQ29tcG9uZW50XSBhdHRhY2htZW50U291cmNlVXJsIGlzIG1pc3NpbmcuIENhbm5vdCBzd2l0Y2ggdG8gU2hhcmVQb2ludCB1cGxvYWQgZW5kcG9pbnQuYCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIC8vI2VuZHJlZ2lvblxyXG5cclxuICAgIGlmICh0aGlzLmRhdGE/LltcIlNlbGVjdEZpbGVPbmx5XCJdKSB7XHJcbiAgICAgIC8vIEFwcGVuZCBhbGwgZmlsZXMgdG8gY29tcG9uZW50IG1lbW9yeVxyXG4gICAgICBlLmZpbGVzLmZvckVhY2goKGZpbGU6IEZpbGVJbmZvKSA9PiB7XHJcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWRVcGxvYWRlZEZpbGUoZmlsZSkpIHtcclxuICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICghZmlsZS5yYXdGaWxlKSB7XHJcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xyXG4gICAgICAgIHJlYWRlci5vbmxvYWQgPSAoZXY6IFByb2dyZXNzRXZlbnQ8RmlsZVJlYWRlcj4pID0+IHtcclxuICAgICAgICAgIC8vIENsb25lIHRoZSBkYXRhIGFuZCBhbHNvIGFkZCB0aGUgcmVhZCBmaWxlIHRvIHRoZSBvYmplY3RcclxuICAgICAgICAgIGNvbnN0IGZpbGVEYXRhOiBTZWxlY3RlZEZpbGVEYXRhID0ge1xyXG4gICAgICAgICAgICAuLi5maWxlLFxyXG4gICAgICAgICAgICBmaWxlOiBldj8udGFyZ2V0Py5yZXN1bHQgPz8gbnVsbCxcclxuICAgICAgICAgIH07XHJcbiAgICAgICAgICBmaWxlRGF0YVtcImZpbGVcIl0gPSBldj8udGFyZ2V0Py5yZXN1bHQ7XHJcblxyXG4gICAgICAgICAgLy8gUHVzaCB0byBjb21wb25lbnQgZmlsZUxpc3RcclxuICAgICAgICAgIHRoaXMuZmlsZUxpc3QucHVzaChmaWxlRGF0YSk7XHJcbiAgICAgICAgICB0aGlzLmdyb3VwW2B6dXBsb2FkXyR7dGhpcy5kYXRhPy5WYWx1ZX1gXSA9IHRoaXMuZmlsZUxpc3Q7XHJcblxyXG4gICAgICAgICAgY29uc3Qgc2VsZWN0ZWRFdmVudCA9IHRoaXMuZGF0YT8uW1wiRmlsZVNlbGVjdGVkRXZlbnRcIl07XHJcbiAgICAgICAgICBpZiAoc2VsZWN0ZWRFdmVudCkge1xyXG4gICAgICAgICAgICB0aGlzLmdyb3VwLnN1YmplY3Q/Lm5leHQoe1xyXG4gICAgICAgICAgICAgIHR5cGU6IFwienVwbG9hZC1maWxlU2VsZWN0ZWRFdmVudFwiLFxyXG4gICAgICAgICAgICAgIHRhcmdldDogc2VsZWN0ZWRFdmVudCxcclxuICAgICAgICAgICAgICBkYXRhOiB0aGlzLmZpbGVMaXN0LFxyXG4gICAgICAgICAgICB9IGFzIFpDb21wb25lbnRPdXRwdXRFdmVudCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcmVhZGVyLm9uZXJyb3IgPSAoKSA9PiB7XHJcbiAgICAgICAgICBjb25zb2xlLndhcm4oYFtadXBsb2FkQ29tcG9uZW50XSBGYWlsZWQgdG8gcmVhZCBmaWxlIGFzIGJhc2U2NC5gLCB7XHJcbiAgICAgICAgICAgIG5hbWU6IGZpbGUucmF3RmlsZT8ubmFtZSxcclxuICAgICAgICAgICAgdWlkOiBmaWxlLnVpZCxcclxuICAgICAgICAgICAgZXJyb3I6IHJlYWRlci5lcnJvcixcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGZpbGUucmF3RmlsZSk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIE9ubHkgd29ya2FibGUgZm9yIEF1dG8gVXBsb2FkID0gZmFsc2VcclxuICAgIGlmICh0aGlzLmRhdGE/LkF1dG9VcGxvYWQpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIENvbXByZXNzaW9uIGZvciBpbWFnZSBmaWxlXHJcbiAgICBjb25zdCBpbWFnZUNvbXByZXNzaW9uRW5hYmxlZCA9IEJvb2xlYW4odGhpcy5kYXRhPy5Db21wcmVzc2lvbik7XHJcblxyXG4gICAgLy8gQ2hlY2sgaWYgSW1hZ2UgQ29tcHJlc3Npb24gaXMgZW5hYmxlZC5cclxuICAgIGlmIChpbWFnZUNvbXByZXNzaW9uRW5hYmxlZCkge1xyXG4gICAgICBlLmZpbGVzLmZvckVhY2goKGZpbGU6IEZpbGVJbmZvKSA9PiB7XHJcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWRVcGxvYWRlZEZpbGUoZmlsZSkpIHtcclxuICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIENvbXByZXNzIG9ubHkgaWYgaXQgaXMgYW4gaW1hZ2UgZmlsZVxyXG4gICAgICAgIGlmICghZmlsZT8ucmF3RmlsZT8udHlwZT8uaW5jbHVkZXMoXCJpbWFnZVwiKSB8fCBmaWxlLnZhbGlkYXRpb25FcnJvcnMpIHtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGltZ0NvbmZpZyA9IHRoaXMuY29tcHJlc3Npb25Db25maWdIYW5kbGVyKHRoaXMuZGF0YS5Db21wcmVzc2lvbik7XHJcbiAgICAgICAgY29uc3QgbWluQnl0ZXMgPSBpbWdDb25maWc/LkZpbGVTaXplTWluU2l6ZUJ5dGUgPz8gMDtcclxuXHJcbiAgICAgICAgLy8gT3JpZ2luYWwgYmVoYXZpb3I6IG9ubHkgY29tcHJlc3MgaWYgZmlsZSBzaXplID4gbWluQnl0ZXNcclxuICAgICAgICBpZiAoZmlsZS5zaXplIDw9IG1pbkJ5dGVzKSB7XHJcbiAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLmNvbXByZXNzSW1hZ2VcclxuICAgICAgICAgIC5jb21wcmVzcyhmaWxlLnJhd0ZpbGUsIGltZ0NvbmZpZykgLy8gUGFzcyBpbiBwYXJhbWV0ZXIgdG8gc2V0IHRoZSBDb21wcmVzc2lvbiBPcHRpb25zXHJcbiAgICAgICAgICAucGlwZSh0YWtlKDEpKVxyXG4gICAgICAgICAgLnN1YnNjcmliZSh7XHJcbiAgICAgICAgICAgIG5leHQ6IChjb21wcmVzc0ZpbGUpID0+IHtcclxuICAgICAgICAgICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgZmlsZS5yYXdGaWxlID0gY29tcHJlc3NGaWxlO1xyXG4gICAgICAgICAgICAgICAgZmlsZS5zaXplID0gY29tcHJlc3NGaWxlLnNpemU7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gUHVzaCB0byBjb21wb25lbnQgZmlsZUxpc3QgKGtlcHQgYXMgb3JpZ2luYWwgaW50ZW50KVxyXG4gICAgICAgICAgICAgICAgY29uc3QgZmlsZURhdGE6IFNlbGVjdGVkRmlsZURhdGEgPSB7IC4uLmZpbGUgfTtcclxuICAgICAgICAgICAgICAgIHRoaXMuZmlsZUxpc3QucHVzaChmaWxlRGF0YSk7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gS2VlcCBvcmlnaW5hbDogcmVhZCB0byBkYXRhIFVSTCAoc2lkZSBlZmZlY3QpXHJcbiAgICAgICAgICAgICAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xyXG4gICAgICAgICAgICAgICAgcmVhZGVyLnJlYWRBc0RhdGFVUkwoZmlsZS5yYXdGaWxlKTtcclxuICAgICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgICAgY29uc29sZS5pbmZvKGBbWnVwbG9hZENvbXBvbmVudF0gSW1hZ2UgY29tcHJlc3NlZCBzdWNjZXNzZnVsbHkuYCwge1xyXG4gICAgICAgICAgICAgICAgbmFtZTogZmlsZT8ucmF3RmlsZT8ubmFtZSxcclxuICAgICAgICAgICAgICAgIG5ld1NpemVLQjogTnVtYmVyKChmaWxlLnJhd0ZpbGUuc2l6ZSAvIDEwMjQpLnRvRml4ZWQoMikpLFxyXG4gICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBlcnJvcjogKGVycikgPT4ge1xyXG4gICAgICAgICAgICAgIC8vIFByZXNlcnZlIGZsb3cgKGRvIG5vdCBibG9jayBzZWxlY3Rpb24pLCBidXQgcHJvdmlkZSBjbGVhcmVyIGRpYWdub3N0aWNcclxuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBbWnVwbG9hZENvbXBvbmVudF0gSW1hZ2UgY29tcHJlc3Npb24gZmFpbGVkLiBVcGxvYWQgd2lsbCBjb250aW51ZSB3aXRoIG9yaWdpbmFsIGZpbGUuYCwge1xyXG4gICAgICAgICAgICAgICAgbmFtZTogZmlsZT8ucmF3RmlsZT8ubmFtZSxcclxuICAgICAgICAgICAgICAgIGVycm9yOiBlcnIsXHJcbiAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICB9KTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQWRkIHRvIGdyb3VwIHNjb3BlIChvcmlnaW5hbCBiZWhhdmlvcjogc3RvcmUgc2VsZWN0ZWQgZmlsZXMpXHJcbiAgICB0aGlzLmdyb3VwW2B6dXBsb2FkXyR7dGhpcy5kYXRhPy5WYWx1ZX1gXSA9IGUuZmlsZXM7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDbGVhcnMgVUktc2VsZWN0ZWQgZmlsZXMgYW5kIHN5bmNzIGdyb3VwIHN0YXRlLlxyXG4gICAqIE5PVEU6IE9yaWdpbmFsIGJlaGF2aW9yIHNldHMgZ3JvdXAgdmFsdWUgdG8gZmlsZUxpc3QgKG5vdCBlbXB0eSk7IHByZXNlcnZlZC5cclxuICAgKi9cclxuICBwdWJsaWMgY2xlYXJGaWxlcygpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy51cGxvYWRDb21wb25lbnQpIHtcclxuICAgICAgY29uc29sZS53YXJuKGBbWnVwbG9hZENvbXBvbmVudF0gY2xlYXJGaWxlczogdXBsb2FkQ29tcG9uZW50IGlzIG5vdCByZWFkeS5gKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMudXBsb2FkQ29tcG9uZW50LmNsZWFyRmlsZXMoKTtcclxuICAgIHRoaXMuZ3JvdXBbYHp1cGxvYWRfJHt0aGlzLmRhdGE/LlZhbHVlfWBdID0gdGhpcy5maWxlTGlzdDtcclxuXHJcbiAgICBjb25zb2xlLmluZm8oYFtadXBsb2FkQ29tcG9uZW50XSBGaWxlcyBjbGVhcmVkIGZyb20gVUkuYCwge1xyXG4gICAgICBzdG9yZWRGaWxlTGlzdENvdW50OiB0aGlzLmZpbGVMaXN0Lmxlbmd0aCxcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRm9ybWF0IGJ5dGVzIGludG8gaHVtYW4tcmVhZGFibGUgc3RyaW5nLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIGJ5dGVzIFJhdyBieXRlIHNpemVcclxuICAgKiBAcmV0dXJucyBGb3JtYXR0ZWQgZmlsZSBzaXplIHN0cmluZyAoZS5nLiBcIjEyLjVNQlwiKVxyXG4gICAqL1xyXG4gIHByaXZhdGUgZm9ybWF0RmlsZVNpemUoYnl0ZXM6IG51bWJlcik6IHN0cmluZyB7XHJcbiAgICBjb25zdCBzaXplcyA9IFtcIkJ5dGVzXCIsIFwiS0JcIiwgXCJNQlwiLCBcIkdCXCIsIFwiVEJcIl07XHJcbiAgICBpZiAoIU51bWJlci5pc0Zpbml0ZShieXRlcykgfHwgYnl0ZXMgPD0gMCkge1xyXG4gICAgICByZXR1cm4gXCIwIEJ5dGVcIjtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBpID0gTWF0aC5mbG9vcihNYXRoLmxvZyhieXRlcykgLyBNYXRoLmxvZygxMDI0KSk7XHJcbiAgICBjb25zdCB2YWx1ZSA9IGJ5dGVzIC8gTWF0aC5wb3coMTAyNCwgaSk7XHJcblxyXG4gICAgLy8gTk9URTogT3JpZ2luYWwgb3V0cHV0IGhhZCBubyBzcGFjZSBiZXR3ZWVuIG51bWJlciBhbmQgdW5pdDsgcHJlc2VydmVkLlxyXG4gICAgcmV0dXJuIGAke051bWJlci5wYXJzZUZsb2F0KHZhbHVlLnRvRml4ZWQoMikpfSR7c2l6ZXNbaV19YDtcclxuICB9XHJcbn1cclxuIiwiPGRpdiBbZm9ybUdyb3VwXT1cImZvcm1cIiBjbGFzcz1cInp1cGxvYWQtY29udGFpbmVyIGUxdGFnLXN0eWxlXCIgW3N0eWxlXT1cImNvbXBvbmVudFByb3BlcnRpZXMuc3R5bGUuc3R5bGVcIj5cclxuICA8a2VuZG8tdXBsb2FkXHJcbiAgICAqbmdJZj1cIiFkYXRhLlNlbGVjdEZpbGVPbmx5XCJcclxuICAgICN1cGxvYWRDb21wb25lbnRcclxuICAgIFtpZF09XCJkYXRhLlZhbHVlXCJcclxuICAgIFthdXRvVXBsb2FkXT1cImlzQXV0b1VwbG9hZFwiXHJcbiAgICBbc2F2ZVVybF09XCJ1cGxvYWRTYXZlVXJsXCJcclxuICAgIFtyZW1vdmVVcmxdPVwidXBsb2FkUmVtb3ZlVXJsXCJcclxuICAgIFtyZXN0cmljdGlvbnNdPVwicmVzdHJpY3Rpb25zXCJcclxuICAgIFttdWx0aXBsZV09XCJpc011bHRpcGxlXCJcclxuICAgIFtjaHVua2FibGVdPVwiY2h1bmtTZXR0aW5nc1wiXHJcbiAgICBbc2hvd0ZpbGVMaXN0XT1cInNob3dGaWxlTGlzdFwiXHJcbiAgICAoc2VsZWN0KT1cInNlbGVjdEV2ZW50SGFuZGxlcigkZXZlbnQpXCJcclxuICAgIChyZW1vdmUpPVwib25SZW1vdmUoJGV2ZW50KVwiXHJcbiAgICAoc3VjY2Vzcyk9XCJvblN1Y2Nlc3MoJGV2ZW50KVwiXHJcbiAgICAodXBsb2FkKT1cInVwbG9hZEV2ZW50SGFuZGxlcigkZXZlbnQpXCJcclxuICAgIFtzdHlsZV09XCJjb21wb25lbnRQcm9wZXJ0aWVzLnN0eWxlLnN0eWxlMVwiXHJcbiAgICBjbGFzcz1cImUxdGFnLXN0eWxlMVwiPlxyXG4gIDwva2VuZG8tdXBsb2FkPlxyXG5cclxuICA8a2VuZG8tZmlsZXNlbGVjdFxyXG4gICAgKm5nSWY9XCJkYXRhLlNlbGVjdEZpbGVPbmx5XCJcclxuICAgICN1cGxvYWRDb21wb25lbnRcclxuICAgIFtpZF09XCJkYXRhLlZhbHVlXCJcclxuICAgIChzZWxlY3QpPVwic2VsZWN0RXZlbnRIYW5kbGVyKCRldmVudClcIlxyXG4gICAgKHJlbW92ZSk9XCJvblJlbW92ZSgkZXZlbnQpXCJcclxuICAgIFtmb3JtQ29udHJvbE5hbWVdPVwiZGF0YS5WYWx1ZVwiXHJcbiAgICAodmFsdWVDaGFuZ2UpPVwib25DaGFuZ2UoJGV2ZW50KVwiIFxyXG4gICAgW3Jlc3RyaWN0aW9uc109XCJyZXN0cmljdGlvbnNcIlxyXG4gICAgW3N0eWxlXT1cImNvbXBvbmVudFByb3BlcnRpZXMuc3R5bGUuc3R5bGUxXCJcclxuICAgIGNsYXNzPVwiZTF0YWctc3R5bGUxXCI+XHJcbiAgPC9rZW5kby1maWxlc2VsZWN0PlxyXG5cclxuICA8ZGl2XHJcbiAgICAqbmdJZj1cImltYWdlUHJldmlld3MubGVuZ3RoXCJcclxuICAgIGNsYXNzPVwiaW1hZ2UtcHJldmlldy1jb250YWluZXIgZTF0YWctc3R5bGUyXCJcclxuICAgIFtzdHlsZV09XCJjb21wb25lbnRQcm9wZXJ0aWVzLnN0eWxlLnN0eWxlMlwiPlxyXG4gICAgPGRpdlxyXG4gICAgICBjbGFzcz1cImxhYmVsLWNvbnRhaW5lciBlMXRhZy1zdHlsZTNcIlxyXG4gICAgICBbc3R5bGVdPVwiY29tcG9uZW50UHJvcGVydGllcy5zdHlsZS5zdHlsZTNcIj5cclxuICAgICAgSW1hZ2UgUHJldmlldzpcclxuICAgIDwvZGl2PlxyXG4gICAgPGRpdlxyXG4gICAgICBjbGFzcz1cImltYWdlLWNvbnRhaW5lciBlMXRhZy1zdHlsZTRcIlxyXG4gICAgICBbc3R5bGVdPVwiY29tcG9uZW50UHJvcGVydGllcy5zdHlsZS5zdHlsZTRcIj5cclxuICAgICAgPGltZ1xyXG4gICAgICAgICpuZ0Zvcj1cImxldCBpbWFnZSBvZiBpbWFnZVByZXZpZXdzXCJcclxuICAgICAgICBbc3JjXT1cImltYWdlLnNyY1wiXHJcbiAgICAgICAgYWx0PVwiaW1hZ2UgcHJldmlld1wiXHJcbiAgICAgICAgaGVpZ2h0PVwiMTAwXCJcclxuICAgICAgICBjbGFzcz1cImUxdGFnLXN0eWxlNVwiXHJcbiAgICAgICAgW3N0eWxlXT1cImNvbXBvbmVudFByb3BlcnRpZXMuc3R5bGUuc3R5bGU1XCIgLz5cclxuICAgIDwvZGl2PlxyXG4gIDwvZGl2PlxyXG48L2Rpdj5cclxuIl19