matrix-react-sdk
Version:
SDK for matrix.org using React
355 lines (281 loc) • 43.1 kB
JavaScript
;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = sendBugReport;
exports.downloadBugReport = downloadBugReport;
exports.submitFeedback = submitFeedback;
var _pako = _interopRequireDefault(require("pako"));
var _MatrixClientPeg = require("../MatrixClientPeg");
var _PlatformPeg = _interopRequireDefault(require("../PlatformPeg"));
var _languageHandler = require("../languageHandler");
var _tarJs = _interopRequireDefault(require("tar-js"));
var rageshake = _interopRequireWildcard(require("./rageshake"));
var TextEncodingUtf8 = _interopRequireWildcard(require("text-encoding-utf-8"));
var _SettingsStore = _interopRequireDefault(require("../settings/SettingsStore"));
var _SdkConfig = _interopRequireDefault(require("../SdkConfig"));
/*
Copyright 2017 OpenMarket Ltd
Copyright 2018 New Vector Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// polyfill textencoder if necessary
let TextEncoder = window.TextEncoder;
if (!TextEncoder) {
TextEncoder = TextEncodingUtf8.TextEncoder;
}
async function collectBugReport(opts
/*: IOpts*/
= {}, gzipLogs = true) {
const progressCallback = opts.progressCallback || (() => {});
progressCallback((0, _languageHandler._t)("Collecting app version information"));
let version = "UNKNOWN";
try {
version = await _PlatformPeg.default.get().getAppVersion();
} catch (err) {} // PlatformPeg already logs this.
let userAgent = "UNKNOWN";
if (window.navigator && window.navigator.userAgent) {
userAgent = window.navigator.userAgent;
}
let installedPWA = "UNKNOWN";
try {
// Known to work at least for desktop Chrome
installedPWA = String(window.matchMedia('(display-mode: standalone)').matches);
} catch (e) {}
let touchInput = "UNKNOWN";
try {
// MDN claims broad support across browsers
touchInput = String(window.matchMedia('(pointer: coarse)').matches);
} catch (e) {}
const client = _MatrixClientPeg.MatrixClientPeg.get();
console.log("Sending bug report.");
const body = new FormData();
body.append('text', opts.userText || "User did not supply any additional text.");
body.append('app', 'element-web');
body.append('version', version);
body.append('user_agent', userAgent);
body.append('installed_pwa', installedPWA);
body.append('touch_input', touchInput);
if (client) {
body.append('user_id', client.credentials.userId);
body.append('device_id', client.deviceId);
if (client.isCryptoEnabled()) {
const keys = [`ed25519:${client.getDeviceEd25519Key()}`];
if (client.getDeviceCurve25519Key) {
keys.push(`curve25519:${client.getDeviceCurve25519Key()}`);
}
body.append('device_keys', keys.join(', '));
body.append('cross_signing_key', client.getCrossSigningId()); // add cross-signing status information
const crossSigning = client._crypto._crossSigningInfo;
const secretStorage = client._crypto._secretStorage;
body.append("cross_signing_ready", String(await client.isCrossSigningReady()));
body.append("cross_signing_supported_by_hs", String(await client.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")));
body.append("cross_signing_key", crossSigning.getId());
body.append("cross_signing_pk_in_secret_storage", String(!!(await crossSigning.isStoredInSecretStorage(secretStorage))));
const pkCache = client.getCrossSigningCacheCallbacks();
body.append("cross_signing_master_pk_cached", String(!!(pkCache && (await pkCache.getCrossSigningKeyCache("master")))));
body.append("cross_signing_self_signing_pk_cached", String(!!(pkCache && (await pkCache.getCrossSigningKeyCache("self_signing")))));
body.append("cross_signing_user_signing_pk_cached", String(!!(pkCache && (await pkCache.getCrossSigningKeyCache("user_signing")))));
body.append("secret_storage_ready", String(await client.isSecretStorageReady()));
body.append("secret_storage_key_in_account", String(!!(await secretStorage.hasKey())));
body.append("session_backup_key_in_secret_storage", String(!!(await client.isKeyBackupKeyStored())));
const sessionBackupKeyFromCache = await client._crypto.getSessionBackupPrivateKey();
body.append("session_backup_key_cached", String(!!sessionBackupKeyFromCache));
body.append("session_backup_key_well_formed", String(sessionBackupKeyFromCache instanceof Uint8Array));
}
}
if (opts.label) {
body.append('label', opts.label);
} // add labs options
const enabledLabs = _SettingsStore.default.getFeatureSettingNames().filter(f => _SettingsStore.default.getValue(f));
if (enabledLabs.length) {
body.append('enabled_labs', enabledLabs.join(', '));
} // if low bandwidth mode is enabled, say so over rageshake, it causes many issues
if (_SettingsStore.default.getValue("lowBandwidth")) {
body.append("lowBandwidth", "enabled");
} // add storage persistence/quota information
if (navigator.storage && navigator.storage.persisted) {
try {
body.append("storageManager_persisted", String(await navigator.storage.persisted()));
} catch (e) {}
} else if (document.hasStorageAccess) {
// Safari
try {
body.append("storageManager_persisted", String(await document.hasStorageAccess()));
} catch (e) {}
}
if (navigator.storage && navigator.storage.estimate) {
try {
const estimate = await navigator.storage.estimate();
body.append("storageManager_quota", String(estimate.quota));
body.append("storageManager_usage", String(estimate.usage));
if (estimate.usageDetails) {
Object.keys(estimate.usageDetails).forEach(k => {
body.append(`storageManager_usage_${k}`, String(estimate.usageDetails[k]));
});
}
} catch (e) {}
}
if (window.Modernizr) {
const missingFeatures = Object.keys(window.Modernizr).filter(key => window.Modernizr[key] === false);
if (missingFeatures.length > 0) {
body.append("modernizr_missing_features", missingFeatures.join(", "));
}
}
body.append("mx_local_settings", localStorage.getItem('mx_local_settings'));
if (opts.sendLogs) {
progressCallback((0, _languageHandler._t)("Collecting logs"));
const logs = await rageshake.getLogsForReport();
for (const entry of logs) {
// encode as UTF-8
let buf = new TextEncoder().encode(entry.lines); // compress
if (gzipLogs) {
buf = _pako.default.gzip(buf);
}
body.append('compressed-log', new Blob([buf]), entry.id);
}
}
return body;
}
/**
* Send a bug report.
*
* @param {string} bugReportEndpoint HTTP url to send the report to
*
* @param {object} opts optional dictionary of options
*
* @param {string} opts.userText Any additional user input.
*
* @param {boolean} opts.sendLogs True to send logs
*
* @param {function(string)} opts.progressCallback Callback to call with progress updates
*
* @return {Promise} Resolved when the bug report is sent.
*/
async function sendBugReport(bugReportEndpoint
/*: string*/
, opts
/*: IOpts*/
= {}) {
if (!bugReportEndpoint) {
throw new Error("No bug report endpoint has been set.");
}
const progressCallback = opts.progressCallback || (() => {});
const body = await collectBugReport(opts);
progressCallback((0, _languageHandler._t)("Uploading logs"));
await _submitReport(bugReportEndpoint, body, progressCallback);
}
/**
* Downloads the files from a bug report. This is the same as sendBugReport,
* but instead causes the browser to download the files locally.
*
* @param {object} opts optional dictionary of options
*
* @param {string} opts.userText Any additional user input.
*
* @param {boolean} opts.sendLogs True to send logs
*
* @param {function(string)} opts.progressCallback Callback to call with progress updates
*
* @return {Promise} Resolved when the bug report is downloaded (or started).
*/
async function downloadBugReport(opts
/*: IOpts*/
= {}) {
const progressCallback = opts.progressCallback || (() => {});
const body = await collectBugReport(opts, false);
progressCallback((0, _languageHandler._t)("Downloading logs"));
let metadata = "";
const tape = new _tarJs.default();
let i = 0;
for (const [key, value] of body.entries()) {
if (key === 'compressed-log') {
await new Promise(resolve => {
const reader = new FileReader();
reader.addEventListener('loadend', ev => {
tape.append(`log-${i++}.log`, new TextDecoder().decode(ev.target.result));
resolve();
});
reader.readAsArrayBuffer(value);
});
} else {
metadata += `${key} = ${value}\n`;
}
}
tape.append('issue.txt', metadata); // We have to create a new anchor to download if we want a filename. Otherwise we could
// just use window.open.
const dl = document.createElement('a');
dl.href = `data:application/octet-stream;base64,${btoa(uint8ToString(tape.out))}`;
dl.download = 'rageshake.tar';
document.body.appendChild(dl);
dl.click();
document.body.removeChild(dl);
} // Source: https://github.com/beatgammit/tar-js/blob/master/examples/main.js
function uint8ToString(buf
/*: Buffer*/
) {
let out = '';
for (let i = 0; i < buf.length; i += 1) {
out += String.fromCharCode(buf[i]);
}
return out;
}
async function submitFeedback(endpoint
/*: string*/
, label
/*: string*/
, comment
/*: string*/
, canContact = false) {
let version = "UNKNOWN";
try {
version = await _PlatformPeg.default.get().getAppVersion();
} catch (err) {} // PlatformPeg already logs this.
const body = new FormData();
body.append("label", label);
body.append("text", comment);
body.append("can_contact", canContact ? "yes" : "no");
body.append("app", "element-web");
body.append("version", version);
body.append("platform", _PlatformPeg.default.get().getHumanReadableName());
body.append("user_id", _MatrixClientPeg.MatrixClientPeg.get()?.getUserId());
await _submitReport(_SdkConfig.default.get().bug_report_endpoint_url, body, () => {});
}
function _submitReport(endpoint
/*: string*/
, body
/*: FormData*/
, progressCallback
/*: (string) => void*/
) {
return new Promise((resolve, reject) => {
const req = new XMLHttpRequest();
req.open("POST", endpoint);
req.timeout = 5 * 60 * 1000;
req.onreadystatechange = function () {
if (req.readyState === XMLHttpRequest.LOADING) {
progressCallback((0, _languageHandler._t)("Waiting for response from server"));
} else if (req.readyState === XMLHttpRequest.DONE) {
// on done
if (req.status < 200 || req.status >= 400) {
reject(new Error(`HTTP ${req.status}`));
return;
}
resolve();
}
};
req.send(body);
});
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yYWdlc2hha2Uvc3VibWl0LXJhZ2VzaGFrZS50cyJdLCJuYW1lcyI6WyJUZXh0RW5jb2RlciIsIndpbmRvdyIsIlRleHRFbmNvZGluZ1V0ZjgiLCJjb2xsZWN0QnVnUmVwb3J0Iiwib3B0cyIsImd6aXBMb2dzIiwicHJvZ3Jlc3NDYWxsYmFjayIsInZlcnNpb24iLCJQbGF0Zm9ybVBlZyIsImdldCIsImdldEFwcFZlcnNpb24iLCJlcnIiLCJ1c2VyQWdlbnQiLCJuYXZpZ2F0b3IiLCJpbnN0YWxsZWRQV0EiLCJTdHJpbmciLCJtYXRjaE1lZGlhIiwibWF0Y2hlcyIsImUiLCJ0b3VjaElucHV0IiwiY2xpZW50IiwiTWF0cml4Q2xpZW50UGVnIiwiY29uc29sZSIsImxvZyIsImJvZHkiLCJGb3JtRGF0YSIsImFwcGVuZCIsInVzZXJUZXh0IiwiY3JlZGVudGlhbHMiLCJ1c2VySWQiLCJkZXZpY2VJZCIsImlzQ3J5cHRvRW5hYmxlZCIsImtleXMiLCJnZXREZXZpY2VFZDI1NTE5S2V5IiwiZ2V0RGV2aWNlQ3VydmUyNTUxOUtleSIsInB1c2giLCJqb2luIiwiZ2V0Q3Jvc3NTaWduaW5nSWQiLCJjcm9zc1NpZ25pbmciLCJfY3J5cHRvIiwiX2Nyb3NzU2lnbmluZ0luZm8iLCJzZWNyZXRTdG9yYWdlIiwiX3NlY3JldFN0b3JhZ2UiLCJpc0Nyb3NzU2lnbmluZ1JlYWR5IiwiZG9lc1NlcnZlclN1cHBvcnRVbnN0YWJsZUZlYXR1cmUiLCJnZXRJZCIsImlzU3RvcmVkSW5TZWNyZXRTdG9yYWdlIiwicGtDYWNoZSIsImdldENyb3NzU2lnbmluZ0NhY2hlQ2FsbGJhY2tzIiwiZ2V0Q3Jvc3NTaWduaW5nS2V5Q2FjaGUiLCJpc1NlY3JldFN0b3JhZ2VSZWFkeSIsImhhc0tleSIsImlzS2V5QmFja3VwS2V5U3RvcmVkIiwic2Vzc2lvbkJhY2t1cEtleUZyb21DYWNoZSIsImdldFNlc3Npb25CYWNrdXBQcml2YXRlS2V5IiwiVWludDhBcnJheSIsImxhYmVsIiwiZW5hYmxlZExhYnMiLCJTZXR0aW5nc1N0b3JlIiwiZ2V0RmVhdHVyZVNldHRpbmdOYW1lcyIsImZpbHRlciIsImYiLCJnZXRWYWx1ZSIsImxlbmd0aCIsInN0b3JhZ2UiLCJwZXJzaXN0ZWQiLCJkb2N1bWVudCIsImhhc1N0b3JhZ2VBY2Nlc3MiLCJlc3RpbWF0ZSIsInF1b3RhIiwidXNhZ2UiLCJ1c2FnZURldGFpbHMiLCJPYmplY3QiLCJmb3JFYWNoIiwiayIsIk1vZGVybml6ciIsIm1pc3NpbmdGZWF0dXJlcyIsImtleSIsImxvY2FsU3RvcmFnZSIsImdldEl0ZW0iLCJzZW5kTG9ncyIsImxvZ3MiLCJyYWdlc2hha2UiLCJnZXRMb2dzRm9yUmVwb3J0IiwiZW50cnkiLCJidWYiLCJlbmNvZGUiLCJsaW5lcyIsInBha28iLCJnemlwIiwiQmxvYiIsImlkIiwic2VuZEJ1Z1JlcG9ydCIsImJ1Z1JlcG9ydEVuZHBvaW50IiwiRXJyb3IiLCJfc3VibWl0UmVwb3J0IiwiZG93bmxvYWRCdWdSZXBvcnQiLCJtZXRhZGF0YSIsInRhcGUiLCJUYXIiLCJpIiwidmFsdWUiLCJlbnRyaWVzIiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZWFkZXIiLCJGaWxlUmVhZGVyIiwiYWRkRXZlbnRMaXN0ZW5lciIsImV2IiwiVGV4dERlY29kZXIiLCJkZWNvZGUiLCJ0YXJnZXQiLCJyZXN1bHQiLCJyZWFkQXNBcnJheUJ1ZmZlciIsImRsIiwiY3JlYXRlRWxlbWVudCIsImhyZWYiLCJidG9hIiwidWludDhUb1N0cmluZyIsIm91dCIsImRvd25sb2FkIiwiYXBwZW5kQ2hpbGQiLCJjbGljayIsInJlbW92ZUNoaWxkIiwiZnJvbUNoYXJDb2RlIiwic3VibWl0RmVlZGJhY2siLCJlbmRwb2ludCIsImNvbW1lbnQiLCJjYW5Db250YWN0IiwiZ2V0SHVtYW5SZWFkYWJsZU5hbWUiLCJnZXRVc2VySWQiLCJTZGtDb25maWciLCJidWdfcmVwb3J0X2VuZHBvaW50X3VybCIsInJlamVjdCIsInJlcSIsIlhNTEh0dHBSZXF1ZXN0Iiwib3BlbiIsInRpbWVvdXQiLCJvbnJlYWR5c3RhdGVjaGFuZ2UiLCJyZWFkeVN0YXRlIiwiTE9BRElORyIsIkRPTkUiLCJzdGF0dXMiLCJzZW5kIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7O0FBa0JBOztBQUVBOztBQUNBOztBQUNBOztBQUNBOztBQUVBOztBQUdBOztBQUNBOztBQUNBOztBQTlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBV0E7QUFJQSxJQUFJQSxXQUFXLEdBQUdDLE1BQU0sQ0FBQ0QsV0FBekI7O0FBQ0EsSUFBSSxDQUFDQSxXQUFMLEVBQWtCO0FBQ2RBLEVBQUFBLFdBQVcsR0FBR0UsZ0JBQWdCLENBQUNGLFdBQS9CO0FBQ0g7O0FBU0QsZUFBZUcsZ0JBQWYsQ0FBZ0NDO0FBQVc7QUFBQSxFQUFHLEVBQTlDLEVBQWtEQyxRQUFRLEdBQUcsSUFBN0QsRUFBbUU7QUFDL0QsUUFBTUMsZ0JBQWdCLEdBQUdGLElBQUksQ0FBQ0UsZ0JBQUwsS0FBMEIsTUFBTSxDQUFFLENBQWxDLENBQXpCOztBQUVBQSxFQUFBQSxnQkFBZ0IsQ0FBQyx5QkFBRyxvQ0FBSCxDQUFELENBQWhCO0FBQ0EsTUFBSUMsT0FBTyxHQUFHLFNBQWQ7O0FBQ0EsTUFBSTtBQUNBQSxJQUFBQSxPQUFPLEdBQUcsTUFBTUMscUJBQVlDLEdBQVosR0FBa0JDLGFBQWxCLEVBQWhCO0FBQ0gsR0FGRCxDQUVFLE9BQU9DLEdBQVAsRUFBWSxDQUFFLENBUCtDLENBTzlDOzs7QUFFakIsTUFBSUMsU0FBUyxHQUFHLFNBQWhCOztBQUNBLE1BQUlYLE1BQU0sQ0FBQ1ksU0FBUCxJQUFvQlosTUFBTSxDQUFDWSxTQUFQLENBQWlCRCxTQUF6QyxFQUFvRDtBQUNoREEsSUFBQUEsU0FBUyxHQUFHWCxNQUFNLENBQUNZLFNBQVAsQ0FBaUJELFNBQTdCO0FBQ0g7O0FBRUQsTUFBSUUsWUFBWSxHQUFHLFNBQW5COztB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VCxDQUF1QitCO0FBQXZCO0FBQUEsRUFBeUN0RztBQUF6QztBQUFBLEVBQXlEbEI7QUFBekQ7QUFBQSxFQUE2RjtBQUN6RixTQUFPLElBQUlpRyxPQUFKLENBQWtCLENBQUNDLE9BQUQsRUFBVTZCLE1BQVYsS0FBcUI7QUFDMUMsVUFBTUMsR0FBRyxHQUFHLElBQUlDLGNBQUosRUFBWjtBQUNBRCxJQUFBQSxHQUFHLENBQUNFLElBQUosQ0FBUyxNQUFULEVBQWlCVixRQUFqQjtBQUNBUSxJQUFBQSxHQUFHLENBQUNHLE9BQUosR0FBYyxJQUFJLEVBQUosR0FBUyxJQUF2Qjs7QUFDQUgsSUFBQUEsR0FBRyxDQUFDSSxrQkFBSixHQUF5QixZQUFXO0FBQ2hDLFVBQUlKLEdBQUcsQ0FBQ0ssVUFBSixLQUFtQkosY0FBYyxDQUFDSyxPQUF0QyxFQUErQztBQUMzQ3RJLFFBQUFBLGdCQUFnQixDQUFDLHlCQUFHLGtDQUFILENBQUQsQ0FBaEI7QUFDSCxPQUZELE1BRU8sSUFBSWdJLEdBQUcsQ0FBQ0ssVUFBSixLQUFtQkosY0FBYyxDQUFDTSxJQUF0QyxFQUE0QztBQUMvQztBQUNBLFlBQUlQLEdBQUcsQ0FBQ1EsTUFBSixHQUFhLEdBQWIsSUFBb0JSLEdBQUcsQ0FBQ1EsTUFBSixJQUFjLEdBQXRDLEVBQTJDO0FBQ3ZDVCxVQUFBQSxNQUFNLENBQUMsSUFBSXZDLEtBQUosQ0FBVyxRQUFPd0MsR0FBRyxDQUFDUSxNQUFPLEVBQTdCLENBQUQsQ0FBTjtBQUNBO0FBQ0g7O0FBQ0R0QyxRQUFBQSxPQUFPO0FBQ1Y7QUFDSixLQVhEOztBQVlBOEIsSUFBQUEsR0FBRyxDQUFDUyxJQUFKLENBQVN2SCxJQUFUO0FBQ0gsR0FqQk0sQ0FBUDtBQWtCSCIsInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAxNyBPcGVuTWFya2V0IEx0ZFxuQ29weXJpZ2h0IDIwMTggTmV3IFZlY3RvciBMdGRcbkNvcHlyaWdodCAyMDE5IFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IHBha28gZnJvbSAncGFrbyc7XG5cbmltcG9ydCB7TWF0cml4Q2xpZW50UGVnfSBmcm9tICcuLi9NYXRyaXhDbGllbnRQZWcnO1xuaW1wb3J0IFBsYXRmb3JtUGVnIGZyb20gJy4uL1BsYXRmb3JtUGVnJztcbmltcG9ydCB7IF90IH0gZnJvbSAnLi4vbGFuZ3VhZ2VIYW5kbGVyJztcbmltcG9ydCBUYXIgZnJvbSBcInRhci1qc1wiO1xuXG5pbXBvcnQgKiBhcyByYWdlc2hha2UgZnJvbSAnLi9yYWdlc2hha2UnO1xuXG4vLyBwb2x5ZmlsbCB0ZXh0ZW5jb2RlciBpZiBuZWNlc3NhcnlcbmltcG9ydCAqIGFzIFRleHRFbmNvZGluZ1V0ZjggZnJvbSAndGV4dC1lbmNvZGluZy11dGYtOCc7XG5pbXBvcnQgU2V0dGluZ3NTdG9yZSBmcm9tIFwiLi4vc2V0dGluZ3MvU2V0dGluZ3NTdG9yZVwiO1xuaW1wb3J0IFNka0NvbmZpZyBmcm9tIFwiLi4vU2RrQ29uZmlnXCI7XG5sZXQgVGV4dEVuY29kZXIgPSB3aW5kb3cuVGV4dEVuY29kZXI7XG5pZiAoIVRleHRFbmNvZGVyKSB7XG4gICAgVGV4dEVuY29kZXIgPSBUZXh0RW5jb2RpbmdVdGY4LlRleHRFbmNvZGVyO1xufVxuXG5pbnRlcmZhY2UgSU9wdHMge1xuICAgIGxhYmVsPzogc3RyaW5nO1xuICAgIHVzZXJUZXh0Pzogc3RyaW5nO1xuICAgIHNlbmRMb2dzPzogYm9vbGVhbjtcbiAgICBwcm9ncmVzc0NhbGxiYWNrPzogKHN0cmluZykgPT4gdm9pZDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY29sbGVjdEJ1Z1JlcG9ydChvcHRzOiBJT3B0cyA9IHt9LCBnemlwTG9ncyA9IHRydWUpIHtcbiAgICBjb25zdCBwcm9ncmVzc0NhbGxiYWNrID0gb3B0cy5wcm9ncmVzc0NhbGxiYWNrIHx8ICgoKSA9PiB7fSk7XG5cbiAgICBwcm9ncmVzc0NhbGxiYWNrKF90KFwiQ29sbGVjdGluZyBhcHAgdmVyc2lvbiBpbmZvcm1hdGlvblwiKSk7XG4gICAgbGV0IHZlcnNpb24gPSBcIlVOS05PV05cIjtcbiAgICB0cnkge1xuICAgICAgICB2ZXJzaW9uID0gYXdhaXQgUGxhdGZvcm1QZWcuZ2V0KCkuZ2V0QXBwVmVyc2lvbigpO1xuICAgIH0gY2F0Y2ggKGVycikge30gLy8gUGxhdGZvcm1QZWcgYWxyZWFkeSBsb2dzIHRoaXMuXG5cbiAgICBsZXQgdXNlckFnZW50ID0gXCJVTktOT1dOXCI7XG4gICAgaWYgKHdpbmRvdy5uYXZpZ2F0b3IgJiYgd2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQpIHtcbiAgICAgICAgdXNlckFnZW50ID0gd2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQ7XG4gICAgfVxuXG4gICAgbGV0IGluc3RhbGxlZFBXQSA9IFwiVU5LTk9XTlwiO1xuICAgIHRyeSB7XG4gICAgICAgIC8vIEtub3duIHRvIHdvcmsgYXQgbGVhc3QgZm9yIGRlc2t0b3AgQ2hyb21lXG4gICAgICAgIGluc3RhbGxlZFBXQSA9IFN0cmluZyh3aW5kb3cubWF0Y2hNZWRpYSgnKGRpc3BsYXktbW9kZTogc3RhbmRhbG9uZSknKS5tYXRjaGVzKTtcbiAgICB9IGNhdGNoIChlKSB7fVxuXG4gICAgbGV0IHRvdWNoSW5wdXQgPSBcIlVOS05PV05cIjtcbiAgICB0cnkge1xuICAgICAgICAvLyBNRE4gY2xhaW1zIGJyb2FkIHN1cHBvcnQgYWNyb3NzIGJyb3dzZXJzXG4gICAgICAgIHRvdWNoSW5wdXQgPSBTdHJpbmcod2luZG93Lm1hdGNoTWVkaWEoJyhwb2ludGVyOiBjb2Fyc2UpJykubWF0Y2hlcyk7XG4gICAgfSBjYXRjaCAoZSkgeyB9XG5cbiAgICBjb25zdCBjbGllbnQgPSBNYXRyaXhDbGllbnRQZWcuZ2V0KCk7XG5cbiAgICBjb25zb2xlLmxvZyhcIlNlbmRpbmcgYnVnIHJlcG9ydC5cIik7XG5cbiAgICBjb25zdCBib2R5ID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgYm9keS5hcHBlbmQoJ3RleHQnLCBvcHRzLnVzZXJUZXh0IHx8IFwiVXNlciBkaWQgbm90IHN1cHBseSBhbnkgYWRkaXRpb25hbCB0ZXh0LlwiKTtcbiAgICBib2R5LmFwcGVuZCgnYXBwJywgJ2VsZW1lbnQtd2ViJyk7XG4gICAgYm9keS5hcHBlbmQoJ3ZlcnNpb24nLCB2ZXJzaW9uKTtcbiAgICBib2R5LmFwcGVuZCgndXNlcl9hZ2VudCcsIHVzZXJBZ2VudCk7XG4gICAgYm9keS5hcHBlbmQoJ2luc3RhbGxlZF9wd2EnLCBpbnN0YWxsZWRQV0EpO1xuICAgIGJvZHkuYXBwZW5kKCd0b3VjaF9pbnB1dCcsIHRvdWNoSW5wdXQpO1xuXG4gICAgaWYgKGNsaWVudCkge1xuICAgICAgICBib2R5LmFwcGVuZCgndXNlcl9pZCcsIGNsaWVudC5jcmVkZW50aWFscy51c2VySWQpO1xuICAgICAgICBib2R5LmFwcGVuZCgnZGV2aWNlX2lkJywgY2xpZW50LmRldmljZUlkKTtcblxuICAgICAgICBpZiAoY2xpZW50LmlzQ3J5cHRvRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICBjb25zdCBrZXlzID0gW2BlZDI1NTE5OiR7Y2xpZW50LmdldERldmljZUVkMjU1MTlLZXkoKX1gXTtcbiAgICAgICAgICAgIGlmIChjbGllbnQuZ2V0RGV2aWNlQ3VydmUyNTUxOUtleSkge1xuICAgICAgICAgICAgICAgIGtleXMucHVzaChgY3VydmUyNTUxOToke2NsaWVudC5nZXREZXZpY2VDdXJ2ZTI1NTE5S2V5KCl9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBib2R5LmFwcGVuZCgnZGV2aWNlX2tleXMnLCBrZXlzLmpvaW4oJywgJykpO1xuICAgICAgICAgICAgYm9keS5hcHBlbmQoJ2Nyb3NzX3NpZ25pbmdfa2V5JywgY2xpZW50LmdldENyb3NzU2lnbmluZ0lkKCkpO1xuXG4gICAgICAgICAgICAvLyBhZGQgY3Jvc3Mtc2lnbmluZyBzdGF0dXMgaW5mb3JtYXRpb25cbiAgICAgICAgICAgIGNvbnN0IGNyb3NzU2lnbmluZyA9IGNsaWVudC5fY3J5cHRvLl9jcm9zc1NpZ25pbmdJbmZvO1xuICAgICAgICAgICAgY29uc3Qgc2VjcmV0U3RvcmFnZSA9IGNsaWVudC5fY3J5cHRvLl9zZWNyZXRTdG9yYWdlO1xuXG4gICAgICAgICAgICBib2R5LmFwcGVuZChcImNyb3NzX3NpZ25pbmdfcmVhZHlcIiwgU3RyaW5nKGF3YWl0IGNsaWVudC5pc0Nyb3NzU2lnbmluZ1JlYWR5KCkpKTtcbiAgICAgICAgICAgIGJvZHkuYXBwZW5kKFwiY3Jvc3Nfc2lnbmluZ19zdXBwb3J0ZWRfYnlfaHNcIixcbiAgICAgICAgICAgICAgICBTdHJpbmcoYXdhaXQgY2xpZW50LmRvZXNTZXJ2ZXJTdXBwb3J0VW5zdGFibGVGZWF0dXJlKFwib3JnLm1hdHJpeC5lMmVfY3Jvc3Nfc2lnbmluZ1wiKSkpO1xuICAgICAgICAgICAgYm9keS5hcHBlbmQoXCJjcm9zc19zaWduaW5nX2tleVwiLCBjcm9zc1NpZ25pbmcuZ2V0SWQoKSk7XG4gICAgICAgICAgICBib2R5LmFwcGVuZChcImNyb3NzX3NpZ25pbmdfcGtfaW5fc2VjcmV0X3N0b3JhZ2VcIixcbiAgICAgICAgICAgICAgICBTdHJpbmcoISEoYXdhaXQgY3Jvc3NTaWduaW5nLmlzU3RvcmVkSW5TZWNyZXRTdG9yYWdlKHNlY3JldFN0b3JhZ2UpKSkpO1xuXG4gICAgICAgICAgICBjb25zdCBwa0NhY2hlID0gY2xpZW50LmdldENyb3NzU2lnbmluZ0NhY2hlQ2FsbGJhY2tzKCk7XG4gICAgICAgICAgICBib2R5LmFwcGVuZChcImNyb3NzX3NpZ25pbmdfbWFzdGVyX3BrX2NhY2hlZFwiLFxuICAgICAgICAgICAgICAgIFN0cmluZyghIShwa0NhY2hlICYmIGF3YWl0IHBrQ2FjaGUuZ2V0Q3Jvc3NTaWduaW5nS2V5Q2FjaGUoXCJtYXN0ZXJcIikpKSk7XG4gICAgICAgICAgICBib2R5LmFwcGVuZChcImNyb3NzX3NpZ25pbmdfc2VsZl9zaWduaW5nX3BrX2NhY2hlZFwiLFxuICAgICAgICAgICAgICAgIFN0cmluZyghIShwa0NhY2hlICYmIGF3YWl0IHBrQ2FjaGUuZ2V0Q3Jvc3NTaWduaW5nS2V5Q2FjaGUoXCJzZWxmX3NpZ25pbmdcIikpKSk7XG4gICAgICAgICAgICBib2R5LmFwcGVuZChcImNyb3NzX3NpZ25pbmdfdXNlcl9zaWduaW5nX3BrX2NhY2hlZFwiLFxuICAgICAgICAgICAgICAgIFN0cmluZyghIShwa0NhY2hlICYmIGF3YWl0IHBrQ2FjaGUuZ2V0Q3Jvc3NTaWduaW5nS2V5Q2FjaGUoXCJ1c2VyX3NpZ25pbmdcIikpKSk7XG5cbiAgICAgICAgICAgIGJvZHkuYXBwZW5kKFwic2VjcmV0X3N0b3JhZ2VfcmVhZHlcIiwgU3RyaW5nKGF3YWl0IGNsaWVudC5pc1NlY3JldFN0b3JhZ2VSZWFkeSgpKSk7XG4gICAgICAgICAgICBib2R5LmFwcGVuZChcInNlY3JldF9zdG9yYWdlX2tleV9pbl9hY2NvdW50XCIsIFN0cmluZyghIShhd2FpdCBzZWNyZXRTdG9yYWdlLmhhc0tleSgpKSkpO1xuXG4gICAgICAgICAgICBib2R5LmFwcGVuZChcInNlc3Npb25fYmFja3VwX2tleV9pbl9zZWNyZXRfc3RvcmFnZVwiLCBTdHJpbmcoISEoYXdhaXQgY2xpZW50LmlzS2V5QmFja3VwS2V5U3RvcmVkKCkpKSk7XG4gICAgICAgICAgICBjb25zdCBzZXNzaW9uQmFja3VwS2V5RnJvbUNhY2hlID0gYXdhaXQgY2xpZW50Ll9jcnlwdG8uZ2V0U2Vzc2lvbkJhY2t1cFByaXZhdGVLZXkoKTtcbiAgICAgICAgICAgIGJvZHkuYXBwZW5kKFwic2Vzc2lvbl9iYWNrdXBfa2V5X2NhY2hlZFwiLCBTdHJpbmcoISFzZXNzaW9uQmFja3VwS2V5RnJvbUNhY2hlKSk7XG4gICAgICAgICAgICBib2R5LmFwcGVuZChcInNlc3Npb25fYmFja3VwX2tleV93ZWxsX2Zvcm1lZFwiLCBTdHJpbmcoc2Vzc2lvbkJhY2t1cEtleUZyb21DYWNoZSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmIChvcHRzLmxhYmVsKSB7XG4gICAgICAgIGJvZHkuYXBwZW5kKCdsYWJlbCcsIG9wdHMubGFiZWwpO1xuICAgIH1cblxuICAgIC8vIGFkZCBsYWJzIG9wdGlvbnNcbiAgICBjb25zdCBlbmFibGVkTGFicyA9IFNldHRpbmdzU3RvcmUuZ2V0RmVhdHVyZVNldHRpbmdOYW1lcygpLmZpbHRlcihmID0+IFNldHRpbmdzU3RvcmUuZ2V0VmFsdWUoZikpO1xuICAgIGlmIChlbmFibGVkTGFicy5sZW5ndGgpIHtcbiAgICAgICAgYm9keS5hcHBlbmQoJ2VuYWJsZWRfbGFicycsIGVuYWJsZWRMYWJzLmpvaW4oJywgJykpO1xuICAgIH1cbiAgICAvLyBpZiBsb3cgYmFuZHdpZHRoIG1vZGUgaXMgZW5hYmxlZCwgc2F5IHNvIG92ZXIgcmFnZXNoYWtlLCBpdCBjYXVzZXMgbWFueSBpc3N1ZXNcbiAgICBpZiAoU2V0dGluZ3NTdG9yZS5nZXRWYWx1ZShcImxvd0JhbmR3aWR0aFwiKSkge1xuICAgICAgICBib2R5LmFwcGVuZChcImxvd0JhbmR3aWR0aFwiLCBcImVuYWJsZWRcIik7XG4gICAgfVxuXG4gICAgLy8gYWRkIHN0b3JhZ2UgcGVyc2lzdGVuY2UvcXVvdGEgaW5mb3JtYXRpb25cbiAgICBpZiAobmF2aWdhdG9yLnN0b3JhZ2UgJiYgbmF2aWdhdG9yLnN0b3JhZ2UucGVyc2lzdGVkKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBib2R5LmFwcGVuZChcInN0b3JhZ2VNYW5hZ2VyX3BlcnNpc3RlZFwiLCBTdHJpbmcoYXdhaXQgbmF2aWdhdG9yLnN0b3JhZ2UucGVyc2lzdGVkKCkpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICB9IGVsc2UgaWYgKGRvY3VtZW50Lmhhc1N0b3JhZ2VBY2Nlc3MpIHsgLy8gU2FmYXJpXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBib2R5LmFwcGVuZChcInN0b3JhZ2VNYW5hZ2VyX3BlcnNpc3RlZFwiLCBTdHJpbmcoYXdhaXQgZG9jdW1lbnQuaGFzU3RvcmFnZUFjY2VzcygpKSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgfVxuICAgIGlmIChuYXZpZ2F0b3Iuc3RvcmFnZSAmJiBuYXZpZ2F0b3Iuc3RvcmFnZS5lc3RpbWF0ZSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgZXN0aW1hdGUgPSBhd2FpdCBuYXZpZ2F0b3Iuc3RvcmFnZS5lc3RpbWF0ZSgpO1xuICAgICAgICAgICAgYm9keS5hcHBlbmQoXCJzdG9yYWdlTWFuYWdlcl9xdW90YVwiLCBTdHJpbmcoZXN0aW1hdGUucXVvdGEpKTtcbiAgICAgICAgICAgIGJvZHkuYXBwZW5kKFwic3RvcmFnZU1hbmFnZXJfdXNhZ2VcIiwgU3RyaW5nKGVzdGltYXRlLnVzYWdlKSk7XG4gICAgICAgICAgICBpZiAoZXN0aW1hdGUudXNhZ2VEZXRhaWxzKSB7XG4gICAgICAgICAgICAgICAgT2JqZWN0LmtleXMoZXN0aW1hdGUudXNhZ2VEZXRhaWxzKS5mb3JFYWNoKGsgPT4ge1xuICAgICAgICAgICAgICAgICAgICBib2R5LmFwcGVuZChgc3RvcmFnZU1hbmFnZXJfdXNhZ2VfJHtrfWAsIFN0cmluZyhlc3RpbWF0ZS51c2FnZURldGFpbHNba10pKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICB9XG5cbiAgICBpZiAod2luZG93Lk1vZGVybml6cikge1xuICAgICAgICBjb25zdCBtaXNzaW5nRmVhdHVyZXMgPSBPYmplY3Qua2V5cyh3aW5kb3cuTW9kZXJuaXpyKS5maWx0ZXIoa2V5ID0+IHdpbmRvdy5Nb2Rlcm5penJba2V5XSA9PT0gZmFsc2UpO1xuICAgICAgICBpZiAobWlzc2luZ0ZlYXR1cmVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGJvZHkuYXBwZW5kKFwibW9kZXJuaXpyX21pc3NpbmdfZmVhdHVyZXNcIiwgbWlzc2luZ0ZlYXR1cmVzLmpvaW4oXCIsIFwiKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBib2R5LmFwcGVuZChcIm14X2xvY2FsX3NldHRpbmdzXCIsIGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdteF9sb2NhbF9zZXR0aW5ncycpKTtcblxuICAgIGlmIChvcHRzLnNlbmRMb2dzKSB7XG4gICAgICAgIHByb2dyZXNzQ2FsbGJhY2soX3QoXCJDb2xsZWN0aW5nIGxvZ3NcIikpO1xuICAgICAgICBjb25zdCBsb2dzID0gYXdhaXQgcmFnZXNoYWtlLmdldExvZ3NGb3JSZXBvcnQoKTtcbiAgICAgICAgZm9yIChjb25zdCBlbnRyeSBvZiBsb2dzKSB7XG4gICAgICAgICAgICAvLyBlbmNvZGUgYXMgVVRGLThcbiAgICAgICAgICAgIGxldCBidWYgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoZW50cnkubGluZXMpO1xuXG4gICAgICAgICAgICAvLyBjb21wcmVzc1xuICAgICAgICAgICAgaWYgKGd6aXBMb2dzKSB7XG4gICAgICAgICAgICAgICAgYnVmID0gcGFrby5nemlwKGJ1Zik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJvZHkuYXBwZW5kKCdjb21wcmVzc2VkLWxvZycsIG5ldyBCbG9iKFtidWZdKSwgZW50cnkuaWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGJvZHk7XG59XG5cbi8qKlxuICogU2VuZCBhIGJ1ZyByZXBvcnQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGJ1Z1JlcG9ydEVuZHBvaW50IEhUVFAgdXJsIHRvIHNlbmQgdGhlIHJlcG9ydCB0b1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzIG9wdGlvbmFsIGRpY3Rpb25hcnkgb2Ygb3B0aW9uc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnVzZXJUZXh0IEFueSBhZGRpdGlvbmFsIHVzZXIgaW5wdXQuXG4gKlxuICogQHBhcmFtIHtib29sZWFufSBvcHRzLnNlbmRMb2dzIFRydWUgdG8gc2VuZCBsb2dzXG4gKlxuICogQHBhcmFtIHtmdW5jdGlvbihzdHJpbmcpfSBvcHRzLnByb2dyZXNzQ2FsbGJhY2sgQ2FsbGJhY2sgdG8gY2FsbCB3aXRoIHByb2dyZXNzIHVwZGF0ZXNcbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlfSBSZXNvbHZlZCB3aGVuIHRoZSBidWcgcmVwb3J0IGlzIHNlbnQuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIHNlbmRCdWdSZXBvcnQoYnVnUmVwb3J0RW5kcG9pbnQ6IHN0cmluZywgb3B0czogSU9wdHMgPSB7fSkge1xuICAgIGlmICghYnVnUmVwb3J0RW5kcG9pbnQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gYnVnIHJlcG9ydCBlbmRwb2ludCBoYXMgYmVlbiBzZXQuXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IHByb2dyZXNzQ2FsbGJhY2sgPSBvcHRzLnByb2dyZXNzQ2FsbGJhY2sgfHwgKCgpID0+IHt9KTtcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgY29sbGVjdEJ1Z1JlcG9ydChvcHRzKTtcblxuICAgIHByb2dyZXNzQ2FsbGJhY2soX3QoXCJVcGxvYWRpbmcgbG9nc1wiKSk7XG4gICAgYXdhaXQgX3N1Ym1pdFJlcG9ydChidWdSZXBvcnRFbmRwb2ludCwgYm9keSwgcHJvZ3Jlc3NDYWxsYmFjayk7XG59XG5cbi8qKlxuICogRG93bmxvYWRzIHRoZSBmaWxlcyBmcm9tIGEgYnVnIHJlcG9ydC4gVGhpcyBpcyB0aGUgc2FtZSBhcyBzZW5kQnVnUmVwb3J0LFxuICogYnV0IGluc3RlYWQgY2F1c2VzIHRoZSBicm93c2VyIHRvIGRvd25sb2FkIHRoZSBmaWxlcyBsb2NhbGx5LlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzIG9wdGlvbmFsIGRpY3Rpb25hcnkgb2Ygb3B0aW9uc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLnVzZXJUZXh0IEFueSBhZGRpdGlvbmFsIHVzZXIgaW5wdXQuXG4gKlxuICogQHBhcmFtIHtib29sZWFufSBvcHRzLnNlbmRMb2dzIFRydWUgdG8gc2VuZCBsb2dzXG4gKlxuICogQHBhcmFtIHtmdW5jdGlvbihzdHJpbmcpfSBvcHRzLnByb2dyZXNzQ2FsbGJhY2sgQ2FsbGJhY2sgdG8gY2FsbCB3aXRoIHByb2dyZXNzIHVwZGF0ZXNcbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlfSBSZXNvbHZlZCB3aGVuIHRoZSBidWcgcmVwb3J0IGlzIGRvd25sb2FkZWQgKG9yIHN0YXJ0ZWQpLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZG93bmxvYWRCdWdSZXBvcnQob3B0czogSU9wdHMgPSB7fSkge1xuICAgIGNvbnN0IHByb2dyZXNzQ2FsbGJhY2sgPSBvcHRzLnByb2dyZXNzQ2FsbGJhY2sgfHwgKCgpID0+IHt9KTtcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgY29sbGVjdEJ1Z1JlcG9ydChvcHRzLCBmYWxzZSk7XG5cbiAgICBwcm9ncmVzc0NhbGxiYWNrKF90KFwiRG93bmxvYWRpbmcgbG9nc1wiKSk7XG4gICAgbGV0IG1ldGFkYXRhID0gXCJcIjtcbiAgICBjb25zdCB0YXBlID0gbmV3IFRhcigpO1xuICAgIGxldCBpID0gMDtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBib2R5LmVudHJpZXMoKSkge1xuICAgICAgICBpZiAoa2V5ID09PSAnY29tcHJlc3NlZC1sb2cnKSB7XG4gICAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcbiAgICAgICAgICAgICAgICByZWFkZXIuYWRkRXZlbnRMaXN0ZW5lcignbG9hZGVuZCcsIGV2ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGFwZS5hcHBlbmQoYGxvZy0ke2krK30ubG9nYCwgbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGV2LnRhcmdldC5yZXN1bHQgYXMgQXJyYXlCdWZmZXIpKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJlYWRlci5yZWFkQXNBcnJheUJ1ZmZlcih2YWx1ZSBhcyBCbG9iKTtcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1ldGFkYXRhICs9IGAke2tleX0gPSAke3ZhbHVlfVxcbmA7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdGFwZS5hcHBlbmQoJ2lzc3VlLnR4dCcsIG1ldGFkYXRhKTtcblxuICAgIC8vIFdlIGhhdmUgdG8gY3JlYXRlIGEgbmV3IGFuY2hvciB0byBkb3dubG9hZCBpZiB3ZSB3YW50IGEgZmlsZW5hbWUuIE90aGVyd2lzZSB3ZSBjb3VsZFxuICAgIC8vIGp1c3QgdXNlIHdpbmRvdy5vcGVuLlxuICAgIGNvbnN0IGRsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgIGRsLmhyZWYgPSBgZGF0YTphcHBsaWNhdGlvbi9vY3RldC1zdHJlYW07YmFzZTY0LCR7YnRvYSh1aW50OFRvU3RyaW5nKHRhcGUub3V0KSl9YDtcbiAgICBkbC5kb3dubG9hZCA9ICdyYWdlc2hha2UudGFyJztcbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGRsKTtcbiAgICBkbC5jbGljaygpO1xuICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoZGwpO1xufVxuXG4vLyBTb3VyY2U6IGh0dHBzOi8vZ2l0aHViLmNvbS9iZWF0Z2FtbWl0L3Rhci1qcy9ibG9iL21hc3Rlci9leGFtcGxlcy9tYWluLmpzXG5mdW5jdGlvbiB1aW50OFRvU3RyaW5nKGJ1ZjogQnVmZmVyKSB7XG4gICAgbGV0IG91dCA9ICcnO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnVmLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgIG91dCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ1ZltpXSk7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdWJtaXRGZWVkYmFjayhlbmRwb2ludDogc3RyaW5nLCBsYWJlbDogc3RyaW5nLCBjb21tZW50OiBzdHJpbmcsIGNhbkNvbnRhY3QgPSBmYWxzZSkge1xuICAgIGxldCB2ZXJzaW9uID0gXCJVTktOT1dOXCI7XG4gICAgdHJ5IHtcbiAgICAgICAgdmVyc2lvbiA9IGF3YWl0IFBsYXRmb3JtUGVnLmdldCgpLmdldEFwcFZlcnNpb24oKTtcbiAgICB9IGNhdGNoIChlcnIpIHt9IC8vIFBsYXRmb3JtUGVnIGFscmVhZHkgbG9ncyB0aGlzLlxuXG4gICAgY29uc3QgYm9keSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgIGJvZHkuYXBwZW5kKFwibGFiZWxcIiwgbGFiZWwpO1xuICAgIGJvZHkuYXBwZW5kKFwidGV4dFwiLCBjb21tZW50KTtcbiAgICBib2R5LmFwcGVuZChcImNhbl9jb250YWN0XCIsIGNhbkNvbnRhY3QgPyBcInllc1wiIDogXCJub1wiKTtcblxuICAgIGJvZHkuYXBwZW5kKFwiYXBwXCIsIFwiZWxlbWVudC13ZWJcIik7XG4gICAgYm9keS5hcHBlbmQoXCJ2ZXJzaW9uXCIsIHZlcnNpb24pO1xuICAgIGJvZHkuYXBwZW5kKFwicGxhdGZvcm1cIiwgUGxhdGZvcm1QZWcuZ2V0KCkuZ2V0SHVtYW5SZWFkYWJsZU5hbWUoKSk7XG4gICAgYm9keS5hcHBlbmQoXCJ1c2VyX2lkXCIsIE1hdHJpeENsaWVudFBlZy5nZXQoKT8uZ2V0VXNlcklkKCkpO1xuXG4gICAgYXdhaXQgX3N1Ym1pdFJlcG9ydChTZGtDb25maWcuZ2V0KCkuYnVnX3JlcG9ydF9lbmRwb2ludF91cmwsIGJvZHksICgpID0+IHt9KTtcbn1cblxuZnVuY3Rpb24gX3N1Ym1pdFJlcG9ydChlbmRwb2ludDogc3RyaW5nLCBib2R5OiBGb3JtRGF0YSwgcHJvZ3Jlc3NDYWxsYmFjazogKHN0cmluZykgPT4gdm9pZCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGNvbnN0IHJlcSA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICByZXEub3BlbihcIlBPU1RcIiwgZW5kcG9pbnQpO1xuICAgICAgICByZXEudGltZW91dCA9IDUgKiA2MCAqIDEwMDA7XG4gICAgICAgIHJlcS5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGlmIChyZXEucmVhZHlTdGF0ZSA9PT0gWE1MSHR0cFJlcXVlc3QuTE9BRElORykge1xuICAgICAgICAgICAgICAgIHByb2dyZXNzQ2FsbGJhY2soX3QoXCJXYWl0aW5nIGZvciByZXNwb25zZSBmcm9tIHNlcnZlclwiKSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHJlcS5yZWFkeVN0YXRlID09PSBYTUxIdHRwUmVxdWVzdC5ET05FKSB7XG4gICAgICAgICAgICAgICAgLy8gb24gZG9uZVxuICAgICAgICAgICAgICAgIGlmIChyZXEuc3RhdHVzIDwgMjAwIHx8IHJlcS5zdGF0dXMgPj0gNDAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYEhUVFAgJHtyZXEuc3RhdHVzfWApKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHJlcS5zZW5kKGJvZHkpO1xuICAgIH0pO1xufVxuIl19