@edugouvfr/ngx-dsfr
Version:
NgxDsfr est un portage Angular des éléments d'interface du Système de Design de l'État Français (DSFR).
154 lines • 40 kB
JavaScript
import { CommonModule } from '@angular/common';
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { ReactiveFormsModule, Validators } from '@angular/forms';
import { DsfrAlertComponent, DsfrButtonComponent, DsfrButtonsGroupComponent, DsfrFranceConnectComponent, } from '../../components';
import { DsfrFormFieldsetComponent, DsfrFormFieldsetElementDirective } from '../../forms/fieldset';
import { DsfrFormCheckboxComponent } from '../../forms/form-checkbox';
import { DsfrFormEmailComponent } from '../../forms/form-email';
import { DsfrFormPasswordComponent } from '../../forms/form-password';
import { LocalStorage, StorageEnum, isOnBrowser } from '../../shared';
import { DsfrI18nPipe } from '../../shared/i18n/i18n.pipe';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "@angular/common";
export class DsfrLoginComponent {
/** @internal */
constructor(fb) {
this.fb = fb;
/** Se souvenir de l'utilisateur. */
this.rememberMe = false;
/** Demande de connexion via FranceConnect. */
this.franceConnectSelect = new EventEmitter();
/** Evénement lorsque le mot de passe change. */
this.passwordChange = new EventEmitter();
/** Emission de `recoveryRoute` s'il y a lieu. */
this.recoveryRouteSelect = new EventEmitter();
/** Demande de connexion avec en paramètre : '{login : string ; password : string}'. */
this.signinSelect = new EventEmitter();
/** Demande de création de compte */
this.signupSelect = new EventEmitter();
this.loginFormGroup = this.fb.group({
login: ['', Validators.required],
password: ['', Validators.required],
rememberMe: false,
});
}
/** @internal */
ngOnInit() {
if (isOnBrowser()) {
this.rememberMe ??= Boolean(LocalStorage.get(StorageEnum.REMEMBER_ME));
if (this.rememberMe)
this.login ??= LocalStorage.get(StorageEnum.LOGIN) ?? '';
}
this.setControlValue('login', this.login);
this.setControlValue('password', this.password);
this.setControlValue('rememberMe', this.rememberMe);
}
/** @internal */
onFranceConnect() {
this.franceConnectSelect.emit();
}
/**
* Inscription, on laisse le développeur faire ce qu'il veut dans ce cas.
* @internal
*/
onSignUp() {
this.signupSelect.emit();
}
/** Connexion */
/** @internal */
onSignIn() {
if (!this.isFormLoginValid())
return; // Ce qui ne peut pas arriver
const login = this.getControlValue('login');
const password = this.getControlValue('password');
const rememberMe = this.getControlValue('rememberMe');
// localStorage
this.saveToLocalStorage(rememberMe, login);
// Event
this.signinSelect.emit({ login: login, password: password, rememberMe: rememberMe });
}
/** @internal */
onPasswordChange(value) {
this.passwordChange.emit(value);
}
/** @internal */
onRecoveryRouteSelect(route) {
this.recoveryRouteSelect.emit(route);
}
/** @internal */
isFormLoginValid() {
return this.loginFormGroup.valid && this.emailComponent.isValid();
}
setControlValue(name, value) {
this.loginFormGroup.controls[name]?.setValue(value);
}
getControlValue(name) {
return this.loginFormGroup.controls[name]?.value;
}
saveToLocalStorage(rememberMe, login) {
if (this.rememberMe) {
LocalStorage.set(StorageEnum.REMEMBER_ME, String(rememberMe));
LocalStorage.set(StorageEnum.LOGIN, login);
}
else {
LocalStorage.remove(StorageEnum.REMEMBER_ME);
LocalStorage.remove(StorageEnum.LOGIN);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DsfrLoginComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DsfrLoginComponent, isStandalone: true, selector: "dsfr-login", inputs: { labelEmail: "labelEmail", hintEmail: "hintEmail", error: "error", recoveryLink: "recoveryLink", recoveryRoute: "recoveryRoute", recoveryRouterLink: "recoveryRouterLink", recoveryRouterLinkActive: "recoveryRouterLinkActive", recoveryRouterLinkExtras: "recoveryRouterLinkExtras", rememberMe: "rememberMe", secure: "secure", service: "service" }, outputs: { franceConnectSelect: "franceConnectSelect", passwordChange: "passwordChange", recoveryRouteSelect: "recoveryRouteSelect", signinSelect: "signinSelect", signupSelect: "signupSelect" }, viewQueries: [{ propertyName: "emailComponent", first: true, predicate: DsfrFormEmailComponent, descendants: true }], ngImport: i0, template: "<div class=\"fr-container fr-container--fluid fr-mb-md-14v\">\n <div class=\"fr-grid-row fr-grid-row--gutters fr-grid-row--center\">\n <div class=\"fr-col-12 fr-col-md-8 fr-col-lg-6\">\n <!-- BUG: classe fr-background-alt--grey inexistante c\u00F4t\u00E9 DSFR 1.11 mais utilis\u00E9 dans leur template -->\n <div class=\"fr-container fr-background-alt--grey fr-px-md-0 fr-pt-10v fr-pt-md-14v fr-pb-6v fr-pb-md-10v\">\n <div class=\"fr-grid-row fr-grid-row--gutters fr-grid-row--center\">\n <div class=\"fr-col-12 fr-col-md-9 fr-col-lg-8\">\n <!-- Heading h4 ------------------------------------------------------------------------------------------->\n <h1 class=\"fr-h4\">{{ ('login.heading' | dsfrI18n) + service }}</h1>\n <!-- France Connect h5 ------------------------------------------------------------------------------------>\n <div class=\"fr-mb-6v\">\n <h2 class=\"fr-h5\">{{ 'login.franceConnect.heading' | dsfrI18n }}</h2>\n <dsfr-franceconnect [secure]=\"secure\" (franceConnectSelect)=\"onFranceConnect()\"></dsfr-franceconnect>\n </div>\n <p class=\"fr-hr-or\">{{ 'login.or' | dsfrI18n }}</p>\n <!-- Formulaire de login h5 ------------------------------------------------------------------------------->\n <div>\n <form [formGroup]=\"loginFormGroup\" (ngSubmit)=\"onSignIn()\">\n <dsfr-fieldset>\n <h2 class=\"fr-h5\" legend>{{ 'login.account.heading' | dsfrI18n }}</h2>\n <dsfr-fieldset\n *fieldsetElement\n [legend]=\"'login.account.srOnly.label' | dsfrI18n\"\n [legendSrOnly]=\"true\"\n [error]=\"error\">\n <ng-container *ngIf=\"error\">\n <dsfr-alert *fieldsetElement severity=\"error\" size=\"SM\" [message]=\"error\"></dsfr-alert>\n </ng-container>\n <!-- Email ---------------------------------------------------------------------------------------->\n <dsfr-form-email\n *fieldsetElement\n formControlName=\"login\"\n autofocus\n [required]=\"true\"\n [hint]=\"hintEmail ?? ('email.hint' | dsfrI18n)\"\n [label]=\"labelEmail ?? ('login.account.email.label' | dsfrI18n)\"></dsfr-form-email>\n <!-- Password ------------------------------------------------------------------------------------->\n <dsfr-form-password\n *fieldsetElement\n formControlName=\"password\"\n [recoveryLink]=\"recoveryLink\"\n [recoveryRoute]=\"recoveryRoute\"\n [recoveryRouterLink]=\"recoveryRouterLink\"\n [recoveryRouterLinkActive]=\"recoveryRouterLinkActive\"\n [label]=\"'login.account.password.label' | dsfrI18n\"\n [recoveryRouterLinkExtras]=\"recoveryRouterLinkExtras\"\n (ngModelChange)=\"onPasswordChange($event)\"\n (recoveryRouteSelect)=\"onRecoveryRouteSelect($event)\"></dsfr-form-password>\n </dsfr-fieldset>\n <!-- Remember Me ------------------------------------------------------------------------------------>\n <dsfr-form-checkbox\n *fieldsetElement\n formControlName=\"rememberMe\"\n [small]=\"true\"\n [label]=\"'login.account.rememberMe.label' | dsfrI18n\"></dsfr-form-checkbox>\n <!-- Bouton de login -------------------------------------------------------------------------------->\n <dsfr-buttons-group *fieldsetElement>\n <dsfr-button\n type=\"submit\"\n customClass=\"fr-mt-2v\"\n [label]=\"'login.account.button.label' | dsfrI18n\"\n [disabled]=\"!isFormLoginValid()\"></dsfr-button>\n </dsfr-buttons-group>\n </dsfr-fieldset>\n </form>\n </div>\n <hr />\n <!-- Cr\u00E9ation de compte h5 -------------------------------------------------------------------------------->\n <h2 class=\"fr-h5\">{{ 'login.noAccount.heading' | dsfrI18n }}</h2>\n <dsfr-buttons-group>\n <dsfr-button\n variant=\"secondary\"\n [label]=\"'login.noAccount.button.label' | dsfrI18n\"\n (click)=\"onSignUp()\"></dsfr-button>\n </dsfr-buttons-group>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: DsfrFranceConnectComponent, selector: "dsfr-franceconnect", inputs: ["secure"], outputs: ["franceConnectSelect"] }, { kind: "component", type: DsfrFormEmailComponent, selector: "dsfr-form-email" }, { kind: "component", type: DsfrFormPasswordComponent, selector: "dsfr-form-password", inputs: ["autocomplete", "labelSrOnly", "required", "message", "messageSeverity", "validationRules", "recoveryLink", "recoveryTargetLink", "recoveryRouterLink", "recoveryRouterLinkActive", "recoveryRouterLinkExtras", "recoveryRoute"], outputs: ["recoveryRouteSelect"] }, { kind: "component", type: DsfrFormFieldsetComponent, selector: "dsfr-fieldset, dsfr-form-fieldset", inputs: ["inline"] }, { kind: "component", type: DsfrFormCheckboxComponent, selector: "dsfr-form-checkbox", inputs: ["labelSrOnly", "ariaInvalid", "small", "message", "messageSeverity", "error", "valid", "indeterminate"] }, { kind: "component", type: DsfrButtonComponent, selector: "dsfr-button", inputs: ["label", "type", "tooltipMessage", "variant", "buttonSize", "icon", "iconPosition", "disabled", "uppercase", "loader", "ariaLabel", "invertedOutlineContrast", "id", "buttonId", "ariaControls", "ariaPressed", "ariaHasPopup", "ariaExpanded", "tabIndex", "customClass", "buttonRole", "labelSrOnly", "size"] }, { kind: "component", type: DsfrButtonsGroupComponent, selector: "dsfr-buttons-group", inputs: ["inline", "alignment", "equisized", "buttonGroupSize", "groupMarkup", "size", "iconPosition"] }, { kind: "component", type: DsfrAlertComponent, selector: "dsfr-alert", inputs: ["heading", "headingLevel", "message", "severity", "ariaRoleValue", "alertSize", "closeControlLabel", "hasAriaRole", "closeable", "size", "closable"], outputs: ["conceal"] }, { kind: "pipe", type: DsfrI18nPipe, name: "dsfrI18n" }, { kind: "directive", type: DsfrFormFieldsetElementDirective, selector: "[fieldsetElement]", inputs: ["fieldsetElement"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DsfrLoginComponent, decorators: [{
type: Component,
args: [{ selector: 'dsfr-login', standalone: true, imports: [
CommonModule,
ReactiveFormsModule,
DsfrFranceConnectComponent,
DsfrFormEmailComponent,
DsfrFormPasswordComponent,
DsfrFormFieldsetComponent,
DsfrFormCheckboxComponent,
DsfrButtonComponent,
DsfrButtonsGroupComponent,
DsfrAlertComponent,
DsfrI18nPipe,
DsfrFormFieldsetElementDirective,
], template: "<div class=\"fr-container fr-container--fluid fr-mb-md-14v\">\n <div class=\"fr-grid-row fr-grid-row--gutters fr-grid-row--center\">\n <div class=\"fr-col-12 fr-col-md-8 fr-col-lg-6\">\n <!-- BUG: classe fr-background-alt--grey inexistante c\u00F4t\u00E9 DSFR 1.11 mais utilis\u00E9 dans leur template -->\n <div class=\"fr-container fr-background-alt--grey fr-px-md-0 fr-pt-10v fr-pt-md-14v fr-pb-6v fr-pb-md-10v\">\n <div class=\"fr-grid-row fr-grid-row--gutters fr-grid-row--center\">\n <div class=\"fr-col-12 fr-col-md-9 fr-col-lg-8\">\n <!-- Heading h4 ------------------------------------------------------------------------------------------->\n <h1 class=\"fr-h4\">{{ ('login.heading' | dsfrI18n) + service }}</h1>\n <!-- France Connect h5 ------------------------------------------------------------------------------------>\n <div class=\"fr-mb-6v\">\n <h2 class=\"fr-h5\">{{ 'login.franceConnect.heading' | dsfrI18n }}</h2>\n <dsfr-franceconnect [secure]=\"secure\" (franceConnectSelect)=\"onFranceConnect()\"></dsfr-franceconnect>\n </div>\n <p class=\"fr-hr-or\">{{ 'login.or' | dsfrI18n }}</p>\n <!-- Formulaire de login h5 ------------------------------------------------------------------------------->\n <div>\n <form [formGroup]=\"loginFormGroup\" (ngSubmit)=\"onSignIn()\">\n <dsfr-fieldset>\n <h2 class=\"fr-h5\" legend>{{ 'login.account.heading' | dsfrI18n }}</h2>\n <dsfr-fieldset\n *fieldsetElement\n [legend]=\"'login.account.srOnly.label' | dsfrI18n\"\n [legendSrOnly]=\"true\"\n [error]=\"error\">\n <ng-container *ngIf=\"error\">\n <dsfr-alert *fieldsetElement severity=\"error\" size=\"SM\" [message]=\"error\"></dsfr-alert>\n </ng-container>\n <!-- Email ---------------------------------------------------------------------------------------->\n <dsfr-form-email\n *fieldsetElement\n formControlName=\"login\"\n autofocus\n [required]=\"true\"\n [hint]=\"hintEmail ?? ('email.hint' | dsfrI18n)\"\n [label]=\"labelEmail ?? ('login.account.email.label' | dsfrI18n)\"></dsfr-form-email>\n <!-- Password ------------------------------------------------------------------------------------->\n <dsfr-form-password\n *fieldsetElement\n formControlName=\"password\"\n [recoveryLink]=\"recoveryLink\"\n [recoveryRoute]=\"recoveryRoute\"\n [recoveryRouterLink]=\"recoveryRouterLink\"\n [recoveryRouterLinkActive]=\"recoveryRouterLinkActive\"\n [label]=\"'login.account.password.label' | dsfrI18n\"\n [recoveryRouterLinkExtras]=\"recoveryRouterLinkExtras\"\n (ngModelChange)=\"onPasswordChange($event)\"\n (recoveryRouteSelect)=\"onRecoveryRouteSelect($event)\"></dsfr-form-password>\n </dsfr-fieldset>\n <!-- Remember Me ------------------------------------------------------------------------------------>\n <dsfr-form-checkbox\n *fieldsetElement\n formControlName=\"rememberMe\"\n [small]=\"true\"\n [label]=\"'login.account.rememberMe.label' | dsfrI18n\"></dsfr-form-checkbox>\n <!-- Bouton de login -------------------------------------------------------------------------------->\n <dsfr-buttons-group *fieldsetElement>\n <dsfr-button\n type=\"submit\"\n customClass=\"fr-mt-2v\"\n [label]=\"'login.account.button.label' | dsfrI18n\"\n [disabled]=\"!isFormLoginValid()\"></dsfr-button>\n </dsfr-buttons-group>\n </dsfr-fieldset>\n </form>\n </div>\n <hr />\n <!-- Cr\u00E9ation de compte h5 -------------------------------------------------------------------------------->\n <h2 class=\"fr-h5\">{{ 'login.noAccount.heading' | dsfrI18n }}</h2>\n <dsfr-buttons-group>\n <dsfr-button\n variant=\"secondary\"\n [label]=\"'login.noAccount.button.label' | dsfrI18n\"\n (click)=\"onSignUp()\"></dsfr-button>\n </dsfr-buttons-group>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n" }]
}], ctorParameters: () => [{ type: i1.FormBuilder }], propDecorators: { emailComponent: [{
type: ViewChild,
args: [DsfrFormEmailComponent]
}], labelEmail: [{
type: Input
}], hintEmail: [{
type: Input
}], error: [{
type: Input
}], recoveryLink: [{
type: Input
}], recoveryRoute: [{
type: Input
}], recoveryRouterLink: [{
type: Input
}], recoveryRouterLinkActive: [{
type: Input
}], recoveryRouterLinkExtras: [{
type: Input
}], rememberMe: [{
type: Input
}], secure: [{
type: Input
}], service: [{
type: Input
}], franceConnectSelect: [{
type: Output
}], passwordChange: [{
type: Output
}], recoveryRouteSelect: [{
type: Output
}], signinSelect: [{
type: Output
}], signupSelect: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9naW4uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWRzZnItY29tcG9uZW50cy9zcmMvbGliL3BhZ2VzL2xvZ2luL2xvZ2luLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1kc2ZyLWNvbXBvbmVudHMvc3JjL2xpYi9wYWdlcy9sb2dpbi9sb2dpbi5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFVLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUYsT0FBTyxFQUEwQixtQkFBbUIsRUFBRSxVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV6RixPQUFPLEVBQ0wsa0JBQWtCLEVBQ2xCLG1CQUFtQixFQUNuQix5QkFBeUIsRUFDekIsMEJBQTBCLEdBQzNCLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUFFLHlCQUF5QixFQUFFLGdDQUFnQyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbkcsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDdEUsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDaEUsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDdEUsT0FBTyxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQzs7OztBQXNCM0QsTUFBTSxPQUFPLGtCQUFrQjtJQXlEN0IsZ0JBQWdCO0lBQ2hCLFlBQW9CLEVBQWU7UUFBZixPQUFFLEdBQUYsRUFBRSxDQUFhO1FBN0JuQyxvQ0FBb0M7UUFDM0IsZUFBVSxHQUFHLEtBQUssQ0FBQztRQVE1Qiw4Q0FBOEM7UUFDcEMsd0JBQW1CLEdBQXVCLElBQUksWUFBWSxFQUFRLENBQUM7UUFFN0UsZ0RBQWdEO1FBQ3RDLG1CQUFjLEdBQXlCLElBQUksWUFBWSxFQUFVLENBQUM7UUFFNUUsaURBQWlEO1FBQ3ZDLHdCQUFtQixHQUF5QixJQUFJLFlBQVksRUFBVSxDQUFDO1FBRWpGLHVGQUF1RjtRQUM3RSxpQkFBWSxHQUE0QixJQUFJLFlBQVksRUFBYSxDQUFDO1FBRWhGLG9DQUFvQztRQUMxQixpQkFBWSxHQUF1QixJQUFJLFlBQVksRUFBUSxDQUFDO1FBUXBFLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUM7WUFDbEMsS0FBSyxFQUFFLENBQUMsRUFBRSxFQUFFLFVBQVUsQ0FBQyxRQUFRLENBQUM7WUFDaEMsUUFBUSxFQUFFLENBQUMsRUFBRSxFQUFFLFVBQVUsQ0FBQyxRQUFRLENBQUM7WUFDbkMsVUFBVSxFQUFFLEtBQUs7U0FDbEIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELGdCQUFnQjtJQUNoQixRQUFRO1FBQ04sSUFBSSxXQUFXLEVBQUUsRUFBRSxDQUFDO1lBQ2xCLElBQUksQ0FBQyxVQUFVLEtBQUssT0FBTyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7WUFDdkUsSUFBSSxJQUFJLENBQUMsVUFBVTtnQkFBRSxJQUFJLENBQUMsS0FBSyxLQUFLLFlBQVksQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNoRixDQUFDO1FBRUQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzFDLElBQUksQ0FBQyxlQUFlLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNoRCxJQUFJLENBQUMsZUFBZSxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDdEQsQ0FBQztJQUVELGdCQUFnQjtJQUNoQixlQUFlO1FBQ2IsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksRUFBRSxDQUFDO0lBQ2xDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxRQUFRO1FBQ04sSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQsZ0JBQWdCO0lBQ2hCLGdCQUFnQjtJQUNoQixRQUFRO1FBQ04sSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTtZQUFFLE9BQU8sQ0FBQyw2QkFBNkI7UUFDbkUsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUM1QyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2xELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsWUFBWSxDQUFDLENBQUM7UUFFdEQsZUFBZTtRQUNmLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxVQUFVLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFM0MsUUFBUTtRQUNSLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZGLENBQUM7SUFFRCxnQkFBZ0I7SUFDaEIsZ0JBQWdCLENBQUMsS0FBYTtRQUM1QixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBRUQsZ0JBQWdCO0lBQ2hCLHFCQUFxQixDQUFDLEtBQWE7UUFDakMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBRUQsZ0JBQWdCO0lBQ2hCLGdCQUFnQjtRQUNkLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNwRSxDQUFDO0lBRU8sZUFBZSxDQUFDLElBQVksRUFBRSxLQUFVO1FBQzlDLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRU8sZUFBZSxDQUFDLElBQVk7UUFDbEMsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLENBQUM7SUFDbkQsQ0FBQztJQUVPLGtCQUFrQixDQUFDLFVBQW1CLEVBQUUsS0FBYTtRQUMzRCxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNwQixZQUFZLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7WUFDOUQsWUFBWSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzdDLENBQUM7YUFBTSxDQUFDO1lBQ04sWUFBWSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDN0MsWUFBWSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekMsQ0FBQztJQUNILENBQUM7K0dBeklVLGtCQUFrQjttR0FBbEIsa0JBQWtCLDJwQkFDRCxzQkFBc0IsZ0RDdENwRCxzekpBaUZBLDJDRDFESSxZQUFZLGtJQUNaLG1CQUFtQiwwNUJBQ25CLDBCQUEwQixxSEFDMUIsc0JBQXNCLDREQUN0Qix5QkFBeUIsNFVBQ3pCLHlCQUF5QixrR0FDekIseUJBQXlCLGlMQUN6QixtQkFBbUIsa1hBQ25CLHlCQUF5Qix1S0FDekIsa0JBQWtCLHVPQUNsQixZQUFZLGlEQUNaLGdDQUFnQzs7NEZBR3ZCLGtCQUFrQjtrQkFuQjlCLFNBQVM7K0JBQ0UsWUFBWSxjQUVWLElBQUksV0FDUDt3QkFDUCxZQUFZO3dCQUNaLG1CQUFtQjt3QkFDbkIsMEJBQTBCO3dCQUMxQixzQkFBc0I7d0JBQ3RCLHlCQUF5Qjt3QkFDekIseUJBQXlCO3dCQUN6Qix5QkFBeUI7d0JBQ3pCLG1CQUFtQjt3QkFDbkIseUJBQXlCO3dCQUN6QixrQkFBa0I7d0JBQ2xCLFlBQVk7d0JBQ1osZ0NBQWdDO3FCQUNqQztnRkFHbUQsY0FBYztzQkFBaEQsU0FBUzt1QkFBQyxzQkFBc0I7Z0JBR3pDLFVBQVU7c0JBQWxCLEtBQUs7Z0JBR0csU0FBUztzQkFBakIsS0FBSztnQkFLRyxLQUFLO3NCQUFiLEtBQUs7Z0JBR0csWUFBWTtzQkFBcEIsS0FBSztnQkFHRyxhQUFhO3NCQUFyQixLQUFLO2dCQUdHLGtCQUFrQjtzQkFBMUIsS0FBSztnQkFHRyx3QkFBd0I7c0JBQWhDLEtBQUs7Z0JBR0csd0JBQXdCO3NCQUFoQyxLQUFLO2dCQUdHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBR0csTUFBTTtzQkFBZCxLQUFLO2dCQUdHLE9BQU87c0JBQWYsS0FBSztnQkFHSSxtQkFBbUI7c0JBQTVCLE1BQU07Z0JBR0csY0FBYztzQkFBdkIsTUFBTTtnQkFHRyxtQkFBbUI7c0JBQTVCLE1BQU07Z0JBR0csWUFBWTtzQkFBckIsTUFBTTtnQkFHRyxZQUFZO3NCQUFyQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25Jbml0LCBPdXRwdXQsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUJ1aWxkZXIsIEZvcm1Hcm91cCwgUmVhY3RpdmVGb3Jtc01vZHVsZSwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IE5hdmlnYXRpb25FeHRyYXMgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHtcbiAgRHNmckFsZXJ0Q29tcG9uZW50LFxuICBEc2ZyQnV0dG9uQ29tcG9uZW50LFxuICBEc2ZyQnV0dG9uc0dyb3VwQ29tcG9uZW50LFxuICBEc2ZyRnJhbmNlQ29ubmVjdENvbXBvbmVudCxcbn0gZnJvbSAnLi4vLi4vY29tcG9uZW50cyc7XG5pbXBvcnQgeyBEc2ZyRm9ybUZpZWxkc2V0Q29tcG9uZW50LCBEc2ZyRm9ybUZpZWxkc2V0RWxlbWVudERpcmVjdGl2ZSB9IGZyb20gJy4uLy4uL2Zvcm1zL2ZpZWxkc2V0JztcbmltcG9ydCB7IERzZnJGb3JtQ2hlY2tib3hDb21wb25lbnQgfSBmcm9tICcuLi8uLi9mb3Jtcy9mb3JtLWNoZWNrYm94JztcbmltcG9ydCB7IERzZnJGb3JtRW1haWxDb21wb25lbnQgfSBmcm9tICcuLi8uLi9mb3Jtcy9mb3JtLWVtYWlsJztcbmltcG9ydCB7IERzZnJGb3JtUGFzc3dvcmRDb21wb25lbnQgfSBmcm9tICcuLi8uLi9mb3Jtcy9mb3JtLXBhc3N3b3JkJztcbmltcG9ydCB7IExvY2FsU3RvcmFnZSwgU3RvcmFnZUVudW0sIGlzT25Ccm93c2VyIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcbmltcG9ydCB7IERzZnJJMThuUGlwZSB9IGZyb20gJy4uLy4uL3NoYXJlZC9pMThuL2kxOG4ucGlwZSc7XG5pbXBvcnQgeyBEc2ZyTG9naW4gfSBmcm9tICcuL2xvZ2luLm1vZGVsJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZHNmci1sb2dpbicsXG4gIHRlbXBsYXRlVXJsOiAnLi9sb2dpbi5jb21wb25lbnQuaHRtbCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBDb21tb25Nb2R1bGUsXG4gICAgUmVhY3RpdmVGb3Jtc01vZHVsZSxcbiAgICBEc2ZyRnJhbmNlQ29ubmVjdENvbXBvbmVudCxcbiAgICBEc2ZyRm9ybUVtYWlsQ29tcG9uZW50LFxuICAgIERzZnJGb3JtUGFzc3dvcmRDb21wb25lbnQsXG4gICAgRHNmckZvcm1GaWVsZHNldENvbXBvbmVudCxcbiAgICBEc2ZyRm9ybUNoZWNrYm94Q29tcG9uZW50LFxuICAgIERzZnJCdXR0b25Db21wb25lbnQsXG4gICAgRHNmckJ1dHRvbnNHcm91cENvbXBvbmVudCxcbiAgICBEc2ZyQWxlcnRDb21wb25lbnQsXG4gICAgRHNmckkxOG5QaXBlLFxuICAgIERzZnJGb3JtRmllbGRzZXRFbGVtZW50RGlyZWN0aXZlLFxuICBdLFxufSlcbmV4cG9ydCBjbGFzcyBEc2ZyTG9naW5Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICAvKiogQGludGVybmFsICovIEBWaWV3Q2hpbGQoRHNmckZvcm1FbWFpbENvbXBvbmVudCkgZW1haWxDb21wb25lbnQ6IERzZnJGb3JtRW1haWxDb21wb25lbnQ7XG5cbiAgLyoqTGFiZWwgZHUgY2hhbXAgZW1haWwgKFwiSWRlbnRpZmlhbnRcIiBwYXIgZMOpZmF1dCkgKi9cbiAgQElucHV0KCkgbGFiZWxFbWFpbDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIC8qKiBTdXJjaGFyZ2VyIGxlIHRleHRlIGRlIGRlc2NyaXB0aW9uIGFkZGl0aW9ubmVsIGR1IGNoYW1wIGVtYWlsICovXG4gIEBJbnB1dCgpIGhpbnRFbWFpbDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBJbmRpcXVlIHVuZSBlcnJldXIgZGUgY29ubmV4aW9uLiBNZXNzYWdlIGRlIGwnZXJyZXVyLlxuICAgKi9cbiAgQElucHV0KCkgZXJyb3I6IHN0cmluZztcblxuICAvKiogVXJsIGRlIHLDqWN1cMOpcmF0aW9uIGR1IG1vdCBkZSBwYXNzZSAob3B0aW9ubmVsKSAqL1xuICBASW5wdXQoKSByZWNvdmVyeUxpbms6IHN0cmluZztcblxuICAvKiogUGF0aCBpbnRlcm5lLiBFeGNsdXNpZiBhdmVjIGxpbmsgZXQgcm91dGVyTGluayAqL1xuICBASW5wdXQoKSByZWNvdmVyeVJvdXRlOiBzdHJpbmc7XG5cbiAgLyoqIFBhdGggYW5ndWxhciBnw6lyw6kgZW4gdGFudCBxdWUgZGlyZWN0aXZlIHJvdXRlckxpbmsuICovXG4gIEBJbnB1dCgpIHJlY292ZXJ5Um91dGVyTGluazogc3RyaW5nIHwgc3RyaW5nW107XG5cbiAgLyoqIFJvdXRlckxpbmsgOiBjbGFzc2UgdXRpbGlzw6llIHBvdXIgbGEgZGlyZWN0aXZlIHJvdXRlckxpbmsgYWN0aXZlLiAqL1xuICBASW5wdXQoKSByZWNvdmVyeVJvdXRlckxpbmtBY3RpdmU6IHN0cmluZyB8IHN0cmluZ1tdO1xuXG4gIC8qKiBSb3V0ZXJMaW5rIDogdmFsZXVycyBhZGRpdGlvbm5lbGxlcyBkZSBuYXZpZ2F0aW9uIHBvdXIgbGUgcm91dGVyTGluayAocXVlcnlQYXJhbXMsIHN0YXRlLCBldGMuKSAqL1xuICBASW5wdXQoKSByZWNvdmVyeVJvdXRlckxpbmtFeHRyYXM6IE5hdmlnYXRpb25FeHRyYXM7XG5cbiAgLyoqIFNlIHNvdXZlbmlyIGRlIGwndXRpbGlzYXRldXIuICovXG4gIEBJbnB1dCgpIHJlbWVtYmVyTWUgPSBmYWxzZTtcblxuICAvKiogVXRpbGlzYXRpb24gZGUgRnJhbmNlQ29ubmVjdCsgKHF1aSBlc3QgcGx1cyBzw6ljdXJpc8OpKS4gKi9cbiAgQElucHV0KCkgc2VjdXJlOiBmYWxzZTtcblxuICAvKiogTm9tIGR1IHNlcnZpY2UuICovXG4gIEBJbnB1dCgpIHNlcnZpY2U6IHN0cmluZztcblxuICAvKiogRGVtYW5kZSBkZSBjb25uZXhpb24gdmlhIEZyYW5jZUNvbm5lY3QuICovXG4gIEBPdXRwdXQoKSBmcmFuY2VDb25uZWN0U2VsZWN0OiBFdmVudEVtaXR0ZXI8dm9pZD4gPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cbiAgLyoqIEV2w6luZW1lbnQgbG9yc3F1ZSBsZSBtb3QgZGUgcGFzc2UgY2hhbmdlLiAqL1xuICBAT3V0cHV0KCkgcGFzc3dvcmRDaGFuZ2U6IEV2ZW50RW1pdHRlcjxzdHJpbmc+ID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG5cbiAgLyoqIEVtaXNzaW9uIGRlIGByZWNvdmVyeVJvdXRlYCBzJ2lsIHkgYSBsaWV1LiAqL1xuICBAT3V0cHV0KCkgcmVjb3ZlcnlSb3V0ZVNlbGVjdDogRXZlbnRFbWl0dGVyPHN0cmluZz4gPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcblxuICAvKiogRGVtYW5kZSBkZSBjb25uZXhpb24gYXZlYyBlbiBwYXJhbcOodHJlIDogJ3tsb2dpbiA6IHN0cmluZyA7IHBhc3N3b3JkIDogc3RyaW5nfScuICovXG4gIEBPdXRwdXQoKSBzaWduaW5TZWxlY3Q6IEV2ZW50RW1pdHRlcjxEc2ZyTG9naW4+ID0gbmV3IEV2ZW50RW1pdHRlcjxEc2ZyTG9naW4+KCk7XG5cbiAgLyoqIERlbWFuZGUgZGUgY3LDqWF0aW9uIGRlIGNvbXB0ZSAqL1xuICBAT3V0cHV0KCkgc2lnbnVwU2VsZWN0OiBFdmVudEVtaXR0ZXI8dm9pZD4gPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cbiAgLyoqIEBpbnRlcm5hbCAqLyBwYXNzd29yZDogc3RyaW5nOyAvLyBQYXNzd29yZCBkZSBsJ3V0aWxpc2F0ZXVyLlxuICAvKiogQGludGVybmFsICovIGxvZ2luOiBzdHJpbmc7IC8vIEVtYWlsIGRlIGwndXRpbGlzYXRldXIuXG4gIC8qKiBAaW50ZXJuYWwgKi8gbG9naW5Gb3JtR3JvdXA6IEZvcm1Hcm91cDtcblxuICAvKiogQGludGVybmFsICovXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZmI6IEZvcm1CdWlsZGVyKSB7XG4gICAgdGhpcy5sb2dpbkZvcm1Hcm91cCA9IHRoaXMuZmIuZ3JvdXAoe1xuICAgICAgbG9naW46IFsnJywgVmFsaWRhdG9ycy5yZXF1aXJlZF0sXG4gICAgICBwYXNzd29yZDogWycnLCBWYWxpZGF0b3JzLnJlcXVpcmVkXSxcbiAgICAgIHJlbWVtYmVyTWU6IGZhbHNlLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICBpZiAoaXNPbkJyb3dzZXIoKSkge1xuICAgICAgdGhpcy5yZW1lbWJlck1lID8/PSBCb29sZWFuKExvY2FsU3RvcmFnZS5nZXQoU3RvcmFnZUVudW0uUkVNRU1CRVJfTUUpKTtcbiAgICAgIGlmICh0aGlzLnJlbWVtYmVyTWUpIHRoaXMubG9naW4gPz89IExvY2FsU3RvcmFnZS5nZXQoU3RvcmFnZUVudW0uTE9HSU4pID8/ICcnO1xuICAgIH1cblxuICAgIHRoaXMuc2V0Q29udHJvbFZhbHVlKCdsb2dpbicsIHRoaXMubG9naW4pO1xuICAgIHRoaXMuc2V0Q29udHJvbFZhbHVlKCdwYXNzd29yZCcsIHRoaXMucGFzc3dvcmQpO1xuICAgIHRoaXMuc2V0Q29udHJvbFZhbHVlKCdyZW1lbWJlck1lJywgdGhpcy5yZW1lbWJlck1lKTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgb25GcmFuY2VDb25uZWN0KCkge1xuICAgIHRoaXMuZnJhbmNlQ29ubmVjdFNlbGVjdC5lbWl0KCk7XG4gIH1cblxuICAvKipcbiAgICogSW5zY3JpcHRpb24sIG9uIGxhaXNzZSBsZSBkw6l2ZWxvcHBldXIgZmFpcmUgY2UgcXUnaWwgdmV1dCBkYW5zIGNlIGNhcy5cbiAgICogQGludGVybmFsXG4gICAqL1xuICBvblNpZ25VcCgpIHtcbiAgICB0aGlzLnNpZ251cFNlbGVjdC5lbWl0KCk7XG4gIH1cblxuICAvKiogQ29ubmV4aW9uICovXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgb25TaWduSW4oKSB7XG4gICAgaWYgKCF0aGlzLmlzRm9ybUxvZ2luVmFsaWQoKSkgcmV0dXJuOyAvLyBDZSBxdWkgbmUgcGV1dCBwYXMgYXJyaXZlclxuICAgIGNvbnN0IGxvZ2luID0gdGhpcy5nZXRDb250cm9sVmFsdWUoJ2xvZ2luJyk7XG4gICAgY29uc3QgcGFzc3dvcmQgPSB0aGlzLmdldENvbnRyb2xWYWx1ZSgncGFzc3dvcmQnKTtcbiAgICBjb25zdCByZW1lbWJlck1lID0gdGhpcy5nZXRDb250cm9sVmFsdWUoJ3JlbWVtYmVyTWUnKTtcblxuICAgIC8vIGxvY2FsU3RvcmFnZVxuICAgIHRoaXMuc2F2ZVRvTG9jYWxTdG9yYWdlKHJlbWVtYmVyTWUsIGxvZ2luKTtcblxuICAgIC8vIEV2ZW50XG4gICAgdGhpcy5zaWduaW5TZWxlY3QuZW1pdCh7IGxvZ2luOiBsb2dpbiwgcGFzc3dvcmQ6IHBhc3N3b3JkLCByZW1lbWJlck1lOiByZW1lbWJlck1lIH0pO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBvblBhc3N3b3JkQ2hhbmdlKHZhbHVlOiBzdHJpbmcpIHtcbiAgICB0aGlzLnBhc3N3b3JkQ2hhbmdlLmVtaXQodmFsdWUpO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBvblJlY292ZXJ5Um91dGVTZWxlY3Qocm91dGU6IHN0cmluZykge1xuICAgIHRoaXMucmVjb3ZlcnlSb3V0ZVNlbGVjdC5lbWl0KHJvdXRlKTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgaXNGb3JtTG9naW5WYWxpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5sb2dpbkZvcm1Hcm91cC52YWxpZCAmJiB0aGlzLmVtYWlsQ29tcG9uZW50LmlzVmFsaWQoKTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0Q29udHJvbFZhbHVlKG5hbWU6IHN0cmluZywgdmFsdWU6IGFueSk6IHZvaWQge1xuICAgIHRoaXMubG9naW5Gb3JtR3JvdXAuY29udHJvbHNbbmFtZV0/LnNldFZhbHVlKHZhbHVlKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Q29udHJvbFZhbHVlKG5hbWU6IHN0cmluZyk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMubG9naW5Gb3JtR3JvdXAuY29udHJvbHNbbmFtZV0/LnZhbHVlO1xuICB9XG5cbiAgcHJpdmF0ZSBzYXZlVG9Mb2NhbFN0b3JhZ2UocmVtZW1iZXJNZTogYm9vbGVhbiwgbG9naW46IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICh0aGlzLnJlbWVtYmVyTWUpIHtcbiAgICAgIExvY2FsU3RvcmFnZS5zZXQoU3RvcmFnZUVudW0uUkVNRU1CRVJfTUUsIFN0cmluZyhyZW1lbWJlck1lKSk7XG4gICAgICBMb2NhbFN0b3JhZ2Uuc2V0KFN0b3JhZ2VFbnVtLkxPR0lOLCBsb2dpbik7XG4gICAgfSBlbHNlIHtcbiAgICAgIExvY2FsU3RvcmFnZS5yZW1vdmUoU3RvcmFnZUVudW0uUkVNRU1CRVJfTUUpO1xuICAgICAgTG9jYWxTdG9yYWdlLnJlbW92ZShTdG9yYWdlRW51bS5MT0dJTik7XG4gICAgfVxuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwiZnItY29udGFpbmVyIGZyLWNvbnRhaW5lci0tZmx1aWQgZnItbWItbWQtMTR2XCI+XG4gIDxkaXYgY2xhc3M9XCJmci1ncmlkLXJvdyBmci1ncmlkLXJvdy0tZ3V0dGVycyBmci1ncmlkLXJvdy0tY2VudGVyXCI+XG4gICAgPGRpdiBjbGFzcz1cImZyLWNvbC0xMiBmci1jb2wtbWQtOCBmci1jb2wtbGctNlwiPlxuICAgICAgPCEtLSBCVUc6IGNsYXNzZSBmci1iYWNrZ3JvdW5kLWFsdC0tZ3JleSBpbmV4aXN0YW50ZSBjw7R0w6kgRFNGUiAxLjExIG1haXMgdXRpbGlzw6kgZGFucyBsZXVyIHRlbXBsYXRlIC0tPlxuICAgICAgPGRpdiBjbGFzcz1cImZyLWNvbnRhaW5lciBmci1iYWNrZ3JvdW5kLWFsdC0tZ3JleSBmci1weC1tZC0wIGZyLXB0LTEwdiBmci1wdC1tZC0xNHYgZnItcGItNnYgZnItcGItbWQtMTB2XCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJmci1ncmlkLXJvdyBmci1ncmlkLXJvdy0tZ3V0dGVycyBmci1ncmlkLXJvdy0tY2VudGVyXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZyLWNvbC0xMiBmci1jb2wtbWQtOSBmci1jb2wtbGctOFwiPlxuICAgICAgICAgICAgPCEtLSBIZWFkaW5nIGg0IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+XG4gICAgICAgICAgICA8aDEgY2xhc3M9XCJmci1oNFwiPnt7ICgnbG9naW4uaGVhZGluZycgfCBkc2ZySTE4bikgKyBzZXJ2aWNlIH19PC9oMT5cbiAgICAgICAgICAgIDwhLS0gRnJhbmNlIENvbm5lY3QgaDUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZyLW1iLTZ2XCI+XG4gICAgICAgICAgICAgIDxoMiBjbGFzcz1cImZyLWg1XCI+e3sgJ2xvZ2luLmZyYW5jZUNvbm5lY3QuaGVhZGluZycgfCBkc2ZySTE4biB9fTwvaDI+XG4gICAgICAgICAgICAgIDxkc2ZyLWZyYW5jZWNvbm5lY3QgW3NlY3VyZV09XCJzZWN1cmVcIiAoZnJhbmNlQ29ubmVjdFNlbGVjdCk9XCJvbkZyYW5jZUNvbm5lY3QoKVwiPjwvZHNmci1mcmFuY2Vjb25uZWN0PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8cCBjbGFzcz1cImZyLWhyLW9yXCI+e3sgJ2xvZ2luLm9yJyB8IGRzZnJJMThuIH19PC9wPlxuICAgICAgICAgICAgPCEtLSBGb3JtdWxhaXJlIGRlIGxvZ2luIGg1IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+XG4gICAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgICA8Zm9ybSBbZm9ybUdyb3VwXT1cImxvZ2luRm9ybUdyb3VwXCIgKG5nU3VibWl0KT1cIm9uU2lnbkluKClcIj5cbiAgICAgICAgICAgICAgICA8ZHNmci1maWVsZHNldD5cbiAgICAgICAgICAgICAgICAgIDxoMiBjbGFzcz1cImZyLWg1XCIgbGVnZW5kPnt7ICdsb2dpbi5hY2NvdW50LmhlYWRpbmcnIHwgZHNmckkxOG4gfX08L2gyPlxuICAgICAgICAgICAgICAgICAgPGRzZnItZmllbGRzZXRcbiAgICAgICAgICAgICAgICAgICAgKmZpZWxkc2V0RWxlbWVudFxuICAgICAgICAgICAgICAgICAgICBbbGVnZW5kXT1cIidsb2dpbi5hY2NvdW50LnNyT25seS5sYWJlbCcgfCBkc2ZySTE4blwiXG4gICAgICAgICAgICAgICAgICAgIFtsZWdlbmRTck9ubHldPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgIFtlcnJvcl09XCJlcnJvclwiPlxuICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZXJyb3JcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8ZHNmci1hbGVydCAqZmllbGRzZXRFbGVtZW50IHNldmVyaXR5PVwiZXJyb3JcIiBzaXplPVwiU01cIiBbbWVzc2FnZV09XCJlcnJvclwiPjwvZHNmci1hbGVydD5cbiAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgICAgIDwhLS0gRW1haWwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT5cbiAgICAgICAgICAgICAgICAgICAgPGRzZnItZm9ybS1lbWFpbFxuICAgICAgICAgICAgICAgICAgICAgICpmaWVsZHNldEVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJsb2dpblwiXG4gICAgICAgICAgICAgICAgICAgICAgYXV0b2ZvY3VzXG4gICAgICAgICAgICAgICAgICAgICAgW3JlcXVpcmVkXT1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICAgIFtoaW50XT1cImhpbnRFbWFpbCA/PyAoJ2VtYWlsLmhpbnQnIHwgZHNmckkxOG4pXCJcbiAgICAgICAgICAgICAgICAgICAgICBbbGFiZWxdPVwibGFiZWxFbWFpbCA/PyAoJ2xvZ2luLmFjY291bnQuZW1haWwubGFiZWwnIHwgZHNmckkxOG4pXCI+PC9kc2ZyLWZvcm0tZW1haWw+XG4gICAgICAgICAgICAgICAgICAgIDwhLS0gUGFzc3dvcmQgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT5cbiAgICAgICAgICAgICAgICAgICAgPGRzZnItZm9ybS1wYXNzd29yZFxuICAgICAgICAgICAgICAgICAgICAgICpmaWVsZHNldEVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJwYXNzd29yZFwiXG4gICAgICAgICAgICAgICAgICAgICAgW3JlY292ZXJ5TGlua109XCJyZWNvdmVyeUxpbmtcIlxuICAgICAgICAgICAgICAgICAgICAgIFtyZWNvdmVyeVJvdXRlXT1cInJlY292ZXJ5Um91dGVcIlxuICAgICAgICAgICAgICAgICAgICAgIFtyZWNvdmVyeVJvdXRlckxpbmtdPVwicmVjb3ZlcnlSb3V0ZXJMaW5rXCJcbiAgICAgICAgICAgICAgICAgICAgICBbcmVjb3ZlcnlSb3V0ZXJMaW5rQWN0aXZlXT1cInJlY292ZXJ5Um91dGVyTGlua0FjdGl2ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgW2xhYmVsXT1cIidsb2dpbi5hY2NvdW50LnBhc3N3b3JkLmxhYmVsJyB8IGRzZnJJMThuXCJcbiAgICAgICAgICAgICAgICAgICAgICBbcmVjb3ZlcnlSb3V0ZXJMaW5rRXh0cmFzXT1cInJlY292ZXJ5Um91dGVyTGlua0V4dHJhc1wiXG4gICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwib25QYXNzd29yZENoYW5nZSgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgICAocmVjb3ZlcnlSb3V0ZVNlbGVjdCk9XCJvblJlY292ZXJ5Um91dGVTZWxlY3QoJGV2ZW50KVwiPjwvZHNmci1mb3JtLXBhc3N3b3JkPlxuICAgICAgICAgICAgICAgICAgPC9kc2ZyLWZpZWxkc2V0PlxuICAgICAgICAgICAgICAgICAgPCEtLSBSZW1lbWJlciBNZSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+XG4gICAgICAgICAgICAgICAgICA8ZHNmci1mb3JtLWNoZWNrYm94XG4gICAgICAgICAgICAgICAgICAgICpmaWVsZHNldEVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicmVtZW1iZXJNZVwiXG4gICAgICAgICAgICAgICAgICAgIFtzbWFsbF09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgW2xhYmVsXT1cIidsb2dpbi5hY2NvdW50LnJlbWVtYmVyTWUubGFiZWwnIHwgZHNmckkxOG5cIj48L2RzZnItZm9ybS1jaGVja2JveD5cbiAgICAgICAgICAgICAgICAgIDwhLS0gQm91dG9uIGRlIGxvZ2luIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tPlxuICAgICAgICAgICAgICAgICAgPGRzZnItYnV0dG9ucy1ncm91cCAqZmllbGRzZXRFbGVtZW50PlxuICAgICAgICAgICAgICAgICAgICA8ZHNmci1idXR0b25cbiAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwic3VibWl0XCJcbiAgICAgICAgICAgICAgICAgICAgICBjdXN0b21DbGFzcz1cImZyLW10LTJ2XCJcbiAgICAgICAgICAgICAgICAgICAgICBbbGFiZWxdPVwiJ2xvZ2luLmFjY291bnQuYnV0dG9uLmxhYmVsJyB8IGRzZnJJMThuXCJcbiAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIWlzRm9ybUxvZ2luVmFsaWQoKVwiPjwvZHNmci1idXR0b24+XG4gICAgICAgICAgICAgICAgICA8L2RzZnItYnV0dG9ucy1ncm91cD5cbiAgICAgICAgICAgICAgICA8L2RzZnItZmllbGRzZXQ+XG4gICAgICAgICAgICAgIDwvZm9ybT5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGhyIC8+XG4gICAgICAgICAgICA8IS0tIENyw6lhdGlvbiBkZSBjb21wdGUgaDUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+XG4gICAgICAgICAgICA8aDIgY2xhc3M9XCJmci1oNVwiPnt7ICdsb2dpbi5ub0FjY291bnQuaGVhZGluZycgfCBkc2ZySTE4biB9fTwvaDI+XG4gICAgICAgICAgICA8ZHNmci1idXR0b25zLWdyb3VwPlxuICAgICAgICAgICAgICA8ZHNmci1idXR0b25cbiAgICAgICAgICAgICAgICB2YXJpYW50PVwic2Vjb25kYXJ5XCJcbiAgICAgICAgICAgICAgICBbbGFiZWxdPVwiJ2xvZ2luLm5vQWNjb3VudC5idXR0b24ubGFiZWwnIHwgZHNmckkxOG5cIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJvblNpZ25VcCgpXCI+PC9kc2ZyLWJ1dHRvbj5cbiAgICAgICAgICAgIDwvZHNmci1idXR0b25zLWdyb3VwPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbjwvZGl2PlxuIl19