matrix-react-sdk
Version:
SDK for matrix.org using React
308 lines (296 loc) • 44.3 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _matrix = require("matrix-js-sdk/src/matrix");
var _Modal = _interopRequireDefault(require("./Modal"));
var _languageHandler = require("./languageHandler");
var _IdentityAuthClient = _interopRequireDefault(require("./IdentityAuthClient"));
var _InteractiveAuthEntryComponents = require("./components/views/auth/InteractiveAuthEntryComponents");
var _InteractiveAuthDialog = _interopRequireDefault(require("./components/views/dialogs/InteractiveAuthDialog"));
/*
Copyright 2024 New Vector Ltd.
Copyright 2019 The Matrix.org Foundation C.I.C.
Copyright 2017 Vector Creations Ltd
Copyright 2016 OpenMarket Ltd
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
function getIdServerDomain(matrixClient) {
const idBaseUrl = matrixClient.getIdentityServerUrl(true);
if (!idBaseUrl) {
throw new _languageHandler.UserFriendlyError("settings|general|identity_server_not_set");
}
return idBaseUrl;
}
// IThreepid modified stripping validated_at and added_at as they aren't necessary for our UI
/**
* Allows a user to add a third party identifier to their homeserver and,
* optionally, the identity servers.
*
* This involves getting an email token from the identity server to "prove" that
* the client owns the given email address, which is then passed to the
* add threepid API on the homeserver.
*
* Diagrams of the intended API flows here are available at:
*
* https://gist.github.com/jryans/839a09bf0c5a70e2f36ed990d50ed928
*/
class AddThreepid {
constructor(matrixClient) {
(0, _defineProperty2.default)(this, "sessionId", void 0);
(0, _defineProperty2.default)(this, "submitUrl", void 0);
(0, _defineProperty2.default)(this, "bind", false);
(0, _defineProperty2.default)(this, "clientSecret", void 0);
/**
* @param {{type: string, session?: string}} auth UI auth object
* @return {Promise<Object>} Response from /3pid/add call (in current spec, an empty object)
*/
(0, _defineProperty2.default)(this, "makeAddThreepidOnlyRequest", auth => {
return this.matrixClient.addThreePidOnly({
sid: this.sessionId,
client_secret: this.clientSecret,
auth: auth ?? undefined
});
});
this.matrixClient = matrixClient;
this.clientSecret = matrixClient.generateClientSecret();
}
/**
* Attempt to add an email threepid to the homeserver.
* This will trigger a side-effect of sending an email to the provided email address.
* @param {string} emailAddress The email address to add
* @return {Promise} Resolves when the email has been sent. Then call checkEmailLinkClicked().
*/
async addEmailAddress(emailAddress) {
try {
const res = await this.matrixClient.requestAdd3pidEmailToken(emailAddress, this.clientSecret, 1);
this.sessionId = res.sid;
return res;
} catch (err) {
if (err instanceof _matrix.MatrixError && err.errcode === "M_THREEPID_IN_USE") {
throw new _languageHandler.UserFriendlyError("settings|general|email_address_in_use", {
cause: err
});
}
// Otherwise, just blurt out the same error
throw err;
}
}
/**
* Attempt to bind an email threepid on the identity server via the homeserver.
* This will trigger a side-effect of sending an email to the provided email address.
* @param {string} emailAddress The email address to add
* @return {Promise} Resolves when the email has been sent. Then call checkEmailLinkClicked().
*/
async bindEmailAddress(emailAddress) {
this.bind = true;
// For separate bind, request a token directly from the IS.
const authClient = new _IdentityAuthClient.default();
const identityAccessToken = (await authClient.getAccessToken()) ?? undefined;
try {
const res = await this.matrixClient.requestEmailToken(emailAddress, this.clientSecret, 1, undefined, identityAccessToken);
this.sessionId = res.sid;
return res;
} catch (err) {
if (err instanceof _matrix.MatrixError && err.errcode === "M_THREEPID_IN_USE") {
throw new _languageHandler.UserFriendlyError("settings|general|email_address_in_use", {
cause: err
});
}
// Otherwise, just blurt out the same error
throw err;
}
}
/**
* Attempt to add a MSISDN threepid to the homeserver.
* This will trigger a side-effect of sending an SMS to the provided phone number.
* @param {string} phoneCountry The ISO 2 letter code of the country to resolve phoneNumber in
* @param {string} phoneNumber The national or international formatted phone number to add
* @return {Promise} Resolves when the text message has been sent. Then call haveMsisdnToken().
*/
async addMsisdn(phoneCountry, phoneNumber) {
try {
const res = await this.matrixClient.requestAdd3pidMsisdnToken(phoneCountry, phoneNumber, this.clientSecret, 1);
this.sessionId = res.sid;
this.submitUrl = res.submit_url;
return res;
} catch (err) {
if (err instanceof _matrix.MatrixError && err.errcode === "M_THREEPID_IN_USE") {
throw new _languageHandler.UserFriendlyError("settings|general|msisdn_in_use", {
cause: err
});
}
// Otherwise, just blurt out the same error
throw err;
}
}
/**
* Attempt to bind a MSISDN threepid on the identity server via the homeserver.
* This will trigger a side-effect of sending an SMS to the provided phone number.
* @param {string} phoneCountry The ISO 2 letter code of the country to resolve phoneNumber in
* @param {string} phoneNumber The national or international formatted phone number to add
* @return {Promise} Resolves when the text message has been sent. Then call haveMsisdnToken().
*/
async bindMsisdn(phoneCountry, phoneNumber) {
this.bind = true;
// For separate bind, request a token directly from the IS.
const authClient = new _IdentityAuthClient.default();
const identityAccessToken = (await authClient.getAccessToken()) ?? undefined;
try {
const res = await this.matrixClient.requestMsisdnToken(phoneCountry, phoneNumber, this.clientSecret, 1, undefined, identityAccessToken);
this.sessionId = res.sid;
return res;
} catch (err) {
if (err instanceof _matrix.MatrixError && err.errcode === "M_THREEPID_IN_USE") {
throw new _languageHandler.UserFriendlyError("settings|general|msisdn_in_use", {
cause: err
});
}
// Otherwise, just blurt out the same error
throw err;
}
}
/**
* Checks if the email link has been clicked by attempting to add the threepid
* @return {Promise} Resolves if the email address was added. Rejects with an object
* with a "message" property which contains a human-readable message detailing why
* the request failed.
*/
async checkEmailLinkClicked() {
try {
if (this.bind) {
const authClient = new _IdentityAuthClient.default();
const identityAccessToken = await authClient.getAccessToken();
if (!identityAccessToken) {
throw new _languageHandler.UserFriendlyError("settings|general|identity_server_no_token");
}
await this.matrixClient.bindThreePid({
sid: this.sessionId,
client_secret: this.clientSecret,
id_server: getIdServerDomain(this.matrixClient),
id_access_token: identityAccessToken
});
} else {
try {
await this.makeAddThreepidOnlyRequest();
// The spec has always required this to use UI auth but synapse briefly
// implemented it without, so this may just succeed and that's OK.
return [true];
} catch (err) {
if (!(err instanceof _matrix.MatrixError) || err.httpStatus !== 401 || !err.data || !err.data.flows) {
// doesn't look like an interactive-auth failure
throw err;
}
const dialogAesthetics = {
[_InteractiveAuthEntryComponents.SSOAuthEntry.PHASE_PREAUTH]: {
title: (0, _languageHandler._t)("auth|uia|sso_title"),
body: (0, _languageHandler._t)("auth|uia|sso_body"),
continueText: (0, _languageHandler._t)("auth|sso"),
continueKind: "primary"
},
[_InteractiveAuthEntryComponents.SSOAuthEntry.PHASE_POSTAUTH]: {
title: (0, _languageHandler._t)("settings|general|confirm_adding_email_title"),
body: (0, _languageHandler._t)("settings|general|confirm_adding_email_body"),
continueText: (0, _languageHandler._t)("action|confirm"),
continueKind: "primary"
}
};
const {
finished
} = _Modal.default.createDialog(_InteractiveAuthDialog.default, {
title: (0, _languageHandler._t)("settings|general|add_email_dialog_title"),
matrixClient: this.matrixClient,
authData: err.data,
makeRequest: this.makeAddThreepidOnlyRequest,
aestheticsForStagePhases: {
[_InteractiveAuthEntryComponents.SSOAuthEntry.LOGIN_TYPE]: dialogAesthetics,
[_InteractiveAuthEntryComponents.SSOAuthEntry.UNSTABLE_LOGIN_TYPE]: dialogAesthetics
}
});
return finished;
}
}
} catch (err) {
if (err instanceof _matrix.HTTPError && err.httpStatus === 401) {
throw new _languageHandler.UserFriendlyError("settings|general|add_email_failed_verification", {
cause: err
});
}
// Otherwise, just blurt out the same error
throw err;
}
return [];
}
/**
* Takes a phone number verification code as entered by the user and validates
* it with the identity server, then if successful, adds the phone number.
* @param {string} msisdnToken phone number verification code as entered by the user
* @return {Promise} Resolves if the phone number was added. Rejects with an object
* with a "message" property which contains a human-readable message detailing why
* the request failed.
*/
async haveMsisdnToken(msisdnToken) {
const authClient = new _IdentityAuthClient.default();
if (this.submitUrl) {
await this.matrixClient.submitMsisdnTokenOtherUrl(this.submitUrl, this.sessionId, this.clientSecret, msisdnToken);
} else if (this.bind) {
await this.matrixClient.submitMsisdnToken(this.sessionId, this.clientSecret, msisdnToken, await authClient.getAccessToken());
} else {
throw new _languageHandler.UserFriendlyError("settings|general|add_msisdn_misconfigured");
}
if (this.bind) {
await this.matrixClient.bindThreePid({
sid: this.sessionId,
client_secret: this.clientSecret,
id_server: getIdServerDomain(this.matrixClient),
id_access_token: await authClient.getAccessToken()
});
return [true];
} else {
try {
await this.makeAddThreepidOnlyRequest();
// The spec has always required this to use UI auth but synapse briefly
// implemented it without, so this may just succeed and that's OK.
return [true];
} catch (err) {
if (!(err instanceof _matrix.MatrixError) || err.httpStatus !== 401 || !err.data || !err.data.flows) {
// doesn't look like an interactive-auth failure
throw err;
}
const dialogAesthetics = {
[_InteractiveAuthEntryComponents.SSOAuthEntry.PHASE_PREAUTH]: {
title: (0, _languageHandler._t)("auth|uia|sso_title"),
body: (0, _languageHandler._t)("settings|general|add_msisdn_confirm_sso_button"),
continueText: (0, _languageHandler._t)("auth|sso"),
continueKind: "primary"
},
[_InteractiveAuthEntryComponents.SSOAuthEntry.PHASE_POSTAUTH]: {
title: (0, _languageHandler._t)("settings|general|add_msisdn_confirm_button"),
body: (0, _languageHandler._t)("settings|general|add_msisdn_confirm_body"),
continueText: (0, _languageHandler._t)("action|confirm"),
continueKind: "primary"
}
};
const {
finished
} = _Modal.default.createDialog(_InteractiveAuthDialog.default, {
title: (0, _languageHandler._t)("settings|general|add_msisdn_dialog_title"),
matrixClient: this.matrixClient,
authData: err.data,
makeRequest: this.makeAddThreepidOnlyRequest,
aestheticsForStagePhases: {
[_InteractiveAuthEntryComponents.SSOAuthEntry.LOGIN_TYPE]: dialogAesthetics,
[_InteractiveAuthEntryComponents.SSOAuthEntry.UNSTABLE_LOGIN_TYPE]: dialogAesthetics
}
});
return finished;
}
}
}
}
exports.default = AddThreepid;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbWF0cml4IiwicmVxdWlyZSIsIl9Nb2RhbCIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfbGFuZ3VhZ2VIYW5kbGVyIiwiX0lkZW50aXR5QXV0aENsaWVudCIsIl9JbnRlcmFjdGl2ZUF1dGhFbnRyeUNvbXBvbmVudHMiLCJfSW50ZXJhY3RpdmVBdXRoRGlhbG9nIiwiZ2V0SWRTZXJ2ZXJEb21haW4iLCJtYXRyaXhDbGllbnQiLCJpZEJhc2VVcmwiLCJnZXRJZGVudGl0eVNlcnZlclVybCIsIlVzZXJGcmllbmRseUVycm9yIiwiQWRkVGhyZWVwaWQiLCJjb25zdHJ1Y3RvciIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJkZWZhdWx0IiwiYXV0aCIsImFkZFRocmVlUGlkT25seSIsInNpZCIsInNlc3Npb25JZCIsImNsaWVudF9zZWNyZXQiLCJjbGllbnRTZWNyZXQiLCJ1bmRlZmluZWQiLCJnZW5lcmF0ZUNsaWVudFNlY3JldCIsImFkZEVtYWlsQWRkcmVzcyIsImVtYWlsQWRkcmVzcyIsInJlcyIsInJlcXVlc3RBZGQzcGlkRW1haWxUb2tlbiIsImVyciIsIk1hdHJpeEVycm9yIiwiZXJyY29kZSIsImNhdXNlIiwiYmluZEVtYWlsQWRkcmVzcyIsImJpbmQiLCJhdXRoQ2xpZW50IiwiSWRlbnRpdHlBdXRoQ2xpZW50IiwiaWRlbnRpdHlBY2Nlc3NUb2tlbiIsImdldEFjY2Vzc1Rva2VuIiwicmVxdWVzdEVtYWlsVG9rZW4iLCJhZGRNc2lzZG4iLCJwaG9uZUNvdW50cnkiLCJwaG9uZU51bWJlciIsInJlcXVlc3RBZGQzcGlkTXNpc2RuVG9rZW4iLCJzdWJtaXRVcmwiLCJzdWJtaXRfdXJsIiwiYmluZE1zaXNkbiIsInJlcXVlc3RNc2lzZG5Ub2tlbiIsImNoZWNrRW1haWxMaW5rQ2xpY2tlZCIsImJpbmRUaHJlZVBpZCIsImlkX3NlcnZlciIsImlkX2FjY2Vzc190b2tlbiIsIm1ha2VBZGRUaHJlZXBpZE9ubHlSZXF1ZXN0IiwiaHR0cFN0YXR1cyIsImRhdGEiLCJmbG93cyIsImRpYWxvZ0Flc3RoZXRpY3MiLCJTU09BdXRoRW50cnkiLCJQSEFTRV9QUkVBVVRIIiwidGl0bGUiLCJfdCIsImJvZHkiLCJjb250aW51ZVRleHQiLCJjb250aW51ZUtpbmQiLCJQSEFTRV9QT1NUQVVUSCIsImZpbmlzaGVkIiwiTW9kYWwiLCJjcmVhdGVEaWFsb2ciLCJJbnRlcmFjdGl2ZUF1dGhEaWFsb2ciLCJhdXRoRGF0YSIsIm1ha2VSZXF1ZXN0IiwiYWVzdGhldGljc0ZvclN0YWdlUGhhc2VzIiwiTE9HSU5fVFlQRSIsIlVOU1RBQkxFX0xPR0lOX1RZUEUiLCJIVFRQRXJyb3IiLCJoYXZlTXNpc2RuVG9rZW4iLCJtc2lzZG5Ub2tlbiIsInN1Ym1pdE1zaXNkblRva2VuT3RoZXJVcmwiLCJzdWJtaXRNc2lzZG5Ub2tlbiIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi9zcmMvQWRkVGhyZWVwaWQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMTkgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cbkNvcHlyaWdodCAyMDE3IFZlY3RvciBDcmVhdGlvbnMgTHRkXG5Db3B5cmlnaHQgMjAxNiBPcGVuTWFya2V0IEx0ZFxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQge1xuICAgIElBZGRUaHJlZVBpZE9ubHlCb2R5LFxuICAgIElBdXRoRGF0YSxcbiAgICBJUmVxdWVzdE1zaXNkblRva2VuUmVzcG9uc2UsXG4gICAgSVJlcXVlc3RUb2tlblJlc3BvbnNlLFxuICAgIE1hdHJpeENsaWVudCxcbiAgICBNYXRyaXhFcnJvcixcbiAgICBIVFRQRXJyb3IsXG4gICAgSVRocmVlcGlkLFxufSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5cbmltcG9ydCBNb2RhbCBmcm9tIFwiLi9Nb2RhbFwiO1xuaW1wb3J0IHsgX3QsIFVzZXJGcmllbmRseUVycm9yIH0gZnJvbSBcIi4vbGFuZ3VhZ2VIYW5kbGVyXCI7XG5pbXBvcnQgSWRlbnRpdHlBdXRoQ2xpZW50IGZyb20gXCIuL0lkZW50aXR5QXV0aENsaWVudFwiO1xuaW1wb3J0IHsgU1NPQXV0aEVudHJ5IH0gZnJvbSBcIi4vY29tcG9uZW50cy92aWV3cy9hdXRoL0ludGVyYWN0aXZlQXV0aEVudHJ5Q29tcG9uZW50c1wiO1xuaW1wb3J0IEludGVyYWN0aXZlQXV0aERpYWxvZywgeyBJbnRlcmFjdGl2ZUF1dGhEaWFsb2dQcm9wcyB9IGZyb20gXCIuL2NvbXBvbmVudHMvdmlld3MvZGlhbG9ncy9JbnRlcmFjdGl2ZUF1dGhEaWFsb2dcIjtcblxuZnVuY3Rpb24gZ2V0SWRTZXJ2ZXJEb21haW4obWF0cml4Q2xpZW50OiBNYXRyaXhDbGllbnQpOiBzdHJpbmcge1xuICAgIGNvbnN0IGlkQmFzZVVybCA9IG1hdHJpeENsaWVudC5nZXRJZGVudGl0eVNlcnZlclVybCh0cnVlKTtcbiAgICBpZiAoIWlkQmFzZVVybCkge1xuICAgICAgICB0aHJvdyBuZXcgVXNlckZyaWVuZGx5RXJyb3IoXCJzZXR0aW5nc3xnZW5lcmFsfGlkZW50aXR5X3NlcnZlcl9ub3Rfc2V0XCIpO1xuICAgIH1cbiAgICByZXR1cm4gaWRCYXNlVXJsO1xufVxuXG5leHBvcnQgdHlwZSBCaW5kaW5nID0ge1xuICAgIGJpbmQ6IGJvb2xlYW47XG4gICAgbGFiZWw6IHN0cmluZztcbiAgICBlcnJvclRpdGxlOiBzdHJpbmc7XG59O1xuXG4vLyBJVGhyZWVwaWQgbW9kaWZpZWQgc3RyaXBwaW5nIHZhbGlkYXRlZF9hdCBhbmQgYWRkZWRfYXQgYXMgdGhleSBhcmVuJ3QgbmVjZXNzYXJ5IGZvciBvdXIgVUlcbmV4cG9ydCB0eXBlIFRoaXJkUGFydHlJZGVudGlmaWVyID0gT21pdDxJVGhyZWVwaWQsIFwidmFsaWRhdGVkX2F0XCIgfCBcImFkZGVkX2F0XCI+O1xuXG4vKipcbiAqIEFsbG93cyBhIHVzZXIgdG8gYWRkIGEgdGhpcmQgcGFydHkgaWRlbnRpZmllciB0byB0aGVpciBob21lc2VydmVyIGFuZCxcbiAqIG9wdGlvbmFsbHksIHRoZSBpZGVudGl0eSBzZXJ2ZXJzLlxuICpcbiAqIFRoaXMgaW52b2x2ZXMgZ2V0dGluZyBhbiBlbWFpbCB0b2tlbiBmcm9tIHRoZSBpZGVudGl0eSBzZXJ2ZXIgdG8gXCJwcm92ZVwiIHRoYXRcbiAqIHRoZSBjbGllbnQgb3ducyB0aGUgZ2l2ZW4gZW1haWwgYWRkcmVzcywgd2hpY2ggaXMgdGhlbiBwYXNzZWQgdG8gdGhlXG4gKiBhZGQgdGhyZWVwaWQgQVBJIG9uIHRoZSBob21lc2VydmVyLlxuICpcbiAqIERpYWdyYW1zIG9mIHRoZSBpbnRlbmRlZCBBUEkgZmxvd3MgaGVyZSBhcmUgYXZhaWxhYmxlIGF0OlxuICpcbiAqIGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL2pyeWFucy84MzlhMDliZjBjNWE3MGUyZjM2ZWQ5OTBkNTBlZDkyOFxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBBZGRUaHJlZXBpZCB7XG4gICAgcHJpdmF0ZSBzZXNzaW9uSWQ/OiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBzdWJtaXRVcmw/OiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBiaW5kID0gZmFsc2U7XG4gICAgcHJpdmF0ZSByZWFkb25seSBjbGllbnRTZWNyZXQ6IHN0cmluZztcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IG1hdHJpeENsaWVudDogTWF0cml4Q2xpZW50KSB7XG4gICAgICAgIHRoaXMuY2xpZW50U2VjcmV0ID0gbWF0cml4Q2xpZW50LmdlbmVyYXRlQ2xpZW50U2VjcmV0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXR0ZW1wdCB0byBhZGQgYW4gZW1haWwgdGhyZWVwaWQgdG8gdGhlIGhvbWVzZXJ2ZXIuXG4gICAgICogVGhpcyB3aWxsIHRyaWdnZXIgYSBzaWRlLWVmZmVjdCBvZiBzZW5kaW5nIGFuIGVtYWlsIHRvIHRoZSBwcm92aWRlZCBlbWFpbCBhZGRyZXNzLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBlbWFpbEFkZHJlc3MgVGhlIGVtYWlsIGFkZHJlc3MgdG8gYWRkXG4gICAgICogQHJldHVybiB7UHJvbWlzZX0gUmVzb2x2ZXMgd2hlbiB0aGUgZW1haWwgaGFzIGJlZW4gc2VudC4gVGhlbiBjYWxsIGNoZWNrRW1haWxMaW5rQ2xpY2tlZCgpLlxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBhZGRFbWFpbEFkZHJlc3MoZW1haWxBZGRyZXNzOiBzdHJpbmcpOiBQcm9taXNlPElSZXF1ZXN0VG9rZW5SZXNwb25zZT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYXRyaXhDbGllbnQucmVxdWVzdEFkZDNwaWRFbWFpbFRva2VuKGVtYWlsQWRkcmVzcywgdGhpcy5jbGllbnRTZWNyZXQsIDEpO1xuICAgICAgICAgICAgdGhpcy5zZXNzaW9uSWQgPSByZXMuc2lkO1xuICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoZXJyIGluc3RhbmNlb2YgTWF0cml4RXJyb3IgJiYgZXJyLmVycmNvZGUgPT09IFwiTV9USFJFRVBJRF9JTl9VU0VcIikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBVc2VyRnJpZW5kbHlFcnJvcihcInNldHRpbmdzfGdlbmVyYWx8ZW1haWxfYWRkcmVzc19pbl91c2VcIiwgeyBjYXVzZTogZXJyIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gT3RoZXJ3aXNlLCBqdXN0IGJsdXJ0IG91dCB0aGUgc2FtZSBlcnJvclxuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXR0ZW1wdCB0byBiaW5kIGFuIGVtYWlsIHRocmVlcGlkIG9uIHRoZSBpZGVudGl0eSBzZXJ2ZXIgdmlhIHRoZSBob21lc2VydmVyLlxuICAgICAqIFRoaXMgd2lsbCB0cmlnZ2VyIGEgc2lkZS1lZmZlY3Qgb2Ygc2VuZGluZyBhbiBlbWFpbCB0byB0aGUgcHJvdmlkZWQgZW1haWwgYWRkcmVzcy5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZW1haWxBZGRyZXNzIFRoZSBlbWFpbCBhZGRyZXNzIHRvIGFkZFxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9IFJlc29sdmVzIHdoZW4gdGhlIGVtYWlsIGhhcyBiZWVuIHNlbnQuIFRoZW4gY2FsbCBjaGVja0VtYWlsTGlua0NsaWNrZWQoKS5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgYmluZEVtYWlsQWRkcmVzcyhlbWFpbEFkZHJlc3M6IHN0cmluZyk6IFByb21pc2U8SVJlcXVlc3RUb2tlblJlc3BvbnNlPiB7XG4gICAgICAgIHRoaXMuYmluZCA9IHRydWU7XG4gICAgICAgIC8vIEZvciBzZXBhcmF0ZSBiaW5kLCByZXF1ZXN0IGEgdG9rZW4gZGlyZWN0bHkgZnJvbSB0aGUgSVMuXG4gICAgICAgIGNvbnN0IGF1dGhDbGllbnQgPSBuZXcgSWRlbnRpdHlBdXRoQ2xpZW50KCk7XG4gICAgICAgIGNvbnN0IGlkZW50aXR5QWNjZXNzVG9rZW4gPSAoYXdhaXQgYXV0aENsaWVudC5nZXRBY2Nlc3NUb2tlbigpKSA/PyB1bmRlZmluZWQ7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLm1hdHJpeENsaWVudC5yZXF1ZXN0RW1haWxUb2tlbihcbiAgICAgICAgICAgICAgICBlbWFpbEFkZHJlc3MsXG4gICAgICAgICAgICAgICAgdGhpcy5jbGllbnRTZWNyZXQsXG4gICAgICAgICAgICAgICAgMSxcbiAgICAgICAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgaWRlbnRpdHlBY2Nlc3NUb2tlbixcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLnNlc3Npb25JZCA9IHJlcy5zaWQ7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBNYXRyaXhFcnJvciAmJiBlcnIuZXJyY29kZSA9PT0gXCJNX1RIUkVFUElEX0lOX1VTRVwiKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFVzZXJGcmllbmRseUVycm9yKFwic2V0dGluZ3N8Z2VuZXJhbHxlbWFpbF9hZGRyZXNzX2luX3VzZVwiLCB7IGNhdXNlOiBlcnIgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBPdGhlcndpc2UsIGp1c3QgYmx1cnQgb3V0IHRoZSBzYW1lIGVycm9yXG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBdHRlbXB0IHRvIGFkZCBhIE1TSVNETiB0aHJlZXBpZCB0byB0aGUgaG9tZXNlcnZlci5cbiAgICAgKiBUaGlzIHdpbGwgdHJpZ2dlciBhIHNpZGUtZWZmZWN0IG9mIHNlbmRpbmcgYW4gU01TIHRvIHRoZSBwcm92aWRlZCBwaG9uZSBudW1iZXIuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHBob25lQ291bnRyeSBUaGUgSVNPIDIgbGV0dGVyIGNvZGUgb2YgdGhlIGNvdW50cnkgdG8gcmVzb2x2ZSBwaG9uZU51bWJlciBpblxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwaG9uZU51bWJlciBUaGUgbmF0aW9uYWwgb3IgaW50ZXJuYXRpb25hbCBmb3JtYXR0ZWQgcGhvbmUgbnVtYmVyIHRvIGFkZFxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9IFJlc29sdmVzIHdoZW4gdGhlIHRleHQgbWVzc2FnZSBoYXMgYmVlbiBzZW50LiBUaGVuIGNhbGwgaGF2ZU1zaXNkblRva2VuKCkuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIGFkZE1zaXNkbihwaG9uZUNvdW50cnk6IHN0cmluZywgcGhvbmVOdW1iZXI6IHN0cmluZyk6IFByb21pc2U8SVJlcXVlc3RNc2lzZG5Ub2tlblJlc3BvbnNlPiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLm1hdHJpeENsaWVudC5yZXF1ZXN0QWRkM3BpZE1zaXNkblRva2VuKFxuICAgICAgICAgICAgICAgIHBob25lQ291bnRyeSxcbiAgICAgICAgICAgICAgICBwaG9uZU51bWJlcixcbiAgICAgICAgICAgICAgICB0aGlzLmNsaWVudFNlY3JldCxcbiAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbklkID0gcmVzLnNpZDtcbiAgICAgICAgICAgIHRoaXMuc3VibWl0VXJsID0gcmVzLnN1Ym1pdF91cmw7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBNYXRyaXhFcnJvciAmJiBlcnIuZXJyY29kZSA9PT0gXCJNX1RIUkVFUElEX0lOX1VTRVwiKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFVzZXJGcmllbmRseUVycm9yKFwic2V0dGluZ3N8Z2VuZXJhbHxtc2lzZG5faW5fdXNlXCIsIHsgY2F1c2U6IGVyciB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE90aGVyd2lzZSwganVzdCBibHVydCBvdXQgdGhlIHNhbWUgZXJyb3JcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEF0dGVtcHQgdG8gYmluZCBhIE1TSVNETiB0aHJlZXBpZCBvbiB0aGUgaWRlbnRpdHkgc2VydmVyIHZpYSB0aGUgaG9tZXNlcnZlci5cbiAgICAgKiBUaGlzIHdpbGwgdHJpZ2dlciBhIHNpZGUtZWZmZWN0IG9mIHNlbmRpbmcgYW4gU01TIHRvIHRoZSBwcm92aWRlZCBwaG9uZSBudW1iZXIuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHBob25lQ291bnRyeSBUaGUgSVNPIDIgbGV0dGVyIGNvZGUgb2YgdGhlIGNvdW50cnkgdG8gcmVzb2x2ZSBwaG9uZU51bWJlciBpblxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwaG9uZU51bWJlciBUaGUgbmF0aW9uYWwgb3IgaW50ZXJuYXRpb25hbCBmb3JtYXR0ZWQgcGhvbmUgbnVtYmVyIHRvIGFkZFxuICAgICAqIEByZXR1cm4ge1Byb21pc2V9IFJlc29sdmVzIHdoZW4gdGhlIHRleHQgbWVzc2FnZSBoYXMgYmVlbiBzZW50LiBUaGVuIGNhbGwgaGF2ZU1zaXNkblRva2VuKCkuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIGJpbmRNc2lzZG4ocGhvbmVDb3VudHJ5OiBzdHJpbmcsIHBob25lTnVtYmVyOiBzdHJpbmcpOiBQcm9taXNlPElSZXF1ZXN0TXNpc2RuVG9rZW5SZXNwb25zZT4ge1xuICAgICAgICB0aGlzLmJpbmQgPSB0cnVlO1xuICAgICAgICAvLyBGb3Igc2VwYXJhdGUgYmluZCwgcmVxdWVzdCBhIHRva2VuIGRpcmVjdGx5IGZyb20gdGhlIElTLlxuICAgICAgICBjb25zdCBhdXRoQ2xpZW50ID0gbmV3IElkZW50aXR5QXV0aENsaWVudCgpO1xuICAgICAgICBjb25zdCBpZGVudGl0eUFjY2Vzc1Rva2VuID0gKGF3YWl0IGF1dGhDbGllbnQuZ2V0QWNjZXNzVG9rZW4oKSkgPz8gdW5kZWZpbmVkO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYXRyaXhDbGllbnQucmVxdWVzdE1zaXNkblRva2VuKFxuICAgICAgICAgICAgICAgIHBob25lQ291bnRyeSxcbiAgICAgICAgICAgICAgICBwaG9uZU51bWJlcixcbiAgICAgICAgICAgICAgICB0aGlzLmNsaWVudFNlY3JldCxcbiAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBpZGVudGl0eUFjY2Vzc1Rva2VuLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRoaXMuc2Vzc2lvbklkID0gcmVzLnNpZDtcbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIE1hdHJpeEVycm9yICYmIGVyci5lcnJjb2RlID09PSBcIk1fVEhSRUVQSURfSU5fVVNFXCIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVXNlckZyaWVuZGx5RXJyb3IoXCJzZXR0aW5nc3xnZW5lcmFsfG1zaXNkbl9pbl91c2VcIiwgeyBjYXVzZTogZXJyIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gT3RoZXJ3aXNlLCBqdXN0IGJsdXJ0IG91dCB0aGUgc2FtZSBlcnJvclxuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIHRoZSBlbWFpbCBsaW5rIGhhcyBiZWVuIGNsaWNrZWQgYnkgYXR0ZW1wdGluZyB0byBhZGQgdGhlIHRocmVlcGlkXG4gICAgICogQHJldHVybiB7UHJvbWlzZX0gUmVzb2x2ZXMgaWYgdGhlIGVtYWlsIGFkZHJlc3Mgd2FzIGFkZGVkLiBSZWplY3RzIHdpdGggYW4gb2JqZWN0XG4gICAgICogd2l0aCBhIFwibWVzc2FnZVwiIHByb3BlcnR5IHdoaWNoIGNvbnRhaW5zIGEgaHVtYW4tcmVhZGFibGUgbWVzc2FnZSBkZXRhaWxpbmcgd2h5XG4gICAgICogdGhlIHJlcXVlc3QgZmFpbGVkLlxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBjaGVja0VtYWlsTGlua0NsaWNrZWQoKTogUHJvbWlzZTxbc3VjY2Vzcz86IGJvb2xlYW4sIHJlc3VsdD86IElBdXRoRGF0YSB8IEVycm9yIHwgbnVsbF0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICh0aGlzLmJpbmQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBhdXRoQ2xpZW50ID0gbmV3IElkZW50aXR5QXV0aENsaWVudCgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGlkZW50aXR5QWNjZXNzVG9rZW4gPSBhd2FpdCBhdXRoQ2xpZW50LmdldEFjY2Vzc1Rva2VuKCk7XG4gICAgICAgICAgICAgICAgaWYgKCFpZGVudGl0eUFjY2Vzc1Rva2VuKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBVc2VyRnJpZW5kbHlFcnJvcihcInNldHRpbmdzfGdlbmVyYWx8aWRlbnRpdHlfc2VydmVyX25vX3Rva2VuXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLm1hdHJpeENsaWVudC5iaW5kVGhyZWVQaWQoe1xuICAgICAgICAgICAgICAgICAgICBzaWQ6IHRoaXMuc2Vzc2lvbklkISxcbiAgICAgICAgICAgICAgICAgICAgY2xpZW50X3NlY3JldDogdGhpcy5jbGllbnRTZWNyZXQsXG4gICAgICAgICAgICAgICAgICAgIGlkX3NlcnZlcjogZ2V0SWRTZXJ2ZXJEb21haW4odGhpcy5tYXRyaXhDbGllbnQpLFxuICAgICAgICAgICAgICAgICAgICBpZF9hY2Nlc3NfdG9rZW46IGlkZW50aXR5QWNjZXNzVG9rZW4sXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMubWFrZUFkZFRocmVlcGlkT25seVJlcXVlc3QoKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgc3BlYyBoYXMgYWx3YXlzIHJlcXVpcmVkIHRoaXMgdG8gdXNlIFVJIGF1dGggYnV0IHN5bmFwc2UgYnJpZWZseVxuICAgICAgICAgICAgICAgICAgICAvLyBpbXBsZW1lbnRlZCBpdCB3aXRob3V0LCBzbyB0aGlzIG1heSBqdXN0IHN1Y2NlZWQgYW5kIHRoYXQncyBPSy5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFt0cnVlXTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoZXJyIGluc3RhbmNlb2YgTWF0cml4RXJyb3IpIHx8IGVyci5odHRwU3RhdHVzICE9PSA0MDEgfHwgIWVyci5kYXRhIHx8ICFlcnIuZGF0YS5mbG93cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZG9lc24ndCBsb29rIGxpa2UgYW4gaW50ZXJhY3RpdmUtYXV0aCBmYWlsdXJlXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBkaWFsb2dBZXN0aGV0aWNzID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgW1NTT0F1dGhFbnRyeS5QSEFTRV9QUkVBVVRIXToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlOiBfdChcImF1dGh8dWlhfHNzb190aXRsZVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBib2R5OiBfdChcImF1dGh8dWlhfHNzb19ib2R5XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlVGV4dDogX3QoXCJhdXRofHNzb1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZUtpbmQ6IFwicHJpbWFyeVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtTU09BdXRoRW50cnkuUEhBU0VfUE9TVEFVVEhdOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU6IF90KFwic2V0dGluZ3N8Z2VuZXJhbHxjb25maXJtX2FkZGluZ19lbWFpbF90aXRsZVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBib2R5OiBfdChcInNldHRpbmdzfGdlbmVyYWx8Y29uZmlybV9hZGRpbmdfZW1haWxfYm9keVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZVRleHQ6IF90KFwiYWN0aW9ufGNvbmZpcm1cIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWVLaW5kOiBcInByaW1hcnlcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgZmluaXNoZWQgfSA9IE1vZGFsLmNyZWF0ZURpYWxvZyhJbnRlcmFjdGl2ZUF1dGhEaWFsb2c8e30+LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aXRsZTogX3QoXCJzZXR0aW5nc3xnZW5lcmFsfGFkZF9lbWFpbF9kaWFsb2dfdGl0bGVcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXhDbGllbnQ6IHRoaXMubWF0cml4Q2xpZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgYXV0aERhdGE6IGVyci5kYXRhLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWFrZVJlcXVlc3Q6IHRoaXMubWFrZUFkZFRocmVlcGlkT25seVJlcXVlc3QsXG4gICAgICAgICAgICAgICAgICAgICAgICBhZXN0aGV0aWNzRm9yU3RhZ2VQaGFzZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbU1NPQXV0aEVudHJ5LkxPR0lOX1RZUEVdOiBkaWFsb2dBZXN0aGV0aWNzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtTU09BdXRoRW50cnkuVU5TVEFCTEVfTE9HSU5fVFlQRV06IGRpYWxvZ0Flc3RoZXRpY3MsXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB9IGFzIEludGVyYWN0aXZlQXV0aERpYWxvZ1Byb3BzPElBZGRUaHJlZVBpZE9ubHlCb2R5Pik7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmaW5pc2hlZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIEhUVFBFcnJvciAmJiBlcnIuaHR0cFN0YXR1cyA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFVzZXJGcmllbmRseUVycm9yKFwic2V0dGluZ3N8Z2VuZXJhbHxhZGRfZW1haWxfZmFpbGVkX3ZlcmlmaWNhdGlvblwiLCB7IGNhdXNlOiBlcnIgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBPdGhlcndpc2UsIGp1c3QgYmx1cnQgb3V0IHRoZSBzYW1lIGVycm9yXG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7e3R5cGU6IHN0cmluZywgc2Vzc2lvbj86IHN0cmluZ319IGF1dGggVUkgYXV0aCBvYmplY3RcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlPE9iamVjdD59IFJlc3BvbnNlIGZyb20gLzNwaWQvYWRkIGNhbGwgKGluIGN1cnJlbnQgc3BlYywgYW4gZW1wdHkgb2JqZWN0KVxuICAgICAqL1xuICAgIHByaXZhdGUgbWFrZUFkZFRocmVlcGlkT25seVJlcXVlc3QgPSAoYXV0aD86IElBZGRUaHJlZVBpZE9ubHlCb2R5W1wiYXV0aFwiXSB8IG51bGwpOiBQcm9taXNlPHt9PiA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLm1hdHJpeENsaWVudC5hZGRUaHJlZVBpZE9ubHkoe1xuICAgICAgICAgICAgc2lkOiB0aGlzLnNlc3Npb25JZCEsXG4gICAgICAgICAgICBjbGllbnRfc2VjcmV0OiB0aGlzLmNsaWVudFNlY3JldCxcbiAgICAgICAgICAgIGF1dGg6IGF1dGggPz8gdW5kZWZpbmVkLFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVGFrZXMgYSBwaG9uZSBudW1iZXIgdmVyaWZpY2F0aW9uIGNvZGUgYXMgZW50ZXJlZCBieSB0aGUgdXNlciBhbmQgdmFsaWRhdGVzXG4gICAgICogaXQgd2l0aCB0aGUgaWRlbnRpdHkgc2VydmVyLCB0aGVuIGlmIHN1Y2Nlc3NmdWwsIGFkZHMgdGhlIHBob25lIG51bWJlci5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbXNpc2RuVG9rZW4gcGhvbmUgbnVtYmVyIHZlcmlmaWNhdGlvbiBjb2RlIGFzIGVudGVyZWQgYnkgdGhlIHVzZXJcbiAgICAgKiBAcmV0dXJuIHtQcm9taXNlfSBSZXNvbHZlcyBpZiB0aGUgcGhvbmUgbnVtYmVyIHdhcyBhZGRlZC4gUmVqZWN0cyB3aXRoIGFuIG9iamVjdFxuICAgICAqIHdpdGggYSBcIm1lc3NhZ2VcIiBwcm9wZXJ0eSB3aGljaCBjb250YWlucyBhIGh1bWFuLXJlYWRhYmxlIG1lc3NhZ2UgZGV0YWlsaW5nIHdoeVxuICAgICAqIHRoZSByZXF1ZXN0IGZhaWxlZC5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgaGF2ZU1zaXNkblRva2VuKG1zaXNkblRva2VuOiBzdHJpbmcpOiBQcm9taXNlPFtzdWNjZXNzPzogYm9vbGVhbiwgcmVzdWx0PzogSUF1dGhEYXRhIHwgRXJyb3IgfCBudWxsXT4ge1xuICAgICAgICBjb25zdCBhdXRoQ2xpZW50ID0gbmV3IElkZW50aXR5QXV0aENsaWVudCgpO1xuXG4gICAgICAgIGlmICh0aGlzLnN1Ym1pdFVybCkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5tYXRyaXhDbGllbnQuc3VibWl0TXNpc2RuVG9rZW5PdGhlclVybChcbiAgICAgICAgICAgICAgICB0aGlzLnN1Ym1pdFVybCxcbiAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb25JZCEsXG4gICAgICAgICAgICAgICAgdGhpcy5jbGllbnRTZWNyZXQsXG4gICAgICAgICAgICAgICAgbXNpc2RuVG9rZW4sXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuYmluZCkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5tYXRyaXhDbGllbnQuc3VibWl0TXNpc2RuVG9rZW4oXG4gICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uSWQhLFxuICAgICAgICAgICAgICAgIHRoaXMuY2xpZW50U2VjcmV0LFxuICAgICAgICAgICAgICAgIG1zaXNkblRva2VuLFxuICAgICAgICAgICAgICAgIGF3YWl0IGF1dGhDbGllbnQuZ2V0QWNjZXNzVG9rZW4oKSxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVXNlckZyaWVuZGx5RXJyb3IoXCJzZXR0aW5nc3xnZW5lcmFsfGFkZF9tc2lzZG5fbWlzY29uZmlndXJlZFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmJpbmQpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMubWF0cml4Q2xpZW50LmJpbmRUaHJlZVBpZCh7XG4gICAgICAgICAgICAgICAgc2lkOiB0aGlzLnNlc3Npb25JZCEsXG4gICAgICAgICAgICAgICAgY2xpZW50X3NlY3JldDogdGhpcy5jbGllbnRTZWNyZXQsXG4gICAgICAgICAgICAgICAgaWRfc2VydmVyOiBnZXRJZFNlcnZlckRvbWFpbih0aGlzLm1hdHJpeENsaWVudCksXG4gICAgICAgICAgICAgICAgaWRfYWNjZXNzX3Rva2VuOiBhd2FpdCBhdXRoQ2xpZW50LmdldEFjY2Vzc1Rva2VuKCksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBbdHJ1ZV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMubWFrZUFkZFRocmVlcGlkT25seVJlcXVlc3QoKTtcblxuICAgICAgICAgICAgICAgIC8vIFRoZSBzcGVjIGhhcyBhbHdheXMgcmVxdWlyZWQgdGhpcyB0byB1c2UgVUkgYXV0aCBidXQgc3luYXBzZSBicmllZmx5XG4gICAgICAgICAgICAgICAgLy8gaW1wbGVtZW50ZWQgaXQgd2l0aG91dCwgc28gdGhpcyBtYXkganVzdCBzdWNjZWVkIGFuZCB0aGF0J3MgT0suXG4gICAgICAgICAgICAgICAgcmV0dXJuIFt0cnVlXTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIGlmICghKGVyciBpbnN0YW5jZW9mIE1hdHJpeEVycm9yKSB8fCBlcnIuaHR0cFN0YXR1cyAhPT0gNDAxIHx8ICFlcnIuZGF0YSB8fCAhZXJyLmRhdGEuZmxvd3MpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gZG9lc24ndCBsb29rIGxpa2UgYW4gaW50ZXJhY3RpdmUtYXV0aCBmYWlsdXJlXG4gICAgICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBkaWFsb2dBZXN0aGV0aWNzID0ge1xuICAgICAgICAgICAgICAgICAgICBbU1NPQXV0aEVudHJ5LlBIQVNFX1BSRUFVVEhdOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aXRsZTogX3QoXCJhdXRofHVpYXxzc29fdGl0bGVcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBib2R5OiBfdChcInNldHRpbmdzfGdlbmVyYWx8YWRkX21zaXNkbl9jb25maXJtX3Nzb19idXR0b25cIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZVRleHQ6IF90KFwiYXV0aHxzc29cIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZUtpbmQ6IFwicHJpbWFyeVwiLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBbU1NPQXV0aEVudHJ5LlBIQVNFX1BPU1RBVVRIXToge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU6IF90KFwic2V0dGluZ3N8Z2VuZXJhbHxhZGRfbXNpc2RuX2NvbmZpcm1fYnV0dG9uXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYm9keTogX3QoXCJzZXR0aW5nc3xnZW5lcmFsfGFkZF9tc2lzZG5fY29uZmlybV9ib2R5XCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWVUZXh0OiBfdChcImFjdGlvbnxjb25maXJtXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWVLaW5kOiBcInByaW1hcnlcIixcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgZmluaXNoZWQgfSA9IE1vZGFsLmNyZWF0ZURpYWxvZyhJbnRlcmFjdGl2ZUF1dGhEaWFsb2c8e30+LCB7XG4gICAgICAgICAgICAgICAgICAgIHRpdGxlOiBfdChcInNldHRpbmdzfGdlbmVyYWx8YWRkX21zaXNkbl9kaWFsb2dfdGl0bGVcIiksXG4gICAgICAgICAgICAgICAgICAgIG1hdHJpeENsaWVudDogdGhpcy5tYXRyaXhDbGllbnQsXG4gICAgICAgICAgICAgICAgICAgIGF1dGhEYXRhOiBlcnIuZGF0YSxcbiAgICAgICAgICAgICAgICAgICAgbWFrZVJlcXVlc3Q6IHRoaXMubWFrZUFkZFRocmVlcGlkT25seVJlcXVlc3QsXG4gICAgICAgICAgICAgICAgICAgIGFlc3RoZXRpY3NGb3JTdGFnZVBoYXNlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgW1NTT0F1dGhFbnRyeS5MT0dJTl9UWVBFXTogZGlhbG9nQWVzdGhldGljcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtTU09BdXRoRW50cnkuVU5TVEFCTEVfTE9HSU5fVFlQRV06IGRpYWxvZ0Flc3RoZXRpY3MsXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSBhcyBJbnRlcmFjdGl2ZUF1dGhEaWFsb2dQcm9wczxJQWRkVGhyZWVQaWRPbmx5Qm9keT4pO1xuICAgICAgICAgICAgICAgIHJldHVybiBmaW5pc2hlZDtcbiAgICAg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