UNPKG

verdaccio

Version:

A lightweight private npm proxy registry

716 lines (574 loc) 65.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getUserAgent = getUserAgent; exports.convertPayloadToBase64 = convertPayloadToBase64; exports.validateName = validateName; exports.validatePackage = validatePackage; exports.isObject = isObject; exports.validateMetadata = validateMetadata; exports.combineBaseUrl = combineBaseUrl; exports.extractTarballFromUrl = extractTarballFromUrl; exports.convertDistRemoteToLocalTarballUrls = convertDistRemoteToLocalTarballUrls; exports.getLocalRegistryTarballUri = getLocalRegistryTarballUri; exports.tagVersion = tagVersion; exports.getVersion = getVersion; exports.parseAddress = parseAddress; exports.semverSort = semverSort; exports.normalizeDistTags = normalizeDistTags; exports.parseInterval = parseInterval; exports.getWebProtocol = getWebProtocol; exports.getLatestVersion = getLatestVersion; exports.parseConfigFile = parseConfigFile; exports.folderExists = folderExists; exports.fileExists = fileExists; exports.sortByName = sortByName; exports.addScope = addScope; exports.deleteProperties = deleteProperties; exports.addGravatarSupport = addGravatarSupport; exports.parseReadme = parseReadme; exports.buildToken = buildToken; exports.getVersionFromTarball = getVersionFromTarball; exports.formatAuthor = formatAuthor; exports.isHTTPProtocol = isHTTPProtocol; exports.pad = pad; exports.mask = mask; exports.encodeScopedUri = encodeScopedUri; exports.hasDiffOneKey = hasDiffOneKey; exports.isVersionValid = isVersionValid; exports.isRelatedToDeprecation = isRelatedToDeprecation; exports.ErrorCode = void 0; var _fs = _interopRequireDefault(require("fs")); var _assert = _interopRequireDefault(require("assert")); var _url = _interopRequireDefault(require("url")); var _lodash = _interopRequireDefault(require("lodash")); var _semver = _interopRequireDefault(require("semver")); var _jsYaml = _interopRequireDefault(require("js-yaml")); var _readme = _interopRequireDefault(require("@verdaccio/readme")); var _commonsApi = require("@verdaccio/commons-api"); var _user = require("../utils/user"); var _constants = require("./constants"); var _storageUtils = require("./storage-utils"); var _logger = require("./logger"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } // eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-var-requires require('pkginfo')(module); const pkgVersion = module.exports.version; const pkgName = module.exports.name; function getUserAgent() { (0, _assert.default)(_lodash.default.isString(pkgName)); (0, _assert.default)(_lodash.default.isString(pkgVersion)); return `${pkgName}/${pkgVersion}`; } function convertPayloadToBase64(payload) { return Buffer.from(payload, 'base64'); } /** * From normalize-package-data/lib/fixer.js * @param {*} name the package name * @return {Boolean} whether is valid or not */ function validateName(name) { if (_lodash.default.isString(name) === false) { return false; } const normalizedName = name.toLowerCase(); /** * Some context about the first regex * - npm used to have a different tarball naming system. * eg: http://registry.npmjs.com/thirty-two * https://registry.npmjs.org/thirty-two/-/thirty-two@0.0.1.tgz * The file name thirty-two@0.0.1.tgz, the version and the pkg name was separated by an at (@) * while nowadays the naming system is based in dashes * https://registry.npmjs.org/verdaccio/-/verdaccio-1.4.0.tgz * * more info here: https://github.com/rlidwka/sinopia/issues/75 */ return !(!normalizedName.match(/^[-a-zA-Z0-9_.!~*'()@]+$/) || normalizedName.startsWith('.') || // ".bin", etc. ['node_modules', '__proto__', 'favicon.ico'].includes(normalizedName)); } /** * Validate a package. * @return {Boolean} whether the package is valid or not */ function validatePackage(name) { const nameList = name.split('/', 2); if (nameList.length === 1) { // normal package return validateName(nameList[0]); } // scoped package return nameList[0][0] === '@' && validateName(nameList[0].slice(1)) && validateName(nameList[1]); } /** * Check whether an element is an Object * @param {*} obj the element * @return {Boolean} */ function isObject(obj) { return _lodash.default.isObject(obj) && _lodash.default.isNull(obj) === false && _lodash.default.isArray(obj) === false; } /** * Validate the package metadata, add additional properties whether are missing within * the metadata properties. * @param {*} object * @param {*} name * @return {Object} the object with additional properties as dist-tags ad versions */ function validateMetadata(object, name) { (0, _assert.default)(isObject(object), 'not a json object'); _assert.default.strictEqual(object.name, name); if (!isObject(object[_constants.DIST_TAGS])) { object[_constants.DIST_TAGS] = {}; } if (!isObject(object['versions'])) { object['versions'] = {}; } if (!isObject(object['time'])) { object['time'] = {}; } return object; } /** * Create base url for registry. * @return {String} base registry url */ function combineBaseUrl(protocol, host, prefix) { const result = `${protocol}://${host}`; const prefixOnlySlash = prefix === '/'; if (prefix && !prefixOnlySlash) { if (prefix.endsWith('/')) { prefix = prefix.slice(0, -1); } if (prefix.startsWith('/')) { return `${result}${prefix}`; } return prefix; } return result; } function extractTarballFromUrl(url) { // @ts-ignore return _url.default.parse(url).pathname.replace(/^.*\//, ''); } /** * Iterate a packages's versions and filter each original tarball url. * @param {*} pkg * @param {*} req * @param {*} config * @return {String} a filtered package */ function convertDistRemoteToLocalTarballUrls(pkg, req, urlPrefix) { for (const ver in pkg.versions) { if (Object.prototype.hasOwnProperty.call(pkg.versions, ver)) { const distName = pkg.versions[ver].dist; if (_lodash.default.isNull(distName) === false && _lodash.default.isNull(distName.tarball) === false) { distName.tarball = getLocalRegistryTarballUri(distName.tarball, pkg.name, req, urlPrefix); } } } return pkg; } /** * Filter a tarball url. * @param {*} uri * @return {String} a parsed url */ function getLocalRegistryTarballUri(uri, pkgName, req, urlPrefix) { const currentHost = req.headers.host; if (!currentHost) { return uri; } const tarballName = extractTarballFromUrl(uri); const headers = req.headers; const protocol = getWebProtocol(req.get(_constants.HEADERS.FORWARDED_PROTO), req.protocol); const domainRegistry = combineBaseUrl(protocol, headers.host, urlPrefix); return `${domainRegistry}/${encodeScopedUri(pkgName)}/-/${tarballName}`; } /** * Create a tag for a package * @param {*} data * @param {*} version * @param {*} tag * @return {Boolean} whether a package has been tagged */ function tagVersion(data, version, tag) { if (tag && data[_constants.DIST_TAGS][tag] !== version && _semver.default.parse(version, true)) { // valid version - store data[_constants.DIST_TAGS][tag] = version; return true; } return false; } /** * Gets version from a package object taking into account semver weirdness. * @return {String} return the semantic version of a package */ function getVersion(pkg, version) { // this condition must allow cast if (_lodash.default.isNil(pkg.versions[version]) === false) { return pkg.versions[version]; } try { version = _semver.default.parse(version, true); for (const versionItem in pkg.versions) { // $FlowFixMe if (version.compare(_semver.default.parse(versionItem, true)) === 0) { return pkg.versions[versionItem]; } } } catch (err) { return undefined; } } /** * Parse an internet address * Allow: - https:localhost:1234 - protocol + host + port - localhost:1234 - host + port - 1234 - port - http::1234 - protocol + port - https://localhost:443/ - full url + https - http://[::1]:443/ - ipv6 - unix:/tmp/http.sock - unix sockets - https://unix:/tmp/http.sock - unix sockets (https) * @param {*} urlAddress the internet address definition * @return {Object|Null} literal object that represent the address parsed */ function parseAddress(urlAddress) { // // TODO: refactor it to something more reasonable? // // protocol : // ( host )|( ipv6 ): port / let urlPattern = /^((https?):(\/\/)?)?((([^\/:]*)|\[([^\[\]]+)\]):)?(\d+)\/?$/.exec(urlAddress); if (urlPattern) { return { proto: urlPattern[2] || _constants.DEFAULT_PROTOCOL, host: urlPattern[6] || urlPattern[7] || _constants.DEFAULT_DOMAIN, port: urlPattern[8] || _constants.DEFAULT_PORT }; } urlPattern = /^((https?):(\/\/)?)?unix:(.*)$/.exec(urlAddress); if (urlPattern) { return { proto: urlPattern[2] || _constants.DEFAULT_PROTOCOL, path: urlPattern[4] }; } return null; } /** * Function filters out bad semver versions and sorts the array. * @return {Array} sorted Array */ function semverSort(listVersions) { return listVersions.filter(function (x) { if (!_semver.default.parse(x, true)) { _logger.logger.warn({ ver: x }, 'ignoring bad version @{ver}'); return false; } return true; }) // FIXME: it seems the @types/semver do not handle a legitimate method named 'compareLoose' // @ts-ignore .sort(_semver.default.compareLoose).map(String); } /** * Flatten arrays of tags. * @param {*} data */ function normalizeDistTags(pkg) { let sorted; if (!pkg[_constants.DIST_TAGS].latest) { // overwrite latest with highest known version based on semver sort sorted = semverSort(Object.keys(pkg.versions)); if (sorted && sorted.length) { pkg[_constants.DIST_TAGS].latest = sorted.pop(); } } for (const tag in pkg[_constants.DIST_TAGS]) { if (_lodash.default.isArray(pkg[_constants.DIST_TAGS][tag])) { if (pkg[_constants.DIST_TAGS][tag].length) { // sort array // FIXME: this is clearly wrong, we need to research why this is like this. // @ts-ignore sorted = semverSort(pkg[_constants.DIST_TAGS][tag]); if (sorted.length) { // use highest version based on semver sort pkg[_constants.DIST_TAGS][tag] = sorted.pop(); } } else { delete pkg[_constants.DIST_TAGS][tag]; } } else if (_lodash.default.isString(pkg[_constants.DIST_TAGS][tag])) { if (!_semver.default.parse(pkg[_constants.DIST_TAGS][tag], true)) { // if the version is invalid, delete the dist-tag entry delete pkg[_constants.DIST_TAGS][tag]; } } } } const parseIntervalTable = { '': 1000, ms: 1, s: 1000, m: 60 * 1000, h: 60 * 60 * 1000, d: 86400000, w: 7 * 86400000, M: 30 * 86400000, y: 365 * 86400000 }; /** * Parse an internal string to number * @param {*} interval * @return {Number} */ function parseInterval(interval) { if (typeof interval === 'number') { return interval * 1000; } let result = 0; let last_suffix = Infinity; interval.split(/\s+/).forEach(function (x) { if (!x) { return; } const m = x.match(/^((0|[1-9][0-9]*)(\.[0-9]+)?)(ms|s|m|h|d|w|M|y|)$/); if (!m || parseIntervalTable[m[4]] >= last_suffix || m[4] === '' && last_suffix !== Infinity) { throw Error('invalid interval: ' + interval); } last_suffix = parseIntervalTable[m[4]]; result += Number(m[1]) * parseIntervalTable[m[4]]; }); return result; } /** * Detect running protocol (http or https) */ function getWebProtocol(headerProtocol, protocol) { if (typeof headerProtocol === 'string' && headerProtocol !== '') { const commaIndex = headerProtocol.indexOf(','); return commaIndex > 0 ? headerProtocol.substr(0, commaIndex) : headerProtocol; } return protocol; } function getLatestVersion(pkgInfo) { return pkgInfo[_constants.DIST_TAGS].latest; } const ErrorCode = { getConflict: _commonsApi.getConflict, getBadData: _commonsApi.getBadData, getBadRequest: _commonsApi.getBadRequest, getInternalError: _commonsApi.getInternalError, getUnauthorized: _commonsApi.getUnauthorized, getForbidden: _commonsApi.getForbidden, getServiceUnavailable: _commonsApi.getServiceUnavailable, getNotFound: _commonsApi.getNotFound, getCode: _commonsApi.getCode }; exports.ErrorCode = ErrorCode; function parseConfigFile(configPath) { try { if (/\.ya?ml$/i.test(configPath)) { return _jsYaml.default.safeLoad(_fs.default.readFileSync(configPath, _constants.CHARACTER_ENCODING.UTF8)); } return require(configPath); } catch (e) { if (e.code !== 'MODULE_NOT_FOUND') { e.message = _constants.APP_ERROR.CONFIG_NOT_VALID; } throw new Error(e); } } /** * Check whether the path already exist. * @param {String} path * @return {Boolean} */ function folderExists(path) { try { const stat = _fs.default.statSync(path); return stat.isDirectory(); } catch (_) { return false; } } /** * Check whether the file already exist. * @param {String} path * @return {Boolean} */ function fileExists(path) { try { const stat = _fs.default.statSync(path); return stat.isFile(); } catch (_) { return false; } } function sortByName(packages, orderAscending = true) { return packages.slice().sort(function (a, b) { const comparatorNames = a.name.toLowerCase() < b.name.toLowerCase(); return orderAscending ? comparatorNames ? -1 : 1 : comparatorNames ? 1 : -1; }); } function addScope(scope, packageName) { return `@${scope}/${packageName}`; } function deleteProperties(propertiesToDelete, objectItem) { _lodash.default.forEach(propertiesToDelete, property => { delete objectItem[property]; }); return objectItem; } function addGravatarSupport(pkgInfo, online = true) { const pkgInfoCopy = _objectSpread({}, pkgInfo); const author = _lodash.default.get(pkgInfo, 'latest.author', null); const contributors = (0, _storageUtils.normalizeContributors)(_lodash.default.get(pkgInfo, 'latest.contributors', [])); const maintainers = _lodash.default.get(pkgInfo, 'latest.maintainers', []); // for author. if (author && _lodash.default.isObject(author)) { const { email } = author; pkgInfoCopy.latest.author.avatar = (0, _user.generateGravatarUrl)(email, online); } if (author && _lodash.default.isString(author)) { pkgInfoCopy.latest.author = { avatar: _user.GENERIC_AVATAR, email: '', author }; } // for contributors if (_lodash.default.isEmpty(contributors) === false) { pkgInfoCopy.latest.contributors = contributors.map(contributor => { if (isObject(contributor)) { contributor.avatar = (0, _user.generateGravatarUrl)(contributor.email, online); } else if (_lodash.default.isString(contributor)) { contributor = { avatar: _user.GENERIC_AVATAR, email: contributor, name: contributor }; } return contributor; }); } // for maintainers if (_lodash.default.isEmpty(maintainers) === false) { pkgInfoCopy.latest.maintainers = maintainers.map(maintainer => { maintainer.avatar = (0, _user.generateGravatarUrl)(maintainer.email, online); return maintainer; }); } return pkgInfoCopy; } /** * parse package readme - markdown/ascii * @param {String} packageName name of package * @param {String} readme package readme * @return {String} converted html template */ function parseReadme(packageName, readme) { if (_lodash.default.isEmpty(readme) === false) { return (0, _readme.default)(readme); } // logs readme not found error _logger.logger.error({ packageName }, '@{packageName}: No readme found'); return (0, _readme.default)('ERROR: No README data found!'); } function buildToken(type, token) { return `${_lodash.default.capitalize(type)} ${token}`; } /** * return package version from tarball name * @param {String} name * @returns {String} */ function getVersionFromTarball(name) { // FIXME: we know the regex is valid, but we should improve this part as ts suggest // @ts-ignore return /.+-(\d.+)\.tgz/.test(name) ? name.match(/.+-(\d.+)\.tgz/)[1] : undefined; } /** * Formats author field for webui. * @see https://docs.npmjs.com/files/package.json#author * @param {string|object|undefined} author */ function formatAuthor(author) { let authorDetails = { name: _constants.DEFAULT_USER, email: '', url: '' }; if (_lodash.default.isNil(author)) { return authorDetails; } if (_lodash.default.isString(author)) { authorDetails = _objectSpread(_objectSpread({}, authorDetails), {}, { name: author }); } if (_lodash.default.isObject(author)) { authorDetails = _objectSpread(_objectSpread({}, authorDetails), author); } return authorDetails; } /** * Check if URI is starting with "http://", "https://" or "//" * @param {string} uri */ function isHTTPProtocol(uri) { return /^(https?:)?\/\//.test(uri); } /** * Apply whitespaces based on the length * @param {*} str the log message * @return {String} */ function pad(str, max) { if (str.length < max) { return str + ' '.repeat(max - str.length); } return str; } /** * return a masquerade string with its first and last {charNum} and three dots in between. * @param {String} str * @param {Number} charNum * @returns {String} */ function mask(str, charNum = 3) { return `${str.substr(0, charNum)}...${str.substr(-charNum)}`; } function encodeScopedUri(packageName) { return packageName.replace(/\//g, '%2f'); } function hasDiffOneKey(versions) { return Object.keys(versions).length !== 1; } function isVersionValid(packageMeta, packageVersion) { const hasVersion = typeof packageVersion !== 'undefined'; if (!hasVersion) { return false; } const hasMatchVersion = Object.keys(packageMeta.versions).includes(packageVersion); return hasMatchVersion; } function isRelatedToDeprecation(pkgInfo) { const { versions } = pkgInfo; for (const version in versions) { if (Object.prototype.hasOwnProperty.call(versions[version], 'deprecated')) { return true; } } return false; } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvdXRpbHMudHMiXSwibmFtZXMiOlsicmVxdWlyZSIsIm1vZHVsZSIsInBrZ1ZlcnNpb24iLCJleHBvcnRzIiwidmVyc2lvbiIsInBrZ05hbWUiLCJuYW1lIiwiZ2V0VXNlckFnZW50IiwiXyIsImlzU3RyaW5nIiwiY29udmVydFBheWxvYWRUb0Jhc2U2NCIsInBheWxvYWQiLCJCdWZmZXIiLCJmcm9tIiwidmFsaWRhdGVOYW1lIiwibm9ybWFsaXplZE5hbWUiLCJ0b0xvd2VyQ2FzZSIsIm1hdGNoIiwic3RhcnRzV2l0aCIsImluY2x1ZGVzIiwidmFsaWRhdGVQYWNrYWdlIiwibmFtZUxpc3QiLCJzcGxpdCIsImxlbmd0aCIsInNsaWNlIiwiaXNPYmplY3QiLCJvYmoiLCJpc051bGwiLCJpc0FycmF5IiwidmFsaWRhdGVNZXRhZGF0YSIsIm9iamVjdCIsImFzc2VydCIsInN0cmljdEVxdWFsIiwiRElTVF9UQUdTIiwiY29tYmluZUJhc2VVcmwiLCJwcm90b2NvbCIsImhvc3QiLCJwcmVmaXgiLCJyZXN1bHQiLCJwcmVmaXhPbmx5U2xhc2giLCJlbmRzV2l0aCIsImV4dHJhY3RUYXJiYWxsRnJvbVVybCIsInVybCIsIlVSTCIsInBhcnNlIiwicGF0aG5hbWUiLCJyZXBsYWNlIiwiY29udmVydERpc3RSZW1vdGVUb0xvY2FsVGFyYmFsbFVybHMiLCJwa2ciLCJyZXEiLCJ1cmxQcmVmaXgiLCJ2ZXIiLCJ2ZXJzaW9ucyIsIk9iamVjdCIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImRpc3ROYW1lIiwiZGlzdCIsInRhcmJhbGwiLCJnZXRMb2NhbFJlZ2lzdHJ5VGFyYmFsbFVyaSIsInVyaSIsImN1cnJlbnRIb3N0IiwiaGVhZGVycyIsInRhcmJhbGxOYW1lIiwiZ2V0V2ViUHJvdG9jb2wiLCJnZXQiLCJIRUFERVJTIiwiRk9SV0FSREVEX1BST1RPIiwiZG9tYWluUmVnaXN0cnkiLCJlbmNvZGVTY29wZWRVcmkiLCJ0YWdWZXJzaW9uIiwiZGF0YSIsInRhZyIsInNlbXZlciIsImdldFZlcnNpb24iLCJpc05pbCIsInZlcnNpb25JdGVtIiwiY29tcGFyZSIsImVyciIsInVuZGVmaW5lZCIsInBhcnNlQWRkcmVzcyIsInVybEFkZHJlc3MiLCJ1cmxQYXR0ZXJuIiwiZXhlYyIsInByb3RvIiwiREVGQVVMVF9QUk9UT0NPTCIsIkRFRkFVTFRfRE9NQUlOIiwicG9ydCIsIkRFRkFVTFRfUE9SVCIsInBhdGgiLCJzZW12ZXJTb3J0IiwibGlzdFZlcnNpb25zIiwiZmlsdGVyIiwieCIsImxvZ2dlciIsIndhcm4iLCJzb3J0IiwiY29tcGFyZUxvb3NlIiwibWFwIiwiU3RyaW5nIiwibm9ybWFsaXplRGlzdFRhZ3MiLCJzb3J0ZWQiLCJsYXRlc3QiLCJrZXlzIiwicG9wIiwicGFyc2VJbnRlcnZhbFRhYmxlIiwibXMiLCJzIiwibSIsImgiLCJkIiwidyIsIk0iLCJ5IiwicGFyc2VJbnRlcnZhbCIsImludGVydmFsIiwibGFzdF9zdWZmaXgiLCJJbmZpbml0eSIsImZvckVhY2giLCJFcnJvciIsIk51bWJlciIsImhlYWRlclByb3RvY29sIiwiY29tbWFJbmRleCIsImluZGV4T2YiLCJzdWJzdHIiLCJnZXRMYXRlc3RWZXJzaW9uIiwicGtnSW5mbyIsIkVycm9yQ29kZSIsImdldENvbmZsaWN0IiwiZ2V0QmFkRGF0YSIsImdldEJhZFJlcXVlc3QiLCJnZXRJbnRlcm5hbEVycm9yIiwiZ2V0VW5hdXRob3JpemVkIiwiZ2V0Rm9yYmlkZGVuIiwiZ2V0U2VydmljZVVuYXZhaWxhYmxlIiwiZ2V0Tm90Rm91bmQiLCJnZXRDb2RlIiwicGFyc2VDb25maWdGaWxlIiwiY29uZmlnUGF0aCIsInRlc3QiLCJZQU1MIiwic2FmZUxvYWQiLCJmcyIsInJlYWRGaWxlU3luYyIsIkNIQVJBQ1RFUl9FTkNPRElORyIsIlVURjgiLCJlIiwiY29kZSIsIm1lc3NhZ2UiLCJBUFBfRVJST1IiLCJDT05GSUdfTk9UX1ZBTElEIiwiZm9sZGVyRXhpc3RzIiwic3RhdCIsInN0YXRTeW5jIiwiaXNEaXJlY3RvcnkiLCJmaWxlRXhpc3RzIiwiaXNGaWxlIiwic29ydEJ5TmFtZSIsInBhY2thZ2VzIiwib3JkZXJBc2NlbmRpbmciLCJhIiwiYiIsImNvbXBhcmF0b3JOYW1lcyIsImFkZFNjb3BlIiwic2NvcGUiLCJwYWNrYWdlTmFtZSIsImRlbGV0ZVByb3BlcnRpZXMiLCJwcm9wZXJ0aWVzVG9EZWxldGUiLCJvYmplY3RJdGVtIiwicHJvcGVydHkiLCJhZGRHcmF2YXRhclN1cHBvcnQiLCJvbmxpbmUiLCJwa2dJbmZvQ29weSIsImF1dGhvciIsImNvbnRyaWJ1dG9ycyIsIm1haW50YWluZXJzIiwiZW1haWwiLCJhdmF0YXIiLCJHRU5FUklDX0FWQVRBUiIsImlzRW1wdHkiLCJjb250cmlidXRvciIsIm1haW50YWluZXIiLCJwYXJzZVJlYWRtZSIsInJlYWRtZSIsImVycm9yIiwiYnVpbGRUb2tlbiIsInR5cGUiLCJ0b2tlbiIsImNhcGl0YWxpemUiLCJnZXRWZXJzaW9uRnJvbVRhcmJhbGwiLCJmb3JtYXRBdXRob3IiLCJhdXRob3JEZXRhaWxzIiwiREVGQVVMVF9VU0VSIiwiaXNIVFRQUHJvdG9jb2wiLCJwYWQiLCJzdHIiLCJtYXgiLCJyZXBlYXQiLCJtYXNrIiwiY2hhck51bSIsImhhc0RpZmZPbmVLZXkiLCJpc1ZlcnNpb25WYWxpZCIsInBhY2thZ2VNZXRhIiwicGFja2FnZVZlcnNpb24iLCJoYXNWZXJzaW9uIiwiaGFzTWF0Y2hWZXJzaW9uIiwiaXNSZWxhdGVkVG9EZXByZWNhdGlvbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUdBOztBQUNBOztBQUNBOztBQUVBOztBQUNBOztBQUNBOztBQUNBOztBQUlBOztBQVdBOztBQUVBOztBQVdBOztBQUVBOzs7Ozs7Ozs7O0FBRUE7QUFDQTtBQUNBQSxPQUFPLENBQUMsU0FBRCxDQUFQLENBQW1CQyxNQUFuQjs7QUFDQSxNQUFNQyxVQUFVLEdBQUdELE1BQU0sQ0FBQ0UsT0FBUCxDQUFlQyxPQUFsQztBQUNBLE1BQU1DLE9BQU8sR0FBR0osTUFBTSxDQUFDRSxPQUFQLENBQWVHLElBQS9COztBQUVPLFNBQVNDLFlBQVQsR0FBZ0M7QUFDckMsdUJBQU9DLGdCQUFFQyxRQUFGLENBQVdKLE9BQVgsQ0FBUDtBQUNBLHVCQUFPRyxnQkFBRUMsUUFBRixDQUFXUCxVQUFYLENBQVA7QUFDQSxTQUFRLEdBQUVHLE9BQVEsSUFBR0gsVUFBVyxFQUFoQztBQUNEOztBQUVNLFNBQVNRLHNCQUFULENBQWdDQyxPQUFoQyxFQUF5RDtBQUM5RCxTQUFPQyxNQUFNLENBQUNDLElBQVAsQ0FBWUYsT0FBWixFQUFxQixRQUFyQixDQUFQO0FBQ0Q7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDTyxTQUFTRyxZQUFULENBQXNCUixJQUF0QixFQUE2QztBQUNsRCxNQUFJRSxnQkFBRUMsUUFBRixDQUFXSCxJQUFYLE1BQXFCLEtBQXpCLEVBQWdDO0FBQzlCLFdBQU8sS0FBUDtBQUNEOztBQUVELFFBQU1TLGNBQXNCLEdBQUdULElBQUksQ0FBQ1UsV0FBTCxFQUEvQjtBQUVBO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBQ0UsU0FBTyxFQUNMLENBQUNELGNBQWMsQ0FBQ0UsS0FBZixDQUFxQiwwQkFBckIsQ0FBRCxJQUNBRixjQUFjLENBQUNHLFVBQWYsQ0FBMEIsR0FBMUIsQ0FEQSxJQUNrQztBQUNsQyxHQUFDLGNBQUQsRUFBaUIsV0FBakIsRUFBOEIsYUFBOUIsRUFBNkNDLFFBQTdDLENBQXNESixjQUF0RCxDQUhLLENBQVA7QUFLRDtBQUVEO0FBQ0E7QUFDQTtBQUNBOzs7QUFDTyxTQUFTSyxlQUFULENBQXlCZCxJQUF6QixFQUFnRDtBQUNyRCxRQUFNZSxRQUFRLEdBQUdmLElBQUksQ0FBQ2dCLEtBQUwsQ0FBVyxHQUFYLEVBQWdCLENBQWhCLENBQWpCOztBQUNBLE1BQUlELFFBQVEsQ0FBQ0UsTUFBVCxLQUFvQixDQUF4QixFQUEyQjtBQUN6QjtBQUNBLFdBQU9ULFlBQVksQ0FBQ08sUUFBUSxDQUFDLENBQUQsQ0FBVCxDQUFuQjtBQUNELEdBTG9ELENBTXJEOzs7QUFDQSxTQUFPQSxRQUFRLENBQUMsQ0FBRCxDQUFSLENBQVksQ0FBWixNQUFtQixHQUFuQixJQUEwQlAsWUFBWSxDQUFDTyxRQUFRLENBQUMsQ0FBRCxDQUFSLENBQVlHLEtBQVosQ0FBa0IsQ0FBbEIsQ0FBRCxDQUF0QyxJQUFnRVYsWUFBWSxDQUFDTyxRQUFRLENBQUMsQ0FBRCxDQUFULENBQW5GO0FBQ0Q7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDTyxTQUFTSSxRQUFULENBQWtCQyxHQUFsQixFQUFxQztBQUMxQyxTQUFPbEIsZ0JBQUVpQixRQUFGLENBQVdDLEdBQVgsS0FBbUJsQixnQkFBRW1CLE1BQUYsQ0FBU0QsR0FBVCxNQUFrQixLQUFyQyxJQUE4Q2xCLGdCQUFFb0IsT0FBRixDQUFVRixHQUFWLE1BQW1CLEtBQXhFO0FBQ0Q7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ08sU0FBU0csZ0JBQVQsQ0FBMEJDLE1BQTFCLEVBQTJDeEIsSUFBM0MsRUFBa0U7QUFDdkUsdUJBQU9tQixRQUFRLENBQUNLLE1BQUQsQ0FBZixFQUF5QixtQkFBekI7O0FBQ0FDLGtCQUFPQyxXQUFQLENBQW1CRixNQUFNLENBQUN4QixJQUExQixFQUFnQ0EsSUFBaEM7O0FBRUEsTUFBSSxDQUFDbUIsUUFBUSxDQUFDSyxNQUFNLENBQUNHLG9CQUFELENBQVAsQ0FBYixFQUFrQztBQUNoQ0gsSUFBQUEsTUFBTSxDQUFDRyxvQkFBRCxDQUFOLEdBQW9CLEVBQXBCO0FBQ0Q7O0FBRUQsTUFBSSxDQUFDUixRQUFRLENBQUNLLE1BQU0sQ0FBQyxVQUFELENBQVAsQ0FBYixFQUFtQztBQUNqQ0EsSUFBQUEsTUFBTSxDQUFDLFVBQUQsQ0FBTixHQUFxQixFQUFyQjtBQUNEOztBQUVELE1BQUksQ0FBQ0wsUUFBUSxDQUFDSyxNQUFNLENBQUMsTUFBRCxDQUFQLENBQWIsRUFBK0I7QUFDN0JBLElBQUFBLE1BQU0sQ0FBQyxNQUFELENBQU4sR0FBaUIsRUFBakI7QUFDRDs7QUFFRCxTQUFPQSxNQUFQO0FBQ0Q7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7O0FBQ08sU0FBU0ksY0FBVCxDQUNMQyxRQURLLEVBRUxDLElBRkssRUFHTEMsTUFISyxFQUlHO0FBQ1IsUUFBTUMsTUFBTSxHQUFJLEdBQUVILFFBQVMsTUFBS0MsSUFBSyxFQUFyQztBQUVBLFFBQU1HLGVBQWUsR0FBR0YsTUFBTSxLQUFLLEdBQW5DOztBQUNBLE1BQUlBLE1BQU0sSUFBSSxDQUFDRSxlQUFmLEVBQWdDO0FBQzlCLFFBQUlGLE1BQU0sQ0FBQ0csUUFBUCxDQUFnQixHQUFoQixDQUFKLEVBQTBCO0FBQ3hCSCxNQUFBQSxNQUFNLEdBQUdBLE1BQU0sQ0FBQ2IsS0FBUCxDQUFhLENBQWIsRUFBZ0IsQ0FBQyxDQUFqQixDQUFUO0FBQ0Q7O0FBRUQsUUFBSWEsTUFBTSxDQUFDbkIsVUFBUCxDQUFrQixHQUFsQixDQUFKLEVBQTRCO0FBQzFCLGFBQVEsR0FBRW9CLE1BQU8sR0FBRUQsTUFBTyxFQUExQjtBQUNEOztBQUVELFdBQU9BLE1BQVA7QUFDRDs7QUFFRCxTQUFPQyxNQUFQO0FBQ0Q7O0FBRU0sU0FBU0cscUJBQVQsQ0FBK0JDLEdBQS9CLEVBQW9EO0FBQ3pEO0FBQ0EsU0FBT0MsYUFBSUMsS0FBSixDQUFVRixHQUFWLEVBQWVHLFFBQWYsQ0FBd0JDLE9BQXhCLENBQWdDLE9BQWhDLEVBQXlDLEVBQXpDLENBQVA7QUFDRDtBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDTyxTQUFTQyxtQ0FBVCxDQUNMQyxHQURLLEVBRUxDLEdBRkssRUFHTEMsU0FISyxFQUlJO0FBQ1QsT0FBSyxNQUFNQyxHQUFYLElBQWtCSCxHQUFHLENBQUNJLFFBQXRCLEVBQWdDO0FBQzlCLFFBQUlDLE1BQU0sQ0FBQ0MsU0FBUCxDQUFpQkMsY0FBakIsQ0FBZ0NDLElBQWhDLENBQXFDUixHQUFHLENBQUNJLFFBQXpDLEVBQW1ERCxHQUFuRCxDQUFKLEVBQTZEO0FBQzNELFlBQU1NLFFBQVEsR0FBR1QsR0FBRyxDQUFDSSxRQUFKLENBQWFELEdBQWIsRUFBa0JPLElBQW5DOztBQUVBLFVBQUlsRCxnQkFBRW1CLE1BQUYsQ0FBUzhCLFFBQVQsTUFBdUIsS0FBdkIsSUFBZ0NqRCxnQkFBRW1CLE1BQUYsQ0FBUzhCLFFBQVEsQ0FBQ0UsT0FBbEIsTUFBK0IsS0FBbkUsRUFBMEU7QUFDeEVGLFFBQUFBLFFBQVEsQ0FBQ0UsT0FBVCxHQUFtQkMsMEJBQTBCLENBQUNILFFBQVEsQ0FBQ0UsT0FBVixFQUFtQlgsR0FBRyxDQUFDMUMsSUFBdkIsRUFBNkIyQyxHQUE3QixFQUFrQ0MsU0FBbEMsQ0FBN0M7QUFDRDtBQUNGO0FBQ0Y7O0FBQ0QsU0FBT0YsR0FBUDtBQUNEO0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ08sU0FBU1ksMEJBQVQsQ0FDTEMsR0FESyxFQUVMeEQsT0FGSyxFQUdMNEMsR0FISyxFQUlMQyxTQUpLLEVBS0c7QUFDUixRQUFNWSxXQUFXLEdBQUdiLEdBQUcsQ0FBQ2MsT0FBSixDQUFZM0IsSUFBaEM7O0FBRUEsTUFBSSxDQUFDMEIsV0FBTCxFQUFrQjtBQUNoQixXQUFPRCxHQUFQO0FBQ0Q7O0FBQ0QsUUFBTUcsV0FBVyxHQUFHdkIscUJBQXFCLENBQUNvQixHQUFELENBQXpDO0FBQ0EsUUFBTUUsT0FBTyxHQUFHZCxHQUFHLENBQUNjLE9BQXBCO0FBQ0EsUUFBTTVCLFFBQVEsR0FBRzhCLGNBQWMsQ0FBQ2hCLEdBQUcsQ0FBQ2lCLEdBQUosQ0FBUUMsbUJBQVFDLGVBQWhCLENBQUQsRUFBbUNuQixHQUFHLENBQUNkLFFBQXZDLENBQS9CO0FBQ0EsUUFBTWtDLGNBQWMsR0FBR25DLGNBQWMsQ0FBQ0MsUUFBRCxFQUFXNEIsT0FBTyxDQUFDM0IsSUFBbkIsRUFBeUJjLFNBQXpCLENBQXJDO0FBRUEsU0FBUSxHQUFFbUIsY0FBZSxJQUFHQyxlQUFlLENBQUNqRSxPQUFELENBQVUsTUFBSzJELFdBQVksRUFBdEU7QUFDRDtBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDTyxTQUFTTyxVQUFULENBQW9CQyxJQUFwQixFQUFtQ3BFLE9BQW5DLEVBQW9EcUUsR0FBcEQsRUFBK0U7QUFDcEYsTUFBSUEsR0FBRyxJQUFJRCxJQUFJLENBQUN2QyxvQkFBRCxDQUFKLENBQWdCd0MsR0FBaEIsTUFBeUJyRSxPQUFoQyxJQUEyQ3NFLGdCQUFPOUIsS0FBUCxDQUFheEMsT0FBYixFQUFzQixJQUF0QixDQUEvQyxFQUE0RTtBQUMxRTtBQUNBb0UsSUFBQUEsSUFBSSxDQUFDdkMsb0JBQUQsQ0FBSixDQUFnQndDLEdBQWhCLElBQXVCckUsT0FBdkI7QUFDQSxXQUFPLElBQVA7QUFDRDs7QUFDRCxTQUFPLEtBQVA7QUFDRDtBQUVEO0FBQ0E7QUFDQTtBQUNBOzs7QUFDTyxTQUFTdUUsVUFBVCxDQUFvQjNCLEdBQXBCLEVBQWtDNUMsT0FBbEMsRUFBZ0U7QUFDckU7QUFDQSxNQUFJSSxnQkFBRW9FLEtBQUYsQ0FBUTVCLEdBQUcsQ0FBQ0ksUUFBSixDQUFhaEQsT0FBYixDQUFSLE1BQW1DLEtBQXZDLEVBQThDO0FBQzVDLFdBQU80QyxHQUFHLENBQUNJLFFBQUosQ0FBYWhELE9BQWIsQ0FBUDtBQUNEOztBQUVELE1BQUk7QUFDRkEsSUFBQUEsT0FBTyxHQUFHc0UsZ0JBQU85QixLQUFQLENBQWF4QyxPQUFiLEVBQXNCLElBQXRCLENBQVY7O0FBQ0EsU0FBSyxNQUFNeUUsV0FBWCxJQUEwQjdCLEdBQUcsQ0FBQ0ksUUFBOUIsRUFBd0M7QUFDdEM7QUFDQSxVQUFJaEQsT0FBTyxDQUFDMEUsT0FBUixDQUFnQkosZ0JBQU85QixLQUFQLENBQWFpQyxXQUFiLEVBQTBCLElBQTFCLENBQWhCLE1BQXFELENBQXpELEVBQTREO0FBQzFELGVBQU83QixHQUFHLENBQUNJLFFBQUosQ0FBYXlCLFdBQWIsQ0FBUDtBQUNEO0FBQ0Y7QUFDRixHQVJELENBUUUsT0FBT0UsR0FBUCxFQUFZO0FBQ1osV0FBT0MsU0FBUDtBQUNEO0FBQ0Y7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDTyxTQUFTQyxZQUFULENBQXNCQyxVQUF0QixFQUE0QztBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQUlDLFVBQVUsR0FBRyw4REFBOERDLElBQTlELENBQW1FRixVQUFuRSxDQUFqQjs7QUFFQSxNQUFJQyxVQUFKLEVBQWdCO0FBQ2QsV0FBTztBQUNMRSxNQUFBQSxLQUFLLEVBQUVGLFVBQVUsQ0FBQyxDQUFELENBQVYsSUFBaUJHLDJCQURuQjtBQUVMbEQsTUFBQUEsSUFBSSxFQUFFK0MsVUFBVSxDQUFDLENBQUQsQ0FBVixJQUFpQkEsVUFBVSxDQUFDLENBQUQsQ0FBM0IsSUFBa0NJLHlCQUZuQztBQUdMQyxNQUFBQSxJQUFJLEVBQUVMLFVBQVUsQ0FBQyxDQUFELENBQVYsSUFBaUJNO0FBSGxCLEtBQVA7QUFLRDs7QUFFRE4sRUFBQUEsVUFBVSxHQUFHLGlDQUFpQ0MsSUFBakMsQ0FBc0NGLFVBQXRDLENBQWI7O0FBRUEsTUFBSUMsVUFBSixFQUFnQjtBQUNkLFdBQU87QUFDTEUsTUFBQUEsS0FBSyxFQUFFRixVQUFVLENBQUMsQ0FBRCxDQUFWLElBQWlCRywyQkFEbkI7QUFFTEksTUFBQUEsSUFBSSxFQUFFUCxVQUFVLENBQUMsQ0FBRDtBQUZYLEtBQVA7QUFJRDs7QUFFRCxTQUFPLElBQVA7QUFDRDtBQUVEO0FBQ0E7QUFDQTtBQUNBOzs7QUFDTyxTQUFTUSxVQUFULENBQW9CQyxZQUFwQixFQUFzRDtBQUMzRCxTQUNFQSxZQUFZLENBQ1RDLE1BREgsQ0FDVSxVQUFVQyxDQUFWLEVBQXNCO0FBQzVCLFFBQUksQ0FBQ3BCLGdCQUFPOUIsS0FBUCxDQUFha0QsQ0FBYixFQUFnQixJQUFoQixDQUFMLEVBQTRCO0FBQzFCQyxxQkFBT0MsSUFBUCxDQUFZO0FBQUU3QyxRQUFBQSxHQUFHLEVBQUUyQztBQUFQLE9BQVosRUFBd0IsNkJBQXhCOztBQUNBLGFBQU8sS0FBUDtBQUNEOztBQUNELFdBQU8sSUFBUDtBQUNELEdBUEgsRUFRRTtBQUNBO0FBVEYsR0FVR0csSUFWSCxDQVVRdkIsZ0JBQU93QixZQVZmLEVBV0dDLEdBWEgsQ0FXT0MsTUFYUCxDQURGO0FBY0Q7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7O0FBQ08sU0FBU0MsaUJBQVQsQ0FBMkJyRCxHQUEzQixFQUErQztBQUNwRCxNQUFJc0QsTUFBSjs7QUFDQSxNQUFJLENBQUN0RCxHQUFHLENBQUNmLG9CQUFELENBQUgsQ0FBZXNFLE1BQXBCLEVBQTRCO0FBQzFCO0FBQ0FELElBQUFBLE1BQU0sR0FBR1gsVUFBVSxDQUFDdEMsTUFBTSxDQUFDbUQsSUFBUCxDQUFZeEQsR0FBRyxDQUFDSSxRQUFoQixDQUFELENBQW5COztBQUNBLFFBQUlrRCxNQUFNLElBQUlBLE1BQU0sQ0FBQy9FLE1BQXJCLEVBQTZCO0FBQzNCeUIsTUFBQUEsR0FBRyxDQUFDZixvQkFBRCxDQUFILENBQWVzRSxNQUFmLEdBQXdCRCxNQUFNLENBQUNHLEdBQVAsRUFBeEI7QUFDRDtBQUNGOztBQUVELE9BQUssTUFBTWhDLEdBQVgsSUFBa0J6QixHQUFHLENBQUNmLG9CQUFELENBQXJCLEVBQWtDO0FBQ2hDLFFBQUl6QixnQkFBRW9CLE9BQUYsQ0FBVW9CLEdBQUcsQ0FBQ2Ysb0JBQUQsQ0FBSCxDQUFld0MsR0FBZixDQUFWLENBQUosRUFBb0M7QUFDbEMsVUFBSXpCLEdBQUcsQ0FBQ2Ysb0JBQUQsQ0FBSCxDQUFld0MsR0FBZixFQUFvQmxELE1BQXhCLEVBQWdDO0FBQzlCO0FBQ0E7QUFDQTtBQUNBK0UsUUFBQUEsTUFBTSxHQUFHWCxVQUFVLENBQUMzQyxHQUFHLENBQUNmLG9CQUFELENBQUgsQ0FBZXdDLEdBQWYsQ0FBRCxDQUFuQjs7QUFDQSxZQUFJNkIsTUFBTSxDQUFDL0UsTUFBWCxFQUFtQjtBQUNqQjtBQUNBeUIsVUFBQUEsR0FBRyxDQUFDZixvQkFBRCxDQUFILENBQWV3QyxHQUFmLElBQXNCNkIsTUFBTSxDQUFDRyxHQUFQLEVBQXRCO0FBQ0Q7QUFDRixPQVRELE1BU087QUFDTCxlQUFPekQsR0FBRyxDQUFDZixvQkFBRCxDQUFILENBQWV3QyxHQUFmLENBQVA7QUFDRDtBQUNGLEtBYkQsTUFhTyxJQUFJakUsZ0JBQUVDLFFBQUYsQ0FBV3VDLEdBQUcsQ0FBQ2Ysb0JBQUQsQ0FBSCxDQUFld0MsR0FBZixDQUFYLENBQUosRUFBcUM7QUFDMUMsVUFBSSxDQUFDQyxnQkFBTzlCLEtBQVAsQ0FBYUksR0FBRyxDQUFDZixvQkFBRCxDQUFILENBQWV3QyxHQUFmLENBQWIsRUFBa0MsSUFBbEMsQ0FBTCxFQUE4QztBQUM1QztBQUNBLGVBQU96QixHQUFHLENBQUNmLG9CQUFELENBQUgsQ0FBZXdDLEdBQWYsQ0FBUDtBQUNEO0FBQ0Y7QUFDRjtBQUNGOztBQUVELE1BQU1pQyxrQkFBa0IsR0FBRztBQUN6QixNQUFJLElBRHFCO0FBRXpCQyxFQUFBQSxFQUFFLEVBQUUsQ0FGcUI7QUFHekJDLEVBQUFBLENBQUMsRUFBRSxJQUhzQjtBQUl6QkMsRUFBQUEsQ0FBQyxFQUFFLEtBQUssSUFKaUI7QUFLekJDLEVBQUFBLENBQUMsRUFBRSxLQUFLLEVBQUwsR0FBVSxJQUxZO0FBTXpCQyxFQUFBQSxDQUFDLEVBQUUsUUFOc0I7QUFPekJDLEVBQUFBLENBQUMsRUFBRSxJQUFJLFFBUGtCO0FBUXpCQyxFQUFBQSxDQUFDLEVBQUUsS0FBSyxRQVJpQjtBQVN6QkMsRUFBQUEsQ0FBQyxFQUFFLE1BQU07QUFUZ0IsQ0FBM0I7QUFZQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUNPLFNBQVNDLGFBQVQsQ0FBdUJDLFFBQXZCLEVBQThDO0FBQ25ELE1BQUksT0FBT0EsUUFBUCxLQUFvQixRQUF4QixFQUFrQztBQUNoQyxXQUFPQSxRQUFRLEdBQUcsSUFBbEI7QUFDRDs7QUFDRCxNQUFJOUUsTUFBTSxHQUFHLENBQWI7QUFDQSxNQUFJK0UsV0FBVyxHQUFHQyxRQUFsQjtBQUNBRixFQUFBQSxRQUFRLENBQUM5RixLQUFULENBQWUsS0FBZixFQUFzQmlHLE9BQXRCLENBQThCLFVBQVV6QixDQUFWLEVBQW1CO0FBQy9DLFFBQUksQ0FBQ0EsQ0FBTCxFQUFRO0FBQ047QUFDRDs7QUFDRCxVQUFNZSxDQUFDLEdBQUdmLENBQUMsQ0FBQzdFLEtBQUYsQ0FBUSxtREFBUixDQUFWOztBQUNBLFFBQ0UsQ0FBQzRGLENBQUQsSUFDQUgsa0JBQWtCLENBQUNHLENBQUMsQ0FBQyxDQUFELENBQUYsQ0FBbEIsSUFBNEJRLFdBRDVCLElBRUNSLENBQUMsQ0FBQyxDQUFELENBQUQsS0FBUyxFQUFULElBQWVRLFdBQVcsS0FBS0MsUUFIbEMsRUFJRTtBQUNBLFlBQU1FLEtBQUssQ0FBQyx1QkFBdUJKLFFBQXhCLENBQVg7QUFDRDs7QUFDREMsSUFBQUEsV0FBVyxHQUFHWCxrQkFBa0IsQ0FBQ0csQ0FBQyxDQUFDLENBQUQsQ0FBRixDQUFoQztBQUNBdkUsSUFBQUEsTUFBTSxJQUFJbUYsTUFBTSxDQUFDWixDQUFDLENBQUMsQ0FBRCxDQUFGLENBQU4sR0FBZUgsa0JBQWtCLENBQUNHLENBQUMsQ0FBQyxDQUFELENBQUYsQ0FBM0M7QUFDRCxHQWREO0FBZUEsU0FBT3ZFLE1BQVA7QUFDRDtBQUVEO0FBQ0E7QUFDQTs7O0FBQ08sU0FBUzJCLGNBQVQsQ0FBd0J5RCxjQUF4QixFQUF1RHZGLFFBQXZELEVBQWlGO0FBQ3RGLE1BQUksT0FBT3VGLGNBQVAsS0FBMEIsUUFBMUIsSUFBc0NBLGNBQWMsS0FBSyxFQUE3RCxFQUFpRTtBQUMvRCxVQUFNQyxVQUFVLEdBQUdELGNBQWMsQ0FBQ0UsT0FBZixDQUF1QixHQUF2QixDQUFuQjtBQUNBLFdBQU9ELFVBQVUsR0FBRyxDQUFiLEdBQWlCRCxjQUFjLENBQUNHLE1BQWYsQ0FBc0IsQ0FBdEIsRUFBeUJGLFVBQXpCLENBQWpCLEdBQXdERCxjQUEvRDtBQUNEOztBQUVELFNBQU92RixRQUFQO0FBQ0Q7O0FBRU0sU0FBUzJGLGdCQUFULENBQTBCQyxPQUExQixFQUFvRDtBQUN6RCxTQUFPQSxPQUFPLENBQUM5RixvQkFBRCxDQUFQLENBQW1Cc0UsTUFBMUI7QUFDRDs7QUFFTSxNQUFNeUIsU0FBUyxHQUFHO0FBQ3ZCQyxFQUFBQSxXQUFXLEVBQVhBLHVCQUR1QjtBQUV2QkMsRUFBQUEsVUFBVSxFQUFWQSxzQkFGdUI7QUFHdkJDLEVBQUFBLGFBQWEsRUFBYkEseUJBSHVCO0FBSXZCQyxFQUFBQSxnQkFBZ0IsRUFBaEJBLDRCQUp1QjtBQUt2QkMsRUFBQUEsZUFBZSxFQUFmQSwyQkFMdUI7QUFNdkJDLEVBQUFBLFlBQVksRUFBWkEsd0JBTnVCO0FBT3ZCQyxFQUFBQSxxQkFBcUIsRUFBckJBLGlDQVB1QjtBQVF2QkMsRUFBQUEsV0FBVyxFQUFYQSx1QkFSdUI7QUFTdkJDLEVBQUFBLE9BQU8sRUFBUEE7QUFUdUIsQ0FBbEI7OztBQVlBLFNBQVNDLGVBQVQsQ0FBeUJDLFVBQXpCLEVBQWtEO0FBQ3ZELE1BQUk7QUFDRixRQUFJLFlBQVlDLElBQVosQ0FBaUJELFVBQWpCLENBQUosRUFBa0M7QUFDaEMsYUFBT0UsZ0JBQUtDLFFBQUwsQ0FBY0MsWUFBR0MsWUFBSCxDQUFnQkwsVUFBaEIsRUFBNEJNLDhCQUFtQkMsSUFBL0MsQ0FBZCxDQUFQO0FBQ0Q7O0FBQ0QsV0FBT2xKLE9BQU8sQ0FBQzJJLFVBQUQsQ0FBZDtBQUNELEdBTEQsQ0FLRSxPQUFPUSxDQUFQLEVBQVU7QUFDVixRQUFJQSxDQUFDLENBQUNDLElBQUYsS0FBVyxrQkFBZixFQUFtQztBQUNqQ0QsTUFBQUEsQ0FBQyxDQUFDRSxPQUFGLEdBQVlDLHFCQUFVQyxnQkFBdEI7QUFDRDs7QUFFRCxVQUFNLElBQUkvQixLQUFKLENBQVUyQixDQUFWLENBQU47QUFDRDtBQUNGO0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ08sU0FBU0ssWUFBVCxDQUFzQjlELElBQXRCLEVBQTZDO0FBQ2xELE1BQUk7QUFDRixVQUFNK0QsSUFBSSxHQUFHVixZQUFHVyxRQUFILENBQVloRSxJQUFaLENBQWI7O0FBQ0EsV0FBTytELElBQUksQ0FBQ0UsV0FBTCxFQUFQO0FBQ0QsR0FIRCxDQUdFLE9BQU9uSixDQUFQLEVBQVU7QUFDVixXQUFPLEtBQVA7QUFDRDtBQUNGO0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQ08sU0FBU29KLFVBQVQsQ0FBb0JsRSxJQUFwQixFQUEyQztBQUNoRCxNQUFJO0FBQ0YsVUFBTStELElBQUksR0FBR1YsWUFBR1csUUFBSCxDQUFZaEUsSUFBWixDQUFiOztBQUNBLFdBQU8rRCxJQUFJLENBQUNJLE1BQUwsRUFBUDtBQUNELEdBSEQsQ0FHRSxPQUFPckosQ0FBUCxFQUFVO0FBQ1YsV0FBTyxLQUFQO0FBQ0Q7QUFDRjs7QUFFTSxTQUFTc0osVUFBVCxDQUFvQkMsUUFBcEIsRUFBcUNDLGNBQThCLEdBQUcsSUFBdEUsRUFBc0Y7QUFDM0YsU0FBT0QsUUFBUSxDQUFDdkksS0FBVCxHQUFpQnlFLElBQWpCLENBQXNCLFVBQVVnRSxDQUFWLEVBQWFDLENBQWIsRUFBd0I7QUFDbkQsVUFBTUMsZUFBZSxHQUFHRixDQUFDLENBQUMzSixJQUFGLENBQU9VLFdBQVAsS0FBdUJrSixDQUFDLENBQUM1SixJQUFGLENBQU9VLFdBQVAsRUFBL0M7QUFFQSxXQUFPZ0osY0FBYyxHQUFJRyxlQUFlLEdBQUcsQ0FBQyxDQUFKLEdBQVEsQ0FBM0IsR0FBZ0NBLGVBQWUsR0FBRyxDQUFILEdBQU8sQ0FBQyxDQUE1RTtBQUNELEdBSk0sQ0FBUDtBQUtEOztBQUVNLFNBQVNDLFFBQVQsQ0FBa0JDLEtBQWxCLEVBQWlDQyxXQUFqQyxFQUE4RDtBQUNuRSxTQUFRLElBQUdELEtBQU0sSUFBR0MsV0FBWSxFQUFoQztBQUNEOztBQUVNLFNBQVNDLGdCQUFULENBQTBCQyxrQkFBMUIsRUFBd0RDLFVBQXhELEVBQThFO0FBQ25Gakssa0JBQUUrRyxPQUFGLENBQVVpRCxrQkFBVixFQUErQkUsUUFBRCxJQUFtQjtBQUMvQyxXQUFPRCxVQUFVLENBQUNDLFFBQUQsQ0FBakI7QUFDRCxHQUZEOztBQUlBLFNBQU9ELFVBQVA7QUFDRDs7QUFFTSxTQUFTRSxrQkFBVCxDQUE0QjVDLE9BQTVCLEVBQThDNkMsTUFBTSxHQUFHLElBQXZELEVBQTJFO0FBQ2hGLFFBQU1DLFdBQVcscUJBQVE5QyxPQUFSLENBQWpCOztBQUNBLFFBQU0rQyxNQUFXLEdBQUd0SyxnQkFBRTBELEdBQUYsQ0FBTTZELE9BQU4sRUFBZSxlQUFmLEVBQWdDLElBQWhDLENBQXBCOztBQUNBLFFBQU1nRCxZQUE0QixHQUFHLHlDQUNuQ3ZLLGdCQUFFMEQsR0FBRixDQUFNNkQsT0FBTixFQUFlLHFCQUFmLEVBQXNDLEVBQXRDLENBRG1DLENBQXJDOztBQUdBLFFBQU1pRCxXQUFXLEdBQUd4SyxnQkFBRTBELEdBQUYsQ0FBTTZELE9BQU4sRUFBZSxvQkFBZixFQUFxQyxFQUFyQyxDQUFwQixDQU5nRixDQVFoRjs7O0FBQ0EsTUFBSStDLE1BQU0sSUFBSXRLLGdCQUFFaUIsUUFBRixDQUFXcUosTUFBWCxDQUFkLEVBQWtDO0FBQ2hDLFVBQU07QUFBRUcsTUFBQUE7QUFBRixRQUFZSCxNQUFsQjtBQUNBRCxJQUFBQSxXQUFXLENBQUN0RSxNQUFaLENBQW1CdUUsTUFBbkIsQ0FBMEJJLE1BQTFCLEdBQW1DLCtCQUFvQkQsS0FBcEIsRUFBMkJMLE1BQTNCLENBQW5DO0FBQ0Q7O0FBRUQsTUFBSUUsTUFBTSxJQUFJdEssZ0JBQUVDLFFBQUYsQ0FBV3FLLE1BQVgsQ0FBZCxFQUFrQztBQUNoQ0QsSUFBQUEsV0FBVyxDQUFDdEUsTUFBWixDQUFtQnVFLE1BQW5CLEdBQTRCO0FBQzFCSSxNQUFBQSxNQUFNLEVBQUVDLG9CQURrQjtBQUUxQkYsTUFBQUEsS0FBSyxFQUFFLEVBRm1CO0FBRzFCSCxNQUFBQTtBQUgwQixLQUE1QjtBQUtELEdBcEIrRSxDQXNCaEY7OztBQUNBLE1BQUl0SyxnQkFBRTRLLE9BQUYsQ0FBVUwsWUFBVixNQUE0QixLQUFoQyxFQUF1QztBQUNyQ0YsSUFBQUEsV0FBVyxDQUFDdEUsTUFBWixDQUFtQndFLFlBQW5CLEdBQWtDQSxZQUFZLENBQUM1RSxHQUFiLENBQy9Ca0YsV0FBRCxJQUErQjtBQUM3QixVQUFJNUosUUFBUSxDQUFDNEosV0FBRCxDQUFaLEVBQTJCO0FBQ3pCQSxRQUFBQSxXQUFXLENBQUNILE1BQVosR0FBcUIsK0JBQW9CRyxXQUFXLENBQUNKLEtBQWhDLEVBQXVDTCxNQUF2QyxDQUFyQjtBQUNELE9BRkQsTUFFTyxJQUFJcEssZ0JBQUVDLFFBQUYsQ0FBVzRLLFdBQVgsQ0FBSixFQUE2QjtBQUNsQ0EsUUFBQUEsV0FBVyxHQUFHO0FBQ1pILFVBQUFBLE1BQU0sRUFBRUMsb0JBREk7QUFFWkYsVUFBQUEsS0FBSyxFQUFFSSxXQUZLO0FBR1ovSyxVQUFBQSxJQUFJLEVBQUUrSztBQUhNLFNBQWQ7QUFLRDs7QUFFRCxhQUFPQSxXQUFQO0FBQ0QsS0FiK0IsQ0FBbEM7QUFlRCxHQXZDK0UsQ0F5Q2hGOzs7QUFDQSxNQUFJN0ssZ0JBQUU0SyxPQUFGLENBQVVKLFdBQVYsTUFBMkIsS0FBL0IsRUFBc0M7QUFDcENILElBQUFBLFdBQVcsQ0FBQ3RFLE1BQVosQ0FBbUJ5RSxXQUFuQixHQUFpQ0EsV0FBVyxDQUFDN0UsR0FBWixDQUFpQm1GLFVBQUQsSUFBc0I7QUFDckVBLE1BQUFBLFVBQVUsQ0FBQ0osTUFBWCxHQUFvQiwrQkFBb0JJLFVBQVUsQ0FBQ0wsS0FBL0IsRUFBc0NMLE1BQXRDLENBQXBCO0FBQ0EsYUFBT1UsVUFBUDtBQUNELEtBSGdDLENBQWpDO0FBSUQ7O0FBRUQsU0FBT1QsV0FBUDtBQUNEO0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDTyxTQUFTVSxXQUFULENBQXFCakIsV0FBckIsRUFBMENrQixNQUExQyxFQUF5RTtBQUM5RSxNQUFJaEwsZ0JBQUU0SyxPQUFGLENBQVVJLE1BQVYsTUFBc0IsS0FBMUIsRUFBaUM7QUFDL0IsV0FBTyxxQkFBZUEsTUFBZixDQUFQO0FBQ0QsR0FINkUsQ0FLOUU7OztBQUNBekYsaUJBQU8wRixLQUFQLENBQWE7QUFBRW5CLElBQUFBO0FBQUYsR0FBYixFQUE4QixpQ0FBOUI7O0FBRUEsU0FBTyxxQkFBZSw4QkFBZixDQUFQO0FBQ0Q7O0FBRU0sU0FBU29CLFVBQVQsQ0FBb0JDLElBQXBCLEVBQWtDQyxLQUFsQyxFQUF5RDtBQUM5RCxTQUFRLEdBQUVwTCxnQkFBRXFMLFVBQUYsQ0FBYUYsSUFBYixDQUFtQixJQUFHQyxLQUFNLEVBQXRDO0FBQ0Q7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDTyxTQUFTRSxxQkFBVCxDQUErQnhMLElBQS9CLEVBQTREO0FBQ2pFO0FBQ0E7QUFDQSxTQUFPLGlCQUFpQnNJLElBQWpCLENBQXNCdEksSUFBdEIsSUFBOEJBLElBQUksQ0FBQ1csS0FBTCxDQUFXLGdCQUFYLEVBQTZCLENBQTdCLENBQTlCLEdBQWdFK0QsU0FBdkU7QUFDRDs7QUFJRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sU0FBUytHLFlBQVQsQ0FBc0JqQixNQUF0QixFQUFpRDtBQUN0RCxNQUFJa0IsYUFBYSxHQUFHO0FBQ2xCMUwsSUFBQUEsSUFBSSxFQUFFMkwsdUJBRFk7QUFFbEJoQixJQUFBQSxLQUFLLEVBQUUsRUFGVztBQUdsQnZJLElBQUFBLEdBQUcsRUFBRTtBQUhhLEdBQXBCOztBQU1BLE1BQUlsQyxnQkFBRW9FLEtBQUYsQ0FBUWtHLE1BQVIsQ0FBSixFQUFxQjtBQUNuQixXQUFPa0IsYUFBUDtBQUNEOztBQUVELE1BQUl4TCxnQkFBRUMsUUFBRixDQUFXcUssTUFBWCxDQUFKLEVBQXdCO0FBQ3RCa0IsSUFBQUEsYUFBYSxtQ0FDUkEsYUFEUTtBQUVYMUwsTUFBQUEsSUFBSSxFQUFFd0s7QUFGSyxNQUFiO0FBSUQ7O0FBRUQsTUFBSXRLLGdCQUFFaUIsUUFBRixDQUFXcUosTUFBWCxDQUFKLEVBQXdCO0FBQ3RCa0IsSUFBQUEsYUFBYSxtQ0FDUkEsYUFEUSxHQUVQbEIsTUFGTyxDQUFiO0FBSUQ7O0FBRUQsU0FBT2tCLGFBQVA7QUFDRDtBQUVEO0FBQ0E7QUFDQTtBQUNBOzs7QUFDTyxTQUFTRSxjQUFULENBQXdCckksR0FBeEIsRUFBOEM7QUFDbkQsU0FBTyxrQkFBa0IrRSxJQUFsQixDQUF1Qi9FLEdBQXZCLENBQVA7QUFDRDtBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNPLFNBQVNzSSxHQUFULENBQWFDLEdBQWIsRUFBa0JDLEdBQWxCLEVBQStCO0FBQ3BDLE1BQUlELEdBQUcsQ0FBQzdLLE1BQUosR0FBYThLLEdBQWpCLEVBQXNCO0FBQ3BCLFdBQU9ELEdBQUcsR0FBRyxJQUFJRSxNQUFKLENBQVdELEdBQUcsR0FBR0QsR0FBRyxDQUFDN0ssTUFBckIsQ0FBYjtBQUNEOztBQUNELFNBQU82SyxHQUFQO0FBQ0Q7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNPLFNBQVNHLElBQVQsQ0FBY0gsR0FBZCxFQUEyQkksT0FBTyxHQUFHLENBQXJDLEVBQWdEO0FBQ3JELFNBQVEsR0FBRUosR0FBRyxDQUFDdkUsTUFBSixDQUFXLENBQVgsRUFBYzJFLE9BQWQsQ0FBdUIsTUFBS0osR0FBRyxDQUFDdkUsTUFBSixDQUFXLENBQUMyRSxPQUFaLENBQXFCLEVBQTNEO0FBQ0Q7O0FBRU0sU0FBU2xJLGVBQVQsQ0FBeUJnRyxXQUF6QixFQUE4QztBQUNuRCxTQUFPQSxXQUFXLENBQUN4SCxPQUFaLENBQW9CLEtBQXBCLEVBQTJCLEtBQTNCLENBQVA7QUFDRDs7QUFFTSxTQUFTMkosYUFBVCxDQUF1QnJKLFFBQXZCLEVBQTBDO0FBQy9DLFNBQU9DLE1BQU0sQ0FBQ21ELElBQVAsQ0FBWXBELFFBQVosRUFBc0I3QixNQUF0QixLQUFpQyxDQUF4QztBQUNEOztBQUVNLFNBQVNtTCxjQUFULENBQXdCQyxXQUF4QixFQUFxQ0MsY0FBckMsRUFBOEQ7QUFDbkUsUUFBTUMsVUFBVSxHQUFHLE9BQU9ELGNBQVAsS0FBMEIsV0FBN0M7O0FBQ0EsTUFBSSxDQUFDQyxVQUFMLEVBQWlCO0FBQ2YsV0FBTyxLQUFQO0FBQ0Q7O0FBRUQsUUFBTUMsZUFBZSxHQUFHekosTUFBTSxDQUFDbUQsSUFBUCxDQUFZbUcsV0FBVyxDQUFDdkosUUFBeEIsRUFBa0NqQyxRQUFsQyxDQUEyQ3lMLGNBQTNDLENBQXhCO0FBQ0EsU0FBT0UsZUFBUDtBQUNEOztBQUVNLFNBQVNDLHNCQUFULENBQWdDaEYsT0FBaEMsRUFBMkQ7QUFDaEUsUUFBTTtBQUFFM0UsSUFBQUE7QUFBRixNQUFlMkUsT0FBckI7O0FBQ0EsT0FBSyxNQUFNM0gsT0FBWCxJQUFzQmdELFFBQXRCLEVBQWdDO0FBQzlCLFFBQUlDLE1BQU0sQ0FBQ0MsU0FBUCxDQUFpQkMsY0FBakIsQ0FBZ0NDLElBQWhDLENBQXFDSixRQUFRLENBQUNoRCxPQUFELENBQTdDLEVBQXdELFlBQXhELENBQUosRUFBMkU7QUFDekUsYUFBTyxJQUFQO0FBQ0Q7QUFDRjs7QUFDRCxTQUFPLEtBQVA7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQHByZXR0aWVyXG4gKi9cbmltcG9ydCBmcyBmcm9tICdmcyc7XG5pbXBvcnQgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgVVJMIGZyb20gJ3VybCc7XG5pbXBvcnQgeyBJbmNvbWluZ0h0dHBIZWFkZXJzIH0gZnJvbSAnaHR0cDInO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCBzZW12ZXIgZnJvbSAnc2VtdmVyJztcbmltcG9ydCBZQU1MIGZyb20gJ2pzLXlhbWwnO1xuaW1wb3J0IHNhbml0aXp5UmVhZG1lIGZyb20gJ0B2ZXJkYWNjaW8vcmVhZG1lJztcblxuaW1wb3J0IHsgUGFja2FnZSwgVmVyc2lvbiwgQXV0aG9yIH0gZnJvbSAnQHZlcmRhY2Npby90eXBlcyc7XG5pbXBvcnQgeyBSZXF1ZXN0IH0gZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQge1xuICBnZXRDb25mbGljdCxcbiAgZ2V0QmFkRGF0YSxcbiAgZ2V0QmFkUmVxdWVzdCxcbiAgZ2V0SW50ZXJuYWxFcnJvcixcbiAgZ2V0VW5hdXRob3JpemVkLFxuICBnZXRGb3JiaWRkZW4sXG4gIGdldFNlcnZpY2VVbmF2YWlsYWJsZSxcbiAgZ2V0Tm90Rm91bmQsXG4gIGdldENvZGVcbn0gZnJvbSAnQHZlcmRhY2Npby9jb21tb25zLWFwaSc7XG5pbXBvcnQgeyBnZW5lcmF0ZUdyYXZhdGFyVXJsLCBHRU5FUklDX0FWQVRBUiB9IGZyb20gJy4uL3V0aWxzL3VzZXInO1xuaW1wb3J0IHsgU3RyaW5nVmFsdWUsIEF1dGhvckF2YXRhciB9IGZyb20gJy4uLy4uL3R5cGVzJztcbmltcG9ydCB7XG4gIEFQUF9FUlJPUixcbiAgREVGQVVMVF9QT1JULFxuICBERUZBVUxUX0RPTUFJTixcbiAgREVGQVVMVF9QUk9UT0NPTCxcbiAgQ0hBUkFDVEVSX0VOQ09ESU5HLFxuICBIRUFERVJTLFxuICBESVNUX1RBR1MsXG4gIERFRkFVTFRfVVNFUlxufSBmcm9tICcuL2NvbnN0YW50cyc7XG5cbmltcG9ydCB7IG5vcm1hbGl6ZUNvbnRyaWJ1dG9ycyB9IGZyb20gJy4vc3RvcmFnZS11dGlscyc7XG5cbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4vbG9nZ2VyJztcblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby12YXItcmVxdWlyZXNcbnJlcXVpcmUoJ3BrZ2luZm8nKShtb2R1bGUpO1xuY29uc3QgcGtnVmVyc2lvbiA9IG1vZHVsZS5leHBvcnRzLnZlcnNpb247XG5jb25zdCBwa2dOYW1lID0gbW9kdWxlLmV4cG9ydHMubmFtZTtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldFVzZXJBZ2VudCgpOiBzdHJpbmcge1xuICBhc3NlcnQoXy5pc1N0cmluZyhwa2dOYW1lKSk7XG4gIGFzc2VydChfLmlzU3RyaW5nKHBrZ1ZlcnNpb24pKTtcbiAgcmV0dXJuIGAke3BrZ05hbWV9LyR7cGtnVmVyc2lvbn1gO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY29udmVydFBheWxvYWRUb0Jhc2U2NChwYXlsb2FkOiBzdHJpbmcpOiBCdWZmZXIge1xuICByZXR1cm4gQnVmZmVyLmZyb20ocGF5bG9hZCwgJ2Jhc2U2NCcpO1xufVxuXG4vKipcbiAqIEZyb20gbm9ybWFsaXplLXBhY2thZ2UtZGF0YS9saWIvZml4ZXIuanNcbiAqIEBwYXJhbSB7Kn0gbmFtZSAgdGhlIHBhY2thZ2UgbmFtZVxuICogQHJldHVybiB7Qm9vbGVhbn0gd2hldGhlciBpcyB2YWxpZCBvciBub3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlTmFtZShuYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgaWYgKF8uaXNTdHJpbmcobmFtZSkgPT09IGZhbHNlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3Qgbm9ybWFsaXplZE5hbWU6IHN0cmluZyA9IG5hbWUudG9Mb3dlckNhc2UoKTtcblxuICAvKipcbiAgICogU29tZSBjb250ZXh0IGFib3V0IHRoZSBmaXJzdCByZWdleFxuICAgKiAtIG5wbSB1c2VkIHRvIGhhdmUgYSBkaWZmZXJlbnQgdGFyYmFsbCBuYW1pbmcgc3lzdGVtLlxuICAgKiBlZzogaHR0cDovL3JlZ2lzdHJ5Lm5wbWpzLmNvbS90aGlydHktdHdvXG4gICAqIGh0dHBzOi8vcmVnaXN0cnkubnBtanMub3JnL3RoaXJ0eS10d28vLS90aGlydHktdHdvQDAuMC4xLnRnelxuICAgKiBUaGUgZmlsZSBuYW1lIHRoaXJ0eS10d29AMC4wLjEudGd6LCB0aGUgdmVyc2lvbiBhbmQgdGhlIHBrZyBuYW1lIHdhcyBzZXBhcmF0ZWQgYnkgYW4gYXQgKEApXG4gICAqIHdoaWxlIG5vd2FkYXlzIHRoZSBuYW1pbmcgc3lzdGVtIGlzIGJhc2VkIGluIGRhc2hlc1xuICAgKiBodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy92ZXJkYWNjaW8vLS92ZXJkYWNjaW8tMS40LjAudGd6XG4gICAqXG4gICAqIG1vcmUgaW5mbyBoZXJlOiBodHRwczovL2dpdGh1Yi5jb20vcmxpZHdrYS9zaW5vcGlhL2lzc3Vlcy83NVxuICAgKi9cbiAgcmV0dXJuICEoXG4gICAgIW5vcm1hbGl6ZWROYW1lLm1hdGNoKC9eWy1hLXpBLVowLTlfLiF+KicoKUBdKyQvKSB8fFxuICAgIG5vcm1hbGl6ZWROYW1lLnN0YXJ0c1dpdGgoJy4nKSB8fCAvLyBcIi5iaW5cIiwgZXRjLlxuICAgIFsnbm9kZV9tb2R1bGVzJywgJ19fcHJvdG9fXycsICdmYXZpY29uLmljbyddLmluY2x1ZGVzKG5vcm1hbGl6ZWROYW1lKVxuICApO1xufVxuXG4vKipcbiAqIFZhbGlkYXRlIGEgcGFja2FnZS5cbiAqIEByZXR1cm4ge0Jvb2xlYW59IHdoZXRoZXIgdGhlIHBhY2thZ2UgaXMgdmFsaWQgb3Igbm90XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZVBhY2thZ2UobmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IG5hbWVMaXN0ID0gbmFtZS5zcGxpdCgnLycsIDIpO1xuICBpZiAobmFtZUxpc3QubGVuZ3RoID09PSAxKSB7XG4gICAgLy8gbm9ybWFsIHBhY2thZ2VcbiAgICByZXR1cm4gdmFsaWRhdGVOYW1lKG5hbWVMaXN0WzBdKTtcbiAgfVxuICAvLyBzY29wZWQgcGFja2FnZVxuICByZXR1cm4gbmFtZUxpc3RbMF1bMF0gPT09ICdAJyAmJiB2YWxpZGF0ZU5hbWUobmFtZUxpc3RbMF0uc2xpY2UoMSkpICYmIHZhbGlkYXRlTmFtZShuYW1lTGlzdFsxXSk7XG59XG5cbi8qKlxuICogQ2hlY2sgd2hldGhlciBhbiBlbGVtZW50IGlzIGFuIE9iamVjdFxuICogQHBhcmFtIHsqfSBvYmogdGhlIGVsZW1lbnRcbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc09iamVjdChvYmo6IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gXy5pc09iamVjdChvYmopICYmIF8uaXNOdWxsKG9iaikgPT09IGZhbHNlICYmIF8uaXNBcnJheShvYmopID09PSBmYWxzZTtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZSB0aGUgcGFja2FnZSBtZXRhZGF0YSwgYWRkIGFkZGl0aW9uYWwgcHJvcGVydGllcyB3aGV0aGVyIGFyZSBtaXNzaW5nIHdpdGhpblxuICogdGhlIG1ldGFkYXRhIHByb3BlcnRpZXMuXG4gKiBAcGFyYW0geyp9IG9iamVjdFxuICogQHBhcmFtIHsqfSBuYW1lXG4gKiBAcmV0dXJuIHtPYmplY3R9IHRoZSBvYmplY3Qgd2l0aCBhZGRpdGlvbmFsIHByb3BlcnRpZXMgYXMgZGlzdC10YWdzIGFkIHZlcnNpb25zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZU1ldGFkYXRhKG9iamVjdDogUGFja2FnZSwgbmFtZTogc3RyaW5nKTogUGFja2FnZSB7XG4gIGFzc2VydChpc09iamVjdChvYmplY3QpLCAnbm90IGEganNvbiBvYmplY3QnKTtcbiAgYXNzZXJ0LnN0cmljdEVxdWFsKG9iamVjdC5uYW1lLCBuYW1lKTtcblxuICBpZiAoIWlzT2JqZWN0KG9iamVjdFtESVNUX1RBR1NdKSkge1xuICAgIG9iamVjdFtESVNUX1RBR1NdID0ge307XG4gIH1cblxuICBpZiAoIWlzT2JqZWN0KG9iamVjdFsndmVyc2lvbnMnXSkpIHtcbiAgICBvYmplY3RbJ3ZlcnNpb25zJ10gPSB7fTtcbiAgfVxuXG4gIGlmICghaXNPYmplY3Qob2JqZWN0Wyd0aW1lJ10pKSB7XG4gICAgb2JqZWN0Wyd0aW1lJ10gPSB7fTtcbiAgfVxuXG4gIHJldHVybiBvYmplY3Q7XG59XG5cbi8qKlxuICogQ3JlYXRlIGJhc2UgdXJsIGZvciByZWdpc3RyeS5cbiAqIEByZXR1cm4ge1N0cmluZ30gYmFzZSByZWdpc3RyeSB1cmxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbWJpbmVCYXNlVXJsKFxuICBwcm90b2NvbDogc3RyaW5nLFxuICBob3N0OiBzdHJpbmcgfCB2b2lkLFxuICBwcmVmaXg/OiBzdHJpbmcgfCB2b2lkXG4pOiBzdHJpbmcge1xuICBjb25zdCByZXN1bHQgPSBgJHtwcm90b2NvbH06Ly8ke2hvc3R9YDtcblxuICBjb25zdCBwcmVmaXhPbmx5U2xhc2ggPSBwcmVmaXggPT09ICcvJztcbiAgaWYgKHByZWZpeCAmJiAhcHJlZml4T25seVNsYXNoKSB7XG4gICAgaWYgKHByZWZpeC5lbmRzV2l0aCgnLycpKSB7XG4gICAgICBwcmVmaXggPSBwcmVmaXguc2xpY2UoMCwgLTEpO1xuICAgIH1cblxuICAgIGlmIChwcmVmaXguc3RhcnRzV2l0aCgnLycpKSB7XG4gICAgICByZXR1cm4gYCR7cmVzdWx0fSR7cHJlZml4fWA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByZWZpeDtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0VGFyYmFsbEZyb21VcmwodXJsOiBzdHJpbmcpOiBzdHJpbmcge1xuICAvLyBAdHMtaWdub3JlXG4gIHJldHVybiBVUkwucGFyc2UodXJsKS5wYXRobmFtZS5yZXBsYWNlKC9eLipcXC8vLCAnJyk7XG59XG5cbi8qKlxuICogSXRlcmF0ZSBhIHBhY2thZ2VzJ3MgdmVyc2lvbnMgYW5kIGZpbHRlciBlYWNoIG9yaWdpbmFsIHRhcmJhbGwgdXJsLlxuICogQHBhcmFtIHsqfSBwa2dcbiAqIEBwYXJhbSB7Kn0gcmVxXG4gKiBAcGFyYW0geyp9IGNvbmZpZ1xuICogQHJldHVybiB7U3RyaW5nfSBhIGZpbHRlcmVkIHBhY2thZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbnZlcnREaXN0UmVtb3RlVG9Mb2NhbFRhcmJhbGxVcmxzKFxuICBwa2c6IFBhY2thZ2UsXG4gIHJlcTogUmVxdWVzdCxcbiAgdXJsUHJlZml4OiBzdHJpbmcgfCB2b2lkXG4pOiBQYWNrYWdlIHtcbiAgZm9yIChjb25zdCB2ZXIgaW4gcGtnLnZlcnNpb25zKSB7XG4gICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChwa2cudmVyc2lvbnMsIHZlcikpIHtcbiAgICAgIGNvbnN0IGRpc3ROYW1lID0gcGtnLnZlcnNpb25zW3Zlcl0uZGlzdDtcblxuICAgICAgaWYgKF8uaXNOdWxsKGRpc3ROYW1lKSA9PT0gZmFsc2UgJiYgXy5pc051bGwoZGlzdE5hbWUudGFyYmFsbCkgPT09IGZhbHNlKSB7XG4gICAgICAgIGRpc3ROYW1lLnRhcmJhbGwgPSBnZXRMb2NhbFJlZ2lzdHJ5VGFyYmFsbFVyaShkaXN0TmFtZS50YXJiYWxsLCBwa2cubmFtZSwgcmVxLCB1cmxQcmVmaXgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gcGtnO1xufVxuXG4vKipcbiAqIEZpbHRlciBhIHRhcmJhbGwgdXJsLlxuICogQHBhcmFtIHsqfSB1cmlcbiAqIEByZXR1cm4ge1N0cmluZ30gYSBwYXJzZWQgdXJsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRMb2NhbFJlZ2lzdHJ5VGFyYmFsbFVyaShcbiAgdXJpOiBzdHJpbmcsXG4gIHBrZ05hbWU6IHN0cmluZyxcbiAgcmVxOiBSZXF1ZXN0LFxuICB1cmxQcmVmaXg6IHN0cmluZyB8IHZvaWRcbik6IHN0cmluZyB7XG4gIGNvbnN0IGN1cnJlbnRIb3N0ID0gcmVxLmhlYWRlcnMuaG9zdDtcblxuICBpZiAoIWN1cnJlbnRIb3N0KSB7XG4gICAgcmV0dXJuIHVyaTtcbiAgfVxuICBjb25zdCB0YXJiYWxsTmFtZSA9IGV4dHJhY3RUYXJiYWxsRnJvbVVybCh1cmkpO1xuICBjb25zdCBoZWFkZXJzID0gcmVxLmhlYWRlcnMgYXMgSW5jb21pbmdIdHRwSGVhZGVycztcbiAgY29uc3QgcHJvdG9jb2wgPSBnZXRXZWJQcm90b2NvbChyZXEuZ2V0KEhFQURFUlMuRk9SV0FSREVEX1BST1RPKSwgcmVxLnByb3RvY29sKTtcbiAgY29uc3QgZG9tYWluUmVnaXN0cnkgPSBjb21iaW5lQmFzZVVybChwcm90b2NvbCwgaGVhZGVycy5ob3N0LCB1cmxQcmVmaXgpO1xuXG4gIHJldHVybiBgJHtkb21haW5SZWdpc3RyeX0vJHtlbmNvZGVTY29wZWRVcmkocGtnTmFtZSl9Ly0vJHt0YXJiYWxsTmFtZX1gO1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIHRhZyBmb3IgYSBwYWNrYWdlXG4gKiBAcGFyYW0geyp9IGRhdGFcbiAqIEBwYXJhbSB7Kn0gdmVyc2lvblxuICogQHBhcmFtIHsqfSB0YWdcbiAqIEByZXR1cm4ge0Jvb2xlYW59IHdoZXRoZXIgYSBwYWNrYWdlIGhhcyBiZWVuIHRhZ2dlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gdGFnVmVyc2lvbihkYXRhOiBQYWNrYWdlLCB2ZXJzaW9uOiBzdHJpbmcsIHRhZzogU3RyaW5nVmFsdWUpOiBib29sZWFuIHtcbiAgaWYgKHRhZyAmJiBkYXRhW0RJU1RfVEFHU11bdGFnXSAhPT0gdmVyc2lv