UNPKG

ng-hotkeys

Version:

ng-hotkeys for Angular 14+

376 lines 42 kB
import { ApplicationRef, Component, ComponentFactoryResolver, ElementRef, Injector, Input, TemplateRef, ViewChild, ViewContainerRef } from "@angular/core"; import { DomPortalOutlet } from "./dom-portal-outlet"; import { TemplatePortal } from "./portal"; import { NgHotkeysService } from './ng-hotkeys.service'; import { NgHotkeysHelpService } from './ng-hotkeys-help.service'; import { animate, style, transition, trigger } from "@angular/animations"; import { distinctUntilChanged, map } from "rxjs/operators"; import { groupBy } from './utils'; import * as i0 from "@angular/core"; import * as i1 from "./ng-hotkeys.service"; import * as i2 from "./ng-hotkeys-help.service"; import * as i3 from "@angular/common"; import * as i4 from "./ng-hotkeys-help-item.component"; function NgHotkeysHelpComponent_ng_template_0_div_1_span_5_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "span"); i0.ɵɵtext(1); i0.ɵɵelementEnd(); } if (rf & 2) { const ctx_r3 = i0.ɵɵnextContext(3); i0.ɵɵadvance(1); i0.ɵɵtextInterpolate1(" ", ctx_r3.emptyMessage, " "); } } function NgHotkeysHelpComponent_ng_template_0_div_1_ul_7_ng_hot_keys_help_item_3_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelement(0, "ng-hot-keys-help-item", 11); } if (rf & 2) { const shortcut_r7 = ctx.$implicit; const i_r8 = ctx.index; i0.ɵɵproperty("shortcut", shortcut_r7)("index", i_r8); } } function NgHotkeysHelpComponent_ng_template_0_div_1_ul_7_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "ul", 8)(1, "h4", 9); i0.ɵɵtext(2); i0.ɵɵelementEnd(); i0.ɵɵtemplate(3, NgHotkeysHelpComponent_ng_template_0_div_1_ul_7_ng_hot_keys_help_item_3_Template, 1, 2, "ng-hot-keys-help-item", 10); i0.ɵɵelementEnd(); } if (rf & 2) { const label_r5 = ctx.$implicit; const ctx_r4 = i0.ɵɵnextContext(3); i0.ɵɵadvance(2); i0.ɵɵtextInterpolate(label_r5); i0.ɵɵadvance(1); i0.ɵɵproperty("ngForOf", ctx_r4.shortcuts[label_r5]); } } function NgHotkeysHelpComponent_ng_template_0_div_1_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "div")(1, "div", 3)(2, "h3", 4); i0.ɵɵtext(3); i0.ɵɵelementEnd()(); i0.ɵɵelementStart(4, "div", 5); i0.ɵɵtemplate(5, NgHotkeysHelpComponent_ng_template_0_div_1_span_5_Template, 2, 1, "span", 6); i0.ɵɵelementStart(6, "div"); i0.ɵɵtemplate(7, NgHotkeysHelpComponent_ng_template_0_div_1_ul_7_Template, 4, 2, "ul", 7); i0.ɵɵelementEnd()()(); } if (rf & 2) { const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵclassMap(ctx_r1.className); i0.ɵɵproperty("@enterAnimation", undefined); i0.ɵɵadvance(2); i0.ɵɵpropertyInterpolate1("id", "modal-", ctx_r1.title, ""); i0.ɵɵadvance(1); i0.ɵɵtextInterpolate(ctx_r1.title); i0.ɵɵadvance(2); i0.ɵɵproperty("ngIf", !ctx_r1.labels.length); i0.ɵɵadvance(2); i0.ɵɵproperty("ngForOf", ctx_r1.labels); } } function NgHotkeysHelpComponent_ng_template_0_div_2_Template(rf, ctx) { if (rf & 1) { const _r10 = i0.ɵɵgetCurrentView(); i0.ɵɵelementStart(0, "div", 12); i0.ɵɵlistener("mousedown", function NgHotkeysHelpComponent_ng_template_0_div_2_Template_div_mousedown_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r9 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r9.hide()); }); i0.ɵɵelementEnd(); } if (rf & 2) { i0.ɵɵproperty("@overlayAnimation", undefined); } } function NgHotkeysHelpComponent_ng_template_0_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "div", 0); i0.ɵɵtemplate(1, NgHotkeysHelpComponent_ng_template_0_div_1_Template, 8, 8, "div", 1); i0.ɵɵtemplate(2, NgHotkeysHelpComponent_ng_template_0_div_2_Template, 1, 1, "div", 2); i0.ɵɵelementEnd(); } if (rf & 2) { const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵattribute("aria-labelledby", "modal-" + ctx_r0.title); i0.ɵɵadvance(1); i0.ɵɵproperty("ngIf", ctx_r0.showing); i0.ɵɵadvance(1); i0.ɵɵproperty("ngIf", ctx_r0.showing); } } /** * @ignore */ const scrollAbleKeys = new Map([ [31, 1], [38, 1], [39, 1], [40, 1] ]); /** * @ignore */ const preventDefault = (ignore) => e => { const modal = e.target.closest(ignore); if (modal) { return; } e = e || window.event; if (e.preventDefault) e.preventDefault(); e.returnValue = false; }; /** * @ignore */ const preventDefaultForScrollKeys = e => { if (!scrollAbleKeys.has(e.keyCode)) { return; } preventDefault(e); return false; }; /** * @ignore */ let scrollEvents = [ { name: "wheel", callback: null }, { name: "touchmove", callback: null }, { name: "DOMMouseScroll", callback: null } ]; /** * @ignore */ const disableScroll = (ignore) => { scrollEvents = scrollEvents.map(event => { const callback = preventDefault(ignore); window.addEventListener(event.name, callback, { passive: false }); return { ...event, callback }; }); window.addEventListener("keydown", preventDefaultForScrollKeys); }; /** * @ignore */ const enableScroll = () => { scrollEvents = scrollEvents.map(event => { window.removeEventListener(event.name, event.callback); return { ...event, callback: null }; }); window.removeEventListener("keydown", preventDefaultForScrollKeys); }; /** * A Component to show all registered shortcut in the app * it is shown as a modal */ export class NgHotkeysHelpComponent { /** * @ignore */ constructor(componentFactoryResolver, appRef, keyboard, element, keyboardHelp, viewContainer, injector) { this.componentFactoryResolver = componentFactoryResolver; this.appRef = appRef; this.keyboard = keyboard; this.element = element; this.keyboardHelp = keyboardHelp; this.viewContainer = viewContainer; this.injector = injector; /** * Disable scrolling while modal is open */ this.disableScrolling = true; this.className = "help-modal"; /** * The title of the help screen * @default: "Keyboard shortcuts" */ this.title = "Keyboard shortcuts"; /** * What message to show when no shortcuts are available on the page. * @default "No shortcuts available" */ this.emptyMessage = "No shortcuts available"; /** * @ignore */ this.showing = false; this.bodyPortalHost = new DomPortalOutlet(document.body, this.componentFactoryResolver, this.appRef, this.injector); } /** * The shortcut to show/hide the help screen */ set key(value) { this._key = value; if (!value) { return; } if (this.clearIds) { this.keyboard.remove(this.clearIds); } this.clearIds = this.addShortcut({ key: value, preventDefault: true, command: () => this.toggle(), description: this.keyDescription, label: this.keyLabel }); } addShortcut(shortcut) { return this.keyboard.add(shortcut); } set closeKey(value) { this._closeKey = value; if (!value) { return; } if (this.closeKeyIds) { this.keyboard.remove(this.closeKeyIds); } this.closeKeyIds = this.addShortcut({ key: value, preventDefault: true, command: () => this.hide(), description: this.closeKeyDescription, label: this.closeKeyDescription }); } /** * Reveal the help screen manually. */ reveal() { this.hide(); if (this.disableScrolling) { disableScroll(`.${this.className}`); } const portal = new TemplatePortal(this.template, this.viewContainer); this.bodyPortalHost.attach(portal); this.showing = true; return this; } /** * Check if help screen is visible. * @returns boolean */ visible() { return this.bodyPortalHost.hasAttached(); } /** * Hide the help screen manually. */ hide() { if (this.disableScrolling) { enableScroll(); } if (!this.bodyPortalHost.hasAttached()) { return this; } this.bodyPortalHost.detach(); this.showing = false; return this; } /** * @ignore */ ngOnDestroy() { this.hide(); if (this.clearIds) { this.keyboard.remove(this.clearIds); } if (this.closeKeyIds) { this.keyboard.remove(this.closeKeyIds); } if (this.subscription) { this.subscription.unsubscribe(); } if (this.timeoutId) { clearTimeout(this.timeoutId); } } /** * Show/Hide the help screen manually. */ toggle() { this.visible() ? this.hide() : this.reveal(); return this; } /** * @ignore */ ngOnInit() { this.subscription = this.keyboardHelp.shortcuts$ .pipe(distinctUntilChanged(), map(shortcuts => groupBy(shortcuts, "label"))) .subscribe(shortcuts => { this.shortcuts = shortcuts; this.labels = Object.keys(shortcuts); }); } } NgHotkeysHelpComponent.ɵfac = function NgHotkeysHelpComponent_Factory(t) { return new (t || NgHotkeysHelpComponent)(i0.ɵɵdirectiveInject(i0.ComponentFactoryResolver), i0.ɵɵdirectiveInject(i0.ApplicationRef), i0.ɵɵdirectiveInject(i1.NgHotkeysService), i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i2.NgHotkeysHelpService), i0.ɵɵdirectiveInject(i0.ViewContainerRef), i0.ɵɵdirectiveInject(i0.Injector)); }; NgHotkeysHelpComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: NgHotkeysHelpComponent, selectors: [["ng-hot-keys-help"]], viewQuery: function NgHotkeysHelpComponent_Query(rf, ctx) { if (rf & 1) { i0.ɵɵviewQuery(TemplateRef, 5); } if (rf & 2) { let _t; i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.template = _t.first); } }, inputs: { disableScrolling: "disableScrolling", keyDescription: "keyDescription", keyLabel: "keyLabel", closeKeyLabel: "closeKeyLabel", closeKeyDescription: "closeKeyDescription", key: "key", closeKey: "closeKey", title: "title", emptyMessage: "emptyMessage" }, decls: 1, vars: 0, consts: [["role", "dialog", 1, "help-modal__container"], [3, "class", 4, "ngIf"], ["class", "help-modal__backdrop", 3, "mousedown", 4, "ngIf"], [1, "title"], [1, "title__text", 3, "id"], [1, "help-modal__body"], [4, "ngIf"], ["class", "help-modal__list", 4, "ngFor", "ngForOf"], [1, "help-modal__list"], [1, "item-group-label"], [3, "shortcut", "index", 4, "ngFor", "ngForOf"], [3, "shortcut", "index"], [1, "help-modal__backdrop", 3, "mousedown"]], template: function NgHotkeysHelpComponent_Template(rf, ctx) { if (rf & 1) { i0.ɵɵtemplate(0, NgHotkeysHelpComponent_ng_template_0_Template, 3, 3, "ng-template"); } }, dependencies: [i3.NgForOf, i3.NgIf, i4.NgHotkeysHelpItemComponent], styles: [".help-modal__container[_ngcontent-%COMP%]{position:fixed;z-index:500;inset:0;display:flex;align-items:center;justify-content:center}.help-modal[_ngcontent-%COMP%]{z-index:2000;min-width:420px;max-height:calc(100% - 100px);overflow:auto;padding:20px;box-shadow:0 11px 15px -7px #0003,0 24px 38px 3px #00000024,0 9px 46px 8px #0000001f;background:#fff}.item-group-label[_ngcontent-%COMP%]{text-transform:capitalize}.title[_ngcontent-%COMP%]{padding:20px 0}.title__text[_ngcontent-%COMP%]{margin:0;padding:0}.help-modal__list[_ngcontent-%COMP%]{padding:0}.help-modal__backdrop[_ngcontent-%COMP%]{position:absolute;background:rgba(0,0,0,.27);inset:0;z-index:1000;pointer-events:auto;-webkit-tap-highlight-color:transparent;opacity:1}"], data: { animation: [ trigger("enterAnimation", [ transition(":enter", [ style({ transform: "translateX(-100%)", opacity: 0 }), animate("0.33s cubic-bezier(0,0,0.3,1)", style({ transform: "translateX(0)", opacity: 1 })) ]), transition(":leave", [ style({ transform: "translateX(0)", opacity: 1 }), animate("0.23s cubic-bezier(0,0,0.3,1)", style({ transform: "translateX(-100%)", opacity: 0 })) ]) ]), trigger("overlayAnimation", [ transition(":enter", [ style({ opacity: 0 }), animate("1s cubic-bezier(0,0,0.3,1)", style({ opacity: 1 })) ]), transition(":leave", [ style({ opacity: 1 }), animate("1s cubic-bezier(0,0,0.3,1)", style({ opacity: 0 })) ]) ]) ] } }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(NgHotkeysHelpComponent, [{ type: Component, args: [{ selector: "ng-hot-keys-help", animations: [ trigger("enterAnimation", [ transition(":enter", [ style({ transform: "translateX(-100%)", opacity: 0 }), animate("0.33s cubic-bezier(0,0,0.3,1)", style({ transform: "translateX(0)", opacity: 1 })) ]), transition(":leave", [ style({ transform: "translateX(0)", opacity: 1 }), animate("0.23s cubic-bezier(0,0,0.3,1)", style({ transform: "translateX(-100%)", opacity: 0 })) ]) ]), trigger("overlayAnimation", [ transition(":enter", [ style({ opacity: 0 }), animate("1s cubic-bezier(0,0,0.3,1)", style({ opacity: 1 })) ]), transition(":leave", [ style({ opacity: 1 }), animate("1s cubic-bezier(0,0,0.3,1)", style({ opacity: 0 })) ]) ]) ], template: "<ng-template>\n <div class=\"help-modal__container\" [attr.aria-labelledby]=\"'modal-' + title\" role=\"dialog\">\n <div class=\"{{className}}\" [@enterAnimation] *ngIf=\"showing\">\n <div class=\"title\">\n <h3 id=\"modal-{{title}}\" class=\"title__text\">{{title}}</h3>\n </div>\n <div class=\"help-modal__body\">\n <span *ngIf=\"!labels.length\">\n {{emptyMessage}}\n </span>\n <div>\n <ul *ngFor=\"let label of labels\" class=\"help-modal__list\">\n <h4 class=\"item-group-label\">{{label}}</h4>\n <ng-hot-keys-help-item\n *ngFor=\"let shortcut of shortcuts[label]; let i = index\"\n [shortcut]=\"shortcut\"\n [index]=\"i\"\n ></ng-hot-keys-help-item>\n </ul>\n </div>\n </div>\n </div>\n <div class=\"help-modal__backdrop\" [@overlayAnimation] (mousedown)=\"hide()\" *ngIf=\"showing\"></div>\n </div>\n</ng-template>\n", styles: [".help-modal__container{position:fixed;z-index:500;inset:0;display:flex;align-items:center;justify-content:center}.help-modal{z-index:2000;min-width:420px;max-height:calc(100% - 100px);overflow:auto;padding:20px;box-shadow:0 11px 15px -7px #0003,0 24px 38px 3px #00000024,0 9px 46px 8px #0000001f;background:#fff}.item-group-label{text-transform:capitalize}.title{padding:20px 0}.title__text{margin:0;padding:0}.help-modal__list{padding:0}.help-modal__backdrop{position:absolute;background:rgba(0,0,0,.27);inset:0;z-index:1000;pointer-events:auto;-webkit-tap-highlight-color:transparent;opacity:1}\n"] }] }], function () { return [{ type: i0.ComponentFactoryResolver }, { type: i0.ApplicationRef }, { type: i1.NgHotkeysService }, { type: i0.ElementRef }, { type: i2.NgHotkeysHelpService }, { type: i0.ViewContainerRef }, { type: i0.Injector }]; }, { disableScrolling: [{ type: Input }], keyDescription: [{ type: Input }], keyLabel: [{ type: Input }], closeKeyLabel: [{ type: Input }], closeKeyDescription: [{ type: Input }], key: [{ type: Input }], closeKey: [{ type: Input }], title: [{ type: Input }], emptyMessage: [{ type: Input }], template: [{ type: ViewChild, args: [TemplateRef] }] }); })(); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctaG90a2V5cy1oZWxwLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25nLWhvdGtleXMvc3JjL2xpYi9uZy1ob3RrZXlzLWhlbHAuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctaG90a2V5cy9zcmMvbGliL25nLWhvdGtleXMtaGVscC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0gsY0FBYyxFQUNkLFNBQVMsRUFDVCx3QkFBd0IsRUFDeEIsVUFBVSxFQUNWLFFBQVEsRUFDUixLQUFLLEVBR0wsV0FBVyxFQUNYLFNBQVMsRUFDVCxnQkFBZ0IsRUFDbkIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDMUMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDeEQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDakUsT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzFFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sU0FBUyxDQUFDOzs7Ozs7O0lDWmxCLDRCQUE2QjtJQUN6QixZQUNKO0lBQUEsaUJBQU87OztJQURILGVBQ0o7SUFESSxvREFDSjs7O0lBSVEsNENBSXlCOzs7O0lBRmpCLHNDQUFxQixlQUFBOzs7SUFKakMsNkJBQTBELFlBQUE7SUFDekIsWUFBUztJQUFBLGlCQUFLO0lBQzNDLHFJQUl5QjtJQUM3QixpQkFBSzs7OztJQU40QixlQUFTO0lBQVQsOEJBQVM7SUFFVCxlQUFxQjtJQUFyQixvREFBcUI7OztJQVpsRSwyQkFBNkQsYUFBQSxZQUFBO0lBRVIsWUFBUztJQUFBLGlCQUFLLEVBQUE7SUFFL0QsOEJBQThCO0lBQzFCLDZGQUVPO0lBQ1AsMkJBQUs7SUFDRCx5RkFPSztJQUNULGlCQUFNLEVBQUEsRUFBQTs7O0lBakJULCtCQUFxQjtJQUFDLDJDQUFpQjtJQUVoQyxlQUFvQjtJQUFwQiwyREFBb0I7SUFBcUIsZUFBUztJQUFULGtDQUFTO0lBRy9DLGVBQW9CO0lBQXBCLDRDQUFvQjtJQUlELGVBQVM7SUFBVCx1Q0FBUzs7OztJQVczQywrQkFBMkY7SUFBckMsd0xBQWEsZUFBQSxhQUFNLENBQUEsSUFBQztJQUFpQixpQkFBTTs7SUFBL0QsNkNBQW1COzs7SUFyQnpELDhCQUEyRjtJQUN2RixxRkFtQk07SUFDTixxRkFBaUc7SUFDckcsaUJBQU07OztJQXRCNkIsMERBQXlDO0lBQzFCLGVBQWE7SUFBYixxQ0FBYTtJQW9CaUIsZUFBYTtJQUFiLHFDQUFhOztBREVqRzs7R0FFRztBQUNILE1BQU0sY0FBYyxHQUFHLElBQUksR0FBRyxDQUFDO0lBQzNCLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNQLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNQLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNQLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztDQUNWLENBQUMsQ0FBQztBQUNIOztHQUVHO0FBQ0gsTUFBTSxjQUFjLEdBQUcsQ0FBQyxNQUFjLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFO0lBQzNDLE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3ZDLElBQUksS0FBSyxFQUFFO1FBQ1AsT0FBTztLQUNWO0lBQ0QsQ0FBQyxHQUFHLENBQUMsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDO0lBQ3RCLElBQUksQ0FBQyxDQUFDLGNBQWM7UUFBRSxDQUFDLENBQUMsY0FBYyxFQUFFLENBQUM7SUFDekMsQ0FBQyxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUM7QUFDMUIsQ0FBQyxDQUFDO0FBQ0Y7O0dBRUc7QUFDSCxNQUFNLDJCQUEyQixHQUFHLENBQUMsQ0FBQyxFQUFFO0lBQ3BDLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRTtRQUNoQyxPQUFPO0tBQ1Y7SUFDRCxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEIsT0FBTyxLQUFLLENBQUM7QUFDakIsQ0FBQyxDQUFDO0FBQ0Y7O0dBRUc7QUFDSCxJQUFJLFlBQVksR0FBRztJQUNmLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO0lBQ2pDLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO0lBQ3JDLEVBQUUsSUFBSSxFQUFFLGdCQUFnQixFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUU7Q0FDN0MsQ0FBQztBQUVGOztHQUVHO0FBQ0gsTUFBTSxhQUFhLEdBQUcsQ0FBQyxNQUFjLEVBQUUsRUFBRTtJQUNyQyxZQUFZLEdBQUcsWUFBWSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRTtRQUNwQyxNQUFNLFFBQVEsR0FBRyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDeEMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDbEUsT0FBTztZQUNILEdBQUcsS0FBSztZQUNSLFFBQVE7U0FDWCxDQUFDO0lBQ04sQ0FBQyxDQUFDLENBQUM7SUFDSCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLDJCQUEyQixDQUFDLENBQUM7QUFDcEUsQ0FBQyxDQUFDO0FBQ0Y7O0dBRUc7QUFDSCxNQUFNLFlBQVksR0FBRyxHQUFHLEVBQUU7SUFDdEIsWUFBWSxHQUFHLFlBQVksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUU7UUFDcEMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3ZELE9BQU87WUFDSCxHQUFHLEtBQUs7WUFDUixRQUFRLEVBQUUsSUFBSTtTQUNqQixDQUFDO0lBQ04sQ0FBQyxDQUFDLENBQUM7SUFDSCxNQUFNLENBQUMsbUJBQW1CLENBQUMsU0FBUyxFQUFFLDJCQUEyQixDQUFDLENBQUM7QUFDdkUsQ0FBQyxDQUFDO0FBRUY7OztHQUdHO0FBa0NILE1BQU0sT0FBTyxzQkFBc0I7SUFpSC9COztPQUVHO0lBQ0gsWUFDWSx3QkFBa0QsRUFDbEQsTUFBc0IsRUFDdEIsUUFBMEIsRUFDMUIsT0FBbUIsRUFDbkIsWUFBa0MsRUFDbEMsYUFBK0IsRUFDL0IsUUFBa0I7UUFObEIsNkJBQXdCLEdBQXhCLHdCQUF3QixDQUEwQjtRQUNsRCxXQUFNLEdBQU4sTUFBTSxDQUFnQjtRQUN0QixhQUFRLEdBQVIsUUFBUSxDQUFrQjtRQUMxQixZQUFPLEdBQVAsT0FBTyxDQUFZO1FBQ25CLGlCQUFZLEdBQVosWUFBWSxDQUFzQjtRQUNsQyxrQkFBYSxHQUFiLGFBQWEsQ0FBa0I7UUFDL0IsYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQTFIOUI7O1dBRUc7UUFDTSxxQkFBZ0IsR0FBRyxJQUFJLENBQUM7UUFNMUIsY0FBUyxHQUFHLFlBQVksQ0FBQztRQXlFaEM7OztXQUdHO1FBQ00sVUFBSyxHQUFHLG9CQUFvQixDQUFDO1FBQ3RDOzs7V0FHRztRQUNNLGlCQUFZLEdBQUcsd0JBQXdCLENBQUM7UUFTakQ7O1dBRUc7UUFDSCxZQUFPLEdBQUcsS0FBSyxDQUFDO1FBcUJaLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxlQUFlLENBQ3JDLFFBQVEsQ0FBQyxJQUFJLEVBQ2IsSUFBSSxDQUFDLHdCQUF3QixFQUM3QixJQUFJLENBQUMsTUFBTSxFQUNYLElBQUksQ0FBQyxRQUFRLENBQ2hCLENBQUM7SUFDTixDQUFDO0lBM0ZEOztPQUVHO0lBQ0gsSUFDSSxHQUFHLENBQUMsS0FBYTtRQUNqQixJQUFJLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQztRQUNsQixJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ1IsT0FBTztTQUNWO1FBQ0QsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2YsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQ3ZDO1FBQ0QsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO1lBQzdCLEdBQUcsRUFBRSxLQUFLO1lBQ1YsY0FBYyxFQUFFLElBQUk7WUFDcEIsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDNUIsV0FBVyxFQUFFLElBQUksQ0FBQyxjQUFjO1lBQ2hDLEtBQUssRUFBRSxJQUFJLENBQUMsUUFBUTtTQUN2QixDQUFDLENBQUM7SUFDUCxDQUFDO0lBRU8sV0FBVyxDQUFDLFFBQWtCO1FBQ2xDLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVELElBQ0ksUUFBUSxDQUFDLEtBQWE7UUFDdEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFDdkIsSUFBSSxDQUFDLEtBQUssRUFBRTtZQUNSLE9BQU87U0FDVjtRQUNELElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUNsQixJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7U0FDMUM7UUFDRCxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7WUFDaEMsR0FBRyxFQUFFLEtBQUs7WUFDVixjQUFjLEVBQUUsSUFBSTtZQUNwQixPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRTtZQUMxQixXQUFXLEVBQUUsSUFBSSxDQUFDLG1CQUFtQjtZQUNyQyxLQUFLLEVBQUUsSUFBSSxDQUFDLG1CQUFtQjtTQUNsQyxDQUFDLENBQUE7SUFDTixDQUFDO0lBb0REOztPQUVHO0lBQ0gsTUFBTTtRQUNGLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNaLElBQUksSUFBSSxDQUFDLGdCQUFnQixFQUFFO1lBQ3ZCLGFBQWEsQ0FBQyxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDO1NBQ3ZDO1FBQ0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxjQUFjLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDbkMsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7UUFDcEIsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVEOzs7T0FHRztJQUNILE9BQU87UUFDSCxPQUFPLElBQUksQ0FBQyxjQUFjLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDN0MsQ0FBQztJQUNEOztPQUVHO0lBQ0gsSUFBSTtRQUNBLElBQUksSUFBSSxDQUFDLGdCQUFnQixFQUFFO1lBQ3ZCLFlBQVksRUFBRSxDQUFDO1NBQ2xCO1FBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsV0FBVyxFQUFFLEVBQUU7WUFDcEMsT0FBTyxJQUFJLENBQUM7U0FDZjtRQUNELElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDN0IsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDckIsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsV0FBVztRQUNQLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNaLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUNmLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUN2QztRQUNELElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUNsQixJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7U0FDMUM7UUFDRCxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUU7WUFDbkIsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztTQUNuQztRQUNELElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNoQixZQUFZLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1NBQ2hDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0gsTUFBTTtRQUNGLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDN0MsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQW1CRDs7T0FFRztJQUNILFFBQVE7UUFDSixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsVUFBVTthQUMzQyxJQUFJLENBQ0Qsb0JBQW9CLEVBQUUsRUFDdEIsR0FBRyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUNoRDthQUNBLFNBQVMsQ0FBQyxTQUFTLENBQUMsRUFBRTtZQUNuQixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztZQUMzQixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDekMsQ0FBQyxDQUFDLENBQUM7SUFDWCxDQUFDOzs0RkFsT1Esc0JBQXNCO3lFQUF0QixzQkFBc0I7dUJBZ0dwQixXQUFXOzs7OztRQ2pPMUIsb0ZBd0JjO3UwQkQ0RUU7WUFDUixPQUFPLENBQUMsZ0JBQWdCLEVBQUU7Z0JBQ3RCLFVBQVUsQ0FBQyxRQUFRLEVBQUU7b0JBQ2pCLEtBQUssQ0FBQyxFQUFFLFNBQVMsRUFBRSxtQkFBbUIsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUM7b0JBQ3JELE9BQU8sQ0FDSCwrQkFBK0IsRUFDL0IsS0FBSyxDQUFDLEVBQUUsU0FBUyxFQUFFLGVBQWUsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FDcEQ7aUJBQ0osQ0FBQztnQkFDRixVQUFVLENBQUMsUUFBUSxFQUFFO29CQUNqQixLQUFLLENBQUMsRUFBRSxTQUFTLEVBQUUsZUFBZSxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQztvQkFDakQsT0FBTyxDQUNILCtCQUErQixFQUMvQixLQUFLLENBQUMsRUFBRSxTQUFTLEVBQUUsbUJBQW1CLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQ3hEO2lCQUNKLENBQUM7YUFDTCxDQUFDO1lBQ0YsT0FBTyxDQUFDLGtCQUFrQixFQUFFO2dCQUN4QixVQUFVLENBQUMsUUFBUSxFQUFFO29CQUNqQixLQUFLLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUM7b0JBQ3JCLE9BQU8sQ0FBQyw0QkFBNEIsRUFBRSxLQUFLLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztpQkFDL0QsQ0FBQztnQkFDRixVQUFVLENBQUMsUUFBUSxFQUFFO29CQUNqQixLQUFLLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUM7b0JBQ3JCLE9BQU8sQ0FBQyw0QkFBNEIsRUFBRSxLQUFLLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztpQkFDL0QsQ0FBQzthQUNMLENBQUM7U0FDTDt1RkFFUSxzQkFBc0I7Y0FqQ2xDLFNBQVM7MkJBQ0ksa0JBQWtCLGNBR2hCO29CQUNSLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRTt3QkFDdEIsVUFBVSxDQUFDLFFBQVEsRUFBRTs0QkFDakIsS0FBSyxDQUFDLEVBQUUsU0FBUyxFQUFFLG1CQUFtQixFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQzs0QkFDckQsT0FBTyxDQUNILCtCQUErQixFQUMvQixLQUFLLENBQUMsRUFBRSxTQUFTLEVBQUUsZUFBZSxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUNwRDt5QkFDSixDQUFDO3dCQUNGLFVBQVUsQ0FBQyxRQUFRLEVBQUU7NEJBQ2pCLEtBQUssQ0FBQyxFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDOzRCQUNqRCxPQUFPLENBQ0gsK0JBQStCLEVBQy9CLEtBQUssQ0FBQyxFQUFFLFNBQVMsRUFBRSxtQkFBbUIsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FDeEQ7eUJBQ0osQ0FBQztxQkFDTCxDQUFDO29CQUNGLE9BQU8sQ0FBQyxrQkFBa0IsRUFBRTt3QkFDeEIsVUFBVSxDQUFDLFFBQVEsRUFBRTs0QkFDakIsS0FBSyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDOzRCQUNyQixPQUFPLENBQUMsNEJBQTRCLEVBQUUsS0FBSyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7eUJBQy9ELENBQUM7d0JBQ0YsVUFBVSxDQUFDLFFBQVEsRUFBRTs0QkFDakIsS0FBSyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDOzRCQUNyQixPQUFPLENBQUMsNEJBQTRCLEVBQUUsS0FBSyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7eUJBQy9ELENBQUM7cUJBQ0wsQ0FBQztpQkFDTDt5UEFNUSxnQkFBZ0I7a0JBQXhCLEtBQUs7WUFhRyxjQUFjO2tCQUF0QixLQUFLO1lBT0csUUFBUTtrQkFBaEIsS0FBSztZQU9HLGFBQWE7a0JBQXJCLEtBQUs7WUFPRyxtQkFBbUI7a0JBQTNCLEtBQUs7WUFNRixHQUFHO2tCQUROLEtBQUs7WUF1QkYsUUFBUTtrQkFEWCxLQUFLO1lBc0JHLEtBQUs7a0JBQWIsS0FBSztZQUtHLFlBQVk7a0JBQXBCLEtBQUs7WUFJa0IsUUFBUTtrQkFBL0IsU0FBUzttQkFBQyxXQUFXIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgICBBcHBsaWNhdGlvblJlZixcbiAgICBDb21wb25lbnQsXG4gICAgQ29tcG9uZW50RmFjdG9yeVJlc29sdmVyLFxuICAgIEVsZW1lbnRSZWYsXG4gICAgSW5qZWN0b3IsXG4gICAgSW5wdXQsXG4gICAgT25EZXN0cm95LFxuICAgIE9uSW5pdCxcbiAgICBUZW1wbGF0ZVJlZixcbiAgICBWaWV3Q2hpbGQsXG4gICAgVmlld0NvbnRhaW5lclJlZlxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgRG9tUG9ydGFsT3V0bGV0IH0gZnJvbSBcIi4vZG9tLXBvcnRhbC1vdXRsZXRcIjtcbmltcG9ydCB7IFRlbXBsYXRlUG9ydGFsIH0gZnJvbSBcIi4vcG9ydGFsXCI7XG5pbXBvcnQgeyBOZ0hvdGtleXNTZXJ2aWNlIH0gZnJvbSAnLi9uZy1ob3RrZXlzLnNlcnZpY2UnO1xuaW1wb3J0IHsgTmdIb3RrZXlzSGVscFNlcnZpY2UgfSBmcm9tICcuL25nLWhvdGtleXMtaGVscC5zZXJ2aWNlJztcbmltcG9ydCB7IGFuaW1hdGUsIHN0eWxlLCB0cmFuc2l0aW9uLCB0cmlnZ2VyIH0gZnJvbSBcIkBhbmd1bGFyL2FuaW1hdGlvbnNcIjtcbmltcG9ydCB7IGRpc3RpbmN0VW50aWxDaGFuZ2VkLCBtYXAgfSBmcm9tIFwicnhqcy9vcGVyYXRvcnNcIjtcbmltcG9ydCB7IGdyb3VwQnkgfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbkxpa2UgfSBmcm9tIFwicnhqc1wiO1xuaW1wb3J0IHsgU2hvcnRjdXQgfSBmcm9tICcuL25nLWhvdGtleXMuaW50ZXJmYWNlcyc7XG5cblxuLyoqXG4gKiBAaWdub3JlXG4gKi9cbmNvbnN0IHNjcm9sbEFibGVLZXlzID0gbmV3IE1hcChbXG4gICAgWzMxLCAxXSxcbiAgICBbMzgsIDFdLFxuICAgIFszOSwgMV0sXG4gICAgWzQwLCAxXVxuXSk7XG4vKipcbiAqIEBpZ25vcmVcbiAqL1xuY29uc3QgcHJldmVudERlZmF1bHQgPSAoaWdub3JlOiBzdHJpbmcpID0+IGUgPT4ge1xuICAgIGNvbnN0IG1vZGFsID0gZS50YXJnZXQuY2xvc2VzdChpZ25vcmUpO1xuICAgIGlmIChtb2RhbCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGUgPSBlIHx8IHdpbmRvdy5ldmVudDtcbiAgICBpZiAoZS5wcmV2ZW50RGVmYXVsdCkgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGUucmV0dXJuVmFsdWUgPSBmYWxzZTtcbn07XG4vKipcbiAqIEBpZ25vcmVcbiAqL1xuY29uc3QgcHJldmVudERlZmF1bHRGb3JTY3JvbGxLZXlzID0gZSA9PiB7XG4gICAgaWYgKCFzY3JvbGxBYmxlS2V5cy5oYXMoZS5rZXlDb2RlKSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHByZXZlbnREZWZhdWx0KGUpO1xuICAgIHJldHVybiBmYWxzZTtcbn07XG4vKipcbiAqIEBpZ25vcmVcbiAqL1xubGV0IHNjcm9sbEV2ZW50cyA9IFtcbiAgICB7IG5hbWU6IFwid2hlZWxcIiwgY2FsbGJhY2s6IG51bGwgfSxcbiAgICB7IG5hbWU6IFwidG91Y2htb3ZlXCIsIGNhbGxiYWNrOiBudWxsIH0sXG4gICAgeyBuYW1lOiBcIkRPTU1vdXNlU2Nyb2xsXCIsIGNhbGxiYWNrOiBudWxsIH1cbl07XG5cbi8qKlxuICogQGlnbm9yZVxuICovXG5jb25zdCBkaXNhYmxlU2Nyb2xsID0gKGlnbm9yZTogc3RyaW5nKSA9PiB7XG4gICAgc2Nyb2xsRXZlbnRzID0gc2Nyb2xsRXZlbnRzLm1hcChldmVudCA9PiB7XG4gICAgICAgIGNvbnN0IGNhbGxiYWNrID0gcHJldmVudERlZmF1bHQoaWdub3JlKTtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnQubmFtZSwgY2FsbGJhY2ssIHsgcGFzc2l2ZTogZmFsc2UgfSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi5ldmVudCxcbiAgICAgICAgICAgIGNhbGxiYWNrXG4gICAgICAgIH07XG4gICAgfSk7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJrZXlkb3duXCIsIHByZXZlbnREZWZhdWx0Rm9yU2Nyb2xsS2V5cyk7XG59O1xuLyoqXG4gKiBAaWdub3JlXG4gKi9cbmNvbnN0IGVuYWJsZVNjcm9sbCA9ICgpID0+IHtcbiAgICBzY3JvbGxFdmVudHMgPSBzY3JvbGxFdmVudHMubWFwKGV2ZW50ID0+IHtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnQubmFtZSwgZXZlbnQuY2FsbGJhY2spO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4uZXZlbnQsXG4gICAgICAgICAgICBjYWxsYmFjazogbnVsbFxuICAgICAgICB9O1xuICAgIH0pO1xuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKFwia2V5ZG93blwiLCBwcmV2ZW50RGVmYXVsdEZvclNjcm9sbEtleXMpO1xufTtcblxuLyoqXG4gKiBBIENvbXBvbmVudCB0byBzaG93IGFsbCByZWdpc3RlcmVkIHNob3J0Y3V0IGluIHRoZSBhcHBcbiAqIGl0IGlzIHNob3duIGFzIGEgbW9kYWxcbiAqL1xuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6IFwibmctaG90LWtleXMtaGVscFwiLFxuICAgIHRlbXBsYXRlVXJsOiBcIi4vbmctaG90a2V5cy1oZWxwLmNvbXBvbmVudC5odG1sXCIsXG4gICAgc3R5bGVVcmxzOiBbXCIuL25nLWhvdGtleXMtaGVscC5jb21wb25lbnQuY3NzXCJdLFxuICAgIGFuaW1hdGlvbnM6IFtcbiAgICAgICAgdHJpZ2dlcihcImVudGVyQW5pbWF0aW9uXCIsIFtcbiAgICAgICAgICAgIHRyYW5zaXRpb24oXCI6ZW50ZXJcIiwgW1xuICAgICAgICAgICAgICAgIHN0eWxlKHsgdHJhbnNmb3JtOiBcInRyYW5zbGF0ZVgoLTEwMCUpXCIsIG9wYWNpdHk6IDAgfSksXG4gICAgICAgICAgICAgICAgYW5pbWF0ZShcbiAgICAgICAgICAgICAgICAgICAgXCIwLjMzcyBjdWJpYy1iZXppZXIoMCwwLDAuMywxKVwiLFxuICAgICAgICAgICAgICAgICAgICBzdHlsZSh7IHRyYW5zZm9ybTogXCJ0cmFuc2xhdGVYKDApXCIsIG9wYWNpdHk6IDEgfSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICBdKSxcbiAgICAgICAgICAgIHRyYW5zaXRpb24oXCI6bGVhdmVcIiwgW1xuICAgICAgICAgICAgICAgIHN0eWxlKHsgdHJhbnNmb3JtOiBcInRyYW5zbGF0ZVgoMClcIiwgb3BhY2l0eTogMSB9KSxcbiAgICAgICAgICAgICAgICBhbmltYXRlKFxuICAgICAgICAgICAgICAgICAgICBcIjAuMjNzIGN1YmljLWJlemllcigwLDAsMC4zLDEpXCIsXG4gICAgICAgICAgICAgICAgICAgIHN0eWxlKHsgdHJhbnNmb3JtOiBcInRyYW5zbGF0ZVgoLTEwMCUpXCIsIG9wYWNpdHk6IDAgfSlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICBdKVxuICAgICAgICBdKSxcbiAgICAgICAgdHJpZ2dlcihcIm92ZXJsYXlBbmltYXRpb25cIiwgW1xuICAgICAgICAgICAgdHJhbnNpdGlvbihcIjplbnRlclwiLCBbXG4gICAgICAgICAgICAgICAgc3R5bGUoeyBvcGFjaXR5OiAwIH0pLFxuICAgICAgICAgICAgICAgIGFuaW1hdGUoXCIxcyBjdWJpYy1iZXppZXIoMCwwLDAuMywxKVwiLCBzdHlsZSh7IG9wYWNpdHk6IDEgfSkpXG4gICAgICAgICAgICBdKSxcbiAgICAgICAgICAgIHRyYW5zaXRpb24oXCI6bGVhdmVcIiwgW1xuICAgICAgICAgICAgICAgIHN0eWxlKHsgb3BhY2l0eTogMSB9KSxcbiAgICAgICAgICAgICAgICBhbmltYXRlKFwiMXMgY3ViaWMtYmV6aWVyKDAsMCwwLjMsMSlcIiwgc3R5bGUoeyBvcGFjaXR5OiAwIH0pKVxuICAgICAgICAgICAgXSlcbiAgICAgICAgXSlcbiAgICBdXG59KVxuZXhwb3J0IGNsYXNzIE5nSG90a2V5c0hlbHBDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gICAgLyoqXG4gICAgICogRGlzYWJsZSBzY3JvbGxpbmcgd2hpbGUgbW9kYWwgaXMgb3BlblxuICAgICAqL1xuICAgIEBJbnB1dCgpIGRpc2FibGVTY3JvbGxpbmcgPSB0cnVlO1xuICAgIC8qKlxuICAgICAqIEBpZ25vcmVcbiAgICAgKi9cbiAgICBwcml2YXRlIF9rZXk6IHN0cmluZztcblxuICAgIHB1YmxpYyBjbGFzc05hbWUgPSBcImhlbHAtbW9kYWxcIjtcblxuICAgIC8qKlxuICAgICAqIEEgZGVzY3JpcHRpb24gdGhhdCB3aWxsIGJlIHNob3duIGluIHRoZSBoZWxwIG1lbnUuXG4gICAgICogTVVTVCBhbG1vc3QgcHJvdmlkZSBhIGxhYmVsIGZvciB0aGUga2V5IHRvIGJlIHNob3duXG4gICAgICogaW4gdGhlIGhlbHAgbWVudVxuICAgICAqL1xuICAgIEBJbnB1dCgpIGtleURlc2NyaXB0aW9uOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbGFiZWwgdG8gZ3JvdXAgYnkgdGhlIGhlbHAgbWVudSB0b2dnbGUgc2hvcnRjdXQuXG4gICAgICogbXVzdCBwcm92aWRlIGEgZGVzY3JpcHRpb24gZm9yIHRoZSBrZXkgdG8gc2hvd1xuICAgICAqIGluIHRoZSBoZWxwIG1lbnVcbiAgICAgKi9cbiAgICBASW5wdXQoKSBrZXlMYWJlbDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGxhYmVsIHRvIGdyb3VwIGJ5IHRoZSBoZWxwIG1lbnUgY2xvc2Ugc2hvcnRjdXQuXG4gICAgICogbXVzdCBwcm92aWRlIGEgZGVzY3JpcHRpb24gZm9yIHRoZSBrZXkgdG8gc2hvd1xuICAgICAqIGluIHRoZSBoZWxwIG1lbnVcbiAgICAgKi9cbiAgICBASW5wdXQoKSBjbG9zZUtleUxhYmVsOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBBIGRlc2NyaXB0aW9uIHRoYXQgd2lsbCBiZSBzaG93biBpbiB0aGUgaGVscCBtZW51LlxuICAgICAqIE1VU1QgYWxtb3N0IHByb3ZpZGUgYSBsYWJlbCBmb3IgdGhlIGtleSB0byBiZSBzaG93blxuICAgICAqIGluIHRoZSBoZWxwIG1lbnVcbiAgICAgKi9cbiAgICBASW5wdXQoKSBjbG9zZUtleURlc2NyaXB0aW9uOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgc2hvcnRjdXQgdG8gc2hvdy9oaWRlIHRoZSBoZWxwIHNjcmVlblxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgc2V0IGtleSh2YWx1ZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuX2tleSA9IHZhbHVlO1xuICAgICAgICBpZiAoIXZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuY2xlYXJJZHMpIHtcbiAgICAgICAgICAgIHRoaXMua2V5Ym9hcmQucmVtb3ZlKHRoaXMuY2xlYXJJZHMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2xlYXJJZHMgPSB0aGlzLmFkZFNob3J0Y3V0KHtcbiAgICAgICAgICAgIGtleTogdmFsdWUsXG4gICAgICAgICAgICBwcmV2ZW50RGVmYXVsdDogdHJ1ZSxcbiAgICAgICAgICAgIGNvbW1hbmQ6ICgpID0+IHRoaXMudG9nZ2xlKCksXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogdGhpcy5rZXlEZXNjcmlwdGlvbixcbiAgICAgICAgICAgIGxhYmVsOiB0aGlzLmtleUxhYmVsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgYWRkU2hvcnRjdXQoc2hvcnRjdXQ6IFNob3J0Y3V0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmtleWJvYXJkLmFkZChzaG9ydGN1dCk7XG4gICAgfVxuICAgIHByaXZhdGUgX2Nsb3NlS2V5O1xuICAgIEBJbnB1dCgpXG4gICAgc2V0IGNsb3NlS2V5KHZhbHVlOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5fY2xvc2VLZXkgPSB2YWx1ZTtcbiAgICAgICAgaWYgKCF2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmNsb3NlS2V5SWRzKSB7XG4gICAgICAgICAgICB0aGlzLmtleWJvYXJkLnJlbW92ZSh0aGlzLmNsb3NlS2V5SWRzKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNsb3NlS2V5SWRzID0gdGhpcy5hZGRTaG9ydGN1dCh7XG4gICAgICAgICAgICBrZXk6IHZhbHVlLFxuICAgICAgICAgICAgcHJldmVudERlZmF1bHQ6IHRydWUsXG4gICAgICAgICAgICBjb21tYW5kOiAoKSA9PiB0aGlzLmhpZGUoKSxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiB0aGlzLmNsb3NlS2V5RGVzY3JpcHRpb24sXG4gICAgICAgICAgICBsYWJlbDogdGhpcy5jbG9zZUtleURlc2NyaXB0aW9uXG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIHRpdGxlIG9mIHRoZSBoZWxwIHNjcmVlblxuICAgICAqIEBkZWZhdWx0OiBcIktleWJvYXJkIHNob3J0Y3V0c1wiXG4gICAgICovXG4gICAgQElucHV0KCkgdGl0bGUgPSBcIktleWJvYXJkIHNob3J0Y3V0c1wiO1xuICAgIC8qKlxuICAgICAqIFdoYXQgbWVzc2FnZSB0byBzaG93IHdoZW4gbm8gc2hvcnRjdXRzIGFyZSBhdmFpbGFibGUgb24gdGhlIHBhZ2UuXG4gICAgICogQGRlZmF1bHQgXCJObyBzaG9ydGN1dHMgYXZhaWxhYmxlXCJcbiAgICAgKi9cbiAgICBASW5wdXQoKSBlbXB0eU1lc3NhZ2UgPSBcIk5vIHNob3J0Y3V0cyBhdmFpbGFibGVcIjtcbiAgICAvKipcbiAgICAgKiBAaWdub3JlXG4gICAgICovXG4gICAgQFZpZXdDaGlsZChUZW1wbGF0ZVJlZikgdGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XG4gICAgLyoqXG4gICAgICogQGlnbm9yZVxuICAgICAqL1xuICAgIHNob3J0Y3V0czogeyBsYWJlbDogc3RyaW5nOyBrZXk6IHN0cmluZyB8IHN0cmluZ1tdOyBkZXNjcmlwdGlvbjogc3RyaW5nIH1bXTtcbiAgICAvKipcbiAgICAgKiBAaWdub3JlXG4gICAgICovXG4gICAgc2hvd2luZyA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBpZ25vcmVcbiAgICAgKi9cbiAgICBsYWJlbHM6IHN0cmluZ1tdO1xuICAgIC8qKlxuICAgICAqIEBpZ25vcmVcbiAgICAgKi9cbiAgICBwcml2YXRlIGJvZHlQb3J0YWxIb3N0OiBEb21Qb3J0YWxPdXRsZXQ7XG4gICAgLyoqXG4gICAgICogQGlnbm9yZVxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcml2YXRlIGNvbXBvbmVudEZhY3RvcnlSZXNvbHZlcjogQ29tcG9uZW50RmFjdG9yeVJlc29sdmVyLFxuICAgICAgICBwcml2YXRlIGFwcFJlZjogQXBwbGljYXRpb25SZWYsXG4gICAgICAgIHByaXZhdGUga2V5Ym9hcmQ6IE5nSG90a2V5c1NlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgZWxlbWVudDogRWxlbWVudFJlZixcbiAgICAgICAgcHJpdmF0ZSBrZXlib2FyZEhlbHA6IE5nSG90a2V5c0hlbHBTZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIHZpZXdDb250YWluZXI6IFZpZXdDb250YWluZXJSZWYsXG4gICAgICAgIHByaXZhdGUgaW5qZWN0b3I6IEluamVjdG9yXG4gICAgKSB7XG4gICAgICAgIHRoaXMuYm9keVBvcnRhbEhvc3QgPSBuZXcgRG9tUG9ydGFsT3V0bGV0KFxuICAgICAgICAgICAgZG9jdW1lbnQuYm9keSxcbiAgICAgICAgICAgIHRoaXMuY29tcG9uZW50RmFjdG9yeVJlc29sdmVyLFxuICAgICAgICAgICAgdGhpcy5hcHBSZWYsXG4gICAgICAgICAgICB0aGlzLmluamVjdG9yXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV2ZWFsIHRoZSBoZWxwIHNjcmVlbiBtYW51YWxseS5cbiAgICAgKi9cbiAgICByZXZlYWwoKTogTmdIb3RrZXlzSGVscENvbXBvbmVudCB7XG4gICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICBpZiAodGhpcy5kaXNhYmxlU2Nyb2xsaW5nKSB7XG4gICAgICAgICAgICBkaXNhYmxlU2Nyb2xsKGAuJHt0aGlzLmNsYXNzTmFtZX1gKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwb3J0YWwgPSBuZXcgVGVtcGxhdGVQb3J0YWwodGhpcy50ZW1wbGF0ZSwgdGhpcy52aWV3Q29udGFpbmVyKTtcbiAgICAgICAgdGhpcy5ib2R5UG9ydGFsSG9zdC5hdHRhY2gocG9ydGFsKTtcbiAgICAgICAgdGhpcy5zaG93aW5nID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgaGVscCBzY3JlZW4gaXMgdmlzaWJsZS5cbiAgICAgKiBAcmV0dXJucyBib29sZWFuXG4gICAgICovXG4gICAgdmlzaWJsZSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYm9keVBvcnRhbEhvc3QuaGFzQXR0YWNoZWQoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSGlkZSB0aGUgaGVscCBzY3JlZW4gbWFudWFsbHkuXG4gICAgICovXG4gICAgaGlkZSgpOiBOZ0hvdGtleXNIZWxwQ29tcG9uZW50IHtcbiAgICAgICAgaWYgKHRoaXMuZGlzYWJsZVNjcm9sbGluZykge1xuICAgICAgICAgICAgZW5hYmxlU2Nyb2xsKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmJvZHlQb3J0YWxIb3N0Lmhhc0F0dGFjaGVkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYm9keVBvcnRhbEhvc3QuZGV0YWNoKCk7XG4gICAgICAgIHRoaXMuc2hvd2luZyA9IGZhbHNlO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAaWdub3JlXG4gICAgICovXG4gICAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgICBpZiAodGhpcy5jbGVhcklkcykge1xuICAgICAgICAgICAgdGhpcy5rZXlib2FyZC5yZW1vdmUodGhpcy5jbGVhcklkcyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuY2xvc2VLZXlJZHMpIHtcbiAgICAgICAgICAgIHRoaXMua2V5Ym9hcmQucmVtb3ZlKHRoaXMuY2xvc2VLZXlJZHMpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnN1YnNjcmlwdGlvbikge1xuICAgICAgICAgICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy50aW1lb3V0SWQpIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnRpbWVvdXRJZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTaG93L0hpZGUgdGhlIGhlbHAgc2NyZWVuIG1hbnVhbGx5LlxuICAgICAqL1xuICAgIHRvZ2dsZSgpOiBOZ0hvdGtleXNIZWxwQ29tcG9uZW50IHtcbiAgICAgICAgdGhpcy52aXNpYmxlKCkgPyB0aGlzLmhpZGUoKSA6IHRoaXMucmV2ZWFsKCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBpZ25vcmVcbiAgICAgKi9cbiAgICBwcml2YXRlIHN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uTGlrZTtcbiAgICAvKipcbiAgICAgKiBAaWdub3JlXG4gICAgICovXG4gICAgcHJpdmF0ZSBjbGVhcklkcztcblxuICAgIC8qKlxuICAgICAqIEBpZ25vcmVcbiAgICAgKi9cbiAgICBwcml2YXRlIGNsb3NlS2V5SWRzO1xuICAgIC8qKlxuICAgICAqIEBpZ25vcmVcbiAgICAgKi9cbiAgICBwcml2YXRlIHRpbWVvdXRJZDtcbiAgICAvKipcbiAgICAgKiBAaWdub3JlXG4gICAgICovXG4gICAgbmdPbkluaXQoKSB7XG4gICAgICAgIHRoaXMuc3Vic2NyaXB0aW9uID0gdGhpcy5rZXlib2FyZEhlbHAuc2hvcnRjdXRzJFxuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKSxcbiAgICAgICAgICAgICAgICBtYXAoc2hvcnRjdXRzID0+IGdyb3VwQnkoc2hvcnRjdXRzLCBcImxhYmVsXCIpKVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLnN1YnNjcmliZShzaG9ydGN1dHMgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvcnRjdXRzID0gc2hvcnRjdXRzO1xuICAgICAgICAgICAgICAgIHRoaXMubGFiZWxzID0gT2JqZWN0LmtleXMoc2hvcnRjdXRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cbn1cbiIsIjxuZy10ZW1wbGF0ZT5cbiAgICA8ZGl2IGNsYXNzPVwiaGVscC1tb2RhbF9fY29udGFpbmVyXCIgW2F0dHIuYXJpYS1sYWJlbGxlZGJ5XT1cIidtb2RhbC0nICsgdGl0bGVcIiByb2xlPVwiZGlhbG9nXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJ7e2NsYXNzTmFtZX19XCIgW0BlbnRlckFuaW1hdGlvbl0gKm5nSWY9XCJzaG93aW5nXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGl0bGVcIj5cbiAgICAgICAgICAgICAgICA8aDMgaWQ9XCJtb2RhbC17e3RpdGxlfX1cIiBjbGFzcz1cInRpdGxlX190ZXh0XCI+e3t0aXRsZX19PC9oMz5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImhlbHAtbW9kYWxfX2JvZHlcIj5cbiAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cIiFsYWJlbHMubGVuZ3RoXCI+XG4gICAgICAgICAgICAgICAgICAgIHt7ZW1wdHlNZXNzYWdlfX1cbiAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgPHVsICpuZ0Zvcj1cImxldCBsYWJlbCBvZiBsYWJlbHNcIiBjbGFzcz1cImhlbHAtbW9kYWxfX2xpc3RcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxoNCBjbGFzcz1cIml0ZW0tZ3JvdXAtbGFiZWxcIj57e2xhYmVsfX08L2g0PlxuICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWhvdC1rZXlzLWhlbHAtaXRlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgc2hvcnRjdXQgb2Ygc2hvcnRjdXRzW2xhYmVsXTsgbGV0IGkgPSBpbmRleFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzaG9ydGN1dF09XCJzaG9ydGN1dFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtpbmRleF09XCJpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgID48L25nLWhvdC1rZXlzLWhlbHAtaXRlbT5cbiAgICAgICAgICAgICAgICAgICAgPC91bD5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImhlbHAtbW9kYWxfX2JhY2tkcm9wXCIgW0BvdmVybGF5QW5pbWF0aW9uXSAobW91c2Vkb3duKT1cImhpZGUoKVwiICpuZ0lmPVwic2hvd2luZ1wiPjwvZGl2PlxuICAgIDwvZGl2PlxuPC9uZy10ZW1wbGF0ZT5cbiJdfQ==