6329 lines
855 KiB
JavaScript
6329 lines
855 KiB
JavaScript
/*! @azure/msal-common v4.0.1 2021-02-18 */
|
||
'use strict';
|
||
/*! *****************************************************************************
|
||
Copyright (c) Microsoft Corporation.
|
||
|
||
Permission to use, copy, modify, and/or distribute this software for any
|
||
purpose with or without fee is hereby granted.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||
PERFORMANCE OF THIS SOFTWARE.
|
||
***************************************************************************** */
|
||
/* global Reflect, Promise */
|
||
|
||
var extendStatics = function(d, b) {
|
||
extendStatics = Object.setPrototypeOf ||
|
||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
||
return extendStatics(d, b);
|
||
};
|
||
|
||
function __extends(d, b) {
|
||
extendStatics(d, b);
|
||
function __() { this.constructor = d; }
|
||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||
}
|
||
|
||
var __assign = function() {
|
||
__assign = Object.assign || function __assign(t) {
|
||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||
s = arguments[i];
|
||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
||
}
|
||
return t;
|
||
};
|
||
return __assign.apply(this, arguments);
|
||
};
|
||
|
||
function __awaiter(thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
}
|
||
|
||
function __generator(thisArg, body) {
|
||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||
function step(op) {
|
||
if (f) throw new TypeError("Generator is already executing.");
|
||
while (_) try {
|
||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||
switch (op[0]) {
|
||
case 0: case 1: t = op; break;
|
||
case 4: _.label++; return { value: op[1], done: false };
|
||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||
default:
|
||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||
if (t[2]) _.ops.pop();
|
||
_.trys.pop(); continue;
|
||
}
|
||
op = body.call(thisArg, _);
|
||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||
}
|
||
}
|
||
|
||
function __spreadArrays() {
|
||
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
||
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
||
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
||
r[k] = a[j];
|
||
return r;
|
||
}
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
var Constants = {
|
||
LIBRARY_NAME: "MSAL.JS",
|
||
SKU: "msal.js.common",
|
||
// Prefix for all library cache entries
|
||
CACHE_PREFIX: "msal",
|
||
// default authority
|
||
DEFAULT_AUTHORITY: "https://login.microsoftonline.com/common/",
|
||
DEFAULT_AUTHORITY_HOST: "login.microsoftonline.com",
|
||
// ADFS String
|
||
ADFS: "adfs",
|
||
// Default AAD Instance Discovery Endpoint
|
||
AAD_INSTANCE_DISCOVERY_ENDPT: "https://login.microsoftonline.com/common/discovery/instance?api-version=1.1&authorization_endpoint=",
|
||
// Resource delimiter - used for certain cache entries
|
||
RESOURCE_DELIM: "|",
|
||
// Placeholder for non-existent account ids/objects
|
||
NO_ACCOUNT: "NO_ACCOUNT",
|
||
// Claims
|
||
CLAIMS: "claims",
|
||
// Consumer UTID
|
||
CONSUMER_UTID: "9188040d-6c67-4c5b-b112-36a304b66dad",
|
||
// Default scopes
|
||
OPENID_SCOPE: "openid",
|
||
PROFILE_SCOPE: "profile",
|
||
OFFLINE_ACCESS_SCOPE: "offline_access",
|
||
EMAIL_SCOPE: "email",
|
||
// Default response type for authorization code flow
|
||
CODE_RESPONSE_TYPE: "code",
|
||
CODE_GRANT_TYPE: "authorization_code",
|
||
RT_GRANT_TYPE: "refresh_token",
|
||
FRAGMENT_RESPONSE_MODE: "fragment",
|
||
S256_CODE_CHALLENGE_METHOD: "S256",
|
||
URL_FORM_CONTENT_TYPE: "application/x-www-form-urlencoded;charset=utf-8",
|
||
AUTHORIZATION_PENDING: "authorization_pending",
|
||
NOT_DEFINED: "not_defined",
|
||
EMPTY_STRING: "",
|
||
FORWARD_SLASH: "/"
|
||
};
|
||
var OIDC_DEFAULT_SCOPES = [
|
||
Constants.OPENID_SCOPE,
|
||
Constants.PROFILE_SCOPE,
|
||
Constants.OFFLINE_ACCESS_SCOPE
|
||
];
|
||
var OIDC_SCOPES = __spreadArrays(OIDC_DEFAULT_SCOPES, [
|
||
Constants.EMAIL_SCOPE
|
||
]);
|
||
/**
|
||
* Request header names
|
||
*/
|
||
var HeaderNames;
|
||
(function (HeaderNames) {
|
||
HeaderNames["CONTENT_TYPE"] = "Content-Type";
|
||
HeaderNames["X_CLIENT_CURR_TELEM"] = "x-client-current-telemetry";
|
||
HeaderNames["X_CLIENT_LAST_TELEM"] = "x-client-last-telemetry";
|
||
HeaderNames["RETRY_AFTER"] = "Retry-After";
|
||
HeaderNames["X_MS_LIB_CAPABILITY"] = "x-ms-lib-capability";
|
||
HeaderNames["X_MS_LIB_CAPABILITY_VALUE"] = "retry-after, h429";
|
||
})(HeaderNames || (HeaderNames = {}));
|
||
/**
|
||
* Persistent cache keys MSAL which stay while user is logged in.
|
||
*/
|
||
var PersistentCacheKeys;
|
||
(function (PersistentCacheKeys) {
|
||
PersistentCacheKeys["ID_TOKEN"] = "idtoken";
|
||
PersistentCacheKeys["CLIENT_INFO"] = "client.info";
|
||
PersistentCacheKeys["ADAL_ID_TOKEN"] = "adal.idtoken";
|
||
PersistentCacheKeys["ERROR"] = "error";
|
||
PersistentCacheKeys["ERROR_DESC"] = "error.description";
|
||
})(PersistentCacheKeys || (PersistentCacheKeys = {}));
|
||
/**
|
||
* String constants related to AAD Authority
|
||
*/
|
||
var AADAuthorityConstants;
|
||
(function (AADAuthorityConstants) {
|
||
AADAuthorityConstants["COMMON"] = "common";
|
||
AADAuthorityConstants["ORGANIZATIONS"] = "organizations";
|
||
AADAuthorityConstants["CONSUMERS"] = "consumers";
|
||
})(AADAuthorityConstants || (AADAuthorityConstants = {}));
|
||
/**
|
||
* Keys in the hashParams sent by AAD Server
|
||
*/
|
||
var AADServerParamKeys;
|
||
(function (AADServerParamKeys) {
|
||
AADServerParamKeys["CLIENT_ID"] = "client_id";
|
||
AADServerParamKeys["REDIRECT_URI"] = "redirect_uri";
|
||
AADServerParamKeys["RESPONSE_TYPE"] = "response_type";
|
||
AADServerParamKeys["RESPONSE_MODE"] = "response_mode";
|
||
AADServerParamKeys["GRANT_TYPE"] = "grant_type";
|
||
AADServerParamKeys["CLAIMS"] = "claims";
|
||
AADServerParamKeys["SCOPE"] = "scope";
|
||
AADServerParamKeys["ERROR"] = "error";
|
||
AADServerParamKeys["ERROR_DESCRIPTION"] = "error_description";
|
||
AADServerParamKeys["ACCESS_TOKEN"] = "access_token";
|
||
AADServerParamKeys["ID_TOKEN"] = "id_token";
|
||
AADServerParamKeys["REFRESH_TOKEN"] = "refresh_token";
|
||
AADServerParamKeys["EXPIRES_IN"] = "expires_in";
|
||
AADServerParamKeys["STATE"] = "state";
|
||
AADServerParamKeys["NONCE"] = "nonce";
|
||
AADServerParamKeys["PROMPT"] = "prompt";
|
||
AADServerParamKeys["SESSION_STATE"] = "session_state";
|
||
AADServerParamKeys["CLIENT_INFO"] = "client_info";
|
||
AADServerParamKeys["CODE"] = "code";
|
||
AADServerParamKeys["CODE_CHALLENGE"] = "code_challenge";
|
||
AADServerParamKeys["CODE_CHALLENGE_METHOD"] = "code_challenge_method";
|
||
AADServerParamKeys["CODE_VERIFIER"] = "code_verifier";
|
||
AADServerParamKeys["CLIENT_REQUEST_ID"] = "client-request-id";
|
||
AADServerParamKeys["X_CLIENT_SKU"] = "x-client-SKU";
|
||
AADServerParamKeys["X_CLIENT_VER"] = "x-client-VER";
|
||
AADServerParamKeys["X_CLIENT_OS"] = "x-client-OS";
|
||
AADServerParamKeys["X_CLIENT_CPU"] = "x-client-CPU";
|
||
AADServerParamKeys["POST_LOGOUT_URI"] = "post_logout_redirect_uri";
|
||
AADServerParamKeys["ID_TOKEN_HINT"] = "id_token_hint";
|
||
AADServerParamKeys["DEVICE_CODE"] = "device_code";
|
||
AADServerParamKeys["CLIENT_SECRET"] = "client_secret";
|
||
AADServerParamKeys["CLIENT_ASSERTION"] = "client_assertion";
|
||
AADServerParamKeys["CLIENT_ASSERTION_TYPE"] = "client_assertion_type";
|
||
AADServerParamKeys["TOKEN_TYPE"] = "token_type";
|
||
AADServerParamKeys["REQ_CNF"] = "req_cnf";
|
||
AADServerParamKeys["OBO_ASSERTION"] = "assertion";
|
||
AADServerParamKeys["REQUESTED_TOKEN_USE"] = "requested_token_use";
|
||
AADServerParamKeys["ON_BEHALF_OF"] = "on_behalf_of";
|
||
AADServerParamKeys["FOCI"] = "foci";
|
||
})(AADServerParamKeys || (AADServerParamKeys = {}));
|
||
/**
|
||
* Claims request keys
|
||
*/
|
||
var ClaimsRequestKeys;
|
||
(function (ClaimsRequestKeys) {
|
||
ClaimsRequestKeys["ACCESS_TOKEN"] = "access_token";
|
||
ClaimsRequestKeys["XMS_CC"] = "xms_cc";
|
||
})(ClaimsRequestKeys || (ClaimsRequestKeys = {}));
|
||
/**
|
||
* we considered making this "enum" in the request instead of string, however it looks like the allowed list of
|
||
* prompt values kept changing over past couple of years. There are some undocumented prompt values for some
|
||
* internal partners too, hence the choice of generic "string" type instead of the "enum"
|
||
*/
|
||
var PromptValue = {
|
||
LOGIN: "login",
|
||
SELECT_ACCOUNT: "select_account",
|
||
CONSENT: "consent",
|
||
NONE: "none",
|
||
};
|
||
/**
|
||
* SSO Types - generated to populate hints
|
||
*/
|
||
var SSOTypes;
|
||
(function (SSOTypes) {
|
||
SSOTypes["ACCOUNT"] = "account";
|
||
SSOTypes["SID"] = "sid";
|
||
SSOTypes["LOGIN_HINT"] = "login_hint";
|
||
SSOTypes["ID_TOKEN"] = "id_token";
|
||
SSOTypes["DOMAIN_HINT"] = "domain_hint";
|
||
SSOTypes["ORGANIZATIONS"] = "organizations";
|
||
SSOTypes["CONSUMERS"] = "consumers";
|
||
SSOTypes["ACCOUNT_ID"] = "accountIdentifier";
|
||
SSOTypes["HOMEACCOUNT_ID"] = "homeAccountIdentifier";
|
||
})(SSOTypes || (SSOTypes = {}));
|
||
/**
|
||
* Disallowed extra query parameters.
|
||
*/
|
||
var BlacklistedEQParams = [
|
||
SSOTypes.SID,
|
||
SSOTypes.LOGIN_HINT
|
||
];
|
||
/**
|
||
* allowed values for codeVerifier
|
||
*/
|
||
var CodeChallengeMethodValues = {
|
||
PLAIN: "plain",
|
||
S256: "S256"
|
||
};
|
||
/**
|
||
* allowed values for response_mode
|
||
*/
|
||
var ResponseMode;
|
||
(function (ResponseMode) {
|
||
ResponseMode["QUERY"] = "query";
|
||
ResponseMode["FRAGMENT"] = "fragment";
|
||
ResponseMode["FORM_POST"] = "form_post";
|
||
})(ResponseMode || (ResponseMode = {}));
|
||
/**
|
||
* allowed grant_type
|
||
*/
|
||
var GrantType;
|
||
(function (GrantType) {
|
||
GrantType["IMPLICIT_GRANT"] = "implicit";
|
||
GrantType["AUTHORIZATION_CODE_GRANT"] = "authorization_code";
|
||
GrantType["CLIENT_CREDENTIALS_GRANT"] = "client_credentials";
|
||
GrantType["RESOURCE_OWNER_PASSWORD_GRANT"] = "password";
|
||
GrantType["REFRESH_TOKEN_GRANT"] = "refresh_token";
|
||
GrantType["DEVICE_CODE_GRANT"] = "device_code";
|
||
GrantType["JWT_BEARER"] = "urn:ietf:params:oauth:grant-type:jwt-bearer";
|
||
})(GrantType || (GrantType = {}));
|
||
/**
|
||
* Account types in Cache
|
||
*/
|
||
var CacheAccountType;
|
||
(function (CacheAccountType) {
|
||
CacheAccountType["MSSTS_ACCOUNT_TYPE"] = "MSSTS";
|
||
CacheAccountType["ADFS_ACCOUNT_TYPE"] = "ADFS";
|
||
CacheAccountType["MSAV1_ACCOUNT_TYPE"] = "MSA";
|
||
CacheAccountType["GENERIC_ACCOUNT_TYPE"] = "Generic"; // NTLM, Kerberos, FBA, Basic etc
|
||
})(CacheAccountType || (CacheAccountType = {}));
|
||
/**
|
||
* Separators used in cache
|
||
*/
|
||
var Separators;
|
||
(function (Separators) {
|
||
Separators["CACHE_KEY_SEPARATOR"] = "-";
|
||
Separators["CLIENT_INFO_SEPARATOR"] = ".";
|
||
})(Separators || (Separators = {}));
|
||
/**
|
||
* Credential Type stored in the cache
|
||
*/
|
||
var CredentialType;
|
||
(function (CredentialType) {
|
||
CredentialType["ID_TOKEN"] = "IdToken";
|
||
CredentialType["ACCESS_TOKEN"] = "AccessToken";
|
||
CredentialType["REFRESH_TOKEN"] = "RefreshToken";
|
||
})(CredentialType || (CredentialType = {}));
|
||
/**
|
||
* Credential Type stored in the cache
|
||
*/
|
||
var CacheSchemaType;
|
||
(function (CacheSchemaType) {
|
||
CacheSchemaType["ACCOUNT"] = "Account";
|
||
CacheSchemaType["CREDENTIAL"] = "Credential";
|
||
CacheSchemaType["ID_TOKEN"] = "IdToken";
|
||
CacheSchemaType["ACCESS_TOKEN"] = "AccessToken";
|
||
CacheSchemaType["REFRESH_TOKEN"] = "RefreshToken";
|
||
CacheSchemaType["APP_METADATA"] = "AppMetadata";
|
||
CacheSchemaType["TEMPORARY"] = "TempCache";
|
||
CacheSchemaType["TELEMETRY"] = "Telemetry";
|
||
CacheSchemaType["UNDEFINED"] = "Undefined";
|
||
CacheSchemaType["THROTTLING"] = "Throttling";
|
||
})(CacheSchemaType || (CacheSchemaType = {}));
|
||
/**
|
||
* Combine all cache types
|
||
*/
|
||
var CacheType;
|
||
(function (CacheType) {
|
||
CacheType[CacheType["ADFS"] = 1001] = "ADFS";
|
||
CacheType[CacheType["MSA"] = 1002] = "MSA";
|
||
CacheType[CacheType["MSSTS"] = 1003] = "MSSTS";
|
||
CacheType[CacheType["GENERIC"] = 1004] = "GENERIC";
|
||
CacheType[CacheType["ACCESS_TOKEN"] = 2001] = "ACCESS_TOKEN";
|
||
CacheType[CacheType["REFRESH_TOKEN"] = 2002] = "REFRESH_TOKEN";
|
||
CacheType[CacheType["ID_TOKEN"] = 2003] = "ID_TOKEN";
|
||
CacheType[CacheType["APP_METADATA"] = 3001] = "APP_METADATA";
|
||
CacheType[CacheType["UNDEFINED"] = 9999] = "UNDEFINED";
|
||
})(CacheType || (CacheType = {}));
|
||
/**
|
||
* More Cache related constants
|
||
*/
|
||
var APP_METADATA = "appmetadata";
|
||
var ClientInfo = "client_info";
|
||
var THE_FAMILY_ID = "1";
|
||
var AUTHORITY_METADATA_CONSTANTS = {
|
||
CACHE_KEY: "authority-metadata",
|
||
REFRESH_TIME_SECONDS: 3600 * 24 // 24 Hours
|
||
};
|
||
var AuthorityMetadataSource;
|
||
(function (AuthorityMetadataSource) {
|
||
AuthorityMetadataSource["CONFIG"] = "config";
|
||
AuthorityMetadataSource["CACHE"] = "cache";
|
||
AuthorityMetadataSource["NETWORK"] = "network";
|
||
})(AuthorityMetadataSource || (AuthorityMetadataSource = {}));
|
||
var SERVER_TELEM_CONSTANTS = {
|
||
SCHEMA_VERSION: 2,
|
||
MAX_HEADER_BYTES: 4000,
|
||
CACHE_KEY: "server-telemetry",
|
||
CATEGORY_SEPARATOR: "|",
|
||
VALUE_SEPARATOR: ",",
|
||
OVERFLOW_TRUE: "1",
|
||
OVERFLOW_FALSE: "0",
|
||
UNKNOWN_ERROR: "unknown_error"
|
||
};
|
||
/**
|
||
* Type of the authentication request
|
||
*/
|
||
var AuthenticationScheme;
|
||
(function (AuthenticationScheme) {
|
||
AuthenticationScheme["POP"] = "pop";
|
||
AuthenticationScheme["BEARER"] = "Bearer";
|
||
})(AuthenticationScheme || (AuthenticationScheme = {}));
|
||
/**
|
||
* Constants related to throttling
|
||
*/
|
||
var ThrottlingConstants = {
|
||
// Default time to throttle RequestThumbprint in seconds
|
||
DEFAULT_THROTTLE_TIME_SECONDS: 60,
|
||
// Default maximum time to throttle in seconds, overrides what the server sends back
|
||
DEFAULT_MAX_THROTTLE_TIME_SECONDS: 3600,
|
||
// Prefix for storing throttling entries
|
||
THROTTLING_PREFIX: "throttling"
|
||
};
|
||
var Errors = {
|
||
INVALID_GRANT_ERROR: "invalid_grant",
|
||
CLIENT_MISMATCH_ERROR: "client_mismatch",
|
||
};
|
||
/**
|
||
* Password grant parameters
|
||
*/
|
||
var PasswordGrantConstants;
|
||
(function (PasswordGrantConstants) {
|
||
PasswordGrantConstants["username"] = "username";
|
||
PasswordGrantConstants["password"] = "password";
|
||
})(PasswordGrantConstants || (PasswordGrantConstants = {}));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* AuthErrorMessage class containing string constants used by error codes and messages.
|
||
*/
|
||
var AuthErrorMessage = {
|
||
unexpectedError: {
|
||
code: "unexpected_error",
|
||
desc: "Unexpected error in authentication."
|
||
}
|
||
};
|
||
/**
|
||
* General error class thrown by the MSAL.js library.
|
||
*/
|
||
var AuthError = /** @class */ (function (_super) {
|
||
__extends(AuthError, _super);
|
||
function AuthError(errorCode, errorMessage, suberror) {
|
||
var _this = this;
|
||
var errorString = errorMessage ? errorCode + ": " + errorMessage : errorCode;
|
||
_this = _super.call(this, errorString) || this;
|
||
Object.setPrototypeOf(_this, AuthError.prototype);
|
||
_this.errorCode = errorCode || Constants.EMPTY_STRING;
|
||
_this.errorMessage = errorMessage || "";
|
||
_this.subError = suberror || "";
|
||
_this.name = "AuthError";
|
||
return _this;
|
||
}
|
||
/**
|
||
* Creates an error that is thrown when something unexpected happens in the library.
|
||
* @param errDesc
|
||
*/
|
||
AuthError.createUnexpectedError = function (errDesc) {
|
||
return new AuthError(AuthErrorMessage.unexpectedError.code, AuthErrorMessage.unexpectedError.desc + ": " + errDesc);
|
||
};
|
||
return AuthError;
|
||
}(Error));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
var DEFAULT_CRYPTO_IMPLEMENTATION = {
|
||
createNewGuid: function () {
|
||
var notImplErr = "Crypto interface - createNewGuid() has not been implemented";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
},
|
||
base64Decode: function () {
|
||
var notImplErr = "Crypto interface - base64Decode() has not been implemented";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
},
|
||
base64Encode: function () {
|
||
var notImplErr = "Crypto interface - base64Encode() has not been implemented";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
},
|
||
generatePkceCodes: function () {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var notImplErr;
|
||
return __generator(this, function (_a) {
|
||
notImplErr = "Crypto interface - generatePkceCodes() has not been implemented";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
});
|
||
});
|
||
},
|
||
getPublicKeyThumbprint: function () {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var notImplErr;
|
||
return __generator(this, function (_a) {
|
||
notImplErr = "Crypto interface - getPublicKeyThumbprint() has not been implemented";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
});
|
||
});
|
||
},
|
||
signJwt: function () {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var notImplErr;
|
||
return __generator(this, function (_a) {
|
||
notImplErr = "Crypto interface - signJwt() has not been implemented";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
});
|
||
});
|
||
}
|
||
};
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* ClientAuthErrorMessage class containing string constants used by error codes and messages.
|
||
*/
|
||
var ClientAuthErrorMessage = {
|
||
clientInfoDecodingError: {
|
||
code: "client_info_decoding_error",
|
||
desc: "The client info could not be parsed/decoded correctly. Please review the trace to determine the root cause."
|
||
},
|
||
clientInfoEmptyError: {
|
||
code: "client_info_empty_error",
|
||
desc: "The client info was empty. Please review the trace to determine the root cause."
|
||
},
|
||
tokenParsingError: {
|
||
code: "token_parsing_error",
|
||
desc: "Token cannot be parsed. Please review stack trace to determine root cause."
|
||
},
|
||
nullOrEmptyToken: {
|
||
code: "null_or_empty_token",
|
||
desc: "The token is null or empty. Please review the trace to determine the root cause."
|
||
},
|
||
endpointResolutionError: {
|
||
code: "endpoints_resolution_error",
|
||
desc: "Error: could not resolve endpoints. Please check network and try again."
|
||
},
|
||
unableToGetOpenidConfigError: {
|
||
code: "openid_config_error",
|
||
desc: "Could not retrieve endpoints. Check your authority and verify the .well-known/openid-configuration endpoint returns the required endpoints."
|
||
},
|
||
hashNotDeserialized: {
|
||
code: "hash_not_deserialized",
|
||
desc: "The hash parameters could not be deserialized. Please review the trace to determine the root cause."
|
||
},
|
||
blankGuidGenerated: {
|
||
code: "blank_guid_generated",
|
||
desc: "The guid generated was blank. Please review the trace to determine the root cause."
|
||
},
|
||
invalidStateError: {
|
||
code: "invalid_state",
|
||
desc: "State was not the expected format. Please check the logs to determine whether the request was sent using ProtocolUtils.setRequestState()."
|
||
},
|
||
stateMismatchError: {
|
||
code: "state_mismatch",
|
||
desc: "State mismatch error. Please check your network. Continued requests may cause cache overflow."
|
||
},
|
||
stateNotFoundError: {
|
||
code: "state_not_found",
|
||
desc: "State not found"
|
||
},
|
||
nonceMismatchError: {
|
||
code: "nonce_mismatch",
|
||
desc: "Nonce mismatch error. This may be caused by a race condition in concurrent requests."
|
||
},
|
||
nonceNotFoundError: {
|
||
code: "nonce_not_found",
|
||
desc: "nonce not found"
|
||
},
|
||
noTokensFoundError: {
|
||
code: "no_tokens_found",
|
||
desc: "No tokens were found for the given scopes, and no authorization code was passed to acquireToken. You must retrieve an authorization code before making a call to acquireToken()."
|
||
},
|
||
multipleMatchingTokens: {
|
||
code: "multiple_matching_tokens",
|
||
desc: "The cache contains multiple tokens satisfying the requirements. " +
|
||
"Call AcquireToken again providing more requirements such as authority or account."
|
||
},
|
||
multipleMatchingAccounts: {
|
||
code: "multiple_matching_accounts",
|
||
desc: "The cache contains multiple accounts satisfying the given parameters. Please pass more info to obtain the correct account"
|
||
},
|
||
multipleMatchingAppMetadata: {
|
||
code: "multiple_matching_appMetadata",
|
||
desc: "The cache contains multiple appMetadata satisfying the given parameters. Please pass more info to obtain the correct appMetadata"
|
||
},
|
||
tokenRequestCannotBeMade: {
|
||
code: "request_cannot_be_made",
|
||
desc: "Token request cannot be made without authorization code or refresh token."
|
||
},
|
||
appendEmptyScopeError: {
|
||
code: "cannot_append_empty_scope",
|
||
desc: "Cannot append null or empty scope to ScopeSet. Please check the stack trace for more info."
|
||
},
|
||
removeEmptyScopeError: {
|
||
code: "cannot_remove_empty_scope",
|
||
desc: "Cannot remove null or empty scope from ScopeSet. Please check the stack trace for more info."
|
||
},
|
||
appendScopeSetError: {
|
||
code: "cannot_append_scopeset",
|
||
desc: "Cannot append ScopeSet due to error."
|
||
},
|
||
emptyInputScopeSetError: {
|
||
code: "empty_input_scopeset",
|
||
desc: "Empty input ScopeSet cannot be processed."
|
||
},
|
||
DeviceCodePollingCancelled: {
|
||
code: "device_code_polling_cancelled",
|
||
desc: "Caller has cancelled token endpoint polling during device code flow by setting DeviceCodeRequest.cancel = true."
|
||
},
|
||
DeviceCodeExpired: {
|
||
code: "device_code_expired",
|
||
desc: "Device code is expired."
|
||
},
|
||
NoAccountInSilentRequest: {
|
||
code: "no_account_in_silent_request",
|
||
desc: "Please pass an account object, silent flow is not supported without account information"
|
||
},
|
||
invalidCacheRecord: {
|
||
code: "invalid_cache_record",
|
||
desc: "Cache record object was null or undefined."
|
||
},
|
||
invalidCacheEnvironment: {
|
||
code: "invalid_cache_environment",
|
||
desc: "Invalid environment when attempting to create cache entry"
|
||
},
|
||
noAccountFound: {
|
||
code: "no_account_found",
|
||
desc: "No account found in cache for given key."
|
||
},
|
||
CachePluginError: {
|
||
code: "no cache plugin set on CacheManager",
|
||
desc: "ICachePlugin needs to be set before using readFromStorage or writeFromStorage"
|
||
},
|
||
noCryptoObj: {
|
||
code: "no_crypto_object",
|
||
desc: "No crypto object detected. This is required for the following operation: "
|
||
},
|
||
invalidCacheType: {
|
||
code: "invalid_cache_type",
|
||
desc: "Invalid cache type"
|
||
},
|
||
unexpectedAccountType: {
|
||
code: "unexpected_account_type",
|
||
desc: "Unexpected account type."
|
||
},
|
||
unexpectedCredentialType: {
|
||
code: "unexpected_credential_type",
|
||
desc: "Unexpected credential type."
|
||
},
|
||
invalidAssertion: {
|
||
code: "invalid_assertion",
|
||
desc: "Client assertion must meet requirements described in https://tools.ietf.org/html/rfc7515"
|
||
},
|
||
invalidClientCredential: {
|
||
code: "invalid_client_credential",
|
||
desc: "Client credential (secret, certificate, or assertion) must not be empty when creating a confidential client. An application should at most have one credential"
|
||
},
|
||
tokenRefreshRequired: {
|
||
code: "token_refresh_required",
|
||
desc: "Cannot return token from cache because it must be refreshed. This may be due to one of the following reasons: forceRefresh parameter is set to true, claims have been requested, there is no cached access token or it is expired."
|
||
},
|
||
userTimeoutReached: {
|
||
code: "user_timeout_reached",
|
||
desc: "User defined timeout for device code polling reached",
|
||
},
|
||
tokenClaimsRequired: {
|
||
code: "token_claims_cnf_required_for_signedjwt",
|
||
desc: "Cannot generate a POP jwt if the token_claims are not populated"
|
||
},
|
||
noAuthorizationCodeFromServer: {
|
||
code: "authorization_code_missing_from_server_response",
|
||
desc: "Srver response does not contain an authorization code to proceed"
|
||
}
|
||
};
|
||
/**
|
||
* Error thrown when there is an error in the client code running on the browser.
|
||
*/
|
||
var ClientAuthError = /** @class */ (function (_super) {
|
||
__extends(ClientAuthError, _super);
|
||
function ClientAuthError(errorCode, errorMessage) {
|
||
var _this = _super.call(this, errorCode, errorMessage) || this;
|
||
_this.name = "ClientAuthError";
|
||
Object.setPrototypeOf(_this, ClientAuthError.prototype);
|
||
return _this;
|
||
}
|
||
/**
|
||
* Creates an error thrown when client info object doesn't decode correctly.
|
||
* @param caughtError
|
||
*/
|
||
ClientAuthError.createClientInfoDecodingError = function (caughtError) {
|
||
return new ClientAuthError(ClientAuthErrorMessage.clientInfoDecodingError.code, ClientAuthErrorMessage.clientInfoDecodingError.desc + " Failed with error: " + caughtError);
|
||
};
|
||
/**
|
||
* Creates an error thrown if the client info is empty.
|
||
* @param rawClientInfo
|
||
*/
|
||
ClientAuthError.createClientInfoEmptyError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.clientInfoEmptyError.code, "" + ClientAuthErrorMessage.clientInfoEmptyError.desc);
|
||
};
|
||
/**
|
||
* Creates an error thrown when the id token extraction errors out.
|
||
* @param err
|
||
*/
|
||
ClientAuthError.createTokenParsingError = function (caughtExtractionError) {
|
||
return new ClientAuthError(ClientAuthErrorMessage.tokenParsingError.code, ClientAuthErrorMessage.tokenParsingError.desc + " Failed with error: " + caughtExtractionError);
|
||
};
|
||
/**
|
||
* Creates an error thrown when the id token string is null or empty.
|
||
* @param invalidRawTokenString
|
||
*/
|
||
ClientAuthError.createTokenNullOrEmptyError = function (invalidRawTokenString) {
|
||
return new ClientAuthError(ClientAuthErrorMessage.nullOrEmptyToken.code, ClientAuthErrorMessage.nullOrEmptyToken.desc + " Raw Token Value: " + invalidRawTokenString);
|
||
};
|
||
/**
|
||
* Creates an error thrown when the endpoint discovery doesn't complete correctly.
|
||
*/
|
||
ClientAuthError.createEndpointDiscoveryIncompleteError = function (errDetail) {
|
||
return new ClientAuthError(ClientAuthErrorMessage.endpointResolutionError.code, ClientAuthErrorMessage.endpointResolutionError.desc + " Detail: " + errDetail);
|
||
};
|
||
/**
|
||
* Creates an error thrown when the openid-configuration endpoint cannot be reached or does not contain the required data
|
||
*/
|
||
ClientAuthError.createUnableToGetOpenidConfigError = function (errDetail) {
|
||
return new ClientAuthError(ClientAuthErrorMessage.unableToGetOpenidConfigError.code, ClientAuthErrorMessage.unableToGetOpenidConfigError.desc + " Attempted to retrieve endpoints from: " + errDetail);
|
||
};
|
||
/**
|
||
* Creates an error thrown when the hash cannot be deserialized.
|
||
* @param hashParamObj
|
||
*/
|
||
ClientAuthError.createHashNotDeserializedError = function (hashParamObj) {
|
||
return new ClientAuthError(ClientAuthErrorMessage.hashNotDeserialized.code, ClientAuthErrorMessage.hashNotDeserialized.desc + " Given Object: " + hashParamObj);
|
||
};
|
||
/**
|
||
* Creates an error thrown when the state cannot be parsed.
|
||
* @param invalidState
|
||
*/
|
||
ClientAuthError.createInvalidStateError = function (invalidState, errorString) {
|
||
return new ClientAuthError(ClientAuthErrorMessage.invalidStateError.code, ClientAuthErrorMessage.invalidStateError.desc + " Invalid State: " + invalidState + ", Root Err: " + errorString);
|
||
};
|
||
/**
|
||
* Creates an error thrown when two states do not match.
|
||
*/
|
||
ClientAuthError.createStateMismatchError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.stateMismatchError.code, ClientAuthErrorMessage.stateMismatchError.desc);
|
||
};
|
||
/**
|
||
* Creates an error thrown when the state is not present
|
||
* @param missingState
|
||
*/
|
||
ClientAuthError.createStateNotFoundError = function (missingState) {
|
||
return new ClientAuthError(ClientAuthErrorMessage.stateNotFoundError.code, ClientAuthErrorMessage.stateNotFoundError.desc + ": " + missingState);
|
||
};
|
||
/**
|
||
* Creates an error thrown when the nonce does not match.
|
||
*/
|
||
ClientAuthError.createNonceMismatchError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.nonceMismatchError.code, ClientAuthErrorMessage.nonceMismatchError.desc);
|
||
};
|
||
/**
|
||
* Creates an error thrown when the mnonce is not present
|
||
* @param missingNonce
|
||
*/
|
||
ClientAuthError.createNonceNotFoundError = function (missingNonce) {
|
||
return new ClientAuthError(ClientAuthErrorMessage.nonceNotFoundError.code, ClientAuthErrorMessage.nonceNotFoundError.desc + ": " + missingNonce);
|
||
};
|
||
/**
|
||
* Creates an error thrown when the authorization code required for a token request is null or empty.
|
||
*/
|
||
ClientAuthError.createNoTokensFoundError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.noTokensFoundError.code, ClientAuthErrorMessage.noTokensFoundError.desc);
|
||
};
|
||
/**
|
||
* Throws error when multiple tokens are in cache.
|
||
*/
|
||
ClientAuthError.createMultipleMatchingTokensInCacheError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.multipleMatchingTokens.code, ClientAuthErrorMessage.multipleMatchingTokens.desc + ".");
|
||
};
|
||
/**
|
||
* Throws error when multiple accounts are in cache for the given params
|
||
*/
|
||
ClientAuthError.createMultipleMatchingAccountsInCacheError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.multipleMatchingAccounts.code, ClientAuthErrorMessage.multipleMatchingAccounts.desc);
|
||
};
|
||
/**
|
||
* Throws error when multiple appMetada are in cache for the given clientId.
|
||
*/
|
||
ClientAuthError.createMultipleMatchingAppMetadataInCacheError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.multipleMatchingAppMetadata.code, ClientAuthErrorMessage.multipleMatchingAppMetadata.desc);
|
||
};
|
||
/**
|
||
* Throws error when no auth code or refresh token is given to ServerTokenRequestParameters.
|
||
*/
|
||
ClientAuthError.createTokenRequestCannotBeMadeError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.tokenRequestCannotBeMade.code, ClientAuthErrorMessage.tokenRequestCannotBeMade.desc);
|
||
};
|
||
/**
|
||
* Throws error when attempting to append a null, undefined or empty scope to a set
|
||
* @param givenScope
|
||
*/
|
||
ClientAuthError.createAppendEmptyScopeToSetError = function (givenScope) {
|
||
return new ClientAuthError(ClientAuthErrorMessage.appendEmptyScopeError.code, ClientAuthErrorMessage.appendEmptyScopeError.desc + " Given Scope: " + givenScope);
|
||
};
|
||
/**
|
||
* Throws error when attempting to append a null, undefined or empty scope to a set
|
||
* @param givenScope
|
||
*/
|
||
ClientAuthError.createRemoveEmptyScopeFromSetError = function (givenScope) {
|
||
return new ClientAuthError(ClientAuthErrorMessage.removeEmptyScopeError.code, ClientAuthErrorMessage.removeEmptyScopeError.desc + " Given Scope: " + givenScope);
|
||
};
|
||
/**
|
||
* Throws error when attempting to append null or empty ScopeSet.
|
||
* @param appendError
|
||
*/
|
||
ClientAuthError.createAppendScopeSetError = function (appendError) {
|
||
return new ClientAuthError(ClientAuthErrorMessage.appendScopeSetError.code, ClientAuthErrorMessage.appendScopeSetError.desc + " Detail Error: " + appendError);
|
||
};
|
||
/**
|
||
* Throws error if ScopeSet is null or undefined.
|
||
* @param givenScopeSet
|
||
*/
|
||
ClientAuthError.createEmptyInputScopeSetError = function (givenScopeSet) {
|
||
return new ClientAuthError(ClientAuthErrorMessage.emptyInputScopeSetError.code, ClientAuthErrorMessage.emptyInputScopeSetError.desc + " Given ScopeSet: " + givenScopeSet);
|
||
};
|
||
/**
|
||
* Throws error if user sets CancellationToken.cancel = true during polling of token endpoint during device code flow
|
||
*/
|
||
ClientAuthError.createDeviceCodeCancelledError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.DeviceCodePollingCancelled.code, "" + ClientAuthErrorMessage.DeviceCodePollingCancelled.desc);
|
||
};
|
||
/**
|
||
* Throws error if device code is expired
|
||
*/
|
||
ClientAuthError.createDeviceCodeExpiredError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.DeviceCodeExpired.code, "" + ClientAuthErrorMessage.DeviceCodeExpired.desc);
|
||
};
|
||
/**
|
||
* Throws error when silent requests are made without an account object
|
||
*/
|
||
ClientAuthError.createNoAccountInSilentRequestError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.NoAccountInSilentRequest.code, "" + ClientAuthErrorMessage.NoAccountInSilentRequest.desc);
|
||
};
|
||
/**
|
||
* Throws error when cache record is null or undefined.
|
||
*/
|
||
ClientAuthError.createNullOrUndefinedCacheRecord = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.invalidCacheRecord.code, ClientAuthErrorMessage.invalidCacheRecord.desc);
|
||
};
|
||
/**
|
||
* Throws error when provided environment is not part of the CloudDiscoveryMetadata object
|
||
*/
|
||
ClientAuthError.createInvalidCacheEnvironmentError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.invalidCacheEnvironment.code, ClientAuthErrorMessage.invalidCacheEnvironment.desc);
|
||
};
|
||
/**
|
||
* Throws error when account is not found in cache.
|
||
*/
|
||
ClientAuthError.createNoAccountFoundError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.noAccountFound.code, ClientAuthErrorMessage.noAccountFound.desc);
|
||
};
|
||
/**
|
||
* Throws error if ICachePlugin not set on CacheManager.
|
||
*/
|
||
ClientAuthError.createCachePluginError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.CachePluginError.code, "" + ClientAuthErrorMessage.CachePluginError.desc);
|
||
};
|
||
/**
|
||
* Throws error if crypto object not found.
|
||
* @param operationName
|
||
*/
|
||
ClientAuthError.createNoCryptoObjectError = function (operationName) {
|
||
return new ClientAuthError(ClientAuthErrorMessage.noCryptoObj.code, "" + ClientAuthErrorMessage.noCryptoObj.desc + operationName);
|
||
};
|
||
/**
|
||
* Throws error if cache type is invalid.
|
||
*/
|
||
ClientAuthError.createInvalidCacheTypeError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.invalidCacheType.code, "" + ClientAuthErrorMessage.invalidCacheType.desc);
|
||
};
|
||
/**
|
||
* Throws error if unexpected account type.
|
||
*/
|
||
ClientAuthError.createUnexpectedAccountTypeError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.unexpectedAccountType.code, "" + ClientAuthErrorMessage.unexpectedAccountType.desc);
|
||
};
|
||
/**
|
||
* Throws error if unexpected credential type.
|
||
*/
|
||
ClientAuthError.createUnexpectedCredentialTypeError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.unexpectedCredentialType.code, "" + ClientAuthErrorMessage.unexpectedCredentialType.desc);
|
||
};
|
||
/**
|
||
* Throws error if client assertion is not valid.
|
||
*/
|
||
ClientAuthError.createInvalidAssertionError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.invalidAssertion.code, "" + ClientAuthErrorMessage.invalidAssertion.desc);
|
||
};
|
||
/**
|
||
* Throws error if client assertion is not valid.
|
||
*/
|
||
ClientAuthError.createInvalidCredentialError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.invalidClientCredential.code, "" + ClientAuthErrorMessage.invalidClientCredential.desc);
|
||
};
|
||
/**
|
||
* Throws error if token cannot be retrieved from cache due to refresh being required.
|
||
*/
|
||
ClientAuthError.createRefreshRequiredError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.tokenRefreshRequired.code, ClientAuthErrorMessage.tokenRefreshRequired.desc);
|
||
};
|
||
/**
|
||
* Throws error if the user defined timeout is reached.
|
||
*/
|
||
ClientAuthError.createUserTimeoutReachedError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.userTimeoutReached.code, ClientAuthErrorMessage.userTimeoutReached.desc);
|
||
};
|
||
/*
|
||
* Throws error if token claims are not populated for a signed jwt generation
|
||
*/
|
||
ClientAuthError.createTokenClaimsRequiredError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.tokenClaimsRequired.code, ClientAuthErrorMessage.tokenClaimsRequired.desc);
|
||
};
|
||
/**
|
||
* Throws error when the authorization code is missing from the server response
|
||
*/
|
||
ClientAuthError.createNoAuthCodeInServerResponseError = function () {
|
||
return new ClientAuthError(ClientAuthErrorMessage.noAuthorizationCodeFromServer.code, ClientAuthErrorMessage.noAuthorizationCodeFromServer.desc);
|
||
};
|
||
return ClientAuthError;
|
||
}(AuthError));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* @hidden
|
||
*/
|
||
var StringUtils = /** @class */ (function () {
|
||
function StringUtils() {
|
||
}
|
||
/**
|
||
* decode a JWT
|
||
*
|
||
* @param authToken
|
||
*/
|
||
StringUtils.decodeAuthToken = function (authToken) {
|
||
if (StringUtils.isEmpty(authToken)) {
|
||
throw ClientAuthError.createTokenNullOrEmptyError(authToken);
|
||
}
|
||
var tokenPartsRegex = /^([^\.\s]*)\.([^\.\s]+)\.([^\.\s]*)$/;
|
||
var matches = tokenPartsRegex.exec(authToken);
|
||
if (!matches || matches.length < 4) {
|
||
throw ClientAuthError.createTokenParsingError("Given token is malformed: " + JSON.stringify(authToken));
|
||
}
|
||
var crackedToken = {
|
||
header: matches[1],
|
||
JWSPayload: matches[2],
|
||
JWSSig: matches[3]
|
||
};
|
||
return crackedToken;
|
||
};
|
||
/**
|
||
* Check if a string is empty.
|
||
*
|
||
* @param str
|
||
*/
|
||
StringUtils.isEmpty = function (str) {
|
||
return (typeof str === "undefined" || !str || 0 === str.length);
|
||
};
|
||
StringUtils.startsWith = function (str, search) {
|
||
return str.indexOf(search) === 0;
|
||
};
|
||
StringUtils.endsWith = function (str, search) {
|
||
return (str.length >= search.length) && (str.lastIndexOf(search) === (str.length - search.length));
|
||
};
|
||
/**
|
||
* Parses string into an object.
|
||
*
|
||
* @param query
|
||
*/
|
||
StringUtils.queryStringToObject = function (query) {
|
||
var match; // Regex for replacing addition symbol with a space
|
||
var pl = /\+/g;
|
||
var search = /([^&=]+)=([^&]*)/g;
|
||
var decode = function (s) { return decodeURIComponent(decodeURIComponent(s.replace(pl, " "))); };
|
||
var obj = {};
|
||
match = search.exec(query);
|
||
while (match) {
|
||
obj[decode(match[1])] = decode(match[2]);
|
||
match = search.exec(query);
|
||
}
|
||
return obj;
|
||
};
|
||
/**
|
||
* Trims entries in an array.
|
||
*
|
||
* @param arr
|
||
*/
|
||
StringUtils.trimArrayEntries = function (arr) {
|
||
return arr.map(function (entry) { return entry.trim(); });
|
||
};
|
||
/**
|
||
* Removes empty strings from array
|
||
* @param arr
|
||
*/
|
||
StringUtils.removeEmptyStringsFromArray = function (arr) {
|
||
return arr.filter(function (entry) {
|
||
return !StringUtils.isEmpty(entry);
|
||
});
|
||
};
|
||
/**
|
||
* Attempts to parse a string into JSON
|
||
* @param str
|
||
*/
|
||
StringUtils.jsonParseHelper = function (str) {
|
||
try {
|
||
return JSON.parse(str);
|
||
}
|
||
catch (e) {
|
||
return null;
|
||
}
|
||
};
|
||
/**
|
||
* Tests if a given string matches a given pattern, with support for wildcards.
|
||
* @param pattern Wildcard pattern to string match. Supports "*" for wildcards
|
||
* @param input String to match against
|
||
*/
|
||
StringUtils.matchPattern = function (pattern, input) {
|
||
// https://stackoverflow.com/a/3117248/4888559
|
||
var regex = new RegExp(pattern.replace(/\*/g, "[^ ]*"));
|
||
return regex.test(input);
|
||
};
|
||
return StringUtils;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* Log message level.
|
||
*/
|
||
var LogLevel;
|
||
(function (LogLevel) {
|
||
LogLevel[LogLevel["Error"] = 0] = "Error";
|
||
LogLevel[LogLevel["Warning"] = 1] = "Warning";
|
||
LogLevel[LogLevel["Info"] = 2] = "Info";
|
||
LogLevel[LogLevel["Verbose"] = 3] = "Verbose";
|
||
})(LogLevel || (LogLevel = {}));
|
||
/**
|
||
* Class which facilitates logging of messages to a specific place.
|
||
*/
|
||
var Logger = /** @class */ (function () {
|
||
function Logger(loggerOptions, packageName, packageVersion) {
|
||
// Current log level, defaults to info.
|
||
this.level = LogLevel.Info;
|
||
var defaultLoggerCallback = function () { };
|
||
this.localCallback = loggerOptions.loggerCallback || defaultLoggerCallback;
|
||
this.piiLoggingEnabled = loggerOptions.piiLoggingEnabled || false;
|
||
this.level = loggerOptions.logLevel || LogLevel.Info;
|
||
this.packageName = packageName || Constants.EMPTY_STRING;
|
||
this.packageVersion = packageVersion || Constants.EMPTY_STRING;
|
||
}
|
||
/**
|
||
* Create new Logger with existing configurations.
|
||
*/
|
||
Logger.prototype.clone = function (packageName, packageVersion) {
|
||
return new Logger({ loggerCallback: this.localCallback, piiLoggingEnabled: this.piiLoggingEnabled, logLevel: this.level }, packageName, packageVersion);
|
||
};
|
||
/**
|
||
* Log message with required options.
|
||
*/
|
||
Logger.prototype.logMessage = function (logMessage, options) {
|
||
if ((options.logLevel > this.level) || (!this.piiLoggingEnabled && options.containsPii)) {
|
||
return;
|
||
}
|
||
var timestamp = new Date().toUTCString();
|
||
var logHeader = StringUtils.isEmpty(this.correlationId) ? "[" + timestamp + "] : " : "[" + timestamp + "] : [" + this.correlationId + "]";
|
||
var log = logHeader + " : " + this.packageName + "@" + this.packageVersion + " : " + LogLevel[options.logLevel] + " - " + logMessage;
|
||
// debug(`msal:${LogLevel[options.logLevel]}${options.containsPii ? "-Pii": ""}${options.context ? `:${options.context}` : ""}`)(logMessage);
|
||
this.executeCallback(options.logLevel, log, options.containsPii || false);
|
||
};
|
||
/**
|
||
* Execute callback with message.
|
||
*/
|
||
Logger.prototype.executeCallback = function (level, message, containsPii) {
|
||
if (this.localCallback) {
|
||
this.localCallback(level, message, containsPii);
|
||
}
|
||
};
|
||
/**
|
||
* Logs error messages.
|
||
*/
|
||
Logger.prototype.error = function (message, correlationId) {
|
||
this.logMessage(message, {
|
||
logLevel: LogLevel.Error,
|
||
containsPii: false,
|
||
correlationId: correlationId || ""
|
||
});
|
||
};
|
||
/**
|
||
* Logs error messages with PII.
|
||
*/
|
||
Logger.prototype.errorPii = function (message, correlationId) {
|
||
this.logMessage(message, {
|
||
logLevel: LogLevel.Error,
|
||
containsPii: true,
|
||
correlationId: correlationId || ""
|
||
});
|
||
};
|
||
/**
|
||
* Logs warning messages.
|
||
*/
|
||
Logger.prototype.warning = function (message, correlationId) {
|
||
this.logMessage(message, {
|
||
logLevel: LogLevel.Warning,
|
||
containsPii: false,
|
||
correlationId: correlationId || ""
|
||
});
|
||
};
|
||
/**
|
||
* Logs warning messages with PII.
|
||
*/
|
||
Logger.prototype.warningPii = function (message, correlationId) {
|
||
this.logMessage(message, {
|
||
logLevel: LogLevel.Warning,
|
||
containsPii: true,
|
||
correlationId: correlationId || ""
|
||
});
|
||
};
|
||
/**
|
||
* Logs info messages.
|
||
*/
|
||
Logger.prototype.info = function (message, correlationId) {
|
||
this.logMessage(message, {
|
||
logLevel: LogLevel.Info,
|
||
containsPii: false,
|
||
correlationId: correlationId || ""
|
||
});
|
||
};
|
||
/**
|
||
* Logs info messages with PII.
|
||
*/
|
||
Logger.prototype.infoPii = function (message, correlationId) {
|
||
this.logMessage(message, {
|
||
logLevel: LogLevel.Info,
|
||
containsPii: true,
|
||
correlationId: correlationId || ""
|
||
});
|
||
};
|
||
/**
|
||
* Logs verbose messages.
|
||
*/
|
||
Logger.prototype.verbose = function (message, correlationId) {
|
||
this.logMessage(message, {
|
||
logLevel: LogLevel.Verbose,
|
||
containsPii: false,
|
||
correlationId: correlationId || ""
|
||
});
|
||
};
|
||
/**
|
||
* Logs verbose messages with PII.
|
||
*/
|
||
Logger.prototype.verbosePii = function (message, correlationId) {
|
||
this.logMessage(message, {
|
||
logLevel: LogLevel.Verbose,
|
||
containsPii: true,
|
||
correlationId: correlationId || ""
|
||
});
|
||
};
|
||
/**
|
||
* Returns whether PII Logging is enabled or not.
|
||
*/
|
||
Logger.prototype.isPiiLoggingEnabled = function () {
|
||
return this.piiLoggingEnabled || false;
|
||
};
|
||
return Logger;
|
||
}());
|
||
|
||
/* eslint-disable header/header */
|
||
var name = "@azure/msal-common";
|
||
var version = "4.0.1";
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* Base type for credentials to be stored in the cache: eg: ACCESS_TOKEN, ID_TOKEN etc
|
||
*
|
||
* Key:Value Schema:
|
||
*
|
||
* Key: <home_account_id*>-<environment>-<credential_type>-<client_id>-<realm*>-<target*>
|
||
*
|
||
* Value Schema:
|
||
* {
|
||
* homeAccountId: home account identifier for the auth scheme,
|
||
* environment: entity that issued the token, represented as a full host
|
||
* credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other
|
||
* clientId: client ID of the application
|
||
* secret: Actual credential as a string
|
||
* familyId: Family ID identifier, usually only used for refresh tokens
|
||
* realm: Full tenant or organizational identifier that the account belongs to
|
||
* target: Permissions that are included in the token, or for refresh tokens, the resource identifier.
|
||
* oboAssertion: access token passed in as part of OBO request
|
||
* }
|
||
*/
|
||
var CredentialEntity = /** @class */ (function () {
|
||
function CredentialEntity() {
|
||
}
|
||
/**
|
||
* Generate Account Id key component as per the schema: <home_account_id>-<environment>
|
||
*/
|
||
CredentialEntity.prototype.generateAccountId = function () {
|
||
return CredentialEntity.generateAccountIdForCacheKey(this.homeAccountId, this.environment);
|
||
};
|
||
/**
|
||
* Generate Credential Id key component as per the schema: <credential_type>-<client_id>-<realm>
|
||
*/
|
||
CredentialEntity.prototype.generateCredentialId = function () {
|
||
return CredentialEntity.generateCredentialIdForCacheKey(this.credentialType, this.clientId, this.realm, this.familyId);
|
||
};
|
||
/**
|
||
* Generate target key component as per schema: <target>
|
||
*/
|
||
CredentialEntity.prototype.generateTarget = function () {
|
||
return CredentialEntity.generateTargetForCacheKey(this.target);
|
||
};
|
||
/**
|
||
* generates credential key
|
||
*/
|
||
CredentialEntity.prototype.generateCredentialKey = function () {
|
||
return CredentialEntity.generateCredentialCacheKey(this.homeAccountId, this.environment, this.credentialType, this.clientId, this.realm, this.target, this.familyId);
|
||
};
|
||
/**
|
||
* returns the type of the cache (in this case credential)
|
||
*/
|
||
CredentialEntity.prototype.generateType = function () {
|
||
switch (this.credentialType) {
|
||
case CredentialType.ID_TOKEN:
|
||
return CacheType.ID_TOKEN;
|
||
case CredentialType.ACCESS_TOKEN:
|
||
return CacheType.ACCESS_TOKEN;
|
||
case CredentialType.REFRESH_TOKEN:
|
||
return CacheType.REFRESH_TOKEN;
|
||
default: {
|
||
throw ClientAuthError.createUnexpectedCredentialTypeError();
|
||
}
|
||
}
|
||
};
|
||
/**
|
||
* helper function to return `CredentialType`
|
||
* @param key
|
||
*/
|
||
CredentialEntity.getCredentialType = function (key) {
|
||
if (key.indexOf(CredentialType.ACCESS_TOKEN.toLowerCase()) !== -1) {
|
||
return CredentialType.ACCESS_TOKEN;
|
||
}
|
||
else if (key.indexOf(CredentialType.ID_TOKEN.toLowerCase()) !== -1) {
|
||
return CredentialType.ID_TOKEN;
|
||
}
|
||
else if (key.indexOf(CredentialType.REFRESH_TOKEN.toLowerCase()) !== -1) {
|
||
return CredentialType.REFRESH_TOKEN;
|
||
}
|
||
return Constants.NOT_DEFINED;
|
||
};
|
||
/**
|
||
* generates credential key
|
||
*/
|
||
CredentialEntity.generateCredentialCacheKey = function (homeAccountId, environment, credentialType, clientId, realm, target, familyId) {
|
||
var credentialKey = [
|
||
this.generateAccountIdForCacheKey(homeAccountId, environment),
|
||
this.generateCredentialIdForCacheKey(credentialType, clientId, realm, familyId),
|
||
this.generateTargetForCacheKey(target),
|
||
];
|
||
return credentialKey.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
|
||
};
|
||
/**
|
||
* generates Account Id for keys
|
||
* @param homeAccountId
|
||
* @param environment
|
||
*/
|
||
CredentialEntity.generateAccountIdForCacheKey = function (homeAccountId, environment) {
|
||
var accountId = [homeAccountId, environment];
|
||
return accountId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
|
||
};
|
||
/**
|
||
* Generates Credential Id for keys
|
||
* @param credentialType
|
||
* @param realm
|
||
* @param clientId
|
||
* @param familyId
|
||
*/
|
||
CredentialEntity.generateCredentialIdForCacheKey = function (credentialType, clientId, realm, familyId) {
|
||
var clientOrFamilyId = credentialType === CredentialType.REFRESH_TOKEN
|
||
? familyId || clientId
|
||
: clientId;
|
||
var credentialId = [
|
||
credentialType,
|
||
clientOrFamilyId,
|
||
realm || "",
|
||
];
|
||
return credentialId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
|
||
};
|
||
/**
|
||
* Generate target key component as per schema: <target>
|
||
*/
|
||
CredentialEntity.generateTargetForCacheKey = function (scopes) {
|
||
return (scopes || "").toLowerCase();
|
||
};
|
||
return CredentialEntity;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* ClientConfigurationErrorMessage class containing string constants used by error codes and messages.
|
||
*/
|
||
var ClientConfigurationErrorMessage = {
|
||
redirectUriNotSet: {
|
||
code: "redirect_uri_empty",
|
||
desc: "A redirect URI is required for all calls, and none has been set."
|
||
},
|
||
postLogoutUriNotSet: {
|
||
code: "post_logout_uri_empty",
|
||
desc: "A post logout redirect has not been set."
|
||
},
|
||
claimsRequestParsingError: {
|
||
code: "claims_request_parsing_error",
|
||
desc: "Could not parse the given claims request object."
|
||
},
|
||
authorityUriInsecure: {
|
||
code: "authority_uri_insecure",
|
||
desc: "Authority URIs must use https. Please see here for valid authority configuration options: https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-js-initializing-client-applications#configuration-options"
|
||
},
|
||
urlParseError: {
|
||
code: "url_parse_error",
|
||
desc: "URL could not be parsed into appropriate segments."
|
||
},
|
||
urlEmptyError: {
|
||
code: "empty_url_error",
|
||
desc: "URL was empty or null."
|
||
},
|
||
emptyScopesError: {
|
||
code: "empty_input_scopes_error",
|
||
desc: "Scopes cannot be passed as null, undefined or empty array because they are required to obtain an access token."
|
||
},
|
||
nonArrayScopesError: {
|
||
code: "nonarray_input_scopes_error",
|
||
desc: "Scopes cannot be passed as non-array."
|
||
},
|
||
clientIdSingleScopeError: {
|
||
code: "clientid_input_scopes_error",
|
||
desc: "Client ID can only be provided as a single scope."
|
||
},
|
||
invalidPrompt: {
|
||
code: "invalid_prompt_value",
|
||
desc: "Supported prompt values are 'login', 'select_account', 'consent' and 'none'. Please see here for valid configuration options: https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-js-initializing-client-applications#configuration-options",
|
||
},
|
||
invalidClaimsRequest: {
|
||
code: "invalid_claims",
|
||
desc: "Given claims parameter must be a stringified JSON object."
|
||
},
|
||
tokenRequestEmptyError: {
|
||
code: "token_request_empty",
|
||
desc: "Token request was empty and not found in cache."
|
||
},
|
||
logoutRequestEmptyError: {
|
||
code: "logout_request_empty",
|
||
desc: "The logout request was null or undefined."
|
||
},
|
||
invalidCodeChallengeMethod: {
|
||
code: "invalid_code_challenge_method",
|
||
desc: "code_challenge_method passed is invalid. Valid values are \"plain\" and \"S256\"."
|
||
},
|
||
invalidCodeChallengeParams: {
|
||
code: "pkce_params_missing",
|
||
desc: "Both params: code_challenge and code_challenge_method are to be passed if to be sent in the request"
|
||
},
|
||
invalidCloudDiscoveryMetadata: {
|
||
code: "invalid_cloud_discovery_metadata",
|
||
desc: "Invalid cloudDiscoveryMetadata provided. Must be a JSON object containing tenant_discovery_endpoint and metadata fields"
|
||
},
|
||
invalidAuthorityMetadata: {
|
||
code: "invalid_authority_metadata",
|
||
desc: "Invalid authorityMetadata provided. Must by a JSON object containing authorization_endpoint, token_endpoint, end_session_endpoint, issuer fields."
|
||
},
|
||
untrustedAuthority: {
|
||
code: "untrusted_authority",
|
||
desc: "The provided authority is not a trusted authority. Please include this authority in the knownAuthorities config parameter."
|
||
},
|
||
resourceRequestParametersRequired: {
|
||
code: "resourceRequest_parameters_required",
|
||
desc: "resourceRequestMethod and resourceRequestUri are required"
|
||
}
|
||
};
|
||
/**
|
||
* Error thrown when there is an error in configuration of the MSAL.js library.
|
||
*/
|
||
var ClientConfigurationError = /** @class */ (function (_super) {
|
||
__extends(ClientConfigurationError, _super);
|
||
function ClientConfigurationError(errorCode, errorMessage) {
|
||
var _this = _super.call(this, errorCode, errorMessage) || this;
|
||
_this.name = "ClientConfigurationError";
|
||
Object.setPrototypeOf(_this, ClientConfigurationError.prototype);
|
||
return _this;
|
||
}
|
||
/**
|
||
* Creates an error thrown when the redirect uri is empty (not set by caller)
|
||
*/
|
||
ClientConfigurationError.createRedirectUriEmptyError = function () {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.redirectUriNotSet.code, ClientConfigurationErrorMessage.redirectUriNotSet.desc);
|
||
};
|
||
/**
|
||
* Creates an error thrown when the post-logout redirect uri is empty (not set by caller)
|
||
*/
|
||
ClientConfigurationError.createPostLogoutRedirectUriEmptyError = function () {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.postLogoutUriNotSet.code, ClientConfigurationErrorMessage.postLogoutUriNotSet.desc);
|
||
};
|
||
/**
|
||
* Creates an error thrown when the claims request could not be successfully parsed
|
||
*/
|
||
ClientConfigurationError.createClaimsRequestParsingError = function (claimsRequestParseError) {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.claimsRequestParsingError.code, ClientConfigurationErrorMessage.claimsRequestParsingError.desc + " Given value: " + claimsRequestParseError);
|
||
};
|
||
/**
|
||
* Creates an error thrown if authority uri is given an insecure protocol.
|
||
* @param urlString
|
||
*/
|
||
ClientConfigurationError.createInsecureAuthorityUriError = function (urlString) {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.authorityUriInsecure.code, ClientConfigurationErrorMessage.authorityUriInsecure.desc + " Given URI: " + urlString);
|
||
};
|
||
/**
|
||
* Creates an error thrown if URL string does not parse into separate segments.
|
||
* @param urlString
|
||
*/
|
||
ClientConfigurationError.createUrlParseError = function (urlParseError) {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.urlParseError.code, ClientConfigurationErrorMessage.urlParseError.desc + " Given Error: " + urlParseError);
|
||
};
|
||
/**
|
||
* Creates an error thrown if URL string is empty or null.
|
||
* @param urlString
|
||
*/
|
||
ClientConfigurationError.createUrlEmptyError = function () {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.urlEmptyError.code, ClientConfigurationErrorMessage.urlEmptyError.desc);
|
||
};
|
||
/**
|
||
* Error thrown when scopes are not an array
|
||
* @param inputScopes
|
||
*/
|
||
ClientConfigurationError.createScopesNonArrayError = function (inputScopes) {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.nonArrayScopesError.code, ClientConfigurationErrorMessage.nonArrayScopesError.desc + " Given Scopes: " + inputScopes);
|
||
};
|
||
/**
|
||
* Error thrown when scopes are empty.
|
||
* @param scopesValue
|
||
*/
|
||
ClientConfigurationError.createEmptyScopesArrayError = function (inputScopes) {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.emptyScopesError.code, ClientConfigurationErrorMessage.emptyScopesError.desc + " Given Scopes: " + inputScopes);
|
||
};
|
||
/**
|
||
* Error thrown when client id scope is not provided as single scope.
|
||
* @param inputScopes
|
||
*/
|
||
ClientConfigurationError.createClientIdSingleScopeError = function (inputScopes) {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.clientIdSingleScopeError.code, ClientConfigurationErrorMessage.clientIdSingleScopeError.desc + " Given Scopes: " + inputScopes);
|
||
};
|
||
/**
|
||
* Error thrown when prompt is not an allowed type.
|
||
* @param promptValue
|
||
*/
|
||
ClientConfigurationError.createInvalidPromptError = function (promptValue) {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidPrompt.code, ClientConfigurationErrorMessage.invalidPrompt.desc + " Given value: " + promptValue);
|
||
};
|
||
/**
|
||
* Creates error thrown when claims parameter is not a stringified JSON object
|
||
*/
|
||
ClientConfigurationError.createInvalidClaimsRequestError = function () {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidClaimsRequest.code, ClientConfigurationErrorMessage.invalidClaimsRequest.desc);
|
||
};
|
||
/**
|
||
* Throws error when token request is empty and nothing cached in storage.
|
||
*/
|
||
ClientConfigurationError.createEmptyLogoutRequestError = function () {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.logoutRequestEmptyError.code, ClientConfigurationErrorMessage.logoutRequestEmptyError.desc);
|
||
};
|
||
/**
|
||
* Throws error when token request is empty and nothing cached in storage.
|
||
*/
|
||
ClientConfigurationError.createEmptyTokenRequestError = function () {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.tokenRequestEmptyError.code, ClientConfigurationErrorMessage.tokenRequestEmptyError.desc);
|
||
};
|
||
/**
|
||
* Throws error when an invalid code_challenge_method is passed by the user
|
||
*/
|
||
ClientConfigurationError.createInvalidCodeChallengeMethodError = function () {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidCodeChallengeMethod.code, ClientConfigurationErrorMessage.invalidCodeChallengeMethod.desc);
|
||
};
|
||
/**
|
||
* Throws error when both params: code_challenge and code_challenge_method are not passed together
|
||
*/
|
||
ClientConfigurationError.createInvalidCodeChallengeParamsError = function () {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidCodeChallengeParams.code, ClientConfigurationErrorMessage.invalidCodeChallengeParams.desc);
|
||
};
|
||
/**
|
||
* Throws an error when the user passes invalid cloudDiscoveryMetadata
|
||
*/
|
||
ClientConfigurationError.createInvalidCloudDiscoveryMetadataError = function () {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidCloudDiscoveryMetadata.code, ClientConfigurationErrorMessage.invalidCloudDiscoveryMetadata.desc);
|
||
};
|
||
/**
|
||
* Throws an error when the user passes invalid cloudDiscoveryMetadata
|
||
*/
|
||
ClientConfigurationError.createInvalidAuthorityMetadataError = function () {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidAuthorityMetadata.code, ClientConfigurationErrorMessage.invalidAuthorityMetadata.desc);
|
||
};
|
||
/**
|
||
* Throws error when provided authority is not a member of the trusted host list
|
||
*/
|
||
ClientConfigurationError.createUntrustedAuthorityError = function () {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.untrustedAuthority.code, ClientConfigurationErrorMessage.untrustedAuthority.desc);
|
||
};
|
||
/**
|
||
* Throws error when resourceRequestMethod or resourceRequestUri is missing
|
||
*/
|
||
ClientConfigurationError.createResourceRequestParametersRequiredError = function () {
|
||
return new ClientConfigurationError(ClientConfigurationErrorMessage.resourceRequestParametersRequired.code, ClientConfigurationErrorMessage.resourceRequestParametersRequired.desc);
|
||
};
|
||
return ClientConfigurationError;
|
||
}(ClientAuthError));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* The ScopeSet class creates a set of scopes. Scopes are case-insensitive, unique values, so the Set object in JS makes
|
||
* the most sense to implement for this class. All scopes are trimmed and converted to lower case strings in intersection and union functions
|
||
* to ensure uniqueness of strings.
|
||
*/
|
||
var ScopeSet = /** @class */ (function () {
|
||
function ScopeSet(inputScopes) {
|
||
var _this = this;
|
||
// Filter empty string and null/undefined array items
|
||
var scopeArr = inputScopes ? StringUtils.trimArrayEntries(__spreadArrays(inputScopes)) : [];
|
||
var filteredInput = scopeArr ? StringUtils.removeEmptyStringsFromArray(scopeArr) : [];
|
||
// Validate and filter scopes (validate function throws if validation fails)
|
||
this.validateInputScopes(filteredInput);
|
||
this.scopes = new Set(); // Iterator in constructor not supported by IE11
|
||
filteredInput.forEach(function (scope) { return _this.scopes.add(scope); });
|
||
}
|
||
/**
|
||
* Factory method to create ScopeSet from space-delimited string
|
||
* @param inputScopeString
|
||
* @param appClientId
|
||
* @param scopesRequired
|
||
*/
|
||
ScopeSet.fromString = function (inputScopeString) {
|
||
inputScopeString = inputScopeString || "";
|
||
var inputScopes = inputScopeString.split(" ");
|
||
return new ScopeSet(inputScopes);
|
||
};
|
||
/**
|
||
* Used to validate the scopes input parameter requested by the developer.
|
||
* @param {Array<string>} inputScopes - Developer requested permissions. Not all scopes are guaranteed to be included in the access token returned.
|
||
* @param {boolean} scopesRequired - Boolean indicating whether the scopes array is required or not
|
||
*/
|
||
ScopeSet.prototype.validateInputScopes = function (inputScopes) {
|
||
// Check if scopes are required but not given or is an empty array
|
||
if (!inputScopes || inputScopes.length < 1) {
|
||
throw ClientConfigurationError.createEmptyScopesArrayError(inputScopes);
|
||
}
|
||
};
|
||
/**
|
||
* Check if a given scope is present in this set of scopes.
|
||
* @param scope
|
||
*/
|
||
ScopeSet.prototype.containsScope = function (scope) {
|
||
var lowerCaseScopes = this.printScopesLowerCase().split(" ");
|
||
var lowerCaseScopesSet = new ScopeSet(lowerCaseScopes);
|
||
// compare lowercase scopes
|
||
return !StringUtils.isEmpty(scope) ? lowerCaseScopesSet.scopes.has(scope.toLowerCase()) : false;
|
||
};
|
||
/**
|
||
* Check if a set of scopes is present in this set of scopes.
|
||
* @param scopeSet
|
||
*/
|
||
ScopeSet.prototype.containsScopeSet = function (scopeSet) {
|
||
var _this = this;
|
||
if (!scopeSet || scopeSet.scopes.size <= 0) {
|
||
return false;
|
||
}
|
||
return (this.scopes.size >= scopeSet.scopes.size && scopeSet.asArray().every(function (scope) { return _this.containsScope(scope); }));
|
||
};
|
||
/**
|
||
* Check if set of scopes contains only the defaults
|
||
*/
|
||
ScopeSet.prototype.containsOnlyOIDCScopes = function () {
|
||
var _this = this;
|
||
var defaultScopeCount = 0;
|
||
OIDC_SCOPES.forEach(function (defaultScope) {
|
||
if (_this.containsScope(defaultScope)) {
|
||
defaultScopeCount += 1;
|
||
}
|
||
});
|
||
return this.scopes.size === defaultScopeCount;
|
||
};
|
||
/**
|
||
* Appends single scope if passed
|
||
* @param newScope
|
||
*/
|
||
ScopeSet.prototype.appendScope = function (newScope) {
|
||
if (!StringUtils.isEmpty(newScope)) {
|
||
this.scopes.add(newScope.trim());
|
||
}
|
||
};
|
||
/**
|
||
* Appends multiple scopes if passed
|
||
* @param newScopes
|
||
*/
|
||
ScopeSet.prototype.appendScopes = function (newScopes) {
|
||
var _this = this;
|
||
try {
|
||
newScopes.forEach(function (newScope) { return _this.appendScope(newScope); });
|
||
}
|
||
catch (e) {
|
||
throw ClientAuthError.createAppendScopeSetError(e);
|
||
}
|
||
};
|
||
/**
|
||
* Removes element from set of scopes.
|
||
* @param scope
|
||
*/
|
||
ScopeSet.prototype.removeScope = function (scope) {
|
||
if (StringUtils.isEmpty(scope)) {
|
||
throw ClientAuthError.createRemoveEmptyScopeFromSetError(scope);
|
||
}
|
||
this.scopes.delete(scope.trim());
|
||
};
|
||
/**
|
||
* Removes default scopes from set of scopes
|
||
* Primarily used to prevent cache misses if the default scopes are not returned from the server
|
||
*/
|
||
ScopeSet.prototype.removeOIDCScopes = function () {
|
||
var _this = this;
|
||
OIDC_SCOPES.forEach(function (defaultScope) {
|
||
_this.scopes.delete(defaultScope);
|
||
});
|
||
};
|
||
/**
|
||
* Combines an array of scopes with the current set of scopes.
|
||
* @param otherScopes
|
||
*/
|
||
ScopeSet.prototype.unionScopeSets = function (otherScopes) {
|
||
if (!otherScopes) {
|
||
throw ClientAuthError.createEmptyInputScopeSetError(otherScopes);
|
||
}
|
||
var unionScopes = new Set(); // Iterator in constructor not supported in IE11
|
||
otherScopes.scopes.forEach(function (scope) { return unionScopes.add(scope.toLowerCase()); });
|
||
this.scopes.forEach(function (scope) { return unionScopes.add(scope.toLowerCase()); });
|
||
return unionScopes;
|
||
};
|
||
/**
|
||
* Check if scopes intersect between this set and another.
|
||
* @param otherScopes
|
||
*/
|
||
ScopeSet.prototype.intersectingScopeSets = function (otherScopes) {
|
||
if (!otherScopes) {
|
||
throw ClientAuthError.createEmptyInputScopeSetError(otherScopes);
|
||
}
|
||
// Do not allow OIDC scopes to be the only intersecting scopes
|
||
if (!otherScopes.containsOnlyOIDCScopes()) {
|
||
otherScopes.removeOIDCScopes();
|
||
}
|
||
var unionScopes = this.unionScopeSets(otherScopes);
|
||
var sizeOtherScopes = otherScopes.getScopeCount();
|
||
var sizeThisScopes = this.getScopeCount();
|
||
var sizeUnionScopes = unionScopes.size;
|
||
return sizeUnionScopes < (sizeThisScopes + sizeOtherScopes);
|
||
};
|
||
/**
|
||
* Returns size of set of scopes.
|
||
*/
|
||
ScopeSet.prototype.getScopeCount = function () {
|
||
return this.scopes.size;
|
||
};
|
||
/**
|
||
* Returns the scopes as an array of string values
|
||
*/
|
||
ScopeSet.prototype.asArray = function () {
|
||
var array = [];
|
||
this.scopes.forEach(function (val) { return array.push(val); });
|
||
return array;
|
||
};
|
||
/**
|
||
* Prints scopes into a space-delimited string
|
||
*/
|
||
ScopeSet.prototype.printScopes = function () {
|
||
if (this.scopes) {
|
||
var scopeArr = this.asArray();
|
||
return scopeArr.join(" ");
|
||
}
|
||
return "";
|
||
};
|
||
/**
|
||
* Prints scopes into a space-delimited lower-case string (used for caching)
|
||
*/
|
||
ScopeSet.prototype.printScopesLowerCase = function () {
|
||
return this.printScopes().toLowerCase();
|
||
};
|
||
return ScopeSet;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* Function to build a client info object
|
||
* @param rawClientInfo
|
||
* @param crypto
|
||
*/
|
||
function buildClientInfo(rawClientInfo, crypto) {
|
||
if (StringUtils.isEmpty(rawClientInfo)) {
|
||
throw ClientAuthError.createClientInfoEmptyError();
|
||
}
|
||
try {
|
||
var decodedClientInfo = crypto.base64Decode(rawClientInfo);
|
||
return JSON.parse(decodedClientInfo);
|
||
}
|
||
catch (e) {
|
||
throw ClientAuthError.createClientInfoDecodingError(e);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* Authority types supported by MSAL.
|
||
*/
|
||
var AuthorityType;
|
||
(function (AuthorityType) {
|
||
AuthorityType[AuthorityType["Default"] = 0] = "Default";
|
||
AuthorityType[AuthorityType["Adfs"] = 1] = "Adfs";
|
||
})(AuthorityType || (AuthorityType = {}));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* Type that defines required and optional parameters for an Account field (based on universal cache schema implemented by all MSALs).
|
||
*
|
||
* Key : Value Schema
|
||
*
|
||
* Key: <home_account_id>-<environment>-<realm*>
|
||
*
|
||
* Value Schema:
|
||
* {
|
||
* homeAccountId: home account identifier for the auth scheme,
|
||
* environment: entity that issued the token, represented as a full host
|
||
* realm: Full tenant or organizational identifier that the account belongs to
|
||
* localAccountId: Original tenant-specific accountID, usually used for legacy cases
|
||
* username: primary username that represents the user, usually corresponds to preferred_username in the v2 endpt
|
||
* authorityType: Accounts authority type as a string
|
||
* name: Full name for the account, including given name and family name,
|
||
* clientInfo: Full base64 encoded client info received from ESTS
|
||
* lastModificationTime: last time this entity was modified in the cache
|
||
* lastModificationApp:
|
||
* oboAssertion: access token passed in as part of OBO request
|
||
* idTokenClaims: Object containing claims parsed from ID token
|
||
* }
|
||
*/
|
||
var AccountEntity = /** @class */ (function () {
|
||
function AccountEntity() {
|
||
}
|
||
/**
|
||
* Generate Account Id key component as per the schema: <home_account_id>-<environment>
|
||
*/
|
||
AccountEntity.prototype.generateAccountId = function () {
|
||
var accountId = [this.homeAccountId, this.environment];
|
||
return accountId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
|
||
};
|
||
/**
|
||
* Generate Account Cache Key as per the schema: <home_account_id>-<environment>-<realm*>
|
||
*/
|
||
AccountEntity.prototype.generateAccountKey = function () {
|
||
return AccountEntity.generateAccountCacheKey({
|
||
homeAccountId: this.homeAccountId,
|
||
environment: this.environment,
|
||
tenantId: this.realm,
|
||
username: this.username,
|
||
localAccountId: this.localAccountId
|
||
});
|
||
};
|
||
/**
|
||
* returns the type of the cache (in this case account)
|
||
*/
|
||
AccountEntity.prototype.generateType = function () {
|
||
switch (this.authorityType) {
|
||
case CacheAccountType.ADFS_ACCOUNT_TYPE:
|
||
return CacheType.ADFS;
|
||
case CacheAccountType.MSAV1_ACCOUNT_TYPE:
|
||
return CacheType.MSA;
|
||
case CacheAccountType.MSSTS_ACCOUNT_TYPE:
|
||
return CacheType.MSSTS;
|
||
case CacheAccountType.GENERIC_ACCOUNT_TYPE:
|
||
return CacheType.GENERIC;
|
||
default: {
|
||
throw ClientAuthError.createUnexpectedAccountTypeError();
|
||
}
|
||
}
|
||
};
|
||
/**
|
||
* Returns the AccountInfo interface for this account.
|
||
*/
|
||
AccountEntity.prototype.getAccountInfo = function () {
|
||
return {
|
||
homeAccountId: this.homeAccountId,
|
||
environment: this.environment,
|
||
tenantId: this.realm,
|
||
username: this.username,
|
||
localAccountId: this.localAccountId,
|
||
name: this.name,
|
||
idTokenClaims: this.idTokenClaims
|
||
};
|
||
};
|
||
/**
|
||
* Generates account key from interface
|
||
* @param accountInterface
|
||
*/
|
||
AccountEntity.generateAccountCacheKey = function (accountInterface) {
|
||
var accountKey = [
|
||
accountInterface.homeAccountId,
|
||
accountInterface.environment || "",
|
||
accountInterface.tenantId || "",
|
||
];
|
||
return accountKey.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
|
||
};
|
||
/**
|
||
* Build Account cache from IdToken, clientInfo and authority/policy. Associated with AAD.
|
||
* @param clientInfo
|
||
* @param authority
|
||
* @param idToken
|
||
* @param policy
|
||
*/
|
||
AccountEntity.createAccount = function (clientInfo, homeAccountId, authority, idToken, oboAssertion, cloudGraphHostName, msGraphHost) {
|
||
var _a, _b, _c, _d, _e, _f;
|
||
var account = new AccountEntity();
|
||
account.authorityType = CacheAccountType.MSSTS_ACCOUNT_TYPE;
|
||
account.clientInfo = clientInfo;
|
||
account.homeAccountId = homeAccountId;
|
||
var env = authority.getPreferredCache();
|
||
if (StringUtils.isEmpty(env)) {
|
||
throw ClientAuthError.createInvalidCacheEnvironmentError();
|
||
}
|
||
account.environment = env;
|
||
// non AAD scenarios can have empty realm
|
||
account.realm = ((_a = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _a === void 0 ? void 0 : _a.tid) || "";
|
||
account.oboAssertion = oboAssertion;
|
||
if (idToken) {
|
||
account.idTokenClaims = idToken.claims;
|
||
// How do you account for MSA CID here?
|
||
account.localAccountId = ((_b = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _b === void 0 ? void 0 : _b.oid) || ((_c = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _c === void 0 ? void 0 : _c.sub) || "";
|
||
/*
|
||
* In B2C scenarios the emails claim is used instead of preferred_username and it is an array. In most cases it will contain a single email.
|
||
* This field should not be relied upon if a custom policy is configured to return more than 1 email.
|
||
*/
|
||
account.username = ((_d = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _d === void 0 ? void 0 : _d.preferred_username) || (((_e = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _e === void 0 ? void 0 : _e.emails) ? idToken.claims.emails[0] : "");
|
||
account.name = (_f = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _f === void 0 ? void 0 : _f.name;
|
||
}
|
||
account.cloudGraphHostName = cloudGraphHostName;
|
||
account.msGraphHost = msGraphHost;
|
||
return account;
|
||
};
|
||
/**
|
||
* Builds non-AAD/ADFS account.
|
||
* @param authority
|
||
* @param idToken
|
||
*/
|
||
AccountEntity.createGenericAccount = function (authority, homeAccountId, idToken, oboAssertion, cloudGraphHostName, msGraphHost) {
|
||
var _a, _b, _c, _d;
|
||
var account = new AccountEntity();
|
||
account.authorityType = (authority.authorityType === AuthorityType.Adfs) ? CacheAccountType.ADFS_ACCOUNT_TYPE : CacheAccountType.GENERIC_ACCOUNT_TYPE;
|
||
account.homeAccountId = homeAccountId;
|
||
// non AAD scenarios can have empty realm
|
||
account.realm = "";
|
||
account.oboAssertion = oboAssertion;
|
||
var env = authority.getPreferredCache();
|
||
if (StringUtils.isEmpty(env)) {
|
||
throw ClientAuthError.createInvalidCacheEnvironmentError();
|
||
}
|
||
if (idToken) {
|
||
// How do you account for MSA CID here?
|
||
account.localAccountId = ((_a = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _a === void 0 ? void 0 : _a.oid) || ((_b = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _b === void 0 ? void 0 : _b.sub) || "";
|
||
// upn claim for most ADFS scenarios
|
||
account.username = ((_c = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _c === void 0 ? void 0 : _c.upn) || "";
|
||
account.name = ((_d = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _d === void 0 ? void 0 : _d.name) || "";
|
||
account.idTokenClaims = idToken === null || idToken === void 0 ? void 0 : idToken.claims;
|
||
}
|
||
account.environment = env;
|
||
account.cloudGraphHostName = cloudGraphHostName;
|
||
account.msGraphHost = msGraphHost;
|
||
/*
|
||
* add uniqueName to claims
|
||
* account.name = idToken.claims.uniqueName;
|
||
*/
|
||
return account;
|
||
};
|
||
/**
|
||
* Generate HomeAccountId from server response
|
||
* @param serverClientInfo
|
||
* @param authType
|
||
*/
|
||
AccountEntity.generateHomeAccountId = function (serverClientInfo, authType, logger, cryptoObj, idToken) {
|
||
var _a;
|
||
var accountId = ((_a = idToken === null || idToken === void 0 ? void 0 : idToken.claims) === null || _a === void 0 ? void 0 : _a.sub) ? idToken.claims.sub : Constants.EMPTY_STRING;
|
||
// since ADFS does not have tid and does not set client_info
|
||
if (authType === AuthorityType.Adfs) {
|
||
return accountId;
|
||
}
|
||
// for cases where there is clientInfo
|
||
if (serverClientInfo) {
|
||
var clientInfo = buildClientInfo(serverClientInfo, cryptoObj);
|
||
if (!StringUtils.isEmpty(clientInfo.uid) && !StringUtils.isEmpty(clientInfo.utid)) {
|
||
return "" + clientInfo.uid + Separators.CLIENT_INFO_SEPARATOR + clientInfo.utid;
|
||
}
|
||
}
|
||
// default to "sub" claim
|
||
logger.verbose("No client info in response");
|
||
return accountId;
|
||
};
|
||
/**
|
||
* Validates an entity: checks for all expected params
|
||
* @param entity
|
||
*/
|
||
AccountEntity.isAccountEntity = function (entity) {
|
||
if (!entity) {
|
||
return false;
|
||
}
|
||
return (entity.hasOwnProperty("homeAccountId") &&
|
||
entity.hasOwnProperty("environment") &&
|
||
entity.hasOwnProperty("realm") &&
|
||
entity.hasOwnProperty("localAccountId") &&
|
||
entity.hasOwnProperty("username") &&
|
||
entity.hasOwnProperty("authorityType"));
|
||
};
|
||
/**
|
||
* Helper function to determine whether 2 accounts are equal
|
||
* Used to avoid unnecessary state updates
|
||
* @param arrayA
|
||
* @param arrayB
|
||
*/
|
||
AccountEntity.accountInfoIsEqual = function (accountA, accountB) {
|
||
if (!accountA || !accountB) {
|
||
return false;
|
||
}
|
||
return (accountA.homeAccountId === accountB.homeAccountId) &&
|
||
(accountA.localAccountId === accountB.localAccountId) &&
|
||
(accountA.username === accountB.username) &&
|
||
(accountA.tenantId === accountB.tenantId) &&
|
||
(accountA.environment === accountB.environment);
|
||
};
|
||
return AccountEntity;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* JWT Token representation class. Parses token string and generates claims object.
|
||
*/
|
||
var AuthToken = /** @class */ (function () {
|
||
function AuthToken(rawToken, crypto) {
|
||
if (StringUtils.isEmpty(rawToken)) {
|
||
throw ClientAuthError.createTokenNullOrEmptyError(rawToken);
|
||
}
|
||
this.rawToken = rawToken;
|
||
this.claims = AuthToken.extractTokenClaims(rawToken, crypto);
|
||
}
|
||
/**
|
||
* Extract token by decoding the rawToken
|
||
*
|
||
* @param encodedToken
|
||
*/
|
||
AuthToken.extractTokenClaims = function (encodedToken, crypto) {
|
||
var decodedToken = StringUtils.decodeAuthToken(encodedToken);
|
||
// token will be decoded to get the username
|
||
try {
|
||
var base64TokenPayload = decodedToken.JWSPayload;
|
||
// base64Decode() should throw an error if there is an issue
|
||
var base64Decoded = crypto.base64Decode(base64TokenPayload);
|
||
return JSON.parse(base64Decoded);
|
||
}
|
||
catch (err) {
|
||
throw ClientAuthError.createTokenParsingError(err);
|
||
}
|
||
};
|
||
return AuthToken;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* Interface class which implement cache storage functions used by MSAL to perform validity checks, and store tokens.
|
||
*/
|
||
var CacheManager = /** @class */ (function () {
|
||
function CacheManager(clientId, cryptoImpl) {
|
||
this.clientId = clientId;
|
||
this.cryptoImpl = cryptoImpl;
|
||
}
|
||
/**
|
||
* Returns all accounts in cache
|
||
*/
|
||
CacheManager.prototype.getAllAccounts = function () {
|
||
var _this = this;
|
||
var currentAccounts = this.getAccountsFilteredBy();
|
||
var accountValues = Object.keys(currentAccounts).map(function (accountKey) { return currentAccounts[accountKey]; });
|
||
var numAccounts = accountValues.length;
|
||
if (numAccounts < 1) {
|
||
return [];
|
||
}
|
||
else {
|
||
var allAccounts = accountValues.map(function (value) {
|
||
var accountEntity = CacheManager.toObject(new AccountEntity(), value);
|
||
var accountInfo = accountEntity.getAccountInfo();
|
||
var idToken = _this.readIdTokenFromCache(_this.clientId, accountInfo);
|
||
if (idToken && !accountInfo.idTokenClaims) {
|
||
accountInfo.idTokenClaims = new AuthToken(idToken.secret, _this.cryptoImpl).claims;
|
||
}
|
||
return accountInfo;
|
||
});
|
||
return allAccounts;
|
||
}
|
||
};
|
||
/**
|
||
* saves a cache record
|
||
* @param cacheRecord
|
||
*/
|
||
CacheManager.prototype.saveCacheRecord = function (cacheRecord) {
|
||
if (!cacheRecord) {
|
||
throw ClientAuthError.createNullOrUndefinedCacheRecord();
|
||
}
|
||
if (!!cacheRecord.account) {
|
||
this.setAccount(cacheRecord.account);
|
||
}
|
||
if (!!cacheRecord.idToken) {
|
||
this.setIdTokenCredential(cacheRecord.idToken);
|
||
}
|
||
if (!!cacheRecord.accessToken) {
|
||
this.saveAccessToken(cacheRecord.accessToken);
|
||
}
|
||
if (!!cacheRecord.refreshToken) {
|
||
this.setRefreshTokenCredential(cacheRecord.refreshToken);
|
||
}
|
||
if (!!cacheRecord.appMetadata) {
|
||
this.setAppMetadata(cacheRecord.appMetadata);
|
||
}
|
||
};
|
||
/**
|
||
* saves access token credential
|
||
* @param credential
|
||
*/
|
||
CacheManager.prototype.saveAccessToken = function (credential) {
|
||
var _this = this;
|
||
var currentTokenCache = this.getCredentialsFilteredBy({
|
||
clientId: credential.clientId,
|
||
credentialType: CredentialType.ACCESS_TOKEN,
|
||
environment: credential.environment,
|
||
homeAccountId: credential.homeAccountId,
|
||
realm: credential.realm,
|
||
});
|
||
var currentScopes = ScopeSet.fromString(credential.target);
|
||
var currentAccessTokens = Object.keys(currentTokenCache.accessTokens).map(function (key) { return currentTokenCache.accessTokens[key]; });
|
||
if (currentAccessTokens) {
|
||
currentAccessTokens.forEach(function (tokenEntity) {
|
||
var tokenScopeSet = ScopeSet.fromString(tokenEntity.target);
|
||
if (tokenScopeSet.intersectingScopeSets(currentScopes)) {
|
||
_this.removeCredential(tokenEntity);
|
||
}
|
||
});
|
||
}
|
||
this.setAccessTokenCredential(credential);
|
||
};
|
||
/**
|
||
* retrieve accounts matching all provided filters; if no filter is set, get all accounts
|
||
* not checking for casing as keys are all generated in lower case, remember to convert to lower case if object properties are compared
|
||
* @param homeAccountId
|
||
* @param environment
|
||
* @param realm
|
||
*/
|
||
CacheManager.prototype.getAccountsFilteredBy = function (accountFilter) {
|
||
return this.getAccountsFilteredByInternal(accountFilter ? accountFilter.homeAccountId : "", accountFilter ? accountFilter.environment : "", accountFilter ? accountFilter.realm : "");
|
||
};
|
||
/**
|
||
* retrieve accounts matching all provided filters; if no filter is set, get all accounts
|
||
* not checking for casing as keys are all generated in lower case, remember to convert to lower case if object properties are compared
|
||
* @param homeAccountId
|
||
* @param environment
|
||
* @param realm
|
||
*/
|
||
CacheManager.prototype.getAccountsFilteredByInternal = function (homeAccountId, environment, realm) {
|
||
var _this = this;
|
||
var allCacheKeys = this.getKeys();
|
||
var matchingAccounts = {};
|
||
allCacheKeys.forEach(function (cacheKey) {
|
||
var entity = _this.getAccount(cacheKey);
|
||
if (!entity) {
|
||
return;
|
||
}
|
||
if (!!homeAccountId && !_this.matchHomeAccountId(entity, homeAccountId)) {
|
||
return;
|
||
}
|
||
if (!!environment && !_this.matchEnvironment(entity, environment)) {
|
||
return;
|
||
}
|
||
if (!!realm && !_this.matchRealm(entity, realm)) {
|
||
return;
|
||
}
|
||
matchingAccounts[cacheKey] = entity;
|
||
});
|
||
return matchingAccounts;
|
||
};
|
||
/**
|
||
* retrieve credentails matching all provided filters; if no filter is set, get all credentials
|
||
* @param homeAccountId
|
||
* @param environment
|
||
* @param credentialType
|
||
* @param clientId
|
||
* @param realm
|
||
* @param target
|
||
*/
|
||
CacheManager.prototype.getCredentialsFilteredBy = function (filter) {
|
||
return this.getCredentialsFilteredByInternal(filter.homeAccountId, filter.environment, filter.credentialType, filter.clientId, filter.familyId, filter.realm, filter.target, filter.oboAssertion);
|
||
};
|
||
/**
|
||
* Support function to help match credentials
|
||
* @param homeAccountId
|
||
* @param environment
|
||
* @param credentialType
|
||
* @param clientId
|
||
* @param realm
|
||
* @param target
|
||
*/
|
||
CacheManager.prototype.getCredentialsFilteredByInternal = function (homeAccountId, environment, credentialType, clientId, familyId, realm, target, oboAssertion) {
|
||
var _this = this;
|
||
var allCacheKeys = this.getKeys();
|
||
var matchingCredentials = {
|
||
idTokens: {},
|
||
accessTokens: {},
|
||
refreshTokens: {},
|
||
};
|
||
allCacheKeys.forEach(function (cacheKey) {
|
||
// don't parse any non-credential type cache entities
|
||
var credType = CredentialEntity.getCredentialType(cacheKey);
|
||
if (credType === Constants.NOT_DEFINED) {
|
||
return;
|
||
}
|
||
// Attempt retrieval
|
||
var entity = _this.getSpecificCredential(cacheKey, credType);
|
||
if (!entity) {
|
||
return;
|
||
}
|
||
if (!!oboAssertion && !_this.matchOboAssertion(entity, oboAssertion)) {
|
||
return;
|
||
}
|
||
if (!!homeAccountId && !_this.matchHomeAccountId(entity, homeAccountId)) {
|
||
return;
|
||
}
|
||
if (!!environment && !_this.matchEnvironment(entity, environment)) {
|
||
return;
|
||
}
|
||
if (!!realm && !_this.matchRealm(entity, realm)) {
|
||
return;
|
||
}
|
||
if (!!credentialType && !_this.matchCredentialType(entity, credentialType)) {
|
||
return;
|
||
}
|
||
if (!!clientId && !_this.matchClientId(entity, clientId)) {
|
||
return;
|
||
}
|
||
if (!!familyId && !_this.matchFamilyId(entity, familyId)) {
|
||
return;
|
||
}
|
||
/*
|
||
* idTokens do not have "target", target specific refreshTokens do exist for some types of authentication
|
||
* Resource specific refresh tokens case will be added when the support is deemed necessary
|
||
*/
|
||
if (!!target && !_this.matchTarget(entity, target)) {
|
||
return;
|
||
}
|
||
switch (credType) {
|
||
case CredentialType.ID_TOKEN:
|
||
matchingCredentials.idTokens[cacheKey] = entity;
|
||
break;
|
||
case CredentialType.ACCESS_TOKEN:
|
||
matchingCredentials.accessTokens[cacheKey] = entity;
|
||
break;
|
||
case CredentialType.REFRESH_TOKEN:
|
||
matchingCredentials.refreshTokens[cacheKey] = entity;
|
||
break;
|
||
}
|
||
});
|
||
return matchingCredentials;
|
||
};
|
||
/**
|
||
* retrieve appMetadata matching all provided filters; if no filter is set, get all appMetadata
|
||
* @param filter
|
||
*/
|
||
CacheManager.prototype.getAppMetadataFilteredBy = function (filter) {
|
||
return this.getAppMetadataFilteredByInternal(filter.environment, filter.clientId);
|
||
};
|
||
/**
|
||
* Support function to help match appMetadata
|
||
* @param environment
|
||
* @param clientId
|
||
*/
|
||
CacheManager.prototype.getAppMetadataFilteredByInternal = function (environment, clientId) {
|
||
var _this = this;
|
||
var allCacheKeys = this.getKeys();
|
||
var matchingAppMetadata = {};
|
||
allCacheKeys.forEach(function (cacheKey) {
|
||
// don't parse any non-appMetadata type cache entities
|
||
if (!_this.isAppMetadata(cacheKey)) {
|
||
return;
|
||
}
|
||
// Attempt retrieval
|
||
var entity = _this.getAppMetadata(cacheKey);
|
||
if (!entity) {
|
||
return;
|
||
}
|
||
if (!!environment && !_this.matchEnvironment(entity, environment)) {
|
||
return;
|
||
}
|
||
if (!!clientId && !_this.matchClientId(entity, clientId)) {
|
||
return;
|
||
}
|
||
matchingAppMetadata[cacheKey] = entity;
|
||
});
|
||
return matchingAppMetadata;
|
||
};
|
||
/**
|
||
* retrieve authorityMetadata that contains a matching alias
|
||
* @param filter
|
||
*/
|
||
CacheManager.prototype.getAuthorityMetadataByAlias = function (host) {
|
||
var _this = this;
|
||
var allCacheKeys = this.getAuthorityMetadataKeys();
|
||
var matchedEntity = null;
|
||
allCacheKeys.forEach(function (cacheKey) {
|
||
// don't parse any non-authorityMetadata type cache entities
|
||
if (!_this.isAuthorityMetadata(cacheKey) || cacheKey.indexOf(_this.clientId) === -1) {
|
||
return;
|
||
}
|
||
// Attempt retrieval
|
||
var entity = _this.getAuthorityMetadata(cacheKey);
|
||
if (!entity) {
|
||
return;
|
||
}
|
||
if (entity.aliases.indexOf(host) === -1) {
|
||
return;
|
||
}
|
||
matchedEntity = entity;
|
||
});
|
||
return matchedEntity;
|
||
};
|
||
/**
|
||
* Removes all accounts and related tokens from cache.
|
||
*/
|
||
CacheManager.prototype.removeAllAccounts = function () {
|
||
var _this = this;
|
||
var allCacheKeys = this.getKeys();
|
||
allCacheKeys.forEach(function (cacheKey) {
|
||
var entity = _this.getAccount(cacheKey);
|
||
if (!entity) {
|
||
return;
|
||
}
|
||
_this.removeAccount(cacheKey);
|
||
});
|
||
return true;
|
||
};
|
||
/**
|
||
* returns a boolean if the given account is removed
|
||
* @param account
|
||
*/
|
||
CacheManager.prototype.removeAccount = function (accountKey) {
|
||
var account = this.getAccount(accountKey);
|
||
if (!account) {
|
||
throw ClientAuthError.createNoAccountFoundError();
|
||
}
|
||
return (this.removeAccountContext(account) && this.removeItem(accountKey, CacheSchemaType.ACCOUNT));
|
||
};
|
||
/**
|
||
* returns a boolean if the given account is removed
|
||
* @param account
|
||
*/
|
||
CacheManager.prototype.removeAccountContext = function (account) {
|
||
var _this = this;
|
||
var allCacheKeys = this.getKeys();
|
||
var accountId = account.generateAccountId();
|
||
allCacheKeys.forEach(function (cacheKey) {
|
||
// don't parse any non-credential type cache entities
|
||
var credType = CredentialEntity.getCredentialType(cacheKey);
|
||
if (credType === Constants.NOT_DEFINED) {
|
||
return;
|
||
}
|
||
var cacheEntity = _this.getSpecificCredential(cacheKey, credType);
|
||
if (!!cacheEntity && accountId === cacheEntity.generateAccountId()) {
|
||
_this.removeCredential(cacheEntity);
|
||
}
|
||
});
|
||
return true;
|
||
};
|
||
/**
|
||
* returns a boolean if the given credential is removed
|
||
* @param credential
|
||
*/
|
||
CacheManager.prototype.removeCredential = function (credential) {
|
||
var key = credential.generateCredentialKey();
|
||
return this.removeItem(key, CacheSchemaType.CREDENTIAL);
|
||
};
|
||
/**
|
||
* Removes all app metadata objects from cache.
|
||
*/
|
||
CacheManager.prototype.removeAppMetadata = function () {
|
||
var _this = this;
|
||
var allCacheKeys = this.getKeys();
|
||
allCacheKeys.forEach(function (cacheKey) {
|
||
if (_this.isAppMetadata(cacheKey)) {
|
||
_this.removeItem(cacheKey, CacheSchemaType.APP_METADATA);
|
||
}
|
||
});
|
||
return true;
|
||
};
|
||
/**
|
||
* Retrieve the cached credentials into a cacherecord
|
||
* @param account
|
||
* @param clientId
|
||
* @param scopes
|
||
* @param environment
|
||
*/
|
||
CacheManager.prototype.readCacheRecord = function (account, clientId, scopes, environment) {
|
||
var cachedAccount = this.readAccountFromCache(account);
|
||
var cachedIdToken = this.readIdTokenFromCache(clientId, account);
|
||
var cachedAccessToken = this.readAccessTokenFromCache(clientId, account, scopes);
|
||
var cachedRefreshToken = this.readRefreshTokenFromCache(clientId, account, false);
|
||
var cachedAppMetadata = this.readAppMetadataFromCache(environment, clientId);
|
||
if (cachedAccount && cachedIdToken) {
|
||
cachedAccount.idTokenClaims = new AuthToken(cachedIdToken.secret, this.cryptoImpl).claims;
|
||
}
|
||
return {
|
||
account: cachedAccount,
|
||
idToken: cachedIdToken,
|
||
accessToken: cachedAccessToken,
|
||
refreshToken: cachedRefreshToken,
|
||
appMetadata: cachedAppMetadata,
|
||
};
|
||
};
|
||
/**
|
||
* Retrieve AccountEntity from cache
|
||
* @param account
|
||
*/
|
||
CacheManager.prototype.readAccountFromCache = function (account) {
|
||
var accountKey = AccountEntity.generateAccountCacheKey(account);
|
||
return this.getAccount(accountKey);
|
||
};
|
||
/**
|
||
* Retrieve IdTokenEntity from cache
|
||
* @param clientId
|
||
* @param account
|
||
* @param inputRealm
|
||
*/
|
||
CacheManager.prototype.readIdTokenFromCache = function (clientId, account) {
|
||
var idTokenFilter = {
|
||
homeAccountId: account.homeAccountId,
|
||
environment: account.environment,
|
||
credentialType: CredentialType.ID_TOKEN,
|
||
clientId: clientId,
|
||
realm: account.tenantId,
|
||
};
|
||
var credentialCache = this.getCredentialsFilteredBy(idTokenFilter);
|
||
var idTokens = Object.keys(credentialCache.idTokens).map(function (key) { return credentialCache.idTokens[key]; });
|
||
var numIdTokens = idTokens.length;
|
||
if (numIdTokens < 1) {
|
||
return null;
|
||
}
|
||
else if (numIdTokens > 1) {
|
||
throw ClientAuthError.createMultipleMatchingTokensInCacheError();
|
||
}
|
||
return idTokens[0];
|
||
};
|
||
/**
|
||
* Retrieve AccessTokenEntity from cache
|
||
* @param clientId
|
||
* @param account
|
||
* @param scopes
|
||
* @param inputRealm
|
||
*/
|
||
CacheManager.prototype.readAccessTokenFromCache = function (clientId, account, scopes) {
|
||
var accessTokenFilter = {
|
||
homeAccountId: account.homeAccountId,
|
||
environment: account.environment,
|
||
credentialType: CredentialType.ACCESS_TOKEN,
|
||
clientId: clientId,
|
||
realm: account.tenantId,
|
||
target: scopes.printScopesLowerCase(),
|
||
};
|
||
var credentialCache = this.getCredentialsFilteredBy(accessTokenFilter);
|
||
var accessTokens = Object.keys(credentialCache.accessTokens).map(function (key) { return credentialCache.accessTokens[key]; });
|
||
var numAccessTokens = accessTokens.length;
|
||
if (numAccessTokens < 1) {
|
||
return null;
|
||
}
|
||
else if (numAccessTokens > 1) {
|
||
throw ClientAuthError.createMultipleMatchingTokensInCacheError();
|
||
}
|
||
return accessTokens[0];
|
||
};
|
||
/**
|
||
* Helper to retrieve the appropriate refresh token from cache
|
||
* @param clientId
|
||
* @param account
|
||
* @param familyRT
|
||
*/
|
||
CacheManager.prototype.readRefreshTokenFromCache = function (clientId, account, familyRT) {
|
||
var id = familyRT ? THE_FAMILY_ID : undefined;
|
||
var refreshTokenFilter = {
|
||
homeAccountId: account.homeAccountId,
|
||
environment: account.environment,
|
||
credentialType: CredentialType.REFRESH_TOKEN,
|
||
clientId: clientId,
|
||
familyId: id
|
||
};
|
||
var credentialCache = this.getCredentialsFilteredBy(refreshTokenFilter);
|
||
var refreshTokens = Object.keys(credentialCache.refreshTokens).map(function (key) { return credentialCache.refreshTokens[key]; });
|
||
var numRefreshTokens = refreshTokens.length;
|
||
if (numRefreshTokens < 1) {
|
||
return null;
|
||
}
|
||
// address the else case after remove functions address environment aliases
|
||
return refreshTokens[0];
|
||
};
|
||
/**
|
||
* Retrieve AppMetadataEntity from cache
|
||
*/
|
||
CacheManager.prototype.readAppMetadataFromCache = function (environment, clientId) {
|
||
var appMetadataFilter = {
|
||
environment: environment,
|
||
clientId: clientId,
|
||
};
|
||
var appMetadata = this.getAppMetadataFilteredBy(appMetadataFilter);
|
||
var appMetadataEntries = Object.keys(appMetadata).map(function (key) { return appMetadata[key]; });
|
||
var numAppMetadata = appMetadataEntries.length;
|
||
if (numAppMetadata < 1) {
|
||
return null;
|
||
}
|
||
else if (numAppMetadata > 1) {
|
||
throw ClientAuthError.createMultipleMatchingAppMetadataInCacheError();
|
||
}
|
||
return appMetadataEntries[0];
|
||
};
|
||
/**
|
||
* Return the family_id value associated with FOCI
|
||
* @param environment
|
||
* @param clientId
|
||
*/
|
||
CacheManager.prototype.isAppMetadataFOCI = function (environment, clientId) {
|
||
var appMetadata = this.readAppMetadataFromCache(environment, clientId);
|
||
return !!(appMetadata && appMetadata.familyId === THE_FAMILY_ID);
|
||
};
|
||
/**
|
||
* helper to match account ids
|
||
* @param value
|
||
* @param homeAccountId
|
||
*/
|
||
CacheManager.prototype.matchHomeAccountId = function (entity, homeAccountId) {
|
||
return !!(entity.homeAccountId && homeAccountId === entity.homeAccountId);
|
||
};
|
||
/**
|
||
* helper to match assertion
|
||
* @param value
|
||
* @param oboAssertion
|
||
*/
|
||
CacheManager.prototype.matchOboAssertion = function (entity, oboAssertion) {
|
||
return !!(entity.oboAssertion && oboAssertion === entity.oboAssertion);
|
||
};
|
||
/**
|
||
* helper to match environment
|
||
* @param value
|
||
* @param environment
|
||
*/
|
||
CacheManager.prototype.matchEnvironment = function (entity, environment) {
|
||
var cloudMetadata = this.getAuthorityMetadataByAlias(environment);
|
||
if (cloudMetadata && cloudMetadata.aliases.indexOf(entity.environment) > -1) {
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
/**
|
||
* helper to match credential type
|
||
* @param entity
|
||
* @param credentialType
|
||
*/
|
||
CacheManager.prototype.matchCredentialType = function (entity, credentialType) {
|
||
return (entity.credentialType && credentialType.toLowerCase() === entity.credentialType.toLowerCase());
|
||
};
|
||
/**
|
||
* helper to match client ids
|
||
* @param entity
|
||
* @param clientId
|
||
*/
|
||
CacheManager.prototype.matchClientId = function (entity, clientId) {
|
||
return !!(entity.clientId && clientId === entity.clientId);
|
||
};
|
||
/**
|
||
* helper to match family ids
|
||
* @param entity
|
||
* @param familyId
|
||
*/
|
||
CacheManager.prototype.matchFamilyId = function (entity, familyId) {
|
||
return !!(entity.familyId && familyId === entity.familyId);
|
||
};
|
||
/**
|
||
* helper to match realm
|
||
* @param entity
|
||
* @param realm
|
||
*/
|
||
CacheManager.prototype.matchRealm = function (entity, realm) {
|
||
return !!(entity.realm && realm === entity.realm);
|
||
};
|
||
/**
|
||
* Returns true if the target scopes are a subset of the current entity's scopes, false otherwise.
|
||
* @param entity
|
||
* @param target
|
||
*/
|
||
CacheManager.prototype.matchTarget = function (entity, target) {
|
||
if (entity.credentialType !== CredentialType.ACCESS_TOKEN || !entity.target) {
|
||
return false;
|
||
}
|
||
var entityScopeSet = ScopeSet.fromString(entity.target);
|
||
var requestTargetScopeSet = ScopeSet.fromString(target);
|
||
if (!requestTargetScopeSet.containsOnlyOIDCScopes()) {
|
||
requestTargetScopeSet.removeOIDCScopes(); // ignore OIDC scopes
|
||
}
|
||
return entityScopeSet.containsScopeSet(requestTargetScopeSet);
|
||
};
|
||
/**
|
||
* returns if a given cache entity is of the type appmetadata
|
||
* @param key
|
||
*/
|
||
CacheManager.prototype.isAppMetadata = function (key) {
|
||
return key.indexOf(APP_METADATA) !== -1;
|
||
};
|
||
/**
|
||
* returns if a given cache entity is of the type authoritymetadata
|
||
* @param key
|
||
*/
|
||
CacheManager.prototype.isAuthorityMetadata = function (key) {
|
||
return key.indexOf(AUTHORITY_METADATA_CONSTANTS.CACHE_KEY) !== -1;
|
||
};
|
||
/**
|
||
* returns cache key used for cloud instance metadata
|
||
*/
|
||
CacheManager.prototype.generateAuthorityMetadataCacheKey = function (authority) {
|
||
return AUTHORITY_METADATA_CONSTANTS.CACHE_KEY + "-" + this.clientId + "-" + authority;
|
||
};
|
||
/**
|
||
* Returns the specific credential (IdToken/AccessToken/RefreshToken) from the cache
|
||
* @param key
|
||
* @param credType
|
||
*/
|
||
CacheManager.prototype.getSpecificCredential = function (key, credType) {
|
||
switch (credType) {
|
||
case CredentialType.ID_TOKEN: {
|
||
return this.getIdTokenCredential(key);
|
||
}
|
||
case CredentialType.ACCESS_TOKEN: {
|
||
return this.getAccessTokenCredential(key);
|
||
}
|
||
case CredentialType.REFRESH_TOKEN: {
|
||
return this.getRefreshTokenCredential(key);
|
||
}
|
||
default:
|
||
return null;
|
||
}
|
||
};
|
||
/**
|
||
* Helper to convert serialized data to object
|
||
* @param obj
|
||
* @param json
|
||
*/
|
||
CacheManager.toObject = function (obj, json) {
|
||
for (var propertyName in json) {
|
||
obj[propertyName] = json[propertyName];
|
||
}
|
||
return obj;
|
||
};
|
||
return CacheManager;
|
||
}());
|
||
var DefaultStorageClass = /** @class */ (function (_super) {
|
||
__extends(DefaultStorageClass, _super);
|
||
function DefaultStorageClass() {
|
||
return _super !== null && _super.apply(this, arguments) || this;
|
||
}
|
||
DefaultStorageClass.prototype.setAccount = function () {
|
||
var notImplErr = "Storage interface - setAccount() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.getAccount = function () {
|
||
var notImplErr = "Storage interface - getAccount() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.setIdTokenCredential = function () {
|
||
var notImplErr = "Storage interface - setIdTokenCredential() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.getIdTokenCredential = function () {
|
||
var notImplErr = "Storage interface - getIdTokenCredential() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.setAccessTokenCredential = function () {
|
||
var notImplErr = "Storage interface - setAccessTokenCredential() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.getAccessTokenCredential = function () {
|
||
var notImplErr = "Storage interface - getAccessTokenCredential() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.setRefreshTokenCredential = function () {
|
||
var notImplErr = "Storage interface - setRefreshTokenCredential() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.getRefreshTokenCredential = function () {
|
||
var notImplErr = "Storage interface - getRefreshTokenCredential() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.setAppMetadata = function () {
|
||
var notImplErr = "Storage interface - setAppMetadata() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.getAppMetadata = function () {
|
||
var notImplErr = "Storage interface - getAppMetadata() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.setServerTelemetry = function () {
|
||
var notImplErr = "Storage interface - setServerTelemetry() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.getServerTelemetry = function () {
|
||
var notImplErr = "Storage interface - getServerTelemetry() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.setAuthorityMetadata = function () {
|
||
var notImplErr = "Storage interface - setAuthorityMetadata() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.getAuthorityMetadata = function () {
|
||
var notImplErr = "Storage interface - getAuthorityMetadata() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.getAuthorityMetadataKeys = function () {
|
||
var notImplErr = "Storage interface - getAuthorityMetadataKeys() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.setThrottlingCache = function () {
|
||
var notImplErr = "Storage interface - setThrottlingCache() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.getThrottlingCache = function () {
|
||
var notImplErr = "Storage interface - getThrottlingCache() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.removeItem = function () {
|
||
var notImplErr = "Storage interface - removeItem() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.containsKey = function () {
|
||
var notImplErr = "Storage interface - containsKey() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.getKeys = function () {
|
||
var notImplErr = "Storage interface - getKeys() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
DefaultStorageClass.prototype.clear = function () {
|
||
var notImplErr = "Storage interface - clear() has not been implemented for the cacheStorage interface.";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
};
|
||
return DefaultStorageClass;
|
||
}(CacheManager));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
// Token renewal offset default in seconds
|
||
var DEFAULT_TOKEN_RENEWAL_OFFSET_SEC = 300;
|
||
var DEFAULT_SYSTEM_OPTIONS = {
|
||
tokenRenewalOffsetSeconds: DEFAULT_TOKEN_RENEWAL_OFFSET_SEC
|
||
};
|
||
var DEFAULT_LOGGER_IMPLEMENTATION = {
|
||
loggerCallback: function () {
|
||
// allow users to not set loggerCallback
|
||
},
|
||
piiLoggingEnabled: false,
|
||
logLevel: LogLevel.Info
|
||
};
|
||
var DEFAULT_NETWORK_IMPLEMENTATION = {
|
||
sendGetRequestAsync: function () {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var notImplErr;
|
||
return __generator(this, function (_a) {
|
||
notImplErr = "Network interface - sendGetRequestAsync() has not been implemented";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
});
|
||
});
|
||
},
|
||
sendPostRequestAsync: function () {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var notImplErr;
|
||
return __generator(this, function (_a) {
|
||
notImplErr = "Network interface - sendPostRequestAsync() has not been implemented";
|
||
throw AuthError.createUnexpectedError(notImplErr);
|
||
});
|
||
});
|
||
}
|
||
};
|
||
var DEFAULT_LIBRARY_INFO = {
|
||
sku: Constants.SKU,
|
||
version: version,
|
||
cpu: "",
|
||
os: ""
|
||
};
|
||
var DEFAULT_CLIENT_CREDENTIALS = {
|
||
clientSecret: "",
|
||
clientAssertion: undefined
|
||
};
|
||
/**
|
||
* Function that sets the default options when not explicitly configured from app developer
|
||
*
|
||
* @param Configuration
|
||
*
|
||
* @returns Configuration
|
||
*/
|
||
function buildClientConfiguration(_a) {
|
||
var userAuthOptions = _a.authOptions, userSystemOptions = _a.systemOptions, userLoggerOption = _a.loggerOptions, storageImplementation = _a.storageInterface, networkImplementation = _a.networkInterface, cryptoImplementation = _a.cryptoInterface, clientCredentials = _a.clientCredentials, libraryInfo = _a.libraryInfo, serverTelemetryManager = _a.serverTelemetryManager, persistencePlugin = _a.persistencePlugin, serializableCache = _a.serializableCache;
|
||
return {
|
||
authOptions: buildAuthOptions(userAuthOptions),
|
||
systemOptions: __assign(__assign({}, DEFAULT_SYSTEM_OPTIONS), userSystemOptions),
|
||
loggerOptions: __assign(__assign({}, DEFAULT_LOGGER_IMPLEMENTATION), userLoggerOption),
|
||
storageInterface: storageImplementation || new DefaultStorageClass(userAuthOptions.clientId, DEFAULT_CRYPTO_IMPLEMENTATION),
|
||
networkInterface: networkImplementation || DEFAULT_NETWORK_IMPLEMENTATION,
|
||
cryptoInterface: cryptoImplementation || DEFAULT_CRYPTO_IMPLEMENTATION,
|
||
clientCredentials: clientCredentials || DEFAULT_CLIENT_CREDENTIALS,
|
||
libraryInfo: __assign(__assign({}, DEFAULT_LIBRARY_INFO), libraryInfo),
|
||
serverTelemetryManager: serverTelemetryManager || null,
|
||
persistencePlugin: persistencePlugin || null,
|
||
serializableCache: serializableCache || null
|
||
};
|
||
}
|
||
/**
|
||
* Construct authoptions from the client and platform passed values
|
||
* @param authOptions
|
||
*/
|
||
function buildAuthOptions(authOptions) {
|
||
return __assign({ clientCapabilities: [] }, authOptions);
|
||
}
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* Error thrown when there is an error with the server code, for example, unavailability.
|
||
*/
|
||
var ServerError = /** @class */ (function (_super) {
|
||
__extends(ServerError, _super);
|
||
function ServerError(errorCode, errorMessage, subError) {
|
||
var _this = _super.call(this, errorCode, errorMessage, subError) || this;
|
||
_this.name = "ServerError";
|
||
Object.setPrototypeOf(_this, ServerError.prototype);
|
||
return _this;
|
||
}
|
||
return ServerError;
|
||
}(AuthError));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
var ThrottlingUtils = /** @class */ (function () {
|
||
function ThrottlingUtils() {
|
||
}
|
||
/**
|
||
* Prepares a RequestThumbprint to be stored as a key.
|
||
* @param thumbprint
|
||
*/
|
||
ThrottlingUtils.generateThrottlingStorageKey = function (thumbprint) {
|
||
return ThrottlingConstants.THROTTLING_PREFIX + "." + JSON.stringify(thumbprint);
|
||
};
|
||
/**
|
||
* Performs necessary throttling checks before a network request.
|
||
* @param cacheManager
|
||
* @param thumbprint
|
||
*/
|
||
ThrottlingUtils.preProcess = function (cacheManager, thumbprint) {
|
||
var _a;
|
||
var key = ThrottlingUtils.generateThrottlingStorageKey(thumbprint);
|
||
var value = cacheManager.getThrottlingCache(key);
|
||
if (value) {
|
||
if (value.throttleTime < Date.now()) {
|
||
cacheManager.removeItem(key, CacheSchemaType.THROTTLING);
|
||
return;
|
||
}
|
||
throw new ServerError(((_a = value.errorCodes) === null || _a === void 0 ? void 0 : _a.join(" ")) || Constants.EMPTY_STRING, value.errorMessage, value.subError);
|
||
}
|
||
};
|
||
/**
|
||
* Performs necessary throttling checks after a network request.
|
||
* @param cacheManager
|
||
* @param thumbprint
|
||
* @param response
|
||
*/
|
||
ThrottlingUtils.postProcess = function (cacheManager, thumbprint, response) {
|
||
if (ThrottlingUtils.checkResponseStatus(response) || ThrottlingUtils.checkResponseForRetryAfter(response)) {
|
||
var thumbprintValue = {
|
||
throttleTime: ThrottlingUtils.calculateThrottleTime(parseInt(response.headers[HeaderNames.RETRY_AFTER])),
|
||
error: response.body.error,
|
||
errorCodes: response.body.error_codes,
|
||
errorMessage: response.body.error_description,
|
||
subError: response.body.suberror
|
||
};
|
||
cacheManager.setThrottlingCache(ThrottlingUtils.generateThrottlingStorageKey(thumbprint), thumbprintValue);
|
||
}
|
||
};
|
||
/**
|
||
* Checks a NetworkResponse object's status codes against 429 or 5xx
|
||
* @param response
|
||
*/
|
||
ThrottlingUtils.checkResponseStatus = function (response) {
|
||
return response.status === 429 || response.status >= 500 && response.status < 600;
|
||
};
|
||
/**
|
||
* Checks a NetworkResponse object's RetryAfter header
|
||
* @param response
|
||
*/
|
||
ThrottlingUtils.checkResponseForRetryAfter = function (response) {
|
||
if (response.headers) {
|
||
return response.headers.hasOwnProperty(HeaderNames.RETRY_AFTER) && (response.status < 200 || response.status >= 300);
|
||
}
|
||
return false;
|
||
};
|
||
/**
|
||
* Calculates the Unix-time value for a throttle to expire given throttleTime in seconds.
|
||
* @param throttleTime
|
||
*/
|
||
ThrottlingUtils.calculateThrottleTime = function (throttleTime) {
|
||
if (throttleTime <= 0) {
|
||
throttleTime = 0;
|
||
}
|
||
var currentSeconds = Date.now() / 1000;
|
||
return Math.floor(Math.min(currentSeconds + (throttleTime || ThrottlingConstants.DEFAULT_THROTTLE_TIME_SECONDS), currentSeconds + ThrottlingConstants.DEFAULT_MAX_THROTTLE_TIME_SECONDS) * 1000);
|
||
};
|
||
ThrottlingUtils.removeThrottle = function (cacheManager, clientId, authority, scopes, homeAccountIdentifier) {
|
||
var thumbprint = {
|
||
clientId: clientId,
|
||
authority: authority,
|
||
scopes: scopes,
|
||
homeAccountIdentifier: homeAccountIdentifier
|
||
};
|
||
var key = this.generateThrottlingStorageKey(thumbprint);
|
||
return cacheManager.removeItem(key, CacheSchemaType.THROTTLING);
|
||
};
|
||
return ThrottlingUtils;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
var NetworkManager = /** @class */ (function () {
|
||
function NetworkManager(networkClient, cacheManager) {
|
||
this.networkClient = networkClient;
|
||
this.cacheManager = cacheManager;
|
||
}
|
||
/**
|
||
* Wraps sendPostRequestAsync with necessary preflight and postflight logic
|
||
* @param thumbprint
|
||
* @param tokenEndpoint
|
||
* @param options
|
||
*/
|
||
NetworkManager.prototype.sendPostRequest = function (thumbprint, tokenEndpoint, options) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var response;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
ThrottlingUtils.preProcess(this.cacheManager, thumbprint);
|
||
return [4 /*yield*/, this.networkClient.sendPostRequestAsync(tokenEndpoint, options)];
|
||
case 1:
|
||
response = _a.sent();
|
||
ThrottlingUtils.postProcess(this.cacheManager, thumbprint, response);
|
||
// Placeholder for Telemetry hook
|
||
return [2 /*return*/, response];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
return NetworkManager;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* Base application class which will construct requests to send to and handle responses from the Microsoft STS using the authorization code flow.
|
||
*/
|
||
var BaseClient = /** @class */ (function () {
|
||
function BaseClient(configuration) {
|
||
// Set the configuration
|
||
this.config = buildClientConfiguration(configuration);
|
||
// Initialize the logger
|
||
this.logger = new Logger(this.config.loggerOptions, name, version);
|
||
// Initialize crypto
|
||
this.cryptoUtils = this.config.cryptoInterface;
|
||
// Initialize storage interface
|
||
this.cacheManager = this.config.storageInterface;
|
||
// Set the network interface
|
||
this.networkClient = this.config.networkInterface;
|
||
// Set the NetworkManager
|
||
this.networkManager = new NetworkManager(this.networkClient, this.cacheManager);
|
||
// Set TelemetryManager
|
||
this.serverTelemetryManager = this.config.serverTelemetryManager;
|
||
// set Authority
|
||
this.authority = this.config.authOptions.authority;
|
||
}
|
||
/**
|
||
* Creates default headers for requests to token endpoint
|
||
*/
|
||
BaseClient.prototype.createDefaultTokenRequestHeaders = function () {
|
||
var headers = this.createDefaultLibraryHeaders();
|
||
headers[HeaderNames.CONTENT_TYPE] = Constants.URL_FORM_CONTENT_TYPE;
|
||
headers[HeaderNames.X_MS_LIB_CAPABILITY] = HeaderNames.X_MS_LIB_CAPABILITY_VALUE;
|
||
if (this.serverTelemetryManager) {
|
||
headers[HeaderNames.X_CLIENT_CURR_TELEM] = this.serverTelemetryManager.generateCurrentRequestHeaderValue();
|
||
headers[HeaderNames.X_CLIENT_LAST_TELEM] = this.serverTelemetryManager.generateLastRequestHeaderValue();
|
||
}
|
||
return headers;
|
||
};
|
||
/**
|
||
* addLibraryData
|
||
*/
|
||
BaseClient.prototype.createDefaultLibraryHeaders = function () {
|
||
var headers = {};
|
||
// client info headers
|
||
headers[AADServerParamKeys.X_CLIENT_SKU] = this.config.libraryInfo.sku;
|
||
headers[AADServerParamKeys.X_CLIENT_VER] = this.config.libraryInfo.version;
|
||
headers[AADServerParamKeys.X_CLIENT_OS] = this.config.libraryInfo.os;
|
||
headers[AADServerParamKeys.X_CLIENT_CPU] = this.config.libraryInfo.cpu;
|
||
return headers;
|
||
};
|
||
/**
|
||
* Http post to token endpoint
|
||
* @param tokenEndpoint
|
||
* @param queryString
|
||
* @param headers
|
||
* @param thumbprint
|
||
*/
|
||
BaseClient.prototype.executePostToTokenEndpoint = function (tokenEndpoint, queryString, headers, thumbprint) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var response;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0: return [4 /*yield*/, this.networkManager.sendPostRequest(thumbprint, tokenEndpoint, { body: queryString, headers: headers })];
|
||
case 1:
|
||
response = _a.sent();
|
||
if (this.config.serverTelemetryManager && response.status < 500 && response.status !== 429) {
|
||
// Telemetry data successfully logged by server, clear Telemetry cache
|
||
this.config.serverTelemetryManager.clearTelemetryCache();
|
||
}
|
||
return [2 /*return*/, response];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Updates the authority object of the client. Endpoint discovery must be completed.
|
||
* @param updatedAuthority
|
||
*/
|
||
BaseClient.prototype.updateAuthority = function (updatedAuthority) {
|
||
if (!updatedAuthority.discoveryComplete()) {
|
||
throw ClientAuthError.createEndpointDiscoveryIncompleteError("Updated authority has not completed endpoint discovery.");
|
||
}
|
||
this.authority = updatedAuthority;
|
||
};
|
||
return BaseClient;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* Validates server consumable params from the "request" objects
|
||
*/
|
||
var RequestValidator = /** @class */ (function () {
|
||
function RequestValidator() {
|
||
}
|
||
/**
|
||
* Utility to check if the `redirectUri` in the request is a non-null value
|
||
* @param redirectUri
|
||
*/
|
||
RequestValidator.validateRedirectUri = function (redirectUri) {
|
||
if (StringUtils.isEmpty(redirectUri)) {
|
||
throw ClientConfigurationError.createRedirectUriEmptyError();
|
||
}
|
||
};
|
||
/**
|
||
* Utility to validate prompt sent by the user in the request
|
||
* @param prompt
|
||
*/
|
||
RequestValidator.validatePrompt = function (prompt) {
|
||
if ([
|
||
PromptValue.LOGIN,
|
||
PromptValue.SELECT_ACCOUNT,
|
||
PromptValue.CONSENT,
|
||
PromptValue.NONE
|
||
].indexOf(prompt) < 0) {
|
||
throw ClientConfigurationError.createInvalidPromptError(prompt);
|
||
}
|
||
};
|
||
RequestValidator.validateClaims = function (claims) {
|
||
try {
|
||
JSON.parse(claims);
|
||
}
|
||
catch (e) {
|
||
throw ClientConfigurationError.createInvalidClaimsRequestError();
|
||
}
|
||
};
|
||
/**
|
||
* Utility to validate code_challenge and code_challenge_method
|
||
* @param codeChallenge
|
||
* @param codeChallengeMethod
|
||
*/
|
||
RequestValidator.validateCodeChallengeParams = function (codeChallenge, codeChallengeMethod) {
|
||
if (StringUtils.isEmpty(codeChallenge) || StringUtils.isEmpty(codeChallengeMethod)) {
|
||
throw ClientConfigurationError.createInvalidCodeChallengeParamsError();
|
||
}
|
||
else {
|
||
this.validateCodeChallengeMethod(codeChallengeMethod);
|
||
}
|
||
};
|
||
/**
|
||
* Utility to validate code_challenge_method
|
||
* @param codeChallengeMethod
|
||
*/
|
||
RequestValidator.validateCodeChallengeMethod = function (codeChallengeMethod) {
|
||
if ([
|
||
CodeChallengeMethodValues.PLAIN,
|
||
CodeChallengeMethodValues.S256
|
||
].indexOf(codeChallengeMethod) < 0) {
|
||
throw ClientConfigurationError.createInvalidCodeChallengeMethodError();
|
||
}
|
||
};
|
||
/**
|
||
* Removes unnecessary or duplicate query parameters from extraQueryParameters
|
||
* @param request
|
||
*/
|
||
RequestValidator.sanitizeEQParams = function (eQParams, queryParams) {
|
||
if (!eQParams) {
|
||
return {};
|
||
}
|
||
// Remove any query parameters already included in SSO params
|
||
queryParams.forEach(function (value, key) {
|
||
if (eQParams[key]) {
|
||
delete eQParams[key];
|
||
}
|
||
});
|
||
return eQParams;
|
||
};
|
||
return RequestValidator;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
var RequestParameterBuilder = /** @class */ (function () {
|
||
function RequestParameterBuilder() {
|
||
this.parameters = new Map();
|
||
}
|
||
/**
|
||
* add response_type = code
|
||
*/
|
||
RequestParameterBuilder.prototype.addResponseTypeCode = function () {
|
||
this.parameters.set(AADServerParamKeys.RESPONSE_TYPE, encodeURIComponent(Constants.CODE_RESPONSE_TYPE));
|
||
};
|
||
/**
|
||
* add response_mode. defaults to query.
|
||
* @param responseMode
|
||
*/
|
||
RequestParameterBuilder.prototype.addResponseMode = function (responseMode) {
|
||
this.parameters.set(AADServerParamKeys.RESPONSE_MODE, encodeURIComponent((responseMode) ? responseMode : ResponseMode.QUERY));
|
||
};
|
||
/**
|
||
* add scopes. set addOidcScopes to false to prevent default scopes in non-user scenarios
|
||
* @param scopeSet
|
||
* @param addOidcScopes
|
||
*/
|
||
RequestParameterBuilder.prototype.addScopes = function (scopes, addOidcScopes) {
|
||
if (addOidcScopes === void 0) { addOidcScopes = true; }
|
||
var requestScopes = addOidcScopes ? __spreadArrays(scopes || [], OIDC_DEFAULT_SCOPES) : scopes || [];
|
||
var scopeSet = new ScopeSet(requestScopes);
|
||
this.parameters.set(AADServerParamKeys.SCOPE, encodeURIComponent(scopeSet.printScopes()));
|
||
};
|
||
/**
|
||
* add clientId
|
||
* @param clientId
|
||
*/
|
||
RequestParameterBuilder.prototype.addClientId = function (clientId) {
|
||
this.parameters.set(AADServerParamKeys.CLIENT_ID, encodeURIComponent(clientId));
|
||
};
|
||
/**
|
||
* add redirect_uri
|
||
* @param redirectUri
|
||
*/
|
||
RequestParameterBuilder.prototype.addRedirectUri = function (redirectUri) {
|
||
RequestValidator.validateRedirectUri(redirectUri);
|
||
this.parameters.set(AADServerParamKeys.REDIRECT_URI, encodeURIComponent(redirectUri));
|
||
};
|
||
/**
|
||
* add post logout redirectUri
|
||
* @param redirectUri
|
||
*/
|
||
RequestParameterBuilder.prototype.addPostLogoutRedirectUri = function (redirectUri) {
|
||
RequestValidator.validateRedirectUri(redirectUri);
|
||
this.parameters.set(AADServerParamKeys.POST_LOGOUT_URI, encodeURIComponent(redirectUri));
|
||
};
|
||
/**
|
||
* add id_token_hint to logout request
|
||
* @param idTokenHint
|
||
*/
|
||
RequestParameterBuilder.prototype.addIdTokenHint = function (idTokenHint) {
|
||
this.parameters.set(AADServerParamKeys.ID_TOKEN_HINT, encodeURIComponent(idTokenHint));
|
||
};
|
||
/**
|
||
* add domain_hint
|
||
* @param domainHint
|
||
*/
|
||
RequestParameterBuilder.prototype.addDomainHint = function (domainHint) {
|
||
this.parameters.set(SSOTypes.DOMAIN_HINT, encodeURIComponent(domainHint));
|
||
};
|
||
/**
|
||
* add login_hint
|
||
* @param loginHint
|
||
*/
|
||
RequestParameterBuilder.prototype.addLoginHint = function (loginHint) {
|
||
this.parameters.set(SSOTypes.LOGIN_HINT, encodeURIComponent(loginHint));
|
||
};
|
||
/**
|
||
* add sid
|
||
* @param sid
|
||
*/
|
||
RequestParameterBuilder.prototype.addSid = function (sid) {
|
||
this.parameters.set(SSOTypes.SID, encodeURIComponent(sid));
|
||
};
|
||
/**
|
||
* add claims
|
||
* @param claims
|
||
*/
|
||
RequestParameterBuilder.prototype.addClaims = function (claims, clientCapabilities) {
|
||
var mergedClaims = this.addClientCapabilitiesToClaims(claims, clientCapabilities);
|
||
RequestValidator.validateClaims(mergedClaims);
|
||
this.parameters.set(AADServerParamKeys.CLAIMS, encodeURIComponent(mergedClaims));
|
||
};
|
||
/**
|
||
* add correlationId
|
||
* @param correlationId
|
||
*/
|
||
RequestParameterBuilder.prototype.addCorrelationId = function (correlationId) {
|
||
this.parameters.set(AADServerParamKeys.CLIENT_REQUEST_ID, encodeURIComponent(correlationId));
|
||
};
|
||
/**
|
||
* add library info query params
|
||
* @param libraryInfo
|
||
*/
|
||
RequestParameterBuilder.prototype.addLibraryInfo = function (libraryInfo) {
|
||
// Telemetry Info
|
||
this.parameters.set(AADServerParamKeys.X_CLIENT_SKU, libraryInfo.sku);
|
||
this.parameters.set(AADServerParamKeys.X_CLIENT_VER, libraryInfo.version);
|
||
this.parameters.set(AADServerParamKeys.X_CLIENT_OS, libraryInfo.os);
|
||
this.parameters.set(AADServerParamKeys.X_CLIENT_CPU, libraryInfo.cpu);
|
||
};
|
||
/**
|
||
* add prompt
|
||
* @param prompt
|
||
*/
|
||
RequestParameterBuilder.prototype.addPrompt = function (prompt) {
|
||
RequestValidator.validatePrompt(prompt);
|
||
this.parameters.set("" + AADServerParamKeys.PROMPT, encodeURIComponent(prompt));
|
||
};
|
||
/**
|
||
* add state
|
||
* @param state
|
||
*/
|
||
RequestParameterBuilder.prototype.addState = function (state) {
|
||
if (!StringUtils.isEmpty(state)) {
|
||
this.parameters.set(AADServerParamKeys.STATE, encodeURIComponent(state));
|
||
}
|
||
};
|
||
/**
|
||
* add nonce
|
||
* @param nonce
|
||
*/
|
||
RequestParameterBuilder.prototype.addNonce = function (nonce) {
|
||
this.parameters.set(AADServerParamKeys.NONCE, encodeURIComponent(nonce));
|
||
};
|
||
/**
|
||
* add code_challenge and code_challenge_method
|
||
* - throw if either of them are not passed
|
||
* @param codeChallenge
|
||
* @param codeChallengeMethod
|
||
*/
|
||
RequestParameterBuilder.prototype.addCodeChallengeParams = function (codeChallenge, codeChallengeMethod) {
|
||
RequestValidator.validateCodeChallengeParams(codeChallenge, codeChallengeMethod);
|
||
if (codeChallenge && codeChallengeMethod) {
|
||
this.parameters.set(AADServerParamKeys.CODE_CHALLENGE, encodeURIComponent(codeChallenge));
|
||
this.parameters.set(AADServerParamKeys.CODE_CHALLENGE_METHOD, encodeURIComponent(codeChallengeMethod));
|
||
}
|
||
else {
|
||
throw ClientConfigurationError.createInvalidCodeChallengeParamsError();
|
||
}
|
||
};
|
||
/**
|
||
* add the `authorization_code` passed by the user to exchange for a token
|
||
* @param code
|
||
*/
|
||
RequestParameterBuilder.prototype.addAuthorizationCode = function (code) {
|
||
this.parameters.set(AADServerParamKeys.CODE, encodeURIComponent(code));
|
||
};
|
||
/**
|
||
* add the `authorization_code` passed by the user to exchange for a token
|
||
* @param code
|
||
*/
|
||
RequestParameterBuilder.prototype.addDeviceCode = function (code) {
|
||
this.parameters.set(AADServerParamKeys.DEVICE_CODE, encodeURIComponent(code));
|
||
};
|
||
/**
|
||
* add the `refreshToken` passed by the user
|
||
* @param refreshToken
|
||
*/
|
||
RequestParameterBuilder.prototype.addRefreshToken = function (refreshToken) {
|
||
this.parameters.set(AADServerParamKeys.REFRESH_TOKEN, encodeURIComponent(refreshToken));
|
||
};
|
||
/**
|
||
* add the `code_verifier` passed by the user to exchange for a token
|
||
* @param codeVerifier
|
||
*/
|
||
RequestParameterBuilder.prototype.addCodeVerifier = function (codeVerifier) {
|
||
this.parameters.set(AADServerParamKeys.CODE_VERIFIER, encodeURIComponent(codeVerifier));
|
||
};
|
||
/**
|
||
* add client_secret
|
||
* @param clientSecret
|
||
*/
|
||
RequestParameterBuilder.prototype.addClientSecret = function (clientSecret) {
|
||
this.parameters.set(AADServerParamKeys.CLIENT_SECRET, encodeURIComponent(clientSecret));
|
||
};
|
||
/**
|
||
* add clientAssertion for confidential client flows
|
||
* @param clientAssertion
|
||
*/
|
||
RequestParameterBuilder.prototype.addClientAssertion = function (clientAssertion) {
|
||
this.parameters.set(AADServerParamKeys.CLIENT_ASSERTION, encodeURIComponent(clientAssertion));
|
||
};
|
||
/**
|
||
* add clientAssertionType for confidential client flows
|
||
* @param clientAssertionType
|
||
*/
|
||
RequestParameterBuilder.prototype.addClientAssertionType = function (clientAssertionType) {
|
||
this.parameters.set(AADServerParamKeys.CLIENT_ASSERTION_TYPE, encodeURIComponent(clientAssertionType));
|
||
};
|
||
/**
|
||
* add OBO assertion for confidential client flows
|
||
* @param clientAssertion
|
||
*/
|
||
RequestParameterBuilder.prototype.addOboAssertion = function (oboAssertion) {
|
||
this.parameters.set(AADServerParamKeys.OBO_ASSERTION, encodeURIComponent(oboAssertion));
|
||
};
|
||
/**
|
||
* add grant type
|
||
* @param grantType
|
||
*/
|
||
RequestParameterBuilder.prototype.addRequestTokenUse = function (tokenUse) {
|
||
this.parameters.set(AADServerParamKeys.REQUESTED_TOKEN_USE, encodeURIComponent(tokenUse));
|
||
};
|
||
/**
|
||
* add grant type
|
||
* @param grantType
|
||
*/
|
||
RequestParameterBuilder.prototype.addGrantType = function (grantType) {
|
||
this.parameters.set(AADServerParamKeys.GRANT_TYPE, encodeURIComponent(grantType));
|
||
};
|
||
/**
|
||
* add client info
|
||
*
|
||
*/
|
||
RequestParameterBuilder.prototype.addClientInfo = function () {
|
||
this.parameters.set(ClientInfo, "1");
|
||
};
|
||
/**
|
||
* add extraQueryParams
|
||
* @param eQparams
|
||
*/
|
||
RequestParameterBuilder.prototype.addExtraQueryParameters = function (eQparams) {
|
||
var _this = this;
|
||
RequestValidator.sanitizeEQParams(eQparams, this.parameters);
|
||
Object.keys(eQparams).forEach(function (key) {
|
||
_this.parameters.set(key, eQparams[key]);
|
||
});
|
||
};
|
||
RequestParameterBuilder.prototype.addClientCapabilitiesToClaims = function (claims, clientCapabilities) {
|
||
var mergedClaims;
|
||
// Parse provided claims into JSON object or initialize empty object
|
||
if (!claims) {
|
||
mergedClaims = {};
|
||
}
|
||
else {
|
||
try {
|
||
mergedClaims = JSON.parse(claims);
|
||
}
|
||
catch (e) {
|
||
throw ClientConfigurationError.createInvalidClaimsRequestError();
|
||
}
|
||
}
|
||
if (clientCapabilities && clientCapabilities.length > 0) {
|
||
if (!mergedClaims.hasOwnProperty(ClaimsRequestKeys.ACCESS_TOKEN)) {
|
||
// Add access_token key to claims object
|
||
mergedClaims[ClaimsRequestKeys.ACCESS_TOKEN] = {};
|
||
}
|
||
// Add xms_cc claim with provided clientCapabilities to access_token key
|
||
mergedClaims[ClaimsRequestKeys.ACCESS_TOKEN][ClaimsRequestKeys.XMS_CC] = {
|
||
values: clientCapabilities
|
||
};
|
||
}
|
||
return JSON.stringify(mergedClaims);
|
||
};
|
||
/**
|
||
* adds `username` for Password Grant flow
|
||
* @param username
|
||
*/
|
||
RequestParameterBuilder.prototype.addUsername = function (username) {
|
||
this.parameters.set(PasswordGrantConstants.username, username);
|
||
};
|
||
/**
|
||
* adds `password` for Password Grant flow
|
||
* @param password
|
||
*/
|
||
RequestParameterBuilder.prototype.addPassword = function (password) {
|
||
this.parameters.set(PasswordGrantConstants.password, password);
|
||
};
|
||
/**
|
||
* add pop_jwk to query params
|
||
* @param cnfString
|
||
*/
|
||
RequestParameterBuilder.prototype.addPopToken = function (cnfString) {
|
||
if (!StringUtils.isEmpty(cnfString)) {
|
||
this.parameters.set(AADServerParamKeys.TOKEN_TYPE, AuthenticationScheme.POP);
|
||
this.parameters.set(AADServerParamKeys.REQ_CNF, encodeURIComponent(cnfString));
|
||
}
|
||
};
|
||
/**
|
||
* Utility to create a URL from the params map
|
||
*/
|
||
RequestParameterBuilder.prototype.createQueryString = function () {
|
||
var queryParameterArray = new Array();
|
||
this.parameters.forEach(function (value, key) {
|
||
queryParameterArray.push(key + "=" + value);
|
||
});
|
||
return queryParameterArray.join("&");
|
||
};
|
||
return RequestParameterBuilder;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* ID_TOKEN Cache
|
||
*
|
||
* Key:Value Schema:
|
||
*
|
||
* Key Example: uid.utid-login.microsoftonline.com-idtoken-clientId-contoso.com-
|
||
*
|
||
* Value Schema:
|
||
* {
|
||
* homeAccountId: home account identifier for the auth scheme,
|
||
* environment: entity that issued the token, represented as a full host
|
||
* credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other
|
||
* clientId: client ID of the application
|
||
* secret: Actual credential as a string
|
||
* realm: Full tenant or organizational identifier that the account belongs to
|
||
* }
|
||
*/
|
||
var IdTokenEntity = /** @class */ (function (_super) {
|
||
__extends(IdTokenEntity, _super);
|
||
function IdTokenEntity() {
|
||
return _super !== null && _super.apply(this, arguments) || this;
|
||
}
|
||
/**
|
||
* Create IdTokenEntity
|
||
* @param homeAccountId
|
||
* @param authenticationResult
|
||
* @param clientId
|
||
* @param authority
|
||
*/
|
||
IdTokenEntity.createIdTokenEntity = function (homeAccountId, environment, idToken, clientId, tenantId, oboAssertion) {
|
||
var idTokenEntity = new IdTokenEntity();
|
||
idTokenEntity.credentialType = CredentialType.ID_TOKEN;
|
||
idTokenEntity.homeAccountId = homeAccountId;
|
||
idTokenEntity.environment = environment;
|
||
idTokenEntity.clientId = clientId;
|
||
idTokenEntity.secret = idToken;
|
||
idTokenEntity.realm = tenantId;
|
||
idTokenEntity.oboAssertion = oboAssertion;
|
||
return idTokenEntity;
|
||
};
|
||
/**
|
||
* Validates an entity: checks for all expected params
|
||
* @param entity
|
||
*/
|
||
IdTokenEntity.isIdTokenEntity = function (entity) {
|
||
if (!entity) {
|
||
return false;
|
||
}
|
||
return (entity.hasOwnProperty("homeAccountId") &&
|
||
entity.hasOwnProperty("environment") &&
|
||
entity.hasOwnProperty("credentialType") &&
|
||
entity.hasOwnProperty("realm") &&
|
||
entity.hasOwnProperty("clientId") &&
|
||
entity.hasOwnProperty("secret") &&
|
||
entity["credentialType"] === CredentialType.ID_TOKEN);
|
||
};
|
||
return IdTokenEntity;
|
||
}(CredentialEntity));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* Utility class which exposes functions for managing date and time operations.
|
||
*/
|
||
var TimeUtils = /** @class */ (function () {
|
||
function TimeUtils() {
|
||
}
|
||
/**
|
||
* return the current time in Unix time (seconds).
|
||
*/
|
||
TimeUtils.nowSeconds = function () {
|
||
// Date.getTime() returns in milliseconds.
|
||
return Math.round(new Date().getTime() / 1000.0);
|
||
};
|
||
/**
|
||
* check if a token is expired based on given UTC time in seconds.
|
||
* @param expiresOn
|
||
*/
|
||
TimeUtils.isTokenExpired = function (expiresOn, offset) {
|
||
// check for access token expiry
|
||
var expirationSec = Number(expiresOn) || 0;
|
||
var offsetCurrentTimeSec = TimeUtils.nowSeconds() + offset;
|
||
// If current time + offset is greater than token expiration time, then token is expired.
|
||
return (offsetCurrentTimeSec > expirationSec);
|
||
};
|
||
return TimeUtils;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* ACCESS_TOKEN Credential Type
|
||
*
|
||
* Key:Value Schema:
|
||
*
|
||
* Key Example: uid.utid-login.microsoftonline.com-accesstoken-clientId-contoso.com-user.read
|
||
*
|
||
* Value Schema:
|
||
* {
|
||
* homeAccountId: home account identifier for the auth scheme,
|
||
* environment: entity that issued the token, represented as a full host
|
||
* credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other
|
||
* clientId: client ID of the application
|
||
* secret: Actual credential as a string
|
||
* familyId: Family ID identifier, usually only used for refresh tokens
|
||
* realm: Full tenant or organizational identifier that the account belongs to
|
||
* target: Permissions that are included in the token, or for refresh tokens, the resource identifier.
|
||
* cachedAt: Absolute device time when entry was created in the cache.
|
||
* expiresOn: Token expiry time, calculated based on current UTC time in seconds. Represented as a string.
|
||
* extendedExpiresOn: Additional extended expiry time until when token is valid in case of server-side outage. Represented as string in UTC seconds.
|
||
* keyId: used for POP and SSH tokenTypes
|
||
* tokenType: Type of the token issued. Usually "Bearer"
|
||
* }
|
||
*/
|
||
var AccessTokenEntity = /** @class */ (function (_super) {
|
||
__extends(AccessTokenEntity, _super);
|
||
function AccessTokenEntity() {
|
||
return _super !== null && _super.apply(this, arguments) || this;
|
||
}
|
||
/**
|
||
* Create AccessTokenEntity
|
||
* @param homeAccountId
|
||
* @param environment
|
||
* @param accessToken
|
||
* @param clientId
|
||
* @param tenantId
|
||
* @param scopes
|
||
* @param expiresOn
|
||
* @param extExpiresOn
|
||
*/
|
||
AccessTokenEntity.createAccessTokenEntity = function (homeAccountId, environment, accessToken, clientId, tenantId, scopes, expiresOn, extExpiresOn, tokenType, oboAssertion) {
|
||
var atEntity = new AccessTokenEntity();
|
||
atEntity.homeAccountId = homeAccountId;
|
||
atEntity.credentialType = CredentialType.ACCESS_TOKEN;
|
||
atEntity.secret = accessToken;
|
||
var currentTime = TimeUtils.nowSeconds();
|
||
atEntity.cachedAt = currentTime.toString();
|
||
/*
|
||
* Token expiry time.
|
||
* This value should be calculated based on the current UTC time measured locally and the value expires_in Represented as a string in JSON.
|
||
*/
|
||
atEntity.expiresOn = expiresOn.toString();
|
||
atEntity.extendedExpiresOn = extExpiresOn.toString();
|
||
atEntity.environment = environment;
|
||
atEntity.clientId = clientId;
|
||
atEntity.realm = tenantId;
|
||
atEntity.target = scopes;
|
||
atEntity.oboAssertion = oboAssertion;
|
||
atEntity.tokenType = StringUtils.isEmpty(tokenType) ? AuthenticationScheme.BEARER : tokenType;
|
||
return atEntity;
|
||
};
|
||
/**
|
||
* Validates an entity: checks for all expected params
|
||
* @param entity
|
||
*/
|
||
AccessTokenEntity.isAccessTokenEntity = function (entity) {
|
||
if (!entity) {
|
||
return false;
|
||
}
|
||
return (entity.hasOwnProperty("homeAccountId") &&
|
||
entity.hasOwnProperty("environment") &&
|
||
entity.hasOwnProperty("credentialType") &&
|
||
entity.hasOwnProperty("realm") &&
|
||
entity.hasOwnProperty("clientId") &&
|
||
entity.hasOwnProperty("secret") &&
|
||
entity.hasOwnProperty("target") &&
|
||
entity["credentialType"] === CredentialType.ACCESS_TOKEN);
|
||
};
|
||
return AccessTokenEntity;
|
||
}(CredentialEntity));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* REFRESH_TOKEN Cache
|
||
*
|
||
* Key:Value Schema:
|
||
*
|
||
* Key Example: uid.utid-login.microsoftonline.com-refreshtoken-clientId--
|
||
*
|
||
* Value:
|
||
* {
|
||
* homeAccountId: home account identifier for the auth scheme,
|
||
* environment: entity that issued the token, represented as a full host
|
||
* credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other
|
||
* clientId: client ID of the application
|
||
* secret: Actual credential as a string
|
||
* familyId: Family ID identifier, '1' represents Microsoft Family
|
||
* realm: Full tenant or organizational identifier that the account belongs to
|
||
* target: Permissions that are included in the token, or for refresh tokens, the resource identifier.
|
||
* }
|
||
*/
|
||
var RefreshTokenEntity = /** @class */ (function (_super) {
|
||
__extends(RefreshTokenEntity, _super);
|
||
function RefreshTokenEntity() {
|
||
return _super !== null && _super.apply(this, arguments) || this;
|
||
}
|
||
/**
|
||
* Create RefreshTokenEntity
|
||
* @param homeAccountId
|
||
* @param authenticationResult
|
||
* @param clientId
|
||
* @param authority
|
||
*/
|
||
RefreshTokenEntity.createRefreshTokenEntity = function (homeAccountId, environment, refreshToken, clientId, familyId, oboAssertion) {
|
||
var rtEntity = new RefreshTokenEntity();
|
||
rtEntity.clientId = clientId;
|
||
rtEntity.credentialType = CredentialType.REFRESH_TOKEN;
|
||
rtEntity.environment = environment;
|
||
rtEntity.homeAccountId = homeAccountId;
|
||
rtEntity.secret = refreshToken;
|
||
rtEntity.oboAssertion = oboAssertion;
|
||
if (familyId)
|
||
rtEntity.familyId = familyId;
|
||
return rtEntity;
|
||
};
|
||
/**
|
||
* Validates an entity: checks for all expected params
|
||
* @param entity
|
||
*/
|
||
RefreshTokenEntity.isRefreshTokenEntity = function (entity) {
|
||
if (!entity) {
|
||
return false;
|
||
}
|
||
return (entity.hasOwnProperty("homeAccountId") &&
|
||
entity.hasOwnProperty("environment") &&
|
||
entity.hasOwnProperty("credentialType") &&
|
||
entity.hasOwnProperty("clientId") &&
|
||
entity.hasOwnProperty("secret") &&
|
||
entity["credentialType"] === CredentialType.REFRESH_TOKEN);
|
||
};
|
||
return RefreshTokenEntity;
|
||
}(CredentialEntity));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* InteractionRequiredAuthErrorMessage class containing string constants used by error codes and messages.
|
||
*/
|
||
var InteractionRequiredAuthErrorMessage = [
|
||
"interaction_required",
|
||
"consent_required",
|
||
"login_required"
|
||
];
|
||
var InteractionRequiredAuthSubErrorMessage = [
|
||
"message_only",
|
||
"additional_action",
|
||
"basic_action",
|
||
"user_password_expired",
|
||
"consent_required"
|
||
];
|
||
/**
|
||
* Error thrown when user interaction is required at the auth server.
|
||
*/
|
||
var InteractionRequiredAuthError = /** @class */ (function (_super) {
|
||
__extends(InteractionRequiredAuthError, _super);
|
||
function InteractionRequiredAuthError(errorCode, errorMessage, subError) {
|
||
var _this = _super.call(this, errorCode, errorMessage, subError) || this;
|
||
_this.name = "InteractionRequiredAuthError";
|
||
Object.setPrototypeOf(_this, InteractionRequiredAuthError.prototype);
|
||
return _this;
|
||
}
|
||
InteractionRequiredAuthError.isInteractionRequiredError = function (errorCode, errorString, subError) {
|
||
var isInteractionRequiredErrorCode = !!errorCode && InteractionRequiredAuthErrorMessage.indexOf(errorCode) > -1;
|
||
var isInteractionRequiredSubError = !!subError && InteractionRequiredAuthSubErrorMessage.indexOf(subError) > -1;
|
||
var isInteractionRequiredErrorDesc = !!errorString && InteractionRequiredAuthErrorMessage.some(function (irErrorCode) {
|
||
return errorString.indexOf(irErrorCode) > -1;
|
||
});
|
||
return isInteractionRequiredErrorCode || isInteractionRequiredErrorDesc || isInteractionRequiredSubError;
|
||
};
|
||
return InteractionRequiredAuthError;
|
||
}(ServerError));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
var CacheRecord = /** @class */ (function () {
|
||
function CacheRecord(accountEntity, idTokenEntity, accessTokenEntity, refreshTokenEntity, appMetadataEntity) {
|
||
this.account = accountEntity || null;
|
||
this.idToken = idTokenEntity || null;
|
||
this.accessToken = accessTokenEntity || null;
|
||
this.refreshToken = refreshTokenEntity || null;
|
||
this.appMetadata = appMetadataEntity || null;
|
||
}
|
||
return CacheRecord;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* Class which provides helpers for OAuth 2.0 protocol specific values
|
||
*/
|
||
var ProtocolUtils = /** @class */ (function () {
|
||
function ProtocolUtils() {
|
||
}
|
||
/**
|
||
* Appends user state with random guid, or returns random guid.
|
||
* @param userState
|
||
* @param randomGuid
|
||
*/
|
||
ProtocolUtils.setRequestState = function (cryptoObj, userState, meta) {
|
||
var libraryState = ProtocolUtils.generateLibraryState(cryptoObj, meta);
|
||
return !StringUtils.isEmpty(userState) ? "" + libraryState + Constants.RESOURCE_DELIM + userState : libraryState;
|
||
};
|
||
/**
|
||
* Generates the state value used by the common library.
|
||
* @param randomGuid
|
||
* @param cryptoObj
|
||
*/
|
||
ProtocolUtils.generateLibraryState = function (cryptoObj, meta) {
|
||
if (!cryptoObj) {
|
||
throw ClientAuthError.createNoCryptoObjectError("generateLibraryState");
|
||
}
|
||
// Create a state object containing a unique id and the timestamp of the request creation
|
||
var stateObj = {
|
||
id: cryptoObj.createNewGuid()
|
||
};
|
||
if (meta) {
|
||
stateObj.meta = meta;
|
||
}
|
||
var stateString = JSON.stringify(stateObj);
|
||
return cryptoObj.base64Encode(stateString);
|
||
};
|
||
/**
|
||
* Parses the state into the RequestStateObject, which contains the LibraryState info and the state passed by the user.
|
||
* @param state
|
||
* @param cryptoObj
|
||
*/
|
||
ProtocolUtils.parseRequestState = function (cryptoObj, state) {
|
||
if (!cryptoObj) {
|
||
throw ClientAuthError.createNoCryptoObjectError("parseRequestState");
|
||
}
|
||
if (StringUtils.isEmpty(state)) {
|
||
throw ClientAuthError.createInvalidStateError(state, "Null, undefined or empty state");
|
||
}
|
||
try {
|
||
// Split the state between library state and user passed state and decode them separately
|
||
var splitState = decodeURIComponent(state).split(Constants.RESOURCE_DELIM);
|
||
var libraryState = splitState[0];
|
||
var userState = splitState.length > 1 ? splitState.slice(1).join(Constants.RESOURCE_DELIM) : "";
|
||
var libraryStateString = cryptoObj.base64Decode(libraryState);
|
||
var libraryStateObj = JSON.parse(libraryStateString);
|
||
return {
|
||
userRequestState: !StringUtils.isEmpty(userState) ? userState : "",
|
||
libraryState: libraryStateObj
|
||
};
|
||
}
|
||
catch (e) {
|
||
throw ClientAuthError.createInvalidStateError(state, e);
|
||
}
|
||
};
|
||
return ProtocolUtils;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* Url object class which can perform various transformations on url strings.
|
||
*/
|
||
var UrlString = /** @class */ (function () {
|
||
function UrlString(url) {
|
||
this._urlString = url;
|
||
if (StringUtils.isEmpty(this._urlString)) {
|
||
// Throws error if url is empty
|
||
throw ClientConfigurationError.createUrlEmptyError();
|
||
}
|
||
if (StringUtils.isEmpty(this.getHash())) {
|
||
this._urlString = UrlString.canonicalizeUri(url);
|
||
}
|
||
}
|
||
Object.defineProperty(UrlString.prototype, "urlString", {
|
||
get: function () {
|
||
return this._urlString;
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
/**
|
||
* Ensure urls are lower case and end with a / character.
|
||
* @param url
|
||
*/
|
||
UrlString.canonicalizeUri = function (url) {
|
||
if (url) {
|
||
url = url.toLowerCase();
|
||
if (StringUtils.endsWith(url, "?")) {
|
||
url = url.slice(0, -1);
|
||
}
|
||
else if (StringUtils.endsWith(url, "?/")) {
|
||
url = url.slice(0, -2);
|
||
}
|
||
if (!StringUtils.endsWith(url, "/")) {
|
||
url += "/";
|
||
}
|
||
}
|
||
return url;
|
||
};
|
||
/**
|
||
* Throws if urlString passed is not a valid authority URI string.
|
||
*/
|
||
UrlString.prototype.validateAsUri = function () {
|
||
// Attempts to parse url for uri components
|
||
var components;
|
||
try {
|
||
components = this.getUrlComponents();
|
||
}
|
||
catch (e) {
|
||
throw ClientConfigurationError.createUrlParseError(e);
|
||
}
|
||
// Throw error if URI or path segments are not parseable.
|
||
if (!components.HostNameAndPort || !components.PathSegments) {
|
||
throw ClientConfigurationError.createUrlParseError("Given url string: " + this.urlString);
|
||
}
|
||
// Throw error if uri is insecure.
|
||
if (!components.Protocol || components.Protocol.toLowerCase() !== "https:") {
|
||
throw ClientConfigurationError.createInsecureAuthorityUriError(this.urlString);
|
||
}
|
||
};
|
||
/**
|
||
* Function to remove query string params from url. Returns the new url.
|
||
* @param url
|
||
* @param name
|
||
*/
|
||
UrlString.prototype.urlRemoveQueryStringParameter = function (name) {
|
||
var regex = new RegExp("(\\&" + name + "=)[^\&]+");
|
||
this._urlString = this.urlString.replace(regex, "");
|
||
// name=value&
|
||
regex = new RegExp("(" + name + "=)[^\&]+&");
|
||
this._urlString = this.urlString.replace(regex, "");
|
||
// name=value
|
||
regex = new RegExp("(" + name + "=)[^\&]+");
|
||
this._urlString = this.urlString.replace(regex, "");
|
||
return this.urlString;
|
||
};
|
||
UrlString.removeHashFromUrl = function (url) {
|
||
return UrlString.canonicalizeUri(url.split("#")[0]);
|
||
};
|
||
/**
|
||
* Given a url like https://a:b/common/d?e=f#g, and a tenantId, returns https://a:b/tenantId/d
|
||
* @param href The url
|
||
* @param tenantId The tenant id to replace
|
||
*/
|
||
UrlString.prototype.replaceTenantPath = function (tenantId) {
|
||
var urlObject = this.getUrlComponents();
|
||
var pathArray = urlObject.PathSegments;
|
||
if (tenantId && (pathArray.length !== 0 && (pathArray[0] === AADAuthorityConstants.COMMON || pathArray[0] === AADAuthorityConstants.ORGANIZATIONS))) {
|
||
pathArray[0] = tenantId;
|
||
}
|
||
return UrlString.constructAuthorityUriFromObject(urlObject);
|
||
};
|
||
/**
|
||
* Returns the anchor part(#) of the URL
|
||
*/
|
||
UrlString.prototype.getHash = function () {
|
||
return UrlString.parseHash(this.urlString);
|
||
};
|
||
/**
|
||
* Parses out the components from a url string.
|
||
* @returns An object with the various components. Please cache this value insted of calling this multiple times on the same url.
|
||
*/
|
||
UrlString.prototype.getUrlComponents = function () {
|
||
// https://gist.github.com/curtisz/11139b2cfcaef4a261e0
|
||
var regEx = RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?");
|
||
// If url string does not match regEx, we throw an error
|
||
var match = this.urlString.match(regEx);
|
||
if (!match) {
|
||
throw ClientConfigurationError.createUrlParseError("Given url string: " + this.urlString);
|
||
}
|
||
// Url component object
|
||
var urlComponents = {
|
||
Protocol: match[1],
|
||
HostNameAndPort: match[4],
|
||
AbsolutePath: match[5],
|
||
QueryString: match[7]
|
||
};
|
||
var pathSegments = urlComponents.AbsolutePath.split("/");
|
||
pathSegments = pathSegments.filter(function (val) { return val && val.length > 0; }); // remove empty elements
|
||
urlComponents.PathSegments = pathSegments;
|
||
if (!StringUtils.isEmpty(urlComponents.QueryString) && urlComponents.QueryString.endsWith("/")) {
|
||
urlComponents.QueryString = urlComponents.QueryString.substring(0, urlComponents.QueryString.length - 1);
|
||
}
|
||
return urlComponents;
|
||
};
|
||
UrlString.getDomainFromUrl = function (url) {
|
||
var regEx = RegExp("^([^:/?#]+://)?([^/?#]*)");
|
||
var match = url.match(regEx);
|
||
if (!match) {
|
||
throw ClientConfigurationError.createUrlParseError("Given url string: " + url);
|
||
}
|
||
return match[2];
|
||
};
|
||
UrlString.getAbsoluteUrl = function (relativeUrl, baseUrl) {
|
||
if (relativeUrl[0] === Constants.FORWARD_SLASH) {
|
||
var url = new UrlString(baseUrl);
|
||
var baseComponents = url.getUrlComponents();
|
||
return baseComponents.Protocol + "//" + baseComponents.HostNameAndPort + relativeUrl;
|
||
}
|
||
return relativeUrl;
|
||
};
|
||
/**
|
||
* Parses hash string from given string. Returns empty string if no hash symbol is found.
|
||
* @param hashString
|
||
*/
|
||
UrlString.parseHash = function (hashString) {
|
||
var hashIndex1 = hashString.indexOf("#");
|
||
var hashIndex2 = hashString.indexOf("#/");
|
||
if (hashIndex2 > -1) {
|
||
return hashString.substring(hashIndex2 + 2);
|
||
}
|
||
else if (hashIndex1 > -1) {
|
||
return hashString.substring(hashIndex1 + 1);
|
||
}
|
||
return "";
|
||
};
|
||
UrlString.constructAuthorityUriFromObject = function (urlObject) {
|
||
return new UrlString(urlObject.Protocol + "//" + urlObject.HostNameAndPort + "/" + urlObject.PathSegments.join("/"));
|
||
};
|
||
/**
|
||
* Returns URL hash as server auth code response object.
|
||
*/
|
||
UrlString.getDeserializedHash = function (hash) {
|
||
// Check if given hash is empty
|
||
if (StringUtils.isEmpty(hash)) {
|
||
return {};
|
||
}
|
||
// Strip the # symbol if present
|
||
var parsedHash = UrlString.parseHash(hash);
|
||
// If # symbol was not present, above will return empty string, so give original hash value
|
||
var deserializedHash = StringUtils.queryStringToObject(StringUtils.isEmpty(parsedHash) ? hash : parsedHash);
|
||
// Check if deserialization didn't work
|
||
if (!deserializedHash) {
|
||
throw ClientAuthError.createHashNotDeserializedError(JSON.stringify(deserializedHash));
|
||
}
|
||
return deserializedHash;
|
||
};
|
||
/**
|
||
* Check if the hash of the URL string contains known properties
|
||
*/
|
||
UrlString.hashContainsKnownProperties = function (hash) {
|
||
if (StringUtils.isEmpty(hash)) {
|
||
return false;
|
||
}
|
||
var parameters = UrlString.getDeserializedHash(hash);
|
||
return !!(parameters.code ||
|
||
parameters.error_description ||
|
||
parameters.error ||
|
||
parameters.state);
|
||
};
|
||
return UrlString;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
var KeyLocation;
|
||
(function (KeyLocation) {
|
||
KeyLocation["SW"] = "sw";
|
||
KeyLocation["UHW"] = "uhw";
|
||
})(KeyLocation || (KeyLocation = {}));
|
||
var PopTokenGenerator = /** @class */ (function () {
|
||
function PopTokenGenerator(cryptoUtils) {
|
||
this.cryptoUtils = cryptoUtils;
|
||
}
|
||
PopTokenGenerator.prototype.generateCnf = function (resourceRequestMethod, resourceRequestUri) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var kidThumbprint, reqCnf;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0: return [4 /*yield*/, this.cryptoUtils.getPublicKeyThumbprint(resourceRequestMethod, resourceRequestUri)];
|
||
case 1:
|
||
kidThumbprint = _a.sent();
|
||
reqCnf = {
|
||
kid: kidThumbprint,
|
||
xms_ksl: KeyLocation.SW
|
||
};
|
||
return [2 /*return*/, this.cryptoUtils.base64Encode(JSON.stringify(reqCnf))];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
PopTokenGenerator.prototype.signPopToken = function (accessToken, resourceRequestMethod, resourceRequestUri) {
|
||
var _a;
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var tokenClaims, resourceUrlString, resourceUrlComponents;
|
||
return __generator(this, function (_b) {
|
||
switch (_b.label) {
|
||
case 0:
|
||
tokenClaims = AuthToken.extractTokenClaims(accessToken, this.cryptoUtils);
|
||
resourceUrlString = new UrlString(resourceRequestUri);
|
||
resourceUrlComponents = resourceUrlString.getUrlComponents();
|
||
if (!((_a = tokenClaims === null || tokenClaims === void 0 ? void 0 : tokenClaims.cnf) === null || _a === void 0 ? void 0 : _a.kid)) {
|
||
throw ClientAuthError.createTokenClaimsRequiredError();
|
||
}
|
||
return [4 /*yield*/, this.cryptoUtils.signJwt({
|
||
at: accessToken,
|
||
ts: "" + TimeUtils.nowSeconds(),
|
||
m: resourceRequestMethod.toUpperCase(),
|
||
u: resourceUrlComponents.HostNameAndPort || "",
|
||
nonce: this.cryptoUtils.createNewGuid(),
|
||
p: resourceUrlComponents.AbsolutePath,
|
||
q: [[], resourceUrlComponents.QueryString],
|
||
}, tokenClaims.cnf.kid)];
|
||
case 1: return [2 /*return*/, _b.sent()];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
return PopTokenGenerator;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* APP_METADATA Cache
|
||
*
|
||
* Key:Value Schema:
|
||
*
|
||
* Key: appmetadata-<environment>-<client_id>
|
||
*
|
||
* Value:
|
||
* {
|
||
* clientId: client ID of the application
|
||
* environment: entity that issued the token, represented as a full host
|
||
* familyId: Family ID identifier, '1' represents Microsoft Family
|
||
* }
|
||
*/
|
||
var AppMetadataEntity = /** @class */ (function () {
|
||
function AppMetadataEntity() {
|
||
}
|
||
/**
|
||
* Generate AppMetadata Cache Key as per the schema: appmetadata-<environment>-<client_id>
|
||
*/
|
||
AppMetadataEntity.prototype.generateAppMetadataKey = function () {
|
||
return AppMetadataEntity.generateAppMetadataCacheKey(this.environment, this.clientId);
|
||
};
|
||
/**
|
||
* Generate AppMetadata Cache Key
|
||
*/
|
||
AppMetadataEntity.generateAppMetadataCacheKey = function (environment, clientId) {
|
||
var appMetaDataKeyArray = [
|
||
APP_METADATA,
|
||
environment,
|
||
clientId,
|
||
];
|
||
return appMetaDataKeyArray.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
|
||
};
|
||
/**
|
||
* Creates AppMetadataEntity
|
||
* @param clientId
|
||
* @param environment
|
||
* @param familyId
|
||
*/
|
||
AppMetadataEntity.createAppMetadataEntity = function (clientId, environment, familyId) {
|
||
var appMetadata = new AppMetadataEntity();
|
||
appMetadata.clientId = clientId;
|
||
appMetadata.environment = environment;
|
||
if (familyId) {
|
||
appMetadata.familyId = familyId;
|
||
}
|
||
return appMetadata;
|
||
};
|
||
/**
|
||
* Validates an entity: checks for all expected params
|
||
* @param entity
|
||
*/
|
||
AppMetadataEntity.isAppMetadataEntity = function (key, entity) {
|
||
if (!entity) {
|
||
return false;
|
||
}
|
||
return (key.indexOf(APP_METADATA) === 0 &&
|
||
entity.hasOwnProperty("clientId") &&
|
||
entity.hasOwnProperty("environment"));
|
||
};
|
||
return AppMetadataEntity;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* This class instance helps track the memory changes facilitating
|
||
* decisions to read from and write to the persistent cache
|
||
*/ var TokenCacheContext = /** @class */ (function () {
|
||
function TokenCacheContext(tokenCache, hasChanged) {
|
||
this.cache = tokenCache;
|
||
this.hasChanged = hasChanged;
|
||
}
|
||
Object.defineProperty(TokenCacheContext.prototype, "cacheHasChanged", {
|
||
/**
|
||
* boolean which indicates the changes in cache
|
||
*/
|
||
get: function () {
|
||
return this.hasChanged;
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
Object.defineProperty(TokenCacheContext.prototype, "tokenCache", {
|
||
/**
|
||
* function to retrieve the token cache
|
||
*/
|
||
get: function () {
|
||
return this.cache;
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
return TokenCacheContext;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* Class that handles response parsing.
|
||
*/
|
||
var ResponseHandler = /** @class */ (function () {
|
||
function ResponseHandler(clientId, cacheStorage, cryptoObj, logger, serializableCache, persistencePlugin) {
|
||
this.clientId = clientId;
|
||
this.cacheStorage = cacheStorage;
|
||
this.cryptoObj = cryptoObj;
|
||
this.logger = logger;
|
||
this.serializableCache = serializableCache;
|
||
this.persistencePlugin = persistencePlugin;
|
||
}
|
||
/**
|
||
* Function which validates server authorization code response.
|
||
* @param serverResponseHash
|
||
* @param cachedState
|
||
* @param cryptoObj
|
||
*/
|
||
ResponseHandler.prototype.validateServerAuthorizationCodeResponse = function (serverResponseHash, cachedState, cryptoObj) {
|
||
if (!serverResponseHash.state || !cachedState) {
|
||
throw !serverResponseHash.state ? ClientAuthError.createStateNotFoundError("Server State") : ClientAuthError.createStateNotFoundError("Cached State");
|
||
}
|
||
if (decodeURIComponent(serverResponseHash.state) !== decodeURIComponent(cachedState)) {
|
||
throw ClientAuthError.createStateMismatchError();
|
||
}
|
||
// Check for error
|
||
if (serverResponseHash.error || serverResponseHash.error_description || serverResponseHash.suberror) {
|
||
if (InteractionRequiredAuthError.isInteractionRequiredError(serverResponseHash.error, serverResponseHash.error_description, serverResponseHash.suberror)) {
|
||
throw new InteractionRequiredAuthError(serverResponseHash.error || Constants.EMPTY_STRING, serverResponseHash.error_description, serverResponseHash.suberror);
|
||
}
|
||
throw new ServerError(serverResponseHash.error || Constants.EMPTY_STRING, serverResponseHash.error_description, serverResponseHash.suberror);
|
||
}
|
||
if (serverResponseHash.client_info) {
|
||
buildClientInfo(serverResponseHash.client_info, cryptoObj);
|
||
}
|
||
};
|
||
/**
|
||
* Function which validates server authorization token response.
|
||
* @param serverResponse
|
||
*/
|
||
ResponseHandler.prototype.validateTokenResponse = function (serverResponse) {
|
||
// Check for error
|
||
if (serverResponse.error || serverResponse.error_description || serverResponse.suberror) {
|
||
if (InteractionRequiredAuthError.isInteractionRequiredError(serverResponse.error, serverResponse.error_description, serverResponse.suberror)) {
|
||
throw new InteractionRequiredAuthError(serverResponse.error, serverResponse.error_description, serverResponse.suberror);
|
||
}
|
||
var errString = serverResponse.error_codes + " - [" + serverResponse.timestamp + "]: " + serverResponse.error_description + " - Correlation ID: " + serverResponse.correlation_id + " - Trace ID: " + serverResponse.trace_id;
|
||
throw new ServerError(serverResponse.error, errString);
|
||
}
|
||
};
|
||
/**
|
||
* Returns a constructed token response based on given string. Also manages the cache updates and cleanups.
|
||
* @param serverTokenResponse
|
||
* @param authority
|
||
*/
|
||
ResponseHandler.prototype.handleServerTokenResponse = function (serverTokenResponse, authority, reqTimestamp, resourceRequestMethod, resourceRequestUri, authCodePayload, requestScopes, oboAssertion, handlingRefreshTokenResponse) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var idTokenObj, requestStateObj, cacheRecord, cacheContext, key, account;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
if (serverTokenResponse.id_token) {
|
||
idTokenObj = new AuthToken(serverTokenResponse.id_token || Constants.EMPTY_STRING, this.cryptoObj);
|
||
// token nonce check (TODO: Add a warning if no nonce is given?)
|
||
if (authCodePayload && !StringUtils.isEmpty(authCodePayload.nonce)) {
|
||
if (idTokenObj.claims.nonce !== authCodePayload.nonce) {
|
||
throw ClientAuthError.createNonceMismatchError();
|
||
}
|
||
}
|
||
}
|
||
// generate homeAccountId
|
||
this.homeAccountIdentifier = AccountEntity.generateHomeAccountId(serverTokenResponse.client_info || Constants.EMPTY_STRING, authority.authorityType, this.logger, this.cryptoObj, idTokenObj);
|
||
if (!!authCodePayload && !!authCodePayload.state) {
|
||
requestStateObj = ProtocolUtils.parseRequestState(this.cryptoObj, authCodePayload.state);
|
||
}
|
||
cacheRecord = this.generateCacheRecord(serverTokenResponse, authority, reqTimestamp, idTokenObj, requestScopes, oboAssertion, authCodePayload);
|
||
_a.label = 1;
|
||
case 1:
|
||
_a.trys.push([1, , 4, 7]);
|
||
if (!(this.persistencePlugin && this.serializableCache)) return [3 /*break*/, 3];
|
||
this.logger.verbose("Persistence enabled, calling beforeCacheAccess");
|
||
cacheContext = new TokenCacheContext(this.serializableCache, true);
|
||
return [4 /*yield*/, this.persistencePlugin.beforeCacheAccess(cacheContext)];
|
||
case 2:
|
||
_a.sent();
|
||
_a.label = 3;
|
||
case 3:
|
||
/*
|
||
* When saving a refreshed tokens to the cache, it is expected that the account that was used is present in the cache.
|
||
* If not present, we should return null, as it's the case that another application called removeAccount in between
|
||
* the calls to getAllAccounts and acquireTokenSilent. We should not overwrite that removal.
|
||
*/
|
||
if (handlingRefreshTokenResponse && cacheRecord.account) {
|
||
key = cacheRecord.account.generateAccountKey();
|
||
account = this.cacheStorage.getAccount(key);
|
||
if (!account) {
|
||
this.logger.warning("Account used to refresh tokens not in persistence, refreshed tokens will not be stored in the cache");
|
||
return [2 /*return*/, ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, idTokenObj, requestStateObj, resourceRequestMethod, resourceRequestUri)];
|
||
}
|
||
}
|
||
this.cacheStorage.saveCacheRecord(cacheRecord);
|
||
return [3 /*break*/, 7];
|
||
case 4:
|
||
if (!(this.persistencePlugin && this.serializableCache && cacheContext)) return [3 /*break*/, 6];
|
||
this.logger.verbose("Persistence enabled, calling afterCacheAccess");
|
||
return [4 /*yield*/, this.persistencePlugin.afterCacheAccess(cacheContext)];
|
||
case 5:
|
||
_a.sent();
|
||
_a.label = 6;
|
||
case 6: return [7 /*endfinally*/];
|
||
case 7: return [2 /*return*/, ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, idTokenObj, requestStateObj, resourceRequestMethod, resourceRequestUri)];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Generates CacheRecord
|
||
* @param serverTokenResponse
|
||
* @param idTokenObj
|
||
* @param authority
|
||
*/
|
||
ResponseHandler.prototype.generateCacheRecord = function (serverTokenResponse, authority, reqTimestamp, idTokenObj, requestScopes, oboAssertion, authCodePayload) {
|
||
var env = authority.getPreferredCache();
|
||
if (StringUtils.isEmpty(env)) {
|
||
throw ClientAuthError.createInvalidCacheEnvironmentError();
|
||
}
|
||
// IdToken: non AAD scenarios can have empty realm
|
||
var cachedIdToken;
|
||
var cachedAccount;
|
||
if (!StringUtils.isEmpty(serverTokenResponse.id_token) && !!idTokenObj) {
|
||
cachedIdToken = IdTokenEntity.createIdTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.id_token || Constants.EMPTY_STRING, this.clientId, idTokenObj.claims.tid || Constants.EMPTY_STRING, oboAssertion);
|
||
cachedAccount = this.generateAccountEntity(serverTokenResponse, idTokenObj, authority, oboAssertion, authCodePayload);
|
||
}
|
||
// AccessToken
|
||
var cachedAccessToken = null;
|
||
if (!StringUtils.isEmpty(serverTokenResponse.access_token)) {
|
||
// If scopes not returned in server response, use request scopes
|
||
var responseScopes = serverTokenResponse.scope ? ScopeSet.fromString(serverTokenResponse.scope) : new ScopeSet(requestScopes || []);
|
||
// Use timestamp calculated before request
|
||
var tokenExpirationSeconds = reqTimestamp + (serverTokenResponse.expires_in || 0);
|
||
var extendedTokenExpirationSeconds = tokenExpirationSeconds + (serverTokenResponse.ext_expires_in || 0);
|
||
// non AAD scenarios can have empty realm
|
||
cachedAccessToken = AccessTokenEntity.createAccessTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.access_token || Constants.EMPTY_STRING, this.clientId, idTokenObj ? idTokenObj.claims.tid || Constants.EMPTY_STRING : authority.tenant, responseScopes.printScopes(), tokenExpirationSeconds, extendedTokenExpirationSeconds, serverTokenResponse.token_type, oboAssertion);
|
||
}
|
||
// refreshToken
|
||
var cachedRefreshToken = null;
|
||
if (!StringUtils.isEmpty(serverTokenResponse.refresh_token)) {
|
||
cachedRefreshToken = RefreshTokenEntity.createRefreshTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.refresh_token || Constants.EMPTY_STRING, this.clientId, serverTokenResponse.foci, oboAssertion);
|
||
}
|
||
// appMetadata
|
||
var cachedAppMetadata = null;
|
||
if (!StringUtils.isEmpty(serverTokenResponse.foci)) {
|
||
cachedAppMetadata = AppMetadataEntity.createAppMetadataEntity(this.clientId, env, serverTokenResponse.foci);
|
||
}
|
||
return new CacheRecord(cachedAccount, cachedIdToken, cachedAccessToken, cachedRefreshToken, cachedAppMetadata);
|
||
};
|
||
/**
|
||
* Generate Account
|
||
* @param serverTokenResponse
|
||
* @param idToken
|
||
* @param authority
|
||
*/
|
||
ResponseHandler.prototype.generateAccountEntity = function (serverTokenResponse, idToken, authority, oboAssertion, authCodePayload) {
|
||
var authorityType = authority.authorityType;
|
||
var cloudGraphHostName = authCodePayload ? authCodePayload.cloud_graph_host_name : "";
|
||
var msGraphhost = authCodePayload ? authCodePayload.msgraph_host : "";
|
||
// ADFS does not require client_info in the response
|
||
if (authorityType === AuthorityType.Adfs) {
|
||
this.logger.verbose("Authority type is ADFS, creating ADFS account");
|
||
return AccountEntity.createGenericAccount(authority, this.homeAccountIdentifier, idToken, oboAssertion, cloudGraphHostName, msGraphhost);
|
||
}
|
||
// This fallback applies to B2C as well as they fall under an AAD account type.
|
||
if (StringUtils.isEmpty(serverTokenResponse.client_info) && authority.protocolMode === "AAD") {
|
||
throw ClientAuthError.createClientInfoEmptyError();
|
||
}
|
||
return serverTokenResponse.client_info ?
|
||
AccountEntity.createAccount(serverTokenResponse.client_info, this.homeAccountIdentifier, authority, idToken, oboAssertion, cloudGraphHostName, msGraphhost) :
|
||
AccountEntity.createGenericAccount(authority, this.homeAccountIdentifier, idToken, oboAssertion, cloudGraphHostName, msGraphhost);
|
||
};
|
||
/**
|
||
* Creates an @AuthenticationResult from @CacheRecord , @IdToken , and a boolean that states whether or not the result is from cache.
|
||
*
|
||
* Optionally takes a state string that is set as-is in the response.
|
||
*
|
||
* @param cacheRecord
|
||
* @param idTokenObj
|
||
* @param fromTokenCache
|
||
* @param stateString
|
||
*/
|
||
ResponseHandler.generateAuthenticationResult = function (cryptoObj, authority, cacheRecord, fromTokenCache, idTokenObj, requestState, resourceRequestMethod, resourceRequestUri) {
|
||
var _a, _b, _c;
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var accessToken, responseScopes, expiresOn, extExpiresOn, familyId, popTokenGenerator, uid, tid;
|
||
return __generator(this, function (_d) {
|
||
switch (_d.label) {
|
||
case 0:
|
||
accessToken = "";
|
||
responseScopes = [];
|
||
expiresOn = null;
|
||
familyId = Constants.EMPTY_STRING;
|
||
if (!cacheRecord.accessToken) return [3 /*break*/, 4];
|
||
if (!(cacheRecord.accessToken.tokenType === AuthenticationScheme.POP)) return [3 /*break*/, 2];
|
||
popTokenGenerator = new PopTokenGenerator(cryptoObj);
|
||
if (!resourceRequestMethod || !resourceRequestUri) {
|
||
throw ClientConfigurationError.createResourceRequestParametersRequiredError();
|
||
}
|
||
return [4 /*yield*/, popTokenGenerator.signPopToken(cacheRecord.accessToken.secret, resourceRequestMethod, resourceRequestUri)];
|
||
case 1:
|
||
accessToken = _d.sent();
|
||
return [3 /*break*/, 3];
|
||
case 2:
|
||
accessToken = cacheRecord.accessToken.secret;
|
||
_d.label = 3;
|
||
case 3:
|
||
responseScopes = ScopeSet.fromString(cacheRecord.accessToken.target).asArray();
|
||
expiresOn = new Date(Number(cacheRecord.accessToken.expiresOn) * 1000);
|
||
extExpiresOn = new Date(Number(cacheRecord.accessToken.extendedExpiresOn) * 1000);
|
||
_d.label = 4;
|
||
case 4:
|
||
if (cacheRecord.appMetadata) {
|
||
familyId = cacheRecord.appMetadata.familyId === THE_FAMILY_ID ? THE_FAMILY_ID : Constants.EMPTY_STRING;
|
||
}
|
||
uid = (idTokenObj === null || idTokenObj === void 0 ? void 0 : idTokenObj.claims.oid) || (idTokenObj === null || idTokenObj === void 0 ? void 0 : idTokenObj.claims.sub) || Constants.EMPTY_STRING;
|
||
tid = (idTokenObj === null || idTokenObj === void 0 ? void 0 : idTokenObj.claims.tid) || Constants.EMPTY_STRING;
|
||
return [2 /*return*/, {
|
||
authority: authority.canonicalAuthority,
|
||
uniqueId: uid,
|
||
tenantId: tid,
|
||
scopes: responseScopes,
|
||
account: cacheRecord.account ? cacheRecord.account.getAccountInfo() : null,
|
||
idToken: idTokenObj ? idTokenObj.rawToken : Constants.EMPTY_STRING,
|
||
idTokenClaims: idTokenObj ? idTokenObj.claims : {},
|
||
accessToken: accessToken,
|
||
fromCache: fromTokenCache,
|
||
expiresOn: expiresOn,
|
||
extExpiresOn: extExpiresOn,
|
||
familyId: familyId,
|
||
tokenType: ((_a = cacheRecord.accessToken) === null || _a === void 0 ? void 0 : _a.tokenType) || Constants.EMPTY_STRING,
|
||
state: requestState ? requestState.userRequestState : Constants.EMPTY_STRING,
|
||
cloudGraphHostName: ((_b = cacheRecord.account) === null || _b === void 0 ? void 0 : _b.cloudGraphHostName) || Constants.EMPTY_STRING,
|
||
msGraphHost: ((_c = cacheRecord.account) === null || _c === void 0 ? void 0 : _c.msGraphHost) || Constants.EMPTY_STRING
|
||
}];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
return ResponseHandler;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* Oauth2.0 Authorization Code client
|
||
*/
|
||
var AuthorizationCodeClient = /** @class */ (function (_super) {
|
||
__extends(AuthorizationCodeClient, _super);
|
||
function AuthorizationCodeClient(configuration) {
|
||
return _super.call(this, configuration) || this;
|
||
}
|
||
/**
|
||
* Creates the URL of the authorization request letting the user input credentials and consent to the
|
||
* application. The URL target the /authorize endpoint of the authority configured in the
|
||
* application object.
|
||
*
|
||
* Once the user inputs their credentials and consents, the authority will send a response to the redirect URI
|
||
* sent in the request and should contain an authorization code, which can then be used to acquire tokens via
|
||
* acquireToken(AuthorizationCodeRequest)
|
||
* @param request
|
||
*/
|
||
AuthorizationCodeClient.prototype.getAuthCodeUrl = function (request) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var queryString;
|
||
return __generator(this, function (_a) {
|
||
queryString = this.createAuthCodeUrlQueryString(request);
|
||
return [2 /*return*/, this.authority.authorizationEndpoint + "?" + queryString];
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* API to acquire a token in exchange of 'authorization_code` acquired by the user in the first leg of the
|
||
* authorization_code_grant
|
||
* @param request
|
||
*/
|
||
AuthorizationCodeClient.prototype.acquireToken = function (request, authCodePayload) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var reqTimestamp, response, responseHandler;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
this.logger.info("in acquireToken call");
|
||
if (!request || StringUtils.isEmpty(request.code)) {
|
||
throw ClientAuthError.createTokenRequestCannotBeMadeError();
|
||
}
|
||
reqTimestamp = TimeUtils.nowSeconds();
|
||
return [4 /*yield*/, this.executeTokenRequest(this.authority, request)];
|
||
case 1:
|
||
response = _a.sent();
|
||
responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin);
|
||
// Validate response. This function throws a server error if an error is returned by the server.
|
||
responseHandler.validateTokenResponse(response.body);
|
||
return [4 /*yield*/, responseHandler.handleServerTokenResponse(response.body, this.authority, reqTimestamp, request.resourceRequestMethod, request.resourceRequestUri, authCodePayload)];
|
||
case 2: return [2 /*return*/, _a.sent()];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Handles the hash fragment response from public client code request. Returns a code response used by
|
||
* the client to exchange for a token in acquireToken.
|
||
* @param hashFragment
|
||
*/
|
||
AuthorizationCodeClient.prototype.handleFragmentResponse = function (hashFragment, cachedState) {
|
||
// Handle responses.
|
||
var responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, null, null);
|
||
// Deserialize hash fragment response parameters.
|
||
var hashUrlString = new UrlString(hashFragment);
|
||
// Deserialize hash fragment response parameters.
|
||
var serverParams = UrlString.getDeserializedHash(hashUrlString.getHash());
|
||
// Get code response
|
||
responseHandler.validateServerAuthorizationCodeResponse(serverParams, cachedState, this.cryptoUtils);
|
||
// throw when there is no auth code in the response
|
||
if (!serverParams.code) {
|
||
throw ClientAuthError.createNoAuthCodeInServerResponseError();
|
||
}
|
||
return __assign(__assign({}, serverParams), {
|
||
// Code param is optional in ServerAuthorizationCodeResponse but required in AuthorizationCodePaylod
|
||
code: serverParams.code });
|
||
};
|
||
/**
|
||
* Use to log out the current user, and redirect the user to the postLogoutRedirectUri.
|
||
* Default behaviour is to redirect the user to `window.location.href`.
|
||
* @param authorityUri
|
||
*/
|
||
AuthorizationCodeClient.prototype.getLogoutUri = function (logoutRequest) {
|
||
// Throw error if logoutRequest is null/undefined
|
||
if (!logoutRequest) {
|
||
throw ClientConfigurationError.createEmptyLogoutRequestError();
|
||
}
|
||
if (logoutRequest.account) {
|
||
// Clear given account.
|
||
this.cacheManager.removeAccount(AccountEntity.generateAccountCacheKey(logoutRequest.account));
|
||
}
|
||
else {
|
||
// Clear all accounts and tokens
|
||
this.cacheManager.clear();
|
||
}
|
||
var queryString = this.createLogoutUrlQueryString(logoutRequest);
|
||
// Construct logout URI.
|
||
return StringUtils.isEmpty(queryString) ? this.authority.endSessionEndpoint : this.authority.endSessionEndpoint + "?" + queryString;
|
||
};
|
||
/**
|
||
* Executes POST request to token endpoint
|
||
* @param authority
|
||
* @param request
|
||
*/
|
||
AuthorizationCodeClient.prototype.executeTokenRequest = function (authority, request) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var thumbprint, requestBody, headers;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
thumbprint = {
|
||
clientId: this.config.authOptions.clientId,
|
||
authority: authority.canonicalAuthority,
|
||
scopes: request.scopes
|
||
};
|
||
return [4 /*yield*/, this.createTokenRequestBody(request)];
|
||
case 1:
|
||
requestBody = _a.sent();
|
||
headers = this.createDefaultTokenRequestHeaders();
|
||
return [2 /*return*/, this.executePostToTokenEndpoint(authority.tokenEndpoint, requestBody, headers, thumbprint)];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Generates a map for all the params to be sent to the service
|
||
* @param request
|
||
*/
|
||
AuthorizationCodeClient.prototype.createTokenRequestBody = function (request) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var parameterBuilder, clientAssertion, popTokenGenerator, cnfString, correlationId;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
parameterBuilder = new RequestParameterBuilder();
|
||
parameterBuilder.addClientId(this.config.authOptions.clientId);
|
||
// validate the redirectUri (to be a non null value)
|
||
parameterBuilder.addRedirectUri(request.redirectUri);
|
||
// Add scope array, parameter builder will add default scopes and dedupe
|
||
parameterBuilder.addScopes(request.scopes);
|
||
// add code: user set, not validated
|
||
parameterBuilder.addAuthorizationCode(request.code);
|
||
// add code_verifier if passed
|
||
if (request.codeVerifier) {
|
||
parameterBuilder.addCodeVerifier(request.codeVerifier);
|
||
}
|
||
if (this.config.clientCredentials.clientSecret) {
|
||
parameterBuilder.addClientSecret(this.config.clientCredentials.clientSecret);
|
||
}
|
||
if (this.config.clientCredentials.clientAssertion) {
|
||
clientAssertion = this.config.clientCredentials.clientAssertion;
|
||
parameterBuilder.addClientAssertion(clientAssertion.assertion);
|
||
parameterBuilder.addClientAssertionType(clientAssertion.assertionType);
|
||
}
|
||
parameterBuilder.addGrantType(GrantType.AUTHORIZATION_CODE_GRANT);
|
||
parameterBuilder.addClientInfo();
|
||
if (!(request.authenticationScheme === AuthenticationScheme.POP && !!request.resourceRequestMethod && !!request.resourceRequestUri)) return [3 /*break*/, 2];
|
||
popTokenGenerator = new PopTokenGenerator(this.cryptoUtils);
|
||
return [4 /*yield*/, popTokenGenerator.generateCnf(request.resourceRequestMethod, request.resourceRequestUri)];
|
||
case 1:
|
||
cnfString = _a.sent();
|
||
parameterBuilder.addPopToken(cnfString);
|
||
_a.label = 2;
|
||
case 2:
|
||
correlationId = request.correlationId || this.config.cryptoInterface.createNewGuid();
|
||
parameterBuilder.addCorrelationId(correlationId);
|
||
if (!StringUtils.isEmpty(request.claims) || this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0) {
|
||
parameterBuilder.addClaims(request.claims, this.config.authOptions.clientCapabilities);
|
||
}
|
||
return [2 /*return*/, parameterBuilder.createQueryString()];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* This API validates the `AuthorizationCodeUrlRequest` and creates a URL
|
||
* @param request
|
||
*/
|
||
AuthorizationCodeClient.prototype.createAuthCodeUrlQueryString = function (request) {
|
||
var parameterBuilder = new RequestParameterBuilder();
|
||
parameterBuilder.addClientId(this.config.authOptions.clientId);
|
||
var requestScopes = __spreadArrays(request.scopes || [], request.extraScopesToConsent || []);
|
||
parameterBuilder.addScopes(requestScopes);
|
||
// validate the redirectUri (to be a non null value)
|
||
parameterBuilder.addRedirectUri(request.redirectUri);
|
||
// generate the correlationId if not set by the user and add
|
||
var correlationId = request.correlationId || this.config.cryptoInterface.createNewGuid();
|
||
parameterBuilder.addCorrelationId(correlationId);
|
||
// add response_mode. If not passed in it defaults to query.
|
||
parameterBuilder.addResponseMode(request.responseMode);
|
||
// add response_type = code
|
||
parameterBuilder.addResponseTypeCode();
|
||
// add library info parameters
|
||
parameterBuilder.addLibraryInfo(this.config.libraryInfo);
|
||
// add client_info=1
|
||
parameterBuilder.addClientInfo();
|
||
if (request.codeChallenge && request.codeChallengeMethod) {
|
||
parameterBuilder.addCodeChallengeParams(request.codeChallenge, request.codeChallengeMethod);
|
||
}
|
||
if (request.prompt) {
|
||
parameterBuilder.addPrompt(request.prompt);
|
||
}
|
||
if (request.domainHint) {
|
||
parameterBuilder.addDomainHint(request.domainHint);
|
||
}
|
||
// Add sid or loginHint with preference for sid -> loginHint -> username of AccountInfo object
|
||
if (request.sid) {
|
||
parameterBuilder.addSid(request.sid);
|
||
}
|
||
else if (request.loginHint) {
|
||
parameterBuilder.addLoginHint(request.loginHint);
|
||
}
|
||
else if (request.account && request.account.username) {
|
||
parameterBuilder.addLoginHint(request.account.username);
|
||
}
|
||
if (request.nonce) {
|
||
parameterBuilder.addNonce(request.nonce);
|
||
}
|
||
if (request.state) {
|
||
parameterBuilder.addState(request.state);
|
||
}
|
||
if (!StringUtils.isEmpty(request.claims) || this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0) {
|
||
parameterBuilder.addClaims(request.claims, this.config.authOptions.clientCapabilities);
|
||
}
|
||
if (request.extraQueryParameters) {
|
||
parameterBuilder.addExtraQueryParameters(request.extraQueryParameters);
|
||
}
|
||
return parameterBuilder.createQueryString();
|
||
};
|
||
/**
|
||
* This API validates the `EndSessionRequest` and creates a URL
|
||
* @param request
|
||
*/
|
||
AuthorizationCodeClient.prototype.createLogoutUrlQueryString = function (request) {
|
||
var parameterBuilder = new RequestParameterBuilder();
|
||
if (request.postLogoutRedirectUri) {
|
||
parameterBuilder.addPostLogoutRedirectUri(request.postLogoutRedirectUri);
|
||
}
|
||
if (request.correlationId) {
|
||
parameterBuilder.addCorrelationId(request.correlationId);
|
||
}
|
||
if (request.idTokenHint) {
|
||
parameterBuilder.addIdTokenHint(request.idTokenHint);
|
||
}
|
||
return parameterBuilder.createQueryString();
|
||
};
|
||
return AuthorizationCodeClient;
|
||
}(BaseClient));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* OAuth2.0 Device code client
|
||
*/
|
||
var DeviceCodeClient = /** @class */ (function (_super) {
|
||
__extends(DeviceCodeClient, _super);
|
||
function DeviceCodeClient(configuration) {
|
||
return _super.call(this, configuration) || this;
|
||
}
|
||
/**
|
||
* Gets device code from device code endpoint, calls back to with device code response, and
|
||
* polls token endpoint to exchange device code for tokens
|
||
* @param request
|
||
*/
|
||
DeviceCodeClient.prototype.acquireToken = function (request) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var deviceCodeResponse, reqTimestamp, response, responseHandler;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0: return [4 /*yield*/, this.getDeviceCode(request)];
|
||
case 1:
|
||
deviceCodeResponse = _a.sent();
|
||
request.deviceCodeCallback(deviceCodeResponse);
|
||
reqTimestamp = TimeUtils.nowSeconds();
|
||
return [4 /*yield*/, this.acquireTokenWithDeviceCode(request, deviceCodeResponse)];
|
||
case 2:
|
||
response = _a.sent();
|
||
responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin);
|
||
// Validate response. This function throws a server error if an error is returned by the server.
|
||
responseHandler.validateTokenResponse(response);
|
||
return [4 /*yield*/, responseHandler.handleServerTokenResponse(response, this.authority, reqTimestamp, request.resourceRequestMethod, request.resourceRequestUri)];
|
||
case 3: return [2 /*return*/, _a.sent()];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Creates device code request and executes http GET
|
||
* @param request
|
||
*/
|
||
DeviceCodeClient.prototype.getDeviceCode = function (request) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var queryString, headers, thumbprint;
|
||
return __generator(this, function (_a) {
|
||
queryString = this.createQueryString(request);
|
||
headers = this.createDefaultTokenRequestHeaders();
|
||
thumbprint = {
|
||
clientId: this.config.authOptions.clientId,
|
||
authority: request.authority,
|
||
scopes: request.scopes
|
||
};
|
||
return [2 /*return*/, this.executePostRequestToDeviceCodeEndpoint(this.authority.deviceCodeEndpoint, queryString, headers, thumbprint)];
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Executes POST request to device code endpoint
|
||
* @param deviceCodeEndpoint
|
||
* @param queryString
|
||
* @param headers
|
||
*/
|
||
DeviceCodeClient.prototype.executePostRequestToDeviceCodeEndpoint = function (deviceCodeEndpoint, queryString, headers, thumbprint) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var _a, userCode, deviceCode, verificationUri, expiresIn, interval, message;
|
||
return __generator(this, function (_b) {
|
||
switch (_b.label) {
|
||
case 0: return [4 /*yield*/, this.networkManager.sendPostRequest(thumbprint, deviceCodeEndpoint, {
|
||
body: queryString,
|
||
headers: headers
|
||
})];
|
||
case 1:
|
||
_a = (_b.sent()).body, userCode = _a.user_code, deviceCode = _a.device_code, verificationUri = _a.verification_uri, expiresIn = _a.expires_in, interval = _a.interval, message = _a.message;
|
||
return [2 /*return*/, {
|
||
userCode: userCode,
|
||
deviceCode: deviceCode,
|
||
verificationUri: verificationUri,
|
||
expiresIn: expiresIn,
|
||
interval: interval,
|
||
message: message
|
||
}];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Create device code endpoint query parameters and returns string
|
||
*/
|
||
DeviceCodeClient.prototype.createQueryString = function (request) {
|
||
var parameterBuilder = new RequestParameterBuilder();
|
||
parameterBuilder.addScopes(request.scopes);
|
||
parameterBuilder.addClientId(this.config.authOptions.clientId);
|
||
if (!StringUtils.isEmpty(request.claims) || this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0) {
|
||
parameterBuilder.addClaims(request.claims, this.config.authOptions.clientCapabilities);
|
||
}
|
||
return parameterBuilder.createQueryString();
|
||
};
|
||
/**
|
||
* Creates token request with device code response and polls token endpoint at interval set by the device code
|
||
* response
|
||
* @param request
|
||
* @param deviceCodeResponse
|
||
*/
|
||
DeviceCodeClient.prototype.acquireTokenWithDeviceCode = function (request, deviceCodeResponse) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var requestBody, headers, userSpecifiedTimeout, deviceCodeExpirationTime, pollingIntervalMilli;
|
||
var _this = this;
|
||
return __generator(this, function (_a) {
|
||
requestBody = this.createTokenRequestBody(request, deviceCodeResponse);
|
||
headers = this.createDefaultTokenRequestHeaders();
|
||
userSpecifiedTimeout = request.timeout ? TimeUtils.nowSeconds() + request.timeout : undefined;
|
||
deviceCodeExpirationTime = TimeUtils.nowSeconds() + deviceCodeResponse.expiresIn;
|
||
pollingIntervalMilli = deviceCodeResponse.interval * 1000;
|
||
/*
|
||
* Poll token endpoint while (device code is not expired AND operation has not been cancelled by
|
||
* setting CancellationToken.cancel = true). POST request is sent at interval set by pollingIntervalMilli
|
||
*/
|
||
return [2 /*return*/, new Promise(function (resolve, reject) {
|
||
var intervalId = setInterval(function () { return __awaiter(_this, void 0, void 0, function () {
|
||
var thumbprint, response, error_1;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
_a.trys.push([0, 6, , 7]);
|
||
if (!request.cancel) return [3 /*break*/, 1];
|
||
this.logger.error("Token request cancelled by setting DeviceCodeRequest.cancel = true");
|
||
clearInterval(intervalId);
|
||
reject(ClientAuthError.createDeviceCodeCancelledError());
|
||
return [3 /*break*/, 5];
|
||
case 1:
|
||
if (!(userSpecifiedTimeout && userSpecifiedTimeout < deviceCodeExpirationTime && TimeUtils.nowSeconds() > userSpecifiedTimeout)) return [3 /*break*/, 2];
|
||
this.logger.error("User defined timeout for device code polling reached. The timeout was set for " + userSpecifiedTimeout);
|
||
clearInterval(intervalId);
|
||
reject(ClientAuthError.createUserTimeoutReachedError());
|
||
return [3 /*break*/, 5];
|
||
case 2:
|
||
if (!(TimeUtils.nowSeconds() > deviceCodeExpirationTime)) return [3 /*break*/, 3];
|
||
if (userSpecifiedTimeout) {
|
||
this.logger.verbose("User specified timeout ignored as the device code has expired before the timeout elapsed. The user specified timeout was set for " + userSpecifiedTimeout);
|
||
}
|
||
this.logger.error("Device code expired. Expiration time of device code was " + deviceCodeExpirationTime);
|
||
clearInterval(intervalId);
|
||
reject(ClientAuthError.createDeviceCodeExpiredError());
|
||
return [3 /*break*/, 5];
|
||
case 3:
|
||
thumbprint = {
|
||
clientId: this.config.authOptions.clientId,
|
||
authority: request.authority,
|
||
scopes: request.scopes
|
||
};
|
||
return [4 /*yield*/, this.executePostToTokenEndpoint(this.authority.tokenEndpoint, requestBody, headers, thumbprint)];
|
||
case 4:
|
||
response = _a.sent();
|
||
if (response.body && response.body.error === Constants.AUTHORIZATION_PENDING) {
|
||
// user authorization is pending. Sleep for polling interval and try again
|
||
this.logger.info(response.body.error_description || "no_error_description");
|
||
}
|
||
else {
|
||
clearInterval(intervalId);
|
||
resolve(response.body);
|
||
}
|
||
_a.label = 5;
|
||
case 5: return [3 /*break*/, 7];
|
||
case 6:
|
||
error_1 = _a.sent();
|
||
clearInterval(intervalId);
|
||
reject(error_1);
|
||
return [3 /*break*/, 7];
|
||
case 7: return [2 /*return*/];
|
||
}
|
||
});
|
||
}); }, pollingIntervalMilli);
|
||
})];
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Creates query parameters and converts to string.
|
||
* @param request
|
||
* @param deviceCodeResponse
|
||
*/
|
||
DeviceCodeClient.prototype.createTokenRequestBody = function (request, deviceCodeResponse) {
|
||
var requestParameters = new RequestParameterBuilder();
|
||
requestParameters.addScopes(request.scopes);
|
||
requestParameters.addClientId(this.config.authOptions.clientId);
|
||
requestParameters.addGrantType(GrantType.DEVICE_CODE_GRANT);
|
||
requestParameters.addDeviceCode(deviceCodeResponse.deviceCode);
|
||
var correlationId = request.correlationId || this.config.cryptoInterface.createNewGuid();
|
||
requestParameters.addCorrelationId(correlationId);
|
||
requestParameters.addClientInfo();
|
||
if (!StringUtils.isEmpty(request.claims) || this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0) {
|
||
requestParameters.addClaims(request.claims, this.config.authOptions.clientCapabilities);
|
||
}
|
||
return requestParameters.createQueryString();
|
||
};
|
||
return DeviceCodeClient;
|
||
}(BaseClient));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* OAuth2.0 refresh token client
|
||
*/
|
||
var RefreshTokenClient = /** @class */ (function (_super) {
|
||
__extends(RefreshTokenClient, _super);
|
||
function RefreshTokenClient(configuration) {
|
||
return _super.call(this, configuration) || this;
|
||
}
|
||
RefreshTokenClient.prototype.acquireToken = function (request) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var reqTimestamp, response, responseHandler;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
reqTimestamp = TimeUtils.nowSeconds();
|
||
return [4 /*yield*/, this.executeTokenRequest(request, this.authority)];
|
||
case 1:
|
||
response = _a.sent();
|
||
responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin);
|
||
responseHandler.validateTokenResponse(response.body);
|
||
return [2 /*return*/, responseHandler.handleServerTokenResponse(response.body, this.authority, reqTimestamp, request.resourceRequestMethod, request.resourceRequestUri, undefined, [], undefined, true)];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Gets cached refresh token and attaches to request, then calls acquireToken API
|
||
* @param request
|
||
*/
|
||
RefreshTokenClient.prototype.acquireTokenByRefreshToken = function (request) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var isFOCI, noFamilyRTInCache, clientMismatchErrorWithFamilyRT;
|
||
return __generator(this, function (_a) {
|
||
// Cannot renew token if no request object is given.
|
||
if (!request) {
|
||
throw ClientConfigurationError.createEmptyTokenRequestError();
|
||
}
|
||
// We currently do not support silent flow for account === null use cases; This will be revisited for confidential flow usecases
|
||
if (!request.account) {
|
||
throw ClientAuthError.createNoAccountInSilentRequestError();
|
||
}
|
||
isFOCI = this.cacheManager.isAppMetadataFOCI(request.account.environment, this.config.authOptions.clientId);
|
||
// if the app is part of the family, retrive a Family refresh token if present and make a refreshTokenRequest
|
||
if (isFOCI) {
|
||
try {
|
||
return [2 /*return*/, this.acquireTokenWithCachedRefreshToken(request, true)];
|
||
}
|
||
catch (e) {
|
||
noFamilyRTInCache = e instanceof ClientAuthError && e.errorCode === ClientAuthErrorMessage.noTokensFoundError.code;
|
||
clientMismatchErrorWithFamilyRT = e instanceof ServerError && e.errorCode === Errors.INVALID_GRANT_ERROR && e.subError === Errors.CLIENT_MISMATCH_ERROR;
|
||
// if family Refresh Token (FRT) cache acquisition fails or if client_mismatch error is seen with FRT, reattempt with application Refresh Token (ART)
|
||
if (noFamilyRTInCache || clientMismatchErrorWithFamilyRT) {
|
||
return [2 /*return*/, this.acquireTokenWithCachedRefreshToken(request, false)];
|
||
// throw in all other cases
|
||
}
|
||
else {
|
||
throw e;
|
||
}
|
||
}
|
||
}
|
||
// fall back to application refresh token acquisition
|
||
return [2 /*return*/, this.acquireTokenWithCachedRefreshToken(request, false)];
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* makes a network call to acquire tokens by exchanging RefreshToken available in userCache; throws if refresh token is not cached
|
||
* @param request
|
||
*/
|
||
RefreshTokenClient.prototype.acquireTokenWithCachedRefreshToken = function (request, foci) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var refreshToken, refreshTokenRequest;
|
||
return __generator(this, function (_a) {
|
||
refreshToken = this.cacheManager.readRefreshTokenFromCache(this.config.authOptions.clientId, request.account, foci);
|
||
// no refresh Token
|
||
if (!refreshToken) {
|
||
throw ClientAuthError.createNoTokensFoundError();
|
||
}
|
||
refreshTokenRequest = __assign(__assign({}, request), { refreshToken: refreshToken.secret, authenticationScheme: AuthenticationScheme.BEARER });
|
||
return [2 /*return*/, this.acquireToken(refreshTokenRequest)];
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Constructs the network message and makes a NW call to the underlying secure token service
|
||
* @param request
|
||
* @param authority
|
||
*/
|
||
RefreshTokenClient.prototype.executeTokenRequest = function (request, authority) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var requestBody, headers, thumbprint;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0: return [4 /*yield*/, this.createTokenRequestBody(request)];
|
||
case 1:
|
||
requestBody = _a.sent();
|
||
headers = this.createDefaultTokenRequestHeaders();
|
||
thumbprint = {
|
||
clientId: this.config.authOptions.clientId,
|
||
authority: authority.canonicalAuthority,
|
||
scopes: request.scopes
|
||
};
|
||
return [2 /*return*/, this.executePostToTokenEndpoint(authority.tokenEndpoint, requestBody, headers, thumbprint)];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Helper function to create the token request body
|
||
* @param request
|
||
*/
|
||
RefreshTokenClient.prototype.createTokenRequestBody = function (request) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var parameterBuilder, correlationId, clientAssertion, popTokenGenerator, _a, _b;
|
||
return __generator(this, function (_c) {
|
||
switch (_c.label) {
|
||
case 0:
|
||
parameterBuilder = new RequestParameterBuilder();
|
||
parameterBuilder.addClientId(this.config.authOptions.clientId);
|
||
parameterBuilder.addScopes(request.scopes);
|
||
parameterBuilder.addGrantType(GrantType.REFRESH_TOKEN_GRANT);
|
||
parameterBuilder.addClientInfo();
|
||
correlationId = request.correlationId || this.config.cryptoInterface.createNewGuid();
|
||
parameterBuilder.addCorrelationId(correlationId);
|
||
parameterBuilder.addRefreshToken(request.refreshToken);
|
||
if (this.config.clientCredentials.clientSecret) {
|
||
parameterBuilder.addClientSecret(this.config.clientCredentials.clientSecret);
|
||
}
|
||
if (this.config.clientCredentials.clientAssertion) {
|
||
clientAssertion = this.config.clientCredentials.clientAssertion;
|
||
parameterBuilder.addClientAssertion(clientAssertion.assertion);
|
||
parameterBuilder.addClientAssertionType(clientAssertion.assertionType);
|
||
}
|
||
if (!(request.authenticationScheme === AuthenticationScheme.POP)) return [3 /*break*/, 2];
|
||
popTokenGenerator = new PopTokenGenerator(this.cryptoUtils);
|
||
if (!request.resourceRequestMethod || !request.resourceRequestUri) {
|
||
throw ClientConfigurationError.createResourceRequestParametersRequiredError();
|
||
}
|
||
_b = (_a = parameterBuilder).addPopToken;
|
||
return [4 /*yield*/, popTokenGenerator.generateCnf(request.resourceRequestMethod, request.resourceRequestUri)];
|
||
case 1:
|
||
_b.apply(_a, [_c.sent()]);
|
||
_c.label = 2;
|
||
case 2:
|
||
if (!StringUtils.isEmpty(request.claims) || this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0) {
|
||
parameterBuilder.addClaims(request.claims, this.config.authOptions.clientCapabilities);
|
||
}
|
||
return [2 /*return*/, parameterBuilder.createQueryString()];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
return RefreshTokenClient;
|
||
}(BaseClient));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* OAuth2.0 client credential grant
|
||
*/
|
||
var ClientCredentialClient = /** @class */ (function (_super) {
|
||
__extends(ClientCredentialClient, _super);
|
||
function ClientCredentialClient(configuration) {
|
||
return _super.call(this, configuration) || this;
|
||
}
|
||
/**
|
||
* Public API to acquire a token with ClientCredential Flow for Confidential clients
|
||
* @param request
|
||
*/
|
||
ClientCredentialClient.prototype.acquireToken = function (request) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var cachedAuthenticationResult;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
this.scopeSet = new ScopeSet(request.scopes || []);
|
||
if (!request.skipCache) return [3 /*break*/, 2];
|
||
return [4 /*yield*/, this.executeTokenRequest(request, this.authority)];
|
||
case 1: return [2 /*return*/, _a.sent()];
|
||
case 2: return [4 /*yield*/, this.getCachedAuthenticationResult()];
|
||
case 3:
|
||
cachedAuthenticationResult = _a.sent();
|
||
if (!cachedAuthenticationResult) return [3 /*break*/, 4];
|
||
return [2 /*return*/, cachedAuthenticationResult];
|
||
case 4: return [4 /*yield*/, this.executeTokenRequest(request, this.authority)];
|
||
case 5: return [2 /*return*/, _a.sent()];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* looks up cache if the tokens are cached already
|
||
*/
|
||
ClientCredentialClient.prototype.getCachedAuthenticationResult = function () {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var cachedAccessToken;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
cachedAccessToken = this.readAccessTokenFromCache();
|
||
if (!cachedAccessToken ||
|
||
TimeUtils.isTokenExpired(cachedAccessToken.expiresOn, this.config.systemOptions.tokenRenewalOffsetSeconds)) {
|
||
return [2 /*return*/, null];
|
||
}
|
||
return [4 /*yield*/, ResponseHandler.generateAuthenticationResult(this.cryptoUtils, this.authority, {
|
||
account: null,
|
||
idToken: null,
|
||
accessToken: cachedAccessToken,
|
||
refreshToken: null,
|
||
appMetadata: null
|
||
}, true)];
|
||
case 1: return [2 /*return*/, _a.sent()];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Reads access token from the cache
|
||
* TODO: Move this call to cacheManager instead
|
||
*/
|
||
ClientCredentialClient.prototype.readAccessTokenFromCache = function () {
|
||
var accessTokenFilter = {
|
||
homeAccountId: "",
|
||
environment: this.authority.canonicalAuthorityUrlComponents.HostNameAndPort,
|
||
credentialType: CredentialType.ACCESS_TOKEN,
|
||
clientId: this.config.authOptions.clientId,
|
||
realm: this.authority.tenant,
|
||
target: this.scopeSet.printScopesLowerCase()
|
||
};
|
||
var credentialCache = this.cacheManager.getCredentialsFilteredBy(accessTokenFilter);
|
||
var accessTokens = Object.keys(credentialCache.accessTokens).map(function (key) { return credentialCache.accessTokens[key]; });
|
||
if (accessTokens.length < 1) {
|
||
return null;
|
||
}
|
||
else if (accessTokens.length > 1) {
|
||
throw ClientAuthError.createMultipleMatchingTokensInCacheError();
|
||
}
|
||
return accessTokens[0];
|
||
};
|
||
/**
|
||
* Makes a network call to request the token from the service
|
||
* @param request
|
||
* @param authority
|
||
*/
|
||
ClientCredentialClient.prototype.executeTokenRequest = function (request, authority) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var requestBody, headers, thumbprint, reqTimestamp, response, responseHandler, tokenResponse;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
requestBody = this.createTokenRequestBody(request);
|
||
headers = this.createDefaultTokenRequestHeaders();
|
||
thumbprint = {
|
||
clientId: this.config.authOptions.clientId,
|
||
authority: request.authority,
|
||
scopes: request.scopes
|
||
};
|
||
reqTimestamp = TimeUtils.nowSeconds();
|
||
return [4 /*yield*/, this.executePostToTokenEndpoint(authority.tokenEndpoint, requestBody, headers, thumbprint)];
|
||
case 1:
|
||
response = _a.sent();
|
||
responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin);
|
||
responseHandler.validateTokenResponse(response.body);
|
||
return [4 /*yield*/, responseHandler.handleServerTokenResponse(response.body, this.authority, reqTimestamp, request.resourceRequestMethod, request.resourceRequestUri, undefined, request.scopes)];
|
||
case 2:
|
||
tokenResponse = _a.sent();
|
||
return [2 /*return*/, tokenResponse];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* generate the request to the server in the acceptable format
|
||
* @param request
|
||
*/
|
||
ClientCredentialClient.prototype.createTokenRequestBody = function (request) {
|
||
var parameterBuilder = new RequestParameterBuilder();
|
||
parameterBuilder.addClientId(this.config.authOptions.clientId);
|
||
parameterBuilder.addScopes(request.scopes, false);
|
||
parameterBuilder.addGrantType(GrantType.CLIENT_CREDENTIALS_GRANT);
|
||
var correlationId = request.correlationId || this.config.cryptoInterface.createNewGuid();
|
||
parameterBuilder.addCorrelationId(correlationId);
|
||
if (this.config.clientCredentials.clientSecret) {
|
||
parameterBuilder.addClientSecret(this.config.clientCredentials.clientSecret);
|
||
}
|
||
if (this.config.clientCredentials.clientAssertion) {
|
||
var clientAssertion = this.config.clientCredentials.clientAssertion;
|
||
parameterBuilder.addClientAssertion(clientAssertion.assertion);
|
||
parameterBuilder.addClientAssertionType(clientAssertion.assertionType);
|
||
}
|
||
if (!StringUtils.isEmpty(request.claims) || this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0) {
|
||
parameterBuilder.addClaims(request.claims, this.config.authOptions.clientCapabilities);
|
||
}
|
||
return parameterBuilder.createQueryString();
|
||
};
|
||
return ClientCredentialClient;
|
||
}(BaseClient));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* On-Behalf-Of client
|
||
*/
|
||
var OnBehalfOfClient = /** @class */ (function (_super) {
|
||
__extends(OnBehalfOfClient, _super);
|
||
function OnBehalfOfClient(configuration) {
|
||
return _super.call(this, configuration) || this;
|
||
}
|
||
/**
|
||
* Public API to acquire tokens with on behalf of flow
|
||
* @param request
|
||
*/
|
||
OnBehalfOfClient.prototype.acquireToken = function (request) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var cachedAuthenticationResult;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
this.scopeSet = new ScopeSet(request.scopes || []);
|
||
if (!request.skipCache) return [3 /*break*/, 2];
|
||
return [4 /*yield*/, this.executeTokenRequest(request, this.authority)];
|
||
case 1: return [2 /*return*/, _a.sent()];
|
||
case 2: return [4 /*yield*/, this.getCachedAuthenticationResult(request)];
|
||
case 3:
|
||
cachedAuthenticationResult = _a.sent();
|
||
if (!cachedAuthenticationResult) return [3 /*break*/, 4];
|
||
return [2 /*return*/, cachedAuthenticationResult];
|
||
case 4: return [4 /*yield*/, this.executeTokenRequest(request, this.authority)];
|
||
case 5: return [2 /*return*/, _a.sent()];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* look up cache for tokens
|
||
* @param request
|
||
*/
|
||
OnBehalfOfClient.prototype.getCachedAuthenticationResult = function (request) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var cachedAccessToken, cachedIdToken, idTokenObject, cachedAccount, localAccountId, accountInfo;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
cachedAccessToken = this.readAccessTokenFromCache(request);
|
||
if (!cachedAccessToken ||
|
||
TimeUtils.isTokenExpired(cachedAccessToken.expiresOn, this.config.systemOptions.tokenRenewalOffsetSeconds)) {
|
||
return [2 /*return*/, null];
|
||
}
|
||
cachedIdToken = this.readIdTokenFromCache(request);
|
||
cachedAccount = null;
|
||
if (cachedIdToken) {
|
||
idTokenObject = new AuthToken(cachedIdToken.secret, this.config.cryptoInterface);
|
||
localAccountId = idTokenObject.claims.oid ? idTokenObject.claims.oid : idTokenObject.claims.sub;
|
||
accountInfo = {
|
||
homeAccountId: cachedIdToken.homeAccountId,
|
||
environment: cachedIdToken.environment,
|
||
tenantId: cachedIdToken.realm,
|
||
username: Constants.EMPTY_STRING,
|
||
localAccountId: localAccountId || ""
|
||
};
|
||
cachedAccount = this.readAccountFromCache(accountInfo);
|
||
}
|
||
return [4 /*yield*/, ResponseHandler.generateAuthenticationResult(this.cryptoUtils, this.authority, {
|
||
account: cachedAccount,
|
||
accessToken: cachedAccessToken,
|
||
idToken: cachedIdToken,
|
||
refreshToken: null,
|
||
appMetadata: null
|
||
}, true, idTokenObject)];
|
||
case 1: return [2 /*return*/, _a.sent()];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* read access token from cache TODO: CacheManager API should be used here
|
||
* @param request
|
||
*/
|
||
OnBehalfOfClient.prototype.readAccessTokenFromCache = function (request) {
|
||
var accessTokenFilter = {
|
||
environment: this.authority.canonicalAuthorityUrlComponents.HostNameAndPort,
|
||
credentialType: CredentialType.ACCESS_TOKEN,
|
||
clientId: this.config.authOptions.clientId,
|
||
realm: this.authority.tenant,
|
||
target: this.scopeSet.printScopesLowerCase(),
|
||
oboAssertion: request.oboAssertion
|
||
};
|
||
var credentialCache = this.cacheManager.getCredentialsFilteredBy(accessTokenFilter);
|
||
var accessTokens = Object.keys(credentialCache.accessTokens).map(function (key) { return credentialCache.accessTokens[key]; });
|
||
var numAccessTokens = accessTokens.length;
|
||
if (numAccessTokens < 1) {
|
||
return null;
|
||
}
|
||
else if (numAccessTokens > 1) {
|
||
throw ClientAuthError.createMultipleMatchingTokensInCacheError();
|
||
}
|
||
return accessTokens[0];
|
||
};
|
||
/**
|
||
* read idtoken from cache TODO: CacheManager API should be used here instead
|
||
* @param request
|
||
*/
|
||
OnBehalfOfClient.prototype.readIdTokenFromCache = function (request) {
|
||
var idTokenFilter = {
|
||
environment: this.authority.canonicalAuthorityUrlComponents.HostNameAndPort,
|
||
credentialType: CredentialType.ID_TOKEN,
|
||
clientId: this.config.authOptions.clientId,
|
||
realm: this.authority.tenant,
|
||
oboAssertion: request.oboAssertion
|
||
};
|
||
var credentialCache = this.cacheManager.getCredentialsFilteredBy(idTokenFilter);
|
||
var idTokens = Object.keys(credentialCache.idTokens).map(function (key) { return credentialCache.idTokens[key]; });
|
||
// When acquiring a token on behalf of an application, there might not be an id token in the cache
|
||
if (idTokens.length < 1) {
|
||
return null;
|
||
}
|
||
return idTokens[0];
|
||
};
|
||
/**
|
||
* read account from cache, TODO: CacheManager API should be used here instead
|
||
* @param account
|
||
*/
|
||
OnBehalfOfClient.prototype.readAccountFromCache = function (account) {
|
||
return this.cacheManager.readAccountFromCache(account);
|
||
};
|
||
/**
|
||
* Make a network call to the server requesting credentials
|
||
* @param request
|
||
* @param authority
|
||
*/
|
||
OnBehalfOfClient.prototype.executeTokenRequest = function (request, authority) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var requestBody, headers, thumbprint, reqTimestamp, response, responseHandler, tokenResponse;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
requestBody = this.createTokenRequestBody(request);
|
||
headers = this.createDefaultTokenRequestHeaders();
|
||
thumbprint = {
|
||
clientId: this.config.authOptions.clientId,
|
||
authority: request.authority,
|
||
scopes: request.scopes
|
||
};
|
||
reqTimestamp = TimeUtils.nowSeconds();
|
||
return [4 /*yield*/, this.executePostToTokenEndpoint(authority.tokenEndpoint, requestBody, headers, thumbprint)];
|
||
case 1:
|
||
response = _a.sent();
|
||
responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin);
|
||
responseHandler.validateTokenResponse(response.body);
|
||
return [4 /*yield*/, responseHandler.handleServerTokenResponse(response.body, this.authority, reqTimestamp, request.resourceRequestMethod, request.resourceRequestUri, undefined, request.scopes, request.oboAssertion)];
|
||
case 2:
|
||
tokenResponse = _a.sent();
|
||
return [2 /*return*/, tokenResponse];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* generate a server request in accepable format
|
||
* @param request
|
||
*/
|
||
OnBehalfOfClient.prototype.createTokenRequestBody = function (request) {
|
||
var parameterBuilder = new RequestParameterBuilder();
|
||
parameterBuilder.addClientId(this.config.authOptions.clientId);
|
||
parameterBuilder.addScopes(request.scopes);
|
||
parameterBuilder.addGrantType(GrantType.JWT_BEARER);
|
||
parameterBuilder.addClientInfo();
|
||
var correlationId = request.correlationId || this.config.cryptoInterface.createNewGuid();
|
||
parameterBuilder.addCorrelationId(correlationId);
|
||
parameterBuilder.addRequestTokenUse(AADServerParamKeys.ON_BEHALF_OF);
|
||
parameterBuilder.addOboAssertion(request.oboAssertion);
|
||
if (this.config.clientCredentials.clientSecret) {
|
||
parameterBuilder.addClientSecret(this.config.clientCredentials.clientSecret);
|
||
}
|
||
if (this.config.clientCredentials.clientAssertion) {
|
||
var clientAssertion = this.config.clientCredentials.clientAssertion;
|
||
parameterBuilder.addClientAssertion(clientAssertion.assertion);
|
||
parameterBuilder.addClientAssertionType(clientAssertion.assertionType);
|
||
}
|
||
return parameterBuilder.createQueryString();
|
||
};
|
||
return OnBehalfOfClient;
|
||
}(BaseClient));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
var SilentFlowClient = /** @class */ (function (_super) {
|
||
__extends(SilentFlowClient, _super);
|
||
function SilentFlowClient(configuration) {
|
||
return _super.call(this, configuration) || this;
|
||
}
|
||
/**
|
||
* Retrieves a token from cache if it is still valid, or uses the cached refresh token to renew
|
||
* the given token and returns the renewed token
|
||
* @param request
|
||
*/
|
||
SilentFlowClient.prototype.acquireToken = function (request) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var e_1, refreshTokenClient;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
_a.trys.push([0, 2, , 3]);
|
||
return [4 /*yield*/, this.acquireCachedToken(request)];
|
||
case 1: return [2 /*return*/, _a.sent()];
|
||
case 2:
|
||
e_1 = _a.sent();
|
||
if (e_1 instanceof ClientAuthError && e_1.errorCode === ClientAuthErrorMessage.tokenRefreshRequired.code) {
|
||
refreshTokenClient = new RefreshTokenClient(this.config);
|
||
return [2 /*return*/, refreshTokenClient.acquireTokenByRefreshToken(request)];
|
||
}
|
||
else {
|
||
throw e_1;
|
||
}
|
||
case 3: return [2 /*return*/];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Retrieves token from cache or throws an error if it must be refreshed.
|
||
* @param request
|
||
*/
|
||
SilentFlowClient.prototype.acquireCachedToken = function (request) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var requestScopes, environment, cacheRecord;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
// Cannot renew token if no request object is given.
|
||
if (!request) {
|
||
throw ClientConfigurationError.createEmptyTokenRequestError();
|
||
}
|
||
// We currently do not support silent flow for account === null use cases; This will be revisited for confidential flow usecases
|
||
if (!request.account) {
|
||
throw ClientAuthError.createNoAccountInSilentRequestError();
|
||
}
|
||
requestScopes = new ScopeSet(request.scopes || []);
|
||
environment = request.authority || this.authority.getPreferredCache();
|
||
cacheRecord = this.cacheManager.readCacheRecord(request.account, this.config.authOptions.clientId, requestScopes, environment);
|
||
if (!this.isRefreshRequired(request, cacheRecord.accessToken)) return [3 /*break*/, 1];
|
||
throw ClientAuthError.createRefreshRequiredError();
|
||
case 1:
|
||
if (this.config.serverTelemetryManager) {
|
||
this.config.serverTelemetryManager.incrementCacheHits();
|
||
}
|
||
return [4 /*yield*/, this.generateResultFromCacheRecord(cacheRecord, request.resourceRequestMethod, request.resourceRequestUri)];
|
||
case 2: return [2 /*return*/, _a.sent()];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Helper function to build response object from the CacheRecord
|
||
* @param cacheRecord
|
||
*/
|
||
SilentFlowClient.prototype.generateResultFromCacheRecord = function (cacheRecord, resourceRequestMethod, resourceRequestUri) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var idTokenObj;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
if (cacheRecord.idToken) {
|
||
idTokenObj = new AuthToken(cacheRecord.idToken.secret, this.config.cryptoInterface);
|
||
}
|
||
return [4 /*yield*/, ResponseHandler.generateAuthenticationResult(this.cryptoUtils, this.authority, cacheRecord, true, idTokenObj, undefined, resourceRequestMethod, resourceRequestUri)];
|
||
case 1: return [2 /*return*/, _a.sent()];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Given a request object and an accessTokenEntity determine if the accessToken needs to be refreshed
|
||
* @param request
|
||
* @param cachedAccessToken
|
||
*/
|
||
SilentFlowClient.prototype.isRefreshRequired = function (request, cachedAccessToken) {
|
||
if (request.forceRefresh || request.claims) {
|
||
// Must refresh due to request parameters
|
||
return true;
|
||
}
|
||
else if (!cachedAccessToken || TimeUtils.isTokenExpired(cachedAccessToken.expiresOn, this.config.systemOptions.tokenRenewalOffsetSeconds)) {
|
||
// Must refresh due to expired or non-existent access_token
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
return SilentFlowClient;
|
||
}(BaseClient));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* Oauth2.0 Password grant client
|
||
* Note: We are only supporting public clients for password grant and for purely testing purposes
|
||
*/
|
||
var UsernamePasswordClient = /** @class */ (function (_super) {
|
||
__extends(UsernamePasswordClient, _super);
|
||
function UsernamePasswordClient(configuration) {
|
||
return _super.call(this, configuration) || this;
|
||
}
|
||
/**
|
||
* API to acquire a token by passing the username and password to the service in exchage of credentials
|
||
* password_grant
|
||
* @param request
|
||
*/
|
||
UsernamePasswordClient.prototype.acquireToken = function (request) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var reqTimestamp, response, responseHandler, tokenResponse;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
this.logger.info("in acquireToken call");
|
||
reqTimestamp = TimeUtils.nowSeconds();
|
||
return [4 /*yield*/, this.executeTokenRequest(this.authority, request)];
|
||
case 1:
|
||
response = _a.sent();
|
||
responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin);
|
||
// Validate response. This function throws a server error if an error is returned by the server.
|
||
responseHandler.validateTokenResponse(response.body);
|
||
tokenResponse = responseHandler.handleServerTokenResponse(response.body, this.authority, reqTimestamp);
|
||
return [2 /*return*/, tokenResponse];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Executes POST request to token endpoint
|
||
* @param authority
|
||
* @param request
|
||
*/
|
||
UsernamePasswordClient.prototype.executeTokenRequest = function (authority, request) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var thumbprint, requestBody, headers;
|
||
return __generator(this, function (_a) {
|
||
thumbprint = {
|
||
clientId: this.config.authOptions.clientId,
|
||
authority: authority.canonicalAuthority,
|
||
scopes: request.scopes
|
||
};
|
||
requestBody = this.createTokenRequestBody(request);
|
||
headers = this.createDefaultTokenRequestHeaders();
|
||
return [2 /*return*/, this.executePostToTokenEndpoint(authority.tokenEndpoint, requestBody, headers, thumbprint)];
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Generates a map for all the params to be sent to the service
|
||
* @param request
|
||
*/
|
||
UsernamePasswordClient.prototype.createTokenRequestBody = function (request) {
|
||
var parameterBuilder = new RequestParameterBuilder();
|
||
parameterBuilder.addClientId(this.config.authOptions.clientId);
|
||
parameterBuilder.addUsername(request.username);
|
||
parameterBuilder.addPassword(request.password);
|
||
parameterBuilder.addScopes(request.scopes);
|
||
parameterBuilder.addGrantType(GrantType.RESOURCE_OWNER_PASSWORD_GRANT);
|
||
parameterBuilder.addClientInfo();
|
||
var correlationId = request.correlationId || this.config.cryptoInterface.createNewGuid();
|
||
parameterBuilder.addCorrelationId(correlationId);
|
||
if (!StringUtils.isEmpty(request.claims) || this.config.authOptions.clientCapabilities && this.config.authOptions.clientCapabilities.length > 0) {
|
||
parameterBuilder.addClaims(request.claims, this.config.authOptions.clientCapabilities);
|
||
}
|
||
return parameterBuilder.createQueryString();
|
||
};
|
||
return UsernamePasswordClient;
|
||
}(BaseClient));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
function isOpenIdConfigResponse(response) {
|
||
return (response.hasOwnProperty("authorization_endpoint") &&
|
||
response.hasOwnProperty("token_endpoint") &&
|
||
response.hasOwnProperty("end_session_endpoint") &&
|
||
response.hasOwnProperty("issuer"));
|
||
}
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* Protocol modes supported by MSAL.
|
||
*/
|
||
var ProtocolMode;
|
||
(function (ProtocolMode) {
|
||
ProtocolMode["AAD"] = "AAD";
|
||
ProtocolMode["OIDC"] = "OIDC";
|
||
})(ProtocolMode || (ProtocolMode = {}));
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
var AuthorityMetadataEntity = /** @class */ (function () {
|
||
function AuthorityMetadataEntity() {
|
||
this.expiresAt = TimeUtils.nowSeconds() + AUTHORITY_METADATA_CONSTANTS.REFRESH_TIME_SECONDS;
|
||
}
|
||
/**
|
||
* Update the entity with new aliases, preferred_cache and preferred_network values
|
||
* @param metadata
|
||
* @param fromNetwork
|
||
*/
|
||
AuthorityMetadataEntity.prototype.updateCloudDiscoveryMetadata = function (metadata, fromNetwork) {
|
||
this.aliases = metadata.aliases;
|
||
this.preferred_cache = metadata.preferred_cache;
|
||
this.preferred_network = metadata.preferred_network;
|
||
this.aliasesFromNetwork = fromNetwork;
|
||
};
|
||
/**
|
||
* Update the entity with new endpoints
|
||
* @param metadata
|
||
* @param fromNetwork
|
||
*/
|
||
AuthorityMetadataEntity.prototype.updateEndpointMetadata = function (metadata, fromNetwork) {
|
||
this.authorization_endpoint = metadata.authorization_endpoint;
|
||
this.token_endpoint = metadata.token_endpoint;
|
||
this.end_session_endpoint = metadata.end_session_endpoint;
|
||
this.issuer = metadata.issuer;
|
||
this.endpointsFromNetwork = fromNetwork;
|
||
};
|
||
/**
|
||
* Save the authority that was used to create this cache entry
|
||
* @param authority
|
||
*/
|
||
AuthorityMetadataEntity.prototype.updateCanonicalAuthority = function (authority) {
|
||
this.canonical_authority = authority;
|
||
};
|
||
/**
|
||
* Reset the exiresAt value
|
||
*/
|
||
AuthorityMetadataEntity.prototype.resetExpiresAt = function () {
|
||
this.expiresAt = TimeUtils.nowSeconds() + AUTHORITY_METADATA_CONSTANTS.REFRESH_TIME_SECONDS;
|
||
};
|
||
/**
|
||
* Returns whether or not the data needs to be refreshed
|
||
*/
|
||
AuthorityMetadataEntity.prototype.isExpired = function () {
|
||
return this.expiresAt <= TimeUtils.nowSeconds();
|
||
};
|
||
/**
|
||
* Validates an entity: checks for all expected params
|
||
* @param entity
|
||
*/
|
||
AuthorityMetadataEntity.isAuthorityMetadataEntity = function (key, entity) {
|
||
if (!entity) {
|
||
return false;
|
||
}
|
||
return (key.indexOf(AUTHORITY_METADATA_CONSTANTS.CACHE_KEY) === 0 &&
|
||
entity.hasOwnProperty("aliases") &&
|
||
entity.hasOwnProperty("preferred_cache") &&
|
||
entity.hasOwnProperty("preferred_network") &&
|
||
entity.hasOwnProperty("canonical_authority") &&
|
||
entity.hasOwnProperty("authorization_endpoint") &&
|
||
entity.hasOwnProperty("token_endpoint") &&
|
||
entity.hasOwnProperty("end_session_endpoint") &&
|
||
entity.hasOwnProperty("issuer") &&
|
||
entity.hasOwnProperty("aliasesFromNetwork") &&
|
||
entity.hasOwnProperty("endpointsFromNetwork") &&
|
||
entity.hasOwnProperty("expiresAt"));
|
||
};
|
||
return AuthorityMetadataEntity;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
function isCloudInstanceDiscoveryResponse(response) {
|
||
return (response.hasOwnProperty("tenant_discovery_endpoint") &&
|
||
response.hasOwnProperty("metadata"));
|
||
}
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
/**
|
||
* The authority class validates the authority URIs used by the user, and retrieves the OpenID Configuration Data from the
|
||
* endpoint. It will store the pertinent config data in this object for use during token calls.
|
||
*/
|
||
var Authority = /** @class */ (function () {
|
||
function Authority(authority, networkInterface, cacheManager, authorityOptions) {
|
||
this.canonicalAuthority = authority;
|
||
this._canonicalAuthority.validateAsUri();
|
||
this.networkInterface = networkInterface;
|
||
this.cacheManager = cacheManager;
|
||
this.authorityOptions = authorityOptions;
|
||
}
|
||
Object.defineProperty(Authority.prototype, "authorityType", {
|
||
// See above for AuthorityType
|
||
get: function () {
|
||
var pathSegments = this.canonicalAuthorityUrlComponents.PathSegments;
|
||
if (pathSegments.length && pathSegments[0].toLowerCase() === Constants.ADFS) {
|
||
return AuthorityType.Adfs;
|
||
}
|
||
return AuthorityType.Default;
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
Object.defineProperty(Authority.prototype, "protocolMode", {
|
||
/**
|
||
* ProtocolMode enum representing the way endpoints are constructed.
|
||
*/
|
||
get: function () {
|
||
return this.authorityOptions.protocolMode;
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
Object.defineProperty(Authority.prototype, "options", {
|
||
/**
|
||
* Returns authorityOptions which can be used to reinstantiate a new authority instance
|
||
*/
|
||
get: function () {
|
||
return this.authorityOptions;
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
Object.defineProperty(Authority.prototype, "canonicalAuthority", {
|
||
/**
|
||
* A URL that is the authority set by the developer
|
||
*/
|
||
get: function () {
|
||
return this._canonicalAuthority.urlString;
|
||
},
|
||
/**
|
||
* Sets canonical authority.
|
||
*/
|
||
set: function (url) {
|
||
this._canonicalAuthority = new UrlString(url);
|
||
this._canonicalAuthority.validateAsUri();
|
||
this._canonicalAuthorityUrlComponents = null;
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
Object.defineProperty(Authority.prototype, "canonicalAuthorityUrlComponents", {
|
||
/**
|
||
* Get authority components.
|
||
*/
|
||
get: function () {
|
||
if (!this._canonicalAuthorityUrlComponents) {
|
||
this._canonicalAuthorityUrlComponents = this._canonicalAuthority.getUrlComponents();
|
||
}
|
||
return this._canonicalAuthorityUrlComponents;
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
Object.defineProperty(Authority.prototype, "hostnameAndPort", {
|
||
/**
|
||
* Get hostname and port i.e. login.microsoftonline.com
|
||
*/
|
||
get: function () {
|
||
return this.canonicalAuthorityUrlComponents.HostNameAndPort.toLowerCase();
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
Object.defineProperty(Authority.prototype, "tenant", {
|
||
/**
|
||
* Get tenant for authority.
|
||
*/
|
||
get: function () {
|
||
return this.canonicalAuthorityUrlComponents.PathSegments[0];
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
Object.defineProperty(Authority.prototype, "authorizationEndpoint", {
|
||
/**
|
||
* OAuth /authorize endpoint for requests
|
||
*/
|
||
get: function () {
|
||
if (this.discoveryComplete()) {
|
||
var endpoint = this.replacePath(this.metadata.authorization_endpoint);
|
||
return this.replaceTenant(endpoint);
|
||
}
|
||
else {
|
||
throw ClientAuthError.createEndpointDiscoveryIncompleteError("Discovery incomplete.");
|
||
}
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
Object.defineProperty(Authority.prototype, "tokenEndpoint", {
|
||
/**
|
||
* OAuth /token endpoint for requests
|
||
*/
|
||
get: function () {
|
||
if (this.discoveryComplete()) {
|
||
var endpoint = this.replacePath(this.metadata.token_endpoint);
|
||
return this.replaceTenant(endpoint);
|
||
}
|
||
else {
|
||
throw ClientAuthError.createEndpointDiscoveryIncompleteError("Discovery incomplete.");
|
||
}
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
Object.defineProperty(Authority.prototype, "deviceCodeEndpoint", {
|
||
get: function () {
|
||
if (this.discoveryComplete()) {
|
||
var endpoint = this.replacePath(this.metadata.token_endpoint.replace("/token", "/devicecode"));
|
||
return this.replaceTenant(endpoint);
|
||
}
|
||
else {
|
||
throw ClientAuthError.createEndpointDiscoveryIncompleteError("Discovery incomplete.");
|
||
}
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
Object.defineProperty(Authority.prototype, "endSessionEndpoint", {
|
||
/**
|
||
* OAuth logout endpoint for requests
|
||
*/
|
||
get: function () {
|
||
if (this.discoveryComplete()) {
|
||
var endpoint = this.replacePath(this.metadata.end_session_endpoint);
|
||
return this.replaceTenant(endpoint);
|
||
}
|
||
else {
|
||
throw ClientAuthError.createEndpointDiscoveryIncompleteError("Discovery incomplete.");
|
||
}
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
Object.defineProperty(Authority.prototype, "selfSignedJwtAudience", {
|
||
/**
|
||
* OAuth issuer for requests
|
||
*/
|
||
get: function () {
|
||
if (this.discoveryComplete()) {
|
||
var endpoint = this.replacePath(this.metadata.issuer);
|
||
return this.replaceTenant(endpoint);
|
||
}
|
||
else {
|
||
throw ClientAuthError.createEndpointDiscoveryIncompleteError("Discovery incomplete.");
|
||
}
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
/**
|
||
* Replaces tenant in url path with current tenant. Defaults to common.
|
||
* @param urlString
|
||
*/
|
||
Authority.prototype.replaceTenant = function (urlString) {
|
||
return urlString.replace(/{tenant}|{tenantid}/g, this.tenant);
|
||
};
|
||
/**
|
||
* Replaces path such as tenant or policy with the current tenant or policy.
|
||
* @param urlString
|
||
*/
|
||
Authority.prototype.replacePath = function (urlString) {
|
||
var endpoint = urlString;
|
||
var cachedAuthorityUrl = new UrlString(this.metadata.canonical_authority);
|
||
var cachedAuthorityParts = cachedAuthorityUrl.getUrlComponents().PathSegments;
|
||
var currentAuthorityParts = this.canonicalAuthorityUrlComponents.PathSegments;
|
||
currentAuthorityParts.forEach(function (currentPart, index) {
|
||
var cachedPart = cachedAuthorityParts[index];
|
||
if (currentPart !== cachedPart) {
|
||
endpoint = endpoint.replace("/" + cachedPart + "/", "/" + currentPart + "/");
|
||
}
|
||
});
|
||
return endpoint;
|
||
};
|
||
Object.defineProperty(Authority.prototype, "defaultOpenIdConfigurationEndpoint", {
|
||
/**
|
||
* The default open id configuration endpoint for any canonical authority.
|
||
*/
|
||
get: function () {
|
||
if (this.authorityType === AuthorityType.Adfs || this.protocolMode === ProtocolMode.OIDC) {
|
||
return this.canonicalAuthority + ".well-known/openid-configuration";
|
||
}
|
||
return this.canonicalAuthority + "v2.0/.well-known/openid-configuration";
|
||
},
|
||
enumerable: true,
|
||
configurable: true
|
||
});
|
||
/**
|
||
* Boolean that returns whethr or not tenant discovery has been completed.
|
||
*/
|
||
Authority.prototype.discoveryComplete = function () {
|
||
return !!this.metadata;
|
||
};
|
||
/**
|
||
* Perform endpoint discovery to discover aliases, preferred_cache, preferred_network
|
||
* and the /authorize, /token and logout endpoints.
|
||
*/
|
||
Authority.prototype.resolveEndpointsAsync = function () {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var metadataEntity, cloudDiscoverySource, endpointSource, cacheKey;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
metadataEntity = this.cacheManager.getAuthorityMetadataByAlias(this.hostnameAndPort);
|
||
if (!metadataEntity) {
|
||
metadataEntity = new AuthorityMetadataEntity();
|
||
metadataEntity.updateCanonicalAuthority(this.canonicalAuthority);
|
||
}
|
||
return [4 /*yield*/, this.updateCloudDiscoveryMetadata(metadataEntity)];
|
||
case 1:
|
||
cloudDiscoverySource = _a.sent();
|
||
this.canonicalAuthority = this.canonicalAuthority.replace(this.hostnameAndPort, metadataEntity.preferred_network);
|
||
return [4 /*yield*/, this.updateEndpointMetadata(metadataEntity)];
|
||
case 2:
|
||
endpointSource = _a.sent();
|
||
if (cloudDiscoverySource !== AuthorityMetadataSource.CACHE && endpointSource !== AuthorityMetadataSource.CACHE) {
|
||
// Reset the expiration time unless both values came from a successful cache lookup
|
||
metadataEntity.resetExpiresAt();
|
||
metadataEntity.updateCanonicalAuthority(this.canonicalAuthority);
|
||
}
|
||
cacheKey = this.cacheManager.generateAuthorityMetadataCacheKey(metadataEntity.preferred_cache);
|
||
this.cacheManager.setAuthorityMetadata(cacheKey, metadataEntity);
|
||
this.metadata = metadataEntity;
|
||
return [2 /*return*/];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Update AuthorityMetadataEntity with new endpoints and return where the information came from
|
||
* @param metadataEntity
|
||
*/
|
||
Authority.prototype.updateEndpointMetadata = function (metadataEntity) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var metadata;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
metadata = this.getEndpointMetadataFromConfig();
|
||
if (metadata) {
|
||
metadataEntity.updateEndpointMetadata(metadata, false);
|
||
return [2 /*return*/, AuthorityMetadataSource.CONFIG];
|
||
}
|
||
if (this.isAuthoritySameType(metadataEntity) && metadataEntity.endpointsFromNetwork && !metadataEntity.isExpired()) {
|
||
// No need to update
|
||
return [2 /*return*/, AuthorityMetadataSource.CACHE];
|
||
}
|
||
return [4 /*yield*/, this.getEndpointMetadataFromNetwork()];
|
||
case 1:
|
||
metadata = _a.sent();
|
||
if (metadata) {
|
||
metadataEntity.updateEndpointMetadata(metadata, true);
|
||
return [2 /*return*/, AuthorityMetadataSource.NETWORK];
|
||
}
|
||
else {
|
||
throw ClientAuthError.createUnableToGetOpenidConfigError(this.defaultOpenIdConfigurationEndpoint);
|
||
}
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Compares the number of url components after the domain to determine if the cached authority metadata can be used for the requested authority
|
||
* Protects against same domain different authority such as login.microsoftonline.com/tenant and login.microsoftonline.com/tfp/tenant/policy
|
||
* @param metadataEntity
|
||
*/
|
||
Authority.prototype.isAuthoritySameType = function (metadataEntity) {
|
||
var cachedAuthorityUrl = new UrlString(metadataEntity.canonical_authority);
|
||
var cachedParts = cachedAuthorityUrl.getUrlComponents().PathSegments;
|
||
return cachedParts.length === this.canonicalAuthorityUrlComponents.PathSegments.length;
|
||
};
|
||
/**
|
||
* Parse authorityMetadata config option
|
||
*/
|
||
Authority.prototype.getEndpointMetadataFromConfig = function () {
|
||
if (this.authorityOptions.authorityMetadata) {
|
||
try {
|
||
return JSON.parse(this.authorityOptions.authorityMetadata);
|
||
}
|
||
catch (e) {
|
||
throw ClientConfigurationError.createInvalidAuthorityMetadataError();
|
||
}
|
||
}
|
||
return null;
|
||
};
|
||
/**
|
||
* Gets OAuth endpoints from the given OpenID configuration endpoint.
|
||
*/
|
||
Authority.prototype.getEndpointMetadataFromNetwork = function () {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var response, e_1;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
_a.trys.push([0, 2, , 3]);
|
||
return [4 /*yield*/, this.networkInterface.sendGetRequestAsync(this.defaultOpenIdConfigurationEndpoint)];
|
||
case 1:
|
||
response = _a.sent();
|
||
return [2 /*return*/, isOpenIdConfigResponse(response.body) ? response.body : null];
|
||
case 2:
|
||
e_1 = _a.sent();
|
||
return [2 /*return*/, null];
|
||
case 3: return [2 /*return*/];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Updates the AuthorityMetadataEntity with new aliases, preferred_network and preferred_cache and returns where the information was retrived from
|
||
* @param cachedMetadata
|
||
* @param newMetadata
|
||
*/
|
||
Authority.prototype.updateCloudDiscoveryMetadata = function (metadataEntity) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var metadata;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
metadata = this.getCloudDiscoveryMetadataFromConfig();
|
||
if (metadata) {
|
||
metadataEntity.updateCloudDiscoveryMetadata(metadata, false);
|
||
return [2 /*return*/, AuthorityMetadataSource.CONFIG];
|
||
}
|
||
// If The cached metadata came from config but that config was not passed to this instance, we must go to the network
|
||
if (this.isAuthoritySameType(metadataEntity) && metadataEntity.aliasesFromNetwork && !metadataEntity.isExpired()) {
|
||
// No need to update
|
||
return [2 /*return*/, AuthorityMetadataSource.CACHE];
|
||
}
|
||
return [4 /*yield*/, this.getCloudDiscoveryMetadataFromNetwork()];
|
||
case 1:
|
||
metadata = _a.sent();
|
||
if (metadata) {
|
||
metadataEntity.updateCloudDiscoveryMetadata(metadata, true);
|
||
return [2 /*return*/, AuthorityMetadataSource.NETWORK];
|
||
}
|
||
else {
|
||
// Metadata could not be obtained from config, cache or network
|
||
throw ClientConfigurationError.createUntrustedAuthorityError();
|
||
}
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Parse cloudDiscoveryMetadata config or check knownAuthorities
|
||
*/
|
||
Authority.prototype.getCloudDiscoveryMetadataFromConfig = function () {
|
||
// Check if network response was provided in config
|
||
if (this.authorityOptions.cloudDiscoveryMetadata) {
|
||
try {
|
||
var parsedResponse = JSON.parse(this.authorityOptions.cloudDiscoveryMetadata);
|
||
var metadata = Authority.getCloudDiscoveryMetadataFromNetworkResponse(parsedResponse.metadata, this.hostnameAndPort);
|
||
if (metadata) {
|
||
return metadata;
|
||
}
|
||
}
|
||
catch (e) {
|
||
throw ClientConfigurationError.createInvalidCloudDiscoveryMetadataError();
|
||
}
|
||
}
|
||
// If cloudDiscoveryMetadata is empty or does not contain the host, check knownAuthorities
|
||
if (this.isInKnownAuthorities()) {
|
||
return Authority.createCloudDiscoveryMetadataFromHost(this.hostnameAndPort);
|
||
}
|
||
return null;
|
||
};
|
||
/**
|
||
* Called to get metadata from network if CloudDiscoveryMetadata was not populated by config
|
||
* @param networkInterface
|
||
*/
|
||
Authority.prototype.getCloudDiscoveryMetadataFromNetwork = function () {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var instanceDiscoveryEndpoint, match, response, metadata, e_2;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
instanceDiscoveryEndpoint = "" + Constants.AAD_INSTANCE_DISCOVERY_ENDPT + this.canonicalAuthority + "oauth2/v2.0/authorize";
|
||
match = null;
|
||
_a.label = 1;
|
||
case 1:
|
||
_a.trys.push([1, 3, , 4]);
|
||
return [4 /*yield*/, this.networkInterface.sendGetRequestAsync(instanceDiscoveryEndpoint)];
|
||
case 2:
|
||
response = _a.sent();
|
||
metadata = isCloudInstanceDiscoveryResponse(response.body) ? response.body.metadata : [];
|
||
match = Authority.getCloudDiscoveryMetadataFromNetworkResponse(metadata, this.hostnameAndPort);
|
||
return [3 /*break*/, 4];
|
||
case 3:
|
||
e_2 = _a.sent();
|
||
return [2 /*return*/, null];
|
||
case 4:
|
||
if (!match) {
|
||
// Custom Domain scenario, host is trusted because Instance Discovery call succeeded
|
||
match = Authority.createCloudDiscoveryMetadataFromHost(this.hostnameAndPort);
|
||
}
|
||
return [2 /*return*/, match];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Helper function to determine if this host is included in the knownAuthorities config option
|
||
*/
|
||
Authority.prototype.isInKnownAuthorities = function () {
|
||
var _this = this;
|
||
var matches = this.authorityOptions.knownAuthorities.filter(function (authority) {
|
||
return UrlString.getDomainFromUrl(authority).toLowerCase() === _this.hostnameAndPort;
|
||
});
|
||
return matches.length > 0;
|
||
};
|
||
/**
|
||
* Creates cloud discovery metadata object from a given host
|
||
* @param host
|
||
*/
|
||
Authority.createCloudDiscoveryMetadataFromHost = function (host) {
|
||
return {
|
||
preferred_network: host,
|
||
preferred_cache: host,
|
||
aliases: [host]
|
||
};
|
||
};
|
||
/**
|
||
* Searches instance discovery network response for the entry that contains the host in the aliases list
|
||
* @param response
|
||
* @param authority
|
||
*/
|
||
Authority.getCloudDiscoveryMetadataFromNetworkResponse = function (response, authority) {
|
||
for (var i = 0; i < response.length; i++) {
|
||
var metadata = response[i];
|
||
if (metadata.aliases.indexOf(authority) > -1) {
|
||
return metadata;
|
||
}
|
||
}
|
||
return null;
|
||
};
|
||
/**
|
||
* helper function to generate environment from authority object
|
||
*/
|
||
Authority.prototype.getPreferredCache = function () {
|
||
if (this.discoveryComplete()) {
|
||
return this.metadata.preferred_cache;
|
||
}
|
||
else {
|
||
throw ClientAuthError.createEndpointDiscoveryIncompleteError("Discovery incomplete.");
|
||
}
|
||
};
|
||
/**
|
||
* Returns whether or not the provided host is an alias of this authority instance
|
||
* @param host
|
||
*/
|
||
Authority.prototype.isAlias = function (host) {
|
||
return this.metadata.aliases.indexOf(host) > -1;
|
||
};
|
||
return Authority;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
var AuthorityFactory = /** @class */ (function () {
|
||
function AuthorityFactory() {
|
||
}
|
||
/**
|
||
* Create an authority object of the correct type based on the url
|
||
* Performs basic authority validation - checks to see if the authority is of a valid type (i.e. aad, b2c, adfs)
|
||
*
|
||
* Also performs endpoint discovery.
|
||
*
|
||
* @param authorityUri
|
||
* @param networkClient
|
||
* @param protocolMode
|
||
*/
|
||
AuthorityFactory.createDiscoveredInstance = function (authorityUri, networkClient, cacheManager, authorityOptions) {
|
||
return __awaiter(this, void 0, void 0, function () {
|
||
var acquireTokenAuthority, e_1;
|
||
return __generator(this, function (_a) {
|
||
switch (_a.label) {
|
||
case 0:
|
||
acquireTokenAuthority = AuthorityFactory.createInstance(authorityUri, networkClient, cacheManager, authorityOptions);
|
||
_a.label = 1;
|
||
case 1:
|
||
_a.trys.push([1, 3, , 4]);
|
||
return [4 /*yield*/, acquireTokenAuthority.resolveEndpointsAsync()];
|
||
case 2:
|
||
_a.sent();
|
||
return [2 /*return*/, acquireTokenAuthority];
|
||
case 3:
|
||
e_1 = _a.sent();
|
||
throw ClientAuthError.createEndpointDiscoveryIncompleteError(e_1);
|
||
case 4: return [2 /*return*/];
|
||
}
|
||
});
|
||
});
|
||
};
|
||
/**
|
||
* Create an authority object of the correct type based on the url
|
||
* Performs basic authority validation - checks to see if the authority is of a valid type (i.e. aad, b2c, adfs)
|
||
*
|
||
* Does not perform endpoint discovery.
|
||
*
|
||
* @param authorityUrl
|
||
* @param networkInterface
|
||
* @param protocolMode
|
||
*/
|
||
AuthorityFactory.createInstance = function (authorityUrl, networkInterface, cacheManager, authorityOptions) {
|
||
// Throw error if authority url is empty
|
||
if (StringUtils.isEmpty(authorityUrl)) {
|
||
throw ClientConfigurationError.createUrlEmptyError();
|
||
}
|
||
return new Authority(authorityUrl, networkInterface, cacheManager, authorityOptions);
|
||
};
|
||
return AuthorityFactory;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
var ServerTelemetryEntity = /** @class */ (function () {
|
||
function ServerTelemetryEntity() {
|
||
this.failedRequests = [];
|
||
this.errors = [];
|
||
this.cacheHits = 0;
|
||
}
|
||
/**
|
||
* validates if a given cache entry is "Telemetry", parses <key,value>
|
||
* @param key
|
||
* @param entity
|
||
*/
|
||
ServerTelemetryEntity.isServerTelemetryEntity = function (key, entity) {
|
||
var validateKey = key.indexOf(SERVER_TELEM_CONSTANTS.CACHE_KEY) === 0;
|
||
var validateEntity = true;
|
||
if (entity) {
|
||
validateEntity =
|
||
entity.hasOwnProperty("failedRequests") &&
|
||
entity.hasOwnProperty("errors") &&
|
||
entity.hasOwnProperty("cacheHits");
|
||
}
|
||
return validateKey && validateEntity;
|
||
};
|
||
return ServerTelemetryEntity;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
var ThrottlingEntity = /** @class */ (function () {
|
||
function ThrottlingEntity() {
|
||
}
|
||
/**
|
||
* validates if a given cache entry is "Throttling", parses <key,value>
|
||
* @param key
|
||
* @param entity
|
||
*/
|
||
ThrottlingEntity.isThrottlingEntity = function (key, entity) {
|
||
var validateKey = false;
|
||
if (key) {
|
||
validateKey = key.indexOf(ThrottlingConstants.THROTTLING_PREFIX) === 0;
|
||
}
|
||
var validateEntity = true;
|
||
if (entity) {
|
||
validateEntity = entity.hasOwnProperty("throttleTime");
|
||
}
|
||
return validateKey && validateEntity;
|
||
};
|
||
return ThrottlingEntity;
|
||
}());
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
var StubbedNetworkModule = {
|
||
sendGetRequestAsync: function () {
|
||
var notImplErr = "Network interface - sendGetRequestAsync() has not been implemented for the Network interface.";
|
||
return Promise.reject(AuthError.createUnexpectedError(notImplErr));
|
||
},
|
||
sendPostRequestAsync: function () {
|
||
var notImplErr = "Network interface - sendPostRequestAsync() has not been implemented for the Network interface.";
|
||
return Promise.reject(AuthError.createUnexpectedError(notImplErr));
|
||
}
|
||
};
|
||
|
||
/*
|
||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
* Licensed under the MIT License.
|
||
*/
|
||
var ServerTelemetryManager = /** @class */ (function () {
|
||
function ServerTelemetryManager(telemetryRequest, cacheManager) {
|
||
this.cacheManager = cacheManager;
|
||
this.apiId = telemetryRequest.apiId;
|
||
this.correlationId = telemetryRequest.correlationId;
|
||
this.forceRefresh = telemetryRequest.forceRefresh || false;
|
||
this.wrapperSKU = telemetryRequest.wrapperSKU || Constants.EMPTY_STRING;
|
||
this.wrapperVer = telemetryRequest.wrapperVer || Constants.EMPTY_STRING;
|
||
this.telemetryCacheKey = SERVER_TELEM_CONSTANTS.CACHE_KEY + Separators.CACHE_KEY_SEPARATOR + telemetryRequest.clientId;
|
||
}
|
||
/**
|
||
* API to add MSER Telemetry to request
|
||
*/
|
||
ServerTelemetryManager.prototype.generateCurrentRequestHeaderValue = function () {
|
||
var forceRefreshInt = this.forceRefresh ? 1 : 0;
|
||
var request = "" + this.apiId + SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR + forceRefreshInt;
|
||
var platformFields = [this.wrapperSKU, this.wrapperVer].join(SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR);
|
||
return [SERVER_TELEM_CONSTANTS.SCHEMA_VERSION, request, platformFields].join(SERVER_TELEM_CONSTANTS.CATEGORY_SEPARATOR);
|
||
};
|
||
/**
|
||
* API to add MSER Telemetry for the last failed request
|
||
*/
|
||
ServerTelemetryManager.prototype.generateLastRequestHeaderValue = function () {
|
||
var lastRequests = this.getLastRequests();
|
||
var maxErrors = ServerTelemetryManager.maxErrorsToSend(lastRequests);
|
||
var failedRequests = lastRequests.failedRequests.slice(0, 2 * maxErrors).join(SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR);
|
||
var errors = lastRequests.errors.slice(0, maxErrors).join(SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR);
|
||
var errorCount = lastRequests.errors.length;
|
||
// Indicate whether this header contains all data or partial data
|
||
var overflow = maxErrors < errorCount ? SERVER_TELEM_CONSTANTS.OVERFLOW_TRUE : SERVER_TELEM_CONSTANTS.OVERFLOW_FALSE;
|
||
var platformFields = [errorCount, overflow].join(SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR);
|
||
return [SERVER_TELEM_CONSTANTS.SCHEMA_VERSION, lastRequests.cacheHits, failedRequests, errors, platformFields].join(SERVER_TELEM_CONSTANTS.CATEGORY_SEPARATOR);
|
||
};
|
||
/**
|
||
* API to cache token failures for MSER data capture
|
||
* @param error
|
||
*/
|
||
ServerTelemetryManager.prototype.cacheFailedRequest = function (error) {
|
||
var lastRequests = this.getLastRequests();
|
||
lastRequests.failedRequests.push(this.apiId, this.correlationId);
|
||
if (!StringUtils.isEmpty(error.subError)) {
|
||
lastRequests.errors.push(error.subError);
|
||
}
|
||
else if (!StringUtils.isEmpty(error.errorCode)) {
|
||
lastRequests.errors.push(error.errorCode);
|
||
}
|
||
else if (!!error && error.toString()) {
|
||
lastRequests.errors.push(error.toString());
|
||
}
|
||
else {
|
||
lastRequests.errors.push(SERVER_TELEM_CONSTANTS.UNKNOWN_ERROR);
|
||
}
|
||
this.cacheManager.setServerTelemetry(this.telemetryCacheKey, lastRequests);
|
||
return;
|
||
};
|
||
/**
|
||
* Update server telemetry cache entry by incrementing cache hit counter
|
||
*/
|
||
ServerTelemetryManager.prototype.incrementCacheHits = function () {
|
||
var lastRequests = this.getLastRequests();
|
||
lastRequests.cacheHits += 1;
|
||
this.cacheManager.setServerTelemetry(this.telemetryCacheKey, lastRequests);
|
||
return lastRequests.cacheHits;
|
||
};
|
||
/**
|
||
* Get the server telemetry entity from cache or initialize a new one
|
||
*/
|
||
ServerTelemetryManager.prototype.getLastRequests = function () {
|
||
var initialValue = new ServerTelemetryEntity();
|
||
var lastRequests = this.cacheManager.getServerTelemetry(this.telemetryCacheKey);
|
||
return lastRequests || initialValue;
|
||
};
|
||
/**
|
||
* Remove server telemetry cache entry
|
||
*/
|
||
ServerTelemetryManager.prototype.clearTelemetryCache = function () {
|
||
var lastRequests = this.getLastRequests();
|
||
var numErrorsFlushed = ServerTelemetryManager.maxErrorsToSend(lastRequests);
|
||
var errorCount = lastRequests.errors.length;
|
||
if (numErrorsFlushed === errorCount) {
|
||
// All errors were sent on last request, clear Telemetry cache
|
||
this.cacheManager.removeItem(this.telemetryCacheKey);
|
||
}
|
||
else {
|
||
// Partial data was flushed to server, construct a new telemetry cache item with errors that were not flushed
|
||
var serverTelemEntity = new ServerTelemetryEntity();
|
||
serverTelemEntity.failedRequests = lastRequests.failedRequests.slice(numErrorsFlushed * 2); // failedRequests contains 2 items for each error
|
||
serverTelemEntity.errors = lastRequests.errors.slice(numErrorsFlushed);
|
||
this.cacheManager.setServerTelemetry(this.telemetryCacheKey, serverTelemEntity);
|
||
}
|
||
};
|
||
/**
|
||
* Returns the maximum number of errors that can be flushed to the server in the next network request
|
||
* @param serverTelemetryEntity
|
||
*/
|
||
ServerTelemetryManager.maxErrorsToSend = function (serverTelemetryEntity) {
|
||
var i;
|
||
var maxErrors = 0;
|
||
var dataSize = 0;
|
||
var errorCount = serverTelemetryEntity.errors.length;
|
||
for (i = 0; i < errorCount; i++) {
|
||
// failedRequests parameter contains pairs of apiId and correlationId, multiply index by 2 to preserve pairs
|
||
var apiId = serverTelemetryEntity.failedRequests[2 * i] || Constants.EMPTY_STRING;
|
||
var correlationId = serverTelemetryEntity.failedRequests[2 * i + 1] || Constants.EMPTY_STRING;
|
||
var errorCode = serverTelemetryEntity.errors[i] || Constants.EMPTY_STRING;
|
||
// Count number of characters that would be added to header, each character is 1 byte. Add 3 at the end to account for separators
|
||
dataSize += apiId.toString().length + correlationId.toString().length + errorCode.length + 3;
|
||
if (dataSize < SERVER_TELEM_CONSTANTS.MAX_HEADER_BYTES) {
|
||
// Adding this entry to the header would still keep header size below the limit
|
||
maxErrors += 1;
|
||
}
|
||
else {
|
||
break;
|
||
}
|
||
}
|
||
return maxErrors;
|
||
};
|
||
return ServerTelemetryManager;
|
||
}());
|
||
|
||
export { AccessTokenEntity, AccountEntity, AppMetadataEntity, AuthError, AuthErrorMessage, AuthToken, AuthenticationScheme, Authority, AuthorityFactory, AuthorityMetadataEntity, AuthorityType, AuthorizationCodeClient, CacheAccountType, CacheManager, CacheSchemaType, CacheType, ClientAuthError, ClientAuthErrorMessage, ClientConfigurationError, ClientConfigurationErrorMessage, ClientCredentialClient, Constants, CredentialEntity, CredentialType, DEFAULT_CRYPTO_IMPLEMENTATION, DEFAULT_SYSTEM_OPTIONS, DefaultStorageClass, DeviceCodeClient, AuthToken as IdToken, IdTokenEntity, InteractionRequiredAuthError, LogLevel, Logger, NetworkManager, OIDC_DEFAULT_SCOPES, OnBehalfOfClient, PersistentCacheKeys, PromptValue, ProtocolMode, ProtocolUtils, RefreshTokenClient, RefreshTokenEntity, ResponseMode, ServerError, ServerTelemetryEntity, ServerTelemetryManager, SilentFlowClient, StringUtils, StubbedNetworkModule, ThrottlingEntity, ThrottlingUtils, TimeUtils, TokenCacheContext, UrlString, UsernamePasswordClient };
|
||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZXMuanMiLCJzb3VyY2VzIjpbIi4uL3NyYy91dGlscy9Db25zdGFudHMudHMiLCIuLi9zcmMvZXJyb3IvQXV0aEVycm9yLnRzIiwiLi4vc3JjL2NyeXB0by9JQ3J5cHRvLnRzIiwiLi4vc3JjL2Vycm9yL0NsaWVudEF1dGhFcnJvci50cyIsIi4uL3NyYy91dGlscy9TdHJpbmdVdGlscy50cyIsIi4uL3NyYy9sb2dnZXIvTG9nZ2VyLnRzIiwiLi4vc3JjL3BhY2thZ2VNZXRhZGF0YS50cyIsIi4uL3NyYy9jYWNoZS9lbnRpdGllcy9DcmVkZW50aWFsRW50aXR5LnRzIiwiLi4vc3JjL2Vycm9yL0NsaWVudENvbmZpZ3VyYXRpb25FcnJvci50cyIsIi4uL3NyYy9yZXF1ZXN0L1Njb3BlU2V0LnRzIiwiLi4vc3JjL2FjY291bnQvQ2xpZW50SW5mby50cyIsIi4uL3NyYy9hdXRob3JpdHkvQXV0aG9yaXR5VHlwZS50cyIsIi4uL3NyYy9jYWNoZS9lbnRpdGllcy9BY2NvdW50RW50aXR5LnRzIiwiLi4vc3JjL2FjY291bnQvQXV0aFRva2VuLnRzIiwiLi4vc3JjL2NhY2hlL0NhY2hlTWFuYWdlci50cyIsIi4uL3NyYy9jb25maWcvQ2xpZW50Q29uZmlndXJhdGlvbi50cyIsIi4uL3NyYy9lcnJvci9TZXJ2ZXJFcnJvci50cyIsIi4uL3NyYy9uZXR3b3JrL1Rocm90dGxpbmdVdGlscy50cyIsIi4uL3NyYy9uZXR3b3JrL05ldHdvcmtNYW5hZ2VyLnRzIiwiLi4vc3JjL2NsaWVudC9CYXNlQ2xpZW50LnRzIiwiLi4vc3JjL3JlcXVlc3QvUmVxdWVzdFZhbGlkYXRvci50cyIsIi4uL3NyYy9yZXF1ZXN0L1JlcXVlc3RQYXJhbWV0ZXJCdWlsZGVyLnRzIiwiLi4vc3JjL2NhY2hlL2VudGl0aWVzL0lkVG9rZW5FbnRpdHkudHMiLCIuLi9zcmMvdXRpbHMvVGltZVV0aWxzLnRzIiwiLi4vc3JjL2NhY2hlL2VudGl0aWVzL0FjY2Vzc1Rva2VuRW50aXR5LnRzIiwiLi4vc3JjL2NhY2hlL2VudGl0aWVzL1JlZnJlc2hUb2tlbkVudGl0eS50cyIsIi4uL3NyYy9lcnJvci9JbnRlcmFjdGlvblJlcXVpcmVkQXV0aEVycm9yLnRzIiwiLi4vc3JjL2NhY2hlL2VudGl0aWVzL0NhY2hlUmVjb3JkLnRzIiwiLi4vc3JjL3V0aWxzL1Byb3RvY29sVXRpbHMudHMiLCIuLi9zcmMvdXJsL1VybFN0cmluZy50cyIsIi4uL3NyYy9jcnlwdG8vUG9wVG9rZW5HZW5lcmF0b3IudHMiLCIuLi9zcmMvY2FjaGUvZW50aXRpZXMvQXBwTWV0YWRhdGFFbnRpdHkudHMiLCIuLi9zcmMvY2FjaGUvcGVyc2lzdGVuY2UvVG9rZW5DYWNoZUNvbnRleHQudHMiLCIuLi9zcmMvcmVzcG9uc2UvUmVzcG9uc2VIYW5kbGVyLnRzIiwiLi4vc3JjL2NsaWVudC9BdXRob3JpemF0aW9uQ29kZUNsaWVudC50cyIsIi4uL3NyYy9jbGllbnQvRGV2aWNlQ29kZUNsaWVudC50cyIsIi4uL3NyYy9jbGllbnQvUmVmcmVzaFRva2VuQ2xpZW50LnRzIiwiLi4vc3JjL2NsaWVudC9DbGllbnRDcmVkZW50aWFsQ2xpZW50LnRzIiwiLi4vc3JjL2NsaWVudC9PbkJlaGFsZk9mQ2xpZW50LnRzIiwiLi4vc3JjL2NsaWVudC9TaWxlbnRGbG93Q2xpZW50LnRzIiwiLi4vc3JjL2NsaWVudC9Vc2VybmFtZVBhc3N3b3JkQ2xpZW50LnRzIiwiLi4vc3JjL2F1dGhvcml0eS9PcGVuSWRDb25maWdSZXNwb25zZS50cyIsIi4uL3NyYy9hdXRob3JpdHkvUHJvdG9jb2xNb2RlLnRzIiwiLi4vc3JjL2NhY2hlL2VudGl0aWVzL0F1dGhvcml0eU1ldGFkYXRhRW50aXR5LnRzIiwiLi4vc3JjL2F1dGhvcml0eS9DbG91ZEluc3RhbmNlRGlzY292ZXJ5UmVzcG9uc2UudHMiLCIuLi9zcmMvYXV0aG9yaXR5L0F1dGhvcml0eS50cyIsIi4uL3NyYy9hdXRob3JpdHkvQXV0aG9yaXR5RmFjdG9yeS50cyIsIi4uL3NyYy9jYWNoZS9lbnRpdGllcy9TZXJ2ZXJUZWxlbWV0cnlFbnRpdHkudHMiLCIuLi9zcmMvY2FjaGUvZW50aXRpZXMvVGhyb3R0bGluZ0VudGl0eS50cyIsIi4uL3NyYy9uZXR3b3JrL0lOZXR3b3JrTW9kdWxlLnRzIiwiLi4vc3JjL3RlbGVtZXRyeS9zZXJ2ZXIvU2VydmVyVGVsZW1ldHJ5TWFuYWdlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmV4cG9ydCBjb25zdCBDb25zdGFudHMgPSB7XHJcbiAgICBMSUJSQVJZX05BTUU6IFwiTVNBTC5KU1wiLFxyXG4gICAgU0tVOiBcIm1zYWwuanMuY29tbW9uXCIsXHJcbiAgICAvLyBQcmVmaXggZm9yIGFsbCBsaWJyYXJ5IGNhY2hlIGVudHJpZXNcclxuICAgIENBQ0hFX1BSRUZJWDogXCJtc2FsXCIsXHJcbiAgICAvLyBkZWZhdWx0IGF1dGhvcml0eVxyXG4gICAgREVGQVVMVF9BVVRIT1JJVFk6IFwiaHR0cHM6Ly9sb2dpbi5taWNyb3NvZnRvbmxpbmUuY29tL2NvbW1vbi9cIixcclxuICAgIERFRkFVTFRfQVVUSE9SSVRZX0hPU1Q6IFwibG9naW4ubWljcm9zb2Z0b25saW5lLmNvbVwiLFxyXG4gICAgLy8gQURGUyBTdHJpbmdcclxuICAgIEFERlM6IFwiYWRmc1wiLFxyXG4gICAgLy8gRGVmYXVsdCBBQUQgSW5zdGFuY2UgRGlzY292ZXJ5IEVuZHBvaW50XHJcbiAgICBBQURfSU5TVEFOQ0VfRElTQ09WRVJZX0VORFBUOiBcImh0dHBzOi8vbG9naW4ubWljcm9zb2Z0b25saW5lLmNvbS9jb21tb24vZGlzY292ZXJ5L2luc3RhbmNlP2FwaS12ZXJzaW9uPTEuMSZhdXRob3JpemF0aW9uX2VuZHBvaW50PVwiLFxyXG4gICAgLy8gUmVzb3VyY2UgZGVsaW1pdGVyIC0gdXNlZCBmb3IgY2VydGFpbiBjYWNoZSBlbnRyaWVzXHJcbiAgICBSRVNPVVJDRV9ERUxJTTogXCJ8XCIsXHJcbiAgICAvLyBQbGFjZWhvbGRlciBmb3Igbm9uLWV4aXN0ZW50IGFjY291bnQgaWRzL29iamVjdHNcclxuICAgIE5PX0FDQ09VTlQ6IFwiTk9fQUNDT1VOVFwiLFxyXG4gICAgLy8gQ2xhaW1zXHJcbiAgICBDTEFJTVM6IFwiY2xhaW1zXCIsXHJcbiAgICAvLyBDb25zdW1lciBVVElEXHJcbiAgICBDT05TVU1FUl9VVElEOiBcIjkxODgwNDBkLTZjNjctNGM1Yi1iMTEyLTM2YTMwNGI2NmRhZFwiLFxyXG4gICAgLy8gRGVmYXVsdCBzY29wZXNcclxuICAgIE9QRU5JRF9TQ09QRTogXCJvcGVuaWRcIixcclxuICAgIFBST0ZJTEVfU0NPUEU6IFwicHJvZmlsZVwiLFxyXG4gICAgT0ZGTElORV9BQ0NFU1NfU0NPUEU6IFwib2ZmbGluZV9hY2Nlc3NcIixcclxuICAgIEVNQUlMX1NDT1BFOiBcImVtYWlsXCIsXHJcbiAgICAvLyBEZWZhdWx0IHJlc3BvbnNlIHR5cGUgZm9yIGF1dGhvcml6YXRpb24gY29kZSBmbG93XHJcbiAgICBDT0RFX1JFU1BPTlNFX1RZUEU6IFwiY29kZVwiLFxyXG4gICAgQ09ERV9HUkFOVF9UWVBFOiBcImF1dGhvcml6YXRpb25fY29kZVwiLFxyXG4gICAgUlRfR1JBTlRfVFlQRTogXCJyZWZyZXNoX3Rva2VuXCIsXHJcbiAgICBGUkFHTUVOVF9SRVNQT05TRV9NT0RFOiBcImZyYWdtZW50XCIsXHJcbiAgICBTMjU2X0NPREVfQ0hBTExFTkdFX01FVEhPRDogXCJTMjU2XCIsXHJcbiAgICBVUkxfRk9STV9DT05URU5UX1RZUEU6IFwiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkO2NoYXJzZXQ9dXRmLThcIixcclxuICAgIEFVVEhPUklaQVRJT05fUEVORElORzogXCJhdXRob3JpemF0aW9uX3BlbmRpbmdcIixcclxuICAgIE5PVF9ERUZJTkVEOiBcIm5vdF9kZWZpbmVkXCIsXHJcbiAgICBFTVBUWV9TVFJJTkc6IFwiXCIsXHJcbiAgICBGT1JXQVJEX1NMQVNIOiBcIi9cIlxyXG59O1xyXG5cclxuZXhwb3J0IGNvbnN0IE9JRENfREVGQVVMVF9TQ09QRVMgPSBbXHJcbiAgICBDb25zdGFudHMuT1BFTklEX1NDT1BFLFxyXG4gICAgQ29uc3RhbnRzLlBST0ZJTEVfU0NPUEUsXHJcbiAgICBDb25zdGFudHMuT0ZGTElORV9BQ0NFU1NfU0NPUEVcclxuXTtcclxuXHJcbmV4cG9ydCBjb25zdCBPSURDX1NDT1BFUyA9IFtcclxuICAgIC4uLk9JRENfREVGQVVMVF9TQ09QRVMsXHJcbiAgICBDb25zdGFudHMuRU1BSUxfU0NPUEVcclxuXTtcclxuXHJcbi8qKlxyXG4gKiBSZXF1ZXN0IGhlYWRlciBuYW1lc1xyXG4gKi9cclxuZXhwb3J0IGVudW0gSGVhZGVyTmFtZXMge1xyXG4gICAgQ09OVEVOVF9UWVBFID0gXCJDb250ZW50LVR5cGVcIixcclxuICAgIFhfQ0xJRU5UX0NVUlJfVEVMRU0gPSBcIngtY2xpZW50LWN1cnJlbnQtdGVsZW1ldHJ5XCIsXHJcbiAgICBYX0NMSUVOVF9MQVNUX1RFTEVNID0gXCJ4LWNsaWVudC1sYXN0LXRlbGVtZXRyeVwiLFxyXG4gICAgUkVUUllfQUZURVIgPSBcIlJldHJ5LUFmdGVyXCIsXHJcbiAgICBYX01TX0xJQl9DQVBBQklMSVRZID0gXCJ4LW1zLWxpYi1jYXBhYmlsaXR5XCIsXHJcbiAgICBYX01TX0xJQl9DQVBBQklMSVRZX1ZBTFVFID0gXCJyZXRyeS1hZnRlciwgaDQyOVwiXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBQZXJzaXN0ZW50IGNhY2hlIGtleXMgTVNBTCB3aGljaCBzdGF5IHdoaWxlIHVzZXIgaXMgbG9nZ2VkIGluLlxyXG4gKi9cclxuZXhwb3J0IGVudW0gUGVyc2lzdGVudENhY2hlS2V5cyB7XHJcbiAgICBJRF9UT0tFTiA9IFwiaWR0b2tlblwiLFxyXG4gICAgQ0xJRU5UX0lORk8gPSBcImNsaWVudC5pbmZvXCIsXHJcbiAgICBBREFMX0lEX1RPS0VOID0gXCJhZGFsLmlkdG9rZW5cIixcclxuICAgIEVSUk9SID0gXCJlcnJvclwiLFxyXG4gICAgRVJST1JfREVTQyA9IFwiZXJyb3IuZGVzY3JpcHRpb25cIlxyXG59XHJcblxyXG4vKipcclxuICogU3RyaW5nIGNvbnN0YW50cyByZWxhdGVkIHRvIEFBRCBBdXRob3JpdHlcclxuICovXHJcbmV4cG9ydCBlbnVtIEFBREF1dGhvcml0eUNvbnN0YW50cyB7XHJcbiAgICBDT01NT04gPSBcImNvbW1vblwiLFxyXG4gICAgT1JHQU5JWkFUSU9OUyA9IFwib3JnYW5pemF0aW9uc1wiLFxyXG4gICAgQ09OU1VNRVJTID0gXCJjb25zdW1lcnNcIlxyXG59XHJcblxyXG4vKipcclxuICogS2V5cyBpbiB0aGUgaGFzaFBhcmFtcyBzZW50IGJ5IEFBRCBTZXJ2ZXJcclxuICovXHJcbmV4cG9ydCBlbnVtIEFBRFNlcnZlclBhcmFtS2V5cyB7XHJcbiAgICBDTElFTlRfSUQgPSBcImNsaWVudF9pZFwiLFxyXG4gICAgUkVESVJFQ1RfVVJJID0gXCJyZWRpcmVjdF91cmlcIixcclxuICAgIFJFU1BPTlNFX1RZUEUgPSBcInJlc3BvbnNlX3R5cGVcIixcclxuICAgIFJFU1BPTlNFX01PREUgPSBcInJlc3BvbnNlX21vZGVcIixcclxuICAgIEdSQU5UX1RZUEUgPSBcImdyYW50X3R5cGVcIixcclxuICAgIENMQUlNUyA9IFwiY2xhaW1zXCIsXHJcbiAgICBTQ09QRSA9IFwic2NvcGVcIixcclxuICAgIEVSUk9SID0gXCJlcnJvclwiLFxyXG4gICAgRVJST1JfREVTQ1JJUFRJT04gPSBcImVycm9yX2Rlc2NyaXB0aW9uXCIsXHJcbiAgICBBQ0NFU1NfVE9LRU4gPSBcImFjY2Vzc190b2tlblwiLFxyXG4gICAgSURfVE9LRU4gPSBcImlkX3Rva2VuXCIsXHJcbiAgICBSRUZSRVNIX1RPS0VOID0gXCJyZWZyZXNoX3Rva2VuXCIsXHJcbiAgICBFWFBJUkVTX0lOID0gXCJleHBpcmVzX2luXCIsXHJcbiAgICBTVEFURSA9IFwic3RhdGVcIixcclxuICAgIE5PTkNFID0gXCJub25jZVwiLFxyXG4gICAgUFJPTVBUID0gXCJwcm9tcHRcIixcclxuICAgIFNFU1NJT05fU1RBVEUgPSBcInNlc3Npb25fc3RhdGVcIixcclxuICAgIENMSUVOVF9JTkZPID0gXCJjbGllbnRfaW5mb1wiLFxyXG4gICAgQ09ERSA9IFwiY29kZVwiLFxyXG4gICAgQ09ERV9DSEFMTEVOR0UgPSBcImNvZGVfY2hhbGxlbmdlXCIsXHJcbiAgICBDT0RFX0NIQUxMRU5HRV9NRVRIT0QgPSBcImNvZGVfY2hhbGxlbmdlX21ldGhvZFwiLFxyXG4gICAgQ09ERV9WRVJJRklFUiA9IFwiY29kZV92ZXJpZmllclwiLFxyXG4gICAgQ0xJRU5UX1JFUVVFU1RfSUQgPSBcImNsaWVudC1yZXF1ZXN0LWlkXCIsXHJcbiAgICBYX0NMSUVOVF9TS1UgPSBcIngtY2xpZW50LVNLVVwiLFxyXG4gICAgWF9DTElFTlRfVkVSID0gXCJ4LWNsaWVudC1WRVJcIixcclxuICAgIFhfQ0xJRU5UX09TID0gXCJ4LWNsaWVudC1PU1wiLFxyXG4gICAgWF9DTElFTlRfQ1BVID0gXCJ4LWNsaWVudC1DUFVcIixcclxuICAgIFBPU1RfTE9HT1VUX1VSSSA9IFwicG9zdF9sb2dvdXRfcmVkaXJlY3RfdXJpXCIsXHJcbiAgICBJRF9UT0tFTl9ISU5UPSBcImlkX3Rva2VuX2hpbnRcIixcclxuICAgIERFVklDRV9DT0RFID0gXCJkZXZpY2VfY29kZVwiLFxyXG4gICAgQ0xJRU5UX1NFQ1JFVCA9IFwiY2xpZW50X3NlY3JldFwiLFxyXG4gICAgQ0xJRU5UX0FTU0VSVElPTiA9IFwiY2xpZW50X2Fzc2VydGlvblwiLFxyXG4gICAgQ0xJRU5UX0FTU0VSVElPTl9UWVBFID0gXCJjbGllbnRfYXNzZXJ0aW9uX3R5cGVcIixcclxuICAgIFRPS0VOX1RZUEUgPSBcInRva2VuX3R5cGVcIixcclxuICAgIFJFUV9DTkYgPSBcInJlcV9jbmZcIixcclxuICAgIE9CT19BU1NFUlRJT04gPSBcImFzc2VydGlvblwiLFxyXG4gICAgUkVRVUVTVEVEX1RPS0VOX1VTRSA9IFwicmVxdWVzdGVkX3Rva2VuX3VzZVwiLFxyXG4gICAgT05fQkVIQUxGX09GID0gXCJvbl9iZWhhbGZfb2ZcIixcclxuICAgIEZPQ0kgPSBcImZvY2lcIlxyXG59XHJcblxyXG4vKipcclxuICogQ2xhaW1zIHJlcXVlc3Qga2V5c1xyXG4gKi9cclxuZXhwb3J0IGVudW0gQ2xhaW1zUmVxdWVzdEtleXMge1xyXG4gICAgQUNDRVNTX1RPS0VOID0gXCJhY2Nlc3NfdG9rZW5cIixcclxuICAgIFhNU19DQyA9IFwieG1zX2NjXCJcclxufVxyXG5cclxuLyoqXHJcbiAqIHdlIGNvbnNpZGVyZWQgbWFraW5nIHRoaXMgXCJlbnVtXCIgaW4gdGhlIHJlcXVlc3QgaW5zdGVhZCBvZiBzdHJpbmcsIGhvd2V2ZXIgaXQgbG9va3MgbGlrZSB0aGUgYWxsb3dlZCBsaXN0IG9mXHJcbiAqIHByb21wdCB2YWx1ZXMga2VwdCBjaGFuZ2luZyBvdmVyIHBhc3QgY291cGxlIG9mIHllYXJzLiBUaGVyZSBhcmUgc29tZSB1bmRvY3VtZW50ZWQgcHJvbXB0IHZhbHVlcyBmb3Igc29tZVxyXG4gKiBpbnRlcm5hbCBwYXJ0bmVycyB0b28sIGhlbmNlIHRoZSBjaG9pY2Ugb2YgZ2VuZXJpYyBcInN0cmluZ1wiIHR5cGUgaW5zdGVhZCBvZiB0aGUgXCJlbnVtXCJcclxuICovXHJcbmV4cG9ydCBjb25zdCBQcm9tcHRWYWx1ZSA9IHtcclxuICAgIExPR0lOOiBcImxvZ2luXCIsXHJcbiAgICBTRUxFQ1RfQUNDT1VOVDogXCJzZWxlY3RfYWNjb3VudFwiLFxyXG4gICAgQ09OU0VOVDogXCJjb25zZW50XCIsXHJcbiAgICBOT05FOiBcIm5vbmVcIixcclxufTtcclxuXHJcbi8qKlxyXG4gKiBTU08gVHlwZXMgLSBnZW5lcmF0ZWQgdG8gcG9wdWxhdGUgaGludHNcclxuICovXHJcbmV4cG9ydCBlbnVtIFNTT1R5cGVzIHtcclxuICAgIEFDQ09VTlQgPSBcImFjY291bnRcIixcclxuICAgIFNJRCA9IFwic2lkXCIsXHJcbiAgICBMT0dJTl9ISU5UID0gXCJsb2dpbl9oaW50XCIsXHJcbiAgICBJRF9UT0tFTiA9IFwiaWRfdG9rZW5cIixcclxuICAgIERPTUFJTl9ISU5UID0gXCJkb21haW5faGludFwiLFxyXG4gICAgT1JHQU5JWkFUSU9OUyA9IFwib3JnYW5pemF0aW9uc1wiLFxyXG4gICAgQ09OU1VNRVJTID0gXCJjb25zdW1lcnNcIixcclxuICAgIEFDQ09VTlRfSUQgPSBcImFjY291bnRJZGVudGlmaWVyXCIsXHJcbiAgICBIT01FQUNDT1VOVF9JRCA9IFwiaG9tZUFjY291bnRJZGVudGlmaWVyXCJcclxufVxyXG5cclxuLyoqXHJcbiAqIERpc2FsbG93ZWQgZXh0cmEgcXVlcnkgcGFyYW1ldGVycy5cclxuICovXHJcbmV4cG9ydCBjb25zdCBCbGFja2xpc3RlZEVRUGFyYW1zID0gW1xyXG4gICAgU1NPVHlwZXMuU0lELFxyXG4gICAgU1NPVHlwZXMuTE9HSU5fSElOVFxyXG5dO1xyXG5cclxuLyoqXHJcbiAqIGFsbG93ZWQgdmFsdWVzIGZvciBjb2RlVmVyaWZpZXJcclxuICovXHJcbmV4cG9ydCBjb25zdCBDb2RlQ2hhbGxlbmdlTWV0aG9kVmFsdWVzID0ge1xyXG4gICAgUExBSU46IFwicGxhaW5cIixcclxuICAgIFMyNTY6IFwiUzI1NlwiXHJcbn07XHJcblxyXG4vKipcclxuICogVGhlIG1ldGhvZCB1c2VkIHRvIGVuY29kZSB0aGUgY29kZSB2ZXJpZmllciBmb3IgdGhlIGNvZGUgY2hhbGxlbmdlIHBhcmFtZXRlci4gY2FuIGJlIG9uZVxyXG4gKiBvZiBwbGFpbiBvciBzMjU2LiBpZiBleGNsdWRlZCwgY29kZSBjaGFsbGVuZ2UgaXMgYXNzdW1lZCB0byBiZSBwbGFpbnRleHQuIGZvciBtb3JlXHJcbiAqIGluZm9ybWF0aW9uLCBzZWUgdGhlIHBrY2UgcmNmOiBodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjNzYzNlxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IENvZGVDaGFsbGVuZ2VNZXRob2RWYWx1ZXNBcnJheTogc3RyaW5nW10gPSBbXHJcbiAgICBDb2RlQ2hhbGxlbmdlTWV0aG9kVmFsdWVzLlBMQUlOLFxyXG4gICAgQ29kZUNoYWxsZW5nZU1ldGhvZFZhbHVlcy5TMjU2XHJcbl07XHJcblxyXG4vKipcclxuICogYWxsb3dlZCB2YWx1ZXMgZm9yIHJlc3BvbnNlX21vZGVcclxuICovXHJcbmV4cG9ydCBlbnVtIFJlc3BvbnNlTW9kZSB7XHJcbiAgICBRVUVSWSA9IFwicXVlcnlcIixcclxuICAgIEZSQUdNRU5UID0gXCJmcmFnbWVudFwiLFxyXG4gICAgRk9STV9QT1NUID0gXCJmb3JtX3Bvc3RcIlxyXG59XHJcblxyXG4vKipcclxuICogYWxsb3dlZCBncmFudF90eXBlXHJcbiAqL1xyXG5leHBvcnQgZW51bSBHcmFudFR5cGUge1xyXG4gICAgSU1QTElDSVRfR1JBTlQgPSBcImltcGxpY2l0XCIsXHJcbiAgICBBVVRIT1JJWkFUSU9OX0NPREVfR1JBTlQgPSBcImF1dGhvcml6YXRpb25fY29kZVwiLFxyXG4gICAgQ0xJRU5UX0NSRURFTlRJQUxTX0dSQU5UID0gXCJjbGllbnRfY3JlZGVudGlhbHNcIixcclxuICAgIFJFU09VUkNFX09XTkVSX1BBU1NXT1JEX0dSQU5UID0gXCJwYXNzd29yZFwiLFxyXG4gICAgUkVGUkVTSF9UT0tFTl9HUkFOVCA9IFwicmVmcmVzaF90b2tlblwiLFxyXG4gICAgREVWSUNFX0NPREVfR1JBTlQgPSBcImRldmljZV9jb2RlXCIsXHJcbiAgICBKV1RfQkVBUkVSID0gXCJ1cm46aWV0ZjpwYXJhbXM6b2F1dGg6Z3JhbnQtdHlwZTpqd3QtYmVhcmVyXCJcclxufVxyXG5cclxuLyoqXHJcbiAqIEFjY291bnQgdHlwZXMgaW4gQ2FjaGVcclxuICovXHJcbmV4cG9ydCBlbnVtIENhY2hlQWNjb3VudFR5cGUge1xyXG4gICAgTVNTVFNfQUNDT1VOVF9UWVBFID0gXCJNU1NUU1wiLFxyXG4gICAgQURGU19BQ0NPVU5UX1RZUEUgPSBcIkFERlNcIixcclxuICAgIE1TQVYxX0FDQ09VTlRfVFlQRSA9IFwiTVNBXCIsXHJcbiAgICBHRU5FUklDX0FDQ09VTlRfVFlQRSA9IFwiR2VuZXJpY1wiIC8vIE5UTE0sIEtlcmJlcm9zLCBGQkEsIEJhc2ljIGV0Y1xyXG59XHJcblxyXG4vKipcclxuICogU2VwYXJhdG9ycyB1c2VkIGluIGNhY2hlXHJcbiAqL1xyXG5leHBvcnQgZW51bSBTZXBhcmF0b3JzIHtcclxuICAgIENBQ0hFX0tFWV9TRVBBUkFUT1IgPSBcIi1cIixcclxuICAgIENMSUVOVF9JTkZPX1NFUEFSQVRPUiA9IFwiLlwiXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDcmVkZW50aWFsIFR5cGUgc3RvcmVkIGluIHRoZSBjYWNoZVxyXG4gKi9cclxuZXhwb3J0IGVudW0gQ3JlZGVudGlhbFR5cGUge1xyXG4gICAgSURfVE9LRU4gPSBcIklkVG9rZW5cIixcclxuICAgIEFDQ0VTU19UT0tFTiA9IFwiQWNjZXNzVG9rZW5cIixcclxuICAgIFJFRlJFU0hfVE9LRU4gPSBcIlJlZnJlc2hUb2tlblwiLFxyXG59XHJcblxyXG4vKipcclxuICogQ3JlZGVudGlhbCBUeXBlIHN0b3JlZCBpbiB0aGUgY2FjaGVcclxuICovXHJcbmV4cG9ydCBlbnVtIENhY2hlU2NoZW1hVHlwZSB7XHJcbiAgICBBQ0NPVU5UID0gXCJBY2NvdW50XCIsXHJcbiAgICBDUkVERU5USUFMID0gXCJDcmVkZW50aWFsXCIsXHJcbiAgICBJRF9UT0tFTiA9IFwiSWRUb2tlblwiLFxyXG4gICAgQUNDRVNTX1RPS0VOID0gXCJBY2Nlc3NUb2tlblwiLFxyXG4gICAgUkVGUkVTSF9UT0tFTiA9IFwiUmVmcmVzaFRva2VuXCIsXHJcbiAgICBBUFBfTUVUQURBVEEgPSBcIkFwcE1ldGFkYXRhXCIsXHJcbiAgICBURU1QT1JBUlkgPSBcIlRlbXBDYWNoZVwiLFxyXG4gICAgVEVMRU1FVFJZID0gXCJUZWxlbWV0cnlcIixcclxuICAgIFVOREVGSU5FRCA9IFwiVW5kZWZpbmVkXCIsXHJcbiAgICBUSFJPVFRMSU5HID0gXCJUaHJvdHRsaW5nXCJcclxufVxyXG5cclxuLyoqXHJcbiAqIENvbWJpbmUgYWxsIGNhY2hlIHR5cGVzXHJcbiAqL1xyXG5leHBvcnQgZW51bSBDYWNoZVR5cGUge1xyXG4gICAgQURGUyA9IDEwMDEsXHJcbiAgICBNU0EgPSAxMDAyLFxyXG4gICAgTVNTVFMgPSAxMDAzLFxyXG4gICAgR0VORVJJQyA9IDEwMDQsXHJcbiAgICBBQ0NFU1NfVE9LRU4gPSAyMDAxLFxyXG4gICAgUkVGUkVTSF9UT0tFTiA9IDIwMDIsXHJcbiAgICBJRF9UT0tFTiA9IDIwMDMsXHJcbiAgICBBUFBfTUVUQURBVEEgPSAzMDAxLFxyXG4gICAgVU5ERUZJTkVEID0gOTk5OVxyXG59XHJcblxyXG4vKipcclxuICogTW9yZSBDYWNoZSByZWxhdGVkIGNvbnN0YW50c1xyXG4gKi9cclxuZXhwb3J0IGNvbnN0IEFQUF9NRVRBREFUQSA9IFwiYXBwbWV0YWRhdGFcIjtcclxuZXhwb3J0IGNvbnN0IENsaWVudEluZm8gPSBcImNsaWVudF9pbmZvXCI7XHJcbmV4cG9ydCBjb25zdCBUSEVfRkFNSUxZX0lEID0gXCIxXCI7XHJcblxyXG5leHBvcnQgY29uc3QgQVVUSE9SSVRZX01FVEFEQVRBX0NPTlNUQU5UUyA9IHtcclxuICAgIENBQ0hFX0tFWTogXCJhdXRob3JpdHktbWV0YWRhdGFcIixcclxuICAgIFJFRlJFU0hfVElNRV9TRUNPTkRTOiAzNjAwICogMjQgLy8gMjQgSG91cnNcclxufTtcclxuXHJcbmV4cG9ydCBlbnVtIEF1dGhvcml0eU1ldGFkYXRhU291cmNlIHtcclxuICAgIENPTkZJRyA9IFwiY29uZmlnXCIsXHJcbiAgICBDQUNIRSA9IFwiY2FjaGVcIixcclxuICAgIE5FVFdPUksgPSBcIm5ldHdvcmtcIlxyXG59XHJcblxyXG5leHBvcnQgY29uc3QgU0VSVkVSX1RFTEVNX0NPTlNUQU5UUyA9IHtcclxuICAgIFNDSEVNQV9WRVJTSU9OOiAyLFxyXG4gICAgTUFYX0hFQURFUl9CWVRFUzogNDAwMCwgLy8gTWF4IGlzIDRLQiwgNDAwMCBCeXRlcyBwcm92aWRlcyA5NiBCeXRlIGJ1ZmZlciBmb3Igc2VwYXJhdG9ycywgc2NoZW1hIHZlcnNpb24sIGV0Yy4gXHJcbiAgICBDQUNIRV9LRVk6IFwic2VydmVyLXRlbGVtZXRyeVwiLFxyXG4gICAgQ0FURUdPUllfU0VQQVJBVE9SOiBcInxcIixcclxuICAgIFZBTFVFX1NFUEFSQVRPUjogXCIsXCIsXHJcbiAgICBPVkVSRkxPV19UUlVFOiBcIjFcIixcclxuICAgIE9WRVJGTE9XX0ZBTFNFOiBcIjBcIixcclxuICAgIFVOS05PV05fRVJST1I6IFwidW5rbm93bl9lcnJvclwiXHJcbn07XHJcblxyXG4vKipcclxuICogVHlwZSBvZiB0aGUgYXV0aGVudGljYXRpb24gcmVxdWVzdFxyXG4gKi9cclxuZXhwb3J0IGVudW0gQXV0aGVudGljYXRpb25TY2hlbWUge1xyXG4gICAgUE9QID0gXCJwb3BcIixcclxuICAgIEJFQVJFUiA9IFwiQmVhcmVyXCJcclxufVxyXG5cclxuLyoqXHJcbiAqIENvbnN0YW50cyByZWxhdGVkIHRvIHRocm90dGxpbmdcclxuICovXHJcbmV4cG9ydCBjb25zdCBUaHJvdHRsaW5nQ29uc3RhbnRzID0ge1xyXG4gICAgLy8gRGVmYXVsdCB0aW1lIHRvIHRocm90dGxlIFJlcXVlc3RUaHVtYnByaW50IGluIHNlY29uZHNcclxuICAgIERFRkFVTFRfVEhST1RUTEVfVElNRV9TRUNPTkRTOiA2MCxcclxuICAgIC8vIERlZmF1bHQgbWF4aW11bSB0aW1lIHRvIHRocm90dGxlIGluIHNlY29uZHMsIG92ZXJyaWRlcyB3aGF0IHRoZSBzZXJ2ZXIgc2VuZHMgYmFja1xyXG4gICAgREVGQVVMVF9NQVhfVEhST1RUTEVfVElNRV9TRUNPTkRTOiAzNjAwLFxyXG4gICAgLy8gUHJlZml4IGZvciBzdG9yaW5nIHRocm90dGxpbmcgZW50cmllc1xyXG4gICAgVEhST1RUTElOR19QUkVGSVg6IFwidGhyb3R0bGluZ1wiXHJcbn07XHJcblxyXG5leHBvcnQgY29uc3QgRXJyb3JzID0ge1xyXG4gICAgSU5WQUxJRF9HUkFOVF9FUlJPUjogXCJpbnZhbGlkX2dyYW50XCIsXHJcbiAgICBDTElFTlRfTUlTTUFUQ0hfRVJST1I6IFwiY2xpZW50X21pc21hdGNoXCIsXHJcbn07XHJcblxyXG4vKipcclxuICogUGFzc3dvcmQgZ3JhbnQgcGFyYW1ldGVyc1xyXG4gKi9cclxuZXhwb3J0IGVudW0gUGFzc3dvcmRHcmFudENvbnN0YW50cyB7XHJcbiAgICB1c2VybmFtZSA9IFwidXNlcm5hbWVcIixcclxuICAgIHBhc3N3b3JkID0gXCJwYXNzd29yZFwiXHJcbn1cclxuIiwiLypcclxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cclxuICovXHJcblxyXG5pbXBvcnQgeyBDb25zdGFudHMgfSBmcm9tIFwiLi4vdXRpbHMvQ29uc3RhbnRzXCI7XHJcblxyXG4vKipcclxuICogQXV0aEVycm9yTWVzc2FnZSBjbGFzcyBjb250YWluaW5nIHN0cmluZyBjb25zdGFudHMgdXNlZCBieSBlcnJvciBjb2RlcyBhbmQgbWVzc2FnZXMuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgQXV0aEVycm9yTWVzc2FnZSA9IHtcclxuICAgIHVuZXhwZWN0ZWRFcnJvcjoge1xyXG4gICAgICAgIGNvZGU6IFwidW5leHBlY3RlZF9lcnJvclwiLFxyXG4gICAgICAgIGRlc2M6IFwiVW5leHBlY3RlZCBlcnJvciBpbiBhdXRoZW50aWNhdGlvbi5cIlxyXG4gICAgfVxyXG59O1xyXG5cclxuLyoqXHJcbiAqIEdlbmVyYWwgZXJyb3IgY2xhc3MgdGhyb3duIGJ5IHRoZSBNU0FMLmpzIGxpYnJhcnkuXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgQXV0aEVycm9yIGV4dGVuZHMgRXJyb3Ige1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2hvcnQgc3RyaW5nIGRlbm90aW5nIGVycm9yXHJcbiAgICAgKi9cclxuICAgIGVycm9yQ29kZTogc3RyaW5nO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGV0YWlsZWQgZGVzY3JpcHRpb24gb2YgZXJyb3JcclxuICAgICAqL1xyXG4gICAgZXJyb3JNZXNzYWdlOiBzdHJpbmc7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZXNjcmliZXMgdGhlIHN1YmNsYXNzIG9mIGFuIGVycm9yXHJcbiAgICAgKi9cclxuICAgIHN1YkVycm9yOiBzdHJpbmc7XHJcblxyXG4gICAgY29uc3RydWN0b3IoZXJyb3JDb2RlPzogc3RyaW5nLCBlcnJvck1lc3NhZ2U/OiBzdHJpbmcsIHN1YmVycm9yPzogc3RyaW5nKSB7XHJcbiAgICAgICAgY29uc3QgZXJyb3JTdHJpbmcgPSBlcnJvck1lc3NhZ2UgPyBgJHtlcnJvckNvZGV9OiAke2Vycm9yTWVzc2FnZX1gIDogZXJyb3JDb2RlO1xyXG4gICAgICAgIHN1cGVyKGVycm9yU3RyaW5nKTtcclxuICAgICAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgQXV0aEVycm9yLnByb3RvdHlwZSk7XHJcblxyXG4gICAgICAgIHRoaXMuZXJyb3JDb2RlID0gZXJyb3JDb2RlIHx8IENvbnN0YW50cy5FTVBUWV9TVFJJTkc7XHJcbiAgICAgICAgdGhpcy5lcnJvck1lc3NhZ2UgPSBlcnJvck1lc3NhZ2UgfHwgXCJcIjtcclxuICAgICAgICB0aGlzLnN1YkVycm9yID0gc3ViZXJyb3IgfHwgXCJcIjtcclxuICAgICAgICB0aGlzLm5hbWUgPSBcIkF1dGhFcnJvclwiO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlcyBhbiBlcnJvciB0aGF0IGlzIHRocm93biB3aGVuIHNvbWV0aGluZyB1bmV4cGVjdGVkIGhhcHBlbnMgaW4gdGhlIGxpYnJhcnkuXHJcbiAgICAgKiBAcGFyYW0gZXJyRGVzY1xyXG4gICAgICovXHJcbiAgICBzdGF0aWMgY3JlYXRlVW5leHBlY3RlZEVycm9yKGVyckRlc2M6IHN0cmluZyk6IEF1dGhFcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBBdXRoRXJyb3IoQXV0aEVycm9yTWVzc2FnZS51bmV4cGVjdGVkRXJyb3IuY29kZSwgYCR7QXV0aEVycm9yTWVzc2FnZS51bmV4cGVjdGVkRXJyb3IuZGVzY306ICR7ZXJyRGVzY31gKTtcclxuICAgIH1cclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IEF1dGhFcnJvciB9IGZyb20gXCIuLi9lcnJvci9BdXRoRXJyb3JcIjtcclxuaW1wb3J0IHsgU2lnbmVkSHR0cFJlcXVlc3QgfSBmcm9tIFwiLi9TaWduZWRIdHRwUmVxdWVzdFwiO1xyXG5cclxuLyoqXHJcbiAqIFRoZSBQa2NlQ29kZXMgdHlwZSBkZXNjcmliZXMgdGhlIHN0cnVjdHVyZVxyXG4gKiBvZiBvYmplY3RzIHRoYXQgY29udGFpbiBQS0NFIGNvZGVcclxuICogY2hhbGxlbmdlIGFuZCB2ZXJpZmllciBwYWlyc1xyXG4gKi9cclxuZXhwb3J0IHR5cGUgUGtjZUNvZGVzID0ge1xyXG4gICAgdmVyaWZpZXI6IHN0cmluZyxcclxuICAgIGNoYWxsZW5nZTogc3RyaW5nXHJcbn07XHJcblxyXG4vKipcclxuICogSW50ZXJmYWNlIGZvciBjcnlwdG8gZnVuY3Rpb25zIHVzZWQgYnkgbGlicmFyeVxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBJQ3J5cHRvIHtcclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlcyBhIGd1aWQgcmFuZG9tbHkuXHJcbiAgICAgKi9cclxuICAgIGNyZWF0ZU5ld0d1aWQoKTogc3RyaW5nO1xyXG4gICAgLyoqXHJcbiAgICAgKiBiYXNlNjQgRW5jb2RlIHN0cmluZ1xyXG4gICAgICogQHBhcmFtIGlucHV0IFxyXG4gICAgICovXHJcbiAgICBiYXNlNjRFbmNvZGUoaW5wdXQ6IHN0cmluZyk6IHN0cmluZztcclxuICAgIC8qKlxyXG4gICAgICogYmFzZTY0IGRlY29kZSBzdHJpbmdcclxuICAgICAqIEBwYXJhbSBpbnB1dCBcclxuICAgICAqL1xyXG4gICAgYmFzZTY0RGVjb2RlKGlucHV0OiBzdHJpbmcpOiBzdHJpbmc7XHJcbiAgICAvKipcclxuICAgICAqIEdlbmVyYXRlIFBLQ0UgY29kZXMgZm9yIE9BdXRoLiBTZWUgUkZDIGhlcmU6IGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM3NjM2XHJcbiAgICAgKi9cclxuICAgIGdlbmVyYXRlUGtjZUNvZGVzKCk6IFByb21pc2U8UGtjZUNvZGVzPjtcclxuICAgIC8qKlxyXG4gICAgICogR2VuZXJhdGVzIGFuIEpXSyBSU0EgUzI1NiBUaHVtYnByaW50XHJcbiAgICAgKiBAcGFyYW0gcmVzb3VyY2VSZXF1ZXN0TWV0aG9kIFxyXG4gICAgICogQHBhcmFtIHJlc291cmNlUmVxdWVzdFVyaSBcclxuICAgICAqL1xyXG4gICAgZ2V0UHVibGljS2V5VGh1bWJwcmludChyZXNvdXJjZVJlcXVlc3RNZXRob2Q6IHN0cmluZywgcmVzb3VyY2VSZXF1ZXN0VXJpOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz47XHJcbiAgICAvKiogXHJcbiAgICAgKiBSZXR1cm5zIGEgc2lnbmVkIHByb29mLW9mLXBvc3Nlc3Npb24gdG9rZW4gd2l0aCBhIGdpdmVuIGFjY2VzIHRva2VuIHRoYXQgY29udGFpbnMgYSBjbmYgY2xhaW0gd2l0aCB0aGUgcmVxdWlyZWQga2lkLlxyXG4gICAgICogQHBhcmFtIGFjY2Vzc1Rva2VuIFxyXG4gICAgICovXHJcbiAgICBzaWduSnd0KHBheWxvYWQ6IFNpZ25lZEh0dHBSZXF1ZXN0LCBraWQ6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPjtcclxufVxyXG5cclxuZXhwb3J0IGNvbnN0IERFRkFVTFRfQ1JZUFRPX0lNUExFTUVOVEFUSU9OOiBJQ3J5cHRvID0ge1xyXG4gICAgY3JlYXRlTmV3R3VpZDogKCk6IHN0cmluZyA9PiB7XHJcbiAgICAgICAgY29uc3Qgbm90SW1wbEVyciA9IFwiQ3J5cHRvIGludGVyZmFjZSAtIGNyZWF0ZU5ld0d1aWQoKSBoYXMgbm90IGJlZW4gaW1wbGVtZW50ZWRcIjtcclxuICAgICAgICB0aHJvdyBBdXRoRXJyb3IuY3JlYXRlVW5leHBlY3RlZEVycm9yKG5vdEltcGxFcnIpO1xyXG4gICAgfSxcclxuICAgIGJhc2U2NERlY29kZTogKCk6IHN0cmluZyA9PiB7XHJcbiAgICAgICAgY29uc3Qgbm90SW1wbEVyciA9IFwiQ3J5cHRvIGludGVyZmFjZSAtIGJhc2U2NERlY29kZSgpIGhhcyBub3QgYmVlbiBpbXBsZW1lbnRlZFwiO1xyXG4gICAgICAgIHRocm93IEF1dGhFcnJvci5jcmVhdGVVbmV4cGVjdGVkRXJyb3Iobm90SW1wbEVycik7XHJcbiAgICB9LFxyXG4gICAgYmFzZTY0RW5jb2RlOiAoKTogc3RyaW5nID0+IHtcclxuICAgICAgICBjb25zdCBub3RJbXBsRXJyID0gXCJDcnlwdG8gaW50ZXJmYWNlIC0gYmFzZTY0RW5jb2RlKCkgaGFzIG5vdCBiZWVuIGltcGxlbWVudGVkXCI7XHJcbiAgICAgICAgdGhyb3cgQXV0aEVycm9yLmNyZWF0ZVVuZXhwZWN0ZWRFcnJvcihub3RJbXBsRXJyKTtcclxuICAgIH0sXHJcbiAgICBhc3luYyBnZW5lcmF0ZVBrY2VDb2RlcygpOiBQcm9taXNlPFBrY2VDb2Rlcz4ge1xyXG4gICAgICAgIGNvbnN0IG5vdEltcGxFcnIgPSBcIkNyeXB0byBpbnRlcmZhY2UgLSBnZW5lcmF0ZVBrY2VDb2RlcygpIGhhcyBub3QgYmVlbiBpbXBsZW1lbnRlZFwiO1xyXG4gICAgICAgIHRocm93IEF1dGhFcnJvci5jcmVhdGVVbmV4cGVjdGVkRXJyb3Iobm90SW1wbEVycik7XHJcbiAgICB9LFxyXG4gICAgYXN5bmMgZ2V0UHVibGljS2V5VGh1bWJwcmludCgpOiBQcm9taXNlPHN0cmluZz4ge1xyXG4gICAgICAgIGNvbnN0IG5vdEltcGxFcnIgPSBcIkNyeXB0byBpbnRlcmZhY2UgLSBnZXRQdWJsaWNLZXlUaHVtYnByaW50KCkgaGFzIG5vdCBiZWVuIGltcGxlbWVudGVkXCI7XHJcbiAgICAgICAgdGhyb3cgQXV0aEVycm9yLmNyZWF0ZVVuZXhwZWN0ZWRFcnJvcihub3RJbXBsRXJyKTtcclxuICAgIH0sXHJcbiAgICBhc3luYyBzaWduSnd0KCk6IFByb21pc2U8c3RyaW5nPiB7XHJcbiAgICAgICAgY29uc3Qgbm90SW1wbEVyciA9IFwiQ3J5cHRvIGludGVyZmFjZSAtIHNpZ25Kd3QoKSBoYXMgbm90IGJlZW4gaW1wbGVtZW50ZWRcIjtcclxuICAgICAgICB0aHJvdyBBdXRoRXJyb3IuY3JlYXRlVW5leHBlY3RlZEVycm9yKG5vdEltcGxFcnIpO1xyXG4gICAgfVxyXG59O1xyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IEF1dGhFcnJvciB9IGZyb20gXCIuL0F1dGhFcnJvclwiO1xyXG5pbXBvcnQgeyBTY29wZVNldCB9IGZyb20gXCIuLi9yZXF1ZXN0L1Njb3BlU2V0XCI7XHJcblxyXG4vKipcclxuICogQ2xpZW50QXV0aEVycm9yTWVzc2FnZSBjbGFzcyBjb250YWluaW5nIHN0cmluZyBjb25zdGFudHMgdXNlZCBieSBlcnJvciBjb2RlcyBhbmQgbWVzc2FnZXMuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgQ2xpZW50QXV0aEVycm9yTWVzc2FnZSA9IHtcclxuICAgIGNsaWVudEluZm9EZWNvZGluZ0Vycm9yOiB7XHJcbiAgICAgICAgY29kZTogXCJjbGllbnRfaW5mb19kZWNvZGluZ19lcnJvclwiLFxyXG4gICAgICAgIGRlc2M6IFwiVGhlIGNsaWVudCBpbmZvIGNvdWxkIG5vdCBiZSBwYXJzZWQvZGVjb2RlZCBjb3JyZWN0bHkuIFBsZWFzZSByZXZpZXcgdGhlIHRyYWNlIHRvIGRldGVybWluZSB0aGUgcm9vdCBjYXVzZS5cIlxyXG4gICAgfSxcclxuICAgIGNsaWVudEluZm9FbXB0eUVycm9yOiB7XHJcbiAgICAgICAgY29kZTogXCJjbGllbnRfaW5mb19lbXB0eV9lcnJvclwiLFxyXG4gICAgICAgIGRlc2M6IFwiVGhlIGNsaWVudCBpbmZvIHdhcyBlbXB0eS4gUGxlYXNlIHJldmlldyB0aGUgdHJhY2UgdG8gZGV0ZXJtaW5lIHRoZSByb290IGNhdXNlLlwiXHJcbiAgICB9LFxyXG4gICAgdG9rZW5QYXJzaW5nRXJyb3I6IHtcclxuICAgICAgICBjb2RlOiBcInRva2VuX3BhcnNpbmdfZXJyb3JcIixcclxuICAgICAgICBkZXNjOiBcIlRva2VuIGNhbm5vdCBiZSBwYXJzZWQuIFBsZWFzZSByZXZpZXcgc3RhY2sgdHJhY2UgdG8gZGV0ZXJtaW5lIHJvb3QgY2F1c2UuXCJcclxuICAgIH0sXHJcbiAgICBudWxsT3JFbXB0eVRva2VuOiB7XHJcbiAgICAgICAgY29kZTogXCJudWxsX29yX2VtcHR5X3Rva2VuXCIsXHJcbiAgICAgICAgZGVzYzogXCJUaGUgdG9rZW4gaXMgbnVsbCBvciBlbXB0eS4gUGxlYXNlIHJldmlldyB0aGUgdHJhY2UgdG8gZGV0ZXJtaW5lIHRoZSByb290IGNhdXNlLlwiXHJcbiAgICB9LFxyXG4gICAgZW5kcG9pbnRSZXNvbHV0aW9uRXJyb3I6IHtcclxuICAgICAgICBjb2RlOiBcImVuZHBvaW50c19yZXNvbHV0aW9uX2Vycm9yXCIsXHJcbiAgICAgICAgZGVzYzogXCJFcnJvcjogY291bGQgbm90IHJlc29sdmUgZW5kcG9pbnRzLiBQbGVhc2UgY2hlY2sgbmV0d29yayBhbmQgdHJ5IGFnYWluLlwiXHJcbiAgICB9LFxyXG4gICAgdW5hYmxlVG9HZXRPcGVuaWRDb25maWdFcnJvcjoge1xyXG4gICAgICAgIGNvZGU6IFwib3BlbmlkX2NvbmZpZ19lcnJvclwiLFxyXG4gICAgICAgIGRlc2M6IFwiQ291bGQgbm90IHJldHJpZXZlIGVuZHBvaW50cy4gQ2hlY2sgeW91ciBhdXRob3JpdHkgYW5kIHZlcmlmeSB0aGUgLndlbGwta25vd24vb3BlbmlkLWNvbmZpZ3VyYXRpb24gZW5kcG9pbnQgcmV0dXJucyB0aGUgcmVxdWlyZWQgZW5kcG9pbnRzLlwiXHJcbiAgICB9LFxyXG4gICAgaGFzaE5vdERlc2VyaWFsaXplZDoge1xyXG4gICAgICAgIGNvZGU6IFwiaGFzaF9ub3RfZGVzZXJpYWxpemVkXCIsXHJcbiAgICAgICAgZGVzYzogXCJUaGUgaGFzaCBwYXJhbWV0ZXJzIGNvdWxkIG5vdCBiZSBkZXNlcmlhbGl6ZWQuIFBsZWFzZSByZXZpZXcgdGhlIHRyYWNlIHRvIGRldGVybWluZSB0aGUgcm9vdCBjYXVzZS5cIlxyXG4gICAgfSxcclxuICAgIGJsYW5rR3VpZEdlbmVyYXRlZDoge1xyXG4gICAgICAgIGNvZGU6IFwiYmxhbmtfZ3VpZF9nZW5lcmF0ZWRcIixcclxuICAgICAgICBkZXNjOiBcIlRoZSBndWlkIGdlbmVyYXRlZCB3YXMgYmxhbmsuIFBsZWFzZSByZXZpZXcgdGhlIHRyYWNlIHRvIGRldGVybWluZSB0aGUgcm9vdCBjYXVzZS5cIlxyXG4gICAgfSxcclxuICAgIGludmFsaWRTdGF0ZUVycm9yOiB7XHJcbiAgICAgICAgY29kZTogXCJpbnZhbGlkX3N0YXRlXCIsXHJcbiAgICAgICAgZGVzYzogXCJTdGF0ZSB3YXMgbm90IHRoZSBleHBlY3RlZCBmb3JtYXQuIFBsZWFzZSBjaGVjayB0aGUgbG9ncyB0byBkZXRlcm1pbmUgd2hldGhlciB0aGUgcmVxdWVzdCB3YXMgc2VudCB1c2luZyBQcm90b2NvbFV0aWxzLnNldFJlcXVlc3RTdGF0ZSgpLlwiXHJcbiAgICB9LFxyXG4gICAgc3RhdGVNaXNtYXRjaEVycm9yOiB7XHJcbiAgICAgICAgY29kZTogXCJzdGF0ZV9taXNtYXRjaFwiLFxyXG4gICAgICAgIGRlc2M6IFwiU3RhdGUgbWlzbWF0Y2ggZXJyb3IuIFBsZWFzZSBjaGVjayB5b3VyIG5ldHdvcmsuIENvbnRpbnVlZCByZXF1ZXN0cyBtYXkgY2F1c2UgY2FjaGUgb3ZlcmZsb3cuXCJcclxuICAgIH0sXHJcbiAgICBzdGF0ZU5vdEZvdW5kRXJyb3I6IHtcclxuICAgICAgICBjb2RlOiBcInN0YXRlX25vdF9mb3VuZFwiLFxyXG4gICAgICAgIGRlc2M6IFwiU3RhdGUgbm90IGZvdW5kXCJcclxuICAgIH0sXHJcbiAgICBub25jZU1pc21hdGNoRXJyb3I6IHtcclxuICAgICAgICBjb2RlOiBcIm5vbmNlX21pc21hdGNoXCIsXHJcbiAgICAgICAgZGVzYzogXCJOb25jZSBtaXNtYXRjaCBlcnJvci4gVGhpcyBtYXkgYmUgY2F1c2VkIGJ5IGEgcmFjZSBjb25kaXRpb24gaW4gY29uY3VycmVudCByZXF1ZXN0cy5cIlxyXG4gICAgfSxcclxuICAgIG5vbmNlTm90Rm91bmRFcnJvcjoge1xyXG4gICAgICAgIGNvZGU6IFwibm9uY2Vfbm90X2ZvdW5kXCIsXHJcbiAgICAgICAgZGVzYzogXCJub25jZSBub3QgZm91bmRcIlxyXG4gICAgfSxcclxuICAgIG5vVG9rZW5zRm91bmRFcnJvcjoge1xyXG4gICAgICAgIGNvZGU6IFwibm9fdG9rZW5zX2ZvdW5kXCIsXHJcbiAgICAgICAgZGVzYzogXCJObyB0b2tlbnMgd2VyZSBmb3VuZCBmb3IgdGhlIGdpdmVuIHNjb3BlcywgYW5kIG5vIGF1dGhvcml6YXRpb24gY29kZSB3YXMgcGFzc2VkIHRvIGFjcXVpcmVUb2tlbi4gWW91IG11c3QgcmV0cmlldmUgYW4gYXV0aG9yaXphdGlvbiBjb2RlIGJlZm9yZSBtYWtpbmcgYSBjYWxsIHRvIGFjcXVpcmVUb2tlbigpLlwiXHJcbiAgICB9LFxyXG4gICAgbXVsdGlwbGVNYXRjaGluZ1Rva2Vuczoge1xyXG4gICAgICAgIGNvZGU6IFwibXVsdGlwbGVfbWF0Y2hpbmdfdG9rZW5zXCIsXHJcbiAgICAgICAgZGVzYzogXCJUaGUgY2FjaGUgY29udGFpbnMgbXVsdGlwbGUgdG9rZW5zIHNhdGlzZnlpbmcgdGhlIHJlcXVpcmVtZW50cy4gXCIgK1xyXG4gICAgICAgICAgICBcIkNhbGwgQWNxdWlyZVRva2VuIGFnYWluIHByb3ZpZGluZyBtb3JlIHJlcXVpcmVtZW50cyBzdWNoIGFzIGF1dGhvcml0eSBvciBhY2NvdW50LlwiXHJcbiAgICB9LFxyXG4gICAgbXVsdGlwbGVNYXRjaGluZ0FjY291bnRzOiB7XHJcbiAgICAgICAgY29kZTogXCJtdWx0aXBsZV9tYXRjaGluZ19hY2NvdW50c1wiLFxyXG4gICAgICAgIGRlc2M6IFwiVGhlIGNhY2hlIGNvbnRhaW5zIG11bHRpcGxlIGFjY291bnRzIHNhdGlzZnlpbmcgdGhlIGdpdmVuIHBhcmFtZXRlcnMuIFBsZWFzZSBwYXNzIG1vcmUgaW5mbyB0byBvYnRhaW4gdGhlIGNvcnJlY3QgYWNjb3VudFwiXHJcbiAgICB9LFxyXG4gICAgbXVsdGlwbGVNYXRjaGluZ0FwcE1ldGFkYXRhOiB7XHJcbiAgICAgICAgY29kZTogXCJtdWx0aXBsZV9tYXRjaGluZ19hcHBNZXRhZGF0YVwiLFxyXG4gICAgICAgIGRlc2M6IFwiVGhlIGNhY2hlIGNvbnRhaW5zIG11bHRpcGxlIGFwcE1ldGFkYXRhIHNhdGlzZnlpbmcgdGhlIGdpdmVuIHBhcmFtZXRlcnMuIFBsZWFzZSBwYXNzIG1vcmUgaW5mbyB0byBvYnRhaW4gdGhlIGNvcnJlY3QgYXBwTWV0YWRhdGFcIlxyXG4gICAgfSxcclxuICAgIHRva2VuUmVxdWVzdENhbm5vdEJlTWFkZToge1xyXG4gICAgICAgIGNvZGU6IFwicmVxdWVzdF9jYW5ub3RfYmVfbWFkZVwiLFxyXG4gICAgICAgIGRlc2M6IFwiVG9rZW4gcmVxdWVzdCBjYW5ub3QgYmUgbWFkZSB3aXRob3V0IGF1dGhvcml6YXRpb24gY29kZSBvciByZWZyZXNoIHRva2VuLlwiXHJcbiAgICB9LFxyXG4gICAgYXBwZW5kRW1wdHlTY29wZUVycm9yOiB7XHJcbiAgICAgICAgY29kZTogXCJjYW5ub3RfYXBwZW5kX2VtcHR5X3Njb3BlXCIsXHJcbiAgICAgICAgZGVzYzogXCJDYW5ub3QgYXBwZW5kIG51bGwgb3IgZW1wdHkgc2NvcGUgdG8gU2NvcGVTZXQuIFBsZWFzZSBjaGVjayB0aGUgc3RhY2sgdHJhY2UgZm9yIG1vcmUgaW5mby5cIlxyXG4gICAgfSxcclxuICAgIHJlbW92ZUVtcHR5U2NvcGVFcnJvcjoge1xyXG4gICAgICAgIGNvZGU6IFwiY2Fubm90X3JlbW92ZV9lbXB0eV9zY29wZVwiLFxyXG4gICAgICAgIGRlc2M6IFwiQ2Fubm90IHJlbW92ZSBudWxsIG9yIGVtcHR5IHNjb3BlIGZyb20gU2NvcGVTZXQuIFBsZWFzZSBjaGVjayB0aGUgc3RhY2sgdHJhY2UgZm9yIG1vcmUgaW5mby5cIlxyXG4gICAgfSxcclxuICAgIGFwcGVuZFNjb3BlU2V0RXJyb3I6IHtcclxuICAgICAgICBjb2RlOiBcImNhbm5vdF9hcHBlbmRfc2NvcGVzZXRcIixcclxuICAgICAgICBkZXNjOiBcIkNhbm5vdCBhcHBlbmQgU2NvcGVTZXQgZHVlIHRvIGVycm9yLlwiXHJcbiAgICB9LFxyXG4gICAgZW1wdHlJbnB1dFNjb3BlU2V0RXJyb3I6IHtcclxuICAgICAgICBjb2RlOiBcImVtcHR5X2lucHV0X3Njb3Blc2V0XCIsXHJcbiAgICAgICAgZGVzYzogXCJFbXB0eSBpbnB1dCBTY29wZVNldCBjYW5ub3QgYmUgcHJvY2Vzc2VkLlwiXHJcbiAgICB9LFxyXG4gICAgRGV2aWNlQ29kZVBvbGxpbmdDYW5jZWxsZWQ6IHtcclxuICAgICAgICBjb2RlOiBcImRldmljZV9jb2RlX3BvbGxpbmdfY2FuY2VsbGVkXCIsXHJcbiAgICAgICAgZGVzYzogXCJDYWxsZXIgaGFzIGNhbmNlbGxlZCB0b2tlbiBlbmRwb2ludCBwb2xsaW5nIGR1cmluZyBkZXZpY2UgY29kZSBmbG93IGJ5IHNldHRpbmcgRGV2aWNlQ29kZVJlcXVlc3QuY2FuY2VsID0gdHJ1ZS5cIlxyXG4gICAgfSxcclxuICAgIERldmljZUNvZGVFeHBpcmVkOiB7XHJcbiAgICAgICAgY29kZTogXCJkZXZpY2VfY29kZV9leHBpcmVkXCIsXHJcbiAgICAgICAgZGVzYzogXCJEZXZpY2UgY29kZSBpcyBleHBpcmVkLlwiXHJcbiAgICB9LFxyXG4gICAgTm9BY2NvdW50SW5TaWxlbnRSZXF1ZXN0OiB7XHJcbiAgICAgICAgY29kZTogXCJub19hY2NvdW50X2luX3NpbGVudF9yZXF1ZXN0XCIsXHJcbiAgICAgICAgZGVzYzogXCJQbGVhc2UgcGFzcyBhbiBhY2NvdW50IG9iamVjdCwgc2lsZW50IGZsb3cgaXMgbm90IHN1cHBvcnRlZCB3aXRob3V0IGFjY291bnQgaW5mb3JtYXRpb25cIlxyXG4gICAgfSxcclxuICAgIGludmFsaWRDYWNoZVJlY29yZDoge1xyXG4gICAgICAgIGNvZGU6IFwiaW52YWxpZF9jYWNoZV9yZWNvcmRcIixcclxuICAgICAgICBkZXNjOiBcIkNhY2hlIHJlY29yZCBvYmplY3Qgd2FzIG51bGwgb3IgdW5kZWZpbmVkLlwiXHJcbiAgICB9LFxyXG4gICAgaW52YWxpZENhY2hlRW52aXJvbm1lbnQ6IHtcclxuICAgICAgICBjb2RlOiBcImludmFsaWRfY2FjaGVfZW52aXJvbm1lbnRcIixcclxuICAgICAgICBkZXNjOiBcIkludmFsaWQgZW52aXJvbm1lbnQgd2hlbiBhdHRlbXB0aW5nIHRvIGNyZWF0ZSBjYWNoZSBlbnRyeVwiXHJcbiAgICB9LFxyXG4gICAgbm9BY2NvdW50Rm91bmQ6IHtcclxuICAgICAgICBjb2RlOiBcIm5vX2FjY291bnRfZm91bmRcIixcclxuICAgICAgICBkZXNjOiBcIk5vIGFjY291bnQgZm91bmQgaW4gY2FjaGUgZm9yIGdpdmVuIGtleS5cIlxyXG4gICAgfSxcclxuICAgIENhY2hlUGx1Z2luRXJyb3I6IHtcclxuICAgICAgICBjb2RlOiBcIm5vIGNhY2hlIHBsdWdpbiBzZXQgb24gQ2FjaGVNYW5hZ2VyXCIsXHJcbiAgICAgICAgZGVzYzogXCJJQ2FjaGVQbHVnaW4gbmVlZHMgdG8gYmUgc2V0IGJlZm9yZSB1c2luZyByZWFkRnJvbVN0b3JhZ2Ugb3Igd3JpdGVGcm9tU3RvcmFnZVwiXHJcbiAgICB9LFxyXG4gICAgbm9DcnlwdG9PYmo6IHtcclxuICAgICAgICBjb2RlOiBcIm5vX2NyeXB0b19vYmplY3RcIixcclxuICAgICAgICBkZXNjOiBcIk5vIGNyeXB0byBvYmplY3QgZGV0ZWN0ZWQuIFRoaXMgaXMgcmVxdWlyZWQgZm9yIHRoZSBmb2xsb3dpbmcgb3BlcmF0aW9uOiBcIlxyXG4gICAgfSxcclxuICAgIGludmFsaWRDYWNoZVR5cGU6IHtcclxuICAgICAgICBjb2RlOiBcImludmFsaWRfY2FjaGVfdHlwZVwiLFxyXG4gICAgICAgIGRlc2M6IFwiSW52YWxpZCBjYWNoZSB0eXBlXCJcclxuICAgIH0sXHJcbiAgICB1bmV4cGVjdGVkQWNjb3VudFR5cGU6IHtcclxuICAgICAgICBjb2RlOiBcInVuZXhwZWN0ZWRfYWNjb3VudF90eXBlXCIsXHJcbiAgICAgICAgZGVzYzogXCJVbmV4cGVjdGVkIGFjY291bnQgdHlwZS5cIlxyXG4gICAgfSxcclxuICAgIHVuZXhwZWN0ZWRDcmVkZW50aWFsVHlwZToge1xyXG4gICAgICAgIGNvZGU6IFwidW5leHBlY3RlZF9jcmVkZW50aWFsX3R5cGVcIixcclxuICAgICAgICBkZXNjOiBcIlVuZXhwZWN0ZWQgY3JlZGVudGlhbCB0eXBlLlwiXHJcbiAgICB9LFxyXG4gICAgaW52YWxpZEFzc2VydGlvbjoge1xyXG4gICAgICAgIGNvZGU6IFwiaW52YWxpZF9hc3NlcnRpb25cIixcclxuICAgICAgICBkZXNjOiBcIkNsaWVudCBhc3NlcnRpb24gbXVzdCBtZWV0IHJlcXVpcmVtZW50cyBkZXNjcmliZWQgaW4gaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzc1MTVcIlxyXG4gICAgfSxcclxuICAgIGludmFsaWRDbGllbnRDcmVkZW50aWFsOiB7XHJcbiAgICAgICAgY29kZTogXCJpbnZhbGlkX2NsaWVudF9jcmVkZW50aWFsXCIsXHJcbiAgICAgICAgZGVzYzogXCJDbGllbnQgY3JlZGVudGlhbCAoc2VjcmV0LCBjZXJ0aWZpY2F0ZSwgb3IgYXNzZXJ0aW9uKSBtdXN0IG5vdCBiZSBlbXB0eSB3aGVuIGNyZWF0aW5nIGEgY29uZmlkZW50aWFsIGNsaWVudC4gQW4gYXBwbGljYXRpb24gc2hvdWxkIGF0IG1vc3QgaGF2ZSBvbmUgY3JlZGVudGlhbFwiXHJcbiAgICB9LFxyXG4gICAgdG9rZW5SZWZyZXNoUmVxdWlyZWQ6IHtcclxuICAgICAgICBjb2RlOiBcInRva2VuX3JlZnJlc2hfcmVxdWlyZWRcIixcclxuICAgICAgICBkZXNjOiBcIkNhbm5vdCByZXR1cm4gdG9rZW4gZnJvbSBjYWNoZSBiZWNhdXNlIGl0IG11c3QgYmUgcmVmcmVzaGVkLiBUaGlzIG1heSBiZSBkdWUgdG8gb25lIG9mIHRoZSBmb2xsb3dpbmcgcmVhc29uczogZm9yY2VSZWZyZXNoIHBhcmFtZXRlciBpcyBzZXQgdG8gdHJ1ZSwgY2xhaW1zIGhhdmUgYmVlbiByZXF1ZXN0ZWQsIHRoZXJlIGlzIG5vIGNhY2hlZCBhY2Nlc3MgdG9rZW4gb3IgaXQgaXMgZXhwaXJlZC5cIlxyXG4gICAgfSxcclxuICAgIHVzZXJUaW1lb3V0UmVhY2hlZDoge1xyXG4gICAgICAgIGNvZGU6IFwidXNlcl90aW1lb3V0X3JlYWNoZWRcIixcclxuICAgICAgICBkZXNjOiBcIlVzZXIgZGVmaW5lZCB0aW1lb3V0IGZvciBkZXZpY2UgY29kZSBwb2xsaW5nIHJlYWNoZWRcIixcclxuICAgIH0sXHJcbiAgICB0b2tlbkNsYWltc1JlcXVpcmVkOiB7XHJcbiAgICAgICAgY29kZTogXCJ0b2tlbl9jbGFpbXNfY25mX3JlcXVpcmVkX2Zvcl9zaWduZWRqd3RcIixcclxuICAgICAgICBkZXNjOiBcIkNhbm5vdCBnZW5lcmF0ZSBhIFBPUCBqd3QgaWYgdGhlIHRva2VuX2NsYWltcyBhcmUgbm90IHBvcHVsYXRlZFwiXHJcbiAgICB9LFxyXG4gICAgbm9BdXRob3JpemF0aW9uQ29kZUZyb21TZXJ2ZXI6IHtcclxuICAgICAgICBjb2RlOiBcImF1dGhvcml6YXRpb25fY29kZV9taXNzaW5nX2Zyb21fc2VydmVyX3Jlc3BvbnNlXCIsXHJcbiAgICAgICAgZGVzYzogXCJTcnZlciByZXNwb25zZSBkb2VzIG5vdCBjb250YWluIGFuIGF1dGhvcml6YXRpb24gY29kZSB0byBwcm9jZWVkXCJcclxuICAgIH1cclxufTtcclxuXHJcbi8qKlxyXG4gKiBFcnJvciB0aHJvd24gd2hlbiB0aGVyZSBpcyBhbiBlcnJvciBpbiB0aGUgY2xpZW50IGNvZGUgcnVubmluZyBvbiB0aGUgYnJvd3Nlci5cclxuICovXHJcbmV4cG9ydCBjbGFzcyBDbGllbnRBdXRoRXJyb3IgZXh0ZW5kcyBBdXRoRXJyb3Ige1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKGVycm9yQ29kZTogc3RyaW5nLCBlcnJvck1lc3NhZ2U/OiBzdHJpbmcpIHtcclxuICAgICAgICBzdXBlcihlcnJvckNvZGUsIGVycm9yTWVzc2FnZSk7XHJcbiAgICAgICAgdGhpcy5uYW1lID0gXCJDbGllbnRBdXRoRXJyb3JcIjtcclxuXHJcbiAgICAgICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKHRoaXMsIENsaWVudEF1dGhFcnJvci5wcm90b3R5cGUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlcyBhbiBlcnJvciB0aHJvd24gd2hlbiBjbGllbnQgaW5mbyBvYmplY3QgZG9lc24ndCBkZWNvZGUgY29ycmVjdGx5LlxyXG4gICAgICogQHBhcmFtIGNhdWdodEVycm9yXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVDbGllbnRJbmZvRGVjb2RpbmdFcnJvcihjYXVnaHRFcnJvcjogc3RyaW5nKTogQ2xpZW50QXV0aEVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudEF1dGhFcnJvcihDbGllbnRBdXRoRXJyb3JNZXNzYWdlLmNsaWVudEluZm9EZWNvZGluZ0Vycm9yLmNvZGUsXHJcbiAgICAgICAgICAgIGAke0NsaWVudEF1dGhFcnJvck1lc3NhZ2UuY2xpZW50SW5mb0RlY29kaW5nRXJyb3IuZGVzY30gRmFpbGVkIHdpdGggZXJyb3I6ICR7Y2F1Z2h0RXJyb3J9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIGFuIGVycm9yIHRocm93biBpZiB0aGUgY2xpZW50IGluZm8gaXMgZW1wdHkuXHJcbiAgICAgKiBAcGFyYW0gcmF3Q2xpZW50SW5mb1xyXG4gICAgICovXHJcbiAgICBzdGF0aWMgY3JlYXRlQ2xpZW50SW5mb0VtcHR5RXJyb3IoKTogQ2xpZW50QXV0aEVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudEF1dGhFcnJvcihDbGllbnRBdXRoRXJyb3JNZXNzYWdlLmNsaWVudEluZm9FbXB0eUVycm9yLmNvZGUsXHJcbiAgICAgICAgICAgIGAke0NsaWVudEF1dGhFcnJvck1lc3NhZ2UuY2xpZW50SW5mb0VtcHR5RXJyb3IuZGVzY31gKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZXMgYW4gZXJyb3IgdGhyb3duIHdoZW4gdGhlIGlkIHRva2VuIGV4dHJhY3Rpb24gZXJyb3JzIG91dC5cclxuICAgICAqIEBwYXJhbSBlcnJcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZVRva2VuUGFyc2luZ0Vycm9yKGNhdWdodEV4dHJhY3Rpb25FcnJvcjogc3RyaW5nKTogQ2xpZW50QXV0aEVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudEF1dGhFcnJvcihDbGllbnRBdXRoRXJyb3JNZXNzYWdlLnRva2VuUGFyc2luZ0Vycm9yLmNvZGUsXHJcbiAgICAgICAgICAgIGAke0NsaWVudEF1dGhFcnJvck1lc3NhZ2UudG9rZW5QYXJzaW5nRXJyb3IuZGVzY30gRmFpbGVkIHdpdGggZXJyb3I6ICR7Y2F1Z2h0RXh0cmFjdGlvbkVycm9yfWApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlcyBhbiBlcnJvciB0aHJvd24gd2hlbiB0aGUgaWQgdG9rZW4gc3RyaW5nIGlzIG51bGwgb3IgZW1wdHkuXHJcbiAgICAgKiBAcGFyYW0gaW52YWxpZFJhd1Rva2VuU3RyaW5nXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVUb2tlbk51bGxPckVtcHR5RXJyb3IoaW52YWxpZFJhd1Rva2VuU3RyaW5nOiBzdHJpbmcpIDogQ2xpZW50QXV0aEVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudEF1dGhFcnJvcihDbGllbnRBdXRoRXJyb3JNZXNzYWdlLm51bGxPckVtcHR5VG9rZW4uY29kZSxcclxuICAgICAgICAgICAgYCR7Q2xpZW50QXV0aEVycm9yTWVzc2FnZS5udWxsT3JFbXB0eVRva2VuLmRlc2N9IFJhdyBUb2tlbiBWYWx1ZTogJHtpbnZhbGlkUmF3VG9rZW5TdHJpbmd9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIGFuIGVycm9yIHRocm93biB3aGVuIHRoZSBlbmRwb2ludCBkaXNjb3ZlcnkgZG9lc24ndCBjb21wbGV0ZSBjb3JyZWN0bHkuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVFbmRwb2ludERpc2NvdmVyeUluY29tcGxldGVFcnJvcihlcnJEZXRhaWw6IHN0cmluZyk6IENsaWVudEF1dGhFcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRBdXRoRXJyb3IoQ2xpZW50QXV0aEVycm9yTWVzc2FnZS5lbmRwb2ludFJlc29sdXRpb25FcnJvci5jb2RlLFxyXG4gICAgICAgICAgICBgJHtDbGllbnRBdXRoRXJyb3JNZXNzYWdlLmVuZHBvaW50UmVzb2x1dGlvbkVycm9yLmRlc2N9IERldGFpbDogJHtlcnJEZXRhaWx9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIGFuIGVycm9yIHRocm93biB3aGVuIHRoZSBvcGVuaWQtY29uZmlndXJhdGlvbiBlbmRwb2ludCBjYW5ub3QgYmUgcmVhY2hlZCBvciBkb2VzIG5vdCBjb250YWluIHRoZSByZXF1aXJlZCBkYXRhXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVVbmFibGVUb0dldE9wZW5pZENvbmZpZ0Vycm9yKGVyckRldGFpbDogc3RyaW5nKTogQ2xpZW50QXV0aEVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudEF1dGhFcnJvcihDbGllbnRBdXRoRXJyb3JNZXNzYWdlLnVuYWJsZVRvR2V0T3BlbmlkQ29uZmlnRXJyb3IuY29kZSxcclxuICAgICAgICAgICAgYCR7Q2xpZW50QXV0aEVycm9yTWVzc2FnZS51bmFibGVUb0dldE9wZW5pZENvbmZpZ0Vycm9yLmRlc2N9IEF0dGVtcHRlZCB0byByZXRyaWV2ZSBlbmRwb2ludHMgZnJvbTogJHtlcnJEZXRhaWx9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIGFuIGVycm9yIHRocm93biB3aGVuIHRoZSBoYXNoIGNhbm5vdCBiZSBkZXNlcmlhbGl6ZWQuXHJcbiAgICAgKiBAcGFyYW0gaGFzaFBhcmFtT2JqXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVIYXNoTm90RGVzZXJpYWxpemVkRXJyb3IoaGFzaFBhcmFtT2JqOiBzdHJpbmcpOiBDbGllbnRBdXRoRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50QXV0aEVycm9yKENsaWVudEF1dGhFcnJvck1lc3NhZ2UuaGFzaE5vdERlc2VyaWFsaXplZC5jb2RlLFxyXG4gICAgICAgICAgICBgJHtDbGllbnRBdXRoRXJyb3JNZXNzYWdlLmhhc2hOb3REZXNlcmlhbGl6ZWQuZGVzY30gR2l2ZW4gT2JqZWN0OiAke2hhc2hQYXJhbU9ian1gKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZXMgYW4gZXJyb3IgdGhyb3duIHdoZW4gdGhlIHN0YXRlIGNhbm5vdCBiZSBwYXJzZWQuXHJcbiAgICAgKiBAcGFyYW0gaW52YWxpZFN0YXRlXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVJbnZhbGlkU3RhdGVFcnJvcihpbnZhbGlkU3RhdGU6IHN0cmluZywgZXJyb3JTdHJpbmc/OiBzdHJpbmcpOiBDbGllbnRBdXRoRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50QXV0aEVycm9yKENsaWVudEF1dGhFcnJvck1lc3NhZ2UuaW52YWxpZFN0YXRlRXJyb3IuY29kZSxcclxuICAgICAgICAgICAgYCR7Q2xpZW50QXV0aEVycm9yTWVzc2FnZS5pbnZhbGlkU3RhdGVFcnJvci5kZXNjfSBJbnZhbGlkIFN0YXRlOiAke2ludmFsaWRTdGF0ZX0sIFJvb3QgRXJyOiAke2Vycm9yU3RyaW5nfWApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlcyBhbiBlcnJvciB0aHJvd24gd2hlbiB0d28gc3RhdGVzIGRvIG5vdCBtYXRjaC5cclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZVN0YXRlTWlzbWF0Y2hFcnJvcigpOiBDbGllbnRBdXRoRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50QXV0aEVycm9yKENsaWVudEF1dGhFcnJvck1lc3NhZ2Uuc3RhdGVNaXNtYXRjaEVycm9yLmNvZGUsXHJcbiAgICAgICAgICAgIENsaWVudEF1dGhFcnJvck1lc3NhZ2Uuc3RhdGVNaXNtYXRjaEVycm9yLmRlc2MpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlcyBhbiBlcnJvciB0aHJvd24gd2hlbiB0aGUgc3RhdGUgaXMgbm90IHByZXNlbnRcclxuICAgICAqIEBwYXJhbSBtaXNzaW5nU3RhdGVcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZVN0YXRlTm90Rm91bmRFcnJvcihtaXNzaW5nU3RhdGU6IHN0cmluZyk6IENsaWVudEF1dGhFcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRBdXRoRXJyb3IoQ2xpZW50QXV0aEVycm9yTWVzc2FnZS5zdGF0ZU5vdEZvdW5kRXJyb3IuY29kZSxcclxuICAgICAgICAgICAgYCR7Q2xpZW50QXV0aEVycm9yTWVzc2FnZS5zdGF0ZU5vdEZvdW5kRXJyb3IuZGVzY306ICAke21pc3NpbmdTdGF0ZX1gKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZXMgYW4gZXJyb3IgdGhyb3duIHdoZW4gdGhlIG5vbmNlIGRvZXMgbm90IG1hdGNoLlxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgY3JlYXRlTm9uY2VNaXNtYXRjaEVycm9yKCk6IENsaWVudEF1dGhFcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRBdXRoRXJyb3IoQ2xpZW50QXV0aEVycm9yTWVzc2FnZS5ub25jZU1pc21hdGNoRXJyb3IuY29kZSxcclxuICAgICAgICAgICAgQ2xpZW50QXV0aEVycm9yTWVzc2FnZS5ub25jZU1pc21hdGNoRXJyb3IuZGVzYyk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIGFuIGVycm9yIHRocm93biB3aGVuIHRoZSBtbm9uY2UgaXMgbm90IHByZXNlbnRcclxuICAgICAqIEBwYXJhbSBtaXNzaW5nTm9uY2VcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZU5vbmNlTm90Rm91bmRFcnJvcihtaXNzaW5nTm9uY2U6IHN0cmluZyk6IENsaWVudEF1dGhFcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRBdXRoRXJyb3IoQ2xpZW50QXV0aEVycm9yTWVzc2FnZS5ub25jZU5vdEZvdW5kRXJyb3IuY29kZSxcclxuICAgICAgICAgICAgYCR7Q2xpZW50QXV0aEVycm9yTWVzc2FnZS5ub25jZU5vdEZvdW5kRXJyb3IuZGVzY306ICAke21pc3NpbmdOb25jZX1gKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZXMgYW4gZXJyb3IgdGhyb3duIHdoZW4gdGhlIGF1dGhvcml6YXRpb24gY29kZSByZXF1aXJlZCBmb3IgYSB0b2tlbiByZXF1ZXN0IGlzIG51bGwgb3IgZW1wdHkuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVOb1Rva2Vuc0ZvdW5kRXJyb3IoKTogQ2xpZW50QXV0aEVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudEF1dGhFcnJvcihDbGllbnRBdXRoRXJyb3JNZXNzYWdlLm5vVG9rZW5zRm91bmRFcnJvci5jb2RlLCBDbGllbnRBdXRoRXJyb3JNZXNzYWdlLm5vVG9rZW5zRm91bmRFcnJvci5kZXNjKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRocm93cyBlcnJvciB3aGVuIG11bHRpcGxlIHRva2VucyBhcmUgaW4gY2FjaGUuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVNdWx0aXBsZU1hdGNoaW5nVG9rZW5zSW5DYWNoZUVycm9yKCk6IENsaWVudEF1dGhFcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRBdXRoRXJyb3IoQ2xpZW50QXV0aEVycm9yTWVzc2FnZS5tdWx0aXBsZU1hdGNoaW5nVG9rZW5zLmNvZGUsXHJcbiAgICAgICAgICAgIGAke0NsaWVudEF1dGhFcnJvck1lc3NhZ2UubXVsdGlwbGVNYXRjaGluZ1Rva2Vucy5kZXNjfS5gKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRocm93cyBlcnJvciB3aGVuIG11bHRpcGxlIGFjY291bnRzIGFyZSBpbiBjYWNoZSBmb3IgdGhlIGdpdmVuIHBhcmFtc1xyXG4gICAgICovXHJcbiAgICBzdGF0aWMgY3JlYXRlTXVsdGlwbGVNYXRjaGluZ0FjY291bnRzSW5DYWNoZUVycm9yKCk6IENsaWVudEF1dGhFcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRBdXRoRXJyb3IoQ2xpZW50QXV0aEVycm9yTWVzc2FnZS5tdWx0aXBsZU1hdGNoaW5nQWNjb3VudHMuY29kZSxcclxuICAgICAgICAgICAgQ2xpZW50QXV0aEVycm9yTWVzc2FnZS5tdWx0aXBsZU1hdGNoaW5nQWNjb3VudHMuZGVzYyk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaHJvd3MgZXJyb3Igd2hlbiBtdWx0aXBsZSBhcHBNZXRhZGEgYXJlIGluIGNhY2hlIGZvciB0aGUgZ2l2ZW4gY2xpZW50SWQuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVNdWx0aXBsZU1hdGNoaW5nQXBwTWV0YWRhdGFJbkNhY2hlRXJyb3IoKTogQ2xpZW50QXV0aEVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudEF1dGhFcnJvcihDbGllbnRBdXRoRXJyb3JNZXNzYWdlLm11bHRpcGxlTWF0Y2hpbmdBcHBNZXRhZGF0YS5jb2RlLFxyXG4gICAgICAgICAgICBDbGllbnRBdXRoRXJyb3JNZXNzYWdlLm11bHRpcGxlTWF0Y2hpbmdBcHBNZXRhZGF0YS5kZXNjKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRocm93cyBlcnJvciB3aGVuIG5vIGF1dGggY29kZSBvciByZWZyZXNoIHRva2VuIGlzIGdpdmVuIHRvIFNlcnZlclRva2VuUmVxdWVzdFBhcmFtZXRlcnMuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVUb2tlblJlcXVlc3RDYW5ub3RCZU1hZGVFcnJvcigpOiBDbGllbnRBdXRoRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50QXV0aEVycm9yKENsaWVudEF1dGhFcnJvck1lc3NhZ2UudG9rZW5SZXF1ZXN0Q2Fubm90QmVNYWRlLmNvZGUsIENsaWVudEF1dGhFcnJvck1lc3NhZ2UudG9rZW5SZXF1ZXN0Q2Fubm90QmVNYWRlLmRlc2MpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhyb3dzIGVycm9yIHdoZW4gYXR0ZW1wdGluZyB0byBhcHBlbmQgYSBudWxsLCB1bmRlZmluZWQgb3IgZW1wdHkgc2NvcGUgdG8gYSBzZXRcclxuICAgICAqIEBwYXJhbSBnaXZlblNjb3BlXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVBcHBlbmRFbXB0eVNjb3BlVG9TZXRFcnJvcihnaXZlblNjb3BlOiBzdHJpbmcpOiBDbGllbnRBdXRoRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50QXV0aEVycm9yKENsaWVudEF1dGhFcnJvck1lc3NhZ2UuYXBwZW5kRW1wdHlTY29wZUVycm9yLmNvZGUsIGAke0NsaWVudEF1dGhFcnJvck1lc3NhZ2UuYXBwZW5kRW1wdHlTY29wZUVycm9yLmRlc2N9IEdpdmVuIFNjb3BlOiAke2dpdmVuU2NvcGV9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaHJvd3MgZXJyb3Igd2hlbiBhdHRlbXB0aW5nIHRvIGFwcGVuZCBhIG51bGwsIHVuZGVmaW5lZCBvciBlbXB0eSBzY29wZSB0byBhIHNldFxyXG4gICAgICogQHBhcmFtIGdpdmVuU2NvcGVcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZVJlbW92ZUVtcHR5U2NvcGVGcm9tU2V0RXJyb3IoZ2l2ZW5TY29wZTogc3RyaW5nKTogQ2xpZW50QXV0aEVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudEF1dGhFcnJvcihDbGllbnRBdXRoRXJyb3JNZXNzYWdlLnJlbW92ZUVtcHR5U2NvcGVFcnJvci5jb2RlLCBgJHtDbGllbnRBdXRoRXJyb3JNZXNzYWdlLnJlbW92ZUVtcHR5U2NvcGVFcnJvci5kZXNjfSBHaXZlbiBTY29wZTogJHtnaXZlblNjb3BlfWApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhyb3dzIGVycm9yIHdoZW4gYXR0ZW1wdGluZyB0byBhcHBlbmQgbnVsbCBvciBlbXB0eSBTY29wZVNldC5cclxuICAgICAqIEBwYXJhbSBhcHBlbmRFcnJvclxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgY3JlYXRlQXBwZW5kU2NvcGVTZXRFcnJvcihhcHBlbmRFcnJvcjogc3RyaW5nKTogQ2xpZW50QXV0aEVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudEF1dGhFcnJvcihDbGllbnRBdXRoRXJyb3JNZXNzYWdlLmFwcGVuZFNjb3BlU2V0RXJyb3IuY29kZSwgYCR7Q2xpZW50QXV0aEVycm9yTWVzc2FnZS5hcHBlbmRTY29wZVNldEVycm9yLmRlc2N9IERldGFpbCBFcnJvcjogJHthcHBlbmRFcnJvcn1gKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRocm93cyBlcnJvciBpZiBTY29wZVNldCBpcyBudWxsIG9yIHVuZGVmaW5lZC5cclxuICAgICAqIEBwYXJhbSBnaXZlblNjb3BlU2V0XHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVFbXB0eUlucHV0U2NvcGVTZXRFcnJvcihnaXZlblNjb3BlU2V0OiBTY29wZVNldCk6IENsaWVudEF1dGhFcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRBdXRoRXJyb3IoQ2xpZW50QXV0aEVycm9yTWVzc2FnZS5lbXB0eUlucHV0U2NvcGVTZXRFcnJvci5jb2RlLCBgJHtDbGllbnRBdXRoRXJyb3JNZXNzYWdlLmVtcHR5SW5wdXRTY29wZVNldEVycm9yLmRlc2N9IEdpdmVuIFNjb3BlU2V0OiAke2dpdmVuU2NvcGVTZXR9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaHJvd3MgZXJyb3IgaWYgdXNlciBzZXRzIENhbmNlbGxhdGlvblRva2VuLmNhbmNlbCA9IHRydWUgZHVyaW5nIHBvbGxpbmcgb2YgdG9rZW4gZW5kcG9pbnQgZHVyaW5nIGRldmljZSBjb2RlIGZsb3dcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZURldmljZUNvZGVDYW5jZWxsZWRFcnJvcigpOiBDbGllbnRBdXRoRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50QXV0aEVycm9yKENsaWVudEF1dGhFcnJvck1lc3NhZ2UuRGV2aWNlQ29kZVBvbGxpbmdDYW5jZWxsZWQuY29kZSwgYCR7Q2xpZW50QXV0aEVycm9yTWVzc2FnZS5EZXZpY2VDb2RlUG9sbGluZ0NhbmNlbGxlZC5kZXNjfWApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhyb3dzIGVycm9yIGlmIGRldmljZSBjb2RlIGlzIGV4cGlyZWRcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZURldmljZUNvZGVFeHBpcmVkRXJyb3IoKTogQ2xpZW50QXV0aEVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudEF1dGhFcnJvcihDbGllbnRBdXRoRXJyb3JNZXNzYWdlLkRldmljZUNvZGVFeHBpcmVkLmNvZGUsIGAke0NsaWVudEF1dGhFcnJvck1lc3NhZ2UuRGV2aWNlQ29kZUV4cGlyZWQuZGVzY31gKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRocm93cyBlcnJvciB3aGVuIHNpbGVudCByZXF1ZXN0cyBhcmUgbWFkZSB3aXRob3V0IGFuIGFjY291bnQgb2JqZWN0XHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVOb0FjY291bnRJblNpbGVudFJlcXVlc3RFcnJvcigpOiBDbGllbnRBdXRoRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50QXV0aEVycm9yKENsaWVudEF1dGhFcnJvck1lc3NhZ2UuTm9BY2NvdW50SW5TaWxlbnRSZXF1ZXN0LmNvZGUsIGAke0NsaWVudEF1dGhFcnJvck1lc3NhZ2UuTm9BY2NvdW50SW5TaWxlbnRSZXF1ZXN0LmRlc2N9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaHJvd3MgZXJyb3Igd2hlbiBjYWNoZSByZWNvcmQgaXMgbnVsbCBvciB1bmRlZmluZWQuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVOdWxsT3JVbmRlZmluZWRDYWNoZVJlY29yZCgpOiBDbGllbnRBdXRoRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50QXV0aEVycm9yKENsaWVudEF1dGhFcnJvck1lc3NhZ2UuaW52YWxpZENhY2hlUmVjb3JkLmNvZGUsIENsaWVudEF1dGhFcnJvck1lc3NhZ2UuaW52YWxpZENhY2hlUmVjb3JkLmRlc2MpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhyb3dzIGVycm9yIHdoZW4gcHJvdmlkZWQgZW52aXJvbm1lbnQgaXMgbm90IHBhcnQgb2YgdGhlIENsb3VkRGlzY292ZXJ5TWV0YWRhdGEgb2JqZWN0XHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVJbnZhbGlkQ2FjaGVFbnZpcm9ubWVudEVycm9yKCk6IENsaWVudEF1dGhFcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRBdXRoRXJyb3IoQ2xpZW50QXV0aEVycm9yTWVzc2FnZS5pbnZhbGlkQ2FjaGVFbnZpcm9ubWVudC5jb2RlLCBDbGllbnRBdXRoRXJyb3JNZXNzYWdlLmludmFsaWRDYWNoZUVudmlyb25tZW50LmRlc2MpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhyb3dzIGVycm9yIHdoZW4gYWNjb3VudCBpcyBub3QgZm91bmQgaW4gY2FjaGUuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVOb0FjY291bnRGb3VuZEVycm9yKCk6IENsaWVudEF1dGhFcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRBdXRoRXJyb3IoQ2xpZW50QXV0aEVycm9yTWVzc2FnZS5ub0FjY291bnRGb3VuZC5jb2RlLCBDbGllbnRBdXRoRXJyb3JNZXNzYWdlLm5vQWNjb3VudEZvdW5kLmRlc2MpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhyb3dzIGVycm9yIGlmIElDYWNoZVBsdWdpbiBub3Qgc2V0IG9uIENhY2hlTWFuYWdlci5cclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZUNhY2hlUGx1Z2luRXJyb3IoKTogQ2xpZW50QXV0aEVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudEF1dGhFcnJvcihDbGllbnRBdXRoRXJyb3JNZXNzYWdlLkNhY2hlUGx1Z2luRXJyb3IuY29kZSwgYCR7Q2xpZW50QXV0aEVycm9yTWVzc2FnZS5DYWNoZVBsdWdpbkVycm9yLmRlc2N9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaHJvd3MgZXJyb3IgaWYgY3J5cHRvIG9iamVjdCBub3QgZm91bmQuXHJcbiAgICAgKiBAcGFyYW0gb3BlcmF0aW9uTmFtZVxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgY3JlYXRlTm9DcnlwdG9PYmplY3RFcnJvcihvcGVyYXRpb25OYW1lOiBzdHJpbmcpOiBDbGllbnRBdXRoRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50QXV0aEVycm9yKENsaWVudEF1dGhFcnJvck1lc3NhZ2Uubm9DcnlwdG9PYmouY29kZSwgYCR7Q2xpZW50QXV0aEVycm9yTWVzc2FnZS5ub0NyeXB0b09iai5kZXNjfSR7b3BlcmF0aW9uTmFtZX1gKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRocm93cyBlcnJvciBpZiBjYWNoZSB0eXBlIGlzIGludmFsaWQuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVJbnZhbGlkQ2FjaGVUeXBlRXJyb3IoKTogQ2xpZW50QXV0aEVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudEF1dGhFcnJvcihDbGllbnRBdXRoRXJyb3JNZXNzYWdlLmludmFsaWRDYWNoZVR5cGUuY29kZSwgYCR7Q2xpZW50QXV0aEVycm9yTWVzc2FnZS5pbnZhbGlkQ2FjaGVUeXBlLmRlc2N9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaHJvd3MgZXJyb3IgaWYgdW5leHBlY3RlZCBhY2NvdW50IHR5cGUuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVVbmV4cGVjdGVkQWNjb3VudFR5cGVFcnJvcigpOiBDbGllbnRBdXRoRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50QXV0aEVycm9yKENsaWVudEF1dGhFcnJvck1lc3NhZ2UudW5leHBlY3RlZEFjY291bnRUeXBlLmNvZGUsIGAke0NsaWVudEF1dGhFcnJvck1lc3NhZ2UudW5leHBlY3RlZEFjY291bnRUeXBlLmRlc2N9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaHJvd3MgZXJyb3IgaWYgdW5leHBlY3RlZCBjcmVkZW50aWFsIHR5cGUuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVVbmV4cGVjdGVkQ3JlZGVudGlhbFR5cGVFcnJvcigpOiBDbGllbnRBdXRoRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50QXV0aEVycm9yKENsaWVudEF1dGhFcnJvck1lc3NhZ2UudW5leHBlY3RlZENyZWRlbnRpYWxUeXBlLmNvZGUsIGAke0NsaWVudEF1dGhFcnJvck1lc3NhZ2UudW5leHBlY3RlZENyZWRlbnRpYWxUeXBlLmRlc2N9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaHJvd3MgZXJyb3IgaWYgY2xpZW50IGFzc2VydGlvbiBpcyBub3QgdmFsaWQuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVJbnZhbGlkQXNzZXJ0aW9uRXJyb3IoKTogQ2xpZW50QXV0aEVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudEF1dGhFcnJvcihDbGllbnRBdXRoRXJyb3JNZXNzYWdlLmludmFsaWRBc3NlcnRpb24uY29kZSwgYCR7Q2xpZW50QXV0aEVycm9yTWVzc2FnZS5pbnZhbGlkQXNzZXJ0aW9uLmRlc2N9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaHJvd3MgZXJyb3IgaWYgY2xpZW50IGFzc2VydGlvbiBpcyBub3QgdmFsaWQuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVJbnZhbGlkQ3JlZGVudGlhbEVycm9yKCk6IENsaWVudEF1dGhFcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRBdXRoRXJyb3IoQ2xpZW50QXV0aEVycm9yTWVzc2FnZS5pbnZhbGlkQ2xpZW50Q3JlZGVudGlhbC5jb2RlLCBgJHtDbGllbnRBdXRoRXJyb3JNZXNzYWdlLmludmFsaWRDbGllbnRDcmVkZW50aWFsLmRlc2N9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaHJvd3MgZXJyb3IgaWYgdG9rZW4gY2Fubm90IGJlIHJldHJpZXZlZCBmcm9tIGNhY2hlIGR1ZSB0byByZWZyZXNoIGJlaW5nIHJlcXVpcmVkLlxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgY3JlYXRlUmVmcmVzaFJlcXVpcmVkRXJyb3IoKTogQ2xpZW50QXV0aEVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudEF1dGhFcnJvcihDbGllbnRBdXRoRXJyb3JNZXNzYWdlLnRva2VuUmVmcmVzaFJlcXVpcmVkLmNvZGUsIENsaWVudEF1dGhFcnJvck1lc3NhZ2UudG9rZW5SZWZyZXNoUmVxdWlyZWQuZGVzYyk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaHJvd3MgZXJyb3IgaWYgdGhlIHVzZXIgZGVmaW5lZCB0aW1lb3V0IGlzIHJlYWNoZWQuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVVc2VyVGltZW91dFJlYWNoZWRFcnJvcigpOiBDbGllbnRBdXRoRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50QXV0aEVycm9yKENsaWVudEF1dGhFcnJvck1lc3NhZ2UudXNlclRpbWVvdXRSZWFjaGVkLmNvZGUsIENsaWVudEF1dGhFcnJvck1lc3NhZ2UudXNlclRpbWVvdXRSZWFjaGVkLmRlc2MpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qXHJcbiAgICAgKiBUaHJvd3MgZXJyb3IgaWYgdG9rZW4gY2xhaW1zIGFyZSBub3QgcG9wdWxhdGVkIGZvciBhIHNpZ25lZCBqd3QgZ2VuZXJhdGlvblxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgY3JlYXRlVG9rZW5DbGFpbXNSZXF1aXJlZEVycm9yKCk6IENsaWVudEF1dGhFcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRBdXRoRXJyb3IoQ2xpZW50QXV0aEVycm9yTWVzc2FnZS50b2tlbkNsYWltc1JlcXVpcmVkLmNvZGUsIENsaWVudEF1dGhFcnJvck1lc3NhZ2UudG9rZW5DbGFpbXNSZXF1aXJlZC5kZXNjKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRocm93cyBlcnJvciB3aGVuIHRoZSBhdXRob3JpemF0aW9uIGNvZGUgaXMgbWlzc2luZyBmcm9tIHRoZSBzZXJ2ZXIgcmVzcG9uc2VcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZU5vQXV0aENvZGVJblNlcnZlclJlc3BvbnNlRXJyb3IoKTogQ2xpZW50QXV0aEVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudEF1dGhFcnJvcihDbGllbnRBdXRoRXJyb3JNZXNzYWdlLm5vQXV0aG9yaXphdGlvbkNvZGVGcm9tU2VydmVyLmNvZGUsIENsaWVudEF1dGhFcnJvck1lc3NhZ2Uubm9BdXRob3JpemF0aW9uQ29kZUZyb21TZXJ2ZXIuZGVzYyk7XHJcbiAgICB9XHJcbn1cclxuIiwiLypcclxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cclxuICovXHJcblxyXG5pbXBvcnQgeyBEZWNvZGVkQXV0aFRva2VuIH0gZnJvbSBcIi4uL2FjY291bnQvRGVjb2RlZEF1dGhUb2tlblwiO1xyXG5pbXBvcnQgeyBDbGllbnRBdXRoRXJyb3IgfSBmcm9tIFwiLi4vZXJyb3IvQ2xpZW50QXV0aEVycm9yXCI7XHJcblxyXG4vKipcclxuICogQGhpZGRlblxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIFN0cmluZ1V0aWxzIHtcclxuXHJcbiAgICAvKipcclxuICAgICAqIGRlY29kZSBhIEpXVFxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSBhdXRoVG9rZW5cclxuICAgICAqL1xyXG4gICAgc3RhdGljIGRlY29kZUF1dGhUb2tlbihhdXRoVG9rZW46IHN0cmluZyk6IERlY29kZWRBdXRoVG9rZW4ge1xyXG4gICAgICAgIGlmIChTdHJpbmdVdGlscy5pc0VtcHR5KGF1dGhUb2tlbikpIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50QXV0aEVycm9yLmNyZWF0ZVRva2VuTnVsbE9yRW1wdHlFcnJvcihhdXRoVG9rZW4pO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25zdCB0b2tlblBhcnRzUmVnZXggPSAvXihbXlxcLlxcc10qKVxcLihbXlxcLlxcc10rKVxcLihbXlxcLlxcc10qKSQvO1xyXG4gICAgICAgIGNvbnN0IG1hdGNoZXMgPSB0b2tlblBhcnRzUmVnZXguZXhlYyhhdXRoVG9rZW4pO1xyXG4gICAgICAgIGlmICghbWF0Y2hlcyB8fCBtYXRjaGVzLmxlbmd0aCA8IDQpIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50QXV0aEVycm9yLmNyZWF0ZVRva2VuUGFyc2luZ0Vycm9yKGBHaXZlbiB0b2tlbiBpcyBtYWxmb3JtZWQ6ICR7SlNPTi5zdHJpbmdpZnkoYXV0aFRva2VuKX1gKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3QgY3JhY2tlZFRva2VuOiBEZWNvZGVkQXV0aFRva2VuID0ge1xyXG4gICAgICAgICAgICBoZWFkZXI6IG1hdGNoZXNbMV0sXHJcbiAgICAgICAgICAgIEpXU1BheWxvYWQ6IG1hdGNoZXNbMl0sXHJcbiAgICAgICAgICAgIEpXU1NpZzogbWF0Y2hlc1szXVxyXG4gICAgICAgIH07XHJcbiAgICAgICAgcmV0dXJuIGNyYWNrZWRUb2tlbjtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENoZWNrIGlmIGEgc3RyaW5nIGlzIGVtcHR5LlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSBzdHJcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGlzRW1wdHkoc3RyPzogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuICh0eXBlb2Ygc3RyID09PSBcInVuZGVmaW5lZFwiIHx8ICFzdHIgfHwgMCA9PT0gc3RyLmxlbmd0aCk7XHJcbiAgICB9XHJcblxyXG4gICAgc3RhdGljIHN0YXJ0c1dpdGgoc3RyOiBzdHJpbmcsIHNlYXJjaDogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIHN0ci5pbmRleE9mKHNlYXJjaCkgPT09IDA7XHJcbiAgICB9XHJcblxyXG4gICAgc3RhdGljIGVuZHNXaXRoKHN0cjogc3RyaW5nLCBzZWFyY2g6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiAoc3RyLmxlbmd0aCA+PSBzZWFyY2gubGVuZ3RoKSAmJiAoc3RyLmxhc3RJbmRleE9mKHNlYXJjaCkgPT09IChzdHIubGVuZ3RoIC0gc2VhcmNoLmxlbmd0aCkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUGFyc2VzIHN0cmluZyBpbnRvIGFuIG9iamVjdC5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gcXVlcnlcclxuICAgICAqL1xyXG4gICAgc3RhdGljIHF1ZXJ5U3RyaW5nVG9PYmplY3Q8VD4ocXVlcnk6IHN0cmluZyk6IFQge1xyXG4gICAgICAgIGxldCBtYXRjaDogQXJyYXk8c3RyaW5nPiB8IG51bGw7IC8vIFJlZ2V4IGZvciByZXBsYWNpbmcgYWRkaXRpb24gc3ltYm9sIHdpdGggYSBzcGFjZVxyXG4gICAgICAgIGNvbnN0IHBsID0gL1xcKy9nO1xyXG4gICAgICAgIGNvbnN0IHNlYXJjaCA9IC8oW14mPV0rKT0oW14mXSopL2c7XHJcbiAgICAgICAgY29uc3QgZGVjb2RlID0gKHM6IHN0cmluZyk6IHN0cmluZyA9PiBkZWNvZGVVUklDb21wb25lbnQoZGVjb2RlVVJJQ29tcG9uZW50KHMucmVwbGFjZShwbCwgXCIgXCIpKSk7XHJcbiAgICAgICAgY29uc3Qgb2JqOiB7fSA9IHt9O1xyXG4gICAgICAgIG1hdGNoID0gc2VhcmNoLmV4ZWMocXVlcnkpO1xyXG4gICAgICAgIHdoaWxlIChtYXRjaCkge1xyXG4gICAgICAgICAgICBvYmpbZGVjb2RlKG1hdGNoWzFdKV0gPSBkZWNvZGUobWF0Y2hbMl0pO1xyXG4gICAgICAgICAgICBtYXRjaCA9IHNlYXJjaC5leGVjKHF1ZXJ5KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIG9iaiBhcyBUO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVHJpbXMgZW50cmllcyBpbiBhbiBhcnJheS5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gYXJyXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyB0cmltQXJyYXlFbnRyaWVzKGFycjogQXJyYXk8c3RyaW5nPik6IEFycmF5PHN0cmluZz4ge1xyXG4gICAgICAgIHJldHVybiBhcnIubWFwKGVudHJ5ID0+IGVudHJ5LnRyaW0oKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZW1vdmVzIGVtcHR5IHN0cmluZ3MgZnJvbSBhcnJheVxyXG4gICAgICogQHBhcmFtIGFyclxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgcmVtb3ZlRW1wdHlTdHJpbmdzRnJvbUFycmF5KGFycjogQXJyYXk8c3RyaW5nPik6IEFycmF5PHN0cmluZz4ge1xyXG4gICAgICAgIHJldHVybiBhcnIuZmlsdGVyKGVudHJ5ID0+IHtcclxuICAgICAgICAgICAgcmV0dXJuICFTdHJpbmdVdGlscy5pc0VtcHR5KGVudHJ5KTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEF0dGVtcHRzIHRvIHBhcnNlIGEgc3RyaW5nIGludG8gSlNPTlxyXG4gICAgICogQHBhcmFtIHN0clxyXG4gICAgICovXHJcbiAgICBzdGF0aWMganNvblBhcnNlSGVscGVyPFQ+KHN0cjogc3RyaW5nKTogVCB8IG51bGwge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIHJldHVybiBKU09OLnBhcnNlKHN0cikgYXMgVDtcclxuICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRlc3RzIGlmIGEgZ2l2ZW4gc3RyaW5nIG1hdGNoZXMgYSBnaXZlbiBwYXR0ZXJuLCB3aXRoIHN1cHBvcnQgZm9yIHdpbGRjYXJkcy5cclxuICAgICAqIEBwYXJhbSBwYXR0ZXJuIFdpbGRjYXJkIHBhdHRlcm4gdG8gc3RyaW5nIG1hdGNoLiBTdXBwb3J0cyBcIipcIiBmb3Igd2lsZGNhcmRzXHJcbiAgICAgKiBAcGFyYW0gaW5wdXQgU3RyaW5nIHRvIG1hdGNoIGFnYWluc3RcclxuICAgICAqL1xyXG4gICAgc3RhdGljIG1hdGNoUGF0dGVybihwYXR0ZXJuOiBzdHJpbmcsIGlucHV0OiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgICAgICAvLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzExNzI0OC80ODg4NTU5XHJcbiAgICAgICAgY29uc3QgcmVnZXg6IFJlZ0V4cCA9IG5ldyBSZWdFeHAocGF0dGVybi5yZXBsYWNlKC9cXCovZywgXCJbXiBdKlwiKSk7XHJcblxyXG4gICAgICAgIHJldHVybiByZWdleC50ZXN0KGlucHV0KTtcclxuICAgIH1cclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IFN0cmluZ1V0aWxzIH0gZnJvbSBcIi4uL3V0aWxzL1N0cmluZ1V0aWxzXCI7XHJcbmltcG9ydCB7IExvZ2dlck9wdGlvbnMgfSBmcm9tIFwiLi4vY29uZmlnL0NsaWVudENvbmZpZ3VyYXRpb25cIjtcclxuaW1wb3J0IHsgQ29uc3RhbnRzIH0gZnJvbSBcIi4uL3V0aWxzL0NvbnN0YW50c1wiO1xyXG5cclxuLyoqXHJcbiAqIE9wdGlvbnMgZm9yIGxvZ2dlciBtZXNzYWdlcy5cclxuICovXHJcbmV4cG9ydCB0eXBlIExvZ2dlck1lc3NhZ2VPcHRpb25zID0ge1xyXG4gICAgbG9nTGV2ZWw6IExvZ0xldmVsLFxyXG4gICAgY29ycmVsYXRpb25JZD86IHN0cmluZyxcclxuICAgIGNvbnRhaW5zUGlpPzogYm9vbGVhbixcclxuICAgIGNvbnRleHQ/OiBzdHJpbmdcclxufTtcclxuXHJcbi8qKlxyXG4gKiBMb2cgbWVzc2FnZSBsZXZlbC5cclxuICovXHJcbmV4cG9ydCBlbnVtIExvZ0xldmVsIHtcclxuICAgIEVycm9yLFxyXG4gICAgV2FybmluZyxcclxuICAgIEluZm8sXHJcbiAgICBWZXJib3NlXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDYWxsYmFjayB0byBzZW5kIHRoZSBtZXNzYWdlcyB0by5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUxvZ2dlckNhbGxiYWNrIHtcclxuICAgIChsZXZlbDogTG9nTGV2ZWwsIG1lc3NhZ2U6IHN0cmluZywgY29udGFpbnNQaWk6IGJvb2xlYW4pOiB2b2lkO1xyXG59XHJcblxyXG4vKipcclxuICogQ2xhc3Mgd2hpY2ggZmFjaWxpdGF0ZXMgbG9nZ2luZyBvZiBtZXNzYWdlcyB0byBhIHNwZWNpZmljIHBsYWNlLlxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIExvZ2dlciB7XHJcblxyXG4gICAgLy8gQ29ycmVsYXRpb24gSUQgZm9yIHJlcXVlc3QsIHVzdWFsbHkgc2V0IGJ5IHVzZXIuXHJcbiAgICBwcml2YXRlIGNvcnJlbGF0aW9uSWQ6IHN0cmluZztcclxuXHJcbiAgICAvLyBDdXJyZW50IGxvZyBsZXZlbCwgZGVmYXVsdHMgdG8gaW5mby5cclxuICAgIHByaXZhdGUgbGV2ZWw6IExvZ0xldmVsID0gTG9nTGV2ZWwuSW5mbztcclxuXHJcbiAgICAvLyBCb29sZWFuIGRlc2NyaWJpbmcgd2hldGhlciBQSUkgbG9nZ2luZyBpcyBhbGxvd2VkLlxyXG4gICAgcHJpdmF0ZSBwaWlMb2dnaW5nRW5hYmxlZDogYm9vbGVhbjtcclxuXHJcbiAgICAvLyBDYWxsYmFjayB0byBzZW5kIG1lc3NhZ2VzIHRvLlxyXG4gICAgcHJpdmF0ZSBsb2NhbENhbGxiYWNrOiBJTG9nZ2VyQ2FsbGJhY2s7XHJcblxyXG4gICAgLy8gUGFja2FnZSBuYW1lIGltcGxlbWVudGluZyB0aGlzIGxvZ2dlclxyXG4gICAgcHJpdmF0ZSBwYWNrYWdlTmFtZTogc3RyaW5nO1xyXG5cclxuICAgIC8vIFBhY2thZ2UgdmVyc2lvbiBpbXBsZW1lbnRpbmcgdGhpcyBsb2dnZXJcclxuICAgIHByaXZhdGUgcGFja2FnZVZlcnNpb246IHN0cmluZztcclxuXHJcbiAgICBjb25zdHJ1Y3Rvcihsb2dnZXJPcHRpb25zOiBMb2dnZXJPcHRpb25zLCBwYWNrYWdlTmFtZT86IHN0cmluZywgcGFja2FnZVZlcnNpb24/OiBzdHJpbmcpIHtcclxuICAgICAgICBjb25zdCBkZWZhdWx0TG9nZ2VyQ2FsbGJhY2sgPSAoKSA9PiB7fTtcclxuICAgICAgICB0aGlzLmxvY2FsQ2FsbGJhY2sgPSBsb2dnZXJPcHRpb25zLmxvZ2dlckNhbGxiYWNrIHx8IGRlZmF1bHRMb2dnZXJDYWxsYmFjaztcclxuICAgICAgICB0aGlzLnBpaUxvZ2dpbmdFbmFibGVkID0gbG9nZ2VyT3B0aW9ucy5waWlMb2dnaW5nRW5hYmxlZCB8fCBmYWxzZTtcclxuICAgICAgICB0aGlzLmxldmVsID0gbG9nZ2VyT3B0aW9ucy5sb2dMZXZlbCB8fCBMb2dMZXZlbC5JbmZvO1xyXG5cclxuICAgICAgICB0aGlzLnBhY2thZ2VOYW1lID0gcGFja2FnZU5hbWUgfHwgQ29uc3RhbnRzLkVNUFRZX1NUUklORztcclxuICAgICAgICB0aGlzLnBhY2thZ2VWZXJzaW9uID0gcGFja2FnZVZlcnNpb24gfHwgQ29uc3RhbnRzLkVNUFRZX1NUUklORztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZSBuZXcgTG9nZ2VyIHdpdGggZXhpc3RpbmcgY29uZmlndXJhdGlvbnMuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBjbG9uZShwYWNrYWdlTmFtZTogc3RyaW5nLCBwYWNrYWdlVmVyc2lvbjogc3RyaW5nKTogTG9nZ2VyIHtcclxuICAgICAgICByZXR1cm4gbmV3IExvZ2dlcih7bG9nZ2VyQ2FsbGJhY2s6IHRoaXMubG9jYWxDYWxsYmFjaywgcGlpTG9nZ2luZ0VuYWJsZWQ6IHRoaXMucGlpTG9nZ2luZ0VuYWJsZWQsIGxvZ0xldmVsOiB0aGlzLmxldmVsfSwgcGFja2FnZU5hbWUsIHBhY2thZ2VWZXJzaW9uKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIExvZyBtZXNzYWdlIHdpdGggcmVxdWlyZWQgb3B0aW9ucy5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBsb2dNZXNzYWdlKGxvZ01lc3NhZ2U6IHN0cmluZywgb3B0aW9uczogTG9nZ2VyTWVzc2FnZU9wdGlvbnMpOiB2b2lkIHtcclxuICAgICAgICBpZiAoKG9wdGlvbnMubG9nTGV2ZWwgPiB0aGlzLmxldmVsKSB8fCAoIXRoaXMucGlpTG9nZ2luZ0VuYWJsZWQgJiYgb3B0aW9ucy5jb250YWluc1BpaSkpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25zdCB0aW1lc3RhbXAgPSBuZXcgRGF0ZSgpLnRvVVRDU3RyaW5nKCk7XHJcbiAgICAgICAgY29uc3QgbG9nSGVhZGVyOiBzdHJpbmcgPSBTdHJpbmdVdGlscy5pc0VtcHR5KHRoaXMuY29ycmVsYXRpb25JZCkgPyBgWyR7dGltZXN0YW1wfV0gOiBgIDogYFske3RpbWVzdGFtcH1dIDogWyR7dGhpcy5jb3JyZWxhdGlvbklkfV1gO1xyXG4gICAgICAgIGNvbnN0IGxvZyA9IGAke2xvZ0hlYWRlcn0gOiAke3RoaXMucGFja2FnZU5hbWV9QCR7dGhpcy5wYWNrYWdlVmVyc2lvbn0gOiAke0xvZ0xldmVsW29wdGlvbnMubG9nTGV2ZWxdfSAtICR7bG9nTWVzc2FnZX1gO1xyXG4gICAgICAgIC8vIGRlYnVnKGBtc2FsOiR7TG9nTGV2ZWxbb3B0aW9ucy5sb2dMZXZlbF19JHtvcHRpb25zLmNvbnRhaW5zUGlpID8gXCItUGlpXCI6IFwiXCJ9JHtvcHRpb25zLmNvbnRleHQgPyBgOiR7b3B0aW9ucy5jb250ZXh0fWAgOiBcIlwifWApKGxvZ01lc3NhZ2UpO1xyXG4gICAgICAgIHRoaXMuZXhlY3V0ZUNhbGxiYWNrKG9wdGlvbnMubG9nTGV2ZWwsIGxvZywgb3B0aW9ucy5jb250YWluc1BpaSB8fCBmYWxzZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBFeGVjdXRlIGNhbGxiYWNrIHdpdGggbWVzc2FnZS5cclxuICAgICAqL1xyXG4gICAgZXhlY3V0ZUNhbGxiYWNrKGxldmVsOiBMb2dMZXZlbCwgbWVzc2FnZTogc3RyaW5nLCBjb250YWluc1BpaTogYm9vbGVhbik6IHZvaWQge1xyXG4gICAgICAgIGlmICh0aGlzLmxvY2FsQ2FsbGJhY2spIHtcclxuICAgICAgICAgICAgdGhpcy5sb2NhbENhbGxiYWNrKGxldmVsLCBtZXNzYWdlLCBjb250YWluc1BpaSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTG9ncyBlcnJvciBtZXNzYWdlcy5cclxuICAgICAqL1xyXG4gICAgZXJyb3IobWVzc2FnZTogc3RyaW5nLCBjb3JyZWxhdGlvbklkPzogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5sb2dNZXNzYWdlKG1lc3NhZ2UsIHtcclxuICAgICAgICAgICAgbG9nTGV2ZWw6IExvZ0xldmVsLkVycm9yLFxyXG4gICAgICAgICAgICBjb250YWluc1BpaTogZmFsc2UsXHJcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IGNvcnJlbGF0aW9uSWQgfHwgXCJcIlxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTG9ncyBlcnJvciBtZXNzYWdlcyB3aXRoIFBJSS5cclxuICAgICAqL1xyXG4gICAgZXJyb3JQaWkobWVzc2FnZTogc3RyaW5nLCBjb3JyZWxhdGlvbklkPzogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5sb2dNZXNzYWdlKG1lc3NhZ2UsIHtcclxuICAgICAgICAgICAgbG9nTGV2ZWw6IExvZ0xldmVsLkVycm9yLFxyXG4gICAgICAgICAgICBjb250YWluc1BpaTogdHJ1ZSxcclxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogY29ycmVsYXRpb25JZCB8fCBcIlwiXHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBMb2dzIHdhcm5pbmcgbWVzc2FnZXMuXHJcbiAgICAgKi9cclxuICAgIHdhcm5pbmcobWVzc2FnZTogc3RyaW5nLCBjb3JyZWxhdGlvbklkPzogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5sb2dNZXNzYWdlKG1lc3NhZ2UsIHtcclxuICAgICAgICAgICAgbG9nTGV2ZWw6IExvZ0xldmVsLldhcm5pbmcsXHJcbiAgICAgICAgICAgIGNvbnRhaW5zUGlpOiBmYWxzZSxcclxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogY29ycmVsYXRpb25JZCB8fCBcIlwiXHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBMb2dzIHdhcm5pbmcgbWVzc2FnZXMgd2l0aCBQSUkuXHJcbiAgICAgKi9cclxuICAgIHdhcm5pbmdQaWkobWVzc2FnZTogc3RyaW5nLCBjb3JyZWxhdGlvbklkPzogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5sb2dNZXNzYWdlKG1lc3NhZ2UsIHtcclxuICAgICAgICAgICAgbG9nTGV2ZWw6IExvZ0xldmVsLldhcm5pbmcsXHJcbiAgICAgICAgICAgIGNvbnRhaW5zUGlpOiB0cnVlLFxyXG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBjb3JyZWxhdGlvbklkIHx8IFwiXCJcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIExvZ3MgaW5mbyBtZXNzYWdlcy5cclxuICAgICAqL1xyXG4gICAgaW5mbyhtZXNzYWdlOiBzdHJpbmcsIGNvcnJlbGF0aW9uSWQ/OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmxvZ01lc3NhZ2UobWVzc2FnZSwge1xyXG4gICAgICAgICAgICBsb2dMZXZlbDogTG9nTGV2ZWwuSW5mbyxcclxuICAgICAgICAgICAgY29udGFpbnNQaWk6IGZhbHNlLFxyXG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBjb3JyZWxhdGlvbklkIHx8IFwiXCJcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIExvZ3MgaW5mbyBtZXNzYWdlcyB3aXRoIFBJSS5cclxuICAgICAqL1xyXG4gICAgaW5mb1BpaShtZXNzYWdlOiBzdHJpbmcsIGNvcnJlbGF0aW9uSWQ/OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmxvZ01lc3NhZ2UobWVzc2FnZSwge1xyXG4gICAgICAgICAgICBsb2dMZXZlbDogTG9nTGV2ZWwuSW5mbyxcclxuICAgICAgICAgICAgY29udGFpbnNQaWk6IHRydWUsXHJcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IGNvcnJlbGF0aW9uSWQgfHwgXCJcIlxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTG9ncyB2ZXJib3NlIG1lc3NhZ2VzLlxyXG4gICAgICovXHJcbiAgICB2ZXJib3NlKG1lc3NhZ2U6IHN0cmluZywgY29ycmVsYXRpb25JZD86IHN0cmluZyk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMubG9nTWVzc2FnZShtZXNzYWdlLCB7XHJcbiAgICAgICAgICAgIGxvZ0xldmVsOiBMb2dMZXZlbC5WZXJib3NlLFxyXG4gICAgICAgICAgICBjb250YWluc1BpaTogZmFsc2UsXHJcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IGNvcnJlbGF0aW9uSWQgfHwgXCJcIlxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTG9ncyB2ZXJib3NlIG1lc3NhZ2VzIHdpdGggUElJLlxyXG4gICAgICovXHJcbiAgICB2ZXJib3NlUGlpKG1lc3NhZ2U6IHN0cmluZywgY29ycmVsYXRpb25JZD86IHN0cmluZyk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMubG9nTWVzc2FnZShtZXNzYWdlLCB7XHJcbiAgICAgICAgICAgIGxvZ0xldmVsOiBMb2dMZXZlbC5WZXJib3NlLFxyXG4gICAgICAgICAgICBjb250YWluc1BpaTogdHJ1ZSxcclxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogY29ycmVsYXRpb25JZCB8fCBcIlwiXHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIHdoZXRoZXIgUElJIExvZ2dpbmcgaXMgZW5hYmxlZCBvciBub3QuXHJcbiAgICAgKi9cclxuICAgIGlzUGlpTG9nZ2luZ0VuYWJsZWQoKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMucGlpTG9nZ2luZ0VuYWJsZWQgfHwgZmFsc2U7XHJcbiAgICB9XHJcbn1cclxuIiwiLyogZXNsaW50LWRpc2FibGUgaGVhZGVyL2hlYWRlciAqL1xuZXhwb3J0IGNvbnN0IG5hbWUgPSBcIkBhenVyZS9tc2FsLWNvbW1vblwiO1xuZXhwb3J0IGNvbnN0IHZlcnNpb24gPSBcIjQuMC4xXCI7XG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IFNlcGFyYXRvcnMsIENyZWRlbnRpYWxUeXBlLCBDYWNoZVR5cGUsIENvbnN0YW50cyB9IGZyb20gXCIuLi8uLi91dGlscy9Db25zdGFudHNcIjtcclxuaW1wb3J0IHsgQ2xpZW50QXV0aEVycm9yIH0gZnJvbSBcIi4uLy4uL2Vycm9yL0NsaWVudEF1dGhFcnJvclwiO1xyXG5cclxuLyoqXHJcbiAqIEJhc2UgdHlwZSBmb3IgY3JlZGVudGlhbHMgdG8gYmUgc3RvcmVkIGluIHRoZSBjYWNoZTogZWc6IEFDQ0VTU19UT0tFTiwgSURfVE9LRU4gZXRjXHJcbiAqXHJcbiAqIEtleTpWYWx1ZSBTY2hlbWE6XHJcbiAqXHJcbiAqIEtleTogPGhvbWVfYWNjb3VudF9pZCo+LTxlbnZpcm9ubWVudD4tPGNyZWRlbnRpYWxfdHlwZT4tPGNsaWVudF9pZD4tPHJlYWxtKj4tPHRhcmdldCo+XHJcbiAqXHJcbiAqIFZhbHVlIFNjaGVtYTpcclxuICoge1xyXG4gKiAgICAgIGhvbWVBY2NvdW50SWQ6IGhvbWUgYWNjb3VudCBpZGVudGlmaWVyIGZvciB0aGUgYXV0aCBzY2hlbWUsXHJcbiAqICAgICAgZW52aXJvbm1lbnQ6IGVudGl0eSB0aGF0IGlzc3VlZCB0aGUgdG9rZW4sIHJlcHJlc2VudGVkIGFzIGEgZnVsbCBob3N0XHJcbiAqICAgICAgY3JlZGVudGlhbFR5cGU6IFR5cGUgb2YgY3JlZGVudGlhbCBhcyBhIHN0cmluZywgY2FuIGJlIG9uZSBvZiB0aGUgZm9sbG93aW5nOiBSZWZyZXNoVG9rZW4sIEFjY2Vzc1Rva2VuLCBJZFRva2VuLCBQYXNzd29yZCwgQ29va2llLCBDZXJ0aWZpY2F0ZSwgT3RoZXJcclxuICogICAgICBjbGllbnRJZDogY2xpZW50IElEIG9mIHRoZSBhcHBsaWNhdGlvblxyXG4gKiAgICAgIHNlY3JldDogQWN0dWFsIGNyZWRlbnRpYWwgYXMgYSBzdHJpbmdcclxuICogICAgICBmYW1pbHlJZDogRmFtaWx5IElEIGlkZW50aWZpZXIsIHVzdWFsbHkgb25seSB1c2VkIGZvciByZWZyZXNoIHRva2Vuc1xyXG4gKiAgICAgIHJlYWxtOiBGdWxsIHRlbmFudCBvciBvcmdhbml6YXRpb25hbCBpZGVudGlmaWVyIHRoYXQgdGhlIGFjY291bnQgYmVsb25ncyB0b1xyXG4gKiAgICAgIHRhcmdldDogUGVybWlzc2lvbnMgdGhhdCBhcmUgaW5jbHVkZWQgaW4gdGhlIHRva2VuLCBvciBmb3IgcmVmcmVzaCB0b2tlbnMsIHRoZSByZXNvdXJjZSBpZGVudGlmaWVyLlxyXG4gKiAgICAgIG9ib0Fzc2VydGlvbjogYWNjZXNzIHRva2VuIHBhc3NlZCBpbiBhcyBwYXJ0IG9mIE9CTyByZXF1ZXN0XHJcbiAqIH1cclxuICovXHJcbmV4cG9ydCBjbGFzcyBDcmVkZW50aWFsRW50aXR5IHtcclxuICAgIGhvbWVBY2NvdW50SWQ6IHN0cmluZztcclxuICAgIGVudmlyb25tZW50OiBzdHJpbmc7XHJcbiAgICBjcmVkZW50aWFsVHlwZTogQ3JlZGVudGlhbFR5cGU7XHJcbiAgICBjbGllbnRJZDogc3RyaW5nO1xyXG4gICAgc2VjcmV0OiBzdHJpbmc7XHJcbiAgICBmYW1pbHlJZD86IHN0cmluZztcclxuICAgIHJlYWxtPzogc3RyaW5nO1xyXG4gICAgdGFyZ2V0Pzogc3RyaW5nO1xyXG4gICAgb2JvQXNzZXJ0aW9uPzogc3RyaW5nO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2VuZXJhdGUgQWNjb3VudCBJZCBrZXkgY29tcG9uZW50IGFzIHBlciB0aGUgc2NoZW1hOiA8aG9tZV9hY2NvdW50X2lkPi08ZW52aXJvbm1lbnQ+XHJcbiAgICAgKi9cclxuICAgIGdlbmVyYXRlQWNjb3VudElkKCk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIENyZWRlbnRpYWxFbnRpdHkuZ2VuZXJhdGVBY2NvdW50SWRGb3JDYWNoZUtleSh0aGlzLmhvbWVBY2NvdW50SWQsIHRoaXMuZW52aXJvbm1lbnQpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2VuZXJhdGUgQ3JlZGVudGlhbCBJZCBrZXkgY29tcG9uZW50IGFzIHBlciB0aGUgc2NoZW1hOiA8Y3JlZGVudGlhbF90eXBlPi08Y2xpZW50X2lkPi08cmVhbG0+XHJcbiAgICAgKi9cclxuICAgIGdlbmVyYXRlQ3JlZGVudGlhbElkKCk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIENyZWRlbnRpYWxFbnRpdHkuZ2VuZXJhdGVDcmVkZW50aWFsSWRGb3JDYWNoZUtleShcclxuICAgICAgICAgICAgdGhpcy5jcmVkZW50aWFsVHlwZSxcclxuICAgICAgICAgICAgdGhpcy5jbGllbnRJZCxcclxuICAgICAgICAgICAgdGhpcy5yZWFsbSxcclxuICAgICAgICAgICAgdGhpcy5mYW1pbHlJZFxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZW5lcmF0ZSB0YXJnZXQga2V5IGNvbXBvbmVudCBhcyBwZXIgc2NoZW1hOiA8dGFyZ2V0PlxyXG4gICAgICovXHJcbiAgICBnZW5lcmF0ZVRhcmdldCgpOiBzdHJpbmcge1xyXG4gICAgICAgIHJldHVybiBDcmVkZW50aWFsRW50aXR5LmdlbmVyYXRlVGFyZ2V0Rm9yQ2FjaGVLZXkodGhpcy50YXJnZXQpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogZ2VuZXJhdGVzIGNyZWRlbnRpYWwga2V5XHJcbiAgICAgKi9cclxuICAgIGdlbmVyYXRlQ3JlZGVudGlhbEtleSgpOiBzdHJpbmcge1xyXG4gICAgICAgIHJldHVybiBDcmVkZW50aWFsRW50aXR5LmdlbmVyYXRlQ3JlZGVudGlhbENhY2hlS2V5KFxyXG4gICAgICAgICAgICB0aGlzLmhvbWVBY2NvdW50SWQsXHJcbiAgICAgICAgICAgIHRoaXMuZW52aXJvbm1lbnQsXHJcbiAgICAgICAgICAgIHRoaXMuY3JlZGVudGlhbFR5cGUsXHJcbiAgICAgICAgICAgIHRoaXMuY2xpZW50SWQsXHJcbiAgICAgICAgICAgIHRoaXMucmVhbG0sXHJcbiAgICAgICAgICAgIHRoaXMudGFyZ2V0LFxyXG4gICAgICAgICAgICB0aGlzLmZhbWlseUlkXHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIHJldHVybnMgdGhlIHR5cGUgb2YgdGhlIGNhY2hlIChpbiB0aGlzIGNhc2UgY3JlZGVudGlhbClcclxuICAgICAqL1xyXG4gICAgZ2VuZXJhdGVUeXBlKCk6IG51bWJlciB7XHJcbiAgICAgICAgc3dpdGNoICh0aGlzLmNyZWRlbnRpYWxUeXBlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgQ3JlZGVudGlhbFR5cGUuSURfVE9LRU46XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gQ2FjaGVUeXBlLklEX1RPS0VOO1xyXG4gICAgICAgICAgICBjYXNlIENyZWRlbnRpYWxUeXBlLkFDQ0VTU19UT0tFTjpcclxuICAgICAgICAgICAgICAgIHJldHVybiBDYWNoZVR5cGUuQUNDRVNTX1RPS0VOO1xyXG4gICAgICAgICAgICBjYXNlIENyZWRlbnRpYWxUeXBlLlJFRlJFU0hfVE9LRU46XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gQ2FjaGVUeXBlLlJFRlJFU0hfVE9LRU47XHJcbiAgICAgICAgICAgIGRlZmF1bHQ6IHtcclxuICAgICAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVVbmV4cGVjdGVkQ3JlZGVudGlhbFR5cGVFcnJvcigpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogaGVscGVyIGZ1bmN0aW9uIHRvIHJldHVybiBgQ3JlZGVudGlhbFR5cGVgXHJcbiAgICAgKiBAcGFyYW0ga2V5XHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBnZXRDcmVkZW50aWFsVHlwZShrZXk6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgaWYgKGtleS5pbmRleE9mKENyZWRlbnRpYWxUeXBlLkFDQ0VTU19UT0tFTi50b0xvd2VyQ2FzZSgpKSAhPT0gLTEpIHtcclxuICAgICAgICAgICAgcmV0dXJuIENyZWRlbnRpYWxUeXBlLkFDQ0VTU19UT0tFTjtcclxuICAgICAgICB9IGVsc2UgaWYgKGtleS5pbmRleE9mKENyZWRlbnRpYWxUeXBlLklEX1RPS0VOLnRvTG93ZXJDYXNlKCkpICE9PSAtMSkge1xyXG4gICAgICAgICAgICByZXR1cm4gQ3JlZGVudGlhbFR5cGUuSURfVE9LRU47XHJcbiAgICAgICAgfSBlbHNlIGlmIChrZXkuaW5kZXhPZihDcmVkZW50aWFsVHlwZS5SRUZSRVNIX1RPS0VOLnRvTG93ZXJDYXNlKCkpICE9PSAtMSkge1xyXG4gICAgICAgICAgICByZXR1cm4gQ3JlZGVudGlhbFR5cGUuUkVGUkVTSF9UT0tFTjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBDb25zdGFudHMuTk9UX0RFRklORUQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBnZW5lcmF0ZXMgY3JlZGVudGlhbCBrZXlcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGdlbmVyYXRlQ3JlZGVudGlhbENhY2hlS2V5KFxyXG4gICAgICAgIGhvbWVBY2NvdW50SWQ6IHN0cmluZyxcclxuICAgICAgICBlbnZpcm9ubWVudDogc3RyaW5nLFxyXG4gICAgICAgIGNyZWRlbnRpYWxUeXBlOiBDcmVkZW50aWFsVHlwZSxcclxuICAgICAgICBjbGllbnRJZDogc3RyaW5nLFxyXG4gICAgICAgIHJlYWxtPzogc3RyaW5nLFxyXG4gICAgICAgIHRhcmdldD86IHN0cmluZyxcclxuICAgICAgICBmYW1pbHlJZD86IHN0cmluZ1xyXG4gICAgKTogc3RyaW5nIHtcclxuICAgICAgICBjb25zdCBjcmVkZW50aWFsS2V5ID0gW1xyXG4gICAgICAgICAgICB0aGlzLmdlbmVyYXRlQWNjb3VudElkRm9yQ2FjaGVLZXkoaG9tZUFjY291bnRJZCwgZW52aXJvbm1lbnQpLFxyXG4gICAgICAgICAgICB0aGlzLmdlbmVyYXRlQ3JlZGVudGlhbElkRm9yQ2FjaGVLZXkoY3JlZGVudGlhbFR5cGUsIGNsaWVudElkLCByZWFsbSwgZmFtaWx5SWQpLFxyXG4gICAgICAgICAgICB0aGlzLmdlbmVyYXRlVGFyZ2V0Rm9yQ2FjaGVLZXkodGFyZ2V0KSxcclxuICAgICAgICBdO1xyXG5cclxuICAgICAgICByZXR1cm4gY3JlZGVudGlhbEtleS5qb2luKFNlcGFyYXRvcnMuQ0FDSEVfS0VZX1NFUEFSQVRPUikudG9Mb3dlckNhc2UoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGdlbmVyYXRlcyBBY2NvdW50IElkIGZvciBrZXlzXHJcbiAgICAgKiBAcGFyYW0gaG9tZUFjY291bnRJZFxyXG4gICAgICogQHBhcmFtIGVudmlyb25tZW50XHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgc3RhdGljIGdlbmVyYXRlQWNjb3VudElkRm9yQ2FjaGVLZXkoXHJcbiAgICAgICAgaG9tZUFjY291bnRJZDogc3RyaW5nLFxyXG4gICAgICAgIGVudmlyb25tZW50OiBzdHJpbmdcclxuICAgICk6IHN0cmluZyB7XHJcbiAgICAgICAgY29uc3QgYWNjb3VudElkOiBBcnJheTxzdHJpbmc+ID0gW2hvbWVBY2NvdW50SWQsIGVudmlyb25tZW50XTtcclxuICAgICAgICByZXR1cm4gYWNjb3VudElkLmpvaW4oU2VwYXJhdG9ycy5DQUNIRV9LRVlfU0VQQVJBVE9SKS50b0xvd2VyQ2FzZSgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2VuZXJhdGVzIENyZWRlbnRpYWwgSWQgZm9yIGtleXNcclxuICAgICAqIEBwYXJhbSBjcmVkZW50aWFsVHlwZVxyXG4gICAgICogQHBhcmFtIHJlYWxtXHJcbiAgICAgKiBAcGFyYW0gY2xpZW50SWRcclxuICAgICAqIEBwYXJhbSBmYW1pbHlJZFxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHN0YXRpYyBnZW5lcmF0ZUNyZWRlbnRpYWxJZEZvckNhY2hlS2V5KFxyXG4gICAgICAgIGNyZWRlbnRpYWxUeXBlOiBDcmVkZW50aWFsVHlwZSxcclxuICAgICAgICBjbGllbnRJZDogc3RyaW5nLFxyXG4gICAgICAgIHJlYWxtPzogc3RyaW5nLFxyXG4gICAgICAgIGZhbWlseUlkPzogc3RyaW5nXHJcbiAgICApOiBzdHJpbmcge1xyXG4gICAgICAgIGNvbnN0IGNsaWVudE9yRmFtaWx5SWQgPVxyXG4gICAgICAgICAgICBjcmVkZW50aWFsVHlwZSA9PT0gQ3JlZGVudGlhbFR5cGUuUkVGUkVTSF9UT0tFTlxyXG4gICAgICAgICAgICAgICAgPyBmYW1pbHlJZCB8fCBjbGllbnRJZFxyXG4gICAgICAgICAgICAgICAgOiBjbGllbnRJZDtcclxuICAgICAgICBjb25zdCBjcmVkZW50aWFsSWQ6IEFycmF5PHN0cmluZz4gPSBbXHJcbiAgICAgICAgICAgIGNyZWRlbnRpYWxUeXBlLFxyXG4gICAgICAgICAgICBjbGllbnRPckZhbWlseUlkLFxyXG4gICAgICAgICAgICByZWFsbSB8fCBcIlwiLFxyXG4gICAgICAgIF07XHJcblxyXG4gICAgICAgIHJldHVybiBjcmVkZW50aWFsSWQuam9pbihTZXBhcmF0b3JzLkNBQ0hFX0tFWV9TRVBBUkFUT1IpLnRvTG93ZXJDYXNlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZW5lcmF0ZSB0YXJnZXQga2V5IGNvbXBvbmVudCBhcyBwZXIgc2NoZW1hOiA8dGFyZ2V0PlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHN0YXRpYyBnZW5lcmF0ZVRhcmdldEZvckNhY2hlS2V5KHNjb3Blcz86IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIChzY29wZXMgfHwgXCJcIikudG9Mb3dlckNhc2UoKTtcclxuICAgIH1cclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IENsaWVudEF1dGhFcnJvciB9IGZyb20gXCIuL0NsaWVudEF1dGhFcnJvclwiO1xyXG5cclxuLyoqXHJcbiAqIENsaWVudENvbmZpZ3VyYXRpb25FcnJvck1lc3NhZ2UgY2xhc3MgY29udGFpbmluZyBzdHJpbmcgY29uc3RhbnRzIHVzZWQgYnkgZXJyb3IgY29kZXMgYW5kIG1lc3NhZ2VzLlxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IENsaWVudENvbmZpZ3VyYXRpb25FcnJvck1lc3NhZ2UgPSB7XHJcbiAgICByZWRpcmVjdFVyaU5vdFNldDoge1xyXG4gICAgICAgIGNvZGU6IFwicmVkaXJlY3RfdXJpX2VtcHR5XCIsXHJcbiAgICAgICAgZGVzYzogXCJBIHJlZGlyZWN0IFVSSSBpcyByZXF1aXJlZCBmb3IgYWxsIGNhbGxzLCBhbmQgbm9uZSBoYXMgYmVlbiBzZXQuXCJcclxuICAgIH0sXHJcbiAgICBwb3N0TG9nb3V0VXJpTm90U2V0OiB7XHJcbiAgICAgICAgY29kZTogXCJwb3N0X2xvZ291dF91cmlfZW1wdHlcIixcclxuICAgICAgICBkZXNjOiBcIkEgcG9zdCBsb2dvdXQgcmVkaXJlY3QgaGFzIG5vdCBiZWVuIHNldC5cIlxyXG4gICAgfSxcclxuICAgIGNsYWltc1JlcXVlc3RQYXJzaW5nRXJyb3I6IHtcclxuICAgICAgICBjb2RlOiBcImNsYWltc19yZXF1ZXN0X3BhcnNpbmdfZXJyb3JcIixcclxuICAgICAgICBkZXNjOiBcIkNvdWxkIG5vdCBwYXJzZSB0aGUgZ2l2ZW4gY2xhaW1zIHJlcXVlc3Qgb2JqZWN0LlwiXHJcbiAgICB9LFxyXG4gICAgYXV0aG9yaXR5VXJpSW5zZWN1cmU6IHtcclxuICAgICAgICBjb2RlOiBcImF1dGhvcml0eV91cmlfaW5zZWN1cmVcIixcclxuICAgICAgICBkZXNjOiBcIkF1dGhvcml0eSBVUklzIG11c3QgdXNlIGh0dHBzLiAgUGxlYXNlIHNlZSBoZXJlIGZvciB2YWxpZCBhdXRob3JpdHkgY29uZmlndXJhdGlvbiBvcHRpb25zOiBodHRwczovL2RvY3MubWljcm9zb2Z0LmNvbS9lbi11cy9henVyZS9hY3RpdmUtZGlyZWN0b3J5L2RldmVsb3AvbXNhbC1qcy1pbml0aWFsaXppbmctY2xpZW50LWFwcGxpY2F0aW9ucyNjb25maWd1cmF0aW9uLW9wdGlvbnNcIlxyXG4gICAgfSxcclxuICAgIHVybFBhcnNlRXJyb3I6IHtcclxuICAgICAgICBjb2RlOiBcInVybF9wYXJzZV9lcnJvclwiLFxyXG4gICAgICAgIGRlc2M6IFwiVVJMIGNvdWxkIG5vdCBiZSBwYXJzZWQgaW50byBhcHByb3ByaWF0ZSBzZWdtZW50cy5cIlxyXG4gICAgfSxcclxuICAgIHVybEVtcHR5RXJyb3I6IHtcclxuICAgICAgICBjb2RlOiBcImVtcHR5X3VybF9lcnJvclwiLFxyXG4gICAgICAgIGRlc2M6IFwiVVJMIHdhcyBlbXB0eSBvciBudWxsLlwiXHJcbiAgICB9LFxyXG4gICAgZW1wdHlTY29wZXNFcnJvcjoge1xyXG4gICAgICAgIGNvZGU6IFwiZW1wdHlfaW5wdXRfc2NvcGVzX2Vycm9yXCIsXHJcbiAgICAgICAgZGVzYzogXCJTY29wZXMgY2Fubm90IGJlIHBhc3NlZCBhcyBudWxsLCB1bmRlZmluZWQgb3IgZW1wdHkgYXJyYXkgYmVjYXVzZSB0aGV5IGFyZSByZXF1aXJlZCB0byBvYnRhaW4gYW4gYWNjZXNzIHRva2VuLlwiXHJcbiAgICB9LFxyXG4gICAgbm9uQXJyYXlTY29wZXNFcnJvcjoge1xyXG4gICAgICAgIGNvZGU6IFwibm9uYXJyYXlfaW5wdXRfc2NvcGVzX2Vycm9yXCIsXHJcbiAgICAgICAgZGVzYzogXCJTY29wZXMgY2Fubm90IGJlIHBhc3NlZCBhcyBub24tYXJyYXkuXCJcclxuICAgIH0sXHJcbiAgICBjbGllbnRJZFNpbmdsZVNjb3BlRXJyb3I6IHtcclxuICAgICAgICBjb2RlOiBcImNsaWVudGlkX2lucHV0X3Njb3Blc19lcnJvclwiLFxyXG4gICAgICAgIGRlc2M6IFwiQ2xpZW50IElEIGNhbiBvbmx5IGJlIHByb3ZpZGVkIGFzIGEgc2luZ2xlIHNjb3BlLlwiXHJcbiAgICB9LFxyXG4gICAgaW52YWxpZFByb21wdDoge1xyXG4gICAgICAgIGNvZGU6IFwiaW52YWxpZF9wcm9tcHRfdmFsdWVcIixcclxuICAgICAgICBkZXNjOiBcIlN1cHBvcnRlZCBwcm9tcHQgdmFsdWVzIGFyZSAnbG9naW4nLCAnc2VsZWN0X2FjY291bnQnLCAnY29uc2VudCcgYW5kICdub25lJy4gIFBsZWFzZSBzZWUgaGVyZSBmb3IgdmFsaWQgY29uZmlndXJhdGlvbiBvcHRpb25zOiBodHRwczovL2RvY3MubWljcm9zb2Z0LmNvbS9lbi11cy9henVyZS9hY3RpdmUtZGlyZWN0b3J5L2RldmVsb3AvbXNhbC1qcy1pbml0aWFsaXppbmctY2xpZW50LWFwcGxpY2F0aW9ucyNjb25maWd1cmF0aW9uLW9wdGlvbnNcIixcclxuICAgIH0sXHJcbiAgICBpbnZhbGlkQ2xhaW1zUmVxdWVzdDoge1xyXG4gICAgICAgIGNvZGU6IFwiaW52YWxpZF9jbGFpbXNcIixcclxuICAgICAgICBkZXNjOiBcIkdpdmVuIGNsYWltcyBwYXJhbWV0ZXIgbXVzdCBiZSBhIHN0cmluZ2lmaWVkIEpTT04gb2JqZWN0LlwiXHJcbiAgICB9LFxyXG4gICAgdG9rZW5SZXF1ZXN0RW1wdHlFcnJvcjoge1xyXG4gICAgICAgIGNvZGU6IFwidG9rZW5fcmVxdWVzdF9lbXB0eVwiLFxyXG4gICAgICAgIGRlc2M6IFwiVG9rZW4gcmVxdWVzdCB3YXMgZW1wdHkgYW5kIG5vdCBmb3VuZCBpbiBjYWNoZS5cIlxyXG4gICAgfSxcclxuICAgIGxvZ291dFJlcXVlc3RFbXB0eUVycm9yOiB7XHJcbiAgICAgICAgY29kZTogXCJsb2dvdXRfcmVxdWVzdF9lbXB0eVwiLFxyXG4gICAgICAgIGRlc2M6IFwiVGhlIGxvZ291dCByZXF1ZXN0IHdhcyBudWxsIG9yIHVuZGVmaW5lZC5cIlxyXG4gICAgfSxcclxuICAgIGludmFsaWRDb2RlQ2hhbGxlbmdlTWV0aG9kOiB7XHJcbiAgICAgICAgY29kZTogXCJpbnZhbGlkX2NvZGVfY2hhbGxlbmdlX21ldGhvZFwiLFxyXG4gICAgICAgIGRlc2M6IFwiY29kZV9jaGFsbGVuZ2VfbWV0aG9kIHBhc3NlZCBpcyBpbnZhbGlkLiBWYWxpZCB2YWx1ZXMgYXJlIFxcXCJwbGFpblxcXCIgYW5kIFxcXCJTMjU2XFxcIi5cIlxyXG4gICAgfSxcclxuICAgIGludmFsaWRDb2RlQ2hhbGxlbmdlUGFyYW1zOiB7XHJcbiAgICAgICAgY29kZTogXCJwa2NlX3BhcmFtc19taXNzaW5nXCIsXHJcbiAgICAgICAgZGVzYzogXCJCb3RoIHBhcmFtczogY29kZV9jaGFsbGVuZ2UgYW5kIGNvZGVfY2hhbGxlbmdlX21ldGhvZCBhcmUgdG8gYmUgcGFzc2VkIGlmIHRvIGJlIHNlbnQgaW4gdGhlIHJlcXVlc3RcIlxyXG4gICAgfSxcclxuICAgIGludmFsaWRDbG91ZERpc2NvdmVyeU1ldGFkYXRhOiB7XHJcbiAgICAgICAgY29kZTogXCJpbnZhbGlkX2Nsb3VkX2Rpc2NvdmVyeV9tZXRhZGF0YVwiLFxyXG4gICAgICAgIGRlc2M6IFwiSW52YWxpZCBjbG91ZERpc2NvdmVyeU1ldGFkYXRhIHByb3ZpZGVkLiBNdXN0IGJlIGEgSlNPTiBvYmplY3QgY29udGFpbmluZyB0ZW5hbnRfZGlzY292ZXJ5X2VuZHBvaW50IGFuZCBtZXRhZGF0YSBmaWVsZHNcIlxyXG4gICAgfSxcclxuICAgIGludmFsaWRBdXRob3JpdHlNZXRhZGF0YToge1xyXG4gICAgICAgIGNvZGU6IFwiaW52YWxpZF9hdXRob3JpdHlfbWV0YWRhdGFcIixcclxuICAgICAgICBkZXNjOiBcIkludmFsaWQgYXV0aG9yaXR5TWV0YWRhdGEgcHJvdmlkZWQuIE11c3QgYnkgYSBKU09OIG9iamVjdCBjb250YWluaW5nIGF1dGhvcml6YXRpb25fZW5kcG9pbnQsIHRva2VuX2VuZHBvaW50LCBlbmRfc2Vzc2lvbl9lbmRwb2ludCwgaXNzdWVyIGZpZWxkcy5cIlxyXG4gICAgfSxcclxuICAgIHVudHJ1c3RlZEF1dGhvcml0eToge1xyXG4gICAgICAgIGNvZGU6IFwidW50cnVzdGVkX2F1dGhvcml0eVwiLFxyXG4gICAgICAgIGRlc2M6IFwiVGhlIHByb3ZpZGVkIGF1dGhvcml0eSBpcyBub3QgYSB0cnVzdGVkIGF1dGhvcml0eS4gUGxlYXNlIGluY2x1ZGUgdGhpcyBhdXRob3JpdHkgaW4gdGhlIGtub3duQXV0aG9yaXRpZXMgY29uZmlnIHBhcmFtZXRlci5cIlxyXG4gICAgfSxcclxuICAgIHJlc291cmNlUmVxdWVzdFBhcmFtZXRlcnNSZXF1aXJlZDoge1xyXG4gICAgICAgIGNvZGU6IFwicmVzb3VyY2VSZXF1ZXN0X3BhcmFtZXRlcnNfcmVxdWlyZWRcIixcclxuICAgICAgICBkZXNjOiBcInJlc291cmNlUmVxdWVzdE1ldGhvZCBhbmQgcmVzb3VyY2VSZXF1ZXN0VXJpIGFyZSByZXF1aXJlZFwiXHJcbiAgICB9XHJcbn07XHJcblxyXG4vKipcclxuICogRXJyb3IgdGhyb3duIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3IgaW4gY29uZmlndXJhdGlvbiBvZiB0aGUgTVNBTC5qcyBsaWJyYXJ5LlxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIENsaWVudENvbmZpZ3VyYXRpb25FcnJvciBleHRlbmRzIENsaWVudEF1dGhFcnJvciB7XHJcblxyXG4gICAgY29uc3RydWN0b3IoZXJyb3JDb2RlOiBzdHJpbmcsIGVycm9yTWVzc2FnZT86IHN0cmluZykge1xyXG4gICAgICAgIHN1cGVyKGVycm9yQ29kZSwgZXJyb3JNZXNzYWdlKTtcclxuICAgICAgICB0aGlzLm5hbWUgPSBcIkNsaWVudENvbmZpZ3VyYXRpb25FcnJvclwiO1xyXG4gICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBDbGllbnRDb25maWd1cmF0aW9uRXJyb3IucHJvdG90eXBlKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZXMgYW4gZXJyb3IgdGhyb3duIHdoZW4gdGhlIHJlZGlyZWN0IHVyaSBpcyBlbXB0eSAobm90IHNldCBieSBjYWxsZXIpXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVSZWRpcmVjdFVyaUVtcHR5RXJyb3IoKTogQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudENvbmZpZ3VyYXRpb25FcnJvcihDbGllbnRDb25maWd1cmF0aW9uRXJyb3JNZXNzYWdlLnJlZGlyZWN0VXJpTm90U2V0LmNvZGUsXHJcbiAgICAgICAgICAgIENsaWVudENvbmZpZ3VyYXRpb25FcnJvck1lc3NhZ2UucmVkaXJlY3RVcmlOb3RTZXQuZGVzYyk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIGFuIGVycm9yIHRocm93biB3aGVuIHRoZSBwb3N0LWxvZ291dCByZWRpcmVjdCB1cmkgaXMgZW1wdHkgKG5vdCBzZXQgYnkgY2FsbGVyKVxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgY3JlYXRlUG9zdExvZ291dFJlZGlyZWN0VXJpRW1wdHlFcnJvcigpOiBDbGllbnRDb25maWd1cmF0aW9uRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yKENsaWVudENvbmZpZ3VyYXRpb25FcnJvck1lc3NhZ2UucG9zdExvZ291dFVyaU5vdFNldC5jb2RlLFxyXG4gICAgICAgICAgICBDbGllbnRDb25maWd1cmF0aW9uRXJyb3JNZXNzYWdlLnBvc3RMb2dvdXRVcmlOb3RTZXQuZGVzYyk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIGFuIGVycm9yIHRocm93biB3aGVuIHRoZSBjbGFpbXMgcmVxdWVzdCBjb3VsZCBub3QgYmUgc3VjY2Vzc2Z1bGx5IHBhcnNlZFxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgY3JlYXRlQ2xhaW1zUmVxdWVzdFBhcnNpbmdFcnJvcihjbGFpbXNSZXF1ZXN0UGFyc2VFcnJvcjogc3RyaW5nKTogQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudENvbmZpZ3VyYXRpb25FcnJvcihDbGllbnRDb25maWd1cmF0aW9uRXJyb3JNZXNzYWdlLmNsYWltc1JlcXVlc3RQYXJzaW5nRXJyb3IuY29kZSxcclxuICAgICAgICAgICAgYCR7Q2xpZW50Q29uZmlndXJhdGlvbkVycm9yTWVzc2FnZS5jbGFpbXNSZXF1ZXN0UGFyc2luZ0Vycm9yLmRlc2N9IEdpdmVuIHZhbHVlOiAke2NsYWltc1JlcXVlc3RQYXJzZUVycm9yfWApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlcyBhbiBlcnJvciB0aHJvd24gaWYgYXV0aG9yaXR5IHVyaSBpcyBnaXZlbiBhbiBpbnNlY3VyZSBwcm90b2NvbC5cclxuICAgICAqIEBwYXJhbSB1cmxTdHJpbmdcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZUluc2VjdXJlQXV0aG9yaXR5VXJpRXJyb3IodXJsU3RyaW5nOiBzdHJpbmcpOiBDbGllbnRDb25maWd1cmF0aW9uRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yKENsaWVudENvbmZpZ3VyYXRpb25FcnJvck1lc3NhZ2UuYXV0aG9yaXR5VXJpSW5zZWN1cmUuY29kZSxcclxuICAgICAgICAgICAgYCR7Q2xpZW50Q29uZmlndXJhdGlvbkVycm9yTWVzc2FnZS5hdXRob3JpdHlVcmlJbnNlY3VyZS5kZXNjfSBHaXZlbiBVUkk6ICR7dXJsU3RyaW5nfWApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlcyBhbiBlcnJvciB0aHJvd24gaWYgVVJMIHN0cmluZyBkb2VzIG5vdCBwYXJzZSBpbnRvIHNlcGFyYXRlIHNlZ21lbnRzLlxyXG4gICAgICogQHBhcmFtIHVybFN0cmluZ1xyXG4gICAgICovXHJcbiAgICBzdGF0aWMgY3JlYXRlVXJsUGFyc2VFcnJvcih1cmxQYXJzZUVycm9yOiBzdHJpbmcpOiBDbGllbnRDb25maWd1cmF0aW9uRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yKENsaWVudENvbmZpZ3VyYXRpb25FcnJvck1lc3NhZ2UudXJsUGFyc2VFcnJvci5jb2RlLFxyXG4gICAgICAgICAgICBgJHtDbGllbnRDb25maWd1cmF0aW9uRXJyb3JNZXNzYWdlLnVybFBhcnNlRXJyb3IuZGVzY30gR2l2ZW4gRXJyb3I6ICR7dXJsUGFyc2VFcnJvcn1gKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZXMgYW4gZXJyb3IgdGhyb3duIGlmIFVSTCBzdHJpbmcgaXMgZW1wdHkgb3IgbnVsbC5cclxuICAgICAqIEBwYXJhbSB1cmxTdHJpbmdcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZVVybEVtcHR5RXJyb3IoKTogQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudENvbmZpZ3VyYXRpb25FcnJvcihDbGllbnRDb25maWd1cmF0aW9uRXJyb3JNZXNzYWdlLnVybEVtcHR5RXJyb3IuY29kZSxcclxuICAgICAgICAgICAgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yTWVzc2FnZS51cmxFbXB0eUVycm9yLmRlc2MpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRXJyb3IgdGhyb3duIHdoZW4gc2NvcGVzIGFyZSBub3QgYW4gYXJyYXlcclxuICAgICAqIEBwYXJhbSBpbnB1dFNjb3Blc1xyXG4gICAgICovXHJcbiAgICBzdGF0aWMgY3JlYXRlU2NvcGVzTm9uQXJyYXlFcnJvcihpbnB1dFNjb3BlczogQXJyYXk8c3RyaW5nPik6IENsaWVudENvbmZpZ3VyYXRpb25FcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRDb25maWd1cmF0aW9uRXJyb3IoQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yTWVzc2FnZS5ub25BcnJheVNjb3Blc0Vycm9yLmNvZGUsXHJcbiAgICAgICAgICAgIGAke0NsaWVudENvbmZpZ3VyYXRpb25FcnJvck1lc3NhZ2Uubm9uQXJyYXlTY29wZXNFcnJvci5kZXNjfSBHaXZlbiBTY29wZXM6ICR7aW5wdXRTY29wZXN9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBFcnJvciB0aHJvd24gd2hlbiBzY29wZXMgYXJlIGVtcHR5LlxyXG4gICAgICogQHBhcmFtIHNjb3Blc1ZhbHVlXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVFbXB0eVNjb3Blc0FycmF5RXJyb3IoaW5wdXRTY29wZXM6IEFycmF5PHN0cmluZz4pOiBDbGllbnRDb25maWd1cmF0aW9uRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yKENsaWVudENvbmZpZ3VyYXRpb25FcnJvck1lc3NhZ2UuZW1wdHlTY29wZXNFcnJvci5jb2RlLFxyXG4gICAgICAgICAgICBgJHtDbGllbnRDb25maWd1cmF0aW9uRXJyb3JNZXNzYWdlLmVtcHR5U2NvcGVzRXJyb3IuZGVzY30gR2l2ZW4gU2NvcGVzOiAke2lucHV0U2NvcGVzfWApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRXJyb3IgdGhyb3duIHdoZW4gY2xpZW50IGlkIHNjb3BlIGlzIG5vdCBwcm92aWRlZCBhcyBzaW5nbGUgc2NvcGUuXHJcbiAgICAgKiBAcGFyYW0gaW5wdXRTY29wZXNcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZUNsaWVudElkU2luZ2xlU2NvcGVFcnJvcihpbnB1dFNjb3BlczogQXJyYXk8c3RyaW5nPik6IENsaWVudENvbmZpZ3VyYXRpb25FcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRDb25maWd1cmF0aW9uRXJyb3IoQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yTWVzc2FnZS5jbGllbnRJZFNpbmdsZVNjb3BlRXJyb3IuY29kZSxcclxuICAgICAgICAgICAgYCR7Q2xpZW50Q29uZmlndXJhdGlvbkVycm9yTWVzc2FnZS5jbGllbnRJZFNpbmdsZVNjb3BlRXJyb3IuZGVzY30gR2l2ZW4gU2NvcGVzOiAke2lucHV0U2NvcGVzfWApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRXJyb3IgdGhyb3duIHdoZW4gcHJvbXB0IGlzIG5vdCBhbiBhbGxvd2VkIHR5cGUuXHJcbiAgICAgKiBAcGFyYW0gcHJvbXB0VmFsdWVcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZUludmFsaWRQcm9tcHRFcnJvcihwcm9tcHRWYWx1ZTogc3RyaW5nKTogQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudENvbmZpZ3VyYXRpb25FcnJvcihDbGllbnRDb25maWd1cmF0aW9uRXJyb3JNZXNzYWdlLmludmFsaWRQcm9tcHQuY29kZSxcclxuICAgICAgICAgICAgYCR7Q2xpZW50Q29uZmlndXJhdGlvbkVycm9yTWVzc2FnZS5pbnZhbGlkUHJvbXB0LmRlc2N9IEdpdmVuIHZhbHVlOiAke3Byb21wdFZhbHVlfWApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlcyBlcnJvciB0aHJvd24gd2hlbiBjbGFpbXMgcGFyYW1ldGVyIGlzIG5vdCBhIHN0cmluZ2lmaWVkIEpTT04gb2JqZWN0XHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVJbnZhbGlkQ2xhaW1zUmVxdWVzdEVycm9yKCk6IENsaWVudENvbmZpZ3VyYXRpb25FcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRDb25maWd1cmF0aW9uRXJyb3IoQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yTWVzc2FnZS5pbnZhbGlkQ2xhaW1zUmVxdWVzdC5jb2RlLFxyXG4gICAgICAgICAgICBDbGllbnRDb25maWd1cmF0aW9uRXJyb3JNZXNzYWdlLmludmFsaWRDbGFpbXNSZXF1ZXN0LmRlc2MpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhyb3dzIGVycm9yIHdoZW4gdG9rZW4gcmVxdWVzdCBpcyBlbXB0eSBhbmQgbm90aGluZyBjYWNoZWQgaW4gc3RvcmFnZS5cclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZUVtcHR5TG9nb3V0UmVxdWVzdEVycm9yKCk6IENsaWVudENvbmZpZ3VyYXRpb25FcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRDb25maWd1cmF0aW9uRXJyb3IoXHJcbiAgICAgICAgICAgIENsaWVudENvbmZpZ3VyYXRpb25FcnJvck1lc3NhZ2UubG9nb3V0UmVxdWVzdEVtcHR5RXJyb3IuY29kZSxcclxuICAgICAgICAgICAgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yTWVzc2FnZS5sb2dvdXRSZXF1ZXN0RW1wdHlFcnJvci5kZXNjXHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRocm93cyBlcnJvciB3aGVuIHRva2VuIHJlcXVlc3QgaXMgZW1wdHkgYW5kIG5vdGhpbmcgY2FjaGVkIGluIHN0b3JhZ2UuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVFbXB0eVRva2VuUmVxdWVzdEVycm9yKCk6IENsaWVudENvbmZpZ3VyYXRpb25FcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRDb25maWd1cmF0aW9uRXJyb3IoXHJcbiAgICAgICAgICAgIENsaWVudENvbmZpZ3VyYXRpb25FcnJvck1lc3NhZ2UudG9rZW5SZXF1ZXN0RW1wdHlFcnJvci5jb2RlLFxyXG4gICAgICAgICAgICBDbGllbnRDb25maWd1cmF0aW9uRXJyb3JNZXNzYWdlLnRva2VuUmVxdWVzdEVtcHR5RXJyb3IuZGVzY1xyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaHJvd3MgZXJyb3Igd2hlbiBhbiBpbnZhbGlkIGNvZGVfY2hhbGxlbmdlX21ldGhvZCBpcyBwYXNzZWQgYnkgdGhlIHVzZXJcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZUludmFsaWRDb2RlQ2hhbGxlbmdlTWV0aG9kRXJyb3IoKTogQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudENvbmZpZ3VyYXRpb25FcnJvcihcclxuICAgICAgICAgICAgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yTWVzc2FnZS5pbnZhbGlkQ29kZUNoYWxsZW5nZU1ldGhvZC5jb2RlLFxyXG4gICAgICAgICAgICBDbGllbnRDb25maWd1cmF0aW9uRXJyb3JNZXNzYWdlLmludmFsaWRDb2RlQ2hhbGxlbmdlTWV0aG9kLmRlc2NcclxuICAgICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhyb3dzIGVycm9yIHdoZW4gYm90aCBwYXJhbXM6IGNvZGVfY2hhbGxlbmdlIGFuZCBjb2RlX2NoYWxsZW5nZV9tZXRob2QgYXJlIG5vdCBwYXNzZWQgdG9nZXRoZXJcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZUludmFsaWRDb2RlQ2hhbGxlbmdlUGFyYW1zRXJyb3IoKTogQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudENvbmZpZ3VyYXRpb25FcnJvcihcclxuICAgICAgICAgICAgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yTWVzc2FnZS5pbnZhbGlkQ29kZUNoYWxsZW5nZVBhcmFtcy5jb2RlLFxyXG4gICAgICAgICAgICBDbGllbnRDb25maWd1cmF0aW9uRXJyb3JNZXNzYWdlLmludmFsaWRDb2RlQ2hhbGxlbmdlUGFyYW1zLmRlc2NcclxuICAgICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhyb3dzIGFuIGVycm9yIHdoZW4gdGhlIHVzZXIgcGFzc2VzIGludmFsaWQgY2xvdWREaXNjb3ZlcnlNZXRhZGF0YVxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgY3JlYXRlSW52YWxpZENsb3VkRGlzY292ZXJ5TWV0YWRhdGFFcnJvcigpOiBDbGllbnRDb25maWd1cmF0aW9uRXJyb3Ige1xyXG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yKENsaWVudENvbmZpZ3VyYXRpb25FcnJvck1lc3NhZ2UuaW52YWxpZENsb3VkRGlzY292ZXJ5TWV0YWRhdGEuY29kZSxcclxuICAgICAgICAgICAgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yTWVzc2FnZS5pbnZhbGlkQ2xvdWREaXNjb3ZlcnlNZXRhZGF0YS5kZXNjKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRocm93cyBhbiBlcnJvciB3aGVuIHRoZSB1c2VyIHBhc3NlcyBpbnZhbGlkIGNsb3VkRGlzY292ZXJ5TWV0YWRhdGFcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZUludmFsaWRBdXRob3JpdHlNZXRhZGF0YUVycm9yKCk6IENsaWVudENvbmZpZ3VyYXRpb25FcnJvciB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRDb25maWd1cmF0aW9uRXJyb3IoQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yTWVzc2FnZS5pbnZhbGlkQXV0aG9yaXR5TWV0YWRhdGEuY29kZSxcclxuICAgICAgICAgICAgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yTWVzc2FnZS5pbnZhbGlkQXV0aG9yaXR5TWV0YWRhdGEuZGVzYyk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaHJvd3MgZXJyb3Igd2hlbiBwcm92aWRlZCBhdXRob3JpdHkgaXMgbm90IGEgbWVtYmVyIG9mIHRoZSB0cnVzdGVkIGhvc3QgbGlzdFxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgY3JlYXRlVW50cnVzdGVkQXV0aG9yaXR5RXJyb3IoKTogQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudENvbmZpZ3VyYXRpb25FcnJvcihDbGllbnRDb25maWd1cmF0aW9uRXJyb3JNZXNzYWdlLnVudHJ1c3RlZEF1dGhvcml0eS5jb2RlLFxyXG4gICAgICAgICAgICBDbGllbnRDb25maWd1cmF0aW9uRXJyb3JNZXNzYWdlLnVudHJ1c3RlZEF1dGhvcml0eS5kZXNjKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRocm93cyBlcnJvciB3aGVuIHJlc291cmNlUmVxdWVzdE1ldGhvZCBvciByZXNvdXJjZVJlcXVlc3RVcmkgaXMgbWlzc2luZ1xyXG4gICAgICovXHJcbiAgICBzdGF0aWMgY3JlYXRlUmVzb3VyY2VSZXF1ZXN0UGFyYW1ldGVyc1JlcXVpcmVkRXJyb3IoKTogQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yIHtcclxuICAgICAgICByZXR1cm4gbmV3IENsaWVudENvbmZpZ3VyYXRpb25FcnJvcihDbGllbnRDb25maWd1cmF0aW9uRXJyb3JNZXNzYWdlLnJlc291cmNlUmVxdWVzdFBhcmFtZXRlcnNSZXF1aXJlZC5jb2RlLFxyXG4gICAgICAgICAgICBDbGllbnRDb25maWd1cmF0aW9uRXJyb3JNZXNzYWdlLnJlc291cmNlUmVxdWVzdFBhcmFtZXRlcnNSZXF1aXJlZC5kZXNjKTtcclxuICAgIH1cclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IENsaWVudENvbmZpZ3VyYXRpb25FcnJvciB9IGZyb20gXCIuLi9lcnJvci9DbGllbnRDb25maWd1cmF0aW9uRXJyb3JcIjtcclxuaW1wb3J0IHsgU3RyaW5nVXRpbHMgfSBmcm9tIFwiLi4vdXRpbHMvU3RyaW5nVXRpbHNcIjtcclxuaW1wb3J0IHsgQ2xpZW50QXV0aEVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL0NsaWVudEF1dGhFcnJvclwiO1xyXG5pbXBvcnQgeyBPSURDX1NDT1BFUyB9IGZyb20gXCIuLi91dGlscy9Db25zdGFudHNcIjtcclxuXHJcbi8qKlxyXG4gKiBUaGUgU2NvcGVTZXQgY2xhc3MgY3JlYXRlcyBhIHNldCBvZiBzY29wZXMuIFNjb3BlcyBhcmUgY2FzZS1pbnNlbnNpdGl2ZSwgdW5pcXVlIHZhbHVlcywgc28gdGhlIFNldCBvYmplY3QgaW4gSlMgbWFrZXNcclxuICogdGhlIG1vc3Qgc2Vuc2UgdG8gaW1wbGVtZW50IGZvciB0aGlzIGNsYXNzLiBBbGwgc2NvcGVzIGFyZSB0cmltbWVkIGFuZCBjb252ZXJ0ZWQgdG8gbG93ZXIgY2FzZSBzdHJpbmdzIGluIGludGVyc2VjdGlvbiBhbmQgdW5pb24gZnVuY3Rpb25zXHJcbiAqIHRvIGVuc3VyZSB1bmlxdWVuZXNzIG9mIHN0cmluZ3MuXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgU2NvcGVTZXQge1xyXG4gICAgLy8gU2NvcGVzIGFzIGEgU2V0IG9mIHN0cmluZ3NcclxuICAgIHByaXZhdGUgc2NvcGVzOiBTZXQ8c3RyaW5nPjtcclxuXHJcbiAgICBjb25zdHJ1Y3RvcihpbnB1dFNjb3BlczogQXJyYXk8c3RyaW5nPikge1xyXG4gICAgICAgIC8vIEZpbHRlciBlbXB0eSBzdHJpbmcgYW5kIG51bGwvdW5kZWZpbmVkIGFycmF5IGl0ZW1zXHJcbiAgICAgICAgY29uc3Qgc2NvcGVBcnIgPSBpbnB1dFNjb3BlcyA/IFN0cmluZ1V0aWxzLnRyaW1BcnJheUVudHJpZXMoWy4uLmlucHV0U2NvcGVzXSkgOiBbXTtcclxuICAgICAgICBjb25zdCBmaWx0ZXJlZElucHV0ID0gc2NvcGVBcnIgPyBTdHJpbmdVdGlscy5yZW1vdmVFbXB0eVN0cmluZ3NGcm9tQXJyYXkoc2NvcGVBcnIpIDogW107XHJcblxyXG4gICAgICAgIC8vIFZhbGlkYXRlIGFuZCBmaWx0ZXIgc2NvcGVzICh2YWxpZGF0ZSBmdW5jdGlvbiB0aHJvd3MgaWYgdmFsaWRhdGlvbiBmYWlscylcclxuICAgICAgICB0aGlzLnZhbGlkYXRlSW5wdXRTY29wZXMoZmlsdGVyZWRJbnB1dCk7XHJcblxyXG4gICAgICAgIHRoaXMuc2NvcGVzID0gbmV3IFNldDxzdHJpbmc+KCk7IC8vIEl0ZXJhdG9yIGluIGNvbnN0cnVjdG9yIG5vdCBzdXBwb3J0ZWQgYnkgSUUxMVxyXG4gICAgICAgIGZpbHRlcmVkSW5wdXQuZm9yRWFjaChzY29wZSA9PiB0aGlzLnNjb3Blcy5hZGQoc2NvcGUpKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEZhY3RvcnkgbWV0aG9kIHRvIGNyZWF0ZSBTY29wZVNldCBmcm9tIHNwYWNlLWRlbGltaXRlZCBzdHJpbmdcclxuICAgICAqIEBwYXJhbSBpbnB1dFNjb3BlU3RyaW5nXHJcbiAgICAgKiBAcGFyYW0gYXBwQ2xpZW50SWRcclxuICAgICAqIEBwYXJhbSBzY29wZXNSZXF1aXJlZFxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgZnJvbVN0cmluZyhpbnB1dFNjb3BlU3RyaW5nOiBzdHJpbmcpOiBTY29wZVNldCB7XHJcbiAgICAgICAgaW5wdXRTY29wZVN0cmluZyA9IGlucHV0U2NvcGVTdHJpbmcgfHwgXCJcIjtcclxuICAgICAgICBjb25zdCBpbnB1dFNjb3BlczogQXJyYXk8c3RyaW5nPiA9IGlucHV0U2NvcGVTdHJpbmcuc3BsaXQoXCIgXCIpO1xyXG4gICAgICAgIHJldHVybiBuZXcgU2NvcGVTZXQoaW5wdXRTY29wZXMpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVXNlZCB0byB2YWxpZGF0ZSB0aGUgc2NvcGVzIGlucHV0IHBhcmFtZXRlciByZXF1ZXN0ZWQgIGJ5IHRoZSBkZXZlbG9wZXIuXHJcbiAgICAgKiBAcGFyYW0ge0FycmF5PHN0cmluZz59IGlucHV0U2NvcGVzIC0gRGV2ZWxvcGVyIHJlcXVlc3RlZCBwZXJtaXNzaW9ucy4gTm90IGFsbCBzY29wZXMgYXJlIGd1YXJhbnRlZWQgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIGFjY2VzcyB0b2tlbiByZXR1cm5lZC5cclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gc2NvcGVzUmVxdWlyZWQgLSBCb29sZWFuIGluZGljYXRpbmcgd2hldGhlciB0aGUgc2NvcGVzIGFycmF5IGlzIHJlcXVpcmVkIG9yIG5vdFxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHZhbGlkYXRlSW5wdXRTY29wZXMoaW5wdXRTY29wZXM6IEFycmF5PHN0cmluZz4pOiB2b2lkIHtcclxuICAgICAgICAvLyBDaGVjayBpZiBzY29wZXMgYXJlIHJlcXVpcmVkIGJ1dCBub3QgZ2l2ZW4gb3IgaXMgYW4gZW1wdHkgYXJyYXlcclxuICAgICAgICBpZiAoIWlucHV0U2NvcGVzIHx8IGlucHV0U2NvcGVzLmxlbmd0aCA8IDEpIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yLmNyZWF0ZUVtcHR5U2NvcGVzQXJyYXlFcnJvcihpbnB1dFNjb3Blcyk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2hlY2sgaWYgYSBnaXZlbiBzY29wZSBpcyBwcmVzZW50IGluIHRoaXMgc2V0IG9mIHNjb3Blcy5cclxuICAgICAqIEBwYXJhbSBzY29wZVxyXG4gICAgICovXHJcbiAgICBjb250YWluc1Njb3BlKHNjb3BlOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgICAgICBjb25zdCBsb3dlckNhc2VTY29wZXMgPSB0aGlzLnByaW50U2NvcGVzTG93ZXJDYXNlKCkuc3BsaXQoXCIgXCIpO1xyXG4gICAgICAgIGNvbnN0IGxvd2VyQ2FzZVNjb3Blc1NldCA9IG5ldyBTY29wZVNldChsb3dlckNhc2VTY29wZXMpO1xyXG4gICAgICAgIC8vIGNvbXBhcmUgbG93ZXJjYXNlIHNjb3Blc1xyXG4gICAgICAgIHJldHVybiAhU3RyaW5nVXRpbHMuaXNFbXB0eShzY29wZSkgPyBsb3dlckNhc2VTY29wZXNTZXQuc2NvcGVzLmhhcyhzY29wZS50b0xvd2VyQ2FzZSgpKSA6IGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2hlY2sgaWYgYSBzZXQgb2Ygc2NvcGVzIGlzIHByZXNlbnQgaW4gdGhpcyBzZXQgb2Ygc2NvcGVzLlxyXG4gICAgICogQHBhcmFtIHNjb3BlU2V0XHJcbiAgICAgKi9cclxuICAgIGNvbnRhaW5zU2NvcGVTZXQoc2NvcGVTZXQ6IFNjb3BlU2V0KTogYm9vbGVhbiB7XHJcbiAgICAgICAgaWYgKCFzY29wZVNldCB8fCBzY29wZVNldC5zY29wZXMuc2l6ZSA8PSAwKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiAodGhpcy5zY29wZXMuc2l6ZSA+PSBzY29wZVNldC5zY29wZXMuc2l6ZSAmJiBzY29wZVNldC5hc0FycmF5KCkuZXZlcnkoc2NvcGUgPT4gdGhpcy5jb250YWluc1Njb3BlKHNjb3BlKSkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2hlY2sgaWYgc2V0IG9mIHNjb3BlcyBjb250YWlucyBvbmx5IHRoZSBkZWZhdWx0c1xyXG4gICAgICovXHJcbiAgICBjb250YWluc09ubHlPSURDU2NvcGVzKCk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGxldCBkZWZhdWx0U2NvcGVDb3VudCA9IDA7XHJcbiAgICAgICAgT0lEQ19TQ09QRVMuZm9yRWFjaCgoZGVmYXVsdFNjb3BlOiBzdHJpbmcpID0+IHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuY29udGFpbnNTY29wZShkZWZhdWx0U2NvcGUpKSB7XHJcbiAgICAgICAgICAgICAgICBkZWZhdWx0U2NvcGVDb3VudCArPSAxO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzLnNjb3Blcy5zaXplID09PSBkZWZhdWx0U2NvcGVDb3VudDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEFwcGVuZHMgc2luZ2xlIHNjb3BlIGlmIHBhc3NlZFxyXG4gICAgICogQHBhcmFtIG5ld1Njb3BlXHJcbiAgICAgKi9cclxuICAgIGFwcGVuZFNjb3BlKG5ld1Njb3BlOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICBpZiAoIVN0cmluZ1V0aWxzLmlzRW1wdHkobmV3U2NvcGUpKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc2NvcGVzLmFkZChuZXdTY29wZS50cmltKCkpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEFwcGVuZHMgbXVsdGlwbGUgc2NvcGVzIGlmIHBhc3NlZFxyXG4gICAgICogQHBhcmFtIG5ld1Njb3Blc1xyXG4gICAgICovXHJcbiAgICBhcHBlbmRTY29wZXMobmV3U2NvcGVzOiBBcnJheTxzdHJpbmc+KTogdm9pZCB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgbmV3U2NvcGVzLmZvckVhY2gobmV3U2NvcGUgPT4gdGhpcy5hcHBlbmRTY29wZShuZXdTY29wZSkpO1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50QXV0aEVycm9yLmNyZWF0ZUFwcGVuZFNjb3BlU2V0RXJyb3IoZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVtb3ZlcyBlbGVtZW50IGZyb20gc2V0IG9mIHNjb3Blcy5cclxuICAgICAqIEBwYXJhbSBzY29wZVxyXG4gICAgICovXHJcbiAgICByZW1vdmVTY29wZShzY29wZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKFN0cmluZ1V0aWxzLmlzRW1wdHkoc2NvcGUpKSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVSZW1vdmVFbXB0eVNjb3BlRnJvbVNldEVycm9yKHNjb3BlKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5zY29wZXMuZGVsZXRlKHNjb3BlLnRyaW0oKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZW1vdmVzIGRlZmF1bHQgc2NvcGVzIGZyb20gc2V0IG9mIHNjb3Blc1xyXG4gICAgICogUHJpbWFyaWx5IHVzZWQgdG8gcHJldmVudCBjYWNoZSBtaXNzZXMgaWYgdGhlIGRlZmF1bHQgc2NvcGVzIGFyZSBub3QgcmV0dXJuZWQgZnJvbSB0aGUgc2VydmVyXHJcbiAgICAgKi9cclxuICAgIHJlbW92ZU9JRENTY29wZXMoKTogdm9pZCB7XHJcbiAgICAgICAgT0lEQ19TQ09QRVMuZm9yRWFjaCgoZGVmYXVsdFNjb3BlOiBzdHJpbmcpID0+IHtcclxuICAgICAgICAgICAgdGhpcy5zY29wZXMuZGVsZXRlKGRlZmF1bHRTY29wZSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDb21iaW5lcyBhbiBhcnJheSBvZiBzY29wZXMgd2l0aCB0aGUgY3VycmVudCBzZXQgb2Ygc2NvcGVzLlxyXG4gICAgICogQHBhcmFtIG90aGVyU2NvcGVzXHJcbiAgICAgKi9cclxuICAgIHVuaW9uU2NvcGVTZXRzKG90aGVyU2NvcGVzOiBTY29wZVNldCk6IFNldDxzdHJpbmc+IHtcclxuICAgICAgICBpZiAoIW90aGVyU2NvcGVzKSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVFbXB0eUlucHV0U2NvcGVTZXRFcnJvcihvdGhlclNjb3Blcyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IHVuaW9uU2NvcGVzID0gbmV3IFNldDxzdHJpbmc+KCk7IC8vIEl0ZXJhdG9yIGluIGNvbnN0cnVjdG9yIG5vdCBzdXBwb3J0ZWQgaW4gSUUxMVxyXG4gICAgICAgIG90aGVyU2NvcGVzLnNjb3Blcy5mb3JFYWNoKHNjb3BlID0+IHVuaW9uU2NvcGVzLmFkZChzY29wZS50b0xvd2VyQ2FzZSgpKSk7XHJcbiAgICAgICAgdGhpcy5zY29wZXMuZm9yRWFjaChzY29wZSA9PiB1bmlvblNjb3Blcy5hZGQoc2NvcGUudG9Mb3dlckNhc2UoKSkpO1xyXG4gICAgICAgIHJldHVybiB1bmlvblNjb3BlcztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENoZWNrIGlmIHNjb3BlcyBpbnRlcnNlY3QgYmV0d2VlbiB0aGlzIHNldCBhbmQgYW5vdGhlci5cclxuICAgICAqIEBwYXJhbSBvdGhlclNjb3Blc1xyXG4gICAgICovXHJcbiAgICBpbnRlcnNlY3RpbmdTY29wZVNldHMob3RoZXJTY29wZXM6IFNjb3BlU2V0KTogYm9vbGVhbiB7XHJcbiAgICAgICAgaWYgKCFvdGhlclNjb3Blcykge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRBdXRoRXJyb3IuY3JlYXRlRW1wdHlJbnB1dFNjb3BlU2V0RXJyb3Iob3RoZXJTY29wZXMpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICAvLyBEbyBub3QgYWxsb3cgT0lEQyBzY29wZXMgdG8gYmUgdGhlIG9ubHkgaW50ZXJzZWN0aW5nIHNjb3Blc1xyXG4gICAgICAgIGlmICghb3RoZXJTY29wZXMuY29udGFpbnNPbmx5T0lEQ1Njb3BlcygpKSB7XHJcbiAgICAgICAgICAgIG90aGVyU2NvcGVzLnJlbW92ZU9JRENTY29wZXMoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3QgdW5pb25TY29wZXMgPSB0aGlzLnVuaW9uU2NvcGVTZXRzKG90aGVyU2NvcGVzKTtcclxuICAgICAgICBjb25zdCBzaXplT3RoZXJTY29wZXMgPSBvdGhlclNjb3Blcy5nZXRTY29wZUNvdW50KCk7XHJcbiAgICAgICAgY29uc3Qgc2l6ZVRoaXNTY29wZXMgPSB0aGlzLmdldFNjb3BlQ291bnQoKTtcclxuICAgICAgICBjb25zdCBzaXplVW5pb25TY29wZXMgPSB1bmlvblNjb3Blcy5zaXplO1xyXG4gICAgICAgIHJldHVybiBzaXplVW5pb25TY29wZXMgPCAoc2l6ZVRoaXNTY29wZXMgKyBzaXplT3RoZXJTY29wZXMpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyBzaXplIG9mIHNldCBvZiBzY29wZXMuXHJcbiAgICAgKi9cclxuICAgIGdldFNjb3BlQ291bnQoKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5zY29wZXMuc2l6ZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgdGhlIHNjb3BlcyBhcyBhbiBhcnJheSBvZiBzdHJpbmcgdmFsdWVzXHJcbiAgICAgKi9cclxuICAgIGFzQXJyYXkoKTogQXJyYXk8c3RyaW5nPiB7XHJcbiAgICAgICAgY29uc3QgYXJyYXk6IEFycmF5PHN0cmluZz4gPSBbXTtcclxuICAgICAgICB0aGlzLnNjb3Blcy5mb3JFYWNoKHZhbCA9PiBhcnJheS5wdXNoKHZhbCkpO1xyXG4gICAgICAgIHJldHVybiBhcnJheTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFByaW50cyBzY29wZXMgaW50byBhIHNwYWNlLWRlbGltaXRlZCBzdHJpbmdcclxuICAgICAqL1xyXG4gICAgcHJpbnRTY29wZXMoKTogc3RyaW5nIHtcclxuICAgICAgICBpZiAodGhpcy5zY29wZXMpIHtcclxuICAgICAgICAgICAgY29uc3Qgc2NvcGVBcnIgPSB0aGlzLmFzQXJyYXkoKTtcclxuICAgICAgICAgICAgcmV0dXJuIHNjb3BlQXJyLmpvaW4oXCIgXCIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gXCJcIjtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFByaW50cyBzY29wZXMgaW50byBhIHNwYWNlLWRlbGltaXRlZCBsb3dlci1jYXNlIHN0cmluZyAodXNlZCBmb3IgY2FjaGluZylcclxuICAgICAqL1xyXG4gICAgcHJpbnRTY29wZXNMb3dlckNhc2UoKTogc3RyaW5nIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5wcmludFNjb3BlcygpLnRvTG93ZXJDYXNlKCk7XHJcbiAgICB9XHJcbn1cclxuIiwiLypcclxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cclxuICovXHJcblxyXG5pbXBvcnQgeyBDbGllbnRBdXRoRXJyb3IgfSBmcm9tIFwiLi4vZXJyb3IvQ2xpZW50QXV0aEVycm9yXCI7XHJcbmltcG9ydCB7IFN0cmluZ1V0aWxzIH0gZnJvbSBcIi4uL3V0aWxzL1N0cmluZ1V0aWxzXCI7XHJcbmltcG9ydCB7IElDcnlwdG8gfSBmcm9tIFwiLi4vY3J5cHRvL0lDcnlwdG9cIjtcclxuXHJcbi8qKlxyXG4gKiBDbGllbnQgaW5mbyBvYmplY3Qgd2hpY2ggY29uc2lzdHMgb2YgdHdvIElEcy4gTmVlZCB0byBhZGQgbW9yZSBpbmZvIGhlcmUuXHJcbiAqL1xyXG5leHBvcnQgdHlwZSBDbGllbnRJbmZvID0ge1xyXG4gICAgdWlkOiBzdHJpbmcsXHJcbiAgICB1dGlkOiBzdHJpbmdcclxufTtcclxuXHJcbi8qKlxyXG4gKiBGdW5jdGlvbiB0byBidWlsZCBhIGNsaWVudCBpbmZvIG9iamVjdFxyXG4gKiBAcGFyYW0gcmF3Q2xpZW50SW5mb1xyXG4gKiBAcGFyYW0gY3J5cHRvXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRDbGllbnRJbmZvKHJhd0NsaWVudEluZm86IHN0cmluZywgY3J5cHRvOiBJQ3J5cHRvKTogQ2xpZW50SW5mbyB7XHJcbiAgICBpZiAoU3RyaW5nVXRpbHMuaXNFbXB0eShyYXdDbGllbnRJbmZvKSkge1xyXG4gICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVDbGllbnRJbmZvRW1wdHlFcnJvcigpO1xyXG4gICAgfVxyXG5cclxuICAgIHRyeSB7XHJcbiAgICAgICAgY29uc3QgZGVjb2RlZENsaWVudEluZm86IHN0cmluZyA9IGNyeXB0by5iYXNlNjREZWNvZGUocmF3Q2xpZW50SW5mbyk7XHJcbiAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UoZGVjb2RlZENsaWVudEluZm8pIGFzIENsaWVudEluZm87XHJcbiAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgdGhyb3cgQ2xpZW50QXV0aEVycm9yLmNyZWF0ZUNsaWVudEluZm9EZWNvZGluZ0Vycm9yKGUpO1xyXG4gICAgfVxyXG59XHJcbiIsIi8qXHJcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIEF1dGhvcml0eSB0eXBlcyBzdXBwb3J0ZWQgYnkgTVNBTC5cclxuICovXHJcbmV4cG9ydCBlbnVtIEF1dGhvcml0eVR5cGUge1xyXG4gICAgRGVmYXVsdCxcclxuICAgIEFkZnNcclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7XHJcbiAgICBTZXBhcmF0b3JzLFxyXG4gICAgQ2FjaGVBY2NvdW50VHlwZSxcclxuICAgIENhY2hlVHlwZSxcclxuICAgIENvbnN0YW50cyxcclxufSBmcm9tIFwiLi4vLi4vdXRpbHMvQ29uc3RhbnRzXCI7XHJcbmltcG9ydCB7IEF1dGhvcml0eSB9IGZyb20gXCIuLi8uLi9hdXRob3JpdHkvQXV0aG9yaXR5XCI7XHJcbmltcG9ydCB7IEF1dGhUb2tlbiB9IGZyb20gXCIuLi8uLi9hY2NvdW50L0F1dGhUb2tlblwiO1xyXG5pbXBvcnQgeyBJQ3J5cHRvIH0gZnJvbSBcIi4uLy4uL2NyeXB0by9JQ3J5cHRvXCI7XHJcbmltcG9ydCB7IGJ1aWxkQ2xpZW50SW5mbyB9IGZyb20gXCIuLi8uLi9hY2NvdW50L0NsaWVudEluZm9cIjtcclxuaW1wb3J0IHsgU3RyaW5nVXRpbHMgfSBmcm9tIFwiLi4vLi4vdXRpbHMvU3RyaW5nVXRpbHNcIjtcclxuaW1wb3J0IHsgQWNjb3VudEluZm8gfSBmcm9tIFwiLi4vLi4vYWNjb3VudC9BY2NvdW50SW5mb1wiO1xyXG5pbXBvcnQgeyBDbGllbnRBdXRoRXJyb3IgfSBmcm9tIFwiLi4vLi4vZXJyb3IvQ2xpZW50QXV0aEVycm9yXCI7XHJcbmltcG9ydCB7IEF1dGhvcml0eVR5cGUgfSBmcm9tIFwiLi4vLi4vYXV0aG9yaXR5L0F1dGhvcml0eVR5cGVcIjtcclxuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSBcIi4uLy4uL2xvZ2dlci9Mb2dnZXJcIjtcclxuaW1wb3J0IHsgVG9rZW5DbGFpbXMgfSBmcm9tIFwiLi4vLi4vYWNjb3VudC9Ub2tlbkNsYWltc1wiO1xyXG5cclxuLyoqXHJcbiAqIFR5cGUgdGhhdCBkZWZpbmVzIHJlcXVpcmVkIGFuZCBvcHRpb25hbCBwYXJhbWV0ZXJzIGZvciBhbiBBY2NvdW50IGZpZWxkIChiYXNlZCBvbiB1bml2ZXJzYWwgY2FjaGUgc2NoZW1hIGltcGxlbWVudGVkIGJ5IGFsbCBNU0FMcykuXHJcbiAqXHJcbiAqIEtleSA6IFZhbHVlIFNjaGVtYVxyXG4gKlxyXG4gKiBLZXk6IDxob21lX2FjY291bnRfaWQ+LTxlbnZpcm9ubWVudD4tPHJlYWxtKj5cclxuICpcclxuICogVmFsdWUgU2NoZW1hOlxyXG4gKiB7XHJcbiAqICAgICAgaG9tZUFjY291bnRJZDogaG9tZSBhY2NvdW50IGlkZW50aWZpZXIgZm9yIHRoZSBhdXRoIHNjaGVtZSxcclxuICogICAgICBlbnZpcm9ubWVudDogZW50aXR5IHRoYXQgaXNzdWVkIHRoZSB0b2tlbiwgcmVwcmVzZW50ZWQgYXMgYSBmdWxsIGhvc3RcclxuICogICAgICByZWFsbTogRnVsbCB0ZW5hbnQgb3Igb3JnYW5pemF0aW9uYWwgaWRlbnRpZmllciB0aGF0IHRoZSBhY2NvdW50IGJlbG9uZ3MgdG9cclxuICogICAgICBsb2NhbEFjY291bnRJZDogT3JpZ2luYWwgdGVuYW50LXNwZWNpZmljIGFjY291bnRJRCwgdXN1YWxseSB1c2VkIGZvciBsZWdhY3kgY2FzZXNcclxuICogICAgICB1c2VybmFtZTogcHJpbWFyeSB1c2VybmFtZSB0aGF0IHJlcHJlc2VudHMgdGhlIHVzZXIsIHVzdWFsbHkgY29ycmVzcG9uZHMgdG8gcHJlZmVycmVkX3VzZXJuYW1lIGluIHRoZSB2MiBlbmRwdFxyXG4gKiAgICAgIGF1dGhvcml0eVR5cGU6IEFjY291bnRzIGF1dGhvcml0eSB0eXBlIGFzIGEgc3RyaW5nXHJcbiAqICAgICAgbmFtZTogRnVsbCBuYW1lIGZvciB0aGUgYWNjb3VudCwgaW5jbHVkaW5nIGdpdmVuIG5hbWUgYW5kIGZhbWlseSBuYW1lLFxyXG4gKiAgICAgIGNsaWVudEluZm86IEZ1bGwgYmFzZTY0IGVuY29kZWQgY2xpZW50IGluZm8gcmVjZWl2ZWQgZnJvbSBFU1RTXHJcbiAqICAgICAgbGFzdE1vZGlmaWNhdGlvblRpbWU6IGxhc3QgdGltZSB0aGlzIGVudGl0eSB3YXMgbW9kaWZpZWQgaW4gdGhlIGNhY2hlXHJcbiAqICAgICAgbGFzdE1vZGlmaWNhdGlvbkFwcDpcclxuICogICAgICBvYm9Bc3NlcnRpb246IGFjY2VzcyB0b2tlbiBwYXNzZWQgaW4gYXMgcGFydCBvZiBPQk8gcmVxdWVzdFxyXG4gKiAgICAgIGlkVG9rZW5DbGFpbXM6IE9iamVjdCBjb250YWluaW5nIGNsYWltcyBwYXJzZWQgZnJvbSBJRCB0b2tlblxyXG4gKiB9XHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgQWNjb3VudEVudGl0eSB7XHJcbiAgICBob21lQWNjb3VudElkOiBzdHJpbmc7XHJcbiAgICBlbnZpcm9ubWVudDogc3RyaW5nO1xyXG4gICAgcmVhbG06IHN0cmluZztcclxuICAgIGxvY2FsQWNjb3VudElkOiBzdHJpbmc7XHJcbiAgICB1c2VybmFtZTogc3RyaW5nO1xyXG4gICAgYXV0aG9yaXR5VHlwZTogc3RyaW5nO1xyXG4gICAgbmFtZT86IHN0cmluZztcclxuICAgIGNsaWVudEluZm8/OiBzdHJpbmc7XHJcbiAgICBsYXN0TW9kaWZpY2F0aW9uVGltZT86IHN0cmluZztcclxuICAgIGxhc3RNb2RpZmljYXRpb25BcHA/OiBzdHJpbmc7XHJcbiAgICBvYm9Bc3NlcnRpb24/OiBzdHJpbmc7XHJcbiAgICBjbG91ZEdyYXBoSG9zdE5hbWU/OiBzdHJpbmc7XHJcbiAgICBtc0dyYXBoSG9zdD86IHN0cmluZzsgXHJcbiAgICBpZFRva2VuQ2xhaW1zPzogVG9rZW5DbGFpbXM7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZW5lcmF0ZSBBY2NvdW50IElkIGtleSBjb21wb25lbnQgYXMgcGVyIHRoZSBzY2hlbWE6IDxob21lX2FjY291bnRfaWQ+LTxlbnZpcm9ubWVudD5cclxuICAgICAqL1xyXG4gICAgZ2VuZXJhdGVBY2NvdW50SWQoKTogc3RyaW5nIHtcclxuICAgICAgICBjb25zdCBhY2NvdW50SWQ6IEFycmF5PHN0cmluZz4gPSBbdGhpcy5ob21lQWNjb3VudElkLCB0aGlzLmVudmlyb25tZW50XTtcclxuICAgICAgICByZXR1cm4gYWNjb3VudElkLmpvaW4oU2VwYXJhdG9ycy5DQUNIRV9LRVlfU0VQQVJBVE9SKS50b0xvd2VyQ2FzZSgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2VuZXJhdGUgQWNjb3VudCBDYWNoZSBLZXkgYXMgcGVyIHRoZSBzY2hlbWE6IDxob21lX2FjY291bnRfaWQ+LTxlbnZpcm9ubWVudD4tPHJlYWxtKj5cclxuICAgICAqL1xyXG4gICAgZ2VuZXJhdGVBY2NvdW50S2V5KCk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIEFjY291bnRFbnRpdHkuZ2VuZXJhdGVBY2NvdW50Q2FjaGVLZXkoe1xyXG4gICAgICAgICAgICBob21lQWNjb3VudElkOiB0aGlzLmhvbWVBY2NvdW50SWQsXHJcbiAgICAgICAgICAgIGVudmlyb25tZW50OiB0aGlzLmVudmlyb25tZW50LFxyXG4gICAgICAgICAgICB0ZW5hbnRJZDogdGhpcy5yZWFsbSxcclxuICAgICAgICAgICAgdXNlcm5hbWU6IHRoaXMudXNlcm5hbWUsXHJcbiAgICAgICAgICAgIGxvY2FsQWNjb3VudElkOiB0aGlzLmxvY2FsQWNjb3VudElkXHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiByZXR1cm5zIHRoZSB0eXBlIG9mIHRoZSBjYWNoZSAoaW4gdGhpcyBjYXNlIGFjY291bnQpXHJcbiAgICAgKi9cclxuICAgIGdlbmVyYXRlVHlwZSgpOiBudW1iZXIge1xyXG4gICAgICAgIHN3aXRjaCAodGhpcy5hdXRob3JpdHlUeXBlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgQ2FjaGVBY2NvdW50VHlwZS5BREZTX0FDQ09VTlRfVFlQRTpcclxuICAgICAgICAgICAgICAgIHJldHVybiBDYWNoZVR5cGUuQURGUztcclxuICAgICAgICAgICAgY2FzZSBDYWNoZUFjY291bnRUeXBlLk1TQVYxX0FDQ09VTlRfVFlQRTpcclxuICAgICAgICAgICAgICAgIHJldHVybiBDYWNoZVR5cGUuTVNBO1xyXG4gICAgICAgICAgICBjYXNlIENhY2hlQWNjb3VudFR5cGUuTVNTVFNfQUNDT1VOVF9UWVBFOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIENhY2hlVHlwZS5NU1NUUztcclxuICAgICAgICAgICAgY2FzZSBDYWNoZUFjY291bnRUeXBlLkdFTkVSSUNfQUNDT1VOVF9UWVBFOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIENhY2hlVHlwZS5HRU5FUklDO1xyXG4gICAgICAgICAgICBkZWZhdWx0OiB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBDbGllbnRBdXRoRXJyb3IuY3JlYXRlVW5leHBlY3RlZEFjY291bnRUeXBlRXJyb3IoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgdGhlIEFjY291bnRJbmZvIGludGVyZmFjZSBmb3IgdGhpcyBhY2NvdW50LlxyXG4gICAgICovXHJcbiAgICBnZXRBY2NvdW50SW5mbygpOiBBY2NvdW50SW5mbyB7XHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgaG9tZUFjY291bnRJZDogdGhpcy5ob21lQWNjb3VudElkLFxyXG4gICAgICAgICAgICBlbnZpcm9ubWVudDogdGhpcy5lbnZpcm9ubWVudCxcclxuICAgICAgICAgICAgdGVuYW50SWQ6IHRoaXMucmVhbG0sXHJcbiAgICAgICAgICAgIHVzZXJuYW1lOiB0aGlzLnVzZXJuYW1lLFxyXG4gICAgICAgICAgICBsb2NhbEFjY291bnRJZDogdGhpcy5sb2NhbEFjY291bnRJZCxcclxuICAgICAgICAgICAgbmFtZTogdGhpcy5uYW1lLFxyXG4gICAgICAgICAgICBpZFRva2VuQ2xhaW1zOiB0aGlzLmlkVG9rZW5DbGFpbXNcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2VuZXJhdGVzIGFjY291bnQga2V5IGZyb20gaW50ZXJmYWNlXHJcbiAgICAgKiBAcGFyYW0gYWNjb3VudEludGVyZmFjZVxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgZ2VuZXJhdGVBY2NvdW50Q2FjaGVLZXkoYWNjb3VudEludGVyZmFjZTogQWNjb3VudEluZm8pOiBzdHJpbmcge1xyXG4gICAgICAgIGNvbnN0IGFjY291bnRLZXkgPSBbXHJcbiAgICAgICAgICAgIGFjY291bnRJbnRlcmZhY2UuaG9tZUFjY291bnRJZCxcclxuICAgICAgICAgICAgYWNjb3VudEludGVyZmFjZS5lbnZpcm9ubWVudCB8fCBcIlwiLFxyXG4gICAgICAgICAgICBhY2NvdW50SW50ZXJmYWNlLnRlbmFudElkIHx8IFwiXCIsXHJcbiAgICAgICAgXTtcclxuXHJcbiAgICAgICAgcmV0dXJuIGFjY291bnRLZXkuam9pbihTZXBhcmF0b3JzLkNBQ0hFX0tFWV9TRVBBUkFUT1IpLnRvTG93ZXJDYXNlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBCdWlsZCBBY2NvdW50IGNhY2hlIGZyb20gSWRUb2tlbiwgY2xpZW50SW5mbyBhbmQgYXV0aG9yaXR5L3BvbGljeS4gQXNzb2NpYXRlZCB3aXRoIEFBRC5cclxuICAgICAqIEBwYXJhbSBjbGllbnRJbmZvXHJcbiAgICAgKiBAcGFyYW0gYXV0aG9yaXR5XHJcbiAgICAgKiBAcGFyYW0gaWRUb2tlblxyXG4gICAgICogQHBhcmFtIHBvbGljeVxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgY3JlYXRlQWNjb3VudChcclxuICAgICAgICBjbGllbnRJbmZvOiBzdHJpbmcsXHJcbiAgICAgICAgaG9tZUFjY291bnRJZDogc3RyaW5nLFxyXG4gICAgICAgIGF1dGhvcml0eTogQXV0aG9yaXR5LFxyXG4gICAgICAgIGlkVG9rZW46IEF1dGhUb2tlbixcclxuICAgICAgICBvYm9Bc3NlcnRpb24/OiBzdHJpbmcsXHJcbiAgICAgICAgY2xvdWRHcmFwaEhvc3ROYW1lPzogc3RyaW5nLFxyXG4gICAgICAgIG1zR3JhcGhIb3N0Pzogc3RyaW5nXHJcbiAgICApOiBBY2NvdW50RW50aXR5IHtcclxuICAgICAgICBjb25zdCBhY2NvdW50OiBBY2NvdW50RW50aXR5ID0gbmV3IEFjY291bnRFbnRpdHkoKTtcclxuXHJcbiAgICAgICAgYWNjb3VudC5hdXRob3JpdHlUeXBlID0gQ2FjaGVBY2NvdW50VHlwZS5NU1NUU19BQ0NPVU5UX1RZUEU7XHJcbiAgICAgICAgYWNjb3VudC5jbGllbnRJbmZvID0gY2xpZW50SW5mbztcclxuICAgICAgICBhY2NvdW50LmhvbWVBY2NvdW50SWQgPSBob21lQWNjb3VudElkO1xyXG5cclxuICAgICAgICBjb25zdCBlbnYgPSBhdXRob3JpdHkuZ2V0UHJlZmVycmVkQ2FjaGUoKTtcclxuICAgICAgICBpZiAoU3RyaW5nVXRpbHMuaXNFbXB0eShlbnYpKSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVJbnZhbGlkQ2FjaGVFbnZpcm9ubWVudEVycm9yKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBhY2NvdW50LmVudmlyb25tZW50ID0gZW52O1xyXG4gICAgICAgIC8vIG5vbiBBQUQgc2NlbmFyaW9zIGNhbiBoYXZlIGVtcHR5IHJlYWxtXHJcbiAgICAgICAgYWNjb3VudC5yZWFsbSA9IGlkVG9rZW4/LmNsYWltcz8udGlkIHx8IFwiXCI7XHJcbiAgICAgICAgYWNjb3VudC5vYm9Bc3NlcnRpb24gPSBvYm9Bc3NlcnRpb247XHJcbiAgICAgICAgXHJcbiAgICAgICAgaWYgKGlkVG9rZW4pIHtcclxuICAgICAgICAgICAgYWNjb3VudC5pZFRva2VuQ2xhaW1zID0gaWRUb2tlbi5jbGFpbXM7XHJcblxyXG4gICAgICAgICAgICAvLyBIb3cgZG8geW91IGFjY291bnQgZm9yIE1TQSBDSUQgaGVyZT9cclxuICAgICAgICAgICAgYWNjb3VudC5sb2NhbEFjY291bnRJZCA9IGlkVG9rZW4/LmNsYWltcz8ub2lkIHx8IGlkVG9rZW4/LmNsYWltcz8uc3ViIHx8IFwiXCI7XHJcblxyXG4gICAgICAgICAgICAvKlxyXG4gICAgICAgICAgICAgKiBJbiBCMkMgc2NlbmFyaW9zIHRoZSBlbWFpbHMgY2xhaW0gaXMgdXNlZCBpbnN0ZWFkIG9mIHByZWZlcnJlZF91c2VybmFtZSBhbmQgaXQgaXMgYW4gYXJyYXkuIEluIG1vc3QgY2FzZXMgaXQgd2lsbCBjb250YWluIGEgc2luZ2xlIGVtYWlsLlxyXG4gICAgICAgICAgICAgKiBUaGlzIGZpZWxkIHNob3VsZCBub3QgYmUgcmVsaWVkIHVwb24gaWYgYSBjdXN0b20gcG9saWN5IGlzIGNvbmZpZ3VyZWQgdG8gcmV0dXJuIG1vcmUgdGhhbiAxIGVtYWlsLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgYWNjb3VudC51c2VybmFtZSA9IGlkVG9rZW4/LmNsYWltcz8ucHJlZmVycmVkX3VzZXJuYW1lIHx8IChpZFRva2VuPy5jbGFpbXM/LmVtYWlscz8gaWRUb2tlbi5jbGFpbXMuZW1haWxzWzBdOiBcIlwiKTtcclxuICAgICAgICAgICAgYWNjb3VudC5uYW1lID0gaWRUb2tlbj8uY2xhaW1zPy5uYW1lO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgYWNjb3VudC5jbG91ZEdyYXBoSG9zdE5hbWUgPSBjbG91ZEdyYXBoSG9zdE5hbWU7XHJcbiAgICAgICAgYWNjb3VudC5tc0dyYXBoSG9zdCA9IG1zR3JhcGhIb3N0O1xyXG5cclxuICAgICAgICByZXR1cm4gYWNjb3VudDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEJ1aWxkcyBub24tQUFEL0FERlMgYWNjb3VudC5cclxuICAgICAqIEBwYXJhbSBhdXRob3JpdHlcclxuICAgICAqIEBwYXJhbSBpZFRva2VuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVHZW5lcmljQWNjb3VudChcclxuICAgICAgICBhdXRob3JpdHk6IEF1dGhvcml0eSxcclxuICAgICAgICBob21lQWNjb3VudElkOiBzdHJpbmcsXHJcbiAgICAgICAgaWRUb2tlbjogQXV0aFRva2VuLFxyXG4gICAgICAgIG9ib0Fzc2VydGlvbj86IHN0cmluZyxcclxuICAgICAgICBjbG91ZEdyYXBoSG9zdE5hbWU/OiBzdHJpbmcsXHJcbiAgICAgICAgbXNHcmFwaEhvc3Q/OiBzdHJpbmdcclxuICAgICk6IEFjY291bnRFbnRpdHkge1xyXG4gICAgICAgIGNvbnN0IGFjY291bnQ6IEFjY291bnRFbnRpdHkgPSBuZXcgQWNjb3VudEVudGl0eSgpO1xyXG5cclxuICAgICAgICBhY2NvdW50LmF1dGhvcml0eVR5cGUgPSAoYXV0aG9yaXR5LmF1dGhvcml0eVR5cGUgPT09IEF1dGhvcml0eVR5cGUuQWRmcykgPyBDYWNoZUFjY291bnRUeXBlLkFERlNfQUNDT1VOVF9UWVBFIDogQ2FjaGVBY2NvdW50VHlwZS5HRU5FUklDX0FDQ09VTlRfVFlQRTtcclxuICAgICAgICBhY2NvdW50LmhvbWVBY2NvdW50SWQgPSBob21lQWNjb3VudElkO1xyXG4gICAgICAgIC8vIG5vbiBBQUQgc2NlbmFyaW9zIGNhbiBoYXZlIGVtcHR5IHJlYWxtXHJcbiAgICAgICAgYWNjb3VudC5yZWFsbSA9IFwiXCI7XHJcbiAgICAgICAgYWNjb3VudC5vYm9Bc3NlcnRpb24gPSBvYm9Bc3NlcnRpb247XHJcblxyXG4gICAgICAgIGNvbnN0IGVudiA9IGF1dGhvcml0eS5nZXRQcmVmZXJyZWRDYWNoZSgpO1xyXG5cclxuICAgICAgICBpZiAoU3RyaW5nVXRpbHMuaXNFbXB0eShlbnYpKSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVJbnZhbGlkQ2FjaGVFbnZpcm9ubWVudEVycm9yKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoaWRUb2tlbikge1xyXG4gICAgICAgICAgICAvLyBIb3cgZG8geW91IGFjY291bnQgZm9yIE1TQSBDSUQgaGVyZT9cclxuICAgICAgICAgICAgYWNjb3VudC5sb2NhbEFjY291bnRJZCA9IGlkVG9rZW4/LmNsYWltcz8ub2lkIHx8IGlkVG9rZW4/LmNsYWltcz8uc3ViIHx8IFwiXCI7XHJcbiAgICAgICAgICAgIC8vIHVwbiBjbGFpbSBmb3IgbW9zdCBBREZTIHNjZW5hcmlvc1xyXG4gICAgICAgICAgICBhY2NvdW50LnVzZXJuYW1lID0gaWRUb2tlbj8uY2xhaW1zPy51cG4gfHwgXCJcIjtcclxuICAgICAgICAgICAgYWNjb3VudC5uYW1lID0gaWRUb2tlbj8uY2xhaW1zPy5uYW1lIHx8IFwiXCI7XHJcbiAgICAgICAgICAgIGFjY291bnQuaWRUb2tlbkNsYWltcyA9IGlkVG9rZW4/LmNsYWltcztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGFjY291bnQuZW52aXJvbm1lbnQgPSBlbnY7XHJcblxyXG4gICAgICAgIGFjY291bnQuY2xvdWRHcmFwaEhvc3ROYW1lID0gY2xvdWRHcmFwaEhvc3ROYW1lO1xyXG4gICAgICAgIGFjY291bnQubXNHcmFwaEhvc3QgPSBtc0dyYXBoSG9zdDtcclxuXHJcbiAgICAgICAgLypcclxuICAgICAgICAgKiBhZGQgdW5pcXVlTmFtZSB0byBjbGFpbXNcclxuICAgICAgICAgKiBhY2NvdW50Lm5hbWUgPSBpZFRva2VuLmNsYWltcy51bmlxdWVOYW1lO1xyXG4gICAgICAgICAqL1xyXG5cclxuICAgICAgICByZXR1cm4gYWNjb3VudDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdlbmVyYXRlIEhvbWVBY2NvdW50SWQgZnJvbSBzZXJ2ZXIgcmVzcG9uc2VcclxuICAgICAqIEBwYXJhbSBzZXJ2ZXJDbGllbnRJbmZvXHJcbiAgICAgKiBAcGFyYW0gYXV0aFR5cGVcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGdlbmVyYXRlSG9tZUFjY291bnRJZChzZXJ2ZXJDbGllbnRJbmZvOiBzdHJpbmcsIGF1dGhUeXBlOiBBdXRob3JpdHlUeXBlLCBsb2dnZXI6IExvZ2dlciwgY3J5cHRvT2JqOiBJQ3J5cHRvLCBpZFRva2VuPzogQXV0aFRva2VuKTogc3RyaW5nIHtcclxuXHJcbiAgICAgICAgY29uc3QgYWNjb3VudElkID0gaWRUb2tlbj8uY2xhaW1zPy5zdWIgPyBpZFRva2VuLmNsYWltcy5zdWIgOiBDb25zdGFudHMuRU1QVFlfU1RSSU5HO1xyXG5cclxuICAgICAgICAvLyBzaW5jZSBBREZTIGRvZXMgbm90IGhhdmUgdGlkIGFuZCBkb2VzIG5vdCBzZXQgY2xpZW50X2luZm9cclxuICAgICAgICBpZiAoYXV0aFR5cGUgPT09IEF1dGhvcml0eVR5cGUuQWRmcykge1xyXG4gICAgICAgICAgICByZXR1cm4gYWNjb3VudElkO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gZm9yIGNhc2VzIHdoZXJlIHRoZXJlIGlzIGNsaWVudEluZm9cclxuICAgICAgICBpZiAoc2VydmVyQ2xpZW50SW5mbykge1xyXG4gICAgICAgICAgICBjb25zdCBjbGllbnRJbmZvID0gYnVpbGRDbGllbnRJbmZvKHNlcnZlckNsaWVudEluZm8sIGNyeXB0b09iaik7XHJcbiAgICAgICAgICAgIGlmICghU3RyaW5nVXRpbHMuaXNFbXB0eShjbGllbnRJbmZvLnVpZCkgJiYgIVN0cmluZ1V0aWxzLmlzRW1wdHkoY2xpZW50SW5mby51dGlkKSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGAke2NsaWVudEluZm8udWlkfSR7U2VwYXJhdG9ycy5DTElFTlRfSU5GT19TRVBBUkFUT1J9JHtjbGllbnRJbmZvLnV0aWR9YDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gZGVmYXVsdCB0byBcInN1YlwiIGNsYWltXHJcbiAgICAgICAgbG9nZ2VyLnZlcmJvc2UoXCJObyBjbGllbnQgaW5mbyBpbiByZXNwb25zZVwiKTtcclxuICAgICAgICByZXR1cm4gYWNjb3VudElkO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVmFsaWRhdGVzIGFuIGVudGl0eTogY2hlY2tzIGZvciBhbGwgZXhwZWN0ZWQgcGFyYW1zXHJcbiAgICAgKiBAcGFyYW0gZW50aXR5XHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBpc0FjY291bnRFbnRpdHkoZW50aXR5OiBvYmplY3QpOiBib29sZWFuIHtcclxuXHJcbiAgICAgICAgaWYgKCFlbnRpdHkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgZW50aXR5Lmhhc093blByb3BlcnR5KFwiaG9tZUFjY291bnRJZFwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJlbnZpcm9ubWVudFwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJyZWFsbVwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJsb2NhbEFjY291bnRJZFwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJ1c2VybmFtZVwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJhdXRob3JpdHlUeXBlXCIpXHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEhlbHBlciBmdW5jdGlvbiB0byBkZXRlcm1pbmUgd2hldGhlciAyIGFjY291bnRzIGFyZSBlcXVhbFxyXG4gICAgICogVXNlZCB0byBhdm9pZCB1bm5lY2Vzc2FyeSBzdGF0ZSB1cGRhdGVzXHJcbiAgICAgKiBAcGFyYW0gYXJyYXlBIFxyXG4gICAgICogQHBhcmFtIGFycmF5QiBcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGFjY291bnRJbmZvSXNFcXVhbChhY2NvdW50QTogQWNjb3VudEluZm8gfCBudWxsLCBhY2NvdW50QjogQWNjb3VudEluZm8gfCBudWxsKTogYm9vbGVhbiB7XHJcbiAgICAgICAgaWYgKCFhY2NvdW50QSB8fCAhYWNjb3VudEIpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gKGFjY291bnRBLmhvbWVBY2NvdW50SWQgPT09IGFjY291bnRCLmhvbWVBY2NvdW50SWQpICYmIFxyXG4gICAgICAgICAgICAoYWNjb3VudEEubG9jYWxBY2NvdW50SWQgPT09IGFjY291bnRCLmxvY2FsQWNjb3VudElkKSAmJlxyXG4gICAgICAgICAgICAoYWNjb3VudEEudXNlcm5hbWUgPT09IGFjY291bnRCLnVzZXJuYW1lKSAmJlxyXG4gICAgICAgICAgICAoYWNjb3VudEEudGVuYW50SWQgPT09IGFjY291bnRCLnRlbmFudElkKSAmJlxyXG4gICAgICAgICAgICAoYWNjb3VudEEuZW52aXJvbm1lbnQgPT09IGFjY291bnRCLmVudmlyb25tZW50KTtcclxuICAgIH1cclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IFRva2VuQ2xhaW1zIH0gZnJvbSBcIi4vVG9rZW5DbGFpbXNcIjtcclxuaW1wb3J0IHsgRGVjb2RlZEF1dGhUb2tlbiB9IGZyb20gXCIuL0RlY29kZWRBdXRoVG9rZW5cIjtcclxuaW1wb3J0IHsgQ2xpZW50QXV0aEVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL0NsaWVudEF1dGhFcnJvclwiO1xyXG5pbXBvcnQgeyBTdHJpbmdVdGlscyB9IGZyb20gXCIuLi91dGlscy9TdHJpbmdVdGlsc1wiO1xyXG5pbXBvcnQgeyBJQ3J5cHRvIH0gZnJvbSBcIi4uL2NyeXB0by9JQ3J5cHRvXCI7XHJcblxyXG4vKipcclxuICogSldUIFRva2VuIHJlcHJlc2VudGF0aW9uIGNsYXNzLiBQYXJzZXMgdG9rZW4gc3RyaW5nIGFuZCBnZW5lcmF0ZXMgY2xhaW1zIG9iamVjdC5cclxuICovXHJcbmV4cG9ydCBjbGFzcyBBdXRoVG9rZW4ge1xyXG5cclxuICAgIC8vIFJhdyBUb2tlbiBzdHJpbmdcclxuICAgIHJhd1Rva2VuOiBzdHJpbmc7XHJcbiAgICAvLyBDbGFpbXMgaW5zaWRlIHRva2VuXHJcbiAgICBjbGFpbXM6IFRva2VuQ2xhaW1zO1xyXG4gICAgY29uc3RydWN0b3IocmF3VG9rZW46IHN0cmluZywgY3J5cHRvOiBJQ3J5cHRvKSB7XHJcbiAgICAgICAgaWYgKFN0cmluZ1V0aWxzLmlzRW1wdHkocmF3VG9rZW4pKSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVUb2tlbk51bGxPckVtcHR5RXJyb3IocmF3VG9rZW4pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5yYXdUb2tlbiA9IHJhd1Rva2VuO1xyXG4gICAgICAgIHRoaXMuY2xhaW1zID0gQXV0aFRva2VuLmV4dHJhY3RUb2tlbkNsYWltcyhyYXdUb2tlbiwgY3J5cHRvKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEV4dHJhY3QgdG9rZW4gYnkgZGVjb2RpbmcgdGhlIHJhd1Rva2VuXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIGVuY29kZWRUb2tlblxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgZXh0cmFjdFRva2VuQ2xhaW1zKGVuY29kZWRUb2tlbjogc3RyaW5nLCBjcnlwdG86IElDcnlwdG8pOiBUb2tlbkNsYWltcyB7XHJcblxyXG4gICAgICAgIGNvbnN0IGRlY29kZWRUb2tlbjogRGVjb2RlZEF1dGhUb2tlbiA9IFN0cmluZ1V0aWxzLmRlY29kZUF1dGhUb2tlbihlbmNvZGVkVG9rZW4pO1xyXG5cclxuICAgICAgICAvLyB0b2tlbiB3aWxsIGJlIGRlY29kZWQgdG8gZ2V0IHRoZSB1c2VybmFtZVxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGJhc2U2NFRva2VuUGF5bG9hZCA9IGRlY29kZWRUb2tlbi5KV1NQYXlsb2FkO1xyXG5cclxuICAgICAgICAgICAgLy8gYmFzZTY0RGVjb2RlKCkgc2hvdWxkIHRocm93IGFuIGVycm9yIGlmIHRoZXJlIGlzIGFuIGlzc3VlXHJcbiAgICAgICAgICAgIGNvbnN0IGJhc2U2NERlY29kZWQgPSBjcnlwdG8uYmFzZTY0RGVjb2RlKGJhc2U2NFRva2VuUGF5bG9hZCk7XHJcbiAgICAgICAgICAgIHJldHVybiBKU09OLnBhcnNlKGJhc2U2NERlY29kZWQpIGFzIFRva2VuQ2xhaW1zO1xyXG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRBdXRoRXJyb3IuY3JlYXRlVG9rZW5QYXJzaW5nRXJyb3IoZXJyKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuIiwiLypcclxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cclxuICovXHJcblxyXG5pbXBvcnQgeyBBY2NvdW50Q2FjaGUsIEFjY291bnRGaWx0ZXIsIENyZWRlbnRpYWxGaWx0ZXIsIENyZWRlbnRpYWxDYWNoZSwgVmFsaWRDcmVkZW50aWFsVHlwZSwgQXBwTWV0YWRhdGFGaWx0ZXIsIEFwcE1ldGFkYXRhQ2FjaGUgfSBmcm9tIFwiLi91dGlscy9DYWNoZVR5cGVzXCI7XHJcbmltcG9ydCB7IENhY2hlUmVjb3JkIH0gZnJvbSBcIi4vZW50aXRpZXMvQ2FjaGVSZWNvcmRcIjtcclxuaW1wb3J0IHsgQ2FjaGVTY2hlbWFUeXBlLCBDcmVkZW50aWFsVHlwZSwgQ29uc3RhbnRzLCBBUFBfTUVUQURBVEEsIFRIRV9GQU1JTFlfSUQsIEFVVEhPUklUWV9NRVRBREFUQV9DT05TVEFOVFMgfSBmcm9tIFwiLi4vdXRpbHMvQ29uc3RhbnRzXCI7XHJcbmltcG9ydCB7IENyZWRlbnRpYWxFbnRpdHkgfSBmcm9tIFwiLi9lbnRpdGllcy9DcmVkZW50aWFsRW50aXR5XCI7XHJcbmltcG9ydCB7IFNjb3BlU2V0IH0gZnJvbSBcIi4uL3JlcXVlc3QvU2NvcGVTZXRcIjtcclxuaW1wb3J0IHsgQWNjb3VudEVudGl0eSB9IGZyb20gXCIuL2VudGl0aWVzL0FjY291bnRFbnRpdHlcIjtcclxuaW1wb3J0IHsgQWNjZXNzVG9rZW5FbnRpdHkgfSBmcm9tIFwiLi9lbnRpdGllcy9BY2Nlc3NUb2tlbkVudGl0eVwiO1xyXG5pbXBvcnQgeyBJZFRva2VuRW50aXR5IH0gZnJvbSBcIi4vZW50aXRpZXMvSWRUb2tlbkVudGl0eVwiO1xyXG5pbXBvcnQgeyBSZWZyZXNoVG9rZW5FbnRpdHkgfSBmcm9tIFwiLi9lbnRpdGllcy9SZWZyZXNoVG9rZW5FbnRpdHlcIjtcclxuaW1wb3J0IHsgQXV0aEVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL0F1dGhFcnJvclwiO1xyXG5pbXBvcnQgeyBJQ2FjaGVNYW5hZ2VyIH0gZnJvbSBcIi4vaW50ZXJmYWNlL0lDYWNoZU1hbmFnZXJcIjtcclxuaW1wb3J0IHsgQ2xpZW50QXV0aEVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL0NsaWVudEF1dGhFcnJvclwiO1xyXG5pbXBvcnQgeyBBY2NvdW50SW5mbyB9IGZyb20gXCIuLi9hY2NvdW50L0FjY291bnRJbmZvXCI7XHJcbmltcG9ydCB7IEFwcE1ldGFkYXRhRW50aXR5IH0gZnJvbSBcIi4vZW50aXRpZXMvQXBwTWV0YWRhdGFFbnRpdHlcIjtcclxuaW1wb3J0IHsgU2VydmVyVGVsZW1ldHJ5RW50aXR5IH0gZnJvbSBcIi4vZW50aXRpZXMvU2VydmVyVGVsZW1ldHJ5RW50aXR5XCI7XHJcbmltcG9ydCB7IFRocm90dGxpbmdFbnRpdHkgfSBmcm9tIFwiLi9lbnRpdGllcy9UaHJvdHRsaW5nRW50aXR5XCI7XHJcbmltcG9ydCB7IEF1dGhUb2tlbiB9IGZyb20gXCIuLi9hY2NvdW50L0F1dGhUb2tlblwiO1xyXG5pbXBvcnQgeyBJQ3J5cHRvIH0gZnJvbSBcIi4uL2NyeXB0by9JQ3J5cHRvXCI7XHJcbmltcG9ydCB7IEF1dGhvcml0eU1ldGFkYXRhRW50aXR5IH0gZnJvbSBcIi4vZW50aXRpZXMvQXV0aG9yaXR5TWV0YWRhdGFFbnRpdHlcIjtcclxuXHJcbi8qKlxyXG4gKiBJbnRlcmZhY2UgY2xhc3Mgd2hpY2ggaW1wbGVtZW50IGNhY2hlIHN0b3JhZ2UgZnVuY3Rpb25zIHVzZWQgYnkgTVNBTCB0byBwZXJmb3JtIHZhbGlkaXR5IGNoZWNrcywgYW5kIHN0b3JlIHRva2Vucy5cclxuICovXHJcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBDYWNoZU1hbmFnZXIgaW1wbGVtZW50cyBJQ2FjaGVNYW5hZ2VyIHtcclxuICAgIHByb3RlY3RlZCBjbGllbnRJZDogc3RyaW5nO1xyXG4gICAgcHJvdGVjdGVkIGNyeXB0b0ltcGw6IElDcnlwdG87XHJcblxyXG4gICAgY29uc3RydWN0b3IoY2xpZW50SWQ6IHN0cmluZywgY3J5cHRvSW1wbDogSUNyeXB0bykge1xyXG4gICAgICAgIHRoaXMuY2xpZW50SWQgPSBjbGllbnRJZDtcclxuICAgICAgICB0aGlzLmNyeXB0b0ltcGwgPSBjcnlwdG9JbXBsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogZmV0Y2ggdGhlIGFjY291bnQgZW50aXR5IGZyb20gdGhlIHBsYXRmb3JtIGNhY2hlXHJcbiAgICAgKiAgQHBhcmFtIGFjY291bnRLZXlcclxuICAgICAqL1xyXG4gICAgYWJzdHJhY3QgZ2V0QWNjb3VudChhY2NvdW50S2V5OiBzdHJpbmcpOiBBY2NvdW50RW50aXR5IHwgbnVsbDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIHNldCBhY2NvdW50IGVudGl0eSBpbiB0aGUgcGxhdGZvcm0gY2FjaGVcclxuICAgICAqIEBwYXJhbSBhY2NvdW50XHJcbiAgICAgKi9cclxuICAgIGFic3RyYWN0IHNldEFjY291bnQoYWNjb3VudDogQWNjb3VudEVudGl0eSk6IHZvaWQ7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBmZXRjaCB0aGUgaWRUb2tlbiBlbnRpdHkgZnJvbSB0aGUgcGxhdGZvcm0gY2FjaGVcclxuICAgICAqIEBwYXJhbSBpZFRva2VuS2V5XHJcbiAgICAgKi9cclxuICAgIGFic3RyYWN0IGdldElkVG9rZW5DcmVkZW50aWFsKGlkVG9rZW5LZXk6IHN0cmluZyk6IElkVG9rZW5FbnRpdHkgfCBudWxsO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogc2V0IGlkVG9rZW4gZW50aXR5IHRvIHRoZSBwbGF0Zm9ybSBjYWNoZVxyXG4gICAgICogQHBhcmFtIGlkVG9rZW5cclxuICAgICAqL1xyXG4gICAgYWJzdHJhY3Qgc2V0SWRUb2tlbkNyZWRlbnRpYWwoaWRUb2tlbjogSWRUb2tlbkVudGl0eSk6IHZvaWQ7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBmZXRjaCB0aGUgaWRUb2tlbiBlbnRpdHkgZnJvbSB0aGUgcGxhdGZvcm0gY2FjaGVcclxuICAgICAqIEBwYXJhbSBhY2Nlc3NUb2tlbktleVxyXG4gICAgICovXHJcbiAgICBhYnN0cmFjdCBnZXRBY2Nlc3NUb2tlbkNyZWRlbnRpYWwoYWNjZXNzVG9rZW5LZXk6IHN0cmluZyk6IEFjY2Vzc1Rva2VuRW50aXR5IHwgbnVsbDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIHNldCBpZFRva2VuIGVudGl0eSB0byB0aGUgcGxhdGZvcm0gY2FjaGVcclxuICAgICAqIEBwYXJhbSBhY2Nlc3NUb2tlblxyXG4gICAgICovXHJcbiAgICBhYnN0cmFjdCBzZXRBY2Nlc3NUb2tlbkNyZWRlbnRpYWwoYWNjZXNzVG9rZW46IEFjY2Vzc1Rva2VuRW50aXR5KTogdm9pZDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIGZldGNoIHRoZSBpZFRva2VuIGVudGl0eSBmcm9tIHRoZSBwbGF0Zm9ybSBjYWNoZVxyXG4gICAgICogQHBhcmFtIHJlZnJlc2hUb2tlbktleVxyXG4gICAgICovXHJcbiAgICBhYnN0cmFjdCBnZXRSZWZyZXNoVG9rZW5DcmVkZW50aWFsKHJlZnJlc2hUb2tlbktleTogc3RyaW5nKTogUmVmcmVzaFRva2VuRW50aXR5IHwgbnVsbDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIHNldCBpZFRva2VuIGVudGl0eSB0byB0aGUgcGxhdGZvcm0gY2FjaGVcclxuICAgICAqIEBwYXJhbSByZWZyZXNoVG9rZW5cclxuICAgICAqL1xyXG4gICAgYWJzdHJhY3Qgc2V0UmVmcmVzaFRva2VuQ3JlZGVudGlhbChyZWZyZXNoVG9rZW46IFJlZnJlc2hUb2tlbkVudGl0eSk6IHZvaWQ7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBmZXRjaCBhcHBNZXRhZGF0YSBlbnRpdHkgZnJvbSB0aGUgcGxhdGZvcm0gY2FjaGVcclxuICAgICAqIEBwYXJhbSBhcHBNZXRhZGF0YUtleVxyXG4gICAgICovXHJcbiAgICBhYnN0cmFjdCBnZXRBcHBNZXRhZGF0YShhcHBNZXRhZGF0YUtleTogc3RyaW5nKTogQXBwTWV0YWRhdGFFbnRpdHkgfCBudWxsO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogc2V0IGFwcE1ldGFkYXRhIGVudGl0eSB0byB0aGUgcGxhdGZvcm0gY2FjaGVcclxuICAgICAqIEBwYXJhbSBhcHBNZXRhZGF0YVxyXG4gICAgICovXHJcbiAgICBhYnN0cmFjdCBzZXRBcHBNZXRhZGF0YShhcHBNZXRhZGF0YTogQXBwTWV0YWRhdGFFbnRpdHkpOiB2b2lkO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogZmV0Y2ggc2VydmVyIHRlbGVtZXRyeSBlbnRpdHkgZnJvbSB0aGUgcGxhdGZvcm0gY2FjaGVcclxuICAgICAqIEBwYXJhbSBzZXJ2ZXJUZWxlbWV0cnlLZXlcclxuICAgICAqL1xyXG4gICAgYWJzdHJhY3QgZ2V0U2VydmVyVGVsZW1ldHJ5KHNlcnZlclRlbGVtZXRyeUtleTogc3RyaW5nKTogU2VydmVyVGVsZW1ldHJ5RW50aXR5IHwgbnVsbDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIHNldCBzZXJ2ZXIgdGVsZW1ldHJ5IGVudGl0eSB0byB0aGUgcGxhdGZvcm0gY2FjaGVcclxuICAgICAqIEBwYXJhbSBzZXJ2ZXJUZWxlbWV0cnlLZXlcclxuICAgICAqIEBwYXJhbSBzZXJ2ZXJUZWxlbWV0cnlcclxuICAgICAqL1xyXG4gICAgYWJzdHJhY3Qgc2V0U2VydmVyVGVsZW1ldHJ5KHNlcnZlclRlbGVtZXRyeUtleTogc3RyaW5nLCBzZXJ2ZXJUZWxlbWV0cnk6IFNlcnZlclRlbGVtZXRyeUVudGl0eSk6IHZvaWQ7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBmZXRjaCBjbG91ZCBkaXNjb3ZlcnkgbWV0YWRhdGEgZW50aXR5IGZyb20gdGhlIHBsYXRmb3JtIGNhY2hlXHJcbiAgICAgKiBAcGFyYW0ga2V5XHJcbiAgICAgKi9cclxuICAgIGFic3RyYWN0IGdldEF1dGhvcml0eU1ldGFkYXRhKGtleTogc3RyaW5nKTogQXV0aG9yaXR5TWV0YWRhdGFFbnRpdHkgfCBudWxsO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogXHJcbiAgICAgKi9cclxuICAgIGFic3RyYWN0IGdldEF1dGhvcml0eU1ldGFkYXRhS2V5cygpOiBBcnJheTxzdHJpbmc+O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogc2V0IGNsb3VkIGRpc2NvdmVyeSBtZXRhZGF0YSBlbnRpdHkgdG8gdGhlIHBsYXRmb3JtIGNhY2hlXHJcbiAgICAgKiBAcGFyYW0ga2V5XHJcbiAgICAgKiBAcGFyYW0gdmFsdWVcclxuICAgICAqL1xyXG4gICAgYWJzdHJhY3Qgc2V0QXV0aG9yaXR5TWV0YWRhdGEoa2V5OiBzdHJpbmcsIHZhbHVlOiBBdXRob3JpdHlNZXRhZGF0YUVudGl0eSk6IHZvaWQ7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBmZXRjaCB0aHJvdHRsaW5nIGVudGl0eSBmcm9tIHRoZSBwbGF0Zm9ybSBjYWNoZVxyXG4gICAgICogQHBhcmFtIHRocm90dGxpbmdDYWNoZUtleVxyXG4gICAgICovXHJcbiAgICBhYnN0cmFjdCBnZXRUaHJvdHRsaW5nQ2FjaGUodGhyb3R0bGluZ0NhY2hlS2V5OiBzdHJpbmcpOiBUaHJvdHRsaW5nRW50aXR5IHwgbnVsbDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIHNldCB0aHJvdHRsaW5nIGVudGl0eSB0byB0aGUgcGxhdGZvcm0gY2FjaGVcclxuICAgICAqIEBwYXJhbSB0aHJvdHRsaW5nQ2FjaGVLZXlcclxuICAgICAqIEBwYXJhbSB0aHJvdHRsaW5nQ2FjaGVcclxuICAgICAqL1xyXG4gICAgYWJzdHJhY3Qgc2V0VGhyb3R0bGluZ0NhY2hlKHRocm90dGxpbmdDYWNoZUtleTogc3RyaW5nLCB0aHJvdHRsaW5nQ2FjaGU6IFRocm90dGxpbmdFbnRpdHkpOiB2b2lkOztcclxuXHJcbiAgICAvKipcclxuICAgICAqIEZ1bmN0aW9uIHRvIHJlbW92ZSBhbiBpdGVtIGZyb20gY2FjaGUgZ2l2ZW4gaXRzIGtleS5cclxuICAgICAqIEBwYXJhbSBrZXlcclxuICAgICAqL1xyXG4gICAgYWJzdHJhY3QgcmVtb3ZlSXRlbShrZXk6IHN0cmluZywgdHlwZT86IHN0cmluZyk6IGJvb2xlYW47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBGdW5jdGlvbiB3aGljaCByZXR1cm5zIGJvb2xlYW4gd2hldGhlciBjYWNoZSBjb250YWlucyBhIHNwZWNpZmljIGtleS5cclxuICAgICAqIEBwYXJhbSBrZXlcclxuICAgICAqL1xyXG4gICAgYWJzdHJhY3QgY29udGFpbnNLZXkoa2V5OiBzdHJpbmcsIHR5cGU/OiBzdHJpbmcpOiBib29sZWFuO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRnVuY3Rpb24gd2hpY2ggcmV0cmlldmVzIGFsbCBjdXJyZW50IGtleXMgZnJvbSB0aGUgY2FjaGUuXHJcbiAgICAgKi9cclxuICAgIGFic3RyYWN0IGdldEtleXMoKTogc3RyaW5nW107XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBGdW5jdGlvbiB3aGljaCBjbGVhcnMgY2FjaGUuXHJcbiAgICAgKi9cclxuICAgIGFic3RyYWN0IGNsZWFyKCk6IHZvaWQ7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIGFsbCBhY2NvdW50cyBpbiBjYWNoZVxyXG4gICAgICovXHJcbiAgICBnZXRBbGxBY2NvdW50cygpOiBBY2NvdW50SW5mb1tdIHtcclxuICAgICAgICBjb25zdCBjdXJyZW50QWNjb3VudHM6IEFjY291bnRDYWNoZSA9IHRoaXMuZ2V0QWNjb3VudHNGaWx0ZXJlZEJ5KCk7XHJcbiAgICAgICAgY29uc3QgYWNjb3VudFZhbHVlczogQWNjb3VudEVudGl0eVtdID0gT2JqZWN0LmtleXMoY3VycmVudEFjY291bnRzKS5tYXAoYWNjb3VudEtleSA9PiBjdXJyZW50QWNjb3VudHNbYWNjb3VudEtleV0pO1xyXG4gICAgICAgIGNvbnN0IG51bUFjY291bnRzID0gYWNjb3VudFZhbHVlcy5sZW5ndGg7XHJcbiAgICAgICAgaWYgKG51bUFjY291bnRzIDwgMSkge1xyXG4gICAgICAgICAgICByZXR1cm4gW107XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgY29uc3QgYWxsQWNjb3VudHMgPSBhY2NvdW50VmFsdWVzLm1hcDxBY2NvdW50SW5mbz4oKHZhbHVlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBhY2NvdW50RW50aXR5ID0gQ2FjaGVNYW5hZ2VyLnRvT2JqZWN0PEFjY291bnRFbnRpdHk+KG5ldyBBY2NvdW50RW50aXR5KCksIHZhbHVlKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGFjY291bnRJbmZvID0gYWNjb3VudEVudGl0eS5nZXRBY2NvdW50SW5mbygpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgaWRUb2tlbiA9IHRoaXMucmVhZElkVG9rZW5Gcm9tQ2FjaGUodGhpcy5jbGllbnRJZCwgYWNjb3VudEluZm8pO1xyXG4gICAgICAgICAgICAgICAgaWYgKGlkVG9rZW4gJiYgIWFjY291bnRJbmZvLmlkVG9rZW5DbGFpbXMpIHtcclxuICAgICAgICAgICAgICAgICAgICBhY2NvdW50SW5mby5pZFRva2VuQ2xhaW1zID0gbmV3IEF1dGhUb2tlbihpZFRva2VuLnNlY3JldCwgdGhpcy5jcnlwdG9JbXBsKS5jbGFpbXM7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFjY291bnRJbmZvO1xyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICByZXR1cm4gYWxsQWNjb3VudHM7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogc2F2ZXMgYSBjYWNoZSByZWNvcmRcclxuICAgICAqIEBwYXJhbSBjYWNoZVJlY29yZFxyXG4gICAgICovXHJcbiAgICBzYXZlQ2FjaGVSZWNvcmQoY2FjaGVSZWNvcmQ6IENhY2hlUmVjb3JkKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKCFjYWNoZVJlY29yZCkge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRBdXRoRXJyb3IuY3JlYXRlTnVsbE9yVW5kZWZpbmVkQ2FjaGVSZWNvcmQoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICghIWNhY2hlUmVjb3JkLmFjY291bnQpIHtcclxuICAgICAgICAgICAgdGhpcy5zZXRBY2NvdW50KGNhY2hlUmVjb3JkLmFjY291bnQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCEhY2FjaGVSZWNvcmQuaWRUb2tlbikge1xyXG4gICAgICAgICAgICB0aGlzLnNldElkVG9rZW5DcmVkZW50aWFsKGNhY2hlUmVjb3JkLmlkVG9rZW4pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCEhY2FjaGVSZWNvcmQuYWNjZXNzVG9rZW4pIHtcclxuICAgICAgICAgICAgdGhpcy5zYXZlQWNjZXNzVG9rZW4oY2FjaGVSZWNvcmQuYWNjZXNzVG9rZW4pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCEhY2FjaGVSZWNvcmQucmVmcmVzaFRva2VuKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc2V0UmVmcmVzaFRva2VuQ3JlZGVudGlhbChjYWNoZVJlY29yZC5yZWZyZXNoVG9rZW4pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCEhY2FjaGVSZWNvcmQuYXBwTWV0YWRhdGEpIHtcclxuICAgICAgICAgICAgdGhpcy5zZXRBcHBNZXRhZGF0YShjYWNoZVJlY29yZC5hcHBNZXRhZGF0YSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogc2F2ZXMgYWNjZXNzIHRva2VuIGNyZWRlbnRpYWxcclxuICAgICAqIEBwYXJhbSBjcmVkZW50aWFsXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgc2F2ZUFjY2Vzc1Rva2VuKGNyZWRlbnRpYWw6IEFjY2Vzc1Rva2VuRW50aXR5KTogdm9pZCB7XHJcbiAgICAgICAgY29uc3QgY3VycmVudFRva2VuQ2FjaGUgPSB0aGlzLmdldENyZWRlbnRpYWxzRmlsdGVyZWRCeSh7XHJcbiAgICAgICAgICAgIGNsaWVudElkOiBjcmVkZW50aWFsLmNsaWVudElkLFxyXG4gICAgICAgICAgICBjcmVkZW50aWFsVHlwZTogQ3JlZGVudGlhbFR5cGUuQUNDRVNTX1RPS0VOLFxyXG4gICAgICAgICAgICBlbnZpcm9ubWVudDogY3JlZGVudGlhbC5lbnZpcm9ubWVudCxcclxuICAgICAgICAgICAgaG9tZUFjY291bnRJZDogY3JlZGVudGlhbC5ob21lQWNjb3VudElkLFxyXG4gICAgICAgICAgICByZWFsbTogY3JlZGVudGlhbC5yZWFsbSxcclxuICAgICAgICB9KTtcclxuICAgICAgICBjb25zdCBjdXJyZW50U2NvcGVzID0gU2NvcGVTZXQuZnJvbVN0cmluZyhjcmVkZW50aWFsLnRhcmdldCk7XHJcbiAgICAgICAgY29uc3QgY3VycmVudEFjY2Vzc1Rva2VuczogQWNjZXNzVG9rZW5FbnRpdHlbXSA9IE9iamVjdC5rZXlzKGN1cnJlbnRUb2tlbkNhY2hlLmFjY2Vzc1Rva2VucykubWFwKGtleSA9PiBjdXJyZW50VG9rZW5DYWNoZS5hY2Nlc3NUb2tlbnNba2V5XSk7XHJcbiAgICAgICAgaWYgKGN1cnJlbnRBY2Nlc3NUb2tlbnMpIHtcclxuICAgICAgICAgICAgY3VycmVudEFjY2Vzc1Rva2Vucy5mb3JFYWNoKCh0b2tlbkVudGl0eSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgdG9rZW5TY29wZVNldCA9IFNjb3BlU2V0LmZyb21TdHJpbmcodG9rZW5FbnRpdHkudGFyZ2V0KTtcclxuICAgICAgICAgICAgICAgIGlmICh0b2tlblNjb3BlU2V0LmludGVyc2VjdGluZ1Njb3BlU2V0cyhjdXJyZW50U2NvcGVzKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlQ3JlZGVudGlhbCh0b2tlbkVudGl0eSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnNldEFjY2Vzc1Rva2VuQ3JlZGVudGlhbChjcmVkZW50aWFsKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIHJldHJpZXZlIGFjY291bnRzIG1hdGNoaW5nIGFsbCBwcm92aWRlZCBmaWx0ZXJzOyBpZiBubyBmaWx0ZXIgaXMgc2V0LCBnZXQgYWxsIGFjY291bnRzXHJcbiAgICAgKiBub3QgY2hlY2tpbmcgZm9yIGNhc2luZyBhcyBrZXlzIGFyZSBhbGwgZ2VuZXJhdGVkIGluIGxvd2VyIGNhc2UsIHJlbWVtYmVyIHRvIGNvbnZlcnQgdG8gbG93ZXIgY2FzZSBpZiBvYmplY3QgcHJvcGVydGllcyBhcmUgY29tcGFyZWRcclxuICAgICAqIEBwYXJhbSBob21lQWNjb3VudElkXHJcbiAgICAgKiBAcGFyYW0gZW52aXJvbm1lbnRcclxuICAgICAqIEBwYXJhbSByZWFsbVxyXG4gICAgICovXHJcbiAgICBnZXRBY2NvdW50c0ZpbHRlcmVkQnkoYWNjb3VudEZpbHRlcj86IEFjY291bnRGaWx0ZXIpOiBBY2NvdW50Q2FjaGUge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmdldEFjY291bnRzRmlsdGVyZWRCeUludGVybmFsKFxyXG4gICAgICAgICAgICBhY2NvdW50RmlsdGVyID8gYWNjb3VudEZpbHRlci5ob21lQWNjb3VudElkIDogXCJcIixcclxuICAgICAgICAgICAgYWNjb3VudEZpbHRlciA/IGFjY291bnRGaWx0ZXIuZW52aXJvbm1lbnQgOiBcIlwiLFxyXG4gICAgICAgICAgICBhY2NvdW50RmlsdGVyID8gYWNjb3VudEZpbHRlci5yZWFsbSA6IFwiXCJcclxuICAgICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogcmV0cmlldmUgYWNjb3VudHMgbWF0Y2hpbmcgYWxsIHByb3ZpZGVkIGZpbHRlcnM7IGlmIG5vIGZpbHRlciBpcyBzZXQsIGdldCBhbGwgYWNjb3VudHNcclxuICAgICAqIG5vdCBjaGVja2luZyBmb3IgY2FzaW5nIGFzIGtleXMgYXJlIGFsbCBnZW5lcmF0ZWQgaW4gbG93ZXIgY2FzZSwgcmVtZW1iZXIgdG8gY29udmVydCB0byBsb3dlciBjYXNlIGlmIG9iamVjdCBwcm9wZXJ0aWVzIGFyZSBjb21wYXJlZFxyXG4gICAgICogQHBhcmFtIGhvbWVBY2NvdW50SWRcclxuICAgICAqIEBwYXJhbSBlbnZpcm9ubWVudFxyXG4gICAgICogQHBhcmFtIHJlYWxtXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2V0QWNjb3VudHNGaWx0ZXJlZEJ5SW50ZXJuYWwoXHJcbiAgICAgICAgaG9tZUFjY291bnRJZD86IHN0cmluZyxcclxuICAgICAgICBlbnZpcm9ubWVudD86IHN0cmluZyxcclxuICAgICAgICByZWFsbT86IHN0cmluZ1xyXG4gICAgKTogQWNjb3VudENhY2hlIHtcclxuICAgICAgICBjb25zdCBhbGxDYWNoZUtleXMgPSB0aGlzLmdldEtleXMoKTtcclxuICAgICAgICBjb25zdCBtYXRjaGluZ0FjY291bnRzOiBBY2NvdW50Q2FjaGUgPSB7fTtcclxuXHJcbiAgICAgICAgYWxsQ2FjaGVLZXlzLmZvckVhY2goKGNhY2hlS2V5KSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IGVudGl0eTogQWNjb3VudEVudGl0eSB8IG51bGwgPSB0aGlzLmdldEFjY291bnQoY2FjaGVLZXkpO1xyXG5cclxuICAgICAgICAgICAgaWYgKCFlbnRpdHkpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKCEhaG9tZUFjY291bnRJZCAmJiAhdGhpcy5tYXRjaEhvbWVBY2NvdW50SWQoZW50aXR5LCBob21lQWNjb3VudElkKSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoISFlbnZpcm9ubWVudCAmJiAhdGhpcy5tYXRjaEVudmlyb25tZW50KGVudGl0eSwgZW52aXJvbm1lbnQpKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICghIXJlYWxtICYmICF0aGlzLm1hdGNoUmVhbG0oZW50aXR5LCByZWFsbSkpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgbWF0Y2hpbmdBY2NvdW50c1tjYWNoZUtleV0gPSBlbnRpdHk7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHJldHVybiBtYXRjaGluZ0FjY291bnRzO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogcmV0cmlldmUgY3JlZGVudGFpbHMgbWF0Y2hpbmcgYWxsIHByb3ZpZGVkIGZpbHRlcnM7IGlmIG5vIGZpbHRlciBpcyBzZXQsIGdldCBhbGwgY3JlZGVudGlhbHNcclxuICAgICAqIEBwYXJhbSBob21lQWNjb3VudElkXHJcbiAgICAgKiBAcGFyYW0gZW52aXJvbm1lbnRcclxuICAgICAqIEBwYXJhbSBjcmVkZW50aWFsVHlwZVxyXG4gICAgICogQHBhcmFtIGNsaWVudElkXHJcbiAgICAgKiBAcGFyYW0gcmVhbG1cclxuICAgICAqIEBwYXJhbSB0YXJnZXRcclxuICAgICAqL1xyXG4gICAgZ2V0Q3JlZGVudGlhbHNGaWx0ZXJlZEJ5KGZpbHRlcjogQ3JlZGVudGlhbEZpbHRlcik6IENyZWRlbnRpYWxDYWNoZSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q3JlZGVudGlhbHNGaWx0ZXJlZEJ5SW50ZXJuYWwoXHJcbiAgICAgICAgICAgIGZpbHRlci5ob21lQWNjb3VudElkLFxyXG4gICAgICAgICAgICBmaWx0ZXIuZW52aXJvbm1lbnQsXHJcbiAgICAgICAgICAgIGZpbHRlci5jcmVkZW50aWFsVHlwZSxcclxuICAgICAgICAgICAgZmlsdGVyLmNsaWVudElkLFxyXG4gICAgICAgICAgICBmaWx0ZXIuZmFtaWx5SWQsXHJcbiAgICAgICAgICAgIGZpbHRlci5yZWFsbSxcclxuICAgICAgICAgICAgZmlsdGVyLnRhcmdldCxcclxuICAgICAgICAgICAgZmlsdGVyLm9ib0Fzc2VydGlvblxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTdXBwb3J0IGZ1bmN0aW9uIHRvIGhlbHAgbWF0Y2ggY3JlZGVudGlhbHNcclxuICAgICAqIEBwYXJhbSBob21lQWNjb3VudElkXHJcbiAgICAgKiBAcGFyYW0gZW52aXJvbm1lbnRcclxuICAgICAqIEBwYXJhbSBjcmVkZW50aWFsVHlwZVxyXG4gICAgICogQHBhcmFtIGNsaWVudElkXHJcbiAgICAgKiBAcGFyYW0gcmVhbG1cclxuICAgICAqIEBwYXJhbSB0YXJnZXRcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBnZXRDcmVkZW50aWFsc0ZpbHRlcmVkQnlJbnRlcm5hbChcclxuICAgICAgICBob21lQWNjb3VudElkPzogc3RyaW5nLFxyXG4gICAgICAgIGVudmlyb25tZW50Pzogc3RyaW5nLFxyXG4gICAgICAgIGNyZWRlbnRpYWxUeXBlPzogc3RyaW5nLFxyXG4gICAgICAgIGNsaWVudElkPzogc3RyaW5nLFxyXG4gICAgICAgIGZhbWlseUlkPzogc3RyaW5nLFxyXG4gICAgICAgIHJlYWxtPzogc3RyaW5nLFxyXG4gICAgICAgIHRhcmdldD86IHN0cmluZyxcclxuICAgICAgICBvYm9Bc3NlcnRpb24/OiBzdHJpbmdcclxuICAgICk6IENyZWRlbnRpYWxDYWNoZSB7XHJcbiAgICAgICAgY29uc3QgYWxsQ2FjaGVLZXlzID0gdGhpcy5nZXRLZXlzKCk7XHJcbiAgICAgICAgY29uc3QgbWF0Y2hpbmdDcmVkZW50aWFsczogQ3JlZGVudGlhbENhY2hlID0ge1xyXG4gICAgICAgICAgICBpZFRva2Vuczoge30sXHJcbiAgICAgICAgICAgIGFjY2Vzc1Rva2Vuczoge30sXHJcbiAgICAgICAgICAgIHJlZnJlc2hUb2tlbnM6IHt9LFxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIGFsbENhY2hlS2V5cy5mb3JFYWNoKChjYWNoZUtleSkgPT4ge1xyXG4gICAgICAgICAgICAvLyBkb24ndCBwYXJzZSBhbnkgbm9uLWNyZWRlbnRpYWwgdHlwZSBjYWNoZSBlbnRpdGllc1xyXG4gICAgICAgICAgICBjb25zdCBjcmVkVHlwZSA9IENyZWRlbnRpYWxFbnRpdHkuZ2V0Q3JlZGVudGlhbFR5cGUoY2FjaGVLZXkpO1xyXG4gICAgICAgICAgICBpZiAoY3JlZFR5cGUgPT09IENvbnN0YW50cy5OT1RfREVGSU5FRCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBBdHRlbXB0IHJldHJpZXZhbFxyXG4gICAgICAgICAgICBjb25zdCBlbnRpdHkgPSB0aGlzLmdldFNwZWNpZmljQ3JlZGVudGlhbChjYWNoZUtleSwgY3JlZFR5cGUpO1xyXG4gICAgICAgICAgICBpZiAoIWVudGl0eSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoISFvYm9Bc3NlcnRpb24gJiYgIXRoaXMubWF0Y2hPYm9Bc3NlcnRpb24oZW50aXR5LCBvYm9Bc3NlcnRpb24pKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICghIWhvbWVBY2NvdW50SWQgJiYgIXRoaXMubWF0Y2hIb21lQWNjb3VudElkKGVudGl0eSwgaG9tZUFjY291bnRJZCkpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKCEhZW52aXJvbm1lbnQgJiYgIXRoaXMubWF0Y2hFbnZpcm9ubWVudChlbnRpdHksIGVudmlyb25tZW50KSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoISFyZWFsbSAmJiAhdGhpcy5tYXRjaFJlYWxtKGVudGl0eSwgcmVhbG0pKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICghIWNyZWRlbnRpYWxUeXBlICYmICF0aGlzLm1hdGNoQ3JlZGVudGlhbFR5cGUoZW50aXR5LCBjcmVkZW50aWFsVHlwZSkpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKCEhY2xpZW50SWQgJiYgIXRoaXMubWF0Y2hDbGllbnRJZChlbnRpdHksIGNsaWVudElkKSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoISFmYW1pbHlJZCAmJiAhdGhpcy5tYXRjaEZhbWlseUlkKGVudGl0eSwgZmFtaWx5SWQpKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8qXHJcbiAgICAgICAgICAgICAqIGlkVG9rZW5zIGRvIG5vdCBoYXZlIFwidGFyZ2V0XCIsIHRhcmdldCBzcGVjaWZpYyByZWZyZXNoVG9rZW5zIGRvIGV4aXN0IGZvciBzb21lIHR5cGVzIG9mIGF1dGhlbnRpY2F0aW9uXHJcbiAgICAgICAgICAgICAqIFJlc291cmNlIHNwZWNpZmljIHJlZnJlc2ggdG9rZW5zIGNhc2Ugd2lsbCBiZSBhZGRlZCB3aGVuIHRoZSBzdXBwb3J0IGlzIGRlZW1lZCBuZWNlc3NhcnlcclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmICghIXRhcmdldCAmJiAhdGhpcy5tYXRjaFRhcmdldChlbnRpdHksIHRhcmdldCkpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgc3dpdGNoIChjcmVkVHlwZSkge1xyXG4gICAgICAgICAgICAgICAgY2FzZSBDcmVkZW50aWFsVHlwZS5JRF9UT0tFTjpcclxuICAgICAgICAgICAgICAgICAgICBtYXRjaGluZ0NyZWRlbnRpYWxzLmlkVG9rZW5zW2NhY2hlS2V5XSA9IGVudGl0eSBhcyBJZFRva2VuRW50aXR5O1xyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSBDcmVkZW50aWFsVHlwZS5BQ0NFU1NfVE9LRU46XHJcbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hpbmdDcmVkZW50aWFscy5hY2Nlc3NUb2tlbnNbY2FjaGVLZXldID0gZW50aXR5IGFzIEFjY2Vzc1Rva2VuRW50aXR5O1xyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSBDcmVkZW50aWFsVHlwZS5SRUZSRVNIX1RPS0VOOlxyXG4gICAgICAgICAgICAgICAgICAgIG1hdGNoaW5nQ3JlZGVudGlhbHMucmVmcmVzaFRva2Vuc1tjYWNoZUtleV0gPSBlbnRpdHkgYXMgUmVmcmVzaFRva2VuRW50aXR5O1xyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHJldHVybiBtYXRjaGluZ0NyZWRlbnRpYWxzO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogcmV0cmlldmUgYXBwTWV0YWRhdGEgbWF0Y2hpbmcgYWxsIHByb3ZpZGVkIGZpbHRlcnM7IGlmIG5vIGZpbHRlciBpcyBzZXQsIGdldCBhbGwgYXBwTWV0YWRhdGFcclxuICAgICAqIEBwYXJhbSBmaWx0ZXJcclxuICAgICAqL1xyXG4gICAgZ2V0QXBwTWV0YWRhdGFGaWx0ZXJlZEJ5KGZpbHRlcjogQXBwTWV0YWRhdGFGaWx0ZXIpOiBBcHBNZXRhZGF0YUNhY2hlIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5nZXRBcHBNZXRhZGF0YUZpbHRlcmVkQnlJbnRlcm5hbChcclxuICAgICAgICAgICAgZmlsdGVyLmVudmlyb25tZW50LFxyXG4gICAgICAgICAgICBmaWx0ZXIuY2xpZW50SWQsXHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFN1cHBvcnQgZnVuY3Rpb24gdG8gaGVscCBtYXRjaCBhcHBNZXRhZGF0YVxyXG4gICAgICogQHBhcmFtIGVudmlyb25tZW50XHJcbiAgICAgKiBAcGFyYW0gY2xpZW50SWRcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBnZXRBcHBNZXRhZGF0YUZpbHRlcmVkQnlJbnRlcm5hbChcclxuICAgICAgICBlbnZpcm9ubWVudD86IHN0cmluZyxcclxuICAgICAgICBjbGllbnRJZD86IHN0cmluZ1xyXG4gICAgKTogQXBwTWV0YWRhdGFDYWNoZSB7XHJcblxyXG4gICAgICAgIGNvbnN0IGFsbENhY2hlS2V5cyA9IHRoaXMuZ2V0S2V5cygpO1xyXG4gICAgICAgIGNvbnN0IG1hdGNoaW5nQXBwTWV0YWRhdGE6IEFwcE1ldGFkYXRhQ2FjaGUgPSB7fTtcclxuXHJcbiAgICAgICAgYWxsQ2FjaGVLZXlzLmZvckVhY2goKGNhY2hlS2V5KSA9PiB7XHJcbiAgICAgICAgICAgIC8vIGRvbid0IHBhcnNlIGFueSBub24tYXBwTWV0YWRhdGEgdHlwZSBjYWNoZSBlbnRpdGllc1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNBcHBNZXRhZGF0YShjYWNoZUtleSkpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gQXR0ZW1wdCByZXRyaWV2YWxcclxuICAgICAgICAgICAgY29uc3QgZW50aXR5ID0gdGhpcy5nZXRBcHBNZXRhZGF0YShjYWNoZUtleSk7XHJcblxyXG4gICAgICAgICAgICBpZiAoIWVudGl0eSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoISFlbnZpcm9ubWVudCAmJiAhdGhpcy5tYXRjaEVudmlyb25tZW50KGVudGl0eSwgZW52aXJvbm1lbnQpKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICghIWNsaWVudElkICYmICF0aGlzLm1hdGNoQ2xpZW50SWQoZW50aXR5LCBjbGllbnRJZCkpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgbWF0Y2hpbmdBcHBNZXRhZGF0YVtjYWNoZUtleV0gPSBlbnRpdHk7XHJcblxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICByZXR1cm4gbWF0Y2hpbmdBcHBNZXRhZGF0YTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIHJldHJpZXZlIGF1dGhvcml0eU1ldGFkYXRhIHRoYXQgY29udGFpbnMgYSBtYXRjaGluZyBhbGlhc1xyXG4gICAgICogQHBhcmFtIGZpbHRlclxyXG4gICAgICovXHJcbiAgICBnZXRBdXRob3JpdHlNZXRhZGF0YUJ5QWxpYXMoaG9zdDogc3RyaW5nKTogQXV0aG9yaXR5TWV0YWRhdGFFbnRpdHkgfCBudWxsIHtcclxuICAgICAgICBjb25zdCBhbGxDYWNoZUtleXMgPSB0aGlzLmdldEF1dGhvcml0eU1ldGFkYXRhS2V5cygpO1xyXG4gICAgICAgIGxldCBtYXRjaGVkRW50aXR5ID0gbnVsbDtcclxuXHJcbiAgICAgICAgYWxsQ2FjaGVLZXlzLmZvckVhY2goKGNhY2hlS2V5KSA9PiB7XHJcbiAgICAgICAgICAgIC8vIGRvbid0IHBhcnNlIGFueSBub24tYXV0aG9yaXR5TWV0YWRhdGEgdHlwZSBjYWNoZSBlbnRpdGllc1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNBdXRob3JpdHlNZXRhZGF0YShjYWNoZUtleSkgfHwgY2FjaGVLZXkuaW5kZXhPZih0aGlzLmNsaWVudElkKSA9PT0gLTEpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gQXR0ZW1wdCByZXRyaWV2YWxcclxuICAgICAgICAgICAgY29uc3QgZW50aXR5ID0gdGhpcy5nZXRBdXRob3JpdHlNZXRhZGF0YShjYWNoZUtleSk7XHJcblxyXG4gICAgICAgICAgICBpZiAoIWVudGl0eSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoZW50aXR5LmFsaWFzZXMuaW5kZXhPZihob3N0KSA9PT0gLTEpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgbWF0Y2hlZEVudGl0eSA9IGVudGl0eTtcclxuXHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgXHJcbiAgICAgICAgcmV0dXJuIG1hdGNoZWRFbnRpdHk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZW1vdmVzIGFsbCBhY2NvdW50cyBhbmQgcmVsYXRlZCB0b2tlbnMgZnJvbSBjYWNoZS5cclxuICAgICAqL1xyXG4gICAgcmVtb3ZlQWxsQWNjb3VudHMoKTogYm9vbGVhbiB7XHJcbiAgICAgICAgY29uc3QgYWxsQ2FjaGVLZXlzID0gdGhpcy5nZXRLZXlzKCk7XHJcbiAgICAgICAgYWxsQ2FjaGVLZXlzLmZvckVhY2goKGNhY2hlS2V5KSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IGVudGl0eSA9IHRoaXMuZ2V0QWNjb3VudChjYWNoZUtleSk7XHJcbiAgICAgICAgICAgIGlmICghZW50aXR5KSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhpcy5yZW1vdmVBY2NvdW50KGNhY2hlS2V5KTtcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiByZXR1cm5zIGEgYm9vbGVhbiBpZiB0aGUgZ2l2ZW4gYWNjb3VudCBpcyByZW1vdmVkXHJcbiAgICAgKiBAcGFyYW0gYWNjb3VudFxyXG4gICAgICovXHJcbiAgICByZW1vdmVBY2NvdW50KGFjY291bnRLZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGNvbnN0IGFjY291bnQgPSB0aGlzLmdldEFjY291bnQoYWNjb3VudEtleSk7XHJcbiAgICAgICAgaWYgKCFhY2NvdW50KSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVOb0FjY291bnRGb3VuZEVycm9yKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiAodGhpcy5yZW1vdmVBY2NvdW50Q29udGV4dChhY2NvdW50KSAmJiB0aGlzLnJlbW92ZUl0ZW0oYWNjb3VudEtleSwgQ2FjaGVTY2hlbWFUeXBlLkFDQ09VTlQpKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIHJldHVybnMgYSBib29sZWFuIGlmIHRoZSBnaXZlbiBhY2NvdW50IGlzIHJlbW92ZWRcclxuICAgICAqIEBwYXJhbSBhY2NvdW50XHJcbiAgICAgKi9cclxuICAgIHJlbW92ZUFjY291bnRDb250ZXh0KGFjY291bnQ6IEFjY291bnRFbnRpdHkpOiBib29sZWFuIHtcclxuICAgICAgICBjb25zdCBhbGxDYWNoZUtleXMgPSB0aGlzLmdldEtleXMoKTtcclxuICAgICAgICBjb25zdCBhY2NvdW50SWQgPSBhY2NvdW50LmdlbmVyYXRlQWNjb3VudElkKCk7XHJcblxyXG4gICAgICAgIGFsbENhY2hlS2V5cy5mb3JFYWNoKChjYWNoZUtleSkgPT4ge1xyXG4gICAgICAgICAgICAvLyBkb24ndCBwYXJzZSBhbnkgbm9uLWNyZWRlbnRpYWwgdHlwZSBjYWNoZSBlbnRpdGllc1xyXG4gICAgICAgICAgICBjb25zdCBjcmVkVHlwZSA9IENyZWRlbnRpYWxFbnRpdHkuZ2V0Q3JlZGVudGlhbFR5cGUoY2FjaGVLZXkpO1xyXG4gICAgICAgICAgICBpZiAoY3JlZFR5cGUgPT09IENvbnN0YW50cy5OT1RfREVGSU5FRCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBjYWNoZUVudGl0eSA9IHRoaXMuZ2V0U3BlY2lmaWNDcmVkZW50aWFsKGNhY2hlS2V5LCBjcmVkVHlwZSk7XHJcbiAgICAgICAgICAgIGlmICghIWNhY2hlRW50aXR5ICYmIGFjY291bnRJZCA9PT0gY2FjaGVFbnRpdHkuZ2VuZXJhdGVBY2NvdW50SWQoKSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVDcmVkZW50aWFsKGNhY2hlRW50aXR5KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIHJldHVybnMgYSBib29sZWFuIGlmIHRoZSBnaXZlbiBjcmVkZW50aWFsIGlzIHJlbW92ZWRcclxuICAgICAqIEBwYXJhbSBjcmVkZW50aWFsXHJcbiAgICAgKi9cclxuICAgIHJlbW92ZUNyZWRlbnRpYWwoY3JlZGVudGlhbDogQ3JlZGVudGlhbEVudGl0eSk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGNvbnN0IGtleSA9IGNyZWRlbnRpYWwuZ2VuZXJhdGVDcmVkZW50aWFsS2V5KCk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMucmVtb3ZlSXRlbShrZXksIENhY2hlU2NoZW1hVHlwZS5DUkVERU5USUFMKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJlbW92ZXMgYWxsIGFwcCBtZXRhZGF0YSBvYmplY3RzIGZyb20gY2FjaGUuXHJcbiAgICAgKi9cclxuICAgIHJlbW92ZUFwcE1ldGFkYXRhKCk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGNvbnN0IGFsbENhY2hlS2V5cyA9IHRoaXMuZ2V0S2V5cygpO1xyXG4gICAgICAgIGFsbENhY2hlS2V5cy5mb3JFYWNoKChjYWNoZUtleSkgPT4ge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5pc0FwcE1ldGFkYXRhKGNhY2hlS2V5KSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVJdGVtKGNhY2hlS2V5LCBDYWNoZVNjaGVtYVR5cGUuQVBQX01FVEFEQVRBKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHJpZXZlIHRoZSBjYWNoZWQgY3JlZGVudGlhbHMgaW50byBhIGNhY2hlcmVjb3JkXHJcbiAgICAgKiBAcGFyYW0gYWNjb3VudFxyXG4gICAgICogQHBhcmFtIGNsaWVudElkXHJcbiAgICAgKiBAcGFyYW0gc2NvcGVzXHJcbiAgICAgKiBAcGFyYW0gZW52aXJvbm1lbnRcclxuICAgICAqL1xyXG4gICAgcmVhZENhY2hlUmVjb3JkKGFjY291bnQ6IEFjY291bnRJbmZvLCBjbGllbnRJZDogc3RyaW5nLCBzY29wZXM6IFNjb3BlU2V0LCBlbnZpcm9ubWVudDogc3RyaW5nKTogQ2FjaGVSZWNvcmQge1xyXG4gICAgICAgIGNvbnN0IGNhY2hlZEFjY291bnQgPSB0aGlzLnJlYWRBY2NvdW50RnJvbUNhY2hlKGFjY291bnQpO1xyXG4gICAgICAgIGNvbnN0IGNhY2hlZElkVG9rZW4gPSB0aGlzLnJlYWRJZFRva2VuRnJvbUNhY2hlKGNsaWVudElkLCBhY2NvdW50KTtcclxuICAgICAgICBjb25zdCBjYWNoZWRBY2Nlc3NUb2tlbiA9IHRoaXMucmVhZEFjY2Vzc1Rva2VuRnJvbUNhY2hlKGNsaWVudElkLCBhY2NvdW50LCBzY29wZXMpO1xyXG4gICAgICAgIGNvbnN0IGNhY2hlZFJlZnJlc2hUb2tlbiA9IHRoaXMucmVhZFJlZnJlc2hUb2tlbkZyb21DYWNoZShjbGllbnRJZCwgYWNjb3VudCwgZmFsc2UpO1xyXG4gICAgICAgIGNvbnN0IGNhY2hlZEFwcE1ldGFkYXRhID0gdGhpcy5yZWFkQXBwTWV0YWRhdGFGcm9tQ2FjaGUoZW52aXJvbm1lbnQsIGNsaWVudElkKTtcclxuXHJcbiAgICAgICAgaWYgKGNhY2hlZEFjY291bnQgJiYgY2FjaGVkSWRUb2tlbikge1xyXG4gICAgICAgICAgICBjYWNoZWRBY2NvdW50LmlkVG9rZW5DbGFpbXMgPSBuZXcgQXV0aFRva2VuKGNhY2hlZElkVG9rZW4uc2VjcmV0LCB0aGlzLmNyeXB0b0ltcGwpLmNsYWltcztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIGFjY291bnQ6IGNhY2hlZEFjY291bnQsXHJcbiAgICAgICAgICAgIGlkVG9rZW46IGNhY2hlZElkVG9rZW4sXHJcbiAgICAgICAgICAgIGFjY2Vzc1Rva2VuOiBjYWNoZWRBY2Nlc3NUb2tlbixcclxuICAgICAgICAgICAgcmVmcmVzaFRva2VuOiBjYWNoZWRSZWZyZXNoVG9rZW4sXHJcbiAgICAgICAgICAgIGFwcE1ldGFkYXRhOiBjYWNoZWRBcHBNZXRhZGF0YSxcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0cmlldmUgQWNjb3VudEVudGl0eSBmcm9tIGNhY2hlXHJcbiAgICAgKiBAcGFyYW0gYWNjb3VudFxyXG4gICAgICovXHJcbiAgICByZWFkQWNjb3VudEZyb21DYWNoZShhY2NvdW50OiBBY2NvdW50SW5mbyk6IEFjY291bnRFbnRpdHkgfCBudWxsIHtcclxuICAgICAgICBjb25zdCBhY2NvdW50S2V5OiBzdHJpbmcgPSBBY2NvdW50RW50aXR5LmdlbmVyYXRlQWNjb3VudENhY2hlS2V5KGFjY291bnQpO1xyXG4gICAgICAgIHJldHVybiB0aGlzLmdldEFjY291bnQoYWNjb3VudEtleSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXRyaWV2ZSBJZFRva2VuRW50aXR5IGZyb20gY2FjaGVcclxuICAgICAqIEBwYXJhbSBjbGllbnRJZFxyXG4gICAgICogQHBhcmFtIGFjY291bnRcclxuICAgICAqIEBwYXJhbSBpbnB1dFJlYWxtXHJcbiAgICAgKi9cclxuICAgIHJlYWRJZFRva2VuRnJvbUNhY2hlKGNsaWVudElkOiBzdHJpbmcsIGFjY291bnQ6IEFjY291bnRJbmZvKTogSWRUb2tlbkVudGl0eSB8IG51bGwge1xyXG4gICAgICAgIGNvbnN0IGlkVG9rZW5GaWx0ZXI6IENyZWRlbnRpYWxGaWx0ZXIgPSB7XHJcbiAgICAgICAgICAgIGhvbWVBY2NvdW50SWQ6IGFjY291bnQuaG9tZUFjY291bnRJZCxcclxuICAgICAgICAgICAgZW52aXJvbm1lbnQ6IGFjY291bnQuZW52aXJvbm1lbnQsXHJcbiAgICAgICAgICAgIGNyZWRlbnRpYWxUeXBlOiBDcmVkZW50aWFsVHlwZS5JRF9UT0tFTixcclxuICAgICAgICAgICAgY2xpZW50SWQ6IGNsaWVudElkLFxyXG4gICAgICAgICAgICByZWFsbTogYWNjb3VudC50ZW5hbnRJZCxcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBjb25zdCBjcmVkZW50aWFsQ2FjaGU6IENyZWRlbnRpYWxDYWNoZSA9IHRoaXMuZ2V0Q3JlZGVudGlhbHNGaWx0ZXJlZEJ5KGlkVG9rZW5GaWx0ZXIpO1xyXG4gICAgICAgIGNvbnN0IGlkVG9rZW5zID0gT2JqZWN0LmtleXMoY3JlZGVudGlhbENhY2hlLmlkVG9rZW5zKS5tYXAoKGtleSkgPT4gY3JlZGVudGlhbENhY2hlLmlkVG9rZW5zW2tleV0pO1xyXG4gICAgICAgIGNvbnN0IG51bUlkVG9rZW5zID0gaWRUb2tlbnMubGVuZ3RoO1xyXG5cclxuICAgICAgICBpZiAobnVtSWRUb2tlbnMgPCAxKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH0gZWxzZSBpZiAobnVtSWRUb2tlbnMgPiAxKSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVNdWx0aXBsZU1hdGNoaW5nVG9rZW5zSW5DYWNoZUVycm9yKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gaWRUb2tlbnNbMF0gYXMgSWRUb2tlbkVudGl0eTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHJpZXZlIEFjY2Vzc1Rva2VuRW50aXR5IGZyb20gY2FjaGVcclxuICAgICAqIEBwYXJhbSBjbGllbnRJZFxyXG4gICAgICogQHBhcmFtIGFjY291bnRcclxuICAgICAqIEBwYXJhbSBzY29wZXNcclxuICAgICAqIEBwYXJhbSBpbnB1dFJlYWxtXHJcbiAgICAgKi9cclxuICAgIHJlYWRBY2Nlc3NUb2tlbkZyb21DYWNoZShjbGllbnRJZDogc3RyaW5nLCBhY2NvdW50OiBBY2NvdW50SW5mbywgc2NvcGVzOiBTY29wZVNldCk6IEFjY2Vzc1Rva2VuRW50aXR5IHwgbnVsbCB7XHJcbiAgICAgICAgY29uc3QgYWNjZXNzVG9rZW5GaWx0ZXI6IENyZWRlbnRpYWxGaWx0ZXIgPSB7XHJcbiAgICAgICAgICAgIGhvbWVBY2NvdW50SWQ6IGFjY291bnQuaG9tZUFjY291bnRJZCxcclxuICAgICAgICAgICAgZW52aXJvbm1lbnQ6IGFjY291bnQuZW52aXJvbm1lbnQsXHJcbiAgICAgICAgICAgIGNyZWRlbnRpYWxUeXBlOiBDcmVkZW50aWFsVHlwZS5BQ0NFU1NfVE9LRU4sXHJcbiAgICAgICAgICAgIGNsaWVudElkLFxyXG4gICAgICAgICAgICByZWFsbTogYWNjb3VudC50ZW5hbnRJZCxcclxuICAgICAgICAgICAgdGFyZ2V0OiBzY29wZXMucHJpbnRTY29wZXNMb3dlckNhc2UoKSxcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBjb25zdCBjcmVkZW50aWFsQ2FjaGU6IENyZWRlbnRpYWxDYWNoZSA9IHRoaXMuZ2V0Q3JlZGVudGlhbHNGaWx0ZXJlZEJ5KGFjY2Vzc1Rva2VuRmlsdGVyKTtcclxuICAgICAgICBjb25zdCBhY2Nlc3NUb2tlbnMgPSBPYmplY3Qua2V5cyhjcmVkZW50aWFsQ2FjaGUuYWNjZXNzVG9rZW5zKS5tYXAoKGtleSkgPT4gY3JlZGVudGlhbENhY2hlLmFjY2Vzc1Rva2Vuc1trZXldKTtcclxuXHJcbiAgICAgICAgY29uc3QgbnVtQWNjZXNzVG9rZW5zID0gYWNjZXNzVG9rZW5zLmxlbmd0aDtcclxuICAgICAgICBpZiAobnVtQWNjZXNzVG9rZW5zIDwgMSkge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9IGVsc2UgaWYgKG51bUFjY2Vzc1Rva2VucyA+IDEpIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50QXV0aEVycm9yLmNyZWF0ZU11bHRpcGxlTWF0Y2hpbmdUb2tlbnNJbkNhY2hlRXJyb3IoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBhY2Nlc3NUb2tlbnNbMF0gYXMgQWNjZXNzVG9rZW5FbnRpdHk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBIZWxwZXIgdG8gcmV0cmlldmUgdGhlIGFwcHJvcHJpYXRlIHJlZnJlc2ggdG9rZW4gZnJvbSBjYWNoZVxyXG4gICAgICogQHBhcmFtIGNsaWVudElkXHJcbiAgICAgKiBAcGFyYW0gYWNjb3VudFxyXG4gICAgICogQHBhcmFtIGZhbWlseVJUXHJcbiAgICAgKi9cclxuICAgIHJlYWRSZWZyZXNoVG9rZW5Gcm9tQ2FjaGUoY2xpZW50SWQ6IHN0cmluZywgYWNjb3VudDogQWNjb3VudEluZm8sIGZhbWlseVJUOiBib29sZWFuKTogUmVmcmVzaFRva2VuRW50aXR5IHwgbnVsbCB7XHJcbiAgICAgICAgY29uc3QgaWQgPSBmYW1pbHlSVCA/IFRIRV9GQU1JTFlfSUQgOiB1bmRlZmluZWQ7XHJcbiAgICAgICAgY29uc3QgcmVmcmVzaFRva2VuRmlsdGVyOiBDcmVkZW50aWFsRmlsdGVyID0ge1xyXG4gICAgICAgICAgICBob21lQWNjb3VudElkOiBhY2NvdW50LmhvbWVBY2NvdW50SWQsXHJcbiAgICAgICAgICAgIGVudmlyb25tZW50OiBhY2NvdW50LmVudmlyb25tZW50LFxyXG4gICAgICAgICAgICBjcmVkZW50aWFsVHlwZTogQ3JlZGVudGlhbFR5cGUuUkVGUkVTSF9UT0tFTixcclxuICAgICAgICAgICAgY2xpZW50SWQ6IGNsaWVudElkLFxyXG4gICAgICAgICAgICBmYW1pbHlJZDogaWRcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBjb25zdCBjcmVkZW50aWFsQ2FjaGU6IENyZWRlbnRpYWxDYWNoZSA9IHRoaXMuZ2V0Q3JlZGVudGlhbHNGaWx0ZXJlZEJ5KHJlZnJlc2hUb2tlbkZpbHRlcik7XHJcbiAgICAgICAgY29uc3QgcmVmcmVzaFRva2VucyA9IE9iamVjdC5rZXlzKGNyZWRlbnRpYWxDYWNoZS5yZWZyZXNoVG9rZW5zKS5tYXAoKGtleSkgPT4gY3JlZGVudGlhbENhY2hlLnJlZnJlc2hUb2tlbnNba2V5XSk7XHJcblxyXG4gICAgICAgIGNvbnN0IG51bVJlZnJlc2hUb2tlbnMgPSByZWZyZXNoVG9rZW5zLmxlbmd0aDtcclxuICAgICAgICBpZiAobnVtUmVmcmVzaFRva2VucyA8IDEpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIGFkZHJlc3MgdGhlIGVsc2UgY2FzZSBhZnRlciByZW1vdmUgZnVuY3Rpb25zIGFkZHJlc3MgZW52aXJvbm1lbnQgYWxpYXNlc1xyXG5cclxuICAgICAgICByZXR1cm4gcmVmcmVzaFRva2Vuc1swXSBhcyBSZWZyZXNoVG9rZW5FbnRpdHk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXRyaWV2ZSBBcHBNZXRhZGF0YUVudGl0eSBmcm9tIGNhY2hlXHJcbiAgICAgKi9cclxuICAgIHJlYWRBcHBNZXRhZGF0YUZyb21DYWNoZShlbnZpcm9ubWVudDogc3RyaW5nLCBjbGllbnRJZDogc3RyaW5nKTogQXBwTWV0YWRhdGFFbnRpdHkgfCBudWxsIHtcclxuICAgICAgICBjb25zdCBhcHBNZXRhZGF0YUZpbHRlcjogQXBwTWV0YWRhdGFGaWx0ZXIgPSB7XHJcbiAgICAgICAgICAgIGVudmlyb25tZW50LFxyXG4gICAgICAgICAgICBjbGllbnRJZCxcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBjb25zdCBhcHBNZXRhZGF0YTogQXBwTWV0YWRhdGFDYWNoZSA9IHRoaXMuZ2V0QXBwTWV0YWRhdGFGaWx0ZXJlZEJ5KGFwcE1ldGFkYXRhRmlsdGVyKTtcclxuICAgICAgICBjb25zdCBhcHBNZXRhZGF0YUVudHJpZXM6IEFwcE1ldGFkYXRhRW50aXR5W10gPSBPYmplY3Qua2V5cyhhcHBNZXRhZGF0YSkubWFwKChrZXkpID0+IGFwcE1ldGFkYXRhW2tleV0pO1xyXG5cclxuICAgICAgICBjb25zdCBudW1BcHBNZXRhZGF0YSA9IGFwcE1ldGFkYXRhRW50cmllcy5sZW5ndGg7XHJcbiAgICAgICAgaWYgKG51bUFwcE1ldGFkYXRhIDwgMSkge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9IGVsc2UgaWYgKG51bUFwcE1ldGFkYXRhID4gMSkge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRBdXRoRXJyb3IuY3JlYXRlTXVsdGlwbGVNYXRjaGluZ0FwcE1ldGFkYXRhSW5DYWNoZUVycm9yKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gYXBwTWV0YWRhdGFFbnRyaWVzWzBdIGFzIEFwcE1ldGFkYXRhRW50aXR5O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJuIHRoZSBmYW1pbHlfaWQgdmFsdWUgYXNzb2NpYXRlZCAgd2l0aCBGT0NJXHJcbiAgICAgKiBAcGFyYW0gZW52aXJvbm1lbnRcclxuICAgICAqIEBwYXJhbSBjbGllbnRJZFxyXG4gICAgICovXHJcbiAgICBpc0FwcE1ldGFkYXRhRk9DSShlbnZpcm9ubWVudDogc3RyaW5nLCBjbGllbnRJZDogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICAgICAgY29uc3QgYXBwTWV0YWRhdGEgPSB0aGlzLnJlYWRBcHBNZXRhZGF0YUZyb21DYWNoZShlbnZpcm9ubWVudCwgY2xpZW50SWQpO1xyXG4gICAgICAgIHJldHVybiAhIShhcHBNZXRhZGF0YSAmJiBhcHBNZXRhZGF0YS5mYW1pbHlJZCA9PT0gVEhFX0ZBTUlMWV9JRCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBoZWxwZXIgdG8gbWF0Y2ggYWNjb3VudCBpZHNcclxuICAgICAqIEBwYXJhbSB2YWx1ZVxyXG4gICAgICogQHBhcmFtIGhvbWVBY2NvdW50SWRcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBtYXRjaEhvbWVBY2NvdW50SWQoZW50aXR5OiBBY2NvdW50RW50aXR5IHwgQ3JlZGVudGlhbEVudGl0eSwgaG9tZUFjY291bnRJZDogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuICEhKGVudGl0eS5ob21lQWNjb3VudElkICYmIGhvbWVBY2NvdW50SWQgPT09IGVudGl0eS5ob21lQWNjb3VudElkKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGhlbHBlciB0byBtYXRjaCBhc3NlcnRpb25cclxuICAgICAqIEBwYXJhbSB2YWx1ZVxyXG4gICAgICogQHBhcmFtIG9ib0Fzc2VydGlvblxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIG1hdGNoT2JvQXNzZXJ0aW9uKGVudGl0eTogQWNjb3VudEVudGl0eSB8IENyZWRlbnRpYWxFbnRpdHksIG9ib0Fzc2VydGlvbjogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuICEhKGVudGl0eS5vYm9Bc3NlcnRpb24gJiYgb2JvQXNzZXJ0aW9uID09PSBlbnRpdHkub2JvQXNzZXJ0aW9uKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGhlbHBlciB0byBtYXRjaCBlbnZpcm9ubWVudFxyXG4gICAgICogQHBhcmFtIHZhbHVlXHJcbiAgICAgKiBAcGFyYW0gZW52aXJvbm1lbnRcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBtYXRjaEVudmlyb25tZW50KGVudGl0eTogQWNjb3VudEVudGl0eSB8IENyZWRlbnRpYWxFbnRpdHkgfCBBcHBNZXRhZGF0YUVudGl0eSwgZW52aXJvbm1lbnQ6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGNvbnN0IGNsb3VkTWV0YWRhdGEgPSB0aGlzLmdldEF1dGhvcml0eU1ldGFkYXRhQnlBbGlhcyhlbnZpcm9ubWVudCk7XHJcbiAgICAgICAgaWYgKGNsb3VkTWV0YWRhdGEgJiYgY2xvdWRNZXRhZGF0YS5hbGlhc2VzLmluZGV4T2YoZW50aXR5LmVudmlyb25tZW50KSA+IC0xKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogaGVscGVyIHRvIG1hdGNoIGNyZWRlbnRpYWwgdHlwZVxyXG4gICAgICogQHBhcmFtIGVudGl0eVxyXG4gICAgICogQHBhcmFtIGNyZWRlbnRpYWxUeXBlXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgbWF0Y2hDcmVkZW50aWFsVHlwZShlbnRpdHk6IENyZWRlbnRpYWxFbnRpdHksIGNyZWRlbnRpYWxUeXBlOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgICAgICByZXR1cm4gKGVudGl0eS5jcmVkZW50aWFsVHlwZSAmJiBjcmVkZW50aWFsVHlwZS50b0xvd2VyQ2FzZSgpID09PSBlbnRpdHkuY3JlZGVudGlhbFR5cGUudG9Mb3dlckNhc2UoKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBoZWxwZXIgdG8gbWF0Y2ggY2xpZW50IGlkc1xyXG4gICAgICogQHBhcmFtIGVudGl0eVxyXG4gICAgICogQHBhcmFtIGNsaWVudElkXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgbWF0Y2hDbGllbnRJZChlbnRpdHk6IENyZWRlbnRpYWxFbnRpdHkgfCBBcHBNZXRhZGF0YUVudGl0eSwgY2xpZW50SWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiAhIShlbnRpdHkuY2xpZW50SWQgJiYgY2xpZW50SWQgPT09IGVudGl0eS5jbGllbnRJZCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBoZWxwZXIgdG8gbWF0Y2ggZmFtaWx5IGlkc1xyXG4gICAgICogQHBhcmFtIGVudGl0eVxyXG4gICAgICogQHBhcmFtIGZhbWlseUlkXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgbWF0Y2hGYW1pbHlJZChlbnRpdHk6IENyZWRlbnRpYWxFbnRpdHkgfCBBcHBNZXRhZGF0YUVudGl0eSwgZmFtaWx5SWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiAhIShlbnRpdHkuZmFtaWx5SWQgJiYgZmFtaWx5SWQgPT09IGVudGl0eS5mYW1pbHlJZCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBoZWxwZXIgdG8gbWF0Y2ggcmVhbG1cclxuICAgICAqIEBwYXJhbSBlbnRpdHlcclxuICAgICAqIEBwYXJhbSByZWFsbVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIG1hdGNoUmVhbG0oZW50aXR5OiBBY2NvdW50RW50aXR5IHwgQ3JlZGVudGlhbEVudGl0eSwgcmVhbG06IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiAhIShlbnRpdHkucmVhbG0gJiYgcmVhbG0gPT09IGVudGl0eS5yZWFsbSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHRhcmdldCBzY29wZXMgYXJlIGEgc3Vic2V0IG9mIHRoZSBjdXJyZW50IGVudGl0eSdzIHNjb3BlcywgZmFsc2Ugb3RoZXJ3aXNlLlxyXG4gICAgICogQHBhcmFtIGVudGl0eVxyXG4gICAgICogQHBhcmFtIHRhcmdldFxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIG1hdGNoVGFyZ2V0KGVudGl0eTogQ3JlZGVudGlhbEVudGl0eSwgdGFyZ2V0OiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgICAgICBpZiAoZW50aXR5LmNyZWRlbnRpYWxUeXBlICE9PSBDcmVkZW50aWFsVHlwZS5BQ0NFU1NfVE9LRU4gfHwgIWVudGl0eS50YXJnZXQpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgZW50aXR5U2NvcGVTZXQ6IFNjb3BlU2V0ID0gU2NvcGVTZXQuZnJvbVN0cmluZyhlbnRpdHkudGFyZ2V0KTtcclxuICAgICAgICBjb25zdCByZXF1ZXN0VGFyZ2V0U2NvcGVTZXQ6IFNjb3BlU2V0ID0gU2NvcGVTZXQuZnJvbVN0cmluZyh0YXJnZXQpO1xyXG5cclxuICAgICAgICBpZiAoIXJlcXVlc3RUYXJnZXRTY29wZVNldC5jb250YWluc09ubHlPSURDU2NvcGVzKCkpIHtcclxuICAgICAgICAgICAgcmVxdWVzdFRhcmdldFNjb3BlU2V0LnJlbW92ZU9JRENTY29wZXMoKTsgLy8gaWdub3JlIE9JREMgc2NvcGVzXHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBlbnRpdHlTY29wZVNldC5jb250YWluc1Njb3BlU2V0KHJlcXVlc3RUYXJnZXRTY29wZVNldCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiByZXR1cm5zIGlmIGEgZ2l2ZW4gY2FjaGUgZW50aXR5IGlzIG9mIHRoZSB0eXBlIGFwcG1ldGFkYXRhXHJcbiAgICAgKiBAcGFyYW0ga2V5XHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgaXNBcHBNZXRhZGF0YShrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiBrZXkuaW5kZXhPZihBUFBfTUVUQURBVEEpICE9PSAtMTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIHJldHVybnMgaWYgYSBnaXZlbiBjYWNoZSBlbnRpdHkgaXMgb2YgdGhlIHR5cGUgYXV0aG9yaXR5bWV0YWRhdGFcclxuICAgICAqIEBwYXJhbSBrZXlcclxuICAgICAqL1xyXG4gICAgcHJvdGVjdGVkIGlzQXV0aG9yaXR5TWV0YWRhdGEoa2V5OiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgICAgICByZXR1cm4ga2V5LmluZGV4T2YoQVVUSE9SSVRZX01FVEFEQVRBX0NPTlNUQU5UUy5DQUNIRV9LRVkpICE9PSAtMTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIHJldHVybnMgY2FjaGUga2V5IHVzZWQgZm9yIGNsb3VkIGluc3RhbmNlIG1ldGFkYXRhXHJcbiAgICAgKi9cclxuICAgIGdlbmVyYXRlQXV0aG9yaXR5TWV0YWRhdGFDYWNoZUtleShhdXRob3JpdHk6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIGAke0FVVEhPUklUWV9NRVRBREFUQV9DT05TVEFOVFMuQ0FDSEVfS0VZfS0ke3RoaXMuY2xpZW50SWR9LSR7YXV0aG9yaXR5fWA7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIHRoZSBzcGVjaWZpYyBjcmVkZW50aWFsIChJZFRva2VuL0FjY2Vzc1Rva2VuL1JlZnJlc2hUb2tlbikgZnJvbSB0aGUgY2FjaGVcclxuICAgICAqIEBwYXJhbSBrZXlcclxuICAgICAqIEBwYXJhbSBjcmVkVHlwZVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGdldFNwZWNpZmljQ3JlZGVudGlhbChrZXk6IHN0cmluZywgY3JlZFR5cGU6IHN0cmluZyk6IFZhbGlkQ3JlZGVudGlhbFR5cGUgfCBudWxsIHtcclxuICAgICAgICBzd2l0Y2ggKGNyZWRUeXBlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgQ3JlZGVudGlhbFR5cGUuSURfVE9LRU46IHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldElkVG9rZW5DcmVkZW50aWFsKGtleSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY2FzZSBDcmVkZW50aWFsVHlwZS5BQ0NFU1NfVE9LRU46IHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldEFjY2Vzc1Rva2VuQ3JlZGVudGlhbChrZXkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNhc2UgQ3JlZGVudGlhbFR5cGUuUkVGUkVTSF9UT0tFTjoge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVmcmVzaFRva2VuQ3JlZGVudGlhbChrZXkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBIZWxwZXIgdG8gY29udmVydCBzZXJpYWxpemVkIGRhdGEgdG8gb2JqZWN0XHJcbiAgICAgKiBAcGFyYW0gb2JqXHJcbiAgICAgKiBAcGFyYW0ganNvblxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgdG9PYmplY3Q8VD4ob2JqOiBULCBqc29uOiBvYmplY3QpOiBUIHtcclxuICAgICAgICBmb3IgKGNvbnN0IHByb3BlcnR5TmFtZSBpbiBqc29uKSB7XHJcbiAgICAgICAgICAgIG9ialtwcm9wZXJ0eU5hbWVdID0ganNvbltwcm9wZXJ0eU5hbWVdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gb2JqO1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgRGVmYXVsdFN0b3JhZ2VDbGFzcyBleHRlbmRzIENhY2hlTWFuYWdlciB7XHJcbiAgICBzZXRBY2NvdW50KCk6IHZvaWQge1xyXG4gICAgICAgIGNvbnN0IG5vdEltcGxFcnIgPSBcIlN0b3JhZ2UgaW50ZXJmYWNlIC0gc2V0QWNjb3VudCgpIGhhcyBub3QgYmVlbiBpbXBsZW1lbnRlZCBmb3IgdGhlIGNhY2hlU3RvcmFnZSBpbnRlcmZhY2UuXCI7XHJcbiAgICAgICAgdGhyb3cgQXV0aEVycm9yLmNyZWF0ZVVuZXhwZWN0ZWRFcnJvcihub3RJbXBsRXJyKTtcclxuICAgIH1cclxuICAgIGdldEFjY291bnQoKTogQWNjb3VudEVudGl0eSB7XHJcbiAgICAgICAgY29uc3Qgbm90SW1wbEVyciA9IFwiU3RvcmFnZSBpbnRlcmZhY2UgLSBnZXRBY2NvdW50KCkgaGFzIG5vdCBiZWVuIGltcGxlbWVudGVkIGZvciB0aGUgY2FjaGVTdG9yYWdlIGludGVyZmFjZS5cIjtcclxuICAgICAgICB0aHJvdyBBdXRoRXJyb3IuY3JlYXRlVW5leHBlY3RlZEVycm9yKG5vdEltcGxFcnIpO1xyXG4gICAgfVxyXG4gICAgc2V0SWRUb2tlbkNyZWRlbnRpYWwoKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3Qgbm90SW1wbEVyciA9IFwiU3RvcmFnZSBpbnRlcmZhY2UgLSBzZXRJZFRva2VuQ3JlZGVudGlhbCgpIGhhcyBub3QgYmVlbiBpbXBsZW1lbnRlZCBmb3IgdGhlIGNhY2hlU3RvcmFnZSBpbnRlcmZhY2UuXCI7XHJcbiAgICAgICAgdGhyb3cgQXV0aEVycm9yLmNyZWF0ZVVuZXhwZWN0ZWRFcnJvcihub3RJbXBsRXJyKTtcclxuICAgIH1cclxuICAgIGdldElkVG9rZW5DcmVkZW50aWFsKCk6IElkVG9rZW5FbnRpdHkge1xyXG4gICAgICAgIGNvbnN0IG5vdEltcGxFcnIgPSBcIlN0b3JhZ2UgaW50ZXJmYWNlIC0gZ2V0SWRUb2tlbkNyZWRlbnRpYWwoKSBoYXMgbm90IGJlZW4gaW1wbGVtZW50ZWQgZm9yIHRoZSBjYWNoZVN0b3JhZ2UgaW50ZXJmYWNlLlwiO1xyXG4gICAgICAgIHRocm93IEF1dGhFcnJvci5jcmVhdGVVbmV4cGVjdGVkRXJyb3Iobm90SW1wbEVycik7XHJcbiAgICB9XHJcbiAgICBzZXRBY2Nlc3NUb2tlbkNyZWRlbnRpYWwoKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3Qgbm90SW1wbEVyciA9IFwiU3RvcmFnZSBpbnRlcmZhY2UgLSBzZXRBY2Nlc3NUb2tlbkNyZWRlbnRpYWwoKSBoYXMgbm90IGJlZW4gaW1wbGVtZW50ZWQgZm9yIHRoZSBjYWNoZVN0b3JhZ2UgaW50ZXJmYWNlLlwiO1xyXG4gICAgICAgIHRocm93IEF1dGhFcnJvci5jcmVhdGVVbmV4cGVjdGVkRXJyb3Iobm90SW1wbEVycik7XHJcbiAgICB9XHJcbiAgICBnZXRBY2Nlc3NUb2tlbkNyZWRlbnRpYWwoKTogQWNjZXNzVG9rZW5FbnRpdHkge1xyXG4gICAgICAgIGNvbnN0IG5vdEltcGxFcnIgPSBcIlN0b3JhZ2UgaW50ZXJmYWNlIC0gZ2V0QWNjZXNzVG9rZW5DcmVkZW50aWFsKCkgaGFzIG5vdCBiZWVuIGltcGxlbWVudGVkIGZvciB0aGUgY2FjaGVTdG9yYWdlIGludGVyZmFjZS5cIjtcclxuICAgICAgICB0aHJvdyBBdXRoRXJyb3IuY3JlYXRlVW5leHBlY3RlZEVycm9yKG5vdEltcGxFcnIpO1xyXG4gICAgfVxyXG4gICAgc2V0UmVmcmVzaFRva2VuQ3JlZGVudGlhbCgpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBub3RJbXBsRXJyID0gXCJTdG9yYWdlIGludGVyZmFjZSAtIHNldFJlZnJlc2hUb2tlbkNyZWRlbnRpYWwoKSBoYXMgbm90IGJlZW4gaW1wbGVtZW50ZWQgZm9yIHRoZSBjYWNoZVN0b3JhZ2UgaW50ZXJmYWNlLlwiO1xyXG4gICAgICAgIHRocm93IEF1dGhFcnJvci5jcmVhdGVVbmV4cGVjdGVkRXJyb3Iobm90SW1wbEVycik7XHJcbiAgICB9XHJcbiAgICBnZXRSZWZyZXNoVG9rZW5DcmVkZW50aWFsKCk6IFJlZnJlc2hUb2tlbkVudGl0eSB7XHJcbiAgICAgICAgY29uc3Qgbm90SW1wbEVyciA9IFwiU3RvcmFnZSBpbnRlcmZhY2UgLSBnZXRSZWZyZXNoVG9rZW5DcmVkZW50aWFsKCkgaGFzIG5vdCBiZWVuIGltcGxlbWVudGVkIGZvciB0aGUgY2FjaGVTdG9yYWdlIGludGVyZmFjZS5cIjtcclxuICAgICAgICB0aHJvdyBBdXRoRXJyb3IuY3JlYXRlVW5leHBlY3RlZEVycm9yKG5vdEltcGxFcnIpO1xyXG4gICAgfVxyXG4gICAgc2V0QXBwTWV0YWRhdGEoKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3Qgbm90SW1wbEVyciA9IFwiU3RvcmFnZSBpbnRlcmZhY2UgLSBzZXRBcHBNZXRhZGF0YSgpIGhhcyBub3QgYmVlbiBpbXBsZW1lbnRlZCBmb3IgdGhlIGNhY2hlU3RvcmFnZSBpbnRlcmZhY2UuXCI7XHJcbiAgICAgICAgdGhyb3cgQXV0aEVycm9yLmNyZWF0ZVVuZXhwZWN0ZWRFcnJvcihub3RJbXBsRXJyKTtcclxuICAgIH1cclxuICAgIGdldEFwcE1ldGFkYXRhKCk6IEFwcE1ldGFkYXRhRW50aXR5IHtcclxuICAgICAgICBjb25zdCBub3RJbXBsRXJyID0gXCJTdG9yYWdlIGludGVyZmFjZSAtIGdldEFwcE1ldGFkYXRhKCkgaGFzIG5vdCBiZWVuIGltcGxlbWVudGVkIGZvciB0aGUgY2FjaGVTdG9yYWdlIGludGVyZmFjZS5cIjtcclxuICAgICAgICB0aHJvdyBBdXRoRXJyb3IuY3JlYXRlVW5leHBlY3RlZEVycm9yKG5vdEltcGxFcnIpO1xyXG4gICAgfVxyXG4gICAgc2V0U2VydmVyVGVsZW1ldHJ5KCk6IHZvaWQge1xyXG4gICAgICAgIGNvbnN0IG5vdEltcGxFcnIgPSBcIlN0b3JhZ2UgaW50ZXJmYWNlIC0gc2V0U2VydmVyVGVsZW1ldHJ5KCkgaGFzIG5vdCBiZWVuIGltcGxlbWVudGVkIGZvciB0aGUgY2FjaGVTdG9yYWdlIGludGVyZmFjZS5cIjtcclxuICAgICAgICB0aHJvdyBBdXRoRXJyb3IuY3JlYXRlVW5leHBlY3RlZEVycm9yKG5vdEltcGxFcnIpO1xyXG4gICAgfVxyXG4gICAgZ2V0U2VydmVyVGVsZW1ldHJ5KCk6IFNlcnZlclRlbGVtZXRyeUVudGl0eSB7XHJcbiAgICAgICAgY29uc3Qgbm90SW1wbEVyciA9IFwiU3RvcmFnZSBpbnRlcmZhY2UgLSBnZXRTZXJ2ZXJUZWxlbWV0cnkoKSBoYXMgbm90IGJlZW4gaW1wbGVtZW50ZWQgZm9yIHRoZSBjYWNoZVN0b3JhZ2UgaW50ZXJmYWNlLlwiO1xyXG4gICAgICAgIHRocm93IEF1dGhFcnJvci5jcmVhdGVVbmV4cGVjdGVkRXJyb3Iobm90SW1wbEVycik7XHJcbiAgICB9XHJcbiAgICBzZXRBdXRob3JpdHlNZXRhZGF0YSgpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBub3RJbXBsRXJyID0gXCJTdG9yYWdlIGludGVyZmFjZSAtIHNldEF1dGhvcml0eU1ldGFkYXRhKCkgaGFzIG5vdCBiZWVuIGltcGxlbWVudGVkIGZvciB0aGUgY2FjaGVTdG9yYWdlIGludGVyZmFjZS5cIjtcclxuICAgICAgICB0aHJvdyBBdXRoRXJyb3IuY3JlYXRlVW5leHBlY3RlZEVycm9yKG5vdEltcGxFcnIpO1xyXG4gICAgfVxyXG4gICAgZ2V0QXV0aG9yaXR5TWV0YWRhdGEoKTogQXV0aG9yaXR5TWV0YWRhdGFFbnRpdHkgfCBudWxsIHtcclxuICAgICAgICBjb25zdCBub3RJbXBsRXJyID0gXCJTdG9yYWdlIGludGVyZmFjZSAtIGdldEF1dGhvcml0eU1ldGFkYXRhKCkgaGFzIG5vdCBiZWVuIGltcGxlbWVudGVkIGZvciB0aGUgY2FjaGVTdG9yYWdlIGludGVyZmFjZS5cIjtcclxuICAgICAgICB0aHJvdyBBdXRoRXJyb3IuY3JlYXRlVW5leHBlY3RlZEVycm9yKG5vdEltcGxFcnIpO1xyXG4gICAgfVxyXG4gICAgZ2V0QXV0aG9yaXR5TWV0YWRhdGFLZXlzKCk6IEFycmF5PHN0cmluZz4ge1xyXG4gICAgICAgIGNvbnN0IG5vdEltcGxFcnIgPSBcIlN0b3JhZ2UgaW50ZXJmYWNlIC0gZ2V0QXV0aG9yaXR5TWV0YWRhdGFLZXlzKCkgaGFzIG5vdCBiZWVuIGltcGxlbWVudGVkIGZvciB0aGUgY2FjaGVTdG9yYWdlIGludGVyZmFjZS5cIjtcclxuICAgICAgICB0aHJvdyBBdXRoRXJyb3IuY3JlYXRlVW5leHBlY3RlZEVycm9yKG5vdEltcGxFcnIpO1xyXG4gICAgfVxyXG4gICAgc2V0VGhyb3R0bGluZ0NhY2hlKCk6IHZvaWQge1xyXG4gICAgICAgIGNvbnN0IG5vdEltcGxFcnIgPSBcIlN0b3JhZ2UgaW50ZXJmYWNlIC0gc2V0VGhyb3R0bGluZ0NhY2hlKCkgaGFzIG5vdCBiZWVuIGltcGxlbWVudGVkIGZvciB0aGUgY2FjaGVTdG9yYWdlIGludGVyZmFjZS5cIjtcclxuICAgICAgICB0aHJvdyBBdXRoRXJyb3IuY3JlYXRlVW5leHBlY3RlZEVycm9yKG5vdEltcGxFcnIpO1xyXG4gICAgfVxyXG4gICAgZ2V0VGhyb3R0bGluZ0NhY2hlKCk6IFRocm90dGxpbmdFbnRpdHkge1xyXG4gICAgICAgIGNvbnN0IG5vdEltcGxFcnIgPSBcIlN0b3JhZ2UgaW50ZXJmYWNlIC0gZ2V0VGhyb3R0bGluZ0NhY2hlKCkgaGFzIG5vdCBiZWVuIGltcGxlbWVudGVkIGZvciB0aGUgY2FjaGVTdG9yYWdlIGludGVyZmFjZS5cIjtcclxuICAgICAgICB0aHJvdyBBdXRoRXJyb3IuY3JlYXRlVW5leHBlY3RlZEVycm9yKG5vdEltcGxFcnIpO1xyXG4gICAgfVxyXG4gICAgcmVtb3ZlSXRlbSgpOiBib29sZWFuIHtcclxuICAgICAgICBjb25zdCBub3RJbXBsRXJyID0gXCJTdG9yYWdlIGludGVyZmFjZSAtIHJlbW92ZUl0ZW0oKSBoYXMgbm90IGJlZW4gaW1wbGVtZW50ZWQgZm9yIHRoZSBjYWNoZVN0b3JhZ2UgaW50ZXJmYWNlLlwiO1xyXG4gICAgICAgIHRocm93IEF1dGhFcnJvci5jcmVhdGVVbmV4cGVjdGVkRXJyb3Iobm90SW1wbEVycik7XHJcbiAgICB9XHJcbiAgICBjb250YWluc0tleSgpOiBib29sZWFuIHtcclxuICAgICAgICBjb25zdCBub3RJbXBsRXJyID0gXCJTdG9yYWdlIGludGVyZmFjZSAtIGNvbnRhaW5zS2V5KCkgaGFzIG5vdCBiZWVuIGltcGxlbWVudGVkIGZvciB0aGUgY2FjaGVTdG9yYWdlIGludGVyZmFjZS5cIjtcclxuICAgICAgICB0aHJvdyBBdXRoRXJyb3IuY3JlYXRlVW5leHBlY3RlZEVycm9yKG5vdEltcGxFcnIpO1xyXG4gICAgfVxyXG4gICAgZ2V0S2V5cygpOiBzdHJpbmdbXSB7XHJcbiAgICAgICAgY29uc3Qgbm90SW1wbEVyciA9IFwiU3RvcmFnZSBpbnRlcmZhY2UgLSBnZXRLZXlzKCkgaGFzIG5vdCBiZWVuIGltcGxlbWVudGVkIGZvciB0aGUgY2FjaGVTdG9yYWdlIGludGVyZmFjZS5cIjtcclxuICAgICAgICB0aHJvdyBBdXRoRXJyb3IuY3JlYXRlVW5leHBlY3RlZEVycm9yKG5vdEltcGxFcnIpO1xyXG4gICAgfVxyXG4gICAgY2xlYXIoKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3Qgbm90SW1wbEVyciA9IFwiU3RvcmFnZSBpbnRlcmZhY2UgLSBjbGVhcigpIGhhcyBub3QgYmVlbiBpbXBsZW1lbnRlZCBmb3IgdGhlIGNhY2hlU3RvcmFnZSBpbnRlcmZhY2UuXCI7XHJcbiAgICAgICAgdGhyb3cgQXV0aEVycm9yLmNyZWF0ZVVuZXhwZWN0ZWRFcnJvcihub3RJbXBsRXJyKTtcclxuICAgIH1cclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IElOZXR3b3JrTW9kdWxlIH0gZnJvbSBcIi4uL25ldHdvcmsvSU5ldHdvcmtNb2R1bGVcIjtcclxuaW1wb3J0IHsgREVGQVVMVF9DUllQVE9fSU1QTEVNRU5UQVRJT04sIElDcnlwdG8gfSBmcm9tIFwiLi4vY3J5cHRvL0lDcnlwdG9cIjtcclxuaW1wb3J0IHsgQXV0aEVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL0F1dGhFcnJvclwiO1xyXG5pbXBvcnQgeyBJTG9nZ2VyQ2FsbGJhY2ssIExvZ0xldmVsIH0gZnJvbSBcIi4uL2xvZ2dlci9Mb2dnZXJcIjtcclxuaW1wb3J0IHsgQ29uc3RhbnRzIH0gZnJvbSBcIi4uL3V0aWxzL0NvbnN0YW50c1wiO1xyXG5pbXBvcnQgeyB2ZXJzaW9uIH0gZnJvbSBcIi4uL3BhY2thZ2VNZXRhZGF0YVwiO1xyXG5pbXBvcnQgeyBBdXRob3JpdHkgfSBmcm9tIFwiLi4vYXV0aG9yaXR5L0F1dGhvcml0eVwiO1xyXG5pbXBvcnQgeyBDYWNoZU1hbmFnZXIsIERlZmF1bHRTdG9yYWdlQ2xhc3MgfSBmcm9tIFwiLi4vY2FjaGUvQ2FjaGVNYW5hZ2VyXCI7XHJcbmltcG9ydCB7IFNlcnZlclRlbGVtZXRyeU1hbmFnZXIgfSBmcm9tIFwiLi4vdGVsZW1ldHJ5L3NlcnZlci9TZXJ2ZXJUZWxlbWV0cnlNYW5hZ2VyXCI7XHJcbmltcG9ydCB7IElDYWNoZVBsdWdpbiB9IGZyb20gXCIuLi9jYWNoZS9pbnRlcmZhY2UvSUNhY2hlUGx1Z2luXCI7XHJcbmltcG9ydCB7IElTZXJpYWxpemFibGVUb2tlbkNhY2hlIH0gZnJvbSBcIi4uL2NhY2hlL2ludGVyZmFjZS9JU2VyaWFsaXphYmxlVG9rZW5DYWNoZVwiO1xyXG5cclxuLy8gVG9rZW4gcmVuZXdhbCBvZmZzZXQgZGVmYXVsdCBpbiBzZWNvbmRzXHJcbmNvbnN0IERFRkFVTFRfVE9LRU5fUkVORVdBTF9PRkZTRVRfU0VDID0gMzAwO1xyXG5cclxuLyoqXHJcbiAqIFVzZSB0aGUgY29uZmlndXJhdGlvbiBvYmplY3QgdG8gY29uZmlndXJlIE1TQUwgTW9kdWxlcyBhbmQgaW5pdGlhbGl6ZSB0aGUgYmFzZSBpbnRlcmZhY2VzIGZvciBNU0FMLlxyXG4gKlxyXG4gKiBUaGlzIG9iamVjdCBhbGxvd3MgeW91IHRvIGNvbmZpZ3VyZSBpbXBvcnRhbnQgZWxlbWVudHMgb2YgTVNBTCBmdW5jdGlvbmFsaXR5OlxyXG4gKiAtIGF1dGhPcHRpb25zICAgICAgICAgICAgICAgIC0gQXV0aGVudGljYXRpb24gZm9yIGFwcGxpY2F0aW9uXHJcbiAqIC0gY3J5cHRvSW50ZXJmYWNlICAgICAgICAgICAgLSBJbXBsZW1lbnRhdGlvbiBvZiBjcnlwdG8gZnVuY3Rpb25zXHJcbiAqIC0gbGlicmFyeUluZm8gICAgICAgICAgICAgICAgLSBMaWJyYXJ5IG1ldGFkYXRhXHJcbiAqIC0gbG9nZ2VyT3B0aW9ucyAgICAgICAgICAgICAgLSBMb2dnaW5nIGZvciBhcHBsaWNhdGlvblxyXG4gKiAtIG5ldHdvcmtJbnRlcmZhY2UgICAgICAgICAgIC0gTmV0d29yayBpbXBsZW1lbnRhdGlvblxyXG4gKiAtIHN0b3JhZ2VJbnRlcmZhY2UgICAgICAgICAgIC0gU3RvcmFnZSBpbXBsZW1lbnRhdGlvblxyXG4gKiAtIHN5c3RlbU9wdGlvbnMgICAgICAgICAgICAgIC0gQWRkaXRpb25hbCBsaWJyYXJ5IG9wdGlvbnNcclxuICogLSBjbGllbnRDcmVkZW50aWFscyAgICAgICAgICAtIENyZWRlbnRpYWxzIG9wdGlvbnMgZm9yIGNvbmZpZGVudGlhbCBjbGllbnRzXHJcbiAqL1xyXG5leHBvcnQgdHlwZSBDbGllbnRDb25maWd1cmF0aW9uID0ge1xyXG4gICAgYXV0aE9wdGlvbnM6IEF1dGhPcHRpb25zLFxyXG4gICAgc3lzdGVtT3B0aW9ucz86IFN5c3RlbU9wdGlvbnMsXHJcbiAgICBsb2dnZXJPcHRpb25zPzogTG9nZ2VyT3B0aW9ucyxcclxuICAgIHN0b3JhZ2VJbnRlcmZhY2U/OiBDYWNoZU1hbmFnZXIsXHJcbiAgICBuZXR3b3JrSW50ZXJmYWNlPzogSU5ldHdvcmtNb2R1bGUsXHJcbiAgICBjcnlwdG9JbnRlcmZhY2U/OiBJQ3J5cHRvLFxyXG4gICAgY2xpZW50Q3JlZGVudGlhbHM/OiBDbGllbnRDcmVkZW50aWFscyxcclxuICAgIGxpYnJhcnlJbmZvPzogTGlicmFyeUluZm9cclxuICAgIHNlcnZlclRlbGVtZXRyeU1hbmFnZXI/OiBTZXJ2ZXJUZWxlbWV0cnlNYW5hZ2VyIHwgbnVsbCxcclxuICAgIHBlcnNpc3RlbmNlUGx1Z2luPzogSUNhY2hlUGx1Z2luIHwgbnVsbCxcclxuICAgIHNlcmlhbGl6YWJsZUNhY2hlPzogSVNlcmlhbGl6YWJsZVRva2VuQ2FjaGUgfCBudWxsXHJcbn07XHJcblxyXG5leHBvcnQgdHlwZSBDb21tb25DbGllbnRDb25maWd1cmF0aW9uID0ge1xyXG4gICAgYXV0aE9wdGlvbnM6IFJlcXVpcmVkPEF1dGhPcHRpb25zPixcclxuICAgIHN5c3RlbU9wdGlvbnM6IFJlcXVpcmVkPFN5c3RlbU9wdGlvbnM+LFxyXG4gICAgbG9nZ2VyT3B0aW9ucyA6IFJlcXVpcmVkPExvZ2dlck9wdGlvbnM+LFxyXG4gICAgc3RvcmFnZUludGVyZmFjZTogQ2FjaGVNYW5hZ2VyLFxyXG4gICAgbmV0d29ya0ludGVyZmFjZSA6IElOZXR3b3JrTW9kdWxlLFxyXG4gICAgY3J5cHRvSW50ZXJmYWNlIDogUmVxdWlyZWQ8SUNyeXB0bz4sXHJcbiAgICBsaWJyYXJ5SW5mbyA6IExpYnJhcnlJbmZvLFxyXG4gICAgc2VydmVyVGVsZW1ldHJ5TWFuYWdlcjogU2VydmVyVGVsZW1ldHJ5TWFuYWdlciB8IG51bGwsXHJcbiAgICBjbGllbnRDcmVkZW50aWFsczogQ2xpZW50Q3JlZGVudGlhbHMsXHJcbiAgICBwZXJzaXN0ZW5jZVBsdWdpbjogSUNhY2hlUGx1Z2luIHwgbnVsbCxcclxuICAgIHNlcmlhbGl6YWJsZUNhY2hlOiBJU2VyaWFsaXphYmxlVG9rZW5DYWNoZSB8IG51bGxcclxufTtcclxuXHJcbi8qKlxyXG4gKiBVc2UgdGhpcyB0byBjb25maWd1cmUgdGhlIGF1dGggb3B0aW9ucyBpbiB0aGUgQ2xpZW50Q29uZmlndXJhdGlvbiBvYmplY3RcclxuICpcclxuICogLSBjbGllbnRJZCAgICAgICAgICAgICAgICAgICAgLSBDbGllbnQgSUQgb2YgeW91ciBhcHAgcmVnaXN0ZXJlZCB3aXRoIG91ciBBcHBsaWNhdGlvbiByZWdpc3RyYXRpb24gcG9ydGFsIDogaHR0cHM6Ly9wb3J0YWwuYXp1cmUuY29tLyNibGFkZS9NaWNyb3NvZnRfQUFEX0lBTS9BY3RpdmVEaXJlY3RvcnlNZW51QmxhZGUvUmVnaXN0ZXJlZEFwcHNQcmV2aWV3IGluIE1pY3Jvc29mdCBJZGVudGl0eSBQbGF0Zm9ybVxyXG4gKiAtIGF1dGhvcml0eSAgICAgICAgICAgICAgICAgICAtIFlvdSBjYW4gY29uZmlndXJlIGEgc3BlY2lmaWMgYXV0aG9yaXR5LCBkZWZhdWx0cyB0byBcIiBcIiBvciBcImh0dHBzOi8vbG9naW4ubWljcm9zb2Z0b25saW5lLmNvbS9jb21tb25cIlxyXG4gKiAtIGtub3duQXV0aG9yaXRpZXMgICAgICAgICAgICAtIEFuIGFycmF5IG9mIFVSSXMgdGhhdCBhcmUga25vd24gdG8gYmUgdmFsaWQuIFVzZWQgaW4gQjJDIHNjZW5hcmlvcy5cclxuICogLSBjbG91ZERpc2NvdmVyeU1ldGFkYXRhICAgICAgLSBBIHN0cmluZyBjb250YWluaW5nIHRoZSBjbG91ZCBkaXNjb3ZlcnkgcmVzcG9uc2UuIFVzZWQgaW4gQUFEIHNjZW5hcmlvcy5cclxuICogLSBjbGllbnRDYXBhYmlsaXRpZXMgICAgICAgICAgLSBBcnJheSBvZiBjYXBhYmlsaXRpZXMgd2hpY2ggd2lsbCBiZSBhZGRlZCB0byB0aGUgY2xhaW1zLmFjY2Vzc190b2tlbi54bXNfY2MgcmVxdWVzdCBwcm9wZXJ0eSBvbiBldmVyeSBuZXR3b3JrIHJlcXVlc3QuXHJcbiAqIC0gcHJvdG9jb2xNb2RlICAgICAgICAgICAgICAgIC0gRW51bSB0aGF0IHJlcHJlc2VudHMgdGhlIHByb3RvY29sIHRoYXQgbXNhbCBmb2xsb3dzLiBVc2VkIGZvciBjb25maWd1cmluZyBwcm9wZXIgZW5kcG9pbnRzLlxyXG4gKi9cclxuZXhwb3J0IHR5cGUgQXV0aE9wdGlvbnMgPSB7XHJcbiAgICBjbGllbnRJZDogc3RyaW5nO1xyXG4gICAgYXV0aG9yaXR5OiBBdXRob3JpdHk7XHJcbiAgICBjbGllbnRDYXBhYmlsaXRpZXM/OiBBcnJheTxzdHJpbmc+O1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFVzZSB0aGlzIHRvIGNvbmZpZ3VyZSB0b2tlbiByZW5ld2FsIGluZm8gaW4gdGhlIENvbmZpZ3VyYXRpb24gb2JqZWN0XHJcbiAqXHJcbiAqIC0gdG9rZW5SZW5ld2FsT2Zmc2V0U2Vjb25kcyAgICAtIFNldHMgdGhlIHdpbmRvdyBvZiBvZmZzZXQgbmVlZGVkIHRvIHJlbmV3IHRoZSB0b2tlbiBiZWZvcmUgZXhwaXJ5XHJcbiAqL1xyXG5leHBvcnQgdHlwZSBTeXN0ZW1PcHRpb25zID0ge1xyXG4gICAgdG9rZW5SZW5ld2FsT2Zmc2V0U2Vjb25kcz86IG51bWJlcjtcclxufTtcclxuXHJcbi8qKlxyXG4gKiAgVXNlIHRoaXMgdG8gY29uZmlndXJlIHRoZSBsb2dnaW5nIHRoYXQgTVNBTCBkb2VzLCBieSBjb25maWd1cmluZyBsb2dnZXIgb3B0aW9ucyBpbiB0aGUgQ29uZmlndXJhdGlvbiBvYmplY3RcclxuICpcclxuICogLSBsb2dnZXJDYWxsYmFjayAgICAgICAgICAgICAgICAtIENhbGxiYWNrIGZvciBsb2dnZXJcclxuICogLSBwaWlMb2dnaW5nRW5hYmxlZCAgICAgICAgICAgICAtIFNldHMgd2hldGhlciBwaWkgbG9nZ2luZyBpcyBlbmFibGVkXHJcbiAqIC0gbG9nTGV2ZWwgICAgICAgICAgICAgICAgICAgICAgLSBTZXRzIHRoZSBsZXZlbCBhdCB3aGljaCBsb2dnaW5nIGhhcHBlbnNcclxuICovXHJcbmV4cG9ydCB0eXBlIExvZ2dlck9wdGlvbnMgPSB7XHJcbiAgICBsb2dnZXJDYWxsYmFjaz86IElMb2dnZXJDYWxsYmFjayxcclxuICAgIHBpaUxvZ2dpbmdFbmFibGVkPzogYm9vbGVhbixcclxuICAgIGxvZ0xldmVsPzogTG9nTGV2ZWxcclxufTtcclxuXHJcbi8qKlxyXG4gKiBMaWJyYXJ5LXNwZWNpZmljIG9wdGlvbnNcclxuICovXHJcbmV4cG9ydCB0eXBlIExpYnJhcnlJbmZvID0ge1xyXG4gICAgc2t1OiBzdHJpbmcsXHJcbiAgICB2ZXJzaW9uOiBzdHJpbmcsXHJcbiAgICBjcHU6IHN0cmluZyxcclxuICAgIG9zOiBzdHJpbmdcclxufTtcclxuXHJcbi8qKlxyXG4gKiBDcmVkZW50aWFscyBmb3IgY29uZmlkZW50aWFsIGNsaWVudHNcclxuICovXHJcbmV4cG9ydCB0eXBlIENsaWVudENyZWRlbnRpYWxzID0ge1xyXG4gICAgY2xpZW50U2VjcmV0Pzogc3RyaW5nLFxyXG4gICAgY2xpZW50QXNzZXJ0aW9uPyA6IHtcclxuICAgICAgICBhc3NlcnRpb246IHN0cmluZyxcclxuICAgICAgICBhc3NlcnRpb25UeXBlOiBzdHJpbmdcclxuICAgIH07XHJcbn07XHJcblxyXG5leHBvcnQgY29uc3QgREVGQVVMVF9TWVNURU1fT1BUSU9OUzogUmVxdWlyZWQ8U3lzdGVtT3B0aW9ucz4gPSB7XHJcbiAgICB0b2tlblJlbmV3YWxPZmZzZXRTZWNvbmRzOiBERUZBVUxUX1RPS0VOX1JFTkVXQUxfT0ZGU0VUX1NFQ1xyXG59O1xyXG5cclxuY29uc3QgREVGQVVMVF9MT0dHRVJfSU1QTEVNRU5UQVRJT046IFJlcXVpcmVkPExvZ2dlck9wdGlvbnM+ID0ge1xyXG4gICAgbG9nZ2VyQ2FsbGJhY2s6ICgpID0+IHtcclxuICAgICAgICAvLyBhbGxvdyB1c2VycyB0byBub3Qgc2V0IGxvZ2dlckNhbGxiYWNrXHJcbiAgICB9LFxyXG4gICAgcGlpTG9nZ2luZ0VuYWJsZWQ6IGZhbHNlLFxyXG4gICAgbG9nTGV2ZWw6IExvZ0xldmVsLkluZm9cclxufTtcclxuXHJcbmNvbnN0IERFRkFVTFRfTkVUV09SS19JTVBMRU1FTlRBVElPTjogSU5ldHdvcmtNb2R1bGUgPSB7XHJcbiAgICBhc3luYyBzZW5kR2V0UmVxdWVzdEFzeW5jPFQ+KCk6IFByb21pc2U8VD4ge1xyXG4gICAgICAgIGNvbnN0IG5vdEltcGxFcnIgPSBcIk5ldHdvcmsgaW50ZXJmYWNlIC0gc2VuZEdldFJlcXVlc3RBc3luYygpIGhhcyBub3QgYmVlbiBpbXBsZW1lbnRlZFwiO1xyXG4gICAgICAgIHRocm93IEF1dGhFcnJvci5jcmVhdGVVbmV4cGVjdGVkRXJyb3Iobm90SW1wbEVycik7XHJcbiAgICB9LFxyXG4gICAgYXN5bmMgc2VuZFBvc3RSZXF1ZXN0QXN5bmM8VD4oKTogUHJvbWlzZTxUPiB7XHJcbiAgICAgICAgY29uc3Qgbm90SW1wbEVyciA9IFwiTmV0d29yayBpbnRlcmZhY2UgLSBzZW5kUG9zdFJlcXVlc3RBc3luYygpIGhhcyBub3QgYmVlbiBpbXBsZW1lbnRlZFwiO1xyXG4gICAgICAgIHRocm93IEF1dGhFcnJvci5jcmVhdGVVbmV4cGVjdGVkRXJyb3Iobm90SW1wbEVycik7XHJcbiAgICB9XHJcbn07XHJcblxyXG5jb25zdCBERUZBVUxUX0xJQlJBUllfSU5GTzogTGlicmFyeUluZm8gPSB7XHJcbiAgICBza3U6IENvbnN0YW50cy5TS1UsXHJcbiAgICB2ZXJzaW9uOiB2ZXJzaW9uLFxyXG4gICAgY3B1OiBcIlwiLFxyXG4gICAgb3M6IFwiXCJcclxufTtcclxuXHJcbmNvbnN0IERFRkFVTFRfQ0xJRU5UX0NSRURFTlRJQUxTOiBDbGllbnRDcmVkZW50aWFscyA9IHtcclxuICAgIGNsaWVudFNlY3JldDogXCJcIixcclxuICAgIGNsaWVudEFzc2VydGlvbjogdW5kZWZpbmVkXHJcbn07XHJcblxyXG4vKipcclxuICogRnVuY3Rpb24gdGhhdCBzZXRzIHRoZSBkZWZhdWx0IG9wdGlvbnMgd2hlbiBub3QgZXhwbGljaXRseSBjb25maWd1cmVkIGZyb20gYXBwIGRldmVsb3BlclxyXG4gKlxyXG4gKiBAcGFyYW0gQ29uZmlndXJhdGlvblxyXG4gKlxyXG4gKiBAcmV0dXJucyBDb25maWd1cmF0aW9uXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRDbGllbnRDb25maWd1cmF0aW9uKFxyXG4gICAge1xyXG4gICAgICAgIGF1dGhPcHRpb25zOiB1c2VyQXV0aE9wdGlvbnMsXHJcbiAgICAgICAgc3lzdGVtT3B0aW9uczogdXNlclN5c3RlbU9wdGlvbnMsXHJcbiAgICAgICAgbG9nZ2VyT3B0aW9uczogdXNlckxvZ2dlck9wdGlvbixcclxuICAgICAgICBzdG9yYWdlSW50ZXJmYWNlOiBzdG9yYWdlSW1wbGVtZW50YXRpb24sXHJcbiAgICAgICAgbmV0d29ya0ludGVyZmFjZTogbmV0d29ya0ltcGxlbWVudGF0aW9uLFxyXG4gICAgICAgIGNyeXB0b0ludGVyZmFjZTogY3J5cHRvSW1wbGVtZW50YXRpb24sXHJcbiAgICAgICAgY2xpZW50Q3JlZGVudGlhbHM6IGNsaWVudENyZWRlbnRpYWxzLFxyXG4gICAgICAgIGxpYnJhcnlJbmZvOiBsaWJyYXJ5SW5mbyxcclxuICAgICAgICBzZXJ2ZXJUZWxlbWV0cnlNYW5hZ2VyOiBzZXJ2ZXJUZWxlbWV0cnlNYW5hZ2VyLFxyXG4gICAgICAgIHBlcnNpc3RlbmNlUGx1Z2luOiBwZXJzaXN0ZW5jZVBsdWdpbixcclxuICAgICAgICBzZXJpYWxpemFibGVDYWNoZTogc2VyaWFsaXphYmxlQ2FjaGVcclxuICAgIH06IENsaWVudENvbmZpZ3VyYXRpb24pOiBDb21tb25DbGllbnRDb25maWd1cmF0aW9uIHtcclxuXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAgIGF1dGhPcHRpb25zOiBidWlsZEF1dGhPcHRpb25zKHVzZXJBdXRoT3B0aW9ucyksXHJcbiAgICAgICAgc3lzdGVtT3B0aW9uczogeyAuLi5ERUZBVUxUX1NZU1RFTV9PUFRJT05TLCAuLi51c2VyU3lzdGVtT3B0aW9ucyB9LFxyXG4gICAgICAgIGxvZ2dlck9wdGlvbnM6IHsgLi4uREVGQVVMVF9MT0dHRVJfSU1QTEVNRU5UQVRJT04sIC4uLnVzZXJMb2dnZXJPcHRpb24gfSxcclxuICAgICAgICBzdG9yYWdlSW50ZXJmYWNlOiBzdG9yYWdlSW1wbGVtZW50YXRpb24gfHwgbmV3IERlZmF1bHRTdG9yYWdlQ2xhc3ModXNlckF1dGhPcHRpb25zLmNsaWVudElkLCBERUZBVUxUX0NSWVBUT19JTVBMRU1FTlRBVElPTiksXHJcbiAgICAgICAgbmV0d29ya0ludGVyZmFjZTogbmV0d29ya0ltcGxlbWVudGF0aW9uIHx8IERFRkFVTFRfTkVUV09SS19JTVBMRU1FTlRBVElPTixcclxuICAgICAgICBjcnlwdG9JbnRlcmZhY2U6IGNyeXB0b0ltcGxlbWVudGF0aW9uIHx8IERFRkFVTFRfQ1JZUFRPX0lNUExFTUVOVEFUSU9OLFxyXG4gICAgICAgIGNsaWVudENyZWRlbnRpYWxzOiBjbGllbnRDcmVkZW50aWFscyB8fCBERUZBVUxUX0NMSUVOVF9DUkVERU5USUFMUyxcclxuICAgICAgICBsaWJyYXJ5SW5mbzogeyAuLi5ERUZBVUxUX0xJQlJBUllfSU5GTywgLi4ubGlicmFyeUluZm8gfSxcclxuICAgICAgICBzZXJ2ZXJUZWxlbWV0cnlNYW5hZ2VyOiBzZXJ2ZXJUZWxlbWV0cnlNYW5hZ2VyIHx8IG51bGwsXHJcbiAgICAgICAgcGVyc2lzdGVuY2VQbHVnaW46IHBlcnNpc3RlbmNlUGx1Z2luIHx8IG51bGwsXHJcbiAgICAgICAgc2VyaWFsaXphYmxlQ2FjaGU6IHNlcmlhbGl6YWJsZUNhY2hlIHx8IG51bGxcclxuICAgIH07XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDb25zdHJ1Y3QgYXV0aG9wdGlvbnMgZnJvbSB0aGUgY2xpZW50IGFuZCBwbGF0Zm9ybSBwYXNzZWQgdmFsdWVzXHJcbiAqIEBwYXJhbSBhdXRoT3B0aW9uc1xyXG4gKi9cclxuZnVuY3Rpb24gYnVpbGRBdXRoT3B0aW9ucyhhdXRoT3B0aW9uczogQXV0aE9wdGlvbnMpOiBSZXF1aXJlZDxBdXRoT3B0aW9ucz4ge1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgICBjbGllbnRDYXBhYmlsaXRpZXM6IFtdLFxyXG4gICAgICAgIC4uLmF1dGhPcHRpb25zXHJcbiAgICB9O1xyXG59XHJcbiIsIi8qXHJcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgQXV0aEVycm9yIH0gZnJvbSBcIi4vQXV0aEVycm9yXCI7XHJcblxyXG4vKipcclxuICogRXJyb3IgdGhyb3duIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3Igd2l0aCB0aGUgc2VydmVyIGNvZGUsIGZvciBleGFtcGxlLCB1bmF2YWlsYWJpbGl0eS5cclxuICovXHJcbmV4cG9ydCBjbGFzcyBTZXJ2ZXJFcnJvciBleHRlbmRzIEF1dGhFcnJvciB7XHJcblxyXG4gICAgY29uc3RydWN0b3IoZXJyb3JDb2RlPzogc3RyaW5nLCBlcnJvck1lc3NhZ2U/OiBzdHJpbmcsIHN1YkVycm9yPzogc3RyaW5nKSB7XHJcbiAgICAgICAgc3VwZXIoZXJyb3JDb2RlLCBlcnJvck1lc3NhZ2UsIHN1YkVycm9yKTtcclxuICAgICAgICB0aGlzLm5hbWUgPSBcIlNlcnZlckVycm9yXCI7XHJcblxyXG4gICAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBTZXJ2ZXJFcnJvci5wcm90b3R5cGUpO1xyXG4gICAgfVxyXG59XHJcbiIsIi8qXHJcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgTmV0d29ya1Jlc3BvbnNlIH0gZnJvbSBcIi4vTmV0d29ya01hbmFnZXJcIjtcclxuaW1wb3J0IHsgU2VydmVyQXV0aG9yaXphdGlvblRva2VuUmVzcG9uc2UgfSBmcm9tIFwiLi4vcmVzcG9uc2UvU2VydmVyQXV0aG9yaXphdGlvblRva2VuUmVzcG9uc2VcIjtcclxuaW1wb3J0IHsgSGVhZGVyTmFtZXMsIENhY2hlU2NoZW1hVHlwZSwgVGhyb3R0bGluZ0NvbnN0YW50cywgQ29uc3RhbnRzIH0gZnJvbSBcIi4uL3V0aWxzL0NvbnN0YW50c1wiO1xyXG5pbXBvcnQgeyBDYWNoZU1hbmFnZXIgfSBmcm9tIFwiLi4vY2FjaGUvQ2FjaGVNYW5hZ2VyXCI7XHJcbmltcG9ydCB7IFNlcnZlckVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL1NlcnZlckVycm9yXCI7XHJcbmltcG9ydCB7IFJlcXVlc3RUaHVtYnByaW50IH0gZnJvbSBcIi4vUmVxdWVzdFRodW1icHJpbnRcIjtcclxuaW1wb3J0IHsgVGhyb3R0bGluZ0VudGl0eSB9IGZyb20gXCIuLi9jYWNoZS9lbnRpdGllcy9UaHJvdHRsaW5nRW50aXR5XCI7XHJcblxyXG5leHBvcnQgY2xhc3MgVGhyb3R0bGluZ1V0aWxzIHtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFByZXBhcmVzIGEgUmVxdWVzdFRodW1icHJpbnQgdG8gYmUgc3RvcmVkIGFzIGEga2V5LlxyXG4gICAgICogQHBhcmFtIHRodW1icHJpbnRcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGdlbmVyYXRlVGhyb3R0bGluZ1N0b3JhZ2VLZXkodGh1bWJwcmludDogUmVxdWVzdFRodW1icHJpbnQpOiBzdHJpbmcge1xyXG4gICAgICAgIHJldHVybiBgJHtUaHJvdHRsaW5nQ29uc3RhbnRzLlRIUk9UVExJTkdfUFJFRklYfS4ke0pTT04uc3RyaW5naWZ5KHRodW1icHJpbnQpfWA7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBQZXJmb3JtcyBuZWNlc3NhcnkgdGhyb3R0bGluZyBjaGVja3MgYmVmb3JlIGEgbmV0d29yayByZXF1ZXN0LlxyXG4gICAgICogQHBhcmFtIGNhY2hlTWFuYWdlclxyXG4gICAgICogQHBhcmFtIHRodW1icHJpbnRcclxuICAgICAqL1xyXG4gICAgc3RhdGljIHByZVByb2Nlc3MoY2FjaGVNYW5hZ2VyOiBDYWNoZU1hbmFnZXIsIHRodW1icHJpbnQ6IFJlcXVlc3RUaHVtYnByaW50KTogdm9pZCB7XHJcbiAgICAgICAgY29uc3Qga2V5ID0gVGhyb3R0bGluZ1V0aWxzLmdlbmVyYXRlVGhyb3R0bGluZ1N0b3JhZ2VLZXkodGh1bWJwcmludCk7XHJcbiAgICAgICAgY29uc3QgdmFsdWUgPSBjYWNoZU1hbmFnZXIuZ2V0VGhyb3R0bGluZ0NhY2hlKGtleSk7XHJcblxyXG4gICAgICAgIGlmICh2YWx1ZSkge1xyXG4gICAgICAgICAgICBpZiAodmFsdWUudGhyb3R0bGVUaW1lIDwgRGF0ZS5ub3coKSkge1xyXG4gICAgICAgICAgICAgICAgY2FjaGVNYW5hZ2VyLnJlbW92ZUl0ZW0oa2V5LCBDYWNoZVNjaGVtYVR5cGUuVEhST1RUTElORyk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhyb3cgbmV3IFNlcnZlckVycm9yKHZhbHVlLmVycm9yQ29kZXM/LmpvaW4oXCIgXCIpIHx8IENvbnN0YW50cy5FTVBUWV9TVFJJTkcsIHZhbHVlLmVycm9yTWVzc2FnZSwgdmFsdWUuc3ViRXJyb3IpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFBlcmZvcm1zIG5lY2Vzc2FyeSB0aHJvdHRsaW5nIGNoZWNrcyBhZnRlciBhIG5ldHdvcmsgcmVxdWVzdC5cclxuICAgICAqIEBwYXJhbSBjYWNoZU1hbmFnZXJcclxuICAgICAqIEBwYXJhbSB0aHVtYnByaW50XHJcbiAgICAgKiBAcGFyYW0gcmVzcG9uc2VcclxuICAgICAqL1xyXG4gICAgc3RhdGljIHBvc3RQcm9jZXNzKGNhY2hlTWFuYWdlcjogQ2FjaGVNYW5hZ2VyLCB0aHVtYnByaW50OiBSZXF1ZXN0VGh1bWJwcmludCwgcmVzcG9uc2U6IE5ldHdvcmtSZXNwb25zZTxTZXJ2ZXJBdXRob3JpemF0aW9uVG9rZW5SZXNwb25zZT4pOiB2b2lkIHtcclxuICAgICAgICBpZiAoVGhyb3R0bGluZ1V0aWxzLmNoZWNrUmVzcG9uc2VTdGF0dXMocmVzcG9uc2UpIHx8IFRocm90dGxpbmdVdGlscy5jaGVja1Jlc3BvbnNlRm9yUmV0cnlBZnRlcihyZXNwb25zZSkpIHtcclxuICAgICAgICAgICAgY29uc3QgdGh1bWJwcmludFZhbHVlOiBUaHJvdHRsaW5nRW50aXR5ID0ge1xyXG4gICAgICAgICAgICAgICAgdGhyb3R0bGVUaW1lOiBUaHJvdHRsaW5nVXRpbHMuY2FsY3VsYXRlVGhyb3R0bGVUaW1lKHBhcnNlSW50KHJlc3BvbnNlLmhlYWRlcnNbSGVhZGVyTmFtZXMuUkVUUllfQUZURVJdKSksXHJcbiAgICAgICAgICAgICAgICBlcnJvcjogcmVzcG9uc2UuYm9keS5lcnJvcixcclxuICAgICAgICAgICAgICAgIGVycm9yQ29kZXM6IHJlc3BvbnNlLmJvZHkuZXJyb3JfY29kZXMsXHJcbiAgICAgICAgICAgICAgICBlcnJvck1lc3NhZ2U6IHJlc3BvbnNlLmJvZHkuZXJyb3JfZGVzY3JpcHRpb24sXHJcbiAgICAgICAgICAgICAgICBzdWJFcnJvcjogcmVzcG9uc2UuYm9keS5zdWJlcnJvclxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICBjYWNoZU1hbmFnZXIuc2V0VGhyb3R0bGluZ0NhY2hlKFxyXG4gICAgICAgICAgICAgICAgVGhyb3R0bGluZ1V0aWxzLmdlbmVyYXRlVGhyb3R0bGluZ1N0b3JhZ2VLZXkodGh1bWJwcmludCksXHJcbiAgICAgICAgICAgICAgICB0aHVtYnByaW50VmFsdWVcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDaGVja3MgYSBOZXR3b3JrUmVzcG9uc2Ugb2JqZWN0J3Mgc3RhdHVzIGNvZGVzIGFnYWluc3QgNDI5IG9yIDV4eFxyXG4gICAgICogQHBhcmFtIHJlc3BvbnNlXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjaGVja1Jlc3BvbnNlU3RhdHVzKHJlc3BvbnNlOiBOZXR3b3JrUmVzcG9uc2U8U2VydmVyQXV0aG9yaXphdGlvblRva2VuUmVzcG9uc2U+KTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlLnN0YXR1cyA9PT0gNDI5IHx8IHJlc3BvbnNlLnN0YXR1cyA+PSA1MDAgJiYgcmVzcG9uc2Uuc3RhdHVzIDwgNjAwO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2hlY2tzIGEgTmV0d29ya1Jlc3BvbnNlIG9iamVjdCdzIFJldHJ5QWZ0ZXIgaGVhZGVyXHJcbiAgICAgKiBAcGFyYW0gcmVzcG9uc2VcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNoZWNrUmVzcG9uc2VGb3JSZXRyeUFmdGVyKHJlc3BvbnNlOiBOZXR3b3JrUmVzcG9uc2U8U2VydmVyQXV0aG9yaXphdGlvblRva2VuUmVzcG9uc2U+KTogYm9vbGVhbiB7XHJcbiAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlcnMpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmhlYWRlcnMuaGFzT3duUHJvcGVydHkoSGVhZGVyTmFtZXMuUkVUUllfQUZURVIpICYmIChyZXNwb25zZS5zdGF0dXMgPCAyMDAgfHwgcmVzcG9uc2Uuc3RhdHVzID49IDMwMCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENhbGN1bGF0ZXMgdGhlIFVuaXgtdGltZSB2YWx1ZSBmb3IgYSB0aHJvdHRsZSB0byBleHBpcmUgZ2l2ZW4gdGhyb3R0bGVUaW1lIGluIHNlY29uZHMuXHJcbiAgICAgKiBAcGFyYW0gdGhyb3R0bGVUaW1lXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjYWxjdWxhdGVUaHJvdHRsZVRpbWUodGhyb3R0bGVUaW1lOiBudW1iZXIpOiBudW1iZXIge1xyXG4gICAgICAgIGlmKHRocm90dGxlVGltZSA8PSAwKSB7XHJcbiAgICAgICAgICAgIHRocm90dGxlVGltZSA9IDA7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IGN1cnJlbnRTZWNvbmRzID0gRGF0ZS5ub3coKSAvIDEwMDA7XHJcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoTWF0aC5taW4oXHJcbiAgICAgICAgICAgIGN1cnJlbnRTZWNvbmRzICsgKHRocm90dGxlVGltZSB8fCBUaHJvdHRsaW5nQ29uc3RhbnRzLkRFRkFVTFRfVEhST1RUTEVfVElNRV9TRUNPTkRTKSxcclxuICAgICAgICAgICAgY3VycmVudFNlY29uZHMgKyBUaHJvdHRsaW5nQ29uc3RhbnRzLkRFRkFVTFRfTUFYX1RIUk9UVExFX1RJTUVfU0VDT05EU1xyXG4gICAgICAgICkgKiAxMDAwKTtcclxuICAgIH1cclxuXHJcbiAgICBzdGF0aWMgcmVtb3ZlVGhyb3R0bGUoY2FjaGVNYW5hZ2VyOiBDYWNoZU1hbmFnZXIsIGNsaWVudElkOiBzdHJpbmcsIGF1dGhvcml0eTogc3RyaW5nLCBzY29wZXM6IEFycmF5PHN0cmluZz4sIGhvbWVBY2NvdW50SWRlbnRpZmllcj86IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGNvbnN0IHRodW1icHJpbnQ6IFJlcXVlc3RUaHVtYnByaW50ID0ge1xyXG4gICAgICAgICAgICBjbGllbnRJZCxcclxuICAgICAgICAgICAgYXV0aG9yaXR5LFxyXG4gICAgICAgICAgICBzY29wZXMsXHJcbiAgICAgICAgICAgIGhvbWVBY2NvdW50SWRlbnRpZmllclxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIGNvbnN0IGtleSA9IHRoaXMuZ2VuZXJhdGVUaHJvdHRsaW5nU3RvcmFnZUtleSh0aHVtYnByaW50KTtcclxuICAgICAgICByZXR1cm4gY2FjaGVNYW5hZ2VyLnJlbW92ZUl0ZW0oa2V5LCBDYWNoZVNjaGVtYVR5cGUuVEhST1RUTElORyk7XHJcbiAgICB9XHJcbn1cclxuIiwiLypcclxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cclxuICovXHJcblxyXG5pbXBvcnQgeyBJTmV0d29ya01vZHVsZSwgTmV0d29ya1JlcXVlc3RPcHRpb25zIH0gZnJvbSBcIi4vSU5ldHdvcmtNb2R1bGVcIjtcclxuaW1wb3J0IHsgUmVxdWVzdFRodW1icHJpbnQgfSBmcm9tIFwiLi9SZXF1ZXN0VGh1bWJwcmludFwiO1xyXG5pbXBvcnQgeyBUaHJvdHRsaW5nVXRpbHMgfSBmcm9tIFwiLi9UaHJvdHRsaW5nVXRpbHNcIjtcclxuaW1wb3J0IHsgQ2FjaGVNYW5hZ2VyIH0gZnJvbSBcIi4uL2NhY2hlL0NhY2hlTWFuYWdlclwiO1xyXG5cclxuZXhwb3J0IHR5cGUgTmV0d29ya1Jlc3BvbnNlPFQ+ID0ge1xyXG4gICAgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcclxuICAgIGJvZHk6IFQ7XHJcbiAgICBzdGF0dXM6IG51bWJlcjtcclxufTtcclxuXHJcbmV4cG9ydCBjbGFzcyBOZXR3b3JrTWFuYWdlciB7XHJcbiAgICBwcml2YXRlIG5ldHdvcmtDbGllbnQ6IElOZXR3b3JrTW9kdWxlO1xyXG4gICAgcHJpdmF0ZSBjYWNoZU1hbmFnZXI6IENhY2hlTWFuYWdlcjtcclxuXHJcbiAgICBjb25zdHJ1Y3RvcihuZXR3b3JrQ2xpZW50OiBJTmV0d29ya01vZHVsZSwgY2FjaGVNYW5hZ2VyOiBDYWNoZU1hbmFnZXIpIHtcclxuICAgICAgICB0aGlzLm5ldHdvcmtDbGllbnQgPSBuZXR3b3JrQ2xpZW50O1xyXG4gICAgICAgIHRoaXMuY2FjaGVNYW5hZ2VyID0gY2FjaGVNYW5hZ2VyO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogV3JhcHMgc2VuZFBvc3RSZXF1ZXN0QXN5bmMgd2l0aCBuZWNlc3NhcnkgcHJlZmxpZ2h0IGFuZCBwb3N0ZmxpZ2h0IGxvZ2ljXHJcbiAgICAgKiBAcGFyYW0gdGh1bWJwcmludFxyXG4gICAgICogQHBhcmFtIHRva2VuRW5kcG9pbnRcclxuICAgICAqIEBwYXJhbSBvcHRpb25zXHJcbiAgICAgKi9cclxuICAgIGFzeW5jIHNlbmRQb3N0UmVxdWVzdDxUPih0aHVtYnByaW50OiBSZXF1ZXN0VGh1bWJwcmludCwgdG9rZW5FbmRwb2ludDogc3RyaW5nLCBvcHRpb25zOiBOZXR3b3JrUmVxdWVzdE9wdGlvbnMpOiBQcm9taXNlPE5ldHdvcmtSZXNwb25zZTxUPj4ge1xyXG4gICAgICAgIFRocm90dGxpbmdVdGlscy5wcmVQcm9jZXNzKHRoaXMuY2FjaGVNYW5hZ2VyLCB0aHVtYnByaW50KTtcclxuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMubmV0d29ya0NsaWVudC5zZW5kUG9zdFJlcXVlc3RBc3luYzxUPih0b2tlbkVuZHBvaW50LCBvcHRpb25zKTtcclxuICAgICAgICBUaHJvdHRsaW5nVXRpbHMucG9zdFByb2Nlc3ModGhpcy5jYWNoZU1hbmFnZXIsIHRodW1icHJpbnQsIHJlc3BvbnNlKTtcclxuXHJcbiAgICAgICAgLy8gUGxhY2Vob2xkZXIgZm9yIFRlbGVtZXRyeSBob29rXHJcblxyXG4gICAgICAgIHJldHVybiByZXNwb25zZTtcclxuICAgIH1cclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IENsaWVudENvbmZpZ3VyYXRpb24sIGJ1aWxkQ2xpZW50Q29uZmlndXJhdGlvbiwgQ29tbW9uQ2xpZW50Q29uZmlndXJhdGlvbiB9IGZyb20gXCIuLi9jb25maWcvQ2xpZW50Q29uZmlndXJhdGlvblwiO1xyXG5pbXBvcnQgeyBJTmV0d29ya01vZHVsZSB9IGZyb20gXCIuLi9uZXR3b3JrL0lOZXR3b3JrTW9kdWxlXCI7XHJcbmltcG9ydCB7IE5ldHdvcmtNYW5hZ2VyLCBOZXR3b3JrUmVzcG9uc2UgfSBmcm9tIFwiLi4vbmV0d29yay9OZXR3b3JrTWFuYWdlclwiO1xyXG5pbXBvcnQgeyBJQ3J5cHRvIH0gZnJvbSBcIi4uL2NyeXB0by9JQ3J5cHRvXCI7XHJcbmltcG9ydCB7IEF1dGhvcml0eSB9IGZyb20gXCIuLi9hdXRob3JpdHkvQXV0aG9yaXR5XCI7XHJcbmltcG9ydCB7IExvZ2dlciB9IGZyb20gXCIuLi9sb2dnZXIvTG9nZ2VyXCI7XHJcbmltcG9ydCB7IEFBRFNlcnZlclBhcmFtS2V5cywgQ29uc3RhbnRzLCBIZWFkZXJOYW1lcyB9IGZyb20gXCIuLi91dGlscy9Db25zdGFudHNcIjtcclxuaW1wb3J0IHsgU2VydmVyQXV0aG9yaXphdGlvblRva2VuUmVzcG9uc2UgfSBmcm9tIFwiLi4vcmVzcG9uc2UvU2VydmVyQXV0aG9yaXphdGlvblRva2VuUmVzcG9uc2VcIjtcclxuaW1wb3J0IHsgQ2FjaGVNYW5hZ2VyIH0gZnJvbSBcIi4uL2NhY2hlL0NhY2hlTWFuYWdlclwiO1xyXG5pbXBvcnQgeyBTZXJ2ZXJUZWxlbWV0cnlNYW5hZ2VyIH0gZnJvbSBcIi4uL3RlbGVtZXRyeS9zZXJ2ZXIvU2VydmVyVGVsZW1ldHJ5TWFuYWdlclwiO1xyXG5pbXBvcnQgeyBSZXF1ZXN0VGh1bWJwcmludCB9IGZyb20gXCIuLi9uZXR3b3JrL1JlcXVlc3RUaHVtYnByaW50XCI7XHJcbmltcG9ydCB7IHZlcnNpb24sIG5hbWUgfSBmcm9tIFwiLi4vcGFja2FnZU1ldGFkYXRhXCI7XHJcbmltcG9ydCB7IENsaWVudEF1dGhFcnJvciB9IGZyb20gXCIuLi9lcnJvci9DbGllbnRBdXRoRXJyb3JcIjtcclxuXHJcbi8qKlxyXG4gKiBCYXNlIGFwcGxpY2F0aW9uIGNsYXNzIHdoaWNoIHdpbGwgY29uc3RydWN0IHJlcXVlc3RzIHRvIHNlbmQgdG8gYW5kIGhhbmRsZSByZXNwb25zZXMgZnJvbSB0aGUgTWljcm9zb2Z0IFNUUyB1c2luZyB0aGUgYXV0aG9yaXphdGlvbiBjb2RlIGZsb3cuXHJcbiAqL1xyXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQmFzZUNsaWVudCB7XHJcbiAgICAvLyBMb2dnZXIgb2JqZWN0XHJcbiAgICBwdWJsaWMgbG9nZ2VyOiBMb2dnZXI7XHJcblxyXG4gICAgLy8gQXBwbGljYXRpb24gY29uZmlnXHJcbiAgICBwcm90ZWN0ZWQgY29uZmlnOiBDb21tb25DbGllbnRDb25maWd1cmF0aW9uO1xyXG5cclxuICAgIC8vIENyeXB0byBJbnRlcmZhY2VcclxuICAgIHByb3RlY3RlZCBjcnlwdG9VdGlsczogSUNyeXB0bztcclxuXHJcbiAgICAvLyBTdG9yYWdlIEludGVyZmFjZVxyXG4gICAgcHJvdGVjdGVkIGNhY2hlTWFuYWdlcjogQ2FjaGVNYW5hZ2VyO1xyXG5cclxuICAgIC8vIE5ldHdvcmsgSW50ZXJmYWNlXHJcbiAgICBwcm90ZWN0ZWQgbmV0d29ya0NsaWVudDogSU5ldHdvcmtNb2R1bGU7XHJcblxyXG4gICAgLy8gU2VydmVyIFRlbGVtZXRyeSBNYW5hZ2VyXHJcbiAgICBwcm90ZWN0ZWQgc2VydmVyVGVsZW1ldHJ5TWFuYWdlcjogU2VydmVyVGVsZW1ldHJ5TWFuYWdlciB8IG51bGw7XHJcblxyXG4gICAgLy8gTmV0d29yayBNYW5hZ2VyXHJcbiAgICBwcm90ZWN0ZWQgbmV0d29ya01hbmFnZXI6IE5ldHdvcmtNYW5hZ2VyO1xyXG5cclxuICAgIC8vIERlZmF1bHQgYXV0aG9yaXR5IG9iamVjdFxyXG4gICAgcHVibGljIGF1dGhvcml0eTogQXV0aG9yaXR5O1xyXG5cclxuICAgIHByb3RlY3RlZCBjb25zdHJ1Y3Rvcihjb25maWd1cmF0aW9uOiBDbGllbnRDb25maWd1cmF0aW9uKSB7XHJcbiAgICAgICAgLy8gU2V0IHRoZSBjb25maWd1cmF0aW9uXHJcbiAgICAgICAgdGhpcy5jb25maWcgPSBidWlsZENsaWVudENvbmZpZ3VyYXRpb24oY29uZmlndXJhdGlvbik7XHJcblxyXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIGxvZ2dlclxyXG4gICAgICAgIHRoaXMubG9nZ2VyID0gbmV3IExvZ2dlcih0aGlzLmNvbmZpZy5sb2dnZXJPcHRpb25zLCBuYW1lLCB2ZXJzaW9uKTtcclxuXHJcbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBjcnlwdG9cclxuICAgICAgICB0aGlzLmNyeXB0b1V0aWxzID0gdGhpcy5jb25maWcuY3J5cHRvSW50ZXJmYWNlO1xyXG5cclxuICAgICAgICAvLyBJbml0aWFsaXplIHN0b3JhZ2UgaW50ZXJmYWNlXHJcbiAgICAgICAgdGhpcy5jYWNoZU1hbmFnZXIgPSB0aGlzLmNvbmZpZy5zdG9yYWdlSW50ZXJmYWNlO1xyXG5cclxuICAgICAgICAvLyBTZXQgdGhlIG5ldHdvcmsgaW50ZXJmYWNlXHJcbiAgICAgICAgdGhpcy5uZXR3b3JrQ2xpZW50ID0gdGhpcy5jb25maWcubmV0d29ya0ludGVyZmFjZTtcclxuXHJcbiAgICAgICAgLy8gU2V0IHRoZSBOZXR3b3JrTWFuYWdlclxyXG4gICAgICAgIHRoaXMubmV0d29ya01hbmFnZXIgPSBuZXcgTmV0d29ya01hbmFnZXIodGhpcy5uZXR3b3JrQ2xpZW50LCB0aGlzLmNhY2hlTWFuYWdlcik7XHJcblxyXG4gICAgICAgIC8vIFNldCBUZWxlbWV0cnlNYW5hZ2VyXHJcbiAgICAgICAgdGhpcy5zZXJ2ZXJUZWxlbWV0cnlNYW5hZ2VyID0gdGhpcy5jb25maWcuc2VydmVyVGVsZW1ldHJ5TWFuYWdlcjtcclxuXHJcbiAgICAgICAgLy8gc2V0IEF1dGhvcml0eVxyXG4gICAgICAgIHRoaXMuYXV0aG9yaXR5ID0gdGhpcy5jb25maWcuYXV0aE9wdGlvbnMuYXV0aG9yaXR5O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlcyBkZWZhdWx0IGhlYWRlcnMgZm9yIHJlcXVlc3RzIHRvIHRva2VuIGVuZHBvaW50XHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBjcmVhdGVEZWZhdWx0VG9rZW5SZXF1ZXN0SGVhZGVycygpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcclxuICAgICAgICBjb25zdCBoZWFkZXJzID0gdGhpcy5jcmVhdGVEZWZhdWx0TGlicmFyeUhlYWRlcnMoKTtcclxuICAgICAgICBoZWFkZXJzW0hlYWRlck5hbWVzLkNPTlRFTlRfVFlQRV0gPSBDb25zdGFudHMuVVJMX0ZPUk1fQ09OVEVOVF9UWVBFO1xyXG4gICAgICAgIGhlYWRlcnNbSGVhZGVyTmFtZXMuWF9NU19MSUJfQ0FQQUJJTElUWV0gPSBIZWFkZXJOYW1lcy5YX01TX0xJQl9DQVBBQklMSVRZX1ZBTFVFO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5zZXJ2ZXJUZWxlbWV0cnlNYW5hZ2VyKSB7XHJcbiAgICAgICAgICAgIGhlYWRlcnNbSGVhZGVyTmFtZXMuWF9DTElFTlRfQ1VSUl9URUxFTV0gPSB0aGlzLnNlcnZlclRlbGVtZXRyeU1hbmFnZXIuZ2VuZXJhdGVDdXJyZW50UmVxdWVzdEhlYWRlclZhbHVlKCk7XHJcbiAgICAgICAgICAgIGhlYWRlcnNbSGVhZGVyTmFtZXMuWF9DTElFTlRfTEFTVF9URUxFTV0gPSB0aGlzLnNlcnZlclRlbGVtZXRyeU1hbmFnZXIuZ2VuZXJhdGVMYXN0UmVxdWVzdEhlYWRlclZhbHVlKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gaGVhZGVycztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGFkZExpYnJhcnlEYXRhXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBjcmVhdGVEZWZhdWx0TGlicmFyeUhlYWRlcnMoKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XHJcbiAgICAgICAgY29uc3QgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xyXG5cclxuICAgICAgICAvLyBjbGllbnQgaW5mbyBoZWFkZXJzXHJcbiAgICAgICAgaGVhZGVyc1tBQURTZXJ2ZXJQYXJhbUtleXMuWF9DTElFTlRfU0tVXSA9IHRoaXMuY29uZmlnLmxpYnJhcnlJbmZvLnNrdTtcclxuICAgICAgICBoZWFkZXJzW0FBRFNlcnZlclBhcmFtS2V5cy5YX0NMSUVOVF9WRVJdID0gdGhpcy5jb25maWcubGlicmFyeUluZm8udmVyc2lvbjtcclxuICAgICAgICBoZWFkZXJzW0FBRFNlcnZlclBhcmFtS2V5cy5YX0NMSUVOVF9PU10gPSB0aGlzLmNvbmZpZy5saWJyYXJ5SW5mby5vcztcclxuICAgICAgICBoZWFkZXJzW0FBRFNlcnZlclBhcmFtS2V5cy5YX0NMSUVOVF9DUFVdID0gdGhpcy5jb25maWcubGlicmFyeUluZm8uY3B1O1xyXG5cclxuICAgICAgICByZXR1cm4gaGVhZGVycztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEh0dHAgcG9zdCB0byB0b2tlbiBlbmRwb2ludFxyXG4gICAgICogQHBhcmFtIHRva2VuRW5kcG9pbnRcclxuICAgICAqIEBwYXJhbSBxdWVyeVN0cmluZ1xyXG4gICAgICogQHBhcmFtIGhlYWRlcnNcclxuICAgICAqIEBwYXJhbSB0aHVtYnByaW50XHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBhc3luYyBleGVjdXRlUG9zdFRvVG9rZW5FbmRwb2ludCh0b2tlbkVuZHBvaW50OiBzdHJpbmcsIHF1ZXJ5U3RyaW5nOiBzdHJpbmcsIGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sIHRodW1icHJpbnQ6IFJlcXVlc3RUaHVtYnByaW50KTogUHJvbWlzZTxOZXR3b3JrUmVzcG9uc2U8U2VydmVyQXV0aG9yaXphdGlvblRva2VuUmVzcG9uc2U+PiB7XHJcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLm5ldHdvcmtNYW5hZ2VyLnNlbmRQb3N0UmVxdWVzdDxTZXJ2ZXJBdXRob3JpemF0aW9uVG9rZW5SZXNwb25zZT4oXHJcbiAgICAgICAgICAgIHRodW1icHJpbnQsXHJcbiAgICAgICAgICAgIHRva2VuRW5kcG9pbnQsXHJcbiAgICAgICAgICAgIHsgYm9keTogcXVlcnlTdHJpbmcsIGhlYWRlcnM6IGhlYWRlcnMgfVxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmNvbmZpZy5zZXJ2ZXJUZWxlbWV0cnlNYW5hZ2VyICYmIHJlc3BvbnNlLnN0YXR1cyA8IDUwMCAmJiByZXNwb25zZS5zdGF0dXMgIT09IDQyOSkge1xyXG4gICAgICAgICAgICAvLyBUZWxlbWV0cnkgZGF0YSBzdWNjZXNzZnVsbHkgbG9nZ2VkIGJ5IHNlcnZlciwgY2xlYXIgVGVsZW1ldHJ5IGNhY2hlXHJcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLnNlcnZlclRlbGVtZXRyeU1hbmFnZXIuY2xlYXJUZWxlbWV0cnlDYWNoZSgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVXBkYXRlcyB0aGUgYXV0aG9yaXR5IG9iamVjdCBvZiB0aGUgY2xpZW50LiBFbmRwb2ludCBkaXNjb3ZlcnkgbXVzdCBiZSBjb21wbGV0ZWQuXHJcbiAgICAgKiBAcGFyYW0gdXBkYXRlZEF1dGhvcml0eSBcclxuICAgICAqL1xyXG4gICAgdXBkYXRlQXV0aG9yaXR5KHVwZGF0ZWRBdXRob3JpdHk6IEF1dGhvcml0eSk6IHZvaWQge1xyXG4gICAgICAgIGlmICghdXBkYXRlZEF1dGhvcml0eS5kaXNjb3ZlcnlDb21wbGV0ZSgpKSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVFbmRwb2ludERpc2NvdmVyeUluY29tcGxldGVFcnJvcihcIlVwZGF0ZWQgYXV0aG9yaXR5IGhhcyBub3QgY29tcGxldGVkIGVuZHBvaW50IGRpc2NvdmVyeS5cIik7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuYXV0aG9yaXR5ID0gdXBkYXRlZEF1dGhvcml0eTtcclxuICAgIH1cclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IFN0cmluZ1V0aWxzIH0gZnJvbSBcIi4uL3V0aWxzL1N0cmluZ1V0aWxzXCI7XHJcbmltcG9ydCB7IENsaWVudENvbmZpZ3VyYXRpb25FcnJvciB9IGZyb20gXCIuLi9lcnJvci9DbGllbnRDb25maWd1cmF0aW9uRXJyb3JcIjtcclxuaW1wb3J0IHsgUHJvbXB0VmFsdWUsIENvZGVDaGFsbGVuZ2VNZXRob2RWYWx1ZXN9IGZyb20gXCIuLi91dGlscy9Db25zdGFudHNcIjtcclxuaW1wb3J0IHsgU3RyaW5nRGljdCB9IGZyb20gXCIuLi91dGlscy9Nc2FsVHlwZXNcIjtcclxuXHJcbi8qKlxyXG4gKiBWYWxpZGF0ZXMgc2VydmVyIGNvbnN1bWFibGUgcGFyYW1zIGZyb20gdGhlIFwicmVxdWVzdFwiIG9iamVjdHNcclxuICovXHJcbmV4cG9ydCBjbGFzcyBSZXF1ZXN0VmFsaWRhdG9yIHtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFV0aWxpdHkgdG8gY2hlY2sgaWYgdGhlIGByZWRpcmVjdFVyaWAgaW4gdGhlIHJlcXVlc3QgaXMgYSBub24tbnVsbCB2YWx1ZVxyXG4gICAgICogQHBhcmFtIHJlZGlyZWN0VXJpXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyB2YWxpZGF0ZVJlZGlyZWN0VXJpKHJlZGlyZWN0VXJpOiBzdHJpbmcpIDogdm9pZCB7XHJcbiAgICAgICAgaWYgKFN0cmluZ1V0aWxzLmlzRW1wdHkocmVkaXJlY3RVcmkpKSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudENvbmZpZ3VyYXRpb25FcnJvci5jcmVhdGVSZWRpcmVjdFVyaUVtcHR5RXJyb3IoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBVdGlsaXR5IHRvIHZhbGlkYXRlIHByb21wdCBzZW50IGJ5IHRoZSB1c2VyIGluIHRoZSByZXF1ZXN0XHJcbiAgICAgKiBAcGFyYW0gcHJvbXB0XHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyB2YWxpZGF0ZVByb21wdChwcm9tcHQ6IHN0cmluZykgOiB2b2lkIHtcclxuICAgICAgICBpZiAoXHJcbiAgICAgICAgICAgIFtcclxuICAgICAgICAgICAgICAgIFByb21wdFZhbHVlLkxPR0lOLFxyXG4gICAgICAgICAgICAgICAgUHJvbXB0VmFsdWUuU0VMRUNUX0FDQ09VTlQsXHJcbiAgICAgICAgICAgICAgICBQcm9tcHRWYWx1ZS5DT05TRU5ULFxyXG4gICAgICAgICAgICAgICAgUHJvbXB0VmFsdWUuTk9ORVxyXG4gICAgICAgICAgICBdLmluZGV4T2YocHJvbXB0KSA8IDBcclxuICAgICAgICApIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yLmNyZWF0ZUludmFsaWRQcm9tcHRFcnJvcihwcm9tcHQpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBzdGF0aWMgdmFsaWRhdGVDbGFpbXMoY2xhaW1zOiBzdHJpbmcpIDogdm9pZCB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgSlNPTi5wYXJzZShjbGFpbXMpO1xyXG4gICAgICAgIH0gY2F0Y2goZSkge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRDb25maWd1cmF0aW9uRXJyb3IuY3JlYXRlSW52YWxpZENsYWltc1JlcXVlc3RFcnJvcigpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFV0aWxpdHkgdG8gdmFsaWRhdGUgY29kZV9jaGFsbGVuZ2UgYW5kIGNvZGVfY2hhbGxlbmdlX21ldGhvZFxyXG4gICAgICogQHBhcmFtIGNvZGVDaGFsbGVuZ2VcclxuICAgICAqIEBwYXJhbSBjb2RlQ2hhbGxlbmdlTWV0aG9kXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyB2YWxpZGF0ZUNvZGVDaGFsbGVuZ2VQYXJhbXMoY29kZUNoYWxsZW5nZTogc3RyaW5nLCBjb2RlQ2hhbGxlbmdlTWV0aG9kOiBzdHJpbmcpIDogdm9pZCAge1xyXG4gICAgICAgIGlmIChTdHJpbmdVdGlscy5pc0VtcHR5KGNvZGVDaGFsbGVuZ2UpIHx8IFN0cmluZ1V0aWxzLmlzRW1wdHkoY29kZUNoYWxsZW5nZU1ldGhvZCkpIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yLmNyZWF0ZUludmFsaWRDb2RlQ2hhbGxlbmdlUGFyYW1zRXJyb3IoKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLnZhbGlkYXRlQ29kZUNoYWxsZW5nZU1ldGhvZChjb2RlQ2hhbGxlbmdlTWV0aG9kKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBVdGlsaXR5IHRvIHZhbGlkYXRlIGNvZGVfY2hhbGxlbmdlX21ldGhvZFxyXG4gICAgICogQHBhcmFtIGNvZGVDaGFsbGVuZ2VNZXRob2RcclxuICAgICAqL1xyXG4gICAgc3RhdGljIHZhbGlkYXRlQ29kZUNoYWxsZW5nZU1ldGhvZChjb2RlQ2hhbGxlbmdlTWV0aG9kOiBzdHJpbmcpIDogdm9pZCB7XHJcbiAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICBbXHJcbiAgICAgICAgICAgICAgICBDb2RlQ2hhbGxlbmdlTWV0aG9kVmFsdWVzLlBMQUlOLFxyXG4gICAgICAgICAgICAgICAgQ29kZUNoYWxsZW5nZU1ldGhvZFZhbHVlcy5TMjU2XHJcbiAgICAgICAgICAgIF0uaW5kZXhPZihjb2RlQ2hhbGxlbmdlTWV0aG9kKSA8IDBcclxuICAgICAgICApIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yLmNyZWF0ZUludmFsaWRDb2RlQ2hhbGxlbmdlTWV0aG9kRXJyb3IoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZW1vdmVzIHVubmVjZXNzYXJ5IG9yIGR1cGxpY2F0ZSBxdWVyeSBwYXJhbWV0ZXJzIGZyb20gZXh0cmFRdWVyeVBhcmFtZXRlcnNcclxuICAgICAqIEBwYXJhbSByZXF1ZXN0XHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBzYW5pdGl6ZUVRUGFyYW1zKGVRUGFyYW1zOiBTdHJpbmdEaWN0LCBxdWVyeVBhcmFtczogTWFwPHN0cmluZywgc3RyaW5nPikgOiBTdHJpbmdEaWN0IHtcclxuICAgICAgICBpZiAoIWVRUGFyYW1zKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB7fTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFJlbW92ZSBhbnkgcXVlcnkgcGFyYW1ldGVycyBhbHJlYWR5IGluY2x1ZGVkIGluIFNTTyBwYXJhbXNcclxuICAgICAgICBxdWVyeVBhcmFtcy5mb3JFYWNoKCh2YWx1ZSwga2V5KSA9PiB7XHJcbiAgICAgICAgICAgIGlmIChlUVBhcmFtc1trZXldKSB7XHJcbiAgICAgICAgICAgICAgICBkZWxldGUgZVFQYXJhbXNba2V5XTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICByZXR1cm4gZVFQYXJhbXM7XHJcbiAgICB9XHJcbn1cclxuIiwiLypcclxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cclxuICovXHJcblxyXG5pbXBvcnQgeyBBQURTZXJ2ZXJQYXJhbUtleXMsIENvbnN0YW50cywgUmVzcG9uc2VNb2RlLCBTU09UeXBlcywgQ2xpZW50SW5mbywgQXV0aGVudGljYXRpb25TY2hlbWUsIENsYWltc1JlcXVlc3RLZXlzLCBQYXNzd29yZEdyYW50Q29uc3RhbnRzLCBPSURDX0RFRkFVTFRfU0NPUEVTfSBmcm9tIFwiLi4vdXRpbHMvQ29uc3RhbnRzXCI7XHJcbmltcG9ydCB7IFNjb3BlU2V0IH0gZnJvbSBcIi4vU2NvcGVTZXRcIjtcclxuaW1wb3J0IHsgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL0NsaWVudENvbmZpZ3VyYXRpb25FcnJvclwiO1xyXG5pbXBvcnQgeyBTdHJpbmdEaWN0IH0gZnJvbSBcIi4uL3V0aWxzL01zYWxUeXBlc1wiO1xyXG5pbXBvcnQgeyBSZXF1ZXN0VmFsaWRhdG9yIH0gZnJvbSBcIi4vUmVxdWVzdFZhbGlkYXRvclwiO1xyXG5pbXBvcnQgeyBMaWJyYXJ5SW5mbyB9IGZyb20gXCIuLi9jb25maWcvQ2xpZW50Q29uZmlndXJhdGlvblwiO1xyXG5pbXBvcnQgeyBTdHJpbmdVdGlscyB9IGZyb20gXCIuLi91dGlscy9TdHJpbmdVdGlsc1wiO1xyXG5cclxuZXhwb3J0IGNsYXNzIFJlcXVlc3RQYXJhbWV0ZXJCdWlsZGVyIHtcclxuXHJcbiAgICBwcml2YXRlIHBhcmFtZXRlcnM6IE1hcDxzdHJpbmcsIHN0cmluZz47XHJcblxyXG4gICAgY29uc3RydWN0b3IoKSB7XHJcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGFkZCByZXNwb25zZV90eXBlID0gY29kZVxyXG4gICAgICovXHJcbiAgICBhZGRSZXNwb25zZVR5cGVDb2RlKCk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5zZXQoXHJcbiAgICAgICAgICAgIEFBRFNlcnZlclBhcmFtS2V5cy5SRVNQT05TRV9UWVBFLCBlbmNvZGVVUklDb21wb25lbnQoQ29uc3RhbnRzLkNPREVfUkVTUE9OU0VfVFlQRSlcclxuICAgICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogYWRkIHJlc3BvbnNlX21vZGUuIGRlZmF1bHRzIHRvIHF1ZXJ5LlxyXG4gICAgICogQHBhcmFtIHJlc3BvbnNlTW9kZVxyXG4gICAgICovXHJcbiAgICBhZGRSZXNwb25zZU1vZGUocmVzcG9uc2VNb2RlPzogUmVzcG9uc2VNb2RlKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNldChcclxuICAgICAgICAgICAgQUFEU2VydmVyUGFyYW1LZXlzLlJFU1BPTlNFX01PREUsXHJcbiAgICAgICAgICAgIGVuY29kZVVSSUNvbXBvbmVudCgocmVzcG9uc2VNb2RlKSA/IHJlc3BvbnNlTW9kZSA6IFJlc3BvbnNlTW9kZS5RVUVSWSlcclxuICAgICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogYWRkIHNjb3Blcy4gc2V0IGFkZE9pZGNTY29wZXMgdG8gZmFsc2UgdG8gcHJldmVudCBkZWZhdWx0IHNjb3BlcyBpbiBub24tdXNlciBzY2VuYXJpb3NcclxuICAgICAqIEBwYXJhbSBzY29wZVNldFxyXG4gICAgICogQHBhcmFtIGFkZE9pZGNTY29wZXNcclxuICAgICAqL1xyXG4gICAgYWRkU2NvcGVzKHNjb3Blczogc3RyaW5nW10sIGFkZE9pZGNTY29wZXM6IGJvb2xlYW4gPSB0cnVlKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3QgcmVxdWVzdFNjb3BlcyA9IGFkZE9pZGNTY29wZXMgPyBbLi4uc2NvcGVzIHx8IFtdLCAuLi5PSURDX0RFRkFVTFRfU0NPUEVTXSA6IHNjb3BlcyB8fCBbXTtcclxuICAgICAgICBjb25zdCBzY29wZVNldCA9IG5ldyBTY29wZVNldChyZXF1ZXN0U2NvcGVzKTtcclxuICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2V0KEFBRFNlcnZlclBhcmFtS2V5cy5TQ09QRSwgZW5jb2RlVVJJQ29tcG9uZW50KHNjb3BlU2V0LnByaW50U2NvcGVzKCkpKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGFkZCBjbGllbnRJZFxyXG4gICAgICogQHBhcmFtIGNsaWVudElkXHJcbiAgICAgKi9cclxuICAgIGFkZENsaWVudElkKGNsaWVudElkOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2V0KEFBRFNlcnZlclBhcmFtS2V5cy5DTElFTlRfSUQsIGVuY29kZVVSSUNvbXBvbmVudChjbGllbnRJZCkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogYWRkIHJlZGlyZWN0X3VyaVxyXG4gICAgICogQHBhcmFtIHJlZGlyZWN0VXJpXHJcbiAgICAgKi9cclxuICAgIGFkZFJlZGlyZWN0VXJpKHJlZGlyZWN0VXJpOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICBSZXF1ZXN0VmFsaWRhdG9yLnZhbGlkYXRlUmVkaXJlY3RVcmkocmVkaXJlY3RVcmkpO1xyXG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5zZXQoQUFEU2VydmVyUGFyYW1LZXlzLlJFRElSRUNUX1VSSSwgZW5jb2RlVVJJQ29tcG9uZW50KHJlZGlyZWN0VXJpKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBhZGQgcG9zdCBsb2dvdXQgcmVkaXJlY3RVcmlcclxuICAgICAqIEBwYXJhbSByZWRpcmVjdFVyaVxyXG4gICAgICovXHJcbiAgICBhZGRQb3N0TG9nb3V0UmVkaXJlY3RVcmkocmVkaXJlY3RVcmk6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgICAgIFJlcXVlc3RWYWxpZGF0b3IudmFsaWRhdGVSZWRpcmVjdFVyaShyZWRpcmVjdFVyaSk7XHJcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNldChBQURTZXJ2ZXJQYXJhbUtleXMuUE9TVF9MT0dPVVRfVVJJLCBlbmNvZGVVUklDb21wb25lbnQocmVkaXJlY3RVcmkpKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGFkZCBpZF90b2tlbl9oaW50IHRvIGxvZ291dCByZXF1ZXN0XHJcbiAgICAgKiBAcGFyYW0gaWRUb2tlbkhpbnRcclxuICAgICAqL1xyXG4gICAgYWRkSWRUb2tlbkhpbnQoaWRUb2tlbkhpbnQ6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5zZXQoQUFEU2VydmVyUGFyYW1LZXlzLklEX1RPS0VOX0hJTlQsIGVuY29kZVVSSUNvbXBvbmVudChpZFRva2VuSGludCkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogYWRkIGRvbWFpbl9oaW50XHJcbiAgICAgKiBAcGFyYW0gZG9tYWluSGludFxyXG4gICAgICovXHJcbiAgICBhZGREb21haW5IaW50KGRvbWFpbkhpbnQ6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5zZXQoU1NPVHlwZXMuRE9NQUlOX0hJTlQsIGVuY29kZVVSSUNvbXBvbmVudChkb21haW5IaW50KSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBhZGQgbG9naW5faGludFxyXG4gICAgICogQHBhcmFtIGxvZ2luSGludFxyXG4gICAgICovXHJcbiAgICBhZGRMb2dpbkhpbnQobG9naW5IaW50OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2V0KFNTT1R5cGVzLkxPR0lOX0hJTlQsIGVuY29kZVVSSUNvbXBvbmVudChsb2dpbkhpbnQpKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGFkZCBzaWRcclxuICAgICAqIEBwYXJhbSBzaWRcclxuICAgICAqL1xyXG4gICAgYWRkU2lkKHNpZDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNldChTU09UeXBlcy5TSUQsIGVuY29kZVVSSUNvbXBvbmVudChzaWQpKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGFkZCBjbGFpbXNcclxuICAgICAqIEBwYXJhbSBjbGFpbXNcclxuICAgICAqL1xyXG4gICAgYWRkQ2xhaW1zKGNsYWltcz86IHN0cmluZywgY2xpZW50Q2FwYWJpbGl0aWVzPzogQXJyYXk8c3RyaW5nPik6IHZvaWQge1xyXG4gICAgICAgIGNvbnN0IG1lcmdlZENsYWltcyA9IHRoaXMuYWRkQ2xpZW50Q2FwYWJpbGl0aWVzVG9DbGFpbXMoY2xhaW1zLCBjbGllbnRDYXBhYmlsaXRpZXMpO1xyXG4gICAgICAgIFJlcXVlc3RWYWxpZGF0b3IudmFsaWRhdGVDbGFpbXMobWVyZ2VkQ2xhaW1zKTtcclxuICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2V0KEFBRFNlcnZlclBhcmFtS2V5cy5DTEFJTVMsIGVuY29kZVVSSUNvbXBvbmVudChtZXJnZWRDbGFpbXMpKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGFkZCBjb3JyZWxhdGlvbklkXHJcbiAgICAgKiBAcGFyYW0gY29ycmVsYXRpb25JZFxyXG4gICAgICovXHJcbiAgICBhZGRDb3JyZWxhdGlvbklkKGNvcnJlbGF0aW9uSWQ6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5zZXQoQUFEU2VydmVyUGFyYW1LZXlzLkNMSUVOVF9SRVFVRVNUX0lELCBlbmNvZGVVUklDb21wb25lbnQoY29ycmVsYXRpb25JZCkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogYWRkIGxpYnJhcnkgaW5mbyBxdWVyeSBwYXJhbXNcclxuICAgICAqIEBwYXJhbSBsaWJyYXJ5SW5mb1xyXG4gICAgICovXHJcbiAgICBhZGRMaWJyYXJ5SW5mbyhsaWJyYXJ5SW5mbzogTGlicmFyeUluZm8pOiB2b2lkIHtcclxuICAgICAgICAvLyBUZWxlbWV0cnkgSW5mb1xyXG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5zZXQoQUFEU2VydmVyUGFyYW1LZXlzLlhfQ0xJRU5UX1NLVSwgbGlicmFyeUluZm8uc2t1KTtcclxuICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2V0KEFBRFNlcnZlclBhcmFtS2V5cy5YX0NMSUVOVF9WRVIsIGxpYnJhcnlJbmZvLnZlcnNpb24pO1xyXG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5zZXQoQUFEU2VydmVyUGFyYW1LZXlzLlhfQ0xJRU5UX09TLCBsaWJyYXJ5SW5mby5vcyk7XHJcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNldChBQURTZXJ2ZXJQYXJhbUtleXMuWF9DTElFTlRfQ1BVLCBsaWJyYXJ5SW5mby5jcHUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogYWRkIHByb21wdFxyXG4gICAgICogQHBhcmFtIHByb21wdFxyXG4gICAgICovXHJcbiAgICBhZGRQcm9tcHQocHJvbXB0OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICBSZXF1ZXN0VmFsaWRhdG9yLnZhbGlkYXRlUHJvbXB0KHByb21wdCk7XHJcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNldChgJHtBQURTZXJ2ZXJQYXJhbUtleXMuUFJPTVBUfWAsIGVuY29kZVVSSUNvbXBvbmVudChwcm9tcHQpKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGFkZCBzdGF0ZVxyXG4gICAgICogQHBhcmFtIHN0YXRlXHJcbiAgICAgKi9cclxuICAgIGFkZFN0YXRlKHN0YXRlOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICBpZiAoIVN0cmluZ1V0aWxzLmlzRW1wdHkoc3RhdGUpKSB7XHJcbiAgICAgICAgICAgIHRoaXMucGFyYW1ldGVycy5zZXQoQUFEU2VydmVyUGFyYW1LZXlzLlNUQVRFLCBlbmNvZGVVUklDb21wb25lbnQoc3RhdGUpKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBhZGQgbm9uY2VcclxuICAgICAqIEBwYXJhbSBub25jZVxyXG4gICAgICovXHJcbiAgICBhZGROb25jZShub25jZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNldChBQURTZXJ2ZXJQYXJhbUtleXMuTk9OQ0UsIGVuY29kZVVSSUNvbXBvbmVudChub25jZSkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogYWRkIGNvZGVfY2hhbGxlbmdlIGFuZCBjb2RlX2NoYWxsZW5nZV9tZXRob2RcclxuICAgICAqIC0gdGhyb3cgaWYgZWl0aGVyIG9mIHRoZW0gYXJlIG5vdCBwYXNzZWRcclxuICAgICAqIEBwYXJhbSBjb2RlQ2hhbGxlbmdlXHJcbiAgICAgKiBAcGFyYW0gY29kZUNoYWxsZW5nZU1ldGhvZFxyXG4gICAgICovXHJcbiAgICBhZGRDb2RlQ2hhbGxlbmdlUGFyYW1zKFxyXG4gICAgICAgIGNvZGVDaGFsbGVuZ2U6IHN0cmluZyxcclxuICAgICAgICBjb2RlQ2hhbGxlbmdlTWV0aG9kOiBzdHJpbmdcclxuICAgICk6IHZvaWQge1xyXG4gICAgICAgIFJlcXVlc3RWYWxpZGF0b3IudmFsaWRhdGVDb2RlQ2hhbGxlbmdlUGFyYW1zKGNvZGVDaGFsbGVuZ2UsIGNvZGVDaGFsbGVuZ2VNZXRob2QpO1xyXG4gICAgICAgIGlmIChjb2RlQ2hhbGxlbmdlICYmIGNvZGVDaGFsbGVuZ2VNZXRob2QpIHtcclxuICAgICAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNldChBQURTZXJ2ZXJQYXJhbUtleXMuQ09ERV9DSEFMTEVOR0UsIGVuY29kZVVSSUNvbXBvbmVudChjb2RlQ2hhbGxlbmdlKSk7XHJcbiAgICAgICAgICAgIHRoaXMucGFyYW1ldGVycy5zZXQoQUFEU2VydmVyUGFyYW1LZXlzLkNPREVfQ0hBTExFTkdFX01FVEhPRCwgZW5jb2RlVVJJQ29tcG9uZW50KGNvZGVDaGFsbGVuZ2VNZXRob2QpKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRDb25maWd1cmF0aW9uRXJyb3IuY3JlYXRlSW52YWxpZENvZGVDaGFsbGVuZ2VQYXJhbXNFcnJvcigpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGFkZCB0aGUgYGF1dGhvcml6YXRpb25fY29kZWAgcGFzc2VkIGJ5IHRoZSB1c2VyIHRvIGV4Y2hhbmdlIGZvciBhIHRva2VuXHJcbiAgICAgKiBAcGFyYW0gY29kZVxyXG4gICAgICovXHJcbiAgICBhZGRBdXRob3JpemF0aW9uQ29kZShjb2RlOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2V0KEFBRFNlcnZlclBhcmFtS2V5cy5DT0RFLCBlbmNvZGVVUklDb21wb25lbnQoY29kZSkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogYWRkIHRoZSBgYXV0aG9yaXphdGlvbl9jb2RlYCBwYXNzZWQgYnkgdGhlIHVzZXIgdG8gZXhjaGFuZ2UgZm9yIGEgdG9rZW5cclxuICAgICAqIEBwYXJhbSBjb2RlXHJcbiAgICAgKi9cclxuICAgIGFkZERldmljZUNvZGUoY29kZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNldChBQURTZXJ2ZXJQYXJhbUtleXMuREVWSUNFX0NPREUsIGVuY29kZVVSSUNvbXBvbmVudChjb2RlKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBhZGQgdGhlIGByZWZyZXNoVG9rZW5gIHBhc3NlZCBieSB0aGUgdXNlclxyXG4gICAgICogQHBhcmFtIHJlZnJlc2hUb2tlblxyXG4gICAgICovXHJcbiAgICBhZGRSZWZyZXNoVG9rZW4ocmVmcmVzaFRva2VuOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2V0KEFBRFNlcnZlclBhcmFtS2V5cy5SRUZSRVNIX1RPS0VOLCBlbmNvZGVVUklDb21wb25lbnQocmVmcmVzaFRva2VuKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBhZGQgdGhlIGBjb2RlX3ZlcmlmaWVyYCBwYXNzZWQgYnkgdGhlIHVzZXIgdG8gZXhjaGFuZ2UgZm9yIGEgdG9rZW5cclxuICAgICAqIEBwYXJhbSBjb2RlVmVyaWZpZXJcclxuICAgICAqL1xyXG4gICAgYWRkQ29kZVZlcmlmaWVyKGNvZGVWZXJpZmllcjogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNldChBQURTZXJ2ZXJQYXJhbUtleXMuQ09ERV9WRVJJRklFUiwgZW5jb2RlVVJJQ29tcG9uZW50KGNvZGVWZXJpZmllcikpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogYWRkIGNsaWVudF9zZWNyZXRcclxuICAgICAqIEBwYXJhbSBjbGllbnRTZWNyZXRcclxuICAgICAqL1xyXG4gICAgYWRkQ2xpZW50U2VjcmV0KGNsaWVudFNlY3JldDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNldChBQURTZXJ2ZXJQYXJhbUtleXMuQ0xJRU5UX1NFQ1JFVCwgZW5jb2RlVVJJQ29tcG9uZW50KGNsaWVudFNlY3JldCkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogYWRkIGNsaWVudEFzc2VydGlvbiBmb3IgY29uZmlkZW50aWFsIGNsaWVudCBmbG93c1xyXG4gICAgICogQHBhcmFtIGNsaWVudEFzc2VydGlvblxyXG4gICAgICovXHJcbiAgICBhZGRDbGllbnRBc3NlcnRpb24oY2xpZW50QXNzZXJ0aW9uOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2V0KEFBRFNlcnZlclBhcmFtS2V5cy5DTElFTlRfQVNTRVJUSU9OLCBlbmNvZGVVUklDb21wb25lbnQoY2xpZW50QXNzZXJ0aW9uKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBhZGQgY2xpZW50QXNzZXJ0aW9uVHlwZSBmb3IgY29uZmlkZW50aWFsIGNsaWVudCBmbG93c1xyXG4gICAgICogQHBhcmFtIGNsaWVudEFzc2VydGlvblR5cGVcclxuICAgICAqL1xyXG4gICAgYWRkQ2xpZW50QXNzZXJ0aW9uVHlwZShjbGllbnRBc3NlcnRpb25UeXBlOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2V0KEFBRFNlcnZlclBhcmFtS2V5cy5DTElFTlRfQVNTRVJUSU9OX1RZUEUsIGVuY29kZVVSSUNvbXBvbmVudChjbGllbnRBc3NlcnRpb25UeXBlKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBhZGQgT0JPIGFzc2VydGlvbiBmb3IgY29uZmlkZW50aWFsIGNsaWVudCBmbG93c1xyXG4gICAgICogQHBhcmFtIGNsaWVudEFzc2VydGlvblxyXG4gICAgICovXHJcbiAgICBhZGRPYm9Bc3NlcnRpb24ob2JvQXNzZXJ0aW9uOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2V0KEFBRFNlcnZlclBhcmFtS2V5cy5PQk9fQVNTRVJUSU9OLCBlbmNvZGVVUklDb21wb25lbnQob2JvQXNzZXJ0aW9uKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBhZGQgZ3JhbnQgdHlwZVxyXG4gICAgICogQHBhcmFtIGdyYW50VHlwZVxyXG4gICAgICovXHJcbiAgICBhZGRSZXF1ZXN0VG9rZW5Vc2UodG9rZW5Vc2U6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5zZXQoQUFEU2VydmVyUGFyYW1LZXlzLlJFUVVFU1RFRF9UT0tFTl9VU0UsIGVuY29kZVVSSUNvbXBvbmVudCh0b2tlblVzZSkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogYWRkIGdyYW50IHR5cGVcclxuICAgICAqIEBwYXJhbSBncmFudFR5cGVcclxuICAgICAqL1xyXG4gICAgYWRkR3JhbnRUeXBlKGdyYW50VHlwZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5wYXJhbWV0ZXJzLnNldChBQURTZXJ2ZXJQYXJhbUtleXMuR1JBTlRfVFlQRSwgZW5jb2RlVVJJQ29tcG9uZW50KGdyYW50VHlwZSkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogYWRkIGNsaWVudCBpbmZvXHJcbiAgICAgKlxyXG4gICAgICovXHJcbiAgICBhZGRDbGllbnRJbmZvKCk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5zZXQoQ2xpZW50SW5mbywgXCIxXCIpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogYWRkIGV4dHJhUXVlcnlQYXJhbXNcclxuICAgICAqIEBwYXJhbSBlUXBhcmFtc1xyXG4gICAgICovXHJcbiAgICBhZGRFeHRyYVF1ZXJ5UGFyYW1ldGVycyhlUXBhcmFtczogU3RyaW5nRGljdCk6IHZvaWQge1xyXG4gICAgICAgIFJlcXVlc3RWYWxpZGF0b3Iuc2FuaXRpemVFUVBhcmFtcyhlUXBhcmFtcywgdGhpcy5wYXJhbWV0ZXJzKTtcclxuICAgICAgICBPYmplY3Qua2V5cyhlUXBhcmFtcykuZm9yRWFjaCgoa2V5KSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMucGFyYW1ldGVycy5zZXQoa2V5LCBlUXBhcmFtc1trZXldKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBhZGRDbGllbnRDYXBhYmlsaXRpZXNUb0NsYWltcyhjbGFpbXM/OiBzdHJpbmcsIGNsaWVudENhcGFiaWxpdGllcz86IEFycmF5PHN0cmluZz4pOiBzdHJpbmcge1xyXG4gICAgICAgIGxldCBtZXJnZWRDbGFpbXM6IG9iamVjdDtcclxuXHJcbiAgICAgICAgLy8gUGFyc2UgcHJvdmlkZWQgY2xhaW1zIGludG8gSlNPTiBvYmplY3Qgb3IgaW5pdGlhbGl6ZSBlbXB0eSBvYmplY3RcclxuICAgICAgICBpZiAoIWNsYWltcykge1xyXG4gICAgICAgICAgICBtZXJnZWRDbGFpbXMgPSB7fTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgbWVyZ2VkQ2xhaW1zID0gSlNPTi5wYXJzZShjbGFpbXMpO1xyXG4gICAgICAgICAgICB9IGNhdGNoKGUpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IENsaWVudENvbmZpZ3VyYXRpb25FcnJvci5jcmVhdGVJbnZhbGlkQ2xhaW1zUmVxdWVzdEVycm9yKCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChjbGllbnRDYXBhYmlsaXRpZXMgJiYgY2xpZW50Q2FwYWJpbGl0aWVzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgaWYgKCFtZXJnZWRDbGFpbXMuaGFzT3duUHJvcGVydHkoQ2xhaW1zUmVxdWVzdEtleXMuQUNDRVNTX1RPS0VOKSl7XHJcbiAgICAgICAgICAgICAgICAvLyBBZGQgYWNjZXNzX3Rva2VuIGtleSB0byBjbGFpbXMgb2JqZWN0XHJcbiAgICAgICAgICAgICAgICBtZXJnZWRDbGFpbXNbQ2xhaW1zUmVxdWVzdEtleXMuQUNDRVNTX1RPS0VOXSA9IHt9O1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBBZGQgeG1zX2NjIGNsYWltIHdpdGggcHJvdmlkZWQgY2xpZW50Q2FwYWJpbGl0aWVzIHRvIGFjY2Vzc190b2tlbiBrZXlcclxuICAgICAgICAgICAgbWVyZ2VkQ2xhaW1zW0NsYWltc1JlcXVlc3RLZXlzLkFDQ0VTU19UT0tFTl1bQ2xhaW1zUmVxdWVzdEtleXMuWE1TX0NDXSA9IHtcclxuICAgICAgICAgICAgICAgIHZhbHVlczogY2xpZW50Q2FwYWJpbGl0aWVzXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkobWVyZ2VkQ2xhaW1zKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGFkZHMgYHVzZXJuYW1lYCBmb3IgUGFzc3dvcmQgR3JhbnQgZmxvd1xyXG4gICAgICogQHBhcmFtIHVzZXJuYW1lXHJcbiAgICAgKi9cclxuICAgIGFkZFVzZXJuYW1lKHVzZXJuYW1lOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2V0KFBhc3N3b3JkR3JhbnRDb25zdGFudHMudXNlcm5hbWUsIHVzZXJuYW1lKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGFkZHMgYHBhc3N3b3JkYCBmb3IgUGFzc3dvcmQgR3JhbnQgZmxvd1xyXG4gICAgICogQHBhcmFtIHBhc3N3b3JkXHJcbiAgICAgKi9cclxuICAgIGFkZFBhc3N3b3JkKHBhc3N3b3JkOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLnBhcmFtZXRlcnMuc2V0KFBhc3N3b3JkR3JhbnRDb25zdGFudHMucGFzc3dvcmQsIHBhc3N3b3JkKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGFkZCBwb3BfandrIHRvIHF1ZXJ5IHBhcmFtc1xyXG4gICAgICogQHBhcmFtIGNuZlN0cmluZ1xyXG4gICAgICovXHJcbiAgICBhZGRQb3BUb2tlbihjbmZTdHJpbmc6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgICAgIGlmICghU3RyaW5nVXRpbHMuaXNFbXB0eShjbmZTdHJpbmcpKSB7XHJcbiAgICAgICAgICAgIHRoaXMucGFyYW1ldGVycy5zZXQoQUFEU2VydmVyUGFyYW1LZXlzLlRPS0VOX1RZUEUsIEF1dGhlbnRpY2F0aW9uU2NoZW1lLlBPUCk7XHJcbiAgICAgICAgICAgIHRoaXMucGFyYW1ldGVycy5zZXQoQUFEU2VydmVyUGFyYW1LZXlzLlJFUV9DTkYsIGVuY29kZVVSSUNvbXBvbmVudChjbmZTdHJpbmcpKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBVdGlsaXR5IHRvIGNyZWF0ZSBhIFVSTCBmcm9tIHRoZSBwYXJhbXMgbWFwXHJcbiAgICAgKi9cclxuICAgIGNyZWF0ZVF1ZXJ5U3RyaW5nKCk6IHN0cmluZyB7XHJcbiAgICAgICAgY29uc3QgcXVlcnlQYXJhbWV0ZXJBcnJheTogQXJyYXk8c3RyaW5nPiA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XHJcblxyXG4gICAgICAgIHRoaXMucGFyYW1ldGVycy5mb3JFYWNoKCh2YWx1ZSwga2V5KSA9PiB7XHJcbiAgICAgICAgICAgIHF1ZXJ5UGFyYW1ldGVyQXJyYXkucHVzaChgJHtrZXl9PSR7dmFsdWV9YCk7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHJldHVybiBxdWVyeVBhcmFtZXRlckFycmF5LmpvaW4oXCImXCIpO1xyXG4gICAgfVxyXG59XHJcbiIsIi8qXHJcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgQ3JlZGVudGlhbEVudGl0eSB9IGZyb20gXCIuL0NyZWRlbnRpYWxFbnRpdHlcIjtcclxuaW1wb3J0IHsgQ3JlZGVudGlhbFR5cGUgfSBmcm9tIFwiLi4vLi4vdXRpbHMvQ29uc3RhbnRzXCI7XHJcblxyXG4vKipcclxuICogSURfVE9LRU4gQ2FjaGVcclxuICpcclxuICogS2V5OlZhbHVlIFNjaGVtYTpcclxuICpcclxuICogS2V5IEV4YW1wbGU6IHVpZC51dGlkLWxvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20taWR0b2tlbi1jbGllbnRJZC1jb250b3NvLmNvbS1cclxuICpcclxuICogVmFsdWUgU2NoZW1hOlxyXG4gKiB7XHJcbiAqICAgICAgaG9tZUFjY291bnRJZDogaG9tZSBhY2NvdW50IGlkZW50aWZpZXIgZm9yIHRoZSBhdXRoIHNjaGVtZSxcclxuICogICAgICBlbnZpcm9ubWVudDogZW50aXR5IHRoYXQgaXNzdWVkIHRoZSB0b2tlbiwgcmVwcmVzZW50ZWQgYXMgYSBmdWxsIGhvc3RcclxuICogICAgICBjcmVkZW50aWFsVHlwZTogVHlwZSBvZiBjcmVkZW50aWFsIGFzIGEgc3RyaW5nLCBjYW4gYmUgb25lIG9mIHRoZSBmb2xsb3dpbmc6IFJlZnJlc2hUb2tlbiwgQWNjZXNzVG9rZW4sIElkVG9rZW4sIFBhc3N3b3JkLCBDb29raWUsIENlcnRpZmljYXRlLCBPdGhlclxyXG4gKiAgICAgIGNsaWVudElkOiBjbGllbnQgSUQgb2YgdGhlIGFwcGxpY2F0aW9uXHJcbiAqICAgICAgc2VjcmV0OiBBY3R1YWwgY3JlZGVudGlhbCBhcyBhIHN0cmluZ1xyXG4gKiAgICAgIHJlYWxtOiBGdWxsIHRlbmFudCBvciBvcmdhbml6YXRpb25hbCBpZGVudGlmaWVyIHRoYXQgdGhlIGFjY291bnQgYmVsb25ncyB0b1xyXG4gKiB9XHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgSWRUb2tlbkVudGl0eSBleHRlbmRzIENyZWRlbnRpYWxFbnRpdHkge1xyXG4gICAgcmVhbG06IHN0cmluZztcclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZSBJZFRva2VuRW50aXR5XHJcbiAgICAgKiBAcGFyYW0gaG9tZUFjY291bnRJZFxyXG4gICAgICogQHBhcmFtIGF1dGhlbnRpY2F0aW9uUmVzdWx0XHJcbiAgICAgKiBAcGFyYW0gY2xpZW50SWRcclxuICAgICAqIEBwYXJhbSBhdXRob3JpdHlcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZUlkVG9rZW5FbnRpdHkoXHJcbiAgICAgICAgaG9tZUFjY291bnRJZDogc3RyaW5nLFxyXG4gICAgICAgIGVudmlyb25tZW50OiBzdHJpbmcsXHJcbiAgICAgICAgaWRUb2tlbjogc3RyaW5nLFxyXG4gICAgICAgIGNsaWVudElkOiBzdHJpbmcsXHJcbiAgICAgICAgdGVuYW50SWQ6IHN0cmluZyxcclxuICAgICAgICBvYm9Bc3NlcnRpb24/OiBzdHJpbmdcclxuICAgICk6IElkVG9rZW5FbnRpdHkge1xyXG4gICAgICAgIGNvbnN0IGlkVG9rZW5FbnRpdHkgPSBuZXcgSWRUb2tlbkVudGl0eSgpO1xyXG5cclxuICAgICAgICBpZFRva2VuRW50aXR5LmNyZWRlbnRpYWxUeXBlID0gQ3JlZGVudGlhbFR5cGUuSURfVE9LRU47XHJcbiAgICAgICAgaWRUb2tlbkVudGl0eS5ob21lQWNjb3VudElkID0gaG9tZUFjY291bnRJZDtcclxuICAgICAgICBpZFRva2VuRW50aXR5LmVudmlyb25tZW50ID0gZW52aXJvbm1lbnQ7XHJcbiAgICAgICAgaWRUb2tlbkVudGl0eS5jbGllbnRJZCA9IGNsaWVudElkO1xyXG4gICAgICAgIGlkVG9rZW5FbnRpdHkuc2VjcmV0ID0gaWRUb2tlbjtcclxuICAgICAgICBpZFRva2VuRW50aXR5LnJlYWxtID0gdGVuYW50SWQ7XHJcbiAgICAgICAgaWRUb2tlbkVudGl0eS5vYm9Bc3NlcnRpb24gPSBvYm9Bc3NlcnRpb247XHJcblxyXG4gICAgICAgIHJldHVybiBpZFRva2VuRW50aXR5O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVmFsaWRhdGVzIGFuIGVudGl0eTogY2hlY2tzIGZvciBhbGwgZXhwZWN0ZWQgcGFyYW1zXHJcbiAgICAgKiBAcGFyYW0gZW50aXR5XHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBpc0lkVG9rZW5FbnRpdHkoZW50aXR5OiBvYmplY3QpOiBib29sZWFuIHtcclxuXHJcbiAgICAgICAgaWYgKCFlbnRpdHkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgZW50aXR5Lmhhc093blByb3BlcnR5KFwiaG9tZUFjY291bnRJZFwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJlbnZpcm9ubWVudFwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJjcmVkZW50aWFsVHlwZVwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJyZWFsbVwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJjbGllbnRJZFwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJzZWNyZXRcIikgJiZcclxuICAgICAgICAgICAgZW50aXR5W1wiY3JlZGVudGlhbFR5cGVcIl0gPT09IENyZWRlbnRpYWxUeXBlLklEX1RPS0VOXHJcbiAgICAgICAgKTtcclxuICAgIH1cclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBVdGlsaXR5IGNsYXNzIHdoaWNoIGV4cG9zZXMgZnVuY3Rpb25zIGZvciBtYW5hZ2luZyBkYXRlIGFuZCB0aW1lIG9wZXJhdGlvbnMuXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgVGltZVV0aWxzIHtcclxuXHJcbiAgICAvKipcclxuICAgICAqIHJldHVybiB0aGUgY3VycmVudCB0aW1lIGluIFVuaXggdGltZSAoc2Vjb25kcykuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBub3dTZWNvbmRzKCk6IG51bWJlciB7XHJcbiAgICAgICAgLy8gRGF0ZS5nZXRUaW1lKCkgcmV0dXJucyBpbiBtaWxsaXNlY29uZHMuXHJcbiAgICAgICAgcmV0dXJuIE1hdGgucm91bmQobmV3IERhdGUoKS5nZXRUaW1lKCkgLyAxMDAwLjApO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvKipcclxuICAgICAqIGNoZWNrIGlmIGEgdG9rZW4gaXMgZXhwaXJlZCBiYXNlZCBvbiBnaXZlbiBVVEMgdGltZSBpbiBzZWNvbmRzLlxyXG4gICAgICogQHBhcmFtIGV4cGlyZXNPblxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgaXNUb2tlbkV4cGlyZWQoZXhwaXJlc09uOiBzdHJpbmcsIG9mZnNldDogbnVtYmVyKTogYm9vbGVhbiB7XHJcbiAgICAgICAgLy8gY2hlY2sgZm9yIGFjY2VzcyB0b2tlbiBleHBpcnlcclxuICAgICAgICBjb25zdCBleHBpcmF0aW9uU2VjID0gTnVtYmVyKGV4cGlyZXNPbikgfHwgMDtcclxuICAgICAgICBjb25zdCBvZmZzZXRDdXJyZW50VGltZVNlYyA9IFRpbWVVdGlscy5ub3dTZWNvbmRzKCkgKyBvZmZzZXQ7IFxyXG5cclxuICAgICAgICAvLyBJZiBjdXJyZW50IHRpbWUgKyBvZmZzZXQgaXMgZ3JlYXRlciB0aGFuIHRva2VuIGV4cGlyYXRpb24gdGltZSwgdGhlbiB0b2tlbiBpcyBleHBpcmVkLlxyXG4gICAgICAgIHJldHVybiAob2Zmc2V0Q3VycmVudFRpbWVTZWMgPiBleHBpcmF0aW9uU2VjKTtcclxuICAgIH1cclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IENyZWRlbnRpYWxFbnRpdHkgfSBmcm9tIFwiLi9DcmVkZW50aWFsRW50aXR5XCI7XHJcbmltcG9ydCB7IENyZWRlbnRpYWxUeXBlLCBBdXRoZW50aWNhdGlvblNjaGVtZSB9IGZyb20gXCIuLi8uLi91dGlscy9Db25zdGFudHNcIjtcclxuaW1wb3J0IHsgVGltZVV0aWxzIH0gZnJvbSBcIi4uLy4uL3V0aWxzL1RpbWVVdGlsc1wiO1xyXG5pbXBvcnQgeyBTdHJpbmdVdGlscyB9IGZyb20gXCIuLi8uLi91dGlscy9TdHJpbmdVdGlsc1wiO1xyXG5cclxuLyoqXHJcbiAqIEFDQ0VTU19UT0tFTiBDcmVkZW50aWFsIFR5cGVcclxuICpcclxuICogS2V5OlZhbHVlIFNjaGVtYTpcclxuICpcclxuICogS2V5IEV4YW1wbGU6IHVpZC51dGlkLWxvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20tYWNjZXNzdG9rZW4tY2xpZW50SWQtY29udG9zby5jb20tdXNlci5yZWFkXHJcbiAqXHJcbiAqIFZhbHVlIFNjaGVtYTpcclxuICoge1xyXG4gKiAgICAgIGhvbWVBY2NvdW50SWQ6IGhvbWUgYWNjb3VudCBpZGVudGlmaWVyIGZvciB0aGUgYXV0aCBzY2hlbWUsXHJcbiAqICAgICAgZW52aXJvbm1lbnQ6IGVudGl0eSB0aGF0IGlzc3VlZCB0aGUgdG9rZW4sIHJlcHJlc2VudGVkIGFzIGEgZnVsbCBob3N0XHJcbiAqICAgICAgY3JlZGVudGlhbFR5cGU6IFR5cGUgb2YgY3JlZGVudGlhbCBhcyBhIHN0cmluZywgY2FuIGJlIG9uZSBvZiB0aGUgZm9sbG93aW5nOiBSZWZyZXNoVG9rZW4sIEFjY2Vzc1Rva2VuLCBJZFRva2VuLCBQYXNzd29yZCwgQ29va2llLCBDZXJ0aWZpY2F0ZSwgT3RoZXJcclxuICogICAgICBjbGllbnRJZDogY2xpZW50IElEIG9mIHRoZSBhcHBsaWNhdGlvblxyXG4gKiAgICAgIHNlY3JldDogQWN0dWFsIGNyZWRlbnRpYWwgYXMgYSBzdHJpbmdcclxuICogICAgICBmYW1pbHlJZDogRmFtaWx5IElEIGlkZW50aWZpZXIsIHVzdWFsbHkgb25seSB1c2VkIGZvciByZWZyZXNoIHRva2Vuc1xyXG4gKiAgICAgIHJlYWxtOiBGdWxsIHRlbmFudCBvciBvcmdhbml6YXRpb25hbCBpZGVudGlmaWVyIHRoYXQgdGhlIGFjY291bnQgYmVsb25ncyB0b1xyXG4gKiAgICAgIHRhcmdldDogUGVybWlzc2lvbnMgdGhhdCBhcmUgaW5jbHVkZWQgaW4gdGhlIHRva2VuLCBvciBmb3IgcmVmcmVzaCB0b2tlbnMsIHRoZSByZXNvdXJjZSBpZGVudGlmaWVyLlxyXG4gKiAgICAgIGNhY2hlZEF0OiBBYnNvbHV0ZSBkZXZpY2UgdGltZSB3aGVuIGVudHJ5IHdhcyBjcmVhdGVkIGluIHRoZSBjYWNoZS5cclxuICogICAgICBleHBpcmVzT246IFRva2VuIGV4cGlyeSB0aW1lLCBjYWxjdWxhdGVkIGJhc2VkIG9uIGN1cnJlbnQgVVRDIHRpbWUgaW4gc2Vjb25kcy4gUmVwcmVzZW50ZWQgYXMgYSBzdHJpbmcuXHJcbiAqICAgICAgZXh0ZW5kZWRFeHBpcmVzT246IEFkZGl0aW9uYWwgZXh0ZW5kZWQgZXhwaXJ5IHRpbWUgdW50aWwgd2hlbiB0b2tlbiBpcyB2YWxpZCBpbiBjYXNlIG9mIHNlcnZlci1zaWRlIG91dGFnZS4gUmVwcmVzZW50ZWQgYXMgc3RyaW5nIGluIFVUQyBzZWNvbmRzLlxyXG4gKiAgICAgIGtleUlkOiB1c2VkIGZvciBQT1AgYW5kIFNTSCB0b2tlblR5cGVzXHJcbiAqICAgICAgdG9rZW5UeXBlOiBUeXBlIG9mIHRoZSB0b2tlbiBpc3N1ZWQuIFVzdWFsbHkgXCJCZWFyZXJcIlxyXG4gKiB9XHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgQWNjZXNzVG9rZW5FbnRpdHkgZXh0ZW5kcyBDcmVkZW50aWFsRW50aXR5IHtcclxuICAgIHJlYWxtOiBzdHJpbmc7XHJcbiAgICB0YXJnZXQ6IHN0cmluZztcclxuICAgIGNhY2hlZEF0OiBzdHJpbmc7XHJcbiAgICBleHBpcmVzT246IHN0cmluZztcclxuICAgIGV4dGVuZGVkRXhwaXJlc09uPzogc3RyaW5nO1xyXG4gICAgcmVmcmVzaE9uPzogc3RyaW5nO1xyXG4gICAga2V5SWQ/OiBzdHJpbmc7IC8vIGZvciBQT1AgYW5kIFNTSCB0b2tlblR5cGVzXHJcbiAgICB0b2tlblR5cGU/OiBzdHJpbmc7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGUgQWNjZXNzVG9rZW5FbnRpdHlcclxuICAgICAqIEBwYXJhbSBob21lQWNjb3VudElkXHJcbiAgICAgKiBAcGFyYW0gZW52aXJvbm1lbnRcclxuICAgICAqIEBwYXJhbSBhY2Nlc3NUb2tlblxyXG4gICAgICogQHBhcmFtIGNsaWVudElkXHJcbiAgICAgKiBAcGFyYW0gdGVuYW50SWRcclxuICAgICAqIEBwYXJhbSBzY29wZXNcclxuICAgICAqIEBwYXJhbSBleHBpcmVzT25cclxuICAgICAqIEBwYXJhbSBleHRFeHBpcmVzT25cclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZUFjY2Vzc1Rva2VuRW50aXR5KFxyXG4gICAgICAgIGhvbWVBY2NvdW50SWQ6IHN0cmluZyxcclxuICAgICAgICBlbnZpcm9ubWVudDogc3RyaW5nLFxyXG4gICAgICAgIGFjY2Vzc1Rva2VuOiBzdHJpbmcsXHJcbiAgICAgICAgY2xpZW50SWQ6IHN0cmluZyxcclxuICAgICAgICB0ZW5hbnRJZDogc3RyaW5nLFxyXG4gICAgICAgIHNjb3Blczogc3RyaW5nLFxyXG4gICAgICAgIGV4cGlyZXNPbjogbnVtYmVyLFxyXG4gICAgICAgIGV4dEV4cGlyZXNPbjogbnVtYmVyLFxyXG4gICAgICAgIHRva2VuVHlwZT86IHN0cmluZyxcclxuICAgICAgICBvYm9Bc3NlcnRpb24/OiBzdHJpbmdcclxuICAgICk6IEFjY2Vzc1Rva2VuRW50aXR5IHtcclxuICAgICAgICBjb25zdCBhdEVudGl0eTogQWNjZXNzVG9rZW5FbnRpdHkgPSBuZXcgQWNjZXNzVG9rZW5FbnRpdHkoKTtcclxuXHJcbiAgICAgICAgYXRFbnRpdHkuaG9tZUFjY291bnRJZCA9IGhvbWVBY2NvdW50SWQ7XHJcbiAgICAgICAgYXRFbnRpdHkuY3JlZGVudGlhbFR5cGUgPSBDcmVkZW50aWFsVHlwZS5BQ0NFU1NfVE9LRU47XHJcbiAgICAgICAgYXRFbnRpdHkuc2VjcmV0ID0gYWNjZXNzVG9rZW47XHJcblxyXG4gICAgICAgIGNvbnN0IGN1cnJlbnRUaW1lID0gVGltZVV0aWxzLm5vd1NlY29uZHMoKTtcclxuICAgICAgICBhdEVudGl0eS5jYWNoZWRBdCA9IGN1cnJlbnRUaW1lLnRvU3RyaW5nKCk7XHJcblxyXG4gICAgICAgIC8qXHJcbiAgICAgICAgICogVG9rZW4gZXhwaXJ5IHRpbWUuXHJcbiAgICAgICAgICogVGhpcyB2YWx1ZSBzaG91bGQgYmUg4oCvY2FsY3VsYXRlZCBiYXNlZCBvbiB0aGUgY3VycmVudCBVVEMgdGltZSBtZWFzdXJlZCBsb2NhbGx5IGFuZCB0aGUgdmFsdWUg4oCvZXhwaXJlc19pbiBSZXByZXNlbnRlZCBhcyBhIHN0cmluZyBpbiBKU09OLlxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIGF0RW50aXR5LmV4cGlyZXNPbiA9IGV4cGlyZXNPbi50b1N0cmluZygpO1xyXG4gICAgICAgIGF0RW50aXR5LmV4dGVuZGVkRXhwaXJlc09uID0gZXh0RXhwaXJlc09uLnRvU3RyaW5nKCk7XHJcblxyXG4gICAgICAgIGF0RW50aXR5LmVudmlyb25tZW50ID0gZW52aXJvbm1lbnQ7XHJcbiAgICAgICAgYXRFbnRpdHkuY2xpZW50SWQgPSBjbGllbnRJZDtcclxuICAgICAgICBhdEVudGl0eS5yZWFsbSA9IHRlbmFudElkO1xyXG4gICAgICAgIGF0RW50aXR5LnRhcmdldCA9IHNjb3BlcztcclxuICAgICAgICBhdEVudGl0eS5vYm9Bc3NlcnRpb24gPSBvYm9Bc3NlcnRpb247XHJcblxyXG4gICAgICAgIGF0RW50aXR5LnRva2VuVHlwZSA9IFN0cmluZ1V0aWxzLmlzRW1wdHkodG9rZW5UeXBlKSA/IEF1dGhlbnRpY2F0aW9uU2NoZW1lLkJFQVJFUiA6IHRva2VuVHlwZTtcclxuICAgICAgICByZXR1cm4gYXRFbnRpdHk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBWYWxpZGF0ZXMgYW4gZW50aXR5OiBjaGVja3MgZm9yIGFsbCBleHBlY3RlZCBwYXJhbXNcclxuICAgICAqIEBwYXJhbSBlbnRpdHlcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGlzQWNjZXNzVG9rZW5FbnRpdHkoZW50aXR5OiBvYmplY3QpOiBib29sZWFuIHtcclxuXHJcbiAgICAgICAgaWYgKCFlbnRpdHkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgZW50aXR5Lmhhc093blByb3BlcnR5KFwiaG9tZUFjY291bnRJZFwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJlbnZpcm9ubWVudFwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJjcmVkZW50aWFsVHlwZVwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJyZWFsbVwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJjbGllbnRJZFwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJzZWNyZXRcIikgJiZcclxuICAgICAgICAgICAgZW50aXR5Lmhhc093blByb3BlcnR5KFwidGFyZ2V0XCIpICYmXHJcbiAgICAgICAgICAgIGVudGl0eVtcImNyZWRlbnRpYWxUeXBlXCJdID09PSBDcmVkZW50aWFsVHlwZS5BQ0NFU1NfVE9LRU5cclxuICAgICAgICApO1xyXG4gICAgfVxyXG59XHJcbiIsIi8qXHJcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgQ3JlZGVudGlhbEVudGl0eSB9IGZyb20gXCIuL0NyZWRlbnRpYWxFbnRpdHlcIjtcclxuaW1wb3J0IHsgQ3JlZGVudGlhbFR5cGUgfSBmcm9tIFwiLi4vLi4vdXRpbHMvQ29uc3RhbnRzXCI7XHJcblxyXG4vKipcclxuICogUkVGUkVTSF9UT0tFTiBDYWNoZVxyXG4gKlxyXG4gKiBLZXk6VmFsdWUgU2NoZW1hOlxyXG4gKlxyXG4gKiBLZXkgRXhhbXBsZTogdWlkLnV0aWQtbG9naW4ubWljcm9zb2Z0b25saW5lLmNvbS1yZWZyZXNodG9rZW4tY2xpZW50SWQtLVxyXG4gKlxyXG4gKiBWYWx1ZTpcclxuICoge1xyXG4gKiAgICAgIGhvbWVBY2NvdW50SWQ6IGhvbWUgYWNjb3VudCBpZGVudGlmaWVyIGZvciB0aGUgYXV0aCBzY2hlbWUsXHJcbiAqICAgICAgZW52aXJvbm1lbnQ6IGVudGl0eSB0aGF0IGlzc3VlZCB0aGUgdG9rZW4sIHJlcHJlc2VudGVkIGFzIGEgZnVsbCBob3N0XHJcbiAqICAgICAgY3JlZGVudGlhbFR5cGU6IFR5cGUgb2YgY3JlZGVudGlhbCBhcyBhIHN0cmluZywgY2FuIGJlIG9uZSBvZiB0aGUgZm9sbG93aW5nOiBSZWZyZXNoVG9rZW4sIEFjY2Vzc1Rva2VuLCBJZFRva2VuLCBQYXNzd29yZCwgQ29va2llLCBDZXJ0aWZpY2F0ZSwgT3RoZXJcclxuICogICAgICBjbGllbnRJZDogY2xpZW50IElEIG9mIHRoZSBhcHBsaWNhdGlvblxyXG4gKiAgICAgIHNlY3JldDogQWN0dWFsIGNyZWRlbnRpYWwgYXMgYSBzdHJpbmdcclxuICogICAgICBmYW1pbHlJZDogRmFtaWx5IElEIGlkZW50aWZpZXIsICcxJyByZXByZXNlbnRzIE1pY3Jvc29mdCBGYW1pbHlcclxuICogICAgICByZWFsbTogRnVsbCB0ZW5hbnQgb3Igb3JnYW5pemF0aW9uYWwgaWRlbnRpZmllciB0aGF0IHRoZSBhY2NvdW50IGJlbG9uZ3MgdG9cclxuICogICAgICB0YXJnZXQ6IFBlcm1pc3Npb25zIHRoYXQgYXJlIGluY2x1ZGVkIGluIHRoZSB0b2tlbiwgb3IgZm9yIHJlZnJlc2ggdG9rZW5zLCB0aGUgcmVzb3VyY2UgaWRlbnRpZmllci5cclxuICogfVxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIFJlZnJlc2hUb2tlbkVudGl0eSBleHRlbmRzIENyZWRlbnRpYWxFbnRpdHkge1xyXG4gICAgZmFtaWx5SWQ/OiBzdHJpbmc7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGUgUmVmcmVzaFRva2VuRW50aXR5XHJcbiAgICAgKiBAcGFyYW0gaG9tZUFjY291bnRJZFxyXG4gICAgICogQHBhcmFtIGF1dGhlbnRpY2F0aW9uUmVzdWx0XHJcbiAgICAgKiBAcGFyYW0gY2xpZW50SWRcclxuICAgICAqIEBwYXJhbSBhdXRob3JpdHlcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNyZWF0ZVJlZnJlc2hUb2tlbkVudGl0eShcclxuICAgICAgICBob21lQWNjb3VudElkOiBzdHJpbmcsXHJcbiAgICAgICAgZW52aXJvbm1lbnQ6IHN0cmluZyxcclxuICAgICAgICByZWZyZXNoVG9rZW46IHN0cmluZyxcclxuICAgICAgICBjbGllbnRJZDogc3RyaW5nLFxyXG4gICAgICAgIGZhbWlseUlkPzogc3RyaW5nLFxyXG4gICAgICAgIG9ib0Fzc2VydGlvbj86IHN0cmluZ1xyXG4gICAgKTogUmVmcmVzaFRva2VuRW50aXR5IHtcclxuICAgICAgICBjb25zdCBydEVudGl0eSA9IG5ldyBSZWZyZXNoVG9rZW5FbnRpdHkoKTtcclxuXHJcbiAgICAgICAgcnRFbnRpdHkuY2xpZW50SWQgPSBjbGllbnRJZDtcclxuICAgICAgICBydEVudGl0eS5jcmVkZW50aWFsVHlwZSA9IENyZWRlbnRpYWxUeXBlLlJFRlJFU0hfVE9LRU47XHJcbiAgICAgICAgcnRFbnRpdHkuZW52aXJvbm1lbnQgPSBlbnZpcm9ubWVudDtcclxuICAgICAgICBydEVudGl0eS5ob21lQWNjb3VudElkID0gaG9tZUFjY291bnRJZDtcclxuICAgICAgICBydEVudGl0eS5zZWNyZXQgPSByZWZyZXNoVG9rZW47XHJcbiAgICAgICAgcnRFbnRpdHkub2JvQXNzZXJ0aW9uID0gb2JvQXNzZXJ0aW9uO1xyXG5cclxuICAgICAgICBpZiAoZmFtaWx5SWQpXHJcbiAgICAgICAgICAgIHJ0RW50aXR5LmZhbWlseUlkID0gZmFtaWx5SWQ7XHJcblxyXG4gICAgICAgIHJldHVybiBydEVudGl0eTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFZhbGlkYXRlcyBhbiBlbnRpdHk6IGNoZWNrcyBmb3IgYWxsIGV4cGVjdGVkIHBhcmFtc1xyXG4gICAgICogQHBhcmFtIGVudGl0eVxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgaXNSZWZyZXNoVG9rZW5FbnRpdHkoZW50aXR5OiBvYmplY3QpOiBib29sZWFuIHtcclxuXHJcbiAgICAgICAgaWYgKCFlbnRpdHkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgZW50aXR5Lmhhc093blByb3BlcnR5KFwiaG9tZUFjY291bnRJZFwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJlbnZpcm9ubWVudFwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJjcmVkZW50aWFsVHlwZVwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJjbGllbnRJZFwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJzZWNyZXRcIikgJiZcclxuICAgICAgICAgICAgZW50aXR5W1wiY3JlZGVudGlhbFR5cGVcIl0gPT09IENyZWRlbnRpYWxUeXBlLlJFRlJFU0hfVE9LRU5cclxuICAgICAgICApO1xyXG4gICAgfVxyXG59XHJcbiIsIi8qXHJcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgU2VydmVyRXJyb3IgfSBmcm9tIFwiLi9TZXJ2ZXJFcnJvclwiO1xyXG5cclxuLyoqXHJcbiAqIEludGVyYWN0aW9uUmVxdWlyZWRBdXRoRXJyb3JNZXNzYWdlIGNsYXNzIGNvbnRhaW5pbmcgc3RyaW5nIGNvbnN0YW50cyB1c2VkIGJ5IGVycm9yIGNvZGVzIGFuZCBtZXNzYWdlcy5cclxuICovXHJcbmV4cG9ydCBjb25zdCBJbnRlcmFjdGlvblJlcXVpcmVkQXV0aEVycm9yTWVzc2FnZSA9IFtcclxuICAgIFwiaW50ZXJhY3Rpb25fcmVxdWlyZWRcIixcclxuICAgIFwiY29uc2VudF9yZXF1aXJlZFwiLFxyXG4gICAgXCJsb2dpbl9yZXF1aXJlZFwiXHJcbl07XHJcblxyXG5leHBvcnQgY29uc3QgSW50ZXJhY3Rpb25SZXF1aXJlZEF1dGhTdWJFcnJvck1lc3NhZ2UgPSBbXHJcbiAgICBcIm1lc3NhZ2Vfb25seVwiLFxyXG4gICAgXCJhZGRpdGlvbmFsX2FjdGlvblwiLFxyXG4gICAgXCJiYXNpY19hY3Rpb25cIixcclxuICAgIFwidXNlcl9wYXNzd29yZF9leHBpcmVkXCIsXHJcbiAgICBcImNvbnNlbnRfcmVxdWlyZWRcIlxyXG5dO1xyXG5cclxuLyoqXHJcbiAqIEVycm9yIHRocm93biB3aGVuIHVzZXIgaW50ZXJhY3Rpb24gaXMgcmVxdWlyZWQgYXQgdGhlIGF1dGggc2VydmVyLlxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIEludGVyYWN0aW9uUmVxdWlyZWRBdXRoRXJyb3IgZXh0ZW5kcyBTZXJ2ZXJFcnJvciB7XHJcblxyXG4gICAgY29uc3RydWN0b3IoZXJyb3JDb2RlPzogc3RyaW5nLCBlcnJvck1lc3NhZ2U/OiBzdHJpbmcsIHN1YkVycm9yPzogc3RyaW5nKSB7XHJcbiAgICAgICAgc3VwZXIoZXJyb3JDb2RlLCBlcnJvck1lc3NhZ2UsIHN1YkVycm9yKTtcclxuICAgICAgICB0aGlzLm5hbWUgPSBcIkludGVyYWN0aW9uUmVxdWlyZWRBdXRoRXJyb3JcIjtcclxuXHJcbiAgICAgICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKHRoaXMsIEludGVyYWN0aW9uUmVxdWlyZWRBdXRoRXJyb3IucHJvdG90eXBlKTtcclxuICAgIH1cclxuXHJcbiAgICBzdGF0aWMgaXNJbnRlcmFjdGlvblJlcXVpcmVkRXJyb3IoZXJyb3JDb2RlPzogc3RyaW5nLCBlcnJvclN0cmluZz86IHN0cmluZywgc3ViRXJyb3I/OiBzdHJpbmcpIDogYm9vbGVhbiB7XHJcbiAgICAgICAgY29uc3QgaXNJbnRlcmFjdGlvblJlcXVpcmVkRXJyb3JDb2RlID0gISFlcnJvckNvZGUgJiYgSW50ZXJhY3Rpb25SZXF1aXJlZEF1dGhFcnJvck1lc3NhZ2UuaW5kZXhPZihlcnJvckNvZGUpID4gLTE7XHJcbiAgICAgICAgY29uc3QgaXNJbnRlcmFjdGlvblJlcXVpcmVkU3ViRXJyb3IgPSAhIXN1YkVycm9yICYmIEludGVyYWN0aW9uUmVxdWlyZWRBdXRoU3ViRXJyb3JNZXNzYWdlLmluZGV4T2Yoc3ViRXJyb3IpID4gLTE7XHJcbiAgICAgICAgY29uc3QgaXNJbnRlcmFjdGlvblJlcXVpcmVkRXJyb3JEZXNjID0gISFlcnJvclN0cmluZyAmJiBJbnRlcmFjdGlvblJlcXVpcmVkQXV0aEVycm9yTWVzc2FnZS5zb21lKChpckVycm9yQ29kZSkgPT4ge1xyXG4gICAgICAgICAgICByZXR1cm4gZXJyb3JTdHJpbmcuaW5kZXhPZihpckVycm9yQ29kZSkgPiAtMTtcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgcmV0dXJuIGlzSW50ZXJhY3Rpb25SZXF1aXJlZEVycm9yQ29kZSB8fCBpc0ludGVyYWN0aW9uUmVxdWlyZWRFcnJvckRlc2MgfHwgaXNJbnRlcmFjdGlvblJlcXVpcmVkU3ViRXJyb3I7XHJcbiAgICB9XHJcbn1cclxuIiwiLypcclxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cclxuICovXHJcblxyXG5pbXBvcnQgeyBJZFRva2VuRW50aXR5IH0gZnJvbSBcIi4vSWRUb2tlbkVudGl0eVwiO1xyXG5pbXBvcnQgeyBBY2Nlc3NUb2tlbkVudGl0eSB9IGZyb20gXCIuL0FjY2Vzc1Rva2VuRW50aXR5XCI7XHJcbmltcG9ydCB7IFJlZnJlc2hUb2tlbkVudGl0eSB9IGZyb20gXCIuL1JlZnJlc2hUb2tlbkVudGl0eVwiO1xyXG5pbXBvcnQgeyBBY2NvdW50RW50aXR5IH0gZnJvbSBcIi4vQWNjb3VudEVudGl0eVwiO1xyXG5pbXBvcnQgeyBBcHBNZXRhZGF0YUVudGl0eSB9IGZyb20gXCIuL0FwcE1ldGFkYXRhRW50aXR5XCI7XHJcblxyXG5leHBvcnQgY2xhc3MgQ2FjaGVSZWNvcmQge1xyXG4gICAgYWNjb3VudDogQWNjb3VudEVudGl0eSB8IG51bGw7XHJcbiAgICBpZFRva2VuOiBJZFRva2VuRW50aXR5IHwgbnVsbDtcclxuICAgIGFjY2Vzc1Rva2VuOiBBY2Nlc3NUb2tlbkVudGl0eSB8IG51bGw7XHJcbiAgICByZWZyZXNoVG9rZW46IFJlZnJlc2hUb2tlbkVudGl0eSB8IG51bGw7XHJcbiAgICBhcHBNZXRhZGF0YTogQXBwTWV0YWRhdGFFbnRpdHkgfCBudWxsO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKGFjY291bnRFbnRpdHk/OiBBY2NvdW50RW50aXR5IHwgbnVsbCwgaWRUb2tlbkVudGl0eT86IElkVG9rZW5FbnRpdHkgfCBudWxsLCBhY2Nlc3NUb2tlbkVudGl0eT86IEFjY2Vzc1Rva2VuRW50aXR5IHwgbnVsbCwgcmVmcmVzaFRva2VuRW50aXR5PzogUmVmcmVzaFRva2VuRW50aXR5IHwgbnVsbCwgYXBwTWV0YWRhdGFFbnRpdHk/OiBBcHBNZXRhZGF0YUVudGl0eSB8IG51bGwpIHtcclxuICAgICAgICB0aGlzLmFjY291bnQgPSBhY2NvdW50RW50aXR5IHx8IG51bGw7XHJcbiAgICAgICAgdGhpcy5pZFRva2VuID0gaWRUb2tlbkVudGl0eSB8fCBudWxsO1xyXG4gICAgICAgIHRoaXMuYWNjZXNzVG9rZW4gPSBhY2Nlc3NUb2tlbkVudGl0eSB8fCBudWxsO1xyXG4gICAgICAgIHRoaXMucmVmcmVzaFRva2VuID0gcmVmcmVzaFRva2VuRW50aXR5IHx8IG51bGw7XHJcbiAgICAgICAgdGhpcy5hcHBNZXRhZGF0YSA9IGFwcE1ldGFkYXRhRW50aXR5IHx8IG51bGw7XHJcbiAgICB9XHJcbn1cclxuIiwiLypcclxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cclxuICovXHJcblxyXG5pbXBvcnQgeyBTdHJpbmdVdGlscyB9IGZyb20gXCIuL1N0cmluZ1V0aWxzXCI7XHJcbmltcG9ydCB7IENvbnN0YW50cyB9IGZyb20gXCIuL0NvbnN0YW50c1wiO1xyXG5pbXBvcnQgeyBJQ3J5cHRvIH0gZnJvbSBcIi4uL2NyeXB0by9JQ3J5cHRvXCI7XHJcbmltcG9ydCB7IENsaWVudEF1dGhFcnJvciB9IGZyb20gXCIuLi9lcnJvci9DbGllbnRBdXRoRXJyb3JcIjtcclxuXHJcbi8qKlxyXG4gKiBUeXBlIHdoaWNoIGRlZmluZXMgdGhlIG9iamVjdCB0aGF0IGlzIHN0cmluZ2lmaWVkLCBlbmNvZGVkIGFuZCBzZW50IGluIHRoZSBzdGF0ZSB2YWx1ZS5cclxuICogQ29udGFpbnMgdGhlIGZvbGxvd2luZzpcclxuICogLSBpZCAtIHVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGlzIHJlcXVlc3RcclxuICogLSB0cyAtIHRpbWVzdGFtcCBmb3IgdGhlIHRpbWUgdGhlIHJlcXVlc3Qgd2FzIG1hZGUuIFVzZWQgdG8gZW5zdXJlIHRoYXQgdG9rZW4gZXhwaXJhdGlvbiBpcyBub3QgY2FsY3VsYXRlZCBpbmNvcnJlY3RseS5cclxuICogLSBwbGF0Zm9ybVN0YXRlIC0gc3RyaW5nIHZhbHVlIHNlbnQgZnJvbSB0aGUgcGxhdGZvcm0uXHJcbiAqL1xyXG5leHBvcnQgdHlwZSBMaWJyYXJ5U3RhdGVPYmplY3QgPSB7XHJcbiAgICBpZDogc3RyaW5nLFxyXG4gICAgbWV0YT86IFJlY29yZDxzdHJpbmcsIHN0cmluZz5cclxufTtcclxuXHJcbi8qKlxyXG4gKiBUeXBlIHdoaWNoIGRlZmluZXMgdGhlIHN0cmluZ2lmaWVkIGFuZCBlbmNvZGVkIG9iamVjdCBzZW50IHRvIHRoZSBzZXJ2aWNlIGluIHRoZSBhdXRob3JpemUgcmVxdWVzdC5cclxuICovXHJcbmV4cG9ydCB0eXBlIFJlcXVlc3RTdGF0ZU9iamVjdCA9IHtcclxuICAgIHVzZXJSZXF1ZXN0U3RhdGU6IHN0cmluZyxcclxuICAgIGxpYnJhcnlTdGF0ZTogTGlicmFyeVN0YXRlT2JqZWN0XHJcbn07XHJcblxyXG4vKipcclxuICogQ2xhc3Mgd2hpY2ggcHJvdmlkZXMgaGVscGVycyBmb3IgT0F1dGggMi4wIHByb3RvY29sIHNwZWNpZmljIHZhbHVlc1xyXG4gKi9cclxuZXhwb3J0IGNsYXNzIFByb3RvY29sVXRpbHMge1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQXBwZW5kcyB1c2VyIHN0YXRlIHdpdGggcmFuZG9tIGd1aWQsIG9yIHJldHVybnMgcmFuZG9tIGd1aWQuXHJcbiAgICAgKiBAcGFyYW0gdXNlclN0YXRlIFxyXG4gICAgICogQHBhcmFtIHJhbmRvbUd1aWQgXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBzZXRSZXF1ZXN0U3RhdGUoY3J5cHRvT2JqOiBJQ3J5cHRvLCB1c2VyU3RhdGU/OiBzdHJpbmcsIG1ldGE/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KTogc3RyaW5nIHtcclxuICAgICAgICBjb25zdCBsaWJyYXJ5U3RhdGUgPSBQcm90b2NvbFV0aWxzLmdlbmVyYXRlTGlicmFyeVN0YXRlKGNyeXB0b09iaiwgbWV0YSk7XHJcbiAgICAgICAgcmV0dXJuICFTdHJpbmdVdGlscy5pc0VtcHR5KHVzZXJTdGF0ZSkgPyBgJHtsaWJyYXJ5U3RhdGV9JHtDb25zdGFudHMuUkVTT1VSQ0VfREVMSU19JHt1c2VyU3RhdGV9YCA6IGxpYnJhcnlTdGF0ZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdlbmVyYXRlcyB0aGUgc3RhdGUgdmFsdWUgdXNlZCBieSB0aGUgY29tbW9uIGxpYnJhcnkuXHJcbiAgICAgKiBAcGFyYW0gcmFuZG9tR3VpZCBcclxuICAgICAqIEBwYXJhbSBjcnlwdG9PYmogXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBnZW5lcmF0ZUxpYnJhcnlTdGF0ZShjcnlwdG9PYmo6IElDcnlwdG8sIG1ldGE/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KTogc3RyaW5nIHtcclxuICAgICAgICBpZiAoIWNyeXB0b09iaikge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRBdXRoRXJyb3IuY3JlYXRlTm9DcnlwdG9PYmplY3RFcnJvcihcImdlbmVyYXRlTGlicmFyeVN0YXRlXCIpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gQ3JlYXRlIGEgc3RhdGUgb2JqZWN0IGNvbnRhaW5pbmcgYSB1bmlxdWUgaWQgYW5kIHRoZSB0aW1lc3RhbXAgb2YgdGhlIHJlcXVlc3QgY3JlYXRpb25cclxuICAgICAgICBjb25zdCBzdGF0ZU9iajogTGlicmFyeVN0YXRlT2JqZWN0ID0ge1xyXG4gICAgICAgICAgICBpZDogY3J5cHRvT2JqLmNyZWF0ZU5ld0d1aWQoKVxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIGlmIChtZXRhKSB7XHJcbiAgICAgICAgICAgIHN0YXRlT2JqLm1ldGEgPSBtZXRhO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3Qgc3RhdGVTdHJpbmcgPSBKU09OLnN0cmluZ2lmeShzdGF0ZU9iaik7XHJcblxyXG4gICAgICAgIHJldHVybiBjcnlwdG9PYmouYmFzZTY0RW5jb2RlKHN0YXRlU3RyaW5nKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFBhcnNlcyB0aGUgc3RhdGUgaW50byB0aGUgUmVxdWVzdFN0YXRlT2JqZWN0LCB3aGljaCBjb250YWlucyB0aGUgTGlicmFyeVN0YXRlIGluZm8gYW5kIHRoZSBzdGF0ZSBwYXNzZWQgYnkgdGhlIHVzZXIuXHJcbiAgICAgKiBAcGFyYW0gc3RhdGUgXHJcbiAgICAgKiBAcGFyYW0gY3J5cHRvT2JqIFxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgcGFyc2VSZXF1ZXN0U3RhdGUoY3J5cHRvT2JqOiBJQ3J5cHRvLCBzdGF0ZTogc3RyaW5nKTogUmVxdWVzdFN0YXRlT2JqZWN0IHtcclxuICAgICAgICBpZiAoIWNyeXB0b09iaikge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRBdXRoRXJyb3IuY3JlYXRlTm9DcnlwdG9PYmplY3RFcnJvcihcInBhcnNlUmVxdWVzdFN0YXRlXCIpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKFN0cmluZ1V0aWxzLmlzRW1wdHkoc3RhdGUpKSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVJbnZhbGlkU3RhdGVFcnJvcihzdGF0ZSwgXCJOdWxsLCB1bmRlZmluZWQgb3IgZW1wdHkgc3RhdGVcIik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAvLyBTcGxpdCB0aGUgc3RhdGUgYmV0d2VlbiBsaWJyYXJ5IHN0YXRlIGFuZCB1c2VyIHBhc3NlZCBzdGF0ZSBhbmQgZGVjb2RlIHRoZW0gc2VwYXJhdGVseVxyXG4gICAgICAgICAgICBjb25zdCBzcGxpdFN0YXRlID0gZGVjb2RlVVJJQ29tcG9uZW50KHN0YXRlKS5zcGxpdChDb25zdGFudHMuUkVTT1VSQ0VfREVMSU0pO1xyXG4gICAgICAgICAgICBjb25zdCBsaWJyYXJ5U3RhdGUgPSBzcGxpdFN0YXRlWzBdO1xyXG4gICAgICAgICAgICBjb25zdCB1c2VyU3RhdGUgPSBzcGxpdFN0YXRlLmxlbmd0aCA+IDEgPyBzcGxpdFN0YXRlLnNsaWNlKDEpLmpvaW4oQ29uc3RhbnRzLlJFU09VUkNFX0RFTElNKSA6IFwiXCI7XHJcbiAgICAgICAgICAgIGNvbnN0IGxpYnJhcnlTdGF0ZVN0cmluZyA9IGNyeXB0b09iai5iYXNlNjREZWNvZGUobGlicmFyeVN0YXRlKTtcclxuICAgICAgICAgICAgY29uc3QgbGlicmFyeVN0YXRlT2JqID0gSlNPTi5wYXJzZShsaWJyYXJ5U3RhdGVTdHJpbmcpIGFzIExpYnJhcnlTdGF0ZU9iamVjdDtcclxuICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgIHVzZXJSZXF1ZXN0U3RhdGU6ICFTdHJpbmdVdGlscy5pc0VtcHR5KHVzZXJTdGF0ZSkgPyB1c2VyU3RhdGUgOiBcIlwiLFxyXG4gICAgICAgICAgICAgICAgbGlicmFyeVN0YXRlOiBsaWJyYXJ5U3RhdGVPYmpcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9IGNhdGNoKGUpIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50QXV0aEVycm9yLmNyZWF0ZUludmFsaWRTdGF0ZUVycm9yKHN0YXRlLCBlKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuIiwiLypcclxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cclxuICovXHJcblxyXG5pbXBvcnQgeyBTZXJ2ZXJBdXRob3JpemF0aW9uQ29kZVJlc3BvbnNlIH0gZnJvbSBcIi4uL3Jlc3BvbnNlL1NlcnZlckF1dGhvcml6YXRpb25Db2RlUmVzcG9uc2VcIjtcclxuaW1wb3J0IHsgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL0NsaWVudENvbmZpZ3VyYXRpb25FcnJvclwiO1xyXG5pbXBvcnQgeyBDbGllbnRBdXRoRXJyb3IgfSBmcm9tIFwiLi4vZXJyb3IvQ2xpZW50QXV0aEVycm9yXCI7XHJcbmltcG9ydCB7IFN0cmluZ1V0aWxzIH0gZnJvbSBcIi4uL3V0aWxzL1N0cmluZ1V0aWxzXCI7XHJcbmltcG9ydCB7IElVcmkgfSBmcm9tIFwiLi9JVXJpXCI7XHJcbmltcG9ydCB7IEFBREF1dGhvcml0eUNvbnN0YW50cywgQ29uc3RhbnRzIH0gZnJvbSBcIi4uL3V0aWxzL0NvbnN0YW50c1wiO1xyXG5cclxuLyoqXHJcbiAqIFVybCBvYmplY3QgY2xhc3Mgd2hpY2ggY2FuIHBlcmZvcm0gdmFyaW91cyB0cmFuc2Zvcm1hdGlvbnMgb24gdXJsIHN0cmluZ3MuXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgVXJsU3RyaW5nIHtcclxuXHJcbiAgICAvLyBpbnRlcm5hbCB1cmwgc3RyaW5nIGZpZWxkXHJcbiAgICBwcml2YXRlIF91cmxTdHJpbmc6IHN0cmluZztcclxuICAgIHB1YmxpYyBnZXQgdXJsU3RyaW5nKCk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3VybFN0cmluZztcclxuICAgIH1cclxuICAgIFxyXG4gICAgY29uc3RydWN0b3IodXJsOiBzdHJpbmcpIHtcclxuICAgICAgICB0aGlzLl91cmxTdHJpbmcgPSB1cmw7XHJcbiAgICAgICAgaWYgKFN0cmluZ1V0aWxzLmlzRW1wdHkodGhpcy5fdXJsU3RyaW5nKSkge1xyXG4gICAgICAgICAgICAvLyBUaHJvd3MgZXJyb3IgaWYgdXJsIGlzIGVtcHR5XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudENvbmZpZ3VyYXRpb25FcnJvci5jcmVhdGVVcmxFbXB0eUVycm9yKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoU3RyaW5nVXRpbHMuaXNFbXB0eSh0aGlzLmdldEhhc2goKSkpIHtcclxuICAgICAgICAgICAgdGhpcy5fdXJsU3RyaW5nID0gVXJsU3RyaW5nLmNhbm9uaWNhbGl6ZVVyaSh1cmwpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEVuc3VyZSB1cmxzIGFyZSBsb3dlciBjYXNlIGFuZCBlbmQgd2l0aCBhIC8gY2hhcmFjdGVyLlxyXG4gICAgICogQHBhcmFtIHVybCBcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGNhbm9uaWNhbGl6ZVVyaSh1cmw6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgaWYgKHVybCkge1xyXG4gICAgICAgICAgICB1cmwgPSB1cmwudG9Mb3dlckNhc2UoKTtcclxuXHJcbiAgICAgICAgICAgIGlmIChTdHJpbmdVdGlscy5lbmRzV2l0aCh1cmwsIFwiP1wiKSkge1xyXG4gICAgICAgICAgICAgICAgdXJsID0gdXJsLnNsaWNlKDAsIC0xKTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChTdHJpbmdVdGlscy5lbmRzV2l0aCh1cmwsIFwiPy9cIikpIHtcclxuICAgICAgICAgICAgICAgIHVybCA9IHVybC5zbGljZSgwLCAtMik7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICghU3RyaW5nVXRpbHMuZW5kc1dpdGgodXJsLCBcIi9cIikpIHtcclxuICAgICAgICAgICAgICAgIHVybCArPSBcIi9cIjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHVybDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRocm93cyBpZiB1cmxTdHJpbmcgcGFzc2VkIGlzIG5vdCBhIHZhbGlkIGF1dGhvcml0eSBVUkkgc3RyaW5nLlxyXG4gICAgICovXHJcbiAgICB2YWxpZGF0ZUFzVXJpKCk6IHZvaWQge1xyXG4gICAgICAgIC8vIEF0dGVtcHRzIHRvIHBhcnNlIHVybCBmb3IgdXJpIGNvbXBvbmVudHNcclxuICAgICAgICBsZXQgY29tcG9uZW50cztcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBjb21wb25lbnRzID0gdGhpcy5nZXRVcmxDb21wb25lbnRzKCk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRDb25maWd1cmF0aW9uRXJyb3IuY3JlYXRlVXJsUGFyc2VFcnJvcihlKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFRocm93IGVycm9yIGlmIFVSSSBvciBwYXRoIHNlZ21lbnRzIGFyZSBub3QgcGFyc2VhYmxlLlxyXG4gICAgICAgIGlmICghY29tcG9uZW50cy5Ib3N0TmFtZUFuZFBvcnQgfHwgIWNvbXBvbmVudHMuUGF0aFNlZ21lbnRzKSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudENvbmZpZ3VyYXRpb25FcnJvci5jcmVhdGVVcmxQYXJzZUVycm9yKGBHaXZlbiB1cmwgc3RyaW5nOiAke3RoaXMudXJsU3RyaW5nfWApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gVGhyb3cgZXJyb3IgaWYgdXJpIGlzIGluc2VjdXJlLlxyXG4gICAgICAgIGlmKCFjb21wb25lbnRzLlByb3RvY29sIHx8IGNvbXBvbmVudHMuUHJvdG9jb2wudG9Mb3dlckNhc2UoKSAhPT0gXCJodHRwczpcIikge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRDb25maWd1cmF0aW9uRXJyb3IuY3JlYXRlSW5zZWN1cmVBdXRob3JpdHlVcmlFcnJvcih0aGlzLnVybFN0cmluZyk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRnVuY3Rpb24gdG8gcmVtb3ZlIHF1ZXJ5IHN0cmluZyBwYXJhbXMgZnJvbSB1cmwuIFJldHVybnMgdGhlIG5ldyB1cmwuXHJcbiAgICAgKiBAcGFyYW0gdXJsXHJcbiAgICAgKiBAcGFyYW0gbmFtZVxyXG4gICAgICovXHJcbiAgICB1cmxSZW1vdmVRdWVyeVN0cmluZ1BhcmFtZXRlcihuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIGxldCByZWdleCA9IG5ldyBSZWdFeHAoXCIoXFxcXCZcIiArIG5hbWUgKyBcIj0pW15cXCZdK1wiKTtcclxuICAgICAgICB0aGlzLl91cmxTdHJpbmcgPSB0aGlzLnVybFN0cmluZy5yZXBsYWNlKHJlZ2V4LCBcIlwiKTtcclxuICAgICAgICAvLyBuYW1lPXZhbHVlJlxyXG4gICAgICAgIHJlZ2V4ID0gbmV3IFJlZ0V4cChcIihcIiArIG5hbWUgKyBcIj0pW15cXCZdKyZcIik7XHJcbiAgICAgICAgdGhpcy5fdXJsU3RyaW5nID0gdGhpcy51cmxTdHJpbmcucmVwbGFjZShyZWdleCwgXCJcIik7XHJcbiAgICAgICAgLy8gbmFtZT12YWx1ZVxyXG4gICAgICAgIHJlZ2V4ID0gbmV3IFJlZ0V4cChcIihcIiArIG5hbWUgKyBcIj0pW15cXCZdK1wiKTtcclxuICAgICAgICB0aGlzLl91cmxTdHJpbmcgPSB0aGlzLnVybFN0cmluZy5yZXBsYWNlKHJlZ2V4LCBcIlwiKTtcclxuICAgICAgICByZXR1cm4gdGhpcy51cmxTdHJpbmc7XHJcbiAgICB9XHJcblxyXG4gICAgc3RhdGljIHJlbW92ZUhhc2hGcm9tVXJsKHVybDogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgICAgICByZXR1cm4gVXJsU3RyaW5nLmNhbm9uaWNhbGl6ZVVyaSh1cmwuc3BsaXQoXCIjXCIpWzBdKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdpdmVuIGEgdXJsIGxpa2UgaHR0cHM6Ly9hOmIvY29tbW9uL2Q/ZT1mI2csIGFuZCBhIHRlbmFudElkLCByZXR1cm5zIGh0dHBzOi8vYTpiL3RlbmFudElkL2RcclxuICAgICAqIEBwYXJhbSBocmVmIFRoZSB1cmxcclxuICAgICAqIEBwYXJhbSB0ZW5hbnRJZCBUaGUgdGVuYW50IGlkIHRvIHJlcGxhY2VcclxuICAgICAqL1xyXG4gICAgcmVwbGFjZVRlbmFudFBhdGgodGVuYW50SWQ6IHN0cmluZyk6IFVybFN0cmluZyB7XHJcbiAgICAgICAgY29uc3QgdXJsT2JqZWN0ID0gdGhpcy5nZXRVcmxDb21wb25lbnRzKCk7XHJcbiAgICAgICAgY29uc3QgcGF0aEFycmF5ID0gdXJsT2JqZWN0LlBhdGhTZWdtZW50cztcclxuICAgICAgICBpZiAodGVuYW50SWQgJiYgKHBhdGhBcnJheS5sZW5ndGggIT09IDAgJiYgKHBhdGhBcnJheVswXSA9PT0gQUFEQXV0aG9yaXR5Q29uc3RhbnRzLkNPTU1PTiB8fCBwYXRoQXJyYXlbMF0gPT09IEFBREF1dGhvcml0eUNvbnN0YW50cy5PUkdBTklaQVRJT05TKSkpIHtcclxuICAgICAgICAgICAgcGF0aEFycmF5WzBdID0gdGVuYW50SWQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBVcmxTdHJpbmcuY29uc3RydWN0QXV0aG9yaXR5VXJpRnJvbU9iamVjdCh1cmxPYmplY3QpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyB0aGUgYW5jaG9yIHBhcnQoIykgb2YgdGhlIFVSTFxyXG4gICAgICovXHJcbiAgICBnZXRIYXNoKCk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIFVybFN0cmluZy5wYXJzZUhhc2godGhpcy51cmxTdHJpbmcpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUGFyc2VzIG91dCB0aGUgY29tcG9uZW50cyBmcm9tIGEgdXJsIHN0cmluZy5cclxuICAgICAqIEByZXR1cm5zIEFuIG9iamVjdCB3aXRoIHRoZSB2YXJpb3VzIGNvbXBvbmVudHMuIFBsZWFzZSBjYWNoZSB0aGlzIHZhbHVlIGluc3RlZCBvZiBjYWxsaW5nIHRoaXMgbXVsdGlwbGUgdGltZXMgb24gdGhlIHNhbWUgdXJsLlxyXG4gICAgICovXHJcbiAgICBnZXRVcmxDb21wb25lbnRzKCk6IElVcmkge1xyXG4gICAgICAgIC8vIGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL2N1cnRpc3ovMTExMzliMmNmY2FlZjRhMjYxZTBcclxuICAgICAgICBjb25zdCByZWdFeCA9IFJlZ0V4cChcIl4oKFteOi8/I10rKTopPygvLyhbXi8/I10qKSk/KFtePyNdKikoXFxcXD8oW14jXSopKT8oIyguKikpP1wiKTtcclxuXHJcbiAgICAgICAgLy8gSWYgdXJsIHN0cmluZyBkb2VzIG5vdCBtYXRjaCByZWdFeCwgd2UgdGhyb3cgYW4gZXJyb3JcclxuICAgICAgICBjb25zdCBtYXRjaCA9IHRoaXMudXJsU3RyaW5nLm1hdGNoKHJlZ0V4KTtcclxuICAgICAgICBpZiAoIW1hdGNoKSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudENvbmZpZ3VyYXRpb25FcnJvci5jcmVhdGVVcmxQYXJzZUVycm9yKGBHaXZlbiB1cmwgc3RyaW5nOiAke3RoaXMudXJsU3RyaW5nfWApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gVXJsIGNvbXBvbmVudCBvYmplY3RcclxuICAgICAgICBjb25zdCB1cmxDb21wb25lbnRzID0ge1xyXG4gICAgICAgICAgICBQcm90b2NvbDogbWF0Y2hbMV0sXHJcbiAgICAgICAgICAgIEhvc3ROYW1lQW5kUG9ydDogbWF0Y2hbNF0sXHJcbiAgICAgICAgICAgIEFic29sdXRlUGF0aDogbWF0Y2hbNV0sXHJcbiAgICAgICAgICAgIFF1ZXJ5U3RyaW5nOiBtYXRjaFs3XVxyXG4gICAgICAgIH0gYXMgSVVyaTtcclxuXHJcbiAgICAgICAgbGV0IHBhdGhTZWdtZW50cyA9IHVybENvbXBvbmVudHMuQWJzb2x1dGVQYXRoLnNwbGl0KFwiL1wiKTtcclxuICAgICAgICBwYXRoU2VnbWVudHMgPSBwYXRoU2VnbWVudHMuZmlsdGVyKCh2YWwpID0+IHZhbCAmJiB2YWwubGVuZ3RoID4gMCk7IC8vIHJlbW92ZSBlbXB0eSBlbGVtZW50c1xyXG4gICAgICAgIHVybENvbXBvbmVudHMuUGF0aFNlZ21lbnRzID0gcGF0aFNlZ21lbnRzO1xyXG5cclxuICAgICAgICBpZiAoIVN0cmluZ1V0aWxzLmlzRW1wdHkodXJsQ29tcG9uZW50cy5RdWVyeVN0cmluZykgJiYgdXJsQ29tcG9uZW50cy5RdWVyeVN0cmluZy5lbmRzV2l0aChcIi9cIikpIHtcclxuICAgICAgICAgICAgdXJsQ29tcG9uZW50cy5RdWVyeVN0cmluZyA9IHVybENvbXBvbmVudHMuUXVlcnlTdHJpbmcuc3Vic3RyaW5nKDAsIHVybENvbXBvbmVudHMuUXVlcnlTdHJpbmcubGVuZ3RoLTEpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdXJsQ29tcG9uZW50cztcclxuICAgIH1cclxuXHJcbiAgICBzdGF0aWMgZ2V0RG9tYWluRnJvbVVybCh1cmw6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgY29uc3QgcmVnRXggPSBSZWdFeHAoXCJeKFteOi8/I10rOi8vKT8oW14vPyNdKilcIik7XHJcblxyXG4gICAgICAgIGNvbnN0IG1hdGNoID0gdXJsLm1hdGNoKHJlZ0V4KTtcclxuXHJcbiAgICAgICAgaWYgKCFtYXRjaCkge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRDb25maWd1cmF0aW9uRXJyb3IuY3JlYXRlVXJsUGFyc2VFcnJvcihgR2l2ZW4gdXJsIHN0cmluZzogJHt1cmx9YCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gbWF0Y2hbMl07XHJcbiAgICB9XHJcblxyXG4gICAgc3RhdGljIGdldEFic29sdXRlVXJsKHJlbGF0aXZlVXJsOiBzdHJpbmcsIGJhc2VVcmw6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgaWYgKHJlbGF0aXZlVXJsWzBdID09PSBDb25zdGFudHMuRk9SV0FSRF9TTEFTSCkge1xyXG4gICAgICAgICAgICBjb25zdCB1cmwgPSBuZXcgVXJsU3RyaW5nKGJhc2VVcmwpO1xyXG4gICAgICAgICAgICBjb25zdCBiYXNlQ29tcG9uZW50cyA9IHVybC5nZXRVcmxDb21wb25lbnRzKCk7XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gYmFzZUNvbXBvbmVudHMuUHJvdG9jb2wgKyBcIi8vXCIgKyBiYXNlQ29tcG9uZW50cy5Ib3N0TmFtZUFuZFBvcnQgKyByZWxhdGl2ZVVybDtcclxuICAgICAgICB9XHJcbiAgICAgICAgXHJcbiAgICAgICAgcmV0dXJuIHJlbGF0aXZlVXJsO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvKipcclxuICAgICAqIFBhcnNlcyBoYXNoIHN0cmluZyBmcm9tIGdpdmVuIHN0cmluZy4gUmV0dXJucyBlbXB0eSBzdHJpbmcgaWYgbm8gaGFzaCBzeW1ib2wgaXMgZm91bmQuXHJcbiAgICAgKiBAcGFyYW0gaGFzaFN0cmluZyBcclxuICAgICAqL1xyXG4gICAgc3RhdGljIHBhcnNlSGFzaChoYXNoU3RyaW5nOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIGNvbnN0IGhhc2hJbmRleDEgPSBoYXNoU3RyaW5nLmluZGV4T2YoXCIjXCIpO1xyXG4gICAgICAgIGNvbnN0IGhhc2hJbmRleDIgPSBoYXNoU3RyaW5nLmluZGV4T2YoXCIjL1wiKTtcclxuICAgICAgICBpZiAoaGFzaEluZGV4MiA+IC0xKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBoYXNoU3RyaW5nLnN1YnN0cmluZyhoYXNoSW5kZXgyICsgMik7XHJcbiAgICAgICAgfSBlbHNlIGlmIChoYXNoSW5kZXgxID4gLTEpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGhhc2hTdHJpbmcuc3Vic3RyaW5nKGhhc2hJbmRleDEgKyAxKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIFwiXCI7XHJcbiAgICB9XHJcblxyXG4gICAgc3RhdGljIGNvbnN0cnVjdEF1dGhvcml0eVVyaUZyb21PYmplY3QodXJsT2JqZWN0OiBJVXJpKTogVXJsU3RyaW5nIHtcclxuICAgICAgICByZXR1cm4gbmV3IFVybFN0cmluZyh1cmxPYmplY3QuUHJvdG9jb2wgKyBcIi8vXCIgKyB1cmxPYmplY3QuSG9zdE5hbWVBbmRQb3J0ICsgXCIvXCIgKyB1cmxPYmplY3QuUGF0aFNlZ21lbnRzLmpvaW4oXCIvXCIpKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgVVJMIGhhc2ggYXMgc2VydmVyIGF1dGggY29kZSByZXNwb25zZSBvYmplY3QuXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBnZXREZXNlcmlhbGl6ZWRIYXNoKGhhc2g6IHN0cmluZyk6IFNlcnZlckF1dGhvcml6YXRpb25Db2RlUmVzcG9uc2Uge1xyXG4gICAgICAgIC8vIENoZWNrIGlmIGdpdmVuIGhhc2ggaXMgZW1wdHlcclxuICAgICAgICBpZiAoU3RyaW5nVXRpbHMuaXNFbXB0eShoYXNoKSkge1xyXG4gICAgICAgICAgICByZXR1cm4ge307XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIFN0cmlwIHRoZSAjIHN5bWJvbCBpZiBwcmVzZW50XHJcbiAgICAgICAgY29uc3QgcGFyc2VkSGFzaCA9IFVybFN0cmluZy5wYXJzZUhhc2goaGFzaCk7XHJcbiAgICAgICAgLy8gSWYgIyBzeW1ib2wgd2FzIG5vdCBwcmVzZW50LCBhYm92ZSB3aWxsIHJldHVybiBlbXB0eSBzdHJpbmcsIHNvIGdpdmUgb3JpZ2luYWwgaGFzaCB2YWx1ZVxyXG4gICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZEhhc2g6IFNlcnZlckF1dGhvcml6YXRpb25Db2RlUmVzcG9uc2UgPSBTdHJpbmdVdGlscy5xdWVyeVN0cmluZ1RvT2JqZWN0PFNlcnZlckF1dGhvcml6YXRpb25Db2RlUmVzcG9uc2U+KFN0cmluZ1V0aWxzLmlzRW1wdHkocGFyc2VkSGFzaCkgPyBoYXNoIDogcGFyc2VkSGFzaCk7XHJcbiAgICAgICAgLy8gQ2hlY2sgaWYgZGVzZXJpYWxpemF0aW9uIGRpZG4ndCB3b3JrXHJcbiAgICAgICAgaWYgKCFkZXNlcmlhbGl6ZWRIYXNoKSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVIYXNoTm90RGVzZXJpYWxpemVkRXJyb3IoSlNPTi5zdHJpbmdpZnkoZGVzZXJpYWxpemVkSGFzaCkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gZGVzZXJpYWxpemVkSGFzaDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENoZWNrIGlmIHRoZSBoYXNoIG9mIHRoZSBVUkwgc3RyaW5nIGNvbnRhaW5zIGtub3duIHByb3BlcnRpZXNcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGhhc2hDb250YWluc0tub3duUHJvcGVydGllcyhoYXNoOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgICAgICBpZiAoU3RyaW5nVXRpbHMuaXNFbXB0eShoYXNoKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBwYXJhbWV0ZXJzOiBTZXJ2ZXJBdXRob3JpemF0aW9uQ29kZVJlc3BvbnNlID0gVXJsU3RyaW5nLmdldERlc2VyaWFsaXplZEhhc2goaGFzaCk7XHJcbiAgICAgICAgcmV0dXJuICEhKFxyXG4gICAgICAgICAgICBwYXJhbWV0ZXJzLmNvZGUgfHxcclxuICAgICAgICAgICAgcGFyYW1ldGVycy5lcnJvcl9kZXNjcmlwdGlvbiB8fFxyXG4gICAgICAgICAgICBwYXJhbWV0ZXJzLmVycm9yIHx8XHJcbiAgICAgICAgICAgIHBhcmFtZXRlcnMuc3RhdGVcclxuICAgICAgICApO1xyXG4gICAgfVxyXG59XHJcbiIsIi8qXHJcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgSUNyeXB0byB9IGZyb20gXCIuL0lDcnlwdG9cIjtcclxuaW1wb3J0IHsgQXV0aFRva2VuIH0gZnJvbSBcIi4uL2FjY291bnQvQXV0aFRva2VuXCI7XHJcbmltcG9ydCB7IFRva2VuQ2xhaW1zIH0gZnJvbSBcIi4uL2FjY291bnQvVG9rZW5DbGFpbXNcIjtcclxuaW1wb3J0IHsgVGltZVV0aWxzIH0gZnJvbSBcIi4uL3V0aWxzL1RpbWVVdGlsc1wiO1xyXG5pbXBvcnQgeyBVcmxTdHJpbmcgfSBmcm9tIFwiLi4vdXJsL1VybFN0cmluZ1wiO1xyXG5pbXBvcnQgeyBJVXJpIH0gZnJvbSBcIi4uL3VybC9JVXJpXCI7XHJcbmltcG9ydCB7IENsaWVudEF1dGhFcnJvciB9IGZyb20gXCIuLi9lcnJvci9DbGllbnRBdXRoRXJyb3JcIjtcclxuXHJcbi8qKlxyXG4gKiBTZWUgZVNUUyBkb2NzIGZvciBtb3JlIGluZm8uXHJcbiAqIC0gQSBraWQgZWxlbWVudCwgd2l0aCB0aGUgdmFsdWUgY29udGFpbmluZyBhbiBSRkMgNzYzOC1jb21wbGlhbnQgSldLIHRodW1icHJpbnQgdGhhdCBpcyBiYXNlNjQgZW5jb2RlZC5cclxuICogLSAgeG1zX2tzbCBlbGVtZW50LCByZXByZXNlbnRpbmcgdGhlIHN0b3JhZ2UgbG9jYXRpb24gb2YgdGhlIGtleSdzIHNlY3JldCBjb21wb25lbnQgb24gdGhlIGNsaWVudCBkZXZpY2UuIE9uZSBvZiB0d28gdmFsdWVzOlxyXG4gKiAgICAgIC0gc3c6IHNvZnR3YXJlIHN0b3JhZ2VcclxuICogICAgICAtIHVodzogaGFyZHdhcmUgc3RvcmFnZVxyXG4gKi9cclxudHlwZSBSZXFDbmYgPSB7XHJcbiAgICBraWQ6IHN0cmluZztcclxuICAgIHhtc19rc2w6IEtleUxvY2F0aW9uO1xyXG59O1xyXG5cclxuZW51bSBLZXlMb2NhdGlvbiB7XHJcbiAgICBTVyA9IFwic3dcIixcclxuICAgIFVIVyA9IFwidWh3XCJcclxufVxyXG5cclxuZXhwb3J0IGNsYXNzIFBvcFRva2VuR2VuZXJhdG9yIHtcclxuXHJcbiAgICBwcml2YXRlIGNyeXB0b1V0aWxzOiBJQ3J5cHRvO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKGNyeXB0b1V0aWxzOiBJQ3J5cHRvKSB7XHJcbiAgICAgICAgdGhpcy5jcnlwdG9VdGlscyA9IGNyeXB0b1V0aWxzO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGdlbmVyYXRlQ25mKHJlc291cmNlUmVxdWVzdE1ldGhvZDogc3RyaW5nLCByZXNvdXJjZVJlcXVlc3RVcmk6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XHJcbiAgICAgICAgY29uc3Qga2lkVGh1bWJwcmludCA9IGF3YWl0IHRoaXMuY3J5cHRvVXRpbHMuZ2V0UHVibGljS2V5VGh1bWJwcmludChyZXNvdXJjZVJlcXVlc3RNZXRob2QsIHJlc291cmNlUmVxdWVzdFVyaSk7XHJcbiAgICAgICAgY29uc3QgcmVxQ25mOiBSZXFDbmYgPSB7XHJcbiAgICAgICAgICAgIGtpZDoga2lkVGh1bWJwcmludCxcclxuICAgICAgICAgICAgeG1zX2tzbDogS2V5TG9jYXRpb24uU1dcclxuICAgICAgICB9O1xyXG4gICAgICAgIHJldHVybiB0aGlzLmNyeXB0b1V0aWxzLmJhc2U2NEVuY29kZShKU09OLnN0cmluZ2lmeShyZXFDbmYpKTtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBzaWduUG9wVG9rZW4oYWNjZXNzVG9rZW46IHN0cmluZywgcmVzb3VyY2VSZXF1ZXN0TWV0aG9kOiBzdHJpbmcsIHJlc291cmNlUmVxdWVzdFVyaTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcclxuICAgICAgICBjb25zdCB0b2tlbkNsYWltczogVG9rZW5DbGFpbXMgfCBudWxsID0gQXV0aFRva2VuLmV4dHJhY3RUb2tlbkNsYWltcyhhY2Nlc3NUb2tlbiwgdGhpcy5jcnlwdG9VdGlscyk7XHJcbiAgICAgICAgY29uc3QgcmVzb3VyY2VVcmxTdHJpbmc6IFVybFN0cmluZyA9IG5ldyBVcmxTdHJpbmcocmVzb3VyY2VSZXF1ZXN0VXJpKTtcclxuICAgICAgICBjb25zdCByZXNvdXJjZVVybENvbXBvbmVudHM6IElVcmkgPSByZXNvdXJjZVVybFN0cmluZy5nZXRVcmxDb21wb25lbnRzKCk7XHJcblxyXG4gICAgICAgIGlmICghdG9rZW5DbGFpbXM/LmNuZj8ua2lkKSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVUb2tlbkNsYWltc1JlcXVpcmVkRXJyb3IoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmNyeXB0b1V0aWxzLnNpZ25Kd3Qoe1xyXG4gICAgICAgICAgICBhdDogYWNjZXNzVG9rZW4sXHJcbiAgICAgICAgICAgIHRzOiBgJHtUaW1lVXRpbHMubm93U2Vjb25kcygpfWAsXHJcbiAgICAgICAgICAgIG06IHJlc291cmNlUmVxdWVzdE1ldGhvZC50b1VwcGVyQ2FzZSgpLFxyXG4gICAgICAgICAgICB1OiByZXNvdXJjZVVybENvbXBvbmVudHMuSG9zdE5hbWVBbmRQb3J0IHx8IFwiXCIsXHJcbiAgICAgICAgICAgIG5vbmNlOiB0aGlzLmNyeXB0b1V0aWxzLmNyZWF0ZU5ld0d1aWQoKSxcclxuICAgICAgICAgICAgcDogcmVzb3VyY2VVcmxDb21wb25lbnRzLkFic29sdXRlUGF0aCxcclxuICAgICAgICAgICAgcTogW1tdLCByZXNvdXJjZVVybENvbXBvbmVudHMuUXVlcnlTdHJpbmddLFxyXG4gICAgICAgIH0sIHRva2VuQ2xhaW1zLmNuZi5raWQpO1xyXG4gICAgfVxyXG59XHJcbiIsIi8qXHJcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgQVBQX01FVEFEQVRBLCBTZXBhcmF0b3JzIH0gZnJvbSBcIi4uLy4uL3V0aWxzL0NvbnN0YW50c1wiO1xyXG5cclxuLyoqXHJcbiAqIEFQUF9NRVRBREFUQSBDYWNoZVxyXG4gKlxyXG4gKiBLZXk6VmFsdWUgU2NoZW1hOlxyXG4gKlxyXG4gKiBLZXk6IGFwcG1ldGFkYXRhLTxlbnZpcm9ubWVudD4tPGNsaWVudF9pZD5cclxuICpcclxuICogVmFsdWU6XHJcbiAqIHtcclxuICogICAgICBjbGllbnRJZDogY2xpZW50IElEIG9mIHRoZSBhcHBsaWNhdGlvblxyXG4gKiAgICAgIGVudmlyb25tZW50OiBlbnRpdHkgdGhhdCBpc3N1ZWQgdGhlIHRva2VuLCByZXByZXNlbnRlZCBhcyBhIGZ1bGwgaG9zdFxyXG4gKiAgICAgIGZhbWlseUlkOiBGYW1pbHkgSUQgaWRlbnRpZmllciwgJzEnIHJlcHJlc2VudHMgTWljcm9zb2Z0IEZhbWlseVxyXG4gKiB9XHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgQXBwTWV0YWRhdGFFbnRpdHkge1xyXG4gICAgY2xpZW50SWQ6IHN0cmluZztcclxuICAgIGVudmlyb25tZW50OiBzdHJpbmc7XHJcbiAgICBmYW1pbHlJZD86IHN0cmluZztcclxuXHJcbiAgICAvKipcclxuICAgICAqIEdlbmVyYXRlIEFwcE1ldGFkYXRhIENhY2hlIEtleSBhcyBwZXIgdGhlIHNjaGVtYTogYXBwbWV0YWRhdGEtPGVudmlyb25tZW50Pi08Y2xpZW50X2lkPlxyXG4gICAgICovXHJcbiAgICBnZW5lcmF0ZUFwcE1ldGFkYXRhS2V5KCk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIEFwcE1ldGFkYXRhRW50aXR5LmdlbmVyYXRlQXBwTWV0YWRhdGFDYWNoZUtleSh0aGlzLmVudmlyb25tZW50LCB0aGlzLmNsaWVudElkKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdlbmVyYXRlIEFwcE1ldGFkYXRhIENhY2hlIEtleVxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgZ2VuZXJhdGVBcHBNZXRhZGF0YUNhY2hlS2V5KGVudmlyb25tZW50OiBzdHJpbmcsIGNsaWVudElkOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIGNvbnN0IGFwcE1ldGFEYXRhS2V5QXJyYXk6IEFycmF5PHN0cmluZz4gPSBbXHJcbiAgICAgICAgICAgIEFQUF9NRVRBREFUQSxcclxuICAgICAgICAgICAgZW52aXJvbm1lbnQsXHJcbiAgICAgICAgICAgIGNsaWVudElkLFxyXG4gICAgICAgIF07XHJcbiAgICAgICAgcmV0dXJuIGFwcE1ldGFEYXRhS2V5QXJyYXkuam9pbihTZXBhcmF0b3JzLkNBQ0hFX0tFWV9TRVBBUkFUT1IpLnRvTG93ZXJDYXNlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIEFwcE1ldGFkYXRhRW50aXR5XHJcbiAgICAgKiBAcGFyYW0gY2xpZW50SWRcclxuICAgICAqIEBwYXJhbSBlbnZpcm9ubWVudFxyXG4gICAgICogQHBhcmFtIGZhbWlseUlkXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVBcHBNZXRhZGF0YUVudGl0eShjbGllbnRJZDogc3RyaW5nLCBlbnZpcm9ubWVudDogc3RyaW5nLCBmYW1pbHlJZD86IHN0cmluZyk6IEFwcE1ldGFkYXRhRW50aXR5IHtcclxuICAgICAgICBjb25zdCBhcHBNZXRhZGF0YSA9IG5ldyBBcHBNZXRhZGF0YUVudGl0eSgpO1xyXG5cclxuICAgICAgICBhcHBNZXRhZGF0YS5jbGllbnRJZCA9IGNsaWVudElkO1xyXG4gICAgICAgIGFwcE1ldGFkYXRhLmVudmlyb25tZW50ID0gZW52aXJvbm1lbnQ7XHJcbiAgICAgICAgaWYgKGZhbWlseUlkKSB7XHJcbiAgICAgICAgICAgIGFwcE1ldGFkYXRhLmZhbWlseUlkID0gZmFtaWx5SWQ7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gYXBwTWV0YWRhdGE7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBWYWxpZGF0ZXMgYW4gZW50aXR5OiBjaGVja3MgZm9yIGFsbCBleHBlY3RlZCBwYXJhbXNcclxuICAgICAqIEBwYXJhbSBlbnRpdHlcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGlzQXBwTWV0YWRhdGFFbnRpdHkoa2V5OiBzdHJpbmcsIGVudGl0eTogb2JqZWN0KTogYm9vbGVhbiB7XHJcblxyXG4gICAgICAgIGlmICghZW50aXR5KSB7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgIGtleS5pbmRleE9mKEFQUF9NRVRBREFUQSkgPT09IDAgJiZcclxuICAgICAgICAgICAgZW50aXR5Lmhhc093blByb3BlcnR5KFwiY2xpZW50SWRcIikgJiZcclxuICAgICAgICAgICAgZW50aXR5Lmhhc093blByb3BlcnR5KFwiZW52aXJvbm1lbnRcIilcclxuICAgICAgICApO1xyXG4gICAgfVxyXG59XHJcbiIsIi8qXHJcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgSVNlcmlhbGl6YWJsZVRva2VuQ2FjaGUgfSBmcm9tIFwiLi4vaW50ZXJmYWNlL0lTZXJpYWxpemFibGVUb2tlbkNhY2hlXCI7XHJcblxyXG4vKipcclxuICogVGhpcyBjbGFzcyBpbnN0YW5jZSBoZWxwcyB0cmFjayB0aGUgbWVtb3J5IGNoYW5nZXMgZmFjaWxpdGF0aW5nXHJcbiAqIGRlY2lzaW9ucyB0byByZWFkIGZyb20gYW5kIHdyaXRlIHRvIHRoZSBwZXJzaXN0ZW50IGNhY2hlXHJcbiAqL2V4cG9ydCBjbGFzcyBUb2tlbkNhY2hlQ29udGV4dCB7XHJcbiAgICAvKipcclxuICAgICAqIGJvb2xlYW4gaW5kaWNhdGluZyBjYWNoZSBjaGFuZ2VcclxuICAgICAqL1xyXG4gICAgaGFzQ2hhbmdlZDogYm9vbGVhbjtcclxuICAgIC8qKlxyXG4gICAgICogc2VyaWFsaXphYmxlIHRva2VuIGNhY2hlIGludGVyZmFjZVxyXG4gICAgICovXHJcbiAgICBjYWNoZTogSVNlcmlhbGl6YWJsZVRva2VuQ2FjaGU7XHJcblxyXG4gICAgY29uc3RydWN0b3IodG9rZW5DYWNoZTogSVNlcmlhbGl6YWJsZVRva2VuQ2FjaGUsIGhhc0NoYW5nZWQ6IGJvb2xlYW4pIHtcclxuICAgICAgICB0aGlzLmNhY2hlID0gdG9rZW5DYWNoZTtcclxuICAgICAgICB0aGlzLmhhc0NoYW5nZWQgPSBoYXNDaGFuZ2VkO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogYm9vbGVhbiB3aGljaCBpbmRpY2F0ZXMgdGhlIGNoYW5nZXMgaW4gY2FjaGVcclxuICAgICAqL1xyXG4gICAgZ2V0IGNhY2hlSGFzQ2hhbmdlZCgpOiBib29sZWFuIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5oYXNDaGFuZ2VkO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogZnVuY3Rpb24gdG8gcmV0cmlldmUgdGhlIHRva2VuIGNhY2hlXHJcbiAgICAgKi9cclxuICAgIGdldCB0b2tlbkNhY2hlKCk6IElTZXJpYWxpemFibGVUb2tlbkNhY2hlIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5jYWNoZTtcclxuICAgIH1cclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IFNlcnZlckF1dGhvcml6YXRpb25Ub2tlblJlc3BvbnNlIH0gZnJvbSBcIi4vU2VydmVyQXV0aG9yaXphdGlvblRva2VuUmVzcG9uc2VcIjtcclxuaW1wb3J0IHsgYnVpbGRDbGllbnRJbmZvfSBmcm9tIFwiLi4vYWNjb3VudC9DbGllbnRJbmZvXCI7XHJcbmltcG9ydCB7IElDcnlwdG8gfSBmcm9tIFwiLi4vY3J5cHRvL0lDcnlwdG9cIjtcclxuaW1wb3J0IHsgQ2xpZW50QXV0aEVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL0NsaWVudEF1dGhFcnJvclwiO1xyXG5pbXBvcnQgeyBTdHJpbmdVdGlscyB9IGZyb20gXCIuLi91dGlscy9TdHJpbmdVdGlsc1wiO1xyXG5pbXBvcnQgeyBTZXJ2ZXJBdXRob3JpemF0aW9uQ29kZVJlc3BvbnNlIH0gZnJvbSBcIi4vU2VydmVyQXV0aG9yaXphdGlvbkNvZGVSZXNwb25zZVwiO1xyXG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tIFwiLi4vbG9nZ2VyL0xvZ2dlclwiO1xyXG5pbXBvcnQgeyBTZXJ2ZXJFcnJvciB9IGZyb20gXCIuLi9lcnJvci9TZXJ2ZXJFcnJvclwiO1xyXG5pbXBvcnQgeyBBdXRoVG9rZW4gfSBmcm9tIFwiLi4vYWNjb3VudC9BdXRoVG9rZW5cIjtcclxuaW1wb3J0IHsgU2NvcGVTZXQgfSBmcm9tIFwiLi4vcmVxdWVzdC9TY29wZVNldFwiO1xyXG5pbXBvcnQgeyBBdXRoZW50aWNhdGlvblJlc3VsdCB9IGZyb20gXCIuL0F1dGhlbnRpY2F0aW9uUmVzdWx0XCI7XHJcbmltcG9ydCB7IEFjY291bnRFbnRpdHkgfSBmcm9tIFwiLi4vY2FjaGUvZW50aXRpZXMvQWNjb3VudEVudGl0eVwiO1xyXG5pbXBvcnQgeyBBdXRob3JpdHkgfSBmcm9tIFwiLi4vYXV0aG9yaXR5L0F1dGhvcml0eVwiO1xyXG5pbXBvcnQgeyBBdXRob3JpdHlUeXBlIH0gZnJvbSBcIi4uL2F1dGhvcml0eS9BdXRob3JpdHlUeXBlXCI7XHJcbmltcG9ydCB7IElkVG9rZW5FbnRpdHkgfSBmcm9tIFwiLi4vY2FjaGUvZW50aXRpZXMvSWRUb2tlbkVudGl0eVwiO1xyXG5pbXBvcnQgeyBBY2Nlc3NUb2tlbkVudGl0eSB9IGZyb20gXCIuLi9jYWNoZS9lbnRpdGllcy9BY2Nlc3NUb2tlbkVudGl0eVwiO1xyXG5pbXBvcnQgeyBSZWZyZXNoVG9rZW5FbnRpdHkgfSBmcm9tIFwiLi4vY2FjaGUvZW50aXRpZXMvUmVmcmVzaFRva2VuRW50aXR5XCI7XHJcbmltcG9ydCB7IEludGVyYWN0aW9uUmVxdWlyZWRBdXRoRXJyb3IgfSBmcm9tIFwiLi4vZXJyb3IvSW50ZXJhY3Rpb25SZXF1aXJlZEF1dGhFcnJvclwiO1xyXG5pbXBvcnQgeyBDYWNoZVJlY29yZCB9IGZyb20gXCIuLi9jYWNoZS9lbnRpdGllcy9DYWNoZVJlY29yZFwiO1xyXG5pbXBvcnQgeyBDYWNoZU1hbmFnZXIgfSBmcm9tIFwiLi4vY2FjaGUvQ2FjaGVNYW5hZ2VyXCI7XHJcbmltcG9ydCB7IFByb3RvY29sVXRpbHMsIFJlcXVlc3RTdGF0ZU9iamVjdCB9IGZyb20gXCIuLi91dGlscy9Qcm90b2NvbFV0aWxzXCI7XHJcbmltcG9ydCB7IEF1dGhlbnRpY2F0aW9uU2NoZW1lLCBDb25zdGFudHMsIFRIRV9GQU1JTFlfSUQgfSBmcm9tIFwiLi4vdXRpbHMvQ29uc3RhbnRzXCI7XHJcbmltcG9ydCB7IFBvcFRva2VuR2VuZXJhdG9yIH0gZnJvbSBcIi4uL2NyeXB0by9Qb3BUb2tlbkdlbmVyYXRvclwiO1xyXG5pbXBvcnQgeyBBcHBNZXRhZGF0YUVudGl0eSB9IGZyb20gXCIuLi9jYWNoZS9lbnRpdGllcy9BcHBNZXRhZGF0YUVudGl0eVwiO1xyXG5pbXBvcnQgeyBJQ2FjaGVQbHVnaW4gfSBmcm9tIFwiLi4vY2FjaGUvaW50ZXJmYWNlL0lDYWNoZVBsdWdpblwiO1xyXG5pbXBvcnQgeyBUb2tlbkNhY2hlQ29udGV4dCB9IGZyb20gXCIuLi9jYWNoZS9wZXJzaXN0ZW5jZS9Ub2tlbkNhY2hlQ29udGV4dFwiO1xyXG5pbXBvcnQgeyBJU2VyaWFsaXphYmxlVG9rZW5DYWNoZSB9IGZyb20gXCIuLi9jYWNoZS9pbnRlcmZhY2UvSVNlcmlhbGl6YWJsZVRva2VuQ2FjaGVcIjtcclxuaW1wb3J0IHsgQXV0aG9yaXphdGlvbkNvZGVQYXlsb2FkIH0gZnJvbSBcIi4vQXV0aG9yaXphdGlvbkNvZGVQYXlsb2FkXCI7XHJcbmltcG9ydCB7IENsaWVudENvbmZpZ3VyYXRpb25FcnJvciB9IGZyb20gXCIuLi9lcnJvci9DbGllbnRDb25maWd1cmF0aW9uRXJyb3JcIjtcclxuXHJcbi8qKlxyXG4gKiBDbGFzcyB0aGF0IGhhbmRsZXMgcmVzcG9uc2UgcGFyc2luZy5cclxuICovXHJcbmV4cG9ydCBjbGFzcyBSZXNwb25zZUhhbmRsZXIge1xyXG4gICAgcHJpdmF0ZSBjbGllbnRJZDogc3RyaW5nO1xyXG4gICAgcHJpdmF0ZSBjYWNoZVN0b3JhZ2U6IENhY2hlTWFuYWdlcjtcclxuICAgIHByaXZhdGUgY3J5cHRvT2JqOiBJQ3J5cHRvO1xyXG4gICAgcHJpdmF0ZSBsb2dnZXI6IExvZ2dlcjtcclxuICAgIHByaXZhdGUgaG9tZUFjY291bnRJZGVudGlmaWVyOiBzdHJpbmc7XHJcbiAgICBwcml2YXRlIHNlcmlhbGl6YWJsZUNhY2hlOiBJU2VyaWFsaXphYmxlVG9rZW5DYWNoZSB8IG51bGw7XHJcbiAgICBwcml2YXRlIHBlcnNpc3RlbmNlUGx1Z2luOiBJQ2FjaGVQbHVnaW4gfCBudWxsO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKGNsaWVudElkOiBzdHJpbmcsIGNhY2hlU3RvcmFnZTogQ2FjaGVNYW5hZ2VyLCBjcnlwdG9PYmo6IElDcnlwdG8sIGxvZ2dlcjogTG9nZ2VyLCBzZXJpYWxpemFibGVDYWNoZTogSVNlcmlhbGl6YWJsZVRva2VuQ2FjaGUgfCBudWxsLCBwZXJzaXN0ZW5jZVBsdWdpbjogSUNhY2hlUGx1Z2luIHwgbnVsbCkge1xyXG4gICAgICAgIHRoaXMuY2xpZW50SWQgPSBjbGllbnRJZDtcclxuICAgICAgICB0aGlzLmNhY2hlU3RvcmFnZSA9IGNhY2hlU3RvcmFnZTtcclxuICAgICAgICB0aGlzLmNyeXB0b09iaiA9IGNyeXB0b09iajtcclxuICAgICAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlcjtcclxuICAgICAgICB0aGlzLnNlcmlhbGl6YWJsZUNhY2hlID0gc2VyaWFsaXphYmxlQ2FjaGU7XHJcbiAgICAgICAgdGhpcy5wZXJzaXN0ZW5jZVBsdWdpbiA9IHBlcnNpc3RlbmNlUGx1Z2luO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRnVuY3Rpb24gd2hpY2ggdmFsaWRhdGVzIHNlcnZlciBhdXRob3JpemF0aW9uIGNvZGUgcmVzcG9uc2UuXHJcbiAgICAgKiBAcGFyYW0gc2VydmVyUmVzcG9uc2VIYXNoXHJcbiAgICAgKiBAcGFyYW0gY2FjaGVkU3RhdGVcclxuICAgICAqIEBwYXJhbSBjcnlwdG9PYmpcclxuICAgICAqL1xyXG4gICAgdmFsaWRhdGVTZXJ2ZXJBdXRob3JpemF0aW9uQ29kZVJlc3BvbnNlKHNlcnZlclJlc3BvbnNlSGFzaDogU2VydmVyQXV0aG9yaXphdGlvbkNvZGVSZXNwb25zZSwgY2FjaGVkU3RhdGU6IHN0cmluZywgY3J5cHRvT2JqOiBJQ3J5cHRvKTogdm9pZCB7XHJcblxyXG4gICAgICAgIGlmICghc2VydmVyUmVzcG9uc2VIYXNoLnN0YXRlIHx8ICFjYWNoZWRTdGF0ZSkge1xyXG4gICAgICAgICAgICB0aHJvdyAhc2VydmVyUmVzcG9uc2VIYXNoLnN0YXRlID8gQ2xpZW50QXV0aEVycm9yLmNyZWF0ZVN0YXRlTm90Rm91bmRFcnJvcihcIlNlcnZlciBTdGF0ZVwiKSA6IENsaWVudEF1dGhFcnJvci5jcmVhdGVTdGF0ZU5vdEZvdW5kRXJyb3IoXCJDYWNoZWQgU3RhdGVcIik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoZGVjb2RlVVJJQ29tcG9uZW50KHNlcnZlclJlc3BvbnNlSGFzaC5zdGF0ZSkgIT09IGRlY29kZVVSSUNvbXBvbmVudChjYWNoZWRTdGF0ZSkpIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50QXV0aEVycm9yLmNyZWF0ZVN0YXRlTWlzbWF0Y2hFcnJvcigpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gQ2hlY2sgZm9yIGVycm9yXHJcbiAgICAgICAgaWYgKHNlcnZlclJlc3BvbnNlSGFzaC5lcnJvciB8fCBzZXJ2ZXJSZXNwb25zZUhhc2guZXJyb3JfZGVzY3JpcHRpb24gfHwgc2VydmVyUmVzcG9uc2VIYXNoLnN1YmVycm9yKSB7XHJcbiAgICAgICAgICAgIGlmIChJbnRlcmFjdGlvblJlcXVpcmVkQXV0aEVycm9yLmlzSW50ZXJhY3Rpb25SZXF1aXJlZEVycm9yKHNlcnZlclJlc3BvbnNlSGFzaC5lcnJvciwgc2VydmVyUmVzcG9uc2VIYXNoLmVycm9yX2Rlc2NyaXB0aW9uLCBzZXJ2ZXJSZXNwb25zZUhhc2guc3ViZXJyb3IpKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJhY3Rpb25SZXF1aXJlZEF1dGhFcnJvcihzZXJ2ZXJSZXNwb25zZUhhc2guZXJyb3IgfHwgQ29uc3RhbnRzLkVNUFRZX1NUUklORywgc2VydmVyUmVzcG9uc2VIYXNoLmVycm9yX2Rlc2NyaXB0aW9uLCBzZXJ2ZXJSZXNwb25zZUhhc2guc3ViZXJyb3IpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB0aHJvdyBuZXcgU2VydmVyRXJyb3Ioc2VydmVyUmVzcG9uc2VIYXNoLmVycm9yIHx8IENvbnN0YW50cy5FTVBUWV9TVFJJTkcsIHNlcnZlclJlc3BvbnNlSGFzaC5lcnJvcl9kZXNjcmlwdGlvbiwgc2VydmVyUmVzcG9uc2VIYXNoLnN1YmVycm9yKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChzZXJ2ZXJSZXNwb25zZUhhc2guY2xpZW50X2luZm8pIHtcclxuICAgICAgICAgICAgYnVpbGRDbGllbnRJbmZvKHNlcnZlclJlc3BvbnNlSGFzaC5jbGllbnRfaW5mbywgY3J5cHRvT2JqKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBGdW5jdGlvbiB3aGljaCB2YWxpZGF0ZXMgc2VydmVyIGF1dGhvcml6YXRpb24gdG9rZW4gcmVzcG9uc2UuXHJcbiAgICAgKiBAcGFyYW0gc2VydmVyUmVzcG9uc2VcclxuICAgICAqL1xyXG4gICAgdmFsaWRhdGVUb2tlblJlc3BvbnNlKHNlcnZlclJlc3BvbnNlOiBTZXJ2ZXJBdXRob3JpemF0aW9uVG9rZW5SZXNwb25zZSk6IHZvaWQge1xyXG4gICAgICAgIC8vIENoZWNrIGZvciBlcnJvclxyXG4gICAgICAgIGlmIChzZXJ2ZXJSZXNwb25zZS5lcnJvciB8fCBzZXJ2ZXJSZXNwb25zZS5lcnJvcl9kZXNjcmlwdGlvbiB8fCBzZXJ2ZXJSZXNwb25zZS5zdWJlcnJvcikge1xyXG4gICAgICAgICAgICBpZiAoSW50ZXJhY3Rpb25SZXF1aXJlZEF1dGhFcnJvci5pc0ludGVyYWN0aW9uUmVxdWlyZWRFcnJvcihzZXJ2ZXJSZXNwb25zZS5lcnJvciwgc2VydmVyUmVzcG9uc2UuZXJyb3JfZGVzY3JpcHRpb24sIHNlcnZlclJlc3BvbnNlLnN1YmVycm9yKSkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEludGVyYWN0aW9uUmVxdWlyZWRBdXRoRXJyb3Ioc2VydmVyUmVzcG9uc2UuZXJyb3IsIHNlcnZlclJlc3BvbnNlLmVycm9yX2Rlc2NyaXB0aW9uLCBzZXJ2ZXJSZXNwb25zZS5zdWJlcnJvcik7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGVyclN0cmluZyA9IGAke3NlcnZlclJlc3BvbnNlLmVycm9yX2NvZGVzfSAtIFske3NlcnZlclJlc3BvbnNlLnRpbWVzdGFtcH1dOiAke3NlcnZlclJlc3BvbnNlLmVycm9yX2Rlc2NyaXB0aW9ufSAtIENvcnJlbGF0aW9uIElEOiAke3NlcnZlclJlc3BvbnNlLmNvcnJlbGF0aW9uX2lkfSAtIFRyYWNlIElEOiAke3NlcnZlclJlc3BvbnNlLnRyYWNlX2lkfWA7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBTZXJ2ZXJFcnJvcihzZXJ2ZXJSZXNwb25zZS5lcnJvciwgZXJyU3RyaW5nKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIGEgY29uc3RydWN0ZWQgdG9rZW4gcmVzcG9uc2UgYmFzZWQgb24gZ2l2ZW4gc3RyaW5nLiBBbHNvIG1hbmFnZXMgdGhlIGNhY2hlIHVwZGF0ZXMgYW5kIGNsZWFudXBzLlxyXG4gICAgICogQHBhcmFtIHNlcnZlclRva2VuUmVzcG9uc2VcclxuICAgICAqIEBwYXJhbSBhdXRob3JpdHlcclxuICAgICAqL1xyXG4gICAgYXN5bmMgaGFuZGxlU2VydmVyVG9rZW5SZXNwb25zZShcclxuICAgICAgICBzZXJ2ZXJUb2tlblJlc3BvbnNlOiBTZXJ2ZXJBdXRob3JpemF0aW9uVG9rZW5SZXNwb25zZSxcclxuICAgICAgICBhdXRob3JpdHk6IEF1dGhvcml0eSxcclxuICAgICAgICByZXFUaW1lc3RhbXA6IG51bWJlcixcclxuICAgICAgICByZXNvdXJjZVJlcXVlc3RNZXRob2Q/OiBzdHJpbmcsXHJcbiAgICAgICAgcmVzb3VyY2VSZXF1ZXN0VXJpPzogc3RyaW5nLFxyXG4gICAgICAgIGF1dGhDb2RlUGF5bG9hZD86IEF1dGhvcml6YXRpb25Db2RlUGF5bG9hZCxcclxuICAgICAgICByZXF1ZXN0U2NvcGVzPzogc3RyaW5nW10sXHJcbiAgICAgICAgb2JvQXNzZXJ0aW9uPzogc3RyaW5nLFxyXG4gICAgICAgIGhhbmRsaW5nUmVmcmVzaFRva2VuUmVzcG9uc2U/OiBib29sZWFuKTogUHJvbWlzZTxBdXRoZW50aWNhdGlvblJlc3VsdD4ge1xyXG5cclxuICAgICAgICAvLyBjcmVhdGUgYW4gaWRUb2tlbiBvYmplY3QgKG5vdCBlbnRpdHkpXHJcbiAgICAgICAgbGV0IGlkVG9rZW5PYmo6IEF1dGhUb2tlbiB8IHVuZGVmaW5lZDtcclxuICAgICAgICBpZiAoc2VydmVyVG9rZW5SZXNwb25zZS5pZF90b2tlbikge1xyXG4gICAgICAgICAgICBpZFRva2VuT2JqID0gbmV3IEF1dGhUb2tlbihzZXJ2ZXJUb2tlblJlc3BvbnNlLmlkX3Rva2VuIHx8IENvbnN0YW50cy5FTVBUWV9TVFJJTkcsIHRoaXMuY3J5cHRvT2JqKTtcclxuICAgIFxyXG4gICAgICAgICAgICAvLyB0b2tlbiBub25jZSBjaGVjayAoVE9ETzogQWRkIGEgd2FybmluZyBpZiBubyBub25jZSBpcyBnaXZlbj8pXHJcbiAgICAgICAgICAgIGlmIChhdXRoQ29kZVBheWxvYWQgJiYgIVN0cmluZ1V0aWxzLmlzRW1wdHkoYXV0aENvZGVQYXlsb2FkLm5vbmNlKSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKGlkVG9rZW5PYmouY2xhaW1zLm5vbmNlICE9PSBhdXRoQ29kZVBheWxvYWQubm9uY2UpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBDbGllbnRBdXRoRXJyb3IuY3JlYXRlTm9uY2VNaXNtYXRjaEVycm9yKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIGdlbmVyYXRlIGhvbWVBY2NvdW50SWRcclxuICAgICAgICB0aGlzLmhvbWVBY2NvdW50SWRlbnRpZmllciA9IEFjY291bnRFbnRpdHkuZ2VuZXJhdGVIb21lQWNjb3VudElkKHNlcnZlclRva2VuUmVzcG9uc2UuY2xpZW50X2luZm8gfHwgQ29uc3RhbnRzLkVNUFRZX1NUUklORywgYXV0aG9yaXR5LmF1dGhvcml0eVR5cGUsIHRoaXMubG9nZ2VyLCB0aGlzLmNyeXB0b09iaiwgaWRUb2tlbk9iaik7XHJcblxyXG4gICAgICAgIC8vIHNhdmUgdGhlIHJlc3BvbnNlIHRva2Vuc1xyXG4gICAgICAgIGxldCByZXF1ZXN0U3RhdGVPYmo6IFJlcXVlc3RTdGF0ZU9iamVjdCB8IHVuZGVmaW5lZDtcclxuICAgICAgICBpZiAoISFhdXRoQ29kZVBheWxvYWQgJiYgISFhdXRoQ29kZVBheWxvYWQuc3RhdGUpIHtcclxuICAgICAgICAgICAgcmVxdWVzdFN0YXRlT2JqID0gUHJvdG9jb2xVdGlscy5wYXJzZVJlcXVlc3RTdGF0ZSh0aGlzLmNyeXB0b09iaiwgYXV0aENvZGVQYXlsb2FkLnN0YXRlKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGNhY2hlUmVjb3JkID0gdGhpcy5nZW5lcmF0ZUNhY2hlUmVjb3JkKHNlcnZlclRva2VuUmVzcG9uc2UsIGF1dGhvcml0eSwgcmVxVGltZXN0YW1wLCBpZFRva2VuT2JqLCByZXF1ZXN0U2NvcGVzLCBvYm9Bc3NlcnRpb24sIGF1dGhDb2RlUGF5bG9hZCk7XHJcbiAgICAgICAgbGV0IGNhY2hlQ29udGV4dDtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5wZXJzaXN0ZW5jZVBsdWdpbiAmJiB0aGlzLnNlcmlhbGl6YWJsZUNhY2hlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci52ZXJib3NlKFwiUGVyc2lzdGVuY2UgZW5hYmxlZCwgY2FsbGluZyBiZWZvcmVDYWNoZUFjY2Vzc1wiKTtcclxuICAgICAgICAgICAgICAgIGNhY2hlQ29udGV4dCA9IG5ldyBUb2tlbkNhY2hlQ29udGV4dCh0aGlzLnNlcmlhbGl6YWJsZUNhY2hlLCB0cnVlKTtcclxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucGVyc2lzdGVuY2VQbHVnaW4uYmVmb3JlQ2FjaGVBY2Nlc3MoY2FjaGVDb250ZXh0KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAvKlxyXG4gICAgICAgICAgICAgKiBXaGVuIHNhdmluZyBhIHJlZnJlc2hlZCB0b2tlbnMgdG8gdGhlIGNhY2hlLCBpdCBpcyBleHBlY3RlZCB0aGF0IHRoZSBhY2NvdW50IHRoYXQgd2FzIHVzZWQgaXMgcHJlc2VudCBpbiB0aGUgY2FjaGUuXHJcbiAgICAgICAgICAgICAqIElmIG5vdCBwcmVzZW50LCB3ZSBzaG91bGQgcmV0dXJuIG51bGwsIGFzIGl0J3MgdGhlIGNhc2UgdGhhdCBhbm90aGVyIGFwcGxpY2F0aW9uIGNhbGxlZCByZW1vdmVBY2NvdW50IGluIGJldHdlZW5cclxuICAgICAgICAgICAgICogdGhlIGNhbGxzIHRvIGdldEFsbEFjY291bnRzIGFuZCBhY3F1aXJlVG9rZW5TaWxlbnQuIFdlIHNob3VsZCBub3Qgb3ZlcndyaXRlIHRoYXQgcmVtb3ZhbC5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmIChoYW5kbGluZ1JlZnJlc2hUb2tlblJlc3BvbnNlICYmIGNhY2hlUmVjb3JkLmFjY291bnQpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGtleSA9IGNhY2hlUmVjb3JkLmFjY291bnQuZ2VuZXJhdGVBY2NvdW50S2V5KCk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBhY2NvdW50ID0gdGhpcy5jYWNoZVN0b3JhZ2UuZ2V0QWNjb3VudChrZXkpO1xyXG4gICAgICAgICAgICAgICAgaWYgKCFhY2NvdW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIud2FybmluZyhcIkFjY291bnQgdXNlZCB0byByZWZyZXNoIHRva2VucyBub3QgaW4gcGVyc2lzdGVuY2UsIHJlZnJlc2hlZCB0b2tlbnMgd2lsbCBub3QgYmUgc3RvcmVkIGluIHRoZSBjYWNoZVwiKTtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gUmVzcG9uc2VIYW5kbGVyLmdlbmVyYXRlQXV0aGVudGljYXRpb25SZXN1bHQodGhpcy5jcnlwdG9PYmosIGF1dGhvcml0eSwgY2FjaGVSZWNvcmQsIGZhbHNlLCBpZFRva2VuT2JqLCByZXF1ZXN0U3RhdGVPYmosIHJlc291cmNlUmVxdWVzdE1ldGhvZCwgcmVzb3VyY2VSZXF1ZXN0VXJpKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB0aGlzLmNhY2hlU3RvcmFnZS5zYXZlQ2FjaGVSZWNvcmQoY2FjaGVSZWNvcmQpO1xyXG4gICAgICAgIH0gZmluYWxseSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLnBlcnNpc3RlbmNlUGx1Z2luICYmIHRoaXMuc2VyaWFsaXphYmxlQ2FjaGUgJiYgY2FjaGVDb250ZXh0KSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci52ZXJib3NlKFwiUGVyc2lzdGVuY2UgZW5hYmxlZCwgY2FsbGluZyBhZnRlckNhY2hlQWNjZXNzXCIpO1xyXG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wZXJzaXN0ZW5jZVBsdWdpbi5hZnRlckNhY2hlQWNjZXNzKGNhY2hlQ29udGV4dCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIFJlc3BvbnNlSGFuZGxlci5nZW5lcmF0ZUF1dGhlbnRpY2F0aW9uUmVzdWx0KHRoaXMuY3J5cHRvT2JqLCBhdXRob3JpdHksIGNhY2hlUmVjb3JkLCBmYWxzZSwgaWRUb2tlbk9iaiwgcmVxdWVzdFN0YXRlT2JqLCByZXNvdXJjZVJlcXVlc3RNZXRob2QsIHJlc291cmNlUmVxdWVzdFVyaSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZW5lcmF0ZXMgQ2FjaGVSZWNvcmRcclxuICAgICAqIEBwYXJhbSBzZXJ2ZXJUb2tlblJlc3BvbnNlXHJcbiAgICAgKiBAcGFyYW0gaWRUb2tlbk9ialxyXG4gICAgICogQHBhcmFtIGF1dGhvcml0eVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGdlbmVyYXRlQ2FjaGVSZWNvcmQoc2VydmVyVG9rZW5SZXNwb25zZTogU2VydmVyQXV0aG9yaXphdGlvblRva2VuUmVzcG9uc2UsIGF1dGhvcml0eTogQXV0aG9yaXR5LCByZXFUaW1lc3RhbXA6IG51bWJlciwgaWRUb2tlbk9iaj86IEF1dGhUb2tlbiwgcmVxdWVzdFNjb3Blcz86IHN0cmluZ1tdLCBvYm9Bc3NlcnRpb24/OiBzdHJpbmcsIGF1dGhDb2RlUGF5bG9hZD86IEF1dGhvcml6YXRpb25Db2RlUGF5bG9hZCk6IENhY2hlUmVjb3JkIHtcclxuICAgICAgICBjb25zdCBlbnYgPSBhdXRob3JpdHkuZ2V0UHJlZmVycmVkQ2FjaGUoKTtcclxuICAgICAgICBpZiAoU3RyaW5nVXRpbHMuaXNFbXB0eShlbnYpKSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVJbnZhbGlkQ2FjaGVFbnZpcm9ubWVudEVycm9yKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBJZFRva2VuOiBub24gQUFEIHNjZW5hcmlvcyBjYW4gaGF2ZSBlbXB0eSByZWFsbVxyXG4gICAgICAgIGxldCBjYWNoZWRJZFRva2VuOiBJZFRva2VuRW50aXR5IHwgdW5kZWZpbmVkO1xyXG4gICAgICAgIGxldCBjYWNoZWRBY2NvdW50OiBBY2NvdW50RW50aXR5IHwgdW5kZWZpbmVkO1xyXG4gICAgICAgIGlmICghU3RyaW5nVXRpbHMuaXNFbXB0eShzZXJ2ZXJUb2tlblJlc3BvbnNlLmlkX3Rva2VuKSAmJiAhIWlkVG9rZW5PYmopIHtcclxuICAgICAgICAgICAgY2FjaGVkSWRUb2tlbiA9IElkVG9rZW5FbnRpdHkuY3JlYXRlSWRUb2tlbkVudGl0eShcclxuICAgICAgICAgICAgICAgIHRoaXMuaG9tZUFjY291bnRJZGVudGlmaWVyLFxyXG4gICAgICAgICAgICAgICAgZW52LFxyXG4gICAgICAgICAgICAgICAgc2VydmVyVG9rZW5SZXNwb25zZS5pZF90b2tlbiB8fCBDb25zdGFudHMuRU1QVFlfU1RSSU5HLFxyXG4gICAgICAgICAgICAgICAgdGhpcy5jbGllbnRJZCxcclxuICAgICAgICAgICAgICAgIGlkVG9rZW5PYmouY2xhaW1zLnRpZCB8fCBDb25zdGFudHMuRU1QVFlfU1RSSU5HLFxyXG4gICAgICAgICAgICAgICAgb2JvQXNzZXJ0aW9uXHJcbiAgICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgICBjYWNoZWRBY2NvdW50ID0gdGhpcy5nZW5lcmF0ZUFjY291bnRFbnRpdHkoXHJcbiAgICAgICAgICAgICAgICBzZXJ2ZXJUb2tlblJlc3BvbnNlLFxyXG4gICAgICAgICAgICAgICAgaWRUb2tlbk9iaixcclxuICAgICAgICAgICAgICAgIGF1dGhvcml0eSxcclxuICAgICAgICAgICAgICAgIG9ib0Fzc2VydGlvbixcclxuICAgICAgICAgICAgICAgIGF1dGhDb2RlUGF5bG9hZFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gQWNjZXNzVG9rZW5cclxuICAgICAgICBsZXQgY2FjaGVkQWNjZXNzVG9rZW46IEFjY2Vzc1Rva2VuRW50aXR5IHwgbnVsbCA9IG51bGw7XHJcbiAgICAgICAgaWYgKCFTdHJpbmdVdGlscy5pc0VtcHR5KHNlcnZlclRva2VuUmVzcG9uc2UuYWNjZXNzX3Rva2VuKSkge1xyXG5cclxuICAgICAgICAgICAgLy8gSWYgc2NvcGVzIG5vdCByZXR1cm5lZCBpbiBzZXJ2ZXIgcmVzcG9uc2UsIHVzZSByZXF1ZXN0IHNjb3Blc1xyXG4gICAgICAgICAgICBjb25zdCByZXNwb25zZVNjb3BlcyA9IHNlcnZlclRva2VuUmVzcG9uc2Uuc2NvcGUgPyBTY29wZVNldC5mcm9tU3RyaW5nKHNlcnZlclRva2VuUmVzcG9uc2Uuc2NvcGUpIDogbmV3IFNjb3BlU2V0KHJlcXVlc3RTY29wZXMgfHwgW10pO1xyXG5cclxuICAgICAgICAgICAgLy8gVXNlIHRpbWVzdGFtcCBjYWxjdWxhdGVkIGJlZm9yZSByZXF1ZXN0XHJcbiAgICAgICAgICAgIGNvbnN0IHRva2VuRXhwaXJhdGlvblNlY29uZHMgPSByZXFUaW1lc3RhbXAgKyAoc2VydmVyVG9rZW5SZXNwb25zZS5leHBpcmVzX2luIHx8IDApO1xyXG4gICAgICAgICAgICBjb25zdCBleHRlbmRlZFRva2VuRXhwaXJhdGlvblNlY29uZHMgPSB0b2tlbkV4cGlyYXRpb25TZWNvbmRzICsgKHNlcnZlclRva2VuUmVzcG9uc2UuZXh0X2V4cGlyZXNfaW4gfHwgMCk7XHJcblxyXG4gICAgICAgICAgICAvLyBub24gQUFEIHNjZW5hcmlvcyBjYW4gaGF2ZSBlbXB0eSByZWFsbVxyXG4gICAgICAgICAgICBjYWNoZWRBY2Nlc3NUb2tlbiA9IEFjY2Vzc1Rva2VuRW50aXR5LmNyZWF0ZUFjY2Vzc1Rva2VuRW50aXR5KFxyXG4gICAgICAgICAgICAgICAgdGhpcy5ob21lQWNjb3VudElkZW50aWZpZXIsXHJcbiAgICAgICAgICAgICAgICBlbnYsXHJcbiAgICAgICAgICAgICAgICBzZXJ2ZXJUb2tlblJlc3BvbnNlLmFjY2Vzc190b2tlbiB8fCBDb25zdGFudHMuRU1QVFlfU1RSSU5HLFxyXG4gICAgICAgICAgICAgICAgdGhpcy5jbGllbnRJZCxcclxuICAgICAgICAgICAgICAgIGlkVG9rZW5PYmogPyBpZFRva2VuT2JqLmNsYWltcy50aWQgfHwgQ29uc3RhbnRzLkVNUFRZX1NUUklORyA6IGF1dGhvcml0eS50ZW5hbnQsXHJcbiAgICAgICAgICAgICAgICByZXNwb25zZVNjb3Blcy5wcmludFNjb3BlcygpLFxyXG4gICAgICAgICAgICAgICAgdG9rZW5FeHBpcmF0aW9uU2Vjb25kcyxcclxuICAgICAgICAgICAgICAgIGV4dGVuZGVkVG9rZW5FeHBpcmF0aW9uU2Vjb25kcyxcclxuICAgICAgICAgICAgICAgIHNlcnZlclRva2VuUmVzcG9uc2UudG9rZW5fdHlwZSxcclxuICAgICAgICAgICAgICAgIG9ib0Fzc2VydGlvblxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gcmVmcmVzaFRva2VuXHJcbiAgICAgICAgbGV0IGNhY2hlZFJlZnJlc2hUb2tlbjogUmVmcmVzaFRva2VuRW50aXR5IHwgbnVsbCA9IG51bGw7XHJcbiAgICAgICAgaWYgKCFTdHJpbmdVdGlscy5pc0VtcHR5KHNlcnZlclRva2VuUmVzcG9uc2UucmVmcmVzaF90b2tlbikpIHtcclxuICAgICAgICAgICAgY2FjaGVkUmVmcmVzaFRva2VuID0gUmVmcmVzaFRva2VuRW50aXR5LmNyZWF0ZVJlZnJlc2hUb2tlbkVudGl0eShcclxuICAgICAgICAgICAgICAgIHRoaXMuaG9tZUFjY291bnRJZGVudGlmaWVyLFxyXG4gICAgICAgICAgICAgICAgZW52LFxyXG4gICAgICAgICAgICAgICAgc2VydmVyVG9rZW5SZXNwb25zZS5yZWZyZXNoX3Rva2VuIHx8IENvbnN0YW50cy5FTVBUWV9TVFJJTkcsXHJcbiAgICAgICAgICAgICAgICB0aGlzLmNsaWVudElkLFxyXG4gICAgICAgICAgICAgICAgc2VydmVyVG9rZW5SZXNwb25zZS5mb2NpLFxyXG4gICAgICAgICAgICAgICAgb2JvQXNzZXJ0aW9uXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBhcHBNZXRhZGF0YVxyXG4gICAgICAgIGxldCBjYWNoZWRBcHBNZXRhZGF0YTogQXBwTWV0YWRhdGFFbnRpdHkgfCBudWxsID0gbnVsbDtcclxuICAgICAgICBpZiAoIVN0cmluZ1V0aWxzLmlzRW1wdHkoc2VydmVyVG9rZW5SZXNwb25zZS5mb2NpKSkge1xyXG4gICAgICAgICAgICBjYWNoZWRBcHBNZXRhZGF0YSA9IEFwcE1ldGFkYXRhRW50aXR5LmNyZWF0ZUFwcE1ldGFkYXRhRW50aXR5KHRoaXMuY2xpZW50SWQsIGVudiwgc2VydmVyVG9rZW5SZXNwb25zZS5mb2NpKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBuZXcgQ2FjaGVSZWNvcmQoY2FjaGVkQWNjb3VudCwgY2FjaGVkSWRUb2tlbiwgY2FjaGVkQWNjZXNzVG9rZW4sIGNhY2hlZFJlZnJlc2hUb2tlbiwgY2FjaGVkQXBwTWV0YWRhdGEpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2VuZXJhdGUgQWNjb3VudFxyXG4gICAgICogQHBhcmFtIHNlcnZlclRva2VuUmVzcG9uc2VcclxuICAgICAqIEBwYXJhbSBpZFRva2VuXHJcbiAgICAgKiBAcGFyYW0gYXV0aG9yaXR5XHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2VuZXJhdGVBY2NvdW50RW50aXR5KHNlcnZlclRva2VuUmVzcG9uc2U6IFNlcnZlckF1dGhvcml6YXRpb25Ub2tlblJlc3BvbnNlLCBpZFRva2VuOiBBdXRoVG9rZW4sIGF1dGhvcml0eTogQXV0aG9yaXR5LCBvYm9Bc3NlcnRpb24/OiBzdHJpbmcsIGF1dGhDb2RlUGF5bG9hZD86IEF1dGhvcml6YXRpb25Db2RlUGF5bG9hZCk6IEFjY291bnRFbnRpdHkge1xyXG4gICAgICAgIGNvbnN0IGF1dGhvcml0eVR5cGUgPSBhdXRob3JpdHkuYXV0aG9yaXR5VHlwZTtcclxuICAgICAgICBjb25zdCBjbG91ZEdyYXBoSG9zdE5hbWUgPSBhdXRoQ29kZVBheWxvYWQgPyBhdXRoQ29kZVBheWxvYWQuY2xvdWRfZ3JhcGhfaG9zdF9uYW1lIDogXCJcIjtcclxuICAgICAgICBjb25zdCBtc0dyYXBoaG9zdCA9IGF1dGhDb2RlUGF5bG9hZCA/IGF1dGhDb2RlUGF5bG9hZC5tc2dyYXBoX2hvc3QgOiBcIlwiO1xyXG5cclxuICAgICAgICAvLyBBREZTIGRvZXMgbm90IHJlcXVpcmUgY2xpZW50X2luZm8gaW4gdGhlIHJlc3BvbnNlXHJcbiAgICAgICAgaWYgKGF1dGhvcml0eVR5cGUgPT09IEF1dGhvcml0eVR5cGUuQWRmcykge1xyXG4gICAgICAgICAgICB0aGlzLmxvZ2dlci52ZXJib3NlKFwiQXV0aG9yaXR5IHR5cGUgaXMgQURGUywgY3JlYXRpbmcgQURGUyBhY2NvdW50XCIpO1xyXG4gICAgICAgICAgICByZXR1cm4gQWNjb3VudEVudGl0eS5jcmVhdGVHZW5lcmljQWNjb3VudChhdXRob3JpdHksIHRoaXMuaG9tZUFjY291bnRJZGVudGlmaWVyLCBpZFRva2VuLCBvYm9Bc3NlcnRpb24sIGNsb3VkR3JhcGhIb3N0TmFtZSwgbXNHcmFwaGhvc3QpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gVGhpcyBmYWxsYmFjayBhcHBsaWVzIHRvIEIyQyBhcyB3ZWxsIGFzIHRoZXkgZmFsbCB1bmRlciBhbiBBQUQgYWNjb3VudCB0eXBlLlxyXG4gICAgICAgIGlmIChTdHJpbmdVdGlscy5pc0VtcHR5KHNlcnZlclRva2VuUmVzcG9uc2UuY2xpZW50X2luZm8pICYmIGF1dGhvcml0eS5wcm90b2NvbE1vZGUgPT09IFwiQUFEXCIpIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50QXV0aEVycm9yLmNyZWF0ZUNsaWVudEluZm9FbXB0eUVycm9yKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gc2VydmVyVG9rZW5SZXNwb25zZS5jbGllbnRfaW5mbyA/XHJcbiAgICAgICAgICAgIEFjY291bnRFbnRpdHkuY3JlYXRlQWNjb3VudChzZXJ2ZXJUb2tlblJlc3BvbnNlLmNsaWVudF9pbmZvLCB0aGlzLmhvbWVBY2NvdW50SWRlbnRpZmllciwgYXV0aG9yaXR5LCBpZFRva2VuLCBvYm9Bc3NlcnRpb24sIGNsb3VkR3JhcGhIb3N0TmFtZSwgbXNHcmFwaGhvc3QpIDpcclxuICAgICAgICAgICAgQWNjb3VudEVudGl0eS5jcmVhdGVHZW5lcmljQWNjb3VudChhdXRob3JpdHksIHRoaXMuaG9tZUFjY291bnRJZGVudGlmaWVyLCBpZFRva2VuLCBvYm9Bc3NlcnRpb24sIGNsb3VkR3JhcGhIb3N0TmFtZSwgbXNHcmFwaGhvc3QpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlcyBhbiBAQXV0aGVudGljYXRpb25SZXN1bHQgZnJvbSBAQ2FjaGVSZWNvcmQgLCBASWRUb2tlbiAsIGFuZCBhIGJvb2xlYW4gdGhhdCBzdGF0ZXMgd2hldGhlciBvciBub3QgdGhlIHJlc3VsdCBpcyBmcm9tIGNhY2hlLlxyXG4gICAgICpcclxuICAgICAqIE9wdGlvbmFsbHkgdGFrZXMgYSBzdGF0ZSBzdHJpbmcgdGhhdCBpcyBzZXQgYXMtaXMgaW4gdGhlIHJlc3BvbnNlLlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSBjYWNoZVJlY29yZFxyXG4gICAgICogQHBhcmFtIGlkVG9rZW5PYmpcclxuICAgICAqIEBwYXJhbSBmcm9tVG9rZW5DYWNoZVxyXG4gICAgICogQHBhcmFtIHN0YXRlU3RyaW5nXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBhc3luYyBnZW5lcmF0ZUF1dGhlbnRpY2F0aW9uUmVzdWx0KFxyXG4gICAgICAgIGNyeXB0b09iajogSUNyeXB0bywgXHJcbiAgICAgICAgYXV0aG9yaXR5OiBBdXRob3JpdHksXHJcbiAgICAgICAgY2FjaGVSZWNvcmQ6IENhY2hlUmVjb3JkLCBcclxuICAgICAgICBmcm9tVG9rZW5DYWNoZTogYm9vbGVhbiwgXHJcbiAgICAgICAgaWRUb2tlbk9iaj86IEF1dGhUb2tlbixcclxuICAgICAgICByZXF1ZXN0U3RhdGU/OiBSZXF1ZXN0U3RhdGVPYmplY3QsXHJcbiAgICAgICAgcmVzb3VyY2VSZXF1ZXN0TWV0aG9kPzogc3RyaW5nLCBcclxuICAgICAgICByZXNvdXJjZVJlcXVlc3RVcmk/OiBzdHJpbmcpOiBQcm9taXNlPEF1dGhlbnRpY2F0aW9uUmVzdWx0PiB7XHJcbiAgICAgICAgbGV0IGFjY2Vzc1Rva2VuOiBzdHJpbmcgPSBcIlwiO1xyXG4gICAgICAgIGxldCByZXNwb25zZVNjb3BlczogQXJyYXk8c3RyaW5nPiA9IFtdO1xyXG4gICAgICAgIGxldCBleHBpcmVzT246IERhdGUgfCBudWxsID0gbnVsbDtcclxuICAgICAgICBsZXQgZXh0RXhwaXJlc09uOiBEYXRlIHwgdW5kZWZpbmVkO1xyXG4gICAgICAgIGxldCBmYW1pbHlJZDogc3RyaW5nID0gQ29uc3RhbnRzLkVNUFRZX1NUUklORztcclxuICAgICAgICBpZiAoY2FjaGVSZWNvcmQuYWNjZXNzVG9rZW4pIHtcclxuICAgICAgICAgICAgaWYgKGNhY2hlUmVjb3JkLmFjY2Vzc1Rva2VuLnRva2VuVHlwZSA9PT0gQXV0aGVudGljYXRpb25TY2hlbWUuUE9QKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBwb3BUb2tlbkdlbmVyYXRvcjogUG9wVG9rZW5HZW5lcmF0b3IgPSBuZXcgUG9wVG9rZW5HZW5lcmF0b3IoY3J5cHRvT2JqKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoIXJlc291cmNlUmVxdWVzdE1ldGhvZCB8fCAhcmVzb3VyY2VSZXF1ZXN0VXJpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yLmNyZWF0ZVJlc291cmNlUmVxdWVzdFBhcmFtZXRlcnNSZXF1aXJlZEVycm9yKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBhY2Nlc3NUb2tlbiA9IGF3YWl0IHBvcFRva2VuR2VuZXJhdG9yLnNpZ25Qb3BUb2tlbihjYWNoZVJlY29yZC5hY2Nlc3NUb2tlbi5zZWNyZXQsIHJlc291cmNlUmVxdWVzdE1ldGhvZCwgcmVzb3VyY2VSZXF1ZXN0VXJpKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGFjY2Vzc1Rva2VuID0gY2FjaGVSZWNvcmQuYWNjZXNzVG9rZW4uc2VjcmV0O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJlc3BvbnNlU2NvcGVzID0gU2NvcGVTZXQuZnJvbVN0cmluZyhjYWNoZVJlY29yZC5hY2Nlc3NUb2tlbi50YXJnZXQpLmFzQXJyYXkoKTtcclxuICAgICAgICAgICAgZXhwaXJlc09uID0gbmV3IERhdGUoTnVtYmVyKGNhY2hlUmVjb3JkLmFjY2Vzc1Rva2VuLmV4cGlyZXNPbikgKiAxMDAwKTtcclxuICAgICAgICAgICAgZXh0RXhwaXJlc09uID0gbmV3IERhdGUoTnVtYmVyKGNhY2hlUmVjb3JkLmFjY2Vzc1Rva2VuLmV4dGVuZGVkRXhwaXJlc09uKSAqIDEwMDApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGNhY2hlUmVjb3JkLmFwcE1ldGFkYXRhKSB7XHJcbiAgICAgICAgICAgIGZhbWlseUlkID0gY2FjaGVSZWNvcmQuYXBwTWV0YWRhdGEuZmFtaWx5SWQgPT09IFRIRV9GQU1JTFlfSUQgPyBUSEVfRkFNSUxZX0lEIDogQ29uc3RhbnRzLkVNUFRZX1NUUklORztcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3QgdWlkID0gaWRUb2tlbk9iaj8uY2xhaW1zLm9pZCB8fCBpZFRva2VuT2JqPy5jbGFpbXMuc3ViIHx8IENvbnN0YW50cy5FTVBUWV9TVFJJTkc7XHJcbiAgICAgICAgY29uc3QgdGlkID0gaWRUb2tlbk9iaj8uY2xhaW1zLnRpZCB8fCBDb25zdGFudHMuRU1QVFlfU1RSSU5HO1xyXG5cclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBhdXRob3JpdHk6IGF1dGhvcml0eS5jYW5vbmljYWxBdXRob3JpdHksXHJcbiAgICAgICAgICAgIHVuaXF1ZUlkOiB1aWQsXHJcbiAgICAgICAgICAgIHRlbmFudElkOiB0aWQsXHJcbiAgICAgICAgICAgIHNjb3BlczogcmVzcG9uc2VTY29wZXMsXHJcbiAgICAgICAgICAgIGFjY291bnQ6IGNhY2hlUmVjb3JkLmFjY291bnQgPyBjYWNoZVJlY29yZC5hY2NvdW50LmdldEFjY291bnRJbmZvKCkgOiBudWxsLFxyXG4gICAgICAgICAgICBpZFRva2VuOiBpZFRva2VuT2JqID8gaWRUb2tlbk9iai5yYXdUb2tlbiA6IENvbnN0YW50cy5FTVBUWV9TVFJJTkcsXHJcbiAgICAgICAgICAgIGlkVG9rZW5DbGFpbXM6IGlkVG9rZW5PYmogPyBpZFRva2VuT2JqLmNsYWltcyA6IHt9LFxyXG4gICAgICAgICAgICBhY2Nlc3NUb2tlbjogYWNjZXNzVG9rZW4sXHJcbiAgICAgICAgICAgIGZyb21DYWNoZTogZnJvbVRva2VuQ2FjaGUsXHJcbiAgICAgICAgICAgIGV4cGlyZXNPbjogZXhwaXJlc09uLFxyXG4gICAgICAgICAgICBleHRFeHBpcmVzT246IGV4dEV4cGlyZXNPbixcclxuICAgICAgICAgICAgZmFtaWx5SWQ6IGZhbWlseUlkLFxyXG4gICAgICAgICAgICB0b2tlblR5cGU6IGNhY2hlUmVjb3JkLmFjY2Vzc1Rva2VuPy50b2tlblR5cGUgfHwgQ29uc3RhbnRzLkVNUFRZX1NUUklORyxcclxuICAgICAgICAgICAgc3RhdGU6IHJlcXVlc3RTdGF0ZSA/IHJlcXVlc3RTdGF0ZS51c2VyUmVxdWVzdFN0YXRlIDogQ29uc3RhbnRzLkVNUFRZX1NUUklORyxcclxuICAgICAgICAgICAgY2xvdWRHcmFwaEhvc3ROYW1lOiBjYWNoZVJlY29yZC5hY2NvdW50Py5jbG91ZEdyYXBoSG9zdE5hbWUgfHwgQ29uc3RhbnRzLkVNUFRZX1NUUklORyxcclxuICAgICAgICAgICAgbXNHcmFwaEhvc3Q6IGNhY2hlUmVjb3JkLmFjY291bnQ/Lm1zR3JhcGhIb3N0IHx8IENvbnN0YW50cy5FTVBUWV9TVFJJTkdcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG59XHJcbiIsIi8qXHJcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgQmFzZUNsaWVudCB9IGZyb20gXCIuL0Jhc2VDbGllbnRcIjtcclxuaW1wb3J0IHsgQ29tbW9uQXV0aG9yaXphdGlvblVybFJlcXVlc3QgfSBmcm9tIFwiLi4vcmVxdWVzdC9Db21tb25BdXRob3JpemF0aW9uVXJsUmVxdWVzdFwiO1xyXG5pbXBvcnQgeyBDb21tb25BdXRob3JpemF0aW9uQ29kZVJlcXVlc3QgfSBmcm9tIFwiLi4vcmVxdWVzdC9Db21tb25BdXRob3JpemF0aW9uQ29kZVJlcXVlc3RcIjtcclxuaW1wb3J0IHsgQXV0aG9yaXR5IH0gZnJvbSBcIi4uL2F1dGhvcml0eS9BdXRob3JpdHlcIjtcclxuaW1wb3J0IHsgUmVxdWVzdFBhcmFtZXRlckJ1aWxkZXIgfSBmcm9tIFwiLi4vcmVxdWVzdC9SZXF1ZXN0UGFyYW1ldGVyQnVpbGRlclwiO1xyXG5pbXBvcnQgeyBHcmFudFR5cGUsIEF1dGhlbnRpY2F0aW9uU2NoZW1lIH0gZnJvbSBcIi4uL3V0aWxzL0NvbnN0YW50c1wiO1xyXG5pbXBvcnQgeyBDbGllbnRDb25maWd1cmF0aW9uIH0gZnJvbSBcIi4uL2NvbmZpZy9DbGllbnRDb25maWd1cmF0aW9uXCI7XHJcbmltcG9ydCB7IFNlcnZlckF1dGhvcml6YXRpb25Ub2tlblJlc3BvbnNlIH0gZnJvbSBcIi4uL3Jlc3BvbnNlL1NlcnZlckF1dGhvcml6YXRpb25Ub2tlblJlc3BvbnNlXCI7XHJcbmltcG9ydCB7IE5ldHdvcmtSZXNwb25zZSB9IGZyb20gXCIuLi9uZXR3b3JrL05ldHdvcmtNYW5hZ2VyXCI7XHJcbmltcG9ydCB7IFJlc3BvbnNlSGFuZGxlciB9IGZyb20gXCIuLi9yZXNwb25zZS9SZXNwb25zZUhhbmRsZXJcIjtcclxuaW1wb3J0IHsgQXV0aGVudGljYXRpb25SZXN1bHQgfSBmcm9tIFwiLi4vcmVzcG9uc2UvQXV0aGVudGljYXRpb25SZXN1bHRcIjtcclxuaW1wb3J0IHsgU3RyaW5nVXRpbHMgfSBmcm9tIFwiLi4vdXRpbHMvU3RyaW5nVXRpbHNcIjtcclxuaW1wb3J0IHsgQ2xpZW50QXV0aEVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL0NsaWVudEF1dGhFcnJvclwiO1xyXG5pbXBvcnQgeyBVcmxTdHJpbmcgfSBmcm9tIFwiLi4vdXJsL1VybFN0cmluZ1wiO1xyXG5pbXBvcnQgeyBTZXJ2ZXJBdXRob3JpemF0aW9uQ29kZVJlc3BvbnNlIH0gZnJvbSBcIi4uL3Jlc3BvbnNlL1NlcnZlckF1dGhvcml6YXRpb25Db2RlUmVzcG9uc2VcIjtcclxuaW1wb3J0IHsgQWNjb3VudEVudGl0eSB9IGZyb20gXCIuLi9jYWNoZS9lbnRpdGllcy9BY2NvdW50RW50aXR5XCI7XHJcbmltcG9ydCB7IENvbW1vbkVuZFNlc3Npb25SZXF1ZXN0IH0gZnJvbSBcIi4uL3JlcXVlc3QvQ29tbW9uRW5kU2Vzc2lvblJlcXVlc3RcIjtcclxuaW1wb3J0IHsgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL0NsaWVudENvbmZpZ3VyYXRpb25FcnJvclwiO1xyXG5pbXBvcnQgeyBQb3BUb2tlbkdlbmVyYXRvciB9IGZyb20gXCIuLi9jcnlwdG8vUG9wVG9rZW5HZW5lcmF0b3JcIjtcclxuaW1wb3J0IHsgUmVxdWVzdFRodW1icHJpbnQgfSBmcm9tIFwiLi4vbmV0d29yay9SZXF1ZXN0VGh1bWJwcmludFwiO1xyXG5pbXBvcnQgeyBBdXRob3JpemF0aW9uQ29kZVBheWxvYWQgfSBmcm9tIFwiLi4vcmVzcG9uc2UvQXV0aG9yaXphdGlvbkNvZGVQYXlsb2FkXCI7XHJcbmltcG9ydCB7IFRpbWVVdGlscyB9IGZyb20gXCIuLi91dGlscy9UaW1lVXRpbHNcIjtcclxuXHJcbi8qKlxyXG4gKiBPYXV0aDIuMCBBdXRob3JpemF0aW9uIENvZGUgY2xpZW50XHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgQXV0aG9yaXphdGlvbkNvZGVDbGllbnQgZXh0ZW5kcyBCYXNlQ2xpZW50IHtcclxuXHJcbiAgICBjb25zdHJ1Y3Rvcihjb25maWd1cmF0aW9uOiBDbGllbnRDb25maWd1cmF0aW9uKSB7XHJcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIHRoZSBVUkwgb2YgdGhlIGF1dGhvcml6YXRpb24gcmVxdWVzdCBsZXR0aW5nIHRoZSB1c2VyIGlucHV0IGNyZWRlbnRpYWxzIGFuZCBjb25zZW50IHRvIHRoZVxyXG4gICAgICogYXBwbGljYXRpb24uIFRoZSBVUkwgdGFyZ2V0IHRoZSAvYXV0aG9yaXplIGVuZHBvaW50IG9mIHRoZSBhdXRob3JpdHkgY29uZmlndXJlZCBpbiB0aGVcclxuICAgICAqIGFwcGxpY2F0aW9uIG9iamVjdC5cclxuICAgICAqXHJcbiAgICAgKiBPbmNlIHRoZSB1c2VyIGlucHV0cyB0aGVpciBjcmVkZW50aWFscyBhbmQgY29uc2VudHMsIHRoZSBhdXRob3JpdHkgd2lsbCBzZW5kIGEgcmVzcG9uc2UgdG8gdGhlIHJlZGlyZWN0IFVSSVxyXG4gICAgICogc2VudCBpbiB0aGUgcmVxdWVzdCBhbmQgc2hvdWxkIGNvbnRhaW4gYW4gYXV0aG9yaXphdGlvbiBjb2RlLCB3aGljaCBjYW4gdGhlbiBiZSB1c2VkIHRvIGFjcXVpcmUgdG9rZW5zIHZpYVxyXG4gICAgICogYWNxdWlyZVRva2VuKEF1dGhvcml6YXRpb25Db2RlUmVxdWVzdClcclxuICAgICAqIEBwYXJhbSByZXF1ZXN0XHJcbiAgICAgKi9cclxuICAgIGFzeW5jIGdldEF1dGhDb2RlVXJsKHJlcXVlc3Q6IENvbW1vbkF1dGhvcml6YXRpb25VcmxSZXF1ZXN0KTogUHJvbWlzZTxzdHJpbmc+IHtcclxuICAgICAgICBjb25zdCBxdWVyeVN0cmluZyA9IHRoaXMuY3JlYXRlQXV0aENvZGVVcmxRdWVyeVN0cmluZyhyZXF1ZXN0KTtcclxuICAgICAgICByZXR1cm4gYCR7dGhpcy5hdXRob3JpdHkuYXV0aG9yaXphdGlvbkVuZHBvaW50fT8ke3F1ZXJ5U3RyaW5nfWA7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBUEkgdG8gYWNxdWlyZSBhIHRva2VuIGluIGV4Y2hhbmdlIG9mICdhdXRob3JpemF0aW9uX2NvZGVgIGFjcXVpcmVkIGJ5IHRoZSB1c2VyIGluIHRoZSBmaXJzdCBsZWcgb2YgdGhlXHJcbiAgICAgKiBhdXRob3JpemF0aW9uX2NvZGVfZ3JhbnRcclxuICAgICAqIEBwYXJhbSByZXF1ZXN0XHJcbiAgICAgKi9cclxuICAgIGFzeW5jIGFjcXVpcmVUb2tlbihyZXF1ZXN0OiBDb21tb25BdXRob3JpemF0aW9uQ29kZVJlcXVlc3QsIGF1dGhDb2RlUGF5bG9hZD86IEF1dGhvcml6YXRpb25Db2RlUGF5bG9hZCk6IFByb21pc2U8QXV0aGVudGljYXRpb25SZXN1bHQ+IHtcclxuICAgICAgICB0aGlzLmxvZ2dlci5pbmZvKFwiaW4gYWNxdWlyZVRva2VuIGNhbGxcIik7XHJcbiAgICAgICAgaWYgKCFyZXF1ZXN0IHx8IFN0cmluZ1V0aWxzLmlzRW1wdHkocmVxdWVzdC5jb2RlKSkge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRBdXRoRXJyb3IuY3JlYXRlVG9rZW5SZXF1ZXN0Q2Fubm90QmVNYWRlRXJyb3IoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHJlcVRpbWVzdGFtcCA9IFRpbWVVdGlscy5ub3dTZWNvbmRzKCk7XHJcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmV4ZWN1dGVUb2tlblJlcXVlc3QodGhpcy5hdXRob3JpdHksIHJlcXVlc3QpO1xyXG5cclxuICAgICAgICBjb25zdCByZXNwb25zZUhhbmRsZXIgPSBuZXcgUmVzcG9uc2VIYW5kbGVyKFxyXG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRJZCxcclxuICAgICAgICAgICAgdGhpcy5jYWNoZU1hbmFnZXIsXHJcbiAgICAgICAgICAgIHRoaXMuY3J5cHRvVXRpbHMsXHJcbiAgICAgICAgICAgIHRoaXMubG9nZ2VyLFxyXG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5zZXJpYWxpemFibGVDYWNoZSxcclxuICAgICAgICAgICAgdGhpcy5jb25maWcucGVyc2lzdGVuY2VQbHVnaW5cclxuICAgICAgICApO1xyXG5cclxuICAgICAgICAvLyBWYWxpZGF0ZSByZXNwb25zZS4gVGhpcyBmdW5jdGlvbiB0aHJvd3MgYSBzZXJ2ZXIgZXJyb3IgaWYgYW4gZXJyb3IgaXMgcmV0dXJuZWQgYnkgdGhlIHNlcnZlci5cclxuICAgICAgICByZXNwb25zZUhhbmRsZXIudmFsaWRhdGVUb2tlblJlc3BvbnNlKHJlc3BvbnNlLmJvZHkpO1xyXG4gICAgICAgIHJldHVybiBhd2FpdCByZXNwb25zZUhhbmRsZXIuaGFuZGxlU2VydmVyVG9rZW5SZXNwb25zZShyZXNwb25zZS5ib2R5LCB0aGlzLmF1dGhvcml0eSwgcmVxVGltZXN0YW1wLCByZXF1ZXN0LnJlc291cmNlUmVxdWVzdE1ldGhvZCwgcmVxdWVzdC5yZXNvdXJjZVJlcXVlc3RVcmksIGF1dGhDb2RlUGF5bG9hZCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBIYW5kbGVzIHRoZSBoYXNoIGZyYWdtZW50IHJlc3BvbnNlIGZyb20gcHVibGljIGNsaWVudCBjb2RlIHJlcXVlc3QuIFJldHVybnMgYSBjb2RlIHJlc3BvbnNlIHVzZWQgYnlcclxuICAgICAqIHRoZSBjbGllbnQgdG8gZXhjaGFuZ2UgZm9yIGEgdG9rZW4gaW4gYWNxdWlyZVRva2VuLlxyXG4gICAgICogQHBhcmFtIGhhc2hGcmFnbWVudFxyXG4gICAgICovXHJcbiAgICBoYW5kbGVGcmFnbWVudFJlc3BvbnNlKGhhc2hGcmFnbWVudDogc3RyaW5nLCBjYWNoZWRTdGF0ZTogc3RyaW5nKTogQXV0aG9yaXphdGlvbkNvZGVQYXlsb2FkIHtcclxuICAgICAgICAvLyBIYW5kbGUgcmVzcG9uc2VzLlxyXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlSGFuZGxlciA9IG5ldyBSZXNwb25zZUhhbmRsZXIodGhpcy5jb25maWcuYXV0aE9wdGlvbnMuY2xpZW50SWQsIHRoaXMuY2FjaGVNYW5hZ2VyLCB0aGlzLmNyeXB0b1V0aWxzLCB0aGlzLmxvZ2dlciwgbnVsbCwgbnVsbCk7XHJcblxyXG4gICAgICAgIC8vIERlc2VyaWFsaXplIGhhc2ggZnJhZ21lbnQgcmVzcG9uc2UgcGFyYW1ldGVycy5cclxuICAgICAgICBjb25zdCBoYXNoVXJsU3RyaW5nID0gbmV3IFVybFN0cmluZyhoYXNoRnJhZ21lbnQpO1xyXG4gICAgICAgIC8vIERlc2VyaWFsaXplIGhhc2ggZnJhZ21lbnQgcmVzcG9uc2UgcGFyYW1ldGVycy5cclxuICAgICAgICBjb25zdCBzZXJ2ZXJQYXJhbXM6IFNlcnZlckF1dGhvcml6YXRpb25Db2RlUmVzcG9uc2UgPSBVcmxTdHJpbmcuZ2V0RGVzZXJpYWxpemVkSGFzaChoYXNoVXJsU3RyaW5nLmdldEhhc2goKSk7XHJcblxyXG4gICAgICAgIC8vIEdldCBjb2RlIHJlc3BvbnNlXHJcbiAgICAgICAgcmVzcG9uc2VIYW5kbGVyLnZhbGlkYXRlU2VydmVyQXV0aG9yaXphdGlvbkNvZGVSZXNwb25zZShzZXJ2ZXJQYXJhbXMsIGNhY2hlZFN0YXRlLCB0aGlzLmNyeXB0b1V0aWxzKTtcclxuXHJcbiAgICAgICAgLy8gdGhyb3cgd2hlbiB0aGVyZSBpcyBubyBhdXRoIGNvZGUgaW4gdGhlIHJlc3BvbnNlXHJcbiAgICAgICAgaWYgKCFzZXJ2ZXJQYXJhbXMuY29kZSkge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRBdXRoRXJyb3IuY3JlYXRlTm9BdXRoQ29kZUluU2VydmVyUmVzcG9uc2VFcnJvcigpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgLi4uc2VydmVyUGFyYW1zLFxyXG4gICAgICAgICAgICAvLyBDb2RlIHBhcmFtIGlzIG9wdGlvbmFsIGluIFNlcnZlckF1dGhvcml6YXRpb25Db2RlUmVzcG9uc2UgYnV0IHJlcXVpcmVkIGluIEF1dGhvcml6YXRpb25Db2RlUGF5bG9kXHJcbiAgICAgICAgICAgIGNvZGU6IHNlcnZlclBhcmFtcy5jb2RlXHJcbiAgICAgICAgfTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFVzZSB0byBsb2cgb3V0IHRoZSBjdXJyZW50IHVzZXIsIGFuZCByZWRpcmVjdCB0aGUgdXNlciB0byB0aGUgcG9zdExvZ291dFJlZGlyZWN0VXJpLlxyXG4gICAgICogRGVmYXVsdCBiZWhhdmlvdXIgaXMgdG8gcmVkaXJlY3QgdGhlIHVzZXIgdG8gYHdpbmRvdy5sb2NhdGlvbi5ocmVmYC5cclxuICAgICAqIEBwYXJhbSBhdXRob3JpdHlVcmlcclxuICAgICAqL1xyXG4gICAgZ2V0TG9nb3V0VXJpKGxvZ291dFJlcXVlc3Q6IENvbW1vbkVuZFNlc3Npb25SZXF1ZXN0KTogc3RyaW5nIHtcclxuICAgICAgICAvLyBUaHJvdyBlcnJvciBpZiBsb2dvdXRSZXF1ZXN0IGlzIG51bGwvdW5kZWZpbmVkXHJcbiAgICAgICAgaWYgKCFsb2dvdXRSZXF1ZXN0KSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudENvbmZpZ3VyYXRpb25FcnJvci5jcmVhdGVFbXB0eUxvZ291dFJlcXVlc3RFcnJvcigpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGxvZ291dFJlcXVlc3QuYWNjb3VudCkge1xyXG4gICAgICAgICAgICAvLyBDbGVhciBnaXZlbiBhY2NvdW50LlxyXG4gICAgICAgICAgICB0aGlzLmNhY2hlTWFuYWdlci5yZW1vdmVBY2NvdW50KEFjY291bnRFbnRpdHkuZ2VuZXJhdGVBY2NvdW50Q2FjaGVLZXkobG9nb3V0UmVxdWVzdC5hY2NvdW50KSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgLy8gQ2xlYXIgYWxsIGFjY291bnRzIGFuZCB0b2tlbnNcclxuICAgICAgICAgICAgdGhpcy5jYWNoZU1hbmFnZXIuY2xlYXIoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHF1ZXJ5U3RyaW5nID0gdGhpcy5jcmVhdGVMb2dvdXRVcmxRdWVyeVN0cmluZyhsb2dvdXRSZXF1ZXN0KTtcclxuXHJcbiAgICAgICAgLy8gQ29uc3RydWN0IGxvZ291dCBVUkkuXHJcbiAgICAgICAgcmV0dXJuIFN0cmluZ1V0aWxzLmlzRW1wdHkocXVlcnlTdHJpbmcpID8gdGhpcy5hdXRob3JpdHkuZW5kU2Vzc2lvbkVuZHBvaW50IDogYCR7dGhpcy5hdXRob3JpdHkuZW5kU2Vzc2lvbkVuZHBvaW50fT8ke3F1ZXJ5U3RyaW5nfWA7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBFeGVjdXRlcyBQT1NUIHJlcXVlc3QgdG8gdG9rZW4gZW5kcG9pbnRcclxuICAgICAqIEBwYXJhbSBhdXRob3JpdHlcclxuICAgICAqIEBwYXJhbSByZXF1ZXN0XHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgYXN5bmMgZXhlY3V0ZVRva2VuUmVxdWVzdChhdXRob3JpdHk6IEF1dGhvcml0eSwgcmVxdWVzdDogQ29tbW9uQXV0aG9yaXphdGlvbkNvZGVSZXF1ZXN0KTogUHJvbWlzZTxOZXR3b3JrUmVzcG9uc2U8U2VydmVyQXV0aG9yaXphdGlvblRva2VuUmVzcG9uc2U+PiB7XHJcbiAgICAgICAgY29uc3QgdGh1bWJwcmludDogUmVxdWVzdFRodW1icHJpbnQgPSB7XHJcbiAgICAgICAgICAgIGNsaWVudElkOiB0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRJZCxcclxuICAgICAgICAgICAgYXV0aG9yaXR5OiBhdXRob3JpdHkuY2Fub25pY2FsQXV0aG9yaXR5LFxyXG4gICAgICAgICAgICBzY29wZXM6IHJlcXVlc3Quc2NvcGVzXHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgY29uc3QgcmVxdWVzdEJvZHkgPSBhd2FpdCB0aGlzLmNyZWF0ZVRva2VuUmVxdWVzdEJvZHkocmVxdWVzdCk7XHJcbiAgICAgICAgY29uc3QgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHRoaXMuY3JlYXRlRGVmYXVsdFRva2VuUmVxdWVzdEhlYWRlcnMoKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZVBvc3RUb1Rva2VuRW5kcG9pbnQoYXV0aG9yaXR5LnRva2VuRW5kcG9pbnQsIHJlcXVlc3RCb2R5LCBoZWFkZXJzLCB0aHVtYnByaW50KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdlbmVyYXRlcyBhIG1hcCBmb3IgYWxsIHRoZSBwYXJhbXMgdG8gYmUgc2VudCB0byB0aGUgc2VydmljZVxyXG4gICAgICogQHBhcmFtIHJlcXVlc3RcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhc3luYyBjcmVhdGVUb2tlblJlcXVlc3RCb2R5KHJlcXVlc3Q6IENvbW1vbkF1dGhvcml6YXRpb25Db2RlUmVxdWVzdCk6IFByb21pc2U8c3RyaW5nPiB7XHJcbiAgICAgICAgY29uc3QgcGFyYW1ldGVyQnVpbGRlciA9IG5ldyBSZXF1ZXN0UGFyYW1ldGVyQnVpbGRlcigpO1xyXG5cclxuICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZENsaWVudElkKHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudElkKTtcclxuXHJcbiAgICAgICAgLy8gdmFsaWRhdGUgdGhlIHJlZGlyZWN0VXJpICh0byBiZSBhIG5vbiBudWxsIHZhbHVlKVxyXG4gICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkUmVkaXJlY3RVcmkocmVxdWVzdC5yZWRpcmVjdFVyaSk7XHJcblxyXG4gICAgICAgIC8vIEFkZCBzY29wZSBhcnJheSwgcGFyYW1ldGVyIGJ1aWxkZXIgd2lsbCBhZGQgZGVmYXVsdCBzY29wZXMgYW5kIGRlZHVwZVxyXG4gICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkU2NvcGVzKHJlcXVlc3Quc2NvcGVzKTtcclxuXHJcbiAgICAgICAgLy8gYWRkIGNvZGU6IHVzZXIgc2V0LCBub3QgdmFsaWRhdGVkXHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRBdXRob3JpemF0aW9uQ29kZShyZXF1ZXN0LmNvZGUpO1xyXG5cclxuICAgICAgICAvLyBhZGQgY29kZV92ZXJpZmllciBpZiBwYXNzZWRcclxuICAgICAgICBpZiAocmVxdWVzdC5jb2RlVmVyaWZpZXIpIHtcclxuICAgICAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRDb2RlVmVyaWZpZXIocmVxdWVzdC5jb2RlVmVyaWZpZXIpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmNsaWVudENyZWRlbnRpYWxzLmNsaWVudFNlY3JldCkge1xyXG4gICAgICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZENsaWVudFNlY3JldCh0aGlzLmNvbmZpZy5jbGllbnRDcmVkZW50aWFscy5jbGllbnRTZWNyZXQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmNsaWVudENyZWRlbnRpYWxzLmNsaWVudEFzc2VydGlvbikge1xyXG4gICAgICAgICAgICBjb25zdCBjbGllbnRBc3NlcnRpb24gPSB0aGlzLmNvbmZpZy5jbGllbnRDcmVkZW50aWFscy5jbGllbnRBc3NlcnRpb247XHJcbiAgICAgICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkQ2xpZW50QXNzZXJ0aW9uKGNsaWVudEFzc2VydGlvbi5hc3NlcnRpb24pO1xyXG4gICAgICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZENsaWVudEFzc2VydGlvblR5cGUoY2xpZW50QXNzZXJ0aW9uLmFzc2VydGlvblR5cGUpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRHcmFudFR5cGUoR3JhbnRUeXBlLkFVVEhPUklaQVRJT05fQ09ERV9HUkFOVCk7XHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRDbGllbnRJbmZvKCk7XHJcblxyXG4gICAgICAgIGlmIChyZXF1ZXN0LmF1dGhlbnRpY2F0aW9uU2NoZW1lID09PSBBdXRoZW50aWNhdGlvblNjaGVtZS5QT1AgJiYgISFyZXF1ZXN0LnJlc291cmNlUmVxdWVzdE1ldGhvZCAmJiAhIXJlcXVlc3QucmVzb3VyY2VSZXF1ZXN0VXJpKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHBvcFRva2VuR2VuZXJhdG9yID0gbmV3IFBvcFRva2VuR2VuZXJhdG9yKHRoaXMuY3J5cHRvVXRpbHMpO1xyXG4gICAgICAgICAgICBjb25zdCBjbmZTdHJpbmcgPSBhd2FpdCBwb3BUb2tlbkdlbmVyYXRvci5nZW5lcmF0ZUNuZihyZXF1ZXN0LnJlc291cmNlUmVxdWVzdE1ldGhvZCwgcmVxdWVzdC5yZXNvdXJjZVJlcXVlc3RVcmkpO1xyXG4gICAgICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZFBvcFRva2VuKGNuZlN0cmluZyk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBjb3JyZWxhdGlvbklkID0gcmVxdWVzdC5jb3JyZWxhdGlvbklkIHx8IHRoaXMuY29uZmlnLmNyeXB0b0ludGVyZmFjZS5jcmVhdGVOZXdHdWlkKCk7XHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRDb3JyZWxhdGlvbklkKGNvcnJlbGF0aW9uSWQpO1xyXG5cclxuICAgICAgICBpZiAoIVN0cmluZ1V0aWxzLmlzRW1wdHkocmVxdWVzdC5jbGFpbXMpIHx8IHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudENhcGFiaWxpdGllcyAmJiB0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRDYXBhYmlsaXRpZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZENsYWltcyhyZXF1ZXN0LmNsYWltcywgdGhpcy5jb25maWcuYXV0aE9wdGlvbnMuY2xpZW50Q2FwYWJpbGl0aWVzKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBwYXJhbWV0ZXJCdWlsZGVyLmNyZWF0ZVF1ZXJ5U3RyaW5nKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGlzIEFQSSB2YWxpZGF0ZXMgdGhlIGBBdXRob3JpemF0aW9uQ29kZVVybFJlcXVlc3RgIGFuZCBjcmVhdGVzIGEgVVJMXHJcbiAgICAgKiBAcGFyYW0gcmVxdWVzdFxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGNyZWF0ZUF1dGhDb2RlVXJsUXVlcnlTdHJpbmcocmVxdWVzdDogQ29tbW9uQXV0aG9yaXphdGlvblVybFJlcXVlc3QpOiBzdHJpbmcge1xyXG4gICAgICAgIGNvbnN0IHBhcmFtZXRlckJ1aWxkZXIgPSBuZXcgUmVxdWVzdFBhcmFtZXRlckJ1aWxkZXIoKTtcclxuXHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRDbGllbnRJZCh0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRJZCk7XHJcblxyXG4gICAgICAgIGNvbnN0IHJlcXVlc3RTY29wZXMgPSBbLi4ucmVxdWVzdC5zY29wZXMgfHwgW10sIC4uLnJlcXVlc3QuZXh0cmFTY29wZXNUb0NvbnNlbnQgfHwgW11dO1xyXG4gICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkU2NvcGVzKHJlcXVlc3RTY29wZXMpO1xyXG5cclxuICAgICAgICAvLyB2YWxpZGF0ZSB0aGUgcmVkaXJlY3RVcmkgKHRvIGJlIGEgbm9uIG51bGwgdmFsdWUpXHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRSZWRpcmVjdFVyaShyZXF1ZXN0LnJlZGlyZWN0VXJpKTtcclxuXHJcbiAgICAgICAgLy8gZ2VuZXJhdGUgdGhlIGNvcnJlbGF0aW9uSWQgaWYgbm90IHNldCBieSB0aGUgdXNlciBhbmQgYWRkXHJcbiAgICAgICAgY29uc3QgY29ycmVsYXRpb25JZCA9IHJlcXVlc3QuY29ycmVsYXRpb25JZCB8fCB0aGlzLmNvbmZpZy5jcnlwdG9JbnRlcmZhY2UuY3JlYXRlTmV3R3VpZCgpO1xyXG4gICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkQ29ycmVsYXRpb25JZChjb3JyZWxhdGlvbklkKTtcclxuXHJcbiAgICAgICAgLy8gYWRkIHJlc3BvbnNlX21vZGUuIElmIG5vdCBwYXNzZWQgaW4gaXQgZGVmYXVsdHMgdG8gcXVlcnkuXHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRSZXNwb25zZU1vZGUocmVxdWVzdC5yZXNwb25zZU1vZGUpO1xyXG5cclxuICAgICAgICAvLyBhZGQgcmVzcG9uc2VfdHlwZSA9IGNvZGVcclxuICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZFJlc3BvbnNlVHlwZUNvZGUoKTtcclxuXHJcbiAgICAgICAgLy8gYWRkIGxpYnJhcnkgaW5mbyBwYXJhbWV0ZXJzXHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRMaWJyYXJ5SW5mbyh0aGlzLmNvbmZpZy5saWJyYXJ5SW5mbyk7XHJcblxyXG4gICAgICAgIC8vIGFkZCBjbGllbnRfaW5mbz0xXHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRDbGllbnRJbmZvKCk7XHJcblxyXG4gICAgICAgIGlmIChyZXF1ZXN0LmNvZGVDaGFsbGVuZ2UgJiYgcmVxdWVzdC5jb2RlQ2hhbGxlbmdlTWV0aG9kKSB7XHJcbiAgICAgICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkQ29kZUNoYWxsZW5nZVBhcmFtcyhyZXF1ZXN0LmNvZGVDaGFsbGVuZ2UsIHJlcXVlc3QuY29kZUNoYWxsZW5nZU1ldGhvZCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAocmVxdWVzdC5wcm9tcHQpIHtcclxuICAgICAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRQcm9tcHQocmVxdWVzdC5wcm9tcHQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHJlcXVlc3QuZG9tYWluSGludCkge1xyXG4gICAgICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZERvbWFpbkhpbnQocmVxdWVzdC5kb21haW5IaW50KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIEFkZCBzaWQgb3IgbG9naW5IaW50IHdpdGggcHJlZmVyZW5jZSBmb3Igc2lkIC0+IGxvZ2luSGludCAtPiB1c2VybmFtZSBvZiBBY2NvdW50SW5mbyBvYmplY3RcclxuICAgICAgICBpZiAocmVxdWVzdC5zaWQpIHtcclxuICAgICAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRTaWQocmVxdWVzdC5zaWQpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAocmVxdWVzdC5sb2dpbkhpbnQpIHtcclxuICAgICAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRMb2dpbkhpbnQocmVxdWVzdC5sb2dpbkhpbnQpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAocmVxdWVzdC5hY2NvdW50ICYmIHJlcXVlc3QuYWNjb3VudC51c2VybmFtZSkge1xyXG4gICAgICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZExvZ2luSGludChyZXF1ZXN0LmFjY291bnQudXNlcm5hbWUpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHJlcXVlc3Qubm9uY2UpIHtcclxuICAgICAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGROb25jZShyZXF1ZXN0Lm5vbmNlKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChyZXF1ZXN0LnN0YXRlKSB7XHJcbiAgICAgICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkU3RhdGUocmVxdWVzdC5zdGF0ZSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIVN0cmluZ1V0aWxzLmlzRW1wdHkocmVxdWVzdC5jbGFpbXMpIHx8IHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudENhcGFiaWxpdGllcyAmJiB0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRDYXBhYmlsaXRpZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZENsYWltcyhyZXF1ZXN0LmNsYWltcywgdGhpcy5jb25maWcuYXV0aE9wdGlvbnMuY2xpZW50Q2FwYWJpbGl0aWVzKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChyZXF1ZXN0LmV4dHJhUXVlcnlQYXJhbWV0ZXJzKSB7XHJcbiAgICAgICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkRXh0cmFRdWVyeVBhcmFtZXRlcnMocmVxdWVzdC5leHRyYVF1ZXJ5UGFyYW1ldGVycyk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gcGFyYW1ldGVyQnVpbGRlci5jcmVhdGVRdWVyeVN0cmluZygpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhpcyBBUEkgdmFsaWRhdGVzIHRoZSBgRW5kU2Vzc2lvblJlcXVlc3RgIGFuZCBjcmVhdGVzIGEgVVJMXHJcbiAgICAgKiBAcGFyYW0gcmVxdWVzdFxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGNyZWF0ZUxvZ291dFVybFF1ZXJ5U3RyaW5nKHJlcXVlc3Q6IENvbW1vbkVuZFNlc3Npb25SZXF1ZXN0KTogc3RyaW5nIHtcclxuICAgICAgICBjb25zdCBwYXJhbWV0ZXJCdWlsZGVyID0gbmV3IFJlcXVlc3RQYXJhbWV0ZXJCdWlsZGVyKCk7XHJcblxyXG4gICAgICAgIGlmIChyZXF1ZXN0LnBvc3RMb2dvdXRSZWRpcmVjdFVyaSkge1xyXG4gICAgICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZFBvc3RMb2dvdXRSZWRpcmVjdFVyaShyZXF1ZXN0LnBvc3RMb2dvdXRSZWRpcmVjdFVyaSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAocmVxdWVzdC5jb3JyZWxhdGlvbklkKSB7XHJcbiAgICAgICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkQ29ycmVsYXRpb25JZChyZXF1ZXN0LmNvcnJlbGF0aW9uSWQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHJlcXVlc3QuaWRUb2tlbkhpbnQpIHtcclxuICAgICAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRJZFRva2VuSGludChyZXF1ZXN0LmlkVG9rZW5IaW50KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBwYXJhbWV0ZXJCdWlsZGVyLmNyZWF0ZVF1ZXJ5U3RyaW5nKCk7XHJcbiAgICB9XHJcbn1cclxuIiwiLypcclxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cclxuICovXHJcblxyXG5pbXBvcnQgeyBEZXZpY2VDb2RlUmVzcG9uc2UsIFNlcnZlckRldmljZUNvZGVSZXNwb25zZSB9IGZyb20gXCIuLi9yZXNwb25zZS9EZXZpY2VDb2RlUmVzcG9uc2VcIjtcclxuaW1wb3J0IHsgQmFzZUNsaWVudCB9IGZyb20gXCIuL0Jhc2VDbGllbnRcIjtcclxuaW1wb3J0IHsgQ29tbW9uRGV2aWNlQ29kZVJlcXVlc3QgfSBmcm9tIFwiLi4vcmVxdWVzdC9Db21tb25EZXZpY2VDb2RlUmVxdWVzdFwiO1xyXG5pbXBvcnQgeyBDbGllbnRBdXRoRXJyb3IgfSBmcm9tIFwiLi4vZXJyb3IvQ2xpZW50QXV0aEVycm9yXCI7XHJcbmltcG9ydCB7IFJlcXVlc3RQYXJhbWV0ZXJCdWlsZGVyIH0gZnJvbSBcIi4uL3JlcXVlc3QvUmVxdWVzdFBhcmFtZXRlckJ1aWxkZXJcIjtcclxuaW1wb3J0IHsgQ29uc3RhbnRzLCBHcmFudFR5cGUgfSBmcm9tIFwiLi4vdXRpbHMvQ29uc3RhbnRzXCI7XHJcbmltcG9ydCB7IENsaWVudENvbmZpZ3VyYXRpb24gfSBmcm9tIFwiLi4vY29uZmlnL0NsaWVudENvbmZpZ3VyYXRpb25cIjtcclxuaW1wb3J0IHsgVGltZVV0aWxzIH0gZnJvbSBcIi4uL3V0aWxzL1RpbWVVdGlsc1wiO1xyXG5pbXBvcnQgeyBTZXJ2ZXJBdXRob3JpemF0aW9uVG9rZW5SZXNwb25zZSB9IGZyb20gXCIuLi9yZXNwb25zZS9TZXJ2ZXJBdXRob3JpemF0aW9uVG9rZW5SZXNwb25zZVwiO1xyXG5pbXBvcnQgeyBSZXNwb25zZUhhbmRsZXIgfSBmcm9tIFwiLi4vcmVzcG9uc2UvUmVzcG9uc2VIYW5kbGVyXCI7XHJcbmltcG9ydCB7IEF1dGhlbnRpY2F0aW9uUmVzdWx0IH0gZnJvbSBcIi4uL3Jlc3BvbnNlL0F1dGhlbnRpY2F0aW9uUmVzdWx0XCI7XHJcbmltcG9ydCB7IFN0cmluZ1V0aWxzIH0gZnJvbSBcIi4uL3V0aWxzL1N0cmluZ1V0aWxzXCI7XHJcbmltcG9ydCB7IFJlcXVlc3RUaHVtYnByaW50IH0gZnJvbSBcIi4uL25ldHdvcmsvUmVxdWVzdFRodW1icHJpbnRcIjtcclxuXHJcbi8qKlxyXG4gKiBPQXV0aDIuMCBEZXZpY2UgY29kZSBjbGllbnRcclxuICovXHJcbmV4cG9ydCBjbGFzcyBEZXZpY2VDb2RlQ2xpZW50IGV4dGVuZHMgQmFzZUNsaWVudCB7XHJcblxyXG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbjogQ2xpZW50Q29uZmlndXJhdGlvbikge1xyXG4gICAgICAgIHN1cGVyKGNvbmZpZ3VyYXRpb24pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyBkZXZpY2UgY29kZSBmcm9tIGRldmljZSBjb2RlIGVuZHBvaW50LCBjYWxscyBiYWNrIHRvIHdpdGggZGV2aWNlIGNvZGUgcmVzcG9uc2UsIGFuZFxyXG4gICAgICogcG9sbHMgdG9rZW4gZW5kcG9pbnQgdG8gZXhjaGFuZ2UgZGV2aWNlIGNvZGUgZm9yIHRva2Vuc1xyXG4gICAgICogQHBhcmFtIHJlcXVlc3RcclxuICAgICAqL1xyXG4gICAgcHVibGljIGFzeW5jIGFjcXVpcmVUb2tlbihyZXF1ZXN0OiBDb21tb25EZXZpY2VDb2RlUmVxdWVzdCk6IFByb21pc2U8QXV0aGVudGljYXRpb25SZXN1bHQgfCBudWxsPiB7XHJcbiAgICAgICAgY29uc3QgZGV2aWNlQ29kZVJlc3BvbnNlOiBEZXZpY2VDb2RlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmdldERldmljZUNvZGUocmVxdWVzdCk7XHJcbiAgICAgICAgcmVxdWVzdC5kZXZpY2VDb2RlQ2FsbGJhY2soZGV2aWNlQ29kZVJlc3BvbnNlKTtcclxuICAgICAgICBjb25zdCByZXFUaW1lc3RhbXAgPSBUaW1lVXRpbHMubm93U2Vjb25kcygpO1xyXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlOiBTZXJ2ZXJBdXRob3JpemF0aW9uVG9rZW5SZXNwb25zZSA9IGF3YWl0IHRoaXMuYWNxdWlyZVRva2VuV2l0aERldmljZUNvZGUoXHJcbiAgICAgICAgICAgIHJlcXVlc3QsXHJcbiAgICAgICAgICAgIGRldmljZUNvZGVSZXNwb25zZSk7XHJcblxyXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlSGFuZGxlciA9IG5ldyBSZXNwb25zZUhhbmRsZXIoXHJcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudElkLFxyXG4gICAgICAgICAgICB0aGlzLmNhY2hlTWFuYWdlcixcclxuICAgICAgICAgICAgdGhpcy5jcnlwdG9VdGlscyxcclxuICAgICAgICAgICAgdGhpcy5sb2dnZXIsXHJcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLnNlcmlhbGl6YWJsZUNhY2hlLFxyXG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5wZXJzaXN0ZW5jZVBsdWdpblxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIC8vIFZhbGlkYXRlIHJlc3BvbnNlLiBUaGlzIGZ1bmN0aW9uIHRocm93cyBhIHNlcnZlciBlcnJvciBpZiBhbiBlcnJvciBpcyByZXR1cm5lZCBieSB0aGUgc2VydmVyLlxyXG4gICAgICAgIHJlc3BvbnNlSGFuZGxlci52YWxpZGF0ZVRva2VuUmVzcG9uc2UocmVzcG9uc2UpO1xyXG4gICAgICAgIHJldHVybiBhd2FpdCByZXNwb25zZUhhbmRsZXIuaGFuZGxlU2VydmVyVG9rZW5SZXNwb25zZShcclxuICAgICAgICAgICAgcmVzcG9uc2UsXHJcbiAgICAgICAgICAgIHRoaXMuYXV0aG9yaXR5LFxyXG4gICAgICAgICAgICByZXFUaW1lc3RhbXAsXHJcbiAgICAgICAgICAgIHJlcXVlc3QucmVzb3VyY2VSZXF1ZXN0TWV0aG9kLFxyXG4gICAgICAgICAgICByZXF1ZXN0LnJlc291cmNlUmVxdWVzdFVyaVxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIGRldmljZSBjb2RlIHJlcXVlc3QgYW5kIGV4ZWN1dGVzIGh0dHAgR0VUXHJcbiAgICAgKiBAcGFyYW0gcmVxdWVzdFxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFzeW5jIGdldERldmljZUNvZGUocmVxdWVzdDogQ29tbW9uRGV2aWNlQ29kZVJlcXVlc3QpOiBQcm9taXNlPERldmljZUNvZGVSZXNwb25zZT4ge1xyXG4gICAgICAgIGNvbnN0IHF1ZXJ5U3RyaW5nID0gdGhpcy5jcmVhdGVRdWVyeVN0cmluZyhyZXF1ZXN0KTtcclxuICAgICAgICBjb25zdCBoZWFkZXJzID0gdGhpcy5jcmVhdGVEZWZhdWx0VG9rZW5SZXF1ZXN0SGVhZGVycygpO1xyXG4gICAgICAgIGNvbnN0IHRodW1icHJpbnQ6IFJlcXVlc3RUaHVtYnByaW50ID0ge1xyXG4gICAgICAgICAgICBjbGllbnRJZDogdGhpcy5jb25maWcuYXV0aE9wdGlvbnMuY2xpZW50SWQsXHJcbiAgICAgICAgICAgIGF1dGhvcml0eTogcmVxdWVzdC5hdXRob3JpdHksXHJcbiAgICAgICAgICAgIHNjb3BlczogcmVxdWVzdC5zY29wZXNcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICByZXR1cm4gdGhpcy5leGVjdXRlUG9zdFJlcXVlc3RUb0RldmljZUNvZGVFbmRwb2ludCh0aGlzLmF1dGhvcml0eS5kZXZpY2VDb2RlRW5kcG9pbnQsIHF1ZXJ5U3RyaW5nLCBoZWFkZXJzLCB0aHVtYnByaW50KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEV4ZWN1dGVzIFBPU1QgcmVxdWVzdCB0byBkZXZpY2UgY29kZSBlbmRwb2ludFxyXG4gICAgICogQHBhcmFtIGRldmljZUNvZGVFbmRwb2ludFxyXG4gICAgICogQHBhcmFtIHF1ZXJ5U3RyaW5nXHJcbiAgICAgKiBAcGFyYW0gaGVhZGVyc1xyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFzeW5jIGV4ZWN1dGVQb3N0UmVxdWVzdFRvRGV2aWNlQ29kZUVuZHBvaW50KFxyXG4gICAgICAgIGRldmljZUNvZGVFbmRwb2ludDogc3RyaW5nLFxyXG4gICAgICAgIHF1ZXJ5U3RyaW5nOiBzdHJpbmcsXHJcbiAgICAgICAgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPixcclxuICAgICAgICB0aHVtYnByaW50OiBSZXF1ZXN0VGh1bWJwcmludCk6IFByb21pc2U8RGV2aWNlQ29kZVJlc3BvbnNlPiB7XHJcblxyXG4gICAgICAgIGNvbnN0IHtcclxuICAgICAgICAgICAgYm9keToge1xyXG4gICAgICAgICAgICAgICAgdXNlcl9jb2RlOiB1c2VyQ29kZSxcclxuICAgICAgICAgICAgICAgIGRldmljZV9jb2RlOiBkZXZpY2VDb2RlLFxyXG4gICAgICAgICAgICAgICAgdmVyaWZpY2F0aW9uX3VyaTogdmVyaWZpY2F0aW9uVXJpLFxyXG4gICAgICAgICAgICAgICAgZXhwaXJlc19pbjogZXhwaXJlc0luLFxyXG4gICAgICAgICAgICAgICAgaW50ZXJ2YWwsXHJcbiAgICAgICAgICAgICAgICBtZXNzYWdlXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9ID0gYXdhaXQgdGhpcy5uZXR3b3JrTWFuYWdlci5zZW5kUG9zdFJlcXVlc3Q8U2VydmVyRGV2aWNlQ29kZVJlc3BvbnNlPihcclxuICAgICAgICAgICAgdGh1bWJwcmludCxcclxuICAgICAgICAgICAgZGV2aWNlQ29kZUVuZHBvaW50LFxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICBib2R5OiBxdWVyeVN0cmluZyxcclxuICAgICAgICAgICAgICAgIGhlYWRlcnM6IGhlYWRlcnNcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIHVzZXJDb2RlLFxyXG4gICAgICAgICAgICBkZXZpY2VDb2RlLFxyXG4gICAgICAgICAgICB2ZXJpZmljYXRpb25VcmksXHJcbiAgICAgICAgICAgIGV4cGlyZXNJbixcclxuICAgICAgICAgICAgaW50ZXJ2YWwsXHJcbiAgICAgICAgICAgIG1lc3NhZ2VcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlIGRldmljZSBjb2RlIGVuZHBvaW50IHF1ZXJ5IHBhcmFtZXRlcnMgYW5kIHJldHVybnMgc3RyaW5nXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgY3JlYXRlUXVlcnlTdHJpbmcocmVxdWVzdDogQ29tbW9uRGV2aWNlQ29kZVJlcXVlc3QpOiBzdHJpbmcge1xyXG5cclxuICAgICAgICBjb25zdCBwYXJhbWV0ZXJCdWlsZGVyOiBSZXF1ZXN0UGFyYW1ldGVyQnVpbGRlciA9IG5ldyBSZXF1ZXN0UGFyYW1ldGVyQnVpbGRlcigpO1xyXG5cclxuICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZFNjb3BlcyhyZXF1ZXN0LnNjb3Blcyk7XHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRDbGllbnRJZCh0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRJZCk7XHJcblxyXG4gICAgICAgIGlmICghU3RyaW5nVXRpbHMuaXNFbXB0eShyZXF1ZXN0LmNsYWltcykgfHwgdGhpcy5jb25maWcuYXV0aE9wdGlvbnMuY2xpZW50Q2FwYWJpbGl0aWVzICYmIHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudENhcGFiaWxpdGllcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkQ2xhaW1zKHJlcXVlc3QuY2xhaW1zLCB0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRDYXBhYmlsaXRpZXMpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHBhcmFtZXRlckJ1aWxkZXIuY3JlYXRlUXVlcnlTdHJpbmcoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZXMgdG9rZW4gcmVxdWVzdCB3aXRoIGRldmljZSBjb2RlIHJlc3BvbnNlIGFuZCBwb2xscyB0b2tlbiBlbmRwb2ludCBhdCBpbnRlcnZhbCBzZXQgYnkgdGhlIGRldmljZSBjb2RlXHJcbiAgICAgKiByZXNwb25zZVxyXG4gICAgICogQHBhcmFtIHJlcXVlc3RcclxuICAgICAqIEBwYXJhbSBkZXZpY2VDb2RlUmVzcG9uc2VcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhc3luYyBhY3F1aXJlVG9rZW5XaXRoRGV2aWNlQ29kZShcclxuICAgICAgICByZXF1ZXN0OiBDb21tb25EZXZpY2VDb2RlUmVxdWVzdCxcclxuICAgICAgICBkZXZpY2VDb2RlUmVzcG9uc2U6IERldmljZUNvZGVSZXNwb25zZSk6IFByb21pc2U8U2VydmVyQXV0aG9yaXphdGlvblRva2VuUmVzcG9uc2U+IHtcclxuXHJcbiAgICAgICAgY29uc3QgcmVxdWVzdEJvZHkgPSB0aGlzLmNyZWF0ZVRva2VuUmVxdWVzdEJvZHkocmVxdWVzdCwgZGV2aWNlQ29kZVJlc3BvbnNlKTtcclxuICAgICAgICBjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0gdGhpcy5jcmVhdGVEZWZhdWx0VG9rZW5SZXF1ZXN0SGVhZGVycygpO1xyXG5cclxuICAgICAgICBjb25zdCB1c2VyU3BlY2lmaWVkVGltZW91dCA9IHJlcXVlc3QudGltZW91dCA/IFRpbWVVdGlscy5ub3dTZWNvbmRzKCkgKyByZXF1ZXN0LnRpbWVvdXQgOiB1bmRlZmluZWQ7XHJcbiAgICAgICAgY29uc3QgZGV2aWNlQ29kZUV4cGlyYXRpb25UaW1lID0gVGltZVV0aWxzLm5vd1NlY29uZHMoKSArIGRldmljZUNvZGVSZXNwb25zZS5leHBpcmVzSW47XHJcbiAgICAgICAgY29uc3QgcG9sbGluZ0ludGVydmFsTWlsbGkgPSBkZXZpY2VDb2RlUmVzcG9uc2UuaW50ZXJ2YWwgKiAxMDAwO1xyXG5cclxuICAgICAgICAvKlxyXG4gICAgICAgICAqIFBvbGwgdG9rZW4gZW5kcG9pbnQgd2hpbGUgKGRldmljZSBjb2RlIGlzIG5vdCBleHBpcmVkIEFORCBvcGVyYXRpb24gaGFzIG5vdCBiZWVuIGNhbmNlbGxlZCBieVxyXG4gICAgICAgICAqIHNldHRpbmcgQ2FuY2VsbGF0aW9uVG9rZW4uY2FuY2VsID0gdHJ1ZSkuIFBPU1QgcmVxdWVzdCBpcyBzZW50IGF0IGludGVydmFsIHNldCBieSBwb2xsaW5nSW50ZXJ2YWxNaWxsaVxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxTZXJ2ZXJBdXRob3JpemF0aW9uVG9rZW5SZXNwb25zZT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG5cclxuICAgICAgICAgICAgY29uc3QgaW50ZXJ2YWxJZDogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gPSBzZXRJbnRlcnZhbChhc3luYyAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXF1ZXN0LmNhbmNlbCkge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoXCJUb2tlbiByZXF1ZXN0IGNhbmNlbGxlZCBieSBzZXR0aW5nIERldmljZUNvZGVSZXF1ZXN0LmNhbmNlbCA9IHRydWVcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwoaW50ZXJ2YWxJZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChDbGllbnRBdXRoRXJyb3IuY3JlYXRlRGV2aWNlQ29kZUNhbmNlbGxlZEVycm9yKCkpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHVzZXJTcGVjaWZpZWRUaW1lb3V0ICYmIHVzZXJTcGVjaWZpZWRUaW1lb3V0IDwgZGV2aWNlQ29kZUV4cGlyYXRpb25UaW1lICYmIFRpbWVVdGlscy5ub3dTZWNvbmRzKCkgPiB1c2VyU3BlY2lmaWVkVGltZW91dCkge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoYFVzZXIgZGVmaW5lZCB0aW1lb3V0IGZvciBkZXZpY2UgY29kZSBwb2xsaW5nIHJlYWNoZWQuIFRoZSB0aW1lb3V0IHdhcyBzZXQgZm9yICR7dXNlclNwZWNpZmllZFRpbWVvdXR9YCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwoaW50ZXJ2YWxJZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChDbGllbnRBdXRoRXJyb3IuY3JlYXRlVXNlclRpbWVvdXRSZWFjaGVkRXJyb3IoKSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoVGltZVV0aWxzLm5vd1NlY29uZHMoKSA+IGRldmljZUNvZGVFeHBpcmF0aW9uVGltZSkge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHVzZXJTcGVjaWZpZWRUaW1lb3V0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci52ZXJib3NlKGBVc2VyIHNwZWNpZmllZCB0aW1lb3V0IGlnbm9yZWQgYXMgdGhlIGRldmljZSBjb2RlIGhhcyBleHBpcmVkIGJlZm9yZSB0aGUgdGltZW91dCBlbGFwc2VkLiBUaGUgdXNlciBzcGVjaWZpZWQgdGltZW91dCB3YXMgc2V0IGZvciAke3VzZXJTcGVjaWZpZWRUaW1lb3V0fWApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihgRGV2aWNlIGNvZGUgZXhwaXJlZC4gRXhwaXJhdGlvbiB0aW1lIG9mIGRldmljZSBjb2RlIHdhcyAke2RldmljZUNvZGVFeHBpcmF0aW9uVGltZX1gKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJJbnRlcnZhbChpbnRlcnZhbElkKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KENsaWVudEF1dGhFcnJvci5jcmVhdGVEZXZpY2VDb2RlRXhwaXJlZEVycm9yKCkpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0aHVtYnByaW50OiBSZXF1ZXN0VGh1bWJwcmludCA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsaWVudElkOiB0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRJZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1dGhvcml0eTogcmVxdWVzdC5hdXRob3JpdHksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY29wZXM6IHJlcXVlc3Quc2NvcGVzXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5leGVjdXRlUG9zdFRvVG9rZW5FbmRwb2ludChcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYXV0aG9yaXR5LnRva2VuRW5kcG9pbnQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0Qm9keSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlcnMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHVtYnByaW50KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5ib2R5ICYmIHJlc3BvbnNlLmJvZHkuZXJyb3IgPT09IENvbnN0YW50cy5BVVRIT1JJWkFUSU9OX1BFTkRJTkcpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHVzZXIgYXV0aG9yaXphdGlvbiBpcyBwZW5kaW5nLiBTbGVlcCBmb3IgcG9sbGluZyBpbnRlcnZhbCBhbmQgdHJ5IGFnYWluXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci5pbmZvKHJlc3BvbnNlLmJvZHkuZXJyb3JfZGVzY3JpcHRpb24gfHwgXCJub19lcnJvcl9kZXNjcmlwdGlvblwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwoaW50ZXJ2YWxJZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlLmJvZHkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICAgICAgICAgICAgICBjbGVhckludGVydmFsKGludGVydmFsSWQpO1xyXG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0sIHBvbGxpbmdJbnRlcnZhbE1pbGxpKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZXMgcXVlcnkgcGFyYW1ldGVycyBhbmQgY29udmVydHMgdG8gc3RyaW5nLlxyXG4gICAgICogQHBhcmFtIHJlcXVlc3RcclxuICAgICAqIEBwYXJhbSBkZXZpY2VDb2RlUmVzcG9uc2VcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBjcmVhdGVUb2tlblJlcXVlc3RCb2R5KHJlcXVlc3Q6IENvbW1vbkRldmljZUNvZGVSZXF1ZXN0LCBkZXZpY2VDb2RlUmVzcG9uc2U6IERldmljZUNvZGVSZXNwb25zZSk6IHN0cmluZyB7XHJcblxyXG4gICAgICAgIGNvbnN0IHJlcXVlc3RQYXJhbWV0ZXJzOiBSZXF1ZXN0UGFyYW1ldGVyQnVpbGRlciA9IG5ldyBSZXF1ZXN0UGFyYW1ldGVyQnVpbGRlcigpO1xyXG5cclxuICAgICAgICByZXF1ZXN0UGFyYW1ldGVycy5hZGRTY29wZXMocmVxdWVzdC5zY29wZXMpO1xyXG4gICAgICAgIHJlcXVlc3RQYXJhbWV0ZXJzLmFkZENsaWVudElkKHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudElkKTtcclxuICAgICAgICByZXF1ZXN0UGFyYW1ldGVycy5hZGRHcmFudFR5cGUoR3JhbnRUeXBlLkRFVklDRV9DT0RFX0dSQU5UKTtcclxuICAgICAgICByZXF1ZXN0UGFyYW1ldGVycy5hZGREZXZpY2VDb2RlKGRldmljZUNvZGVSZXNwb25zZS5kZXZpY2VDb2RlKTtcclxuICAgICAgICBjb25zdCBjb3JyZWxhdGlvbklkID0gcmVxdWVzdC5jb3JyZWxhdGlvbklkIHx8IHRoaXMuY29uZmlnLmNyeXB0b0ludGVyZmFjZS5jcmVhdGVOZXdHdWlkKCk7XHJcbiAgICAgICAgcmVxdWVzdFBhcmFtZXRlcnMuYWRkQ29ycmVsYXRpb25JZChjb3JyZWxhdGlvbklkKTtcclxuICAgICAgICByZXF1ZXN0UGFyYW1ldGVycy5hZGRDbGllbnRJbmZvKCk7XHJcblxyXG4gICAgICAgIGlmICghU3RyaW5nVXRpbHMuaXNFbXB0eShyZXF1ZXN0LmNsYWltcykgfHwgdGhpcy5jb25maWcuYXV0aE9wdGlvbnMuY2xpZW50Q2FwYWJpbGl0aWVzICYmIHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudENhcGFiaWxpdGllcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIHJlcXVlc3RQYXJhbWV0ZXJzLmFkZENsYWltcyhyZXF1ZXN0LmNsYWltcywgdGhpcy5jb25maWcuYXV0aE9wdGlvbnMuY2xpZW50Q2FwYWJpbGl0aWVzKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHJlcXVlc3RQYXJhbWV0ZXJzLmNyZWF0ZVF1ZXJ5U3RyaW5nKCk7XHJcbiAgICB9XHJcbn1cclxuIiwiLypcclxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cclxuICovXHJcblxyXG5pbXBvcnQgeyBDbGllbnRDb25maWd1cmF0aW9uIH0gZnJvbSBcIi4uL2NvbmZpZy9DbGllbnRDb25maWd1cmF0aW9uXCI7XHJcbmltcG9ydCB7IEJhc2VDbGllbnQgfSBmcm9tIFwiLi9CYXNlQ2xpZW50XCI7XHJcbmltcG9ydCB7IENvbW1vblJlZnJlc2hUb2tlblJlcXVlc3QgfSBmcm9tIFwiLi4vcmVxdWVzdC9Db21tb25SZWZyZXNoVG9rZW5SZXF1ZXN0XCI7XHJcbmltcG9ydCB7IEF1dGhvcml0eSB9IGZyb20gXCIuLi9hdXRob3JpdHkvQXV0aG9yaXR5XCI7XHJcbmltcG9ydCB7IFNlcnZlckF1dGhvcml6YXRpb25Ub2tlblJlc3BvbnNlIH0gZnJvbSBcIi4uL3Jlc3BvbnNlL1NlcnZlckF1dGhvcml6YXRpb25Ub2tlblJlc3BvbnNlXCI7XHJcbmltcG9ydCB7IFJlcXVlc3RQYXJhbWV0ZXJCdWlsZGVyIH0gZnJvbSBcIi4uL3JlcXVlc3QvUmVxdWVzdFBhcmFtZXRlckJ1aWxkZXJcIjtcclxuaW1wb3J0IHsgR3JhbnRUeXBlLCBBdXRoZW50aWNhdGlvblNjaGVtZSwgRXJyb3JzICB9IGZyb20gXCIuLi91dGlscy9Db25zdGFudHNcIjtcclxuaW1wb3J0IHsgUmVzcG9uc2VIYW5kbGVyIH0gZnJvbSBcIi4uL3Jlc3BvbnNlL1Jlc3BvbnNlSGFuZGxlclwiO1xyXG5pbXBvcnQgeyBBdXRoZW50aWNhdGlvblJlc3VsdCB9IGZyb20gXCIuLi9yZXNwb25zZS9BdXRoZW50aWNhdGlvblJlc3VsdFwiO1xyXG5pbXBvcnQgeyBQb3BUb2tlbkdlbmVyYXRvciB9IGZyb20gXCIuLi9jcnlwdG8vUG9wVG9rZW5HZW5lcmF0b3JcIjtcclxuaW1wb3J0IHsgU3RyaW5nVXRpbHMgfSBmcm9tIFwiLi4vdXRpbHMvU3RyaW5nVXRpbHNcIjtcclxuaW1wb3J0IHsgUmVxdWVzdFRodW1icHJpbnQgfSBmcm9tIFwiLi4vbmV0d29yay9SZXF1ZXN0VGh1bWJwcmludFwiO1xyXG5pbXBvcnQgeyBOZXR3b3JrUmVzcG9uc2UgfSBmcm9tIFwiLi4vbmV0d29yay9OZXR3b3JrTWFuYWdlclwiO1xyXG5pbXBvcnQgeyBDb21tb25TaWxlbnRGbG93UmVxdWVzdCB9IGZyb20gXCIuLi9yZXF1ZXN0L0NvbW1vblNpbGVudEZsb3dSZXF1ZXN0XCI7XHJcbmltcG9ydCB7IENsaWVudENvbmZpZ3VyYXRpb25FcnJvciB9IGZyb20gXCIuLi9lcnJvci9DbGllbnRDb25maWd1cmF0aW9uRXJyb3JcIjtcclxuaW1wb3J0IHsgQ2xpZW50QXV0aEVycm9yLCBDbGllbnRBdXRoRXJyb3JNZXNzYWdlIH0gZnJvbSBcIi4uL2Vycm9yL0NsaWVudEF1dGhFcnJvclwiO1xyXG5pbXBvcnQgeyBTZXJ2ZXJFcnJvciB9IGZyb20gXCIuLi9lcnJvci9TZXJ2ZXJFcnJvclwiO1xyXG5pbXBvcnQgeyBUaW1lVXRpbHMgfSBmcm9tIFwiLi4vdXRpbHMvVGltZVV0aWxzXCI7XHJcblxyXG4vKipcclxuICogT0F1dGgyLjAgcmVmcmVzaCB0b2tlbiBjbGllbnRcclxuICovXHJcbmV4cG9ydCBjbGFzcyBSZWZyZXNoVG9rZW5DbGllbnQgZXh0ZW5kcyBCYXNlQ2xpZW50IHtcclxuXHJcbiAgICBjb25zdHJ1Y3Rvcihjb25maWd1cmF0aW9uOiBDbGllbnRDb25maWd1cmF0aW9uKSB7XHJcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGFzeW5jIGFjcXVpcmVUb2tlbihyZXF1ZXN0OiBDb21tb25SZWZyZXNoVG9rZW5SZXF1ZXN0KTogUHJvbWlzZTxBdXRoZW50aWNhdGlvblJlc3VsdD57XHJcbiAgICAgICAgY29uc3QgcmVxVGltZXN0YW1wID0gVGltZVV0aWxzLm5vd1NlY29uZHMoKTtcclxuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZXhlY3V0ZVRva2VuUmVxdWVzdChyZXF1ZXN0LCB0aGlzLmF1dGhvcml0eSk7XHJcblxyXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlSGFuZGxlciA9IG5ldyBSZXNwb25zZUhhbmRsZXIoXHJcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudElkLFxyXG4gICAgICAgICAgICB0aGlzLmNhY2hlTWFuYWdlcixcclxuICAgICAgICAgICAgdGhpcy5jcnlwdG9VdGlscyxcclxuICAgICAgICAgICAgdGhpcy5sb2dnZXIsXHJcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLnNlcmlhbGl6YWJsZUNhY2hlLFxyXG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5wZXJzaXN0ZW5jZVBsdWdpblxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIHJlc3BvbnNlSGFuZGxlci52YWxpZGF0ZVRva2VuUmVzcG9uc2UocmVzcG9uc2UuYm9keSk7XHJcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlSGFuZGxlci5oYW5kbGVTZXJ2ZXJUb2tlblJlc3BvbnNlKFxyXG4gICAgICAgICAgICByZXNwb25zZS5ib2R5LFxyXG4gICAgICAgICAgICB0aGlzLmF1dGhvcml0eSxcclxuICAgICAgICAgICAgcmVxVGltZXN0YW1wLFxyXG4gICAgICAgICAgICByZXF1ZXN0LnJlc291cmNlUmVxdWVzdE1ldGhvZCxcclxuICAgICAgICAgICAgcmVxdWVzdC5yZXNvdXJjZVJlcXVlc3RVcmksXHJcbiAgICAgICAgICAgIHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgW10sXHJcbiAgICAgICAgICAgIHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgdHJ1ZVxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIGNhY2hlZCByZWZyZXNoIHRva2VuIGFuZCBhdHRhY2hlcyB0byByZXF1ZXN0LCB0aGVuIGNhbGxzIGFjcXVpcmVUb2tlbiBBUElcclxuICAgICAqIEBwYXJhbSByZXF1ZXN0XHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBhc3luYyBhY3F1aXJlVG9rZW5CeVJlZnJlc2hUb2tlbihyZXF1ZXN0OiBDb21tb25TaWxlbnRGbG93UmVxdWVzdCk6IFByb21pc2U8QXV0aGVudGljYXRpb25SZXN1bHQ+IHtcclxuICAgICAgICAvLyBDYW5ub3QgcmVuZXcgdG9rZW4gaWYgbm8gcmVxdWVzdCBvYmplY3QgaXMgZ2l2ZW4uXHJcbiAgICAgICAgaWYgKCFyZXF1ZXN0KSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudENvbmZpZ3VyYXRpb25FcnJvci5jcmVhdGVFbXB0eVRva2VuUmVxdWVzdEVycm9yKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBXZSBjdXJyZW50bHkgZG8gbm90IHN1cHBvcnQgc2lsZW50IGZsb3cgZm9yIGFjY291bnQgPT09IG51bGwgdXNlIGNhc2VzOyBUaGlzIHdpbGwgYmUgcmV2aXNpdGVkIGZvciBjb25maWRlbnRpYWwgZmxvdyB1c2VjYXNlc1xyXG4gICAgICAgIGlmICghcmVxdWVzdC5hY2NvdW50KSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVOb0FjY291bnRJblNpbGVudFJlcXVlc3RFcnJvcigpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gdHJ5IGNoZWNraW5nIGlmIEZPQ0kgaXMgZW5hYmxlZCBmb3IgdGhlIGdpdmVuIGFwcGxpY2F0aW9uXHJcbiAgICAgICAgY29uc3QgaXNGT0NJID0gdGhpcy5jYWNoZU1hbmFnZXIuaXNBcHBNZXRhZGF0YUZPQ0kocmVxdWVzdC5hY2NvdW50LmVudmlyb25tZW50LCB0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRJZCk7XHJcblxyXG4gICAgICAgIC8vIGlmIHRoZSBhcHAgaXMgcGFydCBvZiB0aGUgZmFtaWx5LCByZXRyaXZlIGEgRmFtaWx5IHJlZnJlc2ggdG9rZW4gaWYgcHJlc2VudCBhbmQgbWFrZSBhIHJlZnJlc2hUb2tlblJlcXVlc3RcclxuICAgICAgICBpZiAoaXNGT0NJKSB7XHJcbiAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3F1aXJlVG9rZW5XaXRoQ2FjaGVkUmVmcmVzaFRva2VuKHJlcXVlc3QsIHRydWUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBub0ZhbWlseVJUSW5DYWNoZSA9IGUgaW5zdGFuY2VvZiBDbGllbnRBdXRoRXJyb3IgJiYgZS5lcnJvckNvZGUgPT09IENsaWVudEF1dGhFcnJvck1lc3NhZ2Uubm9Ub2tlbnNGb3VuZEVycm9yLmNvZGU7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBjbGllbnRNaXNtYXRjaEVycm9yV2l0aEZhbWlseVJUID0gZSBpbnN0YW5jZW9mIFNlcnZlckVycm9yICYmIGUuZXJyb3JDb2RlID09PSBFcnJvcnMuSU5WQUxJRF9HUkFOVF9FUlJPUiAmJiBlLnN1YkVycm9yID09PSBFcnJvcnMuQ0xJRU5UX01JU01BVENIX0VSUk9SO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIGlmIGZhbWlseSBSZWZyZXNoIFRva2VuIChGUlQpIGNhY2hlIGFjcXVpc2l0aW9uIGZhaWxzIG9yIGlmIGNsaWVudF9taXNtYXRjaCBlcnJvciBpcyBzZWVuIHdpdGggRlJULCByZWF0dGVtcHQgd2l0aCBhcHBsaWNhdGlvbiBSZWZyZXNoIFRva2VuIChBUlQpXHJcbiAgICAgICAgICAgICAgICBpZiAobm9GYW1pbHlSVEluQ2FjaGUgfHwgY2xpZW50TWlzbWF0Y2hFcnJvcldpdGhGYW1pbHlSVCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFjcXVpcmVUb2tlbldpdGhDYWNoZWRSZWZyZXNoVG9rZW4ocmVxdWVzdCwgZmFsc2UpO1xyXG4gICAgICAgICAgICAgICAgLy8gdGhyb3cgaW4gYWxsIG90aGVyIGNhc2VzXHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIHRocm93IGU7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIGZhbGwgYmFjayB0byBhcHBsaWNhdGlvbiByZWZyZXNoIHRva2VuIGFjcXVpc2l0aW9uXHJcbiAgICAgICAgcmV0dXJuIHRoaXMuYWNxdWlyZVRva2VuV2l0aENhY2hlZFJlZnJlc2hUb2tlbihyZXF1ZXN0LCBmYWxzZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBtYWtlcyBhIG5ldHdvcmsgY2FsbCB0byBhY3F1aXJlIHRva2VucyBieSBleGNoYW5naW5nIFJlZnJlc2hUb2tlbiBhdmFpbGFibGUgaW4gdXNlckNhY2hlOyB0aHJvd3MgaWYgcmVmcmVzaCB0b2tlbiBpcyBub3QgY2FjaGVkXHJcbiAgICAgKiBAcGFyYW0gcmVxdWVzdFxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFzeW5jIGFjcXVpcmVUb2tlbldpdGhDYWNoZWRSZWZyZXNoVG9rZW4ocmVxdWVzdDogQ29tbW9uU2lsZW50Rmxvd1JlcXVlc3QsIGZvY2k6IGJvb2xlYW4pIHtcclxuICAgICAgICAvLyBmZXRjaGVzIGZhbWlseSBSVCBvciBhcHBsaWNhdGlvbiBSVCBiYXNlZCBvbiBGT0NJIHZhbHVlXHJcbiAgICAgICAgY29uc3QgcmVmcmVzaFRva2VuID0gdGhpcy5jYWNoZU1hbmFnZXIucmVhZFJlZnJlc2hUb2tlbkZyb21DYWNoZSh0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRJZCwgcmVxdWVzdC5hY2NvdW50LCBmb2NpKTtcclxuXHJcbiAgICAgICAgLy8gbm8gcmVmcmVzaCBUb2tlblxyXG4gICAgICAgIGlmICghcmVmcmVzaFRva2VuKSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVOb1Rva2Vuc0ZvdW5kRXJyb3IoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHJlZnJlc2hUb2tlblJlcXVlc3Q6IENvbW1vblJlZnJlc2hUb2tlblJlcXVlc3QgPSB7XHJcbiAgICAgICAgICAgIC4uLnJlcXVlc3QsXHJcbiAgICAgICAgICAgIHJlZnJlc2hUb2tlbjogcmVmcmVzaFRva2VuLnNlY3JldCxcclxuICAgICAgICAgICAgYXV0aGVudGljYXRpb25TY2hlbWU6IEF1dGhlbnRpY2F0aW9uU2NoZW1lLkJFQVJFUlxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzLmFjcXVpcmVUb2tlbihyZWZyZXNoVG9rZW5SZXF1ZXN0KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbnN0cnVjdHMgdGhlIG5ldHdvcmsgbWVzc2FnZSBhbmQgbWFrZXMgYSBOVyBjYWxsIHRvIHRoZSB1bmRlcmx5aW5nIHNlY3VyZSB0b2tlbiBzZXJ2aWNlXHJcbiAgICAgKiBAcGFyYW0gcmVxdWVzdFxyXG4gICAgICogQHBhcmFtIGF1dGhvcml0eVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFzeW5jIGV4ZWN1dGVUb2tlblJlcXVlc3QocmVxdWVzdDogQ29tbW9uUmVmcmVzaFRva2VuUmVxdWVzdCwgYXV0aG9yaXR5OiBBdXRob3JpdHkpXHJcbiAgICAgICAgOiBQcm9taXNlPE5ldHdvcmtSZXNwb25zZTxTZXJ2ZXJBdXRob3JpemF0aW9uVG9rZW5SZXNwb25zZT4+IHtcclxuXHJcbiAgICAgICAgY29uc3QgcmVxdWVzdEJvZHkgPSBhd2FpdCB0aGlzLmNyZWF0ZVRva2VuUmVxdWVzdEJvZHkocmVxdWVzdCk7XHJcbiAgICAgICAgY29uc3QgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHRoaXMuY3JlYXRlRGVmYXVsdFRva2VuUmVxdWVzdEhlYWRlcnMoKTtcclxuICAgICAgICBjb25zdCB0aHVtYnByaW50OiBSZXF1ZXN0VGh1bWJwcmludCA9IHtcclxuICAgICAgICAgICAgY2xpZW50SWQ6IHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudElkLFxyXG4gICAgICAgICAgICBhdXRob3JpdHk6IGF1dGhvcml0eS5jYW5vbmljYWxBdXRob3JpdHksXHJcbiAgICAgICAgICAgIHNjb3BlczogcmVxdWVzdC5zY29wZXNcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICByZXR1cm4gdGhpcy5leGVjdXRlUG9zdFRvVG9rZW5FbmRwb2ludChhdXRob3JpdHkudG9rZW5FbmRwb2ludCwgcmVxdWVzdEJvZHksIGhlYWRlcnMsIHRodW1icHJpbnQpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGVscGVyIGZ1bmN0aW9uIHRvIGNyZWF0ZSB0aGUgdG9rZW4gcmVxdWVzdCBib2R5XHJcbiAgICAgKiBAcGFyYW0gcmVxdWVzdFxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFzeW5jIGNyZWF0ZVRva2VuUmVxdWVzdEJvZHkocmVxdWVzdDogQ29tbW9uUmVmcmVzaFRva2VuUmVxdWVzdCk6IFByb21pc2U8c3RyaW5nPiB7XHJcbiAgICAgICAgY29uc3QgcGFyYW1ldGVyQnVpbGRlciA9IG5ldyBSZXF1ZXN0UGFyYW1ldGVyQnVpbGRlcigpO1xyXG5cclxuICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZENsaWVudElkKHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudElkKTtcclxuXHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRTY29wZXMocmVxdWVzdC5zY29wZXMpO1xyXG5cclxuICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZEdyYW50VHlwZShHcmFudFR5cGUuUkVGUkVTSF9UT0tFTl9HUkFOVCk7XHJcblxyXG4gICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkQ2xpZW50SW5mbygpO1xyXG5cclxuICAgICAgICBjb25zdCBjb3JyZWxhdGlvbklkID0gcmVxdWVzdC5jb3JyZWxhdGlvbklkIHx8IHRoaXMuY29uZmlnLmNyeXB0b0ludGVyZmFjZS5jcmVhdGVOZXdHdWlkKCk7XHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRDb3JyZWxhdGlvbklkKGNvcnJlbGF0aW9uSWQpO1xyXG5cclxuICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZFJlZnJlc2hUb2tlbihyZXF1ZXN0LnJlZnJlc2hUb2tlbik7XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmNvbmZpZy5jbGllbnRDcmVkZW50aWFscy5jbGllbnRTZWNyZXQpIHtcclxuICAgICAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRDbGllbnRTZWNyZXQodGhpcy5jb25maWcuY2xpZW50Q3JlZGVudGlhbHMuY2xpZW50U2VjcmV0KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmNvbmZpZy5jbGllbnRDcmVkZW50aWFscy5jbGllbnRBc3NlcnRpb24pIHtcclxuICAgICAgICAgICAgY29uc3QgY2xpZW50QXNzZXJ0aW9uID0gdGhpcy5jb25maWcuY2xpZW50Q3JlZGVudGlhbHMuY2xpZW50QXNzZXJ0aW9uO1xyXG4gICAgICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZENsaWVudEFzc2VydGlvbihjbGllbnRBc3NlcnRpb24uYXNzZXJ0aW9uKTtcclxuICAgICAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRDbGllbnRBc3NlcnRpb25UeXBlKGNsaWVudEFzc2VydGlvbi5hc3NlcnRpb25UeXBlKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChyZXF1ZXN0LmF1dGhlbnRpY2F0aW9uU2NoZW1lID09PSBBdXRoZW50aWNhdGlvblNjaGVtZS5QT1ApIHtcclxuICAgICAgICAgICAgY29uc3QgcG9wVG9rZW5HZW5lcmF0b3IgPSBuZXcgUG9wVG9rZW5HZW5lcmF0b3IodGhpcy5jcnlwdG9VdGlscyk7XHJcbiAgICAgICAgICAgIGlmICghcmVxdWVzdC5yZXNvdXJjZVJlcXVlc3RNZXRob2QgfHwgIXJlcXVlc3QucmVzb3VyY2VSZXF1ZXN0VXJpKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBDbGllbnRDb25maWd1cmF0aW9uRXJyb3IuY3JlYXRlUmVzb3VyY2VSZXF1ZXN0UGFyYW1ldGVyc1JlcXVpcmVkRXJyb3IoKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRQb3BUb2tlbihhd2FpdCBwb3BUb2tlbkdlbmVyYXRvci5nZW5lcmF0ZUNuZihyZXF1ZXN0LnJlc291cmNlUmVxdWVzdE1ldGhvZCwgcmVxdWVzdC5yZXNvdXJjZVJlcXVlc3RVcmkpKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICghU3RyaW5nVXRpbHMuaXNFbXB0eShyZXF1ZXN0LmNsYWltcykgfHwgdGhpcy5jb25maWcuYXV0aE9wdGlvbnMuY2xpZW50Q2FwYWJpbGl0aWVzICYmIHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudENhcGFiaWxpdGllcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkQ2xhaW1zKHJlcXVlc3QuY2xhaW1zLCB0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRDYXBhYmlsaXRpZXMpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHBhcmFtZXRlckJ1aWxkZXIuY3JlYXRlUXVlcnlTdHJpbmcoKTtcclxuICAgIH1cclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IENsaWVudENvbmZpZ3VyYXRpb24gfSBmcm9tIFwiLi4vY29uZmlnL0NsaWVudENvbmZpZ3VyYXRpb25cIjtcclxuaW1wb3J0IHsgQmFzZUNsaWVudCB9IGZyb20gXCIuL0Jhc2VDbGllbnRcIjtcclxuaW1wb3J0IHsgQXV0aG9yaXR5IH0gZnJvbSBcIi4uL2F1dGhvcml0eS9BdXRob3JpdHlcIjtcclxuaW1wb3J0IHsgUmVxdWVzdFBhcmFtZXRlckJ1aWxkZXIgfSBmcm9tIFwiLi4vcmVxdWVzdC9SZXF1ZXN0UGFyYW1ldGVyQnVpbGRlclwiO1xyXG5pbXBvcnQgeyBTY29wZVNldCB9IGZyb20gXCIuLi9yZXF1ZXN0L1Njb3BlU2V0XCI7XHJcbmltcG9ydCB7IEdyYW50VHlwZSAsIENyZWRlbnRpYWxUeXBlIH0gZnJvbSBcIi4uL3V0aWxzL0NvbnN0YW50c1wiO1xyXG5pbXBvcnQgeyBSZXNwb25zZUhhbmRsZXIgfSBmcm9tIFwiLi4vcmVzcG9uc2UvUmVzcG9uc2VIYW5kbGVyXCI7XHJcbmltcG9ydCB7IEF1dGhlbnRpY2F0aW9uUmVzdWx0IH0gZnJvbSBcIi4uL3Jlc3BvbnNlL0F1dGhlbnRpY2F0aW9uUmVzdWx0XCI7XHJcbmltcG9ydCB7IENvbW1vbkNsaWVudENyZWRlbnRpYWxSZXF1ZXN0IH0gZnJvbSBcIi4uL3JlcXVlc3QvQ29tbW9uQ2xpZW50Q3JlZGVudGlhbFJlcXVlc3RcIjtcclxuaW1wb3J0IHsgQ3JlZGVudGlhbEZpbHRlciwgQ3JlZGVudGlhbENhY2hlIH0gZnJvbSBcIi4uL2NhY2hlL3V0aWxzL0NhY2hlVHlwZXNcIjtcclxuaW1wb3J0IHsgQWNjZXNzVG9rZW5FbnRpdHkgfSBmcm9tIFwiLi4vY2FjaGUvZW50aXRpZXMvQWNjZXNzVG9rZW5FbnRpdHlcIjtcclxuaW1wb3J0IHsgVGltZVV0aWxzIH0gZnJvbSBcIi4uL3V0aWxzL1RpbWVVdGlsc1wiO1xyXG5pbXBvcnQgeyBTdHJpbmdVdGlscyB9IGZyb20gXCIuLi91dGlscy9TdHJpbmdVdGlsc1wiO1xyXG5pbXBvcnQgeyBSZXF1ZXN0VGh1bWJwcmludCB9IGZyb20gXCIuLi9uZXR3b3JrL1JlcXVlc3RUaHVtYnByaW50XCI7XHJcbmltcG9ydCB7IENsaWVudEF1dGhFcnJvciB9IGZyb20gXCIuLi9lcnJvci9DbGllbnRBdXRoRXJyb3JcIjtcclxuXHJcbi8qKlxyXG4gKiBPQXV0aDIuMCBjbGllbnQgY3JlZGVudGlhbCBncmFudFxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIENsaWVudENyZWRlbnRpYWxDbGllbnQgZXh0ZW5kcyBCYXNlQ2xpZW50IHtcclxuXHJcbiAgICBwcml2YXRlIHNjb3BlU2V0OiBTY29wZVNldDtcclxuXHJcbiAgICBjb25zdHJ1Y3Rvcihjb25maWd1cmF0aW9uOiBDbGllbnRDb25maWd1cmF0aW9uKSB7XHJcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBQdWJsaWMgQVBJIHRvIGFjcXVpcmUgYSB0b2tlbiB3aXRoIENsaWVudENyZWRlbnRpYWwgRmxvdyBmb3IgQ29uZmlkZW50aWFsIGNsaWVudHNcclxuICAgICAqIEBwYXJhbSByZXF1ZXN0XHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBhc3luYyBhY3F1aXJlVG9rZW4ocmVxdWVzdDogQ29tbW9uQ2xpZW50Q3JlZGVudGlhbFJlcXVlc3QpOiBQcm9taXNlPEF1dGhlbnRpY2F0aW9uUmVzdWx0IHwgbnVsbD4ge1xyXG5cclxuICAgICAgICB0aGlzLnNjb3BlU2V0ID0gbmV3IFNjb3BlU2V0KHJlcXVlc3Quc2NvcGVzIHx8IFtdKTtcclxuXHJcbiAgICAgICAgaWYgKHJlcXVlc3Quc2tpcENhY2hlKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmV4ZWN1dGVUb2tlblJlcXVlc3QocmVxdWVzdCwgdGhpcy5hdXRob3JpdHkpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgY2FjaGVkQXV0aGVudGljYXRpb25SZXN1bHQgPSBhd2FpdCB0aGlzLmdldENhY2hlZEF1dGhlbnRpY2F0aW9uUmVzdWx0KCk7XHJcbiAgICAgICAgaWYgKGNhY2hlZEF1dGhlbnRpY2F0aW9uUmVzdWx0KSB7XHJcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRBdXRoZW50aWNhdGlvblJlc3VsdDtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5leGVjdXRlVG9rZW5SZXF1ZXN0KHJlcXVlc3QsIHRoaXMuYXV0aG9yaXR5KTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBsb29rcyB1cCBjYWNoZSBpZiB0aGUgdG9rZW5zIGFyZSBjYWNoZWQgYWxyZWFkeVxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGFzeW5jIGdldENhY2hlZEF1dGhlbnRpY2F0aW9uUmVzdWx0KCk6IFByb21pc2U8QXV0aGVudGljYXRpb25SZXN1bHQgfCBudWxsPiB7XHJcbiAgICAgICAgY29uc3QgY2FjaGVkQWNjZXNzVG9rZW4gPSB0aGlzLnJlYWRBY2Nlc3NUb2tlbkZyb21DYWNoZSgpO1xyXG4gICAgICAgIGlmICghY2FjaGVkQWNjZXNzVG9rZW4gfHxcclxuICAgICAgICAgICAgVGltZVV0aWxzLmlzVG9rZW5FeHBpcmVkKGNhY2hlZEFjY2Vzc1Rva2VuLmV4cGlyZXNPbiwgdGhpcy5jb25maWcuc3lzdGVtT3B0aW9ucy50b2tlblJlbmV3YWxPZmZzZXRTZWNvbmRzKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBhd2FpdCBSZXNwb25zZUhhbmRsZXIuZ2VuZXJhdGVBdXRoZW50aWNhdGlvblJlc3VsdChcclxuICAgICAgICAgICAgdGhpcy5jcnlwdG9VdGlscyxcclxuICAgICAgICAgICAgdGhpcy5hdXRob3JpdHksXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIGFjY291bnQ6IG51bGwsXHJcbiAgICAgICAgICAgICAgICBpZFRva2VuOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgYWNjZXNzVG9rZW46IGNhY2hlZEFjY2Vzc1Rva2VuLFxyXG4gICAgICAgICAgICAgICAgcmVmcmVzaFRva2VuOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgYXBwTWV0YWRhdGE6IG51bGxcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgdHJ1ZVxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWFkcyBhY2Nlc3MgdG9rZW4gZnJvbSB0aGUgY2FjaGVcclxuICAgICAqIFRPRE86IE1vdmUgdGhpcyBjYWxsIHRvIGNhY2hlTWFuYWdlciBpbnN0ZWFkXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgcmVhZEFjY2Vzc1Rva2VuRnJvbUNhY2hlKCk6IEFjY2Vzc1Rva2VuRW50aXR5IHwgbnVsbCB7XHJcbiAgICAgICAgY29uc3QgYWNjZXNzVG9rZW5GaWx0ZXI6IENyZWRlbnRpYWxGaWx0ZXIgPSB7XHJcbiAgICAgICAgICAgIGhvbWVBY2NvdW50SWQ6IFwiXCIsXHJcbiAgICAgICAgICAgIGVudmlyb25tZW50OiB0aGlzLmF1dGhvcml0eS5jYW5vbmljYWxBdXRob3JpdHlVcmxDb21wb25lbnRzLkhvc3ROYW1lQW5kUG9ydCxcclxuICAgICAgICAgICAgY3JlZGVudGlhbFR5cGU6IENyZWRlbnRpYWxUeXBlLkFDQ0VTU19UT0tFTixcclxuICAgICAgICAgICAgY2xpZW50SWQ6IHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudElkLFxyXG4gICAgICAgICAgICByZWFsbTogdGhpcy5hdXRob3JpdHkudGVuYW50LFxyXG4gICAgICAgICAgICB0YXJnZXQ6IHRoaXMuc2NvcGVTZXQucHJpbnRTY29wZXNMb3dlckNhc2UoKVxyXG4gICAgICAgIH07XHJcbiAgICAgICAgY29uc3QgY3JlZGVudGlhbENhY2hlOiBDcmVkZW50aWFsQ2FjaGUgPSB0aGlzLmNhY2hlTWFuYWdlci5nZXRDcmVkZW50aWFsc0ZpbHRlcmVkQnkoYWNjZXNzVG9rZW5GaWx0ZXIpO1xyXG4gICAgICAgIGNvbnN0IGFjY2Vzc1Rva2VucyA9IE9iamVjdC5rZXlzKGNyZWRlbnRpYWxDYWNoZS5hY2Nlc3NUb2tlbnMpLm1hcChrZXkgPT4gY3JlZGVudGlhbENhY2hlLmFjY2Vzc1Rva2Vuc1trZXldKTtcclxuICAgICAgICBpZiAoYWNjZXNzVG9rZW5zLmxlbmd0aCA8IDEpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfSBlbHNlIGlmIChhY2Nlc3NUb2tlbnMubGVuZ3RoID4gMSkge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRBdXRoRXJyb3IuY3JlYXRlTXVsdGlwbGVNYXRjaGluZ1Rva2Vuc0luQ2FjaGVFcnJvcigpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gYWNjZXNzVG9rZW5zWzBdIGFzIEFjY2Vzc1Rva2VuRW50aXR5O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWFrZXMgYSBuZXR3b3JrIGNhbGwgdG8gcmVxdWVzdCB0aGUgdG9rZW4gZnJvbSB0aGUgc2VydmljZVxyXG4gICAgICogQHBhcmFtIHJlcXVlc3RcclxuICAgICAqIEBwYXJhbSBhdXRob3JpdHlcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhc3luYyBleGVjdXRlVG9rZW5SZXF1ZXN0KHJlcXVlc3Q6IENvbW1vbkNsaWVudENyZWRlbnRpYWxSZXF1ZXN0LCBhdXRob3JpdHk6IEF1dGhvcml0eSlcclxuICAgICAgICA6IFByb21pc2U8QXV0aGVudGljYXRpb25SZXN1bHQgfCBudWxsPiB7XHJcblxyXG4gICAgICAgIGNvbnN0IHJlcXVlc3RCb2R5ID0gdGhpcy5jcmVhdGVUb2tlblJlcXVlc3RCb2R5KHJlcXVlc3QpO1xyXG4gICAgICAgIGNvbnN0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB0aGlzLmNyZWF0ZURlZmF1bHRUb2tlblJlcXVlc3RIZWFkZXJzKCk7XHJcbiAgICAgICAgY29uc3QgdGh1bWJwcmludDogUmVxdWVzdFRodW1icHJpbnQgPSB7XHJcbiAgICAgICAgICAgIGNsaWVudElkOiB0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRJZCxcclxuICAgICAgICAgICAgYXV0aG9yaXR5OiByZXF1ZXN0LmF1dGhvcml0eSxcclxuICAgICAgICAgICAgc2NvcGVzOiByZXF1ZXN0LnNjb3Blc1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIGNvbnN0IHJlcVRpbWVzdGFtcCA9IFRpbWVVdGlscy5ub3dTZWNvbmRzKCk7XHJcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmV4ZWN1dGVQb3N0VG9Ub2tlbkVuZHBvaW50KGF1dGhvcml0eS50b2tlbkVuZHBvaW50LCByZXF1ZXN0Qm9keSwgaGVhZGVycywgdGh1bWJwcmludCk7XHJcblxyXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlSGFuZGxlciA9IG5ldyBSZXNwb25zZUhhbmRsZXIoXHJcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudElkLFxyXG4gICAgICAgICAgICB0aGlzLmNhY2hlTWFuYWdlcixcclxuICAgICAgICAgICAgdGhpcy5jcnlwdG9VdGlscyxcclxuICAgICAgICAgICAgdGhpcy5sb2dnZXIsXHJcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLnNlcmlhbGl6YWJsZUNhY2hlLFxyXG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5wZXJzaXN0ZW5jZVBsdWdpblxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIHJlc3BvbnNlSGFuZGxlci52YWxpZGF0ZVRva2VuUmVzcG9uc2UocmVzcG9uc2UuYm9keSk7XHJcbiAgICAgICAgY29uc3QgdG9rZW5SZXNwb25zZSA9IGF3YWl0IHJlc3BvbnNlSGFuZGxlci5oYW5kbGVTZXJ2ZXJUb2tlblJlc3BvbnNlKFxyXG4gICAgICAgICAgICByZXNwb25zZS5ib2R5LFxyXG4gICAgICAgICAgICB0aGlzLmF1dGhvcml0eSxcclxuICAgICAgICAgICAgcmVxVGltZXN0YW1wLFxyXG4gICAgICAgICAgICByZXF1ZXN0LnJlc291cmNlUmVxdWVzdE1ldGhvZCxcclxuICAgICAgICAgICAgcmVxdWVzdC5yZXNvdXJjZVJlcXVlc3RVcmksXHJcbiAgICAgICAgICAgIHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgcmVxdWVzdC5zY29wZXNcclxuICAgICAgICApO1xyXG5cclxuICAgICAgICByZXR1cm4gdG9rZW5SZXNwb25zZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGdlbmVyYXRlIHRoZSByZXF1ZXN0IHRvIHRoZSBzZXJ2ZXIgaW4gdGhlIGFjY2VwdGFibGUgZm9ybWF0XHJcbiAgICAgKiBAcGFyYW0gcmVxdWVzdFxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGNyZWF0ZVRva2VuUmVxdWVzdEJvZHkocmVxdWVzdDogQ29tbW9uQ2xpZW50Q3JlZGVudGlhbFJlcXVlc3QpOiBzdHJpbmcge1xyXG4gICAgICAgIGNvbnN0IHBhcmFtZXRlckJ1aWxkZXIgPSBuZXcgUmVxdWVzdFBhcmFtZXRlckJ1aWxkZXIoKTtcclxuXHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRDbGllbnRJZCh0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRJZCk7XHJcblxyXG4gICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkU2NvcGVzKHJlcXVlc3Quc2NvcGVzLCBmYWxzZSk7XHJcblxyXG4gICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkR3JhbnRUeXBlKEdyYW50VHlwZS5DTElFTlRfQ1JFREVOVElBTFNfR1JBTlQpO1xyXG5cclxuICAgICAgICBjb25zdCBjb3JyZWxhdGlvbklkID0gcmVxdWVzdC5jb3JyZWxhdGlvbklkIHx8IHRoaXMuY29uZmlnLmNyeXB0b0ludGVyZmFjZS5jcmVhdGVOZXdHdWlkKCk7XHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRDb3JyZWxhdGlvbklkKGNvcnJlbGF0aW9uSWQpO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5jb25maWcuY2xpZW50Q3JlZGVudGlhbHMuY2xpZW50U2VjcmV0KSB7XHJcbiAgICAgICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkQ2xpZW50U2VjcmV0KHRoaXMuY29uZmlnLmNsaWVudENyZWRlbnRpYWxzLmNsaWVudFNlY3JldCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhpcy5jb25maWcuY2xpZW50Q3JlZGVudGlhbHMuY2xpZW50QXNzZXJ0aW9uKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGNsaWVudEFzc2VydGlvbiA9IHRoaXMuY29uZmlnLmNsaWVudENyZWRlbnRpYWxzLmNsaWVudEFzc2VydGlvbjtcclxuICAgICAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRDbGllbnRBc3NlcnRpb24oY2xpZW50QXNzZXJ0aW9uLmFzc2VydGlvbik7XHJcbiAgICAgICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkQ2xpZW50QXNzZXJ0aW9uVHlwZShjbGllbnRBc3NlcnRpb24uYXNzZXJ0aW9uVHlwZSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIVN0cmluZ1V0aWxzLmlzRW1wdHkocmVxdWVzdC5jbGFpbXMpIHx8IHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudENhcGFiaWxpdGllcyAmJiB0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRDYXBhYmlsaXRpZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZENsYWltcyhyZXF1ZXN0LmNsYWltcywgdGhpcy5jb25maWcuYXV0aE9wdGlvbnMuY2xpZW50Q2FwYWJpbGl0aWVzKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBwYXJhbWV0ZXJCdWlsZGVyLmNyZWF0ZVF1ZXJ5U3RyaW5nKCk7XHJcbiAgICB9XHJcbn1cclxuIiwiLypcclxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cclxuICovXHJcblxyXG5pbXBvcnQgeyBDbGllbnRDb25maWd1cmF0aW9uIH0gZnJvbSBcIi4uL2NvbmZpZy9DbGllbnRDb25maWd1cmF0aW9uXCI7XHJcbmltcG9ydCB7IEJhc2VDbGllbnQgfSBmcm9tIFwiLi9CYXNlQ2xpZW50XCI7XHJcbmltcG9ydCB7IEF1dGhvcml0eSB9IGZyb20gXCIuLi9hdXRob3JpdHkvQXV0aG9yaXR5XCI7XHJcbmltcG9ydCB7IFJlcXVlc3RQYXJhbWV0ZXJCdWlsZGVyIH0gZnJvbSBcIi4uL3JlcXVlc3QvUmVxdWVzdFBhcmFtZXRlckJ1aWxkZXJcIjtcclxuaW1wb3J0IHsgU2NvcGVTZXQgfSBmcm9tIFwiLi4vcmVxdWVzdC9TY29wZVNldFwiO1xyXG5pbXBvcnQgeyBHcmFudFR5cGUsIEFBRFNlcnZlclBhcmFtS2V5cyAsIENyZWRlbnRpYWxUeXBlLCBDb25zdGFudHMgfSBmcm9tIFwiLi4vdXRpbHMvQ29uc3RhbnRzXCI7XHJcbmltcG9ydCB7IFJlc3BvbnNlSGFuZGxlciB9IGZyb20gXCIuLi9yZXNwb25zZS9SZXNwb25zZUhhbmRsZXJcIjtcclxuaW1wb3J0IHsgQXV0aGVudGljYXRpb25SZXN1bHQgfSBmcm9tIFwiLi4vcmVzcG9uc2UvQXV0aGVudGljYXRpb25SZXN1bHRcIjtcclxuaW1wb3J0IHsgQ29tbW9uT25CZWhhbGZPZlJlcXVlc3QgfSBmcm9tIFwiLi4vcmVxdWVzdC9Db21tb25PbkJlaGFsZk9mUmVxdWVzdFwiO1xyXG5pbXBvcnQgeyBUaW1lVXRpbHMgfSBmcm9tIFwiLi4vdXRpbHMvVGltZVV0aWxzXCI7XHJcbmltcG9ydCB7IENyZWRlbnRpYWxGaWx0ZXIsIENyZWRlbnRpYWxDYWNoZSB9IGZyb20gXCIuLi9jYWNoZS91dGlscy9DYWNoZVR5cGVzXCI7XHJcbmltcG9ydCB7IEFjY2Vzc1Rva2VuRW50aXR5IH0gZnJvbSBcIi4uL2NhY2hlL2VudGl0aWVzL0FjY2Vzc1Rva2VuRW50aXR5XCI7XHJcbmltcG9ydCB7IElkVG9rZW5FbnRpdHkgfSBmcm9tIFwiLi4vY2FjaGUvZW50aXRpZXMvSWRUb2tlbkVudGl0eVwiO1xyXG5pbXBvcnQgeyBBY2NvdW50RW50aXR5IH0gZnJvbSBcIi4uL2NhY2hlL2VudGl0aWVzL0FjY291bnRFbnRpdHlcIjtcclxuaW1wb3J0IHsgQXV0aFRva2VuIH0gZnJvbSBcIi4uL2FjY291bnQvQXV0aFRva2VuXCI7XHJcbmltcG9ydCB7IENsaWVudEF1dGhFcnJvciB9IGZyb20gXCIuLi9lcnJvci9DbGllbnRBdXRoRXJyb3JcIjtcclxuaW1wb3J0IHsgUmVxdWVzdFRodW1icHJpbnQgfSBmcm9tIFwiLi4vbmV0d29yay9SZXF1ZXN0VGh1bWJwcmludFwiO1xyXG5pbXBvcnQgeyBBY2NvdW50SW5mbyB9IGZyb20gXCIuLi9hY2NvdW50L0FjY291bnRJbmZvXCI7XHJcblxyXG4vKipcclxuICogT24tQmVoYWxmLU9mIGNsaWVudFxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIE9uQmVoYWxmT2ZDbGllbnQgZXh0ZW5kcyBCYXNlQ2xpZW50IHtcclxuXHJcbiAgICBwcml2YXRlIHNjb3BlU2V0OiBTY29wZVNldDtcclxuXHJcbiAgICBjb25zdHJ1Y3Rvcihjb25maWd1cmF0aW9uOiBDbGllbnRDb25maWd1cmF0aW9uKSB7XHJcbiAgICAgICAgc3VwZXIoY29uZmlndXJhdGlvbik7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBQdWJsaWMgQVBJIHRvIGFjcXVpcmUgdG9rZW5zIHdpdGggb24gYmVoYWxmIG9mIGZsb3dcclxuICAgICAqIEBwYXJhbSByZXF1ZXN0XHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBhc3luYyBhY3F1aXJlVG9rZW4ocmVxdWVzdDogQ29tbW9uT25CZWhhbGZPZlJlcXVlc3QpOiBQcm9taXNlPEF1dGhlbnRpY2F0aW9uUmVzdWx0IHwgbnVsbD4ge1xyXG4gICAgICAgIHRoaXMuc2NvcGVTZXQgPSBuZXcgU2NvcGVTZXQocmVxdWVzdC5zY29wZXMgfHwgW10pO1xyXG5cclxuICAgICAgICBpZiAocmVxdWVzdC5za2lwQ2FjaGUpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuZXhlY3V0ZVRva2VuUmVxdWVzdChyZXF1ZXN0LCB0aGlzLmF1dGhvcml0eSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBjYWNoZWRBdXRoZW50aWNhdGlvblJlc3VsdCA9IGF3YWl0IHRoaXMuZ2V0Q2FjaGVkQXV0aGVudGljYXRpb25SZXN1bHQocmVxdWVzdCk7XHJcbiAgICAgICAgaWYgKGNhY2hlZEF1dGhlbnRpY2F0aW9uUmVzdWx0KSB7XHJcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRBdXRoZW50aWNhdGlvblJlc3VsdDtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5leGVjdXRlVG9rZW5SZXF1ZXN0KHJlcXVlc3QsIHRoaXMuYXV0aG9yaXR5KTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBsb29rIHVwIGNhY2hlIGZvciB0b2tlbnNcclxuICAgICAqIEBwYXJhbSByZXF1ZXN0XHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgYXN5bmMgZ2V0Q2FjaGVkQXV0aGVudGljYXRpb25SZXN1bHQocmVxdWVzdDogQ29tbW9uT25CZWhhbGZPZlJlcXVlc3QpOiBQcm9taXNlPEF1dGhlbnRpY2F0aW9uUmVzdWx0IHwgbnVsbD4ge1xyXG4gICAgICAgIGNvbnN0IGNhY2hlZEFjY2Vzc1Rva2VuID0gdGhpcy5yZWFkQWNjZXNzVG9rZW5Gcm9tQ2FjaGUocmVxdWVzdCk7XHJcbiAgICAgICAgaWYgKCFjYWNoZWRBY2Nlc3NUb2tlbiB8fFxyXG4gICAgICAgICAgICBUaW1lVXRpbHMuaXNUb2tlbkV4cGlyZWQoY2FjaGVkQWNjZXNzVG9rZW4uZXhwaXJlc09uLCB0aGlzLmNvbmZpZy5zeXN0ZW1PcHRpb25zLnRva2VuUmVuZXdhbE9mZnNldFNlY29uZHMpKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgY2FjaGVkSWRUb2tlbiA9IHRoaXMucmVhZElkVG9rZW5Gcm9tQ2FjaGUocmVxdWVzdCk7XHJcbiAgICAgICAgbGV0IGlkVG9rZW5PYmplY3Q6IEF1dGhUb2tlbiB8IHVuZGVmaW5lZDtcclxuICAgICAgICBsZXQgY2FjaGVkQWNjb3VudDogQWNjb3VudEVudGl0eSB8IG51bGwgPSBudWxsO1xyXG4gICAgICAgIGlmIChjYWNoZWRJZFRva2VuKSB7XHJcbiAgICAgICAgICAgIGlkVG9rZW5PYmplY3QgPSBuZXcgQXV0aFRva2VuKGNhY2hlZElkVG9rZW4uc2VjcmV0LCB0aGlzLmNvbmZpZy5jcnlwdG9JbnRlcmZhY2UpO1xyXG4gICAgICAgICAgICBjb25zdCBsb2NhbEFjY291bnRJZCA9IGlkVG9rZW5PYmplY3QuY2xhaW1zLm9pZCA/IGlkVG9rZW5PYmplY3QuY2xhaW1zLm9pZCA6IGlkVG9rZW5PYmplY3QuY2xhaW1zLnN1YjtcclxuICAgICAgICAgICAgY29uc3QgYWNjb3VudEluZm86IEFjY291bnRJbmZvID0ge1xyXG4gICAgICAgICAgICAgICAgaG9tZUFjY291bnRJZDogY2FjaGVkSWRUb2tlbi5ob21lQWNjb3VudElkLFxyXG4gICAgICAgICAgICAgICAgZW52aXJvbm1lbnQ6IGNhY2hlZElkVG9rZW4uZW52aXJvbm1lbnQsXHJcbiAgICAgICAgICAgICAgICB0ZW5hbnRJZDogY2FjaGVkSWRUb2tlbi5yZWFsbSxcclxuICAgICAgICAgICAgICAgIHVzZXJuYW1lOiBDb25zdGFudHMuRU1QVFlfU1RSSU5HLFxyXG4gICAgICAgICAgICAgICAgbG9jYWxBY2NvdW50SWQ6IGxvY2FsQWNjb3VudElkIHx8IFwiXCJcclxuICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgIGNhY2hlZEFjY291bnQgPSB0aGlzLnJlYWRBY2NvdW50RnJvbUNhY2hlKGFjY291bnRJbmZvKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBhd2FpdCBSZXNwb25zZUhhbmRsZXIuZ2VuZXJhdGVBdXRoZW50aWNhdGlvblJlc3VsdChcclxuICAgICAgICAgICAgdGhpcy5jcnlwdG9VdGlscyxcclxuICAgICAgICAgICAgdGhpcy5hdXRob3JpdHksXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIGFjY291bnQ6IGNhY2hlZEFjY291bnQsXHJcbiAgICAgICAgICAgICAgICBhY2Nlc3NUb2tlbjogY2FjaGVkQWNjZXNzVG9rZW4sXHJcbiAgICAgICAgICAgICAgICBpZFRva2VuOiBjYWNoZWRJZFRva2VuLFxyXG4gICAgICAgICAgICAgICAgcmVmcmVzaFRva2VuOiBudWxsLFxyXG4gICAgICAgICAgICAgICAgYXBwTWV0YWRhdGE6IG51bGxcclxuICAgICAgICAgICAgfSwgdHJ1ZSwgaWRUb2tlbk9iamVjdCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiByZWFkIGFjY2VzcyB0b2tlbiBmcm9tIGNhY2hlIFRPRE86IENhY2hlTWFuYWdlciBBUEkgc2hvdWxkIGJlIHVzZWQgaGVyZVxyXG4gICAgICogQHBhcmFtIHJlcXVlc3RcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSByZWFkQWNjZXNzVG9rZW5Gcm9tQ2FjaGUocmVxdWVzdDogQ29tbW9uT25CZWhhbGZPZlJlcXVlc3QpOiBBY2Nlc3NUb2tlbkVudGl0eSB8IG51bGwge1xyXG4gICAgICAgIGNvbnN0IGFjY2Vzc1Rva2VuRmlsdGVyOiBDcmVkZW50aWFsRmlsdGVyID0ge1xyXG4gICAgICAgICAgICBlbnZpcm9ubWVudDogdGhpcy5hdXRob3JpdHkuY2Fub25pY2FsQXV0aG9yaXR5VXJsQ29tcG9uZW50cy5Ib3N0TmFtZUFuZFBvcnQsXHJcbiAgICAgICAgICAgIGNyZWRlbnRpYWxUeXBlOiBDcmVkZW50aWFsVHlwZS5BQ0NFU1NfVE9LRU4sXHJcbiAgICAgICAgICAgIGNsaWVudElkOiB0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRJZCxcclxuICAgICAgICAgICAgcmVhbG06IHRoaXMuYXV0aG9yaXR5LnRlbmFudCxcclxuICAgICAgICAgICAgdGFyZ2V0OiB0aGlzLnNjb3BlU2V0LnByaW50U2NvcGVzTG93ZXJDYXNlKCksXHJcbiAgICAgICAgICAgIG9ib0Fzc2VydGlvbjogcmVxdWVzdC5vYm9Bc3NlcnRpb25cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBjb25zdCBjcmVkZW50aWFsQ2FjaGU6IENyZWRlbnRpYWxDYWNoZSA9IHRoaXMuY2FjaGVNYW5hZ2VyLmdldENyZWRlbnRpYWxzRmlsdGVyZWRCeShhY2Nlc3NUb2tlbkZpbHRlcik7XHJcbiAgICAgICAgY29uc3QgYWNjZXNzVG9rZW5zID0gT2JqZWN0LmtleXMoY3JlZGVudGlhbENhY2hlLmFjY2Vzc1Rva2VucykubWFwKGtleSA9PiBjcmVkZW50aWFsQ2FjaGUuYWNjZXNzVG9rZW5zW2tleV0pO1xyXG5cclxuICAgICAgICBjb25zdCBudW1BY2Nlc3NUb2tlbnMgPSBhY2Nlc3NUb2tlbnMubGVuZ3RoO1xyXG4gICAgICAgIGlmIChudW1BY2Nlc3NUb2tlbnMgPCAxKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH0gZWxzZSBpZiAobnVtQWNjZXNzVG9rZW5zID4gMSkge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRBdXRoRXJyb3IuY3JlYXRlTXVsdGlwbGVNYXRjaGluZ1Rva2Vuc0luQ2FjaGVFcnJvcigpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gYWNjZXNzVG9rZW5zWzBdIGFzIEFjY2Vzc1Rva2VuRW50aXR5O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogcmVhZCBpZHRva2VuIGZyb20gY2FjaGUgVE9ETzogQ2FjaGVNYW5hZ2VyIEFQSSBzaG91bGQgYmUgdXNlZCBoZXJlIGluc3RlYWRcclxuICAgICAqIEBwYXJhbSByZXF1ZXN0XHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgcmVhZElkVG9rZW5Gcm9tQ2FjaGUocmVxdWVzdDogQ29tbW9uT25CZWhhbGZPZlJlcXVlc3QpOiBJZFRva2VuRW50aXR5IHwgbnVsbCB7XHJcbiAgICAgICAgY29uc3QgaWRUb2tlbkZpbHRlcjogQ3JlZGVudGlhbEZpbHRlciA9IHtcclxuICAgICAgICAgICAgZW52aXJvbm1lbnQ6IHRoaXMuYXV0aG9yaXR5LmNhbm9uaWNhbEF1dGhvcml0eVVybENvbXBvbmVudHMuSG9zdE5hbWVBbmRQb3J0LFxyXG4gICAgICAgICAgICBjcmVkZW50aWFsVHlwZTogQ3JlZGVudGlhbFR5cGUuSURfVE9LRU4sXHJcbiAgICAgICAgICAgIGNsaWVudElkOiB0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRJZCxcclxuICAgICAgICAgICAgcmVhbG06IHRoaXMuYXV0aG9yaXR5LnRlbmFudCxcclxuICAgICAgICAgICAgb2JvQXNzZXJ0aW9uOiByZXF1ZXN0Lm9ib0Fzc2VydGlvblxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIGNvbnN0IGNyZWRlbnRpYWxDYWNoZTogQ3JlZGVudGlhbENhY2hlID0gdGhpcy5jYWNoZU1hbmFnZXIuZ2V0Q3JlZGVudGlhbHNGaWx0ZXJlZEJ5KGlkVG9rZW5GaWx0ZXIpO1xyXG4gICAgICAgIGNvbnN0IGlkVG9rZW5zID0gT2JqZWN0LmtleXMoY3JlZGVudGlhbENhY2hlLmlkVG9rZW5zKS5tYXAoa2V5ID0+IGNyZWRlbnRpYWxDYWNoZS5pZFRva2Vuc1trZXldKTtcclxuICAgICAgICAvLyBXaGVuIGFjcXVpcmluZyBhIHRva2VuIG9uIGJlaGFsZiBvZiBhbiBhcHBsaWNhdGlvbiwgdGhlcmUgbWlnaHQgbm90IGJlIGFuIGlkIHRva2VuIGluIHRoZSBjYWNoZVxyXG4gICAgICAgIGlmIChpZFRva2Vucy5sZW5ndGggPCAxKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gaWRUb2tlbnNbMF0gYXMgSWRUb2tlbkVudGl0eTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIHJlYWQgYWNjb3VudCBmcm9tIGNhY2hlLCBUT0RPOiBDYWNoZU1hbmFnZXIgQVBJIHNob3VsZCBiZSB1c2VkIGhlcmUgaW5zdGVhZFxyXG4gICAgICogQHBhcmFtIGFjY291bnRcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSByZWFkQWNjb3VudEZyb21DYWNoZShhY2NvdW50OiBBY2NvdW50SW5mbyk6IEFjY291bnRFbnRpdHkgfCBudWxsIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5jYWNoZU1hbmFnZXIucmVhZEFjY291bnRGcm9tQ2FjaGUoYWNjb3VudCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBNYWtlIGEgbmV0d29yayBjYWxsIHRvIHRoZSBzZXJ2ZXIgcmVxdWVzdGluZyBjcmVkZW50aWFsc1xyXG4gICAgICogQHBhcmFtIHJlcXVlc3RcclxuICAgICAqIEBwYXJhbSBhdXRob3JpdHlcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhc3luYyBleGVjdXRlVG9rZW5SZXF1ZXN0KHJlcXVlc3Q6IENvbW1vbk9uQmVoYWxmT2ZSZXF1ZXN0LCBhdXRob3JpdHk6IEF1dGhvcml0eSlcclxuICAgICAgICA6IFByb21pc2U8QXV0aGVudGljYXRpb25SZXN1bHQgfCBudWxsPiB7XHJcblxyXG4gICAgICAgIGNvbnN0IHJlcXVlc3RCb2R5ID0gdGhpcy5jcmVhdGVUb2tlblJlcXVlc3RCb2R5KHJlcXVlc3QpO1xyXG4gICAgICAgIGNvbnN0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB0aGlzLmNyZWF0ZURlZmF1bHRUb2tlblJlcXVlc3RIZWFkZXJzKCk7XHJcbiAgICAgICAgY29uc3QgdGh1bWJwcmludDogUmVxdWVzdFRodW1icHJpbnQgPSB7XHJcbiAgICAgICAgICAgIGNsaWVudElkOiB0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRJZCxcclxuICAgICAgICAgICAgYXV0aG9yaXR5OiByZXF1ZXN0LmF1dGhvcml0eSxcclxuICAgICAgICAgICAgc2NvcGVzOiByZXF1ZXN0LnNjb3Blc1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIGNvbnN0IHJlcVRpbWVzdGFtcCA9IFRpbWVVdGlscy5ub3dTZWNvbmRzKCk7XHJcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmV4ZWN1dGVQb3N0VG9Ub2tlbkVuZHBvaW50KGF1dGhvcml0eS50b2tlbkVuZHBvaW50LCByZXF1ZXN0Qm9keSwgaGVhZGVycywgdGh1bWJwcmludCk7XHJcblxyXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlSGFuZGxlciA9IG5ldyBSZXNwb25zZUhhbmRsZXIoXHJcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudElkLFxyXG4gICAgICAgICAgICB0aGlzLmNhY2hlTWFuYWdlcixcclxuICAgICAgICAgICAgdGhpcy5jcnlwdG9VdGlscyxcclxuICAgICAgICAgICAgdGhpcy5sb2dnZXIsXHJcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLnNlcmlhbGl6YWJsZUNhY2hlLFxyXG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5wZXJzaXN0ZW5jZVBsdWdpblxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIHJlc3BvbnNlSGFuZGxlci52YWxpZGF0ZVRva2VuUmVzcG9uc2UocmVzcG9uc2UuYm9keSk7XHJcbiAgICAgICAgY29uc3QgdG9rZW5SZXNwb25zZSA9IGF3YWl0IHJlc3BvbnNlSGFuZGxlci5oYW5kbGVTZXJ2ZXJUb2tlblJlc3BvbnNlKFxyXG4gICAgICAgICAgICByZXNwb25zZS5ib2R5LFxyXG4gICAgICAgICAgICB0aGlzLmF1dGhvcml0eSxcclxuICAgICAgICAgICAgcmVxVGltZXN0YW1wLFxyXG4gICAgICAgICAgICByZXF1ZXN0LnJlc291cmNlUmVxdWVzdE1ldGhvZCxcclxuICAgICAgICAgICAgcmVxdWVzdC5yZXNvdXJjZVJlcXVlc3RVcmksXHJcbiAgICAgICAgICAgIHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgcmVxdWVzdC5zY29wZXMsXHJcbiAgICAgICAgICAgIHJlcXVlc3Qub2JvQXNzZXJ0aW9uXHJcbiAgICAgICAgKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHRva2VuUmVzcG9uc2U7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBnZW5lcmF0ZSBhIHNlcnZlciByZXF1ZXN0IGluIGFjY2VwYWJsZSBmb3JtYXRcclxuICAgICAqIEBwYXJhbSByZXF1ZXN0XHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgY3JlYXRlVG9rZW5SZXF1ZXN0Qm9keShyZXF1ZXN0OiBDb21tb25PbkJlaGFsZk9mUmVxdWVzdCk6IHN0cmluZyB7XHJcbiAgICAgICAgY29uc3QgcGFyYW1ldGVyQnVpbGRlciA9IG5ldyBSZXF1ZXN0UGFyYW1ldGVyQnVpbGRlcigpO1xyXG5cclxuICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZENsaWVudElkKHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudElkKTtcclxuXHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRTY29wZXMocmVxdWVzdC5zY29wZXMpO1xyXG5cclxuICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZEdyYW50VHlwZShHcmFudFR5cGUuSldUX0JFQVJFUik7XHJcblxyXG4gICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkQ2xpZW50SW5mbygpO1xyXG5cclxuICAgICAgICBjb25zdCBjb3JyZWxhdGlvbklkID0gcmVxdWVzdC5jb3JyZWxhdGlvbklkIHx8IHRoaXMuY29uZmlnLmNyeXB0b0ludGVyZmFjZS5jcmVhdGVOZXdHdWlkKCk7XHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRDb3JyZWxhdGlvbklkKGNvcnJlbGF0aW9uSWQpO1xyXG5cclxuICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZFJlcXVlc3RUb2tlblVzZShBQURTZXJ2ZXJQYXJhbUtleXMuT05fQkVIQUxGX09GKTtcclxuXHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRPYm9Bc3NlcnRpb24ocmVxdWVzdC5vYm9Bc3NlcnRpb24pO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5jb25maWcuY2xpZW50Q3JlZGVudGlhbHMuY2xpZW50U2VjcmV0KSB7XHJcbiAgICAgICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkQ2xpZW50U2VjcmV0KHRoaXMuY29uZmlnLmNsaWVudENyZWRlbnRpYWxzLmNsaWVudFNlY3JldCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhpcy5jb25maWcuY2xpZW50Q3JlZGVudGlhbHMuY2xpZW50QXNzZXJ0aW9uKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGNsaWVudEFzc2VydGlvbiA9IHRoaXMuY29uZmlnLmNsaWVudENyZWRlbnRpYWxzLmNsaWVudEFzc2VydGlvbjtcclxuICAgICAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRDbGllbnRBc3NlcnRpb24oY2xpZW50QXNzZXJ0aW9uLmFzc2VydGlvbik7XHJcbiAgICAgICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkQ2xpZW50QXNzZXJ0aW9uVHlwZShjbGllbnRBc3NlcnRpb24uYXNzZXJ0aW9uVHlwZSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gcGFyYW1ldGVyQnVpbGRlci5jcmVhdGVRdWVyeVN0cmluZygpO1xyXG4gICAgfVxyXG59XHJcbiIsIi8qXHJcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgQmFzZUNsaWVudCB9IGZyb20gXCIuL0Jhc2VDbGllbnRcIjtcclxuaW1wb3J0IHsgQ2xpZW50Q29uZmlndXJhdGlvbiB9IGZyb20gXCIuLi9jb25maWcvQ2xpZW50Q29uZmlndXJhdGlvblwiO1xyXG5pbXBvcnQgeyBDb21tb25TaWxlbnRGbG93UmVxdWVzdCB9IGZyb20gXCIuLi9yZXF1ZXN0L0NvbW1vblNpbGVudEZsb3dSZXF1ZXN0XCI7XHJcbmltcG9ydCB7IEF1dGhlbnRpY2F0aW9uUmVzdWx0IH0gZnJvbSBcIi4uL3Jlc3BvbnNlL0F1dGhlbnRpY2F0aW9uUmVzdWx0XCI7XHJcbmltcG9ydCB7IEFjY2Vzc1Rva2VuRW50aXR5IH0gZnJvbSBcIi4uL2NhY2hlL2VudGl0aWVzL0FjY2Vzc1Rva2VuRW50aXR5XCI7XHJcbmltcG9ydCB7IFNjb3BlU2V0IH0gZnJvbSBcIi4uL3JlcXVlc3QvU2NvcGVTZXRcIjtcclxuaW1wb3J0IHsgQXV0aFRva2VuIH0gZnJvbSBcIi4uL2FjY291bnQvQXV0aFRva2VuXCI7XHJcbmltcG9ydCB7IFRpbWVVdGlscyB9IGZyb20gXCIuLi91dGlscy9UaW1lVXRpbHNcIjtcclxuaW1wb3J0IHsgUmVmcmVzaFRva2VuQ2xpZW50IH0gZnJvbSBcIi4vUmVmcmVzaFRva2VuQ2xpZW50XCI7XHJcbmltcG9ydCB7IENsaWVudEF1dGhFcnJvciwgQ2xpZW50QXV0aEVycm9yTWVzc2FnZSB9IGZyb20gXCIuLi9lcnJvci9DbGllbnRBdXRoRXJyb3JcIjtcclxuaW1wb3J0IHsgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL0NsaWVudENvbmZpZ3VyYXRpb25FcnJvclwiO1xyXG5pbXBvcnQgeyBSZXNwb25zZUhhbmRsZXIgfSBmcm9tIFwiLi4vcmVzcG9uc2UvUmVzcG9uc2VIYW5kbGVyXCI7XHJcbmltcG9ydCB7IENhY2hlUmVjb3JkIH0gZnJvbSBcIi4uL2NhY2hlL2VudGl0aWVzL0NhY2hlUmVjb3JkXCI7XHJcblxyXG5leHBvcnQgY2xhc3MgU2lsZW50Rmxvd0NsaWVudCBleHRlbmRzIEJhc2VDbGllbnQge1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKGNvbmZpZ3VyYXRpb246IENsaWVudENvbmZpZ3VyYXRpb24pIHtcclxuICAgICAgICBzdXBlcihjb25maWd1cmF0aW9uKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHJpZXZlcyBhIHRva2VuIGZyb20gY2FjaGUgaWYgaXQgaXMgc3RpbGwgdmFsaWQsIG9yIHVzZXMgdGhlIGNhY2hlZCByZWZyZXNoIHRva2VuIHRvIHJlbmV3XHJcbiAgICAgKiB0aGUgZ2l2ZW4gdG9rZW4gYW5kIHJldHVybnMgdGhlIHJlbmV3ZWQgdG9rZW5cclxuICAgICAqIEBwYXJhbSByZXF1ZXN0XHJcbiAgICAgKi9cclxuICAgIGFzeW5jIGFjcXVpcmVUb2tlbihyZXF1ZXN0OiBDb21tb25TaWxlbnRGbG93UmVxdWVzdCk6IFByb21pc2U8QXV0aGVudGljYXRpb25SZXN1bHQ+IHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5hY3F1aXJlQ2FjaGVkVG9rZW4ocmVxdWVzdCk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIENsaWVudEF1dGhFcnJvciAmJiBlLmVycm9yQ29kZSA9PT0gQ2xpZW50QXV0aEVycm9yTWVzc2FnZS50b2tlblJlZnJlc2hSZXF1aXJlZC5jb2RlKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCByZWZyZXNoVG9rZW5DbGllbnQgPSBuZXcgUmVmcmVzaFRva2VuQ2xpZW50KHRoaXMuY29uZmlnKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiByZWZyZXNoVG9rZW5DbGllbnQuYWNxdWlyZVRva2VuQnlSZWZyZXNoVG9rZW4ocmVxdWVzdCk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0cmlldmVzIHRva2VuIGZyb20gY2FjaGUgb3IgdGhyb3dzIGFuIGVycm9yIGlmIGl0IG11c3QgYmUgcmVmcmVzaGVkLlxyXG4gICAgICogQHBhcmFtIHJlcXVlc3RcclxuICAgICAqL1xyXG4gICAgYXN5bmMgYWNxdWlyZUNhY2hlZFRva2VuKHJlcXVlc3Q6IENvbW1vblNpbGVudEZsb3dSZXF1ZXN0KTogUHJvbWlzZTxBdXRoZW50aWNhdGlvblJlc3VsdD4ge1xyXG4gICAgICAgIC8vIENhbm5vdCByZW5ldyB0b2tlbiBpZiBubyByZXF1ZXN0IG9iamVjdCBpcyBnaXZlbi5cclxuICAgICAgICBpZiAoIXJlcXVlc3QpIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yLmNyZWF0ZUVtcHR5VG9rZW5SZXF1ZXN0RXJyb3IoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFdlIGN1cnJlbnRseSBkbyBub3Qgc3VwcG9ydCBzaWxlbnQgZmxvdyBmb3IgYWNjb3VudCA9PT0gbnVsbCB1c2UgY2FzZXM7IFRoaXMgd2lsbCBiZSByZXZpc2l0ZWQgZm9yIGNvbmZpZGVudGlhbCBmbG93IHVzZWNhc2VzXHJcbiAgICAgICAgaWYgKCFyZXF1ZXN0LmFjY291bnQpIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50QXV0aEVycm9yLmNyZWF0ZU5vQWNjb3VudEluU2lsZW50UmVxdWVzdEVycm9yKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCByZXF1ZXN0U2NvcGVzID0gbmV3IFNjb3BlU2V0KHJlcXVlc3Quc2NvcGVzIHx8IFtdKTtcclxuICAgICAgICBjb25zdCBlbnZpcm9ubWVudCA9IHJlcXVlc3QuYXV0aG9yaXR5IHx8IHRoaXMuYXV0aG9yaXR5LmdldFByZWZlcnJlZENhY2hlKCk7XHJcbiAgICAgICAgY29uc3QgY2FjaGVSZWNvcmQgPSB0aGlzLmNhY2hlTWFuYWdlci5yZWFkQ2FjaGVSZWNvcmQocmVxdWVzdC5hY2NvdW50LCB0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRJZCwgcmVxdWVzdFNjb3BlcywgZW52aXJvbm1lbnQpO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5pc1JlZnJlc2hSZXF1aXJlZChyZXF1ZXN0LCBjYWNoZVJlY29yZC5hY2Nlc3NUb2tlbikpIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50QXV0aEVycm9yLmNyZWF0ZVJlZnJlc2hSZXF1aXJlZEVycm9yKCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLnNlcnZlclRlbGVtZXRyeU1hbmFnZXIpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLnNlcnZlclRlbGVtZXRyeU1hbmFnZXIuaW5jcmVtZW50Q2FjaGVIaXRzKCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuZ2VuZXJhdGVSZXN1bHRGcm9tQ2FjaGVSZWNvcmQoY2FjaGVSZWNvcmQsIHJlcXVlc3QucmVzb3VyY2VSZXF1ZXN0TWV0aG9kLCByZXF1ZXN0LnJlc291cmNlUmVxdWVzdFVyaSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGVscGVyIGZ1bmN0aW9uIHRvIGJ1aWxkIHJlc3BvbnNlIG9iamVjdCBmcm9tIHRoZSBDYWNoZVJlY29yZFxyXG4gICAgICogQHBhcmFtIGNhY2hlUmVjb3JkXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgYXN5bmMgZ2VuZXJhdGVSZXN1bHRGcm9tQ2FjaGVSZWNvcmQoY2FjaGVSZWNvcmQ6IENhY2hlUmVjb3JkLCByZXNvdXJjZVJlcXVlc3RNZXRob2Q/OiBzdHJpbmcsIHJlc291cmNlUmVxdWVzdFVyaT86IHN0cmluZyk6IFByb21pc2U8QXV0aGVudGljYXRpb25SZXN1bHQ+IHtcclxuICAgICAgICBsZXQgaWRUb2tlbk9iajogQXV0aFRva2VuIHwgdW5kZWZpbmVkO1xyXG4gICAgICAgIGlmIChjYWNoZVJlY29yZC5pZFRva2VuKSB7XHJcbiAgICAgICAgICAgIGlkVG9rZW5PYmogPSBuZXcgQXV0aFRva2VuKGNhY2hlUmVjb3JkLmlkVG9rZW4uc2VjcmV0LCB0aGlzLmNvbmZpZy5jcnlwdG9JbnRlcmZhY2UpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gYXdhaXQgUmVzcG9uc2VIYW5kbGVyLmdlbmVyYXRlQXV0aGVudGljYXRpb25SZXN1bHQoXHJcbiAgICAgICAgICAgIHRoaXMuY3J5cHRvVXRpbHMsXHJcbiAgICAgICAgICAgIHRoaXMuYXV0aG9yaXR5LFxyXG4gICAgICAgICAgICBjYWNoZVJlY29yZCxcclxuICAgICAgICAgICAgdHJ1ZSxcclxuICAgICAgICAgICAgaWRUb2tlbk9iaixcclxuICAgICAgICAgICAgdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICByZXNvdXJjZVJlcXVlc3RNZXRob2QsXHJcbiAgICAgICAgICAgIHJlc291cmNlUmVxdWVzdFVyaVxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHaXZlbiBhIHJlcXVlc3Qgb2JqZWN0IGFuZCBhbiBhY2Nlc3NUb2tlbkVudGl0eSBkZXRlcm1pbmUgaWYgdGhlIGFjY2Vzc1Rva2VuIG5lZWRzIHRvIGJlIHJlZnJlc2hlZFxyXG4gICAgICogQHBhcmFtIHJlcXVlc3RcclxuICAgICAqIEBwYXJhbSBjYWNoZWRBY2Nlc3NUb2tlblxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGlzUmVmcmVzaFJlcXVpcmVkKHJlcXVlc3Q6IENvbW1vblNpbGVudEZsb3dSZXF1ZXN0LCBjYWNoZWRBY2Nlc3NUb2tlbjogQWNjZXNzVG9rZW5FbnRpdHl8bnVsbCk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGlmIChyZXF1ZXN0LmZvcmNlUmVmcmVzaCB8fCByZXF1ZXN0LmNsYWltcykge1xyXG4gICAgICAgICAgICAvLyBNdXN0IHJlZnJlc2ggZHVlIHRvIHJlcXVlc3QgcGFyYW1ldGVyc1xyXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICB9IGVsc2UgaWYgKCFjYWNoZWRBY2Nlc3NUb2tlbiB8fCBUaW1lVXRpbHMuaXNUb2tlbkV4cGlyZWQoY2FjaGVkQWNjZXNzVG9rZW4uZXhwaXJlc09uLCB0aGlzLmNvbmZpZy5zeXN0ZW1PcHRpb25zLnRva2VuUmVuZXdhbE9mZnNldFNlY29uZHMpKSB7XHJcbiAgICAgICAgICAgIC8vIE11c3QgcmVmcmVzaCBkdWUgdG8gZXhwaXJlZCBvciBub24tZXhpc3RlbnQgYWNjZXNzX3Rva2VuXHJcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG59XHJcbiIsIi8qXHJcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgQmFzZUNsaWVudCB9IGZyb20gXCIuL0Jhc2VDbGllbnRcIjtcclxuaW1wb3J0IHsgQ2xpZW50Q29uZmlndXJhdGlvbiB9IGZyb20gXCIuLi9jb25maWcvQ2xpZW50Q29uZmlndXJhdGlvblwiO1xyXG5pbXBvcnQgeyBDb21tb25Vc2VybmFtZVBhc3N3b3JkUmVxdWVzdCB9IGZyb20gXCIuLi9yZXF1ZXN0L0NvbW1vblVzZXJuYW1lUGFzc3dvcmRSZXF1ZXN0XCI7XHJcbmltcG9ydCB7IEF1dGhlbnRpY2F0aW9uUmVzdWx0IH0gZnJvbSBcIi4uL3Jlc3BvbnNlL0F1dGhlbnRpY2F0aW9uUmVzdWx0XCI7XHJcbmltcG9ydCB7IFJlc3BvbnNlSGFuZGxlciB9IGZyb20gXCIuLi9yZXNwb25zZS9SZXNwb25zZUhhbmRsZXJcIjtcclxuaW1wb3J0IHsgQXV0aG9yaXR5IH0gZnJvbSBcIi4uL2F1dGhvcml0eS9BdXRob3JpdHlcIjtcclxuaW1wb3J0IHsgTmV0d29ya1Jlc3BvbnNlIH0gZnJvbSBcIi4uL25ldHdvcmsvTmV0d29ya01hbmFnZXJcIjtcclxuaW1wb3J0IHsgU2VydmVyQXV0aG9yaXphdGlvblRva2VuUmVzcG9uc2UgfSBmcm9tIFwiLi4vcmVzcG9uc2UvU2VydmVyQXV0aG9yaXphdGlvblRva2VuUmVzcG9uc2VcIjtcclxuaW1wb3J0IHsgUmVxdWVzdFBhcmFtZXRlckJ1aWxkZXIgfSBmcm9tIFwiLi4vcmVxdWVzdC9SZXF1ZXN0UGFyYW1ldGVyQnVpbGRlclwiO1xyXG5pbXBvcnQgeyBHcmFudFR5cGUgfSBmcm9tIFwiLi4vdXRpbHMvQ29uc3RhbnRzXCI7XHJcbmltcG9ydCB7IFN0cmluZ1V0aWxzIH0gZnJvbSBcIi4uL3V0aWxzL1N0cmluZ1V0aWxzXCI7XHJcbmltcG9ydCB7IFJlcXVlc3RUaHVtYnByaW50IH0gZnJvbSBcIi4uL25ldHdvcmsvUmVxdWVzdFRodW1icHJpbnRcIjtcclxuaW1wb3J0IHsgVGltZVV0aWxzIH0gZnJvbSBcIi4uL3V0aWxzL1RpbWVVdGlsc1wiO1xyXG5cclxuLyoqXHJcbiAqIE9hdXRoMi4wIFBhc3N3b3JkIGdyYW50IGNsaWVudFxyXG4gKiBOb3RlOiBXZSBhcmUgb25seSBzdXBwb3J0aW5nIHB1YmxpYyBjbGllbnRzIGZvciBwYXNzd29yZCBncmFudCBhbmQgZm9yIHB1cmVseSB0ZXN0aW5nIHB1cnBvc2VzXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgVXNlcm5hbWVQYXNzd29yZENsaWVudCBleHRlbmRzIEJhc2VDbGllbnQge1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKGNvbmZpZ3VyYXRpb246IENsaWVudENvbmZpZ3VyYXRpb24pIHtcclxuICAgICAgICBzdXBlcihjb25maWd1cmF0aW9uKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEFQSSB0byBhY3F1aXJlIGEgdG9rZW4gYnkgcGFzc2luZyB0aGUgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIHRvIHRoZSBzZXJ2aWNlIGluIGV4Y2hhZ2Ugb2YgY3JlZGVudGlhbHNcclxuICAgICAqIHBhc3N3b3JkX2dyYW50XHJcbiAgICAgKiBAcGFyYW0gcmVxdWVzdFxyXG4gICAgICovXHJcbiAgICBhc3luYyBhY3F1aXJlVG9rZW4ocmVxdWVzdDogQ29tbW9uVXNlcm5hbWVQYXNzd29yZFJlcXVlc3QpOiBQcm9taXNlPEF1dGhlbnRpY2F0aW9uUmVzdWx0IHwgbnVsbD4ge1xyXG4gICAgICAgIHRoaXMubG9nZ2VyLmluZm8oXCJpbiBhY3F1aXJlVG9rZW4gY2FsbFwiKTtcclxuXHJcbiAgICAgICAgY29uc3QgcmVxVGltZXN0YW1wID0gVGltZVV0aWxzLm5vd1NlY29uZHMoKTtcclxuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZXhlY3V0ZVRva2VuUmVxdWVzdCh0aGlzLmF1dGhvcml0eSwgcmVxdWVzdCk7XHJcblxyXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlSGFuZGxlciA9IG5ldyBSZXNwb25zZUhhbmRsZXIoXHJcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudElkLFxyXG4gICAgICAgICAgICB0aGlzLmNhY2hlTWFuYWdlcixcclxuICAgICAgICAgICAgdGhpcy5jcnlwdG9VdGlscyxcclxuICAgICAgICAgICAgdGhpcy5sb2dnZXIsXHJcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLnNlcmlhbGl6YWJsZUNhY2hlLFxyXG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5wZXJzaXN0ZW5jZVBsdWdpblxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIC8vIFZhbGlkYXRlIHJlc3BvbnNlLiBUaGlzIGZ1bmN0aW9uIHRocm93cyBhIHNlcnZlciBlcnJvciBpZiBhbiBlcnJvciBpcyByZXR1cm5lZCBieSB0aGUgc2VydmVyLlxyXG4gICAgICAgIHJlc3BvbnNlSGFuZGxlci52YWxpZGF0ZVRva2VuUmVzcG9uc2UocmVzcG9uc2UuYm9keSk7XHJcbiAgICAgICAgY29uc3QgdG9rZW5SZXNwb25zZSA9IHJlc3BvbnNlSGFuZGxlci5oYW5kbGVTZXJ2ZXJUb2tlblJlc3BvbnNlKHJlc3BvbnNlLmJvZHksIHRoaXMuYXV0aG9yaXR5LCByZXFUaW1lc3RhbXApO1xyXG5cclxuICAgICAgICByZXR1cm4gdG9rZW5SZXNwb25zZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEV4ZWN1dGVzIFBPU1QgcmVxdWVzdCB0byB0b2tlbiBlbmRwb2ludFxyXG4gICAgICogQHBhcmFtIGF1dGhvcml0eVxyXG4gICAgICogQHBhcmFtIHJlcXVlc3RcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhc3luYyBleGVjdXRlVG9rZW5SZXF1ZXN0KGF1dGhvcml0eTogQXV0aG9yaXR5LCByZXF1ZXN0OiBDb21tb25Vc2VybmFtZVBhc3N3b3JkUmVxdWVzdCk6IFByb21pc2U8TmV0d29ya1Jlc3BvbnNlPFNlcnZlckF1dGhvcml6YXRpb25Ub2tlblJlc3BvbnNlPj4ge1xyXG4gICAgICAgIGNvbnN0IHRodW1icHJpbnQ6IFJlcXVlc3RUaHVtYnByaW50ID0ge1xyXG4gICAgICAgICAgICBjbGllbnRJZDogdGhpcy5jb25maWcuYXV0aE9wdGlvbnMuY2xpZW50SWQsXHJcbiAgICAgICAgICAgIGF1dGhvcml0eTogYXV0aG9yaXR5LmNhbm9uaWNhbEF1dGhvcml0eSxcclxuICAgICAgICAgICAgc2NvcGVzOiByZXF1ZXN0LnNjb3Blc1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgY29uc3QgcmVxdWVzdEJvZHkgPSB0aGlzLmNyZWF0ZVRva2VuUmVxdWVzdEJvZHkocmVxdWVzdCk7XHJcbiAgICAgICAgY29uc3QgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHRoaXMuY3JlYXRlRGVmYXVsdFRva2VuUmVxdWVzdEhlYWRlcnMoKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXMuZXhlY3V0ZVBvc3RUb1Rva2VuRW5kcG9pbnQoYXV0aG9yaXR5LnRva2VuRW5kcG9pbnQsIHJlcXVlc3RCb2R5LCBoZWFkZXJzLCB0aHVtYnByaW50KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdlbmVyYXRlcyBhIG1hcCBmb3IgYWxsIHRoZSBwYXJhbXMgdG8gYmUgc2VudCB0byB0aGUgc2VydmljZVxyXG4gICAgICogQHBhcmFtIHJlcXVlc3RcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBjcmVhdGVUb2tlblJlcXVlc3RCb2R5KHJlcXVlc3Q6IENvbW1vblVzZXJuYW1lUGFzc3dvcmRSZXF1ZXN0KTogc3RyaW5nIHtcclxuICAgICAgICBjb25zdCBwYXJhbWV0ZXJCdWlsZGVyID0gbmV3IFJlcXVlc3RQYXJhbWV0ZXJCdWlsZGVyKCk7XHJcblxyXG4gICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkQ2xpZW50SWQodGhpcy5jb25maWcuYXV0aE9wdGlvbnMuY2xpZW50SWQpO1xyXG4gICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkVXNlcm5hbWUocmVxdWVzdC51c2VybmFtZSk7XHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRQYXNzd29yZChyZXF1ZXN0LnBhc3N3b3JkKTtcclxuXHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRTY29wZXMocmVxdWVzdC5zY29wZXMpO1xyXG5cclxuICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZEdyYW50VHlwZShHcmFudFR5cGUuUkVTT1VSQ0VfT1dORVJfUEFTU1dPUkRfR1JBTlQpO1xyXG4gICAgICAgIHBhcmFtZXRlckJ1aWxkZXIuYWRkQ2xpZW50SW5mbygpO1xyXG5cclxuICAgICAgICBjb25zdCBjb3JyZWxhdGlvbklkID0gcmVxdWVzdC5jb3JyZWxhdGlvbklkIHx8IHRoaXMuY29uZmlnLmNyeXB0b0ludGVyZmFjZS5jcmVhdGVOZXdHdWlkKCk7XHJcbiAgICAgICAgcGFyYW1ldGVyQnVpbGRlci5hZGRDb3JyZWxhdGlvbklkKGNvcnJlbGF0aW9uSWQpO1xyXG5cclxuICAgICAgICBpZiAoIVN0cmluZ1V0aWxzLmlzRW1wdHkocmVxdWVzdC5jbGFpbXMpIHx8IHRoaXMuY29uZmlnLmF1dGhPcHRpb25zLmNsaWVudENhcGFiaWxpdGllcyAmJiB0aGlzLmNvbmZpZy5hdXRoT3B0aW9ucy5jbGllbnRDYXBhYmlsaXRpZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICBwYXJhbWV0ZXJCdWlsZGVyLmFkZENsYWltcyhyZXF1ZXN0LmNsYWltcywgdGhpcy5jb25maWcuYXV0aE9wdGlvbnMuY2xpZW50Q2FwYWJpbGl0aWVzKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBwYXJhbWV0ZXJCdWlsZGVyLmNyZWF0ZVF1ZXJ5U3RyaW5nKCk7XHJcbiAgICB9XHJcbn1cclxuIiwiLypcclxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cclxuICovXHJcblxyXG4vKipcclxuICogVGVuYW50IERpc2NvdmVyeSBSZXNwb25zZSB3aGljaCBjb250YWlucyB0aGUgcmVsZXZhbnQgT0F1dGggZW5kcG9pbnRzIGFuZCBkYXRhIG5lZWRlZCBmb3IgYXV0aGVudGljYXRpb24gYW5kIGF1dGhvcml6YXRpb24uXHJcbiAqL1xyXG5leHBvcnQgdHlwZSBPcGVuSWRDb25maWdSZXNwb25zZSA9IHtcclxuICAgIGF1dGhvcml6YXRpb25fZW5kcG9pbnQ6IHN0cmluZztcclxuICAgIHRva2VuX2VuZHBvaW50OiBzdHJpbmc7XHJcbiAgICBlbmRfc2Vzc2lvbl9lbmRwb2ludDogc3RyaW5nO1xyXG4gICAgaXNzdWVyOiBzdHJpbmc7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gaXNPcGVuSWRDb25maWdSZXNwb25zZShyZXNwb25zZTogb2JqZWN0KTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gKFxyXG4gICAgICAgIHJlc3BvbnNlLmhhc093blByb3BlcnR5KFwiYXV0aG9yaXphdGlvbl9lbmRwb2ludFwiKSAmJlxyXG4gICAgICAgIHJlc3BvbnNlLmhhc093blByb3BlcnR5KFwidG9rZW5fZW5kcG9pbnRcIikgJiYgXHJcbiAgICAgICAgcmVzcG9uc2UuaGFzT3duUHJvcGVydHkoXCJlbmRfc2Vzc2lvbl9lbmRwb2ludFwiKSAmJlxyXG4gICAgICAgIHJlc3BvbnNlLmhhc093blByb3BlcnR5KFwiaXNzdWVyXCIpXHJcbiAgICApO1xyXG59XHJcbiIsIi8qXHJcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFByb3RvY29sIG1vZGVzIHN1cHBvcnRlZCBieSBNU0FMLlxyXG4gKi9cclxuZXhwb3J0IGVudW0gUHJvdG9jb2xNb2RlIHtcclxuICAgIEFBRCA9IFwiQUFEXCIsXHJcbiAgICBPSURDID0gXCJPSURDXCJcclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IENsb3VkRGlzY292ZXJ5TWV0YWRhdGEgfSBmcm9tIFwiLi4vLi4vYXV0aG9yaXR5L0Nsb3VkRGlzY292ZXJ5TWV0YWRhdGFcIjtcclxuaW1wb3J0IHsgT3BlbklkQ29uZmlnUmVzcG9uc2UgfSBmcm9tIFwiLi4vLi4vYXV0aG9yaXR5L09wZW5JZENvbmZpZ1Jlc3BvbnNlXCI7XHJcbmltcG9ydCB7IEFVVEhPUklUWV9NRVRBREFUQV9DT05TVEFOVFMgfSBmcm9tIFwiLi4vLi4vdXRpbHMvQ29uc3RhbnRzXCI7XHJcbmltcG9ydCB7IFRpbWVVdGlscyB9IGZyb20gXCIuLi8uLi91dGlscy9UaW1lVXRpbHNcIjtcclxuXHJcbmV4cG9ydCBjbGFzcyBBdXRob3JpdHlNZXRhZGF0YUVudGl0eSB7XHJcbiAgICBhbGlhc2VzOiBBcnJheTxzdHJpbmc+O1xyXG4gICAgcHJlZmVycmVkX2NhY2hlOiBzdHJpbmc7XHJcbiAgICBwcmVmZXJyZWRfbmV0d29yazogc3RyaW5nO1xyXG4gICAgY2Fub25pY2FsX2F1dGhvcml0eTogc3RyaW5nO1xyXG4gICAgYXV0aG9yaXphdGlvbl9lbmRwb2ludDogc3RyaW5nO1xyXG4gICAgdG9rZW5fZW5kcG9pbnQ6IHN0cmluZztcclxuICAgIGVuZF9zZXNzaW9uX2VuZHBvaW50OiBzdHJpbmc7XHJcbiAgICBpc3N1ZXI6IHN0cmluZztcclxuICAgIGFsaWFzZXNGcm9tTmV0d29yazogYm9vbGVhbjtcclxuICAgIGVuZHBvaW50c0Zyb21OZXR3b3JrOiBib29sZWFuO1xyXG4gICAgZXhwaXJlc0F0OiBudW1iZXI7XHJcblxyXG4gICAgY29uc3RydWN0b3IoKSB7XHJcbiAgICAgICAgdGhpcy5leHBpcmVzQXQgPSBUaW1lVXRpbHMubm93U2Vjb25kcygpICsgQVVUSE9SSVRZX01FVEFEQVRBX0NPTlNUQU5UUy5SRUZSRVNIX1RJTUVfU0VDT05EUztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFVwZGF0ZSB0aGUgZW50aXR5IHdpdGggbmV3IGFsaWFzZXMsIHByZWZlcnJlZF9jYWNoZSBhbmQgcHJlZmVycmVkX25ldHdvcmsgdmFsdWVzXHJcbiAgICAgKiBAcGFyYW0gbWV0YWRhdGEgXHJcbiAgICAgKiBAcGFyYW0gZnJvbU5ldHdvcmsgXHJcbiAgICAgKi9cclxuICAgIHVwZGF0ZUNsb3VkRGlzY292ZXJ5TWV0YWRhdGEobWV0YWRhdGE6IENsb3VkRGlzY292ZXJ5TWV0YWRhdGEsIGZyb21OZXR3b3JrOiBib29sZWFuKSB7XHJcbiAgICAgICAgdGhpcy5hbGlhc2VzID0gbWV0YWRhdGEuYWxpYXNlcztcclxuICAgICAgICB0aGlzLnByZWZlcnJlZF9jYWNoZSA9IG1ldGFkYXRhLnByZWZlcnJlZF9jYWNoZTtcclxuICAgICAgICB0aGlzLnByZWZlcnJlZF9uZXR3b3JrID0gbWV0YWRhdGEucHJlZmVycmVkX25ldHdvcms7XHJcbiAgICAgICAgdGhpcy5hbGlhc2VzRnJvbU5ldHdvcmsgPSBmcm9tTmV0d29yaztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFVwZGF0ZSB0aGUgZW50aXR5IHdpdGggbmV3IGVuZHBvaW50c1xyXG4gICAgICogQHBhcmFtIG1ldGFkYXRhIFxyXG4gICAgICogQHBhcmFtIGZyb21OZXR3b3JrIFxyXG4gICAgICovXHJcbiAgICB1cGRhdGVFbmRwb2ludE1ldGFkYXRhKG1ldGFkYXRhOiBPcGVuSWRDb25maWdSZXNwb25zZSwgZnJvbU5ldHdvcms6IGJvb2xlYW4pIHtcclxuICAgICAgICB0aGlzLmF1dGhvcml6YXRpb25fZW5kcG9pbnQgPSBtZXRhZGF0YS5hdXRob3JpemF0aW9uX2VuZHBvaW50O1xyXG4gICAgICAgIHRoaXMudG9rZW5fZW5kcG9pbnQgPSBtZXRhZGF0YS50b2tlbl9lbmRwb2ludDtcclxuICAgICAgICB0aGlzLmVuZF9zZXNzaW9uX2VuZHBvaW50ID0gbWV0YWRhdGEuZW5kX3Nlc3Npb25fZW5kcG9pbnQ7XHJcbiAgICAgICAgdGhpcy5pc3N1ZXIgPSBtZXRhZGF0YS5pc3N1ZXI7XHJcbiAgICAgICAgdGhpcy5lbmRwb2ludHNGcm9tTmV0d29yayA9IGZyb21OZXR3b3JrO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2F2ZSB0aGUgYXV0aG9yaXR5IHRoYXQgd2FzIHVzZWQgdG8gY3JlYXRlIHRoaXMgY2FjaGUgZW50cnlcclxuICAgICAqIEBwYXJhbSBhdXRob3JpdHkgXHJcbiAgICAgKi9cclxuICAgIHVwZGF0ZUNhbm9uaWNhbEF1dGhvcml0eShhdXRob3JpdHk6IHN0cmluZykge1xyXG4gICAgICAgIHRoaXMuY2Fub25pY2FsX2F1dGhvcml0eSA9IGF1dGhvcml0eTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJlc2V0IHRoZSBleGlyZXNBdCB2YWx1ZVxyXG4gICAgICovXHJcbiAgICByZXNldEV4cGlyZXNBdCgpIHtcclxuICAgICAgICB0aGlzLmV4cGlyZXNBdCA9IFRpbWVVdGlscy5ub3dTZWNvbmRzKCkgKyBBVVRIT1JJVFlfTUVUQURBVEFfQ09OU1RBTlRTLlJFRlJFU0hfVElNRV9TRUNPTkRTO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgZGF0YSBuZWVkcyB0byBiZSByZWZyZXNoZWRcclxuICAgICAqL1xyXG4gICAgaXNFeHBpcmVkKCk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmV4cGlyZXNBdCA8PSBUaW1lVXRpbHMubm93U2Vjb25kcygpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVmFsaWRhdGVzIGFuIGVudGl0eTogY2hlY2tzIGZvciBhbGwgZXhwZWN0ZWQgcGFyYW1zXHJcbiAgICAgKiBAcGFyYW0gZW50aXR5XHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBpc0F1dGhvcml0eU1ldGFkYXRhRW50aXR5KGtleTogc3RyaW5nLCBlbnRpdHk6IG9iamVjdCk6IGJvb2xlYW4ge1xyXG5cclxuICAgICAgICBpZiAoIWVudGl0eSkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICBrZXkuaW5kZXhPZihBVVRIT1JJVFlfTUVUQURBVEFfQ09OU1RBTlRTLkNBQ0hFX0tFWSkgPT09IDAgJiZcclxuICAgICAgICAgICAgZW50aXR5Lmhhc093blByb3BlcnR5KFwiYWxpYXNlc1wiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJwcmVmZXJyZWRfY2FjaGVcIikgJiZcclxuICAgICAgICAgICAgZW50aXR5Lmhhc093blByb3BlcnR5KFwicHJlZmVycmVkX25ldHdvcmtcIikgJiZcclxuICAgICAgICAgICAgZW50aXR5Lmhhc093blByb3BlcnR5KFwiY2Fub25pY2FsX2F1dGhvcml0eVwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJhdXRob3JpemF0aW9uX2VuZHBvaW50XCIpICYmXHJcbiAgICAgICAgICAgIGVudGl0eS5oYXNPd25Qcm9wZXJ0eShcInRva2VuX2VuZHBvaW50XCIpICYmXHJcbiAgICAgICAgICAgIGVudGl0eS5oYXNPd25Qcm9wZXJ0eShcImVuZF9zZXNzaW9uX2VuZHBvaW50XCIpICYmXHJcbiAgICAgICAgICAgIGVudGl0eS5oYXNPd25Qcm9wZXJ0eShcImlzc3VlclwiKSAmJlxyXG4gICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJhbGlhc2VzRnJvbU5ldHdvcmtcIikgJiZcclxuICAgICAgICAgICAgZW50aXR5Lmhhc093blByb3BlcnR5KFwiZW5kcG9pbnRzRnJvbU5ldHdvcmtcIikgJiZcclxuICAgICAgICAgICAgZW50aXR5Lmhhc093blByb3BlcnR5KFwiZXhwaXJlc0F0XCIpXHJcbiAgICAgICAgKTtcclxuICAgIH1cclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IENsb3VkRGlzY292ZXJ5TWV0YWRhdGEgfSBmcm9tIFwiLi9DbG91ZERpc2NvdmVyeU1ldGFkYXRhXCI7XHJcblxyXG4vKipcclxuICogVGhlIE9wZW5JRCBDb25maWd1cmF0aW9uIEVuZHBvaW50IFJlc3BvbnNlIHR5cGUuIFVzZWQgYnkgdGhlIGF1dGhvcml0eSBjbGFzcyB0byBnZXQgcmVsZXZhbnQgT0F1dGggZW5kcG9pbnRzLlxyXG4gKi9cclxuZXhwb3J0IHR5cGUgQ2xvdWRJbnN0YW5jZURpc2NvdmVyeVJlc3BvbnNlID0ge1xyXG4gICAgdGVuYW50X2Rpc2NvdmVyeV9lbmRwb2ludDogc3RyaW5nO1xyXG4gICAgbWV0YWRhdGE6IEFycmF5PENsb3VkRGlzY292ZXJ5TWV0YWRhdGE+O1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGlzQ2xvdWRJbnN0YW5jZURpc2NvdmVyeVJlc3BvbnNlKHJlc3BvbnNlOiBvYmplY3QpOiBib29sZWFuIHtcclxuICAgIHJldHVybiAoXHJcbiAgICAgICAgcmVzcG9uc2UuaGFzT3duUHJvcGVydHkoXCJ0ZW5hbnRfZGlzY292ZXJ5X2VuZHBvaW50XCIpICYmXHJcbiAgICAgICAgcmVzcG9uc2UuaGFzT3duUHJvcGVydHkoXCJtZXRhZGF0YVwiKVxyXG4gICAgKTtcclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IEF1dGhvcml0eVR5cGUgfSBmcm9tIFwiLi9BdXRob3JpdHlUeXBlXCI7XHJcbmltcG9ydCB7IGlzT3BlbklkQ29uZmlnUmVzcG9uc2UsIE9wZW5JZENvbmZpZ1Jlc3BvbnNlIH0gZnJvbSBcIi4vT3BlbklkQ29uZmlnUmVzcG9uc2VcIjtcclxuaW1wb3J0IHsgVXJsU3RyaW5nIH0gZnJvbSBcIi4uL3VybC9VcmxTdHJpbmdcIjtcclxuaW1wb3J0IHsgSVVyaSB9IGZyb20gXCIuLi91cmwvSVVyaVwiO1xyXG5pbXBvcnQgeyBDbGllbnRBdXRoRXJyb3IgfSBmcm9tIFwiLi4vZXJyb3IvQ2xpZW50QXV0aEVycm9yXCI7XHJcbmltcG9ydCB7IElOZXR3b3JrTW9kdWxlIH0gZnJvbSBcIi4uL25ldHdvcmsvSU5ldHdvcmtNb2R1bGVcIjtcclxuaW1wb3J0IHsgQXV0aG9yaXR5TWV0YWRhdGFTb3VyY2UsIENvbnN0YW50cyB9IGZyb20gXCIuLi91dGlscy9Db25zdGFudHNcIjtcclxuaW1wb3J0IHsgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL0NsaWVudENvbmZpZ3VyYXRpb25FcnJvclwiO1xyXG5pbXBvcnQgeyBQcm90b2NvbE1vZGUgfSBmcm9tIFwiLi9Qcm90b2NvbE1vZGVcIjtcclxuaW1wb3J0IHsgSUNhY2hlTWFuYWdlciB9IGZyb20gXCIuLi9jYWNoZS9pbnRlcmZhY2UvSUNhY2hlTWFuYWdlclwiO1xyXG5pbXBvcnQgeyBBdXRob3JpdHlNZXRhZGF0YUVudGl0eSB9IGZyb20gXCIuLi9jYWNoZS9lbnRpdGllcy9BdXRob3JpdHlNZXRhZGF0YUVudGl0eVwiO1xyXG5pbXBvcnQgeyBBdXRob3JpdHlPcHRpb25zIH0gZnJvbSBcIi4vQXV0aG9yaXR5T3B0aW9uc1wiO1xyXG5pbXBvcnQgeyBDbG91ZEluc3RhbmNlRGlzY292ZXJ5UmVzcG9uc2UsIGlzQ2xvdWRJbnN0YW5jZURpc2NvdmVyeVJlc3BvbnNlIH0gZnJvbSBcIi4vQ2xvdWRJbnN0YW5jZURpc2NvdmVyeVJlc3BvbnNlXCI7XHJcbmltcG9ydCB7IENsb3VkRGlzY292ZXJ5TWV0YWRhdGEgfSBmcm9tIFwiLi9DbG91ZERpc2NvdmVyeU1ldGFkYXRhXCI7XHJcblxyXG4vKipcclxuICogVGhlIGF1dGhvcml0eSBjbGFzcyB2YWxpZGF0ZXMgdGhlIGF1dGhvcml0eSBVUklzIHVzZWQgYnkgdGhlIHVzZXIsIGFuZCByZXRyaWV2ZXMgdGhlIE9wZW5JRCBDb25maWd1cmF0aW9uIERhdGEgZnJvbSB0aGVcclxuICogZW5kcG9pbnQuIEl0IHdpbGwgc3RvcmUgdGhlIHBlcnRpbmVudCBjb25maWcgZGF0YSBpbiB0aGlzIG9iamVjdCBmb3IgdXNlIGR1cmluZyB0b2tlbiBjYWxscy5cclxuICovXHJcbmV4cG9ydCBjbGFzcyBBdXRob3JpdHkge1xyXG5cclxuICAgIC8vIENhbm9uaWNhbCBhdXRob3JpdHkgdXJsIHN0cmluZ1xyXG4gICAgcHJpdmF0ZSBfY2Fub25pY2FsQXV0aG9yaXR5OiBVcmxTdHJpbmc7XHJcbiAgICAvLyBDYW5vbmljYWx5IGF1dGhvcml0eSB1cmwgY29tcG9uZW50c1xyXG4gICAgcHJpdmF0ZSBfY2Fub25pY2FsQXV0aG9yaXR5VXJsQ29tcG9uZW50czogSVVyaSB8IG51bGw7XHJcbiAgICAvLyBOZXR3b3JrIGludGVyZmFjZSB0byBtYWtlIHJlcXVlc3RzIHdpdGguXHJcbiAgICBwcm90ZWN0ZWQgbmV0d29ya0ludGVyZmFjZTogSU5ldHdvcmtNb2R1bGU7XHJcbiAgICAvLyBDYWNoZSBNYW5hZ2VyIHRvIGNhY2hlIG5ldHdvcmsgcmVzcG9uc2VzXHJcbiAgICBwcm90ZWN0ZWQgY2FjaGVNYW5hZ2VyOiBJQ2FjaGVNYW5hZ2VyO1xyXG4gICAgLy8gUHJvdG9jb2wgbW9kZSB0byBjb25zdHJ1Y3QgZW5kcG9pbnRzXHJcbiAgICBwcml2YXRlIGF1dGhvcml0eU9wdGlvbnM6IEF1dGhvcml0eU9wdGlvbnM7XHJcbiAgICAvLyBBdXRob3JpdHkgbWV0YWRhdGFcclxuICAgIHByaXZhdGUgbWV0YWRhdGE6IEF1dGhvcml0eU1ldGFkYXRhRW50aXR5O1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKGF1dGhvcml0eTogc3RyaW5nLCBuZXR3b3JrSW50ZXJmYWNlOiBJTmV0d29ya01vZHVsZSwgY2FjaGVNYW5hZ2VyOiBJQ2FjaGVNYW5hZ2VyLCBhdXRob3JpdHlPcHRpb25zOiBBdXRob3JpdHlPcHRpb25zKSB7XHJcbiAgICAgICAgdGhpcy5jYW5vbmljYWxBdXRob3JpdHkgPSBhdXRob3JpdHk7XHJcbiAgICAgICAgdGhpcy5fY2Fub25pY2FsQXV0aG9yaXR5LnZhbGlkYXRlQXNVcmkoKTtcclxuICAgICAgICB0aGlzLm5ldHdvcmtJbnRlcmZhY2UgPSBuZXR3b3JrSW50ZXJmYWNlO1xyXG4gICAgICAgIHRoaXMuY2FjaGVNYW5hZ2VyID0gY2FjaGVNYW5hZ2VyO1xyXG4gICAgICAgIHRoaXMuYXV0aG9yaXR5T3B0aW9ucyA9IGF1dGhvcml0eU9wdGlvbnM7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gU2VlIGFib3ZlIGZvciBBdXRob3JpdHlUeXBlXHJcbiAgICBwdWJsaWMgZ2V0IGF1dGhvcml0eVR5cGUoKTogQXV0aG9yaXR5VHlwZSB7XHJcbiAgICAgICAgY29uc3QgcGF0aFNlZ21lbnRzID0gdGhpcy5jYW5vbmljYWxBdXRob3JpdHlVcmxDb21wb25lbnRzLlBhdGhTZWdtZW50cztcclxuXHJcbiAgICAgICAgaWYgKHBhdGhTZWdtZW50cy5sZW5ndGggJiYgcGF0aFNlZ21lbnRzWzBdLnRvTG93ZXJDYXNlKCkgPT09IENvbnN0YW50cy5BREZTKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBBdXRob3JpdHlUeXBlLkFkZnM7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gQXV0aG9yaXR5VHlwZS5EZWZhdWx0O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUHJvdG9jb2xNb2RlIGVudW0gcmVwcmVzZW50aW5nIHRoZSB3YXkgZW5kcG9pbnRzIGFyZSBjb25zdHJ1Y3RlZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGdldCBwcm90b2NvbE1vZGUoKTogUHJvdG9jb2xNb2RlIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5hdXRob3JpdHlPcHRpb25zLnByb3RvY29sTW9kZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgYXV0aG9yaXR5T3B0aW9ucyB3aGljaCBjYW4gYmUgdXNlZCB0byByZWluc3RhbnRpYXRlIGEgbmV3IGF1dGhvcml0eSBpbnN0YW5jZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ2V0IG9wdGlvbnMoKTogQXV0aG9yaXR5T3B0aW9ucyB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aG9yaXR5T3B0aW9ucztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEEgVVJMIHRoYXQgaXMgdGhlIGF1dGhvcml0eSBzZXQgYnkgdGhlIGRldmVsb3BlclxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ2V0IGNhbm9uaWNhbEF1dGhvcml0eSgpOiBzdHJpbmcge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9jYW5vbmljYWxBdXRob3JpdHkudXJsU3RyaW5nO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2V0cyBjYW5vbmljYWwgYXV0aG9yaXR5LlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc2V0IGNhbm9uaWNhbEF1dGhvcml0eSh1cmw6IHN0cmluZykge1xyXG4gICAgICAgIHRoaXMuX2Nhbm9uaWNhbEF1dGhvcml0eSA9IG5ldyBVcmxTdHJpbmcodXJsKTtcclxuICAgICAgICB0aGlzLl9jYW5vbmljYWxBdXRob3JpdHkudmFsaWRhdGVBc1VyaSgpO1xyXG4gICAgICAgIHRoaXMuX2Nhbm9uaWNhbEF1dGhvcml0eVVybENvbXBvbmVudHMgPSBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0IGF1dGhvcml0eSBjb21wb25lbnRzLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ2V0IGNhbm9uaWNhbEF1dGhvcml0eVVybENvbXBvbmVudHMoKTogSVVyaSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLl9jYW5vbmljYWxBdXRob3JpdHlVcmxDb21wb25lbnRzKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX2Nhbm9uaWNhbEF1dGhvcml0eVVybENvbXBvbmVudHMgPSB0aGlzLl9jYW5vbmljYWxBdXRob3JpdHkuZ2V0VXJsQ29tcG9uZW50cygpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Nhbm9uaWNhbEF1dGhvcml0eVVybENvbXBvbmVudHM7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXQgaG9zdG5hbWUgYW5kIHBvcnQgaS5lLiBsb2dpbi5taWNyb3NvZnRvbmxpbmUuY29tXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZXQgaG9zdG5hbWVBbmRQb3J0KCk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuY2Fub25pY2FsQXV0aG9yaXR5VXJsQ29tcG9uZW50cy5Ib3N0TmFtZUFuZFBvcnQudG9Mb3dlckNhc2UoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdldCB0ZW5hbnQgZm9yIGF1dGhvcml0eS5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGdldCB0ZW5hbnQoKTogc3RyaW5nIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5jYW5vbmljYWxBdXRob3JpdHlVcmxDb21wb25lbnRzLlBhdGhTZWdtZW50c1swXTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE9BdXRoIC9hdXRob3JpemUgZW5kcG9pbnQgZm9yIHJlcXVlc3RzXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZXQgYXV0aG9yaXphdGlvbkVuZHBvaW50KCk6IHN0cmluZyB7XHJcbiAgICAgICAgaWYodGhpcy5kaXNjb3ZlcnlDb21wbGV0ZSgpKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGVuZHBvaW50ID0gdGhpcy5yZXBsYWNlUGF0aCh0aGlzLm1ldGFkYXRhLmF1dGhvcml6YXRpb25fZW5kcG9pbnQpO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZXBsYWNlVGVuYW50KGVuZHBvaW50KTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRBdXRoRXJyb3IuY3JlYXRlRW5kcG9pbnREaXNjb3ZlcnlJbmNvbXBsZXRlRXJyb3IoXCJEaXNjb3ZlcnkgaW5jb21wbGV0ZS5cIik7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogT0F1dGggL3Rva2VuIGVuZHBvaW50IGZvciByZXF1ZXN0c1xyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ2V0IHRva2VuRW5kcG9pbnQoKTogc3RyaW5nIHtcclxuICAgICAgICBpZih0aGlzLmRpc2NvdmVyeUNvbXBsZXRlKCkpIHtcclxuICAgICAgICAgICAgY29uc3QgZW5kcG9pbnQgPSB0aGlzLnJlcGxhY2VQYXRoKHRoaXMubWV0YWRhdGEudG9rZW5fZW5kcG9pbnQpO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZXBsYWNlVGVuYW50KGVuZHBvaW50KTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRBdXRoRXJyb3IuY3JlYXRlRW5kcG9pbnREaXNjb3ZlcnlJbmNvbXBsZXRlRXJyb3IoXCJEaXNjb3ZlcnkgaW5jb21wbGV0ZS5cIik7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXQgZGV2aWNlQ29kZUVuZHBvaW50KCk6IHN0cmluZyB7XHJcbiAgICAgICAgaWYodGhpcy5kaXNjb3ZlcnlDb21wbGV0ZSgpKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGVuZHBvaW50ID0gdGhpcy5yZXBsYWNlUGF0aCh0aGlzLm1ldGFkYXRhLnRva2VuX2VuZHBvaW50LnJlcGxhY2UoXCIvdG9rZW5cIiwgXCIvZGV2aWNlY29kZVwiKSk7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlcGxhY2VUZW5hbnQoZW5kcG9pbnQpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVFbmRwb2ludERpc2NvdmVyeUluY29tcGxldGVFcnJvcihcIkRpc2NvdmVyeSBpbmNvbXBsZXRlLlwiKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBPQXV0aCBsb2dvdXQgZW5kcG9pbnQgZm9yIHJlcXVlc3RzXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZXQgZW5kU2Vzc2lvbkVuZHBvaW50KCk6IHN0cmluZyB7XHJcbiAgICAgICAgaWYodGhpcy5kaXNjb3ZlcnlDb21wbGV0ZSgpKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGVuZHBvaW50ID0gdGhpcy5yZXBsYWNlUGF0aCh0aGlzLm1ldGFkYXRhLmVuZF9zZXNzaW9uX2VuZHBvaW50KTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVwbGFjZVRlbmFudChlbmRwb2ludCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50QXV0aEVycm9yLmNyZWF0ZUVuZHBvaW50RGlzY292ZXJ5SW5jb21wbGV0ZUVycm9yKFwiRGlzY292ZXJ5IGluY29tcGxldGUuXCIpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE9BdXRoIGlzc3VlciBmb3IgcmVxdWVzdHNcclxuICAgICAqL1xyXG4gICAgcHVibGljIGdldCBzZWxmU2lnbmVkSnd0QXVkaWVuY2UoKTogc3RyaW5nIHtcclxuICAgICAgICBpZih0aGlzLmRpc2NvdmVyeUNvbXBsZXRlKCkpIHtcclxuICAgICAgICAgICAgY29uc3QgZW5kcG9pbnQgPSB0aGlzLnJlcGxhY2VQYXRoKHRoaXMubWV0YWRhdGEuaXNzdWVyKTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVwbGFjZVRlbmFudChlbmRwb2ludCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50QXV0aEVycm9yLmNyZWF0ZUVuZHBvaW50RGlzY292ZXJ5SW5jb21wbGV0ZUVycm9yKFwiRGlzY292ZXJ5IGluY29tcGxldGUuXCIpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJlcGxhY2VzIHRlbmFudCBpbiB1cmwgcGF0aCB3aXRoIGN1cnJlbnQgdGVuYW50LiBEZWZhdWx0cyB0byBjb21tb24uXHJcbiAgICAgKiBAcGFyYW0gdXJsU3RyaW5nXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgcmVwbGFjZVRlbmFudCh1cmxTdHJpbmc6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIHVybFN0cmluZy5yZXBsYWNlKC97dGVuYW50fXx7dGVuYW50aWR9L2csIHRoaXMudGVuYW50KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJlcGxhY2VzIHBhdGggc3VjaCBhcyB0ZW5hbnQgb3IgcG9saWN5IHdpdGggdGhlIGN1cnJlbnQgdGVuYW50IG9yIHBvbGljeS5cclxuICAgICAqIEBwYXJhbSB1cmxTdHJpbmcgXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgcmVwbGFjZVBhdGgodXJsU3RyaW5nOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIGxldCBlbmRwb2ludCA9IHVybFN0cmluZztcclxuICAgICAgICBjb25zdCBjYWNoZWRBdXRob3JpdHlVcmwgPSBuZXcgVXJsU3RyaW5nKHRoaXMubWV0YWRhdGEuY2Fub25pY2FsX2F1dGhvcml0eSk7XHJcbiAgICAgICAgY29uc3QgY2FjaGVkQXV0aG9yaXR5UGFydHMgPSBjYWNoZWRBdXRob3JpdHlVcmwuZ2V0VXJsQ29tcG9uZW50cygpLlBhdGhTZWdtZW50cztcclxuICAgICAgICBjb25zdCBjdXJyZW50QXV0aG9yaXR5UGFydHMgPSB0aGlzLmNhbm9uaWNhbEF1dGhvcml0eVVybENvbXBvbmVudHMuUGF0aFNlZ21lbnRzO1xyXG5cclxuICAgICAgICBjdXJyZW50QXV0aG9yaXR5UGFydHMuZm9yRWFjaCgoY3VycmVudFBhcnQsIGluZGV4KSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IGNhY2hlZFBhcnQgPSBjYWNoZWRBdXRob3JpdHlQYXJ0c1tpbmRleF07XHJcbiAgICAgICAgICAgIGlmIChjdXJyZW50UGFydCAhPT0gY2FjaGVkUGFydCkge1xyXG4gICAgICAgICAgICAgICAgZW5kcG9pbnQgPSBlbmRwb2ludC5yZXBsYWNlKGAvJHtjYWNoZWRQYXJ0fS9gLCBgLyR7Y3VycmVudFBhcnR9L2ApO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHJldHVybiBlbmRwb2ludDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBkZWZhdWx0IG9wZW4gaWQgY29uZmlndXJhdGlvbiBlbmRwb2ludCBmb3IgYW55IGNhbm9uaWNhbCBhdXRob3JpdHkuXHJcbiAgICAgKi9cclxuICAgIHByb3RlY3RlZCBnZXQgZGVmYXVsdE9wZW5JZENvbmZpZ3VyYXRpb25FbmRwb2ludCgpOiBzdHJpbmcge1xyXG4gICAgICAgIGlmICh0aGlzLmF1dGhvcml0eVR5cGUgPT09IEF1dGhvcml0eVR5cGUuQWRmcyB8fCB0aGlzLnByb3RvY29sTW9kZSA9PT0gUHJvdG9jb2xNb2RlLk9JREMpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGAke3RoaXMuY2Fub25pY2FsQXV0aG9yaXR5fS53ZWxsLWtub3duL29wZW5pZC1jb25maWd1cmF0aW9uYDtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGAke3RoaXMuY2Fub25pY2FsQXV0aG9yaXR5fXYyLjAvLndlbGwta25vd24vb3BlbmlkLWNvbmZpZ3VyYXRpb25gO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQm9vbGVhbiB0aGF0IHJldHVybnMgd2hldGhyIG9yIG5vdCB0ZW5hbnQgZGlzY292ZXJ5IGhhcyBiZWVuIGNvbXBsZXRlZC5cclxuICAgICAqL1xyXG4gICAgZGlzY292ZXJ5Q29tcGxldGUoKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuICEhdGhpcy5tZXRhZGF0YTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFBlcmZvcm0gZW5kcG9pbnQgZGlzY292ZXJ5IHRvIGRpc2NvdmVyIGFsaWFzZXMsIHByZWZlcnJlZF9jYWNoZSwgcHJlZmVycmVkX25ldHdvcmtcclxuICAgICAqIGFuZCB0aGUgL2F1dGhvcml6ZSwgL3Rva2VuIGFuZCBsb2dvdXQgZW5kcG9pbnRzLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgYXN5bmMgcmVzb2x2ZUVuZHBvaW50c0FzeW5jKCk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIGxldCBtZXRhZGF0YUVudGl0eSA9IHRoaXMuY2FjaGVNYW5hZ2VyLmdldEF1dGhvcml0eU1ldGFkYXRhQnlBbGlhcyh0aGlzLmhvc3RuYW1lQW5kUG9ydCk7XHJcbiAgICAgICAgaWYgKCFtZXRhZGF0YUVudGl0eSkge1xyXG4gICAgICAgICAgICBtZXRhZGF0YUVudGl0eSA9IG5ldyBBdXRob3JpdHlNZXRhZGF0YUVudGl0eSgpO1xyXG4gICAgICAgICAgICBtZXRhZGF0YUVudGl0eS51cGRhdGVDYW5vbmljYWxBdXRob3JpdHkodGhpcy5jYW5vbmljYWxBdXRob3JpdHkpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgY2xvdWREaXNjb3ZlcnlTb3VyY2UgPSBhd2FpdCB0aGlzLnVwZGF0ZUNsb3VkRGlzY292ZXJ5TWV0YWRhdGEobWV0YWRhdGFFbnRpdHkpO1xyXG4gICAgICAgIHRoaXMuY2Fub25pY2FsQXV0aG9yaXR5ID0gdGhpcy5jYW5vbmljYWxBdXRob3JpdHkucmVwbGFjZSh0aGlzLmhvc3RuYW1lQW5kUG9ydCwgbWV0YWRhdGFFbnRpdHkucHJlZmVycmVkX25ldHdvcmspO1xyXG4gICAgICAgIGNvbnN0IGVuZHBvaW50U291cmNlID0gYXdhaXQgdGhpcy51cGRhdGVFbmRwb2ludE1ldGFkYXRhKG1ldGFkYXRhRW50aXR5KTtcclxuXHJcbiAgICAgICAgaWYgKGNsb3VkRGlzY292ZXJ5U291cmNlICE9PSBBdXRob3JpdHlNZXRhZGF0YVNvdXJjZS5DQUNIRSAmJiBlbmRwb2ludFNvdXJjZSAhPT0gQXV0aG9yaXR5TWV0YWRhdGFTb3VyY2UuQ0FDSEUpIHtcclxuICAgICAgICAgICAgLy8gUmVzZXQgdGhlIGV4cGlyYXRpb24gdGltZSB1bmxlc3MgYm90aCB2YWx1ZXMgY2FtZSBmcm9tIGEgc3VjY2Vzc2Z1bCBjYWNoZSBsb29rdXBcclxuICAgICAgICAgICAgbWV0YWRhdGFFbnRpdHkucmVzZXRFeHBpcmVzQXQoKTtcclxuICAgICAgICAgICAgbWV0YWRhdGFFbnRpdHkudXBkYXRlQ2Fub25pY2FsQXV0aG9yaXR5KHRoaXMuY2Fub25pY2FsQXV0aG9yaXR5KTtcclxuICAgICAgICB9IFxyXG5cclxuICAgICAgICBjb25zdCBjYWNoZUtleSA9IHRoaXMuY2FjaGVNYW5hZ2VyLmdlbmVyYXRlQXV0aG9yaXR5TWV0YWRhdGFDYWNoZUtleShtZXRhZGF0YUVudGl0eS5wcmVmZXJyZWRfY2FjaGUpO1xyXG4gICAgICAgIHRoaXMuY2FjaGVNYW5hZ2VyLnNldEF1dGhvcml0eU1ldGFkYXRhKGNhY2hlS2V5LCBtZXRhZGF0YUVudGl0eSk7XHJcbiAgICAgICAgdGhpcy5tZXRhZGF0YSA9IG1ldGFkYXRhRW50aXR5O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVXBkYXRlIEF1dGhvcml0eU1ldGFkYXRhRW50aXR5IHdpdGggbmV3IGVuZHBvaW50cyBhbmQgcmV0dXJuIHdoZXJlIHRoZSBpbmZvcm1hdGlvbiBjYW1lIGZyb21cclxuICAgICAqIEBwYXJhbSBtZXRhZGF0YUVudGl0eSBcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhc3luYyB1cGRhdGVFbmRwb2ludE1ldGFkYXRhKG1ldGFkYXRhRW50aXR5OiBBdXRob3JpdHlNZXRhZGF0YUVudGl0eSk6IFByb21pc2U8QXV0aG9yaXR5TWV0YWRhdGFTb3VyY2U+IHtcclxuICAgICAgICBsZXQgbWV0YWRhdGEgPSB0aGlzLmdldEVuZHBvaW50TWV0YWRhdGFGcm9tQ29uZmlnKCk7XHJcbiAgICAgICAgaWYgKG1ldGFkYXRhKSB7XHJcbiAgICAgICAgICAgIG1ldGFkYXRhRW50aXR5LnVwZGF0ZUVuZHBvaW50TWV0YWRhdGEobWV0YWRhdGEsIGZhbHNlKTtcclxuICAgICAgICAgICAgcmV0dXJuIEF1dGhvcml0eU1ldGFkYXRhU291cmNlLkNPTkZJRztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmlzQXV0aG9yaXR5U2FtZVR5cGUobWV0YWRhdGFFbnRpdHkpICYmIG1ldGFkYXRhRW50aXR5LmVuZHBvaW50c0Zyb21OZXR3b3JrICYmICFtZXRhZGF0YUVudGl0eS5pc0V4cGlyZWQoKSkge1xyXG4gICAgICAgICAgICAvLyBObyBuZWVkIHRvIHVwZGF0ZVxyXG4gICAgICAgICAgICByZXR1cm4gQXV0aG9yaXR5TWV0YWRhdGFTb3VyY2UuQ0FDSEU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBtZXRhZGF0YSA9IGF3YWl0IHRoaXMuZ2V0RW5kcG9pbnRNZXRhZGF0YUZyb21OZXR3b3JrKCk7XHJcbiAgICAgICAgaWYgKG1ldGFkYXRhKSB7XHJcbiAgICAgICAgICAgIG1ldGFkYXRhRW50aXR5LnVwZGF0ZUVuZHBvaW50TWV0YWRhdGEobWV0YWRhdGEsIHRydWUpO1xyXG4gICAgICAgICAgICByZXR1cm4gQXV0aG9yaXR5TWV0YWRhdGFTb3VyY2UuTkVUV09SSztcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aHJvdyBDbGllbnRBdXRoRXJyb3IuY3JlYXRlVW5hYmxlVG9HZXRPcGVuaWRDb25maWdFcnJvcih0aGlzLmRlZmF1bHRPcGVuSWRDb25maWd1cmF0aW9uRW5kcG9pbnQpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbXBhcmVzIHRoZSBudW1iZXIgb2YgdXJsIGNvbXBvbmVudHMgYWZ0ZXIgdGhlIGRvbWFpbiB0byBkZXRlcm1pbmUgaWYgdGhlIGNhY2hlZCBhdXRob3JpdHkgbWV0YWRhdGEgY2FuIGJlIHVzZWQgZm9yIHRoZSByZXF1ZXN0ZWQgYXV0aG9yaXR5XHJcbiAgICAgKiBQcm90ZWN0cyBhZ2FpbnN0IHNhbWUgZG9tYWluIGRpZmZlcmVudCBhdXRob3JpdHkgc3VjaCBhcyBsb2dpbi5taWNyb3NvZnRvbmxpbmUuY29tL3RlbmFudCBhbmQgbG9naW4ubWljcm9zb2Z0b25saW5lLmNvbS90ZnAvdGVuYW50L3BvbGljeVxyXG4gICAgICogQHBhcmFtIG1ldGFkYXRhRW50aXR5XHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgaXNBdXRob3JpdHlTYW1lVHlwZShtZXRhZGF0YUVudGl0eTogQXV0aG9yaXR5TWV0YWRhdGFFbnRpdHkpOiBib29sZWFuIHtcclxuICAgICAgICBjb25zdCBjYWNoZWRBdXRob3JpdHlVcmwgPSBuZXcgVXJsU3RyaW5nKG1ldGFkYXRhRW50aXR5LmNhbm9uaWNhbF9hdXRob3JpdHkpO1xyXG4gICAgICAgIGNvbnN0IGNhY2hlZFBhcnRzID0gY2FjaGVkQXV0aG9yaXR5VXJsLmdldFVybENvbXBvbmVudHMoKS5QYXRoU2VnbWVudHM7XHJcbiAgICAgICAgXHJcbiAgICAgICAgcmV0dXJuIGNhY2hlZFBhcnRzLmxlbmd0aCA9PT0gdGhpcy5jYW5vbmljYWxBdXRob3JpdHlVcmxDb21wb25lbnRzLlBhdGhTZWdtZW50cy5sZW5ndGg7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBQYXJzZSBhdXRob3JpdHlNZXRhZGF0YSBjb25maWcgb3B0aW9uXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgZ2V0RW5kcG9pbnRNZXRhZGF0YUZyb21Db25maWcoKTogT3BlbklkQ29uZmlnUmVzcG9uc2UgfCBudWxsIHtcclxuICAgICAgICBpZiAodGhpcy5hdXRob3JpdHlPcHRpb25zLmF1dGhvcml0eU1ldGFkYXRhKSB7XHJcbiAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZSh0aGlzLmF1dGhvcml0eU9wdGlvbnMuYXV0aG9yaXR5TWV0YWRhdGEpIGFzIE9wZW5JZENvbmZpZ1Jlc3BvbnNlO1xyXG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBDbGllbnRDb25maWd1cmF0aW9uRXJyb3IuY3JlYXRlSW52YWxpZEF1dGhvcml0eU1ldGFkYXRhRXJyb3IoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIE9BdXRoIGVuZHBvaW50cyBmcm9tIHRoZSBnaXZlbiBPcGVuSUQgY29uZmlndXJhdGlvbiBlbmRwb2ludC5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhc3luYyBnZXRFbmRwb2ludE1ldGFkYXRhRnJvbU5ldHdvcmsoKTogUHJvbWlzZTxPcGVuSWRDb25maWdSZXNwb25zZSB8IG51bGw+IHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMubmV0d29ya0ludGVyZmFjZS5zZW5kR2V0UmVxdWVzdEFzeW5jPE9wZW5JZENvbmZpZ1Jlc3BvbnNlPih0aGlzLmRlZmF1bHRPcGVuSWRDb25maWd1cmF0aW9uRW5kcG9pbnQpO1xyXG4gICAgICAgICAgICByZXR1cm4gaXNPcGVuSWRDb25maWdSZXNwb25zZShyZXNwb25zZS5ib2R5KSA/IHJlc3BvbnNlLmJvZHkgOiBudWxsO1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVXBkYXRlcyB0aGUgQXV0aG9yaXR5TWV0YWRhdGFFbnRpdHkgd2l0aCBuZXcgYWxpYXNlcywgcHJlZmVycmVkX25ldHdvcmsgYW5kIHByZWZlcnJlZF9jYWNoZSBhbmQgcmV0dXJucyB3aGVyZSB0aGUgaW5mb3JtYXRpb24gd2FzIHJldHJpdmVkIGZyb21cclxuICAgICAqIEBwYXJhbSBjYWNoZWRNZXRhZGF0YSBcclxuICAgICAqIEBwYXJhbSBuZXdNZXRhZGF0YSBcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbG91ZERpc2NvdmVyeU1ldGFkYXRhKG1ldGFkYXRhRW50aXR5OiBBdXRob3JpdHlNZXRhZGF0YUVudGl0eSk6IFByb21pc2U8QXV0aG9yaXR5TWV0YWRhdGFTb3VyY2U+IHtcclxuICAgICAgICBsZXQgbWV0YWRhdGEgPSB0aGlzLmdldENsb3VkRGlzY292ZXJ5TWV0YWRhdGFGcm9tQ29uZmlnKCk7XHJcbiAgICAgICAgaWYgKG1ldGFkYXRhKSB7XHJcbiAgICAgICAgICAgIG1ldGFkYXRhRW50aXR5LnVwZGF0ZUNsb3VkRGlzY292ZXJ5TWV0YWRhdGEobWV0YWRhdGEsIGZhbHNlKTtcclxuICAgICAgICAgICAgcmV0dXJuIEF1dGhvcml0eU1ldGFkYXRhU291cmNlLkNPTkZJRztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIElmIFRoZSBjYWNoZWQgbWV0YWRhdGEgY2FtZSBmcm9tIGNvbmZpZyBidXQgdGhhdCBjb25maWcgd2FzIG5vdCBwYXNzZWQgdG8gdGhpcyBpbnN0YW5jZSwgd2UgbXVzdCBnbyB0byB0aGUgbmV0d29ya1xyXG4gICAgICAgIGlmICh0aGlzLmlzQXV0aG9yaXR5U2FtZVR5cGUobWV0YWRhdGFFbnRpdHkpICYmIG1ldGFkYXRhRW50aXR5LmFsaWFzZXNGcm9tTmV0d29yayAmJiAhbWV0YWRhdGFFbnRpdHkuaXNFeHBpcmVkKCkpIHtcclxuICAgICAgICAgICAgLy8gTm8gbmVlZCB0byB1cGRhdGVcclxuICAgICAgICAgICAgcmV0dXJuIEF1dGhvcml0eU1ldGFkYXRhU291cmNlLkNBQ0hFO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbWV0YWRhdGEgPSBhd2FpdCB0aGlzLmdldENsb3VkRGlzY292ZXJ5TWV0YWRhdGFGcm9tTmV0d29yaygpO1xyXG4gICAgICAgIGlmIChtZXRhZGF0YSkge1xyXG4gICAgICAgICAgICBtZXRhZGF0YUVudGl0eS51cGRhdGVDbG91ZERpc2NvdmVyeU1ldGFkYXRhKG1ldGFkYXRhLCB0cnVlKTtcclxuICAgICAgICAgICAgcmV0dXJuIEF1dGhvcml0eU1ldGFkYXRhU291cmNlLk5FVFdPUks7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgLy8gTWV0YWRhdGEgY291bGQgbm90IGJlIG9idGFpbmVkIGZyb20gY29uZmlnLCBjYWNoZSBvciBuZXR3b3JrXHJcbiAgICAgICAgICAgIHRocm93IENsaWVudENvbmZpZ3VyYXRpb25FcnJvci5jcmVhdGVVbnRydXN0ZWRBdXRob3JpdHlFcnJvcigpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFBhcnNlIGNsb3VkRGlzY292ZXJ5TWV0YWRhdGEgY29uZmlnIG9yIGNoZWNrIGtub3duQXV0aG9yaXRpZXNcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBnZXRDbG91ZERpc2NvdmVyeU1ldGFkYXRhRnJvbUNvbmZpZygpOiBDbG91ZERpc2NvdmVyeU1ldGFkYXRhIHwgbnVsbCB7XHJcbiAgICAgICAgLy8gQ2hlY2sgaWYgbmV0d29yayByZXNwb25zZSB3YXMgcHJvdmlkZWQgaW4gY29uZmlnXHJcbiAgICAgICAgaWYgKHRoaXMuYXV0aG9yaXR5T3B0aW9ucy5jbG91ZERpc2NvdmVyeU1ldGFkYXRhKSB7XHJcbiAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBwYXJzZWRSZXNwb25zZSA9IEpTT04ucGFyc2UodGhpcy5hdXRob3JpdHlPcHRpb25zLmNsb3VkRGlzY292ZXJ5TWV0YWRhdGEpIGFzIENsb3VkSW5zdGFuY2VEaXNjb3ZlcnlSZXNwb25zZTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG1ldGFkYXRhID0gQXV0aG9yaXR5LmdldENsb3VkRGlzY292ZXJ5TWV0YWRhdGFGcm9tTmV0d29ya1Jlc3BvbnNlKHBhcnNlZFJlc3BvbnNlLm1ldGFkYXRhLCB0aGlzLmhvc3RuYW1lQW5kUG9ydCk7XHJcbiAgICAgICAgICAgICAgICBpZiAobWV0YWRhdGEpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWV0YWRhdGE7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IENsaWVudENvbmZpZ3VyYXRpb25FcnJvci5jcmVhdGVJbnZhbGlkQ2xvdWREaXNjb3ZlcnlNZXRhZGF0YUVycm9yKCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIElmIGNsb3VkRGlzY292ZXJ5TWV0YWRhdGEgaXMgZW1wdHkgb3IgZG9lcyBub3QgY29udGFpbiB0aGUgaG9zdCwgY2hlY2sga25vd25BdXRob3JpdGllc1xyXG4gICAgICAgIGlmICh0aGlzLmlzSW5Lbm93bkF1dGhvcml0aWVzKCkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIEF1dGhvcml0eS5jcmVhdGVDbG91ZERpc2NvdmVyeU1ldGFkYXRhRnJvbUhvc3QodGhpcy5ob3N0bmFtZUFuZFBvcnQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDYWxsZWQgdG8gZ2V0IG1ldGFkYXRhIGZyb20gbmV0d29yayBpZiBDbG91ZERpc2NvdmVyeU1ldGFkYXRhIHdhcyBub3QgcG9wdWxhdGVkIGJ5IGNvbmZpZ1xyXG4gICAgICogQHBhcmFtIG5ldHdvcmtJbnRlcmZhY2UgXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgYXN5bmMgZ2V0Q2xvdWREaXNjb3ZlcnlNZXRhZGF0YUZyb21OZXR3b3JrKCk6IFByb21pc2U8Q2xvdWREaXNjb3ZlcnlNZXRhZGF0YSB8IG51bGw+IHtcclxuICAgICAgICBjb25zdCBpbnN0YW5jZURpc2NvdmVyeUVuZHBvaW50ID0gYCR7Q29uc3RhbnRzLkFBRF9JTlNUQU5DRV9ESVNDT1ZFUllfRU5EUFR9JHt0aGlzLmNhbm9uaWNhbEF1dGhvcml0eX1vYXV0aDIvdjIuMC9hdXRob3JpemVgO1xyXG4gICAgICAgIGxldCBtYXRjaCA9IG51bGw7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLm5ldHdvcmtJbnRlcmZhY2Uuc2VuZEdldFJlcXVlc3RBc3luYzxDbG91ZEluc3RhbmNlRGlzY292ZXJ5UmVzcG9uc2U+KGluc3RhbmNlRGlzY292ZXJ5RW5kcG9pbnQpO1xyXG4gICAgICAgICAgICBjb25zdCBtZXRhZGF0YSA9IGlzQ2xvdWRJbnN0YW5jZURpc2NvdmVyeVJlc3BvbnNlKHJlc3BvbnNlLmJvZHkpID8gcmVzcG9uc2UuYm9keS5tZXRhZGF0YSA6IFtdO1xyXG4gICAgICAgICAgICBtYXRjaCA9IEF1dGhvcml0eS5nZXRDbG91ZERpc2NvdmVyeU1ldGFkYXRhRnJvbU5ldHdvcmtSZXNwb25zZShtZXRhZGF0YSwgdGhpcy5ob3N0bmFtZUFuZFBvcnQpO1xyXG4gICAgICAgIH0gY2F0Y2goZSkge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICghbWF0Y2gpIHtcclxuICAgICAgICAgICAgLy8gQ3VzdG9tIERvbWFpbiBzY2VuYXJpbywgaG9zdCBpcyB0cnVzdGVkIGJlY2F1c2UgSW5zdGFuY2UgRGlzY292ZXJ5IGNhbGwgc3VjY2VlZGVkIFxyXG4gICAgICAgICAgICBtYXRjaCA9IEF1dGhvcml0eS5jcmVhdGVDbG91ZERpc2NvdmVyeU1ldGFkYXRhRnJvbUhvc3QodGhpcy5ob3N0bmFtZUFuZFBvcnQpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gbWF0Y2g7XHJcbiAgICB9IFxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGVscGVyIGZ1bmN0aW9uIHRvIGRldGVybWluZSBpZiB0aGlzIGhvc3QgaXMgaW5jbHVkZWQgaW4gdGhlIGtub3duQXV0aG9yaXRpZXMgY29uZmlnIG9wdGlvblxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGlzSW5Lbm93bkF1dGhvcml0aWVzKCk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGNvbnN0IG1hdGNoZXMgPSB0aGlzLmF1dGhvcml0eU9wdGlvbnMua25vd25BdXRob3JpdGllcy5maWx0ZXIoKGF1dGhvcml0eSkgPT4ge1xyXG4gICAgICAgICAgICByZXR1cm4gVXJsU3RyaW5nLmdldERvbWFpbkZyb21VcmwoYXV0aG9yaXR5KS50b0xvd2VyQ2FzZSgpID09PSB0aGlzLmhvc3RuYW1lQW5kUG9ydDtcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgcmV0dXJuIG1hdGNoZXMubGVuZ3RoID4gMDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZXMgY2xvdWQgZGlzY292ZXJ5IG1ldGFkYXRhIG9iamVjdCBmcm9tIGEgZ2l2ZW4gaG9zdFxyXG4gICAgICogQHBhcmFtIGhvc3QgXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVDbG91ZERpc2NvdmVyeU1ldGFkYXRhRnJvbUhvc3QoaG9zdDogc3RyaW5nKTogQ2xvdWREaXNjb3ZlcnlNZXRhZGF0YSB7XHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgcHJlZmVycmVkX25ldHdvcms6IGhvc3QsXHJcbiAgICAgICAgICAgIHByZWZlcnJlZF9jYWNoZTogaG9zdCxcclxuICAgICAgICAgICAgYWxpYXNlczogW2hvc3RdXHJcbiAgICAgICAgfTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFNlYXJjaGVzIGluc3RhbmNlIGRpc2NvdmVyeSBuZXR3b3JrIHJlc3BvbnNlIGZvciB0aGUgZW50cnkgdGhhdCBjb250YWlucyB0aGUgaG9zdCBpbiB0aGUgYWxpYXNlcyBsaXN0XHJcbiAgICAgKiBAcGFyYW0gcmVzcG9uc2UgXHJcbiAgICAgKiBAcGFyYW0gYXV0aG9yaXR5IFxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgZ2V0Q2xvdWREaXNjb3ZlcnlNZXRhZGF0YUZyb21OZXR3b3JrUmVzcG9uc2UocmVzcG9uc2U6IENsb3VkRGlzY292ZXJ5TWV0YWRhdGFbXSwgYXV0aG9yaXR5OiBzdHJpbmcpOiBDbG91ZERpc2NvdmVyeU1ldGFkYXRhIHwgbnVsbCB7XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCByZXNwb25zZS5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBjb25zdCBtZXRhZGF0YSA9IHJlc3BvbnNlW2ldO1xyXG4gICAgICAgICAgICBpZiAobWV0YWRhdGEuYWxpYXNlcy5pbmRleE9mKGF1dGhvcml0eSkgPiAtMSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIGhlbHBlciBmdW5jdGlvbiB0byBnZW5lcmF0ZSBlbnZpcm9ubWVudCBmcm9tIGF1dGhvcml0eSBvYmplY3RcclxuICAgICAqL1xyXG4gICAgZ2V0UHJlZmVycmVkQ2FjaGUoKTogc3RyaW5nIHtcclxuICAgICAgICBpZih0aGlzLmRpc2NvdmVyeUNvbXBsZXRlKCkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubWV0YWRhdGEucHJlZmVycmVkX2NhY2hlO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRocm93IENsaWVudEF1dGhFcnJvci5jcmVhdGVFbmRwb2ludERpc2NvdmVyeUluY29tcGxldGVFcnJvcihcIkRpc2NvdmVyeSBpbmNvbXBsZXRlLlwiKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBwcm92aWRlZCBob3N0IGlzIGFuIGFsaWFzIG9mIHRoaXMgYXV0aG9yaXR5IGluc3RhbmNlXHJcbiAgICAgKiBAcGFyYW0gaG9zdCBcclxuICAgICAqL1xyXG4gICAgaXNBbGlhcyhob3N0OiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5tZXRhZGF0YS5hbGlhc2VzLmluZGV4T2YoaG9zdCkgPiAtMTtcclxuICAgIH1cclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IEF1dGhvcml0eSB9IGZyb20gXCIuL0F1dGhvcml0eVwiO1xyXG5pbXBvcnQgeyBDbGllbnRDb25maWd1cmF0aW9uRXJyb3IgfSBmcm9tIFwiLi4vZXJyb3IvQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yXCI7XHJcbmltcG9ydCB7IElOZXR3b3JrTW9kdWxlIH0gZnJvbSBcIi4uL25ldHdvcmsvSU5ldHdvcmtNb2R1bGVcIjtcclxuaW1wb3J0IHsgU3RyaW5nVXRpbHMgfSBmcm9tIFwiLi4vdXRpbHMvU3RyaW5nVXRpbHNcIjtcclxuaW1wb3J0IHsgQ2xpZW50QXV0aEVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL0NsaWVudEF1dGhFcnJvclwiO1xyXG5pbXBvcnQgeyBJQ2FjaGVNYW5hZ2VyIH0gZnJvbSBcIi4uL2NhY2hlL2ludGVyZmFjZS9JQ2FjaGVNYW5hZ2VyXCI7XHJcbmltcG9ydCB7IEF1dGhvcml0eU9wdGlvbnMgfSBmcm9tIFwiLi9BdXRob3JpdHlPcHRpb25zXCI7XHJcblxyXG5leHBvcnQgY2xhc3MgQXV0aG9yaXR5RmFjdG9yeSB7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGUgYW4gYXV0aG9yaXR5IG9iamVjdCBvZiB0aGUgY29ycmVjdCB0eXBlIGJhc2VkIG9uIHRoZSB1cmxcclxuICAgICAqIFBlcmZvcm1zIGJhc2ljIGF1dGhvcml0eSB2YWxpZGF0aW9uIC0gY2hlY2tzIHRvIHNlZSBpZiB0aGUgYXV0aG9yaXR5IGlzIG9mIGEgdmFsaWQgdHlwZSAoaS5lLiBhYWQsIGIyYywgYWRmcylcclxuICAgICAqXHJcbiAgICAgKiBBbHNvIHBlcmZvcm1zIGVuZHBvaW50IGRpc2NvdmVyeS5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gYXV0aG9yaXR5VXJpXHJcbiAgICAgKiBAcGFyYW0gbmV0d29ya0NsaWVudFxyXG4gICAgICogQHBhcmFtIHByb3RvY29sTW9kZVxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgYXN5bmMgY3JlYXRlRGlzY292ZXJlZEluc3RhbmNlKGF1dGhvcml0eVVyaTogc3RyaW5nLCBuZXR3b3JrQ2xpZW50OiBJTmV0d29ya01vZHVsZSwgY2FjaGVNYW5hZ2VyOiBJQ2FjaGVNYW5hZ2VyLCBhdXRob3JpdHlPcHRpb25zOiBBdXRob3JpdHlPcHRpb25zKTogUHJvbWlzZTxBdXRob3JpdHk+IHtcclxuICAgICAgICAvLyBJbml0aWFsaXplIGF1dGhvcml0eSBhbmQgcGVyZm9ybSBkaXNjb3ZlcnkgZW5kcG9pbnQgY2hlY2suXHJcbiAgICAgICAgY29uc3QgYWNxdWlyZVRva2VuQXV0aG9yaXR5OiBBdXRob3JpdHkgPSBBdXRob3JpdHlGYWN0b3J5LmNyZWF0ZUluc3RhbmNlKGF1dGhvcml0eVVyaSwgbmV0d29ya0NsaWVudCwgY2FjaGVNYW5hZ2VyLCBhdXRob3JpdHlPcHRpb25zKTtcclxuXHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgYXdhaXQgYWNxdWlyZVRva2VuQXV0aG9yaXR5LnJlc29sdmVFbmRwb2ludHNBc3luYygpO1xyXG4gICAgICAgICAgICByZXR1cm4gYWNxdWlyZVRva2VuQXV0aG9yaXR5O1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50QXV0aEVycm9yLmNyZWF0ZUVuZHBvaW50RGlzY292ZXJ5SW5jb21wbGV0ZUVycm9yKGUpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZSBhbiBhdXRob3JpdHkgb2JqZWN0IG9mIHRoZSBjb3JyZWN0IHR5cGUgYmFzZWQgb24gdGhlIHVybFxyXG4gICAgICogUGVyZm9ybXMgYmFzaWMgYXV0aG9yaXR5IHZhbGlkYXRpb24gLSBjaGVja3MgdG8gc2VlIGlmIHRoZSBhdXRob3JpdHkgaXMgb2YgYSB2YWxpZCB0eXBlIChpLmUuIGFhZCwgYjJjLCBhZGZzKVxyXG4gICAgICpcclxuICAgICAqIERvZXMgbm90IHBlcmZvcm0gZW5kcG9pbnQgZGlzY292ZXJ5LlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSBhdXRob3JpdHlVcmxcclxuICAgICAqIEBwYXJhbSBuZXR3b3JrSW50ZXJmYWNlXHJcbiAgICAgKiBAcGFyYW0gcHJvdG9jb2xNb2RlXHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBjcmVhdGVJbnN0YW5jZShhdXRob3JpdHlVcmw6IHN0cmluZywgbmV0d29ya0ludGVyZmFjZTogSU5ldHdvcmtNb2R1bGUsIGNhY2hlTWFuYWdlcjogSUNhY2hlTWFuYWdlciwgYXV0aG9yaXR5T3B0aW9uczogQXV0aG9yaXR5T3B0aW9ucyk6IEF1dGhvcml0eSB7XHJcbiAgICAgICAgLy8gVGhyb3cgZXJyb3IgaWYgYXV0aG9yaXR5IHVybCBpcyBlbXB0eVxyXG4gICAgICAgIGlmIChTdHJpbmdVdGlscy5pc0VtcHR5KGF1dGhvcml0eVVybCkpIHtcclxuICAgICAgICAgICAgdGhyb3cgQ2xpZW50Q29uZmlndXJhdGlvbkVycm9yLmNyZWF0ZVVybEVtcHR5RXJyb3IoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBuZXcgQXV0aG9yaXR5KGF1dGhvcml0eVVybCwgbmV0d29ya0ludGVyZmFjZSwgY2FjaGVNYW5hZ2VyLCBhdXRob3JpdHlPcHRpb25zKTtcclxuICAgIH1cclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IFNFUlZFUl9URUxFTV9DT05TVEFOVFMgfSBmcm9tIFwiLi4vLi4vdXRpbHMvQ29uc3RhbnRzXCI7XHJcblxyXG5leHBvcnQgY2xhc3MgU2VydmVyVGVsZW1ldHJ5RW50aXR5IHtcclxuICAgIGZhaWxlZFJlcXVlc3RzOiBBcnJheTxzdHJpbmd8bnVtYmVyPjtcclxuICAgIGVycm9yczogc3RyaW5nW107XHJcbiAgICBjYWNoZUhpdHM6IG51bWJlcjtcclxuXHJcbiAgICBjb25zdHJ1Y3RvcigpIHtcclxuICAgICAgICB0aGlzLmZhaWxlZFJlcXVlc3RzID0gW107XHJcbiAgICAgICAgdGhpcy5lcnJvcnMgPSBbXTtcclxuICAgICAgICB0aGlzLmNhY2hlSGl0cyA9IDA7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiB2YWxpZGF0ZXMgaWYgYSBnaXZlbiBjYWNoZSBlbnRyeSBpcyBcIlRlbGVtZXRyeVwiLCBwYXJzZXMgPGtleSx2YWx1ZT5cclxuICAgICAqIEBwYXJhbSBrZXlcclxuICAgICAqIEBwYXJhbSBlbnRpdHlcclxuICAgICAqL1xyXG4gICAgc3RhdGljIGlzU2VydmVyVGVsZW1ldHJ5RW50aXR5KGtleTogc3RyaW5nLCBlbnRpdHk/OiBvYmplY3QpOiBib29sZWFuIHtcclxuXHJcbiAgICAgICAgY29uc3QgdmFsaWRhdGVLZXk6IGJvb2xlYW4gPSBrZXkuaW5kZXhPZihTRVJWRVJfVEVMRU1fQ09OU1RBTlRTLkNBQ0hFX0tFWSkgPT09IDA7XHJcbiAgICAgICAgbGV0IHZhbGlkYXRlRW50aXR5OiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgaWYgKGVudGl0eSkge1xyXG4gICAgICAgICAgICB2YWxpZGF0ZUVudGl0eSA9XHJcbiAgICAgICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJmYWlsZWRSZXF1ZXN0c1wiKSAmJlxyXG4gICAgICAgICAgICAgICAgZW50aXR5Lmhhc093blByb3BlcnR5KFwiZXJyb3JzXCIpICYmXHJcbiAgICAgICAgICAgICAgICBlbnRpdHkuaGFzT3duUHJvcGVydHkoXCJjYWNoZUhpdHNcIik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdmFsaWRhdGVLZXkgJiYgdmFsaWRhdGVFbnRpdHk7XHJcbiAgICB9XHJcbn1cclxuIiwiLypcclxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cclxuICovXHJcblxyXG5pbXBvcnQgeyBUaHJvdHRsaW5nQ29uc3RhbnRzIH0gZnJvbSBcIi4uLy4uL3V0aWxzL0NvbnN0YW50c1wiO1xyXG5cclxuZXhwb3J0IGNsYXNzIFRocm90dGxpbmdFbnRpdHkge1xyXG4gICAgLy8gVW5peC10aW1lIHZhbHVlIHJlcHJlc2VudGluZyB0aGUgZXhwaXJhdGlvbiBvZiB0aGUgdGhyb3R0bGVcclxuICAgIHRocm90dGxlVGltZTogbnVtYmVyO1xyXG4gICAgLy8gSW5mb3JtYXRpb24gcHJvdmlkZWQgYnkgdGhlIHNlcnZlclxyXG4gICAgZXJyb3I/OiBzdHJpbmc7XHJcbiAgICBlcnJvckNvZGVzPzogQXJyYXk8c3RyaW5nPjtcclxuICAgIGVycm9yTWVzc2FnZT86IHN0cmluZztcclxuICAgIHN1YkVycm9yPzogc3RyaW5nO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogdmFsaWRhdGVzIGlmIGEgZ2l2ZW4gY2FjaGUgZW50cnkgaXMgXCJUaHJvdHRsaW5nXCIsIHBhcnNlcyA8a2V5LHZhbHVlPlxyXG4gICAgICogQHBhcmFtIGtleVxyXG4gICAgICogQHBhcmFtIGVudGl0eVxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgaXNUaHJvdHRsaW5nRW50aXR5KGtleTogc3RyaW5nLCBlbnRpdHk/OiBvYmplY3QpOiBib29sZWFuIHtcclxuICAgICAgICBcclxuICAgICAgICBsZXQgdmFsaWRhdGVLZXk6IGJvb2xlYW4gPSBmYWxzZTtcclxuICAgICAgICBpZiAoa2V5KSB7XHJcbiAgICAgICAgICAgIHZhbGlkYXRlS2V5ID0ga2V5LmluZGV4T2YoVGhyb3R0bGluZ0NvbnN0YW50cy5USFJPVFRMSU5HX1BSRUZJWCkgPT09IDA7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIFxyXG4gICAgICAgIGxldCB2YWxpZGF0ZUVudGl0eTogYm9vbGVhbiA9IHRydWU7XHJcbiAgICAgICAgaWYgKGVudGl0eSkge1xyXG4gICAgICAgICAgICB2YWxpZGF0ZUVudGl0eSA9IGVudGl0eS5oYXNPd25Qcm9wZXJ0eShcInRocm90dGxlVGltZVwiKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB2YWxpZGF0ZUtleSAmJiB2YWxpZGF0ZUVudGl0eTtcclxuICAgIH1cclxufVxyXG4iLCIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbmltcG9ydCB7IEF1dGhFcnJvciB9IGZyb20gXCIuLi9lcnJvci9BdXRoRXJyb3JcIjtcclxuaW1wb3J0IHsgTmV0d29ya1Jlc3BvbnNlIH0gZnJvbSBcIi4vTmV0d29ya01hbmFnZXJcIjtcclxuXHJcbi8qKlxyXG4gKiBPcHRpb25zIGFsbG93ZWQgYnkgbmV0d29yayByZXF1ZXN0IEFQSXMuXHJcbiAqL1xyXG5leHBvcnQgdHlwZSBOZXR3b3JrUmVxdWVzdE9wdGlvbnMgPSB7XHJcbiAgICBoZWFkZXJzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPixcclxuICAgIGJvZHk/OiBzdHJpbmc7XHJcbn07XHJcblxyXG4vKipcclxuICogQ2xpZW50IG5ldHdvcmsgaW50ZXJmYWNlIHRvIHNlbmQgYmFja2VuZCByZXF1ZXN0cy5cclxuICogQGludGVyZmFjZVxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBJTmV0d29ya01vZHVsZSB7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJbnRlcmZhY2UgZnVuY3Rpb24gZm9yIGFzeW5jIG5ldHdvcmsgXCJHRVRcIiByZXF1ZXN0cy4gQmFzZWQgb24gdGhlIEZldGNoIHN0YW5kYXJkOiBodHRwczovL2ZldGNoLnNwZWMud2hhdHdnLm9yZy9cclxuICAgICAqIEBwYXJhbSB1cmxcclxuICAgICAqIEBwYXJhbSByZXF1ZXN0UGFyYW1zXHJcbiAgICAgKiBAcGFyYW0gZW5hYmxlQ2FjaGluZ1xyXG4gICAgICovXHJcbiAgICBzZW5kR2V0UmVxdWVzdEFzeW5jPFQ+KHVybDogc3RyaW5nLCBvcHRpb25zPzogTmV0d29ya1JlcXVlc3RPcHRpb25zKTogUHJvbWlzZTxOZXR3b3JrUmVzcG9uc2U8VD4+O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW50ZXJmYWNlIGZ1bmN0aW9uIGZvciBhc3luYyBuZXR3b3JrIFwiUE9TVFwiIHJlcXVlc3RzLiBCYXNlZCBvbiB0aGUgRmV0Y2ggc3RhbmRhcmQ6IGh0dHBzOi8vZmV0Y2guc3BlYy53aGF0d2cub3JnL1xyXG4gICAgICogQHBhcmFtIHVybFxyXG4gICAgICogQHBhcmFtIHJlcXVlc3RQYXJhbXNcclxuICAgICAqIEBwYXJhbSBlbmFibGVDYWNoaW5nXHJcbiAgICAgKi9cclxuICAgIHNlbmRQb3N0UmVxdWVzdEFzeW5jPFQ+KHVybDogc3RyaW5nLCBvcHRpb25zPzogTmV0d29ya1JlcXVlc3RPcHRpb25zKTogUHJvbWlzZTxOZXR3b3JrUmVzcG9uc2U8VD4+O1xyXG59XHJcblxyXG5leHBvcnQgY29uc3QgU3R1YmJlZE5ldHdvcmtNb2R1bGU6IElOZXR3b3JrTW9kdWxlID0ge1xyXG4gICAgc2VuZEdldFJlcXVlc3RBc3luYzogKCkgPT4ge1xyXG4gICAgICAgIGNvbnN0IG5vdEltcGxFcnIgPSBcIk5ldHdvcmsgaW50ZXJmYWNlIC0gc2VuZEdldFJlcXVlc3RBc3luYygpIGhhcyBub3QgYmVlbiBpbXBsZW1lbnRlZCBmb3IgdGhlIE5ldHdvcmsgaW50ZXJmYWNlLlwiO1xyXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChBdXRoRXJyb3IuY3JlYXRlVW5leHBlY3RlZEVycm9yKG5vdEltcGxFcnIpKTtcclxuICAgIH0sXHJcbiAgICBzZW5kUG9zdFJlcXVlc3RBc3luYzogKCkgPT4ge1xyXG4gICAgICAgIGNvbnN0IG5vdEltcGxFcnIgPSBcIk5ldHdvcmsgaW50ZXJmYWNlIC0gc2VuZFBvc3RSZXF1ZXN0QXN5bmMoKSBoYXMgbm90IGJlZW4gaW1wbGVtZW50ZWQgZm9yIHRoZSBOZXR3b3JrIGludGVyZmFjZS5cIjtcclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoQXV0aEVycm9yLmNyZWF0ZVVuZXhwZWN0ZWRFcnJvcihub3RJbXBsRXJyKSk7XHJcbiAgICB9XHJcbn07XHJcbiIsIi8qXHJcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgU0VSVkVSX1RFTEVNX0NPTlNUQU5UUywgU2VwYXJhdG9ycywgQ29uc3RhbnRzIH0gZnJvbSBcIi4uLy4uL3V0aWxzL0NvbnN0YW50c1wiO1xyXG5pbXBvcnQgeyBDYWNoZU1hbmFnZXIgfSBmcm9tIFwiLi4vLi4vY2FjaGUvQ2FjaGVNYW5hZ2VyXCI7XHJcbmltcG9ydCB7IEF1dGhFcnJvciB9IGZyb20gXCIuLi8uLi9lcnJvci9BdXRoRXJyb3JcIjtcclxuaW1wb3J0IHsgU2VydmVyVGVsZW1ldHJ5UmVxdWVzdCB9IGZyb20gXCIuL1NlcnZlclRlbGVtZXRyeVJlcXVlc3RcIjtcclxuaW1wb3J0IHsgU2VydmVyVGVsZW1ldHJ5RW50aXR5IH0gZnJvbSBcIi4uLy4uL2NhY2hlL2VudGl0aWVzL1NlcnZlclRlbGVtZXRyeUVudGl0eVwiO1xyXG5pbXBvcnQgeyBTdHJpbmdVdGlscyB9IGZyb20gXCIuLi8uLi91dGlscy9TdHJpbmdVdGlsc1wiO1xyXG5cclxuZXhwb3J0IGNsYXNzIFNlcnZlclRlbGVtZXRyeU1hbmFnZXIge1xyXG4gICAgcHJpdmF0ZSBjYWNoZU1hbmFnZXI6IENhY2hlTWFuYWdlcjtcclxuICAgIHByaXZhdGUgYXBpSWQ6IG51bWJlcjtcclxuICAgIHByaXZhdGUgY29ycmVsYXRpb25JZDogc3RyaW5nO1xyXG4gICAgcHJpdmF0ZSBmb3JjZVJlZnJlc2g6IGJvb2xlYW47XHJcbiAgICBwcml2YXRlIHRlbGVtZXRyeUNhY2hlS2V5OiBzdHJpbmc7XHJcbiAgICBwcml2YXRlIHdyYXBwZXJTS1U6IFN0cmluZztcclxuICAgIHByaXZhdGUgd3JhcHBlclZlcjogU3RyaW5nO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKHRlbGVtZXRyeVJlcXVlc3Q6IFNlcnZlclRlbGVtZXRyeVJlcXVlc3QsIGNhY2hlTWFuYWdlcjogQ2FjaGVNYW5hZ2VyKSB7XHJcbiAgICAgICAgdGhpcy5jYWNoZU1hbmFnZXIgPSBjYWNoZU1hbmFnZXI7XHJcbiAgICAgICAgdGhpcy5hcGlJZCA9IHRlbGVtZXRyeVJlcXVlc3QuYXBpSWQ7XHJcbiAgICAgICAgdGhpcy5jb3JyZWxhdGlvbklkID0gdGVsZW1ldHJ5UmVxdWVzdC5jb3JyZWxhdGlvbklkO1xyXG4gICAgICAgIHRoaXMuZm9yY2VSZWZyZXNoID0gdGVsZW1ldHJ5UmVxdWVzdC5mb3JjZVJlZnJlc2ggfHwgZmFsc2U7XHJcbiAgICAgICAgdGhpcy53cmFwcGVyU0tVID0gdGVsZW1ldHJ5UmVxdWVzdC53cmFwcGVyU0tVIHx8IENvbnN0YW50cy5FTVBUWV9TVFJJTkc7XHJcbiAgICAgICAgdGhpcy53cmFwcGVyVmVyID0gdGVsZW1ldHJ5UmVxdWVzdC53cmFwcGVyVmVyIHx8IENvbnN0YW50cy5FTVBUWV9TVFJJTkc7XHJcblxyXG4gICAgICAgIHRoaXMudGVsZW1ldHJ5Q2FjaGVLZXkgPSBTRVJWRVJfVEVMRU1fQ09OU1RBTlRTLkNBQ0hFX0tFWSArIFNlcGFyYXRvcnMuQ0FDSEVfS0VZX1NFUEFSQVRPUiArIHRlbGVtZXRyeVJlcXVlc3QuY2xpZW50SWQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBUEkgdG8gYWRkIE1TRVIgVGVsZW1ldHJ5IHRvIHJlcXVlc3RcclxuICAgICAqL1xyXG4gICAgZ2VuZXJhdGVDdXJyZW50UmVxdWVzdEhlYWRlclZhbHVlKCk6IHN0cmluZyB7XHJcbiAgICAgICAgY29uc3QgZm9yY2VSZWZyZXNoSW50ID0gdGhpcy5mb3JjZVJlZnJlc2ggPyAxIDogMDtcclxuICAgICAgICBjb25zdCByZXF1ZXN0ID0gYCR7dGhpcy5hcGlJZH0ke1NFUlZFUl9URUxFTV9DT05TVEFOVFMuVkFMVUVfU0VQQVJBVE9SfSR7Zm9yY2VSZWZyZXNoSW50fWA7XHJcbiAgICAgICAgY29uc3QgcGxhdGZvcm1GaWVsZHMgPSBbdGhpcy53cmFwcGVyU0tVLCB0aGlzLndyYXBwZXJWZXJdLmpvaW4oU0VSVkVSX1RFTEVNX0NPTlNUQU5UUy5WQUxVRV9TRVBBUkFUT1IpO1xyXG5cclxuICAgICAgICByZXR1cm4gW1NFUlZFUl9URUxFTV9DT05TVEFOVFMuU0NIRU1BX1ZFUlNJT04sIHJlcXVlc3QsIHBsYXRmb3JtRmllbGRzXS5qb2luKFNFUlZFUl9URUxFTV9DT05TVEFOVFMuQ0FURUdPUllfU0VQQVJBVE9SKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEFQSSB0byBhZGQgTVNFUiBUZWxlbWV0cnkgZm9yIHRoZSBsYXN0IGZhaWxlZCByZXF1ZXN0XHJcbiAgICAgKi9cclxuICAgIGdlbmVyYXRlTGFzdFJlcXVlc3RIZWFkZXJWYWx1ZSgpOiBzdHJpbmcge1xyXG4gICAgICAgIGNvbnN0IGxhc3RSZXF1ZXN0cyA9IHRoaXMuZ2V0TGFzdFJlcXVlc3RzKCk7XHJcblxyXG4gICAgICAgIGNvbnN0IG1heEVycm9ycyA9IFNlcnZlclRlbGVtZXRyeU1hbmFnZXIubWF4RXJyb3JzVG9TZW5kKGxhc3RSZXF1ZXN0cyk7XHJcbiAgICAgICAgY29uc3QgZmFpbGVkUmVxdWVzdHMgPSBsYXN0UmVxdWVzdHMuZmFpbGVkUmVxdWVzdHMuc2xpY2UoMCwgMiptYXhFcnJvcnMpLmpvaW4oU0VSVkVSX1RFTEVNX0NPTlNUQU5UUy5WQUxVRV9TRVBBUkFUT1IpO1xyXG4gICAgICAgIGNvbnN0IGVycm9ycyA9IGxhc3RSZXF1ZXN0cy5lcnJvcnMuc2xpY2UoMCwgbWF4RXJyb3JzKS5qb2luKFNFUlZFUl9URUxFTV9DT05TVEFOVFMuVkFMVUVfU0VQQVJBVE9SKTtcclxuICAgICAgICBjb25zdCBlcnJvckNvdW50ID0gbGFzdFJlcXVlc3RzLmVycm9ycy5sZW5ndGg7XHJcblxyXG4gICAgICAgIC8vIEluZGljYXRlIHdoZXRoZXIgdGhpcyBoZWFkZXIgY29udGFpbnMgYWxsIGRhdGEgb3IgcGFydGlhbCBkYXRhXHJcbiAgICAgICAgY29uc3Qgb3ZlcmZsb3cgPSBtYXhFcnJvcnMgPCBlcnJvckNvdW50ID8gU0VSVkVSX1RFTEVNX0NPTlNUQU5UUy5PVkVSRkxPV19UUlVFIDogU0VSVkVSX1RFTEVNX0NPTlNUQU5UUy5PVkVSRkxPV19GQUxTRTtcclxuICAgICAgICBjb25zdCBwbGF0Zm9ybUZpZWxkcyA9IFtlcnJvckNvdW50LCBvdmVyZmxvd10uam9pbihTRVJWRVJfVEVMRU1fQ09OU1RBTlRTLlZBTFVFX1NFUEFSQVRPUik7XHJcblxyXG4gICAgICAgIHJldHVybiBbU0VSVkVSX1RFTEVNX0NPTlNUQU5UUy5TQ0hFTUFfVkVSU0lPTiwgbGFzdFJlcXVlc3RzLmNhY2hlSGl0cywgZmFpbGVkUmVxdWVzdHMsIGVycm9ycywgcGxhdGZvcm1GaWVsZHNdLmpvaW4oU0VSVkVSX1RFTEVNX0NPTlNUQU5UUy5DQVRFR09SWV9TRVBBUkFUT1IpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQVBJIHRvIGNhY2hlIHRva2VuIGZhaWx1cmVzIGZvciBNU0VSIGRhdGEgY2FwdHVyZVxyXG4gICAgICogQHBhcmFtIGVycm9yXHJcbiAgICAgKi9cclxuICAgIGNhY2hlRmFpbGVkUmVxdWVzdChlcnJvcjogQXV0aEVycm9yKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3QgbGFzdFJlcXVlc3RzID0gdGhpcy5nZXRMYXN0UmVxdWVzdHMoKTtcclxuICAgICAgICBsYXN0UmVxdWVzdHMuZmFpbGVkUmVxdWVzdHMucHVzaCh0aGlzLmFwaUlkLCB0aGlzLmNvcnJlbGF0aW9uSWQpO1xyXG5cclxuICAgICAgICBpZiAoIVN0cmluZ1V0aWxzLmlzRW1wdHkoZXJyb3Iuc3ViRXJyb3IpKSB7XHJcbiAgICAgICAgICAgIGxhc3RSZXF1ZXN0cy5lcnJvcnMucHVzaChlcnJvci5zdWJFcnJvcik7XHJcbiAgICAgICAgfSBlbHNlIGlmICghU3RyaW5nVXRpbHMuaXNFbXB0eShlcnJvci5lcnJvckNvZGUpKSB7XHJcbiAgICAgICAgICAgIGxhc3RSZXF1ZXN0cy5lcnJvcnMucHVzaChlcnJvci5lcnJvckNvZGUpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoISFlcnJvciAmJiBlcnJvci50b1N0cmluZygpKSB7XHJcbiAgICAgICAgICAgIGxhc3RSZXF1ZXN0cy5lcnJvcnMucHVzaChlcnJvci50b1N0cmluZygpKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBsYXN0UmVxdWVzdHMuZXJyb3JzLnB1c2goU0VSVkVSX1RFTEVNX0NPTlNUQU5UUy5VTktOT1dOX0VSUk9SKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuY2FjaGVNYW5hZ2VyLnNldFNlcnZlclRlbGVtZXRyeSh0aGlzLnRlbGVtZXRyeUNhY2hlS2V5LCBsYXN0UmVxdWVzdHMpO1xyXG5cclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBVcGRhdGUgc2VydmVyIHRlbGVtZXRyeSBjYWNoZSBlbnRyeSBieSBpbmNyZW1lbnRpbmcgY2FjaGUgaGl0IGNvdW50ZXJcclxuICAgICAqL1xyXG4gICAgaW5jcmVtZW50Q2FjaGVIaXRzKCk6IG51bWJlciB7XHJcbiAgICAgICAgY29uc3QgbGFzdFJlcXVlc3RzID0gdGhpcy5nZXRMYXN0UmVxdWVzdHMoKTtcclxuICAgICAgICBsYXN0UmVxdWVzdHMuY2FjaGVIaXRzICs9IDE7XHJcblxyXG4gICAgICAgIHRoaXMuY2FjaGVNYW5hZ2VyLnNldFNlcnZlclRlbGVtZXRyeSh0aGlzLnRlbGVtZXRyeUNhY2hlS2V5LCBsYXN0UmVxdWVzdHMpO1xyXG4gICAgICAgIHJldHVybiBsYXN0UmVxdWVzdHMuY2FjaGVIaXRzO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0IHRoZSBzZXJ2ZXIgdGVsZW1ldHJ5IGVudGl0eSBmcm9tIGNhY2hlIG9yIGluaXRpYWxpemUgYSBuZXcgb25lXHJcbiAgICAgKi9cclxuICAgIGdldExhc3RSZXF1ZXN0cygpOiBTZXJ2ZXJUZWxlbWV0cnlFbnRpdHkge1xyXG4gICAgICAgIGNvbnN0IGluaXRpYWxWYWx1ZTogU2VydmVyVGVsZW1ldHJ5RW50aXR5ID0gbmV3IFNlcnZlclRlbGVtZXRyeUVudGl0eSgpO1xyXG4gICAgICAgIGNvbnN0IGxhc3RSZXF1ZXN0cyA9IHRoaXMuY2FjaGVNYW5hZ2VyLmdldFNlcnZlclRlbGVtZXRyeSh0aGlzLnRlbGVtZXRyeUNhY2hlS2V5KSBhcyBTZXJ2ZXJUZWxlbWV0cnlFbnRpdHk7XHJcblxyXG4gICAgICAgIHJldHVybiBsYXN0UmVxdWVzdHMgfHwgaW5pdGlhbFZhbHVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVtb3ZlIHNlcnZlciB0ZWxlbWV0cnkgY2FjaGUgZW50cnlcclxuICAgICAqL1xyXG4gICAgY2xlYXJUZWxlbWV0cnlDYWNoZSgpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBsYXN0UmVxdWVzdHMgPSB0aGlzLmdldExhc3RSZXF1ZXN0cygpO1xyXG4gICAgICAgIGNvbnN0IG51bUVycm9yc0ZsdXNoZWQgPSBTZXJ2ZXJUZWxlbWV0cnlNYW5hZ2VyLm1heEVycm9yc1RvU2VuZChsYXN0UmVxdWVzdHMpO1xyXG4gICAgICAgIGNvbnN0IGVycm9yQ291bnQgPSBsYXN0UmVxdWVzdHMuZXJyb3JzLmxlbmd0aDtcclxuICAgICAgICBpZiAobnVtRXJyb3JzRmx1c2hlZCA9PT0gZXJyb3JDb3VudCkge1xyXG4gICAgICAgICAgICAvLyBBbGwgZXJyb3JzIHdlcmUgc2VudCBvbiBsYXN0IHJlcXVlc3QsIGNsZWFyIFRlbGVtZXRyeSBjYWNoZVxyXG4gICAgICAgICAgICB0aGlzLmNhY2hlTWFuYWdlci5yZW1vdmVJdGVtKHRoaXMudGVsZW1ldHJ5Q2FjaGVLZXkpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIC8vIFBhcnRpYWwgZGF0YSB3YXMgZmx1c2hlZCB0byBzZXJ2ZXIsIGNvbnN0cnVjdCBhIG5ldyB0ZWxlbWV0cnkgY2FjaGUgaXRlbSB3aXRoIGVycm9ycyB0aGF0IHdlcmUgbm90IGZsdXNoZWRcclxuICAgICAgICAgICAgY29uc3Qgc2VydmVyVGVsZW1FbnRpdHkgPSBuZXcgU2VydmVyVGVsZW1ldHJ5RW50aXR5KCk7XHJcbiAgICAgICAgICAgIHNlcnZlclRlbGVtRW50aXR5LmZhaWxlZFJlcXVlc3RzID0gbGFzdFJlcXVlc3RzLmZhaWxlZFJlcXVlc3RzLnNsaWNlKG51bUVycm9yc0ZsdXNoZWQqMik7IC8vIGZhaWxlZFJlcXVlc3RzIGNvbnRhaW5zIDIgaXRlbXMgZm9yIGVhY2ggZXJyb3JcclxuICAgICAgICAgICAgc2VydmVyVGVsZW1FbnRpdHkuZXJyb3JzID0gbGFzdFJlcXVlc3RzLmVycm9ycy5zbGljZShudW1FcnJvcnNGbHVzaGVkKTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuY2FjaGVNYW5hZ2VyLnNldFNlcnZlclRlbGVtZXRyeSh0aGlzLnRlbGVtZXRyeUNhY2hlS2V5LCBzZXJ2ZXJUZWxlbUVudGl0eSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyB0aGUgbWF4aW11bSBudW1iZXIgb2YgZXJyb3JzIHRoYXQgY2FuIGJlIGZsdXNoZWQgdG8gdGhlIHNlcnZlciBpbiB0aGUgbmV4dCBuZXR3b3JrIHJlcXVlc3RcclxuICAgICAqIEBwYXJhbSBzZXJ2ZXJUZWxlbWV0cnlFbnRpdHlcclxuICAgICAqL1xyXG4gICAgc3RhdGljIG1heEVycm9yc1RvU2VuZChzZXJ2ZXJUZWxlbWV0cnlFbnRpdHk6IFNlcnZlclRlbGVtZXRyeUVudGl0eSk6IG51bWJlciB7XHJcbiAgICAgICAgbGV0IGk7XHJcbiAgICAgICAgbGV0IG1heEVycm9ycyA9IDA7XHJcbiAgICAgICAgbGV0IGRhdGFTaXplID0gMDtcclxuICAgICAgICBjb25zdCBlcnJvckNvdW50ID0gc2VydmVyVGVsZW1ldHJ5RW50aXR5LmVycm9ycy5sZW5ndGg7XHJcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGVycm9yQ291bnQ7IGkrKykge1xyXG4gICAgICAgICAgICAvLyBmYWlsZWRSZXF1ZXN0cyBwYXJhbWV0ZXIgY29udGFpbnMgcGFpcnMgb2YgYXBpSWQgYW5kIGNvcnJlbGF0aW9uSWQsIG11bHRpcGx5IGluZGV4IGJ5IDIgdG8gcHJlc2VydmUgcGFpcnNcclxuICAgICAgICAgICAgY29uc3QgYXBpSWQgPSBzZXJ2ZXJUZWxlbWV0cnlFbnRpdHkuZmFpbGVkUmVxdWVzdHNbMippXSB8fCBDb25zdGFudHMuRU1QVFlfU1RSSU5HO1xyXG4gICAgICAgICAgICBjb25zdCBjb3JyZWxhdGlvbklkID0gc2VydmVyVGVsZW1ldHJ5RW50aXR5LmZhaWxlZFJlcXVlc3RzWzIqaSArIDFdIHx8IENvbnN0YW50cy5FTVBUWV9TVFJJTkc7XHJcbiAgICAgICAgICAgIGNvbnN0IGVycm9yQ29kZSA9IHNlcnZlclRlbGVtZXRyeUVudGl0eS5lcnJvcnNbaV0gfHwgQ29uc3RhbnRzLkVNUFRZX1NUUklORztcclxuXHJcbiAgICAgICAgICAgIC8vIENvdW50IG51bWJlciBvZiBjaGFyYWN0ZXJzIHRoYXQgd291bGQgYmUgYWRkZWQgdG8gaGVhZGVyLCBlYWNoIGNoYXJhY3RlciBpcyAxIGJ5dGUuIEFkZCAzIGF0IHRoZSBlbmQgdG8gYWNjb3VudCBmb3Igc2VwYXJhdG9yc1xyXG4gICAgICAgICAgICBkYXRhU2l6ZSArPSBhcGlJZC50b1N0cmluZygpLmxlbmd0aCArIGNvcnJlbGF0aW9uSWQudG9TdHJpbmcoKS5sZW5ndGggKyBlcnJvckNvZGUubGVuZ3RoICsgMztcclxuXHJcbiAgICAgICAgICAgIGlmIChkYXRhU2l6ZSA8IFNFUlZFUl9URUxFTV9DT05TVEFOVFMuTUFYX0hFQURFUl9CWVRFUykge1xyXG4gICAgICAgICAgICAgICAgLy8gQWRkaW5nIHRoaXMgZW50cnkgdG8gdGhlIGhlYWRlciB3b3VsZCBzdGlsbCBrZWVwIGhlYWRlciBzaXplIGJlbG93IHRoZSBsaW1pdFxyXG4gICAgICAgICAgICAgICAgbWF4RXJyb3JzICs9IDE7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIG1heEVycm9ycztcclxuICAgIH1cclxufVxyXG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBOzs7O0lBS2EsU0FBUyxHQUFHO0lBQ3JCLFlBQVksRUFBRSxTQUFTO0lBQ3ZCLEdBQUcsRUFBRSxnQkFBZ0I7O0lBRXJCLFlBQVksRUFBRSxNQUFNOztJQUVwQixpQkFBaUIsRUFBRSwyQ0FBMkM7SUFDOUQsc0JBQXNCLEVBQUUsMkJBQTJCOztJQUVuRCxJQUFJLEVBQUUsTUFBTTs7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
|