UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

338 lines 47 kB
import { Location } from '@angular/common'; import { PRIMARY_OUTLET } from '@angular/router'; import { Logging } from '@microsoft/windows-admin-center-sdk/core/diagnostics/logging'; import { EnvironmentModule } from '@microsoft/windows-admin-center-sdk/core/manifest/environment-modules'; import { forkJoin, Observable, of } from 'rxjs'; import { map } from 'rxjs/operators'; /** * Static function name for the navigation title function in a component class */ export const navigationTitleFunctionName = 'navigationTitle'; /** * Navigation class to provide set of static helper functions. */ export class Navigation { /** * Turn off browser history push. * - instead sending all path change to the Shell to create history. */ static turnOffHistory() { if (window.history.pushState !== MsftSme.noop) { Navigation.pushStateBackup = window.history.pushState; Object.defineProperty(window.history, 'pushState', { value: MsftSme.noop }); } } /** * Turn on browser history push. */ static turnOnHistory() { if (Navigation.pushStateBackup && window.history.pushState === MsftSme.noop) { Object.defineProperty(window.history, 'pushState', { value: Navigation.pushStateBackup }); } } /** * Compare two urls by removing leading and trailing slashes. * * @param url1 the url to compare. * @param url2 the url to compare. * @return boolean true if matches. null url returns false. */ static areEqualUrl(url1, url2) { if (url1 == null || url2 == null) { return false; } return Navigation.trimSlash(url1) === Navigation.trimSlash(url2); } /** * Compare two urls for number of segments. * * @param url1 the url to compare. * @param url2 the url to compare. * @param count the number of segments to compare. * @return boolean true if matches for number of segments. */ static areEqualSegments(url1, url2, count) { if (url1 == null || url2 == null) { return false; } const segments1 = Navigation.trimSlash(url1).split('/'); const segments2 = Navigation.trimSlash(url2).split('/'); if (segments1.length < count || segments2.length < count) { return false; } for (let i = 0; i < count; i++) { if (segments1[i] !== segments2[i]) { return false; } } return true; } /** * Trim leading and trailing slashes. * * @param url the url to trim leading and trailing slashes. * @returns the updated url. */ static trimSlash(url) { if (url == null) { return url; } if (url.length > 0 && url[0] === '/') { url = url.substring(1); } if (url.length > 0 && url[url.length - 1] === '/') { url = url.substring(0, url.length - 1); } return url; } /** * Get url segments combined module name and path of entry point. * * @param moduleName the module name. * @param entryPointName the name of entry point. * @return the url segments. */ static getModuleEntryPointUrlSegment(moduleName, entryPointName) { return `${moduleName}!${entryPointName}`; } /** * Builds selectable paths from the given route. * * @param appContextService The application context service object. * @param route The route to extract the breadcrumb for * @param pathPrefix The prefix to prepend to the route path * @return SelectablePath[] the selectable paths. */ static buildSelectablePathsForRoute(appContextService, route, pathPrefix) { const asyncArray = []; const childrenQueue = route.children.slice(0); pathPrefix = pathPrefix ? pathPrefix : ''; while (childrenQueue.length > 0) { // we are only interested in primary routes that have a displayName at this time const child = childrenQueue.shift(); if (child.outlet === PRIMARY_OUTLET) { // append the routes URL segment const segmentPath = child.url .filter(seg1 => seg1 && seg1.path && seg1.path.length > 0) .map(seg2 => seg2.path) .join('/'); if (segmentPath) { // only add a segment if there's any valuable information to it. pathPrefix = Location.joinWithSlash(pathPrefix, segmentPath); } let result = null; if (child.component && child.component[navigationTitleFunctionName]) { // the label can be null to indicate if it's home page access. result = child.component[navigationTitleFunctionName](appContextService, child); if (result) { if (result instanceof Observable) { // observable query. asyncArray.push(result); } else if (typeof result === 'object') { // returned as array. const paths = result; asyncArray.push(of(paths)); } else if (typeof result === 'string') { // returned as string. const selectablePath = { label: result, path: pathPrefix }; asyncArray.push(of([selectablePath])); } else { const message = MsftSme.getStrings() .MsftSmeShell.Angular.Navigation.NavigationTitleReturnTypeError.message; throw new Error(message); } } } } // continue building recursively child.children.forEach(grandChild => { if (grandChild.outlet === PRIMARY_OUTLET) { childrenQueue.push(grandChild); } }); } return forkJoin(asyncArray).pipe(map(resultArray => { const result = []; resultArray.forEach((items, index, array) => { items.forEach(item => { result.push(item); }); }); return result; })); } /** * Navigate to the connection. * * @param router the router. * @param connection the connection object. */ static navigateConnection(router, connection) { const typeInfo = EnvironmentModule.getConnectionTypeInfo(connection.type); const moduleEntrySegment = Navigation.getModuleEntryPointUrlSegment(typeInfo.solution.parentModule.name, typeInfo.solution.name); const rootEntrySegment = Navigation.getModuleEntryPointUrlSegment(typeInfo.solution.parentModule.name, typeInfo.solution.tools.defaultTool); const pathSegments = ['solutions', moduleEntrySegment, 'tools', rootEntrySegment]; return router.navigate(pathSegments); } /** * Get navigation URL by solution/name, module/name, connection/name and connection/type. * * (ex. * - / * - /msft.sme.server-manager!servers * - /msft.sme.server-manager!servers/tools/msft.sme.server-manager!overview * - /msft.sme.server-manager!servers + * /connections/msft.sme.connection-type.server/sme-full1.redmond.corp.microsoft.com + * /tools/msft.sme.server-manager!overview) * @param data the RPC shell navigate data. * @return string the url to navigate to the tool. */ static getNavigationUrlForToolEntryPoint(data) { if (data.navigateNext) { return data.navigateNext; } if (data.settings) { let settingsUrl = `/settings`; if (data.settings.name) { settingsUrl += `/${data.settings.name}`; } if (data.settings.nestedUrlAndOptions) { settingsUrl += data.settings.nestedUrlAndOptions; } return settingsUrl; } else if (!data.solution || !data.solution.moduleName) { // no solution goes to root (homepage) return '/'; } else if (!data.solution.entryPointName) { // it requires entryPointName. Logging.logError('navigation', 'Argument error: entryPointName of the solution is required.'); return null; } let url = `/${data.solution.moduleName}!${data.solution.entryPointName}`; if (data.connection) { if (!data.connection.name || !data.connection.type) { // connection list for empty connection like 'data.connection === {}' url += '/connections'; return url; } url += `/connections/${data.connection.type}/${data.connection.name}`; } // allow to navigate inside of solution just by tool name, so data.connection == null is expected. if (data.tool) { if (data.tool.moduleName && !data.tool.entryPointName) { // it requires entryPointName. Logging.logError('navigation', 'Argument error: entryPointName of the tool is required.'); return null; } url += `/tools/${data.tool.moduleName}!${data.tool.entryPointName}`; } else if (data.connectionSettings) { url += '/tools/settings'; if (data.connectionSettings.tabUrlName) { url += `/${data.connectionSettings.tabUrlName}`; } } if (data.toolNestedUrlAndOptions) { url += data.toolNestedUrlAndOptions; } return url; } /** * Get navigation extra data from current activated route on shell. * * @param route the activated route. */ static getUrlNavigationDataExtras(route) { const snapshot = route.snapshot; const fragment = snapshot.queryParamMap.get('fragment'); let queryParams = null; try { const query = snapshot.queryParamMap.get('queryParams'); if (query) { queryParams = JSON.parse(query); } } catch { } return { fragment, queryParams }; } /** * Get the navigation data from the path on module. * * @param router the Router object. * @param path The path URI with module. */ static getUrlNavigationData(router, path) { const urlTree = router.parseUrl(path); const options = { fragment: urlTree.fragment, queryParams: urlTree.queryParams }; urlTree.fragment = null; urlTree.queryParams = {}; const rootPath = urlTree.toString(); const rootPathTrimmed = Navigation.trimSlash(rootPath); const commands = rootPathTrimmed === '' ? [''] : rootPathTrimmed.split('/'); for (let index = 0; index < commands.length; index++) { // decodeURI to passing parameters to module path. commands[index] = decodeURI(commands[index]); } return { commands, options }; } /** * Get the navigation queryParams on shell/module. * * @param dataExtras The navigation data extras object. * @returns the params data for router navigation call. */ static getUrlQueryParams(dataExtras) { const params = {}; if (dataExtras.fragment) { params.fragment = dataExtras.fragment; } if (dataExtras.queryParams && Object.keys(dataExtras.queryParams).length > 0) { params.queryParams = JSON.stringify(dataExtras.queryParams); } return params; } /** * Get serialized the data extras object into url string. * * @param options the navigation data extras object. * @returns the URL string. */ static getUrlSerializedDataExtras(options) { let extra = ''; if (options.queryParams) { let keys = Object.keys(options.queryParams); keys = keys.sort(); keys.forEach((key, index) => extra += `${index === 0 ? '?' : '&'}${key}=${options.queryParams[key]}`); } if (options.fragment) { extra += `#${options.fragment}`; } return extra; } } /** * The url options for gateway and connection. */ Navigation.gatewayUrl = 'gatewayUrl'; /** * The url options for version of static content. */ Navigation.staticVersion = 'staticVersion'; Navigation.pushStateBackup = null; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF2aWdhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL2FuZ3VsYXIvc3JjL3NlcnZpY2UvbmF2aWdhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUFrRCxjQUFjLEVBQVUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6RyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sOERBQThELENBQUM7QUFDdkYsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUVBQXVFLENBQUM7QUFJMUcsT0FBTyxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ2hELE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQWtDckM7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSwyQkFBMkIsR0FBRyxpQkFBaUIsQ0FBQztBQWM3RDs7R0FFRztBQUNILE1BQU0sT0FBTyxVQUFVO0lBYW5COzs7T0FHRztJQUNJLE1BQU0sQ0FBQyxjQUFjO1FBQ3hCLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEtBQUssT0FBTyxDQUFDLElBQUksRUFBRTtZQUMzQyxVQUFVLENBQUMsZUFBZSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDO1lBQ3RELE1BQU0sQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxXQUFXLEVBQUU7Z0JBQy9DLEtBQUssRUFBRSxPQUFPLENBQUMsSUFBSTthQUN0QixDQUFDLENBQUM7U0FDTjtJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNJLE1BQU0sQ0FBQyxhQUFhO1FBQ3ZCLElBQUksVUFBVSxDQUFDLGVBQWUsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLFNBQVMsS0FBSyxPQUFPLENBQUMsSUFBSSxFQUFFO1lBQ3pFLE1B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SSxNQUFNLENBQUMsMEJBQTBCLENBQUMsT0FBNkI7UUFDbEUsSUFBSSxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ2YsSUFBSSxPQUFPLENBQUMsV0FBVyxFQUFFO1lBQ3JCLElBQUksSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQzVDLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbkIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssSUFBSSxHQUFHLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLEdBQUcsSUFBSSxPQUFPLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztTQUN6RztRQUVELElBQUksT0FBTyxDQUFDLFFBQVEsRUFBRTtZQUNsQixLQUFLLElBQUksSUFBSSxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUM7U0FDbkM7UUFFRCxPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDOztBQXpXRDs7R0FFRztBQUNXLHFCQUFVLEdBQUcsWUFBWSxDQUFDO0FBRXhDOztHQUVHO0FBQ1csd0JBQWEsR0FBRyxlQUFlLENBQUM7QUFFL0IsMEJBQWUsR0FBUSxJQUFJLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBMb2NhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlLCBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90LCBQYXJhbXMsIFBSSU1BUllfT1VUTEVULCBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xyXG5pbXBvcnQgeyBMb2dnaW5nIH0gZnJvbSAnQG1pY3Jvc29mdC93aW5kb3dzLWFkbWluLWNlbnRlci1zZGsvY29yZS9kaWFnbm9zdGljcy9sb2dnaW5nJztcclxuaW1wb3J0IHsgRW52aXJvbm1lbnRNb2R1bGUgfSBmcm9tICdAbWljcm9zb2Z0L3dpbmRvd3MtYWRtaW4tY2VudGVyLXNkay9jb3JlL21hbmlmZXN0L2Vudmlyb25tZW50LW1vZHVsZXMnO1xyXG5pbXBvcnQgeyBTZWxlY3RhYmxlUGF0aCB9IGZyb20gJ0BtaWNyb3NvZnQvd2luZG93cy1hZG1pbi1jZW50ZXItc2RrL2NvcmUvcnBjL3JlcG9ydC9ycGMtcmVwb3J0LW1vZGVsJztcclxuaW1wb3J0IHsgUnBjU2hlbGxOYXZpZ2F0ZSB9IGZyb20gJ0BtaWNyb3NvZnQvd2luZG93cy1hZG1pbi1jZW50ZXItc2RrL2NvcmUvcnBjL3NoZWxsLW5hdmlnYXRlL3JwYy1zaGVsbC1uYXZpZ2F0ZS1tb2RlbCc7XHJcbmltcG9ydCB7IENvbm5lY3Rpb24gfSBmcm9tICdAbWljcm9zb2Z0L3dpbmRvd3MtYWRtaW4tY2VudGVyLXNkay9jb3JlL3NlY3VyaXR5L2Nvbm5lY3Rpb24nO1xyXG5pbXBvcnQgeyBmb3JrSm9pbiwgT2JzZXJ2YWJsZSwgb2YgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgeyBTdHJpbmdzIH0gZnJvbSAnLi4vZ2VuZXJhdGVkL3N0cmluZ3MnO1xyXG5pbXBvcnQgeyBBcHBDb250ZXh0U2VydmljZSB9IGZyb20gJy4vYXBwLWNvbnRleHQuc2VydmljZSc7XHJcblxyXG4vKipcclxuICogVGhlIG5hdmlnYXRpb24gZGF0YSBleHRyYSBmb3IgaG9sZGluZyBmcmFnZW1lbnQgcGFyYW1ldGVyIGFuZCBxdWVyeVBhcmFtcyBmb3IgbW9kdWxlIHVybC5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgTmF2aWdhdGlvbkRhdGFFeHRyYXMge1xyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgZnJhZ21lbnQgc3RyaW5nIGZvciBtb2R1bGUgaWYgYW55LlxyXG4gICAgICovXHJcbiAgICBmcmFnbWVudD86IHN0cmluZztcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBxdWVyeSBwYXJhbWV0ZXJzIGZvciBtb2R1bGUgaWYgYW55LlxyXG4gICAgICovXHJcbiAgICBxdWVyeVBhcmFtcz86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBUaGUgbmF2aWdhdGlvbiBkYXRhIHRvIG5hdmlnYXRlIGluc2lkZSBvZiBtb2R1bGUuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIE5hdmlnYXRpb25EYXRhIHtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIG5hdmlnYXRpb24gY29tbWFuZHMgKHBhdGggc2VnbWVudHMpLlxyXG4gICAgICovXHJcbiAgICBjb21tYW5kczogc3RyaW5nW107XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgbmF2aWdhdGlvbiBkYXRhIGV4dHJhcyBmb3IgbW9kdWxlLlxyXG4gICAgICovXHJcbiAgICBvcHRpb25zOiBOYXZpZ2F0aW9uRGF0YUV4dHJhcztcclxufVxyXG5cclxuLyoqXHJcbiAqIFN0YXRpYyBmdW5jdGlvbiBuYW1lIGZvciB0aGUgbmF2aWdhdGlvbiB0aXRsZSBmdW5jdGlvbiBpbiBhIGNvbXBvbmVudCBjbGFzc1xyXG4gKi9cclxuZXhwb3J0IGNvbnN0IG5hdmlnYXRpb25UaXRsZUZ1bmN0aW9uTmFtZSA9ICduYXZpZ2F0aW9uVGl0bGUnO1xyXG5cclxuLyoqXHJcbiAqIE5hdmlnYXRpb24gVGl0bGUgRnVuY3Rpb24gUmV0dXJuIHR5cGVcclxuICovXHJcbmV4cG9ydCB0eXBlIE5hdmlnYXRpb25UaXRsZSA9IHN0cmluZyB8IFNlbGVjdGFibGVQYXRoW10gfCBPYnNlcnZhYmxlPFNlbGVjdGFibGVQYXRoW10+O1xyXG5cclxuLyoqXHJcbiAqIENhbGxiYWNrIGZvciBkYXRhLnRpdGxlIHByb3BlcnR5IGluIHJvdXRlciBjb25maWd1cmF0aW9uLlxyXG4gKi9cclxuaW50ZXJmYWNlIE5hdmlnYXRpb25UaXRsZURhdGEge1xyXG4gICAgdGl0bGU6IHN0cmluZyB8ICgoYXBwQ29udGV4dFNlcnZpY2U6IEFwcENvbnRleHRTZXJ2aWNlLCBjaGlsZFJvdXRlcjogQWN0aXZhdGVkUm91dGVTbmFwc2hvdCkgPT4gc3RyaW5nIHwgU2VsZWN0YWJsZVBhdGhbXSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBOYXZpZ2F0aW9uIGNsYXNzIHRvIHByb3ZpZGUgc2V0IG9mIHN0YXRpYyBoZWxwZXIgZnVuY3Rpb25zLlxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIE5hdmlnYXRpb24ge1xyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgdXJsIG9wdGlvbnMgZm9yIGdhdGV3YXkgYW5kIGNvbm5lY3Rpb24uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgZ2F0ZXdheVVybCA9ICdnYXRld2F5VXJsJztcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSB1cmwgb3B0aW9ucyBmb3IgdmVyc2lvbiBvZiBzdGF0aWMgY29udGVudC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBzdGF0aWNWZXJzaW9uID0gJ3N0YXRpY1ZlcnNpb24nO1xyXG5cclxuICAgIHByaXZhdGUgc3RhdGljIHB1c2hTdGF0ZUJhY2t1cDogYW55ID0gbnVsbDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFR1cm4gb2ZmIGJyb3dzZXIgaGlzdG9yeSBwdXNoLlxyXG4gICAgICogLSBpbnN0ZWFkIHNlbmRpbmcgYWxsIHBhdGggY2hhbmdlIHRvIHRoZSBTaGVsbCB0byBjcmVhdGUgaGlzdG9yeS5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyB0dXJuT2ZmSGlzdG9yeSgpOiB2b2lkIHtcclxuICAgICAgICBpZiAod2luZG93Lmhpc3RvcnkucHVzaFN0YXRlICE9PSBNc2Z0U21lLm5vb3ApIHtcclxuICAgICAgICAgICAgTmF2aWdhdGlvbi5wdXNoU3RhdGVCYWNrdXAgPSB3aW5kb3cuaGlzdG9yeS5wdXNoU3RhdGU7XHJcbiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3aW5kb3cuaGlzdG9yeSwgJ3B1c2hTdGF0ZScsIHtcclxuICAgICAgICAgICAgICAgIHZhbHVlOiBNc2Z0U21lLm5vb3BcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVHVybiBvbiBicm93c2VyIGhpc3RvcnkgcHVzaC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyB0dXJuT25IaXN0b3J5KCk6IHZvaWQge1xyXG4gICAgICAgIGlmIChOYXZpZ2F0aW9uLnB1c2hTdGF0ZUJhY2t1cCAmJiB3aW5kb3cuaGlzdG9yeS5wdXNoU3RhdGUgPT09IE1zZnRTbWUubm9vcCkge1xyXG4gICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93Lmhpc3RvcnksICdwdXNoU3RhdGUnLCB7XHJcbiAgICAgICAgICAgICAgICB2YWx1ZTogTmF2aWdhdGlvbi5wdXNoU3RhdGVCYWNrdXBcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ29tcGFyZSB0d28gdXJscyBieSByZW1vdmluZyBsZWFkaW5nIGFuZCB0cmFpbGluZyBzbGFzaGVzLlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB1cmwxIHRoZSB1cmwgdG8gY29tcGFyZS5cclxuICAgICAqIEBwYXJhbSB1cmwyIHRoZSB1cmwgdG8gY29tcGFyZS5cclxuICAgICAqIEByZXR1cm4gYm9vbGVhbiB0cnVlIGlmIG1hdGNoZXMuIG51bGwgdXJsIHJldHVybnMgZmFsc2UuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgYXJlRXF1YWxVcmwodXJsMTogc3RyaW5nLCB1cmwyOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgICAgICBpZiAodXJsMSA9PSBudWxsIHx8IHVybDIgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gTmF2aWdhdGlvbi50cmltU2xhc2godXJsMSkgPT09IE5hdmlnYXRpb24udHJpbVNsYXNoKHVybDIpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ29tcGFyZSB0d28gdXJscyBmb3IgbnVtYmVyIG9mIHNlZ21lbnRzLlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB1cmwxIHRoZSB1cmwgdG8gY29tcGFyZS5cclxuICAgICAqIEBwYXJhbSB1cmwyIHRoZSB1cmwgdG8gY29tcGFyZS5cclxuICAgICAqIEBwYXJhbSBjb3VudCB0aGUgbnVtYmVyIG9mIHNlZ21lbnRzIHRvIGNvbXBhcmUuXHJcbiAgICAgKiBAcmV0dXJuIGJvb2xlYW4gdHJ1ZSBpZiBtYXRjaGVzIGZvciBudW1iZXIgb2Ygc2VnbWVudHMuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgYXJlRXF1YWxTZWdtZW50cyh1cmwxOiBzdHJpbmcsIHVybDI6IHN0cmluZywgY291bnQ6IG51bWJlcik6IGJvb2xlYW4ge1xyXG4gICAgICAgIGlmICh1cmwxID09IG51bGwgfHwgdXJsMiA9PSBudWxsKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHNlZ21lbnRzMSA9IE5hdmlnYXRpb24udHJpbVNsYXNoKHVybDEpLnNwbGl0KCcvJyk7XHJcbiAgICAgICAgY29uc3Qgc2VnbWVudHMyID0gTmF2aWdhdGlvbi50cmltU2xhc2godXJsMikuc3BsaXQoJy8nKTtcclxuXHJcbiAgICAgICAgaWYgKHNlZ21lbnRzMS5sZW5ndGggPCBjb3VudCB8fCBzZWdtZW50czIubGVuZ3RoIDwgY291bnQpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmIChzZWdtZW50czFbaV0gIT09IHNlZ21lbnRzMltpXSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRyaW0gbGVhZGluZyBhbmQgdHJhaWxpbmcgc2xhc2hlcy5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gdXJsIHRoZSB1cmwgdG8gdHJpbSBsZWFkaW5nIGFuZCB0cmFpbGluZyBzbGFzaGVzLlxyXG4gICAgICogQHJldHVybnMgdGhlIHVwZGF0ZWQgdXJsLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHN0YXRpYyB0cmltU2xhc2godXJsOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIGlmICh1cmwgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICByZXR1cm4gdXJsO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHVybC5sZW5ndGggPiAwICYmIHVybFswXSA9PT0gJy8nKSB7XHJcbiAgICAgICAgICAgIHVybCA9IHVybC5zdWJzdHJpbmcoMSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodXJsLmxlbmd0aCA+IDAgJiYgdXJsW3VybC5sZW5ndGggLSAxXSA9PT0gJy8nKSB7XHJcbiAgICAgICAgICAgIHVybCA9IHVybC5zdWJzdHJpbmcoMCwgdXJsLmxlbmd0aCAtIDEpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHVybDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdldCB1cmwgc2VnbWVudHMgY29tYmluZWQgbW9kdWxlIG5hbWUgYW5kIHBhdGggb2YgZW50cnkgcG9pbnQuXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIG1vZHVsZU5hbWUgdGhlIG1vZHVsZSBuYW1lLlxyXG4gICAgICogQHBhcmFtIGVudHJ5UG9pbnROYW1lIHRoZSBuYW1lIG9mIGVudHJ5IHBvaW50LlxyXG4gICAgICogQHJldHVybiB0aGUgdXJsIHNlZ21lbnRzLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIGdldE1vZHVsZUVudHJ5UG9pbnRVcmxTZWdtZW50KG1vZHVsZU5hbWU6IHN0cmluZywgZW50cnlQb2ludE5hbWU/OiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgICAgIHJldHVybiBgJHttb2R1bGVOYW1lfSEke2VudHJ5UG9pbnROYW1lfWA7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBCdWlsZHMgc2VsZWN0YWJsZSBwYXRocyBmcm9tIHRoZSBnaXZlbiByb3V0ZS5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gYXBwQ29udGV4dFNlcnZpY2UgVGhlIGFwcGxpY2F0aW9uIGNvbnRleHQgc2VydmljZSBvYmplY3QuXHJcbiAgICAgKiBAcGFyYW0gcm91dGUgVGhlIHJvdXRlIHRvIGV4dHJhY3QgdGhlIGJyZWFkY3J1bWIgZm9yXHJcbiAgICAgKiBAcGFyYW0gcGF0aFByZWZpeCBUaGUgcHJlZml4IHRvIHByZXBlbmQgdG8gdGhlIHJvdXRlIHBhdGhcclxuICAgICAqIEByZXR1cm4gU2VsZWN0YWJsZVBhdGhbXSB0aGUgc2VsZWN0YWJsZSBwYXRocy5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBidWlsZFNlbGVjdGFibGVQYXRoc0ZvclJvdXRlKFxyXG4gICAgICAgIGFwcENvbnRleHRTZXJ2aWNlOiBBcHBDb250ZXh0U2VydmljZSxcclxuICAgICAgICByb3V0ZTogQWN0aXZhdGVkUm91dGVTbmFwc2hvdCxcclxuICAgICAgICBwYXRoUHJlZml4Pzogc3RyaW5nKTogT2JzZXJ2YWJsZTxTZWxlY3RhYmxlUGF0aFtdPiB7XHJcbiAgICAgICAgY29uc3QgYXN5bmNBcnJheTogT2JzZXJ2YWJsZTxTZWxlY3RhYmxlUGF0aFtdPltdID0gW107XHJcbiAgICAgICAgY29uc3QgY2hpbGRyZW5RdWV1ZSA9IHJvdXRlLmNoaWxkcmVuLnNsaWNlKDApO1xyXG4gICAgICAgIHBhdGhQcmVmaXggPSBwYXRoUHJlZml4ID8gcGF0aFByZWZpeCA6ICcnO1xyXG5cclxuICAgICAgICB3aGlsZSAoY2hpbGRyZW5RdWV1ZS5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIC8vIHdlIGFyZSBvbmx5IGludGVyZXN0ZWQgaW4gcHJpbWFyeSByb3V0ZXMgdGhhdCBoYXZlIGEgZGlzcGxheU5hbWUgYXQgdGhpcyB0aW1lXHJcbiAgICAgICAgICAgIGNvbnN0IGNoaWxkID0gY2hpbGRyZW5RdWV1ZS5zaGlmdCgpO1xyXG4gICAgICAgICAgICBpZiAoY2hpbGQub3V0bGV0ID09PSBQUklNQVJZX09VVExFVCkge1xyXG4gICAgICAgICAgICAgICAgLy8gYXBwZW5kIHRoZSByb3V0ZXMgVVJMIHNlZ21lbnRcclxuICAgICAgICAgICAgICAgIGNvbnN0IHNlZ21lbnRQYXRoID0gY2hpbGQudXJsXHJcbiAgICAgICAgICAgICAgICAgICAgLmZpbHRlcihzZWcxID0+IHNlZzEgJiYgc2VnMS5wYXRoICYmIHNlZzEucGF0aC5sZW5ndGggPiAwKVxyXG4gICAgICAgICAgICAgICAgICAgIC5tYXAoc2VnMiA9PiBzZWcyLnBhdGgpXHJcbiAgICAgICAgICAgICAgICAgICAgLmpvaW4oJy8nKTtcclxuICAgICAgICAgICAgICAgIGlmIChzZWdtZW50UGF0aCkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIG9ubHkgYWRkIGEgc2VnbWVudCBpZiB0aGVyZSdzIGFueSB2YWx1YWJsZSBpbmZvcm1hdGlvbiB0byBpdC5cclxuICAgICAgICAgICAgICAgICAgICBwYXRoUHJlZml4ID0gTG9jYXRpb24uam9pbldpdGhTbGFzaChwYXRoUHJlZml4LCBzZWdtZW50UGF0aCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgbGV0IHJlc3VsdDogTmF2aWdhdGlvblRpdGxlID0gbnVsbDtcclxuICAgICAgICAgICAgICAgIGlmIChjaGlsZC5jb21wb25lbnQgJiYgY2hpbGQuY29tcG9uZW50W25hdmlnYXRpb25UaXRsZUZ1bmN0aW9uTmFtZV0pIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgbGFiZWwgY2FuIGJlIG51bGwgdG8gaW5kaWNhdGUgaWYgaXQncyBob21lIHBhZ2UgYWNjZXNzLlxyXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGNoaWxkLmNvbXBvbmVudFtuYXZpZ2F0aW9uVGl0bGVGdW5jdGlvbk5hbWVdKGFwcENvbnRleHRTZXJ2aWNlLCBjaGlsZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgT2JzZXJ2YWJsZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb2JzZXJ2YWJsZSBxdWVyeS5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzeW5jQXJyYXkucHVzaChyZXN1bHQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiByZXN1bHQgPT09ICdvYmplY3QnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyByZXR1cm5lZCBhcyBhcnJheS5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhdGhzOiBTZWxlY3RhYmxlUGF0aFtdID0gcmVzdWx0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXN5bmNBcnJheS5wdXNoKG9mKHBhdGhzKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHJlc3VsdCA9PT0gJ3N0cmluZycpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJldHVybmVkIGFzIHN0cmluZy5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNlbGVjdGFibGVQYXRoOiBTZWxlY3RhYmxlUGF0aCA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbDogcmVzdWx0LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGg6IHBhdGhQcmVmaXhcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3luY0FycmF5LnB1c2gob2YoW3NlbGVjdGFibGVQYXRoXSkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWVzc2FnZSA9IE1zZnRTbWUuZ2V0U3RyaW5nczxTdHJpbmdzPigpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLk1zZnRTbWVTaGVsbC5Bbmd1bGFyLk5hdmlnYXRpb24uTmF2aWdhdGlvblRpdGxlUmV0dXJuVHlwZUVycm9yLm1lc3NhZ2U7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIGNvbnRpbnVlIGJ1aWxkaW5nIHJlY3Vyc2l2ZWx5XHJcbiAgICAgICAgICAgIGNoaWxkLmNoaWxkcmVuLmZvckVhY2goZ3JhbmRDaGlsZCA9PiB7XHJcbiAgICAgICAgICAgICAgICBpZiAoZ3JhbmRDaGlsZC5vdXRsZXQgPT09IFBSSU1BUllfT1VUTEVUKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW5RdWV1ZS5wdXNoKGdyYW5kQ2hpbGQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBmb3JrSm9pbihhc3luY0FycmF5KS5waXBlKG1hcChyZXN1bHRBcnJheSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdDogU2VsZWN0YWJsZVBhdGhbXSA9IFtdO1xyXG4gICAgICAgICAgICByZXN1bHRBcnJheS5mb3JFYWNoKChpdGVtcywgaW5kZXgsIGFycmF5KSA9PiB7XHJcbiAgICAgICAgICAgICAgICBpdGVtcy5mb3JFYWNoKGl0ZW0gPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKGl0ZW0pO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICAgIH0pKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE5hdmlnYXRlIHRvIHRoZSBjb25uZWN0aW9uLlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSByb3V0ZXIgdGhlIHJvdXRlci5cclxuICAgICAqIEBwYXJhbSBjb25uZWN0aW9uIHRoZSBjb25uZWN0aW9uIG9iamVjdC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBuYXZpZ2F0ZUNvbm5lY3Rpb24ocm91dGVyOiBSb3V0ZXIsIGNvbm5lY3Rpb246IENvbm5lY3Rpb24pOiBQcm9taXNlPGJvb2xlYW4+IHtcclxuICAgICAgICBjb25zdCB0eXBlSW5mbyA9IEVudmlyb25tZW50TW9kdWxlLmdldENvbm5lY3Rpb25UeXBlSW5mbyhjb25uZWN0aW9uLnR5cGUpO1xyXG4gICAgICAgIGNvbnN0IG1vZHVsZUVudHJ5U2VnbWVudCA9IE5hdmlnYXRpb24uZ2V0TW9kdWxlRW50cnlQb2ludFVybFNlZ21lbnQodHlwZUluZm8uc29sdXRpb24ucGFyZW50TW9kdWxlLm5hbWUsIHR5cGVJbmZvLnNvbHV0aW9uLm5hbWUpO1xyXG4gICAgICAgIGNvbnN0IHJvb3RFbnRyeVNlZ21lbnQgPSBOYXZpZ2F0aW9uLmdldE1vZHVsZUVudHJ5UG9pbnRVcmxTZWdtZW50KFxyXG4gICAgICAgICAgICB0eXBlSW5mby5zb2x1dGlvbi5wYXJlbnRNb2R1bGUubmFtZSwgdHlwZUluZm8uc29sdXRpb24udG9vbHMuZGVmYXVsdFRvb2wpO1xyXG4gICAgICAgIGNvbnN0IHBhdGhTZWdtZW50czogc3RyaW5nW10gPSBbJ3NvbHV0aW9ucycsIG1vZHVsZUVudHJ5U2VnbWVudCwgJ3Rvb2xzJywgcm9vdEVudHJ5U2VnbWVudF07XHJcbiAgICAgICAgcmV0dXJuIHJvdXRlci5uYXZpZ2F0ZShwYXRoU2VnbWVudHMpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0IG5hdmlnYXRpb24gVVJMIGJ5IHNvbHV0aW9uL25hbWUsIG1vZHVsZS9uYW1lLCBjb25uZWN0aW9uL25hbWUgYW5kIGNvbm5lY3Rpb24vdHlwZS5cclxuICAgICAqXHJcbiAgICAgKiAoZXguXHJcbiAgICAgKiAgICAtIC9cclxuICAgICAqICAgIC0gL21zZnQuc21lLnNlcnZlci1tYW5hZ2VyIXNlcnZlcnNcclxuICAgICAqICAgIC0gL21zZnQuc21lLnNlcnZlci1tYW5hZ2VyIXNlcnZlcnMvdG9vbHMvbXNmdC5zbWUuc2VydmVyLW1hbmFnZXIhb3ZlcnZpZXdcclxuICAgICAqICAgIC0gL21zZnQuc21lLnNlcnZlci1tYW5hZ2VyIXNlcnZlcnMgK1xyXG4gICAgICogICAgICAgICAgL2Nvbm5lY3Rpb25zL21zZnQuc21lLmNvbm5lY3Rpb24tdHlwZS5zZXJ2ZXIvc21lLWZ1bGwxLnJlZG1vbmQuY29ycC5taWNyb3NvZnQuY29tICtcclxuICAgICAqICAgICAgICAgIC90b29scy9tc2Z0LnNtZS5zZXJ2ZXItbWFuYWdlciFvdmVydmlldylcclxuICAgICAqIEBwYXJhbSBkYXRhIHRoZSBSUEMgc2hlbGwgbmF2aWdhdGUgZGF0YS5cclxuICAgICAqIEByZXR1cm4gc3RyaW5nIHRoZSB1cmwgdG8gbmF2aWdhdGUgdG8gdGhlIHRvb2wuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgZ2V0TmF2aWdhdGlvblVybEZvclRvb2xFbnRyeVBvaW50KGRhdGE6IFJwY1NoZWxsTmF2aWdhdGUpOiBzdHJpbmcge1xyXG4gICAgICAgIGlmIChkYXRhLm5hdmlnYXRlTmV4dCkge1xyXG4gICAgICAgICAgICByZXR1cm4gZGF0YS5uYXZpZ2F0ZU5leHQ7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoZGF0YS5zZXR0aW5ncykge1xyXG4gICAgICAgICAgICBsZXQgc2V0dGluZ3NVcmwgPSBgL3NldHRpbmdzYDtcclxuICAgICAgICAgICAgaWYgKGRhdGEuc2V0dGluZ3MubmFtZSkge1xyXG4gICAgICAgICAgICAgICAgc2V0dGluZ3NVcmwgKz0gYC8ke2RhdGEuc2V0dGluZ3MubmFtZX1gO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoZGF0YS5zZXR0aW5ncy5uZXN0ZWRVcmxBbmRPcHRpb25zKSB7XHJcbiAgICAgICAgICAgICAgICBzZXR0aW5nc1VybCArPSBkYXRhLnNldHRpbmdzLm5lc3RlZFVybEFuZE9wdGlvbnM7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHJldHVybiBzZXR0aW5nc1VybDtcclxuICAgICAgICB9IGVsc2UgaWYgKCFkYXRhLnNvbHV0aW9uIHx8ICFkYXRhLnNvbHV0aW9uLm1vZHVsZU5hbWUpIHtcclxuICAgICAgICAgICAgLy8gbm8gc29sdXRpb24gZ29lcyB0byByb290IChob21lcGFnZSlcclxuICAgICAgICAgICAgcmV0dXJuICcvJztcclxuICAgICAgICB9IGVsc2UgaWYgKCFkYXRhLnNvbHV0aW9uLmVudHJ5UG9pbnROYW1lKSB7XHJcbiAgICAgICAgICAgIC8vIGl0IHJlcXVpcmVzIGVudHJ5UG9pbnROYW1lLlxyXG4gICAgICAgICAgICBMb2dnaW5nLmxvZ0Vycm9yKCduYXZpZ2F0aW9uJywgJ0FyZ3VtZW50IGVycm9yOiBlbnRyeVBvaW50TmFtZSBvZiB0aGUgc29sdXRpb24gaXMgcmVxdWlyZWQuJyk7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IHVybCA9IGAvJHtkYXRhLnNvbHV0aW9uLm1vZHVsZU5hbWV9ISR7ZGF0YS5zb2x1dGlvbi5lbnRyeVBvaW50TmFtZX1gO1xyXG4gICAgICAgIGlmIChkYXRhLmNvbm5lY3Rpb24pIHtcclxuICAgICAgICAgICAgaWYgKCFkYXRhLmNvbm5lY3Rpb24ubmFtZSB8fCAhZGF0YS5jb25uZWN0aW9uLnR5cGUpIHtcclxuICAgICAgICAgICAgICAgIC8vIGNvbm5lY3Rpb24gbGlzdCBmb3IgZW1wdHkgY29ubmVjdGlvbiBsaWtlICdkYXRhLmNvbm5lY3Rpb24gPT09IHt9J1xyXG4gICAgICAgICAgICAgICAgdXJsICs9ICcvY29ubmVjdGlvbnMnO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHVybDtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgdXJsICs9IGAvY29ubmVjdGlvbnMvJHtkYXRhLmNvbm5lY3Rpb24udHlwZX0vJHtkYXRhLmNvbm5lY3Rpb24ubmFtZX1gO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gYWxsb3cgdG8gbmF2aWdhdGUgaW5zaWRlIG9mIHNvbHV0aW9uIGp1c3QgYnkgdG9vbCBuYW1lLCBzbyBkYXRhLmNvbm5lY3Rpb24gPT0gbnVsbCBpcyBleHBlY3RlZC5cclxuICAgICAgICBpZiAoZGF0YS50b29sKSB7XHJcbiAgICAgICAgICAgIGlmIChkYXRhLnRvb2wubW9kdWxlTmFtZSAmJiAhZGF0YS50b29sLmVudHJ5UG9pbnROYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBpdCByZXF1aXJlcyBlbnRyeVBvaW50TmFtZS5cclxuICAgICAgICAgICAgICAgIExvZ2dpbmcubG9nRXJyb3IoJ25hdmlnYXRpb24nLCAnQXJndW1lbnQgZXJyb3I6IGVudHJ5UG9pbnROYW1lIG9mIHRoZSB0b29sIGlzIHJlcXVpcmVkLicpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHVybCArPSBgL3Rvb2xzLyR7ZGF0YS50b29sLm1vZHVsZU5hbWV9ISR7ZGF0YS50b29sLmVudHJ5UG9pbnROYW1lfWA7XHJcbiAgICAgICAgfSBlbHNlIGlmIChkYXRhLmNvbm5lY3Rpb25TZXR0aW5ncykge1xyXG4gICAgICAgICAgICB1cmwgKz0gJy90b29scy9zZXR0aW5ncyc7XHJcbiAgICAgICAgICAgIGlmIChkYXRhLmNvbm5lY3Rpb25TZXR0aW5ncy50YWJVcmxOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICB1cmwgKz0gYC8ke2RhdGEuY29ubmVjdGlvblNldHRpbmdzLnRhYlVybE5hbWV9YDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGRhdGEudG9vbE5lc3RlZFVybEFuZE9wdGlvbnMpIHtcclxuICAgICAgICAgICAgdXJsICs9IGRhdGEudG9vbE5lc3RlZFVybEFuZE9wdGlvbnM7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdXJsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0IG5hdmlnYXRpb24gZXh0cmEgZGF0YSBmcm9tIGN1cnJlbnQgYWN0aXZhdGVkIHJvdXRlIG9uIHNoZWxsLlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSByb3V0ZSB0aGUgYWN0aXZhdGVkIHJvdXRlLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIGdldFVybE5hdmlnYXRpb25EYXRhRXh0cmFzKHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSk6IE5hdmlnYXRpb25EYXRhRXh0cmFzIHtcclxuICAgICAgICBjb25zdCBzbmFwc2hvdCA9IHJvdXRlLnNuYXBzaG90O1xyXG4gICAgICAgIGNvbnN0IGZyYWdtZW50ID0gc25hcHNob3QucXVlcnlQYXJhbU1hcC5nZXQoJ2ZyYWdtZW50Jyk7XHJcbiAgICAgICAgbGV0IHF1ZXJ5UGFyYW1zID0gbnVsbDtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBjb25zdCBxdWVyeSA9IHNuYXBzaG90LnF1ZXJ5UGFyYW1NYXAuZ2V0KCdxdWVyeVBhcmFtcycpO1xyXG4gICAgICAgICAgICBpZiAocXVlcnkpIHtcclxuICAgICAgICAgICAgICAgIHF1ZXJ5UGFyYW1zID0gSlNPTi5wYXJzZShxdWVyeSk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgfSBjYXRjaCB7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4geyBmcmFnbWVudCwgcXVlcnlQYXJhbXMgfTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdldCB0aGUgbmF2aWdhdGlvbiBkYXRhIGZyb20gdGhlIHBhdGggb24gbW9kdWxlLlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSByb3V0ZXIgdGhlIFJvdXRlciBvYmplY3QuXHJcbiAgICAgKiBAcGFyYW0gcGF0aCBUaGUgcGF0aCBVUkkgd2l0aCBtb2R1bGUuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgZ2V0VXJsTmF2aWdhdGlvbkRhdGEocm91dGVyOiBSb3V0ZXIsIHBhdGg6IHN0cmluZyk6IE5hdmlnYXRpb25EYXRhIHtcclxuICAgICAgICBjb25zdCB1cmxUcmVlID0gcm91dGVyLnBhcnNlVXJsKHBhdGgpO1xyXG4gICAgICAgIGNvbnN0IG9wdGlvbnM6IE5hdmlnYXRpb25EYXRhRXh0cmFzID0ge1xyXG4gICAgICAgICAgICBmcmFnbWVudDogdXJsVHJlZS5mcmFnbWVudCxcclxuICAgICAgICAgICAgcXVlcnlQYXJhbXM6IHVybFRyZWUucXVlcnlQYXJhbXNcclxuICAgICAgICB9O1xyXG4gICAgICAgIHVybFRyZWUuZnJhZ21lbnQgPSBudWxsO1xyXG4gICAgICAgIHVybFRyZWUucXVlcnlQYXJhbXMgPSB7fTtcclxuICAgICAgICBjb25zdCByb290UGF0aCA9IHVybFRyZWUudG9TdHJpbmcoKTtcclxuICAgICAgICBjb25zdCByb290UGF0aFRyaW1tZWQgPSBOYXZpZ2F0aW9uLnRyaW1TbGFzaChyb290UGF0aCk7XHJcbiAgICAgICAgY29uc3QgY29tbWFuZHM6IHN0cmluZ1tdID0gcm9vdFBhdGhUcmltbWVkID09PSAnJyA/IFsnJ10gOiByb290UGF0aFRyaW1tZWQuc3BsaXQoJy8nKTtcclxuICAgICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgY29tbWFuZHMubGVuZ3RoOyBpbmRleCsrKSB7XHJcbiAgICAgICAgICAgIC8vIGRlY29kZVVSSSB0byBwYXNzaW5nIHBhcmFtZXRlcnMgdG8gbW9kdWxlIHBhdGguXHJcbiAgICAgICAgICAgIGNvbW1hbmRzW2luZGV4XSA9IGRlY29kZVVSSShjb21tYW5kc1tpbmRleF0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHsgY29tbWFuZHMsIG9wdGlvbnMgfTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdldCB0aGUgbmF2aWdhdGlvbiBxdWVyeVBhcmFtcyBvbiBzaGVsbC9tb2R1bGUuXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIGRhdGFFeHRyYXMgVGhlIG5hdmlnYXRpb24gZGF0YSBleHRyYXMgb2JqZWN0LlxyXG4gICAgICogQHJldHVybnMgdGhlIHBhcmFtcyBkYXRhIGZvciByb3V0ZXIgbmF2aWdhdGlvbiBjYWxsLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIGdldFVybFF1ZXJ5UGFyYW1zKGRhdGFFeHRyYXM6IE5hdmlnYXRpb25EYXRhRXh0cmFzKTogUGFyYW1zIHtcclxuICAgICAgICBjb25zdCBwYXJhbXM6IFBhcmFtcyA9IHt9O1xyXG4gICAgICAgIGlmIChkYXRhRXh0cmFzLmZyYWdtZW50KSB7XHJcbiAgICAgICAgICAgIHBhcmFtcy5mcmFnbWVudCA9IGRhdGFFeHRyYXMuZnJhZ21lbnQ7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoZGF0YUV4dHJhcy5xdWVyeVBhcmFtcyAmJiBPYmplY3Qua2V5cyhkYXRhRXh0cmFzLnF1ZXJ5UGFyYW1zKS5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIHBhcmFtcy5xdWVyeVBhcmFtcyA9IEpTT04uc3RyaW5naWZ5KGRhdGFFeHRyYXMucXVlcnlQYXJhbXMpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHBhcmFtcztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdldCBzZXJpYWxpemVkIHRoZSBkYXRhIGV4dHJhcyBvYmplY3QgaW50byB1cmwgc3RyaW5nLlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSBvcHRpb25zIHRoZSBuYXZpZ2F0aW9uIGRhdGEgZXh0cmFzIG9iamVjdC5cclxuICAgICAqIEByZXR1cm5zIHRoZSBVUkwgc3RyaW5nLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIGdldFVybFNlcmlhbGl6ZWREYXRhRXh0cmFzKG9wdGlvbnM6IE5hdmlnYXRpb25EYXRhRXh0cmFzKTogc3RyaW5nIHtcclxuICAgICAgICBsZXQgZXh0cmEgPSAnJztcclxuICAgICAgICBpZiAob3B0aW9ucy5xdWVyeVBhcmFtcykge1xyXG4gICAgICAgICAgICBsZXQga2V5cyA9IE9iamVjdC5rZXlzKG9wdGlvbnMucXVlcnlQYXJhbXMpO1xyXG4gICAgICAgICAgICBrZXlzID0ga2V5cy5zb3J0KCk7XHJcbiAgICAgICAgICAgIGtleXMuZm9yRWFjaCgoa2V5LCBpbmRleCkgPT4gZXh0cmEgKz0gYCR7aW5kZXggPT09IDAgPyAnPycgOiAnJid9JHtrZXl9PSR7b3B0aW9ucy5xdWVyeVBhcmFtc1trZXldfWApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKG9wdGlvbnMuZnJhZ21lbnQpIHtcclxuICAgICAgICAgICAgZXh0cmEgKz0gYCMke29wdGlvbnMuZnJhZ21lbnR9YDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBleHRyYTtcclxuICAgIH1cclxufVxyXG4iXX0=