@universis/common
Version:
Universis - common directives and services
168 lines • 41.3 kB
JavaScript
import { Component, Input } from '@angular/core';
import { CertificateService } from '../../services/certificate-service/certificate-service.service';
import { BsModalRef } from 'ngx-bootstrap/modal';
import { TranslateService } from '@ngx-translate/core';
import { environment } from '../../../environments/environment';
import { SIGNATURE_INFO } from './i18n/signature-info.translations';
import * as i0 from "@angular/core";
import * as i1 from "ngx-bootstrap/modal";
import * as i2 from "../../services/certificate-service/certificate-service.service";
import * as i3 from "@ngx-translate/core";
import * as i4 from "@angular/common";
export class SignatureInfoComponent {
constructor(_bsModalRef, _certificateService, _translateService) {
this._bsModalRef = _bsModalRef;
this._certificateService = _certificateService;
this._translateService = _translateService;
/**
* The list of attributes to show to the user
*/
this.signatureAttributes = [];
this.tab = 1;
this.generalAttributes = [];
this.purposes = [];
environment.languages.forEach((culture) => {
if (SIGNATURE_INFO[culture])
this._translateService.setTranslation(culture, SIGNATURE_INFO[culture], true);
});
}
async ngOnInit() {
this.signatureAttributes = [
{
translationKey: 'SignatureInfo.CheckHash',
value: this.checkHashKey
},
{
translationKey: 'SignatureInfo.SignatureBlock',
value: this.signatureBlock
}
];
try {
let parsed;
parsed = this._certificateService.getX509Certificate(this.certificate);
if (!this.user) {
this.user = this._certificateService.extractCertificateOwner(parsed);
}
const certAttributes = this.resolveAttributes(parsed);
this.purposes = this._certificateService.extractPurposes(parsed);
this.signatureAttributes = [...certAttributes, ...this.signatureAttributes];
this.generalAttributes = this.getGeneralAttributes(parsed);
}
catch (err) {
console.log('err: ', err);
}
}
/**
*
* Resolves a certificate to usable fields
*
* @param {X509} certificate The X509 object certificate
*
*/
resolveAttributes(certificate) {
const certificateAttributes = [];
certificateAttributes.push({
translationKey: 'SignatureInfo.Version',
value: certificate.getVersion()
});
certificateAttributes.push({
translationKey: 'SignatureInfo.SerialNumber',
value: certificate.getSerialNumberHex()
});
certificateAttributes.push({
translationKey: 'SignatureInfo.Algorithm',
value: certificate.getSignatureAlgorithmField()
});
certificateAttributes.push({
translationKey: 'SignatureInfo.Issuer',
value: (certificate.getIssuer().str).replace(/\//g, '\n')
});
const notBefore = this._certificateService.parseCertificateDate(certificate.getNotBefore());
certificateAttributes.push({
translationKey: 'SignatureInfo.NotValidBefore',
value: notBefore,
validation: {
isValid: notBefore ? new Date() >= notBefore : false,
showValidation: true
}
});
const notAfter = this._certificateService.parseCertificateDate(certificate.getNotAfter());
certificateAttributes.push({
translationKey: 'SignatureInfo.NotValidAfter',
value: notAfter,
validation: {
isValid: notAfter ? notAfter >= new Date() : false,
showValidation: true
}
});
certificateAttributes.push({
translationKey: 'SignatureInfo.Subject',
value: (certificate.getSubject().str).replace(/\//g, '\n')
});
certificateAttributes.push({
translationKey: 'SignatureInfo.PublicKey',
value: certificate.getPublicKeyHex()
});
certificateAttributes.push({
translationKey: 'SignatureInfo.PublicKeyParameters',
value: certificate.getPublicKeyIdx()
});
return certificateAttributes;
}
getGeneralAttributes(certificate) {
let attributes = [];
attributes.push({
translationKey: 'SignatureInfo.IssuedTo',
// get certificate subject common name
value: (certificate.getSubjectString()).split('/').filter(x => x.includes('CN')).join(',').split('=')[1]
});
attributes.push({
translationKey: 'SignatureInfo.Issuer',
// get certificate issuer common name (CN)
value: (certificate.getIssuerString()).split('/').filter(x => x.includes('CN')).join(',').split('=')[1]
});
const notBefore = this._certificateService.parseCertificateDate(certificate.getNotBefore());
attributes.push({
translationKey: 'SignatureInfo.NotValidBeforeShort',
value: notBefore,
validation: {
isValid: notBefore ? new Date() >= notBefore : false,
showValidation: true
}
});
const notAfter = this._certificateService.parseCertificateDate(certificate.getNotAfter());
attributes.push({
translationKey: 'SignatureInfo.NotValidAfterShort',
value: notAfter,
validation: {
isValid: notAfter ? notAfter >= new Date() : false,
showValidation: true
}
});
return attributes;
}
hideCertificateModal() {
this._bsModalRef.hide();
}
}
SignatureInfoComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SignatureInfoComponent, deps: [{ token: i1.BsModalRef }, { token: i2.CertificateService }, { token: i3.TranslateService }], target: i0.ɵɵFactoryTarget.Component });
SignatureInfoComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: SignatureInfoComponent, selector: "universis-signature-info", inputs: { user: "user", isVerified: "isVerified", certificate: "certificate", signatureBlock: "signatureBlock", checkHashKey: "checkHashKey", examinationCode: "examinationCode", dateCreated: "dateCreated" }, ngImport: i0, template: "<div class=\"modal-header p-0\">\n <button\n (click)=\"hideCertificateModal()\"\n type=\"button\"\n class=\"close\"\n data-dismiss=\"modal\"\n aria-label=\"Cancel\"\n >\n <span aria-hidden=\"true\">×</span>\n </button>\n</div>\n<div class=\"modal-body mt-0 pt-0\">\n <div class=\"card-body\" *ngIf=\"user\">\n <div class=\"row\">\n <div class=\"col-12\">\n <h5 class=\"mt-2 mb-3\">\n {{user?.familyName}} {{user?.givenName}}\n <span *ngIf=\"dateCreated\">{{ dateCreated | date:'short' }}</span>\n (\n <span *ngIf=\"isVerified\" class=\"text-purple\" [translate]=\"'SignatureInfo.Verified'\"></span>\n <span *ngIf=\"!isVerified\" class=\"text-red\" [translate]=\"'SignatureInfo.NotVerified'\"></span>\n )\n <small> {{examinationCode}} </small>\n </h5>\n </div>\n </div>\n <div class=\"mb-3\">\n <div class=\" d-none d-md-block\">\n <ul class=\"nav nav-tabs\">\n <li class=\"nav-item\">\n <a class=\"nav-link active\" [class.active]=\"tab === 1\" rel=\"tab1\"\n (click)=\"tab =1\">{{'SignatureInfo.General' | translate}}</a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link\" [class.active]=\"tab === 2\" rel=\"tab2\"\n (click)=\"tab =2\"> {{'SignatureInfo.Details' | translate}}</a>\n </li>\n </ul>\n </div>\n </div>\n\n <div *ngIf=\"tab===1\">\n <div class=\"card\">\n <h5 class=\"d-block card-header mt-2 mb-n2 align-items-center\">\n <i class=\"fa fa-certificate\"></i>\n {{'SignatureInfo.CertificateInformation' | translate}}\n </h5>\n <hr/>\n <div class=\"d-block card-body\">\n <div class=\"container font-lg mt-n2 pt-n2\" *ngIf=\"purposes && purposes.length\">\n <div class=\"row\">\n <div>\n <span> {{'SignatureInfo.CertificatePurposes.Header' |translate}}</span>\n </div>\n </div>\n <ul>\n <li *ngFor=\"let purpose of purposes\">\n {{'SignatureInfo.CertificatePurposes.' + purpose |translate}}\n </li>\n </ul>\n <hr/>\n </div>\n <div *ngFor=\"let attribute of generalAttributes | slice: 0:2\" class=\"row font-lg\">\n <div *ngIf=\"attribute && attribute.value\">\n <div class=\"flex-sm-column flex-wrap\">\n <span class=\"text-theme col-4 text-nowrap\">{{attribute.translationKey | translate}}: </span>\n <span class=\"col-8\">{{attribute.value}}</span>\n </div>\n </div>\n </div>\n <div class=\"row font-lg\">\n <span *ngFor=\"let attribute of generalAttributes |slice: 2:4\" class=\"flex-sm-column\">\n <span *ngIf=\"attribute && attribute.value\">\n <span class=\"col-4 text-theme text-nowrap\">{{attribute.translationKey | translate}}: </span>\n <span class=\"col-4 pr-2\">{{attribute.value |date:'short'}}</span>\n </span>\n </span>\n </div>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"tab=== 2\">\n <div id=\"group-list\" class=\"flex-column\">\n <div class=\"sis--list-group sis--list-group-body\">\n <ul class=\"sis--list-group sis--list-group-header\">\n <li class=\"sis--list-group-item\">\n <div class=\"d-flex justify-content-center align-items-center\">\n <div class=\"sis--list-group-item_lg_column d-none d-block\"\n [translate]=\"'SignatureInfo.Field'\"></div>\n <div class=\"sis--list-group-item_lg_column d-none d-block px-4\"\n [translate]=\"'SignatureInfo.Value'\"></div>\n </div>\n </li>\n </ul>\n <ul class=\"sis--list-group sis--list-group-body\">\n <li class=\"sis--list-group-item\" *ngFor=\"let attribute of signatureAttributes\">\n <div class=\"d-flex justify-content-center align-items-center list-color\">\n <div class=\"sis--list-group-item_lg_column d-none d-block flex-wrap\">\n <span class=\"text-secondary\">\n <i class=\"fa fa-certificate\"></i>\n {{attribute.translationKey | translate}}\n </span>\n </div>\n <div class=\"sis--list-group-item_lg_column d-block flex-wrap\">\n <span class=\"text-secondary p-2 p-md-0 text-break \" [ngClass]=\"{\n 'text-red': attribute.validation && attribute.validation.showValidation && !attribute.validation.isValid,\n 'text-green': attribute.validation && attribute.validation.showValidation && attribute.validation.isValid\n }\">{{ attribute.value}}</span>\n </div>\n </div>\n </li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col text-center\">\n <button\n (click)=\"hideCertificateModal()\"\n class=\"btn btn-success\"\n [translate]=\"'SignatureInfo.Close'\"\n ></button>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "pipe", type: i4.SlicePipe, name: "slice" }, { kind: "pipe", type: i4.DatePipe, name: "date" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SignatureInfoComponent, decorators: [{
type: Component,
args: [{ selector: 'universis-signature-info', template: "<div class=\"modal-header p-0\">\n <button\n (click)=\"hideCertificateModal()\"\n type=\"button\"\n class=\"close\"\n data-dismiss=\"modal\"\n aria-label=\"Cancel\"\n >\n <span aria-hidden=\"true\">×</span>\n </button>\n</div>\n<div class=\"modal-body mt-0 pt-0\">\n <div class=\"card-body\" *ngIf=\"user\">\n <div class=\"row\">\n <div class=\"col-12\">\n <h5 class=\"mt-2 mb-3\">\n {{user?.familyName}} {{user?.givenName}}\n <span *ngIf=\"dateCreated\">{{ dateCreated | date:'short' }}</span>\n (\n <span *ngIf=\"isVerified\" class=\"text-purple\" [translate]=\"'SignatureInfo.Verified'\"></span>\n <span *ngIf=\"!isVerified\" class=\"text-red\" [translate]=\"'SignatureInfo.NotVerified'\"></span>\n )\n <small> {{examinationCode}} </small>\n </h5>\n </div>\n </div>\n <div class=\"mb-3\">\n <div class=\" d-none d-md-block\">\n <ul class=\"nav nav-tabs\">\n <li class=\"nav-item\">\n <a class=\"nav-link active\" [class.active]=\"tab === 1\" rel=\"tab1\"\n (click)=\"tab =1\">{{'SignatureInfo.General' | translate}}</a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link\" [class.active]=\"tab === 2\" rel=\"tab2\"\n (click)=\"tab =2\"> {{'SignatureInfo.Details' | translate}}</a>\n </li>\n </ul>\n </div>\n </div>\n\n <div *ngIf=\"tab===1\">\n <div class=\"card\">\n <h5 class=\"d-block card-header mt-2 mb-n2 align-items-center\">\n <i class=\"fa fa-certificate\"></i>\n {{'SignatureInfo.CertificateInformation' | translate}}\n </h5>\n <hr/>\n <div class=\"d-block card-body\">\n <div class=\"container font-lg mt-n2 pt-n2\" *ngIf=\"purposes && purposes.length\">\n <div class=\"row\">\n <div>\n <span> {{'SignatureInfo.CertificatePurposes.Header' |translate}}</span>\n </div>\n </div>\n <ul>\n <li *ngFor=\"let purpose of purposes\">\n {{'SignatureInfo.CertificatePurposes.' + purpose |translate}}\n </li>\n </ul>\n <hr/>\n </div>\n <div *ngFor=\"let attribute of generalAttributes | slice: 0:2\" class=\"row font-lg\">\n <div *ngIf=\"attribute && attribute.value\">\n <div class=\"flex-sm-column flex-wrap\">\n <span class=\"text-theme col-4 text-nowrap\">{{attribute.translationKey | translate}}: </span>\n <span class=\"col-8\">{{attribute.value}}</span>\n </div>\n </div>\n </div>\n <div class=\"row font-lg\">\n <span *ngFor=\"let attribute of generalAttributes |slice: 2:4\" class=\"flex-sm-column\">\n <span *ngIf=\"attribute && attribute.value\">\n <span class=\"col-4 text-theme text-nowrap\">{{attribute.translationKey | translate}}: </span>\n <span class=\"col-4 pr-2\">{{attribute.value |date:'short'}}</span>\n </span>\n </span>\n </div>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"tab=== 2\">\n <div id=\"group-list\" class=\"flex-column\">\n <div class=\"sis--list-group sis--list-group-body\">\n <ul class=\"sis--list-group sis--list-group-header\">\n <li class=\"sis--list-group-item\">\n <div class=\"d-flex justify-content-center align-items-center\">\n <div class=\"sis--list-group-item_lg_column d-none d-block\"\n [translate]=\"'SignatureInfo.Field'\"></div>\n <div class=\"sis--list-group-item_lg_column d-none d-block px-4\"\n [translate]=\"'SignatureInfo.Value'\"></div>\n </div>\n </li>\n </ul>\n <ul class=\"sis--list-group sis--list-group-body\">\n <li class=\"sis--list-group-item\" *ngFor=\"let attribute of signatureAttributes\">\n <div class=\"d-flex justify-content-center align-items-center list-color\">\n <div class=\"sis--list-group-item_lg_column d-none d-block flex-wrap\">\n <span class=\"text-secondary\">\n <i class=\"fa fa-certificate\"></i>\n {{attribute.translationKey | translate}}\n </span>\n </div>\n <div class=\"sis--list-group-item_lg_column d-block flex-wrap\">\n <span class=\"text-secondary p-2 p-md-0 text-break \" [ngClass]=\"{\n 'text-red': attribute.validation && attribute.validation.showValidation && !attribute.validation.isValid,\n 'text-green': attribute.validation && attribute.validation.showValidation && attribute.validation.isValid\n }\">{{ attribute.value}}</span>\n </div>\n </div>\n </li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col text-center\">\n <button\n (click)=\"hideCertificateModal()\"\n class=\"btn btn-success\"\n [translate]=\"'SignatureInfo.Close'\"\n ></button>\n </div>\n </div>\n</div>\n" }]
}], ctorParameters: function () { return [{ type: i1.BsModalRef }, { type: i2.CertificateService }, { type: i3.TranslateService }]; }, propDecorators: { user: [{
type: Input
}], isVerified: [{
type: Input
}], certificate: [{
type: Input
}], signatureBlock: [{
type: Input
}], checkHashKey: [{
type: Input
}], examinationCode: [{
type: Input
}], dateCreated: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbmF0dXJlLWluZm8uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3NoYXJlZC9jb21wb25lbnRzL3NpZ25hdHVyZS1pbmZvL3NpZ25hdHVyZS1pbmZvLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9zaGFyZWQvY29tcG9uZW50cy9zaWduYXR1cmUtaW5mby9zaWduYXR1cmUtaW5mby5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBVSxNQUFNLGVBQWUsQ0FBQztBQUV6RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxnRUFBZ0UsQ0FBQztBQUNwRyxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFDL0MsT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFDckQsT0FBTyxFQUFDLFdBQVcsRUFBQyxNQUFNLG1DQUFtQyxDQUFDO0FBQzlELE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSxvQ0FBb0MsQ0FBQzs7Ozs7O0FBd0JsRSxNQUFNLE9BQU8sc0JBQXNCO0lBNEJqQyxZQUFvQixXQUF1QixFQUN2QixtQkFBdUMsRUFDdkMsaUJBQW1DO1FBRm5DLGdCQUFXLEdBQVgsV0FBVyxDQUFZO1FBQ3ZCLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBb0I7UUFDdkMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFrQjtRQVZ2RDs7V0FFRztRQUNJLHdCQUFtQixHQUF5QixFQUFFLENBQUM7UUFDL0MsUUFBRyxHQUFZLENBQUMsQ0FBQztRQUNqQixzQkFBaUIsR0FBeUIsRUFBRSxDQUFDO1FBQzdDLGFBQVEsR0FBZSxFQUFFLENBQUM7UUFLL0IsV0FBVyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUN4QyxJQUFHLGNBQWMsQ0FBQyxPQUFPLENBQUM7Z0JBQ3hCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxjQUFjLENBQUMsT0FBTyxFQUFFLGNBQWMsQ0FBQyxPQUFPLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNsRixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsUUFBUTtRQUNaLElBQUksQ0FBQyxtQkFBbUIsR0FBRztZQUN6QjtnQkFDRSxjQUFjLEVBQUUseUJBQXlCO2dCQUN6QyxLQUFLLEVBQUUsSUFBSSxDQUFDLFlBQVk7YUFDekI7WUFDRDtnQkFDRSxjQUFjLEVBQUUsOEJBQThCO2dCQUM5QyxLQUFLLEVBQUUsSUFBSSxDQUFDLGNBQWM7YUFDM0I7U0FDRixDQUFDO1FBQ0YsSUFBSTtZQUNGLElBQUksTUFBTSxDQUFDO1lBQ1gsTUFBTSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDdkUsSUFBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUM7Z0JBQ1osSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsdUJBQXVCLENBQUMsTUFBTSxDQUFDLENBQUM7YUFDdEU7WUFDRCxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdEQsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2pFLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxDQUFDLEdBQUcsY0FBYyxFQUFFLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLENBQUM7WUFDNUUsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztTQUM1RDtRQUFDLE9BQU0sR0FBRyxFQUFFO1lBQ1gsT0FBTyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUM7U0FDM0I7SUFDSCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsaUJBQWlCLENBQUMsV0FBaUI7UUFDakMsTUFBTSxxQkFBcUIsR0FJckIsRUFBRSxDQUFDO1FBQ1QscUJBQXFCLENBQUMsSUFBSSxDQUFDO1lBQ3pCLGNBQWMsRUFBRSx1QkFBdUI7WUFDdkMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxVQUFVLEVBQUU7U0FDaEMsQ0FBQyxDQUFDO1FBQ0gscUJBQXFCLENBQUMsSUFBSSxDQUFDO1lBQ3pCLGNBQWMsRUFBRSw0QkFBNEI7WUFDNUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxrQkFBa0IsRUFBRTtTQUN4QyxDQUFDLENBQUM7UUFDSCxxQkFBcUIsQ0FBQyxJQUFJLENBQUM7WUFDekIsY0FBYyxFQUFFLHlCQUF5QjtZQUN6QyxLQUFLLEVBQUUsV0FBVyxDQUFDLDBCQUEwQixFQUFFO1NBQ2hELENBQUMsQ0FBQztRQUNILHFCQUFxQixDQUFDLElBQUksQ0FBQztZQUN6QixjQUFjLEVBQUUsc0JBQXNCO1lBQ3RDLEtBQUssRUFBRSxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQztTQUMxRCxDQUFDLENBQUM7UUFFSCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsb0JBQW9CLENBQzdELFdBQVcsQ0FBQyxZQUFZLEVBQUUsQ0FDM0IsQ0FBQztRQUVGLHFCQUFxQixDQUFDLElBQUksQ0FBQztZQUN6QixjQUFjLEVBQUUsOEJBQThCO1lBQzlDLEtBQUssRUFBRSxTQUFTO1lBQ2hCLFVBQVUsRUFBRTtnQkFDVixPQUFPLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksRUFBRSxJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSztnQkFDcEQsY0FBYyxFQUFFLElBQUk7YUFDckI7U0FDRixDQUFDLENBQUM7UUFFSCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsb0JBQW9CLENBQzVELFdBQVcsQ0FBQyxXQUFXLEVBQUUsQ0FDMUIsQ0FBQTtRQUVELHFCQUFxQixDQUFDLElBQUksQ0FBQztZQUN6QixjQUFjLEVBQUUsNkJBQTZCO1lBQzdDLEtBQUssRUFBRyxRQUFRO1lBQ2hCLFVBQVUsRUFBRTtnQkFDVixPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxRQUFRLElBQUksSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSztnQkFDbEQsY0FBYyxFQUFFLElBQUk7YUFDckI7U0FDRixDQUFDLENBQUM7UUFDSCxxQkFBcUIsQ0FBQyxJQUFJLENBQUM7WUFDekIsY0FBYyxFQUFFLHVCQUF1QjtZQUN2QyxLQUFLLEVBQUUsQ0FBQyxXQUFXLENBQUMsVUFBVSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUM7U0FDM0QsQ0FBQyxDQUFDO1FBQ0gscUJBQXFCLENBQUMsSUFBSSxDQUFDO1lBQ3pCLGNBQWMsRUFBRSx5QkFBeUI7WUFDekMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxlQUFlLEVBQUU7U0FDckMsQ0FBQyxDQUFDO1FBQ0gscUJBQXFCLENBQUMsSUFBSSxDQUFDO1lBQ3pCLGNBQWMsRUFBRSxtQ0FBbUM7WUFDbkQsS0FBSyxFQUFFLFdBQVcsQ0FBQyxlQUFlLEVBQUU7U0FDckMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxxQkFBcUIsQ0FBQztJQUMvQixDQUFDO0lBRUQsb0JBQW9CLENBQUMsV0FBVztRQUM5QixJQUFJLFVBQVUsR0FJUixFQUFFLENBQUM7UUFDVCxVQUFVLENBQUMsSUFBSSxDQUFDO1lBQ2QsY0FBYyxFQUFFLHdCQUF3QjtZQUN4QyxzQ0FBc0M7WUFDdEMsS0FBSyxFQUFFLENBQUMsV0FBVyxDQUFDLGdCQUFnQixFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQ3pHLENBQUMsQ0FBQztRQUNILFVBQVUsQ0FBQyxJQUFJLENBQUM7WUFDZCxjQUFjLEVBQUUsc0JBQXNCO1lBQ3RDLDBDQUEwQztZQUMxQyxLQUFLLEVBQUUsQ0FBQyxXQUFXLENBQUMsZUFBZSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQ3hHLENBQUMsQ0FBQztRQUNILE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxvQkFBb0IsQ0FDN0QsV0FBVyxDQUFDLFlBQVksRUFBRSxDQUMzQixDQUFDO1FBQ0YsVUFBVSxDQUFDLElBQUksQ0FBQztZQUNkLGNBQWMsRUFBRSxtQ0FBbUM7WUFDbkQsS0FBSyxFQUFFLFNBQVM7WUFDaEIsVUFBVSxFQUFFO2dCQUNWLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxFQUFFLElBQUksU0FBUyxDQUFDLENBQUMsQ0FBQyxLQUFLO2dCQUNwRCxjQUFjLEVBQUUsSUFBSTthQUNyQjtTQUNGLENBQUMsQ0FBQztRQUNILE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxvQkFBb0IsQ0FDNUQsV0FBVyxDQUFDLFdBQVcsRUFBRSxDQUMxQixDQUFDO1FBQ0YsVUFBVSxDQUFDLElBQUksQ0FBQztZQUNkLGNBQWMsRUFBRSxrQ0FBa0M7WUFDbEQsS0FBSyxFQUFHLFFBQVE7WUFDaEIsVUFBVSxFQUFFO2dCQUNWLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsSUFBSSxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLO2dCQUNsRCxjQUFjLEVBQUUsSUFBSTthQUNyQjtTQUNGLENBQUMsQ0FBQztRQUNILE9BQU8sVUFBVSxDQUFDO0lBQ3BCLENBQUM7SUFFRCxvQkFBb0I7UUFDbEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUMxQixDQUFDOztvSEFoTFUsc0JBQXNCO3dHQUF0QixzQkFBc0IsZ1JDOUJuQyxpc0tBK0hBOzRGRGpHYSxzQkFBc0I7a0JBSmxDLFNBQVM7K0JBQ0UsMEJBQTBCO2lLQVEzQixJQUFJO3NCQUFaLEtBQUs7Z0JBT0csVUFBVTtzQkFBbEIsS0FBSztnQkFDRyxXQUFXO3NCQUFuQixLQUFLO2dCQUNHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBQ0csWUFBWTtzQkFBcEIsS0FBSztnQkFDRyxlQUFlO3NCQUF2QixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBPbkluaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFg1MDkgfSBmcm9tICdqc3JzYXNpZ24nO1xuaW1wb3J0IHsgQ2VydGlmaWNhdGVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvY2VydGlmaWNhdGUtc2VydmljZS9jZXJ0aWZpY2F0ZS1zZXJ2aWNlLnNlcnZpY2UnO1xuaW1wb3J0IHtCc01vZGFsUmVmfSBmcm9tICduZ3gtYm9vdHN0cmFwL21vZGFsJztcbmltcG9ydCB7VHJhbnNsYXRlU2VydmljZX0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQge2Vudmlyb25tZW50fSBmcm9tICcuLi8uLi8uLi9lbnZpcm9ubWVudHMvZW52aXJvbm1lbnQnO1xuaW1wb3J0IHtTSUdOQVRVUkVfSU5GT30gZnJvbSAnLi9pMThuL3NpZ25hdHVyZS1pbmZvLnRyYW5zbGF0aW9ucyc7XG5cbi8qKlxuICpcbiAqIEBpbnRlcmZhY2UgU2lnbmF0dXJlQXR0cmlidXRlXG4gKlxuICogQHByb3BlcnR5IHtzdHJpbmd9IHRyYW5zbGF0aW9uS2V5IFRoZSB0cmFuc2xhdGlvbiBrZXkgdG8gc2hvdyB0byB0aGUgdXNlclxuICogQHByb3BlcnR5IHtzdHJpbmd9IHZhbHVlIFRoZSB2YWx1ZSB0byBzaG93IHRvIHRoZSB1c2VyXG4gKiBAcHJvcGVydHkge29iamVjdH0gVmFsaWRhdGlvbiBkYXRhLiBpc1ZhbGlkIGlzIHRoZSB2YWxpZGF0aW9uIHN0YXR1cywgc2hvd1ZhbGlkYXRpb24gaW5kaWNhdGVzIHdoZXRoZXIgdG8gc2hvdyB0aGUgdmFsaWRhdGlvblxuICpcbiAqL1xuaW50ZXJmYWNlIFNpZ25hdHVyZUF0dHJpYnV0ZSB7XG4gIHRyYW5zbGF0aW9uS2V5OiBzdHJpbmc7XG4gIHZhbHVlPzogc3RyaW5nO1xuICB2YWxpZGF0aW9uPzoge1xuICAgIGlzVmFsaWQ6IGJvb2xlYW47XG4gICAgc2hvd1ZhbGlkYXRpb246IGJvb2xlYW47XG4gIH1cbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndW5pdmVyc2lzLXNpZ25hdHVyZS1pbmZvJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3NpZ25hdHVyZS1pbmZvLmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBTaWduYXR1cmVJbmZvQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICAvKipcbiAgICogQHByb3BlcnR5IHtPYmplY3R9IHVzZXIgVGhlIHVzZXIgd2hvIHN1Ym1pdHRlZCB0aGUgZXhhbSAgZG9jdW1lbnRcbiAgICovXG4gIEBJbnB1dCgpIHVzZXI7XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gaXNWZXJpZmllZCBBIGZsYWcgdG8gaW5kaWNhdGUgd2hldGhlciB0aGUgc2lnbmF0dXJlIHdhc1xuICAgKiB2ZXJpZmllZCBhdCBsZWFzdCBvbmNlIG9uIHNlcnZlciBzaWRlLiBDYW4gYmUgdXNlZCB0byBzaG93IHRvIHRoZSB1c2VyIHRoYXRcbiAgICogdGhlIHNpZ25hdHVyZSB3YXMgYWNjZXB0ZWQgYXQgc29tZSBwb2ludCBpbiB0aGUgcGFzdCBldmVuIGlmIHRoZSBjZXJ0aWZpY2F0ZSBpcyBleHBpcmVkLlxuICAgKi9cbiAgQElucHV0KCkgaXNWZXJpZmllZDogYm9vbGVhbiB8IHVuZGVmaW5lZDtcbiAgQElucHV0KCkgY2VydGlmaWNhdGU6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgQElucHV0KCkgc2lnbmF0dXJlQmxvY2s6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgQElucHV0KCkgY2hlY2tIYXNoS2V5OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIEBJbnB1dCgpIGV4YW1pbmF0aW9uQ29kZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBASW5wdXQoKSBkYXRlQ3JlYXRlZDogRGF0ZSB8IHVuZGVmaW5lZDtcblxuXG4gIC8qKlxuICAgKiBUaGUgbGlzdCBvZiBhdHRyaWJ1dGVzIHRvIHNob3cgdG8gdGhlIHVzZXJcbiAgICovXG4gIHB1YmxpYyBzaWduYXR1cmVBdHRyaWJ1dGVzOiBTaWduYXR1cmVBdHRyaWJ1dGVbXSA9IFtdO1xuICBwdWJsaWMgdGFiOiBudW1iZXIgID0gMTtcbiAgcHVibGljIGdlbmVyYWxBdHRyaWJ1dGVzOiBTaWduYXR1cmVBdHRyaWJ1dGVbXSA9IFtdO1xuICBwdWJsaWMgcHVycG9zZXM6IEFycmF5PGFueT4gPSBbXTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9ic01vZGFsUmVmOiBCc01vZGFsUmVmLFxuICAgICAgICAgICAgICBwcml2YXRlIF9jZXJ0aWZpY2F0ZVNlcnZpY2U6IENlcnRpZmljYXRlU2VydmljZSxcbiAgICAgICAgICAgICAgcHJpdmF0ZSBfdHJhbnNsYXRlU2VydmljZTogVHJhbnNsYXRlU2VydmljZSkge1xuICAgIGVudmlyb25tZW50Lmxhbmd1YWdlcy5mb3JFYWNoKChjdWx0dXJlKSA9PiB7XG4gICAgICBpZihTSUdOQVRVUkVfSU5GT1tjdWx0dXJlXSlcbiAgICAgICAgdGhpcy5fdHJhbnNsYXRlU2VydmljZS5zZXRUcmFuc2xhdGlvbihjdWx0dXJlLCBTSUdOQVRVUkVfSU5GT1tjdWx0dXJlXSwgdHJ1ZSk7XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLnNpZ25hdHVyZUF0dHJpYnV0ZXMgPSBbXG4gICAgICB7XG4gICAgICAgIHRyYW5zbGF0aW9uS2V5OiAnU2lnbmF0dXJlSW5mby5DaGVja0hhc2gnLFxuICAgICAgICB2YWx1ZTogdGhpcy5jaGVja0hhc2hLZXlcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHRyYW5zbGF0aW9uS2V5OiAnU2lnbmF0dXJlSW5mby5TaWduYXR1cmVCbG9jaycsXG4gICAgICAgIHZhbHVlOiB0aGlzLnNpZ25hdHVyZUJsb2NrXG4gICAgICB9XG4gICAgXTtcbiAgICB0cnkge1xuICAgICAgbGV0IHBhcnNlZDtcbiAgICAgIHBhcnNlZCA9IHRoaXMuX2NlcnRpZmljYXRlU2VydmljZS5nZXRYNTA5Q2VydGlmaWNhdGUodGhpcy5jZXJ0aWZpY2F0ZSk7XG4gICAgICBpZighdGhpcy51c2VyKXtcbiAgICAgICAgdGhpcy51c2VyID0gdGhpcy5fY2VydGlmaWNhdGVTZXJ2aWNlLmV4dHJhY3RDZXJ0aWZpY2F0ZU93bmVyKHBhcnNlZCk7XG4gICAgICB9XG4gICAgICBjb25zdCBjZXJ0QXR0cmlidXRlcyA9IHRoaXMucmVzb2x2ZUF0dHJpYnV0ZXMocGFyc2VkKTtcbiAgICAgIHRoaXMucHVycG9zZXMgPSB0aGlzLl9jZXJ0aWZpY2F0ZVNlcnZpY2UuZXh0cmFjdFB1cnBvc2VzKHBhcnNlZCk7XG4gICAgICB0aGlzLnNpZ25hdHVyZUF0dHJpYnV0ZXMgPSBbLi4uY2VydEF0dHJpYnV0ZXMsIC4uLnRoaXMuc2lnbmF0dXJlQXR0cmlidXRlc107XG4gICAgICB0aGlzLmdlbmVyYWxBdHRyaWJ1dGVzID0gdGhpcy5nZXRHZW5lcmFsQXR0cmlidXRlcyhwYXJzZWQpO1xuICAgIH0gY2F0Y2goZXJyKSB7XG4gICAgICBjb25zb2xlLmxvZygnZXJyOiAnLCBlcnIpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKlxuICAgKiBSZXNvbHZlcyBhIGNlcnRpZmljYXRlIHRvIHVzYWJsZSBmaWVsZHNcbiAgICpcbiAgICogQHBhcmFtIHtYNTA5fSBjZXJ0aWZpY2F0ZSBUaGUgWDUwOSBvYmplY3QgY2VydGlmaWNhdGVcbiAgICpcbiAgICovXG4gIHJlc29sdmVBdHRyaWJ1dGVzKGNlcnRpZmljYXRlOiBYNTA5KSB7XG4gICAgY29uc3QgY2VydGlmaWNhdGVBdHRyaWJ1dGVzOiB7XG4gICAgICB0cmFuc2xhdGlvbktleTogc3RyaW5nLFxuICAgICAgdmFsdWU/OiBhbnksXG4gICAgICB2YWxpZGF0aW9uPzogYW55XG4gICAgfVtdID0gW107XG4gICAgY2VydGlmaWNhdGVBdHRyaWJ1dGVzLnB1c2goe1xuICAgICAgdHJhbnNsYXRpb25LZXk6ICdTaWduYXR1cmVJbmZvLlZlcnNpb24nLFxuICAgICAgdmFsdWU6IGNlcnRpZmljYXRlLmdldFZlcnNpb24oKVxuICAgIH0pO1xuICAgIGNlcnRpZmljYXRlQXR0cmlidXRlcy5wdXNoKHtcbiAgICAgIHRyYW5zbGF0aW9uS2V5OiAnU2lnbmF0dXJlSW5mby5TZXJpYWxOdW1iZXInLFxuICAgICAgdmFsdWU6IGNlcnRpZmljYXRlLmdldFNlcmlhbE51bWJlckhleCgpXG4gICAgfSk7XG4gICAgY2VydGlmaWNhdGVBdHRyaWJ1dGVzLnB1c2goe1xuICAgICAgdHJhbnNsYXRpb25LZXk6ICdTaWduYXR1cmVJbmZvLkFsZ29yaXRobScsXG4gICAgICB2YWx1ZTogY2VydGlmaWNhdGUuZ2V0U2lnbmF0dXJlQWxnb3JpdGhtRmllbGQoKVxuICAgIH0pO1xuICAgIGNlcnRpZmljYXRlQXR0cmlidXRlcy5wdXNoKHtcbiAgICAgIHRyYW5zbGF0aW9uS2V5OiAnU2lnbmF0dXJlSW5mby5Jc3N1ZXInLFxuICAgICAgdmFsdWU6IChjZXJ0aWZpY2F0ZS5nZXRJc3N1ZXIoKS5zdHIpLnJlcGxhY2UoL1xcLy9nLCAnXFxuJylcbiAgICB9KTtcblxuICAgIGNvbnN0IG5vdEJlZm9yZSA9IHRoaXMuX2NlcnRpZmljYXRlU2VydmljZS5wYXJzZUNlcnRpZmljYXRlRGF0ZShcbiAgICAgIGNlcnRpZmljYXRlLmdldE5vdEJlZm9yZSgpXG4gICAgKTtcblxuICAgIGNlcnRpZmljYXRlQXR0cmlidXRlcy5wdXNoKHtcbiAgICAgIHRyYW5zbGF0aW9uS2V5OiAnU2lnbmF0dXJlSW5mby5Ob3RWYWxpZEJlZm9yZScsXG4gICAgICB2YWx1ZTogbm90QmVmb3JlLFxuICAgICAgdmFsaWRhdGlvbjoge1xuICAgICAgICBpc1ZhbGlkOiBub3RCZWZvcmUgPyBuZXcgRGF0ZSgpID49IG5vdEJlZm9yZSA6IGZhbHNlLFxuICAgICAgICBzaG93VmFsaWRhdGlvbjogdHJ1ZVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29uc3Qgbm90QWZ0ZXIgPSB0aGlzLl9jZXJ0aWZpY2F0ZVNlcnZpY2UucGFyc2VDZXJ0aWZpY2F0ZURhdGUoXG4gICAgICBjZXJ0aWZpY2F0ZS5nZXROb3RBZnRlcigpXG4gICAgKVxuXG4gICAgY2VydGlmaWNhdGVBdHRyaWJ1dGVzLnB1c2goe1xuICAgICAgdHJhbnNsYXRpb25LZXk6ICdTaWduYXR1cmVJbmZvLk5vdFZhbGlkQWZ0ZXInLFxuICAgICAgdmFsdWU6ICBub3RBZnRlcixcbiAgICAgIHZhbGlkYXRpb246IHtcbiAgICAgICAgaXNWYWxpZDogbm90QWZ0ZXIgPyBub3RBZnRlciA+PSBuZXcgRGF0ZSgpIDogZmFsc2UsXG4gICAgICAgIHNob3dWYWxpZGF0aW9uOiB0cnVlXG4gICAgICB9XG4gICAgfSk7XG4gICAgY2VydGlmaWNhdGVBdHRyaWJ1dGVzLnB1c2goe1xuICAgICAgdHJhbnNsYXRpb25LZXk6ICdTaWduYXR1cmVJbmZvLlN1YmplY3QnLFxuICAgICAgdmFsdWU6IChjZXJ0aWZpY2F0ZS5nZXRTdWJqZWN0KCkuc3RyKS5yZXBsYWNlKC9cXC8vZywgJ1xcbicpXG4gICAgfSk7XG4gICAgY2VydGlmaWNhdGVBdHRyaWJ1dGVzLnB1c2goe1xuICAgICAgdHJhbnNsYXRpb25LZXk6ICdTaWduYXR1cmVJbmZvLlB1YmxpY0tleScsXG4gICAgICB2YWx1ZTogY2VydGlmaWNhdGUuZ2V0UHVibGljS2V5SGV4KClcbiAgICB9KTtcbiAgICBjZXJ0aWZpY2F0ZUF0dHJpYnV0ZXMucHVzaCh7XG4gICAgICB0cmFuc2xhdGlvbktleTogJ1NpZ25hdHVyZUluZm8uUHVibGljS2V5UGFyYW1ldGVycycsXG4gICAgICB2YWx1ZTogY2VydGlmaWNhdGUuZ2V0UHVibGljS2V5SWR4KClcbiAgICB9KTtcbiAgICByZXR1cm4gY2VydGlmaWNhdGVBdHRyaWJ1dGVzO1xuICB9XG5cbiAgZ2V0R2VuZXJhbEF0dHJpYnV0ZXMoY2VydGlmaWNhdGUpOiBTaWduYXR1cmVBdHRyaWJ1dGVbXSB7XG4gICAgbGV0IGF0dHJpYnV0ZXM6IHtcbiAgICAgIHRyYW5zbGF0aW9uS2V5OiBzdHJpbmcsXG4gICAgICB2YWx1ZT86IGFueSxcbiAgICAgIHZhbGlkYXRpb24/OiBhbnlcbiAgICB9W10gPSBbXTtcbiAgICBhdHRyaWJ1dGVzLnB1c2goe1xuICAgICAgdHJhbnNsYXRpb25LZXk6ICdTaWduYXR1cmVJbmZvLklzc3VlZFRvJyxcbiAgICAgIC8vIGdldCBjZXJ0aWZpY2F0ZSBzdWJqZWN0IGNvbW1vbiBuYW1lXG4gICAgICB2YWx1ZTogKGNlcnRpZmljYXRlLmdldFN1YmplY3RTdHJpbmcoKSkuc3BsaXQoJy8nKS5maWx0ZXIoeCA9PiB4LmluY2x1ZGVzKCdDTicpKS5qb2luKCcsJykuc3BsaXQoJz0nKVsxXVxuICAgIH0pO1xuICAgIGF0dHJpYnV0ZXMucHVzaCh7XG4gICAgICB0cmFuc2xhdGlvbktleTogJ1NpZ25hdHVyZUluZm8uSXNzdWVyJyxcbiAgICAgIC8vIGdldCBjZXJ0aWZpY2F0ZSBpc3N1ZXIgY29tbW9uIG5hbWUgKENOKVxuICAgICAgdmFsdWU6IChjZXJ0aWZpY2F0ZS5nZXRJc3N1ZXJTdHJpbmcoKSkuc3BsaXQoJy8nKS5maWx0ZXIoeCA9PiB4LmluY2x1ZGVzKCdDTicpKS5qb2luKCcsJykuc3BsaXQoJz0nKVsxXVxuICAgIH0pO1xuICAgIGNvbnN0IG5vdEJlZm9yZSA9IHRoaXMuX2NlcnRpZmljYXRlU2VydmljZS5wYXJzZUNlcnRpZmljYXRlRGF0ZShcbiAgICAgIGNlcnRpZmljYXRlLmdldE5vdEJlZm9yZSgpXG4gICAgKTtcbiAgICBhdHRyaWJ1dGVzLnB1c2goe1xuICAgICAgdHJhbnNsYXRpb25LZXk6ICdTaWduYXR1cmVJbmZvLk5vdFZhbGlkQmVmb3JlU2hvcnQnLFxuICAgICAgdmFsdWU6IG5vdEJlZm9yZSxcbiAgICAgIHZhbGlkYXRpb246IHtcbiAgICAgICAgaXNWYWxpZDogbm90QmVmb3JlID8gbmV3IERhdGUoKSA+PSBub3RCZWZvcmUgOiBmYWxzZSxcbiAgICAgICAgc2hvd1ZhbGlkYXRpb246IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgICBjb25zdCBub3RBZnRlciA9IHRoaXMuX2NlcnRpZmljYXRlU2VydmljZS5wYXJzZUNlcnRpZmljYXRlRGF0ZShcbiAgICAgIGNlcnRpZmljYXRlLmdldE5vdEFmdGVyKClcbiAgICApO1xuICAgIGF0dHJpYnV0ZXMucHVzaCh7XG4gICAgICB0cmFuc2xhdGlvbktleTogJ1NpZ25hdHVyZUluZm8uTm90VmFsaWRBZnRlclNob3J0JyxcbiAgICAgIHZhbHVlOiAgbm90QWZ0ZXIsXG4gICAgICB2YWxpZGF0aW9uOiB7XG4gICAgICAgIGlzVmFsaWQ6IG5vdEFmdGVyID8gbm90QWZ0ZXIgPj0gbmV3IERhdGUoKSA6IGZhbHNlLFxuICAgICAgICBzaG93VmFsaWRhdGlvbjogdHJ1ZVxuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBhdHRyaWJ1dGVzO1xuICB9XG5cbiAgaGlkZUNlcnRpZmljYXRlTW9kYWwoKSB7XG4gICAgdGhpcy5fYnNNb2RhbFJlZi5oaWRlKCk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJtb2RhbC1oZWFkZXIgcC0wXCI+XG4gIDxidXR0b25cbiAgICAoY2xpY2spPVwiaGlkZUNlcnRpZmljYXRlTW9kYWwoKVwiXG4gICAgdHlwZT1cImJ1dHRvblwiXG4gICAgY2xhc3M9XCJjbG9zZVwiXG4gICAgZGF0YS1kaXNtaXNzPVwibW9kYWxcIlxuICAgIGFyaWEtbGFiZWw9XCJDYW5jZWxcIlxuICA+XG4gICAgPHNwYW4gYXJpYS1oaWRkZW49XCJ0cnVlXCI+JnRpbWVzOzwvc3Bhbj5cbiAgPC9idXR0b24+XG48L2Rpdj5cbjxkaXYgY2xhc3M9XCJtb2RhbC1ib2R5IG10LTAgcHQtMFwiPlxuICA8ZGl2IGNsYXNzPVwiY2FyZC1ib2R5XCIgKm5nSWY9XCJ1c2VyXCI+XG4gICAgPGRpdiBjbGFzcz1cInJvd1wiPlxuICAgICAgPGRpdiBjbGFzcz1cImNvbC0xMlwiPlxuICAgICAgICA8aDUgY2xhc3M9XCJtdC0yIG1iLTNcIj5cbiAgICAgICAgICB7e3VzZXI/LmZhbWlseU5hbWV9fSB7e3VzZXI/LmdpdmVuTmFtZX19XG4gICAgICAgICAgPHNwYW4gKm5nSWY9XCJkYXRlQ3JlYXRlZFwiPnt7IGRhdGVDcmVhdGVkIHwgZGF0ZTonc2hvcnQnIH19PC9zcGFuPlxuICAgICAgICAgIChcbiAgICAgICAgICA8c3BhbiAqbmdJZj1cImlzVmVyaWZpZWRcIiBjbGFzcz1cInRleHQtcHVycGxlXCIgW3RyYW5zbGF0ZV09XCInU2lnbmF0dXJlSW5mby5WZXJpZmllZCdcIj48L3NwYW4+XG4gICAgICAgICAgPHNwYW4gKm5nSWY9XCIhaXNWZXJpZmllZFwiIGNsYXNzPVwidGV4dC1yZWRcIiBbdHJhbnNsYXRlXT1cIidTaWduYXR1cmVJbmZvLk5vdFZlcmlmaWVkJ1wiPjwvc3Bhbj5cbiAgICAgICAgICApXG4gICAgICAgICAgPHNtYWxsPiB7e2V4YW1pbmF0aW9uQ29kZX19IDwvc21hbGw+XG4gICAgICAgIDwvaDU+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwibWItM1wiPlxuICAgICAgPGRpdiBjbGFzcz1cIiBkLW5vbmUgZC1tZC1ibG9ja1wiPlxuICAgICAgICA8dWwgY2xhc3M9XCJuYXYgbmF2LXRhYnNcIj5cbiAgICAgICAgICA8bGkgY2xhc3M9XCJuYXYtaXRlbVwiPlxuICAgICAgICAgICAgPGEgY2xhc3M9XCJuYXYtbGluayBhY3RpdmVcIiBbY2xhc3MuYWN0aXZlXT1cInRhYiA9PT0gMVwiIHJlbD1cInRhYjFcIlxuICAgICAgICAgICAgICAgKGNsaWNrKT1cInRhYiA9MVwiPnt7J1NpZ25hdHVyZUluZm8uR2VuZXJhbCcgfCB0cmFuc2xhdGV9fTwvYT5cbiAgICAgICAgICA8L2xpPlxuICAgICAgICAgIDxsaSBjbGFzcz1cIm5hdi1pdGVtXCI+XG4gICAgICAgICAgICA8YSBjbGFzcz1cIm5hdi1saW5rXCIgW2NsYXNzLmFjdGl2ZV09XCJ0YWIgPT09IDJcIiByZWw9XCJ0YWIyXCJcbiAgICAgICAgICAgICAgIChjbGljayk9XCJ0YWIgPTJcIj4ge3snU2lnbmF0dXJlSW5mby5EZXRhaWxzJyB8IHRyYW5zbGF0ZX19PC9hPlxuICAgICAgICAgIDwvbGk+XG4gICAgICAgIDwvdWw+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgKm5nSWY9XCJ0YWI9PT0xXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiY2FyZFwiPlxuICAgICAgICA8aDUgY2xhc3M9XCJkLWJsb2NrIGNhcmQtaGVhZGVyIG10LTIgbWItbjIgYWxpZ24taXRlbXMtY2VudGVyXCI+XG4gICAgICAgICAgPGkgY2xhc3M9XCJmYSBmYS1jZXJ0aWZpY2F0ZVwiPjwvaT5cbiAgICAgICAgICB7eydTaWduYXR1cmVJbmZvLkNlcnRpZmljYXRlSW5mb3JtYXRpb24nIHwgdHJhbnNsYXRlfX1cbiAgICAgICAgPC9oNT5cbiAgICAgICAgPGhyLz5cbiAgICAgICAgPGRpdiBjbGFzcz1cImQtYmxvY2sgY2FyZC1ib2R5XCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNvbnRhaW5lciBmb250LWxnIG10LW4yIHB0LW4yXCIgKm5nSWY9XCJwdXJwb3NlcyAmJiBwdXJwb3Nlcy5sZW5ndGhcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyb3dcIj5cbiAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICA8c3Bhbj4ge3snU2lnbmF0dXJlSW5mby5DZXJ0aWZpY2F0ZVB1cnBvc2VzLkhlYWRlcicgfHRyYW5zbGF0ZX19PC9zcGFuPlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPHVsPlxuICAgICAgICAgICAgICA8bGkgKm5nRm9yPVwibGV0IHB1cnBvc2Ugb2YgcHVycG9zZXNcIj5cbiAgICAgICAgICAgICAgICB7eydTaWduYXR1cmVJbmZvLkNlcnRpZmljYXRlUHVycG9zZXMuJyArIHB1cnBvc2UgfHRyYW5zbGF0ZX19XG4gICAgICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgICA8L3VsPlxuICAgICAgICAgICAgPGhyLz5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8ZGl2ICpuZ0Zvcj1cImxldCBhdHRyaWJ1dGUgb2YgZ2VuZXJhbEF0dHJpYnV0ZXMgfCBzbGljZTogMDoyXCIgY2xhc3M9XCJyb3cgZm9udC1sZ1wiPlxuICAgICAgICAgICAgPGRpdiAqbmdJZj1cImF0dHJpYnV0ZSAmJiBhdHRyaWJ1dGUudmFsdWVcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXgtc20tY29sdW1uIGZsZXgtd3JhcFwiPlxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC10aGVtZSBjb2wtNCB0ZXh0LW5vd3JhcFwiPnt7YXR0cmlidXRlLnRyYW5zbGF0aW9uS2V5IHwgdHJhbnNsYXRlfX06IDwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImNvbC04XCI+e3thdHRyaWJ1dGUudmFsdWV9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwicm93IGZvbnQtbGdcIj5cbiAgICAgICAgICA8c3BhbiAqbmdGb3I9XCJsZXQgYXR0cmlidXRlIG9mIGdlbmVyYWxBdHRyaWJ1dGVzIHxzbGljZTogMjo0XCIgY2xhc3M9XCJmbGV4LXNtLWNvbHVtblwiPlxuICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJhdHRyaWJ1dGUgJiYgYXR0cmlidXRlLnZhbHVlXCI+XG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiY29sLTQgdGV4dC10aGVtZSB0ZXh0LW5vd3JhcFwiPnt7YXR0cmlidXRlLnRyYW5zbGF0aW9uS2V5IHwgdHJhbnNsYXRlfX06IDwvc3Bhbj5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJjb2wtNCBwci0yXCI+e3thdHRyaWJ1dGUudmFsdWUgfGRhdGU6J3Nob3J0J319PC9zcGFuPlxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgKm5nSWY9XCJ0YWI9PT0gMlwiPlxuICAgICAgPGRpdiBpZD1cImdyb3VwLWxpc3RcIiBjbGFzcz1cImZsZXgtY29sdW1uXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJzaXMtLWxpc3QtZ3JvdXAgc2lzLS1saXN0LWdyb3VwLWJvZHlcIj5cbiAgICAgICAgICA8dWwgY2xhc3M9XCJzaXMtLWxpc3QtZ3JvdXAgc2lzLS1saXN0LWdyb3VwLWhlYWRlclwiPlxuICAgICAgICAgICAgPGxpIGNsYXNzPVwic2lzLS1saXN0LWdyb3VwLWl0ZW1cIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtY2VudGVyIGFsaWduLWl0ZW1zLWNlbnRlclwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzaXMtLWxpc3QtZ3JvdXAtaXRlbV9sZ19jb2x1bW4gZC1ub25lIGQtYmxvY2tcIlxuICAgICAgICAgICAgICAgICAgICAgW3RyYW5zbGF0ZV09XCInU2lnbmF0dXJlSW5mby5GaWVsZCdcIj48L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2lzLS1saXN0LWdyb3VwLWl0ZW1fbGdfY29sdW1uIGQtbm9uZSBkLWJsb2NrIHB4LTRcIlxuICAgICAgICAgICAgICAgICAgICAgW3RyYW5zbGF0ZV09XCInU2lnbmF0dXJlSW5mby5WYWx1ZSdcIj48L2Rpdj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2xpPlxuICAgICAgICAgIDwvdWw+XG4gICAgICAgICAgPHVsIGNsYXNzPVwic2lzLS1saXN0LWdyb3VwIHNpcy0tbGlzdC1ncm91cC1ib2R5XCI+XG4gICAgICAgICAgICA8bGkgY2xhc3M9XCJzaXMtLWxpc3QtZ3JvdXAtaXRlbVwiICpuZ0Zvcj1cImxldCBhdHRyaWJ1dGUgb2Ygc2lnbmF0dXJlQXR0cmlidXRlc1wiPlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGp1c3RpZnktY29udGVudC1jZW50ZXIgYWxpZ24taXRlbXMtY2VudGVyIGxpc3QtY29sb3JcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2lzLS1saXN0LWdyb3VwLWl0ZW1fbGdfY29sdW1uIGQtbm9uZSBkLWJsb2NrIGZsZXgtd3JhcFwiPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtc2Vjb25kYXJ5XCI+XG4gICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYSBmYS1jZXJ0aWZpY2F0ZVwiPjwvaT5cbiAgICAgICAgICAgICAgICB7e2F0dHJpYnV0ZS50cmFuc2xhdGlvbktleSB8IHRyYW5zbGF0ZX19XG4gICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2lzLS1saXN0LWdyb3VwLWl0ZW1fbGdfY29sdW1uIGQtYmxvY2sgZmxleC13cmFwXCI+XG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1zZWNvbmRhcnkgcC0yIHAtbWQtMCB0ZXh0LWJyZWFrIFwiIFtuZ0NsYXNzXT1cIntcbiAgICAgICAgICAgICAgICAndGV4dC1yZWQnOiBhdHRyaWJ1dGUudmFsaWRhdGlvbiAmJiBhdHRyaWJ1dGUudmFsaWRhdGlvbi5zaG93VmFsaWRhdGlvbiAmJiAhYXR0cmlidXRlLnZhbGlkYXRpb24uaXNWYWxpZCxcbiAgICAgICAgICAgICAgICAndGV4dC1ncmVlbic6IGF0dHJpYnV0ZS52YWxpZGF0aW9uICYmIGF0dHJpYnV0ZS52YWxpZGF0aW9uLnNob3dWYWxpZGF0aW9uICYmIGF0dHJpYnV0ZS52YWxpZGF0aW9uLmlzVmFsaWRcbiAgICAgICAgICAgICAgfVwiPnt7IGF0dHJpYnV0ZS52YWx1ZX19PC9zcGFuPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgPC91bD5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJyb3dcIj5cbiAgICA8ZGl2IGNsYXNzPVwiY29sIHRleHQtY2VudGVyXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIChjbGljayk9XCJoaWRlQ2VydGlmaWNhdGVNb2RhbCgpXCJcbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLXN1Y2Nlc3NcIlxuICAgICAgICBbdHJhbnNsYXRlXT1cIidTaWduYXR1cmVJbmZvLkNsb3NlJ1wiXG4gICAgICA+PC9idXR0b24+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9kaXY+XG4iXX0=