UNPKG

@alauda-fe/common

Version:

Alauda frontend team common codes.

280 lines 47.4 kB
import { Injectable, IterableDiffers, } from '@angular/core'; import { cloneDeep, isEqual, set, unset } from 'lodash-es'; import * as i0 from "@angular/core"; export const DUPLICATE_ERROR_KEY = 'duplicateError'; // IDENTICAL: 检测具有互反性,传递性。a与b重复,b与c重复,a必然与c重复,此程度上可进行优化 // FULL: 不要求检测具有互反性,传递性。a与b判别重复,b与c判别重复,a未必与c判别重复 // 主要是针对一些复杂的自定义匹配重复的使用场景,FULL模式采用全检查 export var DUPLICATION_JUSTIFY_STRATEGY; (function (DUPLICATION_JUSTIFY_STRATEGY) { DUPLICATION_JUSTIFY_STRATEGY["IDENTICAL"] = "identical"; DUPLICATION_JUSTIFY_STRATEGY["FULL"] = "full"; })(DUPLICATION_JUSTIFY_STRATEGY || (DUPLICATION_JUSTIFY_STRATEGY = {})); export const STRATEGY_JUDGE_MAPPER = { [DUPLICATION_JUSTIFY_STRATEGY.IDENTICAL]: identicalStrategyCheck, [DUPLICATION_JUSTIFY_STRATEGY.FULL]: fullStrategyCheck, }; // use in component lifecycle export class ValidateRowDuplicateService { /** * @param differFactory: used to create support differ, which can be provided by user */ constructor(arrayDiffers) { this.arrayDiffers = arrayDiffers; // used to save last value, to check whether if control changed this.controlValueMap = new WeakMap(); // used to save errors,to solve validators concurrently work(second validator can't get error from previous validator in one turn) this.errorMap = new WeakMap(); } // eslint-disable-next-line sonarjs/cognitive-complexity createFormArrayValidator({ rowKeys, formArray, valueMapFn = defaultValueMapFn, initData = [], matchesFn = matchValue, strategy = DUPLICATION_JUSTIFY_STRATEGY.IDENTICAL, }) { const keys = formatKeys(rowKeys); if (!this.rowsDiffer) { this.rowsDiffer = this.arrayDiffers.find([]).create(); } this.initFormArraySizeChange(formArray, this.rowsDiffer, keys, valueMapFn, matchesFn, strategy, initData); return (control) => { const { controls } = formArray; const lastValue = this.controlValueMap.get(control); if (control.pristine) { return null; } // nothing change const currentValue = getValueInKeys(control.value, keys, valueMapFn); this.controlValueMap.set(control, currentValue); if (lastValue) { let identical = true; Object.entries(keys).forEach(([key, props]) => { if (!equalsValue(props, currentValue[key], lastValue[key])) { identical = false; } }); if (identical) { return this.errorMap.get(control); } } const diffKeys = lastValue ? diffKeysByValue(keys, currentValue, lastValue) : keys; // 和上次值存在差异,可将老数据作为删除行处理 if (lastValue) { this.handleRemoveRowValue(diffKeys, controls, lastValue, valueMapFn, control, matchesFn, strategy, initData); } // 更新后的状态,可能导致其他行出现新的重复 const otherControls = controls.filter(ctrl => ctrl !== control); const ctrlError = {}; otherControls.forEach(ctrl => { const otherValue = getValueInKeys(ctrl.value, diffKeys, valueMapFn); const othersError = {}; // keys 中分别比较 如果 otherValue 与 currentValue 在某个key下,数据相同,则说明此 key 存在重复错误 Object.entries(diffKeys).forEach(([key, props]) => { if (matchesFn(props, otherValue[key], currentValue[key])) { set(othersError, [key], currentValue[key]); set(ctrlError, key, currentValue[key]); } }); this.addDuplicateError(othersError, ctrl, true); }); (initData || []).forEach(initRow => { Object.entries(diffKeys).forEach(([key, props]) => { if (matchesFn(props, initRow[key], currentValue[key])) { set(ctrlError, key, currentValue[key]); } }); }); this.addDuplicateError(ctrlError, control); return this.errorMap.get(control); }; } handleRemoveRowValue(keys, controls, staleValue, mapFn, selfControl, matchesFn, strategy, initData) { if (selfControl) { this.removeDuplicateError(Object.keys(keys), selfControl); } const toRemoveError = STRATEGY_JUDGE_MAPPER[strategy](keys, controls, staleValue, mapFn, matchesFn, initData); (toRemoveError || []).forEach(({ key, control }) => this.removeDuplicateError([key], control, true)); } initFormArraySizeChange(formArray, rowsDiffer, keys, mapFn, matchesFn, strategy, initData) { if (!this.formArraySizeSub) { this.formArraySizeSub = formArray.valueChanges.subscribe(_ => { const { controls } = formArray; const rowsDiff = rowsDiffer.diff(controls); if (rowsDiff) { // on deleting row rowsDiff.forEachRemovedItem(record => { const rawValue = getValueInKeys(record.item.value, keys, mapFn); this.handleRemoveRowValue(keys, controls, rawValue, mapFn, undefined, matchesFn, strategy, initData); }); } }); } } addDuplicateError(errorInfo, control, setControl = false) { const errors = cloneDeep(this.errorMap.get(control)) || {}; // already has error,no need to add if (!Object.keys(errorInfo).some(key => errors?.[DUPLICATE_ERROR_KEY]?.[key] == null)) { return; } Object.keys(errorInfo).forEach(key => { set(errors, [DUPLICATE_ERROR_KEY, key], errorInfo[key]); }); this.errorMap.set(control, errors); if (setControl) { // 当设置重复报错时,需要注意保留原来的报错 const controlError = cloneDeep(control.errors); unset(controlError, [DUPLICATE_ERROR_KEY]); const error = { ...controlError, ...this.errorMap.get(control) }; control.setErrors(Object.keys(error).length === 0 ? null : error, { emitEvent: false, }); // control's error should be shown,it's not pristine any more control.markAsDirty(); } } removeDuplicateError(errorInfo, control, setControl = false) { const errors = cloneDeep(this.errorMap.get(control)); // no need to remove error if (!errorInfo.some(key => errors?.[DUPLICATE_ERROR_KEY]?.[key] != null)) { return; } errorInfo.forEach(key => { unset(errors, [DUPLICATE_ERROR_KEY, key]); }); this.errorMap.set(control, Object.keys(errors?.[DUPLICATE_ERROR_KEY] || {}).length ? errors : null); if (setControl) { const controlError = cloneDeep(control.errors) || {}; unset(controlError, [DUPLICATE_ERROR_KEY]); const error = { ...controlError, ...this.errorMap.get(control) }; control.setErrors(Object.keys(error).length === 0 ? null : error, { emitEvent: false, }); } } ngOnDestroy() { if (this.formArraySizeSub) { this.formArraySizeSub.unsubscribe(); } } static { this.ɵfac = function ValidateRowDuplicateService_Factory(t) { return new (t || ValidateRowDuplicateService)(i0.ɵɵinject(i0.IterableDiffers)); }; } static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: ValidateRowDuplicateService, factory: ValidateRowDuplicateService.ɵfac }); } } (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ValidateRowDuplicateService, [{ type: Injectable }], () => [{ type: i0.IterableDiffers }], null); })(); // 仅返回keys规则下,currentValue与lastValue存在不同的部分key function diffKeysByValue(keys, currentValue, lastValue) { const obj = {}; Object.entries(keys).forEach(([key, props]) => { if (!equalsValue(props, currentValue[key], lastValue[key])) { obj[key] = props; } }); return obj; } // 指定属性下,value1 和 value2 对于所有的属性存在有效值,并且相同,此时可判定重复 function matchValue(props, value1, value2) { return !props.some(prop => unCheckedValue(value1, prop) || value1[prop] !== value2[prop]); } // 指定属性下,value1 和 value2 对于所有的属性相同,此时可判定 value1 , value2 相等 function equalsValue(props, value1, value2) { return !props.some(prop => !isEqual(value1[prop], value2[prop])); } /** * @param keys ['protocol',{complex: ['containerPort','hostPort']}] * @returns [{protocol: ['protocol']}, {complex: ['containerPort','hostPort']}] */ function formatKeys(keys = []) { const obj = {}; keys.forEach(keyObj => { if (typeof keyObj === 'string') { obj[keyObj] = [keyObj]; return; } Object.keys(keyObj).forEach(key => { obj[key] = keyObj[key]; }); }); return obj; } function unCheckedValue(value, key) { return value?.[key] == null || value[key] === ''; } function defaultValueMapFn(data, prop) { return data?.[prop]; } /** * @param value input value,which should include all key behind keys * @param keys formatted keys, key is error key, like [{'containerPort':['containerPort']},{'complexError':['containerPort','hostPort']}] * @returns */ function getValueInKeys(value, keys, mapFn) { const obj = {}; Object.entries(keys).forEach(([key, props]) => { props.forEach(prop => { set(obj, [key, prop], mapFn(value, prop)); }); }); return obj; } // 互反性检查 function identicalStrategyCheck(keys, controls, staleValue, mapFn, matchesFn, initData) { const errorsCounter = {}; Object.entries(keys).forEach(([key, props]) => { errorsCounter[key] = { controls: new Set(), count: 0 }; initData.forEach(initRow => { if (matchValue(props, initRow[key], staleValue[key])) { errorsCounter[key].count++; } }); controls.forEach(ctrl => { const controlValue = getValueInKeys(ctrl.value, keys, mapFn); // 互反性策略,要求和老数据相比,因此只有和老数据相同,但和任意当前其他数据不同的,才需要去掉之前的错误 if (matchesFn(props, controlValue[key], staleValue[key])) { errorsCounter[key].count++; errorsCounter[key].controls.add(ctrl); } }); }); const toRemoveError = []; Object.entries(errorsCounter).forEach(([key, item]) => { if (item.count === 1) { item.controls.forEach(control => { toRemoveError.push({ key, control }); }); } }); return toRemoveError; } // 全检查 function fullStrategyCheck(keys, controls, _, mapFn, matchesFn, initData) { const controlError = new Map(); Object.entries(keys).forEach(([key, props]) => { controls.forEach(ctrl => { const controlValue = getValueInKeys(ctrl.value, keys, mapFn); // 全检查策略,最终错误 key 对应 count 为 0 的ctrl会去掉相应错误 controlError.set(ctrl, { key, count: 0 }); initData.forEach(initRow => { if (matchValue(props, initRow[key], controlValue)) { const rawCount = controlError.get(ctrl).count; controlError.set(ctrl, { key, count: rawCount + 1 }); } }); controls .filter(otherControl => otherControl !== ctrl) .forEach(otherControl => { const otherValue = getValueInKeys(otherControl.value, keys, mapFn); if (matchesFn(props, controlValue[key], otherValue[key])) { const rawCount = controlError.get(ctrl).count; controlError.set(ctrl, { key, count: rawCount + 1 }); } }); }); }); const toRemoveError = []; controlError.forEach(({ count, key }, control) => { if (count === 0) { toRemoveError.push({ key, control }); } }); return toRemoveError; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybS1yb3ctZHVwbGljYXRlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9saWJzL2NvbW1vbi9zcmMvY29yZS9zZXJ2aWNlcy9mb3JtLXJvdy1kdXBsaWNhdGUvZm9ybS1yb3ctZHVwbGljYXRlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFVBQVUsRUFFVixlQUFlLEdBRWhCLE1BQU0sZUFBZSxDQUFDO0FBUXZCLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsTUFBTSxXQUFXLENBQUM7O0FBRzNELE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLGdCQUFnQixDQUFDO0FBcUJwRCx1REFBdUQ7QUFDdkQsaURBQWlEO0FBQ2pELHFDQUFxQztBQUNyQyxNQUFNLENBQU4sSUFBWSw0QkFHWDtBQUhELFdBQVksNEJBQTRCO0lBQ3RDLHVEQUF1QixDQUFBO0lBQ3ZCLDZDQUFhLENBQUE7QUFDZixDQUFDLEVBSFcsNEJBQTRCLEtBQTVCLDRCQUE0QixRQUd2QztBQUVELE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUc5QjtJQUNGLENBQUMsNEJBQTRCLENBQUMsU0FBUyxDQUFDLEVBQUUsc0JBQXNCO0lBQ2hFLENBQUMsNEJBQTRCLENBQUMsSUFBSSxDQUFDLEVBQUUsaUJBQWlCO0NBQ3ZELENBQUM7QUFFRiw2QkFBNkI7QUFFN0IsTUFBTSxPQUFPLDJCQUEyQjtJQUl0Qzs7T0FFRztJQUNILFlBQTZCLFlBQTZCO1FBQTdCLGlCQUFZLEdBQVosWUFBWSxDQUFpQjtRQUUxRCwrREFBK0Q7UUFDOUMsb0JBQWUsR0FBRyxJQUFJLE9BQU8sRUFHM0MsQ0FBQztRQUVKLGtJQUFrSTtRQUNqSCxhQUFRLEdBQUcsSUFBSSxPQUFPLEVBQXFDLENBQUM7SUFUaEIsQ0FBQztJQWE5RCx3REFBd0Q7SUFDeEQsd0JBQXdCLENBQUMs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Q0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDdkQsQ0FBQztZQUNILENBQUMsQ0FBQyxDQUFDO1lBQ0gsUUFBUTtpQkFDTCxNQUFNLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxZQUFZLEtBQUssSUFBSSxDQUFDO2lCQUM3QyxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUU7Z0JBQ3RCLE1BQU0sVUFBVSxHQUFHLGNBQWMsQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDbkUsSUFBSSxTQUFTLENBQUMsS0FBSyxFQUFFLFlBQVksQ0FBQyxHQUFHLENBQUMsRUFBRSxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO29CQUN6RCxNQUFNLFFBQVEsR0FBRyxZQUFZLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQztvQkFDOUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLFFBQVEsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUN2RCxDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxhQUFhLEdBQXFELEVBQUUsQ0FBQztJQUMzRSxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUUsT0FBTyxFQUFFLEVBQUU7UUFDL0MsSUFBSSxLQUFLLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDaEIsYUFBYSxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZDLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztJQUNILE9BQU8sYUFBYSxDQUFDO0FBQ3ZCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBJbmplY3RhYmxlLFxuICBJdGVyYWJsZURpZmZlcixcbiAgSXRlcmFibGVEaWZmZXJzLFxuICBPbkRlc3Ryb3ksXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgQWJzdHJhY3RDb250cm9sLFxuICBGb3JtQXJyYXksXG4gIEZvcm1Hcm91cCxcbiAgVmFsaWRhdGlvbkVycm9ycyxcbiAgVmFsaWRhdG9yRm4sXG59IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IGNsb25lRGVlcCwgaXNFcXVhbCwgc2V0LCB1bnNldCB9IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcblxuZXhwb3J0IGNvbnN0IERVUExJQ0FURV9FUlJPUl9LRVkgPSAnZHVwbGljYXRlRXJyb3InO1xuXG50eXBlIFJvd0tleXMgPSBBcnJheTxzdHJpbmcgfCBSZWNvcmQ8c3RyaW5nLCBzdHJpbmdbXT4+O1xudHlwZSBGb3JtYXRLZXlzID0gUmVjb3JkPHN0cmluZywgc3RyaW5nW10+O1xuZXhwb3J0IHR5cGUgRm9ybWF0VmFsdWUgPSBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuXG5leHBvcnQgdHlwZSBNYXRjaFZhbHVlRm4gPSAoXG4gIHByb3BzOiBzdHJpbmdbXSxcbiAgdmFsdWUxOiBGb3JtYXRWYWx1ZSxcbiAgdmFsdWUyOiBGb3JtYXRWYWx1ZSxcbikgPT4gYm9vbGVhbjtcblxuZXhwb3J0IHR5cGUgU3RyYXRlZ3lGbiA9IChcbiAga2V5czogRm9ybWF0S2V5cyxcbiAgY29udHJvbHM6IEFic3RyYWN0Q29udHJvbFtdLFxuICBzdGFsZVZhbHVlOiBGb3JtYXRWYWx1ZSxcbiAgbWFwRm46IFZhbHVlTWFwRm4sXG4gIG1hdGNoZXNGbjogTWF0Y2hWYWx1ZUZuLFxuICBpbml0RGF0YTogYW55W10sXG4pID0+IEFycmF5PHsga2V5OiBzdHJpbmc7IGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCB9PjtcblxuLy8gSURFTlRJQ0FMOiDmo4DmtYvlhbfmnInkupLlj43mgKfvvIzkvKDpgJLmgKfjgIJh5LiOYumHjeWkje+8jGLkuI5j6YeN5aSN77yMYeW/heeEtuS4jmPph43lpI3vvIzmraTnqIvluqbkuIrlj6/ov5vooYzkvJjljJZcbi8vIEZVTEw6IOS4jeimgeaxguajgOa1i+WFt+acieS6kuWPjeaAp++8jOS8oOmAkuaAp+OAgmHkuI5i5Yik5Yir6YeN5aSN77yMYuS4jmPliKTliKvph43lpI3vvIxh5pyq5b+F5LiOY+WIpOWIq+mHjeWkjVxuLy8g5Li76KaB5piv6ZKI5a+55LiA5Lqb5aSN5p2C55qE6Ieq5a6a5LmJ5Yy56YWN6YeN5aSN55qE5L2/55So5Zy65pmv77yMRlVMTOaooeW8j+mHh+eUqOWFqOajgOafpVxuZXhwb3J0IGVudW0gRFVQTElDQVRJT05fSlVTVElGWV9TVFJBVEVHWSB7XG4gIElERU5USUNBTCA9ICdpZGVudGljYWwnLFxuICBGVUxMID0gJ2Z1bGwnLFxufVxuXG5leHBvcnQgY29uc3QgU1RSQVRFR1lfSlVER0VfTUFQUEVSOiBSZWNvcmQ8XG4gIERVUExJQ0FUSU9OX0pVU1RJRllfU1RSQVRFR1ksXG4gIFN0cmF0ZWd5Rm5cbj4gPSB7XG4gIFtEVVBMSUNBVElPTl9KVVNUSUZZX1NUUkFURUdZLklERU5USUNBTF06IGlkZW50aWNhbFN0cmF0ZWd5Q2hlY2ssXG4gIFtEVVBMSUNBVElPTl9KVVNUSUZZX1NUUkFURUdZLkZVTExdOiBmdWxsU3RyYXRlZ3lDaGVjayxcbn07XG5cbi8vIHVzZSBpbiBjb21wb25lbnQgbGlmZWN5Y2xlXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgVmFsaWRhdGVSb3dEdXBsaWNhdGVTZXJ2aWNlIGltcGxlbWVudHMgT25EZXN0cm95IHtcbiAgLy8gdXNlZCB0byBkZXRlY3QgYWxsIGNvbnRyb2xzIGRhdGEgY2hhbmdlXG4gIHByaXZhdGUgcm93c0RpZmZlcjogSXRlcmFibGVEaWZmZXI8QWJzdHJhY3RDb250cm9sPjtcblxuICAvKipcbiAgICogQHBhcmFtIGRpZmZlckZhY3Rvcnk6IHVzZWQgdG8gY3JlYXRlIHN1cHBvcnQgZGlmZmVyLCB3aGljaCBjYW4gYmUgcHJvdmlkZWQgYnkgdXNlclxuICAgKi9cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBhcnJheURpZmZlcnM6IEl0ZXJhYmxlRGlmZmVycykge31cblxuICAvLyB1c2VkIHRvIHNhdmUgbGFzdCB2YWx1ZSwgdG8gY2hlY2sgd2hldGhlciBpZiBjb250cm9sIGNoYW5nZWRcbiAgcHJpdmF0ZSByZWFkb25seSBjb250cm9sVmFsdWVNYXAgPSBuZXcgV2Vha01hcDxcbiAgICBBYnN0cmFjdENvbnRyb2wsXG4gICAgRm9ybWF0VmFsdWVcbiAgPigpO1xuXG4gIC8vIHVzZWQgdG8gc2F2ZSBlcnJvcnPvvIx0byBzb2x2ZSB2YWxpZGF0b3JzIGNvbmN1cnJlbnRseSB3b3JrKHNlY29uZCB2YWxpZGF0b3IgY2FuJ3QgZ2V0IGVycm9yIGZyb20gcHJldmlvdXMgdmFsaWRhdG9yIGluIG9uZSB0dXJuKVxuICBwcml2YXRlIHJlYWRvbmx5IGVycm9yTWFwID0gbmV3IFdlYWtNYXA8QWJzdHJhY3RDb250cm9sLCBWYWxpZGF0aW9uRXJyb3JzPigpO1xuXG4gIHByaXZhdGUgZm9ybUFycmF5U2l6ZVN1YjogU3Vic2NyaXB0aW9uO1xuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBzb25hcmpzL2NvZ25pdGl2ZS1jb21wbGV4aXR5XG4gIGNyZWF0ZUZvcm1BcnJheVZhbGlkYXRvcih7XG4gICAgcm93S2V5cyxcbiAgICBmb3JtQXJyYXksXG4gICAgdmFsdWVNYXBGbiA9IGRlZmF1bHRWYWx1ZU1hcEZuLFxuICAgIGluaXREYXRhID0gW10sXG4gICAgbWF0Y2hlc0ZuID0gbWF0Y2hWYWx1ZSxcbiAgICBzdHJhdGVneSA9IERVUExJQ0FUSU9OX0pVU1RJRllfU1RSQVRFR1kuSURFTlRJQ0FMLFxuICB9OiB7XG4gICAgcm93S2V5czogUm93S2V5cztcbiAgICBmb3JtQXJyYXk6IEZvcm1BcnJheTtcbiAgICB2YWx1ZU1hcEZuPzogYW55O1xuICAgIGluaXREYXRhPzogYW55W107XG4gICAgbWF0Y2hlc0ZuPzogTWF0Y2hWYWx1ZUZuO1xuICAgIHN0cmF0ZWd5PzogRFVQTElDQVRJT05fSlVTVElGWV9TVFJBVEVHWTtcbiAgfSk6IFZhbGlkYXRvckZuIHtcbiAgICBjb25zdCBrZXlzID0gZm9ybWF0S2V5cyhyb3dLZXlzKTtcbiAgICBpZiAoIXRoaXMucm93c0RpZmZlcikge1xuICAgICAgdGhpcy5yb3dzRGlmZmVyID0gdGhpcy5hcnJheURpZmZlcnMuZmluZChbXSkuY3JlYXRlKCk7XG4gICAgfVxuXG4gICAgdGhpcy5pbml0Rm9ybUFycmF5U2l6ZUNoYW5nZShcbiAgICAgIGZvcm1BcnJheSxcbiAgICAgIHRoaXMucm93c0RpZmZlcixcbiAgICAgIGtleXMsXG4gICAgICB2YWx1ZU1hcEZuLFxuICAgICAgbWF0Y2hlc0ZuLFxuICAgICAgc3RyYXRlZ3ksXG4gICAgICBpbml0RGF0YSxcbiAgICApO1xuXG4gICAgcmV0dXJuIChjb250cm9sOiBGb3JtR3JvdXApID0+IHtcbiAgICAgIGNvbnN0IHsgY29udHJvbHMgfSA9IGZvcm1BcnJheTtcbiAgICAgIGNvbnN0IGxhc3RWYWx1ZSA9IHRoaXMuY29udHJvbFZhbHVlTWFwLmdldChjb250cm9sKTtcbiAgICAgIGlmIChjb250cm9sLnByaXN0aW5lKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgLy8gbm90aGluZyBjaGFuZ2VcbiAgICAgIGNvbnN0IGN1cnJlbnRWYWx1ZSA9IGdldFZhbHVlSW5LZXlzKGNvbnRyb2wudmFsdWUsIGtleXMsIHZhbHVlTWFwRm4pO1xuICAgICAgdGhpcy5jb250cm9sVmFsdWVNYXAuc2V0KGNvbnRyb2wsIGN1cnJlbnRWYWx1ZSk7XG4gICAgICBpZiAobGFzdFZhbHVlKSB7XG4gICAgICAgIGxldCBpZGVudGljYWwgPSB0cnVlO1xuICAgICAgICBPYmplY3QuZW50cmllcyhrZXlzKS5mb3JFYWNoKChba2V5LCBwcm9wc10pID0+IHtcbiAgICAgICAgICBpZiAoIWVxdWFsc1ZhbHVlKHByb3BzLCBjdXJyZW50VmFsdWVba2V5XSwgbGFzdFZhbHVlW2tleV0pKSB7XG4gICAgICAgICAgICBpZGVudGljYWwgPSBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoaWRlbnRpY2FsKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuZXJyb3JNYXAuZ2V0KGNvbnRyb2wpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjb25zdCBkaWZmS2V5cyA9IGxhc3RWYWx1ZVxuICAgICAgICA/IGRpZmZLZXlzQnlWYWx1ZShrZXlzLCBjdXJyZW50VmFsdWUsIGxhc3RWYWx1ZSlcbiAgICAgICAgOiBrZXlzO1xuICAgICAgLy8g5ZKM5LiK5qyh5YC85a2Y5Zyo5beu5byC77yM5Y+v5bCG6ICB5pWw5o2u5L2c5Li65Yig6Zmk6KGM5aSE55CGXG4gICAgICBpZiAobGFzdFZhbHVlKSB7XG4gICAgICAgIHRoaXMuaGFuZGxlUmVtb3ZlUm93VmFsdWUoXG4gICAgICAgICAgZGlmZktleXMsXG4gICAgICAgICAgY29udHJvbHMsXG4gICAgICAgICAgbGFzdFZhbHVlLFxuICAgICAgICAgIHZhbHVlTWFwRm4sXG4gICAgICAgICAgY29udHJvbCxcbiAgICAgICAgICBtYXRjaGVzRm4sXG4gICAgICAgICAgc3RyYXRlZ3ksXG4gICAgICAgICAgaW5pdERhdGEsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICAvLyDmm7TmlrDlkI7nmoTnirbmgIHvvIzlj6/og73lr7zoh7Tlhbbku5booYzlh7rnjrDmlrDnmoTph43lpI1cbiAgICAgIGNvbnN0IG90aGVyQ29udHJvbHMgPSBjb250cm9scy5maWx0ZXIoY3RybCA9PiBjdHJsICE9PSBjb250cm9sKTtcbiAgICAgIGNvbnN0IGN0cmxFcnJvcjogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgICAgb3RoZXJDb250cm9scy5mb3JFYWNoKGN0cmwgPT4ge1xuICAgICAgICBjb25zdCBvdGhlclZhbHVlID0gZ2V0VmFsdWVJbktleXMoY3RybC52YWx1ZSwgZGlmZktleXMsIHZhbHVlTWFwRm4pO1xuICAgICAgICBjb25zdCBvdGhlcnNFcnJvcjogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICAgICAgICAvLyBrZXlzIOS4reWIhuWIq+avlOi+gyDlpoLmnpwgb3RoZXJWYWx1ZSDkuI4gY3VycmVudFZhbHVlIOWcqOafkOS4qmtleeS4i++8jOaVsOaNruebuOWQjO+8jOWImeivtOaYjuatpCBrZXkg5a2Y5Zyo6YeN5aSN6ZSZ6K+vXG4gICAgICAgIE9iamVjdC5lbnRyaWVzKGRpZmZLZXlzKS5mb3JFYWNoKChba2V5LCBwcm9wc10pID0+IHtcbiAgICAgICAgICBpZiAobWF0Y2hlc0ZuKHByb3BzLCBvdGhlclZhbHVlW2tleV0sIGN1cnJlbnRWYWx1ZVtrZXldKSkge1xuICAgICAgICAgICAgc2V0KG90aGVyc0Vycm9yLCBba2V5XSwgY3VycmVudFZhbHVlW2tleV0pO1xuICAgICAgICAgICAgc2V0KGN0cmxFcnJvciwga2V5LCBjdXJyZW50VmFsdWVba2V5XSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5hZGREdXBsaWNhdGVFcnJvcihvdGhlcnNFcnJvciwgY3RybCwgdHJ1ZSk7XG4gICAgICB9KTtcbiAgICAgIChpbml0RGF0YSB8fCBbXSkuZm9yRWFjaChpbml0Um93ID0+IHtcbiAgICAgICAgT2JqZWN0LmVudHJpZXMoZGlmZktleXMpLmZvckVhY2goKFtrZXksIHByb3BzXSkgPT4ge1xuICAgICAgICAgIGlmIChtYXRjaGVzRm4ocHJvcHMsIGluaXRSb3dba2V5XSwgY3VycmVudFZhbHVlW2tleV0pKSB7XG4gICAgICAgICAgICBzZXQoY3RybEVycm9yLCBrZXksIGN1cnJlbnRWYWx1ZVtrZXldKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgICB0aGlzLmFkZER1cGxpY2F0ZUVycm9yKGN0cmxFcnJvciwgY29udHJvbCk7XG4gICAgICByZXR1cm4gdGhpcy5lcnJvck1hcC5nZXQoY29udHJvbCk7XG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlUmVtb3ZlUm93VmFsdWUoXG4gICAga2V5czogRm9ybWF0S2V5cyxcbiAgICBjb250cm9sczogQWJzdHJhY3RDb250cm9sW10sXG4gICAgc3RhbGVWYWx1ZTogRm9ybWF0VmFsdWUsXG4gICAgbWFwRm46IFZhbHVlTWFwRm4sXG4gICAgc2VsZkNvbnRyb2w/OiBBYnN0cmFjdENvbnRyb2wsXG4gICAgbWF0Y2hlc0ZuPzogTWF0Y2hWYWx1ZUZuLFxuICAgIHN0cmF0ZWd5PzogRFVQTElDQVRJT05fSlVTVElGWV9TVFJBVEVHWSxcbiAgICBpbml0RGF0YT86IGFueVtdLFxuICApIHtcbiAgICBpZiAoc2VsZkNvbnRyb2wpIHtcbiAgICAgIHRoaXMucmVtb3ZlRHVwbGljYXRlRXJyb3IoT2JqZWN0LmtleXMoa2V5cyksIHNlbGZDb250cm9sKTtcbiAgICB9XG4gICAgY29uc3QgdG9SZW1vdmVFcnJvciA9IFNUUkFURUdZX0pVREdFX01BUFBFUltzdHJhdGVneV0oXG4gICAgICBrZXlzLFxuICAgICAgY29udHJvbHMsXG4gICAgICBzdGFsZVZhbHVlLFxuICAgICAgbWFwRm4sXG4gICAgICBtYXRjaGVzRm4sXG4gICAgICBpbml0RGF0YSxcbiAgICApO1xuICAgICh0b1JlbW92ZUVycm9yIHx8IFtdKS5mb3JFYWNoKCh7IGtleSwgY29udHJvbCB9KSA9PlxuICAgICAgdGhpcy5yZW1vdmVEdXBsaWNhdGVFcnJvcihba2V5XSwgY29udHJvbCwgdHJ1ZSksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgaW5pdEZvcm1BcnJheVNpemVDaGFuZ2UoXG4gICAgZm9ybUFycmF5OiBGb3JtQXJyYXksXG4gICAgcm93c0RpZmZlcjogSXRlcmFibGVEaWZmZXI8QWJzdHJhY3RDb250cm9sPixcbiAgICBrZXlzOiBGb3JtYXRLZXlzLFxuICAgIG1hcEZuOiBWYWx1ZU1hcEZuLFxuICAgIG1hdGNoZXNGbjogTWF0Y2hWYWx1ZUZuLFxuICAgIHN0cmF0ZWd5OiBEVVBMSUNBVElPTl9KVVNUSUZZX1NUUkFURUdZLFxuICAgIGluaXREYXRhPzogYW55W10sXG4gICkge1xuICAgIGlmICghdGhpcy5mb3JtQXJyYXlTaXplU3ViKSB7XG4gICAgICB0aGlzLmZvcm1BcnJheVNpemVTdWIgPSBmb3JtQXJyYXkudmFsdWVDaGFuZ2VzLnN1YnNjcmliZShfID0+IHtcbiAgICAgICAgY29uc3QgeyBjb250cm9scyB9ID0gZm9ybUFycmF5O1xuICAgICAgICBjb25zdCByb3dzRGlmZiA9IHJvd3NEaWZmZXIuZGlmZihjb250cm9scyk7XG4gICAgICAgIGlmIChyb3dzRGlmZikge1xuICAgICAgICAgIC8vIG9uIGRlbGV0aW5nIHJvd1xuICAgICAgICAgIHJvd3NEaWZmLmZvckVhY2hSZW1vdmVkSXRlbShyZWNvcmQgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmF3VmFsdWUgPSBnZXRWYWx1ZUluS2V5cyhyZWNvcmQuaXRlbS52YWx1ZSwga2V5cywgbWFwRm4pO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVSZW1vdmVSb3dWYWx1ZShcbiAgICAgICAgICAgICAga2V5cyxcbiAgICAgICAgICAgICAgY29udHJvbHMsXG4gICAgICAgICAgICAgIHJhd1ZhbHVlLFxuICAgICAgICAgICAgICBtYXBGbixcbiAgICAgICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgICAgICBtYXRjaGVzRm4sXG4gICAgICAgICAgICAgIHN0cmF0ZWd5LFxuICAgICAgICAgICAgICBpbml0RGF0YSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYWRkRHVwbGljYXRlRXJyb3IoXG4gICAgZXJyb3JJbmZvOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCxcbiAgICBzZXRDb250cm9sID0gZmFsc2UsXG4gICkge1xuICAgIGNvbnN0IGVycm9ycyA9IGNsb25lRGVlcCh0aGlzLmVycm9yTWFwLmdldChjb250cm9sKSkgfHwge307XG4gICAgLy8gYWxyZWFkeSBoYXMgZXJyb3Isbm8gbmVlZCB0byBhZGRcbiAgICBpZiAoXG4gICAgICAhT2JqZWN0LmtleXMoZXJyb3JJbmZvKS5zb21lKFxuICAgICAgICBrZXkgPT4gZXJyb3JzPy5bRFVQTElDQVRFX0VSUk9SX0tFWV0/LltrZXldID09IG51bGwsXG4gICAgICApXG4gICAgKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgT2JqZWN0LmtleXMoZXJyb3JJbmZvKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICBzZXQoZXJyb3JzLCBbRFVQTElDQVRFX0VSUk9SX0tFWSwga2V5XSwgZXJyb3JJbmZvW2tleV0pO1xuICAgIH0pO1xuICAgIHRoaXMuZXJyb3JNYXAuc2V0KGNvbnRyb2wsIGVycm9ycyk7XG4gICAgaWYgKHNldENvbnRyb2wpIHtcbiAgICAgIC8vIOW9k+iuvue9rumHjeWkjeaKpemUmeaXtizpnIDopoHms6jmhI/kv53nlZnljp/mnaXnmoTmiqXplJlcbiAgICAgIGNvbnN0IGNvbnRyb2xFcnJvciA9IGNsb25lRGVlcChjb250cm9sLmVycm9ycyk7XG4gICAgICB1bnNldChjb250cm9sRXJyb3IsIFtEVVBMSUNBVEVfRVJST1JfS0VZXSk7XG4gICAgICBjb25zdCBlcnJvciA9IHsgLi4uY29udHJvbEVycm9yLCAuLi50aGlzLmVycm9yTWFwLmdldChjb250cm9sKSB9O1xuICAgICAgY29udHJvbC5zZXRFcnJvcnMoT2JqZWN0LmtleXMoZXJyb3IpLmxlbmd0aCA9PT0gMCA/IG51bGwgOiBlcnJvciwge1xuICAgICAgICBlbWl0RXZlbnQ6IGZhbHNlLFxuICAgICAgfSk7XG5cbiAgICAgIC8vIGNvbnRyb2wncyBlcnJvciBzaG91bGQgYmUgc2hvd24saXQncyBub3QgcHJpc3RpbmUgYW55IG1vcmVcbiAgICAgIGNvbnRyb2wubWFya0FzRGlydHkoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlbW92ZUR1cGxpY2F0ZUVycm9yKFxuICAgIGVycm9ySW5mbzogc3RyaW5nW10sXG4gICAgY29udHJvbDogQWJzdHJhY3RDb250cm9sLFxuICAgIHNldENvbnRyb2wgPSBmYWxzZSxcbiAgKSB7XG4gICAgY29uc3QgZXJyb3JzID0gY2xvbmVEZWVwKHRoaXMuZXJyb3JNYXAuZ2V0KGNvbnRyb2wpKTtcbiAgICAvLyBubyBuZWVkIHRvIHJlbW92ZSBlcnJvclxuICAgIGlmICghZXJyb3JJbmZvLnNvbWUoa2V5ID0+IGVycm9ycz8uW0RVUExJQ0FURV9FUlJPUl9LRVldPy5ba2V5XSAhPSBudWxsKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBlcnJvckluZm8uZm9yRWFjaChrZXkgPT4ge1xuICAgICAgdW5zZXQoZXJyb3JzLCBbRFVQTElDQVRFX0VSUk9SX0tFWSwga2V5XSk7XG4gICAgfSk7XG4gICAgdGhpcy5lcnJvck1hcC5zZXQoXG4gICAgICBjb250cm9sLFxuICAgICAgT2JqZWN0LmtleXMoZXJyb3JzPy5bRFVQTElDQVRFX0VSUk9SX0tFWV0gfHwge30pLmxlbmd0aCA/IGVycm9ycyA6IG51bGwsXG4gICAgKTtcbiAgICBpZiAoc2V0Q29udHJvbCkge1xuICAgICAgY29uc3QgY29udHJvbEVycm9yOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gY2xvbmVEZWVwKGNvbnRyb2wuZXJyb3JzKSB8fCB7fTtcbiAgICAgIHVuc2V0KGNvbnRyb2xFcnJvciwgW0RVUExJQ0FURV9FUlJPUl9LRVldKTtcblxuICAgICAgY29uc3QgZXJyb3IgPSB7IC4uLmNvbnRyb2xFcnJvciwgLi4udGhpcy5lcnJvck1hcC5nZXQoY29udHJvbCkgfTtcbiAgICAgIGNvbnRyb2wuc2V0RXJyb3JzKE9iamVjdC5rZXlzKGVycm9yKS5sZW5ndGggPT09IDAgPyBudWxsIDogZXJyb3IsIHtcbiAgICAgICAgZW1pdEV2ZW50OiBmYWxzZSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIGlmICh0aGlzLmZvcm1BcnJheVNpemVTdWIpIHtcbiAgICAgIHRoaXMuZm9ybUFycmF5U2l6ZVN1Yi51bnN1YnNjcmliZSgpO1xuICAgIH1cbiAgfVxufVxuXG4vLyDku4Xov5Tlm55rZXlz6KeE5YiZ5LiL77yMY3VycmVudFZhbHVl5LiObGFzdFZhbHVl5a2Y5Zyo5LiN5ZCM55qE6YOo5YiGa2V5XG5mdW5jdGlvbiBkaWZmS2V5c0J5VmFsdWUoXG4gIGtleXM6IEZvcm1hdEtleXMsXG4gIGN1cnJlbnRWYWx1ZTogRm9ybWF0VmFsdWUsXG4gIGxhc3RWYWx1ZTogRm9ybWF0VmFsdWUsXG4pIHtcbiAgY29uc3Qgb2JqOiBGb3JtYXRLZXlzID0ge307XG4gIE9iamVjdC5lbnRyaWVzKGtleXMpLmZvckVhY2goKFtrZXksIHByb3BzXSkgPT4ge1xuICAgIGlmICghZXF1YWxzVmFsdWUocHJvcHMsIGN1cnJlbnRWYWx1ZVtrZXldLCBsYXN0VmFsdWVba2V5XSkpIHtcbiAgICAgIG9ialtrZXldID0gcHJvcHM7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIG9iajtcbn1cblxuLy8g5oyH5a6a5bGe5oCn5LiL77yMdmFsdWUxIOWSjCB2YWx1ZTIg5a+55LqO5omA5pyJ55qE5bGe5oCn5a2Y5Zyo5pyJ5pWI5YC877yM5bm25LiU55u45ZCM77yM5q2k5pe25Y+v5Yik5a6a6YeN5aSNXG5mdW5jdGlvbiBtYXRjaFZhbHVlKHByb3BzOiBzdHJpbmdbXSwgdmFsdWUxOiBGb3JtYXRWYWx1ZSwgdmFsdWUyOiBGb3JtYXRWYWx1ZSkge1xuICByZXR1cm4gIXByb3BzLnNvbWUoXG4gICAgcHJvcCA9PiB1bkNoZWNrZWRWYWx1ZSh2YWx1ZTEsIHByb3ApIHx8IHZhbHVlMVtwcm9wXSAhPT0gdmFsdWUyW3Byb3BdLFxuICApO1xufVxuXG4vLyDmjIflrprlsZ7mgKfkuIvvvIx2YWx1ZTEg5ZKMIHZhbHVlMiDlr7nkuo7miYDmnInnmoTlsZ7mgKfnm7jlkIzvvIzmraTml7blj6/liKTlrpogdmFsdWUxICwgdmFsdWUyIOebuOetiVxuZnVuY3Rpb24gZXF1YWxzVmFsdWUoXG4gIHByb3BzOiBzdHJpbmdbXSxcbiAgdmFsdWUxOiBGb3JtYXRWYWx1ZSxcbiAgdmFsdWUyOiBGb3JtYXRWYWx1ZSxcbikge1xuICByZXR1cm4gIXByb3BzLnNvbWUocHJvcCA9PiAhaXNFcXVhbCh2YWx1ZTFbcHJvcF0sIHZhbHVlMltwcm9wXSkpO1xufVxuXG4vKipcbiAqIEBwYXJhbSBrZXlzIFsncHJvdG9jb2wnLHtjb21wbGV4OiBbJ2NvbnRhaW5lclBvcnQnLCdob3N0UG9ydCddfV1cbiAqIEByZXR1cm5zIFt7cHJvdG9jb2w6IFsncHJvdG9jb2wnXX0sIHtjb21wbGV4OiBbJ2NvbnRhaW5lclBvcnQnLCdob3N0UG9ydCddfV1cbiAqL1xuZnVuY3Rpb24gZm9ybWF0S2V5cyhrZXlzOiBSb3dLZXlzID0gW10pOiBGb3JtYXRLZXlzIHtcbiAgY29uc3Qgb2JqOiBGb3JtYXRLZXlzID0ge307XG4gIGtleXMuZm9yRWFjaChrZXlPYmogPT4ge1xuICAgIGlmICh0eXBlb2Yga2V5T2JqID09PSAnc3RyaW5nJykge1xuICAgICAgb2JqW2tleU9ial0gPSBba2V5T2JqXTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgT2JqZWN0LmtleXMoa2V5T2JqKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICBvYmpba2V5XSA9IGtleU9ialtrZXldO1xuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIG9iajtcbn1cblxuZnVuY3Rpb24gdW5DaGVja2VkVmFsdWUodmFsdWU6IEZvcm1hdFZhbHVlLCBrZXk6IHN0cmluZykge1xuICByZXR1cm4gdmFsdWU/LltrZXldID09IG51bGwgfHwgdmFsdWVba2V5XSA9PT0gJyc7XG59XG5cbmZ1bmN0aW9uIGRlZmF1bHRWYWx1ZU1hcEZuKGRhdGE6IGFueSwgcHJvcDogc3RyaW5nKSB7XG4gIHJldHVybiBkYXRhPy5bcHJvcF07XG59XG5cbnR5cGUgVmFsdWVNYXBGbiA9IChkYXRhOiBhbnksIHByb3A/OiBzdHJpbmcpID0+IGFueTtcblxuLyoqXG4gKiBAcGFyYW0gdmFsdWUgaW5wdXQgdmFsdWUsd2hpY2ggc2hvdWxkIGluY2x1ZGUgYWxsIGtleSBiZWhpbmQga2V5c1xuICogQHBhcmFtIGtleXMgZm9ybWF0dGVkIGtleXMsIGtleSBpcyBlcnJvciBrZXksIGxpa2UgW3snY29udGFpbmVyUG9ydCc6Wydjb250YWluZXJQb3J0J119LHsnY29tcGxleEVycm9yJzpbJ2NvbnRhaW5lclBvcnQnLCdob3N0UG9ydCddfV1cbiAqIEByZXR1cm5zXG4gKi9cbmZ1bmN0aW9uIGdldFZhbHVlSW5LZXlzKFxuICB2YWx1ZTogYW55LFxuICBrZXlzOiBGb3JtYXRLZXlzLFxuICBtYXBGbjogVmFsdWVNYXBGbixcbik6IEZvcm1hdFZhbHVlIHtcbiAgY29uc3Qgb2JqID0ge307XG4gIE9iamVjdC5lbnRyaWVzKGtleXMpLmZvckVhY2goKFtrZXksIHByb3BzXSkgPT4ge1xuICAgIHByb3BzLmZvckVhY2gocHJvcCA9PiB7XG4gICAgICBzZXQob2JqLCBba2V5LCBwcm9wXSwgbWFwRm4odmFsdWUsIHByb3ApKTtcbiAgICB9KTtcbiAgfSk7XG4gIHJldHVybiBvYmo7XG59XG5cbi8vIOS6kuWPjeaAp+ajgOafpVxuZnVuY3Rpb24gaWRlbnRpY2FsU3RyYXRlZ3lDaGVjayhcbiAga2V5czogRm9ybWF0S2V5cyxcbiAgY29udHJvbHM6IEFic3RyYWN0Q29udHJvbFtdLFxuICBzdGFsZVZhbHVlOiBGb3JtYXRWYWx1ZSxcbiAgbWFwRm46IFZhbHVlTWFwRm4sXG4gIG1hdGNoZXNGbjogTWF0Y2hWYWx1ZUZuLFxuICBpbml0RGF0YTogYW55W10sXG4pIHtcbiAgY29uc3QgZXJyb3JzQ291bnRlcjogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICB7IGNvbnRyb2xzOiBTZXQ8QWJzdHJhY3RDb250cm9sPjsgY291bnQ6IG51bWJlciB9XG4gID4gPSB7fTtcblxuICBPYmplY3QuZW50cmllcyhrZXlzKS5mb3JFYWNoKChba2V5LCBwcm9wc10pID0+IHtcbiAgICBlcnJvcnNDb3VudGVyW2tleV0gPSB7IGNvbnRyb2xzOiBuZXcgU2V0KCksIGNvdW50OiAwIH07XG4gICAgaW5pdERhdGEuZm9yRWFjaChpbml0Um93ID0+IHtcbiAgICAgIGlmIChtYXRjaFZhbHVlKHByb3BzLCBpbml0Um93W2tleV0sIHN0YWxlVmFsdWVba2V5XSkpIHtcbiAgICAgICAgZXJyb3JzQ291bnRlcltrZXldLmNvdW50Kys7XG4gICAgICB9XG4gICAgfSk7XG4gICAgY29udHJvbHMuZm9yRWFjaChjdHJsID0+IHtcbiAgICAgIGNvbnN0IGNvbnRyb2xWYWx1ZSA9IGdldFZhbHVlSW5LZXlzKGN0cmwudmFsdWUsIGtleXMsIG1hcEZuKTtcbiAgICAgIC8vIOS6kuWPjeaAp+etlueVpe+8jOimgeaxguWSjOiAgeaVsOaNruebuOavlO+8jOWboOatpOWPquacieWSjOiAgeaVsOaNruebuOWQjO+8jOS9huWSjOS7u+aEj+W9k+WJjeWFtuS7luaVsOaNruS4jeWQjOeahO+8jOaJjemcgOimgeWOu+aOieS5i+WJjeeahOmUmeivr1xuICAgICAgaWYgKG1hdGNoZXNGbihwcm9wcywgY29udHJvbFZhbHVlW2tleV0sIHN0YWxlVmFsdWVba2V5XSkpIHtcbiAgICAgICAgZXJyb3JzQ291bnRlcltrZXldLmNvdW50Kys7XG4gICAgICAgIGVycm9yc0NvdW50ZXJba2V5XS5jb250cm9scy5hZGQoY3RybCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuICBjb25zdCB0b1JlbW92ZUVycm9yOiBBcnJheTx7IGtleTogc3RyaW5nOyBjb250cm9sOiBBYnN0cmFjdENvbnRyb2wgfT4gPSBbXTtcbiAgT2JqZWN0LmVudHJpZXMoZXJyb3JzQ291bnRlcikuZm9yRWFjaCgoW2tleSwgaXRlbV0pID0+IHtcbiAgICBpZiAoaXRlbS5jb3VudCA9PT0gMSkge1xuICAgICAgaXRlbS5jb250cm9scy5mb3JFYWNoKGNvbnRyb2wgPT4ge1xuICAgICAgICB0b1JlbW92ZUVycm9yLnB1c2goeyBrZXksIGNvbnRyb2wgfSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gdG9SZW1vdmVFcnJvcjtcbn1cblxuLy8g5YWo5qOA5p+lXG5mdW5jdGlvbiBmdWxsU3RyYXRlZ3lDaGVjayhcbiAga2V5czogRm9ybWF0S2V5cyxcbiAgY29udHJvbHM6IEFic3RyYWN0Q29udHJvbFtdLFxuICBfOiBGb3JtYXRWYWx1ZSxcbiAgbWFwRm46IFZhbHVlTWFwRm4sXG4gIG1hdGNoZXNGbjogTWF0Y2hWYWx1ZUZuLFxuICBpbml0RGF0YTogYW55W10sXG4pIHtcbiAgY29uc3QgY29udHJvbEVycm9yOiBNYXA8QWJzdHJhY3RDb250cm9sLCB7IGtleTogc3RyaW5nOyBjb3VudDogbnVtYmVyIH0+ID1cbiAgICBuZXcgTWFwKCk7XG5cbiAgT2JqZWN0LmVudHJpZXMoa2V5cykuZm9yRWFjaCgoW2tleSwgcHJvcHNdKSA9PiB7XG4gICAgY29udHJvbHMuZm9yRWFjaChjdHJsID0+IHtcbiAgICAgIGNvbnN0IGNvbnRyb2xWYWx1ZSA9IGdldFZhbHVlSW5LZXlzKGN0cmwudmFsdWUsIGtleXMsIG1hcEZuKTtcbiAgICAgIC8vIOWFqOajgOafpeetlueVpe+8jOacgOe7iOmUmeivryBrZXkg5a+55bqUIGNvdW50IOS4uiAwIOeahGN0cmzkvJrljrvmjonnm7jlupTplJnor69cbiAgICAgIGNvbnRyb2xFcnJvci5zZXQoY3RybCwgeyBrZXksIGNvdW50OiAwIH0pO1xuICAgICAgaW5pdERhdGEuZm9yRWFjaChpbml0Um93ID0+IHtcbiAgICAgICAgaWYgKG1hdGNoVmFsdWUocHJvcHMsIGluaXRSb3dba2V5XSwgY29udHJvbFZhbHVlKSkge1xuICAgICAgICAgIGNvbnN0IHJhd0NvdW50ID0gY29udHJvbEVycm9yLmdldChjdHJsKS5jb3VudDtcbiAgICAgICAgICBjb250cm9sRXJyb3Iuc2V0KGN0cmwsIHsga2V5LCBjb3VudDogcmF3Q291bnQgKyAxIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGNvbnRyb2xzXG4gICAgICAgIC5maWx0ZXIob3RoZXJDb250cm9sID0+IG90aGVyQ29udHJvbCAhPT0gY3RybClcbiAgICAgICAgLmZvckVhY2gob3RoZXJDb250cm9sID0+IHtcbiAgICAgICAgICBjb25zdCBvdGhlclZhbHVlID0gZ2V0VmFsdWVJbktleXMob3RoZXJDb250cm9sLnZhbHVlLCBrZXlzLCBtYXBGbik7XG4gICAgICAgICAgaWYgKG1hdGNoZXNGbihwcm9wcywgY29udHJvbFZhbHVlW2tleV0sIG90aGVyVmFsdWVba2V5XSkpIHtcbiAgICAgICAgICAgIGNvbnN0IHJhd0NvdW50ID0gY29udHJvbEVycm9yLmdldChjdHJsKS5jb3VudDtcbiAgICAgICAgICAgIGNvbnRyb2xFcnJvci5zZXQoY3RybCwgeyBrZXksIGNvdW50OiByYXdDb3VudCArIDEgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG4gIGNvbnN0IHRvUmVtb3ZlRXJyb3I6IEFycmF5PHsga2V5OiBzdHJpbmc7IGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCB9PiA9IFtdO1xuICBjb250cm9sRXJyb3IuZm9yRWFjaCgoeyBjb3VudCwga2V5IH0sIGNvbnRyb2wpID0+IHtcbiAgICBpZiAoY291bnQgPT09IDApIHtcbiAgICAgIHRvUmVtb3ZlRXJyb3IucHVzaCh7IGtleSwgY29udHJvbCB9KTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gdG9SZW1vdmVFcnJvcjtcbn1cbiJdfQ==