UNPKG

@dollhousemcp/mcp-server

Version:

DollhouseMCP - A Model Context Protocol (MCP) server that enables dynamic AI persona management from markdown files, allowing Claude and other compatible AI assistants to activate and switch between different behavioral personas.

312 lines 55.5 kB
/** * Unicode Validator for DollhouseMCP * * Prevents Unicode-based bypass attacks including: * - Homograph attacks (visually similar characters) * - Direction override attacks (RLO/LRO) * - Mixed script attacks * - Zero-width character injection * - Unicode normalization bypasses * * Security: SEC-001 - Unicode attack prevention */ import { SecurityMonitor } from '../securityMonitor.js'; export class UnicodeValidator { /** * Unicode attack patterns and confusable characters */ /** * Direction override characters that can hide or reverse text display * @see https://unicode.org/reports/tr9/#Directional_Formatting_Characters * U+202A-U+202E: Left/Right embedding and override marks (LRE, RLE, PDF, LRO, RLO) * U+2066-U+2069: Isolate formatting characters (LRI, RLI, FSI, PDI) */ static DIRECTION_OVERRIDE_CHARS = /[\u202A-\u202E\u2066-\u2069]/g; /** * Zero-width and invisible formatting characters often used to hide payloads * U+200B-U+200F: Zero-width spaces and directional marks * U+2028-U+202F: Line/paragraph separators and formatting characters * U+FEFF: Zero-width no-break space (Byte Order Mark) */ static ZERO_WIDTH_CHARS = /[\u200B-\u200F\u2028-\u202F\uFEFF]/g; /** * Non-printable control characters that should not appear in normal text * U+0000-U+0008, U+000B-U+000C, U+000E-U+001F: C0 control codes (except TAB, LF, CR) * U+007F-U+009F: Delete and C1 control codes * U+FFFE-U+FFFF: Non-characters that should never appear in valid text */ static NON_PRINTABLE_CHARS = /[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F\uFFFE\uFFFF]/g; /** * Common homograph/confusable character mappings * Maps visually similar Unicode characters to their ASCII equivalents */ static CONFUSABLE_MAPPINGS = new Map([ // Cyrillic to Latin ['а', 'a'], ['е', 'e'], ['о', 'o'], ['р', 'p'], ['с', 'c'], ['х', 'x'], ['у', 'y'], ['А', 'A'], ['В', 'B'], ['Е', 'E'], ['К', 'K'], ['М', 'M'], ['Н', 'H'], ['О', 'O'], ['Р', 'P'], ['С', 'C'], ['Т', 'T'], ['У', 'Y'], ['Х', 'X'], // Greek to Latin ['α', 'a'], ['β', 'b'], ['γ', 'g'], ['δ', 'd'], ['ε', 'e'], ['ζ', 'z'], ['η', 'h'], ['θ', 'th'], ['ι', 'i'], ['κ', 'k'], ['λ', 'l'], ['μ', 'm'], ['ν', 'n'], ['ξ', 'x'], ['ο', 'o'], ['π', 'p'], ['ρ', 'r'], ['σ', 's'], ['τ', 't'], ['υ', 'u'], ['φ', 'f'], ['χ', 'ch'], ['ψ', 'ps'], ['ω', 'w'], // Mathematical symbols to ASCII (various styles) ['𝒂', 'a'], ['𝒃', 'b'], ['𝒄', 'c'], ['𝒅', 'd'], ['𝒆', 'e'], ['𝒇', 'f'], ['𝒈', 'g'], ['𝒉', 'h'], ['𝒊', 'i'], ['𝒋', 'j'], ['𝒌', 'k'], ['𝒍', 'l'], ['𝒎', 'm'], ['𝒏', 'n'], ['𝒐', 'o'], ['𝒑', 'p'], ['𝒒', 'q'], ['𝒓', 'r'], ['𝒔', 's'], ['𝒕', 't'], ['𝒖', 'u'], ['𝒗', 'v'], ['𝒘', 'w'], ['𝒙', 'x'], ['𝒚', 'y'], ['𝒛', 'z'], ['𝐚', 'a'], ['𝐛', 'b'], ['𝐜', 'c'], ['𝐝', 'd'], ['𝐞', 'e'], ['𝐟', 'f'], ['𝐠', 'g'], ['𝐡', 'h'], ['𝐢', 'i'], ['𝐣', 'j'], ['𝐤', 'k'], ['𝐥', 'l'], ['𝐦', 'm'], ['𝐧', 'n'], ['𝐨', 'o'], ['𝐩', 'p'], ['𝐪', 'q'], ['𝐫', 'r'], ['𝐬', 's'], ['𝐭', 't'], ['𝐮', 'u'], ['𝐯', 'v'], ['𝐰', 'w'], ['𝐱', 'x'], ['𝐲', 'y'], ['𝐳', 'z'], // Special i variants (Turkish, etc.) ['ı', 'i'], ['İ', 'I'], ['і', 'i'], ['Ӏ', 'I'], // Other common confusables ['ǝ', 'e'], ['ɐ', 'a'], ['ɔ', 'o'], ['ʇ', 't'], ['ʌ', 'v'], ['ʍ', 'w'], ['℃', 'C'], ['℉', 'F'], ['№', 'No'], ['™', 'TM'], ['®', 'R'], // Fullwidth characters ['A', 'A'], ['B', 'B'], ['C', 'C'], ['D', 'D'], ['E', 'E'], ['F', 'F'], ['G', 'G'], ['H', 'H'], ['I', 'I'], ['J', 'J'], ['K', 'K'], ['L', 'L'], ['M', 'M'], ['N', 'N'], ['O', 'O'], ['P', 'P'], ['Q', 'Q'], ['R', 'R'], ['S', 'S'], ['T', 'T'], ['U', 'U'], ['V', 'V'], ['W', 'W'], ['X', 'X'], ['Y', 'Y'], ['Z', 'Z'], ['a', 'a'], ['b', 'b'], ['c', 'c'], ['d', 'd'], ['e', 'e'], ['f', 'f'], ['g', 'g'], ['h', 'h'], ['i', 'i'], ['j', 'j'], ['k', 'k'], ['l', 'l'], ['m', 'm'], ['n', 'n'], ['o', 'o'], ['p', 'p'], ['q', 'q'], ['r', 'r'], ['s', 's'], ['t', 't'], ['u', 'u'], ['v', 'v'], ['w', 'w'], ['x', 'x'], ['y', 'y'], ['z', 'z'], ['0', '0'], ['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'], ['9', '9'], ]); /** * Script mixing detection patterns * Detects suspicious mixing of different Unicode scripts */ static SCRIPT_PATTERNS = { LATIN: /[\u0000-\u007F\u00A0-\u00FF\u0100-\u017F\u0180-\u024F]/, CYRILLIC: /[\u0400-\u04FF\u0500-\u052F\u2DE0-\u2DFF\uA640-\uA69F]/, GREEK: /[\u0370-\u03FF\u1F00-\u1FFF]/, ARABIC: /[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]/, HEBREW: /[\u0590-\u05FF\uFB1D-\uFB4F]/, CJK: /[\u2E80-\u2EFF\u2F00-\u2FDF\u3000-\u303F\u3040-\u309F\u30A0-\u30FF\u3100-\u312F\u3130-\u318F\u3190-\u319F\u31A0-\u31BF\u31C0-\u31EF\u31F0-\u31FF\u3200-\u32FF\u3300-\u33FF\u3400-\u4DBF\u4DC0-\u4DFF\u4E00-\u9FFF]/, }; /** * Normalize Unicode content to prevent bypass attacks */ static normalize(content) { const issues = []; let normalized = content; let severity = 'low'; try { // 1. Detect and log suspicious Unicode patterns before normalization const suspiciousPatterns = this.detectSuspiciousPatterns(content); issues.push(...suspiciousPatterns.issues); if (suspiciousPatterns.severity) { severity = this.escalateSeverity(severity, suspiciousPatterns.severity); } // 2. Remove direction override characters (prevents RLO/LRO attacks) if (this.DIRECTION_OVERRIDE_CHARS.test(normalized)) { issues.push('Direction override characters detected'); severity = this.escalateSeverity(severity, 'high'); normalized = normalized.replace(this.DIRECTION_OVERRIDE_CHARS, ''); SecurityMonitor.logSecurityEvent({ type: 'UNICODE_DIRECTION_OVERRIDE', severity: 'HIGH', source: 'unicode_validation', details: 'Direction override characters removed from content' }); } // 3. Remove zero-width and non-printable characters if (this.ZERO_WIDTH_CHARS.test(normalized) || this.NON_PRINTABLE_CHARS.test(normalized)) { issues.push('Zero-width or non-printable characters detected'); severity = this.escalateSeverity(severity, 'medium'); normalized = normalized .replace(this.ZERO_WIDTH_CHARS, '') .replace(this.NON_PRINTABLE_CHARS, ''); } // 4. Apply Unicode normalization (NFC - Canonical Decomposition + Composition) normalized = normalized.normalize('NFC'); // 5. Detect mixed script attacks BEFORE confusable replacement const mixedScriptResult = this.detectMixedScripts(normalized); if (mixedScriptResult.isSuspicious) { issues.push(`Mixed script usage detected: ${mixedScriptResult.scripts.join(', ')}`); severity = this.escalateSeverity(severity, 'high'); SecurityMonitor.logSecurityEvent({ type: 'UNICODE_MIXED_SCRIPT', severity: 'HIGH', source: 'unicode_validation', details: `Mixed scripts detected: ${mixedScriptResult.scripts.join(', ')}` }); } // 6. Always replace confusable characters with ASCII equivalents for security // This prevents homograph attacks regardless of script mixing const confusableResult = this.replaceConfusables(normalized); if (confusableResult.hasConfusables) { normalized = confusableResult.normalized; issues.push('Confusable Unicode characters detected and normalized'); severity = this.escalateSeverity(severity, 'medium'); // Log if this happens in legitimate multilingual context if (!mixedScriptResult.isSuspicious) { SecurityMonitor.logSecurityEvent({ type: 'UNICODE_VALIDATION_ERROR', severity: 'LOW', source: 'unicode_validation', details: 'Confusable characters normalized in legitimate multilingual content' }); } } return { isValid: issues.length === 0, normalizedContent: normalized, detectedIssues: issues.length > 0 ? issues : undefined, severity: issues.length > 0 ? severity : undefined }; } catch (error) { SecurityMonitor.logSecurityEvent({ type: 'UNICODE_VALIDATION_ERROR', severity: 'HIGH', source: 'unicode_validation', details: `Unicode validation failed: ${error instanceof Error ? error.message : String(error)}` }); // Fallback: return original content if normalization fails return { isValid: false, normalizedContent: content, detectedIssues: ['Unicode validation failed'], severity: 'high' }; } } /** * Detect suspicious Unicode patterns that might indicate attacks */ static detectSuspiciousPatterns(content) { const issues = []; let severity; // Check for excessive Unicode escapes (possible encoding bypass) /** * Pattern to match Unicode escape sequences * \\u: Literal backslash followed by 'u' * [0-9a-fA-F]{4}: Exactly 4 hexadecimal digits * Used to detect attempts to bypass filters using \u0061dmin style encoding */ const unicodeEscapePattern = /\\u[0-9a-fA-F]{4}/g; const unicodeEscapes = content.match(unicodeEscapePattern); if (unicodeEscapes && unicodeEscapes.length > 10) { issues.push(`Excessive Unicode escapes detected (${unicodeEscapes.length})`); severity = 'high'; } // Check for suspicious Unicode ranges that might hide content const suspiciousRanges = [ { range: /[\uE000-\uF8FF]/g, name: 'Private Use Area' }, // Note: Properly paired surrogate pairs [\uD800-\uDFFF] are normal for emojis { range: /[\uFDD0-\uFDEF]/g, name: 'Non-characters' }, { range: /[\uFFFE\uFFFF]/g, name: 'Non-characters' } ]; for (const { range, name } of suspiciousRanges) { if (range.test(content)) { issues.push(`Suspicious Unicode range detected: ${name}`); severity = this.escalateSeverity(severity, 'medium'); } } // Check for malformed surrogate pairs using safe character-by-character validation // This avoids ReDoS vulnerabilities from complex regex patterns if (this.hasMalformedSurrogates(content)) { issues.push('Malformed surrogate pairs detected'); severity = this.escalateSeverity(severity, 'high'); } return { issues, severity }; } /** * Replace confusable Unicode characters with ASCII equivalents */ static replaceConfusables(content) { let normalized = content; let hasConfusables = false; for (const [confusable, replacement] of this.CONFUSABLE_MAPPINGS) { if (normalized.includes(confusable)) { normalized = normalized.replace(new RegExp(this.escapeRegex(confusable), 'g'), replacement); hasConfusables = true; } } return { normalized, hasConfusables }; } /** * Detect suspicious mixing of different Unicode scripts */ static detectMixedScripts(content) { const detectedScripts = []; for (const [scriptName, pattern] of Object.entries(this.SCRIPT_PATTERNS)) { if (pattern.test(content)) { detectedScripts.push(scriptName); } } // Consider it suspicious if: // 1. More than 3 scripts are mixed (legitimate text rarely mixes >3 scripts) // 2. Content contains Latin + dangerous confusable scripts (Cyrillic/Greek - common attack pattern) // Note: Latin + CJK is common and legitimate (e.g., Chinese with English) const isSuspicious = detectedScripts.length > 3 || (detectedScripts.includes('LATIN') && detectedScripts.length > 1 && (detectedScripts.includes('CYRILLIC') || detectedScripts.includes('GREEK'))); return { isSuspicious, scripts: detectedScripts }; } /** * Escalate severity level (higher severity takes precedence) */ static escalateSeverity(current, newSeverity) { const severityLevels = { low: 1, medium: 2, high: 3, critical: 4 }; const currentLevel = current ? severityLevels[current] : 0; const newLevel = severityLevels[newSeverity]; return newLevel > currentLevel ? newSeverity : (current || 'low'); } /** * Escape special regex characters for safe replacement */ static escapeRegex(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } /** * Check if content contains potentially dangerous Unicode patterns */ static containsDangerousUnicode(content) { // Quick check for obviously dangerous patterns return this.DIRECTION_OVERRIDE_CHARS.test(content) || this.ZERO_WIDTH_CHARS.test(content) || this.NON_PRINTABLE_CHARS.test(content) || this.hasExcessiveUnicodeEscapes(content); } /** * Check if content has excessive Unicode escape sequences * Prevents null pointer exception by safely checking match results */ static hasExcessiveUnicodeEscapes(content) { const matches = content.match(/\\u[0-9a-fA-F]{4}/g); return matches !== null && matches.length > 10; } /** * Safely check for malformed surrogate pairs without ReDoS vulnerability * Uses character-by-character validation instead of complex regex */ static hasMalformedSurrogates(content) { for (let i = 0; i < content.length; i++) { const char = content.charCodeAt(i); // High surrogate (U+D800-U+DBFF) if (char >= 0xD800 && char <= 0xDBFF) { // Check if it's followed by a low surrogate if (i + 1 >= content.length) { return true; // High surrogate at end of string } const nextChar = content.charCodeAt(i + 1); if (nextChar < 0xDC00 || nextChar > 0xDFFF) { return true; // High surrogate not followed by low surrogate } i++; // Skip the valid low surrogate } // Low surrogate (U+DC00-U+DFFF) without preceding high surrogate else if (char >= 0xDC00 && char <= 0xDFFF) { return true; // Unpaired low surrogate } } return false; } /** * Get safe preview of Unicode content for logging */ static getSafePreview(content, maxLength = 100) { // Remove dangerous Unicode characters and truncate for safe logging const cleaned = content .replace(this.DIRECTION_OVERRIDE_CHARS, '[DIR]') .replace(this.ZERO_WIDTH_CHARS, '[ZW]') .replace(this.NON_PRINTABLE_CHARS, '[NP]'); return cleaned.length > maxLength ? cleaned.substring(0, maxLength) + '...' : cleaned; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidW5pY29kZVZhbGlkYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZWN1cml0eS92YWxpZGF0b3JzL3VuaWNvZGVWYWxpZGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7O0dBV0c7QUFHSCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFTeEQsTUFBTSxPQUFPLGdCQUFnQjtJQUMzQjs7T0FFRztJQUVIOzs7OztPQUtHO0lBQ0ssTUFBTSxDQUFVLHdCQUF3QixHQUFHLCtCQUErQixDQUFDO0lBRW5GOzs7OztPQUtHO0lBQ0ssTUFBTSxDQUFVLGdCQUFnQixHQUFHLHFDQUFxQyxDQUFDO0lBRWpGOzs7OztPQUtHO0lBQ0ssTUFBTSxDQUFVLG1CQUFtQixHQUFHLG9FQUFvRSxDQUFDO0lBRW5IOzs7T0FHRztJQUNLLE1BQU0sQ0FBVSxtQkFBbUIsR0FBd0IsSUFBSSxHQUFHLENBQUM7UUFDekUsb0JBQW9CO1FBQ3BCLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQztRQUNsRixDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUM7UUFDbEYsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDO1FBRTFELGlCQUFpQjtRQUNqQixDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUM7UUFDbEYsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDO1FBQ25GLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQztRQUNsRixDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUM7UUFFcEMsaURBQWlEO1FBQ2pELENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQztRQUNoVixDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUM7UUFFaFYscUNBQXFDO1FBQ3JDLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQztRQUU5QywyQkFBMkI7UUFDM0IsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDO1FBQ3RFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQztRQUU1RCx1QkFBdUI7UUFDdkIsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDO1FBQ3RULENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxF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SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxjQUFjLENBQUMsT0FBZSxFQUFFLFlBQW9CLEdBQUc7UUFDNUQsb0VBQW9FO1FBQ3BFLE1BQU0sT0FBTyxHQUFHLE9BQU87YUFDcEIsT0FBTyxDQUFDLElBQUksQ0FBQyx3QkFBd0IsRUFBRSxPQUFPLENBQUM7YUFDL0MsT0FBTyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxNQUFNLENBQUM7YUFDdEMsT0FBTyxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUU3QyxPQUFPLE9BQU8sQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLENBQUM7WUFDakMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsU0FBUyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUM7WUFDekMsT0FBTyxDQUFDO0lBQ1osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVW5pY29kZSBWYWxpZGF0b3IgZm9yIERvbGxob3VzZU1DUFxuICogXG4gKiBQcmV2ZW50cyBVbmljb2RlLWJhc2VkIGJ5cGFzcyBhdHRhY2tzIGluY2x1ZGluZzpcbiAqIC0gSG9tb2dyYXBoIGF0dGFja3MgKHZpc3VhbGx5IHNpbWlsYXIgY2hhcmFjdGVycylcbiAqIC0gRGlyZWN0aW9uIG92ZXJyaWRlIGF0dGFja3MgKFJMTy9MUk8pXG4gKiAtIE1peGVkIHNjcmlwdCBhdHRhY2tzXG4gKiAtIFplcm8td2lkdGggY2hhcmFjdGVyIGluamVjdGlvblxuICogLSBVbmljb2RlIG5vcm1hbGl6YXRpb24gYnlwYXNzZXNcbiAqIFxuICogU2VjdXJpdHk6IFNFQy0wMDEgLSBVbmljb2RlIGF0dGFjayBwcmV2ZW50aW9uXG4gKi9cblxuaW1wb3J0IHsgU2VjdXJpdHlFcnJvciB9IGZyb20gJy4uL2Vycm9ycy5qcyc7XG5pbXBvcnQgeyBTZWN1cml0eU1vbml0b3IgfSBmcm9tICcuLi9zZWN1cml0eU1vbml0b3IuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFVuaWNvZGVWYWxpZGF0aW9uUmVzdWx0IHtcbiAgaXNWYWxpZDogYm9vbGVhbjtcbiAgbm9ybWFsaXplZENvbnRlbnQ6IHN0cmluZztcbiAgZGV0ZWN0ZWRJc3N1ZXM/OiBzdHJpbmdbXTtcbiAgc2V2ZXJpdHk/OiAnbG93JyB8ICdtZWRpdW0nIHwgJ2hpZ2gnIHwgJ2NyaXRpY2FsJztcbn1cblxuZXhwb3J0IGNsYXNzIFVuaWNvZGVWYWxpZGF0b3Ige1xuICAvKipcbiAgICogVW5pY29kZSBhdHRhY2sgcGF0dGVybnMgYW5kIGNvbmZ1c2FibGUgY2hhcmFjdGVyc1xuICAgKi9cbiAgXG4gIC8qKlxuICAgKiBEaXJlY3Rpb24gb3ZlcnJpZGUgY2hhcmFjdGVycyB0aGF0IGNhbiBoaWRlIG9yIHJldmVyc2UgdGV4dCBkaXNwbGF5XG4gICAqIEBzZWUgaHR0cHM6Ly91bmljb2RlLm9yZy9yZXBvcnRzL3RyOS8jRGlyZWN0aW9uYWxfRm9ybWF0dGluZ19DaGFyYWN0ZXJzXG4gICAqIFUrMjAyQS1VKzIwMkU6IExlZnQvUmlnaHQgZW1iZWRkaW5nIGFuZCBvdmVycmlkZSBtYXJrcyAoTFJFLCBSTEUsIFBERiwgTFJPLCBSTE8pXG4gICAqIFUrMjA2Ni1VKzIwNjk6IElzb2xhdGUgZm9ybWF0dGluZyBjaGFyYWN0ZXJzIChMUkksIFJMSSwgRlNJLCBQREkpXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBESVJFQ1RJT05fT1ZFUlJJREVfQ0hBUlMgPSAvW1xcdTIwMkEtXFx1MjAyRVxcdTIwNjYtXFx1MjA2OV0vZztcbiAgXG4gIC8qKlxuICAgKiBaZXJvLXdpZHRoIGFuZCBpbnZpc2libGUgZm9ybWF0dGluZyBjaGFyYWN0ZXJzIG9mdGVuIHVzZWQgdG8gaGlkZSBwYXlsb2Fkc1xuICAgKiBVKzIwMEItVSsyMDBGOiBaZXJvLXdpZHRoIHNwYWNlcyBhbmQgZGlyZWN0aW9uYWwgbWFya3NcbiAgICogVSsyMDI4LVUrMjAyRjogTGluZS9wYXJhZ3JhcGggc2VwYXJhdG9ycyBhbmQgZm9ybWF0dGluZyBjaGFyYWN0ZXJzXG4gICAqIFUrRkVGRjogWmVyby13aWR0aCBuby1icmVhayBzcGFjZSAoQnl0ZSBPcmRlciBNYXJrKVxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgWkVST19XSURUSF9DSEFSUyA9IC9bXFx1MjAwQi1cXHUyMDBGXFx1MjAyOC1cXHUyMDJGXFx1RkVGRl0vZztcbiAgXG4gIC8qKlxuICAgKiBOb24tcHJpbnRhYmxlIGNvbnRyb2wgY2hhcmFjdGVycyB0aGF0IHNob3VsZCBub3QgYXBwZWFyIGluIG5vcm1hbCB0ZXh0XG4gICAqIFUrMDAwMC1VKzAwMDgsIFUrMDAwQi1VKzAwMEMsIFUrMDAwRS1VKzAwMUY6IEMwIGNvbnRyb2wgY29kZXMgKGV4Y2VwdCBUQUIsIExGLCBDUilcbiAgICogVSswMDdGLVUrMDA5RjogRGVsZXRlIGFuZCBDMSBjb250cm9sIGNvZGVzXG4gICAqIFUrRkZGRS1VK0ZGRkY6IE5vbi1jaGFyYWN0ZXJzIHRoYXQgc2hvdWxkIG5ldmVyIGFwcGVhciBpbiB2YWxpZCB0ZXh0XG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBOT05fUFJJTlRBQkxFX0NIQVJTID0gL1tcXHUwMDAwLVxcdTAwMDhcXHUwMDBCXFx1MDAwQ1xcdTAwMEUtXFx1MDAxRlxcdTAwN0YtXFx1MDA5RlxcdUZGRkVcXHVGRkZGXS9nO1xuICBcbiAgLyoqXG4gICAqIENvbW1vbiBob21vZ3JhcGgvY29uZnVzYWJsZSBjaGFyYWN0ZXIgbWFwcGluZ3NcbiAgICogTWFwcyB2aXN1YWxseSBzaW1pbGFyIFVuaWNvZGUgY2hhcmFjdGVycyB0byB0aGVpciBBU0NJSSBlcXVpdmFsZW50c1xuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgQ09ORlVTQUJMRV9NQVBQSU5HUzogTWFwPHN0cmluZywgc3RyaW5nPiA9IG5ldyBNYXAoW1xuICAgIC8vIEN5cmlsbGljIHRvIExhdGluXG4gICAgWyfQsCcsICdhJ10sIFsn0LUnLCAnZSddLCBbJ9C+JywgJ28nXSwgWyfRgCcsICdwJ10sIFsn0YEnLCAnYyddLCBbJ9GFJywgJ3gnXSwgWyfRgycsICd5J10sXG4gICAgWyfQkCcsICdBJ10sIFsn0JInLCAnQiddLCBbJ9CVJywgJ0UnXSwgWyfQmicsICdLJ10sIFsn0JwnLCAnTSddLCBbJ9CdJywgJ0gnXSwgWyfQnicsICdPJ10sIFxuICAgIFsn0KAnLCAnUCddLCBbJ9ChJywgJ0MnXSwgWyfQoicsICdUJ10sIFsn0KMnLCAnWSddLCBbJ9ClJywgJ1gnXSxcbiAgICBcbiAgICAvLyBHcmVlayB0byBMYXRpblxuICAgIFsnzrEnLCAnYSddLCBbJ86yJywgJ2InXSwgWyfOsycsICdnJ10sIFsnzrQnLCAnZCddLCBbJ861JywgJ2UnXSwgWyfOticsICd6J10sIFsnzrcnLCAnaCddLFxuICAgIFsnzrgnLCAndGgnXSwgWyfOuScsICdpJ10sIFsnzronLCAnayddLCBbJ867JywgJ2wnXSwgWyfOvCcsICdtJ10sIFsnzr0nLCAnbiddLCBbJ86+JywgJ3gnXSxcbiAgICBbJ86/JywgJ28nXSwgWyfPgCcsICdwJ10sIFsnz4EnLCAnciddLCBbJ8+DJywgJ3MnXSwgWyfPhCcsICd0J10sIFsnz4UnLCAndSddLCBbJ8+GJywgJ2YnXSxcbiAgICBbJ8+HJywgJ2NoJ10sIFsnz4gnLCAncHMnXSwgWyfPiScsICd3J10sXG4gICAgXG4gICAgLy8gTWF0aGVtYXRpY2FsIHN5bWJvbHMgdG8gQVNDSUkgKHZhcmlvdXMgc3R5bGVzKVxuICAgIFsn8J2SgicsICdhJ10sIFsn8J2SgycsICdiJ10sIFsn8J2ShCcsICdjJ10sIFsn8J2ShScsICdkJ10sIFsn8J2ShicsICdlJ10sIFsn8J2ShycsICdmJ10sIFsn8J2SiCcsICdnJ10sIFsn8J2SiScsICdoJ10sIFsn8J2SiicsICdpJ10sIFsn8J2SiycsICdqJ10sIFsn8J2SjCcsICdrJ10sIFsn8J2SjScsICdsJ10sIFsn8J2SjicsICdtJ10sIFsn8J2SjycsICduJ10sIFsn8J2SkCcsICdvJ10sIFsn8J2SkScsICdwJ10sIFsn8J2SkicsICdxJ10sIFsn8J2SkycsICdyJ10sIFsn8J2SlCcsICdzJ10sIFsn8J2SlScsICd0J10sIFsn8J2SlicsICd1J10sIFsn8J2SlycsICd2J10sIFsn8J2SmCcsICd3J10sIFsn8J2SmScsICd4J10sIFsn8J2SmicsICd5J10sIFsn8J2SmycsICd6J10sXG4gICAgWyfwnZCaJywgJ2EnXSwgWyfwnZCbJywgJ2InXSwgWyfwnZCcJywgJ2MnXSwgWyfwnZCdJywgJ2QnXSwgWyfwnZCeJywgJ2UnXSwgWyfwnZCfJywgJ2YnXSwgWyfwnZCgJywgJ2cnXSwgWyfwnZChJywgJ2gnXSwgWyfwnZCiJywgJ2knXSwgWyfwnZCjJywgJ2onXSwgWyfwnZCkJywgJ2snXSwgWyfwnZClJywgJ2wnXSwgWyfwnZCmJywgJ20nXSwgWyfwnZCnJywgJ24nXSwgWyfwnZCoJywgJ28nXSwgWyfwnZCpJywgJ3AnXSwgWyfwnZCqJywgJ3EnXSwgWyfwnZCrJywgJ3InXSwgWyfwnZCsJywgJ3MnXSwgWyfwnZCtJywgJ3QnXSwgWyfwnZCuJywgJ3UnXSwgWyfwnZCvJywgJ3YnXSwgWyfwnZCwJywgJ3cnXSwgWyfwnZCxJywgJ3gnXSwgWyfwnZCyJywgJ3knXSwgWyfwnZCzJywgJ3onXSxcbiAgICBcbiAgICAvLyBTcGVjaWFsIGkgdmFyaWFudHMgKFR1cmtpc2gsIGV0Yy4pXG4gICAgWyfEsScsICdpJ10sIFsnxLAnLCAnSSddLCBbJ9GWJywgJ2knXSwgWyfTgCcsICdJJ10sXG4gICAgXG4gICAgLy8gT3RoZXIgY29tbW9uIGNvbmZ1c2FibGVzXG4gICAgWyfHnScsICdlJ10sIFsnyZAnLCAnYSddLCBbJ8mUJywgJ28nXSwgWyfKhycsICd0J10sIFsnyownLCAndiddLCBbJ8qNJywgJ3cnXSxcbiAgICBbJ+KEgycsICdDJ10sIFsn4oSJJywgJ0YnXSwgWyfihJYnLCAnTm8nXSwgWyfihKInLCAnVE0nXSwgWyfCricsICdSJ10sXG4gICAgXG4gICAgLy8gRnVsbHdpZHRoIGNoYXJhY3RlcnNcbiAgICBbJ++8oScsICdBJ10sIFsn77yiJywgJ0InXSwgWyfvvKMnLCAnQyddLCBbJ++8pCcsICdEJ10sIFsn77ylJywgJ0UnXSwgWyfvvKYnLCAnRiddLCBbJ++8pycsICdHJ10sIFsn77yoJywgJ0gnXSwgWyfvvKknLCAnSSddLCBbJ++8qicsICdKJ10sIFsn77yrJywgJ0snXSwgWyfvvKwnLCAnTCddLCBbJ++8rScsICdNJ10sIFsn77yuJywgJ04nXSwgWyfvvK8nLCAnTyddLCBbJ++8sCcsICdQJ10sIFsn77yxJywgJ1EnXSwgWyfvvLInLCAnUiddLCBbJ++8sycsICdTJ10sIFsn77y0JywgJ1QnXSwgWyfvvLUnLCAnVSddLCBbJ++8ticsICdWJ10sIFsn77y3JywgJ1cnXSwgWyfvvLgnLCAnWCddLCBbJ++8uScsICdZJ10sIFsn77y6JywgJ1onXSxcbiAgICBbJ++9gScsICdhJ10sIFsn772CJywgJ2InXSwgWyfvvYMnLCAnYyddLCBbJ++9hCcsICdkJ10sIFsn772FJywgJ2UnXSwgWyfvvYYnLCAnZiddLCBbJ++9hycsICdnJ10sIFsn772IJywgJ2gnXSwgWyfvvYknLCAnaSddLCBbJ++9iicsICdqJ10sIFsn772LJywgJ2snXSwgWyfvvYwnLCAnbCddLCBbJ++9jScsICdtJ10sIFsn772OJywgJ24nXSwgWyfvvY8nLCAnbyddLCBbJ++9kCcsICdwJ10sIFsn772RJywgJ3EnXSwgWyfvvZInLCAnciddLCBbJ++9kycsICdzJ10sIFsn772UJywgJ3QnXSwgWyfvvZUnLCAndSddLCBbJ++9licsICd2J10sIFsn772XJywgJ3cnXSwgWyfvvZgnLCAneCddLCBbJ++9mScsICd5J10sIFsn772aJywgJ3onXSxcbiAgICBbJ++8kCcsICcwJ10sIFsn77yRJywgJzEnXSwgWyfvvJInLCAnMiddLCBbJ++8kycsICczJ10sIFsn77yUJywgJzQnXSwgWyfvvJUnLCAnNSddLCBbJ++8licsICc2J10sIFsn77yXJywgJzcnXSwgWyfvvJgnLCAnOCddLCBbJ++8mScsICc5J10sXG4gIF0pO1xuXG4gIC8qKlxuICAgKiBTY3JpcHQgbWl4aW5nIGRldGVjdGlvbiBwYXR0ZXJuc1xuICAgKiBEZXRlY3RzIHN1c3BpY2lvdXMgbWl4aW5nIG9mIGRpZmZlcmVudCBVbmljb2RlIHNjcmlwdHNcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IFNDUklQVF9QQVRURVJOUyA9IHtcbiAgICBMQVRJTjogL1tcXHUwMDAwLVxcdTAwN0ZcXHUwMEEwLVxcdTAwRkZcXHUwMTAwLVxcdTAxN0ZcXHUwMTgwLVxcdTAyNEZdLyxcbiAgICBDWVJJTExJQzogL1tcXHUwNDAwLVxcdTA0RkZcXHUwNTAwLVxcdTA1MkZcXHUyREUwLVxcdTJERkZcXHVBNjQwLVxcdUE2OUZdLyxcbiAgICBHUkVFSzogL1tcXHUwMzcwLVxcdTAzRkZcXHUxRjAwLVxcdTFGRkZdLyxcbiAgICBBUkFCSUM6IC9bXFx1MDYwMC1cXHUwNkZGXFx1MDc1MC1cXHUwNzdGXFx1MDhBMC1cXHUwOEZGXFx1RkI1MC1cXHVGREZGXFx1RkU3MC1cXHVGRUZGXS8sXG4gICAgSEVCUkVXOiAvW1xcdTA1OTAtXFx1MDVGRlxcdUZCMUQtXFx1RkI0Rl0vLFxuICAgIENKSzogL1tcXHUyRTgwLVxcdTJFRkZcXHUyRjAwLVxcdTJGREZcXHUzMDAwLVxcdTMwM0ZcXHUzMDQwLVxcdTMwOUZcXHUzMEEwLVxcdTMwRkZcXHUzMTAwLVxcdTMxMkZcXHUzMTMwLVxcdTMxOEZcXHUzMTkwLVxcdTMxOUZcXHUzMUEwLVxcdTMxQkZcXHUzMUMwLVxcdTMxRUZcXHUzMUYwLVxcdTMxRkZcXHUzMjAwLVxcdTMyRkZcXHUzMzAwLVxcdTMzRkZcXHUzNDAwLVxcdTREQkZcXHU0REMwLVxcdTRERkZcXHU0RTAwLVxcdTlGRkZdLyxcbiAgfTtcblxuICAvKipcbiAgICogTm9ybWFsaXplIFVuaWNvZGUgY29udGVudCB0byBwcmV2ZW50IGJ5cGFzcyBhdHRhY2tzXG4gICAqL1xuICBzdGF0aWMgbm9ybWFsaXplKGNvbnRlbnQ6IHN0cmluZyk6IFVuaWNvZGVWYWxpZGF0aW9uUmVzdWx0IHtcbiAgICBjb25zdCBpc3N1ZXM6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IG5vcm1hbGl6ZWQgPSBjb250ZW50O1xuICAgIGxldCBzZXZlcml0eTogJ2xvdycgfCAnbWVkaXVtJyB8ICdoaWdoJyB8ICdjcml0aWNhbCcgPSAnbG93JztcblxuICAgIHRyeSB7XG4gICAgICAvLyAxLiBEZXRlY3QgYW5kIGxvZyBzdXNwaWNpb3VzIFVuaWNvZGUgcGF0dGVybnMgYmVmb3JlIG5vcm1hbGl6YXRpb25cbiAgICAgIGNvbnN0IHN1c3BpY2lvdXNQYXR0ZXJucyA9IHRoaXMuZGV0ZWN0U3VzcGljaW91c1BhdHRlcm5zKGNvbnRlbnQpO1xuICAgICAgaXNzdWVzLnB1c2goLi4uc3VzcGljaW91c1BhdHRlcm5zLmlzc3Vlcyk7XG4gICAgICBpZiAoc3VzcGljaW91c1BhdHRlcm5zLnNldmVyaXR5KSB7XG4gICAgICAgIHNldmVyaXR5ID0gdGhpcy5lc2NhbGF0ZVNldmVyaXR5KHNldmVyaXR5LCBzdXNwaWNpb3VzUGF0dGVybnMuc2V2ZXJpdHkpO1xuICAgICAgfVxuXG4gICAgICAvLyAyLiBSZW1vdmUgZGlyZWN0aW9uIG92ZXJyaWRlIGNoYXJhY3RlcnMgKHByZXZlbnRzIFJMTy9MUk8gYXR0YWNrcylcbiAgICAgIGlmICh0aGlzLkRJUkVDVElPTl9PVkVSUklERV9DSEFSUy50ZXN0KG5vcm1hbGl6ZWQpKSB7XG4gICAgICAgIGlzc3Vlcy5wdXNoKCdEaXJlY3Rpb24gb3ZlcnJpZGUgY2hhcmFjdGVycyBkZXRlY3RlZCcpO1xuICAgICAgICBzZXZlcml0eSA9IHRoaXMuZXNjYWxhdGVTZXZlcml0eShzZXZlcml0eSwgJ2hpZ2gnKTtcbiAgICAgICAgbm9ybWFsaXplZCA9IG5vcm1hbGl6ZWQucmVwbGFjZSh0aGlzLkRJUkVDVElPTl9PVkVSUklERV9DSEFSUywgJycpO1xuICAgICAgICBcbiAgICAgICAgU2VjdXJpdHlNb25pdG9yLmxvZ1NlY3VyaXR5RXZlbnQoe1xuICAgICAgICAgIHR5cGU6ICdVTklDT0RFX0RJUkVDVElPTl9PVkVSUklERScsXG4gICAgICAgICAgc2V2ZXJpdHk6ICdISUdIJyxcbiAgICAgICAgICBzb3VyY2U6ICd1bmljb2RlX3ZhbGlkYXRpb24nLFxuICAgICAgICAgIGRldGFpbHM6ICdEaXJlY3Rpb24gb3ZlcnJpZGUgY2hhcmFjdGVycyByZW1vdmVkIGZyb20gY29udGVudCdcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIDMuIFJlbW92ZSB6ZXJvLXdpZHRoIGFuZCBub24tcHJpbnRhYmxlIGNoYXJhY3RlcnNcbiAgICAgIGlmICh0aGlzLlpFUk9fV0lEVEhfQ0hBUlMudGVzdChub3JtYWxpemVkKSB8fCB0aGlzLk5PTl9QUklOVEFCTEVfQ0hBUlMudGVzdChub3JtYWxpemVkKSkge1xuICAgICAgICBpc3N1ZXMucHVzaCgnWmVyby13aWR0aCBvciBub24tcHJpbnRhYmxlIGNoYXJhY3RlcnMgZGV0ZWN0ZWQnKTtcbiAgICAgICAgc2V2ZXJpdHkgPSB0aGlzLmVzY2FsYXRlU2V2ZXJpdHkoc2V2ZXJpdHksICdtZWRpdW0nKTtcbiAgICAgICAgbm9ybWFsaXplZCA9IG5vcm1hbGl6ZWRcbiAgICAgICAgICAucmVwbGFjZSh0aGlzLlpFUk9fV0lEVEhfQ0hBUlMsICcnKVxuICAgICAgICAgIC5yZXBsYWNlKHRoaXMuTk9OX1BSSU5UQUJMRV9DSEFSUywgJycpO1xuICAgICAgfVxuXG4gICAgICAvLyA0LiBBcHBseSBVbmljb2RlIG5vcm1hbGl6YXRpb24gKE5GQyAtIENhbm9uaWNhbCBEZWNvbXBvc2l0aW9uICsgQ29tcG9zaXRpb24pXG4gICAgICBub3JtYWxpemVkID0gbm9ybWFsaXplZC5ub3JtYWxpemUoJ05GQycpO1xuXG4gICAgICAvLyA1LiBEZXRlY3QgbWl4ZWQgc2NyaXB0IGF0dGFja3MgQkVGT1JFIGNvbmZ1c2FibGUgcmVwbGFjZW1lbnRcbiAgICAgIGNvbnN0IG1peGVkU2NyaXB0UmVzdWx0ID0gdGhpcy5kZXRlY3RNaXhlZFNjcmlwdHMobm9ybWFsaXplZCk7XG4gICAgICBpZiAobWl4ZWRTY3JpcHRSZXN1bHQuaXNTdXNwaWNpb3VzKSB7XG4gICAgICAgIGlzc3Vlcy5wdXNoKGBNaXhlZCBzY3JpcHQgdXNhZ2UgZGV0ZWN0ZWQ6ICR7bWl4ZWRTY3JpcHRSZXN1bHQuc2NyaXB0cy5qb2luKCcsICcpfWApO1xuICAgICAgICBzZXZlcml0eSA9IHRoaXMuZXNjYWxhdGVTZXZlcml0eShzZXZlcml0eSwgJ2hpZ2gnKTtcbiAgICAgICAgXG4gICAgICAgIFNlY3VyaXR5TW9uaXRvci5sb2dTZWN1cml0eUV2ZW50KHtcbiAgICAgICAgICB0eXBlOiAnVU5JQ09ERV9NSVhFRF9TQ1JJUFQnLFxuICAgICAgICAgIHNldmVyaXR5OiAnSElHSCcsXG4gICAgICAgICAgc291cmNlOiAndW5pY29kZV92YWxpZGF0aW9uJyxcbiAgICAgICAgICBkZXRhaWxzOiBgTWl4ZWQgc2NyaXB0cyBkZXRlY3RlZDogJHttaXhlZFNjcmlwdFJlc3VsdC5zY3JpcHRzLmpvaW4oJywgJyl9YFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgLy8gNi4gQWx3YXlzIHJlcGxhY2UgY29uZnVzYWJsZSBjaGFyYWN0ZXJzIHdpdGggQVNDSUkgZXF1aXZhbGVudHMgZm9yIHNlY3VyaXR5XG4gICAgICAvLyBUaGlzIHByZXZlbnRzIGhvbW9ncmFwaCBhdHRhY2tzIHJlZ2FyZGxlc3Mgb2Ygc2NyaXB0IG1peGluZ1xuICAgICAgY29uc3QgY29uZnVzYWJsZVJlc3VsdCA9IHRoaXMucmVwbGFjZUNvbmZ1c2FibGVzKG5vcm1hbGl6ZWQpO1xuICAgICAgaWYgKGNvbmZ1c2FibGVSZXN1bHQuaGFzQ29uZnVzYWJsZXMpIHtcbiAgICAgICAgbm9ybWFsaXplZCA9IGNvbmZ1c2FibGVSZXN1bHQubm9ybWFsaXplZDtcbiAgICAgICAgaXNzdWVzLnB1c2goJ0NvbmZ1c2FibGUgVW5pY29kZSBjaGFyYWN0ZXJzIGRldGVjdGVkIGFuZCBub3JtYWxpemVkJyk7XG4gICAgICAgIHNldmVyaXR5ID0gdGhpcy5lc2NhbGF0ZVNldmVyaXR5KHNldmVyaXR5LCAnbWVkaXVtJyk7XG4gICAgICAgIFxuICAgICAgICAvLyBMb2cgaWYgdGhpcyBoYXBwZW5zIGluIGxlZ2l0aW1hdGUgbXVsdGlsaW5ndWFsIGNvbnRleHRcbiAgICAgICAgaWYgKCFtaXhlZFNjcmlwdFJlc3VsdC5pc1N1c3BpY2lvdXMpIHtcbiAgICAgICAgICBTZWN1cml0eU1vbml0b3IubG9nU2VjdXJpdHlFdmVudCh7XG4gICAgICAgICAgICB0eXBlOiAnVU5JQ09ERV9WQUxJREFUSU9OX0VSUk9SJyxcbiAgICAgICAgICAgIHNldmVyaXR5OiAnTE9XJyxcbiAgICAgICAgICAgIHNvdXJjZTogJ3VuaWNvZGVfdmFsaWRhdGlvbicsXG4gICAgICAgICAgICBkZXRhaWxzOiAnQ29uZnVzYWJsZSBjaGFyYWN0ZXJzIG5vcm1hbGl6ZWQgaW4gbGVnaXRpbWF0ZSBtdWx0aWxpbmd1YWwgY29udGVudCdcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBpc1ZhbGlkOiBpc3N1ZXMubGVuZ3RoID09PSAwLFxuICAgICAgICBub3JtYWxpemVkQ29udGVudDogbm9ybWFsaXplZCxcbiAgICAgICAgZGV0ZWN0ZWRJc3N1ZXM6IGlzc3Vlcy5sZW5ndGggPiAwID8gaXNzdWVzIDogdW5kZWZpbmVkLFxuICAgICAgICBzZXZlcml0eTogaXNzdWVzLmxlbmd0aCA+IDAgPyBzZXZlcml0eSA6IHVuZGVmaW5lZFxuICAgICAgfTtcblxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBTZWN1cml0eU1vbml0b3IubG9nU2VjdXJpdHlFdmVudCh7XG4gICAgICAgIHR5cGU6ICdVTklDT0RFX1ZBTElEQVRJT05fRVJST1InLFxuICAgICAgICBzZXZlcml0eTogJ0hJR0gnLFxuICAgICAgICBzb3VyY2U6ICd1bmljb2RlX3ZhbGlkYXRpb24nLFxuICAgICAgICBkZXRhaWxzOiBgVW5pY29kZSB2YWxpZGF0aW9uIGZhaWxlZDogJHtlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcil9YFxuICAgICAgfSk7XG5cbiAgICAgIC8vIEZhbGxiYWNrOiByZXR1cm4gb3JpZ2luYWwgY29udGVudCBpZiBub3JtYWxpemF0aW9uIGZhaWxzXG4gICAgICByZXR1cm4ge1xuICAgICAgICBpc1ZhbGlkOiBmYWxzZSxcbiAgICAgICAgbm9ybWFsaXplZENvbnRlbnQ6IGNvbnRlbnQsXG4gICAgICAgIGRldGVjdGVkSXNzdWVzOiBbJ1VuaWNvZGUgdmFsaWRhdGlvbiBmYWlsZWQnXSxcbiAgICAgICAgc2V2ZXJpdHk6ICdoaWdoJ1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGV0ZWN0IHN1c3BpY2lvdXMgVW5pY29kZSBwYXR0ZXJucyB0aGF0IG1pZ2h0IGluZGljYXRlIGF0dGFja3NcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGRldGVjdFN1c3BpY2lvdXNQYXR0ZXJucyhjb250ZW50OiBzdHJpbmcpOiB7IGlzc3Vlczogc3RyaW5nW107IHNldmVyaXR5PzogJ2xvdycgfCAnbWVkaXVtJyB8ICdoaWdoJyB8ICdjcml0aWNhbCcgfSB7XG4gICAgY29uc3QgaXNzdWVzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGxldCBzZXZlcml0eTogJ2xvdycgfCAnbWVkaXVtJyB8ICdoaWdoJyB8ICdjcml0aWNhbCcgfCB1bmRlZmluZWQ7XG5cbiAgICAvLyBDaGVjayBmb3IgZXhjZXNzaXZlIFVuaWNvZGUgZXNjYXBlcyAocG9zc2libGUgZW5jb2RpbmcgYnlwYXNzKVxuICAgIC8qKlxuICAgICAqIFBhdHRlcm4gdG8gbWF0Y2ggVW5pY29kZSBlc2NhcGUgc2VxdWVuY2VzXG4gICAgICogXFxcXHU6IExpdGVyYWwgYmFja3NsYXNoIGZvbGxvd2VkIGJ5ICd1J1xuICAgICAqIFswLTlhLWZBLUZdezR9OiBFeGFjdGx5IDQgaGV4YWRlY2ltYWwgZGlnaXRzXG4gICAgICogVXNlZCB0byBkZXRlY3QgYXR0ZW1wdHMgdG8gYnlwYXNzIGZpbHRlcnMgdXNpbmcgXFx1MDA2MWRtaW4gc3R5bGUgZW5jb2RpbmdcbiAgICAgKi9cbiAgICBjb25zdCB1bmljb2RlRXNjYXBlUGF0dGVybiA9IC9cXFxcdVswLTlhLWZBLUZdezR9L2c7XG4gICAgY29uc3QgdW5pY29kZUVzY2FwZXMgPSBjb250ZW50Lm1hdGNoKHVuaWNvZGVFc2NhcGVQYXR0ZXJuKTtcbiAgICBpZiAodW5pY29kZUVzY2FwZXMgJiYgdW5pY29kZUVzY2FwZXMubGVuZ3RoID4gMTApIHtcbiAgICAgIGlzc3Vlcy5wdXNoKGBFeGNlc3NpdmUgVW5pY29kZSBlc2NhcGVzIGRldGVjdGVkICgke3VuaWNvZGVFc2NhcGVzLmxlbmd0aH0pYCk7XG4gICAgICBzZXZlcml0eSA9ICdoaWdoJztcbiAgICB9XG5cbiAgICAvLyBDaGVjayBmb3Igc3VzcGljaW91cyBVbmljb2RlIHJhbmdlcyB0aGF0IG1pZ2h0IGhpZGUgY29udGVudFxuICAgIGNvbnN0IHN1c3BpY2lvdXNSYW5nZXMgPSBbXG4gICAgICB7IHJhbmdlOiAvW1xcdUUwMDAtXFx1RjhGRl0vZywgbmFtZTogJ1ByaXZhdGUgVXNlIEFyZWEnIH0sXG4gICAgICAvLyBOb3RlOiBQcm9wZXJseSBwYWlyZWQgc3Vycm9nYXRlIHBhaXJzIFtcXHVEODAwLVxcdURGRkZdIGFyZSBub3JtYWwgZm9yIGVtb2ppc1xuICAgICAgeyByYW5nZTogL1tcXHVGREQwLVxcdUZERUZdL2csIG5hbWU6ICdOb24tY2hhcmFjdGVycycgfSxcbiAgICAgIHsgcmFuZ2U6IC9bXFx1RkZGRVxcdUZGRkZdL2csIG5hbWU6ICdOb24tY2hhcmFjdGVycycgfVxuICAgIF07XG5cbiAgICBmb3IgKGNvbnN0IHsgcmFuZ2UsIG5hbWUgfSBvZiBzdXNwaWNpb3VzUmFuZ2VzKSB7XG4gICAgICBpZiAocmFuZ2UudGVzdChjb250ZW50KSkge1xuICAgICAgICBpc3N1ZXMucHVzaChgU3VzcGljaW91cyBVbmljb2RlIHJhbmdlIGRldGVjdGVkOiAke25hbWV9YCk7XG4gICAgICAgIHNldmVyaXR5ID0gdGhpcy5lc2NhbGF0ZVNldmVyaXR5KHNldmVyaXR5LCAnbWVkaXVtJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIG1hbGZvcm1lZCBzdXJyb2dhdGUgcGFpcnMgdXNpbmcgc2FmZSBjaGFyYWN0ZXItYnktY2hhcmFjdGVyIHZhbGlkYXRpb25cbiAgICAvLyBUaGlzIGF2b2lkcyBSZURvUyB2dWxuZXJhYmlsaXRpZXMgZnJvbSBjb21wbGV4IHJlZ2V4IHBhdHRlcm5zXG4gICAgaWYgKHRoaXMuaGFzTWFsZm9ybWVkU3Vycm9nYXRlcyhjb250ZW50KSkge1xuICAgICAgaXNzdWVzLnB1c2goJ01hbGZvcm1lZCBzdXJyb2dhdGUgcGFpcnMgZGV0ZWN0ZWQnKTtcbiAgICAgIHNldmVyaXR5ID0gdGhpcy5lc2NhbGF0ZVNldmVyaXR5KHNldmVyaXR5LCAnaGlnaCcpO1xuICAgIH1cblxuICAgIHJldHVybiB7IGlzc3Vlcywgc2V2ZXJpdHkgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBsYWNlIGNvbmZ1c2FibGUgVW5pY29kZSBjaGFyYWN0ZXJzIHdpdGggQVNDSUkgZXF1aXZhbGVudHNcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHJlcGxhY2VDb25mdXNhYmxlcyhjb250ZW50OiBzdHJpbmcpOiB7IG5vcm1hbGl6ZWQ6IHN0cmluZzsgaGFzQ29uZnVzYWJsZXM6IGJvb2xlYW4gfSB7XG4gICAgbGV0IG5vcm1hbGl6ZWQgPSBjb250ZW50O1xuICAgIGxldCBoYXNDb25mdXNhYmxlcyA9IGZhbHNlO1xuXG4gICAgZm9yIChjb25zdCBbY29uZnVzYWJsZSwgcmVwbGFjZW1lbnRdIG9mIHRoaXMuQ09ORlVTQUJMRV9NQVBQSU5HUykge1xuICAgICAgaWYgKG5vcm1hbGl6ZWQuaW5jbHVkZXMoY29uZnVzYWJsZSkpIHtcbiAgICAgICAgbm9ybWFsaXplZCA9IG5vcm1hbGl6ZWQucmVwbGFjZShuZXcgUmVnRXhwKHRoaXMuZXNjYXBlUmVnZXgoY29uZnVzYWJsZSksICdnJyksIHJlcGxhY2VtZW50KTtcbiAgICAgICAgaGFzQ29uZnVzYWJsZXMgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7IG5vcm1hbGl6ZWQsIGhhc0NvbmZ1c2FibGVzIH07XG4gIH1cblxuICAvKipcbiAgICogRGV0ZWN0IHN1c3BpY2lvdXMgbWl4aW5nIG9mIGRpZmZlcmVudCBVbmljb2RlIHNjcmlwdHNcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGRldGVjdE1peGVkU2NyaXB0cyhjb250ZW50OiBzdHJpbmcpOiB7IGlzU3VzcGljaW91czogYm9vbGVhbjsgc