@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.
Files changed (238) hide show
  1. package/CHANGELOG.md +52 -61
  2. package/README.github.md +2 -2
  3. package/README.md +2 -2
  4. package/README.md.backup +284 -224
  5. package/README.npm.md +2 -2
  6. package/dist/cache/LRUCache.d.ts +3 -0
  7. package/dist/cache/LRUCache.d.ts.map +1 -1
  8. package/dist/cache/LRUCache.js +36 -26
  9. package/dist/config/env.d.ts +14 -4
  10. package/dist/config/env.d.ts.map +1 -1
  11. package/dist/config/env.js +20 -6
  12. package/dist/di/Container.d.ts +21 -0
  13. package/dist/di/Container.d.ts.map +1 -1
  14. package/dist/di/Container.js +250 -53
  15. package/dist/elements/BaseElement.d.ts.map +1 -1
  16. package/dist/elements/BaseElement.js +5 -10
  17. package/dist/elements/base/BaseElementManager.d.ts +22 -0
  18. package/dist/elements/base/BaseElementManager.d.ts.map +1 -1
  19. package/dist/elements/base/BaseElementManager.js +47 -7
  20. package/dist/elements/memories/Memory.d.ts +1 -0
  21. package/dist/elements/memories/Memory.d.ts.map +1 -1
  22. package/dist/elements/memories/Memory.js +12 -8
  23. package/dist/elements/memories/MemoryManager.d.ts.map +1 -1
  24. package/dist/elements/memories/MemoryManager.js +23 -42
  25. package/dist/elements/memories/MemorySearchIndex.js +2 -2
  26. package/dist/generated/version.d.ts +2 -2
  27. package/dist/generated/version.d.ts.map +1 -1
  28. package/dist/generated/version.js +3 -3
  29. package/dist/handlers/EnhancedIndexHandler.js +6 -6
  30. package/dist/handlers/element-crud/listElements.d.ts +2 -0
  31. package/dist/handlers/element-crud/listElements.d.ts.map +1 -1
  32. package/dist/handlers/element-crud/listElements.js +3 -1
  33. package/dist/handlers/mcp-aql/Gatekeeper.d.ts.map +1 -1
  34. package/dist/handlers/mcp-aql/Gatekeeper.js +23 -17
  35. package/dist/handlers/mcp-aql/MCPAQLHandler.d.ts +14 -0
  36. package/dist/handlers/mcp-aql/MCPAQLHandler.d.ts.map +1 -1
  37. package/dist/handlers/mcp-aql/MCPAQLHandler.js +110 -14
  38. package/dist/handlers/mcp-aql/OperationRouter.d.ts.map +1 -1
  39. package/dist/handlers/mcp-aql/OperationRouter.js +13 -1
  40. package/dist/handlers/mcp-aql/OperationSchema.d.ts +7 -0
  41. package/dist/handlers/mcp-aql/OperationSchema.d.ts.map +1 -1
  42. package/dist/handlers/mcp-aql/OperationSchema.js +52 -1
  43. package/dist/handlers/mcp-aql/evaluatePermission.d.ts +53 -0
  44. package/dist/handlers/mcp-aql/evaluatePermission.d.ts.map +1 -0
  45. package/dist/handlers/mcp-aql/evaluatePermission.js +132 -0
  46. package/dist/handlers/mcp-aql/policies/ToolClassification.d.ts.map +1 -1
  47. package/dist/handlers/mcp-aql/policies/ToolClassification.js +2 -1
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +3 -3
  50. package/dist/logging/LogHooks.js +11 -11
  51. package/dist/logging/LogManager.d.ts +0 -2
  52. package/dist/logging/LogManager.d.ts.map +1 -1
  53. package/dist/logging/LogManager.js +1 -3
  54. package/dist/logging/sinks/MemoryLogSink.d.ts +2 -0
  55. package/dist/logging/sinks/MemoryLogSink.d.ts.map +1 -1
  56. package/dist/logging/sinks/MemoryLogSink.js +12 -3
  57. package/dist/logging/types.d.ts +0 -2
  58. package/dist/logging/types.d.ts.map +1 -1
  59. package/dist/logging/types.js +1 -1
  60. package/dist/metrics/GatekeeperMetricsTracker.d.ts +32 -0
  61. package/dist/metrics/GatekeeperMetricsTracker.d.ts.map +1 -0
  62. package/dist/metrics/GatekeeperMetricsTracker.js +42 -0
  63. package/dist/metrics/MetricsManager.d.ts +47 -0
  64. package/dist/metrics/MetricsManager.d.ts.map +1 -0
  65. package/dist/metrics/MetricsManager.js +232 -0
  66. package/dist/metrics/OperationMetricsTracker.d.ts +32 -0
  67. package/dist/metrics/OperationMetricsTracker.d.ts.map +1 -0
  68. package/dist/metrics/OperationMetricsTracker.js +53 -0
  69. package/dist/metrics/collectors/DefaultElementProviderCollector.d.ts +27 -0
  70. package/dist/metrics/collectors/DefaultElementProviderCollector.d.ts.map +1 -0
  71. package/dist/metrics/collectors/DefaultElementProviderCollector.js +69 -0
  72. package/dist/metrics/collectors/FileLockManagerCollector.d.ts +16 -0
  73. package/dist/metrics/collectors/FileLockManagerCollector.d.ts.map +1 -0
  74. package/dist/metrics/collectors/FileLockManagerCollector.js +51 -0
  75. package/dist/metrics/collectors/GatekeeperMetricsCollector.d.ts +16 -0
  76. package/dist/metrics/collectors/GatekeeperMetricsCollector.d.ts.map +1 -0
  77. package/dist/metrics/collectors/GatekeeperMetricsCollector.js +76 -0
  78. package/dist/metrics/collectors/LRUCacheCollector.d.ts +18 -0
  79. package/dist/metrics/collectors/LRUCacheCollector.d.ts.map +1 -0
  80. package/dist/metrics/collectors/LRUCacheCollector.js +95 -0
  81. package/dist/metrics/collectors/OperationMetricsCollector.d.ts +16 -0
  82. package/dist/metrics/collectors/OperationMetricsCollector.d.ts.map +1 -0
  83. package/dist/metrics/collectors/OperationMetricsCollector.js +80 -0
  84. package/dist/metrics/collectors/OperationalTelemetryCollector.d.ts +17 -0
  85. package/dist/metrics/collectors/OperationalTelemetryCollector.d.ts.map +1 -0
  86. package/dist/metrics/collectors/OperationalTelemetryCollector.js +26 -0
  87. package/dist/metrics/collectors/PerformanceMonitorCollector.d.ts +14 -0
  88. package/dist/metrics/collectors/PerformanceMonitorCollector.d.ts.map +1 -0
  89. package/dist/metrics/collectors/PerformanceMonitorCollector.js +141 -0
  90. package/dist/metrics/collectors/SecurityMonitorCollector.d.ts +21 -0
  91. package/dist/metrics/collectors/SecurityMonitorCollector.d.ts.map +1 -0
  92. package/dist/metrics/collectors/SecurityMonitorCollector.js +56 -0
  93. package/dist/metrics/collectors/SecurityTelemetryCollector.d.ts +15 -0
  94. package/dist/metrics/collectors/SecurityTelemetryCollector.d.ts.map +1 -0
  95. package/dist/metrics/collectors/SecurityTelemetryCollector.js +112 -0
  96. package/dist/metrics/collectors/TriggerMetricsTrackerCollector.d.ts +16 -0
  97. package/dist/metrics/collectors/TriggerMetricsTrackerCollector.d.ts.map +1 -0
  98. package/dist/metrics/collectors/TriggerMetricsTrackerCollector.js +26 -0
  99. package/dist/metrics/collectors/index.d.ts +11 -0
  100. package/dist/metrics/collectors/index.d.ts.map +1 -0
  101. package/dist/metrics/collectors/index.js +11 -0
  102. package/dist/metrics/sinks/MemoryMetricsSink.d.ts +22 -0
  103. package/dist/metrics/sinks/MemoryMetricsSink.d.ts.map +1 -0
  104. package/dist/metrics/sinks/MemoryMetricsSink.js +121 -0
  105. package/dist/metrics/types.d.ts +98 -0
  106. package/dist/metrics/types.d.ts.map +1 -0
  107. package/dist/metrics/types.js +24 -0
  108. package/dist/portfolio/DefaultElementProvider.d.ts.map +1 -1
  109. package/dist/portfolio/DefaultElementProvider.js +1 -7
  110. package/dist/portfolio/EnhancedIndexManager.d.ts.map +1 -1
  111. package/dist/portfolio/EnhancedIndexManager.js +18 -18
  112. package/dist/portfolio/NLPScoringManager.d.ts.map +1 -1
  113. package/dist/portfolio/NLPScoringManager.js +5 -9
  114. package/dist/portfolio/PortfolioIndexManager.js +2 -2
  115. package/dist/portfolio/RelationshipManager.js +2 -2
  116. package/dist/portfolio/VerbTriggerManager.d.ts.map +1 -1
  117. package/dist/portfolio/VerbTriggerManager.js +5 -19
  118. package/dist/portfolio/config/IndexConfig.d.ts.map +1 -1
  119. package/dist/portfolio/config/IndexConfig.js +1 -12
  120. package/dist/portfolio/enhanced-index/ElementDefinitionBuilder.d.ts.map +1 -1
  121. package/dist/portfolio/enhanced-index/ElementDefinitionBuilder.js +3 -15
  122. package/dist/portfolio/enhanced-index/SemanticRelationshipService.d.ts.map +1 -1
  123. package/dist/portfolio/enhanced-index/SemanticRelationshipService.js +2 -16
  124. package/dist/portfolio/types/RelationshipTypes.d.ts.map +1 -1
  125. package/dist/portfolio/types/RelationshipTypes.js +3 -17
  126. package/dist/security/audit/config/suppressions.d.ts.map +1 -1
  127. package/dist/security/audit/config/suppressions.js +36 -8
  128. package/dist/security/constants.d.ts.map +1 -1
  129. package/dist/security/constants.js +10 -6
  130. package/dist/security/fileLockManager.d.ts.map +1 -1
  131. package/dist/security/fileLockManager.js +8 -6
  132. package/dist/security/secureYamlParser.d.ts.map +1 -1
  133. package/dist/security/secureYamlParser.js +1 -13
  134. package/dist/security/securityMonitor.d.ts +2 -1
  135. package/dist/security/securityMonitor.d.ts.map +1 -1
  136. package/dist/security/securityMonitor.js +14 -3
  137. package/dist/security/telemetry/SecurityTelemetry.d.ts +16 -0
  138. package/dist/security/telemetry/SecurityTelemetry.d.ts.map +1 -1
  139. package/dist/security/telemetry/SecurityTelemetry.js +30 -2
  140. package/dist/security/tokenManager.d.ts +3 -0
  141. package/dist/security/tokenManager.d.ts.map +1 -1
  142. package/dist/security/tokenManager.js +13 -5
  143. package/dist/security/validation/BackgroundValidator.d.ts.map +1 -1
  144. package/dist/security/validation/BackgroundValidator.js +7 -7
  145. package/dist/server/startup.d.ts.map +1 -1
  146. package/dist/server/startup.js +8 -24
  147. package/dist/server/tools/MCPAQLTools.js +4 -1
  148. package/dist/services/ActivationStore.d.ts.map +1 -1
  149. package/dist/services/ActivationStore.js +9 -3
  150. package/dist/services/FileWatchService.d.ts +1 -0
  151. package/dist/services/FileWatchService.d.ts.map +1 -1
  152. package/dist/services/FileWatchService.js +83 -48
  153. package/dist/services/MetadataService.d.ts.map +1 -1
  154. package/dist/services/MetadataService.js +7 -2
  155. package/dist/services/query/ElementQueryService.d.ts.map +1 -1
  156. package/dist/services/query/ElementQueryService.js +1 -41
  157. package/dist/services/query/PaginationService.d.ts.map +1 -1
  158. package/dist/services/query/PaginationService.js +1 -14
  159. package/dist/services/query/SortService.d.ts.map +1 -1
  160. package/dist/services/query/SortService.js +1 -6
  161. package/dist/services/validation/ValidationService.d.ts.map +1 -1
  162. package/dist/services/validation/ValidationService.js +3 -8
  163. package/dist/storage/ElementStorageLayer.d.ts.map +1 -1
  164. package/dist/storage/ElementStorageLayer.js +5 -2
  165. package/dist/storage/MemoryStorageLayer.d.ts.map +1 -1
  166. package/dist/storage/MemoryStorageLayer.js +5 -2
  167. package/dist/telemetry/OperationalTelemetry.js +2 -2
  168. package/dist/utils/EventDeduplicator.d.ts +44 -0
  169. package/dist/utils/EventDeduplicator.d.ts.map +1 -0
  170. package/dist/utils/EventDeduplicator.js +93 -0
  171. package/dist/utils/FileLock.d.ts.map +1 -1
  172. package/dist/utils/FileLock.js +1 -9
  173. package/dist/utils/PerformanceMonitor.d.ts.map +1 -1
  174. package/dist/utils/PerformanceMonitor.js +5 -5
  175. package/dist/utils/SlidingWindowRateLimiter.d.ts +13 -0
  176. package/dist/utils/SlidingWindowRateLimiter.d.ts.map +1 -0
  177. package/dist/utils/SlidingWindowRateLimiter.js +23 -0
  178. package/dist/web/console/IngestRoutes.d.ts +84 -0
  179. package/dist/web/console/IngestRoutes.d.ts.map +1 -0
  180. package/dist/web/console/IngestRoutes.js +252 -0
  181. package/dist/web/console/LeaderElection.d.ts +89 -0
  182. package/dist/web/console/LeaderElection.d.ts.map +1 -0
  183. package/dist/web/console/LeaderElection.js +205 -0
  184. package/dist/web/console/LeaderForwardingSink.d.ts +61 -0
  185. package/dist/web/console/LeaderForwardingSink.d.ts.map +1 -0
  186. package/dist/web/console/LeaderForwardingSink.js +197 -0
  187. package/dist/web/console/SessionNames.d.ts +46 -0
  188. package/dist/web/console/SessionNames.d.ts.map +1 -0
  189. package/dist/web/console/SessionNames.js +257 -0
  190. package/dist/web/console/UnifiedConsole.d.ts +64 -0
  191. package/dist/web/console/UnifiedConsole.d.ts.map +1 -0
  192. package/dist/web/console/UnifiedConsole.js +119 -0
  193. package/dist/web/contentPipeline.d.ts +58 -0
  194. package/dist/web/contentPipeline.d.ts.map +1 -0
  195. package/dist/web/contentPipeline.js +112 -0
  196. package/dist/web/portDiscovery.d.ts +58 -0
  197. package/dist/web/portDiscovery.d.ts.map +1 -0
  198. package/dist/web/portDiscovery.js +143 -0
  199. package/dist/web/public/app.js +148 -60
  200. package/dist/web/public/logs.js +638 -0
  201. package/dist/web/public/metrics.js +682 -0
  202. package/dist/web/public/permissions.js +394 -0
  203. package/dist/web/public/sessions.js +369 -0
  204. package/dist/web/routes/healthRoutes.d.ts +16 -0
  205. package/dist/web/routes/healthRoutes.d.ts.map +1 -0
  206. package/dist/web/routes/healthRoutes.js +29 -0
  207. package/dist/web/routes/logRoutes.d.ts +18 -0
  208. package/dist/web/routes/logRoutes.d.ts.map +1 -0
  209. package/dist/web/routes/logRoutes.js +126 -0
  210. package/dist/web/routes/metricsRoutes.d.ts +17 -0
  211. package/dist/web/routes/metricsRoutes.d.ts.map +1 -0
  212. package/dist/web/routes/metricsRoutes.js +90 -0
  213. package/dist/web/routes/permissionRoutes.d.ts +16 -0
  214. package/dist/web/routes/permissionRoutes.d.ts.map +1 -0
  215. package/dist/web/routes/permissionRoutes.js +133 -0
  216. package/dist/web/routes.d.ts.map +1 -1
  217. package/dist/web/routes.js +309 -339
  218. package/dist/web/server.d.ts +21 -1
  219. package/dist/web/server.d.ts.map +1 -1
  220. package/dist/web/server.js +42 -4
  221. package/dist/web/sinks/WebSSELogSink.d.ts +15 -0
  222. package/dist/web/sinks/WebSSELogSink.d.ts.map +1 -0
  223. package/dist/web/sinks/WebSSELogSink.js +22 -0
  224. package/dist/web/sinks/WebSSEMetricsSink.d.ts +16 -0
  225. package/dist/web/sinks/WebSSEMetricsSink.d.ts.map +1 -0
  226. package/dist/web/sinks/WebSSEMetricsSink.js +23 -0
  227. package/package.json +2 -2
  228. package/server.json +2 -2
  229. package/dist/constants/version.d.ts +0 -3
  230. package/dist/constants/version.d.ts.map +0 -1
  231. package/dist/constants/version.js +0 -4
  232. package/dist/logging/sinks/SSELogSink.d.ts +0 -35
  233. package/dist/logging/sinks/SSELogSink.d.ts.map +0 -1
  234. package/dist/logging/sinks/SSELogSink.js +0 -181
  235. package/dist/logging/viewer/viewerHtml.d.ts +0 -8
  236. package/dist/logging/viewer/viewerHtml.d.ts.map +0 -1
  237. package/dist/logging/viewer/viewerHtml.js +0 -204
  238. package/dist/web/public/public/app.js +0 -1878
