UNPKG

gst-atom-xcuitest-driver

Version:

ATOM driver for iOS using XCUITest for backend

377 lines (319 loc) 43.7 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.commands = void 0; require("source-map-support/register"); var _lodash = _interopRequireDefault(require("lodash")); var _appiumSupport = require("appium-support"); var _gstAtomIosDriver = require("gst-atom-ios-driver"); var _asyncbox = require("asyncbox"); var _bluebird = _interopRequireDefault(require("bluebird")); var _logger = _interopRequireDefault(require("../logger")); var _os = _interopRequireDefault(require("os")); var _path = _interopRequireDefault(require("path")); var _http = _interopRequireDefault(require("http")); var _teen_process = require("teen_process"); var _portscanner = require("portscanner"); let extensions = {}, commands = {}; exports.commands = commands; const CONFIG_EXTENSION = 'mobileconfig'; const HOST_PORT_RANGE = [38200, 38299]; const TMPSERVER_STARTUP_TIMEOUT = 5000; const Settings = { General: { type: 'accessibility id', value: 'General' }, Profile: { type: '-ios predicate string', value: `name BEGINSWITH 'Profile'` }, About: { type: 'accessibility id', value: 'About' }, Certificate_Trust_Settings: { type: 'accessibility id', value: 'Certificate Trust Settings' } }; const Button = { Install: { type: 'accessibility id', value: 'Install' }, Allow: { type: 'accessibility id', value: 'Allow' }, Done: { type: 'accessibility id', value: 'Done' }, Return_to_Settings: { type: 'accessibility id', value: 'Return to Settings' } }; const Alert = { Install: { type: '-ios class chain', value: '**/XCUIElementTypeAny[`type == \'XCUIElementTypeAlert\' OR type == \'XCUIElementTypeSheet\'`]/**/XCUIElementTypeButton[`label == \'Install\'`]' } }; async function extractCommonName(certBuffer) { const tempCert = await _appiumSupport.tempDir.open({ prefix: 'cert', suffix: '.cer' }); try { await _appiumSupport.fs.writeFile(tempCert.path, certBuffer); const { stdout } = await (0, _teen_process.exec)('openssl', ['x509', '-noout', '-subject', '-in', tempCert.path]); const cnMatch = /\/CN=([^\/]+)/.exec(stdout); if (cnMatch) { return cnMatch[1].trim(); } throw new Error(`There is no common name value in '${stdout}' output`); } catch (err) { throw new Error(`Cannot parse common name value from the certificate. Is it valid and base64-encoded? ` + `Original error: ${err.message}`); } finally { await _appiumSupport.fs.rimraf(tempCert.path); } } function toMobileConfig(certBuffer, commonName) { const getUUID = () => _appiumSupport.util.uuidV4().toUpperCase(); const contentUuid = getUUID(); return { PayloadContent: [{ PayloadCertificateFileName: `${commonName}.cer`, PayloadContent: certBuffer, PayloadDescription: 'Adds a CA root certificate', PayloadDisplayName: commonName, PayloadIdentifier: `com.apple.security.root.${contentUuid}`, PayloadType: 'com.apple.security.root', PayloadUUID: contentUuid, PayloadVersion: 1 }], PayloadDisplayName: commonName, PayloadIdentifier: `${_os.default.hostname().split('.')[0]}.${getUUID()}`, PayloadRemovalDisallowed: false, PayloadType: 'Configuration', PayloadUUID: getUUID(), PayloadVersion: 1 }; } async function clickElement(driver, locator, options = {}) { let element = null; const { timeout = 5000, skipIfInvisible = false } = options; const lookupDelay = 500; try { element = await (0, _asyncbox.retryInterval)(timeout < lookupDelay ? 1 : timeout / lookupDelay, lookupDelay, () => driver.findNativeElementOrElements(locator.type, locator.value, false)); } catch (err) { if (skipIfInvisible) { return false; } throw new Error(`Cannot find ${JSON.stringify(locator)} within ${timeout}ms timeout`); } await driver.nativeClick(element); return true; } async function installPre122Certificate(driver) { await clickElement(driver, Button.Allow, { timeout: 15000 }); await _bluebird.default.delay(2000); if (!(await clickElement(driver, Button.Install, { skipIfInvisible: true }))) { return false; } await _bluebird.default.delay(1500); await clickElement(driver, Button.Install); await clickElement(driver, Alert.Install); await clickElement(driver, Button.Done); return true; } async function trustCertificateInPreferences(driver, name) { await clickElement(driver, Settings.General); await clickElement(driver, Settings.About); const switchLocator = { type: '-ios class chain', value: `**/XCUIElementTypeCell[\`label == '${name}'\`]/**/XCUIElementTypeSwitch` }; await (0, _asyncbox.retry)(5, async () => { await driver.mobileSwipe({ element: await driver.findNativeElementOrElements('class name', 'XCUIElementTypeTable', false), direction: 'up' }); await clickElement(driver, Settings.Certificate_Trust_Settings, { timeout: 500 }); await driver.findNativeElementOrElements(switchLocator.type, switchLocator.value, false); }); if (await clickElement(driver, { type: switchLocator.type, value: `${switchLocator.value}[\`value == '0'\`]` }, { timeout: 1000, skipIfInvisible: true })) { await driver.postAcceptAlert(); } } async function installPost122Certificate(driver, name) { await clickElement(driver, Button.Allow, { timeout: 15000 }); await _bluebird.default.delay(2000); await driver.postAcceptAlert(); await driver.activateApp('com.apple.Preferences'); await clickElement(driver, Settings.General); await clickElement(driver, Settings.Profile); let isCertFound = false; for (let swipeNum = 0; swipeNum < 5; ++swipeNum) { if (await clickElement(driver, { type: '-ios class chain', value: `**/XCUIElementTypeCell[\`label == '${name}'\`]` }, { timeout: 500, skipIfInvisible: true })) { isCertFound = true; break; } await driver.mobileSwipe({ element: await driver.findNativeElementOrElements('class name', 'XCUIElementTypeTable', false), direction: 'up' }); } if (!isCertFound) { throw new Error(`'${name}' cannot be found in the certificates list`); } if (!(await clickElement(driver, Button.Install, { skipIfInvisible: true }))) { return false; } await _bluebird.default.delay(1500); await clickElement(driver, Button.Install); await clickElement(driver, Alert.Install); await clickElement(driver, Button.Done); return true; } commands.mobileInstallCertificate = async function mobileInstallCertificate(opts = {}) { const { content, commonName, isRoot = true } = opts; if (_lodash.default.isEmpty(content)) { throw new Error('Certificate content should not be empty'); } if (this.isSimulator()) { try { const methodName = isRoot ? 'addRootCertificate' : 'addCertificate'; return void (await this.opts.device.simctl[methodName](content, { raw: true })); } catch (e) { _logger.default.debug(e); _logger.default.info(`The certificate cannot be installed via CLI. ` + `Falling back to UI-based deployment`); } } const tmpRoot = await _appiumSupport.tempDir.openDir(); const tmpPort = await (0, _portscanner.findAPortNotInUse)(HOST_PORT_RANGE[0], HOST_PORT_RANGE[1]); const configName = `appium.${CONFIG_EXTENSION}`; const configPath = _path.default.resolve(tmpRoot, configName); const tmpServer = _http.default.createServer(async function (_, res) { const configFile = await _appiumSupport.fs.readFile(configPath); res.end(configFile); }); try { const certBuffer = Buffer.from(content, 'base64'); const cn = commonName || (await extractCommonName(certBuffer)); const mobileConfig = toMobileConfig(certBuffer, cn); try { await _appiumSupport.plist.updatePlistFile(configPath, mobileConfig, false, false); } catch (err) { throw new Error(`Cannot store the generated config as '${configPath}'. ` + `Original error: ${err.message}`); } try { const host = _os.default.hostname(); const certUrl = `http://${host}:${tmpPort}/${configName}`; await tmpServer.listen(tmpPort); try { await (0, _asyncbox.waitForCondition)(async () => { try { return (await (0, _portscanner.checkPortStatus)(tmpPort, host)) === 'open'; } catch (ign) { return false; } }, { waitMs: TMPSERVER_STARTUP_TIMEOUT, intervalMs: 300 }); _logger.default.debug(`The temporary web server is running at http://${host}:${tmpPort}`); } catch (e) { throw new Error(`The temporary web server cannot be started at http://${host}:${tmpPort}.`); } if (this.isRealDevice()) { try { await this.proxyCommand('/url', 'POST', { url: certUrl }); } catch (err) { if (this.isWebContext()) { await _gstAtomIosDriver.iosCommands.general.setUrl.call(this, certUrl); } else { throw err; } } } else { await this.opts.device.openUrl(certUrl); } let isCertAlreadyInstalled = false; if (_appiumSupport.util.compareVersions(this.opts.platformVersion, '>=', '12.2')) { if (await installPost122Certificate(this, cn)) { await clickElement(this, Settings.Profile); await trustCertificateInPreferences(this, cn); } else { isCertAlreadyInstalled = true; } } else { if (await installPre122Certificate(this)) { await clickElement(this, Button.Return_to_Settings); await trustCertificateInPreferences(this, cn); } else { isCertAlreadyInstalled = true; } } if (isCertAlreadyInstalled) { _logger.default.info(`It looks like the '${cn}' certificate has been already added to the CA root`); } } finally { if (this.opts.bundleId) { try { await this.activateApp(this.opts.bundleId); } catch (e) { _logger.default.warn(`Cannot restore the application '${this.opts.bundleId}'. Original error: ${e.message}`); } } } return (await _appiumSupport.util.toInMemoryBase64(configPath)).toString(); } finally { await tmpServer.close(); await _appiumSupport.fs.rimraf(tmpRoot); } }; Object.assign(extensions, commands); var _default = extensions; exports.default = _default;require('source-map-support').install(); //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi9jb21tYW5kcy9jZXJ0aWZpY2F0ZS5qcyJdLCJuYW1lcyI6WyJleHRlbnNpb25zIiwiY29tbWFuZHMiLCJDT05GSUdfRVhURU5TSU9OIiwiSE9TVF9QT1JUX1JBTkdFIiwiVE1QU0VSVkVSX1NUQVJUVVBfVElNRU9VVCIsIlNldHRpbmdzIiwiR2VuZXJhbCIsInR5cGUiLCJ2YWx1ZSIsIlByb2ZpbGUiLCJBYm91dCIsIkNlcnRpZmljYXRlX1RydXN0X1NldHRpbmdzIiwiQnV0dG9uIiwiSW5zdGFsbCIsIkFsbG93IiwiRG9uZSIsIlJldHVybl90b19TZXR0aW5ncyIsIkFsZXJ0IiwiZXh0cmFjdENvbW1vbk5hbWUiLCJjZXJ0QnVmZmVyIiwidGVtcENlcnQiLCJ0ZW1wRGlyIiwib3BlbiIsInByZWZpeCIsInN1ZmZpeCIsImZzIiwid3JpdGVGaWxlIiwicGF0aCIsInN0ZG91dCIsImNuTWF0Y2giLCJleGVjIiwidHJpbSIsIkVycm9yIiwiZXJyIiwibWVzc2FnZSIsInJpbXJhZiIsInRvTW9iaWxlQ29uZmlnIiwiY29tbW9uTmFtZSIsImdldFVVSUQiLCJ1dGlsIiwidXVpZFY0IiwidG9VcHBlckNhc2UiLCJjb250ZW50VXVpZCIsIlBheWxvYWRDb250ZW50IiwiUGF5bG9hZENlcnRpZmljYXRlRmlsZU5hbWUiLCJQYXlsb2FkRGVzY3JpcHRpb24iLCJQYXlsb2FkRGlzcGxheU5hbWUiLCJQYXlsb2FkSWRlbnRpZmllciIsIlBheWxvYWRUeXBlIiwiUGF5bG9hZFVVSUQiLCJQYXlsb2FkVmVyc2lvbiIsIm9zIiwiaG9zdG5hbWUiLCJzcGxpdCIsIlBheWxvYWRSZW1vdmFsRGlzYWxsb3dlZCIsImNsaWNrRWxlbWVudCIsImRyaXZlciIsImxvY2F0b3IiLCJvcHRpb25zIiwiZWxlbWVudCIsInRpbWVvdXQiLCJza2lwSWZJbnZpc2libGUiLCJsb29rdXBEZWxheSIsImZpbmROYXRpdmVFbGVtZW50T3JFbGVtZW50cyIsIkpTT04iLCJzdHJpbmdpZnkiLCJuYXRpdmVDbGljayIsImluc3RhbGxQcmUxMjJDZXJ0aWZpY2F0ZSIsIkIiLCJkZWxheSIsInRydXN0Q2VydGlmaWNhdGVJblByZWZlcmVuY2VzIiwibmFtZSIsInN3aXRjaExvY2F0b3IiLCJtb2JpbGVTd2lwZSIsImRpcmVjdGlvbiIsInBvc3RBY2NlcHRBbGVydCIsImluc3RhbGxQb3N0MTIyQ2VydGlmaWNhdGUiLCJhY3RpdmF0ZUFwcCIsImlzQ2VydEZvdW5kIiwic3dpcGVOdW0iLCJtb2JpbGVJbnN0YWxsQ2VydGlmaWNhdGUiLCJvcHRzIiwiY29udGVudCIsImlzUm9vdCIsIl8iLCJpc0VtcHR5IiwiaXNTaW11bGF0b3IiLCJtZXRob2ROYW1lIiwiZGV2aWNlIiwic2ltY3RsIiwicmF3IiwiZSIsImxvZyIsImRlYnVnIiwiaW5mbyIsInRtcFJvb3QiLCJvcGVuRGlyIiwidG1wUG9ydCIsImNvbmZpZ05hbWUiLCJjb25maWdQYXRoIiwicmVzb2x2ZSIsInRtcFNlcnZlciIsImh0dHAiLCJjcmVhdGVTZXJ2ZXIiLCJyZXMiLCJjb25maWdGaWxlIiwicmVhZEZpbGUiLCJlbmQiLCJCdWZmZXIiLCJmcm9tIiwiY24iLCJtb2JpbGVDb25maWciLCJwbGlzdCIsInVwZGF0ZVBsaXN0RmlsZSIsImhvc3QiLCJjZXJ0VXJsIiwibGlzdGVuIiwiaWduIiwid2FpdE1zIiwiaW50ZXJ2YWxNcyIsImlzUmVhbERldmljZSIsInByb3h5Q29tbWFuZCIsInVybCIsImlzV2ViQ29udGV4dCIsImlvc0NvbW1hbmRzIiwiZ2VuZXJhbCIsInNldFVybCIsImNhbGwiLCJvcGVuVXJsIiwiaXNDZXJ0QWxyZWFkeUluc3RhbGxlZCIsImNvbXBhcmVWZXJzaW9ucyIsInBsYXRmb3JtVmVyc2lvbiIsImJ1bmRsZUlkIiwid2FybiIsInRvSW5NZW1vcnlCYXNlNjQiLCJ0b1N0cmluZyIsImNsb3NlIiwiT2JqZWN0IiwiYXNzaWduIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztB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QUNGLEtBckRELFNBcURVO0FBQ1IsVUFBSSxLQUFLN0IsSUFBTCxDQUFVbUQsUUFBZCxFQUF3QjtBQUN0QixZQUFJO0FBQ0YsZ0JBQU0sS0FBS3ZELFdBQUwsQ0FBaUIsS0FBS0ksSUFBTCxDQUFVbUQsUUFBM0IsQ0FBTjtBQUNELFNBRkQsQ0FFRSxPQUFPekMsQ0FBUCxFQUFVO0FBQ1ZDLDBCQUFJeUMsSUFBSixDQUFVLG1DQUFrQyxLQUFLcEQsSUFBTCxDQUFVbUQsUUFBUyxzQkFBcUJ6QyxDQUFDLENBQUN6RCxPQUFRLEVBQTlGO0FBQ0Q7QUFDRjtBQUNGOztBQUVELFdBQU8sQ0FBQyxNQUFNSyxvQkFBSytGLGdCQUFMLENBQXNCbkMsVUFBdEIsQ0FBUCxFQUEwQ29DLFFBQTFDLEVBQVA7QUFDRCxHQTNFRCxTQTJFVTtBQUNSLFVBQU1sQyxTQUFTLENBQUNtQyxLQUFWLEVBQU47QUFDQSxVQUFNL0csa0JBQUdVLE1BQUgsQ0FBVTRELE9BQVYsQ0FBTjtBQUNEO0FBQ0YsQ0E1R0Q7O0FBOEdBMEMsTUFBTSxDQUFDQyxNQUFQLENBQWMxSSxVQUFkLEVBQTBCQyxRQUExQjtlQUVlRCxVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IGZzLCBwbGlzdCwgdGVtcERpciwgdXRpbCB9IGZyb20gJ2FwcGl1bS1zdXBwb3J0JztcbmltcG9ydCB7IGlvc0NvbW1hbmRzIH0gZnJvbSAnZ3N0LWF0b20taW9zLWRyaXZlcic7XG5pbXBvcnQgeyByZXRyeUludGVydmFsLCByZXRyeSwgd2FpdEZvckNvbmRpdGlvbiB9IGZyb20gJ2FzeW5jYm94JztcbmltcG9ydCBCIGZyb20gJ2JsdWViaXJkJztcbmltcG9ydCBsb2cgZnJvbSAnLi4vbG9nZ2VyJztcbmltcG9ydCBvcyBmcm9tICdvcyc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCBodHRwIGZyb20gJ2h0dHAnO1xuaW1wb3J0IHsgZXhlYyB9IGZyb20gJ3RlZW5fcHJvY2Vzcyc7XG5pbXBvcnQgeyBmaW5kQVBvcnROb3RJblVzZSwgY2hlY2tQb3J0U3RhdHVzIH0gZnJvbSAncG9ydHNjYW5uZXInO1xuXG5sZXQgZXh0ZW5zaW9ucyA9IHt9LCBjb21tYW5kcyA9IHt9O1xuXG5jb25zdCBDT05GSUdfRVhURU5TSU9OID0gJ21vYmlsZWNvbmZpZyc7XG5jb25zdCBIT1NUX1BPUlRfUkFOR0UgPSBbMzgyMDAsIDM4Mjk5XTtcbmNvbnN0IFRNUFNFUlZFUl9TVEFSVFVQX1RJTUVPVVQgPSA1MDAwO1xuY29uc3QgU2V0dGluZ3MgPSB7XG4gIEdlbmVyYWw6IHtcbiAgICB0eXBlOiAnYWNjZXNzaWJpbGl0eSBpZCcsXG4gICAgdmFsdWU6ICdHZW5lcmFsJyxcbiAgfSxcbiAgUHJvZmlsZToge1xuICAgIHR5cGU6ICctaW9zIHByZWRpY2F0ZSBzdHJpbmcnLFxuICAgIHZhbHVlOiBgbmFtZSBCRUdJTlNXSVRIICdQcm9maWxlJ2AsXG4gIH0sXG4gIEFib3V0OiB7XG4gICAgdHlwZTogJ2FjY2Vzc2liaWxpdHkgaWQnLFxuICAgIHZhbHVlOiAnQWJvdXQnLFxuICB9LFxuICBDZXJ0aWZpY2F0ZV9UcnVzdF9TZXR0aW5nczoge1xuICAgIHR5cGU6ICdhY2Nlc3NpYmlsaXR5IGlkJyxcbiAgICB2YWx1ZTogJ0NlcnRpZmljYXRlIFRydXN0IFNldHRpbmdzJyxcbiAgfSxcbn07XG5jb25zdCBCdXR0b24gPSB7XG4gIEluc3RhbGw6IHtcbiAgICB0eXBlOiAnYWNjZXNzaWJpbGl0eSBpZCcsXG4gICAgdmFsdWU6ICdJbnN0YWxsJyxcbiAgfSxcbiAgQWxsb3c6IHtcbiAgICB0eXBlOiAnYWNjZXNzaWJpbGl0eSBpZCcsXG4gICAgdmFsdWU6ICdBbGxvdycsXG4gIH0sXG4gIERvbmU6IHtcbiAgICB0eXBlOiAnYWNjZXNzaWJpbGl0eSBpZCcsXG4gICAgdmFsdWU6ICdEb25lJyxcbiAgfSxcbiAgUmV0dXJuX3RvX1NldHRpbmdzOiB7XG4gICAgdHlwZTogJ2FjY2Vzc2liaWxpdHkgaWQnLFxuICAgIHZhbHVlOiAnUmV0dXJuIHRvIFNldHRpbmdzJyxcbiAgfSxcbn07XG5jb25zdCBBbGVydCA9IHtcbiAgSW5zdGFsbDoge1xuICAgIHR5cGU6ICctaW9zIGNsYXNzIGNoYWluJyxcbiAgICB2YWx1ZTogJyoqL1hDVUlFbGVtZW50VHlwZUFueVtgdHlwZSA9PSBcXCdYQ1VJRWxlbWVudFR5cGVBbGVydFxcJyBPUiB0eXBlID09IFxcJ1hDVUlFbGVtZW50VHlwZVNoZWV0XFwnYF0vKiovWENVSUVsZW1lbnRUeXBlQnV0dG9uW2BsYWJlbCA9PSBcXCdJbnN0YWxsXFwnYF0nLFxuICB9LFxufTtcblxuXG5hc3luYyBmdW5jdGlvbiBleHRyYWN0Q29tbW9uTmFtZSAoY2VydEJ1ZmZlcikge1xuICBjb25zdCB0ZW1wQ2VydCA9IGF3YWl0IHRlbXBEaXIub3Blbih7XG4gICAgcHJlZml4OiAnY2VydCcsXG4gICAgc3VmZml4OiAnLmNlcidcbiAgfSk7XG4gIHRyeSB7XG4gICAgYXdhaXQgZnMud3JpdGVGaWxlKHRlbXBDZXJ0LnBhdGgsIGNlcnRCdWZmZXIpO1xuICAgIGNvbnN0IHtzdGRvdXR9ID0gYXdhaXQgZXhlYygnb3BlbnNzbCcsIFsneDUwOScsICctbm9vdXQnLCAnLXN1YmplY3QnLCAnLWluJywgdGVtcENlcnQucGF0aF0pO1xuICAgIGNvbnN0IGNuTWF0Y2ggPSAvXFwvQ049KFteXFwvXSspLy5leGVjKHN0ZG91dCk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdXNlbGVzcy1lc2NhcGVcbiAgICBpZiAoY25NYXRjaCkge1xuICAgICAgcmV0dXJuIGNuTWF0Y2hbMV0udHJpbSgpO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZXJlIGlzIG5vIGNvbW1vbiBuYW1lIHZhbHVlIGluICcke3N0ZG91dH0nIG91dHB1dGApO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBwYXJzZSBjb21tb24gbmFtZSB2YWx1ZSBmcm9tIHRoZSBjZXJ0aWZpY2F0ZS4gSXMgaXQgdmFsaWQgYW5kIGJhc2U2NC1lbmNvZGVkPyBgICtcbiAgICAgICAgICAgICAgICAgICAgYE9yaWdpbmFsIGVycm9yOiAke2Vyci5tZXNzYWdlfWApO1xuICB9IGZpbmFsbHkge1xuICAgIGF3YWl0IGZzLnJpbXJhZih0ZW1wQ2VydC5wYXRoKTtcbiAgfVxufVxuXG4vKipcbiAqIEdlbmVyYXRlcyBBcHBsZSdzIG92ZXItdGhlLWFpciBjb25maWd1cmF0aW9uIHByb2ZpbGVcbiAqIGZvciBjZXJ0aWZpY2F0ZSBkZXBsb3ltZW50IGJhc2VkIG9uIHRoZSBnaXZlbiBQRU0gY2VydGlmaWNhdGUgY29udGVudC5cbiAqIFJlYWQgaHR0cHM6Ly9kZXZlbG9wZXIuYXBwbGUuY29tL2xpYnJhcnkvY29udGVudC9kb2N1bWVudGF0aW9uL05ldHdvcmtpbmdJbnRlcm5ldC9Db25jZXB0dWFsL2lQaG9uZU9UQUNvbmZpZ3VyYXRpb24vSW50cm9kdWN0aW9uL0ludHJvZHVjdGlvbi5odG1sXG4gKiBmb3IgbW9yZSBkZXRhaWxzIG9uIHN1Y2ggcHJvZmlsZXMuXG4gKlxuICogQHBhcmFtIHtCdWZmZXJ9IGNlcnRCdWZmZXIgLSBUaGUgYWN0dWFsIGNvbnRlbnQgb2YgUEVNIGNlcnRpZmljYXRlIGVuY29kZWQgaW50byBOb2RlSlMgYnVmZmVyXG4gKiBAcGFyYW0ge3N0cmluZ30gY29tbW9uTmFtZSAtIENlcnRpZmljYXRlJ3MgY29tbW9uIG5hbWVcbiAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBlbmNvZGVkIHN0cnVjdHVyZSBvZiB0aGUgZ2l2ZW4gY2VydGlmaWNhdGUsIHdoaWNoIGlzIHJlYWR5IHRvIGJlIHBhc3NlZFxuICogYXMgYW4gYXJndW1lbnQgdG8gcGxpc3QgYnVpbGRlclxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBnaXZlbiBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUgcGFyc2VkXG4gKi9cbmZ1bmN0aW9uIHRvTW9iaWxlQ29uZmlnIChjZXJ0QnVmZmVyLCBjb21tb25OYW1lKSB7XG4gIGNvbnN0IGdldFVVSUQgPSAoKSA9PiB1dGlsLnV1aWRWNCgpLnRvVXBwZXJDYXNlKCk7XG4gIGNvbnN0IGNvbnRlbnRVdWlkID0gZ2V0VVVJRCgpO1xuICByZXR1cm4ge1xuICAgIFBheWxvYWRDb250ZW50OiBbe1xuICAgICAgUGF5bG9hZENlcnRpZmljYXRlRmlsZU5hbWU6IGAke2NvbW1vbk5hbWV9LmNlcmAsXG4gICAgICBQYXlsb2FkQ29udGVudDogY2VydEJ1ZmZlcixcbiAgICAgIFBheWxvYWREZXNjcmlwdGlvbjogJ0FkZHMgYSBDQSByb290IGNlcnRpZmljYXRlJyxcbiAgICAgIFBheWxvYWREaXNwbGF5TmFtZTogY29tbW9uTmFtZSxcbiAgICAgIFBheWxvYWRJZGVudGlmaWVyOiBgY29tLmFwcGxlLnNlY3VyaXR5LnJvb3QuJHtjb250ZW50VXVpZH1gLFxuICAgICAgUGF5bG9hZFR5cGU6ICdjb20uYXBwbGUuc2VjdXJpdHkucm9vdCcsXG4gICAgICBQYXlsb2FkVVVJRDogY29udGVudFV1aWQsXG4gICAgICBQYXlsb2FkVmVyc2lvbjogMVxuICAgIH1dLFxuICAgIFBheWxvYWREaXNwbGF5TmFtZTogY29tbW9uTmFtZSxcbiAgICBQYXlsb2FkSWRlbnRpZmllcjogYCR7b3MuaG9zdG5hbWUoKS5zcGxpdCgnLicpWzBdfS4ke2dldFVVSUQoKX1gLFxuICAgIFBheWxvYWRSZW1vdmFsRGlzYWxsb3dlZDogZmFsc2UsXG4gICAgUGF5bG9hZFR5cGU6ICdDb25maWd1cmF0aW9uJyxcbiAgICBQYXlsb2FkVVVJRDogZ2V0VVVJRCgpLFxuICAgIFBheWxvYWRWZXJzaW9uOiAxXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNsaWNrRWxlbWVudCAoZHJpdmVyLCBsb2NhdG9yLCBvcHRpb25zID0ge30pIHtcbiAgbGV0IGVsZW1lbnQgPSBudWxsO1xuICBjb25zdCB7XG4gICAgdGltZW91dCA9IDUwMDAsXG4gICAgc2tpcElmSW52aXNpYmxlID0gZmFsc2VcbiAgfSA9IG9wdGlvbnM7XG4gIGNvbnN0IGxvb2t1cERlbGF5ID0gNTAwO1xuICB0cnkge1xuICAgIGVsZW1lbnQgPSBhd2FpdCByZXRyeUludGVydmFsKHRpbWVvdXQgPCBsb29rdXBEZWxheSA/IDEgOiB0aW1lb3V0IC8gbG9va3VwRGVsYXksIGxvb2t1cERlbGF5LFxuICAgICAgKCkgPT4gZHJpdmVyLmZpbmROYXRpdmVFbGVtZW50T3JFbGVtZW50cyhsb2NhdG9yLnR5cGUsIGxvY2F0b3IudmFsdWUsIGZhbHNlKVxuICAgICk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGlmIChza2lwSWZJbnZpc2libGUpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgZmluZCAke0pTT04uc3RyaW5naWZ5KGxvY2F0b3IpfSB3aXRoaW4gJHt0aW1lb3V0fW1zIHRpbWVvdXRgKTtcbiAgfVxuICBhd2FpdCBkcml2ZXIubmF0aXZlQ2xpY2soZWxlbWVudCk7XG4gIHJldHVybiB0cnVlO1xufVxuXG5hc3luYyBmdW5jdGlvbiBpbnN0YWxsUHJlMTIyQ2VydGlmaWNhdGUgKGRyaXZlcikge1xuICAvLyBBY2NlcHQgU2FmYXJpIGFsZXJ0XG4gIGF3YWl0IGNsaWNrRWxlbWVudChkcml2ZXIsIEJ1dHRvbi5BbGxvdywge1xuICAgIC8vIGNlcnRpZmljYXRlIGxvYWQgbWlnaHQgdGFrZSBzb21lIHRpbWUgb24gc2xvdyBtYWNoaW5lc1xuICAgIHRpbWVvdXQ6IDE1MDAwLFxuICB9KTtcbiAgLy8gV2FpdCB1bnRpbCBQcmVmZXJlbmNlcyBhcmUgb3BlbmVkXG4gIGF3YWl0IEIuZGVsYXkoMjAwMCk7XG5cbiAgLy8gR28gdGhyb3VnaCBQcmVmZXJlbmNlcyB3aXphcmRcbiAgaWYgKCFhd2FpdCBjbGlja0VsZW1lbnQoZHJpdmVyLCBCdXR0b24uSW5zdGFsbCwge1xuICAgIHNraXBJZkludmlzaWJsZTogdHJ1ZSxcbiAgfSkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgLy8gV2UgbmVlZCB0byBjbGljayBJbnN0YWxsIGJ1dHRvbiBvbiB0d28gZGlmZmVyZW50IHRhYnNcbiAgLy8gVGhlIHNlY29uZCBvbmUgY29uZmlybXMgdGhlIHByZXZpb3VzXG4gIGF3YWl0IEIuZGVsYXkoMTUwMCk7XG4gIGF3YWl0IGNsaWNrRWxlbWVudChkcml2ZXIsIEJ1dHRvbi5JbnN0YWxsKTtcbiAgLy8gQWNjZXB0IGFsZXJ0XG4gIGF3YWl0IGNsaWNrRWxlbWVudChkcml2ZXIsIEFsZXJ0Lkluc3RhbGwpO1xuICAvLyBGaW5pc2ggYWRkaW5nIGNlcnRpZmljYXRlXG4gIGF3YWl0IGNsaWNrRWxlbWVudChkcml2ZXIsIEJ1dHRvbi5Eb25lKTtcbiAgcmV0dXJuIHRydWU7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHRydXN0Q2VydGlmaWNhdGVJblByZWZlcmVuY2VzIChkcml2ZXIsIG5hbWUpIHtcbiAgYXdhaXQgY2xpY2tFbGVtZW50KGRyaXZlciwgU2V0dGluZ3MuR2VuZXJhbCk7XG4gIGF3YWl0IGNsaWNrRWxlbWVudChkcml2ZXIsIFNldHRpbmdzLkFib3V0KTtcbiAgY29uc3Qgc3dpdGNoTG9jYXRvciA9IHtcbiAgICB0eXBlOiAnLWlvcyBjbGFzcyBjaGFpbicsXG4gICAgdmFsdWU6IGAqKi9YQ1VJRWxlbWVudFR5cGVDZWxsW1xcYGxhYmVsID09ICcke25hbWV9J1xcYF0vKiovWENVSUVsZW1lbnRUeXBlU3dpdGNoYCxcbiAgfTtcbiAgYXdhaXQgcmV0cnkoNSwgYXN5bmMgKCkgPT4ge1xuICAgIGF3YWl0IGRyaXZlci5tb2JpbGVTd2lwZSh7XG4gICAgICBlbGVtZW50OiBhd2FpdCBkcml2ZXIuZmluZE5hdGl2ZUVsZW1lbnRPckVsZW1lbnRzKCdjbGFzcyBuYW1lJywgJ1hDVUlFbGVtZW50VHlwZVRhYmxlJywgZmFsc2UpLFxuICAgICAgZGlyZWN0aW9uOiAndXAnXG4gICAgfSk7XG4gICAgYXdhaXQgY2xpY2tFbGVtZW50KGRyaXZlciwgU2V0dGluZ3MuQ2VydGlmaWNhdGVfVHJ1c3RfU2V0dGluZ3MsIHtcbiAgICAgIHRpbWVvdXQ6IDUwMCxcbiAgICB9KTtcblxuICAgIGF3YWl0IGRyaXZlci5maW5kTmF0aXZlRWxlbWVudE9yRWxlbWVudHMoc3dpdGNoTG9jYXRvci50eXBlLCBzd2l0Y2hMb2NhdG9yLnZhbHVlLCBmYWxzZSk7XG4gIH0pO1xuICAvLyBPbmx5IGNsaWNrIHRoZSBzd2l0Y2ggaWYgaXQgaXMgc2V0IHRvIE9mZlxuICBpZiAoYXdhaXQgY2xpY2tFbGVtZW50KGRyaXZlciwge1xuICAgIHR5cGU6IHN3aXRjaExvY2F0b3IudHlwZSxcbiAgICB2YWx1ZTogYCR7c3dpdGNoTG9jYXRvci52YWx1ZX1bXFxgdmFsdWUgPT0gJzAnXFxgXWBcbiAgfSwge1xuICAgIHRpbWVvdXQ6IDEwMDAsXG4gICAgc2tpcElmSW52aXNpYmxlOiB0cnVlLFxuICB9KSkge1xuICAgIGF3YWl0IGRyaXZlci5wb3N0QWNjZXB0QWxlcnQoKTtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBpbnN0YWxsUG9zdDEyMkNlcnRpZmljYXRlIChkcml2ZXIsIG5hbWUpIHtcbiAgLy8gQWNjZXB0IFNhZmFyaSBhbGVydFxuICBhd2FpdCBjbGlja0VsZW1lbnQoZHJpdmVyLCBCdXR0b24uQWxsb3csIHtcbiAgICAvLyBjZXJ0aWZpY2F0ZSBsb2FkIG1pZ2h0IHRha2Ugc29tZSB0aW1lIG9uIHNsb3cgbWFjaGluZXNcbiAgICB0aW1lb3V0OiAxNTAwMCxcbiAgfSk7XG4gIC8vIFdhaXQgZm9yIHRoZSBzZWNvbmQgYWxlcnRcbiAgYXdhaXQgQi5kZWxheSgyMDAwKTtcblxuICBhd2FpdCBkcml2ZXIucG9zdEFjY2VwdEFsZXJ0KCk7XG4gIGF3YWl0IGRyaXZlci5hY3RpdmF0ZUFwcCgnY29tLmFwcGxlLlByZWZlcmVuY2VzJyk7XG4gIGF3YWl0IGNsaWNrRWxlbWVudChkcml2ZXIsIFNldHRpbmdzLkdlbmVyYWwpO1xuICBhd2FpdCBjbGlja0VsZW1lbnQoZHJpdmVyLCBTZXR0aW5ncy5Qcm9maWxlKTtcbiAgLy8gU2VsZWN0IHRoZSB0YXJnZXQgY2VydFxuICBsZXQgaXNDZXJ0Rm91bmQgPSBmYWxzZTtcbiAgZm9yIChsZXQgc3dpcGVOdW0gPSAwOyBzd2lwZU51bSA8IDU7ICsrc3dpcGVOdW0pIHtcbiAgICBpZiAoYXdhaXQgY2xpY2tFbGVtZW50KGRyaXZlciwge1xuICAgICAgdHlwZTogJy1pb3MgY2xhc3MgY2hhaW4nLFxuICAgICAgdmFsdWU6IGAqKi9YQ1VJRWxlbWVudFR5cGVDZWxsW1xcYGxhYmVsID09ICcke25hbWV9J1xcYF1gLFxuICAgIH0sIHtcbiAgICAgIHRpbWVvdXQ6IDUwMCxcbiAgICAgIHNraXBJZkludmlzaWJsZTogdHJ1ZSxcbiAgICB9KSkge1xuICAgICAgaXNDZXJ0Rm91bmQgPSB0cnVlO1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgYXdhaXQgZHJpdmVyLm1vYmlsZVN3aXBlKHtcbiAgICAgIGVsZW1lbnQ6IGF3YWl0IGRyaXZlci5maW5kTmF0aXZlRWxlbWVudE9yRWxlbWVudHMoJ2NsYXNzIG5hbWUnLCAnWENVSUVsZW1lbnRUeXBlVGFibGUnLCBmYWxzZSksXG4gICAgICBkaXJlY3Rpb246ICd1cCdcbiAgICB9KTtcbiAgfVxuICBpZiAoIWlzQ2VydEZvdW5kKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAnJHtuYW1lfScgY2Fubm90IGJlIGZvdW5kIGluIHRoZSBjZXJ0aWZpY2F0ZXMgbGlzdGApO1xuICB9XG5cbiAgLy8gSW5zdGFsbCBvcHRpb24gaXMgb25seSB2aXNpYmxlIGlmIHRoZSBjZXJ0IGlzIG5vdCBpbnN0YWxsZWQgeWV0XG4gIGlmICghYXdhaXQgY2xpY2tFbGVtZW50KGRyaXZlciwgQnV0dG9uLkluc3RhbGwsIHtcbiAgICBza2lwSWZJbnZpc2libGU6IHRydWUsXG4gIH0pKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGF3YWl0IEIuZGVsYXkoMTUwMCk7XG4gIC8vIENvbmZpcm0gdW50cnVzdGVkIGNlcnQgaW5zdGFsbFxuICBhd2FpdCBjbGlja0VsZW1lbnQoZHJpdmVyLCBCdXR0b24uSW5zdGFsbCk7XG4gIC8vIEFjY2VwdCBhbGVydFxuICBhd2FpdCBjbGlja0VsZW1lbnQoZHJpdmVyLCBBbGVydC5JbnN0YWxsKTtcbiAgLy8gRmluaXNoIGFkZGluZyBjZXJ0aWZpY2F0ZVxuICBhd2FpdCBjbGlja0VsZW1lbnQoZHJpdmVyLCBCdXR0b24uRG9uZSk7XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gQ2VydGlmaWNhdGVJbnN0YWxsYXRpb25PcHRpb25zXG4gKlxuICogQHByb3BlcnR5IHshc3RyaW5nfSBjb250ZW50IC0gQmFzZTY0LWVuY29kZWQgY29udGVudCBvZiB0aGUgcHVibGljIGNlcnRpZmljYXRlXG4gKiBAcHJvcGVydHkgez9zdHJpbmd9IGNvbW1vbk5hbWUgLSBDb21tb24gbmFtZSBvZiB0aGUgY2VydGlmaWNhdGUuIElmIHRoaXMgaXMgbm90IHNldFxuICogdGhlbiB0aGUgc2NyaXB0IHdpbGwgdHJ5IHRvIHBhcnNlIGl0IGZyb20gdGhlIGdpdmVuIGNlcnRpZmljYXRlIGNvbnRlbnQuXG4gKiBAcHJvcGVydHkgez9ib29sZWFufSBpc1Jvb3QgW3RydWVdIC0gVGhpcyBvcHRpb24gZGVmaW5lcyB3aGVyZSB0aGUgY2VydGlmaWNhdGUgc2hvdWxkIGJlXG4gKiBpbnN0YWxsZWQgdG86IGVpdGhlciBUcnVzdGVkIFJvb3QgU3RvcmUgKGB0cnVlYCwgdGhlIGRlZmF1bHQgb3B0aW9uKSBvclxuICogdGhlIEtleWNoYWluIChgZmFsc2VgKS4gT24gZW52aXJvbm1lbnRzIG90aGVyIHRoYW4gWGNvZGUgMTEuNCsgU2ltdWxhdG9yIHRoaXNcbiAqIG9wdGlvbiBpcyBpZ25vcmVkLlxuICovXG5cbi8qKlxuICogSW5zdGFsbHMgYSBjdXN0b20gY2VydGlmaWNhdGUgb250byB0aGUgZGV2aWNlLlxuICogU2luY2UgWGNvZGUgU0RLIDExLjQgQXBwbGUgaGFzIGFkZGVkIGEgZGVkaWNhdGVkIHNpbWN0bCBzdWJjb21tYW5kIHRvIHF1aWNrbHkgaGFuZGxlXG4gKiBjZXJ0aWZpY2F0ZXMgb24gU2ltdWxhdG9yIG92ZXIgQ0xJLlxuICogT24gcmVhbCBkZXZpY2VzIG9yIHNpbXVsYXRvcnMgYmVmb3JlIFhjb2RlIDExLjQgU0RLXG4gKiBBcHBsZSBwcm92aWRlcyBubyBvZmZpY2lhbCB3YXkgdG8gZG8gaXQgdmlhIHRoZSBjb21tYW5kIGxpbmUuXG4gKiBJbiBzdWNoIGNhc2UgKGFuZCBhbHNvIGFzIGEgZmFsbGJhY2sgaWYgQ0xJIHNldHVwIGZhaWxzKVxuICogdGhpcyBtZXRob2QgdHJpZXMgdG8gd3JhcCB0aGUgY2VydGlmaWNhdGUgaW50byAubW9iaWxlY29uZmlnIGZvcm1hdFxuICogYW5kIHRoZW4gZGVwbG95cyB0aGUgd3JhcHBlZCBmaWxlIHRvIHRoZSBpbnRlcm5hbCBIVFRQIHNlcnZlcixcbiAqIHNvIG9uZSBjYW4gb3BlbiBpdCB2aWEgbW9iaWxlIFNhZmFyaS5cbiAqIFRoZW4gdGhlIGFsZ29yaXRobSBnb2VzIHRocm91Z2ggdGhlIHByb2ZpbGUgaW5zdGFsbGF0aW9uIHByb2NlZHVyZSBieVxuICogY2xpY2tpbmcgdGhlIG5lY2Vzc2FyeSBidXR0b25zIHVzaW5nIFdlYkRyaXZlckFnZW50LlxuICpcbiAqIEBwYXJhbSB7Q2VydGlmaWNhdGVJbnN0YWxsYXRpb25PcHRpb25zfSBvcHRzXG4gKiBAcmV0dXJucyB7P3N0cmluZ30gVGhlIGNvbnRlbnQgb2YgdGhlIGdlbmVyYXRlZCAubW9iaWxlY29uZmlnIGZpbGUgYXNcbiAqIGJhc2U2NC1lbmNvZGVkIHN0cmluZy4gVGhpcyBjb25maWcgbWlnaHQgYmUgdXNlZnVsIGZvciBkZWJ1Z2dpbmcgcHVycG9zZXMuXG4gKiBJZiB0aGUgY2VydGlmaWNhdGUgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IHNldCB2aWEgQ0xJIHRoZW4gbm90aGluZyBpcyByZXR1cm5lZC5cbiAqL1xuY29tbWFuZHMubW9iaWxlSW5zdGFsbENlcnRpZmljYXRlID0gYXN5bmMgZnVuY3Rpb24gbW9iaWxlSW5zdGFsbENlcnRpZmljYXRlIChvcHRzID0ge30pIHtcbiAgY29uc3Qge1xuICAgIGNvbnRlbnQsXG4gICAgY29tbW9uTmFtZSxcbiAgICBpc1Jvb3QgPSB0cnVlLFxuICB9ID0gb3B0cztcbiAgaWYgKF8uaXNFbXB0eShjb250ZW50KSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2VydGlmaWNhdGUgY29udGVudCBzaG91bGQgbm90IGJlIGVtcHR5Jyk7XG4gIH1cblxuICBpZiAodGhpcy5pc1NpbXVsYXRvcigpKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IG1ldGhvZE5hbWUgPSBpc1Jvb3QgPyAnYWRkUm9vdENlcnRpZmljYXRlJyA6ICdhZGRDZXJ0aWZpY2F0ZSc7XG4gICAgICByZXR1cm4gdm9pZCAoYXdhaXQgdGhpcy5vcHRzLmRldmljZS5zaW1jdGxbbWV0aG9kTmFtZV0oY29udGVudCwge3JhdzogdHJ1ZX0pKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsb2cuZGVidWcoZSk7XG4gICAgICBsb2cuaW5mbyhgVGhlIGNlcnRpZmljYXRlIGNhbm5vdCBiZSBpbnN0YWxsZWQgdmlhIENMSS4gYCArXG4gICAgICAgIGBGYWxsaW5nIGJhY2sgdG8gVUktYmFzZWQgZGVwbG95bWVudGApO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHRtcFJvb3QgPSBhd2FpdCB0ZW1wRGlyLm9wZW5EaXIoKTtcbiAgY29uc3QgdG1wUG9ydCA9IGF3YWl0IGZpbmRBUG9ydE5vdEluVXNlKEhPU1RfUE9SVF9SQU5HRVswXSwgSE9TVF9QT1JUX1JBTkdFWzFdKTtcbiAgY29uc3QgY29uZmlnTmFtZSA9IGBhcHBpdW0uJHtDT05GSUdfRVhURU5TSU9OfWA7XG4gIGNvbnN0IGNvbmZpZ1BhdGggPSBwYXRoLnJlc29sdmUodG1wUm9vdCwgY29uZmlnTmFtZSk7XG4gIGNvbnN0IHRtcFNlcnZlciA9IGh0dHAuY3JlYXRlU2VydmVyKGFzeW5jIGZ1bmN0aW9uIChfLCByZXMpIHtcbiAgICBjb25zdCBjb25maWdGaWxlID0gYXdhaXQgZnMucmVhZEZpbGUoY29uZmlnUGF0aCk7XG4gICAgcmVzLmVuZChjb25maWdGaWxlKTtcbiAgfSk7XG4gIHRyeSB7XG4gICAgY29uc3QgY2VydEJ1ZmZlciA9IEJ1ZmZlci5mcm9tKGNvbnRlbnQsICdiYXNlNjQnKTtcbiAgICBjb25zdCBjbiA9IGNvbW1vbk5hbWUgfHwgYXdhaXQgZXh0cmFjdENvbW1vbk5hbWUoY2VydEJ1ZmZlcik7XG4gICAgY29uc3QgbW9iaWxlQ29uZmlnID0gdG9Nb2JpbGVDb25maWcoY2VydEJ1ZmZlciwgY24pO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBwbGlzdC51cGRhdGVQbGlzdEZpbGUoY29uZmlnUGF0aCwgbW9iaWxlQ29uZmlnLCBmYWxzZSwgZmFsc2UpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3Qgc3RvcmUgdGhlIGdlbmVyYXRlZCBjb25maWcgYXMgJyR7Y29uZmlnUGF0aH0nLiBgICtcbiAgICAgICAgICAgICAgICAgICAgICBgT3JpZ2luYWwgZXJyb3I6ICR7ZXJyLm1lc3NhZ2V9YCk7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGhvc3QgPSBvcy5ob3N0bmFtZSgpO1xuICAgICAgY29uc3QgY2VydFVybCA9IGBodHRwOi8vJHtob3N0fToke3RtcFBvcnR9LyR7Y29uZmlnTmFtZX1gO1xuICAgICAgYXdhaXQgdG1wU2VydmVyLmxpc3Rlbih0bXBQb3J0KTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHdhaXRGb3JDb25kaXRpb24oYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gKGF3YWl0IGNoZWNrUG9ydFN0YXR1cyh0bXBQb3J0LCBob3N0KSkgPT09ICdvcGVuJztcbiAgICAgICAgICB9IGNhdGNoIChpZ24pIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sIHtcbiAgICAgICAgICB3YWl0TXM6IFRNUFNFUlZFUl9TVEFSVFVQX1RJTUVPVVQsXG4gICAgICAgICAgaW50ZXJ2YWxNczogMzAwLFxuICAgICAgICB9KTtcbiAgICAgICAgbG9nLmRlYnVnKGBUaGUgdGVtcG9yYXJ5IHdlYiBzZXJ2ZXIgaXMgcnVubmluZyBhdCBodHRwOi8vJHtob3N0fToke3RtcFBvcnR9YCk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVGhlIHRlbXBvcmFyeSB3ZWIgc2VydmVyIGNhbm5vdCBiZSBzdGFydGVkIGF0IGh0dHA6Ly8ke2hvc3R9OiR7dG1wUG9ydH0uYCk7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5pc1JlYWxEZXZpY2UoKSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHRoaXMucHJveHlDb21tYW5kKCcvdXJsJywgJ1BPU1QnLCB7dXJsOiBjZXJ0VXJsfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGlmICh0aGlzLmlzV2ViQ29udGV4dCgpKSB7XG4gICAgICAgICAgICAvLyBUaGUgY29tbWFuZCBhYm92ZSBkb2VzIG5vdCBhbHdheXMgd29yayBvbiByZWFsIGRldmljZXNcbiAgICAgICAgICAgIGF3YWl0IGlvc0NvbW1hbmRzLmdlbmVyYWwuc2V0VXJsLmNhbGwodGhpcywgY2VydFVybCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IHRoaXMub3B0cy5kZXZpY2Uub3BlblVybChjZXJ0VXJsKTtcbiAgICAgIH1cblxuICAgICAgbGV0IGlzQ2VydEFscmVhZHlJbnN0YWxsZWQgPSBmYWxzZTtcbiAgICAgIGlmICh1dGlsLmNvbXBhcmVWZXJzaW9ucyh0aGlzLm9wdHMucGxhdGZvcm1WZXJzaW9uLCAnPj0nLCAnMTIuMicpKSB7XG4gICAgICAgIGlmIChhd2FpdCBpbnN0YWxsUG9zdDEyMkNlcnRpZmljYXRlKHRoaXMsIGNuKSkge1xuICAgICAgICAgIGF3YWl0IGNsaWNrRWxlbWVudCh0aGlzLCBTZXR0aW5ncy5Qcm9maWxlKTtcbiAgICAgICAgICBhd2FpdCB0cnVzdENlcnRpZmljYXRlSW5QcmVmZXJlbmNlcyh0aGlzLCBjbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaXNDZXJ0QWxyZWFkeUluc3RhbGxlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChhd2FpdCBpbnN0YWxsUHJlMTIyQ2VydGlmaWNhdGUodGhpcykpIHtcbiAgICAgICAgICBhd2FpdCBjbGlja0VsZW1lbnQodGhpcywgQnV0dG9uLlJldHVybl90b19TZXR0aW5ncyk7XG4gICAgICAgICAgYXdhaXQgdHJ1c3RDZXJ0aWZpY2F0ZUluUHJlZmVyZW5jZXModGhpcywgY24pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlzQ2VydEFscmVhZHlJbnN0YWxsZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoaXNDZXJ0QWxyZWFkeUluc3RhbGxlZCkge1xuICAgICAgICBsb2cuaW5mbyhgSXQgbG9va3MgbGlrZSB0aGUgJyR7Y259JyBjZXJ0aWZpY2F0ZSBoYXMgYmVlbiBhbHJlYWR5IGFkZGVkIHRvIHRoZSBDQSByb290YCk7XG4gICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlmICh0aGlzLm9wdHMuYnVuZGxlSWQpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmFjdGl2YXRlQXBwKHRoaXMub3B0cy5idW5kbGVJZCk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBsb2cud2FybihgQ2Fubm90IHJlc3RvcmUgdGhlIGFwcGxpY2F0aW9uICcke3RoaXMub3B0cy5idW5kbGVJZH0nLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gKGF3YWl0IHV0aWwudG9Jbk1lbW9yeUJhc2U2NChjb25maWdQYXRoKSkudG9TdHJpbmcoKTtcbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCB0bXBTZXJ2ZXIuY2xvc2UoKTtcbiAgICBhd2FpdCBmcy5yaW1yYWYodG1wUm9vdCk7XG4gIH1cbn07XG5cbk9iamVjdC5hc3NpZ24oZXh0ZW5zaW9ucywgY29tbWFuZHMpO1xuZXhwb3J0IHsgY29tbWFuZHMgfTtcbmV4cG9ydCBkZWZhdWx0IGV4dGVuc2lvbnM7XG4iXSwiZmlsZSI6ImxpYi9jb21tYW5kcy9jZXJ0aWZpY2F0ZS5qcyIsInNvdXJjZVJvb3QiOiIuLi8uLi8uLiJ9