Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/wp-rocket/assets/js/rocket-insights.js
Keine Baseline-Datei – Diff nur gegen leer.
1
-
1
+
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
2
+
"use strict";
3
+
4
+
/**
5
+
* Rocket Insights functionality for post listing pages
6
+
* This script handles performance score display and updates in admin post listing pages
7
+
*
8
+
* @since 3.20.1
9
+
*/
10
+
11
+
// Export for use with browserify/babelify in gulp
12
+
module.exports = function () {
13
+
'use strict';
14
+
15
+
/**
16
+
* Polling interval for checking ongoing tests (in milliseconds).
17
+
*/
18
+
const POLLING_INTERVAL = 5000; // 5 seconds
19
+
20
+
/**
21
+
* Active polling intervals by post ID.
22
+
*/
23
+
const activePolls = {};
24
+
25
+
/**
26
+
* Initialize Rocket Insights on post listing pages
27
+
*/
28
+
function init() {
29
+
// Attach event listeners.
30
+
attachTestPageListeners();
31
+
attachRetestListeners();
32
+
33
+
// Start polling for any rows that are already running.
34
+
startPollingForRunningTests();
35
+
}
36
+
37
+
/**
38
+
* Attach click listeners to "Test the page" buttons.
39
+
*/
40
+
function attachTestPageListeners() {
41
+
jQuery(document).on('click', '.wpr-ri-test-page', function (e) {
42
+
e.preventDefault();
43
+
const button = jQuery(this);
44
+
const url = button.data('url');
45
+
const column = button.closest('.wpr-ri-column');
46
+
const canAddPages = column.attr('data-can-add-pages') === '1';
47
+
if (!canAddPages) {
48
+
showLimitMessage(column, button);
49
+
return;
50
+
}
51
+
addNewPage(url, column, button);
52
+
});
53
+
}
54
+
55
+
/**
56
+
* Attach click listeners to "Re-test" buttons and links.
57
+
*/
58
+
function attachRetestListeners() {
59
+
// Support both button and link styles with one handler.
60
+
jQuery(document).on('click', '.wpr-ri-retest:not(.wpr-ri-action--disabled), .wpr-ri-retest-link', function (e) {
61
+
e.preventDefault();
62
+
const el = jQuery(this);
63
+
const url = el.data('url');
64
+
const column = el.closest('.wpr-ri-column');
65
+
const rowId = column.data('rocket-insights-id');
66
+
if (!rowId) {
67
+
return;
68
+
}
69
+
70
+
// Retest should only proceed when the user has credit for the test.
71
+
const hasCredit = column.attr('data-has-credit') === '1';
72
+
if (!hasCredit) {
73
+
showLimitMessage(column, el);
74
+
return;
75
+
}
76
+
retestPage(rowId, url, column);
77
+
});
78
+
}
79
+
80
+
/**
81
+
* Start polling for rows that are currently running tests.
82
+
*/
83
+
function startPollingForRunningTests() {
84
+
jQuery('.wpr-ri-loading').each(function () {
85
+
const column = jQuery(this).closest('.wpr-ri-column');
86
+
const rowId = column.data('rocket-insights-id');
87
+
const url = column.data('url');
88
+
if (rowId && !activePolls[rowId]) {
89
+
startPolling(rowId, url, column);
90
+
}
91
+
});
92
+
}
93
+
94
+
/**
95
+
* Add a new page for testing.
96
+
*
97
+
* @param {string} url The URL to test.
98
+
* @param {jQuery} column The column element.
99
+
* @param {jQuery} button The button that was clicked.
100
+
*/
101
+
function addNewPage(url, column, button) {
102
+
// Disable button and show loading state immediately.
103
+
button.prop('disabled', true);
104
+
105
+
// Show loading spinner immediately before API call
106
+
showLoadingState(column, null);
107
+
108
+
// Use REST (HEAD) but keep develop's robust handling.
109
+
window.wp.apiFetch({
110
+
path: '/wp-rocket/v1/rocket-insights/pages/',
111
+
method: 'POST',
112
+
data: {
113
+
page_url: url
114
+
}
115
+
}).then(response => {
116
+
const success = response?.success === true;
117
+
const id = response?.id ?? response?.data?.id ?? null;
118
+
const canAdd = response?.can_add_pages ?? response?.data?.can_add_pages;
119
+
const message = response?.message ?? response?.data?.message;
120
+
if (success && id) {
121
+
// Update column with the row ID and start polling
122
+
column.attr('data-rocket-insights-id', id);
123
+
startPolling(id, url, column);
124
+
125
+
// Check if we've reached the limit and disable all other "Test the page" buttons.
126
+
if (canAdd === false || response?.data?.remaining_urls === 0) {
127
+
disableAllTestPageButtons();
128
+
}
129
+
return;
130
+
}
131
+
132
+
// If backend says we cannot add pages or other errors, restore original state
133
+
// Reload the column HTML from server to restore the button
134
+
reloadColumnFromServer(column, url);
135
+
}).catch(error => {
136
+
// wp.apiFetch throws on WP_Error; reload column to restore button
137
+
console.error(error);
138
+
reloadColumnFromServer(column, url);
139
+
});
140
+
}
141
+
142
+
/**
143
+
* Retest an existing page.
144
+
*
145
+
* @param {number} rowId The database row ID.
146
+
* @param {string} url The URL being tested.
147
+
* @param {jQuery} column The column element.
148
+
*/
149
+
function retestPage(rowId, url, column) {
150
+
// Show loading spinner immediately before API call
151
+
showLoadingState(column, rowId);
152
+
window.wp.apiFetch({
153
+
path: '/wp-rocket/v1/rocket-insights/pages/' + rowId,
154
+
method: 'PATCH'
155
+
}).then(response => {
156
+
if (response.success) {
157
+
// Start polling for results
158
+
startPolling(rowId, url, column);
159
+
} else {
160
+
// If not successful, reload the column to restore previous state
161
+
reloadColumnFromServer(column, url);
162
+
}
163
+
}).catch(error => {
164
+
console.error(error);
165
+
// Reload the column to restore previous state
166
+
reloadColumnFromServer(column, url);
167
+
});
168
+
}
169
+
170
+
/**
171
+
* Start polling for test results.
172
+
*
173
+
* @param {number} rowId The database row ID.
174
+
* @param {string} url The URL being tested.
175
+
* @param {jQuery} column The column element.
176
+
*/
177
+
function startPolling(rowId, url, column) {
178
+
// Clear any existing poll for this row.
179
+
if (activePolls[rowId]) {
180
+
clearInterval(activePolls[rowId]);
181
+
}
182
+
183
+
// Set up new polling interval.
184
+
activePolls[rowId] = setInterval(function () {
185
+
checkStatus(rowId, url, column);
186
+
}, POLLING_INTERVAL);
187
+
188
+
// Also check immediately.
189
+
checkStatus(rowId, url, column);
190
+
}
191
+
192
+
/**
193
+
* Show the per-row limit message (only in the clicked row).
194
+
* Disables the clicked element momentarily while showing the message.
195
+
*
196
+
* @param {jQuery} column The column element.
197
+
* @param {jQuery} clickedEl The element that triggered the action.
198
+
*/
199
+
function showLimitMessage(column, clickedEl) {
200
+
const messageHtml = column.find('.wpr-ri-limit-html').html() || window.rocket_insights_i18n?.limit_reached || '';
201
+
const messageDiv = column.find('.wpr-ri-message');
202
+
messageDiv.html(messageHtml).show();
203
+
204
+
// Disable only the clicked element briefly to prevent spam clicks, then re-enable.
205
+
if (clickedEl && clickedEl.prop) {
206
+
clickedEl.prop('disabled', true);
207
+
setTimeout(function () {
208
+
clickedEl.prop('disabled', false);
209
+
}, 3000);
210
+
}
211
+
}
212
+
213
+
/**
214
+
* Check the status of a test.
215
+
*
216
+
* @param {number} rowId The database row ID.
217
+
* @param {string} url The URL being tested.
218
+
* @param {jQuery} column The column element.
219
+
*/
220
+
function checkStatus(rowId, url, column) {
221
+
window.wp.apiFetch({
222
+
path: window.wp.url.addQueryArgs('/wp-rocket/v1/rocket-insights/pages/progress', {
223
+
ids: [rowId]
224
+
})
225
+
}).then(response => {
226
+
if (response.success && Array.isArray(response.results)) {
227
+
const result = response.results[0];
228
+
if (result.status === 'completed' || result.status === 'failed') {
229
+
// Stop polling.
230
+
clearInterval(activePolls[rowId]);
231
+
delete activePolls[rowId];
232
+
233
+
// Update the column with results (reload rendered HTML from server).
234
+
updateColumnWithResults(column, result);
235
+
}
236
+
}
237
+
});
238
+
}
239
+
240
+
/**
241
+
* Show loading state in the column.
242
+
*
243
+
* @param {jQuery} column The column element.
244
+
* @param {number} rowId The database row ID (can be null when initially showing loading).
245
+
*/
246
+
function showLoadingState(column, rowId) {
247
+
if (rowId) {
248
+
column.attr('data-rocket-insights-id', rowId);
249
+
}
250
+
251
+
// Create elements safely to prevent XSS
252
+
const loadingDiv = jQuery('<div>').addClass('wpr-ri-loading wpr-btn-with-tool-tip');
253
+
const img = jQuery('<img>').addClass('wpr-loading-img').attr({
254
+
src: window.rocket_insights_i18n?.loading_img || '',
255
+
alt: 'Loading...'
256
+
});
257
+
const messageDiv = jQuery('<div>').addClass('wpr-ri-message').css('display', 'none');
258
+
loadingDiv.append(img);
259
+
loadingDiv.append(`<div class="wpr-tooltip"><div class="wpr-tooltip-content">${window.rocket_insights_i18n?.estimated_time_text || 'Analyzing your page (~1 min).'}</div></div>`);
260
+
column.empty().append(loadingDiv).append(messageDiv);
261
+
}
262
+
263
+
/**
264
+
* Reload column HTML from server.
265
+
*
266
+
* @param {jQuery} column The column element.
267
+
* @param {string} url The URL for the column.
268
+
*/
269
+
function reloadColumnFromServer(column, url) {
270
+
const postId = column.data('post-id');
271
+
window.wp.apiFetch({
272
+
path: window.wp.url.addQueryArgs('/wp-rocket/v1/rocket-insights/pages', {
273
+
url: url,
274
+
post_id: postId
275
+
})
276
+
}).then(response => {
277
+
if (response.success && response.html) {
278
+
column.replaceWith(response.html);
279
+
280
+
// Re-attach listeners to the new content.
281
+
attachTestPageListeners();
282
+
attachRetestListeners();
283
+
}
284
+
}).catch(error => {
285
+
console.error('Failed to reload column:', error);
286
+
});
287
+
}
288
+
289
+
/**
290
+
* Update column with test results.
291
+
*
292
+
* @param {jQuery} column The column element.
293
+
* @param {Object} result The test result data.
294
+
*/
295
+
function updateColumnWithResults(column, result) {
296
+
// Reload the entire row from the server to get properly rendered HTML.
297
+
const url = column.data('url');
298
+
reloadColumnFromServer(column, url);
299
+
}
300
+
301
+
/**
302
+
* Mark all remaining "Test the page" buttons as having reached the limit.
303
+
* Updates data attributes so future clicks will show the limit message per-row.
304
+
* Does NOT display any message immediately on all rows.
305
+
*/
306
+
function disableAllTestPageButtons() {
307
+
jQuery('.wpr-ri-test-page').each(function () {
308
+
const button = jQuery(this);
309
+
const column = button.closest('.wpr-ri-column');
310
+
311
+
// Update the data attribute so future clicks will trigger the limit message.
312
+
column.attr('data-can-add-pages', '0');
313
+
});
314
+
}
315
+
316
+
// Auto-initialize on DOM ready
317
+
if (document.readyState === 'loading') {
318
+
document.addEventListener('DOMContentLoaded', init);
319
+
} else {
320
+
init();
321
+
}
322
+
return {
323
+
init: init
324
+
};
325
+
}();
326
+
327
+
},{}]},{},[1])
328
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJzcmMvanMvZ2xvYmFsL3JvY2tldC1pbnNpZ2h0cy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsTUFBTSxDQUFDLE9BQU8sR0FBSSxZQUFZO0VBQzdCLFlBQVk7O0VBRVo7QUFDRDtBQUNBO0VBQ0MsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsQ0FBQzs7RUFFL0I7QUFDRDtBQUNBO0VBQ0MsTUFBTSxXQUFXLEdBQUcsQ0FBQyxDQUFDOztFQUV0QjtBQUNEO0FBQ0E7RUFDQyxTQUFTLElBQUksQ0FBQSxFQUFHO0lBQ2Y7SUFDQSx1QkFBdUIsQ0FBQyxDQUFDO0lBQ3pCLHFCQUFxQixDQUFDLENBQUM7O0lBRXZCO0lBQ0EsMkJBQTJCLENBQUMsQ0FBQztFQUM5Qjs7RUFFQTtBQUNEO0FBQ0E7RUFDQyxTQUFTLHVCQUF1QixDQUFBLEVBQUc7SUFDbEMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsVUFBVSxDQUFDLEVBQUU7TUFDOUQsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDO01BQ2xCLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUM7TUFDM0IsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7TUFDOUIsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQztNQUUvQyxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLEtBQUssR0FBRztNQUU3RCxJQUFLLENBQUUsV0FBVyxFQUFHO1FBQ3BCLGdCQUFnQixDQUFFLE1BQU0sRUFBRSxNQUFPLENBQUM7UUFDbEM7TUFDRDtNQUVBLFVBQVUsQ0FBQyxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUNoQyxDQUFDLENBQUM7RUFDSDs7RUFFQTtBQUNEO0FBQ0E7RUFDQyxTQUFTLHFCQUFxQixDQUFBLEVBQUc7SUFDaEM7SUFDQSxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxtRUFBbUUsRUFBRSxVQUFVLENBQUMsRUFBRTtNQUM5RyxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUM7TUFDbEIsTUFBTSxFQUFFLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQztNQUN2QixNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztNQUMxQixNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDO01BQzNDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUM7TUFFL0MsSUFBSSxDQUFDLEtBQUssRUFBRTtRQUNYO01BQ0Q7O01BRUE7TUFDQSxNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssR0FBRztNQUV4RCxJQUFLLENBQUUsU0FBUyxFQUFHO1FBQ2xCLGdCQUFnQixDQUFFLE1BQU0sRUFBRSxFQUFHLENBQUM7UUFDOUI7TUFDRDtNQUVBLFVBQVUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQztJQUMvQixDQUFDLENBQUM7RUFDSDs7RUFFQTtBQUNEO0FBQ0E7RUFDQyxTQUFTLDJCQUEyQixDQUFBLEVBQUc7SUFDdEMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVk7TUFDMUMsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQztNQUNyRCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDO01BQy9DLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO01BRTlCLElBQUksS0FBSyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxFQUFFO1FBQ2pDLFlBQVksQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQztNQUNqQztJQUNELENBQUMsQ0FBQztFQUNIOztFQUVBO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0MsU0FBUyxVQUFVLENBQUMsR0FBRyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUU7SUFDeEM7SUFDQSxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUM7O0lBRTdCO0lBQ0EsZ0JBQWdCLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQzs7SUFFOUI7SUFDQSxNQUFNLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQztNQUNsQixJQUFJLEVBQUUsc0NBQXNDO01BQzVDLE1BQU0sRUFBRSxNQUFNO01BQ2QsSUFBSSxFQUFFO1FBQUUsUUFBUSxFQUFFO01BQUk7SUFDdkIsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFFLFFBQVEsSUFBSztNQUNyQixNQUFNLE9BQU8sR0FBRyxRQUFRLEVBQUUsT0FBTyxLQUFLLElBQUk7TUFDMUMsTUFBTSxFQUFFLEdBQUcsUUFBUSxFQUFFLEVBQUUsSUFBSSxRQUFRLEVBQUUsSUFBSSxFQUFFLEVBQUUsSUFBSSxJQUFJO01BQ3JELE1BQU0sTUFBTSxHQUFJLFFBQVEsRUFBRSxhQUFhLElBQUksUUFBUSxFQUFFLElBQUksRUFBRSxhQUFjO01BQ3pFLE1BQU0sT0FBTyxHQUFHLFFBQVEsRUFBRSxPQUFPLElBQUksUUFBUSxFQUFFLElBQUksRUFBRSxPQUFPO01BRTVELElBQUksT0FBTyxJQUFJLEVBQUUsRUFBRTtRQUNsQjtRQUNBLE1BQU0sQ0FBQyxJQUFJLENBQUMseUJBQXlCLEVBQUUsRUFBRSxDQUFDO1FBQzFDLFlBQVksQ0FBQyxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQzs7UUFFN0I7UUFDQSxJQUFJLE1BQU0sS0FBSyxLQUFLLElBQUksUUFBUSxFQUFFLElBQUksRUFBRSxjQUFjLEtBQUssQ0FBQyxFQUFFO1VBQzdELHlCQUF5QixDQUFDLENBQUM7UUFDNUI7UUFDQTtNQUNEOztNQUVBO01BQ0E7TUFDQSxzQkFBc0IsQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDO0lBQ3BDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBRSxLQUFLLElBQUs7TUFDbkI7TUFDQSxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQztNQUNwQixzQkFBc0IsQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDO0lBQ3BDLENBQUMsQ0FBQztFQUNIOztFQUVBO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0MsU0FBUyxVQUFVLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUU7SUFDdkM7SUFDQSxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDO0lBRS9CLE1BQU0sQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUNqQjtNQUNDLElBQUksRUFBRSxzQ0FBc0MsR0FBRyxLQUFLO01BQ3BELE1BQU0sRUFBRTtJQUNULENBQ0QsQ0FBQyxDQUFDLElBQUksQ0FBRSxRQUFRLElBQUs7TUFDcEIsSUFBSSxRQUFRLENBQUMsT0FBTyxFQUFFO1FBQ3JCO1FBQ0EsWUFBWSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFDO01BQ2pDLENBQUMsTUFBTTtRQUNOO1FBQ0Esc0JBQXNCLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQztNQUNwQztJQUNELENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBRSxLQUFLLElBQUs7TUFDbkIsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUM7TUFDcEI7TUFDQSxzQkFBc0IsQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDO0lBQ3BDLENBQUUsQ0FBQztFQUNKOztFQUVBO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0MsU0FBUyxZQUFZLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUU7SUFDekM7SUFDQSxJQUFJLFdBQVcsQ0FBQyxLQUFLLENBQUMsRUFBRTtNQUN2QixhQUFhLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2xDOztJQUVBO0lBQ0EsV0FBVyxDQUFDLEtBQUssQ0FBQyxHQUFHLFdBQVcsQ0FBQyxZQUFZO01BQzVDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQztJQUNoQyxDQUFDLEVBQUUsZ0JBQWdCLENBQUM7O0lBRXBCO0lBQ0EsV0FBVyxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFDO0VBQ2hDOztFQUVBO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0MsU0FBUyxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUUsU0FBUyxFQUFFO0lBQzVDLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxvQkFBb0IsRUFBRSxhQUFhLElBQUksRUFBRTtJQUVoSCxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDO0lBQ2pELFVBQVUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7O0lBRW5DO0lBQ0EsSUFBSSxTQUFTLElBQUksU0FBUyxDQUFDLElBQUksRUFBRTtNQUNoQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUM7TUFDaEMsVUFBVSxDQUFDLFlBQVc7UUFDckIsU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsS0FBSyxDQUFDO01BQ2xDLENBQUMsRUFBRSxJQUFJLENBQUM7SUFDVDtFQUNEOztFQUVBO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0MsU0FBUyxXQUFXLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUU7SUFDeEMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQ2pCO01BQ0MsSUFBSSxFQUFFLE1BQU0sQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyw4Q0FBOEMsRUFBRTtRQUFFLEdBQUcsRUFBRSxDQUFDLEtBQUs7TUFBRSxDQUFDO0lBQ2xHLENBQ0QsQ0FBQyxDQUFDLElBQUksQ0FBRSxRQUFRLElBQUs7TUFDcEIsSUFBSSxRQUFRLENBQUMsT0FBTyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ3hELE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBRWxDLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxXQUFXLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxRQUFRLEVBQUU7VUFDaEU7VUFDQSxhQUFhLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO1VBQ2pDLE9BQU8sV0FBVyxDQUFDLEtBQUssQ0FBQzs7VUFFekI7VUFDQSx1QkFBdUIsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDO1FBQ3hDO01BQ0Q7SUFDRCxDQUFDLENBQUM7RUFDSDs7RUFFQTtBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDQyxTQUFTLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUU7SUFDeEMsSUFBSSxLQUFLLEVBQUU7TUFDVixNQUFNLENBQUMsSUFBSSxDQUFDLHlCQUF5QixFQUFFLEtBQUssQ0FBQztJQUM5Qzs7SUFFQTtJQUNBLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxRQUFRLENBQUMsc0NBQXNDLENBQUM7SUFDbkYsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLElBQUksQ0FBQztNQUM1RCxHQUFHLEVBQUUsTUFBTSxDQUFDLG9CQUFvQixFQUFFLFdBQVcsSUFBSSxFQUFFO01BQ25ELEdBQUcsRUFBRTtJQUNOLENBQUMsQ0FBQztJQUNGLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQztJQUVwRixVQUFVLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQztJQUN0QixVQUFVLENBQUMsTUFBTSxDQUFDLDZEQUE2RCxNQUFNLENBQUMsb0JBQW9CLEVBQUUsbUJBQW1CLElBQUksK0JBQStCLGNBQWMsQ0FBQztJQUNqTCxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQztFQUNyRDs7RUFFQTtBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDQyxTQUFTLHNCQUFzQixDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUU7SUFDNUMsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7SUFDckMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQ2pCO01BQ0MsSUFBSSxFQUFFLE1BQU0sQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxxQ0FBcUMsRUFBRTtRQUFFLEdBQUcsRUFBRSxHQUFHO1FBQUUsT0FBTyxFQUFFO01BQU8sQ0FBQztJQUN0RyxDQUNELENBQUMsQ0FBQyxJQUFJLENBQUUsUUFBUSxJQUFLO01BQ3BCLElBQUksUUFBUSxDQUFDLE9BQU8sSUFBSSxRQUFRLENBQUMsSUFBSSxFQUFFO1FBQ3RDLE1BQU0sQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQzs7UUFFakM7UUFDQSx1QkFBdUIsQ0FBQyxDQUFDO1FBQ3pCLHFCQUFxQixDQUFDLENBQUM7TUFDeEI7SUFDRCxDQUFFLENBQUMsQ0FBQyxLQUFLLENBQUksS0FBSyxJQUFNO01BQ3ZCLE9BQU8sQ0FBQyxLQUFLLENBQUMsMEJBQTBCLEVBQUUsS0FBSyxDQUFDO0lBQ2pELENBQUUsQ0FBQztFQUNKOztFQUVBO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNDLFNBQVMsdUJBQXVCLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRTtJQUNoRDtJQUNBLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQzlCLHNCQUFzQixDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUM7RUFDcEM7O0VBRUE7QUFDRDtBQUNBO0FBQ0E7QUFDQTtFQUNDLFNBQVMseUJBQXlCLENBQUEsRUFBRztJQUNwQyxNQUFNLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBVztNQUMzQyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDO01BQzNCLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUM7O01BRS9DO01BQ0EsTUFBTSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxHQUFHLENBQUM7SUFDdkMsQ0FBQyxDQUFDO0VBQ0g7O0VBRUE7RUFDQSxJQUFJLFFBQVEsQ0FBQyxVQUFVLEtBQUssU0FBUyxFQUFFO0lBQ3RDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsRUFBRSxJQUFJLENBQUM7RUFDcEQsQ0FBQyxNQUFNO0lBQ04sSUFBSSxDQUFDLENBQUM7RUFDUDtFQUVBLE9BQU87SUFDTixJQUFJLEVBQUU7RUFDUCxDQUFDO0FBQ0YsQ0FBQyxDQUFFLENBQUMiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIvKipcbiAqIFJvY2tldCBJbnNpZ2h0cyBmdW5jdGlvbmFsaXR5IGZvciBwb3N0IGxpc3RpbmcgcGFnZXNcbiAqIFRoaXMgc2NyaXB0IGhhbmRsZXMgcGVyZm9ybWFuY2Ugc2NvcmUgZGlzcGxheSBhbmQgdXBkYXRlcyBpbiBhZG1pbiBwb3N0IGxpc3RpbmcgcGFnZXNcbiAqXG4gKiBAc2luY2UgMy4yMC4xXG4gKi9cblxuLy8gRXhwb3J0IGZvciB1c2Ugd2l0aCBicm93c2VyaWZ5L2JhYmVsaWZ5IGluIGd1bHBcbm1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uICgpIHtcblx0J3VzZSBzdHJpY3QnO1xuXG5cdC8qKlxuXHQgKiBQb2xsaW5nIGludGVydmFsIGZvciBjaGVja2luZyBvbmdvaW5nIHRlc3RzIChpbiBtaWxsaXNlY29uZHMpLlxuXHQgKi9cblx0Y29uc3QgUE9MTElOR19JTlRFUlZBTCA9IDUwMDA7IC8vIDUgc2Vjb25kc1xuXG5cdC8qKlxuXHQgKiBBY3RpdmUgcG9sbGluZyBpbnRlcnZhbHMgYnkgcG9zdCBJRC5cblx0ICovXG5cdGNvbnN0IGFjdGl2ZVBvbGxzID0ge307XG5cblx0LyoqXG5cdCAqIEluaXRpYWxpemUgUm9ja2V0IEluc2lnaHRzIG9uIHBvc3QgbGlzdGluZyBwYWdlc1xuXHQgKi9cblx0ZnVuY3Rpb24gaW5pdCgpIHtcblx0XHQvLyBBdHRhY2ggZXZlbnQgbGlzdGVuZXJzLlxuXHRcdGF0dGFjaFRlc3RQYWdlTGlzdGVuZXJzKCk7XG5cdFx0YXR0YWNoUmV0ZXN0TGlzdGVuZXJzKCk7XG5cblx0XHQvLyBTdGFydCBwb2xsaW5nIGZvciBhbnkgcm93cyB0aGF0IGFyZSBhbHJlYWR5IHJ1bm5pbmcuXG5cdFx0c3RhcnRQb2xsaW5nRm9yUnVubmluZ1Rlc3RzKCk7XG5cdH1cblxuXHQvKipcblx0ICogQXR0YWNoIGNsaWNrIGxpc3RlbmVycyB0byBcIlRlc3QgdGhlIHBhZ2VcIiBidXR0b25zLlxuXHQgKi9cblx0ZnVuY3Rpb24gYXR0YWNoVGVzdFBhZ2VMaXN0ZW5lcnMoKSB7XG5cdFx0alF1ZXJ5KGRvY3VtZW50KS5vbignY2xpY2snLCAnLndwci1yaS10ZXN0LXBhZ2UnLCBmdW5jdGlvbiAoZSkge1xuXHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0Y29uc3QgYnV0dG9uID0galF1ZXJ5KHRoaXMpO1xuXHRcdFx0Y29uc3QgdXJsID0gYnV0dG9uLmRhdGEoJ3VybCcpO1xuXHRcdFx0Y29uc3QgY29sdW1uID0gYnV0dG9uLmNsb3Nlc3QoJy53cHItcmktY29sdW1uJyk7XG5cblx0XHRcdGNvbnN0IGNhbkFkZFBhZ2VzID0gY29sdW1uLmF0dHIoJ2RhdGEtY2FuLWFkZC1wYWdlcycpID09PSAnMSc7XG5cblx0XHRcdGlmICggISBjYW5BZGRQYWdlcyApIHtcblx0XHRcdFx0c2hvd0xpbWl0TWVzc2FnZSggY29sdW1uLCBidXR0b24gKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRhZGROZXdQYWdlKHVybCwgY29sdW1uLCBidXR0b24pO1xuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEF0dGFjaCBjbGljayBsaXN0ZW5lcnMgdG8gXCJSZS10ZXN0XCIgYnV0dG9ucyBhbmQgbGlua3MuXG5cdCAqL1xuXHRmdW5jdGlvbiBhdHRhY2hSZXRlc3RMaXN0ZW5lcnMoKSB7XG5cdFx0Ly8gU3VwcG9ydCBib3RoIGJ1dHRvbiBhbmQgbGluayBzdHlsZXMgd2l0aCBvbmUgaGFuZGxlci5cblx0XHRqUXVlcnkoZG9jdW1lbnQpLm9uKCdjbGljaycsICcud3ByLXJpLXJldGVzdDpub3QoLndwci1yaS1hY3Rpb24tLWRpc2FibGVkKSwgLndwci1yaS1yZXRlc3QtbGluaycsIGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRjb25zdCBlbCA9IGpRdWVyeSh0aGlzKTtcblx0XHRcdGNvbnN0IHVybCA9IGVsLmRhdGEoJ3VybCcpO1xuXHRcdFx0Y29uc3QgY29sdW1uID0gZWwuY2xvc2VzdCgnLndwci1yaS1jb2x1bW4nKTtcblx0XHRcdGNvbnN0IHJvd0lkID0gY29sdW1uLmRhdGEoJ3JvY2tldC1pbnNpZ2h0cy1pZCcpO1xuXG5cdFx0XHRpZiAoIXJvd0lkKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gUmV0ZXN0IHNob3VsZCBvbmx5IHByb2NlZWQgd2hlbiB0aGUgdXNlciBoYXMgY3JlZGl0IGZvciB0aGUgdGVzdC5cblx0XHRcdGNvbnN0IGhhc0NyZWRpdCA9IGNvbHVtbi5hdHRyKCdkYXRhLWhhcy1jcmVkaXQnKSA9PT0gJzEnO1xuXG5cdFx0XHRpZiAoICEgaGFzQ3JlZGl0ICkge1xuXHRcdFx0XHRzaG93TGltaXRNZXNzYWdlKCBjb2x1bW4sIGVsICk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0cmV0ZXN0UGFnZShyb3dJZCwgdXJsLCBjb2x1bW4pO1xuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIFN0YXJ0IHBvbGxpbmcgZm9yIHJvd3MgdGhhdCBhcmUgY3VycmVudGx5IHJ1bm5pbmcgdGVzdHMuXG5cdCAqL1xuXHRmdW5jdGlvbiBzdGFydFBvbGxpbmdGb3JSdW5uaW5nVGVzdHMoKSB7XG5cdFx0alF1ZXJ5KCcud3ByLXJpLWxvYWRpbmcnKS5lYWNoKGZ1bmN0aW9uICgpIHtcblx0XHRcdGNvbnN0IGNvbHVtbiA9IGpRdWVyeSh0aGlzKS5jbG9zZXN0KCcud3ByLXJpLWNvbHVtbicpO1xuXHRcdFx0Y29uc3Qgcm93SWQgPSBjb2x1bW4uZGF0YSgncm9ja2V0LWluc2lnaHRzLWlkJyk7XG5cdFx0XHRjb25zdCB1cmwgPSBjb2x1bW4uZGF0YSgndXJsJyk7XG5cblx0XHRcdGlmIChyb3dJZCAmJiAhYWN0aXZlUG9sbHNbcm93SWRdKSB7XG5cdFx0XHRcdHN0YXJ0UG9sbGluZyhyb3dJZCwgdXJsLCBjb2x1bW4pO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZCBhIG5ldyBwYWdlIGZvciB0ZXN0aW5nLlxuXHQgKlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gdXJsICAgIFRoZSBVUkwgdG8gdGVzdC5cblx0ICogQHBhcmFtIHtqUXVlcnl9IGNvbHVtbiBUaGUgY29sdW1uIGVsZW1lbnQuXG5cdCAqIEBwYXJhbSB7alF1ZXJ5fSBidXR0b24gVGhlIGJ1dHRvbiB0aGF0IHdhcyBjbGlja2VkLlxuXHQgKi9cblx0ZnVuY3Rpb24gYWRkTmV3UGFnZSh1cmwsIGNvbHVtbiwgYnV0dG9uKSB7XG5cdFx0Ly8gRGlzYWJsZSBidXR0b24gYW5kIHNob3cgbG9hZGluZyBzdGF0ZSBpbW1lZGlhdGVseS5cblx0XHRidXR0b24ucHJvcCgnZGlzYWJsZWQnLCB0cnVlKTtcblxuXHRcdC8vIFNob3cgbG9hZGluZyBzcGlubmVyIGltbWVkaWF0ZWx5IGJlZm9yZSBBUEkgY2FsbFxuXHRcdHNob3dMb2FkaW5nU3RhdGUoY29sdW1uLCBudWxsKTtcblxuXHRcdC8vIFVzZSBSRVNUIChIRUFEKSBidXQga2VlcCBkZXZlbG9wJ3Mgcm9idXN0IGhhbmRsaW5nLlxuXHRcdHdpbmRvdy53cC5hcGlGZXRjaCh7XG5cdFx0XHRwYXRoOiAnL3dwLXJvY2tldC92MS9yb2NrZXQtaW5zaWdodHMvcGFnZXMvJyxcblx0XHRcdG1ldGhvZDogJ1BPU1QnLFxuXHRcdFx0ZGF0YTogeyBwYWdlX3VybDogdXJsIH0sXG5cdFx0fSkudGhlbigocmVzcG9uc2UpID0+IHtcblx0XHRcdGNvbnN0IHN1Y2Nlc3MgPSByZXNwb25zZT8uc3VjY2VzcyA9PT0gdHJ1ZTtcblx0XHRcdGNvbnN0IGlkID0gcmVzcG9uc2U/LmlkID8/IHJlc3BvbnNlPy5kYXRhPy5pZCA/PyBudWxsO1xuXHRcdFx0Y29uc3QgY2FuQWRkID0gKHJlc3BvbnNlPy5jYW5fYWRkX3BhZ2VzID8/IHJlc3BvbnNlPy5kYXRhPy5jYW5fYWRkX3BhZ2VzKTtcblx0XHRcdGNvbnN0IG1lc3NhZ2UgPSByZXNwb25zZT8ubWVzc2FnZSA/PyByZXNwb25zZT8uZGF0YT8ubWVzc2FnZTtcblxuXHRcdFx0aWYgKHN1Y2Nlc3MgJiYgaWQpIHtcblx0XHRcdFx0Ly8gVXBkYXRlIGNvbHVtbiB3aXRoIHRoZSByb3cgSUQgYW5kIHN0YXJ0IHBvbGxpbmdcblx0XHRcdFx0Y29sdW1uLmF0dHIoJ2RhdGEtcm9ja2V0LWluc2lnaHRzLWlkJywgaWQpO1xuXHRcdFx0XHRzdGFydFBvbGxpbmcoaWQsIHVybCwgY29sdW1uKTtcblxuXHRcdFx0XHQvLyBDaGVjayBpZiB3ZSd2ZSByZWFjaGVkIHRoZSBsaW1pdCBhbmQgZGlzYWJsZSBhbGwgb3RoZXIgXCJUZXN0IHRoZSBwYWdlXCIgYnV0dG9ucy5cblx0XHRcdFx0aWYgKGNhbkFkZCA9PT0gZmFsc2UgfHwgcmVzcG9uc2U/LmRhdGE/LnJlbWFpbmluZ191cmxzID09PSAwKSB7XG5cdFx0XHRcdFx0ZGlzYWJsZUFsbFRlc3RQYWdlQnV0dG9ucygpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gSWYgYmFja2VuZCBzYXlzIHdlIGNhbm5vdCBhZGQgcGFnZXMgb3Igb3RoZXIgZXJyb3JzLCByZXN0b3JlIG9yaWdpbmFsIHN0YXRlXG5cdFx0XHQvLyBSZWxvYWQgdGhlIGNvbHVtbiBIVE1MIGZyb20gc2VydmVyIHRvIHJlc3RvcmUgdGhlIGJ1dHRvblxuXHRcdFx0cmVsb2FkQ29sdW1uRnJvbVNlcnZlcihjb2x1bW4sIHVybCk7XG5cdFx0fSkuY2F0Y2goKGVycm9yKSA9PiB7XG5cdFx0XHQvLyB3cC5hcGlGZXRjaCB0aHJvd3Mgb24gV1BfRXJyb3I7IHJlbG9hZCBjb2x1bW4gdG8gcmVzdG9yZSBidXR0b25cblx0XHRcdGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuXHRcdFx0cmVsb2FkQ29sdW1uRnJvbVNlcnZlcihjb2x1bW4sIHVybCk7XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogUmV0ZXN0IGFuIGV4aXN0aW5nIHBhZ2UuXG5cdCAqXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSByb3dJZCAgVGhlIGRhdGFiYXNlIHJvdyBJRC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHVybCAgICBUaGUgVVJMIGJlaW5nIHRlc3RlZC5cblx0ICogQHBhcmFtIHtqUXVlcnl9IGNvbHVtbiBUaGUgY29sdW1uIGVsZW1lbnQuXG5cdCAqL1xuXHRmdW5jdGlvbiByZXRlc3RQYWdlKHJvd0lkLCB1cmwsIGNvbHVtbikge1xuXHRcdC8vIFNob3cgbG9hZGluZyBzcGlubmVyIGltbWVkaWF0ZWx5IGJlZm9yZSBBUEkgY2FsbFxuXHRcdHNob3dMb2FkaW5nU3RhdGUoY29sdW1uLCByb3dJZCk7XG5cblx0XHR3aW5kb3cud3AuYXBpRmV0Y2goXG5cdFx0XHR7XG5cdFx0XHRcdHBhdGg6ICcvd3Atcm9ja2V0L3YxL3JvY2tldC1pbnNpZ2h0cy9wYWdlcy8nICsgcm93SWQsXG5cdFx0XHRcdG1ldGhvZDogJ1BBVENIJyxcblx0XHRcdH1cblx0XHQpLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG5cdFx0XHRpZiAocmVzcG9uc2Uuc3VjY2Vzcykge1xuXHRcdFx0XHQvLyBTdGFydCBwb2xsaW5nIGZvciByZXN1bHRzXG5cdFx0XHRcdHN0YXJ0UG9sbGluZyhyb3dJZCwgdXJsLCBjb2x1bW4pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Ly8gSWYgbm90IHN1Y2Nlc3NmdWwsIHJlbG9hZCB0aGUgY29sdW1uIHRvIHJlc3RvcmUgcHJldmlvdXMgc3RhdGVcblx0XHRcdFx0cmVsb2FkQ29sdW1uRnJvbVNlcnZlcihjb2x1bW4sIHVybCk7XG5cdFx0XHR9XG5cdFx0fSkuY2F0Y2goKGVycm9yKSA9PiB7XG5cdFx0XHRjb25zb2xlLmVycm9yKGVycm9yKTtcblx0XHRcdC8vIFJlbG9hZCB0aGUgY29sdW1uIHRvIHJlc3RvcmUgcHJldmlvdXMgc3RhdGVcblx0XHRcdHJlbG9hZENvbHVtbkZyb21TZXJ2ZXIoY29sdW1uLCB1cmwpO1xuXHRcdH0gKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTdGFydCBwb2xsaW5nIGZvciB0ZXN0IHJlc3VsdHMuXG5cdCAqXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSByb3dJZCAgVGhlIGRhdGFiYXNlIHJvdyBJRC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHVybCAgICBUaGUgVVJMIGJlaW5nIHRlc3RlZC5cblx0ICogQHBhcmFtIHtqUXVlcnl9IGNvbHVtbiBUaGUgY29sdW1uIGVsZW1lbnQuXG5cdCAqL1xuXHRmdW5jdGlvbiBzdGFydFBvbGxpbmcocm93SWQsIHVybCwgY29sdW1uKSB7XG5cdFx0Ly8gQ2xlYXIgYW55IGV4aXN0aW5nIHBvbGwgZm9yIHRoaXMgcm93LlxuXHRcdGlmIChhY3RpdmVQb2xsc1tyb3dJZF0pIHtcblx0XHRcdGNsZWFySW50ZXJ2YWwoYWN0aXZlUG9sbHNbcm93SWRdKTtcblx0XHR9XG5cblx0XHQvLyBTZXQgdXAgbmV3IHBvbGxpbmcgaW50ZXJ2YWwuXG5cdFx0YWN0aXZlUG9sbHNbcm93SWRdID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24gKCkge1xuXHRcdFx0Y2hlY2tTdGF0dXMocm93SWQsIHVybCwgY29sdW1uKTtcblx0XHR9LCBQT0xMSU5HX0lOVEVSVkFMKTtcblxuXHRcdC8vIEFsc28gY2hlY2sgaW1tZWRpYXRlbHkuXG5cdFx0Y2hlY2tTdGF0dXMocm93SWQsIHVybCwgY29sdW1uKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTaG93IHRoZSBwZXItcm93IGxpbWl0IG1lc3NhZ2UgKG9ubHkgaW4gdGhlIGNsaWNrZWQgcm93KS5cblx0ICogRGlzYWJsZXMgdGhlIGNsaWNrZWQgZWxlbWVudCBtb21lbnRhcmlseSB3aGlsZSBzaG93aW5nIHRoZSBtZXNzYWdlLlxuXHQgKlxuXHQgKiBAcGFyYW0ge2pRdWVyeX0gY29sdW1uIFRoZSBjb2x1bW4gZWxlbWVudC5cblx0ICogQHBhcmFtIHtqUXVlcnl9IGNsaWNrZWRFbCBUaGUgZWxlbWVudCB0aGF0IHRyaWdnZXJlZCB0aGUgYWN0aW9uLlxuXHQgKi9cblx0ZnVuY3Rpb24gc2hvd0xpbWl0TWVzc2FnZShjb2x1bW4sIGNsaWNrZWRFbCkge1xuXHRcdGNvbnN0IG1lc3NhZ2VIdG1sID0gY29sdW1uLmZpbmQoJy53cHItcmktbGltaXQtaHRtbCcpLmh0bWwoKSB8fCB3aW5kb3cucm9ja2V0X2luc2lnaHRzX2kxOG4/LmxpbWl0X3JlYWNoZWQgfHwgJyc7XG5cblx0XHRjb25zdCBtZXNzYWdlRGl2ID0gY29sdW1uLmZpbmQoJy53cHItcmktbWVzc2FnZScpO1xuXHRcdG1lc3NhZ2VEaXYuaHRtbChtZXNzYWdlSHRtbCkuc2hvdygpO1xuXG5cdFx0Ly8gRGlzYWJsZSBvbmx5IHRoZSBjbGlja2VkIGVsZW1lbnQgYnJpZWZseSB0byBwcmV2ZW50IHNwYW0gY2xpY2tzLCB0aGVuIHJlLWVuYWJsZS5cblx0XHRpZiAoY2xpY2tlZEVsICYmIGNsaWNrZWRFbC5wcm9wKSB7XG5cdFx0XHRjbGlja2VkRWwucHJvcCgnZGlzYWJsZWQnLCB0cnVlKTtcblx0XHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGNsaWNrZWRFbC5wcm9wKCdkaXNhYmxlZCcsIGZhbHNlKTtcblx0XHRcdH0sIDMwMDApO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVjayB0aGUgc3RhdHVzIG9mIGEgdGVzdC5cblx0ICpcblx0ICogQHBhcmFtIHtudW1iZXJ9IHJvd0lkICBUaGUgZGF0YWJhc2Ugcm93IElELlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gdXJsICAgIFRoZSBVUkwgYmVpbmcgdGVzdGVkLlxuXHQgKiBAcGFyYW0ge2pRdWVyeX0gY29sdW1uIFRoZSBjb2x1bW4gZWxlbWVudC5cblx0ICovXG5cdGZ1bmN0aW9uIGNoZWNrU3RhdHVzKHJvd0lkLCB1cmwsIGNvbHVtbikge1xuXHRcdHdpbmRvdy53cC5hcGlGZXRjaChcblx0XHRcdHtcblx0XHRcdFx0cGF0aDogd2luZG93LndwLnVybC5hZGRRdWVyeUFyZ3MoJy93cC1yb2NrZXQvdjEvcm9ja2V0LWluc2lnaHRzL3BhZ2VzL3Byb2dyZXNzJywgeyBpZHM6IFtyb3dJZF0gfSksXG5cdFx0XHR9XG5cdFx0KS50aGVuKChyZXNwb25zZSkgPT4ge1xuXHRcdFx0aWYgKHJlc3BvbnNlLnN1Y2Nlc3MgJiYgQXJyYXkuaXNBcnJheShyZXNwb25zZS5yZXN1bHRzKSkge1xuXHRcdFx0XHRjb25zdCByZXN1bHQgPSByZXNwb25zZS5yZXN1bHRzWzBdO1xuXG5cdFx0XHRcdGlmIChyZXN1bHQuc3RhdHVzID09PSAnY29tcGxldGVkJyB8fCByZXN1bHQuc3RhdHVzID09PSAnZmFpbGVkJykge1xuXHRcdFx0XHRcdC8vIFN0b3AgcG9sbGluZy5cblx0XHRcdFx0XHRjbGVhckludGVydmFsKGFjdGl2ZVBvbGxzW3Jvd0lkXSk7XG5cdFx0XHRcdFx0ZGVsZXRlIGFjdGl2ZVBvbGxzW3Jvd0lkXTtcblxuXHRcdFx0XHRcdC8vIFVwZGF0ZSB0aGUgY29sdW1uIHdpdGggcmVzdWx0cyAocmVsb2FkIHJlbmRlcmVkIEhUTUwgZnJvbSBzZXJ2ZXIpLlxuXHRcdFx0XHRcdHVwZGF0ZUNvbHVtbldpdGhSZXN1bHRzKGNvbHVtbiwgcmVzdWx0KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNob3cgbG9hZGluZyBzdGF0ZSBpbiB0aGUgY29sdW1uLlxuXHQgKlxuXHQgKiBAcGFyYW0ge2pRdWVyeX0gY29sdW1uIFRoZSBjb2x1bW4gZWxlbWVudC5cblx0ICogQHBhcmFtIHtudW1iZXJ9IHJvd0lkICBUaGUgZGF0YWJhc2Ugcm93IElEIChjYW4gYmUgbnVsbCB3aGVuIGluaXRpYWxseSBzaG93aW5nIGxvYWRpbmcpLlxuXHQgKi9cblx0ZnVuY3Rpb24gc2hvd0xvYWRpbmdTdGF0ZShjb2x1bW4sIHJvd0lkKSB7XG5cdFx0aWYgKHJvd0lkKSB7XG5cdFx0XHRjb2x1bW4uYXR0cignZGF0YS1yb2NrZXQtaW5zaWdodHMtaWQnLCByb3dJZCk7XG5cdFx0fVxuXG5cdFx0Ly8gQ3JlYXRlIGVsZW1lbnRzIHNhZmVseSB0byBwcmV2ZW50IFhTU1xuXHRcdGNvbnN0IGxvYWRpbmdEaXYgPSBqUXVlcnkoJzxkaXY+JykuYWRkQ2xhc3MoJ3dwci1yaS1sb2FkaW5nIHdwci1idG4td2l0aC10b29sLXRpcCcpO1xuXHRcdGNvbnN0IGltZyA9IGpRdWVyeSgnPGltZz4nKS5hZGRDbGFzcygnd3ByLWxvYWRpbmctaW1nJykuYXR0cih7XG5cdFx0XHRzcmM6IHdpbmRvdy5yb2NrZXRfaW5zaWdodHNfaTE4bj8ubG9hZGluZ19pbWcgfHwgJycsXG5cdFx0XHRhbHQ6ICdMb2FkaW5nLi4uJ1xuXHRcdH0pO1xuXHRcdGNvbnN0IG1lc3NhZ2VEaXYgPSBqUXVlcnkoJzxkaXY+JykuYWRkQ2xhc3MoJ3dwci1yaS1tZXNzYWdlJykuY3NzKCdkaXNwbGF5JywgJ25vbmUnKTtcblxuXHRcdGxvYWRpbmdEaXYuYXBwZW5kKGltZyk7XG5cdFx0bG9hZGluZ0Rpdi5hcHBlbmQoYDxkaXYgY2xhc3M9XCJ3cHItdG9vbHRpcFwiPjxkaXYgY2xhc3M9XCJ3cHItdG9vbHRpcC1jb250ZW50XCI+JHt3aW5kb3cucm9ja2V0X2luc2lnaHRzX2kxOG4/LmVzdGltYXRlZF90aW1lX3RleHQgfHwgJ0FuYWx5emluZyB5b3VyIHBhZ2UgKH4xIG1pbikuJ308L2Rpdj48L2Rpdj5gKVxuXHRcdGNvbHVtbi5lbXB0eSgpLmFwcGVuZChsb2FkaW5nRGl2KS5hcHBlbmQobWVzc2FnZURpdik7XG5cdH1cblxuXHQvKipcblx0ICogUmVsb2FkIGNvbHVtbiBIVE1MIGZyb20gc2VydmVyLlxuXHQgKlxuXHQgKiBAcGFyYW0ge2pRdWVyeX0gY29sdW1uIFRoZSBjb2x1bW4gZWxlbWVudC5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHVybCAgICBUaGUgVVJMIGZvciB0aGUgY29sdW1uLlxuXHQgKi9cblx0ZnVuY3Rpb24gcmVsb2FkQ29sdW1uRnJvbVNlcnZlcihjb2x1bW4sIHVybCkge1xuXHRcdGNvbnN0IHBvc3RJZCA9IGNvbHVtbi5kYXRhKCdwb3N0LWlkJyk7XG5cdFx0d2luZG93LndwLmFwaUZldGNoKFxuXHRcdFx0e1xuXHRcdFx0XHRwYXRoOiB3aW5kb3cud3AudXJsLmFkZFF1ZXJ5QXJncygnL3dwLXJvY2tldC92MS9yb2NrZXQtaW5zaWdodHMvcGFnZXMnLCB7IHVybDogdXJsLCBwb3N0X2lkOiBwb3N0SWQgfSksXG5cdFx0XHR9XG5cdFx0KS50aGVuKChyZXNwb25zZSkgPT4ge1xuXHRcdFx0aWYgKHJlc3BvbnNlLnN1Y2Nlc3MgJiYgcmVzcG9uc2UuaHRtbCkge1xuXHRcdFx0XHRjb2x1bW4ucmVwbGFjZVdpdGgocmVzcG9uc2UuaHRtbCk7XG5cblx0XHRcdFx0Ly8gUmUtYXR0YWNoIGxpc3RlbmVycyB0byB0aGUgbmV3IGNvbnRlbnQuXG5cdFx0XHRcdGF0dGFjaFRlc3RQYWdlTGlzdGVuZXJzKCk7XG5cdFx0XHRcdGF0dGFjaFJldGVzdExpc3RlbmVycygpO1xuXHRcdFx0fVxuXHRcdH0gKS5jYXRjaCggKCBlcnJvciApID0+IHtcblx0XHRcdGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCB0byByZWxvYWQgY29sdW1uOicsIGVycm9yKTtcblx0XHR9ICk7XG5cdH1cblxuXHQvKipcblx0ICogVXBkYXRlIGNvbHVtbiB3aXRoIHRlc3QgcmVzdWx0cy5cblx0ICpcblx0ICogQHBhcmFtIHtqUXVlcnl9IGNvbHVtbiBUaGUgY29sdW1uIGVsZW1lbnQuXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSByZXN1bHQgVGhlIHRlc3QgcmVzdWx0IGRhdGEuXG5cdCAqL1xuXHRmdW5jdGlvbiB1cGRhdGVDb2x1bW5XaXRoUmVzdWx0cyhjb2x1bW4sIHJlc3VsdCkge1xuXHRcdC8vIFJlbG9hZCB0aGUgZW50aXJlIHJvdyBmcm9tIHRoZSBzZXJ2ZXIgdG8gZ2V0IHByb3Blcmx5IHJlbmRlcmVkIEhUTUwuXG5cdFx0Y29uc3QgdXJsID0gY29sdW1uLmRhdGEoJ3VybCcpO1xuXHRcdHJlbG9hZENvbHVtbkZyb21TZXJ2ZXIoY29sdW1uLCB1cmwpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1hcmsgYWxsIHJlbWFpbmluZyBcIlRlc3QgdGhlIHBhZ2VcIiBidXR0b25zIGFzIGhhdmluZyByZWFjaGVkIHRoZSBsaW1pdC5cblx0ICogVXBkYXRlcyBkYXRhIGF0dHJpYnV0ZXMgc28gZnV0dXJlIGNsaWNrcyB3aWxsIHNob3cgdGhlIGxpbWl0IG1lc3NhZ2UgcGVyLXJvdy5cblx0ICogRG9lcyBOT1QgZGlzcGxheSBhbnkgbWVzc2FnZSBpbW1lZGlhdGVseSBvbiBhbGwgcm93cy5cblx0ICovXG5cdGZ1bmN0aW9uIGRpc2FibGVBbGxUZXN0UGFnZUJ1dHRvbnMoKSB7XG5cdFx0alF1ZXJ5KCcud3ByLXJpLXRlc3QtcGFnZScpLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRjb25zdCBidXR0b24gPSBqUXVlcnkodGhpcyk7XG5cdFx0XHRjb25zdCBjb2x1bW4gPSBidXR0b24uY2xvc2VzdCgnLndwci1yaS1jb2x1bW4nKTtcblx0XHRcdFxuXHRcdFx0Ly8gVXBkYXRlIHRoZSBkYXRhIGF0dHJpYnV0ZSBzbyBmdXR1cmUgY2xpY2tzIHdpbGwgdHJpZ2dlciB0aGUgbGltaXQgbWVzc2FnZS5cblx0XHRcdGNvbHVtbi5hdHRyKCdkYXRhLWNhbi1hZGQtcGFnZXMnLCAnMCcpO1xuXHRcdH0pO1xuXHR9XG5cblx0Ly8gQXV0by1pbml0aWFsaXplIG9uIERPTSByZWFkeVxuXHRpZiAoZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gJ2xvYWRpbmcnKSB7XG5cdFx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGluaXQpO1xuXHR9IGVsc2Uge1xuXHRcdGluaXQoKTtcblx0fVxuXG5cdHJldHVybiB7XG5cdFx0aW5pdDogaW5pdFxuXHR9O1xufSkoKTtcbiJdfQ==
329
+