keycloak-angular
Version:
Easy Keycloak setup for Angular applications
277 lines • 46.4 kB
JavaScript
import * as tslib_1 from "tslib";
import { Injectable } from '@angular/core';
import { HttpHeaders } from '@angular/common/http';
import { Observable, Subject } from 'rxjs';
import * as Keycloak_ from 'keycloak-js';
export const Keycloak = Keycloak_;
import { KeycloakEventType } from '../interfaces/keycloak-event';
export class KeycloakService {
constructor() {
this._keycloakEvents$ = new Subject();
}
bindsKeycloakEvents() {
this._instance.onAuthError = (errorData => {
this._keycloakEvents$.next({
args: errorData,
type: KeycloakEventType.OnAuthError
});
});
this._instance.onAuthLogout = (() => {
this._keycloakEvents$.next({ type: KeycloakEventType.OnAuthLogout });
});
this._instance.onAuthRefreshSuccess = (() => {
this._keycloakEvents$.next({
type: KeycloakEventType.OnAuthRefreshSuccess
});
});
this._instance.onAuthRefreshError = (() => {
this._keycloakEvents$.next({
type: KeycloakEventType.OnAuthRefreshError
});
});
this._instance.onAuthSuccess = (() => {
this._keycloakEvents$.next({ type: KeycloakEventType.OnAuthSuccess });
});
this._instance.onTokenExpired = (() => {
this._keycloakEvents$.next({
type: KeycloakEventType.OnTokenExpired
});
});
this._instance.onReady = (authenticated => {
this._keycloakEvents$.next({
args: authenticated,
type: KeycloakEventType.OnReady
});
});
}
loadExcludedUrls(bearerExcludedUrls) {
const excludedUrls = [];
for (const item of bearerExcludedUrls) {
let excludedUrl;
if (typeof item === 'string') {
excludedUrl = { urlPattern: new RegExp(item, 'i'), httpMethods: [] };
}
else {
excludedUrl = {
urlPattern: new RegExp(item.url, 'i'),
httpMethods: item.httpMethods
};
}
excludedUrls.push(excludedUrl);
}
return excludedUrls;
}
initServiceValues({ enableBearerInterceptor = true, loadUserProfileAtStartUp = true, bearerExcludedUrls = [], authorizationHeaderName = 'Authorization', bearerPrefix = 'bearer', initOptions }) {
this._enableBearerInterceptor = enableBearerInterceptor;
this._loadUserProfileAtStartUp = loadUserProfileAtStartUp;
this._authorizationHeaderName = authorizationHeaderName;
this._bearerPrefix = bearerPrefix.trim().concat(' ');
this._excludedUrls = this.loadExcludedUrls(bearerExcludedUrls);
this._silentRefresh = initOptions ? initOptions.flow === 'implicit' : false;
}
init(options = {}) {
return new Promise(((resolve, reject) => {
this.initServiceValues(options);
const { config, initOptions } = options;
this._instance = Keycloak(config);
this.bindsKeycloakEvents();
this._instance
.init(initOptions)
.success(((authenticated) => tslib_1.__awaiter(this, void 0, void 0, function* () {
if (authenticated && this._loadUserProfileAtStartUp) {
yield this.loadUserProfile();
}
resolve(authenticated);
})))
.error((kcError => {
let msg = 'An error happened during Keycloak initialization.';
if (kcError) {
let { error, error_description } = kcError;
msg = msg.concat(`\nAdapter error details:\nError: ${error}\nDescription: ${error_description}`);
}
reject(msg);
}));
}));
}
login(options = {}) {
return new Promise(((resolve, reject) => {
this._instance
.login(options)
.success((() => tslib_1.__awaiter(this, void 0, void 0, function* () {
if (this._loadUserProfileAtStartUp) {
yield this.loadUserProfile();
}
resolve();
})))
.error((() => reject(`An error happened during the login.`)));
}));
}
logout(redirectUri) {
return new Promise(((resolve, reject) => {
const options = {
redirectUri
};
this._instance
.logout(options)
.success((() => {
this._userProfile = undefined;
resolve();
}))
.error((() => reject('An error happened during logout.')));
}));
}
register(options = { action: 'register' }) {
return new Promise(((resolve, reject) => {
this._instance
.register(options)
.success((() => {
resolve();
}))
.error((() => reject('An error happened during the register execution.')));
}));
}
isUserInRole(role, resource) {
let hasRole;
hasRole = this._instance.hasResourceRole(role, resource);
if (!hasRole) {
hasRole = this._instance.hasRealmRole(role);
}
return hasRole;
}
getUserRoles(allRoles = true) {
let roles = [];
if (this._instance.resourceAccess) {
for (const key in this._instance.resourceAccess) {
if (this._instance.resourceAccess.hasOwnProperty(key)) {
const resourceAccess = this._instance.resourceAccess[key];
const clientRoles = resourceAccess['roles'] || [];
roles = roles.concat(clientRoles);
}
}
}
if (allRoles && this._instance.realmAccess) {
let realmRoles = this._instance.realmAccess['roles'] || [];
roles.push(...realmRoles);
}
return roles;
}
isLoggedIn() {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
try {
if (!this._instance.authenticated) {
return false;
}
yield this.updateToken(20);
return true;
}
catch (error) {
return false;
}
});
}
isTokenExpired(minValidity = 0) {
return this._instance.isTokenExpired(minValidity);
}
updateToken(minValidity = 5) {
return new Promise(((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
if (this._silentRefresh) {
if (this.isTokenExpired()) {
reject('Failed to refresh the token, or the session is expired');
}
else {
resolve(true);
}
return;
}
if (!this._instance) {
reject('Keycloak Angular library is not initialized.');
return;
}
this._instance
.updateToken(minValidity)
.success((refreshed => {
resolve(refreshed);
}))
.error((() => reject('Failed to refresh the token, or the session is expired')));
})));
}
loadUserProfile(forceReload = false) {
return new Promise(((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
if (this._userProfile && !forceReload) {
resolve(this._userProfile);
return;
}
if (!this._instance.authenticated) {
reject('The user profile was not loaded as the user is not logged in.');
return;
}
this._instance
.loadUserProfile()
.success((result => {
this._userProfile = ((result));
resolve(this._userProfile);
}))
.error((() => reject('The user profile could not be loaded.')));
})));
}
getToken() {
return new Promise(((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
try {
yield this.updateToken(10);
resolve(this._instance.token);
}
catch (error) {
this.login();
}
})));
}
getUsername() {
if (!this._userProfile) {
throw new Error('User not logged in or user profile was not loaded.');
}
return ((this._userProfile.username));
}
clearToken() {
this._instance.clearToken();
}
addTokenToHeader(headers = new HttpHeaders()) {
return Observable.create(((observer) => tslib_1.__awaiter(this, void 0, void 0, function* () {
try {
const token = yield this.getToken();
headers = headers.set(this._authorizationHeaderName, this._bearerPrefix + token);
observer.next(headers);
observer.complete();
}
catch (error) {
observer.error(error);
}
})));
}
getKeycloakInstance() {
return this._instance;
}
get excludedUrls() {
return this._excludedUrls;
}
get enableBearerInterceptor() {
return this._enableBearerInterceptor;
}
get keycloakEvents$() {
return this._keycloakEvents$;
}
}
KeycloakService.decorators = [
{ type: Injectable }
];
if (false) {
KeycloakService.prototype._instance;
KeycloakService.prototype._userProfile;
KeycloakService.prototype._enableBearerInterceptor;
KeycloakService.prototype._silentRefresh;
KeycloakService.prototype._loadUserProfileAtStartUp;
KeycloakService.prototype._bearerPrefix;
KeycloakService.prototype._authorizationHeaderName;
KeycloakService.prototype._excludedUrls;
KeycloakService.prototype._keycloakEvents$;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5Y2xvYWsuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2tleWNsb2FrLWFuZ3VsYXIvIiwic291cmNlcyI6WyJsaWIvY29yZS9zZXJ2aWNlcy9rZXljbG9hay5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFRQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUVuRCxPQUFPLEVBQUUsVUFBVSxFQUFZLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUdyRCxPQUFPLEtBQUssU0FBUyxNQUFNLGFBQWEsQ0FBQztBQUN6QyxNQUFNLE9BQU8sUUFBUSxHQUFHLFNBQVM7QUFHakMsT0FBTyxFQUFpQixpQkFBaUIsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBVWhGLE1BQU0sT0FBTyxlQUFlO0lBRDVCO1FBdUNVLHFCQUFnQixHQUEyQixJQUFJLE9BQU8sRUFBaUIsQ0FBQztJQTJmbEYsQ0FBQztJQWxmUyxtQkFBbUI7UUFDekIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLElBQUcsU0FBUyxDQUFDLEVBQUU7WUFDdkMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQztnQkFDekIsSUFBSSxFQUFFLFNBQVM7Z0JBQ2YsSUFBSSxFQUFFLGlCQUFpQixDQUFDLFdBQVc7YUFDcEMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFBLENBQUM7UUFFRixJQUFJLENBQUMsU0FBUyxDQUFDLFlBQVksSUFBRyxHQUFHLEVBQUU7WUFDakMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxpQkFBaUIsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZFLENBQUMsQ0FBQSxDQUFDO1FBRUYsSUFBSSxDQUFDLFNBQVMsQ0FBQyxvQkFBb0IsSUFBRyxHQUFHLEVBQUU7WUFDekMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQztnQkFDekIsSUFBSSxFQUFFLGlCQUFpQixDQUFDLG9CQUFvQjthQUM3QyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUEsQ0FBQztRQUVGLElBQUksQ0FBQyxTQUFTLENBQUMsa0JBQWtCLElBQUcsR0FBRyxFQUFFO1lBQ3ZDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUM7Z0JBQ3pCLElBQUksRUFBRSxpQkFBaUIsQ0FBQyxrQkFBa0I7YUFDM0MsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFBLENBQUM7UUFFRixJQUFJLENBQUMsU0FBUyxDQUFDLGFBQWEsSUFBRyxHQUFHLEVBQUU7WUFDbEMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxpQkFBaUIsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDO1FBQ3hFLENBQUMsQ0FBQSxDQUFDO1FBRUYsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLElBQUcsR0FBRyxFQUFFO1lBQ25DLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUM7Z0JBQ3pCLElBQUksRUFBRSxpQkFBaUIsQ0FBQyxjQUFjO2FBQ3ZDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQSxDQUFDO1FBRUYsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLElBQUcsYUFBYSxDQUFDLEVBQUU7WUFDdkMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQztnQkFDekIsSUFBSSxFQUFFLGFBQWE7Z0JBQ25CLElBQUksRUFBRSxpQkFBaUIsQ0FBQyxPQUFPO2FBQ2hDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQSxDQUFDO0lBQ0osQ0FBQztJQVNPLGdCQUFnQixDQUFDLGtCQUE0QztjQUM3RCxZQUFZLEdBQXVCLEVBQUU7UUFDM0MsS0FBSyxNQUFNLElBQUksSUFBSSxrQkFBa0IsRUFBRTtnQkFDakMsV0FBNkI7WUFDakMsSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRLEVBQUU7Z0JBQzVCLFdBQVcsR0FBRyxFQUFFLFVBQVUsRUFBRSxJQUFJLE1BQU0sQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLEVBQUUsV0FBVyxFQUFFLEVBQUUsRUFBRSxDQUFDO2FBQ3RFO2lCQUFNO2dCQUNMLFdBQVcsR0FBRztvQkFDWixVQUFVLEVBQUUsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUM7b0JBQ3JDLFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVztpQkFDOUIsQ0FBQzthQUNIO1lBQ0QsWUFBWSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztTQUNoQztRQUNELE9BQU8sWUFBWSxDQUFDO0lBQ3RCLENBQUM7SUFPTyxpQkFBaUIsQ0FBQyxFQUN4Qix1QkFBdUIsR0FBRyxJQUFJLEVBQzlCLHdCQUF3QixHQUFHLElBQUksRUFDL0Isa0JBQWtCLEdBQUcsRUFBRSxFQUN2Qix1QkFBdUIsR0FBRyxlQUFlLEVBQ3pDLFlBQVksR0FBRyxRQUFRLEVBQ3ZCLFdBQVcsRUFDSztRQUNoQixJQUFJLENBQUMsd0JBQXdCLEdBQUcsdUJBQXVCLENBQUM7UUFDeEQsSUFBSSxDQUFDLHlCQUF5QixHQUFHLHdCQUF3QixDQUFDO1FBQzFELElBQUksQ0FBQyx3QkFBd0IsR0FBRyx1QkFBdUIsQ0FBQztRQUN4RCxJQUFJLENBQUMsYUFBYSxHQUFHLFlBQVksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDckQsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUMvRCxJQUFJLENBQUMsY0FBYyxHQUFHLFdBQVcsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLElBQUksS0FBSyxVQUFVLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztJQUM5RSxDQUFDO0lBc0NELElBQUksQ0FBQyxVQUEyQixFQUFFO1FBQ2hDLE9BQU8sSUFBSSxPQUFPLEVBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDckMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxDQUFDO2tCQUMxQixFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsR0FBRyxPQUFPO1lBRXZDLElBQUksQ0FBQyxTQUFTLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2xDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBQzNCLElBQUksQ0FBQyxTQUFTO2lCQUNYLElBQUksQ0FBQyxXQUFXLENBQUM7aUJBQ2pCLE9BQU8sRUFBQyxDQUFNLGFBQWEsRUFBQyxFQUFFO2dCQUM3QixJQUFJLGFBQWEsSUFBSSxJQUFJLENBQUMseUJBQXlCLEVBQUU7b0JBQ25ELE1BQU0sSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO2lCQUM5QjtnQkFDRCxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDekIsQ0FBQyxDQUFBLEVBQUM7aUJBQ0QsS0FBSyxFQUFDLE9BQU8sQ0FBQyxFQUFFO29CQUNYLEdBQUcsR0FBRyxtREFBbUQ7Z0JBQzdELElBQUksT0FBTyxFQUFFO3dCQUNQLEVBQUUsS0FBSyxFQUFFLGlCQUFpQixFQUFFLEdBQUcsT0FBTztvQkFDMUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQ2Qsb0NBQW9DLEtBQUssa0JBQWtCLGlCQUFpQixFQUFFLENBQy9FLENBQUM7aUJBQ0g7Z0JBQ0QsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2QsQ0FBQyxFQUFDLENBQUM7UUFDUCxDQUFDLEVBQUMsQ0FBQztJQUNMLENBQUM7SUF1QkQsS0FBSyxDQUFDLFVBQXlDLEVBQUU7UUFDL0MsT0FBTyxJQUFJLE9BQU8sRUFBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNyQyxJQUFJLENBQUMsU0FBUztpQkFDWCxLQUFLLENBQUMsT0FBTyxDQUFDO2lCQUNkLE9BQU8sRUFBQyxHQUFTLEVBQUU7Z0JBQ2xCLElBQUksSUFBSSxDQUFDLHlCQUF5QixFQUFFO29CQUNsQyxNQUFNLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztpQkFDOUI7Z0JBQ0QsT0FBTyxFQUFFLENBQUM7WUFDWixDQUFDLENBQUEsRUFBQztpQkFDRCxLQUFLLEVBQUMsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLHFDQUFxQyxDQUFDLEVBQUMsQ0FBQztRQUNoRSxDQUFDLEVBQUMsQ0FBQztJQUNMLENBQUM7SUFVRCxNQUFNLENBQUMsV0FBb0I7UUFDekIsT0FBTyxJQUFJLE9BQU8sRUFBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtrQkFDL0IsT0FBTyxHQUFRO2dCQUNuQixXQUFXO2FBQ1o7WUFFRCxJQUFJLENBQUMsU0FBUztpQkFDWCxNQUFNLENBQUMsT0FBTyxDQUFDO2lCQUNmLE9BQU8sRUFBQyxHQUFHLEVBQUU7Z0JBQ1osSUFBSSxDQUFDLFlBQVksR0FBRyxTQUFTLENBQUM7Z0JBQzlCLE9BQU8sRUFBRSxDQUFDO1lBQ1osQ0FBQyxFQUFDO2lCQUNELEtBQUssRUFBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsa0NBQWtDLENBQUMsRUFBQyxDQUFDO1FBQzdELENBQUMsRUFBQyxDQUFDO0lBQ0wsQ0FBQztJQVlELFFBQVEsQ0FBQyxVQUF5QyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUU7UUFDdEUsT0FBTyxJQUFJLE9BQU8sRUFBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNyQyxJQUFJLENBQUMsU0FBUztpQkFDWCxRQUFRLENBQUMsT0FBTyxDQUFDO2lCQUNqQixPQUFPLEVBQUMsR0FBRyxFQUFFO2dCQUNaLE9BQU8sRUFBRSxDQUFDO1lBQ1osQ0FBQyxFQUFDO2lCQUNELEtBQUssRUFBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsa0RBQWtELENBQUMsRUFBQyxDQUFDO1FBQzdFLENBQUMsRUFBQyxDQUFDO0lBQ0wsQ0FBQztJQWFELFlBQVksQ0FBQyxJQUFZLEVBQUUsUUFBaUI7WUFDdEMsT0FBZ0I7UUFDcEIsT0FBTyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsZUFBZSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQztRQUN6RCxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ1osT0FBTyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQzdDO1FBQ0QsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQVlELFlBQVksQ0FBQyxXQUFvQixJQUFJO1lBQy9CLEtBQUssR0FBYSxFQUFFO1FBQ3hCLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUU7WUFDakMsS0FBSyxNQUFNLEdBQUcsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRTtnQkFDL0MsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLEVBQUU7MEJBQy9DLGNBQWMsR0FBUSxJQUFJLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUM7MEJBQ3hELFdBQVcsR0FBRyxjQUFjLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRTtvQkFDakQsS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7aUJBQ25DO2FBQ0Y7U0FDRjtRQUNELElBQUksUUFBUSxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFO2dCQUN0QyxVQUFVLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRTtZQUMxRCxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsVUFBVSxDQUFDLENBQUM7U0FDM0I7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFRSyxVQUFVOztZQUNkLElBQUk7Z0JBQ0YsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsYUFBYSxFQUFFO29CQUNqQyxPQUFPLEtBQUssQ0FBQztpQkFDZDtnQkFDRCxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQzNCLE9BQU8sSUFBSSxDQUFDO2FBQ2I7WUFBQyxPQUFPLEtBQUssRUFBRTtnQkFDZCxPQUFPLEtBQUssQ0FBQzthQUNkO1FBQ0gsQ0FBQztLQUFBO0lBV0QsY0FBYyxDQUFDLGNBQXNCLENBQUM7UUFDcEMsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBYUQsV0FBVyxDQUFDLGNBQXNCLENBQUM7UUFDakMsT0FBTyxJQUFJLE9BQU8sRUFBQyxDQUFPLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUczQyxJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUU7Z0JBQ3ZCLElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRSxFQUFFO29CQUN6QixNQUFNLENBQUMsd0RBQXdELENBQUMsQ0FBQztpQkFDbEU7cUJBQU07b0JBQ0wsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO2lCQUNmO2dCQUNELE9BQU87YUFDUjtZQUVELElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFO2dCQUNuQixNQUFNLENBQUMsOENBQThDLENBQUMsQ0FBQztnQkFDdkQsT0FBTzthQUNSO1lBRUQsSUFBSSxDQUFDLFNBQVM7aUJBQ1gsV0FBVyxDQUFDLFdBQVcsQ0FBQztpQkFDeEIsT0FBTyxFQUFDLFNBQVMsQ0FBQyxFQUFFO2dCQUNuQixPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDckIsQ0FBQyxFQUFDO2lCQUNELEtBQUssRUFBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsd0RBQXdELENBQUMsRUFBQyxDQUFDO1FBQ25GLENBQUMsQ0FBQSxFQUFDLENBQUM7SUFDTCxDQUFDO0lBWUQsZUFBZSxDQUFDLGNBQXVCLEtBQUs7UUFDMUMsT0FBTyxJQUFJLE9BQU8sRUFBQyxDQUFPLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUMzQyxJQUFJLElBQUksQ0FBQyxZQUFZLElBQUksQ0FBQyxXQUFXLEVBQUU7Z0JBQ3JDLE9BQU8sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7Z0JBQzNCLE9BQU87YUFDUjtZQUVELElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLGFBQWEsRUFBRTtnQkFDakMsTUFBTSxDQUFDLCtEQUErRCxDQUFDLENBQUM7Z0JBQ3hFLE9BQU87YUFDUjtZQUVELElBQUksQ0FBQyxTQUFTO2lCQUNYLGVBQWUsRUFBRTtpQkFDakIsT0FBTyxFQUFDLE1BQU0sQ0FBQyxFQUFFO2dCQUNoQixJQUFJLENBQUMsWUFBWSxHQUFHLEVBQUEsTUFBTSxFQUE0QixDQUFDO2dCQUN2RCxPQUFPLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQzdCLENBQUMsRUFBQztpQkFDRCxLQUFLLEVBQUMsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLHVDQUF1QyxDQUFDLEVBQUMsQ0FBQztRQUNsRSxDQUFDLENBQUEsRUFBQyxDQUFDO0lBQ0wsQ0FBQztJQVNELFFBQVE7UUFDTixPQUFPLElBQUksT0FBTyxFQUFDLENBQU8sT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQzNDLElBQUk7Z0JBQ0YsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUMzQixPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUMvQjtZQUFDLE9BQU8sS0FBSyxFQUFFO2dCQUNkLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQzthQUNkO1FBQ0gsQ0FBQyxDQUFBLEVBQUMsQ0FBQztJQUNMLENBQUM7SUFRRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUU7WUFDdEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO1NBQ3ZFO1FBRUQsT0FBTyxFQUFBLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFDLENBQUM7SUFDckMsQ0FBQztJQU9ELFVBQVU7UUFDUixJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQzlCLENBQUM7SUFZRCxnQkFBZ0IsQ0FBQyxVQUF1QixJQUFJLFdBQVcsRUFBRTtRQUN2RCxPQUFPLFVBQVUsQ0FBQyxNQUFNLEVBQUMsQ0FBTyxRQUF1QixFQUFFLEVBQUU7WUFDekQsSUFBSTtzQkFDSSxLQUFLLEdBQVcsTUFBTSxJQUFJLENBQUMsUUFBUSxFQUFFO2dCQUMzQyxPQUFPLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsd0JBQXdCLEVBQUUsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUMsQ0FBQztnQkFDakYsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDdkIsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDO2FBQ3JCO1lBQUMsT0FBTyxLQUFLLEVBQUU7Z0JBQ2QsUUFBUSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUN2QjtRQUNILENBQUMsQ0FBQSxFQUFDLENBQUM7SUFDTCxDQUFDO0lBU0QsbUJBQW1CO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUN4QixDQUFDO0lBU0QsSUFBSSxZQUFZO1FBQ2QsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDO0lBQzVCLENBQUM7SUFRRCxJQUFJLHVCQUF1QjtRQUN6QixPQUFPLElBQUksQ0FBQyx3QkFBd0IsQ0FBQztJQUN2QyxDQUFDO0lBcUJELElBQUksZUFBZTtRQUNqQixPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztJQUMvQixDQUFDOzs7WUFqaUJGLFVBQVU7OztJQUtULG9DQUE2QztJQUk3Qyx1Q0FBK0M7SUFJL0MsbURBQTBDO0lBSzFDLHlDQUFnQztJQUtoQyxvREFBMkM7SUFJM0Msd0NBQThCO0lBSTlCLG1EQUF5QztJQUl6Qyx3Q0FBMEM7SUFJMUMsMkNBQWdGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IE1hdXJpY2lvIEdlbWVsbGkgVmlnb2xvIGFuZCBjb250cmlidXRvcnMuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYSBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2dpdGh1Yi5jb20vbWF1cmljaW92aWdvbG8va2V5Y2xvYWstYW5ndWxhci9MSUNFTlNFXG4gKi9cblxuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSHR0cEhlYWRlcnMgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5cbmltcG9ydCB7IE9ic2VydmFibGUsIE9ic2VydmVyLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5cbi8vIFdvcmthcm91bmQgZm9yIHJvbGx1cCBsaWJyYXJ5IGJlaGF2aW91ciwgYXMgcG9pbnRlZCBvdXQgb24gaXNzdWUgIzEyNjcgKGh0dHBzOi8vZ2l0aHViLmNvbS9yb2xsdXAvcm9sbHVwL2lzc3Vlcy8xMjY3KS5cbmltcG9ydCAqIGFzIEtleWNsb2FrXyBmcm9tICdrZXljbG9hay1qcyc7XG5leHBvcnQgY29uc3QgS2V5Y2xvYWsgPSBLZXljbG9ha187XG5cbmltcG9ydCB7IEV4Y2x1ZGVkVXJsLCBFeGNsdWRlZFVybFJlZ2V4LCBLZXljbG9ha09wdGlvbnMgfSBmcm9tICcuLi9pbnRlcmZhY2VzL2tleWNsb2FrLW9wdGlvbnMnO1xuaW1wb3J0IHsgS2V5Y2xvYWtFdmVudCwgS2V5Y2xvYWtFdmVudFR5cGUgfSBmcm9tICcuLi9pbnRlcmZhY2VzL2tleWNsb2FrLWV2ZW50JztcblxuLyoqXG4gKiBTZXJ2aWNlIHRvIGV4cG9zZSBleGlzdGVudCBtZXRob2RzIGZyb20gdGhlIEtleWNsb2FrIEpTIGFkYXB0ZXIsIGFkZGluZyBuZXdcbiAqIGZ1bmN0aW9uYWxpdGllcyB0byBpbXByb3ZlIHRoZSB1c2Ugb2Yga2V5Y2xvYWsgaW4gQW5ndWxhciB2ID4gNC4zIGFwcGxpY2F0aW9ucy5cbiAqXG4gKiBUaGlzIGNsYXNzIHNob3VsZCBiZSBpbmplY3RlZCBpbiB0aGUgYXBwbGljYXRpb24gYm9vdHN0cmFwLCBzbyB0aGUgc2FtZSBpbnN0YW5jZSB3aWxsIGJlIHVzZWRcbiAqIGFsb25nIHRoZSB3ZWIgYXBwbGljYXRpb24uXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBLZXljbG9ha1NlcnZpY2Uge1xuICAvKipcbiAgICogS2V5Y2xvYWstanMgaW5zdGFuY2UuXG4gICAqL1xuICBwcml2YXRlIF9pbnN0YW5jZTogS2V5Y2xvYWsuS2V5Y2xvYWtJbnN0YW5jZTtcbiAgLyoqXG4gICAqIFVzZXIgcHJvZmlsZSBhcyBLZXljbG9ha1Byb2ZpbGUgaW50ZXJmYWNlLlxuICAgKi9cbiAgcHJpdmF0ZSBfdXNlclByb2ZpbGU6IEtleWNsb2FrLktleWNsb2FrUHJvZmlsZTtcbiAgLyoqXG4gICAqIEZsYWcgdG8gaW5kaWNhdGUgaWYgdGhlIGJlYXJlciB3aWxsIG5vdCBiZSBhZGRlZCB0byB0aGUgYXV0aG9yaXphdGlvbiBoZWFkZXIuXG4gICAqL1xuICBwcml2YXRlIF9lbmFibGVCZWFyZXJJbnRlcmNlcHRvcjogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFdoZW4gdGhlIGltcGxpY2l0IGZsb3cgaXMgY2hvb3NlbiB0aGVyZSBtdXN0IGV4aXN0IGEgc2lsZW50UmVmcmVzaCwgYXMgdGhlcmUgaXNcbiAgICogbm8gcmVmcmVzaCB0b2tlbi5cbiAgICovXG4gIHByaXZhdGUgX3NpbGVudFJlZnJlc2g6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgdGhhdCB0aGUgdXNlciBwcm9maWxlIHNob3VsZCBiZSBsb2FkZWQgYXQgdGhlIGtleWNsb2FrIGluaXRpYWxpemF0aW9uLFxuICAgKiBqdXN0IGFmdGVyIHRoZSBsb2dpbi5cbiAgICovXG4gIHByaXZhdGUgX2xvYWRVc2VyUHJvZmlsZUF0U3RhcnRVcDogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFRoZSBiZWFyZXIgcHJlZml4IHRoYXQgd2lsbCBiZSBhcHBlbmRlZCB0byB0aGUgQXV0aG9yaXphdGlvbiBIZWFkZXIuXG4gICAqL1xuICBwcml2YXRlIF9iZWFyZXJQcmVmaXg6IHN0cmluZztcbiAgLyoqXG4gICAqIFZhbHVlIHRoYXQgd2lsbCBiZSB1c2VkIGFzIHRoZSBBdXRob3JpemF0aW9uIEh0dHAgSGVhZGVyIG5hbWUuXG4gICAqL1xuICBwcml2YXRlIF9hdXRob3JpemF0aW9uSGVhZGVyTmFtZTogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGV4Y2x1ZGVkIHVybHMgcGF0dGVybnMgdGhhdCBtdXN0IHNraXAgdGhlIEtleWNsb2FrQmVhcmVySW50ZXJjZXB0b3IuXG4gICAqL1xuICBwcml2YXRlIF9leGNsdWRlZFVybHM6IEV4Y2x1ZGVkVXJsUmVnZXhbXTtcbiAgLyoqXG4gICAqIE9ic2VydmVyIGZvciB0aGUga2V5Y2xvYWsgZXZlbnRzXG4gICAqL1xuICBwcml2YXRlIF9rZXljbG9ha0V2ZW50cyQ6IFN1YmplY3Q8S2V5Y2xvYWtFdmVudD4gPSBuZXcgU3ViamVjdDxLZXljbG9ha0V2ZW50PigpO1xuXG4gIC8qKlxuICAgKiBCaW5kcyB0aGUga2V5Y2xvYWstanMgZXZlbnRzIHRvIHRoZSBrZXljbG9ha0V2ZW50cyBTdWJqZWN0XG4gICAqIHdoaWNoIGlzIGEgZ29vZCB3YXkgdG8gbW9uaXRvciBmb3IgY2hhbmdlcywgaWYgbmVlZGVkLlxuICAgKlxuICAgKiBUaGUga2V5Y2xvYWtFdmVudHMgcmV0dXJucyB0aGUga2V5Y2xvYWstanMgZXZlbnQgdHlwZSBhbmQgYW55XG4gICAqIGFyZ3VtZW50IGlmIHRoZSBzb3VyY2UgZnVuY3Rpb24gcHJvdmlkZXMgYW55LlxuICAgKi9cbiAgcHJpdmF0ZSBiaW5kc0tleWNsb2FrRXZlbnRzKCk6IHZvaWQge1xuICAgIHRoaXMuX2luc3RhbmNlLm9uQXV0aEVycm9yID0gZXJyb3JEYXRhID0+IHtcbiAgICAgIHRoaXMuX2tleWNsb2FrRXZlbnRzJC5uZXh0KHtcbiAgICAgICAgYXJnczogZXJyb3JEYXRhLFxuICAgICAgICB0eXBlOiBLZXljbG9ha0V2ZW50VHlwZS5PbkF1dGhFcnJvclxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHRoaXMuX2luc3RhbmNlLm9uQXV0aExvZ291dCA9ICgpID0+IHtcbiAgICAgIHRoaXMuX2tleWNsb2FrRXZlbnRzJC5uZXh0KHsgdHlwZTogS2V5Y2xvYWtFdmVudFR5cGUuT25BdXRoTG9nb3V0IH0pO1xuICAgIH07XG5cbiAgICB0aGlzLl9pbnN0YW5jZS5vbkF1dGhSZWZyZXNoU3VjY2VzcyA9ICgpID0+IHtcbiAgICAgIHRoaXMuX2tleWNsb2FrRXZlbnRzJC5uZXh0KHtcbiAgICAgICAgdHlwZTogS2V5Y2xvYWtFdmVudFR5cGUuT25BdXRoUmVmcmVzaFN1Y2Nlc3NcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICB0aGlzLl9pbnN0YW5jZS5vbkF1dGhSZWZyZXNoRXJyb3IgPSAoKSA9PiB7XG4gICAgICB0aGlzLl9rZXljbG9ha0V2ZW50cyQubmV4dCh7XG4gICAgICAgIHR5cGU6IEtleWNsb2FrRXZlbnRUeXBlLk9uQXV0aFJlZnJlc2hFcnJvclxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHRoaXMuX2luc3RhbmNlLm9uQXV0aFN1Y2Nlc3MgPSAoKSA9PiB7XG4gICAgICB0aGlzLl9rZXljbG9ha0V2ZW50cyQubmV4dCh7IHR5cGU6IEtleWNsb2FrRXZlbnRUeXBlLk9uQXV0aFN1Y2Nlc3MgfSk7XG4gICAgfTtcblxuICAgIHRoaXMuX2luc3RhbmNlLm9uVG9rZW5FeHBpcmVkID0gKCkgPT4ge1xuICAgICAgdGhpcy5fa2V5Y2xvYWtFdmVudHMkLm5leHQoe1xuICAgICAgICB0eXBlOiBLZXljbG9ha0V2ZW50VHlwZS5PblRva2VuRXhwaXJlZFxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIHRoaXMuX2luc3RhbmNlLm9uUmVhZHkgPSBhdXRoZW50aWNhdGVkID0+IHtcbiAgICAgIHRoaXMuX2tleWNsb2FrRXZlbnRzJC5uZXh0KHtcbiAgICAgICAgYXJnczogYXV0aGVudGljYXRlZCxcbiAgICAgICAgdHlwZTogS2V5Y2xvYWtFdmVudFR5cGUuT25SZWFkeVxuICAgICAgfSk7XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkcyBhbGwgYmVhcmVyRXhjbHVkZWRVcmwgY29udGVudCBpbiBhIHVuaWZvcm0gdHlwZTogRXhjbHVkZWRVcmwsXG4gICAqIHNvIGl0IGJlY29tZXMgZWFzaWVyIHRvIGhhbmRsZS5cbiAgICpcbiAgICogQHBhcmFtIGJlYXJlckV4Y2x1ZGVkVXJscyBhcnJheSBvZiBzdHJpbmdzIG9yIEV4Y2x1ZGVkVXJsIHRoYXQgaW5jbHVkZXNcbiAgICogdGhlIHVybCBhbmQgSHR0cE1ldGhvZC5cbiAgICovXG4gIHByaXZhdGUgbG9hZEV4Y2x1ZGVkVXJscyhiZWFyZXJFeGNsdWRlZFVybHM6IChzdHJpbmcgfCBFeGNsdWRlZFVybClbXSk6IEV4Y2x1ZGVkVXJsUmVnZXhbXSB7XG4gICAgY29uc3QgZXhjbHVkZWRVcmxzOiBFeGNsdWRlZFVybFJlZ2V4W10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgYmVhcmVyRXhjbHVkZWRVcmxzKSB7XG4gICAgICBsZXQgZXhjbHVkZWRVcmw6IEV4Y2x1ZGVkVXJsUmVnZXg7XG4gICAgICBpZiAodHlwZW9mIGl0ZW0gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGV4Y2x1ZGVkVXJsID0geyB1cmxQYXR0ZXJuOiBuZXcgUmVnRXhwKGl0ZW0sICdpJyksIGh0dHBNZXRob2RzOiBbXSB9O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhjbHVkZWRVcmwgPSB7XG4gICAgICAgICAgdXJsUGF0dGVybjogbmV3IFJlZ0V4cChpdGVtLnVybCwgJ2knKSxcbiAgICAgICAgICBodHRwTWV0aG9kczogaXRlbS5odHRwTWV0aG9kc1xuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgZXhjbHVkZWRVcmxzLnB1c2goZXhjbHVkZWRVcmwpO1xuICAgIH1cbiAgICByZXR1cm4gZXhjbHVkZWRVcmxzO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgdGhlIGNsYXNzIHZhbHVlcyBpbml0aWFsaXphdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIG9wdGlvbnNcbiAgICovXG4gIHByaXZhdGUgaW5pdFNlcnZpY2VWYWx1ZXMoe1xuICAgIGVuYWJsZUJlYXJlckludGVyY2VwdG9yID0gdHJ1ZSxcbiAgICBsb2FkVXNlclByb2ZpbGVBdFN0YXJ0VXAgPSB0cnVlLFxuICAgIGJlYXJlckV4Y2x1ZGVkVXJscyA9IFtdLFxuICAgIGF1dGhvcml6YXRpb25IZWFkZXJOYW1lID0gJ0F1dGhvcml6YXRpb24nLFxuICAgIGJlYXJlclByZWZpeCA9ICdiZWFyZXInLFxuICAgIGluaXRPcHRpb25zXG4gIH06IEtleWNsb2FrT3B0aW9ucyk6IHZvaWQge1xuICAgIHRoaXMuX2VuYWJsZUJlYXJlckludGVyY2VwdG9yID0gZW5hYmxlQmVhcmVySW50ZXJjZXB0b3I7XG4gICAgdGhpcy5fbG9hZFVzZXJQcm9maWxlQXRTdGFydFVwID0gbG9hZFVzZXJQcm9maWxlQXRTdGFydFVwO1xuICAgIHRoaXMuX2F1dGhvcml6YXRpb25IZWFkZXJOYW1lID0gYXV0aG9yaXphdGlvbkhlYWRlck5hbWU7XG4gICAgdGhpcy5fYmVhcmVyUHJlZml4ID0gYmVhcmVyUHJlZml4LnRyaW0oKS5jb25jYXQoJyAnKTtcbiAgICB0aGlzLl9leGNsdWRlZFVybHMgPSB0aGlzLmxvYWRFeGNsdWRlZFVybHMoYmVhcmVyRXhjbHVkZWRVcmxzKTtcbiAgICB0aGlzLl9zaWxlbnRSZWZyZXNoID0gaW5pdE9wdGlvbnMgPyBpbml0T3B0aW9ucy5mbG93ID09PSAnaW1wbGljaXQnIDogZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogS2V5Y2xvYWsgaW5pdGlhbGl6YXRpb24uIEl0IHNob3VsZCBiZSBjYWxsZWQgdG8gaW5pdGlhbGl6ZSB0aGUgYWRhcHRlci5cbiAgICogT3B0aW9ucyBpcyBhIG9iamVjdCB3aXRoIDIgbWFpbiBwYXJhbWV0ZXJzOiBjb25maWcgYW5kIGluaXRPcHRpb25zLiBUaGUgZmlyc3Qgb25lXG4gICAqIHdpbGwgYmUgdXNlZCB0byBjcmVhdGUgdGhlIEtleWNsb2FrIGluc3RhbmNlLiBUaGUgc2Vjb25kIG9uZSBhcmUgb3B0aW9ucyB0byBpbml0aWFsaXplIHRoZVxuICAgKiBrZXljbG9hayBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIG9wdGlvbnNcbiAgICogQ29uZmlnOiBtYXkgYmUgYSBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBrZXljbG9hayBVUkkgb3IgYW4gb2JqZWN0IHdpdGggdGhlXG4gICAqIGZvbGxvd2luZyBjb250ZW50OlxuICAgKiAtIHVybDogS2V5Y2xvYWsganNvbiBVUkxcbiAgICogLSByZWFsbTogcmVhbG0gbmFtZVxuICAgKiAtIGNsaWVudElkOiBjbGllbnQgaWRcbiAgICpcbiAgICogaW5pdE9wdGlvbnM6XG4gICAqIE9wdGlvbnMgdG8gaW5pdGlhbGl6ZSB0aGUgS2V5Y2xvYWsgYWRhcHRlciwgbWF0Y2hlcyB0aGUgb3B0aW9ucyBhcyBwcm92aWRlZCBieSBLZXljbG9hayBpdHNlbGYuXG4gICAqXG4gICAqIGVuYWJsZUJlYXJlckludGVyY2VwdG9yOlxuICAgKiBGbGFnIHRvIGluZGljYXRlIGlmIHRoZSBiZWFyZXIgd2lsbCBhZGRlZCB0byB0aGUgYXV0aG9yaXphdGlvbiBoZWFkZXIuXG4gICAqXG4gICAqIGxvYWRVc2VyUHJvZmlsZUluU3RhcnRVcDpcbiAgICogSW5kaWNhdGVzIHRoYXQgdGhlIHVzZXIgcHJvZmlsZSBzaG91bGQgYmUgbG9hZGVkIGF0IHRoZSBrZXljbG9hayBpbml0aWFsaXphdGlvbixcbiAgICoganVzdCBhZnRlciB0aGUgbG9naW4uXG4gICAqXG4gICAqIGJlYXJlckV4Y2x1ZGVkVXJsczpcbiAgICogU3RyaW5nIEFycmF5IHRvIGV4Y2x1ZGUgdGhlIHVybHMgdGhhdCBzaG91bGQgbm90IGhhdmUgdGhlIEF1dGhvcml6YXRpb24gSGVhZGVyIGF1dG9tYXRpY2FsbHlcbiAgICogYWRkZWQuXG4gICAqXG4gICAqIGF1dGhvcml6YXRpb25IZWFkZXJOYW1lOlxuICAgKiBUaGlzIHZhbHVlIHdpbGwgYmUgdXNlZCBhcyB0aGUgQXV0aG9yaXphdGlvbiBIdHRwIEhlYWRlciBuYW1lLlxuICAgKlxuICAgKiBiZWFyZXJQcmVmaXg6XG4gICAqIFRoaXMgdmFsdWUgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgQXV0aG9yaXphdGlvbiBIdHRwIEhlYWRlciBwYXJhbS5cbiAgICpcbiAgICogQHJldHVybnNcbiAgICogQSBQcm9taXNlIHdpdGggYSBib29sZWFuIGluZGljYXRpbmcgaWYgdGhlIGluaXRpYWxpemF0aW9uIHdhcyBzdWNjZXNzZnVsLlxuICAgKi9cbiAgaW5pdChvcHRpb25zOiBLZXljbG9ha09wdGlvbnMgPSB7fSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLmluaXRTZXJ2aWNlVmFsdWVzKG9wdGlvbnMpO1xuICAgICAgY29uc3QgeyBjb25maWcsIGluaXRPcHRpb25zIH0gPSBvcHRpb25zO1xuXG4gICAgICB0aGlzLl9pbnN0YW5jZSA9IEtleWNsb2FrKGNvbmZpZyk7XG4gICAgICB0aGlzLmJpbmRzS2V5Y2xvYWtFdmVudHMoKTtcbiAgICAgIHRoaXMuX2luc3RhbmNlXG4gICAgICAgIC5pbml0KGluaXRPcHRpb25zKVxuICAgICAgICAuc3VjY2Vzcyhhc3luYyBhdXRoZW50aWNhdGVkID0+IHtcbiAgICAgICAgICBpZiAoYXV0aGVudGljYXRlZCAmJiB0aGlzLl9sb2FkVXNlclByb2ZpbGVBdFN0YXJ0VXApIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMubG9hZFVzZXJQcm9maWxlKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc29sdmUoYXV0aGVudGljYXRlZCk7XG4gICAgICAgIH0pXG4gICAgICAgIC5lcnJvcihrY0Vycm9yID0+IHtcbiAgICAgICAgICBsZXQgbXNnID0gJ0FuIGVycm9yIGhhcHBlbmVkIGR1cmluZyBLZXljbG9hayBpbml0aWFsaXphdGlvbi4nO1xuICAgICAgICAgIGlmIChrY0Vycm9yKSB7XG4gICAgICAgICAgICBsZXQgeyBlcnJvciwgZXJyb3JfZGVzY3JpcHRpb24gfSA9IGtjRXJyb3I7XG4gICAgICAgICAgICBtc2cgPSBtc2cuY29uY2F0KFxuICAgICAgICAgICAgICBgXFxuQWRhcHRlciBlcnJvciBkZXRhaWxzOlxcbkVycm9yOiAke2Vycm9yfVxcbkRlc2NyaXB0aW9uOiAke2Vycm9yX2Rlc2NyaXB0aW9ufWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlamVjdChtc2cpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWRpcmVjdHMgdG8gbG9naW4gZm9ybSBvbiAob3B0aW9ucyBpcyBhbiBvcHRpb25hbCBvYmplY3Qgd2l0aCByZWRpcmVjdFVyaSBhbmQvb3JcbiAgICogcHJvbXB0IGZpZWxkcykuXG4gICAqXG4gICAqIEBwYXJhbSBvcHRpb25zXG4gICAqIE9iamVjdCwgd2hlcmU6XG4gICAqICAtIHJlZGlyZWN0VXJpOiBTcGVjaWZpZXMgdGhlIHVyaSB0byByZWRpcmVjdCB0byBhZnRlciBsb2dpbi5cbiAgICogIC0gcHJvbXB0OkJ5IGRlZmF1bHQgdGhlIGxvZ2luIHNjcmVlbiBpcyBkaXNwbGF5ZWQgaWYgdGhlIHVzZXIgaXMgbm90IGxvZ2dlZC1pbiB0byBLZXljbG9hay5cbiAgICogVG8gb25seSBhdXRoZW50aWNhdGUgdG8gdGhlIGFwcGxpY2F0aW9uIGlmIHRoZSB1c2VyIGlzIGFscmVhZHkgbG9nZ2VkLWluIGFuZCBub3QgZGlzcGxheSB0aGVcbiAgICogbG9naW4gcGFnZSBpZiB0aGUgdXNlciBpcyBub3QgbG9nZ2VkLWluLCBzZXQgdGhpcyBvcHRpb24gdG8gbm9uZS4gVG8gYWx3YXlzIHJlcXVpcmVcbiAgICogcmUtYXV0aGVudGljYXRpb24gYW5kIGlnbm9yZSBTU08sIHNldCB0aGlzIG9wdGlvbiB0byBsb2dpbiAuXG4gICAqICAtIG1heEFnZTogVXNlZCBqdXN0IGlmIHVzZXIgaXMgYWxyZWFkeSBhdXRoZW50aWNhdGVkLiBTcGVjaWZpZXMgbWF4aW11bSB0aW1lIHNpbmNlIHRoZVxuICAgKiBhdXRoZW50aWNhdGlvbiBvZiB1c2VyIGhhcHBlbmVkLiBJZiB1c2VyIGlzIGFscmVhZHkgYXV0aGVudGljYXRlZCBmb3IgbG9uZ2VyIHRpbWUgdGhhblxuICAgKiBtYXhBZ2UsIHRoZSBTU08gaXMgaWdub3JlZCBhbmQgaGUgd2lsbCBuZWVkIHRvIHJlLWF1dGhlbnRpY2F0ZSBhZ2Fpbi5cbiAgICogIC0gbG9naW5IaW50OiBVc2VkIHRvIHByZS1maWxsIHRoZSB1c2VybmFtZS9lbWFpbCBmaWVsZCBvbiB0aGUgbG9naW4gZm9ybS5cbiAgICogIC0gYWN0aW9uOiBJZiB2YWx1ZSBpcyAncmVnaXN0ZXInIHRoZW4gdXNlciBpcyByZWRpcmVjdGVkIHRvIHJlZ2lzdHJhdGlvbiBwYWdlLCBvdGhlcndpc2UgdG9cbiAgICogbG9naW4gcGFnZS5cbiAgICogIC0gbG9jYWxlOiBTcGVjaWZpZXMgdGhlIGRlc2lyZWQgbG9jYWxlIGZvciB0aGUgVUkuXG4gICAqIEByZXR1cm5zXG4gICAqIEEgdm9pZCBQcm9taXNlIGlmIHRoZSBsb2dpbiBpcyBzdWNjZXNzZnVsIGFuZCBhZnRlciB0aGUgdXNlciBwcm9maWxlIGxvYWRpbmcuXG4gICAqL1xuICBsb2dpbihvcHRpb25zOiBLZXljbG9hay5LZXljbG9ha0xvZ2luT3B0aW9ucyA9IHt9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuX2luc3RhbmNlXG4gICAgICAgIC5sb2dpbihvcHRpb25zKVxuICAgICAgICAuc3VjY2Vzcyhhc3luYyAoKSA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMuX2xvYWRVc2VyUHJvZmlsZUF0U3RhcnRVcCkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5sb2FkVXNlclByb2ZpbGUoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICB9KVxuICAgICAgICAuZXJyb3IoKCkgPT4gcmVqZWN0KGBBbiBlcnJvciBoYXBwZW5lZCBkdXJpbmcgdGhlIGxvZ2luLmApKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWRpcmVjdHMgdG8gbG9nb3V0LlxuICAgKlxuICAgKiBAcGFyYW0gcmVkaXJlY3RVcmlcbiAgICogU3BlY2lmaWVzIHRoZSB1cmkgdG8gcmVkaXJlY3QgdG8gYWZ0ZXIgbG9nb3V0LlxuICAgKiBAcmV0dXJuc1xuICAgKiBBIHZvaWQgUHJvbWlzZSBpZiB0aGUgbG9nb3V0IHdhcyBzdWNjZXNzZnVsLCBjbGVhbmluZyBhbHNvIHRoZSB1c2VyUHJvZmlsZS5cbiAgICovXG4gIGxvZ291dChyZWRpcmVjdFVyaT86IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBvcHRpb25zOiBhbnkgPSB7XG4gICAgICAgIHJlZGlyZWN0VXJpXG4gICAgICB9O1xuXG4gICAgICB0aGlzLl9pbnN0YW5jZVxuICAgICAgICAubG9nb3V0KG9wdGlvbnMpXG4gICAgICAgIC5zdWNjZXNzKCgpID0+IHtcbiAgICAgICAgICB0aGlzLl91c2VyUHJvZmlsZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH0pXG4gICAgICAgIC5lcnJvcigoKSA9PiByZWplY3QoJ0FuIGVycm9yIGhhcHBlbmVkIGR1cmluZyBsb2dvdXQuJykpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZGlyZWN0cyB0byByZWdpc3RyYXRpb24gZm9ybS4gU2hvcnRjdXQgZm9yIGxvZ2luIHdpdGggb3B0aW9uXG4gICAqIGFjdGlvbiA9ICdyZWdpc3RlcicuIE9wdGlvbnMgYXJlIHNhbWUgYXMgZm9yIHRoZSBsb2dpbiBtZXRob2QgYnV0ICdhY3Rpb24nIGlzIHNldCB0b1xuICAgKiAncmVnaXN0ZXInLlxuICAgKlxuICAgKiBAcGFyYW0gb3B0aW9uc1xuICAgKiBsb2dpbiBvcHRpb25zXG4gICAqIEByZXR1cm5zXG4gICAqIEEgdm9pZCBQcm9taXNlIGlmIHRoZSByZWdpc3RlciBmbG93IHdhcyBzdWNjZXNzZnVsLlxuICAgKi9cbiAgcmVnaXN0ZXIob3B0aW9uczogS2V5Y2xvYWsuS2V5Y2xvYWtMb2dpbk9wdGlvbnMgPSB7IGFjdGlvbjogJ3JlZ2lzdGVyJyB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuX2luc3RhbmNlXG4gICAgICAgIC5yZWdpc3RlcihvcHRpb25zKVxuICAgICAgICAuc3VjY2VzcygoKSA9PiB7XG4gICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICB9KVxuICAgICAgICAuZXJyb3IoKCkgPT4gcmVqZWN0KCdBbiBlcnJvciBoYXBwZW5lZCBkdXJpbmcgdGhlIHJlZ2lzdGVyIGV4ZWN1dGlvbi4nKSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgdGhlIHVzZXIgaGFzIGFjY2VzcyB0byB0aGUgc3BlY2lmaWVkIHJvbGUuIEl0IHdpbGwgbG9vayBmb3Igcm9sZXMgaW5cbiAgICogcmVhbG0gYW5kIGNsaWVudElkLCBidXQgd2lsbCBub3QgY2hlY2sgaWYgdGhlIHVzZXIgaXMgbG9nZ2VkIGluIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2UuXG4gICAqXG4gICAqIEBwYXJhbSByb2xlXG4gICAqIHJvbGUgbmFtZVxuICAgKiBAcGFyYW0gcmVzb3VyY2VcbiAgICogcmVzb3VyY2UgbmFtZSBJZiBub3Qgc3BlY2lmaWVkLCBgY2xpZW50SWRgIGlzIHVzZWRcbiAgICogQHJldHVybnNcbiAgICogQSBib29sZWFuIG1lYW5pbmcgaWYgdGhlIHVzZXIgaGFzIHRoZSBzcGVjaWZpZWQgUm9sZS5cbiAgICovXG4gIGlzVXNlckluUm9sZShyb2xlOiBzdHJpbmcsIHJlc291cmNlPzogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgbGV0IGhhc1JvbGU6IGJvb2xlYW47XG4gICAgaGFzUm9sZSA9IHRoaXMuX2luc3RhbmNlLmhhc1Jlc291cmNlUm9sZShyb2xlLCByZXNvdXJjZSk7XG4gICAgaWYgKCFoYXNSb2xlKSB7XG4gICAgICBoYXNSb2xlID0gdGhpcy5faW5zdGFuY2UuaGFzUmVhbG1Sb2xlKHJvbGUpO1xuICAgIH1cbiAgICByZXR1cm4gaGFzUm9sZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIHJvbGVzIG9mIHRoZSBsb2dnZWQgdXNlci4gVGhlIGFsbFJvbGVzIHBhcmFtZXRlciwgd2l0aCBkZWZhdWx0IHZhbHVlXG4gICAqIHRydWUsIHdpbGwgcmV0dXJuIHRoZSBjbGllbnRJZCBhbmQgcmVhbG0gcm9sZXMgYXNzb2NpYXRlZCB3aXRoIHRoZSBsb2dnZWQgdXNlci4gSWYgc2V0IHRvIGZhbHNlXG4gICAqIGl0IHdpbGwgb25seSByZXR1cm4gdGhlIHVzZXIgcm9sZXMgYXNzb2NpYXRlZCB3aXRoIHRoZSBjbGllbnRJZC5cbiAgICpcbiAgICogQHBhcmFtIGFsbFJvbGVzXG4gICAqIEZsYWcgdG8gc2V0IGlmIGFsbCByb2xlcyBzaG91bGQgYmUgcmV0dXJuZWQuKE9wdGlvbmFsOiBkZWZhdWx0IHZhbHVlIGlzIHRydWUpXG4gICAqIEByZXR1cm5zXG4gICAqIEFycmF5IG9mIFJvbGVzIGFzc29jaWF0ZWQgd2l0aCB0aGUgbG9nZ2VkIHVzZXIuXG4gICAqL1xuICBnZXRVc2VyUm9sZXMoYWxsUm9sZXM6IGJvb2xlYW4gPSB0cnVlKTogc3RyaW5nW10ge1xuICAgIGxldCByb2xlczogc3RyaW5nW10gPSBbXTtcbiAgICBpZiAodGhpcy5faW5zdGFuY2UucmVzb3VyY2VBY2Nlc3MpIHtcbiAgICAgIGZvciAoY29uc3Qga2V5IGluIHRoaXMuX2luc3RhbmNlLnJlc291cmNlQWNjZXNzKSB7XG4gICAgICAgIGlmICh0aGlzLl9pbnN0YW5jZS5yZXNvdXJjZUFjY2Vzcy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgY29uc3QgcmVzb3VyY2VBY2Nlc3M6IGFueSA9IHRoaXMuX2luc3RhbmNlLnJlc291cmNlQWNjZXNzW2tleV07XG4gICAgICAgICAgY29uc3QgY2xpZW50Um9sZXMgPSByZXNvdXJjZUFjY2Vzc1sncm9sZXMnXSB8fCBbXTtcbiAgICAgICAgICByb2xlcyA9IHJvbGVzLmNvbmNhdChjbGllbnRSb2xlcyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGFsbFJvbGVzICYmIHRoaXMuX2luc3RhbmNlLnJlYWxtQWNjZXNzKSB7XG4gICAgICBsZXQgcmVhbG1Sb2xlcyA9IHRoaXMuX2luc3RhbmNlLnJlYWxtQWNjZXNzWydyb2xlcyddIHx8IFtdO1xuICAgICAgcm9sZXMucHVzaCguLi5yZWFsbVJvbGVzKTtcbiAgICB9XG4gICAgcmV0dXJuIHJvbGVzO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIHVzZXIgaXMgbG9nZ2VkIGluLlxuICAgKlxuICAgKiBAcmV0dXJuc1xuICAgKiBBIGJvb2xlYW4gdGhhdCBpbmRpY2F0ZXMgaWYgdGhlIHVzZXIgaXMgbG9nZ2VkIGluLlxuICAgKi9cbiAgYXN5bmMgaXNMb2dnZWRJbigpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICB0cnkge1xuICAgICAgaWYgKCF0aGlzLl9pbnN0YW5jZS5hdXRoZW50aWNhdGVkKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGF3YWl0IHRoaXMudXBkYXRlVG9rZW4oMjApO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0cnVlIGlmIHRoZSB0b2tlbiBoYXMgbGVzcyB0aGFuIG1pblZhbGlkaXR5IHNlY29uZHMgbGVmdCBiZWZvcmVcbiAgICogaXQgZXhwaXJlcy5cbiAgICpcbiAgICogQHBhcmFtIG1pblZhbGlkaXR5XG4gICAqIFNlY29uZHMgbGVmdC4gKG1pblZhbGlkaXR5KSBpcyBvcHRpb25hbC4gRGVmYXVsdCB2YWx1ZSBpcyAwLlxuICAgKiBAcmV0dXJuc1xuICAgKiBCb29sZWFuIGluZGljYXRpbmcgaWYgdGhlIHRva2VuIGlzIGV4cGlyZWQuXG4gICAqL1xuICBpc1Rva2VuRXhwaXJlZChtaW5WYWxpZGl0eTogbnVtYmVyID0gMCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9pbnN0YW5jZS5pc1Rva2VuRXhwaXJlZChtaW5WYWxpZGl0eSk7XG4gIH1cblxuICAvKipcbiAgICogSWYgdGhlIHRva2VuIGV4cGlyZXMgd2l0aGluIG1pblZhbGlkaXR5IHNlY29uZHMgdGhlIHRva2VuIGlzIHJlZnJlc2hlZC4gSWYgdGhlXG4gICAqIHNlc3Npb24gc3RhdHVzIGlmcmFtZSBpcyBlbmFibGVkLCB0aGUgc2Vzc2lvbiBzdGF0dXMgaXMgYWxzbyBjaGVja2VkLlxuICAgKiBSZXR1cm5zIGEgcHJvbWlzZSB0ZWxsaW5nIGlmIHRoZSB0b2tlbiB3YXMgcmVmcmVzaGVkIG9yIG5vdC4gSWYgdGhlIHNlc3Npb24gaXMgbm90IGFjdGl2ZVxuICAgKiBhbnltb3JlLCB0aGUgcHJvbWlzZSBpcyByZWplY3RlZC5cbiAgICpcbiAgICogQHBhcmFtIG1pblZhbGlkaXR5XG4gICAqIFNlY29uZHMgbGVmdC4gKG1pblZhbGlkaXR5IGlzIG9wdGlvbmFsLCBpZiBub3Qgc3BlY2lmaWVkIDUgaXMgdXNlZClcbiAgICogQHJldHVybnNcbiAgICogUHJvbWlzZSB3aXRoIGEgYm9vbGVhbiBpbmRpY2F0aW5nIGlmIHRoZSB0b2tlbiB3YXMgc3VjY2VzZnVsbHkgdXBkYXRlZC5cbiAgICovXG4gIHVwZGF0ZVRva2VuKG1pblZhbGlkaXR5OiBudW1iZXIgPSA1KTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGFzeW5jIChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIC8vIFRPRE86IHRoaXMgaXMgYSB3b3JrYXJvdW5kIHVudGlsIHRoZSBzaWxlbnQgcmVmcmVzaCAoaXNzdWUgIzQzKVxuICAgICAgLy8gaXMgbm90IGltcGxlbWVudGVkLCBhdm9pZGluZyB0aGUgcmVkaXJlY3QgbG9vcC5cbiAgICAgIGlmICh0aGlzLl9zaWxlbnRSZWZyZXNoKSB7XG4gICAgICAgIGlmICh0aGlzLmlzVG9rZW5FeHBpcmVkKCkpIHtcbiAgICAgICAgICByZWplY3QoJ0ZhaWxlZCB0byByZWZyZXNoIHRoZSB0b2tlbiwgb3IgdGhlIHNlc3Npb24gaXMgZXhwaXJlZCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXRoaXMuX2luc3RhbmNlKSB7XG4gICAgICAgIHJlamVjdCgnS2V5Y2xvYWsgQW5ndWxhciBsaWJyYXJ5IGlzIG5vdCBpbml0aWFsaXplZC4nKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9pbnN0YW5jZVxuICAgICAgICAudXBkYXRlVG9rZW4obWluVmFsaWRpdHkpXG4gICAgICAgIC5zdWNjZXNzKHJlZnJlc2hlZCA9PiB7XG4gICAgICAgICAgcmVzb2x2ZShyZWZyZXNoZWQpO1xuICAgICAgICB9KVxuICAgICAgICAuZXJyb3IoKCkgPT4gcmVqZWN0KCdGYWlsZWQgdG8gcmVmcmVzaCB0aGUgdG9rZW4sIG9yIHRoZSBzZXNzaW9uIGlzIGV4cGlyZWQnKSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogTG9hZHMgdGhlIHVzZXIgcHJvZmlsZS5cbiAgICogUmV0dXJucyBwcm9taXNlIHRvIHNldCBmdW5jdGlvbnMgdG8gYmUgaW52b2tlZCBpZiB0aGUgcHJvZmlsZSB3YXMgbG9hZGVkXG4gICAqIHN1Y2Nlc3NmdWxseSwgb3IgaWYgdGhlIHByb2ZpbGUgY291bGQgbm90IGJlIGxvYWRlZC5cbiAgICpcbiAgICogQHBhcmFtIGZvcmNlUmVsb2FkXG4gICAqIElmIHRydWUgd2lsbCBmb3JjZSB0aGUgbG9hZFVzZXJQcm9maWxlIGV2ZW4gaWYgaXRzIGFscmVhZHkgbG9hZGVkLlxuICAgKiBAcmV0dXJuc1xuICAgKiBBIHByb21pc2Ugd2l0aCB0aGUgS2V5Y2xvYWtQcm9maWxlIGRhdGEgbG9hZGVkLlxuICAgKi9cbiAgbG9hZFVzZXJQcm9maWxlKGZvcmNlUmVsb2FkOiBib29sZWFuID0gZmFsc2UpOiBQcm9taXNlPEtleWNsb2FrLktleWNsb2FrUHJvZmlsZT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBpZiAodGhpcy5fdXNlclByb2ZpbGUgJiYgIWZvcmNlUmVsb2FkKSB7XG4gICAgICAgIHJlc29sdmUodGhpcy5fdXNlclByb2ZpbGUpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmICghdGhpcy5faW5zdGFuY2UuYXV0aGVudGljYXRlZCkge1xuICAgICAgICByZWplY3QoJ1RoZSB1c2VyIHByb2ZpbGUgd2FzIG5vdCBsb2FkZWQgYXMgdGhlIHVzZXIgaXMgbm90IGxvZ2dlZCBpbi4nKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9pbnN0YW5jZVxuICAgICAgICAubG9hZFVzZXJQcm9maWxlKClcbiAgICAgICAgLnN1Y2Nlc3MocmVzdWx0ID0+IHtcbiAgICAgICAgICB0aGlzLl91c2VyUHJvZmlsZSA9IHJlc3VsdCBhcyBLZXljbG9hay5LZXljbG9ha1Byb2ZpbGU7XG4gICAgICAgICAgcmVzb2x2ZSh0aGlzLl91c2VyUHJvZmlsZSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5lcnJvcigoKSA9PiByZWplY3QoJ1RoZSB1c2VyIHByb2ZpbGUgY291bGQgbm90IGJlIGxvYWRlZC4nKSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYXV0aGVudGljYXRlZCB0b2tlbiwgY2FsbGluZyB1cGRhdGVUb2tlbiB0byBnZXQgYSByZWZyZXNoZWQgb25lIGlmXG4gICAqIG5lY2Vzc2FyeS4gSWYgdGhlIHNlc3Npb24gaXMgZXhwaXJlZCB0aGlzIG1ldGhvZCBjYWxscyB0aGUgbG9naW4gbWV0aG9kIGZvciBhIG5ldyBsb2dpbi5cbiAgICpcbiAgICogQHJldHVybnNcbiAgICogUHJvbWlzZSB3aXRoIHRoZSBnZW5lcmF0ZWQgdG9rZW4uXG4gICAqL1xuICBnZXRUb2tlbigpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLnVwZGF0ZVRva2VuKDEwKTtcbiAgICAgICAgcmVzb2x2ZSh0aGlzLl9pbnN0YW5jZS50b2tlbik7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICB0aGlzLmxvZ2luKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgbG9nZ2VkIHVzZXJuYW1lLlxuICAgKlxuICAgKiBAcmV0dXJuc1xuICAgKiBUaGUgbG9nZ2VkIHVzZXJuYW1lLlxuICAgKi9cbiAgZ2V0VXNlcm5hbWUoKTogc3RyaW5nIHtcbiAgICBpZiAoIXRoaXMuX3VzZXJQcm9maWxlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VzZXIgbm90IGxvZ2dlZCBpbiBvciB1c2VyIHByb2ZpbGUgd2FzIG5vdCBsb2FkZWQuJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX3VzZXJQcm9maWxlLnVzZXJuYW1lITtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhciBhdXRoZW50aWNhdGlvbiBzdGF0ZSwgaW5jbHVkaW5nIHRva2Vucy4gVGhpcyBjYW4gYmUgdXNlZnVsIGlmIGFwcGxpY2F0aW9uXG4gICAqIGhhcyBkZXRlY3RlZCB0aGUgc2Vzc2lvbiB3YXMgZXhwaXJlZCwgZm9yIGV4YW1wbGUgaWYgdXBkYXRpbmcgdG9rZW4gZmFpbHMuXG4gICAqIEludm9raW5nIHRoaXMgcmVzdWx0cyBpbiBvbkF1dGhMb2dvdXQgY2FsbGJhY2sgbGlzdGVuZXIgYmVpbmcgaW52b2tlZC5cbiAgICovXG4gIGNsZWFyVG9rZW4oKTogdm9pZCB7XG4gICAgdGhpcy5faW5zdGFuY2UuY2xlYXJUb2tlbigpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSB2YWxpZCB0b2tlbiBpbiBoZWFkZXIuIFRoZSBrZXkgJiB2YWx1ZSBmb3JtYXQgaXM6XG4gICAqIEF1dGhvcml6YXRpb24gQmVhcmVyIDx0b2tlbj4uXG4gICAqIElmIHRoZSBoZWFkZXJzIHBhcmFtIGlzIHVuZGVmaW5lZCBpdCB3aWxsIGNyZWF0ZSB0aGUgQW5ndWxhciBoZWFkZXJzIG9iamVjdC5cbiAgICpcbiAgICogQHBhcmFtIGhlYWRlcnNcbiAgICogVXBkYXRlZCBoZWFkZXIgd2l0aCBBdXRob3JpemF0aW9uIGFuZCBLZXljbG9hayB0b2tlbi5cbiAgICogQHJldHVybnNcbiAgICogQW4gb2JzZXJ2YWJsZSB3aXRoIHdpdGggdGhlIEhUVFAgQXV0aG9yaXphdGlvbiBoZWFkZXIgYW5kIHRoZSBjdXJyZW50IHRva2VuLlxuICAgKi9cbiAgYWRkVG9rZW5Ub0hlYWRlcihoZWFkZXJzOiBIdHRwSGVhZGVycyA9IG5ldyBIdHRwSGVhZGVycygpKTogT2JzZXJ2YWJsZTxIdHRwSGVhZGVycz4ge1xuICAgIHJldHVybiBPYnNlcnZhYmxlLmNyZWF0ZShhc3luYyAob2JzZXJ2ZXI6IE9ic2VydmVyPGFueT4pID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHRva2VuOiBzdHJpbmcgPSBhd2FpdCB0aGlzLmdldFRva2VuKCk7XG4gICAgICAgIGhlYWRlcnMgPSBoZWFkZXJzLnNldCh0aGlzLl9hdXRob3JpemF0aW9uSGVhZGVyTmFtZSwgdGhpcy5fYmVhcmVyUHJlZml4ICsgdG9rZW4pO1xuICAgICAgICBvYnNlcnZlci5uZXh0KGhlYWRlcnMpO1xuICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoZXJyb3IpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIG9yaWdpbmFsIEtleWNsb2FrIGluc3RhbmNlLCBpZiB5b3UgbmVlZCBhbnkgY3VzdG9taXphdGlvbiB0aGF0XG4gICAqIHRoaXMgQW5ndWxhciBzZXJ2aWNlIGRvZXMgbm90IHN1cHBvcnQgeWV0LiBVc2Ugd2l0aCBjYXV0aW9uLlxuICAgKlxuICAgKiBAcmV0dXJuc1xuICAgKiBUaGUgS2V5Y2xvYWtJbnN0YW5jZSBmcm9tIGtleWNsb2FrLWpzLlxuICAgKi9cbiAgZ2V0S2V5Y2xvYWtJbnN0YW5jZSgpOiBLZXljbG9hay5LZXljbG9ha0luc3RhbmNlIHtcbiAgICByZXR1cm4gdGhpcy5faW5zdGFuY2U7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgZXhjbHVkZWQgVVJMcyB0aGF0IHNob3VsZCBub3QgYmUgY29uc2lkZXJlZCBieVxuICAgKiB0aGUgaHR0cCBpbnRlcmNlcHRvciB3aGljaCBhdXRvbWF0aWNhbGx5IGFkZHMgdGhlIGF1dGhvcml6YXRpb24gaGVhZGVyIGluIHRoZSBIdHRwIFJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm5zXG4gICAqIFRoZSBleGNsdWRlZCB1cmxzIHRoYXQgbXVzdCBub3QgYmUgaW50ZXJjZXB0ZWQgYnkgdGhlIEtleWNsb2FrQmVhcmVySW50ZXJjZXB0b3IuXG4gICAqL1xuICBnZXQgZXhjbHVkZWRVcmxzKCk6IEV4Y2x1ZGVkVXJsUmVnZXhbXSB7XG4gICAgcmV0dXJuIHRoaXMuX2V4Y2x1ZGVkVXJscztcbiAgfVxuXG4gIC8qKlxuICAgKiBGbGFnIHRvIGluZGljYXRlIGlmIHRoZSBiZWFyZXIgd2lsbCBiZSBhZGRlZCB0byB0aGUgYXV0aG9yaXphdGlvbiBoZWFkZXIuXG4gICAqXG4gICAqIEByZXR1cm5zXG4gICAqIFJldHVybnMgaWYgdGhlIGJlYXJlciBpbnRlcmNlcHRvciB3YXMgc2V0IHRvIGJlIGRpc2FibGVkLlxuICAgKi9cbiAgZ2V0IGVuYWJsZUJlYXJlckludGVyY2VwdG9yKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9lbmFibGVCZWFyZXJJbnRlcmNlcHRvcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBLZXljbG9hayBzdWJqZWN0IHRvIG1vbml0b3IgdGhlIGV2ZW50cyB0cmlnZ2VyZWQgYnkga2V5Y2xvYWstanMuXG4gICAqIFRoZSBmb2xsb3dpbmcgZXZlbnRzIGFzIGF2YWlsYWJsZSAoYXMgZGVzY3JpYmVkIGF0IGtleWNsb2FrIGRvY3MgLVxuICAgKiBodHRwczovL3d3dy5rZXljbG9hay5vcmcvZG9jcy9sYXRlc3Qvc2VjdXJpbmdfYXBwcy9pbmRleC5odG1sI2NhbGxiYWNrLWV2ZW50cyk6XG4gICAqIC0gT25BdXRoRXJyb3JcbiAgICogLSBPbkF1dGhMb2dvdXRcbiAgICogLSBPbkF1dGhSZWZyZXNoRXJyb3JcbiAgICogLSBPbkF1dGhSZWZyZXNoU3VjY2Vzc1xuICAgKiAtIE9uQXV0aFN1Y2Nlc3NcbiAgICogLSBPblJlYWR5XG4gICAqIC0gT25Ub2tlbkV4cGlyZVxuICAgKiBJbiBlYWNoIG9jY3VycmVuY2Ugb2YgYW55IG9mIHRoZXNlLCB0aGlzIHN1YmplY3Qgd2lsbCByZXR1cm4gdGhlIGV2ZW50IHR5cGUsXG4gICAqIGRlc2NyaWJlZCBhdCB7QGxpbmsgS2V5Y2xvYWtFdmVudFR5cGV9IGVudW0gYW5kIHRoZSBmdW5jdGlvbiBhcmdzIGZyb20gdGhlIGtleWNsb2FrLWpzXG4gICAqIGlmIHByb3ZpZGVkIGFueS5cbiAgICpcbiAgICogQHJldHVybnNcbiAgICogQSBzdWJqZWN0IHdpdGggdGhlIHtAbGluayBLZXljbG9ha0V2ZW50fSB3aGljaCBkZXNjcmliZXMgdGhlIGV2ZW50IHR5cGUgYW5kIGF0dGFjaGVzIHRoZVxuICAgKiBmdW5jdGlvbiBhcmdzLlxuICAgKi9cbiAgZ2V0IGtleWNsb2FrRXZlbnRzJCgpOiBTdWJqZWN0PEtleWNsb2FrRXZlbnQ+IHtcbiAgICByZXR1cm4gdGhpcy5fa2V5Y2xvYWtFdmVudHMkO1xuICB9XG59XG4iXX0=