@angular/platform-browser
Version:
Angular - library for using Angular in a web browser
183 lines • 22 kB
JavaScript
/**
* @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
};
/**
* 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) {
return keyName === 'esc' ? 'escape' : keyName;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: KeyEventsPlugin, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: KeyEventsPlugin }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: KeyEventsPlugin, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5X2V2ZW50cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL3BsYXRmb3JtLWJyb3dzZXIvc3JjL2RvbS9ldmVudHMva2V5X2V2ZW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEVBQUMsUUFBUSxFQUFFLE9BQU8sSUFBSSxNQUFNLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUM1RCxPQUFPLEVBQUMsTUFBTSxFQUFFLFVBQVUsRUFBUyxNQUFNLGVBQWUsQ0FBQztBQUV6RCxPQUFPLEVBQUMsa0JBQWtCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQzs7QUFFbkQ7O0dBRUc7QUFDSCxNQUFNLGFBQWEsR0FBRyxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBRTFELDhGQUE4RjtBQUM5RixtREFBbUQ7QUFDbkQsTUFBTSxPQUFPLEdBQTBCO0lBQ3JDLElBQUksRUFBRSxXQUFXO0lBQ2pCLElBQUksRUFBRSxLQUFLO0lBQ1gsTUFBTSxFQUFFLFFBQVE7SUFDaEIsTUFBTSxFQUFFLFFBQVE7SUFDaEIsS0FBSyxFQUFFLFFBQVE7SUFDZixLQUFLLEVBQUUsUUFBUTtJQUNmLE1BQU0sRUFBRSxXQUFXO0lBQ25CLE9BQU8sRUFBRSxZQUFZO0lBQ3JCLElBQUksRUFBRSxTQUFTO0lBQ2YsTUFBTSxFQUFFLFdBQVc7SUFDbkIsTUFBTSxFQUFFLGFBQWE7SUFDckIsUUFBUSxFQUFFLFlBQVk7SUFDdEIsS0FBSyxFQUFFLElBQUk7Q0FDWixDQUFDO0FBRUY7O0dBRUc7QUFDSCxNQUFNLG9CQUFvQixHQUF1RDtJQUMvRSxLQUFLLEVBQUUsQ0FBQyxLQUFvQixFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTTtJQUM3QyxTQUFTLEVBQUUsQ0FBQyxLQUFvQixFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsT0FBTztJ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QUFDO1FBQ2YsT0FBTyxHQUFHLEtBQUssV0FBVyxDQUFDO0lBQzdCLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSCxNQUFNLENBQUMsYUFBYSxDQUFDLE9BQWUsRUFBRSxPQUFpQixFQUFFLElBQVk7UUFDbkUsT0FBTyxDQUFDLEtBQW9CLEVBQUUsRUFBRTtZQUM5QixJQUFJLGVBQWUsQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLEVBQUU7Z0JBQ3pELElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7YUFDdkM7UUFDSCxDQUFDLENBQUM7SUFDSixDQUFDO0lBRUQsZ0JBQWdCO0lBQ2hCLE1BQU0sQ0FBQyxhQUFhLENBQUMsT0FBZTtRQUNsQyxPQUFPLE9BQU8sS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO0lBQ2hELENBQUM7eUhBNUlVLGVBQWUsa0JBS04sUUFBUTs2SEFMakIsZUFBZTs7c0dBQWYsZUFBZTtrQkFEM0IsVUFBVTs7MEJBTUksTUFBTTsyQkFBQyxRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7RE9DVU1FTlQsIMm1Z2V0RE9NIGFzIGdldERPTX0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7SW5qZWN0LCBJbmplY3RhYmxlLCBOZ1pvbmV9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQge0V2ZW50TWFuYWdlclBsdWdpbn0gZnJvbSAnLi9ldmVudF9tYW5hZ2VyJztcblxuLyoqXG4gKiBEZWZpbmVzIHN1cHBvcnRlZCBtb2RpZmllcnMgZm9yIGtleSBldmVudHMuXG4gKi9cbmNvbnN0IE1PRElGSUVSX0tFWVMgPSBbJ2FsdCcsICdjb250cm9sJywgJ21ldGEnLCAnc2hpZnQnXTtcblxuLy8gVGhlIGZvbGxvd2luZyB2YWx1ZXMgYXJlIGhlcmUgZm9yIGNyb3NzLWJyb3dzZXIgY29tcGF0aWJpbGl0eSBhbmQgdG8gbWF0Y2ggdGhlIFczQyBzdGFuZGFyZFxuLy8gY2YgaHR0cHM6Ly93d3cudzMub3JnL1RSL0RPTS1MZXZlbC0zLUV2ZW50cy1rZXkvXG5jb25zdCBfa2V5TWFwOiB7W2s6IHN0cmluZ106IHN0cmluZ30gPSB7XG4gICdcXGInOiAnQmFja3NwYWNlJyxcbiAgJ1xcdCc6ICdUYWInLFxuICAnXFx4N0YnOiAnRGVsZXRlJyxcbiAgJ1xceDFCJzogJ0VzY2FwZScsXG4gICdEZWwnOiAnRGVsZXRlJyxcbiAgJ0VzYyc6ICdFc2NhcGUnLFxuICAnTGVmdCc6ICdBcnJvd0xlZnQnLFxuICAnUmlnaHQnOiAnQXJyb3dSaWdodCcsXG4gICdVcCc6ICdBcnJvd1VwJyxcbiAgJ0Rvd24nOiAnQXJyb3dEb3duJyxcbiAgJ01lbnUnOiAnQ29udGV4dE1lbnUnLFxuICAnU2Nyb2xsJzogJ1Njcm9sbExvY2snLFxuICAnV2luJzogJ09TJ1xufTtcblxuLyoqXG4gKiBSZXRyaWV2ZXMgbW9kaWZpZXJzIGZyb20ga2V5LWV2ZW50IG9iamVjdHMuXG4gKi9cbmNvbnN0IE1PRElGSUVSX0tFWV9HRVRURVJTOiB7W2tleTogc3RyaW5nXTogKGV2ZW50OiBLZXlib2FyZEV2ZW50KSA9PiBib29sZWFufSA9IHtcbiAgJ2FsdCc6IChldmVudDogS2V5Ym9hcmRFdmVudCkgPT4gZXZlbnQuYWx0S2V5LFxuICAnY29udHJvbCc6IChldmVudDogS2V5Ym9hcmRFdmVudCkgPT4gZXZlbnQuY3RybEtleSxcbiAgJ21ldGEnOiAoZXZlbnQ6IEtleWJvYXJkRXZlbnQpID0+IGV2ZW50Lm1ldGFLZXksXG4gICdzaGlmdCc6IChldmVudDogS2V5Ym9hcmRFdmVudCkgPT4gZXZlbnQuc2hpZnRLZXlcbn07XG5cbi8qKlxuICogQSBicm93c2VyIHBsdWctaW4gdGhhdCBwcm92aWRlcyBzdXBwb3J0IGZvciBoYW5kbGluZyBvZiBrZXkgZXZlbnRzIGluIEFuZ3VsYXIuXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBLZXlFdmVudHNQbHVnaW4gZXh0ZW5kcyBFdmVudE1hbmFnZXJQbHVnaW4ge1xuICAvKipcbiAgICogSW5pdGlhbGl6ZXMgYW4gaW5zdGFuY2Ugb2YgdGhlIGJyb3dzZXIgcGx1Zy1pbi5cbiAgICogQHBhcmFtIGRvYyBUaGUgZG9jdW1lbnQgaW4gd2hpY2gga2V5IGV2ZW50cyB3aWxsIGJlIGRldGVjdGVkLlxuICAgKi9cbiAgY29uc3RydWN0b3IoQEluamVjdChET0NVTUVOVCkgZG9jOiBhbnkpIHtcbiAgICBzdXBlcihkb2MpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcG9ydHMgd2hldGhlciBhIG5hbWVkIGtleSBldmVudCBpcyBzdXBwb3J0ZWQuXG4gICAqIEBwYXJhbSBldmVudE5hbWUgVGhlIGV2ZW50IG5hbWUgdG8gcXVlcnkuXG4gICAqIEByZXR1cm4gVHJ1ZSBpZiB0aGUgbmFtZWQga2V5IGV2ZW50IGlzIHN1cHBvcnRlZC5cbiAgICovXG4gIG92ZXJyaWRlIHN1cHBvcnRzKGV2ZW50TmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIEtleUV2ZW50c1BsdWdpbi5wYXJzZUV2ZW50TmFtZShldmVudE5hbWUpICE9IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0ZXJzIGEgaGFuZGxlciBmb3IgYSBzcGVjaWZpYyBlbGVtZW50IGFuZCBrZXkgZXZlbnQuXG4gICAqIEBwYXJhbSBlbGVtZW50IFRoZSBIVE1MIGVsZW1lbnQgdG8gcmVjZWl2ZSBldmVudCBub3RpZmljYXRpb25zLlxuICAgKiBAcGFyYW0gZXZlbnROYW1lIFRoZSBuYW1lIG9mIHRoZSBrZXkgZXZlbnQgdG8gbGlzdGVuIGZvci5cbiAgICogQHBhcmFtIGhhbmRsZXIgQSBmdW5jdGlvbiB0byBjYWxsIHdoZW4gdGhlIG5vdGlmaWNhdGlvbiBvY2N1cnMuIFJlY2VpdmVzIHRoZVxuICAgKiBldmVudCBvYmplY3QgYXMgYW4gYXJndW1lbnQuXG4gICAqIEByZXR1cm5zIFRoZSBrZXkgZXZlbnQgdGhhdCB3YXMgcmVnaXN0ZXJlZC5cbiAgICovXG4gIG92ZXJyaWRlIGFkZEV2ZW50TGlzdGVuZXIoZWxlbWVudDogSFRNTEVsZW1lbnQsIGV2ZW50TmFtZTogc3RyaW5nLCBoYW5kbGVyOiBGdW5jdGlvbik6IEZ1bmN0aW9uIHtcbiAgICBjb25zdCBwYXJzZWRFdmVudCA9IEtleUV2ZW50c1BsdWdpbi5wYXJzZUV2ZW50TmFtZShldmVudE5hbWUpITtcblxuICAgIGNvbnN0IG91dHNpZGVIYW5kbGVyID1cbiAgICAgICAgS2V5RXZlbnRzUGx1Z2luLmV2ZW50Q2FsbGJhY2socGFyc2VkRXZlbnRbJ2Z1bGxLZXknXSwgaGFuZGxlciwgdGhpcy5tYW5hZ2VyLmdldFpvbmUoKSk7XG5cbiAgICByZXR1cm4gdGhpcy5tYW5hZ2VyLmdldFpvbmUoKS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICByZXR1cm4gZ2V0RE9NKCkub25BbmRDYW5jZWwoZWxlbWVudCwgcGFyc2VkRXZlbnRbJ2RvbUV2ZW50TmFtZSddLCBvdXRzaWRlSGFuZGxlcik7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUGFyc2VzIHRoZSB1c2VyIHByb3ZpZGVkIGZ1bGwga2V5Ym9hcmQgZXZlbnQgZGVmaW5pdGlvbiBhbmQgbm9ybWFsaXplcyBpdCBmb3JcbiAgICogbGF0ZXIgaW50ZXJuYWwgdXNlLiBJdCBlbnN1cmVzIHRoZSBzdHJpbmcgaXMgYWxsIGxvd2VyY2FzZSwgY29udmVydHMgc3BlY2lhbFxuICAgKiBjaGFyYWN0ZXJzIHRvIGEgc3RhbmRhcmQgc3BlbGxpbmcsIGFuZCBvcmRlcnMgYWxsIHRoZSB2YWx1ZXMgY29uc2lzdGVudGx5LlxuICAgKlxuICAgKiBAcGFyYW0gZXZlbnROYW1lIFRoZSBuYW1lIG9mIHRoZSBrZXkgZXZlbnQgdG8gbGlzdGVuIGZvci5cbiAgICogQHJldHVybnMgYW4gb2JqZWN0IHdpdGggdGhlIGZ1bGwsIG5vcm1hbGl6ZWQgc3RyaW5nLCBhbmQgdGhlIGRvbSBldmVudCBuYW1lXG4gICAqIG9yIG51bGwgaW4gdGhlIGNhc2Ugd2hlbiB0aGUgZXZlbnQgZG9lc24ndCBtYXRjaCBhIGtleWJvYXJkIGV2ZW50LlxuICAgKi9cbiAgc3RhdGljIHBhcnNlRXZlbnROYW1lKGV2ZW50TmFtZTogc3RyaW5nKToge2Z1bGxLZXk6IHN0cmluZywgZG9tRXZlbnROYW1lOiBzdHJpbmd9fG51bGwge1xuICAgIGNvbnN0IHBhcnRzOiBzdHJpbmdbXSA9IGV2ZW50TmFtZS50b0xvd2VyQ2FzZSgpLnNwbGl0KCcuJyk7XG5cbiAgICBjb25zdCBkb21FdmVudE5hbWUgPSBwYXJ0cy5zaGlmdCgpO1xuICAgIGlmICgocGFydHMubGVuZ3RoID09PSAwKSB8fCAhKGRvbUV2ZW50TmFtZSA9PT0gJ2tleWRvd24nIHx8IGRvbUV2ZW50TmFtZSA9PT0gJ2tleXVwJykpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IGtleSA9IEtleUV2ZW50c1BsdWdpbi5fbm9ybWFsaXplS2V5KHBhcnRzLnBvcCgpISk7XG5cbiAgICBsZXQgZnVsbEtleSA9ICcnO1xuICAgIGxldCBjb2RlSVggPSBwYXJ0cy5pbmRleE9mKCdjb2RlJyk7XG4gICAgaWYgKGNvZGVJWCA+IC0xKSB7XG4gICAgICBwYXJ0cy5zcGxpY2UoY29kZUlYLCAxKTtcbiAgICAgIGZ1bGxLZXkgPSAnY29kZS4nO1xuICAgIH1cbiAgICBNT0RJRklFUl9LRVlTLmZvckVhY2gobW9kaWZpZXJOYW1lID0+IHtcbiAgICAgIGNvbnN0IGluZGV4OiBudW1iZXIgPSBwYXJ0cy5pbmRleE9mKG1vZGlmaWVyTmFtZSk7XG4gICAgICBpZiAoaW5kZXggPiAtMSkge1xuICAgICAgICBwYXJ0cy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICBmdWxsS2V5ICs9IG1vZGlmaWVyTmFtZSArICcuJztcbiAgICAgIH1cbiAgICB9KTtcbiAgICBmdWxsS2V5ICs9IGtleTtcblxuICAgIGlmIChwYXJ0cy5sZW5ndGggIT0gMCB8fCBrZXkubGVuZ3RoID09PSAwKSB7XG4gICAgICAvLyByZXR1cm5pbmcgbnVsbCBpbnN0ZWFkIG9mIHRocm93aW5nIHRvIGxldCBhbm90aGVyIHBsdWdpbiBwcm9jZXNzIHRoZSBldmVudFxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLy8gTk9URTogUGxlYXNlIGRvbid0IHJld3JpdGUgdGhpcyBhcyBzbywgYXMgaXQgd2lsbCBicmVhayBKU0NvbXBpbGVyIHByb3BlcnR5IHJlbmFtaW5nLlxuICAgIC8vICAgICAgIFRoZSBjb2RlIG11c3QgcmVtYWluIGluIHRoZSBgcmVzdWx0Wydkb21FdmVudE5hbWUnXWAgZm9ybS5cbiAgICAvLyByZXR1cm4ge2RvbUV2ZW50TmFtZSwgZnVsbEtleX07XG4gICAgY29uc3QgcmVzdWx0OiB7ZnVsbEtleTogc3RyaW5nLCBkb21FdmVudE5hbWU6IHN0cmluZ30gPSB7fSBhcyBhbnk7XG4gICAgcmVzdWx0Wydkb21FdmVudE5hbWUnXSA9IGRvbUV2ZW50TmFtZTtcbiAgICByZXN1bHRbJ2Z1bGxLZXknXSA9IGZ1bGxLZXk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIHdoZXRoZXIgdGhlIGFjdHVhbCBrZXlzIHByZXNzZWQgbWF0Y2ggdGhlIGNvbmZpZ3VyZWQga2V5IGNvZGUgc3RyaW5nLlxuICAgKiBUaGUgYGZ1bGxLZXlDb2RlYCBldmVudCBpcyBub3JtYWxpemVkIGluIHRoZSBgcGFyc2VFdmVudE5hbWVgIG1ldGhvZCB3aGVuIHRoZVxuICAgKiBldmVudCBpcyBhdHRhY2hlZCB0byB0aGUgRE9NIGR1cmluZyB0aGUgYGFkZEV2ZW50TGlzdGVuZXJgIGNhbGwuIFRoaXMgaXMgdW5zZWVuXG4gICAqIGJ5IHRoZSBlbmQgdXNlciBhbmQgaXMgbm9ybWFsaXplZCBmb3IgaW50ZXJuYWwgY29uc2lzdGVuY3kgYW5kIHBhcnNpbmcuXG4gICAqXG4gICAqIEBwYXJhbSBldmVudCBUaGUga2V5Ym9hcmQgZXZlbnQuXG4gICAqIEBwYXJhbSBmdWxsS2V5Q29kZSBUaGUgbm9ybWFsaXplZCB1c2VyIGRlZmluZWQgZXhwZWN0ZWQga2V5IGV2ZW50IHN0cmluZ1xuICAgKiBAcmV0dXJucyBib29sZWFuLlxuICAgKi9cbiAgc3RhdGljIG1hdGNoRXZlbnRGdWxsS2V5Q29kZShldmVudDogS2V5Ym9hcmRFdmVudCwgZnVsbEtleUNvZGU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGxldCBrZXljb2RlID0gX2tleU1hcFtldmVudC5rZXldIHx8IGV2ZW50LmtleTtcbiAgICBsZXQga2V5ID0gJyc7XG4gICAgaWYgKGZ1bGxLZXlDb2RlLmluZGV4T2YoJ2NvZGUuJykgPiAtMSkge1xuICAgICAga2V5Y29kZSA9IGV2ZW50LmNvZGU7XG4gICAgICBrZXkgPSAnY29kZS4nO1xuICAgIH1cbiAgICAvLyB0aGUga2V5Y29kZSBjb3VsZCBiZSB1bmlkZW50aWZpZWQgc28gd2UgaGF2ZSB0byBjaGVjayBoZXJlXG4gICAgaWYgKGtleWNvZGUgPT0gbnVsbCB8fCAha2V5Y29kZSkgcmV0dXJuIGZhbHNlO1xuICAgIGtleWNvZGUgPSBrZXljb2RlLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKGtleWNvZGUgPT09ICcgJykge1xuICAgICAga2V5Y29kZSA9ICdzcGFjZSc7ICAvLyBmb3IgcmVhZGFiaWxpdHlcbiAgICB9IGVsc2UgaWYgKGtleWNvZGUgPT09ICcuJykge1xuICAgICAga2V5Y29kZSA9ICdkb3QnOyAgLy8gYmVjYXVzZSAnLicgaXMgdXNlZCBhcyBhIHNlcGFyYXRvciBpbiBldmVudCBuYW1lc1xuICAgIH1cbiAgICBNT0RJRklFUl9LRVlTLmZvckVhY2gobW9kaWZpZXJOYW1lID0+IHtcbiAgICAgIGlmIChtb2RpZmllck5hbWUgIT09IGtleWNvZGUpIHtcbiAgICAgICAgY29uc3QgbW9kaWZpZXJHZXR0ZXIgPSBNT0RJRklFUl9LRVlfR0VUVEVSU1ttb2RpZmllck5hbWVdO1xuICAgICAgICBpZiAobW9kaWZpZXJHZXR0ZXIoZXZlbnQpKSB7XG4gICAgICAgICAga2V5ICs9IG1vZGlmaWVyTmFtZSArICcuJztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIGtleSArPSBrZXljb2RlO1xuICAgIHJldHVybiBrZXkgPT09IGZ1bGxLZXlDb2RlO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyZXMgYSBoYW5kbGVyIGNhbGxiYWNrIGZvciBhIGtleSBldmVudC5cbiAgICogQHBhcmFtIGZ1bGxLZXkgVGhlIGV2ZW50IG5hbWUgdGhhdCBjb21iaW5lcyBhbGwgc2ltdWx0YW5lb3VzIGtleXN0cm9rZXMuXG4gICAqIEBwYXJhbSBoYW5kbGVyIFRoZSBmdW5jdGlvbiB0aGF0IHJlc3BvbmRzIHRvIHRoZSBrZXkgZXZlbnQuXG4gICAqIEBwYXJhbSB6b25lIFRoZSB6b25lIGluIHdoaWNoIHRoZSBldmVudCBvY2N1cnJlZC5cbiAgICogQHJldHVybnMgQSBjYWxsYmFjayBmdW5jdGlvbi5cbiAgICovXG4gIHN0YXRpYyBldmVudENhbGxiYWNrKGZ1bGxLZXk6IHN0cmluZywgaGFuZGxlcjogRnVuY3Rpb24sIHpvbmU6IE5nWm9uZSk6IEZ1bmN0aW9uIHtcbiAgICByZXR1cm4gKGV2ZW50OiBLZXlib2FyZEV2ZW50KSA9PiB7XG4gICAgICBpZiAoS2V5RXZlbnRzUGx1Z2luLm1hdGNoRXZlbnRGdWxsS2V5Q29kZShldmVudCwgZnVsbEtleSkpIHtcbiAgICAgICAgem9uZS5ydW5HdWFyZGVkKCgpID0+IGhhbmRsZXIoZXZlbnQpKTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBzdGF0aWMgX25vcm1hbGl6ZUtleShrZXlOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBrZXlOYW1lID09PSAnZXNjJyA/ICdlc2NhcGUnIDoga2V5TmFtZTtcbiAgfVxufVxuIl19