UNPKG

@nowzoo/ngx-firebase-auth

Version:

Angular components for Firebase email-first sign in and out-of-band (oob) actions (reset password, etc).

2,368 lines 206 kB
import { trigger, state, style, animate, transition } from '@angular/animations';
import { Injectable, Component, Input, Output, EventEmitter, ViewChild, NgZone, NgModule, defineInjectable, inject } from '@angular/core';
import { AngularFireAuth } from 'angularfire2/auth';
import { auth } from 'firebase/app';
import { Router, ActivatedRoute, RouterModule } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil, take, debounceTime } from 'rxjs/operators';
import { FormControl, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
/** @type {?} */
const fadeInOutAnimation = trigger('fadeInOut', [
    state('in', style({ opacity: 1, display: 'block' })),
    transition('void => *', [
        style({ opacity: 0 }),
        animate(300)
    ]),
    transition('* => void', [
        animate(300, style({ opacity: 0 }))
    ])
]);
/** @type {?} */
const screenAnimation = trigger('screen', [
    state('in', style({ opacity: 1 })),
    transition('void => *', [
        style({ opacity: 0 }),
        animate(300)
    ]),
    transition('* => void', [
        animate(0, style({ opacity: 0 }))
    ])
]);
/** @type {?} */
const getOAuthProviderName = (id) => {
    switch (id) {
        case 'twitter.com': return 'Twitter';
        case 'facebook.com': return 'Facebook';
        case 'google.com': return 'Google';
        case 'github.com': return 'GitHub';
        default: return id;
    }
};
/** @type {?} */
const getOAuthProviderIcon = (id) => {
    switch (id) {
        case 'twitter.com':
        case 'facebook.com':
        case 'google.com':
        case 'github.com':
            return 'fab fa-fw fa-' + id.replace('.com', '');
        default: return 'fas fa-fw fa-sign-in-alt';
    }
};

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class NgxFirebaseAuthService {
    /**
     * @param {?} _afAuth
     */
    constructor(_afAuth) {
        this._afAuth = _afAuth;
    }
    /**
     * @return {?}
     */
    get auth() {
        return this._afAuth.auth;
    }
    /**
     * @return {?}
     */
    get storage() {
        return window.localStorage;
    }
    /**
     * @return {?}
     */
    getRemembered() {
        /** @type {?} */
        const str = this.storage.getItem(NgxFirebaseAuthService.rememberKey);
        if (str) {
            try {
                return JSON.parse(str);
            }
            catch (e) {
                return { email: '', remember: true };
            }
        }
        return { email: '', remember: true };
    }
    /**
     * @param {?} remember
     * @param {?} email
     * @return {?}
     */
    setRemembered(remember, email) {
        /** @type {?} */
        const persistence = remember ?
            auth.Auth.Persistence.LOCAL : auth.Auth.Persistence.SESSION;
        return this.auth.setPersistence(persistence)
            .then(() => {
            /** @type {?} */
            const o = {
                email: remember ? email : '',
                remember: remember
            };
            /** @type {?} */
            const str = JSON.stringify(o);
            this.storage.setItem(NgxFirebaseAuthService.rememberKey, str);
            return o;
        });
    }
}
NgxFirebaseAuthService.rememberKey = 'ngx-firebase-auth-remember';
NgxFirebaseAuthService.decorators = [
    { type: Injectable, args: [{
                providedIn: 'root'
            },] },
];
/** @nocollapse */
NgxFirebaseAuthService.ctorParameters = () => [
    { type: AngularFireAuth }
];
/** @nocollapse */ NgxFirebaseAuthService.ngInjectableDef = defineInjectable({ factory: function NgxFirebaseAuthService_Factory() { return new NgxFirebaseAuthService(inject(AngularFireAuth)); }, token: NgxFirebaseAuthService, providedIn: "root" });

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class SignInComponent {
    /**
     * @param {?} _afAuth
     * @param {?} _svc
     * @param {?} _route
     * @param {?} _router
     */
    constructor(_afAuth, _svc, _route, _router) {
        this._afAuth = _afAuth;
        this._svc = _svc;
        this._route = _route;
        this._router = _router;
        this.ngUnsubscribe = new Subject();
        this.tosTemplate = null;
        this.success = new EventEmitter();
        this.mode = new EventEmitter();
        this.initialOAuthError = null;
        this.signedOut = false;
        this.oAuthProviderId = null;
        this.cred = null;
        this.unhandledError = null;
        this.screen = 'wait';
    }
    /**
     * @return {?}
     */
    get auth() {
        return this._afAuth.auth;
    }
    /**
     * @return {?}
     */
    get authService() {
        return this._svc;
    }
    /**
     * @return {?}
     */
    get router() {
        return this._router;
    }
    /**
     * @return {?}
     */
    get route() {
        return this._route;
    }
    /**
     * @return {?}
     */
    get queryParams() {
        return this.route.queryParams;
    }
    /**
     * @return {?}
     */
    get snapshotQueryParams() {
        return this.route.snapshot.queryParams;
    }
    /**
     * @return {?}
     */
    ngOnInit() {
        this.init();
    }
    /**
     * @return {?}
     */
    ngOnDestroy() {
        this.ngUnsubscribe.next();
        this.ngUnsubscribe.complete();
    }
    /**
     * @return {?}
     */
    init() {
        /** @type {?} */
        const rememberRecord = this.authService.getRemembered();
        this.remember = rememberRecord.remember;
        this.email = rememberRecord.email;
        return this.onInitHandleSignOut()
            .then((handled) => {
            if (handled) {
                return handled;
            }
            return this.onInitHandleOAuthRedirect();
        })
            .then((handled) => {
            if (!handled) {
                this.showSignIn();
            }
            this.queryParams.pipe(takeUntil(this.ngUnsubscribe)).subscribe(params => {
                /** @type {?} */
                const action = params["action"] || null;
                switch (action) {
                    case 'signOut':
                        this.showSignOut();
                        break;
                    case 'resetPassword':
                        this.showResetPassword();
                        break;
                    case 'signIn':
                        this.showSignIn();
                        break;
                    case 'signInPassword':
                        this.showSignInPassword();
                        break;
                    case 'signUpPassword':
                        this.showSignUpPassword();
                        break;
                    case 'signInOAuth':
                        this.showSignInOAuth(params["providerId"], null);
                        break;
                }
            });
        });
    }
    /**
     * @return {?}
     */
    onInitHandleSignOut() {
        if (this.snapshotQueryParams["action"] !== 'signOut') {
            return Promise.resolve(false);
        }
        return this.showSignOut().then(() => true);
    }
    /**
     * @return {?}
     */
    onInitHandleOAuthRedirect() {
        return new Promise(resolve => {
            /** @type {?} */
            const remember = this.route.snapshot.queryParams["remember"] === 'true';
            return this.auth.getRedirectResult()
                .then((cred) => {
                if (this.auth.currentUser && cred.user) {
                    this.authService.setRemembered(remember, cred.user.email)
                        .then(() => {
                        this.showSignInSuccess(cred);
                        resolve(true);
                    });
                }
                else {
                    resolve(false);
                }
            })
                .catch((error) => {
                this.showSignInOAuth(null, error);
                resolve(true);
            });
        });
    }
    /**
     * @return {?}
     */
    showSignOut() {
        this.signedOut = false;
        this.screen = 'wait';
        return this.auth.signOut()
            .then(() => {
            this.showSignIn(true);
        });
    }
    /**
     * @param {?=} signedOut
     * @return {?}
     */
    showSignIn(signedOut) {
        this.mode.emit('signIn');
        this.signedOut = signedOut === true;
        this.screen = 'signIn';
    }
    /**
     * @return {?}
     */
    showSignInPassword() {
        this.mode.emit('signIn');
        this.signedOut = false;
        this.screen = 'signInPassword';
    }
    /**
     * @return {?}
     */
    showSignUpPassword() {
        this.mode.emit('signIn');
        this.signedOut = false;
        this.screen = 'signUpPassword';
    }
    /**
     * @param {?} oAuthProviderId
     * @param {?} error
     * @return {?}
     */
    showSignInOAuth(oAuthProviderId, error) {
        this.mode.emit('signIn');
        this.signedOut = false;
        this.oAuthProviderId = oAuthProviderId;
        this.initialOAuthError = error;
        this.screen = 'signInOAuth';
    }
    /**
     * @param {?} cred
     * @return {?}
     */
    showSignInSuccess(cred) {
        this.mode.emit('signIn');
        this.signedOut = false;
        this.cred = cred;
        this.screen = 'signInSuccess';
        this.success.emit(cred);
    }
    /**
     * @return {?}
     */
    showResetPassword() {
        this.mode.emit('resetPassword');
        this.signedOut = false;
        this.screen = 'resetPassword';
    }
    /**
     * @param {?} error
     * @return {?}
     */
    showUnhandledError(error) {
        this.signedOut = false;
        this.unhandledError = error;
        this.screen = 'unhandledError';
    }
}
SignInComponent.decorators = [
    { type: Component, args: [{
                selector: 'ngx-firebase-auth-sign-in',
                template: `<div *ngIf="'wait' === screen" [@screen]="'in'">
  <div class="alert alert-secondary">
    <i class="fas fa-spin fa-spinner fa-fw" aria-hidden="true"></i>
    Please wait...
  </div>
</div>

<div *ngIf="'unhandledError' === screen" [@screen]="'in'">
  <div class="alert alert-danger">
    <i class="fas fa-exclamation-triangle fa-fw text-danger" aria-hidden="true"></i>
    <strong>Woops!</strong> An unexpected error occurred.
  </div>
  <p class="text-muted">
    Code: {{unhandledError.code}}. Message: {{unhandledError.message}}
  </p>
  <p>
    <a routerLink="." [queryParams]="{action: 'signIn'}">Start Over</a>
  </p>
</div>


<div *ngIf="'signInSuccess' === screen" [@screen]="'in'">
  <div class="alert alert-success">
    <i class="fas fa-check fa-fw" aria-hidden="true"></i>
    Welcome, {{cred.user.displayName}}!
  </div>
</div>




<div *ngIf="'signIn' === screen" [@screen]="'in'">
  <div class="alert alert-success" *ngIf="signedOut">
    <i class="fas fa-check fa-fw" aria-hidden="true"></i>
    You’re signed out.
  </div>
  <ngx-firebase-auth-sign-in-methods-form
    [(email)]="email"
    [(remember)]="remember"
    [oAuthProviderIds]="oAuthProviderIds"
    (error)="showUnhandledError($event)"
    (success)="showSignInSuccess($event)"></ngx-firebase-auth-sign-in-methods-form>
  <small class="text-center text-muted my-2 form-text">
    <ng-container *ngTemplateOutlet="tosTemplate"></ng-container>
  </small>
</div>

<div *ngIf="'signInPassword' === screen" [@screen]="'in'">
  <ngx-firebase-auth-sign-in-form
    [email]="email"
    [(remember)]="remember"
    (error)="showUnhandledError($event)"
    (success)="showSignInSuccess($event)"></ngx-firebase-auth-sign-in-form>
  <small class="text-center text-muted my-2 form-text">
    <ng-container *ngTemplateOutlet="tosTemplate"></ng-container>
  </small>
</div>

<div *ngIf="'signUpPassword' === screen" [@screen]="'in'">
  <ngx-firebase-auth-sign-up-form
    [email]="email"
    [(remember)]="remember"
    (error)="showUnhandledError($event)"
    (success)="showSignInSuccess($event)"></ngx-firebase-auth-sign-up-form>
  <small class="text-center text-muted my-2 form-text">
    <ng-container *ngTemplateOutlet="tosTemplate"></ng-container>
  </small>
</div>

<div *ngIf="'signInOAuth' === screen" [@screen]="'in'">
  <ngx-firebase-auth-sign-in-oauth
    [providerId]="oAuthProviderId"
    [initialError]="initialOAuthError"
    [useOAuthPopup]="useOAuthPopup"
    [oAuthProviderFactory]="oAuthProviderFactory"
    [(email)]="email"
    [(remember)]="remember"
    (error)="showUnhandledError($event)"
    (success)="showSignInSuccess($event)"></ngx-firebase-auth-sign-in-oauth>
  <small class="text-center text-muted my-2 form-text">
    <ng-container *ngTemplateOutlet="tosTemplate"></ng-container>
  </small>
</div>



<div *ngIf="'resetPassword' === screen" [@screen]="'in'">
  <h6>Reset Password</h6>
  <ngx-firebase-auth-reset-password-send-form
    [(email)]="email"
    (error)="showUnhandledError($event)"></ngx-firebase-auth-reset-password-send-form>
</div>
`,
                styles: [``],
                animations: [screenAnimation]
            },] },
];
/** @nocollapse */
SignInComponent.ctorParameters = () => [
    { type: AngularFireAuth },
    { type: NgxFirebaseAuthService },
    { type: ActivatedRoute },
    { type: Router }
];
SignInComponent.propDecorators = {
    oAuthProviderIds: [{ type: Input }],
    useOAuthPopup: [{ type: Input }],
    oAuthProviderFactory: [{ type: Input }],
    tosTemplate: [{ type: Input }],
    success: [{ type: Output }],
    mode: [{ type: Output }]
};

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class OobComponent {
    /**
     * @param {?} _route
     */
    constructor(_route) {
        this._route = _route;
        this.screen = null;
        this.mode = new EventEmitter();
        this.navigationError = new EventEmitter();
        this.success = new EventEmitter();
    }
    /**
     * @return {?}
     */
    get queryParams() {
        return this._route.snapshot.queryParams;
    }
    /**
     * @return {?}
     */
    ngOnInit() {
        this.oobCode = this.queryParams["oobCode"] || null;
        if (!this.oobCode) {
            this.navigationError.emit();
            return;
        }
        switch (this.queryParams["mode"]) {
            case 'resetPassword':
            case 'verifyEmail':
            case 'recoverEmail':
                this.screen = this.queryParams["mode"];
                this.mode.emit(this.queryParams["mode"]);
                break;
            default:
                this.navigationError.emit();
                break;
        }
    }
}
OobComponent.decorators = [
    { type: Component, args: [{
                selector: 'ngx-firebase-auth-oob',
                template: `<div *ngIf="'resetPassword' === screen" [@screen]="'in'">
  <ngx-firebase-auth-oob-reset-password
    [oobCode]="oobCode"
    (success)="success.emit($event)"></ngx-firebase-auth-oob-reset-password>
</div>

<div *ngIf="'verifyEmail' === screen" [@screen]="'in'">
  <ngx-firebase-auth-oob-verify-email
    [oobCode]="oobCode"
    (success)="success.emit($event)"></ngx-firebase-auth-oob-verify-email>
</div>

<div *ngIf="'recoverEmail' === screen" [@screen]="'in'">
  <ngx-firebase-auth-oob-recover-email
    [oobCode]="oobCode"
    (success)="success.emit($event)"></ngx-firebase-auth-oob-recover-email>
</div>
`,
                styles: [``],
                animations: [screenAnimation]
            },] },
];
/** @nocollapse */
OobComponent.ctorParameters = () => [
    { type: ActivatedRoute }
];
OobComponent.propDecorators = {
    mode: [{ type: Output }],
    navigationError: [{ type: Output }],
    success: [{ type: Output }]
};

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class NgxFirebaseAuthFormHelper {
    /**
     * @param {?} fc
     * @param {?} key
     * @param {?=} value
     * @return {?}
     */
    static setErrorUntilChanged(fc, key, value = true) {
        /** @type {?} */
        const error = {};
        error[key] = value;
        fc.setErrors(error);
        fc.valueChanges.pipe(take(1)).subscribe(() => {
            NgxFirebaseAuthFormHelper.clearError(fc, key);
        });
    }
    /**
     * @param {?} fc
     * @param {?} key
     * @return {?}
     */
    static clearError(fc, key) {
        /** @type {?} */
        const errors = {};
        if (!fc.errors) {
            return;
        }
        Object.keys(fc.errors).forEach((k) => {
            if (k !== key) {
                errors[k] = fc.errors[k];
            }
        });
        if (Object.keys(errors).length === 0) {
            fc.setErrors(null);
        }
        else {
            fc.setErrors(errors);
        }
    }
    /**
     * @param {?} fc
     * @return {?}
     */
    static requiredNonEmpty(fc) {
        /** @type {?} */
        const value = fc.value;
        if (typeof value !== 'string') {
            return null;
        }
        return value.trim().length === 0 ? { required: true } : null;
    }
}

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class SignInMethodsFormComponent {
    /**
     * @param {?} _afAuth
     * @param {?} _authService
     * @param {?} _ngZone
     */
    constructor(_afAuth, _authService, _ngZone) {
        this._afAuth = _afAuth;
        this._authService = _authService;
        this._ngZone = _ngZone;
        this.oAuthProviderIds = [];
        this.emailChange = new EventEmitter();
        this.rememberChange = new EventEmitter();
        this.success = new EventEmitter();
        this.error = new EventEmitter();
        this.formId = 'ngx-firebase-auth-sign-in-methods-form-';
        this.submitting = false;
        this.getOAuthProviderIcon = getOAuthProviderIcon;
        this.getOAuthProviderName = getOAuthProviderName;
        this.methodsForEmail = { status: 'unfetched', methods: [], email: null };
    }
    /**
     * @return {?}
     */
    get auth() {
        return this._afAuth.auth;
    }
    /**
     * @return {?}
     */
    get authService() {
        return this._authService;
    }
    /**
     * @return {?}
     */
    get methods() {
        return this.methodsForEmail.methods;
    }
    /**
     * @return {?}
     */
    get fetchStatus() {
        return this.methodsForEmail.status;
    }
    /**
     * @return {?}
     */
    get methodsFetched() {
        return this.methodsForEmail.status === 'fetched';
    }
    /**
     * @return {?}
     */
    get accountIsNew() {
        return this.methodsFetched && this.methods.length === 0;
    }
    /**
     * @return {?}
     */
    get accountExists() {
        return this.methodsFetched && this.methods.length > 0;
    }
    /**
     * @return {?}
     */
    get accountHasPassword() {
        return this.accountExists && this.methods.indexOf('password') !== -1;
    }
    /**
     * @return {?}
     */
    get accountOAuthMethods() {
        if (!this.accountExists) {
            return [];
        }
        return this.methods.filter(id => id !== 'password');
    }
    /**
     * @return {?}
     */
    ngOnInit() {
        this.emailFc = new FormControl(this.email, { validators: [Validators.required, Validators.email] });
        this.rememberFc = new FormControl(this.remember);
        this.rememberFc.valueChanges.subscribe(() => this.rememberChange.emit(this.rememberFc.value));
        this.fg = new FormGroup({ email: this.emailFc, remember: this.rememberFc });
        this.emailFc.valueChanges.subscribe(() => this.emailChange.emit(this.emailFc.value.trim()));
        this.emailFc.valueChanges.pipe(debounceTime(500)).subscribe(() => this.fetch());
        this.fetch();
    }
    /**
     * @return {?}
     */
    ngAfterViewInit() {
        this.emailInput.nativeElement.focus();
    }
    /**
     * @return {?}
     */
    fetch() {
        /** @type {?} */
        const email = this.emailFc.value.trim();
        if (email === this.methodsForEmail.email) {
            return;
        }
        if ('fetching' === this.methodsForEmail.status) {
            return;
        }
        this.methodsForEmail = { status: 'fetching', methods: [], email: email };
        if (this.emailFc.invalid) {
            this.methodsForEmail = { status: 'unfetched', methods: [], email: email };
            return;
        }
        this.auth.fetchSignInMethodsForEmail(email)
            .then(results => {
            this.methodsForEmail = { status: 'fetched', methods: results, email: email };
        })
            .catch((error) => {
            this.emailFc.markAsDirty();
            this.emailFc.markAsTouched();
            switch (error.code) {
                case 'auth/invalid-email':
                    NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.emailFc, error.code);
                    break;
            }
            this.methodsForEmail = { email: this.email, status: 'unfetched', methods: [] };
        });
    }
}
SignInMethodsFormComponent.decorators = [
    { type: Component, args: [{
                selector: 'ngx-firebase-auth-sign-in-methods-form',
                template: `<form [formGroup]="fg">
  <div class="form-group">
    <label [attr.for]="formId + 'email'">Email Address</label>
    <input
      #emailInput
      [attr.id]="formId + 'email'"
      [attr.aria-describedby]="formId + 'email'"
      type="email"
      autocomplete="email"
      placeholder="Email Address"
      formControlName="email"
      (blur)="fetch()"
      (keyup.enter)="emailInput.blur()"
      class="form-control"
      [class.is-invalid]="emailFc.touched && emailFc.invalid">
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.touched && emailFc.hasError('required')">
      Required.
    </div>
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.touched && emailFc.hasError('email')">
      Invalid email.
    </div>
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.touched && emailFc.hasError('auth/invalid-email')">
      Invalid email.
    </div>
    <small class="text-muted form-text" [attr.id]="formId + 'email'" [ngSwitch]="fetchStatus">
      <span *ngSwitchCase="'unfetched'" [@fadeInOut]="'in'">
        To get started, enter your email address.
        If you don’t yet have an account we’ll create one for you.
      </span>
      <span *ngSwitchCase="'fetching'" [@fadeInOut]="'in'">
        <i class="fas fa-spin fa-spinner fa-fw" aria-hidden="true"></i>
        Looking up account...
      </span>
      <span *ngSwitchCase="'fetched'" [@fadeInOut]="'in'">
        <i class="fas fa-check fa-fw text-success" aria-hidden="true"></i>
        <span *ngIf="accountExists">Account found.</span>
        <span *ngIf="accountIsNew">We'll create an account.</span>
      </span>
    </small>
  </div>
  <div class="form-group">
    <div class="form-check">
      <input
        class="form-check-input"
        type="checkbox"
        [value]="true"
        formControlName="remember"
        [attr.id]="formId + 'remember'">
      <label class="form-check-label" [attr.for]="formId + 'remember'">
        Remember me on this device.
      </label>
    </div>
  </div>
</form>
<div *ngIf="methodsFetched && accountExists" [@screen]="'in'">
  <small class="text-muted mb-1 form-text">
    <span *ngIf="accountHasPassword">
      <span *ngIf="accountOAuthMethods.length === 0">
        Please sign in with your password...
      </span>
      <span *ngIf="accountOAuthMethods.length === 1">
        Please sign in with your password or your
        linked {{getOAuthProviderName(accountOAuthMethods[0])}} account...
      </span>
      <span *ngIf="accountOAuthMethods.length > 1">
        Please sign in with your password or one of your linked accounts...
      </span>
    </span>
    <span *ngIf="!accountHasPassword">
      <span *ngIf="accountOAuthMethods.length === 1">
        Please sign in with your
        linked {{getOAuthProviderName(accountOAuthMethods[0])}} account...
      </span>
      <span *ngIf="accountOAuthMethods.length > 1">
        Please sign in with one of your linked accounts...
      </span>
    </span>

  </small>

  <div class="list-group">
    <a
      *ngIf="accountHasPassword"
      routerLink="."
      [queryParams]="{action: 'signInPassword'}"
      class="list-group-item list-group-item-action">
      <i class="fas fa-lock fa-fw" aria-hidden="true"></i>
      <span class="ml-2">
        Sign In with Your Password
      </span>
    </a>
    <a
      *ngFor="let id of accountOAuthMethods"
      routerLink="."
      [queryParams]="{action: 'signInOAuth', providerId: id}"
      class="list-group-item list-group-item-action">
      <i [attr.class]="getOAuthProviderIcon(id)" aria-hidden="true"></i>
      <span class="ml-2">
        Sign In with {{getOAuthProviderName(id)}}
      </span>
    </a>
  </div>
</div>

<div *ngIf="methodsFetched && accountIsNew" [@screen]="'in'">
  <small class="text-muted mb-1 form-text">
    <span *ngIf="oAuthProviderIds.length === 0">
      Please create an account...
    </span>
    <span *ngIf="oAuthProviderIds.length === 1">
      Please sign up with your
      {{getOAuthProviderName(oAuthProviderIds[0])}} account,
      or create a separate account with a password....
    </span>
    <span *ngIf="oAuthProviderIds.length >1">
      Please sign up with one of the services listed below,
      or create a separate account with a password....
    </span>
  </small>
  <div class="list-group">

    <a
      *ngFor="let id of oAuthProviderIds"
      routerLink="."
      [queryParams]="{action: 'signInOAuth', providerId: id}"
      class="list-group-item list-group-item-action">
      <i [attr.class]="getOAuthProviderIcon(id)" aria-hidden="true"></i>
      <span class="ml-2">
        Sign Up with {{getOAuthProviderName(id)}}
      </span>
    </a>
    <a
      routerLink="."
      [queryParams]="{action: 'signUpPassword'}"
      class="list-group-item list-group-item-action">
      <i class="fas fa-lock fa-fw" aria-hidden="true"></i>
      <span class="ml-2">
        Create
        <span *ngIf="oAuthProviderIds.length > 0">
          a Separate
        </span>
        Account
      </span>
    </a>
  </div>
</div>
`,
                styles: [``],
                animations: [fadeInOutAnimation, screenAnimation]
            },] },
];
/** @nocollapse */
SignInMethodsFormComponent.ctorParameters = () => [
    { type: AngularFireAuth },
    { type: NgxFirebaseAuthService },
    { type: NgZone }
];
SignInMethodsFormComponent.propDecorators = {
    emailInput: [{ type: ViewChild, args: ['emailInput',] }],
    email: [{ type: Input }],
    remember: [{ type: Input }],
    oAuthProviderIds: [{ type: Input }],
    emailChange: [{ type: Output }],
    rememberChange: [{ type: Output }],
    success: [{ type: Output }],
    error: [{ type: Output }]
};

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class SignInFormComponent {
    /**
     * @param {?} _afAuth
     * @param {?} _authService
     */
    constructor(_afAuth, _authService) {
        this._afAuth = _afAuth;
        this._authService = _authService;
        this.rememberChange = new EventEmitter();
        this.success = new EventEmitter();
        this.error = new EventEmitter();
        this.formId = 'ngx-firebase-auth-sign-in-form-';
        this.submitting = false;
        this.methodsForEmail = [];
        this.getOAuthProviderIcon = getOAuthProviderIcon;
        this.getOAuthProviderName = getOAuthProviderName;
    }
    /**
     * @return {?}
     */
    get auth() {
        return this._afAuth.auth;
    }
    /**
     * @return {?}
     */
    get authService() {
        return this._authService;
    }
    /**
     * @return {?}
     */
    ngOnInit() {
        this.emailFc = new FormControl(this.email, { validators: [Validators.required, Validators.email] });
        this.passwordFc = new FormControl('', { validators: [Validators.required] });
        this.rememberFc = new FormControl(this.remember);
        this.rememberFc.valueChanges.subscribe(val => this.rememberChange.emit(val));
        this.fg = new FormGroup({
            email: this.emailFc,
            password: this.passwordFc,
            remember: this.rememberFc
        });
    }
    /**
     * @return {?}
     */
    ngAfterViewInit() {
        this.passwordInput.nativeElement.focus();
    }
    /**
     * @return {?}
     */
    submit() {
        /** @type {?} */
        const email = this.emailFc.value.trim();
        this.submitting = true;
        this.methodsForEmail = [];
        /** @type {?} */
        let cred;
        this.auth.fetchSignInMethodsForEmail(email)
            .then(results => {
            this.methodsForEmail = results;
            if (results.length === 0) {
                return Promise.reject({
                    code: 'auth/user-not-found'
                });
            }
            if (results.indexOf('password') === -1) {
                return Promise.reject({
                    code: 'ngx-firebase-auth/no-password',
                });
            }
            return this.auth.signInWithEmailAndPassword(email, this.passwordFc.value);
        })
            .then(result => {
            cred = result;
            return this.authService.setRemembered(this.rememberFc.value === true, email);
        })
            .then(() => {
            this.success.emit(cred);
        })
            .catch(error => {
            this.submitting = false;
            this.emailFc.markAsDirty();
            this.emailFc.markAsTouched();
            this.passwordFc.markAsDirty();
            this.passwordFc.markAsTouched();
            switch (error.code) {
                case 'auth/invalid-email':
                case 'auth/user-not-found':
                case 'auth/user-disabled':
                case 'ngx-firebase-auth/no-password':
                    NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.emailFc, error.code);
                    break;
                case 'auth/wrong-password':
                    NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.passwordFc, error.code);
                    break;
                default:
                    this.error.emit(error);
                    break;
            }
        });
    }
}
SignInFormComponent.decorators = [
    { type: Component, args: [{
                selector: 'ngx-firebase-auth-sign-in-form',
                template: `<form [formGroup]="fg" (ngSubmit)="submit()">

  <div class="form-group">
    <label [attr.for]="formId + 'email'">Email Address</label>

    <input
      readonly
      #emailInput
      [attr.id]="formId + 'email'"
      [attr.aria-describedby]="formId + 'email'"
      type="email"
      autocomplete="email"
      placeholder="Email Address"
      formControlName="email"
      class="form-control">
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.hasError('required')">
      Required.
    </div>
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.hasError('email')">
      Invalid email.
    </div>
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.hasError('auth/invalid-email')">
      Invalid email.
    </div>
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.hasError('auth/user-not-found')">
      We could not find an account with that email address.
      <a routerLink="." [queryParams]="{action: 'signIn'}">Create Account</a>
    </div>
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.hasError('auth/user-disabled')">
      The account with that email address has been disabled.
    </div>
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.hasError('ngx-firebase-auth/no-password')">
      The account with that email address does not have a password.
      Please sign in using:
      <span *ngFor="let id of methodsForEmail; let isLast = last">
        <a routerLink="." [queryParams]="{action: 'signInOAuth', providerId: id}">{{getOAuthProviderName(id)}}</a>
        <span *ngIf="!isLast">
          |
        </span>
      </span>
    </div>

    <small class="text-muted form-text" [attr.id]="formId + 'email'" >
      Not your email address?
      <a routerLink="." [queryParams]="{action: 'signIn'}">Start Over</a>
    </small>
  </div>


  <div class="form-group">
    <div class="d-flex justify-content-between align-items-end">
      <label [attr.for]="formId + 'password'">Password</label>
      <small>
        <a (click)="$event.preventDefault(); passwordInput.type = 'password' === passwordInput.type  ? 'text' : 'password'"
          href="#" tabindex="-1" class="d-inline-block">
          <span *ngIf="'password' === passwordInput.type">Show</span>
          <span *ngIf="'text' === passwordInput.type">Hide</span>
        </a>
      </small>
    </div>
    <input
      #passwordInput
      [attr.id]="formId + 'password'"
      [attr.aria-describedby]="formId + 'password-help'"
      type="password"
      formControlName="password"
      placeholder="Password"
      autocomplete="password"
      class="form-control"
      [class.is-invalid]="passwordFc.touched && passwordFc.invalid">
    <div class="invalid-feedback"
      *ngIf="passwordFc.touched && passwordFc.hasError('required')"
      [@fadeInOut]="'in'">
      Required.
    </div>
    <div class="invalid-feedback"
      *ngIf="passwordFc.touched && passwordFc.hasError('auth/wrong-password')"
      [@fadeInOut]="'in'">
      Wrong password.
    </div>
    <small [attr.id]="formId + 'password-help'" class="form-text text-muted">
      Forgot? <a routerLink="." [queryParams]="{action: 'resetPassword'}">Reset Password</a>
    </small>
  </div>
  <div class="form-group">
    <div class="form-check">
      <input
        class="form-check-input"
        type="checkbox"
        [value]="true"
        formControlName="remember"
        [attr.id]="formId + 'remember'">
      <label class="form-check-label" [attr.for]="formId + 'remember'">
        Remember me on this device.
      </label>
    </div>
  </div>
  <div class="form-group">
    <button type="submit"
      class="btn btn-success btn-block"
      [disabled]="fg.invalid || submitting">
      <i class="fas fa-lock fa-fw" aria-hidden="true"></i>
      Sign In
    </button>
  </div>
</form>
`,
                styles: [``],
                animations: [fadeInOutAnimation]
            },] },
];
/** @nocollapse */
SignInFormComponent.ctorParameters = () => [
    { type: AngularFireAuth },
    { type: NgxFirebaseAuthService }
];
SignInFormComponent.propDecorators = {
    passwordInput: [{ type: ViewChild, args: ['passwordInput',] }],
    email: [{ type: Input }],
    remember: [{ type: Input }],
    rememberChange: [{ type: Output }],
    success: [{ type: Output }],
    error: [{ type: Output }]
};

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class SignUpFormComponent {
    /**
     * @param {?} _afAuth
     * @param {?} _authService
     */
    constructor(_afAuth, _authService) {
        this._afAuth = _afAuth;
        this._authService = _authService;
        this.rememberChange = new EventEmitter();
        this.success = new EventEmitter();
        this.error = new EventEmitter();
        this.formId = 'ngx-firebase-auth-sign-up-form-';
        this.submitting = false;
    }
    /**
     * @return {?}
     */
    get auth() {
        return this._afAuth.auth;
    }
    /**
     * @return {?}
     */
    get authService() {
        return this._authService;
    }
    /**
     * @return {?}
     */
    ngOnInit() {
        this.emailFc = new FormControl(this.email, { validators: [Validators.required, Validators.email] });
        this.passwordFc = new FormControl('', { validators: [Validators.required] });
        this.nameFc = new FormControl('', { validators: [Validators.required, NgxFirebaseAuthFormHelper.requiredNonEmpty] });
        this.rememberFc = new FormControl(this.remember);
        this.rememberFc.valueChanges.subscribe(val => this.rememberChange.emit(val));
        this.fg = new FormGroup({
            email: this.emailFc,
            password: this.passwordFc,
            name: this.nameFc,
            remember: this.rememberFc
        });
    }
    /**
     * @return {?}
     */
    ngAfterViewInit() {
        this.passwordInput.nativeElement.focus();
    }
    /**
     * @return {?}
     */
    submit() {
        this.submitting = true;
        /** @type {?} */
        let cred;
        this.auth.fetchSignInMethodsForEmail(this.email)
            .then((results) => {
            if (results.length > 0) {
                return Promise.reject({
                    code: 'ngx-firebase-auth/account-exists'
                });
            }
            return this.auth.createUserWithEmailAndPassword(this.email, this.passwordFc.value);
        })
            .then(result => {
            cred = result;
            return cred.user.updateProfile({ displayName: this.nameFc.value.trim(), photoURL: null });
        })
            .then(() => {
            return this.authService.setRemembered(this.rememberFc.value === true, this.email);
        })
            .then(() => {
            this.success.emit(cred);
        })
            .catch(error => {
            this.submitting = false;
            this.emailFc.markAsDirty();
            this.emailFc.markAsTouched();
            this.passwordFc.markAsDirty();
            this.passwordFc.markAsTouched();
            switch (error.code) {
                case 'auth/invalid-email':
                case 'ngx-firebase-auth/account-exists':
                    NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.emailFc, error.code);
                    break;
                case 'auth/weak-password':
                    NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.passwordFc, error.code);
                    break;
                default:
                    this.error.emit(error);
                    break;
            }
        });
    }
}
SignUpFormComponent.decorators = [
    { type: Component, args: [{
                selector: 'ngx-firebase-auth-sign-up-form',
                template: `<form [formGroup]="fg" (ngSubmit)="submit()">
  <div class="form-group">
    <label [attr.for]="formId + 'email'">Email Address</label>
    <input
      readonly
      #emailInput
      [attr.id]="formId + 'email'"
      [attr.aria-describedby]="formId + 'email'"
      type="email"
      autocomplete="email"
      placeholder="Email Address"
      formControlName="email"
      class="form-control">
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.hasError('required')">
      Required.
    </div>
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.hasError('email')">
      Invalid email.
    </div>
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.hasError('auth/invalid-email')">
      Invalid email.
    </div>
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.hasError('ngx-firebase-auth/account-exists')">
      We found an account with that email address.
      <a routerLink="." [queryParams]="{action: 'signIn'}">Sign In</a>
    </div>
    <small class="text-muted form-text" [attr.id]="formId + 'email'" >
      Not your email address?
      <a routerLink="." [queryParams]="{action: 'signIn'}">Go Back</a>
    </small>
  </div>

  <div class="form-group">
    <div class="d-flex justify-content-between align-items-end">
      <label [attr.for]="formId + 'password'">Choose Password</label>
      <small>
        <a (click)="$event.preventDefault(); passwordInput.type = 'password' === passwordInput.type  ? 'text' : 'password'"
          href="#" tabindex="-1" class="d-inline-block">
          <span *ngIf="'password' === passwordInput.type">Show</span>
          <span *ngIf="'text' === passwordInput.type">Hide</span>
        </a>
      </small>
    </div>
    <input
      #passwordInput
      [attr.id]="formId + 'password'"
      [attr.aria-describedby]="formId + 'password-help'"
      type="password"
      formControlName="password"
      placeholder="Choose Password"
      autocomplete="password"
      class="form-control"
      [class.is-invalid]="passwordFc.touched && passwordFc.invalid">
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="passwordFc.touched && passwordFc.hasError('required')">
      Required.
    </div>
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="passwordFc.touched && passwordFc.hasError('auth/wrong-password')">
      Wrong password.
    </div>
    <small [attr.id]="formId + 'password-help'" class="form-text text-muted">
      Please choose a strong password.
    </small>
  </div>
  <div class="form-group">
    <label [attr.for]="formId + 'name'">Your Name</label>
    <input
      [attr.id]="formId + 'name'"
      type="text"
      formControlName="name"
      placeholder="Your Name"
      class="form-control"
      [class.is-invalid]="nameFc.touched && nameFc.invalid">
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="nameFc.touched && nameFc.hasError('required')">
      Required.
    </div>
  </div>
  <div class="form-group">
    <div class="form-check">
      <input
        class="form-check-input"
        type="checkbox"
        [value]="true"
        formControlName="remember"
        [attr.id]="formId + 'remember'">
      <label class="form-check-label" [attr.for]="formId + 'remember'">
        Remember me on this device.
      </label>
    </div>
  </div>
  <div class="form-group">
    <button type="submit"
      class="btn btn-success btn-block"
      [disabled]="fg.invalid || submitting">
      <i class="fas fa-lock fa-fw" aria-hidden="true"></i>
      Create Account
    </button>
  </div>
</form>
`,
                styles: [``],
                animations: [fadeInOutAnimation]
            },] },
];
/** @nocollapse */
SignUpFormComponent.ctorParameters = () => [
    { type: AngularFireAuth },
    { type: NgxFirebaseAuthService }
];
SignUpFormComponent.propDecorators = {
    passwordInput: [{ type: ViewChild, args: ['passwordInput',] }],
    email: [{ type: Input }],
    remember: [{ type: Input }],
    rememberChange: [{ type: Output }],
    success: [{ type: Output }],
    error: [{ type: Output }]
};

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class ResetPasswordSendFormComponent {
    /**
     * @param {?} _afAuth
     */
    constructor(_afAuth) {
        this._afAuth = _afAuth;
        this.emailChange = new EventEmitter();
        this.error = new EventEmitter();
        this.formId = 'ngx-firebase-auth-reset-password-send-form-';
        this.submitting = false;
        this.sent = null;
    }
    /**
     * @return {?}
     */
    get auth() {
        return this._afAuth.auth;
    }
    /**
     * @return {?}
     */
    ngOnInit() {
        this.emailFc = new FormControl(this.email, { validators: [Validators.required, Validators.email] });
        this.emailFc.valueChanges.subscribe(() => this.emailChange.emit(this.emailFc.value.trim()));
        this.fg = new FormGroup({ email: this.emailFc });
    }
    /**
     * @return {?}
     */
    ngAfterViewInit() {
        this.emailInput.nativeElement.focus();
    }
    /**
     * @return {?}
     */
    submit() {
        /** @type {?} */
        const email = this.emailFc.value.trim();
        this.submitting = true;
        this.sent = null;
        this.auth.sendPasswordResetEmail(email)
            .then(() => {
            this.submitting = false;
            this.sent = email;
        })
            .catch((error) => {
            this.submitting = false;
            this.emailFc.markAsTouched();
            this.emailFc.markAsDirty();
            switch (error.code) {
                case 'auth/invalid-email':
                case 'auth/user-not-found':
                    NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.emailFc, error.code);
                    break;
                default:
                    this.error.emit(error);
                    break;
            }
        });
    }
}
ResetPasswordSendFormComponent.decorators = [
    { type: Component, args: [{
                selector: 'ngx-firebase-auth-reset-password-send-form',
                template: `<form [formGroup]="fg" (ngSubmit)="submit()">
  <div *ngIf="sent" [@fadeInOut]="'in'">
    <div class="alert alert-success">
      <i class="fas fa-check fa-fw" aria-hidden="true"></i>
      We’ve sent a reset password link to {{sent}}.
      Please allow a few moments for the email to arrive.
    </div>
  </div>

  <div class="form-group">
    <label [attr.for]="formId + 'email'">Email Address</label>
    <input
      #emailInput
      [attr.id]="formId + 'email'"
      [attr.aria-describedby]="formId + 'email-help'"
      type="email"
      formControlName="email"
      class="form-control"
      [class.is-invalid]="emailFc.touched && emailFc.invalid">
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.touched && emailFc.hasError('required')">
      Required.
    </div>
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.touched && emailFc.hasError('auth/user-not-found')">
      We could not find an account with that email address.
      Please <a routerLink="." [queryParams]="{action: 'signIUpPassword'}">sign up</a>.
    </div>
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.touched && emailFc.hasError('email')">
      Invalid email.
    </div>
    <div class="invalid-feedback" [@fadeInOut]="'in'"
      *ngIf="emailFc.touched && emailFc.hasError('auth/invalid-email')">
      Invalid email.
    </div>
    <small [attr.id]="formId + 'email-help'" class="form-text text-muted">
      Enter the email address you used to sign up. We’ll
      send a reset password link to that address.
    </small>
  </div>
  <div class="form-group">
    <button type="submit"
      class="btn btn-block btn-success"
      [disabled]="fg.invalid || submitting">
      <i class="fas fa-fw fa-envelope" aria-hidden="true"></i>
      Send Link
    </button>
  </div>
</form>
`,
                styles: [``],
                animations: [fadeInOutAnimation]
            },] },
];
/** @nocollapse */
ResetPasswordSendFormComponent.ctorParameters = () => [
    { type: AngularFireAuth }
];
ResetPasswordSendFormComponent.propDecorators = {
    emailInput: [{ type: ViewChild, args: ['emailInput',] }],
    email: [{ type: Input }],
    emailChange: [{ type: Output }],
    error: [{ type: Output }]
};

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class SignInOauthComponent {
    /**
     * @param {?} _afAuth
     * @param {?} _svc
     * @param {?} _route
     * @param {?} _router
     */
    constructor(_afAuth, _svc, _route, _router) {
        this._afAuth = _afAuth;
        this._svc = _svc;
        this._route = _route;
        this._router = _router;
        this.success = new EventEmitter();
        this.emailChange = new EventEmitter();
        this.rememberChange = new EventEmitter();
        this.error = new EventEmitter();
        this.screen = 'wait';
        this.methodError = null;
        this.getOAuthProviderIcon = getOAuthProviderIcon;
        this.getOAuthProviderName = getOAuthProviderName;
        this.formId = 'ngx-firebase-auth-sign-in-oauth-';
    }
    /**
     * @return {?}
     */
    get auth() {
        return this._afAuth.auth;
    }
    /**
     * @return {?}
     */
    get authService() {
        return this._svc;
    }
    /**
     * @return {?}
     */
    get route() {
        return this._route;
    }
    /**
     * @return {?}
     */
    get router() {
        return this._router;
    }
    /**
     * @return {?}
     */
    ngOnInit() {
        this.rememberFc = new FormControl(this.remember);
        this.rememberFc.valueChanges.subscribe(val => this.rememberChange.emit(val));
        this.fg = new FormGroup({
            remember: this.rememberFc
        });
        if (this.initialError) {
            this.handleOAuthError(this.initialError);
        }
        else {
            this.oAuthSignIn(this.providerId);
        }
    }
    /**
     * @param {?} id
     * @param {?=} forceRedirect
     * @return {?}
     */
    oAuthSignIn(id, forceRedirect) {
        this.methodError = null;
        /** @type {?} */
        let cred;
        if (this.useOAuthPopup && forceRedirect !== true) {
            this.getOAuthProvider(id)
                .then(provider => {
                return this.auth.signInWithPopup(provider);
            })
                .then((result) => {
                cred = result;
                return this.authService.setRemembered(this.rememberFc.value === true, result.user.email);
            })
                .then(() => {
                this.success.emit(cred);
            })
                .catch(error => this.handleOAuthError(error, id));
        }
        else {
            this.router.navigate(['.'], { relativeTo: this.route, queryParams: { remember: this.rememberFc.value === true } })
                .then(() => {
                return this.getOAuthProvider(id);
            })
                .then(provider => {
                return this.auth.signInWithRedirect(provider);
            })
                .catch(error => this.handleOAuthError(error, id));
        }
    }
    /**
     * @param {?} error
     * @param {?=} providerId
     * @return {?}
     */
    handleOAuthError(error, providerId) {
        if (error['email'] && error['credential']) {
            this.emailChange.emit(error['email']);
            this.auth.fetchSignInMethodsForEmail(error['email'])
                .then(results => {
                error['methods'] = results;
                error['accountHasPassword'] = results.indexOf('password') !== -1;
                error['accountOAuthMethods'] = results.filter(id => id !== 'password');
                this.methodError = error;
                this.screen = 'methodError';
            });
            return;
        }
        switch (error.code) {
            case 'auth/cancelled-popup-request':
            case 'auth/popup-closed-by-user':
                this.screen = 'retry';
                break;
            case 'auth/popup-blocked':
                this.oAuthSignIn(providerId, true);
                break;
            default:
                this.error.emit(error);
                break;
        }
    }
    /**
     * @param {?} id
     * @return {?}
     */
    getOAuthProvider(id) {
        /** @type {?} */
        let provider = null;
        if (this.oAuthProviderFactory) {
            provider = this.oAuthProviderFactory(id);
        }
        if (!provider) {
            switch (id) {
                case 'twitter.com':
                    provider = new auth.TwitterAuthProvider();
                    break;
                case 'facebook.com':
                    provider = new auth.FacebookAuthProvider();
                    break;
                case 'google.com':
                    provider = new auth.GoogleAuthProvider();
                    break;
                case 'github.com':
                    provider = new auth.GithubAuthProvider();
                    break;
            }
        }
        if (provider) {
            return Promise.resolve(provider);
        }
        else {
            return Promise.reject({
                code: 'ngx-firebase-auth/no-provider-found',
                message: `We could not create an OAuth provider for provider id "${id}".`
            });
        }
    }
}
SignInOauthComponent.decorators = [
    { type: Component, args: [{
                selector: 'ngx-firebase-auth-sign-in-oauth',
                template: `<div *ngIf="'wait' === screen" [@screen]="'in'">
  <div class="alert alert-secondary">
    <i class="fas fa-spin fa-spinner fa-fw" aria-hidden="true"></i>
    Please wait...
  </div>
</div>

<div *ngIf="'methodError' === screen" [@screen]="'in'">
  <div class="alert alert-danger">
    <i class="fas fa-exclamation-triangle fa-fw" aria-hidden="true"></i>
    We could not sign you in with {{methodError.credential.providerId}}.
  </div>

  <p class="text-muted">
    Please sign in with one of the methods associated with
    {{methodError.email}}:
  </p>

  <div class="list-group">
    <a
      *ngIf="methodError.accountHasPassword"
      routerLink="."
      [queryParams]="{action: 'signInPassword'}"
      class="list-group-item list-group-item-action">
      <i class="fas fa-unlock" aria-hidden="true"></i>
      <span class="ml-2">Sign In with Your Password</span>
    </a>
    <button
      *ngFor="let id of methodError.accountOAuthMethods"
      (click)="oAuthSignIn(id)"
      class="list-group-item list-group-item-action">
      <i [attr.class]="getOAuthProviderIcon(id)" aria-hidden="true"></i>
      <span class="ml-2">Sign In with {{getOAuthProviderName(id)}}</span>
    </button>
  </div>

  <form [formGroup]="fg">
    <div class="form-group">
      <div class="form-check">
        <input
          class="form-check-input"
          type="checkbox"
          [value]="true"
          formControlName="remember"
          [attr.id]="formId + 'remember'">
        <label class="form-check-label" [attr.for]="formId + 'remember'">
          Remember me on this device.
        </label>
      </div>
    </div>
  </form>

  <p class="text-muted">
    Is {{methodError.email}} not your email address?
    <a routerLink="." [queryParams]="{action: 'signIn'}">Start Over</a>
  </p>

</div>

<div *ngIf="'retry' === screen" [@screen]="'in'">
  <div class="alert alert-danger">
    <i class="fas fa-exclamation-triangle fa-fw" aria-hidden="true"></i>
    It looks like you cancelled signing in with
    {{getOAuthProviderName(providerId)}}. Try again:
  </div>

  <div class="list-group">
    <button
      (click)="oAuthSignIn(providerId)"
      class="list-group-item list-group-item-action">
      <i [attr.class]="getOAuthProviderIcon(providerId)" aria-hidden="true"></i>
      <span class="ml-2">Sign In with {{getOAuthProviderName(providerId)}}</span>
    </button>
  </div>

  <form [formGroup]="fg">
    <div class="form-group">
      <div class="form-check">
        <input
          class="form-check-input"
          type="checkbox"
          [value]="true"
          formControlName="remember"
          [attr.id]="formId + 'remember'">
        <label class="form-check-label" [attr.for]="formId + 'remember'">
          Remember me on this device.
        </label>
      </div>
    </div>
  </form>


  <p class="text-muted">
    <a routerLink="." [queryParams]="{action: 'signIn'}">Start Over</a>
  </p>

</div>
`,
                styles: [``],
                animations: [screenAnimation]
            },] },
];
/** @nocollapse */
SignInOauthComponent.ctorParameters = () => [
    { type: AngularFireAuth },
    { type: NgxFirebaseAuthService },
    { type: ActivatedRoute },
    { type: Router }
];
SignInOauthComponent.propDecorators = {
    providerId: [{ type: Input }],
    initialError: [{ type: Input }],
    useOAuthPopup: [{ type: Input }],
    oAuthProviderFactory: [{ type: Input }],
    email: [{ type: Input }],
    remember: [{ type: Input }],
    success: [{ type: Output }],
    emailChange: [{ type: Output }],
    rememberChange: [{ type: Output }],
    error: [{ type: Output }]
};

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class NgxFirebaseAuthModule {
}
NgxFirebaseAuthModule.decorators = [
    { type: NgModule, args: [{
                imports: [
                    CommonModule
                ],
                providers: [
                    NgxFirebaseAuthService
                ]
            },] },
];

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class NgxFirebaseAuthSignInModule {
}
NgxFirebaseAuthSignInModule.decorators = [
    { type: NgModule, args: [{
                imports: [
                    CommonModule,
                    ReactiveFormsModule,
                    RouterModule,
                    NgxFirebaseAuthModule
                ],
                declarations: [
                    SignInComponent,
                    SignInMethodsFormComponent,
                    SignInFormComponent,
                    SignUpFormComponent,
                    ResetPasswordSendFormComponent,
                    SignInOauthComponent,
                ],
                exports: [
                    SignInComponent,
                ]
            },] },
];

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class OobResetPasswordComponent {
    /**
     * @param {?} _afAuth
     * @param {?} _authService
     */
    constructor(_afAuth, _authService) {
        this._afAuth = _afAuth;
        this._authService = _authService;
        this.success = new EventEmitter();
        this.screen = 'wait';
        this.submitting = false;
        this.formId = 'ngx-firebase-auth-oob-reset-password-';
        this.unhandledError = null;
        this.cred = null;
    }
    /**
     * @return {?}
     */
    get auth() {
        return this._afAuth.auth;
    }
    /**
     * @return {?}
     */
    get authService() {
        return this._authService;
    }
    /**
     * @return {?}
     */
    ngOnInit() {
        /** @type {?} */
        const remembered = this.authService.getRemembered();
        this.emailFc = new FormControl('');
        this.passwordFc = new FormControl('', { validators: [Validators.required] });
        this.rememberFc = new FormControl(remembered.remember);
        this.fg = new FormGroup({ email: this.emailFc, password: this.passwordFc, remember: this.rememberFc });
        this.auth.checkActionCode(this.oobCode)
            .then((result) => {
            this.info = result;
            this.emailFc.setValue(result.data.email);
            this.screen = 'form';
        })
            .catch((error) => {
            this.unhandledError = error;
            this.screen = 'error';
        });
    }
    /**
     * @return {?}
     */
    submit() {
        this.submitting = true;
        this.auth.confirmPasswordReset(this.oobCode, this.passwordFc.value)
            .then(() => {
            return this.auth.signInWithEmailAndPassword(this.info.data.email, this.passwordFc.value);
        })
            .then((cred) => {
            this.cred = cred;
            return this.authService.setRemembered(this.rememberFc.value === true, this.info.data.email);
        })
            .then(() => {
            this.screen = 'success';
            this.success.emit({
                mode: 'resetPassword',
                info: this.info,
                cred: this.cred,
                user: this.cred.user
            });
        })
            .catch((error) => {
            this.submitting = false;
            this.passwordFc.markAsDirty();
            this.passwordFc.markAsTouched();
            switch (error.code) {
                case 'auth/weak-password':
                    NgxFirebaseAuthFormHelper.setErrorUntilChanged(this.passwordFc, error.code);
                    break;
                default:
                    this.unhandledError = error;
                    this.screen = 'error';
                    break;
            }
        });
    }
}
OobResetPasswordComponent.decorators = [
    { type: Component, args: [{
                selector: 'ngx-firebase-auth-oob-reset-password',
                template: `<div *ngIf="'wait' === screen" [@screen]="'in'">
  <div class="alert alert-secondary">
    <i class="fas fa-spin fa-spinner fa-fw" aria-hidden="true"></i>
    Please wait...
  </div>
</div>

<div *ngIf="'success' === screen" [@screen]="'in'">
  <div class="alert alert-success">
    <i class="fas fa-check fa-fw" aria-hidden="true"></i>
    Welcome, {{cred.user.displayName}}!
    Your new password has been saved and you are signed in.
  </div>
</div>

<div *ngIf="screen === 'error'" [@screen]="'in'">
  <div class="alert alert-danger">
    <p>
      <i class="fas fa-exclamation-triangle fa-fw" aria-hidden="true"></i>
      Woops! An error occurred.
    </p>
    <div [ngSwitch]="unhandledError.code">
      <p class="mb-0" *ngSwitchCase="'auth/expired-action-code'">
        The reset password link you used has expired.
      </p>
      <p class="mb-0" *ngSwitchCase="'auth/invalid-action-code'">
        The reset password link you used is not valid. This may be because it
        has already been used.
      </p>
      <p class="mb-0" *ngSwitchCase="'auth/user-disabled'">
        The account associated with the reset password link you used has been disabled.
      </p>
      <p class="mb-0" *ngSwitchCase="'auth/user-not-found'">
        The account associated with the reset password link you used has been removed.
      </p>
      <div *ngSwitchDefault>
        <p>Code: {{unhandledError.code}}</p>
        <p class="mb-0">
          Message: {{unhandledError.message}}
        </p>
      </div>
    </div>
  </div>
</div>


<div *ngIf="'form' === screen" [@screen]="'in'">
  <form [formGroup]="fg" (ngSubmit)="submit()">
    <div class="form-group">
      <label [attr.for]="formId + 'email'">Email Address</label>

      <input
        readonly
        #emailInput
        [attr.id]="formId + 'email'"
        [attr.aria-describedby]="formId + 'email'"
        type="email"
        autocomplete="email"
        placeholder="Email Address"
        formControlName="email"
        class="form-control">
      <small class="text-muted form-text" [attr.id]="formId + 'email'" >
        You are resetting the password for {{emailFc.value}}.
      </small>
    </div>

    <div class="form-group">
      <div class="d-flex justify-content-between align-items-end">
        <label [attr.for]="formId + 'password'">Password</label>
        <small>
          <a (click)="$event.preventDefault(); passwordInput.type = 'password' === passwordInput.type  ? 'text' : 'password'"
            href="#" tabindex="-1" class="d-inline-block">
            <span *ngIf="'password' === passwordInput.type">Show</span>
            <span *ngIf="'text' === passwordInput.type">Hide</span>
          </a>
        </small>
      </div>
      <input
        #passwordInput
        [attr.id]="formId + 'password'"
        [attr.aria-describedby]="formId + 'password-help'"
        type="password"
        formControlName="password"
        placeholder="Password"
        autocomplete="password"
        class="form-control"
        [class.is-invalid]="passwordFc.touched && passwordFc.invalid">
      <div class="invalid-feedback" *ngIf="passwordFc.touched && passwordFc.hasError('required')">
        Required.
      </div>
      <div class="invalid-feedback" *ngIf="passwordFc.touched && passwordFc.hasError('auth/weak-password')">
        That password is too weak.
      </div>
      <small [attr.id]="formId + 'password-help'" class="form-text text-muted">
        Please choose a strong password.
      </small>
    </div>
    <div class="form-group">
      <div class="form-check">
        <input
          class="form-check-input"
          type="checkbox"
          [value]="true"
          formControlName="remember"
          [attr.id]="formId + 'remember'">
        <label class="form-check-label" [attr.for]="formId + 'remember'">
          Remember me on this device.
        </label>
      </div>
    </div>
    <div class="form-group">
      <button type="submit"
        class="btn btn-success btn-block"
        [disabled]="fg.invalid || submitting">
        <i class="fas fa-save fa-fw" aria-hidden="true"></i>
        Save Password and Sign In
      </button>
    </div>
  </form>
</div>
`,
                styles: [``],
                animations: [screenAnimation]
            },] },
];
/** @nocollapse */
OobResetPasswordComponent.ctorParameters = () => [
    { type: AngularFireAuth },
    { type: NgxFirebaseAuthService }
];
OobResetPasswordComponent.propDecorators = {
    oobCode: [{ type: Input }],
    success: [{ type: Output }]
};

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class OobRecoverEmailComponent {
    /**
     * @param {?} _afAuth
     */
    constructor(_afAuth) {
        this._afAuth = _afAuth;
        this.success = new EventEmitter();
        this.screen = 'wait';
        this.submitting = false;
    }
    /**
     * @return {?}
     */
    get auth() {
        return this._afAuth.auth;
    }
    /**
     * @return {?}
     */
    ngOnInit() {
        this.auth.checkActionCode(this.oobCode)
            .then((result) => {
            this.info = result;
            this.screen = 'form';
        })
            .catch((error) => {
            this.unhandledError = error;
            this.screen = 'error';
        });
    }
    /**
     * @return {?}
     */
    submit() {
        this.auth.applyActionCode(this.oobCode)
            .then(() => {
            this.screen = 'success';
            this.success.emit({
                mode: 'recoverEmail',
                info: this.info,
                user: this.auth.currentUser
            });
        })
            .catch((error) => {
            this.unhandledError = error;
            this.screen = 'error';
        });
    }
}
OobRecoverEmailComponent.decorators = [
    { type: Component, args: [{
                selector: 'ngx-firebase-auth-oob-recover-email',
                template: `

<div *ngIf="'wait' === screen" [@screen]="'in'">
  <div class="alert alert-secondary">
    <i class="fas fa-spin fa-spinner fa-fw" aria-hidden="true"></i>
    Please wait...
  </div>
</div>


<div *ngIf="'success' === screen" [@screen]="'in'">
  <div class="alert alert-success">
    <i class="fas fa-check fa-fw" aria-hidden="true"></i>
    Your email has been changed back to {{info.data.email}};
  </div>
</div>

<div *ngIf="screen === 'form'" [@screen]="'in'">
  <div class="form-group">
    <p>
      Are you sure you want to change your email back to
      {{info.data.email}} from {{info.data.fromEmail}}?
    </p>
    <button
      type="button"
      [disabled]="submitting"
      (click)="submit()"
      class="btn btn-block btn-success">
      <i class="fas fa-save fa-fw" aria-hidden="true"></i>
      Yes, Continue
    </button>
  </div>
</div>



<div *ngIf="screen === 'error'" [@screen]="'in'">
  <div class="alert alert-danger">
    <p>
      <i class="fas fa-exclamation-triangle fa-fw" aria-hidden="true"></i>
      Woops! An error occurred.
    </p>
    <div [ngSwitch]="unhandledError.code">
      <p class="mb-0" *ngSwitchCase="'auth/expired-action-code'">
        The recover email link you used has expired.
      </p>
      <p class="mb-0" *ngSwitchCase="'auth/invalid-action-code'">
        The recover email link you used is not valid. This may be because it
        has already been used.
      </p>
      <p class="mb-0" *ngSwitchCase="'auth/user-disabled'">
        The account associated with the recover email link you used has been disabled.
      </p>
      <p class="mb-0" *ngSwitchCase="'auth/user-not-found'">
        The account associated with the recover email link you used has been removed.
      </p>
      <div *ngSwitchDefault>
        <p>Code: {{unhandledError.code}}</p>
        <p class="mb-0">
          Message: {{unhandledError.message}}
        </p>
      </div>
    </div>
  </div>
</div>
`,
                styles: [``],
                animations: [screenAnimation]
            },] },
];
/** @nocollapse */
OobRecoverEmailComponent.ctorParameters = () => [
    { type: AngularFireAuth }
];
OobRecoverEmailComponent.propDecorators = {
    oobCode: [{ type: Input }],
    success: [{ type: Output }]
};

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class OobVerifyEmailComponent {
    /**
     * @param {?} _afAuth
     */
    constructor(_afAuth) {
        this._afAuth = _afAuth;
        this.success = new EventEmitter();
        this.screen = 'wait';
        this.submitting = false;
    }
    /**
     * @return {?}
     */
    get auth() {
        return this._afAuth.auth;
    }
    /**
     * @return {?}
     */
    ngOnInit() {
        this.auth.checkActionCode(this.oobCode)
            .then((result) => {
            this.info = result;
            return this.auth.applyActionCode(this.oobCode);
        })
            .then(() => {
            this.screen = 'success';
            this.success.emit({
                mode: 'verifyEmail',
                info: this.info,
                user: this.auth.currentUser
            });
        })
            .catch((error) => {
            this.unhandledError = error;
            this.screen = 'error';
        });
    }
}
OobVerifyEmailComponent.decorators = [
    { type: Component, args: [{
                selector: 'ngx-firebase-auth-oob-verify-email',
                template: `<div *ngIf="'wait' === screen" [@screen]="'in'">
  <div class="alert alert-secondary">
    <i class="fas fa-spin fa-spinner fa-fw" aria-hidden="true"></i>
    Please wait...
  </div>
</div>

<div *ngIf="'success' === screen" [@screen]="'in'">
  <div class="alert alert-success">
    <i class="fas fa-check fa-fw" aria-hidden="true"></i>
    The email {{info.data.email}} has been verified.
  </div>
</div>

<div *ngIf="screen === 'error'" [@screen]="'in'">
  <div class="alert alert-danger">
    <p>
      <i class="fas fa-exclamation-triangle fa-fw" aria-hidden="true"></i>
      Woops! An error occurred.
    </p>
    <div [ngSwitch]="unhandledError.code">
      <p class="mb-0" *ngSwitchCase="'auth/expired-action-code'">
        The verify email link you used has expired.
      </p>
      <p class="mb-0" *ngSwitchCase="'auth/invalid-action-code'">
        The verify email link you used is not valid. This may be because it
        has already been used.
      </p>
      <p class="mb-0" *ngSwitchCase="'auth/user-disabled'">
        The account associated with the verify email link you used has been disabled.
      </p>
      <p class="mb-0" *ngSwitchCase="'auth/user-not-found'">
        The account associated with the verify email link you used has been removed.
      </p>
      <div *ngSwitchDefault>
        <p>Code: {{unhandledError.code}}</p>
        <p class="mb-0">
          Message: {{unhandledError.message}}
        </p>
      </div>
    </div>
  </div>
</div>
`,
                styles: [``],
                animations: [screenAnimation]
            },] },
];
/** @nocollapse */
OobVerifyEmailComponent.ctorParameters = () => [
    { type: AngularFireAuth }
];
OobVerifyEmailComponent.propDecorators = {
    oobCode: [{ type: Input }],
    success: [{ type: Output }]
};

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class NgxFirebaseAuthOobModule {
}
NgxFirebaseAuthOobModule.decorators = [
    { type: NgModule, args: [{
                imports: [
                    CommonModule,
                    ReactiveFormsModule,
                    RouterModule,
                    NgxFirebaseAuthModule
                ],
                declarations: [
                    OobComponent,
                    OobRecoverEmailComponent,
                    OobResetPasswordComponent,
                    OobVerifyEmailComponent
                ],
                exports: [
                    OobComponent,
                ]
            },] },
];

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */

