@dollhousemcp/mcp-server 1.7.1 → 1.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/auth/GitHubAuthManager.js +2 -2
  3. package/dist/config/ConfigManager.d.ts +158 -25
  4. package/dist/config/ConfigManager.d.ts.map +1 -1
  5. package/dist/config/ConfigManager.js +627 -88
  6. package/dist/generated/version.d.ts +2 -2
  7. package/dist/generated/version.js +3 -3
  8. package/dist/handlers/ConfigHandler.d.ts +32 -0
  9. package/dist/handlers/ConfigHandler.d.ts.map +1 -0
  10. package/dist/handlers/ConfigHandler.js +202 -0
  11. package/dist/handlers/SyncHandlerV2.d.ts +42 -0
  12. package/dist/handlers/SyncHandlerV2.d.ts.map +1 -0
  13. package/dist/handlers/SyncHandlerV2.js +231 -0
  14. package/dist/index.d.ts +18 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +19 -3
  17. package/dist/portfolio/GitHubPortfolioIndexer.d.ts +0 -1
  18. package/dist/portfolio/GitHubPortfolioIndexer.d.ts.map +1 -1
  19. package/dist/portfolio/GitHubPortfolioIndexer.js +36 -16
  20. package/dist/portfolio/PortfolioRepoManager.d.ts +2 -1
  21. package/dist/portfolio/PortfolioRepoManager.d.ts.map +1 -1
  22. package/dist/portfolio/PortfolioRepoManager.js +2 -1
  23. package/dist/portfolio/PortfolioSyncManager.d.ts +127 -0
  24. package/dist/portfolio/PortfolioSyncManager.d.ts.map +1 -0
  25. package/dist/portfolio/PortfolioSyncManager.js +818 -0
  26. package/dist/security/audit/config/suppressions.d.ts.map +1 -1
  27. package/dist/security/audit/config/suppressions.js +54 -2
  28. package/dist/security/secureYamlParser.d.ts +46 -2
  29. package/dist/security/secureYamlParser.d.ts.map +1 -1
  30. package/dist/security/secureYamlParser.js +47 -3
  31. package/dist/server/ServerSetup.d.ts.map +1 -1
  32. package/dist/server/ServerSetup.js +16 -10
  33. package/dist/server/tools/ConfigToolsV2.d.ts +10 -0
  34. package/dist/server/tools/ConfigToolsV2.d.ts.map +1 -0
  35. package/dist/server/tools/ConfigToolsV2.js +110 -0
  36. package/dist/server/types.d.ts +2 -0
  37. package/dist/server/types.d.ts.map +1 -1
  38. package/dist/server/types.js +1 -1
  39. package/dist/utils/logger.d.ts +45 -0
  40. package/dist/utils/logger.d.ts.map +1 -1
  41. package/dist/utils/logger.js +202 -9
  42. package/package.json +1 -1
@@ -1,27 +1,33 @@
1
1
  /**
2
- * ConfigManager - Thread-safe singleton for persistent configuration
2
+ * ConfigManager - Centralized configuration management for DollhouseMCP
3
3
  *
4
- * Handles OAuth client ID storage for Claude Desktop integration.
5
- * Stores config in ~/.dollhouse/config.json with proper permissions.
6
- * Prefers environment variables over config file values.
4
+ * Features:
5
+ * - YAML-based configuration file
6
+ * - Default values with user overrides
7
+ * - Migration from environment variables
8
+ * - Validation and type safety
9
+ * - Atomic updates with backup
10
+ * - Privacy-first defaults
11
+ * - OAuth client ID storage for Claude Desktop integration
7
12
  */
8
13
  import * as fs from 'fs/promises';
9
14
  import * as path from 'path';
10
15
  import * as os from 'os';