@@ -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
- * Simple sliding-window rate limiter.
30
- * Tracks timestamps of recent requests and evicts entries older than the window.
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
- class SlidingWindowRateLimiter {
33
- maxRequests;
34
- windowMs;
35
- timestamps = [];
36
- constructor(maxRequests, windowMs) {
37
- this.maxRequests = maxRequests;
38
- this.windowMs = windowMs;
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
- /** Returns true if the request is allowed, false if rate-limited. */
41
- tryAcquire() {
42
- const now = Date.now();
43
- // Evict entries outside the window
44
- this.timestamps = this.timestamps.filter(t => now - t < this.windowMs);
45
- if (this.timestamps.length >= this.maxRequests) {
46
- return false;
47
- }
48
- this.timestamps.push(now);
49
- return true;
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
- export function createApiRoutes(portfolioDir) {
90
- const router = Router();
91
- /**
92
- * GET /api/elements
93
- * Returns all elements across all types with metadata.
94
- * Supports optional pagination: ?page=1&pageSize=50
95
- * Without pagination params, returns all elements (backward compatible).
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 files = await readdir(typeDir);
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('[WebUI] Failed to list elements:', err);
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
- const typeDir = join(portfolioDir, type);
193
- const files = await readdir(typeDir);
194
- const elements = [];
195
- for (const file of files) {
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
- * GET /api/elements/:type/:name
237
- * Returns the raw file content as plain text.
238
- * The client-side app handles YAML/markdown parsing and rendering.
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
- // Prevent path traversal
247
- if (name.includes('..') || name.includes('/') || name.includes('\\')) {
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 typeDir = join(portfolioDir, type);
253
- const files = await readdir(typeDir);
254
- // Find the file by name (with or without extension)
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
- // Reject files larger than 1 MB
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
- // Return raw text — client-side handles parsing/rendering
278
- res.setHeader('Content-Type', 'text/plain; charset=utf-8');
279
- res.send(content);
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
- * GET /api/stats
287
- * Returns portfolio statistics
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.startsWith('.') &&
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
- * GET /api/collection
316
- * Proxies the DollhouseMCP community collection index.
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/elements
498
- * Routes through list_elements for each type, aggregates results.
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('/elements', async (req, res) => {
501
- try {
502
- const pageParam = req.query.page;
503
- const pageSizeParam = req.query.pageSize;
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
- try {
555
- const opResult = asSingleResult(await handler.handleRead({
556
- operation: 'list_elements',
557
- params: { element_type: toSingularType(type), page: 1, pageSize: 1000 },
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
- const opResult = asSingleResult(await handler.handleRead({
588
- operation: 'get_element',
589
- params: { element_name: name, element_type: toSingularType(type) },
590
- }));
591
- if (!opResult.success) {
592
- const errMsg = opResult.error || '';
593
- const status = errMsg.toLowerCase().includes('not found') ? 404 : 500;
594
- res.status(status).json({ error: errMsg || `Failed to get element: ${type}/${name}` });
595
- return;
596
- }
597
- // get_element returns structured data — the web UI expects raw file content
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 { /* GitHub unreachable — fall back to local */ }
662
- const localPaths = [
663
- join(portfolioDir, '..', '..', '..', 'collection', 'public', 'collection-index.json'),
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