@dollhousemcp/mcp-server 2.0.0-rc.6 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -61
- package/README.github.md +2 -2
- package/README.md +2 -2
- package/README.md.backup +284 -224
- package/README.npm.md +2 -2
- package/dist/cache/LRUCache.d.ts +3 -0
- package/dist/cache/LRUCache.d.ts.map +1 -1
- package/dist/cache/LRUCache.js +36 -26
- package/dist/config/env.d.ts +14 -4
- package/dist/config/env.d.ts.map +1 -1
- package/dist/config/env.js +20 -6
- package/dist/di/Container.d.ts +21 -0
- package/dist/di/Container.d.ts.map +1 -1
- package/dist/di/Container.js +250 -53
- package/dist/elements/BaseElement.d.ts.map +1 -1
- package/dist/elements/BaseElement.js +5 -10
- package/dist/elements/base/BaseElementManager.d.ts +22 -0
- package/dist/elements/base/BaseElementManager.d.ts.map +1 -1
- package/dist/elements/base/BaseElementManager.js +47 -7
- package/dist/elements/memories/Memory.d.ts +1 -0
- package/dist/elements/memories/Memory.d.ts.map +1 -1
- package/dist/elements/memories/Memory.js +12 -8
- package/dist/elements/memories/MemoryManager.d.ts.map +1 -1
- package/dist/elements/memories/MemoryManager.js +23 -42
- package/dist/elements/memories/MemorySearchIndex.js +2 -2
- package/dist/generated/version.d.ts +2 -2
- package/dist/generated/version.d.ts.map +1 -1
- package/dist/generated/version.js +3 -3
- package/dist/handlers/EnhancedIndexHandler.js +6 -6
- package/dist/handlers/element-crud/listElements.d.ts +2 -0
- package/dist/handlers/element-crud/listElements.d.ts.map +1 -1
- package/dist/handlers/element-crud/listElements.js +3 -1
- package/dist/handlers/mcp-aql/Gatekeeper.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/Gatekeeper.js +23 -17
- package/dist/handlers/mcp-aql/MCPAQLHandler.d.ts +14 -0
- package/dist/handlers/mcp-aql/MCPAQLHandler.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/MCPAQLHandler.js +110 -14
- package/dist/handlers/mcp-aql/OperationRouter.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/OperationRouter.js +13 -1
- package/dist/handlers/mcp-aql/OperationSchema.d.ts +7 -0
- package/dist/handlers/mcp-aql/OperationSchema.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/OperationSchema.js +52 -1
- package/dist/handlers/mcp-aql/evaluatePermission.d.ts +53 -0
- package/dist/handlers/mcp-aql/evaluatePermission.d.ts.map +1 -0
- package/dist/handlers/mcp-aql/evaluatePermission.js +132 -0
- package/dist/handlers/mcp-aql/policies/ToolClassification.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/policies/ToolClassification.js +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/logging/LogHooks.js +11 -11
- package/dist/logging/LogManager.d.ts +0 -2
- package/dist/logging/LogManager.d.ts.map +1 -1
- package/dist/logging/LogManager.js +1 -3
- package/dist/logging/sinks/MemoryLogSink.d.ts +2 -0
- package/dist/logging/sinks/MemoryLogSink.d.ts.map +1 -1
- package/dist/logging/sinks/MemoryLogSink.js +12 -3
- package/dist/logging/types.d.ts +0 -2
- package/dist/logging/types.d.ts.map +1 -1
- package/dist/logging/types.js +1 -1
- package/dist/metrics/GatekeeperMetricsTracker.d.ts +32 -0
- package/dist/metrics/GatekeeperMetricsTracker.d.ts.map +1 -0
- package/dist/metrics/GatekeeperMetricsTracker.js +42 -0
- package/dist/metrics/MetricsManager.d.ts +47 -0
- package/dist/metrics/MetricsManager.d.ts.map +1 -0
- package/dist/metrics/MetricsManager.js +232 -0
- package/dist/metrics/OperationMetricsTracker.d.ts +32 -0
- package/dist/metrics/OperationMetricsTracker.d.ts.map +1 -0
- package/dist/metrics/OperationMetricsTracker.js +53 -0
- package/dist/metrics/collectors/DefaultElementProviderCollector.d.ts +27 -0
- package/dist/metrics/collectors/DefaultElementProviderCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/DefaultElementProviderCollector.js +69 -0
- package/dist/metrics/collectors/FileLockManagerCollector.d.ts +16 -0
- package/dist/metrics/collectors/FileLockManagerCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/FileLockManagerCollector.js +51 -0
- package/dist/metrics/collectors/GatekeeperMetricsCollector.d.ts +16 -0
- package/dist/metrics/collectors/GatekeeperMetricsCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/GatekeeperMetricsCollector.js +76 -0
- package/dist/metrics/collectors/LRUCacheCollector.d.ts +18 -0
- package/dist/metrics/collectors/LRUCacheCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/LRUCacheCollector.js +95 -0
- package/dist/metrics/collectors/OperationMetricsCollector.d.ts +16 -0
- package/dist/metrics/collectors/OperationMetricsCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/OperationMetricsCollector.js +80 -0
- package/dist/metrics/collectors/OperationalTelemetryCollector.d.ts +17 -0
- package/dist/metrics/collectors/OperationalTelemetryCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/OperationalTelemetryCollector.js +26 -0
- package/dist/metrics/collectors/PerformanceMonitorCollector.d.ts +14 -0
- package/dist/metrics/collectors/PerformanceMonitorCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/PerformanceMonitorCollector.js +141 -0
- package/dist/metrics/collectors/SecurityMonitorCollector.d.ts +21 -0
- package/dist/metrics/collectors/SecurityMonitorCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/SecurityMonitorCollector.js +56 -0
- package/dist/metrics/collectors/SecurityTelemetryCollector.d.ts +15 -0
- package/dist/metrics/collectors/SecurityTelemetryCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/SecurityTelemetryCollector.js +112 -0
- package/dist/metrics/collectors/TriggerMetricsTrackerCollector.d.ts +16 -0
- package/dist/metrics/collectors/TriggerMetricsTrackerCollector.d.ts.map +1 -0
- package/dist/metrics/collectors/TriggerMetricsTrackerCollector.js +26 -0
- package/dist/metrics/collectors/index.d.ts +11 -0
- package/dist/metrics/collectors/index.d.ts.map +1 -0
- package/dist/metrics/collectors/index.js +11 -0
- package/dist/metrics/sinks/MemoryMetricsSink.d.ts +22 -0
- package/dist/metrics/sinks/MemoryMetricsSink.d.ts.map +1 -0
- package/dist/metrics/sinks/MemoryMetricsSink.js +121 -0
- package/dist/metrics/types.d.ts +98 -0
- package/dist/metrics/types.d.ts.map +1 -0
- package/dist/metrics/types.js +24 -0
- package/dist/portfolio/DefaultElementProvider.d.ts.map +1 -1
- package/dist/portfolio/DefaultElementProvider.js +1 -7
- package/dist/portfolio/EnhancedIndexManager.d.ts.map +1 -1
- package/dist/portfolio/EnhancedIndexManager.js +18 -18
- package/dist/portfolio/NLPScoringManager.d.ts.map +1 -1
- package/dist/portfolio/NLPScoringManager.js +5 -9
- package/dist/portfolio/PortfolioIndexManager.js +2 -2
- package/dist/portfolio/RelationshipManager.js +2 -2
- package/dist/portfolio/VerbTriggerManager.d.ts.map +1 -1
- package/dist/portfolio/VerbTriggerManager.js +5 -19
- package/dist/portfolio/config/IndexConfig.d.ts.map +1 -1
- package/dist/portfolio/config/IndexConfig.js +1 -12
- package/dist/portfolio/enhanced-index/ElementDefinitionBuilder.d.ts.map +1 -1
- package/dist/portfolio/enhanced-index/ElementDefinitionBuilder.js +3 -15
- package/dist/portfolio/enhanced-index/SemanticRelationshipService.d.ts.map +1 -1
- package/dist/portfolio/enhanced-index/SemanticRelationshipService.js +2 -16
- package/dist/portfolio/types/RelationshipTypes.d.ts.map +1 -1
- package/dist/portfolio/types/RelationshipTypes.js +3 -17
- package/dist/security/audit/config/suppressions.d.ts.map +1 -1
- package/dist/security/audit/config/suppressions.js +36 -8
- package/dist/security/constants.d.ts.map +1 -1
- package/dist/security/constants.js +10 -6
- package/dist/security/fileLockManager.d.ts.map +1 -1
- package/dist/security/fileLockManager.js +8 -6
- package/dist/security/secureYamlParser.d.ts.map +1 -1
- package/dist/security/secureYamlParser.js +1 -13
- package/dist/security/securityMonitor.d.ts +2 -1
- package/dist/security/securityMonitor.d.ts.map +1 -1
- package/dist/security/securityMonitor.js +14 -3
- package/dist/security/telemetry/SecurityTelemetry.d.ts +16 -0
- package/dist/security/telemetry/SecurityTelemetry.d.ts.map +1 -1
- package/dist/security/telemetry/SecurityTelemetry.js +30 -2
- package/dist/security/tokenManager.d.ts +3 -0
- package/dist/security/tokenManager.d.ts.map +1 -1
- package/dist/security/tokenManager.js +13 -5
- package/dist/security/validation/BackgroundValidator.d.ts.map +1 -1
- package/dist/security/validation/BackgroundValidator.js +7 -7
- package/dist/server/startup.d.ts.map +1 -1
- package/dist/server/startup.js +8 -24
- package/dist/server/tools/MCPAQLTools.js +4 -1
- package/dist/services/ActivationStore.d.ts.map +1 -1
- package/dist/services/ActivationStore.js +9 -3
- package/dist/services/FileWatchService.d.ts +1 -0
- package/dist/services/FileWatchService.d.ts.map +1 -1
- package/dist/services/FileWatchService.js +83 -48
- package/dist/services/MetadataService.d.ts.map +1 -1
- package/dist/services/MetadataService.js +7 -2
- package/dist/services/query/ElementQueryService.d.ts.map +1 -1
- package/dist/services/query/ElementQueryService.js +1 -41
- package/dist/services/query/PaginationService.d.ts.map +1 -1
- package/dist/services/query/PaginationService.js +1 -14
- package/dist/services/query/SortService.d.ts.map +1 -1
- package/dist/services/query/SortService.js +1 -6
- package/dist/services/validation/ValidationService.d.ts.map +1 -1
- package/dist/services/validation/ValidationService.js +3 -8
- package/dist/storage/ElementStorageLayer.d.ts.map +1 -1
- package/dist/storage/ElementStorageLayer.js +5 -2
- package/dist/storage/MemoryStorageLayer.d.ts.map +1 -1
- package/dist/storage/MemoryStorageLayer.js +5 -2
- package/dist/telemetry/OperationalTelemetry.js +2 -2
- package/dist/utils/EventDeduplicator.d.ts +44 -0
- package/dist/utils/EventDeduplicator.d.ts.map +1 -0
- package/dist/utils/EventDeduplicator.js +93 -0
- package/dist/utils/FileLock.d.ts.map +1 -1
- package/dist/utils/FileLock.js +1 -9
- package/dist/utils/PerformanceMonitor.d.ts.map +1 -1
- package/dist/utils/PerformanceMonitor.js +5 -5
- package/dist/utils/SlidingWindowRateLimiter.d.ts +13 -0
- package/dist/utils/SlidingWindowRateLimiter.d.ts.map +1 -0
- package/dist/utils/SlidingWindowRateLimiter.js +23 -0
- package/dist/web/console/IngestRoutes.d.ts +84 -0
- package/dist/web/console/IngestRoutes.d.ts.map +1 -0
- package/dist/web/console/IngestRoutes.js +252 -0
- package/dist/web/console/LeaderElection.d.ts +89 -0
- package/dist/web/console/LeaderElection.d.ts.map +1 -0
- package/dist/web/console/LeaderElection.js +205 -0
- package/dist/web/console/LeaderForwardingSink.d.ts +61 -0
- package/dist/web/console/LeaderForwardingSink.d.ts.map +1 -0
- package/dist/web/console/LeaderForwardingSink.js +197 -0
- package/dist/web/console/SessionNames.d.ts +46 -0
- package/dist/web/console/SessionNames.d.ts.map +1 -0
- package/dist/web/console/SessionNames.js +257 -0
- package/dist/web/console/UnifiedConsole.d.ts +64 -0
- package/dist/web/console/UnifiedConsole.d.ts.map +1 -0
- package/dist/web/console/UnifiedConsole.js +119 -0
- package/dist/web/contentPipeline.d.ts +58 -0
- package/dist/web/contentPipeline.d.ts.map +1 -0
- package/dist/web/contentPipeline.js +112 -0
- package/dist/web/portDiscovery.d.ts +58 -0
- package/dist/web/portDiscovery.d.ts.map +1 -0
- package/dist/web/portDiscovery.js +143 -0
- package/dist/web/public/app.js +148 -60
- package/dist/web/public/logs.js +638 -0
- package/dist/web/public/metrics.js +682 -0
- package/dist/web/public/permissions.js +394 -0
- package/dist/web/public/sessions.js +369 -0
- package/dist/web/routes/healthRoutes.d.ts +16 -0
- package/dist/web/routes/healthRoutes.d.ts.map +1 -0
- package/dist/web/routes/healthRoutes.js +29 -0
- package/dist/web/routes/logRoutes.d.ts +18 -0
- package/dist/web/routes/logRoutes.d.ts.map +1 -0
- package/dist/web/routes/logRoutes.js +126 -0
- package/dist/web/routes/metricsRoutes.d.ts +17 -0
- package/dist/web/routes/metricsRoutes.d.ts.map +1 -0
- package/dist/web/routes/metricsRoutes.js +90 -0
- package/dist/web/routes/permissionRoutes.d.ts +16 -0
- package/dist/web/routes/permissionRoutes.d.ts.map +1 -0
- package/dist/web/routes/permissionRoutes.js +133 -0
- package/dist/web/routes.d.ts.map +1 -1
- package/dist/web/routes.js +309 -339
- package/dist/web/server.d.ts +21 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +42 -4
- package/dist/web/sinks/WebSSELogSink.d.ts +15 -0
- package/dist/web/sinks/WebSSELogSink.d.ts.map +1 -0
- package/dist/web/sinks/WebSSELogSink.js +22 -0
- package/dist/web/sinks/WebSSEMetricsSink.d.ts +16 -0
- package/dist/web/sinks/WebSSEMetricsSink.d.ts.map +1 -0
- package/dist/web/sinks/WebSSEMetricsSink.js +23 -0
- package/package.json +2 -2
- package/server.json +2 -2
- package/dist/constants/version.d.ts +0 -3
- package/dist/constants/version.d.ts.map +0 -1
- package/dist/constants/version.js +0 -4
- package/dist/logging/sinks/SSELogSink.d.ts +0 -35
- package/dist/logging/sinks/SSELogSink.d.ts.map +0 -1
- package/dist/logging/sinks/SSELogSink.js +0 -181
- package/dist/logging/viewer/viewerHtml.d.ts +0 -8
- package/dist/logging/viewer/viewerHtml.d.ts.map +0 -1
- package/dist/logging/viewer/viewerHtml.js +0 -204
- package/dist/web/public/public/app.js +0 -1878
package/dist/web/routes.js
CHANGED
|
@@ -17,36 +17,178 @@ import { readdir, readFile, stat } from 'node:fs/promises';
|
|
|
17
17
|
import { join, extname, resolve } from 'node:path';
|
|
18
18
|
import { SecureYamlParser } from '../security/secureYamlParser.js';
|
|
19
19
|
import { logger } from '../utils/logger.js';
|
|
20
|
+
import { validateElementContent } from './contentPipeline.js';
|
|
20
21
|
/** Normalize user input to NFC form to prevent Unicode homograph attacks */
|
|
21
22
|
function normalizeInput(input) {
|
|
22
23
|
return input.normalize('NFC');
|
|
23
24
|
}
|
|
24
25
|
import { ContentValidator } from '../security/contentValidator.js';
|
|
26
|
+
import { SlidingWindowRateLimiter } from '../utils/SlidingWindowRateLimiter.js';
|
|
25
27
|
const ELEMENT_TYPES = ['personas', 'skills', 'templates', 'agents', 'memories', 'ensembles'];
|
|
26
28
|
/** Max file size for element reads (1 MB) */
|
|
27
29
|
const MAX_FILE_SIZE_BYTES = 1_048_576;
|
|
30
|
+
/** Valid element file extensions */
|
|
31
|
+
const VALID_EXTENSIONS = new Set(['.md', '.yaml', '.yml']);
|
|
32
|
+
/** Known-safe filename pattern: starts alphanumeric, body allows hyphens/underscores, valid extension */
|
|
33
|
+
const SAFE_FILENAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9_-]*\.(yaml|yml|md)$/;
|
|
34
|
+
/** Check if a filename is a backup or cruft file */
|
|
35
|
+
function isBackupOrCruft(filename) {
|
|
36
|
+
// Guaranteed safe filenames skip blacklist checks entirely
|
|
37
|
+
if (SAFE_FILENAME_RE.test(filename))
|
|
38
|
+
return false;
|
|
39
|
+
if (filename.startsWith('.'))
|
|
40
|
+
return true;
|
|
41
|
+
if (filename === '_index.json')
|
|
42
|
+
return true;
|
|
43
|
+
if (filename.includes('.backup') || filename.includes('.state'))
|
|
44
|
+
return true;
|
|
45
|
+
if (filename.endsWith('.bak') || filename.endsWith('~'))
|
|
46
|
+
return true;
|
|
47
|
+
if (filename.includes(' copy'))
|
|
48
|
+
return true;
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Scan a directory for valid elements, running each through the security
|
|
53
|
+
* validation pipeline. Returns metadata objects ready for API responses.
|
|
54
|
+
*/
|
|
55
|
+
async function scanElementDirectory(typeDir, type, logPrefix) {
|
|
56
|
+
const files = await readdir(typeDir);
|
|
57
|
+
const elements = [];
|
|
58
|
+
for (const file of files) {
|
|
59
|
+
if (isBackupOrCruft(file))
|
|
60
|
+
continue;
|
|
61
|
+
const ext = extname(file);
|
|
62
|
+
if (!VALID_EXTENSIONS.has(ext))
|
|
63
|
+
continue;
|
|
64
|
+
try {
|
|
65
|
+
const filePath = join(typeDir, file);
|
|
66
|
+
const fileStat = await stat(filePath);
|
|
67
|
+
if (!fileStat.isFile() || fileStat.size > MAX_FILE_SIZE_BYTES)
|
|
68
|
+
continue;
|
|
69
|
+
const content = await readFile(filePath, 'utf-8');
|
|
70
|
+
const validationResult = validateElementContent(file, content, type);
|
|
71
|
+
if (!validationResult.valid) {
|
|
72
|
+
logger.debug(`${logPrefix} Skipping rejected file ${file}: ${validationResult.rejection?.reason}`);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const { metadata } = validationResult;
|
|
76
|
+
elements.push({
|
|
77
|
+
name: metadata.name || file.replace(ext, ''),
|
|
78
|
+
description: metadata.description || '',
|
|
79
|
+
type: type.slice(0, -1),
|
|
80
|
+
version: metadata.version || '1.0.0',
|
|
81
|
+
author: metadata.author || '',
|
|
82
|
+
category: metadata.category || '',
|
|
83
|
+
tags: metadata.tags || '',
|
|
84
|
+
created: metadata.created || '',
|
|
85
|
+
filename: file,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
logger.debug(`${logPrefix} Failed to parse ${file}:`, err);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return elements;
|
|
93
|
+
}
|
|
94
|
+
/** Normalize plural element type to singular form */
|
|
95
|
+
const PLURAL_TO_SINGULAR = {
|
|
96
|
+
personas: 'persona', skills: 'skill', templates: 'template',
|
|
97
|
+
agents: 'agent', memories: 'memory', ensembles: 'ensemble',
|
|
98
|
+
};
|
|
99
|
+
function toSingularType(type) {
|
|
100
|
+
return PLURAL_TO_SINGULAR[type] || (type.endsWith('s') ? type.slice(0, -1) : type);
|
|
101
|
+
}
|
|
102
|
+
/** Build a structured validation response for element detail routes */
|
|
103
|
+
function buildValidationResponse(validation, content, type) {
|
|
104
|
+
return {
|
|
105
|
+
metadata: validation.metadata,
|
|
106
|
+
body: validation.body,
|
|
107
|
+
raw: content,
|
|
108
|
+
type: toSingularType(type),
|
|
109
|
+
validation: {
|
|
110
|
+
status: validation.valid ? 'pass' : 'warn',
|
|
111
|
+
...(validation.rejection && {
|
|
112
|
+
reason: validation.rejection.reason,
|
|
113
|
+
severity: validation.rejection.severity,
|
|
114
|
+
patterns: validation.rejection.patterns,
|
|
115
|
+
}),
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|
|
28
119
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
120
|
+
* Resolve a file path for an element, handling memory date-paths
|
|
121
|
+
* and name-with-or-without-extension matching.
|
|
122
|
+
* Returns the resolved path or null with an error to send.
|
|
31
123
|
*/
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
124
|
+
async function resolveElementFilePath(portfolioDir, type, name) {
|
|
125
|
+
if (type === 'memories' && name.includes('/')) {
|
|
126
|
+
const parts = name.split('/');
|
|
127
|
+
if (parts.length !== 2 || !/^\d{4}-\d{2}-\d{2}$/.test(parts[0]) || isBackupOrCruft(parts[1])) {
|
|
128
|
+
return { error: 'Invalid memory path', status: 400 };
|
|
129
|
+
}
|
|
130
|
+
const filePath = join(portfolioDir, type, name);
|
|
131
|
+
const resolvedPath = resolve(filePath);
|
|
132
|
+
if (!resolvedPath.startsWith(resolve(portfolioDir))) {
|
|
133
|
+
return { error: 'Path traversal detected', status: 400 };
|
|
134
|
+
}
|
|
135
|
+
return { filePath };
|
|
39
136
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
137
|
+
const typeDir = join(portfolioDir, type);
|
|
138
|
+
const files = await readdir(typeDir);
|
|
139
|
+
const match = files.find(f => {
|
|
140
|
+
const base = f.replace(extname(f), '');
|
|
141
|
+
return base === name || f === name;
|
|
142
|
+
});
|
|
143
|
+
if (!match) {
|
|
144
|
+
return { error: `Element not found: ${type}/${name}`, status: 404 };
|
|
145
|
+
}
|
|
146
|
+
const filePath = join(portfolioDir, type, match);
|
|
147
|
+
const resolvedPath = resolve(filePath);
|
|
148
|
+
if (!resolvedPath.startsWith(resolve(portfolioDir))) {
|
|
149
|
+
return { error: 'Path traversal detected', status: 400 };
|
|
150
|
+
}
|
|
151
|
+
return { filePath };
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Load memories from the _index.json file.
|
|
155
|
+
* Memories use date-partitioned storage with an index, unlike other
|
|
156
|
+
* element types which are flat files in a directory.
|
|
157
|
+
*/
|
|
158
|
+
async function loadMemoriesFromIndex(portfolioDir) {
|
|
159
|
+
const indexPath = join(portfolioDir, 'memories', '_index.json');
|
|
160
|
+
try {
|
|
161
|
+
const raw = await readFile(indexPath, 'utf-8');
|
|
162
|
+
const index = JSON.parse(raw);
|
|
163
|
+
const entries = index.entries || {};
|
|
164
|
+
const elements = [];
|
|
165
|
+
for (const [path, entry] of Object.entries(entries)) {
|
|
166
|
+
if (!entry || typeof entry !== 'object')
|
|
167
|
+
continue;
|
|
168
|
+
const pathParts = path.split('/');
|
|
169
|
+
const filename = pathParts.pop() || path;
|
|
170
|
+
// Extract date from directory path (e.g., "2025-09-19/code-patterns.yaml" -> "2025-09-19")
|
|
171
|
+
const dateFromPath = pathParts.length > 0 && /^\d{4}-\d{2}-\d{2}$/.test(pathParts[0]) ? pathParts[0] : '';
|
|
172
|
+
// Fall back to filename if index has no name or stored "unnamed" (upstream indexer bug)
|
|
173
|
+
const indexName = entry.name && entry.name !== 'unnamed' ? entry.name : null;
|
|
174
|
+
const name = indexName || filename.replace(/\.(yaml|yml|md)$/, '');
|
|
175
|
+
elements.push({
|
|
176
|
+
name,
|
|
177
|
+
description: entry.description || '',
|
|
178
|
+
type: 'memory',
|
|
179
|
+
version: entry.version || '1.0.0',
|
|
180
|
+
author: entry.author || '',
|
|
181
|
+
category: entry.category || entry.memoryType || '',
|
|
182
|
+
tags: entry.tags || [],
|
|
183
|
+
created: entry.created || dateFromPath,
|
|
184
|
+
filename: path, // date/filename path for content loading
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return elements;
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
// Fall back to empty if no index
|
|
191
|
+
return [];
|
|
50
192
|
}
|
|
51
193
|
}
|
|
52
194
|
/** Rate limiter for /api/install: max 10 installs per 60 seconds */
|
|
@@ -86,64 +228,35 @@ function parseYamlFile(content) {
|
|
|
86
228
|
return { metadata: {}, body: content };
|
|
87
229
|
}
|
|
88
230
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
*/
|
|
231
|
+
/**
|
|
232
|
+
* Register portfolio routes shared between simple and gateway modes.
|
|
233
|
+
* The structuredDetail option controls whether detail routes return
|
|
234
|
+
* structured JSON (gateway) or plain text (simple/legacy).
|
|
235
|
+
*/
|
|
236
|
+
function registerPortfolioRoutes(router, portfolioDir, options) {
|
|
237
|
+
const { structuredDetail, logPrefix } = options;
|
|
97
238
|
router.get('/elements', async (req, res) => {
|
|
98
239
|
try {
|
|
99
240
|
const pageParam = req.query.page;
|
|
100
241
|
const pageSizeParam = req.query.pageSize;
|
|
101
242
|
const wantPagination = pageParam !== undefined && pageSizeParam !== undefined;
|
|
102
|
-
const page = Math.max(1, parseInt(pageParam || '1', 10) || 1);
|
|
103
|
-
const pageSize = Math.max(1, Math.min(200, parseInt(pageSizeParam || '50', 10) || 50));
|
|
243
|
+
const page = Math.max(1, Number.parseInt(pageParam || '1', 10) || 1);
|
|
244
|
+
const pageSize = Math.max(1, Math.min(200, Number.parseInt(pageSizeParam || '50', 10) || 50));
|
|
104
245
|
const result = {};
|
|
105
246
|
let totalCount = 0;
|
|
106
247
|
for (const type of ELEMENT_TYPES) {
|
|
107
|
-
const typeDir = join(portfolioDir, type);
|
|
108
248
|
try {
|
|
249
|
+
if (type === 'memories') {
|
|
250
|
+
const memElements = await loadMemoriesFromIndex(portfolioDir);
|
|
251
|
+
result[type] = memElements;
|
|
252
|
+
totalCount += memElements.length;
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
const typeDir = join(portfolioDir, type);
|
|
109
256
|
const dirStat = await stat(typeDir);
|
|
110
257
|
if (!dirStat.isDirectory())
|
|
111
258
|
continue;
|
|
112
|
-
const
|
|
113
|
-
const elements = [];
|
|
114
|
-
for (const file of files) {
|
|
115
|
-
// Skip backups, hidden files, state files
|
|
116
|
-
if (file.startsWith('.') || file.includes('.backup-') || file.includes('.state'))
|
|
117
|
-
continue;
|
|
118
|
-
const ext = extname(file);
|
|
119
|
-
if (ext !== '.md' && ext !== '.yaml' && ext !== '.yml')
|
|
120
|
-
continue;
|
|
121
|
-
try {
|
|
122
|
-
const filePath = join(typeDir, file);
|
|
123
|
-
// Skip files larger than 1 MB
|
|
124
|
-
const fileStat = await stat(filePath);
|
|
125
|
-
if (fileStat.size > MAX_FILE_SIZE_BYTES) {
|
|
126
|
-
logger.debug(`[WebUI] Skipping oversized file (${fileStat.size} bytes): ${file}`);
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
const content = await readFile(filePath, 'utf-8');
|
|
130
|
-
const { metadata } = ext === '.md' ? parseFrontMatter(content) : parseYamlFile(content);
|
|
131
|
-
elements.push({
|
|
132
|
-
name: metadata.name || file.replace(ext, ''),
|
|
133
|
-
description: metadata.description || '',
|
|
134
|
-
type: type.slice(0, -1), // plural → singular
|
|
135
|
-
version: metadata.version || '1.0.0',
|
|
136
|
-
author: metadata.author || '',
|
|
137
|
-
category: metadata.category || '',
|
|
138
|
-
tags: metadata.tags || '',
|
|
139
|
-
created: metadata.created || '',
|
|
140
|
-
filename: file,
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
catch (err) {
|
|
144
|
-
logger.debug(`[WebUI] Failed to parse ${file}:`, err);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
259
|
+
const elements = await scanElementDirectory(typeDir, type, logPrefix);
|
|
147
260
|
result[type] = elements;
|
|
148
261
|
totalCount += elements.length;
|
|
149
262
|
}
|
|
@@ -152,7 +265,6 @@ export function createApiRoutes(portfolioDir) {
|
|
|
152
265
|
}
|
|
153
266
|
}
|
|
154
267
|
if (wantPagination) {
|
|
155
|
-
// Flatten all elements, paginate, then return
|
|
156
268
|
const allElements = [];
|
|
157
269
|
for (const type of ELEMENT_TYPES) {
|
|
158
270
|
allElements.push(...(result[type] || []));
|
|
@@ -160,28 +272,17 @@ export function createApiRoutes(portfolioDir) {
|
|
|
160
272
|
const start = (page - 1) * pageSize;
|
|
161
273
|
const paged = allElements.slice(start, start + pageSize);
|
|
162
274
|
const totalPages = Math.ceil(allElements.length / pageSize);
|
|
163
|
-
res.json({
|
|
164
|
-
elements: paged,
|
|
165
|
-
totalCount: allElements.length,
|
|
166
|
-
page,
|
|
167
|
-
pageSize,
|
|
168
|
-
totalPages,
|
|
169
|
-
});
|
|
275
|
+
res.json({ elements: paged, totalCount: allElements.length, page, pageSize, totalPages });
|
|
170
276
|
}
|
|
171
277
|
else {
|
|
172
|
-
// Backward-compatible: grouped by type
|
|
173
278
|
res.json({ elements: result, totalCount });
|
|
174
279
|
}
|
|
175
280
|
}
|
|
176
281
|
catch (err) {
|
|
177
|
-
logger.error(
|
|
282
|
+
logger.error(`${logPrefix} Failed to list elements:`, err);
|
|
178
283
|
res.status(500).json({ error: 'Failed to list elements' });
|
|
179
284
|
}
|
|
180
285
|
});
|
|
181
|
-
/**
|
|
182
|
-
* GET /api/elements/:type
|
|
183
|
-
* Returns all elements of a specific type
|
|
184
|
-
*/
|
|
185
286
|
router.get('/elements/:type', async (req, res) => {
|
|
186
287
|
const type = normalizeInput(req.params.type);
|
|
187
288
|
if (!ELEMENT_TYPES.includes(type)) {
|
|
@@ -189,115 +290,112 @@ export function createApiRoutes(portfolioDir) {
|
|
|
189
290
|
return;
|
|
190
291
|
}
|
|
191
292
|
try {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if (file.startsWith('.') || file.includes('.backup-') || file.includes('.state'))
|
|
197
|
-
continue;
|
|
198
|
-
const ext = extname(file);
|
|
199
|
-
if (ext !== '.md' && ext !== '.yaml' && ext !== '.yml')
|
|
200
|
-
continue;
|
|
201
|
-
try {
|
|
202
|
-
const filePath = join(typeDir, file);
|
|
203
|
-
// Skip files larger than 1 MB
|
|
204
|
-
const fileStat = await stat(filePath);
|
|
205
|
-
if (fileStat.size > MAX_FILE_SIZE_BYTES) {
|
|
206
|
-
logger.debug(`[WebUI] Skipping oversized file (${fileStat.size} bytes): ${file}`);
|
|
207
|
-
continue;
|
|
208
|
-
}
|
|
209
|
-
const content = await readFile(filePath, 'utf-8');
|
|
210
|
-
const { metadata, body } = ext === '.md' ? parseFrontMatter(content) : parseYamlFile(content);
|
|
211
|
-
elements.push({
|
|
212
|
-
name: metadata.name || file.replace(ext, ''),
|
|
213
|
-
description: metadata.description || '',
|
|
214
|
-
type: type.slice(0, -1),
|
|
215
|
-
version: metadata.version || '1.0.0',
|
|
216
|
-
author: metadata.author || '',
|
|
217
|
-
category: metadata.category || '',
|
|
218
|
-
tags: metadata.tags || '',
|
|
219
|
-
created: metadata.created || '',
|
|
220
|
-
modified: metadata.modified || '',
|
|
221
|
-
filename: file,
|
|
222
|
-
bodyPreview: sanitizeForHtml(body.slice(0, 500)),
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
catch (err) {
|
|
226
|
-
logger.debug(`[WebUI] Failed to parse ${file}:`, err);
|
|
227
|
-
}
|
|
293
|
+
if (type === 'memories') {
|
|
294
|
+
const memElements = await loadMemoriesFromIndex(portfolioDir);
|
|
295
|
+
res.json({ type, elements: memElements, count: memElements.length });
|
|
296
|
+
return;
|
|
228
297
|
}
|
|
298
|
+
const elements = await scanElementDirectory(join(portfolioDir, type), type, logPrefix);
|
|
229
299
|
res.json({ type, elements, count: elements.length });
|
|
230
300
|
}
|
|
231
301
|
catch {
|
|
232
302
|
res.status(500).json({ error: `Failed to list ${type}` });
|
|
233
303
|
}
|
|
234
304
|
});
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
305
|
+
router.get('/elements/memories/:date/:file', async (req, res) => {
|
|
306
|
+
const { date, file } = req.params;
|
|
307
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
308
|
+
res.status(400).json({ error: 'Invalid date format' });
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
if (file.includes('..') || file.includes('/') || file.includes('\\') || isBackupOrCruft(file)) {
|
|
312
|
+
res.status(400).json({ error: 'Invalid filename' });
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
try {
|
|
316
|
+
const filePath = join(portfolioDir, 'memories', date, file);
|
|
317
|
+
const resolvedPath = resolve(filePath);
|
|
318
|
+
if (!resolvedPath.startsWith(resolve(portfolioDir))) {
|
|
319
|
+
res.status(400).json({ error: 'Path traversal detected' });
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const fileStat = await stat(filePath);
|
|
323
|
+
if (!fileStat.isFile() || fileStat.size > MAX_FILE_SIZE_BYTES) {
|
|
324
|
+
res.status(fileStat.isFile() ? 413 : 404).json({ error: fileStat.isFile() ? 'File too large' : 'Not found' });
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
const content = await readFile(filePath, 'utf-8');
|
|
328
|
+
if (structuredDetail) {
|
|
329
|
+
const validation = validateElementContent(file, content, 'memories');
|
|
330
|
+
res.json(buildValidationResponse(validation, content, 'memories'));
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
|
|
334
|
+
res.send(content);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
catch {
|
|
338
|
+
res.status(404).json({ error: `Memory not found: ${date}/${file}` });
|
|
339
|
+
}
|
|
340
|
+
});
|
|
240
341
|
router.get('/elements/:type/:name', async (req, res) => {
|
|
241
342
|
const { type, name } = req.params;
|
|
242
343
|
if (!ELEMENT_TYPES.includes(type)) {
|
|
243
344
|
res.status(400).json({ error: `Invalid element type: ${type}` });
|
|
244
345
|
return;
|
|
245
346
|
}
|
|
246
|
-
|
|
247
|
-
|
|
347
|
+
if (name.includes('..') || name.includes('\\')) {
|
|
348
|
+
res.status(400).json({ error: 'Invalid element name' });
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
if (type !== 'memories' && name.includes('/')) {
|
|
248
352
|
res.status(400).json({ error: 'Invalid element name' });
|
|
249
353
|
return;
|
|
250
354
|
}
|
|
251
355
|
try {
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const match = files.find(f => {
|
|
256
|
-
const base = f.replace(extname(f), '');
|
|
257
|
-
return base === name || f === name;
|
|
258
|
-
});
|
|
259
|
-
if (!match) {
|
|
260
|
-
res.status(404).json({ error: `Element not found: ${type}/${name}` });
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
const filePath = join(typeDir, match);
|
|
264
|
-
// Verify resolved path stays within portfolio directory (defense in depth)
|
|
265
|
-
const resolvedPath = resolve(filePath);
|
|
266
|
-
if (!resolvedPath.startsWith(resolve(portfolioDir))) {
|
|
267
|
-
res.status(400).json({ error: 'Path traversal detected' });
|
|
356
|
+
const resolved = await resolveElementFilePath(portfolioDir, type, name);
|
|
357
|
+
if ('error' in resolved) {
|
|
358
|
+
res.status(resolved.status).json({ error: resolved.error });
|
|
268
359
|
return;
|
|
269
360
|
}
|
|
270
|
-
|
|
271
|
-
const fileStat = await stat(filePath);
|
|
361
|
+
const fileStat = await stat(resolved.filePath);
|
|
272
362
|
if (fileStat.size > MAX_FILE_SIZE_BYTES) {
|
|
273
363
|
res.status(413).json({ error: `File too large (${fileStat.size} bytes). Max 1 MB.` });
|
|
274
364
|
return;
|
|
275
365
|
}
|
|
276
|
-
const content = await readFile(filePath, 'utf-8');
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
366
|
+
const content = await readFile(resolved.filePath, 'utf-8');
|
|
367
|
+
if (structuredDetail) {
|
|
368
|
+
const filename = resolved.filePath.split('/').pop() || name;
|
|
369
|
+
const validation = validateElementContent(filename, content, type);
|
|
370
|
+
res.json(buildValidationResponse(validation, content, type));
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
|
|
374
|
+
res.send(content);
|
|
375
|
+
}
|
|
280
376
|
}
|
|
281
377
|
catch {
|
|
282
378
|
res.status(500).json({ error: `Failed to get element: ${type}/${name}` });
|
|
283
379
|
}
|
|
284
380
|
});
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
*/
|
|
381
|
+
}
|
|
382
|
+
/** Register filesystem-based stats route (shared between simple and gateway) */
|
|
383
|
+
function registerStatsRoute(router, portfolioDir) {
|
|
289
384
|
router.get('/stats', async (_req, res) => {
|
|
290
385
|
try {
|
|
291
386
|
const stats = {};
|
|
292
387
|
let total = 0;
|
|
293
388
|
for (const type of ELEMENT_TYPES) {
|
|
294
389
|
try {
|
|
390
|
+
if (type === 'memories') {
|
|
391
|
+
const memElements = await loadMemoriesFromIndex(portfolioDir);
|
|
392
|
+
stats[type] = memElements.length;
|
|
393
|
+
total += memElements.length;
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
295
396
|
const typeDir = join(portfolioDir, type);
|
|
296
397
|
const files = await readdir(typeDir);
|
|
297
|
-
const count = files.filter(f => !f.
|
|
298
|
-
!f.includes('.backup-') &&
|
|
299
|
-
!f.includes('.state') &&
|
|
300
|
-
['.md', '.yaml', '.yml'].includes(extname(f))).length;
|
|
398
|
+
const count = files.filter(f => !isBackupOrCruft(f) && VALID_EXTENSIONS.has(extname(f))).length;
|
|
301
399
|
stats[type] = count;
|
|
302
400
|
total += count;
|
|
303
401
|
}
|
|
@@ -311,14 +409,11 @@ export function createApiRoutes(portfolioDir) {
|
|
|
311
409
|
res.status(500).json({ error: 'Failed to get stats' });
|
|
312
410
|
}
|
|
313
411
|
});
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
* Prefers GitHub raw (authoritative source), falls back to local file.
|
|
318
|
-
*/
|
|
412
|
+
}
|
|
413
|
+
/** Register collection index proxy route (shared between simple and gateway) */
|
|
414
|
+
function registerCollectionRoute(router, portfolioDir) {
|
|
319
415
|
router.get('/collection', async (_req, res) => {
|
|
320
416
|
res.setHeader('Cache-Control', 'no-cache');
|
|
321
|
-
// Prefer GitHub raw (authoritative, always fresh)
|
|
322
417
|
try {
|
|
323
418
|
const response = await fetch('https://raw.githubusercontent.com/DollhouseMCP/collection/main/public/collection-index.json');
|
|
324
419
|
if (response.ok) {
|
|
@@ -329,7 +424,6 @@ export function createApiRoutes(portfolioDir) {
|
|
|
329
424
|
}
|
|
330
425
|
}
|
|
331
426
|
catch { /* GitHub unreachable — fall back to local */ }
|
|
332
|
-
// Fall back to local collection repo (developer setup, may be stale)
|
|
333
427
|
const localPaths = [
|
|
334
428
|
join(portfolioDir, '..', '..', '..', 'collection', 'public', 'collection-index.json'),
|
|
335
429
|
join(portfolioDir, '..', 'collection', 'public', 'collection-index.json'),
|
|
@@ -345,6 +439,12 @@ export function createApiRoutes(portfolioDir) {
|
|
|
345
439
|
}
|
|
346
440
|
res.status(404).json({ error: 'Collection index not available' });
|
|
347
441
|
});
|
|
442
|
+
}
|
|
443
|
+
export function createApiRoutes(portfolioDir) {
|
|
444
|
+
const router = Router();
|
|
445
|
+
registerPortfolioRoutes(router, portfolioDir, { structuredDetail: false, logPrefix: '[WebUI]' });
|
|
446
|
+
registerStatsRoute(router, portfolioDir);
|
|
447
|
+
registerCollectionRoute(router, portfolioDir);
|
|
348
448
|
/**
|
|
349
449
|
* POST /api/install
|
|
350
450
|
* Install a collection element into the local portfolio.
|
|
@@ -468,16 +568,6 @@ export function createApiRoutes(portfolioDir) {
|
|
|
468
568
|
});
|
|
469
569
|
return router;
|
|
470
570
|
}
|
|
471
|
-
// ────────────────────────────────────────────────────────────────────────────
|
|
472
|
-
// Web MCP-AQL Gateway Routes (Issue #796)
|
|
473
|
-
//
|
|
474
|
-
// These routes translate HTTP requests into MCPAQLHandler calls, routing all
|
|
475
|
-
// reads/writes through the existing element managers, validation, and gatekeeper.
|
|
476
|
-
// ────────────────────────────────────────────────────────────────────────────
|
|
477
|
-
/** Normalize element type to singular form for MCP-AQL operations */
|
|
478
|
-
function toSingularType(type) {
|
|
479
|
-
return type.endsWith('s') ? type.slice(0, -1) : type;
|
|
480
|
-
}
|
|
481
571
|
function asSingleResult(r) {
|
|
482
572
|
if (typeof r === 'object' && r !== null && 'success' in r) {
|
|
483
573
|
return r;
|
|
@@ -493,186 +583,66 @@ function asSingleResult(r) {
|
|
|
493
583
|
*/
|
|
494
584
|
export function createGatewayApiRoutes(handler, portfolioDir) {
|
|
495
585
|
const router = Router();
|
|
586
|
+
// Shared portfolio routes — structured JSON for detail views
|
|
587
|
+
// codeql[js/missing-rate-limiting] — Rate-limited by router.use() middleware in server.ts
|
|
588
|
+
registerPortfolioRoutes(router, portfolioDir, { structuredDetail: true, logPrefix: '[WebUI/Gateway]' });
|
|
589
|
+
registerStatsRoute(router, portfolioDir);
|
|
590
|
+
registerCollectionRoute(router, portfolioDir);
|
|
496
591
|
/**
|
|
497
|
-
* GET /api/
|
|
498
|
-
*
|
|
592
|
+
* GET /api/collection/content/*
|
|
593
|
+
* Proxies collection element content from GitHub, validates through the
|
|
594
|
+
* security pipeline, and returns structured JSON (same format as portfolio detail).
|
|
595
|
+
* codeql[js/missing-rate-limiting] — Rate-limited by router.use() middleware above.
|
|
499
596
|
*/
|
|
500
|
-
router.get('/
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
const wantPagination = pageParam !== undefined && pageSizeParam !== undefined;
|
|
505
|
-
const page = Math.max(1, parseInt(pageParam || '1', 10) || 1);
|
|
506
|
-
const pageSize = Math.max(1, Math.min(200, parseInt(pageSizeParam || '50', 10) || 50));
|
|
507
|
-
const result = {};
|
|
508
|
-
let totalCount = 0;
|
|
509
|
-
// Parallelize element type listing for better performance
|
|
510
|
-
const typeResults = await Promise.all(ELEMENT_TYPES.map(async (type) => {
|
|
511
|
-
const opResult = asSingleResult(await handler.handleRead({
|
|
512
|
-
operation: 'list_elements',
|
|
513
|
-
params: { element_type: toSingularType(type), page: 1, pageSize: 1000 },
|
|
514
|
-
}));
|
|
515
|
-
if (opResult.success && opResult.data) {
|
|
516
|
-
const items = opResult.data.items;
|
|
517
|
-
return { type, items: Array.isArray(items) ? items : [] };
|
|
518
|
-
}
|
|
519
|
-
return { type, items: [] };
|
|
520
|
-
}));
|
|
521
|
-
for (const { type, items } of typeResults) {
|
|
522
|
-
result[type] = items;
|
|
523
|
-
totalCount += items.length;
|
|
524
|
-
}
|
|
525
|
-
if (wantPagination) {
|
|
526
|
-
const allElements = [];
|
|
527
|
-
for (const type of ELEMENT_TYPES) {
|
|
528
|
-
allElements.push(...(result[type] || []));
|
|
529
|
-
}
|
|
530
|
-
const start = (page - 1) * pageSize;
|
|
531
|
-
const paged = allElements.slice(start, start + pageSize);
|
|
532
|
-
const totalPages = Math.ceil(allElements.length / pageSize);
|
|
533
|
-
res.json({ elements: paged, totalCount: allElements.length, page, pageSize, totalPages });
|
|
534
|
-
}
|
|
535
|
-
else {
|
|
536
|
-
res.json({ elements: result, totalCount });
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
catch (err) {
|
|
540
|
-
logger.error('[WebUI/Gateway] Failed to list elements:', err);
|
|
541
|
-
res.status(500).json({ error: 'Failed to list elements' });
|
|
542
|
-
}
|
|
543
|
-
});
|
|
544
|
-
/**
|
|
545
|
-
* GET /api/elements/:type
|
|
546
|
-
* Routes through list_elements for a specific type.
|
|
547
|
-
*/
|
|
548
|
-
router.get('/elements/:type', async (req, res) => {
|
|
549
|
-
const type = normalizeInput(req.params.type);
|
|
550
|
-
if (!ELEMENT_TYPES.includes(type)) {
|
|
551
|
-
res.status(400).json({ error: `Invalid element type: ${type}` });
|
|
597
|
+
router.get('/collection/content/:prefix/:type/:name', async (req, res) => {
|
|
598
|
+
const elementPath = `${req.params.prefix}/${req.params.type}/${req.params.name}`;
|
|
599
|
+
if (!elementPath || elementPath.includes('..') || elementPath.includes('\\')) {
|
|
600
|
+
res.status(400).json({ error: 'Invalid element path' });
|
|
552
601
|
return;
|
|
553
602
|
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
})
|
|
559
|
-
if (!opResult.success) {
|
|
560
|
-
res.status(500).json({ error: opResult.error || `Failed to list ${type}` });
|
|
561
|
-
return;
|
|
562
|
-
}
|
|
563
|
-
const data = opResult.data;
|
|
564
|
-
const items = Array.isArray(data.items) ? data.items : [];
|
|
565
|
-
res.json({ type, elements: items, count: items.length });
|
|
566
|
-
}
|
|
567
|
-
catch {
|
|
568
|
-
res.status(500).json({ error: `Failed to list ${type}` });
|
|
569
|
-
}
|
|
570
|
-
});
|
|
571
|
-
/**
|
|
572
|
-
* GET /api/elements/:type/:name
|
|
573
|
-
* Routes through get_element for a specific element.
|
|
574
|
-
* Returns the raw file content as plain text (same as legacy behavior).
|
|
575
|
-
*/
|
|
576
|
-
router.get('/elements/:type/:name', async (req, res) => {
|
|
577
|
-
const { type, name } = req.params;
|
|
578
|
-
if (!ELEMENT_TYPES.includes(type)) {
|
|
579
|
-
res.status(400).json({ error: `Invalid element type: ${type}` });
|
|
580
|
-
return;
|
|
581
|
-
}
|
|
582
|
-
if (name.includes('..') || name.includes('/') || name.includes('\\')) {
|
|
583
|
-
res.status(400).json({ error: 'Invalid element name' });
|
|
603
|
+
const elementType = req.params.type;
|
|
604
|
+
const filename = req.params.name;
|
|
605
|
+
// Validate element type against known types to prevent arbitrary path construction
|
|
606
|
+
if (!ELEMENT_TYPES.includes(elementType)) {
|
|
607
|
+
res.status(400).json({ error: `Invalid element type: ${elementType}` });
|
|
584
608
|
return;
|
|
585
609
|
}
|
|
586
610
|
try {
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
// for client-side parsing. Extract rawContent if available, otherwise serialize.
|
|
599
|
-
const data = opResult.data;
|
|
600
|
-
const rawContent = data.rawContent || data.raw_content;
|
|
601
|
-
if (typeof rawContent === 'string') {
|
|
602
|
-
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
|
|
603
|
-
res.send(rawContent);
|
|
604
|
-
}
|
|
605
|
-
else {
|
|
606
|
-
// Fallback: return JSON representation
|
|
607
|
-
res.json(data);
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
catch {
|
|
611
|
-
res.status(500).json({ error: `Failed to get element: ${type}/${name}` });
|
|
612
|
-
}
|
|
613
|
-
});
|
|
614
|
-
/**
|
|
615
|
-
* GET /api/stats
|
|
616
|
-
* Portfolio statistics — lightweight aggregate, uses list_elements counts.
|
|
617
|
-
*/
|
|
618
|
-
router.get('/stats', async (_req, res) => {
|
|
619
|
-
try {
|
|
620
|
-
const stats = {};
|
|
621
|
-
let total = 0;
|
|
622
|
-
// Parallelize stats queries
|
|
623
|
-
const typeStats = await Promise.all(ELEMENT_TYPES.map(async (type) => {
|
|
624
|
-
const opResult = asSingleResult(await handler.handleRead({
|
|
625
|
-
operation: 'list_elements',
|
|
626
|
-
params: { element_type: toSingularType(type), page: 1, pageSize: 1 },
|
|
627
|
-
}));
|
|
628
|
-
if (opResult.success && opResult.data) {
|
|
629
|
-
const data = opResult.data;
|
|
630
|
-
const pagination = data.pagination;
|
|
631
|
-
return { type, count: typeof pagination?.totalItems === 'number' ? pagination.totalItems : 0 };
|
|
632
|
-
}
|
|
633
|
-
return { type, count: 0 };
|
|
634
|
-
}));
|
|
635
|
-
for (const { type, count } of typeStats) {
|
|
636
|
-
stats[type] = count;
|
|
637
|
-
total += count;
|
|
638
|
-
}
|
|
639
|
-
res.json({ stats, total });
|
|
640
|
-
}
|
|
641
|
-
catch {
|
|
642
|
-
res.status(500).json({ error: 'Failed to get stats' });
|
|
643
|
-
}
|
|
644
|
-
});
|
|
645
|
-
/**
|
|
646
|
-
* GET /api/collection
|
|
647
|
-
* Proxies the community collection index.
|
|
648
|
-
* No MCP-AQL equivalent — uses direct fetch (same as legacy).
|
|
649
|
-
*/
|
|
650
|
-
router.get('/collection', async (_req, res) => {
|
|
651
|
-
res.setHeader('Cache-Control', 'no-cache');
|
|
652
|
-
try {
|
|
653
|
-
const response = await fetch('https://raw.githubusercontent.com/DollhouseMCP/collection/main/public/collection-index.json');
|
|
654
|
-
if (response.ok) {
|
|
655
|
-
const data = await response.text();
|
|
656
|
-
res.setHeader('Content-Type', 'application/json');
|
|
657
|
-
res.send(data);
|
|
611
|
+
// codeql[js/request-forgery] — mitigated: domain and repo are hardcoded constants,
|
|
612
|
+
// elementType is validated against ELEMENT_TYPES whitelist above, path traversal
|
|
613
|
+
// is checked, and the only reachable target is a specific public GitHub repository.
|
|
614
|
+
const githubUrl = `https://raw.githubusercontent.com/DollhouseMCP/collection/main/${elementPath}`;
|
|
615
|
+
const response = await fetch(githubUrl);
|
|
616
|
+
if (!response.ok) {
|
|
617
|
+
res.status(response.status === 404 ? 404 : 502).json({
|
|
618
|
+
error: response.status === 404
|
|
619
|
+
? `Collection element not found: ${elementPath}`
|
|
620
|
+
: `Failed to fetch from GitHub (HTTP ${response.status})`,
|
|
621
|
+
});
|
|
658
622
|
return;
|
|
659
623
|
}
|
|
624
|
+
const content = await response.text();
|
|
625
|
+
const validation = validateElementContent(filename, content, elementType);
|
|
626
|
+
const singularType = PLURAL_TO_SINGULAR[elementType] || (elementType.endsWith('s') ? elementType.slice(0, -1) : elementType);
|
|
627
|
+
res.json({
|
|
628
|
+
metadata: validation.metadata,
|
|
629
|
+
body: validation.body,
|
|
630
|
+
raw: content,
|
|
631
|
+
type: singularType,
|
|
632
|
+
validation: {
|
|
633
|
+
status: validation.valid ? 'pass' : 'warn',
|
|
634
|
+
...(validation.rejection && {
|
|
635
|
+
reason: validation.rejection.reason,
|
|
636
|
+
severity: validation.rejection.severity,
|
|
637
|
+
patterns: validation.rejection.patterns,
|
|
638
|
+
}),
|
|
639
|
+
},
|
|
640
|
+
});
|
|
660
641
|
}
|
|
661
|
-
catch {
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
join(portfolioDir, '..', 'collection', 'public', 'collection-index.json'),
|
|
665
|
-
];
|
|
666
|
-
for (const localPath of localPaths) {
|
|
667
|
-
try {
|
|
668
|
-
const content = await readFile(localPath, 'utf-8');
|
|
669
|
-
res.setHeader('Content-Type', 'application/json');
|
|
670
|
-
res.send(content);
|
|
671
|
-
return;
|
|
672
|
-
}
|
|
673
|
-
catch { /* try next */ }
|
|
642
|
+
catch (err) {
|
|
643
|
+
logger.error('[WebUI/Gateway] Failed to fetch collection content:', err);
|
|
644
|
+
res.status(502).json({ error: 'Failed to fetch collection element' });
|
|
674
645
|
}
|
|
675
|
-
res.status(404).json({ error: 'Collection index not available' });
|
|
676
646
|
});
|
|
677
647
|
/**
|
|
678
648
|
* POST /api/install
|
|
@@ -720,4 +690,4 @@ export function createGatewayApiRoutes(handler, portfolioDir) {
|
|
|
720
690
|
});
|
|
721
691
|
return router;
|
|
722
692
|
}
|
|
723
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3dlYi9yb3V0ZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUVILE9BQU8sT0FBTyxFQUFFLEVBQUUsTUFBTSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzNELE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNuRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNuRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFHNUMsNEVBQTRFO0FBQzVFLFNBQVMsY0FBYyxDQUFDLEtBQWE7SUFDbkMsT0FBTyxLQUFLLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ2hDLENBQUM7QUFDRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUVuRSxNQUFNLGFBQWEsR0FBRyxDQUFDLFVBQVUsRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsV0FBVyxDQUFVLENBQUM7QUFFdEcsNkNBQTZDO0FBQzdDLE1BQU0sbUJBQW1CLEdBQUcsU0FBUyxDQUFDO0FBRXRDOzs7R0FHRztBQUNILE1BQU0sd0JBQXdCO0lBR1Q7SUFDQTtJQUhYLFVBQVUsR0FBYSxFQUFFLENBQUM7SUFDbEMsWUFDbUIsV0FBbUIsRUFDbkIsUUFBZ0I7UUFEaEIsZ0JBQVcsR0FBWCxXQUFXLENBQVE7UUFDbkIsYUFBUSxHQUFSLFFBQVEsQ0FBUTtJQUNoQyxDQUFDO0lBRUoscUVBQXFFO0lBQ3JFLFVBQVU7UUFDUixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFD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LCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFdlYiBVSSBBUEkgUm91dGVzXG4gKlxuICogUkVTVCBlbmRwb2ludHMgZm9yIHJlYWRpbmcgcG9ydGZvbGlvIGVsZW1lbnRzLlxuICogUmVhZC1vbmx5IOKAlCBubyBtdXRhdGlvbnMgaW4gVjEuXG4gKlxuICogQWxsIGVsZW1lbnQgY29udGVudCBpcyBzYW5pdGl6ZWQgYmVmb3JlIHNlcnZpbmcgdG8gcHJldmVudCBYU1MuXG4gKlxuICogU2VjdXJpdHkgbm90ZTogVGhpcyB3ZWIgc2VydmVyIGJpbmRzIHRvIDEyNy4wLjAuMSBvbmx5IChzZWUgc2VydmVyLnRzKS5cbiAqIFJhdGUgbGltaXRpbmcgb24gcmVhZC1vbmx5IEdFVCBlbmRwb2ludHMgaXMgbm90IHJlcXVpcmVkIGZvciBsb2NhbGhvc3Qtb25seVxuICogbWFuYWdlbWVudCBpbnRlcmZhY2VzLiBUaGUgUE9TVCAvYXBpL2luc3RhbGwgZW5kcG9pbnQgaGFzIGV4cGxpY2l0IHJhdGUgbGltaXRpbmdcbiAqIHZpYSBTbGlkaW5nV2luZG93UmF0ZUxpbWl0ZXIgKG1heCAxMCBwZXIgbWludXRlKS5cbiAqIGNvZGVxbFtqcy9taXNzaW5nLXJhdGUtbGltaXRpbmddIOKAlCBBY2tub3dsZWRnZWQ7IGxvY2FsaG9zdC1vbmx5IGJpbmRpbmcgbWl0aWdhdGVzIERvUyByaXNrLlxuICovXG5cbmltcG9ydCBleHByZXNzLCB7IFJvdXRlciB9IGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHsgcmVhZGRpciwgcmVhZEZpbGUsIHN0YXQgfSBmcm9tICdub2RlOmZzL3Byb21pc2VzJztcbmltcG9ydCB7IGpvaW4sIGV4dG5hbWUsIHJlc29sdmUgfSBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHsgU2VjdXJlWWFtbFBhcnNlciB9IGZyb20gJy4uL3NlY3VyaXR5L3NlY3VyZVlhbWxQYXJzZXIuanMnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvbG9nZ2VyLmpzJztcbmltcG9ydCB0eXBlIHsgTUNQQVFMSGFuZGxlciB9IGZyb20gJy4uL2hhbmRsZXJzL21jcC1hcWwvTUNQQVFMSGFuZGxlci5qcyc7XG5cbi8qKiBOb3JtYWxpemUgdXNlciBpbnB1dCB0byBORkMgZm9ybSB0byBwcmV2ZW50IFVuaWNvZGUgaG9tb2dyYXBoIGF0dGFja3MgKi9cbmZ1bmN0aW9uIG5vcm1hbGl6ZUlucHV0KGlucHV0OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gaW5wdXQubm9ybWFsaXplKCdORkMnKTtcbn1cbmltcG9ydCB7IENvbnRlbnRWYWxpZGF0b3IgfSBmcm9tICcuLi9zZWN1cml0eS9jb250ZW50VmFsaWRhdG9yLmpzJztcblxuY29uc3QgRUxFTUVOVF9UWVBFUyA9IFsncGVyc29uYXMnLCAnc2tpbGxzJywgJ3RlbXBsYXRlcycsICdhZ2VudHMnLCAnbWVtb3JpZXMnLCAnZW5zZW1ibGVzJ10gYXMgY29uc3Q7XG5cbi8qKiBNYXggZmlsZSBzaXplIGZvciBlbGVtZW50IHJlYWRzICgxIE1CKSAqL1xuY29uc3QgTUFYX0ZJTEVfU0laRV9CWVRFUyA9IDFfMDQ4XzU3NjtcblxuLyoqXG4gKiBTaW1wbGUgc2xpZGluZy13aW5kb3cgcmF0ZSBsaW1pdGVyLlxuICogVHJhY2tzIHRpbWVzdGFtcHMgb2YgcmVjZW50IHJlcXVlc3RzIGFuZCBldmljdHMgZW50cmllcyBvbGRlciB0aGFuIHRoZSB3aW5kb3cuXG4gKi9cbmNsYXNzIFNsaWRpbmdXaW5kb3dSYXRlTGltaXRlciB7XG4gIHByaXZhdGUgdGltZXN0YW1wczogbnVtYmVyW10gPSBbXTtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBtYXhSZXF1ZXN0czogbnVtYmVyLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgd2luZG93TXM6IG51bWJlcixcbiAgKSB7fVxuXG4gIC8qKiBSZXR1cm5zIHRydWUgaWYgdGhlIHJlcXVlc3QgaXMgYWxsb3dlZCwgZmFsc2UgaWYgcmF0ZS1saW1pdGVkLiAqL1xuICB0cnlBY3F1aXJlKCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgLy8gRXZpY3QgZW50cmllcyBvdXRzaWRlIHRoZSB3aW5kb3dcbiAgICB0aGlzLnRpbWVzdGFtcHMgPSB0aGlzLnRpbWVzdGFtcHMuZmlsdGVyKHQgPT4gbm93IC0gdCA8IHRoaXMud2luZG93TXMpO1xuICAgIGlmICh0aGlzLnRpbWVzdGFtcHMubGVuZ3RoID49IHRoaXMubWF4UmVxdWVzdHMpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgdGhpcy50aW1lc3RhbXBzLnB1c2gobm93KTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxufVxuXG4vKiogUmF0ZSBsaW1pdGVyIGZvciAvYXBpL2luc3RhbGw6IG1heCAxMCBpbnN0YWxscyBwZXIgNjAgc2Vjb25kcyAqL1xuY29uc3QgaW5zdGFsbFJhdGVMaW1pdGVyID0gbmV3IFNsaWRpbmdXaW5kb3dSYXRlTGltaXRlcigxMCwgNjBfMDAwKTtcblxuLyoqIFNhbml0aXplIHRleHQgY29udGVudCB0byBwcmV2ZW50IFhTUyBpbiByZW5kZXJlZCBIVE1MICovXG5mdW5jdGlvbiBzYW5pdGl6ZUZvckh0bWwodGV4dDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHRleHRcbiAgICAucmVwbGFjZSgvJi9nLCAnJmFtcDsnKVxuICAgIC5yZXBsYWNlKC88L2csICcmbHQ7JylcbiAgICAucmVwbGFjZSgvPi9nLCAnJmd0OycpXG4gICAgLnJlcGxhY2UoL1wiL2csICcmcXVvdDsnKVxuICAgIC5yZXBsYWNlKC8nL2csICcmIzM5OycpO1xufVxuXG4vKiogUGFyc2UgWUFNTCBmcm9udCBtYXR0ZXIgZnJvbSBhIG1hcmtkb3duIGZpbGUgKi9cbmZ1bmN0aW9uIHBhcnNlRnJvbnRNYXR0ZXIoY29udGVudDogc3RyaW5nKTogeyBtZXRhZGF0YTogUmVjb3JkPHN0cmluZywgdW5rbm93bj47IGJvZHk6IHN0cmluZyB9IHtcbiAgY29uc3QgbWF0Y2ggPSBjb250ZW50Lm1hdGNoKC9eLS0tXFxyP1xcbihbXFxzXFxTXSo/KVxccj9cXG4tLS1cXHI/XFxuPyhbXFxzXFxTXSopJC8pO1xuICBpZiAoIW1hdGNoKSB7XG4gICAgcmV0dXJuIHsgbWV0YWRhdGE6IHt9LCBib2R5OiBjb250ZW50IH07XG4gIH1cblxuICB0cnkge1xuICAgIGNvbnN0IHBhcnNlZCA9IFNlY3VyZVlhbWxQYXJzZXIucGFyc2VSYXdZYW1sKG1hdGNoWzFdKTtcbiAgICBjb25zdCBtZXRhZGF0YSA9ICh0eXBlb2YgcGFyc2VkID09PSAnb2JqZWN0JyAmJiBwYXJzZWQgIT09IG51bGwpID8gcGFyc2VkIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IDoge307XG4gICAgcmV0dXJuIHsgbWV0YWRhdGEsIGJvZHk6IG1hdGNoWzJdIH07XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB7IG1ldGFkYXRhOiB7fSwgYm9keTogbWF0Y2hbMl0gfHwgY29udGVudCB9O1xuICB9XG59XG5cbi8qKiBQYXJzZSBhIFlBTUwtb25seSBmaWxlIChtZW1vcmllcykgKi9cbmZ1bmN0aW9uIHBhcnNlWWFtbEZpbGUoY29udGVudDogc3RyaW5nKTogeyBtZXRhZGF0YTogUmVjb3JkPHN0cmluZywgdW5rbm93bj47IGJvZHk6IHN0cmluZyB9IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBwYXJzZWQgPSBTZWN1cmVZYW1sUGFyc2VyLnBhcnNlUmF3WWFtbChjb250ZW50KTtcbiAgICBjb25zdCBtZXRhZGF0YSA9ICh0eXBlb2YgcGFyc2VkID09PSAnb2JqZWN0JyAmJiBwYXJzZWQgIT09IG51bGwpID8gcGFyc2VkIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IDoge307XG4gICAgcmV0dXJuIHsgbWV0YWRhdGEsIGJvZHk6ICcnIH07XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB7IG1ldGFkYXRhOiB7fSwgYm9keTogY29udGVudCB9O1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVBcGlSb3V0ZXMocG9ydGZvbGlvRGlyOiBzdHJpbmcpOiBSb3V0ZXIge1xuICBjb25zdCByb3V0ZXIgPSBSb3V0ZXIoKTtcblxuICAvKipcbiAgICogR0VUIC9hcGkvZWxlbWVudHNcbiAgICogUmV0dXJucyBhbGwgZWxlbWVudHMgYWNyb3NzIGFsbCB0eXBlcyB3aXRoIG1ldGFkYXRhLlxuICAgKiBTdXBwb3J0cyBvcHRpb25hbCBwYWdpbmF0aW9uOiA/cGFnZT0xJnBhZ2VTaXplPTUwXG4gICAqIFdpdGhvdXQgcGFnaW5hdGlvbiBwYXJhbXMsIHJldHVybnMgYWxsIGVsZW1lbnRzIChiYWNrd2FyZCBjb21wYXRpYmxlKS5cbiAgICovXG4gIHJvdXRlci5nZXQoJy9lbGVtZW50cycsIGFzeW5jIChyZXEsIHJlcykgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBwYWdlUGFyYW0gPSByZXEucXVlcnkucGFnZSBhcyBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgICBjb25zdCBwYWdlU2l6ZVBhcmFtID0gcmVxLnF1ZXJ5LnBhZ2VTaXplIGFzIHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IHdhbnRQYWdpbmF0aW9uID0gcGFnZVBhcmFtICE9PSB1bmRlZmluZWQgJiYgcGFnZVNpemVQYXJhbSAhPT0gdW5kZWZpbmVkO1xuICAgICAgY29uc3QgcGFnZSA9IE1hdGgubWF4KDEsIHBhcnNlSW50KHBhZ2VQYXJhbSB8fCAnMScsIDEwKSB8fCAxKTtcbiAgICAgIGNvbnN0IHBhZ2VTaXplID0gTWF0aC5tYXgoMSwgTWF0aC5taW4oMjAwLCBwYXJzZUludChwYWdlU2l6ZVBhcmFtIHx8ICc1MCcsIDEwKSB8fCA1MCkpO1xuXG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHVua25vd25bXT4gPSB7fTtcbiAgICAgIGxldCB0b3RhbENvdW50ID0gMDtcblxuICAgICAgZm9yIChjb25zdCB0eXBlIG9mIEVMRU1FTlRfVFlQRVMpIHtcbiAgICAgICAgY29uc3QgdHlwZURpciA9IGpvaW4ocG9ydGZvbGlvRGlyLCB0eXBlKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBkaXJTdGF0ID0gYXdhaXQgc3RhdCh0eXBlRGlyKTtcbiAgICAgICAgICBpZiAoIWRpclN0YXQuaXNEaXJlY3RvcnkoKSkgY29udGludWU7XG5cbiAgICAgICAgICBjb25zdCBmaWxlcyA9IGF3YWl0IHJlYWRkaXIodHlwZURpcik7XG4gICAgICAgICAgY29uc3QgZWxlbWVudHM6IHVua25vd25bXSA9IFtdO1xuXG4gICAgICAgICAgZm9yIChjb25zdCBmaWxlIG9mIGZpbGVzKSB7XG4gICAgICAgICAgICAvLyBTa2lwIGJhY2t1cHMsIGhpZGRlbiBmaWxlcywgc3RhdGUgZmlsZXNcbiAgICAgICAgICAgIGlmIChmaWxlLnN0YXJ0c1dpdGgoJy4nKSB8fCBmaWxlLmluY2x1ZGVzKCcuYmFja3VwLScpIHx8IGZpbGUuaW5jbHVkZXMoJy5zdGF0ZScpKSBjb250aW51ZTtcblxuICAgICAgICAgICAgY29uc3QgZXh0ID0gZXh0bmFtZShmaWxlKTtcbiAgICAgICAgICAgIGlmIChleHQgIT09ICcubWQnICYmIGV4dCAhPT0gJy55YW1sJyAmJiBleHQgIT09ICcueW1sJykgY29udGludWU7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIGNvbnN0IGZpbGVQYXRoID0gam9pbih0eXBlRGlyLCBmaWxlKTtcblxuICAgICAgICAgICAgICAvLyBTa2lwIGZpbGVzIGxhcmdlciB0aGFuIDEgTUJcbiAgICAgICAgICAgICAgY29uc3QgZmlsZVN0YXQgPSBhd2FpdCBzdGF0KGZpbGVQYXRoKTtcbiAgICAgICAgICAgICAgaWYgKGZpbGVTdGF0LnNpemUgPiBNQVhfRklMRV9TSVpFX0JZVEVTKSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKGBbV2ViVUldIFNraXBwaW5nIG92ZXJzaXplZCBmaWxlICgke2ZpbGVTdGF0LnNpemV9IGJ5dGVzKTogJHtmaWxlfWApO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IHJlYWRGaWxlKGZpbGVQYXRoLCAndXRmLTgnKTtcbiAgICAgICAgICAgICAgY29uc3QgeyBtZXRhZGF0YSB9ID0gZXh0ID09PSAnLm1kJyA/IHBhcnNlRnJvbnRNYXR0ZXIoY29udGVudCkgOiBwYXJzZVlhbWxGaWxlKGNvbnRlbnQpO1xuXG4gICAgICAgICAgICAgIGVsZW1lbnRzLnB1c2goe1xuICAgICAgICAgICAgICAgIG5hbWU6IG1ldGFkYXRhLm5hbWUgfHwgZmlsZS5yZXBsYWNlKGV4dCwgJycpLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBtZXRhZGF0YS5kZXNjcmlwdGlvbiB8fCAnJyxcbiAgICAgICAgICAgICAgICB0eXBlOiB0eXBlLnNsaWNlKDAsIC0xKSwgLy8gcGx1cmFsIOKGkiBzaW5ndWxhclxuICAgICAgICAgICAgICAgIHZlcnNpb246IG1ldGFkYXRhLnZlcnNpb24gfHwgJzEuMC4wJyxcbiAgICAgICAgICAgICAgICBhdXRob3I6IG1ldGFkYXRhLmF1dGhvciB8fCAnJyxcbiAgICAgICAgICAgICAgICBjYXRlZ29yeTogbWV0YWRhdGEuY2F0ZWdvcnkgfHwgJycsXG4gICAgICAgICAgICAgICAgdGFnczogbWV0YWRhdGEudGFncyB8fCAnJyxcbiAgICAgICAgICAgICAgICBjcmVhdGVkOiBtZXRhZGF0YS5jcmVhdGVkIHx8ICcnLFxuICAgICAgICAgICAgICAgIGZpbGVuYW1lOiBmaWxlLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICBsb2dnZXIuZGVidWcoYFtXZWJVSV0gRmFpbGVkIHRvIHBhcnNlICR7ZmlsZX06YCwgZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXN1bHRbdHlwZV0gPSBlbGVtZW50cztcbiAgICAgICAgICB0b3RhbENvdW50ICs9IGVsZW1lbnRzLmxlbmd0aDtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgcmVzdWx0W3R5cGVdID0gW107XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHdhbnRQYWdpbmF0aW9uKSB7XG4gICAgICAgIC8vIEZsYXR0ZW4gYWxsIGVsZW1lbnRzLCBwYWdpbmF0ZSwgdGhlbiByZXR1cm5cbiAgICAgICAgY29uc3QgYWxsRWxlbWVudHM6IHVua25vd25bXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IHR5cGUgb2YgRUxFTUVOVF9UWVBFUykge1xuICAgICAgICAgIGFsbEVsZW1lbnRzLnB1c2goLi4uKHJlc3VsdFt0eXBlXSB8fCBbXSkpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gKHBhZ2UgLSAxKSAqIHBhZ2VTaXplO1xuICAgICAgICBjb25zdCBwYWdlZCA9IGFsbEVsZW1lbnRzLnNsaWNlKHN0YXJ0LCBzdGFydCArIHBhZ2VTaXplKTtcbiAgICAgICAgY29uc3QgdG90YWxQYWdlcyA9IE1hdGguY2VpbChhbGxFbGVtZW50cy5sZW5ndGggLyBwYWdlU2l6ZSk7XG4gICAgICAgIHJlcy5qc29uKHtcbiAgICAgICAgICBlbGVtZW50czogcGFnZWQsXG4gICAgICAgICAgdG90YWxDb3VudDogYWxsRWxlbWVudHMubGVuZ3RoLFxuICAgICAgICAgIHBhZ2UsXG4gICAgICAgICAgcGFnZVNpemUsXG4gICAgICAgICAgdG90YWxQYWdlcyxcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBCYWNrd2FyZC1jb21wYXRpYmxlOiBncm91cGVkIGJ5IHR5cGVcbiAgICAgICAgcmVzLmpzb24oeyBlbGVtZW50czogcmVzdWx0LCB0b3RhbENvdW50IH0pO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgbG9nZ2VyLmVycm9yKCdbV2ViVUldIEZhaWxlZCB0byBsaXN0IGVsZW1lbnRzOicsIGVycik7XG4gICAgICByZXMuc3RhdHVzKDUwMCkuanNvbih7IGVycm9yOiAnRmFpbGVkIHRvIGxpc3QgZWxlbWVudHMnIH0pO1xuICAgIH1cbiAgfSk7XG5cbiAgLyoqXG4gICAqIEdFVCAvYXBpL2VsZW1lbnRzLzp0eXBlXG4gICAqIFJldHVybnMgYWxsIGVsZW1lbnRzIG9mIGEgc3BlY2lmaWMgdHlwZVxuICAgKi9cbiAgcm91dGVyLmdldCgnL2VsZW1lbnRzLzp0eXBlJywgYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgY29uc3QgdHlwZSA9IG5vcm1hbGl6ZUlucHV0KHJlcS5wYXJhbXMudHlwZSk7XG4gICAgaWYgKCFFTEVNRU5UX1RZUEVTLmluY2x1ZGVzKHR5cGUgYXMgdHlwZW9mIEVMRU1FTlRfVFlQRVNbbnVtYmVyXSkpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHsgZXJyb3I6IGBJbnZhbGlkIGVsZW1lbnQgdHlwZTogJHt0eXBlfWAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHR5cGVEaXIgPSBqb2luKHBvcnRmb2xpb0RpciwgdHlwZSk7XG4gICAgICBjb25zdCBmaWxlcyA9IGF3YWl0IHJlYWRkaXIodHlwZURpcik7XG4gICAgICBjb25zdCBlbGVtZW50czogdW5rbm93bltdID0gW107XG5cbiAgICAgIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgICAgICBpZiAoZmlsZS5zdGFydHNXaXRoKCcuJykgfHwgZmlsZS5pbmNsdWRlcygnLmJhY2t1cC0nKSB8fCBmaWxlLmluY2x1ZGVzKCcuc3RhdGUnKSkgY29udGludWU7XG5cbiAgICAgICAgY29uc3QgZXh0ID0gZXh0bmFtZShmaWxlKTtcbiAgICAgICAgaWYgKGV4dCAhPT0gJy5tZCcgJiYgZXh0ICE9PSAnLnlhbWwnICYmIGV4dCAhPT0gJy55bWwnKSBjb250aW51ZTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IGZpbGVQYXRoID0gam9pbih0eXBlRGlyLCBmaWxlKTtcblxuICAgICAgICAgIC8vIFNraXAgZmlsZXMgbGFyZ2VyIHRoYW4gMSBNQlxuICAgICAgICAgIGNvbnN0IGZpbGVTdGF0ID0gYXdhaXQgc3RhdChmaWxlUGF0aCk7XG4gICAgICAgICAgaWYgKGZpbGVTdGF0LnNpemUgPiBNQVhfRklMRV9TSVpFX0JZVEVTKSB7XG4gICAgICAgICAgICBsb2dnZXIuZGVidWcoYFtXZWJVSV0gU2tpcHBpbmcgb3ZlcnNpemVkIGZpbGUgKCR7ZmlsZVN0YXQuc2l6ZX0gYnl0ZXMpOiAke2ZpbGV9YCk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgcmVhZEZpbGUoZmlsZVBhdGgsICd1dGYtOCcpO1xuICAgICAgICAgIGNvbnN0IHsgbWV0YWRhdGEsIGJvZHkgfSA9IGV4dCA9PT0gJy5tZCcgPyBwYXJzZUZyb250TWF0dGVyKGNvbnRlbnQpIDogcGFyc2VZYW1sRmlsZShjb250ZW50KTtcblxuICAgICAgICAgIGVsZW1lbnRzLnB1c2goe1xuICAgICAgICAgICAgbmFtZTogbWV0YWRhdGEubmFtZSB8fCBmaWxlLnJlcGxhY2UoZXh0LCAnJyksXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogbWV0YWRhdGEuZGVzY3JpcHRpb24gfHwgJycsXG4gICAgICAgICAgICB0eXBlOiB0eXBlLnNsaWNlKDAsIC0xKSxcbiAgICAgICAgICAgIHZlcnNpb246IG1ldGFkYXRhLnZlcnNpb24gfHwgJzEuMC4wJyxcbiAgICAgICAgICAgIGF1dGhvcjogbWV0YWRhdGEuYXV0aG9yIHx8ICcnLFxuICAgICAgICAgICAgY2F0ZWdvcnk6IG1ldGFkYXRhLmNhdGVnb3J5IHx8ICcnLFxuICAgICAgICAgICAgdGFnczogbWV0YWRhdGEudGFncyB8fCAnJyxcbiAgICAgICAgICAgIGNyZWF0ZWQ6IG1ldGFkYXRhLmNyZWF0ZWQgfHwgJycsXG4gICAgICAgICAgICBtb2RpZmllZDogbWV0YWRhdGEubW9kaWZpZWQgfHwgJycsXG4gICAgICAgICAgICBmaWxlbmFtZTogZmlsZSxcbiAgICAgICAgICAgIGJvZHlQcmV2aWV3OiBzYW5pdGl6ZUZvckh0bWwoYm9keS5zbGljZSgwLCA1MDApKSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgbG9nZ2VyLmRlYnVnKGBbV2ViVUldIEZhaWxlZCB0byBwYXJzZSAke2ZpbGV9OmAsIGVycik7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmVzLmpzb24oeyB0eXBlLCBlbGVtZW50cywgY291bnQ6IGVsZW1lbnRzLmxlbmd0aCB9KTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHsgZXJyb3I6IGBGYWlsZWQgdG8gbGlzdCAke3R5cGV9YCB9KTtcbiAgICB9XG4gIH0pO1xuXG4gIC8qKlxuICAgKiBHRVQgL2FwaS9lbGVtZW50cy86dHlwZS86bmFtZVxuICAgKiBSZXR1cm5zIHRoZSByYXcgZmlsZSBjb250ZW50IGFzIHBsYWluIHRleHQuXG4gICAqIFRoZSBjbGllbnQtc2lkZSBhcHAgaGFuZGxlcyBZQU1ML21hcmtkb3duIHBhcnNpbmcgYW5kIHJlbmRlcmluZy5cbiAgICovXG4gIHJvdXRlci5nZXQoJy9lbGVtZW50cy86dHlwZS86bmFtZScsIGFzeW5jIChyZXEsIHJlcykgPT4ge1xuICAgIGNvbnN0IHsgdHlwZSwgbmFtZSB9ID0gcmVxLnBhcmFtcztcbiAgICBpZiAoIUVMRU1FTlRfVFlQRVMuaW5jbHVkZXModHlwZSBhcyB0eXBlb2YgRUxFTUVOVF9UWVBFU1tudW1iZXJdKSkge1xuICAgICAgcmVzLnN0YXR1cyg0MDApLmpzb24oeyBlcnJvcjogYEludmFsaWQgZWxlbWVudCB0eXBlOiAke3R5cGV9YCB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBQcmV2ZW50IHBhdGggdHJhdmVyc2FsXG4gICAgaWYgKG5hbWUuaW5jbHVkZXMoJy4uJykgfHwgbmFtZS5pbmNsdWRlcygnLycpIHx8IG5hbWUuaW5jbHVkZXMoJ1xcXFwnKSkge1xuICAgICAgcmVzLnN0YXR1cyg0MDApLmpzb24oeyBlcnJvcjogJ0ludmFsaWQgZWxlbWVudCBuYW1lJyB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgdHlwZURpciA9IGpvaW4ocG9ydGZvbGlvRGlyLCB0eXBlKTtcbiAgICAgIGNvbnN0IGZpbGVzID0gYXdhaXQgcmVhZGRpcih0eXBlRGlyKTtcblxuICAgICAgLy8gRmluZCB0aGUgZmlsZSBieSBuYW1lICh3aXRoIG9yIHdpdGhvdXQgZXh0ZW5zaW9uKVxuICAgICAgY29uc3QgbWF0Y2ggPSBmaWxlcy5maW5kKGYgPT4ge1xuICAgICAgICBjb25zdCBiYXNlID0gZi5yZXBsYWNlKGV4dG5hbWUoZiksICcnKTtcbiAgICAgICAgcmV0dXJuIGJhc2UgPT09IG5hbWUgfHwgZiA9PT0gbmFtZTtcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoIW1hdGNoKSB7XG4gICAgICAgIHJlcy5zdGF0dXMoNDA0KS5qc29uKHsgZXJyb3I6IGBFbGVtZW50IG5vdCBmb3VuZDogJHt0eXBlfS8ke25hbWV9YCB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBmaWxlUGF0aCA9IGpvaW4odHlwZURpciwgbWF0Y2gpO1xuXG4gICAgICAvLyBWZXJpZnkgcmVzb2x2ZWQgcGF0aCBzdGF5cyB3aXRoaW4gcG9ydGZvbGlvIGRpcmVjdG9yeSAoZGVmZW5zZSBpbiBkZXB0aClcbiAgICAgIGNvbnN0IHJlc29sdmVkUGF0aCA9IHJlc29sdmUoZmlsZVBhdGgpO1xuICAgICAgaWYgKCFyZXNvbHZlZFBhdGguc3RhcnRzV2l0aChyZXNvbHZlKHBvcnRmb2xpb0RpcikpKSB7XG4gICAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHsgZXJyb3I6ICdQYXRoIHRyYXZlcnNhbCBkZXRlY3RlZCcgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gUmVqZWN0IGZpbGVzIGxhcmdlciB0aGFuIDEgTUJcbiAgICAgIGNvbnN0IGZpbGVTdGF0ID0gYXdhaXQgc3RhdChmaWxlUGF0aCk7XG4gICAgICBpZiAoZmlsZVN0YXQuc2l6ZSA+IE1BWF9GSUxFX1NJWkVfQllURVMpIHtcbiAgICAgICAgcmVzLnN0YXR1cyg0MTMpLmpzb24oeyBlcnJvcjogYEZpbGUgdG9vIGxhcmdlICgke2ZpbGVTdGF0LnNpemV9IGJ5dGVzKS4gTWF4IDEgTUIuYCB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgcmVhZEZpbGUoZmlsZVBhdGgsICd1dGYtOCcpO1xuXG4gICAgICAvLyBSZXR1cm4gcmF3IHRleHQg4oCUIGNsaWVudC1zaWRlIGhhbmRsZXMgcGFyc2luZy9yZW5kZXJpbmdcbiAgICAgIHJlcy5zZXRIZWFkZXIoJ0NvbnRlbnQtVHlwZScsICd0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04Jyk7XG4gICAgICByZXMuc2VuZChjb250ZW50KTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHsgZXJyb3I6IGBGYWlsZWQgdG8gZ2V0IGVsZW1lbnQ6ICR7dHlwZX0vJHtuYW1lfWAgfSk7XG4gICAgfVxuICB9KTtcblxuICAvKipcbiAgICogR0VUIC9hcGkvc3RhdHNcbiAgICogUmV0dXJucyBwb3J0Zm9saW8gc3RhdGlzdGljc1xuICAgKi9cbiAgcm91dGVyLmdldCgnL3N0YXRzJywgYXN5bmMgKF9yZXEsIHJlcykgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBzdGF0czogUmVjb3JkPHN0cmluZywgbnVtYmVyPiA9IHt9O1xuICAgICAgbGV0IHRvdGFsID0gMDtcblxuICAgICAgZm9yIChjb25zdCB0eXBlIG9mIEVMRU1FTlRfVFlQRVMpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB0eXBlRGlyID0gam9pbihwb3J0Zm9saW9EaXIsIHR5cGUpO1xuICAgICAgICAgIGNvbnN0IGZpbGVzID0gYXdhaXQgcmVhZGRpcih0eXBlRGlyKTtcbiAgICAgICAgICBjb25zdCBjb3VudCA9IGZpbGVzLmZpbHRlcihmID0+XG4gICAgICAgICAgICAhZi5zdGFydHNXaXRoKCcuJykgJiZcbiAgICAgICAgICAgICFmLmluY2x1ZGVzKCcuYmFja3VwLScpICYmXG4gICAgICAgICAgICAhZi5pbmNsdWRlcygnLnN0YXRlJykgJiZcbiAgICAgICAgICAgIFsnLm1kJywgJy55YW1sJywgJy55bWwnXS5pbmNsdWRlcyhleHRuYW1lKGYpKVxuICAgICAgICAgICkubGVuZ3RoO1xuICAgICAgICAgIHN0YXRzW3R5cGVdID0gY291bnQ7XG4gICAgICAgICAgdG90YWwgKz0gY291bnQ7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHN0YXRzW3R5cGVdID0gMDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXMuanNvbih7IHN0YXRzLCB0b3RhbCB9KTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHsgZXJyb3I6ICdGYWlsZWQgdG8gZ2V0IHN0YXRzJyB9KTtcbiAgICB9XG4gIH0pO1xuXG4gIC8qKlxuICAgKiBHRVQgL2FwaS9jb2xsZWN0aW9uXG4gICAqIFByb3hpZXMgdGhlIERvbGxob3VzZU1DUCBjb21tdW5pdHkgY29sbGVjdGlvbiBpbmRleC5cbiAgICogUHJlZmVycyBHaXRIdWIgcmF3IChhdXRob3JpdGF0aXZlIHNvdXJjZSksIGZhbGxzIGJhY2sgdG8gbG9jYWwgZmlsZS5cbiAgICovXG4gIHJvdXRlci5nZXQoJy9jb2xsZWN0aW9uJywgYXN5bmMgKF9yZXEsIHJlcykgPT4ge1xuICAgIHJlcy5zZXRIZWFkZXIoJ0NhY2hlLUNvbnRyb2wnLCAnbm8tY2FjaGUnKTtcblxuICAgIC8vIFByZWZlciBHaXRIdWIgcmF3IChhdXRob3JpdGF0aXZlLCBhbHdheXMgZnJlc2gpXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9Eb2xsaG91c2VNQ1AvY29sbGVjdGlvbi9tYWluL3B1YmxpYy9jb2xsZWN0aW9uLWluZGV4Lmpzb24nKTtcbiAgICAgIGlmIChyZXNwb25zZS5vaykge1xuICAgICAgICBjb25zdCBkYXRhID0gYXdhaXQgcmVzcG9uc2UudGV4dCgpO1xuICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpO1xuICAgICAgICByZXMuc2VuZChkYXRhKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggeyAvKiBHaXRIdWIgdW5yZWFjaGFibGUg4oCUIGZhbGwgYmFjayB0byBsb2NhbCAqLyB9XG5cbiAgICAvLyBGYWxsIGJhY2sgdG8gbG9jYWwgY29sbGVjdGlvbiByZXBvIChkZXZlbG9wZXIgc2V0dXAsIG1heSBiZSBzdGFsZSlcbiAgICBjb25zdCBsb2NhbFBhdGhzID0gW1xuICAgICAgam9pbihwb3J0Zm9saW9EaXIsICcuLicsICcuLicsICcuLicsICdjb2xsZWN0aW9uJywgJ3B1YmxpYycsICdjb2xsZWN0aW9uLWluZGV4Lmpzb24nKSxcbiAgICAgIGpvaW4ocG9ydGZvbGlvRGlyLCAnLi4nLCAnY29sbGVjdGlvbicsICdwdWJsaWMnLCAnY29sbGVjdGlvbi1pbmRleC5qc29uJyksXG4gICAgXTtcblxuICAgIGZvciAoY29uc3QgbG9jYWxQYXRoIG9mIGxvY2FsUGF0aHMpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCByZWFkRmlsZShsb2NhbFBhdGgsICd1dGYtOCcpO1xuICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpO1xuICAgICAgICByZXMuc2VuZChjb250ZW50KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBjYXRjaCB7IC8qIHRyeSBuZXh0ICovIH1cbiAgICB9XG5cbiAgICByZXMuc3RhdHVzKDQwNCkuanNvbih7IGVycm9yOiAnQ29sbGVjdGlvbiBpbmRleCBub3QgYXZhaWxhYmxlJyB9KTtcbiAgfSk7XG5cbiAgLyoqXG4gICAqIFBPU1QgL2FwaS9pbnN0YWxsXG4gICAqIEluc3RhbGwgYSBjb2xsZWN0aW9uIGVsZW1lbnQgaW50byB0aGUgbG9jYWwgcG9ydGZvbGlvLlxuICAgKiBSb3V0ZXMgdGhyb3VnaCBEb2xsaG91c2VNQ1AncyBpbnN0YWxsX2NvbGxlY3Rpb25fY29udGVudCBwaXBlbGluZVxuICAgKiBmb3IgcHJvcGVyIHZhbGlkYXRpb24sIGdhdGVrZWVwZXIgY2hlY2tzLCBhbmQgZWxlbWVudCBtYW5hZ2VtZW50LlxuICAgKlxuICAgKiBSZXF1aXJlcyB0aGUgTUNQIHNlcnZlcidzIENvbGxlY3Rpb25IYW5kbGVyIHRvIGJlIGF2YWlsYWJsZS5cbiAgICogRmFsbHMgYmFjayB0byBkaXJlY3QgZmlsZSB3cml0ZSBpZiBub3QgKHN0YW5kYWxvbmUgd2ViIG1vZGUpLlxuICAgKi9cbiAgcm91dGVyLnBvc3QoJy9pbnN0YWxsJywgZXhwcmVzcy5qc29uKCksIGFzeW5jIChyZXEsIHJlcykgPT4ge1xuICAgIGlmICghaW5zdGFsbFJhdGVMaW1pdGVyLnRyeUFjcXVpcmUoKSkge1xuICAgICAgcmVzLnN0YXR1cyg0MjkpLmpzb24oeyBlcnJvcjogJ1RvbyBtYW55IGluc3RhbGwgcmVxdWVzdHMuIE1heCAxMCBwZXIgbWludXRlLicgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgeyBwYXRoOiBlbGVtZW50UGF0aCwgbmFtZSwgdHlwZSB9ID0gcmVxLmJvZHkgYXMgeyBwYXRoPzogc3RyaW5nOyBuYW1lPzogc3RyaW5nOyB0eXBlPzogc3RyaW5nIH07XG5cbiAgICBpZiAoIWVsZW1lbnRQYXRoIHx8ICF0eXBlIHx8ICFuYW1lKSB7XG4gICAgICByZXMuc3RhdHVzKDQwMCkuanNvbih7IGVycm9yOiAnTWlzc2luZyByZXF1aXJlZCBmaWVsZHM6IHBhdGgsIG5hbWUsIHR5cGUnIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFZhbGlkYXRlIHR5cGVcbiAgICBjb25zdCBwbHVyYWxUeXBlID0gdHlwZS5lbmRzV2l0aCgncycpID8gdHlwZSA6IGAke3R5cGV9c2A7XG4gICAgaWYgKCFFTEVNRU5UX1RZUEVTLmluY2x1ZGVzKHBsdXJhbFR5cGUgYXMgdHlwZW9mIEVMRU1FTlRfVFlQRVNbbnVtYmVyXSkpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHsgZXJyb3I6IGBJbnZhbGlkIGVsZW1lbnQgdHlwZTogJHt0eXBlfWAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gUHJldmVudCBwYXRoIHRyYXZlcnNhbFxuICAgIGlmIChlbGVtZW50UGF0aC5pbmNsdWRlcygnLi4nKSB8fCBuYW1lLmluY2x1ZGVzKCcuLicpKSB7XG4gICAgICByZXMuc3RhdHVzKDQwMCkuanNvbih7IGVycm9yOiAnSW52YWxpZCBwYXRoIG9yIG5hbWUnIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFZhbGlkYXRlIGVsZW1lbnRQYXRoIGNvbnRhaW5zIG9ubHkgc2FmZSBjaGFyYWN0ZXJzIChhbHBoYW51bWVyaWMsIGh5cGhlbnMsIHVuZGVyc2NvcmVzLCBkb3RzLCBzbGFzaGVzKVxuICAgIGlmICghL15bYS16QS1aMC05L18uLV0rJC8udGVzdChlbGVtZW50UGF0aCkpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHsgZXJyb3I6ICdJbnZhbGlkIGVsZW1lbnQgcGF0aCBjaGFyYWN0ZXJzJyB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgLy8gRmV0Y2ggY29udGVudCBmcm9tIEdpdEh1YlxuICAgICAgY29uc3QgZ2hVcmwgPSBgaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0RvbGxob3VzZU1DUC9jb2xsZWN0aW9uL21haW4vJHtlbGVtZW50UGF0aH1gO1xuXG4gICAgICAvLyBWYWxpZGF0ZSB0aGUgY29uc3RydWN0ZWQgVVJMIHN0YXlzIHdpdGhpbiBleHBlY3RlZCBkb21haW4gYW5kIHBhdGhcbiAgICAgIGNvbnN0IHBhcnNlZFVybCA9IG5ldyBVUkwoZ2hVcmwpO1xuICAgICAgaWYgKHBhcnNlZFVybC5ob3N0bmFtZSAhPT0gJ3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20nIHx8ICFwYXJzZWRVcmwucGF0aG5hbWUuc3RhcnRzV2l0aCgnL0RvbGxob3VzZU1DUC9jb2xsZWN0aW9uLycpKSB7XG4gICAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHsgZXJyb3I6ICdJbnZhbGlkIGNvbGxlY3Rpb24gcGF0aCcgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChnaFVybCk7XG4gICAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICAgIHJlcy5zdGF0dXMoNTAyKS5qc29uKHsgZXJyb3I6IGBGYWlsZWQgdG8gZmV0Y2ggZnJvbSBjb2xsZWN0aW9uOiBIVFRQICR7cmVzcG9uc2Uuc3RhdHVzfWAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCByZXNwb25zZS50ZXh0KCk7XG5cbiAgICAgIC8vIFZhbGlkYXRlIGNvbnRlbnQgdGhyb3VnaCB0aGUgc2VjdXJpdHkgcGlwZWxpbmUgYmVmb3JlIHdyaXRpbmdcbiAgICAgIGNvbnN0IGV4dCA9IGV4dG5hbWUoZWxlbWVudFBhdGgpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKGV4dCA9PT0gJy55YW1sJyB8fCBleHQgPT09ICcueW1sJykge1xuICAgICAgICAgIC8vIFZhbGlkYXRlIFlBTUwgY29udGVudCBmb3IgYm9tYnMsIGNpcmN1bGFyIHJlZmVyZW5jZXMsIG1hbGljaW91cyBwYXR0ZXJuc1xuICAgICAgICAgIGlmICghQ29udGVudFZhbGlkYXRvci52YWxpZGF0ZVlhbWxDb250ZW50KGNvbnRlbnQpKSB7XG4gICAgICAgICAgICByZXMuc3RhdHVzKDQyMikuanNvbih7IGVycm9yOiAnQ29udGVudCBmYWlsZWQgWUFNTCB2YWxpZGF0aW9uIOKAlCBwb3RlbnRpYWxseSBtYWxpY2lvdXMgcGF0dGVybnMgZGV0ZWN0ZWQnIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBTZWN1cmVZYW1sUGFyc2VyLnBhcnNlUmF3WWFtbChjb250ZW50KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBWYWxpZGF0ZSBtYXJrZG93bitmcm9udG1hdHRlciBjb250ZW50XG4gICAgICAgICAgU2VjdXJlWWFtbFBhcnNlci5wYXJzZShjb250ZW50KTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAocGFyc2VFcnIpIHtcbiAgICAgICAgcmVzLnN0YXR1cyg0MjIpLmpzb24oeyBlcnJvcjogYENvbnRlbnQgZmFpbGVkIHBhcnNlIHZhbGlkYXRpb246ICR7KHBhcnNlRXJyIGFzIEVycm9yKS5tZXNzYWdlfWAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gVmFsaWRhdGUgY29udGVudCBib2R5IGZvciBpbmplY3Rpb24gcGF0dGVybnNcbiAgICAgIGNvbnN0IHNpbmd1bGFyVHlwZSA9IHBsdXJhbFR5cGUuc2xpY2UoMCwgLTEpO1xuICAgICAgY29uc3QgY29udGV4dFR5cGVzID0gWydwZXJzb25hJywgJ3NraWxsJywgJ3RlbXBsYXRlJywgJ2FnZW50JywgJ21lbW9yeSddIGFzIGNvbnN0O1xuICAgICAgdHlwZSBDb250ZW50Q29udGV4dCA9IHR5cGVvZiBjb250ZXh0VHlwZXNbbnVtYmVyXTtcbiAgICAgIGNvbnN0IGNvbnRlbnRDb250ZXh0ID0gY29udGV4dFR5cGVzLmluY2x1ZGVzKHNpbmd1bGFyVHlwZSBhcyBDb250ZW50Q29udGV4dCkgPyBzaW5ndWxhclR5cGUgYXMgQ29udGVudENvbnRleHQgOiB1bmRlZmluZWQ7XG4gICAgICBjb25zdCB2YWxpZGF0aW9uUmVzdWx0ID0gQ29udGVudFZhbGlkYXRvci52YWxpZGF0ZUFuZFNhbml0aXplKGNvbnRlbnQsIHtcbiAgICAgICAgY29udGVudENvbnRleHQsXG4gICAgICB9KTtcbiAgICAgIGlmICghdmFsaWRhdGlvblJlc3VsdC5pc1ZhbGlkKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKCdbV2ViVUldIEluc3RhbGwgYmxvY2tlZCDigJQgY29udGVudCB2YWxpZGF0aW9uIGZhaWxlZCcsIHtcbiAgICAgICAgICBlbGVtZW50OiBgJHtwbHVyYWxUeXBlfS8ke25hbWV9YCxcbiAgICAgICAgICBwYXR0ZXJuczogdmFsaWRhdGlvblJlc3VsdC5kZXRlY3RlZFBhdHRlcm5zLFxuICAgICAgICAgIHNldmVyaXR5OiB2YWxpZGF0aW9uUmVzdWx0LnNldmVyaXR5LFxuICAgICAgICB9KTtcbiAgICAgICAgcmVzLnN0YXR1cyg0MjIpLmpzb24oe1xuICAgICAgICAgIGVycm9yOiAnQ29udGVudCBmYWlsZWQgc2VjdXJpdHkgdmFsaWRhdGlvbicsXG4gICAgICAgICAgcGF0dGVybnM6IHZhbGlkYXRpb25SZXN1bHQuZGV0ZWN0ZWRQYXR0ZXJucyxcbiAgICAgICAgICBzZXZlcml0eTogdmFsaWRhdGlvblJlc3VsdC5zZXZlcml0eSxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gRGV0ZXJtaW5lIGZpbGVuYW1lXG4gICAgICBjb25zdCBmaWxlbmFtZSA9IGVsZW1lbnRQYXRoLnNwbGl0KCcvJykucG9wKCkgfHwgYCR7bmFtZX0ubWRgO1xuXG4gICAgICAvLyBFbnN1cmUgdHlwZSBkaXJlY3RvcnkgZXhpc3RzXG4gICAgICBjb25zdCB0eXBlRGlyID0gam9pbihwb3J0Zm9saW9EaXIsIHBsdXJhbFR5cGUpO1xuICAgICAgY29uc3QgeyBta2RpciB9ID0gYXdhaXQgaW1wb3J0KCdub2RlOmZzL3Byb21pc2VzJyk7XG4gICAgICBhd2FpdCBta2Rpcih0eXBlRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICAgICAgLy8gV3JpdGUgdG8gcG9ydGZvbGlvXG4gICAgICBjb25zdCBkZXN0UGF0aCA9IGpvaW4odHlwZURpciwgZmlsZW5hbWUpO1xuXG4gICAgICAvLyBWZXJpZnkgcmVzb2x2ZWQgZGVzdGluYXRpb24gcGF0aCBzdGF5cyB3aXRoaW4gcG9ydGZvbGlvIGRpcmVjdG9yeSAoZGVmZW5zZSBpbiBkZXB0aClcbiAgICAgIGNvbnN0IHJlc29sdmVkRGVzdCA9IHJlc29sdmUoZGVzdFBhdGgpO1xuICAgICAgaWYgKCFyZXNvbHZlZERlc3Quc3RhcnRzV2l0aChyZXNvbHZlKHBvcnRmb2xpb0RpcikpKSB7XG4gICAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHsgZXJyb3I6ICdQYXRoIHRyYXZlcnNhbCBkZXRlY3RlZCcgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gQ2hlY2sgaWYgZmlsZSBhbHJlYWR5IGV4aXN0c1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgc3RhdChkZXN0UGF0aCk7XG4gICAgICAgIHJlcy5zdGF0dXMoNDA5KS5qc29uKHsgZXJyb3I6IGBFbGVtZW50IGFscmVhZHkgZXhpc3RzOiAke3BsdXJhbFR5cGV9LyR7ZmlsZW5hbWV9LiBEZWxldGUgaXQgZmlyc3Qgb3IgcmVuYW1lLmAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gY2F0Y2ggeyAvKiBkb2Vzbid0IGV4aXN0IOKAlCBnb29kICovIH1cblxuICAgICAgY29uc3QgeyB3cml0ZUZpbGU6IHdyaXRlRmlsZUZzIH0gPSBhd2FpdCBpbXBvcnQoJ25vZGU6ZnMvcHJvbWlzZXMnKTtcbiAgICAgIGF3YWl0IHdyaXRlRmlsZUZzKGRlc3RQYXRoLCBjb250ZW50LCAndXRmLTgnKTtcblxuICAgICAgbG9nZ2VyLmluZm8oYFtXZWJVSV0gSW5zdGFsbGVkIGNvbGxlY3Rpb24gZWxlbWVudDogJHtwbHVyYWxUeXBlfS8ke2ZpbGVuYW1lfWApO1xuICAgICAgcmVzLmpzb24oeyBzdWNjZXNzOiB0cnVlLCBtZXNzYWdlOiBgSW5zdGFsbGVkICR7bmFtZX0gdG8gcG9ydGZvbGlvYCwgcGF0aDogYCR7cGx1cmFsVHlwZX0vJHtmaWxlbmFtZX1gIH0pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgbG9nZ2VyLmVycm9yKCdbV2ViVUldIEluc3RhbGwgZmFpbGVkOicsIGVycik7XG4gICAgICByZXMuc3RhdHVzKDUwMCkuanNvbih7IGVycm9yOiBgSW5zdGFsbCBmYWlsZWQ6ICR7KGVyciBhcyBFcnJvcikubWVzc2FnZX1gIH0pO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIHJvdXRlcjtcbn1cblxuLy8g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4vLyBXZWIgTUNQLUFRTCBHYXRld2F5IFJvdXRlcyAoSXNzdWUgIzc5Nilcbi8vXG4vLyBUaGVzZSByb3V0ZXMgdHJhbnNsYXRlIEhUVFAgcmVxdWVzdHMgaW50byBNQ1BBUUxIYW5kbGVyIGNhbGxzLCByb3V0aW5nIGFsbFxuLy8gcmVhZHMvd3JpdGVzIHRocm91Z2ggdGhlIGV4aXN0aW5nIGVsZW1lbnQgbWFuYWdlcnMsIHZhbGlkYXRpb24sIGFuZCBnYXRla2VlcGVyLlxuLy8g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbi8qKiBOb3JtYWxpemUgZWxlbWVudCB0eXBlIHRvIHNpbmd1bGFyIGZvcm0gZm9yIE1DUC1BUUwgb3BlcmF0aW9ucyAqL1xuZnVuY3Rpb24gdG9TaW5ndWxhclR5cGUodHlwZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHR5cGUuZW5kc1dpdGgoJ3MnKSA/IHR5cGUuc2xpY2UoMCwgLTEpIDogdHlwZTtcbn1cblxuLyoqXG4gKiBFeHRyYWN0IHNpbmdsZSBvcGVyYXRpb24gcmVzdWx0IGZyb20gTUNQQVFMSGFuZGxlciByZXNwb25zZS5cbiAqIFdlYiByb3V0ZXMgbmV2ZXIgc2VuZCBiYXRjaCByZXF1ZXN0cywgc28gY2FzdCBpcyBzYWZlLlxuICovXG5pbnRlcmZhY2UgU2luZ2xlT3BSZXN1bHQgeyBzdWNjZXNzOiBib29sZWFuOyBkYXRhPzogdW5rbm93bjsgZXJyb3I/OiBzdHJpbmcgfVxuZnVuY3Rpb24gYXNTaW5nbGVSZXN1bHQocjogdW5rbm93bik6IFNpbmdsZU9wUmVzdWx0IHtcbiAgaWYgKHR5cGVvZiByID09PSAnb2JqZWN0JyAmJiByICE9PSBudWxsICYmICdzdWNjZXNzJyBpbiByKSB7XG4gICAgcmV0dXJuIHIgYXMgU2luZ2xlT3BSZXN1bHQ7XG4gIH1cbiAgcmV0dXJuIHsgc3VjY2VzczogZmFsc2UsIGVycm9yOiAnSW52YWxpZCBvcGVyYXRpb24gcmVzdWx0IGZvcm1hdCcgfTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgQVBJIHJvdXRlcyB0aGF0IHJvdXRlIHRocm91Z2ggTUNQQVFMSGFuZGxlciAoZ2F0ZXdheSBtb2RlKS5cbiAqIEFsbCBvcGVyYXRpb25zIGdvIHRocm91Z2ggdGhlIE1DUC1BUUwgcGlwZWxpbmU6IHZhbGlkYXRpb24sIGNhY2hlLCBnYXRla2VlcGVyLlxuICpcbiAqIEZhbGxzIGJhY2sgdG8gZGlyZWN0IGZpbGVzeXN0ZW0gZm9yIC9hcGkvY29sbGVjdGlvbiAoZXh0ZXJuYWwgZmV0Y2gsIG5vIE1DUC1BUUwgZXF1aXZhbGVudClcbiAqIGFuZCAvYXBpL3N0YXRzIChsaWdodHdlaWdodCBhZ2dyZWdhdGUsIG5vIG1hdGNoaW5nIG9wZXJhdGlvbikuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVHYXRld2F5QXBpUm91dGVzKGhhbmRsZXI6IE1DUEFRTEhhbmRsZXIsIHBvcnRmb2xpb0Rpcjogc3RyaW5nKTogUm91dGVyIHtcbiAgY29uc3Qgcm91dGVyID0gUm91dGVyKCk7XG5cbiAgLyoqXG4gICAqIEdFVCAvYXBpL2VsZW1lbnRzXG4gICAqIFJvdXRlcyB0aHJvdWdoIGxpc3RfZWxlbWVudHMgZm9yIGVhY2ggdHlwZSwgYWdncmVnYXRlcyByZXN1bHRzLlxuICAgKi9cbiAgcm91dGVyLmdldCgnL2VsZW1lbnRzJywgYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHBhZ2VQYXJhbSA9IHJlcS5xdWVyeS5wYWdlIGFzIHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IHBhZ2VTaXplUGFyYW0gPSByZXEucXVlcnkucGFnZVNpemUgYXMgc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgY29uc3Qgd2FudFBhZ2luYXRpb24gPSBwYWdlUGFyYW0gIT09IHVuZGVmaW5lZCAmJiBwYWdlU2l6ZVBhcmFtICE9PSB1bmRlZmluZWQ7XG4gICAgICBjb25zdCBwYWdlID0gTWF0aC5tYXgoMSwgcGFyc2VJbnQocGFnZVBhcmFtIHx8ICcxJywgMTApIHx8IDEpO1xuICAgICAgY29uc3QgcGFnZVNpemUgPSBNYXRoLm1heCgxLCBNYXRoLm1pbigyMDAsIHBhcnNlSW50KHBhZ2VTaXplUGFyYW0gfHwgJzUwJywgMTApIHx8IDUwKSk7XG5cbiAgICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgdW5rbm93bltdPiA9IHt9O1xuICAgICAgbGV0IHRvdGFsQ291bnQgPSAwO1xuXG4gICAgICAvLyBQYXJhbGxlbGl6ZSBlbGVtZW50IHR5cGUgbGlzdGluZyBmb3IgYmV0dGVyIHBlcmZvcm1hbmNlXG4gICAgICBjb25zdCB0eXBlUmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKEVMRU1FTlRfVFlQRVMubWFwKGFzeW5jICh0eXBlKSA9PiB7XG4gICAgICAgIGNvbnN0IG9wUmVzdWx0ID0gYXNTaW5nbGVSZXN1bHQoYXdhaXQgaGFuZGxlci5oYW5kbGVSZWFkKHtcbiAgICAgICAgICBvcGVyYXRpb246ICdsaXN0X2VsZW1lbnRzJyxcbiAgICAgICAgICBwYXJhbXM6IHsgZWxlbWVudF90eXBlOiB0b1Npbmd1bGFyVHlwZSh0eXBlKSwgcGFnZTogMSwgcGFnZVNpemU6IDEwMDAgfSxcbiAgICAgICAgfSkpO1xuICAgICAgICBpZiAob3BSZXN1bHQuc3VjY2VzcyAmJiBvcFJlc3VsdC5kYXRhKSB7XG4gICAgICAgICAgY29uc3QgaXRlbXMgPSAob3BSZXN1bHQuZGF0YSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikuaXRlbXM7XG4gICAgICAgICAgcmV0dXJuIHsgdHlwZSwgaXRlbXM6IEFycmF5LmlzQXJyYXkoaXRlbXMpID8gaXRlbXMgOiBbXSB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IHR5cGUsIGl0ZW1zOiBbXSBhcyB1bmtub3duW10gfTtcbiAgICAgIH0pKTtcblxuICAgICAgZm9yIChjb25zdCB7IHR5cGUsIGl0ZW1zIH0gb2YgdHlwZVJlc3VsdHMpIHtcbiAgICAgICAgcmVzdWx0W3R5cGVdID0gaXRlbXM7XG4gICAgICAgIHRvdGFsQ291bnQgKz0gaXRlbXMubGVuZ3RoO1xuICAgICAgfVxuXG4gICAgICBpZiAod2FudFBhZ2luYXRpb24pIHtcbiAgICAgICAgY29uc3QgYWxsRWxlbWVudHM6IHVua25vd25bXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IHR5cGUgb2YgRUxFTUVOVF9UWVBFUykge1xuICAgICAgICAgIGFsbEVsZW1lbnRzLnB1c2goLi4uKHJlc3VsdFt0eXBlXSB8fCBbXSkpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gKHBhZ2UgLSAxKSAqIHBhZ2VTaXplO1xuICAgICAgICBjb25zdCBwYWdlZCA9IGFsbEVsZW1lbnRzLnNsaWNlKHN0YXJ0LCBzdGFydCArIHBhZ2VTaXplKTtcbiAgICAgICAgY29uc3QgdG90YWxQYWdlcyA9IE1hdGguY2VpbChhbGxFbGVtZW50cy5sZW5ndGggLyBwYWdlU2l6ZSk7XG4gICAgICAgIHJlcy5qc29uKHsgZWxlbWVudHM6IHBhZ2VkLCB0b3RhbENvdW50OiBhbGxFbGVtZW50cy5sZW5ndGgsIHBhZ2UsIHBhZ2VTaXplLCB0b3RhbFBhZ2VzIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzLmpzb24oeyBlbGVtZW50czogcmVzdWx0LCB0b3RhbENvdW50IH0pO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgbG9nZ2VyLmVycm9yKCdbV2ViVUkvR2F0ZXdheV0gRmFpbGVkIHRvIGxpc3QgZWxlbWVudHM6JywgZXJyKTtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHsgZXJyb3I6ICdGYWlsZWQgdG8gbGlzdCBlbGVtZW50cycgfSk7XG4gICAgfVxuICB9KTtcblxuICAvKipcbiAgICogR0VUIC9hcGkvZWxlbWVudHMvOnR5cGVcbiAgICogUm91dGVzIHRocm91Z2ggbGlzdF9lbGVtZW50cyBmb3IgYSBzcGVjaWZpYyB0eXBlLlxuICAgKi9cbiAgcm91dGVyLmdldCgnL2VsZW1lbnRzLzp0eXBlJywgYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgY29uc3QgdHlwZSA9IG5vcm1hbGl6ZUlucHV0KHJlcS5wYXJhbXMudHlwZSk7XG4gICAgaWYgKCFFTEVNRU5UX1RZUEVTLmluY2x1ZGVzKHR5cGUgYXMgdHlwZW9mIEVMRU1FTlRfVFlQRVNbbnVtYmVyXSkpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHsgZXJyb3I6IGBJbnZhbGlkIGVsZW1lbnQgdHlwZTogJHt0eXBlfWAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IG9wUmVzdWx0ID0gYXNTaW5nbGVSZXN1bHQoYXdhaXQgaGFuZGxlci5oYW5kbGVSZWFkKHtcbiAgICAgICAgb3BlcmF0aW9uOiAnbGlzdF9lbGVtZW50cycsXG4gICAgICAgIHBhcmFtczogeyBlbGVtZW50X3R5cGU6IHRvU2luZ3VsYXJUeXBlKHR5cGUpLCBwYWdlOiAxLCBwYWdlU2l6ZTogMTAwMCB9LFxuICAgICAgfSkpO1xuXG4gICAgICBpZiAoIW9wUmVzdWx0LnN1Y2Nlc3MpIHtcbiAgICAgICAgcmVzLnN0YXR1cyg1MDApLmpzb24oeyBlcnJvcjogb3BSZXN1bHQuZXJyb3IgfHwgYEZhaWxlZCB0byBsaXN0ICR7dHlwZX1gIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRhdGEgPSBvcFJlc3VsdC5kYXRhIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgICAgY29uc3QgaXRlbXMgPSBBcnJheS5pc0FycmF5KGRhdGEuaXRlbXMpID8gZGF0YS5pdGVtcyA6IFtdO1xuICAgICAgcmVzLmpzb24oeyB0eXBlLCBlbGVtZW50czogaXRlbXMsIGNvdW50OiBpdGVtcy5sZW5ndGggfSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXMuc3RhdHVzKDUwMCkuanNvbih7IGVycm9yOiBgRmFpbGVkIHRvIGxpc3QgJHt0eXBlfWAgfSk7XG4gICAgfVxuICB9KTtcblxuICAvKipcbiAgICogR0VUIC9hcGkvZWxlbWVudHMvOnR5cGUvOm5hbWVcbiAgICogUm91dGVzIHRocm91Z2ggZ2V0X2VsZW1lbnQgZm9yIGEgc3BlY2lmaWMgZWxlbWVudC5cbiAgICogUmV0dXJucyB0aGUgcmF3IGZpbGUgY29udGVudCBhcyBwbGFpbiB0ZXh0IChzYW1lIGFzIGxlZ2FjeSBiZWhhdmlvcikuXG4gICAqL1xuICByb3V0ZXIuZ2V0KCcvZWxlbWVudHMvOnR5cGUvOm5hbWUnLCBhc3luYyAocmVxLCByZXMpID0+IHtcbiAgICBjb25zdCB7IHR5cGUsIG5hbWUgfSA9IHJlcS5wYXJhbXM7XG4gICAgaWYgKCFFTEVNRU5UX1RZUEVTLmluY2x1ZGVzKHR5cGUgYXMgdHlwZW9mIEVMRU1FTlRfVFlQRVNbbnVtYmVyXSkpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHsgZXJyb3I6IGBJbnZhbGlkIGVsZW1lbnQgdHlwZTogJHt0eXBlfWAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKG5hbWUuaW5jbHVkZXMoJy4uJykgfHwgbmFtZS5pbmNsdWRlcygnLycpIHx8IG5hbWUuaW5jbHVkZXMoJ1xcXFwnKSkge1xuICAgICAgcmVzLnN0YXR1cyg0MDApLmpzb24oeyBlcnJvcjogJ0ludmFsaWQgZWxlbWVudCBuYW1lJyB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3Qgb3BSZXN1bHQgPSBhc1NpbmdsZVJlc3VsdChhd2FpdCBoYW5kbGVyLmhhbmRsZVJlYWQoe1xuICAgICAgICBvcGVyYXRpb246ICdnZXRfZWxlbWVudCcsXG4gICAgICAgIHBhcmFtczogeyBlbGVtZW50X25hbWU6IG5hbWUsIGVsZW1lbnRfdHlwZTogdG9TaW5ndWxhclR5cGUodHlwZSkgfSxcbiAgICAgIH0pKTtcblxuICAgICAgaWYgKCFvcFJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICAgIGNvbnN0IGVyck1zZyA9IG9wUmVzdWx0LmVycm9yIHx8ICcnO1xuICAgICAgICBjb25zdCBzdGF0dXMgPSBlcnJNc2cudG9Mb3dlckNhc2UoKS5pbmNsdWRlcygnbm90IGZvdW5kJykgPyA0MDQgOiA1MDA7XG4gICAgICAgIHJlcy5zdGF0dXMoc3RhdHVzKS5qc29uKHsgZXJyb3I6IGVyck1zZyB8fCBgRmFpbGVkIHRvIGdldCBlbGVtZW50OiAke3R5cGV9LyR7bmFtZX1gIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIGdldF9lbGVtZW50IHJldHVybnMgc3RydWN0dXJlZCBkYXRhIOKAlCB0aGUgd2ViIFVJIGV4cGVjdHMgcmF3IGZpbGUgY29udGVudFxuICAgICAgLy8gZm9yIGNsaWVudC1zaWRlIHBhcnNpbmcuIEV4dHJhY3QgcmF3Q29udGVudCBpZiBhdmFpbGFibGUsIG90aGVyd2lzZSBzZXJpYWxpemUuXG4gICAgICBjb25zdCBkYXRhID0gb3BSZXN1bHQuZGF0YSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgIGNvbnN0IHJhd0NvbnRlbnQgPSBkYXRhLnJhd0NvbnRlbnQgfHwgZGF0YS5yYXdfY29udGVudDtcbiAgICAgIGlmICh0eXBlb2YgcmF3Q29udGVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmVzLnNldEhlYWRlcignQ29udGVudC1UeXBlJywgJ3RleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgnKTtcbiAgICAgICAgcmVzLnNlbmQocmF3Q29udGVudCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBGYWxsYmFjazogcmV0dXJuIEpTT04gcmVwcmVzZW50YXRpb25cbiAgICAgICAgcmVzLmpzb24oZGF0YSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXMuc3RhdHVzKDUwMCkuanNvbih7IGVycm9yOiBgRmFpbGVkIHRvIGdldCBlbGVtZW50OiAke3R5cGV9LyR7bmFtZX1gIH0pO1xuICAgIH1cbiAgfSk7XG5cbiAgLyoqXG4gICAqIEdFVCAvYXBpL3N0YXRzXG4gICAqIFBvcnRmb2xpbyBzdGF0aXN0aWNzIOKAlCBsaWdodHdlaWdodCBhZ2dyZWdhdGUsIHVzZXMgbGlzdF9lbGVtZW50cyBjb3VudHMuXG4gICAqL1xuICByb3V0ZXIuZ2V0KCcvc3RhdHMnLCBhc3luYyAoX3JlcSwgcmVzKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+ID0ge307XG4gICAgICBsZXQgdG90YWwgPSAwO1xuXG4gICAgICAvLyBQYXJhbGxlbGl6ZSBzdGF0cyBxdWVyaWVzXG4gICAgICBjb25zdCB0eXBlU3RhdHMgPSBhd2FpdCBQcm9taXNlLmFsbChFTEVNRU5UX1RZUEVTLm1hcChhc3luYyAodHlwZSkgPT4ge1xuICAgICAgICBjb25zdCBvcFJlc3VsdCA9IGFzU2luZ2xlUmVzdWx0KGF3YWl0IGhhbmRsZXIuaGFuZGxlUmVhZCh7XG4gICAgICAgICAgb3BlcmF0aW9uOiAnbGlzdF9lbGVtZW50cycsXG4gICAgICAgICAgcGFyYW1zOiB7IGVsZW1lbnRfdHlwZTogdG9TaW5ndWxhclR5cGUodHlwZSksIHBhZ2U6IDEsIHBhZ2VTaXplOiAxIH0sXG4gICAgICAgIH0pKTtcbiAgICAgICAgaWYgKG9wUmVzdWx0LnN1Y2Nlc3MgJiYgb3BSZXN1bHQuZGF0YSkge1xuICAgICAgICAgIGNvbnN0IGRhdGEgPSBvcFJlc3VsdC5kYXRhIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgICAgICAgIGNvbnN0IHBhZ2luYXRpb24gPSBkYXRhLnBhZ2luYXRpb24gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCB1bmRlZmluZWQ7XG4gICAgICAgICAgcmV0dXJuIHsgdHlwZSwgY291bnQ6IHR5cGVvZiBwYWdpbmF0aW9uPy50b3RhbEl0ZW1zID09PSAnbnVtYmVyJyA/IHBhZ2luYXRpb24udG90YWxJdGVtcyA6IDAgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyB0eXBlLCBjb3VudDogMCB9O1xuICAgICAgfSkpO1xuXG4gICAgICBmb3IgKGNvbnN0IHsgdHlwZSwgY291bnQgfSBvZiB0eXBlU3RhdHMpIHtcbiAgICAgICAgc3RhdHNbdHlwZV0gPSBjb3VudDtcbiAgICAgICAgdG90YWwgKz0gY291bnQ7XG4gICAgICB9XG5cbiAgICAgIHJlcy5qc29uKHsgc3RhdHMsIHRvdGFsIH0pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmVzLnN0YXR1cyg1MDApLmpzb24oeyBlcnJvcjogJ0ZhaWxlZCB0byBnZXQgc3RhdHMnIH0pO1xuICAgIH1cbiAgfSk7XG5cbiAgLyoqXG4gICAqIEdFVCAvYXBpL2NvbGxlY3Rpb25cbiAgICogUHJveGllcyB0aGUgY29tbXVuaXR5IGNvbGxlY3Rpb24gaW5kZXguXG4gICAqIE5vIE1DUC1BUUwgZXF1aXZhbGVudCDigJQgdXNlcyBkaXJlY3QgZmV0Y2ggKHNhbWUgYXMgbGVnYWN5KS5cbiAgICovXG4gIHJvdXRlci5nZXQoJy9jb2xsZWN0aW9uJywgYXN5bmMgKF9yZXEsIHJlcykgPT4ge1xuICAgIHJlcy5zZXRIZWFkZXIoJ0NhY2hlLUNvbnRyb2wnLCAnbm8tY2FjaGUnKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKCdodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vRG9sbGhvdXNlTUNQL2NvbGxlY3Rpb24vbWFpbi9wdWJsaWMvY29sbGVjdGlvbi1pbmRleC5qc29uJyk7XG4gICAgICBpZiAocmVzcG9uc2Uub2spIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHJlc3BvbnNlLnRleHQoKTtcbiAgICAgICAgcmVzLnNldEhlYWRlcignQ29udGVudC1UeXBlJywgJ2FwcGxpY2F0aW9uL2pzb24nKTtcbiAgICAgICAgcmVzLnNlbmQoZGF0YSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9IGNhdGNoIHsgLyogR2l0SHViIHVucmVhY2hhYmxlIOKAlCBmYWxsIGJhY2sgdG8gbG9jYWwgKi8gfVxuXG4gICAgY29uc3QgbG9jYWxQYXRocyA9IFtcbiAgICAgIGpvaW4ocG9ydGZvbGlvRGlyLCAnLi4nLCAnLi4nLCAnLi4nLCAnY29sbGVjdGlvbicsICdwdWJsaWMnLCAnY29sbGVjdGlvbi1pbmRleC5qc29uJyksXG4gICAgICBqb2luKHBvcnRmb2xpb0RpciwgJy4uJywgJ2NvbGxlY3Rpb24nLCAncHVibGljJywgJ2NvbGxlY3Rpb24taW5kZXguanNvbicpLFxuICAgIF07XG5cbiAgICBmb3IgKGNvbnN0IGxvY2FsUGF0aCBvZiBsb2NhbFBhdGhzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgcmVhZEZpbGUobG9jYWxQYXRoLCAndXRmLTgnKTtcbiAgICAgICAgcmVzLnNldEhlYWRlcignQ29udGVudC1UeXBlJywgJ2FwcGxpY2F0aW9uL2pzb24nKTtcbiAgICAgICAgcmVzLnNlbmQoY29udGVudCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gY2F0Y2ggeyAvKiB0cnkgbmV4dCAqLyB9XG4gICAgfVxuXG4gICAgcmVzLnN0YXR1cyg0MDQpLmpzb24oeyBlcnJvcjogJ0NvbGxlY3Rpb24gaW5kZXggbm90IGF2YWlsYWJsZScgfSk7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiBQT1NUIC9hcGkvaW5zdGFsbFxuICAgKiBSb3V0ZXMgdGhyb3VnaCBpbnN0YWxsX2NvbGxlY3Rpb25fY29udGVudCBNQ1AtQVFMIG9wZXJhdGlvbi5cbiAgICogQWxsIHZhbGlkYXRpb24sIGdhdGVrZWVwZXIgY2hlY2tzIGhhbmRsZWQgYnkgdGhlIHBpcGVsaW5lLlxuICAgKi9cbiAgY29uc3QgaW5zdGFsbExpbWl0ZXIgPSBuZXcgU2xpZGluZ1dpbmRvd1JhdGVMaW1pdGVyKDEwLCA2MF8wMDApO1xuICByb3V0ZXIucG9zdCgnL2luc3RhbGwnLCBleHByZXNzLmpzb24oKSwgYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgaWYgKCFpbnN0YWxsTGltaXRlci50cnlBY3F1aXJlKCkpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDI5KS5qc29uKHsgZXJyb3I6ICdUb28gbWFueSBpbnN0YWxsIHJlcXVlc3RzLiBNYXggMTAgcGVyIG1pbnV0ZS4nIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHsgcGF0aDogZWxlbWVudFBhdGgsIG5hbWUsIHR5cGUgfSA9IHJlcS5ib2R5IGFzIHsgcGF0aD86IHN0cmluZzsgbmFtZT86IHN0cmluZzsgdHlwZT86IHN0cmluZyB9O1xuXG4gICAgaWYgKCFlbGVtZW50UGF0aCB8fCAhdHlwZSB8fCAhbmFtZSkge1xuICAgICAgcmVzLnN0YXR1cyg0MDApLmpzb24oeyBlcnJvcjogJ01pc3NpbmcgcmVxdWlyZWQgZmllbGRzOiBwYXRoLCBuYW1lLCB0eXBlJyB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoZWxlbWVudFBhdGguaW5jbHVkZXMoJy4uJykgfHwgbmFtZS5pbmNsdWRlcygnLi4nKSkge1xuICAgICAgcmVzLnN0YXR1cyg0MDApLmpzb24oeyBlcnJvcjogJ0ludmFsaWQgcGF0aCBvciBuYW1lJyB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSBlbGVtZW50UGF0aCBjb250YWlucyBvbmx5IHNhZmUgY2hhcmFjdGVycyAoYWxwaGFudW1lcmljLCBoeXBoZW5zLCB1bmRlcnNjb3JlcywgZG90cywgc2xhc2hlcylcbiAgICBpZiAoIS9eW2EtekEtWjAtOS9fLi1dKyQvLnRlc3QoZWxlbWVudFBhdGgpKSB7XG4gICAgICByZXMuc3RhdHVzKDQwMCkuanNvbih7IGVycm9yOiAnSW52YWxpZCBlbGVtZW50IHBhdGggY2hhcmFjdGVycycgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIC8vIFJvdXRlIHRocm91Z2ggTUNQLUFRTCBpbnN0YWxsX2NvbGxlY3Rpb25fY29udGVudCBvcGVyYXRpb25cbiAgICAgIGNvbnN0IGluc3RhbGxQYXRoID0gZWxlbWVudFBhdGgucmVwbGFjZSgvXmxpYnJhcnlcXC8vLCAnJyk7XG4gICAgICBjb25zdCBvcFJlc3VsdCA9IGFzU2luZ2xlUmVzdWx0KGF3YWl0IGhhbmRsZXIuaGFuZGxlQ3JlYXRlKHtcbiAgICAgICAgb3BlcmF0aW9uOiAnaW5zdGFsbF9jb2xsZWN0aW9uX2NvbnRlbnQnLFxuICAgICAgICBwYXJhbXM6IHsgcGF0aDogaW5zdGFsbFBhdGggfSxcbiAgICAgIH0pKTtcblxuICAgICAgaWYgKCFvcFJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICAgIHJlcy5zdGF0dXMoNDIyKS5qc29uKHsgZXJyb3I6IG9wUmVzdWx0LmVycm9yIHx8ICdJbnN0YWxsIGZhaWxlZCcgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgbG9nZ2VyLmluZm8oYFtXZWJVSS9HYXRld2F5XSBJbnN0YWxsZWQgY29sbGVjdGlvbiBlbGVtZW50OiAke2luc3RhbGxQYXRofWApO1xuICAgICAgcmVzLmpzb24oeyBzdWNjZXNzOiB0cnVlLCBtZXNzYWdlOiBgSW5zdGFsbGVkICR7bmFtZX0gdG8gcG9ydGZvbGlvYCwgZGF0YTogb3BSZXN1bHQuZGF0YSB9KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGxvZ2dlci5lcnJvcignW1dlYlVJL0dhdGV3YXldIEluc3RhbGwgZmFpbGVkOicsIGVycik7XG4gICAgICByZXMuc3RhdHVzKDUwMCkuanNvbih7IGVycm9yOiBgSW5zdGFsbCBmYWlsZWQ6ICR7KGVyciBhcyBFcnJvcikubWVzc2FnZX1gIH0pO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIHJvdXRlcjtcbn1cbiJdfQ==
|
|
693
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3dlYi9yb3V0ZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUVILE9BQU8sT0FBTyxFQUFFLEVBQUUsTUFBTSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzNELE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNuRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNuRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDNUMsT0FBTyxFQUFFLHNCQUFzQixFQUFvRCxNQUFNLHNCQUFzQixDQUFDO0FBR2hILDRFQUE0RTtBQUM1RSxTQUFTLGNBQWMsQ0FBQyxLQUFhO0lBQ25DLE9BQU8sS0FBSyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNoQyxDQUFDO0FBQ0QsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbkUsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sc0NBQXNDLENBQUM7QUFFaEYsTUFBTSxhQUFhLEdBQUcsQ0FBQyxVQUFVLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLFdBQVcsQ0FBVSxDQUFDO0FBRXRHLDZDQUE2QztBQUM3QyxNQUFNLG1CQUFtQixHQUFHLFNBQVMsQ0FBQztBQUV0QyxvQ0FBb0M7QUFDcEMsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztBQUUzRCx5R0FBeUc7QUFDekcsTUFBTSxnQkFBZ0IsR0FBRyw0Q0FBNEMs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WUFDN0QsTUFBTSxXQUFXLEdBQUcsV0FBVyxDQUFDLE9BQU8sQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDMUQsTUFBTSxRQUFRLEdBQUcsY0FBYyxDQUFDLE1BQU0sT0FBTyxDQUFDLFlBQVksQ0FBQztnQkFDekQsU0FBUyxFQUFFLDRCQUE0QjtnQkFDdkMsTUFBTSxFQUFFLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRTthQUM5QixDQUFDLENBQUMsQ0FBQztZQUVKLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ3RCLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLFFBQVEsQ0FBQyxLQUFLLElBQUksZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDO2dCQUNwRSxPQUFPO1lBQ1QsQ0FBQztZQUVELE1BQU0sQ0FBQyxJQUFJLENBQUMsaURBQWlELFdBQVcsRUFBRSxDQUFDLENBQUM7WUFDNUUsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLGFBQWEsSUFBSSxlQUFlLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQzlGLENBQUM7UUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1lBQ2IsTUFBTSxDQUFDLEtBQUssQ0FBQyxpQ0FBaUMsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUNyRCxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxtQkFBb0IsR0FBYSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztRQUMvRSxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7SUFFSCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBXZWIgVUkgQVBJIFJvdXRlc1xuICpcbiAqIFJFU1QgZW5kcG9pbnRzIGZvciByZWFkaW5nIHBvcnRmb2xpbyBlbGVtZW50cy5cbiAqIFJlYWQtb25seSDigJQgbm8gbXV0YXRpb25zIGluIFYxLlxuICpcbiAqIEFsbCBlbGVtZW50IGNvbnRlbnQgaXMgc2FuaXRpemVkIGJlZm9yZSBzZXJ2aW5nIHRvIHByZXZlbnQgWFNTLlxuICpcbiAqIFNlY3VyaXR5IG5vdGU6IFRoaXMgd2ViIHNlcnZlciBiaW5kcyB0byAxMjcuMC4wLjEgb25seSAoc2VlIHNlcnZlci50cykuXG4gKiBSYXRlIGxpbWl0aW5nIG9uIHJlYWQtb25seSBHRVQgZW5kcG9pbnRzIGlzIG5vdCByZXF1aXJlZCBmb3IgbG9jYWxob3N0LW9ubHlcbiAqIG1hbmFnZW1lbnQgaW50ZXJmYWNlcy4gVGhlIFBPU1QgL2FwaS9pbnN0YWxsIGVuZHBvaW50IGhhcyBleHBsaWNpdCByYXRlIGxpbWl0aW5nXG4gKiB2aWEgU2xpZGluZ1dpbmRvd1JhdGVMaW1pdGVyIChtYXggMTAgcGVyIG1pbnV0ZSkuXG4gKiBjb2RlcWxbanMvbWlzc2luZy1yYXRlLWxpbWl0aW5nXSDigJQgQWNrbm93bGVkZ2VkOyBsb2NhbGhvc3Qtb25seSBiaW5kaW5nIG1pdGlnYXRlcyBEb1Mgcmlzay5cbiAqL1xuXG5pbXBvcnQgZXhwcmVzcywgeyBSb3V0ZXIgfSBmcm9tICdleHByZXNzJztcbmltcG9ydCB7IHJlYWRkaXIsIHJlYWRGaWxlLCBzdGF0IH0gZnJvbSAnbm9kZTpmcy9wcm9taXNlcyc7XG5pbXBvcnQgeyBqb2luLCBleHRuYW1lLCByZXNvbHZlIH0gZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7IFNlY3VyZVlhbWxQYXJzZXIgfSBmcm9tICcuLi9zZWN1cml0eS9zZWN1cmVZYW1sUGFyc2VyLmpzJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyB2YWxpZGF0ZUVsZW1lbnRDb250ZW50LCB0eXBlIFBpcGVsaW5lUmVzdWx0LCB0eXBlIEVsZW1lbnREaXNwbGF5TWV0YWRhdGEgfSBmcm9tICcuL2NvbnRlbnRQaXBlbGluZS5qcyc7XG5pbXBvcnQgdHlwZSB7IE1DUEFRTEhhbmRsZXIgfSBmcm9tICcuLi9oYW5kbGVycy9tY3AtYXFsL01DUEFRTEhhbmRsZXIuanMnO1xuXG4vKiogTm9ybWFsaXplIHVzZXIgaW5wdXQgdG8gTkZDIGZvcm0gdG8gcHJldmVudCBVbmljb2RlIGhvbW9ncmFwaCBhdHRhY2tzICovXG5mdW5jdGlvbiBub3JtYWxpemVJbnB1dChpbnB1dDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGlucHV0Lm5vcm1hbGl6ZSgnTkZDJyk7XG59XG5pbXBvcnQgeyBDb250ZW50VmFsaWRhdG9yIH0gZnJvbSAnLi4vc2VjdXJpdHkvY29udGVudFZhbGlkYXRvci5qcyc7XG5pbXBvcnQgeyBTbGlkaW5nV2luZG93UmF0ZUxpbWl0ZXIgfSBmcm9tICcuLi91dGlscy9TbGlkaW5nV2luZG93UmF0ZUxpbWl0ZXIuanMnO1xuXG5jb25zdCBFTEVNRU5UX1RZUEVTID0gWydwZXJzb25hcycsICdza2lsbHMnLCAndGVtcGxhdGVzJywgJ2FnZW50cycsICdtZW1vcmllcycsICdlbnNlbWJsZXMnXSBhcyBjb25zdDtcblxuLyoqIE1heCBmaWxlIHNpemUgZm9yIGVsZW1lbnQgcmVhZHMgKDEgTUIpICovXG5jb25zdCBNQVhfRklMRV9TSVpFX0JZVEVTID0gMV8wNDhfNTc2O1xuXG4vKiogVmFsaWQgZWxlbWVudCBmaWxlIGV4dGVuc2lvbnMgKi9cbmNvbnN0IFZBTElEX0VYVEVOU0lPTlMgPSBuZXcgU2V0KFsnLm1kJywgJy55YW1sJywgJy55bWwnXSk7XG5cbi8qKiBLbm93bi1zYWZlIGZpbGVuYW1lIHBhdHRlcm46IHN0YXJ0cyBhbHBoYW51bWVyaWMsIGJvZHkgYWxsb3dzIGh5cGhlbnMvdW5kZXJzY29yZXMsIHZhbGlkIGV4dGVuc2lvbiAqL1xuY29uc3QgU0FGRV9GSUxFTkFNRV9SRSA9IC9eW2EtekEtWjAtOV1bYS16QS1aMC05Xy1dKlxcLih5YW1sfHltbHxtZCkkLztcblxuLyoqIENoZWNrIGlmIGEgZmlsZW5hbWUgaXMgYSBiYWNrdXAgb3IgY3J1ZnQgZmlsZSAqL1xuZnVuY3Rpb24gaXNCYWNrdXBPckNydWZ0KGZpbGVuYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgLy8gR3VhcmFudGVlZCBzYWZlIGZpbGVuYW1lcyBza2lwIGJsYWNrbGlzdCBjaGVja3MgZW50aXJlbHlcbiAgaWYgKFNBRkVfRklMRU5BTUVfUkUudGVzdChmaWxlbmFtZSkpIHJldHVybiBmYWxzZTtcbiAgaWYgKGZpbGVuYW1lLnN0YXJ0c1dpdGgoJy4nKSkgcmV0dXJuIHRydWU7XG4gIGlmIChmaWxlbmFtZSA9PT0gJ19pbmRleC5qc29uJykgcmV0dXJuIHRydWU7XG4gIGlmIChmaWxlbmFtZS5pbmNsdWRlcygnLmJhY2t1cCcpIHx8IGZpbGVuYW1lLmluY2x1ZGVzKCcuc3RhdGUnKSkgcmV0dXJuIHRydWU7XG4gIGlmIChmaWxlbmFtZS5lbmRzV2l0aCgnLmJhaycpIHx8IGZpbGVuYW1lLmVuZHNXaXRoKCd+JykpIHJldHVybiB0cnVlO1xuICBpZiAoZmlsZW5hbWUuaW5jbHVkZXMoJyBjb3B5JykpIHJldHVybiB0cnVlO1xuICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogU2NhbiBhIGRpcmVjdG9yeSBmb3IgdmFsaWQgZWxlbWVudHMsIHJ1bm5pbmcgZWFjaCB0aHJvdWdoIHRoZSBzZWN1cml0eVxuICogdmFsaWRhdGlvbiBwaXBlbGluZS4gUmV0dXJucyBtZXRhZGF0YSBvYmplY3RzIHJlYWR5IGZvciBBUEkgcmVzcG9uc2VzLlxuICovXG5hc3luYyBmdW5jdGlvbiBzY2FuRWxlbWVudERpcmVjdG9yeSh0eXBlRGlyOiBzdHJpbmcsIHR5cGU6IHN0cmluZywgbG9nUHJlZml4OiBzdHJpbmcpOiBQcm9taXNlPHVua25vd25bXT4ge1xuICBjb25zdCBmaWxlcyA9IGF3YWl0IHJlYWRkaXIodHlwZURpcik7XG4gIGNvbnN0IGVsZW1lbnRzOiB1bmtub3duW10gPSBbXTtcblxuICBmb3IgKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICBpZiAoaXNCYWNrdXBPckNydWZ0KGZpbGUpKSBjb250aW51ZTtcbiAgICBjb25zdCBleHQgPSBleHRuYW1lKGZpbGUpO1xuICAgIGlmICghVkFMSURfRVhURU5TSU9OUy5oYXMoZXh0KSkgY29udGludWU7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgZmlsZVBhdGggPSBqb2luKHR5cGVEaXIsIGZpbGUpO1xuICAgICAgY29uc3QgZmlsZVN0YXQgPSBhd2FpdCBzdGF0KGZpbGVQYXRoKTtcbiAgICAgIGlmICghZmlsZVN0YXQuaXNGaWxlKCkgfHwgZmlsZVN0YXQuc2l6ZSA+IE1BWF9GSUxFX1NJWkVfQllURVMpIGNvbnRpbnVlO1xuXG4gICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgcmVhZEZpbGUoZmlsZVBhdGgsICd1dGYtOCcpO1xuICAgICAgY29uc3QgdmFsaWRhdGlvblJlc3VsdCA9IHZhbGlkYXRlRWxlbWVudENvbnRlbnQoZmlsZSwgY29udGVudCwgdHlwZSk7XG5cbiAgICAgIGlmICghdmFsaWRhdGlvblJlc3VsdC52YWxpZCkge1xuICAgICAgICBsb2dnZXIuZGVidWcoYCR7bG9nUHJlZml4fSBTa2lwcGluZyByZWplY3RlZCBmaWxlICR7ZmlsZX06ICR7dmFsaWRhdGlvblJlc3VsdC5yZWplY3Rpb24/LnJlYXNvbn1gKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHsgbWV0YWRhdGEgfSA9IHZhbGlkYXRpb25SZXN1bHQ7XG4gICAgICBlbGVtZW50cy5wdXNoKHtcbiAgICAgICAgbmFtZTogbWV0YWRhdGEubmFtZSB8fCBmaWxlLnJlcGxhY2UoZXh0LCAnJyksXG4gICAgICAgIGRlc2NyaXB0aW9uOiBtZXRhZGF0YS5kZXNjcmlwdGlvbiB8fCAnJyxcbiAgICAgICAgdHlwZTogdHlwZS5zbGljZSgwLCAtMSksXG4gICAgICAgIHZlcnNpb246IG1ldGFkYXRhLnZlcnNpb24gfHwgJzEuMC4wJyxcbiAgICAgICAgYXV0aG9yOiBtZXRhZGF0YS5hdXRob3IgfHwgJycsXG4gICAgICAgIGNhdGVnb3J5OiBtZXRhZGF0YS5jYXRlZ29yeSB8fCAnJyxcbiAgICAgICAgdGFnczogbWV0YWRhdGEudGFncyB8fCAnJyxcbiAgICAgICAgY3JlYXRlZDogbWV0YWRhdGEuY3JlYXRlZCB8fCAnJyxcbiAgICAgICAgZmlsZW5hbWU6IGZpbGUsXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhgJHtsb2dQcmVmaXh9IEZhaWxlZCB0byBwYXJzZSAke2ZpbGV9OmAsIGVycik7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGVsZW1lbnRzO1xufVxuXG4vKiogTm9ybWFsaXplIHBsdXJhbCBlbGVtZW50IHR5cGUgdG8gc2luZ3VsYXIgZm9ybSAqL1xuY29uc3QgUExVUkFMX1RPX1NJTkdVTEFSOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICBwZXJzb25hczogJ3BlcnNvbmEnLCBza2lsbHM6ICdza2lsbCcsIHRlbXBsYXRlczogJ3RlbXBsYXRlJyxcbiAgYWdlbnRzOiAnYWdlbnQnLCBtZW1vcmllczogJ21lbW9yeScsIGVuc2VtYmxlczogJ2Vuc2VtYmxlJyxcbn07XG5mdW5jdGlvbiB0b1Npbmd1bGFyVHlwZSh0eXBlOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gUExVUkFMX1RPX1NJTkdVTEFSW3R5cGVdIHx8ICh0eXBlLmVuZHNXaXRoKCdzJykgPyB0eXBlLnNsaWNlKDAsIC0xKSA6IHR5cGUpO1xufVxuXG4vKiogQnVpbGQgYSBzdHJ1Y3R1cmVkIHZhbGlkYXRpb24gcmVzcG9uc2UgZm9yIGVsZW1lbnQgZGV0YWlsIHJvdXRlcyAqL1xuZnVuY3Rpb24gYnVpbGRWYWxpZGF0aW9uUmVzcG9uc2UodmFsaWRhdGlvbjogUGlwZWxpbmVSZXN1bHQsIGNvbnRlbnQ6IHN0cmluZywgdHlwZTogc3RyaW5nKSB7XG4gIHJldHVybiB7XG4gICAgbWV0YWRhdGE6IHZhbGlkYXRpb24ubWV0YWRhdGEsXG4gICAgYm9keTogdmFsaWRhdGlvbi5ib2R5LFxuICAgIHJhdzogY29udGVudCxcbiAgICB0eXBlOiB0b1Npbmd1bGFyVHlwZSh0eXBlKSxcbiAgICB2YWxpZGF0aW9uOiB7XG4gICAgICBzdGF0dXM6IHZhbGlkYXRpb24udmFsaWQgPyAncGFzcycgOiAnd2FybicsXG4gICAgICAuLi4odmFsaWRhdGlvbi5yZWplY3Rpb24gJiYge1xuICAgICAgICByZWFzb246IHZhbGlkYXRpb24ucmVqZWN0aW9uLnJlYXNvbixcbiAgICAgICAgc2V2ZXJpdHk6IHZhbGlkYXRpb24ucmVqZWN0aW9uLnNldmVyaXR5LFxuICAgICAgICBwYXR0ZXJuczogdmFsaWRhdGlvbi5yZWplY3Rpb24ucGF0dGVybnMsXG4gICAgICB9KSxcbiAgICB9LFxuICB9O1xufVxuXG4vKipcbiAqIFJlc29sdmUgYSBmaWxlIHBhdGggZm9yIGFuIGVsZW1lbnQsIGhhbmRsaW5nIG1lbW9yeSBkYXRlLXBhdGhzXG4gKiBhbmQgbmFtZS13aXRoLW9yLXdpdGhvdXQtZXh0ZW5zaW9uIG1hdGNoaW5nLlxuICogUmV0dXJucyB0aGUgcmVzb2x2ZWQgcGF0aCBvciBudWxsIHdpdGggYW4gZXJyb3IgdG8gc2VuZC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZUVsZW1lbnRGaWxlUGF0aChcbiAgcG9ydGZvbGlvRGlyOiBzdHJpbmcsIHR5cGU6IHN0cmluZywgbmFtZTogc3RyaW5nXG4pOiBQcm9taXNlPHsgZmlsZVBhdGg6IHN0cmluZyB9IHwgeyBlcnJvcjogc3RyaW5nOyBzdGF0dXM6IG51bWJlciB9PiB7XG4gIGlmICh0eXBlID09PSAnbWVtb3JpZXMnICYmIG5hbWUuaW5jbHVkZXMoJy8nKSkge1xuICAgIGNvbnN0IHBhcnRzID0gbmFtZS5zcGxpdCgnLycpO1xuICAgIGlmIChwYXJ0cy5sZW5ndGggIT09IDIgfHwgIS9eXFxkezR9LVxcZHsyfS1cXGR7Mn0kLy50ZXN0KHBhcnRzWzBdKSB8fCBpc0JhY2t1cE9yQ3J1ZnQocGFydHNbMV0pKSB7XG4gICAgICByZXR1cm4geyBlcnJvcjogJ0ludmFsaWQgbWVtb3J5IHBhdGgnLCBzdGF0dXM6IDQwMCB9O1xuICAgIH1cbiAgICBjb25zdCBmaWxlUGF0aCA9IGpvaW4ocG9ydGZvbGlvRGlyLCB0eXBlLCBuYW1lKTtcbiAgICBjb25zdCByZXNvbHZlZFBhdGggPSByZXNvbHZlKGZpbGVQYXRoKTtcbiAgICBpZiAoIXJlc29sdmVkUGF0aC5zdGFydHNXaXRoKHJlc29sdmUocG9ydGZvbGlvRGlyKSkpIHtcbiAgICAgIHJldHVybiB7IGVycm9yOiAnUGF0aCB0cmF2ZXJzYWwgZGV0ZWN0ZWQnLCBzdGF0dXM6IDQwMCB9O1xuICAgIH1cbiAgICByZXR1cm4geyBmaWxlUGF0aCB9O1xuICB9XG5cbiAgY29uc3QgdHlwZURpciA9IGpvaW4ocG9ydGZvbGlvRGlyLCB0eXBlKTtcbiAgY29uc3QgZmlsZXMgPSBhd2FpdCByZWFkZGlyKHR5cGVEaXIpO1xuICBjb25zdCBtYXRjaCA9IGZpbGVzLmZpbmQoZiA9PiB7XG4gICAgY29uc3QgYmFzZSA9IGYucmVwbGFjZShleHRuYW1lKGYpLCAnJyk7XG4gICAgcmV0dXJuIGJhc2UgPT09IG5hbWUgfHwgZiA9PT0gbmFtZTtcbiAgfSk7XG5cbiAgaWYgKCFtYXRjaCkge1xuICAgIHJldHVybiB7IGVycm9yOiBgRWxlbWVudCBub3QgZm91bmQ6ICR7dHlwZX0vJHtuYW1lfWAsIHN0YXR1czogNDA0IH07XG4gIH1cblxuICBjb25zdCBmaWxlUGF0aCA9IGpvaW4ocG9ydGZvbGlvRGlyLCB0eXBlLCBtYXRjaCk7XG4gIGNvbnN0IHJlc29sdmVkUGF0aCA9IHJlc29sdmUoZmlsZVBhdGgpO1xuICBpZiAoIXJlc29sdmVkUGF0aC5zdGFydHNXaXRoKHJlc29sdmUocG9ydGZvbGlvRGlyKSkpIHtcbiAgICByZXR1cm4geyBlcnJvcjogJ1BhdGggdHJhdmVyc2FsIGRldGVjdGVkJywgc3RhdHVzOiA0MDAgfTtcbiAgfVxuICByZXR1cm4geyBmaWxlUGF0aCB9O1xufVxuXG4vKipcbiAqIExvYWQgbWVtb3JpZXMgZnJvbSB0aGUgX2luZGV4Lmpzb24gZmlsZS5cbiAqIE1lbW9yaWVzIHVzZSBkYXRlLXBhcnRpdGlvbmVkIHN0b3JhZ2Ugd2l0aCBhbiBpbmRleCwgdW5saWtlIG90aGVyXG4gKiBlbGVtZW50IHR5cGVzIHdoaWNoIGFyZSBmbGF0IGZpbGVzIGluIGEgZGlyZWN0b3J5LlxuICovXG5hc3luYyBmdW5jdGlvbiBsb2FkTWVtb3JpZXNGcm9tSW5kZXgocG9ydGZvbGlvRGlyOiBzdHJpbmcpOiBQcm9taXNlPHVua25vd25bXT4ge1xuICBjb25zdCBpbmRleFBhdGggPSBqb2luKHBvcnRmb2xpb0RpciwgJ21lbW9yaWVzJywgJ19pbmRleC5qc29uJyk7XG4gIHRyeSB7XG4gICAgY29uc3QgcmF3ID0gYXdhaXQgcmVhZEZpbGUoaW5kZXhQYXRoLCAndXRmLTgnKTtcbiAgICBjb25zdCBpbmRleCA9IEpTT04ucGFyc2UocmF3KSBhcyB7XG4gICAgICBlbnRyaWVzPzogUmVjb3JkPHN0cmluZywgeyBuYW1lPzogc3RyaW5nOyBkZXNjcmlwdGlvbj86IHN0cmluZzsgdGFncz86IHN0cmluZ1tdOyBjcmVhdGVkPzogc3RyaW5nOyBba2V5OiBzdHJpbmddOiB1bmtub3duIH0+O1xuICAgICAgZW50cnlDb3VudD86IG51bWJlcjtcbiAgICB9O1xuXG4gICAgY29uc3QgZW50cmllcyA9IGluZGV4LmVudHJpZXMgfHwge307XG4gICAgY29uc3QgZWxlbWVudHM6IHVua25vd25bXSA9IFtdO1xuXG4gICAgZm9yIChjb25zdCBbcGF0aCwgZW50cnldIG9mIE9iamVjdC5lbnRyaWVzKGVudHJpZXMpKSB7XG4gICAgICBpZiAoIWVudHJ5IHx8IHR5cGVvZiBlbnRyeSAhPT0gJ29iamVjdCcpIGNvbnRpbnVlO1xuICAgICAgY29uc3QgcGF0aFBhcnRzID0gcGF0aC5zcGxpdCgnLycpO1xuICAgICAgY29uc3QgZmlsZW5hbWUgPSBwYXRoUGFydHMucG9wKCkgfHwgcGF0aDtcbiAgICAgIC8vIEV4dHJhY3QgZGF0ZSBmcm9tIGRpcmVjdG9yeSBwYXRoIChlLmcuLCBcIjIwMjUtMDktMTkvY29kZS1wYXR0ZXJucy55YW1sXCIgLT4gXCIyMDI1LTA5LTE5XCIpXG4gICAgICBjb25zdCBkYXRlRnJvbVBhdGggPSBwYXRoUGFydHMubGVuZ3RoID4gMCAmJiAvXlxcZHs0fS1cXGR7Mn0tXFxkezJ9JC8udGVzdChwYXRoUGFydHNbMF0pID8gcGF0aFBhcnRzWzBdIDogJyc7XG4gICAgICAvLyBGYWxsIGJhY2sgdG8gZmlsZW5hbWUgaWYgaW5kZXggaGFzIG5vIG5hbWUgb3Igc3RvcmVkIFwidW5uYW1lZFwiICh1cHN0cmVhbSBpbmRleGVyIGJ1ZylcbiAgICAgIGNvbnN0IGluZGV4TmFtZSA9IGVudHJ5Lm5hbWUgJiYgZW50cnkubmFtZSAhPT0gJ3VubmFtZWQnID8gZW50cnkubmFtZSA6IG51bGw7XG4gICAgICBjb25zdCBuYW1lID0gaW5kZXhOYW1lIHx8IGZpbGVuYW1lLnJlcGxhY2UoL1xcLih5YW1sfHltbHxtZCkkLywgJycpO1xuXG4gICAgICBlbGVtZW50cy5wdXNoKHtcbiAgICAgICAgbmFtZSxcbiAgICAgICAgZGVzY3JpcHRpb246IGVudHJ5LmRlc2NyaXB0aW9uIHx8ICcnLFxuICAgICAgICB0eXBlOiAnbWVtb3J5JyxcbiAgICAgICAgdmVyc2lvbjogZW50cnkudmVyc2lvbiB8fCAnMS4wLjAnLFxuICAgICAgICBhdXRob3I6IGVudHJ5LmF1dGhvciB8fCAnJyxcbiAgICAgICAgY2F0ZWdvcnk6IGVudHJ5LmNhdGVnb3J5IHx8IGVudHJ5Lm1lbW9yeVR5cGUgfHwgJycsXG4gICAgICAgIHRhZ3M6IGVudHJ5LnRhZ3MgfHwgW10sXG4gICAgICAgIGNyZWF0ZWQ6IGVudHJ5LmNyZWF0ZWQgfHwgZGF0ZUZyb21QYXRoLFxuICAgICAgICBmaWxlbmFtZTogcGF0aCwgLy8gZGF0ZS9maWxlbmFtZSBwYXRoIGZvciBjb250ZW50IGxvYWRpbmdcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBlbGVtZW50cztcbiAgfSBjYXRjaCB7XG4gICAgLy8gRmFsbCBiYWNrIHRvIGVtcHR5IGlmIG5vIGluZGV4XG4gICAgcmV0dXJuIFtdO1xuICB9XG59XG5cbi8qKiBSYXRlIGxpbWl0ZXIgZm9yIC9hcGkvaW5zdGFsbDogbWF4IDEwIGluc3RhbGxzIHBlciA2MCBzZWNvbmRzICovXG5jb25zdCBpbnN0YWxsUmF0ZUxpbWl0ZXIgPSBuZXcgU2xpZGluZ1dpbmRvd1JhdGVMaW1pdGVyKDEwLCA2MF8wMDApO1xuXG4vKiogU2FuaXRpemUgdGV4dCBjb250ZW50IHRvIHByZXZlbnQgWFNTIGluIHJlbmRlcmVkIEhUTUwgKi9cbmZ1bmN0aW9uIHNhbml0aXplRm9ySHRtbCh0ZXh0OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gdGV4dFxuICAgIC5yZXBsYWNlKC8mL2csICcmYW1wOycpXG4gICAgLnJlcGxhY2UoLzwvZywgJyZsdDsnKVxuICAgIC5yZXBsYWNlKC8+L2csICcmZ3Q7JylcbiAgICAucmVwbGFjZSgvXCIvZywgJyZxdW90OycpXG4gICAgLnJlcGxhY2UoLycvZywgJyYjMzk7Jyk7XG59XG5cbi8qKiBQYXJzZSBZQU1MIGZyb250IG1hdHRlciBmcm9tIGEgbWFya2Rvd24gZmlsZSAqL1xuZnVuY3Rpb24gcGFyc2VGcm9udE1hdHRlcihjb250ZW50OiBzdHJpbmcpOiB7IG1ldGFkYXRhOiBFbGVtZW50RGlzcGxheU1ldGFkYXRhOyBib2R5OiBzdHJpbmcgfSB7XG4gIGNvbnN0IG1hdGNoID0gY29udGVudC5tYXRjaCgvXi0tLVxccj9cXG4oW1xcc1xcU10qPylcXHI/XFxuLS0tXFxyP1xcbj8oW1xcc1xcU10qKSQvKTtcbiAgaWYgKCFtYXRjaCkge1xuICAgIHJldHVybiB7IG1ldGFkYXRhOiB7fSwgYm9keTogY29udGVudCB9O1xuICB9XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBwYXJzZWQgPSBTZWN1cmVZYW1sUGFyc2VyLnBhcnNlUmF3WWFtbChtYXRjaFsxXSk7XG4gICAgY29uc3QgbWV0YWRhdGEgPSAodHlwZW9mIHBhcnNlZCA9PT0gJ29iamVjdCcgJiYgcGFyc2VkICE9PSBudWxsKSA/IHBhcnNlZCBhcyBFbGVtZW50RGlzcGxheU1ldGFkYXRhIDoge307XG4gICAgcmV0dXJuIHsgbWV0YWRhdGEsIGJvZHk6IG1hdGNoWzJdIH07XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB7IG1ldGFkYXRhOiB7fSwgYm9keTogbWF0Y2hbMl0gfHwgY29udGVudCB9O1xuICB9XG59XG5cbi8qKiBQYXJzZSBhIFlBTUwtb25seSBmaWxlIChtZW1vcmllcykgKi9cbmZ1bmN0aW9uIHBhcnNlWWFtbEZpbGUoY29udGVudDogc3RyaW5nKTogeyBtZXRhZGF0YTogRWxlbWVudERpc3BsYXlNZXRhZGF0YTsgYm9keTogc3RyaW5nIH0ge1xuICB0cnkge1xuICAgIGNvbnN0IHBhcnNlZCA9IFNlY3VyZVlhbWxQYXJzZXIucGFyc2VSYXdZYW1sKGNvbnRlbnQpO1xuICAgIGNvbnN0IG1ldGFkYXRhID0gKHR5cGVvZiBwYXJzZWQgPT09ICdvYmplY3QnICYmIHBhcnNlZCAhPT0gbnVsbCkgPyBwYXJzZWQgYXMgRWxlbWVudERpc3BsYXlNZXRhZGF0YSA6IHt9O1xuICAgIHJldHVybiB7IG1ldGFkYXRhLCBib2R5OiAnJyB9O1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4geyBtZXRhZGF0YToge30sIGJvZHk6IGNvbnRlbnQgfTtcbiAgfVxufVxuXG4vKipcbiAqIFJlZ2lzdGVyIHBvcnRmb2xpbyByb3V0ZXMgc2hhcmVkIGJldHdlZW4gc2ltcGxlIGFuZCBnYXRld2F5IG1vZGVzLlxuICogVGhlIHN0cnVjdHVyZWREZXRhaWwgb3B0aW9uIGNvbnRyb2xzIHdoZXRoZXIgZGV0YWlsIHJvdXRlcyByZXR1cm5cbiAqIHN0cnVjdHVyZWQgSlNPTiAoZ2F0ZXdheSkgb3IgcGxhaW4gdGV4dCAoc2ltcGxlL2xlZ2FjeSkuXG4gKi9cbmZ1bmN0aW9uIHJlZ2lzdGVyUG9ydGZvbGlvUm91dGVzKFxuICByb3V0ZXI6IFJvdXRlcixcbiAgcG9ydGZvbGlvRGlyOiBzdHJpbmcsXG4gIG9wdGlvbnM6IHsgc3RydWN0dXJlZERldGFpbDogYm9vbGVhbjsgbG9nUHJlZml4OiBzdHJpbmcgfSxcbik6IHZvaWQge1xuICBjb25zdCB7IHN0cnVjdHVyZWREZXRhaWwsIGxvZ1ByZWZpeCB9ID0gb3B0aW9ucztcblxuICByb3V0ZXIuZ2V0KCcvZWxlbWVudHMnLCBhc3luYyAocmVxLCByZXMpID0+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcGFnZVBhcmFtID0gcmVxLnF1ZXJ5LnBhZ2UgYXMgc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgY29uc3QgcGFnZVNpemVQYXJhbSA9IHJlcS5xdWVyeS5wYWdlU2l6ZSBhcyBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgICBjb25zdCB3YW50UGFnaW5hdGlvbiA9IHBhZ2VQYXJhbSAhPT0gdW5kZWZpbmVkICYmIHBhZ2VTaXplUGFyYW0gIT09IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IHBhZ2UgPSBNYXRoLm1heCgxLCBOdW1iZXIucGFyc2VJbnQocGFnZVBhcmFtIHx8ICcxJywgMTApIHx8IDEpO1xuICAgICAgY29uc3QgcGFnZVNpemUgPSBNYXRoLm1heCgxLCBNYXRoLm1pbigyMDAsIE51bWJlci5wYXJzZUludChwYWdlU2l6ZVBhcmFtIHx8ICc1MCcsIDEwKSB8fCA1MCkpO1xuXG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHVua25vd25bXT4gPSB7fTtcbiAgICAgIGxldCB0b3RhbENvdW50ID0gMDtcblxuICAgICAgZm9yIChjb25zdCB0eXBlIG9mIEVMRU1FTlRfVFlQRVMpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBpZiAodHlwZSA9PT0gJ21lbW9yaWVzJykge1xuICAgICAgICAgICAgY29uc3QgbWVtRWxlbWVudHMgPSBhd2FpdCBsb2FkTWVtb3JpZXNGcm9tSW5kZXgocG9ydGZvbGlvRGlyKTtcbiAgICAgICAgICAgIHJlc3VsdFt0eXBlXSA9IG1lbUVsZW1lbnRzO1xuICAgICAgICAgICAgdG90YWxDb3VudCArPSBtZW1FbGVtZW50cy5sZW5ndGg7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCB0eXBlRGlyID0gam9pbihwb3J0Zm9saW9EaXIsIHR5cGUpO1xuICAgICAgICAgIGNvbnN0IGRpclN0YXQgPSBhd2FpdCBzdGF0KHR5cGVEaXIpO1xuICAgICAgICAgIGlmICghZGlyU3RhdC5pc0RpcmVjdG9yeSgpKSBjb250aW51ZTtcblxuICAgICAgICAgIGNvbnN0IGVsZW1lbnRzID0gYXdhaXQgc2NhbkVsZW1lbnREaXJlY3RvcnkodHlwZURpciwgdHlwZSwgbG9nUHJlZml4KTtcbiAgICAgICAgICByZXN1bHRbdHlwZV0gPSBlbGVtZW50cztcbiAgICAgICAgICB0b3RhbENvdW50ICs9IGVsZW1lbnRzLmxlbmd0aDtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgcmVzdWx0W3R5cGVdID0gW107XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHdhbnRQYWdpbmF0aW9uKSB7XG4gICAgICAgIGNvbnN0IGFsbEVsZW1lbnRzOiB1bmtub3duW10gPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCB0eXBlIG9mIEVMRU1FTlRfVFlQRVMpIHtcbiAgICAgICAgICBhbGxFbGVtZW50cy5wdXNoKC4uLihyZXN1bHRbdHlwZV0gfHwgW10pKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzdGFydCA9IChwYWdlIC0gMSkgKiBwYWdlU2l6ZTtcbiAgICAgICAgY29uc3QgcGFnZWQgPSBhbGxFbGVtZW50cy5zbGljZShzdGFydCwgc3RhcnQgKyBwYWdlU2l6ZSk7XG4gICAgICAgIGNvbnN0IHRvdGFsUGFnZXMgPSBNYXRoLmNlaWwoYWxsRWxlbWVudHMubGVuZ3RoIC8gcGFnZVNpemUpO1xuICAgICAgICByZXMuanNvbih7IGVsZW1lbnRzOiBwYWdlZCwgdG90YWxDb3VudDogYWxsRWxlbWVudHMubGVuZ3RoLCBwYWdlLCBwYWdlU2l6ZSwgdG90YWxQYWdlcyB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlcy5qc29uKHsgZWxlbWVudHM6IHJlc3VsdCwgdG90YWxDb3VudCB9KTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGxvZ2dlci5lcnJvcihgJHtsb2dQcmVmaXh9IEZhaWxlZCB0byBsaXN0IGVsZW1lbnRzOmAsIGVycik7XG4gICAgICByZXMuc3RhdHVzKDUwMCkuanNvbih7IGVycm9yOiAnRmFpbGVkIHRvIGxpc3QgZWxlbWVudHMnIH0pO1xuICAgIH1cbiAgfSk7XG5cbiAgcm91dGVyLmdldCgnL2VsZW1lbnRzLzp0eXBlJywgYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgY29uc3QgdHlwZSA9IG5vcm1hbGl6ZUlucHV0KHJlcS5wYXJhbXMudHlwZSk7XG4gICAgaWYgKCFFTEVNRU5UX1RZUEVTLmluY2x1ZGVzKHR5cGUgYXMgdHlwZW9mIEVMRU1FTlRfVFlQRVNbbnVtYmVyXSkpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHsgZXJyb3I6IGBJbnZhbGlkIGVsZW1lbnQgdHlwZTogJHt0eXBlfWAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGlmICh0eXBlID09PSAnbWVtb3JpZXMnKSB7XG4gICAgICAgIGNvbnN0IG1lbUVsZW1lbnRzID0gYXdhaXQgbG9hZE1lbW9yaWVzRnJvbUluZGV4KHBvcnRmb2xpb0Rpcik7XG4gICAgICAgIHJlcy5qc29uKHsgdHlwZSwgZWxlbWVudHM6IG1lbUVsZW1lbnRzLCBjb3VudDogbWVtRWxlbWVudHMubGVuZ3RoIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVsZW1lbnRzID0gYXdhaXQgc2NhbkVsZW1lbnREaXJlY3Rvcnkoam9pbihwb3J0Zm9saW9EaXIsIHR5cGUpLCB0eXBlLCBsb2dQcmVmaXgpO1xuICAgICAgcmVzLmpzb24oeyB0eXBlLCBlbGVtZW50cywgY291bnQ6IGVsZW1lbnRzLmxlbmd0aCB9KTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHsgZXJyb3I6IGBGYWlsZWQgdG8gbGlzdCAke3R5cGV9YCB9KTtcbiAgICB9XG4gIH0pO1xuXG4gIHJvdXRlci5nZXQoJy9lbGVtZW50cy9tZW1vcmllcy86ZGF0ZS86ZmlsZScsIGFzeW5jIChyZXEsIHJlcykgPT4ge1xuICAgIGNvbnN0IHsgZGF0ZSwgZmlsZSB9ID0gcmVxLnBhcmFtcztcblxuICAgIGlmICghL15cXGR7NH0tXFxkezJ9LVxcZHsyfSQvLnRlc3QoZGF0ZSkpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHsgZXJyb3I6ICdJbnZhbGlkIGRhdGUgZm9ybWF0JyB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGZpbGUuaW5jbHVkZXMoJy4uJykgfHwgZmlsZS5pbmNsdWRlcygnLycpIHx8IGZpbGUuaW5jbHVkZXMoJ1xcXFwnKSB8fCBpc0JhY2t1cE9yQ3J1ZnQoZmlsZSkpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHsgZXJyb3I6ICdJbnZhbGlkIGZpbGVuYW1lJyB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgZmlsZVBhdGggPSBqb2luKHBvcnRmb2xpb0RpciwgJ21lbW9yaWVzJywgZGF0ZSwgZmlsZSk7XG4gICAgICBjb25zdCByZXNvbHZlZFBhdGggPSByZXNvbHZlKGZpbGVQYXRoKTtcbiAgICAgIGlmICghcmVzb2x2ZWRQYXRoLnN0YXJ0c1dpdGgocmVzb2x2ZShwb3J0Zm9saW9EaXIpKSkge1xuICAgICAgICByZXMuc3RhdHVzKDQwMCkuanNvbih7IGVycm9yOiAnUGF0aCB0cmF2ZXJzYWwgZGV0ZWN0ZWQnIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGZpbGVTdGF0ID0gYXdhaXQgc3RhdChmaWxlUGF0aCk7XG4gICAgICBpZiAoIWZpbGVTdGF0LmlzRmlsZSgpIHx8IGZpbGVTdGF0LnNpemUgPiBNQVhfRklMRV9TSVpFX0JZVEVTKSB7XG4gICAgICAgIHJlcy5zdGF0dXMoZmlsZVN0YXQuaXNGaWxlKCkgPyA0MTMgOiA0MDQpLmpzb24oeyBlcnJvcjogZmlsZVN0YXQuaXNGaWxlKCkgPyAnRmlsZSB0b28gbGFyZ2UnIDogJ05vdCBmb3VuZCcgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IHJlYWRGaWxlKGZpbGVQYXRoLCAndXRmLTgnKTtcbiAgICAgIGlmIChzdHJ1Y3R1cmVkRGV0YWlsKSB7XG4gICAgICAgIGNvbnN0IHZhbGlkYXRpb24gPSB2YWxpZGF0ZUVsZW1lbnRDb250ZW50KGZpbGUsIGNvbnRlbnQsICdtZW1vcmllcycpO1xuICAgICAgICByZXMuanNvbihidWlsZFZhbGlkYXRpb25SZXNwb25zZSh2YWxpZGF0aW9uLCBjb250ZW50LCAnbWVtb3JpZXMnKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAndGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCcpO1xuICAgICAgICByZXMuc2VuZChjb250ZW50KTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIHtcbiAgICAgIHJlcy5zdGF0dXMoNDA0KS5qc29uKHsgZXJyb3I6IGBNZW1vcnkgbm90IGZvdW5kOiAke2RhdGV9LyR7ZmlsZX1gIH0pO1xuICAgIH1cbiAgfSk7XG5cbiAgcm91dGVyLmdldCgnL2VsZW1lbnRzLzp0eXBlLzpuYW1lJywgYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgY29uc3QgeyB0eXBlLCBuYW1lIH0gPSByZXEucGFyYW1zO1xuICAgIGlmICghRUxFTUVOVF9UWVBFUy5pbmNsdWRlcyh0eXBlIGFzIHR5cGVvZiBFTEVNRU5UX1RZUEVTW251bWJlcl0pKSB7XG4gICAgICByZXMuc3RhdHVzKDQwMCkuanNvbih7IGVycm9yOiBgSW52YWxpZCBlbGVtZW50IHR5cGU6ICR7dHlwZX1gIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChuYW1lLmluY2x1ZGVzKCcuLicpIHx8IG5hbWUuaW5jbHVkZXMoJ1xcXFwnKSkge1xuICAgICAgcmVzLnN0YXR1cyg0MDApLmpzb24oeyBlcnJvcjogJ0ludmFsaWQgZWxlbWVudCBuYW1lJyB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodHlwZSAhPT0gJ21lbW9yaWVzJyAmJiBuYW1lLmluY2x1ZGVzKCcvJykpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHsgZXJyb3I6ICdJbnZhbGlkIGVsZW1lbnQgbmFtZScgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc29sdmVkID0gYXdhaXQgcmVzb2x2ZUVsZW1lbnRGaWxlUGF0aChwb3J0Zm9saW9EaXIsIHR5cGUsIG5hbWUpO1xuICAgICAgaWYgKCdlcnJvcicgaW4gcmVzb2x2ZWQpIHtcbiAgICAgICAgcmVzLnN0YXR1cyhyZXNvbHZlZC5zdGF0dXMpLmpzb24oeyBlcnJvcjogcmVzb2x2ZWQuZXJyb3IgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZmlsZVN0YXQgPSBhd2FpdCBzdGF0KHJlc29sdmVkLmZpbGVQYXRoKTtcbiAgICAgIGlmIChmaWxlU3RhdC5zaXplID4gTUFYX0ZJTEVfU0laRV9CWVRFUykge1xuICAgICAgICByZXMuc3RhdHVzKDQxMykuanNvbih7IGVycm9yOiBgRmlsZSB0b28gbGFyZ2UgKCR7ZmlsZVN0YXQuc2l6ZX0gYnl0ZXMpLiBNYXggMSBNQi5gIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCByZWFkRmlsZShyZXNvbHZlZC5maWxlUGF0aCwgJ3V0Zi04Jyk7XG4gICAgICBpZiAoc3RydWN0dXJlZERldGFpbCkge1xuICAgICAgICBjb25zdCBmaWxlbmFtZSA9IHJlc29sdmVkLmZpbGVQYXRoLnNwbGl0KCcvJykucG9wKCkgfHwgbmFtZTtcbiAgICAgICAgY29uc3QgdmFsaWRhdGlvbiA9IHZhbGlkYXRlRWxlbWVudENvbnRlbnQoZmlsZW5hbWUsIGNvbnRlbnQsIHR5cGUpO1xuICAgICAgICByZXMuanNvbihidWlsZFZhbGlkYXRpb25SZXNwb25zZSh2YWxpZGF0aW9uLCBjb250ZW50LCB0eXBlKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAndGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCcpO1xuICAgICAgICByZXMuc2VuZChjb250ZW50KTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIHtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHsgZXJyb3I6IGBGYWlsZWQgdG8gZ2V0IGVsZW1lbnQ6ICR7dHlwZX0vJHtuYW1lfWAgfSk7XG4gICAgfVxuICB9KTtcbn1cblxuLyoqIFJlZ2lzdGVyIGZpbGVzeXN0ZW0tYmFzZWQgc3RhdHMgcm91dGUgKHNoYXJlZCBiZXR3ZWVuIHNpbXBsZSBhbmQgZ2F0ZXdheSkgKi9cbmZ1bmN0aW9uIHJlZ2lzdGVyU3RhdHNSb3V0ZShyb3V0ZXI6IFJvdXRlciwgcG9ydGZvbGlvRGlyOiBzdHJpbmcpOiB2b2lkIHtcbiAgcm91dGVyLmdldCgnL3N0YXRzJywgYXN5bmMgKF9yZXEsIHJlcykgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBzdGF0czogUmVjb3JkPHN0cmluZywgbnVtYmVyPiA9IHt9O1xuICAgICAgbGV0IHRvdGFsID0gMDtcblxuICAgICAgZm9yIChjb25zdCB0eXBlIG9mIEVMRU1FTlRfVFlQRVMpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBpZiAodHlwZSA9PT0gJ21lbW9yaWVzJykge1xuICAgICAgICAgICAgY29uc3QgbWVtRWxlbWVudHMgPSBhd2FpdCBsb2FkTWVtb3JpZXNGcm9tSW5kZXgocG9ydGZvbGlvRGlyKTtcbiAgICAgICAgICAgIHN0YXRzW3R5cGVdID0gbWVtRWxlbWVudHMubGVuZ3RoO1xuICAgICAgICAgICAgdG90YWwgKz0gbWVtRWxlbWVudHMubGVuZ3RoO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IHR5cGVEaXIgPSBqb2luKHBvcnRmb2xpb0RpciwgdHlwZSk7XG4gICAgICAgICAgY29uc3QgZmlsZXMgPSBhd2FpdCByZWFkZGlyKHR5cGVEaXIpO1xuICAgICAgICAgIGNvbnN0IGNvdW50ID0gZmlsZXMuZmlsdGVyKGYgPT4gIWlzQmFja3VwT3JDcnVmdChmKSAmJiBWQUxJRF9FWFRFTlNJT05TLmhhcyhleHRuYW1lKGYpKSkubGVuZ3RoO1xuICAgICAgICAgIHN0YXRzW3R5cGVdID0gY291bnQ7XG4gICAgICAgICAgdG90YWwgKz0gY291bnQ7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHN0YXRzW3R5cGVdID0gMDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXMuanNvbih7IHN0YXRzLCB0b3RhbCB9KTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHsgZXJyb3I6ICdGYWlsZWQgdG8gZ2V0IHN0YXRzJyB9KTtcbiAgICB9XG4gIH0pO1xufVxuXG4vKiogUmVnaXN0ZXIgY29sbGVjdGlvbiBpbmRleCBwcm94eSByb3V0ZSAoc2hhcmVkIGJldHdlZW4gc2ltcGxlIGFuZCBnYXRld2F5KSAqL1xuZnVuY3Rpb24gcmVnaXN0ZXJDb2xsZWN0aW9uUm91dGUocm91dGVyOiBSb3V0ZXIsIHBvcnRmb2xpb0Rpcjogc3RyaW5nKTogdm9pZCB7XG4gIHJvdXRlci5nZXQoJy9jb2xsZWN0aW9uJywgYXN5bmMgKF9yZXEsIHJlcykgPT4ge1xuICAgIHJlcy5zZXRIZWFkZXIoJ0NhY2hlLUNvbnRyb2wnLCAnbm8tY2FjaGUnKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKCdodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vRG9sbGhvdXNlTUNQL2NvbGxlY3Rpb24vbWFpbi9wdWJsaWMvY29sbGVjdGlvbi1pbmRleC5qc29uJyk7XG4gICAgICBpZiAocmVzcG9uc2Uub2spIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHJlc3BvbnNlLnRleHQoKTtcbiAgICAgICAgcmVzLnNldEhlYWRlcignQ29udGVudC1UeXBlJywgJ2FwcGxpY2F0aW9uL2pzb24nKTtcbiAgICAgICAgcmVzLnNlbmQoZGF0YSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9IGNhdGNoIHsgLyogR2l0SHViIHVucmVhY2hhYmxlIOKAlCBmYWxsIGJhY2sgdG8gbG9jYWwgKi8gfVxuXG4gICAgY29uc3QgbG9jYWxQYXRocyA9IFtcbiAgICAgIGpvaW4ocG9ydGZvbGlvRGlyLCAnLi4nLCAnLi4nLCAnLi4nLCAnY29sbGVjdGlvbicsICdwdWJsaWMnLCAnY29sbGVjdGlvbi1pbmRleC5qc29uJyksXG4gICAgICBqb2luKHBvcnRmb2xpb0RpciwgJy4uJywgJ2NvbGxlY3Rpb24nLCAncHVibGljJywgJ2NvbGxlY3Rpb24taW5kZXguanNvbicpLFxuICAgIF07XG5cbiAgICBmb3IgKGNvbnN0IGxvY2FsUGF0aCBvZiBsb2NhbFBhdGhzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgcmVhZEZpbGUobG9jYWxQYXRoLCAndXRmLTgnKTtcbiAgICAgICAgcmVzLnNldEhlYWRlcignQ29udGVudC1UeXBlJywgJ2FwcGxpY2F0aW9uL2pzb24nKTtcbiAgICAgICAgcmVzLnNlbmQoY29udGVudCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gY2F0Y2ggeyAvKiB0cnkgbmV4dCAqLyB9XG4gICAgfVxuXG4gICAgcmVzLnN0YXR1cyg0MDQpLmpzb24oeyBlcnJvcjogJ0NvbGxlY3Rpb24gaW5kZXggbm90IGF2YWlsYWJsZScgfSk7XG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQXBpUm91dGVzKHBvcnRmb2xpb0Rpcjogc3RyaW5nKTogUm91dGVyIHtcbiAgY29uc3Qgcm91dGVyID0gUm91dGVyKCk7XG5cbiAgcmVnaXN0ZXJQb3J0Zm9saW9Sb3V0ZXMocm91dGVyLCBwb3J0Zm9saW9EaXIsIHsgc3RydWN0dXJlZERldGFpbDogZmFsc2UsIGxvZ1ByZWZpeDogJ1tXZWJVSV0nIH0pO1xuXG4gIHJlZ2lzdGVyU3RhdHNSb3V0ZShyb3V0ZXIsIHBvcnRmb2xpb0Rpcik7XG4gIHJlZ2lzdGVyQ29sbGVjdGlvblJvdXRlKHJvdXRlciwgcG9ydGZvbGlvRGlyKTtcblxuICAvKipcbiAgICogUE9TVCAvYXBpL2luc3RhbGxcbiAgICogSW5zdGFsbCBhIGNvbGxlY3Rpb24gZWxlbWVudCBpbnRvIHRoZSBsb2NhbCBwb3J0Zm9saW8uXG4gICAqIFJvdXRlcyB0aHJvdWdoIERvbGxob3VzZU1DUCdzIGluc3RhbGxfY29sbGVjdGlvbl9jb250ZW50IHBpcGVsaW5lXG4gICAqIGZvciBwcm9wZXIgdmFsaWRhdGlvbiwgZ2F0ZWtlZXBlciBjaGVja3MsIGFuZCBlbGVtZW50IG1hbmFnZW1lbnQuXG4gICAqXG4gICAqIFJlcXVpcmVzIHRoZSBNQ1Agc2VydmVyJ3MgQ29sbGVjdGlvbkhhbmRsZXIgdG8gYmUgYXZhaWxhYmxlLlxuICAgKiBGYWxscyBiYWNrIHRvIGRpcmVjdCBmaWxlIHdyaXRlIGlmIG5vdCAoc3RhbmRhbG9uZSB3ZWIgbW9kZSkuXG4gICAqL1xuICByb3V0ZXIucG9zdCgnL2luc3RhbGwnLCBleHByZXNzLmpzb24oKSwgYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgaWYgKCFpbnN0YWxsUmF0ZUxpbWl0ZXIudHJ5QWNxdWlyZSgpKSB7XG4gICAgICByZXMuc3RhdHVzKDQyOSkuanNvbih7IGVycm9yOiAnVG9vIG1hbnkgaW5zdGFsbCByZXF1ZXN0cy4gTWF4IDEwIHBlciBtaW51dGUuJyB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB7IHBhdGg6IGVsZW1lbnRQYXRoLCBuYW1lLCB0eXBlIH0gPSByZXEuYm9keSBhcyB7IHBhdGg/OiBzdHJpbmc7IG5hbWU/OiBzdHJpbmc7IHR5cGU/OiBzdHJpbmcgfTtcblxuICAgIGlmICghZWxlbWVudFBhdGggfHwgIXR5cGUgfHwgIW5hbWUpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHsgZXJyb3I6ICdNaXNzaW5nIHJlcXVpcmVkIGZpZWxkczogcGF0aCwgbmFtZSwgdHlwZScgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgdHlwZVxuICAgIGNvbnN0IHBsdXJhbFR5cGUgPSB0eXBlLmVuZHNXaXRoKCdzJykgPyB0eXBlIDogYCR7dHlwZX1zYDtcbiAgICBpZiAoIUVMRU1FTlRfVFlQRVMuaW5jbHVkZXMocGx1cmFsVHlwZSBhcyB0eXBlb2YgRUxFTUVOVF9UWVBFU1tudW1iZXJdKSkge1xuICAgICAgcmVzLnN0YXR1cyg0MDApLmpzb24oeyBlcnJvcjogYEludmFsaWQgZWxlbWVudCB0eXBlOiAke3R5cGV9YCB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBQcmV2ZW50IHBhdGggdHJhdmVyc2FsXG4gICAgaWYgKGVsZW1lbnRQYXRoLmluY2x1ZGVzKCcuLicpIHx8IG5hbWUuaW5jbHVkZXMoJy4uJykpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHsgZXJyb3I6ICdJbnZhbGlkIHBhdGggb3IgbmFtZScgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgZWxlbWVudFBhdGggY29udGFpbnMgb25seSBzYWZlIGNoYXJhY3RlcnMgKGFscGhhbnVtZXJpYywgaHlwaGVucywgdW5kZXJzY29yZXMsIGRvdHMsIHNsYXNoZXMpXG4gICAgaWYgKCEvXlthLXpBLVowLTkvXy4tXSskLy50ZXN0KGVsZW1lbnRQYXRoKSkge1xuICAgICAgcmVzLnN0YXR1cyg0MDApLmpzb24oeyBlcnJvcjogJ0ludmFsaWQgZWxlbWVudCBwYXRoIGNoYXJhY3RlcnMnIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICAvLyBGZXRjaCBjb250ZW50IGZyb20gR2l0SHViXG4gICAgICBjb25zdCBnaFVybCA9IGBodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vRG9sbGhvdXNlTUNQL2NvbGxlY3Rpb24vbWFpbi8ke2VsZW1lbnRQYXRofWA7XG5cbiAgICAgIC8vIFZhbGlkYXRlIHRoZSBjb25zdHJ1Y3RlZCBVUkwgc3RheXMgd2l0aGluIGV4cGVjdGVkIGRvbWFpbiBhbmQgcGF0aFxuICAgICAgY29uc3QgcGFyc2VkVXJsID0gbmV3IFVSTChnaFVybCk7XG4gICAgICBpZiAocGFyc2VkVXJsLmhvc3RuYW1lICE9PSAncmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbScgfHwgIXBhcnNlZFVybC5wYXRobmFtZS5zdGFydHNXaXRoKCcvRG9sbGhvdXNlTUNQL2NvbGxlY3Rpb24vJykpIHtcbiAgICAgICAgcmVzLnN0YXR1cyg0MDApLmpzb24oeyBlcnJvcjogJ0ludmFsaWQgY29sbGVjdGlvbiBwYXRoJyB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGdoVXJsKTtcbiAgICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgcmVzLnN0YXR1cyg1MDIpLmpzb24oeyBlcnJvcjogYEZhaWxlZCB0byBmZXRjaCBmcm9tIGNvbGxlY3Rpb246IEhUVFAgJHtyZXNwb25zZS5zdGF0dXN9YCB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IHJlc3BvbnNlLnRleHQoKTtcblxuICAgICAgLy8gVmFsaWRhdGUgY29udGVudCB0aHJvdWdoIHRoZSBzZWN1cml0eSBwaXBlbGluZSBiZWZvcmUgd3JpdGluZ1xuICAgICAgY29uc3QgZXh0ID0gZXh0bmFtZShlbGVtZW50UGF0aCk7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoZXh0ID09PSAnLnlhbWwnIHx8IGV4dCA9PT0gJy55bWwnKSB7XG4gICAgICAgICAgLy8gVmFsaWRhdGUgWUFNTCBjb250ZW50IGZvciBib21icywgY2lyY3VsYXIgcmVmZXJlbmNlcywgbWFsaWNpb3VzIHBhdHRlcm5zXG4gICAgICAgICAgaWYgKCFDb250ZW50VmFsaWRhdG9yLnZhbGlkYXRlWWFtbENvbnRlbnQoY29udGVudCkpIHtcbiAgICAgICAgICAgIHJlcy5zdGF0dXMoNDIyKS5qc29uKHsgZXJyb3I6ICdDb250ZW50IGZhaWxlZCBZQU1MIHZhbGlkYXRpb24g4oCUIHBvdGVudGlhbGx5IG1hbGljaW91cyBwYXR0ZXJucyBkZXRlY3RlZCcgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIFNlY3VyZVlhbWxQYXJzZXIucGFyc2VSYXdZYW1sKGNvbnRlbnQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIFZhbGlkYXRlIG1hcmtkb3duK2Zyb250bWF0dGVyIGNvbnRlbnRcbiAgICAgICAgICBTZWN1cmVZYW1sUGFyc2VyLnBhcnNlKGNvbnRlbnQpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChwYXJzZUVycikge1xuICAgICAgICByZXMuc3RhdHVzKDQyMikuanNvbih7IGVycm9yOiBgQ29udGVudCBmYWlsZWQgcGFyc2UgdmFsaWRhdGlvbjogJHsocGFyc2VFcnIgYXMgRXJyb3IpLm1lc3NhZ2V9YCB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBWYWxpZGF0ZSBjb250ZW50IGJvZHkgZm9yIGluamVjdGlvbiBwYXR0ZXJuc1xuICAgICAgY29uc3Qgc2luZ3VsYXJUeXBlID0gcGx1cmFsVHlwZS5zbGljZSgwLCAtMSk7XG4gICAgICBjb25zdCBjb250ZXh0VHlwZXMgPSBbJ3BlcnNvbmEnLCAnc2tpbGwnLCAndGVtcGxhdGUnLCAnYWdlbnQnLCAnbWVtb3J5J10gYXMgY29uc3Q7XG4gICAgICB0eXBlIENvbnRlbnRDb250ZXh0ID0gdHlwZW9mIGNvbnRleHRUeXBlc1tudW1iZXJdO1xuICAgICAgY29uc3QgY29udGVudENvbnRleHQgPSBjb250ZXh0VHlwZXMuaW5jbHVkZXMoc2luZ3VsYXJUeXBlIGFzIENvbnRlbnRDb250ZXh0KSA/IHNpbmd1bGFyVHlwZSBhcyBDb250ZW50Q29udGV4dCA6IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IHZhbGlkYXRpb25SZXN1bHQgPSBDb250ZW50VmFsaWRhdG9yLnZhbGlkYXRlQW5kU2FuaXRpemUoY29udGVudCwge1xuICAgICAgICBjb250ZW50Q29udGV4dCxcbiAgICAgIH0pO1xuICAgICAgaWYgKCF2YWxpZGF0aW9uUmVzdWx0LmlzVmFsaWQpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1tXZWJVSV0gSW5zdGFsbCBibG9ja2VkIOKAlCBjb250ZW50IHZhbGlkYXRpb24gZmFpbGVkJywge1xuICAgICAgICAgIGVsZW1lbnQ6IGAke3BsdXJhbFR5cGV9LyR7bmFtZX1gLFxuICAgICAgICAgIHBhdHRlcm5zOiB2YWxpZGF0aW9uUmVzdWx0LmRldGVjdGVkUGF0dGVybnMsXG4gICAgICAgICAgc2V2ZXJpdHk6IHZhbGlkYXRpb25SZXN1bHQuc2V2ZXJpdHksXG4gICAgICAgIH0pO1xuICAgICAgICByZXMuc3RhdHVzKDQyMikuanNvbih7XG4gICAgICAgICAgZXJyb3I6ICdDb250ZW50IGZhaWxlZCBzZWN1cml0eSB2YWxpZGF0aW9uJyxcbiAgICAgICAgICBwYXR0ZXJuczogdmFsaWRhdGlvblJlc3VsdC5kZXRlY3RlZFBhdHRlcm5zLFxuICAgICAgICAgIHNldmVyaXR5OiB2YWxpZGF0aW9uUmVzdWx0LnNldmVyaXR5LFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBEZXRlcm1pbmUgZmlsZW5hbWVcbiAgICAgIGNvbnN0IGZpbGVuYW1lID0gZWxlbWVudFBhdGguc3BsaXQoJy8nKS5wb3AoKSB8fCBgJHtuYW1lfS5tZGA7XG5cbiAgICAgIC8vIEVuc3VyZSB0eXBlIGRpcmVjdG9yeSBleGlzdHNcbiAgICAgIGNvbnN0IHR5cGVEaXIgPSBqb2luKHBvcnRmb2xpb0RpciwgcGx1cmFsVHlwZSk7XG4gICAgICBjb25zdCB7IG1rZGlyIH0gPSBhd2FpdCBpbXBvcnQoJ25vZGU6ZnMvcHJvbWlzZXMnKTtcbiAgICAgIGF3YWl0IG1rZGlyKHR5cGVEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuXG4gICAgICAvLyBXcml0ZSB0byBwb3J0Zm9saW9cbiAgICAgIGNvbnN0IGRlc3RQYXRoID0gam9pbih0eXBlRGlyLCBmaWxlbmFtZSk7XG5cbiAgICAgIC8vIFZlcmlmeSByZXNvbHZlZCBkZXN0aW5hdGlvbiBwYXRoIHN0YXlzIHdpdGhpbiBwb3J0Zm9saW8gZGlyZWN0b3J5IChkZWZlbnNlIGluIGRlcHRoKVxuICAgICAgY29uc3QgcmVzb2x2ZWREZXN0ID0gcmVzb2x2ZShkZXN0UGF0aCk7XG4gICAgICBpZiAoIXJlc29sdmVkRGVzdC5zdGFydHNXaXRoKHJlc29sdmUocG9ydGZvbGlvRGlyKSkpIHtcbiAgICAgICAgcmVzLnN0YXR1cyg0MDApLmpzb24oeyBlcnJvcjogJ1BhdGggdHJhdmVyc2FsIGRldGVjdGVkJyB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayBpZiBmaWxlIGFscmVhZHkgZXhpc3RzXG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBzdGF0KGRlc3RQYXRoKTtcbiAgICAgICAgcmVzLnN0YXR1cyg0MDkpLmpzb24oeyBlcnJvcjogYEVsZW1lbnQgYWxyZWFkeSBleGlzdHM6ICR7cGx1cmFsVHlwZX0vJHtmaWxlbmFtZX0uIERlbGV0ZSBpdCBmaXJzdCBvciByZW5hbWUuYCB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBjYXRjaCB7IC8qIGRvZXNuJ3QgZXhpc3Qg4oCUIGdvb2QgKi8gfVxuXG4gICAgICBjb25zdCB7IHdyaXRlRmlsZTogd3JpdGVGaWxlRnMgfSA9IGF3YWl0IGltcG9ydCgnbm9kZTpmcy9wcm9taXNlcycpO1xuICAgICAgYXdhaXQgd3JpdGVGaWxlRnMoZGVzdFBhdGgsIGNvbnRlbnQsICd1dGYtOCcpO1xuXG4gICAgICBsb2dnZXIuaW5mbyhgW1dlYlVJXSBJbnN0YWxsZWQgY29sbGVjdGlvbiBlbGVtZW50OiAke3BsdXJhbFR5cGV9LyR7ZmlsZW5hbWV9YCk7XG4gICAgICByZXMuanNvbih7IHN1Y2Nlc3M6IHRydWUsIG1lc3NhZ2U6IGBJbnN0YWxsZWQgJHtuYW1lfSB0byBwb3J0Zm9saW9gLCBwYXRoOiBgJHtwbHVyYWxUeXBlfS8ke2ZpbGVuYW1lfWAgfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ1tXZWJVSV0gSW5zdGFsbCBmYWlsZWQ6JywgZXJyKTtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHsgZXJyb3I6IGBJbnN0YWxsIGZhaWxlZDogJHsoZXJyIGFzIEVycm9yKS5tZXNzYWdlfWAgfSk7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gcm91dGVyO1xufVxuXG4vLyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbi8vIFdlYiBNQ1AtQVFMIEdhdGV3YXkgUm91dGVzIChJc3N1ZSAjNzk2KVxuLy9cbi8vIFRoZXNlIHJvdXRlcyB0cmFuc2xhdGUgSFRUUCByZXF1ZXN0cyBpbnRvIE1DUEFRTEhhbmRsZXIgY2FsbHMsIHJvdXRpbmcgYWxsXG4vLyByZWFkcy93cml0ZXMgdGhyb3VnaCB0aGUgZXhpc3RpbmcgZWxlbWVudCBtYW5hZ2VycywgdmFsaWRhdGlvbiwgYW5kIGdhdGVrZWVwZXIuXG4vLyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuLyoqXG4gKiBFeHRyYWN0IHNpbmdsZSBvcGVyYXRpb24gcmVzdWx0IGZyb20gTUNQQVFMSGFuZGxlciByZXNwb25zZS5cbiAqIFdlYiByb3V0ZXMgbmV2ZXIgc2VuZCBiYXRjaCByZXF1ZXN0cywgc28gY2FzdCBpcyBzYWZlLlxuICovXG5pbnRlcmZhY2UgU2luZ2xlT3BSZXN1bHQgeyBzdWNjZXNzOiBib29sZWFuOyBkYXRhPzogdW5rbm93bjsgZXJyb3I/OiBzdHJpbmcgfVxuZnVuY3Rpb24gYXNTaW5nbGVSZXN1bHQocjogdW5rbm93bik6IFNpbmdsZU9wUmVzdWx0IHtcbiAgaWYgKHR5cGVvZiByID09PSAnb2JqZWN0JyAmJiByICE9PSBudWxsICYmICdzdWNjZXNzJyBpbiByKSB7XG4gICAgcmV0dXJuIHIgYXMgU2luZ2xlT3BSZXN1bHQ7XG4gIH1cbiAgcmV0dXJuIHsgc3VjY2VzczogZmFsc2UsIGVycm9yOiAnSW52YWxpZCBvcGVyYXRpb24gcmVzdWx0IGZvcm1hdCcgfTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgQVBJIHJvdXRlcyB0aGF0IHJvdXRlIHRocm91Z2ggTUNQQVFMSGFuZGxlciAoZ2F0ZXdheSBtb2RlKS5cbiAqIEFsbCBvcGVyYXRpb25zIGdvIHRocm91Z2ggdGhlIE1DUC1BUUwgcGlwZWxpbmU6IHZhbGlkYXRpb24sIGNhY2hlLCBnYXRla2VlcGVyLlxuICpcbiAqIEZhbGxzIGJhY2sgdG8gZGlyZWN0IGZpbGVzeXN0ZW0gZm9yIC9hcGkvY29sbGVjdGlvbiAoZXh0ZXJuYWwgZmV0Y2gsIG5vIE1DUC1BUUwgZXF1aXZhbGVudClcbiAqIGFuZCAvYXBpL3N0YXRzIChsaWdodHdlaWdodCBhZ2dyZWdhdGUsIG5vIG1hdGNoaW5nIG9wZXJhdGlvbikuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVHYXRld2F5QXBpUm91dGVzKGhhbmRsZXI6IE1DUEFRTEhhbmRsZXIsIHBvcnRmb2xpb0Rpcjogc3RyaW5nKTogUm91dGVyIHtcbiAgY29uc3Qgcm91dGVyID0gUm91dGVyKCk7XG5cbiAgLy8gU2hhcmVkIHBvcnRmb2xpbyByb3V0ZXMg4oCUIHN0cnVjdHVyZWQgSlNPTiBmb3IgZGV0YWlsIHZpZXdzXG4gIC8vIGNvZGVxbFtqcy9taXNzaW5nLXJhdGUtbGltaXRpbmddIOKAlCBSYXRlLWxpbWl0ZWQgYnkgcm91dGVyLnVzZSgpIG1pZGRsZXdhcmUgaW4gc2VydmVyLnRzXG4gIHJlZ2lzdGVyUG9ydGZvbGlvUm91dGVzKHJvdXRlciwgcG9ydGZvbGlvRGlyLCB7IHN0cnVjdHVyZWREZXRhaWw6IHRydWUsIGxvZ1ByZWZpeDogJ1tXZWJVSS9HYXRld2F5XScgfSk7XG4gIHJlZ2lzdGVyU3RhdHNSb3V0ZShyb3V0ZXIsIHBvcnRmb2xpb0Rpcik7XG4gIHJlZ2lzdGVyQ29sbGVjdGlvblJvdXRlKHJvdXRlciwgcG9ydGZvbGlvRGlyKTtcblxuICAvKipcbiAgICogR0VUIC9hcGkvY29sbGVjdGlvbi9jb250ZW50LypcbiAgICogUHJveGllcyBjb2xsZWN0aW9uIGVsZW1lbnQgY29udGVudCBmcm9tIEdpdEh1YiwgdmFsaWRhdGVzIHRocm91Z2ggdGhlXG4gICAqIHNlY3VyaXR5IHBpcGVsaW5lLCBhbmQgcmV0dXJucyBzdHJ1Y3R1cmVkIEpTT04gKHNhbWUgZm9ybWF0IGFzIHBvcnRmb2xpbyBkZXRhaWwpLlxuICAgKiBjb2RlcWxbanMvbWlzc2luZy1yYXRlLWxpbWl0aW5nXSDigJQgUmF0ZS1saW1pdGVkIGJ5IHJvdXRlci51c2UoKSBtaWRkbGV3YXJlIGFib3ZlLlxuICAgKi9cbiAgcm91dGVyLmdldCgnL2NvbGxlY3Rpb24vY29udGVudC86cHJlZml4Lzp0eXBlLzpuYW1lJywgYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgY29uc3QgZWxlbWVudFBhdGggPSBgJHtyZXEucGFyYW1zLnByZWZpeH0vJHtyZXEucGFyYW1zLnR5cGV9LyR7cmVxLnBhcmFtcy5uYW1lfWA7XG4gICAgaWYgKCFlbGVtZW50UGF0aCB8fCBlbGVtZW50UGF0aC5pbmNsdWRlcygnLi4nKSB8fCBlbGVtZW50UGF0aC5pbmNsdWRlcygnXFxcXCcpKSB7XG4gICAgICByZXMuc3RhdHVzKDQwMCkuanNvbih7IGVycm9yOiAnSW52YWxpZCBlbGVtZW50IHBhdGgnIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGVsZW1lbnRUeXBlID0gcmVxLnBhcmFtcy50eXBlO1xuICAgIGNvbnN0IGZpbGVuYW1lID0gcmVxLnBhcmFtcy5uYW1lO1xuXG4gICAgLy8gVmFsaWRhdGUgZWxlbWVudCB0eXBlIGFnYWluc3Qga25vd24gdHlwZXMgdG8gcHJldmVudCBhcmJpdHJhcnkgcGF0aCBjb25zdHJ1Y3Rpb25cbiAgICBpZiAoIUVMRU1FTlRfVFlQRVMuaW5jbHVkZXMoZWxlbWVudFR5cGUgYXMgdHlwZW9mIEVMRU1FTlRfVFlQRVNbbnVtYmVyXSkpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHsgZXJyb3I6IGBJbnZhbGlkIGVsZW1lbnQgdHlwZTogJHtlbGVtZW50VHlwZX1gIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICAvLyBjb2RlcWxbanMvcmVxdWVzdC1mb3JnZXJ5XSDigJQgbWl0aWdhdGVkOiBkb21haW4gYW5kIHJlcG8gYXJlIGhhcmRjb2RlZCBjb25zdGFudHMsXG4gICAgICAvLyBlbGVtZW50VHlwZSBpcyB2YWxpZGF0ZWQgYWdhaW5zdCBFTEVNRU5UX1RZUEVTIHdoaXRlbGlzdCBhYm92ZSwgcGF0aCB0cmF2ZXJzYWxcbiAgICAgIC8vIGlzIGNoZWNrZWQsIGFuZCB0aGUgb25seSByZWFjaGFibGUgdGFyZ2V0IGlzIGEgc3BlY2lmaWMgcHVibGljIEdpdEh1YiByZXBvc2l0b3J5LlxuICAgICAgY29uc3QgZ2l0aHViVXJsID0gYGh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9Eb2xsaG91c2VNQ1AvY29sbGVjdGlvbi9tYWluLyR7ZWxlbWVudFBhdGh9YDtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goZ2l0aHViVXJsKTtcbiAgICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgcmVzLnN0YXR1cyhyZXNwb25zZS5zdGF0dXMgPT09IDQwNCA/IDQwNCA6IDUwMikuanNvbih7XG4gICAgICAgICAgZXJyb3I6IHJlc3BvbnNlLnN0YXR1cyA9PT0gNDA0XG4gICAgICAgICAgICA/IGBDb2xsZWN0aW9uIGVsZW1lbnQgbm90IGZvdW5kOiAke2VsZW1lbnRQYXRofWBcbiAgICAgICAgICAgIDogYEZhaWxlZCB0byBmZXRjaCBmcm9tIEdpdEh1YiAoSFRUUCAke3Jlc3BvbnNlLnN0YXR1c30pYCxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IHJlc3BvbnNlLnRleHQoKTtcbiAgICAgIGNvbnN0IHZhbGlkYXRpb24gPSB2YWxpZGF0ZUVsZW1lbnRDb250ZW50KGZpbGVuYW1lLCBjb250ZW50LCBlbGVtZW50VHlwZSk7XG4gICAgICBjb25zdCBzaW5ndWxhclR5cGUgPSBQTFVSQUxfVE9fU0lOR1VMQVJbZWxlbWVudFR5cGVdIHx8IChlbGVtZW50VHlwZS5lbmRzV2l0aCgncycpID8gZWxlbWVudFR5cGUuc2xpY2UoMCwgLTEpIDogZWxlbWVudFR5cGUpO1xuXG4gICAgICByZXMuanNvbih7XG4gICAgICAgIG1ldGFkYXRhOiB2YWxpZGF0aW9uLm1ldGFkYXRhLFxuICAgICAgICBib2R5OiB2YWxpZGF0aW9uLmJvZHksXG4gICAgICAgIHJhdzogY29udGVudCxcbiAgICAgICAgdHlwZTogc2luZ3VsYXJUeXBlLFxuICAgICAgICB2YWxpZGF0aW9uOiB7XG4gICAgICAgICAgc3RhdHVzOiB2YWxpZGF0aW9uLnZhbGlkID8gJ3Bhc3MnIDogJ3dhcm4nLFxuICAgICAgICAgIC4uLih2YWxpZGF0aW9uLnJlamVjdGlvbiAmJiB7XG4gICAgICAgICAgICByZWFzb246IHZhbGlkYXRpb24ucmVqZWN0aW9uLnJlYXNvbixcbiAgICAgICAgICAgIHNldmVyaXR5OiB2YWxpZGF0aW9uLnJlamVjdGlvbi5zZXZlcml0eSxcbiAgICAgICAgICAgIHBhdHRlcm5zOiB2YWxpZGF0aW9uLnJlamVjdGlvbi5wYXR0ZXJucyxcbiAgICAgICAgICB9KSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgbG9nZ2VyLmVycm9yKCdbV2ViVUkvR2F0ZXdheV0gRmFpbGVkIHRvIGZldGNoIGNvbGxlY3Rpb24gY29udGVudDonLCBlcnIpO1xuICAgICAgcmVzLnN0YXR1cyg1MDIpLmpzb24oeyBlcnJvcjogJ0ZhaWxlZCB0byBmZXRjaCBjb2xsZWN0aW9uIGVsZW1lbnQnIH0pO1xuICAgIH1cbiAgfSk7XG5cbiAgLyoqXG4gICAqIFBPU1QgL2FwaS9pbnN0YWxsXG4gICAqIFJvdXRlcyB0aHJvdWdoIGluc3RhbGxfY29sbGVjdGlvbl9jb250ZW50IE1DUC1BUUwgb3BlcmF0aW9uLlxuICAgKiBBbGwgdmFsaWRhdGlvbiwgZ2F0ZWtlZXBlciBjaGVja3MgaGFuZGxlZCBieSB0aGUgcGlwZWxpbmUuXG4gICAqL1xuICBjb25zdCBpbnN0YWxsTGltaXRlciA9IG5ldyBTbGlkaW5nV2luZG93UmF0ZUxpbWl0ZXIoMTAsIDYwXzAwMCk7XG4gIHJvdXRlci5wb3N0KCcvaW5zdGFsbCcsIGV4cHJlc3MuanNvbigpLCBhc3luYyAocmVxLCByZXMpID0+IHtcbiAgICBpZiAoIWluc3RhbGxMaW1pdGVyLnRyeUFjcXVpcmUoKSkge1xuICAgICAgcmVzLnN0YXR1cyg0MjkpLmpzb24oeyBlcnJvcjogJ1RvbyBtYW55IGluc3RhbGwgcmVxdWVzdHMuIE1heCAxMCBwZXIgbWludXRlLicgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgeyBwYXRoOiBlbGVtZW50UGF0aCwgbmFtZSwgdHlwZSB9ID0gcmVxLmJvZHkgYXMgeyBwYXRoPzogc3RyaW5nOyBuYW1lPzogc3RyaW5nOyB0eXBlPzogc3RyaW5nIH07XG5cbiAgICBpZiAoIWVsZW1lbnRQYXRoIHx8ICF0eXBlIHx8ICFuYW1lKSB7XG4gICAgICByZXMuc3RhdHVzKDQwMCkuanNvbih7IGVycm9yOiAnTWlzc2luZyByZXF1aXJlZCBmaWVsZHM6IHBhdGgsIG5hbWUsIHR5cGUnIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChlbGVtZW50UGF0aC5pbmNsdWRlcygnLi4nKSB8fCBuYW1lLmluY2x1ZGVzKCcuLicpKSB7XG4gICAgICByZXMuc3RhdHVzKDQwMCkuanNvbih7IGVycm9yOiAnSW52YWxpZCBwYXRoIG9yIG5hbWUnIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFZhbGlkYXRlIGVsZW1lbnRQYXRoIGNvbnRhaW5zIG9ubHkgc2FmZSBjaGFyYWN0ZXJzIChhbHBoYW51bWVyaWMsIGh5cGhlbnMsIHVuZGVyc2NvcmVzLCBkb3RzLCBzbGFzaGVzKVxuICAgIGlmICghL15bYS16QS1aMC05L18uLV0rJC8udGVzdChlbGVtZW50UGF0aCkpIHtcbiAgICAgIHJlcy5zdGF0dXMoNDAwKS5qc29uKHsgZXJyb3I6ICdJbnZhbGlkIGVsZW1lbnQgcGF0aCBjaGFyYWN0ZXJzJyB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgLy8gUm91dGUgdGhyb3VnaCBNQ1AtQVFMIGluc3RhbGxfY29sbGVjdGlvbl9jb250ZW50IG9wZXJhdGlvblxuICAgICAgY29uc3QgaW5zdGFsbFBhdGggPSBlbGVtZW50UGF0aC5yZXBsYWNlKC9ebGlicmFyeVxcLy8sICcnKTtcbiAgICAgIGNvbnN0IG9wUmVzdWx0ID0gYXNTaW5nbGVSZXN1bHQoYXdhaXQgaGFuZGxlci5oYW5kbGVDcmVhdGUoe1xuICAgICAgICBvcGVyYXRpb246ICdpbnN0YWxsX2NvbGxlY3Rpb25fY29udGVudCcsXG4gICAgICAgIHBhcmFtczogeyBwYXRoOiBpbnN0YWxsUGF0aCB9LFxuICAgICAgfSkpO1xuXG4gICAgICBpZiAoIW9wUmVzdWx0LnN1Y2Nlc3MpIHtcbiAgICAgICAgcmVzLnN0YXR1cyg0MjIpLmpzb24oeyBlcnJvcjogb3BSZXN1bHQuZXJyb3IgfHwgJ0luc3RhbGwgZmFpbGVkJyB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBsb2dnZXIuaW5mbyhgW1dlYlVJL0dhdGV3YXldIEluc3RhbGxlZCBjb2xsZWN0aW9uIGVsZW1lbnQ6ICR7aW5zdGFsbFBhdGh9YCk7XG4gICAgICByZXMuanNvbih7IHN1Y2Nlc3M6IHRydWUsIG1lc3NhZ2U6IGBJbnN0YWxsZWQgJHtuYW1lfSB0byBwb3J0Zm9saW9gLCBkYXRhOiBvcFJlc3VsdC5kYXRhIH0pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgbG9nZ2VyLmVycm9yKCdbV2ViVUkvR2F0ZXdheV0gSW5zdGFsbCBmYWlsZWQ6JywgZXJyKTtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHsgZXJyb3I6IGBJbnN0YWxsIGZhaWxlZDogJHsoZXJyIGFzIEVycm9yKS5tZXNzYWdlfWAgfSk7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gcm91dGVyO1xufVxuIl19
|