filestack-js
Version:
Official JavaScript library for Filestack
476 lines (474 loc) • 49.5 kB
JavaScript
/*
* Copyright (c) 2018 by Filestack
* Some rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { __extends } from "tslib";
import { EventEmitter } from 'eventemitter3';
import * as Sentry from '@sentry/browser';
import { config } from '../config';
import { FilestackError } from './../filestack_error';
import { metadata, remove, retrieve, download } from './api/file';
import { transform } from './api/transform';
import { storeURL } from './api/store';
import * as Utils from './utils';
import { Upload } from './api/upload';
import { preview } from './api/preview';
import { CloudClient } from './api/cloud';
import { Prefetch } from './api/prefetch';
import { picker } from './picker';
/* istanbul ignore next */
Sentry.addBreadcrumb({ category: 'sdk', message: 'filestack-js-sdk scope' });
/**
* The Filestack client, the entry point for all public methods. Encapsulates session information.
*
* ### Example
* ```js
* // ES module
* import * as filestack from 'filestack-js';
* const client = filestack.init('apikey');
* ```
*
* ```js
* // UMD module in browser
* <script src="https://static.filestackapi.com/filestack-js/3.x.x/filestack.min.js"></script>
* const client = filestack.init('apikey');
* ```
*/
var Client = /** @class */ (function (_super) {
__extends(Client, _super);
function Client(apikey, options) {
var _this = _super.call(this) || this;
_this.options = options;
_this.forwardErrors = true;
/* istanbul ignore if */
if (options && options.forwardErrors) {
_this.forwardErrors = options.forwardErrors;
}
if (!apikey || typeof apikey !== 'string' || apikey.length === 0) {
throw new Error('An apikey is required to initialize the Filestack client');
}
var urls = config.urls;
_this.session = { apikey: apikey, urls: urls };
if (options) {
var cname = options.cname, security = options.security;
_this.setSecurity(security);
_this.setCname(cname);
}
_this.prefetchInstance = new Prefetch(_this.session);
_this.cloud = new CloudClient(_this.session, options);
return _this;
}
Object.defineProperty(Client.prototype, "utils", {
/**
* Returns filestack utils
*
* @readonly
* @memberof Client
*/
get: function () {
return Utils;
},
enumerable: false,
configurable: true
});
/**
* Make basic prefetch request to check permissions
*
* @param params
*/
Client.prototype.prefetch = function (params) {
return this.prefetchInstance.getConfig(params);
};
/**
* Set security object
*
* @param {Security} security
* @memberof Client
*/
Client.prototype.setSecurity = function (security) {
if (security && !(security.policy && security.signature)) {
throw new FilestackError('Both policy and signature are required for client security');
}
if (security && security.policy && security.signature) {
this.session.policy = security.policy;
this.session.signature = security.signature;
}
};
/**
* Set custom cname
*
* @param {string} cname
* @returns
* @memberof Client
*/
Client.prototype.setCname = function (cname) {
if (!cname || cname.length === 0) {
return;
}
this.session.cname = cname;
this.session.urls = Utils.resolveHost(this.session.urls, cname);
};
/**
* Clear all current cloud sessions in the picker.
* Optionally pass a cloud source name to only log out of that cloud source.
* This essentially clears the OAuth authorization codes from the Filestack session.
* @param name Optional cloud source name.
*/
Client.prototype.logout = function (name) {
return this.cloud.logout(name);
};
/**
* Retrieve detailed data of stored files.
*
* ### Example
*
* ```js
* client
* .metadata('DCL5K46FS3OIxb5iuKby')
* .then((res) => {
* console.log(res);
* })
* .catch((err) => {
* console.log(err);
* }));
* ```
* @see [File API - Metadata](https://www.filestack.com/docs/api/file#metadata).
* @param handle Valid Filestack handle.
* @param options Metadata fields to enable on response.
* @param security Optional security override.
*/
Client.prototype.metadata = function (handle, options, security) {
/* istanbul ignore next */
return metadata(this.session, handle, options, security);
};
/**
* Construct a new picker instance.
*/
Client.prototype.picker = function (options) {
/* istanbul ignore next */
return picker(this, options);
};
/**
* Used for viewing files via Filestack handles or storage aliases, __requires Document Viewer addon to your Filestack application__.
* Opens document viewer in new window if id option is not provided.
*
* ### Example
*
* ```js
* // <div id="preview"></div>
*
* client.preview('DCL5K46FS3OIxb5iuKby', { id: 'preview' });
* ```
* @param handle Valid Filestack handle.
* @param options Preview options
*/
Client.prototype.preview = function (handle, options) {
/* istanbul ignore next */
return preview(this.session, handle, options);
};
/**
* Remove a file from storage and the Filestack system.
*
* __Requires a valid security policy and signature__. The policy and signature will be pulled from the client session, or it can be overridden with the security parameter.
*
* ### Example
*
* ```js
* client
* .remove('DCL5K46FS3OIxb5iuKby')
* .then((res) => {
* console.log(res);
* })
* .catch((err) => {
* console.log(err);
* }));
* ```
* @see [File API - Delete](https://www.filestack.com/docs/api/file#delete)
* @param handle Valid Filestack handle.
* @param security Optional security override.
*/
Client.prototype.remove = function (handle, security) {
/* istanbul ignore next */
return remove(this.session, handle, false, security);
};
/**
* Remove a file **only** from the Filestack system. The file remains in storage.
*
* __Requires a valid security policy and signature__. The policy and signature will be pulled from the client session, or it can be overridden with the security parameter.
*
* ### Example
*
* ```js
* client
* .removeMetadata('DCL5K46FS3OIxb5iuKby')
* .then((res) => {
* console.log(res);
* })
* .catch((err) => {
* console.log(err);
* }));
* ```
* @see [File API - Delete](https://www.filestack.com/docs/api/file#delete)
* @param handle Valid Filestack handle.
* @param security Optional security override.
*/
Client.prototype.removeMetadata = function (handle, security) {
/* istanbul ignore next */
return remove(this.session, handle, true, security);
};
/**
* Store a file from its URL.
*
* ### Example
*
* ```js
* client
* .storeURL('https://d1wtqaffaaj63z.cloudfront.net/images/NY_199_E_of_Hammertown_2014.jpg')
* .then(res => console.log(res));
* ```
* @see [File API - Store](https://www.filestack.com/docs/api/file#store)
* @param url Valid URL to a file.
* @param options Configure file storage.
* @param token Optional control token to call .cancel()
* @param security Optional security override.
* @param uploadTags Optional tags visible in webhooks.
* @param headers Optional headers to send
* @param workflowIds Optional workflowIds to send
*/
Client.prototype.storeURL = function (url, storeParams, token, security, uploadTags, headers, workflowIds) {
return storeURL({
session: this.session,
url: url,
storeParams: storeParams,
token: token,
security: security,
uploadTags: uploadTags,
headers: headers,
workflowIds: workflowIds,
});
};
/**
* Access files via their Filestack handles.
*
* If head option is provided - request headers are returned in promise
* If metadata option is provided - metadata object is returned in promise
* Otherwise file blob is returned
* Metadata and head options cannot be mixed
*
* ### Example
*
* ```js
* client.retrieve('fileHandle', {
* metadata: true,
* }).then((response) => {
* console.log(response);
* }).catch((err) => {
* console.error(err);
* })
* ```
*
* @see [File API - Download](https://www.filestack.com/docs/api/file#download)
* @deprecated use metadata or download methods instead
* @param handle Valid file handle
* @param options RetrieveOptions
* @param security Optional security override.
* @throws Error
*/
Client.prototype.retrieve = function (handle, options, security) {
/* istanbul ignore next */
return retrieve(this.session, handle, options, security);
};
/**
* Download file by handle
*
*
* ### Browser Example
*
* ```js
* client.download('fileHandle').then((response) => {
* const img = new Image();
* img.src = URL.createObjectURL(res.data)
* document.body.appendChild(img);
* }).catch((err) => {
* console.error(err);
* })
* ```
*
* @see [File API - Download](https://www.filestack.com/docs/api/file#download)
* @param handle Valid file handle
* @throws Error
*/
Client.prototype.download = function (handle, security) {
/* istanbul ignore next */
return download(this.session, handle, security);
};
/**
* Interface to the Filestack [Processing API](https://www.filestack.com/docs/api/processing).
* Convert a URL, handle, or storage alias to another URL which links to the transformed file.
* You can optionally store the returned URL with client.storeURL.
*
* Transform params can be provided in camelCase or snakeCase style ie: partial_pixelate or partialPixelate
*
* ### Example
*
* ```js
* const transformedUrl = client.transform(url, {
* crop: {
* dim: [x, y, width, height],
* },
* vignette: {
* blurmode: 'gaussian',
* amount: 50,
* },
* flip: true,
* partial_pixelate: {
* objects: [[10, 20, 200, 250], [275, 91, 500, 557]],
* },
* };
*
* // optionally store the new URL
* client.storeURL(transformedUrl).then(res => console.log(res));
* ```
* @see [Filestack Processing API](https://www.filestack.com/docs/api/processing)
* @param url Single or multiple valid URLs (http(s)://), file handles, or storage aliases (src://) to an image.
* @param options Transformations are applied in the order specified by this object.
* @param b64 Use new more safe format for generating transforms url (default=false) Note: If there will be any issues with url please test it with enabled b64 support
* @returns A new URL that points to the transformed resource.
*/
Client.prototype.transform = function (url, options, b64) {
if (b64 === void 0) { b64 = false; }
/* istanbul ignore next */
return transform(this.session, url, options, b64);
};
/**
* Initiates a multi-part upload flow. Use this for Filestack CIN and FII uploads.
*
* In Node runtimes the file argument is treated as a file path.
* Uploading from a Node buffer is not yet implemented.
*
* ### Example
*
* ```js
* const token = {};
* const onRetry = (obj) => {
* console.log(`Retrying ${obj.location} for ${obj.filename}. Attempt ${obj.attempt} of 10.`);
* };
*
* client.upload(file, { onRetry }, { filename: 'foobar.jpg' }, token)
* .then(res => console.log(res));
*
* client.upload({file, name}, { onRetry }, { filename: 'foobar.jpg' }, token)
* .then(res => console.log(res));
*
* token.pause(); // Pause flow
* token.resume(); // Resume flow
* token.cancel(); // Cancel flow (rejects)
* ```
* @param {InputFile} file Must be a valid [File | Blob | Buffer | string]
* @param uploadOptions Uploader options.
* @param storeOptions Storage options.
* @param token A control token that can be used to call cancel(), pause(), and resume().
* @param security Optional security policy and signature override.
*
* @returns {Promise}
*/
Client.prototype.upload = function (file, options, storeOptions, token, security) {
var _this = this;
var upload = new Upload(options, storeOptions);
upload.setSession(this.session);
if (token) {
upload.setToken(token);
}
if (security) {
upload.setSecurity(security);
}
upload.on('start', function () { return _this.emit('upload.start'); });
/* istanbul ignore next */
upload.on('error', function (e) {
if (_this.forwardErrors) {
Sentry.withScope(function (scope) {
scope.setTag('filestack-apikey', _this.session.apikey);
scope.setTag('filestack-version', Utils.getVersion());
scope.setExtra('filestack-options', _this.options);
scope.setExtras({ uploadOptions: options, storeOptions: storeOptions, details: e.details });
e.message = "FS-".concat(e.message);
scope.captureException(e);
});
}
_this.emit('upload.error', e);
});
return upload.upload(file, options && options.altText);
};
/**
* Initiates a multi-part upload flow. Use this for Filestack CIN and FII uploads.
*
* In Node runtimes the file argument is treated as a file path.
* Uploading from a Node buffer is not yet implemented.
*
* ### Example
*
* ```js
* const token = {};
* const onRetry = (obj) => {
* console.log(`Retrying ${obj.location} for ${obj.filename}. Attempt ${obj.attempt} of 10.`);
* };
*
* client.multiupload([file], { onRetry }, token)
* .then(res => console.log(res));
*
* client.multiupload([{file, name}], { onRetry }, token)
* .then(res => console.log(res));
*
* token.pause(); // Pause flow
* token.resume(); // Resume flow
* token.cancel(); // Cancel flow (rejects)
* ```
* @param {InputFile[]} file Must be a valid [File | Blob | Buffer | string (base64)]
* @param uploadOptions Upload options.
* @param storeOptions Storage options.
* @param token A control token that can be used to call cancel(), pause(), and resume().
* @param security Optional security policy and signature override.
*
* @returns {Promise}
*/
Client.prototype.multiupload = function (file, options, storeOptions, token, security) {
var _this = this;
var upload = new Upload(options, storeOptions);
upload.setSession(this.session);
if (token) {
upload.setToken(token);
}
if (security) {
upload.setSecurity(security);
}
upload.on('start', function () { return _this.emit('upload.start'); });
/* istanbul ignore next */
upload.on('error', function (e) {
Sentry.withScope(function (scope) {
scope.setTag('filestack-apikey', _this.session.apikey);
scope.setTag('filestack-version', Utils.getVersion());
scope.setExtra('filestack-options', _this.options);
scope.setExtras(e.details);
scope.setExtras({ uploadOptions: options, storeOptions: storeOptions });
scope.captureException(e);
});
_this.emit('upload.error', e);
});
return upload.multiupload(file);
};
return Client;
}(EventEmitter));
export { Client };
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvY2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRzs7QUFFSCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzdDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxFQUFFLE1BQU0sRUFBUyxNQUFNLFdBQVcsQ0FBQztBQUMxQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDdEQsT0FBTyxFQUFFLFFBQVEsRUFBbUIsTUFBTSxFQUFFLFFBQVEsRUFBbUIsUUFBUSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3BHLE9BQU8sRUFBRSxTQUFTLEVBQW9CLE1BQU0saUJBQWlCLENBQUM7QUFDOUQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN2QyxPQUFPLEtBQUssS0FBSyxNQUFNLFNBQVMsQ0FBQztBQUNqQyxPQUFPLEVBQUUsTUFBTSxFQUE0RCxNQUFNLGNBQWMsQ0FBQztBQUNoRyxPQUFPLEVBQUUsT0FBTyxFQUFrQixNQUFNLGVBQWUsQ0FBQztBQUN4RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzFDLE9BQU8sRUFBRSxRQUFRLEVBQXFDLE1BQU0sZ0JBQWdCLENBQUM7QUFJN0UsT0FBTyxFQUFFLE1BQU0sRUFBaUMsTUFBTSxVQUFVLENBQUM7QUFFakUsMEJBQTBCO0FBQzFCLE1BQU0sQ0FBQyxhQUFhLENBQUMsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxDQUFDLENBQUM7QUE2QzdFOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUNIO0lBQTRCLDBCQUFZO0lBaUJ0QyxnQkFBWSxNQUFjLEVBQVUsT0FBdUI7UUFBM0QsWUFDRSxpQkFBTyxTQXNCUjtRQXZCbUMsYUFBTyxHQUFQLE9BQU8sQ0FBZ0I7UUFabkQsbUJBQWEsR0FBWSxJQUFJLENBQUM7UUFlcEMsd0JBQXdCO1FBQ3hCLElBQUksT0FBTyxJQUFJLE9BQU8sQ0FBQyxhQUFhLEVBQUU7WUFDcEMsS0FBSSxDQUFDLGFBQWEsR0FBRyxPQUFPLENBQUMsYUFBYSxDQUFDO1NBQzVDO1FBRUQsSUFBSSxDQUFDLE1BQU0sSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDaEUsTUFBTSxJQUFJLEtBQUssQ0FBQywwREFBMEQsQ0FBQyxDQUFDO1NBQzdFO1FBQ08sSUFBQSxJQUFJLEdBQUssTUFBTSxLQUFYLENBQVk7UUFDeEIsS0FBSSxDQUFDLE9BQU8sR0FBRyxFQUFFLE1BQU0sUUFBQSxFQUFFLElBQUksTUFBQSxFQUFFLENBQUM7UUFFaEMsSUFBSSxPQUFPLEVBQUU7WUFDSCxJQUFBLEtBQUssR0FBZSxPQUFPLE1BQXRCLEVBQUUsUUFBUSxHQUFLLE9BQU8sU0FBWixDQUFhO1lBRXBDLEtBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDM0IsS0FBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUN0QjtRQUVELEtBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLFFBQVEsQ0FBQyxLQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbkQsS0FBSSxDQUFDLEtBQUssR0FBRyxJQUFJLFdBQVcsQ0FBQyxLQUFJLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDOztJQUN0RCxDQUFDO0lBM0JELHNCQUFJLHlCQUFLO1FBTlQ7Ozs7O1dBS0c7YUFDSDtZQUNFLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQzs7O09BQUE7SUEyQkQ7Ozs7T0FJRztJQUNILHlCQUFRLEdBQVIsVUFBUyxNQUF1QjtRQUM5QixPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDakQsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsNEJBQVcsR0FBWCxVQUFZLFFBQWtCO1FBQzVCLElBQUksUUFBUSxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxJQUFJLFFBQVEsQ0FBQyxTQUFTLENBQUMsRUFBRTtZQUN4RCxNQUFNLElBQUksY0FBYyxDQUFDLDREQUE0RCxDQUFDLENBQUM7U0FDeEY7UUFFRCxJQUFJLFFBQVEsSUFBSSxRQUFRLENBQUMsTUFBTSxJQUFJLFFBQVEsQ0FBQyxTQUFTLEVBQUU7WUFDckQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQztZQUN0QyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDO1NBQzdDO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILHlCQUFRLEdBQVIsVUFBUyxLQUFhO1FBQ3BCLElBQUksQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDaEMsT0FBTztTQUNSO1FBRUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQzNCLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDbEUsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsdUJBQU0sR0FBTixVQUFPLElBQWE7UUFDbEIsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBQ0Q7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FtQkc7SUFDSCx5QkFBUSxHQUFSLFVBQVMsTUFBYyxFQUFFLE9BQXlCLEVBQUUsUUFBbUI7UUFDckUsMEJBQTBCO1FBQzFCLE9BQU8sUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBQ0Q7O09BRUc7SUFDSCx1QkFBTSxHQUFOLFVBQU8sT0FBdUI7UUFDNUIsMEJBQTBCO1FBQzFCLE9BQU8sTUFBTSxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztJQUMvQixDQUFDO0lBQ0Q7Ozs7Ozs7Ozs7Ozs7T0FhRztJQUNILHdCQUFPLEdBQVAsVUFBUSxNQUFjLEVBQUUsT0FBd0I7UUFDOUMsMEJBQTBCO1FBQzFCLE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ2hELENBQUM7SUFDRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FvQkc7SUFDSCx1QkFBTSxHQUFOLFVBQU8sTUFBYyxFQUFFLFFBQW1CO1FBQ3hDLDBCQUEwQjtRQUMxQixPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDdkQsQ0FBQztJQUNEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQW9CRztJQUNILCtCQUFjLEdBQWQsVUFBZSxNQUFjLEVBQUUsUUFBbUI7UUFDaEQsMEJBQTBCO1FBQzFCLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBQ0Q7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQWtCRztJQUNILHlCQUFRLEdBQVIsVUFBUyxHQUFXLEVBQUUsV0FBeUIsRUFBRSxLQUFXLEVBQUUsUUFBbUIsRUFBRSxVQUF1QixFQUFFLE9BQWlDLEVBQUUsV0FBc0I7UUFDbkssT0FBTyxRQUFRLENBQUM7WUFDZCxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87WUFDckIsR0FBRyxLQUFBO1lBQ0gsV0FBVyxhQUFBO1lBQ1gsS0FBSyxPQUFBO1lBQ0wsUUFBUSxVQUFBO1lBQ1IsVUFBVSxZQUFBO1lBQ1YsT0FBTyxTQUFBO1lBQ1AsV0FBVyxhQUFBO1NBQ1osQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQTBCRztJQUNILHlCQUFRLEdBQVIsVUFBUyxNQUFjLEVBQUUsT0FBeUIsRUFBRSxRQUFtQjtRQUNyRSwwQkFBMEI7UUFDMUIsT0FBTyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQzNELENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQW1CRztJQUNILHlCQUFRLEdBQVIsVUFBUyxNQUFjLEVBQUUsUUFBbUI7UUFDMUMsMEJBQTBCO1FBQzFCLE9BQU8sUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FnQ0c7SUFDSCwwQkFBUyxHQUFULFVBQVUsR0FBc0IsRUFBRSxPQUF5QixFQUFFLEdBQW9CO1FBQXBCLG9CQUFBLEVBQUEsV0FBb0I7UUFDL0UsMEJBQTBCO1FBQzFCLE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0ErQkc7SUFDSCx1QkFBTSxHQUFOLFVBQU8sSUFBZSxFQUFFLE9BQXVCLEVBQUUsWUFBaUMsRUFBRSxLQUFXLEVBQUUsUUFBbUI7UUFBcEgsaUJBOEJDO1FBN0JDLElBQUksTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxZQUFZLENBQUMsQ0FBQztRQUMvQyxNQUFNLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVoQyxJQUFJLEtBQUssRUFBRTtZQUNULE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDeEI7UUFFRCxJQUFJLFFBQVEsRUFBRTtZQUNaLE1BQU0sQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7U0FDOUI7UUFFRCxNQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxjQUFNLE9BQUEsS0FBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsRUFBekIsQ0FBeUIsQ0FBQyxDQUFDO1FBQ3BELDBCQUEwQjtRQUMxQixNQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxVQUFBLENBQUM7WUFDbEIsSUFBSSxLQUFJLENBQUMsYUFBYSxFQUFFO2dCQUN0QixNQUFNLENBQUMsU0FBUyxDQUFDLFVBQUEsS0FBSztvQkFDcEIsS0FBSyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSxLQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO29CQUN0RCxLQUFLLENBQUMsTUFBTSxDQUFDLG1CQUFtQixFQUFFLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO29CQUN0RCxLQUFLLENBQUMsUUFBUSxDQUFDLG1CQUFtQixFQUFFLEtBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztvQkFDbEQsS0FBSyxDQUFDLFNBQVMsQ0FBQyxFQUFFLGFBQWEsRUFBRSxPQUFPLEVBQUUsWUFBWSxjQUFBLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO29CQUM5RSxDQUFDLENBQUMsT0FBTyxHQUFHLGFBQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBRSxDQUFDO29CQUM5QixLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzVCLENBQUMsQ0FBQyxDQUFDO2FBQ0o7WUFFRCxLQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUMvQixDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsT0FBTyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0ErQkc7SUFDSCw0QkFBVyxHQUFYLFVBQVksSUFBaUIsRUFBRSxPQUF1QixFQUFFLFlBQWlDLEVBQUUsS0FBVyxFQUFFLFFBQW1CO1FBQTNILGlCQTZCQztRQTVCQyxJQUFJLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBQyxPQUFPLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFFL0MsTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFaEMsSUFBSSxLQUFLLEVBQUU7WUFDVCxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQ3hCO1FBRUQsSUFBSSxRQUFRLEVBQUU7WUFDWixNQUFNLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQzlCO1FBRUQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsY0FBTSxPQUFBLEtBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLEVBQXpCLENBQXlCLENBQUMsQ0FBQztRQUNwRCwwQkFBMEI7UUFDMUIsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsVUFBQSxDQUFDO1lBQ2xCLE1BQU0sQ0FBQyxTQUFTLENBQUMsVUFBQSxLQUFLO2dCQUNwQixLQUFLLENBQUMsTUFBTSxDQUFDLGtCQUFrQixFQUFFLEtBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQ3RELEtBQUssQ0FBQyxNQUFNLENBQUMsbUJBQW1CLEVBQUUsS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUM7Z0JBQ3RELEtBQUssQ0FBQyxRQUFRLENBQUMsbUJBQW1CLEVBQUUsS0FBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUNsRCxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDM0IsS0FBSyxDQUFDLFNBQVMsQ0FBQyxFQUFFLGFBQWEsRUFBRSxPQUFPLEVBQUUsWUFBWSxjQUFBLEVBQUUsQ0FBQyxDQUFDO2dCQUMxRCxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDNUIsQ0FBQyxDQUFDLENBQUM7WUFFSCxLQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUMvQixDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBQ0gsYUFBQztBQUFELENBN2JBLEFBNmJDLENBN2IyQixZQUFZLEdBNmJ2QyIsImZpbGUiOiJsaWIvY2xpZW50LmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoYykgMjAxOCBieSBGaWxlc3RhY2tcbiAqIFNvbWUgcmlnaHRzIHJlc2VydmVkLlxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBFdmVudEVtaXR0ZXIgfSBmcm9tICdldmVudGVtaXR0ZXIzJztcbmltcG9ydCAqIGFzIFNlbnRyeSBmcm9tICdAc2VudHJ5L2Jyb3dzZXInO1xuaW1wb3J0IHsgY29uZmlnLCBIb3N0cyB9IGZyb20gJy4uL2NvbmZpZyc7XG5pbXBvcnQgeyBGaWxlc3RhY2tFcnJvciB9IGZyb20gJy4vLi4vZmlsZXN0YWNrX2Vycm9yJztcbmltcG9ydCB7IG1ldGFkYXRhLCBNZXRhZGF0YU9wdGlvbnMsIHJlbW92ZSwgcmV0cmlldmUsIFJldHJpZXZlT3B0aW9ucywgZG93bmxvYWQgfSBmcm9tICcuL2FwaS9maWxlJztcbmltcG9ydCB7IHRyYW5zZm9ybSwgVHJhbnNmb3JtT3B0aW9ucyB9IGZyb20gJy4vYXBpL3RyYW5zZm9ybSc7XG5pbXBvcnQgeyBzdG9yZVVSTCB9IGZyb20gJy4vYXBpL3N0b3JlJztcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHsgVXBsb2FkLCBJbnB1dEZpbGUsIFVwbG9hZE9wdGlvbnMsIFN0b3JlVXBsb2FkT3B0aW9ucywgVXBsb2FkVGFncyB9IGZyb20gJy4vYXBpL3VwbG9hZCc7XG5pbXBvcnQgeyBwcmV2aWV3LCBQcmV2aWV3T3B0aW9ucyB9IGZyb20gJy4vYXBpL3ByZXZpZXcnO1xuaW1wb3J0IHsgQ2xvdWRDbGllbnQgfSBmcm9tICcuL2FwaS9jbG91ZCc7XG5pbXBvcnQgeyBQcmVmZXRjaCwgUHJlZmV0Y2hSZXNwb25zZSwgUHJlZmV0Y2hPcHRpb25zIH0gZnJvbSAnLi9hcGkvcHJlZmV0Y2gnO1xuaW1wb3J0IHsgRnNSZXNwb25zZSB9IGZyb20gJy4vcmVxdWVzdC90eXBlcyc7XG5pbXBvcnQgeyBTdG9yZVBhcmFtcyB9IGZyb20gJy4vZmlsZWxpbmsnO1xuXG5pbXBvcnQgeyBwaWNrZXIsIFBpY2tlckluc3RhbmNlLCBQaWNrZXJPcHRpb25zIH0gZnJvbSAnLi9waWNrZXInO1xuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuU2VudHJ5LmFkZEJyZWFkY3J1bWIoeyBjYXRlZ29yeTogJ3NkaycsIG1lc3NhZ2U6ICdmaWxlc3RhY2stanMtc2RrIHNjb3BlJyB9KTtcblxuZXhwb3J0IGludGVyZmFjZSBTZXNzaW9uIHtcbiAgYXBpa2V5OiBzdHJpbmc7XG4gIHVybHM6IEhvc3RzO1xuICBjbmFtZT86IHN0cmluZztcbiAgcG9saWN5Pzogc3RyaW5nO1xuICBzaWduYXR1cmU/OiBzdHJpbmc7XG4gIHByZWZldGNoPzogUHJlZmV0Y2hSZXNwb25zZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTZWN1cml0eSB7XG4gIHBvbGljeTogc3RyaW5nO1xuICBzaWduYXR1cmU6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDbGllbnRPcHRpb25zIHtcbiAgW29wdGlvbjogc3RyaW5nXTogYW55O1xuICAvKipcbiAgICogU2VjdXJpdHkgb2JqZWN0IHdpdGggcG9saWN5IGFuZCBzaWduYXR1cmUga2V5cy5cbiAgICogQ2FuIGJlIHVzZWQgdG8gbGltaXQgY2xpZW50IGNhcGFiaWxpdGllcyBhbmQgcHJvdGVjdCBwdWJsaWMgVVJMcy5cbiAgICogSXQgaXMgaW50ZW5kZWQgdG8gYmUgdXNlZCB3aXRoIHNlcnZlci1zaWRlIHBvbGljeSBhbmQgc2lnbmF0dXJlIGdlbmVyYXRpb24uXG4gICAqIFJlYWQgYWJvdXQgW3NlY3VyaXR5IHBvbGljaWVzXShodHRwczovL3d3dy5maWxlc3RhY2suY29tL2RvY3MvY29uY2VwdHMvc2VjdXJpdHkpLlxuICAgKi9cbiAgc2VjdXJpdHk/OiBTZWN1cml0eTtcbiAgLyoqXG4gICAqIERvbWFpbiB0byB1c2UgZm9yIGFsbCBVUkxzLiBfX1JlcXVpcmVzIHRoZSBjdXN0b20gQ05BTUUgYWRkb25fXy5cbiAgICogSWYgdGhpcyBpcyBlbmFibGVkIHRoZW4geW91IG11c3QgYWxzbyBzZXQgdXAgeW91ciBvd24gT0F1dGggYXBwbGljYXRpb25zXG4gICAqIGZvciBlYWNoIGNsb3VkIHNvdXJjZSB5b3Ugd2lzaCB0byB1c2UgaW4gdGhlIHBpY2tlci5cbiAgICovXG4gIGNuYW1lPzogc3RyaW5nO1xuICAvKipcbiAgICogRW5hYmxlL2Rpc2FibGUgY2FjaGluZyBvZiB0aGUgY2xvdWQgc2Vzc2lvbiB0b2tlbi4gRGVmYXVsdCBpcyBmYWxzZS5cbiAgICogVGhpcyBlbnN1cmVzIHRoYXQgdXNlcnMgd2lsbCBiZSByZW1lbWJlcmVkIG9uIHlvdXIgZG9tYWluIHdoZW4gY2FsbGluZyB0aGUgY2xvdWQgQVBJIGZyb20gdGhlIGJyb3dzZXIuXG4gICAqIFBsZWFzZSBiZSBhd2FyZSB0aGF0IHRva2VucyBzdG9yZWQgaW4gbG9jYWxTdG9yYWdlIGFyZSBhY2Nlc3NpYmxlIGJ5IG90aGVyIHNjcmlwdHMgb24gdGhlIHNhbWUgZG9tYWluLlxuICAgKi9cbiAgc2Vzc2lvbkNhY2hlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRW5hYmxlIGZvcndhcmRpbmcgZXJyb3IgbG9ncyB0byBzZW50cnlcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIGZvcndhcmRFcnJvcnM/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFRoZSBGaWxlc3RhY2sgY2xpZW50LCB0aGUgZW50cnkgcG9pbnQgZm9yIGFsbCBwdWJsaWMgbWV0aG9kcy4gRW5jYXBzdWxhdGVzIHNlc3Npb24gaW5mb3JtYXRpb24uXG4gKlxuICogIyMjIEV4YW1wbGVcbiAqIGBgYGpzXG4gKiAvLyBFUyBtb2R1bGVcbiAqIGltcG9ydCAqIGFzIGZpbGVzdGFjayBmcm9tICdmaWxlc3RhY2stanMnO1xuICogY29uc3QgY2xpZW50ID0gZmlsZXN0YWNrLmluaXQoJ2FwaWtleScpO1xuICogYGBgXG4gKlxuICogYGBganNcbiAqIC8vIFVNRCBtb2R1bGUgaW4gYnJvd3NlclxuICogPHNjcmlwdCBzcmM9XCJodHRwczovL3N0YXRpYy5maWxlc3RhY2thcGkuY29tL2ZpbGVzdGFjay1qcy8zLngueC9maWxlc3RhY2subWluLmpzXCI+PC9zY3JpcHQ+XG4gKiBjb25zdCBjbGllbnQgPSBmaWxlc3RhY2suaW5pdCgnYXBpa2V5Jyk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIENsaWVudCBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG4gIHB1YmxpYyBzZXNzaW9uOiBTZXNzaW9uO1xuICBwcml2YXRlIGNsb3VkOiBDbG91ZENsaWVudDtcbiAgcHJpdmF0ZSBwcmVmZXRjaEluc3RhbmNlOiBQcmVmZXRjaDtcblxuICBwcml2YXRlIGZvcndhcmRFcnJvcnM6IGJvb2xlYW4gPSB0cnVlO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGZpbGVzdGFjayB1dGlsc1xuICAgKlxuICAgKiBAcmVhZG9ubHlcbiAgICogQG1lbWJlcm9mIENsaWVudFxuICAgKi9cbiAgZ2V0IHV0aWxzKCkge1xuICAgIHJldHVybiBVdGlscztcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKGFwaWtleTogc3RyaW5nLCBwcml2YXRlIG9wdGlvbnM/OiBDbGllbnRPcHRpb25zKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMuZm9yd2FyZEVycm9ycykge1xuICAgICAgdGhpcy5mb3J3YXJkRXJyb3JzID0gb3B0aW9ucy5mb3J3YXJkRXJyb3JzO1xuICAgIH1cblxuICAgIGlmICghYXBpa2V5IHx8IHR5cGVvZiBhcGlrZXkgIT09ICdzdHJpbmcnIHx8IGFwaWtleS5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQW4gYXBpa2V5IGlzIHJlcXVpcmVkIHRvIGluaXRpYWxpemUgdGhlIEZpbGVzdGFjayBjbGllbnQnKTtcbiAgICB9XG4gICAgY29uc3QgeyB1cmxzIH0gPSBjb25maWc7XG4gICAgdGhpcy5zZXNzaW9uID0geyBhcGlrZXksIHVybHMgfTtcblxuICAgIGlmIChvcHRpb25zKSB7XG4gICAgICBjb25zdCB7IGNuYW1lLCBzZWN1cml0eSB9ID0gb3B0aW9ucztcblxuICAgICAgdGhpcy5zZXRTZWN1cml0eShzZWN1cml0eSk7XG4gICAgICB0aGlzLnNldENuYW1lKGNuYW1lKTtcbiAgICB9XG5cbiAgICB0aGlzLnByZWZldGNoSW5zdGFuY2UgPSBuZXcgUHJlZmV0Y2godGhpcy5zZXNzaW9uKTtcbiAgICB0aGlzLmNsb3VkID0gbmV3IENsb3VkQ2xpZW50KHRoaXMuc2Vzc2lvbiwgb3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogTWFrZSBiYXNpYyBwcmVmZXRjaCByZXF1ZXN0IHRvIGNoZWNrIHBlcm1pc3Npb25zXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXNcbiAgICovXG4gIHByZWZldGNoKHBhcmFtczogUHJlZmV0Y2hPcHRpb25zKSB7XG4gICAgcmV0dXJuIHRoaXMucHJlZmV0Y2hJbnN0YW5jZS5nZXRDb25maWcocGFyYW1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgc2VjdXJpdHkgb2JqZWN0XG4gICAqXG4gICAqIEBwYXJhbSB7U2VjdXJpdHl9IHNlY3VyaXR5XG4gICAqIEBtZW1iZXJvZiBDbGllbnRcbiAgICovXG4gIHNldFNlY3VyaXR5KHNlY3VyaXR5OiBTZWN1cml0eSkge1xuICAgIGlmIChzZWN1cml0eSAmJiAhKHNlY3VyaXR5LnBvbGljeSAmJiBzZWN1cml0eS5zaWduYXR1cmUpKSB7XG4gICAgICB0aHJvdyBuZXcgRmlsZXN0YWNrRXJyb3IoJ0JvdGggcG9saWN5IGFuZCBzaWduYXR1cmUgYXJlIHJlcXVpcmVkIGZvciBjbGllbnQgc2VjdXJpdHknKTtcbiAgICB9XG5cbiAgICBpZiAoc2VjdXJpdHkgJiYgc2VjdXJpdHkucG9saWN5ICYmIHNlY3VyaXR5LnNpZ25hdHVyZSkge1xuICAgICAgdGhpcy5zZXNzaW9uLnBvbGljeSA9IHNlY3VyaXR5LnBvbGljeTtcbiAgICAgIHRoaXMuc2Vzc2lvbi5zaWduYXR1cmUgPSBzZWN1cml0eS5zaWduYXR1cmU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldCBjdXN0b20gY25hbWVcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGNuYW1lXG4gICAqIEByZXR1cm5zXG4gICAqIEBtZW1iZXJvZiBDbGllbnRcbiAgICovXG4gIHNldENuYW1lKGNuYW1lOiBzdHJpbmcpIHtcbiAgICBpZiAoIWNuYW1lIHx8IGNuYW1lLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc2Vzc2lvbi5jbmFtZSA9IGNuYW1lO1xuICAgIHRoaXMuc2Vzc2lvbi51cmxzID0gVXRpbHMucmVzb2x2ZUhvc3QodGhpcy5zZXNzaW9uLnVybHMsIGNuYW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhciBhbGwgY3VycmVudCBjbG91ZCBzZXNzaW9ucyBpbiB0aGUgcGlja2VyLlxuICAgKiBPcHRpb25hbGx5IHBhc3MgYSBjbG91ZCBzb3VyY2UgbmFtZSB0byBvbmx5IGxvZyBvdXQgb2YgdGhhdCBjbG91ZCBzb3VyY2UuXG4gICAqIFRoaXMgZXNzZW50aWFsbHkgY2xlYXJzIHRoZSBPQXV0aCBhdXRob3JpemF0aW9uIGNvZGVzIGZyb20gdGhlIEZpbGVzdGFjayBzZXNzaW9uLlxuICAgKiBAcGFyYW0gbmFtZSBPcHRpb25hbCBjbG91ZCBzb3VyY2UgbmFtZS5cbiAgICovXG4gIGxvZ291dChuYW1lPzogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuY2xvdWQubG9nb3V0KG5hbWUpO1xuICB9XG4gIC8qKlxuICAgKiBSZXRyaWV2ZSBkZXRhaWxlZCBkYXRhIG9mIHN0b3JlZCBmaWxlcy5cbiAgICpcbiAgICogIyMjIEV4YW1wbGVcbiAgICpcbiAgICogYGBganNcbiAgICogY2xpZW50XG4gICAqICAgLm1ldGFkYXRhKCdEQ0w1SzQ2RlMzT0l4YjVpdUtieScpXG4gICAqICAgLnRoZW4oKHJlcykgPT4ge1xuICAgKiAgICAgY29uc29sZS5sb2cocmVzKTtcbiAgICogICB9KVxuICAgKiAgIC5jYXRjaCgoZXJyKSA9PiB7XG4gICAqICAgICBjb25zb2xlLmxvZyhlcnIpO1xuICAgKiAgIH0pKTtcbiAgICogYGBgXG4gICAqIEBzZWUgW0ZpbGUgQVBJIC0gTWV0YWRhdGFdKGh0dHBzOi8vd3d3LmZpbGVzdGFjay5jb20vZG9jcy9hcGkvZmlsZSNtZXRhZGF0YSkuXG4gICAqIEBwYXJhbSBoYW5kbGUgVmFsaWQgRmlsZXN0YWNrIGhhbmRsZS5cbiAgICogQHBhcmFtIG9wdGlvbnMgTWV0YWRhdGEgZmllbGRzIHRvIGVuYWJsZSBvbiByZXNwb25zZS5cbiAgICogQHBhcmFtIHNlY3VyaXR5IE9wdGlvbmFsIHNlY3VyaXR5IG92ZXJyaWRlLlxuICAgKi9cbiAgbWV0YWRhdGEoaGFuZGxlOiBzdHJpbmcsIG9wdGlvbnM/OiBNZXRhZGF0YU9wdGlvbnMsIHNlY3VyaXR5PzogU2VjdXJpdHkpIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIHJldHVybiBtZXRhZGF0YSh0aGlzLnNlc3Npb24sIGhhbmRsZSwgb3B0aW9ucywgc2VjdXJpdHkpO1xuICB9XG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgYSBuZXcgcGlja2VyIGluc3RhbmNlLlxuICAgKi9cbiAgcGlja2VyKG9wdGlvbnM/OiBQaWNrZXJPcHRpb25zKTogUGlja2VySW5zdGFuY2Uge1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgcmV0dXJuIHBpY2tlcih0aGlzLCBvcHRpb25zKTtcbiAgfVxuICAvKipcbiAgICogVXNlZCBmb3Igdmlld2luZyBmaWxlcyB2aWEgRmlsZXN0YWNrIGhhbmRsZXMgb3Igc3RvcmFnZSBhbGlhc2VzLCBfX3JlcXVpcmVzIERvY3VtZW50IFZpZXdlciBhZGRvbiB0byB5b3VyIEZpbGVzdGFjayBhcHBsaWNhdGlvbl9fLlxuICAgKiBPcGVucyBkb2N1bWVudCB2aWV3ZXIgaW4gbmV3IHdpbmRvdyBpZiBpZCBvcHRpb24gaXMgbm90IHByb3ZpZGVkLlxuICAgKlxuICAgKiAjIyMgRXhhbXBsZVxuICAgKlxuICAgKiBgYGBqc1xuICAgKiAvLyA8ZGl2IGlkPVwicHJldmlld1wiPjwvZGl2PlxuICAgKlxuICAgKiBjbGllbnQucHJldmlldygnRENMNUs0NkZTM09JeGI1aXVLYnknLCB7IGlkOiAncHJldmlldycgfSk7XG4gICAqIGBgYFxuICAgKiBAcGFyYW0gaGFuZGxlIFZhbGlkIEZpbGVzdGFjayBoYW5kbGUuXG4gICAqIEBwYXJhbSBvcHRpb25zIFByZXZpZXcgb3B0aW9uc1xuICAgKi9cbiAgcHJldmlldyhoYW5kbGU6IHN0cmluZywgb3B0aW9ucz86IFByZXZpZXdPcHRpb25zKSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICByZXR1cm4gcHJldmlldyh0aGlzLnNlc3Npb24sIGhhbmRsZSwgb3B0aW9ucyk7XG4gIH1cbiAgLyoqXG4gICAqIFJlbW92ZSBhIGZpbGUgZnJvbSBzdG9yYWdlIGFuZCB0aGUgRmlsZXN0YWNrIHN5c3RlbS5cbiAgICpcbiAgICogX19SZXF1aXJlcyBhIHZhbGlkIHNlY3VyaXR5IHBvbGljeSBhbmQgc2lnbmF0dXJlX18uIFRoZSBwb2xpY3kgYW5kIHNpZ25hdHVyZSB3aWxsIGJlIHB1bGxlZCBmcm9tIHRoZSBjbGllbnQgc2Vzc2lvbiwgb3IgaXQgY2FuIGJlIG92ZXJyaWRkZW4gd2l0aCB0aGUgc2VjdXJpdHkgcGFyYW1ldGVyLlxuICAgKlxuICAgKiAjIyMgRXhhbXBsZVxuICAgKlxuICAgKiBgYGBqc1xuICAgKiBjbGllbnRcbiAgICogICAucmVtb3ZlKCdEQ0w1SzQ2RlMzT0l4YjVpdUtieScpXG4gICAqICAgLnRoZW4oKHJlcykgPT4ge1xuICAgKiAgICAgY29uc29sZS5sb2cocmVzKTtcbiAgICogICB9KVxuICAgKiAgIC5jYXRjaCgoZXJyKSA9PiB7XG4gICAqICAgICBjb25zb2xlLmxvZyhlcnIpO1xuICAgKiAgIH0pKTtcbiAgICogYGBgXG4gICAqIEBzZWUgW0ZpbGUgQVBJIC0gRGVsZXRlXShodHRwczovL3d3dy5maWxlc3RhY2suY29tL2RvY3MvYXBpL2ZpbGUjZGVsZXRlKVxuICAgKiBAcGFyYW0gaGFuZGxlIFZhbGlkIEZpbGVzdGFjayBoYW5kbGUuXG4gICAqIEBwYXJhbSBzZWN1cml0eSBPcHRpb25hbCBzZWN1cml0eSBvdmVycmlkZS5cbiAgICovXG4gIHJlbW92ZShoYW5kbGU6IHN0cmluZywgc2VjdXJpdHk/OiBTZWN1cml0eSk6IFByb21pc2U8YW55PiB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICByZXR1cm4gcmVtb3ZlKHRoaXMuc2Vzc2lvbiwgaGFuZGxlLCBmYWxzZSwgc2VjdXJpdHkpO1xuICB9XG4gIC8qKlxuICAgKiBSZW1vdmUgYSBmaWxlICoqb25seSoqIGZyb20gdGhlIEZpbGVzdGFjayBzeXN0ZW0uIFRoZSBmaWxlIHJlbWFpbnMgaW4gc3RvcmFnZS5cbiAgICpcbiAgICogX19SZXF1aXJlcyBhIHZhbGlkIHNlY3VyaXR5IHBvbGljeSBhbmQgc2lnbmF0dXJlX18uIFRoZSBwb2xpY3kgYW5kIHNpZ25hdHVyZSB3aWxsIGJlIHB1bGxlZCBmcm9tIHRoZSBjbGllbnQgc2Vzc2lvbiwgb3IgaXQgY2FuIGJlIG92ZXJyaWRkZW4gd2l0aCB0aGUgc2VjdXJpdHkgcGFyYW1ldGVyLlxuICAgKlxuICAgKiAjIyMgRXhhbXBsZVxuICAgKlxuICAgKiBgYGBqc1xuICAgKiBjbGllbnRcbiAgICogICAucmVtb3ZlTWV0YWRhdGEoJ0RDTDVLNDZGUzNPSXhiNWl1S2J5JylcbiAgICogICAudGhlbigocmVzKSA9PiB7XG4gICAqICAgICBjb25zb2xlLmxvZyhyZXMpO1xuICAgKiAgIH0pXG4gICAqICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICogICAgIGNvbnNvbGUubG9nKGVycik7XG4gICAqICAgfSkpO1xuICAgKiBgYGBcbiAgICogQHNlZSBbRmlsZSBBUEkgLSBEZWxldGVdKGh0dHBzOi8vd3d3LmZpbGVzdGFjay5jb20vZG9jcy9hcGkvZmlsZSNkZWxldGUpXG4gICAqIEBwYXJhbSBoYW5kbGUgVmFsaWQgRmlsZXN0YWNrIGhhbmRsZS5cbiAgICogQHBhcmFtIHNlY3VyaXR5IE9wdGlvbmFsIHNlY3VyaXR5IG92ZXJyaWRlLlxuICAgKi9cbiAgcmVtb3ZlTWV0YWRhdGEoaGFuZGxlOiBzdHJpbmcsIHNlY3VyaXR5PzogU2VjdXJpdHkpOiBQcm9taXNlPGFueT4ge1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgcmV0dXJuIHJlbW92ZSh0aGlzLnNlc3Npb24sIGhhbmRsZSwgdHJ1ZSwgc2VjdXJpdHkpO1xuICB9XG4gIC8qKlxuICAgKiBTdG9yZSBhIGZpbGUgZnJvbSBpdHMgVVJMLlxuICAgKlxuICAgKiAjIyMgRXhhbXBsZVxuICAgKlxuICAgKiBgYGBqc1xuICAgKiBjbGllbnRcbiAgICogICAuc3RvcmVVUkwoJ2h0dHBzOi8vZDF3dHFhZmZhYWo2M3ouY2xvdWRmcm9udC5uZXQvaW1hZ2VzL05ZXzE5OV9FX29mX0hhbW1lcnRvd25fMjAxNC5qcGcnKVxuICAgKiAgIC50aGVuKHJlcyA9PiBjb25zb2xlLmxvZyhyZXMpKTtcbiAgICogYGBgXG4gICAqIEBzZWUgW0ZpbGUgQVBJIC0gU3RvcmVdKGh0dHBzOi8vd3d3LmZpbGVzdGFjay5jb20vZG9jcy9hcGkvZmlsZSNzdG9yZSlcbiAgICogQHBhcmFtIHVybCAgICAgICBWYWxpZCBVUkwgdG8gYSBmaWxlLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAgIENvbmZpZ3VyZSBmaWxlIHN0b3JhZ2UuXG4gICAqIEBwYXJhbSB0b2tlbiAgICAgT3B0aW9uYWwgY29udHJvbCB0b2tlbiB0byBjYWxsIC5jYW5jZWwoKVxuICAgKiBAcGFyYW0gc2VjdXJpdHkgIE9wdGlvbmFsIHNlY3VyaXR5IG92ZXJyaWRlLlxuICAgKiBAcGFyYW0gdXBsb2FkVGFncyBPcHRpb25hbCB0YWdzIHZpc2libGUgaW4gd2ViaG9va3MuXG4gICAqIEBwYXJhbSBoZWFkZXJzICAgIE9wdGlvbmFsIGhlYWRlcnMgdG8gc2VuZFxuICAgKiBAcGFyYW0gd29ya2Zsb3dJZHMgICAgT3B0aW9uYWwgd29ya2Zsb3dJZHMgdG8gc2VuZFxuICAgKi9cbiAgc3RvcmVVUkwodXJsOiBzdHJpbmcsIHN0b3JlUGFyYW1zPzogU3RvcmVQYXJhbXMsIHRva2VuPzogYW55LCBzZWN1cml0eT86IFNlY3VyaXR5LCB1cGxvYWRUYWdzPzogVXBsb2FkVGFncywgaGVhZGVycz86IHtba2V5OiBzdHJpbmddOiBzdHJpbmd9LCB3b3JrZmxvd0lkcz86IHN0cmluZ1tdKTogUHJvbWlzZTxPYmplY3Q+IHtcbiAgICByZXR1cm4gc3RvcmVVUkwoe1xuICAgICAgc2Vzc2lvbjogdGhpcy5zZXNzaW9uLFxuICAgICAgdXJsLFxuICAgICAgc3RvcmVQYXJhbXMsXG4gICAgICB0b2tlbixcbiAgICAgIHNlY3VyaXR5LFxuICAgICAgdXBsb2FkVGFncyxcbiAgICAgIGhlYWRlcnMsXG4gICAgICB3b3JrZmxvd0lkcyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBY2Nlc3MgZmlsZXMgdmlhIHRoZWlyIEZpbGVzdGFjayBoYW5kbGVzLlxuICAgKlxuICAgKiBJZiBoZWFkIG9wdGlvbiBpcyBwcm92aWRlZCAtIHJlcXVlc3QgaGVhZGVycyBhcmUgcmV0dXJuZWQgaW4gcHJvbWlzZVxuICAgKiBJZiBtZXRhZGF0YSBvcHRpb24gaXMgcHJvdmlkZWQgLSBtZXRhZGF0YSBvYmplY3QgaXMgcmV0dXJuZWQgaW4gcHJvbWlzZVxuICAgKiBPdGhlcndpc2UgZmlsZSBibG9iIGlzIHJldHVybmVkXG4gICAqIE1ldGFkYXRhIGFuZCBoZWFkIG9wdGlvbnMgY2Fubm90IGJlIG1peGVkXG4gICAqXG4gICAqICMjIyBFeGFtcGxlXG4gICAqXG4gICAqIGBgYGpzXG4gICAqIGNsaWVudC5yZXRyaWV2ZSgnZmlsZUhhbmRsZScsIHtcbiAgICogIG1ldGFkYXRhOiB0cnVlLFxuICAgKiB9KS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgKiAgY29uc29sZS5sb2cocmVzcG9uc2UpO1xuICAgKiB9KS5jYXRjaCgoZXJyKSA9PiB7XG4gICAqICBjb25zb2xlLmVycm9yKGVycik7XG4gICAqIH0pXG4gICAqIGBgYFxuICAgKlxuICAgKiBAc2VlIFtGaWxlIEFQSSAtIERvd25sb2FkXShodHRwczovL3d3dy5maWxlc3RhY2suY29tL2RvY3MvYXBpL2ZpbGUjZG93bmxvYWQpXG4gICAqIEBkZXByZWNhdGVkIHVzZSBtZXRhZGF0YSBvciBkb3dubG9hZCBtZXRob2RzIGluc3RlYWRcbiAgICogQHBhcmFtIGhhbmRsZSAgICBWYWxpZCBmaWxlIGhhbmRsZVxuICAgKiBAcGFyYW0gb3B0aW9ucyAgIFJldHJpZXZlT3B0aW9uc1xuICAgKiBAcGFyYW0gc2VjdXJpdHkgIE9wdGlvbmFsIHNlY3VyaXR5IG92ZXJyaWRlLlxuICAgKiBAdGhyb3dzICAgICAgICAgIEVycm9yXG4gICAqL1xuICByZXRyaWV2ZShoYW5kbGU6IHN0cmluZywgb3B0aW9ucz86IFJldHJpZXZlT3B0aW9ucywgc2VjdXJpdHk/OiBTZWN1cml0eSk6IFByb21pc2U8T2JqZWN0IHwgQmxvYj4ge1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgcmV0dXJuIHJldHJpZXZlKHRoaXMuc2Vzc2lvbiwgaGFuZGxlLCBvcHRpb25zLCBzZWN1cml0eSk7XG4gIH1cblxuICAvKipcbiAgICogRG93bmxvYWQgZmlsZSBieSBoYW5kbGVcbiAgICpcbiAgICpcbiAgICogIyMjIEJyb3dzZXIgRXhhbXBsZVxuICAgKlxuICAgKiBgYGBqc1xuICAgKiBjbGllbnQuZG93bmxvYWQoJ2ZpbGVIYW5kbGUnKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgKiBjb25zdCBpbWcgPSBuZXcgSW1hZ2UoKTtcbiAgICogaW1nLnNyYyA9IFVSTC5jcmVhdGVPYmplY3RVUkwocmVzLmRhdGEpXG4gICAqIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoaW1nKTtcbiAgICogfSkuY2F0Y2goKGVycikgPT4ge1xuICAgKiAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgKiB9KVxuICAgKiBgYGBcbiAgICpcbiAgICogQHNlZSBbRmlsZSBBUEkgLSBEb3dubG9hZF0oaHR0cHM6Ly93d3cuZmlsZXN0YWNrLmNvbS9kb2NzL2FwaS9maWxlI2Rvd25sb2FkKVxuICAgKiBAcGFyYW0gaGFuZGxlICAgIFZhbGlkIGZpbGUgaGFuZGxlXG4gICAqIEB0aHJvd3MgICAgICAgICAgRXJyb3JcbiAgICovXG4gIGRvd25sb2FkKGhhbmRsZTogc3RyaW5nLCBzZWN1cml0eT86IFNlY3VyaXR5KTogUHJvbWlzZTxGc1Jlc3BvbnNlPiB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICByZXR1cm4gZG93bmxvYWQodGhpcy5zZXNzaW9uLCBoYW5kbGUsIHNlY3VyaXR5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnRlcmZhY2UgdG8gdGhlIEZpbGVzdGFjayBbUHJvY2Vzc2luZyBBUEldKGh0dHBzOi8vd3d3LmZpbGVzdGFjay5jb20vZG9jcy9hcGkvcHJvY2Vzc2luZykuXG4gICAqIENvbnZlcnQgYSBVUkwsIGhhbmRsZSwgb3Igc3RvcmFnZSBhbGlhcyB0byBhbm90aGVyIFVSTCB3aGljaCBsaW5rcyB0byB0aGUgdHJhbnNmb3JtZWQgZmlsZS5cbiAgICogWW91IGNhbiBvcHRpb25hbGx5IHN0b3JlIHRoZSByZXR1cm5lZCBVUkwgd2l0aCBjbGllbnQuc3RvcmVVUkwuXG4gICAqXG4gICAqIFRyYW5zZm9ybSBwYXJhbXMgY2FuIGJlIHByb3ZpZGVkIGluIGNhbWVsQ2FzZSBvciBzbmFrZUNhc2Ugc3R5bGUgaWU6IHBhcnRpYWxfcGl4ZWxhdGUgb3IgcGFydGlhbFBpeGVsYXRlXG4gICAqXG4gICAqICMjIyBFeGFtcGxlXG4gICAqXG4gICAqIGBgYGpzXG4gICAqIGNvbnN0IHRyYW5zZm9ybWVkVXJsID0gY2xpZW50LnRyYW5zZm9ybSh1cmwsIHtcbiAgICogICBjcm9wOiB7XG4gICAqICAgICBkaW06IFt4LCB5LCB3aWR0aCwgaGVpZ2h0XSxcbiAgICogICB9LFxuICAgKiAgIHZpZ25ldHRlOiB7XG4gICAqICAgICBibHVybW9kZTogJ2dhdXNzaWFuJyxcbiAgICogICAgIGFtb3VudDogNTAsXG4gICAqICAgfSxcbiAgICogICBmbGlwOiB0cnVlLFxuICAgKiAgIHBhcnRpYWxfcGl4ZWxhdGU6IHtcbiAgICogICAgIG9iamVjdHM6IFtbMTAsIDIwLCAyMDAsIDI1MF0sIFsyNzUsIDkxLCA1MDAsIDU1N11dLFxuICAgKiAgIH0sXG4gICAqIH07XG4gICAqXG4gICAqIC8vIG9wdGlvbmFsbHkgc3RvcmUgdGhlIG5ldyBVUkxcbiAgICogY2xpZW50LnN0b3JlVVJMKHRyYW5zZm9ybWVkVXJsKS50aGVuKHJlcyA9PiBjb25zb2xlLmxvZyhyZXMpKTtcbiAgICogYGBgXG4gICAqIEBzZWUgW0ZpbGVzdGFjayBQcm9jZXNzaW5nIEFQSV0oaHR0cHM6Ly93d3cuZmlsZXN0YWNrLmNvbS9kb2NzL2FwaS9wcm9jZXNzaW5nKVxuICAgKiBAcGFyYW0gdXJsICAgICBTaW5nbGUgb3IgbXVsdGlwbGUgdmFsaWQgVVJMcyAoaHR0cChzKTovLyksIGZpbGUgaGFuZGxlcywgb3Igc3RvcmFnZSBhbGlhc2VzIChzcmM6Ly8pIHRvIGFuIGltYWdlLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUcmFuc2Zvcm1hdGlvbnMgYXJlIGFwcGxpZWQgaW4gdGhlIG9yZGVyIHNwZWNpZmllZCBieSB0aGlzIG9iamVjdC5cbiAgICogQHBhcmFtIGI2NCAgICAgVXNlIG5ldyBtb3JlIHNhZmUgZm9ybWF0IGZvciBnZW5lcmF0aW5nIHRyYW5zZm9ybXMgdXJsIChkZWZhdWx0PWZhbHNlKSBOb3RlOiBJZiB0aGVyZSB3aWxsIGJlIGFueSBpc3N1ZXMgd2l0aCB1cmwgcGxlYXNlIHRlc3QgaXQgd2l0aCBlbmFibGVkIGI2NCBzdXBwb3J0XG4gICAqIEByZXR1cm5zICAgICAgIEEgbmV3IFVSTCB0aGF0IHBvaW50cyB0byB0aGUgdHJhbnNmb3JtZWQgcmVzb3VyY2UuXG4gICAqL1xuICB0cmFuc2Zvcm0odXJsOiBzdHJpbmcgfCBzdHJpbmdbXSwgb3B0aW9uczogVHJhbnNmb3JtT3B0aW9ucywgYjY0OiBib29sZWFuID0gZmFsc2UpIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIHJldHVybiB0cmFuc2Zvcm0odGhpcy5zZXNzaW9uLCB1cmwsIG9wdGlvbnMsIGI2NCk7XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhdGVzIGEgbXVsdGktcGFydCB1cGxvYWQgZmxvdy4gVXNlIHRoaXMgZm9yIEZpbGVzdGFjayBDSU4gYW5kIEZJSSB1cGxvYWRzLlxuICAgKlxuICAgKiBJbiBOb2RlIHJ1bnRpbWVzIHRoZSBmaWxlIGFyZ3VtZW50IGlzIHRyZWF0ZWQgYXMgYSBmaWxlIHBhdGguXG4gICAqIFVwbG9hZGluZyBmcm9tIGEgTm9kZSBidWZmZXIgaXMgbm90IHlldCBpbXBsZW1lbnRlZC5cbiAgICpcbiAgICogIyMjIEV4YW1wbGVcbiAgICpcbiAgICogYGBganNcbiAgICogY29uc3QgdG9rZW4gPSB7fTtcbiAgICogY29uc3Qgb25SZXRyeSA9IChvYmopID0+IHtcbiAgICogICBjb25zb2xlLmxvZyhgUmV0cnlpbmcgJHtvYmoubG9jYXRpb259IGZvciAke29iai5maWxlbmFtZX0uIEF0dGVtcHQgJHtvYmouYXR0ZW1wdH0gb2YgMTAuYCk7XG4gICAqIH07XG4gICAqXG4gICAqIGNsaWVudC51cGxvYWQoZmlsZSwgeyBvblJldHJ5IH0sIHsgZmlsZW5hbWU6ICdmb29iYXIuanBnJyB9LCB0b2tlbilcbiAgICogICAudGhlbihyZXMgPT4gY29uc29sZS5sb2cocmVzKSk7XG4gICAqXG4gICAqIGNsaWVudC51cGxvYWQoe2ZpbGUsIG5hbWV9LCB7IG9uUmV0cnkgfSwgeyBmaWxlbmFtZTogJ2Zvb2Jhci5qcGcnIH0sIHRva2VuKVxuICAgKiAgIC50aGVuKHJlcyA9PiBjb25zb2xlLmxvZyhyZXMpKTtcbiAgICpcbiAgICogdG9rZW4ucGF1c2UoKTsgIC8vIFBhdXNlIGZsb3dcbiAgICogdG9rZW4ucmVzdW1lKCk7IC8vIFJlc3VtZSBmbG93XG4gICAqIHRva2VuLmNhbmNlbCgpOyAvLyBDYW5jZWwgZmxvdyAocmVqZWN0cylcbiAgICogYGBgXG4gICAqIEBwYXJhbSB7SW5wdXRGaWxlfSAgICBmaWxlICAgICAgICAgICBNdXN0IGJlIGEgdmFsaWQgW0ZpbGUgfCBCbG9iIHwgQnVmZmVyIHwgc3RyaW5nXVxuICAgKiBAcGFyYW0gdXBsb2FkT3B0aW9ucyAgVXBsb2FkZXIgb3B0aW9ucy5cbiAgICogQHBhcmFtIHN0b3JlT3B0aW9ucyAgIFN0b3JhZ2Ugb3B0aW9ucy5cbiAgICogQHBhcmFtIHRva2VuICAgICAgICAgIEEgY29udHJvbCB0b2tlbiB0aGF0IGNhbiBiZSB1c2VkIHRvIGNhbGwgY2FuY2VsKCksIHBhdXNlKCksIGFuZCByZXN1bWUoKS5cbiAgICogQHBhcmFtIHNlY3VyaXR5ICAgICAgIE9wdGlvbmFsIHNlY3VyaXR5IHBvbGljeSBhbmQgc2lnbmF0dXJlIG92ZXJyaWRlLlxuICAgKlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZX1cbiAgICovXG4gIHVwbG9hZChmaWxlOiBJbnB1dEZpbGUsIG9wdGlvbnM/OiBVcGxvYWRPcHRpb25zLCBzdG9yZU9wdGlvbnM/OiBTdG9yZVVwbG9hZE9wdGlvbnMsIHRva2VuPzogYW55LCBzZWN1cml0eT86IFNlY3VyaXR5KSB7XG4gICAgbGV0IHVwbG9hZCA9IG5ldyBVcGxvYWQob3B0aW9ucywgc3RvcmVPcHRpb25zKTtcbiAgICB1cGxvYWQuc2V0U2Vzc2lvbih0aGlzLnNlc3Npb24pO1xuXG4gICAgaWYgKHRva2VuKSB7XG4gICAgICB1cGxvYWQuc2V0VG9rZW4odG9rZW4pO1xuICAgIH1cblxuICAgIGlmIChzZWN1cml0eSkge1xuICAgICAgdXBsb2FkLnNldFNlY3VyaXR5KHNlY3VyaXR5KTtcbiAgICB9XG5cbiAgICB1cGxvYWQub24oJ3N0YXJ0JywgKCkgPT4gdGhpcy5lbWl0KCd1cGxvYWQuc3RhcnQnKSk7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICB1cGxvYWQub24oJ2Vycm9yJywgZSA9PiB7XG4gICAgICBpZiAodGhpcy5mb3J3YXJkRXJyb3JzKSB7XG4gICAgICAgIFNlbnRyeS53aXRoU2NvcGUoc2NvcGUgPT4ge1xuICAgICAgICAgIHNjb3BlLnNldFRhZygnZmlsZXN0YWNrLWFwaWtleScsIHRoaXMuc2Vzc2lvbi5hcGlrZXkpO1xuICAgICAgICAgIHNjb3BlLnNldFRhZygnZmlsZXN0YWNrLXZlcnNpb24nLCBVdGlscy5nZXRWZXJzaW9uKCkpO1xuICAgICAgICAgIHNjb3BlLnNldEV4dHJhKCdmaWxlc3RhY2stb3B0aW9ucycsIHRoaXMub3B0aW9ucyk7XG4gICAgICAgICAgc2NvcGUuc2V0RXh0cmFzKHsgdXBsb2FkT3B0aW9uczogb3B0aW9ucywgc3RvcmVPcHRpb25zLCBkZXRhaWxzOiBlLmRldGFpbHMgfSk7XG4gICAgICAgICAgZS5tZXNzYWdlID0gYEZTLSR7ZS5tZXNzYWdlfWA7XG4gICAgICAgICAgc2NvcGUuY2FwdHVyZUV4Y2VwdGlvbihlKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuZW1pdCgndXBsb2FkLmVycm9yJywgZSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gdXBsb2FkLnVwbG9hZChmaWxlLCBvcHRpb25zICYmIG9wdGlvbnMuYWx0VGV4dCk7XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhdGVzIGEgbXVsdGktcGFydCB1cGxvYWQgZmxvdy4gVXNlIHRoaXMgZm9yIEZpbGVzdGFjayBDSU4gYW5kIEZJSSB1cGxvYWRzLlxuICAgKlxuICAgKiBJbiBOb2RlIHJ1bnRpbWVzIHRoZSBmaWxlIGFyZ3VtZW50IGlzIHRyZWF0ZWQgYXMgYSBmaWxlIHBhdGguXG4gICAqIFVwbG9hZGluZyBmcm9tIGEgTm9kZSBidWZmZXIgaXMgbm90IHlldCBpbXBsZW1lbnRlZC5cbiAgICpcbiAgICogIyMjIEV4YW1wbGVcbiAgICpcbiAgICogYGBganNcbiAgICogY29uc3QgdG9rZW4gPSB7fTtcbiAgICogY29uc3Qgb25SZXRyeSA9IChvYmopID0+IHtcbiAgICogICBjb25zb2xlLmxvZyhgUmV0cnlpbmcgJHtvYmoubG9jYXRpb259IGZvciAke29iai5maWxlbmFtZX0uIEF0dGVtcHQgJHtvYmouYXR0ZW1wdH0gb2YgMTAuYCk7XG4gICAqIH07XG4gICAqXG4gICAqIGNsaWVudC5tdWx0aXVwbG9hZChbZmlsZV0sIHsgb25SZXRyeSB9LCB0b2tlbilcbiAgICogICAudGhlbihyZXMgPT4gY29uc29sZS5sb2cocmVzKSk7XG4gICAqXG4gICAqIGNsaWVudC5tdWx0aXVwbG9hZChbe2ZpbGUsIG5hbWV9XSwgeyBvblJldHJ5IH0sIHRva2VuKVxuICAgKiAgIC50aGVuKHJlcyA9PiBjb25zb2xlLmxvZyhyZXMpKTtcbiAgICpcbiAgICogdG9rZW4ucGF1c2UoKTsgIC8vIFBhdXNlIGZsb3dcbiAgICogdG9rZW4ucmVzdW1lKCk7IC8vIFJlc3VtZSBmbG93XG4gICAqIHRva2VuLmNhbmNlbCgpOyAvLyBDYW5jZWwgZmxvdyAocmVqZWN0cylcbiAgICogYGBgXG4gICAqIEBwYXJhbSB7SW5wdXRGaWxlW119ICBmaWxlICAgICAgICAgICBNdXN0IGJlIGEgdmFsaWQgW0ZpbGUgfCBCbG9iIHwgQnVmZmVyIHwgc3RyaW5nIChiYXNlNjQpXVxuICAgKiBAcGFyYW0gdXBsb2FkT3B0aW9ucyAgVXBsb2FkIG9wdGlvbnMuXG4gICAqIEBwYXJhbSBzdG9yZU9wdGlvbnMgICBTdG9yYWdlIG9wdGlvbnMuXG4gICAqIEBwYXJhbSB0b2tlbiAgICAgICAgICBBIGNvbnRyb2wgdG9rZW4gdGhhdCBjYW4gYmUgdXNlZCB0byBjYWxsIGNhbmNlbCgpLCBwYXVzZSgpLCBhbmQgcmVzdW1lKCkuXG4gICAqIEBwYXJhbSBzZWN1cml0eSAgICAgICBPcHRpb25hbCBzZWN1cml0eSBwb2xpY3kgYW5kIHNpZ25hdHVyZSBvdmVycmlkZS5cbiAgICpcbiAgICogQHJldHVybnMge1Byb21pc2V9XG4gICAqL1xuICBtdWx0aXVwbG9hZChmaWxlOiBJbnB1dEZpbGVbXSwgb3B0aW9ucz86IFVwbG9hZE9wdGlvbnMsIHN0b3JlT3B0aW9ucz86IFN0b3JlVXBsb2FkT3B0aW9ucywgdG9rZW4/OiBhbnksIHNlY3VyaXR5PzogU2VjdXJpdHkpIHtcbiAgICBsZXQgdXBsb2FkID0gbmV3IFVwbG9hZChvcHRpb25zLCBzdG9yZU9wdGlvbnMpO1xuXG4gICAgdXBsb2FkLnNldFNlc3Npb24odGhpcy5zZXNzaW9uKTtcblxuICAgIGlmICh0b2tlbikge1xuICAgICAgdXBsb2FkLnNldFRva2VuKHRva2VuKTtcbiAgICB9XG5cbiAgICBpZiAoc2VjdXJpdHkpIHtcbiAgICAgIHVwbG9hZC5zZXRTZWN1cml0eShzZWN1cml0eSk7XG4gICAgfVxuXG4gICAgdXBsb2FkLm9uKCdzdGFydCcsICgpID0+IHRoaXMuZW1pdCgndXBsb2FkLnN0YXJ0JykpO1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdXBsb2FkLm9uKCdlcnJvcicsIGUgPT4ge1xuICAgICAgU2VudHJ5LndpdGhTY29wZShzY29wZSA9PiB7XG4gICAgICAgIHNjb3BlLnNldFRhZygnZmlsZXN0YWNrLWFwaWtleScsIHRoaXMuc2Vzc2lvbi5hcGlrZXkpO1xuICAgICAgICBzY29wZS5zZXRUYWcoJ2ZpbGVzdGFjay12ZXJzaW9uJywgVXRpbHMuZ2V0VmVyc2lvbigpKTtcbiAgICAgICAgc2NvcGUuc2V0RXh0cmEoJ2ZpbGVzdGFjay1vcHRpb25zJywgdGhpcy5vcHRpb25zKTtcbiAgICAgICAgc2NvcGUuc2V0RXh0cmFzKGUuZGV0YWlscyk7XG4gICAgICAgIHNjb3BlLnNldEV4dHJhcyh7IHVwbG9hZE9wdGlvbnM6IG9wdGlvbnMsIHN0b3JlT3B0aW9ucyB9KTtcbiAgICAgICAgc2NvcGUuY2FwdHVyZUV4Y2VwdGlvbihlKTtcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLmVtaXQoJ3VwbG9hZC5lcnJvcicsIGUpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHVwbG9hZC5tdWx0aXVwbG9hZChmaWxlKTtcbiAgfVxufVxuIl19