/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import { DOCUMENT, ɵgetDOM as getDOM } from '@angular/common'; import { Inject, Injectable } from '@angular/core'; import { EventManagerPlugin } from './event_manager'; import * as i0 from "@angular/core"; /** * Defines supported modifiers for key events. */ const MODIFIER_KEYS = ['alt', 'control', 'meta', 'shift']; // The following values are here for cross-browser compatibility and to match the W3C standard // cf https://www.w3.org/TR/DOM-Level-3-Events-key/ const _keyMap = { '\b': 'Backspace', '\t': 'Tab', '\x7F': 'Delete', '\x1B': 'Escape', 'Del': 'Delete', 'Esc': 'Escape', 'Left': 'ArrowLeft', 'Right': 'ArrowRight', 'Up': 'ArrowUp', 'Down': 'ArrowDown', 'Menu': 'ContextMenu', 'Scroll': 'ScrollLock', 'Win': 'OS' }; /** * Retrieves modifiers from key-event objects. */ const MODIFIER_KEY_GETTERS = { 'alt': (event) => event.altKey, 'control': (event) => event.ctrlKey, 'meta': (event) => event.metaKey, 'shift': (event) => event.shiftKey }; /** * @publicApi * A browser plug-in that provides support for handling of key events in Angular. */ export class KeyEventsPlugin extends EventManagerPlugin { /** * Initializes an instance of the browser plug-in. * @param doc The document in which key events will be detected. */ constructor(doc) { super(doc); } /** * Reports whether a named key event is supported. * @param eventName The event name to query. * @return True if the named key event is supported. */ supports(eventName) { return KeyEventsPlugin.parseEventName(eventName) != null; } /** * Registers a handler for a specific element and key event. * @param element The HTML element to receive event notifications. * @param eventName The name of the key event to listen for. * @param handler A function to call when the notification occurs. Receives the * event object as an argument. * @returns The key event that was registered. */ addEventListener(element, eventName, handler) { const parsedEvent = KeyEventsPlugin.parseEventName(eventName); const outsideHandler = KeyEventsPlugin.eventCallback(parsedEvent['fullKey'], handler, this.manager.getZone()); return this.manager.getZone().runOutsideAngular(() => { return getDOM().onAndCancel(element, parsedEvent['domEventName'], outsideHandler); }); } /** * Parses the user provided full keyboard event definition and normalizes it for * later internal use. It ensures the string is all lowercase, converts special * characters to a standard spelling, and orders all the values consistently. * * @param eventName The name of the key event to listen for. * @returns an object with the full, normalized string, and the dom event name * or null in the case when the event doesn't match a keyboard event. */ static parseEventName(eventName) { const parts = eventName.toLowerCase().split('.'); const domEventName = parts.shift(); if ((parts.length === 0) || !(domEventName === 'keydown' || domEventName === 'keyup')) { return null; } const key = KeyEventsPlugin._normalizeKey(parts.pop()); let fullKey = ''; let codeIX = parts.indexOf('code'); if (codeIX > -1) { parts.splice(codeIX, 1); fullKey = 'code.'; } MODIFIER_KEYS.forEach(modifierName => { const index = parts.indexOf(modifierName); if (index > -1) { parts.splice(index, 1); fullKey += modifierName + '.'; } }); fullKey += key; if (parts.length != 0 || key.length === 0) { // returning null instead of throwing to let another plugin process the event return null; } // NOTE: Please don't rewrite this as so, as it will break JSCompiler property renaming. // The code must remain in the `result['domEventName']` form. // return {domEventName, fullKey}; const result = {}; result['domEventName'] = domEventName; result['fullKey'] = fullKey; return result; } /** * Determines whether the actual keys pressed match the configured key code string. * The `fullKeyCode` event is normalized in the `parseEventName` method when the * event is attached to the DOM during the `addEventListener` call. This is unseen * by the end user and is normalized for internal consistency and parsing. * * @param event The keyboard event. * @param fullKeyCode The normalized user defined expected key event string * @returns boolean. */ static matchEventFullKeyCode(event, fullKeyCode) { let keycode = _keyMap[event.key] || event.key; let key = ''; if (fullKeyCode.indexOf('code.') > -1) { keycode = event.code; key = 'code.'; } // the keycode could be unidentified so we have to check here if (keycode == null || !keycode) return false; keycode = keycode.toLowerCase(); if (keycode === ' ') { keycode = 'space'; // for readability } else if (keycode === '.') { keycode = 'dot'; // because '.' is used as a separator in event names } MODIFIER_KEYS.forEach(modifierName => { if (modifierName !== keycode) { const modifierGetter = MODIFIER_KEY_GETTERS[modifierName]; if (modifierGetter(event)) { key += modifierName + '.'; } } }); key += keycode; return key === fullKeyCode; } /** * Configures a handler callback for a key event. * @param fullKey The event name that combines all simultaneous keystrokes. * @param handler The function that responds to the key event. * @param zone The zone in which the event occurred. * @returns A callback function. */ static eventCallback(fullKey, handler, zone) { return (event) => { if (KeyEventsPlugin.matchEventFullKeyCode(event, fullKey)) { zone.runGuarded(() => handler(event)); } }; } /** @internal */ static _normalizeKey(keyName) { // TODO: switch to a Map if the mapping grows too much switch (keyName) { case 'esc': return 'escape'; default: return keyName; } } } KeyEventsPlugin.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: KeyEventsPlugin, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable }); KeyEventsPlugin.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: KeyEventsPlugin }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: KeyEventsPlugin, decorators: [{ type: Injectable }], ctorParameters: function () { return [{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT] }] }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5X2V2ZW50cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL3BsYXRmb3JtLWJyb3dzZXIvc3JjL2RvbS9ldmVudHMva2V5X2V2ZW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEVBQUMsUUFBUSxFQUFFLE9BQU8sSUFBSSxNQUFNLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUM1RCxPQUFPLEVBQUMsTUFBTSxFQUFFLFVBQVUsRUFBUyxNQUFNLGVBQWUsQ0FBQztBQUV6RCxPQUFPLEVBQUMsa0JBQWtCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQzs7QUFFbkQ7O0dBRUc7QUFDSCxNQUFNLGFBQWEsR0FBRyxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBRTFELDhGQUE4RjtBQUM5RixtREFBbUQ7QUFDbkQsTUFBTSxPQUFPLEdBQTBCO0lBQ3JDLElBQUksRUFBRSxXQUFXO0lBQ2pCLElBQUksRUFBRSxLQUFLO0lBQ1gsTUFBTSxFQUFFLFFBQVE7SUFDaEIsTUFBTSxFQUFFLFFBQVE7SUFDaEIsS0FBSyxFQUFFLFFBQVE7SUFDZixLQUFLLEVBQUUsUUFBUTtJQUNmLE1BQU0sRUFBRSxXQUFXO0lBQ25CLE9BQU8sRUFBRSxZQUFZO0lBQ3JCLElBQUksRUFBRSxTQUFTO0lBQ2YsTUFBTSxFQUFFLFdBQVc7SUFDbkIsTUFBTSxFQUFFLGFBQWE7SUFDckIsUUFBUSxFQUFFLFlBQVk7SUFDdEIsS0FBSyxFQUFFLElBQUk7Q0FDWixDQUFDO0FBRUY7O0dBRUc7QUFDSCxNQUFNLG9CQUFvQixHQUF1RDtJQUMvRSxLQUFLLEVBQUUsQ0FBQyxLQUFvQixFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTTtJQUM3QyxTQUFTLEVBQUUsQ0FBQyxLQUFvQixFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsT0FBTztJ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Q0FBQztRQUNmLE9BQU8sR0FBRyxLQUFLLFdBQVcsQ0FBQztJQUM3QixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsTUFBTSxDQUFDLGFBQWEsQ0FBQyxPQUFlLEVBQUUsT0FBaUIsRUFBRSxJQUFZO1FBQ25FLE9BQU8sQ0FBQyxLQUFvQixFQUFFLEVBQUU7WUFDOUIsSUFBSSxlQUFlLENBQUMscUJBQXFCLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxFQUFFO2dCQUN6RCxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO2FBQ3ZDO1FBQ0gsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVELGdCQUFnQjtJQUNoQixNQUFNLENBQUMsYUFBYSxDQUFDLE9BQWU7UUFDbEMsc0RBQXNEO1FBQ3RELFFBQVEsT0FBTyxFQUFFO1lBQ2YsS0FBSyxLQUFLO2dCQUNSLE9BQU8sUUFBUSxDQUFDO1lBQ2xCO2dCQUNFLE9BQU8sT0FBTyxDQUFDO1NBQ2xCO0lBQ0gsQ0FBQzs7dUhBbEpVLGVBQWUsa0JBS04sUUFBUTsySEFMakIsZUFBZTtzR0FBZixlQUFlO2tCQUQzQixVQUFVOzswQkFNSSxNQUFNOzJCQUFDLFFBQVEiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHtET0NVTUVOVCwgybVnZXRET00gYXMgZ2V0RE9NfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtJbmplY3QsIEluamVjdGFibGUsIE5nWm9uZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7RXZlbnRNYW5hZ2VyUGx1Z2lufSBmcm9tICcuL2V2ZW50X21hbmFnZXInO1xuXG4vKipcbiAqIERlZmluZXMgc3VwcG9ydGVkIG1vZGlmaWVycyBmb3Iga2V5IGV2ZW50cy5cbiAqL1xuY29uc3QgTU9ESUZJRVJfS0VZUyA9IFsnYWx0JywgJ2NvbnRyb2wnLCAnbWV0YScsICdzaGlmdCddO1xuXG4vLyBUaGUgZm9sbG93aW5nIHZhbHVlcyBhcmUgaGVyZSBmb3IgY3Jvc3MtYnJvd3NlciBjb21wYXRpYmlsaXR5IGFuZCB0byBtYXRjaCB0aGUgVzNDIHN0YW5kYXJkXG4vLyBjZiBodHRwczovL3d3dy53My5vcmcvVFIvRE9NLUxldmVsLTMtRXZlbnRzLWtleS9cbmNvbnN0IF9rZXlNYXA6IHtbazogc3RyaW5nXTogc3RyaW5nfSA9IHtcbiAgJ1xcYic6ICdCYWNrc3BhY2UnLFxuICAnXFx0JzogJ1RhYicsXG4gICdcXHg3Ric6ICdEZWxldGUnLFxuICAnXFx4MUInOiAnRXNjYXBlJyxcbiAgJ0RlbCc6ICdEZWxldGUnLFxuICAnRXNjJzogJ0VzY2FwZScsXG4gICdMZWZ0JzogJ0Fycm93TGVmdCcsXG4gICdSaWdodCc6ICdBcnJvd1JpZ2h0JyxcbiAgJ1VwJzogJ0Fycm93VXAnLFxuICAnRG93bic6ICdBcnJvd0Rvd24nLFxuICAnTWVudSc6ICdDb250ZXh0TWVudScsXG4gICdTY3JvbGwnOiAnU2Nyb2xsTG9jaycsXG4gICdXaW4nOiAnT1MnXG59O1xuXG4vKipcbiAqIFJldHJpZXZlcyBtb2RpZmllcnMgZnJvbSBrZXktZXZlbnQgb2JqZWN0cy5cbiAqL1xuY29uc3QgTU9ESUZJRVJfS0VZX0dFVFRFUlM6IHtba2V5OiBzdHJpbmddOiAoZXZlbnQ6IEtleWJvYXJkRXZlbnQpID0+IGJvb2xlYW59ID0ge1xuICAnYWx0JzogKGV2ZW50OiBLZXlib2FyZEV2ZW50KSA9PiBldmVudC5hbHRLZXksXG4gICdjb250cm9sJzogKGV2ZW50OiBLZXlib2FyZEV2ZW50KSA9PiBldmVudC5jdHJsS2V5LFxuICAnbWV0YSc6IChldmVudDogS2V5Ym9hcmRFdmVudCkgPT4gZXZlbnQubWV0YUtleSxcbiAgJ3NoaWZ0JzogKGV2ZW50OiBLZXlib2FyZEV2ZW50KSA9PiBldmVudC5zaGlmdEtleVxufTtcblxuLyoqXG4gKiBAcHVibGljQXBpXG4gKiBBIGJyb3dzZXIgcGx1Zy1pbiB0aGF0IHByb3ZpZGVzIHN1cHBvcnQgZm9yIGhhbmRsaW5nIG9mIGtleSBldmVudHMgaW4gQW5ndWxhci5cbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEtleUV2ZW50c1BsdWdpbiBleHRlbmRzIEV2ZW50TWFuYWdlclBsdWdpbiB7XG4gIC8qKlxuICAgKiBJbml0aWFsaXplcyBhbiBpbnN0YW5jZSBvZiB0aGUgYnJvd3NlciBwbHVnLWluLlxuICAgKiBAcGFyYW0gZG9jIFRoZSBkb2N1bWVudCBpbiB3aGljaCBrZXkgZXZlbnRzIHdpbGwgYmUgZGV0ZWN0ZWQuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihASW5qZWN0KERPQ1VNRU5UKSBkb2M6IGFueSkge1xuICAgIHN1cGVyKGRvYyk7XG4gIH1cblxuICAvKipcbiAgICogUmVwb3J0cyB3aGV0aGVyIGEgbmFtZWQga2V5IGV2ZW50IGlzIHN1cHBvcnRlZC5cbiAgICogQHBhcmFtIGV2ZW50TmFtZSBUaGUgZXZlbnQgbmFtZSB0byBxdWVyeS5cbiAgICogQHJldHVybiBUcnVlIGlmIHRoZSBuYW1lZCBrZXkgZXZlbnQgaXMgc3VwcG9ydGVkLlxuICAgKi9cbiAgb3ZlcnJpZGUgc3VwcG9ydHMoZXZlbnROYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gS2V5RXZlbnRzUGx1Z2luLnBhcnNlRXZlbnROYW1lKGV2ZW50TmFtZSkgIT0gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgYSBoYW5kbGVyIGZvciBhIHNwZWNpZmljIGVsZW1lbnQgYW5kIGtleSBldmVudC5cbiAgICogQHBhcmFtIGVsZW1lbnQgVGhlIEhUTUwgZWxlbWVudCB0byByZWNlaXZlIGV2ZW50IG5vdGlmaWNhdGlvbnMuXG4gICAqIEBwYXJhbSBldmVudE5hbWUgVGhlIG5hbWUgb2YgdGhlIGtleSBldmVudCB0byBsaXN0ZW4gZm9yLlxuICAgKiBAcGFyYW0gaGFuZGxlciBBIGZ1bmN0aW9uIHRvIGNhbGwgd2hlbiB0aGUgbm90aWZpY2F0aW9uIG9jY3Vycy4gUmVjZWl2ZXMgdGhlXG4gICAqIGV2ZW50IG9iamVjdCBhcyBhbiBhcmd1bWVudC5cbiAgICogQHJldHVybnMgVGhlIGtleSBldmVudCB0aGF0IHdhcyByZWdpc3RlcmVkLlxuICAgKi9cbiAgb3ZlcnJpZGUgYWRkRXZlbnRMaXN0ZW5lcihlbGVtZW50OiBIVE1MRWxlbWVudCwgZXZlbnROYW1lOiBzdHJpbmcsIGhhbmRsZXI6IEZ1bmN0aW9uKTogRnVuY3Rpb24ge1xuICAgIGNvbnN0IHBhcnNlZEV2ZW50ID0gS2V5RXZlbnRzUGx1Z2luLnBhcnNlRXZlbnROYW1lKGV2ZW50TmFtZSkhO1xuXG4gICAgY29uc3Qgb3V0c2lkZUhhbmRsZXIgPVxuICAgICAgICBLZXlFdmVudHNQbHVnaW4uZXZlbnRDYWxsYmFjayhwYXJzZWRFdmVudFsnZnVsbEtleSddLCBoYW5kbGVyLCB0aGlzLm1hbmFnZXIuZ2V0Wm9uZSgpKTtcblxuICAgIHJldHVybiB0aGlzLm1hbmFnZXIuZ2V0Wm9uZSgpLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgIHJldHVybiBnZXRET00oKS5vbkFuZENhbmNlbChlbGVtZW50LCBwYXJzZWRFdmVudFsnZG9tRXZlbnROYW1lJ10sIG91dHNpZGVIYW5kbGVyKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZXMgdGhlIHVzZXIgcHJvdmlkZWQgZnVsbCBrZXlib2FyZCBldmVudCBkZWZpbml0aW9uIGFuZCBub3JtYWxpemVzIGl0IGZvclxuICAgKiBsYXRlciBpbnRlcm5hbCB1c2UuIEl0IGVuc3VyZXMgdGhlIHN0cmluZyBpcyBhbGwgbG93ZXJjYXNlLCBjb252ZXJ0cyBzcGVjaWFsXG4gICAqIGNoYXJhY3RlcnMgdG8gYSBzdGFuZGFyZCBzcGVsbGluZywgYW5kIG9yZGVycyBhbGwgdGhlIHZhbHVlcyBjb25zaXN0ZW50bHkuXG4gICAqXG4gICAqIEBwYXJhbSBldmVudE5hbWUgVGhlIG5hbWUgb2YgdGhlIGtleSBldmVudCB0byBsaXN0ZW4gZm9yLlxuICAgKiBAcmV0dXJucyBhbiBvYmplY3Qgd2l0aCB0aGUgZnVsbCwgbm9ybWFsaXplZCBzdHJpbmcsIGFuZCB0aGUgZG9tIGV2ZW50IG5hbWVcbiAgICogb3IgbnVsbCBpbiB0aGUgY2FzZSB3aGVuIHRoZSBldmVudCBkb2Vzbid0IG1hdGNoIGEga2V5Ym9hcmQgZXZlbnQuXG4gICAqL1xuICBzdGF0aWMgcGFyc2VFdmVudE5hbWUoZXZlbnROYW1lOiBzdHJpbmcpOiB7ZnVsbEtleTogc3RyaW5nLCBkb21FdmVudE5hbWU6IHN0cmluZ318bnVsbCB7XG4gICAgY29uc3QgcGFydHM6IHN0cmluZ1tdID0gZXZlbnROYW1lLnRvTG93ZXJDYXNlKCkuc3BsaXQoJy4nKTtcblxuICAgIGNvbnN0IGRvbUV2ZW50TmFtZSA9IHBhcnRzLnNoaWZ0KCk7XG4gICAgaWYgKChwYXJ0cy5sZW5ndGggPT09IDApIHx8ICEoZG9tRXZlbnROYW1lID09PSAna2V5ZG93bicgfHwgZG9tRXZlbnROYW1lID09PSAna2V5dXAnKSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3Qga2V5ID0gS2V5RXZlbnRzUGx1Z2luLl9ub3JtYWxpemVLZXkocGFydHMucG9wKCkhKTtcblxuICAgIGxldCBmdWxsS2V5ID0gJyc7XG4gICAgbGV0IGNvZGVJWCA9IHBhcnRzLmluZGV4T2YoJ2NvZGUnKTtcbiAgICBpZiAoY29kZUlYID4gLTEpIHtcbiAgICAgIHBhcnRzLnNwbGljZShjb2RlSVgsIDEpO1xuICAgICAgZnVsbEtleSA9ICdjb2RlLic7XG4gICAgfVxuICAgIE1PRElGSUVSX0tFWVMuZm9yRWFjaChtb2RpZmllck5hbWUgPT4ge1xuICAgICAgY29uc3QgaW5kZXg6IG51bWJlciA9IHBhcnRzLmluZGV4T2YobW9kaWZpZXJOYW1lKTtcbiAgICAgIGlmIChpbmRleCA+IC0xKSB7XG4gICAgICAgIHBhcnRzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgIGZ1bGxLZXkgKz0gbW9kaWZpZXJOYW1lICsgJy4nO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGZ1bGxLZXkgKz0ga2V5O1xuXG4gICAgaWYgKHBhcnRzLmxlbmd0aCAhPSAwIHx8IGtleS5sZW5ndGggPT09IDApIHtcbiAgICAgIC8vIHJldHVybmluZyBudWxsIGluc3RlYWQgb2YgdGhyb3dpbmcgdG8gbGV0IGFub3RoZXIgcGx1Z2luIHByb2Nlc3MgdGhlIGV2ZW50XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBOT1RFOiBQbGVhc2UgZG9uJ3QgcmV3cml0ZSB0aGlzIGFzIHNvLCBhcyBpdCB3aWxsIGJyZWFrIEpTQ29tcGlsZXIgcHJvcGVydHkgcmVuYW1pbmcuXG4gICAgLy8gICAgICAgVGhlIGNvZGUgbXVzdCByZW1haW4gaW4gdGhlIGByZXN1bHRbJ2RvbUV2ZW50TmFtZSddYCBmb3JtLlxuICAgIC8vIHJldHVybiB7ZG9tRXZlbnROYW1lLCBmdWxsS2V5fTtcbiAgICBjb25zdCByZXN1bHQ6IHtmdWxsS2V5OiBzdHJpbmcsIGRvbUV2ZW50TmFtZTogc3RyaW5nfSA9IHt9IGFzIGFueTtcbiAgICByZXN1bHRbJ2RvbUV2ZW50TmFtZSddID0gZG9tRXZlbnROYW1lO1xuICAgIHJlc3VsdFsnZnVsbEtleSddID0gZnVsbEtleTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZXMgd2hldGhlciB0aGUgYWN0dWFsIGtleXMgcHJlc3NlZCBtYXRjaCB0aGUgY29uZmlndXJlZCBrZXkgY29kZSBzdHJpbmcuXG4gICAqIFRoZSBgZnVsbEtleUNvZGVgIGV2ZW50IGlzIG5vcm1hbGl6ZWQgaW4gdGhlIGBwYXJzZUV2ZW50TmFtZWAgbWV0aG9kIHdoZW4gdGhlXG4gICAqIGV2ZW50IGlzIGF0dGFjaGVkIHRvIHRoZSBET00gZHVyaW5nIHRoZSBgYWRkRXZlbnRMaXN0ZW5lcmAgY2FsbC4gVGhpcyBpcyB1bnNlZW5cbiAgICogYnkgdGhlIGVuZCB1c2VyIGFuZCBpcyBub3JtYWxpemVkIGZvciBpbnRlcm5hbCBjb25zaXN0ZW5jeSBhbmQgcGFyc2luZy5cbiAgICpcbiAgICogQHBhcmFtIGV2ZW50IFRoZSBrZXlib2FyZCBldmVudC5cbiAgICogQHBhcmFtIGZ1bGxLZXlDb2RlIFRoZSBub3JtYWxpemVkIHVzZXIgZGVmaW5lZCBleHBlY3RlZCBrZXkgZXZlbnQgc3RyaW5nXG4gICAqIEByZXR1cm5zIGJvb2xlYW4uXG4gICAqL1xuICBzdGF0aWMgbWF0Y2hFdmVudEZ1bGxLZXlDb2RlKGV2ZW50OiBLZXlib2FyZEV2ZW50LCBmdWxsS2V5Q29kZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgbGV0IGtleWNvZGUgPSBfa2V5TWFwW2V2ZW50LmtleV0gfHwgZXZlbnQua2V5O1xuICAgIGxldCBrZXkgPSAnJztcbiAgICBpZiAoZnVsbEtleUNvZGUuaW5kZXhPZignY29kZS4nKSA+IC0xKSB7XG4gICAgICBrZXljb2RlID0gZXZlbnQuY29kZTtcbiAgICAgIGtleSA9ICdjb2RlLic7XG4gICAgfVxuICAgIC8vIHRoZSBrZXljb2RlIGNvdWxkIGJlIHVuaWRlbnRpZmllZCBzbyB3ZSBoYXZlIHRvIGNoZWNrIGhlcmVcbiAgICBpZiAoa2V5Y29kZSA9PSBudWxsIHx8ICFrZXljb2RlKSByZXR1cm4gZmFsc2U7XG4gICAga2V5Y29kZSA9IGtleWNvZGUudG9Mb3dlckNhc2UoKTtcbiAgICBpZiAoa2V5Y29kZSA9PT0gJyAnKSB7XG4gICAgICBrZXljb2RlID0gJ3NwYWNlJzsgIC8vIGZvciByZWFkYWJpbGl0eVxuICAgIH0gZWxzZSBpZiAoa2V5Y29kZSA9PT0gJy4nKSB7XG4gICAgICBrZXljb2RlID0gJ2RvdCc7ICAvLyBiZWNhdXNlICcuJyBpcyB1c2VkIGFzIGEgc2VwYXJhdG9yIGluIGV2ZW50IG5hbWVzXG4gICAgfVxuICAgIE1PRElGSUVSX0tFWVMuZm9yRWFjaChtb2RpZmllck5hbWUgPT4ge1xuICAgICAgaWYgKG1vZGlmaWVyTmFtZSAhPT0ga2V5Y29kZSkge1xuICAgICAgICBjb25zdCBtb2RpZmllckdldHRlciA9IE1PRElGSUVSX0tFWV9HRVRURVJTW21vZGlmaWVyTmFtZV07XG4gICAgICAgIGlmIChtb2RpZmllckdldHRlcihldmVudCkpIHtcbiAgICAgICAgICBrZXkgKz0gbW9kaWZpZXJOYW1lICsgJy4nO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAga2V5ICs9IGtleWNvZGU7XG4gICAgcmV0dXJuIGtleSA9PT0gZnVsbEtleUNvZGU7XG4gIH1cblxuICAvKipcbiAgICogQ29uZmlndXJlcyBhIGhhbmRsZXIgY2FsbGJhY2sgZm9yIGEga2V5IGV2ZW50LlxuICAgKiBAcGFyYW0gZnVsbEtleSBUaGUgZXZlbnQgbmFtZSB0aGF0IGNvbWJpbmVzIGFsbCBzaW11bHRhbmVvdXMga2V5c3Ryb2tlcy5cbiAgICogQHBhcmFtIGhhbmRsZXIgVGhlIGZ1bmN0aW9uIHRoYXQgcmVzcG9uZHMgdG8gdGhlIGtleSBldmVudC5cbiAgICogQHBhcmFtIHpvbmUgVGhlIHpvbmUgaW4gd2hpY2ggdGhlIGV2ZW50IG9jY3VycmVkLlxuICAgKiBAcmV0dXJucyBBIGNhbGxiYWNrIGZ1bmN0aW9uLlxuICAgKi9cbiAgc3RhdGljIGV2ZW50Q2FsbGJhY2soZnVsbEtleTogc3RyaW5nLCBoYW5kbGVyOiBGdW5jdGlvbiwgem9uZTogTmdab25lKTogRnVuY3Rpb24ge1xuICAgIHJldHVybiAoZXZlbnQ6IEtleWJvYXJkRXZlbnQpID0+IHtcbiAgICAgIGlmIChLZXlFdmVudHNQbHVnaW4ubWF0Y2hFdmVudEZ1bGxLZXlDb2RlKGV2ZW50LCBmdWxsS2V5KSkge1xuICAgICAgICB6b25lLnJ1bkd1YXJkZWQoKCkgPT4gaGFuZGxlcihldmVudCkpO1xuICAgICAgfVxuICAgIH07XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIHN0YXRpYyBfbm9ybWFsaXplS2V5KGtleU5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgLy8gVE9ETzogc3dpdGNoIHRvIGEgTWFwIGlmIHRoZSBtYXBwaW5nIGdyb3dzIHRvbyBtdWNoXG4gICAgc3dpdGNoIChrZXlOYW1lKSB7XG4gICAgICBjYXNlICdlc2MnOlxuICAgICAgICByZXR1cm4gJ2VzY2FwZSc7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4ga2V5TmFtZTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==