export { fadeInOutAnimation, screenAnimation, getOAuthProviderName, getOAuthProviderIcon, NgxFirebaseAuthService, SignInComponent, OobComponent, NgxFirebaseAuthSignInModule, NgxFirebaseAuthOobModule, NgxFirebaseAuthModule, OobRecoverEmailComponent as ɵf, OobResetPasswordComponent as ɵg, OobVerifyEmailComponent as ɵh, ResetPasswordSendFormComponent as ɵd, SignInFormComponent as ɵb, SignInMethodsFormComponent as ɵa, SignInOauthComponent as ɵe, SignUpFormComponent as ɵc };

//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm93em9vLW5neC1maXJlYmFzZS1hdXRoLmpzLm1hcCIsInNvdXJjZXMiOlsibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9zaGFyZWQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL3NpZ24taW4vc2lnbi1pbi5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL29vYi9vb2IuY29tcG9uZW50LnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9mb3JtLWhlbHBlci50cyIsIm5nOi8vQG5vd3pvby9uZ3gtZmlyZWJhc2UtYXV0aC9saWIvc2lnbi1pbi9zaWduLWluLW1ldGhvZHMtZm9ybS9zaWduLWluLW1ldGhvZHMtZm9ybS5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL3NpZ24taW4vc2lnbi1pbi1mb3JtL3NpZ24taW4tZm9ybS5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL3NpZ24taW4vc2lnbi11cC1mb3JtL3NpZ24tdXAtZm9ybS5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL3NpZ24taW4vcmVzZXQtcGFzc3dvcmQtc2VuZC1mb3JtL3Jlc2V0LXBhc3N3b3JkLXNlbmQtZm9ybS5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL3NpZ24taW4vc2lnbi1pbi1vYXV0aC9zaWduLWluLW9hdXRoLmNvbXBvbmVudC50cyIsIm5nOi8vQG5vd3pvby9uZ3gtZmlyZWJhc2UtYXV0aC9saWIvbmd4LWZpcmViYXNlLWF1dGgubW9kdWxlLnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9zaWduLWluL25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4ubW9kdWxlLnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9vb2Ivb29iLXJlc2V0LXBhc3N3b3JkL29vYi1yZXNldC1wYXNzd29yZC5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL29vYi9vb2ItcmVjb3Zlci1lbWFpbC9vb2ItcmVjb3Zlci1lbWFpbC5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL29vYi9vb2ItdmVyaWZ5LWVtYWlsL29vYi12ZXJpZnktZW1haWwuY29tcG9uZW50LnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9vb2Ivbmd4LWZpcmViYXNlLWF1dGgtb29iLm1vZHVsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBbmltYXRpb25UcmlnZ2VyTWV0YWRhdGEsIHRyaWdnZXIsIHN0YXRlLCBzdHlsZSwgYW5pbWF0ZSwgdHJhbnNpdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2FuaW1hdGlvbnMnO1xuaW1wb3J0IHsgYXV0aCwgVXNlciB9IGZyb20gJ2ZpcmViYXNlL2FwcCc7XG5cblxuZXhwb3J0IGludGVyZmFjZSBJU2lnbkluTWV0aG9kc0ZvckVtYWlsUmVzdWx0IHtcbiAgZW1haWw6IHN0cmluZztcbiAgbWV0aG9kczogc3RyaW5nW107XG4gIHN0YXR1czogJ3VuZmV0Y2hlZCcgfCAnZmV0Y2hpbmcnIHwgJ2ZldGNoZWQnO1xufVxuXG5cbmV4cG9ydCBpbnRlcmZhY2UgSU5neEZpcmViYXNlQXV0aFJlbWVtYmVyUmVjb3JkIHtcbiAgcmVtZW1iZXI6IGJvb2xlYW47XG4gIGVtYWlsOiBzdHJpbmc7XG59XG5cblxuZXhwb3J0IGNvbnN0IGZhZGVJbk91dEFuaW1hdGlvbjogQW5pbWF0aW9uVHJpZ2dlck1ldGFkYXRhID0gdHJpZ2dlcignZmFkZUluT3V0JywgW1xuICBzdGF0ZSgnaW4nLCBzdHlsZSh7b3BhY2l0eTogMSwgZGlzcGxheTogJ2Jsb2NrJ30pKSxcbiAgdHJhbnNpdGlvbigndm9pZCA9PiAqJywgW1xuICAgIHN0eWxlKHtvcGFjaXR5OiAwfSksXG4gICAgYW5pbWF0ZSgzMDApXG4gIF0pLFxuICB0cmFuc2l0aW9uKCcqID0+IHZvaWQnLCBbXG4gICAgYW5pbWF0ZSgzMDAsIHN0eWxlKHtvcGFjaXR5OiAwfSkpXG4gIF0pXG5dKTtcblxuZXhwb3J0IGNvbnN0IHNjcmVlbkFuaW1hdGlvbjogQW5pbWF0aW9uVHJpZ2dlck1ldGFkYXRhID0gdHJpZ2dlcignc2NyZWVuJywgW1xuICBzdGF0ZSgnaW4nLCBzdHlsZSh7b3BhY2l0eTogMX0pKSxcbiAgdHJhbnNpdGlvbigndm9pZCA9PiAqJywgW1xuICAgIHN0eWxlKHtvcGFjaXR5OiAwfSksXG4gICAgYW5pbWF0ZSgzMDApXG4gIF0pLFxuICB0cmFuc2l0aW9uKCcqID0+IHZvaWQnLCBbXG4gICAgYW5pbWF0ZSgwLCBzdHlsZSh7b3BhY2l0eTogMH0pKVxuICBdKVxuXSk7XG5cbmV4cG9ydCBjb25zdCBnZXRPQXV0aFByb3ZpZGVyTmFtZSA9IChpZDogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgc3dpdGNoIChpZCkge1xuICAgIGNhc2UgJ3R3aXR0ZXIuY29tJzogcmV0dXJuICdUd2l0dGVyJztcbiAgICBjYXNlICdmYWNlYm9vay5jb20nOiByZXR1cm4gJ0ZhY2Vib29rJztcbiAgICBjYXNlICdnb29nbGUuY29tJzogcmV0dXJuICdHb29nbGUnO1xuICAgIGNhc2UgJ2dpdGh1Yi5jb20nOiByZXR1cm4gJ0dpdEh1Yic7XG4gICAgZGVmYXVsdDogcmV0dXJuIGlkO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0T0F1dGhQcm92aWRlckljb24gPSAoaWQ6IHN0cmluZyk6IHN0cmluZyAgPT4ge1xuICBzd2l0Y2ggKGlkKSB7XG4gICAgY2FzZSAndHdpdHRlci5jb20nOlxuICAgIGNhc2UgJ2ZhY2Vib29rLmNvbSc6XG4gICAgY2FzZSAnZ29vZ2xlLmNvbSc6XG4gICAgY2FzZSAnZ2l0aHViLmNvbSc6XG4gICAgICByZXR1cm4gJ2ZhYiBmYS1mdyBmYS0nICsgaWQucmVwbGFjZSgnLmNvbScsICcnKTtcbiAgICBkZWZhdWx0OiByZXR1cm4gJ2ZhcyBmYS1mdyBmYS1zaWduLWluLWFsdCc7XG4gIH1cbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgSU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3Mge1xuICBtb2RlOiAncmVzZXRQYXNzd29yZCcgfCAndmVyaWZ5RW1haWwnIHwgJ3JlY292ZXJFbWFpbCc7XG4gIGluZm86IGF1dGguQWN0aW9uQ29kZUluZm87XG4gIGNyZWQ/OiBhdXRoLlVzZXJDcmVkZW50aWFsO1xuICB1c2VyPzogVXNlcjtcbn1cbiIsImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGgsIFVzZXIgfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgSU5neEZpcmViYXNlQXV0aFJlbWVtYmVyUmVjb3JkIH0gZnJvbSAnLi9zaGFyZWQnO1xuXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIHtcbiAgc3RhdGljIHJlbWVtYmVyS2V5ID0gJ25neC1maXJlYmFzZS1hdXRoLXJlbWVtYmVyJztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aFxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG4gIGdldCBzdG9yYWdlKCk6IFN0b3JhZ2Uge1xuICAgIHJldHVybiB3aW5kb3cubG9jYWxTdG9yYWdlO1xuICB9XG5cbiAgZ2V0UmVtZW1iZXJlZCgpOiBJTmd4RmlyZWJhc2VBdXRoUmVtZW1iZXJSZWNvcmQge1xuICAgIGNvbnN0IHN0ciA9IHRoaXMuc3RvcmFnZS5nZXRJdGVtKE5neEZpcmViYXNlQXV0aFNlcnZpY2UucmVtZW1iZXJLZXkpO1xuICAgIGlmIChzdHIpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBKU09OLnBhcnNlKHN0cik7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiB7ZW1haWw6ICcnLCByZW1lbWJlcjogdHJ1ZX07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7ZW1haWw6ICcnLCByZW1lbWJlcjogdHJ1ZX07XG4gIH1cblxuICBzZXRSZW1lbWJlcmVkKHJlbWVtYmVyOiBib29sZWFuLCBlbWFpbDogc3RyaW5nKTogUHJvbWlzZTxJTmd4RmlyZWJhc2VBdXRoUmVtZW1iZXJSZWNvcmQ+IHtcbiAgICBjb25zdCBwZXJzaXN0ZW5jZTogYXV0aC5BdXRoLlBlcnNpc3RlbmNlID0gcmVtZW1iZXIgP1xuICAgICAgYXV0aC5BdXRoLlBlcnNpc3RlbmNlLkxPQ0FMIDogYXV0aC5BdXRoLlBlcnNpc3RlbmNlLlNFU1NJT047XG4gICAgcmV0dXJuIHRoaXMuYXV0aC5zZXRQZXJzaXN0ZW5jZShwZXJzaXN0ZW5jZSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgY29uc3QgbzogSU5neEZpcmViYXNlQXV0aFJlbWVtYmVyUmVjb3JkID0ge1xuICAgICAgICAgIGVtYWlsOiByZW1lbWJlciA/IGVtYWlsIDogJycsXG4gICAgICAgICAgcmVtZW1iZXI6IHJlbWVtYmVyXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHN0ciA9IEpTT04uc3RyaW5naWZ5KG8pO1xuICAgICAgICB0aGlzLnN0b3JhZ2Uuc2V0SXRlbShOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlLnJlbWVtYmVyS2V5LCBzdHIpO1xuICAgICAgICByZXR1cm4gbztcbiAgICAgIH0pO1xuICB9XG5cblxuXG59XG4iLCJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgT25EZXN0cm95LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIFRlbXBsYXRlUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBSb3V0ZXIsIEFjdGl2YXRlZFJvdXRlIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IEZvcm1Hcm91cCwgRm9ybUNvbnRyb2wsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBTdWJqZWN0LCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBhdXRoLCBVc2VyIH0gZnJvbSAnZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IHNjcmVlbkFuaW1hdGlvbiB9IGZyb20gJy4uL3NoYXJlZCc7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyIH0gZnJvbSAnLi4vZm9ybS1oZWxwZXInO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB9IGZyb20gJy4uL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UnO1xuXG5cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWZpcmViYXNlLWF1dGgtc2lnbi1pbicsXG4gIHRlbXBsYXRlOiBgPGRpdiAqbmdJZj1cIid3YWl0JyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc2Vjb25kYXJ5XCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtc3BpbiBmYS1zcGlubmVyIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFBsZWFzZSB3YWl0Li4uXG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCIndW5oYW5kbGVkRXJyb3InID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1leGNsYW1hdGlvbi10cmlhbmdsZSBmYS1mdyB0ZXh0LWRhbmdlclwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICA8c3Ryb25nPldvb3BzITwvc3Ryb25nPiBBbiB1bmV4cGVjdGVkIGVycm9yIG9jY3VycmVkLlxuICA8L2Rpdj5cbiAgPHAgY2xhc3M9XCJ0ZXh0LW11dGVkXCI+XG4gICAgQ29kZToge3t1bmhhbmRsZWRFcnJvci5jb2RlfX0uIE1lc3NhZ2U6IHt7dW5oYW5kbGVkRXJyb3IubWVzc2FnZX19XG4gIDwvcD5cbiAgPHA+XG4gICAgPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbid9XCI+U3RhcnQgT3ZlcjwvYT5cbiAgPC9wPlxuPC9kaXY+XG5cblxuPGRpdiAqbmdJZj1cIidzaWduSW5TdWNjZXNzJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc3VjY2Vzc1wiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNoZWNrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFdlbGNvbWUsIHt7Y3JlZC51c2VyLmRpc3BsYXlOYW1lfX0hXG4gIDwvZGl2PlxuPC9kaXY+XG5cblxuXG5cbjxkaXYgKm5nSWY9XCInc2lnbkluJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc3VjY2Vzc1wiICpuZ0lmPVwic2lnbmVkT3V0XCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtY2hlY2sgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgWW91w6LCgMKZcmUgc2lnbmVkIG91dC5cbiAgPC9kaXY+XG4gIDxuZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW1ldGhvZHMtZm9ybVxuICAgIFsoZW1haWwpXT1cImVtYWlsXCJcbiAgICBbKHJlbWVtYmVyKV09XCJyZW1lbWJlclwiXG4gICAgW29BdXRoUHJvdmlkZXJJZHNdPVwib0F1dGhQcm92aWRlcklkc1wiXG4gICAgKGVycm9yKT1cInNob3dVbmhhbmRsZWRFcnJvcigkZXZlbnQpXCJcbiAgICAoc3VjY2Vzcyk9XCJzaG93U2lnbkluU3VjY2VzcygkZXZlbnQpXCI+PC9uZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW1ldGhvZHMtZm9ybT5cbiAgPHNtYWxsIGNsYXNzPVwidGV4dC1jZW50ZXIgdGV4dC1tdXRlZCBteS0yIGZvcm0tdGV4dFwiPlxuICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0b3NUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxuICA8L3NtYWxsPlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCInc2lnbkluUGFzc3dvcmQnID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxuZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLWZvcm1cbiAgICBbZW1haWxdPVwiZW1haWxcIlxuICAgIFsocmVtZW1iZXIpXT1cInJlbWVtYmVyXCJcbiAgICAoZXJyb3IpPVwic2hvd1VuaGFuZGxlZEVycm9yKCRldmVudClcIlxuICAgIChzdWNjZXNzKT1cInNob3dTaWduSW5TdWNjZXNzKCRldmVudClcIj48L25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4tZm9ybT5cbiAgPHNtYWxsIGNsYXNzPVwidGV4dC1jZW50ZXIgdGV4dC1tdXRlZCBteS0yIGZvcm0tdGV4dFwiPlxuICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0b3NUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxuICA8L3NtYWxsPlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCInc2lnblVwUGFzc3dvcmQnID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxuZ3gtZmlyZWJhc2UtYXV0aC1zaWduLXVwLWZvcm1cbiAgICBbZW1haWxdPVwiZW1haWxcIlxuICAgIFsocmVtZW1iZXIpXT1cInJlbWVtYmVyXCJcbiAgICAoZXJyb3IpPVwic2hvd1VuaGFuZGxlZEVycm9yKCRldmVudClcIlxuICAgIChzdWNjZXNzKT1cInNob3dTaWduSW5TdWNjZXNzKCRldmVudClcIj48L25neC1maXJlYmFzZS1hdXRoLXNpZ24tdXAtZm9ybT5cbiAgPHNtYWxsIGNsYXNzPVwidGV4dC1jZW50ZXIgdGV4dC1tdXRlZCBteS0yIGZvcm0tdGV4dFwiPlxuICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0b3NUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxuICA8L3NtYWxsPlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCInc2lnbkluT0F1dGgnID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxuZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW9hdXRoXG4gICAgW3Byb3ZpZGVySWRdPVwib0F1dGhQcm92aWRlcklkXCJcbiAgICBbaW5pdGlhbEVycm9yXT1cImluaXRpYWxPQXV0aEVycm9yXCJcbiAgICBbdXNlT0F1dGhQb3B1cF09XCJ1c2VPQXV0aFBvcHVwXCJcbiAgICBbb0F1dGhQcm92aWRlckZhY3RvcnldPVwib0F1dGhQcm92aWRlckZhY3RvcnlcIlxuICAgIFsoZW1haWwpXT1cImVtYWlsXCJcbiAgICBbKHJlbWVtYmVyKV09XCJyZW1lbWJlclwiXG4gICAgKGVycm9yKT1cInNob3dVbmhhbmRsZWRFcnJvcigkZXZlbnQpXCJcbiAgICAoc3VjY2Vzcyk9XCJzaG93U2lnbkluU3VjY2VzcygkZXZlbnQpXCI+PC9uZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW9hdXRoPlxuICA8c21hbGwgY2xhc3M9XCJ0ZXh0LWNlbnRlciB0ZXh0LW11dGVkIG15LTIgZm9ybS10ZXh0XCI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInRvc1RlbXBsYXRlXCI+PC9uZy1jb250YWluZXI+XG4gIDwvc21hbGw+XG48L2Rpdj5cblxuXG5cbjxkaXYgKm5nSWY9XCIncmVzZXRQYXNzd29yZCcgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGg2PlJlc2V0IFBhc3N3b3JkPC9oNj5cbiAgPG5neC1maXJlYmFzZS1hdXRoLXJlc2V0LXBhc3N3b3JkLXNlbmQtZm9ybVxuICAgIFsoZW1haWwpXT1cImVtYWlsXCJcbiAgICAoZXJyb3IpPVwic2hvd1VuaGFuZGxlZEVycm9yKCRldmVudClcIj48L25neC1maXJlYmFzZS1hdXRoLXJlc2V0LXBhc3N3b3JkLXNlbmQtZm9ybT5cbjwvZGl2PlxuYCxcbiAgc3R5bGVzOiBbYGBdLFxuICBhbmltYXRpb25zOiBbc2NyZWVuQW5pbWF0aW9uXVxufSlcbmV4cG9ydCBjbGFzcyBTaWduSW5Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIHByaXZhdGUgbmdVbnN1YnNjcmliZTogU3ViamVjdDx2b2lkPiA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIEBJbnB1dCgpIG9BdXRoUHJvdmlkZXJJZHM6IHN0cmluZ1tdO1xuICBASW5wdXQoKSB1c2VPQXV0aFBvcHVwOiBib29sZWFuO1xuICBASW5wdXQoKSBvQXV0aFByb3ZpZGVyRmFjdG9yeTogKHByb3ZpZGVySWQ6IHN0cmluZykgPT4gYXV0aC5BdXRoUHJvdmlkZXI7XG4gIEBJbnB1dCgpIHRvc1RlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+ID0gbnVsbDtcbiAgQE91dHB1dCgpIHN1Y2Nlc3M6IEV2ZW50RW1pdHRlcjxhdXRoLlVzZXJDcmVkZW50aWFsPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIG1vZGU6IEV2ZW50RW1pdHRlcjwnc2lnbkluJyB8ICdyZXNldFBhc3N3b3JkJz4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgcmVtZW1iZXI6IGJvb2xlYW47XG4gIGVtYWlsOiBzdHJpbmc7XG4gIGluaXRpYWxPQXV0aEVycm9yOiBhdXRoLkVycm9yID0gbnVsbDtcbiAgc2lnbmVkT3V0ID0gZmFsc2U7XG4gIG9BdXRoUHJvdmlkZXJJZDogc3RyaW5nID0gbnVsbDtcbiAgY3JlZDogYXV0aC5Vc2VyQ3JlZGVudGlhbCA9IG51bGw7XG4gIHVuaGFuZGxlZEVycm9yOiBhdXRoLkVycm9yID0gbnVsbDtcblxuICBzY3JlZW46ICd3YWl0JyB8XG4gICAgJ3NpZ25JbicgfCAnc2lnbkluUGFzc3dvcmQnIHwgJ3NpZ25VcFBhc3N3b3JkJyB8ICdzaWduSW5PQXV0aCcgfCAnc2lnbkluU3VjY2VzcycgfFxuICAgICdyZXNldFBhc3N3b3JkJyB8ICd1bmhhbmRsZWRFcnJvcicgPSAnd2FpdCc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICAgcHJpdmF0ZSBfc3ZjOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlLFxuICAgIHByaXZhdGUgX3JvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICBwcml2YXRlIF9yb3V0ZXI6IFJvdXRlcixcbiAgKSB7fVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG5cbiAgZ2V0IGF1dGhTZXJ2aWNlKCk6IE5neEZpcmViYXNlQXV0aFNlcnZpY2Uge1xuICAgIHJldHVybiB0aGlzLl9zdmM7XG4gIH1cblxuICBnZXQgcm91dGVyKCk6IFJvdXRlciB7XG4gICAgcmV0dXJuIHRoaXMuX3JvdXRlcjtcbiAgfVxuXG4gIGdldCByb3V0ZSgpOiBBY3RpdmF0ZWRSb3V0ZSB7XG4gICAgcmV0dXJuIHRoaXMuX3JvdXRlO1xuICB9XG5cbiAgZ2V0IHF1ZXJ5UGFyYW1zKCk6IE9ic2VydmFibGU8e1trZXk6IHN0cmluZ106IGFueX0+IHtcbiAgICByZXR1cm4gdGhpcy5yb3V0ZS5xdWVyeVBhcmFtcztcbiAgfVxuXG4gIGdldCBzbmFwc2hvdFF1ZXJ5UGFyYW1zKCk6IHtba2V5OiBzdHJpbmddOiBhbnl9IHtcbiAgICByZXR1cm4gdGhpcy5yb3V0ZS5zbmFwc2hvdC5xdWVyeVBhcmFtcztcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuaW5pdCgpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5uZ1Vuc3Vic2NyaWJlLm5leHQoKTtcbiAgICB0aGlzLm5nVW5zdWJzY3JpYmUuY29tcGxldGUoKTtcbiAgfVxuXG4gIGluaXQoKSB7XG4gICAgY29uc3QgcmVtZW1iZXJSZWNvcmQgPSB0aGlzLmF1dGhTZXJ2aWNlLmdldFJlbWVtYmVyZWQoKTtcbiAgICB0aGlzLnJlbWVtYmVyID0gcmVtZW1iZXJSZWNvcmQucmVtZW1iZXI7XG4gICAgdGhpcy5lbWFpbCA9IHJlbWVtYmVyUmVjb3JkLmVtYWlsO1xuICAgIHJldHVybiB0aGlzLm9uSW5pdEhhbmRsZVNpZ25PdXQoKVxuICAgICAgLnRoZW4oKGhhbmRsZWQ6IGJvb2xlYW4pID0+IHtcbiAgICAgICAgaWYgKGhhbmRsZWQpIHtcbiAgICAgICAgICByZXR1cm4gaGFuZGxlZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5vbkluaXRIYW5kbGVPQXV0aFJlZGlyZWN0KCk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKGhhbmRsZWQ6IGJvb2xlYW4pID0+IHtcbiAgICAgICAgaWYgKCEgaGFuZGxlZCkge1xuICAgICAgICAgIHRoaXMuc2hvd1NpZ25JbigpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucXVlcnlQYXJhbXMucGlwZSh0YWtlVW50aWwodGhpcy5uZ1Vuc3Vic2NyaWJlKSkuc3Vic2NyaWJlKHBhcmFtcyA9PiB7XG4gICAgICAgICAgY29uc3QgYWN0aW9uID0gcGFyYW1zLmFjdGlvbiB8fCBudWxsO1xuICAgICAgICAgIHN3aXRjaCAoYWN0aW9uKSB7XG4gICAgICAgICAgICBjYXNlICdzaWduT3V0JzpcbiAgICAgICAgICAgICAgdGhpcy5zaG93U2lnbk91dCgpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3Jlc2V0UGFzc3dvcmQnOlxuICAgICAgICAgICAgICB0aGlzLnNob3dSZXNldFBhc3N3b3JkKCk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnc2lnbkluJzpcbiAgICAgICAgICAgICAgdGhpcy5zaG93U2lnbkluKCk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnc2lnbkluUGFzc3dvcmQnOlxuICAgICAgICAgICAgICB0aGlzLnNob3dTaWduSW5QYXNzd29yZCgpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3NpZ25VcFBhc3N3b3JkJzpcbiAgICAgICAgICAgICAgdGhpcy5zaG93U2lnblVwUGFzc3dvcmQoKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdzaWduSW5PQXV0aCc6XG4gICAgICAgICAgICAgIHRoaXMuc2hvd1NpZ25Jbk9BdXRoKHBhcmFtcy5wcm92aWRlcklkLCBudWxsKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICB9XG5cbiAgb25Jbml0SGFuZGxlU2lnbk91dCgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAodGhpcy5zbmFwc2hvdFF1ZXJ5UGFyYW1zLmFjdGlvbiAhPT0gJ3NpZ25PdXQnKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGZhbHNlKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2hvd1NpZ25PdXQoKS50aGVuKCgpID0+IHRydWUpO1xuICB9XG4gIG9uSW5pdEhhbmRsZU9BdXRoUmVkaXJlY3QoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgY29uc3QgcmVtZW1iZXI6IGJvb2xlYW4gPSB0aGlzLnJvdXRlLnNuYXBzaG90LnF1ZXJ5UGFyYW1zLnJlbWVtYmVyID09PSAndHJ1ZSc7XG4gICAgICByZXR1cm4gdGhpcy5hdXRoLmdldFJlZGlyZWN0UmVzdWx0KClcbiAgICAgICAgLnRoZW4oKGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWwpID0+IHtcbiAgICAgICAgICBpZiAodGhpcy5hdXRoLmN1cnJlbnRVc2VyICYmIGNyZWQudXNlcikge1xuICAgICAgICAgICAgdGhpcy5hdXRoU2VydmljZS5zZXRSZW1lbWJlcmVkKHJlbWVtYmVyLCBjcmVkLnVzZXIuZW1haWwpXG4gICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3dTaWduSW5TdWNjZXNzKGNyZWQpO1xuICAgICAgICAgICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXNvbHZlKGZhbHNlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaCgoZXJyb3I6IGF1dGguRXJyb3IpID0+IHtcbiAgICAgICAgICB0aGlzLnNob3dTaWduSW5PQXV0aChudWxsLCBlcnJvciApO1xuICAgICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuXG5cbiAgc2hvd1NpZ25PdXQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICB0aGlzLnNpZ25lZE91dCA9IGZhbHNlO1xuICAgIHRoaXMuc2NyZWVuID0gJ3dhaXQnO1xuICAgIHJldHVybiB0aGlzLmF1dGguc2lnbk91dCgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMuc2hvd1NpZ25Jbih0cnVlKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgc2hvd1NpZ25JbihzaWduZWRPdXQ/OiBib29sZWFuKSB7XG4gICAgdGhpcy5tb2RlLmVtaXQoJ3NpZ25JbicpO1xuICAgIHRoaXMuc2lnbmVkT3V0ID0gc2lnbmVkT3V0ID09PSB0cnVlO1xuICAgIHRoaXMuc2NyZWVuID0gJ3NpZ25Jbic7XG4gIH1cblxuICBzaG93U2lnbkluUGFzc3dvcmQoKSB7XG4gICAgdGhpcy5tb2RlLmVtaXQoJ3NpZ25JbicpO1xuICAgIHRoaXMuc2lnbmVkT3V0ID0gZmFsc2U7XG4gICAgdGhpcy5zY3JlZW4gPSAnc2lnbkluUGFzc3dvcmQnO1xuICB9XG5cbiAgc2hvd1NpZ25VcFBhc3N3b3JkKCkge1xuICAgIHRoaXMubW9kZS5lbWl0KCdzaWduSW4nKTtcbiAgICB0aGlzLnNpZ25lZE91dCA9IGZhbHNlO1xuICAgIHRoaXMuc2NyZWVuID0gJ3NpZ25VcFBhc3N3b3JkJztcblxuICB9XG5cbiAgc2hvd1NpZ25Jbk9BdXRoKG9BdXRoUHJvdmlkZXJJZDogc3RyaW5nLCBlcnJvcjogYXV0aC5FcnJvcikge1xuICAgIHRoaXMubW9kZS5lbWl0KCdzaWduSW4nKTtcbiAgICB0aGlzLnNpZ25lZE91dCA9IGZhbHNlO1xuICAgIHRoaXMub0F1dGhQcm92aWRlcklkID0gb0F1dGhQcm92aWRlcklkO1xuICAgIHRoaXMuaW5pdGlhbE9BdXRoRXJyb3IgPSBlcnJvcjtcbiAgICB0aGlzLnNjcmVlbiA9ICdzaWduSW5PQXV0aCc7XG4gIH1cblxuICBzaG93U2lnbkluU3VjY2VzcyhjcmVkOiBhdXRoLlVzZXJDcmVkZW50aWFsKSB7XG4gICAgdGhpcy5tb2RlLmVtaXQoJ3NpZ25JbicpO1xuICAgIHRoaXMuc2lnbmVkT3V0ID0gZmFsc2U7XG4gICAgdGhpcy5jcmVkID0gY3JlZDtcbiAgICB0aGlzLnNjcmVlbiA9ICdzaWduSW5TdWNjZXNzJztcbiAgICB0aGlzLnN1Y2Nlc3MuZW1pdChjcmVkKTtcbiAgfVxuXG4gIHNob3dSZXNldFBhc3N3b3JkKCkge1xuICAgIHRoaXMubW9kZS5lbWl0KCdyZXNldFBhc3N3b3JkJyk7XG4gICAgdGhpcy5zaWduZWRPdXQgPSBmYWxzZTtcbiAgICB0aGlzLnNjcmVlbiA9ICdyZXNldFBhc3N3b3JkJztcbiAgfVxuXG4gIHNob3dVbmhhbmRsZWRFcnJvcihlcnJvcjogYXV0aC5FcnJvcikge1xuICAgIHRoaXMuc2lnbmVkT3V0ID0gZmFsc2U7XG4gICAgdGhpcy51bmhhbmRsZWRFcnJvciA9IGVycm9yO1xuICAgIHRoaXMuc2NyZWVuID0gJ3VuaGFuZGxlZEVycm9yJztcbiAgfVxufVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBzY3JlZW5BbmltYXRpb24gfSBmcm9tICcuLi9zaGFyZWQnO1xuaW1wb3J0IHsgSU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3MgfSBmcm9tICcuLi9zaGFyZWQnO1xuXG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLW9vYicsXG4gIHRlbXBsYXRlOiBgPGRpdiAqbmdJZj1cIidyZXNldFBhc3N3b3JkJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8bmd4LWZpcmViYXNlLWF1dGgtb29iLXJlc2V0LXBhc3N3b3JkXG4gICAgW29vYkNvZGVdPVwib29iQ29kZVwiXG4gICAgKHN1Y2Nlc3MpPVwic3VjY2Vzcy5lbWl0KCRldmVudClcIj48L25neC1maXJlYmFzZS1hdXRoLW9vYi1yZXNldC1wYXNzd29yZD5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwiJ3ZlcmlmeUVtYWlsJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8bmd4LWZpcmViYXNlLWF1dGgtb29iLXZlcmlmeS1lbWFpbFxuICAgIFtvb2JDb2RlXT1cIm9vYkNvZGVcIlxuICAgIChzdWNjZXNzKT1cInN1Y2Nlc3MuZW1pdCgkZXZlbnQpXCI+PC9uZ3gtZmlyZWJhc2UtYXV0aC1vb2ItdmVyaWZ5LWVtYWlsPlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCIncmVjb3ZlckVtYWlsJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8bmd4LWZpcmViYXNlLWF1dGgtb29iLXJlY292ZXItZW1haWxcbiAgICBbb29iQ29kZV09XCJvb2JDb2RlXCJcbiAgICAoc3VjY2Vzcyk9XCJzdWNjZXNzLmVtaXQoJGV2ZW50KVwiPjwvbmd4LWZpcmViYXNlLWF1dGgtb29iLXJlY292ZXItZW1haWw+XG48L2Rpdj5cbmAsXG4gIHN0eWxlczogW2BgXSxcbiAgYW5pbWF0aW9uczogW3NjcmVlbkFuaW1hdGlvbl1cbn0pXG5leHBvcnQgY2xhc3MgT29iQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBvb2JDb2RlOiBzdHJpbmc7XG4gIHNjcmVlbjogJ3Jlc2V0UGFzc3dvcmQnIHwgJ3ZlcmlmeUVtYWlsJyB8ICdyZWNvdmVyRW1haWwnID0gbnVsbDtcblxuICBAT3V0cHV0KCkgbW9kZTogRXZlbnRFbWl0dGVyPCdyZXNldFBhc3N3b3JkJyB8ICd2ZXJpZnlFbWFpbCcgfCAncmVjb3ZlckVtYWlsJz4gID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgbmF2aWdhdGlvbkVycm9yOiBFdmVudEVtaXR0ZXI8dm9pZD4gID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgc3VjY2VzczogRXZlbnRFbWl0dGVyPElOZ3hGaXJlYmFzZUF1dGhPb2JTdWNjZXNzPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgX3JvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgKSB7IH1cblxuXG4gIGdldCBxdWVyeVBhcmFtcygpOiB7W2tleTogc3RyaW5nXTogYW55fSB7XG4gICAgcmV0dXJuIHRoaXMuX3JvdXRlLnNuYXBzaG90LnF1ZXJ5UGFyYW1zO1xuICB9XG5cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLm9vYkNvZGUgPSB0aGlzLnF1ZXJ5UGFyYW1zLm9vYkNvZGUgfHwgbnVsbDtcbiAgICBpZiAoISB0aGlzLm9vYkNvZGUpIHtcbiAgICAgIHRoaXMubmF2aWdhdGlvbkVycm9yLmVtaXQoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgc3dpdGNoICh0aGlzLnF1ZXJ5UGFyYW1zLm1vZGUpIHtcbiAgICAgIGNhc2UgJ3Jlc2V0UGFzc3dvcmQnOlxuICAgICAgY2FzZSAndmVyaWZ5RW1haWwnOlxuICAgICAgY2FzZSAncmVjb3ZlckVtYWlsJzpcbiAgICAgICAgdGhpcy5zY3JlZW4gPSB0aGlzLnF1ZXJ5UGFyYW1zLm1vZGU7XG4gICAgICAgIHRoaXMubW9kZS5lbWl0KHRoaXMucXVlcnlQYXJhbXMubW9kZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhpcy5uYXZpZ2F0aW9uRXJyb3IuZW1pdCgpO1xuICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgfVxufVxuIiwiaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmV4cG9ydCBjbGFzcyBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyIHtcbiAgc3RhdGljIHNldEVycm9yVW50aWxDaGFuZ2VkKGZjOiBBYnN0cmFjdENvbnRyb2wsIGtleTogc3RyaW5nLCB2YWx1ZTogYW55ID0gdHJ1ZSkge1xuICAgIGNvbnN0IGVycm9yID0ge307XG4gICAgZXJyb3Jba2V5XSA9IHZhbHVlO1xuICAgIGZjLnNldEVycm9ycyhlcnJvcik7XG4gICAgZmMudmFsdWVDaGFuZ2VzLnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIuY2xlYXJFcnJvcihmYywga2V5KTtcbiAgICB9KTtcblxuICB9XG5cbiAgc3RhdGljIGNsZWFyRXJyb3IoZmM6IEFic3RyYWN0Q29udHJvbCwga2V5OiBzdHJpbmcpIHtcbiAgICBjb25zdCBlcnJvcnMgPSB7fTtcbiAgICBpZiAoISBmYy5lcnJvcnMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgT2JqZWN0LmtleXMoZmMuZXJyb3JzKS5mb3JFYWNoKChrKSA9PiB7XG4gICAgICBpZiAoayAhPT0ga2V5KSB7XG4gICAgICAgIGVycm9yc1trXSA9IGZjLmVycm9yc1trXTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAoT2JqZWN0LmtleXMoZXJyb3JzKS5sZW5ndGggPT09IDApIHtcbiAgICAgIGZjLnNldEVycm9ycyhudWxsKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZmMuc2V0RXJyb3JzKGVycm9ycyk7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIHJlcXVpcmVkTm9uRW1wdHkoZmM6IEFic3RyYWN0Q29udHJvbCkge1xuICAgIGNvbnN0IHZhbHVlID0gZmMudmFsdWU7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWUudHJpbSgpLmxlbmd0aCA9PT0gMCA/IHtyZXF1aXJlZDogdHJ1ZX0gOiBudWxsO1xuICB9XG5cblxufVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIEFmdGVyVmlld0luaXQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgTmdab25lLCBWaWV3Q2hpbGQsIEVsZW1lbnRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Db250cm9sLCBGb3JtR3JvdXAsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBhdXRoIH0gZnJvbSAnZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IGRlYm91bmNlVGltZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IElTaWduSW5NZXRob2RzRm9yRW1haWxSZXN1bHQsIGdldE9BdXRoUHJvdmlkZXJJY29uLCBnZXRPQXV0aFByb3ZpZGVyTmFtZSB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyIH0gZnJvbSAnLi4vLi4vZm9ybS1oZWxwZXInO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB9IGZyb20gJy4uLy4uL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UnO1xuaW1wb3J0IHsgZmFkZUluT3V0QW5pbWF0aW9uLCBzY3JlZW5BbmltYXRpb24gfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW1ldGhvZHMtZm9ybScsXG4gIHRlbXBsYXRlOiBgPGZvcm0gW2Zvcm1Hcm91cF09XCJmZ1wiPlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiPkVtYWlsIEFkZHJlc3M8L2xhYmVsPlxuICAgIDxpbnB1dFxuICAgICAgI2VtYWlsSW5wdXRcbiAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbCdcIlxuICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJmb3JtSWQgKyAnZW1haWwnXCJcbiAgICAgIHR5cGU9XCJlbWFpbFwiXG4gICAgICBhdXRvY29tcGxldGU9XCJlbWFpbFwiXG4gICAgICBwbGFjZWhvbGRlcj1cIkVtYWlsIEFkZHJlc3NcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiZW1haWxcIlxuICAgICAgKGJsdXIpPVwiZmV0Y2goKVwiXG4gICAgICAoa2V5dXAuZW50ZXIpPVwiZW1haWxJbnB1dC5ibHVyKClcIlxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwiZW1haWxGYy50b3VjaGVkICYmIGVtYWlsRmMuaW52YWxpZFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMudG91Y2hlZCAmJiBlbWFpbEZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICBSZXF1aXJlZC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLnRvdWNoZWQgJiYgZW1haWxGYy5oYXNFcnJvcignZW1haWwnKVwiPlxuICAgICAgSW52YWxpZCBlbWFpbC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLnRvdWNoZWQgJiYgZW1haWxGYy5oYXNFcnJvcignYXV0aC9pbnZhbGlkLWVtYWlsJylcIj5cbiAgICAgIEludmFsaWQgZW1haWwuXG4gICAgPC9kaXY+XG4gICAgPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZCBmb3JtLXRleHRcIiBbYXR0ci5pZF09XCJmb3JtSWQgKyAnZW1haWwnXCIgW25nU3dpdGNoXT1cImZldGNoU3RhdHVzXCI+XG4gICAgICA8c3BhbiAqbmdTd2l0Y2hDYXNlPVwiJ3VuZmV0Y2hlZCdcIiBbQGZhZGVJbk91dF09XCInaW4nXCI+XG4gICAgICAgIFRvIGdldCBzdGFydGVkLCBlbnRlciB5b3VyIGVtYWlsIGFkZHJlc3MuXG4gICAgICAgIElmIHlvdSBkb27DosKAwpl0IHlldCBoYXZlIGFuIGFjY291bnQgd2XDosKAwplsbCBjcmVhdGUgb25lIGZvciB5b3UuXG4gICAgICA8L3NwYW4+XG4gICAgICA8c3BhbiAqbmdTd2l0Y2hDYXNlPVwiJ2ZldGNoaW5nJ1wiIFtAZmFkZUluT3V0XT1cIidpbidcIj5cbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtc3BpbiBmYS1zcGlubmVyIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgICBMb29raW5nIHVwIGFjY291bnQuLi5cbiAgICAgIDwvc3Bhbj5cbiAgICAgIDxzcGFuICpuZ1N3aXRjaENhc2U9XCInZmV0Y2hlZCdcIiBbQGZhZGVJbk91dF09XCInaW4nXCI+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNoZWNrIGZhLWZ3IHRleHQtc3VjY2Vzc1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgICAgPHNwYW4gKm5nSWY9XCJhY2NvdW50RXhpc3RzXCI+QWNjb3VudCBmb3VuZC48L3NwYW4+XG4gICAgICAgIDxzcGFuICpuZ0lmPVwiYWNjb3VudElzTmV3XCI+V2UnbGwgY3JlYXRlIGFuIGFjY291bnQuPC9zcGFuPlxuICAgICAgPC9zcGFuPlxuICAgIDwvc21hbGw+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrXCI+XG4gICAgICA8aW5wdXRcbiAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCJcbiAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgW3ZhbHVlXT1cInRydWVcIlxuICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZW1lbWJlclwiXG4gICAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWxcIiBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICBSZW1lbWJlciBtZSBvbiB0aGlzIGRldmljZS5cbiAgICAgIDwvbGFiZWw+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9mb3JtPlxuPGRpdiAqbmdJZj1cIm1ldGhvZHNGZXRjaGVkICYmIGFjY291bnRFeGlzdHNcIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxzbWFsbCBjbGFzcz1cInRleHQtbXV0ZWQgbWItMSBmb3JtLXRleHRcIj5cbiAgICA8c3BhbiAqbmdJZj1cImFjY291bnRIYXNQYXNzd29yZFwiPlxuICAgICAgPHNwYW4gKm5nSWY9XCJhY2NvdW50T0F1dGhNZXRob2RzLmxlbmd0aCA9PT0gMFwiPlxuICAgICAgICBQbGVhc2Ugc2lnbiBpbiB3aXRoIHlvdXIgcGFzc3dvcmQuLi5cbiAgICAgIDwvc3Bhbj5cbiAgICAgIDxzcGFuICpuZ0lmPVwiYWNjb3VudE9BdXRoTWV0aG9kcy5sZW5ndGggPT09IDFcIj5cbiAgICAgICAgUGxlYXNlIHNpZ24gaW4gd2l0aCB5b3VyIHBhc3N3b3JkIG9yIHlvdXJcbiAgICAgICAgbGlua2VkIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUoYWNjb3VudE9BdXRoTWV0aG9kc1swXSl9fSBhY2NvdW50Li4uXG4gICAgICA8L3NwYW4+XG4gICAgICA8c3BhbiAqbmdJZj1cImFjY291bnRPQXV0aE1ldGhvZHMubGVuZ3RoID4gMVwiPlxuICAgICAgICBQbGVhc2Ugc2lnbiBpbiB3aXRoIHlvdXIgcGFzc3dvcmQgb3Igb25lIG9mIHlvdXIgbGlua2VkIGFjY291bnRzLi4uXG4gICAgICA8L3NwYW4+XG4gICAgPC9zcGFuPlxuICAgIDxzcGFuICpuZ0lmPVwiIWFjY291bnRIYXNQYXNzd29yZFwiPlxuICAgICAgPHNwYW4gKm5nSWY9XCJhY2NvdW50T0F1dGhNZXRob2RzLmxlbmd0aCA9PT0gMVwiPlxuICAgICAgICBQbGVhc2Ugc2lnbiBpbiB3aXRoIHlvdXJcbiAgICAgICAgbGlua2VkIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUoYWNjb3VudE9BdXRoTWV0aG9kc1swXSl9fSBhY2NvdW50Li4uXG4gICAgICA8L3NwYW4+XG4gICAgICA8c3BhbiAqbmdJZj1cImFjY291bnRPQXV0aE1ldGhvZHMubGVuZ3RoID4gMVwiPlxuICAgICAgICBQbGVhc2Ugc2lnbiBpbiB3aXRoIG9uZSBvZiB5b3VyIGxpbmtlZCBhY2NvdW50cy4uLlxuICAgICAgPC9zcGFuPlxuICAgIDwvc3Bhbj5cblxuICA8L3NtYWxsPlxuXG4gIDxkaXYgY2xhc3M9XCJsaXN0LWdyb3VwXCI+XG4gICAgPGFcbiAgICAgICpuZ0lmPVwiYWNjb3VudEhhc1Bhc3N3b3JkXCJcbiAgICAgIHJvdXRlckxpbms9XCIuXCJcbiAgICAgIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluUGFzc3dvcmQnfVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBjbGFzcz1cImZhcyBmYS1sb2NrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgPHNwYW4gY2xhc3M9XCJtbC0yXCI+XG4gICAgICAgIFNpZ24gSW4gd2l0aCBZb3VyIFBhc3N3b3JkXG4gICAgICA8L3NwYW4+XG4gICAgPC9hPlxuICAgIDxhXG4gICAgICAqbmdGb3I9XCJsZXQgaWQgb2YgYWNjb3VudE9BdXRoTWV0aG9kc1wiXG4gICAgICByb3V0ZXJMaW5rPVwiLlwiXG4gICAgICBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbk9BdXRoJywgcHJvdmlkZXJJZDogaWR9XCJcbiAgICAgIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGxpc3QtZ3JvdXAtaXRlbS1hY3Rpb25cIj5cbiAgICAgIDxpIFthdHRyLmNsYXNzXT1cImdldE9BdXRoUHJvdmlkZXJJY29uKGlkKVwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIDxzcGFuIGNsYXNzPVwibWwtMlwiPlxuICAgICAgICBTaWduIEluIHdpdGgge3tnZXRPQXV0aFByb3ZpZGVyTmFtZShpZCl9fVxuICAgICAgPC9zcGFuPlxuICAgIDwvYT5cbiAgPC9kaXY+XG48L2Rpdj5cblxuPGRpdiAqbmdJZj1cIm1ldGhvZHNGZXRjaGVkICYmIGFjY291bnRJc05ld1wiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZCBtYi0xIGZvcm0tdGV4dFwiPlxuICAgIDxzcGFuICpuZ0lmPVwib0F1dGhQcm92aWRlcklkcy5sZW5ndGggPT09IDBcIj5cbiAgICAgIFBsZWFzZSBjcmVhdGUgYW4gYWNjb3VudC4uLlxuICAgIDwvc3Bhbj5cbiAgICA8c3BhbiAqbmdJZj1cIm9BdXRoUHJvdmlkZXJJZHMubGVuZ3RoID09PSAxXCI+XG4gICAgICBQbGVhc2Ugc2lnbiB1cCB3aXRoIHlvdXJcbiAgICAgIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUob0F1dGhQcm92aWRlcklkc1swXSl9fSBhY2NvdW50LFxuICAgICAgb3IgY3JlYXRlIGEgc2VwYXJhdGUgYWNjb3VudCB3aXRoIGEgcGFzc3dvcmQuLi4uXG4gICAgPC9zcGFuPlxuICAgIDxzcGFuICpuZ0lmPVwib0F1dGhQcm92aWRlcklkcy5sZW5ndGggPjFcIj5cbiAgICAgIFBsZWFzZSBzaWduIHVwIHdpdGggb25lIG9mIHRoZSBzZXJ2aWNlcyBsaXN0ZWQgYmVsb3csXG4gICAgICBvciBjcmVhdGUgYSBzZXBhcmF0ZSBhY2NvdW50IHdpdGggYSBwYXNzd29yZC4uLi5cbiAgICA8L3NwYW4+XG4gIDwvc21hbGw+XG4gIDxkaXYgY2xhc3M9XCJsaXN0LWdyb3VwXCI+XG5cbiAgICA8YVxuICAgICAgKm5nRm9yPVwibGV0IGlkIG9mIG9BdXRoUHJvdmlkZXJJZHNcIlxuICAgICAgcm91dGVyTGluaz1cIi5cIlxuICAgICAgW3F1ZXJ5UGFyYW1zXT1cInthY3Rpb246ICdzaWduSW5PQXV0aCcsIHByb3ZpZGVySWQ6IGlkfVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBbYXR0ci5jbGFzc109XCJnZXRPQXV0aFByb3ZpZGVySWNvbihpZClcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICA8c3BhbiBjbGFzcz1cIm1sLTJcIj5cbiAgICAgICAgU2lnbiBVcCB3aXRoIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUoaWQpfX1cbiAgICAgIDwvc3Bhbj5cbiAgICA8L2E+XG4gICAgPGFcbiAgICAgIHJvdXRlckxpbms9XCIuXCJcbiAgICAgIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnblVwUGFzc3dvcmQnfVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBjbGFzcz1cImZhcyBmYS1sb2NrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgPHNwYW4gY2xhc3M9XCJtbC0yXCI+XG4gICAgICAgIENyZWF0ZVxuICAgICAgICA8c3BhbiAqbmdJZj1cIm9BdXRoUHJvdmlkZXJJZHMubGVuZ3RoID4gMFwiPlxuICAgICAgICAgIGEgU2VwYXJhdGVcbiAgICAgICAgPC9zcGFuPlxuICAgICAgICBBY2NvdW50XG4gICAgICA8L3NwYW4+XG4gICAgPC9hPlxuICA8L2Rpdj5cbjwvZGl2PlxuYCxcbiAgc3R5bGVzOiBbYGBdLFxuICBhbmltYXRpb25zOiBbZmFkZUluT3V0QW5pbWF0aW9uLCBzY3JlZW5BbmltYXRpb25dXG59KVxuZXhwb3J0IGNsYXNzIFNpZ25Jbk1ldGhvZHNGb3JtQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0IHtcblxuXG4gIEBWaWV3Q2hpbGQoJ2VtYWlsSW5wdXQnKSBlbWFpbElucHV0OiBFbGVtZW50UmVmO1xuICBASW5wdXQoKSBlbWFpbDogc3RyaW5nO1xuICBASW5wdXQoKSByZW1lbWJlcjogYm9vbGVhbjtcbiAgQElucHV0KCkgb0F1dGhQcm92aWRlcklkczogc3RyaW5nW10gPSBbXTtcbiAgQE91dHB1dCgpIGVtYWlsQ2hhbmdlOiBFdmVudEVtaXR0ZXI8c3RyaW5nPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHJlbWVtYmVyQ2hhbmdlOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBzdWNjZXNzOiBFdmVudEVtaXR0ZXI8YXV0aC5Vc2VyQ3JlZGVudGlhbD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBlcnJvcjogRXZlbnRFbWl0dGVyPGF1dGguRXJyb3I+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG5cbiAgZm9ybUlkID0gJ25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4tbWV0aG9kcy1mb3JtLSc7XG4gIHN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgZmc6IEZvcm1Hcm91cDtcbiAgZW1haWxGYzogRm9ybUNvbnRyb2w7XG4gIHJlbWVtYmVyRmM6IEZvcm1Db250cm9sO1xuICBnZXRPQXV0aFByb3ZpZGVySWNvbiA9IGdldE9BdXRoUHJvdmlkZXJJY29uO1xuICBnZXRPQXV0aFByb3ZpZGVyTmFtZSA9IGdldE9BdXRoUHJvdmlkZXJOYW1lO1xuICBtZXRob2RzRm9yRW1haWw6IElTaWduSW5NZXRob2RzRm9yRW1haWxSZXN1bHQgPSB7c3RhdHVzOiAndW5mZXRjaGVkJywgbWV0aG9kczogW10sIGVtYWlsOiBudWxsfTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgICBwcml2YXRlIF9hdXRoU2VydmljZTogTmd4RmlyZWJhc2VBdXRoU2VydmljZSxcbiAgICBwcml2YXRlIF9uZ1pvbmU6IE5nWm9uZVxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG4gIGdldCBhdXRoU2VydmljZSgpOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIHtcbiAgICByZXR1cm4gdGhpcy5fYXV0aFNlcnZpY2U7XG4gIH1cblxuXG4gIGdldCBtZXRob2RzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5tZXRob2RzRm9yRW1haWwubWV0aG9kcztcbiAgfVxuXG4gIGdldCBmZXRjaFN0YXR1cygpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLm1ldGhvZHNGb3JFbWFpbC5zdGF0dXM7XG4gIH1cblxuICBnZXQgbWV0aG9kc0ZldGNoZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubWV0aG9kc0ZvckVtYWlsLnN0YXR1cyA9PT0gJ2ZldGNoZWQnO1xuICB9XG5cbiAgZ2V0IGFjY291bnRJc05ldygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5tZXRob2RzRmV0Y2hlZCAmJiB0aGlzLm1ldGhvZHMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgZ2V0IGFjY291bnRFeGlzdHMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubWV0aG9kc0ZldGNoZWQgJiYgdGhpcy5tZXRob2RzLmxlbmd0aCA+IDA7XG4gIH1cblxuICBnZXQgYWNjb3VudEhhc1Bhc3N3b3JkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmFjY291bnRFeGlzdHMgJiYgdGhpcy5tZXRob2RzLmluZGV4T2YoJ3Bhc3N3b3JkJykgIT09IC0xO1xuICB9XG5cbiAgZ2V0IGFjY291bnRPQXV0aE1ldGhvZHMoKTogc3RyaW5nW10ge1xuICAgIGlmICghIHRoaXMuYWNjb3VudEV4aXN0cykge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5tZXRob2RzLmZpbHRlcihpZCA9PiBpZCAhPT0gJ3Bhc3N3b3JkJyk7XG4gIH1cblxuXG5cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmVtYWlsRmMgPSBuZXcgRm9ybUNvbnRyb2woXG4gICAgICB0aGlzLmVtYWlsLFxuICAgICAge3ZhbGlkYXRvcnM6IFtWYWxpZGF0b3JzLnJlcXVpcmVkLCBWYWxpZGF0b3JzLmVtYWlsXX1cbiAgICApO1xuICAgIHRoaXMucmVtZW1iZXJGYyA9IG5ldyBGb3JtQ29udHJvbCh0aGlzLnJlbWVtYmVyKTtcbiAgICB0aGlzLnJlbWVtYmVyRmMudmFsdWVDaGFuZ2VzLnN1YnNjcmliZSgoKSA9PiB0aGlzLnJlbWVtYmVyQ2hhbmdlLmVtaXQodGhpcy5yZW1lbWJlckZjLnZhbHVlKSk7XG4gICAgdGhpcy5mZyA9IG5ldyBGb3JtR3JvdXAoe2VtYWlsOiB0aGlzLmVtYWlsRmMsIHJlbWVtYmVyOiB0aGlzLnJlbWVtYmVyRmN9KTtcbiAgICB0aGlzLmVtYWlsRmMudmFsdWVDaGFuZ2VzLnN1YnNjcmliZSgoKSA9PiB0aGlzLmVtYWlsQ2hhbmdlLmVtaXQodGhpcy5lbWFpbEZjLnZhbHVlLnRyaW0oKSkpO1xuICAgIHRoaXMuZW1haWxGYy52YWx1ZUNoYW5nZXMucGlwZShkZWJvdW5jZVRpbWUoNTAwKSkuc3Vic2NyaWJlKCgpID0+IHRoaXMuZmV0Y2goKSk7XG4gICAgdGhpcy5mZXRjaCgpO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHRoaXMuZW1haWxJbnB1dC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG5cbiAgfVxuXG5cbiAgZmV0Y2goKSB7XG4gICAgY29uc3QgZW1haWwgPSB0aGlzLmVtYWlsRmMudmFsdWUudHJpbSgpO1xuICAgIGlmIChlbWFpbCA9PT0gdGhpcy5tZXRob2RzRm9yRW1haWwuZW1haWwpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKCdmZXRjaGluZycgPT09IHRoaXMubWV0aG9kc0ZvckVtYWlsLnN0YXR1cykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLm1ldGhvZHNGb3JFbWFpbCA9IHtzdGF0dXM6ICdmZXRjaGluZycsIG1ldGhvZHM6IFtdLCBlbWFpbDogZW1haWx9O1xuICAgIGlmICh0aGlzLmVtYWlsRmMuaW52YWxpZCkge1xuICAgICAgdGhpcy5tZXRob2RzRm9yRW1haWwgPSB7c3RhdHVzOiAndW5mZXRjaGVkJywgbWV0aG9kczogW10sIGVtYWlsOiBlbWFpbH07XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuYXV0aC5mZXRjaFNpZ25Jbk1ldGhvZHNGb3JFbWFpbChlbWFpbClcbiAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICB0aGlzLm1ldGhvZHNGb3JFbWFpbCA9IHtzdGF0dXM6ICdmZXRjaGVkJywgbWV0aG9kczogcmVzdWx0cywgZW1haWw6IGVtYWlsfTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGVycm9yOiBhdXRoLkVycm9yKSA9PiB7XG4gICAgICAgIHRoaXMuZW1haWxGYy5tYXJrQXNEaXJ0eSgpO1xuICAgICAgICB0aGlzLmVtYWlsRmMubWFya0FzVG91Y2hlZCgpO1xuICAgICAgICBzd2l0Y2ggKGVycm9yLmNvZGUpIHtcbiAgICAgICAgICBjYXNlICdhdXRoL2ludmFsaWQtZW1haWwnOlxuICAgICAgICAgICAgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlci5zZXRFcnJvclVudGlsQ2hhbmdlZCh0aGlzLmVtYWlsRmMsIGVycm9yLmNvZGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5tZXRob2RzRm9yRW1haWwgPSB7ZW1haWw6IHRoaXMuZW1haWwsIHN0YXR1czogJ3VuZmV0Y2hlZCcsIG1ldGhvZHM6IFtdfTtcbiAgICAgIH0pO1xuICB9XG5cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBBZnRlclZpZXdJbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIFZpZXdDaGlsZCwgRWxlbWVudFJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGggfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuXG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyIH0gZnJvbSAnLi4vLi4vZm9ybS1oZWxwZXInO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB9IGZyb20gJy4uLy4uL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UnO1xuaW1wb3J0IHsgZ2V0T0F1dGhQcm92aWRlckljb24sIGdldE9BdXRoUHJvdmlkZXJOYW1lLCBmYWRlSW5PdXRBbmltYXRpb24gfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuXG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4tZm9ybScsXG4gIHRlbXBsYXRlOiBgPGZvcm0gW2Zvcm1Hcm91cF09XCJmZ1wiIChuZ1N1Ym1pdCk9XCJzdWJtaXQoKVwiPlxuXG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGxhYmVsIFthdHRyLmZvcl09XCJmb3JtSWQgKyAnZW1haWwnXCI+RW1haWwgQWRkcmVzczwvbGFiZWw+XG5cbiAgICA8aW5wdXRcbiAgICAgIHJlYWRvbmx5XG4gICAgICAjZW1haWxJbnB1dFxuICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiXG4gICAgICBbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cImZvcm1JZCArICdlbWFpbCdcIlxuICAgICAgdHlwZT1cImVtYWlsXCJcbiAgICAgIGF1dG9jb21wbGV0ZT1cImVtYWlsXCJcbiAgICAgIHBsYWNlaG9sZGVyPVwiRW1haWwgQWRkcmVzc1wiXG4gICAgICBmb3JtQ29udHJvbE5hbWU9XCJlbWFpbFwiXG4gICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ3JlcXVpcmVkJylcIj5cbiAgICAgIFJlcXVpcmVkLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ2VtYWlsJylcIj5cbiAgICAgIEludmFsaWQgZW1haWwuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy5oYXNFcnJvcignYXV0aC9pbnZhbGlkLWVtYWlsJylcIj5cbiAgICAgIEludmFsaWQgZW1haWwuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy5oYXNFcnJvcignYXV0aC91c2VyLW5vdC1mb3VuZCcpXCI+XG4gICAgICBXZSBjb3VsZCBub3QgZmluZCBhbiBhY2NvdW50IHdpdGggdGhhdCBlbWFpbCBhZGRyZXNzLlxuICAgICAgPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbid9XCI+Q3JlYXRlIEFjY291bnQ8L2E+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy5oYXNFcnJvcignYXV0aC91c2VyLWRpc2FibGVkJylcIj5cbiAgICAgIFRoZSBhY2NvdW50IHdpdGggdGhhdCBlbWFpbCBhZGRyZXNzIGhhcyBiZWVuIGRpc2FibGVkLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ25neC1maXJlYmFzZS1hdXRoL25vLXBhc3N3b3JkJylcIj5cbiAgICAgIFRoZSBhY2NvdW50IHdpdGggdGhhdCBlbWFpbCBhZGRyZXNzIGRvZXMgbm90IGhhdmUgYSBwYXNzd29yZC5cbiAgICAgIFBsZWFzZSBzaWduIGluIHVzaW5nOlxuICAgICAgPHNwYW4gKm5nRm9yPVwibGV0IGlkIG9mIG1ldGhvZHNGb3JFbWFpbDsgbGV0IGlzTGFzdCA9IGxhc3RcIj5cbiAgICAgICAgPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbk9BdXRoJywgcHJvdmlkZXJJZDogaWR9XCI+e3tnZXRPQXV0aFByb3ZpZGVyTmFtZShpZCl9fTwvYT5cbiAgICAgICAgPHNwYW4gKm5nSWY9XCIhaXNMYXN0XCI+XG4gICAgICAgICAgfFxuICAgICAgICA8L3NwYW4+XG4gICAgICA8L3NwYW4+XG4gICAgPC9kaXY+XG5cbiAgICA8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkIGZvcm0tdGV4dFwiIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbCdcIiA+XG4gICAgICBOb3QgeW91ciBlbWFpbCBhZGRyZXNzP1xuICAgICAgPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbid9XCI+U3RhcnQgT3ZlcjwvYT5cbiAgICA8L3NtYWxsPlxuICA8L2Rpdj5cblxuXG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1lbmRcIj5cbiAgICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkJ1wiPlBhc3N3b3JkPC9sYWJlbD5cbiAgICAgIDxzbWFsbD5cbiAgICAgICAgPGEgKGNsaWNrKT1cIiRldmVudC5wcmV2ZW50RGVmYXVsdCgpOyBwYXNzd29yZElucHV0LnR5cGUgPSAncGFzc3dvcmQnID09PSBwYXNzd29yZElucHV0LnR5cGUgID8gJ3RleHQnIDogJ3Bhc3N3b3JkJ1wiXG4gICAgICAgICAgaHJlZj1cIiNcIiB0YWJpbmRleD1cIi0xXCIgY2xhc3M9XCJkLWlubGluZS1ibG9ja1wiPlxuICAgICAgICAgIDxzcGFuICpuZ0lmPVwiJ3Bhc3N3b3JkJyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlXCI+U2hvdzwvc3Bhbj5cbiAgICAgICAgICA8c3BhbiAqbmdJZj1cIid0ZXh0JyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlXCI+SGlkZTwvc3Bhbj5cbiAgICAgICAgPC9hPlxuICAgICAgPC9zbWFsbD5cbiAgICA8L2Rpdj5cbiAgICA8aW5wdXRcbiAgICAgICNwYXNzd29yZElucHV0XG4gICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAncGFzc3dvcmQnXCJcbiAgICAgIFthdHRyLmFyaWEtZGVzY3JpYmVkYnldPVwiZm9ybUlkICsgJ3Bhc3N3b3JkLWhlbHAnXCJcbiAgICAgIHR5cGU9XCJwYXNzd29yZFwiXG4gICAgICBmb3JtQ29udHJvbE5hbWU9XCJwYXNzd29yZFwiXG4gICAgICBwbGFjZWhvbGRlcj1cIlBhc3N3b3JkXCJcbiAgICAgIGF1dG9jb21wbGV0ZT1cInBhc3N3b3JkXCJcbiAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgIFtjbGFzcy5pcy1pbnZhbGlkXT1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmludmFsaWRcIj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiXG4gICAgICAqbmdJZj1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCJcbiAgICAgIFtAZmFkZUluT3V0XT1cIidpbidcIj5cbiAgICAgIFJlcXVpcmVkLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCJcbiAgICAgICpuZ0lmPVwicGFzc3dvcmRGYy50b3VjaGVkICYmIHBhc3N3b3JkRmMuaGFzRXJyb3IoJ2F1dGgvd3JvbmctcGFzc3dvcmQnKVwiXG4gICAgICBbQGZhZGVJbk91dF09XCInaW4nXCI+XG4gICAgICBXcm9uZyBwYXNzd29yZC5cbiAgICA8L2Rpdj5cbiAgICA8c21hbGwgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkLWhlbHAnXCIgY2xhc3M9XCJmb3JtLXRleHQgdGV4dC1tdXRlZFwiPlxuICAgICAgRm9yZ290PyA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAncmVzZXRQYXNzd29yZCd9XCI+UmVzZXQgUGFzc3dvcmQ8L2E+XG4gICAgPC9zbWFsbD5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2tcIj5cbiAgICAgIDxpbnB1dFxuICAgICAgICBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIlxuICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICBbdmFsdWVdPVwidHJ1ZVwiXG4gICAgICAgIGZvcm1Db250cm9sTmFtZT1cInJlbWVtYmVyXCJcbiAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbFwiIFthdHRyLmZvcl09XCJmb3JtSWQgKyAncmVtZW1iZXInXCI+XG4gICAgICAgIFJlbWVtYmVyIG1lIG9uIHRoaXMgZGV2aWNlLlxuICAgICAgPC9sYWJlbD5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGJ1dHRvbiB0eXBlPVwic3VibWl0XCJcbiAgICAgIGNsYXNzPVwiYnRuIGJ0bi1zdWNjZXNzIGJ0bi1ibG9ja1wiXG4gICAgICBbZGlzYWJsZWRdPVwiZmcuaW52YWxpZCB8fCBzdWJtaXR0aW5nXCI+XG4gICAgICA8aSBjbGFzcz1cImZhcyBmYS1sb2NrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgU2lnbiBJblxuICAgIDwvYnV0dG9uPlxuICA8L2Rpdj5cbjwvZm9ybT5cbmAsXG4gIHN0eWxlczogW2BgXSxcbiAgYW5pbWF0aW9uczogW2ZhZGVJbk91dEFuaW1hdGlvbl1cbn0pXG5leHBvcnQgY2xhc3MgU2lnbkluRm9ybUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XG5cbiAgQFZpZXdDaGlsZCgncGFzc3dvcmRJbnB1dCcpIHBhc3N3b3JkSW5wdXQ6IEVsZW1lbnRSZWY7XG4gIEBJbnB1dCgpIGVtYWlsOiBzdHJpbmc7XG4gIEBJbnB1dCgpIHJlbWVtYmVyOiBib29sZWFuO1xuICBAT3V0cHV0KCkgcmVtZW1iZXJDaGFuZ2U6IEV2ZW50RW1pdHRlcjxib29sZWFuPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHN1Y2Nlc3M6IEV2ZW50RW1pdHRlcjxhdXRoLlVzZXJDcmVkZW50aWFsPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIGVycm9yOiBFdmVudEVtaXR0ZXI8YXV0aC5FcnJvcj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgZm9ybUlkID0gJ25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4tZm9ybS0nO1xuICBzdWJtaXR0aW5nID0gZmFsc2U7XG4gIGZnOiBGb3JtR3JvdXA7XG4gIGVtYWlsRmM6IEZvcm1Db250cm9sO1xuICBwYXNzd29yZEZjOiBGb3JtQ29udHJvbDtcbiAgcmVtZW1iZXJGYzogRm9ybUNvbnRyb2w7XG4gIG1ldGhvZHNGb3JFbWFpbDogc3RyaW5nW10gPSBbXTtcbiAgZ2V0T0F1dGhQcm92aWRlckljb24gPSBnZXRPQXV0aFByb3ZpZGVySWNvbjtcbiAgZ2V0T0F1dGhQcm92aWRlck5hbWUgPSBnZXRPQXV0aFByb3ZpZGVyTmFtZTtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICAgcHJpdmF0ZSBfYXV0aFNlcnZpY2U6IE5neEZpcmViYXNlQXV0aFNlcnZpY2VcbiAgKSB7IH1cblxuICBnZXQgYXV0aCgpOiBhdXRoLkF1dGgge1xuICAgIHJldHVybiB0aGlzLl9hZkF1dGguYXV0aDtcbiAgfVxuXG4gIGdldCBhdXRoU2VydmljZSgpOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIHtcbiAgICByZXR1cm4gdGhpcy5fYXV0aFNlcnZpY2U7XG4gIH1cblxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuZW1haWxGYyA9IG5ldyBGb3JtQ29udHJvbChcbiAgICAgIHRoaXMuZW1haWwsXG4gICAgICB7dmFsaWRhdG9yczogW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMuZW1haWxdfVxuICAgICk7XG4gICAgdGhpcy5wYXNzd29yZEZjID0gbmV3IEZvcm1Db250cm9sKCcnLCB7dmFsaWRhdG9yczogW1ZhbGlkYXRvcnMucmVxdWlyZWRdfSk7XG4gICAgdGhpcy5yZW1lbWJlckZjID0gbmV3IEZvcm1Db250cm9sKHRoaXMucmVtZW1iZXIpO1xuICAgIHRoaXMucmVtZW1iZXJGYy52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKHZhbCA9PiB0aGlzLnJlbWVtYmVyQ2hhbmdlLmVtaXQodmFsKSk7XG4gICAgdGhpcy5mZyA9IG5ldyBGb3JtR3JvdXAoe1xuICAgICAgZW1haWw6IHRoaXMuZW1haWxGYyxcbiAgICAgIHBhc3N3b3JkOiB0aGlzLnBhc3N3b3JkRmMsXG4gICAgICByZW1lbWJlcjogdGhpcy5yZW1lbWJlckZjXG4gICAgfSk7XG4gIH1cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHRoaXMucGFzc3dvcmRJbnB1dC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gIH1cblxuXG5cbiAgc3VibWl0KCkge1xuICAgIGNvbnN0IGVtYWlsID0gdGhpcy5lbWFpbEZjLnZhbHVlLnRyaW0oKTtcbiAgICB0aGlzLnN1Ym1pdHRpbmcgPSB0cnVlO1xuICAgIHRoaXMubWV0aG9kc0ZvckVtYWlsID0gW107XG4gICAgbGV0IGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWw7XG4gICAgdGhpcy5hdXRoLmZldGNoU2lnbkluTWV0aG9kc0ZvckVtYWlsKGVtYWlsKVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgIHRoaXMubWV0aG9kc0ZvckVtYWlsID0gcmVzdWx0cztcbiAgICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHtcbiAgICAgICAgICAgIGNvZGU6ICdhdXRoL3VzZXItbm90LWZvdW5kJ1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZXN1bHRzLmluZGV4T2YoJ3Bhc3N3b3JkJykgPT09IC0xKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHtcbiAgICAgICAgICAgIGNvZGU6ICduZ3gtZmlyZWJhc2UtYXV0aC9uby1wYXNzd29yZCcsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aC5zaWduSW5XaXRoRW1haWxBbmRQYXNzd29yZChlbWFpbCwgdGhpcy5wYXNzd29yZEZjLnZhbHVlKTtcbiAgICAgIH0pXG4gICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICBjcmVkID0gcmVzdWx0O1xuICAgICAgICByZXR1cm4gdGhpcy5hdXRoU2VydmljZS5zZXRSZW1lbWJlcmVkKHRoaXMucmVtZW1iZXJGYy52YWx1ZSA9PT0gdHJ1ZSwgZW1haWwpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy5zdWNjZXNzLmVtaXQoY3JlZCk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgdGhpcy5zdWJtaXR0aW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZW1haWxGYy5tYXJrQXNEaXJ0eSgpO1xuICAgICAgICB0aGlzLmVtYWlsRmMubWFya0FzVG91Y2hlZCgpO1xuICAgICAgICB0aGlzLnBhc3N3b3JkRmMubWFya0FzRGlydHkoKTtcbiAgICAgICAgdGhpcy5wYXNzd29yZEZjLm1hcmtBc1RvdWNoZWQoKTtcbiAgICAgICAgc3dpdGNoIChlcnJvci5jb2RlKSB7XG4gICAgICAgICAgY2FzZSAnYXV0aC9pbnZhbGlkLWVtYWlsJzpcbiAgICAgICAgICBjYXNlICdhdXRoL3VzZXItbm90LWZvdW5kJzpcbiAgICAgICAgICBjYXNlICdhdXRoL3VzZXItZGlzYWJsZWQnOlxuICAgICAgICAgIGNhc2UgJ25neC1maXJlYmFzZS1hdXRoL25vLXBhc3N3b3JkJzpcbiAgICAgICAgICAgIE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIuc2V0RXJyb3JVbnRpbENoYW5nZWQodGhpcy5lbWFpbEZjLCBlcnJvci5jb2RlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ2F1dGgvd3JvbmctcGFzc3dvcmQnOlxuICAgICAgICAgICAgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlci5zZXRFcnJvclVudGlsQ2hhbmdlZCh0aGlzLnBhc3N3b3JkRmMsIGVycm9yLmNvZGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRoaXMuZXJyb3IuZW1pdChlcnJvcik7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxufVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIEFmdGVyVmlld0luaXQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgVmlld0NoaWxkLCBFbGVtZW50UmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtQ29udHJvbCwgRm9ybUdyb3VwLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgQW5ndWxhckZpcmVBdXRoIH0gZnJvbSAnYW5ndWxhcmZpcmUyL2F1dGgnO1xuaW1wb3J0IHsgYXV0aCB9IGZyb20gJ2ZpcmViYXNlL2FwcCc7XG5cbmltcG9ydCB7IGZhZGVJbk91dEFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyIH0gZnJvbSAnLi4vLi4vZm9ybS1oZWxwZXInO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB9IGZyb20gJy4uLy4uL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UnO1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWZpcmViYXNlLWF1dGgtc2lnbi11cC1mb3JtJyxcbiAgdGVtcGxhdGU6IGA8Zm9ybSBbZm9ybUdyb3VwXT1cImZnXCIgKG5nU3VibWl0KT1cInN1Ym1pdCgpXCI+XG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGxhYmVsIFthdHRyLmZvcl09XCJmb3JtSWQgKyAnZW1haWwnXCI+RW1haWwgQWRkcmVzczwvbGFiZWw+XG4gICAgPGlucHV0XG4gICAgICByZWFkb25seVxuICAgICAgI2VtYWlsSW5wdXRcbiAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbCdcIlxuICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJmb3JtSWQgKyAnZW1haWwnXCJcbiAgICAgIHR5cGU9XCJlbWFpbFwiXG4gICAgICBhdXRvY29tcGxldGU9XCJlbWFpbFwiXG4gICAgICBwbGFjZWhvbGRlcj1cIkVtYWlsIEFkZHJlc3NcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiZW1haWxcIlxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICBSZXF1aXJlZC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLmhhc0Vycm9yKCdlbWFpbCcpXCI+XG4gICAgICBJbnZhbGlkIGVtYWlsLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ2F1dGgvaW52YWxpZC1lbWFpbCcpXCI+XG4gICAgICBJbnZhbGlkIGVtYWlsLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ25neC1maXJlYmFzZS1hdXRoL2FjY291bnQtZXhpc3RzJylcIj5cbiAgICAgIFdlIGZvdW5kIGFuIGFjY291bnQgd2l0aCB0aGF0IGVtYWlsIGFkZHJlc3MuXG4gICAgICA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluJ31cIj5TaWduIEluPC9hPlxuICAgIDwvZGl2PlxuICAgIDxzbWFsbCBjbGFzcz1cInRleHQtbXV0ZWQgZm9ybS10ZXh0XCIgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiID5cbiAgICAgIE5vdCB5b3VyIGVtYWlsIGFkZHJlc3M/XG4gICAgICA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluJ31cIj5HbyBCYWNrPC9hPlxuICAgIDwvc21hbGw+XG4gIDwvZGl2PlxuXG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1lbmRcIj5cbiAgICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkJ1wiPkNob29zZSBQYXNzd29yZDwvbGFiZWw+XG4gICAgICA8c21hbGw+XG4gICAgICAgIDxhIChjbGljayk9XCIkZXZlbnQucHJldmVudERlZmF1bHQoKTsgcGFzc3dvcmRJbnB1dC50eXBlID0gJ3Bhc3N3b3JkJyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlICA/ICd0ZXh0JyA6ICdwYXNzd29yZCdcIlxuICAgICAgICAgIGhyZWY9XCIjXCIgdGFiaW5kZXg9XCItMVwiIGNsYXNzPVwiZC1pbmxpbmUtYmxvY2tcIj5cbiAgICAgICAgICA8c3BhbiAqbmdJZj1cIidwYXNzd29yZCcgPT09IHBhc3N3b3JkSW5wdXQudHlwZVwiPlNob3c8L3NwYW4+XG4gICAgICAgICAgPHNwYW4gKm5nSWY9XCIndGV4dCcgPT09IHBhc3N3b3JkSW5wdXQudHlwZVwiPkhpZGU8L3NwYW4+XG4gICAgICAgIDwvYT5cbiAgICAgIDwvc21hbGw+XG4gICAgPC9kaXY+XG4gICAgPGlucHV0XG4gICAgICAjcGFzc3dvcmRJbnB1dFxuICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkJ1wiXG4gICAgICBbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cImZvcm1JZCArICdwYXNzd29yZC1oZWxwJ1wiXG4gICAgICB0eXBlPVwicGFzc3dvcmRcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicGFzc3dvcmRcIlxuICAgICAgcGxhY2Vob2xkZXI9XCJDaG9vc2UgUGFzc3dvcmRcIlxuICAgICAgYXV0b2NvbXBsZXRlPVwicGFzc3dvcmRcIlxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwicGFzc3dvcmRGYy50b3VjaGVkICYmIHBhc3N3b3JkRmMuaW52YWxpZFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICBSZXF1aXJlZC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJwYXNzd29yZEZjLnRvdWNoZWQgJiYgcGFzc3dvcmRGYy5oYXNFcnJvcignYXV0aC93cm9uZy1wYXNzd29yZCcpXCI+XG4gICAgICBXcm9uZyBwYXNzd29yZC5cbiAgICA8L2Rpdj5cbiAgICA8c21hbGwgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkLWhlbHAnXCIgY2xhc3M9XCJmb3JtLXRleHQgdGV4dC1tdXRlZFwiPlxuICAgICAgUGxlYXNlIGNob29zZSBhIHN0cm9uZyBwYXNzd29yZC5cbiAgICA8L3NtYWxsPlxuICA8L2Rpdj5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8bGFiZWwgW2F0dHIuZm9yXT1cImZvcm1JZCArICduYW1lJ1wiPllvdXIgTmFtZTwvbGFiZWw+XG4gICAgPGlucHV0XG4gICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAnbmFtZSdcIlxuICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwibmFtZVwiXG4gICAgICBwbGFjZWhvbGRlcj1cIllvdXIgTmFtZVwiXG4gICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICBbY2xhc3MuaXMtaW52YWxpZF09XCJuYW1lRmMudG91Y2hlZCAmJiBuYW1lRmMuaW52YWxpZFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cIm5hbWVGYy50b3VjaGVkICYmIG5hbWVGYy5oYXNFcnJvcigncmVxdWlyZWQnKVwiPlxuICAgICAgUmVxdWlyZWQuXG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrXCI+XG4gICAgICA8aW5wdXRcbiAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCJcbiAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgW3ZhbHVlXT1cInRydWVcIlxuICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZW1lbWJlclwiXG4gICAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWxcIiBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICBSZW1lbWJlciBtZSBvbiB0aGlzIGRldmljZS5cbiAgICAgIDwvbGFiZWw+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxidXR0b24gdHlwZT1cInN1Ym1pdFwiXG4gICAgICBjbGFzcz1cImJ0biBidG4tc3VjY2VzcyBidG4tYmxvY2tcIlxuICAgICAgW2Rpc2FibGVkXT1cImZnLmludmFsaWQgfHwgc3VibWl0dGluZ1wiPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtbG9jayBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIENyZWF0ZSBBY2NvdW50XG4gICAgPC9idXR0b24+XG4gIDwvZGl2PlxuPC9mb3JtPlxuYCxcbiAgc3R5bGVzOiBbYGBdLFxuICBhbmltYXRpb25zOiBbIGZhZGVJbk91dEFuaW1hdGlvbiBdXG59KVxuZXhwb3J0IGNsYXNzIFNpZ25VcEZvcm1Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQge1xuXG4gIEBWaWV3Q2hpbGQoJ3Bhc3N3b3JkSW5wdXQnKSBwYXNzd29yZElucHV0OiBFbGVtZW50UmVmO1xuICBASW5wdXQoKSBlbWFpbDogc3RyaW5nO1xuICBASW5wdXQoKSByZW1lbWJlcjogYm9vbGVhbjtcbiAgQE91dHB1dCgpIHJlbWVtYmVyQ2hhbmdlOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBzdWNjZXNzOiBFdmVudEVtaXR0ZXI8YXV0aC5Vc2VyQ3JlZGVudGlhbD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBlcnJvcjogRXZlbnRFbWl0dGVyPGF1dGguRXJyb3I+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIGZvcm1JZCA9ICduZ3gtZmlyZWJhc2UtYXV0aC1zaWduLXVwLWZvcm0tJztcbiAgc3VibWl0dGluZyA9IGZhbHNlO1xuICBmZzogRm9ybUdyb3VwO1xuICBlbWFpbEZjOiBGb3JtQ29udHJvbDtcbiAgcGFzc3dvcmRGYzogRm9ybUNvbnRyb2w7XG4gIG5hbWVGYzogRm9ybUNvbnRyb2w7XG4gIHJlbWVtYmVyRmM6IEZvcm1Db250cm9sO1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgICBwcml2YXRlIF9hdXRoU2VydmljZTogTmd4RmlyZWJhc2VBdXRoU2VydmljZVxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG5cbiAgZ2V0IGF1dGhTZXJ2aWNlKCk6IE5neEZpcmViYXNlQXV0aFNlcnZpY2Uge1xuICAgIHJldHVybiB0aGlzLl9hdXRoU2VydmljZTtcbiAgfVxuXG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5lbWFpbEZjID0gbmV3IEZvcm1Db250cm9sKFxuICAgICAgdGhpcy5lbWFpbCxcbiAgICAgIHt2YWxpZGF0b3JzOiBbVmFsaWRhdG9ycy5yZXF1aXJlZCwgVmFsaWRhdG9ycy5lbWFpbF19XG4gICAgKTtcbiAgICB0aGlzLnBhc3N3b3JkRmMgPSBuZXcgRm9ybUNvbnRyb2woJycsIHt2YWxpZGF0b3JzOiBbVmFsaWRhdG9ycy5yZXF1aXJlZF19KTtcbiAgICB0aGlzLm5hbWVGYyA9IG5ldyBGb3JtQ29udHJvbCgnJywge3ZhbGlkYXRvcnM6IFtWYWxpZGF0b3JzLnJlcXVpcmVkLCBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyLnJlcXVpcmVkTm9uRW1wdHldfSk7XG4gICAgdGhpcy5yZW1lbWJlckZjID0gbmV3IEZvcm1Db250cm9sKHRoaXMucmVtZW1iZXIpO1xuICAgIHRoaXMucmVtZW1iZXJGYy52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKHZhbCA9PiB0aGlzLnJlbWVtYmVyQ2hhbmdlLmVtaXQodmFsKSk7XG4gICAgdGhpcy5mZyA9IG5ldyBGb3JtR3JvdXAoe1xuICAgICAgZW1haWw6IHRoaXMuZW1haWxGYyxcbiAgICAgIHBhc3N3b3JkOiB0aGlzLnBhc3N3b3JkRmMsXG4gICAgICBuYW1lOiB0aGlzLm5hbWVGYyxcbiAgICAgIHJlbWVtYmVyOiB0aGlzLnJlbWVtYmVyRmNcbiAgICB9KTtcbiAgfVxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgdGhpcy5wYXNzd29yZElucHV0Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgfVxuXG4gIHN1Ym1pdCgpIHtcblxuICAgIHRoaXMuc3VibWl0dGluZyA9IHRydWU7XG4gICAgbGV0IGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWw7XG4gICAgdGhpcy5hdXRoLmZldGNoU2lnbkluTWV0aG9kc0ZvckVtYWlsKHRoaXMuZW1haWwpXG4gICAgICAudGhlbigocmVzdWx0cykgPT4ge1xuICAgICAgICBpZiAocmVzdWx0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHtcbiAgICAgICAgICAgIGNvZGU6ICduZ3gtZmlyZWJhc2UtYXV0aC9hY2NvdW50LWV4aXN0cydcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5hdXRoLmNyZWF0ZVVzZXJXaXRoRW1haWxBbmRQYXNzd29yZCh0aGlzLmVtYWlsLCB0aGlzLnBhc3N3b3JkRmMudmFsdWUpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICAgIGNyZWQgPSByZXN1bHQ7XG4gICAgICAgIHJldHVybiBjcmVkLnVzZXIudXBkYXRlUHJvZmlsZSh7ZGlzcGxheU5hbWU6IHRoaXMubmFtZUZjLnZhbHVlLnRyaW0oKSwgcGhvdG9VUkw6IG51bGx9KTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGhTZXJ2aWNlLnNldFJlbWVtYmVyZWQodGhpcy5yZW1lbWJlckZjLnZhbHVlID09PSB0cnVlLCB0aGlzLmVtYWlsKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMuc3VjY2Vzcy5lbWl0KGNyZWQpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIHRoaXMuc3VibWl0dGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmVtYWlsRmMubWFya0FzRGlydHkoKTtcbiAgICAgICAgdGhpcy5lbWFpbEZjLm1hcmtBc1RvdWNoZWQoKTtcbiAgICAgICAgdGhpcy5wYXNzd29yZEZjLm1hcmtBc0RpcnR5KCk7XG4gICAgICAgIHRoaXMucGFzc3dvcmRGYy5tYXJrQXNUb3VjaGVkKCk7XG4gICAgICAgIHN3aXRjaCAoZXJyb3IuY29kZSkge1xuICAgICAgICAgIGNhc2UgJ2F1dGgvaW52YWxpZC1lbWFpbCc6XG4gICAgICAgICAgY2FzZSAnbmd4LWZpcmViYXNlLWF1dGgvYWNjb3VudC1leGlzdHMnOlxuICAgICAgICAgICAgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlci5zZXRFcnJvclVudGlsQ2hhbmdlZCh0aGlzLmVtYWlsRmMsIGVycm9yLmNvZGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnYXV0aC93ZWFrLXBhc3N3b3JkJzpcbiAgICAgICAgICAgIE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIuc2V0RXJyb3JVbnRpbENoYW5nZWQodGhpcy5wYXNzd29yZEZjLCBlcnJvci5jb2RlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0aGlzLmVycm9yLmVtaXQoZXJyb3IpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBBZnRlclZpZXdJbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIFZpZXdDaGlsZCwgRWxlbWVudFJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGggfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlciB9IGZyb20gJy4uLy4uL2Zvcm0taGVscGVyJztcbmltcG9ydCB7IGZhZGVJbk91dEFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLXJlc2V0LXBhc3N3b3JkLXNlbmQtZm9ybScsXG4gIHRlbXBsYXRlOiBgPGZvcm0gW2Zvcm1Hcm91cF09XCJmZ1wiIChuZ1N1Ym1pdCk9XCJzdWJtaXQoKVwiPlxuICA8ZGl2ICpuZ0lmPVwic2VudFwiIFtAZmFkZUluT3V0XT1cIidpbidcIj5cbiAgICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc3VjY2Vzc1wiPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtY2hlY2sgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICBXZcOiwoDCmXZlIHNlbnQgYSByZXNldCBwYXNzd29yZCBsaW5rIHRvIHt7c2VudH19LlxuICAgICAgUGxlYXNlIGFsbG93IGEgZmV3IG1vbWVudHMgZm9yIHRoZSBlbWFpbCB0byBhcnJpdmUuXG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuXG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGxhYmVsIFthdHRyLmZvcl09XCJmb3JtSWQgKyAnZW1haWwnXCI+RW1haWwgQWRkcmVzczwvbGFiZWw+XG4gICAgPGlucHV0XG4gICAgICAjZW1haWxJbnB1dFxuICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiXG4gICAgICBbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cImZvcm1JZCArICdlbWFpbC1oZWxwJ1wiXG4gICAgICB0eXBlPVwiZW1haWxcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiZW1haWxcIlxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwiZW1haWxGYy50b3VjaGVkICYmIGVtYWlsRmMuaW52YWxpZFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMudG91Y2hlZCAmJiBlbWFpbEZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICBSZXF1aXJlZC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLnRvdWNoZWQgJiYgZW1haWxGYy5oYXNFcnJvcignYXV0aC91c2VyLW5vdC1mb3VuZCcpXCI+XG4gICAgICBXZSBjb3VsZCBub3QgZmluZCBhbiBhY2NvdW50IHdpdGggdGhhdCBlbWFpbCBhZGRyZXNzLlxuICAgICAgUGxlYXNlIDxhIHJvdXRlckxpbms9XCIuXCIgW3F1ZXJ5UGFyYW1zXT1cInthY3Rpb246ICdzaWduSVVwUGFzc3dvcmQnfVwiPnNpZ24gdXA8L2E+LlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMudG91Y2hlZCAmJiBlbWFpbEZjLmhhc0Vycm9yKCdlbWFpbCcpXCI+XG4gICAgICBJbnZhbGlkIGVtYWlsLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMudG91Y2hlZCAmJiBlbWFpbEZjLmhhc0Vycm9yKCdhdXRoL2ludmFsaWQtZW1haWwnKVwiPlxuICAgICAgSW52YWxpZCBlbWFpbC5cbiAgICA8L2Rpdj5cbiAgICA8c21hbGwgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsLWhlbHAnXCIgY2xhc3M9XCJmb3JtLXRleHQgdGV4dC1tdXRlZFwiPlxuICAgICAgRW50ZXIgdGhlIGVtYWlsIGFkZHJlc3MgeW91IHVzZWQgdG8gc2lnbiB1cC4gV2XDosKAwplsbFxuICAgICAgc2VuZCBhIHJlc2V0IHBhc3N3b3JkIGxpbmsgdG8gdGhhdCBhZGRyZXNzLlxuICAgIDwvc21hbGw+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxidXR0b24gdHlwZT1cInN1Ym1pdFwiXG4gICAgICBjbGFzcz1cImJ0biBidG4tYmxvY2sgYnRuLXN1Y2Nlc3NcIlxuICAgICAgW2Rpc2FibGVkXT1cImZnLmludmFsaWQgfHwgc3VibWl0dGluZ1wiPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtZncgZmEtZW52ZWxvcGVcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICBTZW5kIExpbmtcbiAgICA8L2J1dHRvbj5cbiAgPC9kaXY+XG48L2Zvcm0+XG5gLFxuICBzdHlsZXM6IFtgYF0sXG4gIGFuaW1hdGlvbnM6IFtmYWRlSW5PdXRBbmltYXRpb25dXG59KVxuZXhwb3J0IGNsYXNzIFJlc2V0UGFzc3dvcmRTZW5kRm9ybUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XG5cbiAgQFZpZXdDaGlsZCgnZW1haWxJbnB1dCcpIGVtYWlsSW5wdXQ6IEVsZW1lbnRSZWY7XG4gIEBJbnB1dCgpIGVtYWlsOiBzdHJpbmc7XG4gIEBPdXRwdXQoKSBlbWFpbENoYW5nZTogRXZlbnRFbWl0dGVyPHN0cmluZz4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBlcnJvcjogRXZlbnRFbWl0dGVyPGF1dGguRXJyb3I+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIGZvcm1JZCA9ICduZ3gtZmlyZWJhc2UtYXV0aC1yZXNldC1wYXNzd29yZC1zZW5kLWZvcm0tJztcbiAgZmc6IEZvcm1Hcm91cDtcbiAgZW1haWxGYzogRm9ybUNvbnRyb2w7XG4gIHN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgc2VudDogc3RyaW5nID0gbnVsbDtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICkgeyB9XG5cbiAgZ2V0IGF1dGgoKTogYXV0aC5BdXRoIHtcbiAgICByZXR1cm4gdGhpcy5fYWZBdXRoLmF1dGg7XG4gIH1cblxuXG5cblxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuZW1haWxGYyA9IG5ldyBGb3JtQ29udHJvbChcbiAgICAgIHRoaXMuZW1haWwsXG4gICAgICB7dmFsaWRhdG9yczogW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMuZW1haWxdfVxuICAgICk7XG4gICAgdGhpcy5lbWFpbEZjLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUoKCkgPT4gdGhpcy5lbWFpbENoYW5nZS5lbWl0KHRoaXMuZW1haWxGYy52YWx1ZS50cmltKCkpKTtcbiAgICB0aGlzLmZnID0gbmV3IEZvcm1Hcm91cCh7ZW1haWw6IHRoaXMuZW1haWxGY30pO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHRoaXMuZW1haWxJbnB1dC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gIH1cblxuXG4gIHN1Ym1pdCgpIHtcbiAgICBjb25zdCBlbWFpbCA9IHRoaXMuZW1haWxGYy52YWx1ZS50cmltKCk7XG4gICAgdGhpcy5zdWJtaXR0aW5nID0gdHJ1ZTtcbiAgICB0aGlzLnNlbnQgPSBudWxsO1xuICAgIHRoaXMuYXV0aC5zZW5kUGFzc3dvcmRSZXNldEVtYWlsKGVtYWlsKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLnN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5zZW50ID0gZW1haWw7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcjogYXV0aC5FcnJvcikgPT4ge1xuICAgICAgICB0aGlzLnN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5lbWFpbEZjLm1hcmtBc1RvdWNoZWQoKTtcbiAgICAgICAgdGhpcy5lbWFpbEZjLm1hcmtBc0RpcnR5KCk7XG4gICAgICAgIHN3aXRjaCAoZXJyb3IuY29kZSkge1xuICAgICAgICAgIGNhc2UgJ2F1dGgvaW52YWxpZC1lbWFpbCc6XG4gICAgICAgICAgY2FzZSAnYXV0aC91c2VyLW5vdC1mb3VuZCc6XG4gICAgICAgICAgICBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyLnNldEVycm9yVW50aWxDaGFuZ2VkKHRoaXMuZW1haWxGYywgZXJyb3IuY29kZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhpcy5lcnJvci5lbWl0KGVycm9yKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuXG4gIH1cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlLCBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgYXV0aCB9IGZyb20gJ2ZpcmViYXNlL2FwcCc7XG5pbXBvcnQgeyBGb3JtR3JvdXAsIEZvcm1Db250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBnZXRPQXV0aFByb3ZpZGVySWNvbiwgZ2V0T0F1dGhQcm92aWRlck5hbWUgfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB9IGZyb20gJy4uLy4uL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UnO1xuaW1wb3J0IHsgc2NyZWVuQW5pbWF0aW9uIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcblxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW9hdXRoJyxcbiAgdGVtcGxhdGU6IGA8ZGl2ICpuZ0lmPVwiJ3dhaXQnID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1zZWNvbmRhcnlcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1zcGluIGZhLXNwaW5uZXIgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgUGxlYXNlIHdhaXQuLi5cbiAgPC9kaXY+XG48L2Rpdj5cblxuPGRpdiAqbmdJZj1cIidtZXRob2RFcnJvcicgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlclwiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFdlIGNvdWxkIG5vdCBzaWduIHlvdSBpbiB3aXRoIHt7bWV0aG9kRXJyb3IuY3JlZGVudGlhbC5wcm92aWRlcklkfX0uXG4gIDwvZGl2PlxuXG4gIDxwIGNsYXNzPVwidGV4dC1tdXRlZFwiPlxuICAgIFBsZWFzZSBzaWduIGluIHdpdGggb25lIG9mIHRoZSBtZXRob2RzIGFzc29jaWF0ZWQgd2l0aFxuICAgIHt7bWV0aG9kRXJyb3IuZW1haWx9fTpcbiAgPC9wPlxuXG4gIDxkaXYgY2xhc3M9XCJsaXN0LWdyb3VwXCI+XG4gICAgPGFcbiAgICAgICpuZ0lmPVwibWV0aG9kRXJyb3IuYWNjb3VudEhhc1Bhc3N3b3JkXCJcbiAgICAgIHJvdXRlckxpbms9XCIuXCJcbiAgICAgIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluUGFzc3dvcmQnfVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBjbGFzcz1cImZhcyBmYS11bmxvY2tcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICA8c3BhbiBjbGFzcz1cIm1sLTJcIj5TaWduIEluIHdpdGggWW91ciBQYXNzd29yZDwvc3Bhbj5cbiAgICA8L2E+XG4gICAgPGJ1dHRvblxuICAgICAgKm5nRm9yPVwibGV0IGlkIG9mIG1ldGhvZEVycm9yLmFjY291bnRPQXV0aE1ldGhvZHNcIlxuICAgICAgKGNsaWNrKT1cIm9BdXRoU2lnbkluKGlkKVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBbYXR0ci5jbGFzc109XCJnZXRPQXV0aFByb3ZpZGVySWNvbihpZClcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICA8c3BhbiBjbGFzcz1cIm1sLTJcIj5TaWduIEluIHdpdGgge3tnZXRPQXV0aFByb3ZpZGVyTmFtZShpZCl9fTwvc3Bhbj5cbiAgICA8L2J1dHRvbj5cbiAgPC9kaXY+XG5cbiAgPGZvcm0gW2Zvcm1Hcm91cF09XCJmZ1wiPlxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1jaGVja1wiPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIlxuICAgICAgICAgIHR5cGU9XCJjaGVja2JveFwiXG4gICAgICAgICAgW3ZhbHVlXT1cInRydWVcIlxuICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInJlbWVtYmVyXCJcbiAgICAgICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAncmVtZW1iZXInXCI+XG4gICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWxcIiBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICAgIFJlbWVtYmVyIG1lIG9uIHRoaXMgZGV2aWNlLlxuICAgICAgICA8L2xhYmVsPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZm9ybT5cblxuICA8cCBjbGFzcz1cInRleHQtbXV0ZWRcIj5cbiAgICBJcyB7e21ldGhvZEVycm9yLmVtYWlsfX0gbm90IHlvdXIgZW1haWwgYWRkcmVzcz9cbiAgICA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluJ31cIj5TdGFydCBPdmVyPC9hPlxuICA8L3A+XG5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwiJ3JldHJ5JyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtZGFuZ2VyXCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGUgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgSXQgbG9va3MgbGlrZSB5b3UgY2FuY2VsbGVkIHNpZ25pbmcgaW4gd2l0aFxuICAgIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUocHJvdmlkZXJJZCl9fS4gVHJ5IGFnYWluOlxuICA8L2Rpdj5cblxuICA8ZGl2IGNsYXNzPVwibGlzdC1ncm91cFwiPlxuICAgIDxidXR0b25cbiAgICAgIChjbGljayk9XCJvQXV0aFNpZ25Jbihwcm92aWRlcklkKVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBbYXR0ci5jbGFzc109XCJnZXRPQXV0aFByb3ZpZGVySWNvbihwcm92aWRlcklkKVwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIDxzcGFuIGNsYXNzPVwibWwtMlwiPlNpZ24gSW4gd2l0aCB7e2dldE9BdXRoUHJvdmlkZXJOYW1lKHByb3ZpZGVySWQpfX08L3NwYW4+XG4gICAgPC9idXR0b24+XG4gIDwvZGl2PlxuXG4gIDxmb3JtIFtmb3JtR3JvdXBdPVwiZmdcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2tcIj5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCJcbiAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAgIFt2YWx1ZV09XCJ0cnVlXCJcbiAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZW1lbWJlclwiXG4gICAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsXCIgW2F0dHIuZm9yXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgICAgICBSZW1lbWJlciBtZSBvbiB0aGlzIGRldmljZS5cbiAgICAgICAgPC9sYWJlbD5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L2Zvcm0+XG5cblxuICA8cCBjbGFzcz1cInRleHQtbXV0ZWRcIj5cbiAgICA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluJ31cIj5TdGFydCBPdmVyPC9hPlxuICA8L3A+XG5cbjwvZGl2PlxuYCxcbiAgc3R5bGVzOiBbYGBdLFxuICBhbmltYXRpb25zOiBbIHNjcmVlbkFuaW1hdGlvbiBdXG59KVxuZXhwb3J0IGNsYXNzIFNpZ25Jbk9hdXRoQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBASW5wdXQoKSBwcm92aWRlcklkOiBzdHJpbmc7XG4gIEBJbnB1dCgpIGluaXRpYWxFcnJvcjogYXV0aC5FcnJvcjtcbiAgQElucHV0KCkgdXNlT0F1dGhQb3B1cDogYm9vbGVhbjtcbiAgQElucHV0KCkgb0F1dGhQcm92aWRlckZhY3Rvcnk6IChwcm92aWRlcklkOiBzdHJpbmcpID0+IGF1dGguQXV0aFByb3ZpZGVyO1xuICBASW5wdXQoKSBlbWFpbDogc3RyaW5nO1xuICBASW5wdXQoKSByZW1lbWJlcjogYm9vbGVhbjtcbiAgQE91dHB1dCgpIHN1Y2Nlc3M6IEV2ZW50RW1pdHRlcjxhdXRoLlVzZXJDcmVkZW50aWFsPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIGVtYWlsQ2hhbmdlOiBFdmVudEVtaXR0ZXI8c3RyaW5nPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHJlbWVtYmVyQ2hhbmdlOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBlcnJvcjogRXZlbnRFbWl0dGVyPGF1dGguRXJyb3I+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG5cbiAgc2NyZWVuOiAnd2FpdCcgfCAnbWV0aG9kRXJyb3InIHwgJ3JldHJ5JyA9ICd3YWl0JztcbiAgbWV0aG9kRXJyb3I6IGF1dGguRXJyb3J8YW55ID0gbnVsbDtcbiAgZ2V0T0F1dGhQcm92aWRlckljb24gPSBnZXRPQXV0aFByb3ZpZGVySWNvbjtcbiAgZ2V0T0F1dGhQcm92aWRlck5hbWUgPSBnZXRPQXV0aFByb3ZpZGVyTmFtZTtcbiAgZmc6IEZvcm1Hcm91cDtcbiAgcmVtZW1iZXJGYzogRm9ybUNvbnRyb2w7XG4gIGZvcm1JZCA9ICduZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW9hdXRoLSc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICAgcHJpdmF0ZSBfc3ZjOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlLFxuICAgIHByaXZhdGUgX3JvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICBwcml2YXRlIF9yb3V0ZXI6IFJvdXRlclxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG5cbiAgZ2V0IGF1dGhTZXJ2aWNlKCk6IE5neEZpcmViYXNlQXV0aFNlcnZpY2Uge1xuICAgIHJldHVybiB0aGlzLl9zdmM7XG4gIH1cblxuICBnZXQgcm91dGUoKTogQWN0aXZhdGVkUm91dGUge1xuICAgIHJldHVybiB0aGlzLl9yb3V0ZTtcbiAgfVxuXG4gIGdldCByb3V0ZXIoKTogUm91dGVyIHtcbiAgICByZXR1cm4gdGhpcy5fcm91dGVyO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5yZW1lbWJlckZjID0gbmV3IEZvcm1Db250cm9sKHRoaXMucmVtZW1iZXIpO1xuICAgIHRoaXMucmVtZW1iZXJGYy52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKHZhbCA9PiB0aGlzLnJlbWVtYmVyQ2hhbmdlLmVtaXQodmFsKSk7XG4gICAgdGhpcy5mZyA9IG5ldyBGb3JtR3JvdXAoe1xuICAgICAgcmVtZW1iZXI6IHRoaXMucmVtZW1iZXJGY1xuICAgIH0pO1xuICAgIGlmICh0aGlzLmluaXRpYWxFcnJvcikge1xuICAgICAgdGhpcy5oYW5kbGVPQXV0aEVycm9yKHRoaXMuaW5pdGlhbEVycm9yKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5vQXV0aFNpZ25Jbih0aGlzLnByb3ZpZGVySWQpO1xuICAgIH1cbiAgfVxuXG5cbiAgb0F1dGhTaWduSW4oaWQ6IHN0cmluZywgZm9yY2VSZWRpcmVjdD86IGJvb2xlYW4pIHtcbiAgICB0aGlzLm1ldGhvZEVycm9yID0gbnVsbDtcbiAgICBsZXQgY3JlZDogYXV0aC5Vc2VyQ3JlZGVudGlhbDtcbiAgICBpZiAodGhpcy51c2VPQXV0aFBvcHVwICAmJiBmb3JjZVJlZGlyZWN0ICE9PSB0cnVlKSB7XG4gICAgICB0aGlzLmdldE9BdXRoUHJvdmlkZXIoaWQpXG4gICAgICAgIC50aGVuKHByb3ZpZGVyID0+IHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5hdXRoLnNpZ25JbldpdGhQb3B1cChwcm92aWRlcik7XG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKChyZXN1bHQ6IGF1dGguVXNlckNyZWRlbnRpYWwpID0+IHtcbiAgICAgICAgICBjcmVkID0gcmVzdWx0O1xuICAgICAgICAgIHJldHVybiB0aGlzLmF1dGhTZXJ2aWNlLnNldFJlbWVtYmVyZWQodGhpcy5yZW1lbWJlckZjLnZhbHVlID09PSB0cnVlLCByZXN1bHQudXNlci5lbWFpbCk7XG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICB0aGlzLnN1Y2Nlc3MuZW1pdChjcmVkKTtcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHRoaXMuaGFuZGxlT0F1dGhFcnJvcihlcnJvciwgaWQpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoWycuJ10sIHtyZWxhdGl2ZVRvOiB0aGlzLnJvdXRlLCBxdWVyeVBhcmFtczoge3JlbWVtYmVyOiB0aGlzLnJlbWVtYmVyRmMudmFsdWUgPT09IHRydWV9fSlcbiAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHJldHVybiB0aGlzLmdldE9BdXRoUHJvdmlkZXIoaWQpO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbihwcm92aWRlciA9PiB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuYXV0aC5zaWduSW5XaXRoUmVkaXJlY3QocHJvdmlkZXIpO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4gdGhpcy5oYW5kbGVPQXV0aEVycm9yKGVycm9yLCBpZCkpO1xuICAgIH1cbiAgfVxuXG4gIGhhbmRsZU9BdXRoRXJyb3IoZXJyb3I6IGF1dGguRXJyb3IsIHByb3ZpZGVySWQ/OiBzdHJpbmcpIHtcbiAgICBpZiAoZXJyb3JbJ2VtYWlsJ10gJiYgZXJyb3JbJ2NyZWRlbnRpYWwnXSkge1xuICAgICAgdGhpcy5lbWFpbENoYW5nZS5lbWl0KGVycm9yWydlbWFpbCddKTtcbiAgICAgIHRoaXMuYXV0aC5mZXRjaFNpZ25Jbk1ldGhvZHNGb3JFbWFpbChlcnJvclsnZW1haWwnXSlcbiAgICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgICAgZXJyb3JbJ21ldGhvZHMnXSA9IHJlc3VsdHM7XG4gICAgICAgICAgZXJyb3JbJ2FjY291bnRIYXNQYXNzd29yZCddID0gcmVzdWx0cy5pbmRleE9mKCdwYXNzd29yZCcpICE9PSAtMTtcbiAgICAgICAgICBlcnJvclsnYWNjb3VudE9BdXRoTWV0aG9kcyddID0gcmVzdWx0cy5maWx0ZXIoaWQgPT4gaWQgIT09ICdwYXNzd29yZCcpO1xuICAgICAgICAgIHRoaXMubWV0aG9kRXJyb3IgPSBlcnJvcjtcbiAgICAgICAgICB0aGlzLnNjcmVlbiA9ICdtZXRob2RFcnJvcic7XG4gICAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBzd2l0Y2ggKGVycm9yLmNvZGUpIHtcbiAgICAgIGNhc2UgJ2F1dGgvY2FuY2VsbGVkLXBvcHVwLXJlcXVlc3QnOlxuICAgICAgY2FzZSAnYXV0aC9wb3B1cC1jbG9zZWQtYnktdXNlcic6XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ3JldHJ5JztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdhdXRoL3BvcHVwLWJsb2NrZWQnOlxuICAgICAgICB0aGlzLm9BdXRoU2lnbkluKHByb3ZpZGVySWQsIHRydWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRoaXMuZXJyb3IuZW1pdChlcnJvcik7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIGdldE9BdXRoUHJvdmlkZXIoaWQ6IHN0cmluZyk6IFByb21pc2U8YXV0aC5BdXRoUHJvdmlkZXI+IHtcbiAgICBsZXQgcHJvdmlkZXI6IGF1dGguQXV0aFByb3ZpZGVyID0gbnVsbDtcbiAgICBpZiAodGhpcy5vQXV0aFByb3ZpZGVyRmFjdG9yeSkge1xuICAgICAgcHJvdmlkZXIgPSB0aGlzLm9BdXRoUHJvdmlkZXJGYWN0b3J5KGlkKTtcbiAgICB9XG4gICAgaWYgKCEgcHJvdmlkZXIpIHtcbiAgICAgIHN3aXRjaCAoaWQpIHtcbiAgICAgICAgY2FzZSAndHdpdHRlci5jb20nOlxuICAgICAgICAgIHByb3ZpZGVyID0gbmV3IGF1dGguVHdpdHRlckF1dGhQcm92aWRlcigpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdmYWNlYm9vay5jb20nOlxuICAgICAgICAgIHByb3ZpZGVyID0gbmV3IGF1dGguRmFjZWJvb2tBdXRoUHJvdmlkZXIoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZ29vZ2xlLmNvbSc6XG4gICAgICAgICAgcHJvdmlkZXIgPSBuZXcgYXV0aC5Hb29nbGVBdXRoUHJvdmlkZXIoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZ2l0aHViLmNvbSc6XG4gICAgICAgICAgcHJvdmlkZXIgPSBuZXcgYXV0aC5HaXRodWJBdXRoUHJvdmlkZXIoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHByb3ZpZGVyKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHByb3ZpZGVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHtcbiAgICAgICAgY29kZTogJ25neC1maXJlYmFzZS1hdXRoL25vLXByb3ZpZGVyLWZvdW5kJyxcbiAgICAgICAgbWVzc2FnZTogYFdlIGNvdWxkIG5vdCBjcmVhdGUgYW4gT0F1dGggcHJvdmlkZXIgZm9yIHByb3ZpZGVyIGlkIFwiJHtpZH1cIi5gXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxufVxuIiwiaW1wb3J0IHsgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIH0gZnJvbSAnLi9uZ3gtZmlyZWJhc2UtYXV0aC5zZXJ2aWNlJztcblxuXG5cblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZVxuICBdLFxuICBwcm92aWRlcnM6IFtcbiAgICBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgTmd4RmlyZWJhc2VBdXRoTW9kdWxlIHsgfVxuIiwiaW1wb3J0IHsgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBSb3V0ZXJNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgUmVhY3RpdmVGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IFNpZ25JbkNvbXBvbmVudCB9IGZyb20gJy4vc2lnbi1pbi5jb21wb25lbnQnO1xuaW1wb3J0IHsgU2lnbkluTWV0aG9kc0Zvcm1Db21wb25lbnQgfSBmcm9tICcuL3NpZ24taW4tbWV0aG9kcy1mb3JtL3NpZ24taW4tbWV0aG9kcy1mb3JtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBTaWduSW5Gb3JtQ29tcG9uZW50IH0gZnJvbSAnLi9zaWduLWluLWZvcm0vc2lnbi1pbi1mb3JtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBTaWduVXBGb3JtQ29tcG9uZW50IH0gZnJvbSAnLi9zaWduLXVwLWZvcm0vc2lnbi11cC1mb3JtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBSZXNldFBhc3N3b3JkU2VuZEZvcm1Db21wb25lbnQgfSBmcm9tICcuL3Jlc2V0LXBhc3N3b3JkLXNlbmQtZm9ybS9yZXNldC1wYXNzd29yZC1zZW5kLWZvcm0uY29tcG9uZW50JztcbmltcG9ydCB7IFNpZ25Jbk9hdXRoQ29tcG9uZW50IH0gZnJvbSAnLi9zaWduLWluLW9hdXRoL3NpZ24taW4tb2F1dGguY29tcG9uZW50JztcblxuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoTW9kdWxlIH0gZnJvbSAnLi4vbmd4LWZpcmViYXNlLWF1dGgubW9kdWxlJztcblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSxcbiAgICBSZWFjdGl2ZUZvcm1zTW9kdWxlLFxuICAgIFJvdXRlck1vZHVsZSxcbiAgICBOZ3hGaXJlYmFzZUF1dGhNb2R1bGVcbiAgXSxcbiAgZGVjbGFyYXRpb25zOiBbXG4gICAgU2lnbkluQ29tcG9uZW50LFxuICAgIFNpZ25Jbk1ldGhvZHNGb3JtQ29tcG9uZW50LFxuICAgIFNpZ25JbkZvcm1Db21wb25lbnQsXG4gICAgU2lnblVwRm9ybUNvbXBvbmVudCxcbiAgICBSZXNldFBhc3N3b3JkU2VuZEZvcm1Db21wb25lbnQsXG4gICAgU2lnbkluT2F1dGhDb21wb25lbnQsXG4gIF0sXG4gIGV4cG9ydHM6IFtcbiAgICBTaWduSW5Db21wb25lbnQsXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgTmd4RmlyZWJhc2VBdXRoU2lnbkluTW9kdWxlIHsgfVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUdyb3VwLCBGb3JtQ29udHJvbCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGgsIFVzZXIgfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgSU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3MgfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlciB9IGZyb20gJy4uLy4uL2Zvcm0taGVscGVyJztcbmltcG9ydCB7IE5neEZpcmViYXNlQXV0aFNlcnZpY2UgfSBmcm9tICcuLi8uLi9uZ3gtZmlyZWJhc2UtYXV0aC5zZXJ2aWNlJztcbmltcG9ydCB7IHNjcmVlbkFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLW9vYi1yZXNldC1wYXNzd29yZCcsXG4gIHRlbXBsYXRlOiBgPGRpdiAqbmdJZj1cIid3YWl0JyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc2Vjb25kYXJ5XCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtc3BpbiBmYS1zcGlubmVyIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFBsZWFzZSB3YWl0Li4uXG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCInc3VjY2VzcycgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXN1Y2Nlc3NcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1jaGVjayBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICBXZWxjb21lLCB7e2NyZWQudXNlci5kaXNwbGF5TmFtZX19IVxuICAgIFlvdXIgbmV3IHBhc3N3b3JkIGhhcyBiZWVuIHNhdmVkIGFuZCB5b3UgYXJlIHNpZ25lZCBpbi5cbiAgPC9kaXY+XG48L2Rpdj5cblxuPGRpdiAqbmdJZj1cInNjcmVlbiA9PT0gJ2Vycm9yJ1wiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlclwiPlxuICAgIDxwPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGUgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICBXb29wcyEgQW4gZXJyb3Igb2NjdXJyZWQuXG4gICAgPC9wPlxuICAgIDxkaXYgW25nU3dpdGNoXT1cInVuaGFuZGxlZEVycm9yLmNvZGVcIj5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC9leHBpcmVkLWFjdGlvbi1jb2RlJ1wiPlxuICAgICAgICBUaGUgcmVzZXQgcGFzc3dvcmQgbGluayB5b3UgdXNlZCBoYXMgZXhwaXJlZC5cbiAgICAgIDwvcD5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC9pbnZhbGlkLWFjdGlvbi1jb2RlJ1wiPlxuICAgICAgICBUaGUgcmVzZXQgcGFzc3dvcmQgbGluayB5b3UgdXNlZCBpcyBub3QgdmFsaWQuIFRoaXMgbWF5IGJlIGJlY2F1c2UgaXRcbiAgICAgICAgaGFzIGFscmVhZHkgYmVlbiB1c2VkLlxuICAgICAgPC9wPlxuICAgICAgPHAgY2xhc3M9XCJtYi0wXCIgKm5nU3dpdGNoQ2FzZT1cIidhdXRoL3VzZXItZGlzYWJsZWQnXCI+XG4gICAgICAgIFRoZSBhY2NvdW50IGFzc29jaWF0ZWQgd2l0aCB0aGUgcmVzZXQgcGFzc3dvcmQgbGluayB5b3UgdXNlZCBoYXMgYmVlbiBkaXNhYmxlZC5cbiAgICAgIDwvcD5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC91c2VyLW5vdC1mb3VuZCdcIj5cbiAgICAgICAgVGhlIGFjY291bnQgYXNzb2NpYXRlZCB3aXRoIHRoZSByZXNldCBwYXNzd29yZCBsaW5rIHlvdSB1c2VkIGhhcyBiZWVuIHJlbW92ZWQuXG4gICAgICA8L3A+XG4gICAgICA8ZGl2ICpuZ1N3aXRjaERlZmF1bHQ+XG4gICAgICAgIDxwPkNvZGU6IHt7dW5oYW5kbGVkRXJyb3IuY29kZX19PC9wPlxuICAgICAgICA8cCBjbGFzcz1cIm1iLTBcIj5cbiAgICAgICAgICBNZXNzYWdlOiB7e3VuaGFuZGxlZEVycm9yLm1lc3NhZ2V9fVxuICAgICAgICA8L3A+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj5cblxuXG48ZGl2ICpuZ0lmPVwiJ2Zvcm0nID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxmb3JtIFtmb3JtR3JvdXBdPVwiZmdcIiAobmdTdWJtaXQpPVwic3VibWl0KClcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgPGxhYmVsIFthdHRyLmZvcl09XCJmb3JtSWQgKyAnZW1haWwnXCI+RW1haWwgQWRkcmVzczwvbGFiZWw+XG5cbiAgICAgIDxpbnB1dFxuICAgICAgICByZWFkb25seVxuICAgICAgICAjZW1haWxJbnB1dFxuICAgICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAnZW1haWwnXCJcbiAgICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJmb3JtSWQgKyAnZW1haWwnXCJcbiAgICAgICAgdHlwZT1cImVtYWlsXCJcbiAgICAgICAgYXV0b2NvbXBsZXRlPVwiZW1haWxcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIkVtYWlsIEFkZHJlc3NcIlxuICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJlbWFpbFwiXG4gICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCI+XG4gICAgICA8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkIGZvcm0tdGV4dFwiIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbCdcIiA+XG4gICAgICAgIFlvdSBhcmUgcmVzZXR0aW5nIHRoZSBwYXNzd29yZCBmb3Ige3tlbWFpbEZjLnZhbHVlfX0uXG4gICAgICA8L3NtYWxsPlxuICAgIDwvZGl2PlxuXG4gICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gYWxpZ24taXRlbXMtZW5kXCI+XG4gICAgICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkJ1wiPlBhc3N3b3JkPC9sYWJlbD5cbiAgICAgICAgPHNtYWxsPlxuICAgICAgICAgIDxhIChjbGljayk9XCIkZXZlbnQucHJldmVudERlZmF1bHQoKTsgcGFzc3dvcmRJbnB1dC50eXBlID0gJ3Bhc3N3b3JkJyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlICA/ICd0ZXh0JyA6ICdwYXNzd29yZCdcIlxuICAgICAgICAgICAgaHJlZj1cIiNcIiB0YWJpbmRleD1cIi0xXCIgY2xhc3M9XCJkLWlubGluZS1ibG9ja1wiPlxuICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCIncGFzc3dvcmQnID09PSBwYXNzd29yZElucHV0LnR5cGVcIj5TaG93PC9zcGFuPlxuICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCIndGV4dCcgPT09IHBhc3N3b3JkSW5wdXQudHlwZVwiPkhpZGU8L3NwYW4+XG4gICAgICAgICAgPC9hPlxuICAgICAgICA8L3NtYWxsPlxuICAgICAgPC9kaXY+XG4gICAgICA8aW5wdXRcbiAgICAgICAgI3Bhc3N3b3JkSW5wdXRcbiAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkJ1wiXG4gICAgICAgIFthdHRyLmFyaWEtZGVzY3JpYmVkYnldPVwiZm9ybUlkICsgJ3Bhc3N3b3JkLWhlbHAnXCJcbiAgICAgICAgdHlwZT1cInBhc3N3b3JkXCJcbiAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicGFzc3dvcmRcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIlBhc3N3b3JkXCJcbiAgICAgICAgYXV0b2NvbXBsZXRlPVwicGFzc3dvcmRcIlxuICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgIFtjbGFzcy5pcy1pbnZhbGlkXT1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmludmFsaWRcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgKm5nSWY9XCJwYXNzd29yZEZjLnRvdWNoZWQgJiYgcGFzc3dvcmRGYy5oYXNFcnJvcigncmVxdWlyZWQnKVwiPlxuICAgICAgICBSZXF1aXJlZC5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiAqbmdJZj1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmhhc0Vycm9yKCdhdXRoL3dlYWstcGFzc3dvcmQnKVwiPlxuICAgICAgICBUaGF0IHBhc3N3b3JkIGlzIHRvbyB3ZWFrLlxuICAgICAgPC9kaXY+XG4gICAgICA8c21hbGwgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkLWhlbHAnXCIgY2xhc3M9XCJmb3JtLXRleHQgdGV4dC1tdXRlZFwiPlxuICAgICAgICBQbGVhc2UgY2hvb3NlIGEgc3Ryb25nIHBhc3N3b3JkLlxuICAgICAgPC9zbWFsbD5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2tcIj5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCJcbiAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAgIFt2YWx1ZV09XCJ0cnVlXCJcbiAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZW1lbWJlclwiXG4gICAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsXCIgW2F0dHIuZm9yXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgICAgICBSZW1lbWJlciBtZSBvbiB0aGlzIGRldmljZS5cbiAgICAgICAgPC9sYWJlbD5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICA8YnV0dG9uIHR5cGU9XCJzdWJtaXRcIlxuICAgICAgICBjbGFzcz1cImJ0biBidG4tc3VjY2VzcyBidG4tYmxvY2tcIlxuICAgICAgICBbZGlzYWJsZWRdPVwiZmcuaW52YWxpZCB8fCBzdWJtaXR0aW5nXCI+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXNhdmUgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICAgIFNhdmUgUGFzc3dvcmQgYW5kIFNpZ24gSW5cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICA8L2Zvcm0+XG48L2Rpdj5cbmAsXG4gIHN0eWxlczogW2BgXSxcbiAgYW5pbWF0aW9uczogW3NjcmVlbkFuaW1hdGlvbl1cbn0pXG5leHBvcnQgY2xhc3MgT29iUmVzZXRQYXNzd29yZENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgQElucHV0KCkgb29iQ29kZTogc3RyaW5nO1xuICBAT3V0cHV0KCkgc3VjY2VzczogRXZlbnRFbWl0dGVyPElOZ3hGaXJlYmFzZUF1dGhPb2JTdWNjZXNzPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBzY3JlZW46ICd3YWl0JyB8ICdmb3JtJyB8ICdlcnJvcicgfCAnc3VjY2VzcycgPSAnd2FpdCc7XG4gIGluZm86IGF1dGguQWN0aW9uQ29kZUluZm87XG4gIHN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgZm9ybUlkID0gJ25neC1maXJlYmFzZS1hdXRoLW9vYi1yZXNldC1wYXNzd29yZC0nO1xuICBmZzogRm9ybUdyb3VwO1xuICBlbWFpbEZjOiBGb3JtQ29udHJvbDtcbiAgcGFzc3dvcmRGYzogRm9ybUNvbnRyb2w7XG4gIHJlbWVtYmVyRmM6IEZvcm1Db250cm9sO1xuICB1bmhhbmRsZWRFcnJvcjogYXV0aC5FcnJvciA9IG51bGw7XG4gIGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWwgPSBudWxsO1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgICAgIHByaXZhdGUgX2F1dGhTZXJ2aWNlOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlLFxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG4gIGdldCBhdXRoU2VydmljZSgpOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIHtcbiAgICByZXR1cm4gdGhpcy5fYXV0aFNlcnZpY2U7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICBjb25zdCByZW1lbWJlcmVkID0gdGhpcy5hdXRoU2VydmljZS5nZXRSZW1lbWJlcmVkKCk7XG4gICAgdGhpcy5lbWFpbEZjID0gbmV3IEZvcm1Db250cm9sKCcnKTtcbiAgICB0aGlzLnBhc3N3b3JkRmMgPSBuZXcgRm9ybUNvbnRyb2woJycsIHt2YWxpZGF0b3JzOiBbVmFsaWRhdG9ycy5yZXF1aXJlZF19KTtcbiAgICB0aGlzLnJlbWVtYmVyRmMgPSBuZXcgRm9ybUNvbnRyb2wocmVtZW1iZXJlZC5yZW1lbWJlcik7XG4gICAgdGhpcy5mZyA9IG5ldyBGb3JtR3JvdXAoe2VtYWlsOiB0aGlzLmVtYWlsRmMsIHBhc3N3b3JkOiB0aGlzLnBhc3N3b3JkRmMsIHJlbWVtYmVyOiB0aGlzLnJlbWVtYmVyRmN9KTtcbiAgICB0aGlzLmF1dGguY2hlY2tBY3Rpb25Db2RlKHRoaXMub29iQ29kZSlcbiAgICAgIC50aGVuKChyZXN1bHQ6IGF1dGguQWN0aW9uQ29kZUluZm8pID0+IHtcbiAgICAgICAgdGhpcy5pbmZvID0gcmVzdWx0O1xuICAgICAgICB0aGlzLmVtYWlsRmMuc2V0VmFsdWUocmVzdWx0LmRhdGEuZW1haWwpO1xuICAgICAgICB0aGlzLnNjcmVlbiA9ICdmb3JtJztcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGVycm9yOiBhdXRoLkVycm9yKSA9PiB7XG4gICAgICAgIHRoaXMudW5oYW5kbGVkRXJyb3IgPSBlcnJvcjtcbiAgICAgICAgdGhpcy5zY3JlZW4gPSAnZXJyb3InO1xuICAgICAgfSk7XG4gIH1cblxuICBzdWJtaXQoKSB7XG4gICAgdGhpcy5zdWJtaXR0aW5nID0gdHJ1ZTtcbiAgICB0aGlzLmF1dGguY29uZmlybVBhc3N3b3JkUmVzZXQodGhpcy5vb2JDb2RlLCB0aGlzLnBhc3N3b3JkRmMudmFsdWUpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGguc2lnbkluV2l0aEVtYWlsQW5kUGFzc3dvcmQodGhpcy5pbmZvLmRhdGEuZW1haWwsIHRoaXMucGFzc3dvcmRGYy52YWx1ZSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWwpID0+IHtcbiAgICAgICAgdGhpcy5jcmVkID0gY3JlZDtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aFNlcnZpY2Uuc2V0UmVtZW1iZXJlZCh0aGlzLnJlbWVtYmVyRmMudmFsdWUgPT09IHRydWUsIHRoaXMuaW5mby5kYXRhLmVtYWlsKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ3N1Y2Nlc3MnO1xuICAgICAgICB0aGlzLnN1Y2Nlc3MuZW1pdCh7XG4gICAgICAgICAgbW9kZTogJ3Jlc2V0UGFzc3dvcmQnLFxuICAgICAgICAgIGluZm86IHRoaXMuaW5mbyxcbiAgICAgICAgICBjcmVkOiB0aGlzLmNyZWQsXG4gICAgICAgICAgdXNlcjogdGhpcy5jcmVkLnVzZXJcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcjogYXV0aC5FcnJvcikgPT4ge1xuICAgICAgICB0aGlzLnN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5wYXNzd29yZEZjLm1hcmtBc0RpcnR5KCk7XG4gICAgICAgIHRoaXMucGFzc3dvcmRGYy5tYXJrQXNUb3VjaGVkKCk7XG4gICAgICAgIHN3aXRjaCAoZXJyb3IuY29kZSkge1xuICAgICAgICAgIGNhc2UgJ2F1dGgvd2Vhay1wYXNzd29yZCc6XG4gICAgICAgICAgICBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyLnNldEVycm9yVW50aWxDaGFuZ2VkKHRoaXMucGFzc3dvcmRGYywgZXJyb3IuY29kZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhpcy51bmhhbmRsZWRFcnJvciA9IGVycm9yO1xuICAgICAgICAgICAgdGhpcy5zY3JlZW4gPSAnZXJyb3InO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Hcm91cCwgRm9ybUNvbnRyb2wsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBhdXRoLCBVc2VyIH0gZnJvbSAnZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IElOZ3hGaXJlYmFzZUF1dGhPb2JTdWNjZXNzIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcbmltcG9ydCB7IHNjcmVlbkFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLW9vYi1yZWNvdmVyLWVtYWlsJyxcbiAgdGVtcGxhdGU6IGBcblxuPGRpdiAqbmdJZj1cIid3YWl0JyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc2Vjb25kYXJ5XCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtc3BpbiBmYS1zcGlubmVyIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFBsZWFzZSB3YWl0Li4uXG4gIDwvZGl2PlxuPC9kaXY+XG5cblxuPGRpdiAqbmdJZj1cIidzdWNjZXNzJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc3VjY2Vzc1wiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNoZWNrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFlvdXIgZW1haWwgaGFzIGJlZW4gY2hhbmdlZCBiYWNrIHRvIHt7aW5mby5kYXRhLmVtYWlsfX07XG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCJzY3JlZW4gPT09ICdmb3JtJ1wiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8cD5cbiAgICAgIEFyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byBjaGFuZ2UgeW91ciBlbWFpbCBiYWNrIHRvXG4gICAgICB7e2luZm8uZGF0YS5lbWFpbH19IGZyb20ge3tpbmZvLmRhdGEuZnJvbUVtYWlsfX0/XG4gICAgPC9wPlxuICAgIDxidXR0b25cbiAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgW2Rpc2FibGVkXT1cInN1Ym1pdHRpbmdcIlxuICAgICAgKGNsaWNrKT1cInN1Ym1pdCgpXCJcbiAgICAgIGNsYXNzPVwiYnRuIGJ0bi1ibG9jayBidG4tc3VjY2Vzc1wiPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtc2F2ZSBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIFllcywgQ29udGludWVcbiAgICA8L2J1dHRvbj5cbiAgPC9kaXY+XG48L2Rpdj5cblxuXG5cbjxkaXYgKm5nSWY9XCJzY3JlZW4gPT09ICdlcnJvcidcIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIj5cbiAgICA8cD5cbiAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgV29vcHMhIEFuIGVycm9yIG9jY3VycmVkLlxuICAgIDwvcD5cbiAgICA8ZGl2IFtuZ1N3aXRjaF09XCJ1bmhhbmRsZWRFcnJvci5jb2RlXCI+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvZXhwaXJlZC1hY3Rpb24tY29kZSdcIj5cbiAgICAgICAgVGhlIHJlY292ZXIgZW1haWwgbGluayB5b3UgdXNlZCBoYXMgZXhwaXJlZC5cbiAgICAgIDwvcD5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC9pbnZhbGlkLWFjdGlvbi1jb2RlJ1wiPlxuICAgICAgICBUaGUgcmVjb3ZlciBlbWFpbCBsaW5rIHlvdSB1c2VkIGlzIG5vdCB2YWxpZC4gVGhpcyBtYXkgYmUgYmVjYXVzZSBpdFxuICAgICAgICBoYXMgYWxyZWFkeSBiZWVuIHVzZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvdXNlci1kaXNhYmxlZCdcIj5cbiAgICAgICAgVGhlIGFjY291bnQgYXNzb2NpYXRlZCB3aXRoIHRoZSByZWNvdmVyIGVtYWlsIGxpbmsgeW91IHVzZWQgaGFzIGJlZW4gZGlzYWJsZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvdXNlci1ub3QtZm91bmQnXCI+XG4gICAgICAgIFRoZSBhY2NvdW50IGFzc29jaWF0ZWQgd2l0aCB0aGUgcmVjb3ZlciBlbWFpbCBsaW5rIHlvdSB1c2VkIGhhcyBiZWVuIHJlbW92ZWQuXG4gICAgICA8L3A+XG4gICAgICA8ZGl2ICpuZ1N3aXRjaERlZmF1bHQ+XG4gICAgICAgIDxwPkNvZGU6IHt7dW5oYW5kbGVkRXJyb3IuY29kZX19PC9wPlxuICAgICAgICA8cCBjbGFzcz1cIm1iLTBcIj5cbiAgICAgICAgICBNZXNzYWdlOiB7e3VuaGFuZGxlZEVycm9yLm1lc3NhZ2V9fVxuICAgICAgICA8L3A+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj5cbmAsXG4gIHN0eWxlczogW2BgXSxcbiAgYW5pbWF0aW9uczogW3NjcmVlbkFuaW1hdGlvbl1cbn0pXG5leHBvcnQgY2xhc3MgT29iUmVjb3ZlckVtYWlsQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBASW5wdXQoKSBvb2JDb2RlOiBzdHJpbmc7XG4gIEBPdXRwdXQoKSBzdWNjZXNzOiBFdmVudEVtaXR0ZXI8SU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3M+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIHNjcmVlbjogJ3dhaXQnIHwgJ2Zvcm0nIHwgJ2Vycm9yJyB8ICdzdWNjZXNzJyA9ICd3YWl0JztcbiAgaW5mbzogYXV0aC5BY3Rpb25Db2RlSW5mbztcbiAgc3VibWl0dGluZyA9IGZhbHNlO1xuICB1bmhhbmRsZWRFcnJvcjogYXV0aC5FcnJvcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgKSB7IH1cblxuICBnZXQgYXV0aCgpOiBhdXRoLkF1dGgge1xuICAgIHJldHVybiB0aGlzLl9hZkF1dGguYXV0aDtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuXG4gICAgdGhpcy5hdXRoLmNoZWNrQWN0aW9uQ29kZSh0aGlzLm9vYkNvZGUpXG4gICAgICAudGhlbigocmVzdWx0OiBhdXRoLkFjdGlvbkNvZGVJbmZvKSA9PiB7XG4gICAgICAgIHRoaXMuaW5mbyA9IHJlc3VsdDtcbiAgICAgICAgdGhpcy5zY3JlZW4gPSAnZm9ybSc7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcjogYXV0aC5FcnJvcikgPT4ge1xuICAgICAgICB0aGlzLnVuaGFuZGxlZEVycm9yID0gZXJyb3I7XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ2Vycm9yJztcbiAgICAgIH0pO1xuICB9XG5cbiAgc3VibWl0KCkge1xuICAgIHRoaXMuYXV0aC5hcHBseUFjdGlvbkNvZGUodGhpcy5vb2JDb2RlKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLnNjcmVlbiA9ICdzdWNjZXNzJztcbiAgICAgICAgdGhpcy5zdWNjZXNzLmVtaXQoe1xuICAgICAgICAgIG1vZGU6ICdyZWNvdmVyRW1haWwnLFxuICAgICAgICAgIGluZm86IHRoaXMuaW5mbyxcbiAgICAgICAgICB1c2VyOiB0aGlzLmF1dGguY3VycmVudFVzZXJcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcjogYXV0aC5FcnJvcikgPT4ge1xuICAgICAgICB0aGlzLnVuaGFuZGxlZEVycm9yID0gZXJyb3I7XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ2Vycm9yJztcbiAgICAgIH0pO1xuICB9XG5cblxufVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUdyb3VwLCBGb3JtQ29udHJvbCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGgsIFVzZXIgfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgSU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3MgfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuaW1wb3J0IHsgc2NyZWVuQW5pbWF0aW9uIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWZpcmViYXNlLWF1dGgtb29iLXZlcmlmeS1lbWFpbCcsXG4gIHRlbXBsYXRlOiBgPGRpdiAqbmdJZj1cIid3YWl0JyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc2Vjb25kYXJ5XCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtc3BpbiBmYS1zcGlubmVyIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFBsZWFzZSB3YWl0Li4uXG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCInc3VjY2VzcycgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXN1Y2Nlc3NcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1jaGVjayBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICBUaGUgZW1haWwge3tpbmZvLmRhdGEuZW1haWx9fSBoYXMgYmVlbiB2ZXJpZmllZC5cbiAgPC9kaXY+XG48L2Rpdj5cblxuPGRpdiAqbmdJZj1cInNjcmVlbiA9PT0gJ2Vycm9yJ1wiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlclwiPlxuICAgIDxwPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGUgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICBXb29wcyEgQW4gZXJyb3Igb2NjdXJyZWQuXG4gICAgPC9wPlxuICAgIDxkaXYgW25nU3dpdGNoXT1cInVuaGFuZGxlZEVycm9yLmNvZGVcIj5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC9leHBpcmVkLWFjdGlvbi1jb2RlJ1wiPlxuICAgICAgICBUaGUgdmVyaWZ5IGVtYWlsIGxpbmsgeW91IHVzZWQgaGFzIGV4cGlyZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvaW52YWxpZC1hY3Rpb24tY29kZSdcIj5cbiAgICAgICAgVGhlIHZlcmlmeSBlbWFpbCBsaW5rIHlvdSB1c2VkIGlzIG5vdCB2YWxpZC4gVGhpcyBtYXkgYmUgYmVjYXVzZSBpdFxuICAgICAgICBoYXMgYWxyZWFkeSBiZWVuIHVzZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvdXNlci1kaXNhYmxlZCdcIj5cbiAgICAgICAgVGhlIGFjY291bnQgYXNzb2NpYXRlZCB3aXRoIHRoZSB2ZXJpZnkgZW1haWwgbGluayB5b3UgdXNlZCBoYXMgYmVlbiBkaXNhYmxlZC5cbiAgICAgIDwvcD5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC91c2VyLW5vdC1mb3VuZCdcIj5cbiAgICAgICAgVGhlIGFjY291bnQgYXNzb2NpYXRlZCB3aXRoIHRoZSB2ZXJpZnkgZW1haWwgbGluayB5b3UgdXNlZCBoYXMgYmVlbiByZW1vdmVkLlxuICAgICAgPC9wPlxuICAgICAgPGRpdiAqbmdTd2l0Y2hEZWZhdWx0PlxuICAgICAgICA8cD5Db2RlOiB7e3VuaGFuZGxlZEVycm9yLmNvZGV9fTwvcD5cbiAgICAgICAgPHAgY2xhc3M9XCJtYi0wXCI+XG4gICAgICAgICAgTWVzc2FnZToge3t1bmhhbmRsZWRFcnJvci5tZXNzYWdlfX1cbiAgICAgICAgPC9wPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9kaXY+XG5gLFxuICBzdHlsZXM6IFtgYF0sXG4gIGFuaW1hdGlvbnM6IFtzY3JlZW5BbmltYXRpb25dXG59KVxuZXhwb3J0IGNsYXNzIE9vYlZlcmlmeUVtYWlsQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBASW5wdXQoKSBvb2JDb2RlOiBzdHJpbmc7XG4gIEBPdXRwdXQoKSBzdWNjZXNzOiBFdmVudEVtaXR0ZXI8SU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3M+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIHNjcmVlbjogJ3dhaXQnIHwgJ2Vycm9yJyB8ICdzdWNjZXNzJyA9ICd3YWl0JztcbiAgaW5mbzogYXV0aC5BY3Rpb25Db2RlSW5mbztcbiAgc3VibWl0dGluZyA9IGZhbHNlO1xuICB1bmhhbmRsZWRFcnJvcjogYXV0aC5FcnJvcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgKSB7IH1cblxuICBnZXQgYXV0aCgpOiBhdXRoLkF1dGgge1xuICAgIHJldHVybiB0aGlzLl9hZkF1dGguYXV0aDtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuXG4gICAgdGhpcy5hdXRoLmNoZWNrQWN0aW9uQ29kZSh0aGlzLm9vYkNvZGUpXG4gICAgICAudGhlbigocmVzdWx0OiBhdXRoLkFjdGlvbkNvZGVJbmZvKSA9PiB7XG4gICAgICAgIHRoaXMuaW5mbyA9IHJlc3VsdDtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aC5hcHBseUFjdGlvbkNvZGUodGhpcy5vb2JDb2RlKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ3N1Y2Nlc3MnO1xuICAgICAgICB0aGlzLnN1Y2Nlc3MuZW1pdCh7XG4gICAgICAgICAgbW9kZTogJ3ZlcmlmeUVtYWlsJyxcbiAgICAgICAgICBpbmZvOiB0aGlzLmluZm8sXG4gICAgICAgICAgdXNlcjogdGhpcy5hdXRoLmN1cnJlbnRVc2VyXG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3I6IGF1dGguRXJyb3IpID0+IHtcbiAgICAgICAgdGhpcy51bmhhbmRsZWRFcnJvciA9IGVycm9yO1xuICAgICAgICB0aGlzLnNjcmVlbiA9ICdlcnJvcic7XG4gICAgICB9KTtcbiAgfVxuXG59XG4iLCJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IFJvdXRlck1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBPb2JDb21wb25lbnQgfSBmcm9tICcuL29vYi5jb21wb25lbnQnO1xuaW1wb3J0IHsgT29iUmVzZXRQYXNzd29yZENvbXBvbmVudCB9IGZyb20gJy4vb29iLXJlc2V0LXBhc3N3b3JkL29vYi1yZXNldC1wYXNzd29yZC5jb21wb25lbnQnO1xuaW1wb3J0IHsgT29iUmVjb3ZlckVtYWlsQ29tcG9uZW50IH0gZnJvbSAnLi9vb2ItcmVjb3Zlci1lbWFpbC9vb2ItcmVjb3Zlci1lbWFpbC5jb21wb25lbnQnO1xuaW1wb3J0IHsgT29iVmVyaWZ5RW1haWxDb21wb25lbnQgfSBmcm9tICcuL29vYi12ZXJpZnktZW1haWwvb29iLXZlcmlmeS1lbWFpbC5jb21wb25lbnQnO1xuXG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhNb2R1bGUgfSBmcm9tICcuLi9uZ3gtZmlyZWJhc2UtYXV0aC5tb2R1bGUnO1xuXG5ATmdNb2R1bGUoe1xuICBpbXBvcnRzOiBbXG4gICAgQ29tbW9uTW9kdWxlLFxuICAgIFJlYWN0aXZlRm9ybXNNb2R1bGUsXG4gICAgUm91dGVyTW9kdWxlLFxuICAgIE5neEZpcmViYXNlQXV0aE1vZHVsZVxuICBdLFxuICBkZWNsYXJhdGlvbnM6IFtcbiAgICBPb2JDb21wb25lbnQsXG4gICAgT29iUmVjb3ZlckVtYWlsQ29tcG9uZW50LFxuICAgIE9vYlJlc2V0UGFzc3dvcmRDb21wb25lbnQsXG4gICAgT29iVmVyaWZ5RW1haWxDb21wb25lbnRcbiAgXSxcbiAgZXhwb3J0czogW1xuICAgIE9vYkNvbXBvbmVudCxcbiAgXVxufSlcbmV4cG9ydCBjbGFzcyBOZ3hGaXJlYmFzZUF1dGhPb2JNb2R1bGUgeyB9XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQWlCQSxNQUFhLGtCQUFrQixHQUE2QixPQUFPLENBQUMsV0FBVyxFQUFFO0lBQy9FLEtBQUssQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLEVBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFDLENBQUMsQ0FBQztJQUNsRCxVQUFVLENBQUMsV0FB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