UNPKG

matrix-react-sdk

Version:
303 lines (247 loc) 38.4 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _languageHandler = require("../../../languageHandler"); var sdk = _interopRequireWildcard(require("../../../index")); var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher")); var Lifecycle = _interopRequireWildcard(require("../../../Lifecycle")); var _Modal = _interopRequireDefault(require("../../../Modal")); var _MatrixClientPeg = require("../../../MatrixClientPeg"); var _Login = require("../../../Login"); var _AuthPage = _interopRequireDefault(require("../../views/auth/AuthPage")); var _BasePlatform = require("../../../BasePlatform"); var _SSOButtons = _interopRequireDefault(require("../../views/elements/SSOButtons")); var _replaceableComponent = require("../../../utils/replaceableComponent"); var _dec, _class, _temp; const LOGIN_VIEW = { LOADING: 1, PASSWORD: 2, CAS: 3, // SSO, but old SSO: 4, UNSUPPORTED: 5 }; const FLOWS_TO_VIEWS = { "m.login.password": LOGIN_VIEW.PASSWORD, "m.login.cas": LOGIN_VIEW.CAS, "m.login.sso": LOGIN_VIEW.SSO }; let SoftLogout = (_dec = (0, _replaceableComponent.replaceableComponent)("structures.auth.SoftLogout"), _dec(_class = (_temp = class SoftLogout extends _react.default.Component /*:: <IProps, IState>*/ { constructor(props) { super(props); (0, _defineProperty2.default)(this, "onClearAll", () => { const ConfirmWipeDeviceDialog = sdk.getComponent('dialogs.ConfirmWipeDeviceDialog'); _Modal.default.createTrackedDialog('Clear Data', 'Soft Logout', ConfirmWipeDeviceDialog, { onFinished: wipeData => { if (!wipeData) return; console.log("Clearing data from soft-logged-out session"); Lifecycle.logout(); } }); }); (0, _defineProperty2.default)(this, "onPasswordChange", ev => { this.setState({ password: ev.target.value }); }); (0, _defineProperty2.default)(this, "onForgotPassword", () => { _dispatcher.default.dispatch({ action: 'start_password_recovery' }); }); (0, _defineProperty2.default)(this, "onPasswordLogin", async ev => { ev.preventDefault(); ev.stopPropagation(); this.setState({ busy: true }); const hsUrl = _MatrixClientPeg.MatrixClientPeg.get().getHomeserverUrl(); const isUrl = _MatrixClientPeg.MatrixClientPeg.get().getIdentityServerUrl(); const loginType = "m.login.password"; const loginParams = { identifier: { type: "m.id.user", user: _MatrixClientPeg.MatrixClientPeg.get().getUserId() }, password: this.state.password, device_id: _MatrixClientPeg.MatrixClientPeg.get().getDeviceId() }; let credentials = null; try { credentials = await (0, _Login.sendLoginRequest)(hsUrl, isUrl, loginType, loginParams); } catch (e) { let errorText = (0, _languageHandler._t)("Failed to re-authenticate due to a homeserver problem"); if (e.errcode === "M_FORBIDDEN" && (e.httpStatus === 401 || e.httpStatus === 403)) { errorText = (0, _languageHandler._t)("Incorrect password"); } this.setState({ busy: false, errorText: errorText }); return; } Lifecycle.hydrateSession(credentials).catch(e => { console.error(e); this.setState({ busy: false, errorText: (0, _languageHandler._t)("Failed to re-authenticate") }); }); }); this.state = { loginView: LOGIN_VIEW.LOADING, keyBackupNeeded: true, // assume we do while we figure it out (see componentDidMount) busy: false, password: "", errorText: "", flows: [] }; } componentDidMount() /*: void*/ { // We've ended up here when we don't need to - navigate to login if (!Lifecycle.isSoftLogout()) { _dispatcher.default.dispatch({ action: "start_login" }); return; } this.initLogin(); const cli = _MatrixClientPeg.MatrixClientPeg.get(); if (cli.isCryptoEnabled()) { cli.countSessionsNeedingBackup().then(remaining => { this.setState({ keyBackupNeeded: remaining > 0 }); }); } } async initLogin() { const queryParams = this.props.realQueryParams; const hasAllParams = queryParams && queryParams['loginToken']; if (hasAllParams) { this.setState({ loginView: LOGIN_VIEW.LOADING }); this.trySsoLogin(); return; } // Note: we don't use the existing Login class because it is heavily flow-based. We don't // care about login flows here, unless it is the single flow we support. const client = _MatrixClientPeg.MatrixClientPeg.get(); const flows = (await client.loginFlows()).flows; const loginViews = flows.map(f => FLOWS_TO_VIEWS[f.type]); const chosenView = loginViews.filter(f => !!f)[0] || LOGIN_VIEW.UNSUPPORTED; this.setState({ flows, loginView: chosenView }); } async trySsoLogin() { this.setState({ busy: true }); const hsUrl = localStorage.getItem(_BasePlatform.SSO_HOMESERVER_URL_KEY); const isUrl = localStorage.getItem(_BasePlatform.SSO_ID_SERVER_URL_KEY) || _MatrixClientPeg.MatrixClientPeg.get().getIdentityServerUrl(); const loginType = "m.login.token"; const loginParams = { token: this.props.realQueryParams['loginToken'], device_id: _MatrixClientPeg.MatrixClientPeg.get().getDeviceId() }; let credentials = null; try { credentials = await (0, _Login.sendLoginRequest)(hsUrl, isUrl, loginType, loginParams); } catch (e) { console.error(e); this.setState({ busy: false, loginView: LOGIN_VIEW.UNSUPPORTED }); return; } Lifecycle.hydrateSession(credentials).then(() => { if (this.props.onTokenLoginCompleted) this.props.onTokenLoginCompleted(); }).catch(e => { console.error(e); this.setState({ busy: false, loginView: LOGIN_VIEW.UNSUPPORTED }); }); } renderSignInSection() { if (this.state.loginView === LOGIN_VIEW.LOADING) { const Spinner = sdk.getComponent("elements.Spinner"); return /*#__PURE__*/_react.default.createElement(Spinner, null); } let introText = null; // null is translated to something area specific in this function if (this.state.keyBackupNeeded) { introText = (0, _languageHandler._t)("Regain access to your account and recover encryption keys stored in this session. " + "Without them, you won’t be able to read all of your secure messages in any session."); } if (this.state.loginView === LOGIN_VIEW.PASSWORD) { const Field = sdk.getComponent("elements.Field"); const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); let error = null; if (this.state.errorText) { error = /*#__PURE__*/_react.default.createElement("span", { className: "mx_Login_error" }, this.state.errorText); } if (!introText) { introText = (0, _languageHandler._t)("Enter your password to sign in and regain access to your account."); } // else we already have a message and should use it (key backup warning) return /*#__PURE__*/_react.default.createElement("form", { onSubmit: this.onPasswordLogin }, /*#__PURE__*/_react.default.createElement("p", null, introText), error, /*#__PURE__*/_react.default.createElement(Field, { type: "password", label: (0, _languageHandler._t)("Password"), onChange: this.onPasswordChange, value: this.state.password, disabled: this.state.busy }), /*#__PURE__*/_react.default.createElement(AccessibleButton, { onClick: this.onPasswordLogin, kind: "primary", type: "submit", disabled: this.state.busy }, (0, _languageHandler._t)("Sign In")), /*#__PURE__*/_react.default.createElement(AccessibleButton, { onClick: this.onForgotPassword, kind: "link" }, (0, _languageHandler._t)("Forgotten your password?"))); } if (this.state.loginView === LOGIN_VIEW.SSO || this.state.loginView === LOGIN_VIEW.CAS) { if (!introText) { introText = (0, _languageHandler._t)("Sign in and regain access to your account."); } // else we already have a message and should use it (key backup warning) const loginType = this.state.loginView === LOGIN_VIEW.CAS ? "cas" : "sso"; const flow = this.state.flows.find(flow => flow.type === "m.login." + loginType); return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, introText), /*#__PURE__*/_react.default.createElement(_SSOButtons.default, { matrixClient: _MatrixClientPeg.MatrixClientPeg.get(), flow: flow, loginType: loginType, fragmentAfterLogin: this.props.fragmentAfterLogin, primary: !this.state.flows.find(flow => flow.type === "m.login.password") })); } // Default: assume unsupported/error return /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("You cannot sign in to your account. Please contact your " + "homeserver admin for more information.")); } render() { const AuthHeader = sdk.getComponent("auth.AuthHeader"); const AuthBody = sdk.getComponent("auth.AuthBody"); const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); return /*#__PURE__*/_react.default.createElement(_AuthPage.default, null, /*#__PURE__*/_react.default.createElement(AuthHeader, null), /*#__PURE__*/_react.default.createElement(AuthBody, null, /*#__PURE__*/_react.default.createElement("h2", null, (0, _languageHandler._t)("You're signed out")), /*#__PURE__*/_react.default.createElement("h3", null, (0, _languageHandler._t)("Sign in")), /*#__PURE__*/_react.default.createElement("div", null, this.renderSignInSection()), /*#__PURE__*/_react.default.createElement("h3", null, (0, _languageHandler._t)("Clear personal data")), /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("Warning: Your personal data (including encryption keys) is still stored " + "in this session. Clear it if you're finished using this session, or want to sign " + "in to another account.")), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(AccessibleButton, { onClick: this.onClearAll, kind: "danger" }, (0, _languageHandler._t)("Clear all data"))))); } }, _temp)) || _class); exports.default = SoftLogout; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3N0cnVjdHVyZXMvYXV0aC9Tb2Z0TG9nb3V0LnRzeCJdLCJuYW1lcyI6WyJMT0dJTl9WSUVXIiwiTE9BRElORyIsIlBBU1NXT1JEIiwiQ0FTIiwiU1NPIiwiVU5TVVBQT1JURUQiLCJGTE9XU19UT19WSUVXUyIsIlNvZnRMb2dvdXQiLCJSZWFjdCIsIkNvbXBvbmVudCIsImNvbnN0cnVjdG9yIiwicHJvcHMiLCJDb25maXJtV2lwZURldmljZURpYWxvZyIsInNkayIsImdldENvbXBvbmVudCIsIk1vZGFsIiwiY3JlYXRlVHJhY2tlZERpYWxvZyIsIm9uRmluaXNoZWQiLCJ3aXBlRGF0YSIsImNvbnNvbGUiLCJsb2ciLCJMaWZlY3ljbGUiLCJsb2dvdXQiLCJldiIsInNldFN0YXRlIiwicGFzc3dvcmQiLCJ0YXJnZXQiLCJ2YWx1ZSIsImRpcyIsImRpc3BhdGNoIiwiYWN0aW9uIiwicHJldmVudERlZmF1bHQiLCJzdG9wUHJvcGFnYXRpb24iLCJidXN5IiwiaHNVcmwiLCJNYXRyaXhDbGllbnRQZWciLCJnZXQiLCJnZXRIb21lc2VydmVyVXJsIiwiaXNVcmwiLCJnZXRJZGVudGl0eVNlcnZlclVybCIsImxvZ2luVHlwZSIsImxvZ2luUGFyYW1zIiwiaWRlbnRpZmllciIsInR5cGUiLCJ1c2VyIiwiZ2V0VXNlcklkIiwic3RhdGUiLCJkZXZpY2VfaWQiLCJnZXREZXZpY2VJZCIsImNyZWRlbnRpYWxzIiwiZSIsImVycm9yVGV4dCIsImVycmNvZGUiLCJodHRwU3RhdHVzIiwiaHlkcmF0ZVNlc3Npb24iLCJjYXRjaCIsImVycm9yIiwibG9naW5WaWV3Iiwia2V5QmFja3VwTmVlZGVkIiwiZmxvd3MiLCJjb21wb25lbnREaWRNb3VudCIsImlzU29mdExvZ291dCIsImluaXRMb2dpbiIsImNsaSIsImlzQ3J5cHRvRW5hYmxlZCIsImNvdW50U2Vzc2lvbnNOZWVkaW5nQmFja3VwIiwidGhlbiIsInJlbWFpbmluZyIsInF1ZXJ5UGFyYW1zIiwicmVhbFF1ZXJ5UGFyYW1zIiwiaGFzQWxsUGFyYW1zIiwidHJ5U3NvTG9naW4iLCJjbGllbnQiLCJsb2dpbkZsb3dzIiwibG9naW5WaWV3cyIsIm1hcCIsImYiLCJjaG9zZW5WaWV3IiwiZmlsdGVyIiwibG9jYWxTdG9yYWdlIiwiZ2V0SXRlbSIsIlNTT19IT01FU0VSVkVSX1VSTF9LRVkiLCJTU09fSURfU0VSVkVSX1VSTF9LRVkiLCJ0b2tlbiIsIm9uVG9rZW5Mb2dpbkNvbXBsZXRlZCIsInJlbmRlclNpZ25JblNlY3Rpb24iLCJTcGlubmVyIiwiaW50cm9UZXh0IiwiRmllbGQiLCJBY2Nlc3NpYmxlQnV0dG9uIiwib25QYXNzd29yZExvZ2luIiwib25QYXNzd29yZENoYW5nZSIsIm9uRm9yZ290UGFzc3dvcmQiLCJmbG93IiwiZmluZCIsImZyYWdtZW50QWZ0ZXJMb2dpbiIsInJlbmRlciIsIkF1dGhIZWFkZXIiLCJBdXRoQm9keSIsIm9uQ2xlYXJBbGwiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFnQkE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFFQSxNQUFNQSxVQUFVLEdBQUc7QUFDZkMsRUFBQUEsT0FBTyxFQUFFLENBRE07QUFFZkMsRUFBQUEsUUFBUSxFQUFFLENBRks7QUFHZkMsRUFBQUEsR0FBRyxFQUFFLENBSFU7QUFHUDtBQUNSQyxFQUFBQSxHQUFHLEVBQUUsQ0FKVTtBQUtmQyxFQUFBQSxXQUFXLEVBQUU7QUFMRSxDQUFuQjtBQVFBLE1BQU1DLGNBQWMsR0FBRztBQUNuQixzQkFBb0JOLFVBQVUsQ0FBQ0UsUUFEWjtBQUVuQixpQkFBZUYsVUFBVSxDQUFDRyxHQUZQO0FBR25CLGlCQUFlSCxVQUFVLENBQUNJO0FBSFAsQ0FBdkI7SUEyQnFCRyxVLFdBRHBCLGdEQUFxQiw0QkFBckIsQyx5QkFBRCxNQUNxQkEsVUFEckIsU0FDd0NDLGVBQU1DO0FBRDlDO0FBQ3dF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Q0MsWUFBSixDQUFpQixlQUFqQixDQUFqQjtBQUNBLFVBQU0yRSxnQkFBZ0IsR0FBRzVFLEdBQUcsQ0FBQ0MsWUFBSixDQUFpQiwyQkFBakIsQ0FBekI7QUFFQSx3QkFDSSw2QkFBQyxpQkFBRCxxQkFDSSw2QkFBQyxVQUFELE9BREosZUFFSSw2QkFBQyxRQUFELHFCQUNJLHlDQUNLLHlCQUFHLG1CQUFILENBREwsQ0FESixlQUtJLHlDQUFLLHlCQUFHLFNBQUgsQ0FBTCxDQUxKLGVBTUksMENBQ0ssS0FBS3VFLG1CQUFMLEVBREwsQ0FOSixlQVVJLHlDQUFLLHlCQUFHLHFCQUFILENBQUwsQ0FWSixlQVdJLHdDQUNLLHlCQUNHLDZFQUNBLG1GQURBLEdBRUEsd0JBSEgsQ0FETCxDQVhKLGVBa0JJLHVEQUNJLDZCQUFDLGdCQUFEO0FBQWtCLE1BQUEsT0FBTyxFQUFFLEtBQUtjLFVBQWhDO0FBQTRDLE1BQUEsSUFBSSxFQUFDO0FBQWpELE9BQ0sseUJBQUcsZ0JBQUgsQ0FETCxDQURKLENBbEJKLENBRkosQ0FESjtBQTZCSDs7QUFqUW1FLEMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMTktMjAyMSBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiovXG5cbmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQge190fSBmcm9tICcuLi8uLi8uLi9sYW5ndWFnZUhhbmRsZXInO1xuaW1wb3J0ICogYXMgc2RrIGZyb20gJy4uLy4uLy4uL2luZGV4JztcbmltcG9ydCBkaXMgZnJvbSAnLi4vLi4vLi4vZGlzcGF0Y2hlci9kaXNwYXRjaGVyJztcbmltcG9ydCAqIGFzIExpZmVjeWNsZSBmcm9tICcuLi8uLi8uLi9MaWZlY3ljbGUnO1xuaW1wb3J0IE1vZGFsIGZyb20gJy4uLy4uLy4uL01vZGFsJztcbmltcG9ydCB7TWF0cml4Q2xpZW50UGVnfSBmcm9tIFwiLi4vLi4vLi4vTWF0cml4Q2xpZW50UGVnXCI7XG5pbXBvcnQge0lTU09GbG93LCBMb2dpbkZsb3csIHNlbmRMb2dpblJlcXVlc3R9IGZyb20gXCIuLi8uLi8uLi9Mb2dpblwiO1xuaW1wb3J0IEF1dGhQYWdlIGZyb20gXCIuLi8uLi92aWV3cy9hdXRoL0F1dGhQYWdlXCI7XG5pbXBvcnQge1NTT19IT01FU0VSVkVSX1VSTF9LRVksIFNTT19JRF9TRVJWRVJfVVJMX0tFWX0gZnJvbSBcIi4uLy4uLy4uL0Jhc2VQbGF0Zm9ybVwiO1xuaW1wb3J0IFNTT0J1dHRvbnMgZnJvbSBcIi4uLy4uL3ZpZXdzL2VsZW1lbnRzL1NTT0J1dHRvbnNcIjtcbmltcG9ydCB7cmVwbGFjZWFibGVDb21wb25lbnR9IGZyb20gXCIuLi8uLi8uLi91dGlscy9yZXBsYWNlYWJsZUNvbXBvbmVudFwiO1xuXG5jb25zdCBMT0dJTl9WSUVXID0ge1xuICAgIExPQURJTkc6IDEsXG4gICAgUEFTU1dPUkQ6IDIsXG4gICAgQ0FTOiAzLCAvLyBTU08sIGJ1dCBvbGRcbiAgICBTU086IDQsXG4gICAgVU5TVVBQT1JURUQ6IDUsXG59O1xuXG5jb25zdCBGTE9XU19UT19WSUVXUyA9IHtcbiAgICBcIm0ubG9naW4ucGFzc3dvcmRcIjogTE9HSU5fVklFVy5QQVNTV09SRCxcbiAgICBcIm0ubG9naW4uY2FzXCI6IExPR0lOX1ZJRVcuQ0FTLFxuICAgIFwibS5sb2dpbi5zc29cIjogTE9HSU5fVklFVy5TU08sXG59O1xuXG5pbnRlcmZhY2UgSVByb3BzIHtcbiAgICAvLyBRdWVyeSBwYXJhbWV0ZXJzIGZyb20gTWF0cml4Q2hhdFxuICAgIHJlYWxRdWVyeVBhcmFtczoge1xuICAgICAgICBsb2dpblRva2VuPzogc3RyaW5nO1xuICAgIH07XG4gICAgZnJhZ21lbnRBZnRlckxvZ2luPzogc3RyaW5nO1xuXG4gICAgLy8gQ2FsbGVkIHdoZW4gdGhlIFNTTyBsb2dpbiBjb21wbGV0ZXNcbiAgICBvblRva2VuTG9naW5Db21wbGV0ZWQ6ICgpID0+IHZvaWQsXG59XG5cbmludGVyZmFjZSBJU3RhdGUge1xuICAgIGxvZ2luVmlldzogbnVtYmVyO1xuICAgIGtleUJhY2t1cE5lZWRlZDogYm9vbGVhbjtcbiAgICBidXN5OiBib29sZWFuO1xuICAgIHBhc3N3b3JkOiBzdHJpbmc7XG4gICAgZXJyb3JUZXh0OiBzdHJpbmc7XG4gICAgZmxvd3M6IExvZ2luRmxvd1tdO1xufVxuXG5AcmVwbGFjZWFibGVDb21wb25lbnQoXCJzdHJ1Y3R1cmVzLmF1dGguU29mdExvZ291dFwiKVxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU29mdExvZ291dCBleHRlbmRzIFJlYWN0LkNvbXBvbmVudDxJUHJvcHMsIElTdGF0ZT4ge1xuICAgIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgICAgIHN1cGVyKHByb3BzKTtcblxuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAgbG9naW5WaWV3OiBMT0dJTl9WSUVXLkxPQURJTkcsXG4gICAgICAgICAgICBrZXlCYWNrdXBOZWVkZWQ6IHRydWUsIC8vIGFzc3VtZSB3ZSBkbyB3aGlsZSB3ZSBmaWd1cmUgaXQgb3V0IChzZWUgY29tcG9uZW50RGlkTW91bnQpXG4gICAgICAgICAgICBidXN5OiBmYWxzZSxcbiAgICAgICAgICAgIHBhc3N3b3JkOiBcIlwiLFxuICAgICAgICAgICAgZXJyb3JUZXh0OiBcIlwiLFxuICAgICAgICAgICAgZmxvd3M6IFtdLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGNvbXBvbmVudERpZE1vdW50KCk6IHZvaWQge1xuICAgICAgICAvLyBXZSd2ZSBlbmRlZCB1cCBoZXJlIHdoZW4gd2UgZG9uJ3QgbmVlZCB0byAtIG5hdmlnYXRlIHRvIGxvZ2luXG4gICAgICAgIGlmICghTGlmZWN5Y2xlLmlzU29mdExvZ291dCgpKSB7XG4gICAgICAgICAgICBkaXMuZGlzcGF0Y2goe2FjdGlvbjogXCJzdGFydF9sb2dpblwifSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmluaXRMb2dpbigpO1xuXG4gICAgICAgIGNvbnN0IGNsaSA9IE1hdHJpeENsaWVudFBlZy5nZXQoKTtcbiAgICAgICAgaWYgKGNsaS5pc0NyeXB0b0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgY2xpLmNvdW50U2Vzc2lvbnNOZWVkaW5nQmFja3VwKCkudGhlbihyZW1haW5pbmcgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoeyBrZXlCYWNrdXBOZWVkZWQ6IHJlbWFpbmluZyA+IDAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG9uQ2xlYXJBbGwgPSAoKSA9PiB7XG4gICAgICAgIGNvbnN0IENvbmZpcm1XaXBlRGV2aWNlRGlhbG9nID0gc2RrLmdldENvbXBvbmVudCgnZGlhbG9ncy5Db25maXJtV2lwZURldmljZURpYWxvZycpO1xuICAgICAgICBNb2RhbC5jcmVhdGVUcmFja2VkRGlhbG9nKCdDbGVhciBEYXRhJywgJ1NvZnQgTG9nb3V0JywgQ29uZmlybVdpcGVEZXZpY2VEaWFsb2csIHtcbiAgICAgICAgICAgIG9uRmluaXNoZWQ6ICh3aXBlRGF0YSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghd2lwZURhdGEpIHJldHVybjtcblxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiQ2xlYXJpbmcgZGF0YSBmcm9tIHNvZnQtbG9nZ2VkLW91dCBzZXNzaW9uXCIpO1xuICAgICAgICAgICAgICAgIExpZmVjeWNsZS5sb2dvdXQoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBwcml2YXRlIGFzeW5jIGluaXRMb2dpbigpIHtcbiAgICAgICAgY29uc3QgcXVlcnlQYXJhbXMgPSB0aGlzLnByb3BzLnJlYWxRdWVyeVBhcmFtcztcbiAgICAgICAgY29uc3QgaGFzQWxsUGFyYW1zID0gcXVlcnlQYXJhbXMgJiYgcXVlcnlQYXJhbXNbJ2xvZ2luVG9rZW4nXTtcbiAgICAgICAgaWYgKGhhc0FsbFBhcmFtcykge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7bG9naW5WaWV3OiBMT0dJTl9WSUVXLkxPQURJTkd9KTtcbiAgICAgICAgICAgIHRoaXMudHJ5U3NvTG9naW4oKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE5vdGU6IHdlIGRvbid0IHVzZSB0aGUgZXhpc3RpbmcgTG9naW4gY2xhc3MgYmVjYXVzZSBpdCBpcyBoZWF2aWx5IGZsb3ctYmFzZWQuIFdlIGRvbid0XG4gICAgICAgIC8vIGNhcmUgYWJvdXQgbG9naW4gZmxvd3MgaGVyZSwgdW5sZXNzIGl0IGlzIHRoZSBzaW5nbGUgZmxvdyB3ZSBzdXBwb3J0LlxuICAgICAgICBjb25zdCBjbGllbnQgPSBNYXRyaXhDbGllbnRQZWcuZ2V0KCk7XG4gICAgICAgIGNvbnN0IGZsb3dzID0gKGF3YWl0IGNsaWVudC5sb2dpbkZsb3dzKCkpLmZsb3dzO1xuICAgICAgICBjb25zdCBsb2dpblZpZXdzID0gZmxvd3MubWFwKGYgPT4gRkxPV1NfVE9fVklFV1NbZi50eXBlXSk7XG5cbiAgICAgICAgY29uc3QgY2hvc2VuVmlldyA9IGxvZ2luVmlld3MuZmlsdGVyKGYgPT4gISFmKVswXSB8fCBMT0dJTl9WSUVXLlVOU1VQUE9SVEVEO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHsgZmxvd3MsIGxvZ2luVmlldzogY2hvc2VuVmlldyB9KTtcbiAgICB9XG5cbiAgICBvblBhc3N3b3JkQ2hhbmdlID0gKGV2KSA9PiB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe3Bhc3N3b3JkOiBldi50YXJnZXQudmFsdWV9KTtcbiAgICB9O1xuXG4gICAgb25Gb3Jnb3RQYXNzd29yZCA9ICgpID0+IHtcbiAgICAgICAgZGlzLmRpc3BhdGNoKHthY3Rpb246ICdzdGFydF9wYXNzd29yZF9yZWNvdmVyeSd9KTtcbiAgICB9O1xuXG4gICAgb25QYXNzd29yZExvZ2luID0gYXN5bmMgKGV2KSA9PiB7XG4gICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGV2LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe2J1c3k6IHRydWV9KTtcblxuICAgICAgICBjb25zdCBoc1VybCA9IE1hdHJpeENsaWVudFBlZy5nZXQoKS5nZXRIb21lc2VydmVyVXJsKCk7XG4gICAgICAgIGNvbnN0IGlzVXJsID0gTWF0cml4Q2xpZW50UGVnLmdldCgpLmdldElkZW50aXR5U2VydmVyVXJsKCk7XG4gICAgICAgIGNvbnN0IGxvZ2luVHlwZSA9IFwibS5sb2dpbi5wYXNzd29yZFwiO1xuICAgICAgICBjb25zdCBsb2dpblBhcmFtcyA9IHtcbiAgICAgICAgICAgIGlkZW50aWZpZXI6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcIm0uaWQudXNlclwiLFxuICAgICAgICAgICAgICAgIHVzZXI6IE1hdHJpeENsaWVudFBlZy5nZXQoKS5nZXRVc2VySWQoKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwYXNzd29yZDogdGhpcy5zdGF0ZS5wYXNzd29yZCxcbiAgICAgICAgICAgIGRldmljZV9pZDogTWF0cml4Q2xpZW50UGVnLmdldCgpLmdldERldmljZUlkKCksXG4gICAgICAgIH07XG5cbiAgICAgICAgbGV0IGNyZWRlbnRpYWxzID0gbnVsbDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNyZWRlbnRpYWxzID0gYXdhaXQgc2VuZExvZ2luUmVxdWVzdChoc1VybCwgaXNVcmwsIGxvZ2luVHlwZSwgbG9naW5QYXJhbXMpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBsZXQgZXJyb3JUZXh0ID0gX3QoXCJGYWlsZWQgdG8gcmUtYXV0aGVudGljYXRlIGR1ZSB0byBhIGhvbWVzZXJ2ZXIgcHJvYmxlbVwiKTtcbiAgICAgICAgICAgIGlmIChlLmVycmNvZGUgPT09IFwiTV9GT1JCSURERU5cIiAmJiAoZS5odHRwU3RhdHVzID09PSA0MDEgfHwgZS5odHRwU3RhdHVzID09PSA0MDMpKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JUZXh0ID0gX3QoXCJJbmNvcnJlY3QgcGFzc3dvcmRcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgIGJ1c3k6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGVycm9yVGV4dDogZXJyb3JUZXh0LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBMaWZlY3ljbGUuaHlkcmF0ZVNlc3Npb24oY3JlZGVudGlhbHMpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7YnVzeTogZmFsc2UsIGVycm9yVGV4dDogX3QoXCJGYWlsZWQgdG8gcmUtYXV0aGVudGljYXRlXCIpfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBhc3luYyB0cnlTc29Mb2dpbigpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7YnVzeTogdHJ1ZX0pO1xuXG4gICAgICAgIGNvbnN0IGhzVXJsID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oU1NPX0hPTUVTRVJWRVJfVVJMX0tFWSk7XG4gICAgICAgIGNvbnN0IGlzVXJsID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oU1NPX0lEX1NFUlZFUl9VUkxfS0VZKSB8fCBNYXRyaXhDbGllbnRQZWcuZ2V0KCkuZ2V0SWRlbnRpdHlTZXJ2ZXJVcmwoKTtcbiAgICAgICAgY29uc3QgbG9naW5UeXBlID0gXCJtLmxvZ2luLnRva2VuXCI7XG4gICAgICAgIGNvbnN0IGxvZ2luUGFyYW1zID0ge1xuICAgICAgICAgICAgdG9rZW46IHRoaXMucHJvcHMucmVhbFF1ZXJ5UGFyYW1zWydsb2dpblRva2VuJ10sXG4gICAgICAgICAgICBkZXZpY2VfaWQ6IE1hdHJpeENsaWVudFBlZy5nZXQoKS5nZXREZXZpY2VJZCgpLFxuICAgICAgICB9O1xuXG4gICAgICAgIGxldCBjcmVkZW50aWFscyA9IG51bGw7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjcmVkZW50aWFscyA9IGF3YWl0IHNlbmRMb2dpblJlcXVlc3QoaHNVcmwsIGlzVXJsLCBsb2dpblR5cGUsIGxvZ2luUGFyYW1zKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe2J1c3k6IGZhbHNlLCBsb2dpblZpZXc6IExPR0lOX1ZJRVcuVU5TVVBQT1JURUR9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIExpZmVjeWNsZS5oeWRyYXRlU2Vzc2lvbihjcmVkZW50aWFscykudGhlbigoKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5wcm9wcy5vblRva2VuTG9naW5Db21wbGV0ZWQpIHRoaXMucHJvcHMub25Ub2tlbkxvZ2luQ29tcGxldGVkKCk7XG4gICAgICAgIH0pLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7YnVzeTogZmFsc2UsIGxvZ2luVmlldzogTE9HSU5fVklFVy5VTlNVUFBPUlRFRH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJlbmRlclNpZ25JblNlY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLmxvZ2luVmlldyA9PT0gTE9HSU5fVklFVy5MT0FESU5HKSB7XG4gICAgICAgICAgICBjb25zdCBTcGlubmVyID0gc2RrLmdldENvbXBvbmVudChcImVsZW1lbnRzLlNwaW5uZXJcIik7XG4gICAgICAgICAgICByZXR1cm4gPFNwaW5uZXIgLz47XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgaW50cm9UZXh0ID0gbnVsbDsgLy8gbnVsbCBpcyB0cmFuc2xhdGVkIHRvIHNvbWV0aGluZyBhcmVhIHNwZWNpZmljIGluIHRoaXMgZnVuY3Rpb25cbiAgICAgICAgaWYgKHRoaXMuc3RhdGUua2V5QmFja3VwTmVlZGVkKSB7XG4gICAgICAgICAgICBpbnRyb1RleHQgPSBfdChcbiAgICAgICAgICAgICAgICBcIlJlZ2FpbiBhY2Nlc3MgdG8geW91ciBhY2NvdW50IGFuZCByZWNvdmVyIGVuY3J5cHRpb24ga2V5cyBzdG9yZWQgaW4gdGhpcyBzZXNzaW9uLiBcIiArXG4gICAgICAgICAgICAgICAgXCJXaXRob3V0IHRoZW0sIHlvdSB3b27igJl0IGJlIGFibGUgdG8gcmVhZCBhbGwgb2YgeW91ciBzZWN1cmUgbWVzc2FnZXMgaW4gYW55IHNlc3Npb24uXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuc3RhdGUubG9naW5WaWV3ID09PSBMT0dJTl9WSUVXLlBBU1NXT1JEKSB7XG4gICAgICAgICAgICBjb25zdCBGaWVsZCA9IHNkay5nZXRDb21wb25lbnQoXCJlbGVtZW50cy5GaWVsZFwiKTtcbiAgICAgICAgICAgIGNvbnN0IEFjY2Vzc2libGVCdXR0b24gPSBzZGsuZ2V0Q29tcG9uZW50KCdlbGVtZW50cy5BY2Nlc3NpYmxlQnV0dG9uJyk7XG5cbiAgICAgICAgICAgIGxldCBlcnJvciA9IG51bGw7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5lcnJvclRleHQpIHtcbiAgICAgICAgICAgICAgICBlcnJvciA9IDxzcGFuIGNsYXNzTmFtZT0nbXhfTG9naW5fZXJyb3InPnt0aGlzLnN0YXRlLmVycm9yVGV4dH08L3NwYW4+O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWludHJvVGV4dCkge1xuICAgICAgICAgICAgICAgIGludHJvVGV4dCA9IF90KFwiRW50ZXIgeW91ciBwYXNzd29yZCB0byBzaWduIGluIGFuZCByZWdhaW4gYWNjZXNzIHRvIHlvdXIgYWNjb3VudC5cIik7XG4gICAgICAgICAgICB9IC8vIGVsc2Ugd2UgYWxyZWFkeSBoYXZlIGEgbWVzc2FnZSBhbmQgc2hvdWxkIHVzZSBpdCAoa2V5IGJhY2t1cCB3YXJuaW5nKVxuXG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIDxmb3JtIG9uU3VibWl0PXt0aGlzLm9uUGFzc3dvcmRMb2dpbn0+XG4gICAgICAgICAgICAgICAgICAgIDxwPntpbnRyb1RleHR9PC9wPlxuICAgICAgICAgICAgICAgICAgICB7ZXJyb3J9XG4gICAgICAgICAgICAgICAgICAgIDxGaWVsZFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cInBhc3N3b3JkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsPXtfdChcIlBhc3N3b3JkXCIpfVxuICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e3RoaXMub25QYXNzd29yZENoYW5nZX1cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPXt0aGlzLnN0YXRlLnBhc3N3b3JkfVxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ9e3RoaXMuc3RhdGUuYnVzeX1cbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgPEFjY2Vzc2libGVCdXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9e3RoaXMub25QYXNzd29yZExvZ2lufVxuICAgICAgICAgICAgICAgICAgICAgICAga2luZD1cInByaW1hcnlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cInN1Ym1pdFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlZD17dGhpcy5zdGF0ZS5idXN5fVxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICB7X3QoXCJTaWduIEluXCIpfVxuICAgICAgICAgICAgICAgICAgICA8L0FjY2Vzc2libGVCdXR0b24+XG4gICAgICAgICAgICAgICAgICAgIDxBY2Nlc3NpYmxlQnV0dG9uIG9uQ2xpY2s9e3RoaXMub25Gb3Jnb3RQYXNzd29yZH0ga2luZD1cImxpbmtcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIHtfdChcIkZvcmdvdHRlbiB5b3VyIHBhc3N3b3JkP1wiKX1cbiAgICAgICAgICAgICAgICAgICAgPC9BY2Nlc3NpYmxlQnV0dG9uPlxuICAgICAgICAgICAgICAgIDwvZm9ybT5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5zdGF0ZS5sb2dpblZpZXcgPT09IExPR0lOX1ZJRVcuU1NPIHx8IHRoaXMuc3RhdGUubG9naW5WaWV3ID09PSBMT0dJTl9WSUVXLkNBUykge1xuICAgICAgICAgICAgaWYgKCFpbnRyb1RleHQpIHtcbiAgICAgICAgICAgICAgICBpbnRyb1RleHQgPSBfdChcIlNpZ24gaW4gYW5kIHJlZ2FpbiBhY2Nlc3MgdG8geW91ciBhY2NvdW50LlwiKTtcbiAgICAgICAgICAgIH0gLy8gZWxzZSB3ZSBhbHJlYWR5IGhhdmUgYSBtZXNzYWdlIGFuZCBzaG91bGQgdXNlIGl0IChrZXkgYmFja3VwIHdhcm5pbmcpXG5cbiAgICAgICAgICAgIGNvbnN0IGxvZ2luVHlwZSA9IHRoaXMuc3RhdGUubG9naW5WaWV3ID09PSBMT0dJTl9WSUVXLkNBUyA/IFwiY2FzXCIgOiBcInNzb1wiO1xuICAgICAgICAgICAgY29uc3QgZmxvdyA9IHRoaXMuc3RhdGUuZmxvd3MuZmluZChmbG93ID0+IGZsb3cudHlwZSA9PT0gXCJtLmxvZ2luLlwiICsgbG9naW5UeXBlKSBhcyBJU1NPRmxvdztcblxuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgICAgICAgICA8cD57aW50cm9UZXh0fTwvcD5cbiAgICAgICAgICAgICAgICAgICAgPFNTT0J1dHRvbnNcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdHJpeENsaWVudD17TWF0cml4Q2xpZW50UGVnLmdldCgpfVxuICAgICAgICAgICAgICAgICAgICAgICAgZmxvdz17Zmxvd31cbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2luVHlwZT17bG9naW5UeXBlfVxuICAgICAgICAgICAgICAgICAgICAgICAgZnJhZ21lbnRBZnRlckxvZ2luPXt0aGlzLnByb3BzLmZyYWdtZW50QWZ0ZXJMb2dpbn1cbiAgICAgICAgICAgICAgICAgICAgICAgIHByaW1hcnk9eyF0aGlzLnN0YXRlLmZsb3dzLmZpbmQoZmxvdyA9PiBmbG93LnR5cGUgPT09IFwibS5sb2dpbi5wYXNzd29yZFwiKX1cbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZWZhdWx0OiBhc3N1bWUgdW5zdXBwb3J0ZWQvZXJyb3JcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxwPlxuICAgICAgICAgICAgICAgIHtfdChcbiAgICAgICAgICAgICAgICAgICAgXCJZb3UgY2Fubm90IHNpZ24gaW4gdG8geW91ciBhY2NvdW50LiBQbGVhc2UgY29udGFjdCB5b3VyIFwiICtcbiAgICAgICAgICAgICAgICAgICAgXCJob21lc2VydmVyIGFkbWluIGZvciBtb3JlIGluZm9ybWF0aW9uLlwiLFxuICAgICAgICAgICAgICAgICl9XG4gICAgICAgICAgICA8L3A+XG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcmVuZGVyKCkge1xuICAgICAgICBjb25zdCBBdXRoSGVhZGVyID0gc2RrLmdldENvbXBvbmVudChcImF1dGguQXV0aEhlYWRlclwiKTtcbiAgICAgICAgY29uc3QgQXV0aEJvZHkgPSBzZGsuZ2V0Q29tcG9uZW50KFwiYXV0aC5BdXRoQm9keVwiKTtcbiAgICAgICAgY29uc3QgQWNjZXNzaWJsZUJ1dHRvbiA9IHNkay5nZXRDb21wb25lbnQoJ2VsZW1lbnRzLkFjY2Vzc2libGVCdXR0b24nKTtcblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgPEF1dGhQYWdlPlxuICAgICAgICAgICAgICAgIDxBdXRoSGVhZGVyIC8+XG4gICAgICAgICAgICAgICAgPEF1dGhCb2R5PlxuICAgICAgICAgICAgICAgICAgICA8aDI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7X3QoXCJZb3UncmUgc2lnbmVkIG91dFwiKX1cbiAgICAgICAgICAgICAgICAgICAgPC9oMj5cblxuICAgICAgICAgICAgICAgICAgICA8aDM+e190KFwiU2lnbiBpblwiKX08L2gzPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAge3RoaXMucmVuZGVyU2lnbkluU2VjdGlvbigpfVxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgICAgICA8aDM+e190KFwiQ2xlYXIgcGVyc29uYWwgZGF0YVwiKX08L2gzPlxuICAgICAgICAgICAgICAgICAgICA8cD5cbiAgICAgICAgICAgICAgICAgICAgICAgIHtfdChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIldhcm5pbmc6IFlvdXIgcGVyc29uYWwgZGF0YSAoaW5jbHVkaW5nIGVuY3J5cHRpb24ga2V5cykgaXMgc3RpbGwgc3RvcmVkIFwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImluIHRoaXMgc2Vzc2lvbi4gQ2xlYXIgaXQgaWYgeW91J3JlIGZpbmlzaGVkIHVzaW5nIHRoaXMgc2Vzc2lvbiwgb3Igd2FudCB0byBzaWduIFwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImluIHRvIGFub3RoZXIgYWNjb3VudC5cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICl9XG4gICAgICAgICAgICAgICAgICAgIDwvcD5cbiAgICAgICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxBY2Nlc3NpYmxlQnV0dG9uIG9uQ2xpY2s9e3RoaXMub25DbGVhckFsbH0ga2luZD1cImRhbmdlclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtfdChcIkNsZWFyIGFsbCBkYXRhXCIpfVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9BY2Nlc3NpYmxlQnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L0F1dGhCb2R5PlxuICAgICAgICAgICAgPC9BdXRoUGFnZT5cbiAgICAgICAgKTtcbiAgICB9XG59XG4iXX0=