angular-mentions
Version:
Angular mentions for text fields.
349 lines • 49.8 kB
JavaScript
import { Directive } from "@angular/core";
import { EventEmitter, Input, Output } from "@angular/core";
import { getCaretPosition, getValue, insertValue, setCaretPosition } from './mention-utils';
import { MentionListComponent } from './mention-list.component';
import * as i0 from "@angular/core";
const KEY_BACKSPACE = 8;
const KEY_TAB = 9;
const KEY_ENTER = 13;
const KEY_SHIFT = 16;
const KEY_ESCAPE = 27;
const KEY_SPACE = 32;
const KEY_LEFT = 37;
const KEY_UP = 38;
const KEY_RIGHT = 39;
const KEY_DOWN = 40;
const KEY_BUFFERED = 229;
/**
* Angular Mentions.
* https://github.com/dmacfarlane/angular-mentions
*
* Copyright (c) 2017 Dan MacFarlane
*/
export class MentionDirective {
constructor(_element, _componentResolver, _viewContainerRef) {
this._element = _element;
this._componentResolver = _componentResolver;
this._viewContainerRef = _viewContainerRef;
// the provided configuration object
this.mentionConfig = { items: [] };
this.DEFAULT_CONFIG = {
items: [],
triggerChar: '@',
labelKey: 'label',
maxItems: -1,
allowSpace: false,
returnTrigger: false,
mentionSelect: (item, triggerChar) => {
return this.activeConfig.triggerChar + item[this.activeConfig.labelKey];
},
mentionFilter: (searchString, items) => {
const searchStringLowerCase = searchString.toLowerCase();
return items.filter(e => e[this.activeConfig.labelKey].toLowerCase().startsWith(searchStringLowerCase));
}
};
// event emitted whenever the search term changes
this.searchTerm = new EventEmitter();
// event emitted when an item is selected
this.itemSelected = new EventEmitter();
// event emitted whenever the mention list is opened or closed
this.opened = new EventEmitter();
this.closed = new EventEmitter();
this.triggerChars = {};
}
set mention(items) {
this.mentionItems = items;
}
ngOnChanges(changes) {
// console.log('config change', changes);
if (changes['mention'] || changes['mentionConfig']) {
this.updateConfig();
}
}
updateConfig() {
let config = this.mentionConfig;
this.triggerChars = {};
// use items from directive if they have been set
if (this.mentionItems) {
config.items = this.mentionItems;
}
this.addConfig(config);
// nested configs
if (config.mentions) {
config.mentions.forEach(config => this.addConfig(config));
}
}
// add configuration for a trigger char
addConfig(config) {
// defaults
let defaults = Object.assign({}, this.DEFAULT_CONFIG);
config = Object.assign(defaults, config);
// items
let items = config.items;
if (items && items.length > 0) {
// convert strings to objects
if (typeof items[0] == 'string') {
items = items.map((label) => {
let object = {};
object[config.labelKey] = label;
return object;
});
}
if (config.labelKey) {
// remove items without an labelKey (as it's required to filter the list)
items = items.filter(e => e[config.labelKey]);
if (!config.disableSort) {
items.sort((a, b) => a[config.labelKey].localeCompare(b[config.labelKey]));
}
}
}
config.items = items;
// add the config
this.triggerChars[config.triggerChar] = config;
// for async update while menu/search is active
if (this.activeConfig && this.activeConfig.triggerChar == config.triggerChar) {
this.activeConfig = config;
this.updateSearchList();
}
}
setIframe(iframe) {
this.iframe = iframe;
}
stopEvent(event) {
//if (event instanceof KeyboardEvent) { // does not work for iframe
if (!event.wasClick) {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
}
}
blurHandler(event) {
this.stopEvent(event);
this.stopSearch();
}
inputHandler(event, nativeElement = this._element.nativeElement) {
if (this.lastKeyCode === KEY_BUFFERED && event.data) {
let keyCode = event.data.charCodeAt(0);
this.keyHandler({ keyCode, inputEvent: true }, nativeElement);
}
}
// @param nativeElement is the alternative text element in an iframe scenario
keyHandler(event, nativeElement = this._element.nativeElement) {
this.lastKeyCode = event.keyCode;
if (event.isComposing || event.keyCode === KEY_BUFFERED) {
return;
}
let val = getValue(nativeElement);
let pos = getCaretPosition(nativeElement, this.iframe);
let charPressed = event.key;
if (!charPressed) {
let charCode = event.which || event.keyCode;
if (!event.shiftKey && (charCode >= 65 && charCode <= 90)) {
charPressed = String.fromCharCode(charCode + 32);
}
// else if (event.shiftKey && charCode === KEY_2) {
// charPressed = this.config.triggerChar;
// }
else {
// TODO (dmacfarlane) fix this for non-alpha keys
// http://stackoverflow.com/questions/2220196/how-to-decode-character-pressed-from-jquerys-keydowns-event-handler?lq=1
charPressed = String.fromCharCode(event.which || event.keyCode);
}
}
if (event.keyCode == KEY_ENTER && event.wasClick && pos < this.startPos) {
// put caret back in position prior to contenteditable menu click
pos = this.startNode.length;
setCaretPosition(this.startNode, pos, this.iframe);
}
//console.log("keyHandler", this.startPos, pos, val, charPressed, event);
let config = this.triggerChars[charPressed];
if (config) {
this.activeConfig = config;
this.startPos = event.inputEvent ? pos - 1 : pos;
this.startNode = (this.iframe ? this.iframe.contentWindow.getSelection() : window.getSelection()).anchorNode;
this.searching = true;
this.searchString = null;
this.showSearchList(nativeElement);
this.updateSearchList();
if (config.returnTrigger) {
this.searchTerm.emit(config.triggerChar);
}
}
else if (this.startPos >= 0 && this.searching) {
if (pos <= this.startPos) {
this.searchList.hidden = true;
}
// ignore shift when pressed alone, but not when used with another key
else if (event.keyCode !== KEY_SHIFT &&
!event.metaKey &&
!event.altKey &&
!event.ctrlKey &&
pos > this.startPos) {
if (!this.activeConfig.allowSpace && event.keyCode === KEY_SPACE) {
this.startPos = -1;
}
else if (event.keyCode === KEY_BACKSPACE && pos > 0) {
pos--;
if (pos == this.startPos) {
this.stopSearch();
}
}
else if (this.searchList.hidden) {
if (event.keyCode === KEY_TAB || event.keyCode === KEY_ENTER) {
this.stopSearch();
return;
}
}
else if (!this.searchList.hidden) {
if (event.keyCode === KEY_TAB || event.keyCode === KEY_ENTER) {
this.stopEvent(event);
// emit the selected list item
this.itemSelected.emit(this.searchList.activeItem);
// optional function to format the selected item before inserting the text
const text = this.activeConfig.mentionSelect(this.searchList.activeItem, this.activeConfig.triggerChar);
// value is inserted without a trailing space for consistency
// between element types (div and iframe do not preserve the space)
insertValue(nativeElement, this.startPos, pos, text, this.iframe);
// fire input event so angular bindings are updated
if ("createEvent" in document) {
let evt = document.createEvent("HTMLEvents");
if (this.iframe) {
// a 'change' event is required to trigger tinymce updates
evt.initEvent("change", true, false);
}
else {
evt.initEvent("input", true, false);
}
// this seems backwards, but fire the event from this elements nativeElement (not the
// one provided that may be in an iframe, as it won't be propogate)
this._element.nativeElement.dispatchEvent(evt);
}
this.startPos = -1;
this.stopSearch();
return false;
}
else if (event.keyCode === KEY_ESCAPE) {
this.stopEvent(event);
this.stopSearch();
return false;
}
else if (event.keyCode === KEY_DOWN) {
this.stopEvent(event);
this.searchList.activateNextItem();
return false;
}
else if (event.keyCode === KEY_UP) {
this.stopEvent(event);
this.searchList.activatePreviousItem();
return false;
}
}
if (charPressed.length != 1 && event.keyCode != KEY_BACKSPACE) {
this.stopEvent(event);
return false;
}
else if (this.searching) {
let mention = val.substring(this.startPos + 1, pos);
if (event.keyCode !== KEY_BACKSPACE && !event.inputEvent) {
mention += charPressed;
}
this.searchString = mention;
if (this.activeConfig.returnTrigger) {
const triggerChar = (this.searchString || event.keyCode === KEY_BACKSPACE) ? val.substring(this.startPos, this.startPos + 1) : '';
this.searchTerm.emit(triggerChar + this.searchString);
}
else {
this.searchTerm.emit(this.searchString);
}
this.updateSearchList();
}
}
}
}
// exposed for external calls to open the mention list, e.g. by clicking a button
startSearch(triggerChar, nativeElement = this._element.nativeElement) {
triggerChar = triggerChar || this.mentionConfig.triggerChar || this.DEFAULT_CONFIG.triggerChar;
const pos = getCaretPosition(nativeElement, this.iframe);
insertValue(nativeElement, pos, pos, triggerChar, this.iframe);
this.keyHandler({ key: triggerChar, inputEvent: true }, nativeElement);
}
stopSearch() {
if (this.searchList && !this.searchList.hidden) {
this.searchList.hidden = true;
this.closed.emit();
}
this.activeConfig = null;
this.searching = false;
}
updateSearchList() {
let matches = [];
if (this.activeConfig && this.activeConfig.items) {
let objects = this.activeConfig.items;
// disabling the search relies on the async operation to do the filtering
if (!this.activeConfig.disableSearch && this.searchString && this.activeConfig.labelKey) {
if (this.activeConfig.mentionFilter) {
objects = this.activeConfig.mentionFilter(this.searchString, objects);
}
}
matches = objects;
if (this.activeConfig.maxItems > 0) {
matches = matches.slice(0, this.activeConfig.maxItems);
}
}
// update the search list
if (this.searchList) {
this.searchList.items = matches;
this.searchList.hidden = matches.length == 0;
}
}
showSearchList(nativeElement) {
this.opened.emit();
if (this.searchList == null) {
let componentFactory = this._componentResolver.resolveComponentFactory(MentionListComponent);
let componentRef = this._viewContainerRef.createComponent(componentFactory);
this.searchList = componentRef.instance;
this.searchList.itemTemplate = this.mentionListTemplate;
componentRef.instance['itemClick'].subscribe(() => {
nativeElement.focus();
let fakeKeydown = { key: 'Enter', keyCode: KEY_ENTER, wasClick: true };
this.keyHandler(fakeKeydown, nativeElement);
});
}
this.searchList.labelKey = this.activeConfig.labelKey;
this.searchList.dropUp = this.activeConfig.dropUp;
this.searchList.styleOff = this.mentionConfig.disableStyle;
this.searchList.activeIndex = 0;
this.searchList.position(nativeElement, this.iframe);
window.requestAnimationFrame(() => this.searchList.reset());
}
}
MentionDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: MentionDirective, deps: [{ token: i0.ElementRef }, { token: i0.ComponentFactoryResolver }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive });
MentionDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.6", type: MentionDirective, selector: "[mention], [mentionConfig]", inputs: { mention: "mention", mentionConfig: "mentionConfig", mentionListTemplate: "mentionListTemplate" }, outputs: { searchTerm: "searchTerm", itemSelected: "itemSelected", opened: "opened", closed: "closed" }, host: { attributes: { "autocomplete": "off" }, listeners: { "keydown": "keyHandler($event)", "input": "inputHandler($event)", "blur": "blurHandler($event)" } }, usesOnChanges: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: MentionDirective, decorators: [{
type: Directive,
args: [{
selector: '[mention], [mentionConfig]',
host: {
'(keydown)': 'keyHandler($event)',
'(input)': 'inputHandler($event)',
'(blur)': 'blurHandler($event)',
'autocomplete': 'off'
}
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ComponentFactoryResolver }, { type: i0.ViewContainerRef }]; }, propDecorators: { mention: [{
type: Input,
args: ['mention']
}], mentionConfig: [{
type: Input
}], mentionListTemplate: [{
type: Input
}], searchTerm: [{
type: Output
}], itemSelected: [{
type: Output
}], opened: [{
type: Output
}], closed: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVudGlvbi5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLW1lbnRpb25zL3NyYy9saWIvbWVudGlvbi5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUE0QixTQUFTLEVBQTZDLE1BQU0sZUFBZSxDQUFDO0FBQy9HLE9BQU8sRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFhLE1BQU0sRUFBaUIsTUFBTSxlQUFlLENBQUM7QUFDdEYsT0FBTyxFQUFFLGdCQUFnQixFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUc1RixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7QUFFaEUsTUFBTSxhQUFhLEdBQUcsQ0FBQyxDQUFDO0FBQ3hCLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQztBQUNsQixNQUFNLFNBQVMsR0FBRyxFQUFFLENBQUM7QUFDckIsTUFBTSxTQUFTLEdBQUcsRUFBRSxDQUFDO0FBQ3JCLE1BQU0sVUFBVSxHQUFHLEVBQUUsQ0FBQztBQUN0QixNQUFNLFNBQVMsR0FBRyxFQUFFLENBQUM7QUFDckIsTUFBTSxRQUFRLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQztBQUNsQixNQUFNLFNBQVMsR0FBRyxFQUFFLENBQUM7QUFDckIsTUFBTSxRQUFRLEdBQUcsRUFBRSxDQUFDO0FBQ3BCLE1BQU0sWUFBWSxHQUFHLEdBQUcsQ0FBQztBQUV6Qjs7Ozs7R0FLRztBQVVILE1BQU0sT0FBTyxnQkFBZ0I7SUFxRDNCLFlBQ1UsUUFBb0IsRUFDcEIsa0JBQTRDLEVBQzVDLGlCQUFtQztRQUZuQyxhQUFRLEdBQVIsUUFBUSxDQUFZO1FBQ3BCLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBMEI7UUFDNUMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFr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QyxDQUFDLENBQUM7U0FDSjtRQUNELElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDO1FBQ3RELElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDO1FBQ2xELElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDO1FBQzNELElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQztRQUNoQyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3JELE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDOUQsQ0FBQzs7NkdBcFZVLGdCQUFnQjtpR0FBaEIsZ0JBQWdCOzJGQUFoQixnQkFBZ0I7a0JBVDVCLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLDRCQUE0QjtvQkFDdEMsSUFBSSxFQUFFO3dCQUNKLFdBQVcsRUFBRSxvQkFBb0I7d0JBQ2pDLFNBQVMsRUFBRSxzQkFBc0I7d0JBQ2pDLFFBQVEsRUFBRSxxQkFBcUI7d0JBQy9CLGNBQWMsRUFBRSxLQUFLO3FCQUN0QjtpQkFDRjt1S0FNdUIsT0FBTztzQkFBNUIsS0FBSzt1QkFBQyxTQUFTO2dCQUtQLGFBQWE7c0JBQXJCLEtBQUs7Z0JBcUJHLG1CQUFtQjtzQkFBM0IsS0FBSztnQkFHSSxVQUFVO3NCQUFuQixNQUFNO2dCQUdHLFlBQVk7c0JBQXJCLE1BQU07Z0JBR0csTUFBTTtzQkFBZixNQUFNO2dCQUNHLE1BQU07c0JBQWYsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudEZhY3RvcnlSZXNvbHZlciwgRGlyZWN0aXZlLCBFbGVtZW50UmVmLCBUZW1wbGF0ZVJlZiwgVmlld0NvbnRhaW5lclJlZiB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBFdmVudEVtaXR0ZXIsIElucHV0LCBPbkNoYW5nZXMsIE91dHB1dCwgU2ltcGxlQ2hhbmdlcyB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBnZXRDYXJldFBvc2l0aW9uLCBnZXRWYWx1ZSwgaW5zZXJ0VmFsdWUsIHNldENhcmV0UG9zaXRpb24gfSBmcm9tICcuL21lbnRpb24tdXRpbHMnO1xuXG5pbXBvcnQgeyBNZW50aW9uQ29uZmlnIH0gZnJvbSBcIi4vbWVudGlvbi1jb25maWdcIjtcbmltcG9ydCB7IE1lbnRpb25MaXN0Q29tcG9uZW50IH0gZnJvbSAnLi9tZW50aW9uLWxpc3QuY29tcG9uZW50JztcblxuY29uc3QgS0VZX0JBQ0tTUEFDRSA9IDg7XG5jb25zdCBLRVlfVEFCID0gOTtcbmNvbnN0IEtFWV9FTlRFUiA9IDEzO1xuY29uc3QgS0VZX1NISUZUID0gMTY7XG5jb25zdCBLRVlfRVNDQVBFID0gMjc7XG5jb25zdCBLRVlfU1BBQ0UgPSAzMjtcbmNvbnN0IEtFWV9MRUZUID0gMzc7XG5jb25zdCBLRVlfVVAgPSAzODtcbmNvbnN0IEtFWV9SSUdIVCA9IDM5O1xuY29uc3QgS0VZX0RPV04gPSA0MDtcbmNvbnN0IEtFWV9CVUZGRVJFRCA9IDIyOTtcblxuLyoqXG4gKiBBbmd1bGFyIE1lbnRpb25zLlxuICogaHR0cHM6Ly9naXRodWIuY29tL2RtYWNmYXJsYW5lL2FuZ3VsYXItbWVudGlvbnNcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTcgRGFuIE1hY0ZhcmxhbmVcbiAqL1xuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW21lbnRpb25dLCBbbWVudGlvbkNvbmZpZ10nLFxuICBob3N0OiB7XG4gICAgJyhrZXlkb3duKSc6ICdrZXlIYW5kbGVyKCRldmVudCknLFxuICAgICcoaW5wdXQpJzogJ2lucHV0SGFuZGxlcigkZXZlbnQpJyxcbiAgICAnKGJsdXIpJzogJ2JsdXJIYW5kbGVyKCRldmVudCknLFxuICAgICdhdXRvY29tcGxldGUnOiAnb2ZmJ1xuICB9XG59KVxuZXhwb3J0IGNsYXNzIE1lbnRpb25EaXJlY3RpdmUgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xuXG4gIC8vIHN0b3JlcyB0aGUgaXRlbXMgcGFzc2VkIHRvIHRoZSBtZW50aW9ucyBkaXJlY3RpdmUgYW5kIHVzZWQgdG8gcG9wdWxhdGUgdGhlIHJvb3QgaXRlbXMgaW4gbWVudGlvbkNvbmZpZ1xuICBwcml2YXRlIG1lbnRpb25JdGVtczogYW55W107XG5cbiAgQElucHV0KCdtZW50aW9uJykgc2V0IG1lbnRpb24oaXRlbXM6IGFueVtdKSB7XG4gICAgdGhpcy5tZW50aW9uSXRlbXMgPSBpdGVtcztcbiAgfVxuXG4gIC8vIHRoZSBwcm92aWRlZCBjb25maWd1cmF0aW9uIG9iamVjdFxuICBASW5wdXQoKSBtZW50aW9uQ29uZmlnOiBNZW50aW9uQ29uZmlnID0geyBpdGVtczogW10gfTtcblxuICBwcml2YXRlIGFjdGl2ZUNvbmZpZzogTWVudGlvbkNvbmZpZztcblxuICBwcml2YXRlIERFRkFVTFRfQ09ORklHOiBNZW50aW9uQ29uZmlnID0ge1xuICAgIGl0ZW1zOiBbXSxcbiAgICB0cmlnZ2VyQ2hhcjogJ0AnLFxuICAgIGxhYmVsS2V5OiAnbGFiZWwnLFxuICAgIG1heEl0ZW1zOiAtMSxcbiAgICBhbGxvd1NwYWNlOiBmYWxzZSxcbiAgICByZXR1cm5UcmlnZ2VyOiBmYWxzZSxcbiAgICBtZW50aW9uU2VsZWN0OiAoaXRlbTogYW55LCB0cmlnZ2VyQ2hhcj86IHN0cmluZykgPT4ge1xuICAgICAgcmV0dXJuIHRoaXMuYWN0aXZlQ29uZmlnLnRyaWdnZXJDaGFyICsgaXRlbVt0aGlzLmFjdGl2ZUNvbmZpZy5sYWJlbEtleV07XG4gICAgfSxcbiAgICBtZW50aW9uRmlsdGVyOiAoc2VhcmNoU3RyaW5nOiBzdHJpbmcsIGl0ZW1zOiBhbnlbXSkgPT4ge1xuICAgICAgY29uc3Qgc2VhcmNoU3RyaW5nTG93ZXJDYXNlID0gc2VhcmNoU3RyaW5nLnRvTG93ZXJDYXNlKCk7XG4gICAgICByZXR1cm4gaXRlbXMuZmlsdGVyKGUgPT4gZVt0aGlzLmFjdGl2ZUNvbmZpZy5sYWJlbEtleV0udG9Mb3dlckNhc2UoKS5zdGFydHNXaXRoKHNlYXJjaFN0cmluZ0xvd2VyQ2FzZSkpO1xuICAgIH1cbiAgfVxuXG4gIC8vIHRlbXBsYXRlIHRvIHVzZSBmb3IgcmVuZGVyaW5nIGxpc3QgaXRlbXNcbiAgQElucHV0KCkgbWVudGlvbkxpc3RUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcblxuICAvLyBldmVudCBlbWl0dGVkIHdoZW5ldmVyIHRoZSBzZWFyY2ggdGVybSBjaGFuZ2VzXG4gIEBPdXRwdXQoKSBzZWFyY2hUZXJtID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG5cbiAgLy8gZXZlbnQgZW1pdHRlZCB3aGVuIGFuIGl0ZW0gaXMgc2VsZWN0ZWRcbiAgQE91dHB1dCgpIGl0ZW1TZWxlY3RlZCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gIC8vIGV2ZW50IGVtaXR0ZWQgd2hlbmV2ZXIgdGhlIG1lbnRpb24gbGlzdCBpcyBvcGVuZWQgb3IgY2xvc2VkXG4gIEBPdXRwdXQoKSBvcGVuZWQgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBjbG9zZWQgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgcHJpdmF0ZSB0cmlnZ2VyQ2hhcnM6IHsgW2tleTogc3RyaW5nXTogTWVudGlvbkNvbmZpZyB9ID0ge307XG5cbiAgcHJpdmF0ZSBzZWFyY2hTdHJpbmc6IHN0cmluZztcbiAgcHJpdmF0ZSBzdGFydFBvczogbnVtYmVyO1xuICBwcml2YXRlIHN0YXJ0Tm9kZTtcbiAgcHJpdmF0ZSBzZWFyY2hMaXN0OiBNZW50aW9uTGlzdENvbXBvbmVudDtcbiAgcHJpdmF0ZSBzZWFyY2hpbmc6IGJvb2xlYW47XG4gIHByaXZhdGUgaWZyYW1lOiBhbnk7IC8vIG9wdGlvbmFsXG4gIHByaXZhdGUgbGFzdEtleUNvZGU6IG51bWJlcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9lbGVtZW50OiBFbGVtZW50UmVmLFxuICAgIHByaXZhdGUgX2NvbXBvbmVudFJlc29sdmVyOiBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsXG4gICAgcHJpdmF0ZSBfdmlld0NvbnRhaW5lclJlZjogVmlld0NvbnRhaW5lclJlZlxuICApIHsgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICAvLyBjb25zb2xlLmxvZygnY29uZmlnIGNoYW5nZScsIGNoYW5nZXMpO1xuICAgIGlmIChjaGFuZ2VzWydtZW50aW9uJ10gfHwgY2hhbmdlc1snbWVudGlvbkNvbmZpZyddKSB7XG4gICAgICB0aGlzLnVwZGF0ZUNvbmZpZygpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyB1cGRhdGVDb25maWcoKSB7XG4gICAgbGV0IGNvbmZpZyA9IHRoaXMubWVudGlvbkNvbmZpZztcbiAgICB0aGlzLnRyaWdnZXJDaGFycyA9IHt9O1xuICAgIC8vIHVzZSBpdGVtcyBmcm9tIGRpcmVjdGl2ZSBpZiB0aGV5IGhhdmUgYmVlbiBzZXRcbiAgICBpZiAodGhpcy5tZW50aW9uSXRlbXMpIHtcbiAgICAgIGNvbmZpZy5pdGVtcyA9IHRoaXMubWVudGlvbkl0ZW1zO1xuICAgIH1cbiAgICB0aGlzLmFkZENvbmZpZyhjb25maWcpO1xuICAgIC8vIG5lc3RlZCBjb25maWdzXG4gICAgaWYgKGNvbmZpZy5tZW50aW9ucykge1xuICAgICAgY29uZmlnLm1lbnRpb25zLmZvckVhY2goY29uZmlnID0+IHRoaXMuYWRkQ29uZmlnKGNvbmZpZykpO1xuICAgIH1cbiAgfVxuXG4gIC8vIGFkZCBjb25maWd1cmF0aW9uIGZvciBhIHRyaWdnZXIgY2hhclxuICBwcml2YXRlIGFkZENvbmZpZyhjb25maWc6IE1lbnRpb25Db25maWcpIHtcbiAgICAvLyBkZWZhdWx0c1xuICAgIGxldCBkZWZhdWx0cyA9IE9iamVjdC5hc3NpZ24oe30sIHRoaXMuREVGQVVMVF9DT05GSUcpO1xuICAgIGNvbmZpZyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIGNvbmZpZyk7XG4gICAgLy8gaXRlbXNcbiAgICBsZXQgaXRlbXMgPSBjb25maWcuaXRlbXM7XG4gICAgaWYgKGl0ZW1zICYmIGl0ZW1zLmxlbmd0aCA+IDApIHtcbiAgICAgIC8vIGNvbnZlcnQgc3RyaW5ncyB0byBvYmplY3RzXG4gICAgICBpZiAodHlwZW9mIGl0ZW1zWzBdID09ICdzdHJpbmcnKSB7XG4gICAgICAgIGl0ZW1zID0gaXRlbXMubWFwKChsYWJlbCkgPT4ge1xuICAgICAgICAgIGxldCBvYmplY3QgPSB7fTtcbiAgICAgICAgICBvYmplY3RbY29uZmlnLmxhYmVsS2V5XSA9IGxhYmVsO1xuICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgaWYgKGNvbmZpZy5sYWJlbEtleSkge1xuICAgICAgICAvLyByZW1vdmUgaXRlbXMgd2l0aG91dCBhbiBsYWJlbEtleSAoYXMgaXQncyByZXF1aXJlZCB0byBmaWx0ZXIgdGhlIGxpc3QpXG4gICAgICAgIGl0ZW1zID0gaXRlbXMuZmlsdGVyKGUgPT4gZVtjb25maWcubGFiZWxLZXldKTtcbiAgICAgICAgaWYgKCFjb25maWcuZGlzYWJsZVNvcnQpIHtcbiAgICAgICAgICBpdGVtcy5zb3J0KChhLCBiKSA9PiBhW2NvbmZpZy5sYWJlbEtleV0ubG9jYWxlQ29tcGFyZShiW2NvbmZpZy5sYWJlbEtleV0pKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBjb25maWcuaXRlbXMgPSBpdGVtcztcblxuICAgIC8vIGFkZCB0aGUgY29uZmlnXG4gICAgdGhpcy50cmlnZ2VyQ2hhcnNbY29uZmlnLnRyaWdnZXJDaGFyXSA9IGNvbmZpZztcblxuICAgIC8vIGZvciBhc3luYyB1cGRhdGUgd2hpbGUgbWVudS9zZWFyY2ggaXMgYWN0aXZlXG4gICAgaWYgKHRoaXMuYWN0aXZlQ29uZmlnICYmIHRoaXMuYWN0aXZlQ29uZmlnLnRyaWdnZXJDaGFyID09IGNvbmZpZy50cmlnZ2VyQ2hhcikge1xuICAgICAgdGhpcy5hY3RpdmVDb25maWcgPSBjb25maWc7XG4gICAgICB0aGlzLnVwZGF0ZVNlYXJjaExpc3QoKTtcbiAgICB9XG4gIH1cblxuICBzZXRJZnJhbWUoaWZyYW1lOiBIVE1MSUZyYW1lRWxlbWVudCkge1xuICAgIHRoaXMuaWZyYW1lID0gaWZyYW1lO1xuICB9XG5cbiAgc3RvcEV2ZW50KGV2ZW50OiBhbnkpIHtcbiAgICAvL2lmIChldmVudCBpbnN0YW5jZW9mIEtleWJvYXJkRXZlbnQpIHsgLy8gZG9lcyBub3Qgd29yayBmb3IgaWZyYW1lXG4gICAgaWYgKCFldmVudC53YXNDbGljaykge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgYmx1ckhhbmRsZXIoZXZlbnQ6IGFueSkge1xuICAgIHRoaXMuc3RvcEV2ZW50KGV2ZW50KTtcbiAgICB0aGlzLnN0b3BTZWFyY2goKTtcbiAgfVxuXG4gIGlucHV0SGFuZGxlcihldmVudDogYW55LCBuYXRpdmVFbGVtZW50OiBIVE1MSW5wdXRFbGVtZW50ID0gdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50KSB7XG4gICAgaWYgKHRoaXMubGFzdEtleUNvZGUgPT09IEtFWV9CVUZGRVJFRCAmJiBldmVudC5kYXRhKSB7XG4gICAgICBsZXQga2V5Q29kZSA9IGV2ZW50LmRhdGEuY2hhckNvZGVBdCgwKTtcbiAgICAgIHRoaXMua2V5SGFuZGxlcih7IGtleUNvZGUsIGlucHV0RXZlbnQ6IHRydWUgfSwgbmF0aXZlRWxlbWVudCk7XG4gICAgfVxuICB9XG5cbiAgLy8gQHBhcmFtIG5hdGl2ZUVsZW1lbnQgaXMgdGhlIGFsdGVybmF0aXZlIHRleHQgZWxlbWVudCBpbiBhbiBpZnJhbWUgc2NlbmFyaW9cbiAga2V5SGFuZGxlcihldmVudDogYW55LCBuYXRpdmVFbGVtZW50OiBIVE1MSW5wdXRFbGVtZW50ID0gdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50KSB7XG4gICAgdGhpcy5sYXN0S2V5Q29kZSA9IGV2ZW50LmtleUNvZGU7XG5cbiAgICBpZiAoZXZlbnQuaXNDb21wb3NpbmcgfHwgZXZlbnQua2V5Q29kZSA9PT0gS0VZX0JVRkZFUkVEKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHZhbDogc3RyaW5nID0gZ2V0VmFsdWUobmF0aXZlRWxlbWVudCk7XG4gICAgbGV0IHBvcyA9IGdldENhcmV0UG9zaXRpb24obmF0aXZlRWxlbWVudCwgdGhpcy5pZnJhbWUpO1xuICAgIGxldCBjaGFyUHJlc3NlZCA9IGV2ZW50LmtleTtcbiAgICBpZiAoIWNoYXJQcmVzc2VkKSB7XG4gICAgICBsZXQgY2hhckNvZGUgPSBldmVudC53aGljaCB8fCBldmVudC5rZXlDb2RlO1xuICAgICAgaWYgKCFldmVudC5zaGlmdEtleSAmJiAoY2hhckNvZGUgPj0gNjUgJiYgY2hhckNvZGUgPD0gOTApKSB7XG4gICAgICAgIGNoYXJQcmVzc2VkID0gU3RyaW5nLmZyb21DaGFyQ29kZShjaGFyQ29kZSArIDMyKTtcbiAgICAgIH1cbiAgICAgIC8vIGVsc2UgaWYgKGV2ZW50LnNoaWZ0S2V5ICYmIGNoYXJDb2RlID09PSBLRVlfMikge1xuICAgICAgLy8gICBjaGFyUHJlc3NlZCA9IHRoaXMuY29uZmlnLnRyaWdnZXJDaGFyO1xuICAgICAgLy8gfVxuICAgICAgZWxzZSB7XG4gICAgICAgIC8vIFRPRE8gKGRtYWNmYXJsYW5lKSBmaXggdGhpcyBmb3Igbm9uLWFscGhhIGtleXNcbiAgICAgICAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMjIwMTk2L2hvdy10by1kZWNvZGUtY2hhcmFjdGVyLXByZXNzZWQtZnJvbS1qcXVlcnlzLWtleWRvd25zLWV2ZW50LWhhbmRsZXI/bHE9MVxuICAgICAgICBjaGFyUHJlc3NlZCA9IFN0cmluZy5mcm9tQ2hhckNvZGUoZXZlbnQud2hpY2ggfHwgZXZlbnQua2V5Q29kZSk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChldmVudC5rZXlDb2RlID09IEtFWV9FTlRFUiAmJiBldmVudC53YXNDbGljayAmJiBwb3MgPCB0aGlzLnN0YXJ0UG9zKSB7XG4gICAgICAvLyBwdXQgY2FyZXQgYmFjayBpbiBwb3NpdGlvbiBwcmlvciB0byBjb250ZW50ZWRpdGFibGUgbWVudSBjbGlja1xuICAgICAgcG9zID0gdGhpcy5zdGFydE5vZGUubGVuZ3RoO1xuICAgICAgc2V0Q2FyZXRQb3NpdGlvbih0aGlzLnN0YXJ0Tm9kZSwgcG9zLCB0aGlzLmlmcmFtZSk7XG4gICAgfVxuICAgIC8vY29uc29sZS5sb2coXCJrZXlIYW5kbGVyXCIsIHRoaXMuc3RhcnRQb3MsIHBvcywgdmFsLCBjaGFyUHJlc3NlZCwgZXZlbnQpO1xuXG4gICAgbGV0IGNvbmZpZyA9IHRoaXMudHJpZ2dlckNoYXJzW2NoYXJQcmVzc2VkXTtcbiAgICBpZiAoY29uZmlnKSB7XG4gICAgICB0aGlzLmFjdGl2ZUNvbmZpZyA9IGNvbmZpZztcbiAgICAgIHRoaXMuc3RhcnRQb3MgPSBldmVudC5pbnB1dEV2ZW50ID8gcG9zIC0gMSA6IHBvcztcbiAgICAgIHRoaXMuc3RhcnROb2RlID0gKHRoaXMuaWZyYW1lID8gdGhpcy5pZnJhbWUuY29udGVudFdpbmRvdy5nZXRTZWxlY3Rpb24oKSA6IHdpbmRvdy5nZXRTZWxlY3Rpb24oKSkuYW5jaG9yTm9kZTtcbiAgICAgIHRoaXMuc2VhcmNoaW5nID0gdHJ1ZTtcbiAgICAgIHRoaXMuc2VhcmNoU3RyaW5nID0gbnVsbDtcbiAgICAgIHRoaXMuc2hvd1NlYXJjaExpc3QobmF0aXZlRWxlbWVudCk7XG4gICAgICB0aGlzLnVwZGF0ZVNlYXJjaExpc3QoKTtcblxuICAgICAgaWYgKGNvbmZpZy5yZXR1cm5UcmlnZ2VyKSB7XG4gICAgICAgIHRoaXMuc2VhcmNoVGVybS5lbWl0KGNvbmZpZy50cmlnZ2VyQ2hhcik7XG4gICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKHRoaXMuc3RhcnRQb3MgPj0gMCAmJiB0aGlzLnNlYXJjaGluZykge1xuICAgICAgaWYgKHBvcyA8PSB0aGlzLnN0YXJ0UG9zKSB7XG4gICAgICAgIHRoaXMuc2VhcmNoTGlzdC5oaWRkZW4gPSB0cnVlO1xuICAgICAgfVxuICAgICAgLy8gaWdub3JlIHNoaWZ0IHdoZW4gcHJlc3NlZCBhbG9uZSwgYnV0IG5vdCB3aGVuIHVzZWQgd2l0aCBhbm90aGVyIGtleVxuICAgICAgZWxzZSBpZiAoZXZlbnQua2V5Q29kZSAhPT0gS0VZX1NISUZUICYmXG4gICAgICAgICFldmVudC5tZXRhS2V5ICYmXG4gICAgICAgICFldmVudC5hbHRLZXkgJiZcbiAgICAgICAgIWV2ZW50LmN0cmxLZXkgJiZcbiAgICAgICAgcG9zID4gdGhpcy5zdGFydFBvc1xuICAgICAgKSB7XG4gICAgICAgIGlmICghdGhpcy5hY3RpdmVDb25maWcuYWxsb3dTcGFjZSAmJiBldmVudC5rZXlDb2RlID09PSBLRVlfU1BBQ0UpIHtcbiAgICAgICAgICB0aGlzLnN0YXJ0UG9zID0gLTE7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZXZlbnQua2V5Q29kZSA9PT0gS0VZX0JBQ0tTUEFDRSAmJiBwb3MgPiAwKSB7XG4gICAgICAgICAgcG9zLS07XG4gICAgICAgICAgaWYgKHBvcyA9PSB0aGlzLnN0YXJ0UG9zKSB7XG4gICAgICAgICAgICB0aGlzLnN0b3BTZWFyY2goKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5zZWFyY2hMaXN0LmhpZGRlbikge1xuICAgICAgICAgIGlmIChldmVudC5rZXlDb2RlID09PSBLRVlfVEFCIHx8IGV2ZW50LmtleUNvZGUgPT09IEtFWV9FTlRFUikge1xuICAgICAgICAgICAgdGhpcy5zdG9wU2VhcmNoKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKCF0aGlzLnNlYXJjaExpc3QuaGlkZGVuKSB7XG4gICAgICAgICAgaWYgKGV2ZW50LmtleUNvZGUgPT09IEtFWV9UQUIgfHwgZXZlbnQua2V5Q29kZSA9PT0gS0VZX0VOVEVSKSB7XG4gICAgICAgICAgICB0aGlzLnN0b3BFdmVudChldmVudCk7XG4gICAgICAgICAgICAvLyBlbWl0IHRoZSBzZWxlY3RlZCBsaXN0IGl0ZW1cbiAgICAgICAgICAgIHRoaXMuaXRlbVNlbGVjdGVkLmVtaXQodGhpcy5zZWFyY2hMaXN0LmFjdGl2ZUl0ZW0pO1xuICAgICAgICAgICAgLy8gb3B0aW9uYWwgZnVuY3Rpb24gdG8gZm9ybWF0IHRoZSBzZWxlY3RlZCBpdGVtIGJlZm9yZSBpbnNlcnRpbmcgdGhlIHRleHRcbiAgICAgICAgICAgIGNvbnN0IHRleHQgPSB0aGlzLmFjdGl2ZUNvbmZpZy5tZW50aW9uU2VsZWN0KHRoaXMuc2VhcmNoTGlzdC5hY3RpdmVJdGVtLCB0aGlzLmFjdGl2ZUNvbmZpZy50cmlnZ2VyQ2hhcik7XG4gICAgICAgICAgICAvLyB2YWx1ZSBpcyBpbnNlcnRlZCB3aXRob3V0IGEgdHJhaWxpbmcgc3BhY2UgZm9yIGNvbnNpc3RlbmN5XG4gICAgICAgICAgICAvLyBiZXR3ZWVuIGVsZW1lbnQgdHlwZXMgKGRpdiBhbmQgaWZyYW1lIGRvIG5vdCBwcmVzZXJ2ZSB0aGUgc3BhY2UpXG4gICAgICAgICAgICBpbnNlcnRWYWx1ZShuYXRpdmVFbGVtZW50LCB0aGlzLnN0YXJ0UG9zLCBwb3MsIHRleHQsIHRoaXMuaWZyYW1lKTtcbiAgICAgICAgICAgIC8vIGZpcmUgaW5wdXQgZXZlbnQgc28gYW5ndWxhciBiaW5kaW5ncyBhcmUgdXBkYXRlZFxuICAgICAgICAgICAgaWYgKFwiY3JlYXRlRXZlbnRcIiBpbiBkb2N1bWVudCkge1xuICAgICAgICAgICAgICBsZXQgZXZ0ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoXCJIVE1MRXZlbnRzXCIpO1xuICAgICAgICAgICAgICBpZiAodGhpcy5pZnJhbWUpIHtcbiAgICAgICAgICAgICAgICAvLyBhICdjaGFuZ2UnIGV2ZW50IGlzIHJlcXVpcmVkIHRvIHRyaWdnZXIgdGlueW1jZSB1cGRhdGVzXG4gICAgICAgICAgICAgICAgZXZ0LmluaXRFdmVudChcImNoYW5nZVwiLCB0cnVlLCBmYWxzZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZXZ0LmluaXRFdmVudChcImlucHV0XCIsIHRydWUsIGZhbHNlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAvLyB0aGlzIHNlZW1zIGJhY2t3YXJkcywgYnV0IGZpcmUgdGhlIGV2ZW50IGZyb20gdGhpcyBlbGVtZW50cyBuYXRpdmVFbGVtZW50IChub3QgdGhlXG4gICAgICAgICAgICAgIC8vIG9uZSBwcm92aWRlZCB0aGF0IG1heSBiZSBpbiBhbiBpZnJhbWUsIGFzIGl0IHdvbid0IGJlIHByb3BvZ2F0ZSlcbiAgICAgICAgICAgICAgdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50LmRpc3BhdGNoRXZlbnQoZXZ0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc3RhcnRQb3MgPSAtMTtcbiAgICAgICAgICAgIHRoaXMuc3RvcFNlYXJjaCgpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmIChldmVudC5rZXlDb2RlID09PSBLRVlfRVNDQVBFKSB7XG4gICAgICAgICAgICB0aGlzLnN0b3BFdmVudChldmVudCk7XG4gICAgICAgICAgICB0aGlzLnN0b3BTZWFyY2goKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSBpZiAoZXZlbnQua2V5Q29kZSA9PT0gS0VZX0RPV04pIHtcbiAgICAgICAgICAgIHRoaXMuc3RvcEV2ZW50KGV2ZW50KTtcbiAgICAgICAgICAgIHRoaXMuc2VhcmNoTGlzdC5hY3RpdmF0ZU5leHRJdGVtKCk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2UgaWYgKGV2ZW50LmtleUNvZGUgPT09IEtFWV9VUCkge1xuICAgICAgICAgICAgdGhpcy5zdG9wRXZlbnQoZXZlbnQpO1xuICAgICAgICAgICAgdGhpcy5zZWFyY2hMaXN0LmFjdGl2YXRlUHJldmlvdXNJdGVtKCk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNoYXJQcmVzc2VkLmxlbmd0aCE9MSAmJiBldmVudC5rZXlDb2RlIT1LRVlfQkFDS1NQQUNFKSB7XG4gICAgICAgICAgdGhpcy5zdG9wRXZlbnQoZXZlbnQpO1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLnNlYXJjaGluZykge1xuICAgICAgICAgIGxldCBtZW50aW9uID0gdmFsLnN1YnN0cmluZyh0aGlzLnN0YXJ0UG9zICsgMSwgcG9zKTtcbiAgICAgICAgICBpZiAoZXZlbnQua2V5Q29kZSAhPT0gS0VZX0JBQ0tTUEFDRSAmJiAhZXZlbnQuaW5wdXRFdmVudCkge1xuICAgICAgICAgICAgbWVudGlvbiArPSBjaGFyUHJlc3NlZDtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5zZWFyY2hTdHJpbmcgPSBtZW50aW9uO1xuICAgICAgICAgIGlmICh0aGlzLmFjdGl2ZUNvbmZpZy5yZXR1cm5UcmlnZ2VyKSB7XG4gICAgICAgICAgICBjb25zdCB0cmlnZ2VyQ2hhciA9ICh0aGlzLnNlYXJjaFN0cmluZyB8fCBldmVudC5rZXlDb2RlID09PSBLRVlfQkFDS1NQQUNFKSA/IHZhbC5zdWJzdHJpbmcodGhpcy5zdGFydFBvcywgdGhpcy5zdGFydFBvcyArIDEpIDogJyc7XG4gICAgICAgICAgICB0aGlzLnNlYXJjaFRlcm0uZW1pdCh0cmlnZ2VyQ2hhciArIHRoaXMuc2VhcmNoU3RyaW5nKTtcbiAgICAgICAgICB9IFxuICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zZWFyY2hUZXJtLmVtaXQodGhpcy5zZWFyY2hTdHJpbmcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLnVwZGF0ZVNlYXJjaExpc3QoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIGV4cG9zZWQgZm9yIGV4dGVybmFsIGNhbGxzIHRvIG9wZW4gdGhlIG1lbnRpb24gbGlzdCwgZS5nLiBieSBjbGlja2luZyBhIGJ1dHRvblxuICBwdWJsaWMgc3RhcnRTZWFyY2godHJpZ2dlckNoYXI/OiBzdHJpbmcsIG5hdGl2ZUVsZW1lbnQ6IEhUTUxJbnB1dEVsZW1lbnQgPSB0aGlzLl9lbGVtZW50Lm5hdGl2ZUVsZW1lbnQpIHtcbiAgICB0cmlnZ2VyQ2hhciA9IHRyaWdnZXJDaGFyIHx8IHRoaXMubWVudGlvbkNvbmZpZy50cmlnZ2VyQ2hhciB8fCB0aGlzLkRFRkFVTFRfQ09ORklHLnRyaWdnZXJDaGFyO1xuICAgIGNvbnN0IHBvcyA9IGdldENhcmV0UG9zaXRpb24obmF0aXZlRWxlbWVudCwgdGhpcy5pZnJhbWUpO1xuICAgIGluc2VydFZhbHVlKG5hdGl2ZUVsZW1lbnQsIHBvcywgcG9zLCB0cmlnZ2VyQ2hhciwgdGhpcy5pZnJhbWUpO1xuICAgIHRoaXMua2V5SGFuZGxlcih7IGtleTogdHJpZ2dlckNoYXIsIGlucHV0RXZlbnQ6IHRydWUgfSwgbmF0aXZlRWxlbWVudCk7XG4gIH1cblxuICBzdG9wU2VhcmNoKCkge1xuICAgIGlmICh0aGlzLnNlYXJjaExpc3QgJiYgIXRoaXMuc2VhcmNoTGlzdC5oaWRkZW4pIHtcbiAgICAgIHRoaXMuc2VhcmNoTGlzdC5oaWRkZW4gPSB0cnVlO1xuICAgICAgdGhpcy5jbG9zZWQuZW1pdCgpO1xuICAgIH1cbiAgICB0aGlzLmFjdGl2ZUNvbmZpZyA9IG51bGw7XG4gICAgdGhpcy5zZWFyY2hpbmcgPSBmYWxzZTtcbiAgfVxuXG4gIHVwZGF0ZVNlYXJjaExpc3QoKSB7XG4gICAgbGV0IG1hdGNoZXM6IGFueVtdID0gW107XG4gICAgaWYgKHRoaXMuYWN0aXZlQ29uZmlnICYmIHRoaXMuYWN0aXZlQ29uZmlnLml0ZW1zKSB7XG4gICAgICBsZXQgb2JqZWN0cyA9IHRoaXMuYWN0aXZlQ29uZmlnLml0ZW1zO1xuICAgICAgLy8gZGlzYWJsaW5nIHRoZSBzZWFyY2ggcmVsaWVzIG9uIHRoZSBhc3luYyBvcGVyYXRpb24gdG8gZG8gdGhlIGZpbHRlcmluZ1xuICAgICAgaWYgKCF0aGlzLmFjdGl2ZUNvbmZpZy5kaXNhYmxlU2VhcmNoICYmIHRoaXMuc2VhcmNoU3RyaW5nICYmIHRoaXMuYWN0aXZlQ29uZmlnLmxhYmVsS2V5KSB7XG4gICAgICAgIGlmICh0aGlzLmFjdGl2ZUNvbmZpZy5tZW50aW9uRmlsdGVyKSB7XG4gICAgICAgICAgb2JqZWN0cyA9IHRoaXMuYWN0aXZlQ29uZmlnLm1lbnRpb25GaWx0ZXIodGhpcy5zZWFyY2hTdHJpbmcsIG9iamVjdHMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBtYXRjaGVzID0gb2JqZWN0cztcbiAgICAgIGlmICh0aGlzLmFjdGl2ZUNvbmZpZy5tYXhJdGVtcyA+IDApIHtcbiAgICAgICAgbWF0Y2hlcyA9IG1hdGNoZXMuc2xpY2UoMCwgdGhpcy5hY3RpdmVDb25maWcubWF4SXRlbXMpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyB1cGRhdGUgdGhlIHNlYXJjaCBsaXN0XG4gICAgaWYgKHRoaXMuc2VhcmNoTGlzdCkge1xuICAgICAgdGhpcy5zZWFyY2hMaXN0Lml0ZW1zID0gbWF0Y2hlcztcbiAgICAgIHRoaXMuc2VhcmNoTGlzdC5oaWRkZW4gPSBtYXRjaGVzLmxlbmd0aCA9PSAwO1xuICAgIH1cbiAgfVxuXG4gIHNob3dTZWFyY2hMaXN0KG5hdGl2ZUVsZW1lbnQ6IEhUTUxJbnB1dEVsZW1lbnQpIHtcbiAgICB0aGlzLm9wZW5lZC5lbWl0KCk7XG5cbiAgICBpZiAodGhpcy5zZWFyY2hMaXN0ID09IG51bGwpIHtcbiAgICAgIGxldCBjb21wb25lbnRGYWN0b3J5ID0gdGhpcy5fY29tcG9uZW50UmVzb2x2ZXIucmVzb2x2ZUNvbXBvbmVudEZhY3RvcnkoTWVudGlvbkxpc3RDb21wb25lbnQpO1xuICAgICAgbGV0IGNvbXBvbmVudFJlZiA9IHRoaXMuX3ZpZXdDb250YWluZXJSZWYuY3JlYXRlQ29tcG9uZW50KGNvbXBvbmVudEZhY3RvcnkpO1xuICAgICAgdGhpcy5zZWFyY2hMaXN0ID0gY29tcG9uZW50UmVmLmluc3RhbmNlO1xuICAgICAgdGhpcy5zZWFyY2hMaXN0Lml0ZW1UZW1wbGF0ZSA9IHRoaXMubWVudGlvbkxpc3RUZW1wbGF0ZTtcbiAgICAgIGNvbXBvbmVudFJlZi5pbnN0YW5jZVsnaXRlbUNsaWNrJ10uc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgbmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICAgICAgICBsZXQgZmFrZUtleWRvd24gPSB7IGtleTogJ0VudGVyJywga2V5Q29kZTogS0VZX0VOVEVSLCB3YXNDbGljazogdHJ1ZSB9O1xuICAgICAgICB0aGlzLmtleUhhbmRsZXIoZmFrZUtleWRvd24sIG5hdGl2ZUVsZW1lbnQpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHRoaXMuc2VhcmNoTGlzdC5sYWJlbEtleSA9IHRoaXMuYWN0aXZlQ29uZmlnLmxhYmVsS2V5O1xuICAgIHRoaXMuc2VhcmNoTGlzdC5kcm9wVXAgPSB0aGlzLmFjdGl2ZUNvbmZpZy5kcm9wVXA7XG4gICAgdGhpcy5zZWFyY2hMaXN0LnN0eWxlT2ZmID0gdGhpcy5tZW50aW9uQ29uZmlnLmRpc2FibGVTdHlsZTtcbiAgICB0aGlzLnNlYXJjaExpc3QuYWN0aXZlSW5kZXggPSAwO1xuICAgIHRoaXMuc2VhcmNoTGlzdC5wb3NpdGlvbihuYXRpdmVFbGVtZW50LCB0aGlzLmlmcmFtZSk7XG4gICAgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB0aGlzLnNlYXJjaExpc3QucmVzZXQoKSk7XG4gIH1cbn1cbiJdfQ==