toolshed-8.x-1.x-dev/js/toolshed.js
js/toolshed.js
"use strict";
// Define the Toolshed object scope.
Drupal.Toolshed = {
/**
* Check if this value is a string or not. Helps to encapsulate a safe way to
* test for string.
*
* @param {*} str
* The variable to check if this is a string.
*
* @return {bool}
* TRUE if the parameter is a string, FALSE otherwise.
*/
isString(str) {
return typeof str === 'string' || str instanceof String;
},
/**
* Simple escaping of RegExp strings.
*
* Does not handle advanced regular expressions, but will take care of
* most cases. Meant to be used when concatenating string to create a
* regular expressions.
*
* @param {string} str
* String to escape.
*
* @return {string}
* String with the regular expression special characters escaped.
*/
escapeRegex(str) {
return str.replace(/[\^$+*?[\]{}()\\]/g, '\\$&');
},
/**
* Helper function to uppercase the first letter of a string.
*
* @param {string} str
* String to transform.
*
* @return {string}
* String which has the first letter uppercased.
*/
ucFirst(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
},
/**
* Transform a string into camel case. It will remove spaces, underscores
* and hyphens, and uppercase the letter directly following them.
*
* @param {string} str
* The string to try to transform into camel case.
*
* @return {string}
* The string transformed into camel case.
*/
camelCase(str) {
return str.replace(/(?:[ _-]+)([a-z])/g, (match, p1) => p1.toUpperCase());
},
/**
* Transforms a string into Pascal case. This is basically the same as
* camel case, except that it will upper case the first letter as well.
*
* @param {string} str
* The original string to transform into Pascal case.
*
* @return {string}
* The transformed string.
*/
pascalCase(str) {
return str.replace(/(?:^|[ _-]+)([a-z])/g, (match, p1) => p1.toUpperCase());
},
/**
* Gets the current page Drupal URL (excluding the query or base path).
*
* @return {string}
* The current internal path for Drupal. This would be the path
* without the "base path", however, it can still be a path alias.
*/
getCurrentPath() {
if (!this.getCurrentPath.path) {
this.getCurrentPath.path = null;
if (drupalSettings.path.baseUrl) {
const regex = new RegExp(`^${this.escapeRegex(drupalSettings.path.baseUrl)}`, 'i');
this.getCurrentPath.path = window.location.pathname.replace(regex, '');
} else {
throw Error('Base path is unavailable. This usually occurs if getCurrentPath() is run before the DOM is loaded.');
}
}
return this.getCurrentPath.path;
},
/**
* Parse URL query paramters from a URL.
*
* @param {string} url
* Full URL including the query parameters starting with '?' and
* separated with '&' characters.
*
* @return {Object}
* JSON formatted object which has the property names as the query
* key, and the property value is the query value.
*/
getUrlParams(url) {
const params = {};
const [uri] = (url || window.location.search).split('#', 2);
const [, query = null] = uri.split('?', 2);
if (query) {
query.split('&').forEach(param => {
const matches = /^([^=]+)=(.*)$/.exec(param);
if (matches) {
params[decodeURIComponent(matches[1])] = decodeURIComponent(matches[2]);
}
});
}
return params;
},
/**
* Build a URL based on a Drupal internal path. This function will test
* for the availability of clean URL's and prefer them if available.
* The URL components will be run through URL encoding.
*
* @param {string} rawUrl
* The URL to add the query parameters to. The URL can previously have
* query parameters already include. This will append additional params.
* @param {Object|string} params
* An object containing parameters to use as the URL query. Object
* property keys are the query variable names, and the object property
* value is the value to use for the query.
*
* @return {string}
* The valid Drupal URL based on values passed.
*/
buildUrl(rawUrl, params) {
let url = rawUrl || '';
// leave absolute URL's alone.
if (!/^([a-z]{2,5}:)?\/\//i.test(url)) {
const baseUrl = drupalSettings.path.baseUrl ? drupalSettings.path.baseUrl : '/';
url = url.replace(/^[/,\s]+|<front>|([/,\s]+$)/g, '');
url = `${baseUrl}${drupalSettings.path.pathPrefix}${url}`;
}
if (params) {
const paramConcat = (acc, entry) => `${acc}&${encodeURIComponent(entry[0])}=${encodeURIComponent(entry[1])}`;
const qry = this.isString(params) ? params : Object.entries(params).reduce(paramConcat, '').substring(1);
if (qry.length) {
const [base, fragment] = url.split('#', 2);
url = base + (base.indexOf('?') === -1 ? '?' : '&') + qry + (fragment ? `#${fragment}` : '');
}
}
return url;
},
/**
* Create a lambda that can make requests GET to a specified URI.
*
* The resulting high order function will return a Promise encapsulating a
* HTTP request to the URL with the parameters passed, and the XHR reference
* to allow aborting the request or listening for events.
*
* This allows for aborting the request, which at the time of this writing
* "fetch" does not support.
*
* @param {string} uri
* URI to create a request function for.
* @param {object} opts
* Options for how the request should be sent and the expected data
* results should appear.
*
* The following options are available:
* - method: The HTTP method to use when creating the request.
* - format: The expected response format (JSON, HTML, URL encoded, etc...)
* - encoding(optional): Encoding of content for POST and PUT requests.
*
* @return {function(query:object):Promise|function(content, query:object):Promise}
* A lambda that creates a request to specified URI with
* passed in URL query params.
*
* If the request method is POST or PUT then the resulting lambda expects
* a content and query parameter that contains the request body and
* aditional URI query parameters respectively. GET and other methods are
* not expecting to send data, and therefore exclude the content parameter.
*
* The lamba returns a Promise which can be used to process the
* results or errors.
*/
createRequester(uri, opts = {}) {
const ts = this;
opts = {
method: 'GET',
format: 'json',
encoding: 'urlencoded',
...opts
};
// Only needed for legacy support because IE 11 and older does not handle
// the JSON response type correctly and just returns a text response.
const formatResponse = resp => ts.isString(resp) && opts.format === 'json' ? JSON.parse(resp) : resp;
if (opts.method === 'POST' || opts.method === 'PUT') {
let bodyType;
let bodyFormatter;
// Default to the same data text encoding as the response format.
switch (opts.encoding) {
case 'json':
bodyType = 'application/json';
bodyFormatter = JSON.stringify;
break;
case 'html':
case 'urlencoded':
default:
bodyType = 'application/x-www-form-urlencoded';
bodyFormatter = data => Object.entries(data).reduce((acc, [key, val]) => `${acc}&${encodeURIComponent(key)}=${encodeURIComponent(val)}`, '').substring(1);
}
return (content, query) => {
const xhr = new XMLHttpRequest();
const promise = new Promise((resolve, reject) => {
xhr.open(opts.method, ts.buildUrl(uri, query), true);
xhr.responseType = opts.format;
xhr.onreadystatechange = function onStateChange() {
if (this.readyState === XMLHttpRequest.DONE) {
if (this.status === 200) resolve(formatResponse(this.response));else reject(new Error(`${this.status}: ${this.statusText}`));
}
};
// Unable to contact the server or no response.
xhr.onerror = () => reject(new Error('Unable to connect'));
xhr.onabort = () => reject(new Error('Cancelled'));
xhr.ontimeout = () => reject(new Error('Timeout'));
// Convert parameters into URL encoded values for returning.
if (content instanceof FormData) {
xhr.send(content);
} else {
xhr.setRequestHeader('Content-Type', bodyType);
xhr.send(ts.isString(content) ? content : bodyFormatter(content));
}
});
return {
promise,
xhr
};
};
}
// Basic GET or HEAD HTTP requests.
return query => {
const xhr = new XMLHttpRequest();
const promise = new Promise((resolve, reject) => {
xhr.open(opts.method, ts.buildUrl(uri, query), true);
xhr.responseType = opts.format;
xhr.onload = () => {
if (xhr.status === 200) resolve(formatResponse(xhr.response));else reject(new Error(`${xhr.status}: ${xhr.statusText}`));
};
// Unable to contact the server or no response.
xhr.onerror = () => reject(new Error('Unable to connect'));
xhr.onabort = () => reject(new Error('Cancelled'));
xhr.ontimeout = () => reject(new Error('Timeout'));
xhr.send();
});
return {
promise,
xhr
};
};
},
/**
* Send a Request to URI with provided parameters and return Promise.
*
* @param {string} uri
* URI to build the request for.
* @param {array|null} params
* Parameters to include when making the request.
* @param {object} opts
* Same set of options as for createRequester() function.
*
* @return {Promise}
* Promise wrapping the HTTP request.
*
* @see Drupal.Toolshed.createRequester()
*/
sendRequest(uri, params, opts = {}) {
const {
promise
} = this.createRequester(uri, opts)(params);
return promise;
},
/**
* Utility function used to find an object based on a string name.
*
* @param {string} name
* Fully qualified name of the object to fetch.
*
* @return {Object}
* the object matching the name, or NULL if it cannot be found.
*/
getObject(name) {
if (!(name && name.split)) return null;
const fetchObj = (obj, items) => {
const part = items.shift();
if (obj[part]) return items.length ? fetchObj(obj[part], items) : obj[part];
return null;
};
return fetchObj(window, name.split('.'));
},
/**
* Apply a callback to DOM elements with a specified CSS class name.
*
* @param {Element} context
* The DOM Element which either has the class or should be searched within
* for elements with the class name.
* @param {string} className
* The class name to search for.
* @param {Function} callback
* The callback function to apply to all the matching elements. The
* callback should accept the DOM element as its single parameter.
* @param {string} [once=null]
* If a non-null string then use this string to as a class name to
* indicate if this callback has been called previously on these elemnts.
*/
walkByClass(context, className, callback, once = null) {
const items = context.classList && context.classList.contains(className) ? [context] : context.getElementsByClassName(className);
this._applyToElements(items, callback, once);
},
/**
* Apply a callback to all DOM elements that match a selector query.
*
* @param {Element} context
* The DOM Element which either matches the selector or should be searched
* within for elements which match the selector.
* @param {string} query
* The select query to use in order to locate elements to apply the
* callback function to.
* @param {Function} callback
* The callback function to apply to all the matching elements. The
* callback should accept the DOM element as its single parameter.
* @param {string} [once=null]
* If a non-null string then use this string to as a class name to
* indicate if this callback has been called previously on these elemnts.
*/
walkBySelector(context, query, callback, once = null) {
const items = context.matches && context.matches(query) ? [context] : context.querySelectorAll(query);
this._applyToElements(items, callback, once);
},
/**
* A browser compliant method for applying a function to an iterable object.
*
* NOTE: Though the underlying call to Array.foreach() method supports
* additional parameters such as the index and the iterable object, this
* method could be applying to either a NodeList or a HTMLCollection depending
* on how we got here and it shouldn't be assumed the index is meaningful or
* can be relied on, especially in cases where elements might get removed.
*
* @param {Iterable<Element>} elements
* An iterable list of HTML Elements to apply the callback to. If a value
* is assigned to once, the once class name is checked before applying
* the callback to the element.
* @param {Function} callback
* A callback to apply to each of the DOM elements.
* @param {[type]} [once=null]
* A class name to check for, and apply to the elements to ensure they
* do not get processed multiple times with the same "once" value.
*/
_applyToElements(elements, callback, once = null) {
if (once) {
const origFunc = callback;
callback = item => {
if (!item.classList.contains(once)) {
item.classList.add(once);
return origFunc(item);
}
};
}
Array.prototype.forEach.call(elements, callback);
}
};
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbHNoZWQuanMiLCJuYW1lcyI6WyJEcnVwYWwiLCJUb29sc2hlZCIsImlzU3RyaW5nIiwic3RyIiwiU3RyaW5nIiwiZXNjYXBlUmVnZXgiLCJyZXBsYWNlIiwidWNGaXJzdCIsImNoYXJBdCIsInRvVXBwZXJDYXNlIiwic2xpY2UiLCJjYW1lbENhc2UiLCJtYXRjaCIsInAxIiwicGFzY2FsQ2FzZSIsImdldEN1cnJlbnRQYXRoIiwicGF0aCIsImRydXBhbFNldHRpbmdzIiwiYmFzZVVybCIsInJlZ2V4IiwiUmVnRXhwIiwid2luZG93IiwibG9jYXRpb24iLCJwYXRobmFtZSIsIkVycm9yIiwiZ2V0VXJsUGFyYW1zIiwidXJsIiwicGFyYW1zIiwidXJpIiwic2VhcmNoIiwic3BsaXQiLCJxdWVyeSIsImZvckVhY2giLCJwYXJhbSIsIm1hdGNoZXMiLCJleGVjIiwiZGVjb2RlVVJJQ29tcG9uZW50IiwiYnVpbGRVcmwiLCJyYXdVcmwiLCJ0ZXN0IiwicGF0aFByZWZpeCIsInBhcmFtQ29uY2F0IiwiYWNjIiwiZW50cnkiLCJlbmNvZGVVUklDb21wb25lbnQiLCJxcnkiLCJPYmplY3QiLCJlbnRyaWVzIiwicmVkdWNlIiwic3Vic3RyaW5nIiwibGVuZ3RoIiwiYmFzZSIsImZyYWdtZW50IiwiaW5kZXhPZiIsImNyZWF0ZVJlcXVlc3RlciIsIm9wdHMiLCJ0cyIsIm1ldGhvZCIsImZvcm1hdCIsImVuY29kaW5nIiwiZm9ybWF0UmVzcG9uc2UiLCJyZXNwIiwiSlNPTiIsInBhcnNlIiwiYm9keVR5cGUiLCJib2R5Rm9ybWF0dGVyIiwic3RyaW5naWZ5IiwiZGF0YSIsImtleSIsInZhbCIsImNvbnRlbnQiLCJ4aHIiLCJYTUxIdHRwUmVxdWVzdCIsInByb21pc2UiLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlamVjdCIsIm9wZW4iLCJyZXNwb25zZVR5cGUiLCJvbnJlYWR5c3RhdGVjaGFuZ2UiLCJvblN0YXRlQ2hhbmdlIiwicmVhZHlTdGF0ZSIsIkRPTkUiLCJzdGF0dXMiLCJyZXNwb25zZSIsInN0YXR1c1RleHQiLCJvbmVycm9yIiwib25hYm9ydCIsIm9udGltZW91dCIsIkZvcm1EYXRhIiwic2VuZCIsInNldFJlcXVlc3RIZWFkZXIiLCJvbmxvYWQiLCJzZW5kUmVxdWVzdCIsImdldE9iamVjdCIsIm5hbWUiLCJmZXRjaE9iaiIsIm9iaiIsIml0ZW1zIiwicGFydCIsInNoaWZ0Iiwid2Fsa0J5Q2xhc3MiLCJjb250ZXh0IiwiY2xhc3NOYW1lIiwiY2FsbGJhY2siLCJvbmNlIiwiY2xhc3NMaXN0IiwiY29udGFpbnMiLCJnZXRFbGVtZW50c0J5Q2xhc3NOYW1lIiwiX2FwcGx5VG9FbGVtZW50cyIsIndhbGtCeVNlbGVjdG9yIiwicXVlcnlTZWxlY3RvckFsbCIsImVsZW1lbnRzIiwib3JpZ0Z1bmMiLCJpdGVtIiwiYWRkIiwiQXJyYXkiLCJwcm90b3R5cGUiLCJjYWxsIl0sInNvdXJjZXMiOlsidG9vbHNoZWQuZXM2LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIERlZmluZSB0aGUgVG9vbHNoZWQgb2JqZWN0IHNjb3BlLlxuRHJ1cGFsLlRvb2xzaGVkID0ge1xuICAvKipcbiAgICogQ2hlY2sgaWYgdGhpcyB2YWx1ZSBpcyBhIHN0cmluZyBvciBub3QuIEhlbHBzIHRvIGVuY2Fwc3VsYXRlIGEgc2FmZSB3YXkgdG9cbiAgICogdGVzdCBmb3Igc3RyaW5nLlxuICAgKlxuICAgKiBAcGFyYW0geyp9IHN0clxuICAgKiAgIFRoZSB2YXJpYWJsZSB0byBjaGVjayBpZiB0aGlzIGlzIGEgc3RyaW5nLlxuICAgKlxuICAgKiBAcmV0dXJuIHtib29sfVxuICAgKiAgIFRSVUUgaWYgdGhlIHBhcmFtZXRlciBpcyBhIHN0cmluZywgRkFMU0Ugb3RoZXJ3aXNlLlxuICAgKi9cbiAgaXNTdHJpbmcoc3RyKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBzdHIgPT09ICdzdHJpbmcnIHx8IHN0ciBpbnN0YW5jZW9mIFN0cmluZztcbiAgfSxcblxuICAvKipcbiAgICogU2ltcGxlIGVzY2FwaW5nIG9mIFJlZ0V4cCBzdHJpbmdzLlxuICAgKlxuICAgKiBEb2VzIG5vdCBoYW5kbGUgYWR2YW5jZWQgcmVndWxhciBleHByZXNzaW9ucywgYnV0IHdpbGwgdGFrZSBjYXJlIG9mXG4gICAqIG1vc3QgY2FzZXMuIE1lYW50IHRvIGJlIHVzZWQgd2hlbiBjb25jYXRlbmF0aW5nIHN0cmluZyB0byBjcmVhdGUgYVxuICAgKiByZWd1bGFyIGV4cHJlc3Npb25zLlxuICAgKlxuICAgKiBAcGFyYW0gIHtzdHJpbmd9IHN0clxuICAgKiAgU3RyaW5nIHRvIGVzY2FwZS5cbiAgICpcbiAgICogQHJldHVybiB7c3RyaW5nfVxuICAgKiAgU3RyaW5nIHdpdGggdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbiBzcGVjaWFsIGNoYXJhY3RlcnMgZXNjYXBlZC5cbiAgICovXG4gIGVzY2FwZVJlZ2V4KHN0cikge1xuICAgIHJldHVybiBzdHIucmVwbGFjZSgvW1xcXiQrKj9bXFxde30oKVxcXFxdL2csICdcXFxcJCYnKTtcbiAgfSxcblxuICAvKipcbiAgICogSGVscGVyIGZ1bmN0aW9uIHRvIHVwcGVyY2FzZSB0aGUgZmlyc3QgbGV0dGVyIG9mIGEgc3RyaW5nLlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyXG4gICAqICBTdHJpbmcgdG8gdHJhbnNmb3JtLlxuICAgKlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAqICBTdHJpbmcgd2hpY2ggaGFzIHRoZSBmaXJzdCBsZXR0ZXIgdXBwZXJjYXNlZC5cbiAgICovXG4gIHVjRmlyc3Qoc3RyKSB7XG4gICAgcmV0dXJuIHN0ci5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHN0ci5zbGljZSgxKTtcbiAgfSxcblxuICAvKipcbiAgICogVHJhbnNmb3JtIGEgc3RyaW5nIGludG8gY2FtZWwgY2FzZS4gSXQgd2lsbCByZW1vdmUgc3BhY2VzLCB1bmRlcnNjb3Jlc1xuICAgKiBhbmQgaHlwaGVucywgYW5kIHVwcGVyY2FzZSB0aGUgbGV0dGVyIGRpcmVjdGx5IGZvbGxvd2luZyB0aGVtLlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyXG4gICAqICBUaGUgc3RyaW5nIHRvIHRyeSB0byB0cmFuc2Zvcm0gaW50byBjYW1lbCBjYXNlLlxuICAgKlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAqICBUaGUgc3RyaW5nIHRyYW5zZm9ybWVkIGludG8gY2FtZWwgY2FzZS5cbiAgICovXG4gIGNhbWVsQ2FzZShzdHIpIHtcbiAgICByZXR1cm4gc3RyLnJlcGxhY2UoLyg/OlsgXy1dKykoW2Etel0pL2csIChtYXRjaCwgcDEpID0+IHAxLnRvVXBwZXJDYXNlKCkpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBUcmFuc2Zvcm1zIGEgc3RyaW5nIGludG8gUGFzY2FsIGNhc2UuIFRoaXMgaXMgYmFzaWNhbGx5IHRoZSBzYW1lIGFzXG4gICAqIGNhbWVsIGNhc2UsIGV4Y2VwdCB0aGF0IGl0IHdpbGwgdXBwZXIgY2FzZSB0aGUgZmlyc3QgbGV0dGVyIGFzIHdlbGwuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcbiAgICogIFRoZSBvcmlnaW5hbCBzdHJpbmcgdG8gdHJhbnNmb3JtIGludG8gUGFzY2FsIGNhc2UuXG4gICAqXG4gICAqIEByZXR1cm4ge3N0cmluZ31cbiAgICogIFRoZSB0cmFuc2Zvcm1lZCBzdHJpbmcuXG4gICAqL1xuICBwYXNjYWxDYXNlKHN0cikge1xuICAgIHJldHVybiBzdHIucmVwbGFjZSgvKD86XnxbIF8tXSspKFthLXpdKS9nLCAobWF0Y2gsIHAxKSA9PiBwMS50b1VwcGVyQ2FzZSgpKTtcbiAgfSxcblxuICAvKipcbiAgICogR2V0cyB0aGUgY3VycmVudCBwYWdlIERydXBhbCBVUkwgKGV4Y2x1ZGluZyB0aGUgcXVlcnkgb3IgYmFzZSBwYXRoKS5cbiAgICpcbiAgICogQHJldHVybiB7c3RyaW5nfVxuICAgKiAgVGhlIGN1cnJlbnQgaW50ZXJuYWwgcGF0aCBmb3IgRHJ1cGFsLiBUaGlzIHdvdWxkIGJlIHRoZSBwYXRoXG4gICAqICB3aXRob3V0IHRoZSBcImJhc2UgcGF0aFwiLCBob3dldmVyLCBpdCBjYW4gc3RpbGwgYmUgYSBwYXRoIGFsaWFzLlxuICAgKi9cbiAgZ2V0Q3VycmVudFBhdGgoKSB7XG4gICAgaWYgKCF0aGlzLmdldEN1cnJlbnRQYXRoLnBhdGgpIHtcbiAgICAgIHRoaXMuZ2V0Q3VycmVudFBhdGgucGF0aCA9IG51bGw7XG5cbiAgICAgIGlmIChkcnVwYWxTZXR0aW5ncy5wYXRoLmJhc2VVcmwpIHtcbiAgICAgICAgY29uc3QgcmVnZXggPSBuZXcgUmVnRXhwKGBeJHt0aGlzLmVzY2FwZVJlZ2V4KGRydXBhbFNldHRpbmdzLnBhdGguYmFzZVVybCl9YCwgJ2knKTtcbiAgICAgICAgdGhpcy5nZXRDdXJyZW50UGF0aC5wYXRoID0gd2luZG93LmxvY2F0aW9uLnBhdGhuYW1lLnJlcGxhY2UocmVnZXgsICcnKTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICB0aHJvdyBFcnJvcignQmFzZSBwYXRoIGlzIHVuYXZhaWxhYmxlLiBUaGlzIHVzdWFsbHkgb2NjdXJzIGlmIGdldEN1cnJlbnRQYXRoKCkgaXMgcnVuIGJlZm9yZSB0aGUgRE9NIGlzIGxvYWRlZC4nKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5nZXRDdXJyZW50UGF0aC5wYXRoO1xuICB9LFxuXG4gIC8qKlxuICAgKiBQYXJzZSBVUkwgcXVlcnkgcGFyYW10ZXJzIGZyb20gYSBVUkwuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1cmxcbiAgICogIEZ1bGwgVVJMIGluY2x1ZGluZyB0aGUgcXVlcnkgcGFyYW1ldGVycyBzdGFydGluZyB3aXRoICc/JyBhbmRcbiAgICogIHNlcGFyYXRlZCB3aXRoICcmJyBjaGFyYWN0ZXJzLlxuICAgKlxuICAgKiBAcmV0dXJuIHtPYmplY3R9XG4gICAqICBKU09OIGZvcm1hdHRlZCBvYmplY3Qgd2hpY2ggaGFzIHRoZSBwcm9wZXJ0eSBuYW1lcyBhcyB0aGUgcXVlcnlcbiAgICogIGtleSwgYW5kIHRoZSBwcm9wZXJ0eSB2YWx1ZSBpcyB0aGUgcXVlcnkgdmFsdWUuXG4gICAqL1xuICBnZXRVcmxQYXJhbXModXJsKSB7XG4gICAgY29uc3QgcGFyYW1zID0ge307XG4gICAgY29uc3QgW3VyaV0gPSAodXJsIHx8IHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gpLnNwbGl0KCcjJywgMik7XG4gICAgY29uc3QgWywgcXVlcnkgPSBudWxsXSA9IHVyaS5zcGxpdCgnPycsIDIpO1xuXG4gICAgaWYgKHF1ZXJ5KSB7XG4gICAgICBxdWVyeS5zcGxpdCgnJicpLmZvckVhY2goKHBhcmFtKSA9PiB7XG4gICAgICAgIGNvbnN0IG1hdGNoZXMgPSAvXihbXj1dKyk9KC4qKSQvLmV4ZWMocGFyYW0pO1xuXG4gICAgICAgIGlmIChtYXRjaGVzKSB7XG4gICAgICAgICAgcGFyYW1zW2RlY29kZVVSSUNvbXBvbmVudChtYXRjaGVzWzFdKV0gPSBkZWNvZGVVUklDb21wb25lbnQobWF0Y2hlc1syXSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBwYXJhbXM7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEJ1aWxkIGEgVVJMIGJhc2VkIG9uIGEgRHJ1cGFsIGludGVybmFsIHBhdGguIFRoaXMgZnVuY3Rpb24gd2lsbCB0ZXN0XG4gICAqIGZvciB0aGUgYXZhaWxhYmlsaXR5IG9mIGNsZWFuIFVSTCdzIGFuZCBwcmVmZXIgdGhlbSBpZiBhdmFpbGFibGUuXG4gICAqIFRoZSBVUkwgY29tcG9uZW50cyB3aWxsIGJlIHJ1biB0aHJvdWdoIFVSTCBlbmNvZGluZy5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHJhd1VybFxuICAgKiAgVGhlIFVSTCB0byBhZGQgdGhlIHF1ZXJ5IHBhcmFtZXRlcnMgdG8uIFRoZSBVUkwgY2FuIHByZXZpb3VzbHkgaGF2ZVxuICAgKiAgcXVlcnkgcGFyYW1ldGVycyBhbHJlYWR5IGluY2x1ZGUuIFRoaXMgd2lsbCBhcHBlbmQgYWRkaXRpb25hbCBwYXJhbXMuXG4gICAqIEBwYXJhbSB7T2JqZWN0fHN0cmluZ30gcGFyYW1zXG4gICAqICBBbiBvYmplY3QgY29udGFpbmluZyBwYXJhbWV0ZXJzIHRvIHVzZSBhcyB0aGUgVVJMIHF1ZXJ5LiBPYmplY3RcbiAgICogIHByb3BlcnR5IGtleXMgYXJlIHRoZSBxdWVyeSB2YXJpYWJsZSBuYW1lcywgYW5kIHRoZSBvYmplY3QgcHJvcGVydHlcbiAgICogIHZhbHVlIGlzIHRoZSB2YWx1ZSB0byB1c2UgZm9yIHRoZSBxdWVyeS5cbiAgICpcbiAgICogQHJldHVybiB7c3RyaW5nfVxuICAgKiAgVGhlIHZhbGlkIERydXBhbCBVUkwgYmFzZWQgb24gdmFsdWVzIHBhc3NlZC5cbiAgICovXG4gIGJ1aWxkVXJsKHJhd1VybCwgcGFyYW1zKSB7XG4gICAgbGV0IHVybCA9IHJhd1VybCB8fCAnJztcblxuICAgIC8vIGxlYXZlIGFic29sdXRlIFVSTCdzIGFsb25lLlxuICAgIGlmICghKC9eKFthLXpdezIsNX06KT9cXC9cXC8vaSkudGVzdCh1cmwpKSB7XG4gICAgICBjb25zdCBiYXNlVXJsID0gKGRydXBhbFNldHRpbmdzLnBhdGguYmFzZVVybCA/IGRydXBhbFNldHRpbmdzLnBhdGguYmFzZVVybCA6ICcvJyk7XG4gICAgICB1cmwgPSB1cmwucmVwbGFjZSgvXlsvLFxcc10rfDxmcm9udD58KFsvLFxcc10rJCkvZywgJycpO1xuICAgICAgdXJsID0gYCR7YmFzZVVybH0ke2RydXBhbFNldHRpbmdzLnBhdGgucGF0aFByZWZpeH0ke3VybH1gO1xuICAgIH1cblxuICAgIGlmIChwYXJhbXMpIHtcbiAgICAgIGNvbnN0IHBhcmFtQ29uY2F0ID0gKGFjYywgZW50cnkpID0+IGAke2FjY30mJHtlbmNvZGVVUklDb21wb25lbnQoZW50cnlbMF0pfT0ke2VuY29kZVVSSUNvbXBvbmVudChlbnRyeVsxXSl9YDtcbiAgICAgIGNvbnN0IHFyeSA9IHRoaXMuaXNTdHJpbmcocGFyYW1zKSA/IHBhcmFtcyA6IE9iamVjdC5lbnRyaWVzKHBhcmFtcykucmVkdWNlKHBhcmFtQ29uY2F0LCAnJykuc3Vic3RyaW5nKDEpO1xuXG4gICAgICBpZiAocXJ5Lmxlbmd0aCkge1xuICAgICAgICBjb25zdCBbYmFzZSwgZnJhZ21lbnRdID0gdXJsLnNwbGl0KCcjJywgMik7XG4gICAgICAgIHVybCA9IGJhc2UgKyAoYmFzZS5pbmRleE9mKCc/JykgPT09IC0xID8gJz8nIDogJyYnKSArIHFyeSArIChmcmFnbWVudCA/IGAjJHtmcmFnbWVudH1gIDogJycpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB1cmw7XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIGxhbWJkYSB0aGF0IGNhbiBtYWtlIHJlcXVlc3RzIEdFVCB0byBhIHNwZWNpZmllZCBVUkkuXG4gICAqXG4gICAqIFRoZSByZXN1bHRpbmcgaGlnaCBvcmRlciBmdW5jdGlvbiB3aWxsIHJldHVybiBhIFByb21pc2UgZW5jYXBzdWxhdGluZyBhXG4gICAqIEhUVFAgcmVxdWVzdCB0byB0aGUgVVJMIHdpdGggdGhlIHBhcmFtZXRlcnMgcGFzc2VkLCBhbmQgdGhlIFhIUiByZWZlcmVuY2VcbiAgICogdG8gYWxsb3cgYWJvcnRpbmcgdGhlIHJlcXVlc3Qgb3IgbGlzdGVuaW5nIGZvciBldmVudHMuXG4gICAqXG4gICAqIFRoaXMgYWxsb3dzIGZvciBhYm9ydGluZyB0aGUgcmVxdWVzdCwgd2hpY2ggYXQgdGhlIHRpbWUgb2YgdGhpcyB3cml0aW5nXG4gICAqIFwiZmV0Y2hcIiBkb2VzIG5vdCBzdXBwb3J0LlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdXJpXG4gICAqICAgVVJJIHRvIGNyZWF0ZSBhIHJlcXVlc3QgZnVuY3Rpb24gZm9yLlxuICAgKiBAcGFyYW0ge29iamVjdH0gb3B0c1xuICAgKiAgIE9wdGlvbnMgZm9yIGhvdyB0aGUgcmVxdWVzdCBzaG91bGQgYmUgc2VudCBhbmQgdGhlIGV4cGVjdGVkIGRhdGFcbiAgICogICByZXN1bHRzIHNob3VsZCBhcHBlYXIuXG4gICAqXG4gICAqICAgVGhlIGZvbGxvd2luZyBvcHRpb25zIGFyZSBhdmFpbGFibGU6XG4gICAqICAgIC0gbWV0aG9kOiBUaGUgSFRUUCBtZXRob2QgdG8gdXNlIHdoZW4gY3JlYXRpbmcgdGhlIHJlcXVlc3QuXG4gICAqICAgIC0gZm9ybWF0OiBUaGUgZXhwZWN0ZWQgcmVzcG9uc2UgZm9ybWF0IChKU09OLCBIVE1MLCBVUkwgZW5jb2RlZCwgZXRjLi4uKVxuICAgKiAgICAtIGVuY29kaW5nKG9wdGlvbmFsKTogRW5jb2Rpbmcgb2YgY29udGVudCBmb3IgUE9TVCBhbmQgUFVUIHJlcXVlc3RzLlxuICAgKlxuICAgKiBAcmV0dXJuIHtmdW5jdGlvbihxdWVyeTpvYmplY3QpOlByb21pc2V8ZnVuY3Rpb24oY29udGVudCwgcXVlcnk6b2JqZWN0KTpQcm9taXNlfVxuICAgKiAgIEEgbGFtYmRhIHRoYXQgY3JlYXRlcyBhIHJlcXVlc3QgdG8gc3BlY2lmaWVkIFVSSSB3aXRoXG4gICAqICAgcGFzc2VkIGluIFVSTCBxdWVyeSBwYXJhbXMuXG4gICAqXG4gICAqICAgSWYgdGhlIHJlcXVlc3QgbWV0aG9kIGlzIFBPU1Qgb3IgUFVUIHRoZW4gdGhlIHJlc3VsdGluZyBsYW1iZGEgZXhwZWN0c1xuICAgKiAgIGEgY29udGVudCBhbmQgcXVlcnkgcGFyYW1ldGVyIHRoYXQgY29udGFpbnMgdGhlIHJlcXVlc3QgYm9keSBhbmRcbiAgICogICBhZGl0aW9uYWwgVVJJIHF1ZXJ5IHBhcmFtZXRlcnMgcmVzcGVjdGl2ZWx5LiBHRVQgYW5kIG90aGVyIG1ldGhvZHMgYXJlXG4gICAqICAgbm90IGV4cGVjdGluZyB0byBzZW5kIGRhdGEsIGFuZCB0aGVyZWZvcmUgZXhjbHVkZSB0aGUgY29udGVudCBwYXJhbWV0ZXIuXG4gICAqXG4gICAqICAgVGhlIGxhbWJhIHJldHVybnMgYSBQcm9taXNlIHdoaWNoIGNhbiBiZSB1c2VkIHRvIHByb2Nlc3MgdGhlXG4gICAqICAgcmVzdWx0cyBvciBlcnJvcnMuXG4gICAqL1xuICBjcmVhdGVSZXF1ZXN0ZXIodXJpLCBvcHRzID0ge30pIHtcbiAgICBjb25zdCB0cyA9IHRoaXM7XG5cbiAgICBvcHRzID0ge1xuICAgICAgbWV0aG9kOiAnR0VUJyxcbiAgICAgIGZvcm1hdDogJ2pzb24nLFxuICAgICAgZW5jb2Rpbmc6ICd1cmxlbmNvZGVkJyxcbiAgICAgIC4uLm9wdHMsXG4gICAgfTtcblxuICAgIC8vIE9ubHkgbmVlZGVkIGZvciBsZWdhY3kgc3VwcG9ydCBiZWNhdXNlIElFIDExIGFuZCBvbGRlciBkb2VzIG5vdCBoYW5kbGVcbiAgICAvLyB0aGUgSlNPTiByZXNwb25zZSB0eXBlIGNvcnJlY3RseSBhbmQganVzdCByZXR1cm5zIGEgdGV4dCByZXNwb25zZS5cbiAgICBjb25zdCBmb3JtYXRSZXNwb25zZSA9IChyZXNwKSA9PiAodHMuaXNTdHJpbmcocmVzcCkgJiYgb3B0cy5mb3JtYXQgPT09ICdqc29uJykgPyBKU09OLnBhcnNlKHJlc3ApIDogcmVzcDtcblxuICAgIGlmIChvcHRzLm1ldGhvZCA9PT0gJ1BPU1QnIHx8IG9wdHMubWV0aG9kID09PSAnUFVUJykge1xuICAgICAgbGV0IGJvZHlUeXBlO1xuICAgICAgbGV0IGJvZHlGb3JtYXR0ZXI7XG5cbiAgICAgIC8vIERlZmF1bHQgdG8gdGhlIHNhbWUgZGF0YSB0ZXh0IGVuY29kaW5nIGFzIHRoZSByZXNwb25zZSBmb3JtYXQuXG4gICAgICBzd2l0Y2ggKG9wdHMuZW5jb2RpbmcpIHtcbiAgICAgICAgY2FzZSAnanNvbic6XG4gICAgICAgICAgYm9keVR5cGUgPSAnYXBwbGljYXRpb24vanNvbic7XG4gICAgICAgICAgYm9keUZvcm1hdHRlciA9IEpTT04uc3RyaW5naWZ5O1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ2h0bWwnOlxuICAgICAgICBjYXNlICd1cmxlbmNvZGVkJzpcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBib2R5VHlwZSA9ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnO1xuICAgICAgICAgIGJvZHlGb3JtYXR0ZXIgPSAoZGF0YSkgPT4gT2JqZWN0LmVudHJpZXMoZGF0YSkucmVkdWNlKChhY2MsIFtrZXksIHZhbF0pID0+IGAke2FjY30mJHtlbmNvZGVVUklDb21wb25lbnQoa2V5KX09JHtlbmNvZGVVUklDb21wb25lbnQodmFsKX1gLCAnJykuc3Vic3RyaW5nKDEpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gKGNvbnRlbnQsIHF1ZXJ5KSA9PiB7XG4gICAgICAgIGNvbnN0IHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICBjb25zdCBwcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgIHhoci5vcGVuKG9wdHMubWV0aG9kLCB0cy5idWlsZFVybCh1cmksIHF1ZXJ5KSwgdHJ1ZSk7XG4gICAgICAgICAgeGhyLnJlc3BvbnNlVHlwZSA9IG9wdHMuZm9ybWF0O1xuICAgICAgICAgIHhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbiBvblN0YXRlQ2hhbmdlKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZHlTdGF0ZSA9PT0gWE1MSHR0cFJlcXVlc3QuRE9ORSkge1xuICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0dXMgPT09IDIwMCkgcmVzb2x2ZShmb3JtYXRSZXNwb25zZSh0aGlzLnJlc3BvbnNlKSk7XG4gICAgICAgICAgICAgIGVsc2UgcmVqZWN0KG5ldyBFcnJvcihgJHt0aGlzLnN0YXR1c306ICR7dGhpcy5zdGF0dXNUZXh0fWApKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgLy8gVW5hYmxlIHRvIGNvbnRhY3QgdGhlIHNlcnZlciBvciBubyByZXNwb25zZS5cbiAgICAgICAgICB4aHIub25lcnJvciA9ICgpID0+IHJlamVjdChuZXcgRXJyb3IoJ1VuYWJsZSB0byBjb25uZWN0JykpO1xuICAgICAgICAgIHhoci5vbmFib3J0ID0gKCkgPT4gcmVqZWN0KG5ldyBFcnJvcignQ2FuY2VsbGVkJykpO1xuICAgICAgICAgIHhoci5vbnRpbWVvdXQgPSAoKSA9PiByZWplY3QobmV3IEVycm9yKCdUaW1lb3V0JykpO1xuXG4gICAgICAgICAgLy8gQ29udmVydCBwYXJhbWV0ZXJzIGludG8gVVJMIGVuY29kZWQgdmFsdWVzIGZvciByZXR1cm5pbmcuXG4gICAgICAgICAgaWYgKGNvbnRlbnQgaW5zdGFuY2VvZiBGb3JtRGF0YSkge1xuICAgICAgICAgICAgeGhyLnNlbmQoY29udGVudCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIoJ0NvbnRlbnQtVHlwZScsIGJvZHlUeXBlKTtcbiAgICAgICAgICAgIHhoci5zZW5kKHRzLmlzU3RyaW5nKGNvbnRlbnQpID8gY29udGVudCA6IGJvZHlGb3JtYXR0ZXIoY29udGVudCkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHsgcHJvbWlzZSwgeGhyIH07XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIEJhc2ljIEdFVCBvciBIRUFEIEhUVFAgcmVxdWVzdHMuXG4gICAgcmV0dXJuIChxdWVyeSkgPT4ge1xuICAgICAgY29uc3QgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICBjb25zdCBwcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICB4aHIub3BlbihvcHRzLm1ldGhvZCwgdHMuYnVpbGRVcmwodXJpLCBxdWVyeSksIHRydWUpO1xuICAgICAgICB4aHIucmVzcG9uc2VUeXBlID0gb3B0cy5mb3JtYXQ7XG5cbiAgICAgICAgeGhyLm9ubG9hZCA9ICgpID0+IHtcbiAgICAgICAgICBpZiAoeGhyLnN0YXR1cyA9PT0gMjAwKSByZXNvbHZlKGZvcm1hdFJlc3BvbnNlKHhoci5yZXNwb25zZSkpO1xuICAgICAgICAgIGVsc2UgcmVqZWN0KG5ldyBFcnJvcihgJHt4aHIuc3RhdHVzfTogJHt4aHIuc3RhdHVzVGV4dH1gKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gVW5hYmxlIHRvIGNvbnRhY3QgdGhlIHNlcnZlciBvciBubyByZXNwb25zZS5cbiAgICAgICAgeGhyLm9uZXJyb3IgPSAoKSA9PiByZWplY3QobmV3IEVycm9yKCdVbmFibGUgdG8gY29ubmVjdCcpKTtcbiAgICAgICAgeGhyLm9uYWJvcnQgPSAoKSA9PiByZWplY3QobmV3IEVycm9yKCdDYW5jZWxsZWQnKSk7XG4gICAgICAgIHhoci5vbnRpbWVvdXQgPSAoKSA9PiByZWplY3QobmV3IEVycm9yKCdUaW1lb3V0JykpO1xuICAgICAgICB4aHIuc2VuZCgpO1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB7IHByb21pc2UsIHhociB9O1xuICAgIH07XG4gIH0sXG5cbiAgLyoqXG4gICAqIFNlbmQgYSBSZXF1ZXN0IHRvIFVSSSB3aXRoIHByb3ZpZGVkIHBhcmFtZXRlcnMgYW5kIHJldHVybiBQcm9taXNlLlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdXJpXG4gICAqICAgVVJJIHRvIGJ1aWxkIHRoZSByZXF1ZXN0IGZvci5cbiAgICogQHBhcmFtIHthcnJheXxudWxsfSBwYXJhbXNcbiAgICogICBQYXJhbWV0ZXJzIHRvIGluY2x1ZGUgd2hlbiBtYWtpbmcgdGhlIHJlcXVlc3QuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzXG4gICAqICBTYW1lIHNldCBvZiBvcHRpb25zIGFzIGZvciBjcmVhdGVSZXF1ZXN0ZXIoKSBmdW5jdGlvbi5cbiAgICpcbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBQcm9taXNlIHdyYXBwaW5nIHRoZSBIVFRQIHJlcXVlc3QuXG4gICAqXG4gICAqIEBzZWUgRHJ1cGFsLlRvb2xzaGVkLmNyZWF0ZVJlcXVlc3RlcigpXG4gICAqL1xuICBzZW5kUmVxdWVzdCh1cmksIHBhcmFtcywgb3B0cyA9IHsgfSkge1xuICAgIGNvbnN0IHsgcHJvbWlzZSB9ID0gdGhpcy5jcmVhdGVSZXF1ZXN0ZXIodXJpLCBvcHRzKShwYXJhbXMpO1xuICAgIHJldHVybiBwcm9taXNlO1xuICB9LFxuXG4gIC8qKlxuICAgKiBVdGlsaXR5IGZ1bmN0aW9uIHVzZWQgdG8gZmluZCBhbiBvYmplY3QgYmFzZWQgb24gYSBzdHJpbmcgbmFtZS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICogIEZ1bGx5IHF1YWxpZmllZCBuYW1lIG9mIHRoZSBvYmplY3QgdG8gZmV0Y2guXG4gICAqXG4gICAqIEByZXR1cm4ge09iamVjdH1cbiAgICogIHRoZSBvYmplY3QgbWF0Y2hpbmcgdGhlIG5hbWUsIG9yIE5VTEwgaWYgaXQgY2Fubm90IGJlIGZvdW5kLlxuICAgKi9cbiAgZ2V0T2JqZWN0KG5hbWUpIHtcbiAgICBpZiAoIShuYW1lICYmIG5hbWUuc3BsaXQpKSByZXR1cm4gbnVsbDtcblxuICAgIGNvbnN0IGZldGNoT2JqID0gKG9iaiwgaXRlbXMpID0+IHtcbiAgICAgIGNvbnN0IHBhcnQgPSBpdGVtcy5zaGlmdCgpO1xuXG4gICAgICBpZiAob2JqW3BhcnRdKSByZXR1cm4gaXRlbXMubGVuZ3RoID8gZmV0Y2hPYmoob2JqW3BhcnRdLCBpdGVtcykgOiBvYmpbcGFydF07XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuXG4gICAgcmV0dXJuIGZldGNoT2JqKHdpbmRvdywgbmFtZS5zcGxpdCgnLicpKTtcbiAgfSxcblxuICAvKipcbiAgICogQXBwbHkgYSBjYWxsYmFjayB0byBET00gZWxlbWVudHMgd2l0aCBhIHNwZWNpZmllZCBDU1MgY2xhc3MgbmFtZS5cbiAgICpcbiAgICogQHBhcmFtIHtFbGVtZW50fSBjb250ZXh0XG4gICAqICAgVGhlIERPTSBFbGVtZW50IHdoaWNoIGVpdGhlciBoYXMgdGhlIGNsYXNzIG9yIHNob3VsZCBiZSBzZWFyY2hlZCB3aXRoaW5cbiAgICogICBmb3IgZWxlbWVudHMgd2l0aCB0aGUgY2xhc3MgbmFtZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzTmFtZVxuICAgKiAgIFRoZSBjbGFzcyBuYW1lIHRvIHNlYXJjaCBmb3IuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqICAgVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGFwcGx5IHRvIGFsbCB0aGUgbWF0Y2hpbmcgZWxlbWVudHMuIFRoZVxuICAgKiAgIGNhbGxiYWNrIHNob3VsZCBhY2NlcHQgdGhlIERPTSBlbGVtZW50IGFzIGl0cyBzaW5nbGUgcGFyYW1ldGVyLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW29uY2U9bnVsbF1cbiAgICogICBJZiBhIG5vbi1udWxsIHN0cmluZyB0aGVuIHVzZSB0aGlzIHN0cmluZyB0byBhcyBhIGNsYXNzIG5hbWUgdG9cbiAgICogICBpbmRpY2F0ZSBpZiB0aGlzIGNhbGxiYWNrIGhhcyBiZWVuIGNhbGxlZCBwcmV2aW91c2x5IG9uIHRoZXNlIGVsZW1udHMuXG4gICAqL1xuICB3YWxrQnlDbGFzcyhjb250ZXh0LCBjbGFzc05hbWUsIGNhbGxiYWNrLCBvbmNlID0gbnVsbCkge1xuICAgIGNvbnN0IGl0ZW1zID0gY29udGV4dC5jbGFzc0xpc3QgJiYgY29udGV4dC5jbGFzc0xpc3QuY29udGFpbnMoY2xhc3NOYW1lKVxuICAgICAgPyBbY29udGV4dF0gOiBjb250ZXh0LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoY2xhc3NOYW1lKTtcblxuICAgIHRoaXMuX2FwcGx5VG9FbGVtZW50cyhpdGVtcywgY2FsbGJhY2ssIG9uY2UpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBBcHBseSBhIGNhbGxiYWNrIHRvIGFsbCBET00gZWxlbWVudHMgdGhhdCBtYXRjaCBhIHNlbGVjdG9yIHF1ZXJ5LlxuICAgKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IGNvbnRleHRcbiAgICogICBUaGUgRE9NIEVsZW1lbnQgd2hpY2ggZWl0aGVyIG1hdGNoZXMgdGhlIHNlbGVjdG9yIG9yIHNob3VsZCBiZSBzZWFyY2hlZFxuICAgKiAgIHdpdGhpbiBmb3IgZWxlbWVudHMgd2hpY2ggbWF0Y2ggdGhlIHNlbGVjdG9yLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcXVlcnlcbiAgICogICBUaGUgc2VsZWN0IHF1ZXJ5IHRvIHVzZSBpbiBvcmRlciB0byBsb2NhdGUgZWxlbWVudHMgdG8gYXBwbHkgdGhlXG4gICAqICAgY2FsbGJhY2sgZnVuY3Rpb24gdG8uXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqICAgVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGFwcGx5IHRvIGFsbCB0aGUgbWF0Y2hpbmcgZWxlbWVudHMuIFRoZVxuICAgKiAgIGNhbGxiYWNrIHNob3VsZCBhY2NlcHQgdGhlIERPTSBlbGVtZW50IGFzIGl0cyBzaW5nbGUgcGFyYW1ldGVyLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW29uY2U9bnVsbF1cbiAgICogICBJZiBhIG5vbi1udWxsIHN0cmluZyB0aGVuIHVzZSB0aGlzIHN0cmluZyB0byBhcyBhIGNsYXNzIG5hbWUgdG9cbiAgICogICBpbmRpY2F0ZSBpZiB0aGlzIGNhbGxiYWNrIGhhcyBiZWVuIGNhbGxlZCBwcmV2aW91c2x5IG9uIHRoZXNlIGVsZW1udHMuXG4gICAqL1xuICB3YWxrQnlTZWxlY3Rvcihjb250ZXh0LCBxdWVyeSwgY2FsbGJhY2ssIG9uY2UgPSBudWxsKSB7XG4gICAgY29uc3QgaXRlbXMgPSBjb250ZXh0Lm1hdGNoZXMgJiYgY29udGV4dC5tYXRjaGVzKHF1ZXJ5KVxuICAgICAgPyBbY29udGV4dF0gOiBjb250ZXh0LnF1ZXJ5U2VsZWN0b3JBbGwocXVlcnkpO1xuXG4gICAgdGhpcy5fYXBwbHlUb0VsZW1lbnRzKGl0ZW1zLCBjYWxsYmFjaywgb25jZSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEEgYnJvd3NlciBjb21wbGlhbnQgbWV0aG9kIGZvciBhcHBseWluZyBhIGZ1bmN0aW9uIHRvIGFuIGl0ZXJhYmxlIG9iamVjdC5cbiAgICpcbiAgICogTk9URTogVGhvdWdoIHRoZSB1bmRlcmx5aW5nIGNhbGwgdG8gQXJyYXkuZm9yZWFjaCgpIG1ldGhvZCBzdXBwb3J0c1xuICAgKiBhZGRpdGlvbmFsIHBhcmFtZXRlcnMgc3VjaCBhcyB0aGUgaW5kZXggYW5kIHRoZSBpdGVyYWJsZSBvYmplY3QsIHRoaXNcbiAgICogbWV0aG9kIGNvdWxkIGJlIGFwcGx5aW5nIHRvIGVpdGhlciBhIE5vZGVMaXN0IG9yIGEgSFRNTENvbGxlY3Rpb24gZGVwZW5kaW5nXG4gICAqIG9uIGhvdyB3ZSBnb3QgaGVyZSBhbmQgaXQgc2hvdWxkbid0IGJlIGFzc3VtZWQgdGhlIGluZGV4IGlzIG1lYW5pbmdmdWwgb3JcbiAgICogY2FuIGJlIHJlbGllZCBvbiwgZXNwZWNpYWxseSBpbiBjYXNlcyB3aGVyZSBlbGVtZW50cyBtaWdodCBnZXQgcmVtb3ZlZC5cbiAgICpcbiAgICogQHBhcmFtIHtJdGVyYWJsZTxFbGVtZW50Pn0gZWxlbWVudHNcbiAgICogICBBbiBpdGVyYWJsZSBsaXN0IG9mIEhUTUwgRWxlbWVudHMgdG8gYXBwbHkgdGhlIGNhbGxiYWNrIHRvLiBJZiBhIHZhbHVlXG4gICAqICAgaXMgYXNzaWduZWQgdG8gb25jZSwgdGhlIG9uY2UgY2xhc3MgbmFtZSBpcyBjaGVja2VkIGJlZm9yZSBhcHBseWluZ1xuICAgKiAgIHRoZSBjYWxsYmFjayB0byB0aGUgZWxlbWVudC5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICogICBBIGNhbGxiYWNrIHRvIGFwcGx5IHRvIGVhY2ggb2YgdGhlIERPTSBlbGVtZW50cy5cbiAgICogQHBhcmFtIHtbdHlwZV19IFtvbmNlPW51bGxdXG4gICAqICAgQSBjbGFzcyBuYW1lIHRvIGNoZWNrIGZvciwgYW5kIGFwcGx5IHRvIHRoZSBlbGVtZW50cyB0byBlbnN1cmUgdGhleVxuICAgKiAgIGRvIG5vdCBnZXQgcHJvY2Vzc2VkIG11bHRpcGxlIHRpbWVzIHdpdGggdGhlIHNhbWUgXCJvbmNlXCIgdmFsdWUuXG4gICAqL1xuICBfYXBwbHlUb0VsZW1lbnRzKGVsZW1lbnRzLCBjYWxsYmFjaywgb25jZSA9IG51bGwpIHtcbiAgICBpZiAob25jZSkge1xuICAgICAgY29uc3Qgb3JpZ0Z1bmMgPSBjYWxsYmFjaztcblxuICAgICAgY2FsbGJhY2sgPSAoaXRlbSkgPT4ge1xuICAgICAgICBpZiAoIWl0ZW0uY2xhc3NMaXN0LmNvbnRhaW5zKG9uY2UpKSB7XG4gICAgICAgICAgaXRlbS5jbGFzc0xpc3QuYWRkKG9uY2UpO1xuICAgICAgICAgIHJldHVybiBvcmlnRnVuYyhpdGVtKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG5cbiAgICBBcnJheS5wcm90b3R5cGUuZm9yRWFjaC5jYWxsKGVsZW1lbnRzLCBjYWxsYmFjayk7XG4gIH0sXG59O1xuIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0FBLE1BQU0sQ0FBQ0MsUUFBUSxHQUFHO0VBQ2hCO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0VDLFFBQVEsQ0FBQ0MsR0FBRyxFQUFFO0lBQ1osT0FBTyxPQUFPQSxHQUFHLEtBQUssUUFBUSxJQUFJQSxHQUFHLFlBQVlDLE1BQU07RUFDekQsQ0FBQztFQUVEO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0VDLFdBQVcsQ0FBQ0YsR0FBRyxFQUFFO0lBQ2YsT0FBT0EsR0FBRyxDQUFDRyxPQUFPLENBQUMsb0JBQW9CLEVBQUUsTUFBTSxDQUFDO0VBQ2xELENBQUM7RUFFRDtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDRUMsT0FBTyxDQUFDSixHQUFHLEVBQUU7SUFDWCxPQUFPQSxHQUFHLENBQUNLLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQ0MsV0FBVyxFQUFFLEdBQUdOLEdBQUcsQ0FBQ08sS0FBSyxDQUFDLENBQUMsQ0FBQztFQUNuRCxDQUFDO0VBRUQ7QUFDRjtB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