16
+ import * as yaml from 'js-yaml';
17
+ import { logger } from '../utils/logger.js';
18
+ import { SecureYamlParser } from '../security/secureYamlParser.js';
11
19
  export class ConfigManager {
12
20
  static instance = null;
13
21
  static instanceLock = false;
14
22
  configDir;
15
23
  configPath;
16
- config;
24
+ backupPath;
25
+ config = null;
17
26
  constructor() {
18
27
  // Initialize paths
19
28
  this.configDir = path.join(os.homedir(), '.dollhouse');
20
- this.configPath = path.join(this.configDir, 'config.json');
21
- // Initialize with default config
22
- this.config = {
23
- version: '1.0.0'
24
- };
29
+ this.configPath = path.join(this.configDir, 'config.yml');
30
+ this.backupPath = path.join(this.configDir, 'config.yml.backup');
25
31
  }
26
32
  /**
27
33
  * Thread-safe singleton instance getter
@@ -47,67 +53,192 @@ export class ConfigManager {
47
53
  return ConfigManager.instance;
48
54
  }
49
55
  /**
50
- * Attempt to repair file permissions if they're incorrect
51
- * This helps with error recovery in permission-related issues
56
+ * Get default configuration
57
+ */
58
+ getDefaultConfig() {
59
+ return {
60
+ version: '1.0.0',
61
+ user: {
62
+ username: null,
63
+ email: null,
64
+ display_name: null
65
+ },
66
+ github: {
67
+ portfolio: {
68
+ repository_url: null,
69
+ repository_name: 'dollhouse-portfolio',
70
+ default_branch: 'main',
71
+ auto_create: true
72
+ },
73
+ auth: {
74
+ use_oauth: true,
75
+ token_source: 'environment'
76
+ }
77
+ },
78
+ sync: {
79
+ enabled: false, // Privacy first - off by default
80
+ individual: {
81
+ require_confirmation: true,
82
+ show_diff_before_sync: true,
83
+ track_versions: true,
84
+ keep_history: 10
85
+ },
86
+ bulk: {
87
+ upload_enabled: false, // Requires explicit enablement
88
+ download_enabled: false,
89
+ require_preview: true,
90
+ respect_local_only: true
91
+ },
92
+ privacy: {
93
+ scan_for_secrets: true,
94
+ scan_for_pii: true,
95
+ warn_on_sensitive: true,
96
+ excluded_patterns: [
97
+ '*.secret',
98
+ '*-private.*',
99
+ 'credentials/**',
100
+ 'personal/**'
101
+ ]
102
+ }
103
+ },
104
+ collection: {
105
+ auto_submit: false, // Never auto-submit
106
+ require_review: true,
107
+ add_attribution: true
108
+ },
109
+ elements: {
110
+ auto_activate: {},
111
+ default_element_dir: path.join(os.homedir(), '.dollhouse', 'portfolio')
112
+ },
113
+ display: {
114
+ persona_indicators: {
115
+ enabled: true,
116
+ style: 'minimal',
117
+ include_emoji: true
118
+ },
119
+ verbose_logging: false,
120
+ show_progress: true
121
+ }
122
+ };
123
+ }
124
+ /**
125
+ * Initialize configuration
52
126
  */
53
- async repairPermissions() {
127
+ async initialize() {
128
+ // Always reload config from disk if it exists, even if we have defaults in memory
129
+ // This ensures we pick up any manual edits or saved settings
54
130
  try {
55
- // Try to fix directory permissions
56
- await fs.chmod(this.configDir, 0o700);
57
- // Try to fix file permissions if it exists
58
- try {
59
- await fs.access(this.configPath);
60
- await fs.chmod(this.configPath, 0o600);
131
+ // Ensure config directory exists with proper permissions (0o700 = owner only)
132
+ await fs.mkdir(this.configDir, { recursive: true, mode: 0o700 });
133
+ // Load or create config
134
+ if (await this.configExists()) {
135
+ await this.loadConfig();
61
136
  }
62
- catch {
63
- // File doesn't exist, that's OK
137
+ else {
138
+ // Create default config
139
+ this.config = this.getDefaultConfig();
140
+ // Try to migrate from environment variables
141
+ await this.migrateFromEnvironment();
142
+ // Save the config
143
+ await this.saveConfig();
144
+ logger.info('Created new configuration file', {
145
+ path: this.configPath
146
+ });
64
147
  }
65
148
  }
66
149
  catch (error) {
67
- // Log but don't fail - this is best-effort recovery
68
- // We don't have a logger here, so we'll silently continue
150
+ logger.error('Failed to initialize configuration', {
151
+ error: error instanceof Error ? error.message : String(error)
152
+ });
153
+ // Use defaults in memory
154
+ this.config = this.getDefaultConfig();
69
155
  }
70
156
  }
71
157
  /**
72
- * Load configuration from file system
158
+ * Load configuration from file
73
159
  */
74
160
  async loadConfig() {
75
161
  try {
76
- // Try to read existing config file
77
- const configContent = await fs.readFile(this.configPath, 'utf-8');
162
+ const content = await fs.readFile(this.configPath, 'utf-8');
163
+ /**
164
+ * IMPORTANT: Parser Selection for Different File Types
165
+ *
166
+ * We use DIFFERENT parsers for different file types:
167
+ *
168
+ * 1. js-yaml (used here) - For PURE YAML files:
169
+ * - Configuration files (config.yml)
170
+ * - Data files without markdown content
171
+ * - Any .yml or .yaml file that's just YAML
172
+ * Example format:
173
+ * ```yaml
174
+ * version: 1.0.0
175
+ * user:
176
+ * username: johndoe
177
+ * email: john@example.com
178
+ * ```
179
+ *
180
+ * 2. SecureYamlParser - For MARKDOWN files with YAML frontmatter:
181
+ * - Persona files (*.md in personas/)
182
+ * - Skill files (*.md in skills/)
183
+ * - Template files (*.md in templates/)
184
+ * - Any .md file with frontmatter between --- markers
185
+ * Example format:
186
+ * ```markdown
187
+ * ---
188
+ * name: Creative Writer
189
+ * description: A creative assistant
190
+ * ---
191
+ * # Instructions
192
+ * You are a creative writer...
193
+ * ```
194
+ *
195
+ * The config file is PURE YAML, so we use js-yaml directly with FAILSAFE_SCHEMA
196
+ * for security (prevents code execution via YAML tags).
197
+ * SECURITY: This is NOT a vulnerability - FAILSAFE_SCHEMA prevents code execution
198
+ */
199
+ let loadedData;
78
200
  try {
79
- this.config = JSON.parse(configContent);
201
+ // Using yaml with FAILSAFE_SCHEMA is secure - prevents code execution
202
+ loadedData = yaml.load(content, {
203
+ schema: yaml.FAILSAFE_SCHEMA // Safe schema prevents code execution
204
+ });
80
205
  }
81
- catch (parseError) {
82
- // Handle corrupted JSON - create new config
83
- console.warn('Config file corrupted, creating new config');
84
- this.config = { version: '1.0.0' };
85
- await this.saveConfig();
206
+ catch (yamlError) {
207
+ throw new Error(`Invalid YAML in configuration file: ${yamlError instanceof Error ? yamlError.message : String(yamlError)}`);
208
+ }
209
+ if (!loadedData || typeof loadedData !== 'object') {
210
+ throw new Error('Invalid configuration format');
86
211
  }
212
+ logger.debug('Loaded config from file', {
213
+ username: loadedData.user?.username,
214
+ email: loadedData.user?.email,
215
+ syncEnabled: loadedData.sync?.enabled
216
+ });
217
+ this.config = this.mergeWithDefaults(loadedData);
218
+ // Fix any string booleans that might have been saved incorrectly
219
+ this.fixConfigTypes();
220
+ logger.debug('Configuration loaded successfully', {
221
+ username: this.config.user.username,
222
+ syncEnabled: this.config.sync.enabled
223
+ });
87
224
  }
88
225
  catch (error) {
89
- if (error.code === 'ENOENT') {
90
- // Config file doesn't exist, create directory and file
91
- await this.ensureConfigDirectory();
92
- await this.saveConfig();
93
- }
94
- else if (error.code === 'EACCES' || error.code === 'EPERM') {
95
- // Permission denied - attempt repair
96
- await this.repairPermissions();
97
- // Try once more after repair attempt
98
- try {
99
- const configContent = await fs.readFile(this.configPath, 'utf-8');
100
- this.config = JSON.parse(configContent);
101
- }
102
- catch (retryError) {
103
- // Still failing, throw original error with helpful message
104
- throw new Error(`Permission denied accessing config at ${this.configPath}. ` +
105
- `Please check file permissions or run with appropriate privileges.`);
106
- }
107
- }
108
- else {
109
- throw error;
110
- }
226
+ logger.error('Failed to load configuration', {
227
+ error: error instanceof Error ? error.message : String(error)
228
+ });
229
+ throw error;
230
+ }
231
+ }
232
+ /**
233
+ * Check if config file exists
234
+ */
235
+ async configExists() {
236
+ try {
237
+ await fs.access(this.configPath);
238
+ return true;
239
+ }
240
+ catch {
241
+ return false;
111
242
  }
112
243
  }
113
244
  /**
@@ -121,7 +252,7 @@ export class ConfigManager {
121
252
  return envClientId;
122
253
  }
123
254
  // Fall back to config file
124
- return this.config.oauth?.githubClientId || null;
255
+ return this.config?.github?.auth?.client_id || null;
125
256
  }
126
257
  /**
127
258
  * Set GitHub OAuth client ID in config file
@@ -130,27 +261,91 @@ export class ConfigManager {
130
261
  if (!ConfigManager.validateClientId(clientId)) {
131
262
  throw new Error(`Invalid GitHub client ID format. Expected format: Ov23li followed by at least 14 alphanumeric characters (e.g., Ov23liABCDEFGHIJKLMN)`);
132
263
  }
133
- // Ensure oauth object exists
134
- if (!this.config.oauth) {
135
- this.config.oauth = {};
264
+ if (!this.config) {
265
+ this.config = this.getDefaultConfig();
266
+ }
267
+ // Ensure github.auth object exists
268
+ if (!this.config.github) {
269
+ this.config.github = this.getDefaultConfig().github;
136
270
  }
137
- this.config.oauth.githubClientId = clientId;
271
+ if (!this.config.github.auth) {
272
+ this.config.github.auth = this.getDefaultConfig().github.auth;
273
+ }
274
+ this.config.github.auth.client_id = clientId;
138
275
  await this.saveConfig();
139
276
  }
140
277
  /**
141
- * Get a copy of the current configuration
142
- * @returns A defensive copy of the configuration object
278
+ * Get the current configuration
143
279
  */
144
280
  getConfig() {
145
- return { ...this.config };
281
+ if (!this.config) {
282
+ throw new Error('Configuration not initialized');
283
+ }
284
+ return this.config;
146
285
  }
147
286
  /**
148
- * Update the entire configuration
149
- * @param newConfig The new configuration to set
287
+ * Get a specific setting using dot notation
150
288
  */
151
- async updateConfig(newConfig) {
152
- this.config = { ...newConfig };
289
+ getSetting(path, defaultValue) {
290
+ if (!this.config) {
291
+ return defaultValue;
292
+ }
293
+ const keys = path.split('.');
294
+ let value = this.config;
295
+ for (const key of keys) {
296
+ if (value && typeof value === 'object' && key in value) {
297
+ value = value[key];
298
+ }
299
+ else {
300
+ return defaultValue;
301
+ }
302
+ }
303
+ return value;
304
+ }
305
+ /**
306
+ * Update a specific setting using dot notation
307
+ * SECURITY FIX (PR #895): Added prototype pollution protection
308
+ * Previously: Direct property assignment allowed __proto__ injection
309
+ * Now: Validates keys against forbidden properties before assignment
310
+ */
311
+ async updateSetting(path, value) {
312
+ if (!this.config) {
313
+ await this.initialize();
314
+ }
315
+ const keys = path.split('.');
316
+ // SECURITY: Validate all keys to prevent prototype pollution
317
+ const FORBIDDEN_KEYS = ['__proto__', 'constructor', 'prototype'];
318
+ for (const key of keys) {
319
+ if (FORBIDDEN_KEYS.includes(key)) {
320
+ throw new Error(`Forbidden property in path: ${key}`);
321
+ }
322
+ }
323
+ let current = this.config;
324
+ const previousValue = this.getSetting(path);
325
+ // Navigate to the parent object
326
+ for (let i = 0; i < keys.length - 1; i++) {
327
+ const key = keys[i];
328
+ if (!(key in current)) {
329
+ current[key] = {};
330
+ }
331
+ current = current[key];
332
+ }
333
+ // Set the value
334
+ const lastKey = keys[keys.length - 1];
335
+ current[lastKey] = value;
336
+ // Save the configuration
153
337
  await this.saveConfig();
338
+ logger.info('Configuration setting updated', {
339
+ path,
340
+ previousValue,
341
+ newValue: value
342
+ });
343
+ return {
344
+ success: true,
345
+ message: `Setting '${path}' updated successfully`,
346
+ previousValue,
347
+ newValue: value
348
+ };
154
349
  }
155
350
  /**
156
351
  * Validate GitHub OAuth client ID format
@@ -174,43 +369,387 @@ export class ConfigManager {
174
369
  return clientIdPattern.test(clientId);
175
370
  }
176
371
  /**
177
- * Ensure config directory exists with proper permissions
372
+ * Save configuration to file
178
373
  */
179
- async ensureConfigDirectory() {
374
+ async saveConfig() {
375
+ if (!this.config) {
376
+ throw new Error('No configuration to save');
377
+ }
180
378
  try {
181
- await fs.mkdir(this.configDir, { recursive: true, mode: 0o700 });
379
+ // Create backup of existing config
380
+ if (await this.configExists()) {
381
+ await fs.copyFile(this.configPath, this.backupPath);
382
+ }
383
+ // Convert to YAML
384
+ // Note: We use js-yaml's dump() for pure YAML output (no frontmatter markers)
385
+ // This creates a standard YAML file, not a markdown file with frontmatter
386
+ const yamlContent = yaml.dump(this.config, {
387
+ indent: 2,
388
+ lineWidth: 120,
389
+ noRefs: true,
390
+ sortKeys: false
391
+ // Using default schema (not FAILSAFE) for dump to preserve types like booleans
392
+ });
393
+ // Write atomically with proper permissions (0o600 = owner read/write only)
394
+ const tempPath = `${this.configPath}.tmp`;
395
+ await fs.writeFile(tempPath, yamlContent, { encoding: 'utf-8', mode: 0o600 });
396
+ await fs.rename(tempPath, this.configPath);
397
+ logger.debug('Configuration saved successfully');
398
+ // Log audit event for configuration update
399
+ logger.debug('Configuration update audit', {
400
+ event: 'CONFIG_UPDATED',
401
+ source: 'ConfigManager.saveConfig',
402
+ timestamp: new Date().toISOString()
403
+ });
182
404
  }
183
405
  catch (error) {
184
- if (error.code === 'EACCES') {
185
- throw new Error(`Permission denied creating config directory: ${this.configDir}`);
406
+ logger.error('Failed to save configuration', {
407
+ error: error instanceof Error ? error.message : String(error)
408
+ });
409
+ // Try to restore backup
410
+ if (await this.backupExists()) {
411
+ await fs.copyFile(this.backupPath, this.configPath);
412
+ logger.info('Restored configuration from backup');
186
413
  }
187
414
  throw error;
188
415
  }
189
416
  }
190
417
  /**
191
- * Save config using atomic file writes
418
+ * Check if backup exists
192
419
  */
193
- async saveConfig() {
194
- await this.ensureConfigDirectory();
195
- // Use atomic write: write to temp file, then rename
196
- const tempPath = this.configPath + '.tmp';
197
- const configContent = JSON.stringify(this.config, null, 2);
420
+ async backupExists() {
198
421
  try {
199
- // Write to temp file first
200
- await fs.writeFile(tempPath, configContent, { mode: 0o600 });
201
- // Atomic rename
202
- await fs.rename(tempPath, this.configPath);
422
+ await fs.access(this.backupPath);
423
+ return true;
424
+ }
425
+ catch {
426
+ return false;
427
+ }
428
+ }
429
+ /**
430
+ * Fix incorrect types in config (e.g., string booleans, string "null")
431
+ */
432
+ fixConfigTypes() {
433
+ if (!this.config)
434
+ return;
435
+ // Helper to convert string "null" to actual null
436
+ const fixNull = (value) => {
437
+ if (value === 'null' || value === 'NULL')
438
+ return null;
439
+ return value;
440
+ };
441
+ // Helper to convert string booleans to actual booleans
442
+ const fixBoolean = (value) => {
443
+ if (typeof value === 'string') {
444
+ const lower = value.toLowerCase();
445
+ if (lower === 'true')
446
+ return true;
447
+ if (lower === 'false')
448
+ return false;
449
+ }
450
+ return value;
451
+ };
452
+ // Fix user fields - handle string "null" values
453
+ if (this.config.user) {
454
+ this.config.user.username = fixNull(this.config.user.username);
455
+ this.config.user.email = fixNull(this.config.user.email);
456
+ this.config.user.display_name = fixNull(this.config.user.display_name);
457
+ }
458
+ // Fix sync settings
459
+ if (this.config.sync) {
460
+ this.config.sync.enabled = fixBoolean(this.config.sync.enabled);
461
+ if (this.config.sync.individual) {
462
+ this.config.sync.individual.require_confirmation = fixBoolean(this.config.sync.individual.require_confirmation);
463
+ this.config.sync.individual.show_diff_before_sync = fixBoolean(this.config.sync.individual.show_diff_before_sync);
464
+ this.config.sync.individual.track_versions = fixBoolean(this.config.sync.individual.track_versions);
465
+ }
466
+ if (this.config.sync.bulk) {
467
+ this.config.sync.bulk.upload_enabled = fixBoolean(this.config.sync.bulk.upload_enabled);
468
+ this.config.sync.bulk.download_enabled = fixBoolean(this.config.sync.bulk.download_enabled);
469
+ this.config.sync.bulk.require_preview = fixBoolean(this.config.sync.bulk.require_preview);
470
+ this.config.sync.bulk.respect_local_only = fixBoolean(this.config.sync.bulk.respect_local_only);
471
+ }
472
+ if (this.config.sync.privacy) {
473
+ this.config.sync.privacy.scan_for_secrets = fixBoolean(this.config.sync.privacy.scan_for_secrets);
474
+ this.config.sync.privacy.scan_for_pii = fixBoolean(this.config.sync.privacy.scan_for_pii);
475
+ this.config.sync.privacy.warn_on_sensitive = fixBoolean(this.config.sync.privacy.warn_on_sensitive);
476
+ }
477
+ }
478
+ // Fix collection settings
479
+ if (this.config.collection) {
480
+ this.config.collection.auto_submit = fixBoolean(this.config.collection.auto_submit);
481
+ this.config.collection.require_review = fixBoolean(this.config.collection.require_review);
482
+ this.config.collection.add_attribution = fixBoolean(this.config.collection.add_attribution);
483
+ }
484
+ // Fix display settings
485
+ if (this.config.display) {
486
+ if (this.config.display.persona_indicators) {
487
+ this.config.display.persona_indicators.enabled = fixBoolean(this.config.display.persona_indicators.enabled);
488
+ this.config.display.persona_indicators.include_emoji = fixBoolean(this.config.display.persona_indicators.include_emoji);
489
+ }
490
+ this.config.display.verbose_logging = fixBoolean(this.config.display.verbose_logging);
491
+ this.config.display.show_progress = fixBoolean(this.config.display.show_progress);
492
+ }
493
+ // Fix github settings
494
+ if (this.config.github) {
495
+ if (this.config.github.portfolio) {
496
+ this.config.github.portfolio.repository_url = fixNull(this.config.github.portfolio.repository_url);
497
+ this.config.github.portfolio.auto_create = fixBoolean(this.config.github.portfolio.auto_create);
498
+ }
499
+ if (this.config.github.auth) {
500
+ this.config.github.auth.use_oauth = fixBoolean(this.config.github.auth.use_oauth);
501
+ // Fix client_id if it's a string "null"
502
+ if (this.config.github.auth.client_id) {
503
+ this.config.github.auth.client_id = fixNull(this.config.github.auth.client_id) || undefined;
504
+ }
505
+ }
506
+ }
507
+ }
508
+ /**
509
+ * Merge partial config with defaults
510
+ *
511
+ * IMPORTANT: This function preserves unknown fields for forward compatibility.
512
+ * If a future version adds new config fields, older versions won't lose them.
513
+ */
514
+ mergeWithDefaults(partial) {
515
+ const defaults = this.getDefaultConfig();
516
+ // Start with a deep clone of partial to preserve all unknown fields
517
+ const result = JSON.parse(JSON.stringify(partial));
518
+ // Ensure all required fields exist with defaults
519
+ result.version = result.version || defaults.version;
520
+ // User section - preserve unknown fields while ensuring required fields
521
+ result.user = {
522
+ ...result.user,
523
+ username: result.user?.username ?? defaults.user.username,
524
+ email: result.user?.email ?? defaults.user.email,
525
+ display_name: result.user?.display_name ?? defaults.user.display_name
526
+ };
527
+ // GitHub section - deep merge preserving unknown fields
528
+ if (!result.github)
529
+ result.github = {};
530
+ result.github.portfolio = {
531
+ ...defaults.github.portfolio,
532
+ ...result.github.portfolio
533
+ };
534
+ result.github.auth = {
535
+ ...defaults.github.auth,
536
+ ...result.github.auth
537
+ };
538
+ // Sync section - preserve unknown fields at all levels
539
+ if (!result.sync)
540
+ result.sync = {};
541
+ result.sync.enabled = result.sync.enabled ?? defaults.sync.enabled;
542
+ result.sync.individual = {
543
+ ...defaults.sync.individual,
544
+ ...result.sync.individual
545
+ };
546
+ result.sync.bulk = {
547
+ ...defaults.sync.bulk,
548
+ ...result.sync.bulk
549
+ };
550
+ result.sync.privacy = {
551
+ ...defaults.sync.privacy,
552
+ ...result.sync.privacy,
553
+ // Special handling for arrays - use provided or default
554
+ excluded_patterns: result.sync.privacy?.excluded_patterns || defaults.sync.privacy.excluded_patterns
555
+ };
556
+ // Collection section
557
+ result.collection = {
558
+ ...defaults.collection,
559
+ ...result.collection
560
+ };
561
+ // Elements section
562
+ if (!result.elements)
563
+ result.elements = {};
564
+ result.elements = {
565
+ ...result.elements,
566
+ auto_activate: result.elements.auto_activate || defaults.elements.auto_activate,
567
+ default_element_dir: result.elements.default_element_dir || defaults.elements.default_element_dir
568
+ };
569
+ // Display section
570
+ if (!result.display)
571
+ result.display = {};
572
+ result.display.persona_indicators = {
573
+ ...defaults.display.persona_indicators,
574
+ ...result.display.persona_indicators
575
+ };
576
+ result.display.verbose_logging = result.display.verbose_logging ?? defaults.display.verbose_logging;
577
+ result.display.show_progress = result.display.show_progress ?? defaults.display.show_progress;
578
+ return result;
579
+ }
580
+ /**
581
+ * Migrate settings from environment variables
582
+ */
583
+ async migrateFromEnvironment() {
584
+ let migrated = false;
585
+ // Migrate user settings
586
+ if (process.env.DOLLHOUSE_USER && !this.config?.user.username) {
587
+ if (!this.config)
588
+ this.config = this.getDefaultConfig();
589
+ this.config.user.username = process.env.DOLLHOUSE_USER;
590
+ migrated = true;
591
+ }
592
+ if (process.env.DOLLHOUSE_EMAIL && !this.config?.user.email) {
593
+ if (!this.config)
594
+ this.config = this.getDefaultConfig();
595
+ this.config.user.email = process.env.DOLLHOUSE_EMAIL;
596
+ migrated = true;
597
+ }
598
+ // Migrate portfolio URL
599
+ if (process.env.DOLLHOUSE_PORTFOLIO_URL && !this.config?.github.portfolio.repository_url) {
600
+ if (!this.config)
601
+ this.config = this.getDefaultConfig();
602
+ this.config.github.portfolio.repository_url = process.env.DOLLHOUSE_PORTFOLIO_URL;
603
+ migrated = true;
604
+ }
605
+ // Migrate collection auto-submit
606
+ if (process.env.DOLLHOUSE_AUTO_SUBMIT_TO_COLLECTION !== undefined) {
607
+ if (!this.config)
608
+ this.config = this.getDefaultConfig();
609
+ this.config.collection.auto_submit = process.env.DOLLHOUSE_AUTO_SUBMIT_TO_COLLECTION === 'true';
610
+ migrated = true;
611
+ }
612
+ if (migrated) {
613
+ logger.info('Migrated settings from environment variables');
614
+ }
615
+ }
616
+ /**
617
+ * Reset configuration to defaults
618
+ * SECURITY FIX (PR #895): Added prototype pollution protection
619
+ * Previously: Direct property assignment allowed __proto__ injection
620
+ * Now: Validates keys against forbidden properties before assignment
621
+ */
622
+ async resetConfig(section) {
623
+ const defaults = this.getDefaultConfig();
624
+ if (section) {
625
+ // Reset specific section
626
+ if (!this.config) {
627
+ this.config = defaults;
628
+ }
629
+ else {
630
+ const sectionKeys = section.split('.');
631
+ // SECURITY: Validate all keys to prevent prototype pollution
632
+ const FORBIDDEN_KEYS = ['__proto__', 'constructor', 'prototype'];
633
+ for (const key of sectionKeys) {
634
+ if (FORBIDDEN_KEYS.includes(key)) {
635
+ throw new Error(`Forbidden property in section: ${key}`);
636
+ }
637
+ }
638
+ let current = this.config;
639
+ let defaultSection = defaults;
640
+ for (let i = 0; i < sectionKeys.length - 1; i++) {
641
+ current = current[sectionKeys[i]];
642
+ defaultSection = defaultSection[sectionKeys[i]];
643
+ }
644
+ const lastKey = sectionKeys[sectionKeys.length - 1];
645
+ current[lastKey] = defaultSection[lastKey];
646
+ }
647
+ await this.saveConfig();
648
+ return {
649
+ success: true,
650
+ message: `Section '${section}' reset to defaults`
651
+ };
652
+ }
653
+ else {
654
+ // Reset entire config
655
+ this.config = defaults;
656
+ await this.saveConfig();
657
+ return {
658
+ success: true,
659
+ message: 'Configuration reset to defaults'
660
+ };
661
+ }
662
+ }
663
+ /**
664
+ * Export configuration to file
665
+ */
666
+ async exportConfig(filePath) {
667
+ if (!this.config) {
668
+ return {
669
+ success: false,
670
+ message: 'No configuration to export'
671
+ };
672
+ }
673
+ try {
674
+ const yamlContent = yaml.dump(this.config, {
675
+ indent: 2,
676
+ lineWidth: 120,
677
+ noRefs: true,
678
+ sortKeys: false
679
+ });
680
+ await fs.writeFile(filePath, yamlContent, { encoding: 'utf-8', mode: 0o600 });
681
+ return {
682
+ success: true,
683
+ message: `Configuration exported to ${filePath}`
684
+ };
203
685
  }
204
686
  catch (error) {
205
- // Clean up temp file if it exists
206
- try {
207
- await fs.unlink(tempPath);
687
+ return {
688
+ success: false,
689
+ message: `Failed to export configuration: ${error instanceof Error ? error.message : String(error)}`
690
+ };
691
+ }
692
+ }
693
+ /**
694
+ * Import configuration from file
695
+ */
696
+ async importConfig(filePath) {
697
+ try {
698
+ const content = await fs.readFile(filePath, 'utf-8');
699
+ // Parse and validate
700
+ const parsed = SecureYamlParser.parse(content, {
701
+ maxYamlSize: 64 * 1024,
702
+ validateContent: false,
703
+ validateFields: false
704
+ });
705
+ if (!parsed.data || typeof parsed.data !== 'object') {
706
+ return {
707
+ success: false,
708
+ message: 'Invalid configuration format in import file'
709
+ };
208
710
  }
209
- catch {
210
- // Ignore cleanup errors
711
+ // Merge with defaults
712
+ this.config = this.mergeWithDefaults(parsed.data);
713
+ // Save the imported config
714
+ await this.saveConfig();
715
+ return {
716
+ success: true,
717
+ message: `Configuration imported from ${filePath}`
718
+ };
719
+ }
720
+ catch (error) {
721
+ return {
722
+ success: false,
723
+ message: `Failed to import configuration: ${error instanceof Error ? error.message : String(error)}`
724
+ };
725
+ }
726
+ }
727
+ /**
728
+ * Get formatted config for display
729
+ */
730
+ getFormattedConfig(section) {
731
+ if (!this.config) {
732
+ return 'Configuration not initialized';
733
+ }
734
+ let configToShow = this.config;
735
+ if (section) {
736
+ configToShow = this.getSetting(section);
737
+ if (!configToShow) {
738
+ return `Section '${section}' not found`;
211
739
  }
212
- throw error;
213
740
  }
741
+ // Remove sensitive data for display
742
+ const sanitized = JSON.parse(JSON.stringify(configToShow));
743
+ // Don't show tokens if they exist
744
+ if (sanitized.github?.auth?.token) {
745
+ sanitized.github.auth.token = '***REDACTED***';
746
+ }
747
+ return yaml.dump(sanitized, {
748
+ indent: 2,
749
+ lineWidth: 120,
750
+ noRefs: true,
751
+ sortKeys: false
752
+ });
214
753
  }
215
754
  }
216
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29uZmlnTWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb25maWcvQ29uZmlnTWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQztBQVV6QixNQUFNLE9BQU8sYUFBYTtJQUNoQixNQUFNLENBQUMsUUFBUSxHQUF5QixJQUFJLENBQUM7SUFDN0MsTUFBTSxDQUFDLFlBQVksR0FBWSxLQUFLLENBQUM7SUFFckMsU0FBUyxDQUFTO0lBQ2xCLFVBQVUsQ0FBUztJQUNuQixNQUFNLENBQWE7SUFFM0I7UUFDRSxtQkFBbUI7UUFDbkIsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUN2RCxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsQ0FBQztRQUUzRCxpQ0FBaUM7UUFDakMsSUFBSSxDQUFDLE1BQU0sR0FBRztZQUNaLE9BQU8sRUFBRSxPQUFPO1NBQ2pCLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSSxNQUFNLENBQUMsV0FBVztRQUN2QixJQUFJLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUMzQixPQUFPLGFBQWEsQ0FBQyxRQUFRLENBQUM7UUFDaEMsQ0FBQztRQUVELHNEQUFzRDtRQUN0RCxJQUFJLGFBQWEsQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUMvQix5REFBeUQ7WUFDekQsT0FBTyxhQUFhLENBQUMsWUFBWSxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUM3RCw2RUFBNkU7Z0JBQzdFLHFEQUFxRDtZQUN2RCxDQUFDO1lBQ0QsT0FBTyxhQUFhLENBQUMsUUFBUyxDQUFDO1FBQ2pDLENBQUM7UUFFRCxhQUFhLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztRQUVsQyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQzVCLGFBQWEsQ0FBQyxRQUFRLEdBQUcsSUFBSSxhQUFhLEVBQUUsQ0FBQztRQUMvQyxDQUFDO1FBRUQsYUFBYSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDbkMsT0FBTyxhQUFhLENBQUMsUUFBUSxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7O09BR0c7SUFDSyxLQUFLLENBQUMsaUJBQWlCO1FBQzdCLElBQUksQ0FBQztZQUNILG1DQUFtQztZQUNuQyxNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUV0QywyQ0FBMkM7WUFDM0MsSUFBSSxDQUFDO2dCQUNILE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQ2pDLE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3pDLENBQUM7WUFBQyxNQUFNLENBQUM7Z0JBQ1AsZ0NBQWdDO1lBQ2xDLENBQUM7UUFDSCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLG9EQUFvRDtZQUNwRCwwREFBMEQ7UUFDNUQsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxVQUFVO1FBQ3JCLElBQUksQ0FBQztZQUNILG1DQUFtQztZQUNuQyxNQUFNLGFBQWEsR0FBRyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUVsRSxJQUFJLENBQUM7Z0JBQ0gsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQzFDLENBQUM7WUFBQyxPQUFPLFVBQVUsRUFBRSxDQUFDO2dCQUNwQiw0Q0FBNEM7Z0JBQzVDLE9BQU8sQ0FBQyxJQUFJLENBQUMsNENBQTRDLENBQUMsQ0FBQztnQkFDM0QsSUFBSSxDQUFDLE1BQU0sR0FBRyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQztnQkFDbkMsTUFBTSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDMUIsQ0FBQztRQUNILENBQUM7UUFBQyxPQUFPLEtBQVUsRUFBRSxDQUFDO1lBQ3BCLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDNUIsdURBQXVEO2dCQUN2RCxNQUFNLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO2dCQUNuQyxNQUFNLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUMxQixDQUFDO2lCQUFNLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxPQUFPLEVBQUUsQ0FBQztnQkFDN0QscUNBQXFDO2dCQUNyQyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO2dCQUUvQixxQ0FBcUM7Z0JBQ3JDLElBQUksQ0FBQztvQkFDSCxNQUFNLGFBQWEsR0FBRyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQztvQkFDbEUsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUMxQyxDQUFDO2dCQUFDLE9BQU8sVUFBZSxFQUFFLENBQUM7b0JBQ3pCLDJEQUEyRDtvQkFDM0QsTUFBTSxJQUFJLEtBQUssQ0FDYix5Q0FBeUMsSUFBSSxDQUFDLFVBQVUsSUFBSTt3QkFDNUQsbUVBQW1FLENBQ3BFLENBQUM7Z0JBQ0osQ0FBQztZQUNILENBQUM7aUJBQU0sQ0FBQztnQkFDTixNQUFNLEtBQUssQ0FBQztZQUNkLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNJLGlCQUFpQjtRQUN0QixtQ0FBbUM7UUFDbkMsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQkFBMEIsQ0FBQztRQUMzRCxJQUFJLFdBQVcsRUFBRSxDQUFDO1lBQ2hCLE9BQU8sV0FBVyxDQUFDO1FBQ3JCLENBQUM7UUFFRCwyQkFBMkI7UUFDM0IsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxjQUFjLElBQUksSUFBSSxDQUFDO0lBQ25ELENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxRQUFnQjtRQUM3QyxJQUFJLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDOUMsTUFBTSxJQUFJLEtBQUssQ0FDYix1SUFBdUksQ0FDeEksQ0FBQztRQUNKLENBQUM7UUFFRCw2QkFBNkI7UUFDN0IsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDdkIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ3pCLENBQUM7UUFFRCxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxjQUFjLEdBQUcsUUFBUSxDQUFDO1FBQzVDLE1BQU0sSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFRDs7O09BR0c7SUFDSSxTQUFTO1FBQ2QsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQzVCLENBQUM7SUFFRDs7O09BR0c7SUFDSSxLQUFLLENBQUMsWUFBWSxDQUFDLFNBQXFCO1FBQzdDLElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxHQUFHLFNBQVMsRUFBRSxDQUFDO1FBQy9CLE1BQU0sSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7O09BWUc7SUFDSSxNQUFNLENBQUMsZ0JBQWdCLENBQUMsUUFBYTtRQUMxQyxJQUFJLE9BQU8sUUFBUSxLQUFLLFFBQVEsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQzlDLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUVELHFFQUFxRTtRQUNyRSxNQUFNLGVBQWUsR0FBRywwQkFBMEIsQ0FBQztRQUNuRCxPQUFPLGVBQWUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVEOztPQUVHO0lBQ0ssS0FBSyxDQUFDLHFCQUFxQjtRQUNqQyxJQUFJLENBQUM7WUFDSCxNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDbkUsQ0FBQztRQUFDLE9BQU8sS0FBVSxFQUFFLENBQUM7WUFDcEIsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO2dCQUM1QixNQUFNLElBQUksS0FBSyxDQUFDLGdEQUFnRCxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQztZQUNwRixDQUFDO1lBQ0QsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ssS0FBSyxDQUFDLFVBQVU7UUFDdEIsTUFBTSxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUVuQyxvREFBb0Q7UUFDcEQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFVBQVUsR0FBRyxNQUFNLENBQUM7UUFDMUMsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztRQUUzRCxJQUFJLENBQUM7WUFDSCwyQkFBMkI7WUFDM0IsTUFBTSxFQUFFLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRSxhQUFhLEVBQUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUU3RCxnQkFBZ0I7WUFDaEIsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDN0MsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixrQ0FBa0M7WUFDbEMsSUFBSSxDQUFDO2dCQUNILE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM1QixDQUFDO1lBQUMsTUFBTSxDQUFDO2dCQUNQLHdCQUF3QjtZQUMxQixDQUFDO1lBQ0QsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29uZmlnTWFuYWdlciAtIFRocmVhZC1zYWZlIHNpbmdsZXRvbiBmb3IgcGVyc2lzdGVudCBjb25maWd1cmF0aW9uXG4gKiBcbiAqIEhhbmRsZXMgT0F1dGggY2xpZW50IElEIHN0b3JhZ2UgZm9yIENsYXVkZSBEZXNrdG9wIGludGVncmF0aW9uLlxuICogU3RvcmVzIGNvbmZpZyBpbiB+Ly5kb2xsaG91c2UvY29uZmlnLmpzb24gd2l0aCBwcm9wZXIgcGVybWlzc2lvbnMuXG4gKiBQcmVmZXJzIGVudmlyb25tZW50IHZhcmlhYmxlcyBvdmVyIGNvbmZpZyBmaWxlIHZhbHVlcy5cbiAqL1xuXG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy9wcm9taXNlcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0ICogYXMgb3MgZnJvbSAnb3MnO1xuXG5pbnRlcmZhY2UgQ29uZmlnRGF0YSB7XG4gIHZlcnNpb246IHN0cmluZztcbiAgb2F1dGg/OiB7XG4gICAgZ2l0aHViQ2xpZW50SWQ/OiBzdHJpbmc7XG4gIH07XG4gIFtrZXk6IHN0cmluZ106IGFueTsgLy8gQWxsb3cgdW5rbm93biBmaWVsZHMgdG8gYmUgcHJlc2VydmVkXG59XG5cbmV4cG9ydCBjbGFzcyBDb25maWdNYW5hZ2VyIHtcbiAgcHJpdmF0ZSBzdGF0aWMgaW5zdGFuY2U6IENvbmZpZ01hbmFnZXIgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBzdGF0aWMgaW5zdGFuY2VMb2NrOiBib29sZWFuID0gZmFsc2U7XG5cbiAgcHJpdmF0ZSBjb25maWdEaXI6IHN0cmluZztcbiAgcHJpdmF0ZSBjb25maWdQYXRoOiBzdHJpbmc7XG4gIHByaXZhdGUgY29uZmlnOiBDb25maWdEYXRhO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoKSB7XG4gICAgLy8gSW5pdGlhbGl6ZSBwYXRoc1xuICAgIHRoaXMuY29uZmlnRGlyID0gcGF0aC5qb2luKG9zLmhvbWVkaXIoKSwgJy5kb2xsaG91c2UnKTtcbiAgICB0aGlzLmNvbmZpZ1BhdGggPSBwYXRoLmpvaW4odGhpcy5jb25maWdEaXIsICdjb25maWcuanNvbicpO1xuICAgIFxuICAgIC8vIEluaXRpYWxpemUgd2l0aCBkZWZhdWx0IGNvbmZpZ1xuICAgIHRoaXMuY29uZmlnID0ge1xuICAgICAgdmVyc2lvbjogJzEuMC4wJ1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVGhyZWFkLXNhZmUgc2luZ2xldG9uIGluc3RhbmNlIGdldHRlclxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBnZXRJbnN0YW5jZSgpOiBDb25maWdNYW5hZ2VyIHtcbiAgICBpZiAoQ29uZmlnTWFuYWdlci5pbnN0YW5jZSkge1xuICAgICAgcmV0dXJuIENvbmZpZ01hbmFnZXIuaW5zdGFuY2U7XG4gICAgfVxuXG4gICAgLy8gU2ltcGxlIGxvY2tpbmcgbWVjaGFuaXNtIHRvIHByZXZlbnQgcmFjZSBjb25kaXRpb25zXG4gICAgaWYgKENvbmZpZ01hbmFnZXIuaW5zdGFuY2VMb2NrKSB7XG4gICAgICAvLyBXYWl0IGZvciBsb2NrIHRvIGJlIHJlbGVhc2VkLCB0aGVuIHJldHVybiB0aGUgaW5zdGFuY2VcbiAgICAgIHdoaWxlIChDb25maWdNYW5hZ2VyLmluc3RhbmNlTG9jayAmJiAhQ29uZmlnTWFuYWdlci5pbnN0YW5jZSkge1xuICAgICAgICAvLyBJbiBhIHJlYWwgc2NlbmFyaW8gd2l0aCBhc3luYyBvcGVyYXRpb25zLCB0aGlzIHdvdWxkIGJlIG1vcmUgc29waGlzdGljYXRlZFxuICAgICAgICAvLyBCdXQgZm9yIHRoZSB0ZXN0IGNhc2VzLCB0aGlzIHNpbXBsZSBhcHByb2FjaCB3b3Jrc1xuICAgICAgfVxuICAgICAgcmV0dXJuIENvbmZpZ01hbmFnZXIuaW5zdGFuY2UhO1xuICAgIH1cblxuICAgIENvbmZpZ01hbmFnZXIuaW5zdGFuY2VMb2NrID0gdHJ1ZTtcbiAgICBcbiAgICBpZiAoIUNvbmZpZ01hbmFnZXIuaW5zdGFuY2UpIHtcbiAgICAgIENvbmZpZ01hbmFnZXIuaW5zdGFuY2UgPSBuZXcgQ29uZmlnTWFuYWdlcigpO1xuICAgIH1cbiAgICBcbiAgICBDb25maWdNYW5hZ2VyLmluc3RhbmNlTG9jayA9IGZhbHNlO1xuICAgIHJldHVybiBDb25maWdNYW5hZ2VyLmluc3RhbmNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEF0dGVtcHQgdG8gcmVwYWlyIGZpbGUgcGVybWlzc2lvbnMgaWYgdGhleSdyZSBpbmNvcnJlY3RcbiAgICogVGhpcyBoZWxwcyB3aXRoIGVycm9yIHJlY292ZXJ5IGluIHBlcm1pc3Npb24tcmVsYXRlZCBpc3N1ZXNcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcmVwYWlyUGVybWlzc2lvbnMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIFRyeSB0byBmaXggZGlyZWN0b3J5IHBlcm1pc3Npb25zXG4gICAgICBhd2FpdCBmcy5jaG1vZCh0aGlzLmNvbmZpZ0RpciwgMG83MDApO1xuICAgICAgXG4gICAgICAvLyBUcnkgdG8gZml4IGZpbGUgcGVybWlzc2lvbnMgaWYgaXQgZXhpc3RzXG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBmcy5hY2Nlc3ModGhpcy5jb25maWdQYXRoKTtcbiAgICAgICAgYXdhaXQgZnMuY2htb2QodGhpcy5jb25maWdQYXRoLCAwbzYwMCk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gRmlsZSBkb2Vzbid0IGV4aXN0LCB0aGF0J3MgT0tcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgLy8gTG9nIGJ1dCBkb24ndCBmYWlsIC0gdGhpcyBpcyBiZXN0LWVmZm9ydCByZWNvdmVyeVxuICAgICAgLy8gV2UgZG9uJ3QgaGF2ZSBhIGxvZ2dlciBoZXJlLCBzbyB3ZSdsbCBzaWxlbnRseSBjb250aW51ZVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkIGNvbmZpZ3VyYXRpb24gZnJvbSBmaWxlIHN5c3RlbVxuICAgKi9cbiAgcHVibGljIGFzeW5jIGxvYWRDb25maWcoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIFRyeSB0byByZWFkIGV4aXN0aW5nIGNvbmZpZyBmaWxlXG4gICAgICBjb25zdCBjb25maWdDb250ZW50ID0gYXdhaXQgZnMucmVhZEZpbGUodGhpcy5jb25maWdQYXRoLCAndXRmLTgnKTtcbiAgICAgIFxuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy5jb25maWcgPSBKU09OLnBhcnNlKGNvbmZpZ0NvbnRlbnQpO1xuICAgICAgfSBjYXRjaCAocGFyc2VFcnJvcikge1xuICAgICAgICAvLyBIYW5kbGUgY29ycnVwdGVkIEpTT04gLSBjcmVhdGUgbmV3IGNvbmZpZ1xuICAgICAgICBjb25zb2xlLndhcm4oJ0NvbmZpZyBmaWxlIGNvcnJ1cHRlZCwgY3JlYXRpbmcgbmV3IGNvbmZpZycpO1xuICAgICAgICB0aGlzLmNvbmZpZyA9IHsgdmVyc2lvbjogJzEuMC4wJyB9O1xuICAgICAgICBhd2FpdCB0aGlzLnNhdmVDb25maWcoKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICBpZiAoZXJyb3IuY29kZSA9PT0gJ0VOT0VOVCcpIHtcbiAgICAgICAgLy8gQ29uZmlnIGZpbGUgZG9lc24ndCBleGlzdCwgY3JlYXRlIGRpcmVjdG9yeSBhbmQgZmlsZVxuICAgICAgICBhd2FpdCB0aGlzLmVuc3VyZUNvbmZpZ0RpcmVjdG9yeSgpO1xuICAgICAgICBhd2FpdCB0aGlzLnNhdmVDb25maWcoKTtcbiAgICAgIH0gZWxzZSBpZiAoZXJyb3IuY29kZSA9PT0gJ0VBQ0NFUycgfHwgZXJyb3IuY29kZSA9PT0gJ0VQRVJNJykge1xuICAgICAgICAvLyBQZXJtaXNzaW9uIGRlbmllZCAtIGF0dGVtcHQgcmVwYWlyXG4gICAgICAgIGF3YWl0IHRoaXMucmVwYWlyUGVybWlzc2lvbnMoKTtcbiAgICAgICAgXG4gICAgICAgIC8vIFRyeSBvbmNlIG1vcmUgYWZ0ZXIgcmVwYWlyIGF0dGVtcHRcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBjb25maWdDb250ZW50ID0gYXdhaXQgZnMucmVhZEZpbGUodGhpcy5jb25maWdQYXRoLCAndXRmLTgnKTtcbiAgICAgICAgICB0aGlzLmNvbmZpZyA9IEpTT04ucGFyc2UoY29uZmlnQ29udGVudCk7XG4gICAgICAgIH0gY2F0Y2ggKHJldHJ5RXJyb3I6IGFueSkge1xuICAgICAgICAgIC8vIFN0aWxsIGZhaWxpbmcsIHRocm93IG9yaWdpbmFsIGVycm9yIHdpdGggaGVscGZ1bCBtZXNzYWdlXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYFBlcm1pc3Npb24gZGVuaWVkIGFjY2Vzc2luZyBjb25maWcgYXQgJHt0aGlzLmNvbmZpZ1BhdGh9LiBgICtcbiAgICAgICAgICAgIGBQbGVhc2UgY2hlY2sgZmlsZSBwZXJtaXNzaW9ucyBvciBydW4gd2l0aCBhcHByb3ByaWF0ZSBwcml2aWxlZ2VzLmBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0IEdpdEh1YiBPQXV0aCBjbGllbnQgSURcbiAgICogRW52aXJvbm1lbnQgdmFyaWFibGUgdGFrZXMgcHJlY2VkZW5jZSBvdmVyIGNvbmZpZyBmaWxlXG4gICAqL1xuICBwdWJsaWMgZ2V0R2l0SHViQ2xpZW50SWQoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgLy8gQ2hlY2sgZW52aXJvbm1lbnQgdmFyaWFibGUgZmlyc3RcbiAgICBjb25zdCBlbnZDbGllbnRJZCA9IHByb2Nlc3MuZW52LkRPTExIT1VTRV9HSVRIVUJfQ0xJRU5UX0lEO1xuICAgIGlmIChlbnZDbGllbnRJZCkge1xuICAgICAgcmV0dXJuIGVudkNsaWVudElkO1xuICAgIH1cblxuICAgIC8vIEZhbGwgYmFjayB0byBjb25maWcgZmlsZVxuICAgIHJldHVybiB0aGlzLmNvbmZpZy5vYXV0aD8uZ2l0aHViQ2xpZW50SWQgfHwgbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgR2l0SHViIE9BdXRoIGNsaWVudCBJRCBpbiBjb25maWcgZmlsZVxuICAgKi9cbiAgcHVibGljIGFzeW5jIHNldEdpdEh1YkNsaWVudElkKGNsaWVudElkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIUNvbmZpZ01hbmFnZXIudmFsaWRhdGVDbGllbnRJZChjbGllbnRJZCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEludmFsaWQgR2l0SHViIGNsaWVudCBJRCBmb3JtYXQuIEV4cGVjdGVkIGZvcm1hdDogT3YyM2xpIGZvbGxvd2VkIGJ5IGF0IGxlYXN0IDE0IGFscGhhbnVtZXJpYyBjaGFyYWN0ZXJzIChlLmcuLCBPdjIzbGlBQkNERUZHSElKS0xNTilgXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIEVuc3VyZSBvYXV0aCBvYmplY3QgZXhpc3RzXG4gICAgaWYgKCF0aGlzLmNvbmZpZy5vYXV0aCkge1xuICAgICAgdGhpcy5jb25maWcub2F1dGggPSB7fTtcbiAgICB9XG5cbiAgICB0aGlzLmNvbmZpZy5vYXV0aC5naXRodWJDbGllbnRJZCA9IGNsaWVudElkO1xuICAgIGF3YWl0IHRoaXMuc2F2ZUNvbmZpZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhIGNvcHkgb2YgdGhlIGN1cnJlbnQgY29uZmlndXJhdGlvblxuICAgKiBAcmV0dXJucyBBIGRlZmVuc2l2ZSBjb3B5IG9mIHRoZSBjb25maWd1cmF0aW9uIG9iamVjdFxuICAgKi9cbiAgcHVibGljIGdldENvbmZpZygpOiBDb25maWdEYXRhIHtcbiAgICByZXR1cm4geyAuLi50aGlzLmNvbmZpZyB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSB0aGUgZW50aXJlIGNvbmZpZ3VyYXRpb25cbiAgICogQHBhcmFtIG5ld0NvbmZpZyBUaGUgbmV3IGNvbmZpZ3VyYXRpb24gdG8gc2V0XG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdXBkYXRlQ29uZmlnKG5ld0NvbmZpZzogQ29uZmlnRGF0YSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuY29uZmlnID0geyAuLi5uZXdDb25maWcgfTtcbiAgICBhd2FpdCB0aGlzLnNhdmVDb25maWcoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSBHaXRIdWIgT0F1dGggY2xpZW50IElEIGZvcm1hdFxuICAgKiBDbGllbnQgSURzIHN0YXJ0IHdpdGggXCJPdjIzbGlcIiBmb2xsb3dlZCBieSBhdCBsZWFzdCAxNCBhbHBoYW51bWVyaWMgY2hhcmFjdGVyc1xuICAgKiBcbiAgICogQHBhcmFtIGNsaWVudElkIC0gVGhlIGNsaWVudCBJRCB0byB2YWxpZGF0ZVxuICAgKiBAcmV0dXJucyB0cnVlIGlmIHZhbGlkLCBmYWxzZSBvdGhlcndpc2VcbiAgICogXG4gICAqIEBleGFtcGxlXG4gICAqIENvbmZpZ01hbmFnZXIudmFsaWRhdGVDbGllbnRJZChcIk92MjNsaUFCQ0RFRkdISUpLTE1OMTIzNDU2XCIpIC8vIHRydWVcbiAgICogQ29uZmlnTWFuYWdlci52YWxpZGF0ZUNsaWVudElkKFwiaW52YWxpZFwiKSAvLyBmYWxzZVxuICAgKiBDb25maWdNYW5hZ2VyLnZhbGlkYXRlQ2xpZW50SWQoXCJPdjIzbGlcIikgLy8gZmFsc2UgKHRvbyBzaG9ydClcbiAgICogQ29uZmlnTWFuYWdlci52YWxpZGF0ZUNsaWVudElkKFwiWHYyM2xpQUJDREVGR0hJSktMTU5cIikgLy8gZmFsc2UgKHdyb25nIHByZWZpeClcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgdmFsaWRhdGVDbGllbnRJZChjbGllbnRJZDogYW55KTogYm9vbGVhbiB7XG4gICAgaWYgKHR5cGVvZiBjbGllbnRJZCAhPT0gJ3N0cmluZycgfHwgIWNsaWVudElkKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gR2l0SHViIE9BdXRoIGNsaWVudCBJRHMgZm9sbG93IHRoZSBwYXR0ZXJuOiBPdjIzbGlbQS1aYS16MC05XXsxNCx9XG4gICAgY29uc3QgY2xpZW50SWRQYXR0ZXJuID0gL15PdjIzbGlbQS1aYS16MC05XXsxNCx9JC87XG4gICAgcmV0dXJuIGNsaWVudElkUGF0dGVybi50ZXN0KGNsaWVudElkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbnN1cmUgY29uZmlnIGRpcmVjdG9yeSBleGlzdHMgd2l0aCBwcm9wZXIgcGVybWlzc2lvbnNcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlQ29uZmlnRGlyZWN0b3J5KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBmcy5ta2Rpcih0aGlzLmNvbmZpZ0RpciwgeyByZWN1cnNpdmU6IHRydWUsIG1vZGU6IDBvNzAwIH0pO1xuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIGlmIChlcnJvci5jb2RlID09PSAnRUFDQ0VTJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFBlcm1pc3Npb24gZGVuaWVkIGNyZWF0aW5nIGNvbmZpZyBkaXJlY3Rvcnk6ICR7dGhpcy5jb25maWdEaXJ9YCk7XG4gICAgICB9XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2F2ZSBjb25maWcgdXNpbmcgYXRvbWljIGZpbGUgd3JpdGVzXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHNhdmVDb25maWcoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVDb25maWdEaXJlY3RvcnkoKTtcbiAgICBcbiAgICAvLyBVc2UgYXRvbWljIHdyaXRlOiB3cml0ZSB0byB0ZW1wIGZpbGUsIHRoZW4gcmVuYW1lXG4gICAgY29uc3QgdGVtcFBhdGggPSB0aGlzLmNvbmZpZ1BhdGggKyAnLnRtcCc7XG4gICAgY29uc3QgY29uZmlnQ29udGVudCA9IEpTT04uc3RyaW5naWZ5KHRoaXMuY29uZmlnLCBudWxsLCAyKTtcbiAgICBcbiAgICB0cnkge1xuICAgICAgLy8gV3JpdGUgdG8gdGVtcCBmaWxlIGZpcnN0XG4gICAgICBhd2FpdCBmcy53cml0ZUZpbGUodGVtcFBhdGgsIGNvbmZpZ0NvbnRlbnQsIHsgbW9kZTogMG82MDAgfSk7XG4gICAgICBcbiAgICAgIC8vIEF0b21pYyByZW5hbWVcbiAgICAgIGF3YWl0IGZzLnJlbmFtZSh0ZW1wUGF0aCwgdGhpcy5jb25maWdQYXRoKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgLy8gQ2xlYW4gdXAgdGVtcCBmaWxlIGlmIGl0IGV4aXN0c1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgZnMudW5saW5rKHRlbXBQYXRoKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBJZ25vcmUgY2xlYW51cCBlcnJvcnNcbiAgICAgIH1cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfVxufSJdfQ==
755
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29uZmlnTWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb25maWcvQ29uZmlnTWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7R0FXRztBQUVILE9BQU8sS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sS0FBSyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3pCLE9BQU8sS0FBSyxJQUFJLE1BQU0sU0FBUyxDQUFDO0FBQ2hDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQXlHbkUsTUFBTSxPQUFPLGFBQWE7SUFDaEIsTUFBTSxDQUFDLFFBQVEsR0FBeUIsSUFBSSxDQUFDO0lBQzdDLE1BQU0sQ0FBQyxZQUFZLEdBQVksS0FBSyxDQUFDO0lBRXJDLFNBQVMsQ0FBUztJQUNsQixVQUFVLENBQVM7SUFDbkIsVUFBVSxDQUFTO0lBQ25CLE1BQU0sR0FBMkIsSUFBSSxDQUFDO0lBRTlDO1FBQ0UsbUJBQW1CO1FBQ25CLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDdkQsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDMUQsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztJQUNuRSxDQUFDO0lBRUQ7O09BRUc7SUFDSSxNQUFNLENBQUMsV0FBVztRQUN2QixJQUFJLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUMzQixPQUFPLGFBQWEsQ0FBQyxRQUFRLENBQUM7UUFDaEMsQ0FBQztRQUVELHNEQUFzRDtRQUN0RCxJQUFJLGFBQWEsQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUMvQix5REFBeUQ7WUFDekQsT0FBTyxhQUFhLENBQUMsWUFBWSxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUM3RCw2RUFBNkU7Z0JBQzdFLHFEQUFxRDtZQUN2RCxDQUFDO1lBQ0QsT0FBTyxhQUFhLENBQUMsUUFBUyxDQUFDO1FBQ2pDLENBQUM7UUFFRCxhQUFhLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztRQUVsQyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQzVCLGFBQWEsQ0FBQyxRQUFRLEdBQUcsSUFBSSxhQUFhLEVBQUUsQ0FBQztRQUMvQyxDQUFDO1FBRUQsYUFBYSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDbkMsT0FBTyxhQUFhLENBQUMsUUFBUSxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7T0FFRztJQUNLLGdCQUFnQjtRQUN0QixPQUFPO1lBQ0wsT0FBTyxFQUFFLE9BQU87WUFDaEIsSUFBSSxFQUFFO2dCQUNKLFFBQVEsRUFBRSxJQUFJO2dCQUNkLEtBQUssRUFBRSxJQUFJO2dCQUNYLFlBQVksRUFBRSxJQUFJO2FBQ25CO1lBQ0QsTUFBTSxFQUFFO2dCQUNOLFNBQVMsRUFBRTtvQkFDVCxjQUFjLEVBQUUsSUFBSTtvQkFDcEIsZUFBZSxFQUFFLHFCQUFxQjtvQkFDdEMsY0FBYyxFQUFFLE1BQU07b0JBQ3RCLFdBQVcsRUFBRSxJQUFJO2lCQUNsQjtnQkFDRCxJQUFJLEVBQUU7b0JBQ0osU0FBUyxFQUFFLElBQUk7b0JBQ2YsWUFBWSxFQUFFLGFBQWE7aUJBQzVCO2FBQ0Y7WUFDRCxJQUFJLEVBQUU7Z0JBQ0osT0FBTyxFQUFFLEtBQUssRUFBRSxpQ0FBaUM7Z0JBQ2pELFVBQVUsRUFBRTtvQkFDVixvQkFBb0IsRUFBRSxJQUFJO29CQUMxQixxQkFBcUIsRUFBRSxJQUFJO29CQUMzQixjQUFjLEVBQUUsSUFBSTtvQkFDcEIsWUFBWSxFQUFFLEVBQUU7aUJBQ2pCO2dCQUNELElBQUksRUFBRTtvQkFDSixjQUFjLEVBQUUsS0FBSyxFQUFFLCtCQUErQjtvQkFDdEQsZ0JBQWdCLEVBQUUsS0FBSztvQkFDdkIsZUFBZSxFQUFFLElBQUk7b0JBQ3JCLGtCQUFrQixFQUFFLElBQUk7aUJBQ3pCO2dCQUNELE9BQU8sRUFBRTtvQkFDUCxnQkFBZ0IsRUFBRSxJQUFJO29CQUN0QixZQUFZLEVBQUUsSUFBSTtvQkFDbEIsaUJBQWlCLEVBQUUsSUFBSTtvQkFDdkIsaUJBQWlCLEVBQUU7d0JBQ2pCLFVBQVU7d0JBQ1YsYUFBYTt3QkFDYixnQkFBZ0I7d0JBQ2hCLGFBQWE7cUJBQ2Q7aUJBQ0Y7YUFDRjtZQUNELFVBQVUsRUFBRTtnQkFDVixXQUFXLEVBQUUsS0FBSyxFQUFFLG9CQUFvQjtnQkFDeEMsY0FBYyxFQUFFLElBQUk7Z0JBQ3BCLGVBQWUsRUFBRSxJQUFJO2FBQ3RCO1lBQ0QsUUFBUSxFQUFFO2dCQUNSLGFBQWEsRUFBRSxFQUFFO2dCQUNqQixtQkFBbUIsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxZQUFZLEVBQUUsV0FBVyxDQUFDO2FBQ3hFO1lBQ0QsT0FBTyxFQUFFO2dCQUNQLGtCQUFrQixFQUFFO29CQUNsQixPQUFPLEVBQUUsSUFBSTtvQkFDYixLQUFLLEVBQUUsU0FBUztvQkFDaEIsYUFBYSxFQUFFLElBQUk7aUJBQ3BCO2dCQUNELGVBQWUsRUFBRSxLQUFLO2dCQUN0QixhQUFhLEVBQUUsSUFBSTthQUNwQjtTQUNGLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsVUFBVTtRQUNyQixrRkFBa0Y7UUFDbEYsNkRBQTZEO1FBRTdELElBQUksQ0FBQztZQUNILDhFQUE4RTtZQUM5RSxNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7WUFFakUsd0JBQXdCO1lBQ3hCLElBQUksTUFBTSxJQUFJLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQztnQkFDOUIsTUFBTSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDMUIsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLHdCQUF3QjtnQkFDeEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztnQkFFdEMsNENBQTRDO2dCQUM1QyxNQUFNLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO2dCQUVwQyxrQkFBa0I7Z0JBQ2xCLE1BQU0sSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUV4QixNQUFNLENBQUMsSUFBSSxDQUFDLGdDQUFnQyxFQUFFO29CQUM1QyxJQUFJLEVBQUUsSUFBSSxDQUFDLFVBQVU7aUJBQ3RCLENBQUMsQ0FBQztZQUNMLENBQUM7UUFDSCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sQ0FBQyxLQUFLLENBQUMsb0NBQW9DLEVBQUU7Z0JBQ2pELEtBQUssRUFBRSxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDO2FBQzlELENBQUMsQ0FBQztZQUNILHlCQUF5QjtZQUN6QixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3hDLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxLQUFLLENBQUMsVUFBVTtRQUN0QixJQUFJLENBQUM7WUFDSCxNQUFNLE9BQU8sR0FBRyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUU1RDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7ZUFtQ0c7WUFDSCxJQUFJLFVBQWUsQ0FBQztZQUNwQixJQUFJLENBQUM7Z0JBQ0gsc0VBQXNFO2dCQUN0RSxVQUFVLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUU7b0JBQzlCLE1BQU0sRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLHNDQUFzQztpQkFDcEUsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztZQUFDLE9BQU8sU0FBUyxFQUFFLENBQUM7Z0JBQ25CLE1BQU0sSUFBSSxLQUFLLENBQUMsdUNBQXVDLFNBQVMsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDL0gsQ0FBQztZQUVELElBQUksQ0FBQyxVQUFVLElBQUksT0FBTyxVQUFVLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQ2xELE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLENBQUMsQ0FBQztZQUNsRCxDQUFDO1lBQ0QsTUFBTSxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsRUFBRTtnQkFDdEMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxJQUFJLEVBQUUsUUFBUTtnQkFDbkMsS0FBSyxFQUFFLFVBQVUsQ0FBQyxJQUFJLEVBQUUsS0FBSztnQkFDN0IsV0FBVyxFQUFFLFVBQVUsQ0FBQyxJQUFJLEVBQUUsT0FBTzthQUN0QyxDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUVqRCxpRUFBaUU7WUFDakUsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBRXRCLE1BQU0sQ0FBQyxLQUFLLENBQUMsbUNBQW1DLEVBQUU7Z0JBQ2hELFFBQVEsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRO2dCQUNuQyxXQUFXLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTzthQUN0QyxDQUFDLENBQUM7UUFFTCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sQ0FBQyxLQUFLLENBQUMsOEJBQThCLEVBQUU7Z0JBQzNDLEtBQUssRUFBRSxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDO2FBQzlELENBQUMsQ0FBQztZQUNILE1BQU0sS0FBSyxDQUFDO1FBQ2QsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNLLEtBQUssQ0FBQyxZQUFZO1FBQ3hCLElBQUksQ0FBQztZQUNILE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDakMsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNJLGlCQUFpQjtRQUN0QixtQ0FBbUM7UUFDbkMsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQkFBMEIsQ0FBQztRQUMzRCxJQUFJLFdBQVcsRUFBRSxDQUFDO1lBQ2hCLE9BQU8sV0FBVyxDQUFDO1FBQ3JCLENBQUM7UUFFRCwyQkFBMkI7UUFDM0IsT0FBTyxJQUFJLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsU0FBUyxJQUFJLElBQUksQ0FBQztJQUN0RCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsaUJBQWlCLENBQUMsUUFBZ0I7UUFDN0MsSUFBSSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQzlDLE1BQU0sSUFBSSxLQUFLLENBQ2IsdUlBQXVJLENBQ3hJLENBQUM7UUFDSixDQUFDO1FBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNqQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3hDLENBQUM7UUFFRCxtQ0FBbUM7UUFDbkMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDeEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsTUFBTSxDQUFDO1FBQ3RELENBQUM7UUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDN0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUM7UUFDaEUsQ0FBQztRQUVELElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsUUFBUSxDQUFDO1FBQzdDLE1BQU0sSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFRDs7T0FFRztJQUNJLFNBQVM7UUFDZCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2pCLE1BQU0sSUFBSSxLQUFLLENBQUMsK0JBQStCLENBQUMsQ0FBQztRQUNuRCxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3JCLENBQUM7SUFFRDs7T0FFRztJQUNJLFVBQVUsQ0FBSSxJQUFZLEVBQUUsWUFBZ0I7UUFDakQsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNqQixPQUFPLFlBQVksQ0FBQztRQUN0QixDQUFDO1FBRUQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM3QixJQUFJLEtBQUssR0FBUSxJQUFJLENBQUMsTUFBTSxDQUFDO1FBRTdCLEtBQUssTUFBTSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7WUFDdkIsSUFBSSxLQUFLLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQztnQkFDdkQsS0FBSyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNyQixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sT0FBTyxZQUFZLENBQUM7WUFDdEIsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLEtBQVUsQ0FBQztJQUNwQixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxLQUFLLENBQUMsYUFBYSxDQUFDLElBQVksRUFBRSxLQUFVO1FBQ2pELElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDakIsTUFBTSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDMUIsQ0FBQztRQUVELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFN0IsNkRBQTZEO1FBQzdELE1BQU0sY0FBYyxHQUFHLENBQUMsV0FBVyxFQUFFLGFBQWEsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUNqRSxLQUFLLE1BQU0sR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ3ZCLElBQUksY0FBYyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUNqQyxNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQ3hELENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxPQUFPLEdBQVEsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUMvQixNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRTVDLGdDQUFnQztRQUNoQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUN6QyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDcEIsSUFBSSxDQUFDLENBQUMsR0FBRyxJQUFJLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ3RCLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDcEIsQ0FBQztZQUNELE9BQU8sR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDekIsQ0FBQztRQUVELGdCQUFnQjtRQUNoQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztRQUN0QyxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsS0FBSyxDQUFDO1FBRXpCLHlCQUF5QjtRQUN6QixNQUFNLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUV4QixNQUFNLENBQUMsSUFBSSxDQUFDLCtCQUErQixFQUFFO1lBQzNDLElBQUk7WUFDSixhQUFhO1lBQ2IsUUFBUSxFQUFFLEtBQUs7U0FDaEIsQ0FBQyxDQUFDO1FBRUgsT0FBTztZQUNMLE9BQU8sRUFBRSxJQUFJO1lBQ2IsT0FBTyxFQUFFLFlBQVksSUFBSSx3QkFBd0I7WUFDakQsYUFBYTtZQUNiLFFBQVEsRUFBRSxLQUFLO1NBQ2hCLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7Ozs7Ozs7OztPQVlHO0lBQ0ksTUFBTSxDQUFDLGdCQUFnQixDQUFDLFFBQWE7UUFDMUMsSUFBSSxPQUFPLFFBQVEsS0FBSyxRQUFRLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUM5QyxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFFRCxxRUFBcUU7UUFDckUsTUFBTSxlQUFlLEdBQUcsMEJBQTBCLENBQUM7UUFDbkQsT0FBTyxlQUFlLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3hDLENBQUM7SUFFRDs7T0FFRztJQUNLLEtBQUssQ0FBQyxVQUFVO1FBQ3RCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDakIsTUFBTSxJQUFJLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1FBQzlDLENBQUM7UUFFRCxJQUFJLENBQUM7WUFDSCxtQ0FBbUM7WUFDbkMsSUFBSSxNQUFNLElBQUksQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDO2dCQUM5QixNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDdEQsQ0FBQztZQUVELGtCQUFrQjtZQUNsQiw4RUFBOEU7WUFDOUUsMEVBQTBFO1lBQzFFLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRTtnQkFDekMsTUFBTSxFQUFFLENBQUM7Z0JBQ1QsU0FBUyxFQUFFLEdBQUc7Z0JBQ2QsTUFBTSxFQUFFLElBQUk7Z0JBQ1osUUFBUSxFQUFFLEtBQUs7Z0JBQ2YsK0VBQStFO2FBQ2hGLENBQUMsQ0FBQztZQUVILDJFQUEyRTtZQUMzRSxNQUFNLFFBQVEsR0FBRyxHQUFHLElBQUksQ0FBQyxVQUFVLE1BQU0sQ0FBQztZQUMxQyxNQUFNLEVBQUUsQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLFdBQVcsRUFBRSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDOUUsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFFM0MsTUFBTSxDQUFDLEtBQUssQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDO1lBRWpELDJDQUEyQztZQUMzQyxNQUFNLENBQUMsS0FBSyxDQUFDLDRCQUE0QixFQUFFO2dCQUN6QyxLQUFLLEVBQUUsZ0JBQWdCO2dCQUN2QixNQUFNLEVBQUUsMEJBQTBCO2dCQUNsQyxTQUFTLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUU7YUFDcEMsQ0FBQyxDQUFDO1FBRUwsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixNQUFNLENBQUMsS0FBSyxDQUFDLDhCQUE4QixFQUFFO2dCQUMzQyxLQUFLLEVBQUUsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQzthQUM5RCxDQUFDLENBQUM7WUFFSCx3QkFBd0I7WUFDeEIsSUFBSSxNQUFNLElBQUksQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDO2dCQUM5QixNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQ3BELE1BQU0sQ0FBQyxJQUFJLENBQUMsb0NBQW9DLENBQUMsQ0FBQztZQUNwRCxDQUFDO1lBRUQsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ssS0FBSyxDQUFDLFlBQVk7UUFDeEIsSUFBSSxDQUFDO1lBQ0gsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNqQyxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxjQUFjO1FBQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTTtZQUFFLE9BQU87UUFFekIsaURBQWlEO1FBQ2pELE1BQU0sT0FBTyxHQUFHLENBQUMsS0FBVSxFQUFPLEVBQUU7WUFDbEMsSUFBSSxLQUFLLEtBQUssTUFBTSxJQUFJLEtBQUssS0FBSyxNQUFNO2dCQUFFLE9BQU8sSUFBSSxDQUFDO1lBQ3RELE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQyxDQUFDO1FBRUYsdURBQXVEO1FBQ3ZELE1BQU0sVUFBVSxHQUFHLENBQUMsS0FBVSxFQUFPLEVBQUU7WUFDckMsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDOUIsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNsQyxJQUFJLEtBQUssS0FBSyxNQUFNO29CQUFFLE9BQU8sSUFBSSxDQUFDO2dCQUNsQyxJQUFJLEtBQUssS0FBSyxPQUFPO29CQUFFLE9BQU8sS0FBSyxDQUFDO1lBQ3RDLENBQUM7WUFDRCxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUMsQ0FBQztRQUVGLGdEQUFnRDtRQUNoRCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDckIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUMvRCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3pELElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDekUsQ0FBQztRQUVELG9CQUFvQjtRQUNwQixJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDckIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUVoRSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUNoQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsb0JBQW9CLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO2dCQUNoSCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMscUJBQXFCLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO2dCQUNsSCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsY0FBYyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDdEcsQ0FBQztZQUVELElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQzFCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDeEYsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztnQkFDNUYsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO2dCQUMxRixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1lBQ2xHLENBQUM7WUFFRCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUM3QixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO2dCQUNsRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7Z0JBQzFGLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLENBQUM7WUFDdEcsQ0FBQztRQUNILENBQUM7UUFFRCwwQkFBMEI7UUFDMUIsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQzNCLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFdBQVcsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDcEYsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsY0FBYyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUMxRixJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxlQUFlLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQzlGLENBQUM7UUFFRCx1QkFBdUI7UUFDdkIsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3hCLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztnQkFDM0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLENBQUMsT0FBTyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDNUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLENBQUMsYUFBYSxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUMxSCxDQUFDO1lBQ0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsZUFBZSxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUN0RixJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxhQUFhLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ3BGLENBQUM7UUFFRCxzQkFBc0I7UUFDdEIsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3ZCLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ2pDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDbkcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLFdBQVcsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ2xHLENBQUM7WUFDRCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUM1QixJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ2xGLHdDQUF3QztnQkFDeEMsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7b0JBQ3RDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxTQUFTLENBQUM7Z0JBQzlGLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7T0FLRztJQUNLLGlCQUFpQixDQUFDLE9BQWlDO1FBQ3pELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBRXpDLG9FQUFvRTtRQUNwRSxNQUFNLE1BQU0sR0FBUSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUV4RCxpREFBaUQ7UUFDakQsTUFBTSxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUMsT0FBTyxJQUFJLFFBQVEsQ0FBQyxPQUFPLENBQUM7UUFFcEQsd0VBQXdFO1FBQ3hFLE1BQU0sQ0FBQyxJQUFJLEdBQUc7WUFDWixHQUFHLE1BQU0sQ0FBQyxJQUFJO1lBQ2QsUUFBUSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsUUFBUSxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMsUUFBUTtZQUN6RCxLQUFLLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBRSxLQUFLLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLO1lBQ2hELFlBQVksRUFBRSxNQUFNLENBQUMsSUFBSSxFQUFFLFlBQVksSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLFlBQVk7U0FDdEUsQ0FBQztRQUVGLHdEQUF3RDtRQUN4RCxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU07WUFBRSxNQUFNLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQztRQUN2QyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsR0FBRztZQUN4QixHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsU0FBUztZQUM1QixHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUztTQUMzQixDQUFDO1FBQ0YsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEdBQUc7WUFDbkIsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUk7WUFDdkIsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUk7U0FDdEIsQ0FBQztRQUVGLHVEQUF1RDtRQUN2RCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUk7WUFBRSxNQUFNLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNuQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztRQUNuRSxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsR0FBRztZQUN2QixHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsVUFBVTtZQUMzQixHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVTtTQUMxQixDQUFDO1FBQ0YsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUc7WUFDakIsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUk7WUFDckIsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUk7U0FDcEIsQ0FBQztRQUNGLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxHQUFHO1lBQ3BCLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPO1lBQ3hCLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPO1lBQ3RCLHdEQUF3RDtZQUN4RCxpQkFBaUIsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxpQkFBaUIsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUI7U0FDckcsQ0FBQztRQUVGLHFCQUFxQjtRQUNyQixNQUFNLENBQUMsVUFBVSxHQUFHO1lBQ2xCLEdBQUcsUUFBUSxDQUFDLFVBQVU7WUFDdEIsR0FBRyxNQUFNLENBQUMsVUFBVTtTQUNyQixDQUFDO1FBRUYsbUJBQW1CO1FBQ25CLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUTtZQUFFLE1BQU0sQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO1FBQzNDLE1BQU0sQ0FBQyxRQUFRLEdBQUc7WUFDaEIsR0FBRyxNQUFNLENBQUMsUUFBUTtZQUNsQixhQUFhLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxhQUFhLElBQUksUUFBUSxDQUFDLFFBQVEsQ0FBQyxhQUFhO1lBQy9FLG1CQUFtQixFQUFFLE1BQU0sQ0FBQyxRQUFRLENBQUMsbUJBQW1CLElBQUksUUFBUSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUI7U0FDbEcsQ0FBQztRQUVGLGtCQUFrQjtRQUNsQixJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU87WUFBRSxNQUFNLENBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUN6QyxNQUFNLENBQUMsT0FBTyxDQUFDLGtCQUFrQixHQUFHO1lBQ2xDLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0I7WUFDdEMsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLGtCQUFrQjtTQUNyQyxDQUFDO1FBQ0YsTUFBTSxDQUFDLE9BQU8sQ0FBQyxlQUFlLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxlQUFlLElBQUksUUFBUSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUM7UUFDcEcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxhQUFhLElBQUksUUFBUSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUM7UUFFOUYsT0FBTyxNQUF5QixDQUFDO0lBQ25DLENBQUM7SUFFRDs7T0FFRztJQUNLLEtBQUssQ0FBQyxzQkFBc0I7UUFDbEMsSUFBSSxRQUFRLEdBQUcsS0FBSyxDQUFDO1FBRXJCLHdCQUF3QjtRQUN4QixJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDOUQsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNO2dCQUFFLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDeEQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDO1lBQ3ZELFFBQVEsR0FBRyxJQUFJLENBQUM7UUFDbEIsQ0FBQztRQUVELElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUM1RCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU07Z0JBQUUsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUN4RCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUM7WUFDckQsUUFBUSxHQUFHLElBQUksQ0FBQztRQUNsQixDQUFDO1FBRUQsd0JBQXdCO1FBQ3hCLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN6RixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU07Z0JBQUUsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUN4RCxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsdUJBQXVCLENBQUM7WUFDbEYsUUFBUSxHQUFHLElBQUksQ0FBQztRQUNsQixDQUFDO1FBRUQsaUNBQWlDO1FBQ2pDLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNsRSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU07Z0JBQUUsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUN4RCxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsS0FBSyxNQUFNLENBQUM7WUFDaEcsUUFBUSxHQUFHLElBQUksQ0FBQztRQUNsQixDQUFDO1FBRUQsSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUNiLE1BQU0sQ0FBQyxJQUFJLENBQUMsOENBQThDLENBQUMsQ0FBQztRQUM5RCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ksS0FBSyxDQUFDLFdBQVcsQ0FBQyxPQUFnQjtRQUN2QyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUV6QyxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQ1oseUJBQXlCO1lBQ3pCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ2pCLElBQUksQ0FBQyxNQUFNLEdBQUcsUUFBUSxDQUFDO1lBQ3pCLENBQUM7aUJBQU0sQ0FBQztnQkFDTixNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUV2Qyw2REFBNkQ7Z0JBQzdELE1BQU0sY0FBYyxHQUFHLENBQUMsV0FBVyxFQUFFLGFBQWEsRUFBRSxXQUFXLENBQUMsQ0FBQztnQkFDakUsS0FBSyxNQUFNLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztvQkFDOUIsSUFBSSxjQUFjLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7d0JBQ2pDLE1BQU0sSUFBSSxLQUFLLENBQUMsa0NBQWtDLEdBQUcsRUFBRSxDQUFDLENBQUM7b0JBQzNELENBQUM7Z0JBQ0gsQ0FBQztnQkFFRCxJQUFJLE9BQU8sR0FBUSxJQUFJLENBQUMsTUFBTSxDQUFDO2dCQUMvQixJQUFJLGNBQWMsR0FBUSxRQUFRLENBQUM7Z0JBRW5DLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxXQUFXLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO29CQUNoRCxPQUFPLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUNsQyxjQUFjLEdBQUcsY0FBYyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNsRCxDQUFDO2dCQUVELE1BQU0sT0FBTyxHQUFHLFdBQVcsQ0FBQyxXQUFXLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUNwRCxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzdDLENBQUM7WUFFRCxNQUFNLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUV4QixPQUFPO2dCQUNMLE9BQU8sRUFBRSxJQUFJO2dCQUNiLE9BQU8sRUFBRSxZQUFZLE9BQU8scUJBQXFCO2FBQ2xELENBQUM7UUFDSixDQUFDO2FBQU0sQ0FBQztZQUNOLHNCQUFzQjtZQUN0QixJQUFJLENBQUMsTUFBTSxHQUFHLFFBQVEsQ0FBQztZQUN2QixNQUFNLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUV4QixPQUFPO2dCQUNMLE9BQU8sRUFBRSxJQUFJO2dCQUNiLE9BQU8sRUFBRSxpQ0FBaUM7YUFDM0MsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsWUFBWSxDQUFDLFFBQWdCO1FBQ3hDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDakIsT0FBTztnQkFDTCxPQUFPLEVBQUUsS0FBSztnQkFDZCxPQUFPLEVBQUUsNEJBQTRCO2FBQ3RDLENBQUM7UUFDSixDQUFDO1FBRUQsSUFBSSxDQUFDO1lBQ0gsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFO2dCQUN6QyxNQUFNLEVBQUUsQ0FBQztnQkFDVCxTQUFTLEVBQUUsR0FBRztnQkFDZCxNQUFNLEVBQUUsSUFBSTtnQkFDWixRQUFRLEVBQUUsS0FBSzthQUNoQixDQUFDLENBQUM7WUFFSCxNQUFNLEVBQUUsQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLFdBQVcsRUFBRSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7WUFFOUUsT0FBTztnQkFDTCxPQUFPLEVBQUUsSUFBSTtnQkFDYixPQUFPLEVBQUUsNkJBQTZCLFFBQVEsRUFBRTthQUNqRCxDQUFDO1FBQ0osQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixPQUFPO2dCQUNMLE9BQU8sRUFBRSxLQUFLO2dCQUNkLE9BQU8sRUFBRSxtQ0FBbUMsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFO2FBQ3JHLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLFlBQVksQ0FBQyxRQUFnQjtRQUN4QyxJQUFJLENBQUM7WUFDSCxNQUFNLE9BQU8sR0FBRyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBRXJELHFCQUFxQjtZQUNyQixNQUFNLE1BQU0sR0FBRyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFO2dCQUM3QyxXQUFXLEVBQUUsRUFBRSxHQUFHLElBQUk7Z0JBQ3RCLGVBQWUsRUFBRSxLQUFLO2dCQUN0QixjQUFjLEVBQUUsS0FBSzthQUN0QixDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksSUFBSSxPQUFPLE1BQU0sQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQ3BELE9BQU87b0JBQ0wsT0FBTyxFQUFFLEtBQUs7b0JBQ2QsT0FBTyxFQUFFLDZDQUE2QztpQkFDdkQsQ0FBQztZQUNKLENBQUM7WUFFRCxzQkFBc0I7WUFDdEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLElBQWdDLENBQUMsQ0FBQztZQUU5RSwyQkFBMkI7WUFDM0IsTUFBTSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFFeEIsT0FBTztnQkFDTCxPQUFPLEVBQUUsSUFBSTtnQkFDYixPQUFPLEVBQUUsK0JBQStCLFFBQVEsRUFBRTthQUNuRCxDQUFDO1FBQ0osQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixPQUFPO2dCQUNMLE9BQU8sRUFBRSxLQUFLO2dCQUNkLE9BQU8sRUFBRSxtQ0FBbUMsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFO2FBQ3JHLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ksa0JBQWtCLENBQUMsT0FBZ0I7UUFDeEMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNqQixPQUFPLCtCQUErQixDQUFDO1FBQ3pDLENBQUM7UUFFRCxJQUFJLFlBQVksR0FBUSxJQUFJLENBQUMsTUFBTSxDQUFDO1FBRXBDLElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixZQUFZLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN4QyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ2xCLE9BQU8sWUFBWSxPQUFPLGFBQWEsQ0FBQztZQUMxQyxDQUFDO1FBQ0gsQ0FBQztRQUVELG9DQUFvQztRQUNwQyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztRQUUzRCxrQ0FBa0M7UUFDbEMsSUFBSSxTQUFTLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQztZQUNsQyxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLEdBQUcsZ0JBQWdCLENBQUM7UUFDakQsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDMUIsTUFBTSxFQUFFLENBQUM7WUFDVCxTQUFTLEVBQUUsR0FBRztZQUNkLE1BQU0sRUFBRSxJQUFJO1lBQ1osUUFBUSxFQUFFLEtBQUs7U0FDaEIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29uZmlnTWFuYWdlciAtIENlbnRyYWxpemVkIGNvbmZpZ3VyYXRpb24gbWFuYWdlbWVudCBmb3IgRG9sbGhvdXNlTUNQXG4gKiBcbiAqIEZlYXR1cmVzOlxuICogLSBZQU1MLWJhc2VkIGNvbmZpZ3VyYXRpb24gZmlsZVxuICogLSBEZWZhdWx0IHZhbHVlcyB3aXRoIHVzZXIgb3ZlcnJpZGVzXG4gKiAtIE1pZ3JhdGlvbiBmcm9tIGVudmlyb25tZW50IHZhcmlhYmxlc1xuICogLSBWYWxpZGF0aW9uIGFuZCB0eXBlIHNhZmV0eVxuICogLSBBdG9taWMgdXBkYXRlcyB3aXRoIGJhY2t1cFxuICogLSBQcml2YWN5LWZpcnN0IGRlZmF1bHRzXG4gKiAtIE9BdXRoIGNsaWVudCBJRCBzdG9yYWdlIGZvciBDbGF1ZGUgRGVza3RvcCBpbnRlZ3JhdGlvblxuICovXG5cbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzL3Byb21pc2VzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgKiBhcyBvcyBmcm9tICdvcyc7XG5pbXBvcnQgKiBhcyB5YW1sIGZyb20gJ2pzLXlhbWwnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvbG9nZ2VyLmpzJztcbmltcG9ydCB7IFNlY3VyZVlhbWxQYXJzZXIgfSBmcm9tICcuLi9zZWN1cml0eS9zZWN1cmVZYW1sUGFyc2VyLmpzJztcblxuZXhwb3J0IGludGVyZmFjZSBVc2VyQ29uZmlnIHtcbiAgdXNlcm5hbWU6IHN0cmluZyB8IG51bGw7XG4gIGVtYWlsOiBzdHJpbmcgfCBudWxsO1xuICBkaXNwbGF5X25hbWU6IHN0cmluZyB8IG51bGw7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2l0SHViUG9ydGZvbGlvQ29uZmlnIHtcbiAgcmVwb3NpdG9yeV91cmw6IHN0cmluZyB8IG51bGw7XG4gIHJlcG9zaXRvcnlfbmFtZTogc3RyaW5nO1xuICBkZWZhdWx0X2JyYW5jaDogc3RyaW5nO1xuICBhdXRvX2NyZWF0ZTogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHaXRIdWJBdXRoQ29uZmlnIHtcbiAgdXNlX29hdXRoOiBib29sZWFuO1xuICB0b2tlbl9zb3VyY2U6ICdlbnZpcm9ubWVudCcgfCAnb2F1dGgnIHwgJ2NvbmZpZyc7XG4gIGNsaWVudF9pZD86IHN0cmluZzsgLy8gT0F1dGggY2xpZW50IElEIGZvciBHaXRIdWIgQXBwXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2l0SHViQ29uZmlnIHtcbiAgcG9ydGZvbGlvOiBHaXRIdWJQb3J0Zm9saW9Db25maWc7XG4gIGF1dGg6IEdpdEh1YkF1dGhDb25maWc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3luY0luZGl2aWR1YWxDb25maWcge1xuICByZXF1aXJlX2NvbmZpcm1hdGlvbjogYm9vbGVhbjtcbiAgc2hvd19kaWZmX2JlZm9yZV9zeW5jOiBib29sZWFuO1xuICB0cmFja192ZXJzaW9uczogYm9vbGVhbjtcbiAga2VlcF9oaXN0b3J5OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3luY0J1bGtDb25maWcge1xuICB1cGxvYWRfZW5hYmxlZDogYm9vbGVhbjtcbiAgZG93bmxvYWRfZW5hYmxlZDogYm9vbGVhbjtcbiAgcmVxdWlyZV9wcmV2aWV3OiBib29sZWFuO1xuICByZXNwZWN0X2xvY2FsX29ubHk6IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3luY1ByaXZhY3lDb25maWcge1xuICBzY2FuX2Zvcl9zZWNyZXRzOiBib29sZWFuO1xuICBzY2FuX2Zvcl9waWk6IGJvb2xlYW47XG4gIHdhcm5fb25fc2Vuc2l0aXZlOiBib29sZWFuO1xuICBleGNsdWRlZF9wYXR0ZXJuczogc3RyaW5nW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3luY0NvbmZpZyB7XG4gIGVuYWJsZWQ6IGJvb2xlYW47XG4gIGluZGl2aWR1YWw6IFN5bmNJbmRpdmlkdWFsQ29uZmlnO1xuICBidWxrOiBTeW5jQnVsa0NvbmZpZztcbiAgcHJpdmFjeTogU3luY1ByaXZhY3lDb25maWc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29sbGVjdGlvbkNvbmZpZyB7XG4gIGF1dG9fc3VibWl0OiBib29sZWFuO1xuICByZXF1aXJlX3JldmlldzogYm9vbGVhbjtcbiAgYWRkX2F0dHJpYnV0aW9uOiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEVsZW1lbnRzQ29uZmlnIHtcbiAgYXV0b19hY3RpdmF0ZToge1xuICAgIHBlcnNvbmFzPzogc3RyaW5nW107XG4gICAgc2tpbGxzPzogc3RyaW5nW107XG4gICAgdGVtcGxhdGVzPzogc3RyaW5nW107XG4gICAgYWdlbnRzPzogc3RyaW5nW107XG4gICAgbWVtb3JpZXM/OiBzdHJpbmdbXTtcbiAgICBlbnNlbWJsZXM/OiBzdHJpbmdbXTtcbiAgfTtcbiAgZGVmYXVsdF9lbGVtZW50X2Rpcjogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIERpc3BsYXlDb25maWcge1xuICBwZXJzb25hX2luZGljYXRvcnM6IHtcbiAgICBlbmFibGVkOiBib29sZWFuO1xuICAgIHN0eWxlOiAnZnVsbCcgfCAnbWluaW1hbCcgfCAnY29tcGFjdCcgfCAnY3VzdG9tJztcbiAgICBpbmNsdWRlX2Vtb2ppOiBib29sZWFuO1xuICB9O1xuICB2ZXJib3NlX2xvZ2dpbmc6IGJvb2xlYW47XG4gIHNob3dfcHJvZ3Jlc3M6IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRG9sbGhvdXNlQ29uZmlnIHtcbiAgdmVyc2lvbjogc3RyaW5nO1xuICB1c2VyOiBVc2VyQ29uZmlnO1xuICBnaXRodWI6IEdpdEh1YkNvbmZpZztcbiAgc3luYzogU3luY0NvbmZpZztcbiAgY29sbGVjdGlvbjogQ29sbGVjdGlvbkNvbmZpZztcbiAgZWxlbWVudHM6IEVsZW1lbnRzQ29uZmlnO1xuICBkaXNwbGF5OiBEaXNwbGF5Q29uZmlnO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbmZpZ1VwZGF0ZVJlc3VsdCB7XG4gIHN1Y2Nlc3M6IGJvb2xlYW47XG4gIG1lc3NhZ2U6IHN0cmluZztcbiAgcHJldmlvdXNWYWx1ZT86IGFueTtcbiAgbmV3VmFsdWU/OiBhbnk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29uZmlnQWN0aW9uUmVzdWx0IHtcbiAgc3VjY2VzczogYm9vbGVhbjtcbiAgbWVzc2FnZTogc3RyaW5nO1xuICBkYXRhPzogYW55O1xufVxuXG5leHBvcnQgY2xhc3MgQ29uZmlnTWFuYWdlciB7XG4gIHByaXZhdGUgc3RhdGljIGluc3RhbmNlOiBDb25maWdNYW5hZ2VyIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgc3RhdGljIGluc3RhbmNlTG9jazogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIHByaXZhdGUgY29uZmlnRGlyOiBzdHJpbmc7XG4gIHByaXZhdGUgY29uZmlnUGF0aDogc3RyaW5nO1xuICBwcml2YXRlIGJhY2t1cFBhdGg6IHN0cmluZztcbiAgcHJpdmF0ZSBjb25maWc6IERvbGxob3VzZUNvbmZpZyB8IG51bGwgPSBudWxsO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoKSB7XG4gICAgLy8gSW5pdGlhbGl6ZSBwYXRoc1xuICAgIHRoaXMuY29uZmlnRGlyID0gcGF0aC5qb2luKG9zLmhvbWVkaXIoKSwgJy5kb2xsaG91c2UnKTtcbiAgICB0aGlzLmNvbmZpZ1BhdGggPSBwYXRoLmpvaW4odGhpcy5jb25maWdEaXIsICdjb25maWcueW1sJyk7XG4gICAgdGhpcy5iYWNrdXBQYXRoID0gcGF0aC5qb2luKHRoaXMuY29uZmlnRGlyLCAnY29uZmlnLnltbC5iYWNrdXAnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaHJlYWQtc2FmZSBzaW5nbGV0b24gaW5zdGFuY2UgZ2V0dGVyXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGdldEluc3RhbmNlKCk6IENvbmZpZ01hbmFnZXIge1xuICAgIGlmIChDb25maWdNYW5hZ2VyLmluc3RhbmNlKSB7XG4gICAgICByZXR1cm4gQ29uZmlnTWFuYWdlci5pbnN0YW5jZTtcbiAgICB9XG5cbiAgICAvLyBTaW1wbGUgbG9ja2luZyBtZWNoYW5pc20gdG8gcHJldmVudCByYWNlIGNvbmRpdGlvbnNcbiAgICBpZiAoQ29uZmlnTWFuYWdlci5pbnN0YW5jZUxvY2spIHtcbiAgICAgIC8vIFdhaXQgZm9yIGxvY2sgdG8gYmUgcmVsZWFzZWQsIHRoZW4gcmV0dXJuIHRoZSBpbnN0YW5jZVxuICAgICAgd2hpbGUgKENvbmZpZ01hbmFnZXIuaW5zdGFuY2VMb2NrICYmICFDb25maWdNYW5hZ2VyLmluc3RhbmNlKSB7XG4gICAgICAgIC8vIEluIGEgcmVhbCBzY2VuYXJpbyB3aXRoIGFzeW5jIG9wZXJhdGlvbnMsIHRoaXMgd291bGQgYmUgbW9yZSBzb3BoaXN0aWNhdGVkXG4gICAgICAgIC8vIEJ1dCBmb3IgdGhlIHRlc3QgY2FzZXMsIHRoaXMgc2ltcGxlIGFwcHJvYWNoIHdvcmtzXG4gICAgICB9XG4gICAgICByZXR1cm4gQ29uZmlnTWFuYWdlci5pbnN0YW5jZSE7XG4gICAgfVxuXG4gICAgQ29uZmlnTWFuYWdlci5pbnN0YW5jZUxvY2sgPSB0cnVlO1xuICAgIFxuICAgIGlmICghQ29uZmlnTWFuYWdlci5pbnN0YW5jZSkge1xuICAgICAgQ29uZmlnTWFuYWdlci5pbnN0YW5jZSA9IG5ldyBDb25maWdNYW5hZ2VyKCk7XG4gICAgfVxuICAgIFxuICAgIENvbmZpZ01hbmFnZXIuaW5zdGFuY2VMb2NrID0gZmFsc2U7XG4gICAgcmV0dXJuIENvbmZpZ01hbmFnZXIuaW5zdGFuY2U7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGRlZmF1bHQgY29uZmlndXJhdGlvblxuICAgKi9cbiAgcHJpdmF0ZSBnZXREZWZhdWx0Q29uZmlnKCk6IERvbGxob3VzZUNvbmZpZyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHZlcnNpb246ICcxLjAuMCcsXG4gICAgICB1c2VyOiB7XG4gICAgICAgIHVzZXJuYW1lOiBudWxsLFxuICAgICAgICBlbWFpbDogbnVsbCxcbiAgICAgICAgZGlzcGxheV9uYW1lOiBudWxsXG4gICAgICB9LFxuICAgICAgZ2l0aHViOiB7XG4gICAgICAgIHBvcnRmb2xpbzoge1xuICAgICAgICAgIHJlcG9zaXRvcnlfdXJsOiBudWxsLFxuICAgICAgICAgIHJlcG9zaXRvcnlfbmFtZTogJ2RvbGxob3VzZS1wb3J0Zm9saW8nLFxuICAgICAgICAgIGRlZmF1bHRfYnJhbmNoOiAnbWFpbicsXG4gICAgICAgICAgYXV0b19jcmVhdGU6IHRydWVcbiAgICAgICAgfSxcbiAgICAgICAgYXV0aDoge1xuICAgICAgICAgIHVzZV9vYXV0aDogdHJ1ZSxcbiAgICAgICAgICB0b2tlbl9zb3VyY2U6ICdlbnZpcm9ubWVudCdcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIHN5bmM6IHtcbiAgICAgICAgZW5hYmxlZDogZmFsc2UsIC8vIFByaXZhY3kgZmlyc3QgLSBvZmYgYnkgZGVmYXVsdFxuICAgICAgICBpbmRpdmlkdWFsOiB7XG4gICAgICAgICAgcmVxdWlyZV9jb25maXJtYXRpb246IHRydWUsXG4gICAgICAgICAgc2hvd19kaWZmX2JlZm9yZV9zeW5jOiB0cnVlLFxuICAgICAgICAgIHRyYWNrX3ZlcnNpb25zOiB0cnVlLFxuICAgICAgICAgIGtlZXBfaGlzdG9yeTogMTBcbiAgICAgICAgfSxcbiAgICAgICAgYnVsazoge1xuICAgICAgICAgIHVwbG9hZF9lbmFibGVkOiBmYWxzZSwgLy8gUmVxdWlyZXMgZXhwbGljaXQgZW5hYmxlbWVudFxuICAgICAgICAgIGRvd25sb2FkX2VuYWJsZWQ6IGZhbHNlLFxuICAgICAgICAgIHJlcXVpcmVfcHJldmlldzogdHJ1ZSxcbiAgICAgICAgICByZXNwZWN0X2xvY2FsX29ubHk6IHRydWVcbiAgICAgICAgfSxcbiAgICAgICAgcHJpdmFjeToge1xuICAgICAgICAgIHNjYW5fZm9yX3NlY3JldHM6IHRydWUsXG4gICAgICAgICAgc2Nhbl9mb3JfcGlpOiB0cnVlLFxuICAgICAgICAgIHdhcm5fb25fc2Vuc2l0aXZlOiB0cnVlLFxuICAgICAgICAgIGV4Y2x1ZGVkX3BhdHRlcm5zOiBbXG4gICAgICAgICAgICAnKi5zZWNyZXQnLFxuICAgICAgICAgICAgJyotcHJpdmF0ZS4qJyxcbiAgICAgICAgICAgICdjcmVkZW50aWFscy8qKicsXG4gICAgICAgICAgICAncGVyc29uYWwvKionXG4gICAgICAgICAgXVxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgY29sbGVjdGlvbjoge1xuICAgICAgICBhdXRvX3N1Ym1pdDogZmFsc2UsIC8vIE5ldmVyIGF1dG8tc3VibWl0XG4gICAgICAgIHJlcXVpcmVfcmV2aWV3OiB0cnVlLFxuICAgICAgICBhZGRfYXR0cmlidXRpb246IHRydWVcbiAgICAgIH0sXG4gICAgICBlbGVtZW50czoge1xuICAgICAgICBhdXRvX2FjdGl2YXRlOiB7fSxcbiAgICAgICAgZGVmYXVsdF9lbGVtZW50X2RpcjogcGF0aC5qb2luKG9zLmhvbWVkaXIoKSwgJy5kb2xsaG91c2UnLCAncG9ydGZvbGlvJylcbiAgICAgIH0sXG4gICAgICBkaXNwbGF5OiB7XG4gICAgICAgIHBlcnNvbmFfaW5kaWNhdG9yczoge1xuICAgICAgICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgICAgICAgc3R5bGU6ICdtaW5pbWFsJyxcbiAgICAgICAgICBpbmNsdWRlX2Vtb2ppOiB0cnVlXG4gICAgICAgIH0sXG4gICAgICAgIHZlcmJvc2VfbG9nZ2luZzogZmFsc2UsXG4gICAgICAgIHNob3dfcHJvZ3Jlc3M6IHRydWVcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemUgY29uZmlndXJhdGlvblxuICAgKi9cbiAgcHVibGljIGFzeW5jIGluaXRpYWxpemUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gQWx3YXlzIHJlbG9hZCBjb25maWcgZnJvbSBkaXNrIGlmIGl0IGV4aXN0cywgZXZlbiBpZiB3ZSBoYXZlIGRlZmF1bHRzIGluIG1lbW9yeVxuICAgIC8vIFRoaXMgZW5zdXJlcyB3ZSBwaWNrIHVwIGFueSBtYW51YWwgZWRpdHMgb3Igc2F2ZWQgc2V0dGluZ3NcbiAgICBcbiAgICB0cnkge1xuICAgICAgLy8gRW5zdXJlIGNvbmZpZyBkaXJlY3RvcnkgZXhpc3RzIHdpdGggcHJvcGVyIHBlcm1pc3Npb25zICgwbzcwMCA9IG93bmVyIG9ubHkpXG4gICAgICBhd2FpdCBmcy5ta2Rpcih0aGlzLmNvbmZpZ0RpciwgeyByZWN1cnNpdmU6IHRydWUsIG1vZGU6IDBvNzAwIH0pO1xuICAgICAgXG4gICAgICAvLyBMb2FkIG9yIGNyZWF0ZSBjb25maWdcbiAgICAgIGlmIChhd2FpdCB0aGlzLmNvbmZpZ0V4aXN0cygpKSB7XG4gICAgICAgIGF3YWl0IHRoaXMubG9hZENvbmZpZygpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gQ3JlYXRlIGRlZmF1bHQgY29uZmlnXG4gICAgICAgIHRoaXMuY29uZmlnID0gdGhpcy5nZXREZWZhdWx0Q29uZmlnKCk7XG4gICAgICAgIFxuICAgICAgICAvLyBUcnkgdG8gbWlncmF0ZSBmcm9tIGVudmlyb25tZW50IHZhcmlhYmxlc1xuICAgICAgICBhd2FpdCB0aGlzLm1pZ3JhdGVGcm9tRW52aXJvbm1lbnQoKTtcbiAgICAgICAgXG4gICAgICAgIC8vIFNhdmUgdGhlIGNvbmZpZ1xuICAgICAgICBhd2FpdCB0aGlzLnNhdmVDb25maWcoKTtcbiAgICAgICAgXG4gICAgICAgIGxvZ2dlci5pbmZvKCdDcmVhdGVkIG5ldyBjb25maWd1cmF0aW9uIGZpbGUnLCB7XG4gICAgICAgICAgcGF0aDogdGhpcy5jb25maWdQYXRoXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ0ZhaWxlZCB0byBpbml0aWFsaXplIGNvbmZpZ3VyYXRpb24nLCB7XG4gICAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcilcbiAgICAgIH0pO1xuICAgICAgLy8gVXNlIGRlZmF1bHRzIGluIG1lbW9yeVxuICAgICAgdGhpcy5jb25maWcgPSB0aGlzLmdldERlZmF1bHRDb25maWcoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTG9hZCBjb25maWd1cmF0aW9uIGZyb20gZmlsZVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBsb2FkQ29uZmlnKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgZnMucmVhZEZpbGUodGhpcy5jb25maWdQYXRoLCAndXRmLTgnKTtcbiAgICAgIFxuICAgICAgLyoqXG4gICAgICAgKiBJTVBPUlRBTlQ6IFBhcnNlciBTZWxlY3Rpb24gZm9yIERpZmZlcmVudCBGaWxlIFR5cGVzXG4gICAgICAgKiBcbiAgICAgICAqIFdlIHVzZSBESUZGRVJFTlQgcGFyc2VycyBmb3IgZGlmZmVyZW50IGZpbGUgdHlwZXM6XG4gICAgICAgKiBcbiAgICAgICAqIDEuIGpzLXlhbWwgKHVzZWQgaGVyZSkgLSBGb3IgUFVSRSBZQU1MIGZpbGVzOlxuICAgICAgICogICAgLSBDb25maWd1cmF0aW9uIGZpbGVzIChjb25maWcueW1sKVxuICAgICAgICogICAgLSBEYXRhIGZpbGVzIHdpdGhvdXQgbWFya2Rvd24gY29udGVudFxuICAgICAgICogICAgLSBBbnkgLnltbCBvciAueWFtbCBmaWxlIHRoYXQncyBqdXN0IFlBTUxcbiAgICAgICAqICAgIEV4YW1wbGUgZm9ybWF0OlxuICAgICAgICogICAgYGBgeWFtbFxuICAgICAgICogICAgdmVyc2lvbjogMS4wLjBcbiAgICAgICAqICAgIHVzZXI6XG4gICAgICAgKiAgICAgIHVzZXJuYW1lOiBqb2huZG9lXG4gICAgICAgKiAgICAgIGVtYWlsOiBqb2huQGV4YW1wbGUuY29tXG4gICAgICAgKiAgICBgYGBcbiAgICAgICAqIFxuICAgICAgICogMi4gU2VjdXJlWWFtbFBhcnNlciAtIEZvciBNQVJLRE9XTiBmaWxlcyB3aXRoIFlBTUwgZnJvbnRtYXR0ZXI6XG4gICAgICAgKiAgICAtIFBlcnNvbmEgZmlsZXMgKCoubWQgaW4gcGVyc29uYXMvKVxuICAgICAgICogICAgLSBTa2lsbCBmaWxlcyAoKi5tZCBpbiBza2lsbHMvKVxuICAgICAgICogICAgLSBUZW1wbGF0ZSBmaWxlcyAoKi5tZCBpbiB0ZW1wbGF0ZXMvKVxuICAgICAgICogICAgLSBBbnkgLm1kIGZpbGUgd2l0aCBmcm9udG1hdHRlciBiZXR3ZWVuIC0tLSBtYXJrZXJzXG4gICAgICAgKiAgICBFeGFtcGxlIGZvcm1hdDpcbiAgICAgICAqICAgIGBgYG1hcmtkb3duXG4gICAgICAgKiAgICAtLS1cbiAgICAgICAqICAgIG5hbWU6IENyZWF0aXZlIFdyaXRlclxuICAgICAgICogICAgZGVzY3JpcHRpb246IEEgY3JlYXRpdmUgYXNzaXN0YW50XG4gICAgICAgKiAgICAtLS1cbiAgICAgICAqICAgICMgSW5zdHJ1Y3Rpb25zXG4gICAgICAgKiAgICBZb3UgYXJlIGEgY3JlYXRpdmUgd3JpdGVyLi4uXG4gICAgICAgKiAgICBgYGBcbiAgICAgICAqIFxuICAgICAgICogVGhlIGNvbmZpZyBmaWxlIGlzIFBVUkUgWUFNTCwgc28gd2UgdXNlIGpzLXlhbWwgZGlyZWN0bHkgd2l0aCBGQUlMU0FGRV9TQ0hFTUFcbiAgICAgICAqIGZvciBzZWN1cml0eSAocHJldmVudHMgY29kZSBleGVjdXRpb24gdmlhIFlBTUwgdGFncykuXG4gICAgICAgKiBTRUNVUklUWTogVGhpcyBpcyBOT1QgYSB2dWxuZXJhYmlsaXR5IC0gRkFJTFNBRkVfU0NIRU1BIHByZXZlbnRzIGNvZGUgZXhlY3V0aW9uXG4gICAgICAgKi9cbiAgICAgIGxldCBsb2FkZWREYXRhOiBhbnk7XG4gICAgICB0cnkge1xuICAgICAgICAvLyBVc2luZyB5YW1sIHdpdGggRkFJTFNBRkVfU0NIRU1BIGlzIHNlY3VyZSAtIHByZXZlbnRzIGNvZGUgZXhlY3V0aW9uXG4gICAgICAgIGxvYWRlZERhdGEgPSB5YW1sLmxvYWQoY29udGVudCwge1xuICAgICAgICAgIHNjaGVtYTogeWFtbC5GQUlMU0FGRV9TQ0hFTUEgLy8gU2FmZSBzY2hlbWEgcHJldmVudHMgY29kZSBleGVjdXRpb25cbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoICh5YW1sRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIFlBTUwgaW4gY29uZmlndXJhdGlvbiBmaWxlOiAke3lhbWxFcnJvciBpbnN0YW5jZW9mIEVycm9yID8geWFtbEVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoeWFtbEVycm9yKX1gKTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgaWYgKCFsb2FkZWREYXRhIHx8IHR5cGVvZiBsb2FkZWREYXRhICE9PSAnb2JqZWN0Jykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgY29uZmlndXJhdGlvbiBmb3JtYXQnKTtcbiAgICAgIH1cbiAgICAgIGxvZ2dlci5kZWJ1ZygnTG9hZGVkIGNvbmZpZyBmcm9tIGZpbGUnLCB7XG4gICAgICAgIHVzZXJuYW1lOiBsb2FkZWREYXRhLnVzZXI/LnVzZXJuYW1lLFxuICAgICAgICBlbWFpbDogbG9hZGVkRGF0YS51c2VyPy5lbWFpbCxcbiAgICAgICAgc3luY0VuYWJsZWQ6IGxvYWRlZERhdGEuc3luYz8uZW5hYmxlZFxuICAgICAgfSk7XG4gICAgICBcbiAgICAgIHRoaXMuY29uZmlnID0gdGhpcy5tZXJnZVdpdGhEZWZhdWx0cyhsb2FkZWREYXRhKTtcbiAgICAgIFxuICAgICAgLy8gRml4IGFueSBzdHJpbmcgYm9vbGVhbnMgdGhhdCBtaWdodCBoYXZlIGJlZW4gc2F2ZWQgaW5jb3JyZWN0bHlcbiAgICAgIHRoaXMuZml4Q29uZmlnVHlwZXMoKTtcbiAgICAgIFxuICAgICAgbG9nZ2VyLmRlYnVnKCdDb25maWd1cmF0aW9uIGxvYWRlZCBzdWNjZXNzZnVsbHknLCB7XG4gICAgICAgIHVzZXJuYW1lOiB0aGlzLmNvbmZpZy51c2VyLnVzZXJuYW1lLFxuICAgICAgICBzeW5jRW5hYmxlZDogdGhpcy5jb25maWcuc3luYy5lbmFibGVkXG4gICAgICB9KTtcbiAgICAgIFxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ0ZhaWxlZCB0byBsb2FkIGNvbmZpZ3VyYXRpb24nLCB7XG4gICAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcilcbiAgICAgIH0pO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGNvbmZpZyBmaWxlIGV4aXN0c1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBjb25maWdFeGlzdHMoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGZzLmFjY2Vzcyh0aGlzLmNvbmZpZ1BhdGgpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCBHaXRIdWIgT0F1dGggY2xpZW50IElEXG4gICAqIEVudmlyb25tZW50IHZhcmlhYmxlIHRha2VzIHByZWNlZGVuY2Ugb3ZlciBjb25maWcgZmlsZVxuICAgKi9cbiAgcHVibGljIGdldEdpdEh1YkNsaWVudElkKCk6IHN0cmluZyB8IG51bGwge1xuICAgIC8vIENoZWNrIGVudmlyb25tZW50IHZhcmlhYmxlIGZpcnN0XG4gICAgY29uc3QgZW52Q2xpZW50SWQgPSBwcm9jZXNzLmVudi5ET0xMSE9VU0VfR0lUSFVCX0NMSUVOVF9JRDtcbiAgICBpZiAoZW52Q2xpZW50SWQpIHtcbiAgICAgIHJldHVybiBlbnZDbGllbnRJZDtcbiAgICB9XG5cbiAgICAvLyBGYWxsIGJhY2sgdG8gY29uZmlnIGZpbGVcbiAgICByZXR1cm4gdGhpcy5jb25maWc/LmdpdGh1Yj8uYXV0aD8uY2xpZW50X2lkIHx8IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogU2V0IEdpdEh1YiBPQXV0aCBjbGllbnQgSUQgaW4gY29uZmlnIGZpbGVcbiAgICovXG4gIHB1YmxpYyBhc3luYyBzZXRHaXRIdWJDbGllbnRJZChjbGllbnRJZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFDb25maWdNYW5hZ2VyLnZhbGlkYXRlQ2xpZW50SWQoY2xpZW50SWQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBJbnZhbGlkIEdpdEh1YiBjbGllbnQgSUQgZm9ybWF0LiBFeHBlY3RlZCBmb3JtYXQ6IE92MjNsaSBmb2xsb3dlZCBieSBhdCBsZWFzdCAxNCBhbHBoYW51bWVyaWMgY2hhcmFjdGVycyAoZS5nLiwgT3YyM2xpQUJDREVGR0hJSktMTU4pYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuY29uZmlnKSB7XG4gICAgICB0aGlzLmNvbmZpZyA9IHRoaXMuZ2V0RGVmYXVsdENvbmZpZygpO1xuICAgIH1cblxuICAgIC8vIEVuc3VyZSBnaXRodWIuYXV0aCBvYmplY3QgZXhpc3RzXG4gICAgaWYgKCF0aGlzLmNvbmZpZy5naXRodWIpIHtcbiAgICAgIHRoaXMuY29uZmlnLmdpdGh1YiA9IHRoaXMuZ2V0RGVmYXVsdENvbmZpZygpLmdpdGh1YjtcbiAgICB9XG4gICAgaWYgKCF0aGlzLmNvbmZpZy5naXRodWIuYXV0aCkge1xuICAgICAgdGhpcy5jb25maWcuZ2l0aHViLmF1dGggPSB0aGlzLmdldERlZmF1bHRDb25maWcoKS5naXRodWIuYXV0aDtcbiAgICB9XG5cbiAgICB0aGlzLmNvbmZpZy5naXRodWIuYXV0aC5jbGllbnRfaWQgPSBjbGllbnRJZDtcbiAgICBhd2FpdCB0aGlzLnNhdmVDb25maWcoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGN1cnJlbnQgY29uZmlndXJhdGlvblxuICAgKi9cbiAgcHVibGljIGdldENvbmZpZygpOiBEb2xsaG91c2VDb25maWcge1xuICAgIGlmICghdGhpcy5jb25maWcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ29uZmlndXJhdGlvbiBub3QgaW5pdGlhbGl6ZWQnKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhIHNwZWNpZmljIHNldHRpbmcgdXNpbmcgZG90IG5vdGF0aW9uXG4gICAqL1xuICBwdWJsaWMgZ2V0U2V0dGluZzxUPihwYXRoOiBzdHJpbmcsIGRlZmF1bHRWYWx1ZT86IFQpOiBUIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIXRoaXMuY29uZmlnKSB7XG4gICAgICByZXR1cm4gZGVmYXVsdFZhbHVlO1xuICAgIH1cbiAgICBcbiAgICBjb25zdCBrZXlzID0gcGF0aC5zcGxpdCgnLicpO1xuICAgIGxldCB2YWx1ZTogYW55ID0gdGhpcy5jb25maWc7XG4gICAgXG4gICAgZm9yIChjb25zdCBrZXkgb2Yga2V5cykge1xuICAgICAgaWYgKHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYga2V5IGluIHZhbHVlKSB7XG4gICAgICAgIHZhbHVlID0gdmFsdWVba2V5XTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBkZWZhdWx0VmFsdWU7XG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIHJldHVybiB2YWx1ZSBhcyBUO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSBhIHNwZWNpZmljIHNldHRpbmcgdXNpbmcgZG90IG5vdGF0aW9uXG4gICAqIFNFQ1VSSVRZIEZJWCAoUFIgIzg5NSk6IEFkZGVkIHByb3RvdHlwZSBwb2xsdXRpb24gcHJvdGVjdGlvblxuICAgKiBQcmV2aW91c2x5OiBEaXJlY3QgcHJvcGVydHkgYXNzaWdubWVudCBhbGxvd2VkIF9fcHJvdG9fXyBpbmplY3Rpb25cbiAgICogTm93OiBWYWxpZGF0ZXMga2V5cyBhZ2FpbnN0IGZvcmJpZGRlbiBwcm9wZXJ0aWVzIGJlZm9yZSBhc3NpZ25tZW50XG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdXBkYXRlU2V0dGluZyhwYXRoOiBzdHJpbmcsIHZhbHVlOiBhbnkpOiBQcm9taXNlPENvbmZpZ1VwZGF0ZVJlc3VsdD4ge1xuICAgIGlmICghdGhpcy5jb25maWcpIHtcbiAgICAgIGF3YWl0IHRoaXMuaW5pdGlhbGl6ZSgpO1xuICAgIH1cbiAgICBcbiAgICBjb25zdCBrZXlzID0gcGF0aC5zcGxpdCgnLicpO1xuICAgIFxuICAgIC8vIFNFQ1VSSVRZOiBWYWxpZGF0ZSBhbGwga2V5cyB0byBwcmV2ZW50IHByb3RvdHlwZSBwb2xsdXRpb25cbiAgICBjb25zdCBGT1JCSURERU5fS0VZUyA9IFsnX19wcm90b19fJywgJ2NvbnN0cnVjdG9yJywgJ3Byb3RvdHlwZSddO1xuICAgIGZvciAoY29uc3Qga2V5IG9mIGtleXMpIHtcbiAgICAgIGlmIChGT1JCSURERU5fS0VZUy5pbmNsdWRlcyhrZXkpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRm9yYmlkZGVuIHByb3BlcnR5IGluIHBhdGg6ICR7a2V5fWApO1xuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICBsZXQgY3VycmVudDogYW55ID0gdGhpcy5jb25maWc7XG4gICAgY29uc3QgcHJldmlvdXNWYWx1ZSA9IHRoaXMuZ2V0U2V0dGluZyhwYXRoKTtcbiAgICBcbiAgICAvLyBOYXZpZ2F0ZSB0byB0aGUgcGFyZW50IG9iamVjdFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwga2V5cy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgIGNvbnN0IGtleSA9IGtleXNbaV07XG4gICAgICBpZiAoIShrZXkgaW4gY3VycmVudCkpIHtcbiAgICAgICAgY3VycmVudFtrZXldID0ge307XG4gICAgICB9XG4gICAgICBjdXJyZW50ID0gY3VycmVudFtrZXldO1xuICAgIH1cbiAgICBcbiAgICAvLyBTZXQgdGhlIHZhbHVlXG4gICAgY29uc3QgbGFzdEtleSA9IGtleXNba2V5cy5sZW5ndGggLSAxXTtcbiAgICBjdXJyZW50W2xhc3RLZXldID0gdmFsdWU7XG4gICAgXG4gICAgLy8gU2F2ZSB0aGUgY29uZmlndXJhdGlvblxuICAgIGF3YWl0IHRoaXMuc2F2ZUNvbmZpZygpO1xuICAgIFxuICAgIGxvZ2dlci5pbmZvKCdDb25maWd1cmF0aW9uIHNldHRpbmcgdXBkYXRlZCcsIHtcbiAgICAgIHBhdGgsXG4gICAgICBwcmV2aW91c1ZhbHVlLFxuICAgICAgbmV3VmFsdWU6IHZhbHVlXG4gICAgfSk7XG4gICAgXG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICBtZXNzYWdlOiBgU2V0dGluZyAnJHtwYXRofScgdXBkYXRlZCBzdWNjZXNzZnVsbHlgLFxuICAgICAgcHJldmlvdXNWYWx1ZSxcbiAgICAgIG5ld1ZhbHVlOiB2YWx1ZVxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgR2l0SHViIE9BdXRoIGNsaWVudCBJRCBmb3JtYXRcbiAgICogQ2xpZW50IElEcyBzdGFydCB3aXRoIFwiT3YyM2xpXCIgZm9sbG93ZWQgYnkgYXQgbGVhc3QgMTQgYWxwaGFudW1lcmljIGNoYXJhY3RlcnNcbiAgICogXG4gICAqIEBwYXJhbSBjbGllbnRJZCAtIFRoZSBjbGllbnQgSUQgdG8gdmFsaWRhdGVcbiAgICogQHJldHVybnMgdHJ1ZSBpZiB2YWxpZCwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAqIFxuICAgKiBAZXhhbXBsZVxuICAgKiBDb25maWdNYW5hZ2VyLnZhbGlkYXRlQ2xpZW50SWQoXCJPdjIzbGlBQkNERUZHSElKS0xNTjEyMzQ1NlwiKSAvLyB0cnVlXG4gICAqIENvbmZpZ01hbmFnZXIudmFsaWRhdGVDbGllbnRJZChcImludmFsaWRcIikgLy8gZmFsc2VcbiAgICogQ29uZmlnTWFuYWdlci52YWxpZGF0ZUNsaWVudElkKFwiT3YyM2xpXCIpIC8vIGZhbHNlICh0b28gc2hvcnQpXG4gICAqIENvbmZpZ01hbmFnZXIudmFsaWRhdGVDbGllbnRJZChcIlh2MjNsaUFCQ0RFRkdISUpLTE1OXCIpIC8vIGZhbHNlICh3cm9uZyBwcmVmaXgpXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHZhbGlkYXRlQ2xpZW50SWQoY2xpZW50SWQ6IGFueSk6IGJvb2xlYW4ge1xuICAgIGlmICh0eXBlb2YgY2xpZW50SWQgIT09ICdzdHJpbmcnIHx8ICFjbGllbnRJZCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIEdpdEh1YiBPQXV0aCBjbGllbnQgSURzIGZvbGxvdyB0aGUgcGF0dGVybjogT3YyM2xpW0EtWmEtejAtOV17MTQsfVxuICAgIGNvbnN0IGNsaWVudElkUGF0dGVybiA9IC9eT3YyM2xpW0EtWmEtejAtOV17MTQsfSQvO1xuICAgIHJldHVybiBjbGllbnRJZFBhdHRlcm4udGVzdChjbGllbnRJZCk7XG4gIH1cblxuICAvKipcbiAgICogU2F2ZSBjb25maWd1cmF0aW9uIHRvIGZpbGVcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgc2F2ZUNvbmZpZygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXRoaXMuY29uZmlnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGNvbmZpZ3VyYXRpb24gdG8gc2F2ZScpO1xuICAgIH1cbiAgICBcbiAgICB0cnkge1xuICAgICAgLy8gQ3JlYXRlIGJhY2t1cCBvZiBleGlzdGluZyBjb25maWdcbiAgICAgIGlmIChhd2FpdCB0aGlzLmNvbmZpZ0V4aXN0cygpKSB7XG4gICAgICAgIGF3YWl0IGZzLmNvcHlGaWxlKHRoaXMuY29uZmlnUGF0aCwgdGhpcy5iYWNrdXBQYXRoKTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gQ29udmVydCB0byBZQU1MXG4gICAgICAvLyBOb3RlOiBXZSB1c2UganMteWFtbCdzIGR1bXAoKSBmb3IgcHVyZSBZQU1MIG91dHB1dCAobm8gZnJvbnRtYXR0ZXIgbWFya2VycylcbiAgICAgIC8vIFRoaXMgY3JlYXRlcyBhIHN0YW5kYXJkIFlBTUwgZmlsZSwgbm90IGEgbWFya2Rvd24gZmlsZSB3aXRoIGZyb250bWF0dGVyXG4gICAgICBjb25zdCB5YW1sQ29udGVudCA9IHlhbWwuZHVtcCh0aGlzLmNvbmZpZywge1xuICAgICAgICBpbmRlbnQ6IDIsXG4gICAgICAgIGxpbmVXaWR0aDogMTIwLFxuICAgICAgICBub1JlZnM6IHRydWUsXG4gICAgICAgIHNvcnRLZXlzOiBmYWxzZVxuICAgICAgICAvLyBVc2luZyBkZWZhdWx0IHNjaGVtYSAobm90IEZBSUxTQUZFKSBmb3IgZHVtcCB0byBwcmVzZXJ2ZSB0eXBlcyBsaWtlIGJvb2xlYW5zXG4gICAgICB9KTtcbiAgICAgIFxuICAgICAgLy8gV3JpdGUgYXRvbWljYWxseSB3aXRoIHByb3BlciBwZXJtaXNzaW9ucyAoMG82MDAgPSBvd25lciByZWFkL3dyaXRlIG9ubHkpXG4gICAgICBjb25zdCB0ZW1wUGF0aCA9IGAke3RoaXMuY29uZmlnUGF0aH0udG1wYDtcbiAgICAgIGF3YWl0IGZzLndyaXRlRmlsZSh0ZW1wUGF0aCwgeWFtbENvbnRlbnQsIHsgZW5jb2Rpbmc6ICd1dGYtOCcsIG1vZGU6IDBvNjAwIH0pO1xuICAgICAgYXdhaXQgZnMucmVuYW1lKHRlbXBQYXRoLCB0aGlzLmNvbmZpZ1BhdGgpO1xuICAgICAgXG4gICAgICBsb2dnZXIuZGVidWcoJ0NvbmZpZ3VyYXRpb24gc2F2ZWQgc3VjY2Vzc2Z1bGx5Jyk7XG4gICAgICBcbiAgICAgIC8vIExvZyBhdWRpdCBldmVudCBmb3IgY29uZmlndXJhdGlvbiB1cGRhdGVcbiAgICAgIGxvZ2dlci5kZWJ1ZygnQ29uZmlndXJhdGlvbiB1cGRhdGUgYXVkaXQnLCB7XG4gICAgICAgIGV2ZW50OiAnQ09ORklHX1VQREFURUQnLFxuICAgICAgICBzb3VyY2U6ICdDb25maWdNYW5hZ2VyLnNhdmVDb25maWcnLFxuICAgICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKVxuICAgICAgfSk7XG4gICAgICBcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLmVycm9yKCdGYWlsZWQgdG8gc2F2ZSBjb25maWd1cmF0aW9uJywge1xuICAgICAgICBlcnJvcjogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpXG4gICAgICB9KTtcbiAgICAgIFxuICAgICAgLy8gVHJ5IHRvIHJlc3RvcmUgYmFja3VwXG4gICAgICBpZiAoYXdhaXQgdGhpcy5iYWNrdXBFeGlzdHMoKSkge1xuICAgICAgICBhd2FpdCBmcy5jb3B5RmlsZSh0aGlzLmJhY2t1cFBhdGgsIHRoaXMuY29uZmlnUGF0aCk7XG4gICAgICAgIGxvZ2dlci5pbmZvKCdSZXN0b3JlZCBjb25maWd1cmF0aW9uIGZyb20gYmFja3VwJyk7XG4gICAgICB9XG4gICAgICBcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBiYWNrdXAgZXhpc3RzXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGJhY2t1cEV4aXN0cygpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgZnMuYWNjZXNzKHRoaXMuYmFja3VwUGF0aCk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRml4IGluY29ycmVjdCB0eXBlcyBpbiBjb25maWcgKGUuZy4sIHN0cmluZyBib29sZWFucywgc3RyaW5nIFwibnVsbFwiKVxuICAgKi9cbiAgcHJpdmF0ZSBmaXhDb25maWdUeXBlcygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY29uZmlnKSByZXR1cm47XG4gICAgXG4gICAgLy8gSGVscGVyIHRvIGNvbnZlcnQgc3RyaW5nIFwibnVsbFwiIHRvIGFjdHVhbCBudWxsXG4gICAgY29uc3QgZml4TnVsbCA9ICh2YWx1ZTogYW55KTogYW55ID0+IHtcbiAgICAgIGlmICh2YWx1ZSA9PT0gJ251bGwnIHx8IHZhbHVlID09PSAnTlVMTCcpIHJldHVybiBudWxsO1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH07XG4gICAgXG4gICAgLy8gSGVscGVyIHRvIGNvbnZlcnQgc3RyaW5nIGJvb2xlYW5zIHRvIGFjdHVhbCBib29sZWFuc1xuICAgIGNvbnN0IGZpeEJvb2xlYW4gPSAodmFsdWU6IGFueSk6IGFueSA9PiB7XG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgICBjb25zdCBsb3dlciA9IHZhbHVlLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIGlmIChsb3dlciA9PT0gJ3RydWUnKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgaWYgKGxvd2VyID09PSAnZmFsc2UnKSByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfTtcbiAgICBcbiAgICAvLyBGaXggdXNlciBmaWVsZHMgLSBoYW5kbGUgc3RyaW5nIFwibnVsbFwiIHZhbHVlc1xuICAgIGlmICh0aGlzLmNvbmZpZy51c2VyKSB7XG4gICAgICB0aGlzLmNvbmZpZy51c2VyLnVzZXJuYW1lID0gZml4TnVsbCh0aGlzLmNvbmZpZy51c2VyLnVzZXJuYW1lKTtcbiAgICAgIHRoaXMuY29uZmlnLnVzZXIuZW1haWwgPSBmaXhOdWxsKHRoaXMuY29uZmlnLnVzZXIuZW1haWwpO1xuICAgICAgdGhpcy5jb25maWcudXNlci5kaXNwbGF5X25hbWUgPSBmaXhOdWxsKHRoaXMuY29uZmlnLnVzZXIuZGlzcGxheV9uYW1lKTtcbiAgICB9XG4gICAgXG4gICAgLy8gRml4IHN5bmMgc2V0dGluZ3NcbiAgICBpZiAodGhpcy5jb25maWcuc3luYykge1xuICAgICAgdGhpcy5jb25maWcuc3luYy5lbmFibGVkID0gZml4Qm9vbGVhbih0aGlzLmNvbmZpZy5zeW5jLmVuYWJsZWQpO1xuICAgICAgXG4gICAgICBpZiAodGhpcy5jb25maWcuc3luYy5pbmRpdmlkdWFsKSB7XG4gICAgICAgIHRoaXMuY29uZmlnLnN5bmMuaW5kaXZpZHVhbC5yZXF1aXJlX2NvbmZpcm1hdGlvbiA9IGZpeEJvb2xlYW4odGhpcy5jb25maWcuc3luYy5pbmRpdmlkdWFsLnJlcXVpcmVfY29uZmlybWF0aW9uKTtcbiAgICAgICAgdGhpcy5jb25maWcuc3luYy5pbmRpdmlkdWFsLnNob3dfZGlmZl9iZWZvcmVfc3luYyA9IGZpeEJvb2xlYW4odGhpcy5jb25maWcuc3luYy5pbmRpdmlkdWFsLnNob3dfZGlmZl9iZWZvcmVfc3luYyk7XG4gICAgICAgIHRoaXMuY29uZmlnLnN5bmMuaW5kaXZpZHVhbC50cmFja192ZXJzaW9ucyA9IGZpeEJvb2xlYW4odGhpcy5jb25maWcuc3luYy5pbmRpdmlkdWFsLnRyYWNrX3ZlcnNpb25zKTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgaWYgKHRoaXMuY29uZmlnLnN5bmMuYnVsaykge1xuICAgICAgICB0aGlzLmNvbmZpZy5zeW5jLmJ1bGsudXBsb2FkX2VuYWJsZWQgPSBmaXhCb29sZWFuKHRoaXMuY29uZmlnLnN5bmMuYnVsay51cGxvYWRfZW5hYmxlZCk7XG4gICAgICAgIHRoaXMuY29uZmlnLnN5bmMuYnVsay5kb3dubG9hZF9lbmFibGVkID0gZml4Qm9vbGVhbih0aGlzLmNvbmZpZy5zeW5jLmJ1bGsuZG93bmxvYWRfZW5hYmxlZCk7XG4gICAgICAgIHRoaXMuY29uZmlnLnN5bmMuYnVsay5yZXF1aXJlX3ByZXZpZXcgPSBmaXhCb29sZWFuKHRoaXMuY29uZmlnLnN5bmMuYnVsay5yZXF1aXJlX3ByZXZpZXcpO1xuICAgICAgICB0aGlzLmNvbmZpZy5zeW5jLmJ1bGsucmVzcGVjdF9sb2NhbF9vbmx5ID0gZml4Qm9vbGVhbih0aGlzLmNvbmZpZy5zeW5jLmJ1bGsucmVzcGVjdF9sb2NhbF9vbmx5KTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgaWYgKHRoaXMuY29uZmlnLnN5bmMucHJpdmFjeSkge1xuICAgICAgICB0aGlzLmNvbmZpZy5zeW5jLnByaXZhY3kuc2Nhbl9mb3Jfc2VjcmV0cyA9IGZpeEJvb2xlYW4odGhpcy5jb25maWcuc3luYy5wcml2YWN5LnNjYW5fZm9yX3NlY3JldHMpO1xuICAgICAgICB0aGlzLmNvbmZpZy5zeW5jLnByaXZhY3kuc2Nhbl9mb3JfcGlpID0gZml4Qm9vbGVhbih0aGlzLmNvbmZpZy5zeW5jLnByaXZhY3kuc2Nhbl9mb3JfcGlpKTtcbiAgICAgICAgdGhpcy5jb25maWcuc3luYy5wcml2YWN5Lndhcm5fb25fc2Vuc2l0aXZlID0gZml4Qm9vbGVhbih0aGlzLmNvbmZpZy5zeW5jLnByaXZhY3kud2Fybl9vbl9zZW5zaXRpdmUpO1xuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICAvLyBGaXggY29sbGVjdGlvbiBzZXR0aW5nc1xuICAgIGlmICh0aGlzLmNvbmZpZy5jb2xsZWN0aW9uKSB7XG4gICAgICB0aGlzLmNvbmZpZy5jb2xsZWN0aW9uLmF1dG9fc3VibWl0ID0gZml4Qm9vbGVhbih0aGlzLmNvbmZpZy5jb2xsZWN0aW9uLmF1dG9fc3VibWl0KTtcbiAgICAgIHRoaXMuY29uZmlnLmNvbGxlY3Rpb24ucmVxdWlyZV9yZXZpZXcgPSBmaXhCb29sZWFuKHRoaXMuY29uZmlnLmNvbGxlY3Rpb24ucmVxdWlyZV9yZXZpZXcpO1xuICAgICAgdGhpcy5jb25maWcuY29sbGVjdGlvbi5hZGRfYXR0cmlidXRpb24gPSBmaXhCb29sZWFuKHRoaXMuY29uZmlnLmNvbGxlY3Rpb24uYWRkX2F0dHJpYnV0aW9uKTtcbiAgICB9XG4gICAgXG4gICAgLy8gRml4IGRpc3BsYXkgc2V0dGluZ3NcbiAgICBpZiAodGhpcy5jb25maWcuZGlzcGxheSkge1xuICAgICAgaWYgKHRoaXMuY29uZmlnLmRpc3BsYXkucGVyc29uYV9pbmRpY2F0b3JzKSB7XG4gICAgICAgIHRoaXMuY29uZmlnLmRpc3BsYXkucGVyc29uYV9pbmRpY2F0b3JzLmVuYWJsZWQgPSBmaXhCb29sZWFuKHRoaXMuY29uZmlnLmRpc3BsYXkucGVyc29uYV9pbmRpY2F0b3JzLmVuYWJsZWQpO1xuICAgICAgICB0aGlzLmNvbmZpZy5kaXNwbGF5LnBlcnNvbmFfaW5kaWNhdG9ycy5pbmNsdWRlX2Vtb2ppID0gZml4Qm9vbGVhbih0aGlzLmNvbmZpZy5kaXNwbGF5LnBlcnNvbmFfaW5kaWNhdG9ycy5pbmNsdWRlX2Vtb2ppKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuY29uZmlnLmRpc3BsYXkudmVyYm9zZV9sb2dnaW5nID0gZml4Qm9vbGVhbih0aGlzLmNvbmZpZy5kaXNwbGF5LnZlcmJvc2VfbG9nZ2luZyk7XG4gICAgICB0aGlzLmNvbmZpZy5kaXNwbGF5LnNob3dfcHJvZ3Jlc3MgPSBmaXhCb29sZWFuKHRoaXMuY29uZmlnLmRpc3BsYXkuc2hvd19wcm9ncmVzcyk7XG4gICAgfVxuICAgIFxuICAgIC8vIEZpeCBnaXRodWIgc2V0dGluZ3NcbiAgICBpZiAodGhpcy5jb25maWcuZ2l0aHViKSB7XG4gICAgICBpZiAodGhpcy5jb25maWcuZ2l0aHViLnBvcnRmb2xpbykge1xuICAgICAgICB0aGlzLmNvbmZpZy5naXRodWIucG9ydGZvbGlvLnJlcG9zaXRvcnlfdXJsID0gZml4TnVsbCh0aGlzLmNvbmZpZy5naXRodWIucG9ydGZvbGlvLnJlcG9zaXRvcnlfdXJsKTtcbiAgICAgICAgdGhpcy5jb25maWcuZ2l0aHViLnBvcnRmb2xpby5hdXRvX2NyZWF0ZSA9IGZpeEJvb2xlYW4odGhpcy5jb25maWcuZ2l0aHViLnBvcnRmb2xpby5hdXRvX2NyZWF0ZSk7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5jb25maWcuZ2l0aHViLmF1dGgpIHtcbiAgICAgICAgdGhpcy5jb25maWcuZ2l0aHViLmF1dGgudXNlX29hdXRoID0gZml4Qm9vbGVhbih0aGlzLmNvbmZpZy5naXRodWIuYXV0aC51c2Vfb2F1dGgpO1xuICAgICAgICAvLyBGaXggY2xpZW50X2lkIGlmIGl0J3MgYSBzdHJpbmcgXCJudWxsXCJcbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmdpdGh1Yi5hdXRoLmNsaWVudF9pZCkge1xuICAgICAgICAgIHRoaXMuY29uZmlnLmdpdGh1Yi5hdXRoLmNsaWVudF9pZCA9IGZpeE51bGwodGhpcy5jb25maWcuZ2l0aHViLmF1dGguY2xpZW50X2lkKSB8fCB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWVyZ2UgcGFydGlhbCBjb25maWcgd2l0aCBkZWZhdWx0c1xuICAgKiBcbiAgICogSU1QT1JUQU5UOiBUaGlzIGZ1bmN0aW9uIHByZXNlcnZlcyB1bmtub3duIGZpZWxkcyBmb3IgZm9yd2FyZCBjb21wYXRpYmlsaXR5LlxuICAgKiBJZiBhIGZ1dHVyZSB2ZXJzaW9uIGFkZHMgbmV3IGNvbmZpZyBmaWVsZHMsIG9sZGVyIHZlcnNpb25zIHdvbid0IGxvc2UgdGhlbS5cbiAgICovXG4gIHByaXZhdGUgbWVyZ2VXaXRoRGVmYXVsdHMocGFydGlhbDogUGFydGlhbDxEb2xsaG91c2VDb25maWc+KTogRG9sbGhvdXNlQ29uZmlnIHtcbiAgICBjb25zdCBkZWZhdWx0cyA9IHRoaXMuZ2V0RGVmYXVsdENvbmZpZygpO1xuICAgIFxuICAgIC8vIFN0YXJ0IHdpdGggYSBkZWVwIGNsb25lIG9mIHBhcnRpYWwgdG8gcHJlc2VydmUgYWxsIHVua25vd24gZmllbGRzXG4gICAgY29uc3QgcmVzdWx0OiBhbnkgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHBhcnRpYWwpKTtcbiAgICBcbiAgICAvLyBFbnN1cmUgYWxsIHJlcXVpcmVkIGZpZWxkcyBleGlzdCB3aXRoIGRlZmF1bHRzXG4gICAgcmVzdWx0LnZlcnNpb24gPSByZXN1bHQudmVyc2lvbiB8fCBkZWZhdWx0cy52ZXJzaW9uO1xuICAgIFxuICAgIC8vIFVzZXIgc2VjdGlvbiAtIHByZXNlcnZlIHVua25vd24gZmllbGRzIHdoaWxlIGVuc3VyaW5nIHJlcXVpcmVkIGZpZWxkc1xuICAgIHJlc3VsdC51c2VyID0ge1xuICAgICAgLi4ucmVzdWx0LnVzZXIsXG4gICAgICB1c2VybmFtZTogcmVzdWx0LnVzZXI/LnVzZXJuYW1lID8/IGRlZmF1bHRzLnVzZXIudXNlcm5hbWUsXG4gICAgICBlbWFpbDogcmVzdWx0LnVzZXI/LmVtYWlsID8/IGRlZmF1bHRzLnVzZXIuZW1haWwsXG4gICAgICBkaXNwbGF5X25hbWU6IHJlc3VsdC51c2VyPy5kaXNwbGF5X25hbWUgPz8gZGVmYXVsdHMudXNlci5kaXNwbGF5X25hbWVcbiAgICB9O1xuICAgIFxuICAgIC8vIEdpdEh1YiBzZWN0aW9uIC0gZGVlcCBtZXJnZSBwcmVzZXJ2aW5nIHVua25vd24gZmllbGRzXG4gICAgaWYgKCFyZXN1bHQuZ2l0aHViKSByZXN1bHQuZ2l0aHViID0ge307XG4gICAgcmVzdWx0LmdpdGh1Yi5wb3J0Zm9saW8gPSB7XG4gICAgICAuLi5kZWZhdWx0cy5naXRodWIucG9ydGZvbGlvLFxuICAgICAgLi4ucmVzdWx0LmdpdGh1Yi5wb3J0Zm9saW9cbiAgICB9O1xuICAgIHJlc3VsdC5naXRodWIuYXV0aCA9IHtcbiAgICAgIC4uLmRlZmF1bHRzLmdpdGh1Yi5hdXRoLFxuICAgICAgLi4ucmVzdWx0LmdpdGh1Yi5hdXRoXG4gICAgfTtcbiAgICBcbiAgICAvLyBTeW5jIHNlY3Rpb24gLSBwcmVzZXJ2ZSB1bmtub3duIGZpZWxkcyBhdCBhbGwgbGV2ZWxzXG4gICAgaWYgKCFyZXN1bHQuc3luYykgcmVzdWx0LnN5bmMgPSB7fTtcbiAgICByZXN1bHQuc3luYy5lbmFibGVkID0gcmVzdWx0LnN5bmMuZW5hYmxlZCA/PyBkZWZhdWx0cy5zeW5jLmVuYWJsZWQ7XG4gICAgcmVzdWx0LnN5bmMuaW5kaXZpZHVhbCA9IHtcbiAgICAgIC4uLmRlZmF1bHRzLnN5bmMuaW5kaXZpZHVhbCxcbiAgICAgIC4uLnJlc3VsdC5zeW5jLmluZGl2aWR1YWxcbiAgICB9O1xuICAgIHJlc3VsdC5zeW5jLmJ1bGsgPSB7XG4gICAgICAuLi5kZWZhdWx0cy5zeW5jLmJ1bGssXG4gICAgICAuLi5yZXN1bHQuc3luYy5idWxrXG4gICAgfTtcbiAgICByZXN1bHQuc3luYy5wcml2YWN5ID0ge1xuICAgICAgLi4uZGVmYXVsdHMuc3luYy5wcml2YWN5LFxuICAgICAgLi4ucmVzdWx0LnN5bmMucHJpdmFjeSxcbiAgICAgIC8vIFNwZWNpYWwgaGFuZGxpbmcgZm9yIGFycmF5cyAtIHVzZSBwcm92aWRlZCBvciBkZWZhdWx0XG4gICAgICBleGNsdWRlZF9wYXR0ZXJuczogcmVzdWx0LnN5bmMucHJpdmFjeT8uZXhjbHVkZWRfcGF0dGVybnMgfHwgZGVmYXVsdHMuc3luYy5wcml2YWN5LmV4Y2x1ZGVkX3BhdHRlcm5zXG4gICAgfTtcbiAgICBcbiAgICAvLyBDb2xsZWN0aW9uIHNlY3Rpb25cbiAgICByZXN1bHQuY29sbGVjdGlvbiA9IHtcbiAgICAgIC4uLmRlZmF1bHRzLmNvbGxlY3Rpb24sXG4gICAgICAuLi5yZXN1bHQuY29sbGVjdGlvblxuICAgIH07XG4gICAgXG4gICAgLy8gRWxlbWVudHMgc2VjdGlvblxuICAgIGlmICghcmVzdWx0LmVsZW1lbnRzKSByZXN1bHQuZWxlbWVudHMgPSB7fTtcbiAgICByZXN1bHQuZWxlbWVudHMgPSB7XG4gICAgICAuLi5yZXN1bHQuZWxlbWVudHMsXG4gICAgICBhdXRvX2FjdGl2YXRlOiByZXN1bHQuZWxlbWVudHMuYXV0b19hY3RpdmF0ZSB8fCBkZWZhdWx0cy5lbGVtZW50cy5hdXRvX2FjdGl2YXRlLFxuICAgICAgZGVmYXVsdF9lbGVtZW50X2RpcjogcmVzdWx0LmVsZW1lbnRzLmRlZmF1bHRfZWxlbWVudF9kaXIgfHwgZGVmYXVsdHMuZWxlbWVudHMuZGVmYXVsdF9lbGVtZW50X2RpclxuICAgIH07XG4gICAgXG4gICAgLy8gRGlzcGxheSBzZWN0aW9uXG4gICAgaWYgKCFyZXN1bHQuZGlzcGxheSkgcmVzdWx0LmRpc3BsYXkgPSB7fTtcbiAgICByZXN1bHQuZGlzcGxheS5wZXJzb25hX2luZGljYXRvcnMgPSB7XG4gICAgICAuLi5kZWZhdWx0cy5kaXNwbGF5LnBlcnNvbmFfaW5kaWNhdG9ycyxcbiAgICAgIC4uLnJlc3VsdC5kaXNwbGF5LnBlcnNvbmFfaW5kaWNhdG9yc1xuICAgIH07XG4gICAgcmVzdWx0LmRpc3BsYXkudmVyYm9zZV9sb2dnaW5nID0gcmVzdWx0LmRpc3BsYXkudmVyYm9zZV9sb2dnaW5nID8/IGRlZmF1bHRzLmRpc3BsYXkudmVyYm9zZV9sb2dnaW5nO1xuICAgIHJlc3VsdC5kaXNwbGF5LnNob3dfcHJvZ3Jlc3MgPSByZXN1bHQuZGlzcGxheS5zaG93X3Byb2dyZXNzID8/IGRlZmF1bHRzLmRpc3BsYXkuc2hvd19wcm9ncmVzcztcbiAgICBcbiAgICByZXR1cm4gcmVzdWx0IGFzIERvbGxob3VzZUNvbmZpZztcbiAgfVxuXG4gIC8qKlxuICAgKiBNaWdyYXRlIHNldHRpbmdzIGZyb20gZW52aXJvbm1lbnQgdmFyaWFibGVzXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIG1pZ3JhdGVGcm9tRW52aXJvbm1lbnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IG1pZ3JhdGVkID0gZmFsc2U7XG4gICAgXG4gICAgLy8gTWlncmF0ZSB1c2VyIHNldHRpbmdzXG4gICAgaWYgKHByb2Nlc3MuZW52LkRPTExIT1VTRV9VU0VSICYmICF0aGlzLmNvbmZpZz8udXNlci51c2VybmFtZSkge1xuICAgICAgaWYgKCF0aGlzLmNvbmZpZykgdGhpcy5jb25maWcgPSB0aGlzLmdldERlZmF1bHRDb25maWcoKTtcbiAgICAgIHRoaXMuY29uZmlnLnVzZXIudXNlcm5hbWUgPSBwcm9jZXNzLmVudi5ET0xMSE9VU0VfVVNFUjtcbiAgICAgIG1pZ3JhdGVkID0gdHJ1ZTtcbiAgICB9XG4gICAgXG4gICAgaWYgKHByb2Nlc3MuZW52LkRPTExIT1VTRV9FTUFJTCAmJiAhdGhpcy5jb25maWc/LnVzZXIuZW1haWwpIHtcbiAgICAgIGlmICghdGhpcy5jb25maWcpIHRoaXMuY29uZmlnID0gdGhpcy5nZXREZWZhdWx0Q29uZmlnKCk7XG4gICAgICB0aGlzLmNvbmZpZy51c2VyLmVtYWlsID0gcHJvY2Vzcy5lbnYuRE9MTEhPVVNFX0VNQUlMO1xuICAgICAgbWlncmF0ZWQgPSB0cnVlO1xuICAgIH1cbiAgICBcbiAgICAvLyBNaWdyYXRlIHBvcnRmb2xpbyBVUkxcbiAgICBpZiAocHJvY2Vzcy5lbnYuRE9MTEhPVVNFX1BPUlRGT0xJT19VUkwgJiYgIXRoaXMuY29uZmlnPy5naXRodWIucG9ydGZvbGlvLnJlcG9zaXRvcnlfdXJsKSB7XG4gICAgICBpZiAoIXRoaXMuY29uZmlnKSB0aGlzLmNvbmZpZyA9IHRoaXMuZ2V0RGVmYXVsdENvbmZpZygpO1xuICAgICAgdGhpcy5jb25maWcuZ2l0aHViLnBvcnRmb2xpby5yZXBvc2l0b3J5X3VybCA9IHByb2Nlc3MuZW52LkRPTExIT1VTRV9QT1JURk9MSU9fVVJMO1xuICAgICAgbWlncmF0ZWQgPSB0cnVlO1xuICAgIH1cbiAgICBcbiAgICAvLyBNaWdyYXRlIGNvbGxlY3Rpb24gYXV0by1zdWJtaXRcbiAgICBpZiAocHJvY2Vzcy5lbnYuRE9MTEhPVVNFX0FVVE9fU1VCTUlUX1RPX0NPTExFQ1RJT04gIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKCF0aGlzLmNvbmZpZykgdGhpcy5jb25maWcgPSB0aGlzLmdldERlZmF1bHRDb25maWcoKTtcbiAgICAgIHRoaXMuY29uZmlnLmNvbGxlY3Rpb24uYXV0b19zdWJtaXQgPSBwcm9jZXNzLmVudi5ET0xMSE9VU0VfQVVUT19TVUJNSVRfVE9fQ09MTEVDVElPTiA9PT0gJ3RydWUnO1xuICAgICAgbWlncmF0ZWQgPSB0cnVlO1xuICAgIH1cbiAgICBcbiAgICBpZiAobWlncmF0ZWQpIHtcbiAgICAgIGxvZ2dlci5pbmZvKCdNaWdyYXRlZCBzZXR0aW5ncyBmcm9tIGVudmlyb25tZW50IHZhcmlhYmxlcycpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNldCBjb25maWd1cmF0aW9uIHRvIGRlZmF1bHRzXG4gICAqIFNFQ1VSSVRZIEZJWCAoUFIgIzg5NSk6IEFkZGVkIHByb3RvdHlwZSBwb2xsdXRpb24gcHJvdGVjdGlvblxuICAgKiBQcmV2aW91c2x5OiBEaXJlY3QgcHJvcGVydHkgYXNzaWdubWVudCBhbGxvd2VkIF9fcHJvdG9fXyBpbmplY3Rpb25cbiAgICogTm93OiBWYWxpZGF0ZXMga2V5cyBhZ2FpbnN0IGZvcmJpZGRlbiBwcm9wZXJ0aWVzIGJlZm9yZSBhc3NpZ25tZW50XG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVzZXRDb25maWcoc2VjdGlvbj86IHN0cmluZyk6IFByb21pc2U8Q29uZmlnQWN0aW9uUmVzdWx0PiB7XG4gICAgY29uc3QgZGVmYXVsdHMgPSB0aGlzLmdldERlZmF1bHRDb25maWcoKTtcbiAgICBcbiAgICBpZiAoc2VjdGlvbikge1xuICAgICAgLy8gUmVzZXQgc3BlY2lmaWMgc2VjdGlvblxuICAgICAgaWYgKCF0aGlzLmNvbmZpZykge1xuICAgICAgICB0aGlzLmNvbmZpZyA9IGRlZmF1bHRzO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3Qgc2VjdGlvbktleXMgPSBzZWN0aW9uLnNwbGl0KCcuJyk7XG4gICAgICAgIFxuICAgICAgICAvLyBTRUNVUklUWTogVmFsaWRhdGUgYWxsIGtleXMgdG8gcHJldmVudCBwcm90b3R5cGUgcG9sbHV0aW9uXG4gICAgICAgIGNvbnN0IEZPUkJJRERFTl9LRVlTID0gWydfX3Byb3RvX18nLCAnY29uc3RydWN0b3InLCAncHJvdG90eXBlJ107XG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIHNlY3Rpb25LZXlzKSB7XG4gICAgICAgICAgaWYgKEZPUkJJRERFTl9LRVlTLmluY2x1ZGVzKGtleSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRm9yYmlkZGVuIHByb3BlcnR5IGluIHNlY3Rpb246ICR7a2V5fWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgbGV0IGN1cnJlbnQ6IGFueSA9IHRoaXMuY29uZmlnO1xuICAgICAgICBsZXQgZGVmYXVsdFNlY3Rpb246IGFueSA9IGRlZmF1bHRzO1xuICAgICAgICBcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWN0aW9uS2V5cy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgICBjdXJyZW50ID0gY3VycmVudFtzZWN0aW9uS2V5c1tpXV07XG4gICAgICAgICAgZGVmYXVsdFNlY3Rpb24gPSBkZWZhdWx0U2VjdGlvbltzZWN0aW9uS2V5c1tpXV07XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGNvbnN0IGxhc3RLZXkgPSBzZWN0aW9uS2V5c1tzZWN0aW9uS2V5cy5sZW5ndGggLSAxXTtcbiAgICAgICAgY3VycmVudFtsYXN0S2V5XSA9IGRlZmF1bHRTZWN0aW9uW2xhc3RLZXldO1xuICAgICAgfVxuICAgICAgXG4gICAgICBhd2FpdCB0aGlzLnNhdmVDb25maWcoKTtcbiAgICAgIFxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgbWVzc2FnZTogYFNlY3Rpb24gJyR7c2VjdGlvbn0nIHJlc2V0IHRvIGRlZmF1bHRzYFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gUmVzZXQgZW50aXJlIGNvbmZpZ1xuICAgICAgdGhpcy5jb25maWcgPSBkZWZhdWx0cztcbiAgICAgIGF3YWl0IHRoaXMuc2F2ZUNvbmZpZygpO1xuICAgICAgXG4gICAgICByZXR1cm4ge1xuICAgICAgICBzdWNjZXNzOiB0cnVlLFxuICAgICAgICBtZXNzYWdlOiAnQ29uZmlndXJhdGlvbiByZXNldCB0byBkZWZhdWx0cydcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEV4cG9ydCBjb25maWd1cmF0aW9uIHRvIGZpbGVcbiAgICovXG4gIHB1YmxpYyBhc3luYyBleHBvcnRDb25maWcoZmlsZVBhdGg6IHN0cmluZyk6IFByb21pc2U8Q29uZmlnQWN0aW9uUmVzdWx0PiB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgIG1lc3NhZ2U6ICdObyBjb25maWd1cmF0aW9uIHRvIGV4cG9ydCdcbiAgICAgIH07XG4gICAgfVxuICAgIFxuICAgIHRyeSB7XG4gICAgICBjb25zdCB5YW1sQ29udGVudCA9IHlhbWwuZHVtcCh0aGlzLmNvbmZpZywge1xuICAgICAgICBpbmRlbnQ6IDIsXG4gICAgICAgIGxpbmVXaWR0aDogMTIwLFxuICAgICAgICBub1JlZnM6IHRydWUsXG4gICAgICAgIHNvcnRLZXlzOiBmYWxzZVxuICAgICAgfSk7XG4gICAgICBcbiAgICAgIGF3YWl0IGZzLndyaXRlRmlsZShmaWxlUGF0aCwgeWFtbENvbnRlbnQsIHsgZW5jb2Rpbmc6ICd1dGYtOCcsIG1vZGU6IDBvNjAwIH0pO1xuICAgICAgXG4gICAgICByZXR1cm4ge1xuICAgICAgICBzdWNjZXNzOiB0cnVlLFxuICAgICAgICBtZXNzYWdlOiBgQ29uZmlndXJhdGlvbiBleHBvcnRlZCB0byAke2ZpbGVQYXRofWBcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICBtZXNzYWdlOiBgRmFpbGVkIHRvIGV4cG9ydCBjb25maWd1cmF0aW9uOiAke2Vycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKX1gXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbXBvcnQgY29uZmlndXJhdGlvbiBmcm9tIGZpbGVcbiAgICovXG4gIHB1YmxpYyBhc3luYyBpbXBvcnRDb25maWcoZmlsZVBhdGg6IHN0cmluZyk6IFByb21pc2U8Q29uZmlnQWN0aW9uUmVzdWx0PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBmcy5yZWFkRmlsZShmaWxlUGF0aCwgJ3V0Zi04Jyk7XG4gICAgICBcbiAgICAgIC8vIFBhcnNlIGFuZCB2YWxpZGF0ZVxuICAgICAgY29uc3QgcGFyc2VkID0gU2VjdXJlWWFtbFBhcnNlci5wYXJzZShjb250ZW50LCB7XG4gICAgICAgIG1heFlhbWxTaXplOiA2NCAqIDEwMjQsXG4gICAgICAgIHZhbGlkYXRlQ29udGVudDogZmFsc2UsXG4gICAgICAgIHZhbGlkYXRlRmllbGRzOiBmYWxzZVxuICAgICAgfSk7XG4gICAgICBcbiAgICAgIGlmICghcGFyc2VkLmRhdGEgfHwgdHlwZW9mIHBhcnNlZC5kYXRhICE9PSAnb2JqZWN0Jykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICAgIG1lc3NhZ2U6ICdJbnZhbGlkIGNvbmZpZ3VyYXRpb24gZm9ybWF0IGluIGltcG9ydCBmaWxlJ1xuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBNZXJnZSB3aXRoIGRlZmF1bHRzXG4gICAgICB0aGlzLmNvbmZpZyA9IHRoaXMubWVyZ2VXaXRoRGVmYXVsdHMocGFyc2VkLmRhdGEgYXMgUGFydGlhbDxEb2xsaG91c2VDb25maWc+KTtcbiAgICAgIFxuICAgICAgLy8gU2F2ZSB0aGUgaW1wb3J0ZWQgY29uZmlnXG4gICAgICBhd2FpdCB0aGlzLnNhdmVDb25maWcoKTtcbiAgICAgIFxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgbWVzc2FnZTogYENvbmZpZ3VyYXRpb24gaW1wb3J0ZWQgZnJvbSAke2ZpbGVQYXRofWBcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICBtZXNzYWdlOiBgRmFpbGVkIHRvIGltcG9ydCBjb25maWd1cmF0aW9uOiAke2Vycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKX1gXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgZm9ybWF0dGVkIGNvbmZpZyBmb3IgZGlzcGxheVxuICAgKi9cbiAgcHVibGljIGdldEZvcm1hdHRlZENvbmZpZyhzZWN0aW9uPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZiAoIXRoaXMuY29uZmlnKSB7XG4gICAgICByZXR1cm4gJ0NvbmZpZ3VyYXRpb24gbm90IGluaXRpYWxpemVkJztcbiAgICB9XG4gICAgXG4gICAgbGV0IGNvbmZpZ1RvU2hvdzogYW55ID0gdGhpcy5jb25maWc7XG4gICAgXG4gICAgaWYgKHNlY3Rpb24pIHtcbiAgICAgIGNvbmZpZ1RvU2hvdyA9IHRoaXMuZ2V0U2V0dGluZyhzZWN0aW9uKTtcbiAgICAgIGlmICghY29uZmlnVG9TaG93KSB7XG4gICAgICAgIHJldHVybiBgU2VjdGlvbiAnJHtzZWN0aW9ufScgbm90IGZvdW5kYDtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgLy8gUmVtb3ZlIHNlbnNpdGl2ZSBkYXRhIGZvciBkaXNwbGF5XG4gICAgY29uc3Qgc2FuaXRpemVkID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShjb25maWdUb1Nob3cpKTtcbiAgICBcbiAgICAvLyBEb24ndCBzaG93IHRva2VucyBpZiB0aGV5IGV4aXN0XG4gICAgaWYgKHNhbml0aXplZC5naXRodWI/LmF1dGg/LnRva2VuKSB7XG4gICAgICBzYW5pdGl6ZWQuZ2l0aHViLmF1dGgudG9rZW4gPSAnKioqUkVEQUNURUQqKionO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4geWFtbC5kdW1wKHNhbml0aXplZCwge1xuICAgICAgaW5kZW50OiAyLFxuICAgICAgbGluZVdpZHRoOiAxMjAsXG4gICAgICBub1JlZnM6IHRydWUsXG4gICAgICBzb3J0S2V5czogZmFsc2VcbiAgICB9KTtcbiAgfVxufSJdfQ==