@arsedizioni/ars-utils 18.5.62 → 19.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/arsedizioni-ars-utils-clipper.common.mjs +10 -10
- package/fesm2022/arsedizioni-ars-utils-clipper.common.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-clipper.ui.mjs +41 -41
- package/fesm2022/arsedizioni-ars-utils-clipper.ui.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-core.mjs +99 -99
- package/fesm2022/arsedizioni-ars-utils-core.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-evolution.common.mjs +10 -10
- package/fesm2022/arsedizioni-ars-utils-evolution.common.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-help.mjs +13 -13
- package/fesm2022/arsedizioni-ars-utils-help.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-support.common.mjs +10 -10
- package/fesm2022/arsedizioni-ars-utils-support.common.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-support.ui.mjs +6 -6
- package/fesm2022/arsedizioni-ars-utils-support.ui.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-tinymce.mjs +7 -7
- package/fesm2022/arsedizioni-ars-utils-tinymce.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-ui.application.mjs +58 -58
- package/fesm2022/arsedizioni-ars-utils-ui.application.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-ui.mjs +34 -34
- package/fesm2022/arsedizioni-ars-utils-ui.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-ui.oauth.mjs +7 -7
- package/fesm2022/arsedizioni-ars-utils-ui.oauth.mjs.map +1 -1
- package/package.json +5 -29
- package/esm2022/arsedizioni-ars-utils.mjs +0 -5
- package/esm2022/clipper.common/arsedizioni-ars-utils-clipper.common.mjs +0 -5
- package/esm2022/clipper.common/common/common.module.mjs +0 -16
- package/esm2022/clipper.common/common/definitions.mjs +0 -2041
- package/esm2022/clipper.common/common/interceptors/auth.interceptor.mjs +0 -100
- package/esm2022/clipper.common/common/messages.mjs +0 -36
- package/esm2022/clipper.common/common/services/clipper.service.mjs +0 -1011
- package/esm2022/clipper.common/public_api.mjs +0 -5
- package/esm2022/clipper.ui/arsedizioni-ars-utils-clipper.ui.mjs +0 -5
- package/esm2022/clipper.ui/documents.mjs +0 -50
- package/esm2022/clipper.ui/public_api.mjs +0 -18
- package/esm2022/clipper.ui/ui/browser-dialog/browser-dialog.component.mjs +0 -766
- package/esm2022/clipper.ui/ui/document/document.component.mjs +0 -688
- package/esm2022/clipper.ui/ui/document-index/document-index.component.mjs +0 -118
- package/esm2022/clipper.ui/ui/document-manager/document-manager.mjs +0 -441
- package/esm2022/clipper.ui/ui/document-menu/document-menu.component.mjs +0 -217
- package/esm2022/clipper.ui/ui/references/references.component.mjs +0 -380
- package/esm2022/clipper.ui/ui/search-calendar/search-calendar.component.mjs +0 -116
- package/esm2022/clipper.ui/ui/search-dialog/search-dialog.component.mjs +0 -339
- package/esm2022/clipper.ui/ui/search-facets/search-facets.component.mjs +0 -251
- package/esm2022/clipper.ui/ui/search-free-text-help/search-free-text-help.component.mjs +0 -17
- package/esm2022/clipper.ui/ui/search-free-text-query-builder/search-free-text-query-builder.component.mjs +0 -106
- package/esm2022/clipper.ui/ui/search-result-item/search-result-item.component.mjs +0 -120
- package/esm2022/clipper.ui/ui/search-result-manager/search-result-manager.mjs +0 -531
- package/esm2022/core/arsedizioni-ars-utils-core.mjs +0 -5
- package/esm2022/core/core.module.mjs +0 -151
- package/esm2022/core/dateFnsAdapter.mjs +0 -203
- package/esm2022/core/definitions.mjs +0 -47
- package/esm2022/core/directives/autoFocusDirective.mjs +0 -22
- package/esm2022/core/directives/changeDateIntervalDirective.mjs +0 -48
- package/esm2022/core/directives/copyClipboardDirective.mjs +0 -46
- package/esm2022/core/directives/validators.mjs +0 -502
- package/esm2022/core/pipes/format.pipe.mjs +0 -53
- package/esm2022/core/pipes/replace.pipe.mjs +0 -29
- package/esm2022/core/pipes/safe-html.pipe.mjs +0 -24
- package/esm2022/core/pipes/safe-url.pipe.mjs +0 -24
- package/esm2022/core/pipes/search-callback.pipe.mjs +0 -21
- package/esm2022/core/pipes/search-filter.pipe.mjs +0 -50
- package/esm2022/core/public_api.mjs +0 -22
- package/esm2022/core/selectable.mjs +0 -131
- package/esm2022/core/services/broadcast.service.mjs +0 -35
- package/esm2022/core/services/broadcastChannelManager.mjs +0 -80
- package/esm2022/core/services/environment.service.mjs +0 -29
- package/esm2022/core/services/screen.service.mjs +0 -23
- package/esm2022/core/services/theme.service.mjs +0 -140
- package/esm2022/core/system.mjs +0 -664
- package/esm2022/evolution.common/arsedizioni-ars-utils-evolution.common.mjs +0 -5
- package/esm2022/evolution.common/common/common.module.mjs +0 -16
- package/esm2022/evolution.common/common/definitions.mjs +0 -454
- package/esm2022/evolution.common/common/interceptors/auth.interceptor.mjs +0 -100
- package/esm2022/evolution.common/common/messages.mjs +0 -8
- package/esm2022/evolution.common/common/services/evolution.service.mjs +0 -490
- package/esm2022/evolution.common/public_api.mjs +0 -5
- package/esm2022/help/arsedizioni-ars-utils-help.mjs +0 -5
- package/esm2022/help/components/help-viewer/help-viewer.component.mjs +0 -442
- package/esm2022/help/definitions.mjs +0 -2
- package/esm2022/help/help.module.mjs +0 -12
- package/esm2022/help/public_api.mjs +0 -7
- package/esm2022/help/services/help.service.mjs +0 -77
- package/esm2022/public_api.mjs +0 -15
- package/esm2022/support.common/arsedizioni-ars-utils-support.common.mjs +0 -5
- package/esm2022/support.common/common/common.module.mjs +0 -16
- package/esm2022/support.common/common/definitions.mjs +0 -29
- package/esm2022/support.common/common/interceptors/auth.interceptor.mjs +0 -100
- package/esm2022/support.common/common/messages.mjs +0 -13
- package/esm2022/support.common/common/services/support.service.mjs +0 -289
- package/esm2022/support.common/public_api.mjs +0 -8
- package/esm2022/support.ui/arsedizioni-ars-utils-support.ui.mjs +0 -5
- package/esm2022/support.ui/public_api.mjs +0 -5
- package/esm2022/support.ui/ui/notifications-browser/notification/notification.component.mjs +0 -80
- package/esm2022/support.ui/ui/notifications-browser/notifications-browser.component.mjs +0 -233
- package/esm2022/tinymce/arsedizioni-ars-utils-tinymce.mjs +0 -5
- package/esm2022/tinymce/full-screen-editor/full-screen-editor.component.mjs +0 -48
- package/esm2022/tinymce/public_api.mjs +0 -7
- package/esm2022/tinymce/tinymce.module.mjs +0 -19
- package/esm2022/tinymce/utils.mjs +0 -150
- package/esm2022/ui/arsedizioni-ars-utils-ui.mjs +0 -5
- package/esm2022/ui/public_api.mjs +0 -12
- package/esm2022/ui/ui/components/button-selector/button-selector.component.mjs +0 -150
- package/esm2022/ui/ui/components/button-toggle/button-toggle.component.mjs +0 -51
- package/esm2022/ui/ui/components/calendar-empty-header/calendar-empy-header.component.mjs +0 -30
- package/esm2022/ui/ui/components/chips-selector/chips-selector.component.mjs +0 -272
- package/esm2022/ui/ui/components/file-input/file-input.component.mjs +0 -264
- package/esm2022/ui/ui/components/file-preview/file-preview.component.mjs +0 -73
- package/esm2022/ui/ui/components/filter-bar/filter-bar.component.mjs +0 -356
- package/esm2022/ui/ui/definitions.mjs +0 -2
- package/esm2022/ui/ui/dialogs/busy/busy-dialog.component.mjs +0 -47
- package/esm2022/ui/ui/dialogs/confirm/confirm-dialog.component.mjs +0 -101
- package/esm2022/ui/ui/dialogs/credentials/credentials-dialog.component.mjs +0 -86
- package/esm2022/ui/ui/dialogs/info/info-dialog.component.mjs +0 -51
- package/esm2022/ui/ui/dialogs/prompt/prompt-dialog.component.mjs +0 -77
- package/esm2022/ui/ui/dialogs/prompt-date/prompt-date-dialog.component.mjs +0 -79
- package/esm2022/ui/ui/dialogs/prompt-time/prompt-time-dialog.component.mjs +0 -72
- package/esm2022/ui/ui/dialogs/recover-password/recover-password-dialog.component.mjs +0 -49
- package/esm2022/ui/ui/dialogs/reset-password/reset-password-dialog.component.mjs +0 -89
- package/esm2022/ui/ui/dialogs/select/select-dialog.component.mjs +0 -374
- package/esm2022/ui/ui/dialogs/select-file/select-file-dialog.component.mjs +0 -106
- package/esm2022/ui/ui/dialogs/select-picture/select-picture-dialog.component.mjs +0 -62
- package/esm2022/ui/ui/dialogs/select-tree/select-tree-dialog.component.mjs +0 -277
- package/esm2022/ui/ui/dialogs/send-to/send-to-dialog.component.mjs +0 -90
- package/esm2022/ui/ui/dialogs/toast/toast.component.mjs +0 -32
- package/esm2022/ui/ui/directives/resize-table-column.directive.mjs +0 -63
- package/esm2022/ui/ui/filters.mjs +0 -43
- package/esm2022/ui/ui/paginatorIntl.mjs +0 -34
- package/esm2022/ui/ui/services/dialog.service.mjs +0 -417
- package/esm2022/ui/ui/services/ui.service.mjs +0 -21
- package/esm2022/ui/ui/ui.module.mjs +0 -21
- package/esm2022/ui.application/arsedizioni-ars-utils-ui.application.mjs +0 -5
- package/esm2022/ui.application/public_api.mjs +0 -21
- package/esm2022/ui.application/ui/components/button-selector/button-selector.component.mjs +0 -150
- package/esm2022/ui.application/ui/components/button-toggle/button-toggle.component.mjs +0 -51
- package/esm2022/ui.application/ui/components/calendar-empty-header/calendar-empy-header.component.mjs +0 -30
- package/esm2022/ui.application/ui/components/chips-selector/chips-selector.component.mjs +0 -272
- package/esm2022/ui.application/ui/components/file-input/file-input.component.mjs +0 -264
- package/esm2022/ui.application/ui/components/file-preview/file-preview.component.mjs +0 -73
- package/esm2022/ui.application/ui/components/filter-bar/filter-bar.component.mjs +0 -356
- package/esm2022/ui.application/ui/definitions.mjs +0 -31
- package/esm2022/ui.application/ui/dialogs/prompt/prompt-dialog.component.mjs +0 -77
- package/esm2022/ui.application/ui/dialogs/prompt-date/prompt-date-dialog.component.mjs +0 -79
- package/esm2022/ui.application/ui/dialogs/prompt-time/prompt-time-dialog.component.mjs +0 -72
- package/esm2022/ui.application/ui/dialogs/select/select-dialog.component.mjs +0 -374
- package/esm2022/ui.application/ui/dialogs/select-file/select-file-dialog.component.mjs +0 -106
- package/esm2022/ui.application/ui/dialogs/select-picture/select-picture-dialog.component.mjs +0 -62
- package/esm2022/ui.application/ui/dialogs/select-tree/select-tree-dialog.component.mjs +0 -277
- package/esm2022/ui.application/ui/dialogs/send-to/send-to-dialog.component.mjs +0 -90
- package/esm2022/ui.application/ui/directives/resize-table-column.directive.mjs +0 -63
- package/esm2022/ui.application/ui/filters.mjs +0 -43
- package/esm2022/ui.application/ui/services/applicationDialog.service.mjs +0 -304
- package/esm2022/ui.application/ui/ui.module.mjs +0 -30
- package/esm2022/ui.oauth/arsedizioni-ars-utils-ui.oauth.mjs +0 -5
- package/esm2022/ui.oauth/public_api.mjs +0 -6
- package/esm2022/ui.oauth/ui/components/login/login-oauth.component.mjs +0 -199
- package/esm2022/ui.oauth/ui/definitions.mjs +0 -7
- package/esm2022/ui.oauth/ui/ui.module.mjs +0 -13
- package/ui/ui/components/button-selector/button-selector.component.d.ts +0 -52
- package/ui/ui/components/button-toggle/button-toggle.component.d.ts +0 -28
- package/ui/ui/components/calendar-empty-header/calendar-empy-header.component.d.ts +0 -11
- package/ui/ui/components/chips-selector/chips-selector.component.d.ts +0 -82
- package/ui/ui/components/file-input/file-input.component.d.ts +0 -88
- package/ui/ui/components/file-preview/file-preview.component.d.ts +0 -26
- package/ui/ui/components/filter-bar/filter-bar.component.d.ts +0 -83
- package/ui/ui/dialogs/prompt/prompt-dialog.component.d.ts +0 -18
- package/ui/ui/dialogs/prompt-date/prompt-date-dialog.component.d.ts +0 -18
- package/ui/ui/dialogs/prompt-time/prompt-time-dialog.component.d.ts +0 -18
- package/ui/ui/dialogs/select/select-dialog.component.d.ts +0 -122
- package/ui/ui/dialogs/select-file/select-file-dialog.component.d.ts +0 -36
- package/ui/ui/dialogs/select-picture/select-picture-dialog.component.d.ts +0 -26
- package/ui/ui/dialogs/select-tree/select-tree-dialog.component.d.ts +0 -98
- package/ui/ui/dialogs/send-to/send-to-dialog.component.d.ts +0 -28
- package/ui/ui/directives/resize-table-column.directive.d.ts +0 -19
- package/ui/ui/filters.d.ts +0 -57
package/esm2022/core/system.mjs
DELETED
|
@@ -1,664 +0,0 @@
|
|
|
1
|
-
import { HttpParams } from "@angular/common/http";
|
|
2
|
-
import { format, parse, parseISO, setHours } from 'date-fns';
|
|
3
|
-
import { it } from 'date-fns/locale';
|
|
4
|
-
import { fromZonedTime } from 'date-fns-tz';
|
|
5
|
-
export var DateFormat;
|
|
6
|
-
(function (DateFormat) {
|
|
7
|
-
DateFormat[DateFormat["Short"] = 1] = "Short";
|
|
8
|
-
DateFormat[DateFormat["Long"] = 2] = "Long";
|
|
9
|
-
DateFormat[DateFormat["LongWithShortMonth"] = 3] = "LongWithShortMonth";
|
|
10
|
-
DateFormat[DateFormat["LongWithWeekDay"] = 4] = "LongWithWeekDay";
|
|
11
|
-
DateFormat[DateFormat["LongWithShortWeekDay"] = 5] = "LongWithShortWeekDay";
|
|
12
|
-
DateFormat[DateFormat["MonthAndYear"] = 6] = "MonthAndYear";
|
|
13
|
-
DateFormat[DateFormat["LongMonthAndYear"] = 7] = "LongMonthAndYear";
|
|
14
|
-
DateFormat[DateFormat["WeekDay"] = 8] = "WeekDay";
|
|
15
|
-
DateFormat[DateFormat["LongWeekDay"] = 9] = "LongWeekDay";
|
|
16
|
-
DateFormat[DateFormat["DayAndMonth"] = 10] = "DayAndMonth";
|
|
17
|
-
DateFormat[DateFormat["ShortUS"] = 11] = "ShortUS";
|
|
18
|
-
DateFormat[DateFormat["ShortISO8601"] = 12] = "ShortISO8601"; // yyyy-mm-dd
|
|
19
|
-
})(DateFormat || (DateFormat = {}));
|
|
20
|
-
export class SystemUtils {
|
|
21
|
-
/**
|
|
22
|
-
* Array find by key
|
|
23
|
-
* @param array : the array to scan
|
|
24
|
-
* @param key : key name
|
|
25
|
-
* @param value : the value to search for
|
|
26
|
-
* @returns : the property value or null
|
|
27
|
-
*/
|
|
28
|
-
static arrayFindByKey(array, key, value) {
|
|
29
|
-
if (!array)
|
|
30
|
-
return null;
|
|
31
|
-
for (const item of array) {
|
|
32
|
-
if (item[key] === value) {
|
|
33
|
-
return item;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Array find index by key
|
|
40
|
-
* @param array : the array to scan
|
|
41
|
-
* @param key : the key name
|
|
42
|
-
* @param value : the value to search for
|
|
43
|
-
* @returns : the array index or -1 if not found
|
|
44
|
-
*/
|
|
45
|
-
static arrayFindIndexByKey(array, key, value) {
|
|
46
|
-
if (!array)
|
|
47
|
-
return -1;
|
|
48
|
-
for (let i = 0; i < array.length; i++) {
|
|
49
|
-
if (array[i][key] === value) {
|
|
50
|
-
return i;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return -1;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Get a value from and array made of name|value items
|
|
57
|
-
* @param array : the array to scan
|
|
58
|
-
* @param value : the value to search for
|
|
59
|
-
* @returns : the property value or null if not found
|
|
60
|
-
*/
|
|
61
|
-
static arrayGetValue(array, value) {
|
|
62
|
-
if (!array)
|
|
63
|
-
return null;
|
|
64
|
-
for (var i = 0; i < array.length; i++) {
|
|
65
|
-
const item = array[i];
|
|
66
|
-
if (item.value === value) {
|
|
67
|
-
return item.name || item.id;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Convert items to nodes into a tree structure
|
|
74
|
-
* @param items : list of nodes
|
|
75
|
-
* @param parent : parent node
|
|
76
|
-
* @returns : an array of INode objects
|
|
77
|
-
*/
|
|
78
|
-
static arrayToNodes(items, parent = null) {
|
|
79
|
-
const nodes = [];
|
|
80
|
-
items.forEach((n) => {
|
|
81
|
-
const node = {
|
|
82
|
-
id: n.id.toString(),
|
|
83
|
-
name: n.name,
|
|
84
|
-
count: n.count ? n.count : 0,
|
|
85
|
-
children: null,
|
|
86
|
-
parent,
|
|
87
|
-
bag: n,
|
|
88
|
-
};
|
|
89
|
-
nodes.push(node);
|
|
90
|
-
node.children =
|
|
91
|
-
n.children && n.children.length > 0
|
|
92
|
-
? this.arrayToNodes(n.children, node)
|
|
93
|
-
: [];
|
|
94
|
-
});
|
|
95
|
-
return nodes;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Used to copare items during an array of objects sorting
|
|
99
|
-
* @param key : the property name to sort for
|
|
100
|
-
* @param order : the order 'asc' or 'desc'
|
|
101
|
-
* @returns : 0 if equals, 1 if bigger, -1 if lower
|
|
102
|
-
*/
|
|
103
|
-
static arraySortCompare(key, order = "asc") {
|
|
104
|
-
const result = function innerSort(a, b) {
|
|
105
|
-
if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) {
|
|
106
|
-
// property doesn't exist on either object
|
|
107
|
-
return 0;
|
|
108
|
-
}
|
|
109
|
-
const varA = typeof a[key] === "string" ? a[key].toUpperCase() : a[key];
|
|
110
|
-
const varB = typeof b[key] === "string" ? b[key].toUpperCase() : b[key];
|
|
111
|
-
let comparison = 0;
|
|
112
|
-
if (varA > varB)
|
|
113
|
-
comparison = 1;
|
|
114
|
-
else if (varA < varB)
|
|
115
|
-
comparison = -1;
|
|
116
|
-
return order === "desc" ? comparison * -1 : comparison;
|
|
117
|
-
};
|
|
118
|
-
return result;
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Format weight
|
|
122
|
-
* @param gr : grams
|
|
123
|
-
* @returns : the formatted string
|
|
124
|
-
*/
|
|
125
|
-
static formatWeight(gr) {
|
|
126
|
-
if (gr > 1000000)
|
|
127
|
-
return (gr / 1000000).toFixed(2) + " t";
|
|
128
|
-
else if (gr > 100000)
|
|
129
|
-
return (gr / 100000).toFixed(2) + " q";
|
|
130
|
-
else if (gr > 1000)
|
|
131
|
-
return (gr / 1000).toFixed(2) + " kg";
|
|
132
|
-
else
|
|
133
|
-
return gr + " gr";
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Format file size
|
|
137
|
-
* @param bytes : number of bytes
|
|
138
|
-
* @returns : the formatted string
|
|
139
|
-
*/
|
|
140
|
-
static formatFileSize(bytes) {
|
|
141
|
-
if (bytes > 1024000)
|
|
142
|
-
return (bytes / 1024000).toFixed(1) + " MB";
|
|
143
|
-
if (bytes > 1024)
|
|
144
|
-
return (bytes / 1024).toFixed(1) + " Kb";
|
|
145
|
-
return bytes + " byte";
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Compare two string
|
|
149
|
-
* @param a : string a
|
|
150
|
-
* @param b : string b
|
|
151
|
-
* @returns : 0 if equals, 1 if bigger, -1 if lower
|
|
152
|
-
*/
|
|
153
|
-
static compareString(a, b) {
|
|
154
|
-
if ((a ?? "").toLowerCase() > (b ?? "").toLowerCase())
|
|
155
|
-
return 1;
|
|
156
|
-
if ((a ?? "").toLowerCase() < (b ?? "").toLowerCase())
|
|
157
|
-
return -1;
|
|
158
|
-
return 0;
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Capitalize a string
|
|
162
|
-
* @param s : the string to capitalize
|
|
163
|
-
* @returns : the capitalized string
|
|
164
|
-
*/
|
|
165
|
-
static capitalize(s) {
|
|
166
|
-
if (!s)
|
|
167
|
-
return null;
|
|
168
|
-
let b = "";
|
|
169
|
-
let cap = true;
|
|
170
|
-
for (const char of s) {
|
|
171
|
-
if (char === " ") {
|
|
172
|
-
b += char;
|
|
173
|
-
cap = true;
|
|
174
|
-
}
|
|
175
|
-
else if (cap) {
|
|
176
|
-
b += char.toUpperCase();
|
|
177
|
-
cap = false;
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
b += char.toLowerCase();
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return b;
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Truncate a string
|
|
187
|
-
* @param s : the string to truncate
|
|
188
|
-
* @param max : the max number of chars
|
|
189
|
-
* @returns : the truncated string
|
|
190
|
-
*/
|
|
191
|
-
static truncate(s, max = 500) {
|
|
192
|
-
if (!s)
|
|
193
|
-
return null;
|
|
194
|
-
if (s.length < max)
|
|
195
|
-
return s;
|
|
196
|
-
let i = max - 1;
|
|
197
|
-
while (i > 0) {
|
|
198
|
-
if (s[i] === ' ')
|
|
199
|
-
return s.slice(0, i);
|
|
200
|
-
i--;
|
|
201
|
-
}
|
|
202
|
-
return s;
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* Join a list of strings
|
|
206
|
-
* @param items : the list of strings
|
|
207
|
-
* @param sep : the separator string
|
|
208
|
-
* @param max : the maximum resulting string
|
|
209
|
-
* @returns : the joined string
|
|
210
|
-
*/
|
|
211
|
-
static join(items, sep = " ", max = 350) {
|
|
212
|
-
if (!items || items.length === 0)
|
|
213
|
-
return null;
|
|
214
|
-
if (items.length > 1) {
|
|
215
|
-
let l = 0;
|
|
216
|
-
let s = "";
|
|
217
|
-
while (s.length < max && items.length > l) {
|
|
218
|
-
if (l > 0) {
|
|
219
|
-
s += sep;
|
|
220
|
-
}
|
|
221
|
-
s += items[l++];
|
|
222
|
-
}
|
|
223
|
-
if (items.length > l) {
|
|
224
|
-
s += "...";
|
|
225
|
-
}
|
|
226
|
-
return s;
|
|
227
|
-
}
|
|
228
|
-
return items[0];
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Replace stuff in text html
|
|
232
|
-
* @param s : the string to process
|
|
233
|
-
* @returns : the replaced string
|
|
234
|
-
*/
|
|
235
|
-
static replaceAsHtml(s) {
|
|
236
|
-
const regex = /https?:\/\/.*[^\s]/ig;
|
|
237
|
-
const m = regex.exec(s);
|
|
238
|
-
if (m && m.length > 0) {
|
|
239
|
-
let v = null;
|
|
240
|
-
for (let i = 0; i < m.length; i++) {
|
|
241
|
-
v = m[i];
|
|
242
|
-
s = s.replace(v, '<a href="' + v + '" target="_blank">' + v + '</a>');
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
return s;
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Compare two names
|
|
249
|
-
* @param a : name a
|
|
250
|
-
* @param b : name b
|
|
251
|
-
* @returns : true if a equals b
|
|
252
|
-
*/
|
|
253
|
-
static compareNames(a, b) {
|
|
254
|
-
if (a)
|
|
255
|
-
a = a.trim();
|
|
256
|
-
if (b)
|
|
257
|
-
b = b.trim();
|
|
258
|
-
if (a && b && a.length !== b.length)
|
|
259
|
-
return false;
|
|
260
|
-
if (this.compareString(a, b) === 0)
|
|
261
|
-
return true;
|
|
262
|
-
const p1 = a.split(" ");
|
|
263
|
-
const p2 = b.split(" ");
|
|
264
|
-
if (p1.length !== p2.length)
|
|
265
|
-
return false;
|
|
266
|
-
let matches = p1.length;
|
|
267
|
-
for (const s1 of p1) {
|
|
268
|
-
for (const s2 of p2) {
|
|
269
|
-
if (this.compareString(s1, s2) === 0) {
|
|
270
|
-
matches--;
|
|
271
|
-
break;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
return matches === 0;
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* Cipher a text
|
|
279
|
-
* @param text : the text
|
|
280
|
-
* @param key : the key
|
|
281
|
-
* @param reverse : true to decode, false to encode
|
|
282
|
-
* @returns :the ciphered text
|
|
283
|
-
*/
|
|
284
|
-
static cipher(text, key, reverse = false) {
|
|
285
|
-
// Surrogate pair limit
|
|
286
|
-
var bound = 0x10000;
|
|
287
|
-
// Create string from character codes
|
|
288
|
-
return String.fromCharCode.apply(null,
|
|
289
|
-
// Turn string to character codes
|
|
290
|
-
text.split("").map(function (v, i) {
|
|
291
|
-
// Get rotation from key
|
|
292
|
-
var rotation = key.charCodeAt(i % key.length);
|
|
293
|
-
// Are we decrypting?
|
|
294
|
-
if (reverse)
|
|
295
|
-
rotation = -rotation;
|
|
296
|
-
// Return current character code + rotation
|
|
297
|
-
return (v.charCodeAt() + rotation + bound) % bound;
|
|
298
|
-
}));
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* Clone an object using JSON
|
|
302
|
-
* @param obj : the oblect to clone
|
|
303
|
-
* @returns : a new object
|
|
304
|
-
*/
|
|
305
|
-
static clone(obj) {
|
|
306
|
-
if (!obj)
|
|
307
|
-
return null;
|
|
308
|
-
return JSON.parse(JSON.stringify(obj));
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* Clone an object using deep cloning
|
|
312
|
-
* @param obj : the oblect to clone
|
|
313
|
-
* @returns : a new object
|
|
314
|
-
*/
|
|
315
|
-
static deepClone(obj, dest = null) {
|
|
316
|
-
const cloneObj = dest ? dest : obj.constructor();
|
|
317
|
-
const attributes = Object.keys(obj);
|
|
318
|
-
for (const attribute of attributes) {
|
|
319
|
-
const property = obj[attribute];
|
|
320
|
-
if (typeof property === "object" && property != null) {
|
|
321
|
-
cloneObj[attribute] = this.deepClone(property);
|
|
322
|
-
}
|
|
323
|
-
else {
|
|
324
|
-
cloneObj[attribute] = property;
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
return cloneObj;
|
|
328
|
-
}
|
|
329
|
-
/**
|
|
330
|
-
* Check if a string is a valid UUID
|
|
331
|
-
* @param value : the value to parse
|
|
332
|
-
* @returns : true if is a valid UUID
|
|
333
|
-
*/
|
|
334
|
-
static parseUUID(value) {
|
|
335
|
-
const regex = /^({|()?[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}(}|))?$/;
|
|
336
|
-
return regex.test(value);
|
|
337
|
-
}
|
|
338
|
-
/**
|
|
339
|
-
* Parse and ensure that UUID is not empty
|
|
340
|
-
* @param value : the value to parse
|
|
341
|
-
* @returns : true if valid and not empty
|
|
342
|
-
*/
|
|
343
|
-
static parseUUIDNotEmpty(value) {
|
|
344
|
-
const regex = /^({|()?0{8}-(0{4}-){3}0{12}(}|))?$/;
|
|
345
|
-
return this.parseUUID(value) && !regex.test(value);
|
|
346
|
-
}
|
|
347
|
-
/**
|
|
348
|
-
* Return an empty UUID
|
|
349
|
-
* @returns : the empty UUID
|
|
350
|
-
*/
|
|
351
|
-
static emptyUUID() { return "00000000-0000-0000-0000-000000000000"; }
|
|
352
|
-
;
|
|
353
|
-
/**
|
|
354
|
-
* Create a new UUID
|
|
355
|
-
* @returns : the string UUID
|
|
356
|
-
*/
|
|
357
|
-
static generateUUID() {
|
|
358
|
-
const regex = /[xy]/g;
|
|
359
|
-
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(regex, function (c) {
|
|
360
|
-
var r = (Math.random() * 16) | 0, v = c === "x" ? r : (r & 0x3) | 0x8;
|
|
361
|
-
return v.toString(16);
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* Parse a text and return true if is a valid email or null
|
|
366
|
-
* @param value : email
|
|
367
|
-
* @returns : true if the email is valid or empty
|
|
368
|
-
*/
|
|
369
|
-
static parseEmail(value) {
|
|
370
|
-
if (!value)
|
|
371
|
-
return true;
|
|
372
|
-
const regex = /(?:[a-z0-9+!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/gi;
|
|
373
|
-
return regex.test(value.trim().toLowerCase());
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* Parse a text and return true if is a valid url or null
|
|
377
|
-
* @param value : the url to parse
|
|
378
|
-
* @returns : true if the url is valid or empty
|
|
379
|
-
*/
|
|
380
|
-
static parseUrl(value) {
|
|
381
|
-
if (!value)
|
|
382
|
-
return true;
|
|
383
|
-
const regex = new RegExp("(https?://)?([\\da-z.-]+)\\.([a-z.]{2,6})[/\\w .-]*/?");
|
|
384
|
-
return regex.test(value.trim().toLowerCase());
|
|
385
|
-
}
|
|
386
|
-
/**
|
|
387
|
-
* Get date parts from a string value
|
|
388
|
-
* @param value : the string to parse
|
|
389
|
-
* @returns : an array of numbers with year, month, day
|
|
390
|
-
*/
|
|
391
|
-
static getDateParts(value) {
|
|
392
|
-
if (!value)
|
|
393
|
-
return null;
|
|
394
|
-
let parts = [];
|
|
395
|
-
if (value.indexOf("-") !== -1) {
|
|
396
|
-
const p = value.split("-");
|
|
397
|
-
if (p.length !== 3)
|
|
398
|
-
return null;
|
|
399
|
-
parts = [parseInt(p[0]), parseInt(p[1]) - 1, parseInt(p[2])];
|
|
400
|
-
}
|
|
401
|
-
else if (value.indexOf("/") !== -1) {
|
|
402
|
-
const p = value.split("/");
|
|
403
|
-
if (p.length !== 3)
|
|
404
|
-
return null;
|
|
405
|
-
parts = [parseInt(p[2]), parseInt(p[1]) - 1, parseInt(p[0])];
|
|
406
|
-
}
|
|
407
|
-
return parts;
|
|
408
|
-
}
|
|
409
|
-
/**
|
|
410
|
-
* Parse a date
|
|
411
|
-
* @param value : the value to check
|
|
412
|
-
* @param locale : the locale to use
|
|
413
|
-
* @returns : a valid Date object or null
|
|
414
|
-
*/
|
|
415
|
-
static parseDate(value, locale = it) {
|
|
416
|
-
// No value at all
|
|
417
|
-
if (!value)
|
|
418
|
-
return null;
|
|
419
|
-
// A Date value
|
|
420
|
-
if (value instanceof Date && value.getTime())
|
|
421
|
-
return value;
|
|
422
|
-
// Parse known formats using date-fns
|
|
423
|
-
let d = parseISO(value);
|
|
424
|
-
if (d && d.getTime() && d.getFullYear() > 1750)
|
|
425
|
-
return d;
|
|
426
|
-
d = parse(value, 'dd/MM/yyyy', new Date(), { locale: locale });
|
|
427
|
-
if (d && d.getTime() && d.getFullYear() > 1750)
|
|
428
|
-
return d;
|
|
429
|
-
d = parse(value, 'yyyy-MM-dd', new Date(), { locale: locale });
|
|
430
|
-
if (d && d.getTime() && d.getFullYear() > 1750)
|
|
431
|
-
return d;
|
|
432
|
-
// Parse values manually
|
|
433
|
-
let parts = this.getDateParts(value);
|
|
434
|
-
if (parts[0] < 100)
|
|
435
|
-
parts[0] += 2000;
|
|
436
|
-
if (isNaN(parts[0]) || parts[0] < 0 || parts[0] < 1750)
|
|
437
|
-
return null;
|
|
438
|
-
if (isNaN(parts[1]) || parts[1] < 0)
|
|
439
|
-
return null;
|
|
440
|
-
if (isNaN(parts[2]) || parts[2] < 0)
|
|
441
|
-
return null;
|
|
442
|
-
if (parts[1] > 11)
|
|
443
|
-
return null;
|
|
444
|
-
if (parts[1] === 1 && parts[2] > 29)
|
|
445
|
-
return null;
|
|
446
|
-
else if (parts[1] !== 1 && parts[2] > 31)
|
|
447
|
-
return null;
|
|
448
|
-
return new Date(parts[0], parts[1], parts[2], 2);
|
|
449
|
-
}
|
|
450
|
-
/**
|
|
451
|
-
* Format a date
|
|
452
|
-
* @param value : the date or string to format
|
|
453
|
-
* @param fmt : the DateFormat to use or the string pattern
|
|
454
|
-
* @param locale : the locale to use (default is IT)
|
|
455
|
-
* @returns : the formatted string
|
|
456
|
-
*/
|
|
457
|
-
static formatDate(value, fmt = DateFormat.Short, locale = it) {
|
|
458
|
-
// No value at all
|
|
459
|
-
if (!value)
|
|
460
|
-
return null;
|
|
461
|
-
// A string
|
|
462
|
-
if (typeof value === 'string' || value instanceof String)
|
|
463
|
-
value = this.parseDate(value);
|
|
464
|
-
// Not a date
|
|
465
|
-
if (!(value instanceof Date && value.getTime()))
|
|
466
|
-
return null;
|
|
467
|
-
// Format
|
|
468
|
-
switch (fmt) {
|
|
469
|
-
case DateFormat.Short: return format(value, "dd/MM/yyyy", { locale: locale });
|
|
470
|
-
case DateFormat.Long: return format(value, "d MMMM yyyy", { locale: locale });
|
|
471
|
-
case DateFormat.LongWithShortMonth: return format(value, "d MMM yyyy", { locale: locale });
|
|
472
|
-
case DateFormat.LongWithWeekDay: return format(value, "EEEE, d MMMM yyyy", { locale: locale });
|
|
473
|
-
case DateFormat.LongWithShortWeekDay: return format(value, "EEE, d MMMM yyyy", { locale: locale });
|
|
474
|
-
case DateFormat.MonthAndYear: return format(value, "MMM yyyy", { locale: locale });
|
|
475
|
-
case DateFormat.LongMonthAndYear: return format(value, "MMMM yyyy", { locale: locale });
|
|
476
|
-
case DateFormat.WeekDay: return format(value, "EEE, d", { locale: locale });
|
|
477
|
-
case DateFormat.LongWeekDay: return format(value, "EEEE, d", { locale: locale });
|
|
478
|
-
case DateFormat.DayAndMonth: return format(value, "d MMMM", { locale: locale });
|
|
479
|
-
case DateFormat.ShortUS: return format(value, "MM/dd/yyyy", { locale: locale });
|
|
480
|
-
case DateFormat.ShortISO8601: return format(value, "yyyy-MM-dd", { locale: locale });
|
|
481
|
-
default:
|
|
482
|
-
return format(value, fmt, { locale: locale });
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
/**
|
|
486
|
-
* Return an italian local date
|
|
487
|
-
* @param value : the date
|
|
488
|
-
* @returns : the new date
|
|
489
|
-
*/
|
|
490
|
-
static toLocalDate(value) {
|
|
491
|
-
// No value at all
|
|
492
|
-
if (!value)
|
|
493
|
-
return null;
|
|
494
|
-
// A string
|
|
495
|
-
if (typeof value === 'string' || value instanceof String)
|
|
496
|
-
value = this.parseDate(value);
|
|
497
|
-
// Not a date
|
|
498
|
-
if (!(value instanceof Date && value.getTime()))
|
|
499
|
-
return null;
|
|
500
|
-
// Update date
|
|
501
|
-
return setHours(value, 2);
|
|
502
|
-
}
|
|
503
|
-
/**
|
|
504
|
-
* Update a DateInterval object according to a string
|
|
505
|
-
* @param value : string value
|
|
506
|
-
* @param interval : DateInterval value to update
|
|
507
|
-
* @param end : true if must be updated the first or the end value
|
|
508
|
-
* @param copy : copy the same value (works only if not end element)
|
|
509
|
-
*/
|
|
510
|
-
static changeDateInterval(value, interval, end = false, copy = false) {
|
|
511
|
-
if (value) {
|
|
512
|
-
let year = -1;
|
|
513
|
-
if (value.length === 4 && (year = parseInt(value)) > 1750) {
|
|
514
|
-
if (!end) {
|
|
515
|
-
interval.from = fromZonedTime(new Date(year, 0, 1), 'UTC');
|
|
516
|
-
interval.to = fromZonedTime(new Date(year, 11, 31), 'UTC');
|
|
517
|
-
}
|
|
518
|
-
else
|
|
519
|
-
interval.to = new Date(year, 11, 31);
|
|
520
|
-
}
|
|
521
|
-
else {
|
|
522
|
-
let parts = this.getDateParts(value);
|
|
523
|
-
if (!parts || isNaN(parts[0]) || parts[0] < 0 || parts[0] < 1750)
|
|
524
|
-
return;
|
|
525
|
-
const d = fromZonedTime(new Date(parts[0], parts[1], parts[2]), 'UTC');
|
|
526
|
-
if (end)
|
|
527
|
-
interval.to = d;
|
|
528
|
-
else if (copy) {
|
|
529
|
-
interval.from = d;
|
|
530
|
-
interval.to = d;
|
|
531
|
-
}
|
|
532
|
-
else
|
|
533
|
-
interval.from = d;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
/**
|
|
538
|
-
* Encode url
|
|
539
|
-
* @param value : the value to encode
|
|
540
|
-
* @returns : the url encoded string
|
|
541
|
-
*/
|
|
542
|
-
static urlEncode(value) {
|
|
543
|
-
return encodeURIComponent(value);
|
|
544
|
-
}
|
|
545
|
-
/**
|
|
546
|
-
* Decode url
|
|
547
|
-
* @param value : the url to decode
|
|
548
|
-
* @returns : the decode url string
|
|
549
|
-
*/
|
|
550
|
-
static urlDecode(value) {
|
|
551
|
-
const regex = /\+/g;
|
|
552
|
-
return decodeURIComponent((value + "").replace(regex, "%20"));
|
|
553
|
-
}
|
|
554
|
-
/**
|
|
555
|
-
* Get a querystring parameter value
|
|
556
|
-
* @param name : the parameter name
|
|
557
|
-
* @returns : the string value
|
|
558
|
-
*/
|
|
559
|
-
static getQueryStringValueByName(name) {
|
|
560
|
-
if (!this.isBrowser())
|
|
561
|
-
return null;
|
|
562
|
-
const url = window.location.href;
|
|
563
|
-
if (url.includes("?")) {
|
|
564
|
-
const httpParams = new HttpParams({ fromString: url.split("?")[1] });
|
|
565
|
-
const v = decodeURIComponent(httpParams.get(name));
|
|
566
|
-
if (v !== "null")
|
|
567
|
-
return v;
|
|
568
|
-
else
|
|
569
|
-
return null;
|
|
570
|
-
}
|
|
571
|
-
return null;
|
|
572
|
-
}
|
|
573
|
-
/**
|
|
574
|
-
* Generate a password
|
|
575
|
-
* @returns : the password string
|
|
576
|
-
*/
|
|
577
|
-
static generatePassword() {
|
|
578
|
-
const random = "$" + Math.random().toString(36).slice(-7);
|
|
579
|
-
let password = "";
|
|
580
|
-
let hasUpperCase = false;
|
|
581
|
-
for (const rnd of random) {
|
|
582
|
-
if (!hasUpperCase && "abcdefghjilmnopqrstuvywxz".includes(rnd)) {
|
|
583
|
-
password += rnd.toUpperCase();
|
|
584
|
-
hasUpperCase = true;
|
|
585
|
-
}
|
|
586
|
-
else {
|
|
587
|
-
password += rnd;
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
if (!hasUpperCase)
|
|
591
|
-
password = password.substring(0, 7) + "M";
|
|
592
|
-
return password;
|
|
593
|
-
}
|
|
594
|
-
/**
|
|
595
|
-
* Check if current browser supports touch
|
|
596
|
-
* @returns : true if the display is touchable
|
|
597
|
-
*/
|
|
598
|
-
static isTouchable() {
|
|
599
|
-
return (this.isBrowser() && ("ontouchstart" in window ||
|
|
600
|
-
navigator.maxTouchPoints > 0));
|
|
601
|
-
}
|
|
602
|
-
/**
|
|
603
|
-
* This check will prevent 'window' logic to be executed
|
|
604
|
-
* while executing the server rendering
|
|
605
|
-
* @returns : true if using the browser
|
|
606
|
-
*/
|
|
607
|
-
static isBrowser() {
|
|
608
|
-
return typeof (window) !== 'undefined';
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* Convert folders in a tree of Node object.
|
|
612
|
-
* @param folders : the subfolders group or null to root
|
|
613
|
-
* @returns : a node list
|
|
614
|
-
*/
|
|
615
|
-
static toNodes(folders) {
|
|
616
|
-
return this._toNodes(folders, undefined);
|
|
617
|
-
}
|
|
618
|
-
/**
|
|
619
|
-
* Convert folders in a tree of Node object.
|
|
620
|
-
* @param folders : the children group or null to root
|
|
621
|
-
* @param parent : the parent node
|
|
622
|
-
* @returns : a node list
|
|
623
|
-
*/
|
|
624
|
-
static _toNodes(folders, parent) {
|
|
625
|
-
const nodes = [];
|
|
626
|
-
folders.forEach((n) => {
|
|
627
|
-
const node = {
|
|
628
|
-
id: n.id,
|
|
629
|
-
name: n.name,
|
|
630
|
-
count: n.count,
|
|
631
|
-
parent: parent,
|
|
632
|
-
children: undefined,
|
|
633
|
-
bag: n,
|
|
634
|
-
};
|
|
635
|
-
node.children =
|
|
636
|
-
n.children && n.children.length > 0
|
|
637
|
-
? this._toNodes(n.children, node)
|
|
638
|
-
: [];
|
|
639
|
-
nodes.push(node);
|
|
640
|
-
});
|
|
641
|
-
return nodes;
|
|
642
|
-
}
|
|
643
|
-
/**
|
|
644
|
-
* Return the flags array to be used in selections
|
|
645
|
-
* @param value : the new value
|
|
646
|
-
* @param max: the max number of flags
|
|
647
|
-
*/
|
|
648
|
-
static getFlags(value, max = 30) {
|
|
649
|
-
if (value) {
|
|
650
|
-
let items = [];
|
|
651
|
-
let v = 1;
|
|
652
|
-
let m = 1 << max;
|
|
653
|
-
while (v < m) {
|
|
654
|
-
if ((value & v) === v)
|
|
655
|
-
items.push(v);
|
|
656
|
-
v = v << 1;
|
|
657
|
-
}
|
|
658
|
-
return items;
|
|
659
|
-
}
|
|
660
|
-
else
|
|
661
|
-
return [];
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3lzdGVtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvYXJzLXV0aWxzL2NvcmUvc3lzdGVtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUVsRCxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQzdELE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNyQyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBWTVDLE1BQU0sQ0FBTixJQUFZLFVBYVg7QUFiRCxXQUFZLFVBQVU7SUFDcEIsNkNBQVMsQ0FBQTtJQUNULDJDQUFRLENBQUE7SUFDUix1RUFBc0IsQ0FBQTtJQUN0QixpRUFBbUIsQ0FBQTtJQUNuQiwyRUFBd0IsQ0FBQTtJQUN4QiwyREFBZ0IsQ0FBQTtJQUNoQixtRUFBb0IsQ0FBQTtJQUNwQixpREFBVyxDQUFBO0lBQ1gseURBQWUsQ0FBQTtJQUNmLDBEQUFnQixDQUFBO0lBQ2hCLGtEQUFZLENBQUE7SUFDWiw0REFBaUIsQ0FBQSxDQUFTLGFBQWE7QUFDekMsQ0FBQyxFQWJXLFVBQVUsS0FBVixVQUFVLFFBYXJCO0FBRUQsTUFBTSxPQUFPLFdBQVc7SUFDdEI7Ozs7OztPQU1HO0lBQ0gsTUFBTSxDQUFDLGNBQWMsQ0FBSSxLQUE2QixFQUFFLEdBQVcsRUFBRSxLQUFVO1FBQzdFLElBQUksQ0FBQyxLQUFLO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFDeEIsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUN6QixJQUFLLElBQVksQ0FBQyxHQUFHLENBQUMsS0FBSyxLQUFLLEVBQUUsQ0FBQztnQkFDakMsT0FBTyxJQUFJLENBQUM7WUFDZCxDQUFDO1FBQ0gsQ0FBQztRQUNELE9BQU8sSUFBSSxD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RixJQUFJLENBQUMsUUFBUTtnQkFDWCxDQUFDLENBQUMsUUFBUSxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUM7b0JBQ2pDLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDO29CQUNqQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ1QsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNuQixDQUFDLENBQUMsQ0FBQztRQUNILE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVEOzs7O0tBSUM7SUFDRCxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQWEsRUFBRSxNQUFjLEVBQUU7UUFDN0MsSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUNWLElBQUksS0FBSyxHQUFhLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDVixJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDO1lBQ2pCLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUNiLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQztvQkFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNyQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNiLENBQUM7WUFDRCxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7O1lBQU0sT0FBTyxFQUFFLENBQUM7SUFDbkIsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSHR0cFBhcmFtcyB9IGZyb20gXCJAYW5ndWxhci9jb21tb24vaHR0cFwiO1xyXG5pbXBvcnQgeyBEYXRlSW50ZXJ2YWwgfSBmcm9tICcuL2RlZmluaXRpb25zJztcclxuaW1wb3J0IHsgZm9ybWF0LCBwYXJzZSwgcGFyc2VJU08sIHNldEhvdXJzIH0gZnJvbSAnZGF0ZS1mbnMnO1xyXG5pbXBvcnQgeyBpdCB9IGZyb20gJ2RhdGUtZm5zL2xvY2FsZSc7XHJcbmltcG9ydCB7IGZyb21ab25lZFRpbWUgfSBmcm9tICdkYXRlLWZucy10eic7XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIElOb2RlIHtcclxuICBpZDogc3RyaW5nO1xyXG4gIG5hbWU/OiBzdHJpbmcgfCBudWxsO1xyXG4gIGNvdW50PzogbnVtYmVyIHwgbnVsbDtcclxuICBjaGlsZHJlbj86IElOb2RlW10gfCBudWxsO1xyXG4gIHBhcmVudD86IElOb2RlIHwgbnVsbDtcclxuICBiYWc/OiBhbnkgfCBudWxsXHJcbn1cclxuXHJcblxyXG5leHBvcnQgZW51bSBEYXRlRm9ybWF0IHtcclxuICBTaG9ydCA9IDEsICAgICAgICAgICAgICAgIC8vIGRkL21tL3l5eXlcclxuICBMb25nID0gMiwgICAgICAgICAgICAgICAgIC8vIGQgbW1tbSB5eXl5XHJcbiAgTG9uZ1dpdGhTaG9ydE1vbnRoID0gMywgICAvLyBkIG1tbSB5eXl5XHJcbiAgTG9uZ1dpdGhXZWVrRGF5ID0gNCwgICAgICAvLyB3d3d3LCBkIG1tbW0geXl5eVxyXG4gIExvbmdXaXRoU2hvcnRXZWVrRGF5ID0gNSwgLy8gd3d3LCBkIG1tbW0geXl5eVxyXG4gIE1vbnRoQW5kWWVhciA9IDYsICAgICAgICAgLy8gbW1tIHl5eXlcclxuICBMb25nTW9udGhBbmRZZWFyID0gNywgICAgIC8vIG1tbW0geXl5eVxyXG4gIFdlZWtEYXkgPSA4LCAgICAgICAgICAgICAgLy8gd3d3IGRcclxuICBMb25nV2Vla0RheSA9IDksICAgICAgICAgIC8vIHd3d3cgZFxyXG4gIERheUFuZE1vbnRoID0gMTAsICAgICAgICAgLy8gZCBtbW1tXHJcbiAgU2hvcnRVUyA9IDExLCAgICAgICAgICAgICAvLyBtbS9kZC95eXl5XHJcbiAgU2hvcnRJU084NjAxID0gMTIgICAgICAgICAvLyB5eXl5LW1tLWRkXHJcbn1cclxuXHJcbmV4cG9ydCBjbGFzcyBTeXN0ZW1VdGlscyB7XHJcbiAgLyoqXHJcbiAgICogQXJyYXkgZmluZCBieSBrZXlcclxuICAgKiBAcGFyYW0gYXJyYXkgICAgIDogdGhlIGFycmF5IHRvIHNjYW5cclxuICAgKiBAcGFyYW0ga2V5ICAgICAgIDoga2V5IG5hbWVcclxuICAgKiBAcGFyYW0gdmFsdWUgICAgIDogdGhlIHZhbHVlIHRvIHNlYXJjaCBmb3JcclxuICAgKiBAcmV0dXJucyAgICAgICAgIDogdGhlIHByb3BlcnR5IHZhbHVlIG9yIG51bGxcclxuICAgKi9cclxuICBzdGF0aWMgYXJyYXlGaW5kQnlLZXk8VD4oYXJyYXk6IFRbXSB8IG51bGwgfCB1bmRlZmluZWQsIGtleTogc3RyaW5nLCB2YWx1ZTogYW55KTogVCB8IG51bGwge1xyXG4gICAgaWYgKCFhcnJheSkgcmV0dXJuIG51bGw7XHJcbiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgYXJyYXkpIHtcclxuICAgICAgaWYgKChpdGVtIGFzIGFueSlba2V5XSA9PT0gdmFsdWUpIHtcclxuICAgICAgICByZXR1cm4gaXRlbTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBcnJheSBmaW5kIGluZGV4IGJ5IGtleVxyXG4gICAqIEBwYXJhbSBhcnJheSAgIDogdGhlIGFycmF5IHRvIHNjYW5cclxuICAgKiBAcGFyYW0ga2V5ICAgICA6IHRoZSBrZXkgbmFtZVxyXG4gICAqIEBwYXJhbSB2YWx1ZSAgIDogdGhlIHZhbHVlIHRvIHNlYXJjaCBmb3JcclxuICAgKiBAcmV0dXJucyAgICAgICA6IHRoZSBhcnJheSBpbmRleCBvciAtMSBpZiBub3QgZm91bmRcclxuICAgKi9cclxuICBzdGF0aWMgYXJyYXlGaW5kSW5kZXhCeUtleTxUPihhcnJheTogVFtdIHwgbnVsbCB8IHVuZGVmaW5lZCwga2V5OiBzdHJpbmcsIHZhbHVlOiBhbnkpOiBudW1iZXIge1xyXG4gICAgaWYgKCFhcnJheSkgcmV0dXJuIC0xO1xyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xyXG4gICAgICBpZiAoKGFycmF5W2ldIGFzIGFueSlba2V5XSA9PT0gdmFsdWUpIHtcclxuICAgICAgICByZXR1cm4gaTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIC0xO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0IGEgdmFsdWUgZnJvbSBhbmQgYXJyYXkgbWFkZSBvZiBuYW1lfHZhbHVlIGl0ZW1zXHJcbiAgICogQHBhcmFtIGFycmF5ICAgOiB0aGUgYXJyYXkgdG8gc2NhblxyXG4gICAqIEBwYXJhbSB2YWx1ZSAgIDogdGhlIHZhbHVlIHRvIHNlYXJjaCBmb3JcclxuICAgKiBAcmV0dXJucyAgICAgICA6IHRoZSBwcm9wZXJ0eSB2YWx1ZSBvciBudWxsIGlmIG5vdCBmb3VuZFxyXG4gICAqL1xyXG4gIHN0YXRpYyBhcnJheUdldFZhbHVlPFQ+KGFycmF5OiBUW10gfCBudWxsIHwgdW5kZWZpbmVkLCB2YWx1ZTogYW55KTogYW55IHtcclxuICAgIGlmICghYXJyYXkpIHJldHVybiBudWxsO1xyXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xyXG4gICAgICBjb25zdCBpdGVtID0gKGFycmF5W2ldIGFzIGFueSk7XHJcbiAgICAgIGlmIChpdGVtLnZhbHVlID09PSB2YWx1ZSkge1xyXG4gICAgICAgIHJldHVybiBpdGVtLm5hbWUgfHwgaXRlbS5pZDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDb252ZXJ0IGl0ZW1zIHRvIG5vZGVzIGludG8gYSB0cmVlIHN0cnVjdHVyZVxyXG4gICAqIEBwYXJhbSBpdGVtcyAgIDogbGlzdCBvZiBub2Rlc1xyXG4gICAqIEBwYXJhbSBwYXJlbnQgIDogcGFyZW50IG5vZGVcclxuICAgKiBAcmV0dXJucyAgICAgICA6IGFuIGFycmF5IG9mIElOb2RlIG9iamVjdHNcclxuICAgKi9cclxuICBzdGF0aWMgYXJyYXlUb05vZGVzKGl0ZW1zOiBJTm9kZVtdLCBwYXJlbnQ6IElOb2RlID0gbnVsbCk6IElOb2RlW10ge1xyXG4gICAgY29uc3Qgbm9kZXM6IElOb2RlW10gPSBbXTtcclxuICAgIGl0ZW1zLmZvckVhY2goKG4pID0+IHtcclxuICAgICAgY29uc3Qgbm9kZTogSU5vZGUgPSB7XHJcbiAgICAgICAgaWQ6IG4uaWQudG9TdHJpbmcoKSxcclxuICAgICAgICBuYW1lOiBuLm5hbWUsXHJcbiAgICAgICAgY291bnQ6IG4uY291bnQgPyBuLmNvdW50IDogMCxcclxuICAgICAgICBjaGlsZHJlbjogbnVsbCxcclxuICAgICAgICBwYXJlbnQsXHJcbiAgICAgICAgYmFnOiBuLFxyXG4gICAgICB9O1xyXG4gICAgICBub2Rlcy5wdXNoKG5vZGUpO1xyXG4gICAgICBub2RlLmNoaWxkcmVuID1cclxuICAgICAgICBuLmNoaWxkcmVuICYmIG4uY2hpbGRyZW4ubGVuZ3RoID4gMFxyXG4gICAgICAgICAgPyB0aGlzLmFycmF5VG9Ob2RlcyhuLmNoaWxkcmVuLCBub2RlKVxyXG4gICAgICAgICAgOiBbXTtcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIG5vZGVzO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVXNlZCB0byBjb3BhcmUgaXRlbXMgZHVyaW5nIGFuIGFycmF5IG9mIG9iamVjdHMgc29ydGluZ1xyXG4gICAqIEBwYXJhbSBrZXkgICAgIDogdGhlIHByb3BlcnR5IG5hbWUgdG8gc29ydCBmb3JcclxuICAgKiBAcGFyYW0gb3JkZXIgICA6IHRoZSBvcmRlciAnYXNjJyBvciAnZGVzYydcclxuICAgKiBAcmV0dXJucyAgICAgICA6IDAgaWYgZXF1YWxzLCAxIGlmIGJpZ2dlciwgLTEgaWYgbG93ZXJcclxuICAgKi9cclxuICBzdGF0aWMgYXJyYXlTb3J0Q29tcGFyZShrZXk6IHN0cmluZywgb3JkZXI6IHN0cmluZyA9IFwiYXNjXCIpIHtcclxuICAgIGNvbnN0IHJlc3VsdCA9IGZ1bmN0aW9uIGlubmVyU29ydChhOiBhbnksIGI6IGFueSkge1xyXG4gICAgICBpZiAoIWEuaGFzT3duUHJvcGVydHkoa2V5KSB8fCAhYi5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XHJcbiAgICAgICAgLy8gcHJvcGVydHkgZG9lc24ndCBleGlzdCBvbiBlaXRoZXIgb2JqZWN0XHJcbiAgICAgICAgcmV0dXJuIDA7XHJcbiAgICAgIH1cclxuICAgICAgY29uc3QgdmFyQSA9IHR5cGVvZiBhW2tleV0gPT09IFwic3RyaW5nXCIgPyBhW2tleV0udG9VcHBlckNhc2UoKSA6IGFba2V5XTtcclxuICAgICAgY29uc3QgdmFyQiA9IHR5cGVvZiBiW2tleV0gPT09IFwic3RyaW5nXCIgPyBiW2tleV0udG9VcHBlckNhc2UoKSA6IGJba2V5XTtcclxuICAgICAgbGV0IGNvbXBhcmlzb24gPSAwO1xyXG4gICAgICBpZiAodmFyQSA+IHZhckIpIGNvbXBhcmlzb24gPSAxO1xyXG4gICAgICBlbHNlIGlmICh2YXJBIDwgdmFyQikgY29tcGFyaXNvbiA9IC0xO1xyXG4gICAgICByZXR1cm4gb3JkZXIgPT09IFwiZGVzY1wiID8gY29tcGFyaXNvbiAqIC0xIDogY29tcGFyaXNvbjtcclxuICAgIH07XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRm9ybWF0IHdlaWdodFxyXG4gICAqIEBwYXJhbSBnciAgICA6IGdyYW1zXHJcbiAgICogQHJldHVybnMgICAgIDogdGhlIGZvcm1hdHRlZCBzdHJpbmdcclxuICAgKi9cclxuICBzdGF0aWMgZm9ybWF0V2VpZ2h0KGdyOiBudW1iZXIpOiBzdHJpbmcge1xyXG4gICAgaWYgKGdyID4gMTAwMDAwMCkgcmV0dXJuIChnciAvIDEwMDAwMDApLnRvRml4ZWQoMikgKyBcIiB0XCI7XHJcbiAgICBlbHNlIGlmIChnciA+IDEwMDAwMCkgcmV0dXJuIChnciAvIDEwMDAwMCkudG9GaXhlZCgyKSArIFwiIHFcIjtcclxuICAgIGVsc2UgaWYgKGdyID4gMTAwMCkgcmV0dXJuIChnciAvIDEwMDApLnRvRml4ZWQoMikgKyBcIiBrZ1wiO1xyXG4gICAgZWxzZSByZXR1cm4gZ3IgKyBcIiBnclwiO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRm9ybWF0IGZpbGUgc2l6ZVxyXG4gICAqIEBwYXJhbSBieXRlcyA6IG51bWJlciBvZiBieXRlc1xyXG4gICAqIEByZXR1cm5zICAgICA6IHRoZSBmb3JtYXR0ZWQgc3RyaW5nXHJcbiAgICovXHJcbiAgc3RhdGljIGZvcm1hdEZpbGVTaXplKGJ5dGVzOiBudW1iZXIpOiBzdHJpbmcge1xyXG4gICAgaWYgKGJ5dGVzID4gMTAyNDAwMCkgcmV0dXJuIChieXRlcyAvIDEwMjQwMDApLnRvRml4ZWQoMSkgKyBcIiBNQlwiO1xyXG4gICAgaWYgKGJ5dGVzID4gMTAyNCkgcmV0dXJuIChieXRlcyAvIDEwMjQpLnRvRml4ZWQoMSkgKyBcIiBLYlwiO1xyXG4gICAgcmV0dXJuIGJ5dGVzICsgXCIgYnl0ZVwiO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ29tcGFyZSB0d28gc3RyaW5nXHJcbiAgICogQHBhcmFtIGEgICA6IHN0cmluZyBhXHJcbiAgICogQHBhcmFtIGIgICA6IHN0cmluZyBiXHJcbiAgICogQHJldHVybnMgICA6IDAgaWYgZXF1YWxzLCAxIGlmIGJpZ2dlciwgLTEgaWYgbG93ZXJcclxuICAgKi9cclxuICBzdGF0aWMgY29tcGFyZVN0cmluZyhhOiBzdHJpbmcsIGI6IHN0cmluZyk6IG51bWJlciB7XHJcbiAgICBpZiAoKGEgPz8gXCJcIikudG9Mb3dlckNhc2UoKSA+IChiID8/IFwiXCIpLnRvTG93ZXJDYXNlKCkpIHJldHVybiAxO1xyXG4gICAgaWYgKChhID8/IFwiXCIpLnRvTG93ZXJDYXNlKCkgPCAoYiA/PyBcIlwiKS50b0xvd2VyQ2FzZSgpKSByZXR1cm4gLTE7XHJcbiAgICByZXR1cm4gMDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENhcGl0YWxpemUgYSBzdHJpbmdcclxuICAgKiBAcGFyYW0gcyAgIDogdGhlIHN0cmluZyB0byBjYXBpdGFsaXplXHJcbiAgICogQHJldHVybnMgICA6IHRoZSBjYXBpdGFsaXplZCBzdHJpbmcgIFxyXG4gICAqL1xyXG4gIHN0YXRpYyBjYXBpdGFsaXplKHM6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICBpZiAoIXMpIHJldHVybiBudWxsO1xyXG4gICAgbGV0IGIgPSBcIlwiO1xyXG4gICAgbGV0IGNhcCA9IHRydWU7XHJcbiAgICBmb3IgKGNvbnN0IGNoYXIgb2Ygcykge1xyXG4gICAgICBpZiAoY2hhciA9PT0gXCIgXCIpIHtcclxuICAgICAgICBiICs9IGNoYXI7XHJcbiAgICAgICAgY2FwID0gdHJ1ZTtcclxuICAgICAgfSBlbHNlIGlmIChjYXApIHtcclxuICAgICAgICBiICs9IGNoYXIudG9VcHBlckNhc2UoKTtcclxuICAgICAgICBjYXAgPSBmYWxzZTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBiICs9IGNoYXIudG9Mb3dlckNhc2UoKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGI7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUcnVuY2F0ZSBhIHN0cmluZ1xyXG4gICAqIEBwYXJhbSBzICAgICA6IHRoZSBzdHJpbmcgdG8gdHJ1bmNhdGVcclxuICAgKiBAcGFyYW0gbWF4ICAgOiB0aGUgbWF4IG51bWJlciBvZiBjaGFyc1xyXG4gICAqIEByZXR1cm5zICAgICA6IHRoZSB0cnVuY2F0ZWQgc3RyaW5nXHJcbiAgICovXHJcbiAgc3RhdGljIHRydW5jYXRlKHM6IHN0cmluZywgbWF4OiBudW1iZXIgPSA1MDApOiBzdHJpbmcge1xyXG4gICAgaWYgKCFzKSByZXR1cm4gbnVsbDtcclxuICAgIGlmIChzLmxlbmd0aCA8IG1heCkgcmV0dXJuIHM7XHJcbiAgICBsZXQgaSA9IG1heCAtIDE7XHJcbiAgICB3aGlsZSAoaSA+IDApIHtcclxuICAgICAgaWYgKHNbaV0gPT09ICcgJykgcmV0dXJuIHMuc2xpY2UoMCwgaSk7XHJcbiAgICAgIGktLTtcclxuICAgIH1cclxuICAgIHJldHVybiBzO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSm9pbiBhIGxpc3Qgb2Ygc3RyaW5nc1xyXG4gICAqIEBwYXJhbSBpdGVtcyAgICAgOiB0aGUgbGlzdCBvZiBzdHJpbmdzXHJcbiAgICogQHBhcmFtIHNlcCAgICAgICA6IHRoZSBzZXBhcmF0b3Igc3RyaW5nXHJcbiAgICogQHBhcmFtIG1heCAgICAgICA6IHRoZSBtYXhpbXVtIHJlc3VsdGluZyBzdHJpbmdcclxuICAgKiBAcmV0dXJucyAgICAgICAgIDogdGhlIGpvaW5lZCBzdHJpbmdcclxuICAgKi9cclxuICBzdGF0aWMgam9pbihpdGVtczogc3RyaW5nW10sIHNlcDogc3RyaW5nID0gXCIgXCIsIG1heDogbnVtYmVyID0gMzUwKTogc3RyaW5nIHtcclxuICAgIGlmICghaXRlbXMgfHwgaXRlbXMubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcclxuICAgIGlmIChpdGVtcy5sZW5ndGggPiAxKSB7XHJcbiAgICAgIGxldCBsID0gMDtcclxuICAgICAgbGV0IHMgPSBcIlwiXHJcbiAgICAgIHdoaWxlIChzLmxlbmd0aCA8IG1heCAmJiBpdGVtcy5sZW5ndGggPiBsKSB7XHJcbiAgICAgICAgaWYgKGwgPiAwKSB7XHJcbiAgICAgICAgICBzICs9IHNlcDtcclxuICAgICAgICB9XHJcbiAgICAgICAgcyArPSBpdGVtc1tsKytdO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChpdGVtcy5sZW5ndGggPiBsKSB7XHJcbiAgICAgICAgcyArPSBcIi4uLlwiO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBzO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGl0ZW1zWzBdO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmVwbGFjZSBzdHVmZiBpbiB0ZXh0IGh0bWxcclxuICAgKiBAcGFyYW0gcyAgIDogdGhlIHN0cmluZyB0byBwcm9jZXNzXHJcbiAgICogQHJldHVybnMgICA6IHRoZSByZXBsYWNlZCBzdHJpbmcgIFxyXG4gICAqL1xyXG4gIHN0YXRpYyByZXBsYWNlQXNIdG1sKHM6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICBjb25zdCByZWdleCA9IC9odHRwcz86XFwvXFwvLipbXlxcc10vaWdcclxuICAgIGNvbnN0IG0gPSByZWdleC5leGVjKHMpO1xyXG4gICAgaWYgKG0gJiYgbS5sZW5ndGggPiAwKSB7XHJcbiAgICAgIGxldCB2ID0gbnVsbDtcclxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgdiA9IG1baV07XHJcbiAgICAgICAgcyA9IHMucmVwbGFjZSh2LCAnPGEgaHJlZj1cIicgKyB2ICsgJ1wiIHRhcmdldD1cIl9ibGFua1wiPicgKyB2ICsgJzwvYT4nKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHM7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDb21wYXJlIHR3byBuYW1lc1xyXG4gICAqIEBwYXJhbSBhICAgOiBuYW1lIGFcclxuICAgKiBAcGFyYW0gYiAgIDogbmFtZSBiXHJcbiAgICogQHJldHVybnMgICA6IHRydWUgaWYgYSBlcXVhbHMgYlxyXG4gICAqL1xyXG4gIHN0YXRpYyBjb21wYXJlTmFtZXMoYTogc3RyaW5nLCBiOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgIGlmIChhKSBhID0gYS50cmltKCk7XHJcbiAgICBpZiAoYikgYiA9IGIudHJpbSgpO1xyXG4gICAgaWYgKGEgJiYgYiAmJiBhLmxlbmd0aCAhPT0gYi5sZW5ndGgpIHJldHVybiBmYWxzZTtcclxuICAgIGlmICh0aGlzLmNvbXBhcmVTdHJpbmcoYSwgYikgPT09IDApIHJldHVybiB0cnVlO1xyXG4gICAgY29uc3QgcDEgPSBhLnNwbGl0KFwiIFwiKTtcclxuICAgIGNvbnN0IHAyID0gYi5zcGxpdChcIiBcIik7XHJcbiAgICBpZiAocDEubGVuZ3RoICE9PSBwMi5sZW5ndGgpIHJldHVybiBmYWxzZTtcclxuICAgIGxldCBtYXRjaGVzID0gcDEubGVuZ3RoO1xyXG4gICAgZm9yIChjb25zdCBzMSBvZiBwMSkge1xyXG4gICAgICBmb3IgKGNvbnN0IHMyIG9mIHAyKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuY29tcGFyZVN0cmluZyhzMSwgczIpID09PSAwKSB7XHJcbiAgICAgICAgICBtYXRjaGVzLS07XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gbWF0Y2hlcyA9PT0gMDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENpcGhlciBhIHRleHRcclxuICAgKiBAcGFyYW0gdGV4dCAgICA6IHRoZSB0ZXh0XHJcbiAgICogQHBhcmFtIGtleSAgICAgOiB0aGUga2V5XHJcbiAgICogQHBhcmFtIHJldmVyc2UgOiB0cnVlIHRvIGRlY29kZSwgZmFsc2UgdG8gZW5jb2RlXHJcbiAgICogQHJldHVybnMgICAgICAgOnRoZSBjaXBoZXJlZCB0ZXh0XHJcbiAgICovXHJcbiAgc3RhdGljIGNpcGhlcih0ZXh0OiBzdHJpbmcsIGtleTogc3RyaW5nLCByZXZlcnNlOiBib29sZWFuID0gZmFsc2UpOiBzdHJpbmcge1xyXG4gICAgLy8gU3Vycm9nYXRlIHBhaXIgbGltaXRcclxuICAgIHZhciBib3VuZCA9IDB4MTAwMDA7XHJcblxyXG4gICAgLy8gQ3JlYXRlIHN0cmluZyBmcm9tIGNoYXJhY3RlciBjb2Rlc1xyXG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoXHJcbiAgICAgIG51bGwsXHJcbiAgICAgIC8vIFR1cm4gc3RyaW5nIHRvIGNoYXJhY3RlciBjb2Rlc1xyXG4gICAgICB0ZXh0LnNwbGl0KFwiXCIpLm1hcChmdW5jdGlvbiAodjogYW55LCBpOiBudW1iZXIpIHtcclxuICAgICAgICAvLyBHZXQgcm90YXRpb24gZnJvbSBrZXlcclxuICAgICAgICB2YXIgcm90YXRpb24gPSBrZXkuY2hhckNvZGVBdChpICUga2V5Lmxlbmd0aCk7XHJcblxyXG4gICAgICAgIC8vIEFyZSB3ZSBkZWNyeXB0aW5nP1xyXG4gICAgICAgIGlmIChyZXZlcnNlKSByb3RhdGlvbiA9IC1yb3RhdGlvbjtcclxuXHJcbiAgICAgICAgLy8gUmV0dXJuIGN1cnJlbnQgY2hhcmFjdGVyIGNvZGUgKyByb3RhdGlvblxyXG4gICAgICAgIHJldHVybiAodi5jaGFyQ29kZUF0KCkgKyByb3RhdGlvbiArIGJvdW5kKSAlIGJvdW5kO1xyXG4gICAgICB9KVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENsb25lIGFuIG9iamVjdCB1c2luZyBKU09OXHJcbiAgICogQHBhcmFtIG9iaiA6IHRoZSBvYmxlY3QgdG8gY2xvbmVcclxuICAgKiBAcmV0dXJucyAgIDogYSBuZXcgb2JqZWN0XHJcbiAgICovXHJcbiAgc3RhdGljIGNsb25lKG9iajogYW55KTogYW55IHtcclxuICAgIGlmICghb2JqKSByZXR1cm4gbnVsbDtcclxuICAgIHJldHVybiBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KG9iaikpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2xvbmUgYW4gb2JqZWN0IHVzaW5nIGRlZXAgY2xvbmluZ1xyXG4gICAqIEBwYXJhbSBvYmogICA6IHRoZSBvYmxlY3QgdG8gY2xvbmVcclxuICAgKiBAcmV0dXJucyAgICAgOiBhIG5ldyBvYmplY3RcclxuICAgKi9cclxuICBzdGF0aWMgZGVlcENsb25lPFQ+KG9iajogYW55LCBkZXN0OiBUID0gbnVsbCk6IFQge1xyXG4gICAgY29uc3QgY2xvbmVPYmogPSBkZXN0ID8gZGVzdCA6IChvYmouY29uc3RydWN0b3IoKSBhcyBhbnkpO1xyXG4gICAgY29uc3QgYXR0cmlidXRlcyA9IE9iamVjdC5rZXlzKG9iaik7XHJcbiAgICBmb3IgKGNvbnN0IGF0dHJpYnV0ZSBvZiBhdHRyaWJ1dGVzKSB7XHJcbiAgICAgIGNvbnN0IHByb3BlcnR5ID0gb2JqW2F0dHJpYnV0ZV07XHJcbiAgICAgIGlmICh0eXBlb2YgcHJvcGVydHkgPT09IFwib2JqZWN0XCIgJiYgcHJvcGVydHkgIT0gbnVsbCkge1xyXG4gICAgICAgIGNsb25lT2JqW2F0dHJpYnV0ZV0gPSB0aGlzLmRlZXBDbG9uZShwcm9wZXJ0eSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgY2xvbmVPYmpbYXR0cmlidXRlXSA9IHByb3BlcnR5O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gY2xvbmVPYmo7XHJcbiAgfVxyXG5cclxuXHJcbiAgLyoqXHJcbiAgICogQ2hlY2sgaWYgYSBzdHJpbmcgaXMgYSB2YWxpZCBVVUlEXHJcbiAgICogQHBhcmFtIHZhbHVlICAgOiB0aGUgdmFsdWUgdG8gcGFyc2VcclxuICAgKiBAcmV0dXJucyAgICAgICA6IHRydWUgaWYgaXMgYSB2YWxpZCBVVUlEXHJcbiAgICovXHJcbiAgc3RhdGljIHBhcnNlVVVJRCh2YWx1ZTogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICBjb25zdCByZWdleCA9IC9eKHt8KCk/WzAtOWEtZkEtRl17OH0tKFswLTlhLWZBLUZdezR9LSl7M31bMC05YS1mQS1GXXsxMn0ofXwpKT8kLztcclxuICAgIHJldHVybiByZWdleC50ZXN0KHZhbHVlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFBhcnNlIGFuZCBlbnN1cmUgdGhhdCBVVUlEIGlzIG5vdCBlbXB0eVxyXG4gICAqIEBwYXJhbSB2YWx1ZSAgIDogdGhlIHZhbHVlIHRvIHBhcnNlXHJcbiAgICogQHJldHVybnMgICAgICAgOiB0cnVlIGlmIHZhbGlkIGFuZCBub3QgZW1wdHlcclxuICAgKi9cclxuICBzdGF0aWMgcGFyc2VVVUlETm90RW1wdHkodmFsdWU6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgY29uc3QgcmVnZXggPSAvXih7fCgpPzB7OH0tKDB7NH0tKXszfTB7MTJ9KH18KSk/JC87XHJcbiAgICByZXR1cm4gdGhpcy5wYXJzZVVVSUQodmFsdWUpICYmICFyZWdleC50ZXN0KHZhbHVlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybiBhbiBlbXB0eSBVVUlEXHJcbiAgICogQHJldHVybnMgOiB0aGUgZW1wdHkgVVVJRFxyXG4gICAqL1xyXG4gIHN0YXRpYyBlbXB0eVVVSUQoKTogc3RyaW5nIHsgcmV0dXJuIFwiMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAwXCIgfTtcclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlIGEgbmV3IFVVSURcclxuICAgKiBAcmV0dXJucyA6IHRoZSBzdHJpbmcgVVVJRFxyXG4gICAqL1xyXG4gIHN0YXRpYyBnZW5lcmF0ZVVVSUQoKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IHJlZ2V4ID0gL1t4eV0vZztcclxuICAgIHJldHVybiBcInh4eHh4eHh4LXh4eHgtNHh4eC15eHh4LXh4eHh4eHh4eHh4eFwiLnJlcGxhY2UocmVnZXgsIGZ1bmN0aW9uIChjKSB7XHJcbiAgICAgIHZhciByID0gKE1hdGgucmFuZG9tKCkgKiAxNikgfCAwLFxyXG4gICAgICAgIHYgPSBjID09PSBcInhcIiA/IHIgOiAociAmIDB4MykgfCAweDg7XHJcbiAgICAgIHJldHVybiB2LnRvU3RyaW5nKDE2KTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUGFyc2UgYSB0ZXh0IGFuZCByZXR1cm4gdHJ1ZSBpZiBpcyBhIHZhbGlkIGVtYWlsIG9yIG51bGxcclxuICAgKiBAcGFyYW0gdmFsdWUgOiBlbWFpbFxyXG4gICAqIEByZXR1cm5zICAgICA6IHRydWUgaWYgdGhlIGVtYWlsIGlzIHZhbGlkIG9yIGVtcHR5XHJcbiAgICovXHJcbiAgc3RhdGljIHBhcnNlRW1haWwodmFsdWU6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKCF2YWx1ZSkgcmV0dXJuIHRydWU7XHJcbiAgICBjb25zdCByZWdleCA9IC8oPzpbYS16MC05KyEjJCUmJyorXFwvPT9eX2B7fH1+LV0rKD86XFwuW2EtejAtOSEjJCUmJyorXFwvPT9eX2B7fH1+LV0rKSp8XCIoPzpbXFx4MDEtXFx4MDhcXHgwYlxceDBjXFx4MGUtXFx4MWZcXHgyMVxceDIzLVxceDViXFx4NWQtXFx4N2ZdfFxcXFxbXFx4MDEtXFx4MDlcXHgwYlxceDBjXFx4MGUtXFx4N2ZdKSpcIilAKD86KD86W2EtejAtOV0oPzpbYS16MC05LV0qW2EtejAtOV0pP1xcLikrW2EtejAtOV0oPzpbYS16MC05LV0qW2EtejAtOV0pP3xcXFsoPzooPzoyNVswLTVdfDJbMC00XVswLTldfFswMV0/WzAtOV1bMC05XT8pXFwuKXszfSg/OjI1WzAtNV18MlswLTRdWzAtOV18WzAxXT9bMC05XVswLTldP3xbYS16MC05LV0qW2EtejAtOV06KD86W1xceDAxLVxceDA4XFx4MGJcXHgwY1xceDBlLVxceDFmXFx4MjEtXFx4NWFcXHg1My1cXHg3Zl18XFxcXFtcXHgwMS1cXHgwOVxceDBiXFx4MGNcXHgwZS1cXHg3Zl0pKylcXF0pL2dpXHJcbiAgICByZXR1cm4gcmVnZXgudGVzdCh2YWx1ZS50cmltKCkudG9Mb3dlckNhc2UoKSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBQYXJzZSBhIHRleHQgYW5kIHJldHVybiB0cnVlIGlmIGlzIGEgdmFsaWQgdXJsIG9yIG51bGxcclxuICAgKiBAcGFyYW0gdmFsdWUgOiB0aGUgdXJsIHRvIHBhcnNlXHJcbiAgICogQHJldHVybnMgICAgIDogdHJ1ZSBpZiB0aGUgdXJsIGlzIHZhbGlkIG9yIGVtcHR5XHJcbiAgICovXHJcbiAgc3RhdGljIHBhcnNlVXJsKHZhbHVlOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgIGlmICghdmFsdWUpIHJldHVybiB0cnVlO1xyXG4gICAgY29uc3QgcmVnZXggPSBuZXcgUmVnRXhwKFxyXG4gICAgICBcIihodHRwcz86Ly8pPyhbXFxcXGRhLXouLV0rKVxcXFwuKFthLXouXXsyLDZ9KVsvXFxcXHcgLi1dKi8/XCJcclxuICAgICk7XHJcbiAgICByZXR1cm4gcmVnZXgudGVzdCh2YWx1ZS50cmltKCkudG9Mb3dlckNhc2UoKSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgZGF0ZSBwYXJ0cyBmcm9tIGEgc3RyaW5nIHZhbHVlXHJcbiAgICogQHBhcmFtIHZhbHVlICAgOiB0aGUgc3RyaW5nIHRvIHBhcnNlXHJcbiAgICogQHJldHVybnMgICAgICAgOiBhbiBhcnJheSBvZiBudW1iZXJzIHdpdGggeWVhciwgbW9udGgsIGRheVxyXG4gICAqL1xyXG4gIHN0YXRpYyBnZXREYXRlUGFydHModmFsdWU6IHN0cmluZyk6IG51bWJlcltdIHtcclxuICAgIGlmICghdmFsdWUpIHJldHVybiBudWxsO1xyXG4gICAgbGV0IHBhcnRzOiBudW1iZXJbXSA9IFtdO1xyXG4gICAgaWYgKHZhbHVlLmluZGV4T2YoXCItXCIpICE9PSAtMSkge1xyXG4gICAgICBjb25zdCBwID0gdmFsdWUuc3BsaXQoXCItXCIpO1xyXG4gICAgICBpZiAocC5sZW5ndGggIT09IDMpIHJldHVybiBudWxsO1xyXG4gICAgICBwYXJ0cyA9IFtwYXJzZUludChwWzBdKSwgcGFyc2VJbnQocFsxXSkgLSAxLCBwYXJzZUludChwWzJdKV07XHJcbiAgICB9IGVsc2UgaWYgKHZhbHVlLmluZGV4T2YoXCIvXCIpICE9PSAtMSkge1xyXG4gICAgICBjb25zdCBwID0gdmFsdWUuc3BsaXQoXCIvXCIpO1xyXG4gICAgICBpZiAocC5sZW5ndGggIT09IDMpIHJldHVybiBudWxsO1xyXG4gICAgICBwYXJ0cyA9IFtwYXJzZUludChwWzJdKSwgcGFyc2VJbnQocFsxXSkgLSAxLCBwYXJzZUludChwWzBdKV07XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcGFydHM7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBQYXJzZSBhIGRhdGVcclxuICAgKiBAcGFyYW0gdmFsdWUgICA6IHRoZSB2YWx1ZSB0byBjaGVja1xyXG4gICAqIEBwYXJhbSBsb2NhbGUgIDogdGhlIGxvY2FsZSB0byB1c2VcclxuICAgKiBAcmV0dXJucyAgICAgICA6IGEgdmFsaWQgRGF0ZSBvYmplY3Qgb3IgbnVsbFxyXG4gICAqL1xyXG4gIHN0YXRpYyBwYXJzZURhdGUodmFsdWU6IHN0cmluZyB8IERhdGUsIGxvY2FsZTogYW55ID0gaXQpOiBEYXRlIHtcclxuICAgIC8vIE5vIHZhbHVlIGF0IGFsbFxyXG4gICAgaWYgKCF2YWx1ZSkgcmV0dXJuIG51bGw7XHJcbiAgICAvLyBBIERhdGUgdmFsdWVcclxuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUgJiYgdmFsdWUuZ2V0VGltZSgpKSByZXR1cm4gdmFsdWU7XHJcbiAgICAvLyBQYXJzZSBrbm93biBmb3JtYXRzIHVzaW5nIGRhdGUtZm5zXHJcbiAgICBsZXQgZCA9IHBhcnNlSVNPKHZhbHVlIGFzIHN0cmluZyk7XHJcbiAgICBpZiAoZCAmJiBkLmdldFRpbWUoKSAmJiBkLmdldEZ1bGxZZWFyKCkgPiAxNzUwKSByZXR1cm4gZDtcclxuICAgIGQgPSBwYXJzZSh2YWx1ZSBhcyBzdHJpbmcsICdkZC9NTS95eXl5JywgbmV3IERhdGUoKSwgeyBsb2NhbGU6IGxvY2FsZSB9KTtcclxuICAgIGlmIChkICYmIGQuZ2V0VGltZSgpICYmIGQuZ2V0RnVsbFllYXIoKSA+IDE3NTApIHJldHVybiBkO1xyXG4gICAgZCA9IHBhcnNlKHZhbHVlIGFzIHN0cmluZywgJ3l5eXktTU0tZGQnLCBuZXcgRGF0ZSgpLCB7IGxvY2FsZTogbG9jYWxlIH0pO1xyXG4gICAgaWYgKGQgJiYgZC5nZXRUaW1lKCkgJiYgZC5nZXRGdWxsWWVhcigpID4gMTc1MCkgcmV0dXJuIGQ7XHJcbiAgICAvLyBQYXJzZSB2YWx1ZXMgbWFudWFsbHlcclxuICAgIGxldCBwYXJ0cyA9IHRoaXMuZ2V0RGF0ZVBhcnRzKHZhbHVlIGFzIHN0cmluZyk7XHJcbiAgICBpZiAocGFydHNbMF0gPCAxMDApIHBhcnRzWzBdICs9IDIwMDA7XHJcbiAgICBpZiAoaXNOYU4ocGFydHNbMF0pIHx8IHBhcnRzWzBdIDwgMCB8fCBwYXJ0c1swXSA8IDE3NTApIHJldHVybiBudWxsO1xyXG4gICAgaWYgKGlzTmFOKHBhcnRzWzFdKSB8fCBwYXJ0c1sxXSA8IDApIHJldHVybiBudWxsO1xyXG4gICAgaWYgKGlzTmFOKHBhcnRzWzJdKSB8fCBwYXJ0c1syXSA8IDApIHJldHVybiBudWxsO1xyXG4gICAgaWYgKHBhcnRzWzFdID4gMTEpIHJldHVybiBudWxsO1xyXG4gICAgaWYgKHBhcnRzWzFdID09PSAxICYmIHBhcnRzWzJdID4gMjkpIHJldHVybiBudWxsO1xyXG4gICAgZWxzZSBpZiAocGFydHNbMV0gIT09IDEgJiYgcGFydHNbMl0gPiAzMSkgcmV0dXJuIG51bGw7XHJcbiAgICByZXR1cm4gbmV3IERhdGUocGFydHNbMF0sIHBhcnRzWzFdLCBwYXJ0c1syXSwgMik7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBGb3JtYXQgYSBkYXRlXHJcbiAgICogQHBhcmFtIHZhbHVlICAgICA6IHRoZSBkYXRlIG9yIHN0cmluZyB0byBmb3JtYXRcclxuICAgKiBAcGFyYW0gZm10ICAgICAgIDogdGhlIERhdGVGb3JtYXQgdG8gdXNlIG9yIHRoZSBzdHJpbmcgcGF0dGVyblxyXG4gICAqIEBwYXJhbSBsb2NhbGUgICAgOiB0aGUgbG9jYWxlIHRvIHVzZSAoZGVmYXVsdCBpcyBJVClcclxuICAgKiBAcmV0dXJucyAgICAgICAgIDogdGhlIGZvcm1hdHRlZCBzdHJpbmdcclxuICAgKi9cclxuICBzdGF0aWMgZm9ybWF0RGF0ZShcclxuICAgIHZhbHVlOiBEYXRlIHwgc3RyaW5nLFxyXG4gICAgZm10OiBEYXRlRm9ybWF0IHwgc3RyaW5nID0gRGF0ZUZvcm1hdC5TaG9ydCxcclxuICAgIGxvY2FsZTogYW55ID0gaXQpOiBzdHJpbmcge1xyXG4gICAgLy8gTm8gdmFsdWUgYXQgYWxsXHJcbiAgICBpZiAoIXZhbHVlKSByZXR1cm4gbnVsbDtcclxuICAgIC8vIEEgc3RyaW5nXHJcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyB8fCB2YWx1ZSBpbnN0YW5jZW9mIFN0cmluZylcclxuICAgICAgdmFsdWUgPSB0aGlzLnBhcnNlRGF0ZSh2YWx1ZSBhcyBzdHJpbmcpO1xyXG4gICAgLy8gTm90IGEgZGF0ZSBcclxuICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgRGF0ZSAmJiB2YWx1ZS5nZXRUaW1lKCkpKVxyXG4gICAgICByZXR1cm4gbnVsbDtcclxuICAgIC8vIEZvcm1hdFxyXG4gICAgc3dpdGNoIChmbXQpIHtcclxuICAgICAgY2FzZSBEYXRlRm9ybWF0LlNob3J0OiByZXR1cm4gZm9ybWF0KHZhbHVlLCBcImRkL01NL3l5eXlcIiwgeyBsb2NhbGU6IGxvY2FsZSB9KTtcclxuICAgICAgY2FzZSBEYXRlRm9ybWF0Lkxvbmc6IHJldHVybiBmb3JtYXQodmFsdWUsIFwiZCBNTU1NIHl5eXlcIiwgeyBsb2NhbGU6IGxvY2FsZSB9KTtcclxuICAgICAgY2FzZSBEYXRlRm9ybWF0LkxvbmdXaXRoU2hvcnRNb250aDogcmV0dXJuIGZvcm1hdCh2YWx1ZSwgXCJkIE1NTSB5eXl5XCIsIHsgbG9jYWxlOiBsb2NhbGUgfSk7XHJcbiAgICAgIGNhc2UgRGF0ZUZvcm1hdC5Mb25nV2l0aFdlZWtEYXk6IHJldHVybiBmb3JtYXQodmFsdWUsIFwiRUVFRSwgZCBNTU1NIHl5eXlcIiwgeyBsb2NhbGU6IGxvY2FsZSB9KTtcclxuICAgICAgY2FzZSBEYXRlRm9ybWF0LkxvbmdXaXRoU2hvcnRXZWVrRGF5OiByZXR1cm4gZm9ybWF0KHZhbHVlLCBcIkVFRSwgZCBNTU1NIHl5eXlcIiwgeyBsb2NhbGU6IGxvY2FsZSB9KTtcclxuICAgICAgY2FzZSBEYXRlRm9ybWF0Lk1vbnRoQW5kWWVhcjogcmV0dXJuIGZvcm1hdCh2YWx1ZSwgXCJNTU0geXl5eVwiLCB7IGxvY2FsZTogbG9jYWxlIH0pO1xyXG4gICAgICBjYXNlIERhdGVGb3JtYXQuTG9uZ01vbnRoQW5kWWVhcjogcmV0dXJuIGZvcm1hdCh2YWx1ZSwgXCJNTU1NIHl5eXlcIiwgeyBsb2NhbGU6IGxvY2FsZSB9KTtcclxuICAgICAgY2FzZSBEYXRlRm9ybWF0LldlZWtEYXk6IHJldHVybiBmb3JtYXQodmFsdWUsIFwiRUVFLCBkXCIsIHsgbG9jYWxlOiBsb2NhbGUgfSk7XHJcbiAgICAgIGNhc2UgRGF0ZUZvcm1hdC5Mb25nV2Vla0RheTogcmV0dXJuIGZvcm1hdCh2YWx1ZSwgXCJFRUVFLCBkXCIsIHsgbG9jYWxlOiBsb2NhbGUgfSk7XHJcbiAgICAgIGNhc2UgRGF0ZUZvcm1hdC5EYXlBbmRNb250aDogcmV0dXJuIGZvcm1hdCh2YWx1ZSwgXCJkIE1NTU1cIiwgeyBsb2NhbGU6IGxvY2FsZSB9KTtcclxuICAgICAgY2FzZSBEYXRlRm9ybWF0LlNob3J0VVM6IHJldHVybiBmb3JtYXQodmFsdWUsIFwiTU0vZGQveXl5eVwiLCB7IGxvY2FsZTogbG9jYWxlIH0pO1xyXG4gICAgICBjYXNlIERhdGVGb3JtYXQuU2hvcnRJU084NjAxOiByZXR1cm4gZm9ybWF0KHZhbHVlLCBcInl5eXktTU0tZGRcIiwgeyBsb2NhbGU6IGxvY2FsZSB9KTtcclxuICAgICAgZGVmYXVsdDpcclxuICAgICAgICByZXR1cm4gZm9ybWF0KHZhbHVlLCBmbXQsIHsgbG9jYWxlOiBsb2NhbGUgfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXR1cm4gYW4gaXRhbGlhbiBsb2NhbCBkYXRlXHJcbiAgICogQHBhcmFtIHZhbHVlICA6IHRoZSBkYXRlXHJcbiAgICogQHJldHVybnMgICAgIDogdGhlIG5ldyBkYXRlXHJcbiAgICovXHJcbiAgc3RhdGljIHRvTG9jYWxEYXRlKHZhbHVlOiBEYXRlIHwgc3RyaW5nKTogRGF0ZSB7XHJcbiAgICAvLyBObyB2YWx1ZSBhdCBhbGxcclxuICAgIGlmICghdmFsdWUpIHJldHVybiBudWxsO1xyXG4gICAgLy8gQSBzdHJpbmdcclxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnIHx8IHZhbHVlIGluc3RhbmNlb2YgU3RyaW5nKVxyXG4gICAgICB2YWx1ZSA9IHRoaXMucGFyc2VEYXRlKHZhbHVlIGFzIHN0cmluZyk7XHJcbiAgICAvLyBOb3QgYSBkYXRlXHJcbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIERhdGUgJiYgdmFsdWUuZ2V0VGltZSgpKSkgcmV0dXJuIG51bGw7XHJcbiAgICAvLyBVcGRhdGUgZGF0ZVxyXG4gICAgcmV0dXJuIHNldEhvdXJzKHZhbHVlLCAyKTtcclxuXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBVcGRhdGUgYSBEYXRlSW50ZXJ2YWwgb2JqZWN0IGFjY29yZGluZyB0byBhIHN0cmluZ1xyXG4gICAqIEBwYXJhbSB2YWx1ZSAgICAgICA6IHN0cmluZyB2YWx1ZVxyXG4gICAqIEBwYXJhbSBpbnRlcnZhbCAgICA6IERhdGVJbnRlcnZhbCB2YWx1ZSB0byB1cGRhdGVcclxuICAgKiBAcGFyYW0gZW5kICAgICAgICAgOiB0cnVlIGlmIG11c3QgYmUgdXBkYXRlZCB0aGUgZmlyc3Qgb3IgdGhlIGVuZCB2YWx1ZSBcclxuICAgKiBAcGFyYW0gY29weSAgICAgICAgOiBjb3B5IHRoZSBzYW1lIHZhbHVlICh3b3JrcyBvbmx5IGlmIG5vdCBlbmQgZWxlbWVudClcclxuICAgKi9cclxuICBzdGF0aWMgY2hhbmdlRGF0ZUludGVydmFsKHZhbHVlOiBzdHJpbmcsIGludGVydmFsOiBEYXRlSW50ZXJ2YWwsIGVuZDogYm9vbGVhbiA9IGZhbHNlLCBjb3B5OiBib29sZWFuID0gZmFsc2UpIHtcclxuICAgIGlmICh2YWx1ZSkge1xyXG4gICAgICBsZXQgeWVhciA9IC0xO1xyXG4gICAgICBpZiAodmFsdWUubGVuZ3RoID09PSA0ICYmICh5ZWFyID0gcGFyc2VJbnQodmFsdWUpKSA+IDE3NTApIHtcclxuICAgICAgICBpZiAoIWVuZCkge1xyXG4gICAgICAgICAgaW50ZXJ2YWwuZnJvbSA9IGZyb21ab25lZFRpbWUobmV3IERhdGUoeWVhciwgMCwgMSksICdVVEMnKTtcclxuICAgICAgICAgIGludGVydmFsLnRvID0gZnJvbVpvbmVkVGltZShuZXcgRGF0ZSh5ZWFyLCAxMSwgMzEpLCAnVVRDJyk7XHJcbiAgICAgICAgfSBlbHNlXHJcbiAgICAgICAgICBpbnRlcnZhbC50byA9IG5ldyBEYXRlKHllYXIsIDExLCAzMSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgbGV0IHBhcnRzID0gdGhpcy5nZXREYXRlUGFydHModmFsdWUpO1xyXG4gICAgICAgIGlmICghcGFydHMgfHwgaXNOYU4ocGFydHNbMF0pIHx8IHBhcnRzWzBdIDwgMCB8fCBwYXJ0c1swXSA8IDE3NTApIHJldHVybjtcclxuICAgICAgICBjb25zdCBkID0gZnJvbVpvbmVkVGltZShuZXcgRGF0ZShwYXJ0c1swXSwgcGFydHNbMV0sIHBhcnRzWzJdKSwgJ1VUQycpO1xyXG4gICAgICAgIGlmIChlbmQpXHJcbiAgICAgICAgICBpbnRlcnZhbC50byA9IGQ7XHJcbiAgICAgICAgZWxzZSBpZiAoY29weSkge1xyXG4gICAgICAgICAgaW50ZXJ2YWwuZnJvbSA9IGQ7XHJcbiAgICAgICAgICBpbnRlcnZhbC50byA9IGQ7XHJcbiAgICAgICAgfSBlbHNlXHJcbiAgICAgICAgICBpbnRlcnZhbC5mcm9tID0gZDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRW5jb2RlIHVybFxyXG4gICAqIEBwYXJhbSB2YWx1ZSA6IHRoZSB2YWx1ZSB0byBlbmNvZGVcclxuICAgKiBAcmV0dXJucyAgICAgOiB0aGUgdXJsIGVuY29kZWQgc3RyaW5nXHJcbiAgICovXHJcbiAgc3RhdGljIHVybEVuY29kZSh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIHJldHVybiBlbmNvZGVVUklDb21wb25lbnQodmFsdWUpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRGVjb2RlIHVybFxyXG4gICAqIEBwYXJhbSB2YWx1ZSA6IHRoZSB1cmwgdG8gZGVjb2RlXHJcbiAgICogQHJldHVybnMgICAgIDogdGhlIGRlY29kZSB1cmwgc3RyaW5nXHJcbiAgICovXHJcbiAgc3RhdGljIHVybERlY29kZSh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IHJlZ2V4ID0gL1xcKy9nO1xyXG4gICAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudCgodmFsdWUgKyBcIlwiKS5yZXBsYWNlKHJlZ2V4LCBcIiUyMFwiKSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgYSBxdWVyeXN0cmluZyBwYXJhbWV0ZXIgdmFsdWVcclxuICAgKiBAcGFyYW0gbmFtZSAgOiB0aGUgcGFyYW1ldGVyIG5hbWVcclxuICAgKiBAcmV0dXJucyAgICAgOiB0aGUgc3RyaW5nIHZhbHVlXHJcbiAgICovXHJcbiAgc3RhdGljIGdldFF1ZXJ5U3RyaW5nVmFsdWVCeU5hbWUobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIGlmICghdGhpcy5pc0Jyb3dzZXIoKSkgcmV0dXJuIG51bGw7XHJcbiAgICBjb25zdCB1cmwgPSB3aW5kb3cubG9jYXRpb24uaHJlZjtcclxuICAgIGlmICh1cmwuaW5jbHVkZXMoXCI/XCIpKSB7XHJcbiAgICAgIGNvbnN0IGh0dHBQYXJhbXMgPSBuZXcgSHR0cFBhcmFtcyh7IGZyb21TdHJpbmc6IHVybC5zcGxpdChcIj9cIilbMV0gfSk7XHJcbiAgICAgIGNvbnN0IHYgPSBkZWNvZGVVUklDb21wb25lbnQoaHR0cFBhcmFtcy5nZXQobmFtZSkpO1xyXG4gICAgICBpZiAodiAhPT0gXCJudWxsXCIpIHJldHVybiB2O1xyXG4gICAgICBlbHNlIHJldHVybiBudWxsO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZW5lcmF0ZSBhIHBhc3N3b3JkXHJcbiAgICogQHJldHVybnMgOiB0aGUgcGFzc3dvcmQgc3RyaW5nXHJcbiAgICovXHJcbiAgc3RhdGljIGdlbmVyYXRlUGFzc3dvcmQoKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IHJhbmRvbSA9IFwiJFwiICsgTWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc2xpY2UoLTcpO1xyXG4gICAgbGV0IHBhc3N3b3JkID0gXCJcIjtcclxuICAgIGxldCBoYXNVcHBlckNhc2UgPSBmYWxzZTtcclxuICAgIGZvciAoY29uc3Qgcm5kIG9mIHJhbmRvbSkge1xyXG4gICAgICBpZiAoIWhhc1VwcGVyQ2FzZSAmJiBcImFiY2RlZmdoamlsbW5vcHFyc3R1dnl3eHpcIi5pbmNsdWRlcyhybmQpKSB7XHJcbiAgICAgICAgcGFzc3dvcmQgKz0gcm5kLnRvVXBwZXJDYXNlKCk7XHJcbiAgICAgICAgaGFzVXBwZXJDYXNlID0gdHJ1ZTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBwYXNzd29yZCArPSBybmQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGlmICghaGFzVXBwZXJDYXNlKVxyXG4gICAgICBwYXNzd29yZCA9IHBhc3N3b3JkLnN1YnN0cmluZygwLCA3KSArIFwiTVwiO1xyXG4gICAgcmV0dXJuIHBhc3N3b3JkO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2hlY2sgaWYgY3VycmVudCBicm93c2VyIHN1cHBvcnRzIHRvdWNoXHJcbiAgICogQHJldHVybnMgOiB0cnVlIGlmIHRoZSBkaXNwbGF5IGlzIHRvdWNoYWJsZVxyXG4gICAqL1xyXG4gIHN0YXRpYyBpc1RvdWNoYWJsZSgpOiBib29sZWFuIHtcclxuICAgIHJldHVybiAoXHJcbiAgICAgIHRoaXMuaXNCcm93c2VyKCkgJiYgKFxyXG4gICAgICAgIFwib250b3VjaHN0YXJ0XCIgaW4gd2luZG93IHx8XHJcbiAgICAgICAgbmF2aWdhdG9yLm1heFRvdWNoUG9pbnRzID4gMClcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUaGlzIGNoZWNrIHdpbGwgcHJldmVudCAnd2luZG93JyBsb2dpYyB0byBiZSBleGVjdXRlZFxyXG4gICAqIHdoaWxlIGV4ZWN1dGluZyB0aGUgc2VydmVyIHJlbmRlcmluZ1xyXG4gICAqIEByZXR1cm5zIDogdHJ1ZSBpZiB1c2luZyB0aGUgYnJvd3NlclxyXG4gICAqL1xyXG4gIHN0YXRpYyBpc0Jyb3dzZXIoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdHlwZW9mICh3aW5kb3cpICE9PSAndW5kZWZpbmVkJztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gKiBDb252ZXJ0IGZvbGRlcnMgaW4gYSB0cmVlIG9mIE5vZGUgb2JqZWN0LlxyXG4gKiBAcGFyYW0gZm9sZGVycyA6IHRoZSBzdWJmb2xkZXJzIGdyb3VwIG9yIG51bGwgdG8gcm9vdFxyXG4gKiBAcmV0dXJucyAgICAgICA6IGEgbm9kZSBsaXN0XHJcbiAqL1xyXG4gIHN0YXRpYyB0b05vZGVzKGZvbGRlcnM6IElOb2RlW10pOiBJTm9kZVtdIHtcclxuICAgIHJldHVybiB0aGlzLl90b05vZGVzKGZvbGRlcnMsIHVuZGVmaW5lZCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDb252ZXJ0IGZvbGRlcnMgaW4gYSB0cmVlIG9mIE5vZGUgb2JqZWN0LlxyXG4gICAqIEBwYXJhbSBmb2xkZXJzIDogdGhlIGNoaWxkcmVuIGdyb3VwIG9yIG51bGwgdG8gcm9vdFxyXG4gICAqIEBwYXJhbSBwYXJlbnQgIDogdGhlIHBhcmVudCBub2RlXHJcbiAgICogQHJldHVybnMgICAgICAgOiBhIG5vZGUgbGlzdCBcclxuICAgKi9cclxuICBwcml2YXRlIHN0YXRpYyBfdG9Ob2Rlcyhmb2xkZXJzOiBJTm9kZVtdLCBwYXJlbnQ6IElOb2RlIHwgdW5kZWZpbmVkKTogSU5vZGVbXSB7XHJcbiAgICBjb25zdCBub2RlczogSU5vZGVbXSA9IFtdO1xyXG4gICAgZm9sZGVycy5mb3JFYWNoKChuOiBJTm9kZSkgPT4ge1xyXG4gICAgICBjb25zdCBub2RlOiBJTm9kZSA9IHtcclxuICAgICAgICBpZDogbi5pZCxcclxuICAgICAgICBuYW1lOiBuLm5hbWUsXHJcbiAgICAgICAgY291bnQ6IG4uY291bnQsXHJcbiAgICAgICAgcGFyZW50OiBwYXJlbnQsXHJcbiAgICAgICAgY2hpbGRyZW46IHVuZGVmaW5lZCxcclxuICAgICAgICBiYWc6IG4sXHJcbiAgICAgIH07XHJcbiAgICAgIG5vZGUuY2hpbGRyZW4gPVxyXG4gICAgICAgIG4uY2hpbGRyZW4gJiYgbi5jaGlsZHJlbi5sZW5ndGggPiAwXHJcbiAgICAgICAgICA/IHRoaXMuX3RvTm9kZXMobi5jaGlsZHJlbiwgbm9kZSlcclxuICAgICAgICAgIDogW107XHJcbiAgICAgIG5vZGVzLnB1c2gobm9kZSk7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBub2RlcztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gKiBSZXR1cm4gdGhlIGZsYWdzIGFycmF5IHRvIGJlIHVzZWQgaW4gc2VsZWN0aW9uc1xyXG4gKiBAcGFyYW0gdmFsdWUgOiB0aGUgbmV3IHZhbHVlXHJcbiAqIEBwYXJhbSBtYXg6IHRoZSBtYXggbnVtYmVyIG9mIGZsYWdzXHJcbiAqL1xyXG4gIHN0YXRpYyBnZXRGbGFncyh2YWx1ZTogbnVtYmVyLCBtYXg6IG51bWJlciA9IDMwKTogbnVtYmVyW10ge1xyXG4gICAgaWYgKHZhbHVlKSB7XHJcbiAgICAgIGxldCBpdGVtczogbnVtYmVyW10gPSBbXTtcclxuICAgICAgbGV0IHYgPSAxO1xyXG4gICAgICBsZXQgbSA9IDEgPDwgbWF4O1xyXG4gICAgICB3aGlsZSAodiA8IG0pIHtcclxuICAgICAgICBpZiAoKHZhbHVlICYgdikgPT09IHYpIGl0ZW1zLnB1c2godik7XHJcbiAgICAgICAgdiA9IHYgPDwgMTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gaXRlbXM7XHJcbiAgICB9IGVsc2UgcmV0dXJuIFtdO1xyXG4gIH1cclxufVxyXG4iXX0=
|