UNPKG

ngx-hybrid-soap

Version:
352 lines 53.4 kB
/* * Copyright (c) 2011 Vinay Pulim <vinay@milewise.com> * MIT Licensed */ import * as assert from 'assert'; import { findPrefix } from './utils'; import * as _ from 'lodash'; import uuid4 from 'uuid/v4'; import { from, throwError } from 'rxjs'; import { mergeMap, map } from 'rxjs/operators'; import { Multipart } from './multipart'; import { SoapAttachment } from './soapAttachment'; const nonIdentifierChars = /[^a-z$_0-9]/i; export const Client = function (wsdl, endpoint, options) { options = options || {}; this.wsdl = wsdl; this._initializeOptions(options); this._initializeServices(endpoint); this.httpClient = options.httpClient; const promiseOptions = { multiArgs: true }; if (options.overridePromiseSuffix) { promiseOptions.suffix = options.overridePromiseSuffix; } Promise.all([this, promiseOptions]); }; Client.prototype.addSoapHeader = function (soapHeader, name, namespace, xmlns) { if (!this.soapHeaders) { this.soapHeaders = []; } if (typeof soapHeader === 'object') { soapHeader = this.wsdl.objectToXML(soapHeader, name, namespace, xmlns, true); } return this.soapHeaders.push(soapHeader) - 1; }; Client.prototype.changeSoapHeader = function (index, soapHeader, name, namespace, xmlns) { if (!this.soapHeaders) { this.soapHeaders = []; } if (typeof soapHeader === 'object') { soapHeader = this.wsdl.objectToXML(soapHeader, name, namespace, xmlns, true); } this.soapHeaders[index] = soapHeader; }; Client.prototype.getSoapHeaders = function () { return this.soapHeaders; }; Client.prototype.clearSoapHeaders = function () { this.soapHeaders = null; }; Client.prototype.addHttpHeader = function (name, value) { if (!this.httpHeaders) { this.httpHeaders = {}; } this.httpHeaders[name] = value; }; Client.prototype.getHttpHeaders = function () { return this.httpHeaders; }; Client.prototype.clearHttpHeaders = function () { this.httpHeaders = {}; }; Client.prototype.addBodyAttribute = function (bodyAttribute, name, namespace, xmlns) { if (!this.bodyAttributes) { this.bodyAttributes = []; } if (typeof bodyAttribute === 'object') { let composition = ''; Object.getOwnPropertyNames(bodyAttribute).forEach(function (prop, idx, array) { composition += ' ' + prop + '="' + bodyAttribute[prop] + '"'; }); bodyAttribute = composition; } if (bodyAttribute.substr(0, 1) !== ' ') bodyAttribute = ' ' + bodyAttribute; this.bodyAttributes.push(bodyAttribute); }; Client.prototype.getBodyAttributes = function () { return this.bodyAttributes; }; Client.prototype.clearBodyAttributes = function () { this.bodyAttributes = null; }; Client.prototype.setEndpoint = function (endpoint) { this.endpoint = endpoint; this._initializeServices(endpoint); }; Client.prototype.describe = function () { const types = this.wsdl.definitions.types; return this.wsdl.describeServices(); }; Client.prototype.setSecurity = function (security) { this.security = security; }; Client.prototype.setSOAPAction = function (SOAPAction) { this.SOAPAction = SOAPAction; }; Client.prototype._initializeServices = function (endpoint) { const definitions = this.wsdl.definitions, services = definitions.services; for (const name in services) { this[name] = this._defineService(services[name], endpoint); } }; Client.prototype._initializeOptions = function (options) { this.streamAllowed = options.stream; this.normalizeNames = options.normalizeNames; this.wsdl.options.attributesKey = options.attributesKey || 'attributes'; this.wsdl.options.envelopeKey = options.envelopeKey || 'soap'; this.wsdl.options.preserveWhitespace = !!options.preserveWhitespace; if (options.ignoredNamespaces !== undefined) { if (options.ignoredNamespaces.override !== undefined) { if (options.ignoredNamespaces.override === true) { if (options.ignoredNamespaces.namespaces !== undefined) { this.wsdl.options.ignoredNamespaces = options.ignoredNamespaces.namespaces; } } } } if (options.overrideRootElement !== undefined) { this.wsdl.options.overrideRootElement = options.overrideRootElement; } this.wsdl.options.forceSoap12Headers = !!options.forceSoap12Headers; }; Client.prototype._defineService = function (service, endpoint) { const ports = service.ports, def = {}; for (const name in ports) { def[name] = this._definePort(ports[name], endpoint ? endpoint : ports[name].location); } return def; }; Client.prototype._definePort = function (port, endpoint) { const location = endpoint, binding = port.binding, methods = binding.methods, def = {}; for (const name in methods) { def[name] = this._defineMethod(methods[name], location); const methodName = this.normalizeNames ? name.replace(nonIdentifierChars, '_') : name; this[methodName] = def[name]; } return def; }; Client.prototype._defineMethod = function (method, location) { const self = this; let temp = null; return function (args, options, extraHeaders) { return self._invoke(method, args, location, options, extraHeaders); }; }; Client.prototype._invoke = function (method, args, location, options, extraHeaders) { let self = this, name = method.$name, input = method.input, output = method.output, style = method.style, defs = this.wsdl.definitions, envelopeKey = this.wsdl.options.envelopeKey, ns = defs.$targetNamespace, encoding = '', message = '', xml = null, req = null, soapAction = null, alias = findPrefix(defs.xmlns, ns), headers = { 'Content-Type': 'text/xml; charset=utf-8' }, xmlnsSoap = 'xmlns:' + envelopeKey + '="http://schemas.xmlsoap.org/soap/envelope/"'; if (this.wsdl.options.forceSoap12Headers) { headers['Content-Type'] = 'application/soap+xml; charset=utf-8'; xmlnsSoap = 'xmlns:' + envelopeKey + '="http://www.w3.org/2003/05/soap-envelope"'; } if (this.SOAPAction) { soapAction = this.SOAPAction; } else if (method.soapAction !== undefined && method.soapAction !== null) { soapAction = method.soapAction; } else { soapAction = (ns.lastIndexOf('/') !== ns.length - 1 ? ns + '/' : ns) + name; } if (!this.wsdl.options.forceSoap12Headers) { headers.SOAPAction = '"' + soapAction + '"'; } options = options || {}; //Add extra headers for (const header in this.httpHeaders) { headers[header] = this.httpHeaders[header]; } for (const attr in extraHeaders) { headers[attr] = extraHeaders[attr]; } // Allow the security object to add headers if (self.security && self.security.addHeaders) self.security.addHeaders(headers); if (self.security && self.security.addOptions) self.security.addOptions(options); if (style === 'rpc' && (input.parts || input.name === 'element' || args === null)) { assert.ok(!style || style === 'rpc', 'invalid message definition for document style binding'); message = self.wsdl.objectToRpcXML(name, args, alias, ns, input.name !== 'element'); method.inputSoap === 'encoded' && (encoding = 'soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" '); } else { assert.ok(!style || style === 'document', 'invalid message definition for rpc style binding'); // pass `input.$lookupType` if `input.$type` could not be found message = self.wsdl.objectToDocumentXML(input.$name, args, input.targetNSAlias, input.targetNamespace, input.$type || input.$lookupType); } xml = '<?xml version="1.0" encoding="utf-8"?>' + '<' + envelopeKey + ':Envelope ' + xmlnsSoap + ' ' + 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' + encoding + this.wsdl.xmlnsInEnvelope + '>' + (self.soapHeaders || self.security ? '<' + envelopeKey + ':Header>' + (self.soapHeaders ? self.soapHeaders.join('\n') : '') + (self.security && !self.security.postProcess ? self.security.toXML() : '') + '</' + envelopeKey + ':Header>' : '') + '<' + envelopeKey + ':Body' + (self.bodyAttributes ? self.bodyAttributes.join(' ') : '') + (self.security && self.security.postProcess ? ' Id="_0"' : '') + '>' + message + '</' + envelopeKey + ':Body>' + '</' + envelopeKey + ':Envelope>'; if (self.security && self.security.postProcess) { xml = self.security.postProcess(xml, envelopeKey); } if (options && options.postProcess) { xml = options.postProcess(xml); } self.lastMessage = message; self.lastRequest = xml; self.lastEndpoint = location; const tryJSONparse = function (body) { try { return JSON.parse(body); } catch (err) { return undefined; } }; return from(SoapAttachment.fromFormFiles(options.attachments)).pipe(map((soapAttachments) => { if (!soapAttachments.length) { return xml; } if (options.forceMTOM || soapAttachments.length > 0) { const start = uuid4(); const boundry = uuid4(); let action = null; if (headers['Content-Type'].indexOf('action') > -1) { for (const ct of headers['Content-Type'].split('; ')) { if (ct.indexOf('action') > -1) { action = ct; } } } headers['Content-Type'] = 'multipart/related; type="application/xop+xml"; start="<' + start + '>"; start-info="text/xml"; boundary="' + boundry + '"'; if (action) { headers['Content-Type'] = headers['Content-Type'] + '; ' + action; } const multipart = [ { 'Content-Type': 'application/xop+xml; charset=UTF-8; type="text/xml"', 'Content-ID': '<' + start + '>', body: xml } ]; soapAttachments.forEach((attachment) => { multipart.push({ 'Content-Type': attachment.mimetype + ';', 'Content-Transfer-Encoding': 'binary', 'Content-ID': '<' + (attachment.contentId || attachment.name) + '>', 'Content-Disposition': 'attachment; name="' + attachment.name + '"; filename="' + attachment.name + '"', body: attachment.body }); }); return new Multipart().build(multipart, boundry); } }), mergeMap((body) => (self.httpClient) .post(location, body, { headers: headers, responseType: 'text', observe: 'response' }) .pipe(map((response) => { self.lastResponse = response.body; self.lastResponseHeaders = response && response.headers; return parseSync(response.body, response); })))); function parseSync(body, response) { let obj; try { obj = self.wsdl.xmlToObject(body); } catch (error) { // When the output element cannot be looked up in the wsdl and the body is JSON // instead of sending the error, we pass the body in the response. if (!output || !output.$lookupTypes) { // debug('Response element is not present. Unable to convert response xml to json.'); // If the response is JSON then return it as-is. const json = _.isObject(body) ? body : tryJSONparse(body); if (json) { return { err: null, response, responseBody: json, header: undefined, xml }; } } error.response = response; error.body = body; // self.emit('soapError', error, eid); throw error; } return finish(obj, body, response); } function finish(obj, responseBody, response) { let result = null; if (!output) { // one-way, no output expected return { err: null, response: null, responseBody, header: obj.Header, xml }; } // If it's not HTML and Soap Body is empty if (!obj.html && !obj.Body) { return { err: null, obj, responseBody, header: obj.Header, xml }; } if (typeof obj.Body !== 'object') { const error = new Error('Cannot parse response'); error.response = response; error.body = responseBody; return { err: error, obj, responseBody, header: undefined, xml }; } result = obj.Body[output.$name]; // RPC/literal response body may contain elements with added suffixes I.E. // 'Response', or 'Output', or 'Out' // This doesn't necessarily equal the ouput message name. See WSDL 1.1 Section 2.4.5 if (!result) { result = obj.Body[output.$name.replace(/(?:Out(?:put)?|Response)$/, '')]; } if (!result) { ['Response', 'Out', 'Output'].forEach(function (term) { if (obj.Body.hasOwnProperty(name + term)) { return (result = obj.Body[name + term]); } }); } return { err: null, result, responseBody, header: obj.Header, xml }; } }; Client.prototype.call = function (method, body, options, extraHeaders) { // console.log('call', method); if (!this[method]) { return throwError(`Method ${method} not found`); } return this[method].call(this, body, options, extraHeaders); }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNvYXAvc3JjL2xpYi9zb2FwL2NsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFHSCxPQUFPLEtBQUssTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUNqQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3JDLE9BQU8sS0FBSyxDQUFDLE1BQU0sUUFBUSxDQUFDO0FBQzVCLE9BQU8sS0FBSyxNQUFNLFNBQVMsQ0FBQztBQUM1QixPQUFPLEVBQUUsSUFBSSxFQUFjLFVBQVUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNwRCxPQUFPLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDeEMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRWxELE1BQU0sa0JBQWtCLEdBQUcsY0FBYyxDQUFDO0FBRTFDLE1BQU0sQ0FBQyxNQUFNLE1BQU0sR0FBRyxVQUFTLElBQUksRUFBRSxRQUFRLEVBQUUsT0FBTztJQUNsRCxPQUFPLEdBQUcsT0FBTyxJQUFJLEVBQUUsQ0FBQztJQUN4QixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztJQUNqQixJQUFJLENBQUMsa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDakMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ25DLElBQUksQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQXdCLENBQUM7SUFDbkQsTUFBTSxjQUFjLEdBQVEsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUM7SUFDaEQsSUFBSSxPQUFPLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUNoQyxjQUFjLENBQUMsTUFBTSxHQUFHLE9B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SUFBSSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUM7b0JBQ3ZDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztnQkFDNUMsQ0FBQztZQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQztRQUVELE9BQU8sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUM7SUFDeEUsQ0FBQztBQUNMLENBQUMsQ0FBQztBQUVGLE1BQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxHQUFHLFVBQVMsTUFBYyxFQUFFLElBQVMsRUFBRSxPQUFhLEVBQUUsWUFBa0I7SUFDekYsK0JBQStCO0lBRS9CLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUNoQixPQUFPLFVBQVUsQ0FBQyxVQUFVLE1BQU0sWUFBWSxDQUFDLENBQUM7SUFDcEQsQ0FBQztJQUVELE9BQWtCLElBQUksQ0FBQyxNQUFNLENBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFDNUUsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoYykgMjAxMSBWaW5heSBQdWxpbSA8dmluYXlAbWlsZXdpc2UuY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuaW1wb3J0IHsgSHR0cENsaWVudCwgSHR0cFJlc3BvbnNlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0ICogYXMgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgeyBmaW5kUHJlZml4IH0gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgdXVpZDQgZnJvbSAndXVpZC92NCc7XG5pbXBvcnQgeyBmcm9tLCBPYnNlcnZhYmxlLCB0aHJvd0Vycm9yIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBtZXJnZU1hcCwgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgTXVsdGlwYXJ0IH0gZnJvbSAnLi9tdWx0aXBhcnQnO1xuaW1wb3J0IHsgU29hcEF0dGFjaG1lbnQgfSBmcm9tICcuL3NvYXBBdHRhY2htZW50JztcblxuY29uc3Qgbm9uSWRlbnRpZmllckNoYXJzID0gL1teYS16JF8wLTldL2k7XG5cbmV4cG9ydCBjb25zdCBDbGllbnQgPSBmdW5jdGlvbih3c2RsLCBlbmRwb2ludCwgb3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICAgIHRoaXMud3NkbCA9IHdzZGw7XG4gICAgdGhpcy5faW5pdGlhbGl6ZU9wdGlvbnMob3B0aW9ucyk7XG4gICAgdGhpcy5faW5pdGlhbGl6ZVNlcnZpY2VzKGVuZHBvaW50KTtcbiAgICB0aGlzLmh0dHBDbGllbnQgPSBvcHRpb25zLmh0dHBDbGllbnQgYXMgSHR0cENsaWVudDtcbiAgICBjb25zdCBwcm9taXNlT3B0aW9uczogYW55ID0geyBtdWx0aUFyZ3M6IHRydWUgfTtcbiAgICBpZiAob3B0aW9ucy5vdmVycmlkZVByb21pc2VTdWZmaXgpIHtcbiAgICAgICAgcHJvbWlzZU9wdGlvbnMuc3VmZml4ID0gb3B0aW9ucy5vdmVycmlkZVByb21pc2VTdWZmaXg7XG4gICAgfVxuICAgIFByb21pc2UuYWxsKFt0aGlzLCBwcm9taXNlT3B0aW9uc10pO1xufTtcblxuQ2xpZW50LnByb3RvdHlwZS5hZGRTb2FwSGVhZGVyID0gZnVuY3Rpb24oc29hcEhlYWRlciwgbmFtZSwgbmFtZXNwYWNlLCB4bWxucykge1xuICAgIGlmICghdGhpcy5zb2FwSGVhZGVycykge1xuICAgICAgICB0aGlzLnNvYXBIZWFkZXJzID0gW107XG4gICAgfVxuICAgIGlmICh0eXBlb2Ygc29hcEhlYWRlciA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgc29hcEhlYWRlciA9IHRoaXMud3NkbC5vYmplY3RUb1hNTChzb2FwSGVhZGVyLCBuYW1lLCBuYW1lc3BhY2UsIHhtbG5zLCB0cnVlKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc29hcEhlYWRlcnMucHVzaChzb2FwSGVhZGVyKSAtIDE7XG59O1xuXG5DbGllbnQucHJvdG90eXBlLmNoYW5nZVNvYXBIZWFkZXIgPSBmdW5jdGlvbihpbmRleCwgc29hcEhlYWRlciwgbmFtZSwgbmFtZXNwYWNlLCB4bWxucykge1xuICAgIGlmICghdGhpcy5zb2FwSGVhZGVycykge1xuICAgICAgICB0aGlzLnNvYXBIZWFkZXJzID0gW107XG4gICAgfVxuICAgIGlmICh0eXBlb2Ygc29hcEhlYWRlciA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgc29hcEhlYWRlciA9IHRoaXMud3NkbC5vYmplY3RUb1hNTChzb2FwSGVhZGVyLCBuYW1lLCBuYW1lc3BhY2UsIHhtbG5zLCB0cnVlKTtcbiAgICB9XG4gICAgdGhpcy5zb2FwSGVhZGVyc1tpbmRleF0gPSBzb2FwSGVhZGVyO1xufTtcblxuQ2xpZW50LnByb3RvdHlwZS5nZXRTb2FwSGVhZGVycyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnNvYXBIZWFkZXJzO1xufTtcblxuQ2xpZW50LnByb3RvdHlwZS5jbGVhclNvYXBIZWFkZXJzID0gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5zb2FwSGVhZGVycyA9IG51bGw7XG59O1xuXG5DbGllbnQucHJvdG90eXBlLmFkZEh0dHBIZWFkZXIgPSBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICAgIGlmICghdGhpcy5odHRwSGVhZGVycykge1xuICAgICAgICB0aGlzLmh0dHBIZWFkZXJzID0ge307XG4gICAgfVxuICAgIHRoaXMuaHR0cEhlYWRlcnNbbmFtZV0gPSB2YWx1ZTtcbn07XG5cbkNsaWVudC5wcm90b3R5cGUuZ2V0SHR0cEhlYWRlcnMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5odHRwSGVhZGVycztcbn07XG5cbkNsaWVudC5wcm90b3R5cGUuY2xlYXJIdHRwSGVhZGVycyA9IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuaHR0cEhlYWRlcnMgPSB7fTtcbn07XG5cbkNsaWVudC5wcm90b3R5cGUuYWRkQm9keUF0dHJpYnV0ZSA9IGZ1bmN0aW9uKGJvZHlBdHRyaWJ1dGUsIG5hbWUsIG5hbWVzcGFjZSwgeG1sbnMpIHtcbiAgICBpZiAoIXRoaXMuYm9keUF0dHJpYnV0ZXMpIHtcbiAgICAgICAgdGhpcy5ib2R5QXR0cmlidXRlcyA9IFtdO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGJvZHlBdHRyaWJ1dGUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIGxldCBjb21wb3NpdGlvbiA9ICcnO1xuICAgICAgICBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhib2R5QXR0cmlidXRlKS5mb3JFYWNoKGZ1bmN0aW9uKHByb3AsIGlkeCwgYXJyYXkpIHtcbiAgICAgICAgICAgIGNvbXBvc2l0aW9uICs9ICcgJyArIHByb3AgKyAnPVwiJyArIGJvZHlBdHRyaWJ1dGVbcHJvcF0gKyAnXCInO1xuICAgICAgICB9KTtcbiAgICAgICAgYm9keUF0dHJpYnV0ZSA9IGNvbXBvc2l0aW9uO1xuICAgIH1cbiAgICBpZiAoYm9keUF0dHJpYnV0ZS5zdWJzdHIoMCwgMSkgIT09ICcgJykgYm9keUF0dHJpYnV0ZSA9ICcgJyArIGJvZHlBdHRyaWJ1dGU7XG4gICAgdGhpcy5ib2R5QXR0cmlidXRlcy5wdXNoKGJvZHlBdHRyaWJ1dGUpO1xufTtcblxuQ2xpZW50LnByb3RvdHlwZS5nZXRCb2R5QXR0cmlidXRlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmJvZHlBdHRyaWJ1dGVzO1xufTtcblxuQ2xpZW50LnByb3RvdHlwZS5jbGVhckJvZHlBdHRyaWJ1dGVzID0gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5ib2R5QXR0cmlidXRlcyA9IG51bGw7XG59O1xuXG5DbGllbnQucHJvdG90eXBlLnNldEVuZHBvaW50ID0gZnVuY3Rpb24oZW5kcG9pbnQpIHtcbiAgICB0aGlzLmVuZHBvaW50ID0gZW5kcG9pbnQ7XG4gICAgdGhpcy5faW5pdGlhbGl6ZVNlcnZpY2VzKGVuZHBvaW50KTtcbn07XG5cbkNsaWVudC5wcm90b3R5cGUuZGVzY3JpYmUgPSBmdW5jdGlvbigpIHtcbiAgICBjb25zdCB0eXBlcyA9IHRoaXMud3NkbC5kZWZpbml0aW9ucy50eXBlcztcbiAgICByZXR1cm4gdGhpcy53c2RsLmRlc2NyaWJlU2VydmljZXMoKTtcbn07XG5cbkNsaWVudC5wcm90b3R5cGUuc2V0U2VjdXJpdHkgPSBmdW5jdGlvbihzZWN1cml0eSkge1xuICAgIHRoaXMuc2VjdXJpdHkgPSBzZWN1cml0eTtcbn07XG5cbkNsaWVudC5wcm90b3R5cGUuc2V0U09BUEFjdGlvbiA9IGZ1bmN0aW9uKFNPQVBBY3Rpb24pIHtcbiAgICB0aGlzLlNPQVBBY3Rpb24gPSBTT0FQQWN0aW9uO1xufTtcblxuQ2xpZW50LnByb3RvdHlwZS5faW5pdGlhbGl6ZVNlcnZpY2VzID0gZnVuY3Rpb24oZW5kcG9pbnQpIHtcbiAgICBjb25zdCBkZWZpbml0aW9ucyA9IHRoaXMud3NkbC5kZWZpbml0aW9ucyxcbiAgICAgICAgc2VydmljZXMgPSBkZWZpbml0aW9ucy5zZXJ2aWNlcztcbiAgICBmb3IgKGNvbnN0IG5hbWUgaW4gc2VydmljZXMpIHtcbiAgICAgICAgdGhpc1tuYW1lXSA9IHRoaXMuX2RlZmluZVNlcnZpY2Uoc2VydmljZXNbbmFtZV0sIGVuZHBvaW50KTtcbiAgICB9XG59O1xuXG5DbGllbnQucHJvdG90eXBlLl9pbml0aWFsaXplT3B0aW9ucyA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICB0aGlzLnN0cmVhbUFsbG93ZWQgPSBvcHRpb25zLnN0cmVhbTtcbiAgICB0aGlzLm5vcm1hbGl6ZU5hbWVzID0gb3B0aW9ucy5ub3JtYWxpemVOYW1lcztcbiAgICB0aGlzLndzZGwub3B0aW9ucy5hdHRyaWJ1dGVzS2V5ID0gb3B0aW9ucy5hdHRyaWJ1dGVzS2V5IHx8ICdhdHRyaWJ1dGVzJztcbiAgICB0aGlzLndzZGwub3B0aW9ucy5lbnZlbG9wZUtleSA9IG9wdGlvbnMuZW52ZWxvcGVLZXkgfHwgJ3NvYXAnO1xuICAgIHRoaXMud3NkbC5vcHRpb25zLnByZXNlcnZlV2hpdGVzcGFjZSA9ICEhb3B0aW9ucy5wcmVzZXJ2ZVdoaXRlc3BhY2U7XG4gICAgaWYgKG9wdGlvbnMuaWdub3JlZE5hbWVzcGFjZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAob3B0aW9ucy5pZ25vcmVkTmFtZXNwYWNlcy5vdmVycmlkZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5pZ25vcmVkTmFtZXNwYWNlcy5vdmVycmlkZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmlnbm9yZWROYW1lc3BhY2VzLm5hbWVzcGFjZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndzZGwub3B0aW9ucy5pZ25vcmVkTmFtZXNwYWNlcyA9IG9wdGlvbnMuaWdub3JlZE5hbWVzcGFjZXMubmFtZXNwYWNlcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKG9wdGlvbnMub3ZlcnJpZGVSb290RWxlbWVudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMud3NkbC5vcHRpb25zLm92ZXJyaWRlUm9vdEVsZW1lbnQgPSBvcHRpb25zLm92ZXJyaWRlUm9vdEVsZW1lbnQ7XG4gICAgfVxuICAgIHRoaXMud3NkbC5vcHRpb25zLmZvcmNlU29hcDEySGVhZGVycyA9ICEhb3B0aW9ucy5mb3JjZVNvYXAxMkhlYWRlcnM7XG59O1xuXG5DbGllbnQucHJvdG90eXBlLl9kZWZpbmVTZXJ2aWNlID0gZnVuY3Rpb24oc2VydmljZSwgZW5kcG9pbnQpIHtcbiAgICBjb25zdCBwb3J0cyA9IHNlcnZpY2UucG9ydHMsXG4gICAgICAgIGRlZiA9IHt9O1xuICAgIGZvciAoY29uc3QgbmFtZSBpbiBwb3J0cykge1xuICAgICAgICBkZWZbbmFtZV0gPSB0aGlzLl9kZWZpbmVQb3J0KHBvcnRzW25hbWVdLCBlbmRwb2ludCA/IGVuZHBvaW50IDogcG9ydHNbbmFtZV0ubG9jYXRpb24pO1xuICAgIH1cbiAgICByZXR1cm4gZGVmO1xufTtcblxuQ2xpZW50LnByb3RvdHlwZS5fZGVmaW5lUG9ydCA9IGZ1bmN0aW9uKHBvcnQsIGVuZHBvaW50KSB7XG4gICAgY29uc3QgbG9jYXRpb24gPSBlbmRwb2ludCxcbiAgICAgICAgYmluZGluZyA9IHBvcnQuYmluZGluZyxcbiAgICAgICAgbWV0aG9kcyA9IGJpbmRpbmcubWV0aG9kcyxcbiAgICAgICAgZGVmID0ge307XG4gICAgZm9yIChjb25zdCBuYW1lIGluIG1ldGhvZHMpIHtcbiAgICAgICAgZGVmW25hbWVdID0gdGhpcy5fZGVmaW5lTWV0aG9kKG1ldGhvZHNbbmFtZV0sIGxvY2F0aW9uKTtcbiAgICAgICAgY29uc3QgbWV0aG9kTmFtZSA9IHRoaXMubm9ybWFsaXplTmFtZXMgPyBuYW1lLnJlcGxhY2Uobm9uSWRlbnRpZmllckNoYXJzLCAnXycpIDogbmFtZTtcbiAgICAgICAgdGhpc1ttZXRob2ROYW1lXSA9IGRlZltuYW1lXTtcbiAgICB9XG4gICAgcmV0dXJuIGRlZjtcbn07XG5cbkNsaWVudC5wcm90b3R5cGUuX2RlZmluZU1ldGhvZCA9IGZ1bmN0aW9uKG1ldGhvZCwgbG9jYXRpb24pIHtcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBsZXQgdGVtcCA9IG51bGw7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGFyZ3MsIG9wdGlvbnMsIGV4dHJhSGVhZGVycyk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgICAgIHJldHVybiBzZWxmLl9pbnZva2UobWV0aG9kLCBhcmdzLCBsb2NhdGlvbiwgb3B0aW9ucywgZXh0cmFIZWFkZXJzKTtcbiAgICB9O1xufTtcblxuQ2xpZW50LnByb3RvdHlwZS5faW52b2tlID0gZnVuY3Rpb24obWV0aG9kLCBhcmdzLCBsb2NhdGlvbiwgb3B0aW9ucywgZXh0cmFIZWFkZXJzKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICBsZXQgc2VsZiA9IHRoaXMsXG4gICAgICAgIG5hbWUgPSBtZXRob2QuJG5hbWUsXG4gICAgICAgIGlucHV0ID0gbWV0aG9kLmlucHV0LFxuICAgICAgICBvdXRwdXQgPSBtZXRob2Qub3V0cHV0LFxuICAgICAgICBzdHlsZSA9IG1ldGhvZC5zdHlsZSxcbiAgICAgICAgZGVmcyA9IHRoaXMud3NkbC5kZWZpbml0aW9ucyxcbiAgICAgICAgZW52ZWxvcGVLZXkgPSB0aGlzLndzZGwub3B0aW9ucy5lbnZlbG9wZUtleSxcbiAgICAgICAgbnMgPSBkZWZzLiR0YXJnZXROYW1lc3BhY2UsXG4gICAgICAgIGVuY29kaW5nID0gJycsXG4gICAgICAgIG1lc3NhZ2UgPSAnJyxcbiAgICAgICAgeG1sID0gbnVsbCxcbiAgICAgICAgcmVxID0gbnVsbCxcbiAgICAgICAgc29hcEFjdGlvbiA9IG51bGwsXG4gICAgICAgIGFsaWFzID0gZmluZFByZWZpeChkZWZzLnhtbG5zLCBucyksXG4gICAgICAgIGhlYWRlcnM6IGFueSA9IHtcbiAgICAgICAgICAgICdDb250ZW50LVR5cGUnOiAndGV4dC94bWw7IGNoYXJzZXQ9dXRmLTgnXG4gICAgICAgIH0sXG4gICAgICAgIHhtbG5zU29hcCA9ICd4bWxuczonICsgZW52ZWxvcGVLZXkgKyAnPVwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvc29hcC9lbnZlbG9wZS9cIic7XG5cbiAgICBpZiAodGhpcy53c2RsLm9wdGlvbnMuZm9yY2VTb2FwMTJIZWFkZXJzKSB7XG4gICAgICAgIGhlYWRlcnNbJ0NvbnRlbnQtVHlwZSddID0gJ2FwcGxpY2F0aW9uL3NvYXAreG1sOyBjaGFyc2V0PXV0Zi04JztcbiAgICAgICAgeG1sbnNTb2FwID0gJ3htbG5zOicgKyBlbnZlbG9wZUtleSArICc9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAzLzA1L3NvYXAtZW52ZWxvcGVcIic7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuU09BUEFjdGlvbikge1xuICAgICAgICBzb2FwQWN0aW9uID0gdGhpcy5TT0FQQWN0aW9uO1xuICAgIH0gZWxzZSBpZiAobWV0aG9kLnNvYXBBY3Rpb24gIT09IHVuZGVmaW5lZCAmJiBtZXRob2Quc29hcEFjdGlvbiAhPT0gbnVsbCkge1xuICAgICAgICBzb2FwQWN0aW9uID0gbWV0aG9kLnNvYXBBY3Rpb247XG4gICAgfSBlbHNlIHtcbiAgICAgICAgc29hcEFjdGlvbiA9IChucy5sYXN0SW5kZXhPZignLycpICE9PSBucy5sZW5ndGggLSAxID8gbnMgKyAnLycgOiBucykgKyBuYW1lO1xuICAgIH1cblxuICAgIGlmICghdGhpcy53c2RsLm9wdGlvbnMuZm9yY2VTb2FwMTJIZWFkZXJzKSB7XG4gICAgICAgIGhlYWRlcnMuU09BUEFjdGlvbiA9ICdcIicgKyBzb2FwQWN0aW9uICsgJ1wiJztcbiAgICB9XG5cbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICAgIC8vQWRkIGV4dHJhIGhlYWRlcnNcbiAgICBmb3IgKGNvbnN0IGhlYWRlciBpbiB0aGlzLmh0dHBIZWFkZXJzKSB7XG4gICAgICAgIGhlYWRlcnNbaGVhZGVyXSA9IHRoaXMuaHR0cEhlYWRlcnNbaGVhZGVyXTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBhdHRyIGluIGV4dHJhSGVhZGVycykge1xuICAgICAgICBoZWFkZXJzW2F0dHJdID0gZXh0cmFIZWFkZXJzW2F0dHJdO1xuICAgIH1cblxuICAgIC8vIEFsbG93IHRoZSBzZWN1cml0eSBvYmplY3QgdG8gYWRkIGhlYWRlcnNcbiAgICBpZiAoc2VsZi5zZWN1cml0eSAmJiBzZWxmLnNlY3VyaXR5LmFkZEhlYWRlcnMpIHNlbGYuc2VjdXJpdHkuYWRkSGVhZGVycyhoZWFkZXJzKTtcbiAgICBpZiAoc2VsZi5zZWN1cml0eSAmJiBzZWxmLnNlY3VyaXR5LmFkZE9wdGlvbnMpIHNlbGYuc2VjdXJpdHkuYWRkT3B0aW9ucyhvcHRpb25zKTtcblxuICAgIGlmIChzdHlsZSA9PT0gJ3JwYycgJiYgKGlucHV0LnBhcnRzIHx8IGlucHV0Lm5hbWUgPT09ICdlbGVtZW50JyB8fCBhcmdzID09PSBudWxsKSkge1xuICAgICAgICBhc3NlcnQub2soIXN0eWxlIHx8IHN0eWxlID09PSAncnBjJywgJ2ludmFsaWQgbWVzc2FnZSBkZWZpbml0aW9uIGZvciBkb2N1bWVudCBzdHlsZSBiaW5kaW5nJyk7XG4gICAgICAgIG1lc3NhZ2UgPSBzZWxmLndzZGwub2JqZWN0VG9ScGNYTUwobmFtZSwgYXJncywgYWxpYXMsIG5zLCBpbnB1dC5uYW1lICE9PSAnZWxlbWVudCcpO1xuICAgICAgICBtZXRob2QuaW5wdXRTb2FwID09PSAnZW5jb2RlZCcgJiYgKGVuY29kaW5nID0gJ3NvYXA6ZW5jb2RpbmdTdHlsZT1cImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3NvYXAvZW5jb2RpbmcvXCIgJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYXNzZXJ0Lm9rKCFzdHlsZSB8fCBzdHlsZSA9PT0gJ2RvY3VtZW50JywgJ2ludmFsaWQgbWVzc2FnZSBkZWZpbml0aW9uIGZvciBycGMgc3R5bGUgYmluZGluZycpO1xuICAgICAgICAvLyBwYXNzIGBpbnB1dC4kbG9va3VwVHlwZWAgaWYgYGlucHV0LiR0eXBlYCBjb3VsZCBub3QgYmUgZm91bmRcbiAgICAgICAgbWVzc2FnZSA9IHNlbGYud3NkbC5vYmplY3RUb0RvY3VtZW50WE1MKGlucHV0LiRuYW1lLCBhcmdzLCBpbnB1dC50YXJnZXROU0FsaWFzLCBpbnB1dC50YXJnZXROYW1lc3BhY2UsIGlucHV0LiR0eXBlIHx8IGlucHV0LiRsb29rdXBUeXBlKTtcbiAgICB9XG4gICAgeG1sID1cbiAgICAgICAgJzw/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cInV0Zi04XCI/PicgK1xuICAgICAgICAnPCcgK1xuICAgICAgICBlbnZlbG9wZUtleSArXG4gICAgICAgICc6RW52ZWxvcGUgJyArXG4gICAgICAgIHhtbG5zU29hcCArXG4gICAgICAgICcgJyArXG4gICAgICAgICd4bWxuczp4c2k9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZVwiICcgK1xuICAgICAgICBlbmNvZGluZyArXG4gICAgICAgIHRoaXMud3NkbC54bWxuc0luRW52ZWxvcGUgK1xuICAgICAgICAnPicgK1xuICAgICAgICAoc2VsZi5zb2FwSGVhZGVycyB8fCBzZWxmLnNlY3VyaXR5XG4gICAgICAgICAgICA/ICc8JyArXG4gICAgICAgICAgICAgIGVudmVsb3BlS2V5ICtcbiAgICAgICAgICAgICAgJzpIZWFkZXI+JyArXG4gICAgICAgICAgICAgIChzZWxmLnNvYXBIZWFkZXJzID8gc2VsZi5zb2FwSGVhZGVycy5qb2luKCdcXG4nKSA6ICcnKSArXG4gICAgICAgICAgICAgIChzZWxmLnNlY3VyaXR5ICYmICFzZWxmLnNlY3VyaXR5LnBvc3RQcm9jZXNzID8gc2VsZi5zZWN1cml0eS50b1hNTCgpIDogJycpICtcbiAgICAgICAgICAgICAgJzwvJyArXG4gICAgICAgICAgICAgIGVudmVsb3BlS2V5ICtcbiAgICAgICAgICAgICAgJzpIZWFkZXI+J1xuICAgICAgICAgICAgOiAnJykgK1xuICAgICAgICAnPCcgK1xuICAgICAgICBlbnZlbG9wZUtleSArXG4gICAgICAgICc6Qm9keScgK1xuICAgICAgICAoc2VsZi5ib2R5QXR0cmlidXRlcyA/IHNlbGYuYm9keUF0dHJpYnV0ZXMuam9pbignICcpIDogJycpICtcbiAgICAgICAgKHNlbGYuc2VjdXJpdHkgJiYgc2VsZi5zZWN1cml0eS5wb3N0UHJvY2VzcyA/ICcgSWQ9XCJfMFwiJyA6ICcnKSArXG4gICAgICAgICc+JyArXG4gICAgICAgIG1lc3NhZ2UgK1xuICAgICAgICAnPC8nICtcbiAgICAgICAgZW52ZWxvcGVLZXkgK1xuICAgICAgICAnOkJvZHk+JyArXG4gICAgICAgICc8LycgK1xuICAgICAgICBlbnZlbG9wZUtleSArXG4gICAgICAgICc6RW52ZWxvcGU+JztcblxuICAgIGlmIChzZWxmLnNlY3VyaXR5ICYmIHNlbGYuc2VjdXJpdHkucG9zdFByb2Nlc3MpIHtcbiAgICAgICAgeG1sID0gc2VsZi5zZWN1cml0eS5wb3N0UHJvY2Vzcyh4bWwsIGVudmVsb3BlS2V5KTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLnBvc3RQcm9jZXNzKSB7XG4gICAgICAgIHhtbCA9IG9wdGlvbnMucG9zdFByb2Nlc3MoeG1sKTtcbiAgICB9XG5cbiAgICBzZWxmLmxhc3RNZXNzYWdlID0gbWVzc2FnZTtcbiAgICBzZWxmLmxhc3RSZXF1ZXN0ID0geG1sO1xuICAgIHNlbGYubGFzdEVuZHBvaW50ID0gbG9jYXRpb247XG5cbiAgICBjb25zdCB0cnlKU09OcGFyc2UgPSBmdW5jdGlvbihib2R5KSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShib2R5KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBmcm9tKFNvYXBBdHRhY2htZW50LmZyb21Gb3JtRmlsZXMob3B0aW9ucy5hdHRhY2htZW50cykpLnBpcGUoXG4gICAgICAgIG1hcCgoc29hcEF0dGFjaG1lbnRzOiBTb2FwQXR0YWNobWVudFtdKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXNvYXBBdHRhY2htZW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geG1sO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5mb3JjZU1UT00gfHwgc29hcEF0dGFjaG1lbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdGFydCA9IHV1aWQ0KCk7XG4gICAgICAgICAgICAgICAgY29uc3QgYm91bmRyeSA9IHV1aWQ0KCk7XG4gICAgICAgICAgICAgICAgbGV0IGFjdGlvbiA9IG51bGw7XG4gICAgICAgICAgICAgICAgaWYgKGhlYWRlcnNbJ0NvbnRlbnQtVHlwZSddLmluZGV4T2YoJ2FjdGlvbicpID4gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBjdCBvZiBoZWFkZXJzWydDb250ZW50LVR5cGUnXS5zcGxpdCgnOyAnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN0LmluZGV4T2YoJ2FjdGlvbicpID4gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb24gPSBjdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGhlYWRlcnNbJ0NvbnRlbnQtVHlwZSddID1cbiAgICAgICAgICAgICAgICAgICAgJ211bHRpcGFydC9yZWxhdGVkOyB0eXBlPVwiYXBwbGljYXRpb24veG9wK3htbFwiOyBzdGFydD1cIjwnICsgc3RhcnQgKyAnPlwiOyBzdGFydC1pbmZvPVwidGV4dC94bWxcIjsgYm91bmRhcnk9XCInICsgYm91bmRyeSArICdcIic7XG4gICAgICAgICAgICAgICAgaWYgKGFjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBoZWFkZXJzWydDb250ZW50LVR5cGUnXSA9IGhlYWRlcnNbJ0NvbnRlbnQtVHlwZSddICsgJzsgJyArIGFjdGlvbjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBtdWx0aXBhcnQ6IGFueVtdID0gW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL3hvcCt4bWw7IGNoYXJzZXQ9VVRGLTg7IHR5cGU9XCJ0ZXh0L3htbFwiJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICdDb250ZW50LUlEJzogJzwnICsgc3RhcnQgKyAnPicsXG4gICAgICAgICAgICAgICAgICAgICAgICBib2R5OiB4bWxcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF07XG5cbiAgICAgICAgICAgICAgICBzb2FwQXR0YWNobWVudHMuZm9yRWFjaCgoYXR0YWNobWVudDogU29hcEF0dGFjaG1lbnQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlwYXJ0LnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgJ0NvbnRlbnQtVHlwZSc6IGF0dGFjaG1lbnQubWltZXR5cGUgKyAnOycsXG4gICAgICAgICAgICAgICAgICAgICAgICAnQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyc6ICdiaW5hcnknLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ0NvbnRlbnQtSUQnOiAnPCcgKyAoYXR0YWNobWVudC5jb250ZW50SWQgfHwgYXR0YWNobWVudC5uYW1lKSArICc+JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICdDb250ZW50LURpc3Bvc2l0aW9uJzogJ2F0dGFjaG1lbnQ7IG5hbWU9XCInICsgYXR0YWNobWVudC5uYW1lICsgJ1wiOyBmaWxlbmFtZT1cIicgKyBhdHRhY2htZW50Lm5hbWUgKyAnXCInLFxuICAgICAgICAgICAgICAgICAgICAgICAgYm9keTogYXR0YWNobWVudC5ib2R5XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBNdWx0aXBhcnQoKS5idWlsZChtdWx0aXBhcnQsIGJvdW5kcnkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KSxcbiAgICAgICAgbWVyZ2VNYXAoKGJvZHk6IGFueSkgPT5cbiAgICAgICAgICAgIChzZWxmLmh0dHBDbGllbnQpXG4gICAgICAgICAgICAgICAgLnBvc3QobG9jYXRpb24sIGJvZHksIHtcbiAgICAgICAgICAgICAgICAgICAgaGVhZGVyczogaGVhZGVycyxcbiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2VUeXBlOiAndGV4dCcsXG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmU6ICdyZXNwb25zZSdcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgICAgICBtYXAoKHJlc3BvbnNlOiBIdHRwUmVzcG9uc2U8YW55PikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5sYXN0UmVzcG9uc2UgPSByZXNwb25zZS5ib2R5O1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5sYXN0UmVzcG9uc2VIZWFkZXJzID0gcmVzcG9uc2UgJiYgcmVzcG9uc2UuaGVhZGVycztcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXJzZVN5bmMocmVzcG9uc2UuYm9keSwgcmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgKVxuICAgICk7XG5cbiAgICBmdW5jdGlvbiBwYXJzZVN5bmMoYm9keSwgcmVzcG9uc2U6IEh0dHBSZXNwb25zZTxhbnk+KSB7XG4gICAgICAgIGxldCBvYmo7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBvYmogPSBzZWxmLndzZGwueG1sVG9PYmplY3QoYm9keSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAvLyAgV2hlbiB0aGUgb3V0cHV0IGVsZW1lbnQgY2Fubm90IGJlIGxvb2tlZCB1cCBpbiB0aGUgd3NkbCBhbmQgdGhlIGJvZHkgaXMgSlNPTlxuI