@dollhousemcp/mcp-server 1.5.2 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -0
- package/README.md +494 -111
- package/data/agents/code-reviewer.md +8 -1
- package/data/agents/research-assistant.md +8 -1
- package/data/agents/task-manager.md +8 -1
- package/data/ensembles/business-advisor.md +8 -1
- package/data/ensembles/creative-studio.md +8 -1
- package/data/ensembles/development-team.md +8 -1
- package/data/ensembles/security-analysis-team.md +8 -1
- package/data/memories/conversation-history.md +8 -1
- package/data/memories/learning-progress.md +8 -1
- package/data/memories/project-context.md +8 -1
- package/data/personas/business-consultant.md +8 -1
- package/data/personas/creative-writer.md +8 -1
- package/data/personas/debug-detective.md +8 -1
- package/data/personas/eli5-explainer.md +8 -1
- package/data/personas/security-analyst.md +8 -1
- package/data/personas/technical-analyst.md +8 -1
- package/data/skills/code-review.md +8 -1
- package/data/skills/creative-writing.md +8 -1
- package/data/skills/data-analysis.md +8 -1
- package/data/skills/penetration-testing.md +8 -1
- package/data/skills/research.md +8 -1
- package/data/skills/threat-modeling.md +8 -1
- package/data/skills/translation.md +8 -1
- package/data/templates/code-documentation.md +8 -1
- package/data/templates/email-professional.md +8 -1
- package/data/templates/meeting-notes.md +8 -1
- package/data/templates/penetration-test-report.md +8 -1
- package/data/templates/project-brief.md +8 -1
- package/data/templates/report-executive.md +8 -1
- package/data/templates/security-vulnerability-report.md +8 -1
- package/data/templates/threat-assessment-report.md +8 -1
- package/dist/auth/GitHubAuthManager.d.ts +6 -1
- package/dist/auth/GitHubAuthManager.d.ts.map +1 -1
- package/dist/auth/GitHubAuthManager.js +45 -18
- package/dist/benchmarks/IndexPerformanceBenchmark.d.ts +98 -0
- package/dist/benchmarks/IndexPerformanceBenchmark.d.ts.map +1 -0
- package/dist/benchmarks/IndexPerformanceBenchmark.js +531 -0
- package/dist/cache/CollectionCache.d.ts.map +1 -1
- package/dist/cache/CollectionCache.js +13 -3
- package/dist/cache/CollectionIndexCache.d.ts +77 -0
- package/dist/cache/CollectionIndexCache.d.ts.map +1 -0
- package/dist/cache/CollectionIndexCache.js +349 -0
- package/dist/cache/LRUCache.d.ts +93 -0
- package/dist/cache/LRUCache.d.ts.map +1 -0
- package/dist/cache/LRUCache.js +299 -0
- package/dist/cache/index.d.ts +1 -0
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +2 -1
- package/dist/collection/CollectionBrowser.d.ts +21 -1
- package/dist/collection/CollectionBrowser.d.ts.map +1 -1
- package/dist/collection/CollectionBrowser.js +130 -10
- package/dist/collection/CollectionIndexManager.d.ts +151 -0
- package/dist/collection/CollectionIndexManager.d.ts.map +1 -0
- package/dist/collection/CollectionIndexManager.js +499 -0
- package/dist/collection/CollectionSearch.d.ts +55 -0
- package/dist/collection/CollectionSearch.d.ts.map +1 -1
- package/dist/collection/CollectionSearch.js +338 -13
- package/dist/collection/CollectionSeeder.d.ts.map +1 -1
- package/dist/collection/CollectionSeeder.js +38 -1
- package/dist/collection/ElementInstaller.d.ts +31 -0
- package/dist/collection/ElementInstaller.d.ts.map +1 -1
- package/dist/collection/ElementInstaller.js +77 -15
- package/dist/collection/PersonaSubmitter.d.ts +1 -1
- package/dist/collection/PersonaSubmitter.d.ts.map +1 -1
- package/dist/collection/PersonaSubmitter.js +2 -2
- package/dist/collection/index.d.ts +1 -0
- package/dist/collection/index.d.ts.map +1 -1
- package/dist/collection/index.js +2 -1
- package/dist/config/ConfigManager.d.ts +78 -0
- package/dist/config/ConfigManager.d.ts.map +1 -0
- package/dist/config/ConfigManager.js +216 -0
- package/dist/config/element-types.d.ts +135 -0
- package/dist/config/element-types.d.ts.map +1 -0
- package/dist/config/element-types.js +108 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +3 -1
- package/dist/config/portfolio-constants.d.ts +83 -0
- package/dist/config/portfolio-constants.d.ts.map +1 -0
- package/dist/config/portfolio-constants.js +99 -0
- package/dist/elements/BaseElement.d.ts +14 -2
- package/dist/elements/BaseElement.d.ts.map +1 -1
- package/dist/elements/BaseElement.js +88 -6
- package/dist/elements/agents/Agent.d.ts +10 -1
- package/dist/elements/agents/Agent.d.ts.map +1 -1
- package/dist/elements/agents/Agent.js +66 -19
- package/dist/elements/agents/AgentManager.d.ts +2 -0
- package/dist/elements/agents/AgentManager.d.ts.map +1 -1
- package/dist/elements/agents/AgentManager.js +12 -10
- package/dist/elements/skills/Skill.d.ts +10 -1
- package/dist/elements/skills/Skill.d.ts.map +1 -1
- package/dist/elements/skills/Skill.js +40 -3
- package/dist/elements/skills/SkillManager.d.ts +1 -0
- package/dist/elements/skills/SkillManager.d.ts.map +1 -1
- package/dist/elements/skills/SkillManager.js +10 -4
- package/dist/elements/templates/Template.d.ts +10 -1
- package/dist/elements/templates/Template.d.ts.map +1 -1
- package/dist/elements/templates/Template.js +35 -18
- package/dist/elements/templates/TemplateManager.d.ts +1 -1
- package/dist/elements/templates/TemplateManager.d.ts.map +1 -1
- package/dist/elements/templates/TemplateManager.js +6 -5
- package/dist/generated/version.d.ts +2 -2
- package/dist/generated/version.js +3 -3
- package/dist/index.barrel.d.ts +1 -2
- package/dist/index.barrel.d.ts.map +1 -1
- package/dist/index.barrel.js +2 -4
- package/dist/index.d.ts +143 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1883 -310
- package/dist/persona/PersonaElement.d.ts +10 -0
- package/dist/persona/PersonaElement.d.ts.map +1 -1
- package/dist/persona/PersonaElement.js +55 -32
- package/dist/persona/PersonaElementManager.d.ts.map +1 -1
- package/dist/persona/PersonaElementManager.js +13 -11
- package/dist/persona/PersonaLoader.d.ts.map +1 -1
- package/dist/persona/PersonaLoader.js +8 -2
- package/dist/persona/export-import/PersonaImporter.d.ts.map +1 -1
- package/dist/persona/export-import/PersonaImporter.js +24 -5
- package/dist/persona/export-import/PersonaSharer.d.ts +21 -0
- package/dist/persona/export-import/PersonaSharer.d.ts.map +1 -1
- package/dist/persona/export-import/PersonaSharer.js +198 -22
- package/dist/portfolio/DefaultElementProvider.d.ts +90 -0
- package/dist/portfolio/DefaultElementProvider.d.ts.map +1 -1
- package/dist/portfolio/DefaultElementProvider.js +499 -7
- package/dist/portfolio/GitHubPortfolioIndexer.d.ts +129 -0
- package/dist/portfolio/GitHubPortfolioIndexer.d.ts.map +1 -0
- package/dist/portfolio/GitHubPortfolioIndexer.js +475 -0
- package/dist/portfolio/MigrationManager.d.ts.map +1 -1
- package/dist/portfolio/MigrationManager.js +136 -3
- package/dist/portfolio/PortfolioIndexManager.d.ts +130 -0
- package/dist/portfolio/PortfolioIndexManager.d.ts.map +1 -0
- package/dist/portfolio/PortfolioIndexManager.js +478 -0
- package/dist/portfolio/PortfolioManager.d.ts +5 -0
- package/dist/portfolio/PortfolioManager.d.ts.map +1 -1
- package/dist/portfolio/PortfolioManager.js +61 -20
- package/dist/portfolio/PortfolioRepoManager.d.ts +75 -0
- package/dist/portfolio/PortfolioRepoManager.d.ts.map +1 -0
- package/dist/portfolio/PortfolioRepoManager.js +337 -0
- package/dist/portfolio/UnifiedIndexManager.d.ts +388 -0
- package/dist/portfolio/UnifiedIndexManager.d.ts.map +1 -0
- package/dist/portfolio/UnifiedIndexManager.js +1434 -0
- package/dist/portfolio/index.d.ts +15 -0
- package/dist/portfolio/index.d.ts.map +1 -0
- package/dist/portfolio/index.js +15 -0
- package/dist/portfolio/types.d.ts +7 -0
- package/dist/portfolio/types.d.ts.map +1 -1
- package/dist/portfolio/types.js +6 -1
- package/dist/security/InputValidator.d.ts.map +1 -1
- package/dist/security/InputValidator.js +50 -48
- package/dist/security/audit/SecurityAuditor.d.ts.map +1 -1
- package/dist/security/audit/SecurityAuditor.js +17 -9
- package/dist/security/audit/config/suppressions.d.ts.map +1 -1
- package/dist/security/audit/config/suppressions.js +19 -3
- package/dist/security/contentValidator.d.ts +2 -0
- package/dist/security/contentValidator.d.ts.map +1 -1
- package/dist/security/contentValidator.js +115 -4
- package/dist/security/secureYamlParser.d.ts +1 -0
- package/dist/security/secureYamlParser.d.ts.map +1 -1
- package/dist/security/secureYamlParser.js +29 -7
- package/dist/security/securityMonitor.d.ts +1 -1
- package/dist/security/securityMonitor.d.ts.map +1 -1
- package/dist/security/securityMonitor.js +1 -1
- package/dist/security/tokenManager.d.ts +1 -1
- package/dist/security/tokenManager.d.ts.map +1 -1
- package/dist/security/tokenManager.js +30 -10
- package/dist/server/ServerSetup.d.ts +22 -2
- package/dist/server/ServerSetup.d.ts.map +1 -1
- package/dist/server/ServerSetup.js +77 -12
- package/dist/server/tools/AuthTools.d.ts.map +1 -1
- package/dist/server/tools/AuthTools.js +33 -1
- package/dist/server/tools/BuildInfoTools.d.ts +25 -0
- package/dist/server/tools/BuildInfoTools.d.ts.map +1 -0
- package/dist/server/tools/BuildInfoTools.js +36 -0
- package/dist/server/tools/CollectionTools.d.ts.map +1 -1
- package/dist/server/tools/CollectionTools.js +55 -46
- package/dist/server/tools/ConfigTools.d.ts.map +1 -1
- package/dist/server/tools/ConfigTools.js +29 -1
- package/dist/server/tools/PersonaTools.d.ts +4 -2
- package/dist/server/tools/PersonaTools.d.ts.map +1 -1
- package/dist/server/tools/PersonaTools.js +5 -152
- package/dist/server/tools/PortfolioTools.d.ts +12 -0
- package/dist/server/tools/PortfolioTools.d.ts.map +1 -0
- package/dist/server/tools/PortfolioTools.js +221 -0
- package/dist/server/tools/index.d.ts +3 -1
- package/dist/server/tools/index.d.ts.map +1 -1
- package/dist/server/tools/index.js +4 -2
- package/dist/server/types.d.ts +40 -5
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js +1 -1
- package/dist/services/BuildInfoService.d.ts +84 -0
- package/dist/services/BuildInfoService.d.ts.map +1 -0
- package/dist/services/BuildInfoService.js +271 -0
- package/dist/tools/portfolio/PortfolioElementAdapter.d.ts +54 -0
- package/dist/tools/portfolio/PortfolioElementAdapter.d.ts.map +1 -0
- package/dist/tools/portfolio/PortfolioElementAdapter.js +229 -0
- package/dist/tools/portfolio/submitToPortfolioTool.d.ts +164 -0
- package/dist/tools/portfolio/submitToPortfolioTool.d.ts.map +1 -0
- package/dist/tools/portfolio/submitToPortfolioTool.js +1523 -0
- package/dist/tools/portfolio/types.d.ts +41 -0
- package/dist/tools/portfolio/types.d.ts.map +1 -0
- package/dist/tools/portfolio/types.js +15 -0
- package/dist/types/collection.d.ts +51 -0
- package/dist/types/collection.d.ts.map +1 -1
- package/dist/types/collection.js +1 -1
- package/dist/utils/EarlyTerminationSearch.d.ts +41 -0
- package/dist/utils/EarlyTerminationSearch.d.ts.map +1 -0
- package/dist/utils/EarlyTerminationSearch.js +164 -0
- package/dist/utils/ErrorHandler.d.ts +86 -0
- package/dist/utils/ErrorHandler.d.ts.map +1 -0
- package/dist/utils/ErrorHandler.js +201 -0
- package/dist/utils/FileDiscoveryUtil.d.ts +53 -0
- package/dist/utils/FileDiscoveryUtil.d.ts.map +1 -0
- package/dist/utils/FileDiscoveryUtil.js +169 -0
- package/dist/utils/GitHubRateLimiter.d.ts +88 -0
- package/dist/utils/GitHubRateLimiter.d.ts.map +1 -0
- package/dist/utils/GitHubRateLimiter.js +315 -0
- package/dist/utils/PerformanceMonitor.d.ts +134 -0
- package/dist/utils/PerformanceMonitor.d.ts.map +1 -0
- package/dist/utils/PerformanceMonitor.js +347 -0
- package/dist/utils/RateLimiter.d.ts.map +1 -0
- package/dist/utils/RateLimiter.js +172 -0
- package/dist/utils/SecureDownloader.d.ts +241 -0
- package/dist/utils/SecureDownloader.d.ts.map +1 -0
- package/dist/utils/SecureDownloader.js +759 -0
- package/dist/utils/ToolCache.d.ts +82 -0
- package/dist/utils/ToolCache.d.ts.map +1 -0
- package/dist/utils/ToolCache.js +196 -0
- package/dist/utils/errorCodes.d.ts +136 -0
- package/dist/utils/errorCodes.d.ts.map +1 -0
- package/dist/utils/errorCodes.js +87 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -1
- package/dist/utils/installation.d.ts +1 -1
- package/dist/utils/installation.d.ts.map +1 -1
- package/dist/utils/installation.js +9 -8
- package/dist/utils/searchUtils.d.ts +31 -0
- package/dist/utils/searchUtils.d.ts.map +1 -1
- package/dist/utils/searchUtils.js +62 -1
- package/package.json +17 -7
- package/dist/config/updateConfig.d.ts +0 -84
- package/dist/config/updateConfig.d.ts.map +0 -1
- package/dist/config/updateConfig.js +0 -148
- package/dist/server/tools/UpdateTools.d.ts +0 -10
- package/dist/server/tools/UpdateTools.d.ts.map +0 -1
- package/dist/server/tools/UpdateTools.js +0 -85
- package/dist/update/BackupManager.d.ts +0 -63
- package/dist/update/BackupManager.d.ts.map +0 -1
- package/dist/update/BackupManager.js +0 -370
- package/dist/update/DependencyChecker.d.ts +0 -41
- package/dist/update/DependencyChecker.d.ts.map +0 -1
- package/dist/update/DependencyChecker.js +0 -132
- package/dist/update/RateLimiter.d.ts.map +0 -1
- package/dist/update/RateLimiter.js +0 -172
- package/dist/update/SignatureVerifier.d.ts +0 -71
- package/dist/update/SignatureVerifier.d.ts.map +0 -1
- package/dist/update/SignatureVerifier.js +0 -214
- package/dist/update/UpdateChecker.d.ts +0 -132
- package/dist/update/UpdateChecker.d.ts.map +0 -1
- package/dist/update/UpdateChecker.js +0 -506
- package/dist/update/UpdateManager.d.ts +0 -60
- package/dist/update/UpdateManager.d.ts.map +0 -1
- package/dist/update/UpdateManager.js +0 -730
- package/dist/update/VersionManager.d.ts +0 -31
- package/dist/update/VersionManager.d.ts.map +0 -1
- package/dist/update/VersionManager.js +0 -181
- package/dist/update/index.d.ts +0 -9
- package/dist/update/index.d.ts.map +0 -1
- package/dist/update/index.js +0 -9
- /package/dist/{update → utils}/RateLimiter.d.ts +0 -0
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* It ensures users have example content to work with immediately after installation.
|
|
7
7
|
*/
|
|
8
8
|
import * as fs from 'fs/promises';
|
|
9
|
+
import * as fsSync from 'fs';
|
|
9
10
|
import * as path from 'path';
|
|
10
11
|
import { fileURLToPath } from 'url';
|
|
11
12
|
import { createHash } from 'crypto';
|
|
@@ -13,6 +14,7 @@ import { logger } from '../utils/logger.js';
|
|
|
13
14
|
import { ElementType } from './types.js';
|
|
14
15
|
import { UnicodeValidator } from '../security/validators/unicodeValidator.js';
|
|
15
16
|
import { SecurityMonitor } from '../security/securityMonitor.js';
|
|
17
|
+
import { SecureYamlParser } from '../security/secureYamlParser.js';
|
|
16
18
|
// File operation constants
|
|
17
19
|
export const FILE_CONSTANTS = {
|
|
18
20
|
ELEMENT_EXTENSION: '.md',
|
|
@@ -24,6 +26,18 @@ export const FILE_CONSTANTS = {
|
|
|
24
26
|
FILE_PERMISSIONS: 0o644,
|
|
25
27
|
CHUNK_SIZE: 64 * 1024 // 64KB chunks for reading large files
|
|
26
28
|
};
|
|
29
|
+
// Development mode detection
|
|
30
|
+
// When running from a git clone, we don't want to auto-load test data
|
|
31
|
+
const IS_DEVELOPMENT_MODE = (() => {
|
|
32
|
+
try {
|
|
33
|
+
// Check if we're in a git repository (development mode)
|
|
34
|
+
const gitDir = path.join(process.cwd(), '.git');
|
|
35
|
+
return fsSync.existsSync(gitDir);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
})();
|
|
27
41
|
// Internal constants
|
|
28
42
|
const DATA_DIR_CACHE_KEY = 'dollhouse_data_dir';
|
|
29
43
|
const COPY_RETRY_ATTEMPTS = 3;
|
|
@@ -33,13 +47,66 @@ export class DefaultElementProvider {
|
|
|
33
47
|
static cachedDataDir = null;
|
|
34
48
|
static populateInProgress = new Map();
|
|
35
49
|
config;
|
|
50
|
+
// PERFORMANCE OPTIMIZATION: Cache metadata with file mtime for invalidation
|
|
51
|
+
static metadataCache = new Map();
|
|
52
|
+
static MAX_CACHE_SIZE = 20; // MEMORY LEAK FIX: Further reduced cache size to prevent accumulation during performance tests
|
|
36
53
|
constructor(config) {
|
|
37
54
|
const __filename = fileURLToPath(import.meta.url);
|
|
38
55
|
this.__dirname = path.dirname(__filename);
|
|
56
|
+
// Check environment variable for test data loading
|
|
57
|
+
const envLoadTestData = process.env.DOLLHOUSE_LOAD_TEST_DATA;
|
|
58
|
+
const loadTestDataFromEnv = envLoadTestData === 'true' || envLoadTestData === '1';
|
|
59
|
+
const disableTestDataFromEnv = envLoadTestData === 'false' || envLoadTestData === '0';
|
|
60
|
+
// Check if we're in development mode (with respect to FORCE_PRODUCTION_MODE override)
|
|
61
|
+
const isDevMode = (() => {
|
|
62
|
+
// Respect FORCE_PRODUCTION_MODE override first
|
|
63
|
+
if (process.env.FORCE_PRODUCTION_MODE === 'true') {
|
|
64
|
+
return false; // Force production mode
|
|
65
|
+
}
|
|
66
|
+
if (process.env.FORCE_PRODUCTION_MODE === 'false') {
|
|
67
|
+
return true; // Force development mode
|
|
68
|
+
}
|
|
69
|
+
// Fall back to git detection
|
|
70
|
+
return IS_DEVELOPMENT_MODE;
|
|
71
|
+
})();
|
|
72
|
+
// Determine loadTestData value
|
|
73
|
+
let computedLoadTestData;
|
|
74
|
+
if (loadTestDataFromEnv) {
|
|
75
|
+
// Environment explicitly enables test data
|
|
76
|
+
computedLoadTestData = true;
|
|
77
|
+
}
|
|
78
|
+
else if (disableTestDataFromEnv) {
|
|
79
|
+
// Environment explicitly disables test data
|
|
80
|
+
computedLoadTestData = false;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
// Default logic: enable in production, disable in development unless config overrides
|
|
84
|
+
computedLoadTestData = !isDevMode && (config?.loadTestData ?? true);
|
|
85
|
+
}
|
|
39
86
|
this.config = {
|
|
40
87
|
useDefaultPaths: true,
|
|
41
|
-
...config
|
|
88
|
+
...config,
|
|
89
|
+
// Apply final loadTestData logic - environment variables and development mode take precedence
|
|
90
|
+
loadTestData: loadTestDataFromEnv ? true : disableTestDataFromEnv ? false : computedLoadTestData
|
|
42
91
|
};
|
|
92
|
+
if (isDevMode && !this.config.loadTestData) {
|
|
93
|
+
logger.info('[DefaultElementProvider] Development mode detected - test data loading disabled');
|
|
94
|
+
logger.info('[DefaultElementProvider] To enable test data, set DOLLHOUSE_LOAD_TEST_DATA=true');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get the current loadTestData configuration value
|
|
99
|
+
* @returns Whether test data loading is enabled
|
|
100
|
+
*/
|
|
101
|
+
get isTestDataLoadingEnabled() {
|
|
102
|
+
return this.config.loadTestData ?? false;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get whether the system is in development mode
|
|
106
|
+
* @returns Whether running in development mode
|
|
107
|
+
*/
|
|
108
|
+
get isDevelopmentMode() {
|
|
109
|
+
return IS_DEVELOPMENT_MODE;
|
|
43
110
|
}
|
|
44
111
|
/**
|
|
45
112
|
* Search paths for bundled data directory
|
|
@@ -53,9 +120,15 @@ export class DefaultElementProvider {
|
|
|
53
120
|
}
|
|
54
121
|
// Add default paths if enabled
|
|
55
122
|
if (this.config.useDefaultPaths !== false) {
|
|
123
|
+
// Skip development/repository data paths unless test data loading is enabled
|
|
124
|
+
if (this.config.loadTestData) {
|
|
125
|
+
// Development/Git installation (relative to this file)
|
|
126
|
+
paths.push(path.join(this.__dirname, '../../data'), path.join(this.__dirname, '../../../data'),
|
|
127
|
+
// Current working directory (last resort)
|
|
128
|
+
path.join(process.cwd(), 'data'));
|
|
129
|
+
}
|
|
130
|
+
// Always include NPM installation paths (these would have production data)
|
|
56
131
|
paths.push(
|
|
57
|
-
// Development/Git installation (relative to this file)
|
|
58
|
-
path.join(this.__dirname, '../../data'), path.join(this.__dirname, '../../../data'),
|
|
59
132
|
// NPM installations - macOS Homebrew
|
|
60
133
|
'/opt/homebrew/lib/node_modules/@dollhousemcp/mcp-server/data',
|
|
61
134
|
// NPM installations - standard Unix/Linux
|
|
@@ -63,9 +136,7 @@ export class DefaultElementProvider {
|
|
|
63
136
|
// NPM installations - Windows
|
|
64
137
|
'C:\\Program Files\\nodejs\\node_modules\\@dollhousemcp\\mcp-server\\data', 'C:\\Program Files (x86)\\nodejs\\node_modules\\@dollhousemcp\\mcp-server\\data',
|
|
65
138
|
// NPM installations - Windows with nvm
|
|
66
|
-
path.join(process.env.APPDATA || '', 'npm', 'node_modules', '@dollhousemcp', 'mcp-server', 'data')
|
|
67
|
-
// Current working directory (last resort)
|
|
68
|
-
path.join(process.cwd(), 'data'));
|
|
139
|
+
path.join(process.env.APPDATA || '', 'npm', 'node_modules', '@dollhousemcp', 'mcp-server', 'data'));
|
|
69
140
|
}
|
|
70
141
|
return paths;
|
|
71
142
|
}
|
|
@@ -122,6 +193,380 @@ export class DefaultElementProvider {
|
|
|
122
193
|
return false;
|
|
123
194
|
}
|
|
124
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Validate file path to prevent path traversal attacks
|
|
198
|
+
* SECURITY FIX: Added file path validation to prevent directory traversal
|
|
199
|
+
* Previously: File paths were used without validation, allowing potential ../../../ attacks
|
|
200
|
+
* Now: Strict validation ensures paths stay within allowed directories
|
|
201
|
+
* @param filePath The file path to validate
|
|
202
|
+
* @param allowedBasePaths Array of allowed base paths (optional)
|
|
203
|
+
* @returns true if path is safe, false otherwise
|
|
204
|
+
*/
|
|
205
|
+
validateFilePath(filePath, allowedBasePaths) {
|
|
206
|
+
try {
|
|
207
|
+
// SECURITY: Normalize path to prevent traversal attempts
|
|
208
|
+
const normalizedPath = path.normalize(filePath);
|
|
209
|
+
// SECURITY: Reject paths containing traversal patterns
|
|
210
|
+
if (normalizedPath.includes('..')) {
|
|
211
|
+
logger.warn(`[DefaultElementProvider] Path traversal attempt blocked: ${filePath}`);
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
// SECURITY: Check for home directory expansion attempts, but allow Windows 8.3 short path names
|
|
215
|
+
// Windows short path names use ~ followed by a digit (e.g., RUNNER~1), which should be allowed
|
|
216
|
+
// Only block ~ followed by / or \ (home directory expansion patterns)
|
|
217
|
+
if (normalizedPath.includes('~/') || normalizedPath.includes('~\\')) {
|
|
218
|
+
logger.warn(`[DefaultElementProvider] Home directory expansion attempt blocked: ${filePath}`);
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
// SECURITY: Reject absolute paths outside allowed directories
|
|
222
|
+
if (path.isAbsolute(normalizedPath) && allowedBasePaths) {
|
|
223
|
+
const isAllowed = allowedBasePaths.some(basePath => {
|
|
224
|
+
const normalizedBase = path.normalize(basePath);
|
|
225
|
+
return normalizedPath.startsWith(normalizedBase);
|
|
226
|
+
});
|
|
227
|
+
if (!isAllowed) {
|
|
228
|
+
logger.warn(`[DefaultElementProvider] Absolute path outside allowed directories: ${filePath}`);
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
// SECURITY: Reject null bytes and other dangerous characters
|
|
233
|
+
if (normalizedPath.includes('\0') || normalizedPath.includes('\x00')) {
|
|
234
|
+
logger.warn(`[DefaultElementProvider] Null byte in path blocked: ${filePath}`);
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
logger.warn(`[DefaultElementProvider] Path validation error: ${error}`);
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// DEPRECATED: Commented out filename pattern detection - replaced with metadata-based detection
|
|
245
|
+
/**
|
|
246
|
+
* Cached compiled regex patterns for performance optimization
|
|
247
|
+
* @deprecated Use metadata-based detection instead
|
|
248
|
+
*/
|
|
249
|
+
// private static compiledTestPatterns: RegExp[] | null = null;
|
|
250
|
+
/**
|
|
251
|
+
* Get compiled test patterns with caching for better performance
|
|
252
|
+
* @deprecated Use metadata-based detection instead
|
|
253
|
+
* @returns Array of compiled regex patterns
|
|
254
|
+
*/
|
|
255
|
+
// private getCompiledTestPatterns(): RegExp[] {
|
|
256
|
+
// // Use cached patterns if available
|
|
257
|
+
// if (DefaultElementProvider.compiledTestPatterns) {
|
|
258
|
+
// return DefaultElementProvider.compiledTestPatterns;
|
|
259
|
+
// }
|
|
260
|
+
//
|
|
261
|
+
// // Compile and cache patterns on first use
|
|
262
|
+
// // CRITICAL FIX: Removed overly broad /^test-/i pattern that was blocking legitimate use
|
|
263
|
+
// // Users should be able to create personas like "test-driven-developer" or "test-automation-expert"
|
|
264
|
+
// // We only block specific test patterns that are clearly from our test suite
|
|
265
|
+
// DefaultElementProvider.compiledTestPatterns = [
|
|
266
|
+
// /^testpersona/i, // Our test suite pattern
|
|
267
|
+
// /^yamltest/i, // Security test pattern
|
|
268
|
+
// /^yamlbomb/i, // Security test pattern
|
|
269
|
+
// /^memory-test-/i, // Performance test pattern
|
|
270
|
+
// /^perf-test-/i, // Performance test pattern
|
|
271
|
+
// /^test-fixture-/i, // Test fixture pattern (more specific)
|
|
272
|
+
// /^test-data-/i, // Test data pattern (more specific)
|
|
273
|
+
// /bin-sh|rm-rf|pwned/i, // Malicious patterns
|
|
274
|
+
// /concurrent-\d+/i, // Concurrent test pattern
|
|
275
|
+
// /legacy\.md$/i, // Legacy test pattern
|
|
276
|
+
// /performance-test/i, // Performance test pattern
|
|
277
|
+
// /-\d{13}-[a-z0-9]+\.md$/i, // Timestamp-based test files
|
|
278
|
+
// /^unittest-/i, // Unit test pattern
|
|
279
|
+
// /^integrationtest-/i, // Integration test pattern
|
|
280
|
+
// ];
|
|
281
|
+
//
|
|
282
|
+
// return DefaultElementProvider.compiledTestPatterns;
|
|
283
|
+
// }
|
|
284
|
+
/**
|
|
285
|
+
* Check if a filename matches test data patterns that should never be copied to production
|
|
286
|
+
* @deprecated Use isDollhouseMCPTestElement() for metadata-based detection instead
|
|
287
|
+
* @param filename The filename to check
|
|
288
|
+
* @returns true if the filename matches test patterns that should be blocked
|
|
289
|
+
*/
|
|
290
|
+
// private isTestDataPattern(filename: string): boolean {
|
|
291
|
+
// const patterns = this.getCompiledTestPatterns();
|
|
292
|
+
// return patterns.some(pattern => pattern.test(filename));
|
|
293
|
+
// }
|
|
294
|
+
/**
|
|
295
|
+
* Read metadata from YAML frontmatter only (never reads content body)
|
|
296
|
+
* Uses a small buffer to safely extract only the frontmatter between --- markers
|
|
297
|
+
* @param filePath Path to the file to read metadata from
|
|
298
|
+
* @returns Parsed metadata object or null if no frontmatter found
|
|
299
|
+
*/
|
|
300
|
+
// PERFORMANCE OPTIMIZATION: Reusable buffer pool to reduce allocations
|
|
301
|
+
static bufferPool = [];
|
|
302
|
+
static MAX_POOL_SIZE = 20; // MEMORY LEAK FIX: Reduced buffer pool size to match cache size for consistent memory management
|
|
303
|
+
static bufferPoolStats = { hits: 0, misses: 0, created: 0 };
|
|
304
|
+
getBuffer() {
|
|
305
|
+
// PERFORMANCE: Track buffer pool usage for optimization monitoring
|
|
306
|
+
let buffer = DefaultElementProvider.bufferPool.pop();
|
|
307
|
+
if (buffer) {
|
|
308
|
+
DefaultElementProvider.bufferPoolStats.hits++;
|
|
309
|
+
return buffer;
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
DefaultElementProvider.bufferPoolStats.misses++;
|
|
313
|
+
DefaultElementProvider.bufferPoolStats.created++;
|
|
314
|
+
buffer = Buffer.alloc(4096);
|
|
315
|
+
logger.debug(`[DefaultElementProvider] Created new buffer (pool empty), total created: ${DefaultElementProvider.bufferPoolStats.created}`);
|
|
316
|
+
return buffer;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
releaseBuffer(buffer) {
|
|
320
|
+
// CRITICAL FIX: Always attempt to return buffer to pool for reuse
|
|
321
|
+
if (DefaultElementProvider.bufferPool.length < DefaultElementProvider.MAX_POOL_SIZE) {
|
|
322
|
+
buffer.fill(0); // SECURITY: Clear buffer before reuse to prevent data leakage
|
|
323
|
+
DefaultElementProvider.bufferPool.push(buffer);
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
// PERFORMANCE: If pool is full, clear the buffer to help GC
|
|
327
|
+
buffer.fill(0);
|
|
328
|
+
logger.debug('[DefaultElementProvider] Buffer pool full, discarding buffer');
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Clean up buffer pool and cache to free memory
|
|
333
|
+
* PERFORMANCE FIX: Added cleanup method to prevent memory leaks
|
|
334
|
+
* This should be called during application shutdown or periodic cleanup
|
|
335
|
+
*/
|
|
336
|
+
static cleanup() {
|
|
337
|
+
// Clear buffer pool
|
|
338
|
+
DefaultElementProvider.bufferPool.length = 0;
|
|
339
|
+
// Clear metadata cache
|
|
340
|
+
DefaultElementProvider.metadataCache.clear();
|
|
341
|
+
// Clear cached data directory
|
|
342
|
+
DefaultElementProvider.cachedDataDir = null;
|
|
343
|
+
// Clear population promises
|
|
344
|
+
DefaultElementProvider.populateInProgress.clear();
|
|
345
|
+
logger.info('[DefaultElementProvider] Memory cleanup completed', {
|
|
346
|
+
bufferStats: DefaultElementProvider.bufferPoolStats,
|
|
347
|
+
cacheCleared: true
|
|
348
|
+
});
|
|
349
|
+
// Reset stats
|
|
350
|
+
DefaultElementProvider.bufferPoolStats = { hits: 0, misses: 0, created: 0 };
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Get performance statistics for monitoring
|
|
354
|
+
* PERFORMANCE MONITORING: Added statistics method for performance tracking
|
|
355
|
+
* This provides insights into buffer pool efficiency and cache performance
|
|
356
|
+
* @returns Object containing performance metrics
|
|
357
|
+
*/
|
|
358
|
+
static getPerformanceStats() {
|
|
359
|
+
const bufferHits = DefaultElementProvider.bufferPoolStats.hits;
|
|
360
|
+
const bufferMisses = DefaultElementProvider.bufferPoolStats.misses;
|
|
361
|
+
const totalRequests = bufferHits + bufferMisses;
|
|
362
|
+
return {
|
|
363
|
+
bufferPool: {
|
|
364
|
+
hits: bufferHits,
|
|
365
|
+
misses: bufferMisses,
|
|
366
|
+
created: DefaultElementProvider.bufferPoolStats.created,
|
|
367
|
+
hitRate: totalRequests > 0 ? bufferHits / totalRequests : 0,
|
|
368
|
+
poolSize: DefaultElementProvider.bufferPool.length,
|
|
369
|
+
maxPoolSize: DefaultElementProvider.MAX_POOL_SIZE
|
|
370
|
+
},
|
|
371
|
+
metadataCache: {
|
|
372
|
+
size: DefaultElementProvider.metadataCache.size,
|
|
373
|
+
maxSize: DefaultElementProvider.MAX_CACHE_SIZE
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
async readMetadataOnly(filePath, retries = 2) {
|
|
378
|
+
// PERFORMANCE: Check cache first before reading file
|
|
379
|
+
try {
|
|
380
|
+
const stats = await fs.stat(filePath);
|
|
381
|
+
const cacheKey = filePath;
|
|
382
|
+
const cached = DefaultElementProvider.metadataCache.get(cacheKey);
|
|
383
|
+
// Return cached metadata if file hasn't changed
|
|
384
|
+
// CRITICAL FIX: Use integer mtime comparison to avoid floating-point precision issues
|
|
385
|
+
if (cached && Math.floor(cached.mtime) === Math.floor(stats.mtimeMs) && cached.size === stats.size) {
|
|
386
|
+
logger.debug(`[DefaultElementProvider] Cache hit for ${filePath}`);
|
|
387
|
+
return cached.metadata;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
catch {
|
|
391
|
+
// File doesn't exist, proceed with normal flow
|
|
392
|
+
}
|
|
393
|
+
try {
|
|
394
|
+
// Open file and read only first 4KB to avoid reading dangerous content
|
|
395
|
+
const fd = await fs.open(filePath, 'r');
|
|
396
|
+
// PERFORMANCE: Use buffer pool instead of allocating new buffer each time
|
|
397
|
+
const buffer = this.getBuffer();
|
|
398
|
+
try {
|
|
399
|
+
const result = await fd.read(buffer, 0, 4096, 0);
|
|
400
|
+
const header = buffer.subarray(0, result.bytesRead).toString('utf-8');
|
|
401
|
+
// Look for YAML frontmatter between --- markers
|
|
402
|
+
// Support both Unix (\n) and Windows (\r\n) line endings
|
|
403
|
+
const match = header.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
404
|
+
if (!match) {
|
|
405
|
+
return null; // No frontmatter found
|
|
406
|
+
}
|
|
407
|
+
// Parse the YAML frontmatter safely
|
|
408
|
+
try {
|
|
409
|
+
// SECURITY FIX: Replace direct YAML parsing function with SecureYamlParser for enhanced security
|
|
410
|
+
// SecureYamlParser provides additional validation, injection prevention, and content sanitization
|
|
411
|
+
// It expects full YAML with --- markers, so we reconstruct the frontmatter block
|
|
412
|
+
// We disable specific field validation as this is general metadata parsing, not persona-specific
|
|
413
|
+
const fullYaml = `---\n${match[1]}\n---`;
|
|
414
|
+
const parseResult = SecureYamlParser.parse(fullYaml, {
|
|
415
|
+
validateContent: false,
|
|
416
|
+
validateFields: false
|
|
417
|
+
});
|
|
418
|
+
const metadata = parseResult.data;
|
|
419
|
+
// PERFORMANCE: Cache the metadata with file stats for future reads
|
|
420
|
+
if (typeof metadata === 'object' && metadata !== null) {
|
|
421
|
+
try {
|
|
422
|
+
const stats = await fs.stat(filePath);
|
|
423
|
+
const cacheEntry = {
|
|
424
|
+
metadata,
|
|
425
|
+
mtime: stats.mtimeMs,
|
|
426
|
+
size: stats.size
|
|
427
|
+
};
|
|
428
|
+
// CRITICAL MEMORY LEAK FIX: More aggressive cache management to prevent unbounded growth
|
|
429
|
+
// Check if this entry already exists and just update it instead of adding new
|
|
430
|
+
if (DefaultElementProvider.metadataCache.has(filePath)) {
|
|
431
|
+
// Update existing entry - no eviction needed
|
|
432
|
+
DefaultElementProvider.metadataCache.set(filePath, cacheEntry);
|
|
433
|
+
logger.debug(`[DefaultElementProvider] Updated existing cache entry for ${filePath}`);
|
|
434
|
+
}
|
|
435
|
+
else {
|
|
436
|
+
// New entry - check if we need to evict first
|
|
437
|
+
// Use > instead of >= to ensure we never exceed MAX_CACHE_SIZE
|
|
438
|
+
if (DefaultElementProvider.metadataCache.size >= DefaultElementProvider.MAX_CACHE_SIZE) {
|
|
439
|
+
// More aggressive eviction: remove enough entries to stay well under limit
|
|
440
|
+
const entriesToEvict = Math.max(1, Math.floor(DefaultElementProvider.MAX_CACHE_SIZE * 0.4));
|
|
441
|
+
const keysToEvict = Array.from(DefaultElementProvider.metadataCache.keys()).slice(0, entriesToEvict);
|
|
442
|
+
for (const key of keysToEvict) {
|
|
443
|
+
DefaultElementProvider.metadataCache.delete(key);
|
|
444
|
+
}
|
|
445
|
+
logger.debug(`[DefaultElementProvider] Evicted ${keysToEvict.length} cache entries to manage memory (cache size was ${DefaultElementProvider.metadataCache.size + keysToEvict.length})`);
|
|
446
|
+
}
|
|
447
|
+
DefaultElementProvider.metadataCache.set(filePath, cacheEntry);
|
|
448
|
+
logger.debug(`[DefaultElementProvider] Added new cache entry for ${filePath} (cache size now: ${DefaultElementProvider.metadataCache.size})`);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
catch {
|
|
452
|
+
// Ignore cache errors, return metadata anyway
|
|
453
|
+
}
|
|
454
|
+
return metadata;
|
|
455
|
+
}
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
catch (yamlError) {
|
|
459
|
+
// Invalid YAML, return null
|
|
460
|
+
// ENHANCEMENT: Include error type for better debugging
|
|
461
|
+
const yamlErrorType = yamlError?.constructor?.name || 'YAMLError';
|
|
462
|
+
logger.debug(`[DefaultElementProvider] Invalid YAML in ${filePath}: ${yamlErrorType} - ${yamlError}`);
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
finally {
|
|
467
|
+
// CRITICAL FIX: Ensure file descriptor is closed and buffer is released in ALL paths
|
|
468
|
+
try {
|
|
469
|
+
await fd.close();
|
|
470
|
+
}
|
|
471
|
+
catch (closeError) {
|
|
472
|
+
logger.debug(`[DefaultElementProvider] Error closing file descriptor for ${filePath}: ${closeError}`);
|
|
473
|
+
}
|
|
474
|
+
// PERFORMANCE: Return buffer to pool for reuse
|
|
475
|
+
this.releaseBuffer(buffer);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
catch (error) {
|
|
479
|
+
// ENHANCEMENT: Include error type in debug logs for better debugging
|
|
480
|
+
const errorType = error?.constructor?.name || 'UnknownError';
|
|
481
|
+
const errorCode = error?.code || 'NO_CODE';
|
|
482
|
+
// RELIABILITY: Add retry logic for transient failures
|
|
483
|
+
if (retries > 0 && (errorCode === 'EBUSY' || errorCode === 'EAGAIN')) {
|
|
484
|
+
logger.debug(`[DefaultElementProvider] Retrying read for ${filePath} after ${errorType}:${errorCode}`);
|
|
485
|
+
await new Promise(resolve => setTimeout(resolve, 50)); // Brief delay before retry
|
|
486
|
+
return this.readMetadataOnly(filePath, retries - 1);
|
|
487
|
+
}
|
|
488
|
+
logger.debug(`[DefaultElementProvider] Could not read metadata from ${filePath}: ${errorType}:${errorCode} - ${error?.message || error}`);
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Check if a file is a DollhouseMCP test element based on metadata
|
|
494
|
+
* This replaces filename pattern detection with accurate metadata-based detection
|
|
495
|
+
* @param filePath Path to the file to check
|
|
496
|
+
* @returns true if the file contains _dollhouseMCPTest: true metadata
|
|
497
|
+
*/
|
|
498
|
+
async isDollhouseMCPTestElement(filePath) {
|
|
499
|
+
try {
|
|
500
|
+
const metadata = await this.readMetadataOnly(filePath);
|
|
501
|
+
const isTest = !!(metadata && metadata._dollhouseMCPTest === true);
|
|
502
|
+
return isTest;
|
|
503
|
+
}
|
|
504
|
+
catch (error) {
|
|
505
|
+
// If we can't read the metadata, assume it's not a test file
|
|
506
|
+
logger.debug(`[DefaultElementProvider] Error checking test metadata for ${filePath}: ${error}`);
|
|
507
|
+
return false;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Detect if we're in a production environment by checking for production indicators
|
|
512
|
+
* Uses a confidence-based approach requiring multiple indicators for better accuracy
|
|
513
|
+
* @returns true if this appears to be a production environment
|
|
514
|
+
*/
|
|
515
|
+
isProductionEnvironment() {
|
|
516
|
+
// Allow tests to explicitly override production mode detection
|
|
517
|
+
if (process.env.FORCE_PRODUCTION_MODE === 'true') {
|
|
518
|
+
return true;
|
|
519
|
+
}
|
|
520
|
+
if (process.env.FORCE_PRODUCTION_MODE === 'false') {
|
|
521
|
+
return false;
|
|
522
|
+
}
|
|
523
|
+
// Weighted indicators for production detection
|
|
524
|
+
const indicators = {
|
|
525
|
+
// Strong indicators (weight: 2)
|
|
526
|
+
hasUserHomeDir: (process.env.HOME && (process.env.HOME.includes('/Users/') || process.env.HOME.includes('/home/'))) ||
|
|
527
|
+
!!process.env.USERPROFILE,
|
|
528
|
+
isProductionNode: process.env.NODE_ENV === 'production',
|
|
529
|
+
notInTestDir: (() => {
|
|
530
|
+
const cwd = process.cwd().toLowerCase();
|
|
531
|
+
// Normalize path separators for cross-platform checking (Windows uses \ but checks use /)
|
|
532
|
+
const normalizedCwd = cwd.replace(/\\/g, '/');
|
|
533
|
+
return !normalizedCwd.includes('/test') &&
|
|
534
|
+
!normalizedCwd.includes('/__tests__') &&
|
|
535
|
+
!normalizedCwd.includes('/temp') &&
|
|
536
|
+
!normalizedCwd.includes('/dist/test');
|
|
537
|
+
})(),
|
|
538
|
+
// Moderate indicators (weight: 1)
|
|
539
|
+
notInCI: !process.env.CI,
|
|
540
|
+
noTestEnv: process.env.NODE_ENV !== 'test',
|
|
541
|
+
noDevEnv: process.env.NODE_ENV !== 'development',
|
|
542
|
+
};
|
|
543
|
+
// Calculate weighted score
|
|
544
|
+
let score = 0;
|
|
545
|
+
if (indicators.hasUserHomeDir)
|
|
546
|
+
score += 2;
|
|
547
|
+
if (indicators.isProductionNode)
|
|
548
|
+
score += 2;
|
|
549
|
+
if (indicators.notInTestDir)
|
|
550
|
+
score += 2;
|
|
551
|
+
if (indicators.notInCI)
|
|
552
|
+
score += 1;
|
|
553
|
+
if (indicators.noTestEnv)
|
|
554
|
+
score += 1;
|
|
555
|
+
if (indicators.noDevEnv)
|
|
556
|
+
score += 1;
|
|
557
|
+
// Log detection details for debugging
|
|
558
|
+
const activeIndicators = Object.entries(indicators)
|
|
559
|
+
.filter(([_, value]) => value)
|
|
560
|
+
.map(([key]) => key);
|
|
561
|
+
// TYPESCRIPT FIX: Removed logger.isDebugEnabled() check as this method doesn't exist on MCPLogger
|
|
562
|
+
// The logger already handles debug level internally, so we can call debug() directly
|
|
563
|
+
if (score >= 3) {
|
|
564
|
+
logger.debug('[DefaultElementProvider] Production environment detected', { score, activeIndicators, forceMode: 'not set' });
|
|
565
|
+
}
|
|
566
|
+
// Require a score of at least 3 for production detection (more confident)
|
|
567
|
+
// This prevents false positives in edge cases while maintaining security
|
|
568
|
+
return score >= 3;
|
|
569
|
+
}
|
|
125
570
|
/**
|
|
126
571
|
* Copy all files from source directory to destination directory
|
|
127
572
|
* Skips files that already exist to preserve user modifications
|
|
@@ -146,6 +591,40 @@ export class DefaultElementProvider {
|
|
|
146
591
|
}
|
|
147
592
|
const sourcePath = path.join(sourceDir, normalizedFile.normalizedContent);
|
|
148
593
|
const destPath = path.join(destDir, normalizedFile.normalizedContent);
|
|
594
|
+
// SECURITY FIX: Validate file paths to prevent path traversal attacks
|
|
595
|
+
// This prevents malicious files from escaping the intended directory structure
|
|
596
|
+
const sourceValid = this.validateFilePath(sourcePath, [sourceDir]);
|
|
597
|
+
const destValid = this.validateFilePath(destPath, [destDir]);
|
|
598
|
+
if (!sourceValid || !destValid) {
|
|
599
|
+
logger.warn(`[DefaultElementProvider] Skipping file with invalid path: ${normalizedFile.normalizedContent}`, { sourcePath, destPath, elementType });
|
|
600
|
+
continue;
|
|
601
|
+
}
|
|
602
|
+
// Production safety check: Block DollhouseMCP test elements in production environments
|
|
603
|
+
// Skip this check if loadTestData is explicitly enabled (for testing scenarios)
|
|
604
|
+
if (!this.config.loadTestData && this.isProductionEnvironment()) {
|
|
605
|
+
const isDollhouseTest = await this.isDollhouseMCPTestElement(sourcePath);
|
|
606
|
+
if (isDollhouseTest) {
|
|
607
|
+
logger.warn(`[DefaultElementProvider] SECURITY: Blocking DollhouseMCP test element in production: ${normalizedFile.normalizedContent}`, {
|
|
608
|
+
file: normalizedFile.normalizedContent,
|
|
609
|
+
reason: 'DollhouseMCP test element detected in production environment',
|
|
610
|
+
elementType
|
|
611
|
+
});
|
|
612
|
+
// Log security event for blocked test data
|
|
613
|
+
SecurityMonitor.logSecurityEvent({
|
|
614
|
+
type: 'TEST_DATA_BLOCKED',
|
|
615
|
+
severity: 'MEDIUM',
|
|
616
|
+
source: 'DefaultElementProvider.copyElementFiles',
|
|
617
|
+
details: `Blocked DollhouseMCP test element in production: ${normalizedFile.normalizedContent}`,
|
|
618
|
+
metadata: {
|
|
619
|
+
filename: normalizedFile.normalizedContent,
|
|
620
|
+
elementType,
|
|
621
|
+
reason: 'DollhouseMCP test element detected in production environment',
|
|
622
|
+
detectionMethod: 'metadata-based'
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
149
628
|
try {
|
|
150
629
|
// Check if destination file already exists
|
|
151
630
|
await fs.access(destPath);
|
|
@@ -322,6 +801,19 @@ export class DefaultElementProvider {
|
|
|
322
801
|
* @param portfolioBaseDir Base directory of the portfolio
|
|
323
802
|
*/
|
|
324
803
|
async performPopulation(portfolioBaseDir) {
|
|
804
|
+
// Check if test data loading is disabled
|
|
805
|
+
// Note: This check is needed even though constructor sets config, because
|
|
806
|
+
// config can be overridden after construction
|
|
807
|
+
// Use production environment detection that respects FORCE_PRODUCTION_MODE
|
|
808
|
+
const isDevelopmentMode = !this.isProductionEnvironment();
|
|
809
|
+
if (isDevelopmentMode && !this.config.loadTestData) {
|
|
810
|
+
logger.info('[DefaultElementProvider] Skipping default element population in development mode', {
|
|
811
|
+
portfolioBaseDir,
|
|
812
|
+
reason: 'Test data loading disabled',
|
|
813
|
+
enableWith: 'Set DOLLHOUSE_LOAD_TEST_DATA=true to enable'
|
|
814
|
+
});
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
325
817
|
logger.info('[DefaultElementProvider] Starting default element population', { portfolioBaseDir });
|
|
326
818
|
// Log security event for portfolio initialization
|
|
327
819
|
SecurityMonitor.logSecurityEvent({
|
|
@@ -383,4 +875,4 @@ export class DefaultElementProvider {
|
|
|
383
875
|
}
|
|
384
876
|
}
|
|
385
877
|
}
|
|
386
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRGVmYXVsdEVsZW1lbnRQcm92aWRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wb3J0Zm9saW8vRGVmYXVsdEVsZW1lbnRQcm92aWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDcEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDekMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFDOUUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRWpFLDJCQUEyQjtBQUMzQixNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUc7SUFDNUIsaUJBQWlCLEVBQUUsS0FBSztJQUN4QixjQUFjLEVBQUUsT0FBTztJQUN2QixhQUFhLEVBQUUsTUFBTTtJQUNyQixjQUFjLEVBQUUsT0FBTztJQUN2QixhQUFhLEVBQUUsRUFBRSxHQUFHLElBQUksR0FBRyxJQUFJLEVBQUUsZ0NBQWdDO0lBQ2pFLGtCQUFrQixFQUFFLFFBQVE7SUFDNUIsZ0JBQWdCLEVBQUUsS0FBSztJQUN2QixVQUFVLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxzQ0FBc0M7Q0FDcEQsQ0FBQztBQUVYLHFCQUFxQjtBQUNyQixNQUFNLGtCQUFrQixHQUFHLG9CQUFvQixDQUFDO0FBQ2hELE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO0FBQzlCLE1BQU0sZ0JBQWdCLEdBQUcsR0FBRyxDQUFDLENBQUMsS0FBSztBQVNuQyxN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biAqIERlZmF1bHRFbGVtZW50UHJvdmlkZXIgLSBQb3B1bGF0ZXMgcG9ydGZvbGlvIHdpdGggZGVmYXVsdCBlbGVtZW50cyBmcm9tIGJ1bmRsZWQgZGF0YVxuICogXG4gKiBUaGlzIGNsYXNzIGhhbmRsZXMgY29weWluZyBkZWZhdWx0IHBlcnNvbmFzLCBza2lsbHMsIHRlbXBsYXRlcywgYW5kIG90aGVyIGVsZW1lbnRzXG4gKiBmcm9tIHRoZSBOUE0gcGFja2FnZSBvciBHaXQgcmVwb3NpdG9yeSB0byB0aGUgdXNlcidzIHBvcnRmb2xpbyBvbiBmaXJzdCBydW4uXG4gKiBJdCBlbnN1cmVzIHVzZXJzIGhhdmUgZXhhbXBsZSBjb250ZW50IHRvIHdvcmsgd2l0aCBpbW1lZGlhdGVseSBhZnRlciBpbnN0YWxsYXRpb24uXG4gKi9cblxuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMvcHJvbWlzZXMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tICd1cmwnO1xuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXIuanMnO1xuaW1wb3J0IHsgRWxlbWVudFR5cGUgfSBmcm9tICcuL3R5cGVzLmpzJztcbmltcG9ydCB7IFVuaWNvZGVWYWxpZGF0b3IgfSBmcm9tICcuLi9zZWN1cml0eS92YWxpZGF0b3JzL3VuaWNvZGVWYWxpZGF0b3IuanMnO1xuaW1wb3J0IHsgU2VjdXJpdHlNb25pdG9yIH0gZnJvbSAnLi4vc2VjdXJpdHkvc2VjdXJpdHlNb25pdG9yLmpzJztcblxuLy8gRmlsZSBvcGVyYXRpb24gY29uc3RhbnRzXG5leHBvcnQgY29uc3QgRklMRV9DT05TVEFOVFMgPSB7XG4gIEVMRU1FTlRfRVhURU5TSU9OOiAnLm1kJyxcbiAgWUFNTF9FWFRFTlNJT046ICcueWFtbCcsXG4gIFlNTF9FWFRFTlNJT046ICcueW1sJyxcbiAgSlNPTl9FWFRFTlNJT046ICcuanNvbicsXG4gIE1BWF9GSUxFX1NJWkU6IDEwICogMTAyNCAqIDEwMjQsIC8vIDEwTUIgbWF4IGZpbGUgc2l6ZSBmb3Igc2FmZXR5XG4gIENIRUNLU1VNX0FMR09SSVRITTogJ3NoYTI1NicsXG4gIEZJTEVfUEVSTUlTU0lPTlM6IDBvNjQ0LFxuICBDSFVOS19TSVpFOiA2NCAqIDEwMjQgLy8gNjRLQiBjaHVua3MgZm9yIHJlYWRpbmcgbGFyZ2UgZmlsZXNcbn0gYXMgY29uc3Q7XG5cbi8vIEludGVybmFsIGNvbnN0YW50c1xuY29uc3QgREFUQV9ESVJfQ0FDSEVfS0VZID0gJ2RvbGxob3VzZV9kYXRhX2Rpcic7XG5jb25zdCBDT1BZX1JFVFJZX0FUVEVNUFRTID0gMztcbmNvbnN0IENPUFlfUkVUUllfREVMQVkgPSAxMDA7IC8vIG1zXG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVmYXVsdEVsZW1lbnRQcm92aWRlckNvbmZpZyB7XG4gIC8qKiBDdXN0b20gZGF0YSBkaXJlY3RvcnkgcGF0aHMgdG8gc2VhcmNoIChjaGVja2VkIGJlZm9yZSBkZWZhdWx0IHBhdGhzKSAqL1xuICBjdXN0b21EYXRhUGF0aHM/OiBzdHJpbmdbXTtcbiAgLyoqIFdoZXRoZXIgdG8gdXNlIGRlZmF1bHQgc2VhcmNoIHBhdGhzIGFmdGVyIGN1c3RvbSBwYXRocyAqL1xuICB1c2VEZWZhdWx0UGF0aHM/OiBib29sZWFuO1xufVxuXG5leHBvcnQgY2xhc3MgRGVmYXVsdEVsZW1lbnRQcm92aWRlciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgX19kaXJuYW1lOiBzdHJpbmc7XG4gIHByaXZhdGUgc3RhdGljIGNhY2hlZERhdGFEaXI6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHN0YXRpYyBwb3B1bGF0ZUluUHJvZ3Jlc3M6IE1hcDxzdHJpbmcsIFByb21pc2U8dm9pZD4+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIHJlYWRvbmx5IGNvbmZpZzogRGVmYXVsdEVsZW1lbnRQcm92aWRlckNvbmZpZztcbiAgXG4gIGNvbnN0cnVjdG9yKGNvbmZpZz86IERlZmF1bHRFbGVtZW50UHJvdmlkZXJDb25maWcpIHtcbiAgICBjb25zdCBfX2ZpbGVuYW1lID0gZmlsZVVSTFRvUGF0aChpbXBvcnQubWV0YS51cmwpO1xuICAgIHRoaXMuX19kaXJuYW1lID0gcGF0aC5kaXJuYW1lKF9fZmlsZW5hbWUpO1xuICAgIHRoaXMuY29uZmlnID0ge1xuICAgICAgdXNlRGVmYXVsdFBhdGhzOiB0cnVlLFxuICAgICAgLi4uY29uZmlnXG4gICAgfTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIFNlYXJjaCBwYXRocyBmb3IgYnVuZGxlZCBkYXRhIGRpcmVjdG9yeVxuICAgKiBPcmRlcmVkIGJ5IHByaW9yaXR5IC0gY3VzdG9tIHBhdGhzIGZpcnN0LCB0aGVuIGRldmVsb3BtZW50L2dpdCwgdGhlbiBOUE0gbG9jYXRpb25zXG4gICAqL1xuICBwcml2YXRlIGdldCBkYXRhU2VhcmNoUGF0aHMoKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IHBhdGhzOiBzdHJpbmdbXSA9IFtdO1xuICAgIFxuICAgIC8vIEFkZCBjdXN0b20gcGF0aHMgZmlyc3QgKGhpZ2hlc3QgcHJpb3JpdHkpXG4gICAgaWYgKHRoaXMuY29uZmlnLmN1c3RvbURhdGFQYXRocykge1xuICAgICAgcGF0aHMucHVzaCguLi50aGlzLmNvbmZpZy5jdXN0b21EYXRhUGF0aHMpO1xuICAgIH1cbiAgICBcbiAgICAvLyBBZGQgZGVmYXVsdCBwYXRocyBpZiBlbmFibGVkXG4gICAgaWYgKHRoaXMuY29uZmlnLnVzZURlZmF1bHRQYXRocyAhPT0gZmFsc2UpIHtcbiAgICAgIHBhdGhzLnB1c2goXG4gICAgICAgIC8vIERldmVsb3BtZW50L0dpdCBpbnN0YWxsYXRpb24gKHJlbGF0aXZlIHRvIHRoaXMgZmlsZSlcbiAgICAgICAgcGF0aC5qb2luKHRoaXMuX19kaXJuYW1lLCAnLi4vLi4vZGF0YScpLFxuICAgICAgICBwYXRoLmpvaW4odGhpcy5fX2Rpcm5hbWUsICcuLi8uLi8uLi9kYXRhJyksXG4gICAgICAgIFxuICAgICAgICAvLyBOUE0gaW5zdGFsbGF0aW9ucyAtIG1hY09TIEhvbWVicmV3XG4gICAgICAgICcvb3B0L2hvbWVicmV3L2xpYi9ub2RlX21vZHVsZXMvQGRvbGxob3VzZW1jcC9tY3Atc2VydmVyL2RhdGEnLFxuICAgICAgICBcbiAgICAgICAgLy8gTlBNIGluc3RhbGxhdGlvbnMgLSBzdGFuZGFyZCBVbml4L0xpbnV4XG4gICAgICAgICcvdXNyL2xvY2FsL2xpYi9ub2RlX21vZHVsZXMvQGRvbGxob3VzZW1jcC9tY3Atc2VydmVyL2RhdGEnLFxuICAgICAgICAnL3Vzci9saWIvbm9kZV9tb2R1bGVzL0Bkb2xsaG91c2VtY3AvbWNwLXNlcnZlci9kYXRhJyxcbiAgICAgICAgXG4gICAgICAgIC8vIE5QTSBpbnN0YWxsYXRpb25zIC0gV2luZG93c1xuICAgICAgICAnQzpcXFxcUHJvZ3JhbSBGaWxlc1xcXFxub2RlanNcXFxcbm9kZV9tb2R1bGVzXFxcXEBkb2xsaG91c2VtY3BcXFxcbWNwLXNlcnZlclxcXFxkYXRhJyxcbiAgICAgICAgJ0M6XFxcXFByb2dyYW0gRmlsZXMgKHg4NilcXFxcbm9kZWpzXFxcXG5vZGVfbW9kdWxlc1xcXFxAZG9sbGhvdXNlbWNwXFxcXG1jcC1zZXJ2ZXJcXFxcZGF0YScsXG4gICAgICAgIFxuICAgICAgICAvLyBOUE0gaW5zdGFsbGF0aW9ucyAtIFdpbmRvd3Mgd2l0aCBudm1cbiAgICAgICAgcGF0aC5qb2luKHByb2Nlc3MuZW52LkFQUERBVEEgfHwgJycsICducG0nLCAnbm9kZV9tb2R1bGVzJywgJ0Bkb2xsaG91c2VtY3AnLCAnbWNwLXNlcnZlcicsICdkYXRhJyksXG4gICAgICAgIFxuICAgICAgICAvLyBDdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5IChsYXN0IHJlc29ydClcbiAgICAgICAgcGF0aC5qb2luKHByb2Nlc3MuY3dkKCksICdkYXRhJylcbiAgICAgICk7XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBwYXRocztcbiAgfVxuICBcbiAgLyoqXG4gICAqIEZpbmQgdGhlIGJ1bmRsZWQgZGF0YSBkaXJlY3RvcnkgYnkgY2hlY2tpbmcgZWFjaCBzZWFyY2ggcGF0aFxuICAgKiBVc2VzIFByb21pc2UuYWxsU2V0dGxlZCBmb3IgYmV0dGVyIHBlcmZvcm1hbmNlIGFuZCBjYWNoZXMgdGhlIHJlc3VsdFxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBmaW5kRGF0YURpcmVjdG9yeSgpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+IHtcbiAgICAvLyBSZXR1cm4gY2FjaGVkIHZhbHVlIGlmIGF2YWlsYWJsZVxuICAgIGlmIChEZWZhdWx0RWxlbWVudFByb3ZpZGVyLmNhY2hlZERhdGFEaXIgIT09IG51bGwpIHtcbiAgICAgIHJldHVybiBEZWZhdWx0RWxlbWVudFByb3ZpZGVyLmNhY2hlZERhdGFEaXI7XG4gICAgfVxuICAgIFxuICAgIC8vIENoZWNrIGFsbCBwYXRocyBpbiBwYXJhbGxlbCBmb3IgYmV0dGVyIHBlcmZvcm1hbmNlXG4gICAgY29uc3QgY2hlY2tQcm9taXNlcyA9IHRoaXMuZGF0YVNlYXJjaFBhdGhzLm1hcChhc3luYyAoc2VhcmNoUGF0aCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3Qgc3RhdHMgPSBhd2FpdCBmcy5zdGF0KHNlYXJjaFBhdGgpO1xuICAgICAgICBpZiAoc3RhdHMuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICAgIC8vIFZlcmlmeSBpdCBjb250YWlucyBleHBlY3RlZCBzdWJkaXJlY3Rvcmllc1xuICAgICAgICAgIGNvbnN0IGhhc1BlcnNvbmFzID0gYXdhaXQgdGhpcy5kaXJlY3RvcnlFeGlzdHMocGF0aC5qb2luKHNlYXJjaFBhdGgsICdwZXJzb25hcycpKTtcbiAgICAgICAgICBjb25zdCBoYXNTa2lsbHMgPSBhd2FpdCB0aGlzLmRpcmVjdG9yeUV4aXN0cyhwYXRoLmpvaW4oc2VhcmNoUGF0aCwgJ3NraWxscycpKTtcbiAgICAgICAgICBpZiAoaGFzUGVyc29uYXMgfHwgaGFzU2tpbGxzKSB7XG4gICAgICAgICAgICByZXR1cm4gc2VhcmNoUGF0aDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIC8vIERpcmVjdG9yeSBkb2Vzbid0IGV4aXN0IG9yIGNhbid0IGJlIGFjY2Vzc2VkXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSk7XG4gICAgXG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChjaGVja1Byb21pc2VzKTtcbiAgICBcbiAgICAvLyBGaW5kIHRoZSBmaXJzdCBzdWNjZXNzZnVsIHJlc3VsdFxuICAgIGZvciAoY29uc3QgcmVzdWx0IG9mIHJlc3VsdHMpIHtcbiAgICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSAnZnVsZmlsbGVkJyAmJiByZXN1bHQudmFsdWUgIT09IG51bGwpIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBGb3VuZCBkYXRhIGRpcmVjdG9yeSBhdDogJHtyZXN1bHQudmFsdWV9YCk7XG4gICAgICAgIC8vIENhY2hlIHRoZSByZXN1bHRcbiAgICAgICAgRGVmYXVsdEVsZW1lbnRQcm92aWRlci5jYWNoZWREYXRhRGlyID0gcmVzdWx0LnZhbHVlO1xuICAgICAgICByZXR1cm4gcmVzdWx0LnZhbHVlO1xuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICBsb2dnZXIud2FybignW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIE5vIGJ1bmRsZWQgZGF0YSBkaXJlY3RvcnkgZm91bmQgaW4gYW55IHNlYXJjaCBwYXRoJyk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBIZWxwZXIgdG8gY2hlY2sgaWYgYSBkaXJlY3RvcnkgZXhpc3RzXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGRpcmVjdG9yeUV4aXN0cyhkaXJQYXRoOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3Qgc3RhdHMgPSBhd2FpdCBmcy5zdGF0KGRpclBhdGgpO1xuICAgICAgcmV0dXJuIHN0YXRzLmlzRGlyZWN0b3J5KCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG4gIFxuICAvKipcbiAgICogQ29weSBhbGwgZmlsZXMgZnJvbSBzb3VyY2UgZGlyZWN0b3J5IHRvIGRlc3RpbmF0aW9uIGRpcmVjdG9yeVxuICAgKiBTa2lwcyBmaWxlcyB0aGF0IGFscmVhZHkgZXhpc3QgdG8gcHJlc2VydmUgdXNlciBtb2RpZmljYXRpb25zXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGNvcHlFbGVtZW50RmlsZXMoc291cmNlRGlyOiBzdHJpbmcsIGRlc3REaXI6IHN0cmluZywgZWxlbWVudFR5cGU6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgbGV0IGNvcGllZENvdW50ID0gMDtcbiAgICBcbiAgICB0cnkge1xuICAgICAgLy8gRW5zdXJlIGRlc3RpbmF0aW9uIGRpcmVjdG9yeSBleGlzdHNcbiAgICAgIGF3YWl0IGZzLm1rZGlyKGRlc3REaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgXG4gICAgICAvLyBSZWFkIHNvdXJjZSBkaXJlY3RvcnlcbiAgICAgIGNvbnN0IGZpbGVzID0gYXdhaXQgZnMucmVhZGRpcihzb3VyY2VEaXIpO1xuICAgICAgXG4gICAgICBmb3IgKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgICAgLy8gT25seSBjb3B5IG1hcmtkb3duIGZpbGVzXG4gICAgICAgIGlmICghZmlsZS5lbmRzV2l0aChGSUxFX0NPTlNUQU5UUy5FTEVNRU5UX0VYVEVOU0lPTikpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLy8gTm9ybWFsaXplIGZpbGVuYW1lIGZvciBzZWN1cml0eVxuICAgICAgICBjb25zdCBub3JtYWxpemVkRmlsZSA9IFVuaWNvZGVWYWxpZGF0b3Iubm9ybWFsaXplKGZpbGUpO1xuICAgICAgICBpZiAoIW5vcm1hbGl6ZWRGaWxlLmlzVmFsaWQpIHtcbiAgICAgICAgICBsb2dnZXIud2FybihgW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIFNraXBwaW5nIGZpbGUgd2l0aCBpbnZhbGlkIFVuaWNvZGU6ICR7ZmlsZX1gKTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgY29uc3Qgc291cmNlUGF0aCA9IHBhdGguam9pbihzb3VyY2VEaXIsIG5vcm1hbGl6ZWRGaWxlLm5vcm1hbGl6ZWRDb250ZW50KTtcbiAgICAgICAgY29uc3QgZGVzdFBhdGggPSBwYXRoLmpvaW4oZGVzdERpciwgbm9ybWFsaXplZEZpbGUubm9ybWFsaXplZENvbnRlbnQpO1xuICAgICAgICBcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAvLyBDaGVjayBpZiBkZXN0aW5hdGlvbiBmaWxlIGFscmVhZHkgZXhpc3RzXG4gICAgICAgICAgYXdhaXQgZnMuYWNjZXNzKGRlc3RQYXRoKTtcbiAgICAgICAgICBsb2dnZXIuZGVidWcoYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBTa2lwcGluZyBleGlzdGluZyBmaWxlOiAke25vcm1hbGl6ZWRGaWxlLm5vcm1hbGl6ZWRDb250ZW50fWApO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAvLyBGaWxlIGRvZXNuJ3QgZXhpc3QsIHByb2NlZWQgd2l0aCBjb3B5XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gVmFsaWRhdGUgc291cmNlIGZpbGUgYmVmb3JlIGNvcHlpbmdcbiAgICAgICAgICBjb25zdCBzb3VyY2VTdGF0cyA9IGF3YWl0IGZzLnN0YXQoc291cmNlUGF0aCk7XG4gICAgICAgICAgXG4gICAgICAgICAgLy8gQ2hlY2sgZmlsZSBzaXplIGxpbWl0XG4gICAgICAgICAgaWYgKHNvdXJjZVN0YXRzLnNpemUgPiBGSUxFX0NPTlNUQU5UUy5NQVhfRklMRV9TSVpFKSB7XG4gICAgICAgICAgICBsb2dnZXIud2FybihcbiAgICAgICAgICAgICAgYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBTa2lwcGluZyBvdmVyc2l6ZWQgZmlsZSAke25vcm1hbGl6ZWRGaWxlLm5vcm1hbGl6ZWRDb250ZW50fTogYCArXG4gICAgICAgICAgICAgIGAke3NvdXJjZVN0YXRzLnNpemV9IGJ5dGVzIChtYXg6ICR7RklMRV9DT05TVEFOVFMuTUFYX0ZJTEVfU0laRX0gYnl0ZXMpYCxcbiAgICAgICAgICAgICAgeyBcbiAgICAgICAgICAgICAgICBmaWxlOiBub3JtYWxpemVkRmlsZS5ub3JtYWxpemVkQ29udGVudCwgXG4gICAgICAgICAgICAgICAgc2l6ZTogc291cmNlU3RhdHMuc2l6ZSxcbiAgICAgICAgICAgICAgICBtYXhTaXplOiBGSUxFX0NPTlNUQU5UUy5NQVhfRklMRV9TSVpFLFxuICAgICAgICAgICAgICAgIGVsZW1lbnRUeXBlIFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIFxuICAgICAgICAgIC8vIENvcHkgdGhlIGZpbGUgd2l0aCB2ZXJpZmljYXRpb25cbiAgICAgICAgICBhd2FpdCB0aGlzLmNvcHlGaWxlV2l0aFZlcmlmaWNhdGlvbihzb3VyY2VQYXRoLCBkZXN0UGF0aCk7XG4gICAgICAgICAgY29waWVkQ291bnQrKztcbiAgICAgICAgICBsb2dnZXIuZGVidWcoYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBDb3BpZWQgJHtlbGVtZW50VHlwZX06ICR7bm9ybWFsaXplZEZpbGUubm9ybWFsaXplZENvbnRlbnR9YCk7XG4gICAgICAgICAgXG4gICAgICAgICAgLy8gTG9nIHNlY3VyaXR5IGV2ZW50IGZvciBlYWNoIGZpbGUgY29waWVkXG4gICAgICAgICAgU2VjdXJpdHlNb25pdG9yLmxvZ1NlY3VyaXR5RXZlbnQoe1xuICAgICAgICAgICAgdHlwZTogJ0ZJTEVfQ09QSUVEJyxcbiAgICAgICAgICAgIHNldmVyaXR5OiAnTE9XJyxcbiAgICAgICAgICAgIHNvdXJjZTogJ0RlZmF1bHRFbGVtZW50UHJvdmlkZXIuY29weUVsZW1lbnRGaWxlcycsXG4gICAgICAgICAgICBkZXRhaWxzOiBgQ29waWVkIGRlZmF1bHQgJHtlbGVtZW50VHlwZX0gZmlsZTogJHtub3JtYWxpemVkRmlsZS5ub3JtYWxpemVkQ29udGVudH1gLFxuICAgICAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgc291cmNlUGF0aCxcbiAgICAgICAgICAgICAgZGVzdFBhdGgsXG4gICAgICAgICAgICAgIGVsZW1lbnRUeXBlLFxuICAgICAgICAgICAgICBmaWxlU2l6ZTogKGF3YWl0IGZzLnN0YXQoZGVzdFBhdGgpKS5zaXplXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgY29uc3QgZXJyID0gZXJyb3IgYXMgRXJyb3I7XG4gICAgICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBGYWlsZWQgdG8gY29weSAke25vcm1hbGl6ZWRGaWxlLm5vcm1hbGl6ZWRDb250ZW50fWAsXG4gICAgICAgICAgICB7IFxuICAgICAgICAgICAgICBlcnJvcjogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIHN0YWNrOiBlcnIuc3RhY2ssXG4gICAgICAgICAgICAgIHNvdXJjZVBhdGgsXG4gICAgICAgICAgICAgIGRlc3RQYXRoLFxuICAgICAgICAgICAgICBlbGVtZW50VHlwZVxuICAgICAgICAgICAgfVxuICAgICAgICAgICk7XG4gICAgICAgICAgLy8gQ29udGludWUgd2l0aCBvdGhlciBmaWxlcyBpbnN0ZWFkIG9mIGZhaWxpbmcgY29tcGxldGVseVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBcbiAgICAgIGlmIChjb3BpZWRDb3VudCA+IDApIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBDb3BpZWQgJHtjb3BpZWRDb3VudH0gJHtlbGVtZW50VHlwZX0gZmlsZShzKWApO1xuICAgICAgfVxuICAgICAgXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci5lcnJvcihgW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIEVycm9yIGNvcHlpbmcgJHtlbGVtZW50VHlwZX0gZmlsZXM6YCwgZXJyb3IpO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gY29waWVkQ291bnQ7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBDb3B5IGEgZmlsZSB3aXRoIGludGVncml0eSB2ZXJpZmljYXRpb25cbiAgICogRW5zdXJlcyB0aGUgZmlsZSB3YXMgY29waWVkIGNvcnJlY3RseSBieSBjb21wYXJpbmcgc2l6ZXNcbiAgICovXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgY2hlY2tzdW0gb2YgYSBmaWxlIGZvciBpbnRlZ3JpdHkgdmVyaWZpY2F0aW9uXG4gICAqIEBwYXJhbSBmaWxlUGF0aCBQYXRoIHRvIHRoZSBmaWxlXG4gICAqIEByZXR1cm5zIEhleC1lbmNvZGVkIGNoZWNrc3VtXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGNhbGN1bGF0ZUNoZWNrc3VtKGZpbGVQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IGhhc2ggPSBjcmVhdGVIYXNoKEZJTEVfQ09OU1RBTlRTLkNIRUNLU1VNX0FMR09SSVRITSk7XG4gICAgY29uc3Qgc3RyZWFtID0gYXdhaXQgZnMub3BlbihmaWxlUGF0aCwgJ3InKTtcbiAgICBcbiAgICB0cnkge1xuICAgICAgY29uc3QgYnVmZmVyID0gQnVmZmVyLmFsbG9jKEZJTEVfQ09OU1RBTlRTLkNIVU5LX1NJWkUpO1xuICAgICAgbGV0IGJ5dGVzUmVhZDogbnVtYmVyO1xuICAgICAgXG4gICAgICBkbyB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0cmVhbS5yZWFkKGJ1ZmZlciwgMCwgRklMRV9DT05TVEFOVFMuQ0hVTktfU0laRSk7XG4gICAgICAgIGJ5dGVzUmVhZCA9IHJlc3VsdC5ieXRlc1JlYWQ7XG4gICAgICAgIFxuICAgICAgICBpZiAoYnl0ZXNSZWFkID4gMCkge1xuICAgICAgICAgIGhhc2gudXBkYXRlKGJ1ZmZlci5zdWJhcnJheSgwLCBieXRlc1JlYWQpKTtcbiAgICAgICAgfVxuICAgICAgfSB3aGlsZSAoYnl0ZXNSZWFkID4gMCk7XG4gICAgICBcbiAgICAgIHJldHVybiBoYXNoLmRpZ2VzdCgnaGV4Jyk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGF3YWl0IHN0cmVhbS5jbG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb3B5IGZpbGUgd2l0aCBpbnRlZ3JpdHkgdmVyaWZpY2F0aW9uIGFuZCByZXRyeSBsb2dpY1xuICAgKiBAcGFyYW0gc291cmNlUGF0aCBTb3VyY2UgZmlsZSBwYXRoXG4gICAqIEBwYXJhbSBkZXN0UGF0aCBEZXN0aW5hdGlvbiBmaWxlIHBhdGhcbiAgICogQHRocm93cyBFcnJvciBpZiBjb3B5IGZhaWxzIGFmdGVyIGFsbCByZXRyeSBhdHRlbXB0c1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBjb3B5RmlsZVdpdGhWZXJpZmljYXRpb24oc291cmNlUGF0aDogc3RyaW5nLCBkZXN0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IGxhc3RFcnJvcjogRXJyb3IgfCBudWxsID0gbnVsbDtcbiAgICBcbiAgICBmb3IgKGxldCBhdHRlbXB0ID0gMTsgYXR0ZW1wdCA8PSBDT1BZX1JFVFJZX0FUVEVNUFRTOyBhdHRlbXB0KyspIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIENvcHkgdGhlIGZpbGVcbiAgICAgICAgYXdhaXQgZnMuY29weUZpbGUoc291cmNlUGF0aCwgZGVzdFBhdGgpO1xuICAgICAgICBcbiAgICAgICAgLy8gVmVyaWZ5IHNpemUgbWF0Y2hlc1xuICAgICAgICBjb25zdCBbc291cmNlU3RhdHMsIGRlc3RTdGF0c10gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgICAgZnMuc3RhdChzb3VyY2VQYXRoKSxcbiAgICAgICAgICBmcy5zdGF0KGRlc3RQYXRoKVxuICAgICAgICBdKTtcbiAgICAgICAgXG4gICAgICAgIGlmIChzb3VyY2VTdGF0cy5zaXplICE9PSBkZXN0U3RhdHMuc2l6ZSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBTaXplIG1pc21hdGNoIGFmdGVyIGNvcHkgLSBzb3VyY2U6ICR7c291cmNlU3RhdHMuc2l6ZX0gYnl0ZXMsIGAgK1xuICAgICAgICAgICAgYGRlc3RpbmF0aW9uOiAke2Rlc3RTdGF0cy5zaXplfSBieXRlc2BcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICAvLyBWZXJpZnkgY2hlY2tzdW0gbWF0Y2hlcyBmb3IgY29tcGxldGUgaW50ZWdyaXR5XG4gICAgICAgIGNvbnN0IFtzb3VyY2VDaGVja3N1bSwgZGVzdENoZWNrc3VtXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICB0aGlzLmNhbGN1bGF0ZUNoZWNrc3VtKHNvdXJjZVBhdGgpLFxuICAgICAgICAgIHRoaXMuY2FsY3VsYXRlQ2hlY2tzdW0oZGVzdFBhdGgpXG4gICAgICAgIF0pO1xuICAgICAgICBcbiAgICAgICAgaWYgKHNvdXJjZUNoZWNrc3VtICE9PSBkZXN0Q2hlY2tzdW0pIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgQ2hlY2tzdW0gbWlzbWF0Y2ggYWZ0ZXIgY29weSAtIHNvdXJjZTogJHtzb3VyY2VDaGVja3N1bX0sIGAgK1xuICAgICAgICAgICAgYGRlc3RpbmF0aW9uOiAke2Rlc3RDaGVja3N1bX1gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLy8gU2V0IHByb3BlciBwZXJtaXNzaW9uc1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGZzLmNobW9kKGRlc3RQYXRoLCBGSUxFX0NPTlNUQU5UUy5GSUxFX1BFUk1JU1NJT05TKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBsb2dnZXIuZGVidWcoXG4gICAgICAgICAgICBgW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIENvdWxkIG5vdCBzZXQgcGVybWlzc2lvbnMgb24gJHtkZXN0UGF0aH06ICR7ZXJyb3J9YCxcbiAgICAgICAgICAgIHsgc291cmNlUGF0aCwgZGVzdFBhdGgsIGF0dGVtcHQgfVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIC8vIFN1Y2Nlc3MgLSBmaWxlIGNvcGllZCBhbmQgdmVyaWZpZWRcbiAgICAgICAgbG9nZ2VyLmRlYnVnKFxuICAgICAgICAgIGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gU3VjY2Vzc2Z1bGx5IGNvcGllZCBhbmQgdmVyaWZpZWQ6ICR7cGF0aC5iYXNlbmFtZShzb3VyY2VQYXRoKX1gLFxuICAgICAgICAgIHsgc2l6ZTogc291cmNlU3RhdHMuc2l6ZSwgY2hlY2tzdW06IHNvdXJjZUNoZWNrc3VtLnN1YnN0cmluZygwLCA4KSB9XG4gICAgICAgICk7XG4gICAgICAgIHJldHVybjtcbiAgICAgICAgXG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBsYXN0RXJyb3IgPSBlcnJvciBhcyBFcnJvcjtcbiAgICAgICAgXG4gICAgICAgIC8vIENsZWFuIHVwIGZhaWxlZCBjb3B5XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgZnMudW5saW5rKGRlc3RQYXRoKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgLy8gSWdub3JlIGNsZWFudXAgZXJyb3JzXG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGlmIChhdHRlbXB0IDwgQ09QWV9SRVRSWV9BVFRFTVBUUykge1xuICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgIGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gQ29weSBhdHRlbXB0ICR7YXR0ZW1wdH0gZmFpbGVkLCByZXRyeWluZy4uLmAsXG4gICAgICAgICAgICB7IGVycm9yOiBsYXN0RXJyb3IubWVzc2FnZSwgc291cmNlUGF0aCwgZGVzdFBhdGggfVxuICAgICAgICAgICk7XG4gICAgICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIENPUFlfUkVUUllfREVMQVkgKiBhdHRlbXB0KSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgLy8gQWxsIGF0dGVtcHRzIGZhaWxlZFxuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBGYWlsZWQgdG8gY29weSAke3BhdGguYmFzZW5hbWUoc291cmNlUGF0aCl9IGFmdGVyICR7Q09QWV9SRVRSWV9BVFRFTVBUU30gYXR0ZW1wdHM6IGAgK1xuICAgICAgYCR7bGFzdEVycm9yPy5tZXNzYWdlIHx8ICdVbmtub3duIGVycm9yJ31gXG4gICAgKTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIFBvcHVsYXRlIHRoZSBwb3J0Zm9saW8gd2l0aCBkZWZhdWx0IGVsZW1lbnRzIGZyb20gYnVuZGxlZCBkYXRhXG4gICAqIFRoaXMgaXMgY2FsbGVkIGR1cmluZyBwb3J0Zm9saW8gaW5pdGlhbGl6YXRpb24gZm9yIG5ldyBpbnN0YWxsYXRpb25zXG4gICAqIFByb3RlY3RlZCBhZ2FpbnN0IGNvbmN1cnJlbnQgY2FsbHMgdG8gcHJldmVudCByYWNlIGNvbmRpdGlvbnNcbiAgICovXG4gIHB1YmxpYyBhc3luYyBwb3B1bGF0ZURlZmF1bHRzKHBvcnRmb2xpb0Jhc2VEaXI6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIENoZWNrIGlmIHBvcHVsYXRpb24gaXMgYWxyZWFkeSBpbiBwcm9ncmVzcyBmb3IgdGhpcyBwb3J0Zm9saW9cbiAgICBjb25zdCBleGlzdGluZ1BvcHVsYXRpb24gPSBEZWZhdWx0RWxlbWVudFByb3ZpZGVyLnBvcHVsYXRlSW5Qcm9ncmVzcy5nZXQocG9ydGZvbGlvQmFzZURpcik7XG4gICAgaWYgKGV4aXN0aW5nUG9wdWxhdGlvbikge1xuICAgICAgbG9nZ2VyLmRlYnVnKFxuICAgICAgICAnW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIFBvcHVsYXRpb24gYWxyZWFkeSBpbiBwcm9ncmVzcyBmb3IgcG9ydGZvbGlvLCB3YWl0aW5nLi4uJyxcbiAgICAgICAgeyBwb3J0Zm9saW9CYXNlRGlyIH1cbiAgICAgICk7XG4gICAgICByZXR1cm4gZXhpc3RpbmdQb3B1bGF0aW9uO1xuICAgIH1cbiAgICBcbiAgICAvLyBDcmVhdGUgbmV3IHBvcHVsYXRpb24gcHJvbWlzZVxuICAgIGNvbnN0IHBvcHVsYXRpb25Qcm9taXNlID0gdGhpcy5wZXJmb3JtUG9wdWxhdGlvbihwb3J0Zm9saW9CYXNlRGlyKVxuICAgICAgLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICAvLyBDbGVhbiB1cCB3aGVuIGRvbmVcbiAgICAgICAgRGVmYXVsdEVsZW1lbnRQcm92aWRlci5wb3B1bGF0ZUluUHJvZ3Jlc3MuZGVsZXRlKHBvcnRmb2xpb0Jhc2VEaXIpO1xuICAgICAgfSk7XG4gICAgXG4gICAgRGVmYXVsdEVsZW1lbnRQcm92aWRlci5wb3B1bGF0ZUluUHJvZ3Jlc3Muc2V0KHBvcnRmb2xpb0Jhc2VEaXIsIHBvcHVsYXRpb25Qcm9taXNlKTtcbiAgICByZXR1cm4gcG9wdWxhdGlvblByb21pc2U7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBQZXJmb3JtIHRoZSBhY3R1YWwgcG9wdWxhdGlvbiBvZiBkZWZhdWx0IGVsZW1lbnRzXG4gICAqIEBwYXJhbSBwb3J0Zm9saW9CYXNlRGlyIEJhc2UgZGlyZWN0b3J5IG9mIHRoZSBwb3J0Zm9saW9cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcGVyZm9ybVBvcHVsYXRpb24ocG9ydGZvbGlvQmFzZURpcjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbG9nZ2VyLmluZm8oXG4gICAgICAnW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIFN0YXJ0aW5nIGRlZmF1bHQgZWxlbWVudCBwb3B1bGF0aW9uJyxcbiAgICAgIHsgcG9ydGZvbGlvQmFzZURpciB9XG4gICAgKTtcbiAgICBcbiAgICAvLyBMb2cgc2VjdXJpdHkgZXZlbnQgZm9yIHBvcnRmb2xpbyBpbml0aWFsaXphdGlvblxuICAgIFNlY3VyaXR5TW9uaXRvci5sb2dTZWN1cml0eUV2ZW50KHtcbiAgICAgIHR5cGU6ICdQT1JURk9MSU9fSU5JVElBTElaQVRJT04nLFxuICAgICAgc2V2ZXJpdHk6ICdMT1cnLFxuICAgICAgc291cmNlOiAnRGVmYXVsdEVsZW1lbnRQcm92aWRlci5wZXJmb3JtUG9wdWxhdGlvbicsXG4gICAgICBkZXRhaWxzOiBgU3RhcnRpbmcgZGVmYXVsdCBlbGVtZW50IHBvcHVsYXRpb24gZm9yIHBvcnRmb2xpbzogJHtwb3J0Zm9saW9CYXNlRGlyfWBcbiAgICB9KTtcbiAgICBcbiAgICAvLyBGaW5kIHRoZSBidW5kbGVkIGRhdGEgZGlyZWN0b3J5XG4gICAgY29uc3QgZGF0YURpciA9IGF3YWl0IHRoaXMuZmluZERhdGFEaXJlY3RvcnkoKTtcbiAgICBpZiAoIWRhdGFEaXIpIHtcbiAgICAgIGxvZ2dlci53YXJuKFxuICAgICAgICAnW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIE5vIGJ1bmRsZWQgZGF0YSBkaXJlY3RvcnkgZm91bmQgLSBwb3J0Zm9saW8gd2lsbCBzdGFydCBlbXB0eScsXG4gICAgICAgIHsgXG4gICAgICAgICAgc2VhcmNoUGF0aHM6IHRoaXMuZGF0YVNlYXJjaFBhdGhzLnNsaWNlKDAsIDMpLCAvLyBMb2cgZmlyc3QgZmV3IHBhdGhzIGZvciBkZWJ1Z2dpbmdcbiAgICAgICAgICBjd2Q6IHByb2Nlc3MuY3dkKCksXG4gICAgICAgICAgZGlybmFtZTogdGhpcy5fX2Rpcm5hbWVcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgXG4gICAgLy8gVHJhY2sgdG90YWwgZmlsZXMgY29waWVkXG4gICAgbGV0IHRvdGFsQ29waWVkID0gMDtcbiAgICBjb25zdCBjb3BpZWRDb3VudHM6IFJlY29yZDxzdHJpbmcsIG51bWJlcj4gPSB7fTtcbiAgICBcbiAgICAvLyBDb3B5IGVhY2ggZWxlbWVudCB0eXBlIC0gZGlyZWN0b3JpZXMgbm93IG1hdGNoIGVudW0gdmFsdWVzIChhbGwgcGx1cmFsKVxuICAgIGZvciAoY29uc3QgZWxlbWVudFR5cGUgb2YgT2JqZWN0LnZhbHVlcyhFbGVtZW50VHlwZSkpIHtcbiAgICAgIGNvbnN0IHNvdXJjZURpciA9IHBhdGguam9pbihkYXRhRGlyLCBlbGVtZW50VHlwZSk7XG4gICAgICBjb25zdCBkZXN0RGlyID0gcGF0aC5qb2luKHBvcnRmb2xpb0Jhc2VEaXIsIGVsZW1lbnRUeXBlKTtcbiAgICAgIFxuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgc291cmNlIGRpcmVjdG9yeSBleGlzdHNcbiAgICAgICAgYXdhaXQgZnMuYWNjZXNzKHNvdXJjZURpcik7XG4gICAgICAgIGNvbnN0IGNvcGllZENvdW50ID0gYXdhaXQgdGhpcy5jb3B5RWxlbWVudEZpbGVzKHNvdXJjZURpciwgZGVzdERpciwgZWxlbWVudFR5cGUpO1xuICAgICAgICBjb3BpZWRDb3VudHNbZWxlbWVudFR5cGVdID0gY29waWVkQ291bnQ7XG4gICAgICAgIHRvdGFsQ29waWVkICs9IGNvcGllZENvdW50O1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgLy8gU291cmNlIGRpcmVjdG9yeSBkb2Vzbid0IGV4aXN0LCBza2lwXG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhgW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIE5vICR7ZWxlbWVudFR5cGV9IGRpcmVjdG9yeSBpbiBidW5kbGVkIGRhdGFgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgaWYgKHRvdGFsQ29waWVkID4gMCkge1xuICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgIGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gU3VjY2Vzc2Z1bGx5IHBvcHVsYXRlZCBwb3J0Zm9saW8gd2l0aCAke3RvdGFsQ29waWVkfSBkZWZhdWx0IGVsZW1lbnQocylgLFxuICAgICAgICB7XG4gICAgICAgICAgcG9ydGZvbGlvQmFzZURpcixcbiAgICAgICAgICBkYXRhRGlyLFxuICAgICAgICAgIGJyZWFrZG93bjogY29waWVkQ291bnRzXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgICBcbiAgICAgIC8vIExvZyBzZWN1cml0eSBldmVudCBmb3Igc3VjY2Vzc2Z1bCBwb3B1bGF0aW9uXG4gICAgICBTZWN1cml0eU1vbml0b3IubG9nU2VjdXJpdHlFdmVudCh7XG4gICAgICAgIHR5cGU6ICdQT1JURk9MSU9fUE9QVUxBVEVEJyxcbiAgICAgICAgc2V2ZXJpdHk6ICdMT1cnLFxuICAgICAgICBzb3VyY2U6ICdEZWZhdWx0RWxlbWVudFByb3ZpZGVyLnBlcmZvcm1Qb3B1bGF0aW9uJyxcbiAgICAgICAgZGV0YWlsczogYFN1Y2Nlc3NmdWxseSBwb3B1bGF0ZWQgcG9ydGZvbGlvIHdpdGggJHt0b3RhbENvcGllZH0gZGVmYXVsdCBlbGVtZW50c2AsXG4gICAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgICAgcG9ydGZvbGlvQmFzZURpcixcbiAgICAgICAgICBkYXRhRGlyLFxuICAgICAgICAgIGNvcGllZENvdW50c1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgbG9nZ2VyLmluZm8oJ1tEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBObyBuZXcgZWxlbWVudHMgdG8gY29weSAtIHBvcnRmb2xpbyBtYXkgYWxyZWFkeSBoYXZlIGNvbnRlbnQnKTtcbiAgICB9XG4gIH1cbn0iXX0=
|
|
878
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRGVmYXVsdEVsZW1lbnRQcm92aWRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wb3J0Zm9saW8vRGVmYXVsdEVsZW1lbnRQcm92aWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLEtBQUssTUFBTSxNQUFNLElBQUksQ0FBQztBQUM3QixPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFFcEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDekMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFDOUUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ2pFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBRW5FLDJCQUEyQjtBQUMzQixNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUc7SUFDNUIsaUJBQWlCLEVBQUUsS0FBSztJQUN4QixjQUFjLEVBQUUsT0FBTztJQUN2QixhQUFhLEVBQUUsTUFBTTtJQUNyQixjQUFjLEVBQUUsT0FBTztJQUN2QixhQUFhLEVBQUUsRUFBRSxHQUFHLElBQUksR0FBRyxJQUFJLEVBQUUsZ0NBQWdDO0lBQ2pFLGtCQUFrQixFQUFFLFFBQVE7SUFDNUIsZ0JBQWdCLEVBQUUsS0FBSztJQUN2QixVQUFVLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxzQ0FBc0M7Q0FDcEQsQ0FBQztBQUVYLDZCQUE2QjtBQUM3QixzRUFBc0U7QUFDdEUsTUFBTSxtQkFBbUIsR0FBRyxD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WUFDdkYsQ0FBQztRQUNILENBQUM7UUFFRCxJQUFJLFdBQVcsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNwQixNQUFNLENBQUMsSUFBSSxDQUNULGtFQUFrRSxXQUFXLHFCQUFxQixFQUNsRztnQkFDRSxnQkFBZ0I7Z0JBQ2hCLE9BQU87Z0JBQ1AsU0FBUyxFQUFFLFlBQVk7YUFDeEIsQ0FDRixDQUFDO1lBRUYsK0NBQStDO1lBQy9DLGVBQWUsQ0FBQyxnQkFBZ0IsQ0FBQztnQkFDL0IsSUFBSSxFQUFFLHFCQUFxQjtnQkFDM0IsUUFBUSxFQUFFLEtBQUs7Z0JBQ2YsTUFBTSxFQUFFLDBDQUEwQztnQkFDbEQsT0FBTyxFQUFFLHlDQUF5QyxXQUFXLG1CQUFtQjtnQkFDaEYsUUFBUSxFQUFFO29CQUNSLGdCQUFnQjtvQkFDaEIsT0FBTztvQkFDUCxZQUFZO2lCQUNiO2FBQ0YsQ0FBQyxDQUFDO1FBQ0wsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLENBQUMsSUFBSSxDQUFDLHVGQUF1RixDQUFDLENBQUM7UUFDdkcsQ0FBQztJQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIERlZmF1bHRFbGVtZW50UHJvdmlkZXIgLSBQb3B1bGF0ZXMgcG9ydGZvbGlvIHdpdGggZGVmYXVsdCBlbGVtZW50cyBmcm9tIGJ1bmRsZWQgZGF0YVxuICogXG4gKiBUaGlzIGNsYXNzIGhhbmRsZXMgY29weWluZyBkZWZhdWx0IHBlcnNvbmFzLCBza2lsbHMsIHRlbXBsYXRlcywgYW5kIG90aGVyIGVsZW1lbnRzXG4gKiBmcm9tIHRoZSBOUE0gcGFja2FnZSBvciBHaXQgcmVwb3NpdG9yeSB0byB0aGUgdXNlcidzIHBvcnRmb2xpbyBvbiBmaXJzdCBydW4uXG4gKiBJdCBlbnN1cmVzIHVzZXJzIGhhdmUgZXhhbXBsZSBjb250ZW50IHRvIHdvcmsgd2l0aCBpbW1lZGlhdGVseSBhZnRlciBpbnN0YWxsYXRpb24uXG4gKi9cblxuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMvcHJvbWlzZXMnO1xuaW1wb3J0ICogYXMgZnNTeW5jIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBmaWxlVVJMVG9QYXRoIH0gZnJvbSAndXJsJztcbmltcG9ydCB7IGNyZWF0ZUhhc2ggfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0ICogYXMgeWFtbCBmcm9tICdqcy15YW1sJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBFbGVtZW50VHlwZSB9IGZyb20gJy4vdHlwZXMuanMnO1xuaW1wb3J0IHsgVW5pY29kZVZhbGlkYXRvciB9IGZyb20gJy4uL3NlY3VyaXR5L3ZhbGlkYXRvcnMvdW5pY29kZVZhbGlkYXRvci5qcyc7XG5pbXBvcnQgeyBTZWN1cml0eU1vbml0b3IgfSBmcm9tICcuLi9zZWN1cml0eS9zZWN1cml0eU1vbml0b3IuanMnO1xuaW1wb3J0IHsgU2VjdXJlWWFtbFBhcnNlciB9IGZyb20gJy4uL3NlY3VyaXR5L3NlY3VyZVlhbWxQYXJzZXIuanMnO1xuXG4vLyBGaWxlIG9wZXJhdGlvbiBjb25zdGFudHNcbmV4cG9ydCBjb25zdCBGSUxFX0NPTlNUQU5UUyA9IHtcbiAgRUxFTUVOVF9FWFRFTlNJT046ICcubWQnLFxuICBZQU1MX0VYVEVOU0lPTjogJy55YW1sJyxcbiAgWU1MX0VYVEVOU0lPTjogJy55bWwnLFxuICBKU09OX0VYVEVOU0lPTjogJy5qc29uJyxcbiAgTUFYX0ZJTEVfU0laRTogMTAgKiAxMDI0ICogMTAyNCwgLy8gMTBNQiBtYXggZmlsZSBzaXplIGZvciBzYWZldHlcbiAgQ0hFQ0tTVU1fQUxHT1JJVEhNOiAnc2hhMjU2JyxcbiAgRklMRV9QRVJNSVNTSU9OUzogMG82NDQsXG4gIENIVU5LX1NJWkU6IDY0ICogMTAyNCAvLyA2NEtCIGNodW5rcyBmb3IgcmVhZGluZyBsYXJnZSBmaWxlc1xufSBhcyBjb25zdDtcblxuLy8gRGV2ZWxvcG1lbnQgbW9kZSBkZXRlY3Rpb25cbi8vIFdoZW4gcnVubmluZyBmcm9tIGEgZ2l0IGNsb25lLCB3ZSBkb24ndCB3YW50IHRvIGF1dG8tbG9hZCB0ZXN0IGRhdGFcbmNvbnN0IElTX0RFVkVMT1BNRU5UX01PREUgPSAoKCkgPT4ge1xuICB0cnkge1xuICAgIC8vIENoZWNrIGlmIHdlJ3JlIGluIGEgZ2l0IHJlcG9zaXRvcnkgKGRldmVsb3BtZW50IG1vZGUpXG4gICAgY29uc3QgZ2l0RGlyID0gcGF0aC5qb2luKHByb2Nlc3MuY3dkKCksICcuZ2l0Jyk7XG4gICAgcmV0dXJuIGZzU3luYy5leGlzdHNTeW5jKGdpdERpcik7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufSkoKTtcblxuLy8gSW50ZXJuYWwgY29uc3RhbnRzXG5jb25zdCBEQVRBX0RJUl9DQUNIRV9LRVkgPSAnZG9sbGhvdXNlX2RhdGFfZGlyJztcbmNvbnN0IENPUFlfUkVUUllfQVRURU1QVFMgPSAzO1xuY29uc3QgQ09QWV9SRVRSWV9ERUxBWSA9IDEwMDsgLy8gbXNcblxuZXhwb3J0IGludGVyZmFjZSBEZWZhdWx0RWxlbWVudFByb3ZpZGVyQ29uZmlnIHtcbiAgLyoqIEN1c3RvbSBkYXRhIGRpcmVjdG9yeSBwYXRocyB0byBzZWFyY2ggKGNoZWNrZWQgYmVmb3JlIGRlZmF1bHQgcGF0aHMpICovXG4gIGN1c3RvbURhdGFQYXRocz86IHN0cmluZ1tdO1xuICAvKiogV2hldGhlciB0byB1c2UgZGVmYXVsdCBzZWFyY2ggcGF0aHMgYWZ0ZXIgY3VzdG9tIHBhdGhzICovXG4gIHVzZURlZmF1bHRQYXRocz86IGJvb2xlYW47XG4gIC8qKiBXaGV0aGVyIHRvIGxvYWQgdGVzdC9leGFtcGxlIGRhdGEgZnJvbSByZXBvc2l0b3J5IChkZWZhdWx0OiBmYWxzZSBpbiBkZXYgbW9kZSkgKi9cbiAgbG9hZFRlc3REYXRhPzogYm9vbGVhbjtcbn1cblxuLy8gUEVSRk9STUFOQ0U6IE1ldGFkYXRhIGNhY2hlIHdpdGggbXRpbWUtYmFzZWQgaW52YWxpZGF0aW9uXG5pbnRlcmZhY2UgTWV0YWRhdGFDYWNoZUVudHJ5IHtcbiAgbWV0YWRhdGE6IGFueTtcbiAgbXRpbWU6IG51bWJlcjtcbiAgc2l6ZTogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgRGVmYXVsdEVsZW1lbnRQcm92aWRlciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgX19kaXJuYW1lOiBzdHJpbmc7XG4gIHByaXZhdGUgc3RhdGljIGNhY2hlZERhdGFEaXI6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHN0YXRpYyBwb3B1bGF0ZUluUHJvZ3Jlc3M6IE1hcDxzdHJpbmcsIFByb21pc2U8dm9pZD4+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIHJlYWRvbmx5IGNvbmZpZzogRGVmYXVsdEVsZW1lbnRQcm92aWRlckNvbmZpZztcbiAgXG4gIC8vIFBFUkZPUk1BTkNFIE9QVElNSVpBVElPTjogQ2FjaGUgbWV0YWRhdGEgd2l0aCBmaWxlIG10aW1lIGZvciBpbnZhbGlkYXRpb25cbiAgcHJpdmF0ZSBzdGF0aWMgbWV0YWRhdGFDYWNoZTogTWFwPHN0cmluZywgTWV0YWRhdGFDYWNoZUVudHJ5PiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgTUFYX0NBQ0hFX1NJWkUgPSAyMDsgLy8gTUVNT1JZIExFQUsgRklYOiBGdXJ0aGVyIHJlZHVjZWQgY2FjaGUgc2l6ZSB0byBwcmV2ZW50IGFjY3VtdWxhdGlvbiBkdXJpbmcgcGVyZm9ybWFuY2UgdGVzdHNcbiAgXG4gIGNvbnN0cnVjdG9yKGNvbmZpZz86IERlZmF1bHRFbGVtZW50UHJvdmlkZXJDb25maWcpIHtcbiAgICBjb25zdCBfX2ZpbGVuYW1lID0gZmlsZVVSTFRvUGF0aChpbXBvcnQubWV0YS51cmwpO1xuICAgIHRoaXMuX19kaXJuYW1lID0gcGF0aC5kaXJuYW1lKF9fZmlsZW5hbWUpO1xuICAgIFxuICAgIC8vIENoZWNrIGVudmlyb25tZW50IHZhcmlhYmxlIGZvciB0ZXN0IGRhdGEgbG9hZGluZ1xuICAgIGNvbnN0IGVudkxvYWRUZXN0RGF0YSA9IHByb2Nlc3MuZW52LkRPTExIT1VTRV9MT0FEX1RFU1RfREFUQTtcbiAgICBjb25zdCBsb2FkVGVzdERhdGFGcm9tRW52ID0gZW52TG9hZFRlc3REYXRhID09PSAndHJ1ZScgfHwgZW52TG9hZFRlc3REYXRhID09PSAnMSc7XG4gICAgY29uc3QgZGlzYWJsZVRlc3REYXRhRnJvbUVudiA9IGVudkxvYWRUZXN0RGF0YSA9PT0gJ2ZhbHNlJyB8fCBlbnZMb2FkVGVzdERhdGEgPT09ICcwJztcbiAgICBcbiAgICAvLyBDaGVjayBpZiB3ZSdyZSBpbiBkZXZlbG9wbWVudCBtb2RlICh3aXRoIHJlc3BlY3QgdG8gRk9SQ0VfUFJPRFVDVElPTl9NT0RFIG92ZXJyaWRlKVxuICAgIGNvbnN0IGlzRGV2TW9kZSA9ICgoKSA9PiB7XG4gICAgICAvLyBSZXNwZWN0IEZPUkNFX1BST0RVQ1RJT05fTU9ERSBvdmVycmlkZSBmaXJzdFxuICAgICAgaWYgKHByb2Nlc3MuZW52LkZPUkNFX1BST0RVQ1RJT05fTU9ERSA9PT0gJ3RydWUnKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTsgLy8gRm9yY2UgcHJvZHVjdGlvbiBtb2RlXG4gICAgICB9XG4gICAgICBpZiAocHJvY2Vzcy5lbnYuRk9SQ0VfUFJPRFVDVElPTl9NT0RFID09PSAnZmFsc2UnKSB7XG4gICAgICAgIHJldHVybiB0cnVlOyAvLyBGb3JjZSBkZXZlbG9wbWVudCBtb2RlXG4gICAgICB9XG4gICAgICAvLyBGYWxsIGJhY2sgdG8gZ2l0IGRldGVjdGlvblxuICAgICAgcmV0dXJuIElTX0RFVkVMT1BNRU5UX01PREU7XG4gICAgfSkoKTtcbiAgICBcbiAgICAvLyBEZXRlcm1pbmUgbG9hZFRlc3REYXRhIHZhbHVlXG4gICAgbGV0IGNvbXB1dGVkTG9hZFRlc3REYXRhOiBib29sZWFuO1xuICAgIGlmIChsb2FkVGVzdERhdGFGcm9tRW52KSB7XG4gICAgICAvLyBFbnZpcm9ubWVudCBleHBsaWNpdGx5IGVuYWJsZXMgdGVzdCBkYXRhXG4gICAgICBjb21wdXRlZExvYWRUZXN0RGF0YSA9IHRydWU7XG4gICAgfSBlbHNlIGlmIChkaXNhYmxlVGVzdERhdGFGcm9tRW52KSB7XG4gICAgICAvLyBFbnZpcm9ubWVudCBleHBsaWNpdGx5IGRpc2FibGVzIHRlc3QgZGF0YVxuICAgICAgY29tcHV0ZWRMb2FkVGVzdERhdGEgPSBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRGVmYXVsdCBsb2dpYzogZW5hYmxlIGluIHByb2R1Y3Rpb24sIGRpc2FibGUgaW4gZGV2ZWxvcG1lbnQgdW5sZXNzIGNvbmZpZyBvdmVycmlkZXNcbiAgICAgIGNvbXB1dGVkTG9hZFRlc3REYXRhID0gIWlzRGV2TW9kZSAmJiAoY29uZmlnPy5sb2FkVGVzdERhdGEgPz8gdHJ1ZSk7XG4gICAgfVxuICAgIFxuICAgIHRoaXMuY29uZmlnID0ge1xuICAgICAgdXNlRGVmYXVsdFBhdGhzOiB0cnVlLFxuICAgICAgLi4uY29uZmlnLFxuICAgICAgLy8gQXBwbHkgZmluYWwgbG9hZFRlc3REYXRhIGxvZ2ljIC0gZW52aXJvbm1lbnQgdmFyaWFibGVzIGFuZCBkZXZlbG9wbWVudCBtb2RlIHRha2UgcHJlY2VkZW5jZVxuICAgICAgbG9hZFRlc3REYXRhOiBsb2FkVGVzdERhdGFGcm9tRW52ID8gdHJ1ZSA6IGRpc2FibGVUZXN0RGF0YUZyb21FbnYgPyBmYWxzZSA6IGNvbXB1dGVkTG9hZFRlc3REYXRhXG4gICAgfTtcbiAgICBcbiAgICBpZiAoaXNEZXZNb2RlICYmICF0aGlzLmNvbmZpZy5sb2FkVGVzdERhdGEpIHtcbiAgICAgIGxvZ2dlci5pbmZvKCdbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gRGV2ZWxvcG1lbnQgbW9kZSBkZXRlY3RlZCAtIHRlc3QgZGF0YSBsb2FkaW5nIGRpc2FibGVkJyk7XG4gICAgICBsb2dnZXIuaW5mbygnW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIFRvIGVuYWJsZSB0ZXN0IGRhdGEsIHNldCBET0xMSE9VU0VfTE9BRF9URVNUX0RBVEE9dHJ1ZScpO1xuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIEdldCB0aGUgY3VycmVudCBsb2FkVGVzdERhdGEgY29uZmlndXJhdGlvbiB2YWx1ZVxuICAgKiBAcmV0dXJucyBXaGV0aGVyIHRlc3QgZGF0YSBsb2FkaW5nIGlzIGVuYWJsZWRcbiAgICovXG4gIHB1YmxpYyBnZXQgaXNUZXN0RGF0YUxvYWRpbmdFbmFibGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmNvbmZpZy5sb2FkVGVzdERhdGEgPz8gZmFsc2U7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBHZXQgd2hldGhlciB0aGUgc3lzdGVtIGlzIGluIGRldmVsb3BtZW50IG1vZGVcbiAgICogQHJldHVybnMgV2hldGhlciBydW5uaW5nIGluIGRldmVsb3BtZW50IG1vZGVcbiAgICovXG4gIHB1YmxpYyBnZXQgaXNEZXZlbG9wbWVudE1vZGUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIElTX0RFVkVMT1BNRU5UX01PREU7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBTZWFyY2ggcGF0aHMgZm9yIGJ1bmRsZWQgZGF0YSBkaXJlY3RvcnlcbiAgICogT3JkZXJlZCBieSBwcmlvcml0eSAtIGN1c3RvbSBwYXRocyBmaXJzdCwgdGhlbiBkZXZlbG9wbWVudC9naXQsIHRoZW4gTlBNIGxvY2F0aW9uc1xuICAgKi9cbiAgcHJpdmF0ZSBnZXQgZGF0YVNlYXJjaFBhdGhzKCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBwYXRoczogc3RyaW5nW10gPSBbXTtcbiAgICBcbiAgICAvLyBBZGQgY3VzdG9tIHBhdGhzIGZpcnN0IChoaWdoZXN0IHByaW9yaXR5KVxuICAgIGlmICh0aGlzLmNvbmZpZy5jdXN0b21EYXRhUGF0aHMpIHtcbiAgICAgIHBhdGhzLnB1c2goLi4udGhpcy5jb25maWcuY3VzdG9tRGF0YVBhdGhzKTtcbiAgICB9XG4gICAgXG4gICAgLy8gQWRkIGRlZmF1bHQgcGF0aHMgaWYgZW5hYmxlZFxuICAgIGlmICh0aGlzLmNvbmZpZy51c2VEZWZhdWx0UGF0aHMgIT09IGZhbHNlKSB7XG4gICAgICAvLyBTa2lwIGRldmVsb3BtZW50L3JlcG9zaXRvcnkgZGF0YSBwYXRocyB1bmxlc3MgdGVzdCBkYXRhIGxvYWRpbmcgaXMgZW5hYmxlZFxuICAgICAgaWYgKHRoaXMuY29uZmlnLmxvYWRUZXN0RGF0YSkge1xuICAgICAgICAvLyBEZXZlbG9wbWVudC9HaXQgaW5zdGFsbGF0aW9uIChyZWxhdGl2ZSB0byB0aGlzIGZpbGUpXG4gICAgICAgIHBhdGhzLnB1c2goXG4gICAgICAgICAgcGF0aC5qb2luKHRoaXMuX19kaXJuYW1lLCAnLi4vLi4vZGF0YScpLFxuICAgICAgICAgIHBhdGguam9pbih0aGlzLl9fZGlybmFtZSwgJy4uLy4uLy4uL2RhdGEnKSxcbiAgICAgICAgICAvLyBDdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5IChsYXN0IHJlc29ydClcbiAgICAgICAgICBwYXRoLmpvaW4ocHJvY2Vzcy5jd2QoKSwgJ2RhdGEnKVxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBBbHdheXMgaW5jbHVkZSBOUE0gaW5zdGFsbGF0aW9uIHBhdGhzICh0aGVzZSB3b3VsZCBoYXZlIHByb2R1Y3Rpb24gZGF0YSlcbiAgICAgIHBhdGhzLnB1c2goXG4gICAgICAgIC8vIE5QTSBpbnN0YWxsYXRpb25zIC0gbWFjT1MgSG9tZWJyZXdcbiAgICAgICAgJy9vcHQvaG9tZWJyZXcvbGliL25vZGVfbW9kdWxlcy9AZG9sbGhvdXNlbWNwL21jcC1zZXJ2ZXIvZGF0YScsXG4gICAgICAgIFxuICAgICAgICAvLyBOUE0gaW5zdGFsbGF0aW9ucyAtIHN0YW5kYXJkIFVuaXgvTGludXhcbiAgICAgICAgJy91c3IvbG9jYWwvbGliL25vZGVfbW9kdWxlcy9AZG9sbGhvdXNlbWNwL21jcC1zZXJ2ZXIvZGF0YScsXG4gICAgICAgICcvdXNyL2xpYi9ub2RlX21vZHVsZXMvQGRvbGxob3VzZW1jcC9tY3Atc2VydmVyL2RhdGEnLFxuICAgICAgICBcbiAgICAgICAgLy8gTlBNIGluc3RhbGxhdGlvbnMgLSBXaW5kb3dzXG4gICAgICAgICdDOlxcXFxQcm9ncmFtIEZpbGVzXFxcXG5vZGVqc1xcXFxub2RlX21vZHVsZXNcXFxcQGRvbGxob3VzZW1jcFxcXFxtY3Atc2VydmVyXFxcXGRhdGEnLFxuICAgICAgICAnQzpcXFxcUHJvZ3JhbSBGaWxlcyAoeDg2KVxcXFxub2RlanNcXFxcbm9kZV9tb2R1bGVzXFxcXEBkb2xsaG91c2VtY3BcXFxcbWNwLXNlcnZlclxcXFxkYXRhJyxcbiAgICAgICAgXG4gICAgICAgIC8vIE5QTSBpbnN0YWxsYXRpb25zIC0gV2luZG93cyB3aXRoIG52bVxuICAgICAgICBwYXRoLmpvaW4ocHJvY2Vzcy5lbnYuQVBQREFUQSB8fCAnJywgJ25wbScsICdub2RlX21vZHVsZXMnLCAnQGRvbGxob3VzZW1jcCcsICdtY3Atc2VydmVyJywgJ2RhdGEnKVxuICAgICAgKTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIHBhdGhzO1xuICB9XG4gIFxuICAvKipcbiAgICogRmluZCB0aGUgYnVuZGxlZCBkYXRhIGRpcmVjdG9yeSBieSBjaGVja2luZyBlYWNoIHNlYXJjaCBwYXRoXG4gICAqIFVzZXMgUHJvbWlzZS5hbGxTZXR0bGVkIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2UgYW5kIGNhY2hlcyB0aGUgcmVzdWx0XG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGZpbmREYXRhRGlyZWN0b3J5KCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgIC8vIFJldHVybiBjYWNoZWQgdmFsdWUgaWYgYXZhaWxhYmxlXG4gICAgaWYgKERlZmF1bHRFbGVtZW50UHJvdmlkZXIuY2FjaGVkRGF0YURpciAhPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIERlZmF1bHRFbGVtZW50UHJvdmlkZXIuY2FjaGVkRGF0YURpcjtcbiAgICB9XG4gICAgXG4gICAgLy8gQ2hlY2sgYWxsIHBhdGhzIGluIHBhcmFsbGVsIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2VcbiAgICBjb25zdCBjaGVja1Byb21pc2VzID0gdGhpcy5kYXRhU2VhcmNoUGF0aHMubWFwKGFzeW5jIChzZWFyY2hQYXRoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBzdGF0cyA9IGF3YWl0IGZzLnN0YXQoc2VhcmNoUGF0aCk7XG4gICAgICAgIGlmIChzdGF0cy5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICAgICAgLy8gVmVyaWZ5IGl0IGNvbnRhaW5zIGV4cGVjdGVkIHN1YmRpcmVjdG9yaWVzXG4gICAgICAgICAgY29uc3QgaGFzUGVyc29uYXMgPSBhd2FpdCB0aGlzLmRpcmVjdG9yeUV4aXN0cyhwYXRoLmpvaW4oc2VhcmNoUGF0aCwgJ3BlcnNvbmFzJykpO1xuICAgICAgICAgIGNvbnN0IGhhc1NraWxscyA9IGF3YWl0IHRoaXMuZGlyZWN0b3J5RXhpc3RzKHBhdGguam9pbihzZWFyY2hQYXRoLCAnc2tpbGxzJykpO1xuICAgICAgICAgIGlmIChoYXNQZXJzb25hcyB8fCBoYXNTa2lsbHMpIHtcbiAgICAgICAgICAgIHJldHVybiBzZWFyY2hQYXRoO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgLy8gRGlyZWN0b3J5IGRvZXNuJ3QgZXhpc3Qgb3IgY2FuJ3QgYmUgYWNjZXNzZWRcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9KTtcbiAgICBcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKGNoZWNrUHJvbWlzZXMpO1xuICAgIFxuICAgIC8vIEZpbmQgdGhlIGZpcnN0IHN1Y2Nlc3NmdWwgcmVzdWx0XG4gICAgZm9yIChjb25zdCByZXN1bHQgb2YgcmVzdWx0cykge1xuICAgICAgaWYgKHJlc3VsdC5zdGF0dXMgPT09ICdmdWxmaWxsZWQnICYmIHJlc3VsdC52YWx1ZSAhPT0gbnVsbCkge1xuICAgICAgICBsb2dnZXIuaW5mbyhgW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIEZvdW5kIGRhdGEgZGlyZWN0b3J5IGF0OiAke3Jlc3VsdC52YWx1ZX1gKTtcbiAgICAgICAgLy8gQ2FjaGUgdGhlIHJlc3VsdFxuICAgICAgICBEZWZhdWx0RWxlbWVudFByb3ZpZGVyLmNhY2hlZERhdGFEaXIgPSByZXN1bHQudmFsdWU7XG4gICAgICAgIHJldHVybiByZXN1bHQudmFsdWU7XG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIGxvZ2dlci53YXJuKCdbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gTm8gYnVuZGxlZCBkYXRhIGRpcmVjdG9yeSBmb3VuZCBpbiBhbnkgc2VhcmNoIHBhdGgnKTtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEhlbHBlciB0byBjaGVjayBpZiBhIGRpcmVjdG9yeSBleGlzdHNcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZGlyZWN0b3J5RXhpc3RzKGRpclBhdGg6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBzdGF0cyA9IGF3YWl0IGZzLnN0YXQoZGlyUGF0aCk7XG4gICAgICByZXR1cm4gc3RhdHMuaXNEaXJlY3RvcnkoKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgZmlsZSBwYXRoIHRvIHByZXZlbnQgcGF0aCB0cmF2ZXJzYWwgYXR0YWNrc1xuICAgKiBTRUNVUklUWSBGSVg6IEFkZGVkIGZpbGUgcGF0aCB2YWxpZGF0aW9uIHRvIHByZXZlbnQgZGlyZWN0b3J5IHRyYXZlcnNhbFxuICAgKiBQcmV2aW91c2x5OiBGaWxlIHBhdGhzIHdlcmUgdXNlZCB3aXRob3V0IHZhbGlkYXRpb24sIGFsbG93aW5nIHBvdGVudGlhbCAuLi8uLi8uLi8gYXR0YWNrc1xuICAgKiBOb3c6IFN0cmljdCB2YWxpZGF0aW9uIGVuc3VyZXMgcGF0aHMgc3RheSB3aXRoaW4gYWxsb3dlZCBkaXJlY3Rvcmllc1xuICAgKiBAcGFyYW0gZmlsZVBhdGggVGhlIGZpbGUgcGF0aCB0byB2YWxpZGF0ZVxuICAgKiBAcGFyYW0gYWxsb3dlZEJhc2VQYXRocyBBcnJheSBvZiBhbGxvd2VkIGJhc2UgcGF0aHMgKG9wdGlvbmFsKVxuICAgKiBAcmV0dXJucyB0cnVlIGlmIHBhdGggaXMgc2FmZSwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlRmlsZVBhdGgoZmlsZVBhdGg6IHN0cmluZywgYWxsb3dlZEJhc2VQYXRocz86IHN0cmluZ1tdKTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIFNFQ1VSSVRZOiBOb3JtYWxpemUgcGF0aCB0byBwcmV2ZW50IHRyYXZlcnNhbCBhdHRlbXB0c1xuICAgICAgY29uc3Qgbm9ybWFsaXplZFBhdGggPSBwYXRoLm5vcm1hbGl6ZShmaWxlUGF0aCk7XG4gICAgICBcbiAgICAgIC8vIFNFQ1VSSVRZOiBSZWplY3QgcGF0aHMgY29udGFpbmluZyB0cmF2ZXJzYWwgcGF0dGVybnNcbiAgICAgIGlmIChub3JtYWxpemVkUGF0aC5pbmNsdWRlcygnLi4nKSkge1xuICAgICAgICBsb2dnZXIud2FybihgW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIFBhdGggdHJhdmVyc2FsIGF0dGVtcHQgYmxvY2tlZDogJHtmaWxlUGF0aH1gKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBTRUNVUklUWTogQ2hlY2sgZm9yIGhvbWUgZGlyZWN0b3J5IGV4cGFuc2lvbiBhdHRlbXB0cywgYnV0IGFsbG93IFdpbmRvd3MgOC4zIHNob3J0IHBhdGggbmFtZXNcbiAgICAgIC8vIFdpbmRvd3Mgc2hvcnQgcGF0aCBuYW1lcyB1c2UgfiBmb2xsb3dlZCBieSBhIGRpZ2l0IChlLmcuLCBSVU5ORVJ+MSksIHdoaWNoIHNob3VsZCBiZSBhbGxvd2VkXG4gICAgICAvLyBPbmx5IGJsb2NrIH4gZm9sbG93ZWQgYnkgLyBvciBcXCAoaG9tZSBkaXJlY3RvcnkgZXhwYW5zaW9uIHBhdHRlcm5zKVxuICAgICAgaWYgKG5vcm1hbGl6ZWRQYXRoLmluY2x1ZGVzKCd+LycpIHx8IG5vcm1hbGl6ZWRQYXRoLmluY2x1ZGVzKCd+XFxcXCcpKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gSG9tZSBkaXJlY3RvcnkgZXhwYW5zaW9uIGF0dGVtcHQgYmxvY2tlZDogJHtmaWxlUGF0aH1gKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBTRUNVUklUWTogUmVqZWN0IGFic29sdXRlIHBhdGhzIG91dHNpZGUgYWxsb3dlZCBkaXJlY3Rvcmllc1xuICAgICAgaWYgKHBhdGguaXNBYnNvbHV0ZShub3JtYWxpemVkUGF0aCkgJiYgYWxsb3dlZEJhc2VQYXRocykge1xuICAgICAgICBjb25zdCBpc0FsbG93ZWQgPSBhbGxvd2VkQmFzZVBhdGhzLnNvbWUoYmFzZVBhdGggPT4ge1xuICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRCYXNlID0gcGF0aC5ub3JtYWxpemUoYmFzZVBhdGgpO1xuICAgICAgICAgIHJldHVybiBub3JtYWxpemVkUGF0aC5zdGFydHNXaXRoKG5vcm1hbGl6ZWRCYXNlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIFxuICAgICAgICBpZiAoIWlzQWxsb3dlZCkge1xuICAgICAgICAgIGxvZ2dlci53YXJuKGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gQWJzb2x1dGUgcGF0aCBvdXRzaWRlIGFsbG93ZWQgZGlyZWN0b3JpZXM6ICR7ZmlsZVBhdGh9YCk7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIFNFQ1VSSVRZOiBSZWplY3QgbnVsbCBieXRlcyBhbmQgb3RoZXIgZGFuZ2Vyb3VzIGNoYXJhY3RlcnNcbiAgICAgIGlmIChub3JtYWxpemVkUGF0aC5pbmNsdWRlcygnXFwwJykgfHwgbm9ybWFsaXplZFBhdGguaW5jbHVkZXMoJ1xceDAwJykpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBOdWxsIGJ5dGUgaW4gcGF0aCBibG9ja2VkOiAke2ZpbGVQYXRofWApO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIud2FybihgW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIFBhdGggdmFsaWRhdGlvbiBlcnJvcjogJHtlcnJvcn1gKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvLyBERVBSRUNBVEVEOiBDb21tZW50ZWQgb3V0IGZpbGVuYW1lIHBhdHRlcm4gZGV0ZWN0aW9uIC0gcmVwbGFjZWQgd2l0aCBtZXRhZGF0YS1iYXNlZCBkZXRlY3Rpb25cbiAgLyoqXG4gICAqIENhY2hlZCBjb21waWxlZCByZWdleCBwYXR0ZXJucyBmb3IgcGVyZm9ybWFuY2Ugb3B0aW1pemF0aW9uXG4gICAqIEBkZXByZWNhdGVkIFVzZSBtZXRhZGF0YS1iYXNlZCBkZXRlY3Rpb24gaW5zdGVhZFxuICAgKi9cbiAgLy8gcHJpdmF0ZSBzdGF0aWMgY29tcGlsZWRUZXN0UGF0dGVybnM6IFJlZ0V4cFtdIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqXG4gICAqIEdldCBjb21waWxlZCB0ZXN0IHBhdHRlcm5zIHdpdGggY2FjaGluZyBmb3IgYmV0dGVyIHBlcmZvcm1hbmNlXG4gICAqIEBkZXByZWNhdGVkIFVzZSBtZXRhZGF0YS1iYXNlZCBkZXRlY3Rpb24gaW5zdGVhZFxuICAgKiBAcmV0dXJucyBBcnJheSBvZiBjb21waWxlZCByZWdleCBwYXR0ZXJuc1xuICAgKi9cbiAgLy8gcHJpdmF0ZSBnZXRDb21waWxlZFRlc3RQYXR0ZXJucygpOiBSZWdFeHBbXSB7XG4gIC8vICAgLy8gVXNlIGNhY2hlZCBwYXR0ZXJucyBpZiBhdmFpbGFibGVcbiAgLy8gICBpZiAoRGVmYXVsdEVsZW1lbnRQcm92aWRlci5jb21waWxlZFRlc3RQYXR0ZXJucykge1xuICAvLyAgICAgcmV0dXJuIERlZmF1bHRFbGVtZW50UHJvdmlkZXIuY29tcGlsZWRUZXN0UGF0dGVybnM7XG4gIC8vICAgfVxuICAvLyAgIFxuICAvLyAgIC8vIENvbXBpbGUgYW5kIGNhY2hlIHBhdHRlcm5zIG9uIGZpcnN0IHVzZVxuICAvLyAgIC8vIENSSVRJQ0FMIEZJWDogUmVtb3ZlZCBvdmVybHkgYnJvYWQgL150ZXN0LS9pIHBhdHRlcm4gdGhhdCB3YXMgYmxvY2tpbmcgbGVnaXRpbWF0ZSB1c2VcbiAgLy8gICAvLyBVc2VycyBzaG91bGQgYmUgYWJsZSB0byBjcmVhdGUgcGVyc29uYXMgbGlrZSBcInRlc3QtZHJpdmVuLWRldmVsb3BlclwiIG9yIFwidGVzdC1hdXRvbWF0aW9uLWV4cGVydFwiXG4gIC8vICAgLy8gV2Ugb25seSBibG9jayBzcGVjaWZpYyB0ZXN0IHBhdHRlcm5zIHRoYXQgYXJlIGNsZWFybHkgZnJvbSBvdXIgdGVzdCBzdWl0ZVxuICAvLyAgIERlZmF1bHRFbGVtZW50UHJvdmlkZXIuY29tcGlsZWRUZXN0UGF0dGVybnMgPSBbXG4gIC8vICAgICAvXnRlc3RwZXJzb25hL2ksICAgICAgICAgICAgICAvLyBPdXIgdGVzdCBzdWl0ZSBwYXR0ZXJuXG4gIC8vICAgICAvXnlhbWx0ZXN0L2ksICAgICAgICAgICAgICAgICAvLyBTZWN1cml0eSB0ZXN0IHBhdHRlcm5cbiAgLy8gICAgIC9eeWFtbGJvbWIvaSwgICAgICAgICAgICAgICAgIC8vIFNlY3VyaXR5IHRlc3QgcGF0dGVyblxuICAvLyAgICAgL15tZW1vcnktdGVzdC0vaSwgICAgICAgICAgICAgLy8gUGVyZm9ybWFuY2UgdGVzdCBwYXR0ZXJuXG4gIC8vICAgICAvXnBlcmYtdGVzdC0vaSwgICAgICAgICAgICAgICAvLyBQZXJmb3JtYW5jZSB0ZXN0IHBhdHRlcm5cbiAgLy8gICAgIC9edGVzdC1maXh0dXJlLS9pLCAgICAgICAgICAgIC8vIFRlc3QgZml4dHVyZSBwYXR0ZXJuIChtb3JlIHNwZWNpZmljKVxuICAvLyAgICAgL150ZXN0LWRhdGEtL2ksICAgICAgICAgICAgICAgLy8gVGVzdCBkYXRhIHBhdHRlcm4gKG1vcmUgc3BlY2lmaWMpXG4gIC8vICAgICAvYmluLXNofHJtLXJmfHB3bmVkL2ksICAgICAgICAvLyBNYWxpY2lvdXMgcGF0dGVybnNcbiAgLy8gICAgIC9jb25jdXJyZW50LVxcZCsvaSwgICAgICAgICAgICAvLyBDb25jdXJyZW50IHRlc3QgcGF0dGVyblxuICAvLyAgICAgL2xlZ2FjeVxcLm1kJC9pLCAgICAgICAgICAgICAgIC8vIExlZ2FjeSB0ZXN0IHBhdHRlcm5cbiAgLy8gICAgIC9wZXJmb3JtYW5jZS10ZXN0L2ksICAgICAgICAgIC8vIFBlcmZvcm1hbmNlIHRlc3QgcGF0dGVyblxuICAvLyAgICAgLy1cXGR7MTN9LVthLXowLTldK1xcLm1kJC9pLCAgICAvLyBUaW1lc3RhbXAtYmFzZWQgdGVzdCBmaWxlc1xuICAvLyAgICAgL151bml0dGVzdC0vaSwgICAgICAgICAgICAgICAgLy8gVW5pdCB0ZXN0IHBhdHRlcm5cbiAgLy8gICAgIC9eaW50ZWdyYXRpb250ZXN0LS9pLCAgICAgICAgIC8vIEludGVncmF0aW9uIHRlc3QgcGF0dGVyblxuICAvLyAgIF07XG4gIC8vICAgXG4gIC8vICAgcmV0dXJuIERlZmF1bHRFbGVtZW50UHJvdmlkZXIuY29tcGlsZWRUZXN0UGF0dGVybnM7XG4gIC8vIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgYSBmaWxlbmFtZSBtYXRjaGVzIHRlc3QgZGF0YSBwYXR0ZXJucyB0aGF0IHNob3VsZCBuZXZlciBiZSBjb3BpZWQgdG8gcHJvZHVjdGlvblxuICAgKiBAZGVwcmVjYXRlZCBVc2UgaXNEb2xsaG91c2VNQ1BUZXN0RWxlbWVudCgpIGZvciBtZXRhZGF0YS1iYXNlZCBkZXRlY3Rpb24gaW5zdGVhZFxuICAgKiBAcGFyYW0gZmlsZW5hbWUgVGhlIGZpbGVuYW1lIHRvIGNoZWNrXG4gICAqIEByZXR1cm5zIHRydWUgaWYgdGhlIGZpbGVuYW1lIG1hdGNoZXMgdGVzdCBwYXR0ZXJucyB0aGF0IHNob3VsZCBiZSBibG9ja2VkXG4gICAqL1xuICAvLyBwcml2YXRlIGlzVGVzdERhdGFQYXR0ZXJuKGZpbGVuYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgLy8gICBjb25zdCBwYXR0ZXJucyA9IHRoaXMuZ2V0Q29tcGlsZWRUZXN0UGF0dGVybnMoKTtcbiAgLy8gICByZXR1cm4gcGF0dGVybnMuc29tZShwYXR0ZXJuID0+IHBhdHRlcm4udGVzdChmaWxlbmFtZSkpO1xuICAvLyB9XG5cbiAgLyoqXG4gICAqIFJlYWQgbWV0YWRhdGEgZnJvbSBZQU1MIGZyb250bWF0dGVyIG9ubHkgKG5ldmVyIHJlYWRzIGNvbnRlbnQgYm9keSlcbiAgICogVXNlcyBhIHNtYWxsIGJ1ZmZlciB0byBzYWZlbHkgZXh0cmFjdCBvbmx5IHRoZSBmcm9udG1hdHRlciBiZXR3ZWVuIC0tLSBtYXJrZXJzXG4gICAqIEBwYXJhbSBmaWxlUGF0aCBQYXRoIHRvIHRoZSBmaWxlIHRvIHJlYWQgbWV0YWRhdGEgZnJvbVxuICAgKiBAcmV0dXJucyBQYXJzZWQgbWV0YWRhdGEgb2JqZWN0IG9yIG51bGwgaWYgbm8gZnJvbnRtYXR0ZXIgZm91bmRcbiAgICovXG4gIC8vIFBFUkZPUk1BTkNFIE9QVElNSVpBVElPTjogUmV1c2FibGUgYnVmZmVyIHBvb2wgdG8gcmVkdWNlIGFsbG9jYXRpb25zXG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IGJ1ZmZlclBvb2w6IEJ1ZmZlcltdID0gW107XG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IE1BWF9QT09MX1NJWkUgPSAyMDsgLy8gTUVNT1JZIExFQUsgRklYOiBSZWR1Y2VkIGJ1ZmZlciBwb29sIHNpemUgdG8gbWF0Y2ggY2FjaGUgc2l6ZSBmb3IgY29uc2lzdGVudCBtZW1vcnkgbWFuYWdlbWVudFxuICBwcml2YXRlIHN0YXRpYyBidWZmZXJQb29sU3RhdHMgPSB7IGhpdHM6IDAsIG1pc3NlczogMCwgY3JlYXRlZDogMCB9O1xuICBcbiAgcHJpdmF0ZSBnZXRCdWZmZXIoKTogQnVmZmVyIHtcbiAgICAvLyBQRVJGT1JNQU5DRTogVHJhY2sgYnVmZmVyIHBvb2wgdXNhZ2UgZm9yIG9wdGltaXphdGlvbiBtb25pdG9yaW5nXG4gICAgbGV0IGJ1ZmZlciA9IERlZmF1bHRFbGVtZW50UHJvdmlkZXIuYnVmZmVyUG9vbC5wb3AoKTtcbiAgICBpZiAoYnVmZmVyKSB7XG4gICAgICBEZWZhdWx0RWxlbWVudFByb3ZpZGVyLmJ1ZmZlclBvb2xTdGF0cy5oaXRzKys7XG4gICAgICByZXR1cm4gYnVmZmVyO1xuICAgIH0gZWxzZSB7XG4gICAgICBEZWZhdWx0RWxlbWVudFByb3ZpZGVyLmJ1ZmZlclBvb2xTdGF0cy5taXNzZXMrKztcbiAgICAgIERlZmF1bHRFbGVtZW50UHJvdmlkZXIuYnVmZmVyUG9vbFN0YXRzLmNyZWF0ZWQrKztcbiAgICAgIGJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyg0MDk2KTtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhgW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIENyZWF0ZWQgbmV3IGJ1ZmZlciAocG9vbCBlbXB0eSksIHRvdGFsIGNyZWF0ZWQ6ICR7RGVmYXVsdEVsZW1lbnRQcm92aWRlci5idWZmZXJQb29sU3RhdHMuY3JlYXRlZH1gKTtcbiAgICAgIHJldHVybiBidWZmZXI7XG4gICAgfVxuICB9XG4gIFxuICBwcml2YXRlIHJlbGVhc2VCdWZmZXIoYnVmZmVyOiBCdWZmZXIpOiB2b2lkIHtcbiAgICAvLyBDUklUSUNBTCBGSVg6IEFsd2F5cyBhdHRlbXB0IHRvIHJldHVybiBidWZmZXIgdG8gcG9vbCBmb3IgcmV1c2VcbiAgICBpZiAoRGVmYXVsdEVsZW1lbnRQcm92aWRlci5idWZmZXJQb29sLmxlbmd0aCA8IERlZmF1bHRFbGVtZW50UHJvdmlkZXIuTUFYX1BPT0xfU0laRSkge1xuICAgICAgYnVmZmVyLmZpbGwoMCk7IC8vIFNFQ1VSSVRZOiBDbGVhciBidWZmZXIgYmVmb3JlIHJldXNlIHRvIHByZXZlbnQgZGF0YSBsZWFrYWdlXG4gICAgICBEZWZhdWx0RWxlbWVudFByb3ZpZGVyLmJ1ZmZlclBvb2wucHVzaChidWZmZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBQRVJGT1JNQU5DRTogSWYgcG9vbCBpcyBmdWxsLCBjbGVhciB0aGUgYnVmZmVyIHRvIGhlbHAgR0NcbiAgICAgIGJ1ZmZlci5maWxsKDApO1xuICAgICAgbG9nZ2VyLmRlYnVnKCdbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gQnVmZmVyIHBvb2wgZnVsbCwgZGlzY2FyZGluZyBidWZmZXInKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2xlYW4gdXAgYnVmZmVyIHBvb2wgYW5kIGNhY2hlIHRvIGZyZWUgbWVtb3J5XG4gICAqIFBFUkZPUk1BTkNFIEZJWDogQWRkZWQgY2xlYW51cCBtZXRob2QgdG8gcHJldmVudCBtZW1vcnkgbGVha3NcbiAgICogVGhpcyBzaG91bGQgYmUgY2FsbGVkIGR1cmluZyBhcHBsaWNhdGlvbiBzaHV0ZG93biBvciBwZXJpb2RpYyBjbGVhbnVwXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNsZWFudXAoKTogdm9pZCB7XG4gICAgLy8gQ2xlYXIgYnVmZmVyIHBvb2xcbiAgICBEZWZhdWx0RWxlbWVudFByb3ZpZGVyLmJ1ZmZlclBvb2wubGVuZ3RoID0gMDtcbiAgICBcbiAgICAvLyBDbGVhciBtZXRhZGF0YSBjYWNoZVxuICAgIERlZmF1bHRFbGVtZW50UHJvdmlkZXIubWV0YWRhdGFDYWNoZS5jbGVhcigpO1xuICAgIFxuICAgIC8vIENsZWFyIGNhY2hlZCBkYXRhIGRpcmVjdG9yeVxuICAgIERlZmF1bHRFbGVtZW50UHJvdmlkZXIuY2FjaGVkRGF0YURpciA9IG51bGw7XG4gICAgXG4gICAgLy8gQ2xlYXIgcG9wdWxhdGlvbiBwcm9taXNlc1xuICAgIERlZmF1bHRFbGVtZW50UHJvdmlkZXIucG9wdWxhdGVJblByb2dyZXNzLmNsZWFyKCk7XG4gICAgXG4gICAgbG9nZ2VyLmluZm8oJ1tEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBNZW1vcnkgY2xlYW51cCBjb21wbGV0ZWQnLCB7XG4gICAgICBidWZmZXJTdGF0czogRGVmYXVsdEVsZW1lbnRQcm92aWRlci5idWZmZXJQb29sU3RhdHMsXG4gICAgICBjYWNoZUNsZWFyZWQ6IHRydWVcbiAgICB9KTtcbiAgICBcbiAgICAvLyBSZXNldCBzdGF0c1xuICAgIERlZmF1bHRFbGVtZW50UHJvdmlkZXIuYnVmZmVyUG9vbFN0YXRzID0geyBoaXRzOiAwLCBtaXNzZXM6IDAsIGNyZWF0ZWQ6IDAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgcGVyZm9ybWFuY2Ugc3RhdGlzdGljcyBmb3IgbW9uaXRvcmluZ1xuICAgKiBQRVJGT1JNQU5DRSBNT05JVE9SSU5HOiBBZGRlZCBzdGF0aXN0aWNzIG1ldGhvZCBmb3IgcGVyZm9ybWFuY2UgdHJhY2tpbmdcbiAgICogVGhpcyBwcm92aWRlcyBpbnNpZ2h0cyBpbnRvIGJ1ZmZlciBwb29sIGVmZmljaWVuY3kgYW5kIGNhY2hlIHBlcmZvcm1hbmNlXG4gICAqIEByZXR1cm5zIE9iamVjdCBjb250YWluaW5nIHBlcmZvcm1hbmNlIG1ldHJpY3NcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZ2V0UGVyZm9ybWFuY2VTdGF0cygpOiB7XG4gICAgYnVmZmVyUG9vbDoge1xuICAgICAgaGl0czogbnVtYmVyO1xuICAgICAgbWlzc2VzOiBudW1iZXI7IFxuICAgICAgY3JlYXRlZDogbnVtYmVyO1xuICAgICAgaGl0UmF0ZTogbnVtYmVyO1xuICAgICAgcG9vbFNpemU6IG51bWJlcjtcbiAgICAgIG1heFBvb2xTaXplOiBudW1iZXI7XG4gICAgfTtcbiAgICBtZXRhZGF0YUNhY2hlOiB7XG4gICAgICBzaXplOiBudW1iZXI7XG4gICAgICBtYXhTaXplOiBudW1iZXI7XG4gICAgfTtcbiAgfSB7XG4gICAgY29uc3QgYnVmZmVySGl0cyA9IERlZmF1bHRFbGVtZW50UHJvdmlkZXIuYnVmZmVyUG9vbFN0YXRzLmhpdHM7XG4gICAgY29uc3QgYnVmZmVyTWlzc2VzID0gRGVmYXVsdEVsZW1lbnRQcm92aWRlci5idWZmZXJQb29sU3RhdHMubWlzc2VzO1xuICAgIGNvbnN0IHRvdGFsUmVxdWVzdHMgPSBidWZmZXJIaXRzICsgYnVmZmVyTWlzc2VzO1xuICAgIFxuICAgIHJldHVybiB7XG4gICAgICBidWZmZXJQb29sOiB7XG4gICAgICAgIGhpdHM6IGJ1ZmZlckhpdHMsXG4gICAgICAgIG1pc3NlczogYnVmZmVyTWlzc2VzLFxuICAgICAgICBjcmVhdGVkOiBEZWZhdWx0RWxlbWVudFByb3ZpZGVyLmJ1ZmZlclBvb2xTdGF0cy5jcmVhdGVkLFxuICAgICAgICBoaXRSYXRlOiB0b3RhbFJlcXVlc3RzID4gMCA/IGJ1ZmZlckhpdHMgLyB0b3RhbFJlcXVlc3RzIDogMCxcbiAgICAgICAgcG9vbFNpemU6IERlZmF1bHRFbGVtZW50UHJvdmlkZXIuYnVmZmVyUG9vbC5sZW5ndGgsXG4gICAgICAgIG1heFBvb2xTaXplOiBEZWZhdWx0RWxlbWVudFByb3ZpZGVyLk1BWF9QT09MX1NJWkVcbiAgICAgIH0sXG4gICAgICBtZXRhZGF0YUNhY2hlOiB7XG4gICAgICAgIHNpemU6IERlZmF1bHRFbGVtZW50UHJvdmlkZXIubWV0YWRhdGFDYWNoZS5zaXplLFxuICAgICAgICBtYXhTaXplOiBEZWZhdWx0RWxlbWVudFByb3ZpZGVyLk1BWF9DQUNIRV9TSVpFXG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcmVhZE1ldGFkYXRhT25seShmaWxlUGF0aDogc3RyaW5nLCByZXRyaWVzID0gMik6IFByb21pc2U8YW55IHwgbnVsbD4ge1xuICAgIC8vIFBFUkZPUk1BTkNFOiBDaGVjayBjYWNoZSBmaXJzdCBiZWZvcmUgcmVhZGluZyBmaWxlXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHN0YXRzID0gYXdhaXQgZnMuc3RhdChmaWxlUGF0aCk7XG4gICAgICBjb25zdCBjYWNoZUtleSA9IGZpbGVQYXRoO1xuICAgICAgY29uc3QgY2FjaGVkID0gRGVmYXVsdEVsZW1lbnRQcm92aWRlci5tZXRhZGF0YUNhY2hlLmdldChjYWNoZUtleSk7XG4gICAgICBcbiAgICAgIC8vIFJldHVybiBjYWNoZWQgbWV0YWRhdGEgaWYgZmlsZSBoYXNuJ3QgY2hhbmdlZCBcbiAgICAgIC8vIENSSVRJQ0FMIEZJWDogVXNlIGludGVnZXIgbXRpbWUgY29tcGFyaXNvbiB0byBhdm9pZCBmbG9hdGluZy1wb2ludCBwcmVjaXNpb24gaXNzdWVzXG4gICAgICBpZiAoY2FjaGVkICYmIE1hdGguZmxvb3IoY2FjaGVkLm10aW1lKSA9PT0gTWF0aC5mbG9vcihzdGF0cy5tdGltZU1zKSAmJiBjYWNoZWQuc2l6ZSA9PT0gc3RhdHMuc2l6ZSkge1xuICAgICAgICBsb2dnZXIuZGVidWcoYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBDYWNoZSBoaXQgZm9yICR7ZmlsZVBhdGh9YCk7XG4gICAgICAgIHJldHVybiBjYWNoZWQubWV0YWRhdGE7XG4gICAgICB9XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBGaWxlIGRvZXNuJ3QgZXhpc3QsIHByb2NlZWQgd2l0aCBub3JtYWwgZmxvd1xuICAgIH1cbiAgICBcbiAgICB0cnkge1xuICAgICAgLy8gT3BlbiBmaWxlIGFuZCByZWFkIG9ubHkgZmlyc3QgNEtCIHRvIGF2b2lkIHJlYWRpbmcgZGFuZ2Vyb3VzIGNvbnRlbnRcbiAgICAgIGNvbnN0IGZkID0gYXdhaXQgZnMub3BlbihmaWxlUGF0aCwgJ3InKTtcbiAgICAgIC8vIFBFUkZPUk1BTkNFOiBVc2UgYnVmZmVyIHBvb2wgaW5zdGVhZCBvZiBhbGxvY2F0aW5nIG5ldyBidWZmZXIgZWFjaCB0aW1lXG4gICAgICBjb25zdCBidWZmZXIgPSB0aGlzLmdldEJ1ZmZlcigpO1xuICAgICAgXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBmZC5yZWFkKGJ1ZmZlciwgMCwgNDA5NiwgMCk7XG4gICAgICAgIGNvbnN0IGhlYWRlciA9IGJ1ZmZlci5zdWJhcnJheSgwLCByZXN1bHQuYnl0ZXNSZWFkKS50b1N0cmluZygndXRmLTgnKTtcbiAgICAgICAgXG4gICAgICAgIC8vIExvb2sgZm9yIFlBTUwgZnJvbnRtYXR0ZXIgYmV0d2VlbiAtLS0gbWFya2Vyc1xuICAgICAgICAvLyBTdXBwb3J0IGJvdGggVW5peCAoXFxuKSBhbmQgV2luZG93cyAoXFxyXFxuKSBsaW5lIGVuZGluZ3NcbiAgICAgICAgY29uc3QgbWF0Y2ggPSBoZWFkZXIubWF0Y2goL14tLS1cXHI/XFxuKFtcXHNcXFNdKj8pXFxyP1xcbi0tLS8pO1xuICAgICAgICBpZiAoIW1hdGNoKSB7XG4gICAgICAgICAgcmV0dXJuIG51bGw7IC8vIE5vIGZyb250bWF0dGVyIGZvdW5kXG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIC8vIFBhcnNlIHRoZSBZQU1MIGZyb250bWF0dGVyIHNhZmVseVxuICAgICAgICB0cnkge1xuICAgICAgICAgIC8vIFNFQ1VSSVRZIEZJWDogUmVwbGFjZSBkaXJlY3QgWUFNTCBwYXJzaW5nIGZ1bmN0aW9uIHdpdGggU2VjdXJlWWFtbFBhcnNlciBmb3IgZW5oYW5jZWQgc2VjdXJpdHlcbiAgICAgICAgICAvLyBTZWN1cmVZYW1sUGFyc2VyIHByb3ZpZGVzIGFkZGl0aW9uYWwgdmFsaWRhdGlvbiwgaW5qZWN0aW9uIHByZXZlbnRpb24sIGFuZCBjb250ZW50IHNhbml0aXphdGlvblxuICAgICAgICAgIC8vIEl0IGV4cGVjdHMgZnVsbCBZQU1MIHdpdGggLS0tIG1hcmtlcnMsIHNvIHdlIHJlY29uc3RydWN0IHRoZSBmcm9udG1hdHRlciBibG9ja1xuICAgICAgICAgIC8vIFdlIGRpc2FibGUgc3BlY2lmaWMgZmllbGQgdmFsaWRhdGlvbiBhcyB0aGlzIGlzIGdlbmVyYWwgbWV0YWRhdGEgcGFyc2luZywgbm90IHBlcnNvbmEtc3BlY2lmaWNcbiAgICAgICAgICBjb25zdCBmdWxsWWFtbCA9IGAtLS1cXG4ke21hdGNoWzFdfVxcbi0tLWA7XG4gICAgICAgICAgY29uc3QgcGFyc2VSZXN1bHQgPSBTZWN1cmVZYW1sUGFyc2VyLnBhcnNlKGZ1bGxZYW1sLCB7IFxuICAgICAgICAgICAgdmFsaWRhdGVDb250ZW50OiBmYWxzZSwgXG4gICAgICAgICAgICB2YWxpZGF0ZUZpZWxkczogZmFsc2UgXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgY29uc3QgbWV0YWRhdGEgPSBwYXJzZVJlc3VsdC5kYXRhO1xuICAgICAgICAgIFxuICAgICAgICAgIC8vIFBFUkZPUk1BTkNFOiBDYWNoZSB0aGUgbWV0YWRhdGEgd2l0aCBmaWxlIHN0YXRzIGZvciBmdXR1cmUgcmVhZHNcbiAgICAgICAgICBpZiAodHlwZW9mIG1ldGFkYXRhID09PSAnb2JqZWN0JyAmJiBtZXRhZGF0YSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgY29uc3Qgc3RhdHMgPSBhd2FpdCBmcy5zdGF0KGZpbGVQYXRoKTtcbiAgICAgICAgICAgICAgY29uc3QgY2FjaGVFbnRyeTogTWV0YWRhdGFDYWNoZUVudHJ5ID0ge1xuICAgICAgICAgICAgICAgIG1ldGFkYXRhLFxuICAgICAgICAgICAgICAgIG10aW1lOiBzdGF0cy5tdGltZU1zLFxuICAgICAgICAgICAgICAgIHNpemU6IHN0YXRzLnNpemVcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgIC8vIENSSVRJQ0FMIE1FTU9SWSBMRUFLIEZJWDogTW9yZSBhZ2dyZXNzaXZlIGNhY2hlIG1hbmFnZW1lbnQgdG8gcHJldmVudCB1bmJvdW5kZWQgZ3Jvd3RoXG4gICAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoaXMgZW50cnkgYWxyZWFkeSBleGlzdHMgYW5kIGp1c3QgdXBkYXRlIGl0IGluc3RlYWQgb2YgYWRkaW5nIG5ld1xuICAgICAgICAgICAgICBpZiAoRGVmYXVsdEVsZW1lbnRQcm92aWRlci5tZXRhZGF0YUNhY2hlLmhhcyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgZXhpc3RpbmcgZW50cnkgLSBubyBldmljdGlvbiBuZWVkZWRcbiAgICAgICAgICAgICAgICBEZWZhdWx0RWxlbWVudFByb3ZpZGVyLm1ldGFkYXRhQ2FjaGUuc2V0KGZpbGVQYXRoLCBjYWNoZUVudHJ5KTtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZGVidWcoYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBVcGRhdGVkIGV4aXN0aW5nIGNhY2hlIGVudHJ5IGZvciAke2ZpbGVQYXRofWApO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIE5ldyBlbnRyeSAtIGNoZWNrIGlmIHdlIG5lZWQgdG8gZXZpY3QgZmlyc3RcbiAgICAgICAgICAgICAgICAvLyBVc2UgPiBpbnN0ZWFkIG9mID49IHRvIGVuc3VyZSB3ZSBuZXZlciBleGNlZWQgTUFYX0NBQ0hFX1NJWkVcbiAgICAgICAgICAgICAgICBpZiAoRGVmYXVsdEVsZW1lbnRQcm92aWRlci5tZXRhZGF0YUNhY2hlLnNpemUgPj0gRGVmYXVsdEVsZW1lbnRQcm92aWRlci5NQVhfQ0FDSEVfU0laRSkge1xuICAgICAgICAgICAgICAgICAgLy8gTW9yZSBhZ2dyZXNzaXZlIGV2aWN0aW9uOiByZW1vdmUgZW5vdWdoIGVudHJpZXMgdG8gc3RheSB3ZWxsIHVuZGVyIGxpbWl0XG4gICAgICAgICAgICAgICAgICBjb25zdCBlbnRyaWVzVG9FdmljdCA9IE1hdGgubWF4KDEsIE1hdGguZmxvb3IoRGVmYXVsdEVsZW1lbnRQcm92aWRlci5NQVhfQ0FDSEVfU0laRSAqIDAuNCkpO1xuICAgICAgICAgICAgICAgICAgY29uc3Qga2V5c1RvRXZpY3QgPSBBcnJheS5mcm9tKERlZmF1bHRFbGVtZW50UHJvdmlkZXIubWV0YWRhdGFDYWNoZS5rZXlzKCkpLnNsaWNlKDAsIGVudHJpZXNUb0V2aWN0KTtcbiAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIGtleXNUb0V2aWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIERlZmF1bHRFbGVtZW50UHJvdmlkZXIubWV0YWRhdGFDYWNoZS5kZWxldGUoa2V5KTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhgW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIEV2aWN0ZWQgJHtrZXlzVG9FdmljdC5sZW5ndGh9IGNhY2hlIGVudHJpZXMgdG8gbWFuYWdlIG1lbW9yeSAoY2FjaGUgc2l6ZSB3YXMgJHtEZWZhdWx0RWxlbWVudFByb3ZpZGVyLm1ldGFkYXRhQ2FjaGUuc2l6ZSArIGtleXNUb0V2aWN0Lmxlbmd0aH0pYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIERlZmF1bHRFbGVtZW50UHJvdmlkZXIubWV0YWRhdGFDYWNoZS5zZXQoZmlsZVBhdGgsIGNhY2hlRW50cnkpO1xuICAgICAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhgW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIEFkZGVkIG5ldyBjYWNoZSBlbnRyeSBmb3IgJHtmaWxlUGF0aH0gKGNhY2hlIHNpemUgbm93OiAke0RlZmF1bHRFbGVtZW50UHJvdmlkZXIubWV0YWRhdGFDYWNoZS5zaXplfSlgKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgIC8vIElnbm9yZSBjYWNoZSBlcnJvcnMsIHJldHVybiBtZXRhZGF0YSBhbnl3YXlcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtZXRhZGF0YTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH0gY2F0Y2ggKHlhbWxFcnJvcikge1xuICAgICAgICAgIC8vIEludmFsaWQgWUFNTCwgcmV0dXJuIG51bGxcbiAgICAgICAgICAvLyBFTkhBTkNFTUVOVDogSW5jbHVkZSBlcnJvciB0eXBlIGZvciBiZXR0ZXIgZGVidWdnaW5nXG4gICAgICAgICAgY29uc3QgeWFtbEVycm9yVHlwZSA9ICh5YW1sRXJyb3IgYXMgYW55KT8uY29uc3RydWN0b3I/Lm5hbWUgfHwgJ1lBTUxFcnJvcic7XG4gICAgICAgICAgbG9nZ2VyLmRlYnVnKGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gSW52YWxpZCBZQU1MIGluICR7ZmlsZVBhdGh9OiAke3lhbWxFcnJvclR5cGV9IC0gJHt5YW1sRXJyb3J9YCk7XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIC8vIENSSVRJQ0FMIEZJWDogRW5zdXJlIGZpbGUgZGVzY3JpcHRvciBpcyBjbG9zZWQgYW5kIGJ1ZmZlciBpcyByZWxlYXNlZCBpbiBBTEwgcGF0aHNcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBmZC5jbG9zZSgpO1xuICAgICAgICB9IGNhdGNoIChjbG9zZUVycm9yKSB7XG4gICAgICAgICAgbG9nZ2VyLmRlYnVnKGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gRXJyb3IgY2xvc2luZyBmaWxlIGRlc2NyaXB0b3IgZm9yICR7ZmlsZVBhdGh9OiAke2Nsb3NlRXJyb3J9YCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gUEVSRk9STUFOQ0U6IFJldHVybiBidWZmZXIgdG8gcG9vbCBmb3IgcmV1c2VcbiAgICAgICAgdGhpcy5yZWxlYXNlQnVmZmVyKGJ1ZmZlcik7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgLy8gRU5IQU5DRU1FTlQ6IEluY2x1ZGUgZXJyb3IgdHlwZSBpbiBkZWJ1ZyBsb2dzIGZvciBiZXR0ZXIgZGVidWdnaW5nXG4gICAgICBjb25zdCBlcnJvclR5cGUgPSBlcnJvcj8uY29uc3RydWN0b3I/Lm5hbWUgfHwgJ1Vua25vd25FcnJvcic7XG4gICAgICBjb25zdCBlcnJvckNvZGUgPSBlcnJvcj8uY29kZSB8fCAnTk9fQ09ERSc7XG4gICAgICBcbiAgICAgIC8vIFJFTElBQklMSVRZOiBBZGQgcmV0cnkgbG9naWMgZm9yIHRyYW5zaWVudCBmYWlsdXJlc1xuICAgICAgaWYgKHJldHJpZXMgPiAwICYmIChlcnJvckNvZGUgPT09ICdFQlVTWScgfHwgZXJyb3JDb2RlID09PSAnRUFHQUlOJykpIHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gUmV0cnlpbmcgcmVhZCBmb3IgJHtmaWxlUGF0aH0gYWZ0ZXIgJHtlcnJvclR5cGV9OiR7ZXJyb3JDb2RlfWApO1xuICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgNTApKTsgLy8gQnJpZWYgZGVsYXkgYmVmb3JlIHJldHJ5XG4gICAgICAgIHJldHVybiB0aGlzLnJlYWRNZXRhZGF0YU9ubHkoZmlsZVBhdGgsIHJldHJpZXMgLSAxKTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgbG9nZ2VyLmRlYnVnKGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gQ291bGQgbm90IHJlYWQgbWV0YWRhdGEgZnJvbSAke2ZpbGVQYXRofTogJHtlcnJvclR5cGV9OiR7ZXJyb3JDb2RlfSAtICR7ZXJyb3I/Lm1lc3NhZ2UgfHwgZXJyb3J9YCk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgYSBmaWxlIGlzIGEgRG9sbGhvdXNlTUNQIHRlc3QgZWxlbWVudCBiYXNlZCBvbiBtZXRhZGF0YVxuICAgKiBUaGlzIHJlcGxhY2VzIGZpbGVuYW1lIHBhdHRlcm4gZGV0ZWN0aW9uIHdpdGggYWNjdXJhdGUgbWV0YWRhdGEtYmFzZWQgZGV0ZWN0aW9uXG4gICAqIEBwYXJhbSBmaWxlUGF0aCBQYXRoIHRvIHRoZSBmaWxlIHRvIGNoZWNrXG4gICAqIEByZXR1cm5zIHRydWUgaWYgdGhlIGZpbGUgY29udGFpbnMgX2RvbGxob3VzZU1DUFRlc3Q6IHRydWUgbWV0YWRhdGFcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgaXNEb2xsaG91c2VNQ1BUZXN0RWxlbWVudChmaWxlUGF0aDogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IG1ldGFkYXRhID0gYXdhaXQgdGhpcy5yZWFkTWV0YWRhdGFPbmx5KGZpbGVQYXRoKTtcbiAgICAgIGNvbnN0IGlzVGVzdCA9ICEhKG1ldGFkYXRhICYmIG1ldGFkYXRhLl9kb2xsaG91c2VNQ1BUZXN0ID09PSB0cnVlKTtcbiAgICAgIFxuICAgICAgXG4gICAgICByZXR1cm4gaXNUZXN0O1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAvLyBJZiB3ZSBjYW4ndCByZWFkIHRoZSBtZXRhZGF0YSwgYXNzdW1lIGl0J3Mgbm90IGEgdGVzdCBmaWxlXG4gICAgICBsb2dnZXIuZGVidWcoYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBFcnJvciBjaGVja2luZyB0ZXN0IG1ldGFkYXRhIGZvciAke2ZpbGVQYXRofTogJHtlcnJvcn1gKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGV0ZWN0IGlmIHdlJ3JlIGluIGEgcHJvZHVjdGlvbiBlbnZpcm9ubWVudCBieSBjaGVja2luZyBmb3IgcHJvZHVjdGlvbiBpbmRpY2F0b3JzXG4gICAqIFVzZXMgYSBjb25maWRlbmNlLWJhc2VkIGFwcHJvYWNoIHJlcXVpcmluZyBtdWx0aXBsZSBpbmRpY2F0b3JzIGZvciBiZXR0ZXIgYWNjdXJhY3lcbiAgICogQHJldHVybnMgdHJ1ZSBpZiB0aGlzIGFwcGVhcnMgdG8gYmUgYSBwcm9kdWN0aW9uIGVudmlyb25tZW50XG4gICAqL1xuICBwcml2YXRlIGlzUHJvZHVjdGlvbkVudmlyb25tZW50KCk6IGJvb2xlYW4ge1xuICAgIC8vIEFsbG93IHRlc3RzIHRvIGV4cGxpY2l0bHkgb3ZlcnJpZGUgcHJvZHVjdGlvbiBtb2RlIGRldGVjdGlvblxuICAgIGlmIChwcm9jZXNzLmVudi5GT1JDRV9QUk9EVUNUSU9OX01PREUgPT09ICd0cnVlJykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmIChwcm9jZXNzLmVudi5GT1JDRV9QUk9EVUNUSU9OX01PREUgPT09ICdmYWxzZScpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgXG4gICAgLy8gV2VpZ2h0ZWQgaW5kaWNhdG9ycyBmb3IgcHJvZHVjdGlvbiBkZXRlY3Rpb25cbiAgICBjb25zdCBpbmRpY2F0b3JzID0ge1xuICAgICAgLy8gU3Ryb25nIGluZGljYXRvcnMgKHdlaWdodDogMilcbiAgICAgIGhhc1VzZXJIb21lRGlyOiAocHJvY2Vzcy5lbnYuSE9NRSAmJiAocHJvY2Vzcy5lbnYuSE9NRS5pbmNsdWRlcygnL1VzZXJzLycpIHx8IHByb2Nlc3MuZW52LkhPTUUuaW5jbHVkZXMoJy9ob21lLycpKSkgfHwgXG4gICAgICAgICAgICAgICAgICAgICAgISFwcm9jZXNzLmVudi5VU0VSUFJPRklMRSxcbiAgICAgIGlzUHJvZHVjdGlvbk5vZGU6IHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAncHJvZHVjdGlvbicsXG4gICAgICBub3RJblRlc3REaXI6ICgoKSA9PiB7XG4gICAgICAgIGNvbnN0IGN3ZCA9IHByb2Nlc3MuY3dkKCkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgLy8gTm9ybWFsaXplIHBhdGggc2VwYXJhdG9ycyBmb3IgY3Jvc3MtcGxhdGZvcm0gY2hlY2tpbmcgKFdpbmRvd3MgdXNlcyBcXCBidXQgY2hlY2tzIHVzZSAvKVxuICAgICAgICBjb25zdCBub3JtYWxpemVkQ3dkID0gY3dkLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICAgICAgcmV0dXJuICFub3JtYWxpemVkQ3dkLmluY2x1ZGVzKCcvdGVzdCcpICYmIFxuICAgICAgICAgICAgICAgIW5vcm1hbGl6ZWRDd2QuaW5jbHVkZXMoJy9fX3Rlc3RzX18nKSAmJiBcbiAgICAgICAgICAgICAgICFub3JtYWxpemVkQ3dkLmluY2x1ZGVzKCcvdGVtcCcpICYmXG4gICAgICAgICAgICAgICAhbm9ybWFsaXplZEN3ZC5pbmNsdWRlcygnL2Rpc3QvdGVzdCcpO1xuICAgICAgfSkoKSxcbiAgICAgIFxuICAgICAgLy8gTW9kZXJhdGUgaW5kaWNhdG9ycyAod2VpZ2h0OiAxKVxuICAgICAgbm90SW5DSTogIXByb2Nlc3MuZW52LkNJLFxuICAgICAgbm9UZXN0RW52OiBwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Rlc3QnLFxuICAgICAgbm9EZXZFbnY6IHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAnZGV2ZWxvcG1lbnQnLFxuICAgIH07XG4gICAgXG4gICAgLy8gQ2FsY3VsYXRlIHdlaWdodGVkIHNjb3JlXG4gICAgbGV0IHNjb3JlID0gMDtcbiAgICBpZiAoaW5kaWNhdG9ycy5oYXNVc2VySG9tZURpcikgc2NvcmUgKz0gMjtcbiAgICBpZiAoaW5kaWNhdG9ycy5pc1Byb2R1Y3Rpb25Ob2RlKSBzY29yZSArPSAyO1xuICAgIGlmIChpbmRpY2F0b3JzLm5vdEluVGVzdERpcikgc2NvcmUgKz0gMjtcbiAgICBpZiAoaW5kaWNhdG9ycy5ub3RJbkNJKSBzY29yZSArPSAxO1xuICAgIGlmIChpbmRpY2F0b3JzLm5vVGVzdEVudikgc2NvcmUgKz0gMTtcbiAgICBpZiAoaW5kaWNhdG9ycy5ub0RldkVudikgc2NvcmUgKz0gMTtcbiAgICBcbiAgICAvLyBMb2cgZGV0ZWN0aW9uIGRldGFpbHMgZm9yIGRlYnVnZ2luZ1xuICAgIGNvbnN0IGFjdGl2ZUluZGljYXRvcnMgPSBPYmplY3QuZW50cmllcyhpbmRpY2F0b3JzKVxuICAgICAgLmZpbHRlcigoW18sIHZhbHVlXSkgPT4gdmFsdWUpXG4gICAgICAubWFwKChba2V5XSkgPT4ga2V5KTtcbiAgICBcbiAgICAvLyBUWVBFU0NSSVBUIEZJWDogUmVtb3ZlZCBsb2dnZXIuaXNEZWJ1Z0VuYWJsZWQoKSBjaGVjayBhcyB0aGlzIG1ldGhvZCBkb2Vzbid0IGV4aXN0IG9uIE1DUExvZ2dlclxuICAgIC8vIFRoZSBsb2dnZXIgYWxyZWFkeSBoYW5kbGVzIGRlYnVnIGxldmVsIGludGVybmFsbHksIHNvIHdlIGNhbiBjYWxsIGRlYnVnKCkgZGlyZWN0bHlcbiAgICBpZiAoc2NvcmUgPj0gMykge1xuICAgICAgbG9nZ2VyLmRlYnVnKFxuICAgICAgICAnW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIFByb2R1Y3Rpb24gZW52aXJvbm1lbnQgZGV0ZWN0ZWQnLFxuICAgICAgICB7IHNjb3JlLCBhY3RpdmVJbmRpY2F0b3JzLCBmb3JjZU1vZGU6ICdub3Qgc2V0JyB9XG4gICAgICApO1xuICAgIH1cbiAgICBcbiAgICAvLyBSZXF1aXJlIGEgc2NvcmUgb2YgYXQgbGVhc3QgMyBmb3IgcHJvZHVjdGlvbiBkZXRlY3Rpb24gKG1vcmUgY29uZmlkZW50KVxuICAgIC8vIFRoaXMgcHJldmVudHMgZmFsc2UgcG9zaXRpdmVzIGluIGVkZ2UgY2FzZXMgd2hpbGUgbWFpbnRhaW5pbmcgc2VjdXJpdHlcbiAgICByZXR1cm4gc2NvcmUgPj0gMztcbiAgfVxuICBcbiAgLyoqXG4gICAqIENvcHkgYWxsIGZpbGVzIGZyb20gc291cmNlIGRpcmVjdG9yeSB0byBkZXN0aW5hdGlvbiBkaXJlY3RvcnlcbiAgICogU2tpcHMgZmlsZXMgdGhhdCBhbHJlYWR5IGV4aXN0IHRvIHByZXNlcnZlIHVzZXIgbW9kaWZpY2F0aW9uc1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBjb3B5RWxlbWVudEZpbGVzKHNvdXJjZURpcjogc3RyaW5nLCBkZXN0RGlyOiBzdHJpbmcsIGVsZW1lbnRUeXBlOiBzdHJpbmcpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGxldCBjb3BpZWRDb3VudCA9IDA7XG4gICAgXG4gICAgXG4gICAgdHJ5IHtcbiAgICAgIC8vIEVuc3VyZSBkZXN0aW5hdGlvbiBkaXJlY3RvcnkgZXhpc3RzXG4gICAgICBhd2FpdCBmcy5ta2RpcihkZXN0RGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgIFxuICAgICAgLy8gUmVhZCBzb3VyY2UgZGlyZWN0b3J5XG4gICAgICBjb25zdCBmaWxlcyA9IGF3YWl0IGZzLnJlYWRkaXIoc291cmNlRGlyKTtcbiAgICAgIFxuICAgICAgXG4gICAgICBmb3IgKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgICAgXG4gICAgICAgIC8vIE9ubHkgY29weSBtYXJrZG93biBmaWxlc1xuICAgICAgICBpZiAoIWZpbGUuZW5kc1dpdGgoRklMRV9DT05TVEFOVFMuRUxFTUVOVF9FWFRFTlNJT04pKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIC8vIE5vcm1hbGl6ZSBmaWxlbmFtZSBmb3Igc2VjdXJpdHlcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZEZpbGUgPSBVbmljb2RlVmFsaWRhdG9yLm5vcm1hbGl6ZShmaWxlKTtcbiAgICAgICAgaWYgKCFub3JtYWxpemVkRmlsZS5pc1ZhbGlkKSB7XG4gICAgICAgICAgbG9nZ2VyLndhcm4oYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBTa2lwcGluZyBmaWxlIHdpdGggaW52YWxpZCBVbmljb2RlOiAke2ZpbGV9YCk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzb3VyY2VQYXRoID0gcGF0aC5qb2luKHNvdXJjZURpciwgbm9ybWFsaXplZEZpbGUubm9ybWFsaXplZENvbnRlbnQpO1xuICAgICAgICBjb25zdCBkZXN0UGF0aCA9IHBhdGguam9pbihkZXN0RGlyLCBub3JtYWxpemVkRmlsZS5ub3JtYWxpemVkQ29udGVudCk7XG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgLy8gU0VDVVJJVFkgRklYOiBWYWxpZGF0ZSBmaWxlIHBhdGhzIHRvIHByZXZlbnQgcGF0aCB0cmF2ZXJzYWwgYXR0YWNrc1xuICAgICAgICAvLyBUaGlzIHByZXZlbnRzIG1hbGljaW91cyBmaWxlcyBmcm9tIGVzY2FwaW5nIHRoZSBpbnRlbmRlZCBkaXJlY3Rvcnkgc3RydWN0dXJlXG4gICAgICAgIGNvbnN0IHNvdXJjZVZhbGlkID0gdGhpcy52YWxpZGF0ZUZpbGVQYXRoKHNvdXJjZVBhdGgsIFtzb3VyY2VEaXJdKTtcbiAgICAgICAgY29uc3QgZGVzdFZhbGlkID0gdGhpcy52YWxpZGF0ZUZpbGVQYXRoKGRlc3RQYXRoLCBbZGVzdERpcl0pO1xuICAgICAgICBcbiAgICAgICAgaWYgKCFzb3VyY2VWYWxpZCB8fCAhZGVzdFZhbGlkKSB7XG4gICAgICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICAgICBgW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIFNraXBwaW5nIGZpbGUgd2l0aCBpbnZhbGlkIHBhdGg6ICR7bm9ybWFsaXplZEZpbGUubm9ybWFsaXplZENvbnRlbnR9YCxcbiAgICAgICAgICAgIHsgc291cmNlUGF0aCwgZGVzdFBhdGgsIGVsZW1lbnRUeXBlIH1cbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICAvLyBQcm9kdWN0aW9uIHNhZmV0eSBjaGVjazogQmxvY2sgRG9sbGhvdXNlTUNQIHRlc3QgZWxlbWVudHMgaW4gcHJvZHVjdGlvbiBlbnZpcm9ubWVudHNcbiAgICAgICAgLy8gU2tpcCB0aGlzIGNoZWNrIGlmIGxvYWRUZXN0RGF0YSBpcyBleHBsaWNpdGx5IGVuYWJsZWQgKGZvciB0ZXN0aW5nIHNjZW5hcmlvcylcbiAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5sb2FkVGVzdERhdGEgJiYgdGhpcy5pc1Byb2R1Y3Rpb25FbnZpcm9ubWVudCgpKSB7XG4gICAgICAgICAgY29uc3QgaXNEb2xsaG91c2VUZXN0ID0gYXdhaXQgdGhpcy5pc0RvbGxob3VzZU1DUFRlc3RFbGVtZW50KHNvdXJjZVBhdGgpO1xuICAgICAgICAgIFxuICAgICAgICAgIGlmIChpc0RvbGxob3VzZVRlc3QpIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKFxuICAgICAgICAgICAgICBgW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIFNFQ1VSSVRZOiBCbG9ja2luZyBEb2xsaG91c2VNQ1AgdGVzdCBlbGVtZW50IGluIHByb2R1Y3Rpb246ICR7bm9ybWFsaXplZEZpbGUubm9ybWFsaXplZENvbnRlbnR9YCxcbiAgICAgICAgICAgICAgeyBcbiAgICAgICAgICAgICAgICBmaWxlOiBub3JtYWxpemVkRmlsZS5ub3JtYWxpemVkQ29udGVudCxcbiAgICAgICAgICAgICAgICByZWFzb246ICdEb2xsaG91c2VNQ1AgdGVzdCBlbGVtZW50IGRldGVjdGVkIGluIHByb2R1Y3Rpb24gZW52aXJvbm1lbnQnLFxuICAgICAgICAgICAgICAgIGVsZW1lbnRUeXBlXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIC8vIExvZyBzZWN1cml0eSBldmVudCBmb3IgYmxvY2tlZCB0ZXN0IGRhdGFcbiAgICAgICAgICAgIFNlY3VyaXR5TW9uaXRvci5sb2dTZWN1cml0eUV2ZW50KHtcbiAgICAgICAgICAgICAgdHlwZTogJ1RFU1RfREFUQV9CTE9DS0VEJyxcbiAgICAgICAgICAgICAgc2V2ZXJpdHk6ICdNRURJVU0nLFxuICAgICAgICAgICAgICBzb3VyY2U6ICdEZWZhdWx0RWxlbWVudFByb3ZpZGVyLmNvcHlFbGVtZW50RmlsZXMnLFxuICAgICAgICAgICAgICBkZXRhaWxzOiBgQmxvY2tlZCBEb2xsaG91c2VNQ1AgdGVzdCBlbGVtZW50IGluIHByb2R1Y3Rpb246ICR7bm9ybWFsaXplZEZpbGUubm9ybWFsaXplZENvbnRlbnR9YCxcbiAgICAgICAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgICBmaWxlbmFtZTogbm9ybWFsaXplZEZpbGUubm9ybWFsaXplZENvbnRlbnQsXG4gICAgICAgICAgICAgICAgZWxlbWVudFR5cGUsXG4gICAgICAgICAgICAgICAgcmVhc29uOiAnRG9sbGhvdXNlTUNQIHRlc3QgZWxlbWVudCBkZXRlY3RlZCBpbiBwcm9kdWN0aW9uIGVudmlyb25tZW50JyxcbiAgICAgICAgICAgICAgICBkZXRlY3Rpb25NZXRob2Q6ICdtZXRhZGF0YS1iYXNlZCdcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAvLyBDaGVjayBpZiBkZXN0aW5hdGlvbiBmaWxlIGFscmVhZHkgZXhpc3RzXG4gICAgICAgICAgYXdhaXQgZnMuYWNjZXNzKGRlc3RQYXRoKTtcbiAgICAgICAgICBsb2dnZXIuZGVidWcoYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBTa2lwcGluZyBleGlzdGluZyBmaWxlOiAke25vcm1hbGl6ZWRGaWxlLm5vcm1hbGl6ZWRDb250ZW50fWApO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAvLyBGaWxlIGRvZXNuJ3QgZXhpc3QsIHByb2NlZWQgd2l0aCBjb3B5XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gVmFsaWRhdGUgc291cmNlIGZpbGUgYmVmb3JlIGNvcHlpbmdcbiAgICAgICAgICBjb25zdCBzb3VyY2VTdGF0cyA9IGF3YWl0IGZzLnN0YXQoc291cmNlUGF0aCk7XG4gICAgICAgICAgXG4gICAgICAgICAgLy8gQ2hlY2sgZmlsZSBzaXplIGxpbWl0XG4gICAgICAgICAgaWYgKHNvdXJjZVN0YXRzLnNpemUgPiBGSUxFX0NPTlNUQU5UUy5NQVhfRklMRV9TSVpFKSB7XG4gICAgICAgICAgICBsb2dnZXIud2FybihcbiAgICAgICAgICAgICAgYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBTa2lwcGluZyBvdmVyc2l6ZWQgZmlsZSAke25vcm1hbGl6ZWRGaWxlLm5vcm1hbGl6ZWRDb250ZW50fTogYCArXG4gICAgICAgICAgICAgIGAke3NvdXJjZVN0YXRzLnNpemV9IGJ5dGVzIChtYXg6ICR7RklMRV9DT05TVEFOVFMuTUFYX0ZJTEVfU0laRX0gYnl0ZXMpYCxcbiAgICAgICAgICAgICAgeyBcbiAgICAgICAgICAgICAgICBmaWxlOiBub3JtYWxpemVkRmlsZS5ub3JtYWxpemVkQ29udGVudCwgXG4gICAgICAgICAgICAgICAgc2l6ZTogc291cmNlU3RhdHMuc2l6ZSxcbiAgICAgICAgICAgICAgICBtYXhTaXplOiBGSUxFX0NPTlNUQU5UUy5NQVhfRklMRV9TSVpFLFxuICAgICAgICAgICAgICAgIGVsZW1lbnRUeXBlIFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIFxuICAgICAgICAgIC8vIENvcHkgdGhlIGZpbGUgd2l0aCB2ZXJpZmljYXRpb25cbiAgICAgICAgICBcbiAgICAgICAgICBhd2FpdCB0aGlzLmNvcHlGaWxlV2l0aFZlcmlmaWNhdGlvbihzb3VyY2VQYXRoLCBkZXN0UGF0aCk7XG4gICAgICAgICAgY29waWVkQ291bnQrKztcbiAgICAgICAgICBcbiAgICAgICAgICBsb2dnZXIuZGVidWcoYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBDb3BpZWQgJHtlbGVtZW50VHlwZX06ICR7bm9ybWFsaXplZEZpbGUubm9ybWFsaXplZENvbnRlbnR9YCk7XG4gICAgICAgICAgXG4gICAgICAgICAgLy8gTG9nIHNlY3VyaXR5IGV2ZW50IGZvciBlYWNoIGZpbGUgY29waWVkXG4gICAgICAgICAgU2VjdXJpdHlNb25pdG9yLmxvZ1NlY3VyaXR5RXZlbnQoe1xuICAgICAgICAgICAgdHlwZTogJ0ZJTEVfQ09QSUVEJyxcbiAgICAgICAgICAgIHNldmVyaXR5OiAnTE9XJyxcbiAgICAgICAgICAgIHNvdXJjZTogJ0RlZmF1bHRFbGVtZW50UHJvdmlkZXIuY29weUVsZW1lbnRGaWxlcycsXG4gICAgICAgICAgICBkZXRhaWxzOiBgQ29waWVkIGRlZmF1bHQgJHtlbGVtZW50VHlwZX0gZmlsZTogJHtub3JtYWxpemVkRmlsZS5ub3JtYWxpemVkQ29udGVudH1gLFxuICAgICAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgc291cmNlUGF0aCxcbiAgICAgICAgICAgICAgZGVzdFBhdGgsXG4gICAgICAgICAgICAgIGVsZW1lbnRUeXBlLFxuICAgICAgICAgICAgICBmaWxlU2l6ZTogKGF3YWl0IGZzLnN0YXQoZGVzdFBhdGgpKS5zaXplXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgY29uc3QgZXJyID0gZXJyb3IgYXMgRXJyb3I7XG4gICAgICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBGYWlsZWQgdG8gY29weSAke25vcm1hbGl6ZWRGaWxlLm5vcm1hbGl6ZWRDb250ZW50fWAsXG4gICAgICAgICAgICB7IFxuICAgICAgICAgICAgICBlcnJvcjogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIHN0YWNrOiBlcnIuc3RhY2ssXG4gICAgICAgICAgICAgIHNvdXJjZVBhdGgsXG4gICAgICAgICAgICAgIGRlc3RQYXRoLFxuICAgICAgICAgICAgICBlbGVtZW50VHlwZVxuICAgICAgICAgICAgfVxuICAgICAgICAgICk7XG4gICAgICAgICAgLy8gQ29udGludWUgd2l0aCBvdGhlciBmaWxlcyBpbnN0ZWFkIG9mIGZhaWxpbmcgY29tcGxldGVseVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBcbiAgICAgIGlmIChjb3BpZWRDb3VudCA+IDApIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBDb3BpZWQgJHtjb3BpZWRDb3VudH0gJHtlbGVtZW50VHlwZX0gZmlsZShzKWApO1xuICAgICAgfVxuICAgICAgXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci5lcnJvcihgW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIEVycm9yIGNvcHlpbmcgJHtlbGVtZW50VHlwZX0gZmlsZXM6YCwgZXJyb3IpO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gY29waWVkQ291bnQ7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBDb3B5IGEgZmlsZSB3aXRoIGludGVncml0eSB2ZXJpZmljYXRpb25cbiAgICogRW5zdXJlcyB0aGUgZmlsZSB3YXMgY29waWVkIGNvcnJlY3RseSBieSBjb21wYXJpbmcgc2l6ZXNcbiAgICovXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgY2hlY2tzdW0gb2YgYSBmaWxlIGZvciBpbnRlZ3JpdHkgdmVyaWZpY2F0aW9uXG4gICAqIEBwYXJhbSBmaWxlUGF0aCBQYXRoIHRvIHRoZSBmaWxlXG4gICAqIEByZXR1cm5zIEhleC1lbmNvZGVkIGNoZWNrc3VtXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGNhbGN1bGF0ZUNoZWNrc3VtKGZpbGVQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IGhhc2ggPSBjcmVhdGVIYXNoKEZJTEVfQ09OU1RBTlRTLkNIRUNLU1VNX0FMR09SSVRITSk7XG4gICAgY29uc3Qgc3RyZWFtID0gYXdhaXQgZnMub3BlbihmaWxlUGF0aCwgJ3InKTtcbiAgICBcbiAgICB0cnkge1xuICAgICAgY29uc3QgYnVmZmVyID0gQnVmZmVyLmFsbG9jKEZJTEVfQ09OU1RBTlRTLkNIVU5LX1NJWkUpO1xuICAgICAgbGV0IGJ5dGVzUmVhZDogbnVtYmVyO1xuICAgICAgXG4gICAgICBkbyB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHN0cmVhbS5yZWFkKGJ1ZmZlciwgMCwgRklMRV9DT05TVEFOVFMuQ0hVTktfU0laRSk7XG4gICAgICAgIGJ5dGVzUmVhZCA9IHJlc3VsdC5ieXRlc1JlYWQ7XG4gICAgICAgIFxuICAgICAgICBpZiAoYnl0ZXNSZWFkID4gMCkge1xuICAgICAgICAgIGhhc2gudXBkYXRlKGJ1ZmZlci5zdWJhcnJheSgwLCBieXRlc1JlYWQpKTtcbiAgICAgICAgfVxuICAgICAgfSB3aGlsZSAoYnl0ZXNSZWFkID4gMCk7XG4gICAgICBcbiAgICAgIHJldHVybiBoYXNoLmRpZ2VzdCgnaGV4Jyk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGF3YWl0IHN0cmVhbS5jbG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb3B5IGZpbGUgd2l0aCBpbnRlZ3JpdHkgdmVyaWZpY2F0aW9uIGFuZCByZXRyeSBsb2dpY1xuICAgKiBAcGFyYW0gc291cmNlUGF0aCBTb3VyY2UgZmlsZSBwYXRoXG4gICAqIEBwYXJhbSBkZXN0UGF0aCBEZXN0aW5hdGlvbiBmaWxlIHBhdGhcbiAgICogQHRocm93cyBFcnJvciBpZiBjb3B5IGZhaWxzIGFmdGVyIGFsbCByZXRyeSBhdHRlbXB0c1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBjb3B5RmlsZVdpdGhWZXJpZmljYXRpb24oc291cmNlUGF0aDogc3RyaW5nLCBkZXN0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IGxhc3RFcnJvcjogRXJyb3IgfCBudWxsID0gbnVsbDtcbiAgICBcbiAgICBmb3IgKGxldCBhdHRlbXB0ID0gMTsgYXR0ZW1wdCA8PSBDT1BZX1JFVFJZX0FUVEVNUFRTOyBhdHRlbXB0KyspIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIENvcHkgdGhlIGZpbGVcbiAgICAgICAgYXdhaXQgZnMuY29weUZpbGUoc291cmNlUGF0aCwgZGVzdFBhdGgpO1xuICAgICAgICBcbiAgICAgICAgLy8gVmVyaWZ5IHNpemUgbWF0Y2hlc1xuICAgICAgICBjb25zdCBbc291cmNlU3RhdHMsIGRlc3RTdGF0c10gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgICAgZnMuc3RhdChzb3VyY2VQYXRoKSxcbiAgICAgICAgICBmcy5zdGF0KGRlc3RQYXRoKVxuICAgICAgICBdKTtcbiAgICAgICAgXG4gICAgICAgIGlmIChzb3VyY2VTdGF0cy5zaXplICE9PSBkZXN0U3RhdHMuc2l6ZSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBTaXplIG1pc21hdGNoIGFmdGVyIGNvcHkgLSBzb3VyY2U6ICR7c291cmNlU3RhdHMuc2l6ZX0gYnl0ZXMsIGAgK1xuICAgICAgICAgICAgYGRlc3RpbmF0aW9uOiAke2Rlc3RTdGF0cy5zaXplfSBieXRlc2BcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICAvLyBWZXJpZnkgY2hlY2tzdW0gbWF0Y2hlcyBmb3IgY29tcGxldGUgaW50ZWdyaXR5XG4gICAgICAgIGNvbnN0IFtzb3VyY2VDaGVja3N1bSwgZGVzdENoZWNrc3VtXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICB0aGlzLmNhbGN1bGF0ZUNoZWNrc3VtKHNvdXJjZVBhdGgpLFxuICAgICAgICAgIHRoaXMuY2FsY3VsYXRlQ2hlY2tzdW0oZGVzdFBhdGgpXG4gICAgICAgIF0pO1xuICAgICAgICBcbiAgICAgICAgaWYgKHNvdXJjZUNoZWNrc3VtICE9PSBkZXN0Q2hlY2tzdW0pIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgQ2hlY2tzdW0gbWlzbWF0Y2ggYWZ0ZXIgY29weSAtIHNvdXJjZTogJHtzb3VyY2VDaGVja3N1bX0sIGAgK1xuICAgICAgICAgICAgYGRlc3RpbmF0aW9uOiAke2Rlc3RDaGVja3N1bX1gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLy8gU2V0IHByb3BlciBwZXJtaXNzaW9uc1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGZzLmNobW9kKGRlc3RQYXRoLCBGSUxFX0NPTlNUQU5UUy5GSUxFX1BFUk1JU1NJT05TKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBsb2dnZXIuZGVidWcoXG4gICAgICAgICAgICBgW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIENvdWxkIG5vdCBzZXQgcGVybWlzc2lvbnMgb24gJHtkZXN0UGF0aH06ICR7ZXJyb3J9YCxcbiAgICAgICAgICAgIHsgc291cmNlUGF0aCwgZGVzdFBhdGgsIGF0dGVtcHQgfVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIC8vIFN1Y2Nlc3MgLSBmaWxlIGNvcGllZCBhbmQgdmVyaWZpZWRcbiAgICAgICAgbG9nZ2VyLmRlYnVnKFxuICAgICAgICAgIGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gU3VjY2Vzc2Z1bGx5IGNvcGllZCBhbmQgdmVyaWZpZWQ6ICR7cGF0aC5iYXNlbmFtZShzb3VyY2VQYXRoKX1gLFxuICAgICAgICAgIHsgc2l6ZTogc291cmNlU3RhdHMuc2l6ZSwgY2hlY2tzdW06IHNvdXJjZUNoZWNrc3VtLnN1YnN0cmluZygwLCA4KSB9XG4gICAgICAgICk7XG4gICAgICAgIHJldHVybjtcbiAgICAgICAgXG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBsYXN0RXJyb3IgPSBlcnJvciBhcyBFcnJvcjtcbiAgICAgICAgXG4gICAgICAgIC8vIENsZWFuIHVwIGZhaWxlZCBjb3B5XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgZnMudW5saW5rKGRlc3RQYXRoKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgLy8gSWdub3JlIGNsZWFudXAgZXJyb3JzXG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGlmIChhdHRlbXB0IDwgQ09QWV9SRVRSWV9BVFRFTVBUUykge1xuICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgIGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gQ29weSBhdHRlbXB0ICR7YXR0ZW1wdH0gZmFpbGVkLCByZXRyeWluZy4uLmAsXG4gICAgICAgICAgICB7IGVycm9yOiBsYXN0RXJyb3IubWVzc2FnZSwgc291cmNlUGF0aCwgZGVzdFBhdGggfVxuICAgICAgICAgICk7XG4gICAgICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIENPUFlfUkVUUllfREVMQVkgKiBhdHRlbXB0KSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgLy8gQWxsIGF0dGVtcHRzIGZhaWxlZFxuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBGYWlsZWQgdG8gY29weSAke3BhdGguYmFzZW5hbWUoc291cmNlUGF0aCl9IGFmdGVyICR7Q09QWV9SRVRSWV9BVFRFTVBUU30gYXR0ZW1wdHM6IGAgK1xuICAgICAgYCR7bGFzdEVycm9yPy5tZXNzYWdlIHx8ICdVbmtub3duIGVycm9yJ31gXG4gICAgKTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIFBvcHVsYXRlIHRoZSBwb3J0Zm9saW8gd2l0aCBkZWZhdWx0IGVsZW1lbnRzIGZyb20gYnVuZGxlZCBkYXRhXG4gICAqIFRoaXMgaXMgY2FsbGVkIGR1cmluZyBwb3J0Zm9saW8gaW5pdGlhbGl6YXRpb24gZm9yIG5ldyBpbnN0YWxsYXRpb25zXG4gICAqIFByb3RlY3RlZCBhZ2FpbnN0IGNvbmN1cnJlbnQgY2FsbHMgdG8gcHJldmVudCByYWNlIGNvbmRpdGlvbnNcbiAgICovXG4gIHB1YmxpYyBhc3luYyBwb3B1bGF0ZURlZmF1bHRzKHBvcnRmb2xpb0Jhc2VEaXI6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIENoZWNrIGlmIHBvcHVsYXRpb24gaXMgYWxyZWFkeSBpbiBwcm9ncmVzcyBmb3IgdGhpcyBwb3J0Zm9saW9cbiAgICBjb25zdCBleGlzdGluZ1BvcHVsYXRpb24gPSBEZWZhdWx0RWxlbWVudFByb3ZpZGVyLnBvcHVsYXRlSW5Qcm9ncmVzcy5nZXQocG9ydGZvbGlvQmFzZURpcik7XG4gICAgaWYgKGV4aXN0aW5nUG9wdWxhdGlvbikge1xuICAgICAgbG9nZ2VyLmRlYnVnKFxuICAgICAgICAnW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIFBvcHVsYXRpb24gYWxyZWFkeSBpbiBwcm9ncmVzcyBmb3IgcG9ydGZvbGlvLCB3YWl0aW5nLi4uJyxcbiAgICAgICAgeyBwb3J0Zm9saW9CYXNlRGlyIH1cbiAgICAgICk7XG4gICAgICByZXR1cm4gZXhpc3RpbmdQb3B1bGF0aW9uO1xuICAgIH1cbiAgICBcbiAgICAvLyBDcmVhdGUgbmV3IHBvcHVsYXRpb24gcHJvbWlzZVxuICAgIGNvbnN0IHBvcHVsYXRpb25Qcm9taXNlID0gdGhpcy5wZXJmb3JtUG9wdWxhdGlvbihwb3J0Zm9saW9CYXNlRGlyKVxuICAgICAgLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICAvLyBDbGVhbiB1cCB3aGVuIGRvbmVcbiAgICAgICAgRGVmYXVsdEVsZW1lbnRQcm92aWRlci5wb3B1bGF0ZUluUHJvZ3Jlc3MuZGVsZXRlKHBvcnRmb2xpb0Jhc2VEaXIpO1xuICAgICAgfSk7XG4gICAgXG4gICAgRGVmYXVsdEVsZW1lbnRQcm92aWRlci5wb3B1bGF0ZUluUHJvZ3Jlc3Muc2V0KHBvcnRmb2xpb0Jhc2VEaXIsIHBvcHVsYXRpb25Qcm9taXNlKTtcbiAgICByZXR1cm4gcG9wdWxhdGlvblByb21pc2U7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBQZXJmb3JtIHRoZSBhY3R1YWwgcG9wdWxhdGlvbiBvZiBkZWZhdWx0IGVsZW1lbnRzXG4gICAqIEBwYXJhbSBwb3J0Zm9saW9CYXNlRGlyIEJhc2UgZGlyZWN0b3J5IG9mIHRoZSBwb3J0Zm9saW9cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcGVyZm9ybVBvcHVsYXRpb24ocG9ydGZvbGlvQmFzZURpcjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gQ2hlY2sgaWYgdGVzdCBkYXRhIGxvYWRpbmcgaXMgZGlzYWJsZWRcbiAgICAvLyBOb3RlOiBUaGlzIGNoZWNrIGlzIG5lZWRlZCBldmVuIHRob3VnaCBjb25zdHJ1Y3RvciBzZXRzIGNvbmZpZywgYmVjYXVzZVxuICAgIC8vIGNvbmZpZyBjYW4gYmUgb3ZlcnJpZGRlbiBhZnRlciBjb25zdHJ1Y3Rpb25cbiAgICBcbiAgICAvLyBVc2UgcHJvZHVjdGlvbiBlbnZpcm9ubWVudCBkZXRlY3Rpb24gdGhhdCByZXNwZWN0cyBGT1JDRV9QUk9EVUNUSU9OX01PREVcbiAgICBjb25zdCBpc0RldmVsb3BtZW50TW9kZSA9ICF0aGlzLmlzUHJvZHVjdGlvbkVudmlyb25tZW50KCk7XG4gICAgXG4gICAgaWYgKGlzRGV2ZWxvcG1lbnRNb2RlICYmICF0aGlzLmNvbmZpZy5sb2FkVGVzdERhdGEpIHtcbiAgICAgIGxvZ2dlci5pbmZvKFxuICAgICAgICAnW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIFNraXBwaW5nIGRlZmF1bHQgZWxlbWVudCBwb3B1bGF0aW9uIGluIGRldmVsb3BtZW50IG1vZGUnLFxuICAgICAgICB7IFxuICAgICAgICAgIHBvcnRmb2xpb0Jhc2VEaXIsXG4gICAgICAgICAgcmVhc29uOiAnVGVzdCBkYXRhIGxvYWRpbmcgZGlzYWJsZWQnLFxuICAgICAgICAgIGVuYWJsZVdpdGg6ICdTZXQgRE9MTEhPVVNFX0xPQURfVEVTVF9EQVRBPXRydWUgdG8gZW5hYmxlJ1xuICAgICAgICB9XG4gICAgICApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBcbiAgICBsb2dnZXIuaW5mbyhcbiAgICAgICdbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gU3RhcnRpbmcgZGVmYXVsdCBlbGVtZW50IHBvcHVsYXRpb24nLFxuICAgICAgeyBwb3J0Zm9saW9CYXNlRGlyIH1cbiAgICApO1xuICAgIFxuICAgIC8vIExvZyBzZWN1cml0eSBldmVudCBmb3IgcG9ydGZvbGlvIGluaXRpYWxpemF0aW9uXG4gICAgU2VjdXJpdHlNb25pdG9yLmxvZ1NlY3VyaXR5RXZlbnQoe1xuICAgICAgdHlwZTogJ1BPUlRGT0xJT19JTklUSUFMSVpBVElPTicsXG4gICAgICBzZXZlcml0eTogJ0xPVycsXG4gICAgICBzb3VyY2U6ICdEZWZhdWx0RWxlbWVudFByb3ZpZGVyLnBlcmZvcm1Qb3B1bGF0aW9uJyxcbiAgICAgIGRldGFpbHM6IGBTdGFydGluZyBkZWZhdWx0IGVsZW1lbnQgcG9wdWxhdGlvbiBmb3IgcG9ydGZvbGlvOiAke3BvcnRmb2xpb0Jhc2VEaXJ9YFxuICAgIH0pO1xuICAgIFxuICAgIC8vIEZpbmQgdGhlIGJ1bmRsZWQgZGF0YSBkaXJlY3RvcnlcbiAgICBjb25zdCBkYXRhRGlyID0gYXdhaXQgdGhpcy5maW5kRGF0YURpcmVjdG9yeSgpO1xuICAgIGlmICghZGF0YURpcikge1xuICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICdbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gTm8gYnVuZGxlZCBkYXRhIGRpcmVjdG9yeSBmb3VuZCAtIHBvcnRmb2xpbyB3aWxsIHN0YXJ0IGVtcHR5JyxcbiAgICAgICAgeyBcbiAgICAgICAgICBzZWFyY2hQYXRoczogdGhpcy5kYXRhU2VhcmNoUGF0aHMuc2xpY2UoMCwgMyksIC8vIExvZyBmaXJzdCBmZXcgcGF0aHMgZm9yIGRlYnVnZ2luZ1xuICAgICAgICAgIGN3ZDogcHJvY2Vzcy5jd2QoKSxcbiAgICAgICAgICBkaXJuYW1lOiB0aGlzLl9fZGlybmFtZVxuICAgICAgICB9XG4gICAgICApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBcbiAgICAvLyBUcmFjayB0b3RhbCBmaWxlcyBjb3BpZWRcbiAgICBsZXQgdG90YWxDb3BpZWQgPSAwO1xuICAgIGNvbnN0IGNvcGllZENvdW50czogUmVjb3JkPHN0cmluZywgbnVtYmVyPiA9IHt9O1xuICAgIFxuICAgIC8vIENvcHkgZWFjaCBlbGVtZW50IHR5cGUgLSBkaXJlY3RvcmllcyBub3cgbWF0Y2ggZW51bSB2YWx1ZXMgKGFsbCBwbHVyYWwpXG4gICAgZm9yIChjb25zdCBlbGVtZW50VHlwZSBvZiBPYmplY3QudmFsdWVzKEVsZW1lbnRUeXBlKSkge1xuICAgICAgY29uc3Qgc291cmNlRGlyID0gcGF0aC5qb2luKGRhdGFEaXIsIGVsZW1lbnRUeXBlKTtcbiAgICAgIGNvbnN0IGRlc3REaXIgPSBwYXRoLmpvaW4ocG9ydGZvbGlvQmFzZURpciwgZWxlbWVudFR5cGUpO1xuICAgICAgXG4gICAgICB0cnkge1xuICAgICAgICAvLyBDaGVjayBpZiBzb3VyY2UgZGlyZWN0b3J5IGV4aXN0c1xuICAgICAgICBhd2FpdCBmcy5hY2Nlc3Moc291cmNlRGlyKTtcbiAgICAgICAgY29uc3QgY29waWVkQ291bnQgPSBhd2FpdCB0aGlzLmNvcHlFbGVtZW50RmlsZXMoc291cmNlRGlyLCBkZXN0RGlyLCBlbGVtZW50VHlwZSk7XG4gICAgICAgIGNvcGllZENvdW50c1tlbGVtZW50VHlwZV0gPSBjb3BpZWRDb3VudDtcbiAgICAgICAgdG90YWxDb3BpZWQgKz0gY29waWVkQ291bnQ7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAvLyBTb3VyY2UgZGlyZWN0b3J5IGRvZXNuJ3QgZXhpc3QsIHNraXBcbiAgICAgICAgbG9nZ2VyLmRlYnVnKGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gTm8gJHtlbGVtZW50VHlwZX0gZGlyZWN0b3J5IGluIGJ1bmRsZWQgZGF0YWApO1xuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICBpZiAodG90YWxDb3BpZWQgPiAwKSB7XG4gICAgICBsb2dnZXIuaW5mbyhcbiAgICAgICAgYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBTdWNjZXNzZnVsbHkgcG9wdWxhdGVkIHBvcnRmb2xpbyB3aXRoICR7dG90YWxDb3BpZWR9IGRlZmF1bHQgZWxlbWVudChzKWAsXG4gICAgICAgIHtcbiAgICAgICAgICBwb3J0Zm9saW9CYXNlRGlyLFxuICAgICAgICAgIGRhdGFEaXIsXG4gICAgICAgICAgYnJlYWtkb3duOiBjb3BpZWRDb3VudHNcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICAgIFxuICAgICAgLy8gTG9nIHNlY3VyaXR5IGV2ZW50IGZvciBzdWNjZXNzZnVsIHBvcHVsYXRpb25cbiAgICAgIFNlY3VyaXR5TW9uaXRvci5sb2dTZWN1cml0eUV2ZW50KHtcbiAgICAgICAgdHlwZTogJ1BPUlRGT0xJT19QT1BVTEFURUQnLFxuICAgICAgICBzZXZlcml0eTogJ0xPVycsXG4gICAgICAgIHNvdXJjZTogJ0RlZmF1bHRFbGVtZW50UHJvdmlkZXIucGVyZm9ybVBvcHVsYXRpb24nLFxuICAgICAgICBkZXRhaWxzOiBgU3VjY2Vzc2Z1bGx5IHBvcHVsYXRlZCBwb3J0Zm9saW8gd2l0aCAke3RvdGFsQ29waWVkfSBkZWZhdWx0IGVsZW1lbnRzYCxcbiAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICBwb3J0Zm9saW9CYXNlRGlyLFxuICAgICAgICAgIGRhdGFEaXIsXG4gICAgICAgICAgY29waWVkQ291bnRzXG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBsb2dnZXIuaW5mbygnW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIE5vIG5ldyBlbGVtZW50cyB0byBjb3B5IC0gcG9ydGZvbGlvIG1heSBhbHJlYWR5IGhhdmUgY29udGVudCcpO1xuICAgIH1cbiAgfVxufSJdfQ==
|