Skip to content

Instantly share code, notes, and snippets.

@Acconut
Created May 21, 2017 10:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Acconut/70a9e263a23d027f044a5da50abe045c to your computer and use it in GitHub Desktop.
Save Acconut/70a9e263a23d027f044a5da50abe045c to your computer and use it in GitHub Desktop.
requirebin sketch
var Uppy = require('uppy')
var Transloadit = require('uppy/src/plugins/Transloadit')
var uppy = new Uppy.Core({wait: false, debug: true})
uppy
.use(Transloadit, {
params: {
steps: {
"screenshot": {
"robot": "/html/convert",
"url": "http://lunrjs.com/"
},
"resize": {
"use": "screenshot",
"robot": "/image/resize",
"width": 400,
"height": 300,
"strip": true,
"resize_strategy": "crop",
"gravity": "top"
}
},
auth: {
key: "AUTH_KEY"
}
},
waitForEncoding: true
})
.run()
uppy.upload()
.then(console.log)
.catch(console.error)
uppy.on('transloadit:result', (stepName, result) => {
console.log("result", result.ssl_url)
var img = new Image()
img.width = 300
img.alt = fileId
img.src = result.ssl_url
document.body.appendChild(img)
})
This file has been truncated, but you can view the full file.
setTimeout(function(){
;require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
},{}],2:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
// cached from whatever global is present so that test runners that stub it
// don't break things. But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals. It's inside a
// function because try/catches deoptimize in certain engines.
var cachedSetTimeout;
var cachedClearTimeout;
function defaultSetTimout() {
throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout () {
throw new Error('clearTimeout has not been defined');
}
(function () {
try {
if (typeof setTimeout === 'function') {
cachedSetTimeout = setTimeout;
} else {
cachedSetTimeout = defaultSetTimout;
}
} catch (e) {
cachedSetTimeout = defaultSetTimout;
}
try {
if (typeof clearTimeout === 'function') {
cachedClearTimeout = clearTimeout;
} else {
cachedClearTimeout = defaultClearTimeout;
}
} catch (e) {
cachedClearTimeout = defaultClearTimeout;
}
} ())
function runTimeout(fun) {
if (cachedSetTimeout === setTimeout) {
//normal enviroments in sane situations
return setTimeout(fun, 0);
}
// if setTimeout wasn't available but was latter defined
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
cachedSetTimeout = setTimeout;
return setTimeout(fun, 0);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedSetTimeout(fun, 0);
} catch(e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedSetTimeout.call(null, fun, 0);
} catch(e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
return cachedSetTimeout.call(this, fun, 0);
}
}
}
function runClearTimeout(marker) {
if (cachedClearTimeout === clearTimeout) {
//normal enviroments in sane situations
return clearTimeout(marker);
}
// if clearTimeout wasn't available but was latter defined
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
cachedClearTimeout = clearTimeout;
return clearTimeout(marker);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedClearTimeout(marker);
} catch (e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedClearTimeout.call(null, marker);
} catch (e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
return cachedClearTimeout.call(this, marker);
}
}
}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
if (!draining || !currentQueue) {
return;
}
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = runTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
runClearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
runTimeout(drainQueue);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };
},{}],3:[function(require,module,exports){
(function (global){
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Utils = require('../core/Utils');
var Translator = require('../core/Translator');
var UppySocket = require('./UppySocket');
var ee = require('namespace-emitter');
var throttle = require('lodash.throttle');
// const en_US = require('../locales/en_US')
// const deepFreeze = require('deep-freeze-strict')
/**
* Main Uppy core
*
* @param {object} opts general options, like locales, to show modal or not to show
*/
var Uppy = function () {
function Uppy(opts) {
_classCallCheck(this, Uppy);
// set default options
var defaultOptions = {
// load English as the default locale
// locale: en_US,
autoProceed: true,
debug: false
};
// Merge default options with the ones set by user
this.opts = _extends({}, defaultOptions, opts);
// // Dictates in what order different plugin types are ran:
// this.types = [ 'presetter', 'orchestrator', 'progressindicator',
// 'acquirer', 'modifier', 'uploader', 'presenter', 'debugger']
// Container for different types of plugins
this.plugins = {};
this.translator = new Translator({ locale: this.opts.locale });
this.i18n = this.translator.translate.bind(this.translator);
this.getState = this.getState.bind(this);
this.updateMeta = this.updateMeta.bind(this);
this.initSocket = this.initSocket.bind(this);
this.log = this.log.bind(this);
this.addFile = this.addFile.bind(this);
this.calculateProgress = this.calculateProgress.bind(this);
this.bus = this.emitter = ee();
this.on = this.bus.on.bind(this.bus);
this.emit = this.bus.emit.bind(this.bus);
this.preProcessors = [];
this.uploaders = [];
this.postProcessors = [];
this.state = {
files: {},
capabilities: {
resumableUploads: false
},
totalProgress: 0
};
// for debugging and testing
this.updateNum = 0;
if (this.opts.debug) {
global.UppyState = this.state;
global.uppyLog = '';
global.UppyAddFile = this.addFile.bind(this);
global._Uppy = this;
}
}
/**
* Iterate on all plugins and run `update` on them. Called each time state changes
*
*/
Uppy.prototype.updateAll = function updateAll(state) {
var _this = this;
Object.keys(this.plugins).forEach(function (pluginType) {
_this.plugins[pluginType].forEach(function (plugin) {
plugin.update(state);
});
});
};
/**
* Updates state
*
* @param {newState} object
*/
Uppy.prototype.setState = function setState(stateUpdate) {
var newState = _extends({}, this.state, stateUpdate);
this.emit('core:state-update', this.state, newState, stateUpdate);
this.state = newState;
this.updateAll(this.state);
};
/**
* Returns current state
*
*/
Uppy.prototype.getState = function getState() {
// use deepFreeze for debugging
// return deepFreeze(this.state)
return this.state;
};
Uppy.prototype.addPreProcessor = function addPreProcessor(fn) {
this.preProcessors.push(fn);
};
Uppy.prototype.removePreProcessor = function removePreProcessor(fn) {
var i = this.preProcessors.indexOf(fn);
if (i !== -1) {
this.preProcessors.splice(i, 1);
}
};
Uppy.prototype.addPostProcessor = function addPostProcessor(fn) {
this.postProcessors.push(fn);
};
Uppy.prototype.removePostProcessor = function removePostProcessor(fn) {
var i = this.postProcessors.indexOf(fn);
if (i !== -1) {
this.postProcessors.splice(i, 1);
}
};
Uppy.prototype.addUploader = function addUploader(fn) {
this.uploaders.push(fn);
};
Uppy.prototype.removeUploader = function removeUploader(fn) {
var i = this.uploaders.indexOf(fn);
if (i !== -1) {
this.uploaders.splice(i, 1);
}
};
Uppy.prototype.updateMeta = function updateMeta(data, fileID) {
var updatedFiles = _extends({}, this.getState().files);
var newMeta = _extends({}, updatedFiles[fileID].meta, data);
updatedFiles[fileID] = _extends({}, updatedFiles[fileID], {
meta: newMeta
});
this.setState({ files: updatedFiles });
};
Uppy.prototype.addFile = function addFile(file) {
var updatedFiles = _extends({}, this.state.files);
var fileName = file.name || 'noname';
var fileType = Utils.getFileType(file);
var fileTypeGeneral = fileType[0];
var fileTypeSpecific = fileType[1];
var fileExtension = Utils.getFileNameAndExtension(fileName)[1];
var isRemote = file.isRemote || false;
var fileID = Utils.generateFileID(fileName);
var newFile = {
source: file.source || '',
id: fileID,
name: fileName,
extension: fileExtension || '',
meta: {
name: fileName
},
type: {
general: fileTypeGeneral,
specific: fileTypeSpecific
},
data: file.data,
progress: {
percentage: 0,
uploadComplete: false,
uploadStarted: false
},
size: file.data.size || 'N/A',
isRemote: isRemote,
remote: file.remote || '',
preview: file.preview
};
updatedFiles[fileID] = newFile;
this.setState({ files: updatedFiles });
this.bus.emit('file-added', fileID);
this.log('Added file: ' + fileName + ', ' + fileID + ', mime type: ' + fileType);
if (fileTypeGeneral === 'image' && !isRemote) {
this.addThumbnail(newFile.id);
}
if (this.opts.autoProceed) {
this.upload().catch(function (err) {
console.error(err.stack || err.message);
});
// this.bus.emit('core:upload')
}
};
Uppy.prototype.removeFile = function removeFile(fileID) {
var updatedFiles = _extends({}, this.getState().files);
delete updatedFiles[fileID];
this.setState({ files: updatedFiles });
this.calculateTotalProgress();
this.log('Removed file: ' + fileID);
};
Uppy.prototype.addThumbnail = function addThumbnail(fileID) {
var _this2 = this;
var file = this.getState().files[fileID];
// const thumbnail = URL.createObjectURL(file.data)
// const updatedFiles = Object.assign({}, this.getState().files)
// const updatedFile = Object.assign({}, updatedFiles[fileID], {
// preview: thumbnail
// })
// updatedFiles[fileID] = updatedFile
// this.setState({files: updatedFiles})
Utils.readFile(file.data).then(function (imgDataURI) {
return Utils.createImageThumbnail(imgDataURI, 200);
}).then(function (thumbnail) {
var updatedFiles = _extends({}, _this2.getState().files);
var updatedFile = _extends({}, updatedFiles[fileID], {
preview: thumbnail
});
updatedFiles[fileID] = updatedFile;
_this2.setState({ files: updatedFiles });
}).catch(function (err) {
return _this2.log(err);
});
};
Uppy.prototype.calculateProgress = function calculateProgress(data) {
var fileID = data.id;
var updatedFiles = _extends({}, this.getState().files);
// skip progress event for a file that’s been removed
if (!updatedFiles[fileID]) {
this.log('Trying to set progress for a file that’s not with us anymore: ', fileID);
return;
}
var updatedFile = _extends({}, updatedFiles[fileID], _extends({}, {
progress: _extends({}, updatedFiles[fileID].progress, {
bytesUploaded: data.bytesUploaded,
bytesTotal: data.bytesTotal,
percentage: Math.floor((data.bytesUploaded / data.bytesTotal * 100).toFixed(2))
})
}));
updatedFiles[data.id] = updatedFile;
this.setState({
files: updatedFiles
});
this.calculateTotalProgress();
};
Uppy.prototype.calculateTotalProgress = function calculateTotalProgress() {
// calculate total progress, using the number of files currently uploading,
// multiplied by 100 and the summ of individual progress of each file
var files = _extends({}, this.getState().files);
var inProgress = Object.keys(files).filter(function (file) {
return files[file].progress.uploadStarted;
});
var progressMax = inProgress.length * 100;
var progressAll = 0;
inProgress.forEach(function (file) {
progressAll = progressAll + files[file].progress.percentage;
});
var totalProgress = Math.floor((progressAll * 100 / progressMax).toFixed(2));
this.setState({
totalProgress: totalProgress
});
// if (totalProgress === 100) {
// const completeFiles = Object.keys(updatedFiles).filter((file) => {
// // this should be `uploadComplete`
// return updatedFiles[file].progress.percentage === 100
// })
// this.emit('core:success', completeFiles.length)
// }
};
/**
* Registers listeners for all global actions, like:
* `file-add`, `file-remove`, `upload-progress`, `reset`
*
*/
Uppy.prototype.actions = function actions() {
var _this3 = this;
// this.bus.on('*', (payload) => {
// console.log('emitted: ', this.event)
// console.log('with payload: ', payload)
// })
// stress-test re-rendering
// setInterval(() => {
// this.setState({bla: 'bla'})
// }, 20)
this.on('core:file-add', function (data) {
_this3.addFile(data);
});
// `remove-file` removes a file from `state.files`, for example when
// a user decides not to upload particular file and clicks a button to remove it
this.on('core:file-remove', function (fileID) {
_this3.removeFile(fileID);
});
this.on('core:cancel-all', function () {
var files = _this3.getState().files;
Object.keys(files).forEach(function (file) {
_this3.removeFile(files[file].id);
});
});
this.on('core:upload-started', function (fileID, upload) {
var updatedFiles = _extends({}, _this3.getState().files);
var updatedFile = _extends({}, updatedFiles[fileID], _extends({}, {
progress: _extends({}, updatedFiles[fileID].progress, {
uploadStarted: Date.now()
})
}));
updatedFiles[fileID] = updatedFile;
_this3.setState({ files: updatedFiles });
});
// upload progress events can occur frequently, especially when you have a good
// connection to the remote server. Therefore, we are throtteling them to
// prevent accessive function calls.
// see also: https://github.com/tus/tus-js-client/commit/9940f27b2361fd7e10ba58b09b60d82422183bbb
var throttledCalculateProgress = throttle(this.calculateProgress, 100, { leading: true, trailing: false });
this.on('core:upload-progress', function (data) {
// this.calculateProgress(data)
throttledCalculateProgress(data);
});
this.on('core:upload-success', function (fileID, uploadResp, uploadURL) {
var updatedFiles = _extends({}, _this3.getState().files);
var updatedFile = _extends({}, updatedFiles[fileID], {
progress: _extends({}, updatedFiles[fileID].progress, {
uploadComplete: true,
// good or bad idea? setting the percentage to 100 if upload is successful,
// so that if we lost some progress events on the way, its still marked “compete”?
percentage: 100
}),
uploadURL: uploadURL
});
updatedFiles[fileID] = updatedFile;
_this3.setState({
files: updatedFiles
});
_this3.calculateTotalProgress();
if (_this3.getState().totalProgress === 100) {
var completeFiles = Object.keys(updatedFiles).filter(function (file) {
return updatedFiles[file].progress.uploadComplete;
});
_this3.emit('core:upload-complete', completeFiles.length);
}
});
this.on('core:update-meta', function (data, fileID) {
_this3.updateMeta(data, fileID);
});
// show informer if offline
if (typeof window !== 'undefined') {
window.addEventListener('online', function () {
return _this3.isOnline(true);
});
window.addEventListener('offline', function () {
return _this3.isOnline(false);
});
setTimeout(function () {
return _this3.isOnline();
}, 3000);
}
};
Uppy.prototype.isOnline = function isOnline(status) {
var online = status || window.navigator.onLine;
if (!online) {
this.emit('is-offline');
this.emit('informer', 'No internet connection', 'error', 0);
this.wasOffline = true;
} else {
this.emit('is-online');
if (this.wasOffline) {
this.emit('back-online');
this.emit('informer', 'Connected!', 'success', 3000);
this.wasOffline = false;
}
}
};
/**
* Registers a plugin with Core
*
* @param {Class} Plugin object
* @param {Object} options object that will be passed to Plugin later
* @return {Object} self for chaining
*/
Uppy.prototype.use = function use(Plugin, opts) {
// Instantiate
var plugin = new Plugin(this, opts);
var pluginName = plugin.id;
this.plugins[plugin.type] = this.plugins[plugin.type] || [];
if (!pluginName) {
throw new Error('Your plugin must have a name');
}
if (!plugin.type) {
throw new Error('Your plugin must have a type');
}
var existsPluginAlready = this.getPlugin(pluginName);
if (existsPluginAlready) {
var msg = 'Already found a plugin named \'' + existsPluginAlready.name + '\'.\n Tried to use: \'' + pluginName + '\'.\n Uppy is currently limited to running one of every plugin.\n Share your use case with us over at\n https://github.com/transloadit/uppy/issues/\n if you want us to reconsider.';
throw new Error(msg);
}
this.plugins[plugin.type].push(plugin);
plugin.install();
return this;
};
/**
* Find one Plugin by name
*
* @param string name description
*/
Uppy.prototype.getPlugin = function getPlugin(name) {
var foundPlugin = false;
this.iteratePlugins(function (plugin) {
var pluginName = plugin.id;
if (pluginName === name) {
foundPlugin = plugin;
return false;
}
});
return foundPlugin;
};
/**
* Iterate through all `use`d plugins
*
* @param function method description
*/
Uppy.prototype.iteratePlugins = function iteratePlugins(method) {
var _this4 = this;
Object.keys(this.plugins).forEach(function (pluginType) {
_this4.plugins[pluginType].forEach(method);
});
};
/**
* Uninstall and remove a plugin.
*
* @param {Plugin} instance The plugin instance to remove.
*/
Uppy.prototype.removePlugin = function removePlugin(instance) {
var list = this.plugins[instance.type];
if (instance.uninstall) {
instance.uninstall();
}
var index = list.indexOf(instance);
if (index !== -1) {
list.splice(index, 1);
}
};
/**
* Uninstall all plugins and close down this Uppy instance.
*/
Uppy.prototype.close = function close() {
this.iteratePlugins(function (plugin) {
plugin.uninstall();
});
if (this.socket) {
this.socket.close();
}
};
/**
* Logs stuff to console, only if `debug` is set to true. Silent in production.
*
* @return {String|Object} to log
*/
Uppy.prototype.log = function log(msg, type) {
if (!this.opts.debug) {
return;
}
if (msg === '' + msg) {
console.log('LOG: ' + msg);
} else {
console.dir(msg);
}
if (type === 'error') {
console.error('LOG: ' + msg);
}
global.uppyLog = global.uppyLog + '\n' + 'DEBUG LOG: ' + msg;
};
Uppy.prototype.initSocket = function initSocket(opts) {
if (!this.socket) {
this.socket = new UppySocket(opts);
}
return this.socket;
};
// installAll () {
// Object.keys(this.plugins).forEach((pluginType) => {
// this.plugins[pluginType].forEach((plugin) => {
// plugin.install(this)
// })
// })
// }
/**
* Initializes actions, installs all plugins (by iterating on them and calling `install`), sets options
*
*/
Uppy.prototype.run = function run() {
this.log('Core is run, initializing actions...');
this.actions();
// Forse set `autoProceed` option to false if there are multiple selector Plugins active
// if (this.plugins.acquirer && this.plugins.acquirer.length > 1) {
// this.opts.autoProceed = false
// }
// Install all plugins
// this.installAll()
return;
};
Uppy.prototype.upload = function upload() {
var _this5 = this;
var promise = Promise.resolve();
this.emit('core:upload');[].concat(this.preProcessors, this.uploaders, this.postProcessors).forEach(function (fn) {
promise = promise.then(function () {
return fn();
});
});
// Not returning the `catch`ed promise, because we still want to return a rejected
// promise from this method if the upload failed.
promise.catch(function (err) {
_this5.emit('core:error', err);
});
return promise.then(function () {
_this5.emit('core:success');
});
};
return Uppy;
}();
module.exports = function (opts) {
if (!(this instanceof Uppy)) {
return new Uppy(opts);
}
};
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"../core/Translator":4,"../core/Utils":6,"./UppySocket":5,"lodash.throttle":61,"namespace-emitter":62}],4:[function(require,module,exports){
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Translates strings with interpolation & pluralization support.
* Extensible with custom dictionaries and pluralization functions.
*
* Borrows heavily from and inspired by Polyglot https://github.com/airbnb/polyglot.js,
* basically a stripped-down version of it. Differences: pluralization functions are not hardcoded
* and can be easily added among with dictionaries, nested objects are used for pluralization
* as opposed to `||||` delimeter
*
* Usage example: `translator.translate('files_chosen', {smart_count: 3})`
*
* @param {object} opts
*/
module.exports = function () {
function Translator(opts) {
_classCallCheck(this, Translator);
var defaultOptions = {
locale: {
strings: {},
pluralize: function pluralize(n) {
if (n === 1) {
return 0;
}
return 1;
}
}
};
this.opts = _extends({}, defaultOptions, opts);
this.locale = _extends({}, defaultOptions.locale, opts.locale);
// console.log(this.opts.locale)
// this.locale.pluralize = this.locale ? this.locale.pluralize : defaultPluralize
// this.locale.strings = Object.assign({}, en_US.strings, this.opts.locale.strings)
}
/**
* Takes a string with placeholder variables like `%{smart_count} file selected`
* and replaces it with values from options `{smart_count: 5}`
*
* @license https://github.com/airbnb/polyglot.js/blob/master/LICENSE
* taken from https://github.com/airbnb/polyglot.js/blob/master/lib/polyglot.js#L299
*
* @param {string} phrase that needs interpolation, with placeholders
* @param {object} options with values that will be used to replace placeholders
* @return {string} interpolated
*/
Translator.prototype.interpolate = function interpolate(phrase, options) {
var replace = String.prototype.replace;
var dollarRegex = /\$/g;
var dollarBillsYall = '$$$$';
for (var arg in options) {
if (arg !== '_' && options.hasOwnProperty(arg)) {
// Ensure replacement value is escaped to prevent special $-prefixed
// regex replace tokens. the "$$$$" is needed because each "$" needs to
// be escaped with "$" itself, and we need two in the resulting output.
var replacement = options[arg];
if (typeof replacement === 'string') {
replacement = replace.call(options[arg], dollarRegex, dollarBillsYall);
}
// We create a new `RegExp` each time instead of using a more-efficient
// string replace so that the same argument can be replaced multiple times
// in the same phrase.
phrase = replace.call(phrase, new RegExp('%\\{' + arg + '\\}', 'g'), replacement);
}
}
return phrase;
};
/**
* Public translate method
*
* @param {string} key
* @param {object} options with values that will be used later to replace placeholders in string
* @return {string} translated (and interpolated)
*/
Translator.prototype.translate = function translate(key, options) {
if (options && options.smart_count) {
var plural = this.locale.pluralize(options.smart_count);
return this.interpolate(this.opts.locale.strings[key][plural], options);
}
return this.interpolate(this.opts.locale.strings[key], options);
};
return Translator;
}();
},{}],5:[function(require,module,exports){
'use strict';
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var ee = require('namespace-emitter');
module.exports = function () {
function UppySocket(opts) {
var _this = this;
_classCallCheck(this, UppySocket);
this.queued = [];
this.isOpen = false;
this.socket = new WebSocket(opts.target);
this.emitter = ee();
this.socket.onopen = function (e) {
_this.isOpen = true;
while (_this.queued.length > 0 && _this.isOpen) {
var first = _this.queued[0];
_this.send(first.action, first.payload);
_this.queued = _this.queued.slice(1);
}
};
this.socket.onclose = function (e) {
_this.isOpen = false;
};
this._handleMessage = this._handleMessage.bind(this);
this.socket.onmessage = this._handleMessage;
this.close = this.close.bind(this);
this.emit = this.emit.bind(this);
this.on = this.on.bind(this);
this.once = this.once.bind(this);
this.send = this.send.bind(this);
}
UppySocket.prototype.close = function close() {
return this.socket.close();
};
UppySocket.prototype.send = function send(action, payload) {
// attach uuid
if (!this.isOpen) {
this.queued.push({ action: action, payload: payload });
return;
}
this.socket.send(JSON.stringify({
action: action,
payload: payload
}));
};
UppySocket.prototype.on = function on(action, handler) {
console.log(action);
this.emitter.on(action, handler);
};
UppySocket.prototype.emit = function emit(action, payload) {
console.log(action);
this.emitter.emit(action, payload);
};
UppySocket.prototype.once = function once(action, handler) {
this.emitter.once(action, handler);
};
UppySocket.prototype._handleMessage = function _handleMessage(e) {
try {
var message = JSON.parse(e.data);
console.log(message);
this.emit(message.action, message.payload);
} catch (err) {
console.log(err);
}
};
return UppySocket;
}();
},{"namespace-emitter":62}],6:[function(require,module,exports){
'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;
// import mime from 'mime-types'
// import pica from 'pica'
/**
* A collection of small utility functions that help with dom manipulation, adding listeners,
* promises and other good things.
*
* @module Utils
*/
/**
* Shallow flatten nested arrays.
*/
function flatten(arr) {
return [].concat.apply([], arr);
}
function isTouchDevice() {
return 'ontouchstart' in window || // works on most browsers
navigator.maxTouchPoints; // works on IE10/11 and Surface
}
// /**
// * Shorter and fast way to select a single node in the DOM
// * @param { String } selector - unique dom selector
// * @param { Object } ctx - DOM node where the target of our search will is located
// * @returns { Object } dom node found
// */
// function $ (selector, ctx) {
// return (ctx || document).querySelector(selector)
// }
// /**
// * Shorter and fast way to select multiple nodes in the DOM
// * @param { String|Array } selector - DOM selector or nodes list
// * @param { Object } ctx - DOM node where the targets of our search will is located
// * @returns { Object } dom nodes found
// */
// function $$ (selector, ctx) {
// var els
// if (typeof selector === 'string') {
// els = (ctx || document).querySelectorAll(selector)
// } else {
// els = selector
// return Array.prototype.slice.call(els)
// }
// }
function truncateString(str, length) {
if (str.length > length) {
return str.substr(0, length / 2) + '...' + str.substr(str.length - length / 4, str.length);
}
return str;
// more precise version if needed
// http://stackoverflow.com/a/831583
}
function secondsToTime(rawSeconds) {
var hours = Math.floor(rawSeconds / 3600) % 24;
var minutes = Math.floor(rawSeconds / 60) % 60;
var seconds = Math.floor(rawSeconds % 60);
return { hours: hours, minutes: minutes, seconds: seconds };
}
/**
* Partition array by a grouping function.
* @param {[type]} array Input array
* @param {[type]} groupingFn Grouping function
* @return {[type]} Array of arrays
*/
function groupBy(array, groupingFn) {
return array.reduce(function (result, item) {
var key = groupingFn(item);
var xs = result.get(key) || [];
xs.push(item);
result.set(key, xs);
return result;
}, new Map());
}
/**
* Tests if every array element passes predicate
* @param {Array} array Input array
* @param {Object} predicateFn Predicate
* @return {bool} Every element pass
*/
function every(array, predicateFn) {
return array.reduce(function (result, item) {
if (!result) {
return false;
}
return predicateFn(item);
}, true);
}
/**
* Converts list into array
*/
function toArray(list) {
return Array.prototype.slice.call(list || [], 0);
}
/**
* Takes a fileName and turns it into fileID, by converting to lowercase,
* removing extra characters and adding unix timestamp
*
* @param {String} fileName
*
*/
function generateFileID(fileName) {
var fileID = fileName.toLowerCase();
fileID = fileID.replace(/[^A-Z0-9]/ig, '');
fileID = fileID + Date.now();
return fileID;
}
function extend() {
for (var _len = arguments.length, objs = Array(_len), _key = 0; _key < _len; _key++) {
objs[_key] = arguments[_key];
}
return Object.assign.apply(this, [{}].concat(objs));
}
/**
* Takes function or class, returns its name.
* Because IE doesn’t support `constructor.name`.
* https://gist.github.com/dfkaye/6384439, http://stackoverflow.com/a/15714445
*
* @param {Object} fn — function
*
*/
// function getFnName (fn) {
// var f = typeof fn === 'function'
// var s = f && ((fn.name && ['', fn.name]) || fn.toString().match(/function ([^\(]+)/))
// return (!f && 'not a function') || (s && s[1] || 'anonymous')
// }
function getProportionalImageHeight(img, newWidth) {
var aspect = img.width / img.height;
var newHeight = Math.round(newWidth / aspect);
return newHeight;
}
function getFileType(file) {
return file.type ? file.type.split('/') : ['', ''];
// return mime.lookup(file.name)
}
// TODO Check which types are actually supported in browsers. Chrome likes webm
// from my testing, but we may need more.
// We could use a library but they tend to contain dozens of KBs of mappings,
// most of which will go unused, so not sure if that's worth it.
var mimeToExtensions = {
'video/ogg': 'ogv',
'audio/ogg': 'ogg',
'video/webm': 'webm',
'audio/webm': 'webm',
'video/mp4': 'mp4',
'audio/mp3': 'mp3'
};
function getFileTypeExtension(mimeType) {
return mimeToExtensions[mimeType] || null;
}
// returns [fileName, fileExt]
function getFileNameAndExtension(fullFileName) {
var re = /(?:\.([^.]+))?$/;
var fileExt = re.exec(fullFileName)[1];
var fileName = fullFileName.replace('.' + fileExt, '');
return [fileName, fileExt];
}
/**
* Reads file as data URI from file object,
* the one you get from input[type=file] or drag & drop.
*
* @param {Object} file object
* @return {Promise} dataURL of the file
*
*/
function readFile(fileObj) {
return new _Promise(function (resolve, reject) {
var reader = new FileReader();
reader.addEventListener('load', function (ev) {
return resolve(ev.target.result);
});
reader.readAsDataURL(fileObj);
// function workerScript () {
// self.addEventListener('message', (e) => {
// const file = e.data.file
// try {
// const reader = new FileReaderSync()
// postMessage({
// file: reader.readAsDataURL(file)
// })
// } catch (err) {
// console.log(err)
// }
// })
// }
//
// const worker = makeWorker(workerScript)
// worker.postMessage({file: fileObj})
// worker.addEventListener('message', (e) => {
// const fileDataURL = e.data.file
// console.log('FILE _ DATA _ URL')
// return resolve(fileDataURL)
// })
});
}
/**
* Resizes an image to specified width and proportional height, using canvas
* See https://davidwalsh.name/resize-image-canvas,
* http://babalan.com/resizing-images-with-javascript/
* @TODO see if we need https://github.com/stomita/ios-imagefile-megapixel for iOS
*
* @param {String} Data URI of the original image
* @param {String} width of the resulting image
* @return {String} Data URI of the resized image
*/
function createImageThumbnail(imgDataURI, newWidth) {
return new _Promise(function (resolve, reject) {
var img = new Image();
img.addEventListener('load', function () {
var newImageWidth = newWidth;
var newImageHeight = getProportionalImageHeight(img, newImageWidth);
// create an off-screen canvas
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// set its dimension to target size
canvas.width = newImageWidth;
canvas.height = newImageHeight;
// draw source image into the off-screen canvas:
// ctx.clearRect(0, 0, width, height)
ctx.drawImage(img, 0, 0, newImageWidth, newImageHeight);
// pica.resizeCanvas(img, canvas, (err) => {
// if (err) console.log(err)
// const thumbnail = canvas.toDataURL('image/png')
// return resolve(thumbnail)
// })
// encode image to data-uri with base64 version of compressed image
// canvas.toDataURL('image/jpeg', quality); // quality = [0.0, 1.0]
var thumbnail = canvas.toDataURL('image/png');
return resolve(thumbnail);
});
img.src = imgDataURI;
});
}
function supportsMediaRecorder() {
return typeof MediaRecorder === 'function' && !!MediaRecorder.prototype && typeof MediaRecorder.prototype.start === 'function';
}
function dataURItoBlob(dataURI, opts, toFile) {
// get the base64 data
var data = dataURI.split(',')[1];
// user may provide mime type, if not get it from data URI
var mimeType = opts.mimeType || dataURI.split(',')[0].split(':')[1].split(';')[0];
// default to plain/text if data URI has no mimeType
if (mimeType == null) {
mimeType = 'plain/text';
}
var binary = atob(data);
var array = [];
for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
// Convert to a File?
if (toFile) {
return new File([new Uint8Array(array)], opts.name || '', { type: mimeType });
}
return new Blob([new Uint8Array(array)], { type: mimeType });
}
function dataURItoFile(dataURI, opts) {
return dataURItoBlob(dataURI, opts, true);
}
/**
* Copies text to clipboard by creating an almost invisible textarea,
* adding text there, then running execCommand('copy').
* Falls back to prompt() when the easy way fails (hello, Safari!)
* From http://stackoverflow.com/a/30810322
*
* @param {String} textToCopy
* @param {String} fallbackString
* @return {Promise}
*/
function copyToClipboard(textToCopy, fallbackString) {
fallbackString = fallbackString || 'Copy the URL below';
return new _Promise(function (resolve, reject) {
var textArea = document.createElement('textarea');
textArea.setAttribute('style', {
position: 'fixed',
top: 0,
left: 0,
width: '2em',
height: '2em',
padding: 0,
border: 'none',
outline: 'none',
boxShadow: 'none',
background: 'transparent'
});
textArea.value = textToCopy;
document.body.appendChild(textArea);
textArea.select();
var magicCopyFailed = function magicCopyFailed(err) {
document.body.removeChild(textArea);
window.prompt(fallbackString, textToCopy);
return reject('Oops, unable to copy displayed fallback prompt: ' + err);
};
try {
var successful = document.execCommand('copy');
if (!successful) {
return magicCopyFailed('copy command unavailable');
}
document.body.removeChild(textArea);
return resolve();
} catch (err) {
document.body.removeChild(textArea);
return magicCopyFailed(err);
}
});
}
// function createInlineWorker (workerFunction) {
// let code = workerFunction.toString()
// code = code.substring(code.indexOf('{') + 1, code.lastIndexOf('}'))
//
// const blob = new Blob([code], {type: 'application/javascript'})
// const worker = new Worker(URL.createObjectURL(blob))
//
// return worker
// }
// function makeWorker (script) {
// var URL = window.URL || window.webkitURL
// var Blob = window.Blob
// var Worker = window.Worker
//
// if (!URL || !Blob || !Worker || !script) {
// return null
// }
//
// let code = script.toString()
// code = code.substring(code.indexOf('{') + 1, code.lastIndexOf('}'))
//
// var blob = new Blob([code])
// var worker = new Worker(URL.createObjectURL(blob))
// return worker
// }
function getSpeed(fileProgress) {
if (!fileProgress.bytesUploaded) return 0;
var timeElapsed = new Date() - fileProgress.uploadStarted;
var uploadSpeed = fileProgress.bytesUploaded / (timeElapsed / 1000);
return uploadSpeed;
}
function getETA(fileProgress) {
if (!fileProgress.bytesUploaded) return 0;
var uploadSpeed = getSpeed(fileProgress);
var bytesRemaining = fileProgress.bytesTotal - fileProgress.bytesUploaded;
var secondsRemaining = Math.round(bytesRemaining / uploadSpeed * 10) / 10;
return secondsRemaining;
}
function prettyETA(seconds) {
var time = secondsToTime(seconds);
// Only display hours and minutes if they are greater than 0 but always
// display minutes if hours is being displayed
// Display a leading zero if the there is a preceding unit: 1m 05s, but 5s
var hoursStr = time.hours ? time.hours + 'h ' : '';
var minutesVal = time.hours ? ('0' + time.minutes).substr(-2) : time.minutes;
var minutesStr = minutesVal ? minutesVal + 'm ' : '';
var secondsVal = minutesVal ? ('0' + time.seconds).substr(-2) : time.seconds;
var secondsStr = secondsVal + 's';
return '' + hoursStr + minutesStr + secondsStr;
}
// function makeCachingFunction () {
// let cachedEl = null
// let lastUpdate = Date.now()
//
// return function cacheElement (el, time) {
// if (Date.now() - lastUpdate < time) {
// return cachedEl
// }
//
// cachedEl = el
// lastUpdate = Date.now()
//
// return el
// }
// }
/**
* Check if an object is a DOM element. Duck-typing based on `nodeType`.
*
* @param {*} obj
*/
function isDOMElement(obj) {
return obj && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && obj.nodeType === Node.ELEMENT_NODE;
}
/**
* Find a DOM element.
*
* @param {Node|string} element
* @return {Node|null}
*/
function findDOMElement(element) {
if (typeof element === 'string') {
return document.querySelector(element);
}
if ((typeof element === 'undefined' ? 'undefined' : _typeof(element)) === 'object' && isDOMElement(element)) {
return element;
}
}
module.exports = {
generateFileID: generateFileID,
toArray: toArray,
every: every,
flatten: flatten,
groupBy: groupBy,
// $,
// $$,
extend: extend,
readFile: readFile,
createImageThumbnail: createImageThumbnail,
getProportionalImageHeight: getProportionalImageHeight,
supportsMediaRecorder: supportsMediaRecorder,
isTouchDevice: isTouchDevice,
getFileNameAndExtension: getFileNameAndExtension,
truncateString: truncateString,
getFileTypeExtension: getFileTypeExtension,
getFileType: getFileType,
secondsToTime: secondsToTime,
dataURItoBlob: dataURItoBlob,
dataURItoFile: dataURItoFile,
getSpeed: getSpeed,
getETA: getETA,
// makeWorker,
// makeCachingFunction,
copyToClipboard: copyToClipboard,
prettyETA: prettyETA,
findDOMElement: findDOMElement
};
},{"es6-promise":60}],7:[function(require,module,exports){
'use strict';
var Core = require('./Core');
module.exports = Core;
},{"./Core":3}],8:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
module.exports = function (props) {
var _uppyProviderAuthBtnDemo, _uppyProviderAuthTitleName, _br, _uppyProviderAuthTitle, _uppyProviderAuthBtn, _uppyProviderAuth;
var demoLink = props.demo ? (_uppyProviderAuthBtnDemo = document.createElement('button'), _uppyProviderAuthBtnDemo.onclick = props.handleDemoAuth, _uppyProviderAuthBtnDemo.setAttribute('class', 'UppyProvider-authBtnDemo'), _uppyProviderAuthBtnDemo.textContent = 'Proceed with Demo Account', _uppyProviderAuthBtnDemo) : null;
return _uppyProviderAuth = document.createElement('div'), _uppyProviderAuth.setAttribute('class', 'UppyProvider-auth'), _appendChild(_uppyProviderAuth, [' ', (_uppyProviderAuthTitle = document.createElement('h1'), _uppyProviderAuthTitle.setAttribute('class', 'UppyProvider-authTitle'), _appendChild(_uppyProviderAuthTitle, [' Please authenticate with ', (_uppyProviderAuthTitleName = document.createElement('span'), _uppyProviderAuthTitleName.setAttribute('class', 'UppyProvider-authTitleName'), _appendChild(_uppyProviderAuthTitleName, [props.pluginName]), _uppyProviderAuthTitleName), (_br = document.createElement('br'), _br), ' to select files ']), _uppyProviderAuthTitle), ' ', (_uppyProviderAuthBtn = document.createElement('button'), _uppyProviderAuthBtn.onclick = props.handleAuth, _uppyProviderAuthBtn.setAttribute('class', 'UppyProvider-authBtn'), _uppyProviderAuthBtn.textContent = 'Authenticate', _uppyProviderAuthBtn), ' ', demoLink, ' ']), _uppyProviderAuth;
};
},{"yo-yoify/lib/appendChild":131}],9:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
module.exports = function (props) {
var _button, _li;
return _li = document.createElement('li'), _appendChild(_li, [' ', (_button = document.createElement('button'), _button.onclick = props.getFolder, _appendChild(_button, [props.title]), _button), ' ']), _li;
};
},{"yo-yoify/lib/appendChild":131}],10:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
var Breadcrumb = require('./Breadcrumb');
module.exports = function (props) {
var _uppyProviderBreadcrumbs;
return _uppyProviderBreadcrumbs = document.createElement('ul'), _uppyProviderBreadcrumbs.setAttribute('class', 'UppyProvider-breadcrumbs'), _appendChild(_uppyProviderBreadcrumbs, [' ', props.directories.map(function (directory) {
return Breadcrumb({
getFolder: function getFolder() {
return props.getFolder(directory.id);
},
title: directory.title
});
}), ' ']), _uppyProviderBreadcrumbs;
};
},{"./Breadcrumb":9,"yo-yoify/lib/appendChild":131}],11:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
var Breadcrumbs = require('./Breadcrumbs');
var Table = require('./Table');
module.exports = function (props) {
var _browserSearch, _header, _browserUserLogout, _browserSubHeader, _browserContent, _browserBody, _browser;
var filteredFolders = props.folders;
var filteredFiles = props.files;
if (props.filterInput !== '') {
filteredFolders = props.filterItems(props.folders);
filteredFiles = props.filterItems(props.files);
}
return _browser = document.createElement('div'), _browser.setAttribute('class', 'Browser'), _appendChild(_browser, [' ', (_header = document.createElement('header'), _appendChild(_header, [' ', (_browserSearch = document.createElement('input'), _browserSearch.setAttribute('type', 'text'), _browserSearch.setAttribute('placeholder', 'Search Drive'), _browserSearch.onkeyup = props.filterQuery, _browserSearch.setAttribute('value', '' + String(props.filterInput) + ''), _browserSearch.setAttribute('class', 'Browser-search'), _browserSearch), ' ']), _header), ' ', (_browserSubHeader = document.createElement('div'), _browserSubHeader.setAttribute('class', 'Browser-subHeader'), _appendChild(_browserSubHeader, [' ', Breadcrumbs({
getFolder: props.getFolder,
directories: props.directories
}), ' ', (_browserUserLogout = document.createElement('button'), _browserUserLogout.onclick = props.logout, _browserUserLogout.setAttribute('class', 'Browser-userLogout'), _browserUserLogout.textContent = 'Log out', _browserUserLogout), ' ']), _browserSubHeader), ' ', (_browserBody = document.createElement('div'), _browserBody.setAttribute('class', 'Browser-body'), _appendChild(_browserBody, [' ', (_browserContent = document.createElement('main'), _browserContent.setAttribute('class', 'Browser-content'), _appendChild(_browserContent, [' ', Table({
columns: [{
name: 'Name',
key: 'title'
}],
folders: filteredFolders,
files: filteredFiles,
activeRow: props.isActiveRow,
sortByTitle: props.sortByTitle,
sortByDate: props.sortByDate,
handleRowClick: props.handleRowClick,
handleFileDoubleClick: props.addFile,
handleFolderDoubleClick: props.getNextFolder,
getItemName: props.getItemName,
getItemIcon: props.getItemIcon
}), ' ']), _browserContent), ' ']), _browserBody), ' ']), _browser;
};
},{"./Breadcrumbs":10,"./Table":14,"yo-yoify/lib/appendChild":131}],12:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
module.exports = function (props) {
var _span, _uppyProviderError;
return _uppyProviderError = document.createElement('div'), _uppyProviderError.setAttribute('class', 'UppyProvider-error'), _appendChild(_uppyProviderError, [' ', (_span = document.createElement('span'), _appendChild(_span, [' Something went wrong. Probably our fault. ', props.error, ' ']), _span), ' ']), _uppyProviderError;
};
},{"yo-yoify/lib/appendChild":131}],13:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
module.exports = function (props) {
var _span, _uppyProviderLoading;
return _uppyProviderLoading = document.createElement('div'), _uppyProviderLoading.setAttribute('class', 'UppyProvider-loading'), _appendChild(_uppyProviderLoading, [' ', (_span = document.createElement('span'), _span.textContent = ' Loading ... ', _span), ' ']), _uppyProviderLoading;
};
},{"yo-yoify/lib/appendChild":131}],14:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
var Row = require('./TableRow');
module.exports = function (props) {
var _tr, _browserTableHeader, _tbody, _browserTable;
var headers = props.columns.map(function (column) {
var _browserTableHeaderColumn;
return _browserTableHeaderColumn = document.createElement('th'), _browserTableHeaderColumn.onclick = props.sortByTitle, _browserTableHeaderColumn.setAttribute('class', 'BrowserTable-headerColumn BrowserTable-column'), _appendChild(_browserTableHeaderColumn, [' ', column.name, ' ']), _browserTableHeaderColumn;
});
return _browserTable = document.createElement('table'), _browserTable.setAttribute('class', 'BrowserTable'), _appendChild(_browserTable, [' ', (_browserTableHeader = document.createElement('thead'), _browserTableHeader.setAttribute('class', 'BrowserTable-header'), _appendChild(_browserTableHeader, [' ', (_tr = document.createElement('tr'), _appendChild(_tr, [' ', headers, ' ']), _tr), ' ']), _browserTableHeader), ' ', (_tbody = document.createElement('tbody'), _appendChild(_tbody, [' ', props.folders.map(function (folder) {
return Row({
title: props.getItemName(folder),
active: props.activeRow(folder),
getItemIcon: function getItemIcon() {
return props.getItemIcon(folder);
},
handleClick: function handleClick() {
return props.handleRowClick(folder);
},
handleDoubleClick: function handleDoubleClick() {
return props.handleFolderDoubleClick(folder);
},
columns: props.columns
});
}), ' ', props.files.map(function (file) {
return Row({
title: props.getItemName(file),
active: props.activeRow(file),
getItemIcon: function getItemIcon() {
return props.getItemIcon(file);
},
handleClick: function handleClick() {
return props.handleRowClick(file);
},
handleDoubleClick: function handleDoubleClick() {
return props.handleFileDoubleClick(file);
},
columns: props.columns
});
}), ' ']), _tbody), ' ']), _browserTable;
};
},{"./TableRow":16,"yo-yoify/lib/appendChild":131}],15:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
module.exports = function (props) {
var _browserTableRowColumn;
return _browserTableRowColumn = document.createElement('td'), _browserTableRowColumn.setAttribute('class', 'BrowserTable-rowColumn BrowserTable-column'), _appendChild(_browserTableRowColumn, [' ', props.getItemIcon(), ' ', props.value, ' ']), _browserTableRowColumn;
};
},{"yo-yoify/lib/appendChild":131}],16:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
var Column = require('./TableColumn');
module.exports = function (props) {
var _tr;
var classes = props.active ? 'BrowserTable-row is-active' : 'BrowserTable-row';
return _tr = document.createElement('tr'), _tr.onclick = props.handleClick, _tr.ondblclick = props.handleDoubleClick, _tr.setAttribute('class', '' + String(classes) + ''), _appendChild(_tr, [' ', Column({
getItemIcon: props.getItemIcon,
value: props.title
}), ' ']), _tr;
};
},{"./TableColumn":15,"yo-yoify/lib/appendChild":131}],17:[function(require,module,exports){
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var AuthView = require('./AuthView');
var Browser = require('./Browser');
var ErrorView = require('./Error');
var LoaderView = require('./Loader');
var Utils = require('../core/Utils');
/**
* Class to easily generate generic views for plugins
*
* This class expects the plugin using to have the following attributes
*
* stateId {String} object key of which the plugin state is stored
*
* This class also expects the plugin instance using it to have the following
* accessor methods.
* Each method takes the item whose property is to be accessed
* as a param
*
* isFolder
* @return {Boolean} for if the item is a folder or not
* getItemData
* @return {Object} that is format ready for uppy upload/download
* getItemIcon
* @return {Object} html instance of the item's icon
* getItemSubList
* @return {Array} sub-items in the item. e.g a folder may contain sub-items
* getItemName
* @return {String} display friendly name of the item
* getMimeType
* @return {String} mime type of the item
* getItemId
* @return {String} unique id of the item
* getItemRequestPath
* @return {String} unique request path of the item when making calls to uppy server
* getItemModifiedDate
* @return {object} or {String} date of when last the item was modified
*/
module.exports = function () {
/**
* @param {object} instance of the plugin
*/
function View(plugin) {
_classCallCheck(this, View);
this.plugin = plugin;
this.Provider = plugin[plugin.id];
// Logic
this.addFile = this.addFile.bind(this);
this.filterItems = this.filterItems.bind(this);
this.filterQuery = this.filterQuery.bind(this);
this.getFolder = this.getFolder.bind(this);
this.getNextFolder = this.getNextFolder.bind(this);
this.handleRowClick = this.handleRowClick.bind(this);
this.logout = this.logout.bind(this);
this.handleAuth = this.handleAuth.bind(this);
this.handleDemoAuth = this.handleDemoAuth.bind(this);
this.sortByTitle = this.sortByTitle.bind(this);
this.sortByDate = this.sortByDate.bind(this);
this.isActiveRow = this.isActiveRow.bind(this);
this.handleError = this.handleError.bind(this);
// Visual
this.render = this.render.bind(this);
}
/**
* Little shorthand to update the state with the plugin's state
*/
View.prototype.updateState = function updateState(newState) {
var _plugin$core$setState;
var stateId = this.plugin.stateId;
var state = this.plugin.core.state;
this.plugin.core.setState((_plugin$core$setState = {}, _plugin$core$setState[stateId] = _extends({}, state[stateId], newState), _plugin$core$setState));
};
/**
* Based on folder ID, fetch a new folder and update it to state
* @param {String} id Folder id
* @return {Promise} Folders/files in folder
*/
View.prototype.getFolder = function getFolder(id, name) {
var _this = this;
return this._loaderWrapper(this.Provider.list(id), function (res) {
var folders = [];
var files = [];
var updatedDirectories = void 0;
var state = _this.plugin.core.getState()[_this.plugin.stateId];
var index = state.directories.findIndex(function (dir) {
return id === dir.id;
});
if (index !== -1) {
updatedDirectories = state.directories.slice(0, index + 1);
} else {
updatedDirectories = state.directories.concat([{ id: id, title: name || _this.plugin.getItemName(res) }]);
}
_this.plugin.getItemSubList(res).forEach(function (item) {
if (_this.plugin.isFolder(item)) {
folders.push(item);
} else {
files.push(item);
}
});
var data = { folders: folders, files: files, directories: updatedDirectories };
_this.updateState(data);
return data;
}, this.handleError);
};
/**
* Fetches new folder
* @param {Object} Folder
* @param {String} title Folder title
*/
View.prototype.getNextFolder = function getNextFolder(folder) {
var id = this.plugin.getItemRequestPath(folder);
this.getFolder(id, this.plugin.getItemName(folder));
};
View.prototype.addFile = function addFile(file) {
var tagFile = {
source: this.plugin.id,
data: this.plugin.getItemData(file),
name: this.plugin.getItemName(file),
type: this.plugin.getMimeType(file),
isRemote: true,
body: {
fileId: this.plugin.getItemId(file)
},
remote: {
host: this.plugin.opts.host,
url: this.plugin.opts.host + '/' + this.Provider.id + '/get/' + this.plugin.getItemRequestPath(file),
body: {
fileId: this.plugin.getItemId(file)
}
}
};
if (Utils.getFileType(tagFile)[0] === 'image') {
tagFile.preview = this.plugin.opts.host + '/' + this.Provider.id + '/thumbnail/' + this.plugin.getItemRequestPath(file);
}
console.log('adding file');
this.plugin.core.emitter.emit('core:file-add', tagFile);
};
/**
* Removes session token on client side.
*/
View.prototype.logout = function logout() {
var _this2 = this;
this.Provider.logout(location.href).then(function (res) {
return res.json();
}).then(function (res) {
if (res.ok) {
var newState = {
authenticated: false,
files: [],
folders: [],
directories: []
};
_this2.updateState(newState);
}
}).catch(this.handleError);
};
/**
* Used to set active file/folder.
* @param {Object} file Active file/folder
*/
View.prototype.handleRowClick = function handleRowClick(file) {
var state = this.plugin.core.getState()[this.plugin.stateId];
var newState = _extends({}, state, {
activeRow: this.plugin.getItemId(file)
});
this.updateState(newState);
};
View.prototype.filterQuery = function filterQuery(e) {
var state = this.plugin.core.getState()[this.plugin.stateId];
this.updateState(_extends({}, state, {
filterInput: e.target.value
}));
};
View.prototype.filterItems = function filterItems(items) {
var _this3 = this;
var state = this.plugin.core.getState()[this.plugin.stateId];
return items.filter(function (folder) {
return _this3.plugin.getItemName(folder).toLowerCase().indexOf(state.filterInput.toLowerCase()) !== -1;
});
};
View.prototype.sortByTitle = function sortByTitle() {
var _this4 = this;
var state = _extends({}, this.plugin.core.getState()[this.plugin.stateId]);
var files = state.files,
folders = state.folders,
sorting = state.sorting;
var sortedFiles = files.sort(function (fileA, fileB) {
if (sorting === 'titleDescending') {
return _this4.plugin.getItemName(fileB).localeCompare(_this4.plugin.getItemName(fileA));
}
return _this4.plugin.getItemName(fileA).localeCompare(_this4.plugin.getItemName(fileB));
});
var sortedFolders = folders.sort(function (folderA, folderB) {
if (sorting === 'titleDescending') {
return _this4.plugin.getItemName(folderB).localeCompare(_this4.plugin.getItemName(folderA));
}
return _this4.plugin.getItemName(folderA).localeCompare(_this4.plugin.getItemName(folderB));
});
this.updateState(_extends({}, state, {
files: sortedFiles,
folders: sortedFolders,
sorting: sorting === 'titleDescending' ? 'titleAscending' : 'titleDescending'
}));
};
View.prototype.sortByDate = function sortByDate() {
var _this5 = this;
var state = _extends({}, this.plugin.core.getState()[this.plugin.stateId]);
var files = state.files,
folders = state.folders,
sorting = state.sorting;
var sortedFiles = files.sort(function (fileA, fileB) {
var a = new Date(_this5.plugin.getItemModifiedDate(fileA));
var b = new Date(_this5.plugin.getItemModifiedDate(fileB));
if (sorting === 'dateDescending') {
return a > b ? -1 : a < b ? 1 : 0;
}
return a > b ? 1 : a < b ? -1 : 0;
});
var sortedFolders = folders.sort(function (folderA, folderB) {
var a = new Date(_this5.plugin.getItemModifiedDate(folderA));
var b = new Date(_this5.plugin.getItemModifiedDate(folderB));
if (sorting === 'dateDescending') {
return a > b ? -1 : a < b ? 1 : 0;
}
return a > b ? 1 : a < b ? -1 : 0;
});
this.updateState(_extends({}, state, {
files: sortedFiles,
folders: sortedFolders,
sorting: sorting === 'dateDescending' ? 'dateAscending' : 'dateDescending'
}));
};
View.prototype.isActiveRow = function isActiveRow(file) {
return this.plugin.core.getState()[this.plugin.stateId].activeRow === this.plugin.getItemId(file);
};
View.prototype.handleDemoAuth = function handleDemoAuth() {
var state = this.plugin.core.getState()[this.plugin.stateId];
this.updateState({}, state, {
authenticated: true
});
};
View.prototype.handleAuth = function handleAuth() {
var _this6 = this;
var urlId = Math.floor(Math.random() * 999999) + 1;
var redirect = '' + location.href + (location.search ? '&' : '?') + 'id=' + urlId;
var authState = btoa(JSON.stringify({ redirect: redirect }));
var link = this.plugin.opts.host + '/connect/' + this.Provider.authProvider + '?state=' + authState;
var authWindow = window.open(link, '_blank');
var checkAuth = function checkAuth() {
var authWindowUrl = void 0;
try {
authWindowUrl = authWindow.location.href;
} catch (e) {
if (e instanceof DOMException || e instanceof TypeError) {
return setTimeout(checkAuth, 100);
} else throw e;
}
// split url because chrome adds '#' to redirects
if (authWindowUrl.split('#')[0] === redirect) {
authWindow.close();
_this6._loaderWrapper(_this6.Provider.auth(), _this6.plugin.onAuth, _this6.handleError);
} else {
setTimeout(checkAuth, 100);
}
};
checkAuth();
};
View.prototype.handleError = function handleError(error) {
this.updateState({ error: error });
};
// displays loader view while asynchronous request is being made.
View.prototype._loaderWrapper = function _loaderWrapper(promise, then, catch_) {
var _this7 = this;
promise.then(function (result) {
_this7.updateState({ loading: false });
then(result);
}).catch(function (err) {
_this7.updateState({ loading: false });
catch_(err);
});
this.updateState({ loading: true });
};
View.prototype.render = function render(state) {
var _state$plugin$stateId = state[this.plugin.stateId],
authenticated = _state$plugin$stateId.authenticated,
error = _state$plugin$stateId.error,
loading = _state$plugin$stateId.loading;
if (error) {
this.updateState({ error: undefined });
return ErrorView({ error: error });
}
if (loading) {
return LoaderView();
}
if (!authenticated) {
return AuthView({
pluginName: this.plugin.title,
demo: this.plugin.opts.demo,
handleAuth: this.handleAuth,
handleDemoAuth: this.handleDemoAuth
});
}
var browserProps = _extends({}, state[this.plugin.stateId], {
getNextFolder: this.getNextFolder,
getFolder: this.getFolder,
addFile: this.addFile,
filterItems: this.filterItems,
filterQuery: this.filterQuery,
handleRowClick: this.handleRowClick,
sortByTitle: this.sortByTitle,
sortByDate: this.sortByDate,
logout: this.logout,
demo: this.plugin.opts.demo,
isActiveRow: this.isActiveRow,
getItemName: this.plugin.getItemName,
getItemIcon: this.plugin.getItemIcon
});
return Browser(browserProps);
};
return View;
}();
},{"../core/Utils":6,"./AuthView":8,"./Browser":11,"./Error":12,"./Loader":13}],18:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
module.exports = function (props) {
var _uppyDashboardInput, _uppyDashboardBrowse, _span;
var input = (_uppyDashboardInput = document.createElement('input'), _uppyDashboardInput.setAttribute('type', 'file'), _uppyDashboardInput.setAttribute('name', 'files[]'), 'true' && _uppyDashboardInput.setAttribute('multiple', 'multiple'), _uppyDashboardInput.onchange = props.handleInputChange, _uppyDashboardInput.setAttribute('class', 'UppyDashboard-input'), _uppyDashboardInput);
return _span = document.createElement('span'), _appendChild(_span, [' ', props.acquirers.length === 0 ? props.i18n('dropPaste') : props.i18n('dropPasteImport'), ' ', (_uppyDashboardBrowse = document.createElement('button'), _uppyDashboardBrowse.setAttribute('type', 'button'), _uppyDashboardBrowse.onclick = function (ev) {
input.click();
}, _uppyDashboardBrowse.setAttribute('class', 'UppyDashboard-browse'), _appendChild(_uppyDashboardBrowse, [props.i18n('browse')]), _uppyDashboardBrowse), ' ', input, ' ']), _span;
};
},{"yo-yoify/lib/appendChild":131}],19:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild'),
_onload = require('on-load');
var FileList = require('./FileList');
var Tabs = require('./Tabs');
var FileCard = require('./FileCard');
var UploadBtn = require('./UploadBtn');
var StatusBar = require('./StatusBar');
var _require = require('../../core/Utils'),
isTouchDevice = _require.isTouchDevice,
toArray = _require.toArray;
var _require2 = require('./icons'),
closeIcon = _require2.closeIcon;
// http://dev.edenspiekermann.com/2016/02/11/introducing-accessible-modal-dialog
module.exports = function Dashboard(props) {
var _uppyDashboardClose, _uppyDashboardOverlay, _uppyDashboardActions, _uppyDashboardFilesContainer, _uppyDashboardContentTitle, _uppyDashboardContentBack, _uppyDashboardContentBar, _uppyDashboardContentPanel, _uppyDashboardProgressindicators, _uppyDashboardInnerWrap, _uppyDashboardInner, _div;
function handleInputChange(ev) {
ev.preventDefault();
var files = toArray(ev.target.files);
files.forEach(function (file) {
props.addFile({
source: props.id,
name: file.name,
type: file.type,
data: file
});
});
}
// @TODO Exprimental, work in progress
// no names, weird API, Chrome-only http://stackoverflow.com/a/22940020
function handlePaste(ev) {
ev.preventDefault();
var files = toArray(ev.clipboardData.items);
files.forEach(function (file) {
if (file.kind !== 'file') return;
var blob = file.getAsFile();
props.log('File pasted');
props.addFile({
source: props.id,
name: file.name,
type: file.type,
data: blob
});
});
}
return _div = document.createElement('div'), _onload(_div, function () {
return props.updateDashboardElWidth();
}, null, 1), _div.setAttribute('aria-hidden', '' + String(props.inline ? 'false' : props.modal.isHidden) + ''), _div.setAttribute('aria-label', '' + String(!props.inline ? props.i18n('dashboardWindowTitle') : props.i18n('dashboardTitle')) + ''), _div.setAttribute('role', 'dialog'), _div.onpaste = handlePaste, _div.setAttribute('class', 'Uppy UppyTheme--default UppyDashboard\n ' + String(isTouchDevice() ? 'Uppy--isTouchDevice' : '') + '\n ' + String(props.semiTransparent ? 'UppyDashboard--semiTransparent' : '') + '\n ' + String(!props.inline ? 'UppyDashboard--modal' : '') + '\n ' + String(props.isWide ? 'UppyDashboard--wide' : '') + ''), _appendChild(_div, [' ', (_uppyDashboardClose = document.createElement('button'), _uppyDashboardClose.setAttribute('aria-label', '' + String(props.i18n('closeModal')) + ''), _uppyDashboardClose.setAttribute('title', '' + String(props.i18n('closeModal')) + ''), _uppyDashboardClose.onclick = props.hideModal, _uppyDashboardClose.setAttribute('class', 'UppyDashboard-close'), _appendChild(_uppyDashboardClose, [closeIcon()]), _uppyDashboardClose), ' ', (_uppyDashboardOverlay = document.createElement('div'), _uppyDashboardOverlay.onclick = props.hideModal, _uppyDashboardOverlay.setAttribute('class', 'UppyDashboard-overlay'), _uppyDashboardOverlay), ' ', (_uppyDashboardInner = document.createElement('div'), _uppyDashboardInner.setAttribute('tabindex', '0'), _uppyDashboardInner.setAttribute('style', '\n ' + String(props.inline && props.maxWidth ? 'max-width: ' + props.maxWidth + 'px;' : '') + '\n ' + String(props.inline && props.maxHeight ? 'max-height: ' + props.maxHeight + 'px;' : '') + '\n '), _uppyDashboardInner.setAttribute('class', 'UppyDashboard-inner'), _appendChild(_uppyDashboardInner, [' ', (_uppyDashboardInnerWrap = document.createElement('div'), _uppyDashboardInnerWrap.setAttribute('class', 'UppyDashboard-innerWrap'), _appendChild(_uppyDashboardInnerWrap, [' ', Tabs({
files: props.files,
handleInputChange: handleInputChange,
acquirers: props.acquirers,
panelSelectorPrefix: props.panelSelectorPrefix,
showPanel: props.showPanel,
i18n: props.i18n
}), ' ', FileCard({
files: props.files,
fileCardFor: props.fileCardFor,
done: props.fileCardDone,
metaFields: props.metaFields,
log: props.log,
i18n: props.i18n
}), ' ', (_uppyDashboardFilesContainer = document.createElement('div'), _uppyDashboardFilesContainer.setAttribute('class', 'UppyDashboard-filesContainer'), _appendChild(_uppyDashboardFilesContainer, [' ', FileList({
acquirers: props.acquirers,
files: props.files,
handleInputChange: handleInputChange,
showFileCard: props.showFileCard,
showProgressDetails: props.showProgressDetails,
totalProgress: props.totalProgress,
totalFileCount: props.totalFileCount,
info: props.info,
i18n: props.i18n,
log: props.log,
removeFile: props.removeFile,
pauseAll: props.pauseAll,
resumeAll: props.resumeAll,
pauseUpload: props.pauseUpload,
startUpload: props.startUpload,
cancelUpload: props.cancelUpload,
resumableUploads: props.resumableUploads,
isWide: props.isWide
}), ' ', (_uppyDashboardActions = document.createElement('div'), _uppyDashboardActions.setAttribute('class', 'UppyDashboard-actions'), _appendChild(_uppyDashboardActions, [' ', !props.autoProceed && props.newFiles.length > 0 ? UploadBtn({
i18n: props.i18n,
startUpload: props.startUpload,
newFileCount: props.newFiles.length
}) : null, ' ']), _uppyDashboardActions), ' ']), _uppyDashboardFilesContainer), ' ', (_uppyDashboardContentPanel = document.createElement('div'), _uppyDashboardContentPanel.setAttribute('role', 'tabpanel'), _uppyDashboardContentPanel.setAttribute('aria-hidden', '' + String(props.activePanel ? 'false' : 'true') + ''), _uppyDashboardContentPanel.setAttribute('class', 'UppyDashboardContent-panel'), _appendChild(_uppyDashboardContentPanel, [' ', (_uppyDashboardContentBar = document.createElement('div'), _uppyDashboardContentBar.setAttribute('class', 'UppyDashboardContent-bar'), _appendChild(_uppyDashboardContentBar, [' ', (_uppyDashboardContentTitle = document.createElement('h2'), _uppyDashboardContentTitle.setAttribute('class', 'UppyDashboardContent-title'), _appendChild(_uppyDashboardContentTitle, [' ', props.i18n('importFrom'), ' ', props.activePanel ? props.activePanel.name : null, ' ']), _uppyDashboardContentTitle), ' ', (_uppyDashboardContentBack = document.createElement('button'), _uppyDashboardContentBack.onclick = props.hideAllPanels, _uppyDashboardContentBack.setAttribute('class', 'UppyDashboardContent-back'), _appendChild(_uppyDashboardContentBack, [props.i18n('done')]), _uppyDashboardContentBack), ' ']), _uppyDashboardContentBar), ' ', props.activePanel ? props.activePanel.render(props.state) : '', ' ']), _uppyDashboardContentPanel), ' ', (_uppyDashboardProgressindicators = document.createElement('div'), _uppyDashboardProgressindicators.setAttribute('class', 'UppyDashboard-progressindicators'), _appendChild(_uppyDashboardProgressindicators, [' ', StatusBar({
totalProgress: props.totalProgress,
totalFileCount: props.totalFileCount,
totalSize: props.totalSize,
totalUploadedSize: props.totalUploadedSize,
uploadStartedFiles: props.uploadStartedFiles,
isAllComplete: props.isAllComplete,
isAllPaused: props.isAllPaused,
isUploadStarted: props.isUploadStarted,
pauseAll: props.pauseAll,
resumeAll: props.resumeAll,
cancelAll: props.cancelAll,
complete: props.completeFiles.length,
inProgress: props.inProgress,
totalSpeed: props.totalSpeed,
totalETA: props.totalETA,
startUpload: props.startUpload,
newFileCount: props.newFiles.length,
i18n: props.i18n,
resumableUploads: props.resumableUploads
}), ' ', props.progressindicators.map(function (target) {
return target.render(props.state);
}), ' ']), _uppyDashboardProgressindicators), ' ']), _uppyDashboardInnerWrap), ' ']), _uppyDashboardInner), ' ']), _div;
};
},{"../../core/Utils":6,"./FileCard":20,"./FileList":23,"./StatusBar":24,"./Tabs":25,"./UploadBtn":26,"./icons":28,"on-load":63,"yo-yoify/lib/appendChild":131}],20:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
var getFileTypeIcon = require('./getFileTypeIcon');
var _require = require('./icons'),
checkIcon = _require.checkIcon;
// function getIconByMime (fileTypeGeneral) {
// switch (fileTypeGeneral) {
// case 'text':
// return iconText()
// case 'audio':
// return iconAudio()
// default:
// return iconFile()
// }
// }
module.exports = function fileCard(props) {
var _uppyDashboardContentTitleFile, _uppyDashboardContentTitle, _uppyDashboardContentBack, _uppyDashboardContentBar, _uppyButtonCircular, _uppyDashboardActions, _uppyDashboardFileCard, _uppyDashboardFileCardPreview, _uppyDashboardFileCardLabel2, _uppyDashboardFileCardInput2, _uppyDashboardFileCardFieldset2, _uppyDashboardFileCardInfo, _uppyDashboardFileCardInner, _img, _uppyDashboardItemPreviewIcon;
var file = props.fileCardFor ? props.files[props.fileCardFor] : false;
var meta = {};
function tempStoreMeta(ev) {
var value = ev.target.value;
var name = ev.target.attributes.name.value;
meta[name] = value;
}
function renderMetaFields(file) {
var metaFields = props.metaFields || [];
return metaFields.map(function (field) {
var _uppyDashboardFileCardLabel, _uppyDashboardFileCardInput, _uppyDashboardFileCardFieldset;
return _uppyDashboardFileCardFieldset = document.createElement('fieldset'), _uppyDashboardFileCardFieldset.setAttribute('class', 'UppyDashboardFileCard-fieldset'), _appendChild(_uppyDashboardFileCardFieldset, [' ', (_uppyDashboardFileCardLabel = document.createElement('label'), _uppyDashboardFileCardLabel.setAttribute('class', 'UppyDashboardFileCard-label'), _appendChild(_uppyDashboardFileCardLabel, [field.name]), _uppyDashboardFileCardLabel), ' ', (_uppyDashboardFileCardInput = document.createElement('input'), _uppyDashboardFileCardInput.setAttribute('name', '' + String(field.id) + ''), _uppyDashboardFileCardInput.setAttribute('type', 'text'), _uppyDashboardFileCardInput.setAttribute('value', '' + String(file.meta[field.id]) + ''), _uppyDashboardFileCardInput.setAttribute('placeholder', '' + String(field.placeholder || '') + ''), _uppyDashboardFileCardInput.onkeyup = tempStoreMeta, _uppyDashboardFileCardInput.setAttribute('class', 'UppyDashboardFileCard-input'), _uppyDashboardFileCardInput)]), _uppyDashboardFileCardFieldset;
});
}
return _uppyDashboardFileCard = document.createElement('div'), _uppyDashboardFileCard.setAttribute('aria-hidden', '' + String(!props.fileCardFor) + ''), _uppyDashboardFileCard.setAttribute('class', 'UppyDashboardFileCard'), _appendChild(_uppyDashboardFileCard, [' ', (_uppyDashboardContentBar = document.createElement('div'), _uppyDashboardContentBar.setAttribute('class', 'UppyDashboardContent-bar'), _appendChild(_uppyDashboardContentBar, [' ', (_uppyDashboardContentTitle = document.createElement('h2'), _uppyDashboardContentTitle.setAttribute('class', 'UppyDashboardContent-title'), _appendChild(_uppyDashboardContentTitle, ['Editing ', (_uppyDashboardContentTitleFile = document.createElement('span'), _uppyDashboardContentTitleFile.setAttribute('class', 'UppyDashboardContent-titleFile'), _appendChild(_uppyDashboardContentTitleFile, [file.meta ? file.meta.name : file.name]), _uppyDashboardContentTitleFile)]), _uppyDashboardContentTitle), ' ', (_uppyDashboardContentBack = document.createElement('button'), _uppyDashboardContentBack.setAttribute('title', 'Finish editing file'), _uppyDashboardContentBack.onclick = function () {
return props.done(meta, file.id);
}, _uppyDashboardContentBack.setAttribute('class', 'UppyDashboardContent-back'), _uppyDashboardContentBack.textContent = 'Done', _uppyDashboardContentBack), ' ']), _uppyDashboardContentBar), ' ', props.fileCardFor ? (_uppyDashboardFileCardInner = document.createElement('div'), _uppyDashboardFileCardInner.setAttribute('class', 'UppyDashboardFileCard-inner'), _appendChild(_uppyDashboardFileCardInner, [' ', (_uppyDashboardFileCardPreview = document.createElement('div'), _uppyDashboardFileCardPreview.setAttribute('class', 'UppyDashboardFileCard-preview'), _appendChild(_uppyDashboardFileCardPreview, [' ', file.preview ? (_img = document.createElement('img'), _img.setAttribute('alt', '' + String(file.name) + ''), _img.setAttribute('src', '' + String(file.preview) + ''), _img) : (_uppyDashboardItemPreviewIcon = document.createElement('div'), _uppyDashboardItemPreviewIcon.setAttribute('style', 'color: ' + String(getFileTypeIcon(file.type.general, file.type.specific).color) + ''), _uppyDashboardItemPreviewIcon.setAttribute('class', 'UppyDashboardItem-previewIcon'), _appendChild(_uppyDashboardItemPreviewIcon, [' ', getFileTypeIcon(file.type.general, file.type.specific).icon, ' ']), _uppyDashboardItemPreviewIcon), ' ']), _uppyDashboardFileCardPreview), ' ', (_uppyDashboardFileCardInfo = document.createElement('div'), _uppyDashboardFileCardInfo.setAttribute('class', 'UppyDashboardFileCard-info'), _appendChild(_uppyDashboardFileCardInfo, [' ', (_uppyDashboardFileCardFieldset2 = document.createElement('fieldset'), _uppyDashboardFileCardFieldset2.setAttribute('class', 'UppyDashboardFileCard-fieldset'), _appendChild(_uppyDashboardFileCardFieldset2, [' ', (_uppyDashboardFileCardLabel2 = document.createElement('label'), _uppyDashboardFileCardLabel2.setAttribute('class', 'UppyDashboardFileCard-label'), _uppyDashboardFileCardLabel2.textContent = 'Name', _uppyDashboardFileCardLabel2), ' ', (_uppyDashboardFileCardInput2 = document.createElement('input'), _uppyDashboardFileCardInput2.setAttribute('name', 'name'), _uppyDashboardFileCardInput2.setAttribute('type', 'text'), _uppyDashboardFileCardInput2.setAttribute('value', '' + String(file.meta.name) + ''), _uppyDashboardFileCardInput2.onkeyup = tempStoreMeta, _uppyDashboardFileCardInput2.setAttribute('class', 'UppyDashboardFileCard-input'), _uppyDashboardFileCardInput2), ' ']), _uppyDashboardFileCardFieldset2), ' ', renderMetaFields(file), ' ']), _uppyDashboardFileCardInfo), ' ']), _uppyDashboardFileCardInner) : null, ' ', (_uppyDashboardActions = document.createElement('div'), _uppyDashboardActions.setAttribute('class', 'UppyDashboard-actions'), _appendChild(_uppyDashboardActions, [' ', (_uppyButtonCircular = document.createElement('button'), _uppyButtonCircular.setAttribute('type', 'button'), _uppyButtonCircular.setAttribute('title', 'Finish editing file'), _uppyButtonCircular.onclick = function () {
return props.done(meta, file.id);
}, _uppyButtonCircular.setAttribute('class', 'UppyButton--circular UppyButton--blue UppyDashboardFileCard-done'), _appendChild(_uppyButtonCircular, [checkIcon()]), _uppyButtonCircular), ' ']), _uppyDashboardActions), ' ']), _uppyDashboardFileCard;
};
},{"./getFileTypeIcon":27,"./icons":28,"yo-yoify/lib/appendChild":131}],21:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild'),
_svgNamespace = 'http://www.w3.org/2000/svg';
var _require = require('../../core/Utils'),
getETA = _require.getETA,
getSpeed = _require.getSpeed,
prettyETA = _require.prettyETA,
getFileNameAndExtension = _require.getFileNameAndExtension,
truncateString = _require.truncateString,
copyToClipboard = _require.copyToClipboard;
var prettyBytes = require('prettier-bytes');
var FileItemProgress = require('./FileItemProgress');
var getFileTypeIcon = require('./getFileTypeIcon');
var _require2 = require('./icons'),
iconEdit = _require2.iconEdit,
iconCopy = _require2.iconCopy;
module.exports = function fileItem(props) {
var _uppyDashboardItemProgressBtn, _uppyDashboardItemProgress, _uppyDashboardItemPreview, _uppyDashboardItemName, _uppyDashboardItemStatusSize, _uppyDashboardItemStatus, _uppyDashboardItemInfo, _uppyDashboardItemAction, _li, _uppyDashboardItemSourceIcon, _img, _uppyDashboardItemPreviewIcon, _uppyDashboardItemProgressInfo, _span2, _a, _uppyDashboardItemEdit, _uppyDashboardItemCopyLink, _ellipse, _path, _uppyIcon, _uppyDashboardItemRemove;
var file = props.file;
var acquirers = props.acquirers;
var isUploaded = file.progress.uploadComplete;
var uploadInProgressOrComplete = file.progress.uploadStarted;
var uploadInProgress = file.progress.uploadStarted && !file.progress.uploadComplete;
var isPaused = file.isPaused || false;
var fileName = getFileNameAndExtension(file.meta.name)[0];
var truncatedFileName = props.isWide ? truncateString(fileName, 15) : fileName;
return _li = document.createElement('li'), _li.setAttribute('id', 'uppy_' + String(file.id) + ''), _li.setAttribute('title', '' + String(file.meta.name) + ''), _li.setAttribute('class', 'UppyDashboardItem\n ' + String(uploadInProgress ? 'is-inprogress' : '') + '\n ' + String(isUploaded ? 'is-complete' : '') + '\n ' + String(isPaused ? 'is-paused' : '') + '\n ' + String(props.resumableUploads ? 'is-resumable' : '') + ''), _appendChild(_li, [' ', (_uppyDashboardItemPreview = document.createElement('div'), _uppyDashboardItemPreview.setAttribute('class', 'UppyDashboardItem-preview'), _appendChild(_uppyDashboardItemPreview, [' ', file.source ? (_uppyDashboardItemSourceIcon = document.createElement('div'), _uppyDashboardItemSourceIcon.setAttribute('class', 'UppyDashboardItem-sourceIcon'), _appendChild(_uppyDashboardItemSourceIcon, [' ', acquirers.map(function (acquirer) {
var _span;
if (acquirer.id === file.source) return _span = document.createElement('span'), _span.setAttribute('title', '' + String(acquirer.name) + ''), _appendChild(_span, [acquirer.icon()]), _span;
}), ' ']), _uppyDashboardItemSourceIcon) : '', ' ', file.preview ? (_img = document.createElement('img'), _img.setAttribute('alt', '' + String(file.name) + ''), _img.setAttribute('src', '' + String(file.preview) + ''), _img) : (_uppyDashboardItemPreviewIcon = document.createElement('div'), _uppyDashboardItemPreviewIcon.setAttribute('style', 'color: ' + String(getFileTypeIcon(file.type.general, file.type.specific).color) + ''), _uppyDashboardItemPreviewIcon.setAttribute('class', 'UppyDashboardItem-previewIcon'), _appendChild(_uppyDashboardItemPreviewIcon, [' ', getFileTypeIcon(file.type.general, file.type.specific).icon, ' ']), _uppyDashboardItemPreviewIcon), ' ', (_uppyDashboardItemProgress = document.createElement('div'), _uppyDashboardItemProgress.setAttribute('class', 'UppyDashboardItem-progress'), _appendChild(_uppyDashboardItemProgress, [' ', (_uppyDashboardItemProgressBtn = document.createElement('button'), _uppyDashboardItemProgressBtn.setAttribute('title', '' + String(isUploaded ? 'upload complete' : props.resumableUploads ? file.isPaused ? 'resume upload' : 'pause upload' : 'cancel upload') + ''), _uppyDashboardItemProgressBtn.onclick = function (ev) {
if (isUploaded) return;
if (props.resumableUploads) {
props.pauseUpload(file.id);
} else {
props.cancelUpload(file.id);
}
}, _uppyDashboardItemProgressBtn.setAttribute('class', 'UppyDashboardItem-progressBtn'), _appendChild(_uppyDashboardItemProgressBtn, [' ', FileItemProgress({
progress: file.progress.percentage,
fileID: file.id
}), ' ']), _uppyDashboardItemProgressBtn), ' ', props.showProgressDetails ? (_uppyDashboardItemProgressInfo = document.createElement('div'), _uppyDashboardItemProgressInfo.setAttribute('title', '' + String(props.i18n('fileProgress')) + ''), _uppyDashboardItemProgressInfo.setAttribute('aria-label', '' + String(props.i18n('fileProgress')) + ''), _uppyDashboardItemProgressInfo.setAttribute('class', 'UppyDashboardItem-progressInfo'), _appendChild(_uppyDashboardItemProgressInfo, [' ', !file.isPaused && !isUploaded ? (_span2 = document.createElement('span'), _appendChild(_span2, [prettyETA(getETA(file.progress)), ' \u30FB \u2191 ', prettyBytes(getSpeed(file.progress)), '/s']), _span2) : null, ' ']), _uppyDashboardItemProgressInfo) : null, ' ']), _uppyDashboardItemProgress), ' ']), _uppyDashboardItemPreview), ' ', (_uppyDashboardItemInfo = document.createElement('div'), _uppyDashboardItemInfo.setAttribute('class', 'UppyDashboardItem-info'), _appendChild(_uppyDashboardItemInfo, [' ', (_uppyDashboardItemName = document.createElement('h4'), _uppyDashboardItemName.setAttribute('title', '' + String(fileName) + ''), _uppyDashboardItemName.setAttribute('class', 'UppyDashboardItem-name'), _appendChild(_uppyDashboardItemName, [' ', file.uploadURL ? (_a = document.createElement('a'), _a.setAttribute('href', '' + String(file.uploadURL) + ''), _a.setAttribute('target', '_blank'), _appendChild(_a, [' ', file.extension ? truncatedFileName + '.' + file.extension : truncatedFileName, ' ']), _a) : file.extension ? truncatedFileName + '.' + file.extension : truncatedFileName, ' ']), _uppyDashboardItemName), ' ', (_uppyDashboardItemStatus = document.createElement('div'), _uppyDashboardItemStatus.setAttribute('class', 'UppyDashboardItem-status'), _appendChild(_uppyDashboardItemStatus, [' ', (_uppyDashboardItemStatusSize = document.createElement('span'), _uppyDashboardItemStatusSize.setAttribute('class', 'UppyDashboardItem-statusSize'), _appendChild(_uppyDashboardItemStatusSize, [file.data.size ? prettyBytes(file.data.size) : '?']), _uppyDashboardItemStatusSize), ' ']), _uppyDashboardItemStatus), ' ', !uploadInProgressOrComplete ? (_uppyDashboardItemEdit = document.createElement('button'), _uppyDashboardItemEdit.setAttribute('aria-label', 'Edit file'), _uppyDashboardItemEdit.setAttribute('title', 'Edit file'), _uppyDashboardItemEdit.onclick = function (e) {
return props.showFileCard(file.id);
}, _uppyDashboardItemEdit.setAttribute('class', 'UppyDashboardItem-edit'), _appendChild(_uppyDashboardItemEdit, [' ', iconEdit()]), _uppyDashboardItemEdit) : null, ' ', file.uploadURL ? (_uppyDashboardItemCopyLink = document.createElement('button'), _uppyDashboardItemCopyLink.setAttribute('aria-label', 'Copy link'), _uppyDashboardItemCopyLink.setAttribute('title', 'Copy link'), _uppyDashboardItemCopyLink.onclick = function () {
copyToClipboard(file.uploadURL, props.i18n('copyLinkToClipboardFallback')).then(function () {
props.log('Link copied to clipboard.');
props.info(props.i18n('copyLinkToClipboardSuccess'), 'info', 3000);
}).catch(props.log);
}, _uppyDashboardItemCopyLink.setAttribute('class', 'UppyDashboardItem-copyLink'), _appendChild(_uppyDashboardItemCopyLink, [iconCopy()]), _uppyDashboardItemCopyLink) : null, ' ']), _uppyDashboardItemInfo), ' ', (_uppyDashboardItemAction = document.createElement('div'), _uppyDashboardItemAction.setAttribute('class', 'UppyDashboardItem-action'), _appendChild(_uppyDashboardItemAction, [' ', !isUploaded ? (_uppyDashboardItemRemove = document.createElement('button'), _uppyDashboardItemRemove.setAttribute('aria-label', 'Remove file'), _uppyDashboardItemRemove.setAttribute('title', 'Remove file'), _uppyDashboardItemRemove.onclick = function () {
return props.removeFile(file.id);
}, _uppyDashboardItemRemove.setAttribute('class', 'UppyDashboardItem-remove'), _appendChild(_uppyDashboardItemRemove, [' ', (_uppyIcon = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon.setAttribute('width', '22'), _uppyIcon.setAttribute('height', '21'), _uppyIcon.setAttribute('viewBox', '0 0 18 17'), _uppyIcon.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon, [' ', (_ellipse = document.createElementNS(_svgNamespace, 'ellipse'), _ellipse.setAttribute('cx', '8.62'), _ellipse.setAttribute('cy', '8.383'), _ellipse.setAttribute('rx', '8.62'), _ellipse.setAttribute('ry', '8.383'), _ellipse), ' ', (_path = document.createElementNS(_svgNamespace, 'path'), _path.setAttribute('stroke', '#FFF'), _path.setAttribute('fill', '#FFF'), _path.setAttribute('d', 'M11 6.147L10.85 6 8.5 8.284 6.15 6 6 6.147 8.35 8.43 6 10.717l.15.146L8.5 8.578l2.35 2.284.15-.146L8.65 8.43z'), _path), ' ']), _uppyIcon), ' ']), _uppyDashboardItemRemove) : null, ' ']), _uppyDashboardItemAction), ' ']), _li;
};
},{"../../core/Utils":6,"./FileItemProgress":22,"./getFileTypeIcon":27,"./icons":28,"prettier-bytes":66,"yo-yoify/lib/appendChild":131}],22:[function(require,module,exports){
'use strict';
var _svgNamespace = 'http://www.w3.org/2000/svg',
_appendChild = require('yo-yoify/lib/appendChild');
// http://codepen.io/Harkko/pen/rVxvNM
// https://css-tricks.com/svg-line-animation-works/
// https://gist.github.com/eswak/ad4ea57bcd5ff7aa5d42
// circle length equals 2 * PI * R
var circleLength = 2 * Math.PI * 15;
// stroke-dashoffset is a percentage of the progress from circleLength,
// substracted from circleLength, because its an offset
module.exports = function (props) {
var _bg, _progress, _progressGroup, _play, _rect, _rect2, _pause, _check, _cancel, _uppyIcon;
return _uppyIcon = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon.setAttribute('width', '70'), _uppyIcon.setAttribute('height', '70'), _uppyIcon.setAttribute('viewBox', '0 0 36 36'), _uppyIcon.setAttribute('class', 'UppyIcon UppyIcon-progressCircle'), _appendChild(_uppyIcon, [' ', (_progressGroup = document.createElementNS(_svgNamespace, 'g'), _progressGroup.setAttribute('class', 'progress-group'), _appendChild(_progressGroup, [' ', (_bg = document.createElementNS(_svgNamespace, 'circle'), _bg.setAttribute('r', '15'), _bg.setAttribute('cx', '18'), _bg.setAttribute('cy', '18'), _bg.setAttribute('stroke-width', '2'), _bg.setAttribute('fill', 'none'), _bg.setAttribute('class', 'bg'), _bg), ' ', (_progress = document.createElementNS(_svgNamespace, 'circle'), _progress.setAttribute('r', '15'), _progress.setAttribute('cx', '18'), _progress.setAttribute('cy', '18'), _progress.setAttribute('transform', 'rotate(-90, 18, 18)'), _progress.setAttribute('stroke-width', '2'), _progress.setAttribute('fill', 'none'), _progress.setAttribute('stroke-dasharray', '' + String(circleLength) + ''), _progress.setAttribute('stroke-dashoffset', '' + String(circleLength - circleLength / 100 * props.progress) + ''), _progress.setAttribute('class', 'progress'), _progress), ' ']), _progressGroup), ' ', (_play = document.createElementNS(_svgNamespace, 'polygon'), _play.setAttribute('transform', 'translate(3, 3)'), _play.setAttribute('points', '12 20 12 10 20 15'), _play.setAttribute('class', 'play'), _play), ' ', (_pause = document.createElementNS(_svgNamespace, 'g'), _pause.setAttribute('transform', 'translate(14.5, 13)'), _pause.setAttribute('class', 'pause'), _appendChild(_pause, [' ', (_rect = document.createElementNS(_svgNamespace, 'rect'), _rect.setAttribute('x', '0'), _rect.setAttribute('y', '0'), _rect.setAttribute('width', '2'), _rect.setAttribute('height', '10'), _rect.setAttribute('rx', '0'), _rect), ' ', (_rect2 = document.createElementNS(_svgNamespace, 'rect'), _rect2.setAttribute('x', '5'), _rect2.setAttribute('y', '0'), _rect2.setAttribute('width', '2'), _rect2.setAttribute('height', '10'), _rect2.setAttribute('rx', '0'), _rect2), ' ']), _pause), ' ', (_check = document.createElementNS(_svgNamespace, 'polygon'), _check.setAttribute('transform', 'translate(2, 3)'), _check.setAttribute('points', '14 22.5 7 15.2457065 8.99985857 13.1732815 14 18.3547104 22.9729883 9 25 11.1005634'), _check.setAttribute('class', 'check'), _check), ' ', (_cancel = document.createElementNS(_svgNamespace, 'polygon'), _cancel.setAttribute('transform', 'translate(2, 2)'), _cancel.setAttribute('points', '19.8856516 11.0625 16 14.9481516 12.1019737 11.0625 11.0625 12.1143484 14.9481516 16 11.0625 19.8980263 12.1019737 20.9375 16 17.0518484 19.8856516 20.9375 20.9375 19.8980263 17.0518484 16 20.9375 12'), _cancel.setAttribute('class', 'cancel'), _cancel)]), _uppyIcon;
};
},{"yo-yoify/lib/appendChild":131}],23:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
var FileItem = require('./FileItem');
var ActionBrowseTagline = require('./ActionBrowseTagline');
var _require = require('./icons'),
dashboardBgIcon = _require.dashboardBgIcon;
module.exports = function (props) {
var _ul, _uppyDashboardDropFilesTitle, _uppyDashboardInput, _uppyDashboardBgIcon;
return _ul = document.createElement('ul'), _ul.setAttribute('class', 'UppyDashboard-files\n ' + String(props.totalFileCount === 0 ? 'UppyDashboard-files--noFiles' : '') + ''), _appendChild(_ul, [' ', props.totalFileCount === 0 ? (_uppyDashboardBgIcon = document.createElement('div'), _uppyDashboardBgIcon.setAttribute('class', 'UppyDashboard-bgIcon'), _appendChild(_uppyDashboardBgIcon, [' ', dashboardBgIcon(), ' ', (_uppyDashboardDropFilesTitle = document.createElement('h3'), _uppyDashboardDropFilesTitle.setAttribute('class', 'UppyDashboard-dropFilesTitle'), _appendChild(_uppyDashboardDropFilesTitle, [' ', ActionBrowseTagline({
acquirers: props.acquirers,
handleInputChange: props.handleInputChange,
i18n: props.i18n
}), ' ']), _uppyDashboardDropFilesTitle), ' ', (_uppyDashboardInput = document.createElement('input'), _uppyDashboardInput.setAttribute('type', 'file'), _uppyDashboardInput.setAttribute('name', 'files[]'), 'true' && _uppyDashboardInput.setAttribute('multiple', 'multiple'), _uppyDashboardInput.onchange = props.handleInputChange, _uppyDashboardInput.setAttribute('class', 'UppyDashboard-input'), _uppyDashboardInput), ' ']), _uppyDashboardBgIcon) : null, ' ', Object.keys(props.files).map(function (fileID) {
return FileItem({
acquirers: props.acquirers,
file: props.files[fileID],
showFileCard: props.showFileCard,
showProgressDetails: props.showProgressDetails,
info: props.info,
log: props.log,
i18n: props.i18n,
removeFile: props.removeFile,
pauseUpload: props.pauseUpload,
cancelUpload: props.cancelUpload,
resumableUploads: props.resumableUploads,
isWide: props.isWide
});
}), ' ']), _ul;
};
},{"./ActionBrowseTagline":18,"./FileItem":21,"./icons":28,"yo-yoify/lib/appendChild":131}],24:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild'),
_svgNamespace = 'http://www.w3.org/2000/svg';
var throttle = require('lodash.throttle');
function progressBarWidth(props) {
return props.totalProgress;
}
function progressDetails(props) {
var _span;
// console.log(Date.now())
return _span = document.createElement('span'), _appendChild(_span, [props.totalProgress || 0, '%\u30FB', props.complete, ' / ', props.inProgress, '\u30FB', props.totalUploadedSize, ' / ', props.totalSize, '\u30FB\u2191 ', props.totalSpeed, '/s\u30FB', props.totalETA]), _span;
}
var throttledProgressDetails = throttle(progressDetails, 1000, { leading: true, trailing: true });
// const throttledProgressBarWidth = throttle(progressBarWidth, 300, {leading: true, trailing: true})
module.exports = function (props) {
var _progress, _uppyDashboardStatusBarProgress, _uppyDashboardStatusBarContent, _div, _span2, _span3, _path, _uppyDashboardStatusBarAction, _span4;
props = props || {};
var isHidden = props.totalFileCount === 0 || !props.isUploadStarted;
return _div = document.createElement('div'), _div.setAttribute('aria-hidden', '' + String(isHidden) + ''), _div.setAttribute('title', ''), _div.setAttribute('class', 'UppyDashboard-statusBar\n ' + String(props.isAllComplete ? 'is-complete' : '') + ''), _appendChild(_div, [' ', (_progress = document.createElement('progress'), _progress.setAttribute('style', 'display: none;'), _progress.setAttribute('min', '0'), _progress.setAttribute('max', '100'), _progress.setAttribute('value', '' + String(props.totalProgress) + ''), _progress), ' ', (_uppyDashboardStatusBarProgress = document.createElement('div'), _uppyDashboardStatusBarProgress.setAttribute('style', 'width: ' + String(progressBarWidth(props)) + '%'), _uppyDashboardStatusBarProgress.setAttribute('class', 'UppyDashboard-statusBarProgress'), _uppyDashboardStatusBarProgress), ' ', (_uppyDashboardStatusBarContent = document.createElement('div'), _uppyDashboardStatusBarContent.setAttribute('class', 'UppyDashboard-statusBarContent'), _appendChild(_uppyDashboardStatusBarContent, [' ', props.isUploadStarted && !props.isAllComplete ? !props.isAllPaused ? (_span2 = document.createElement('span'), _span2.setAttribute('title', 'Uploading'), _appendChild(_span2, [pauseResumeButtons(props), ' Uploading... ', throttledProgressDetails(props)]), _span2) : (_span3 = document.createElement('span'), _span3.setAttribute('title', 'Paused'), _appendChild(_span3, [pauseResumeButtons(props), ' Paused\u30FB', props.totalProgress, '%']), _span3) : null, ' ', props.isAllComplete ? (_span4 = document.createElement('span'), _span4.setAttribute('title', 'Complete'), _appendChild(_span4, [(_uppyDashboardStatusBarAction = document.createElementNS(_svgNamespace, 'svg'), _uppyDashboardStatusBarAction.setAttribute('width', '18'), _uppyDashboardStatusBarAction.setAttribute('height', '17'), _uppyDashboardStatusBarAction.setAttribute('viewBox', '0 0 23 17'), _uppyDashboardStatusBarAction.setAttribute('class', 'UppyDashboard-statusBarAction UppyIcon'), _appendChild(_uppyDashboardStatusBarAction, [' ', (_path = document.createElementNS(_svgNamespace, 'path'), _path.setAttribute('d', 'M8.944 17L0 7.865l2.555-2.61 6.39 6.525L20.41 0 23 2.645z'), _path), ' ']), _uppyDashboardStatusBarAction), 'Upload complete\u30FB', props.totalProgress, '%']), _span4) : null, ' ']), _uppyDashboardStatusBarContent), ' ']), _div;
};
var pauseResumeButtons = function pauseResumeButtons(props) {
var _uppyDashboardStatusBarAction2, _path2, _uppyIcon, _path3, _uppyIcon2, _path4, _uppyIcon3;
var title = props.resumableUploads ? props.isAllPaused ? 'resume upload' : 'pause upload' : 'cancel upload';
return _uppyDashboardStatusBarAction2 = document.createElement('button'), _uppyDashboardStatusBarAction2.setAttribute('title', '' + String(title) + ''), _uppyDashboardStatusBarAction2.setAttribute('type', 'button'), _uppyDashboardStatusBarAction2.onclick = function () {
return togglePauseResume(props);
}, _uppyDashboardStatusBarAction2.setAttribute('class', 'UppyDashboard-statusBarAction'), _appendChild(_uppyDashboardStatusBarAction2, [' ', props.resumableUploads ? props.isAllPaused ? (_uppyIcon = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon.setAttribute('width', '15'), _uppyIcon.setAttribute('height', '17'), _uppyIcon.setAttribute('viewBox', '0 0 11 13'), _uppyIcon.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon, [' ', (_path2 = document.createElementNS(_svgNamespace, 'path'), _path2.setAttribute('d', 'M1.26 12.534a.67.67 0 0 1-.674.012.67.67 0 0 1-.336-.583v-11C.25.724.38.5.586.382a.658.658 0 0 1 .673.012l9.165 5.5a.66.66 0 0 1 .325.57.66.66 0 0 1-.325.573l-9.166 5.5z'), _path2), ' ']), _uppyIcon) : (_uppyIcon2 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon2.setAttribute('width', '16'), _uppyIcon2.setAttribute('height', '17'), _uppyIcon2.setAttribute('viewBox', '0 0 12 13'), _uppyIcon2.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon2, [' ', (_path3 = document.createElementNS(_svgNamespace, 'path'), _path3.setAttribute('d', 'M4.888.81v11.38c0 .446-.324.81-.722.81H2.722C2.324 13 2 12.636 2 12.19V.81c0-.446.324-.81.722-.81h1.444c.398 0 .722.364.722.81zM9.888.81v11.38c0 .446-.324.81-.722.81H7.722C7.324 13 7 12.636 7 12.19V.81c0-.446.324-.81.722-.81h1.444c.398 0 .722.364.722.81z'), _path3), ' ']), _uppyIcon2) : (_uppyIcon3 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon3.setAttribute('width', '16px'), _uppyIcon3.setAttribute('height', '16px'), _uppyIcon3.setAttribute('viewBox', '0 0 19 19'), _uppyIcon3.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon3, [' ', (_path4 = document.createElementNS(_svgNamespace, 'path'), _path4.setAttribute('d', 'M17.318 17.232L9.94 9.854 9.586 9.5l-.354.354-7.378 7.378h.707l-.62-.62v.706L9.318 9.94l.354-.354-.354-.354L1.94 1.854v.707l.62-.62h-.706l7.378 7.378.354.354.354-.354 7.378-7.378h-.707l.622.62v-.706L9.854 9.232l-.354.354.354.354 7.378 7.378.708-.707-7.38-7.378v.708l7.38-7.38.353-.353-.353-.353-.622-.622-.353-.353-.354.352-7.378 7.38h.708L2.56 1.23 2.208.88l-.353.353-.622.62-.353.355.352.353 7.38 7.38v-.708l-7.38 7.38-.353.353.352.353.622.622.353.353.354-.353 7.38-7.38h-.708l7.38 7.38z'), _path4), ' ']), _uppyIcon3), ' ']), _uppyDashboardStatusBarAction2;
};
var togglePauseResume = function togglePauseResume(props) {
if (props.isAllComplete) return;
if (!props.resumableUploads) {
return props.cancelAll();
}
if (props.isAllPaused) {
return props.resumeAll();
}
return props.pauseAll();
};
},{"lodash.throttle":61,"yo-yoify/lib/appendChild":131}],25:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
var ActionBrowseTagline = require('./ActionBrowseTagline');
var _require = require('./icons'),
localIcon = _require.localIcon;
module.exports = function (props) {
var _uppyDashboardInput, _uppyDashboardTabName, _uppyDashboardTabBtn, _uppyDashboardTab, _uppyDashboardTabsList, _nav, _uppyDashboardTabs2;
var isHidden = Object.keys(props.files).length === 0;
if (props.acquirers.length === 0) {
var _uppyDashboardTabsTitle, _uppyDashboardTabs;
return _uppyDashboardTabs = document.createElement('div'), _uppyDashboardTabs.setAttribute('aria-hidden', '' + String(isHidden) + ''), _uppyDashboardTabs.setAttribute('class', 'UppyDashboardTabs'), _appendChild(_uppyDashboardTabs, [' ', (_uppyDashboardTabsTitle = document.createElement('h3'), _uppyDashboardTabsTitle.setAttribute('class', 'UppyDashboardTabs-title'), _appendChild(_uppyDashboardTabsTitle, [' ', ActionBrowseTagline({
acquirers: props.acquirers,
handleInputChange: props.handleInputChange,
i18n: props.i18n
}), ' ']), _uppyDashboardTabsTitle), ' ']), _uppyDashboardTabs;
}
var input = (_uppyDashboardInput = document.createElement('input'), _uppyDashboardInput.setAttribute('type', 'file'), _uppyDashboardInput.setAttribute('name', 'files[]'), 'true' && _uppyDashboardInput.setAttribute('multiple', 'multiple'), _uppyDashboardInput.onchange = props.handleInputChange, _uppyDashboardInput.setAttribute('class', 'UppyDashboard-input'), _uppyDashboardInput);
return _uppyDashboardTabs2 = document.createElement('div'), _uppyDashboardTabs2.setAttribute('class', 'UppyDashboardTabs'), _appendChild(_uppyDashboardTabs2, [' ', (_nav = document.createElement('nav'), _appendChild(_nav, [' ', (_uppyDashboardTabsList = document.createElement('ul'), _uppyDashboardTabsList.setAttribute('role', 'tablist'), _uppyDashboardTabsList.setAttribute('class', 'UppyDashboardTabs-list'), _appendChild(_uppyDashboardTabsList, [' ', (_uppyDashboardTab = document.createElement('li'), _uppyDashboardTab.setAttribute('class', 'UppyDashboardTab'), _appendChild(_uppyDashboardTab, [' ', (_uppyDashboardTabBtn = document.createElement('button'), _uppyDashboardTabBtn.setAttribute('type', 'button'), _uppyDashboardTabBtn.setAttribute('role', 'tab'), _uppyDashboardTabBtn.setAttribute('tabindex', '0'), _uppyDashboardTabBtn.onclick = function (ev) {
input.click();
}, _uppyDashboardTabBtn.setAttribute('class', 'UppyDashboardTab-btn UppyDashboard-focus'), _appendChild(_uppyDashboardTabBtn, [' ', localIcon(), ' ', (_uppyDashboardTabName = document.createElement('h5'), _uppyDashboardTabName.setAttribute('class', 'UppyDashboardTab-name'), _appendChild(_uppyDashboardTabName, [props.i18n('localDisk')]), _uppyDashboardTabName), ' ']), _uppyDashboardTabBtn), ' ', input, ' ']), _uppyDashboardTab), ' ', props.acquirers.map(function (target) {
var _uppyDashboardTabName2, _uppyDashboardTabBtn2, _uppyDashboardTab2;
return _uppyDashboardTab2 = document.createElement('li'), _uppyDashboardTab2.setAttribute('class', 'UppyDashboardTab'), _appendChild(_uppyDashboardTab2, [' ', (_uppyDashboardTabBtn2 = document.createElement('button'), _uppyDashboardTabBtn2.setAttribute('role', 'tab'), _uppyDashboardTabBtn2.setAttribute('tabindex', '0'), _uppyDashboardTabBtn2.setAttribute('aria-controls', 'UppyDashboardContent-panel--' + String(target.id) + ''), _uppyDashboardTabBtn2.setAttribute('aria-selected', '' + String(target.isHidden ? 'false' : 'true') + ''), _uppyDashboardTabBtn2.onclick = function () {
return props.showPanel(target.id);
}, _uppyDashboardTabBtn2.setAttribute('class', 'UppyDashboardTab-btn'), _appendChild(_uppyDashboardTabBtn2, [' ', target.icon(), ' ', (_uppyDashboardTabName2 = document.createElement('h5'), _uppyDashboardTabName2.setAttribute('class', 'UppyDashboardTab-name'), _appendChild(_uppyDashboardTabName2, [target.name]), _uppyDashboardTabName2), ' ']), _uppyDashboardTabBtn2), ' ']), _uppyDashboardTab2;
}), ' ']), _uppyDashboardTabsList), ' ']), _nav), ' ']), _uppyDashboardTabs2;
};
},{"./ActionBrowseTagline":18,"./icons":28,"yo-yoify/lib/appendChild":131}],26:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
var _require = require('./icons'),
uploadIcon = _require.uploadIcon;
module.exports = function (props) {
var _uppyDashboardUploadCount, _uppyButtonCircular;
props = props || {};
return _uppyButtonCircular = document.createElement('button'), _uppyButtonCircular.setAttribute('type', 'button'), _uppyButtonCircular.setAttribute('title', '' + String(props.i18n('uploadAllNewFiles')) + ''), _uppyButtonCircular.setAttribute('aria-label', '' + String(props.i18n('uploadAllNewFiles')) + ''), _uppyButtonCircular.onclick = props.startUpload, _uppyButtonCircular.setAttribute('class', 'UppyButton--circular\n UppyButton--blue\n UppyDashboard-upload'), _appendChild(_uppyButtonCircular, [' ', uploadIcon(), ' ', (_uppyDashboardUploadCount = document.createElement('sup'), _uppyDashboardUploadCount.setAttribute('title', '' + String(props.i18n('numberOfSelectedFiles')) + ''), _uppyDashboardUploadCount.setAttribute('aria-label', '' + String(props.i18n('numberOfSelectedFiles')) + ''), _uppyDashboardUploadCount.setAttribute('class', 'UppyDashboard-uploadCount'), _appendChild(_uppyDashboardUploadCount, [' ', props.newFileCount]), _uppyDashboardUploadCount), ' ']), _uppyButtonCircular;
};
},{"./icons":28,"yo-yoify/lib/appendChild":131}],27:[function(require,module,exports){
'use strict';
var _require = require('./icons'),
iconText = _require.iconText,
iconFile = _require.iconFile,
iconAudio = _require.iconAudio,
iconVideo = _require.iconVideo,
iconPDF = _require.iconPDF;
module.exports = function getIconByMime(fileTypeGeneral, fileTypeSpecific) {
if (fileTypeGeneral === 'text') {
return {
color: '#000',
icon: iconText()
};
}
if (fileTypeGeneral === 'audio') {
return {
color: '#1abc9c',
icon: iconAudio()
};
}
if (fileTypeGeneral === 'video') {
return {
color: '#2980b9',
icon: iconVideo()
};
}
if (fileTypeGeneral === 'application' && fileTypeSpecific === 'pdf') {
return {
color: '#e74c3c',
icon: iconPDF()
};
}
return {
color: '#000',
icon: iconFile()
};
};
},{"./icons":28}],28:[function(require,module,exports){
'use strict';
var _svgNamespace = 'http://www.w3.org/2000/svg',
_appendChild = require('yo-yoify/lib/appendChild');
// https://css-tricks.com/creating-svg-icon-system-react/
function defaultTabIcon() {
var _path, _uppyIcon;
return _uppyIcon = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon.setAttribute('width', '30'), _uppyIcon.setAttribute('height', '30'), _uppyIcon.setAttribute('viewBox', '0 0 30 30'), _uppyIcon.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon, [' ', (_path = document.createElementNS(_svgNamespace, 'path'), _path.setAttribute('d', 'M15 30c8.284 0 15-6.716 15-15 0-8.284-6.716-15-15-15C6.716 0 0 6.716 0 15c0 8.284 6.716 15 15 15zm4.258-12.676v6.846h-8.426v-6.846H5.204l9.82-12.364 9.82 12.364H19.26z'), _path), ' ']), _uppyIcon;
}
function iconCopy() {
var _path2, _path3, _uppyIcon2;
return _uppyIcon2 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon2.setAttribute('width', '51'), _uppyIcon2.setAttribute('height', '51'), _uppyIcon2.setAttribute('viewBox', '0 0 51 51'), _uppyIcon2.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon2, [' ', (_path2 = document.createElementNS(_svgNamespace, 'path'), _path2.setAttribute('d', 'M17.21 45.765a5.394 5.394 0 0 1-7.62 0l-4.12-4.122a5.393 5.393 0 0 1 0-7.618l6.774-6.775-2.404-2.404-6.775 6.776c-3.424 3.427-3.424 9 0 12.426l4.12 4.123a8.766 8.766 0 0 0 6.216 2.57c2.25 0 4.5-.858 6.214-2.57l13.55-13.552a8.72 8.72 0 0 0 2.575-6.213 8.73 8.73 0 0 0-2.575-6.213l-4.123-4.12-2.404 2.404 4.123 4.12a5.352 5.352 0 0 1 1.58 3.81c0 1.438-.562 2.79-1.58 3.808l-13.55 13.55z'), _path2), ' ', (_path3 = document.createElementNS(_svgNamespace, 'path'), _path3.setAttribute('d', 'M44.256 2.858A8.728 8.728 0 0 0 38.043.283h-.002a8.73 8.73 0 0 0-6.212 2.574l-13.55 13.55a8.725 8.725 0 0 0-2.575 6.214 8.73 8.73 0 0 0 2.574 6.216l4.12 4.12 2.405-2.403-4.12-4.12a5.357 5.357 0 0 1-1.58-3.812c0-1.437.562-2.79 1.58-3.808l13.55-13.55a5.348 5.348 0 0 1 3.81-1.58c1.44 0 2.792.562 3.81 1.58l4.12 4.12c2.1 2.1 2.1 5.518 0 7.617L39.2 23.775l2.404 2.404 6.775-6.777c3.426-3.427 3.426-9 0-12.426l-4.12-4.12z'), _path3), ' ']), _uppyIcon2;
}
function iconResume() {
var _play, _uppyIcon3;
return _uppyIcon3 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon3.setAttribute('width', '25'), _uppyIcon3.setAttribute('height', '25'), _uppyIcon3.setAttribute('viewBox', '0 0 44 44'), _uppyIcon3.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon3, [' ', (_play = document.createElementNS(_svgNamespace, 'polygon'), _play.setAttribute('transform', 'translate(6, 5.5)'), _play.setAttribute('points', '13 21.6666667 13 11 21 16.3333333'), _play.setAttribute('class', 'play'), _play), ' ']), _uppyIcon3;
}
function iconPause() {
var _rect, _rect2, _pause, _uppyIcon4;
return _uppyIcon4 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon4.setAttribute('width', '25px'), _uppyIcon4.setAttribute('height', '25px'), _uppyIcon4.setAttribute('viewBox', '0 0 44 44'), _uppyIcon4.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon4, [' ', (_pause = document.createElementNS(_svgNamespace, 'g'), _pause.setAttribute('transform', 'translate(18, 17)'), _pause.setAttribute('class', 'pause'), _appendChild(_pause, [' ', (_rect = document.createElementNS(_svgNamespace, 'rect'), _rect.setAttribute('x', '0'), _rect.setAttribute('y', '0'), _rect.setAttribute('width', '2'), _rect.setAttribute('height', '10'), _rect.setAttribute('rx', '0'), _rect), ' ', (_rect2 = document.createElementNS(_svgNamespace, 'rect'), _rect2.setAttribute('x', '6'), _rect2.setAttribute('y', '0'), _rect2.setAttribute('width', '2'), _rect2.setAttribute('height', '10'), _rect2.setAttribute('rx', '0'), _rect2), ' ']), _pause), ' ']), _uppyIcon4;
}
function iconEdit() {
var _path4, _uppyIcon5;
return _uppyIcon5 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon5.setAttribute('width', '28'), _uppyIcon5.setAttribute('height', '28'), _uppyIcon5.setAttribute('viewBox', '0 0 28 28'), _uppyIcon5.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon5, [' ', (_path4 = document.createElementNS(_svgNamespace, 'path'), _path4.setAttribute('d', 'M25.436 2.566a7.98 7.98 0 0 0-2.078-1.51C22.638.703 21.906.5 21.198.5a3 3 0 0 0-1.023.17 2.436 2.436 0 0 0-.893.562L2.292 18.217.5 27.5l9.28-1.796 16.99-16.99c.255-.254.444-.56.562-.888a3 3 0 0 0 .17-1.023c0-.708-.205-1.44-.555-2.16a8 8 0 0 0-1.51-2.077zM9.01 24.252l-4.313.834c0-.03.008-.06.012-.09.007-.944-.74-1.715-1.67-1.723-.04 0-.078.007-.118.01l.83-4.29L17.72 5.024l5.264 5.264L9.01 24.252zm16.84-16.96a.818.818 0 0 1-.194.31l-1.57 1.57-5.26-5.26 1.57-1.57a.82.82 0 0 1 .31-.194 1.45 1.45 0 0 1 .492-.074c.397 0 .917.126 1.468.397.55.27 1.13.678 1.656 1.21.53.53.94 1.11 1.208 1.655.272.55.397 1.07.393 1.468.004.193-.027.358-.074.488z'), _path4), ' ']), _uppyIcon5;
}
function localIcon() {
var _path5, _path6, _uppyIcon6;
return _uppyIcon6 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon6.setAttribute('width', '27'), _uppyIcon6.setAttribute('height', '25'), _uppyIcon6.setAttribute('viewBox', '0 0 27 25'), _uppyIcon6.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon6, [' ', (_path5 = document.createElementNS(_svgNamespace, 'path'), _path5.setAttribute('d', 'M5.586 9.288a.313.313 0 0 0 .282.176h4.84v3.922c0 1.514 1.25 2.24 2.792 2.24 1.54 0 2.79-.726 2.79-2.24V9.464h4.84c.122 0 .23-.068.284-.176a.304.304 0 0 0-.046-.324L13.735.106a.316.316 0 0 0-.472 0l-7.63 8.857a.302.302 0 0 0-.047.325z'), _path5), ' ', (_path6 = document.createElementNS(_svgNamespace, 'path'), _path6.setAttribute('d', 'M24.3 5.093c-.218-.76-.54-1.187-1.208-1.187h-4.856l1.018 1.18h3.948l2.043 11.038h-7.193v2.728H9.114v-2.725h-7.36l2.66-11.04h3.33l1.018-1.18H3.907c-.668 0-1.06.46-1.21 1.186L0 16.456v7.062C0 24.338.676 25 1.51 25h23.98c.833 0 1.51-.663 1.51-1.482v-7.062L24.3 5.093z'), _path6), ' ']), _uppyIcon6;
}
function closeIcon() {
var _path7, _uppyIcon7;
return _uppyIcon7 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon7.setAttribute('width', '14px'), _uppyIcon7.setAttribute('height', '14px'), _uppyIcon7.setAttribute('viewBox', '0 0 19 19'), _uppyIcon7.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon7, [' ', (_path7 = document.createElementNS(_svgNamespace, 'path'), _path7.setAttribute('d', 'M17.318 17.232L9.94 9.854 9.586 9.5l-.354.354-7.378 7.378h.707l-.62-.62v.706L9.318 9.94l.354-.354-.354-.354L1.94 1.854v.707l.62-.62h-.706l7.378 7.378.354.354.354-.354 7.378-7.378h-.707l.622.62v-.706L9.854 9.232l-.354.354.354.354 7.378 7.378.708-.707-7.38-7.378v.708l7.38-7.38.353-.353-.353-.353-.622-.622-.353-.353-.354.352-7.378 7.38h.708L2.56 1.23 2.208.88l-.353.353-.622.62-.353.355.352.353 7.38 7.38v-.708l-7.38 7.38-.353.353.352.353.622.622.353.353.354-.353 7.38-7.38h-.708l7.38 7.38z'), _path7), ' ']), _uppyIcon7;
}
function pluginIcon() {
var _path8, _path9, _uppyIcon8;
return _uppyIcon8 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon8.setAttribute('width', '16px'), _uppyIcon8.setAttribute('height', '16px'), _uppyIcon8.setAttribute('viewBox', '0 0 32 30'), _uppyIcon8.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon8, [' ', (_path8 = document.createElementNS(_svgNamespace, 'path'), _path8.setAttribute('d', 'M6.6209894,11.1451162 C6.6823051,11.2751669 6.81374248,11.3572188 6.95463813,11.3572188 L12.6925482,11.3572188 L12.6925482,16.0630427 C12.6925482,17.880509 14.1726048,18.75 16.0000083,18.75 C17.8261072,18.75 19.3074684,17.8801847 19.3074684,16.0630427 L19.3074684,11.3572188 L25.0437478,11.3572188 C25.1875787,11.3572188 25.3164069,11.2751669 25.3790272,11.1451162 C25.4370814,11.0173358 25.4171865,10.8642587 25.3252129,10.7562615 L16.278212,0.127131837 C16.2093949,0.0463771751 16.1069846,0 15.9996822,0 C15.8910751,0 15.7886648,0.0463771751 15.718217,0.127131837 L6.6761083,10.7559371 C6.58250402,10.8642587 6.56293518,11.0173358 6.6209894,11.1451162 L6.6209894,11.1451162 Z'), _path8), ' ', (_path9 = document.createElementNS(_svgNamespace, 'path'), _path9.setAttribute('d', 'M28.8008722,6.11142645 C28.5417891,5.19831555 28.1583331,4.6875 27.3684848,4.6875 L21.6124454,4.6875 L22.8190234,6.10307874 L27.4986725,6.10307874 L29.9195817,19.3486449 L21.3943891,19.3502502 L21.3943891,22.622552 L10.8023461,22.622552 L10.8023461,19.3524977 L2.07815702,19.3534609 L5.22979699,6.10307874 L9.17871529,6.10307874 L10.3840011,4.6875 L4.6308691,4.6875 C3.83940559,4.6875 3.37421888,5.2390909 3.19815864,6.11142645 L0,19.7470874 L0,28.2212959 C0,29.2043992 0.801477937,30 1.78870751,30 L30.2096773,30 C31.198199,30 32,29.2043992 32,28.2212959 L32,19.7470874 L28.8008722,6.11142645 L28.8008722,6.11142645 Z'), _path9), ' ']), _uppyIcon8;
}
function checkIcon() {
var _polygon, _uppyIcon9;
return _uppyIcon9 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon9.setAttribute('width', '13px'), _uppyIcon9.setAttribute('height', '9px'), _uppyIcon9.setAttribute('viewBox', '0 0 13 9'), _uppyIcon9.setAttribute('class', 'UppyIcon UppyIcon-check'), _appendChild(_uppyIcon9, [' ', (_polygon = document.createElementNS(_svgNamespace, 'polygon'), _polygon.setAttribute('points', '5 7.293 1.354 3.647 0.646 4.354 5 8.707 12.354 1.354 11.646 0.647'), _polygon)]), _uppyIcon9;
}
function iconAudio() {
var _path10, _uppyIcon10;
return _uppyIcon10 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon10.setAttribute('viewBox', '0 0 55 55'), _uppyIcon10.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon10, [' ', (_path10 = document.createElementNS(_svgNamespace, 'path'), _path10.setAttribute('d', 'M52.66.25c-.216-.19-.5-.276-.79-.242l-31 4.01a1 1 0 0 0-.87.992V40.622C18.174 38.428 15.273 37 12 37c-5.514 0-10 4.037-10 9s4.486 9 10 9 10-4.037 10-9c0-.232-.02-.46-.04-.687.014-.065.04-.124.04-.192V16.12l29-3.753v18.257C49.174 28.428 46.273 27 43 27c-5.514 0-10 4.037-10 9s4.486 9 10 9c5.464 0 9.913-3.966 9.993-8.867 0-.013.007-.024.007-.037V1a.998.998 0 0 0-.34-.75zM12 53c-4.41 0-8-3.14-8-7s3.59-7 8-7 8 3.14 8 7-3.59 7-8 7zm31-10c-4.41 0-8-3.14-8-7s3.59-7 8-7 8 3.14 8 7-3.59 7-8 7zM22 14.1V5.89l29-3.753v8.21l-29 3.754z'), _path10), ' ']), _uppyIcon10;
}
function iconVideo() {
var _path11, _path12, _uppyIcon11;
return _uppyIcon11 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon11.setAttribute('viewBox', '0 0 58 58'), _uppyIcon11.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon11, [' ', (_path11 = document.createElementNS(_svgNamespace, 'path'), _path11.setAttribute('d', 'M36.537 28.156l-11-7a1.005 1.005 0 0 0-1.02-.033C24.2 21.3 24 21.635 24 22v14a1 1 0 0 0 1.537.844l11-7a1.002 1.002 0 0 0 0-1.688zM26 34.18V23.82L34.137 29 26 34.18z'), _path11), (_path12 = document.createElementNS(_svgNamespace, 'path'), _path12.setAttribute('d', 'M57 6H1a1 1 0 0 0-1 1v44a1 1 0 0 0 1 1h56a1 1 0 0 0 1-1V7a1 1 0 0 0-1-1zM10 28H2v-9h8v9zm-8 2h8v9H2v-9zm10 10V8h34v42H12V40zm44-12h-8v-9h8v9zm-8 2h8v9h-8v-9zm8-22v9h-8V8h8zM2 8h8v9H2V8zm0 42v-9h8v9H2zm54 0h-8v-9h8v9z'), _path12), ' ']), _uppyIcon11;
}
function iconPDF() {
var _path13, _uppyIcon12;
return _uppyIcon12 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon12.setAttribute('viewBox', '0 0 342 335'), _uppyIcon12.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon12, [' ', (_path13 = document.createElementNS(_svgNamespace, 'path'), _path13.setAttribute('d', 'M329.337 227.84c-2.1 1.3-8.1 2.1-11.9 2.1-12.4 0-27.6-5.7-49.1-14.9 8.3-.6 15.8-.9 22.6-.9 12.4 0 16 0 28.2 3.1 12.1 3 12.2 9.3 10.2 10.6zm-215.1 1.9c4.8-8.4 9.7-17.3 14.7-26.8 12.2-23.1 20-41.3 25.7-56.2 11.5 20.9 25.8 38.6 42.5 52.8 2.1 1.8 4.3 3.5 6.7 5.3-34.1 6.8-63.6 15-89.6 24.9zm39.8-218.9c6.8 0 10.7 17.06 11 33.16.3 16-3.4 27.2-8.1 35.6-3.9-12.4-5.7-31.8-5.7-44.5 0 0-.3-24.26 2.8-24.26zm-133.4 307.2c3.9-10.5 19.1-31.3 41.6-49.8 1.4-1.1 4.9-4.4 8.1-7.4-23.5 37.6-39.3 52.5-49.7 57.2zm315.2-112.3c-6.8-6.7-22-10.2-45-10.5-15.6-.2-34.3 1.2-54.1 3.9-8.8-5.1-17.9-10.6-25.1-17.3-19.2-18-35.2-42.9-45.2-70.3.6-2.6 1.2-4.8 1.7-7.1 0 0 10.8-61.5 7.9-82.3-.4-2.9-.6-3.7-1.4-5.9l-.9-2.5c-2.9-6.76-8.7-13.96-17.8-13.57l-5.3-.17h-.1c-10.1 0-18.4 5.17-20.5 12.84-6.6 24.3.2 60.5 12.5 107.4l-3.2 7.7c-8.8 21.4-19.8 43-29.5 62l-1.3 2.5c-10.2 20-19.5 37-27.9 51.4l-8.7 4.6c-.6.4-15.5 8.2-19 10.3-29.6 17.7-49.28 37.8-52.54 53.8-1.04 5-.26 11.5 5.01 14.6l8.4 4.2c3.63 1.8 7.53 2.7 11.43 2.7 21.1 0 45.6-26.2 79.3-85.1 39-12.7 83.4-23.3 122.3-29.1 29.6 16.7 66 28.3 89 28.3 4.1 0 7.6-.4 10.5-1.2 4.4-1.1 8.1-3.6 10.4-7.1 4.4-6.7 5.4-15.9 4.1-25.4-.3-2.8-2.6-6.3-5-8.7z'), _path13), ' ']), _uppyIcon12;
}
function iconFile() {
var _path14, _uppyIcon13;
return _uppyIcon13 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon13.setAttribute('width', '44'), _uppyIcon13.setAttribute('height', '58'), _uppyIcon13.setAttribute('viewBox', '0 0 44 58'), _uppyIcon13.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon13, [' ', (_path14 = document.createElementNS(_svgNamespace, 'path'), _path14.setAttribute('d', 'M27.437.517a1 1 0 0 0-.094.03H4.25C2.037.548.217 2.368.217 4.58v48.405c0 2.212 1.82 4.03 4.03 4.03H39.03c2.21 0 4.03-1.818 4.03-4.03V15.61a1 1 0 0 0-.03-.28 1 1 0 0 0 0-.093 1 1 0 0 0-.03-.032 1 1 0 0 0 0-.03 1 1 0 0 0-.032-.063 1 1 0 0 0-.03-.063 1 1 0 0 0-.032 0 1 1 0 0 0-.03-.063 1 1 0 0 0-.032-.03 1 1 0 0 0-.03-.063 1 1 0 0 0-.063-.062l-14.593-14a1 1 0 0 0-.062-.062A1 1 0 0 0 28 .708a1 1 0 0 0-.374-.157 1 1 0 0 0-.156 0 1 1 0 0 0-.03-.03l-.003-.003zM4.25 2.547h22.218v9.97c0 2.21 1.82 4.03 4.03 4.03h10.564v36.438a2.02 2.02 0 0 1-2.032 2.032H4.25c-1.13 0-2.032-.9-2.032-2.032V4.58c0-1.13.902-2.032 2.03-2.032zm24.218 1.345l10.375 9.937.75.718H30.5c-1.13 0-2.032-.9-2.032-2.03V3.89z'), _path14), ' ']), _uppyIcon13;
}
function iconText() {
var _path15, _path16, _uppyIcon14;
return _uppyIcon14 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon14.setAttribute('viewBox', '0 0 64 64'), _uppyIcon14.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon14, [' ', (_path15 = document.createElementNS(_svgNamespace, 'path'), _path15.setAttribute('d', 'M8 64h48V0H22.586L8 14.586V64zm46-2H10V16h14V2h30v60zM11.414 14L22 3.414V14H11.414z'), _path15), ' ', (_path16 = document.createElementNS(_svgNamespace, 'path'), _path16.setAttribute('d', 'M32 13h14v2H32zM18 23h28v2H18zM18 33h28v2H18zM18 43h28v2H18zM18 53h28v2H18z'), _path16), ' ']), _uppyIcon14;
}
function uploadIcon() {
var _path17, _path18, _uppyIcon15;
return _uppyIcon15 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon15.setAttribute('width', '37'), _uppyIcon15.setAttribute('height', '33'), _uppyIcon15.setAttribute('viewBox', '0 0 37 33'), _uppyIcon15.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon15, [' ', (_path17 = document.createElementNS(_svgNamespace, 'path'), _path17.setAttribute('d', 'M29.107 24.5c4.07 0 7.393-3.355 7.393-7.442 0-3.994-3.105-7.307-7.012-7.502l.468.415C29.02 4.52 24.34.5 18.886.5c-4.348 0-8.27 2.522-10.138 6.506l.446-.288C4.394 6.782.5 10.758.5 15.608c0 4.924 3.906 8.892 8.76 8.892h4.872c.635 0 1.095-.467 1.095-1.104 0-.636-.46-1.103-1.095-1.103H9.26c-3.644 0-6.63-3.035-6.63-6.744 0-3.71 2.926-6.685 6.57-6.685h.964l.14-.28.177-.362c1.477-3.4 4.744-5.576 8.347-5.576 4.58 0 8.45 3.452 9.01 8.072l.06.536.05.446h1.101c2.87 0 5.204 2.37 5.204 5.295s-2.333 5.296-5.204 5.296h-6.062c-.634 0-1.094.467-1.094 1.103 0 .637.46 1.104 1.094 1.104h6.12z'), _path17), ' ', (_path18 = document.createElementNS(_svgNamespace, 'path'), _path18.setAttribute('d', 'M23.196 18.92l-4.828-5.258-.366-.4-.368.398-4.828 5.196a1.13 1.13 0 0 0 0 1.546c.428.46 1.11.46 1.537 0l3.45-3.71-.868-.34v15.03c0 .64.445 1.118 1.075 1.118.63 0 1.075-.48 1.075-1.12V16.35l-.867.34 3.45 3.712a1 1 0 0 0 .767.345 1 1 0 0 0 .77-.345c.416-.33.416-1.036 0-1.485v.003z'), _path18), ' ']), _uppyIcon15;
}
function dashboardBgIcon() {
var _path19, _uppyIcon16;
return _uppyIcon16 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon16.setAttribute('width', '48'), _uppyIcon16.setAttribute('height', '69'), _uppyIcon16.setAttribute('viewBox', '0 0 48 69'), _uppyIcon16.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon16, [' ', (_path19 = document.createElementNS(_svgNamespace, 'path'), _path19.setAttribute('d', 'M.5 1.5h5zM10.5 1.5h5zM20.5 1.5h5zM30.504 1.5h5zM45.5 11.5v5zM45.5 21.5v5zM45.5 31.5v5zM45.5 41.502v5zM45.5 51.502v5zM45.5 61.5v5zM45.5 66.502h-4.998zM35.503 66.502h-5zM25.5 66.502h-5zM15.5 66.502h-5zM5.5 66.502h-5zM.5 66.502v-5zM.5 56.502v-5zM.5 46.503V41.5zM.5 36.5v-5zM.5 26.5v-5zM.5 16.5v-5zM.5 6.5V1.498zM44.807 11H36V2.195z'), _path19), ' ']), _uppyIcon16;
}
module.exports = {
defaultTabIcon: defaultTabIcon,
iconCopy: iconCopy,
iconResume: iconResume,
iconPause: iconPause,
iconEdit: iconEdit,
localIcon: localIcon,
closeIcon: closeIcon,
pluginIcon: pluginIcon,
checkIcon: checkIcon,
iconAudio: iconAudio,
iconVideo: iconVideo,
iconPDF: iconPDF,
iconFile: iconFile,
iconText: iconText,
uploadIcon: uploadIcon,
dashboardBgIcon: dashboardBgIcon
};
},{"yo-yoify/lib/appendChild":131}],29:[function(require,module,exports){
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var Plugin = require('../Plugin');
var Translator = require('../../core/Translator');
var dragDrop = require('drag-drop');
var Dashboard = require('./Dashboard');
var _require = require('../../core/Utils'),
getSpeed = _require.getSpeed;
var _require2 = require('../../core/Utils'),
getETA = _require2.getETA;
var _require3 = require('../../core/Utils'),
prettyETA = _require3.prettyETA;
var _require4 = require('../../core/Utils'),
findDOMElement = _require4.findDOMElement;
var prettyBytes = require('prettier-bytes');
var _require5 = require('./icons'),
defaultTabIcon = _require5.defaultTabIcon;
/**
* Modal Dialog & Dashboard
*/
module.exports = function (_Plugin) {
_inherits(DashboardUI, _Plugin);
function DashboardUI(core, opts) {
_classCallCheck(this, DashboardUI);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, core, opts));
_this.id = 'DashboardUI';
_this.title = 'Dashboard UI';
_this.type = 'orchestrator';
var defaultLocale = {
strings: {
selectToUpload: 'Select files to upload',
closeModal: 'Close Modal',
upload: 'Upload',
importFrom: 'Import files from',
dashboardWindowTitle: 'Uppy Dashboard Window (Press escape to close)',
dashboardTitle: 'Uppy Dashboard',
copyLinkToClipboardSuccess: 'Link copied to clipboard.',
copyLinkToClipboardFallback: 'Copy the URL below',
done: 'Done',
localDisk: 'Local Disk',
dropPasteImport: 'Drop files here, paste, import from one of the locations above or',
dropPaste: 'Drop files here, paste or',
browse: 'browse',
fileProgress: 'File progress: upload speed and ETA',
numberOfSelectedFiles: 'Number of selected files',
uploadAllNewFiles: 'Upload all new files'
}
};
// set default options
var defaultOptions = {
target: 'body',
inline: false,
width: 750,
height: 550,
semiTransparent: false,
defaultTabIcon: defaultTabIcon(),
showProgressDetails: false,
locale: defaultLocale
};
// merge default options with the ones set by user
_this.opts = _extends({}, defaultOptions, opts);
_this.locale = _extends({}, defaultLocale, _this.opts.locale);
_this.locale.strings = _extends({}, defaultLocale.strings, _this.opts.locale.strings);
_this.translator = new Translator({ locale: _this.locale });
_this.containerWidth = _this.translator.translate.bind(_this.translator);
_this.hideModal = _this.hideModal.bind(_this);
_this.showModal = _this.showModal.bind(_this);
_this.addTarget = _this.addTarget.bind(_this);
_this.actions = _this.actions.bind(_this);
_this.hideAllPanels = _this.hideAllPanels.bind(_this);
_this.showPanel = _this.showPanel.bind(_this);
_this.initEvents = _this.initEvents.bind(_this);
_this.handleEscapeKeyPress = _this.handleEscapeKeyPress.bind(_this);
_this.handleFileCard = _this.handleFileCard.bind(_this);
_this.handleDrop = _this.handleDrop.bind(_this);
_this.pauseAll = _this.pauseAll.bind(_this);
_this.resumeAll = _this.resumeAll.bind(_this);
_this.cancelAll = _this.cancelAll.bind(_this);
_this.updateDashboardElWidth = _this.updateDashboardElWidth.bind(_this);
_this.render = _this.render.bind(_this);
_this.install = _this.install.bind(_this);
return _this;
}
DashboardUI.prototype.addTarget = function addTarget(plugin) {
var callerPluginId = plugin.id || plugin.constructor.name;
var callerPluginName = plugin.title || callerPluginId;
var callerPluginIcon = plugin.icon || this.opts.defaultTabIcon;
var callerPluginType = plugin.type;
if (callerPluginType !== 'acquirer' && callerPluginType !== 'progressindicator' && callerPluginType !== 'presenter') {
var msg = 'Error: Modal can only be used by plugins of types: acquirer, progressindicator, presenter';
this.core.log(msg);
return;
}
var target = {
id: callerPluginId,
name: callerPluginName,
icon: callerPluginIcon,
type: callerPluginType,
focus: plugin.focus,
render: plugin.render,
isHidden: true
};
var modal = this.core.getState().modal;
var newTargets = modal.targets.slice();
newTargets.push(target);
this.core.setState({
modal: _extends({}, modal, {
targets: newTargets
})
});
return this.target;
};
DashboardUI.prototype.hideAllPanels = function hideAllPanels() {
var modal = this.core.getState().modal;
this.core.setState({ modal: _extends({}, modal, {
activePanel: false
}) });
};
DashboardUI.prototype.showPanel = function showPanel(id) {
var modal = this.core.getState().modal;
var activePanel = modal.targets.filter(function (target) {
return target.type === 'acquirer' && target.id === id;
})[0];
this.core.setState({ modal: _extends({}, modal, {
activePanel: activePanel
}) });
};
DashboardUI.prototype.hideModal = function hideModal() {
var modal = this.core.getState().modal;
this.core.setState({
modal: _extends({}, modal, {
isHidden: true
})
});
document.body.classList.remove('is-UppyDashboard-open');
};
DashboardUI.prototype.showModal = function showModal() {
var modal = this.core.getState().modal;
this.core.setState({
modal: _extends({}, modal, {
isHidden: false
})
});
// add class to body that sets position fixed
document.body.classList.add('is-UppyDashboard-open');
// focus on modal inner block
this.target.querySelector('.UppyDashboard-inner').focus();
this.updateDashboardElWidth();
// to be sure, sometimes when the function runs, container size is still 0
setTimeout(this.updateDashboardElWidth, 300);
};
// Close the Modal on esc key press
DashboardUI.prototype.handleEscapeKeyPress = function handleEscapeKeyPress(event) {
if (event.keyCode === 27) {
this.hideModal();
}
};
DashboardUI.prototype.initEvents = function initEvents() {
var _this2 = this;
// const dashboardEl = this.target.querySelector(`${this.opts.target} .UppyDashboard`)
// Modal open button
var showModalTrigger = findDOMElement(this.opts.trigger);
if (!this.opts.inline && showModalTrigger) {
showModalTrigger.addEventListener('click', this.showModal);
} else {
this.core.log('Modal trigger wasn’t found');
}
document.body.addEventListener('keyup', this.handleEscapeKeyPress);
// Drag Drop
this.removeDragDropListener = dragDrop(this.el, function (files) {
_this2.handleDrop(files);
});
};
DashboardUI.prototype.removeEvents = function removeEvents() {
var showModalTrigger = findDOMElement(this.opts.trigger);
if (!this.opts.inline && showModalTrigger) {
showModalTrigger.removeEventListener('click', this.showModal);
}
this.removeDragDropListener();
document.body.removeEventListener('keyup', this.handleEscapeKeyPress);
};
DashboardUI.prototype.actions = function actions() {
var bus = this.core.bus;
bus.on('core:file-add', this.hideAllPanels);
bus.on('dashboard:file-card', this.handleFileCard);
window.addEventListener('resize', this.updateDashboardElWidth);
// bus.on('core:success', (uploadedCount) => {
// bus.emit(
// 'informer',
// `${this.core.i18n('files', {'smart_count': uploadedCount})} successfully uploaded, Sir!`,
// 'info',
// 6000
// )
// })
};
DashboardUI.prototype.removeActions = function removeActions() {
var bus = this.core.bus;
window.removeEventListener('resize', this.updateDashboardElWidth);
bus.off('core:file-add', this.hideAllPanels);
bus.off('dashboard:file-card', this.handleFileCard);
};
DashboardUI.prototype.updateDashboardElWidth = function updateDashboardElWidth() {
var dashboardEl = this.target.querySelector('.UppyDashboard-inner');
var containerWidth = dashboardEl.offsetWidth;
console.log(containerWidth);
var modal = this.core.getState().modal;
this.core.setState({
modal: _extends({}, modal, {
containerWidth: dashboardEl.offsetWidth
})
});
};
DashboardUI.prototype.handleFileCard = function handleFileCard(fileId) {
var modal = this.core.getState().modal;
this.core.setState({
modal: _extends({}, modal, {
fileCardFor: fileId || false
})
});
};
DashboardUI.prototype.handleDrop = function handleDrop(files) {
var _this3 = this;
this.core.log('All right, someone dropped something...');
files.forEach(function (file) {
_this3.core.bus.emit('core:file-add', {
source: _this3.id,
name: file.name,
type: file.type,
data: file
});
});
};
DashboardUI.prototype.cancelAll = function cancelAll() {
this.core.bus.emit('core:cancel-all');
};
DashboardUI.prototype.pauseAll = function pauseAll() {
this.core.bus.emit('core:pause-all');
};
DashboardUI.prototype.resumeAll = function resumeAll() {
this.core.bus.emit('core:resume-all');
};
DashboardUI.prototype.getTotalSpeed = function getTotalSpeed(files) {
var totalSpeed = 0;
files.forEach(function (file) {
totalSpeed = totalSpeed + getSpeed(file.progress);
});
return totalSpeed;
};
DashboardUI.prototype.getTotalETA = function getTotalETA(files) {
var totalSeconds = 0;
files.forEach(function (file) {
totalSeconds = totalSeconds + getETA(file.progress);
});
return totalSeconds;
};
DashboardUI.prototype.render = function render(state) {
var _this4 = this;
var files = state.files;
var newFiles = Object.keys(files).filter(function (file) {
return !files[file].progress.uploadStarted;
});
var uploadStartedFiles = Object.keys(files).filter(function (file) {
return files[file].progress.uploadStarted;
});
var completeFiles = Object.keys(files).filter(function (file) {
return files[file].progress.uploadComplete;
});
var inProgressFiles = Object.keys(files).filter(function (file) {
return !files[file].progress.uploadComplete && files[file].progress.uploadStarted && !files[file].isPaused;
});
var inProgressFilesArray = [];
inProgressFiles.forEach(function (file) {
inProgressFilesArray.push(files[file]);
});
var totalSpeed = prettyBytes(this.getTotalSpeed(inProgressFilesArray));
var totalETA = prettyETA(this.getTotalETA(inProgressFilesArray));
// total size and uploaded size
var totalSize = 0;
var totalUploadedSize = 0;
inProgressFilesArray.forEach(function (file) {
totalSize = totalSize + (file.progress.bytesTotal || 0);
totalUploadedSize = totalUploadedSize + (file.progress.bytesUploaded || 0);
});
totalSize = prettyBytes(totalSize);
totalUploadedSize = prettyBytes(totalUploadedSize);
var isAllComplete = state.totalProgress === 100;
var isAllPaused = inProgressFiles.length === 0 && !isAllComplete && uploadStartedFiles.length > 0;
var isUploadStarted = uploadStartedFiles.length > 0;
var acquirers = state.modal.targets.filter(function (target) {
return target.type === 'acquirer';
});
var progressindicators = state.modal.targets.filter(function (target) {
return target.type === 'progressindicator';
});
var addFile = function addFile(file) {
_this4.core.emitter.emit('core:file-add', file);
};
var removeFile = function removeFile(fileID) {
_this4.core.emitter.emit('core:file-remove', fileID);
};
var startUpload = function startUpload(ev) {
_this4.core.upload().catch(function (err) {
// Log error.
console.error(err.stack || err.message);
});
};
var pauseUpload = function pauseUpload(fileID) {
_this4.core.emitter.emit('core:upload-pause', fileID);
};
var cancelUpload = function cancelUpload(fileID) {
_this4.core.emitter.emit('core:upload-cancel', fileID);
_this4.core.emitter.emit('core:file-remove', fileID);
};
var showFileCard = function showFileCard(fileID) {
_this4.core.emitter.emit('dashboard:file-card', fileID);
};
var fileCardDone = function fileCardDone(meta, fileID) {
_this4.core.emitter.emit('core:update-meta', meta, fileID);
_this4.core.emitter.emit('dashboard:file-card');
};
var info = function info(text, type, duration) {
_this4.core.emitter.emit('informer', text, type, duration);
};
var resumableUploads = this.core.getState().capabilities.resumableUploads || false;
return Dashboard({
state: state,
modal: state.modal,
newFiles: newFiles,
files: files,
totalFileCount: Object.keys(files).length,
isUploadStarted: isUploadStarted,
inProgress: uploadStartedFiles.length,
completeFiles: completeFiles,
inProgressFiles: inProgressFiles,
totalSpeed: totalSpeed,
totalETA: totalETA,
totalProgress: state.totalProgress,
totalSize: totalSize,
totalUploadedSize: totalUploadedSize,
isAllComplete: isAllComplete,
isAllPaused: isAllPaused,
acquirers: acquirers,
activePanel: state.modal.activePanel,
progressindicators: progressindicators,
autoProceed: this.core.opts.autoProceed,
id: this.id,
hideModal: this.hideModal,
showProgressDetails: this.opts.showProgressDetails,
inline: this.opts.inline,
semiTransparent: this.opts.semiTransparent,
onPaste: this.handlePaste,
showPanel: this.showPanel,
hideAllPanels: this.hideAllPanels,
log: this.core.log,
bus: this.core.emitter,
i18n: this.containerWidth,
pauseAll: this.pauseAll,
resumeAll: this.resumeAll,
cancelAll: this.cancelAll,
addFile: addFile,
removeFile: removeFile,
info: info,
metaFields: state.metaFields,
resumableUploads: resumableUploads,
startUpload: startUpload,
pauseUpload: pauseUpload,
cancelUpload: cancelUpload,
fileCardFor: state.modal.fileCardFor,
showFileCard: showFileCard,
fileCardDone: fileCardDone,
updateDashboardElWidth: this.updateDashboardElWidth,
maxWidth: this.opts.maxWidth,
maxHeight: this.opts.maxHeight,
currentWidth: state.modal.containerWidth,
isWide: state.modal.containerWidth > 400
});
};
DashboardUI.prototype.install = function install() {
// Set default state for Modal
this.core.setState({ modal: {
isHidden: true,
showFileCard: false,
activePanel: false,
targets: []
} });
var target = this.opts.target;
var plugin = this;
this.target = this.mount(target, plugin);
this.initEvents();
this.actions();
};
DashboardUI.prototype.uninstall = function uninstall() {
this.unmount();
this.removeActions();
this.removeEvents();
};
return DashboardUI;
}(Plugin);
},{"../../core/Translator":4,"../../core/Utils":6,"../Plugin":39,"./Dashboard":19,"./icons":28,"drag-drop":57,"prettier-bytes":66}],30:[function(require,module,exports){
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _svgNamespace = 'http://www.w3.org/2000/svg',
_appendChild = require('yo-yoify/lib/appendChild');
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var Plugin = require('./../Plugin');
var Translator = require('../../core/Translator');
var _require = require('../../core/Utils'),
toArray = _require.toArray;
var dragDrop = require('drag-drop');
/**
* Drag & Drop plugin
*
*/
module.exports = function (_Plugin) {
_inherits(DragDrop, _Plugin);
function DragDrop(core, opts) {
var _path, _path2, _path3, _uppyIcon;
_classCallCheck(this, DragDrop);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, core, opts));
_this.type = 'acquirer';
_this.id = 'DragDrop';
_this.title = 'Drag & Drop';
_this.icon = (_uppyIcon = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon.setAttribute('width', '28'), _uppyIcon.setAttribute('height', '28'), _uppyIcon.setAttribute('viewBox', '0 0 16 16'), _uppyIcon.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon, [' ', (_path = document.createElementNS(_svgNamespace, 'path'), _path.setAttribute('d', 'M15.982 2.97c0-.02 0-.02-.018-.037 0-.017-.017-.035-.035-.053 0 0 0-.018-.02-.018-.017-.018-.034-.053-.052-.07L13.19.123c-.017-.017-.034-.035-.07-.053h-.018c-.018-.017-.035-.017-.053-.034h-.02c-.017 0-.034-.018-.052-.018h-6.31a.415.415 0 0 0-.446.426V11.11c0 .25.196.446.445.446h8.89A.44.44 0 0 0 16 11.11V3.023c-.018-.018-.018-.035-.018-.053zm-2.65-1.46l1.157 1.157h-1.157V1.51zm1.78 9.157h-8V.89h5.332v2.22c0 .25.196.446.445.446h2.22v7.11z'), _path), ' ', (_path2 = document.createElementNS(_svgNamespace, 'path'), _path2.setAttribute('d', 'M9.778 12.89H4V2.666a.44.44 0 0 0-.444-.445.44.44 0 0 0-.445.445v10.666c0 .25.197.445.446.445h6.222a.44.44 0 0 0 .444-.445.44.44 0 0 0-.444-.444z'), _path2), ' ', (_path3 = document.createElementNS(_svgNamespace, 'path'), _path3.setAttribute('d', 'M.444 16h6.223a.44.44 0 0 0 .444-.444.44.44 0 0 0-.443-.445H.89V4.89a.44.44 0 0 0-.446-.446A.44.44 0 0 0 0 4.89v10.666c0 .248.196.444.444.444z'), _path3), ' ']), _uppyIcon);
var defaultLocale = {
strings: {
chooseFile: 'Choose a file',
orDragDrop: 'or drop it here',
upload: 'Upload',
selectedFiles: {
0: '%{smart_count} file selected',
1: '%{smart_count} files selected'
}
}
};
// Default options
var defaultOpts = {
target: '.UppyDragDrop',
locale: defaultLocale
};
// Merge default options with the ones set by user
_this.opts = _extends({}, defaultOpts, opts);
_this.locale = _extends({}, defaultLocale, _this.opts.locale);
_this.locale.strings = _extends({}, defaultLocale.strings, _this.opts.locale.strings);
// Check for browser dragDrop support
_this.isDragDropSupported = _this.checkDragDropSupport();
// i18n
_this.translator = new Translator({ locale: _this.locale });
_this.i18n = _this.translator.translate.bind(_this.translator);
// Bind `this` to class methods
_this.handleDrop = _this.handleDrop.bind(_this);
_this.checkDragDropSupport = _this.checkDragDropSupport.bind(_this);
_this.handleInputChange = _this.handleInputChange.bind(_this);
_this.render = _this.render.bind(_this);
return _this;
}
/**
* Checks if the browser supports Drag & Drop (not supported on mobile devices, for example).
* @return {Boolean} true if supported, false otherwise
*/
DragDrop.prototype.checkDragDropSupport = function checkDragDropSupport() {
var div = document.createElement('div');
if (!('draggable' in div) || !('ondragstart' in div && 'ondrop' in div)) {
return false;
}
if (!('FormData' in window)) {
return false;
}
if (!('FileReader' in window)) {
return false;
}
return true;
};
DragDrop.prototype.handleDrop = function handleDrop(files) {
var _this2 = this;
this.core.log('All right, someone dropped something...');
files.forEach(function (file) {
_this2.core.addFile({
source: _this2.id,
name: file.name,
type: file.type,
data: file
});
});
};
DragDrop.prototype.handleInputChange = function handleInputChange(ev) {
var _this3 = this;
this.core.log('All right, something selected through input...');
var files = toArray(ev.target.files);
files.forEach(function (file) {
_this3.core.emitter.emit('core:file-add', {
source: _this3.id,
name: file.name,
type: file.type,
data: file
});
});
};
DragDrop.prototype.render = function render(state) {
var _this4 = this,
_uppyDragDropInput,
_strong,
_uppyDragDropDragText,
_uppyDragDropLabel,
_uppyDragDropInner,
_div,
_uppyDragDropSelectedCount;
var onSelect = function onSelect(ev) {
var input = _this4.target.querySelector('.UppyDragDrop-input');
input.click();
};
// const next = (ev) => {
// ev.preventDefault()
// ev.stopPropagation()
// this.core.emitter.emit('core:upload')
// }
// onload=${(ev) => {
// const firstInput = this.target.querySelector('.UppyDragDrop-focus')
// firstInput.focus()
// }}
// ${!this.core.opts.autoProceed
// ? html`<button class="UppyDragDrop-uploadBtn UppyNextBtn"
// type="submit"
// onclick=${next}>
// ${this.i18n('upload')}
// </button>`
// : ''}
var selectedFilesCount = Object.keys(state.files).length;
return _div = document.createElement('div'), _div.setAttribute('class', 'Uppy UppyTheme--default UppyDragDrop-container ' + String(this.isDragDropSupported ? 'is-dragdrop-supported' : '') + ''), _appendChild(_div, [' ', (_uppyDragDropInner = document.createElement('form'), _uppyDragDropInner.onsubmit = function (ev) {
return ev.preventDefault();
}, _uppyDragDropInner.setAttribute('class', 'UppyDragDrop-inner'), _appendChild(_uppyDragDropInner, [' ', (_uppyDragDropInput = document.createElement('input'), _uppyDragDropInput.setAttribute('type', 'file'), _uppyDragDropInput.setAttribute('name', 'files[]'), 'true' && _uppyDragDropInput.setAttribute('multiple', 'multiple'), _uppyDragDropInput.setAttribute('value', ''), _uppyDragDropInput.onchange = this.handleInputChange.bind(this), _uppyDragDropInput.setAttribute('class', 'UppyDragDrop-input UppyDragDrop-focus'), _uppyDragDropInput), ' ', (_uppyDragDropLabel = document.createElement('label'), _uppyDragDropLabel.onclick = onSelect, _uppyDragDropLabel.setAttribute('class', 'UppyDragDrop-label'), _appendChild(_uppyDragDropLabel, [' ', (_strong = document.createElement('strong'), _appendChild(_strong, [this.i18n('chooseFile')]), _strong), ' ', (_uppyDragDropDragText = document.createElement('span'), _uppyDragDropDragText.setAttribute('class', 'UppyDragDrop-dragText'), _appendChild(_uppyDragDropDragText, [this.i18n('orDragDrop')]), _uppyDragDropDragText), ' ']), _uppyDragDropLabel), ' ', selectedFilesCount > 0 ? (_uppyDragDropSelectedCount = document.createElement('div'), _uppyDragDropSelectedCount.setAttribute('class', 'UppyDragDrop-selectedCount'), _appendChild(_uppyDragDropSelectedCount, [' ', this.i18n('selectedFiles', { 'smart_count': selectedFilesCount }), ' ']), _uppyDragDropSelectedCount) : '', ' ']), _uppyDragDropInner), ' ']), _div;
};
DragDrop.prototype.install = function install() {
var _this5 = this;
var target = this.opts.target;
var plugin = this;
this.target = this.mount(target, plugin);
var dndContainer = this.target.querySelector('.UppyDragDrop-container');
this.removeDragDropListener = dragDrop(dndContainer, function (files) {
_this5.handleDrop(files);
_this5.core.log(files);
});
};
DragDrop.prototype.uninstall = function uninstall() {
this.removeDragDropListener();
this.unmount();
};
return DragDrop;
}(Plugin);
},{"../../core/Translator":4,"../../core/Utils":6,"./../Plugin":39,"drag-drop":57,"yo-yoify/lib/appendChild":131}],31:[function(require,module,exports){
'use strict';
var _svgNamespace = 'http://www.w3.org/2000/svg',
_appendChild = require('yo-yoify/lib/appendChild');
module.exports = {
folder: function folder() {
var _path, _uppyIcon;
return _uppyIcon = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon.setAttribute('style', 'width:16px;margin-right:3px'), _uppyIcon.setAttribute('viewBox', '0 0 276.157 276.157'), _uppyIcon.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon, [' ', (_path = document.createElementNS(_svgNamespace, 'path'), _path.setAttribute('d', 'M273.08 101.378c-3.3-4.65-8.86-7.32-15.254-7.32h-24.34V67.59c0-10.2-8.3-18.5-18.5-18.5h-85.322c-3.63 0-9.295-2.875-11.436-5.805l-6.386-8.735c-4.982-6.814-15.104-11.954-23.546-11.954H58.73c-9.292 0-18.638 6.608-21.737 15.372l-2.033 5.752c-.958 2.71-4.72 5.37-7.596 5.37H18.5C8.3 49.09 0 57.39 0 67.59v167.07c0 .886.16 1.73.443 2.52.152 3.306 1.18 6.424 3.053 9.064 3.3 4.652 8.86 7.32 15.255 7.32h188.487c11.395 0 23.27-8.425 27.035-19.18l40.677-116.188c2.11-6.035 1.43-12.164-1.87-16.816zM18.5 64.088h8.864c9.295 0 18.64-6.607 21.738-15.37l2.032-5.75c.96-2.712 4.722-5.373 7.597-5.373h29.565c3.63 0 9.295 2.876 11.437 5.806l6.386 8.735c4.982 6.815 15.104 11.954 23.546 11.954h85.322c1.898 0 3.5 1.602 3.5 3.5v26.47H69.34c-11.395 0-23.27 8.423-27.035 19.178L15 191.23V67.59c0-1.898 1.603-3.5 3.5-3.5zm242.29 49.15l-40.676 116.188c-1.674 4.78-7.812 9.135-12.877 9.135H18.75c-1.447 0-2.576-.372-3.02-.997-.442-.625-.422-1.814.057-3.18l40.677-116.19c1.674-4.78 7.812-9.134 12.877-9.134h188.487c1.448 0 2.577.372 3.02.997.443.625.423 1.814-.056 3.18z'), _path), ' ']), _uppyIcon;
},
music: function music() {
var _path2, _path3, _path4, _path5, _g, _uppyIcon2;
return _uppyIcon2 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon2.setAttribute('width', '16.000000pt'), _uppyIcon2.setAttribute('height', '16.000000pt'), _uppyIcon2.setAttribute('viewBox', '0 0 48.000000 48.000000'), _uppyIcon2.setAttribute('preserveAspectRatio', 'xMidYMid meet'), _uppyIcon2.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon2, [' ', (_g = document.createElementNS(_svgNamespace, 'g'), _g.setAttribute('transform', 'translate(0.000000,48.000000) scale(0.100000,-0.100000)'), _g.setAttribute('fill', '#525050'), _g.setAttribute('stroke', 'none'), _appendChild(_g, [' ', (_path2 = document.createElementNS(_svgNamespace, 'path'), _path2.setAttribute('d', 'M209 473 c0 -5 0 -52 1 -106 1 -54 -2 -118 -6 -143 l-7 -46 -44 5\n c-73 8 -133 -46 -133 -120 0 -17 -5 -35 -10 -38 -18 -11 0 -25 33 -24 30 1 30\n 1 7 8 -15 4 -20 10 -13 14 6 4 9 16 6 27 -9 34 7 70 40 90 17 11 39 20 47 20\n 8 0 -3 -9 -26 -19 -42 -19 -54 -36 -54 -75 0 -36 30 -56 84 -56 41 0 53 5 82\n 34 19 19 34 31 34 27 0 -4 -5 -12 -12 -19 -9 -9 -1 -12 39 -12 106 0 183 -21\n 121 -33 -17 -3 -14 -5 10 -6 25 -1 32 3 32 17 0 26 -20 42 -51 42 -39 0 -43\n 13 -10 38 56 41 76 124 45 185 -25 48 -72 105 -103 123 -15 9 -36 29 -47 45\n -17 26 -63 41 -65 22z m56 -48 c16 -24 31 -42 34 -39 9 9 79 -69 74 -83 -3 -7\n -2 -13 3 -12 18 3 25 -1 19 -12 -5 -7 -16 -2 -33 13 l-26 23 16 -25 c17 -27\n 29 -92 16 -84 -4 3 -8 -8 -8 -25 0 -16 4 -33 10 -36 5 -3 7 0 4 9 -3 9 3 20\n 15 28 13 8 21 24 22 43 1 18 3 23 6 12 3 -10 2 -29 -1 -43 -7 -26 -62 -94 -77\n -94 -13 0 -11 17 4 32 21 19 4 88 -28 115 -14 13 -22 23 -16 23 5 0 21 -14 35\n -31 14 -17 26 -25 26 -19 0 21 -60 72 -79 67 -16 -4 -17 -1 -8 34 6 24 14 36\n 21 32 6 -3 1 5 -11 18 -12 13 -22 29 -23 34 -1 6 -6 17 -12 25 -6 10 -7 -39\n -4 -142 l6 -158 -26 10 c-33 13 -44 12 -21 -1 17 -10 24 -44 10 -52 -5 -3 -39\n -8 -76 -12 -68 -7 -69 -7 -65 17 4 28 64 60 117 62 l36 1 0 157 c0 87 2 158 5\n 158 3 0 18 -20 35 -45z m15 -159 c0 -2 -7 -7 -16 -10 -8 -3 -12 -2 -9 4 6 10\n 25 14 25 6z m50 -92 c0 -13 -4 -26 -10 -29 -14 -9 -13 -48 2 -63 9 -9 6 -12\n -15 -12 -22 0 -27 5 -27 24 0 14 -4 28 -10 31 -15 9 -13 102 3 108 18 7 57\n -33 57 -59z m-139 -135 c-32 -26 -121 -25 -121 2 0 6 8 5 19 -1 26 -14 64 -13\n 55 1 -4 8 1 9 16 4 13 -4 20 -3 17 2 -3 5 4 10 16 10 22 2 22 2 -2 -18z'), _path2), ' ', (_path3 = document.createElementNS(_svgNamespace, 'path'), _path3.setAttribute('d', 'M330 345 c19 -19 36 -35 39 -35 3 0 -10 16 -29 35 -19 19 -36 35 -39\n 35 -3 0 10 -16 29 -35z'), _path3), ' ', (_path4 = document.createElementNS(_svgNamespace, 'path'), _path4.setAttribute('d', 'M349 123 c-13 -16 -12 -17 4 -4 16 13 21 21 13 21 -2 0 -10 -8 -17\n -17z'), _path4), ' ', (_path5 = document.createElementNS(_svgNamespace, 'path'), _path5.setAttribute('d', 'M243 13 c15 -2 39 -2 55 0 15 2 2 4 -28 4 -30 0 -43 -2 -27 -4z'), _path5), ' ']), _g), ' ']), _uppyIcon2;
},
page_white_picture: function page_white_picture() {
var _path6, _path7, _path8, _path9, _path10, _path11, _path12, _path13, _path14, _g2, _uppyIcon3;
return _uppyIcon3 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon3.setAttribute('width', '16.000000pt'), _uppyIcon3.setAttribute('height', '16.000000pt'), _uppyIcon3.setAttribute('viewBox', '0 0 48.000000 36.000000'), _uppyIcon3.setAttribute('preserveAspectRatio', 'xMidYMid meet'), _uppyIcon3.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon3, [' ', (_g2 = document.createElementNS(_svgNamespace, 'g'), _g2.setAttribute('transform', 'translate(0.000000,36.000000) scale(0.100000,-0.100000)'), _g2.setAttribute('fill', '#565555'), _g2.setAttribute('stroke', 'none'), _appendChild(_g2, [' ', (_path6 = document.createElementNS(_svgNamespace, 'path'), _path6.setAttribute('d', 'M0 180 l0 -180 240 0 240 0 0 180 0 180 -240 0 -240 0 0 -180z m470\n 0 l0 -170 -230 0 -230 0 0 170 0 170 230 0 230 0 0 -170z'), _path6), ' ', (_path7 = document.createElementNS(_svgNamespace, 'path'), _path7.setAttribute('d', 'M40 185 l0 -135 200 0 200 0 0 135 0 135 -200 0 -200 0 0 -135z m390\n 59 l0 -65 -29 20 c-37 27 -45 26 -65 -4 -9 -14 -22 -25 -28 -25 -7 0 -24 -12\n -39 -26 -26 -25 -28 -25 -53 -9 -17 11 -26 13 -26 6 0 -7 -4 -9 -10 -6 -5 3\n -22 -2 -37 -12 l-28 -18 20 27 c11 15 26 25 33 23 6 -2 12 -1 12 4 0 10 -37\n 21 -65 20 -14 -1 -12 -3 7 -8 l28 -6 -50 -55 -49 -55 0 126 1 126 189 1 189 2\n 0 -66z m-16 -73 c11 -12 14 -21 8 -21 -6 0 -13 4 -17 10 -3 5 -12 7 -19 4 -8\n -3 -16 2 -19 13 -3 11 -4 7 -4 -9 1 -19 6 -25 18 -23 19 4 46 -21 35 -32 -4\n -4 -11 -1 -16 7 -6 8 -10 10 -10 4 0 -6 7 -17 15 -24 24 -20 11 -24 -76 -27\n -69 -1 -83 1 -97 18 -9 10 -20 19 -25 19 -5 0 -4 -6 2 -14 14 -17 -5 -26 -55\n -26 -36 0 -46 16 -17 27 10 4 22 13 27 22 8 13 10 12 17 -4 7 -17 8 -18 8 -2\n 1 23 11 22 55 -8 33 -22 35 -23 26 -5 -9 16 -8 20 5 20 8 0 15 5 15 11 0 5 -4\n 7 -10 4 -5 -3 -10 -4 -10 -1 0 4 59 36 67 36 2 0 1 -10 -2 -21 -5 -15 -4 -19\n 5 -14 6 4 9 17 6 28 -12 49 27 53 68 8z'), _path7), ' ', (_path8 = document.createElementNS(_svgNamespace, 'path'), _path8.setAttribute('d', 'M100 296 c0 -2 7 -7 16 -10 8 -3 12 -2 9 4 -6 10 -25 14 -25 6z'), _path8), ' ', (_path9 = document.createElementNS(_svgNamespace, 'path'), _path9.setAttribute('d', 'M243 293 c9 -2 23 -2 30 0 6 3 -1 5 -18 5 -16 0 -22 -2 -12 -5z'), _path9), ' ', (_path10 = document.createElementNS(_svgNamespace, 'path'), _path10.setAttribute('d', 'M65 280 c-3 -5 -2 -10 4 -10 5 0 13 5 16 10 3 6 2 10 -4 10 -5 0 -13\n -4 -16 -10z'), _path10), ' ', (_path11 = document.createElementNS(_svgNamespace, 'path'), _path11.setAttribute('d', 'M155 270 c-3 -6 1 -7 9 -4 18 7 21 14 7 14 -6 0 -13 -4 -16 -10z'), _path11), ' ', (_path12 = document.createElementNS(_svgNamespace, 'path'), _path12.setAttribute('d', 'M233 252 c-13 -2 -23 -8 -23 -13 0 -7 -12 -8 -30 -4 -22 5 -30 3 -30\n -7 0 -10 -2 -10 -9 1 -5 8 -19 12 -35 9 -14 -3 -27 -1 -30 4 -2 5 -4 4 -3 -3\n 2 -6 6 -10 10 -10 3 0 20 -4 37 -9 18 -5 32 -5 36 1 3 6 13 8 21 5 13 -5 113\n 21 113 30 0 3 -19 2 -57 -4z'), _path12), ' ', (_path13 = document.createElementNS(_svgNamespace, 'path'), _path13.setAttribute('d', 'M275 220 c-13 -6 -15 -9 -5 -9 8 0 22 4 30 9 18 12 2 12 -25 0z'), _path13), ' ', (_path14 = document.createElementNS(_svgNamespace, 'path'), _path14.setAttribute('d', 'M132 23 c59 -2 158 -2 220 0 62 1 14 3 -107 3 -121 0 -172 -2 -113\n -3z'), _path14), ' ']), _g2), ' ']), _uppyIcon3;
},
word: function word() {
var _path15, _path16, _path17, _path18, _path19, _path20, _path21, _g3, _uppyIcon4;
return _uppyIcon4 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon4.setAttribute('width', '16.000000pt'), _uppyIcon4.setAttribute('height', '16.000000pt'), _uppyIcon4.setAttribute('viewBox', '0 0 48.000000 48.000000'), _uppyIcon4.setAttribute('preserveAspectRatio', 'xMidYMid meet'), _uppyIcon4.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon4, [' ', (_g3 = document.createElementNS(_svgNamespace, 'g'), _g3.setAttribute('transform', 'translate(0.000000,48.000000) scale(0.100000,-0.100000)'), _g3.setAttribute('fill', '#423d3d'), _g3.setAttribute('stroke', 'none'), _appendChild(_g3, [' ', (_path15 = document.createElementNS(_svgNamespace, 'path'), _path15.setAttribute('d', 'M0 466 c0 -15 87 -26 213 -26 l77 0 0 -140 0 -140 -77 0 c-105 0\n -213 -11 -213 -21 0 -5 15 -9 34 -9 25 0 33 -4 33 -17 0 -74 4 -113 13 -113 6\n 0 10 32 10 75 l0 75 105 0 105 0 0 150 0 150 -105 0 c-87 0 -105 3 -105 15 0\n 11 -12 15 -45 15 -31 0 -45 -4 -45 -14z'), _path15), ' ', (_path16 = document.createElementNS(_svgNamespace, 'path'), _path16.setAttribute('d', 'M123 468 c-2 -5 50 -8 116 -8 l121 0 0 -50 c0 -46 -2 -50 -23 -50\n -14 0 -24 -6 -24 -15 0 -8 4 -15 9 -15 4 0 8 -20 8 -45 0 -25 -4 -45 -8 -45\n -5 0 -9 -7 -9 -15 0 -9 10 -15 24 -15 22 0 23 3 23 75 l0 75 50 0 50 0 0 -170\n 0 -170 -175 0 -175 0 -2 63 c-2 59 -2 60 -5 13 -3 -27 -2 -60 2 -73 l5 -23\n 183 2 182 3 2 216 c3 275 19 254 -194 254 -85 0 -157 -3 -160 -7z m337 -85 c0\n -2 -18 -3 -39 -3 -39 0 -39 0 -43 45 l-3 44 42 -41 c24 -23 43 -43 43 -45z\n m-19 50 c19 -22 23 -29 9 -18 -36 30 -50 43 -50 49 0 11 6 6 41 -31z'), _path16), ' ', (_path17 = document.createElementNS(_svgNamespace, 'path'), _path17.setAttribute('d', 'M4 300 c0 -74 1 -105 3 -67 2 37 2 97 0 135 -2 37 -3 6 -3 -68z'), _path17), ' ', (_path18 = document.createElementNS(_svgNamespace, 'path'), _path18.setAttribute('d', 'M20 300 l0 -131 128 3 127 3 3 128 3 127 -131 0 -130 0 0 -130z m250\n 100 c0 -16 -7 -20 -33 -20 -31 0 -34 -2 -34 -31 0 -28 2 -30 13 -14 8 10 11\n 22 8 26 -3 5 1 9 9 9 11 0 9 -12 -12 -50 -14 -27 -32 -50 -39 -50 -15 0 -31\n 38 -26 63 2 10 -1 15 -8 11 -6 -4 -9 -1 -6 6 2 8 10 16 16 18 8 2 12 -10 12\n -38 0 -38 2 -41 16 -29 9 7 12 15 7 16 -5 2 -7 17 -5 33 4 26 1 30 -20 30 -17\n 0 -29 -9 -39 -27 -20 -41 -22 -50 -6 -30 14 17 15 16 20 -5 4 -13 2 -40 -2\n -60 -9 -37 -8 -38 20 -38 26 0 33 8 64 70 19 39 37 70 40 70 3 0 5 -40 5 -90\n l0 -90 -120 0 -120 0 0 120 0 120 120 0 c113 0 120 -1 120 -20z'), _path18), ' ', (_path19 = document.createElementNS(_svgNamespace, 'path'), _path19.setAttribute('d', 'M40 371 c0 -6 5 -13 10 -16 6 -3 10 -35 10 -71 0 -57 2 -64 20 -64\n 13 0 27 14 40 40 25 49 25 63 0 30 -19 -25 -39 -23 -24 2 5 7 7 23 6 35 -2 11\n 2 24 7 28 23 13 9 25 -29 25 -22 0 -40 -4 -40 -9z m53 -9 c-6 -4 -13 -28 -15\n -52 l-3 -45 -5 53 c-5 47 -3 52 15 52 13 0 16 -3 8 -8z'), _path19), ' ', (_path20 = document.createElementNS(_svgNamespace, 'path'), _path20.setAttribute('d', 'M313 165 c0 -9 10 -15 24 -15 14 0 23 6 23 15 0 9 -9 15 -23 15 -14\n 0 -24 -6 -24 -15z'), _path20), ' ', (_path21 = document.createElementNS(_svgNamespace, 'path'), _path21.setAttribute('d', 'M180 105 c0 -12 17 -15 90 -15 73 0 90 3 90 15 0 12 -17 15 -90 15\n -73 0 -90 -3 -90 -15z'), _path21), ' ']), _g3), ' ']), _uppyIcon4;
},
powerpoint: function powerpoint() {
var _path22, _path23, _path24, _path25, _path26, _path27, _path28, _path29, _path30, _path31, _path32, _path33, _path34, _path35, _path36, _path37, _path38, _path39, _g4, _uppyIcon5;
return _uppyIcon5 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon5.setAttribute('width', '16.000000pt'), _uppyIcon5.setAttribute('height', '16.000000pt'), _uppyIcon5.setAttribute('viewBox', '0 0 16.000000 16.000000'), _uppyIcon5.setAttribute('preserveAspectRatio', 'xMidYMid meet'), _uppyIcon5.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon5, [' ', (_g4 = document.createElementNS(_svgNamespace, 'g'), _g4.setAttribute('transform', 'translate(0.000000,144.000000) scale(0.100000,-0.100000)'), _g4.setAttribute('fill', '#494747'), _g4.setAttribute('stroke', 'none'), _appendChild(_g4, [' ', (_path22 = document.createElementNS(_svgNamespace, 'path'), _path22.setAttribute('d', 'M0 1390 l0 -50 93 0 c50 0 109 -3 130 -6 l37 -7 0 57 0 56 -130 0\n -130 0 0 -50z'), _path22), ' ', (_path23 = document.createElementNS(_svgNamespace, 'path'), _path23.setAttribute('d', 'M870 1425 c0 -8 -12 -18 -27 -22 l-28 -6 30 -9 c17 -5 75 -10 130\n -12 86 -2 100 -5 99 -19 0 -10 -1 -80 -2 -157 l-2 -140 -65 0 c-60 0 -80 -9\n -55 -25 8 -5 7 -11 -1 -21 -17 -20 2 -25 112 -27 l94 -2 0 40 0 40 100 5 c55\n 3 104 3 108 -1 8 -6 11 -1008 4 -1016 -2 -2 -236 -4 -520 -6 -283 -1 -519 -5\n -523 -9 -4 -4 -1 -14 6 -23 11 -13 82 -15 561 -15 l549 0 0 570 c0 543 -1 570\n -18 570 -10 0 -56 39 -103 86 -46 47 -93 90 -104 95 -11 6 22 -31 73 -82 50\n -50 92 -95 92 -99 0 -14 -23 -16 -136 -12 l-111 4 -6 124 c-6 119 -7 126 -32\n 145 -14 12 -23 25 -20 30 4 5 -38 9 -99 9 -87 0 -106 -3 -106 -15z'), _path23), ' ', (_path24 = document.createElementNS(_svgNamespace, 'path'), _path24.setAttribute('d', 'M1190 1429 c0 -14 225 -239 239 -239 7 0 11 30 11 85 0 77 -2 85 -19\n 85 -21 0 -61 44 -61 66 0 11 -20 14 -85 14 -55 0 -85 -4 -85 -11z'), _path24), ' ', (_path25 = document.createElementNS(_svgNamespace, 'path'), _path25.setAttribute('d', 'M281 1331 c-24 -16 7 -23 127 -31 100 -6 107 -7 47 -9 -38 -1 -142\n -8 -229 -14 l-160 -12 -7 -28 c-10 -37 -16 -683 -6 -693 4 -4 10 -4 15 0 4 4\n 8 166 9 359 l2 352 358 -3 358 -2 5 -353 c3 -193 2 -356 -2 -361 -3 -4 -136\n -8 -295 -7 -290 2 -423 -4 -423 -20 0 -5 33 -9 73 -9 39 0 90 -3 111 -7 l39\n -6 -45 -18 c-26 -10 -90 -20 -151 -25 l-107 -7 0 -38 c0 -35 3 -39 24 -39 36\n 0 126 -48 128 -68 1 -9 2 -40 3 -69 2 -29 6 -91 10 -138 l7 -85 44 0 44 0 0\n 219 0 220 311 1 c172 0 314 2 318 4 5 4 6 301 2 759 l-1 137 -297 0 c-164 0\n -304 -4 -312 -9z'), _path25), ' ', (_path26 = document.createElementNS(_svgNamespace, 'path'), _path26.setAttribute('d', 'M2 880 c-1 -276 2 -378 10 -360 12 30 11 657 -2 710 -5 21 -8 -121\n -8 -350z'), _path26), ' ', (_path27 = document.createElementNS(_svgNamespace, 'path'), _path27.setAttribute('d', 'M145 1178 c-3 -8 -4 -141 -3 -298 l3 -285 295 0 295 0 0 295 0 295\n -293 3 c-230 2 -294 0 -297 -10z m553 -27 c11 -6 13 -60 11 -260 -1 -139 -6\n -254 -9 -256 -4 -3 -124 -6 -266 -7 l-259 -3 -3 255 c-1 140 0 260 3 267 3 10\n 62 13 257 13 139 0 259 -4 266 -9z'), _path27), ' ', (_path28 = document.createElementNS(_svgNamespace, 'path'), _path28.setAttribute('d', 'M445 1090 l-210 -5 -3 -37 -3 -38 225 0 226 0 0 34 c0 18 -6 37 -12\n 42 -7 5 -107 7 -223 4z'), _path28), ' ', (_path29 = document.createElementNS(_svgNamespace, 'path'), _path29.setAttribute('d', 'M295 940 c-3 -6 1 -12 9 -15 9 -3 23 -7 31 -10 10 -3 15 -18 15 -49\n 0 -25 3 -47 8 -49 15 -9 47 11 52 33 9 38 28 34 41 -8 10 -35 9 -43 -7 -66\n -23 -31 -51 -34 -56 -4 -4 31 -26 34 -38 4 -5 -14 -12 -26 -16 -26 -4 0 -22\n 16 -41 36 -33 35 -34 40 -28 86 7 48 6 50 -16 46 -18 -2 -23 -9 -21 -23 2 -11\n 3 -49 3 -85 0 -72 6 -83 60 -111 57 -29 95 -25 144 15 37 31 46 34 83 29 40\n -5 42 -5 42 21 0 24 -3 27 -27 24 -24 -3 -28 1 -31 25 -3 24 0 28 20 25 13 -2\n 23 2 23 7 0 6 -9 9 -20 8 -13 -2 -28 9 -44 32 -13 19 -31 35 -41 35 -10 0 -23\n 7 -30 15 -14 17 -105 21 -115 5z'), _path29), ' ', (_path30 = document.createElementNS(_svgNamespace, 'path'), _path30.setAttribute('d', 'M522 919 c-28 -11 -20 -29 14 -29 14 0 24 6 24 14 0 21 -11 25 -38\n 15z'), _path30), ' ', (_path31 = document.createElementNS(_svgNamespace, 'path'), _path31.setAttribute('d', 'M623 922 c-53 -5 -43 -32 12 -32 32 0 45 4 45 14 0 17 -16 22 -57 18z'), _path31), ' ', (_path32 = document.createElementNS(_svgNamespace, 'path'), _path32.setAttribute('d', 'M597 854 c-13 -14 6 -24 44 -24 28 0 39 4 39 15 0 11 -11 15 -38 15\n -21 0 -42 -3 -45 -6z'), _path32), ' ', (_path33 = document.createElementNS(_svgNamespace, 'path'), _path33.setAttribute('d', 'M597 794 c-4 -4 -7 -18 -7 -31 0 -21 4 -23 46 -23 44 0 45 1 42 28\n -3 23 -8 27 -38 30 -20 2 -39 0 -43 -4z'), _path33), ' ', (_path34 = document.createElementNS(_svgNamespace, 'path'), _path34.setAttribute('d', 'M989 883 c-34 -4 -37 -6 -37 -37 0 -32 2 -34 45 -40 25 -3 72 -6 104\n -6 l59 0 0 45 0 45 -67 -2 c-38 -1 -84 -3 -104 -5z'), _path34), ' ', (_path35 = document.createElementNS(_svgNamespace, 'path'), _path35.setAttribute('d', 'M993 703 c-42 -4 -54 -15 -33 -28 8 -5 8 -11 0 -20 -16 -20 -3 -24\n 104 -31 l96 -7 0 47 0 46 -62 -2 c-35 -1 -82 -3 -105 -5z'), _path35), ' ', (_path36 = document.createElementNS(_svgNamespace, 'path'), _path36.setAttribute('d', 'M1005 523 c-50 -6 -59 -12 -46 -26 8 -10 7 -17 -1 -25 -6 -6 -9 -14\n -6 -17 3 -3 51 -8 107 -12 l101 -6 0 46 0 47 -62 -1 c-35 -1 -76 -4 -93 -6z'), _path36), ' ', (_path37 = document.createElementNS(_svgNamespace, 'path'), _path37.setAttribute('d', 'M537 344 c-4 -4 -7 -25 -7 -46 l0 -38 46 0 45 0 -3 43 c-3 40 -4 42\n -38 45 -20 2 -39 0 -43 -4z'), _path37), ' ', (_path38 = document.createElementNS(_svgNamespace, 'path'), _path38.setAttribute('d', 'M714 341 c-2 -2 -4 -22 -4 -43 l0 -38 225 0 225 0 0 45 0 46 -221 -3\n c-121 -2 -222 -5 -225 -7z'), _path38), ' ', (_path39 = document.createElementNS(_svgNamespace, 'path'), _path39.setAttribute('d', 'M304 205 c0 -66 1 -92 3 -57 2 34 2 88 0 120 -2 31 -3 3 -3 -63z'), _path39), ' ']), _g4), ' ']), _uppyIcon5;
},
page_white: function page_white() {
var _path40, _path41, _path42, _path43, _path44, _g5, _uppyIcon6;
return _uppyIcon6 = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon6.setAttribute('width', '16.000000pt'), _uppyIcon6.setAttribute('height', '16.000000pt'), _uppyIcon6.setAttribute('viewBox', '0 0 48.000000 48.000000'), _uppyIcon6.setAttribute('preserveAspectRatio', 'xMidYMid meet'), _uppyIcon6.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon6, [' ', (_g5 = document.createElementNS(_svgNamespace, 'g'), _g5.setAttribute('transform', 'translate(0.000000,48.000000) scale(0.100000,-0.100000)'), _g5.setAttribute('fill', '#000000'), _g5.setAttribute('stroke', 'none'), _appendChild(_g5, [' ', (_path40 = document.createElementNS(_svgNamespace, 'path'), _path40.setAttribute('d', 'M20 240 c1 -202 3 -240 16 -240 12 0 14 38 14 240 0 208 -2 240 -15\n 240 -13 0 -15 -31 -15 -240z'), _path40), ' ', (_path41 = document.createElementNS(_svgNamespace, 'path'), _path41.setAttribute('d', 'M75 471 c-4 -8 32 -11 119 -11 l126 0 0 -50 0 -50 50 0 c28 0 50 5\n 50 10 0 6 -18 10 -40 10 l-40 0 0 42 0 42 43 -39 42 -40 -43 45 -42 45 -129 3\n c-85 2 -131 0 -136 -7z'), _path41), ' ', (_path42 = document.createElementNS(_svgNamespace, 'path'), _path42.setAttribute('d', 'M398 437 l42 -43 0 -197 c0 -168 2 -197 15 -197 13 0 15 29 15 198\n l0 198 -36 42 c-21 25 -44 42 -57 42 -18 0 -16 -6 21 -43z'), _path42), ' ', (_path43 = document.createElementNS(_svgNamespace, 'path'), _path43.setAttribute('d', 'M92 353 l2 -88 3 78 4 77 89 0 89 0 8 -42 c8 -43 9 -43 55 -46 44 -3\n 47 -5 51 -35 4 -31 4 -31 5 6 l2 37 -50 0 -50 0 0 50 0 50 -105 0 -105 0 2\n -87z'), _path43), ' ', (_path44 = document.createElementNS(_svgNamespace, 'path'), _path44.setAttribute('d', 'M75 10 c8 -13 332 -13 340 0 4 7 -55 10 -170 10 -115 0 -174 -3 -170\n -10z'), _path44), ' ']), _g5), ' ']), _uppyIcon6;
}
};
},{"yo-yoify/lib/appendChild":131}],32:[function(require,module,exports){
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _svgNamespace = 'http://www.w3.org/2000/svg',
_appendChild = require('yo-yoify/lib/appendChild');
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var Plugin = require('../Plugin');
var Provider = require('../../uppy-base/src/plugins/Provider');
var View = require('../../generic-provider-views/index');
var icons = require('./icons');
module.exports = function (_Plugin) {
_inherits(Dropbox, _Plugin);
function Dropbox(core, opts) {
_classCallCheck(this, Dropbox);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, core, opts));
_this.type = 'acquirer';
_this.id = 'Dropbox';
_this.title = 'Dropbox';
_this.stateId = 'dropbox';
_this.icon = function () {
var _path, _path2, _path3, _uppyIcon;
return _uppyIcon = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon.setAttribute('width', '128'), _uppyIcon.setAttribute('height', '118'), _uppyIcon.setAttribute('viewBox', '0 0 128 118'), _uppyIcon.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon, [' ', (_path = document.createElementNS(_svgNamespace, 'path'), _path.setAttribute('d', 'M38.145.777L1.108 24.96l25.608 20.507 37.344-23.06z'), _path), ' ', (_path2 = document.createElementNS(_svgNamespace, 'path'), _path2.setAttribute('d', 'M1.108 65.975l37.037 24.183L64.06 68.525l-37.343-23.06zM64.06 68.525l25.917 21.633 37.036-24.183-25.61-20.51z'), _path2), ' ', (_path3 = document.createElementNS(_svgNamespace, 'path'), _path3.setAttribute('d', 'M127.014 24.96L89.977.776 64.06 22.407l37.345 23.06zM64.136 73.18l-25.99 21.567-11.122-7.262v8.142l37.112 22.256 37.114-22.256v-8.142l-11.12 7.262z'), _path3), ' ']), _uppyIcon;
};
// writing out the key explicitly for readability the key used to store
// the provider instance must be equal to this.id.
_this.Dropbox = new Provider({
host: _this.opts.host,
provider: 'dropbox'
});
_this.files = [];
_this.onAuth = _this.onAuth.bind(_this);
// Visual
_this.render = _this.render.bind(_this);
// set default options
var defaultOptions = {};
// merge default options with the ones set by user
_this.opts = _extends({}, defaultOptions, opts);
return _this;
}
Dropbox.prototype.install = function install() {
this.view = new View(this);
// Set default state
this.core.setState({
// writing out the key explicitly for readability the key used to store
// the plugin state must be equal to this.stateId.
dropbox: {
authenticated: false,
files: [],
folders: [],
directories: [],
activeRow: -1,
filterInput: ''
}
});
var target = this.opts.target;
var plugin = this;
this.target = this.mount(target, plugin);
this[this.id].auth().then(this.onAuth).catch(this.view.handleError);
return;
};
Dropbox.prototype.uninstall = function uninstall() {
this.unmount();
};
Dropbox.prototype.onAuth = function onAuth(authenticated) {
this.view.updateState({ authenticated: authenticated });
if (authenticated) {
this.view.getFolder();
}
};
Dropbox.prototype.isFolder = function isFolder(item) {
return item.is_dir;
};
Dropbox.prototype.getItemData = function getItemData(item) {
return _extends({}, item, { size: item.bytes });
};
Dropbox.prototype.getItemIcon = function getItemIcon(item) {
var icon = icons[item.icon];
if (!icon) {
if (item.icon.startsWith('folder')) {
icon = icons['folder'];
} else {
icon = icons['page_white'];
}
}
return icon();
};
Dropbox.prototype.getItemSubList = function getItemSubList(item) {
return item.contents;
};
Dropbox.prototype.getItemName = function getItemName(item) {
return item.path.length > 1 ? item.path.substring(1) : item.path;
};
Dropbox.prototype.getMimeType = function getMimeType(item) {
return item.mime_type;
};
Dropbox.prototype.getItemId = function getItemId(item) {
return item.rev;
};
Dropbox.prototype.getItemRequestPath = function getItemRequestPath(item) {
return encodeURIComponent(this.getItemName(item));
};
Dropbox.prototype.getItemModifiedDate = function getItemModifiedDate(item) {
return item.modified;
};
Dropbox.prototype.render = function render(state) {
return this.view.render(state);
};
return Dropbox;
}(Plugin);
},{"../../generic-provider-views/index":17,"../../uppy-base/src/plugins/Provider":54,"../Plugin":39,"./icons":31,"yo-yoify/lib/appendChild":131}],33:[function(require,module,exports){
'use strict';
var _onload = require('on-load'),
_appendChild = require('yo-yoify/lib/appendChild');
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var Plugin = require('./Plugin');
// const yo = require('yo-yo')
/**
* Dummy
* A test plugin, does nothing useful
*/
module.exports = function (_Plugin) {
_inherits(Dummy, _Plugin);
function Dummy(core, opts) {
var _h;
_classCallCheck(this, Dummy);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, core, opts));
_this.type = 'acquirer';
_this.id = 'Dummy';
_this.title = 'Mr. Plugin';
// set default options
var defaultOptions = {};
// merge default options with the ones set by user
_this.opts = _extends({}, defaultOptions, opts);
_this.strange = (_h = document.createElement('h1'), _h.textContent = 'this is strange 1', _h);
_this.render = _this.render.bind(_this);
_this.install = _this.install.bind(_this);
return _this;
}
Dummy.prototype.addFakeFileJustToTest = function addFakeFileJustToTest() {
var blob = new Blob(['data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTIwIDEyMCI+CiAgPGNpcmNsZSBjeD0iNjAiIGN5PSI2MCIgcj0iNTAiLz4KPC9zdmc+Cg=='], { type: 'image/svg+xml' });
var file = {
source: 'acceptance-test',
name: 'test-file',
type: 'image/svg+xml',
data: blob
};
this.props.log('Adding fake file blob');
this.props.addFile(file);
};
Dummy.prototype.render = function render(state) {
var _h2, _uppyDummyFirstInput, _wowThisWorks;
var bla = (_h2 = document.createElement('h2'), _h2.textContent = 'this is strange 2', _h2);
return _wowThisWorks = document.createElement('div'), _wowThisWorks.setAttribute('class', 'wow-this-works'), _appendChild(_wowThisWorks, [' ', (_uppyDummyFirstInput = document.createElement('input'), _onload(_uppyDummyFirstInput, function (el) {
el.focus();
}, null, 2), _uppyDummyFirstInput.setAttribute('type', 'text'), _uppyDummyFirstInput.setAttribute('value', 'hello'), _uppyDummyFirstInput.setAttribute('class', 'UppyDummy-firstInput'), _uppyDummyFirstInput), ' ', this.strange, ' ', bla, ' ', state.dummy.text, ' ']), _wowThisWorks;
};
Dummy.prototype.install = function install() {
var _this2 = this;
this.core.setState({ dummy: { text: '123' } });
var target = this.opts.target;
var plugin = this;
this.target = this.mount(target, plugin);
setTimeout(function () {
_this2.core.setState({ dummy: { text: '!!!' } });
}, 2000);
};
return Dummy;
}(Plugin);
// module.exports = function (core, opts) {
// if (!(this instanceof Dummy)) {
// return new Dummy(core, opts)
// }
// }
},{"./Plugin":39,"on-load":63,"yo-yoify/lib/appendChild":131}],34:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var Plugin = require('./Plugin');
var Utils = require('../core/Utils');
var Translator = require('../core/Translator');
module.exports = function (_Plugin) {
_inherits(FileInput, _Plugin);
function FileInput(core, opts) {
_classCallCheck(this, FileInput);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, core, opts));
_this.id = 'FileInput';
_this.title = 'FileInput';
_this.type = 'acquirer';
var defaultLocale = {
strings: {
selectToUpload: 'Select to upload'
}
};
// Default options
var defaultOptions = {
target: '.UppyForm',
replaceTargetContent: true,
multipleFiles: true,
pretty: true,
locale: defaultLocale
};
// Merge default options with the ones set by user
_this.opts = _extends({}, defaultOptions, opts);
_this.locale = _extends({}, defaultLocale, _this.opts.locale);
_this.locale.strings = _extends({}, defaultLocale.strings, _this.opts.locale.strings);
// i18n
_this.translator = new Translator({ locale: _this.locale });
_this.i18n = _this.translator.translate.bind(_this.translator);
_this.render = _this.render.bind(_this);
return _this;
}
FileInput.prototype.handleInputChange = function handleInputChange(ev) {
var _this2 = this;
this.core.log('All right, something selected through input...');
var files = Utils.toArray(ev.target.files);
files.forEach(function (file) {
_this2.core.emitter.emit('core:file-add', {
source: _this2.id,
name: file.name,
type: file.type,
data: file
});
});
};
FileInput.prototype.render = function render(state) {
var _uppyFileInputInput, _uppy, _uppyFileInputBtn;
var hiddenInputStyle = 'width: 0.1px; height: 0.1px; opacity: 0; overflow: hidden; position: absolute; z-index: -1;';
var input = (_uppyFileInputInput = document.createElement('input'), _uppyFileInputInput.setAttribute('style', '' + String(this.opts.pretty ? hiddenInputStyle : '') + ''), _uppyFileInputInput.setAttribute('type', 'file'), _uppyFileInputInput.setAttribute('name', 'files[]'), _uppyFileInputInput.onchange = this.handleInputChange.bind(this), (this.opts.multipleFiles ? 'true' : 'false') && _uppyFileInputInput.setAttribute('multiple', 'multiple'), _uppyFileInputInput.setAttribute('value', ''), _uppyFileInputInput.setAttribute('class', 'uppy-FileInput-input'), _uppyFileInputInput);
return _uppy = document.createElement('form'), _uppy.setAttribute('class', 'Uppy uppy-FileInput-form'), _appendChild(_uppy, [' ', input, ' ', this.opts.pretty ? (_uppyFileInputBtn = document.createElement('button'), _uppyFileInputBtn.setAttribute('type', 'button'), _uppyFileInputBtn.onclick = function () {
return input.click();
}, _uppyFileInputBtn.setAttribute('class', 'uppy-FileInput-btn'), _appendChild(_uppyFileInputBtn, [' ', this.i18n('selectToUpload'), ' ']), _uppyFileInputBtn) : null, ' ']), _uppy;
};
FileInput.prototype.install = function install() {
var target = this.opts.target;
var plugin = this;
this.target = this.mount(target, plugin);
};
FileInput.prototype.uninstall = function uninstall() {
this.unmount();
};
return FileInput;
}(Plugin);
},{"../core/Translator":4,"../core/Utils":6,"./Plugin":39,"yo-yoify/lib/appendChild":131}],35:[function(require,module,exports){
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _svgNamespace = 'http://www.w3.org/2000/svg',
_appendChild = require('yo-yoify/lib/appendChild');
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var Plugin = require('../Plugin');
var Provider = require('../../uppy-base/src/plugins/Provider');
var View = require('../../generic-provider-views/index');
module.exports = function (_Plugin) {
_inherits(Google, _Plugin);
function Google(core, opts) {
_classCallCheck(this, Google);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, core, opts));
_this.type = 'acquirer';
_this.id = 'GoogleDrive';
_this.title = 'Google Drive';
_this.stateId = 'googleDrive';
_this.icon = function () {
var _path, _uppyIcon;
return _uppyIcon = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon.setAttribute('width', '28'), _uppyIcon.setAttribute('height', '28'), _uppyIcon.setAttribute('viewBox', '0 0 16 16'), _uppyIcon.setAttribute('class', 'UppyIcon UppyModalTab-icon'), _appendChild(_uppyIcon, [' ', (_path = document.createElementNS(_svgNamespace, 'path'), _path.setAttribute('d', 'M2.955 14.93l2.667-4.62H16l-2.667 4.62H2.955zm2.378-4.62l-2.666 4.62L0 10.31l5.19-8.99 2.666 4.62-2.523 4.37zm10.523-.25h-5.333l-5.19-8.99h5.334l5.19 8.99z'), _path), ' ']), _uppyIcon;
};
// writing out the key explicitly for readability the key used to store
// the provider instance must be equal to this.id.
_this.GoogleDrive = new Provider({
host: _this.opts.host,
provider: 'drive',
authProvider: 'google'
});
_this.files = [];
_this.onAuth = _this.onAuth.bind(_this);
// Visual
_this.render = _this.render.bind(_this);
// set default options
var defaultOptions = {};
// merge default options with the ones set by user
_this.opts = _extends({}, defaultOptions, opts);
return _this;
}
Google.prototype.install = function install() {
this.view = new View(this);
// Set default state for Google Drive
this.core.setState({
// writing out the key explicitly for readability the key used to store
// the plugin state must be equal to this.stateId.
googleDrive: {
authenticated: false,
files: [],
folders: [],
directories: [],
activeRow: -1,
filterInput: ''
}
});
var target = this.opts.target;
var plugin = this;
this.target = this.mount(target, plugin);
// catch error here.
this[this.id].auth().then(this.onAuth).catch(this.view.handleError);
return;
};
Google.prototype.uninstall = function uninstall() {
this.unmount();
};
Google.prototype.onAuth = function onAuth(authenticated) {
this.view.updateState({ authenticated: authenticated });
if (authenticated) {
this.view.getFolder('root');
}
};
Google.prototype.isFolder = function isFolder(item) {
return item.mimeType === 'application/vnd.google-apps.folder';
};
Google.prototype.getItemData = function getItemData(item) {
return _extends({}, item, { size: parseFloat(item.fileSize) });
};
Google.prototype.getItemIcon = function getItemIcon(item) {
var _img;
return _img = document.createElement('img'), _img.setAttribute('src', '' + String(item.iconLink) + ''), _img;
};
Google.prototype.getItemSubList = function getItemSubList(item) {
return item.items;
};
Google.prototype.getItemName = function getItemName(item) {
return item.title ? item.title : '/';
};
Google.prototype.getMimeType = function getMimeType(item) {
return item.mimeType;
};
Google.prototype.getItemId = function getItemId(item) {
return item.id;
};
Google.prototype.getItemRequestPath = function getItemRequestPath(item) {
return this.getItemId(item);
};
Google.prototype.getItemModifiedDate = function getItemModifiedDate(item) {
return item.modifiedByMeDate;
};
Google.prototype.render = function render(state) {
return this.view.render(state);
};
return Google;
}(Plugin);
},{"../../generic-provider-views/index":17,"../../uppy-base/src/plugins/Provider":54,"../Plugin":39,"yo-yoify/lib/appendChild":131}],36:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var Plugin = require('./Plugin');
/**
* Informer
* Shows rad message bubbles
* used like this: `bus.emit('informer', 'hello world', 'info', 5000)`
* or for errors: `bus.emit('informer', 'Error uploading img.jpg', 'error', 5000)`
*
*/
module.exports = function (_Plugin) {
_inherits(Informer, _Plugin);
function Informer(core, opts) {
_classCallCheck(this, Informer);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, core, opts));
_this.type = 'progressindicator';
_this.id = 'Informer';
_this.title = 'Informer';
_this.timeoutID = undefined;
// set default options
var defaultOptions = {
typeColors: {
info: {
text: '#fff',
bg: '#000'
},
warning: {
text: '#fff',
bg: '#F6A623'
},
error: {
text: '#fff',
bg: '#e74c3c'
},
success: {
text: '#fff',
bg: '#7ac824'
}
}
};
// merge default options with the ones set by user
_this.opts = _extends({}, defaultOptions, opts);
_this.render = _this.render.bind(_this);
return _this;
}
Informer.prototype.showInformer = function showInformer(msg, type, duration) {
var _this2 = this;
this.core.setState({
informer: {
isHidden: false,
type: type,
msg: msg
}
});
window.clearTimeout(this.timeoutID);
if (duration === 0) {
this.timeoutID = undefined;
return;
}
// hide the informer after `duration` milliseconds
this.timeoutID = setTimeout(function () {
var newInformer = _extends({}, _this2.core.getState().informer, {
isHidden: true
});
_this2.core.setState({
informer: newInformer
});
}, duration);
};
Informer.prototype.hideInformer = function hideInformer() {
var newInformer = _extends({}, this.core.getState().informer, {
isHidden: true
});
this.core.setState({
informer: newInformer
});
};
Informer.prototype.render = function render(state) {
var _p, _uppy;
var isHidden = state.informer.isHidden;
var msg = state.informer.msg;
var type = state.informer.type || 'info';
var style = 'background-color: ' + this.opts.typeColors[type].bg + '; color: ' + this.opts.typeColors[type].text + ';';
// @TODO add aria-live for screen-readers
return _uppy = document.createElement('div'), _uppy.setAttribute('style', '' + String(style) + ''), _uppy.setAttribute('aria-hidden', '' + String(isHidden) + ''), _uppy.setAttribute('class', 'Uppy UppyTheme--default UppyInformer'), _appendChild(_uppy, [' ', (_p = document.createElement('p'), _appendChild(_p, [msg]), _p), ' ']), _uppy;
};
Informer.prototype.install = function install() {
var _this3 = this;
// Set default state for Google Drive
this.core.setState({
informer: {
isHidden: true,
type: '',
msg: ''
}
});
this.core.on('informer', function (msg, type, duration) {
_this3.showInformer(msg, type, duration);
});
this.core.on('informer:hide', function () {
_this3.hideInformer();
});
var target = this.opts.target;
var plugin = this;
this.target = this.mount(target, plugin);
};
Informer.prototype.uninstall = function uninstall() {
this.unmount();
};
return Informer;
}(Plugin);
},{"./Plugin":39,"yo-yoify/lib/appendChild":131}],37:[function(require,module,exports){
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var Plugin = require('./Plugin');
/**
* Meta Data
* Adds metadata fields to Uppy
*
*/
module.exports = function (_Plugin) {
_inherits(MetaData, _Plugin);
function MetaData(core, opts) {
_classCallCheck(this, MetaData);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, core, opts));
_this.type = 'modifier';
_this.id = 'MetaData';
_this.title = 'Meta Data';
// set default options
var defaultOptions = {};
// merge default options with the ones set by user
_this.opts = _extends({}, defaultOptions, opts);
_this.handleFileAdded = _this.handleFileAdded.bind(_this);
return _this;
}
MetaData.prototype.handleFileAdded = function handleFileAdded(fileID) {
var _this2 = this;
var metaFields = this.opts.fields;
metaFields.forEach(function (item) {
var obj = {};
obj[item.id] = item.value;
_this2.core.updateMeta(obj, fileID);
});
};
MetaData.prototype.addInitialMeta = function addInitialMeta() {
var metaFields = this.opts.fields;
this.core.setState({
metaFields: metaFields
});
this.core.emitter.on('file-added', this.handleFileAdded);
};
MetaData.prototype.install = function install() {
this.addInitialMeta();
};
MetaData.prototype.uninstall = function uninstall() {
this.core.emitter.off('file-added', this.handleFileAdded);
};
return MetaData;
}(Plugin);
},{"./Plugin":39}],38:[function(require,module,exports){
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;
var Plugin = require('./Plugin');
module.exports = function (_Plugin) {
_inherits(Multipart, _Plugin);
function Multipart(core, opts) {
_classCallCheck(this, Multipart);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, core, opts));
_this.type = 'uploader';
_this.id = 'Multipart';
_this.title = 'Multipart';
// Default options
var defaultOptions = {
fieldName: 'files[]',
responseUrlFieldName: 'url',
bundle: true
};
// Merge default options with the ones set by user
_this.opts = _extends({}, defaultOptions, opts);
_this.handleUpload = _this.handleUpload.bind(_this);
return _this;
}
Multipart.prototype.upload = function upload(file, current, total) {
var _this2 = this;
this.core.log('uploading ' + current + ' of ' + total);
return new _Promise(function (resolve, reject) {
// turn file into an array so we can use bundle
// if (!this.opts.bundle) {
// files = [files[current]]
// }
// for (let i in files) {
// formPost.append(this.opts.fieldName, files[i])
// }
var formPost = new FormData();
formPost.append(_this2.opts.fieldName, file.data);
Object.keys(file.meta).forEach(function (item) {
// console.log(file.meta, file.meta[item])
formPost.append(item, file.meta[item]);
});
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', function (ev) {
if (ev.lengthComputable) {
_this2.core.emitter.emit('core:upload-progress', {
uploader: _this2,
id: file.id,
bytesUploaded: ev.loaded,
bytesTotal: ev.total
});
}
});
xhr.addEventListener('load', function (ev) {
if (ev.target.status >= 200 && ev.target.status < 300) {
var resp = JSON.parse(xhr.response);
var uploadURL = resp[_this2.opts.responseUrlFieldName];
_this2.core.emitter.emit('core:upload-success', file.id, resp, uploadURL);
if (uploadURL) {
_this2.core.log('Download ' + file.name + ' from ' + file.uploadURL);
}
return resolve(file);
} else {
_this2.core.emitter.emit('core:upload-error', file.id, xhr);
return reject('Upload error');
}
// var upload = {}
//
// if (this.opts.bundle) {
// upload = {files: files}
// } else {
// upload = {file: files[current]}
// }
});
xhr.addEventListener('error', function (ev) {
_this2.core.emitter.emit('core:upload-error', file.id);
return reject('Upload error');
});
xhr.open('POST', _this2.opts.endpoint, true);
xhr.send(formPost);
_this2.core.emitter.on('core:upload-cancel', function (fileID) {
if (fileID === file.id) {
xhr.abort();
}
});
_this2.core.emitter.on('core:cancel-all', function () {
// const files = this.core.getState().files
// if (!files[file.id]) return
xhr.abort();
});
_this2.core.emitter.emit('core:upload-started', file.id);
});
};
Multipart.prototype.selectForUpload = function selectForUpload(files) {
var _this3 = this;
if (Object.keys(files).length === 0) {
this.core.log('no files to upload!');
return;
}
var filesForUpload = [];
Object.keys(files).forEach(function (file) {
if (!files[file].progress.uploadStarted || files[file].isRemote) {
filesForUpload.push(files[file]);
}
});
filesForUpload.forEach(function (file, i) {
var current = parseInt(i, 10) + 1;
var total = filesForUpload.length;
_this3.upload(file, current, total);
});
// if (this.opts.bundle) {
// uploaders.push(this.upload(files, 0, files.length))
// } else {
// for (let i in files) {
// uploaders.push(this.upload(files, i, files.length))
// }
// }
};
Multipart.prototype.handleUpload = function handleUpload() {
var _this4 = this;
this.core.log('Multipart is uploading...');
var files = this.core.getState().files;
this.selectForUpload(files);
return new _Promise(function (resolve) {
_this4.core.bus.once('core:upload-complete', resolve);
});
};
Multipart.prototype.install = function install() {
this.core.addUploader(this.handleUpload);
};
Multipart.prototype.uninstall = function uninstall() {
this.core.removeUploader(this.handleUpload);
};
return Multipart;
}(Plugin);
},{"./Plugin":39,"es6-promise":60}],39:[function(require,module,exports){
'use strict';
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var yo = require('yo-yo');
// const nanoraf = require('nanoraf')
var _require = require('../core/Utils'),
findDOMElement = _require.findDOMElement;
/**
* Boilerplate that all Plugins share - and should not be used
* directly. It also shows which methods final plugins should implement/override,
* this deciding on structure.
*
* @param {object} main Uppy core object
* @param {object} object with plugin options
* @return {array | string} files or success/fail message
*/
module.exports = function () {
function Plugin(core, opts) {
_classCallCheck(this, Plugin);
this.core = core;
this.opts = opts || {};
this.type = 'none';
// clear everything inside the target selector
this.opts.replaceTargetContent === this.opts.replaceTargetContent || true;
this.update = this.update.bind(this);
this.mount = this.mount.bind(this);
this.focus = this.focus.bind(this);
this.install = this.install.bind(this);
this.uninstall = this.uninstall.bind(this);
// this.frame = null
}
Plugin.prototype.update = function update(state) {
if (typeof this.el === 'undefined') {
return;
}
// const prev = {}
// if (!this.frame) {
// console.log('creating frame')
// this.frame = nanoraf((state, prev) => {
// console.log('updating!', Date.now())
// const newEl = this.render(state)
// this.el = yo.update(this.el, newEl)
// })
// }
// console.log('attempting an update...', Date.now())
// this.frame(state, prev)
// this.core.log('update number: ' + this.core.updateNum++)
var newEl = this.render(state);
yo.update(this.el, newEl);
// optimizes performance?
// requestAnimationFrame(() => {
// const newEl = this.render(state)
// yo.update(this.el, newEl)
// })
};
/**
* Check if supplied `target` is a DOM element or an `object`.
* If it’s an object — target is a plugin, and we search `plugins`
* for a plugin with same name and return its target.
*
* @param {String|Object} target
*
*/
Plugin.prototype.mount = function mount(target, plugin) {
var callerPluginName = plugin.id;
var targetElement = findDOMElement(target);
if (targetElement) {
this.core.log('Installing ' + callerPluginName + ' to a DOM element');
// clear everything inside the target container
if (this.opts.replaceTargetContent) {
targetElement.innerHTML = '';
}
this.el = plugin.render(this.core.state);
targetElement.appendChild(this.el);
return targetElement;
} else {
// TODO: is instantiating the plugin really the way to roll
// just to get the plugin name?
var Target = target;
var targetPluginName = new Target().id;
this.core.log('Installing ' + callerPluginName + ' to ' + targetPluginName);
var targetPlugin = this.core.getPlugin(targetPluginName);
var selectorTarget = targetPlugin.addTarget(plugin);
return selectorTarget;
}
};
Plugin.prototype.unmount = function unmount() {
if (this.el && this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
};
Plugin.prototype.focus = function focus() {
return;
};
Plugin.prototype.install = function install() {
return;
};
Plugin.prototype.uninstall = function uninstall() {
return;
};
return Plugin;
}();
},{"../core/Utils":6,"yo-yo":124}],40:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var Plugin = require('./Plugin');
/**
* Progress bar
*
*/
module.exports = function (_Plugin) {
_inherits(ProgressBar, _Plugin);
function ProgressBar(core, opts) {
_classCallCheck(this, ProgressBar);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, core, opts));
_this.id = 'ProgressBar';
_this.title = 'Progress Bar';
_this.type = 'progressindicator';
// set default options
var defaultOptions = {
replaceTargetContent: false,
fixed: false
};
// merge default options with the ones set by user
_this.opts = _extends({}, defaultOptions, opts);
_this.render = _this.render.bind(_this);
return _this;
}
ProgressBar.prototype.render = function render(state) {
var _uppyProgressBarInner, _uppyProgressBarPercentage, _uppyProgressBar;
var progress = state.totalProgress || 0;
return _uppyProgressBar = document.createElement('div'), _uppyProgressBar.setAttribute('style', '' + String(this.opts.fixed ? 'position: fixed' : 'null') + ''), _uppyProgressBar.setAttribute('class', 'UppyProgressBar'), _appendChild(_uppyProgressBar, [' ', (_uppyProgressBarInner = document.createElement('div'), _uppyProgressBarInner.setAttribute('style', 'width: ' + String(progress) + '%'), _uppyProgressBarInner.setAttribute('class', 'UppyProgressBar-inner'), _uppyProgressBarInner), ' ', (_uppyProgressBarPercentage = document.createElement('div'), _uppyProgressBarPercentage.setAttribute('class', 'UppyProgressBar-percentage'), _appendChild(_uppyProgressBarPercentage, [progress]), _uppyProgressBarPercentage), ' ']), _uppyProgressBar;
};
ProgressBar.prototype.install = function install() {
var target = this.opts.target;
var plugin = this;
this.target = this.mount(target, plugin);
};
ProgressBar.prototype.uninstall = function uninstall() {
this.unmount();
};
return ProgressBar;
}(Plugin);
},{"./Plugin":39,"yo-yoify/lib/appendChild":131}],41:[function(require,module,exports){
'use strict';
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* A Barebones HTTP API client for Transloadit.
*/
module.exports = function () {
function Client() {
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, Client);
this.apiUrl = 'https://api2.transloadit.com';
this.opts = opts;
}
/**
* Create a new assembly.
*
* @param {object} options
*/
Client.prototype.createAssembly = function createAssembly(_ref) {
var templateId = _ref.templateId,
params = _ref.params,
fields = _ref.fields,
signature = _ref.signature,
expectedFiles = _ref.expectedFiles;
var data = new FormData();
data.append('params', typeof params === 'string' ? params : JSON.stringify(params));
if (signature) {
data.append('signature', signature);
}
data.append('fields', JSON.stringify(fields));
data.append('tus_num_expected_upload_files', expectedFiles);
return fetch(this.apiUrl + '/assemblies', {
method: 'post',
body: data
}).then(function (response) {
return response.json();
}).then(function (assembly) {
if (assembly.error) {
var error = new Error(assembly.message);
error.code = assembly.error;
error.status = assembly;
throw error;
}
return assembly;
});
};
/**
* Get the current status for an assembly.
*
* @param {string} url The status endpoint of the assembly.
*/
Client.prototype.getAssemblyStatus = function getAssemblyStatus(url) {
return fetch(url).then(function (response) {
return response.json();
});
};
return Client;
}();
},{}],42:[function(require,module,exports){
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var io = require('socket.io-client');
var Emitter = require('namespace-emitter');
var parseUrl = require('url-parse');
/**
* WebSocket status API client for Transloadit.
*/
module.exports = function () {
function TransloaditSocket(url, assembly) {
_classCallCheck(this, TransloaditSocket);
var emitter = Emitter();
this.on = emitter.on.bind(emitter);
this.off = emitter.off.bind(emitter);
this.emit = emitter.emit.bind(emitter);
var parsed = parseUrl(url);
this.assembly = assembly;
this.socket = io.connect(parsed.origin, {
path: parsed.pathname
});
this.attachDefaultHandlers();
}
TransloaditSocket.prototype.attachDefaultHandlers = function attachDefaultHandlers() {
var _this = this;
this.socket.on('connect', function () {
_this.socket.emit('assembly_connect', {
id: _this.assembly.assembly_id
});
_this.emit('connect');
});
this.socket.on('assembly_finished', function () {
_this.emit('finished');
_this.close();
});
this.socket.on('assembly_upload_finished', function (file) {
_this.emit('upload', file);
});
this.socket.on('assembly_upload_meta_data_extracted', function () {
_this.emit('metadata');
});
this.socket.on('assembly_result_finished', function (stepName, result) {
_this.emit('result', stepName, result);
});
this.socket.on('assembly_error', function (err) {
_this.emit('error', _extends(new Error(err.message), err));
});
};
TransloaditSocket.prototype.close = function close() {
this.socket.disconnect();
};
return TransloaditSocket;
}();
},{"namespace-emitter":62,"socket.io-client":67,"url-parse":120}],43:[function(require,module,exports){
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;
var Plugin = require('../Plugin');
var Client = require('./Client');
var StatusSocket = require('./Socket');
/**
* Upload files to Transloadit using Tus.
*/
module.exports = function (_Plugin) {
_inherits(Transloadit, _Plugin);
function Transloadit(core, opts) {
_classCallCheck(this, Transloadit);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, core, opts));
_this.type = 'uploader';
_this.id = 'Transloadit';
_this.title = 'Transloadit';
var defaultOptions = {
waitForEncoding: false,
waitForMetadata: false,
signature: null,
params: null,
fields: {}
};
_this.opts = _extends({}, defaultOptions, opts);
_this.prepareUpload = _this.prepareUpload.bind(_this);
_this.afterUpload = _this.afterUpload.bind(_this);
if (!_this.opts.params) {
throw new Error('Transloadit: The `params` option is required.');
}
var params = _this.opts.params;
if (typeof params === 'string') {
try {
params = JSON.parse(params);
} catch (err) {
// Tell the user that this is not an Uppy bug!
err.message = 'Transloadit: The `params` option is a malformed JSON string: ' + err.message;
throw err;
}
}
if (!params.auth || !params.auth.key) {
throw new Error('Transloadit: The `params.auth.key` option is required. ' + 'You can find your Transloadit API key at https://transloadit.com/accounts/credentials.');
}
_this.client = new Client();
return _this;
}
Transloadit.prototype.createAssembly = function createAssembly() {
var _this2 = this;
this.core.log('Transloadit: create assembly');
var files = this.core.state.files;
var expectedFiles = Object.keys(files).reduce(function (count, fileID) {
if (!files[fileID].progress.uploadStarted || files[fileID].isRemote) {
return count + 1;
}
return count;
}, 0);
return this.client.createAssembly({
params: this.opts.params,
fields: this.opts.fields,
expectedFiles: expectedFiles,
signature: this.opts.signature
}).then(function (assembly) {
_this2.updateState({ assembly: assembly });
function attachAssemblyMetadata(file, assembly) {
// Attach meta parameters for the Tus plugin. See:
// https://github.com/tus/tusd/wiki/Uploading-to-Transloadit-using-tus#uploading-using-tus
// TODO Should this `meta` be moved to a `tus.meta` property instead?
// If the MetaData plugin can add eg. resize parameters, it doesn't
// make much sense to set those as upload-metadata for tus.
var meta = _extends({}, file.meta, {
assembly_url: assembly.assembly_url,
filename: file.name,
fieldname: 'file'
});
// Add assembly-specific Tus endpoint.
var tus = _extends({}, file.tus, {
endpoint: assembly.tus_url
});
return _extends({}, file, { meta: meta, tus: tus });
}
var filesObj = _this2.core.state.files;
var files = {};
Object.keys(filesObj).forEach(function (id) {
files[id] = attachAssemblyMetadata(filesObj[id], assembly);
});
_this2.core.setState({ files: files });
return _this2.connectSocket();
}).then(function () {
_this2.core.log('Transloadit: Created assembly');
}).catch(function (err) {
_this2.core.emit('informer', '⚠️ Transloadit: Could not create assembly', 'error', 0);
// Reject the promise.
throw err;
});
};
Transloadit.prototype.shouldWait = function shouldWait() {
return this.opts.waitForEncoding || this.opts.waitForMetadata;
};
// TODO if/when the transloadit API returns tus upload metadata in the
// file objects in the assembly status, change this to use a unique ID
// instead of checking the file name and size.
Transloadit.prototype.findFile = function findFile(_ref) {
var name = _ref.name,
size = _ref.size;
var files = this.core.state.files;
for (var id in files) {
if (!files.hasOwnProperty(id)) {
continue;
}
if (files[id].name === name && files[id].size === size) {
return files[id];
}
}
};
Transloadit.prototype.onFileUploadComplete = function onFileUploadComplete(uploadedFile) {
var _extends2;
var file = this.findFile(uploadedFile);
this.updateState({
files: _extends({}, this.state.files, (_extends2 = {}, _extends2[uploadedFile.id] = {
id: file.id,
uploadedFile: uploadedFile
}, _extends2))
});
this.core.bus.emit('transloadit:upload', uploadedFile);
};
Transloadit.prototype.onResult = function onResult(stepName, result) {
var file = this.state.files[result.original_id];
result.localId = file.id;
this.updateState({
results: this.state.results.concat(result)
});
this.core.bus.emit('transloadit:result', stepName, result);
};
Transloadit.prototype.connectSocket = function connectSocket() {
var _this3 = this;
this.socket = new StatusSocket(this.state.assembly.websocket_url, this.state.assembly);
this.socket.on('upload', this.onFileUploadComplete.bind(this));
if (this.opts.waitForEncoding) {
this.socket.on('result', this.onResult.bind(this));
}
this.assemblyReady = new _Promise(function (resolve, reject) {
if (_this3.opts.waitForEncoding) {
_this3.socket.on('finished', resolve);
} else if (_this3.opts.waitForMetadata) {
_this3.socket.on('metadata', resolve);
}
_this3.socket.on('error', reject);
});
return new _Promise(function (resolve, reject) {
_this3.socket.on('connect', resolve);
_this3.socket.on('error', reject);
}).then(function () {
_this3.core.log('Transloadit: Socket is ready');
});
};
Transloadit.prototype.prepareUpload = function prepareUpload() {
var _this4 = this;
this.core.emit('informer', '🔄 Preparing upload...', 'info', 0);
return this.createAssembly().then(function () {
_this4.core.emit('informer:hide');
});
};
Transloadit.prototype.afterUpload = function afterUpload() {
var _this5 = this;
// If we don't have to wait for encoding metadata or results, we can close
// the socket immediately and finish the upload.
if (!this.shouldWait()) {
this.socket.close();
return;
}
this.core.emit('informer', '🔄 Encoding...', 'info', 0);
return this.assemblyReady.then(function () {
return _this5.client.getAssemblyStatus(_this5.state.assembly.status_endpoint);
}).then(function (assembly) {
_this5.updateState({ assembly: assembly });
// TODO set the `file.uploadURL` to a result?
// We will probably need an option here so the plugin user can tell us
// which result to pick…?
_this5.core.emit('informer:hide');
}).catch(function (err) {
// Always hide the Informer
_this5.core.emit('informer:hide');
throw err;
});
};
Transloadit.prototype.install = function install() {
this.core.addPreProcessor(this.prepareUpload);
this.core.addPostProcessor(this.afterUpload);
this.updateState({
assembly: null,
files: {},
results: []
});
};
Transloadit.prototype.uninstall = function uninstall() {
this.core.removePreProcessor(this.prepareUpload);
this.core.removePostProcessor(this.afterUpload);
};
Transloadit.prototype.updateState = function updateState(newState) {
var transloadit = _extends({}, this.state, newState);
this.core.setState({ transloadit: transloadit });
};
_createClass(Transloadit, [{
key: 'state',
get: function get() {
return this.core.state.transloadit || {};
}
}]);
return Transloadit;
}(Plugin);
},{"../Plugin":39,"./Client":41,"./Socket":42,"es6-promise":60}],44:[function(require,module,exports){
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;
var Plugin = require('./Plugin');
var tus = require('tus-js-client');
var UppySocket = require('../core/UppySocket');
var throttle = require('lodash.throttle');
require('whatwg-fetch');
// Extracted from https://github.com/tus/tus-js-client/blob/master/lib/upload.js#L13
// excepted we removed 'fingerprint' key to avoid adding more dependencies
var tusDefaultOptions = {
endpoint: '',
resume: true,
onProgress: null,
onChunkComplete: null,
onSuccess: null,
onError: null,
headers: {},
chunkSize: Infinity,
withCredentials: false,
uploadUrl: null,
uploadSize: null,
overridePatchMethod: false,
retryDelays: null
};
/**
* Tus resumable file uploader
*
*/
module.exports = function (_Plugin) {
_inherits(Tus10, _Plugin);
function Tus10(core, opts) {
_classCallCheck(this, Tus10);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, core, opts));
_this.type = 'uploader';
_this.id = 'Tus';
_this.title = 'Tus';
// set default options
var defaultOptions = {
resume: true,
allowPause: true,
autoRetry: true
};
// merge default options with the ones set by user
_this.opts = _extends({}, defaultOptions, opts);
_this.handlePauseAll = _this.handlePauseAll.bind(_this);
_this.handleResumeAll = _this.handleResumeAll.bind(_this);
_this.handleUpload = _this.handleUpload.bind(_this);
return _this;
}
Tus10.prototype.pauseResume = function pauseResume(action, fileID) {
var updatedFiles = _extends({}, this.core.getState().files);
var inProgressUpdatedFiles = Object.keys(updatedFiles).filter(function (file) {
return !updatedFiles[file].progress.uploadComplete && updatedFiles[file].progress.uploadStarted;
});
switch (action) {
case 'toggle':
if (updatedFiles[fileID].uploadComplete) return;
var wasPaused = updatedFiles[fileID].isPaused || false;
var isPaused = !wasPaused;
var updatedFile = void 0;
if (wasPaused) {
updatedFile = _extends({}, updatedFiles[fileID], {
isPaused: false
});
} else {
updatedFile = _extends({}, updatedFiles[fileID], {
isPaused: true
});
}
updatedFiles[fileID] = updatedFile;
this.core.setState({ files: updatedFiles });
return isPaused;
case 'pauseAll':
inProgressUpdatedFiles.forEach(function (file) {
var updatedFile = _extends({}, updatedFiles[file], {
isPaused: true
});
updatedFiles[file] = updatedFile;
});
this.core.setState({ files: updatedFiles });
return;
case 'resumeAll':
inProgressUpdatedFiles.forEach(function (file) {
var updatedFile = _extends({}, updatedFiles[file], {
isPaused: false
});
updatedFiles[file] = updatedFile;
});
this.core.setState({ files: updatedFiles });
return;
}
};
Tus10.prototype.handlePauseAll = function handlePauseAll() {
this.pauseResume('pauseAll');
};
Tus10.prototype.handleResumeAll = function handleResumeAll() {
this.pauseResume('resumeAll');
};
/**
* Create a new Tus upload
*
* @param {object} file for use with upload
* @param {integer} current file in a queue
* @param {integer} total number of files in a queue
* @returns {Promise}
*/
Tus10.prototype.upload = function upload(file, current, total) {
var _this2 = this;
this.core.log('uploading ' + current + ' of ' + total);
// Create a new tus upload
return new _Promise(function (resolve, reject) {
var optsTus = _extends({}, tusDefaultOptions, _this2.opts,
// Install file-specific upload overrides.
file.tus || {});
optsTus.onError = function (err) {
_this2.core.log(err);
_this2.core.emitter.emit('core:upload-error', file.id, err);
reject('Failed because: ' + err);
};
optsTus.onProgress = function (bytesUploaded, bytesTotal) {
_this2.core.emitter.emit('core:upload-progress', {
uploader: _this2,
id: file.id,
bytesUploaded: bytesUploaded,
bytesTotal: bytesTotal
});
};
optsTus.onSuccess = function () {
_this2.core.emitter.emit('core:upload-success', file.id, upload, upload.url);
if (upload.url) {
_this2.core.log('Download ' + upload.file.name + ' from ' + upload.url);
}
resolve(upload);
};
optsTus.metadata = file.meta;
var upload = new tus.Upload(file.data, optsTus);
_this2.onFileRemove(file.id, function () {
_this2.core.log('removing file:', file.id);
upload.abort();
resolve('upload ' + file.id + ' was removed');
});
_this2.onPause(file.id, function (isPaused) {
isPaused ? upload.abort() : upload.start();
});
_this2.onPauseAll(file.id, function () {
upload.abort();
});
_this2.onResumeAll(file.id, function () {
upload.start();
});
_this2.core.on('core:retry-started', function () {
var files = _this2.core.getState().files;
if (files[file.id].progress.uploadComplete || !files[file.id].progress.uploadStarted || files[file.id].isPaused) {
return;
}
upload.start();
});
upload.start();
_this2.core.emitter.emit('core:upload-started', file.id, upload);
});
};
Tus10.prototype.uploadRemote = function uploadRemote(file, current, total) {
var _this3 = this;
return new _Promise(function (resolve, reject) {
_this3.core.log(file.remote.url);
var endpoint = _this3.opts.endpoint;
if (file.tus && file.tus.endpoint) {
endpoint = file.tus.endpoint;
}
fetch(file.remote.url, {
method: 'post',
credentials: 'include',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(_extends({}, file.remote.body, {
endpoint: endpoint,
protocol: 'tus',
size: file.data.size
// TODO add `file.meta` as tus metadata here
}))
}).then(function (res) {
if (res.status < 200 && res.status > 300) {
return reject(res.statusText);
}
_this3.core.emitter.emit('core:upload-started', file.id);
res.json().then(function (data) {
// get the host domain
// var regex = /^(?:https?:\/\/|\/\/)?(?:[^@\/\n]+@)?(?:www\.)?([^\/\n]+)/
var regex = /^(?:https?:\/\/|\/\/)?(?:[^@\n]+@)?(?:www\.)?([^\n]+)/;
var host = regex.exec(file.remote.host)[1];
var socketProtocol = location.protocol === 'https:' ? 'wss' : 'ws';
var token = data.token;
var socket = new UppySocket({
target: socketProtocol + ('://' + host + '/api/' + token)
});
_this3.onFileRemove(file.id, function () {
socket.send('pause', {});
resolve('upload ' + file.id + ' was removed');
});
_this3.onPause(file.id, function (isPaused) {
isPaused ? socket.send('pause', {}) : socket.send('resume', {});
});
_this3.onPauseAll(file.id, function () {
socket.send('pause', {});
});
_this3.onResumeAll(file.id, function () {
socket.send('resume', {});
});
var emitProgress = function emitProgress(progressData) {
var progress = progressData.progress,
bytesUploaded = progressData.bytesUploaded,
bytesTotal = progressData.bytesTotal;
if (progress) {
_this3.core.log('Upload progress: ' + progress);
console.log(file.id);
_this3.core.emitter.emit('core:upload-progress', {
uploader: _this3,
id: file.id,
bytesUploaded: bytesUploaded,
bytesTotal: bytesTotal
});
}
};
var throttledEmitProgress = throttle(emitProgress, 300, { leading: true, trailing: true });
socket.on('progress', throttledEmitProgress);
socket.on('success', function (data) {
_this3.core.emitter.emit('core:upload-success', file.id, data, data.url);
socket.close();
return resolve();
});
});
});
});
};
Tus10.prototype.onFileRemove = function onFileRemove(fileID, cb) {
this.core.emitter.on('core:file-remove', function (targetFileID) {
if (fileID === targetFileID) cb();
});
};
Tus10.prototype.onPause = function onPause(fileID, cb) {
var _this4 = this;
this.core.emitter.on('core:upload-pause', function (targetFileID) {
if (fileID === targetFileID) {
var isPaused = _this4.pauseResume('toggle', fileID);
cb(isPaused);
}
});
};
Tus10.prototype.onPauseAll = function onPauseAll(fileID, cb) {
var _this5 = this;
this.core.emitter.on('core:pause-all', function () {
var files = _this5.core.getState().files;
if (!files[fileID]) return;
cb();
});
};
Tus10.prototype.onResumeAll = function onResumeAll(fileID, cb) {
var _this6 = this;
this.core.emitter.on('core:resume-all', function () {
var files = _this6.core.getState().files;
if (!files[fileID]) return;
cb();
});
};
Tus10.prototype.uploadFiles = function uploadFiles(files) {
var _this7 = this;
if (Object.keys(files).length === 0) {
this.core.log('no files to upload!');
return;
}
files.forEach(function (file, index) {
var current = parseInt(index, 10) + 1;
var total = files.length;
if (!file.isRemote) {
_this7.upload(file, current, total);
} else {
_this7.uploadRemote(file, current, total);
}
});
};
Tus10.prototype.selectForUpload = function selectForUpload(files) {
// TODO: replace files[file].isRemote with some logic
//
// filter files that are now yet being uploaded / haven’t been uploaded
// and remote too
var filesForUpload = Object.keys(files).filter(function (file) {
if (!files[file].progress.uploadStarted || files[file].isRemote) {
return true;
}
return false;
}).map(function (file) {
return files[file];
});
this.uploadFiles(filesForUpload);
};
Tus10.prototype.handleUpload = function handleUpload() {
var _this8 = this;
this.core.log('Tus is uploading...');
var files = this.core.getState().files;
this.selectForUpload(files);
return new _Promise(function (resolve) {
_this8.core.bus.once('core:upload-complete', resolve);
});
};
Tus10.prototype.actions = function actions() {
var _this9 = this;
this.core.emitter.on('core:pause-all', this.handlePauseAll);
this.core.emitter.on('core:resume-all', this.handleResumeAll);
if (this.opts.autoRetry) {
this.core.emitter.on('back-online', function () {
_this9.core.emitter.emit('core:retry-started');
});
}
};
Tus10.prototype.addResumableUploadsCapabilityFlag = function addResumableUploadsCapabilityFlag() {
var newCapabilities = _extends({}, this.core.getState().capabilities);
newCapabilities.resumableUploads = true;
this.core.setState({
capabilities: newCapabilities
});
};
Tus10.prototype.install = function install() {
this.addResumableUploadsCapabilityFlag();
this.core.addUploader(this.handleUpload);
this.actions();
};
Tus10.prototype.uninstall = function uninstall() {
this.core.removeUploader(this.handleUpload);
this.core.emitter.off('core:pause-all', this.handlePauseAll);
this.core.emitter.off('core:resume-all', this.handleResumeAll);
};
return Tus10;
}(Plugin);
},{"../core/UppySocket":5,"./Plugin":39,"es6-promise":60,"lodash.throttle":61,"tus-js-client":116,"whatwg-fetch":123}],45:[function(require,module,exports){
'use strict';
var _svgNamespace = 'http://www.w3.org/2000/svg',
_appendChild = require('yo-yoify/lib/appendChild');
module.exports = function (props) {
var _path, _path2, _uppyIcon;
return _uppyIcon = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon.setAttribute('width', '100'), _uppyIcon.setAttribute('height', '77'), _uppyIcon.setAttribute('viewBox', '0 0 100 77'), _uppyIcon.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon, [' ', (_path = document.createElementNS(_svgNamespace, 'path'), _path.setAttribute('d', 'M50 32c-7.168 0-13 5.832-13 13s5.832 13 13 13 13-5.832 13-13-5.832-13-13-13z'), _path), ' ', (_path2 = document.createElementNS(_svgNamespace, 'path'), _path2.setAttribute('d', 'M87 13H72c0-7.18-5.82-13-13-13H41c-7.18 0-13 5.82-13 13H13C5.82 13 0 18.82 0 26v38c0 7.18 5.82 13 13 13h74c7.18 0 13-5.82 13-13V26c0-7.18-5.82-13-13-13zM50 68c-12.683 0-23-10.318-23-23s10.317-23 23-23 23 10.318 23 23-10.317 23-23 23z'), _path2), ' ']), _uppyIcon;
};
},{"yo-yoify/lib/appendChild":131}],46:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild'),
_onload = require('on-load');
var SnapshotButton = require('./SnapshotButton');
var RecordButton = require('./RecordButton');
function isModeAvailable(modes, mode) {
return modes.indexOf(mode) !== -1;
}
module.exports = function (props) {
var _uppyWebcamVideoContainer, _uppyWebcamButtonContainer, _uppyWebcamCanvas, _uppyWebcamContainer;
var src = props.src || '';
var video = void 0;
if (props.useTheFlash) {
video = props.getSWFHTML();
} else {
var _uppyWebcamVideo;
video = (_uppyWebcamVideo = document.createElement('video'), _uppyWebcamVideo.setAttribute('autoplay', 'autoplay'), _uppyWebcamVideo.setAttribute('src', '' + String(src) + ''), _uppyWebcamVideo.setAttribute('class', 'UppyWebcam-video'), _uppyWebcamVideo);
}
var shouldShowRecordButton = props.supportsRecording && (isModeAvailable(props.modes, 'video-only') || isModeAvailable(props.modes, 'audio-only') || isModeAvailable(props.modes, 'video-audio'));
var shouldShowSnapshotButton = isModeAvailable(props.modes, 'picture');
return _uppyWebcamContainer = document.createElement('div'), _onload(_uppyWebcamContainer, function (el) {
props.onFocus();
var recordButton = el.querySelector('.UppyWebcam-recordButton');
if (recordButton) recordButton.focus();
}, function (el) {
props.onStop();
}, 3), _uppyWebcamContainer.setAttribute('class', 'UppyWebcam-container'), _appendChild(_uppyWebcamContainer, [' ', (_uppyWebcamVideoContainer = document.createElement('div'), _uppyWebcamVideoContainer.setAttribute('class', 'UppyWebcam-videoContainer'), _appendChild(_uppyWebcamVideoContainer, [' ', video, ' ']), _uppyWebcamVideoContainer), ' ', (_uppyWebcamButtonContainer = document.createElement('div'), _uppyWebcamButtonContainer.setAttribute('class', 'UppyWebcam-buttonContainer'), _appendChild(_uppyWebcamButtonContainer, [' ', shouldShowRecordButton ? RecordButton(props) : null, ' ', shouldShowSnapshotButton ? SnapshotButton(props) : null, ' ']), _uppyWebcamButtonContainer), ' ', (_uppyWebcamCanvas = document.createElement('canvas'), _uppyWebcamCanvas.setAttribute('style', 'display: none;'), _uppyWebcamCanvas.setAttribute('class', 'UppyWebcam-canvas'), _uppyWebcamCanvas), ' ']), _uppyWebcamContainer;
};
},{"./RecordButton":48,"./SnapshotButton":51,"on-load":63,"yo-yoify/lib/appendChild":131}],47:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
module.exports = function (props) {
var _h, _span, _div;
return _div = document.createElement('div'), _appendChild(_div, [' ', (_h = document.createElement('h1'), _h.textContent = 'Please allow access to your camera', _h), ' ', (_span = document.createElement('span'), _span.textContent = 'You have been prompted to allow camera access from this site. In order to take pictures with your camera you must approve this request.', _span), ' ']), _div;
};
},{"yo-yoify/lib/appendChild":131}],48:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
var RecordStartIcon = require('./RecordStartIcon');
var RecordStopIcon = require('./RecordStopIcon');
module.exports = function RecordButton(_ref) {
var _uppyButtonCircular2;
var recording = _ref.recording,
onStartRecording = _ref.onStartRecording,
onStopRecording = _ref.onStopRecording;
if (recording) {
var _uppyButtonCircular;
return _uppyButtonCircular = document.createElement('button'), _uppyButtonCircular.setAttribute('type', 'button'), _uppyButtonCircular.setAttribute('title', 'Stop Recording'), _uppyButtonCircular.setAttribute('aria-label', 'Stop Recording'), _uppyButtonCircular.onclick = onStopRecording, _uppyButtonCircular.setAttribute('class', 'UppyButton--circular UppyButton--red UppyButton--sizeM UppyWebcam-recordButton'), _appendChild(_uppyButtonCircular, [' ', RecordStopIcon(), ' ']), _uppyButtonCircular;
}
return _uppyButtonCircular2 = document.createElement('button'), _uppyButtonCircular2.setAttribute('type', 'button'), _uppyButtonCircular2.setAttribute('title', 'Begin Recording'), _uppyButtonCircular2.setAttribute('aria-label', 'Begin Recording'), _uppyButtonCircular2.onclick = onStartRecording, _uppyButtonCircular2.setAttribute('class', 'UppyButton--circular UppyButton--red UppyButton--sizeM UppyWebcam-recordButton'), _appendChild(_uppyButtonCircular2, [' ', RecordStartIcon(), ' ']), _uppyButtonCircular2;
};
},{"./RecordStartIcon":49,"./RecordStopIcon":50,"yo-yoify/lib/appendChild":131}],49:[function(require,module,exports){
'use strict';
var _svgNamespace = 'http://www.w3.org/2000/svg',
_appendChild = require('yo-yoify/lib/appendChild');
module.exports = function (props) {
var _circle, _uppyIcon;
return _uppyIcon = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon.setAttribute('width', '100'), _uppyIcon.setAttribute('height', '100'), _uppyIcon.setAttribute('viewBox', '0 0 100 100'), _uppyIcon.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon, [' ', (_circle = document.createElementNS(_svgNamespace, 'circle'), _circle.setAttribute('cx', '50'), _circle.setAttribute('cy', '50'), _circle.setAttribute('r', '40'), _circle), ' ']), _uppyIcon;
};
},{"yo-yoify/lib/appendChild":131}],50:[function(require,module,exports){
'use strict';
var _svgNamespace = 'http://www.w3.org/2000/svg',
_appendChild = require('yo-yoify/lib/appendChild');
module.exports = function (props) {
var _rect, _uppyIcon;
return _uppyIcon = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon.setAttribute('width', '100'), _uppyIcon.setAttribute('height', '100'), _uppyIcon.setAttribute('viewBox', '0 0 100 100'), _uppyIcon.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon, [' ', (_rect = document.createElementNS(_svgNamespace, 'rect'), _rect.setAttribute('x', '15'), _rect.setAttribute('y', '15'), _rect.setAttribute('width', '70'), _rect.setAttribute('height', '70'), _rect), ' ']), _uppyIcon;
};
},{"yo-yoify/lib/appendChild":131}],51:[function(require,module,exports){
'use strict';
var _appendChild = require('yo-yoify/lib/appendChild');
var CameraIcon = require('./CameraIcon');
module.exports = function SnapshotButton(_ref) {
var _uppyButtonCircular;
var onSnapshot = _ref.onSnapshot;
return _uppyButtonCircular = document.createElement('button'), _uppyButtonCircular.setAttribute('type', 'button'), _uppyButtonCircular.setAttribute('title', 'Take a snapshot'), _uppyButtonCircular.setAttribute('aria-label', 'Take a snapshot'), _uppyButtonCircular.onclick = onSnapshot, _uppyButtonCircular.setAttribute('class', 'UppyButton--circular UppyButton--red UppyButton--sizeM UppyWebcam-recordButton'), _appendChild(_uppyButtonCircular, [' ', CameraIcon(), ' ']), _uppyButtonCircular;
};
},{"./CameraIcon":45,"yo-yoify/lib/appendChild":131}],52:[function(require,module,exports){
'use strict';
var _svgNamespace = 'http://www.w3.org/2000/svg',
_appendChild = require('yo-yoify/lib/appendChild');
module.exports = function (props) {
var _path, _path2, _uppyIcon;
return _uppyIcon = document.createElementNS(_svgNamespace, 'svg'), _uppyIcon.setAttribute('width', '18'), _uppyIcon.setAttribute('height', '21'), _uppyIcon.setAttribute('viewBox', '0 0 18 21'), _uppyIcon.setAttribute('class', 'UppyIcon'), _appendChild(_uppyIcon, [' ', (_path = document.createElementNS(_svgNamespace, 'path'), _path.setAttribute('d', 'M14.8 16.9c1.9-1.7 3.2-4.1 3.2-6.9 0-5-4-9-9-9s-9 4-9 9c0 2.8 1.2 5.2 3.2 6.9C1.9 17.9.5 19.4 0 21h3c1-1.9 11-1.9 12 0h3c-.5-1.6-1.9-3.1-3.2-4.1zM9 4c3.3 0 6 2.7 6 6s-2.7 6-6 6-6-2.7-6-6 2.7-6 6-6z'), _path), ' ', (_path2 = document.createElementNS(_svgNamespace, 'path'), _path2.setAttribute('d', 'M9 14c2.2 0 4-1.8 4-4s-1.8-4-4-4-4 1.8-4 4 1.8 4 4 4zM8 8c.6 0 1 .4 1 1s-.4 1-1 1-1-.4-1-1c0-.5.4-1 1-1z'), _path2), ' ']), _uppyIcon;
};
},{"yo-yoify/lib/appendChild":131}],53:[function(require,module,exports){
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;
var Plugin = require('../Plugin');
var WebcamProvider = require('../../uppy-base/src/plugins/Webcam');
var _require = require('../../core/Utils'),
extend = _require.extend,
getFileTypeExtension = _require.getFileTypeExtension,
supportsMediaRecorder = _require.supportsMediaRecorder;
var WebcamIcon = require('./WebcamIcon');
var CameraScreen = require('./CameraScreen');
var PermissionsScreen = require('./PermissionsScreen');
/**
* Webcam
*/
module.exports = function (_Plugin) {
_inherits(Webcam, _Plugin);
function Webcam(core, opts) {
_classCallCheck(this, Webcam);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, core, opts));
_this.userMedia = true;
_this.protocol = location.protocol.match(/https/i) ? 'https' : 'http';
_this.type = 'acquirer';
_this.id = 'Webcam';
_this.title = 'Webcam';
_this.icon = WebcamIcon;
// set default options
var defaultOptions = {
enableFlash: true,
modes: ['video-audio', 'video-only', 'audio-only', 'picture']
};
_this.params = {
swfURL: 'webcam.swf',
width: 400,
height: 300,
dest_width: 800, // size of captured image
dest_height: 600, // these default to width/height
image_format: 'jpeg', // image format (may be jpeg or png)
jpeg_quality: 90, // jpeg image quality from 0 (worst) to 100 (best)
enable_flash: true, // enable flash fallback,
force_flash: false, // force flash mode,
flip_horiz: false, // flip image horiz (mirror mode)
fps: 30, // camera frames per second
upload_name: 'webcam', // name of file in upload post data
constraints: null, // custom user media constraints,
flashNotDetectedText: 'ERROR: No Adobe Flash Player detected. Webcam.js relies on Flash for browsers that do not support getUserMedia (like yours).',
noInterfaceFoundText: 'No supported webcam interface found.',
unfreeze_snap: true // Whether to unfreeze the camera after snap (defaults to true)
};
// merge default options with the ones set by user
_this.opts = _extends({}, defaultOptions, opts);
_this.install = _this.install.bind(_this);
_this.updateState = _this.updateState.bind(_this);
_this.render = _this.render.bind(_this);
// Camera controls
_this.start = _this.start.bind(_this);
_this.stop = _this.stop.bind(_this);
_this.takeSnapshot = _this.takeSnapshot.bind(_this);
_this.startRecording = _this.startRecording.bind(_this);
_this.stopRecording = _this.stopRecording.bind(_this);
_this.webcam = new WebcamProvider(_this.opts, _this.params);
_this.webcamActive = false;
return _this;
}
Webcam.prototype.start = function start() {
var _this2 = this;
this.webcamActive = true;
this.webcam.start().then(function (stream) {
_this2.stream = stream;
_this2.updateState({
// videoStream: stream,
cameraReady: true
});
}).catch(function (err) {
_this2.updateState({
cameraError: err
});
});
};
Webcam.prototype.startRecording = function startRecording() {
var _this3 = this;
// TODO We can check here if any of the mime types listed in the
// mimeToExtensions map in Utils.js are supported, and prefer to use one of
// those.
// Right now we let the browser pick a type that it deems appropriate.
this.recorder = new MediaRecorder(this.stream);
this.recordingChunks = [];
this.recorder.addEventListener('dataavailable', function (event) {
_this3.recordingChunks.push(event.data);
});
this.recorder.start();
this.updateState({
isRecording: true
});
};
Webcam.prototype.stopRecording = function stopRecording() {
var _this4 = this;
return new _Promise(function (resolve, reject) {
_this4.recorder.addEventListener('stop', function () {
_this4.updateState({
isRecording: false
});
var mimeType = _this4.recordingChunks[0].type;
var fileExtension = getFileTypeExtension(mimeType);
if (!fileExtension) {
reject(new Error('Could not upload file: Unsupported media type "' + mimeType + '"'));
return;
}
var file = {
source: _this4.id,
name: 'webcam-' + Date.now() + '.' + fileExtension,
type: mimeType,
data: new Blob(_this4.recordingChunks, { type: mimeType })
};
_this4.core.emitter.emit('core:file-add', file);
_this4.recordingChunks = null;
_this4.recorder = null;
resolve();
});
_this4.recorder.stop();
});
};
Webcam.prototype.stop = function stop() {
this.stream.getAudioTracks().forEach(function (track) {
track.stop();
});
this.stream.getVideoTracks().forEach(function (track) {
track.stop();
});
this.webcamActive = false;
this.stream = null;
this.streamSrc = null;
};
Webcam.prototype.takeSnapshot = function takeSnapshot() {
var opts = {
name: 'webcam-' + Date.now() + '.jpg',
mimeType: 'image/jpeg'
};
var video = this.target.querySelector('.UppyWebcam-video');
var image = this.webcam.getImage(video, opts);
var tagFile = {
source: this.id,
name: opts.name,
data: image.data,
type: opts.mimeType
};
this.core.emitter.emit('core:file-add', tagFile);
};
Webcam.prototype.render = function render(state) {
if (!this.webcamActive) {
this.start();
}
if (!state.webcam.cameraReady && !state.webcam.useTheFlash) {
return PermissionsScreen(state.webcam);
}
if (!this.streamSrc) {
this.streamSrc = this.stream ? URL.createObjectURL(this.stream) : null;
}
return CameraScreen(extend(state.webcam, {
onSnapshot: this.takeSnapshot,
onStartRecording: this.startRecording,
onStopRecording: this.stopRecording,
onFocus: this.focus,
onStop: this.stop,
modes: this.opts.modes,
supportsRecording: supportsMediaRecorder(),
recording: state.webcam.isRecording,
getSWFHTML: this.webcam.getSWFHTML,
src: this.streamSrc
}));
};
Webcam.prototype.focus = function focus() {
var _this5 = this;
setTimeout(function () {
_this5.core.emitter.emit('informer', 'Smile!', 'warning', 2000);
}, 1000);
};
Webcam.prototype.install = function install() {
this.webcam.init();
this.core.setState({
webcam: {
cameraReady: false
}
});
var target = this.opts.target;
var plugin = this;
this.target = this.mount(target, plugin);
};
Webcam.prototype.uninstall = function uninstall() {
this.webcam.reset();
this.unmount();
};
/**
* Little shorthand to update the state with my new state
*/
Webcam.prototype.updateState = function updateState(newState) {
var state = this.core.state;
var webcam = _extends({}, state.webcam, newState);
this.core.setState({ webcam: webcam });
};
return Webcam;
}(Plugin);
},{"../../core/Utils":6,"../../uppy-base/src/plugins/Webcam":55,"../Plugin":39,"./CameraScreen":46,"./PermissionsScreen":47,"./WebcamIcon":52,"es6-promise":60}],54:[function(require,module,exports){
'use strict';
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
require('whatwg-fetch');
var _getName = function _getName(id) {
return id.split('-').map(function (s) {
return s.charAt(0).toUpperCase() + s.slice(1);
}).join(' ');
};
module.exports = function () {
function Provider(opts) {
_classCallCheck(this, Provider);
this.opts = opts;
this.provider = opts.provider;
this.id = this.provider;
this.authProvider = opts.authProvider || this.provider;
this.name = this.opts.name || _getName(this.id);
}
_createClass(Provider, [{
key: 'auth',
value: function auth() {
return fetch(this.opts.host + '/' + this.id + '/auth', {
method: 'get',
credentials: 'include',
headers: {
'Accept': 'application/json',
'Content-Type': 'application.json'
}
}).then(function (res) {
return res.json().then(function (payload) {
return payload.authenticated;
});
});
}
}, {
key: 'list',
value: function list(directory) {
return fetch(this.opts.host + '/' + this.id + '/list/' + (directory || ''), {
method: 'get',
credentials: 'include',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
}).then(function (res) {
return res.json();
});
}
}, {
key: 'logout',
value: function logout() {
var redirect = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : location.href;
return fetch(this.opts.host + '/' + this.id + '/logout?redirect=' + redirect, {
method: 'get',
credentials: 'include',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
});
}
}]);
return Provider;
}();
},{"whatwg-fetch":123}],55:[function(require,module,exports){
'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var dataURItoFile = require('../utils/dataURItoFile');
/**
* Webcam Plugin
*/
module.exports = function () {
function Webcam() {
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classCallCheck(this, Webcam);
this._userMedia;
this.userMedia = true;
this.protocol = location.protocol.match(/https/i) ? 'https' : 'http';
// set default options
var defaultOptions = {
enableFlash: true,
modes: []
};
var defaultParams = {
swfURL: 'webcam.swf',
width: 400,
height: 300,
dest_width: 800, // size of captured image
dest_height: 600, // these default to width/height
image_format: 'jpeg', // image format (may be jpeg or png)
jpeg_quality: 90, // jpeg image quality from 0 (worst) to 100 (best)
enable_flash: true, // enable flash fallback,
force_flash: false, // force flash mode,
flip_horiz: false, // flip image horiz (mirror mode)
fps: 30, // camera frames per second
upload_name: 'webcam', // name of file in upload post data
constraints: null, // custom user media constraints,
flashNotDetectedText: 'ERROR: No Adobe Flash Player detected. Webcam.js relies on Flash for browsers that do not support getUserMedia (like yours).',
noInterfaceFoundText: 'No supported webcam interface found.',
unfreeze_snap: true // Whether to unfreeze the camera after snap (defaults to true)
};
this.params = Object.assign({}, defaultParams, params);
// merge default options with the ones set by user
this.opts = Object.assign({}, defaultOptions, opts);
// Camera controls
this.start = this.start.bind(this);
this.init = this.init.bind(this);
this.stop = this.stop.bind(this);
// this.startRecording = this.startRecording.bind(this)
// this.stopRecording = this.stopRecording.bind(this)
this.takeSnapshot = this.takeSnapshot.bind(this);
this.getImage = this.getImage.bind(this);
this.getSWFHTML = this.getSWFHTML.bind(this);
this.detectFlash = this.detectFlash.bind(this);
this.getUserMedia = this.getUserMedia.bind(this);
this.getMediaDevices = this.getMediaDevices.bind(this);
}
/**
* Checks for getUserMedia support
*/
_createClass(Webcam, [{
key: 'init',
value: function init() {
var _this = this;
// initialize, check for getUserMedia support
this.mediaDevices = this.getMediaDevices();
this.userMedia = this.getUserMedia(this.mediaDevices);
// Make sure media stream is closed when navigating away from page
if (this.userMedia) {
window.addEventListener('beforeunload', function (event) {
_this.reset();
});
}
return {
mediaDevices: this.mediaDevices,
userMedia: this.userMedia
};
}
// Setup getUserMedia, with polyfill for older browsers
// Adapted from: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
}, {
key: 'getMediaDevices',
value: function getMediaDevices() {
return navigator.mediaDevices && navigator.mediaDevices.getUserMedia ? navigator.mediaDevices : navigator.mozGetUserMedia || navigator.webkitGetUserMedia ? {
getUserMedia: function getUserMedia(opts) {
return new Promise(function (resolve, reject) {
(navigator.mozGetUserMedia || navigator.webkitGetUserMedia).call(navigator, opts, resolve, reject);
});
}
} : null;
}
}, {
key: 'getUserMedia',
value: function getUserMedia(mediaDevices) {
var userMedia = true;
// Older versions of firefox (< 21) apparently claim support but user media does not actually work
if (navigator.userAgent.match(/Firefox\D+(\d+)/)) {
if (parseInt(RegExp.$1, 10) < 21) {
return null;
}
}
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
return userMedia && !!mediaDevices && !!window.URL;
}
}, {
key: 'start',
value: function start() {
var _this2 = this;
this.userMedia = this._userMedia === undefined ? this.userMedia : this._userMedia;
return new Promise(function (resolve, reject) {
if (_this2.userMedia) {
var acceptsAudio = _this2.opts.modes.indexOf('video-audio') !== -1 || _this2.opts.modes.indexOf('audio-only') !== -1;
var acceptsVideo = _this2.opts.modes.indexOf('video-audio') !== -1 || _this2.opts.modes.indexOf('video-only') !== -1 || _this2.opts.modes.indexOf('picture') !== -1;
// ask user for access to their camera
_this2.mediaDevices.getUserMedia({
audio: acceptsAudio,
video: acceptsVideo
}).then(function (stream) {
return resolve(stream);
}).catch(function (err) {
return reject(err);
});
}
});
}
/**
* Detects if browser supports flash
* Code snippet borrowed from: https://github.com/swfobject/swfobject
*
* @return {bool} flash supported
*/
}, {
key: 'detectFlash',
value: function detectFlash() {
var SHOCKWAVE_FLASH = 'Shockwave Flash';
var SHOCKWAVE_FLASH_AX = 'ShockwaveFlash.ShockwaveFlash';
var FLASH_MIME_TYPE = 'application/x-shockwave-flash';
var win = window;
var nav = navigator;
var hasFlash = false;
if (typeof nav.plugins !== 'undefined' && _typeof(nav.plugins[SHOCKWAVE_FLASH]) === 'object') {
var desc = nav.plugins[SHOCKWAVE_FLASH].description;
if (desc && typeof nav.mimeTypes !== 'undefined' && nav.mimeTypes[FLASH_MIME_TYPE] && nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin) {
hasFlash = true;
}
} else if (typeof win.ActiveXObject !== 'undefined') {
try {
var ax = new win.ActiveXObject(SHOCKWAVE_FLASH_AX);
if (ax) {
var ver = ax.GetVariable('$version');
if (ver) hasFlash = true;
}
} catch (e) {}
}
return hasFlash;
}
}, {
key: 'reset',
value: function reset() {
// shutdown camera, reset to potentially attach again
if (this.preview_active) this.unfreeze();
if (this.userMedia) {
if (this.stream) {
if (this.stream.getVideoTracks) {
// get video track to call stop on it
var tracks = this.stream.getVideoTracks();
if (tracks && tracks[0] && tracks[0].stop) tracks[0].stop();
} else if (this.stream.stop) {
// deprecated, may be removed in future
this.stream.stop();
}
}
delete this.stream;
}
if (this.userMedia !== true) {
// call for turn off camera in flash
this.getMovie()._releaseCamera();
}
}
}, {
key: 'getSWFHTML',
value: function getSWFHTML() {
// Return HTML for embedding flash based webcam capture movie
var swfURL = this.params.swfURL;
// make sure we aren't running locally (flash doesn't work)
if (location.protocol.match(/file/)) {
return '<h3 style="color:red">ERROR: the Webcam.js Flash fallback does not work from local disk. Please run it from a web server.</h3>';
}
// make sure we have flash
if (!this.detectFlash()) {
return '<h3 style="color:red">No flash</h3>';
}
// set default swfURL if not explicitly set
if (!swfURL) {
// find our script tag, and use that base URL
var baseUrl = '';
var scpts = document.getElementsByTagName('script');
for (var idx = 0, len = scpts.length; idx < len; idx++) {
var src = scpts[idx].getAttribute('src');
if (src && src.match(/\/webcam(\.min)?\.js/)) {
baseUrl = src.replace(/\/webcam(\.min)?\.js.*$/, '');
idx = len;
}
}
if (baseUrl) swfURL = baseUrl + '/webcam.swf';else swfURL = 'webcam.swf';
}
// // if this is the user's first visit, set flashvar so flash privacy settings panel is shown first
// if (window.localStorage && !localStorage.getItem('visited')) {
// // this.params.new_user = 1
// localStorage.setItem('visited', 1)
// }
// this.params.new_user = 1
// construct flashvars string
var flashvars = '';
for (var key in this.params) {
if (flashvars) flashvars += '&';
flashvars += key + '=' + escape(this.params[key]);
}
// construct object/embed tag
return '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" type="application/x-shockwave-flash" codebase="' + this.protocol + '://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="' + this.params.width + '" height="' + this.params.height + '" id="webcam_movie_obj" align="middle"><param name="wmode" value="opaque" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="' + swfURL + '" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="' + flashvars + '"/><embed id="webcam_movie_embed" src="' + swfURL + '" wmode="opaque" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="' + this.params.width + '" height="' + this.params.height + '" name="webcam_movie_embed" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="' + flashvars + '"></embed></object>';
}
}, {
key: 'getMovie',
value: function getMovie() {
// get reference to movie object/embed in DOM
var movie = document.getElementById('webcam_movie_obj');
if (!movie || !movie._snap) movie = document.getElementById('webcam_movie_embed');
if (!movie) console.log('getMovie error');
return movie;
}
/**
* Stops the webcam capture and video playback.
*/
}, {
key: 'stop',
value: function stop() {
var videoStream = this.videoStream;
this.updateState({
cameraReady: false
});
if (videoStream) {
if (videoStream.stop) {
videoStream.stop();
} else if (videoStream.msStop) {
videoStream.msStop();
}
videoStream.onended = null;
videoStream = null;
}
}
}, {
key: 'flashNotify',
value: function flashNotify(type, msg) {
// receive notification from flash about event
switch (type) {
case 'flashLoadComplete':
// movie loaded successfully
break;
case 'cameraLive':
// camera is live and ready to snap
this.live = true;
break;
case 'error':
// Flash error
console.log('There was a flash error', msg);
break;
default:
// catch-all event, just in case
console.log('webcam flash_notify: ' + type + ': ' + msg);
break;
}
}
}, {
key: 'configure',
value: function configure(panel) {
// open flash configuration panel -- specify tab name:
// 'camera', 'privacy', 'default', 'localStorage', 'microphone', 'settingsManager'
if (!panel) panel = 'camera';
this.getMovie()._configure(panel);
}
/**
* Takes a snapshot and displays it in a canvas.
*/
}, {
key: 'getImage',
value: function getImage(video, opts) {
var canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
canvas.getContext('2d').drawImage(video, 0, 0);
var dataUrl = canvas.toDataURL(opts.mimeType);
var file = dataURItoFile(dataUrl, {
name: opts.name
});
return {
dataUrl: dataUrl,
data: file,
type: opts.mimeType
};
}
}, {
key: 'takeSnapshot',
value: function takeSnapshot(video, canvas) {
var opts = {
name: 'webcam-' + Date.now() + '.jpg',
mimeType: 'image/jpeg'
};
var image = this.getImage(video, canvas, opts);
var tagFile = {
source: this.id,
name: opts.name,
data: image.data,
type: opts.type
};
return tagFile;
}
}]);
return Webcam;
}();
},{"../utils/dataURItoFile":56}],56:[function(require,module,exports){
'use strict';
function dataURItoBlob(dataURI, opts, toFile) {
// get the base64 data
var data = dataURI.split(',')[1];
// user may provide mime type, if not get it from data URI
var mimeType = opts.mimeType || dataURI.split(',')[0].split(':')[1].split(';')[0];
// default to plain/text if data URI has no mimeType
if (mimeType == null) {
mimeType = 'plain/text';
}
var binary = atob(data);
var array = [];
for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
// Convert to a File?
if (toFile) {
return new File([new Uint8Array(array)], opts.name || '', { type: mimeType });
}
return new Blob([new Uint8Array(array)], { type: mimeType });
}
module.exports = function (dataURI, opts) {
return dataURItoBlob(dataURI, opts, true);
};
},{}],57:[function(require,module,exports){
module.exports = dragDrop
var flatten = require('flatten')
var parallel = require('run-parallel')
function dragDrop (elem, listeners) {
if (typeof elem === 'string') {
var selector = elem
elem = window.document.querySelector(elem)
if (!elem) {
throw new Error('"' + selector + '" does not match any HTML elements')
}
}
if (!elem) {
throw new Error('"' + elem + '" is not a valid HTML element')
}
if (typeof listeners === 'function') {
listeners = { onDrop: listeners }
}
var timeout
elem.addEventListener('dragenter', onDragEnter, false)
elem.addEventListener('dragover', onDragOver, false)
elem.addEventListener('dragleave', onDragLeave, false)
elem.addEventListener('drop', onDrop, false)
// Function to remove drag-drop listeners
return function remove () {
removeDragClass()
elem.removeEventListener('dragenter', onDragEnter, false)
elem.removeEventListener('dragover', onDragOver, false)
elem.removeEventListener('dragleave', onDragLeave, false)
elem.removeEventListener('drop', onDrop, false)
}
function onDragEnter (e) {
if (listeners.onDragEnter) {
listeners.onDragEnter(e)
}
// Prevent event
e.stopPropagation()
e.preventDefault()
return false
}
function onDragOver (e) {
e.stopPropagation()
e.preventDefault()
if (e.dataTransfer.items) {
// Only add "drag" class when `items` contains items that are able to be
// handled by the registered listeners (files vs. text)
var items = toArray(e.dataTransfer.items)
var fileItems = items.filter(function (item) { return item.kind === 'file' })
var textItems = items.filter(function (item) { return item.kind === 'string' })
if (fileItems.length === 0 && !listeners.onDropText) return
if (textItems.length === 0 && !listeners.onDrop) return
if (fileItems.length === 0 && textItems.length === 0) return
}
elem.classList.add('drag')
clearTimeout(timeout)
if (listeners.onDragOver) {
listeners.onDragOver(e)
}
e.dataTransfer.dropEffect = 'copy'
return false
}
function onDragLeave (e) {
e.stopPropagation()
e.preventDefault()
if (listeners.onDragLeave) {
listeners.onDragLeave(e)
}
clearTimeout(timeout)
timeout = setTimeout(removeDragClass, 50)
return false
}
function onDrop (e) {
e.stopPropagation()
e.preventDefault()
if (listeners.onDragLeave) {
listeners.onDragLeave(e)
}
clearTimeout(timeout)
removeDragClass()
var pos = {
x: e.clientX,
y: e.clientY
}
// text drop support
var text = e.dataTransfer.getData('text')
if (text && listeners.onDropText) {
listeners.onDropText(text, pos)
}
// file drop support
if (e.dataTransfer.items) {
// Handle directories in Chrome using the proprietary FileSystem API
var items = toArray(e.dataTransfer.items).filter(function (item) {
return item.kind === 'file'
})
if (items.length === 0) return
parallel(items.map(function (item) {
return function (cb) {
processEntry(item.webkitGetAsEntry(), cb)
}
}), function (err, results) {
// This catches permission errors with file:// in Chrome. This should never
// throw in production code, so the user does not need to use try-catch.
if (err) throw err
if (listeners.onDrop) {
listeners.onDrop(flatten(results), pos)
}
})
} else {
var files = toArray(e.dataTransfer.files)
if (files.length === 0) return
files.forEach(function (file) {
file.fullPath = '/' + file.name
})
if (listeners.onDrop) {
listeners.onDrop(files, pos)
}
}
return false
}
function removeDragClass () {
elem.classList.remove('drag')
}
}
function processEntry (entry, cb) {
var entries = []
if (entry.isFile) {
entry.file(function (file) {
file.fullPath = entry.fullPath // preserve pathing for consumer
cb(null, file)
}, function (err) {
cb(err)
})
} else if (entry.isDirectory) {
var reader = entry.createReader()
readEntries()
}
function readEntries () {
reader.readEntries(function (entries_) {
if (entries_.length > 0) {
entries = entries.concat(toArray(entries_))
readEntries() // continue reading entries until `readEntries` returns no more
} else {
doneEntries()
}
})
}
function doneEntries () {
parallel(entries.map(function (entry) {
return function (cb) {
processEntry(entry, cb)
}
}), cb)
}
}
function toArray (list) {
return Array.prototype.slice.call(list || [], 0)
}
},{"flatten":58,"run-parallel":59}],58:[function(require,module,exports){
module.exports = function flatten(list, depth) {
depth = (typeof depth == 'number') ? depth : Infinity;
if (!depth) {
if (Array.isArray(list)) {
return list.map(function(i) { return i; });
}
return list;
}
return _flatten(list, 1);
function _flatten(list, d) {
return list.reduce(function (acc, item) {
if (Array.isArray(item) && d < depth) {
return acc.concat(_flatten(item, d + 1));
}
else {
return acc.concat(item);
}
}, []);
}
};
},{}],59:[function(require,module,exports){
(function (process){
module.exports = function (tasks, cb) {
var results, pending, keys
var isSync = true
if (Array.isArray(tasks)) {
results = []
pending = tasks.length
} else {
keys = Object.keys(tasks)
results = {}
pending = keys.length
}
function done (err) {
function end () {
if (cb) cb(err, results)
cb = null
}
if (isSync) process.nextTick(end)
else end()
}
function each (i, err, result) {
results[i] = result
if (--pending === 0 || err) {
done(err)
}
}
if (!pending) {
// empty
done(null)
} else if (keys) {
// object
keys.forEach(function (key) {
tasks[key](function (err, result) { each(key, err, result) })
})
} else {
// array
tasks.forEach(function (task, i) {
task(function (err, result) { each(i, err, result) })
})
}
isSync = false
}
}).call(this,require('_process'))
},{"_process":2}],60:[function(require,module,exports){
(function (process,global){
/*!
* @overview es6-promise - a tiny implementation of Promises/A+.
* @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
* @license Licensed under MIT license
* See https://raw.githubusercontent.com/jakearchibald/es6-promise/master/LICENSE
* @version 3.2.1
*/
(function() {
"use strict";
function lib$es6$promise$utils$$objectOrFunction(x) {
return typeof x === 'function' || (typeof x === 'object' && x !== null);
}
function lib$es6$promise$utils$$isFunction(x) {
return typeof x === 'function';
}
function lib$es6$promise$utils$$isMaybeThenable(x) {
return typeof x === 'object' && x !== null;
}
var lib$es6$promise$utils$$_isArray;
if (!Array.isArray) {
lib$es6$promise$utils$$_isArray = function (x) {
return Object.prototype.toString.call(x) === '[object Array]';
};
} else {
lib$es6$promise$utils$$_isArray = Array.isArray;
}
var lib$es6$promise$utils$$isArray = lib$es6$promise$utils$$_isArray;
var lib$es6$promise$asap$$len = 0;
var lib$es6$promise$asap$$vertxNext;
var lib$es6$promise$asap$$customSchedulerFn;
var lib$es6$promise$asap$$asap = function asap(callback, arg) {
lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len] = callback;
lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len + 1] = arg;
lib$es6$promise$asap$$len += 2;
if (lib$es6$promise$asap$$len === 2) {
// If len is 2, that means that we need to schedule an async flush.
// If additional callbacks are queued before the queue is flushed, they
// will be processed by this flush that we are scheduling.
if (lib$es6$promise$asap$$customSchedulerFn) {
lib$es6$promise$asap$$customSchedulerFn(lib$es6$promise$asap$$flush);
} else {
lib$es6$promise$asap$$scheduleFlush();
}
}
}
function lib$es6$promise$asap$$setScheduler(scheduleFn) {
lib$es6$promise$asap$$customSchedulerFn = scheduleFn;
}
function lib$es6$promise$asap$$setAsap(asapFn) {
lib$es6$promise$asap$$asap = asapFn;
}
var lib$es6$promise$asap$$browserWindow = (typeof window !== 'undefined') ? window : undefined;
var lib$es6$promise$asap$$browserGlobal = lib$es6$promise$asap$$browserWindow || {};
var lib$es6$promise$asap$$BrowserMutationObserver = lib$es6$promise$asap$$browserGlobal.MutationObserver || lib$es6$promise$asap$$browserGlobal.WebKitMutationObserver;
var lib$es6$promise$asap$$isNode = typeof self === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';
// test for web worker but not in IE10
var lib$es6$promise$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' &&
typeof importScripts !== 'undefined' &&
typeof MessageChannel !== 'undefined';
// node
function lib$es6$promise$asap$$useNextTick() {
// node version 0.10.x displays a deprecation warning when nextTick is used recursively
// see https://github.com/cujojs/when/issues/410 for details
return function() {
process.nextTick(lib$es6$promise$asap$$flush);
};
}
// vertx
function lib$es6$promise$asap$$useVertxTimer() {
return function() {
lib$es6$promise$asap$$vertxNext(lib$es6$promise$asap$$flush);
};
}
function lib$es6$promise$asap$$useMutationObserver() {
var iterations = 0;
var observer = new lib$es6$promise$asap$$BrowserMutationObserver(lib$es6$promise$asap$$flush);
var node = document.createTextNode('');
observer.observe(node, { characterData: true });
return function() {
node.data = (iterations = ++iterations % 2);
};
}
// web worker
function lib$es6$promise$asap$$useMessageChannel() {
var channel = new MessageChannel();
channel.port1.onmessage = lib$es6$promise$asap$$flush;
return function () {
channel.port2.postMessage(0);
};
}
function lib$es6$promise$asap$$useSetTimeout() {
return function() {
setTimeout(lib$es6$promise$asap$$flush, 1);
};
}
var lib$es6$promise$asap$$queue = new Array(1000);
function lib$es6$promise$asap$$flush() {
for (var i = 0; i < lib$es6$promise$asap$$len; i+=2) {
var callback = lib$es6$promise$asap$$queue[i];
var arg = lib$es6$promise$asap$$queue[i+1];
callback(arg);
lib$es6$promise$asap$$queue[i] = undefined;
lib$es6$promise$asap$$queue[i+1] = undefined;
}
lib$es6$promise$asap$$len = 0;
}
function lib$es6$promise$asap$$attemptVertx() {
try {
var r = require;
var vertx = r('vertx');
lib$es6$promise$asap$$vertxNext = vertx.runOnLoop || vertx.runOnContext;
return lib$es6$promise$asap$$useVertxTimer();
} catch(e) {
return lib$es6$promise$asap$$useSetTimeout();
}
}
var lib$es6$promise$asap$$scheduleFlush;
// Decide what async method to use to triggering processing of queued callbacks:
if (lib$es6$promise$asap$$isNode) {
lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useNextTick();
} else if (lib$es6$promise$asap$$BrowserMutationObserver) {
lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useMutationObserver();
} else if (lib$es6$promise$asap$$isWorker) {
lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useMessageChannel();
} else if (lib$es6$promise$asap$$browserWindow === undefined && typeof require === 'function') {
lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$attemptVertx();
} else {
lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useSetTimeout();
}
function lib$es6$promise$then$$then(onFulfillment, onRejection) {
var parent = this;
var child = new this.constructor(lib$es6$promise$$internal$$noop);
if (child[lib$es6$promise$$internal$$PROMISE_ID] === undefined) {
lib$es6$promise$$internal$$makePromise(child);
}
var state = parent._state;
if (state) {
var callback = arguments[state - 1];
lib$es6$promise$asap$$asap(function(){
lib$es6$promise$$internal$$invokeCallback(state, child, callback, parent._result);
});
} else {
lib$es6$promise$$internal$$subscribe(parent, child, onFulfillment, onRejection);
}
return child;
}
var lib$es6$promise$then$$default = lib$es6$promise$then$$then;
function lib$es6$promise$promise$resolve$$resolve(object) {
/*jshint validthis:true */
var Constructor = this;
if (object && typeof object === 'object' && object.constructor === Constructor) {
return object;
}
var promise = new Constructor(lib$es6$promise$$internal$$noop);
lib$es6$promise$$internal$$resolve(promise, object);
return promise;
}
var lib$es6$promise$promise$resolve$$default = lib$es6$promise$promise$resolve$$resolve;
var lib$es6$promise$$internal$$PROMISE_ID = Math.random().toString(36).substring(16);
function lib$es6$promise$$internal$$noop() {}
var lib$es6$promise$$internal$$PENDING = void 0;
var lib$es6$promise$$internal$$FULFILLED = 1;
var lib$es6$promise$$internal$$REJECTED = 2;
var lib$es6$promise$$internal$$GET_THEN_ERROR = new lib$es6$promise$$internal$$ErrorObject();
function lib$es6$promise$$internal$$selfFulfillment() {
return new TypeError("You cannot resolve a promise with itself");
}
function lib$es6$promise$$internal$$cannotReturnOwn() {
return new TypeError('A promises callback cannot return that same promise.');
}
function lib$es6$promise$$internal$$getThen(promise) {
try {
return promise.then;
} catch(error) {
lib$es6$promise$$internal$$GET_THEN_ERROR.error = error;
return lib$es6$promise$$internal$$GET_THEN_ERROR;
}
}
function lib$es6$promise$$internal$$tryThen(then, value, fulfillmentHandler, rejectionHandler) {
try {
then.call(value, fulfillmentHandler, rejectionHandler);
} catch(e) {
return e;
}
}
function lib$es6$promise$$internal$$handleForeignThenable(promise, thenable, then) {
lib$es6$promise$asap$$asap(function(promise) {
var sealed = false;
var error = lib$es6$promise$$internal$$tryThen(then, thenable, function(value) {
if (sealed) { return; }
sealed = true;
if (thenable !== value) {
lib$es6$promise$$internal$$resolve(promise, value);
} else {
lib$es6$promise$$internal$$fulfill(promise, value);
}
}, function(reason) {
if (sealed) { return; }
sealed = true;
lib$es6$promise$$internal$$reject(promise, reason);
}, 'Settle: ' + (promise._label || ' unknown promise'));
if (!sealed && error) {
sealed = true;
lib$es6$promise$$internal$$reject(promise, error);
}
}, promise);
}
function lib$es6$promise$$internal$$handleOwnThenable(promise, thenable) {
if (thenable._state === lib$es6$promise$$internal$$FULFILLED) {
lib$es6$promise$$internal$$fulfill(promise, thenable._result);
} else if (thenable._state === lib$es6$promise$$internal$$REJECTED) {
lib$es6$promise$$internal$$reject(promise, thenable._result);
} else {
lib$es6$promise$$internal$$subscribe(thenable, undefined, function(value) {
lib$es6$promise$$internal$$resolve(promise, value);
}, function(reason) {
lib$es6$promise$$internal$$reject(promise, reason);
});
}
}
function lib$es6$promise$$internal$$handleMaybeThenable(promise, maybeThenable, then) {
if (maybeThenable.constructor === promise.constructor &&
then === lib$es6$promise$then$$default &&
constructor.resolve === lib$es6$promise$promise$resolve$$default) {
lib$es6$promise$$internal$$handleOwnThenable(promise, maybeThenable);
} else {
if (then === lib$es6$promise$$internal$$GET_THEN_ERROR) {
lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$GET_THEN_ERROR.error);
} else if (then === undefined) {
lib$es6$promise$$internal$$fulfill(promise, maybeThenable);
} else if (lib$es6$promise$utils$$isFunction(then)) {
lib$es6$promise$$internal$$handleForeignThenable(promise, maybeThenable, then);
} else {
lib$es6$promise$$internal$$fulfill(promise, maybeThenable);
}
}
}
function lib$es6$promise$$internal$$resolve(promise, value) {
if (promise === value) {
lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$selfFulfillment());
} else if (lib$es6$promise$utils$$objectOrFunction(value)) {
lib$es6$promise$$internal$$handleMaybeThenable(promise, value, lib$es6$promise$$internal$$getThen(value));
} else {
lib$es6$promise$$internal$$fulfill(promise, value);
}
}
function lib$es6$promise$$internal$$publishRejection(promise) {
if (promise._onerror) {
promise._onerror(promise._result);
}
lib$es6$promise$$internal$$publish(promise);
}
function lib$es6$promise$$internal$$fulfill(promise, value) {
if (promise._state !== lib$es6$promise$$internal$$PENDING) { return; }
promise._result = value;
promise._state = lib$es6$promise$$internal$$FULFILLED;
if (promise._subscribers.length !== 0) {
lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish, promise);
}
}
function lib$es6$promise$$internal$$reject(promise, reason) {
if (promise._state !== lib$es6$promise$$internal$$PENDING) { return; }
promise._state = lib$es6$promise$$internal$$REJECTED;
promise._result = reason;
lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publishRejection, promise);
}
function lib$es6$promise$$internal$$subscribe(parent, child, onFulfillment, onRejection) {
var subscribers = parent._subscribers;
var length = subscribers.length;
parent._onerror = null;
subscribers[length] = child;
subscribers[length + lib$es6$promise$$internal$$FULFILLED] = onFulfillment;
subscribers[length + lib$es6$promise$$internal$$REJECTED] = onRejection;
if (length === 0 && parent._state) {
lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish, parent);
}
}
function lib$es6$promise$$internal$$publish(promise) {
var subscribers = promise._subscribers;
var settled = promise._state;
if (subscribers.length === 0) { return; }
var child, callback, detail = promise._result;
for (var i = 0; i < subscribers.length; i += 3) {
child = subscribers[i];
callback = subscribers[i + settled];
if (child) {
lib$es6$promise$$internal$$invokeCallback(settled, child, callback, detail);
} else {
callback(detail);
}
}
promise._subscribers.length = 0;
}
function lib$es6$promise$$internal$$ErrorObject() {
this.error = null;
}
var lib$es6$promise$$internal$$TRY_CATCH_ERROR = new lib$es6$promise$$internal$$ErrorObject();
function lib$es6$promise$$internal$$tryCatch(callback, detail) {
try {
return callback(detail);
} catch(e) {
lib$es6$promise$$internal$$TRY_CATCH_ERROR.error = e;
return lib$es6$promise$$internal$$TRY_CATCH_ERROR;
}
}
function lib$es6$promise$$internal$$invokeCallback(settled, promise, callback, detail) {
var hasCallback = lib$es6$promise$utils$$isFunction(callback),
value, error, succeeded, failed;
if (hasCallback) {
value = lib$es6$promise$$internal$$tryCatch(callback, detail);
if (value === lib$es6$promise$$internal$$TRY_CATCH_ERROR) {
failed = true;
error = value.error;
value = null;
} else {
succeeded = true;
}
if (promise === value) {
lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$cannotReturnOwn());
return;
}
} else {
value = detail;
succeeded = true;
}
if (promise._state !== lib$es6$promise$$internal$$PENDING) {
// noop
} else if (hasCallback && succeeded) {
lib$es6$promise$$internal$$resolve(promise, value);
} else if (failed) {
lib$es6$promise$$internal$$reject(promise, error);
} else if (settled === lib$es6$promise$$internal$$FULFILLED) {
lib$es6$promise$$internal$$fulfill(promise, value);
} else if (settled === lib$es6$promise$$internal$$REJECTED) {
lib$es6$promise$$internal$$reject(promise, value);
}
}
function lib$es6$promise$$internal$$initializePromise(promise, resolver) {
try {
resolver(function resolvePromise(value){
lib$es6$promise$$internal$$resolve(promise, value);
}, function rejectPromise(reason) {
lib$es6$promise$$internal$$reject(promise, reason);
});
} catch(e) {
lib$es6$promise$$internal$$reject(promise, e);
}
}
var lib$es6$promise$$internal$$id = 0;
function lib$es6$promise$$internal$$nextId() {
return lib$es6$promise$$internal$$id++;
}
function lib$es6$promise$$internal$$makePromise(promise) {
promise[lib$es6$promise$$internal$$PROMISE_ID] = lib$es6$promise$$internal$$id++;
promise._state = undefined;
promise._result = undefined;
promise._subscribers = [];
}
function lib$es6$promise$promise$all$$all(entries) {
return new lib$es6$promise$enumerator$$default(this, entries).promise;
}
var lib$es6$promise$promise$all$$default = lib$es6$promise$promise$all$$all;
function lib$es6$promise$promise$race$$race(entries) {
/*jshint validthis:true */
var Constructor = this;
if (!lib$es6$promise$utils$$isArray(entries)) {
return new Constructor(function(resolve, reject) {
reject(new TypeError('You must pass an array to race.'));
});
} else {
return new Constructor(function(resolve, reject) {
var length = entries.length;
for (var i = 0; i < length; i++) {
Constructor.resolve(entries[i]).then(resolve, reject);
}
});
}
}
var lib$es6$promise$promise$race$$default = lib$es6$promise$promise$race$$race;
function lib$es6$promise$promise$reject$$reject(reason) {
/*jshint validthis:true */
var Constructor = this;
var promise = new Constructor(lib$es6$promise$$internal$$noop);
lib$es6$promise$$internal$$reject(promise, reason);
return promise;
}
var lib$es6$promise$promise$reject$$default = lib$es6$promise$promise$reject$$reject;
function lib$es6$promise$promise$$needsResolver() {
throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
}
function lib$es6$promise$promise$$needsNew() {
throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
}
var lib$es6$promise$promise$$default = lib$es6$promise$promise$$Promise;
/**
Promise objects represent the eventual result of an asynchronous operation. The
primary way of interacting with a promise is through its `then` method, which
registers callbacks to receive either a promise's eventual value or the reason
why the promise cannot be fulfilled.
Terminology
-----------
- `promise` is an object or function with a `then` method whose behavior conforms to this specification.
- `thenable` is an object or function that defines a `then` method.
- `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
- `exception` is a value that is thrown using the throw statement.
- `reason` is a value that indicates why a promise was rejected.
- `settled` the final resting state of a promise, fulfilled or rejected.
A promise can be in one of three states: pending, fulfilled, or rejected.
Promises that are fulfilled have a fulfillment value and are in the fulfilled
state. Promises that are rejected have a rejection reason and are in the
rejected state. A fulfillment value is never a thenable.
Promises can also be said to *resolve* a value. If this value is also a
promise, then the original promise's settled state will match the value's
settled state. So a promise that *resolves* a promise that rejects will
itself reject, and a promise that *resolves* a promise that fulfills will
itself fulfill.
Basic Usage:
------------
```js
var promise = new Promise(function(resolve, reject) {
// on success
resolve(value);
// on failure
reject(reason);
});
promise.then(function(value) {
// on fulfillment
}, function(reason) {
// on rejection
});
```
Advanced Usage:
---------------
Promises shine when abstracting away asynchronous interactions such as
`XMLHttpRequest`s.
```js
function getJSON(url) {
return new Promise(function(resolve, reject){
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onreadystatechange = handler;
xhr.responseType = 'json';
xhr.setRequestHeader('Accept', 'application/json');
xhr.send();
function handler() {
if (this.readyState === this.DONE) {
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
}
}
};
});
}
getJSON('/posts.json').then(function(json) {
// on fulfillment
}, function(reason) {
// on rejection
});
```
Unlike callbacks, promises are great composable primitives.
```js
Promise.all([
getJSON('/posts'),
getJSON('/comments')
]).then(function(values){
values[0] // => postsJSON
values[1] // => commentsJSON
return values;
});
```
@class Promise
@param {function} resolver
Useful for tooling.
@constructor
*/
function lib$es6$promise$promise$$Promise(resolver) {
this[lib$es6$promise$$internal$$PROMISE_ID] = lib$es6$promise$$internal$$nextId();
this._result = this._state = undefined;
this._subscribers = [];
if (lib$es6$promise$$internal$$noop !== resolver) {
typeof resolver !== 'function' && lib$es6$promise$promise$$needsResolver();
this instanceof lib$es6$promise$promise$$Promise ? lib$es6$promise$$internal$$initializePromise(this, resolver) : lib$es6$promise$promise$$needsNew();
}
}
lib$es6$promise$promise$$Promise.all = lib$es6$promise$promise$all$$default;
lib$es6$promise$promise$$Promise.race = lib$es6$promise$promise$race$$default;
lib$es6$promise$promise$$Promise.resolve = lib$es6$promise$promise$resolve$$default;
lib$es6$promise$promise$$Promise.reject = lib$es6$promise$promise$reject$$default;
lib$es6$promise$promise$$Promise._setScheduler = lib$es6$promise$asap$$setScheduler;
lib$es6$promise$promise$$Promise._setAsap = lib$es6$promise$asap$$setAsap;
lib$es6$promise$promise$$Promise._asap = lib$es6$promise$asap$$asap;
lib$es6$promise$promise$$Promise.prototype = {
constructor: lib$es6$promise$promise$$Promise,
/**
The primary way of interacting with a promise is through its `then` method,
which registers callbacks to receive either a promise's eventual value or the
reason why the promise cannot be fulfilled.
```js
findUser().then(function(user){
// user is available
}, function(reason){
// user is unavailable, and you are given the reason why
});
```
Chaining
--------
The return value of `then` is itself a promise. This second, 'downstream'
promise is resolved with the return value of the first promise's fulfillment
or rejection handler, or rejected if the handler throws an exception.
```js
findUser().then(function (user) {
return user.name;
}, function (reason) {
return 'default name';
}).then(function (userName) {
// If `findUser` fulfilled, `userName` will be the user's name, otherwise it
// will be `'default name'`
});
findUser().then(function (user) {
throw new Error('Found user, but still unhappy');
}, function (reason) {
throw new Error('`findUser` rejected and we're unhappy');
}).then(function (value) {
// never reached
}, function (reason) {
// if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
// If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
});
```
If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
```js
findUser().then(function (user) {
throw new PedagogicalException('Upstream error');
}).then(function (value) {
// never reached
}).then(function (value) {
// never reached
}, function (reason) {
// The `PedgagocialException` is propagated all the way down to here
});
```
Assimilation
------------
Sometimes the value you want to propagate to a downstream promise can only be
retrieved asynchronously. This can be achieved by returning a promise in the
fulfillment or rejection handler. The downstream promise will then be pending
until the returned promise is settled. This is called *assimilation*.
```js
findUser().then(function (user) {
return findCommentsByAuthor(user);
}).then(function (comments) {
// The user's comments are now available
});
```
If the assimliated promise rejects, then the downstream promise will also reject.
```js
findUser().then(function (user) {
return findCommentsByAuthor(user);
}).then(function (comments) {
// If `findCommentsByAuthor` fulfills, we'll have the value here
}, function (reason) {
// If `findCommentsByAuthor` rejects, we'll have the reason here
});
```
Simple Example
--------------
Synchronous Example
```javascript
var result;
try {
result = findResult();
// success
} catch(reason) {
// failure
}
```
Errback Example
```js
findResult(function(result, err){
if (err) {
// failure
} else {
// success
}
});
```
Promise Example;
```javascript
findResult().then(function(result){
// success
}, function(reason){
// failure
});
```
Advanced Example
--------------
Synchronous Example
```javascript
var author, books;
try {
author = findAuthor();
books = findBooksByAuthor(author);
// success
} catch(reason) {
// failure
}
```
Errback Example
```js
function foundBooks(books) {
}
function failure(reason) {
}
findAuthor(function(author, err){
if (err) {
failure(err);
// failure
} else {
try {
findBoooksByAuthor(author, function(books, err) {
if (err) {
failure(err);
} else {
try {
foundBooks(books);
} catch(reason) {
failure(reason);
}
}
});
} catch(error) {
failure(err);
}
// success
}
});
```
Promise Example;
```javascript
findAuthor().
then(findBooksByAuthor).
then(function(books){
// found books
}).catch(function(reason){
// something went wrong
});
```
@method then
@param {Function} onFulfilled
@param {Function} onRejected
Useful for tooling.
@return {Promise}
*/
then: lib$es6$promise$then$$default,
/**
`catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
as the catch block of a try/catch statement.
```js
function findAuthor(){
throw new Error('couldn't find that author');
}
// synchronous
try {
findAuthor();
} catch(reason) {
// something went wrong
}
// async with promises
findAuthor().catch(function(reason){
// something went wrong
});
```
@method catch
@param {Function} onRejection
Useful for tooling.
@return {Promise}
*/
'catch': function(onRejection) {
return this.then(null, onRejection);
}
};
var lib$es6$promise$enumerator$$default = lib$es6$promise$enumerator$$Enumerator;
function lib$es6$promise$enumerator$$Enumerator(Constructor, input) {
this._instanceConstructor = Constructor;
this.promise = new Constructor(lib$es6$promise$$internal$$noop);
if (!this.promise[lib$es6$promise$$internal$$PROMISE_ID]) {
lib$es6$promise$$internal$$makePromise(this.promise);
}
if (lib$es6$promise$utils$$isArray(input)) {
this._input = input;
this.length = input.length;
this._remaining = input.length;
this._result = new Array(this.length);
if (this.length === 0) {
lib$es6$promise$$internal$$fulfill(this.promise, this._result);
} else {
this.length = this.length || 0;
this._enumerate();
if (this._remaining === 0) {
lib$es6$promise$$internal$$fulfill(this.promise, this._result);
}
}
} else {
lib$es6$promise$$internal$$reject(this.promise, lib$es6$promise$enumerator$$validationError());
}
}
function lib$es6$promise$enumerator$$validationError() {
return new Error('Array Methods must be provided an Array');
}
lib$es6$promise$enumerator$$Enumerator.prototype._enumerate = function() {
var length = this.length;
var input = this._input;
for (var i = 0; this._state === lib$es6$promise$$internal$$PENDING && i < length; i++) {
this._eachEntry(input[i], i);
}
};
lib$es6$promise$enumerator$$Enumerator.prototype._eachEntry = function(entry, i) {
var c = this._instanceConstructor;
var resolve = c.resolve;
if (resolve === lib$es6$promise$promise$resolve$$default) {
var then = lib$es6$promise$$internal$$getThen(entry);
if (then === lib$es6$promise$then$$default &&
entry._state !== lib$es6$promise$$internal$$PENDING) {
this._settledAt(entry._state, i, entry._result);
} else if (typeof then !== 'function') {
this._remaining--;
this._result[i] = entry;
} else if (c === lib$es6$promise$promise$$default) {
var promise = new c(lib$es6$promise$$internal$$noop);
lib$es6$promise$$internal$$handleMaybeThenable(promise, entry, then);
this._willSettleAt(promise, i);
} else {
this._willSettleAt(new c(function(resolve) { resolve(entry); }), i);
}
} else {
this._willSettleAt(resolve(entry), i);
}
};
lib$es6$promise$enumerator$$Enumerator.prototype._settledAt = function(state, i, value) {
var promise = this.promise;
if (promise._state === lib$es6$promise$$internal$$PENDING) {
this._remaining--;
if (state === lib$es6$promise$$internal$$REJECTED) {
lib$es6$promise$$internal$$reject(promise, value);
} else {
this._result[i] = value;
}
}
if (this._remaining === 0) {
lib$es6$promise$$internal$$fulfill(promise, this._result);
}
};
lib$es6$promise$enumerator$$Enumerator.prototype._willSettleAt = function(promise, i) {
var enumerator = this;
lib$es6$promise$$internal$$subscribe(promise, undefined, function(value) {
enumerator._settledAt(lib$es6$promise$$internal$$FULFILLED, i, value);
}, function(reason) {
enumerator._settledAt(lib$es6$promise$$internal$$REJECTED, i, reason);
});
};
function lib$es6$promise$polyfill$$polyfill() {
var local;
if (typeof global !== 'undefined') {
local = global;
} else if (typeof self !== 'undefined') {
local = self;
} else {
try {
local = Function('return this')();
} catch (e) {
throw new Error('polyfill failed because global object is unavailable in this environment');
}
}
var P = local.Promise;
if (P && Object.prototype.toString.call(P.resolve()) === '[object Promise]' && !P.cast) {
return;
}
local.Promise = lib$es6$promise$promise$$default;
}
var lib$es6$promise$polyfill$$default = lib$es6$promise$polyfill$$polyfill;
var lib$es6$promise$umd$$ES6Promise = {
'Promise': lib$es6$promise$promise$$default,
'polyfill': lib$es6$promise$polyfill$$default
};
/* global define:true module:true window: true */
if (typeof define === 'function' && define['amd']) {
define(function() { return lib$es6$promise$umd$$ES6Promise; });
} else if (typeof module !== 'undefined' && module['exports']) {
module['exports'] = lib$es6$promise$umd$$ES6Promise;
} else if (typeof this !== 'undefined') {
this['ES6Promise'] = lib$es6$promise$umd$$ES6Promise;
}
lib$es6$promise$polyfill$$default();
}).call(this);
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"_process":2}],61:[function(require,module,exports){
(function (global){
/**
* lodash (Custom Build) <https://lodash.com/>
* Build: `lodash modularize exports="npm" -o ./`
* Copyright jQuery Foundation and other contributors <https://jquery.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
/** Used as the `TypeError` message for "Functions" methods. */
var FUNC_ERROR_TEXT = 'Expected a function';
/** Used as references for various `Number` constants. */
var NAN = 0 / 0;
/** `Object#toString` result references. */
var symbolTag = '[object Symbol]';
/** Used to match leading and trailing whitespace. */
var reTrim = /^\s+|\s+$/g;
/** Used to detect bad signed hexadecimal string values. */
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
/** Used to detect binary string values. */
var reIsBinary = /^0b[01]+$/i;
/** Used to detect octal string values. */
var reIsOctal = /^0o[0-7]+$/i;
/** Built-in method references without a dependency on `root`. */
var freeParseInt = parseInt;
/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();
/** Used for built-in method references. */
var objectProto = Object.prototype;
/**
* Used to resolve the
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
* of values.
*/
var objectToString = objectProto.toString;
/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeMax = Math.max,
nativeMin = Math.min;
/**
* Gets the timestamp of the number of milliseconds that have elapsed since
* the Unix epoch (1 January 1970 00:00:00 UTC).
*
* @static
* @memberOf _
* @since 2.4.0
* @category Date
* @returns {number} Returns the timestamp.
* @example
*
* _.defer(function(stamp) {
* console.log(_.now() - stamp);
* }, _.now());
* // => Logs the number of milliseconds it took for the deferred invocation.
*/
var now = function() {
return root.Date.now();
};
/**
* Creates a debounced function that delays invoking `func` until after `wait`
* milliseconds have elapsed since the last time the debounced function was
* invoked. The debounced function comes with a `cancel` method to cancel
* delayed `func` invocations and a `flush` method to immediately invoke them.
* Provide `options` to indicate whether `func` should be invoked on the
* leading and/or trailing edge of the `wait` timeout. The `func` is invoked
* with the last arguments provided to the debounced function. Subsequent
* calls to the debounced function return the result of the last `func`
* invocation.
*
* **Note:** If `leading` and `trailing` options are `true`, `func` is
* invoked on the trailing edge of the timeout only if the debounced function
* is invoked more than once during the `wait` timeout.
*
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
*
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
* for details over the differences between `_.debounce` and `_.throttle`.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Function
* @param {Function} func The function to debounce.
* @param {number} [wait=0] The number of milliseconds to delay.
* @param {Object} [options={}] The options object.
* @param {boolean} [options.leading=false]
* Specify invoking on the leading edge of the timeout.
* @param {number} [options.maxWait]
* The maximum time `func` is allowed to be delayed before it's invoked.
* @param {boolean} [options.trailing=true]
* Specify invoking on the trailing edge of the timeout.
* @returns {Function} Returns the new debounced function.
* @example
*
* // Avoid costly calculations while the window size is in flux.
* jQuery(window).on('resize', _.debounce(calculateLayout, 150));
*
* // Invoke `sendMail` when clicked, debouncing subsequent calls.
* jQuery(element).on('click', _.debounce(sendMail, 300, {
* 'leading': true,
* 'trailing': false
* }));
*
* // Ensure `batchLog` is invoked once after 1 second of debounced calls.
* var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
* var source = new EventSource('/stream');
* jQuery(source).on('message', debounced);
*
* // Cancel the trailing debounced invocation.
* jQuery(window).on('popstate', debounced.cancel);
*/
function debounce(func, wait, options) {
var lastArgs,
lastThis,
maxWait,
result,
timerId,
lastCallTime,
lastInvokeTime = 0,
leading = false,
maxing = false,
trailing = true;
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
wait = toNumber(wait) || 0;
if (isObject(options)) {
leading = !!options.leading;
maxing = 'maxWait' in options;
maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
trailing = 'trailing' in options ? !!options.trailing : trailing;
}
function invokeFunc(time) {
var args = lastArgs,
thisArg = lastThis;
lastArgs = lastThis = undefined;
lastInvokeTime = time;
result = func.apply(thisArg, args);
return result;
}
function leadingEdge(time) {
// Reset any `maxWait` timer.
lastInvokeTime = time;
// Start the timer for the trailing edge.
timerId = setTimeout(timerExpired, wait);
// Invoke the leading edge.
return leading ? invokeFunc(time) : result;
}
function remainingWait(time) {
var timeSinceLastCall = time - lastCallTime,
timeSinceLastInvoke = time - lastInvokeTime,
result = wait - timeSinceLastCall;
return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
}
function shouldInvoke(time) {
var timeSinceLastCall = time - lastCallTime,
timeSinceLastInvoke = time - lastInvokeTime;
// Either this is the first call, activity has stopped and we're at the
// trailing edge, the system time has gone backwards and we're treating
// it as the trailing edge, or we've hit the `maxWait` limit.
return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
(timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
}
function timerExpired() {
var time = now();
if (shouldInvoke(time)) {
return trailingEdge(time);
}
// Restart the timer.
timerId = setTimeout(timerExpired, remainingWait(time));
}
function trailingEdge(time) {
timerId = undefined;
// Only invoke if we have `lastArgs` which means `func` has been
// debounced at least once.
if (trailing && lastArgs) {
return invokeFunc(time);
}
lastArgs = lastThis = undefined;
return result;
}
function cancel() {
if (timerId !== undefined) {
clearTimeout(timerId);
}
lastInvokeTime = 0;
lastArgs = lastCallTime = lastThis = timerId = undefined;
}
function flush() {
return timerId === undefined ? result : trailingEdge(now());
}
function debounced() {
var time = now(),
isInvoking = shouldInvoke(time);
lastArgs = arguments;
lastThis = this;
lastCallTime = time;
if (isInvoking) {
if (timerId === undefined) {
return leadingEdge(lastCallTime);
}
if (maxing) {
// Handle invocations in a tight loop.
timerId = setTimeout(timerExpired, wait);
return invokeFunc(lastCallTime);
}
}
if (timerId === undefined) {
timerId = setTimeout(timerExpired, wait);
}
return result;
}
debounced.cancel = cancel;
debounced.flush = flush;
return debounced;
}
/**
* Creates a throttled function that only invokes `func` at most once per
* every `wait` milliseconds. The throttled function comes with a `cancel`
* method to cancel delayed `func` invocations and a `flush` method to
* immediately invoke them. Provide `options` to indicate whether `func`
* should be invoked on the leading and/or trailing edge of the `wait`
* timeout. The `func` is invoked with the last arguments provided to the
* throttled function. Subsequent calls to the throttled function return the
* result of the last `func` invocation.
*
* **Note:** If `leading` and `trailing` options are `true`, `func` is
* invoked on the trailing edge of the timeout only if the throttled function
* is invoked more than once during the `wait` timeout.
*
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
*
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
* for details over the differences between `_.throttle` and `_.debounce`.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Function
* @param {Function} func The function to throttle.
* @param {number} [wait=0] The number of milliseconds to throttle invocations to.
* @param {Object} [options={}] The options object.
* @param {boolean} [options.leading=true]
* Specify invoking on the leading edge of the timeout.
* @param {boolean} [options.trailing=true]
* Specify invoking on the trailing edge of the timeout.
* @returns {Function} Returns the new throttled function.
* @example
*
* // Avoid excessively updating the position while scrolling.
* jQuery(window).on('scroll', _.throttle(updatePosition, 100));
*
* // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
* var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
* jQuery(element).on('click', throttled);
*
* // Cancel the trailing throttled invocation.
* jQuery(window).on('popstate', throttled.cancel);
*/
function throttle(func, wait, options) {
var leading = true,
trailing = true;
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
if (isObject(options)) {
leading = 'leading' in options ? !!options.leading : leading;
trailing = 'trailing' in options ? !!options.trailing : trailing;
}
return debounce(func, wait, {
'leading': leading,
'maxWait': wait,
'trailing': trailing
});
}
/**
* Checks if `value` is the
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an object, else `false`.
* @example
*
* _.isObject({});
* // => true
*
* _.isObject([1, 2, 3]);
* // => true
*
* _.isObject(_.noop);
* // => true
*
* _.isObject(null);
* // => false
*/
function isObject(value) {
var type = typeof value;
return !!value && (type == 'object' || type == 'function');
}
/**
* Checks if `value` is object-like. A value is object-like if it's not `null`
* and has a `typeof` result of "object".
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
* @example
*
* _.isObjectLike({});
* // => true
*
* _.isObjectLike([1, 2, 3]);
* // => true
*
* _.isObjectLike(_.noop);
* // => false
*
* _.isObjectLike(null);
* // => false
*/
function isObjectLike(value) {
return !!value && typeof value == 'object';
}
/**
* Checks if `value` is classified as a `Symbol` primitive or object.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
* @example
*
* _.isSymbol(Symbol.iterator);
* // => true
*
* _.isSymbol('abc');
* // => false
*/
function isSymbol(value) {
return typeof value == 'symbol' ||
(isObjectLike(value) && objectToString.call(value) == symbolTag);
}
/**
* Converts `value` to a number.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to process.
* @returns {number} Returns the number.
* @example
*
* _.toNumber(3.2);
* // => 3.2
*
* _.toNumber(Number.MIN_VALUE);
* // => 5e-324
*
* _.toNumber(Infinity);
* // => Infinity
*
* _.toNumber('3.2');
* // => 3.2
*/
function toNumber(value) {
if (typeof value == 'number') {
return value;
}
if (isSymbol(value)) {
return NAN;
}
if (isObject(value)) {
var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
value = isObject(other) ? (other + '') : other;
}
if (typeof value != 'string') {
return value === 0 ? value : +value;
}
value = value.replace(reTrim, '');
var isBinary = reIsBinary.test(value);
return (isBinary || reIsOctal.test(value))
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
: (reIsBadHex.test(value) ? NAN : +value);
}
module.exports = throttle;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],62:[function(require,module,exports){
/**
* Create an event emitter with namespaces
* @name createNamespaceEmitter
* @example
* var emitter = require('./index')()
*
* emitter.on('*', function () {
* console.log('all events emitted', this.event)
* })
*
* emitter.on('example', function () {
* console.log('example event emitted')
* })
*/
module.exports = function createNamespaceEmitter () {
var emitter = { _fns: {} }
/**
* Emit an event. Optionally namespace the event. Separate the namespace and event with a `:`
* @name emit
* @param {String} event – the name of the event, with optional namespace
* @param {...*} data – data variables that will be passed as arguments to the event listener
* @example
* emitter.emit('example')
* emitter.emit('demo:test')
* emitter.emit('data', { example: true}, 'a string', 1)
*/
emitter.emit = function emit (event) {
var args = [].slice.call(arguments, 1)
var namespaced = namespaces(event)
if (this._fns[event]) emitAll(event, this._fns[event], args)
if (namespaced) emitAll(event, namespaced, args)
}
/**
* Create en event listener.
* @name on
* @param {String} event
* @param {Function} fn
* @example
* emitter.on('example', function () {})
* emitter.on('demo', function () {})
*/
emitter.on = function on (event, fn) {
if (typeof fn !== 'function') { throw new Error('callback required') }
(this._fns[event] = this._fns[event] || []).push(fn)
}
/**
* Create en event listener that fires once.
* @name once
* @param {String} event
* @param {Function} fn
* @example
* emitter.once('example', function () {})
* emitter.once('demo', function () {})
*/
emitter.once = function once (event, fn) {
function one () {
fn.apply(this, arguments)
emitter.off(event, one)
}
this.on(event, one)
}
/**
* Stop listening to an event. Stop all listeners on an event by only passing the event name. Stop a single listener by passing that event handler as a callback.
* You must be explicit about what will be unsubscribed: `emitter.off('demo')` will unsubscribe an `emitter.on('demo')` listener,
* `emitter.off('demo:example')` will unsubscribe an `emitter.on('demo:example')` listener
* @name off
* @param {String} event
* @param {Function} [fn] – the specific handler
* @example
* emitter.off('example')
* emitter.off('demo', function () {})
*/
emitter.off = function off (event, fn) {
var keep = []
if (event && fn) {
for (var i = 0; i < this._fns.length; i++) {
if (this._fns[i] !== fn) {
keep.push(this._fns[i])
}
}
}
keep.length ? this._fns[event] = keep : delete this._fns[event]
}
function namespaces (e) {
var out = []
var args = e.split(':')
var fns = emitter._fns
Object.keys(fns).forEach(function (key) {
if (key === '*') out = out.concat(fns[key])
if (args.length === 2 && args[0] === key) out = out.concat(fns[key])
})
return out
}
function emitAll (e, fns, args) {
for (var i = 0; i < fns.length; i++) {
if (!fns[i]) break
fns[i].event = e
fns[i].apply(fns[i], args)
}
}
return emitter
}
},{}],63:[function(require,module,exports){
/* global MutationObserver */
var document = require('global/document')
var window = require('global/window')
var watch = Object.create(null)
var KEY_ID = 'onloadid' + (new Date() % 9e6).toString(36)
var KEY_ATTR = 'data-' + KEY_ID
var INDEX = 0
if (window && window.MutationObserver) {
var observer = new MutationObserver(function (mutations) {
if (Object.keys(watch).length < 1) return
for (var i = 0; i < mutations.length; i++) {
if (mutations[i].attributeName === KEY_ATTR) {
eachAttr(mutations[i], turnon, turnoff)
continue
}
eachMutation(mutations[i].removedNodes, turnoff)
eachMutation(mutations[i].addedNodes, turnon)
}
})
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeOldValue: true,
attributeFilter: [KEY_ATTR]
})
}
module.exports = function onload (el, on, off, caller) {
on = on || function () {}
off = off || function () {}
el.setAttribute(KEY_ATTR, 'o' + INDEX)
watch['o' + INDEX] = [on, off, 0, caller || onload.caller]
INDEX += 1
return el
}
function turnon (index, el) {
if (watch[index][0] && watch[index][2] === 0) {
watch[index][0](el)
watch[index][2] = 1
}
}
function turnoff (index, el) {
if (watch[index][1] && watch[index][2] === 1) {
watch[index][1](el)
watch[index][2] = 0
}
}
function eachAttr (mutation, on, off) {
var newValue = mutation.target.getAttribute(KEY_ATTR)
if (sameOrigin(mutation.oldValue, newValue)) {
watch[newValue] = watch[mutation.oldValue]
return
}
if (watch[mutation.oldValue]) {
off(mutation.oldValue, mutation.target)
}
if (watch[newValue]) {
on(newValue, mutation.target)
}
}
function sameOrigin (oldValue, newValue) {
if (!oldValue || !newValue) return false
return watch[oldValue][3] === watch[newValue][3]
}
function eachMutation (nodes, fn) {
var keys = Object.keys(watch)
for (var i = 0; i < nodes.length; i++) {
if (nodes[i] && nodes[i].getAttribute && nodes[i].getAttribute(KEY_ATTR)) {
var onloadid = nodes[i].getAttribute(KEY_ATTR)
keys.forEach(function (k) {
if (onloadid === k) {
fn(k, nodes[i])
}
})
}
if (nodes[i].childNodes.length > 0) {
eachMutation(nodes[i].childNodes, fn)
}
}
}
},{"global/document":64,"global/window":65}],64:[function(require,module,exports){
(function (global){
var topLevel = typeof global !== 'undefined' ? global :
typeof window !== 'undefined' ? window : {}
var minDoc = require('min-document');
var doccy;
if (typeof document !== 'undefined') {
doccy = document;
} else {
doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];
if (!doccy) {
doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;
}
}
module.exports = doccy;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"min-document":1}],65:[function(require,module,exports){
(function (global){
var win;
if (typeof window !== "undefined") {
win = window;
} else if (typeof global !== "undefined") {
win = global;
} else if (typeof self !== "undefined"){
win = self;
} else {
win = {};
}
module.exports = win;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],66:[function(require,module,exports){
module.exports = prettierBytes
function prettierBytes (num) {
if (typeof num !== 'number' || Number.isNaN(num)) {
throw new TypeError('Expected a number, got ' + typeof num)
}
var neg = num < 0
var units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
if (neg) {
num = -num
}
if (num < 1) {
return (neg ? '-' : '') + num + ' B'
}
var exponent = Math.min(Math.floor(Math.log(num) / Math.log(1000)), units.length - 1)
num = Number(num / Math.pow(1000, exponent))
var unit = units[exponent]
if (num >= 10 || num % 1 === 0) {
// Do not show decimals when the number is two-digit, or if the number has no
// decimal component.
return (neg ? '-' : '') + num.toFixed(0) + ' ' + unit
} else {
return (neg ? '-' : '') + num.toFixed(1) + ' ' + unit
}
}
},{}],67:[function(require,module,exports){
/**
* Module dependencies.
*/
var url = require('./url');
var parser = require('socket.io-parser');
var Manager = require('./manager');
var debug = require('debug')('socket.io-client');
/**
* Module exports.
*/
module.exports = exports = lookup;
/**
* Managers cache.
*/
var cache = exports.managers = {};
/**
* Looks up an existing `Manager` for multiplexing.
* If the user summons:
*
* `io('http://localhost/a');`
* `io('http://localhost/b');`
*
* We reuse the existing instance based on same scheme/port/host,
* and we initialize sockets for each namespace.
*
* @api public
*/
function lookup (uri, opts) {
if (typeof uri === 'object') {
opts = uri;
uri = undefined;
}
opts = opts || {};
var parsed = url(uri);
var source = parsed.source;
var id = parsed.id;
var path = parsed.path;
var sameNamespace = cache[id] && path in cache[id].nsps;
var newConnection = opts.forceNew || opts['force new connection'] ||
false === opts.multiplex || sameNamespace;
var io;
if (newConnection) {
debug('ignoring socket cache for %s', source);
io = Manager(source, opts);
} else {
if (!cache[id]) {
debug('new io instance for %s', source);
cache[id] = Manager(source, opts);
}
io = cache[id];
}
if (parsed.query && !opts.query) {
opts.query = parsed.query;
} else if (opts && 'object' === typeof opts.query) {
opts.query = encodeQueryString(opts.query);
}
return io.socket(parsed.path, opts);
}
/**
* Helper method to parse query objects to string.
* @param {object} query
* @returns {string}
*/
function encodeQueryString (obj) {
var str = [];
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]));
}
}
return str.join('&');
}
/**
* Protocol version.
*
* @api public
*/
exports.protocol = parser.protocol;
/**
* `connect`.
*
* @param {String} uri
* @api public
*/
exports.connect = lookup;
/**
* Expose constructors for standalone build.
*
* @api public
*/
exports.Manager = require('./manager');
exports.Socket = require('./socket');
},{"./manager":68,"./socket":70,"./url":71,"debug":77,"socket.io-parser":105}],68:[function(require,module,exports){
/**
* Module dependencies.
*/
var eio = require('engine.io-client');
var Socket = require('./socket');
var Emitter = require('component-emitter');
var parser = require('socket.io-parser');
var on = require('./on');
var bind = require('component-bind');
var debug = require('debug')('socket.io-client:manager');
var indexOf = require('indexof');
var Backoff = require('backo2');
/**
* IE6+ hasOwnProperty
*/
var has = Object.prototype.hasOwnProperty;
/**
* Module exports
*/
module.exports = Manager;
/**
* `Manager` constructor.
*
* @param {String} engine instance or engine uri/opts
* @param {Object} options
* @api public
*/
function Manager (uri, opts) {
if (!(this instanceof Manager)) return new Manager(uri, opts);
if (uri && ('object' === typeof uri)) {
opts = uri;
uri = undefined;
}
opts = opts || {};
opts.path = opts.path || '/socket.io';
this.nsps = {};
this.subs = [];
this.opts = opts;
this.reconnection(opts.reconnection !== false);
this.reconnectionAttempts(opts.reconnectionAttempts || Infinity);
this.reconnectionDelay(opts.reconnectionDelay || 1000);
this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000);
this.randomizationFactor(opts.randomizationFactor || 0.5);
this.backoff = new Backoff({
min: this.reconnectionDelay(),
max: this.reconnectionDelayMax(),
jitter: this.randomizationFactor()
});
this.timeout(null == opts.timeout ? 20000 : opts.timeout);
this.readyState = 'closed';
this.uri = uri;
this.connecting = [];
this.lastPing = null;
this.encoding = false;
this.packetBuffer = [];
var _parser = opts.parser || parser;
this.encoder = new _parser.Encoder();
this.decoder = new _parser.Decoder();
this.autoConnect = opts.autoConnect !== false;
if (this.autoConnect) this.open();
}
/**
* Propagate given event to sockets and emit on `this`
*
* @api private
*/
Manager.prototype.emitAll = function () {
this.emit.apply(this, arguments);
for (var nsp in this.nsps) {
if (has.call(this.nsps, nsp)) {
this.nsps[nsp].emit.apply(this.nsps[nsp], arguments);
}
}
};
/**
* Update `socket.id` of all sockets
*
* @api private
*/
Manager.prototype.updateSocketIds = function () {
for (var nsp in this.nsps) {
if (has.call(this.nsps, nsp)) {
this.nsps[nsp].id = this.generateId(nsp);
}
}
};
/**
* generate `socket.id` for the given `nsp`
*
* @param {String} nsp
* @return {String}
* @api private
*/
Manager.prototype.generateId = function (nsp) {
return (nsp === '/' ? '' : (nsp + '#')) + this.engine.id;
};
/**
* Mix in `Emitter`.
*/
Emitter(Manager.prototype);
/**
* Sets the `reconnection` config.
*
* @param {Boolean} true/false if it should automatically reconnect
* @return {Manager} self or value
* @api public
*/
Manager.prototype.reconnection = function (v) {
if (!arguments.length) return this._reconnection;
this._reconnection = !!v;
return this;
};
/**
* Sets the reconnection attempts config.
*
* @param {Number} max reconnection attempts before giving up
* @return {Manager} self or value
* @api public
*/
Manager.prototype.reconnectionAttempts = function (v) {
if (!arguments.length) return this._reconnectionAttempts;
this._reconnectionAttempts = v;
return this;
};
/**
* Sets the delay between reconnections.
*
* @param {Number} delay
* @return {Manager} self or value
* @api public
*/
Manager.prototype.reconnectionDelay = function (v) {
if (!arguments.length) return this._reconnectionDelay;
this._reconnectionDelay = v;
this.backoff && this.backoff.setMin(v);
return this;
};
Manager.prototype.randomizationFactor = function (v) {
if (!arguments.length) return this._randomizationFactor;
this._randomizationFactor = v;
this.backoff && this.backoff.setJitter(v);
return this;
};
/**
* Sets the maximum delay between reconnections.
*
* @param {Number} delay
* @return {Manager} self or value
* @api public
*/
Manager.prototype.reconnectionDelayMax = function (v) {
if (!arguments.length) return this._reconnectionDelayMax;
this._reconnectionDelayMax = v;
this.backoff && this.backoff.setMax(v);
return this;
};
/**
* Sets the connection timeout. `false` to disable
*
* @return {Manager} self or value
* @api public
*/
Manager.prototype.timeout = function (v) {
if (!arguments.length) return this._timeout;
this._timeout = v;
return this;
};
/**
* Starts trying to reconnect if reconnection is enabled and we have not
* started reconnecting yet
*
* @api private
*/
Manager.prototype.maybeReconnectOnOpen = function () {
// Only try to reconnect if it's the first time we're connecting
if (!this.reconnecting && this._reconnection && this.backoff.attempts === 0) {
// keeps reconnection from firing twice for the same reconnection loop
this.reconnect();
}
};
/**
* Sets the current transport `socket`.
*
* @param {Function} optional, callback
* @return {Manager} self
* @api public
*/
Manager.prototype.open =
Manager.prototype.connect = function (fn, opts) {
debug('readyState %s', this.readyState);
if (~this.readyState.indexOf('open')) return this;
debug('opening %s', this.uri);
this.engine = eio(this.uri, this.opts);
var socket = this.engine;
var self = this;
this.readyState = 'opening';
this.skipReconnect = false;
// emit `open`
var openSub = on(socket, 'open', function () {
self.onopen();
fn && fn();
});
// emit `connect_error`
var errorSub = on(socket, 'error', function (data) {
debug('connect_error');
self.cleanup();
self.readyState = 'closed';
self.emitAll('connect_error', data);
if (fn) {
var err = new Error('Connection error');
err.data = data;
fn(err);
} else {
// Only do this if there is no fn to handle the error
self.maybeReconnectOnOpen();
}
});
// emit `connect_timeout`
if (false !== this._timeout) {
var timeout = this._timeout;
debug('connect attempt will timeout after %d', timeout);
// set timer
var timer = setTimeout(function () {
debug('connect attempt timed out after %d', timeout);
openSub.destroy();
socket.close();
socket.emit('error', 'timeout');
self.emitAll('connect_timeout', timeout);
}, timeout);
this.subs.push({
destroy: function () {
clearTimeout(timer);
}
});
}
this.subs.push(openSub);
this.subs.push(errorSub);
return this;
};
/**
* Called upon transport open.
*
* @api private
*/
Manager.prototype.onopen = function () {
debug('open');
// clear old subs
this.cleanup();
// mark as open
this.readyState = 'open';
this.emit('open');
// add new subs
var socket = this.engine;
this.subs.push(on(socket, 'data', bind(this, 'ondata')));
this.subs.push(on(socket, 'ping', bind(this, 'onping')));
this.subs.push(on(socket, 'pong', bind(this, 'onpong')));
this.subs.push(on(socket, 'error', bind(this, 'onerror')));
this.subs.push(on(socket, 'close', bind(this, 'onclose')));
this.subs.push(on(this.decoder, 'decoded', bind(this, 'ondecoded')));
};
/**
* Called upon a ping.
*
* @api private
*/
Manager.prototype.onping = function () {
this.lastPing = new Date();
this.emitAll('ping');
};
/**
* Called upon a packet.
*
* @api private
*/
Manager.prototype.onpong = function () {
this.emitAll('pong', new Date() - this.lastPing);
};
/**
* Called with data.
*
* @api private
*/
Manager.prototype.ondata = function (data) {
this.decoder.add(data);
};
/**
* Called when parser fully decodes a packet.
*
* @api private
*/
Manager.prototype.ondecoded = function (packet) {
this.emit('packet', packet);
};
/**
* Called upon socket error.
*
* @api private
*/
Manager.prototype.onerror = function (err) {
debug('error', err);
this.emitAll('error', err);
};
/**
* Creates a new socket for the given `nsp`.
*
* @return {Socket}
* @api public
*/
Manager.prototype.socket = function (nsp, opts) {
var socket = this.nsps[nsp];
if (!socket) {
socket = new Socket(this, nsp, opts);
this.nsps[nsp] = socket;
var self = this;
socket.on('connecting', onConnecting);
socket.on('connect', function () {
socket.id = self.generateId(nsp);
});
if (this.autoConnect) {
// manually call here since connecting event is fired before listening
onConnecting();
}
}
function onConnecting () {
if (!~indexOf(self.connecting, socket)) {
self.connecting.push(socket);
}
}
return socket;
};
/**
* Called upon a socket close.
*
* @param {Socket} socket
*/
Manager.prototype.destroy = function (socket) {
var index = indexOf(this.connecting, socket);
if (~index) this.connecting.splice(index, 1);
if (this.connecting.length) return;
this.close();
};
/**
* Writes a packet.
*
* @param {Object} packet
* @api private
*/
Manager.prototype.packet = function (packet) {
debug('writing packet %j', packet);
var self = this;
if (packet.query && packet.type === 0) packet.nsp += '?' + packet.query;
if (!self.encoding) {
// encode, then write to engine with result
self.encoding = true;
this.encoder.encode(packet, function (encodedPackets) {
for (var i = 0; i < encodedPackets.length; i++) {
self.engine.write(encodedPackets[i], packet.options);
}
self.encoding = false;
self.processPacketQueue();
});
} else { // add packet to the queue
self.packetBuffer.push(packet);
}
};
/**
* If packet buffer is non-empty, begins encoding the
* next packet in line.
*
* @api private
*/
Manager.prototype.processPacketQueue = function () {
if (this.packetBuffer.length > 0 && !this.encoding) {
var pack = this.packetBuffer.shift();
this.packet(pack);
}
};
/**
* Clean up transport subscriptions and packet buffer.
*
* @api private
*/
Manager.prototype.cleanup = function () {
debug('cleanup');
var subsLength = this.subs.length;
for (var i = 0; i < subsLength; i++) {
var sub = this.subs.shift();
sub.destroy();
}
this.packetBuffer = [];
this.encoding = false;
this.lastPing = null;
this.decoder.destroy();
};
/**
* Close the current socket.
*
* @api private
*/
Manager.prototype.close =
Manager.prototype.disconnect = function () {
debug('disconnect');
this.skipReconnect = true;
this.reconnecting = false;
if ('opening' === this.readyState) {
// `onclose` will not fire because
// an open event never happened
this.cleanup();
}
this.backoff.reset();
this.readyState = 'closed';
if (this.engine) this.engine.close();
};
/**
* Called upon engine close.
*
* @api private
*/
Manager.prototype.onclose = function (reason) {
debug('onclose');
this.cleanup();
this.backoff.reset();
this.readyState = 'closed';
this.emit('close', reason);
if (this._reconnection && !this.skipReconnect) {
this.reconnect();
}
};
/**
* Attempt a reconnection.
*
* @api private
*/
Manager.prototype.reconnect = function () {
if (this.reconnecting || this.skipReconnect) return this;
var self = this;
if (this.backoff.attempts >= this._reconnectionAttempts) {
debug('reconnect failed');
this.backoff.reset();
this.emitAll('reconnect_failed');
this.reconnecting = false;
} else {
var delay = this.backoff.duration();
debug('will wait %dms before reconnect attempt', delay);
this.reconnecting = true;
var timer = setTimeout(function () {
if (self.skipReconnect) return;
debug('attempting reconnect');
self.emitAll('reconnect_attempt', self.backoff.attempts);
self.emitAll('reconnecting', self.backoff.attempts);
// check again for the case socket closed in above events
if (self.skipReconnect) return;
self.open(function (err) {
if (err) {
debug('reconnect attempt error');
self.reconnecting = false;
self.reconnect();
self.emitAll('reconnect_error', err.data);
} else {
debug('reconnect success');
self.onreconnect();
}
});
}, delay);
this.subs.push({
destroy: function () {
clearTimeout(timer);
}
});
}
};
/**
* Called upon successful reconnect.
*
* @api private
*/
Manager.prototype.onreconnect = function () {
var attempt = this.backoff.attempts;
this.reconnecting = false;
this.backoff.reset();
this.updateSocketIds();
this.emitAll('reconnect', attempt);
};
},{"./on":69,"./socket":70,"backo2":72,"component-bind":74,"component-emitter":75,"debug":77,"engine.io-client":79,"indexof":102,"socket.io-parser":105}],69:[function(require,module,exports){
/**
* Module exports.
*/
module.exports = on;
/**
* Helper for subscriptions.
*
* @param {Object|EventEmitter} obj with `Emitter` mixin or `EventEmitter`
* @param {String} event name
* @param {Function} callback
* @api public
*/
function on (obj, ev, fn) {
obj.on(ev, fn);
return {
destroy: function () {
obj.removeListener(ev, fn);
}
};
}
},{}],70:[function(require,module,exports){
/**
* Module dependencies.
*/
var parser = require('socket.io-parser');
var Emitter = require('component-emitter');
var toArray = require('to-array');
var on = require('./on');
var bind = require('component-bind');
var debug = require('debug')('socket.io-client:socket');
/**
* Module exports.
*/
module.exports = exports = Socket;
/**
* Internal events (blacklisted).
* These events can't be emitted by the user.
*
* @api private
*/
var events = {
connect: 1,
connect_error: 1,
connect_timeout: 1,
connecting: 1,
disconnect: 1,
error: 1,
reconnect: 1,
reconnect_attempt: 1,
reconnect_failed: 1,
reconnect_error: 1,
reconnecting: 1,
ping: 1,
pong: 1
};
/**
* Shortcut to `Emitter#emit`.
*/
var emit = Emitter.prototype.emit;
/**
* `Socket` constructor.
*
* @api public
*/
function Socket (io, nsp, opts) {
this.io = io;
this.nsp = nsp;
this.json = this; // compat
this.ids = 0;
this.acks = {};
this.receiveBuffer = [];
this.sendBuffer = [];
this.connected = false;
this.disconnected = true;
if (opts && opts.query) {
this.query = opts.query;
}
if (this.io.autoConnect) this.open();
}
/**
* Mix in `Emitter`.
*/
Emitter(Socket.prototype);
/**
* Subscribe to open, close and packet events
*
* @api private
*/
Socket.prototype.subEvents = function () {
if (this.subs) return;
var io = this.io;
this.subs = [
on(io, 'open', bind(this, 'onopen')),
on(io, 'packet', bind(this, 'onpacket')),
on(io, 'close', bind(this, 'onclose'))
];
};
/**
* "Opens" the socket.
*
* @api public
*/
Socket.prototype.open =
Socket.prototype.connect = function () {
if (this.connected) return this;
this.subEvents();
this.io.open(); // ensure open
if ('open' === this.io.readyState) this.onopen();
this.emit('connecting');
return this;
};
/**
* Sends a `message` event.
*
* @return {Socket} self
* @api public
*/
Socket.prototype.send = function () {
var args = toArray(arguments);
args.unshift('message');
this.emit.apply(this, args);
return this;
};
/**
* Override `emit`.
* If the event is in `events`, it's emitted normally.
*
* @param {String} event name
* @return {Socket} self
* @api public
*/
Socket.prototype.emit = function (ev) {
if (events.hasOwnProperty(ev)) {
emit.apply(this, arguments);
return this;
}
var args = toArray(arguments);
var packet = { type: parser.EVENT, data: args };
packet.options = {};
packet.options.compress = !this.flags || false !== this.flags.compress;
// event ack callback
if ('function' === typeof args[args.length - 1]) {
debug('emitting packet with ack id %d', this.ids);
this.acks[this.ids] = args.pop();
packet.id = this.ids++;
}
if (this.connected) {
this.packet(packet);
} else {
this.sendBuffer.push(packet);
}
delete this.flags;
return this;
};
/**
* Sends a packet.
*
* @param {Object} packet
* @api private
*/
Socket.prototype.packet = function (packet) {
packet.nsp = this.nsp;
this.io.packet(packet);
};
/**
* Called upon engine `open`.
*
* @api private
*/
Socket.prototype.onopen = function () {
debug('transport is open - connecting');
// write connect packet if necessary
if ('/' !== this.nsp) {
if (this.query) {
this.packet({type: parser.CONNECT, query: this.query});
} else {
this.packet({type: parser.CONNECT});
}
}
};
/**
* Called upon engine `close`.
*
* @param {String} reason
* @api private
*/
Socket.prototype.onclose = function (reason) {
debug('close (%s)', reason);
this.connected = false;
this.disconnected = true;
delete this.id;
this.emit('disconnect', reason);
};
/**
* Called with socket packet.
*
* @param {Object} packet
* @api private
*/
Socket.prototype.onpacket = function (packet) {
if (packet.nsp !== this.nsp) return;
switch (packet.type) {
case parser.CONNECT:
this.onconnect();
break;
case parser.EVENT:
this.onevent(packet);
break;
case parser.BINARY_EVENT:
this.onevent(packet);
break;
case parser.ACK:
this.onack(packet);
break;
case parser.BINARY_ACK:
this.onack(packet);
break;
case parser.DISCONNECT:
this.ondisconnect();
break;
case parser.ERROR:
this.emit('error', packet.data);
break;
}
};
/**
* Called upon a server event.
*
* @param {Object} packet
* @api private
*/
Socket.prototype.onevent = function (packet) {
var args = packet.data || [];
debug('emitting event %j', args);
if (null != packet.id) {
debug('attaching ack callback to event');
args.push(this.ack(packet.id));
}
if (this.connected) {
emit.apply(this, args);
} else {
this.receiveBuffer.push(args);
}
};
/**
* Produces an ack callback to emit with an event.
*
* @api private
*/
Socket.prototype.ack = function (id) {
var self = this;
var sent = false;
return function () {
// prevent double callbacks
if (sent) return;
sent = true;
var args = toArray(arguments);
debug('sending ack %j', args);
self.packet({
type: parser.ACK,
id: id,
data: args
});
};
};
/**
* Called upon a server acknowlegement.
*
* @param {Object} packet
* @api private
*/
Socket.prototype.onack = function (packet) {
var ack = this.acks[packet.id];
if ('function' === typeof ack) {
debug('calling ack %s with %j', packet.id, packet.data);
ack.apply(this, packet.data);
delete this.acks[packet.id];
} else {
debug('bad ack %s', packet.id);
}
};
/**
* Called upon server connect.
*
* @api private
*/
Socket.prototype.onconnect = function () {
this.connected = true;
this.disconnected = false;
this.emit('connect');
this.emitBuffered();
};
/**
* Emit buffered events (received and emitted).
*
* @api private
*/
Socket.prototype.emitBuffered = function () {
var i;
for (i = 0; i < this.receiveBuffer.length; i++) {
emit.apply(this, this.receiveBuffer[i]);
}
this.receiveBuffer = [];
for (i = 0; i < this.sendBuffer.length; i++) {
this.packet(this.sendBuffer[i]);
}
this.sendBuffer = [];
};
/**
* Called upon server disconnect.
*
* @api private
*/
Socket.prototype.ondisconnect = function () {
debug('server disconnect (%s)', this.nsp);
this.destroy();
this.onclose('io server disconnect');
};
/**
* Called upon forced client/server side disconnections,
* this method ensures the manager stops tracking us and
* that reconnections don't get triggered for this.
*
* @api private.
*/
Socket.prototype.destroy = function () {
if (this.subs) {
// clean subscriptions to avoid reconnections
for (var i = 0; i < this.subs.length; i++) {
this.subs[i].destroy();
}
this.subs = null;
}
this.io.destroy(this);
};
/**
* Disconnects the socket manually.
*
* @return {Socket} self
* @api public
*/
Socket.prototype.close =
Socket.prototype.disconnect = function () {
if (this.connected) {
debug('performing disconnect (%s)', this.nsp);
this.packet({ type: parser.DISCONNECT });
}
// remove socket from pool
this.destroy();
if (this.connected) {
// fire events
this.onclose('io client disconnect');
}
return this;
};
/**
* Sets the compress flag.
*
* @param {Boolean} if `true`, compresses the sending data
* @return {Socket} self
* @api public
*/
Socket.prototype.compress = function (compress) {
this.flags = this.flags || {};
this.flags.compress = compress;
return this;
};
},{"./on":69,"component-bind":74,"component-emitter":75,"debug":77,"socket.io-parser":105,"to-array":109}],71:[function(require,module,exports){
(function (global){
/**
* Module dependencies.
*/
var parseuri = require('parseuri');
var debug = require('debug')('socket.io-client:url');
/**
* Module exports.
*/
module.exports = url;
/**
* URL parser.
*
* @param {String} url
* @param {Object} An object meant to mimic window.location.
* Defaults to window.location.
* @api public
*/
function url (uri, loc) {
var obj = uri;
// default to window.location
loc = loc || global.location;
if (null == uri) uri = loc.protocol + '//' + loc.host;
// relative path support
if ('string' === typeof uri) {
if ('/' === uri.charAt(0)) {
if ('/' === uri.charAt(1)) {
uri = loc.protocol + uri;
} else {
uri = loc.host + uri;
}
}
if (!/^(https?|wss?):\/\//.test(uri)) {
debug('protocol-less url %s', uri);
if ('undefined' !== typeof loc) {
uri = loc.protocol + '//' + uri;
} else {
uri = 'https://' + uri;
}
}
// parse
debug('parse %s', uri);
obj = parseuri(uri);
}
// make sure we treat `localhost:80` and `localhost` equally
if (!obj.port) {
if (/^(http|ws)$/.test(obj.protocol)) {
obj.port = '80';
} else if (/^(http|ws)s$/.test(obj.protocol)) {
obj.port = '443';
}
}
obj.path = obj.path || '/';
var ipv6 = obj.host.indexOf(':') !== -1;
var host = ipv6 ? '[' + obj.host + ']' : obj.host;
// define unique id
obj.id = obj.protocol + '://' + host + ':' + obj.port;
// define href
obj.href = obj.protocol + '://' + host + (loc && loc.port === obj.port ? '' : (':' + obj.port));
return obj;
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"debug":77,"parseuri":103}],72:[function(require,module,exports){
/**
* Expose `Backoff`.
*/
module.exports = Backoff;
/**
* Initialize backoff timer with `opts`.
*
* - `min` initial timeout in milliseconds [100]
* - `max` max timeout [10000]
* - `jitter` [0]
* - `factor` [2]
*
* @param {Object} opts
* @api public
*/
function Backoff(opts) {
opts = opts || {};
this.ms = opts.min || 100;
this.max = opts.max || 10000;
this.factor = opts.factor || 2;
this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0;
this.attempts = 0;
}
/**
* Return the backoff duration.
*
* @return {Number}
* @api public
*/
Backoff.prototype.duration = function(){
var ms = this.ms * Math.pow(this.factor, this.attempts++);
if (this.jitter) {
var rand = Math.random();
var deviation = Math.floor(rand * this.jitter * ms);
ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation;
}
return Math.min(ms, this.max) | 0;
};
/**
* Reset the number of attempts.
*
* @api public
*/
Backoff.prototype.reset = function(){
this.attempts = 0;
};
/**
* Set the minimum duration
*
* @api public
*/
Backoff.prototype.setMin = function(min){
this.ms = min;
};
/**
* Set the maximum duration
*
* @api public
*/
Backoff.prototype.setMax = function(max){
this.max = max;
};
/**
* Set the jitter
*
* @api public
*/
Backoff.prototype.setJitter = function(jitter){
this.jitter = jitter;
};
},{}],73:[function(require,module,exports){
/*
* base64-arraybuffer
* https://github.com/niklasvh/base64-arraybuffer
*
* Copyright (c) 2012 Niklas von Hertzen
* Licensed under the MIT license.
*/
(function(){
"use strict";
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// Use a lookup table to find the index.
var lookup = new Uint8Array(256);
for (var i = 0; i < chars.length; i++) {
lookup[chars.charCodeAt(i)] = i;
}
exports.encode = function(arraybuffer) {
var bytes = new Uint8Array(arraybuffer),
i, len = bytes.length, base64 = "";
for (i = 0; i < len; i+=3) {
base64 += chars[bytes[i] >> 2];
base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
base64 += chars[bytes[i + 2] & 63];
}
if ((len % 3) === 2) {
base64 = base64.substring(0, base64.length - 1) + "=";
} else if (len % 3 === 1) {
base64 = base64.substring(0, base64.length - 2) + "==";
}
return base64;
};
exports.decode = function(base64) {
var bufferLength = base64.length * 0.75,
len = base64.length, i, p = 0,
encoded1, encoded2, encoded3, encoded4;
if (base64[base64.length - 1] === "=") {
bufferLength--;
if (base64[base64.length - 2] === "=") {
bufferLength--;
}
}
var arraybuffer = new ArrayBuffer(bufferLength),
bytes = new Uint8Array(arraybuffer);
for (i = 0; i < len; i+=4) {
encoded1 = lookup[base64.charCodeAt(i)];
encoded2 = lookup[base64.charCodeAt(i+1)];
encoded3 = lookup[base64.charCodeAt(i+2)];
encoded4 = lookup[base64.charCodeAt(i+3)];
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
}
return arraybuffer;
};
})();
},{}],74:[function(require,module,exports){
/**
* Slice reference.
*/
var slice = [].slice;
/**
* Bind `obj` to `fn`.
*
* @param {Object} obj
* @param {Function|String} fn or string
* @return {Function}
* @api public
*/
module.exports = function(obj, fn){
if ('string' == typeof fn) fn = obj[fn];
if ('function' != typeof fn) throw new Error('bind() requires a function');
var args = slice.call(arguments, 2);
return function(){
return fn.apply(obj, args.concat(slice.call(arguments)));
}
};
},{}],75:[function(require,module,exports){
/**
* Expose `Emitter`.
*/
if (typeof module !== 'undefined') {
module.exports = Emitter;
}
/**
* Initialize a new `Emitter`.
*
* @api public
*/
function Emitter(obj) {
if (obj) return mixin(obj);
};
/**
* Mixin the emitter properties.
*
* @param {Object} obj
* @return {Object}
* @api private
*/
function mixin(obj) {
for (var key in Emitter.prototype) {
obj[key] = Emitter.prototype[key];
}
return obj;
}
/**
* Listen on the given `event` with `fn`.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.on =
Emitter.prototype.addEventListener = function(event, fn){
this._callbacks = this._callbacks || {};
(this._callbacks['$' + event] = this._callbacks['$' + event] || [])
.push(fn);
return this;
};
/**
* Adds an `event` listener that will be invoked a single
* time then automatically removed.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.once = function(event, fn){
function on() {
this.off(event, on);
fn.apply(this, arguments);
}
on.fn = fn;
this.on(event, on);
return this;
};
/**
* Remove the given callback for `event` or all
* registered callbacks.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.off =
Emitter.prototype.removeListener =
Emitter.prototype.removeAllListeners =
Emitter.prototype.removeEventListener = function(event, fn){
this._callbacks = this._callbacks || {};
// all
if (0 == arguments.length) {
this._callbacks = {};
return this;
}
// specific event
var callbacks = this._callbacks['$' + event];
if (!callbacks) return this;
// remove all handlers
if (1 == arguments.length) {
delete this._callbacks['$' + event];
return this;
}
// remove specific handler
var cb;
for (var i = 0; i < callbacks.length; i++) {
cb = callbacks[i];
if (cb === fn || cb.fn === fn) {
callbacks.splice(i, 1);
break;
}
}
return this;
};
/**
* Emit `event` with the given args.
*
* @param {String} event
* @param {Mixed} ...
* @return {Emitter}
*/
Emitter.prototype.emit = function(event){
this._callbacks = this._callbacks || {};
var args = [].slice.call(arguments, 1)
, callbacks = this._callbacks['$' + event];
if (callbacks) {
callbacks = callbacks.slice(0);
for (var i = 0, len = callbacks.length; i < len; ++i) {
callbacks[i].apply(this, args);
}
}
return this;
};
/**
* Return array of callbacks for `event`.
*
* @param {String} event
* @return {Array}
* @api public
*/
Emitter.prototype.listeners = function(event){
this._callbacks = this._callbacks || {};
return this._callbacks['$' + event] || [];
};
/**
* Check if this emitter has `event` handlers.
*
* @param {String} event
* @return {Boolean}
* @api public
*/
Emitter.prototype.hasListeners = function(event){
return !! this.listeners(event).length;
};
},{}],76:[function(require,module,exports){
/**
* Helpers.
*/
var s = 1000
var m = s * 60
var h = m * 60
var d = h * 24
var y = d * 365.25
/**
* Parse or format the given `val`.
*
* Options:
*
* - `long` verbose formatting [false]
*
* @param {String|Number} val
* @param {Object} [options]
* @throws {Error} throw an error if val is not a non-empty string or a number
* @return {String|Number}
* @api public
*/
module.exports = function (val, options) {
options = options || {}
var type = typeof val
if (type === 'string' && val.length > 0) {
return parse(val)
} else if (type === 'number' && isNaN(val) === false) {
return options.long ?
fmtLong(val) :
fmtShort(val)
}
throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val))
}
/**
* Parse the given `str` and return milliseconds.
*
* @param {String} str
* @return {Number}
* @api private
*/
function parse(str) {
str = String(str)
if (str.length > 10000) {
return
}
var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str)
if (!match) {
return
}
var n = parseFloat(match[1])
var type = (match[2] || 'ms').toLowerCase()
switch (type) {
case 'years':
case 'year':
case 'yrs':
case 'yr':
case 'y':
return n * y
case 'days':
case 'day':
case 'd':
return n * d
case 'hours':
case 'hour':
case 'hrs':
case 'hr':
case 'h':
return n * h
case 'minutes':
case 'minute':
case 'mins':
case 'min':
case 'm':
return n * m
case 'seconds':
case 'second':
case 'secs':
case 'sec':
case 's':
return n * s
case 'milliseconds':
case 'millisecond':
case 'msecs':
case 'msec':
case 'ms':
return n
default:
return undefined
}
}
/**
* Short format for `ms`.
*
* @param {Number} ms
* @return {String}
* @api private
*/
function fmtShort(ms) {
if (ms >= d) {
return Math.round(ms / d) + 'd'
}
if (ms >= h) {
return Math.round(ms / h) + 'h'
}
if (ms >= m) {
return Math.round(ms / m) + 'm'
}
if (ms >= s) {
return Math.round(ms / s) + 's'
}
return ms + 'ms'
}
/**
* Long format for `ms`.
*
* @param {Number} ms
* @return {String}
* @api private
*/
function fmtLong(ms) {
return plural(ms, d, 'day') ||
plural(ms, h, 'hour') ||
plural(ms, m, 'minute') ||
plural(ms, s, 'second') ||
ms + ' ms'
}
/**
* Pluralization helper.
*/
function plural(ms, n, name) {
if (ms < n) {
return
}
if (ms < n * 1.5) {
return Math.floor(ms / n) + ' ' + name
}
return Math.ceil(ms / n) + ' ' + name + 's'
}
},{}],77:[function(require,module,exports){
(function (process){
/**
* This is the web browser implementation of `debug()`.
*
* Expose `debug()` as the module.
*/
exports = module.exports = require('./debug');
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.storage = 'undefined' != typeof chrome
&& 'undefined' != typeof chrome.storage
? chrome.storage.local
: localstorage();
/**
* Colors.
*/
exports.colors = [
'lightseagreen',
'forestgreen',
'goldenrod',
'dodgerblue',
'darkorchid',
'crimson'
];
/**
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
* and the Firebug extension (any Firefox version) are known
* to support "%c" CSS customizations.
*
* TODO: add a `localStorage` variable to explicitly enable/disable colors
*/
function useColors() {
// NB: In an Electron preload script, document will be defined but not fully
// initialized. Since we know we're in Chrome, we'll just detect this case
// explicitly
if (typeof window !== 'undefined' && window && typeof window.process !== 'undefined' && window.process.type === 'renderer') {
return true;
}
// is webkit? http://stackoverflow.com/a/16459606/376773
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
return (typeof document !== 'undefined' && document && 'WebkitAppearance' in document.documentElement.style) ||
// is firebug? http://stackoverflow.com/a/398120/376773
(typeof window !== 'undefined' && window && window.console && (console.firebug || (console.exception && console.table))) ||
// is firefox >= v31?
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
(typeof navigator !== 'undefined' && navigator && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
// double check webkit in userAgent just in case we are in a worker
(typeof navigator !== 'undefined' && navigator && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
}
/**
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
*/
exports.formatters.j = function(v) {
try {
return JSON.stringify(v);
} catch (err) {
return '[UnexpectedJSONParseError]: ' + err.message;
}
};
/**
* Colorize log arguments if enabled.
*
* @api public
*/
function formatArgs(args) {
var useColors = this.useColors;
args[0] = (useColors ? '%c' : '')
+ this.namespace
+ (useColors ? ' %c' : ' ')
+ args[0]
+ (useColors ? '%c ' : ' ')
+ '+' + exports.humanize(this.diff);
if (!useColors) return;
var c = 'color: ' + this.color;
args.splice(1, 0, c, 'color: inherit')
// the final "%c" is somewhat tricky, because there could be other
// arguments passed either before or after the %c, so we need to
// figure out the correct index to insert the CSS into
var index = 0;
var lastC = 0;
args[0].replace(/%[a-zA-Z%]/g, function(match) {
if ('%%' === match) return;
index++;
if ('%c' === match) {
// we only are interested in the *last* %c
// (the user may have provided their own)
lastC = index;
}
});
args.splice(lastC, 0, c);
}
/**
* Invokes `console.log()` when available.
* No-op when `console.log` is not a "function".
*
* @api public
*/
function log() {
// this hackery is required for IE8/9, where
// the `console.log` function doesn't have 'apply'
return 'object' === typeof console
&& console.log
&& Function.prototype.apply.call(console.log, console, arguments);
}
/**
* Save `namespaces`.
*
* @param {String} namespaces
* @api private
*/
function save(namespaces) {
try {
if (null == namespaces) {
exports.storage.removeItem('debug');
} else {
exports.storage.debug = namespaces;
}
} catch(e) {}
}
/**
* Load `namespaces`.
*
* @return {String} returns the previously persisted debug modes
* @api private
*/
function load() {
var r;
try {
r = exports.storage.debug;
} catch(e) {}
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
if (!r && typeof process !== 'undefined' && 'env' in process) {
r = process.env.DEBUG;
}
return r;
}
/**
* Enable namespaces listed in `localStorage.debug` initially.
*/
exports.enable(load());
/**
* Localstorage attempts to return the localstorage.
*
* This is necessary because safari throws
* when a user disables cookies/localstorage
* and you attempt to access it.
*
* @return {LocalStorage}
* @api private
*/
function localstorage() {
try {
return window.localStorage;
} catch (e) {}
}
}).call(this,require('_process'))
},{"./debug":78,"_process":2}],78:[function(require,module,exports){
/**
* This is the common logic for both the Node.js and web browser
* implementations of `debug()`.
*
* Expose `debug()` as the module.
*/
exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
exports.coerce = coerce;
exports.disable = disable;
exports.enable = enable;
exports.enabled = enabled;
exports.humanize = require('ms');
/**
* The currently active debug mode names, and names to skip.
*/
exports.names = [];
exports.skips = [];
/**
* Map of special "%n" handling functions, for the debug "format" argument.
*
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
*/
exports.formatters = {};
/**
* Previous log timestamp.
*/
var prevTime;
/**
* Select a color.
* @param {String} namespace
* @return {Number}
* @api private
*/
function selectColor(namespace) {
var hash = 0, i;
for (i in namespace) {
hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
hash |= 0; // Convert to 32bit integer
}
return exports.colors[Math.abs(hash) % exports.colors.length];
}
/**
* Create a debugger with the given `namespace`.
*
* @param {String} namespace
* @return {Function}
* @api public
*/
function createDebug(namespace) {
function debug() {
// disabled?
if (!debug.enabled) return;
var self = debug;
// set `diff` timestamp
var curr = +new Date();
var ms = curr - (prevTime || curr);
self.diff = ms;
self.prev = prevTime;
self.curr = curr;
prevTime = curr;
// turn the `arguments` into a proper Array
var args = new Array(arguments.length);
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i];
}
args[0] = exports.coerce(args[0]);
if ('string' !== typeof args[0]) {
// anything else let's inspect with %O
args.unshift('%O');
}
// apply any `formatters` transformations
var index = 0;
args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
// if we encounter an escaped % then don't increase the array index
if (match === '%%') return match;
index++;
var formatter = exports.formatters[format];
if ('function' === typeof formatter) {
var val = args[index];
match = formatter.call(self, val);
// now we need to remove `args[index]` since it's inlined in the `format`
args.splice(index, 1);
index--;
}
return match;
});
// apply env-specific formatting (colors, etc.)
exports.formatArgs.call(self, args);
var logFn = debug.log || exports.log || console.log.bind(console);
logFn.apply(self, args);
}
debug.namespace = namespace;
debug.enabled = exports.enabled(namespace);
debug.useColors = exports.useColors();
debug.color = selectColor(namespace);
// env-specific initialization logic for debug instances
if ('function' === typeof exports.init) {
exports.init(debug);
}
return debug;
}
/**
* Enables a debug mode by namespaces. This can include modes
* separated by a colon and wildcards.
*
* @param {String} namespaces
* @api public
*/
function enable(namespaces) {
exports.save(namespaces);
exports.names = [];
exports.skips = [];
var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
var len = split.length;
for (var i = 0; i < len; i++) {
if (!split[i]) continue; // ignore empty strings
namespaces = split[i].replace(/\*/g, '.*?');
if (namespaces[0] === '-') {
exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
} else {
exports.names.push(new RegExp('^' + namespaces + '$'));
}
}
}
/**
* Disable debug output.
*
* @api public
*/
function disable() {
exports.enable('');
}
/**
* Returns true if the given mode name is enabled, false otherwise.
*
* @param {String} name
* @return {Boolean}
* @api public
*/
function enabled(name) {
var i, len;
for (i = 0, len = exports.skips.length; i < len; i++) {
if (exports.skips[i].test(name)) {
return false;
}
}
for (i = 0, len = exports.names.length; i < len; i++) {
if (exports.names[i].test(name)) {
return true;
}
}
return false;
}
/**
* Coerce `val`.
*
* @param {Mixed} val
* @return {Mixed}
* @api private
*/
function coerce(val) {
if (val instanceof Error) return val.stack || val.message;
return val;
}
},{"ms":76}],79:[function(require,module,exports){
module.exports = require('./lib/index');
},{"./lib/index":80}],80:[function(require,module,exports){
module.exports = require('./socket');
/**
* Exports parser
*
* @api public
*
*/
module.exports.parser = require('engine.io-parser');
},{"./socket":81,"engine.io-parser":90}],81:[function(require,module,exports){
(function (global){
/**
* Module dependencies.
*/
var transports = require('./transports/index');
var Emitter = require('component-emitter');
var debug = require('debug')('engine.io-client:socket');
var index = require('indexof');
var parser = require('engine.io-parser');
var parseuri = require('parseuri');
var parsejson = require('parsejson');
var parseqs = require('parseqs');
/**
* Module exports.
*/
module.exports = Socket;
/**
* Socket constructor.
*
* @param {String|Object} uri or options
* @param {Object} options
* @api public
*/
function Socket (uri, opts) {
if (!(this instanceof Socket)) return new Socket(uri, opts);
opts = opts || {};
if (uri && 'object' === typeof uri) {
opts = uri;
uri = null;
}
if (uri) {
uri = parseuri(uri);
opts.hostname = uri.host;
opts.secure = uri.protocol === 'https' || uri.protocol === 'wss';
opts.port = uri.port;
if (uri.query) opts.query = uri.query;
} else if (opts.host) {
opts.hostname = parseuri(opts.host).host;
}
this.secure = null != opts.secure ? opts.secure
: (global.location && 'https:' === location.protocol);
if (opts.hostname && !opts.port) {
// if no port is specified manually, use the protocol default
opts.port = this.secure ? '443' : '80';
}
this.agent = opts.agent || false;
this.hostname = opts.hostname ||
(global.location ? location.hostname : 'localhost');
this.port = opts.port || (global.location && location.port
? location.port
: (this.secure ? 443 : 80));
this.query = opts.query || {};
if ('string' === typeof this.query) this.query = parseqs.decode(this.query);
this.upgrade = false !== opts.upgrade;
this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/';
this.forceJSONP = !!opts.forceJSONP;
this.jsonp = false !== opts.jsonp;
this.forceBase64 = !!opts.forceBase64;
this.enablesXDR = !!opts.enablesXDR;
this.timestampParam = opts.timestampParam || 't';
this.timestampRequests = opts.timestampRequests;
this.transports = opts.transports || ['polling', 'websocket'];
this.transportOptions = opts.transportOptions || {};
this.readyState = '';
this.writeBuffer = [];
this.prevBufferLen = 0;
this.policyPort = opts.policyPort || 843;
this.rememberUpgrade = opts.rememberUpgrade || false;
this.binaryType = null;
this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades;
this.perMessageDeflate = false !== opts.perMessageDeflate ? (opts.perMessageDeflate || {}) : false;
if (true === this.perMessageDeflate) this.perMessageDeflate = {};
if (this.perMessageDeflate && null == this.perMessageDeflate.threshold) {
this.perMessageDeflate.threshold = 1024;
}
// SSL options for Node.js client
this.pfx = opts.pfx || null;
this.key = opts.key || null;
this.passphrase = opts.passphrase || null;
this.cert = opts.cert || null;
this.ca = opts.ca || null;
this.ciphers = opts.ciphers || null;
this.rejectUnauthorized = opts.rejectUnauthorized === undefined ? true : opts.rejectUnauthorized;
this.forceNode = !!opts.forceNode;
// other options for Node.js client
var freeGlobal = typeof global === 'object' && global;
if (freeGlobal.global === freeGlobal) {
if (opts.extraHeaders && Object.keys(opts.extraHeaders).length > 0) {
this.extraHeaders = opts.extraHeaders;
}
if (opts.localAddress) {
this.localAddress = opts.localAddress;
}
}
// set on handshake
this.id = null;
this.upgrades = null;
this.pingInterval = null;
this.pingTimeout = null;
// set on heartbeat
this.pingIntervalTimer = null;
this.pingTimeoutTimer = null;
this.open();
}
Socket.priorWebsocketSuccess = false;
/**
* Mix in `Emitter`.
*/
Emitter(Socket.prototype);
/**
* Protocol version.
*
* @api public
*/
Socket.protocol = parser.protocol; // this is an int
/**
* Expose deps for legacy compatibility
* and standalone browser access.
*/
Socket.Socket = Socket;
Socket.Transport = require('./transport');
Socket.transports = require('./transports/index');
Socket.parser = require('engine.io-parser');
/**
* Creates transport of the given type.
*
* @param {String} transport name
* @return {Transport}
* @api private
*/
Socket.prototype.createTransport = function (name) {
debug('creating transport "%s"', name);
var query = clone(this.query);
// append engine.io protocol identifier
query.EIO = parser.protocol;
// transport name
query.transport = name;
// per-transport options
var options = this.transportOptions[name] || {};
// session id if we already have one
if (this.id) query.sid = this.id;
var transport = new transports[name]({
query: query,
socket: this,
agent: options.agent || this.agent,
hostname: options.hostname || this.hostname,
port: options.port || this.port,
secure: options.secure || this.secure,
path: options.path || this.path,
forceJSONP: options.forceJSONP || this.forceJSONP,
jsonp: options.jsonp || this.jsonp,
forceBase64: options.forceBase64 || this.forceBase64,
enablesXDR: options.enablesXDR || this.enablesXDR,
timestampRequests: options.timestampRequests || this.timestampRequests,
timestampParam: options.timestampParam || this.timestampParam,
policyPort: options.policyPort || this.policyPort,
pfx: options.pfx || this.pfx,
key: options.key || this.key,
passphrase: options.passphrase || this.passphrase,
cert: options.cert || this.cert,
ca: options.ca || this.ca,
ciphers: options.ciphers || this.ciphers,
rejectUnauthorized: options.rejectUnauthorized || this.rejectUnauthorized,
perMessageDeflate: options.perMessageDeflate || this.perMessageDeflate,
extraHeaders: options.extraHeaders || this.extraHeaders,
forceNode: options.forceNode || this.forceNode,
localAddress: options.localAddress || this.localAddress,
requestTimeout: options.requestTimeout || this.requestTimeout,
protocols: options.protocols || void (0)
});
return transport;
};
function clone (obj) {
var o = {};
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
o[i] = obj[i];
}
}
return o;
}
/**
* Initializes transport to use and starts probe.
*
* @api private
*/
Socket.prototype.open = function () {
var transport;
if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') !== -1) {
transport = 'websocket';
} else if (0 === this.transports.length) {
// Emit error on next tick so it can be listened to
var self = this;
setTimeout(function () {
self.emit('error', 'No transports available');
}, 0);
return;
} else {
transport = this.transports[0];
}
this.readyState = 'opening';
// Retry with the next transport if the transport is disabled (jsonp: false)
try {
transport = this.createTransport(transport);
} catch (e) {
this.transports.shift();
this.open();
return;
}
transport.open();
this.setTransport(transport);
};
/**
* Sets the current transport. Disables the existing one (if any).
*
* @api private
*/
Socket.prototype.setTransport = function (transport) {
debug('setting transport %s', transport.name);
var self = this;
if (this.transport) {
debug('clearing existing transport %s', this.transport.name);
this.transport.removeAllListeners();
}
// set up transport
this.transport = transport;
// set up transport listeners
transport
.on('drain', function () {
self.onDrain();
})
.on('packet', function (packet) {
self.onPacket(packet);
})
.on('error', function (e) {
self.onError(e);
})
.on('close', function () {
self.onClose('transport close');
});
};
/**
* Probes a transport.
*
* @param {String} transport name
* @api private
*/
Socket.prototype.probe = function (name) {
debug('probing transport "%s"', name);
var transport = this.createTransport(name, { probe: 1 });
var failed = false;
var self = this;
Socket.priorWebsocketSuccess = false;
function onTransportOpen () {
if (self.onlyBinaryUpgrades) {
var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;
failed = failed || upgradeLosesBinary;
}
if (failed) return;
debug('probe transport "%s" opened', name);
transport.send([{ type: 'ping', data: 'probe' }]);
transport.once('packet', function (msg) {
if (failed) return;
if ('pong' === msg.type && 'probe' === msg.data) {
debug('probe transport "%s" pong', name);
self.upgrading = true;
self.emit('upgrading', transport);
if (!transport) return;
Socket.priorWebsocketSuccess = 'websocket' === transport.name;
debug('pausing current transport "%s"', self.transport.name);
self.transport.pause(function () {
if (failed) return;
if ('closed' === self.readyState) return;
debug('changing transport and sending upgrade packet');
cleanup();
self.setTransport(transport);
transport.send([{ type: 'upgrade' }]);
self.emit('upgrade', transport);
transport = null;
self.upgrading = false;
self.flush();
});
} else {
debug('probe transport "%s" failed', name);
var err = new Error('probe error');
err.transport = transport.name;
self.emit('upgradeError', err);
}
});
}
function freezeTransport () {
if (failed) return;
// Any callback called by transport should be ignored since now
failed = true;
cleanup();
transport.close();
transport = null;
}
// Handle any error that happens while probing
function onerror (err) {
var error = new Error('probe error: ' + err);
error.transport = transport.name;
freezeTransport();
debug('probe transport "%s" failed because of error: %s', name, err);
self.emit('upgradeError', error);
}
function onTransportClose () {
onerror('transport closed');
}
// When the socket is closed while we're probing
function onclose () {
onerror('socket closed');
}
// When the socket is upgraded while we're probing
function onupgrade (to) {
if (transport && to.name !== transport.name) {
debug('"%s" works - aborting "%s"', to.name, transport.name);
freezeTransport();
}
}
// Remove all listeners on the transport and on self
function cleanup () {
transport.removeListener('open', onTransportOpen);
transport.removeListener('error', onerror);
transport.removeListener('close', onTransportClose);
self.removeListener('close', onclose);
self.removeListener('upgrading', onupgrade);
}
transport.once('open', onTransportOpen);
transport.once('error', onerror);
transport.once('close', onTransportClose);
this.once('close', onclose);
this.once('upgrading', onupgrade);
transport.open();
};
/**
* Called when connection is deemed open.
*
* @api public
*/
Socket.prototype.onOpen = function () {
debug('socket open');
this.readyState = 'open';
Socket.priorWebsocketSuccess = 'websocket' === this.transport.name;
this.emit('open');
this.flush();
// we check for `readyState` in case an `open`
// listener already closed the socket
if ('open' === this.readyState && this.upgrade && this.transport.pause) {
debug('starting upgrade probes');
for (var i = 0, l = this.upgrades.length; i < l; i++) {
this.probe(this.upgrades[i]);
}
}
};
/**
* Handles a packet.
*
* @api private
*/
Socket.prototype.onPacket = function (packet) {
if ('opening' === this.readyState || 'open' === this.readyState ||
'closing' === this.readyState) {
debug('socket receive: type "%s", data "%s"', packet.type, packet.data);
this.emit('packet', packet);
// Socket is live - any packet counts
this.emit('heartbeat');
switch (packet.type) {
case 'open':
this.onHandshake(parsejson(packet.data));
break;
case 'pong':
this.setPing();
this.emit('pong');
break;
case 'error':
var err = new Error('server error');
err.code = packet.data;
this.onError(err);
break;
case 'message':
this.emit('data', packet.data);
this.emit('message', packet.data);
break;
}
} else {
debug('packet received with socket readyState "%s"', this.readyState);
}
};
/**
* Called upon handshake completion.
*
* @param {Object} handshake obj
* @api private
*/
Socket.prototype.onHandshake = function (data) {
this.emit('handshake', data);
this.id = data.sid;
this.transport.query.sid = data.sid;
this.upgrades = this.filterUpgrades(data.upgrades);
this.pingInterval = data.pingInterval;
this.pingTimeout = data.pingTimeout;
this.onOpen();
// In case open handler closes socket
if ('closed' === this.readyState) return;
this.setPing();
// Prolong liveness of socket on heartbeat
this.removeListener('heartbeat', this.onHeartbeat);
this.on('heartbeat', this.onHeartbeat);
};
/**
* Resets ping timeout.
*
* @api private
*/
Socket.prototype.onHeartbeat = function (timeout) {
clearTimeout(this.pingTimeoutTimer);
var self = this;
self.pingTimeoutTimer = setTimeout(function () {
if ('closed' === self.readyState) return;
self.onClose('ping timeout');
}, timeout || (self.pingInterval + self.pingTimeout));
};
/**
* Pings server every `this.pingInterval` and expects response
* within `this.pingTimeout` or closes connection.
*
* @api private
*/
Socket.prototype.setPing = function () {
var self = this;
clearTimeout(self.pingIntervalTimer);
self.pingIntervalTimer = setTimeout(function () {
debug('writing ping packet - expecting pong within %sms', self.pingTimeout);
self.ping();
self.onHeartbeat(self.pingTimeout);
}, self.pingInterval);
};
/**
* Sends a ping packet.
*
* @api private
*/
Socket.prototype.ping = function () {
var self = this;
this.sendPacket('ping', function () {
self.emit('ping');
});
};
/**
* Called on `drain` event
*
* @api private
*/
Socket.prototype.onDrain = function () {
this.writeBuffer.splice(0, this.prevBufferLen);
// setting prevBufferLen = 0 is very important
// for example, when upgrading, upgrade packet is sent over,
// and a nonzero prevBufferLen could cause problems on `drain`
this.prevBufferLen = 0;
if (0 === this.writeBuffer.length) {
this.emit('drain');
} else {
this.flush();
}
};
/**
* Flush write buffers.
*
* @api private
*/
Socket.prototype.flush = function () {
if ('closed' !== this.readyState && this.transport.writable &&
!this.upgrading && this.writeBuffer.length) {
debug('flushing %d packets in socket', this.writeBuffer.length);
this.transport.send(this.writeBuffer);
// keep track of current length of writeBuffer
// splice writeBuffer and callbackBuffer on `drain`
this.prevBufferLen = this.writeBuffer.length;
this.emit('flush');
}
};
/**
* Sends a message.
*
* @param {String} message.
* @param {Function} callback function.
* @param {Object} options.
* @return {Socket} for chaining.
* @api public
*/
Socket.prototype.write =
Socket.prototype.send = function (msg, options, fn) {
this.sendPacket('message', msg, options, fn);
return this;
};
/**
* Sends a packet.
*
* @param {String} packet type.
* @param {String} data.
* @param {Object} options.
* @param {Function} callback function.
* @api private
*/
Socket.prototype.sendPacket = function (type, data, options, fn) {
if ('function' === typeof data) {
fn = data;
data = undefined;
}
if ('function' === typeof options) {
fn = options;
options = null;
}
if ('closing' === this.readyState || 'closed' === this.readyState) {
return;
}
options = options || {};
options.compress = false !== options.compress;
var packet = {
type: type,
data: data,
options: options
};
this.emit('packetCreate', packet);
this.writeBuffer.push(packet);
if (fn) this.once('flush', fn);
this.flush();
};
/**
* Closes the connection.
*
* @api private
*/
Socket.prototype.close = function () {
if ('opening' === this.readyState || 'open' === this.readyState) {
this.readyState = 'closing';
var self = this;
if (this.writeBuffer.length) {
this.once('drain', function () {
if (this.upgrading) {
waitForUpgrade();
} else {
close();
}
});
} else if (this.upgrading) {
waitForUpgrade();
} else {
close();
}
}
function close () {
self.onClose('forced close');
debug('socket closing - telling transport to close');
self.transport.close();
}
function cleanupAndClose () {
self.removeListener('upgrade', cleanupAndClose);
self.removeListener('upgradeError', cleanupAndClose);
close();
}
function waitForUpgrade () {
// wait for upgrade to finish since we can't send packets while pausing a transport
self.once('upgrade', cleanupAndClose);
self.once('upgradeError', cleanupAndClose);
}
return this;
};
/**
* Called upon transport error
*
* @api private
*/
Socket.prototype.onError = function (err) {
debug('socket error %j', err);
Socket.priorWebsocketSuccess = false;
this.emit('error', err);
this.onClose('transport error', err);
};
/**
* Called upon transport close.
*
* @api private
*/
Socket.prototype.onClose = function (reason, desc) {
if ('opening' === this.readyState || 'open' === this.readyState || 'closing' === this.readyState) {
debug('socket close with reason: "%s"', reason);
var self = this;
// clear timers
clearTimeout(this.pingIntervalTimer);
clearTimeout(this.pingTimeoutTimer);
// stop event from firing again for transport
this.transport.removeAllListeners('close');
// ensure transport won't stay open
this.transport.close();
// ignore further transport communication
this.transport.removeAllListeners();
// set ready state
this.readyState = 'closed';
// clear session id
this.id = null;
// emit close event
this.emit('close', reason, desc);
// clean buffers after, so users can still
// grab the buffers on `close` event
self.writeBuffer = [];
self.prevBufferLen = 0;
}
};
/**
* Filters upgrades, returning only those matching client transports.
*
* @param {Array} server upgrades
* @api private
*
*/
Socket.prototype.filterUpgrades = function (upgrades) {
var filteredUpgrades = [];
for (var i = 0, j = upgrades.length; i < j; i++) {
if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]);
}
return filteredUpgrades;
};
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./transport":82,"./transports/index":83,"component-emitter":75,"debug":77,"engine.io-parser":90,"indexof":102,"parsejson":98,"parseqs":99,"parseuri":103}],82:[function(require,module,exports){
/**
* Module dependencies.
*/
var parser = require('engine.io-parser');
var Emitter = require('component-emitter');
/**
* Module exports.
*/
module.exports = Transport;
/**
* Transport abstract constructor.
*
* @param {Object} options.
* @api private
*/
function Transport (opts) {
this.path = opts.path;
this.hostname = opts.hostname;
this.port = opts.port;
this.secure = opts.secure;
this.query = opts.query;
this.timestampParam = opts.timestampParam;
this.timestampRequests = opts.timestampRequests;
this.readyState = '';
this.agent = opts.agent || false;
this.socket = opts.socket;
this.enablesXDR = opts.enablesXDR;
// SSL options for Node.js client
this.pfx = opts.pfx;
this.key = opts.key;
this.passphrase = opts.passphrase;
this.cert = opts.cert;
this.ca = opts.ca;
this.ciphers = opts.ciphers;
this.rejectUnauthorized = opts.rejectUnauthorized;
this.forceNode = opts.forceNode;
// other options for Node.js client
this.extraHeaders = opts.extraHeaders;
this.localAddress = opts.localAddress;
}
/**
* Mix in `Emitter`.
*/
Emitter(Transport.prototype);
/**
* Emits an error.
*
* @param {String} str
* @return {Transport} for chaining
* @api public
*/
Transport.prototype.onError = function (msg, desc) {
var err = new Error(msg);
err.type = 'TransportError';
err.description = desc;
this.emit('error', err);
return this;
};
/**
* Opens the transport.
*
* @api public
*/
Transport.prototype.open = function () {
if ('closed' === this.readyState || '' === this.readyState) {
this.readyState = 'opening';
this.doOpen();
}
return this;
};
/**
* Closes the transport.
*
* @api private
*/
Transport.prototype.close = function () {
if ('opening' === this.readyState || 'open' === this.readyState) {
this.doClose();
this.onClose();
}
return this;
};
/**
* Sends multiple packets.
*
* @param {Array} packets
* @api private
*/
Transport.prototype.send = function (packets) {
if ('open' === this.readyState) {
this.write(packets);
} else {
throw new Error('Transport not open');
}
};
/**
* Called upon open
*
* @api private
*/
Transport.prototype.onOpen = function () {
this.readyState = 'open';
this.writable = true;
this.emit('open');
};
/**
* Called with data.
*
* @param {String} data
* @api private
*/
Transport.prototype.onData = function (data) {
var packet = parser.decodePacket(data, this.socket.binaryType);
this.onPacket(packet);
};
/**
* Called with a decoded packet.
*/
Transport.prototype.onPacket = function (packet) {
this.emit('packet', packet);
};
/**
* Called upon close.
*
* @api private
*/
Transport.prototype.onClose = function () {
this.readyState = 'closed';
this.emit('close');
};
},{"component-emitter":75,"engine.io-parser":90}],83:[function(require,module,exports){
(function (global){
/**
* Module dependencies
*/
var XMLHttpRequest = require('xmlhttprequest-ssl');
var XHR = require('./polling-xhr');
var JSONP = require('./polling-jsonp');
var websocket = require('./websocket');
/**
* Export transports.
*/
exports.polling = polling;
exports.websocket = websocket;
/**
* Polling transport polymorphic constructor.
* Decides on xhr vs jsonp based on feature detection.
*
* @api private
*/
function polling (opts) {
var xhr;
var xd = false;
var xs = false;
var jsonp = false !== opts.jsonp;
if (global.location) {
var isSSL = 'https:' === location.protocol;
var port = location.port;
// some user agents have empty `location.port`
if (!port) {
port = isSSL ? 443 : 80;
}
xd = opts.hostname !== location.hostname || port !== opts.port;
xs = opts.secure !== isSSL;
}
opts.xdomain = xd;
opts.xscheme = xs;
xhr = new XMLHttpRequest(opts);
if ('open' in xhr && !opts.forceJSONP) {
return new XHR(opts);
} else {
if (!jsonp) throw new Error('JSONP disabled');
return new JSONP(opts);
}
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./polling-jsonp":84,"./polling-xhr":85,"./websocket":87,"xmlhttprequest-ssl":88}],84:[function(require,module,exports){
(function (global){
/**
* Module requirements.
*/
var Polling = require('./polling');
var inherit = require('component-inherit');
/**
* Module exports.
*/
module.exports = JSONPPolling;
/**
* Cached regular expressions.
*/
var rNewline = /\n/g;
var rEscapedNewline = /\\n/g;
/**
* Global JSONP callbacks.
*/
var callbacks;
/**
* Noop.
*/
function empty () { }
/**
* JSONP Polling constructor.
*
* @param {Object} opts.
* @api public
*/
function JSONPPolling (opts) {
Polling.call(this, opts);
this.query = this.query || {};
// define global callbacks array if not present
// we do this here (lazily) to avoid unneeded global pollution
if (!callbacks) {
// we need to consider multiple engines in the same page
if (!global.___eio) global.___eio = [];
callbacks = global.___eio;
}
// callback identifier
this.index = callbacks.length;
// add callback to jsonp global
var self = this;
callbacks.push(function (msg) {
self.onData(msg);
});
// append to query string
this.query.j = this.index;
// prevent spurious errors from being emitted when the window is unloaded
if (global.document && global.addEventListener) {
global.addEventListener('beforeunload', function () {
if (self.script) self.script.onerror = empty;
}, false);
}
}
/**
* Inherits from Polling.
*/
inherit(JSONPPolling, Polling);
/*
* JSONP only supports binary as base64 encoded strings
*/
JSONPPolling.prototype.supportsBinary = false;
/**
* Closes the socket.
*
* @api private
*/
JSONPPolling.prototype.doClose = function () {
if (this.script) {
this.script.parentNode.removeChild(this.script);
this.script = null;
}
if (this.form) {
this.form.parentNode.removeChild(this.form);
this.form = null;
this.iframe = null;
}
Polling.prototype.doClose.call(this);
};
/**
* Starts a poll cycle.
*
* @api private
*/
JSONPPolling.prototype.doPoll = function () {
var self = this;
var script = document.createElement('script');
if (this.script) {
this.script.parentNode.removeChild(this.script);
this.script = null;
}
script.async = true;
script.src = this.uri();
script.onerror = function (e) {
self.onError('jsonp poll error', e);
};
var insertAt = document.getElementsByTagName('script')[0];
if (insertAt) {
insertAt.parentNode.insertBefore(script, insertAt);
} else {
(document.head || document.body).appendChild(script);
}
this.script = script;
var isUAgecko = 'undefined' !== typeof navigator && /gecko/i.test(navigator.userAgent);
if (isUAgecko) {
setTimeout(function () {
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
document.body.removeChild(iframe);
}, 100);
}
};
/**
* Writes with a hidden iframe.
*
* @param {String} data to send
* @param {Function} called upon flush.
* @api private
*/
JSONPPolling.prototype.doWrite = function (data, fn) {
var self = this;
if (!this.form) {
var form = document.createElement('form');
var area = document.createElement('textarea');
var id = this.iframeId = 'eio_iframe_' + this.index;
var iframe;
form.className = 'socketio';
form.style.position = 'absolute';
form.style.top = '-1000px';
form.style.left = '-1000px';
form.target = id;
form.method = 'POST';
form.setAttribute('accept-charset', 'utf-8');
area.name = 'd';
form.appendChild(area);
document.body.appendChild(form);
this.form = form;
this.area = area;
}
this.form.action = this.uri();
function complete () {
initIframe();
fn();
}
function initIframe () {
if (self.iframe) {
try {
self.form.removeChild(self.iframe);
} catch (e) {
self.onError('jsonp polling iframe removal error', e);
}
}
try {
// ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
var html = '<iframe src="javascript:0" name="' + self.iframeId + '">';
iframe = document.createElement(html);
} catch (e) {
iframe = document.createElement('iframe');
iframe.name = self.iframeId;
iframe.src = 'javascript:0';
}
iframe.id = self.iframeId;
self.form.appendChild(iframe);
self.iframe = iframe;
}
initIframe();
// escape \n to prevent it from being converted into \r\n by some UAs
// double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side
data = data.replace(rEscapedNewline, '\\\n');
this.area.value = data.replace(rNewline, '\\n');
try {
this.form.submit();
} catch (e) {}
if (this.iframe.attachEvent) {
this.iframe.onreadystatechange = function () {
if (self.iframe.readyState === 'complete') {
complete();
}
};
} else {
this.iframe.onload = complete;
}
};
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./polling":86,"component-inherit":89}],85:[function(require,module,exports){
(function (global){
/**
* Module requirements.
*/
var XMLHttpRequest = require('xmlhttprequest-ssl');
var Polling = require('./polling');
var Emitter = require('component-emitter');
var inherit = require('component-inherit');
var debug = require('debug')('engine.io-client:polling-xhr');
/**
* Module exports.
*/
module.exports = XHR;
module.exports.Request = Request;
/**
* Empty function
*/
function empty () {}
/**
* XHR Polling constructor.
*
* @param {Object} opts
* @api public
*/
function XHR (opts) {
Polling.call(this, opts);
this.requestTimeout = opts.requestTimeout;
this.extraHeaders = opts.extraHeaders;
if (global.location) {
var isSSL = 'https:' === location.protocol;
var port = location.port;
// some user agents have empty `location.port`
if (!port) {
port = isSSL ? 443 : 80;
}
this.xd = opts.hostname !== global.location.hostname ||
port !== opts.port;
this.xs = opts.secure !== isSSL;
}
}
/**
* Inherits from Polling.
*/
inherit(XHR, Polling);
/**
* XHR supports binary
*/
XHR.prototype.supportsBinary = true;
/**
* Creates a request.
*
* @param {String} method
* @api private
*/
XHR.prototype.request = function (opts) {
opts = opts || {};
opts.uri = this.uri();
opts.xd = this.xd;
opts.xs = this.xs;
opts.agent = this.agent || false;
opts.supportsBinary = this.supportsBinary;
opts.enablesXDR = this.enablesXDR;
// SSL options for Node.js client
opts.pfx = this.pfx;
opts.key = this.key;
opts.passphrase = this.passphrase;
opts.cert = this.cert;
opts.ca = this.ca;
opts.ciphers = this.ciphers;
opts.rejectUnauthorized = this.rejectUnauthorized;
opts.requestTimeout = this.requestTimeout;
// other options for Node.js client
opts.extraHeaders = this.extraHeaders;
return new Request(opts);
};
/**
* Sends data.
*
* @param {String} data to send.
* @param {Function} called upon flush.
* @api private
*/
XHR.prototype.doWrite = function (data, fn) {
var isBinary = typeof data !== 'string' && data !== undefined;
var req = this.request({ method: 'POST', data: data, isBinary: isBinary });
var self = this;
req.on('success', fn);
req.on('error', function (err) {
self.onError('xhr post error', err);
});
this.sendXhr = req;
};
/**
* Starts a poll cycle.
*
* @api private
*/
XHR.prototype.doPoll = function () {
debug('xhr poll');
var req = this.request();
var self = this;
req.on('data', function (data) {
self.onData(data);
});
req.on('error', function (err) {
self.onError('xhr poll error', err);
});
this.pollXhr = req;
};
/**
* Request constructor
*
* @param {Object} options
* @api public
*/
function Request (opts) {
this.method = opts.method || 'GET';
this.uri = opts.uri;
this.xd = !!opts.xd;
this.xs = !!opts.xs;
this.async = false !== opts.async;
this.data = undefined !== opts.data ? opts.data : null;
this.agent = opts.agent;
this.isBinary = opts.isBinary;
this.supportsBinary = opts.supportsBinary;
this.enablesXDR = opts.enablesXDR;
this.requestTimeout = opts.requestTimeout;
// SSL options for Node.js client
this.pfx = opts.pfx;
this.key = opts.key;
this.passphrase = opts.passphrase;
this.cert = opts.cert;
this.ca = opts.ca;
this.ciphers = opts.ciphers;
this.rejectUnauthorized = opts.rejectUnauthorized;
// other options for Node.js client
this.extraHeaders = opts.extraHeaders;
this.create();
}
/**
* Mix in `Emitter`.
*/
Emitter(Request.prototype);
/**
* Creates the XHR object and sends the request.
*
* @api private
*/
Request.prototype.create = function () {
var opts = { agent: this.agent, xdomain: this.xd, xscheme: this.xs, enablesXDR: this.enablesXDR };
// SSL options for Node.js client
opts.pfx = this.pfx;
opts.key = this.key;
opts.passphrase = this.passphrase;
opts.cert = this.cert;
opts.ca = this.ca;
opts.ciphers = this.ciphers;
opts.rejectUnauthorized = this.rejectUnauthorized;
var xhr = this.xhr = new XMLHttpRequest(opts);
var self = this;
try {
debug('xhr open %s: %s', this.method, this.uri);
xhr.open(this.method, this.uri, this.async);
try {
if (this.extraHeaders) {
xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);
for (var i in this.extraHeaders) {
if (this.extraHeaders.hasOwnProperty(i)) {
xhr.setRequestHeader(i, this.extraHeaders[i]);
}
}
}
} catch (e) {}
if ('POST' === this.method) {
try {
if (this.isBinary) {
xhr.setRequestHeader('Content-type', 'application/octet-stream');
} else {
xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
}
} catch (e) {}
}
try {
xhr.setRequestHeader('Accept', '*/*');
} catch (e) {}
// ie6 check
if ('withCredentials' in xhr) {
xhr.withCredentials = true;
}
if (this.requestTimeout) {
xhr.timeout = this.requestTimeout;
}
if (this.hasXDR()) {
xhr.onload = function () {
self.onLoad();
};
xhr.onerror = function () {
self.onError(xhr.responseText);
};
} else {
xhr.onreadystatechange = function () {
if (xhr.readyState === 2) {
var contentType;
try {
contentType = xhr.getResponseHeader('Content-Type');
} catch (e) {}
if (contentType === 'application/octet-stream') {
xhr.responseType = 'arraybuffer';
}
}
if (4 !== xhr.readyState) return;
if (200 === xhr.status || 1223 === xhr.status) {
self.onLoad();
} else {
// make sure the `error` event handler that's user-set
// does not throw in the same tick and gets caught here
setTimeout(function () {
self.onError(xhr.status);
}, 0);
}
};
}
debug('xhr data %s', this.data);
xhr.send(this.data);
} catch (e) {
// Need to defer since .create() is called directly fhrom the constructor
// and thus the 'error' event can only be only bound *after* this exception
// occurs. Therefore, also, we cannot throw here at all.
setTimeout(function () {
self.onError(e);
}, 0);
return;
}
if (global.document) {
this.index = Request.requestsCount++;
Request.requests[this.index] = this;
}
};
/**
* Called upon successful response.
*
* @api private
*/
Request.prototype.onSuccess = function () {
this.emit('success');
this.cleanup();
};
/**
* Called if we have data.
*
* @api private
*/
Request.prototype.onData = function (data) {
this.emit('data', data);
this.onSuccess();
};
/**
* Called upon error.
*
* @api private
*/
Request.prototype.onError = function (err) {
this.emit('error', err);
this.cleanup(true);
};
/**
* Cleans up house.
*
* @api private
*/
Request.prototype.cleanup = function (fromError) {
if ('undefined' === typeof this.xhr || null === this.xhr) {
return;
}
// xmlhttprequest
if (this.hasXDR()) {
this.xhr.onload = this.xhr.onerror = empty;
} else {
this.xhr.onreadystatechange = empty;
}
if (fromError) {
try {
this.xhr.abort();
} catch (e) {}
}
if (global.document) {
delete Request.requests[this.index];
}
this.xhr = null;
};
/**
* Called upon load.
*
* @api private
*/
Request.prototype.onLoad = function () {
var data;
try {
var contentType;
try {
contentType = this.xhr.getResponseHeader('Content-Type');
} catch (e) {}
if (contentType === 'application/octet-stream') {
data = this.xhr.response || this.xhr.responseText;
} else {
data = this.xhr.responseText;
}
} catch (e) {
this.onError(e);
}
if (null != data) {
this.onData(data);
}
};
/**
* Check if it has XDomainRequest.
*
* @api private
*/
Request.prototype.hasXDR = function () {
return 'undefined' !== typeof global.XDomainRequest && !this.xs && this.enablesXDR;
};
/**
* Aborts the request.
*
* @api public
*/
Request.prototype.abort = function () {
this.cleanup();
};
/**
* Aborts pending requests when unloading the window. This is needed to prevent
* memory leaks (e.g. when using IE) and to ensure that no spurious error is
* emitted.
*/
Request.requestsCount = 0;
Request.requests = {};
if (global.document) {
if (global.attachEvent) {
global.attachEvent('onunload', unloadHandler);
} else if (global.addEventListener) {
global.addEventListener('beforeunload', unloadHandler, false);
}
}
function unloadHandler () {
for (var i in Request.requests) {
if (Request.requests.hasOwnProperty(i)) {
Request.requests[i].abort();
}
}
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./polling":86,"component-emitter":75,"component-inherit":89,"debug":77,"xmlhttprequest-ssl":88}],86:[function(require,module,exports){
/**
* Module dependencies.
*/
var Transport = require('../transport');
var parseqs = require('parseqs');
var parser = require('engine.io-parser');
var inherit = require('component-inherit');
var yeast = require('yeast');
var debug = require('debug')('engine.io-client:polling');
/**
* Module exports.
*/
module.exports = Polling;
/**
* Is XHR2 supported?
*/
var hasXHR2 = (function () {
var XMLHttpRequest = require('xmlhttprequest-ssl');
var xhr = new XMLHttpRequest({ xdomain: false });
return null != xhr.responseType;
})();
/**
* Polling interface.
*
* @param {Object} opts
* @api private
*/
function Polling (opts) {
var forceBase64 = (opts && opts.forceBase64);
if (!hasXHR2 || forceBase64) {
this.supportsBinary = false;
}
Transport.call(this, opts);
}
/**
* Inherits from Transport.
*/
inherit(Polling, Transport);
/**
* Transport name.
*/
Polling.prototype.name = 'polling';
/**
* Opens the socket (triggers polling). We write a PING message to determine
* when the transport is open.
*
* @api private
*/
Polling.prototype.doOpen = function () {
this.poll();
};
/**
* Pauses polling.
*
* @param {Function} callback upon buffers are flushed and transport is paused
* @api private
*/
Polling.prototype.pause = function (onPause) {
var self = this;
this.readyState = 'pausing';
function pause () {
debug('paused');
self.readyState = 'paused';
onPause();
}
if (this.polling || !this.writable) {
var total = 0;
if (this.polling) {
debug('we are currently polling - waiting to pause');
total++;
this.once('pollComplete', function () {
debug('pre-pause polling complete');
--total || pause();
});
}
if (!this.writable) {
debug('we are currently writing - waiting to pause');
total++;
this.once('drain', function () {
debug('pre-pause writing complete');
--total || pause();
});
}
} else {
pause();
}
};
/**
* Starts polling cycle.
*
* @api public
*/
Polling.prototype.poll = function () {
debug('polling');
this.polling = true;
this.doPoll();
this.emit('poll');
};
/**
* Overloads onData to detect payloads.
*
* @api private
*/
Polling.prototype.onData = function (data) {
var self = this;
debug('polling got data %s', data);
var callback = function (packet, index, total) {
// if its the first message we consider the transport open
if ('opening' === self.readyState) {
self.onOpen();
}
// if its a close packet, we close the ongoing requests
if ('close' === packet.type) {
self.onClose();
return false;
}
// otherwise bypass onData and handle the message
self.onPacket(packet);
};
// decode payload
parser.decodePayload(data, this.socket.binaryType, callback);
// if an event did not trigger closing
if ('closed' !== this.readyState) {
// if we got data we're not polling
this.polling = false;
this.emit('pollComplete');
if ('open' === this.readyState) {
this.poll();
} else {
debug('ignoring poll - transport state "%s"', this.readyState);
}
}
};
/**
* For polling, send a close packet.
*
* @api private
*/
Polling.prototype.doClose = function () {
var self = this;
function close () {
debug('writing close packet');
self.write([{ type: 'close' }]);
}
if ('open' === this.readyState) {
debug('transport open - closing');
close();
} else {
// in case we're trying to close while
// handshaking is in progress (GH-164)
debug('transport not open - deferring close');
this.once('open', close);
}
};
/**
* Writes a packets payload.
*
* @param {Array} data packets
* @param {Function} drain callback
* @api private
*/
Polling.prototype.write = function (packets) {
var self = this;
this.writable = false;
var callbackfn = function () {
self.writable = true;
self.emit('drain');
};
parser.encodePayload(packets, this.supportsBinary, function (data) {
self.doWrite(data, callbackfn);
});
};
/**
* Generates uri for connection.
*
* @api private
*/
Polling.prototype.uri = function () {
var query = this.query || {};
var schema = this.secure ? 'https' : 'http';
var port = '';
// cache busting is forced
if (false !== this.timestampRequests) {
query[this.timestampParam] = yeast();
}
if (!this.supportsBinary && !query.sid) {
query.b64 = 1;
}
query = parseqs.encode(query);
// avoid port if default for schema
if (this.port && (('https' === schema && Number(this.port) !== 443) ||
('http' === schema && Number(this.port) !== 80))) {
port = ':' + this.port;
}
// prepend ? to query
if (query.length) {
query = '?' + query;
}
var ipv6 = this.hostname.indexOf(':') !== -1;
return schema + '://' + (ipv6 ? '[' + this.hostname + ']' : this.hostname) + port + this.path + query;
};
},{"../transport":82,"component-inherit":89,"debug":77,"engine.io-parser":90,"parseqs":99,"xmlhttprequest-ssl":88,"yeast":100}],87:[function(require,module,exports){
(function (global){
/**
* Module dependencies.
*/
var Transport = require('../transport');
var parser = require('engine.io-parser');
var parseqs = require('parseqs');
var inherit = require('component-inherit');
var yeast = require('yeast');
var debug = require('debug')('engine.io-client:websocket');
var BrowserWebSocket = global.WebSocket || global.MozWebSocket;
var NodeWebSocket;
if (typeof window === 'undefined') {
try {
NodeWebSocket = require('ws');
} catch (e) { }
}
/**
* Get either the `WebSocket` or `MozWebSocket` globals
* in the browser or try to resolve WebSocket-compatible
* interface exposed by `ws` for Node-like environment.
*/
var WebSocket = BrowserWebSocket;
if (!WebSocket && typeof window === 'undefined') {
WebSocket = NodeWebSocket;
}
/**
* Module exports.
*/
module.exports = WS;
/**
* WebSocket transport constructor.
*
* @api {Object} connection options
* @api public
*/
function WS (opts) {
var forceBase64 = (opts && opts.forceBase64);
if (forceBase64) {
this.supportsBinary = false;
}
this.perMessageDeflate = opts.perMessageDeflate;
this.usingBrowserWebSocket = BrowserWebSocket && !opts.forceNode;
this.protocols = opts.protocols;
if (!this.usingBrowserWebSocket) {
WebSocket = NodeWebSocket;
}
Transport.call(this, opts);
}
/**
* Inherits from Transport.
*/
inherit(WS, Transport);
/**
* Transport name.
*
* @api public
*/
WS.prototype.name = 'websocket';
/*
* WebSockets support binary
*/
WS.prototype.supportsBinary = true;
/**
* Opens socket.
*
* @api private
*/
WS.prototype.doOpen = function () {
if (!this.check()) {
// let probe timeout
return;
}
var uri = this.uri();
var protocols = this.protocols;
var opts = {
agent: this.agent,
perMessageDeflate: this.perMessageDeflate
};
// SSL options for Node.js client
opts.pfx = this.pfx;
opts.key = this.key;
opts.passphrase = this.passphrase;
opts.cert = this.cert;
opts.ca = this.ca;
opts.ciphers = this.ciphers;
opts.rejectUnauthorized = this.rejectUnauthorized;
if (this.extraHeaders) {
opts.headers = this.extraHeaders;
}
if (this.localAddress) {
opts.localAddress = this.localAddress;
}
try {
this.ws = this.usingBrowserWebSocket ? (protocols ? new WebSocket(uri, protocols) : new WebSocket(uri)) : new WebSocket(uri, protocols, opts);
} catch (err) {
return this.emit('error', err);
}
if (this.ws.binaryType === undefined) {
this.supportsBinary = false;
}
if (this.ws.supports && this.ws.supports.binary) {
this.supportsBinary = true;
this.ws.binaryType = 'nodebuffer';
} else {
this.ws.binaryType = 'arraybuffer';
}
this.addEventListeners();
};
/**
* Adds event listeners to the socket
*
* @api private
*/
WS.prototype.addEventListeners = function () {
var self = this;
this.ws.onopen = function () {
self.onOpen();
};
this.ws.onclose = function () {
self.onClose();
};
this.ws.onmessage = function (ev) {
self.onData(ev.data);
};
this.ws.onerror = function (e) {
self.onError('websocket error', e);
};
};
/**
* Writes data to socket.
*
* @param {Array} array of packets.
* @api private
*/
WS.prototype.write = function (packets) {
var self = this;
this.writable = false;
// encodePacket efficient as it uses WS framing
// no need for encodePayload
var total = packets.length;
for (var i = 0, l = total; i < l; i++) {
(function (packet) {
parser.encodePacket(packet, self.supportsBinary, function (data) {
if (!self.usingBrowserWebSocket) {
// always create a new object (GH-437)
var opts = {};
if (packet.options) {
opts.compress = packet.options.compress;
}
if (self.perMessageDeflate) {
var len = 'string' === typeof data ? global.Buffer.byteLength(data) : data.length;
if (len < self.perMessageDeflate.threshold) {
opts.compress = false;
}
}
}
// Sometimes the websocket has already been closed but the browser didn't
// have a chance of informing us about it yet, in that case send will
// throw an error
try {
if (self.usingBrowserWebSocket) {
// TypeError is thrown when passing the second argument on Safari
self.ws.send(data);
} else {
self.ws.send(data, opts);
}
} catch (e) {
debug('websocket closed before onclose event');
}
--total || done();
});
})(packets[i]);
}
function done () {
self.emit('flush');
// fake drain
// defer to next tick to allow Socket to clear writeBuffer
setTimeout(function () {
self.writable = true;
self.emit('drain');
}, 0);
}
};
/**
* Called upon close
*
* @api private
*/
WS.prototype.onClose = function () {
Transport.prototype.onClose.call(this);
};
/**
* Closes socket.
*
* @api private
*/
WS.prototype.doClose = function () {
if (typeof this.ws !== 'undefined') {
this.ws.close();
}
};
/**
* Generates uri for connection.
*
* @api private
*/
WS.prototype.uri = function () {
var query = this.query || {};
var schema = this.secure ? 'wss' : 'ws';
var port = '';
// avoid port if default for schema
if (this.port && (('wss' === schema && Number(this.port) !== 443) ||
('ws' === schema && Number(this.port) !== 80))) {
port = ':' + this.port;
}
// append timestamp to URI
if (this.timestampRequests) {
query[this.timestampParam] = yeast();
}
// communicate binary support capabilities
if (!this.supportsBinary) {
query.b64 = 1;
}
query = parseqs.encode(query);
// prepend ? to query
if (query.length) {
query = '?' + query;
}
var ipv6 = this.hostname.indexOf(':') !== -1;
return schema + '://' + (ipv6 ? '[' + this.hostname + ']' : this.hostname) + port + this.path + query;
};
/**
* Feature detection for WebSocket.
*
* @return {Boolean} whether this transport is available.
* @api public
*/
WS.prototype.check = function () {
return !!WebSocket && !('__initialize' in WebSocket && this.name === WS.prototype.name);
};
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"../transport":82,"component-inherit":89,"debug":77,"engine.io-parser":90,"parseqs":99,"ws":1,"yeast":100}],88:[function(require,module,exports){
(function (global){
// browser shim for xmlhttprequest module
var hasCORS = require('has-cors');
module.exports = function (opts) {
var xdomain = opts.xdomain;
// scheme must be same when usign XDomainRequest
// http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx
var xscheme = opts.xscheme;
// XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default.
// https://github.com/Automattic/engine.io-client/pull/217
var enablesXDR = opts.enablesXDR;
// XMLHttpRequest can be disabled on IE
try {
if ('undefined' !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {
return new XMLHttpRequest();
}
} catch (e) { }
// Use XDomainRequest for IE8 if enablesXDR is true
// because loading bar keeps flashing when using jsonp-polling
// https://github.com/yujiosaka/socke.io-ie8-loading-example
try {
if ('undefined' !== typeof XDomainRequest && !xscheme && enablesXDR) {
return new XDomainRequest();
}
} catch (e) { }
if (!xdomain) {
try {
return new global[['Active'].concat('Object').join('X')]('Microsoft.XMLHTTP');
} catch (e) { }
}
};
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"has-cors":101}],89:[function(require,module,exports){
module.exports = function(a, b){
var fn = function(){};
fn.prototype = b.prototype;
a.prototype = new fn;
a.prototype.constructor = a;
};
},{}],90:[function(require,module,exports){
(function (global){
/**
* Module dependencies.
*/
var keys = require('./keys');
var hasBinary = require('has-binary2');
var sliceBuffer = require('arraybuffer.slice');
var after = require('after');
var utf8 = require('./utf8');
var base64encoder;
if (global && global.ArrayBuffer) {
base64encoder = require('base64-arraybuffer');
}
/**
* Check if we are running an android browser. That requires us to use
* ArrayBuffer with polling transports...
*
* http://ghinda.net/jpeg-blob-ajax-android/
*/
var isAndroid = typeof navigator !== 'undefined' && /Android/i.test(navigator.userAgent);
/**
* Check if we are running in PhantomJS.
* Uploading a Blob with PhantomJS does not work correctly, as reported here:
* https://github.com/ariya/phantomjs/issues/11395
* @type boolean
*/
var isPhantomJS = typeof navigator !== 'undefined' && /PhantomJS/i.test(navigator.userAgent);
/**
* When true, avoids using Blobs to encode payloads.
* @type boolean
*/
var dontSendBlobs = isAndroid || isPhantomJS;
/**
* Current protocol version.
*/
exports.protocol = 3;
/**
* Packet types.
*/
var packets = exports.packets = {
open: 0 // non-ws
, close: 1 // non-ws
, ping: 2
, pong: 3
, message: 4
, upgrade: 5
, noop: 6
};
var packetslist = keys(packets);
/**
* Premade error packet.
*/
var err = { type: 'error', data: 'parser error' };
/**
* Create a blob api even for blob builder when vendor prefixes exist
*/
var Blob = require('blob');
/**
* Encodes a packet.
*
* <packet type id> [ <data> ]
*
* Example:
*
* 5hello world
* 3
* 4
*
* Binary is encoded in an identical principle
*
* @api private
*/
exports.encodePacket = function (packet, supportsBinary, utf8encode, callback) {
if (typeof supportsBinary === 'function') {
callback = supportsBinary;
supportsBinary = false;
}
if (typeof utf8encode === 'function') {
callback = utf8encode;
utf8encode = null;
}
var data = (packet.data === undefined)
? undefined
: packet.data.buffer || packet.data;
if (global.ArrayBuffer && data instanceof ArrayBuffer) {
return encodeArrayBuffer(packet, supportsBinary, callback);
} else if (Blob && data instanceof global.Blob) {
return encodeBlob(packet, supportsBinary, callback);
}
// might be an object with { base64: true, data: dataAsBase64String }
if (data && data.base64) {
return encodeBase64Object(packet, callback);
}
// Sending data as a utf-8 string
var encoded = packets[packet.type];
// data fragment is optional
if (undefined !== packet.data) {
encoded += utf8encode ? utf8.encode(String(packet.data), { strict: false }) : String(packet.data);
}
return callback('' + encoded);
};
function encodeBase64Object(packet, callback) {
// packet data is an object { base64: true, data: dataAsBase64String }
var message = 'b' + exports.packets[packet.type] + packet.data.data;
return callback(message);
}
/**
* Encode packet helpers for binary types
*/
function encodeArrayBuffer(packet, supportsBinary, callback) {
if (!supportsBinary) {
return exports.encodeBase64Packet(packet, callback);
}
var data = packet.data;
var contentArray = new Uint8Array(data);
var resultBuffer = new Uint8Array(1 + data.byteLength);
resultBuffer[0] = packets[packet.type];
for (var i = 0; i < contentArray.length; i++) {
resultBuffer[i+1] = contentArray[i];
}
return callback(resultBuffer.buffer);
}
function encodeBlobAsArrayBuffer(packet, supportsBinary, callback) {
if (!supportsBinary) {
return exports.encodeBase64Packet(packet, callback);
}
var fr = new FileReader();
fr.onload = function() {
packet.data = fr.result;
exports.encodePacket(packet, supportsBinary, true, callback);
};
return fr.readAsArrayBuffer(packet.data);
}
function encodeBlob(packet, supportsBinary, callback) {
if (!supportsBinary) {
return exports.encodeBase64Packet(packet, callback);
}
if (dontSendBlobs) {
return encodeBlobAsArrayBuffer(packet, supportsBinary, callback);
}
var length = new Uint8Array(1);
length[0] = packets[packet.type];
var blob = new Blob([length.buffer, packet.data]);
return callback(blob);
}
/**
* Encodes a packet with binary data in a base64 string
*
* @param {Object} packet, has `type` and `data`
* @return {String} base64 encoded message
*/
exports.encodeBase64Packet = function(packet, callback) {
var message = 'b' + exports.packets[packet.type];
if (Blob && packet.data instanceof global.Blob) {
var fr = new FileReader();
fr.onload = function() {
var b64 = fr.result.split(',')[1];
callback(message + b64);
};
return fr.readAsDataURL(packet.data);
}
var b64data;
try {
b64data = String.fromCharCode.apply(null, new Uint8Array(packet.data));
} catch (e) {
// iPhone Safari doesn't let you apply with typed arrays
var typed = new Uint8Array(packet.data);
var basic = new Array(typed.length);
for (var i = 0; i < typed.length; i++) {
basic[i] = typed[i];
}
b64data = String.fromCharCode.apply(null, basic);
}
message += global.btoa(b64data);
return callback(message);
};
/**
* Decodes a packet. Changes format to Blob if requested.
*
* @return {Object} with `type` and `data` (if any)
* @api private
*/
exports.decodePacket = function (data, binaryType, utf8decode) {
if (data === undefined) {
return err;
}
// String data
if (typeof data === 'string') {
if (data.charAt(0) === 'b') {
return exports.decodeBase64Packet(data.substr(1), binaryType);
}
if (utf8decode) {
data = tryDecode(data);
if (data === false) {
return err;
}
}
var type = data.charAt(0);
if (Number(type) != type || !packetslist[type]) {
return err;
}
if (data.length > 1) {
return { type: packetslist[type], data: data.substring(1) };
} else {
return { type: packetslist[type] };
}
}
var asArray = new Uint8Array(data);
var type = asArray[0];
var rest = sliceBuffer(data, 1);
if (Blob && binaryType === 'blob') {
rest = new Blob([rest]);
}
return { type: packetslist[type], data: rest };
};
function tryDecode(data) {
try {
data = utf8.decode(data, { strict: false });
} catch (e) {
return false;
}
return data;
}
/**
* Decodes a packet encoded in a base64 string
*
* @param {String} base64 encoded message
* @return {Object} with `type` and `data` (if any)
*/
exports.decodeBase64Packet = function(msg, binaryType) {
var type = packetslist[msg.charAt(0)];
if (!base64encoder) {
return { type: type, data: { base64: true, data: msg.substr(1) } };
}
var data = base64encoder.decode(msg.substr(1));
if (binaryType === 'blob' && Blob) {
data = new Blob([data]);
}
return { type: type, data: data };
};
/**
* Encodes multiple messages (payload).
*
* <length>:data
*
* Example:
*
* 11:hello world2:hi
*
* If any contents are binary, they will be encoded as base64 strings. Base64
* encoded strings are marked with a b before the length specifier
*
* @param {Array} packets
* @api private
*/
exports.encodePayload = function (packets, supportsBinary, callback) {
if (typeof supportsBinary === 'function') {
callback = supportsBinary;
supportsBinary = null;
}
var isBinary = hasBinary(packets);
if (supportsBinary && isBinary) {
if (Blob && !dontSendBlobs) {
return exports.encodePayloadAsBlob(packets, callback);
}
return exports.encodePayloadAsArrayBuffer(packets, callback);
}
if (!packets.length) {
return callback('0:');
}
function setLengthHeader(message) {
return message.length + ':' + message;
}
function encodeOne(packet, doneCallback) {
exports.encodePacket(packet, !isBinary ? false : supportsBinary, false, function(message) {
doneCallback(null, setLengthHeader(message));
});
}
map(packets, encodeOne, function(err, results) {
return callback(results.join(''));
});
};
/**
* Async array map using after
*/
function map(ary, each, done) {
var result = new Array(ary.length);
var next = after(ary.length, done);
var eachWithIndex = function(i, el, cb) {
each(el, function(error, msg) {
result[i] = msg;
cb(error, result);
});
};
for (var i = 0; i < ary.length; i++) {
eachWithIndex(i, ary[i], next);
}
}
/*
* Decodes data when a payload is maybe expected. Possible binary contents are
* decoded from their base64 representation
*
* @param {String} data, callback method
* @api public
*/
exports.decodePayload = function (data, binaryType, callback) {
if (typeof data !== 'string') {
return exports.decodePayloadAsBinary(data, binaryType, callback);
}
if (typeof binaryType === 'function') {
callback = binaryType;
binaryType = null;
}
var packet;
if (data === '') {
// parser error - ignoring payload
return callback(err, 0, 1);
}
var length = '', n, msg;
for (var i = 0, l = data.length; i < l; i++) {
var chr = data.charAt(i);
if (chr !== ':') {
length += chr;
continue;
}
if (length === '' || (length != (n = Number(length)))) {
// parser error - ignoring payload
return callback(err, 0, 1);
}
msg = data.substr(i + 1, n);
if (length != msg.length) {
// parser error - ignoring payload
return callback(err, 0, 1);
}
if (msg.length) {
packet = exports.decodePacket(msg, binaryType, false);
if (err.type === packet.type && err.data === packet.data) {
// parser error in individual packet - ignoring payload
return callback(err, 0, 1);
}
var ret = callback(packet, i + n, l);
if (false === ret) return;
}
// advance cursor
i += n;
length = '';
}
if (length !== '') {
// parser error - ignoring payload
return callback(err, 0, 1);
}
};
/**
* Encodes multiple messages (payload) as binary.
*
* <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
* 255><data>
*
* Example:
* 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
*
* @param {Array} packets
* @return {ArrayBuffer} encoded payload
* @api private
*/
exports.encodePayloadAsArrayBuffer = function(packets, callback) {
if (!packets.length) {
return callback(new ArrayBuffer(0));
}
function encodeOne(packet, doneCallback) {
exports.encodePacket(packet, true, true, function(data) {
return doneCallback(null, data);
});
}
map(packets, encodeOne, function(err, encodedPackets) {
var totalLength = encodedPackets.reduce(function(acc, p) {
var len;
if (typeof p === 'string'){
len = p.length;
} else {
len = p.byteLength;
}
return acc + len.toString().length + len + 2; // string/binary identifier + separator = 2
}, 0);
var resultArray = new Uint8Array(totalLength);
var bufferIndex = 0;
encodedPackets.forEach(function(p) {
var isString = typeof p === 'string';
var ab = p;
if (isString) {
var view = new Uint8Array(p.length);
for (var i = 0; i < p.length; i++) {
view[i] = p.charCodeAt(i);
}
ab = view.buffer;
}
if (isString) { // not true binary
resultArray[bufferIndex++] = 0;
} else { // true binary
resultArray[bufferIndex++] = 1;
}
var lenStr = ab.byteLength.toString();
for (var i = 0; i < lenStr.length; i++) {
resultArray[bufferIndex++] = parseInt(lenStr[i]);
}
resultArray[bufferIndex++] = 255;
var view = new Uint8Array(ab);
for (var i = 0; i < view.length; i++) {
resultArray[bufferIndex++] = view[i];
}
});
return callback(resultArray.buffer);
});
};
/**
* Encode as Blob
*/
exports.encodePayloadAsBlob = function(packets, callback) {
function encodeOne(packet, doneCallback) {
exports.encodePacket(packet, true, true, function(encoded) {
var binaryIdentifier = new Uint8Array(1);
binaryIdentifier[0] = 1;
if (typeof encoded === 'string') {
var view = new Uint8Array(encoded.length);
for (var i = 0; i < encoded.length; i++) {
view[i] = encoded.charCodeAt(i);
}
encoded = view.buffer;
binaryIdentifier[0] = 0;
}
var len = (encoded instanceof ArrayBuffer)
? encoded.byteLength
: encoded.size;
var lenStr = len.toString();
var lengthAry = new Uint8Array(lenStr.length + 1);
for (var i = 0; i < lenStr.length; i++) {
lengthAry[i] = parseInt(lenStr[i]);
}
lengthAry[lenStr.length] = 255;
if (Blob) {
var blob = new Blob([binaryIdentifier.buffer, lengthAry.buffer, encoded]);
doneCallback(null, blob);
}
});
}
map(packets, encodeOne, function(err, results) {
return callback(new Blob(results));
});
};
/*
* Decodes data when a payload is maybe expected. Strings are decoded by
* interpreting each byte as a key code for entries marked to start with 0. See
* description of encodePayloadAsBinary
*
* @param {ArrayBuffer} data, callback method
* @api public
*/
exports.decodePayloadAsBinary = function (data, binaryType, callback) {
if (typeof binaryType === 'function') {
callback = binaryType;
binaryType = null;
}
var bufferTail = data;
var buffers = [];
while (bufferTail.byteLength > 0) {
var tailArray = new Uint8Array(bufferTail);
var isString = tailArray[0] === 0;
var msgLength = '';
for (var i = 1; ; i++) {
if (tailArray[i] === 255) break;
// 310 = char length of Number.MAX_VALUE
if (msgLength.length > 310) {
return callback(err, 0, 1);
}
msgLength += tailArray[i];
}
bufferTail = sliceBuffer(bufferTail, 2 + msgLength.length);
msgLength = parseInt(msgLength);
var msg = sliceBuffer(bufferTail, 0, msgLength);
if (isString) {
try {
msg = String.fromCharCode.apply(null, new Uint8Array(msg));
} catch (e) {
// iPhone Safari doesn't let you apply to typed arrays
var typed = new Uint8Array(msg);
msg = '';
for (var i = 0; i < typed.length; i++) {
msg += String.fromCharCode(typed[i]);
}
}
}
buffers.push(msg);
bufferTail = sliceBuffer(bufferTail, msgLength);
}
var total = buffers.length;
buffers.forEach(function(buffer, i) {
callback(exports.decodePacket(buffer, binaryType, true), i, total);
});
};
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./keys":91,"./utf8":92,"after":93,"arraybuffer.slice":94,"base64-arraybuffer":73,"blob":95,"has-binary2":96}],91:[function(require,module,exports){
/**
* Gets the keys for an object.
*
* @return {Array} keys
* @api private
*/
module.exports = Object.keys || function keys (obj){
var arr = [];
var has = Object.prototype.hasOwnProperty;
for (var i in obj) {
if (has.call(obj, i)) {
arr.push(i);
}
}
return arr;
};
},{}],92:[function(require,module,exports){
(function (global){
/*! https://mths.be/utf8js v2.1.2 by @mathias */
;(function(root) {
// Detect free variables `exports`
var freeExports = typeof exports == 'object' && exports;
// Detect free variable `module`
var freeModule = typeof module == 'object' && module &&
module.exports == freeExports && module;
// Detect free variable `global`, from Node.js or Browserified code,
// and use it as `root`
var freeGlobal = typeof global == 'object' && global;
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
root = freeGlobal;
}
/*--------------------------------------------------------------------------*/
var stringFromCharCode = String.fromCharCode;
// Taken from https://mths.be/punycode
function ucs2decode(string) {
var output = [];
var counter = 0;
var length = string.length;
var value;
var extra;
while (counter < length) {
value = string.charCodeAt(counter++);
if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
// high surrogate, and there is a next character
extra = string.charCodeAt(counter++);
if ((extra & 0xFC00) == 0xDC00) { // low surrogate
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
} else {
// unmatched surrogate; only append this code unit, in case the next
// code unit is the high surrogate of a surrogate pair
output.push(value);
counter--;
}
} else {
output.push(value);
}
}
return output;
}
// Taken from https://mths.be/punycode
function ucs2encode(array) {
var length = array.length;
var index = -1;
var value;
var output = '';
while (++index < length) {
value = array[index];
if (value > 0xFFFF) {
value -= 0x10000;
output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
value = 0xDC00 | value & 0x3FF;
}
output += stringFromCharCode(value);
}
return output;
}
function checkScalarValue(codePoint, strict) {
if (codePoint >= 0xD800 && codePoint <= 0xDFFF) {
if (strict) {
throw Error(
'Lone surrogate U+' + codePoint.toString(16).toUpperCase() +
' is not a scalar value'
);
}
return false;
}
return true;
}
/*--------------------------------------------------------------------------*/
function createByte(codePoint, shift) {
return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80);
}
function encodeCodePoint(codePoint, strict) {
if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence
return stringFromCharCode(codePoint);
}
var symbol = '';
if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence
symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0);
}
else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence
if (!checkScalarValue(codePoint, strict)) {
codePoint = 0xFFFD;
}
symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0);
symbol += createByte(codePoint, 6);
}
else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence
symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0);
symbol += createByte(codePoint, 12);
symbol += createByte(codePoint, 6);
}
symbol += stringFromCharCode((codePoint & 0x3F) | 0x80);
return symbol;
}
function utf8encode(string, opts) {
opts = opts || {};
var strict = false !== opts.strict;
var codePoints = ucs2decode(string);
var length = codePoints.length;
var index = -1;
var codePoint;
var byteString = '';
while (++index < length) {
codePoint = codePoints[index];
byteString += encodeCodePoint(codePoint, strict);
}
return byteString;
}
/*--------------------------------------------------------------------------*/
function readContinuationByte() {
if (byteIndex >= byteCount) {
throw Error('Invalid byte index');
}
var continuationByte = byteArray[byteIndex] & 0xFF;
byteIndex++;
if ((continuationByte & 0xC0) == 0x80) {
return continuationByte & 0x3F;
}
// If we end up here, it’s not a continuation byte
throw Error('Invalid continuation byte');
}
function decodeSymbol(strict) {
var byte1;
var byte2;
var byte3;
var byte4;
var codePoint;
if (byteIndex > byteCount) {
throw Error('Invalid byte index');
}
if (byteIndex == byteCount) {
return false;
}
// Read first byte
byte1 = byteArray[byteIndex] & 0xFF;
byteIndex++;
// 1-byte sequence (no continuation bytes)
if ((byte1 & 0x80) == 0) {
return byte1;
}
// 2-byte sequence
if ((byte1 & 0xE0) == 0xC0) {
byte2 = readContinuationByte();
codePoint = ((byte1 & 0x1F) << 6) | byte2;
if (codePoint >= 0x80) {
return codePoint;
} else {
throw Error('Invalid continuation byte');
}
}
// 3-byte sequence (may include unpaired surrogates)
if ((byte1 & 0xF0) == 0xE0) {
byte2 = readContinuationByte();
byte3 = readContinuationByte();
codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
if (codePoint >= 0x0800) {
return checkScalarValue(codePoint, strict) ? codePoint : 0xFFFD;
} else {
throw Error('Invalid continuation byte');
}
}
// 4-byte sequence
if ((byte1 & 0xF8) == 0xF0) {
byte2 = readContinuationByte();
byte3 = readContinuationByte();
byte4 = readContinuationByte();
codePoint = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0C) |
(byte3 << 0x06) | byte4;
if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) {
return codePoint;
}
}
throw Error('Invalid UTF-8 detected');
}
var byteArray;
var byteCount;
var byteIndex;
function utf8decode(byteString, opts) {
opts = opts || {};
var strict = false !== opts.strict;
byteArray = ucs2decode(byteString);
byteCount = byteArray.length;
byteIndex = 0;
var codePoints = [];
var tmp;
while ((tmp = decodeSymbol(strict)) !== false) {
codePoints.push(tmp);
}
return ucs2encode(codePoints);
}
/*--------------------------------------------------------------------------*/
var utf8 = {
'version': '2.1.2',
'encode': utf8encode,
'decode': utf8decode
};
// Some AMD build optimizers, like r.js, check for specific condition patterns
// like the following:
if (
typeof define == 'function' &&
typeof define.amd == 'object' &&
define.amd
) {
define(function() {
return utf8;
});
} else if (freeExports && !freeExports.nodeType) {
if (freeModule) { // in Node.js or RingoJS v0.8.0+
freeModule.exports = utf8;
} else { // in Narwhal or RingoJS v0.7.0-
var object = {};
var hasOwnProperty = object.hasOwnProperty;
for (var key in utf8) {
hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]);
}
}
} else { // in Rhino or a web browser
root.utf8 = utf8;
}
}(this));
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],93:[function(require,module,exports){
module.exports = after
function after(count, callback, err_cb) {
var bail = false
err_cb = err_cb || noop
proxy.count = count
return (count === 0) ? callback() : proxy
function proxy(err, result) {
if (proxy.count <= 0) {
throw new Error('after called too many times')
}
--proxy.count
// after first error, rest are passed to err_cb
if (err) {
bail = true
callback(err)
// future error callbacks will go to error handler
callback = err_cb
} else if (proxy.count === 0 && !bail) {
callback(null, result)
}
}
}
function noop() {}
},{}],94:[function(require,module,exports){
/**
* An abstraction for slicing an arraybuffer even when
* ArrayBuffer.prototype.slice is not supported
*
* @api public
*/
module.exports = function(arraybuffer, start, end) {
var bytes = arraybuffer.byteLength;
start = start || 0;
end = end || bytes;
if (arraybuffer.slice) { return arraybuffer.slice(start, end); }
if (start < 0) { start += bytes; }
if (end < 0) { end += bytes; }
if (end > bytes) { end = bytes; }
if (start >= bytes || start >= end || bytes === 0) {
return new ArrayBuffer(0);
}
var abv = new Uint8Array(arraybuffer);
var result = new Uint8Array(end - start);
for (var i = start, ii = 0; i < end; i++, ii++) {
result[ii] = abv[i];
}
return result.buffer;
};
},{}],95:[function(require,module,exports){
(function (global){
/**
* Create a blob builder even when vendor prefixes exist
*/
var BlobBuilder = global.BlobBuilder
|| global.WebKitBlobBuilder
|| global.MSBlobBuilder
|| global.MozBlobBuilder;
/**
* Check if Blob constructor is supported
*/
var blobSupported = (function() {
try {
var a = new Blob(['hi']);
return a.size === 2;
} catch(e) {
return false;
}
})();
/**
* Check if Blob constructor supports ArrayBufferViews
* Fails in Safari 6, so we need to map to ArrayBuffers there.
*/
var blobSupportsArrayBufferView = blobSupported && (function() {
try {
var b = new Blob([new Uint8Array([1,2])]);
return b.size === 2;
} catch(e) {
return false;
}
})();
/**
* Check if BlobBuilder is supported
*/
var blobBuilderSupported = BlobBuilder
&& BlobBuilder.prototype.append
&& BlobBuilder.prototype.getBlob;
/**
* Helper function that maps ArrayBufferViews to ArrayBuffers
* Used by BlobBuilder constructor and old browsers that didn't
* support it in the Blob constructor.
*/
function mapArrayBufferViews(ary) {
for (var i = 0; i < ary.length; i++) {
var chunk = ary[i];
if (chunk.buffer instanceof ArrayBuffer) {
var buf = chunk.buffer;
// if this is a subarray, make a copy so we only
// include the subarray region from the underlying buffer
if (chunk.byteLength !== buf.byteLength) {
var copy = new Uint8Array(chunk.byteLength);
copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength));
buf = copy.buffer;
}
ary[i] = buf;
}
}
}
function BlobBuilderConstructor(ary, options) {
options = options || {};
var bb = new BlobBuilder();
mapArrayBufferViews(ary);
for (var i = 0; i < ary.length; i++) {
bb.append(ary[i]);
}
return (options.type) ? bb.getBlob(options.type) : bb.getBlob();
};
function BlobConstructor(ary, options) {
mapArrayBufferViews(ary);
return new Blob(ary, options || {});
};
module.exports = (function() {
if (blobSupported) {
return blobSupportsArrayBufferView ? global.Blob : BlobConstructor;
} else if (blobBuilderSupported) {
return BlobBuilderConstructor;
} else {
return undefined;
}
})();
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],96:[function(require,module,exports){
(function (global){
/* global Blob File */
/*
* Module requirements.
*/
var isArray = require('isarray');
var toString = Object.prototype.toString;
var withNativeBlob = typeof global.Blob === 'function' || toString.call(global.Blob) === '[object BlobConstructor]';
var withNativeFile = typeof global.File === 'function' || toString.call(global.File) === '[object FileConstructor]';
/**
* Module exports.
*/
module.exports = hasBinary;
/**
* Checks for binary data.
*
* Supports Buffer, ArrayBuffer, Blob and File.
*
* @param {Object} anything
* @api public
*/
function hasBinary (obj) {
if (!obj || typeof obj !== 'object') {
return false;
}
if (isArray(obj)) {
for (var i = 0, l = obj.length; i < l; i++) {
if (hasBinary(obj[i])) {
return true;
}
}
return false;
}
if ((typeof global.Buffer === 'function' && global.Buffer.isBuffer && global.Buffer.isBuffer(obj)) ||
(typeof global.ArrayBuffer === 'function' && obj instanceof ArrayBuffer) ||
(withNativeBlob && obj instanceof Blob) ||
(withNativeFile && obj instanceof File)
) {
return true;
}
// see: https://github.com/Automattic/has-binary/pull/4
if (obj.toJSON && typeof obj.toJSON === 'function' && arguments.length === 1) {
return hasBinary(obj.toJSON(), true);
}
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key) && hasBinary(obj[key])) {
return true;
}
}
return false;
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"isarray":97}],97:[function(require,module,exports){
var toString = {}.toString;
module.exports = Array.isArray || function (arr) {
return toString.call(arr) == '[object Array]';
};
},{}],98:[function(require,module,exports){
(function (global){
/**
* JSON parse.
*
* @see Based on jQuery#parseJSON (MIT) and JSON2
* @api private
*/
var rvalidchars = /^[\],:{}\s]*$/;
var rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
var rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
var rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g;
var rtrimLeft = /^\s+/;
var rtrimRight = /\s+$/;
module.exports = function parsejson(data) {
if ('string' != typeof data || !data) {
return null;
}
data = data.replace(rtrimLeft, '').replace(rtrimRight, '');
// Attempt to parse using the native JSON parser first
if (global.JSON && JSON.parse) {
return JSON.parse(data);
}
if (rvalidchars.test(data.replace(rvalidescape, '@')
.replace(rvalidtokens, ']')
.replace(rvalidbraces, ''))) {
return (new Function('return ' + data))();
}
};
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],99:[function(require,module,exports){
/**
* Compiles a querystring
* Returns string representation of the object
*
* @param {Object}
* @api private
*/
exports.encode = function (obj) {
var str = '';
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
if (str.length) str += '&';
str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
}
}
return str;
};
/**
* Parses a simple querystring into an object
*
* @param {String} qs
* @api private
*/
exports.decode = function(qs){
var qry = {};
var pairs = qs.split('&');
for (var i = 0, l = pairs.length; i < l; i++) {
var pair = pairs[i].split('=');
qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
}
return qry;
};
},{}],100:[function(require,module,exports){
'use strict';
var alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split('')
, length = 64
, map = {}
, seed = 0
, i = 0
, prev;
/**
* Return a string representing the specified number.
*
* @param {Number} num The number to convert.
* @returns {String} The string representation of the number.
* @api public
*/
function encode(num) {
var encoded = '';
do {
encoded = alphabet[num % length] + encoded;
num = Math.floor(num / length);
} while (num > 0);
return encoded;
}
/**
* Return the integer value specified by the given string.
*
* @param {String} str The string to convert.
* @returns {Number} The integer value represented by the string.
* @api public
*/
function decode(str) {
var decoded = 0;
for (i = 0; i < str.length; i++) {
decoded = decoded * length + map[str.charAt(i)];
}
return decoded;
}
/**
* Yeast: A tiny growing id generator.
*
* @returns {String} A unique id.
* @api public
*/
function yeast() {
var now = encode(+new Date());
if (now !== prev) return seed = 0, prev = now;
return now +'.'+ encode(seed++);
}
//
// Map each character to its index.
//
for (; i < length; i++) map[alphabet[i]] = i;
//
// Expose the `yeast`, `encode` and `decode` functions.
//
yeast.encode = encode;
yeast.decode = decode;
module.exports = yeast;
},{}],101:[function(require,module,exports){
/**
* Module exports.
*
* Logic borrowed from Modernizr:
*
* - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js
*/
try {
module.exports = typeof XMLHttpRequest !== 'undefined' &&
'withCredentials' in new XMLHttpRequest();
} catch (err) {
// if XMLHttp support is disabled in IE then it will throw
// when trying to create
module.exports = false;
}
},{}],102:[function(require,module,exports){
var indexOf = [].indexOf;
module.exports = function(arr, obj){
if (indexOf) return arr.indexOf(obj);
for (var i = 0; i < arr.length; ++i) {
if (arr[i] === obj) return i;
}
return -1;
};
},{}],103:[function(require,module,exports){
/**
* Parses an URI
*
* @author Steven Levithan <stevenlevithan.com> (MIT license)
* @api private
*/
var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
var parts = [
'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
];
module.exports = function parseuri(str) {
var src = str,
b = str.indexOf('['),
e = str.indexOf(']');
if (b != -1 && e != -1) {
str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
}
var m = re.exec(str || ''),
uri = {},
i = 14;
while (i--) {
uri[parts[i]] = m[i] || '';
}
if (b != -1 && e != -1) {
uri.source = src;
uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');
uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');
uri.ipv6uri = true;
}
return uri;
};
},{}],104:[function(require,module,exports){
(function (global){
/*global Blob,File*/
/**
* Module requirements
*/
var isArray = require('isarray');
var isBuf = require('./is-buffer');
var toString = Object.prototype.toString;
var withNativeBlob = typeof global.Blob === 'function' || toString.call(global.Blob) === '[object BlobConstructor]';
var withNativeFile = typeof global.File === 'function' || toString.call(global.File) === '[object FileConstructor]';
/**
* Replaces every Buffer | ArrayBuffer in packet with a numbered placeholder.
* Anything with blobs or files should be fed through removeBlobs before coming
* here.
*
* @param {Object} packet - socket.io event packet
* @return {Object} with deconstructed packet and list of buffers
* @api public
*/
exports.deconstructPacket = function(packet) {
var buffers = [];
var packetData = packet.data;
var pack = packet;
pack.data = _deconstructPacket(packetData, buffers);
pack.attachments = buffers.length; // number of binary 'attachments'
return {packet: pack, buffers: buffers};
};
function _deconstructPacket(data, buffers) {
if (!data) return data;
if (isBuf(data)) {
var placeholder = { _placeholder: true, num: buffers.length };
buffers.push(data);
return placeholder;
} else if (isArray(data)) {
var newData = new Array(data.length);
for (var i = 0; i < data.length; i++) {
newData[i] = _deconstructPacket(data[i], buffers);
}
return newData;
} else if (typeof data === 'object' && !(data instanceof Date)) {
var newData = {};
for (var key in data) {
newData[key] = _deconstructPacket(data[key], buffers);
}
return newData;
}
return data;
}
/**
* Reconstructs a binary packet from its placeholder packet and buffers
*
* @param {Object} packet - event packet with placeholders
* @param {Array} buffers - binary buffers to put in placeholder positions
* @return {Object} reconstructed packet
* @api public
*/
exports.reconstructPacket = function(packet, buffers) {
packet.data = _reconstructPacket(packet.data, buffers);
packet.attachments = undefined; // no longer useful
return packet;
};
function _reconstructPacket(data, buffers) {
if (!data) return data;
if (data && data._placeholder) {
return buffers[data.num]; // appropriate buffer (should be natural order anyway)
} else if (isArray(data)) {
for (var i = 0; i < data.length; i++) {
data[i] = _reconstructPacket(data[i], buffers);
}
} else if (typeof data === 'object') {
for (var key in data) {
data[key] = _reconstructPacket(data[key], buffers);
}
}
return data;
}
/**
* Asynchronously removes Blobs or Files from data via
* FileReader's readAsArrayBuffer method. Used before encoding
* data as msgpack. Calls callback with the blobless data.
*
* @param {Object} data
* @param {Function} callback
* @api private
*/
exports.removeBlobs = function(data, callback) {
function _removeBlobs(obj, curKey, containingObject) {
if (!obj) return obj;
// convert any blob
if ((withNativeBlob && obj instanceof Blob) ||
(withNativeFile && obj instanceof File)) {
pendingBlobs++;
// async filereader
var fileReader = new FileReader();
fileReader.onload = function() { // this.result == arraybuffer
if (containingObject) {
containingObject[curKey] = this.result;
}
else {
bloblessData = this.result;
}
// if nothing pending its callback time
if(! --pendingBlobs) {
callback(bloblessData);
}
};
fileReader.readAsArrayBuffer(obj); // blob -> arraybuffer
} else if (isArray(obj)) { // handle array
for (var i = 0; i < obj.length; i++) {
_removeBlobs(obj[i], i, obj);
}
} else if (typeof obj === 'object' && !isBuf(obj)) { // and object
for (var key in obj) {
_removeBlobs(obj[key], key, obj);
}
}
}
var pendingBlobs = 0;
var bloblessData = data;
_removeBlobs(bloblessData);
if (!pendingBlobs) {
callback(bloblessData);
}
};
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./is-buffer":106,"isarray":108}],105:[function(require,module,exports){
/**
* Module dependencies.
*/
var debug = require('debug')('socket.io-parser');
var Emitter = require('component-emitter');
var hasBin = require('has-binary2');
var binary = require('./binary');
var isBuf = require('./is-buffer');
/**
* Protocol version.
*
* @api public
*/
exports.protocol = 4;
/**
* Packet types.
*
* @api public
*/
exports.types = [
'CONNECT',
'DISCONNECT',
'EVENT',
'ACK',
'ERROR',
'BINARY_EVENT',
'BINARY_ACK'
];
/**
* Packet type `connect`.
*
* @api public
*/
exports.CONNECT = 0;
/**
* Packet type `disconnect`.
*
* @api public
*/
exports.DISCONNECT = 1;
/**
* Packet type `event`.
*
* @api public
*/
exports.EVENT = 2;
/**
* Packet type `ack`.
*
* @api public
*/
exports.ACK = 3;
/**
* Packet type `error`.
*
* @api public
*/
exports.ERROR = 4;
/**
* Packet type 'binary event'
*
* @api public
*/
exports.BINARY_EVENT = 5;
/**
* Packet type `binary ack`. For acks with binary arguments.
*
* @api public
*/
exports.BINARY_ACK = 6;
/**
* Encoder constructor.
*
* @api public
*/
exports.Encoder = Encoder;
/**
* Decoder constructor.
*
* @api public
*/
exports.Decoder = Decoder;
/**
* A socket.io Encoder instance
*
* @api public
*/
function Encoder() {}
/**
* Encode a packet as a single string if non-binary, or as a
* buffer sequence, depending on packet type.
*
* @param {Object} obj - packet object
* @param {Function} callback - function to handle encodings (likely engine.write)
* @return Calls callback with Array of encodings
* @api public
*/
Encoder.prototype.encode = function(obj, callback){
if ((obj.type === exports.EVENT || obj.type === exports.ACK) && hasBin(obj.data)) {
obj.type = obj.type === exports.EVENT ? exports.BINARY_EVENT : exports.BINARY_ACK;
}
debug('encoding packet %j', obj);
if (exports.BINARY_EVENT === obj.type || exports.BINARY_ACK === obj.type) {
encodeAsBinary(obj, callback);
}
else {
var encoding = encodeAsString(obj);
callback([encoding]);
}
};
/**
* Encode packet as string.
*
* @param {Object} packet
* @return {String} encoded
* @api private
*/
function encodeAsString(obj) {
// first is type
var str = '' + obj.type;
// attachments if we have them
if (exports.BINARY_EVENT === obj.type || exports.BINARY_ACK === obj.type) {
str += obj.attachments + '-';
}
// if we have a namespace other than `/`
// we append it followed by a comma `,`
if (obj.nsp && '/' !== obj.nsp) {
str += obj.nsp + ',';
}
// immediately followed by the id
if (null != obj.id) {
str += obj.id;
}
// json data
if (null != obj.data) {
str += JSON.stringify(obj.data);
}
debug('encoded %j as %s', obj, str);
return str;
}
/**
* Encode packet as 'buffer sequence' by removing blobs, and
* deconstructing packet into object with placeholders and
* a list of buffers.
*
* @param {Object} packet
* @return {Buffer} encoded
* @api private
*/
function encodeAsBinary(obj, callback) {
function writeEncoding(bloblessData) {
var deconstruction = binary.deconstructPacket(bloblessData);
var pack = encodeAsString(deconstruction.packet);
var buffers = deconstruction.buffers;
buffers.unshift(pack); // add packet info to beginning of data list
callback(buffers); // write all the buffers
}
binary.removeBlobs(obj, writeEncoding);
}
/**
* A socket.io Decoder instance
*
* @return {Object} decoder
* @api public
*/
function Decoder() {
this.reconstructor = null;
}
/**
* Mix in `Emitter` with Decoder.
*/
Emitter(Decoder.prototype);
/**
* Decodes an ecoded packet string into packet JSON.
*
* @param {String} obj - encoded packet
* @return {Object} packet
* @api public
*/
Decoder.prototype.add = function(obj) {
var packet;
if (typeof obj === 'string') {
packet = decodeString(obj);
if (exports.BINARY_EVENT === packet.type || exports.BINARY_ACK === packet.type) { // binary packet's json
this.reconstructor = new BinaryReconstructor(packet);
// no attachments, labeled binary but no binary data to follow
if (this.reconstructor.reconPack.attachments === 0) {
this.emit('decoded', packet);
}
} else { // non-binary full packet
this.emit('decoded', packet);
}
}
else if (isBuf(obj) || obj.base64) { // raw binary data
if (!this.reconstructor) {
throw new Error('got binary data when not reconstructing a packet');
} else {
packet = this.reconstructor.takeBinaryData(obj);
if (packet) { // received final buffer
this.reconstructor = null;
this.emit('decoded', packet);
}
}
}
else {
throw new Error('Unknown type: ' + obj);
}
};
/**
* Decode a packet String (JSON data)
*
* @param {String} str
* @return {Object} packet
* @api private
*/
function decodeString(str) {
var i = 0;
// look up type
var p = {
type: Number(str.charAt(0))
};
if (null == exports.types[p.type]) return error();
// look up attachments if type binary
if (exports.BINARY_EVENT === p.type || exports.BINARY_ACK === p.type) {
var buf = '';
while (str.charAt(++i) !== '-') {
buf += str.charAt(i);
if (i == str.length) break;
}
if (buf != Number(buf) || str.charAt(i) !== '-') {
throw new Error('Illegal attachments');
}
p.attachments = Number(buf);
}
// look up namespace (if any)
if ('/' === str.charAt(i + 1)) {
p.nsp = '';
while (++i) {
var c = str.charAt(i);
if (',' === c) break;
p.nsp += c;
if (i === str.length) break;
}
} else {
p.nsp = '/';
}
// look up id
var next = str.charAt(i + 1);
if ('' !== next && Number(next) == next) {
p.id = '';
while (++i) {
var c = str.charAt(i);
if (null == c || Number(c) != c) {
--i;
break;
}
p.id += str.charAt(i);
if (i === str.length) break;
}
p.id = Number(p.id);
}
// look up json data
if (str.charAt(++i)) {
p = tryParse(p, str.substr(i));
}
debug('decoded %s as %j', str, p);
return p;
}
function tryParse(p, str) {
try {
p.data = JSON.parse(str);
} catch(e){
return error();
}
return p;
}
/**
* Deallocates a parser's resources
*
* @api public
*/
Decoder.prototype.destroy = function() {
if (this.reconstructor) {
this.reconstructor.finishedReconstruction();
}
};
/**
* A manager of a binary event's 'buffer sequence'. Should
* be constructed whenever a packet of type BINARY_EVENT is
* decoded.
*
* @param {Object} packet
* @return {BinaryReconstructor} initialized reconstructor
* @api private
*/
function BinaryReconstructor(packet) {
this.reconPack = packet;
this.buffers = [];
}
/**
* Method to be called when binary data received from connection
* after a BINARY_EVENT packet.
*
* @param {Buffer | ArrayBuffer} binData - the raw binary data received
* @return {null | Object} returns null if more binary data is expected or
* a reconstructed packet object if all buffers have been received.
* @api private
*/
BinaryReconstructor.prototype.takeBinaryData = function(binData) {
this.buffers.push(binData);
if (this.buffers.length === this.reconPack.attachments) { // done with buffer list
var packet = binary.reconstructPacket(this.reconPack, this.buffers);
this.finishedReconstruction();
return packet;
}
return null;
};
/**
* Cleans up binary packet reconstruction variables.
*
* @api private
*/
BinaryReconstructor.prototype.finishedReconstruction = function() {
this.reconPack = null;
this.buffers = [];
};
function error() {
return {
type: exports.ERROR,
data: 'parser error'
};
}
},{"./binary":104,"./is-buffer":106,"component-emitter":75,"debug":77,"has-binary2":107}],106:[function(require,module,exports){
(function (global){
module.exports = isBuf;
/**
* Returns true if obj is a buffer or an arraybuffer.
*
* @api private
*/
function isBuf(obj) {
return (global.Buffer && global.Buffer.isBuffer(obj)) ||
(global.ArrayBuffer && obj instanceof ArrayBuffer);
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],107:[function(require,module,exports){
(function (global){
/* global Blob File */
/*
* Module requirements.
*/
var isArray = require('isarray');
var toString = Object.prototype.toString;
var withNativeBlob = typeof global.Blob === 'function' || toString.call(global.Blob) === '[object BlobConstructor]';
var withNativeFile = typeof global.File === 'function' || toString.call(global.File) === '[object FileConstructor]';
/**
* Module exports.
*/
module.exports = hasBinary;
/**
* Checks for binary data.
*
* Supports Buffer, ArrayBuffer, Blob and File.
*
* @param {Object} anything
* @api public
*/
function hasBinary (obj) {
if (!obj || typeof obj !== 'object') {
return false;
}
if (isArray(obj)) {
for (var i = 0, l = obj.length; i < l; i++) {
if (hasBinary(obj[i])) {
return true;
}
}
return false;
}
if ((typeof global.Buffer === 'function' && global.Buffer.isBuffer && global.Buffer.isBuffer(obj)) ||
(typeof global.ArrayBuffer === 'function' && obj instanceof ArrayBuffer) ||
(withNativeBlob && obj instanceof Blob) ||
(withNativeFile && obj instanceof File)
) {
return true;
}
// see: https://github.com/Automattic/has-binary/pull/4
if (obj.toJSON && typeof obj.toJSON === 'function' && arguments.length === 1) {
return hasBinary(obj.toJSON(), true);
}
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key) && hasBinary(obj[key])) {
return true;
}
}
return false;
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"isarray":108}],108:[function(require,module,exports){
arguments[4][97][0].apply(exports,arguments)
},{"dup":97}],109:[function(require,module,exports){
module.exports = toArray
function toArray(list, index) {
var array = []
index = index || 0
for (var i = index || 0; i < list.length; i++) {
array[i - index] = list[i]
}
return array
}
},{}],110:[function(require,module,exports){
// Generated by Babel
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.encode = encode;
/* global: window */
var _window = window;
var btoa = _window.btoa;
function encode(data) {
return btoa(unescape(encodeURIComponent(data)));
}
var isSupported = exports.isSupported = "btoa" in window;
},{}],111:[function(require,module,exports){
// Generated by Babel
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.newRequest = newRequest;
exports.resolveUrl = resolveUrl;
var _resolveUrl = require("resolve-url");
var _resolveUrl2 = _interopRequireDefault(_resolveUrl);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function newRequest() {
return new window.XMLHttpRequest();
} /* global window */
function resolveUrl(origin, link) {
return (0, _resolveUrl2.default)(origin, link);
}
},{"resolve-url":119}],112:[function(require,module,exports){
// Generated by Babel
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getSource = getSource;
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var FileSource = function () {
function FileSource(file) {
_classCallCheck(this, FileSource);
this._file = file;
this.size = file.size;
}
_createClass(FileSource, [{
key: "slice",
value: function slice(start, end) {
return this._file.slice(start, end);
}
}, {
key: "close",
value: function close() {}
}]);
return FileSource;
}();
function getSource(input) {
// Since we emulate the Blob type in our tests (not all target browsers
// support it), we cannot use `instanceof` for testing whether the input value
// can be handled. Instead, we simply check is the slice() function and the
// size property are available.
if (typeof input.slice === "function" && typeof input.size !== "undefined") {
return new FileSource(input);
}
throw new Error("source object may only be an instance of File or Blob in this environment");
}
},{}],113:[function(require,module,exports){
// Generated by Babel
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.setItem = setItem;
exports.getItem = getItem;
exports.removeItem = removeItem;
/* global window, localStorage */
var hasStorage = false;
try {
hasStorage = "localStorage" in window;
// Attempt to store and read entries from the local storage to detect Private
// Mode on Safari on iOS (see #49)
var key = "tusSupport";
localStorage.setItem(key, localStorage.getItem(key));
} catch (e) {
// If we try to access localStorage inside a sandboxed iframe, a SecurityError
// is thrown. When in private mode on iOS Safari, a QuotaExceededError is
// thrown (see #49)
if (e.code === e.SECURITY_ERR || e.code === e.QUOTA_EXCEEDED_ERR) {
hasStorage = false;
} else {
throw e;
}
}
var canStoreURLs = exports.canStoreURLs = hasStorage;
function setItem(key, value) {
if (!hasStorage) return;
return localStorage.setItem(key, value);
}
function getItem(key) {
if (!hasStorage) return;
return localStorage.getItem(key);
}
function removeItem(key) {
if (!hasStorage) return;
return localStorage.removeItem(key);
}
},{}],114:[function(require,module,exports){
// Generated by Babel
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var DetailedError = function (_Error) {
_inherits(DetailedError, _Error);
function DetailedError(error) {
var causingErr = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1];
var xhr = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2];
_classCallCheck(this, DetailedError);
var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(DetailedError).call(this, error.message));
_this.originalRequest = xhr;
_this.causingError = causingErr;
var message = error.message;
if (causingErr != null) {
message += ", caused by " + causingErr.toString();
}
if (xhr != null) {
message += ", originated from request (response code: " + xhr.status + ", response text: " + xhr.responseText + ")";
}
_this.message = message;
return _this;
}
return DetailedError;
}(Error);
exports.default = DetailedError;
},{}],115:[function(require,module,exports){
// Generated by Babel
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = fingerprint;
/**
* Generate a fingerprint for a file which will be used the store the endpoint
*
* @param {File} file
* @return {String}
*/
function fingerprint(file) {
return ["tus", file.name, file.type, file.size, file.lastModified].join("-");
}
},{}],116:[function(require,module,exports){
// Generated by Babel
"use strict";
var _upload = require("./upload");
var _upload2 = _interopRequireDefault(_upload);
var _storage = require("./node/storage");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* global window */
var defaultOptions = _upload2.default.defaultOptions;
if (typeof window !== "undefined") {
// Browser environment using XMLHttpRequest
var _window = window;
var XMLHttpRequest = _window.XMLHttpRequest;
var Blob = _window.Blob;
var isSupported = XMLHttpRequest && Blob && typeof Blob.prototype.slice === "function";
} else {
// Node.js environment using http module
var isSupported = true;
}
// The usage of the commonjs exporting syntax instead of the new ECMAScript
// one is actually inteded and prevents weird behaviour if we are trying to
// import this module in another module using Babel.
module.exports = {
Upload: _upload2.default,
isSupported: isSupported,
canStoreURLs: _storage.canStoreURLs,
defaultOptions: defaultOptions
};
},{"./node/storage":113,"./upload":117}],117:[function(require,module,exports){
// Generated by Babel
"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /* global window */
// We import the files used inside the Node environment which are rewritten
// for browsers using the rules defined in the package.json
Object.defineProperty(exports, "__esModule", {
value: true
});
var _fingerprint = require("./fingerprint");
var _fingerprint2 = _interopRequireDefault(_fingerprint);
var _error = require("./error");
var _error2 = _interopRequireDefault(_error);
var _extend = require("extend");
var _extend2 = _interopRequireDefault(_extend);
var _request = require("./node/request");
var _source = require("./node/source");
var _base = require("./node/base64");
var Base64 = _interopRequireWildcard(_base);
var _storage = require("./node/storage");
var Storage = _interopRequireWildcard(_storage);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var defaultOptions = {
endpoint: "",
fingerprint: _fingerprint2.default,
resume: true,
onProgress: null,
onChunkComplete: null,
onSuccess: null,
onError: null,
headers: {},
chunkSize: Infinity,
withCredentials: false,
uploadUrl: null,
uploadSize: null,
overridePatchMethod: false,
retryDelays: null
};
var Upload = function () {
function Upload(file, options) {
_classCallCheck(this, Upload);
this.options = (0, _extend2.default)(true, {}, defaultOptions, options);
// The underlying File/Blob object
this.file = file;
// The URL against which the file will be uploaded
this.url = null;
// The underlying XHR object for the current PATCH request
this._xhr = null;
// The fingerpinrt for the current file (set after start())
this._fingerprint = null;
// The offset used in the current PATCH request
this._offset = null;
// True if the current PATCH request has been aborted
this._aborted = false;
// The file's size in bytes
this._size = null;
// The Source object which will wrap around the given file and provides us
// with a unified interface for getting its size and slice chunks from its
// content allowing us to easily handle Files, Blobs, Buffers and Streams.
this._source = null;
// The current count of attempts which have been made. Null indicates none.
this._retryAttempt = 0;
// The timeout's ID which is used to delay the next retry
this._retryTimeout = null;
// The offset of the remote upload before the latest attempt was started.
this._offsetBeforeRetry = 0;
}
_createClass(Upload, [{
key: "start",
value: function start() {
var _this = this;
var file = this.file;
if (!file) {
this._emitError(new Error("tus: no file or stream to upload provided"));
return;
}
if (!this.options.endpoint) {
this._emitError(new Error("tus: no endpoint provided"));
return;
}
var source = this._source = (0, _source.getSource)(file, this.options.chunkSize);
// Firstly, check if the caller has supplied a manual upload size or else
// we will use the calculated size by the source object.
if (this.options.uploadSize != null) {
var size = +this.options.uploadSize;
if (isNaN(size)) {
throw new Error("tus: cannot convert `uploadSize` option into a number");
}
this._size = size;
} else {
var size = source.size;
// The size property will be null if we cannot calculate the file's size,
// for example if you handle a stream.
if (size == null) {
throw new Error("tus: cannot automatically derive upload's size from input and must be specified manually using the `uploadSize` option");
}
this._size = size;
}
var retryDelays = this.options.retryDelays;
if (retryDelays != null) {
if (Object.prototype.toString.call(retryDelays) !== "[object Array]") {
throw new Error("tus: the `retryDelays` option must either be an array or null");
} else {
(function () {
var errorCallback = _this.options.onError;
_this.options.onError = function (err) {
// Restore the original error callback which may have been set.
_this.options.onError = errorCallback;
// We will reset the attempt counter if
// - we were already able to connect to the server (offset != null) and
// - we were able to upload a small chunk of data to the server
var shouldResetDelays = _this._offset != null && _this._offset > _this._offsetBeforeRetry;
if (shouldResetDelays) {
_this._retryAttempt = 0;
}
var isOnline = true;
if (typeof window !== "undefined" && "navigator" in window && window.navigator.onLine === false) {
isOnline = false;
}
// We only attempt a retry if
// - we didn't exceed the maxium number of retries, yet, and
// - this error was caused by a request or it's response and
// - the browser does not indicate that we are offline
var shouldRetry = _this._retryAttempt < retryDelays.length && err.originalRequest != null && isOnline;
if (!shouldRetry) {
_this._emitError(err);
return;
}
var delay = retryDelays[_this._retryAttempt++];
_this._offsetBeforeRetry = _this._offset;
_this.options.uploadUrl = _this.url;
_this._retryTimeout = setTimeout(function () {
_this.start();
}, delay);
};
})();
}
}
// Reset the aborted flag when the upload is started or else the
// _startUpload will stop before sending a request if the upload has been
// aborted previously.
this._aborted = false;
// A URL has manually been specified, so we try to resume
if (this.options.uploadUrl != null) {
this.url = this.options.uploadUrl;
this._resumeUpload();
return;
}
// Try to find the endpoint for the file in the storage
if (this.options.resume) {
this._fingerprint = this.options.fingerprint(file);
var resumedUrl = Storage.getItem(this._fingerprint);
if (resumedUrl != null) {
this.url = resumedUrl;
this._resumeUpload();
return;
}
}
// An upload has not started for the file yet, so we start a new one
this._createUpload();
}
}, {
key: "abort",
value: function abort() {
if (this._xhr !== null) {
this._xhr.abort();
this._source.close();
this._aborted = true;
}
if (this._retryTimeout != null) {
clearTimeout(this._retryTimeout);
this._retryTimeout = null;
}
}
}, {
key: "_emitXhrError",
value: function _emitXhrError(xhr, err, causingErr) {
this._emitError(new _error2.default(err, causingErr, xhr));
}
}, {
key: "_emitError",
value: function _emitError(err) {
if (typeof this.options.onError === "function") {
this.options.onError(err);
} else {
throw err;
}
}
}, {
key: "_emitSuccess",
value: function _emitSuccess() {
if (typeof this.options.onSuccess === "function") {
this.options.onSuccess();
}
}
/**
* Publishes notification when data has been sent to the server. This
* data may not have been accepted by the server yet.
* @param {number} bytesSent Number of bytes sent to the server.
* @param {number} bytesTotal Total number of bytes to be sent to the server.
*/
}, {
key: "_emitProgress",
value: function _emitProgress(bytesSent, bytesTotal) {
if (typeof this.options.onProgress === "function") {
this.options.onProgress(bytesSent, bytesTotal);
}
}
/**
* Publishes notification when a chunk of data has been sent to the server
* and accepted by the server.
* @param {number} chunkSize Size of the chunk that was accepted by the
* server.
* @param {number} bytesAccepted Total number of bytes that have been
* accepted by the server.
* @param {number} bytesTotal Total number of bytes to be sent to the server.
*/
}, {
key: "_emitChunkComplete",
value: function _emitChunkComplete(chunkSize, bytesAccepted, bytesTotal) {
if (typeof this.options.onChunkComplete === "function") {
this.options.onChunkComplete(chunkSize, bytesAccepted, bytesTotal);
}
}
/**
* Set the headers used in the request and the withCredentials property
* as defined in the options
*
* @param {XMLHttpRequest} xhr
*/
}, {
key: "_setupXHR",
value: function _setupXHR(xhr) {
xhr.setRequestHeader("Tus-Resumable", "1.0.0");
var headers = this.options.headers;
for (var name in headers) {
xhr.setRequestHeader(name, headers[name]);
}
xhr.withCredentials = this.options.withCredentials;
}
/**
* Create a new upload using the creation extension by sending a POST
* request to the endpoint. After successful creation the file will be
* uploaded
*
* @api private
*/
}, {
key: "_createUpload",
value: function _createUpload() {
var _this2 = this;
var xhr = (0, _request.newRequest)();
xhr.open("POST", this.options.endpoint, true);
xhr.onload = function () {
if (!(xhr.status >= 200 && xhr.status < 300)) {
_this2._emitXhrError(xhr, new Error("tus: unexpected response while creating upload"));
return;
}
_this2.url = (0, _request.resolveUrl)(_this2.options.endpoint, xhr.getResponseHeader("Location"));
if (_this2.options.resume) {
Storage.setItem(_this2._fingerprint, _this2.url);
}
_this2._offset = 0;
_this2._startUpload();
};
xhr.onerror = function (err) {
_this2._emitXhrError(xhr, new Error("tus: failed to create upload"), err);
};
this._setupXHR(xhr);
xhr.setRequestHeader("Upload-Length", this._size);
// Add metadata if values have been added
var metadata = encodeMetadata(this.options.metadata);
if (metadata !== "") {
xhr.setRequestHeader("Upload-Metadata", metadata);
}
xhr.send(null);
}
/*
* Try to resume an existing upload. First a HEAD request will be sent
* to retrieve the offset. If the request fails a new upload will be
* created. In the case of a successful response the file will be uploaded.
*
* @api private
*/
}, {
key: "_resumeUpload",
value: function _resumeUpload() {
var _this3 = this;
var xhr = (0, _request.newRequest)();
xhr.open("HEAD", this.url, true);
xhr.onload = function () {
if (!(xhr.status >= 200 && xhr.status < 300)) {
if (_this3.options.resume) {
// Remove stored fingerprint and corresponding endpoint,
// since the file can not be found
Storage.removeItem(_this3._fingerprint);
}
// If the upload is locked (indicated by the 423 Locked status code), we
// emit an error instead of directly starting a new upload. This way the
// retry logic can catch the error and will retry the upload. An upload
// is usually locked for a short period of time and will be available
// afterwards.
if (xhr.status === 423) {
_this3._emitXhrError(xhr, new Error("tus: upload is currently locked; retry later"));
return;
}
// Try to create a new upload
_this3.url = null;
_this3._createUpload();
return;
}
var offset = parseInt(xhr.getResponseHeader("Upload-Offset"), 10);
if (isNaN(offset)) {
_this3._emitXhrError(xhr, new Error("tus: invalid or missing offset value"));
return;
}
var length = parseInt(xhr.getResponseHeader("Upload-Length"), 10);
if (isNaN(length)) {
_this3._emitXhrError(xhr, new Error("tus: invalid or missing length value"));
return;
}
// Upload has already been completed and we do not need to send additional
// data to the server
if (offset === length) {
_this3._emitProgress(length, length);
_this3._emitSuccess();
return;
}
_this3._offset = offset;
_this3._startUpload();
};
xhr.onerror = function (err) {
_this3._emitXhrError(xhr, new Error("tus: failed to resume upload"), err);
};
this._setupXHR(xhr);
xhr.send(null);
}
/**
* Start uploading the file using PATCH requests. The file will be divided
* into chunks as specified in the chunkSize option. During the upload
* the onProgress event handler may be invoked multiple times.
*
* @api private
*/
}, {
key: "_startUpload",
value: function _startUpload() {
var _this4 = this;
// If the upload has been aborted, we will not send the next PATCH request.
// This is important if the abort method was called during a callback, such
// as onChunkComplete or onProgress.
if (this._aborted) {
return;
}
var xhr = this._xhr = (0, _request.newRequest)();
// Some browser and servers may not support the PATCH method. For those
// cases, you can tell tus-js-client to use a POST request with the
// X-HTTP-Method-Override header for simulating a PATCH request.
if (this.options.overridePatchMethod) {
xhr.open("POST", this.url, true);
xhr.setRequestHeader("X-HTTP-Method-Override", "PATCH");
} else {
xhr.open("PATCH", this.url, true);
}
xhr.onload = function () {
if (!(xhr.status >= 200 && xhr.status < 300)) {
_this4._emitXhrError(xhr, new Error("tus: unexpected response while uploading chunk"));
return;
}
var offset = parseInt(xhr.getResponseHeader("Upload-Offset"), 10);
if (isNaN(offset)) {
_this4._emitXhrError(xhr, new Error("tus: invalid or missing offset value"));
return;
}
_this4._emitProgress(offset, _this4._size);
_this4._emitChunkComplete(offset - _this4._offset, offset, _this4._size);
_this4._offset = offset;
if (offset == _this4._size) {
// Yay, finally done :)
_this4._emitSuccess();
_this4._source.close();
return;
}
_this4._startUpload();
};
xhr.onerror = function (err) {
// Don't emit an error if the upload was aborted manually
if (_this4._aborted) {
return;
}
_this4._emitXhrError(xhr, new Error("tus: failed to upload chunk at offset " + _this4._offset), err);
};
// Test support for progress events before attaching an event listener
if ("upload" in xhr) {
xhr.upload.onprogress = function (e) {
if (!e.lengthComputable) {
return;
}
_this4._emitProgress(start + e.loaded, _this4._size);
};
}
this._setupXHR(xhr);
xhr.setRequestHeader("Upload-Offset", this._offset);
xhr.setRequestHeader("Content-Type", "application/offset+octet-stream");
var start = this._offset;
var end = this._offset + this.options.chunkSize;
// The specified chunkSize may be Infinity or the calcluated end position
// may exceed the file's size. In both cases, we limit the end position to
// the input's total size for simpler calculations and correctness.
if (end === Infinity || end > this._size) {
end = this._size;
}
xhr.send(this._source.slice(start, end));
}
}]);
return Upload;
}();
function encodeMetadata(metadata) {
if (!Base64.isSupported) {
return "";
}
var encoded = [];
for (var key in metadata) {
encoded.push(key + " " + Base64.encode(metadata[key]));
}
return encoded.join(",");
}
Upload.defaultOptions = defaultOptions;
exports.default = Upload;
},{"./error":114,"./fingerprint":115,"./node/base64":110,"./node/request":111,"./node/source":112,"./node/storage":113,"extend":118}],118:[function(require,module,exports){
'use strict';
var hasOwn = Object.prototype.hasOwnProperty;
var toStr = Object.prototype.toString;
var isArray = function isArray(arr) {
if (typeof Array.isArray === 'function') {
return Array.isArray(arr);
}
return toStr.call(arr) === '[object Array]';
};
var isPlainObject = function isPlainObject(obj) {
if (!obj || toStr.call(obj) !== '[object Object]') {
return false;
}
var hasOwnConstructor = hasOwn.call(obj, 'constructor');
var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf');
// Not own constructor property must be Object
if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) {
return false;
}
// Own properties are enumerated firstly, so to speed up,
// if last one is own, then all properties are own.
var key;
for (key in obj) { /**/ }
return typeof key === 'undefined' || hasOwn.call(obj, key);
};
module.exports = function extend() {
var options, name, src, copy, copyIsArray, clone;
var target = arguments[0];
var i = 1;
var length = arguments.length;
var deep = false;
// Handle a deep copy situation
if (typeof target === 'boolean') {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
}
if (target == null || (typeof target !== 'object' && typeof target !== 'function')) {
target = {};
}
for (; i < length; ++i) {
options = arguments[i];
// Only deal with non-null/undefined values
if (options != null) {
// Extend the base object
for (name in options) {
src = target[name];
copy = options[name];
// Prevent never-ending loop
if (target !== copy) {
// Recurse if we're merging plain objects or arrays
if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) {
if (copyIsArray) {
copyIsArray = false;
clone = src && isArray(src) ? src : [];
} else {
clone = src && isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
target[name] = extend(deep, clone, copy);
// Don't bring in undefined values
} else if (typeof copy !== 'undefined') {
target[name] = copy;
}
}
}
}
}
// Return the modified object
return target;
};
},{}],119:[function(require,module,exports){
// Copyright 2014 Simon Lydell
// X11 (“MIT”) Licensed. (See LICENSE.)
void (function(root, factory) {
if (typeof define === "function" && define.amd) {
define(factory)
} else if (typeof exports === "object") {
module.exports = factory()
} else {
root.resolveUrl = factory()
}
}(this, function() {
function resolveUrl(/* ...urls */) {
var numUrls = arguments.length
if (numUrls === 0) {
throw new Error("resolveUrl requires at least one argument; got none.")
}
var base = document.createElement("base")
base.href = arguments[0]
if (numUrls === 1) {
return base.href
}
var head = document.getElementsByTagName("head")[0]
head.insertBefore(base, head.firstChild)
var a = document.createElement("a")
var resolved
for (var index = 1; index < numUrls; index++) {
a.href = arguments[index]
resolved = a.href
base.href = resolved
}
head.removeChild(base)
return resolved
}
return resolveUrl
}));
},{}],120:[function(require,module,exports){
(function (global){
'use strict';
var required = require('requires-port')
, qs = require('querystringify')
, protocolre = /^([a-z][a-z0-9.+-]*:)?(\/\/)?([\S\s]*)/i
, slashes = /^[A-Za-z][A-Za-z0-9+-.]*:\/\//;
/**
* These are the parse rules for the URL parser, it informs the parser
* about:
*
* 0. The char it Needs to parse, if it's a string it should be done using
* indexOf, RegExp using exec and NaN means set as current value.
* 1. The property we should set when parsing this value.
* 2. Indication if it's backwards or forward parsing, when set as number it's
* the value of extra chars that should be split off.
* 3. Inherit from location if non existing in the parser.
* 4. `toLowerCase` the resulting value.
*/
var rules = [
['#', 'hash'], // Extract from the back.
['?', 'query'], // Extract from the back.
['/', 'pathname'], // Extract from the back.
['@', 'auth', 1], // Extract from the front.
[NaN, 'host', undefined, 1, 1], // Set left over value.
[/:(\d+)$/, 'port', undefined, 1], // RegExp the back.
[NaN, 'hostname', undefined, 1, 1] // Set left over.
];
/**
* These properties should not be copied or inherited from. This is only needed
* for all non blob URL's as a blob URL does not include a hash, only the
* origin.
*
* @type {Object}
* @private
*/
var ignore = { hash: 1, query: 1 };
/**
* The location object differs when your code is loaded through a normal page,
* Worker or through a worker using a blob. And with the blobble begins the
* trouble as the location object will contain the URL of the blob, not the
* location of the page where our code is loaded in. The actual origin is
* encoded in the `pathname` so we can thankfully generate a good "default"
* location from it so we can generate proper relative URL's again.
*
* @param {Object|String} loc Optional default location object.
* @returns {Object} lolcation object.
* @api public
*/
function lolcation(loc) {
loc = loc || global.location || {};
var finaldestination = {}
, type = typeof loc
, key;
if ('blob:' === loc.protocol) {
finaldestination = new URL(unescape(loc.pathname), {});
} else if ('string' === type) {
finaldestination = new URL(loc, {});
for (key in ignore) delete finaldestination[key];
} else if ('object' === type) {
for (key in loc) {
if (key in ignore) continue;
finaldestination[key] = loc[key];
}
if (finaldestination.slashes === undefined) {
finaldestination.slashes = slashes.test(loc.href);
}
}
return finaldestination;
}
/**
* @typedef ProtocolExtract
* @type Object
* @property {String} protocol Protocol matched in the URL, in lowercase.
* @property {Boolean} slashes `true` if protocol is followed by "//", else `false`.
* @property {String} rest Rest of the URL that is not part of the protocol.
*/
/**
* Extract protocol information from a URL with/without double slash ("//").
*
* @param {String} address URL we want to extract from.
* @return {ProtocolExtract} Extracted information.
* @api private
*/
function extractProtocol(address) {
var match = protocolre.exec(address);
return {
protocol: match[1] ? match[1].toLowerCase() : '',
slashes: !!match[2],
rest: match[3]
};
}
/**
* Resolve a relative URL pathname against a base URL pathname.
*
* @param {String} relative Pathname of the relative URL.
* @param {String} base Pathname of the base URL.
* @return {String} Resolved pathname.
* @api private
*/
function resolve(relative, base) {
var path = (base || '/').split('/').slice(0, -1).concat(relative.split('/'))
, i = path.length
, last = path[i - 1]
, unshift = false
, up = 0;
while (i--) {
if (path[i] === '.') {
path.splice(i, 1);
} else if (path[i] === '..') {
path.splice(i, 1);
up++;
} else if (up) {
if (i === 0) unshift = true;
path.splice(i, 1);
up--;
}
}
if (unshift) path.unshift('');
if (last === '.' || last === '..') path.push('');
return path.join('/');
}
/**
* The actual URL instance. Instead of returning an object we've opted-in to
* create an actual constructor as it's much more memory efficient and
* faster and it pleases my OCD.
*
* @constructor
* @param {String} address URL we want to parse.
* @param {Object|String} location Location defaults for relative paths.
* @param {Boolean|Function} parser Parser for the query string.
* @api public
*/
function URL(address, location, parser) {
if (!(this instanceof URL)) {
return new URL(address, location, parser);
}
var relative, extracted, parse, instruction, index, key
, instructions = rules.slice()
, type = typeof location
, url = this
, i = 0;
//
// The following if statements allows this module two have compatibility with
// 2 different API:
//
// 1. Node.js's `url.parse` api which accepts a URL, boolean as arguments
// where the boolean indicates that the query string should also be parsed.
//
// 2. The `URL` interface of the browser which accepts a URL, object as
// arguments. The supplied object will be used as default values / fall-back
// for relative paths.
//
if ('object' !== type && 'string' !== type) {
parser = location;
location = null;
}
if (parser && 'function' !== typeof parser) parser = qs.parse;
location = lolcation(location);
//
// Extract protocol information before running the instructions.
//
extracted = extractProtocol(address || '');
relative = !extracted.protocol && !extracted.slashes;
url.slashes = extracted.slashes || relative && location.slashes;
url.protocol = extracted.protocol || location.protocol || '';
address = extracted.rest;
//
// When the authority component is absent the URL starts with a path
// component.
//
if (!extracted.slashes) instructions[2] = [/(.*)/, 'pathname'];
for (; i < instructions.length; i++) {
instruction = instructions[i];
parse = instruction[0];
key = instruction[1];
if (parse !== parse) {
url[key] = address;
} else if ('string' === typeof parse) {
if (~(index = address.indexOf(parse))) {
if ('number' === typeof instruction[2]) {
url[key] = address.slice(0, index);
address = address.slice(index + instruction[2]);
} else {
url[key] = address.slice(index);
address = address.slice(0, index);
}
}
} else if ((index = parse.exec(address))) {
url[key] = index[1];
address = address.slice(0, index.index);
}
url[key] = url[key] || (
relative && instruction[3] ? location[key] || '' : ''
);
//
// Hostname, host and protocol should be lowercased so they can be used to
// create a proper `origin`.
//
if (instruction[4]) url[key] = url[key].toLowerCase();
}
//
// Also parse the supplied query string in to an object. If we're supplied
// with a custom parser as function use that instead of the default build-in
// parser.
//
if (parser) url.query = parser(url.query);
//
// If the URL is relative, resolve the pathname against the base URL.
//
if (
relative
&& location.slashes
&& url.pathname.charAt(0) !== '/'
&& (url.pathname !== '' || location.pathname !== '')
) {
url.pathname = resolve(url.pathname, location.pathname);
}
//
// We should not add port numbers if they are already the default port number
// for a given protocol. As the host also contains the port number we're going
// override it with the hostname which contains no port number.
//
if (!required(url.port, url.protocol)) {
url.host = url.hostname;
url.port = '';
}
//
// Parse down the `auth` for the username and password.
//
url.username = url.password = '';
if (url.auth) {
instruction = url.auth.split(':');
url.username = instruction[0] || '';
url.password = instruction[1] || '';
}
url.origin = url.protocol && url.host && url.protocol !== 'file:'
? url.protocol +'//'+ url.host
: 'null';
//
// The href is just the compiled result.
//
url.href = url.toString();
}
/**
* This is convenience method for changing properties in the URL instance to
* insure that they all propagate correctly.
*
* @param {String} part Property we need to adjust.
* @param {Mixed} value The newly assigned value.
* @param {Boolean|Function} fn When setting the query, it will be the function
* used to parse the query.
* When setting the protocol, double slash will be
* removed from the final url if it is true.
* @returns {URL}
* @api public
*/
function set(part, value, fn) {
var url = this;
switch (part) {
case 'query':
if ('string' === typeof value && value.length) {
value = (fn || qs.parse)(value);
}
url[part] = value;
break;
case 'port':
url[part] = value;
if (!required(value, url.protocol)) {
url.host = url.hostname;
url[part] = '';
} else if (value) {
url.host = url.hostname +':'+ value;
}
break;
case 'hostname':
url[part] = value;
if (url.port) value += ':'+ url.port;
url.host = value;
break;
case 'host':
url[part] = value;
if (/:\d+$/.test(value)) {
value = value.split(':');
url.port = value.pop();
url.hostname = value.join(':');
} else {
url.hostname = value;
url.port = '';
}
break;
case 'protocol':
url.protocol = value.toLowerCase();
url.slashes = !fn;
break;
case 'pathname':
url.pathname = value.length && value.charAt(0) !== '/' ? '/' + value : value;
break;
default:
url[part] = value;
}
for (var i = 0; i < rules.length; i++) {
var ins = rules[i];
if (ins[4]) url[ins[1]] = url[ins[1]].toLowerCase();
}
url.origin = url.protocol && url.host && url.protocol !== 'file:'
? url.protocol +'//'+ url.host
: 'null';
url.href = url.toString();
return url;
}
/**
* Transform the properties back in to a valid and full URL string.
*
* @param {Function} stringify Optional query stringify function.
* @returns {String}
* @api public
*/
function toString(stringify) {
if (!stringify || 'function' !== typeof stringify) stringify = qs.stringify;
var query
, url = this
, protocol = url.protocol;
if (protocol && protocol.charAt(protocol.length - 1) !== ':') protocol += ':';
var result = protocol + (url.slashes ? '//' : '');
if (url.username) {
result += url.username;
if (url.password) result += ':'+ url.password;
result += '@';
}
result += url.host + url.pathname;
query = 'object' === typeof url.query ? stringify(url.query) : url.query;
if (query) result += '?' !== query.charAt(0) ? '?'+ query : query;
if (url.hash) result += url.hash;
return result;
}
URL.prototype = { set: set, toString: toString };
//
// Expose the URL parser and some additional properties that might be useful for
// others or testing.
//
URL.extractProtocol = extractProtocol;
URL.location = lolcation;
URL.qs = qs;
module.exports = URL;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"querystringify":121,"requires-port":122}],121:[function(require,module,exports){
'use strict';
var has = Object.prototype.hasOwnProperty;
/**
* Decode a URI encoded string.
*
* @param {String} input The URI encoded string.
* @returns {String} The decoded string.
* @api private
*/
function decode(input) {
return decodeURIComponent(input.replace(/\+/g, ' '));
}
/**
* Simple query string parser.
*
* @param {String} query The query string that needs to be parsed.
* @returns {Object}
* @api public
*/
function querystring(query) {
var parser = /([^=?&]+)=?([^&]*)/g
, result = {}
, part;
//
// Little nifty parsing hack, leverage the fact that RegExp.exec increments
// the lastIndex property so we can continue executing this loop until we've
// parsed all results.
//
for (;
part = parser.exec(query);
result[decode(part[1])] = decode(part[2])
);
return result;
}
/**
* Transform a query string to an object.
*
* @param {Object} obj Object that should be transformed.
* @param {String} prefix Optional prefix.
* @returns {String}
* @api public
*/
function querystringify(obj, prefix) {
prefix = prefix || '';
var pairs = [];
//
// Optionally prefix with a '?' if needed
//
if ('string' !== typeof prefix) prefix = '?';
for (var key in obj) {
if (has.call(obj, key)) {
pairs.push(encodeURIComponent(key) +'='+ encodeURIComponent(obj[key]));
}
}
return pairs.length ? prefix + pairs.join('&') : '';
}
//
// Expose the module.
//
exports.stringify = querystringify;
exports.parse = querystring;
},{}],122:[function(require,module,exports){
'use strict';
/**
* Check if we're required to add a port number.
*
* @see https://url.spec.whatwg.org/#default-port
* @param {Number|String} port Port number we need to check
* @param {String} protocol Protocol we need to check against.
* @returns {Boolean} Is it a default port for the given protocol
* @api private
*/
module.exports = function required(port, protocol) {
protocol = protocol.split(':')[0];
port = +port;
if (!port) return false;
switch (protocol) {
case 'http':
case 'ws':
return port !== 80;
case 'https':
case 'wss':
return port !== 443;
case 'ftp':
return port !== 21;
case 'gopher':
return port !== 70;
case 'file':
return false;
}
return port !== 0;
};
},{}],123:[function(require,module,exports){
(function(self) {
'use strict';
if (self.fetch) {
return
}
var support = {
searchParams: 'URLSearchParams' in self,
iterable: 'Symbol' in self && 'iterator' in Symbol,
blob: 'FileReader' in self && 'Blob' in self && (function() {
try {
new Blob()
return true
} catch(e) {
return false
}
})(),
formData: 'FormData' in self,
arrayBuffer: 'ArrayBuffer' in self
}
if (support.arrayBuffer) {
var viewClasses = [
'[object Int8Array]',
'[object Uint8Array]',
'[object Uint8ClampedArray]',
'[object Int16Array]',
'[object Uint16Array]',
'[object Int32Array]',
'[object Uint32Array]',
'[object Float32Array]',
'[object Float64Array]'
]
var isDataView = function(obj) {
return obj && DataView.prototype.isPrototypeOf(obj)
}
var isArrayBufferView = ArrayBuffer.isView || function(obj) {
return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1
}
}
function normalizeName(name) {
if (typeof name !== 'string') {
name = String(name)
}
if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
throw new TypeError('Invalid character in header field name')
}
return name.toLowerCase()
}
function normalizeValue(value) {
if (typeof value !== 'string') {
value = String(value)
}
return value
}
// Build a destructive iterator for the value list
function iteratorFor(items) {
var iterator = {
next: function() {
var value = items.shift()
return {done: value === undefined, value: value}
}
}
if (support.iterable) {
iterator[Symbol.iterator] = function() {
return iterator
}
}
return iterator
}
function Headers(headers) {
this.map = {}
if (headers instanceof Headers) {
headers.forEach(function(value, name) {
this.append(name, value)
}, this)
} else if (Array.isArray(headers)) {
headers.forEach(function(header) {
this.append(header[0], header[1])
}, this)
} else if (headers) {
Object.getOwnPropertyNames(headers).forEach(function(name) {
this.append(name, headers[name])
}, this)
}
}
Headers.prototype.append = function(name, value) {
name = normalizeName(name)
value = normalizeValue(value)
var oldValue = this.map[name]
this.map[name] = oldValue ? oldValue+','+value : value
}
Headers.prototype['delete'] = function(name) {
delete this.map[normalizeName(name)]
}
Headers.prototype.get = function(name) {
name = normalizeName(name)
return this.has(name) ? this.map[name] : null
}
Headers.prototype.has = function(name) {
return this.map.hasOwnProperty(normalizeName(name))
}
Headers.prototype.set = function(name, value) {
this.map[normalizeName(name)] = normalizeValue(value)
}
Headers.prototype.forEach = function(callback, thisArg) {
for (var name in this.map) {
if (this.map.hasOwnProperty(name)) {
callback.call(thisArg, this.map[name], name, this)
}
}
}
Headers.prototype.keys = function() {
var items = []
this.forEach(function(value, name) { items.push(name) })
return iteratorFor(items)
}
Headers.prototype.values = function() {
var items = []
this.forEach(function(value) { items.push(value) })
return iteratorFor(items)
}
Headers.prototype.entries = function() {
var items = []
this.forEach(function(value, name) { items.push([name, value]) })
return iteratorFor(items)
}
if (support.iterable) {
Headers.prototype[Symbol.iterator] = Headers.prototype.entries
}
function consumed(body) {
if (body.bodyUsed) {
return Promise.reject(new TypeError('Already read'))
}
body.bodyUsed = true
}
function fileReaderReady(reader) {
return new Promise(function(resolve, reject) {
reader.onload = function() {
resolve(reader.result)
}
reader.onerror = function() {
reject(reader.error)
}
})
}
function readBlobAsArrayBuffer(blob) {
var reader = new FileReader()
var promise = fileReaderReady(reader)
reader.readAsArrayBuffer(blob)
return promise
}
function readBlobAsText(blob) {
var reader = new FileReader()
var promise = fileReaderReady(reader)
reader.readAsText(blob)
return promise
}
function readArrayBufferAsText(buf) {
var view = new Uint8Array(buf)
var chars = new Array(view.length)
for (var i = 0; i < view.length; i++) {
chars[i] = String.fromCharCode(view[i])
}
return chars.join('')
}
function bufferClone(buf) {
if (buf.slice) {
return buf.slice(0)
} else {
var view = new Uint8Array(buf.byteLength)
view.set(new Uint8Array(buf))
return view.buffer
}
}
function Body() {
this.bodyUsed = false
this._initBody = function(body) {
this._bodyInit = body
if (!body) {
this._bodyText = ''
} else if (typeof body === 'string') {
this._bodyText = body
} else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
this._bodyBlob = body
} else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
this._bodyFormData = body
} else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
this._bodyText = body.toString()
} else if (support.arrayBuffer && support.blob && isDataView(body)) {
this._bodyArrayBuffer = bufferClone(body.buffer)
// IE 10-11 can't handle a DataView body.
this._bodyInit = new Blob([this._bodyArrayBuffer])
} else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
this._bodyArrayBuffer = bufferClone(body)
} else {
throw new Error('unsupported BodyInit type')
}
if (!this.headers.get('content-type')) {
if (typeof body === 'string') {
this.headers.set('content-type', 'text/plain;charset=UTF-8')
} else if (this._bodyBlob && this._bodyBlob.type) {
this.headers.set('content-type', this._bodyBlob.type)
} else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')
}
}
}
if (support.blob) {
this.blob = function() {
var rejected = consumed(this)
if (rejected) {
return rejected
}
if (this._bodyBlob) {
return Promise.resolve(this._bodyBlob)
} else if (this._bodyArrayBuffer) {
return Promise.resolve(new Blob([this._bodyArrayBuffer]))
} else if (this._bodyFormData) {
throw new Error('could not read FormData body as blob')
} else {
return Promise.resolve(new Blob([this._bodyText]))
}
}
this.arrayBuffer = function() {
if (this._bodyArrayBuffer) {
return consumed(this) || Promise.resolve(this._bodyArrayBuffer)
} else {
return this.blob().then(readBlobAsArrayBuffer)
}
}
}
this.text = function() {
var rejected = consumed(this)
if (rejected) {
return rejected
}
if (this._bodyBlob) {
return readBlobAsText(this._bodyBlob)
} else if (this._bodyArrayBuffer) {
return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer))
} else if (this._bodyFormData) {
throw new Error('could not read FormData body as text')
} else {
return Promise.resolve(this._bodyText)
}
}
if (support.formData) {
this.formData = function() {
return this.text().then(decode)
}
}
this.json = function() {
return this.text().then(JSON.parse)
}
return this
}
// HTTP methods whose capitalization should be normalized
var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']
function normalizeMethod(method) {
var upcased = method.toUpperCase()
return (methods.indexOf(upcased) > -1) ? upcased : method
}
function Request(input, options) {
options = options || {}
var body = options.body
if (input instanceof Request) {
if (input.bodyUsed) {
throw new TypeError('Already read')
}
this.url = input.url
this.credentials = input.credentials
if (!options.headers) {
this.headers = new Headers(input.headers)
}
this.method = input.method
this.mode = input.mode
if (!body && input._bodyInit != null) {
body = input._bodyInit
input.bodyUsed = true
}
} else {
this.url = String(input)
}
this.credentials = options.credentials || this.credentials || 'omit'
if (options.headers || !this.headers) {
this.headers = new Headers(options.headers)
}
this.method = normalizeMethod(options.method || this.method || 'GET')
this.mode = options.mode || this.mode || null
this.referrer = null
if ((this.method === 'GET' || this.method === 'HEAD') && body) {
throw new TypeError('Body not allowed for GET or HEAD requests')
}
this._initBody(body)
}
Request.prototype.clone = function() {
return new Request(this, { body: this._bodyInit })
}
function decode(body) {
var form = new FormData()
body.trim().split('&').forEach(function(bytes) {
if (bytes) {
var split = bytes.split('=')
var name = split.shift().replace(/\+/g, ' ')
var value = split.join('=').replace(/\+/g, ' ')
form.append(decodeURIComponent(name), decodeURIComponent(value))
}
})
return form
}
function parseHeaders(rawHeaders) {
var headers = new Headers()
rawHeaders.split(/\r?\n/).forEach(function(line) {
var parts = line.split(':')
var key = parts.shift().trim()
if (key) {
var value = parts.join(':').trim()
headers.append(key, value)
}
})
return headers
}
Body.call(Request.prototype)
function Response(bodyInit, options) {
if (!options) {
options = {}
}
this.type = 'default'
this.status = 'status' in options ? options.status : 200
this.ok = this.status >= 200 && this.status < 300
this.statusText = 'statusText' in options ? options.statusText : 'OK'
this.headers = new Headers(options.headers)
this.url = options.url || ''
this._initBody(bodyInit)
}
Body.call(Response.prototype)
Response.prototype.clone = function() {
return new Response(this._bodyInit, {
status: this.status,
statusText: this.statusText,
headers: new Headers(this.headers),
url: this.url
})
}
Response.error = function() {
var response = new Response(null, {status: 0, statusText: ''})
response.type = 'error'
return response
}
var redirectStatuses = [301, 302, 303, 307, 308]
Response.redirect = function(url, status) {
if (redirectStatuses.indexOf(status) === -1) {
throw new RangeError('Invalid status code')
}
return new Response(null, {status: status, headers: {location: url}})
}
self.Headers = Headers
self.Request = Request
self.Response = Response
self.fetch = function(input, init) {
return new Promise(function(resolve, reject) {
var request = new Request(input, init)
var xhr = new XMLHttpRequest()
xhr.onload = function() {
var options = {
status: xhr.status,
statusText: xhr.statusText,
headers: parseHeaders(xhr.getAllResponseHeaders() || '')
}
options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
var body = 'response' in xhr ? xhr.response : xhr.responseText
resolve(new Response(body, options))
}
xhr.onerror = function() {
reject(new TypeError('Network request failed'))
}
xhr.ontimeout = function() {
reject(new TypeError('Network request failed'))
}
xhr.open(request.method, request.url, true)
if (request.credentials === 'include') {
xhr.withCredentials = true
}
if ('responseType' in xhr && support.blob) {
xhr.responseType = 'blob'
}
request.headers.forEach(function(value, name) {
xhr.setRequestHeader(name, value)
})
xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
})
}
self.fetch.polyfill = true
})(typeof self !== 'undefined' ? self : this);
},{}],124:[function(require,module,exports){
var bel = require('bel') // turns template tag into DOM elements
var morphdom = require('morphdom') // efficiently diffs + morphs two DOM elements
var defaultEvents = require('./update-events.js') // default events to be copied when dom elements update
module.exports = bel
// TODO move this + defaultEvents to a new module once we receive more feedback
module.exports.update = function (fromNode, toNode, opts) {
if (!opts) opts = {}
if (opts.events !== false) {
if (!opts.onBeforeElUpdated) opts.onBeforeElUpdated = copier
}
return morphdom(fromNode, toNode, opts)
// morphdom only copies attributes. we decided we also wanted to copy events
// that can be set via attributes
function copier (f, t) {
// copy events:
var events = opts.events || defaultEvents
for (var i = 0; i < events.length; i++) {
var ev = events[i]
if (t[ev]) { // if new element has a whitelisted attribute
f[ev] = t[ev] // update existing element
} else if (f[ev]) { // if existing element has it and new one doesnt
f[ev] = undefined // remove it from existing element
}
}
var oldValue = f.value
var newValue = t.value
// copy values for form elements
if ((f.nodeName === 'INPUT' && f.type !== 'file') || f.nodeName === 'SELECT') {
if (!newValue) {
t.value = f.value
} else if (newValue !== oldValue) {
f.value = newValue
}
} else if (f.nodeName === 'TEXTAREA') {
if (t.getAttribute('value') === null) f.value = t.value
}
}
}
},{"./update-events.js":130,"bel":125,"morphdom":129}],125:[function(require,module,exports){
var document = require('global/document')
var hyperx = require('hyperx')
var onload = require('on-load')
var SVGNS = 'http://www.w3.org/2000/svg'
var XLINKNS = 'http://www.w3.org/1999/xlink'
var BOOL_PROPS = {
autofocus: 1,
checked: 1,
defaultchecked: 1,
disabled: 1,
formnovalidate: 1,
indeterminate: 1,
readonly: 1,
required: 1,
selected: 1,
willvalidate: 1
}
var COMMENT_TAG = '!--'
var SVG_TAGS = [
'svg',
'altGlyph', 'altGlyphDef', 'altGlyphItem', 'animate', 'animateColor',
'animateMotion', 'animateTransform', 'circle', 'clipPath', 'color-profile',
'cursor', 'defs', 'desc', 'ellipse', 'feBlend', 'feColorMatrix',
'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting',
'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB',
'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode',
'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting',
'feSpotLight', 'feTile', 'feTurbulence', 'filter', 'font', 'font-face',
'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri',
'foreignObject', 'g', 'glyph', 'glyphRef', 'hkern', 'image', 'line',
'linearGradient', 'marker', 'mask', 'metadata', 'missing-glyph', 'mpath',
'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect',
'set', 'stop', 'switch', 'symbol', 'text', 'textPath', 'title', 'tref',
'tspan', 'use', 'view', 'vkern'
]
function belCreateElement (tag, props, children) {
var el
// If an svg tag, it needs a namespace
if (SVG_TAGS.indexOf(tag) !== -1) {
props.namespace = SVGNS
}
// If we are using a namespace
var ns = false
if (props.namespace) {
ns = props.namespace
delete props.namespace
}
// Create the element
if (ns) {
el = document.createElementNS(ns, tag)
} else if (tag === COMMENT_TAG) {
return document.createComment(props.comment)
} else {
el = document.createElement(tag)
}
// If adding onload events
if (props.onload || props.onunload) {
var load = props.onload || function () {}
var unload = props.onunload || function () {}
onload(el, function belOnload () {
load(el)
}, function belOnunload () {
unload(el)
},
// We have to use non-standard `caller` to find who invokes `belCreateElement`
belCreateElement.caller.caller.caller)
delete props.onload
delete props.onunload
}
// Create the properties
for (var p in props) {
if (props.hasOwnProperty(p)) {
var key = p.toLowerCase()
var val = props[p]
// Normalize className
if (key === 'classname') {
key = 'class'
p = 'class'
}
// The for attribute gets transformed to htmlFor, but we just set as for
if (p === 'htmlFor') {
p = 'for'
}
// If a property is boolean, set itself to the key
if (BOOL_PROPS[key]) {
if (val === 'true') val = key
else if (val === 'false') continue
}
// If a property prefers being set directly vs setAttribute
if (key.slice(0, 2) === 'on') {
el[p] = val
} else {
if (ns) {
if (p === 'xlink:href') {
el.setAttributeNS(XLINKNS, p, val)
} else if (/^xmlns($|:)/i.test(p)) {
// skip xmlns definitions
} else {
el.setAttributeNS(null, p, val)
}
} else {
el.setAttribute(p, val)
}
}
}
}
function appendChild (childs) {
if (!Array.isArray(childs)) return
for (var i = 0; i < childs.length; i++) {
var node = childs[i]
if (Array.isArray(node)) {
appendChild(node)
continue
}
if (typeof node === 'number' ||
typeof node === 'boolean' ||
typeof node === 'function' ||
node instanceof Date ||
node instanceof RegExp) {
node = node.toString()
}
if (typeof node === 'string') {
if (el.lastChild && el.lastChild.nodeName === '#text') {
el.lastChild.nodeValue += node
continue
}
node = document.createTextNode(node)
}
if (node && node.nodeType) {
el.appendChild(node)
}
}
}
appendChild(children)
return el
}
module.exports = hyperx(belCreateElement, {comments: true})
module.exports.default = module.exports
module.exports.createElement = belCreateElement
},{"global/document":126,"hyperx":127,"on-load":63}],126:[function(require,module,exports){
(function (global){
var topLevel = typeof global !== 'undefined' ? global :
typeof window !== 'undefined' ? window : {}
var minDoc = require('min-document');
var doccy;
if (typeof document !== 'undefined') {
doccy = document;
} else {
doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];
if (!doccy) {
doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;
}
}
module.exports = doccy;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"min-document":1}],127:[function(require,module,exports){
var attrToProp = require('hyperscript-attribute-to-property')
var VAR = 0, TEXT = 1, OPEN = 2, CLOSE = 3, ATTR = 4
var ATTR_KEY = 5, ATTR_KEY_W = 6
var ATTR_VALUE_W = 7, ATTR_VALUE = 8
var ATTR_VALUE_SQ = 9, ATTR_VALUE_DQ = 10
var ATTR_EQ = 11, ATTR_BREAK = 12
var COMMENT = 13
module.exports = function (h, opts) {
if (!opts) opts = {}
var concat = opts.concat || function (a, b) {
return String(a) + String(b)
}
if (opts.attrToProp !== false) {
h = attrToProp(h)
}
return function (strings) {
var state = TEXT, reg = ''
var arglen = arguments.length
var parts = []
for (var i = 0; i < strings.length; i++) {
if (i < arglen - 1) {
var arg = arguments[i+1]
var p = parse(strings[i])
var xstate = state
if (xstate === ATTR_VALUE_DQ) xstate = ATTR_VALUE
if (xstate === ATTR_VALUE_SQ) xstate = ATTR_VALUE
if (xstate === ATTR_VALUE_W) xstate = ATTR_VALUE
if (xstate === ATTR) xstate = ATTR_KEY
p.push([ VAR, xstate, arg ])
parts.push.apply(parts, p)
} else parts.push.apply(parts, parse(strings[i]))
}
var tree = [null,{},[]]
var stack = [[tree,-1]]
for (var i = 0; i < parts.length; i++) {
var cur = stack[stack.length-1][0]
var p = parts[i], s = p[0]
if (s === OPEN && /^\//.test(p[1])) {
var ix = stack[stack.length-1][1]
if (stack.length > 1) {
stack.pop()
stack[stack.length-1][0][2][ix] = h(
cur[0], cur[1], cur[2].length ? cur[2] : undefined
)
}
} else if (s === OPEN) {
var c = [p[1],{},[]]
cur[2].push(c)
stack.push([c,cur[2].length-1])
} else if (s === ATTR_KEY || (s === VAR && p[1] === ATTR_KEY)) {
var key = ''
var copyKey
for (; i < parts.length; i++) {
if (parts[i][0] === ATTR_KEY) {
key = concat(key, parts[i][1])
} else if (parts[i][0] === VAR && parts[i][1] === ATTR_KEY) {
if (typeof parts[i][2] === 'object' && !key) {
for (copyKey in parts[i][2]) {
if (parts[i][2].hasOwnProperty(copyKey) && !cur[1][copyKey]) {
cur[1][copyKey] = parts[i][2][copyKey]
}
}
} else {
key = concat(key, parts[i][2])
}
} else break
}
if (parts[i][0] === ATTR_EQ) i++
var j = i
for (; i < parts.length; i++) {
if (parts[i][0] === ATTR_VALUE || parts[i][0] === ATTR_KEY) {
if (!cur[1][key]) cur[1][key] = strfn(parts[i][1])
else cur[1][key] = concat(cur[1][key], parts[i][1])
} else if (parts[i][0] === VAR
&& (parts[i][1] === ATTR_VALUE || parts[i][1] === ATTR_KEY)) {
if (!cur[1][key]) cur[1][key] = strfn(parts[i][2])
else cur[1][key] = concat(cur[1][key], parts[i][2])
} else {
if (key.length && !cur[1][key] && i === j
&& (parts[i][0] === CLOSE || parts[i][0] === ATTR_BREAK)) {
// https://html.spec.whatwg.org/multipage/infrastructure.html#boolean-attributes
// empty string is falsy, not well behaved value in browser
cur[1][key] = key.toLowerCase()
}
break
}
}
} else if (s === ATTR_KEY) {
cur[1][p[1]] = true
} else if (s === VAR && p[1] === ATTR_KEY) {
cur[1][p[2]] = true
} else if (s === CLOSE) {
if (selfClosing(cur[0]) && stack.length) {
var ix = stack[stack.length-1][1]
stack.pop()
stack[stack.length-1][0][2][ix] = h(
cur[0], cur[1], cur[2].length ? cur[2] : undefined
)
}
} else if (s === VAR && p[1] === TEXT) {
if (p[2] === undefined || p[2] === null) p[2] = ''
else if (!p[2]) p[2] = concat('', p[2])
if (Array.isArray(p[2][0])) {
cur[2].push.apply(cur[2], p[2])
} else {
cur[2].push(p[2])
}
} else if (s === TEXT) {
cur[2].push(p[1])
} else if (s === ATTR_EQ || s === ATTR_BREAK) {
// no-op
} else {
throw new Error('unhandled: ' + s)
}
}
if (tree[2].length > 1 && /^\s*$/.test(tree[2][0])) {
tree[2].shift()
}
if (tree[2].length > 2
|| (tree[2].length === 2 && /\S/.test(tree[2][1]))) {
throw new Error(
'multiple root elements must be wrapped in an enclosing tag'
)
}
if (Array.isArray(tree[2][0]) && typeof tree[2][0][0] === 'string'
&& Array.isArray(tree[2][0][2])) {
tree[2][0] = h(tree[2][0][0], tree[2][0][1], tree[2][0][2])
}
return tree[2][0]
function parse (str) {
var res = []
if (state === ATTR_VALUE_W) state = ATTR
for (var i = 0; i < str.length; i++) {
var c = str.charAt(i)
if (state === TEXT && c === '<') {
if (reg.length) res.push([TEXT, reg])
reg = ''
state = OPEN
} else if (c === '>' && !quot(state) && state !== COMMENT) {
if (state === OPEN) {
res.push([OPEN,reg])
} else if (state === ATTR_KEY) {
res.push([ATTR_KEY,reg])
} else if (state === ATTR_VALUE && reg.length) {
res.push([ATTR_VALUE,reg])
}
res.push([CLOSE])
reg = ''
state = TEXT
} else if (state === COMMENT && /-$/.test(reg) && c === '-') {
if (opts.comments) {
res.push([ATTR_VALUE,reg.substr(0, reg.length - 1)],[CLOSE])
}
reg = ''
state = TEXT
} else if (state === OPEN && /^!--$/.test(reg)) {
if (opts.comments) {
res.push([OPEN, reg],[ATTR_KEY,'comment'],[ATTR_EQ])
}
reg = c
state = COMMENT
} else if (state === TEXT || state === COMMENT) {
reg += c
} else if (state === OPEN && /\s/.test(c)) {
res.push([OPEN, reg])
reg = ''
state = ATTR
} else if (state === OPEN) {
reg += c
} else if (state === ATTR && /[^\s"'=/]/.test(c)) {
state = ATTR_KEY
reg = c
} else if (state === ATTR && /\s/.test(c)) {
if (reg.length) res.push([ATTR_KEY,reg])
res.push([ATTR_BREAK])
} else if (state === ATTR_KEY && /\s/.test(c)) {
res.push([ATTR_KEY,reg])
reg = ''
state = ATTR_KEY_W
} else if (state === ATTR_KEY && c === '=') {
res.push([ATTR_KEY,reg],[ATTR_EQ])
reg = ''
state = ATTR_VALUE_W
} else if (state === ATTR_KEY) {
reg += c
} else if ((state === ATTR_KEY_W || state === ATTR) && c === '=') {
res.push([ATTR_EQ])
state = ATTR_VALUE_W
} else if ((state === ATTR_KEY_W || state === ATTR) && !/\s/.test(c)) {
res.push([ATTR_BREAK])
if (/[\w-]/.test(c)) {
reg += c
state = ATTR_KEY
} else state = ATTR
} else if (state === ATTR_VALUE_W && c === '"') {
state = ATTR_VALUE_DQ
} else if (state === ATTR_VALUE_W && c === "'") {
state = ATTR_VALUE_SQ
} else if (state === ATTR_VALUE_DQ && c === '"') {
res.push([ATTR_VALUE,reg],[ATTR_BREAK])
reg = ''
state = ATTR
} else if (state === ATTR_VALUE_SQ && c === "'") {
res.push([ATTR_VALUE,reg],[ATTR_BREAK])
reg = ''
state = ATTR
} else if (state === ATTR_VALUE_W && !/\s/.test(c)) {
state = ATTR_VALUE
i--
} else if (state === ATTR_VALUE && /\s/.test(c)) {
res.push([ATTR_VALUE,reg],[ATTR_BREAK])
reg = ''
state = ATTR
} else if (state === ATTR_VALUE || state === ATTR_VALUE_SQ
|| state === ATTR_VALUE_DQ) {
reg += c
}
}
if (state === TEXT && reg.length) {
res.push([TEXT,reg])
reg = ''
} else if (state === ATTR_VALUE && reg.length) {
res.push([ATTR_VALUE,reg])
reg = ''
} else if (state === ATTR_VALUE_DQ && reg.length) {
res.push([ATTR_VALUE,reg])
reg = ''
} else if (state === ATTR_VALUE_SQ && reg.length) {
res.push([ATTR_VALUE,reg])
reg = ''
} else if (state === ATTR_KEY) {
res.push([ATTR_KEY,reg])
reg = ''
}
return res
}
}
function strfn (x) {
if (typeof x === 'function') return x
else if (typeof x === 'string') return x
else if (x && typeof x === 'object') return x
else return concat('', x)
}
}
function quot (state) {
return state === ATTR_VALUE_SQ || state === ATTR_VALUE_DQ
}
var hasOwn = Object.prototype.hasOwnProperty
function has (obj, key) { return hasOwn.call(obj, key) }
var closeRE = RegExp('^(' + [
'area', 'base', 'basefont', 'bgsound', 'br', 'col', 'command', 'embed',
'frame', 'hr', 'img', 'input', 'isindex', 'keygen', 'link', 'meta', 'param',
'source', 'track', 'wbr', '!--',
// SVG TAGS
'animate', 'animateTransform', 'circle', 'cursor', 'desc', 'ellipse',
'feBlend', 'feColorMatrix', 'feComposite',
'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap',
'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR',
'feGaussianBlur', 'feImage', 'feMergeNode', 'feMorphology',
'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile',
'feTurbulence', 'font-face-format', 'font-face-name', 'font-face-uri',
'glyph', 'glyphRef', 'hkern', 'image', 'line', 'missing-glyph', 'mpath',
'path', 'polygon', 'polyline', 'rect', 'set', 'stop', 'tref', 'use', 'view',
'vkern'
].join('|') + ')(?:[\.#][a-zA-Z0-9\u007F-\uFFFF_:-]+)*$')
function selfClosing (tag) { return closeRE.test(tag) }
},{"hyperscript-attribute-to-property":128}],128:[function(require,module,exports){
module.exports = attributeToProperty
var transform = {
'class': 'className',
'for': 'htmlFor',
'http-equiv': 'httpEquiv'
}
function attributeToProperty (h) {
return function (tagName, attrs, children) {
for (var attr in attrs) {
if (attr in transform) {
attrs[transform[attr]] = attrs[attr]
delete attrs[attr]
}
}
return h(tagName, attrs, children)
}
}
},{}],129:[function(require,module,exports){
'use strict';
var range; // Create a range object for efficently rendering strings to elements.
var NS_XHTML = 'http://www.w3.org/1999/xhtml';
var doc = typeof document === 'undefined' ? undefined : document;
var testEl = doc ?
doc.body || doc.createElement('div') :
{};
// Fixes <https://github.com/patrick-steele-idem/morphdom/issues/32>
// (IE7+ support) <=IE7 does not support el.hasAttribute(name)
var actualHasAttributeNS;
if (testEl.hasAttributeNS) {
actualHasAttributeNS = function(el, namespaceURI, name) {
return el.hasAttributeNS(namespaceURI, name);
};
} else if (testEl.hasAttribute) {
actualHasAttributeNS = function(el, namespaceURI, name) {
return el.hasAttribute(name);
};
} else {
actualHasAttributeNS = function(el, namespaceURI, name) {
return el.getAttributeNode(namespaceURI, name) != null;
};
}
var hasAttributeNS = actualHasAttributeNS;
function toElement(str) {
if (!range && doc.createRange) {
range = doc.createRange();
range.selectNode(doc.body);
}
var fragment;
if (range && range.createContextualFragment) {
fragment = range.createContextualFragment(str);
} else {
fragment = doc.createElement('body');
fragment.innerHTML = str;
}
return fragment.childNodes[0];
}
/**
* Returns true if two node's names are the same.
*
* NOTE: We don't bother checking `namespaceURI` because you will never find two HTML elements with the same
* nodeName and different namespace URIs.
*
* @param {Element} a
* @param {Element} b The target element
* @return {boolean}
*/
function compareNodeNames(fromEl, toEl) {
var fromNodeName = fromEl.nodeName;
var toNodeName = toEl.nodeName;
if (fromNodeName === toNodeName) {
return true;
}
if (toEl.actualize &&
fromNodeName.charCodeAt(0) < 91 && /* from tag name is upper case */
toNodeName.charCodeAt(0) > 90 /* target tag name is lower case */) {
// If the target element is a virtual DOM node then we may need to normalize the tag name
// before comparing. Normal HTML elements that are in the "http://www.w3.org/1999/xhtml"
// are converted to upper case
return fromNodeName === toNodeName.toUpperCase();
} else {
return false;
}
}
/**
* Create an element, optionally with a known namespace URI.
*
* @param {string} name the element name, e.g. 'div' or 'svg'
* @param {string} [namespaceURI] the element's namespace URI, i.e. the value of
* its `xmlns` attribute or its inferred namespace.
*
* @return {Element}
*/
function createElementNS(name, namespaceURI) {
return !namespaceURI || namespaceURI === NS_XHTML ?
doc.createElement(name) :
doc.createElementNS(namespaceURI, name);
}
/**
* Copies the children of one DOM element to another DOM element
*/
function moveChildren(fromEl, toEl) {
var curChild = fromEl.firstChild;
while (curChild) {
var nextChild = curChild.nextSibling;
toEl.appendChild(curChild);
curChild = nextChild;
}
return toEl;
}
function morphAttrs(fromNode, toNode) {
var attrs = toNode.attributes;
var i;
var attr;
var attrName;
var attrNamespaceURI;
var attrValue;
var fromValue;
for (i = attrs.length - 1; i >= 0; --i) {
attr = attrs[i];
attrName = attr.name;
attrNamespaceURI = attr.namespaceURI;
attrValue = attr.value;
if (attrNamespaceURI) {
attrName = attr.localName || attrName;
fromValue = fromNode.getAttributeNS(attrNamespaceURI, attrName);
if (fromValue !== attrValue) {
fromNode.setAttributeNS(attrNamespaceURI, attrName, attrValue);
}
} else {
fromValue = fromNode.getAttribute(attrName);
if (fromValue !== attrValue) {
fromNode.setAttribute(attrName, attrValue);
}
}
}
// Remove any extra attributes found on the original DOM element that
// weren't found on the target element.
attrs = fromNode.attributes;
for (i = attrs.length - 1; i >= 0; --i) {
attr = attrs[i];
if (attr.specified !== false) {
attrName = attr.name;
attrNamespaceURI = attr.namespaceURI;
if (attrNamespaceURI) {
attrName = attr.localName || attrName;
if (!hasAttributeNS(toNode, attrNamespaceURI, attrName)) {
fromNode.removeAttributeNS(attrNamespaceURI, attrName);
}
} else {
if (!hasAttributeNS(toNode, null, attrName)) {
fromNode.removeAttribute(attrName);
}
}
}
}
}
function syncBooleanAttrProp(fromEl, toEl, name) {
if (fromEl[name] !== toEl[name]) {
fromEl[name] = toEl[name];
if (fromEl[name]) {
fromEl.setAttribute(name, '');
} else {
fromEl.removeAttribute(name, '');
}
}
}
var specialElHandlers = {
/**
* Needed for IE. Apparently IE doesn't think that "selected" is an
* attribute when reading over the attributes using selectEl.attributes
*/
OPTION: function(fromEl, toEl) {
syncBooleanAttrProp(fromEl, toEl, 'selected');
},
/**
* The "value" attribute is special for the <input> element since it sets
* the initial value. Changing the "value" attribute without changing the
* "value" property will have no effect since it is only used to the set the
* initial value. Similar for the "checked" attribute, and "disabled".
*/
INPUT: function(fromEl, toEl) {
syncBooleanAttrProp(fromEl, toEl, 'checked');
syncBooleanAttrProp(fromEl, toEl, 'disabled');
if (fromEl.value !== toEl.value) {
fromEl.value = toEl.value;
}
if (!hasAttributeNS(toEl, null, 'value')) {
fromEl.removeAttribute('value');
}
},
TEXTAREA: function(fromEl, toEl) {
var newValue = toEl.value;
if (fromEl.value !== newValue) {
fromEl.value = newValue;
}
var firstChild = fromEl.firstChild;
if (firstChild) {
// Needed for IE. Apparently IE sets the placeholder as the
// node value and vise versa. This ignores an empty update.
var oldValue = firstChild.nodeValue;
if (oldValue == newValue || (!newValue && oldValue == fromEl.placeholder)) {
return;
}
firstChild.nodeValue = newValue;
}
},
SELECT: function(fromEl, toEl) {
if (!hasAttributeNS(toEl, null, 'multiple')) {
var selectedIndex = -1;
var i = 0;
var curChild = toEl.firstChild;
while(curChild) {
var nodeName = curChild.nodeName;
if (nodeName && nodeName.toUpperCase() === 'OPTION') {
if (hasAttributeNS(curChild, null, 'selected')) {
selectedIndex = i;
break;
}
i++;
}
curChild = curChild.nextSibling;
}
fromEl.selectedIndex = i;
}
}
};
var ELEMENT_NODE = 1;
var TEXT_NODE = 3;
var COMMENT_NODE = 8;
function noop() {}
function defaultGetNodeKey(node) {
return node.id;
}
function morphdomFactory(morphAttrs) {
return function morphdom(fromNode, toNode, options) {
if (!options) {
options = {};
}
if (typeof toNode === 'string') {
if (fromNode.nodeName === '#document' || fromNode.nodeName === 'HTML') {
var toNodeHtml = toNode;
toNode = doc.createElement('html');
toNode.innerHTML = toNodeHtml;
} else {
toNode = toElement(toNode);
}
}
var getNodeKey = options.getNodeKey || defaultGetNodeKey;
var onBeforeNodeAdded = options.onBeforeNodeAdded || noop;
var onNodeAdded = options.onNodeAdded || noop;
var onBeforeElUpdated = options.onBeforeElUpdated || noop;
var onElUpdated = options.onElUpdated || noop;
var onBeforeNodeDiscarded = options.onBeforeNodeDiscarded || noop;
var onNodeDiscarded = options.onNodeDiscarded || noop;
var onBeforeElChildrenUpdated = options.onBeforeElChildrenUpdated || noop;
var childrenOnly = options.childrenOnly === true;
// This object is used as a lookup to quickly find all keyed elements in the original DOM tree.
var fromNodesLookup = {};
var keyedRemovalList;
function addKeyedRemoval(key) {
if (keyedRemovalList) {
keyedRemovalList.push(key);
} else {
keyedRemovalList = [key];
}
}
function walkDiscardedChildNodes(node, skipKeyedNodes) {
if (node.nodeType === ELEMENT_NODE) {
var curChild = node.firstChild;
while (curChild) {
var key = undefined;
if (skipKeyedNodes && (key = getNodeKey(curChild))) {
// If we are skipping keyed nodes then we add the key
// to a list so that it can be handled at the very end.
addKeyedRemoval(key);
} else {
// Only report the node as discarded if it is not keyed. We do this because
// at the end we loop through all keyed elements that were unmatched
// and then discard them in one final pass.
onNodeDiscarded(curChild);
if (curChild.firstChild) {
walkDiscardedChildNodes(curChild, skipKeyedNodes);
}
}
curChild = curChild.nextSibling;
}
}
}
/**
* Removes a DOM node out of the original DOM
*
* @param {Node} node The node to remove
* @param {Node} parentNode The nodes parent
* @param {Boolean} skipKeyedNodes If true then elements with keys will be skipped and not discarded.
* @return {undefined}
*/
function removeNode(node, parentNode, skipKeyedNodes) {
if (onBeforeNodeDiscarded(node) === false) {
return;
}
if (parentNode) {
parentNode.removeChild(node);
}
onNodeDiscarded(node);
walkDiscardedChildNodes(node, skipKeyedNodes);
}
// // TreeWalker implementation is no faster, but keeping this around in case this changes in the future
// function indexTree(root) {
// var treeWalker = document.createTreeWalker(
// root,
// NodeFilter.SHOW_ELEMENT);
//
// var el;
// while((el = treeWalker.nextNode())) {
// var key = getNodeKey(el);
// if (key) {
// fromNodesLookup[key] = el;
// }
// }
// }
// // NodeIterator implementation is no faster, but keeping this around in case this changes in the future
//
// function indexTree(node) {
// var nodeIterator = document.createNodeIterator(node, NodeFilter.SHOW_ELEMENT);
// var el;
// while((el = nodeIterator.nextNode())) {
// var key = getNodeKey(el);
// if (key) {
// fromNodesLookup[key] = el;
// }
// }
// }
function indexTree(node) {
if (node.nodeType === ELEMENT_NODE) {
var curChild = node.firstChild;
while (curChild) {
var key = getNodeKey(curChild);
if (key) {
fromNodesLookup[key] = curChild;
}
// Walk recursively
indexTree(curChild);
curChild = curChild.nextSibling;
}
}
}
indexTree(fromNode);
function handleNodeAdded(el) {
onNodeAdded(el);
var curChild = el.firstChild;
while (curChild) {
var nextSibling = curChild.nextSibling;
var key = getNodeKey(curChild);
if (key) {
var unmatchedFromEl = fromNodesLookup[key];
if (unmatchedFromEl && compareNodeNames(curChild, unmatchedFromEl)) {
curChild.parentNode.replaceChild(unmatchedFromEl, curChild);
morphEl(unmatchedFromEl, curChild);
}
}
handleNodeAdded(curChild);
curChild = nextSibling;
}
}
function morphEl(fromEl, toEl, childrenOnly) {
var toElKey = getNodeKey(toEl);
var curFromNodeKey;
if (toElKey) {
// If an element with an ID is being morphed then it is will be in the final
// DOM so clear it out of the saved elements collection
delete fromNodesLookup[toElKey];
}
if (toNode.isSameNode && toNode.isSameNode(fromNode)) {
return;
}
if (!childrenOnly) {
if (onBeforeElUpdated(fromEl, toEl) === false) {
return;
}
morphAttrs(fromEl, toEl);
onElUpdated(fromEl);
if (onBeforeElChildrenUpdated(fromEl, toEl) === false) {
return;
}
}
if (fromEl.nodeName !== 'TEXTAREA') {
var curToNodeChild = toEl.firstChild;
var curFromNodeChild = fromEl.firstChild;
var curToNodeKey;
var fromNextSibling;
var toNextSibling;
var matchingFromEl;
outer: while (curToNodeChild) {
toNextSibling = curToNodeChild.nextSibling;
curToNodeKey = getNodeKey(curToNodeChild);
while (curFromNodeChild) {
fromNextSibling = curFromNodeChild.nextSibling;
if (curToNodeChild.isSameNode && curToNodeChild.isSameNode(curFromNodeChild)) {
curToNodeChild = toNextSibling;
curFromNodeChild = fromNextSibling;
continue outer;
}
curFromNodeKey = getNodeKey(curFromNodeChild);
var curFromNodeType = curFromNodeChild.nodeType;
var isCompatible = undefined;
if (curFromNodeType === curToNodeChild.nodeType) {
if (curFromNodeType === ELEMENT_NODE) {
// Both nodes being compared are Element nodes
if (curToNodeKey) {
// The target node has a key so we want to match it up with the correct element
// in the original DOM tree
if (curToNodeKey !== curFromNodeKey) {
// The current element in the original DOM tree does not have a matching key so
// let's check our lookup to see if there is a matching element in the original
// DOM tree
if ((matchingFromEl = fromNodesLookup[curToNodeKey])) {
if (curFromNodeChild.nextSibling === matchingFromEl) {
// Special case for single element removals. To avoid removing the original
// DOM node out of the tree (since that can break CSS transitions, etc.),
// we will instead discard the current node and wait until the next
// iteration to properly match up the keyed target element with its matching
// element in the original tree
isCompatible = false;
} else {
// We found a matching keyed element somewhere in the original DOM tree.
// Let's moving the original DOM node into the current position and morph
// it.
// NOTE: We use insertBefore instead of replaceChild because we want to go through
// the `removeNode()` function for the node that is being discarded so that
// all lifecycle hooks are correctly invoked
fromEl.insertBefore(matchingFromEl, curFromNodeChild);
fromNextSibling = curFromNodeChild.nextSibling;
if (curFromNodeKey) {
// Since the node is keyed it might be matched up later so we defer
// the actual removal to later
addKeyedRemoval(curFromNodeKey);
} else {
// NOTE: we skip nested keyed nodes from being removed since there is
// still a chance they will be matched up later
removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);
}
curFromNodeChild = matchingFromEl;
}
} else {
// The nodes are not compatible since the "to" node has a key and there
// is no matching keyed node in the source tree
isCompatible = false;
}
}
} else if (curFromNodeKey) {
// The original has a key
isCompatible = false;
}
isCompatible = isCompatible !== false && compareNodeNames(curFromNodeChild, curToNodeChild);
if (isCompatible) {
// We found compatible DOM elements so transform
// the current "from" node to match the current
// target DOM node.
morphEl(curFromNodeChild, curToNodeChild);
}
} else if (curFromNodeType === TEXT_NODE || curFromNodeType == COMMENT_NODE) {
// Both nodes being compared are Text or Comment nodes
isCompatible = true;
// Simply update nodeValue on the original node to
// change the text value
curFromNodeChild.nodeValue = curToNodeChild.nodeValue;
}
}
if (isCompatible) {
// Advance both the "to" child and the "from" child since we found a match
curToNodeChild = toNextSibling;
curFromNodeChild = fromNextSibling;
continue outer;
}
// No compatible match so remove the old node from the DOM and continue trying to find a
// match in the original DOM. However, we only do this if the from node is not keyed
// since it is possible that a keyed node might match up with a node somewhere else in the
// target tree and we don't want to discard it just yet since it still might find a
// home in the final DOM tree. After everything is done we will remove any keyed nodes
// that didn't find a home
if (curFromNodeKey) {
// Since the node is keyed it might be matched up later so we defer
// the actual removal to later
addKeyedRemoval(curFromNodeKey);
} else {
// NOTE: we skip nested keyed nodes from being removed since there is
// still a chance they will be matched up later
removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);
}
curFromNodeChild = fromNextSibling;
}
// If we got this far then we did not find a candidate match for
// our "to node" and we exhausted all of the children "from"
// nodes. Therefore, we will just append the current "to" node
// to the end
if (curToNodeKey && (matchingFromEl = fromNodesLookup[curToNodeKey]) && compareNodeNames(matchingFromEl, curToNodeChild)) {
fromEl.appendChild(matchingFromEl);
morphEl(matchingFromEl, curToNodeChild);
} else {
var onBeforeNodeAddedResult = onBeforeNodeAdded(curToNodeChild);
if (onBeforeNodeAddedResult !== false) {
if (onBeforeNodeAddedResult) {
curToNodeChild = onBeforeNodeAddedResult;
}
if (curToNodeChild.actualize) {
curToNodeChild = curToNodeChild.actualize(fromEl.ownerDocument || doc);
}
fromEl.appendChild(curToNodeChild);
handleNodeAdded(curToNodeChild);
}
}
curToNodeChild = toNextSibling;
curFromNodeChild = fromNextSibling;
}
// We have processed all of the "to nodes". If curFromNodeChild is
// non-null then we still have some from nodes left over that need
// to be removed
while (curFromNodeChild) {
fromNextSibling = curFromNodeChild.nextSibling;
if ((curFromNodeKey = getNodeKey(curFromNodeChild))) {
// Since the node is keyed it might be matched up later so we defer
// the actual removal to later
addKeyedRemoval(curFromNodeKey);
} else {
// NOTE: we skip nested keyed nodes from being removed since there is
// still a chance they will be matched up later
removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);
}
curFromNodeChild = fromNextSibling;
}
}
var specialElHandler = specialElHandlers[fromEl.nodeName];
if (specialElHandler) {
specialElHandler(fromEl, toEl);
}
} // END: morphEl(...)
var morphedNode = fromNode;
var morphedNodeType = morphedNode.nodeType;
var toNodeType = toNode.nodeType;
if (!childrenOnly) {
// Handle the case where we are given two DOM nodes that are not
// compatible (e.g. <div> --> <span> or <div> --> TEXT)
if (morphedNodeType === ELEMENT_NODE) {
if (toNodeType === ELEMENT_NODE) {
if (!compareNodeNames(fromNode, toNode)) {
onNodeDiscarded(fromNode);
morphedNode = moveChildren(fromNode, createElementNS(toNode.nodeName, toNode.namespaceURI));
}
} else {
// Going from an element node to a text node
morphedNode = toNode;
}
} else if (morphedNodeType === TEXT_NODE || morphedNodeType === COMMENT_NODE) { // Text or comment node
if (toNodeType === morphedNodeType) {
morphedNode.nodeValue = toNode.nodeValue;
return morphedNode;
} else {
// Text node to something else
morphedNode = toNode;
}
}
}
if (morphedNode === toNode) {
// The "to node" was not compatible with the "from node" so we had to
// toss out the "from node" and use the "to node"
onNodeDiscarded(fromNode);
} else {
morphEl(morphedNode, toNode, childrenOnly);
// We now need to loop over any keyed nodes that might need to be
// removed. We only do the removal if we know that the keyed node
// never found a match. When a keyed node is matched up we remove
// it out of fromNodesLookup and we use fromNodesLookup to determine
// if a keyed node has been matched up or not
if (keyedRemovalList) {
for (var i=0, len=keyedRemovalList.length; i<len; i++) {
var elToRemove = fromNodesLookup[keyedRemovalList[i]];
if (elToRemove) {
removeNode(elToRemove, elToRemove.parentNode, false);
}
}
}
}
if (!childrenOnly && morphedNode !== fromNode && fromNode.parentNode) {
if (morphedNode.actualize) {
morphedNode = morphedNode.actualize(fromNode.ownerDocument || doc);
}
// If we had to swap out the from node with a new node because the old
// node was not compatible with the target node then we need to
// replace the old DOM node in the original DOM tree. This is only
// possible if the original DOM node was part of a DOM tree which
// we know is the case if it has a parent node.
fromNode.parentNode.replaceChild(morphedNode, fromNode);
}
return morphedNode;
};
}
var morphdom = morphdomFactory(morphAttrs);
module.exports = morphdom;
},{}],130:[function(require,module,exports){
module.exports = [
// attribute events (can be set with attributes)
'onclick',
'ondblclick',
'onmousedown',
'onmouseup',
'onmouseover',
'onmousemove',
'onmouseout',
'ondragstart',
'ondrag',
'ondragenter',
'ondragleave',
'ondragover',
'ondrop',
'ondragend',
'onkeydown',
'onkeypress',
'onkeyup',
'onunload',
'onabort',
'onerror',
'onresize',
'onscroll',
'onselect',
'onchange',
'onsubmit',
'onreset',
'onfocus',
'onblur',
'oninput',
// other common events
'oncontextmenu',
'onfocusin',
'onfocusout'
]
},{}],131:[function(require,module,exports){
module.exports = function yoyoifyAppendChild (el, childs) {
for (var i = 0; i < childs.length; i++) {
var node = childs[i]
if (Array.isArray(node)) {
yoyoifyAppendChild(el, node)
continue
}
if (typeof node === 'number' ||
typeof node === 'boolean' ||
node instanceof Date ||
node instanceof RegExp) {
node = node.toString()
}
if (typeof node === 'string') {
if (el.lastChild && el.lastChild.nodeName === '#text') {
el.lastChild.nodeValue += node
continue
}
node = document.createTextNode(node)
}
if (node && node.nodeType) {
el.appendChild(node)
}
}
}
},{}],"uppy":[function(require,module,exports){
'use strict';
var Core = require('./core/index.js');
// Parent
var Plugin = require('./plugins/Plugin');
// Orchestrators
var Dashboard = require('./plugins/Dashboard/index.js');
// Acquirers
var Dummy = require('./plugins/Dummy');
var DragDrop = require('./plugins/DragDrop/index.js');
var FileInput = require('./plugins/FileInput.js');
var GoogleDrive = require('./plugins/GoogleDrive/index.js');
var Dropbox = require('./plugins/Dropbox/index.js');
var Webcam = require('./plugins/Webcam/index.js');
// Progressindicators
var ProgressBar = require('./plugins/ProgressBar.js');
var Informer = require('./plugins/Informer.js');
// Modifiers
var MetaData = require('./plugins/MetaData.js');
// Uploaders
var Tus10 = require('./plugins/Tus10');
var Multipart = require('./plugins/Multipart');
var Transloadit = require('./plugins/Transloadit');
module.exports = {
Core: Core,
Plugin: Plugin,
Dummy: Dummy,
ProgressBar: ProgressBar,
Informer: Informer,
DragDrop: DragDrop,
GoogleDrive: GoogleDrive,
Dropbox: Dropbox,
FileInput: FileInput,
Tus10: Tus10,
Multipart: Multipart,
Transloadit: Transloadit,
Dashboard: Dashboard,
MetaData: MetaData,
Webcam: Webcam
};
},{"./core/index.js":7,"./plugins/Dashboard/index.js":29,"./plugins/DragDrop/index.js":30,"./plugins/Dropbox/index.js":32,"./plugins/Dummy":33,"./plugins/FileInput.js":34,"./plugins/GoogleDrive/index.js":35,"./plugins/Informer.js":36,"./plugins/MetaData.js":37,"./plugins/Multipart":38,"./plugins/Plugin":39,"./plugins/ProgressBar.js":40,"./plugins/Transloadit":43,"./plugins/Tus10":44,"./plugins/Webcam/index.js":53}]},{},[])
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcmVzb2x2ZS9lbXB0eS5qcyIsIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL3Byb2Nlc3MvYnJvd3Nlci5qcyIsImxpYi9jb3JlL0NvcmUuanMiLCJsaWIvY29yZS9UcmFuc2xhdG9yLmpzIiwibGliL2NvcmUvVXBweVNvY2tldC5qcyIsImxpYi9jb3JlL1V0aWxzLmpzIiwibGliL2NvcmUvaW5kZXguanMiLCJsaWIvZ2VuZXJpYy1wcm92aWRlci12aWV3cy9BdXRoVmlldy5qcyIsImxpYi9nZW5lcmljLXByb3ZpZGVyLXZpZXdzL0JyZWFkY3J1bWIuanMiLCJsaWIvZ2VuZXJpYy1wcm92aWRlci12aWV3cy9CcmVhZGNydW1icy5qcyIsImxpYi9nZW5lcmljLXByb3ZpZGVyLXZpZXdzL0Jyb3dzZXIuanMiLCJsaWIvZ2VuZXJpYy1wcm92aWRlci12aWV3cy9FcnJvci5qcyIsImxpYi9nZW5lcmljLXByb3ZpZGVyLXZpZXdzL0xvYWRlci5qcyIsImxpYi9nZW5lcmljLXByb3ZpZGVyLXZpZXdzL1RhYmxlLmpzIiwibGliL2dlbmVyaWMtcHJvdmlkZXItdmlld3MvVGFibGVDb2x1bW4uanMiLCJsaWIvZ2VuZXJpYy1wcm92aWRlci12aWV3cy9UYWJsZVJvdy5qcyIsImxpYi9nZW5lcmljLXByb3ZpZGVyLXZpZXdzL2luZGV4LmpzIiwibGliL3BsdWdpbnMvRGFzaGJvYXJkL0FjdGlvbkJyb3dzZVRhZ2xpbmUuanMiLCJsaWIvcGx1Z2lucy9EYXNoYm9hcmQvRGFzaGJvYXJkLmpzIiwibGliL3BsdWdpbnMvRGFzaGJvYXJkL0ZpbGVDYXJkLmpzIiwibGliL3BsdWdpbnMvRGFzaGJvYXJkL0ZpbGVJdGVtLmpzIiwibGliL3BsdWdpbnMvRGFzaGJvYXJkL0ZpbGVJdGVtUHJvZ3Jlc3MuanMiLCJsaWIvcGx1Z2lucy9EYXNoYm9hcmQvRmlsZUxpc3QuanMiLCJsaWIvcGx1Z2lucy9EYXNoYm9hcmQvU3RhdHVzQmFyLmpzIiwibGliL3BsdWdpbnMvRGFzaGJvYXJkL1RhYnMuanMiLCJsaWIvcGx1Z2lucy9EYXNoYm9hcmQvVXBsb2FkQnRuLmpzIiwibGliL3BsdWdpbnMvRGFzaGJvYXJkL2dldEZpbGVUeXBlSWNvbi5qcyIsImxpYi9wbHVnaW5zL0Rhc2hib2FyZC9pY29ucy5qcyIsImxpYi9wbHVnaW5zL0Rhc2hib2FyZC9pbmRleC5qcyIsImxpYi9wbHVnaW5zL0RyYWdEcm9wL2luZGV4LmpzIiwibGliL3BsdWdpbnMvRHJvcGJveC9pY29ucy5qcyIsImxpYi9wbHVnaW5zL0Ryb3Bib3gvaW5kZXguanMiLCJsaWIvcGx1Z2lucy9EdW1teS5qcyIsImxpYi9wbHVnaW5zL0ZpbGVJbnB1dC5qcyIsImxpYi9wbHVnaW5zL0dvb2dsZURyaXZlL2luZGV4LmpzIiwibGliL3BsdWdpbnMvSW5mb3JtZXIuanMiLCJsaWIvcGx1Z2lucy9NZXRhRGF0YS5qcyIsImxpYi9wbHVnaW5zL011bHRpcGFydC5qcyIsImxpYi9wbHVnaW5zL1BsdWdpbi5qcyIsImxpYi9wbHVnaW5zL1Byb2dyZXNzQmFyLmpzIiwibGliL3BsdWdpbnMvVHJhbnNsb2FkaXQvQ2xpZW50LmpzIiwibGliL3BsdWdpbnMvVHJhbnNsb2FkaXQvU29ja2V0LmpzIiwibGliL3BsdWdpbnMvVHJhbnNsb2FkaXQvaW5kZXguanMiLCJsaWIvcGx1Z2lucy9UdXMxMC5qcyIsImxpYi9wbHVnaW5zL1dlYmNhbS9DYW1lcmFJY29uLmpzIiwibGliL3BsdWdpbnMvV2ViY2FtL0NhbWVyYVNjcmVlbi5qcyIsImxpYi9wbHVnaW5zL1dlYmNhbS9QZXJtaXNzaW9uc1NjcmVlbi5qcyIsImxpYi9wbHVnaW5zL1dlYmNhbS9SZWNvcmRCdXR0b24uanMiLCJsaWIvcGx1Z2lucy9XZWJjYW0vUmVjb3JkU3RhcnRJY29uLmpzIiwibGliL3BsdWdpbnMvV2ViY2FtL1JlY29yZFN0b3BJY29uLmpzIiwibGliL3BsdWdpbnMvV2ViY2FtL1NuYXBzaG90QnV0dG9uLmpzIiwibGliL3BsdWdpbnMvV2ViY2FtL1dlYmNhbUljb24uanMiLCJsaWIvcGx1Z2lucy9XZWJjYW0vaW5kZXguanMiLCJsaWIvdXBweS1iYXNlL3NyYy9wbHVnaW5zL1Byb3ZpZGVyLmpzIiwibGliL3VwcHktYmFzZS9zcmMvcGx1Z2lucy9XZWJjYW0uanMiLCJsaWIvdXBweS1iYXNlL3NyYy91dGlscy9kYXRhVVJJdG9GaWxlLmpzIiwibm9kZV9tb2R1bGVzL2RyYWctZHJvcC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9kcmFnLWRyb3Avbm9kZV9tb2R1bGVzL2ZsYXR0ZW4vaW5kZXguanMiLCJub2RlX21vZHVsZXMvZHJhZy1kcm9wL25vZGVfbW9kdWxlcy9ydW4tcGFyYWxsZWwvaW5kZXguanMiLCJub2RlX21vZHVsZXMvZXM2LXByb21pc2UvZGlzdC9lczYtcHJvbWlzZS5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gudGhyb3R0bGUvaW5kZXguanMiLCJub2RlX21vZHVsZXMvbmFtZXNwYWNlLWVtaXR0ZXIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvb24tbG9hZC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9vbi1sb2FkL25vZGVfbW9kdWxlcy9nbG9iYWwvZG9jdW1lbnQuanMiLCJub2RlX21vZHVsZXMvb24tbG9hZC9ub2RlX21vZHVsZXMvZ2xvYmFsL3dpbmRvdy5qcyIsIm5vZGVfbW9kdWxlcy9wcmV0dGllci1ieXRlcy9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9zb2NrZXQuaW8tY2xpZW50L2xpYi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9zb2NrZXQuaW8tY2xpZW50L2xpYi9tYW5hZ2VyLmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbGliL29uLmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbGliL3NvY2tldC5qcyIsIm5vZGVfbW9kdWxlcy9zb2NrZXQuaW8tY2xpZW50L2xpYi91cmwuanMiLCJub2RlX21vZHVsZXMvc29ja2V0LmlvLWNsaWVudC9ub2RlX21vZHVsZXMvYmFja28yL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2Jhc2U2NC1hcnJheWJ1ZmZlci9saWIvYmFzZTY0LWFycmF5YnVmZmVyLmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2NvbXBvbmVudC1iaW5kL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2NvbXBvbmVudC1lbWl0dGVyL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2RlYnVnL25vZGVfbW9kdWxlcy9tcy9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9zb2NrZXQuaW8tY2xpZW50L25vZGVfbW9kdWxlcy9kZWJ1Zy9zcmMvYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy9zb2NrZXQuaW8tY2xpZW50L25vZGVfbW9kdWxlcy9kZWJ1Zy9zcmMvZGVidWcuanMiLCJub2RlX21vZHVsZXMvc29ja2V0LmlvLWNsaWVudC9ub2RlX21vZHVsZXMvZW5naW5lLmlvLWNsaWVudC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9zb2NrZXQuaW8tY2xpZW50L25vZGVfbW9kdWxlcy9lbmdpbmUuaW8tY2xpZW50L2xpYi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9zb2NrZXQuaW8tY2xpZW50L25vZGVfbW9kdWxlcy9lbmdpbmUuaW8tY2xpZW50L2xpYi9zb2NrZXQuanMiLCJub2RlX21vZHVsZXMvc29ja2V0LmlvLWNsaWVudC9ub2RlX21vZHVsZXMvZW5naW5lLmlvLWNsaWVudC9saWIvdHJhbnNwb3J0LmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2VuZ2luZS5pby1jbGllbnQvbGliL3RyYW5zcG9ydHMvaW5kZXguanMiLCJub2RlX21vZHVsZXMvc29ja2V0LmlvLWNsaWVudC9ub2RlX21vZHVsZXMvZW5naW5lLmlvLWNsaWVudC9saWIvdHJhbnNwb3J0cy9wb2xsaW5nLWpzb25wLmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2VuZ2luZS5pby1jbGllbnQvbGliL3RyYW5zcG9ydHMvcG9sbGluZy14aHIuanMiLCJub2RlX21vZHVsZXMvc29ja2V0LmlvLWNsaWVudC9ub2RlX21vZHVsZXMvZW5naW5lLmlvLWNsaWVudC9saWIvdHJhbnNwb3J0cy9wb2xsaW5nLmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2VuZ2luZS5pby1jbGllbnQvbGliL3RyYW5zcG9ydHMvd2Vic29ja2V0LmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2VuZ2luZS5pby1jbGllbnQvbGliL3htbGh0dHByZXF1ZXN0LmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2VuZ2luZS5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2NvbXBvbmVudC1pbmhlcml0L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2VuZ2luZS5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2VuZ2luZS5pby1wYXJzZXIvbGliL2Jyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvc29ja2V0LmlvLWNsaWVudC9ub2RlX21vZHVsZXMvZW5naW5lLmlvLWNsaWVudC9ub2RlX21vZHVsZXMvZW5naW5lLmlvLXBhcnNlci9saWIva2V5cy5qcyIsIm5vZGVfbW9kdWxlcy9zb2NrZXQuaW8tY2xpZW50L25vZGVfbW9kdWxlcy9lbmdpbmUuaW8tY2xpZW50L25vZGVfbW9kdWxlcy9lbmdpbmUuaW8tcGFyc2VyL2xpYi91dGY4LmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2VuZ2luZS5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2VuZ2luZS5pby1wYXJzZXIvbm9kZV9tb2R1bGVzL2FmdGVyL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2VuZ2luZS5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2VuZ2luZS5pby1wYXJzZXIvbm9kZV9tb2R1bGVzL2FycmF5YnVmZmVyLnNsaWNlL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2VuZ2luZS5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2VuZ2luZS5pby1wYXJzZXIvbm9kZV9tb2R1bGVzL2Jsb2IvaW5kZXguanMiLCJub2RlX21vZHVsZXMvc29ja2V0LmlvLWNsaWVudC9ub2RlX21vZHVsZXMvZW5naW5lLmlvLWNsaWVudC9ub2RlX21vZHVsZXMvZW5naW5lLmlvLXBhcnNlci9ub2RlX21vZHVsZXMvaGFzLWJpbmFyeTIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvc29ja2V0LmlvLWNsaWVudC9ub2RlX21vZHVsZXMvZW5naW5lLmlvLWNsaWVudC9ub2RlX21vZHVsZXMvZW5naW5lLmlvLXBhcnNlci9ub2RlX21vZHVsZXMvaGFzLWJpbmFyeTIvbm9kZV9tb2R1bGVzL2lzYXJyYXkvaW5kZXguanMiLCJub2RlX21vZHVsZXMvc29ja2V0LmlvLWNsaWVudC9ub2RlX21vZHVsZXMvZW5naW5lLmlvLWNsaWVudC9ub2RlX21vZHVsZXMvcGFyc2Vqc29uL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL2VuZ2luZS5pby1jbGllbnQvbm9kZV9tb2R1bGVzL3BhcnNlcXMvaW5kZXguanMiLCJub2RlX21vZHVsZXMvc29ja2V0LmlvLWNsaWVudC9ub2RlX21vZHVsZXMvZW5naW5lLmlvLWNsaWVudC9ub2RlX21vZHVsZXMveWVhc3QvaW5kZXguanMiLCJub2RlX21vZHVsZXMvc29ja2V0LmlvLWNsaWVudC9ub2RlX21vZHVsZXMvaGFzLWNvcnMvaW5kZXguanMiLCJub2RlX21vZHVsZXMvc29ja2V0LmlvLWNsaWVudC9ub2RlX21vZHVsZXMvaW5kZXhvZi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9zb2NrZXQuaW8tY2xpZW50L25vZGVfbW9kdWxlcy9wYXJzZXVyaS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9zb2NrZXQuaW8tY2xpZW50L25vZGVfbW9kdWxlcy9zb2NrZXQuaW8tcGFyc2VyL2JpbmFyeS5qcyIsIm5vZGVfbW9kdWxlcy9zb2NrZXQuaW8tY2xpZW50L25vZGVfbW9kdWxlcy9zb2NrZXQuaW8tcGFyc2VyL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL3NvY2tldC5pby1wYXJzZXIvaXMtYnVmZmVyLmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL3NvY2tldC5pby1wYXJzZXIvbm9kZV9tb2R1bGVzL2hhcy1iaW5hcnkyL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3NvY2tldC5pby1jbGllbnQvbm9kZV9tb2R1bGVzL3RvLWFycmF5L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3R1cy1qcy1jbGllbnQvbGliLmVzNS9icm93c2VyL2Jhc2U2NC5qcyIsIm5vZGVfbW9kdWxlcy90dXMtanMtY2xpZW50L2xpYi5lczUvYnJvd3Nlci9yZXF1ZXN0LmpzIiwibm9kZV9tb2R1bGVzL3R1cy1qcy1jbGllbnQvbGliLmVzNS9icm93c2VyL3NvdXJjZS5qcyIsIm5vZGVfbW9kdWxlcy90dXMtanMtY2xpZW50L2xpYi5lczUvYnJvd3Nlci9zdG9yYWdlLmpzIiwibm9kZV9tb2R1bGVzL3R1cy1qcy1jbGllbnQvbGliLmVzNS9lcnJvci5qcyIsIm5vZGVfbW9kdWxlcy90dXMtanMtY2xpZW50L2xpYi5lczUvZmluZ2VycHJpbnQuanMiLCJub2RlX21vZHVsZXMvdHVzLWpzLWNsaWVudC9saWIuZXM1L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3R1cy1qcy1jbGllbnQvbGliLmVzNS91cGxvYWQuanMiLCJub2RlX21vZHVsZXMvdHVzLWpzLWNsaWVudC9ub2RlX21vZHVsZXMvZXh0ZW5kL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3R1cy1qcy1jbGllbnQvbm9kZV9tb2R1bGVzL3Jlc29sdmUtdXJsL3Jlc29sdmUtdXJsLmpzIiwibm9kZV9tb2R1bGVzL3VybC1wYXJzZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy91cmwtcGFyc2Uvbm9kZV9tb2R1bGVzL3F1ZXJ5c3RyaW5naWZ5L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3VybC1wYXJzZS9ub2RlX21vZHVsZXMvcmVxdWlyZXMtcG9ydC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy93aGF0d2ctZmV0Y2gvZmV0Y2guanMiLCJub2RlX21vZHVsZXMveW8teW8vaW5kZXguanMiLCJub2RlX21vZHVsZXMveW8teW8vbm9kZV9tb2R1bGVzL2JlbC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy95by15by9ub2RlX21vZHVsZXMvYmVsL25vZGVfbW9kdWxlcy9nbG9iYWwvZG9jdW1lbnQuanMiLCJub2RlX21vZHVsZXMveW8teW8vbm9kZV9tb2R1bGVzL2JlbC9ub2RlX21vZHVsZXMvaHlwZXJ4L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3lvLXlvL25vZGVfbW9kdWxlcy9iZWwvbm9kZV9tb2R1bGVzL2h5cGVyeC9ub2RlX21vZHVsZXMvaHlwZXJzY3JpcHQtYXR0cmlidXRlLXRvLXByb3BlcnR5L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3lvLXlvL25vZGVfbW9kdWxlcy9tb3JwaGRvbS9kaXN0L21vcnBoZG9tLmpzIiwibm9kZV9tb2R1bGVzL3lvLXlvL3VwZGF0ZS1ldmVudHMuanMiLCJub2RlX21vZHVsZXMveW8teW9pZnkvbGliL2FwcGVuZENoaWxkLmpzIiwidXBweSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUNwTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDL21CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25lQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdZQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdE1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25HQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5UUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvWkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDblhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQzlDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDLzdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDdmJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9HQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDdkZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3akJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUMvWkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUMzRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25LQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ3JKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUN6TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxTUE7QUFDQTtBQUNBOztBQ0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ1ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDeHVCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUM3SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQ3JEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUN2T0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDN1pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDclBBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDOVJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUNyQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ05BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDOWxCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUMvUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDaEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzlEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUMvQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUN2Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUM3SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDaFpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDYkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7QUM5REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoaUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUMvQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDdlpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3Y0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUN6SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0UkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwcUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiIiwiLy8gc2hpbSBmb3IgdXNpbmcgcHJvY2VzcyBpbiBicm93c2VyXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbi8vIGNhY2hlZCBmcm9tIHdoYXRldmVyIGdsb2JhbCBpcyBwcmVzZW50IHNvIHRoYXQgdGVzdCBydW5uZXJzIHRoYXQgc3R1YiBpdFxuLy8gZG9uJ3QgYnJlYWsgdGhpbmdzLiAgQnV0IHdlIG5lZWQgdG8gd3JhcCBpdCBpbiBhIHRyeSBjYXRjaCBpbiBjYXNlIGl0IGlzXG4vLyB3cmFwcGVkIGluIHN0cmljdCBtb2RlIGNvZGUgd2hpY2ggZG9lc24ndCBkZWZpbmUgYW55IGdsb2JhbHMuICBJdCdzIGluc2lkZSBhXG4vLyBmdW5jdGlvbiBiZWNhdXNlIHRyeS9jYXRjaGVzIGRlb3B0aW1pemUgaW4gY2VydGFpbiBlbmdpbmVzLlxuXG52YXIgY2FjaGVkU2V0VGltZW91dDtcbnZhciBjYWNoZWRDbGVhclRpbWVvdXQ7XG5cbmZ1bmN0aW9uIGRlZmF1bHRTZXRUaW1vdXQoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzZXRUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJyk7XG59XG5mdW5jdGlvbiBkZWZhdWx0Q2xlYXJUaW1lb3V0ICgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NsZWFyVGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZCcpO1xufVxuKGZ1bmN0aW9uICgpIHtcbiAgICB0cnkge1xuICAgICAgICBpZiAodHlwZW9mIHNldFRpbWVvdXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBzZXRUaW1lb3V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IGRlZmF1bHRTZXRUaW1vdXQ7XG4gICAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBkZWZhdWx0U2V0VGltb3V0O1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICBpZiAodHlwZW9mIGNsZWFyVGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gY2xlYXJUaW1lb3V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gZGVmYXVsdENsZWFyVGltZW91dDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gZGVmYXVsdENsZWFyVGltZW91dDtcbiAgICB9XG59ICgpKVxuZnVuY3Rpb24gcnVuVGltZW91dChmdW4pIHtcbiAgICBpZiAoY2FjaGVkU2V0VGltZW91dCA9PT0gc2V0VGltZW91dCkge1xuICAgICAgICAvL25vcm1hbCBlbnZpcm9tZW50cyBpbiBzYW5lIHNpdHVhdGlvbnNcbiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9XG4gICAgLy8gaWYgc2V0VGltZW91dCB3YXNuJ3QgYXZhaWxhYmxlIGJ1dCB3YXMgbGF0dGVyIGRlZmluZWRcbiAgICBpZiAoKGNhY2hlZFNldFRpbWVvdXQgPT09IGRlZmF1bHRTZXRUaW1vdXQgfHwgIWNhY2hlZFNldFRpbWVvdXQpICYmIHNldFRpbWVvdXQpIHtcbiAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gICAgICAgIHJldHVybiBzZXRUaW1lb3V0KGZ1biwgMCk7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIC8vIHdoZW4gd2hlbiBzb21lYm9keSBoYXMgc2NyZXdlZCB3aXRoIHNldFRpbWVvdXQgYnV0IG5vIEkuRS4gbWFkZG5lc3NcbiAgICAgICAgcmV0dXJuIGNhY2hlZFNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9IGNhdGNoKGUpe1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gV2hlbiB3ZSBhcmUgaW4gSS5FLiBidXQgdGhlIHNjcmlwdCBoYXMgYmVlbiBldmFsZWQgc28gSS5FLiBkb2Vzbid0IHRydXN0IHRoZSBnbG9iYWwgb2JqZWN0IHdoZW4gY2FsbGVkIG5vcm1hbGx5XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dC5jYWxsKG51bGwsIGZ1biwgMCk7XG4gICAgICAgIH0gY2F0Y2goZSl7XG4gICAgICAgICAgICAvLyBzYW1lIGFzIGFib3ZlIGJ1dCB3aGVuIGl0J3MgYSB2ZXJzaW9uIG9mIEkuRS4gdGhhdCBtdXN0IGhhdmUgdGhlIGdsb2JhbCBvYmplY3QgZm9yICd0aGlzJywgaG9wZnVsbHkgb3VyIGNvbnRleHQgY29ycmVjdCBvdGhlcndpc2UgaXQgd2lsbCB0aHJvdyBhIGdsb2JhbCBlcnJvclxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZFNldFRpbWVvdXQuY2FsbCh0aGlzLCBmdW4sIDApO1xuICAgICAgICB9XG4gICAgfVxuXG5cbn1cbmZ1bmN0aW9uIHJ1bkNsZWFyVGltZW91dChtYXJrZXIpIHtcbiAgICBpZiAoY2FjaGVkQ2xlYXJUaW1lb3V0ID09PSBjbGVhclRpbWVvdXQpIHtcbiAgICAgICAgLy9ub3JtYWwgZW52aXJvbWVudHMgaW4gc2FuZSBzaXR1YXRpb25zXG4gICAgICAgIHJldHVybiBjbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9XG4gICAgLy8gaWYgY2xlYXJUaW1lb3V0IHdhc24ndCBhdmFpbGFibGUgYnV0IHdhcyBsYXR0ZXIgZGVmaW5lZFxuICAgIGlmICgoY2FjaGVkQ2xlYXJUaW1lb3V0ID09PSBkZWZhdWx0Q2xlYXJUaW1lb3V0IHx8ICFjYWNoZWRDbGVhclRpbWVvdXQpICYmIGNsZWFyVGltZW91dCkge1xuICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBjbGVhclRpbWVvdXQ7XG4gICAgICAgIHJldHVybiBjbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gd2hlbiB3aGVuIHNvbWVib2R5IGhhcyBzY3Jld2VkIHdpdGggc2V0VGltZW91dCBidXQgbm8gSS5FLiBtYWRkbmVzc1xuICAgICAgICByZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0KG1hcmtlcik7XG4gICAgfSBjYXRjaCAoZSl7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBpbiBJLkUuIGJ1dCB0aGUgc2NyaXB0IGhhcyBiZWVuIGV2YWxlZCBzbyBJLkUuIGRvZXNuJ3QgIHRydXN0IHRoZSBnbG9iYWwgb2JqZWN0IHdoZW4gY2FsbGVkIG5vcm1hbGx5XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0LmNhbGwobnVsbCwgbWFya2VyKTtcbiAgICAgICAgfSBjYXRjaCAoZSl7XG4gICAgICAgICAgICAvLyBzYW1lIGFzIGFib3ZlIGJ1dCB3aGVuIGl0J3MgYSB2ZXJzaW9uIG9mIEkuRS4gdGhhdCBtdXN0IGhhdmUgdGhlIGdsb2JhbCBvYmplY3QgZm9yICd0aGlzJywgaG9wZnVsbHkgb3VyIGNvbnRleHQgY29ycmVjdCBvdGhlcndpc2UgaXQgd2lsbCB0aHJvdyBhIGdsb2JhbCBlcnJvci5cbiAgICAgICAgICAgIC8vIFNvbWUgdmVyc2lvbnMgb2YgSS5FLiBoYXZlIGRpZmZlcmVudCBydWxlcyBmb3IgY2xlYXJUaW1lb3V0IHZzIHNldFRpbWVvdXRcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbCh0aGlzLCBtYXJrZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG5cblxufVxudmFyIHF1ZXVlID0gW107XG52YXIgZHJhaW5pbmcgPSBmYWxzZTtcbnZhciBjdXJyZW50UXVldWU7XG52YXIgcXVldWVJbmRleCA9IC0xO1xuXG5mdW5jdGlvbiBjbGVhblVwTmV4dFRpY2soKSB7XG4gICAgaWYgKCFkcmFpbmluZyB8fCAhY3VycmVudFF1ZXVlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBpZiAoY3VycmVudFF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBxdWV1ZSA9IGN1cnJlbnRRdWV1ZS5jb25jYXQocXVldWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICB9XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBkcmFpblF1ZXVlKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmFpblF1ZXVlKCkge1xuICAgIGlmIChkcmFpbmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciB0aW1lb3V0ID0gcnVuVGltZW91dChjbGVhblVwTmV4dFRpY2spO1xuICAgIGRyYWluaW5nID0gdHJ1ZTtcblxuICAgIHZhciBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgd2hpbGUobGVuKSB7XG4gICAgICAgIGN1cnJlbnRRdWV1ZSA9IHF1ZXVlO1xuICAgICAgICBxdWV1ZSA9IFtdO1xuICAgICAgICB3aGlsZSAoKytxdWV1ZUluZGV4IDwgbGVuKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudFF1ZXVlKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudFF1ZXVlW3F1ZXVlSW5kZXhdLnJ1bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICAgICAgbGVuID0gcXVldWUubGVuZ3RoO1xuICAgIH1cbiAgICBjdXJyZW50UXVldWUgPSBudWxsO1xuICAgIGRyYWluaW5nID0gZmFsc2U7XG4gICAgcnVuQ2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xufVxuXG5wcm9jZXNzLm5leHRUaWNrID0gZnVuY3Rpb24gKGZ1bikge1xuICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGggLSAxKTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgICB9XG4gICAgfVxuICAgIHF1ZXVlLnB1c2gobmV3IEl0ZW0oZnVuLCBhcmdzKSk7XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCA9PT0gMSAmJiAhZHJhaW5pbmcpIHtcbiAgICAgICAgcnVuVGltZW91dChkcmFpblF1ZXVlKTtcbiAgICB9XG59O1xuXG4vLyB2OCBsaWtlcyBwcmVkaWN0aWJsZSBvYmplY3RzXG5mdW5jdGlvbiBJdGVtKGZ1biwgYXJyYXkpIHtcbiAgICB0aGlzLmZ1biA9IGZ1bjtcbiAgICB0aGlzLmFycmF5ID0gYXJyYXk7XG59XG5JdGVtLnByb3RvdHlwZS5ydW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5mdW4uYXBwbHkobnVsbCwgdGhpcy5hcnJheSk7XG59O1xucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5wcm9jZXNzLnZlcnNpb24gPSAnJzsgLy8gZW1wdHkgc3RyaW5nIHRvIGF2b2lkIHJlZ2V4cCBpc3N1ZXNcbnByb2Nlc3MudmVyc2lvbnMgPSB7fTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnByb2Nlc3Mub24gPSBub29wO1xucHJvY2Vzcy5hZGRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLm9uY2UgPSBub29wO1xucHJvY2Vzcy5vZmYgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUFsbExpc3RlbmVycyA9IG5vb3A7XG5wcm9jZXNzLmVtaXQgPSBub29wO1xuXG5wcm9jZXNzLmJpbmRpbmcgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5cbnByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gJy8nIH07XG5wcm9jZXNzLmNoZGlyID0gZnVuY3Rpb24gKGRpcikge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xucHJvY2Vzcy51bWFzayA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gMDsgfTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIF9leHRlbmRzID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiAodGFyZ2V0KSB7IGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7IHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07IGZvciAodmFyIGtleSBpbiBzb3VyY2UpIHsgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHsgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTsgfSB9IH0gcmV0dXJuIHRhcmdldDsgfTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxudmFyIFV0aWxzID0gcmVxdWlyZSgnLi4vY29yZS9VdGlscycpO1xudmFyIFRyYW5zbGF0b3IgPSByZXF1aXJlKCcuLi9jb3JlL1RyYW5zbGF0b3InKTtcbnZhciBVcHB5U29ja2V0ID0gcmVxdWlyZSgnLi9VcHB5U29ja2V0Jyk7XG52YXIgZWUgPSByZXF1aXJlKCduYW1lc3BhY2UtZW1pdHRlcicpO1xudmFyIHRocm90dGxlID0gcmVxdWlyZSgnbG9kYXNoLnRocm90dGxlJyk7XG4vLyBjb25zdCBlbl9VUyA9IHJlcXVpcmUoJy4uL2xvY2FsZXMvZW5fVVMnKVxuLy8gY29uc3QgZGVlcEZyZWV6ZSA9IHJlcXVpcmUoJ2RlZXAtZnJlZXplLXN0cmljdCcpXG5cbi8qKlxuICogTWFpbiBVcHB5IGNvcmVcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0cyBnZW5lcmFsIG9wdGlvbnMsIGxpa2UgbG9jYWxlcywgdG8gc2hvdyBtb2RhbCBvciBub3QgdG8gc2hvd1xuICovXG5cbnZhciBVcHB5ID0gZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBVcHB5KG9wdHMpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgVXBweSk7XG5cbiAgICAvLyBzZXQgZGVmYXVsdCBvcHRpb25zXG4gICAgdmFyIGRlZmF1bHRPcHRpb25zID0ge1xuICAgICAgLy8gbG9hZCBFbmdsaXNoIGFzIHRoZSBkZWZhdWx0IGxvY2FsZVxuICAgICAgLy8gbG9jYWxlOiBlbl9VUyxcbiAgICAgIGF1dG9Qcm9jZWVkOiB0cnVlLFxuICAgICAgZGVidWc6IGZhbHNlXG4gICAgfTtcblxuICAgIC8vIE1lcmdlIGRlZmF1bHQgb3B0aW9ucyB3aXRoIHRoZSBvbmVzIHNldCBieSB1c2VyXG4gICAgdGhpcy5vcHRzID0gX2V4dGVuZHMoe30sIGRlZmF1bHRPcHRpb25zLCBvcHRzKTtcblxuICAgIC8vIC8vIERpY3RhdGVzIGluIHdoYXQgb3JkZXIgZGlmZmVyZW50IHBsdWdpbiB0eXBlcyBhcmUgcmFuOlxuICAgIC8vIHRoaXMudHlwZXMgPSBbICdwcmVzZXR0ZXInLCAnb3JjaGVzdHJhdG9yJywgJ3Byb2dyZXNzaW5kaWNhdG9yJyxcbiAgICAvLyAgICAgICAgICAgICAgICAgJ2FjcXVpcmVyJywgJ21vZGlmaWVyJywgJ3VwbG9hZGVyJywgJ3ByZXNlbnRlcicsICdkZWJ1Z2dlciddXG5cbiAgICAvLyBDb250YWluZXIgZm9yIGRpZmZlcmVudCB0eXBlcyBvZiBwbHVnaW5zXG4gICAgdGhpcy5wbHVnaW5zID0ge307XG5cbiAgICB0aGlzLnRyYW5zbGF0b3IgPSBuZXcgVHJhbnNsYXRvcih7IGxvY2FsZTogdGhpcy5vcHRzLmxvY2FsZSB9KTtcbiAgICB0aGlzLmkxOG4gPSB0aGlzLnRyYW5zbGF0b3IudHJhbnNsYXRlLmJpbmQodGhpcy50cmFuc2xhdG9yKTtcbiAgICB0aGlzLmdldFN0YXRlID0gdGhpcy5nZXRTdGF0ZS5iaW5kKHRoaXMpO1xuICAgIHRoaXMudXBkYXRlTWV0YSA9IHRoaXMudXBkYXRlTWV0YS5iaW5kKHRoaXMpO1xuICAgIHRoaXMuaW5pdFNvY2tldCA9IHRoaXMuaW5pdFNvY2tldC5iaW5kKHRoaXMpO1xuICAgIHRoaXMubG9nID0gdGhpcy5sb2cuYmluZCh0aGlzKTtcbiAgICB0aGlzLmFkZEZpbGUgPSB0aGlzLmFkZEZpbGUuYmluZCh0aGlzKTtcbiAgICB0aGlzLmNhbGN1bGF0ZVByb2dyZXNzID0gdGhpcy5jYWxjdWxhdGVQcm9ncmVzcy5iaW5kKHRoaXMpO1xuXG4gICAgdGhpcy5idXMgPSB0aGlzLmVtaXR0ZXIgPSBlZSgpO1xuICAgIHRoaXMub24gPSB0aGlzLmJ1cy5vbi5iaW5kKHRoaXMuYnVzKTtcbiAgICB0aGlzLmVtaXQgPSB0aGlzLmJ1cy5lbWl0LmJpbmQodGhpcy5idXMpO1xuXG4gICAgdGhpcy5wcmVQcm9jZXNzb3JzID0gW107XG4gICAgdGhpcy51cGxvYWRlcnMgPSBbXTtcbiAgICB0aGlzLnBvc3RQcm9jZXNzb3JzID0gW107XG5cbiAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgZmlsZXM6IHt9LFxuICAgICAgY2FwYWJpbGl0aWVzOiB7XG4gICAgICAgIHJlc3VtYWJsZVVwbG9hZHM6IGZhbHNlXG4gICAgICB9LFxuICAgICAgdG90YWxQcm9ncmVzczogMFxuICAgIH07XG5cbiAgICAvLyBmb3IgZGVidWdnaW5nIGFuZCB0ZXN0aW5nXG4gICAgdGhpcy51cGRhdGVOdW0gPSAwO1xuICAgIGlmICh0aGlzLm9wdHMuZGVidWcpIHtcbiAgICAgIGdsb2JhbC5VcHB5U3RhdGUgPSB0aGlzLnN0YXRlO1xuICAgICAgZ2xvYmFsLnVwcHlMb2cgPSAnJztcbiAgICAgIGdsb2JhbC5VcHB5QWRkRmlsZSA9IHRoaXMuYWRkRmlsZS5iaW5kKHRoaXMpO1xuICAgICAgZ2xvYmFsLl9VcHB5ID0gdGhpcztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSXRlcmF0ZSBvbiBhbGwgcGx1Z2lucyBhbmQgcnVuIGB1cGRhdGVgIG9uIHRoZW0uIENhbGxlZCBlYWNoIHRpbWUgc3RhdGUgY2hhbmdlc1xuICAgKlxuICAgKi9cblxuXG4gIFVwcHkucHJvdG90eXBlLnVwZGF0ZUFsbCA9IGZ1bmN0aW9uIHVwZGF0ZUFsbChzdGF0ZSkge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICBPYmplY3Qua2V5cyh0aGlzLnBsdWdpbnMpLmZvckVhY2goZnVuY3Rpb24gKHBsdWdpblR5cGUpIHtcbiAgICAgIF90aGlzLnBsdWdpbnNbcGx1Z2luVHlwZV0uZm9yRWFjaChmdW5jdGlvbiAocGx1Z2luKSB7XG4gICAgICAgIHBsdWdpbi51cGRhdGUoc3RhdGUpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFVwZGF0ZXMgc3RhdGVcbiAgICpcbiAgICogQHBhcmFtIHtuZXdTdGF0ZX0gb2JqZWN0XG4gICAqL1xuXG5cbiAgVXBweS5wcm90b3R5cGUuc2V0U3RhdGUgPSBmdW5jdGlvbiBzZXRTdGF0ZShzdGF0ZVVwZGF0ZSkge1xuICAgIHZhciBuZXdTdGF0ZSA9IF9leHRlbmRzKHt9LCB0aGlzLnN0YXRlLCBzdGF0ZVVwZGF0ZSk7XG4gICAgdGhpcy5lbWl0KCdjb3JlOnN0YXRlLXVwZGF0ZScsIHRoaXMuc3RhdGUsIG5ld1N0YXRlLCBzdGF0ZVVwZGF0ZSk7XG5cbiAgICB0aGlzLnN0YXRlID0gbmV3U3RhdGU7XG4gICAgdGhpcy51cGRhdGVBbGwodGhpcy5zdGF0ZSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFJldHVybnMgY3VycmVudCBzdGF0ZVxuICAgKlxuICAgKi9cblxuXG4gIFVwcHkucHJvdG90eXBlLmdldFN0YXRlID0gZnVuY3Rpb24gZ2V0U3RhdGUoKSB7XG4gICAgLy8gdXNlIGRlZXBGcmVlemUgZm9yIGRlYnVnZ2luZ1xuICAgIC8vIHJldHVybiBkZWVwRnJlZXplKHRoaXMuc3RhdGUpXG4gICAgcmV0dXJuIHRoaXMuc3RhdGU7XG4gIH07XG5cbiAgVXBweS5wcm90b3R5cGUuYWRkUHJlUHJvY2Vzc29yID0gZnVuY3Rpb24gYWRkUHJlUHJvY2Vzc29yKGZuKSB7XG4gICAgdGhpcy5wcmVQcm9jZXNzb3JzLnB1c2goZm4pO1xuICB9O1xuXG4gIFVwcHkucHJvdG90eXBlLnJlbW92ZVByZVByb2Nlc3NvciA9IGZ1bmN0aW9uIHJlbW92ZVByZVByb2Nlc3Nvcihmbikge1xuICAgIHZhciBpID0gdGhpcy5wcmVQcm9jZXNzb3JzLmluZGV4T2YoZm4pO1xuICAgIGlmIChpICE9PSAtMSkge1xuICAgICAgdGhpcy5wcmVQcm9jZXNzb3JzLnNwbGljZShpLCAxKTtcbiAgICB9XG4gIH07XG5cbiAgVXBweS5wcm90b3R5cGUuYWRkUG9zdFByb2Nlc3NvciA9IGZ1bmN0aW9uIGFkZFBvc3RQcm9jZXNzb3IoZm4pIHtcbiAgICB0aGlzLnBvc3RQcm9jZXNzb3JzLnB1c2goZm4pO1xuICB9O1xuXG4gIFVwcHkucHJvdG90eXBlLnJlbW92ZVBvc3RQcm9jZXNzb3IgPSBmdW5jdGlvbiByZW1vdmVQb3N0UHJvY2Vzc29yKGZuKSB7XG4gICAgdmFyIGkgPSB0aGlzLnBvc3RQcm9jZXNzb3JzLmluZGV4T2YoZm4pO1xuICAgIGlmIChpICE9PSAtMSkge1xuICAgICAgdGhpcy5wb3N0UHJvY2Vzc29ycy5zcGxpY2UoaSwgMSk7XG4gICAgfVxuICB9O1xuXG4gIFVwcHkucHJvdG90eXBlLmFkZFVwbG9hZGVyID0gZnVuY3Rpb24gYWRkVXBsb2FkZXIoZm4pIHtcbiAgICB0aGlzLnVwbG9hZGVycy5wdXNoKGZuKTtcbiAgfTtcblxuICBVcHB5LnByb3RvdHlwZS5yZW1vdmVVcGxvYWRlciA9IGZ1bmN0aW9uIHJlbW92ZVVwbG9hZGVyKGZuKSB7XG4gICAgdmFyIGkgPSB0aGlzLnVwbG9hZGVycy5pbmRleE9mKGZuKTtcbiAgICBpZiAoaSAhPT0gLTEpIHtcbiAgICAgIHRoaXMudXBsb2FkZXJzLnNwbGljZShpLCAxKTtcbiAgICB9XG4gIH07XG5cbiAgVXBweS5wcm90b3R5cGUudXBkYXRlTWV0YSA9IGZ1bmN0aW9uIHVwZGF0ZU1ldGEoZGF0YSwgZmlsZUlEKSB7XG4gICAgdmFyIHVwZGF0ZWRGaWxlcyA9IF9leHRlbmRzKHt9LCB0aGlzLmdldFN0YXRlKCkuZmlsZXMpO1xuICAgIHZhciBuZXdNZXRhID0gX2V4dGVuZHMoe30sIHVwZGF0ZWRGaWxlc1tmaWxlSURdLm1ldGEsIGRhdGEpO1xuICAgIHVwZGF0ZWRGaWxlc1tmaWxlSURdID0gX2V4dGVuZHMoe30sIHVwZGF0ZWRGaWxlc1tmaWxlSURdLCB7XG4gICAgICBtZXRhOiBuZXdNZXRhXG4gICAgfSk7XG4gICAgdGhpcy5zZXRTdGF0ZSh7IGZpbGVzOiB1cGRhdGVkRmlsZXMgfSk7XG4gIH07XG5cbiAgVXBweS5wcm90b3R5cGUuYWRkRmlsZSA9IGZ1bmN0aW9uIGFkZEZpbGUoZmlsZSkge1xuICAgIHZhciB1cGRhdGVkRmlsZXMgPSBfZXh0ZW5kcyh7fSwgdGhpcy5zdGF0ZS5maWxlcyk7XG5cbiAgICB2YXIgZmlsZU5hbWUgPSBmaWxlLm5hbWUgfHwgJ25vbmFtZSc7XG4gICAgdmFyIGZpbGVUeXBlID0gVXRpbHMuZ2V0RmlsZVR5cGUoZmlsZSk7XG4gICAgdmFyIGZpbGVUeXBlR2VuZXJhbCA9IGZpbGVUeXBlWzBdO1xuICAgIHZhciBmaWxlVHlwZVNwZWNpZmljID0gZmlsZVR5cGVbMV07XG4gICAgdmFyIGZpbGVFeHRlbnNpb24gPSBVdGlscy5nZXRGaWxlTmFtZUFuZEV4dGVuc2lvbihmaWxlTmFtZSlbMV07XG4gICAgdmFyIGlzUmVtb3RlID0gZmlsZS5pc1JlbW90ZSB8fCBmYWxzZTtcblxuICAgIHZhciBmaWxlSUQgPSBVdGlscy5nZW5lcmF0ZUZpbGVJRChmaWxlTmFtZSk7XG5cbiAgICB2YXIgbmV3RmlsZSA9IHtcbiAgICAgIHNvdXJjZTogZmlsZS5zb3VyY2UgfHwgJycsXG4gICAgICBpZDogZmlsZUlELFxuICAgICAgbmFtZTogZmlsZU5hbWUsXG4gICAgICBleHRlbnNpb246IGZpbGVFeHRlbnNpb24gfHwgJycsXG4gICAgICBtZXRhOiB7XG4gICAgICAgIG5hbWU6IGZpbGVOYW1lXG4gICAgICB9LFxuICAgICAgdHlwZToge1xuICAgICAgICBnZW5lcmFsOiBmaWxlVHlwZUdlbmVyYWwsXG4gICAgICAgIHNwZWNpZmljOiBmaWxlVHlwZVNwZWNpZmljXG4gICAgICB9LFxuICAgICAgZGF0YTogZmlsZS5kYXRhLFxuICAgICAgcHJvZ3Jlc3M6IHtcbiAgICAgICAgcGVyY2VudGFnZTogMCxcbiAgICAgICAgdXBsb2FkQ29tcGxldGU6IGZhbHNlLFxuICAgICAgICB1cGxvYWRTdGFydGVkOiBmYWxzZVxuICAgICAgfSxcbiAgICAgIHNpemU6IGZpbGUuZGF0YS5zaXplIHx8ICdOL0EnLFxuICAgICAgaXNSZW1vdGU6IGlzUmVtb3RlLFxuICAgICAgcmVtb3RlOiBmaWxlLnJlbW90ZSB8fCAnJyxcbiAgICAgIHByZXZpZXc6IGZpbGUucHJldmlld1xuICAgIH07XG5cbiAgICB1cGRhdGVkRmlsZXNbZmlsZUlEXSA9IG5ld0ZpbGU7XG4gICAgdGhpcy5zZXRTdGF0ZSh7IGZpbGVzOiB1cGRhdGVkRmlsZXMgfSk7XG5cbiAgICB0aGlzLmJ1cy5lbWl0KCdmaWxlLWFkZGVkJywgZmlsZUlEKTtcbiAgICB0aGlzLmxvZygnQWRkZWQgZmlsZTogJyArIGZpbGVOYW1lICsgJywgJyArIGZpbGVJRCArICcsIG1pbWUgdHlwZTogJyArIGZpbGVUeXBlKTtcblxuICAgIGlmIChmaWxlVHlwZUdlbmVyYWwgPT09ICdpbWFnZScgJiYgIWlzUmVtb3RlKSB7XG4gICAgICB0aGlzLmFkZFRodW1ibmFpbChuZXdGaWxlLmlkKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5vcHRzLmF1dG9Qcm9jZWVkKSB7XG4gICAgICB0aGlzLnVwbG9hZCgpLmNhdGNoKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihlcnIuc3RhY2sgfHwgZXJyLm1lc3NhZ2UpO1xuICAgICAgfSk7XG4gICAgICAvLyB0aGlzLmJ1cy5lbWl0KCdjb3JlOnVwbG9hZCcpXG4gICAgfVxuICB9O1xuXG4gIFVwcHkucHJvdG90eXBlLnJlbW92ZUZpbGUgPSBmdW5jdGlvbiByZW1vdmVGaWxlKGZpbGVJRCkge1xuICAgIHZhciB1cGRhdGVkRmlsZXMgPSBfZXh0ZW5kcyh7fSwgdGhpcy5nZXRTdGF0ZSgpLmZpbGVzKTtcbiAgICBkZWxldGUgdXBkYXRlZEZpbGVzW2ZpbGVJRF07XG4gICAgdGhpcy5zZXRTdGF0ZSh7IGZpbGVzOiB1cGRhdGVkRmlsZXMgfSk7XG4gICAgdGhpcy5jYWxjdWxhdGVUb3RhbFByb2dyZXNzKCk7XG4gICAgdGhpcy5sb2coJ1JlbW92ZWQgZmlsZTogJyArIGZpbGVJRCk7XG4gIH07XG5cbiAgVXBweS5wcm90b3R5cGUuYWRkVGh1bWJuYWlsID0gZnVuY3Rpb24gYWRkVGh1bWJuYWlsKGZpbGVJRCkge1xuICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgdmFyIGZpbGUgPSB0aGlzLmdldFN0YXRlKCkuZmlsZXNbZmlsZUlEXTtcblxuICAgIC8vIGNvbnN0IHRodW1ibmFpbCA9IFVSTC5jcmVhdGVPYmplY3RVUkwoZmlsZS5kYXRhKVxuICAgIC8vIGNvbnN0IHVwZGF0ZWRGaWxlcyA9IE9iamVjdC5hc3NpZ24oe30sIHRoaXMuZ2V0U3RhdGUoKS5maWxlcylcbiAgICAvLyBjb25zdCB1cGRhdGVkRmlsZSA9IE9iamVjdC5hc3NpZ24oe30sIHVwZGF0ZWRGaWxlc1tmaWxlSURdLCB7XG4gICAgLy8gICBwcmV2aWV3OiB0aHVtYm5haWxcbiAgICAvLyB9KVxuICAgIC8vIHVwZGF0ZWRGaWxlc1tmaWxlSURdID0gdXBkYXRlZEZpbGVcbiAgICAvLyB0aGlzLnNldFN0YXRlKHtmaWxlczogdXBkYXRlZEZpbGVzfSlcblxuICAgIFV0aWxzLnJlYWRGaWxlKGZpbGUuZGF0YSkudGhlbihmdW5jdGlvbiAoaW1nRGF0YVVSSSkge1xuICAgICAgcmV0dXJuIFV0aWxzLmNyZWF0ZUltYWdlVGh1bWJuYWlsKGltZ0RhdGFVUkksIDIwMCk7XG4gICAgfSkudGhlbihmdW5jdGlvbiAodGh1bWJuYWlsKSB7XG4gICAgICB2YXIgdXBkYXRlZEZpbGVzID0gX2V4dGVuZHMoe30sIF90aGlzMi5nZXRTdGF0ZSgpLmZpbGVzKTtcbiAgICAgIHZhciB1cGRhdGVkRmlsZSA9IF9leHRlbmRzKHt9LCB1cGRhdGVkRmlsZXNbZmlsZUlEXSwge1xuICAgICAgICBwcmV2aWV3OiB0aHVtYm5haWxcbiAgICAgIH0pO1xuICAgICAgdXBkYXRlZEZpbGVzW2ZpbGVJRF0gPSB1cGRhdGVkRmlsZTtcbiAgICAgIF90aGlzMi5zZXRTdGF0ZSh7IGZpbGVzOiB1cGRhdGVkRmlsZXMgfSk7XG4gICAgfSkuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgICAgcmV0dXJuIF90aGlzMi5sb2coZXJyKTtcbiAgICB9KTtcbiAgfTtcblxuICBVcHB5LnByb3RvdHlwZS5jYWxjdWxhdGVQcm9ncmVzcyA9IGZ1bmN0aW9uIGNhbGN1bGF0ZVByb2dyZXNzKGRhdGEpIHtcbiAgICB2YXIgZmlsZUlEID0gZGF0YS5pZDtcbiAgICB2YXIgdXBkYXRlZEZpbGVzID0gX2V4dGVuZHMoe30sIHRoaXMuZ2V0U3RhdGUoKS5maWxlcyk7XG5cbiAgICAvLyBza2lwIHByb2dyZXNzIGV2ZW50IGZvciBhIGZpbGUgdGhhdOKAmXMgYmVlbiByZW1vdmVkXG4gICAgaWYgKCF1cGRhdGVkRmlsZXNbZmlsZUlEXSkge1xuICAgICAgdGhpcy5sb2coJ1RyeWluZyB0byBzZXQgcHJvZ3Jlc3MgZm9yIGEgZmlsZSB0aGF04oCZcyBub3Qgd2l0aCB1cyBhbnltb3JlOiAnLCBmaWxlSUQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciB1cGRhdGVkRmlsZSA9IF9leHRlbmRzKHt9LCB1cGRhdGVkRmlsZXNbZmlsZUlEXSwgX2V4dGVuZHMoe30sIHtcbiAgICAgIHByb2dyZXNzOiBfZXh0ZW5kcyh7fSwgdXBkYXRlZEZpbGVzW2ZpbGVJRF0ucHJvZ3Jlc3MsIHtcbiAgICAgICAgYnl0ZXNVcGxvYWRlZDogZGF0YS5ieXRlc1VwbG9hZGVkLFxuICAgICAgICBieXRlc1RvdGFsOiBkYXRhLmJ5dGVzVG90YWwsXG4gICAgICAgIHBlcmNlbnRhZ2U6IE1hdGguZmxvb3IoKGRhdGEuYnl0ZXNVcGxvYWRlZCAvIGRhdGEuYnl0ZXNUb3RhbCAqIDEwMCkudG9GaXhlZCgyKSlcbiAgICAgIH0pXG4gICAgfSkpO1xuICAgIHVwZGF0ZWRGaWxlc1tkYXRhLmlkXSA9IHVwZGF0ZWRGaWxlO1xuXG4gICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICBmaWxlczogdXBkYXRlZEZpbGVzXG4gICAgfSk7XG5cbiAgICB0aGlzLmNhbGN1bGF0ZVRvdGFsUHJvZ3Jlc3MoKTtcbiAgfTtcblxuICBVcHB5LnByb3RvdHlwZS5jYWxjdWxhdGVUb3RhbFByb2dyZXNzID0gZnVuY3Rpb24gY2FsY3VsYXRlVG90YWxQcm9ncmVzcygpIHtcbiAgICAvLyBjYWxjdWxhdGUgdG90YWwgcHJvZ3Jlc3MsIHVzaW5nIHRoZSBudW1iZXIgb2YgZmlsZXMgY3VycmVudGx5IHVwbG9hZGluZyxcbiAgICAvLyBtdWx0aXBsaWVkIGJ5IDEwMCBhbmQgdGhlIHN1bW0gb2YgaW5kaXZpZHVhbCBwcm9ncmVzcyBvZiBlYWNoIGZpbGVcbiAgICB2YXIgZmlsZXMgPSBfZXh0ZW5kcyh7fSwgdGhpcy5nZXRTdGF0ZSgpLmZpbGVzKTtcblxuICAgIHZhciBpblByb2dyZXNzID0gT2JqZWN0LmtleXMoZmlsZXMpLmZpbHRlcihmdW5jdGlvbiAoZmlsZSkge1xuICAgICAgcmV0dXJuIGZpbGVzW2ZpbGVdLnByb2dyZXNzLnVwbG9hZFN0YXJ0ZWQ7XG4gICAgfSk7XG4gICAgdmFyIHByb2dyZXNzTWF4ID0gaW5Qcm9ncmVzcy5sZW5ndGggKiAxMDA7XG4gICAgdmFyIHByb2dyZXNzQWxsID0gMDtcbiAgICBpblByb2dyZXNzLmZvckVhY2goZnVuY3Rpb24gKGZpbGUpIHtcbiAgICAgIHByb2dyZXNzQWxsID0gcHJvZ3Jlc3NBbGwgKyBmaWxlc1tmaWxlXS5wcm9ncmVzcy5wZXJjZW50YWdlO1xuICAgIH0pO1xuXG4gICAgdmFyIHRvdGFsUHJvZ3Jlc3MgPSBNYXRoLmZsb29yKChwcm9ncmVzc0FsbCAqIDEwMCAvIHByb2dyZXNzTWF4KS50b0ZpeGVkKDIpKTtcblxuICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgdG90YWxQcm9ncmVzczogdG90YWxQcm9ncmVzc1xuICAgIH0pO1xuXG4gICAgLy8gaWYgKHRvdGFsUHJvZ3Jlc3MgPT09IDEwMCkge1xuICAgIC8vICAgY29uc3QgY29tcGxldGVGaWxlcyA9IE9iamVjdC5rZXlzKHVwZGF0ZWRGaWxlcykuZmlsdGVyKChmaWxlKSA9PiB7XG4gICAgLy8gICAgIC8vIHRoaXMgc2hvdWxkIGJlIGB1cGxvYWRDb21wbGV0ZWBcbiAgICAvLyAgICAgcmV0dXJuIHVwZGF0ZWRGaWxlc1tmaWxlXS5wcm9ncmVzcy5wZXJjZW50YWdlID09PSAxMDBcbiAgICAvLyAgIH0pXG4gICAgLy8gICB0aGlzLmVtaXQoJ2NvcmU6c3VjY2VzcycsIGNvbXBsZXRlRmlsZXMubGVuZ3RoKVxuICAgIC8vIH1cbiAgfTtcblxuICAvKipcbiAgICogUmVnaXN0ZXJzIGxpc3RlbmVycyBmb3IgYWxsIGdsb2JhbCBhY3Rpb25zLCBsaWtlOlxuICAgKiBgZmlsZS1hZGRgLCBgZmlsZS1yZW1vdmVgLCBgdXBsb2FkLXByb2dyZXNzYCwgYHJlc2V0YFxuICAgKlxuICAgKi9cblxuXG4gIFVwcHkucHJvdG90eXBlLmFjdGlvbnMgPSBmdW5jdGlvbiBhY3Rpb25zKCkge1xuICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgLy8gdGhpcy5idXMub24oJyonLCAocGF5bG9hZCkgPT4ge1xuICAgIC8vICAgY29uc29sZS5sb2coJ2VtaXR0ZWQ6ICcsIHRoaXMuZXZlbnQpXG4gICAgLy8gICBjb25zb2xlLmxvZygnd2l0aCBwYXlsb2FkOiAnLCBwYXlsb2FkKVxuICAgIC8vIH0pXG5cbiAgICAvLyBzdHJlc3MtdGVzdCByZS1yZW5kZXJpbmdcbiAgICAvLyBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgLy8gICB0aGlzLnNldFN0YXRlKHtibGE6ICdibGEnfSlcbiAgICAvLyB9LCAyMClcblxuICAgIHRoaXMub24oJ2NvcmU6ZmlsZS1hZGQnLCBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgX3RoaXMzLmFkZEZpbGUoZGF0YSk7XG4gICAgfSk7XG5cbiAgICAvLyBgcmVtb3ZlLWZpbGVgIHJlbW92ZXMgYSBmaWxlIGZyb20gYHN0YXRlLmZpbGVzYCwgZm9yIGV4YW1wbGUgd2hlblxuICAgIC8vIGEgdXNlciBkZWNpZGVzIG5vdCB0byB1cGxvYWQgcGFydGljdWxhciBmaWxlIGFuZCBjbGlja3MgYSBidXR0b24gdG8gcmVtb3ZlIGl0XG4gICAgdGhpcy5vbignY29yZTpmaWxlLXJlbW92ZScsIGZ1bmN0aW9uIChmaWxlSUQpIHtcbiAgICAgIF90aGlzMy5yZW1vdmVGaWxlKGZpbGVJRCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLm9uKCdjb3JlOmNhbmNlbC1hbGwnLCBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgZmlsZXMgPSBfdGhpczMuZ2V0U3RhdGUoKS5maWxlcztcbiAgICAgIE9iamVjdC5rZXlzKGZpbGVzKS5mb3JFYWNoKGZ1bmN0aW9uIChmaWxlKSB7XG4gICAgICAgIF90aGlzMy5yZW1vdmVGaWxlKGZpbGVzW2ZpbGVdLmlkKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGhpcy5vbignY29yZTp1cGxvYWQtc3RhcnRlZCcsIGZ1bmN0aW9uIChmaWxlSUQsIHVwbG9hZCkge1xuICAgICAgdmFyIHVwZGF0ZWRGaWxlcyA9IF9leHRlbmRzKHt9LCBfdGhpczMuZ2V0U3RhdGUoKS5maWxlcyk7XG4gICAgICB2YXIgdXBkYXRlZEZpbGUgPSBfZXh0ZW5kcyh7fSwgdXBkYXRlZEZpbGVzW2ZpbGVJRF0sIF9leHRlbmRzKHt9LCB7XG4gICAgICAgIHByb2dyZXNzOiBfZXh0ZW5kcyh7fSwgdXBkYXRlZEZpbGVzW2ZpbGVJRF0ucHJvZ3Jlc3MsIHtcbiAgICAgICAgICB1cGxvYWRTdGFydGVkOiBEYXRlLm5vdygpXG4gICAgICAgIH0pXG4gICAgICB9KSk7XG4gICAgICB1cGRhdGVkRmlsZXNbZmlsZUlEXSA9IHVwZGF0ZWRGaWxlO1xuXG4gICAgICBfdGhpczMuc2V0U3RhdGUoeyBmaWxlczogdXBkYXRlZEZpbGVzIH0pO1xuICAgIH0pO1xuXG4gICAgLy8gdXBsb2FkIHByb2dyZXNzIGV2ZW50cyBjYW4gb2NjdXIgZnJlcXVlbnRseSwgZXNwZWNpYWxseSB3aGVuIHlvdSBoYXZlIGEgZ29vZFxuICAgIC8vIGNvbm5lY3Rpb24gdG8gdGhlIHJlbW90ZSBzZXJ2ZXIuIFRoZXJlZm9yZSwgd2UgYXJlIHRocm90dGVsaW5nIHRoZW0gdG9cbiAgICAvLyBwcmV2ZW50IGFjY2Vzc2l2ZSBmdW5jdGlvbiBjYWxscy5cbiAgICAvLyBzZWUgYWxzbzogaHR0cHM6Ly9naXRodWIuY29tL3R1cy90dXMtanMtY2xpZW50L2NvbW1pdC85OTQwZjI3YjIzNjFmZDdlMTBiYTU4YjA5YjYwZDgyNDIyMTgzYmJiXG4gICAgdmFyIHRocm90dGxlZENhbGN1bGF0ZVByb2dyZXNzID0gdGhyb3R0bGUodGhpcy5jYWxjdWxhdGVQcm9ncmVzcywgMTAwLCB7IGxlYWRpbmc6IHRydWUsIHRyYWlsaW5nOiBmYWxzZSB9KTtcblxuICAgIHRoaXMub24oJ2NvcmU6dXBsb2FkLXByb2dyZXNzJywgZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgIC8vIHRoaXMuY2FsY3VsYXRlUHJvZ3Jlc3MoZGF0YSlcbiAgICAgIHRocm90dGxlZENhbGN1bGF0ZVByb2dyZXNzKGRhdGEpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5vbignY29yZTp1cGxvYWQtc3VjY2VzcycsIGZ1bmN0aW9uIChmaWxlSUQsIHVwbG9hZFJlc3AsIHVwbG9hZFVSTCkge1xuICAgICAgdmFyIHVwZGF0ZWRGaWxlcyA9IF9leHRlbmRzKHt9LCBfdGhpczMuZ2V0U3RhdGUoKS5maWxlcyk7XG4gICAgICB2YXIgdXBkYXRlZEZpbGUgPSBfZXh0ZW5kcyh7fSwgdXBkYXRlZEZpbGVzW2ZpbGVJRF0sIHtcbiAgICAgICAgcHJvZ3Jlc3M6IF9leHRlbmRzKHt9LCB1cGRhdGVkRmlsZXNbZmlsZUlEXS5wcm9ncmVzcywge1xuICAgICAgICAgIHVwbG9hZENvbXBsZXRlOiB0cnVlLFxuICAgICAgICAgIC8vIGdvb2Qgb3IgYmFkIGlkZWE/IHNldHRpbmcgdGhlIHBlcmNlbnRhZ2UgdG8gMTAwIGlmIHVwbG9hZCBpcyBzdWNjZXNzZnVsLFxuICAgICAgICAgIC8vIHNvIHRoYXQgaWYgd2UgbG9zdCBzb21lIHByb2dyZXNzIGV2ZW50cyBvbiB0aGUgd2F5LCBpdHMgc3RpbGwgbWFya2VkIOKAnGNvbXBldGXigJ0/XG4gICAgICAgICAgcGVyY2VudGFnZTogMTAwXG4gICAgICAgIH0pLFxuICAgICAgICB1cGxvYWRVUkw6IHVwbG9hZFVSTFxuICAgICAgfSk7XG4gICAgICB1cGRhdGVkRmlsZXNbZmlsZUlEXSA9IHVwZGF0ZWRGaWxlO1xuXG4gICAgICBfdGhpczMuc2V0U3RhdGUoe1xuICAgICAgICBmaWxlczogdXBkYXRlZEZpbGVzXG4gICAgICB9KTtcblxuICAgICAgX3RoaXMzLmNhbGN1bGF0ZVRvdGFsUHJvZ3Jlc3MoKTtcblxuICAgICAgaWYgKF90aGlzMy5nZXRTdGF0ZSgpLnRvdGFsUHJvZ3Jlc3MgPT09IDEwMCkge1xuICAgICAgICB2YXIgY29tcGxldGVGaWxlcyA9IE9iamVjdC5rZXlzKHVwZGF0ZWRGaWxlcykuZmlsdGVyKGZ1bmN0aW9uIChmaWxlKSB7XG4gICAgICAgICAgcmV0dXJuIHVwZGF0ZWRGaWxlc1tmaWxlXS5wcm9ncmVzcy51cGxvYWRDb21wbGV0ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIF90aGlzMy5lbWl0KCdjb3JlOnVwbG9hZC1jb21wbGV0ZScsIGNvbXBsZXRlRmlsZXMubGVuZ3RoKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHRoaXMub24oJ2NvcmU6dXBkYXRlLW1ldGEnLCBmdW5jdGlvbiAoZGF0YSwgZmlsZUlEKSB7XG4gICAgICBfdGhpczMudXBkYXRlTWV0YShkYXRhLCBmaWxlSUQpO1xuICAgIH0pO1xuXG4gICAgLy8gc2hvdyBpbmZvcm1lciBpZiBvZmZsaW5lXG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignb25saW5lJywgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gX3RoaXMzLmlzT25saW5lKHRydWUpO1xuICAgICAgfSk7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignb2ZmbGluZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIF90aGlzMy5pc09ubGluZShmYWxzZSk7XG4gICAgICB9KTtcbiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gX3RoaXMzLmlzT25saW5lKCk7XG4gICAgICB9LCAzMDAwKTtcbiAgICB9XG4gIH07XG5cbiAgVXBweS5wcm90b3R5cGUuaXNPbmxpbmUgPSBmdW5jdGlvbiBpc09ubGluZShzdGF0dXMpIHtcbiAgICB2YXIgb25saW5lID0gc3RhdHVzIHx8IHdpbmRvdy5uYXZpZ2F0b3Iub25MaW5lO1xuICAgIGlmICghb25saW5lKSB7XG4gICAgICB0aGlzLmVtaXQoJ2lzLW9mZmxpbmUnKTtcbiAgICAgIHRoaXMuZW1pdCgnaW5mb3JtZXInLCAnTm8gaW50ZXJuZXQgY29ubmVjdGlvbicsICdlcnJvcicsIDApO1xuICAgICAgdGhpcy53YXNPZmZsaW5lID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5lbWl0KCdpcy1vbmxpbmUnKTtcbiAgICAgIGlmICh0aGlzLndhc09mZmxpbmUpIHtcbiAgICAgICAgdGhpcy5lbWl0KCdiYWNrLW9ubGluZScpO1xuICAgICAgICB0aGlzLmVtaXQoJ2luZm9ybWVyJywgJ0Nvbm5lY3RlZCEnLCAnc3VjY2VzcycsIDMwMDApO1xuICAgICAgICB0aGlzLndhc09mZmxpbmUgPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhIHBsdWdpbiB3aXRoIENvcmVcbiAgICpcbiAgICogQHBhcmFtIHtDbGFzc30gUGx1Z2luIG9iamVjdFxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBvYmplY3QgdGhhdCB3aWxsIGJlIHBhc3NlZCB0byBQbHVnaW4gbGF0ZXJcbiAgICogQHJldHVybiB7T2JqZWN0fSBzZWxmIGZvciBjaGFpbmluZ1xuICAgKi9cblxuXG4gIFVwcHkucHJvdG90eXBlLnVzZSA9IGZ1bmN0aW9uIHVzZShQbHVnaW4sIG9wdHMpIHtcbiAgICAvLyBJbnN0YW50aWF0ZVxuICAgIHZhciBwbHVnaW4gPSBuZXcgUGx1Z2luKHRoaXMsIG9wdHMpO1xuICAgIHZhciBwbHVnaW5OYW1lID0gcGx1Z2luLmlkO1xuICAgIHRoaXMucGx1Z2luc1twbHVnaW4udHlwZV0gPSB0aGlzLnBsdWdpbnNbcGx1Z2luLnR5cGVdIHx8IFtdO1xuXG4gICAgaWYgKCFwbHVnaW5OYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdXIgcGx1Z2luIG11c3QgaGF2ZSBhIG5hbWUnKTtcbiAgICB9XG5cbiAgICBpZiAoIXBsdWdpbi50eXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdXIgcGx1Z2luIG11c3QgaGF2ZSBhIHR5cGUnKTtcbiAgICB9XG5cbiAgICB2YXIgZXhpc3RzUGx1Z2luQWxyZWFkeSA9IHRoaXMuZ2V0UGx1Z2luKHBsdWdpbk5hbWUpO1xuICAgIGlmIChleGlzdHNQbHVnaW5BbHJlYWR5KSB7XG4gICAgICB2YXIgbXNnID0gJ0FscmVhZHkgZm91bmQgYSBwbHVnaW4gbmFtZWQgXFwnJyArIGV4aXN0c1BsdWdpbkFscmVhZHkubmFtZSArICdcXCcuXFxuICAgICAgICBUcmllZCB0byB1c2U6IFxcJycgKyBwbHVnaW5OYW1lICsgJ1xcJy5cXG4gICAgICAgIFVwcHkgaXMgY3VycmVudGx5IGxpbWl0ZWQgdG8gcnVubmluZyBvbmUgb2YgZXZlcnkgcGx1Z2luLlxcbiAgICAgICAgU2hhcmUgeW91ciB1c2UgY2FzZSB3aXRoIHVzIG92ZXIgYXRcXG4gICAgICAgIGh0dHBzOi8vZ2l0aHViLmNvbS90cmFuc2xvYWRpdC91cHB5L2lzc3Vlcy9cXG4gICAgICAgIGlmIHlvdSB3YW50IHVzIHRvIHJlY29uc2lkZXIuJztcbiAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xuICAgIH1cblxuICAgIHRoaXMucGx1Z2luc1twbHVnaW4udHlwZV0ucHVzaChwbHVnaW4pO1xuICAgIHBsdWdpbi5pbnN0YWxsKCk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfTtcblxuICAvKipcbiAgICogRmluZCBvbmUgUGx1Z2luIGJ5IG5hbWVcbiAgICpcbiAgICogQHBhcmFtIHN0cmluZyBuYW1lIGRlc2NyaXB0aW9uXG4gICAqL1xuXG5cbiAgVXBweS5wcm90b3R5cGUuZ2V0UGx1Z2luID0gZnVuY3Rpb24gZ2V0UGx1Z2luKG5hbWUpIHtcbiAgICB2YXIgZm91bmRQbHVnaW4gPSBmYWxzZTtcbiAgICB0aGlzLml0ZXJhdGVQbHVnaW5zKGZ1bmN0aW9uIChwbHVnaW4pIHtcbiAgICAgIHZhciBwbHVnaW5OYW1lID0gcGx1Z2luLmlkO1xuICAgICAgaWYgKHBsdWdpbk5hbWUgPT09IG5hbWUpIHtcbiAgICAgICAgZm91bmRQbHVnaW4gPSBwbHVnaW47XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gZm91bmRQbHVnaW47XG4gIH07XG5cbiAgLyoqXG4gICAqIEl0ZXJhdGUgdGhyb3VnaCBhbGwgYHVzZWBkIHBsdWdpbnNcbiAgICpcbiAgICogQHBhcmFtIGZ1bmN0aW9uIG1ldGhvZCBkZXNjcmlwdGlvblxuICAgKi9cblxuXG4gIFVwcHkucHJvdG90eXBlLml0ZXJhdGVQbHVnaW5zID0gZnVuY3Rpb24gaXRlcmF0ZVBsdWdpbnMobWV0aG9kKSB7XG4gICAgdmFyIF90aGlzNCA9IHRoaXM7XG5cbiAgICBPYmplY3Qua2V5cyh0aGlzLnBsdWdpbnMpLmZvckVhY2goZnVuY3Rpb24gKHBsdWdpblR5cGUpIHtcbiAgICAgIF90aGlzNC5wbHVnaW5zW3BsdWdpblR5cGVdLmZvckVhY2gobWV0aG9kKTtcbiAgICB9KTtcbiAgfTtcblxuICAvKipcbiAgICogVW5pbnN0YWxsIGFuZCByZW1vdmUgYSBwbHVnaW4uXG4gICAqXG4gICAqIEBwYXJhbSB7UGx1Z2lufSBpbnN0YW5jZSBUaGUgcGx1Z2luIGluc3RhbmNlIHRvIHJlbW92ZS5cbiAgICovXG5cblxuICBVcHB5LnByb3RvdHlwZS5yZW1vdmVQbHVnaW4gPSBmdW5jdGlvbiByZW1vdmVQbHVnaW4oaW5zdGFuY2UpIHtcbiAgICB2YXIgbGlzdCA9IHRoaXMucGx1Z2luc1tpbnN0YW5jZS50eXBlXTtcblxuICAgIGlmIChpbnN0YW5jZS51bmluc3RhbGwpIHtcbiAgICAgIGluc3RhbmNlLnVuaW5zdGFsbCgpO1xuICAgIH1cblxuICAgIHZhciBpbmRleCA9IGxpc3QuaW5kZXhPZihpbnN0YW5jZSk7XG4gICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgbGlzdC5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogVW5pbnN0YWxsIGFsbCBwbHVnaW5zIGFuZCBjbG9zZSBkb3duIHRoaXMgVXBweSBpbnN0YW5jZS5cbiAgICovXG5cblxuICBVcHB5LnByb3RvdHlwZS5jbG9zZSA9IGZ1bmN0aW9uIGNsb3NlKCkge1xuICAgIHRoaXMuaXRlcmF0ZVBsdWdpbnMoZnVuY3Rpb24gKHBsdWdpbikge1xuICAgICAgcGx1Z2luLnVuaW5zdGFsbCgpO1xuICAgIH0pO1xuXG4gICAgaWYgKHRoaXMuc29ja2V0KSB7XG4gICAgICB0aGlzLnNvY2tldC5jbG9zZSgpO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogTG9ncyBzdHVmZiB0byBjb25zb2xlLCBvbmx5IGlmIGBkZWJ1Z2AgaXMgc2V0IHRvIHRydWUuIFNpbGVudCBpbiBwcm9kdWN0aW9uLlxuICAgKlxuICAgKiBAcmV0dXJuIHtTdHJpbmd8T2JqZWN0fSB0byBsb2dcbiAgICovXG5cblxuICBVcHB5LnByb3RvdHlwZS5sb2cgPSBmdW5jdGlvbiBsb2cobXNnLCB0eXBlKSB7XG4gICAgaWYgKCF0aGlzLm9wdHMuZGVidWcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKG1zZyA9PT0gJycgKyBtc2cpIHtcbiAgICAgIGNvbnNvbGUubG9nKCdMT0c6ICcgKyBtc2cpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zb2xlLmRpcihtc2cpO1xuICAgIH1cblxuICAgIGlmICh0eXBlID09PSAnZXJyb3InKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdMT0c6ICcgKyBtc2cpO1xuICAgIH1cblxuICAgIGdsb2JhbC51cHB5TG9nID0gZ2xvYmFsLnVwcHlMb2cgKyAnXFxuJyArICdERUJVRyBMT0c6ICcgKyBtc2c7XG4gIH07XG5cbiAgVXBweS5wcm90b3R5cGUuaW5pdFNvY2tldCA9IGZ1bmN0aW9uIGluaXRTb2NrZXQob3B0cykge1xuICAgIGlmICghdGhpcy5zb2NrZXQpIHtcbiAgICAgIHRoaXMuc29ja2V0ID0gbmV3IFVwcHlTb2NrZXQob3B0cyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc29ja2V0O1xuICB9O1xuXG4gIC8vIGluc3RhbGxBbGwgKCkge1xuICAvLyAgIE9iamVjdC5rZXlzKHRoaXMucGx1Z2lucykuZm9yRWFjaCgocGx1Z2luVHlwZSkgPT4ge1xuICAvLyAgICAgdGhpcy5wbHVnaW5zW3BsdWdpblR5cGVdLmZvckVhY2goKHBsdWdpbikgPT4ge1xuICAvLyAgICAgICBwbHVnaW4uaW5zdGFsbCh0aGlzKVxuICAvLyAgICAgfSlcbiAgLy8gICB9KVxuICAvLyB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemVzIGFjdGlvbnMsIGluc3RhbGxzIGFsbCBwbHVnaW5zIChieSBpdGVyYXRpbmcgb24gdGhlbSBhbmQgY2FsbGluZyBgaW5zdGFsbGApLCBzZXRzIG9wdGlvbnNcbiAgICpcbiAgICovXG5cblxuICBVcHB5LnByb3RvdHlwZS5ydW4gPSBmdW5jdGlvbiBydW4oKSB7XG4gICAgdGhpcy5sb2coJ0NvcmUgaXMgcnVuLCBpbml0aWFsaXppbmcgYWN0aW9ucy4uLicpO1xuXG4gICAgdGhpcy5hY3Rpb25zKCk7XG5cbiAgICAvLyBGb3JzZSBzZXQgYGF1dG9Qcm9jZWVkYCBvcHRpb24gdG8gZmFsc2UgaWYgdGhlcmUgYXJlIG11bHRpcGxlIHNlbGVjdG9yIFBsdWdpbnMgYWN0aXZlXG4gICAgLy8gaWYgKHRoaXMucGx1Z2lucy5hY3F1aXJlciAmJiB0aGlzLnBsdWdpbnMuYWNxdWlyZXIubGVuZ3RoID4gMSkge1xuICAgIC8vICAgdGhpcy5vcHRzLmF1dG9Qcm9jZWVkID0gZmFsc2VcbiAgICAvLyB9XG5cbiAgICAvLyBJbnN0YWxsIGFsbCBwbHVnaW5zXG4gICAgLy8gdGhpcy5pbnN0YWxsQWxsKClcblxuICAgIHJldHVybjtcbiAgfTtcblxuICBVcHB5LnByb3RvdHlwZS51cGxvYWQgPSBmdW5jdGlvbiB1cGxvYWQoKSB7XG4gICAgdmFyIF90aGlzNSA9IHRoaXM7XG5cbiAgICB2YXIgcHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuXG4gICAgdGhpcy5lbWl0KCdjb3JlOnVwbG9hZCcpO1tdLmNvbmNhdCh0aGlzLnByZVByb2Nlc3NvcnMsIHRoaXMudXBsb2FkZXJzLCB0aGlzLnBvc3RQcm9jZXNzb3JzKS5mb3JFYWNoKGZ1bmN0aW9uIChmbikge1xuICAgICAgcHJvbWlzZSA9IHByb21pc2UudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBmbigpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvLyBOb3QgcmV0dXJuaW5nIHRoZSBgY2F0Y2hgZWQgcHJvbWlzZSwgYmVjYXVzZSB3ZSBzdGlsbCB3YW50IHRvIHJldHVybiBhIHJlamVjdGVkXG4gICAgLy8gcHJvbWlzZSBmcm9tIHRoaXMgbWV0aG9kIGlmIHRoZSB1cGxvYWQgZmFpbGVkLlxuICAgIHByb21pc2UuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgICAgX3RoaXM1LmVtaXQoJ2NvcmU6ZXJyb3InLCBlcnIpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHByb21pc2UudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICBfdGhpczUuZW1pdCgnY29yZTpzdWNjZXNzJyk7XG4gICAgfSk7XG4gIH07XG5cbiAgcmV0dXJuIFVwcHk7XG59KCk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9wdHMpIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFVwcHkpKSB7XG4gICAgcmV0dXJuIG5ldyBVcHB5KG9wdHMpO1xuICB9XG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Q29yZS5qcy5tYXAiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfZXh0ZW5kcyA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gKHRhcmdldCkgeyBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgeyB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldOyBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7IGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoc291cmNlLCBrZXkpKSB7IHRhcmdldFtrZXldID0gc291cmNlW2tleV07IH0gfSB9IHJldHVybiB0YXJnZXQ7IH07XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbi8qKlxuICogVHJhbnNsYXRlcyBzdHJpbmdzIHdpdGggaW50ZXJwb2xhdGlvbiAmIHBsdXJhbGl6YXRpb24gc3VwcG9ydC5cbiAqIEV4dGVuc2libGUgd2l0aCBjdXN0b20gZGljdGlvbmFyaWVzIGFuZCBwbHVyYWxpemF0aW9uIGZ1bmN0aW9ucy5cbiAqXG4gKiBCb3Jyb3dzIGhlYXZpbHkgZnJvbSBhbmQgaW5zcGlyZWQgYnkgUG9seWdsb3QgaHR0cHM6Ly9naXRodWIuY29tL2FpcmJuYi9wb2x5Z2xvdC5qcyxcbiAqIGJhc2ljYWxseSBhIHN0cmlwcGVkLWRvd24gdmVyc2lvbiBvZiBpdC4gRGlmZmVyZW5jZXM6IHBsdXJhbGl6YXRpb24gZnVuY3Rpb25zIGFyZSBub3QgaGFyZGNvZGVkXG4gKiBhbmQgY2FuIGJlIGVhc2lseSBhZGRlZCBhbW9uZyB3aXRoIGRpY3Rpb25hcmllcywgbmVzdGVkIG9iamVjdHMgYXJlIHVzZWQgZm9yIHBsdXJhbGl6YXRpb25cbiAqIGFzIG9wcG9zZWQgdG8gYHx8fHxgIGRlbGltZXRlclxuICpcbiAqIFVzYWdlIGV4YW1wbGU6IGB0cmFuc2xhdG9yLnRyYW5zbGF0ZSgnZmlsZXNfY2hvc2VuJywge3NtYXJ0X2NvdW50OiAzfSlgXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IG9wdHNcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIFRyYW5zbGF0b3Iob3B0cykge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBUcmFuc2xhdG9yKTtcblxuICAgIHZhciBkZWZhdWx0T3B0aW9ucyA9IHtcbiAgICAgIGxvY2FsZToge1xuICAgICAgICBzdHJpbmdzOiB7fSxcbiAgICAgICAgcGx1cmFsaXplOiBmdW5jdGlvbiBwbHVyYWxpemUobikge1xuICAgICAgICAgIGlmIChuID09PSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdGhpcy5vcHRzID0gX2V4dGVuZHMoe30sIGRlZmF1bHRPcHRpb25zLCBvcHRzKTtcbiAgICB0aGlzLmxvY2FsZSA9IF9leHRlbmRzKHt9LCBkZWZhdWx0T3B0aW9ucy5sb2NhbGUsIG9wdHMubG9jYWxlKTtcblxuICAgIC8vIGNvbnNvbGUubG9nKHRoaXMub3B0cy5sb2NhbGUpXG5cbiAgICAvLyB0aGlzLmxvY2FsZS5wbHVyYWxpemUgPSB0aGlzLmxvY2FsZSA/IHRoaXMubG9jYWxlLnBsdXJhbGl6ZSA6IGRlZmF1bHRQbHVyYWxpemVcbiAgICAvLyB0aGlzLmxvY2FsZS5zdHJpbmdzID0gT2JqZWN0LmFzc2lnbih7fSwgZW5fVVMuc3RyaW5ncywgdGhpcy5vcHRzLmxvY2FsZS5zdHJpbmdzKVxuICB9XG5cbiAgLyoqXG4gICAqIFRha2VzIGEgc3RyaW5nIHdpdGggcGxhY2Vob2xkZXIgdmFyaWFibGVzIGxpa2UgYCV7c21hcnRfY291bnR9IGZpbGUgc2VsZWN0ZWRgXG4gICAqIGFuZCByZXBsYWNlcyBpdCB3aXRoIHZhbHVlcyBmcm9tIG9wdGlvbnMgYHtzbWFydF9jb3VudDogNX1gXG4gICAqXG4gICAqIEBsaWNlbnNlIGh0dHBzOi8vZ2l0aHViLmNvbS9haXJibmIvcG9seWdsb3QuanMvYmxvYi9tYXN0ZXIvTElDRU5TRVxuICAgKiB0YWtlbiBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9haXJibmIvcG9seWdsb3QuanMvYmxvYi9tYXN0ZXIvbGliL3BvbHlnbG90LmpzI0wyOTlcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHBocmFzZSB0aGF0IG5lZWRzIGludGVycG9sYXRpb24sIHdpdGggcGxhY2Vob2xkZXJzXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zIHdpdGggdmFsdWVzIHRoYXQgd2lsbCBiZSB1c2VkIHRvIHJlcGxhY2UgcGxhY2Vob2xkZXJzXG4gICAqIEByZXR1cm4ge3N0cmluZ30gaW50ZXJwb2xhdGVkXG4gICAqL1xuXG5cbiAgVHJhbnNsYXRvci5wcm90b3R5cGUuaW50ZXJwb2xhdGUgPSBmdW5jdGlvbiBpbnRlcnBvbGF0ZShwaHJhc2UsIG9wdGlvbnMpIHtcbiAgICB2YXIgcmVwbGFjZSA9IFN0cmluZy5wcm90b3R5cGUucmVwbGFjZTtcbiAgICB2YXIgZG9sbGFyUmVnZXggPSAvXFwkL2c7XG4gICAgdmFyIGRvbGxhckJpbGxzWWFsbCA9ICckJCQkJztcblxuICAgIGZvciAodmFyIGFyZyBpbiBvcHRpb25zKSB7XG4gICAgICBpZiAoYXJnICE9PSAnXycgJiYgb3B0aW9ucy5oYXNPd25Qcm9wZXJ0eShhcmcpKSB7XG4gICAgICAgIC8vIEVuc3VyZSByZXBsYWNlbWVudCB2YWx1ZSBpcyBlc2NhcGVkIHRvIHByZXZlbnQgc3BlY2lhbCAkLXByZWZpeGVkXG4gICAgICAgIC8vIHJlZ2V4IHJlcGxhY2UgdG9rZW5zLiB0aGUgXCIkJCQkXCIgaXMgbmVlZGVkIGJlY2F1c2UgZWFjaCBcIiRcIiBuZWVkcyB0b1xuICAgICAgICAvLyBiZSBlc2NhcGVkIHdpdGggXCIkXCIgaXRzZWxmLCBhbmQgd2UgbmVlZCB0d28gaW4gdGhlIHJlc3VsdGluZyBvdXRwdXQuXG4gICAgICAgIHZhciByZXBsYWNlbWVudCA9IG9wdGlvbnNbYXJnXTtcbiAgICAgICAgaWYgKHR5cGVvZiByZXBsYWNlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICByZXBsYWNlbWVudCA9IHJlcGxhY2UuY2FsbChvcHRpb25zW2FyZ10sIGRvbGxhclJlZ2V4LCBkb2xsYXJCaWxsc1lhbGwpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFdlIGNyZWF0ZSBhIG5ldyBgUmVnRXhwYCBlYWNoIHRpbWUgaW5zdGVhZCBvZiB1c2luZyBhIG1vcmUtZWZmaWNpZW50XG4gICAgICAgIC8vIHN0cmluZyByZXBsYWNlIHNvIHRoYXQgdGhlIHNhbWUgYXJndW1lbnQgY2FuIGJlIHJlcGxhY2VkIG11bHRpcGxlIHRpbWVzXG4gICAgICAgIC8vIGluIHRoZSBzYW1lIHBocmFzZS5cbiAgICAgICAgcGhyYXNlID0gcmVwbGFjZS5jYWxsKHBocmFzZSwgbmV3IFJlZ0V4cCgnJVxcXFx7JyArIGFyZyArICdcXFxcfScsICdnJyksIHJlcGxhY2VtZW50KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHBocmFzZTtcbiAgfTtcblxuICAvKipcbiAgICogUHVibGljIHRyYW5zbGF0ZSBtZXRob2RcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9ucyB3aXRoIHZhbHVlcyB0aGF0IHdpbGwgYmUgdXNlZCBsYXRlciB0byByZXBsYWNlIHBsYWNlaG9sZGVycyBpbiBzdHJpbmdcbiAgICogQHJldHVybiB7c3RyaW5nfSB0cmFuc2xhdGVkIChhbmQgaW50ZXJwb2xhdGVkKVxuICAgKi9cblxuXG4gIFRyYW5zbGF0b3IucHJvdG90eXBlLnRyYW5zbGF0ZSA9IGZ1bmN0aW9uIHRyYW5zbGF0ZShrZXksIG9wdGlvbnMpIHtcbiAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLnNtYXJ0X2NvdW50KSB7XG4gICAgICB2YXIgcGx1cmFsID0gdGhpcy5sb2NhbGUucGx1cmFsaXplKG9wdGlvbnMuc21hcnRfY291bnQpO1xuICAgICAgcmV0dXJuIHRoaXMuaW50ZXJwb2xhdGUodGhpcy5vcHRzLmxvY2FsZS5zdHJpbmdzW2tleV1bcGx1cmFsXSwgb3B0aW9ucyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuaW50ZXJwb2xhdGUodGhpcy5vcHRzLmxvY2FsZS5zdHJpbmdzW2tleV0sIG9wdGlvbnMpO1xuICB9O1xuXG4gIHJldHVybiBUcmFuc2xhdG9yO1xufSgpO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9VHJhbnNsYXRvci5qcy5tYXAiLCIndXNlIHN0cmljdCc7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbnZhciBlZSA9IHJlcXVpcmUoJ25hbWVzcGFjZS1lbWl0dGVyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBVcHB5U29ja2V0KG9wdHMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFVwcHlTb2NrZXQpO1xuXG4gICAgdGhpcy5xdWV1ZWQgPSBbXTtcbiAgICB0aGlzLmlzT3BlbiA9IGZhbHNlO1xuICAgIHRoaXMuc29ja2V0ID0gbmV3IFdlYlNvY2tldChvcHRzLnRhcmdldCk7XG4gICAgdGhpcy5lbWl0dGVyID0gZWUoKTtcblxuICAgIHRoaXMuc29ja2V0Lm9ub3BlbiA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICBfdGhpcy5pc09wZW4gPSB0cnVlO1xuXG4gICAgICB3aGlsZSAoX3RoaXMucXVldWVkLmxlbmd0aCA+IDAgJiYgX3RoaXMuaXNPcGVuKSB7XG4gICAgICAgIHZhciBmaXJzdCA9IF90aGlzLnF1ZXVlZFswXTtcbiAgICAgICAgX3RoaXMuc2VuZChmaXJzdC5hY3Rpb24sIGZpcnN0LnBheWxvYWQpO1xuICAgICAgICBfdGhpcy5xdWV1ZWQgPSBfdGhpcy5xdWV1ZWQuc2xpY2UoMSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHRoaXMuc29ja2V0Lm9uY2xvc2UgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgX3RoaXMuaXNPcGVuID0gZmFsc2U7XG4gICAgfTtcblxuICAgIHRoaXMuX2hhbmRsZU1lc3NhZ2UgPSB0aGlzLl9oYW5kbGVNZXNzYWdlLmJpbmQodGhpcyk7XG5cbiAgICB0aGlzLnNvY2tldC5vbm1lc3NhZ2UgPSB0aGlzLl9oYW5kbGVNZXNzYWdlO1xuXG4gICAgdGhpcy5jbG9zZSA9IHRoaXMuY2xvc2UuYmluZCh0aGlzKTtcbiAgICB0aGlzLmVtaXQgPSB0aGlzLmVtaXQuYmluZCh0aGlzKTtcbiAgICB0aGlzLm9uID0gdGhpcy5vbi5iaW5kKHRoaXMpO1xuICAgIHRoaXMub25jZSA9IHRoaXMub25jZS5iaW5kKHRoaXMpO1xuICAgIHRoaXMuc2VuZCA9IHRoaXMuc2VuZC5iaW5kKHRoaXMpO1xuICB9XG5cbiAgVXBweVNvY2tldC5wcm90b3R5cGUuY2xvc2UgPSBmdW5jdGlvbiBjbG9zZSgpIHtcbiAgICByZXR1cm4gdGhpcy5zb2NrZXQuY2xvc2UoKTtcbiAgfTtcblxuICBVcHB5U29ja2V0LnByb3RvdHlwZS5zZW5kID0gZnVuY3Rpb24gc2VuZChhY3Rpb24sIHBheWxvYWQpIHtcbiAgICAvLyBhdHRhY2ggdXVpZFxuXG4gICAgaWYgKCF0aGlzLmlzT3Blbikge1xuICAgICAgdGhpcy5xdWV1ZWQucHVzaCh7IGFjdGlvbjogYWN0aW9uLCBwYXlsb2FkOiBwYXlsb2FkIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc29ja2V0LnNlbmQoSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgYWN0aW9uOiBhY3Rpb24sXG4gICAgICBwYXlsb2FkOiBwYXlsb2FkXG4gICAgfSkpO1xuICB9O1xuXG4gIFVwcHlTb2NrZXQucHJvdG90eXBlLm9uID0gZnVuY3Rpb24gb24oYWN0aW9uLCBoYW5kbGVyKSB7XG4gICAgY29uc29sZS5sb2coYWN0aW9uKTtcbiAgICB0aGlzLmVtaXR0ZXIub24oYWN0aW9uLCBoYW5kbGVyKTtcbiAgfTtcblxuICBVcHB5U29ja2V0LnByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24gZW1pdChhY3Rpb24sIHBheWxvYWQpIHtcbiAgICBjb25zb2xlLmxvZyhhY3Rpb24pO1xuICAgIHRoaXMuZW1pdHRlci5lbWl0KGFjdGlvbiwgcGF5bG9hZCk7XG4gIH07XG5cbiAgVXBweVNvY2tldC5wcm90b3R5cGUub25jZSA9IGZ1bmN0aW9uIG9uY2UoYWN0aW9uLCBoYW5kbGVyKSB7XG4gICAgdGhpcy5lbWl0dGVyLm9uY2UoYWN0aW9uLCBoYW5kbGVyKTtcbiAgfTtcblxuICBVcHB5U29ja2V0LnByb3RvdHlwZS5faGFuZGxlTWVzc2FnZSA9IGZ1bmN0aW9uIF9oYW5kbGVNZXNzYWdlKGUpIHtcbiAgICB0cnkge1xuICAgICAgdmFyIG1lc3NhZ2UgPSBKU09OLnBhcnNlKGUuZGF0YSk7XG4gICAgICBjb25zb2xlLmxvZyhtZXNzYWdlKTtcbiAgICAgIHRoaXMuZW1pdChtZXNzYWdlLmFjdGlvbiwgbWVzc2FnZS5wYXlsb2FkKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnNvbGUubG9nKGVycik7XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBVcHB5U29ja2V0O1xufSgpO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9VXBweVNvY2tldC5qcy5tYXAiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfdHlwZW9mID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBTeW1ib2wuaXRlcmF0b3IgPT09IFwic3ltYm9sXCIgPyBmdW5jdGlvbiAob2JqKSB7IHJldHVybiB0eXBlb2Ygb2JqOyB9IDogZnVuY3Rpb24gKG9iaikgeyByZXR1cm4gb2JqICYmIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajsgfTtcblxudmFyIF9Qcm9taXNlID0gdHlwZW9mIFByb21pc2UgPT09ICd1bmRlZmluZWQnID8gcmVxdWlyZSgnZXM2LXByb21pc2UnKS5Qcm9taXNlIDogUHJvbWlzZTtcblxuLy8gaW1wb3J0IG1pbWUgZnJvbSAnbWltZS10eXBlcydcbi8vIGltcG9ydCBwaWNhIGZyb20gJ3BpY2EnXG5cbi8qKlxuICogQSBjb2xsZWN0aW9uIG9mIHNtYWxsIHV0aWxpdHkgZnVuY3Rpb25zIHRoYXQgaGVscCB3aXRoIGRvbSBtYW5pcHVsYXRpb24sIGFkZGluZyBsaXN0ZW5lcnMsXG4gKiBwcm9taXNlcyBhbmQgb3RoZXIgZ29vZCB0aGluZ3MuXG4gKlxuICogQG1vZHVsZSBVdGlsc1xuICovXG5cbi8qKlxuICogU2hhbGxvdyBmbGF0dGVuIG5lc3RlZCBhcnJheXMuXG4gKi9cbmZ1bmN0aW9uIGZsYXR0ZW4oYXJyKSB7XG4gIHJldHVybiBbXS5jb25jYXQuYXBwbHkoW10sIGFycik7XG59XG5cbmZ1bmN0aW9uIGlzVG91Y2hEZXZpY2UoKSB7XG4gIHJldHVybiAnb250b3VjaHN0YXJ0JyBpbiB3aW5kb3cgfHwgLy8gd29ya3Mgb24gbW9zdCBicm93c2Vyc1xuICBuYXZpZ2F0b3IubWF4VG91Y2hQb2ludHM7IC8vIHdvcmtzIG9uIElFMTAvMTEgYW5kIFN1cmZhY2Vcbn1cblxuLy8gLyoqXG4vLyAgKiBTaG9ydGVyIGFuZCBmYXN0IHdheSB0byBzZWxlY3QgYSBzaW5nbGUgbm9kZSBpbiB0aGUgRE9NXG4vLyAgKiBAcGFyYW0gICB7IFN0cmluZyB9IHNlbGVjdG9yIC0gdW5pcXVlIGRvbSBzZWxlY3RvclxuLy8gICogQHBhcmFtICAgeyBPYmplY3QgfSBjdHggLSBET00gbm9kZSB3aGVyZSB0aGUgdGFyZ2V0IG9mIG91ciBzZWFyY2ggd2lsbCBpcyBsb2NhdGVkXG4vLyAgKiBAcmV0dXJucyB7IE9iamVjdCB9IGRvbSBub2RlIGZvdW5kXG4vLyAgKi9cbi8vIGZ1bmN0aW9uICQgKHNlbGVjdG9yLCBjdHgpIHtcbi8vICAgcmV0dXJuIChjdHggfHwgZG9jdW1lbnQpLnF1ZXJ5U2VsZWN0b3Ioc2VsZWN0b3IpXG4vLyB9XG5cbi8vIC8qKlxuLy8gICogU2hvcnRlciBhbmQgZmFzdCB3YXkgdG8gc2VsZWN0IG11bHRpcGxlIG5vZGVzIGluIHRoZSBET01cbi8vICAqIEBwYXJhbSAgIHsgU3RyaW5nfEFycmF5IH0gc2VsZWN0b3IgLSBET00gc2VsZWN0b3Igb3Igbm9kZXMgbGlzdFxuLy8gICogQHBhcmFtICAgeyBPYmplY3QgfSBjdHggLSBET00gbm9kZSB3aGVyZSB0aGUgdGFyZ2V0cyBvZiBvdXIgc2VhcmNoIHdpbGwgaXMgbG9jYXRlZFxuLy8gICogQHJldHVybnMgeyBPYmplY3QgfSBkb20gbm9kZXMgZm91bmRcbi8vICAqL1xuLy8gZnVuY3Rpb24gJCQgKHNlbGVjdG9yLCBjdHgpIHtcbi8vICAgdmFyIGVsc1xuLy8gICBpZiAodHlwZW9mIHNlbGVjdG9yID09PSAnc3RyaW5nJykge1xuLy8gICAgIGVscyA9IChjdHggfHwgZG9jdW1lbnQpLnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpXG4vLyAgIH0gZWxzZSB7XG4vLyAgICAgZWxzID0gc2VsZWN0b3Jcbi8vICAgICByZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZWxzKVxuLy8gICB9XG4vLyB9XG5cbmZ1bmN0aW9uIHRydW5jYXRlU3RyaW5nKHN0ciwgbGVuZ3RoKSB7XG4gIGlmIChzdHIubGVuZ3RoID4gbGVuZ3RoKSB7XG4gICAgcmV0dXJuIHN0ci5zdWJzdHIoMCwgbGVuZ3RoIC8gMikgKyAnLi4uJyArIHN0ci5zdWJzdHIoc3RyLmxlbmd0aCAtIGxlbmd0aCAvIDQsIHN0ci5sZW5ndGgpO1xuICB9XG4gIHJldHVybiBzdHI7XG5cbiAgLy8gbW9yZSBwcmVjaXNlIHZlcnNpb24gaWYgbmVlZGVkXG4gIC8vIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzgzMTU4M1xufVxuXG5mdW5jdGlvbiBzZWNvbmRzVG9UaW1lKHJhd1NlY29uZHMpIHtcbiAgdmFyIGhvdXJzID0gTWF0aC5mbG9vcihyYXdTZWNvbmRzIC8gMzYwMCkgJSAyNDtcbiAgdmFyIG1pbnV0ZXMgPSBNYXRoLmZsb29yKHJhd1NlY29uZHMgLyA2MCkgJSA2MDtcbiAgdmFyIHNlY29uZHMgPSBNYXRoLmZsb29yKHJhd1NlY29uZHMgJSA2MCk7XG5cbiAgcmV0dXJuIHsgaG91cnM6IGhvdXJzLCBtaW51dGVzOiBtaW51dGVzLCBzZWNvbmRzOiBzZWNvbmRzIH07XG59XG5cbi8qKlxuICogUGFydGl0aW9uIGFycmF5IGJ5IGEgZ3JvdXBpbmcgZnVuY3Rpb24uXG4gKiBAcGFyYW0gIHtbdHlwZV19IGFycmF5ICAgICAgSW5wdXQgYXJyYXlcbiAqIEBwYXJhbSAge1t0eXBlXX0gZ3JvdXBpbmdGbiBHcm91cGluZyBmdW5jdGlvblxuICogQHJldHVybiB7W3R5cGVdfSAgICAgICAgICAgIEFycmF5IG9mIGFycmF5c1xuICovXG5mdW5jdGlvbiBncm91cEJ5KGFycmF5LCBncm91cGluZ0ZuKSB7XG4gIHJldHVybiBhcnJheS5yZWR1Y2UoZnVuY3Rpb24gKHJlc3VsdCwgaXRlbSkge1xuICAgIHZhciBrZXkgPSBncm91cGluZ0ZuKGl0ZW0pO1xuICAgIHZhciB4cyA9IHJlc3VsdC5nZXQoa2V5KSB8fCBbXTtcbiAgICB4cy5wdXNoKGl0ZW0pO1xuICAgIHJlc3VsdC5zZXQoa2V5LCB4cyk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSwgbmV3IE1hcCgpKTtcbn1cblxuLyoqXG4gKiBUZXN0cyBpZiBldmVyeSBhcnJheSBlbGVtZW50IHBhc3NlcyBwcmVkaWNhdGVcbiAqIEBwYXJhbSAge0FycmF5fSAgYXJyYXkgICAgICAgSW5wdXQgYXJyYXlcbiAqIEBwYXJhbSAge09iamVjdH0gcHJlZGljYXRlRm4gUHJlZGljYXRlXG4gKiBAcmV0dXJuIHtib29sfSAgICAgICAgICAgICAgIEV2ZXJ5IGVsZW1lbnQgcGFzc1xuICovXG5mdW5jdGlvbiBldmVyeShhcnJheSwgcHJlZGljYXRlRm4pIHtcbiAgcmV0dXJuIGFycmF5LnJlZHVjZShmdW5jdGlvbiAocmVzdWx0LCBpdGVtKSB7XG4gICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJlZGljYXRlRm4oaXRlbSk7XG4gIH0sIHRydWUpO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIGxpc3QgaW50byBhcnJheVxuKi9cbmZ1bmN0aW9uIHRvQXJyYXkobGlzdCkge1xuICByZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwobGlzdCB8fCBbXSwgMCk7XG59XG5cbi8qKlxuICogVGFrZXMgYSBmaWxlTmFtZSBhbmQgdHVybnMgaXQgaW50byBmaWxlSUQsIGJ5IGNvbnZlcnRpbmcgdG8gbG93ZXJjYXNlLFxuICogcmVtb3ZpbmcgZXh0cmEgY2hhcmFjdGVycyBhbmQgYWRkaW5nIHVuaXggdGltZXN0YW1wXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGZpbGVOYW1lXG4gKlxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZUZpbGVJRChmaWxlTmFtZSkge1xuICB2YXIgZmlsZUlEID0gZmlsZU5hbWUudG9Mb3dlckNhc2UoKTtcbiAgZmlsZUlEID0gZmlsZUlELnJlcGxhY2UoL1teQS1aMC05XS9pZywgJycpO1xuICBmaWxlSUQgPSBmaWxlSUQgKyBEYXRlLm5vdygpO1xuICByZXR1cm4gZmlsZUlEO1xufVxuXG5mdW5jdGlvbiBleHRlbmQoKSB7XG4gIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBvYmpzID0gQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgb2Jqc1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTtcbiAgfVxuXG4gIHJldHVybiBPYmplY3QuYXNzaWduLmFwcGx5KHRoaXMsIFt7fV0uY29uY2F0KG9ianMpKTtcbn1cblxuLyoqXG4gKiBUYWtlcyBmdW5jdGlvbiBvciBjbGFzcywgcmV0dXJucyBpdHMgbmFtZS5cbiAqIEJlY2F1c2UgSUUgZG9lc27igJl0IHN1cHBvcnQgYGNvbnN0cnVjdG9yLm5hbWVgLlxuICogaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vZGZrYXllLzYzODQ0MzksIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzE1NzE0NDQ1XG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGZuIOKAlCBmdW5jdGlvblxuICpcbiAqL1xuLy8gZnVuY3Rpb24gZ2V0Rm5OYW1lIChmbikge1xuLy8gICB2YXIgZiA9IHR5cGVvZiBmbiA9PT0gJ2Z1bmN0aW9uJ1xuLy8gICB2YXIgcyA9IGYgJiYgKChmbi5uYW1lICYmIFsnJywgZm4ubmFtZV0pIHx8IGZuLnRvU3RyaW5nKCkubWF0Y2goL2Z1bmN0aW9uIChbXlxcKF0rKS8pKVxuLy8gICByZXR1cm4gKCFmICYmICdub3QgYSBmdW5jdGlvbicpIHx8IChzICYmIHNbMV0gfHwgJ2Fub255bW91cycpXG4vLyB9XG5cbmZ1bmN0aW9uIGdldFByb3BvcnRpb25hbEltYWdlSGVpZ2h0KGltZywgbmV3V2lkdGgpIHtcbiAgdmFyIGFzcGVjdCA9IGltZy53aWR0aCAvIGltZy5oZWlnaHQ7XG4gIHZhciBuZXdIZWlnaHQgPSBNYXRoLnJvdW5kKG5ld1dpZHRoIC8gYXNwZWN0KTtcbiAgcmV0dXJuIG5ld0hlaWdodDtcbn1cblxuZnVuY3Rpb24gZ2V0RmlsZVR5cGUoZmlsZSkge1xuICByZXR1cm4gZmlsZS50eXBlID8gZmlsZS50eXBlLnNwbGl0KCcvJykgOiBbJycsICcnXTtcbiAgLy8gcmV0dXJuIG1pbWUubG9va3VwKGZpbGUubmFtZSlcbn1cblxuLy8gVE9ETyBDaGVjayB3aGljaCB0eXBlcyBhcmUgYWN0dWFsbHkgc3VwcG9ydGVkIGluIGJyb3dzZXJzLiBDaHJvbWUgbGlrZXMgd2VibVxuLy8gZnJvbSBteSB0ZXN0aW5nLCBidXQgd2UgbWF5IG5lZWQgbW9yZS5cbi8vIFdlIGNvdWxkIHVzZSBhIGxpYnJhcnkgYnV0IHRoZXkgdGVuZCB0byBjb250YWluIGRvemVucyBvZiBLQnMgb2YgbWFwcGluZ3MsXG4vLyBtb3N0IG9mIHdoaWNoIHdpbGwgZ28gdW51c2VkLCBzbyBub3Qgc3VyZSBpZiB0aGF0J3Mgd29ydGggaXQuXG52YXIgbWltZVRvRXh0ZW5zaW9ucyA9IHtcbiAgJ3ZpZGVvL29nZyc6ICdvZ3YnLFxuICAnYXVkaW8vb2dnJzogJ29nZycsXG4gICd2aWRlby93ZWJtJzogJ3dlYm0nLFxuICAnYXVkaW8vd2VibSc6ICd3ZWJtJyxcbiAgJ3ZpZGVvL21wNCc6ICdtcDQnLFxuICAnYXVkaW8vbXAzJzogJ21wMydcbn07XG5cbmZ1bmN0aW9uIGdldEZpbGVUeXBlRXh0ZW5zaW9uKG1pbWVUeXBlKSB7XG4gIHJldHVybiBtaW1lVG9FeHRlbnNpb25zW21pbWVUeXBlXSB8fCBudWxsO1xufVxuXG4vLyByZXR1cm5zIFtmaWxlTmFtZSwgZmlsZUV4dF1cbmZ1bmN0aW9uIGdldEZpbGVOYW1lQW5kRXh0ZW5zaW9uKGZ1bGxGaWxlTmFtZSkge1xuICB2YXIgcmUgPSAvKD86XFwuKFteLl0rKSk/JC87XG4gIHZhciBmaWxlRXh0ID0gcmUuZXhlYyhmdWxsRmlsZU5hbWUpWzFdO1xuICB2YXIgZmlsZU5hbWUgPSBmdWxsRmlsZU5hbWUucmVwbGFjZSgnLicgKyBmaWxlRXh0LCAnJyk7XG4gIHJldHVybiBbZmlsZU5hbWUsIGZpbGVFeHRdO1xufVxuXG4vKipcbiAqIFJlYWRzIGZpbGUgYXMgZGF0YSBVUkkgZnJvbSBmaWxlIG9iamVjdCxcbiAqIHRoZSBvbmUgeW91IGdldCBmcm9tIGlucHV0W3R5cGU9ZmlsZV0gb3IgZHJhZyAmIGRyb3AuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGZpbGUgb2JqZWN0XG4gKiBAcmV0dXJuIHtQcm9taXNlfSBkYXRhVVJMIG9mIHRoZSBmaWxlXG4gKlxuICovXG5mdW5jdGlvbiByZWFkRmlsZShmaWxlT2JqKSB7XG4gIHJldHVybiBuZXcgX1Byb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIHZhciByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xuICAgIHJlYWRlci5hZGRFdmVudExpc3RlbmVyKCdsb2FkJywgZnVuY3Rpb24gKGV2KSB7XG4gICAgICByZXR1cm4gcmVzb2x2ZShldi50YXJnZXQucmVzdWx0KTtcbiAgICB9KTtcbiAgICByZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlT2JqKTtcblxuICAgIC8vIGZ1bmN0aW9uIHdvcmtlclNjcmlwdCAoKSB7XG4gICAgLy8gICBzZWxmLmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCAoZSkgPT4ge1xuICAgIC8vICAgICBjb25zdCBmaWxlID0gZS5kYXRhLmZpbGVcbiAgICAvLyAgICAgdHJ5IHtcbiAgICAvLyAgICAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlclN5bmMoKVxuICAgIC8vICAgICAgIHBvc3RNZXNzYWdlKHtcbiAgICAvLyAgICAgICAgIGZpbGU6IHJlYWRlci5yZWFkQXNEYXRhVVJMKGZpbGUpXG4gICAgLy8gICAgICAgfSlcbiAgICAvLyAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgLy8gICAgICAgY29uc29sZS5sb2coZXJyKVxuICAgIC8vICAgICB9XG4gICAgLy8gICB9KVxuICAgIC8vIH1cbiAgICAvL1xuICAgIC8vIGNvbnN0IHdvcmtlciA9IG1ha2VXb3JrZXIod29ya2VyU2NyaXB0KVxuICAgIC8vIHdvcmtlci5wb3N0TWVzc2FnZSh7ZmlsZTogZmlsZU9ian0pXG4gICAgLy8gd29ya2VyLmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCAoZSkgPT4ge1xuICAgIC8vICAgY29uc3QgZmlsZURhdGFVUkwgPSBlLmRhdGEuZmlsZVxuICAgIC8vICAgY29uc29sZS5sb2coJ0ZJTEUgXyBEQVRBIF8gVVJMJylcbiAgICAvLyAgIHJldHVybiByZXNvbHZlKGZpbGVEYXRhVVJMKVxuICAgIC8vIH0pXG4gIH0pO1xufVxuXG4vKipcbiAqIFJlc2l6ZXMgYW4gaW1hZ2UgdG8gc3BlY2lmaWVkIHdpZHRoIGFuZCBwcm9wb3J0aW9uYWwgaGVpZ2h0LCB1c2luZyBjYW52YXNcbiAqIFNlZSBodHRwczovL2Rhdmlkd2Fsc2gubmFtZS9yZXNpemUtaW1hZ2UtY2FudmFzLFxuICogaHR0cDovL2JhYmFsYW4uY29tL3Jlc2l6aW5nLWltYWdlcy13aXRoLWphdmFzY3JpcHQvXG4gKiBAVE9ETyBzZWUgaWYgd2UgbmVlZCBodHRwczovL2dpdGh1Yi5jb20vc3RvbWl0YS9pb3MtaW1hZ2VmaWxlLW1lZ2FwaXhlbCBmb3IgaU9TXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IERhdGEgVVJJIG9mIHRoZSBvcmlnaW5hbCBpbWFnZVxuICogQHBhcmFtIHtTdHJpbmd9IHdpZHRoIG9mIHRoZSByZXN1bHRpbmcgaW1hZ2VcbiAqIEByZXR1cm4ge1N0cmluZ30gRGF0YSBVUkkgb2YgdGhlIHJlc2l6ZWQgaW1hZ2VcbiAqL1xuZnVuY3Rpb24gY3JlYXRlSW1hZ2VUaHVtYm5haWwoaW1nRGF0YVVSSSwgbmV3V2lkdGgpIHtcbiAgcmV0dXJuIG5ldyBfUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgdmFyIGltZyA9IG5ldyBJbWFnZSgpO1xuICAgIGltZy5hZGRFdmVudExpc3RlbmVyKCdsb2FkJywgZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIG5ld0ltYWdlV2lkdGggPSBuZXdXaWR0aDtcbiAgICAgIHZhciBuZXdJbWFnZUhlaWdodCA9IGdldFByb3BvcnRpb25hbEltYWdlSGVpZ2h0KGltZywgbmV3SW1hZ2VXaWR0aCk7XG5cbiAgICAgIC8vIGNyZWF0ZSBhbiBvZmYtc2NyZWVuIGNhbnZhc1xuICAgICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgdmFyIGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuXG4gICAgICAvLyBzZXQgaXRzIGRpbWVuc2lvbiB0byB0YXJnZXQgc2l6ZVxuICAgICAgY2FudmFzLndpZHRoID0gbmV3SW1hZ2VXaWR0aDtcbiAgICAgIGNhbnZhcy5oZWlnaHQgPSBuZXdJbWFnZUhlaWdodDtcblxuICAgICAgLy8gZHJhdyBzb3VyY2UgaW1hZ2UgaW50byB0aGUgb2ZmLXNjcmVlbiBjYW52YXM6XG4gICAgICAvLyBjdHguY2xlYXJSZWN0KDAsIDAsIHdpZHRoLCBoZWlnaHQpXG4gICAgICBjdHguZHJhd0ltYWdlKGltZywgMCwgMCwgbmV3SW1hZ2VXaWR0aCwgbmV3SW1hZ2VIZWlnaHQpO1xuXG4gICAgICAvLyBwaWNhLnJlc2l6ZUNhbnZhcyhpbWcsIGNhbnZhcywgKGVycikgPT4ge1xuICAgICAgLy8gICBpZiAoZXJyKSBjb25zb2xlLmxvZyhlcnIpXG4gICAgICAvLyAgIGNvbnN0IHRodW1ibmFpbCA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3BuZycpXG4gICAgICAvLyAgIHJldHVybiByZXNvbHZlKHRodW1ibmFpbClcbiAgICAgIC8vIH0pXG5cbiAgICAgIC8vIGVuY29kZSBpbWFnZSB0byBkYXRhLXVyaSB3aXRoIGJhc2U2NCB2ZXJzaW9uIG9mIGNvbXByZXNzZWQgaW1hZ2VcbiAgICAgIC8vIGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL2pwZWcnLCBxdWFsaXR5KTsgIC8vIHF1YWxpdHkgPSBbMC4wLCAxLjBdXG4gICAgICB2YXIgdGh1bWJuYWlsID0gY2FudmFzLnRvRGF0YVVSTCgnaW1hZ2UvcG5nJyk7XG4gICAgICByZXR1cm4gcmVzb2x2ZSh0aHVtYm5haWwpO1xuICAgIH0pO1xuICAgIGltZy5zcmMgPSBpbWdEYXRhVVJJO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gc3VwcG9ydHNNZWRpYVJlY29yZGVyKCkge1xuICByZXR1cm4gdHlwZW9mIE1lZGlhUmVjb3JkZXIgPT09ICdmdW5jdGlvbicgJiYgISFNZWRpYVJlY29yZGVyLnByb3RvdHlwZSAmJiB0eXBlb2YgTWVkaWFSZWNvcmRlci5wcm90b3R5cGUuc3RhcnQgPT09ICdmdW5jdGlvbic7XG59XG5cbmZ1bmN0aW9uIGRhdGFVUkl0b0Jsb2IoZGF0YVVSSSwgb3B0cywgdG9GaWxlKSB7XG4gIC8vIGdldCB0aGUgYmFzZTY0IGRhdGFcbiAgdmFyIGRhdGEgPSBkYXRhVVJJLnNwbGl0KCcsJylbMV07XG5cbiAgLy8gdXNlciBtYXkgcHJvdmlkZSBtaW1lIHR5cGUsIGlmIG5vdCBnZXQgaXQgZnJvbSBkYXRhIFVSSVxuICB2YXIgbWltZVR5cGUgPSBvcHRzLm1pbWVUeXBlIHx8IGRhdGFVUkkuc3BsaXQoJywnKVswXS5zcGxpdCgnOicpWzFdLnNwbGl0KCc7JylbMF07XG5cbiAgLy8gZGVmYXVsdCB0byBwbGFpbi90ZXh0IGlmIGRhdGEgVVJJIGhhcyBubyBtaW1lVHlwZVxuICBpZiAobWltZVR5cGUgPT0gbnVsbCkge1xuICAgIG1pbWVUeXBlID0gJ3BsYWluL3RleHQnO1xuICB9XG5cbiAgdmFyIGJpbmFyeSA9IGF0b2IoZGF0YSk7XG4gIHZhciBhcnJheSA9IFtdO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGJpbmFyeS5sZW5ndGg7IGkrKykge1xuICAgIGFycmF5LnB1c2goYmluYXJ5LmNoYXJDb2RlQXQoaSkpO1xuICB9XG5cbiAgLy8gQ29udmVydCB0byBhIEZpbGU/XG4gIGlmICh0b0ZpbGUpIHtcbiAgICByZXR1cm4gbmV3IEZpbGUoW25ldyBVaW50OEFycmF5KGFycmF5KV0sIG9wdHMubmFtZSB8fCAnJywgeyB0eXBlOiBtaW1lVHlwZSB9KTtcbiAgfVxuXG4gIHJldHVybiBuZXcgQmxvYihbbmV3IFVpbnQ4QXJyYXkoYXJyYXkpXSwgeyB0eXBlOiBtaW1lVHlwZSB9KTtcbn1cblxuZnVuY3Rpb24gZGF0YVVSSXRvRmlsZShkYXRhVVJJLCBvcHRzKSB7XG4gIHJldHVybiBkYXRhVVJJdG9CbG9iKGRhdGFVUkksIG9wdHMsIHRydWUpO1xufVxuXG4vKipcbiAqIENvcGllcyB0ZXh0IHRvIGNsaXBib2FyZCBieSBjcmVhdGluZyBhbiBhbG1vc3QgaW52aXNpYmxlIHRleHRhcmVhLFxuICogYWRkaW5nIHRleHQgdGhlcmUsIHRoZW4gcnVubmluZyBleGVjQ29tbWFuZCgnY29weScpLlxuICogRmFsbHMgYmFjayB0byBwcm9tcHQoKSB3aGVuIHRoZSBlYXN5IHdheSBmYWlscyAoaGVsbG8sIFNhZmFyaSEpXG4gKiBGcm9tIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzMwODEwMzIyXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHRleHRUb0NvcHlcbiAqIEBwYXJhbSB7U3RyaW5nfSBmYWxsYmFja1N0cmluZ1xuICogQHJldHVybiB7UHJvbWlzZX1cbiAqL1xuZnVuY3Rpb24gY29weVRvQ2xpcGJvYXJkKHRleHRUb0NvcHksIGZhbGxiYWNrU3RyaW5nKSB7XG4gIGZhbGxiYWNrU3RyaW5nID0gZmFsbGJhY2tTdHJpbmcgfHwgJ0NvcHkgdGhlIFVSTCBiZWxvdyc7XG5cbiAgcmV0dXJuIG5ldyBfUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgdmFyIHRleHRBcmVhID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndGV4dGFyZWEnKTtcbiAgICB0ZXh0QXJlYS5zZXRBdHRyaWJ1dGUoJ3N0eWxlJywge1xuICAgICAgcG9zaXRpb246ICdmaXhlZCcsXG4gICAgICB0b3A6IDAsXG4gICAgICBsZWZ0OiAwLFxuICAgICAgd2lkdGg6ICcyZW0nLFxuICAgICAgaGVpZ2h0OiAnMmVtJyxcbiAgICAgIHBhZGRpbmc6IDAsXG4gICAgICBib3JkZXI6ICdub25lJyxcbiAgICAgIG91dGxpbmU6ICdub25lJyxcbiAgICAgIGJveFNoYWRvdzogJ25vbmUnLFxuICAgICAgYmFja2dyb3VuZDogJ3RyYW5zcGFyZW50J1xuICAgIH0pO1xuXG4gICAgdGV4dEFyZWEudmFsdWUgPSB0ZXh0VG9Db3B5O1xuICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQodGV4dEFyZWEpO1xuICAgIHRleHRBcmVhLnNlbGVjdCgpO1xuXG4gICAgdmFyIG1hZ2ljQ29weUZhaWxlZCA9IGZ1bmN0aW9uIG1hZ2ljQ29weUZhaWxlZChlcnIpIHtcbiAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQodGV4dEFyZWEpO1xuICAgICAgd2luZG93LnByb21wdChmYWxsYmFja1N0cmluZywgdGV4dFRvQ29weSk7XG4gICAgICByZXR1cm4gcmVqZWN0KCdPb3BzLCB1bmFibGUgdG8gY29weSBkaXNwbGF5ZWQgZmFsbGJhY2sgcHJvbXB0OiAnICsgZXJyKTtcbiAgICB9O1xuXG4gICAgdHJ5IHtcbiAgICAgIHZhciBzdWNjZXNzZnVsID0gZG9jdW1lbnQuZXhlY0NvbW1hbmQoJ2NvcHknKTtcbiAgICAgIGlmICghc3VjY2Vzc2Z1bCkge1xuICAgICAgICByZXR1cm4gbWFnaWNDb3B5RmFpbGVkKCdjb3B5IGNvbW1hbmQgdW5hdmFpbGFibGUnKTtcbiAgICAgIH1cbiAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQodGV4dEFyZWEpO1xuICAgICAgcmV0dXJuIHJlc29sdmUoKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQodGV4dEFyZWEpO1xuICAgICAgcmV0dXJuIG1hZ2ljQ29weUZhaWxlZChlcnIpO1xuICAgIH1cbiAgfSk7XG59XG5cbi8vIGZ1bmN0aW9uIGNyZWF0ZUlubGluZVdvcmtlciAod29ya2VyRnVuY3Rpb24pIHtcbi8vICAgbGV0IGNvZGUgPSB3b3JrZXJGdW5jdGlvbi50b1N0cmluZygpXG4vLyAgIGNvZGUgPSBjb2RlLnN1YnN0cmluZyhjb2RlLmluZGV4T2YoJ3snKSArIDEsIGNvZGUubGFzdEluZGV4T2YoJ30nKSlcbi8vXG4vLyAgIGNvbnN0IGJsb2IgPSBuZXcgQmxvYihbY29kZV0sIHt0eXBlOiAnYXBwbGljYXRpb24vamF2YXNjcmlwdCd9KVxuLy8gICBjb25zdCB3b3JrZXIgPSBuZXcgV29ya2VyKFVSTC5jcmVhdGVPYmplY3RVUkwoYmxvYikpXG4vL1xuLy8gICByZXR1cm4gd29ya2VyXG4vLyB9XG5cbi8vIGZ1bmN0aW9uIG1ha2VXb3JrZXIgKHNjcmlwdCkge1xuLy8gICB2YXIgVVJMID0gd2luZG93LlVSTCB8fCB3aW5kb3cud2Via2l0VVJMXG4vLyAgIHZhciBCbG9iID0gd2luZG93LkJsb2Jcbi8vICAgdmFyIFdvcmtlciA9IHdpbmRvdy5Xb3JrZXJcbi8vXG4vLyAgIGlmICghVVJMIHx8ICFCbG9iIHx8ICFXb3JrZXIgfHwgIXNjcmlwdCkge1xuLy8gICAgIHJldHVybiBudWxsXG4vLyAgIH1cbi8vXG4vLyAgIGxldCBjb2RlID0gc2NyaXB0LnRvU3RyaW5nKClcbi8vICAgY29kZSA9IGNvZGUuc3Vic3RyaW5nKGNvZGUuaW5kZXhPZigneycpICsgMSwgY29kZS5sYXN0SW5kZXhPZignfScpKVxuLy9cbi8vICAgdmFyIGJsb2IgPSBuZXcgQmxvYihbY29kZV0pXG4vLyAgIHZhciB3b3JrZXIgPSBuZXcgV29ya2VyKFVSTC5jcmVhdGVPYmplY3RVUkwoYmxvYikpXG4vLyAgIHJldHVybiB3b3JrZXJcbi8vIH1cblxuZnVuY3Rpb24gZ2V0U3BlZWQoZmlsZVByb2dyZXNzKSB7XG4gIGlmICghZmlsZVByb2dyZXNzLmJ5dGVzVXBsb2FkZWQpIHJldHVybiAwO1xuXG4gIHZhciB0aW1lRWxhcHNlZCA9IG5ldyBEYXRlKCkgLSBmaWxlUHJvZ3Jlc3MudXBsb2FkU3RhcnRlZDtcbiAgdmFyIHVwbG9hZFNwZWVkID0gZmlsZVByb2dyZXNzLmJ5dGVzVXBsb2FkZWQgLyAodGltZUVsYXBzZWQgLyAxMDAwKTtcbiAgcmV0dXJuIHVwbG9hZFNwZWVkO1xufVxuXG5mdW5jdGlvbiBnZXRFVEEoZmlsZVByb2dyZXNzKSB7XG4gIGlmICghZmlsZVByb2dyZXNzLmJ5dGVzVXBsb2FkZWQpIHJldHVybiAwO1xuXG4gIHZhciB1cGxvYWRTcGVlZCA9IGdldFNwZWVkKGZpbGVQcm9ncmVzcyk7XG4gIHZhciBieXRlc1JlbWFpbmluZyA9IGZpbGVQcm9ncmVzcy5ieXRlc1RvdGFsIC0gZmlsZVByb2dyZXNzLmJ5dGVzVXBsb2FkZWQ7XG4gIHZhciBzZWNvbmRzUmVtYWluaW5nID0gTWF0aC5yb3VuZChieXRlc1JlbWFpbmluZyAvIHVwbG9hZFNwZWVkICogMTApIC8gMTA7XG5cbiAgcmV0dXJuIHNlY29uZHNSZW1haW5pbmc7XG59XG5cbmZ1bmN0aW9uIHByZXR0eUVUQShzZWNvbmRzKSB7XG4gIHZhciB0aW1lID0gc2Vjb25kc1RvVGltZShzZWNvbmRzKTtcblxuICAvLyBPbmx5IGRpc3BsYXkgaG91cnMgYW5kIG1pbnV0ZXMgaWYgdGhleSBhcmUgZ3JlYXRlciB0aGFuIDAgYnV0IGFsd2F5c1xuICAvLyBkaXNwbGF5IG1pbnV0ZXMgaWYgaG91cnMgaXMgYmVpbmcgZGlzcGxheWVkXG4gIC8vIERpc3BsYXkgYSBsZWFkaW5nIHplcm8gaWYgdGhlIHRoZXJlIGlzIGEgcHJlY2VkaW5nIHVuaXQ6IDFtIDA1cywgYnV0IDVzXG4gIHZhciBob3Vyc1N0ciA9IHRpbWUuaG91cnMgPyB0aW1lLmhvdXJzICsgJ2ggJyA6ICcnO1xuICB2YXIgbWludXRlc1ZhbCA9IHRpbWUuaG91cnMgPyAoJzAnICsgdGltZS5taW51dGVzKS5zdWJzdHIoLTIpIDogdGltZS5taW51dGVzO1xuICB2YXIgbWludXRlc1N0ciA9IG1pbnV0ZXNWYWwgPyBtaW51dGVzVmFsICsgJ20gJyA6ICcnO1xuICB2YXIgc2Vjb25kc1ZhbCA9IG1pbnV0ZXNWYWwgPyAoJzAnICsgdGltZS5zZWNvbmRzKS5zdWJzdHIoLTIpIDogdGltZS5zZWNvbmRzO1xuICB2YXIgc2Vjb25kc1N0ciA9IHNlY29uZHNWYWwgKyAncyc7XG5cbiAgcmV0dXJuICcnICsgaG91cnNTdHIgKyBtaW51dGVzU3RyICsgc2Vjb25kc1N0cjtcbn1cblxuLy8gZnVuY3Rpb24gbWFrZUNhY2hpbmdGdW5jdGlvbiAoKSB7XG4vLyAgIGxldCBjYWNoZWRFbCA9IG51bGxcbi8vICAgbGV0IGxhc3RVcGRhdGUgPSBEYXRlLm5vdygpXG4vL1xuLy8gICByZXR1cm4gZnVuY3Rpb24gY2FjaGVFbGVtZW50IChlbCwgdGltZSkge1xuLy8gICAgIGlmIChEYXRlLm5vdygpIC0gbGFzdFVwZGF0ZSA8IHRpbWUpIHtcbi8vICAgICAgIHJldHVybiBjYWNoZWRFbFxuLy8gICAgIH1cbi8vXG4vLyAgICAgY2FjaGVkRWwgPSBlbFxuLy8gICAgIGxhc3RVcGRhdGUgPSBEYXRlLm5vdygpXG4vL1xuLy8gICAgIHJldHVybiBlbFxuLy8gICB9XG4vLyB9XG5cbi8qKlxuICogQ2hlY2sgaWYgYW4gb2JqZWN0IGlzIGEgRE9NIGVsZW1lbnQuIER1Y2stdHlwaW5nIGJhc2VkIG9uIGBub2RlVHlwZWAuXG4gKlxuICogQHBhcmFtIHsqfSBvYmpcbiAqL1xuZnVuY3Rpb24gaXNET01FbGVtZW50KG9iaikge1xuICByZXR1cm4gb2JqICYmICh0eXBlb2Ygb2JqID09PSAndW5kZWZpbmVkJyA/ICd1bmRlZmluZWQnIDogX3R5cGVvZihvYmopKSA9PT0gJ29iamVjdCcgJiYgb2JqLm5vZGVUeXBlID09PSBOb2RlLkVMRU1FTlRfTk9ERTtcbn1cblxuLyoqXG4gKiBGaW5kIGEgRE9NIGVsZW1lbnQuXG4gKlxuICogQHBhcmFtIHtOb2RlfHN0cmluZ30gZWxlbWVudFxuICogQHJldHVybiB7Tm9kZXxudWxsfVxuICovXG5mdW5jdGlvbiBmaW5kRE9NRWxlbWVudChlbGVtZW50KSB7XG4gIGlmICh0eXBlb2YgZWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihlbGVtZW50KTtcbiAgfVxuXG4gIGlmICgodHlwZW9mIGVsZW1lbnQgPT09ICd1bmRlZmluZWQnID8gJ3VuZGVmaW5lZCcgOiBfdHlwZW9mKGVsZW1lbnQpKSA9PT0gJ29iamVjdCcgJiYgaXNET01FbGVtZW50KGVsZW1lbnQpKSB7XG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGdlbmVyYXRlRmlsZUlEOiBnZW5lcmF0ZUZpbGVJRCxcbiAgdG9BcnJheTogdG9BcnJheSxcbiAgZXZlcnk6IGV2ZXJ5LFxuICBmbGF0dGVuOiBmbGF0dGVuLFxuICBncm91cEJ5OiBncm91cEJ5LFxuICAvLyAkLFxuICAvLyAkJCxcbiAgZXh0ZW5kOiBleHRlbmQsXG4gIHJlYWRGaWxlOiByZWFkRmlsZSxcbiAgY3JlYXRlSW1hZ2VUaHVtYm5haWw6IGNyZWF0ZUltYWdlVGh1bWJuYWlsLFxuICBnZXRQcm9wb3J0aW9uYWxJbWFnZUhlaWdodDogZ2V0UHJvcG9ydGlvbmFsSW1hZ2VIZWlnaHQsXG4gIHN1cHBvcnRzTWVkaWFSZWNvcmRlcjogc3VwcG9ydHNNZWRpYVJlY29yZGVyLFxuICBpc1RvdWNoRGV2aWNlOiBpc1RvdWNoRGV2aWNlLFxuICBnZXRGaWxlTmFtZUFuZEV4dGVuc2lvbjogZ2V0RmlsZU5hbWVBbmRFeHRlbnNpb24sXG4gIHRydW5jYXRlU3RyaW5nOiB0cnVuY2F0ZVN0cmluZyxcbiAgZ2V0RmlsZVR5cGVFeHRlbnNpb246IGdldEZpbGVUeXBlRXh0ZW5zaW9uLFxuICBnZXRGaWxlVHlwZTogZ2V0RmlsZVR5cGUsXG4gIHNlY29uZHNUb1RpbWU6IHNlY29uZHNUb1RpbWUsXG4gIGRhdGFVUkl0b0Jsb2I6IGRhdGFVUkl0b0Jsb2IsXG4gIGRhdGFVUkl0b0ZpbGU6IGRhdGFVUkl0b0ZpbGUsXG4gIGdldFNwZWVkOiBnZXRTcGVlZCxcbiAgZ2V0RVRBOiBnZXRFVEEsXG4gIC8vIG1ha2VXb3JrZXIsXG4gIC8vIG1ha2VDYWNoaW5nRnVuY3Rpb24sXG4gIGNvcHlUb0NsaXBib2FyZDogY29weVRvQ2xpcGJvYXJkLFxuICBwcmV0dHlFVEE6IHByZXR0eUVUQSxcbiAgZmluZERPTUVsZW1lbnQ6IGZpbmRET01FbGVtZW50XG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9VXRpbHMuanMubWFwIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgQ29yZSA9IHJlcXVpcmUoJy4vQ29yZScpO1xubW9kdWxlLmV4cG9ydHMgPSBDb3JlO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW5kZXguanMubWFwIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgX2FwcGVuZENoaWxkID0gcmVxdWlyZSgneW8teW9pZnkvbGliL2FwcGVuZENoaWxkJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHByb3BzKSB7XG4gIHZhciBfdXBweVByb3ZpZGVyQXV0aEJ0bkRlbW8sIF91cHB5UHJvdmlkZXJBdXRoVGl0bGVOYW1lLCBfYnIsIF91cHB5UHJvdmlkZXJBdXRoVGl0bGUsIF91cHB5UHJvdmlkZXJBdXRoQnRuLCBfdXBweVByb3ZpZGVyQXV0aDtcblxuICB2YXIgZGVtb0xpbmsgPSBwcm9wcy5kZW1vID8gKF91cHB5UHJvdmlkZXJBdXRoQnRuRGVtbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2J1dHRvbicpLCBfdXBweVByb3ZpZGVyQXV0aEJ0bkRlbW8ub25jbGljayA9IHByb3BzLmhhbmRsZURlbW9BdXRoLCBfdXBweVByb3ZpZGVyQXV0aEJ0bkRlbW8uc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5UHJvdmlkZXItYXV0aEJ0bkRlbW8nKSwgX3VwcHlQcm92aWRlckF1dGhCdG5EZW1vLnRleHRDb250ZW50ID0gJ1Byb2NlZWQgd2l0aCBEZW1vIEFjY291bnQnLCBfdXBweVByb3ZpZGVyQXV0aEJ0bkRlbW8pIDogbnVsbDtcbiAgcmV0dXJuIF91cHB5UHJvdmlkZXJBdXRoID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksIF91cHB5UHJvdmlkZXJBdXRoLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweVByb3ZpZGVyLWF1dGgnKSwgX2FwcGVuZENoaWxkKF91cHB5UHJvdmlkZXJBdXRoLCBbJyAnLCAoX3VwcHlQcm92aWRlckF1dGhUaXRsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2gxJyksIF91cHB5UHJvdmlkZXJBdXRoVGl0bGUuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5UHJvdmlkZXItYXV0aFRpdGxlJyksIF9hcHBlbmRDaGlsZChfdXBweVByb3ZpZGVyQXV0aFRpdGxlLCBbJyBQbGVhc2UgYXV0aGVudGljYXRlIHdpdGggJywgKF91cHB5UHJvdmlkZXJBdXRoVGl0bGVOYW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpLCBfdXBweVByb3ZpZGVyQXV0aFRpdGxlTmFtZS5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlQcm92aWRlci1hdXRoVGl0bGVOYW1lJyksIF9hcHBlbmRDaGlsZChfdXBweVByb3ZpZGVyQXV0aFRpdGxlTmFtZSwgW3Byb3BzLnBsdWdpbk5hbWVdKSwgX3VwcHlQcm92aWRlckF1dGhUaXRsZU5hbWUpLCAoX2JyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnInKSwgX2JyKSwgJyB0byBzZWxlY3QgZmlsZXMgJ10pLCBfdXBweVByb3ZpZGVyQXV0aFRpdGxlKSwgJyAnLCAoX3VwcHlQcm92aWRlckF1dGhCdG4gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdidXR0b24nKSwgX3VwcHlQcm92aWRlckF1dGhCdG4ub25jbGljayA9IHByb3BzLmhhbmRsZUF1dGgsIF91cHB5UHJvdmlkZXJBdXRoQnRuLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweVByb3ZpZGVyLWF1dGhCdG4nKSwgX3VwcHlQcm92aWRlckF1dGhCdG4udGV4dENvbnRlbnQgPSAnQXV0aGVudGljYXRlJywgX3VwcHlQcm92aWRlckF1dGhCdG4pLCAnICcsIGRlbW9MaW5rLCAnICddKSwgX3VwcHlQcm92aWRlckF1dGg7XG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9QXV0aFZpZXcuanMubWFwIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgX2FwcGVuZENoaWxkID0gcmVxdWlyZSgneW8teW9pZnkvbGliL2FwcGVuZENoaWxkJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHByb3BzKSB7XG4gIHZhciBfYnV0dG9uLCBfbGk7XG5cbiAgcmV0dXJuIF9saSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xpJyksIF9hcHBlbmRDaGlsZChfbGksIFsnICcsIChfYnV0dG9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnV0dG9uJyksIF9idXR0b24ub25jbGljayA9IHByb3BzLmdldEZvbGRlciwgX2FwcGVuZENoaWxkKF9idXR0b24sIFtwcm9wcy50aXRsZV0pLCBfYnV0dG9uKSwgJyAnXSksIF9saTtcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1CcmVhZGNydW1iLmpzLm1hcCIsIid1c2Ugc3RyaWN0JztcblxudmFyIF9hcHBlbmRDaGlsZCA9IHJlcXVpcmUoJ3lvLXlvaWZ5L2xpYi9hcHBlbmRDaGlsZCcpO1xuXG52YXIgQnJlYWRjcnVtYiA9IHJlcXVpcmUoJy4vQnJlYWRjcnVtYicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChwcm9wcykge1xuICB2YXIgX3VwcHlQcm92aWRlckJyZWFkY3J1bWJzO1xuXG4gIHJldHVybiBfdXBweVByb3ZpZGVyQnJlYWRjcnVtYnMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd1bCcpLCBfdXBweVByb3ZpZGVyQnJlYWRjcnVtYnMuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5UHJvdmlkZXItYnJlYWRjcnVtYnMnKSwgX2FwcGVuZENoaWxkKF91cHB5UHJvdmlkZXJCcmVhZGNydW1icywgWycgJywgcHJvcHMuZGlyZWN0b3JpZXMubWFwKGZ1bmN0aW9uIChkaXJlY3RvcnkpIHtcbiAgICByZXR1cm4gQnJlYWRjcnVtYih7XG4gICAgICBnZXRGb2xkZXI6IGZ1bmN0aW9uIGdldEZvbGRlcigpIHtcbiAgICAgICAgcmV0dXJuIHByb3BzLmdldEZvbGRlcihkaXJlY3RvcnkuaWQpO1xuICAgICAgfSxcbiAgICAgIHRpdGxlOiBkaXJlY3RvcnkudGl0bGVcbiAgICB9KTtcbiAgfSksICcgJ10pLCBfdXBweVByb3ZpZGVyQnJlYWRjcnVtYnM7XG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9QnJlYWRjcnVtYnMuanMubWFwIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgX2FwcGVuZENoaWxkID0gcmVxdWlyZSgneW8teW9pZnkvbGliL2FwcGVuZENoaWxkJyk7XG5cbnZhciBCcmVhZGNydW1icyA9IHJlcXVpcmUoJy4vQnJlYWRjcnVtYnMnKTtcbnZhciBUYWJsZSA9IHJlcXVpcmUoJy4vVGFibGUnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAocHJvcHMpIHtcbiAgdmFyIF9icm93c2VyU2VhcmNoLCBfaGVhZGVyLCBfYnJvd3NlclVzZXJMb2dvdXQsIF9icm93c2VyU3ViSGVhZGVyLCBfYnJvd3NlckNvbnRlbnQsIF9icm93c2VyQm9keSwgX2Jyb3dzZXI7XG5cbiAgdmFyIGZpbHRlcmVkRm9sZGVycyA9IHByb3BzLmZvbGRlcnM7XG4gIHZhciBmaWx0ZXJlZEZpbGVzID0gcHJvcHMuZmlsZXM7XG5cbiAgaWYgKHByb3BzLmZpbHRlcklucHV0ICE9PSAnJykge1xuICAgIGZpbHRlcmVkRm9sZGVycyA9IHByb3BzLmZpbHRlckl0ZW1zKHByb3BzLmZvbGRlcnMpO1xuICAgIGZpbHRlcmVkRmlsZXMgPSBwcm9wcy5maWx0ZXJJdGVtcyhwcm9wcy5maWxlcyk7XG4gIH1cblxuICByZXR1cm4gX2Jyb3dzZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSwgX2Jyb3dzZXIuc2V0QXR0cmlidXRlKCdjbGFzcycsICdCcm93c2VyJyksIF9hcHBlbmRDaGlsZChfYnJvd3NlciwgWycgJywgKF9oZWFkZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdoZWFkZXInKSwgX2FwcGVuZENoaWxkKF9oZWFkZXIsIFsnICcsIChfYnJvd3NlclNlYXJjaCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0JyksIF9icm93c2VyU2VhcmNoLnNldEF0dHJpYnV0ZSgndHlwZScsICd0ZXh0JyksIF9icm93c2VyU2VhcmNoLnNldEF0dHJpYnV0ZSgncGxhY2Vob2xkZXInLCAnU2VhcmNoIERyaXZlJyksIF9icm93c2VyU2VhcmNoLm9ua2V5dXAgPSBwcm9wcy5maWx0ZXJRdWVyeSwgX2Jyb3dzZXJTZWFyY2guc2V0QXR0cmlidXRlKCd2YWx1ZScsICcnICsgU3RyaW5nKHByb3BzLmZpbHRlcklucHV0KSArICcnKSwgX2Jyb3dzZXJTZWFyY2guc2V0QXR0cmlidXRlKCdjbGFzcycsICdCcm93c2VyLXNlYXJjaCcpLCBfYnJvd3NlclNlYXJjaCksICcgJ10pLCBfaGVhZGVyKSwgJyAnLCAoX2Jyb3dzZXJTdWJIZWFkZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSwgX2Jyb3dzZXJTdWJIZWFkZXIuc2V0QXR0cmlidXRlKCdjbGFzcycsICdCcm93c2VyLXN1YkhlYWRlcicpLCBfYXBwZW5kQ2hpbGQoX2Jyb3dzZXJTdWJIZWFkZXIsIFsnICcsIEJyZWFkY3J1bWJzKHtcbiAgICBnZXRGb2xkZXI6IHByb3BzLmdldEZvbGRlcixcbiAgICBkaXJlY3RvcmllczogcHJvcHMuZGlyZWN0b3JpZXNcbiAgfSksICcgJywgKF9icm93c2VyVXNlckxvZ291dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2J1dHRvbicpLCBfYnJvd3NlclVzZXJMb2dvdXQub25jbGljayA9IHByb3BzLmxvZ291dCwgX2Jyb3dzZXJVc2VyTG9nb3V0LnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnQnJvd3Nlci11c2VyTG9nb3V0JyksIF9icm93c2VyVXNlckxvZ291dC50ZXh0Q29udGVudCA9ICdMb2cgb3V0JywgX2Jyb3dzZXJVc2VyTG9nb3V0KSwgJyAnXSksIF9icm93c2VyU3ViSGVhZGVyKSwgJyAnLCAoX2Jyb3dzZXJCb2R5ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksIF9icm93c2VyQm9keS5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ0Jyb3dzZXItYm9keScpLCBfYXBwZW5kQ2hpbGQoX2Jyb3dzZXJCb2R5LCBbJyAnLCAoX2Jyb3dzZXJDb250ZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbWFpbicpLCBfYnJvd3NlckNvbnRlbnQuc2V0QXR0cmlidXRlKCdjbGFzcycsICdCcm93c2VyLWNvbnRlbnQnKSwgX2FwcGVuZENoaWxkKF9icm93c2VyQ29udGVudCwgWycgJywgVGFibGUoe1xuICAgIGNvbHVtbnM6IFt7XG4gICAgICBuYW1lOiAnTmFtZScsXG4gICAgICBrZXk6ICd0aXRsZSdcbiAgICB9XSxcbiAgICBmb2xkZXJzOiBmaWx0ZXJlZEZvbGRlcnMsXG4gICAgZmlsZXM6IGZpbHRlcmVkRmlsZXMsXG4gICAgYWN0aXZlUm93OiBwcm9wcy5pc0FjdGl2ZVJvdyxcbiAgICBzb3J0QnlUaXRsZTogcHJvcHMuc29ydEJ5VGl0bGUsXG4gICAgc29ydEJ5RGF0ZTogcHJvcHMuc29ydEJ5RGF0ZSxcbiAgICBoYW5kbGVSb3dDbGljazogcHJvcHMuaGFuZGxlUm93Q2xpY2ssXG4gICAgaGFuZGxlRmlsZURvdWJsZUNsaWNrOiBwcm9wcy5hZGRGaWxlLFxuICAgIGhhbmRsZUZvbGRlckRvdWJsZUNsaWNrOiBwcm9wcy5nZXROZXh0Rm9sZGVyLFxuICAgIGdldEl0ZW1OYW1lOiBwcm9wcy5nZXRJdGVtTmFtZSxcbiAgICBnZXRJdGVtSWNvbjogcHJvcHMuZ2V0SXRlbUljb25cbiAgfSksICcgJ10pLCBfYnJvd3NlckNvbnRlbnQpLCAnICddKSwgX2Jyb3dzZXJCb2R5KSwgJyAnXSksIF9icm93c2VyO1xufTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPUJyb3dzZXIuanMubWFwIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgX2FwcGVuZENoaWxkID0gcmVxdWlyZSgneW8teW9pZnkvbGliL2FwcGVuZENoaWxkJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHByb3BzKSB7XG4gIHZhciBfc3BhbiwgX3VwcHlQcm92aWRlckVycm9yO1xuXG4gIHJldHVybiBfdXBweVByb3ZpZGVyRXJyb3IgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSwgX3VwcHlQcm92aWRlckVycm9yLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweVByb3ZpZGVyLWVycm9yJyksIF9hcHBlbmRDaGlsZChfdXBweVByb3ZpZGVyRXJyb3IsIFsnICcsIChfc3BhbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKSwgX2FwcGVuZENoaWxkKF9zcGFuLCBbJyBTb21ldGhpbmcgd2VudCB3cm9uZy4gUHJvYmFibHkgb3VyIGZhdWx0LiAnLCBwcm9wcy5lcnJvciwgJyAnXSksIF9zcGFuKSwgJyAnXSksIF91cHB5UHJvdmlkZXJFcnJvcjtcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1FcnJvci5qcy5tYXAiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfYXBwZW5kQ2hpbGQgPSByZXF1aXJlKCd5by15b2lmeS9saWIvYXBwZW5kQ2hpbGQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAocHJvcHMpIHtcbiAgdmFyIF9zcGFuLCBfdXBweVByb3ZpZGVyTG9hZGluZztcblxuICByZXR1cm4gX3VwcHlQcm92aWRlckxvYWRpbmcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSwgX3VwcHlQcm92aWRlckxvYWRpbmcuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5UHJvdmlkZXItbG9hZGluZycpLCBfYXBwZW5kQ2hpbGQoX3VwcHlQcm92aWRlckxvYWRpbmcsIFsnICcsIChfc3BhbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKSwgX3NwYW4udGV4dENvbnRlbnQgPSAnIExvYWRpbmcgLi4uICcsIF9zcGFuKSwgJyAnXSksIF91cHB5UHJvdmlkZXJMb2FkaW5nO1xufTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPUxvYWRlci5qcy5tYXAiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfYXBwZW5kQ2hpbGQgPSByZXF1aXJlKCd5by15b2lmeS9saWIvYXBwZW5kQ2hpbGQnKTtcblxudmFyIFJvdyA9IHJlcXVpcmUoJy4vVGFibGVSb3cnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAocHJvcHMpIHtcbiAgdmFyIF90ciwgX2Jyb3dzZXJUYWJsZUhlYWRlciwgX3Rib2R5LCBfYnJvd3NlclRhYmxlO1xuXG4gIHZhciBoZWFkZXJzID0gcHJvcHMuY29sdW1ucy5tYXAoZnVuY3Rpb24gKGNvbHVtbikge1xuICAgIHZhciBfYnJvd3NlclRhYmxlSGVhZGVyQ29sdW1uO1xuXG4gICAgcmV0dXJuIF9icm93c2VyVGFibGVIZWFkZXJDb2x1bW4gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0aCcpLCBfYnJvd3NlclRhYmxlSGVhZGVyQ29sdW1uLm9uY2xpY2sgPSBwcm9wcy5zb3J0QnlUaXRsZSwgX2Jyb3dzZXJUYWJsZUhlYWRlckNvbHVtbi5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ0Jyb3dzZXJUYWJsZS1oZWFkZXJDb2x1bW4gQnJvd3NlclRhYmxlLWNvbHVtbicpLCBfYXBwZW5kQ2hpbGQoX2Jyb3dzZXJUYWJsZUhlYWRlckNvbHVtbiwgWycgJywgY29sdW1uLm5hbWUsICcgJ10pLCBfYnJvd3NlclRhYmxlSGVhZGVyQ29sdW1uO1xuICB9KTtcblxuICByZXR1cm4gX2Jyb3dzZXJUYWJsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3RhYmxlJyksIF9icm93c2VyVGFibGUuc2V0QXR0cmlidXRlKCdjbGFzcycsICdCcm93c2VyVGFibGUnKSwgX2FwcGVuZENoaWxkKF9icm93c2VyVGFibGUsIFsnICcsIChfYnJvd3NlclRhYmxlSGVhZGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndGhlYWQnKSwgX2Jyb3dzZXJUYWJsZUhlYWRlci5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ0Jyb3dzZXJUYWJsZS1oZWFkZXInKSwgX2FwcGVuZENoaWxkKF9icm93c2VyVGFibGVIZWFkZXIsIFsnICcsIChfdHIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0cicpLCBfYXBwZW5kQ2hpbGQoX3RyLCBbJyAnLCBoZWFkZXJzLCAnICddKSwgX3RyKSwgJyAnXSksIF9icm93c2VyVGFibGVIZWFkZXIpLCAnICcsIChfdGJvZHkgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0Ym9keScpLCBfYXBwZW5kQ2hpbGQoX3Rib2R5LCBbJyAnLCBwcm9wcy5mb2xkZXJzLm1hcChmdW5jdGlvbiAoZm9sZGVyKSB7XG4gICAgcmV0dXJuIFJvdyh7XG4gICAgICB0aXRsZTogcHJvcHMuZ2V0SXRlbU5hbWUoZm9sZGVyKSxcbiAgICAgIGFjdGl2ZTogcHJvcHMuYWN0aXZlUm93KGZvbGRlciksXG4gICAgICBnZXRJdGVtSWNvbjogZnVuY3Rpb24gZ2V0SXRlbUljb24oKSB7XG4gICAgICAgIHJldHVybiBwcm9wcy5nZXRJdGVtSWNvbihmb2xkZXIpO1xuICAgICAgfSxcbiAgICAgIGhhbmRsZUNsaWNrOiBmdW5jdGlvbiBoYW5kbGVDbGljaygpIHtcbiAgICAgICAgcmV0dXJuIHByb3BzLmhhbmRsZVJvd0NsaWNrKGZvbGRlcik7XG4gICAgICB9LFxuICAgICAgaGFuZGxlRG91YmxlQ2xpY2s6IGZ1bmN0aW9uIGhhbmRsZURvdWJsZUNsaWNrKCkge1xuICAgICAgICByZXR1cm4gcHJvcHMuaGFuZGxlRm9sZGVyRG91YmxlQ2xpY2soZm9sZGVyKTtcbiAgICAgIH0sXG4gICAgICBjb2x1bW5zOiBwcm9wcy5jb2x1bW5zXG4gICAgfSk7XG4gIH0pLCAnICcsIHByb3BzLmZpbGVzLm1hcChmdW5jdGlvbiAoZmlsZSkge1xuICAgIHJldHVybiBSb3coe1xuICAgICAgdGl0bGU6IHByb3BzLmdldEl0ZW1OYW1lKGZpbGUpLFxuICAgICAgYWN0aXZlOiBwcm9wcy5hY3RpdmVSb3coZmlsZSksXG4gICAgICBnZXRJdGVtSWNvbjogZnVuY3Rpb24gZ2V0SXRlbUljb24oKSB7XG4gICAgICAgIHJldHVybiBwcm9wcy5nZXRJdGVtSWNvbihmaWxlKTtcbiAgICAgIH0sXG4gICAgICBoYW5kbGVDbGljazogZnVuY3Rpb24gaGFuZGxlQ2xpY2soKSB7XG4gICAgICAgIHJldHVybiBwcm9wcy5oYW5kbGVSb3dDbGljayhmaWxlKTtcbiAgICAgIH0sXG4gICAgICBoYW5kbGVEb3VibGVDbGljazogZnVuY3Rpb24gaGFuZGxlRG91YmxlQ2xpY2soKSB7XG4gICAgICAgIHJldHVybiBwcm9wcy5oYW5kbGVGaWxlRG91YmxlQ2xpY2soZmlsZSk7XG4gICAgICB9LFxuICAgICAgY29sdW1uczogcHJvcHMuY29sdW1uc1xuICAgIH0pO1xuICB9KSwgJyAnXSksIF90Ym9keSksICcgJ10pLCBfYnJvd3NlclRhYmxlO1xufTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPVRhYmxlLmpzLm1hcCIsIid1c2Ugc3RyaWN0JztcblxudmFyIF9hcHBlbmRDaGlsZCA9IHJlcXVpcmUoJ3lvLXlvaWZ5L2xpYi9hcHBlbmRDaGlsZCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChwcm9wcykge1xuICB2YXIgX2Jyb3dzZXJUYWJsZVJvd0NvbHVtbjtcblxuICByZXR1cm4gX2Jyb3dzZXJUYWJsZVJvd0NvbHVtbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3RkJyksIF9icm93c2VyVGFibGVSb3dDb2x1bW4uc2V0QXR0cmlidXRlKCdjbGFzcycsICdCcm93c2VyVGFibGUtcm93Q29sdW1uIEJyb3dzZXJUYWJsZS1jb2x1bW4nKSwgX2FwcGVuZENoaWxkKF9icm93c2VyVGFibGVSb3dDb2x1bW4sIFsnICcsIHByb3BzLmdldEl0ZW1JY29uKCksICcgJywgcHJvcHMudmFsdWUsICcgJ10pLCBfYnJvd3NlclRhYmxlUm93Q29sdW1uO1xufTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPVRhYmxlQ29sdW1uLmpzLm1hcCIsIid1c2Ugc3RyaWN0JztcblxudmFyIF9hcHBlbmRDaGlsZCA9IHJlcXVpcmUoJ3lvLXlvaWZ5L2xpYi9hcHBlbmRDaGlsZCcpO1xuXG52YXIgQ29sdW1uID0gcmVxdWlyZSgnLi9UYWJsZUNvbHVtbicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChwcm9wcykge1xuICB2YXIgX3RyO1xuXG4gIHZhciBjbGFzc2VzID0gcHJvcHMuYWN0aXZlID8gJ0Jyb3dzZXJUYWJsZS1yb3cgaXMtYWN0aXZlJyA6ICdCcm93c2VyVGFibGUtcm93JztcbiAgcmV0dXJuIF90ciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3RyJyksIF90ci5vbmNsaWNrID0gcHJvcHMuaGFuZGxlQ2xpY2ssIF90ci5vbmRibGNsaWNrID0gcHJvcHMuaGFuZGxlRG91YmxlQ2xpY2ssIF90ci5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJycgKyBTdHJpbmcoY2xhc3NlcykgKyAnJyksIF9hcHBlbmRDaGlsZChfdHIsIFsnICcsIENvbHVtbih7XG4gICAgZ2V0SXRlbUljb246IHByb3BzLmdldEl0ZW1JY29uLFxuICAgIHZhbHVlOiBwcm9wcy50aXRsZVxuICB9KSwgJyAnXSksIF90cjtcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1UYWJsZVJvdy5qcy5tYXAiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfZXh0ZW5kcyA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gKHRhcmdldCkgeyBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgeyB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldOyBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7IGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoc291cmNlLCBrZXkpKSB7IHRhcmdldFtrZXldID0gc291cmNlW2tleV07IH0gfSB9IHJldHVybiB0YXJnZXQ7IH07XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbnZhciBBdXRoVmlldyA9IHJlcXVpcmUoJy4vQXV0aFZpZXcnKTtcbnZhciBCcm93c2VyID0gcmVxdWlyZSgnLi9Ccm93c2VyJyk7XG52YXIgRXJyb3JWaWV3ID0gcmVxdWlyZSgnLi9FcnJvcicpO1xudmFyIExvYWRlclZpZXcgPSByZXF1aXJlKCcuL0xvYWRlcicpO1xudmFyIFV0aWxzID0gcmVxdWlyZSgnLi4vY29yZS9VdGlscycpO1xuXG4vKipcbiAqIENsYXNzIHRvIGVhc2lseSBnZW5lcmF0ZSBnZW5lcmljIHZpZXdzIGZvciBwbHVnaW5zXG4gKlxuICogVGhpcyBjbGFzcyBleHBlY3RzIHRoZSBwbHVnaW4gdXNpbmcgdG8gaGF2ZSB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXNcbiAqXG4gKiBzdGF0ZUlkIHtTdHJpbmd9IG9iamVjdCBrZXkgb2Ygd2hpY2ggdGhlIHBsdWdpbiBzdGF0ZSBpcyBzdG9yZWRcbiAqXG4gKiBUaGlzIGNsYXNzIGFsc28gZXhwZWN0cyB0aGUgcGx1Z2luIGluc3RhbmNlIHVzaW5nIGl0IHRvIGhhdmUgdGhlIGZvbGxvd2luZ1xuICogYWNjZXNzb3IgbWV0aG9kcy5cbiAqIEVhY2ggbWV0aG9kIHRha2VzIHRoZSBpdGVtIHdob3NlIHByb3BlcnR5IGlzIHRvIGJlIGFjY2Vzc2VkXG4gKiBhcyBhIHBhcmFtXG4gKlxuICogaXNGb2xkZXJcbiAqICAgIEByZXR1cm4ge0Jvb2xlYW59IGZvciBpZiB0aGUgaXRlbSBpcyBhIGZvbGRlciBvciBub3RcbiAqIGdldEl0ZW1EYXRhXG4gKiAgICBAcmV0dXJuIHtPYmplY3R9IHRoYXQgaXMgZm9ybWF0IHJlYWR5IGZvciB1cHB5IHVwbG9hZC9kb3dubG9hZFxuICogZ2V0SXRlbUljb25cbiAqICAgIEByZXR1cm4ge09iamVjdH0gaHRtbCBpbnN0YW5jZSBvZiB0aGUgaXRlbSdzIGljb25cbiAqIGdldEl0ZW1TdWJMaXN0XG4gKiAgICBAcmV0dXJuIHtBcnJheX0gc3ViLWl0ZW1zIGluIHRoZSBpdGVtLiBlLmcgYSBmb2xkZXIgbWF5IGNvbnRhaW4gc3ViLWl0ZW1zXG4gKiBnZXRJdGVtTmFtZVxuICogICAgQHJldHVybiB7U3RyaW5nfSBkaXNwbGF5IGZyaWVuZGx5IG5hbWUgb2YgdGhlIGl0ZW1cbiAqIGdldE1pbWVUeXBlXG4gKiAgICBAcmV0dXJuIHtTdHJpbmd9IG1pbWUgdHlwZSBvZiB0aGUgaXRlbVxuICogZ2V0SXRlbUlkXG4gKiAgICBAcmV0dXJuIHtTdHJpbmd9IHVuaXF1ZSBpZCBvZiB0aGUgaXRlbVxuICogZ2V0SXRlbVJlcXVlc3RQYXRoXG4gKiAgICBAcmV0dXJuIHtTdHJpbmd9IHVuaXF1ZSByZXF1ZXN0IHBhdGggb2YgdGhlIGl0ZW0gd2hlbiBtYWtpbmcgY2FsbHMgdG8gdXBweSBzZXJ2ZXJcbiAqIGdldEl0ZW1Nb2RpZmllZERhdGVcbiAqICAgIEByZXR1cm4ge29iamVjdH0gb3Ige1N0cmluZ30gZGF0ZSBvZiB3aGVuIGxhc3QgdGhlIGl0ZW0gd2FzIG1vZGlmaWVkXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuICAvKipcbiAgICogQHBhcmFtIHtvYmplY3R9IGluc3RhbmNlIG9mIHRoZSBwbHVnaW5cbiAgICovXG4gIGZ1bmN0aW9uIFZpZXcocGx1Z2luKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFZpZXcpO1xuXG4gICAgdGhpcy5wbHVnaW4gPSBwbHVnaW47XG4gICAgdGhpcy5Qcm92aWRlciA9IHBsdWdpbltwbHVnaW4uaWRdO1xuXG4gICAgLy8gTG9naWNcbiAgICB0aGlzLmFkZEZpbGUgPSB0aGlzLmFkZEZpbGUuYmluZCh0aGlzKTtcbiAgICB0aGlzLmZpbHRlckl0ZW1zID0gdGhpcy5maWx0ZXJJdGVtcy5iaW5kKHRoaXMpO1xuICAgIHRoaXMuZmlsdGVyUXVlcnkgPSB0aGlzLmZpbHRlclF1ZXJ5LmJpbmQodGhpcyk7XG4gICAgdGhpcy5nZXRGb2xkZXIgPSB0aGlzLmdldEZvbGRlci5iaW5kKHRoaXMpO1xuICAgIHRoaXMuZ2V0TmV4dEZvbGRlciA9IHRoaXMuZ2V0TmV4dEZvbGRlci5iaW5kKHRoaXMpO1xuICAgIHRoaXMuaGFuZGxlUm93Q2xpY2sgPSB0aGlzLmhhbmRsZVJvd0NsaWNrLmJpbmQodGhpcyk7XG4gICAgdGhpcy5sb2dvdXQgPSB0aGlzLmxvZ291dC5iaW5kKHRoaXMpO1xuICAgIHRoaXMuaGFuZGxlQXV0aCA9IHRoaXMuaGFuZGxlQXV0aC5iaW5kKHRoaXMpO1xuICAgIHRoaXMuaGFuZGxlRGVtb0F1dGggPSB0aGlzLmhhbmRsZURlbW9BdXRoLmJpbmQodGhpcyk7XG4gICAgdGhpcy5zb3J0QnlUaXRsZSA9IHRoaXMuc29ydEJ5VGl0bGUuYmluZCh0aGlzKTtcbiAgICB0aGlzLnNvcnRCeURhdGUgPSB0aGlzLnNvcnRCeURhdGUuYmluZCh0aGlzKTtcbiAgICB0aGlzLmlzQWN0aXZlUm93ID0gdGhpcy5pc0FjdGl2ZVJvdy5iaW5kKHRoaXMpO1xuICAgIHRoaXMuaGFuZGxlRXJyb3IgPSB0aGlzLmhhbmRsZUVycm9yLmJpbmQodGhpcyk7XG5cbiAgICAvLyBWaXN1YWxcbiAgICB0aGlzLnJlbmRlciA9IHRoaXMucmVuZGVyLmJpbmQodGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogTGl0dGxlIHNob3J0aGFuZCB0byB1cGRhdGUgdGhlIHN0YXRlIHdpdGggdGhlIHBsdWdpbidzIHN0YXRlXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUudXBkYXRlU3RhdGUgPSBmdW5jdGlvbiB1cGRhdGVTdGF0ZShuZXdTdGF0ZSkge1xuICAgIHZhciBfcGx1Z2luJGNvcmUkc2V0U3RhdGU7XG5cbiAgICB2YXIgc3RhdGVJZCA9IHRoaXMucGx1Z2luLnN0YXRlSWQ7XG4gICAgdmFyIHN0YXRlID0gdGhpcy5wbHVnaW4uY29yZS5zdGF0ZTtcblxuXG4gICAgdGhpcy5wbHVnaW4uY29yZS5zZXRTdGF0ZSgoX3BsdWdpbiRjb3JlJHNldFN0YXRlID0ge30sIF9wbHVnaW4kY29yZSRzZXRTdGF0ZVtzdGF0ZUlkXSA9IF9leHRlbmRzKHt9LCBzdGF0ZVtzdGF0ZUlkXSwgbmV3U3RhdGUpLCBfcGx1Z2luJGNvcmUkc2V0U3RhdGUpKTtcbiAgfTtcblxuICAvKipcbiAgICogQmFzZWQgb24gZm9sZGVyIElELCBmZXRjaCBhIG5ldyBmb2xkZXIgYW5kIHVwZGF0ZSBpdCB0byBzdGF0ZVxuICAgKiBAcGFyYW0gIHtTdHJpbmd9IGlkIEZvbGRlciBpZFxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSAgIEZvbGRlcnMvZmlsZXMgaW4gZm9sZGVyXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuZ2V0Rm9sZGVyID0gZnVuY3Rpb24gZ2V0Rm9sZGVyKGlkLCBuYW1lKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgIHJldHVybiB0aGlzLl9sb2FkZXJXcmFwcGVyKHRoaXMuUHJvdmlkZXIubGlzdChpZCksIGZ1bmN0aW9uIChyZXMpIHtcbiAgICAgIHZhciBmb2xkZXJzID0gW107XG4gICAgICB2YXIgZmlsZXMgPSBbXTtcbiAgICAgIHZhciB1cGRhdGVkRGlyZWN0b3JpZXMgPSB2b2lkIDA7XG5cbiAgICAgIHZhciBzdGF0ZSA9IF90aGlzLnBsdWdpbi5jb3JlLmdldFN0YXRlKClbX3RoaXMucGx1Z2luLnN0YXRlSWRdO1xuICAgICAgdmFyIGluZGV4ID0gc3RhdGUuZGlyZWN0b3JpZXMuZmluZEluZGV4KGZ1bmN0aW9uIChkaXIpIHtcbiAgICAgICAgcmV0dXJuIGlkID09PSBkaXIuaWQ7XG4gICAgICB9KTtcblxuICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICB1cGRhdGVkRGlyZWN0b3JpZXMgPSBzdGF0ZS5kaXJlY3Rvcmllcy5zbGljZSgwLCBpbmRleCArIDEpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXBkYXRlZERpcmVjdG9yaWVzID0gc3RhdGUuZGlyZWN0b3JpZXMuY29uY2F0KFt7IGlkOiBpZCwgdGl0bGU6IG5hbWUgfHwgX3RoaXMucGx1Z2luLmdldEl0ZW1OYW1lKHJlcykgfV0pO1xuICAgICAgfVxuXG4gICAgICBfdGhpcy5wbHVnaW4uZ2V0SXRlbVN1Ykxpc3QocmVzKS5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICAgIGlmIChfdGhpcy5wbHVnaW4uaXNGb2xkZXIoaXRlbSkpIHtcbiAgICAgICAgICBmb2xkZXJzLnB1c2goaXRlbSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZmlsZXMucHVzaChpdGVtKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHZhciBkYXRhID0geyBmb2xkZXJzOiBmb2xkZXJzLCBmaWxlczogZmlsZXMsIGRpcmVjdG9yaWVzOiB1cGRhdGVkRGlyZWN0b3JpZXMgfTtcbiAgICAgIF90aGlzLnVwZGF0ZVN0YXRlKGRhdGEpO1xuXG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9LCB0aGlzLmhhbmRsZUVycm9yKTtcbiAgfTtcblxuICAvKipcbiAgICogRmV0Y2hlcyBuZXcgZm9sZGVyXG4gICAqIEBwYXJhbSAge09iamVjdH0gRm9sZGVyXG4gICAqIEBwYXJhbSAge1N0cmluZ30gdGl0bGUgRm9sZGVyIHRpdGxlXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuZ2V0TmV4dEZvbGRlciA9IGZ1bmN0aW9uIGdldE5leHRGb2xkZXIoZm9sZGVyKSB7XG4gICAgdmFyIGlkID0gdGhpcy5wbHVnaW4uZ2V0SXRlbVJlcXVlc3RQYXRoKGZvbGRlcik7XG4gICAgdGhpcy5nZXRGb2xkZXIoaWQsIHRoaXMucGx1Z2luLmdldEl0ZW1OYW1lKGZvbGRlcikpO1xuICB9O1xuXG4gIFZpZXcucHJvdG90eXBlLmFkZEZpbGUgPSBmdW5jdGlvbiBhZGRGaWxlKGZpbGUpIHtcbiAgICB2YXIgdGFnRmlsZSA9IHtcbiAgICAgIHNvdXJjZTogdGhpcy5wbHVnaW4uaWQsXG4gICAgICBkYXRhOiB0aGlzLnBsdWdpbi5nZXRJdGVtRGF0YShmaWxlKSxcbiAgICAgIG5hbWU6IHRoaXMucGx1Z2luLmdldEl0ZW1OYW1lKGZpbGUpLFxuICAgICAgdHlwZTogdGhpcy5wbHVnaW4uZ2V0TWltZVR5cGUoZmlsZSksXG4gICAgICBpc1JlbW90ZTogdHJ1ZSxcbiAgICAgIGJvZHk6IHtcbiAgICAgICAgZmlsZUlkOiB0aGlzLnBsdWdpbi5nZXRJdGVtSWQoZmlsZSlcbiAgICAgIH0sXG4gICAgICByZW1vdGU6IHtcbiAgICAgICAgaG9zdDogdGhpcy5wbHVnaW4ub3B0cy5ob3N0LFxuICAgICAgICB1cmw6IHRoaXMucGx1Z2luLm9wdHMuaG9zdCArICcvJyArIHRoaXMuUHJvdmlkZXIuaWQgKyAnL2dldC8nICsgdGhpcy5wbHVnaW4uZ2V0SXRlbVJlcXVlc3RQYXRoKGZpbGUpLFxuICAgICAgICBib2R5OiB7XG4gICAgICAgICAgZmlsZUlkOiB0aGlzLnBsdWdpbi5nZXRJdGVtSWQoZmlsZSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAoVXRpbHMuZ2V0RmlsZVR5cGUodGFnRmlsZSlbMF0gPT09ICdpbWFnZScpIHtcbiAgICAgIHRhZ0ZpbGUucHJldmlldyA9IHRoaXMucGx1Z2luLm9wdHMuaG9zdCArICcvJyArIHRoaXMuUHJvdmlkZXIuaWQgKyAnL3RodW1ibmFpbC8nICsgdGhpcy5wbHVnaW4uZ2V0SXRlbVJlcXVlc3RQYXRoKGZpbGUpO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZygnYWRkaW5nIGZpbGUnKTtcbiAgICB0aGlzLnBsdWdpbi5jb3JlLmVtaXR0ZXIuZW1pdCgnY29yZTpmaWxlLWFkZCcsIHRhZ0ZpbGUpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBSZW1vdmVzIHNlc3Npb24gdG9rZW4gb24gY2xpZW50IHNpZGUuXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUubG9nb3V0ID0gZnVuY3Rpb24gbG9nb3V0KCkge1xuICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgdGhpcy5Qcm92aWRlci5sb2dvdXQobG9jYXRpb24uaHJlZikudGhlbihmdW5jdGlvbiAocmVzKSB7XG4gICAgICByZXR1cm4gcmVzLmpzb24oKTtcbiAgICB9KS50aGVuKGZ1bmN0aW9uIChyZXMpIHtcbiAgICAgIGlmIChyZXMub2spIHtcbiAgICAgICAgdmFyIG5ld1N0YXRlID0ge1xuICAgICAgICAgIGF1dGhlbnRpY2F0ZWQ6IGZhbHNlLFxuICAgICAgICAgIGZpbGVzOiBbXSxcbiAgICAgICAgICBmb2xkZXJzOiBbXSxcbiAgICAgICAgICBkaXJlY3RvcmllczogW11cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMyLnVwZGF0ZVN0YXRlKG5ld1N0YXRlKTtcbiAgICAgIH1cbiAgICB9KS5jYXRjaCh0aGlzLmhhbmRsZUVycm9yKTtcbiAgfTtcblxuICAvKipcbiAgICogVXNlZCB0byBzZXQgYWN0aXZlIGZpbGUvZm9sZGVyLlxuICAgKiBAcGFyYW0gIHtPYmplY3R9IGZpbGUgICBBY3RpdmUgZmlsZS9mb2xkZXJcbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5oYW5kbGVSb3dDbGljayA9IGZ1bmN0aW9uIGhhbmRsZVJvd0NsaWNrKGZpbGUpIHtcbiAgICB2YXIgc3RhdGUgPSB0aGlzLnBsdWdpbi5jb3JlLmdldFN0YXRlKClbdGhpcy5wbHVnaW4uc3RhdGVJZF07XG4gICAgdmFyIG5ld1N0YXRlID0gX2V4dGVuZHMoe30sIHN0YXRlLCB7XG4gICAgICBhY3RpdmVSb3c6IHRoaXMucGx1Z2luLmdldEl0ZW1JZChmaWxlKVxuICAgIH0pO1xuXG4gICAgdGhpcy51cGRhdGVTdGF0ZShuZXdTdGF0ZSk7XG4gIH07XG5cbiAgVmlldy5wcm90b3R5cGUuZmlsdGVyUXVlcnkgPSBmdW5jdGlvbiBmaWx0ZXJRdWVyeShlKSB7XG4gICAgdmFyIHN0YXRlID0gdGhpcy5wbHVnaW4uY29yZS5nZXRTdGF0ZSgpW3RoaXMucGx1Z2luLnN0YXRlSWRdO1xuICAgIHRoaXMudXBkYXRlU3RhdGUoX2V4dGVuZHMoe30sIHN0YXRlLCB7XG4gICAgICBmaWx0ZXJJbnB1dDogZS50YXJnZXQudmFsdWVcbiAgICB9KSk7XG4gIH07XG5cbiAgVmlldy5wcm90b3R5cGUuZmlsdGVySXRlbXMgPSBmdW5jdGlvbiBmaWx0ZXJJdGVtcyhpdGVtcykge1xuICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgdmFyIHN0YXRlID0gdGhpcy5wbHVnaW4uY29yZS5nZXRTdGF0ZSgpW3RoaXMucGx1Z2luLnN0YXRlSWRdO1xuICAgIHJldHVybiBpdGVtcy5maWx0ZXIoZnVuY3Rpb24gKGZvbGRlcikge1xuICAgICAgcmV0dXJuIF90aGlzMy5wbHVnaW4uZ2V0SXRlbU5hbWUoZm9sZGVyKS50b0xvd2VyQ2FzZSgpLmluZGV4T2Yoc3RhdGUuZmlsdGVySW5wdXQudG9Mb3dlckNhc2UoKSkgIT09IC0xO1xuICAgIH0pO1xuICB9O1xuXG4gIFZpZXcucHJvdG90eXBlLnNvcnRCeVRpdGxlID0gZnVuY3Rpb24gc29ydEJ5VGl0bGUoKSB7XG4gICAgdmFyIF90aGlzNCA9IHRoaXM7XG5cbiAgICB2YXIgc3RhdGUgPSBfZXh0ZW5kcyh7fSwgdGhpcy5wbHVnaW4uY29yZS5nZXRTdGF0ZSgpW3RoaXMucGx1Z2luLnN0YXRlSWRdKTtcbiAgICB2YXIgZmlsZXMgPSBzdGF0ZS5maWxlcyxcbiAgICAgICAgZm9sZGVycyA9IHN0YXRlLmZvbGRlcnMsXG4gICAgICAgIHNvcnRpbmcgPSBzdGF0ZS5zb3J0aW5nO1xuXG5cbiAgICB2YXIgc29ydGVkRmlsZXMgPSBmaWxlcy5zb3J0KGZ1bmN0aW9uIChmaWxlQSwgZmlsZUIpIHtcbiAgICAgIGlmIChzb3J0aW5nID09PSAndGl0bGVEZXNjZW5kaW5nJykge1xuICAgICAgICByZXR1cm4gX3RoaXM0LnBsdWdpbi5nZXRJdGVtTmFtZShmaWxlQikubG9jYWxlQ29tcGFyZShfdGhpczQucGx1Z2luLmdldEl0ZW1OYW1lKGZpbGVBKSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gX3RoaXM0LnBsdWdpbi5nZXRJdGVtTmFtZShmaWxlQSkubG9jYWxlQ29tcGFyZShfdGhpczQucGx1Z2luLmdldEl0ZW1OYW1lKGZpbGVCKSk7XG4gICAgfSk7XG5cbiAgICB2YXIgc29ydGVkRm9sZGVycyA9IGZvbGRlcnMuc29ydChmdW5jdGlvbiAoZm9sZGVyQSwgZm9sZGVyQikge1xuICAgICAgaWYgKHNvcnRpbmcgPT09ICd0aXRsZURlc2NlbmRpbmcnKSB7XG4gICAgICAgIHJldHVybiBfdGhpczQucGx1Z2luLmdldEl0ZW1OYW1lKGZvbGRlckIpLmxvY2FsZUNvbXBhcmUoX3RoaXM0LnBsdWdpbi5nZXRJdGVtTmFtZShmb2xkZXJBKSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gX3RoaXM0LnBsdWdpbi5nZXRJdGVtTmFtZShmb2xkZXJBKS5sb2NhbGVDb21wYXJlKF90aGlzNC5wbHVnaW4uZ2V0SXRlbU5hbWUoZm9sZGVyQikpO1xuICAgIH0pO1xuXG4gICAgdGhpcy51cGRhdGVTdGF0ZShfZXh0ZW5kcyh7fSwgc3RhdGUsIHtcbiAgICAgIGZpbGVzOiBzb3J0ZWRGaWxlcyxcbiAgICAgIGZvbGRlcnM6IHNvcnRlZEZvbGRlcnMsXG4gICAgICBzb3J0aW5nOiBzb3J0aW5nID09PSAndGl0bGVEZXNjZW5kaW5nJyA/ICd0aXRsZUFzY2VuZGluZycgOiAndGl0bGVEZXNjZW5kaW5nJ1xuICAgIH0pKTtcbiAgfTtcblxuICBWaWV3LnByb3RvdHlwZS5zb3J0QnlEYXRlID0gZnVuY3Rpb24gc29ydEJ5RGF0ZSgpIHtcbiAgICB2YXIgX3RoaXM1ID0gdGhpcztcblxuICAgIHZhciBzdGF0ZSA9IF9leHRlbmRzKHt9LCB0aGlzLnBsdWdpbi5jb3JlLmdldFN0YXRlKClbdGhpcy5wbHVnaW4uc3RhdGVJZF0pO1xuICAgIHZhciBmaWxlcyA9IHN0YXRlLmZpbGVzLFxuICAgICAgICBmb2xkZXJzID0gc3RhdGUuZm9sZGVycyxcbiAgICAgICAgc29ydGluZyA9IHN0YXRlLnNvcnRpbmc7XG5cblxuICAgIHZhciBzb3J0ZWRGaWxlcyA9IGZpbGVzLnNvcnQoZnVuY3Rpb24gKGZpbGVBLCBmaWxlQikge1xuICAgICAgdmFyIGEgPSBuZXcgRGF0ZShfdGhpczUucGx1Z2luLmdldEl0ZW1Nb2RpZmllZERhdGUoZmlsZUEpKTtcbiAgICAgIHZhciBiID0gbmV3IERhdGUoX3RoaXM1LnBsdWdpbi5nZXRJdGVtTW9kaWZpZWREYXRlKGZpbGVCKSk7XG5cbiAgICAgIGlmIChzb3J0aW5nID09PSAnZGF0ZURlc2NlbmRpbmcnKSB7XG4gICAgICAgIHJldHVybiBhID4gYiA/IC0xIDogYSA8IGIgPyAxIDogMDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhID4gYiA/IDEgOiBhIDwgYiA/IC0xIDogMDtcbiAgICB9KTtcblxuICAgIHZhciBzb3J0ZWRGb2xkZXJzID0gZm9sZGVycy5zb3J0KGZ1bmN0aW9uIChmb2xkZXJBLCBmb2xkZXJCKSB7XG4gICAgICB2YXIgYSA9IG5ldyBEYXRlKF90aGlzNS5wbHVnaW4uZ2V0SXRlbU1vZGlmaWVkRGF0ZShmb2xkZXJBKSk7XG4gICAgICB2YXIgYiA9IG5ldyBEYXRlKF90aGlzNS5wbHVnaW4uZ2V0SXRlbU1vZGlmaWVkRGF0ZShmb2xkZXJCKSk7XG5cbiAgICAgIGlmIChzb3J0aW5nID09PSAnZGF0ZURlc2NlbmRpbmcnKSB7XG4gICAgICAgIHJldHVybiBhID4gYiA/IC0xIDogYSA8IGIgPyAxIDogMDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IGEgPCBiID8gLTEgOiAwO1xuICAgIH0pO1xuXG4gICAgdGhpcy51cGRhdGVTdGF0ZShfZXh0ZW5kcyh7fSwgc3RhdGUsIHtcbiAgICAgIGZpbGVzOiBzb3J0ZWRGaWxlcyxcbiAgICAgIGZvbGRlcnM6IHNvcnRlZEZvbGRlcnMsXG4gICAgICBzb3J0aW5nOiBzb3J0aW5nID09PSAnZGF0ZURlc2NlbmRpbmcnID8gJ2RhdGVBc2NlbmRpbmcnIDogJ2RhdGVEZXNjZW5kaW5nJ1xuICAgIH0pKTtcbiAgfTtcblxuICBWaWV3LnByb3RvdHlwZS5pc0FjdGl2ZVJvdyA9IGZ1bmN0aW9uIGlzQWN0aXZlUm93KGZpbGUpIHtcbiAgICByZXR1cm4gdGhpcy5wbHVnaW4uY29yZS5nZXRTdGF0ZSgpW3RoaXMucGx1Z2luLnN0YXRlSWRdLmFjdGl2ZVJvdyA9PT0gdGhpcy5wbHVnaW4uZ2V0SXRlbUlkKGZpbGUpO1xuICB9O1xuXG4gIFZpZXcucHJvdG90eXBlLmhhbmRsZURlbW9BdXRoID0gZnVuY3Rpb24gaGFuZGxlRGVtb0F1dGgoKSB7XG4gICAgdmFyIHN0YXRlID0gdGhpcy5wbHVnaW4uY29yZS5nZXRTdGF0ZSgpW3RoaXMucGx1Z2luLnN0YXRlSWRdO1xuICAgIHRoaXMudXBkYXRlU3RhdGUoe30sIHN0YXRlLCB7XG4gICAgICBhdXRoZW50aWNhdGVkOiB0cnVlXG4gICAgfSk7XG4gIH07XG5cbiAgVmlldy5wcm90b3R5cGUuaGFuZGxlQXV0aCA9IGZ1bmN0aW9uIGhhbmRsZUF1dGgoKSB7XG4gICAgdmFyIF90aGlzNiA9IHRoaXM7XG5cbiAgICB2YXIgdXJsSWQgPSBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiA5OTk5OTkpICsgMTtcbiAgICB2YXIgcmVkaXJlY3QgPSAnJyArIGxvY2F0aW9uLmhyZWYgKyAobG9jYXRpb24uc2VhcmNoID8gJyYnIDogJz8nKSArICdpZD0nICsgdXJsSWQ7XG5cbiAgICB2YXIgYXV0aFN0YXRlID0gYnRvYShKU09OLnN0cmluZ2lmeSh7IHJlZGlyZWN0OiByZWRpcmVjdCB9KSk7XG4gICAgdmFyIGxpbmsgPSB0aGlzLnBsdWdpbi5vcHRzLmhvc3QgKyAnL2Nvbm5lY3QvJyArIHRoaXMuUHJvdmlkZXIuYXV0aFByb3ZpZGVyICsgJz9zdGF0ZT0nICsgYXV0aFN0YXRlO1xuXG4gICAgdmFyIGF1dGhXaW5kb3cgPSB3aW5kb3cub3BlbihsaW5rLCAnX2JsYW5rJyk7XG4gICAgdmFyIGNoZWNrQXV0aCA9IGZ1bmN0aW9uIGNoZWNrQXV0aCgpIHtcbiAgICAgIHZhciBhdXRoV2luZG93VXJsID0gdm9pZCAwO1xuXG4gICAgICB0cnkge1xuICAgICAgICBhdXRoV2luZG93VXJsID0gYXV0aFdpbmRvdy5sb2NhdGlvbi5ocmVmO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIERPTUV4Y2VwdGlvbiB8fCBlIGluc3RhbmNlb2YgVHlwZUVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoY2hlY2tBdXRoLCAxMDApO1xuICAgICAgICB9IGVsc2UgdGhyb3cgZTtcbiAgICAgIH1cblxuICAgICAgLy8gc3BsaXQgdXJsIGJlY2F1c2UgY2hyb21lIGFkZHMgJyMnIHRvIHJlZGlyZWN0c1xuICAgICAgaWYgKGF1dGhXaW5kb3dVcmwuc3BsaXQoJyMnKVswXSA9PT0gcmVkaXJlY3QpIHtcbiAgICAgICAgYXV0aFdpbmRvdy5jbG9zZSgpO1xuICAgICAgICBfdGhpczYuX2xvYWRlcldyYXBwZXIoX3RoaXM2LlByb3ZpZGVyLmF1dGgoKSwgX3RoaXM2LnBsdWdpbi5vbkF1dGgsIF90aGlzNi5oYW5kbGVFcnJvcik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZXRUaW1lb3V0KGNoZWNrQXV0aCwgMTAwKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY2hlY2tBdXRoKCk7XG4gIH07XG5cbiAgVmlldy5wcm90b3R5cGUuaGFuZGxlRXJyb3IgPSBmdW5jdGlvbiBoYW5kbGVFcnJvcihlcnJvcikge1xuICAgIHRoaXMudXBkYXRlU3RhdGUoeyBlcnJvcjogZXJyb3IgfSk7XG4gIH07XG5cbiAgLy8gZGlzcGxheXMgbG9hZGVyIHZpZXcgd2hpbGUgYXN5bmNocm9ub3VzIHJlcXVlc3QgaXMgYmVpbmcgbWFkZS5cblxuXG4gIFZpZXcucHJvdG90eXBlLl9sb2FkZXJXcmFwcGVyID0gZnVuY3Rpb24gX2xvYWRlcldyYXBwZXIocHJvbWlzZSwgdGhlbiwgY2F0Y2hfKSB7XG4gICAgdmFyIF90aGlzNyA9IHRoaXM7XG5cbiAgICBwcm9taXNlLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgX3RoaXM3LnVwZGF0ZVN0YXRlKHsgbG9hZGluZzogZmFsc2UgfSk7XG4gICAgICB0aGVuKHJlc3VsdCk7XG4gICAgfSkuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgICAgX3RoaXM3LnVwZGF0ZVN0YXRlKHsgbG9hZGluZzogZmFsc2UgfSk7XG4gICAgICBjYXRjaF8oZXJyKTtcbiAgICB9KTtcbiAgICB0aGlzLnVwZGF0ZVN0YXRlKHsgbG9hZGluZzogdHJ1ZSB9KTtcbiAgfTtcblxuICBWaWV3LnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiByZW5kZXIoc3RhdGUpIHtcbiAgICB2YXIgX3N0YXRlJHBsdWdpbiRzdGF0ZUlkID0gc3RhdGVbdGhpcy5wbHVnaW4uc3RhdGVJZF0sXG4gICAgICAgIGF1dGhlbnRpY2F0ZWQgPSBfc3RhdGUkcGx1Z2luJHN0YXRlSWQuYXV0aGVudGljYXRlZCxcbiAgICAgICAgZXJyb3IgPSBfc3RhdGUkcGx1Z2luJHN0YXRlSWQuZXJyb3IsXG4gICAgICAgIGxvYWRpbmcgPSBfc3RhdGUkcGx1Z2luJHN0YXRlSWQubG9hZGluZztcblxuXG4gICAgaWYgKGVycm9yKSB7XG4gICAgICB0aGlzLnVwZGF0ZVN0YXRlKHsgZXJyb3I6IHVuZGVmaW5lZCB9KTtcbiAgICAgIHJldHVybiBFcnJvclZpZXcoeyBlcnJvcjogZXJyb3IgfSk7XG4gICAgfVxuXG4gICAgaWYgKGxvYWRpbmcpIHtcbiAgICAgIHJldHVybiBMb2FkZXJWaWV3KCk7XG4gICAgfVxuXG4gICAgaWYgKCFhdXRoZW50aWNhdGVkKSB7XG4gICAgICByZXR1cm4gQXV0aFZpZXcoe1xuICAgICAgICBwbHVnaW5OYW1lOiB0aGlzLnBsdWdpbi50aXRsZSxcbiAgICAgICAgZGVtbzogdGhpcy5wbHVnaW4ub3B0cy5kZW1vLFxuICAgICAgICBoYW5kbGVBdXRoOiB0aGlzLmhhbmRsZUF1dGgsXG4gICAgICAgIGhhbmRsZURlbW9BdXRoOiB0aGlzLmhhbmRsZURlbW9BdXRoXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgYnJvd3NlclByb3BzID0gX2V4dGVuZHMoe30sIHN0YXRlW3RoaXMucGx1Z2luLnN0YXRlSWRdLCB7XG4gICAgICBnZXROZXh0Rm9sZGVyOiB0aGlzLmdldE5leHRGb2xkZXIsXG4gICAgICBnZXRGb2xkZXI6IHRoaXMuZ2V0Rm9sZGVyLFxuICAgICAgYWRkRmlsZTogdGhpcy5hZGRGaWxlLFxuICAgICAgZmlsdGVySXRlbXM6IHRoaXMuZmlsdGVySXRlbXMsXG4gICAgICBmaWx0ZXJRdWVyeTogdGhpcy5maWx0ZXJRdWVyeSxcbiAgICAgIGhhbmRsZVJvd0NsaWNrOiB0aGlzLmhhbmRsZVJvd0NsaWNrLFxuICAgICAgc29ydEJ5VGl0bGU6IHRoaXMuc29ydEJ5VGl0bGUsXG4gICAgICBzb3J0QnlEYXRlOiB0aGlzLnNvcnRCeURhdGUsXG4gICAgICBsb2dvdXQ6IHRoaXMubG9nb3V0LFxuICAgICAgZGVtbzogdGhpcy5wbHVnaW4ub3B0cy5kZW1vLFxuICAgICAgaXNBY3RpdmVSb3c6IHRoaXMuaXNBY3RpdmVSb3csXG4gICAgICBnZXRJdGVtTmFtZTogdGhpcy5wbHVnaW4uZ2V0SXRlbU5hbWUsXG4gICAgICBnZXRJdGVtSWNvbjogdGhpcy5wbHVnaW4uZ2V0SXRlbUljb25cbiAgICB9KTtcblxuICAgIHJldHVybiBCcm93c2VyKGJyb3dzZXJQcm9wcyk7XG4gIH07XG5cbiAgcmV0dXJuIFZpZXc7XG59KCk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pbmRleC5qcy5tYXAiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfYXBwZW5kQ2hpbGQgPSByZXF1aXJlKCd5by15b2lmeS9saWIvYXBwZW5kQ2hpbGQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAocHJvcHMpIHtcbiAgdmFyIF91cHB5RGFzaGJvYXJkSW5wdXQsIF91cHB5RGFzaGJvYXJkQnJvd3NlLCBfc3BhbjtcblxuICB2YXIgaW5wdXQgPSAoX3VwcHlEYXNoYm9hcmRJbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0JyksIF91cHB5RGFzaGJvYXJkSW5wdXQuc2V0QXR0cmlidXRlKCd0eXBlJywgJ2ZpbGUnKSwgX3VwcHlEYXNoYm9hcmRJbnB1dC5zZXRBdHRyaWJ1dGUoJ25hbWUnLCAnZmlsZXNbXScpLCAndHJ1ZScgJiYgX3VwcHlEYXNoYm9hcmRJbnB1dC5zZXRBdHRyaWJ1dGUoJ211bHRpcGxlJywgJ211bHRpcGxlJyksIF91cHB5RGFzaGJvYXJkSW5wdXQub25jaGFuZ2UgPSBwcm9wcy5oYW5kbGVJbnB1dENoYW5nZSwgX3VwcHlEYXNoYm9hcmRJbnB1dC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmQtaW5wdXQnKSwgX3VwcHlEYXNoYm9hcmRJbnB1dCk7XG5cbiAgcmV0dXJuIF9zcGFuID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpLCBfYXBwZW5kQ2hpbGQoX3NwYW4sIFsnICcsIHByb3BzLmFjcXVpcmVycy5sZW5ndGggPT09IDAgPyBwcm9wcy5pMThuKCdkcm9wUGFzdGUnKSA6IHByb3BzLmkxOG4oJ2Ryb3BQYXN0ZUltcG9ydCcpLCAnICcsIChfdXBweURhc2hib2FyZEJyb3dzZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2J1dHRvbicpLCBfdXBweURhc2hib2FyZEJyb3dzZS5zZXRBdHRyaWJ1dGUoJ3R5cGUnLCAnYnV0dG9uJyksIF91cHB5RGFzaGJvYXJkQnJvd3NlLm9uY2xpY2sgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICBpbnB1dC5jbGljaygpO1xuICB9LCBfdXBweURhc2hib2FyZEJyb3dzZS5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmQtYnJvd3NlJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZEJyb3dzZSwgW3Byb3BzLmkxOG4oJ2Jyb3dzZScpXSksIF91cHB5RGFzaGJvYXJkQnJvd3NlKSwgJyAnLCBpbnB1dCwgJyAnXSksIF9zcGFuO1xufTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPUFjdGlvbkJyb3dzZVRhZ2xpbmUuanMubWFwIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgX2FwcGVuZENoaWxkID0gcmVxdWlyZSgneW8teW9pZnkvbGliL2FwcGVuZENoaWxkJyksXG4gICAgX29ubG9hZCA9IHJlcXVpcmUoJ29uLWxvYWQnKTtcblxudmFyIEZpbGVMaXN0ID0gcmVxdWlyZSgnLi9GaWxlTGlzdCcpO1xudmFyIFRhYnMgPSByZXF1aXJlKCcuL1RhYnMnKTtcbnZhciBGaWxlQ2FyZCA9IHJlcXVpcmUoJy4vRmlsZUNhcmQnKTtcbnZhciBVcGxvYWRCdG4gPSByZXF1aXJlKCcuL1VwbG9hZEJ0bicpO1xudmFyIFN0YXR1c0JhciA9IHJlcXVpcmUoJy4vU3RhdHVzQmFyJyk7XG5cbnZhciBfcmVxdWlyZSA9IHJlcXVpcmUoJy4uLy4uL2NvcmUvVXRpbHMnKSxcbiAgICBpc1RvdWNoRGV2aWNlID0gX3JlcXVpcmUuaXNUb3VjaERldmljZSxcbiAgICB0b0FycmF5ID0gX3JlcXVpcmUudG9BcnJheTtcblxudmFyIF9yZXF1aXJlMiA9IHJlcXVpcmUoJy4vaWNvbnMnKSxcbiAgICBjbG9zZUljb24gPSBfcmVxdWlyZTIuY2xvc2VJY29uO1xuXG4vLyBodHRwOi8vZGV2LmVkZW5zcGlla2VybWFubi5jb20vMjAxNi8wMi8xMS9pbnRyb2R1Y2luZy1hY2Nlc3NpYmxlLW1vZGFsLWRpYWxvZ1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIERhc2hib2FyZChwcm9wcykge1xuICB2YXIgX3VwcHlEYXNoYm9hcmRDbG9zZSwgX3VwcHlEYXNoYm9hcmRPdmVybGF5LCBfdXBweURhc2hib2FyZEFjdGlvbnMsIF91cHB5RGFzaGJvYXJkRmlsZXNDb250YWluZXIsIF91cHB5RGFzaGJvYXJkQ29udGVudFRpdGxlLCBfdXBweURhc2hib2FyZENvbnRlbnRCYWNrLCBfdXBweURhc2hib2FyZENvbnRlbnRCYXIsIF91cHB5RGFzaGJvYXJkQ29udGVudFBhbmVsLCBfdXBweURhc2hib2FyZFByb2dyZXNzaW5kaWNhdG9ycywgX3VwcHlEYXNoYm9hcmRJbm5lcldyYXAsIF91cHB5RGFzaGJvYXJkSW5uZXIsIF9kaXY7XG5cbiAgZnVuY3Rpb24gaGFuZGxlSW5wdXRDaGFuZ2UoZXYpIHtcbiAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHZhciBmaWxlcyA9IHRvQXJyYXkoZXYudGFyZ2V0LmZpbGVzKTtcblxuICAgIGZpbGVzLmZvckVhY2goZnVuY3Rpb24gKGZpbGUpIHtcbiAgICAgIHByb3BzLmFkZEZpbGUoe1xuICAgICAgICBzb3VyY2U6IHByb3BzLmlkLFxuICAgICAgICBuYW1lOiBmaWxlLm5hbWUsXG4gICAgICAgIHR5cGU6IGZpbGUudHlwZSxcbiAgICAgICAgZGF0YTogZmlsZVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvLyBAVE9ETyBFeHByaW1lbnRhbCwgd29yayBpbiBwcm9ncmVzc1xuICAvLyBubyBuYW1lcywgd2VpcmQgQVBJLCBDaHJvbWUtb25seSBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8yMjk0MDAyMFxuICBmdW5jdGlvbiBoYW5kbGVQYXN0ZShldikge1xuICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICB2YXIgZmlsZXMgPSB0b0FycmF5KGV2LmNsaXBib2FyZERhdGEuaXRlbXMpO1xuICAgIGZpbGVzLmZvckVhY2goZnVuY3Rpb24gKGZpbGUpIHtcbiAgICAgIGlmIChmaWxlLmtpbmQgIT09ICdmaWxlJykgcmV0dXJuO1xuXG4gICAgICB2YXIgYmxvYiA9IGZpbGUuZ2V0QXNGaWxlKCk7XG4gICAgICBwcm9wcy5sb2coJ0ZpbGUgcGFzdGVkJyk7XG4gICAgICBwcm9wcy5hZGRGaWxlKHtcbiAgICAgICAgc291cmNlOiBwcm9wcy5pZCxcbiAgICAgICAgbmFtZTogZmlsZS5uYW1lLFxuICAgICAgICB0eXBlOiBmaWxlLnR5cGUsXG4gICAgICAgIGRhdGE6IGJsb2JcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIF9kaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSwgX29ubG9hZChfZGl2LCBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHByb3BzLnVwZGF0ZURhc2hib2FyZEVsV2lkdGgoKTtcbiAgfSwgbnVsbCwgMSksIF9kaXYuc2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicsICcnICsgU3RyaW5nKHByb3BzLmlubGluZSA/ICdmYWxzZScgOiBwcm9wcy5tb2RhbC5pc0hpZGRlbikgKyAnJyksIF9kaXYuc2V0QXR0cmlidXRlKCdhcmlhLWxhYmVsJywgJycgKyBTdHJpbmcoIXByb3BzLmlubGluZSA/IHByb3BzLmkxOG4oJ2Rhc2hib2FyZFdpbmRvd1RpdGxlJykgOiBwcm9wcy5pMThuKCdkYXNoYm9hcmRUaXRsZScpKSArICcnKSwgX2Rpdi5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAnZGlhbG9nJyksIF9kaXYub25wYXN0ZSA9IGhhbmRsZVBhc3RlLCBfZGl2LnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweSBVcHB5VGhlbWUtLWRlZmF1bHQgVXBweURhc2hib2FyZFxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJyArIFN0cmluZyhpc1RvdWNoRGV2aWNlKCkgPyAnVXBweS0taXNUb3VjaERldmljZScgOiAnJykgKyAnXFxuICAgICAgICAgICAgICAgICAgICAgICAgICAnICsgU3RyaW5nKHByb3BzLnNlbWlUcmFuc3BhcmVudCA/ICdVcHB5RGFzaGJvYXJkLS1zZW1pVHJhbnNwYXJlbnQnIDogJycpICsgJ1xcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJyArIFN0cmluZyghcHJvcHMuaW5saW5lID8gJ1VwcHlEYXNoYm9hcmQtLW1vZGFsJyA6ICcnKSArICdcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICcgKyBTdHJpbmcocHJvcHMuaXNXaWRlID8gJ1VwcHlEYXNoYm9hcmQtLXdpZGUnIDogJycpICsgJycpLCBfYXBwZW5kQ2hpbGQoX2RpdiwgWycgJywgKF91cHB5RGFzaGJvYXJkQ2xvc2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdidXR0b24nKSwgX3VwcHlEYXNoYm9hcmRDbG9zZS5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCAnJyArIFN0cmluZyhwcm9wcy5pMThuKCdjbG9zZU1vZGFsJykpICsgJycpLCBfdXBweURhc2hib2FyZENsb3NlLnNldEF0dHJpYnV0ZSgndGl0bGUnLCAnJyArIFN0cmluZyhwcm9wcy5pMThuKCdjbG9zZU1vZGFsJykpICsgJycpLCBfdXBweURhc2hib2FyZENsb3NlLm9uY2xpY2sgPSBwcm9wcy5oaWRlTW9kYWwsIF91cHB5RGFzaGJvYXJkQ2xvc2Uuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkLWNsb3NlJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZENsb3NlLCBbY2xvc2VJY29uKCldKSwgX3VwcHlEYXNoYm9hcmRDbG9zZSksICcgJywgKF91cHB5RGFzaGJvYXJkT3ZlcmxheSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLCBfdXBweURhc2hib2FyZE92ZXJsYXkub25jbGljayA9IHByb3BzLmhpZGVNb2RhbCwgX3VwcHlEYXNoYm9hcmRPdmVybGF5LnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZC1vdmVybGF5JyksIF91cHB5RGFzaGJvYXJkT3ZlcmxheSksICcgJywgKF91cHB5RGFzaGJvYXJkSW5uZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSwgX3VwcHlEYXNoYm9hcmRJbm5lci5zZXRBdHRyaWJ1dGUoJ3RhYmluZGV4JywgJzAnKSwgX3VwcHlEYXNoYm9hcmRJbm5lci5zZXRBdHRyaWJ1dGUoJ3N0eWxlJywgJ1xcbiAgICAgICAgICAnICsgU3RyaW5nKHByb3BzLmlubGluZSAmJiBwcm9wcy5tYXhXaWR0aCA/ICdtYXgtd2lkdGg6ICcgKyBwcm9wcy5tYXhXaWR0aCArICdweDsnIDogJycpICsgJ1xcbiAgICAgICAgICAnICsgU3RyaW5nKHByb3BzLmlubGluZSAmJiBwcm9wcy5tYXhIZWlnaHQgPyAnbWF4LWhlaWdodDogJyArIHByb3BzLm1heEhlaWdodCArICdweDsnIDogJycpICsgJ1xcbiAgICAgICAgICcpLCBfdXBweURhc2hib2FyZElubmVyLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZC1pbm5lcicpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmRJbm5lciwgWycgJywgKF91cHB5RGFzaGJvYXJkSW5uZXJXcmFwID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksIF91cHB5RGFzaGJvYXJkSW5uZXJXcmFwLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZC1pbm5lcldyYXAnKSwgX2FwcGVuZENoaWxkKF91cHB5RGFzaGJvYXJkSW5uZXJXcmFwLCBbJyAnLCBUYWJzKHtcbiAgICBmaWxlczogcHJvcHMuZmlsZXMsXG4gICAgaGFuZGxlSW5wdXRDaGFuZ2U6IGhhbmRsZUlucHV0Q2hhbmdlLFxuICAgIGFjcXVpcmVyczogcHJvcHMuYWNxdWlyZXJzLFxuICAgIHBhbmVsU2VsZWN0b3JQcmVmaXg6IHByb3BzLnBhbmVsU2VsZWN0b3JQcmVmaXgsXG4gICAgc2hvd1BhbmVsOiBwcm9wcy5zaG93UGFuZWwsXG4gICAgaTE4bjogcHJvcHMuaTE4blxuICB9KSwgJyAnLCBGaWxlQ2FyZCh7XG4gICAgZmlsZXM6IHByb3BzLmZpbGVzLFxuICAgIGZpbGVDYXJkRm9yOiBwcm9wcy5maWxlQ2FyZEZvcixcbiAgICBkb25lOiBwcm9wcy5maWxlQ2FyZERvbmUsXG4gICAgbWV0YUZpZWxkczogcHJvcHMubWV0YUZpZWxkcyxcbiAgICBsb2c6IHByb3BzLmxvZyxcbiAgICBpMThuOiBwcm9wcy5pMThuXG4gIH0pLCAnICcsIChfdXBweURhc2hib2FyZEZpbGVzQ29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksIF91cHB5RGFzaGJvYXJkRmlsZXNDb250YWluZXIuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkLWZpbGVzQ29udGFpbmVyJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZEZpbGVzQ29udGFpbmVyLCBbJyAnLCBGaWxlTGlzdCh7XG4gICAgYWNxdWlyZXJzOiBwcm9wcy5hY3F1aXJlcnMsXG4gICAgZmlsZXM6IHByb3BzLmZpbGVzLFxuICAgIGhhbmRsZUlucHV0Q2hhbmdlOiBoYW5kbGVJbnB1dENoYW5nZSxcbiAgICBzaG93RmlsZUNhcmQ6IHByb3BzLnNob3dGaWxlQ2FyZCxcbiAgICBzaG93UHJvZ3Jlc3NEZXRhaWxzOiBwcm9wcy5zaG93UHJvZ3Jlc3NEZXRhaWxzLFxuICAgIHRvdGFsUHJvZ3Jlc3M6IHByb3BzLnRvdGFsUHJvZ3Jlc3MsXG4gICAgdG90YWxGaWxlQ291bnQ6IHByb3BzLnRvdGFsRmlsZUNvdW50LFxuICAgIGluZm86IHByb3BzLmluZm8sXG4gICAgaTE4bjogcHJvcHMuaTE4bixcbiAgICBsb2c6IHByb3BzLmxvZyxcbiAgICByZW1vdmVGaWxlOiBwcm9wcy5yZW1vdmVGaWxlLFxuICAgIHBhdXNlQWxsOiBwcm9wcy5wYXVzZUFsbCxcbiAgICByZXN1bWVBbGw6IHByb3BzLnJlc3VtZUFsbCxcbiAgICBwYXVzZVVwbG9hZDogcHJvcHMucGF1c2VVcGxvYWQsXG4gICAgc3RhcnRVcGxvYWQ6IHByb3BzLnN0YXJ0VXBsb2FkLFxuICAgIGNhbmNlbFVwbG9hZDogcHJvcHMuY2FuY2VsVXBsb2FkLFxuICAgIHJlc3VtYWJsZVVwbG9hZHM6IHByb3BzLnJlc3VtYWJsZVVwbG9hZHMsXG4gICAgaXNXaWRlOiBwcm9wcy5pc1dpZGVcbiAgfSksICcgJywgKF91cHB5RGFzaGJvYXJkQWN0aW9ucyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLCBfdXBweURhc2hib2FyZEFjdGlvbnMuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkLWFjdGlvbnMnKSwgX2FwcGVuZENoaWxkKF91cHB5RGFzaGJvYXJkQWN0aW9ucywgWycgJywgIXByb3BzLmF1dG9Qcm9jZWVkICYmIHByb3BzLm5ld0ZpbGVzLmxlbmd0aCA+IDAgPyBVcGxvYWRCdG4oe1xuICAgIGkxOG46IHByb3BzLmkxOG4sXG4gICAgc3RhcnRVcGxvYWQ6IHByb3BzLnN0YXJ0VXBsb2FkLFxuICAgIG5ld0ZpbGVDb3VudDogcHJvcHMubmV3RmlsZXMubGVuZ3RoXG4gIH0pIDogbnVsbCwgJyAnXSksIF91cHB5RGFzaGJvYXJkQWN0aW9ucyksICcgJ10pLCBfdXBweURhc2hib2FyZEZpbGVzQ29udGFpbmVyKSwgJyAnLCAoX3VwcHlEYXNoYm9hcmRDb250ZW50UGFuZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSwgX3VwcHlEYXNoYm9hcmRDb250ZW50UGFuZWwuc2V0QXR0cmlidXRlKCdyb2xlJywgJ3RhYnBhbmVsJyksIF91cHB5RGFzaGJvYXJkQ29udGVudFBhbmVsLnNldEF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nLCAnJyArIFN0cmluZyhwcm9wcy5hY3RpdmVQYW5lbCA/ICdmYWxzZScgOiAndHJ1ZScpICsgJycpLCBfdXBweURhc2hib2FyZENvbnRlbnRQYW5lbC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRDb250ZW50LXBhbmVsJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZENvbnRlbnRQYW5lbCwgWycgJywgKF91cHB5RGFzaGJvYXJkQ29udGVudEJhciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLCBfdXBweURhc2hib2FyZENvbnRlbnRCYXIuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkQ29udGVudC1iYXInKSwgX2FwcGVuZENoaWxkKF91cHB5RGFzaGJvYXJkQ29udGVudEJhciwgWycgJywgKF91cHB5RGFzaGJvYXJkQ29udGVudFRpdGxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaDInKSwgX3VwcHlEYXNoYm9hcmRDb250ZW50VGl0bGUuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkQ29udGVudC10aXRsZScpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmRDb250ZW50VGl0bGUsIFsnICcsIHByb3BzLmkxOG4oJ2ltcG9ydEZyb20nKSwgJyAnLCBwcm9wcy5hY3RpdmVQYW5lbCA/IHByb3BzLmFjdGl2ZVBhbmVsLm5hbWUgOiBudWxsLCAnICddKSwgX3VwcHlEYXNoYm9hcmRDb250ZW50VGl0bGUpLCAnICcsIChfdXBweURhc2hib2FyZENvbnRlbnRCYWNrID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnV0dG9uJyksIF91cHB5RGFzaGJvYXJkQ29udGVudEJhY2sub25jbGljayA9IHByb3BzLmhpZGVBbGxQYW5lbHMsIF91cHB5RGFzaGJvYXJkQ29udGVudEJhY2suc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkQ29udGVudC1iYWNrJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZENvbnRlbnRCYWNrLCBbcHJvcHMuaTE4bignZG9uZScpXSksIF91cHB5RGFzaGJvYXJkQ29udGVudEJhY2spLCAnICddKSwgX3VwcHlEYXNoYm9hcmRDb250ZW50QmFyKSwgJyAnLCBwcm9wcy5hY3RpdmVQYW5lbCA/IHByb3BzLmFjdGl2ZVBhbmVsLnJlbmRlcihwcm9wcy5zdGF0ZSkgOiAnJywgJyAnXSksIF91cHB5RGFzaGJvYXJkQ29udGVudFBhbmVsKSwgJyAnLCAoX3VwcHlEYXNoYm9hcmRQcm9ncmVzc2luZGljYXRvcnMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSwgX3VwcHlEYXNoYm9hcmRQcm9ncmVzc2luZGljYXRvcnMuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkLXByb2dyZXNzaW5kaWNhdG9ycycpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmRQcm9ncmVzc2luZGljYXRvcnMsIFsnICcsIFN0YXR1c0Jhcih7XG4gICAgdG90YWxQcm9ncmVzczogcHJvcHMudG90YWxQcm9ncmVzcyxcbiAgICB0b3RhbEZpbGVDb3VudDogcHJvcHMudG90YWxGaWxlQ291bnQsXG4gICAgdG90YWxTaXplOiBwcm9wcy50b3RhbFNpemUsXG4gICAgdG90YWxVcGxvYWRlZFNpemU6IHByb3BzLnRvdGFsVXBsb2FkZWRTaXplLFxuICAgIHVwbG9hZFN0YXJ0ZWRGaWxlczogcHJvcHMudXBsb2FkU3RhcnRlZEZpbGVzLFxuICAgIGlzQWxsQ29tcGxldGU6IHByb3BzLmlzQWxsQ29tcGxldGUsXG4gICAgaXNBbGxQYXVzZWQ6IHByb3BzLmlzQWxsUGF1c2VkLFxuICAgIGlzVXBsb2FkU3RhcnRlZDogcHJvcHMuaXNVcGxvYWRTdGFydGVkLFxuICAgIHBhdXNlQWxsOiBwcm9wcy5wYXVzZUFsbCxcbiAgICByZXN1bWVBbGw6IHByb3BzLnJlc3VtZUFsbCxcbiAgICBjYW5jZWxBbGw6IHByb3BzLmNhbmNlbEFsbCxcbiAgICBjb21wbGV0ZTogcHJvcHMuY29tcGxldGVGaWxlcy5sZW5ndGgsXG4gICAgaW5Qcm9ncmVzczogcHJvcHMuaW5Qcm9ncmVzcyxcbiAgICB0b3RhbFNwZWVkOiBwcm9wcy50b3RhbFNwZWVkLFxuICAgIHRvdGFsRVRBOiBwcm9wcy50b3RhbEVUQSxcbiAgICBzdGFydFVwbG9hZDogcHJvcHMuc3RhcnRVcGxvYWQsXG4gICAgbmV3RmlsZUNvdW50OiBwcm9wcy5uZXdGaWxlcy5sZW5ndGgsXG4gICAgaTE4bjogcHJvcHMuaTE4bixcbiAgICByZXN1bWFibGVVcGxvYWRzOiBwcm9wcy5yZXN1bWFibGVVcGxvYWRzXG4gIH0pLCAnICcsIHByb3BzLnByb2dyZXNzaW5kaWNhdG9ycy5tYXAoZnVuY3Rpb24gKHRhcmdldCkge1xuICAgIHJldHVybiB0YXJnZXQucmVuZGVyKHByb3BzLnN0YXRlKTtcbiAgfSksICcgJ10pLCBfdXBweURhc2hib2FyZFByb2dyZXNzaW5kaWNhdG9ycyksICcgJ10pLCBfdXBweURhc2hib2FyZElubmVyV3JhcCksICcgJ10pLCBfdXBweURhc2hib2FyZElubmVyKSwgJyAnXSksIF9kaXY7XG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9RGFzaGJvYXJkLmpzLm1hcCIsIid1c2Ugc3RyaWN0JztcblxudmFyIF9hcHBlbmRDaGlsZCA9IHJlcXVpcmUoJ3lvLXlvaWZ5L2xpYi9hcHBlbmRDaGlsZCcpO1xuXG52YXIgZ2V0RmlsZVR5cGVJY29uID0gcmVxdWlyZSgnLi9nZXRGaWxlVHlwZUljb24nKTtcblxudmFyIF9yZXF1aXJlID0gcmVxdWlyZSgnLi9pY29ucycpLFxuICAgIGNoZWNrSWNvbiA9IF9yZXF1aXJlLmNoZWNrSWNvbjtcblxuLy8gZnVuY3Rpb24gZ2V0SWNvbkJ5TWltZSAoZmlsZVR5cGVHZW5lcmFsKSB7XG4vLyAgIHN3aXRjaCAoZmlsZVR5cGVHZW5lcmFsKSB7XG4vLyAgICAgY2FzZSAndGV4dCc6XG4vLyAgICAgICByZXR1cm4gaWNvblRleHQoKVxuLy8gICAgIGNhc2UgJ2F1ZGlvJzpcbi8vICAgICAgIHJldHVybiBpY29uQXVkaW8oKVxuLy8gICAgIGRlZmF1bHQ6XG4vLyAgICAgICByZXR1cm4gaWNvbkZpbGUoKVxuLy8gICB9XG4vLyB9XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZmlsZUNhcmQocHJvcHMpIHtcbiAgdmFyIF91cHB5RGFzaGJvYXJkQ29udGVudFRpdGxlRmlsZSwgX3VwcHlEYXNoYm9hcmRDb250ZW50VGl0bGUsIF91cHB5RGFzaGJvYXJkQ29udGVudEJhY2ssIF91cHB5RGFzaGJvYXJkQ29udGVudEJhciwgX3VwcHlCdXR0b25DaXJjdWxhciwgX3VwcHlEYXNoYm9hcmRBY3Rpb25zLCBfdXBweURhc2hib2FyZEZpbGVDYXJkLCBfdXBweURhc2hib2FyZEZpbGVDYXJkUHJldmlldywgX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZExhYmVsMiwgX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZElucHV0MiwgX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZEZpZWxkc2V0MiwgX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZEluZm8sIF91cHB5RGFzaGJvYXJkRmlsZUNhcmRJbm5lciwgX2ltZywgX3VwcHlEYXNoYm9hcmRJdGVtUHJldmlld0ljb247XG5cbiAgdmFyIGZpbGUgPSBwcm9wcy5maWxlQ2FyZEZvciA/IHByb3BzLmZpbGVzW3Byb3BzLmZpbGVDYXJkRm9yXSA6IGZhbHNlO1xuICB2YXIgbWV0YSA9IHt9O1xuXG4gIGZ1bmN0aW9uIHRlbXBTdG9yZU1ldGEoZXYpIHtcbiAgICB2YXIgdmFsdWUgPSBldi50YXJnZXQudmFsdWU7XG4gICAgdmFyIG5hbWUgPSBldi50YXJnZXQuYXR0cmlidXRlcy5uYW1lLnZhbHVlO1xuICAgIG1ldGFbbmFtZV0gPSB2YWx1ZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlbmRlck1ldGFGaWVsZHMoZmlsZSkge1xuICAgIHZhciBtZXRhRmllbGRzID0gcHJvcHMubWV0YUZpZWxkcyB8fCBbXTtcbiAgICByZXR1cm4gbWV0YUZpZWxkcy5tYXAoZnVuY3Rpb24gKGZpZWxkKSB7XG4gICAgICB2YXIgX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZExhYmVsLCBfdXBweURhc2hib2FyZEZpbGVDYXJkSW5wdXQsIF91cHB5RGFzaGJvYXJkRmlsZUNhcmRGaWVsZHNldDtcblxuICAgICAgcmV0dXJuIF91cHB5RGFzaGJvYXJkRmlsZUNhcmRGaWVsZHNldCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ZpZWxkc2V0JyksIF91cHB5RGFzaGJvYXJkRmlsZUNhcmRGaWVsZHNldC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRGaWxlQ2FyZC1maWVsZHNldCcpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZEZpZWxkc2V0LCBbJyAnLCAoX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZExhYmVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGFiZWwnKSwgX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZExhYmVsLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZEZpbGVDYXJkLWxhYmVsJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZEZpbGVDYXJkTGFiZWwsIFtmaWVsZC5uYW1lXSksIF91cHB5RGFzaGJvYXJkRmlsZUNhcmRMYWJlbCksICcgJywgKF91cHB5RGFzaGJvYXJkRmlsZUNhcmRJbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0JyksIF91cHB5RGFzaGJvYXJkRmlsZUNhcmRJbnB1dC5zZXRBdHRyaWJ1dGUoJ25hbWUnLCAnJyArIFN0cmluZyhmaWVsZC5pZCkgKyAnJyksIF91cHB5RGFzaGJvYXJkRmlsZUNhcmRJbnB1dC5zZXRBdHRyaWJ1dGUoJ3R5cGUnLCAndGV4dCcpLCBfdXBweURhc2hib2FyZEZpbGVDYXJkSW5wdXQuc2V0QXR0cmlidXRlKCd2YWx1ZScsICcnICsgU3RyaW5nKGZpbGUubWV0YVtmaWVsZC5pZF0pICsgJycpLCBfdXBweURhc2hib2FyZEZpbGVDYXJkSW5wdXQuc2V0QXR0cmlidXRlKCdwbGFjZWhvbGRlcicsICcnICsgU3RyaW5nKGZpZWxkLnBsYWNlaG9sZGVyIHx8ICcnKSArICcnKSwgX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZElucHV0Lm9ua2V5dXAgPSB0ZW1wU3RvcmVNZXRhLCBfdXBweURhc2hib2FyZEZpbGVDYXJkSW5wdXQuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkRmlsZUNhcmQtaW5wdXQnKSwgX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZElucHV0KV0pLCBfdXBweURhc2hib2FyZEZpbGVDYXJkRmllbGRzZXQ7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLCBfdXBweURhc2hib2FyZEZpbGVDYXJkLnNldEF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nLCAnJyArIFN0cmluZyghcHJvcHMuZmlsZUNhcmRGb3IpICsgJycpLCBfdXBweURhc2hib2FyZEZpbGVDYXJkLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZEZpbGVDYXJkJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZEZpbGVDYXJkLCBbJyAnLCAoX3VwcHlEYXNoYm9hcmRDb250ZW50QmFyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksIF91cHB5RGFzaGJvYXJkQ29udGVudEJhci5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRDb250ZW50LWJhcicpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmRDb250ZW50QmFyLCBbJyAnLCAoX3VwcHlEYXNoYm9hcmRDb250ZW50VGl0bGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdoMicpLCBfdXBweURhc2hib2FyZENvbnRlbnRUaXRsZS5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRDb250ZW50LXRpdGxlJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZENvbnRlbnRUaXRsZSwgWydFZGl0aW5nICcsIChfdXBweURhc2hib2FyZENvbnRlbnRUaXRsZUZpbGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyksIF91cHB5RGFzaGJvYXJkQ29udGVudFRpdGxlRmlsZS5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRDb250ZW50LXRpdGxlRmlsZScpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmRDb250ZW50VGl0bGVGaWxlLCBbZmlsZS5tZXRhID8gZmlsZS5tZXRhLm5hbWUgOiBmaWxlLm5hbWVdKSwgX3VwcHlEYXNoYm9hcmRDb250ZW50VGl0bGVGaWxlKV0pLCBfdXBweURhc2hib2FyZENvbnRlbnRUaXRsZSksICcgJywgKF91cHB5RGFzaGJvYXJkQ29udGVudEJhY2sgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdidXR0b24nKSwgX3VwcHlEYXNoYm9hcmRDb250ZW50QmFjay5zZXRBdHRyaWJ1dGUoJ3RpdGxlJywgJ0ZpbmlzaCBlZGl0aW5nIGZpbGUnKSwgX3VwcHlEYXNoYm9hcmRDb250ZW50QmFjay5vbmNsaWNrID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBwcm9wcy5kb25lKG1ldGEsIGZpbGUuaWQpO1xuICB9LCBfdXBweURhc2hib2FyZENvbnRlbnRCYWNrLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZENvbnRlbnQtYmFjaycpLCBfdXBweURhc2hib2FyZENvbnRlbnRCYWNrLnRleHRDb250ZW50ID0gJ0RvbmUnLCBfdXBweURhc2hib2FyZENvbnRlbnRCYWNrKSwgJyAnXSksIF91cHB5RGFzaGJvYXJkQ29udGVudEJhciksICcgJywgcHJvcHMuZmlsZUNhcmRGb3IgPyAoX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZElubmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksIF91cHB5RGFzaGJvYXJkRmlsZUNhcmRJbm5lci5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRGaWxlQ2FyZC1pbm5lcicpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZElubmVyLCBbJyAnLCAoX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZFByZXZpZXcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSwgX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZFByZXZpZXcuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkRmlsZUNhcmQtcHJldmlldycpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZFByZXZpZXcsIFsnICcsIGZpbGUucHJldmlldyA/IChfaW1nID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW1nJyksIF9pbWcuc2V0QXR0cmlidXRlKCdhbHQnLCAnJyArIFN0cmluZyhmaWxlLm5hbWUpICsgJycpLCBfaW1nLnNldEF0dHJpYnV0ZSgnc3JjJywgJycgKyBTdHJpbmcoZmlsZS5wcmV2aWV3KSArICcnKSwgX2ltZykgOiAoX3VwcHlEYXNoYm9hcmRJdGVtUHJldmlld0ljb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSwgX3VwcHlEYXNoYm9hcmRJdGVtUHJldmlld0ljb24uc2V0QXR0cmlidXRlKCdzdHlsZScsICdjb2xvcjogJyArIFN0cmluZyhnZXRGaWxlVHlwZUljb24oZmlsZS50eXBlLmdlbmVyYWwsIGZpbGUudHlwZS5zcGVjaWZpYykuY29sb3IpICsgJycpLCBfdXBweURhc2hib2FyZEl0ZW1QcmV2aWV3SWNvbi5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRJdGVtLXByZXZpZXdJY29uJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZEl0ZW1QcmV2aWV3SWNvbiwgWycgJywgZ2V0RmlsZVR5cGVJY29uKGZpbGUudHlwZS5nZW5lcmFsLCBmaWxlLnR5cGUuc3BlY2lmaWMpLmljb24sICcgJ10pLCBfdXBweURhc2hib2FyZEl0ZW1QcmV2aWV3SWNvbiksICcgJ10pLCBfdXBweURhc2hib2FyZEZpbGVDYXJkUHJldmlldyksICcgJywgKF91cHB5RGFzaGJvYXJkRmlsZUNhcmRJbmZvID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksIF91cHB5RGFzaGJvYXJkRmlsZUNhcmRJbmZvLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZEZpbGVDYXJkLWluZm8nKSwgX2FwcGVuZENoaWxkKF91cHB5RGFzaGJvYXJkRmlsZUNhcmRJbmZvLCBbJyAnLCAoX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZEZpZWxkc2V0MiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ZpZWxkc2V0JyksIF91cHB5RGFzaGJvYXJkRmlsZUNhcmRGaWVsZHNldDIuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkRmlsZUNhcmQtZmllbGRzZXQnKSwgX2FwcGVuZENoaWxkKF91cHB5RGFzaGJvYXJkRmlsZUNhcmRGaWVsZHNldDIsIFsnICcsIChfdXBweURhc2hib2FyZEZpbGVDYXJkTGFiZWwyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGFiZWwnKSwgX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZExhYmVsMi5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRGaWxlQ2FyZC1sYWJlbCcpLCBfdXBweURhc2hib2FyZEZpbGVDYXJkTGFiZWwyLnRleHRDb250ZW50ID0gJ05hbWUnLCBfdXBweURhc2hib2FyZEZpbGVDYXJkTGFiZWwyKSwgJyAnLCAoX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZElucHV0MiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0JyksIF91cHB5RGFzaGJvYXJkRmlsZUNhcmRJbnB1dDIuc2V0QXR0cmlidXRlKCduYW1lJywgJ25hbWUnKSwgX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZElucHV0Mi5zZXRBdHRyaWJ1dGUoJ3R5cGUnLCAndGV4dCcpLCBfdXBweURhc2hib2FyZEZpbGVDYXJkSW5wdXQyLnNldEF0dHJpYnV0ZSgndmFsdWUnLCAnJyArIFN0cmluZyhmaWxlLm1ldGEubmFtZSkgKyAnJyksIF91cHB5RGFzaGJvYXJkRmlsZUNhcmRJbnB1dDIub25rZXl1cCA9IHRlbXBTdG9yZU1ldGEsIF91cHB5RGFzaGJvYXJkRmlsZUNhcmRJbnB1dDIuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkRmlsZUNhcmQtaW5wdXQnKSwgX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZElucHV0MiksICcgJ10pLCBfdXBweURhc2hib2FyZEZpbGVDYXJkRmllbGRzZXQyKSwgJyAnLCByZW5kZXJNZXRhRmllbGRzKGZpbGUpLCAnICddKSwgX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZEluZm8pLCAnICddKSwgX3VwcHlEYXNoYm9hcmRGaWxlQ2FyZElubmVyKSA6IG51bGwsICcgJywgKF91cHB5RGFzaGJvYXJkQWN0aW9ucyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLCBfdXBweURhc2hib2FyZEFjdGlvbnMuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkLWFjdGlvbnMnKSwgX2FwcGVuZENoaWxkKF91cHB5RGFzaGJvYXJkQWN0aW9ucywgWycgJywgKF91cHB5QnV0dG9uQ2lyY3VsYXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdidXR0b24nKSwgX3VwcHlCdXR0b25DaXJjdWxhci5zZXRBdHRyaWJ1dGUoJ3R5cGUnLCAnYnV0dG9uJyksIF91cHB5QnV0dG9uQ2lyY3VsYXIuc2V0QXR0cmlidXRlKCd0aXRsZScsICdGaW5pc2ggZWRpdGluZyBmaWxlJyksIF91cHB5QnV0dG9uQ2lyY3VsYXIub25jbGljayA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gcHJvcHMuZG9uZShtZXRhLCBmaWxlLmlkKTtcbiAgfSwgX3VwcHlCdXR0b25DaXJjdWxhci5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlCdXR0b24tLWNpcmN1bGFyIFVwcHlCdXR0b24tLWJsdWUgVXBweURhc2hib2FyZEZpbGVDYXJkLWRvbmUnKSwgX2FwcGVuZENoaWxkKF91cHB5QnV0dG9uQ2lyY3VsYXIsIFtjaGVja0ljb24oKV0pLCBfdXBweUJ1dHRvbkNpcmN1bGFyKSwgJyAnXSksIF91cHB5RGFzaGJvYXJkQWN0aW9ucyksICcgJ10pLCBfdXBweURhc2hib2FyZEZpbGVDYXJkO1xufTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPUZpbGVDYXJkLmpzLm1hcCIsIid1c2Ugc3RyaWN0JztcblxudmFyIF9hcHBlbmRDaGlsZCA9IHJlcXVpcmUoJ3lvLXlvaWZ5L2xpYi9hcHBlbmRDaGlsZCcpLFxuICAgIF9zdmdOYW1lc3BhY2UgPSAnaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnO1xuXG52YXIgX3JlcXVpcmUgPSByZXF1aXJlKCcuLi8uLi9jb3JlL1V0aWxzJyksXG4gICAgZ2V0RVRBID0gX3JlcXVpcmUuZ2V0RVRBLFxuICAgIGdldFNwZWVkID0gX3JlcXVpcmUuZ2V0U3BlZWQsXG4gICAgcHJldHR5RVRBID0gX3JlcXVpcmUucHJldHR5RVRBLFxuICAgIGdldEZpbGVOYW1lQW5kRXh0ZW5zaW9uID0gX3JlcXVpcmUuZ2V0RmlsZU5hbWVBbmRFeHRlbnNpb24sXG4gICAgdHJ1bmNhdGVTdHJpbmcgPSBfcmVxdWlyZS50cnVuY2F0ZVN0cmluZyxcbiAgICBjb3B5VG9DbGlwYm9hcmQgPSBfcmVxdWlyZS5jb3B5VG9DbGlwYm9hcmQ7XG5cbnZhciBwcmV0dHlCeXRlcyA9IHJlcXVpcmUoJ3ByZXR0aWVyLWJ5dGVzJyk7XG52YXIgRmlsZUl0ZW1Qcm9ncmVzcyA9IHJlcXVpcmUoJy4vRmlsZUl0ZW1Qcm9ncmVzcycpO1xudmFyIGdldEZpbGVUeXBlSWNvbiA9IHJlcXVpcmUoJy4vZ2V0RmlsZVR5cGVJY29uJyk7XG5cbnZhciBfcmVxdWlyZTIgPSByZXF1aXJlKCcuL2ljb25zJyksXG4gICAgaWNvbkVkaXQgPSBfcmVxdWlyZTIuaWNvbkVkaXQsXG4gICAgaWNvbkNvcHkgPSBfcmVxdWlyZTIuaWNvbkNvcHk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZmlsZUl0ZW0ocHJvcHMpIHtcbiAgdmFyIF91cHB5RGFzaGJvYXJkSXRlbVByb2dyZXNzQnRuLCBfdXBweURhc2hib2FyZEl0ZW1Qcm9ncmVzcywgX3VwcHlEYXNoYm9hcmRJdGVtUHJldmlldywgX3VwcHlEYXNoYm9hcmRJdGVtTmFtZSwgX3VwcHlEYXNoYm9hcmRJdGVtU3RhdHVzU2l6ZSwgX3VwcHlEYXNoYm9hcmRJdGVtU3RhdHVzLCBfdXBweURhc2hib2FyZEl0ZW1JbmZvLCBfdXBweURhc2hib2FyZEl0ZW1BY3Rpb24sIF9saSwgX3VwcHlEYXNoYm9hcmRJdGVtU291cmNlSWNvbiwgX2ltZywgX3VwcHlEYXNoYm9hcmRJdGVtUHJldmlld0ljb24sIF91cHB5RGFzaGJvYXJkSXRlbVByb2dyZXNzSW5mbywgX3NwYW4yLCBfYSwgX3VwcHlEYXNoYm9hcmRJdGVtRWRpdCwgX3VwcHlEYXNoYm9hcmRJdGVtQ29weUxpbmssIF9lbGxpcHNlLCBfcGF0aCwgX3VwcHlJY29uLCBfdXBweURhc2hib2FyZEl0ZW1SZW1vdmU7XG5cbiAgdmFyIGZpbGUgPSBwcm9wcy5maWxlO1xuICB2YXIgYWNxdWlyZXJzID0gcHJvcHMuYWNxdWlyZXJzO1xuXG4gIHZhciBpc1VwbG9hZGVkID0gZmlsZS5wcm9ncmVzcy51cGxvYWRDb21wbGV0ZTtcbiAgdmFyIHVwbG9hZEluUHJvZ3Jlc3NPckNvbXBsZXRlID0gZmlsZS5wcm9ncmVzcy51cGxvYWRTdGFydGVkO1xuICB2YXIgdXBsb2FkSW5Qcm9ncmVzcyA9IGZpbGUucHJvZ3Jlc3MudXBsb2FkU3RhcnRlZCAmJiAhZmlsZS5wcm9ncmVzcy51cGxvYWRDb21wbGV0ZTtcbiAgdmFyIGlzUGF1c2VkID0gZmlsZS5pc1BhdXNlZCB8fCBmYWxzZTtcblxuICB2YXIgZmlsZU5hbWUgPSBnZXRGaWxlTmFtZUFuZEV4dGVuc2lvbihmaWxlLm1ldGEubmFtZSlbMF07XG4gIHZhciB0cnVuY2F0ZWRGaWxlTmFtZSA9IHByb3BzLmlzV2lkZSA/IHRydW5jYXRlU3RyaW5nKGZpbGVOYW1lLCAxNSkgOiBmaWxlTmFtZTtcblxuICByZXR1cm4gX2xpID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGknKSwgX2xpLnNldEF0dHJpYnV0ZSgnaWQnLCAndXBweV8nICsgU3RyaW5nKGZpbGUuaWQpICsgJycpLCBfbGkuc2V0QXR0cmlidXRlKCd0aXRsZScsICcnICsgU3RyaW5nKGZpbGUubWV0YS5uYW1lKSArICcnKSwgX2xpLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZEl0ZW1cXG4gICAgICAgICAgICAgICAgICAgICAgICAnICsgU3RyaW5nKHVwbG9hZEluUHJvZ3Jlc3MgPyAnaXMtaW5wcm9ncmVzcycgOiAnJykgKyAnXFxuICAgICAgICAgICAgICAgICAgICAgICAgJyArIFN0cmluZyhpc1VwbG9hZGVkID8gJ2lzLWNvbXBsZXRlJyA6ICcnKSArICdcXG4gICAgICAgICAgICAgICAgICAgICAgICAnICsgU3RyaW5nKGlzUGF1c2VkID8gJ2lzLXBhdXNlZCcgOiAnJykgKyAnXFxuICAgICAgICAgICAgICAgICAgICAgICAgJyArIFN0cmluZyhwcm9wcy5yZXN1bWFibGVVcGxvYWRzID8gJ2lzLXJlc3VtYWJsZScgOiAnJykgKyAnJyksIF9hcHBlbmRDaGlsZChfbGksIFsnICcsIChfdXBweURhc2hib2FyZEl0ZW1QcmV2aWV3ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksIF91cHB5RGFzaGJvYXJkSXRlbVByZXZpZXcuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkSXRlbS1wcmV2aWV3JyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZEl0ZW1QcmV2aWV3LCBbJyAnLCBmaWxlLnNvdXJjZSA/IChfdXBweURhc2hib2FyZEl0ZW1Tb3VyY2VJY29uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksIF91cHB5RGFzaGJvYXJkSXRlbVNvdXJjZUljb24uc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkSXRlbS1zb3VyY2VJY29uJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZEl0ZW1Tb3VyY2VJY29uLCBbJyAnLCBhY3F1aXJlcnMubWFwKGZ1bmN0aW9uIChhY3F1aXJlcikge1xuICAgIHZhciBfc3BhbjtcblxuICAgIGlmIChhY3F1aXJlci5pZCA9PT0gZmlsZS5zb3VyY2UpIHJldHVybiBfc3BhbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKSwgX3NwYW4uc2V0QXR0cmlidXRlKCd0aXRsZScsICcnICsgU3RyaW5nKGFjcXVpcmVyLm5hbWUpICsgJycpLCBfYXBwZW5kQ2hpbGQoX3NwYW4sIFthY3F1aXJlci5pY29uKCldKSwgX3NwYW47XG4gIH0pLCAnICddKSwgX3VwcHlEYXNoYm9hcmRJdGVtU291cmNlSWNvbikgOiAnJywgJyAnLCBmaWxlLnByZXZpZXcgPyAoX2ltZyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpLCBfaW1nLnNldEF0dHJpYnV0ZSgnYWx0JywgJycgKyBTdHJpbmcoZmlsZS5uYW1lKSArICcnKSwgX2ltZy5zZXRBdHRyaWJ1dGUoJ3NyYycsICcnICsgU3RyaW5nKGZpbGUucHJldmlldykgKyAnJyksIF9pbWcpIDogKF91cHB5RGFzaGJvYXJkSXRlbVByZXZpZXdJY29uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksIF91cHB5RGFzaGJvYXJkSXRlbVByZXZpZXdJY29uLnNldEF0dHJpYnV0ZSgnc3R5bGUnLCAnY29sb3I6ICcgKyBTdHJpbmcoZ2V0RmlsZVR5cGVJY29uKGZpbGUudHlwZS5nZW5lcmFsLCBmaWxlLnR5cGUuc3BlY2lmaWMpLmNvbG9yKSArICcnKSwgX3VwcHlEYXNoYm9hcmRJdGVtUHJldmlld0ljb24uc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkSXRlbS1wcmV2aWV3SWNvbicpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmRJdGVtUHJldmlld0ljb24sIFsnICcsIGdldEZpbGVUeXBlSWNvbihmaWxlLnR5cGUuZ2VuZXJhbCwgZmlsZS50eXBlLnNwZWNpZmljKS5pY29uLCAnICddKSwgX3VwcHlEYXNoYm9hcmRJdGVtUHJldmlld0ljb24pLCAnICcsIChfdXBweURhc2hib2FyZEl0ZW1Qcm9ncmVzcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLCBfdXBweURhc2hib2FyZEl0ZW1Qcm9ncmVzcy5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRJdGVtLXByb2dyZXNzJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZEl0ZW1Qcm9ncmVzcywgWycgJywgKF91cHB5RGFzaGJvYXJkSXRlbVByb2dyZXNzQnRuID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnV0dG9uJyksIF91cHB5RGFzaGJvYXJkSXRlbVByb2dyZXNzQnRuLnNldEF0dHJpYnV0ZSgndGl0bGUnLCAnJyArIFN0cmluZyhpc1VwbG9hZGVkID8gJ3VwbG9hZCBjb21wbGV0ZScgOiBwcm9wcy5yZXN1bWFibGVVcGxvYWRzID8gZmlsZS5pc1BhdXNlZCA/ICdyZXN1bWUgdXBsb2FkJyA6ICdwYXVzZSB1cGxvYWQnIDogJ2NhbmNlbCB1cGxvYWQnKSArICcnKSwgX3VwcHlEYXNoYm9hcmRJdGVtUHJvZ3Jlc3NCdG4ub25jbGljayA9IGZ1bmN0aW9uIChldikge1xuICAgIGlmIChpc1VwbG9hZGVkKSByZXR1cm47XG4gICAgaWYgKHByb3BzLnJlc3VtYWJsZVVwbG9hZHMpIHtcbiAgICAgIHByb3BzLnBhdXNlVXBsb2FkKGZpbGUuaWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9wcy5jYW5jZWxVcGxvYWQoZmlsZS5pZCk7XG4gICAgfVxuICB9LCBfdXBweURhc2hib2FyZEl0ZW1Qcm9ncmVzc0J0bi5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRJdGVtLXByb2dyZXNzQnRuJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZEl0ZW1Qcm9ncmVzc0J0biwgWycgJywgRmlsZUl0ZW1Qcm9ncmVzcyh7XG4gICAgcHJvZ3Jlc3M6IGZpbGUucHJvZ3Jlc3MucGVyY2VudGFnZSxcbiAgICBmaWxlSUQ6IGZpbGUuaWRcbiAgfSksICcgJ10pLCBfdXBweURhc2hib2FyZEl0ZW1Qcm9ncmVzc0J0biksICcgJywgcHJvcHMuc2hvd1Byb2dyZXNzRGV0YWlscyA/IChfdXBweURhc2hib2FyZEl0ZW1Qcm9ncmVzc0luZm8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSwgX3VwcHlEYXNoYm9hcmRJdGVtUHJvZ3Jlc3NJbmZvLnNldEF0dHJpYnV0ZSgndGl0bGUnLCAnJyArIFN0cmluZyhwcm9wcy5pMThuKCdmaWxlUHJvZ3Jlc3MnKSkgKyAnJyksIF91cHB5RGFzaGJvYXJkSXRlbVByb2dyZXNzSW5mby5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCAnJyArIFN0cmluZyhwcm9wcy5pMThuKCdmaWxlUHJvZ3Jlc3MnKSkgKyAnJyksIF91cHB5RGFzaGJvYXJkSXRlbVByb2dyZXNzSW5mby5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRJdGVtLXByb2dyZXNzSW5mbycpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmRJdGVtUHJvZ3Jlc3NJbmZvLCBbJyAnLCAhZmlsZS5pc1BhdXNlZCAmJiAhaXNVcGxvYWRlZCA/IChfc3BhbjIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyksIF9hcHBlbmRDaGlsZChfc3BhbjIsIFtwcmV0dHlFVEEoZ2V0RVRBKGZpbGUucHJvZ3Jlc3MpKSwgJyBcXHUzMEZCIFxcdTIxOTEgJywgcHJldHR5Qnl0ZXMoZ2V0U3BlZWQoZmlsZS5wcm9ncmVzcykpLCAnL3MnXSksIF9zcGFuMikgOiBudWxsLCAnICddKSwgX3VwcHlEYXNoYm9hcmRJdGVtUHJvZ3Jlc3NJbmZvKSA6IG51bGwsICcgJ10pLCBfdXBweURhc2hib2FyZEl0ZW1Qcm9ncmVzcyksICcgJ10pLCBfdXBweURhc2hib2FyZEl0ZW1QcmV2aWV3KSwgJyAnLCAoX3VwcHlEYXNoYm9hcmRJdGVtSW5mbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLCBfdXBweURhc2hib2FyZEl0ZW1JbmZvLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZEl0ZW0taW5mbycpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmRJdGVtSW5mbywgWycgJywgKF91cHB5RGFzaGJvYXJkSXRlbU5hbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdoNCcpLCBfdXBweURhc2hib2FyZEl0ZW1OYW1lLnNldEF0dHJpYnV0ZSgndGl0bGUnLCAnJyArIFN0cmluZyhmaWxlTmFtZSkgKyAnJyksIF91cHB5RGFzaGJvYXJkSXRlbU5hbWUuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkSXRlbS1uYW1lJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZEl0ZW1OYW1lLCBbJyAnLCBmaWxlLnVwbG9hZFVSTCA/IChfYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKSwgX2Euc2V0QXR0cmlidXRlKCdocmVmJywgJycgKyBTdHJpbmcoZmlsZS51cGxvYWRVUkwpICsgJycpLCBfYS5zZXRBdHRyaWJ1dGUoJ3RhcmdldCcsICdfYmxhbmsnKSwgX2FwcGVuZENoaWxkKF9hLCBbJyAnLCBmaWxlLmV4dGVuc2lvbiA/IHRydW5jYXRlZEZpbGVOYW1lICsgJy4nICsgZmlsZS5leHRlbnNpb24gOiB0cnVuY2F0ZWRGaWxlTmFtZSwgJyAnXSksIF9hKSA6IGZpbGUuZXh0ZW5zaW9uID8gdHJ1bmNhdGVkRmlsZU5hbWUgKyAnLicgKyBmaWxlLmV4dGVuc2lvbiA6IHRydW5jYXRlZEZpbGVOYW1lLCAnICddKSwgX3VwcHlEYXNoYm9hcmRJdGVtTmFtZSksICcgJywgKF91cHB5RGFzaGJvYXJkSXRlbVN0YXR1cyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLCBfdXBweURhc2hib2FyZEl0ZW1TdGF0dXMuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkSXRlbS1zdGF0dXMnKSwgX2FwcGVuZENoaWxkKF91cHB5RGFzaGJvYXJkSXRlbVN0YXR1cywgWycgJywgKF91cHB5RGFzaGJvYXJkSXRlbVN0YXR1c1NpemUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyksIF91cHB5RGFzaGJvYXJkSXRlbVN0YXR1c1NpemUuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkSXRlbS1zdGF0dXNTaXplJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZEl0ZW1TdGF0dXNTaXplLCBbZmlsZS5kYXRhLnNpemUgPyBwcmV0dHlCeXRlcyhmaWxlLmRhdGEuc2l6ZSkgOiAnPyddKSwgX3VwcHlEYXNoYm9hcmRJdGVtU3RhdHVzU2l6ZSksICcgJ10pLCBfdXBweURhc2hib2FyZEl0ZW1TdGF0dXMpLCAnICcsICF1cGxvYWRJblByb2dyZXNzT3JDb21wbGV0ZSA/IChfdXBweURhc2hib2FyZEl0ZW1FZGl0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnV0dG9uJyksIF91cHB5RGFzaGJvYXJkSXRlbUVkaXQuc2V0QXR0cmlidXRlKCdhcmlhLWxhYmVsJywgJ0VkaXQgZmlsZScpLCBfdXBweURhc2hib2FyZEl0ZW1FZGl0LnNldEF0dHJpYnV0ZSgndGl0bGUnLCAnRWRpdCBmaWxlJyksIF91cHB5RGFzaGJvYXJkSXRlbUVkaXQub25jbGljayA9IGZ1bmN0aW9uIChlKSB7XG4gICAgcmV0dXJuIHByb3BzLnNob3dGaWxlQ2FyZChmaWxlLmlkKTtcbiAgfSwgX3VwcHlEYXNoYm9hcmRJdGVtRWRpdC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRJdGVtLWVkaXQnKSwgX2FwcGVuZENoaWxkKF91cHB5RGFzaGJvYXJkSXRlbUVkaXQsIFsnICcsIGljb25FZGl0KCldKSwgX3VwcHlEYXNoYm9hcmRJdGVtRWRpdCkgOiBudWxsLCAnICcsIGZpbGUudXBsb2FkVVJMID8gKF91cHB5RGFzaGJvYXJkSXRlbUNvcHlMaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnV0dG9uJyksIF91cHB5RGFzaGJvYXJkSXRlbUNvcHlMaW5rLnNldEF0dHJpYnV0ZSgnYXJpYS1sYWJlbCcsICdDb3B5IGxpbmsnKSwgX3VwcHlEYXNoYm9hcmRJdGVtQ29weUxpbmsuc2V0QXR0cmlidXRlKCd0aXRsZScsICdDb3B5IGxpbmsnKSwgX3VwcHlEYXNoYm9hcmRJdGVtQ29weUxpbmsub25jbGljayA9IGZ1bmN0aW9uICgpIHtcbiAgICBjb3B5VG9DbGlwYm9hcmQoZmlsZS51cGxvYWRVUkwsIHByb3BzLmkxOG4oJ2NvcHlMaW5rVG9DbGlwYm9hcmRGYWxsYmFjaycpKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHByb3BzLmxvZygnTGluayBjb3BpZWQgdG8gY2xpcGJvYXJkLicpO1xuICAgICAgcHJvcHMuaW5mbyhwcm9wcy5pMThuKCdjb3B5TGlua1RvQ2xpcGJvYXJkU3VjY2VzcycpLCAnaW5mbycsIDMwMDApO1xuICAgIH0pLmNhdGNoKHByb3BzLmxvZyk7XG4gIH0sIF91cHB5RGFzaGJvYXJkSXRlbUNvcHlMaW5rLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZEl0ZW0tY29weUxpbmsnKSwgX2FwcGVuZENoaWxkKF91cHB5RGFzaGJvYXJkSXRlbUNvcHlMaW5rLCBbaWNvbkNvcHkoKV0pLCBfdXBweURhc2hib2FyZEl0ZW1Db3B5TGluaykgOiBudWxsLCAnICddKSwgX3VwcHlEYXNoYm9hcmRJdGVtSW5mbyksICcgJywgKF91cHB5RGFzaGJvYXJkSXRlbUFjdGlvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLCBfdXBweURhc2hib2FyZEl0ZW1BY3Rpb24uc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkSXRlbS1hY3Rpb24nKSwgX2FwcGVuZENoaWxkKF91cHB5RGFzaGJvYXJkSXRlbUFjdGlvbiwgWycgJywgIWlzVXBsb2FkZWQgPyAoX3VwcHlEYXNoYm9hcmRJdGVtUmVtb3ZlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnV0dG9uJyksIF91cHB5RGFzaGJvYXJkSXRlbVJlbW92ZS5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCAnUmVtb3ZlIGZpbGUnKSwgX3VwcHlEYXNoYm9hcmRJdGVtUmVtb3ZlLnNldEF0dHJpYnV0ZSgndGl0bGUnLCAnUmVtb3ZlIGZpbGUnKSwgX3VwcHlEYXNoYm9hcmRJdGVtUmVtb3ZlLm9uY2xpY2sgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHByb3BzLnJlbW92ZUZpbGUoZmlsZS5pZCk7XG4gIH0sIF91cHB5RGFzaGJvYXJkSXRlbVJlbW92ZS5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRJdGVtLXJlbW92ZScpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmRJdGVtUmVtb3ZlLCBbJyAnLCAoX3VwcHlJY29uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdzdmcnKSwgX3VwcHlJY29uLnNldEF0dHJpYnV0ZSgnd2lkdGgnLCAnMjInKSwgX3VwcHlJY29uLnNldEF0dHJpYnV0ZSgnaGVpZ2h0JywgJzIxJyksIF91cHB5SWNvbi5zZXRBdHRyaWJ1dGUoJ3ZpZXdCb3gnLCAnMCAwIDE4IDE3JyksIF91cHB5SWNvbi5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlJY29uJyksIF9hcHBlbmRDaGlsZChfdXBweUljb24sIFsnICcsIChfZWxsaXBzZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAnZWxsaXBzZScpLCBfZWxsaXBzZS5zZXRBdHRyaWJ1dGUoJ2N4JywgJzguNjInKSwgX2VsbGlwc2Uuc2V0QXR0cmlidXRlKCdjeScsICc4LjM4MycpLCBfZWxsaXBzZS5zZXRBdHRyaWJ1dGUoJ3J4JywgJzguNjInKSwgX2VsbGlwc2Uuc2V0QXR0cmlidXRlKCdyeScsICc4LjM4MycpLCBfZWxsaXBzZSksICcgJywgKF9wYXRoID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwYXRoJyksIF9wYXRoLnNldEF0dHJpYnV0ZSgnc3Ryb2tlJywgJyNGRkYnKSwgX3BhdGguc2V0QXR0cmlidXRlKCdmaWxsJywgJyNGRkYnKSwgX3BhdGguc2V0QXR0cmlidXRlKCdkJywgJ00xMSA2LjE0N0wxMC44NSA2IDguNSA4LjI4NCA2LjE1IDYgNiA2LjE0NyA4LjM1IDguNDMgNiAxMC43MTdsLjE1LjE0Nkw4LjUgOC41NzhsMi4zNSAyLjI4NC4xNS0uMTQ2TDguNjUgOC40M3onKSwgX3BhdGgpLCAnICddKSwgX3VwcHlJY29uKSwgJyAnXSksIF91cHB5RGFzaGJvYXJkSXRlbVJlbW92ZSkgOiBudWxsLCAnICddKSwgX3VwcHlEYXNoYm9hcmRJdGVtQWN0aW9uKSwgJyAnXSksIF9saTtcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1GaWxlSXRlbS5qcy5tYXAiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfc3ZnTmFtZXNwYWNlID0gJ2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJyxcbiAgICBfYXBwZW5kQ2hpbGQgPSByZXF1aXJlKCd5by15b2lmeS9saWIvYXBwZW5kQ2hpbGQnKTtcblxuLy8gaHR0cDovL2NvZGVwZW4uaW8vSGFya2tvL3Blbi9yVnh2Tk1cbi8vIGh0dHBzOi8vY3NzLXRyaWNrcy5jb20vc3ZnLWxpbmUtYW5pbWF0aW9uLXdvcmtzL1xuLy8gaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vZXN3YWsvYWQ0ZWE1N2JjZDVmZjdhYTVkNDJcblxuLy8gY2lyY2xlIGxlbmd0aCBlcXVhbHMgMiAqIFBJICogUlxudmFyIGNpcmNsZUxlbmd0aCA9IDIgKiBNYXRoLlBJICogMTU7XG5cbi8vIHN0cm9rZS1kYXNob2Zmc2V0IGlzIGEgcGVyY2VudGFnZSBvZiB0aGUgcHJvZ3Jlc3MgZnJvbSBjaXJjbGVMZW5ndGgsXG4vLyBzdWJzdHJhY3RlZCBmcm9tIGNpcmNsZUxlbmd0aCwgYmVjYXVzZSBpdHMgYW4gb2Zmc2V0XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChwcm9wcykge1xuICB2YXIgX2JnLCBfcHJvZ3Jlc3MsIF9wcm9ncmVzc0dyb3VwLCBfcGxheSwgX3JlY3QsIF9yZWN0MiwgX3BhdXNlLCBfY2hlY2ssIF9jYW5jZWwsIF91cHB5SWNvbjtcblxuICByZXR1cm4gX3VwcHlJY29uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdzdmcnKSwgX3VwcHlJY29uLnNldEF0dHJpYnV0ZSgnd2lkdGgnLCAnNzAnKSwgX3VwcHlJY29uLnNldEF0dHJpYnV0ZSgnaGVpZ2h0JywgJzcwJyksIF91cHB5SWNvbi5zZXRBdHRyaWJ1dGUoJ3ZpZXdCb3gnLCAnMCAwIDM2IDM2JyksIF91cHB5SWNvbi5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlJY29uIFVwcHlJY29uLXByb2dyZXNzQ2lyY2xlJyksIF9hcHBlbmRDaGlsZChfdXBweUljb24sIFsnICcsIChfcHJvZ3Jlc3NHcm91cCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAnZycpLCBfcHJvZ3Jlc3NHcm91cC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ3Byb2dyZXNzLWdyb3VwJyksIF9hcHBlbmRDaGlsZChfcHJvZ3Jlc3NHcm91cCwgWycgJywgKF9iZyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAnY2lyY2xlJyksIF9iZy5zZXRBdHRyaWJ1dGUoJ3InLCAnMTUnKSwgX2JnLnNldEF0dHJpYnV0ZSgnY3gnLCAnMTgnKSwgX2JnLnNldEF0dHJpYnV0ZSgnY3knLCAnMTgnKSwgX2JnLnNldEF0dHJpYnV0ZSgnc3Ryb2tlLXdpZHRoJywgJzInKSwgX2JnLnNldEF0dHJpYnV0ZSgnZmlsbCcsICdub25lJyksIF9iZy5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ2JnJyksIF9iZyksICcgJywgKF9wcm9ncmVzcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAnY2lyY2xlJyksIF9wcm9ncmVzcy5zZXRBdHRyaWJ1dGUoJ3InLCAnMTUnKSwgX3Byb2dyZXNzLnNldEF0dHJpYnV0ZSgnY3gnLCAnMTgnKSwgX3Byb2dyZXNzLnNldEF0dHJpYnV0ZSgnY3knLCAnMTgnKSwgX3Byb2dyZXNzLnNldEF0dHJpYnV0ZSgndHJhbnNmb3JtJywgJ3JvdGF0ZSgtOTAsIDE4LCAxOCknKSwgX3Byb2dyZXNzLnNldEF0dHJpYnV0ZSgnc3Ryb2tlLXdpZHRoJywgJzInKSwgX3Byb2dyZXNzLnNldEF0dHJpYnV0ZSgnZmlsbCcsICdub25lJyksIF9wcm9ncmVzcy5zZXRBdHRyaWJ1dGUoJ3N0cm9rZS1kYXNoYXJyYXknLCAnJyArIFN0cmluZyhjaXJjbGVMZW5ndGgpICsgJycpLCBfcHJvZ3Jlc3Muc2V0QXR0cmlidXRlKCdzdHJva2UtZGFzaG9mZnNldCcsICcnICsgU3RyaW5nKGNpcmNsZUxlbmd0aCAtIGNpcmNsZUxlbmd0aCAvIDEwMCAqIHByb3BzLnByb2dyZXNzKSArICcnKSwgX3Byb2dyZXNzLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAncHJvZ3Jlc3MnKSwgX3Byb2dyZXNzKSwgJyAnXSksIF9wcm9ncmVzc0dyb3VwKSwgJyAnLCAoX3BsYXkgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3BvbHlnb24nKSwgX3BsYXkuc2V0QXR0cmlidXRlKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKDMsIDMpJyksIF9wbGF5LnNldEF0dHJpYnV0ZSgncG9pbnRzJywgJzEyIDIwIDEyIDEwIDIwIDE1JyksIF9wbGF5LnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAncGxheScpLCBfcGxheSksICcgJywgKF9wYXVzZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAnZycpLCBfcGF1c2Uuc2V0QXR0cmlidXRlKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKDE0LjUsIDEzKScpLCBfcGF1c2Uuc2V0QXR0cmlidXRlKCdjbGFzcycsICdwYXVzZScpLCBfYXBwZW5kQ2hpbGQoX3BhdXNlLCBbJyAnLCAoX3JlY3QgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3JlY3QnKSwgX3JlY3Quc2V0QXR0cmlidXRlKCd4JywgJzAnKSwgX3JlY3Quc2V0QXR0cmlidXRlKCd5JywgJzAnKSwgX3JlY3Quc2V0QXR0cmlidXRlKCd3aWR0aCcsICcyJyksIF9yZWN0LnNldEF0dHJpYnV0ZSgnaGVpZ2h0JywgJzEwJyksIF9yZWN0LnNldEF0dHJpYnV0ZSgncngnLCAnMCcpLCBfcmVjdCksICcgJywgKF9yZWN0MiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAncmVjdCcpLCBfcmVjdDIuc2V0QXR0cmlidXRlKCd4JywgJzUnKSwgX3JlY3QyLnNldEF0dHJpYnV0ZSgneScsICcwJyksIF9yZWN0Mi5zZXRBdHRyaWJ1dGUoJ3dpZHRoJywgJzInKSwgX3JlY3QyLnNldEF0dHJpYnV0ZSgnaGVpZ2h0JywgJzEwJyksIF9yZWN0Mi5zZXRBdHRyaWJ1dGUoJ3J4JywgJzAnKSwgX3JlY3QyKSwgJyAnXSksIF9wYXVzZSksICcgJywgKF9jaGVjayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAncG9seWdvbicpLCBfY2hlY2suc2V0QXR0cmlidXRlKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKDIsIDMpJyksIF9jaGVjay5zZXRBdHRyaWJ1dGUoJ3BvaW50cycsICcxNCAyMi41IDcgMTUuMjQ1NzA2NSA4Ljk5OTg1ODU3IDEzLjE3MzI4MTUgMTQgMTguMzU0NzEwNCAyMi45NzI5ODgzIDkgMjUgMTEuMTAwNTYzNCcpLCBfY2hlY2suc2V0QXR0cmlidXRlKCdjbGFzcycsICdjaGVjaycpLCBfY2hlY2spLCAnICcsIChfY2FuY2VsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwb2x5Z29uJyksIF9jYW5jZWwuc2V0QXR0cmlidXRlKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKDIsIDIpJyksIF9jYW5jZWwuc2V0QXR0cmlidXRlKCdwb2ludHMnLCAnMTkuODg1NjUxNiAxMS4wNjI1IDE2IDE0Ljk0ODE1MTYgMTIuMTAxOTczNyAxMS4wNjI1IDExLjA2MjUgMTIuMTE0MzQ4NCAxNC45NDgxNTE2IDE2IDExLjA2MjUgMTkuODk4MDI2MyAxMi4xMDE5NzM3IDIwLjkzNzUgMTYgMTcuMDUxODQ4NCAxOS44ODU2NTE2IDIwLjkzNzUgMjAuOTM3NSAxOS44OTgwMjYzIDE3LjA1MTg0ODQgMTYgMjAuOTM3NSAxMicpLCBfY2FuY2VsLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnY2FuY2VsJyksIF9jYW5jZWwpXSksIF91cHB5SWNvbjtcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1GaWxlSXRlbVByb2dyZXNzLmpzLm1hcCIsIid1c2Ugc3RyaWN0JztcblxudmFyIF9hcHBlbmRDaGlsZCA9IHJlcXVpcmUoJ3lvLXlvaWZ5L2xpYi9hcHBlbmRDaGlsZCcpO1xuXG52YXIgRmlsZUl0ZW0gPSByZXF1aXJlKCcuL0ZpbGVJdGVtJyk7XG52YXIgQWN0aW9uQnJvd3NlVGFnbGluZSA9IHJlcXVpcmUoJy4vQWN0aW9uQnJvd3NlVGFnbGluZScpO1xuXG52YXIgX3JlcXVpcmUgPSByZXF1aXJlKCcuL2ljb25zJyksXG4gICAgZGFzaGJvYXJkQmdJY29uID0gX3JlcXVpcmUuZGFzaGJvYXJkQmdJY29uO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChwcm9wcykge1xuICB2YXIgX3VsLCBfdXBweURhc2hib2FyZERyb3BGaWxlc1RpdGxlLCBfdXBweURhc2hib2FyZElucHV0LCBfdXBweURhc2hib2FyZEJnSWNvbjtcblxuICByZXR1cm4gX3VsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndWwnKSwgX3VsLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZC1maWxlc1xcbiAgICAgICAgICAgICAgICAgICAgICAgICAnICsgU3RyaW5nKHByb3BzLnRvdGFsRmlsZUNvdW50ID09PSAwID8gJ1VwcHlEYXNoYm9hcmQtZmlsZXMtLW5vRmlsZXMnIDogJycpICsgJycpLCBfYXBwZW5kQ2hpbGQoX3VsLCBbJyAnLCBwcm9wcy50b3RhbEZpbGVDb3VudCA9PT0gMCA/IChfdXBweURhc2hib2FyZEJnSWNvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLCBfdXBweURhc2hib2FyZEJnSWNvbi5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmQtYmdJY29uJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZEJnSWNvbiwgWycgJywgZGFzaGJvYXJkQmdJY29uKCksICcgJywgKF91cHB5RGFzaGJvYXJkRHJvcEZpbGVzVGl0bGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdoMycpLCBfdXBweURhc2hib2FyZERyb3BGaWxlc1RpdGxlLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZC1kcm9wRmlsZXNUaXRsZScpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmREcm9wRmlsZXNUaXRsZSwgWycgJywgQWN0aW9uQnJvd3NlVGFnbGluZSh7XG4gICAgYWNxdWlyZXJzOiBwcm9wcy5hY3F1aXJlcnMsXG4gICAgaGFuZGxlSW5wdXRDaGFuZ2U6IHByb3BzLmhhbmRsZUlucHV0Q2hhbmdlLFxuICAgIGkxOG46IHByb3BzLmkxOG5cbiAgfSksICcgJ10pLCBfdXBweURhc2hib2FyZERyb3BGaWxlc1RpdGxlKSwgJyAnLCAoX3VwcHlEYXNoYm9hcmRJbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0JyksIF91cHB5RGFzaGJvYXJkSW5wdXQuc2V0QXR0cmlidXRlKCd0eXBlJywgJ2ZpbGUnKSwgX3VwcHlEYXNoYm9hcmRJbnB1dC5zZXRBdHRyaWJ1dGUoJ25hbWUnLCAnZmlsZXNbXScpLCAndHJ1ZScgJiYgX3VwcHlEYXNoYm9hcmRJbnB1dC5zZXRBdHRyaWJ1dGUoJ211bHRpcGxlJywgJ211bHRpcGxlJyksIF91cHB5RGFzaGJvYXJkSW5wdXQub25jaGFuZ2UgPSBwcm9wcy5oYW5kbGVJbnB1dENoYW5nZSwgX3VwcHlEYXNoYm9hcmRJbnB1dC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmQtaW5wdXQnKSwgX3VwcHlEYXNoYm9hcmRJbnB1dCksICcgJ10pLCBfdXBweURhc2hib2FyZEJnSWNvbikgOiBudWxsLCAnICcsIE9iamVjdC5rZXlzKHByb3BzLmZpbGVzKS5tYXAoZnVuY3Rpb24gKGZpbGVJRCkge1xuICAgIHJldHVybiBGaWxlSXRlbSh7XG4gICAgICBhY3F1aXJlcnM6IHByb3BzLmFjcXVpcmVycyxcbiAgICAgIGZpbGU6IHByb3BzLmZpbGVzW2ZpbGVJRF0sXG4gICAgICBzaG93RmlsZUNhcmQ6IHByb3BzLnNob3dGaWxlQ2FyZCxcbiAgICAgIHNob3dQcm9ncmVzc0RldGFpbHM6IHByb3BzLnNob3dQcm9ncmVzc0RldGFpbHMsXG4gICAgICBpbmZvOiBwcm9wcy5pbmZvLFxuICAgICAgbG9nOiBwcm9wcy5sb2csXG4gICAgICBpMThuOiBwcm9wcy5pMThuLFxuICAgICAgcmVtb3ZlRmlsZTogcHJvcHMucmVtb3ZlRmlsZSxcbiAgICAgIHBhdXNlVXBsb2FkOiBwcm9wcy5wYXVzZVVwbG9hZCxcbiAgICAgIGNhbmNlbFVwbG9hZDogcHJvcHMuY2FuY2VsVXBsb2FkLFxuICAgICAgcmVzdW1hYmxlVXBsb2FkczogcHJvcHMucmVzdW1hYmxlVXBsb2FkcyxcbiAgICAgIGlzV2lkZTogcHJvcHMuaXNXaWRlXG4gICAgfSk7XG4gIH0pLCAnICddKSwgX3VsO1xufTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPUZpbGVMaXN0LmpzLm1hcCIsIid1c2Ugc3RyaWN0JztcblxudmFyIF9hcHBlbmRDaGlsZCA9IHJlcXVpcmUoJ3lvLXlvaWZ5L2xpYi9hcHBlbmRDaGlsZCcpLFxuICAgIF9zdmdOYW1lc3BhY2UgPSAnaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnO1xuXG52YXIgdGhyb3R0bGUgPSByZXF1aXJlKCdsb2Rhc2gudGhyb3R0bGUnKTtcblxuZnVuY3Rpb24gcHJvZ3Jlc3NCYXJXaWR0aChwcm9wcykge1xuICByZXR1cm4gcHJvcHMudG90YWxQcm9ncmVzcztcbn1cblxuZnVuY3Rpb24gcHJvZ3Jlc3NEZXRhaWxzKHByb3BzKSB7XG4gIHZhciBfc3BhbjtcblxuICAvLyBjb25zb2xlLmxvZyhEYXRlLm5vdygpKVxuICByZXR1cm4gX3NwYW4gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyksIF9hcHBlbmRDaGlsZChfc3BhbiwgW3Byb3BzLnRvdGFsUHJvZ3Jlc3MgfHwgMCwgJyVcXHUzMEZCJywgcHJvcHMuY29tcGxldGUsICcgLyAnLCBwcm9wcy5pblByb2dyZXNzLCAnXFx1MzBGQicsIHByb3BzLnRvdGFsVXBsb2FkZWRTaXplLCAnIC8gJywgcHJvcHMudG90YWxTaXplLCAnXFx1MzBGQlxcdTIxOTEgJywgcHJvcHMudG90YWxTcGVlZCwgJy9zXFx1MzBGQicsIHByb3BzLnRvdGFsRVRBXSksIF9zcGFuO1xufVxuXG52YXIgdGhyb3R0bGVkUHJvZ3Jlc3NEZXRhaWxzID0gdGhyb3R0bGUocHJvZ3Jlc3NEZXRhaWxzLCAxMDAwLCB7IGxlYWRpbmc6IHRydWUsIHRyYWlsaW5nOiB0cnVlIH0pO1xuLy8gY29uc3QgdGhyb3R0bGVkUHJvZ3Jlc3NCYXJXaWR0aCA9IHRocm90dGxlKHByb2dyZXNzQmFyV2lkdGgsIDMwMCwge2xlYWRpbmc6IHRydWUsIHRyYWlsaW5nOiB0cnVlfSlcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAocHJvcHMpIHtcbiAgdmFyIF9wcm9ncmVzcywgX3VwcHlEYXNoYm9hcmRTdGF0dXNCYXJQcm9ncmVzcywgX3VwcHlEYXNoYm9hcmRTdGF0dXNCYXJDb250ZW50LCBfZGl2LCBfc3BhbjIsIF9zcGFuMywgX3BhdGgsIF91cHB5RGFzaGJvYXJkU3RhdHVzQmFyQWN0aW9uLCBfc3BhbjQ7XG5cbiAgcHJvcHMgPSBwcm9wcyB8fCB7fTtcblxuICB2YXIgaXNIaWRkZW4gPSBwcm9wcy50b3RhbEZpbGVDb3VudCA9PT0gMCB8fCAhcHJvcHMuaXNVcGxvYWRTdGFydGVkO1xuXG4gIHJldHVybiBfZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksIF9kaXYuc2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicsICcnICsgU3RyaW5nKGlzSGlkZGVuKSArICcnKSwgX2Rpdi5zZXRBdHRyaWJ1dGUoJ3RpdGxlJywgJycpLCBfZGl2LnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZC1zdGF0dXNCYXJcXG4gICAgICAgICAgICAgICAgJyArIFN0cmluZyhwcm9wcy5pc0FsbENvbXBsZXRlID8gJ2lzLWNvbXBsZXRlJyA6ICcnKSArICcnKSwgX2FwcGVuZENoaWxkKF9kaXYsIFsnICcsIChfcHJvZ3Jlc3MgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdwcm9ncmVzcycpLCBfcHJvZ3Jlc3Muc2V0QXR0cmlidXRlKCdzdHlsZScsICdkaXNwbGF5OiBub25lOycpLCBfcHJvZ3Jlc3Muc2V0QXR0cmlidXRlKCdtaW4nLCAnMCcpLCBfcHJvZ3Jlc3Muc2V0QXR0cmlidXRlKCdtYXgnLCAnMTAwJyksIF9wcm9ncmVzcy5zZXRBdHRyaWJ1dGUoJ3ZhbHVlJywgJycgKyBTdHJpbmcocHJvcHMudG90YWxQcm9ncmVzcykgKyAnJyksIF9wcm9ncmVzcyksICcgJywgKF91cHB5RGFzaGJvYXJkU3RhdHVzQmFyUHJvZ3Jlc3MgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSwgX3VwcHlEYXNoYm9hcmRTdGF0dXNCYXJQcm9ncmVzcy5zZXRBdHRyaWJ1dGUoJ3N0eWxlJywgJ3dpZHRoOiAnICsgU3RyaW5nKHByb2dyZXNzQmFyV2lkdGgocHJvcHMpKSArICclJyksIF91cHB5RGFzaGJvYXJkU3RhdHVzQmFyUHJvZ3Jlc3Muc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkLXN0YXR1c0JhclByb2dyZXNzJyksIF91cHB5RGFzaGJvYXJkU3RhdHVzQmFyUHJvZ3Jlc3MpLCAnICcsIChfdXBweURhc2hib2FyZFN0YXR1c0JhckNvbnRlbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSwgX3VwcHlEYXNoYm9hcmRTdGF0dXNCYXJDb250ZW50LnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZC1zdGF0dXNCYXJDb250ZW50JyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZFN0YXR1c0JhckNvbnRlbnQsIFsnICcsIHByb3BzLmlzVXBsb2FkU3RhcnRlZCAmJiAhcHJvcHMuaXNBbGxDb21wbGV0ZSA/ICFwcm9wcy5pc0FsbFBhdXNlZCA/IChfc3BhbjIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyksIF9zcGFuMi5zZXRBdHRyaWJ1dGUoJ3RpdGxlJywgJ1VwbG9hZGluZycpLCBfYXBwZW5kQ2hpbGQoX3NwYW4yLCBbcGF1c2VSZXN1bWVCdXR0b25zKHByb3BzKSwgJyBVcGxvYWRpbmcuLi4gJywgdGhyb3R0bGVkUHJvZ3Jlc3NEZXRhaWxzKHByb3BzKV0pLCBfc3BhbjIpIDogKF9zcGFuMyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKSwgX3NwYW4zLnNldEF0dHJpYnV0ZSgndGl0bGUnLCAnUGF1c2VkJyksIF9hcHBlbmRDaGlsZChfc3BhbjMsIFtwYXVzZVJlc3VtZUJ1dHRvbnMocHJvcHMpLCAnIFBhdXNlZFxcdTMwRkInLCBwcm9wcy50b3RhbFByb2dyZXNzLCAnJSddKSwgX3NwYW4zKSA6IG51bGwsICcgJywgcHJvcHMuaXNBbGxDb21wbGV0ZSA/IChfc3BhbjQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyksIF9zcGFuNC5zZXRBdHRyaWJ1dGUoJ3RpdGxlJywgJ0NvbXBsZXRlJyksIF9hcHBlbmRDaGlsZChfc3BhbjQsIFsoX3VwcHlEYXNoYm9hcmRTdGF0dXNCYXJBY3Rpb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3N2ZycpLCBfdXBweURhc2hib2FyZFN0YXR1c0JhckFjdGlvbi5zZXRBdHRyaWJ1dGUoJ3dpZHRoJywgJzE4JyksIF91cHB5RGFzaGJvYXJkU3RhdHVzQmFyQWN0aW9uLnNldEF0dHJpYnV0ZSgnaGVpZ2h0JywgJzE3JyksIF91cHB5RGFzaGJvYXJkU3RhdHVzQmFyQWN0aW9uLnNldEF0dHJpYnV0ZSgndmlld0JveCcsICcwIDAgMjMgMTcnKSwgX3VwcHlEYXNoYm9hcmRTdGF0dXNCYXJBY3Rpb24uc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkLXN0YXR1c0JhckFjdGlvbiBVcHB5SWNvbicpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmRTdGF0dXNCYXJBY3Rpb24sIFsnICcsIChfcGF0aCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAncGF0aCcpLCBfcGF0aC5zZXRBdHRyaWJ1dGUoJ2QnLCAnTTguOTQ0IDE3TDAgNy44NjVsMi41NTUtMi42MSA2LjM5IDYuNTI1TDIwLjQxIDAgMjMgMi42NDV6JyksIF9wYXRoKSwgJyAnXSksIF91cHB5RGFzaGJvYXJkU3RhdHVzQmFyQWN0aW9uKSwgJ1VwbG9hZCBjb21wbGV0ZVxcdTMwRkInLCBwcm9wcy50b3RhbFByb2dyZXNzLCAnJSddKSwgX3NwYW40KSA6IG51bGwsICcgJ10pLCBfdXBweURhc2hib2FyZFN0YXR1c0JhckNvbnRlbnQpLCAnICddKSwgX2Rpdjtcbn07XG5cbnZhciBwYXVzZVJlc3VtZUJ1dHRvbnMgPSBmdW5jdGlvbiBwYXVzZVJlc3VtZUJ1dHRvbnMocHJvcHMpIHtcbiAgdmFyIF91cHB5RGFzaGJvYXJkU3RhdHVzQmFyQWN0aW9uMiwgX3BhdGgyLCBfdXBweUljb24sIF9wYXRoMywgX3VwcHlJY29uMiwgX3BhdGg0LCBfdXBweUljb24zO1xuXG4gIHZhciB0aXRsZSA9IHByb3BzLnJlc3VtYWJsZVVwbG9hZHMgPyBwcm9wcy5pc0FsbFBhdXNlZCA/ICdyZXN1bWUgdXBsb2FkJyA6ICdwYXVzZSB1cGxvYWQnIDogJ2NhbmNlbCB1cGxvYWQnO1xuXG4gIHJldHVybiBfdXBweURhc2hib2FyZFN0YXR1c0JhckFjdGlvbjIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdidXR0b24nKSwgX3VwcHlEYXNoYm9hcmRTdGF0dXNCYXJBY3Rpb24yLnNldEF0dHJpYnV0ZSgndGl0bGUnLCAnJyArIFN0cmluZyh0aXRsZSkgKyAnJyksIF91cHB5RGFzaGJvYXJkU3RhdHVzQmFyQWN0aW9uMi5zZXRBdHRyaWJ1dGUoJ3R5cGUnLCAnYnV0dG9uJyksIF91cHB5RGFzaGJvYXJkU3RhdHVzQmFyQWN0aW9uMi5vbmNsaWNrID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0b2dnbGVQYXVzZVJlc3VtZShwcm9wcyk7XG4gIH0sIF91cHB5RGFzaGJvYXJkU3RhdHVzQmFyQWN0aW9uMi5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmQtc3RhdHVzQmFyQWN0aW9uJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZFN0YXR1c0JhckFjdGlvbjIsIFsnICcsIHByb3BzLnJlc3VtYWJsZVVwbG9hZHMgPyBwcm9wcy5pc0FsbFBhdXNlZCA/IChfdXBweUljb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3N2ZycpLCBfdXBweUljb24uc2V0QXR0cmlidXRlKCd3aWR0aCcsICcxNScpLCBfdXBweUljb24uc2V0QXR0cmlidXRlKCdoZWlnaHQnLCAnMTcnKSwgX3VwcHlJY29uLnNldEF0dHJpYnV0ZSgndmlld0JveCcsICcwIDAgMTEgMTMnKSwgX3VwcHlJY29uLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweUljb24nKSwgX2FwcGVuZENoaWxkKF91cHB5SWNvbiwgWycgJywgKF9wYXRoMiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAncGF0aCcpLCBfcGF0aDIuc2V0QXR0cmlidXRlKCdkJywgJ00xLjI2IDEyLjUzNGEuNjcuNjcgMCAwIDEtLjY3NC4wMTIuNjcuNjcgMCAwIDEtLjMzNi0uNTgzdi0xMUMuMjUuNzI0LjM4LjUuNTg2LjM4MmEuNjU4LjY1OCAwIDAgMSAuNjczLjAxMmw5LjE2NSA1LjVhLjY2LjY2IDAgMCAxIC4zMjUuNTcuNjYuNjYgMCAwIDEtLjMyNS41NzNsLTkuMTY2IDUuNXonKSwgX3BhdGgyKSwgJyAnXSksIF91cHB5SWNvbikgOiAoX3VwcHlJY29uMiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAnc3ZnJyksIF91cHB5SWNvbjIuc2V0QXR0cmlidXRlKCd3aWR0aCcsICcxNicpLCBfdXBweUljb24yLnNldEF0dHJpYnV0ZSgnaGVpZ2h0JywgJzE3JyksIF91cHB5SWNvbjIuc2V0QXR0cmlidXRlKCd2aWV3Qm94JywgJzAgMCAxMiAxMycpLCBfdXBweUljb24yLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweUljb24nKSwgX2FwcGVuZENoaWxkKF91cHB5SWNvbjIsIFsnICcsIChfcGF0aDMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3BhdGgnKSwgX3BhdGgzLnNldEF0dHJpYnV0ZSgnZCcsICdNNC44ODguODF2MTEuMzhjMCAuNDQ2LS4zMjQuODEtLjcyMi44MUgyLjcyMkMyLjMyNCAxMyAyIDEyLjYzNiAyIDEyLjE5Vi44MWMwLS40NDYuMzI0LS44MS43MjItLjgxaDEuNDQ0Yy4zOTggMCAuNzIyLjM2NC43MjIuODF6TTkuODg4LjgxdjExLjM4YzAgLjQ0Ni0uMzI0LjgxLS43MjIuODFINy43MjJDNy4zMjQgMTMgNyAxMi42MzYgNyAxMi4xOVYuODFjMC0uNDQ2LjMyNC0uODEuNzIyLS44MWgxLjQ0NGMuMzk4IDAgLjcyMi4zNjQuNzIyLjgxeicpLCBfcGF0aDMpLCAnICddKSwgX3VwcHlJY29uMikgOiAoX3VwcHlJY29uMyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAnc3ZnJyksIF91cHB5SWNvbjMuc2V0QXR0cmlidXRlKCd3aWR0aCcsICcxNnB4JyksIF91cHB5SWNvbjMuc2V0QXR0cmlidXRlKCdoZWlnaHQnLCAnMTZweCcpLCBfdXBweUljb24zLnNldEF0dHJpYnV0ZSgndmlld0JveCcsICcwIDAgMTkgMTknKSwgX3VwcHlJY29uMy5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlJY29uJyksIF9hcHBlbmRDaGlsZChfdXBweUljb24zLCBbJyAnLCAoX3BhdGg0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwYXRoJyksIF9wYXRoNC5zZXRBdHRyaWJ1dGUoJ2QnLCAnTTE3LjMxOCAxNy4yMzJMOS45NCA5Ljg1NCA5LjU4NiA5LjVsLS4zNTQuMzU0LTcuMzc4IDcuMzc4aC43MDdsLS42Mi0uNjJ2LjcwNkw5LjMxOCA5Ljk0bC4zNTQtLjM1NC0uMzU0LS4zNTRMMS45NCAxLjg1NHYuNzA3bC42Mi0uNjJoLS43MDZsNy4zNzggNy4zNzguMzU0LjM1NC4zNTQtLjM1NCA3LjM3OC03LjM3OGgtLjcwN2wuNjIyLjYydi0uNzA2TDkuODU0IDkuMjMybC0uMzU0LjM1NC4zNTQuMzU0IDcuMzc4IDcuMzc4LjcwOC0uNzA3LTcuMzgtNy4zNzh2LjcwOGw3LjM4LTcuMzguMzUzLS4zNTMtLjM1My0uMzUzLS42MjItLjYyMi0uMzUzLS4zNTMtLjM1NC4zNTItNy4zNzggNy4zOGguNzA4TDIuNTYgMS4yMyAyLjIwOC44OGwtLjM1My4zNTMtLjYyMi42Mi0uMzUzLjM1NS4zNTIuMzUzIDcuMzggNy4zOHYtLjcwOGwtNy4zOCA3LjM4LS4zNTMuMzUzLjM1Mi4zNTMuNjIyLjYyMi4zNTMuMzUzLjM1NC0uMzUzIDcuMzgtNy4zOGgtLjcwOGw3LjM4IDcuMzh6JyksIF9wYXRoNCksICcgJ10pLCBfdXBweUljb24zKSwgJyAnXSksIF91cHB5RGFzaGJvYXJkU3RhdHVzQmFyQWN0aW9uMjtcbn07XG5cbnZhciB0b2dnbGVQYXVzZVJlc3VtZSA9IGZ1bmN0aW9uIHRvZ2dsZVBhdXNlUmVzdW1lKHByb3BzKSB7XG4gIGlmIChwcm9wcy5pc0FsbENvbXBsZXRlKSByZXR1cm47XG5cbiAgaWYgKCFwcm9wcy5yZXN1bWFibGVVcGxvYWRzKSB7XG4gICAgcmV0dXJuIHByb3BzLmNhbmNlbEFsbCgpO1xuICB9XG5cbiAgaWYgKHByb3BzLmlzQWxsUGF1c2VkKSB7XG4gICAgcmV0dXJuIHByb3BzLnJlc3VtZUFsbCgpO1xuICB9XG5cbiAgcmV0dXJuIHByb3BzLnBhdXNlQWxsKCk7XG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9U3RhdHVzQmFyLmpzLm1hcCIsIid1c2Ugc3RyaWN0JztcblxudmFyIF9hcHBlbmRDaGlsZCA9IHJlcXVpcmUoJ3lvLXlvaWZ5L2xpYi9hcHBlbmRDaGlsZCcpO1xuXG52YXIgQWN0aW9uQnJvd3NlVGFnbGluZSA9IHJlcXVpcmUoJy4vQWN0aW9uQnJvd3NlVGFnbGluZScpO1xuXG52YXIgX3JlcXVpcmUgPSByZXF1aXJlKCcuL2ljb25zJyksXG4gICAgbG9jYWxJY29uID0gX3JlcXVpcmUubG9jYWxJY29uO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChwcm9wcykge1xuICB2YXIgX3VwcHlEYXNoYm9hcmRJbnB1dCwgX3VwcHlEYXNoYm9hcmRUYWJOYW1lLCBfdXBweURhc2hib2FyZFRhYkJ0biwgX3VwcHlEYXNoYm9hcmRUYWIsIF91cHB5RGFzaGJvYXJkVGFic0xpc3QsIF9uYXYsIF91cHB5RGFzaGJvYXJkVGFiczI7XG5cbiAgdmFyIGlzSGlkZGVuID0gT2JqZWN0LmtleXMocHJvcHMuZmlsZXMpLmxlbmd0aCA9PT0gMDtcblxuICBpZiAocHJvcHMuYWNxdWlyZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgIHZhciBfdXBweURhc2hib2FyZFRhYnNUaXRsZSwgX3VwcHlEYXNoYm9hcmRUYWJzO1xuXG4gICAgcmV0dXJuIF91cHB5RGFzaGJvYXJkVGFicyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLCBfdXBweURhc2hib2FyZFRhYnMuc2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicsICcnICsgU3RyaW5nKGlzSGlkZGVuKSArICcnKSwgX3VwcHlEYXNoYm9hcmRUYWJzLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZFRhYnMnKSwgX2FwcGVuZENoaWxkKF91cHB5RGFzaGJvYXJkVGFicywgWycgJywgKF91cHB5RGFzaGJvYXJkVGFic1RpdGxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaDMnKSwgX3VwcHlEYXNoYm9hcmRUYWJzVGl0bGUuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkVGFicy10aXRsZScpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmRUYWJzVGl0bGUsIFsnICcsIEFjdGlvbkJyb3dzZVRhZ2xpbmUoe1xuICAgICAgYWNxdWlyZXJzOiBwcm9wcy5hY3F1aXJlcnMsXG4gICAgICBoYW5kbGVJbnB1dENoYW5nZTogcHJvcHMuaGFuZGxlSW5wdXRDaGFuZ2UsXG4gICAgICBpMThuOiBwcm9wcy5pMThuXG4gICAgfSksICcgJ10pLCBfdXBweURhc2hib2FyZFRhYnNUaXRsZSksICcgJ10pLCBfdXBweURhc2hib2FyZFRhYnM7XG4gIH1cblxuICB2YXIgaW5wdXQgPSAoX3VwcHlEYXNoYm9hcmRJbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0JyksIF91cHB5RGFzaGJvYXJkSW5wdXQuc2V0QXR0cmlidXRlKCd0eXBlJywgJ2ZpbGUnKSwgX3VwcHlEYXNoYm9hcmRJbnB1dC5zZXRBdHRyaWJ1dGUoJ25hbWUnLCAnZmlsZXNbXScpLCAndHJ1ZScgJiYgX3VwcHlEYXNoYm9hcmRJbnB1dC5zZXRBdHRyaWJ1dGUoJ211bHRpcGxlJywgJ211bHRpcGxlJyksIF91cHB5RGFzaGJvYXJkSW5wdXQub25jaGFuZ2UgPSBwcm9wcy5oYW5kbGVJbnB1dENoYW5nZSwgX3VwcHlEYXNoYm9hcmRJbnB1dC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmQtaW5wdXQnKSwgX3VwcHlEYXNoYm9hcmRJbnB1dCk7XG5cbiAgcmV0dXJuIF91cHB5RGFzaGJvYXJkVGFiczIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSwgX3VwcHlEYXNoYm9hcmRUYWJzMi5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRUYWJzJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZFRhYnMyLCBbJyAnLCAoX25hdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ25hdicpLCBfYXBwZW5kQ2hpbGQoX25hdiwgWycgJywgKF91cHB5RGFzaGJvYXJkVGFic0xpc3QgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd1bCcpLCBfdXBweURhc2hib2FyZFRhYnNMaXN0LnNldEF0dHJpYnV0ZSgncm9sZScsICd0YWJsaXN0JyksIF91cHB5RGFzaGJvYXJkVGFic0xpc3Quc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkVGFicy1saXN0JyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZFRhYnNMaXN0LCBbJyAnLCAoX3VwcHlEYXNoYm9hcmRUYWIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsaScpLCBfdXBweURhc2hib2FyZFRhYi5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRUYWInKSwgX2FwcGVuZENoaWxkKF91cHB5RGFzaGJvYXJkVGFiLCBbJyAnLCAoX3VwcHlEYXNoYm9hcmRUYWJCdG4gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdidXR0b24nKSwgX3VwcHlEYXNoYm9hcmRUYWJCdG4uc2V0QXR0cmlidXRlKCd0eXBlJywgJ2J1dHRvbicpLCBfdXBweURhc2hib2FyZFRhYkJ0bi5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAndGFiJyksIF91cHB5RGFzaGJvYXJkVGFiQnRuLnNldEF0dHJpYnV0ZSgndGFiaW5kZXgnLCAnMCcpLCBfdXBweURhc2hib2FyZFRhYkJ0bi5vbmNsaWNrID0gZnVuY3Rpb24gKGV2KSB7XG4gICAgaW5wdXQuY2xpY2soKTtcbiAgfSwgX3VwcHlEYXNoYm9hcmRUYWJCdG4uc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkVGFiLWJ0biBVcHB5RGFzaGJvYXJkLWZvY3VzJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZFRhYkJ0biwgWycgJywgbG9jYWxJY29uKCksICcgJywgKF91cHB5RGFzaGJvYXJkVGFiTmFtZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2g1JyksIF91cHB5RGFzaGJvYXJkVGFiTmFtZS5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRUYWItbmFtZScpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmRUYWJOYW1lLCBbcHJvcHMuaTE4bignbG9jYWxEaXNrJyldKSwgX3VwcHlEYXNoYm9hcmRUYWJOYW1lKSwgJyAnXSksIF91cHB5RGFzaGJvYXJkVGFiQnRuKSwgJyAnLCBpbnB1dCwgJyAnXSksIF91cHB5RGFzaGJvYXJkVGFiKSwgJyAnLCBwcm9wcy5hY3F1aXJlcnMubWFwKGZ1bmN0aW9uICh0YXJnZXQpIHtcbiAgICB2YXIgX3VwcHlEYXNoYm9hcmRUYWJOYW1lMiwgX3VwcHlEYXNoYm9hcmRUYWJCdG4yLCBfdXBweURhc2hib2FyZFRhYjI7XG5cbiAgICByZXR1cm4gX3VwcHlEYXNoYm9hcmRUYWIyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGknKSwgX3VwcHlEYXNoYm9hcmRUYWIyLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZFRhYicpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEYXNoYm9hcmRUYWIyLCBbJyAnLCAoX3VwcHlEYXNoYm9hcmRUYWJCdG4yID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnV0dG9uJyksIF91cHB5RGFzaGJvYXJkVGFiQnRuMi5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAndGFiJyksIF91cHB5RGFzaGJvYXJkVGFiQnRuMi5zZXRBdHRyaWJ1dGUoJ3RhYmluZGV4JywgJzAnKSwgX3VwcHlEYXNoYm9hcmRUYWJCdG4yLnNldEF0dHJpYnV0ZSgnYXJpYS1jb250cm9scycsICdVcHB5RGFzaGJvYXJkQ29udGVudC1wYW5lbC0tJyArIFN0cmluZyh0YXJnZXQuaWQpICsgJycpLCBfdXBweURhc2hib2FyZFRhYkJ0bjIuc2V0QXR0cmlidXRlKCdhcmlhLXNlbGVjdGVkJywgJycgKyBTdHJpbmcodGFyZ2V0LmlzSGlkZGVuID8gJ2ZhbHNlJyA6ICd0cnVlJykgKyAnJyksIF91cHB5RGFzaGJvYXJkVGFiQnRuMi5vbmNsaWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHByb3BzLnNob3dQYW5lbCh0YXJnZXQuaWQpO1xuICAgIH0sIF91cHB5RGFzaGJvYXJkVGFiQnRuMi5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEYXNoYm9hcmRUYWItYnRuJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZFRhYkJ0bjIsIFsnICcsIHRhcmdldC5pY29uKCksICcgJywgKF91cHB5RGFzaGJvYXJkVGFiTmFtZTIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdoNScpLCBfdXBweURhc2hib2FyZFRhYk5hbWUyLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURhc2hib2FyZFRhYi1uYW1lJyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZFRhYk5hbWUyLCBbdGFyZ2V0Lm5hbWVdKSwgX3VwcHlEYXNoYm9hcmRUYWJOYW1lMiksICcgJ10pLCBfdXBweURhc2hib2FyZFRhYkJ0bjIpLCAnICddKSwgX3VwcHlEYXNoYm9hcmRUYWIyO1xuICB9KSwgJyAnXSksIF91cHB5RGFzaGJvYXJkVGFic0xpc3QpLCAnICddKSwgX25hdiksICcgJ10pLCBfdXBweURhc2hib2FyZFRhYnMyO1xufTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPVRhYnMuanMubWFwIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgX2FwcGVuZENoaWxkID0gcmVxdWlyZSgneW8teW9pZnkvbGliL2FwcGVuZENoaWxkJyk7XG5cbnZhciBfcmVxdWlyZSA9IHJlcXVpcmUoJy4vaWNvbnMnKSxcbiAgICB1cGxvYWRJY29uID0gX3JlcXVpcmUudXBsb2FkSWNvbjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAocHJvcHMpIHtcbiAgdmFyIF91cHB5RGFzaGJvYXJkVXBsb2FkQ291bnQsIF91cHB5QnV0dG9uQ2lyY3VsYXI7XG5cbiAgcHJvcHMgPSBwcm9wcyB8fCB7fTtcblxuICByZXR1cm4gX3VwcHlCdXR0b25DaXJjdWxhciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2J1dHRvbicpLCBfdXBweUJ1dHRvbkNpcmN1bGFyLnNldEF0dHJpYnV0ZSgndHlwZScsICdidXR0b24nKSwgX3VwcHlCdXR0b25DaXJjdWxhci5zZXRBdHRyaWJ1dGUoJ3RpdGxlJywgJycgKyBTdHJpbmcocHJvcHMuaTE4bigndXBsb2FkQWxsTmV3RmlsZXMnKSkgKyAnJyksIF91cHB5QnV0dG9uQ2lyY3VsYXIuc2V0QXR0cmlidXRlKCdhcmlhLWxhYmVsJywgJycgKyBTdHJpbmcocHJvcHMuaTE4bigndXBsb2FkQWxsTmV3RmlsZXMnKSkgKyAnJyksIF91cHB5QnV0dG9uQ2lyY3VsYXIub25jbGljayA9IHByb3BzLnN0YXJ0VXBsb2FkLCBfdXBweUJ1dHRvbkNpcmN1bGFyLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweUJ1dHRvbi0tY2lyY3VsYXJcXG4gICAgICAgICAgICAgICAgICAgVXBweUJ1dHRvbi0tYmx1ZVxcbiAgICAgICAgICAgICAgICAgICBVcHB5RGFzaGJvYXJkLXVwbG9hZCcpLCBfYXBwZW5kQ2hpbGQoX3VwcHlCdXR0b25DaXJjdWxhciwgWycgJywgdXBsb2FkSWNvbigpLCAnICcsIChfdXBweURhc2hib2FyZFVwbG9hZENvdW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3VwJyksIF91cHB5RGFzaGJvYXJkVXBsb2FkQ291bnQuc2V0QXR0cmlidXRlKCd0aXRsZScsICcnICsgU3RyaW5nKHByb3BzLmkxOG4oJ251bWJlck9mU2VsZWN0ZWRGaWxlcycpKSArICcnKSwgX3VwcHlEYXNoYm9hcmRVcGxvYWRDb3VudC5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCAnJyArIFN0cmluZyhwcm9wcy5pMThuKCdudW1iZXJPZlNlbGVjdGVkRmlsZXMnKSkgKyAnJyksIF91cHB5RGFzaGJvYXJkVXBsb2FkQ291bnQuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RGFzaGJvYXJkLXVwbG9hZENvdW50JyksIF9hcHBlbmRDaGlsZChfdXBweURhc2hib2FyZFVwbG9hZENvdW50LCBbJyAnLCBwcm9wcy5uZXdGaWxlQ291bnRdKSwgX3VwcHlEYXNoYm9hcmRVcGxvYWRDb3VudCksICcgJ10pLCBfdXBweUJ1dHRvbkNpcmN1bGFyO1xufTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPVVwbG9hZEJ0bi5qcy5tYXAiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfcmVxdWlyZSA9IHJlcXVpcmUoJy4vaWNvbnMnKSxcbiAgICBpY29uVGV4dCA9IF9yZXF1aXJlLmljb25UZXh0LFxuICAgIGljb25GaWxlID0gX3JlcXVpcmUuaWNvbkZpbGUsXG4gICAgaWNvbkF1ZGlvID0gX3JlcXVpcmUuaWNvbkF1ZGlvLFxuICAgIGljb25WaWRlbyA9IF9yZXF1aXJlLmljb25WaWRlbyxcbiAgICBpY29uUERGID0gX3JlcXVpcmUuaWNvblBERjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBnZXRJY29uQnlNaW1lKGZpbGVUeXBlR2VuZXJhbCwgZmlsZVR5cGVTcGVjaWZpYykge1xuICBpZiAoZmlsZVR5cGVHZW5lcmFsID09PSAndGV4dCcpIHtcbiAgICByZXR1cm4ge1xuICAgICAgY29sb3I6ICcjMDAwJyxcbiAgICAgIGljb246IGljb25UZXh0KClcbiAgICB9O1xuICB9XG5cbiAgaWYgKGZpbGVUeXBlR2VuZXJhbCA9PT0gJ2F1ZGlvJykge1xuICAgIHJldHVybiB7XG4gICAgICBjb2xvcjogJyMxYWJjOWMnLFxuICAgICAgaWNvbjogaWNvbkF1ZGlvKClcbiAgICB9O1xuICB9XG5cbiAgaWYgKGZpbGVUeXBlR2VuZXJhbCA9PT0gJ3ZpZGVvJykge1xuICAgIHJldHVybiB7XG4gICAgICBjb2xvcjogJyMyOTgwYjknLFxuICAgICAgaWNvbjogaWNvblZpZGVvKClcbiAgICB9O1xuICB9XG5cbiAgaWYgKGZpbGVUeXBlR2VuZXJhbCA9PT0gJ2FwcGxpY2F0aW9uJyAmJiBmaWxlVHlwZVNwZWNpZmljID09PSAncGRmJykge1xuICAgIHJldHVybiB7XG4gICAgICBjb2xvcjogJyNlNzRjM2MnLFxuICAgICAgaWNvbjogaWNvblBERigpXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgY29sb3I6ICcjMDAwJyxcbiAgICBpY29uOiBpY29uRmlsZSgpXG4gIH07XG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Z2V0RmlsZVR5cGVJY29uLmpzLm1hcCIsIid1c2Ugc3RyaWN0JztcblxudmFyIF9zdmdOYW1lc3BhY2UgPSAnaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnLFxuICAgIF9hcHBlbmRDaGlsZCA9IHJlcXVpcmUoJ3lvLXlvaWZ5L2xpYi9hcHBlbmRDaGlsZCcpO1xuXG4vLyBodHRwczovL2Nzcy10cmlja3MuY29tL2NyZWF0aW5nLXN2Zy1pY29uLXN5c3RlbS1yZWFjdC9cblxuZnVuY3Rpb24gZGVmYXVsdFRhYkljb24oKSB7XG4gIHZhciBfcGF0aCwgX3VwcHlJY29uO1xuXG4gIHJldHVybiBfdXBweUljb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3N2ZycpLCBfdXBweUljb24uc2V0QXR0cmlidXRlKCd3aWR0aCcsICczMCcpLCBfdXBweUljb24uc2V0QXR0cmlidXRlKCdoZWlnaHQnLCAnMzAnKSwgX3VwcHlJY29uLnNldEF0dHJpYnV0ZSgndmlld0JveCcsICcwIDAgMzAgMzAnKSwgX3VwcHlJY29uLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweUljb24nKSwgX2FwcGVuZENoaWxkKF91cHB5SWNvbiwgWycgJywgKF9wYXRoID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwYXRoJyksIF9wYXRoLnNldEF0dHJpYnV0ZSgnZCcsICdNMTUgMzBjOC4yODQgMCAxNS02LjcxNiAxNS0xNSAwLTguMjg0LTYuNzE2LTE1LTE1LTE1QzYuNzE2IDAgMCA2LjcxNiAwIDE1YzAgOC4yODQgNi43MTYgMTUgMTUgMTV6bTQuMjU4LTEyLjY3NnY2Ljg0NmgtOC40MjZ2LTYuODQ2SDUuMjA0bDkuODItMTIuMzY0IDkuODIgMTIuMzY0SDE5LjI2eicpLCBfcGF0aCksICcgJ10pLCBfdXBweUljb247XG59XG5cbmZ1bmN0aW9uIGljb25Db3B5KCkge1xuICB2YXIgX3BhdGgyLCBfcGF0aDMsIF91cHB5SWNvbjI7XG5cbiAgcmV0dXJuIF91cHB5SWNvbjIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3N2ZycpLCBfdXBweUljb24yLnNldEF0dHJpYnV0ZSgnd2lkdGgnLCAnNTEnKSwgX3VwcHlJY29uMi5zZXRBdHRyaWJ1dGUoJ2hlaWdodCcsICc1MScpLCBfdXBweUljb24yLnNldEF0dHJpYnV0ZSgndmlld0JveCcsICcwIDAgNTEgNTEnKSwgX3VwcHlJY29uMi5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlJY29uJyksIF9hcHBlbmRDaGlsZChfdXBweUljb24yLCBbJyAnLCAoX3BhdGgyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwYXRoJyksIF9wYXRoMi5zZXRBdHRyaWJ1dGUoJ2QnLCAnTTE3LjIxIDQ1Ljc2NWE1LjM5NCA1LjM5NCAwIDAgMS03LjYyIDBsLTQuMTItNC4xMjJhNS4zOTMgNS4zOTMgMCAwIDEgMC03LjYxOGw2Ljc3NC02Ljc3NS0yLjQwNC0yLjQwNC02Ljc3NSA2Ljc3NmMtMy40MjQgMy40MjctMy40MjQgOSAwIDEyLjQyNmw0LjEyIDQuMTIzYTguNzY2IDguNzY2IDAgMCAwIDYuMjE2IDIuNTdjMi4yNSAwIDQuNS0uODU4IDYuMjE0LTIuNTdsMTMuNTUtMTMuNTUyYTguNzIgOC43MiAwIDAgMCAyLjU3NS02LjIxMyA4LjczIDguNzMgMCAwIDAtMi41NzUtNi4yMTNsLTQuMTIzLTQuMTItMi40MDQgMi40MDQgNC4xMjMgNC4xMmE1LjM1MiA1LjM1MiAwIDAgMSAxLjU4IDMuODFjMCAxLjQzOC0uNTYyIDIuNzktMS41OCAzLjgwOGwtMTMuNTUgMTMuNTV6JyksIF9wYXRoMiksICcgJywgKF9wYXRoMyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAncGF0aCcpLCBfcGF0aDMuc2V0QXR0cmlidXRlKCdkJywgJ000NC4yNTYgMi44NThBOC43MjggOC43MjggMCAwIDAgMzguMDQzLjI4M2gtLjAwMmE4LjczIDguNzMgMCAwIDAtNi4yMTIgMi41NzRsLTEzLjU1IDEzLjU1YTguNzI1IDguNzI1IDAgMCAwLTIuNTc1IDYuMjE0IDguNzMgOC43MyAwIDAgMCAyLjU3NCA2LjIxNmw0LjEyIDQuMTIgMi40MDUtMi40MDMtNC4xMi00LjEyYTUuMzU3IDUuMzU3IDAgMCAxLTEuNTgtMy44MTJjMC0xLjQzNy41NjItMi43OSAxLjU4LTMuODA4bDEzLjU1LTEzLjU1YTUuMzQ4IDUuMzQ4IDAgMCAxIDMuODEtMS41OGMxLjQ0IDAgMi43OTIuNTYyIDMuODEgMS41OGw0LjEyIDQuMTJjMi4xIDIuMSAyLjEgNS41MTggMCA3LjYxN0wzOS4yIDIzLjc3NWwyLjQwNCAyLjQwNCA2Ljc3NS02Ljc3N2MzLjQyNi0zLjQyNyAzLjQyNi05IDAtMTIuNDI2bC00LjEyLTQuMTJ6JyksIF9wYXRoMyksICcgJ10pLCBfdXBweUljb24yO1xufVxuXG5mdW5jdGlvbiBpY29uUmVzdW1lKCkge1xuICB2YXIgX3BsYXksIF91cHB5SWNvbjM7XG5cbiAgcmV0dXJuIF91cHB5SWNvbjMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3N2ZycpLCBfdXBweUljb24zLnNldEF0dHJpYnV0ZSgnd2lkdGgnLCAnMjUnKSwgX3VwcHlJY29uMy5zZXRBdHRyaWJ1dGUoJ2hlaWdodCcsICcyNScpLCBfdXBweUljb24zLnNldEF0dHJpYnV0ZSgndmlld0JveCcsICcwIDAgNDQgNDQnKSwgX3VwcHlJY29uMy5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlJY29uJyksIF9hcHBlbmRDaGlsZChfdXBweUljb24zLCBbJyAnLCAoX3BsYXkgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3BvbHlnb24nKSwgX3BsYXkuc2V0QXR0cmlidXRlKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKDYsIDUuNSknKSwgX3BsYXkuc2V0QXR0cmlidXRlKCdwb2ludHMnLCAnMTMgMjEuNjY2NjY2NyAxMyAxMSAyMSAxNi4zMzMzMzMzJyksIF9wbGF5LnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAncGxheScpLCBfcGxheSksICcgJ10pLCBfdXBweUljb24zO1xufVxuXG5mdW5jdGlvbiBpY29uUGF1c2UoKSB7XG4gIHZhciBfcmVjdCwgX3JlY3QyLCBfcGF1c2UsIF91cHB5SWNvbjQ7XG5cbiAgcmV0dXJuIF91cHB5SWNvbjQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3N2ZycpLCBfdXBweUljb240LnNldEF0dHJpYnV0ZSgnd2lkdGgnLCAnMjVweCcpLCBfdXBweUljb240LnNldEF0dHJpYnV0ZSgnaGVpZ2h0JywgJzI1cHgnKSwgX3VwcHlJY29uNC5zZXRBdHRyaWJ1dGUoJ3ZpZXdCb3gnLCAnMCAwIDQ0IDQ0JyksIF91cHB5SWNvbjQuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5SWNvbicpLCBfYXBwZW5kQ2hpbGQoX3VwcHlJY29uNCwgWycgJywgKF9wYXVzZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAnZycpLCBfcGF1c2Uuc2V0QXR0cmlidXRlKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKDE4LCAxNyknKSwgX3BhdXNlLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAncGF1c2UnKSwgX2FwcGVuZENoaWxkKF9wYXVzZSwgWycgJywgKF9yZWN0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdyZWN0JyksIF9yZWN0LnNldEF0dHJpYnV0ZSgneCcsICcwJyksIF9yZWN0LnNldEF0dHJpYnV0ZSgneScsICcwJyksIF9yZWN0LnNldEF0dHJpYnV0ZSgnd2lkdGgnLCAnMicpLCBfcmVjdC5zZXRBdHRyaWJ1dGUoJ2hlaWdodCcsICcxMCcpLCBfcmVjdC5zZXRBdHRyaWJ1dGUoJ3J4JywgJzAnKSwgX3JlY3QpLCAnICcsIChfcmVjdDIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3JlY3QnKSwgX3JlY3QyLnNldEF0dHJpYnV0ZSgneCcsICc2JyksIF9yZWN0Mi5zZXRBdHRyaWJ1dGUoJ3knLCAnMCcpLCBfcmVjdDIuc2V0QXR0cmlidXRlKCd3aWR0aCcsICcyJyksIF9yZWN0Mi5zZXRBdHRyaWJ1dGUoJ2hlaWdodCcsICcxMCcpLCBfcmVjdDIuc2V0QXR0cmlidXRlKCdyeCcsICcwJyksIF9yZWN0MiksICcgJ10pLCBfcGF1c2UpLCAnICddKSwgX3VwcHlJY29uNDtcbn1cblxuZnVuY3Rpb24gaWNvbkVkaXQoKSB7XG4gIHZhciBfcGF0aDQsIF91cHB5SWNvbjU7XG5cbiAgcmV0dXJuIF91cHB5SWNvbjUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3N2ZycpLCBfdXBweUljb241LnNldEF0dHJpYnV0ZSgnd2lkdGgnLCAnMjgnKSwgX3VwcHlJY29uNS5zZXRBdHRyaWJ1dGUoJ2hlaWdodCcsICcyOCcpLCBfdXBweUljb241LnNldEF0dHJpYnV0ZSgndmlld0JveCcsICcwIDAgMjggMjgnKSwgX3VwcHlJY29uNS5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlJY29uJyksIF9hcHBlbmRDaGlsZChfdXBweUljb241LCBbJyAnLCAoX3BhdGg0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwYXRoJyksIF9wYXRoNC5zZXRBdHRyaWJ1dGUoJ2QnLCAnTTI1LjQzNiAyLjU2NmE3Ljk4IDcuOTggMCAwIDAtMi4wNzgtMS41MUMyMi42MzguNzAzIDIxLjkwNi41IDIxLjE5OC41YTMgMyAwIDAgMC0xLjAyMy4xNyAyLjQzNiAyLjQzNiAwIDAgMC0uODkzLjU2MkwyLjI5MiAxOC4yMTcuNSAyNy41bDkuMjgtMS43OTYgMTYuOTktMTYuOTljLjI1NS0uMjU0LjQ0NC0uNTYuNTYyLS44ODhhMyAzIDAgMCAwIC4xNy0xLjAyM2MwLS43MDgtLjIwNS0xLjQ0LS41NTUtMi4xNmE4IDggMCAwIDAtMS41MS0yLjA3N3pNOS4wMSAyNC4yNTJsLTQuMzEzLjgzNGMwLS4wMy4wMDgtLjA2LjAxMi0uMDkuMDA3LS45NDQtLjc0LTEuNzE1LTEuNjctMS43MjMtLjA0IDAtLjA3OC4wMDctLjExOC4wMWwuODMtNC4yOUwxNy43MiA1LjAyNGw1LjI2NCA1LjI2NEw5LjAxIDI0LjI1MnptMTYuODQtMTYuOTZhLjgxOC44MTggMCAwIDEtLjE5NC4zMWwtMS41NyAxLjU3LTUuMjYtNS4yNiAxLjU3LTEuNTdhLjgyLjgyIDAgMCAxIC4zMS0uMTk0IDEuNDUgMS40NSAwIDAgMSAuNDkyLS4wNzRjLjM5NyAwIC45MTcuMTI2IDEuNDY4LjM5Ny41NS4yNyAxLjEzLjY3OCAxLjY1NiAxLjIxLjUzLjUzLjk0IDEuMTEgMS4yMDggMS42NTUuMjcyLjU1LjM5NyAxLjA3LjM5MyAxLjQ2OC4wMDQuMTkzLS4wMjcuMzU4LS4wNzQuNDg4eicpLCBfcGF0aDQpLCAnICddKSwgX3VwcHlJY29uNTtcbn1cblxuZnVuY3Rpb24gbG9jYWxJY29uKCkge1xuICB2YXIgX3BhdGg1LCBfcGF0aDYsIF91cHB5SWNvbjY7XG5cbiAgcmV0dXJuIF91cHB5SWNvbjYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3N2ZycpLCBfdXBweUljb242LnNldEF0dHJpYnV0ZSgnd2lkdGgnLCAnMjcnKSwgX3VwcHlJY29uNi5zZXRBdHRyaWJ1dGUoJ2hlaWdodCcsICcyNScpLCBfdXBweUljb242LnNldEF0dHJpYnV0ZSgndmlld0JveCcsICcwIDAgMjcgMjUnKSwgX3VwcHlJY29uNi5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlJY29uJyksIF9hcHBlbmRDaGlsZChfdXBweUljb242LCBbJyAnLCAoX3BhdGg1ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwYXRoJyksIF9wYXRoNS5zZXRBdHRyaWJ1dGUoJ2QnLCAnTTUuNTg2IDkuMjg4YS4zMTMuMzEzIDAgMCAwIC4yODIuMTc2aDQuODR2My45MjJjMCAxLjUxNCAxLjI1IDIuMjQgMi43OTIgMi4yNCAxLjU0IDAgMi43OS0uNzI2IDIuNzktMi4yNFY5LjQ2NGg0Ljg0Yy4xMjIgMCAuMjMtLjA2OC4yODQtLjE3NmEuMzA0LjMwNCAwIDAgMC0uMDQ2LS4zMjRMMTMuNzM1LjEwNmEuMzE2LjMxNiAwIDAgMC0uNDcyIDBsLTcuNjMgOC44NTdhLjMwMi4zMDIgMCAwIDAtLjA0Ny4zMjV6JyksIF9wYXRoNSksICcgJywgKF9wYXRoNiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAncGF0aCcpLCBfcGF0aDYuc2V0QXR0cmlidXRlKCdkJywgJ00yNC4zIDUuMDkzYy0uMjE4LS43Ni0uNTQtMS4xODctMS4yMDgtMS4xODdoLTQuODU2bDEuMDE4IDEuMThoMy45NDhsMi4wNDMgMTEuMDM4aC03LjE5M3YyLjcyOEg5LjExNHYtMi43MjVoLTcuMzZsMi42Ni0xMS4wNGgzLjMzbDEuMDE4LTEuMThIMy45MDdjLS42NjggMC0xLjA2LjQ2LTEuMjEgMS4xODZMMCAxNi40NTZ2Ny4wNjJDMCAyNC4zMzguNjc2IDI1IDEuNTEgMjVoMjMuOThjLjgzMyAwIDEuNTEtLjY2MyAxLjUxLTEuNDgydi03LjA2MkwyNC4zIDUuMDkzeicpLCBfcGF0aDYpLCAnICddKSwgX3VwcHlJY29uNjtcbn1cblxuZnVuY3Rpb24gY2xvc2VJY29uKCkge1xuICB2YXIgX3BhdGg3LCBfdXBweUljb243O1xuXG4gIHJldHVybiBfdXBweUljb243ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdzdmcnKSwgX3VwcHlJY29uNy5zZXRBdHRyaWJ1dGUoJ3dpZHRoJywgJzE0cHgnKSwgX3VwcHlJY29uNy5zZXRBdHRyaWJ1dGUoJ2hlaWdodCcsICcxNHB4JyksIF91cHB5SWNvbjcuc2V0QXR0cmlidXRlKCd2aWV3Qm94JywgJzAgMCAxOSAxOScpLCBfdXBweUljb243LnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweUljb24nKSwgX2FwcGVuZENoaWxkKF91cHB5SWNvbjcsIFsnICcsIChfcGF0aDcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3BhdGgnKSwgX3BhdGg3LnNldEF0dHJpYnV0ZSgnZCcsICdNMTcuMzE4IDE3LjIzMkw5Ljk0IDkuODU0IDkuNTg2IDkuNWwtLjM1NC4zNTQtNy4zNzggNy4zNzhoLjcwN2wtLjYyLS42MnYuNzA2TDkuMzE4IDkuOTRsLjM1NC0uMzU0LS4zNTQtLjM1NEwxLjk0IDEuODU0di43MDdsLjYyLS42MmgtLjcwNmw3LjM3OCA3LjM3OC4zNTQuMzU0LjM1NC0uMzU0IDcuMzc4LTcuMzc4aC0uNzA3bC42MjIuNjJ2LS43MDZMOS44NTQgOS4yMzJsLS4zNTQuMzU0LjM1NC4zNTQgNy4zNzggNy4zNzguNzA4LS43MDctNy4zOC03LjM3OHYuNzA4bDcuMzgtNy4zOC4zNTMtLjM1My0uMzUzLS4zNTMtLjYyMi0uNjIyLS4zNTMtLjM1My0uMzU0LjM1Mi03LjM3OCA3LjM4aC43MDhMMi41NiAxLjIzIDIuMjA4Ljg4bC0uMzUzLjM1My0uNjIyLjYyLS4zNTMuMzU1LjM1Mi4zNTMgNy4zOCA3LjM4di0uNzA4bC03LjM4IDcuMzgtLjM1My4zNTMuMzUyLjM1My42MjIuNjIyLjM1My4zNTMuMzU0LS4zNTMgNy4zOC03LjM4aC0uNzA4bDcuMzggNy4zOHonKSwgX3BhdGg3KSwgJyAnXSksIF91cHB5SWNvbjc7XG59XG5cbmZ1bmN0aW9uIHBsdWdpbkljb24oKSB7XG4gIHZhciBfcGF0aDgsIF9wYXRoOSwgX3VwcHlJY29uODtcblxuICByZXR1cm4gX3VwcHlJY29uOCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAnc3ZnJyksIF91cHB5SWNvbjguc2V0QXR0cmlidXRlKCd3aWR0aCcsICcxNnB4JyksIF91cHB5SWNvbjguc2V0QXR0cmlidXRlKCdoZWlnaHQnLCAnMTZweCcpLCBfdXBweUljb244LnNldEF0dHJpYnV0ZSgndmlld0JveCcsICcwIDAgMzIgMzAnKSwgX3VwcHlJY29uOC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlJY29uJyksIF9hcHBlbmRDaGlsZChfdXBweUljb244LCBbJyAnLCAoX3BhdGg4ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwYXRoJyksIF9wYXRoOC5zZXRBdHRyaWJ1dGUoJ2QnLCAnTTYuNjIwOTg5NCwxMS4xNDUxMTYyIEM2LjY4MjMwNTEsMTEuMjc1MTY2OSA2LjgxMzc0MjQ4LDExLjM1NzIxODggNi45NTQ2MzgxMywxMS4zNTcyMTg4IEwxMi42OTI1NDgyLDExLjM1NzIxODggTDEyLjY5MjU0ODIsMTYuMDYzMDQyNyBDMTIuNjkyNTQ4MiwxNy44ODA1MDkgMTQuMTcyNjA0OCwxOC43NSAxNi4wMDAwMDgzLDE4Ljc1IEMxNy44MjYxMDcyLDE4Ljc1IDE5LjMwNzQ2ODQsMTcuODgwMTg0NyAxOS4zMDc0Njg0LDE2LjA2MzA0MjcgTDE5LjMwNzQ2ODQsMTEuMzU3MjE4OCBMMjUuMDQzNzQ3OCwxMS4zNTcyMTg4IEMyNS4xODc1Nzg3LDExLjM1NzIxODggMjUuMzE2NDA2OSwxMS4yNzUxNjY5IDI1LjM3OTAyNzIsMTEuMTQ1MTE2MiBDMjUuNDM3MDgxNCwxMS4wMTczMzU4IDI1LjQxNzE4NjUsMTAuODY0MjU4NyAyNS4zMjUyMTI5LDEwLjc1NjI2MTUgTDE2LjI3ODIxMiwwLjEyNzEzMTgzNyBDMTYuMjA5Mzk0OSwwLjA0NjM3NzE3NTEgMTYuMTA2OTg0NiwwIDE1Ljk5OTY4MjIsMCBDMTUuODkxMDc1MSwwIDE1Ljc4ODY2NDgsMC4wNDYzNzcxNzUxIDE1LjcxODIxNywwLjEyNzEzMTgzNyBMNi42NzYxMDgzLDEwLjc1NTkzNzEgQzYuNTgyNTA0MDIsMTAuODY0MjU4NyA2LjU2MjkzNTE4LDExLjAxNzMzNTggNi42MjA5ODk0LDExLjE0NTExNjIgTDYuNjIwOTg5NCwxMS4xNDUxMTYyIFonKSwgX3BhdGg4KSwgJyAnLCAoX3BhdGg5ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwYXRoJyksIF9wYXRoOS5zZXRBdHRyaWJ1dGUoJ2QnLCAnTTI4LjgwMDg3MjIsNi4xMTE0MjY0NSBDMjguNTQxNzg5MSw1LjE5ODMxNTU1IDI4LjE1ODMzMzEsNC42ODc1IDI3LjM2ODQ4NDgsNC42ODc1IEwyMS42MTI0NDU0LDQuNjg3NSBMMjIuODE5MDIzNCw2LjEwMzA3ODc0IEwyNy40OTg2NzI1LDYuMTAzMDc4NzQgTDI5LjkxOTU4MTcsMTkuMzQ4NjQ0OSBMMjEuMzk0Mzg5MSwxOS4zNTAyNTAyIEwyMS4zOTQzODkxLDIyLjYyMjU1MiBMMTAuODAyMzQ2MSwyMi42MjI1NTIgTDEwLjgwMjM0NjEsMTkuMzUyNDk3NyBMMi4wNzgxNTcwMiwxOS4zNTM0NjA5IEw1LjIyOTc5Njk5LDYuMTAzMDc4NzQgTDkuMTc4NzE1MjksNi4xMDMwNzg3NCBMMTAuMzg0MDAxMSw0LjY4NzUgTDQuNjMwODY5MSw0LjY4NzUgQzMuODM5NDA1NTksNC42ODc1IDMuMzc0MjE4ODgsNS4yMzkwOTA5IDMuMTk4MTU4NjQsNi4xMTE0MjY0NSBMMCwxOS43NDcwODc0IEwwLDI4LjIyMTI5NTkgQzAsMjkuMjA0Mzk5MiAwLjgwMTQ3NzkzNywzMCAxLjc4ODcwNzUxLDMwIEwzMC4yMDk2NzczLDMwIEMzMS4xOTgxOTksMzAgMzIsMjkuMjA0Mzk5MiAzMiwyOC4yMjEyOTU5IEwzMiwxOS43NDcwODc0IEwyOC44MDA4NzIyLDYuMTExNDI2NDUgTDI4LjgwMDg3MjIsNi4xMTE0MjY0NSBaJyksIF9wYXRoOSksICcgJ10pLCBfdXBweUljb244O1xufVxuXG5mdW5jdGlvbiBjaGVja0ljb24oKSB7XG4gIHZhciBfcG9seWdvbiwgX3VwcHlJY29uOTtcblxuICByZXR1cm4gX3VwcHlJY29uOSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAnc3ZnJyksIF91cHB5SWNvbjkuc2V0QXR0cmlidXRlKCd3aWR0aCcsICcxM3B4JyksIF91cHB5SWNvbjkuc2V0QXR0cmlidXRlKCdoZWlnaHQnLCAnOXB4JyksIF91cHB5SWNvbjkuc2V0QXR0cmlidXRlKCd2aWV3Qm94JywgJzAgMCAxMyA5JyksIF91cHB5SWNvbjkuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5SWNvbiBVcHB5SWNvbi1jaGVjaycpLCBfYXBwZW5kQ2hpbGQoX3VwcHlJY29uOSwgWycgJywgKF9wb2x5Z29uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwb2x5Z29uJyksIF9wb2x5Z29uLnNldEF0dHJpYnV0ZSgncG9pbnRzJywgJzUgNy4yOTMgMS4zNTQgMy42NDcgMC42NDYgNC4zNTQgNSA4LjcwNyAxMi4zNTQgMS4zNTQgMTEuNjQ2IDAuNjQ3JyksIF9wb2x5Z29uKV0pLCBfdXBweUljb245O1xufVxuXG5mdW5jdGlvbiBpY29uQXVkaW8oKSB7XG4gIHZhciBfcGF0aDEwLCBfdXBweUljb24xMDtcblxuICByZXR1cm4gX3VwcHlJY29uMTAgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3N2ZycpLCBfdXBweUljb24xMC5zZXRBdHRyaWJ1dGUoJ3ZpZXdCb3gnLCAnMCAwIDU1IDU1JyksIF91cHB5SWNvbjEwLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweUljb24nKSwgX2FwcGVuZENoaWxkKF91cHB5SWNvbjEwLCBbJyAnLCAoX3BhdGgxMCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAncGF0aCcpLCBfcGF0aDEwLnNldEF0dHJpYnV0ZSgnZCcsICdNNTIuNjYuMjVjLS4yMTYtLjE5LS41LS4yNzYtLjc5LS4yNDJsLTMxIDQuMDFhMSAxIDAgMCAwLS44Ny45OTJWNDAuNjIyQzE4LjE3NCAzOC40MjggMTUuMjczIDM3IDEyIDM3Yy01LjUxNCAwLTEwIDQuMDM3LTEwIDlzNC40ODYgOSAxMCA5IDEwLTQuMDM3IDEwLTljMC0uMjMyLS4wMi0uNDYtLjA0LS42ODcuMDE0LS4wNjUuMDQtLjEyNC4wNC0uMTkyVjE2LjEybDI5LTMuNzUzdjE4LjI1N0M0OS4xNzQgMjguNDI4IDQ2LjI3MyAyNyA0MyAyN2MtNS41MTQgMC0xMCA0LjAzNy0xMCA5czQuNDg2IDkgMTAgOWM1LjQ2NCAwIDkuOTEzLTMuOTY2IDkuOTkzLTguODY3IDAtLjAxMy4wMDctLjAyNC4wMDctLjAzN1YxYS45OTguOTk4IDAgMCAwLS4zNC0uNzV6TTEyIDUzYy00LjQxIDAtOC0zLjE0LTgtN3MzLjU5LTcgOC03IDggMy4xNCA4IDctMy41OSA3LTggN3ptMzEtMTBjLTQuNDEgMC04LTMuMTQtOC03czMuNTktNyA4LTcgOCAzLjE0IDggNy0zLjU5IDctOCA3ek0yMiAxNC4xVjUuODlsMjktMy43NTN2OC4yMWwtMjkgMy43NTR6JyksIF9wYXRoMTApLCAnICddKSwgX3VwcHlJY29uMTA7XG59XG5cbmZ1bmN0aW9uIGljb25WaWRlbygpIHtcbiAgdmFyIF9wYXRoMTEsIF9wYXRoMTIsIF91cHB5SWNvbjExO1xuXG4gIHJldHVybiBfdXBweUljb24xMSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAnc3ZnJyksIF91cHB5SWNvbjExLnNldEF0dHJpYnV0ZSgndmlld0JveCcsICcwIDAgNTggNTgnKSwgX3VwcHlJY29uMTEuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5SWNvbicpLCBfYXBwZW5kQ2hpbGQoX3VwcHlJY29uMTEsIFsnICcsIChfcGF0aDExID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwYXRoJyksIF9wYXRoMTEuc2V0QXR0cmlidXRlKCdkJywgJ00zNi41MzcgMjguMTU2bC0xMS03YTEuMDA1IDEuMDA1IDAgMCAwLTEuMDItLjAzM0MyNC4yIDIxLjMgMjQgMjEuNjM1IDI0IDIydjE0YTEgMSAwIDAgMCAxLjUzNy44NDRsMTEtN2ExLjAwMiAxLjAwMiAwIDAgMCAwLTEuNjg4ek0yNiAzNC4xOFYyMy44MkwzNC4xMzcgMjkgMjYgMzQuMTh6JyksIF9wYXRoMTEpLCAoX3BhdGgxMiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAncGF0aCcpLCBfcGF0aDEyLnNldEF0dHJpYnV0ZSgnZCcsICdNNTcgNkgxYTEgMSAwIDAgMC0xIDF2NDRhMSAxIDAgMCAwIDEgMWg1NmExIDEgMCAwIDAgMS0xVjdhMSAxIDAgMCAwLTEtMXpNMTAgMjhIMnYtOWg4djl6bS04IDJoOHY5SDJ2LTl6bTEwIDEwVjhoMzR2NDJIMTJWNDB6bTQ0LTEyaC04di05aDh2OXptLTggMmg4djloLTh2LTl6bTgtMjJ2OWgtOFY4aDh6TTIgOGg4djlIMlY4em0wIDQydi05aDh2OUgyem01NCAwaC04di05aDh2OXonKSwgX3BhdGgxMiksICcgJ10pLCBfdXBweUljb24xMTtcbn1cblxuZnVuY3Rpb24gaWNvblBERigpIHtcbiAgdmFyIF9wYXRoMTMsIF91cHB5SWNvbjEyO1xuXG4gIHJldHVybiBfdXBweUljb24xMiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAnc3ZnJyksIF91cHB5SWNvbjEyLnNldEF0dHJpYnV0ZSgndmlld0JveCcsICcwIDAgMzQyIDMzNScpLCBfdXBweUljb24xMi5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlJY29uJyksIF9hcHBlbmRDaGlsZChfdXBweUljb24xMiwgWycgJywgKF9wYXRoMTMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3BhdGgnKSwgX3BhdGgxMy5zZXRBdHRyaWJ1dGUoJ2QnLCAnTTMyOS4zMzcgMjI3Ljg0Yy0yLjEgMS4zLTguMSAyLjEtMTEuOSAyLjEtMTIuNCAwLTI3LjYtNS43LTQ5LjEtMTQuOSA4LjMtLjYgMTUuOC0uOSAyMi42LS45IDEyLjQgMCAxNiAwIDI4LjIgMy4xIDEyLjEgMyAxMi4yIDkuMyAxMC4yIDEwLjZ6bS0yMTUuMSAxLjljNC44LTguNCA5LjctMTcuMyAxNC43LTI2LjggMTIuMi0yMy4xIDIwLTQxLjMgMjUuNy01Ni4yIDExLjUgMjAuOSAyNS44IDM4LjYgNDIuNSA1Mi44IDIuMSAxLjggNC4zIDMuNSA2LjcgNS4zLTM0LjEgNi44LTYzLjYgMTUtODkuNiAyNC45em0zOS44LTIxOC45YzYuOCAwIDEwLjcgMTcuMDYgMTEgMzMuMTYuMyAxNi0zLjQgMjcuMi04LjEgMzUuNi0zLjktMTIuNC01LjctMzEuOC01LjctNDQuNSAwIDAtLjMtMjQuMjYgMi44LTI0LjI2em0tMTMzLjQgMzA3LjJjMy45LTEwLjUgMTkuMS0zMS4zIDQxLjYtNDkuOCAxLjQtMS4xIDQuOS00LjQgOC4xLTcuNC0yMy41IDM3LjYtMzkuMyA1Mi41LTQ5LjcgNTcuMnptMzE1LjItMTEyLjNjLTYuOC02LjctMjItMTAuMi00NS0xMC41LTE1LjYtLjItMzQuMyAxLjItNTQuMSAzLjktOC44LTUuMS0xNy45LTEwLjYtMjUuMS0xNy4zLTE5LjItMTgtMzUuMi00Mi45LTQ1LjItNzAuMy42LTIuNiAxLjItNC44IDEuNy03LjEgMCAwIDEwLjgtNjEuNSA3LjktODIuMy0uNC0yLjktLjYtMy43LTEuNC01LjlsLS45LTIuNWMtMi45LTYuNzYtOC43LTEzLjk2LTE3LjgtMTMuNTdsLTUuMy0uMTdoLS4xYy0xMC4xIDAtMTguNCA1LjE3LTIwLjUgMTIuODQtNi42IDI0LjMuMiA2MC41IDEyLjUgMTA3LjRsLTMuMiA3LjdjLTguOCAyMS40LTE5LjggNDMtMjkuNSA2MmwtMS4zIDIuNWMtMTAuMiAyMC0xOS41IDM3LTI3LjkgNTEuNGwtOC43IDQuNmMtLjYuNC0xNS41IDguMi0xOSAxMC4zLTI5LjYgMTcuNy00OS4yOCAzNy44LTUyLjU0IDUzLjgtMS4wNCA1LS4yNiAxMS41IDUuMDEgMTQuNmw4LjQgNC4yYzMuNjMgMS44IDcuNTMgMi43IDExLjQzIDIuNyAyMS4xIDAgNDUuNi0yNi4yIDc5LjMtODUuMSAzOS0xMi43IDgzLjQtMjMuMyAxMjIuMy0yOS4xIDI5LjYgMTYuNyA2NiAyOC4zIDg5IDI4LjMgNC4xIDAgNy42LS40IDEwLjUtMS4yIDQuNC0xLjEgOC4xLTMuNiAxMC40LTcuMSA0LjQtNi43IDUuNC0xNS45IDQuMS0yNS40LS4zLTIuOC0yLjYtNi4zLTUtOC43eicpLCBfcGF0aDEzKSwgJyAnXSksIF91cHB5SWNvbjEyO1xufVxuXG5mdW5jdGlvbiBpY29uRmlsZSgpIHtcbiAgdmFyIF9wYXRoMTQsIF91cHB5SWNvbjEzO1xuXG4gIHJldHVybiBfdXBweUljb24xMyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAnc3ZnJyksIF91cHB5SWNvbjEzLnNldEF0dHJpYnV0ZSgnd2lkdGgnLCAnNDQnKSwgX3VwcHlJY29uMTMuc2V0QXR0cmlidXRlKCdoZWlnaHQnLCAnNTgnKSwgX3VwcHlJY29uMTMuc2V0QXR0cmlidXRlKCd2aWV3Qm94JywgJzAgMCA0NCA1OCcpLCBfdXBweUljb24xMy5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlJY29uJyksIF9hcHBlbmRDaGlsZChfdXBweUljb24xMywgWycgJywgKF9wYXRoMTQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3BhdGgnKSwgX3BhdGgxNC5zZXRBdHRyaWJ1dGUoJ2QnLCAnTTI3LjQzNy41MTdhMSAxIDAgMCAwLS4wOTQuMDNINC4yNUMyLjAzNy41NDguMjE3IDIuMzY4LjIxNyA0LjU4djQ4LjQwNWMwIDIuMjEyIDEuODIgNC4wMyA0LjAzIDQuMDNIMzkuMDNjMi4yMSAwIDQuMDMtMS44MTggNC4wMy00LjAzVjE1LjYxYTEgMSAwIDAgMC0uMDMtLjI4IDEgMSAwIDAgMCAwLS4wOTMgMSAxIDAgMCAwLS4wMy0uMDMyIDEgMSAwIDAgMCAwLS4wMyAxIDEgMCAwIDAtLjAzMi0uMDYzIDEgMSAwIDAgMC0uMDMtLjA2MyAxIDEgMCAwIDAtLjAzMiAwIDEgMSAwIDAgMC0uMDMtLjA2MyAxIDEgMCAwIDAtLjAzMi0uMDMgMSAxIDAgMCAwLS4wMy0uMDYzIDEgMSAwIDAgMC0uMDYzLS4wNjJsLTE0LjU5My0xNGExIDEgMCAwIDAtLjA2Mi0uMDYyQTEgMSAwIDAgMCAyOCAuNzA4YTEgMSAwIDAgMC0uMzc0LS4xNTcgMSAxIDAgMCAwLS4xNTYgMCAxIDEgMCAwIDAtLjAzLS4wM2wtLjAwMy0uMDAzek00LjI1IDIuNTQ3aDIyLjIxOHY5Ljk3YzAgMi4yMSAxLjgyIDQuMDMgNC4wMyA0LjAzaDEwLjU2NHYzNi40MzhhMi4wMiAyLjAyIDAgMCAxLTIuMDMyIDIuMDMySDQuMjVjLTEuMTMgMC0yLjAzMi0uOS0yLjAzMi0yLjAzMlY0LjU4YzAtMS4xMy45MDItMi4wMzIgMi4wMy0yLjAzMnptMjQuMjE4IDEuMzQ1bDEwLjM3NSA5LjkzNy43NS43MThIMzAuNWMtMS4xMyAwLTIuMDMyLS45LTIuMDMyLTIuMDNWMy44OXonKSwgX3BhdGgxNCksICcgJ10pLCBfdXBweUljb24xMztcbn1cblxuZnVuY3Rpb24gaWNvblRleHQoKSB7XG4gIHZhciBfcGF0aDE1LCBfcGF0aDE2LCBfdXBweUljb24xNDtcblxuICByZXR1cm4gX3VwcHlJY29uMTQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3N2ZycpLCBfdXBweUljb24xNC5zZXRBdHRyaWJ1dGUoJ3ZpZXdCb3gnLCAnMCAwIDY0IDY0JyksIF91cHB5SWNvbjE0LnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweUljb24nKSwgX2FwcGVuZENoaWxkKF91cHB5SWNvbjE0LCBbJyAnLCAoX3BhdGgxNSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAncGF0aCcpLCBfcGF0aDE1LnNldEF0dHJpYnV0ZSgnZCcsICdNOCA2NGg0OFYwSDIyLjU4Nkw4IDE0LjU4NlY2NHptNDYtMkgxMFYxNmgxNFYyaDMwdjYwek0xMS40MTQgMTRMMjIgMy40MTRWMTRIMTEuNDE0eicpLCBfcGF0aDE1KSwgJyAnLCAoX3BhdGgxNiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAncGF0aCcpLCBfcGF0aDE2LnNldEF0dHJpYnV0ZSgnZCcsICdNMzIgMTNoMTR2MkgzMnpNMTggMjNoMjh2MkgxOHpNMTggMzNoMjh2MkgxOHpNMTggNDNoMjh2MkgxOHpNMTggNTNoMjh2MkgxOHonKSwgX3BhdGgxNiksICcgJ10pLCBfdXBweUljb24xNDtcbn1cblxuZnVuY3Rpb24gdXBsb2FkSWNvbigpIHtcbiAgdmFyIF9wYXRoMTcsIF9wYXRoMTgsIF91cHB5SWNvbjE1O1xuXG4gIHJldHVybiBfdXBweUljb24xNSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAnc3ZnJyksIF91cHB5SWNvbjE1LnNldEF0dHJpYnV0ZSgnd2lkdGgnLCAnMzcnKSwgX3VwcHlJY29uMTUuc2V0QXR0cmlidXRlKCdoZWlnaHQnLCAnMzMnKSwgX3VwcHlJY29uMTUuc2V0QXR0cmlidXRlKCd2aWV3Qm94JywgJzAgMCAzNyAzMycpLCBfdXBweUljb24xNS5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlJY29uJyksIF9hcHBlbmRDaGlsZChfdXBweUljb24xNSwgWycgJywgKF9wYXRoMTcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3BhdGgnKSwgX3BhdGgxNy5zZXRBdHRyaWJ1dGUoJ2QnLCAnTTI5LjEwNyAyNC41YzQuMDcgMCA3LjM5My0zLjM1NSA3LjM5My03LjQ0MiAwLTMuOTk0LTMuMTA1LTcuMzA3LTcuMDEyLTcuNTAybC40NjguNDE1QzI5LjAyIDQuNTIgMjQuMzQuNSAxOC44ODYuNWMtNC4zNDggMC04LjI3IDIuNTIyLTEwLjEzOCA2LjUwNmwuNDQ2LS4yODhDNC4zOTQgNi43ODIuNSAxMC43NTguNSAxNS42MDhjMCA0LjkyNCAzLjkwNiA4Ljg5MiA4Ljc2IDguODkyaDQuODcyYy42MzUgMCAxLjA5NS0uNDY3IDEuMDk1LTEuMTA0IDAtLjYzNi0uNDYtMS4xMDMtMS4wOTUtMS4xMDNIOS4yNmMtMy42NDQgMC02LjYzLTMuMDM1LTYuNjMtNi43NDQgMC0zLjcxIDIuOTI2LTYuNjg1IDYuNTctNi42ODVoLjk2NGwuMTQtLjI4LjE3Ny0uMzYyYzEuNDc3LTMuNCA0Ljc0NC01LjU3NiA4LjM0Ny01LjU3NiA0LjU4IDAgOC40NSAzLjQ1MiA5LjAxIDguMDcybC4wNi41MzYuMDUuNDQ2aDEuMTAxYzIuODcgMCA1LjIwNCAyLjM3IDUuMjA0IDUuMjk1cy0yLjMzMyA1LjI5Ni01LjIwNCA1LjI5NmgtNi4wNjJjLS42MzQgMC0xLjA5NC40NjctMS4wOTQgMS4xMDMgMCAuNjM3LjQ2IDEuMTA0IDEuMDk0IDEuMTA0aDYuMTJ6JyksIF9wYXRoMTcpLCAnICcsIChfcGF0aDE4ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwYXRoJyksIF9wYXRoMTguc2V0QXR0cmlidXRlKCdkJywgJ00yMy4xOTYgMTguOTJsLTQuODI4LTUuMjU4LS4zNjYtLjQtLjM2OC4zOTgtNC44MjggNS4xOTZhMS4xMyAxLjEzIDAgMCAwIDAgMS41NDZjLjQyOC40NiAxLjExLjQ2IDEuNTM3IDBsMy40NS0zLjcxLS44NjgtLjM0djE1LjAzYzAgLjY0LjQ0NSAxLjExOCAxLjA3NSAxLjExOC42MyAwIDEuMDc1LS40OCAxLjA3NS0xLjEyVjE2LjM1bC0uODY3LjM0IDMuNDUgMy43MTJhMSAxIDAgMCAwIC43NjcuMzQ1IDEgMSAwIDAgMCAuNzctLjM0NWMuNDE2LS4zMy40MTYtMS4wMzYgMC0xLjQ4NXYuMDAzeicpLCBfcGF0aDE4KSwgJyAnXSksIF91cHB5SWNvbjE1O1xufVxuXG5mdW5jdGlvbiBkYXNoYm9hcmRCZ0ljb24oKSB7XG4gIHZhciBfcGF0aDE5LCBfdXBweUljb24xNjtcblxuICByZXR1cm4gX3VwcHlJY29uMTYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3N2ZycpLCBfdXBweUljb24xNi5zZXRBdHRyaWJ1dGUoJ3dpZHRoJywgJzQ4JyksIF91cHB5SWNvbjE2LnNldEF0dHJpYnV0ZSgnaGVpZ2h0JywgJzY5JyksIF91cHB5SWNvbjE2LnNldEF0dHJpYnV0ZSgndmlld0JveCcsICcwIDAgNDggNjknKSwgX3VwcHlJY29uMTYuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5SWNvbicpLCBfYXBwZW5kQ2hpbGQoX3VwcHlJY29uMTYsIFsnICcsIChfcGF0aDE5ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwYXRoJyksIF9wYXRoMTkuc2V0QXR0cmlidXRlKCdkJywgJ00uNSAxLjVoNXpNMTAuNSAxLjVoNXpNMjAuNSAxLjVoNXpNMzAuNTA0IDEuNWg1ek00NS41IDExLjV2NXpNNDUuNSAyMS41djV6TTQ1LjUgMzEuNXY1ek00NS41IDQxLjUwMnY1ek00NS41IDUxLjUwMnY1ek00NS41IDYxLjV2NXpNNDUuNSA2Ni41MDJoLTQuOTk4ek0zNS41MDMgNjYuNTAyaC01ek0yNS41IDY2LjUwMmgtNXpNMTUuNSA2Ni41MDJoLTV6TTUuNSA2Ni41MDJoLTV6TS41IDY2LjUwMnYtNXpNLjUgNTYuNTAydi01ek0uNSA0Ni41MDNWNDEuNXpNLjUgMzYuNXYtNXpNLjUgMjYuNXYtNXpNLjUgMTYuNXYtNXpNLjUgNi41VjEuNDk4ek00NC44MDcgMTFIMzZWMi4xOTV6JyksIF9wYXRoMTkpLCAnICddKSwgX3VwcHlJY29uMTY7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBkZWZhdWx0VGFiSWNvbjogZGVmYXVsdFRhYkljb24sXG4gIGljb25Db3B5OiBpY29uQ29weSxcbiAgaWNvblJlc3VtZTogaWNvblJlc3VtZSxcbiAgaWNvblBhdXNlOiBpY29uUGF1c2UsXG4gIGljb25FZGl0OiBpY29uRWRpdCxcbiAgbG9jYWxJY29uOiBsb2NhbEljb24sXG4gIGNsb3NlSWNvbjogY2xvc2VJY29uLFxuICBwbHVnaW5JY29uOiBwbHVnaW5JY29uLFxuICBjaGVja0ljb246IGNoZWNrSWNvbixcbiAgaWNvbkF1ZGlvOiBpY29uQXVkaW8sXG4gIGljb25WaWRlbzogaWNvblZpZGVvLFxuICBpY29uUERGOiBpY29uUERGLFxuICBpY29uRmlsZTogaWNvbkZpbGUsXG4gIGljb25UZXh0OiBpY29uVGV4dCxcbiAgdXBsb2FkSWNvbjogdXBsb2FkSWNvbixcbiAgZGFzaGJvYXJkQmdJY29uOiBkYXNoYm9hcmRCZ0ljb25cbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pY29ucy5qcy5tYXAiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfZXh0ZW5kcyA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gKHRhcmdldCkgeyBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgeyB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldOyBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7IGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoc291cmNlLCBrZXkpKSB7IHRhcmdldFtrZXldID0gc291cmNlW2tleV07IH0gfSB9IHJldHVybiB0YXJnZXQ7IH07XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbmZ1bmN0aW9uIF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHNlbGYsIGNhbGwpIHsgaWYgKCFzZWxmKSB7IHRocm93IG5ldyBSZWZlcmVuY2VFcnJvcihcInRoaXMgaGFzbid0IGJlZW4gaW5pdGlhbGlzZWQgLSBzdXBlcigpIGhhc24ndCBiZWVuIGNhbGxlZFwiKTsgfSByZXR1cm4gY2FsbCAmJiAodHlwZW9mIGNhbGwgPT09IFwib2JqZWN0XCIgfHwgdHlwZW9mIGNhbGwgPT09IFwiZnVuY3Rpb25cIikgPyBjYWxsIDogc2VsZjsgfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSBcImZ1bmN0aW9uXCIgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCBcIiArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH1cblxudmFyIFBsdWdpbiA9IHJlcXVpcmUoJy4uL1BsdWdpbicpO1xudmFyIFRyYW5zbGF0b3IgPSByZXF1aXJlKCcuLi8uLi9jb3JlL1RyYW5zbGF0b3InKTtcbnZhciBkcmFnRHJvcCA9IHJlcXVpcmUoJ2RyYWctZHJvcCcpO1xudmFyIERhc2hib2FyZCA9IHJlcXVpcmUoJy4vRGFzaGJvYXJkJyk7XG5cbnZhciBfcmVxdWlyZSA9IHJlcXVpcmUoJy4uLy4uL2NvcmUvVXRpbHMnKSxcbiAgICBnZXRTcGVlZCA9IF9yZXF1aXJlLmdldFNwZWVkO1xuXG52YXIgX3JlcXVpcmUyID0gcmVxdWlyZSgnLi4vLi4vY29yZS9VdGlscycpLFxuICAgIGdldEVUQSA9IF9yZXF1aXJlMi5nZXRFVEE7XG5cbnZhciBfcmVxdWlyZTMgPSByZXF1aXJlKCcuLi8uLi9jb3JlL1V0aWxzJyksXG4gICAgcHJldHR5RVRBID0gX3JlcXVpcmUzLnByZXR0eUVUQTtcblxudmFyIF9yZXF1aXJlNCA9IHJlcXVpcmUoJy4uLy4uL2NvcmUvVXRpbHMnKSxcbiAgICBmaW5kRE9NRWxlbWVudCA9IF9yZXF1aXJlNC5maW5kRE9NRWxlbWVudDtcblxudmFyIHByZXR0eUJ5dGVzID0gcmVxdWlyZSgncHJldHRpZXItYnl0ZXMnKTtcblxudmFyIF9yZXF1aXJlNSA9IHJlcXVpcmUoJy4vaWNvbnMnKSxcbiAgICBkZWZhdWx0VGFiSWNvbiA9IF9yZXF1aXJlNS5kZWZhdWx0VGFiSWNvbjtcblxuLyoqXG4gKiBNb2RhbCBEaWFsb2cgJiBEYXNoYm9hcmRcbiAqL1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKF9QbHVnaW4pIHtcbiAgX2luaGVyaXRzKERhc2hib2FyZFVJLCBfUGx1Z2luKTtcblxuICBmdW5jdGlvbiBEYXNoYm9hcmRVSShjb3JlLCBvcHRzKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIERhc2hib2FyZFVJKTtcblxuICAgIHZhciBfdGhpcyA9IF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHRoaXMsIF9QbHVnaW4uY2FsbCh0aGlzLCBjb3JlLCBvcHRzKSk7XG5cbiAgICBfdGhpcy5pZCA9ICdEYXNoYm9hcmRVSSc7XG4gICAgX3RoaXMudGl0bGUgPSAnRGFzaGJvYXJkIFVJJztcbiAgICBfdGhpcy50eXBlID0gJ29yY2hlc3RyYXRvcic7XG5cbiAgICB2YXIgZGVmYXVsdExvY2FsZSA9IHtcbiAgICAgIHN0cmluZ3M6IHtcbiAgICAgICAgc2VsZWN0VG9VcGxvYWQ6ICdTZWxlY3QgZmlsZXMgdG8gdXBsb2FkJyxcbiAgICAgICAgY2xvc2VNb2RhbDogJ0Nsb3NlIE1vZGFsJyxcbiAgICAgICAgdXBsb2FkOiAnVXBsb2FkJyxcbiAgICAgICAgaW1wb3J0RnJvbTogJ0ltcG9ydCBmaWxlcyBmcm9tJyxcbiAgICAgICAgZGFzaGJvYXJkV2luZG93VGl0bGU6ICdVcHB5IERhc2hib2FyZCBXaW5kb3cgKFByZXNzIGVzY2FwZSB0byBjbG9zZSknLFxuICAgICAgICBkYXNoYm9hcmRUaXRsZTogJ1VwcHkgRGFzaGJvYXJkJyxcbiAgICAgICAgY29weUxpbmtUb0NsaXBib2FyZFN1Y2Nlc3M6ICdMaW5rIGNvcGllZCB0byBjbGlwYm9hcmQuJyxcbiAgICAgICAgY29weUxpbmtUb0NsaXBib2FyZEZhbGxiYWNrOiAnQ29weSB0aGUgVVJMIGJlbG93JyxcbiAgICAgICAgZG9uZTogJ0RvbmUnLFxuICAgICAgICBsb2NhbERpc2s6ICdMb2NhbCBEaXNrJyxcbiAgICAgICAgZHJvcFBhc3RlSW1wb3J0OiAnRHJvcCBmaWxlcyBoZXJlLCBwYXN0ZSwgaW1wb3J0IGZyb20gb25lIG9mIHRoZSBsb2NhdGlvbnMgYWJvdmUgb3InLFxuICAgICAgICBkcm9wUGFzdGU6ICdEcm9wIGZpbGVzIGhlcmUsIHBhc3RlIG9yJyxcbiAgICAgICAgYnJvd3NlOiAnYnJvd3NlJyxcbiAgICAgICAgZmlsZVByb2dyZXNzOiAnRmlsZSBwcm9ncmVzczogdXBsb2FkIHNwZWVkIGFuZCBFVEEnLFxuICAgICAgICBudW1iZXJPZlNlbGVjdGVkRmlsZXM6ICdOdW1iZXIgb2Ygc2VsZWN0ZWQgZmlsZXMnLFxuICAgICAgICB1cGxvYWRBbGxOZXdGaWxlczogJ1VwbG9hZCBhbGwgbmV3IGZpbGVzJ1xuICAgICAgfVxuICAgIH07XG5cbiAgICAvLyBzZXQgZGVmYXVsdCBvcHRpb25zXG4gICAgdmFyIGRlZmF1bHRPcHRpb25zID0ge1xuICAgICAgdGFyZ2V0OiAnYm9keScsXG4gICAgICBpbmxpbmU6IGZhbHNlLFxuICAgICAgd2lkdGg6IDc1MCxcbiAgICAgIGhlaWdodDogNTUwLFxuICAgICAgc2VtaVRyYW5zcGFyZW50OiBmYWxzZSxcbiAgICAgIGRlZmF1bHRUYWJJY29uOiBkZWZhdWx0VGFiSWNvbigpLFxuICAgICAgc2hvd1Byb2dyZXNzRGV0YWlsczogZmFsc2UsXG4gICAgICBsb2NhbGU6IGRlZmF1bHRMb2NhbGVcbiAgICB9O1xuXG4gICAgLy8gbWVyZ2UgZGVmYXVsdCBvcHRpb25zIHdpdGggdGhlIG9uZXMgc2V0IGJ5IHVzZXJcbiAgICBfdGhpcy5vcHRzID0gX2V4dGVuZHMoe30sIGRlZmF1bHRPcHRpb25zLCBvcHRzKTtcblxuICAgIF90aGlzLmxvY2FsZSA9IF9leHRlbmRzKHt9LCBkZWZhdWx0TG9jYWxlLCBfdGhpcy5vcHRzLmxvY2FsZSk7XG4gICAgX3RoaXMubG9jYWxlLnN0cmluZ3MgPSBfZXh0ZW5kcyh7fSwgZGVmYXVsdExvY2FsZS5zdHJpbmdzLCBfdGhpcy5vcHRzLmxvY2FsZS5zdHJpbmdzKTtcblxuICAgIF90aGlzLnRyYW5zbGF0b3IgPSBuZXcgVHJhbnNsYXRvcih7IGxvY2FsZTogX3RoaXMubG9jYWxlIH0pO1xuICAgIF90aGlzLmNvbnRhaW5lcldpZHRoID0gX3RoaXMudHJhbnNsYXRvci50cmFuc2xhdGUuYmluZChfdGhpcy50cmFuc2xhdG9yKTtcblxuICAgIF90aGlzLmhpZGVNb2RhbCA9IF90aGlzLmhpZGVNb2RhbC5iaW5kKF90aGlzKTtcbiAgICBfdGhpcy5zaG93TW9kYWwgPSBfdGhpcy5zaG93TW9kYWwuYmluZChfdGhpcyk7XG5cbiAgICBfdGhpcy5hZGRUYXJnZXQgPSBfdGhpcy5hZGRUYXJnZXQuYmluZChfdGhpcyk7XG4gICAgX3RoaXMuYWN0aW9ucyA9IF90aGlzLmFjdGlvbnMuYmluZChfdGhpcyk7XG4gICAgX3RoaXMuaGlkZUFsbFBhbmVscyA9IF90aGlzLmhpZGVBbGxQYW5lbHMuYmluZChfdGhpcyk7XG4gICAgX3RoaXMuc2hvd1BhbmVsID0gX3RoaXMuc2hvd1BhbmVsLmJpbmQoX3RoaXMpO1xuICAgIF90aGlzLmluaXRFdmVudHMgPSBfdGhpcy5pbml0RXZlbnRzLmJpbmQoX3RoaXMpO1xuICAgIF90aGlzLmhhbmRsZUVzY2FwZUtleVByZXNzID0gX3RoaXMuaGFuZGxlRXNjYXBlS2V5UHJlc3MuYmluZChfdGhpcyk7XG4gICAgX3RoaXMuaGFuZGxlRmlsZUNhcmQgPSBfdGhpcy5oYW5kbGVGaWxlQ2FyZC5iaW5kKF90aGlzKTtcbiAgICBfdGhpcy5oYW5kbGVEcm9wID0gX3RoaXMuaGFuZGxlRHJvcC5iaW5kKF90aGlzKTtcbiAgICBfdGhpcy5wYXVzZUFsbCA9IF90aGlzLnBhdXNlQWxsLmJpbmQoX3RoaXMpO1xuICAgIF90aGlzLnJlc3VtZUFsbCA9IF90aGlzLnJlc3VtZUFsbC5iaW5kKF90aGlzKTtcbiAgICBfdGhpcy5jYW5jZWxBbGwgPSBfdGhpcy5jYW5jZWxBbGwuYmluZChfdGhpcyk7XG4gICAgX3RoaXMudXBkYXRlRGFzaGJvYXJkRWxXaWR0aCA9IF90aGlzLnVwZGF0ZURhc2hib2FyZEVsV2lkdGguYmluZChfdGhpcyk7XG4gICAgX3RoaXMucmVuZGVyID0gX3RoaXMucmVuZGVyLmJpbmQoX3RoaXMpO1xuICAgIF90aGlzLmluc3RhbGwgPSBfdGhpcy5pbnN0YWxsLmJpbmQoX3RoaXMpO1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuXG4gIERhc2hib2FyZFVJLnByb3RvdHlwZS5hZGRUYXJnZXQgPSBmdW5jdGlvbiBhZGRUYXJnZXQocGx1Z2luKSB7XG4gICAgdmFyIGNhbGxlclBsdWdpbklkID0gcGx1Z2luLmlkIHx8IHBsdWdpbi5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgIHZhciBjYWxsZXJQbHVnaW5OYW1lID0gcGx1Z2luLnRpdGxlIHx8IGNhbGxlclBsdWdpbklkO1xuICAgIHZhciBjYWxsZXJQbHVnaW5JY29uID0gcGx1Z2luLmljb24gfHwgdGhpcy5vcHRzLmRlZmF1bHRUYWJJY29uO1xuICAgIHZhciBjYWxsZXJQbHVnaW5UeXBlID0gcGx1Z2luLnR5cGU7XG5cbiAgICBpZiAoY2FsbGVyUGx1Z2luVHlwZSAhPT0gJ2FjcXVpcmVyJyAmJiBjYWxsZXJQbHVnaW5UeXBlICE9PSAncHJvZ3Jlc3NpbmRpY2F0b3InICYmIGNhbGxlclBsdWdpblR5cGUgIT09ICdwcmVzZW50ZXInKSB7XG4gICAgICB2YXIgbXNnID0gJ0Vycm9yOiBNb2RhbCBjYW4gb25seSBiZSB1c2VkIGJ5IHBsdWdpbnMgb2YgdHlwZXM6IGFjcXVpcmVyLCBwcm9ncmVzc2luZGljYXRvciwgcHJlc2VudGVyJztcbiAgICAgIHRoaXMuY29yZS5sb2cobXNnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgdGFyZ2V0ID0ge1xuICAgICAgaWQ6IGNhbGxlclBsdWdpbklkLFxuICAgICAgbmFtZTogY2FsbGVyUGx1Z2luTmFtZSxcbiAgICAgIGljb246IGNhbGxlclBsdWdpbkljb24sXG4gICAgICB0eXBlOiBjYWxsZXJQbHVnaW5UeXBlLFxuICAgICAgZm9jdXM6IHBsdWdpbi5mb2N1cyxcbiAgICAgIHJlbmRlcjogcGx1Z2luLnJlbmRlcixcbiAgICAgIGlzSGlkZGVuOiB0cnVlXG4gICAgfTtcblxuICAgIHZhciBtb2RhbCA9IHRoaXMuY29yZS5nZXRTdGF0ZSgpLm1vZGFsO1xuICAgIHZhciBuZXdUYXJnZXRzID0gbW9kYWwudGFyZ2V0cy5zbGljZSgpO1xuICAgIG5ld1RhcmdldHMucHVzaCh0YXJnZXQpO1xuXG4gICAgdGhpcy5jb3JlLnNldFN0YXRlKHtcbiAgICAgIG1vZGFsOiBfZXh0ZW5kcyh7fSwgbW9kYWwsIHtcbiAgICAgICAgdGFyZ2V0czogbmV3VGFyZ2V0c1xuICAgICAgfSlcbiAgICB9KTtcblxuICAgIHJldHVybiB0aGlzLnRhcmdldDtcbiAgfTtcblxuICBEYXNoYm9hcmRVSS5wcm90b3R5cGUuaGlkZUFsbFBhbmVscyA9IGZ1bmN0aW9uIGhpZGVBbGxQYW5lbHMoKSB7XG4gICAgdmFyIG1vZGFsID0gdGhpcy5jb3JlLmdldFN0YXRlKCkubW9kYWw7XG5cbiAgICB0aGlzLmNvcmUuc2V0U3RhdGUoeyBtb2RhbDogX2V4dGVuZHMoe30sIG1vZGFsLCB7XG4gICAgICAgIGFjdGl2ZVBhbmVsOiBmYWxzZVxuICAgICAgfSkgfSk7XG4gIH07XG5cbiAgRGFzaGJvYXJkVUkucHJvdG90eXBlLnNob3dQYW5lbCA9IGZ1bmN0aW9uIHNob3dQYW5lbChpZCkge1xuICAgIHZhciBtb2RhbCA9IHRoaXMuY29yZS5nZXRTdGF0ZSgpLm1vZGFsO1xuXG4gICAgdmFyIGFjdGl2ZVBhbmVsID0gbW9kYWwudGFyZ2V0cy5maWx0ZXIoZnVuY3Rpb24gKHRhcmdldCkge1xuICAgICAgcmV0dXJuIHRhcmdldC50eXBlID09PSAnYWNxdWlyZXInICYmIHRhcmdldC5pZCA9PT0gaWQ7XG4gICAgfSlbMF07XG5cbiAgICB0aGlzLmNvcmUuc2V0U3RhdGUoeyBtb2RhbDogX2V4dGVuZHMoe30sIG1vZGFsLCB7XG4gICAgICAgIGFjdGl2ZVBhbmVsOiBhY3RpdmVQYW5lbFxuICAgICAgfSkgfSk7XG4gIH07XG5cbiAgRGFzaGJvYXJkVUkucHJvdG90eXBlLmhpZGVNb2RhbCA9IGZ1bmN0aW9uIGhpZGVNb2RhbCgpIHtcbiAgICB2YXIgbW9kYWwgPSB0aGlzLmNvcmUuZ2V0U3RhdGUoKS5tb2RhbDtcblxuICAgIHRoaXMuY29yZS5zZXRTdGF0ZSh7XG4gICAgICBtb2RhbDogX2V4dGVuZHMoe30sIG1vZGFsLCB7XG4gICAgICAgIGlzSGlkZGVuOiB0cnVlXG4gICAgICB9KVxuICAgIH0pO1xuXG4gICAgZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QucmVtb3ZlKCdpcy1VcHB5RGFzaGJvYXJkLW9wZW4nKTtcbiAgfTtcblxuICBEYXNoYm9hcmRVSS5wcm90b3R5cGUuc2hvd01vZGFsID0gZnVuY3Rpb24gc2hvd01vZGFsKCkge1xuICAgIHZhciBtb2RhbCA9IHRoaXMuY29yZS5nZXRTdGF0ZSgpLm1vZGFsO1xuXG4gICAgdGhpcy5jb3JlLnNldFN0YXRlKHtcbiAgICAgIG1vZGFsOiBfZXh0ZW5kcyh7fSwgbW9kYWwsIHtcbiAgICAgICAgaXNIaWRkZW46IGZhbHNlXG4gICAgICB9KVxuICAgIH0pO1xuXG4gICAgLy8gYWRkIGNsYXNzIHRvIGJvZHkgdGhhdCBzZXRzIHBvc2l0aW9uIGZpeGVkXG4gICAgZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuYWRkKCdpcy1VcHB5RGFzaGJvYXJkLW9wZW4nKTtcbiAgICAvLyBmb2N1cyBvbiBtb2RhbCBpbm5lciBibG9ja1xuICAgIHRoaXMudGFyZ2V0LnF1ZXJ5U2VsZWN0b3IoJy5VcHB5RGFzaGJvYXJkLWlubmVyJykuZm9jdXMoKTtcblxuICAgIHRoaXMudXBkYXRlRGFzaGJvYXJkRWxXaWR0aCgpO1xuICAgIC8vIHRvIGJlIHN1cmUsIHNvbWV0aW1lcyB3aGVuIHRoZSBmdW5jdGlvbiBydW5zLCBjb250YWluZXIgc2l6ZSBpcyBzdGlsbCAwXG4gICAgc2V0VGltZW91dCh0aGlzLnVwZGF0ZURhc2hib2FyZEVsV2lkdGgsIDMwMCk7XG4gIH07XG5cbiAgLy8gQ2xvc2UgdGhlIE1vZGFsIG9uIGVzYyBrZXkgcHJlc3NcblxuXG4gIERhc2hib2FyZFVJLnByb3RvdHlwZS5oYW5kbGVFc2NhcGVLZXlQcmVzcyA9IGZ1bmN0aW9uIGhhbmRsZUVzY2FwZUtleVByZXNzKGV2ZW50KSB7XG4gICAgaWYgKGV2ZW50LmtleUNvZGUgPT09IDI3KSB7XG4gICAgICB0aGlzLmhpZGVNb2RhbCgpO1xuICAgIH1cbiAgfTtcblxuICBEYXNoYm9hcmRVSS5wcm90b3R5cGUuaW5pdEV2ZW50cyA9IGZ1bmN0aW9uIGluaXRFdmVudHMoKSB7XG4gICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAvLyBjb25zdCBkYXNoYm9hcmRFbCA9IHRoaXMudGFyZ2V0LnF1ZXJ5U2VsZWN0b3IoYCR7dGhpcy5vcHRzLnRhcmdldH0gLlVwcHlEYXNoYm9hcmRgKVxuXG4gICAgLy8gTW9kYWwgb3BlbiBidXR0b25cbiAgICB2YXIgc2hvd01vZGFsVHJpZ2dlciA9IGZpbmRET01FbGVtZW50KHRoaXMub3B0cy50cmlnZ2VyKTtcbiAgICBpZiAoIXRoaXMub3B0cy5pbmxpbmUgJiYgc2hvd01vZGFsVHJpZ2dlcikge1xuICAgICAgc2hvd01vZGFsVHJpZ2dlci5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuc2hvd01vZGFsKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5jb3JlLmxvZygnTW9kYWwgdHJpZ2dlciB3YXNu4oCZdCBmb3VuZCcpO1xuICAgIH1cblxuICAgIGRvY3VtZW50LmJvZHkuYWRkRXZlbnRMaXN0ZW5lcigna2V5dXAnLCB0aGlzLmhhbmRsZUVzY2FwZUtleVByZXNzKTtcblxuICAgIC8vIERyYWcgRHJvcFxuICAgIHRoaXMucmVtb3ZlRHJhZ0Ryb3BMaXN0ZW5lciA9IGRyYWdEcm9wKHRoaXMuZWwsIGZ1bmN0aW9uIChmaWxlcykge1xuICAgICAgX3RoaXMyLmhhbmRsZURyb3AoZmlsZXMpO1xuICAgIH0pO1xuICB9O1xuXG4gIERhc2hib2FyZFVJLnByb3RvdHlwZS5yZW1vdmVFdmVudHMgPSBmdW5jdGlvbiByZW1vdmVFdmVudHMoKSB7XG4gICAgdmFyIHNob3dNb2RhbFRyaWdnZXIgPSBmaW5kRE9NRWxlbWVudCh0aGlzLm9wdHMudHJpZ2dlcik7XG4gICAgaWYgKCF0aGlzLm9wdHMuaW5saW5lICYmIHNob3dNb2RhbFRyaWdnZXIpIHtcbiAgICAgIHNob3dNb2RhbFRyaWdnZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLnNob3dNb2RhbCk7XG4gICAgfVxuXG4gICAgdGhpcy5yZW1vdmVEcmFnRHJvcExpc3RlbmVyKCk7XG4gICAgZG9jdW1lbnQuYm9keS5yZW1vdmVFdmVudExpc3RlbmVyKCdrZXl1cCcsIHRoaXMuaGFuZGxlRXNjYXBlS2V5UHJlc3MpO1xuICB9O1xuXG4gIERhc2hib2FyZFVJLnByb3RvdHlwZS5hY3Rpb25zID0gZnVuY3Rpb24gYWN0aW9ucygpIHtcbiAgICB2YXIgYnVzID0gdGhpcy5jb3JlLmJ1cztcblxuICAgIGJ1cy5vbignY29yZTpmaWxlLWFkZCcsIHRoaXMuaGlkZUFsbFBhbmVscyk7XG4gICAgYnVzLm9uKCdkYXNoYm9hcmQ6ZmlsZS1jYXJkJywgdGhpcy5oYW5kbGVGaWxlQ2FyZCk7XG5cbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy51cGRhdGVEYXNoYm9hcmRFbFdpZHRoKTtcblxuICAgIC8vIGJ1cy5vbignY29yZTpzdWNjZXNzJywgKHVwbG9hZGVkQ291bnQpID0+IHtcbiAgICAvLyAgIGJ1cy5lbWl0KFxuICAgIC8vICAgICAnaW5mb3JtZXInLFxuICAgIC8vICAgICBgJHt0aGlzLmNvcmUuaTE4bignZmlsZXMnLCB7J3NtYXJ0X2NvdW50JzogdXBsb2FkZWRDb3VudH0pfSBzdWNjZXNzZnVsbHkgdXBsb2FkZWQsIFNpciFgLFxuICAgIC8vICAgICAnaW5mbycsXG4gICAgLy8gICAgIDYwMDBcbiAgICAvLyAgIClcbiAgICAvLyB9KVxuICB9O1xuXG4gIERhc2hib2FyZFVJLnByb3RvdHlwZS5yZW1vdmVBY3Rpb25zID0gZnVuY3Rpb24gcmVtb3ZlQWN0aW9ucygpIHtcbiAgICB2YXIgYnVzID0gdGhpcy5jb3JlLmJ1cztcblxuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdyZXNpemUnLCB0aGlzLnVwZGF0ZURhc2hib2FyZEVsV2lkdGgpO1xuXG4gICAgYnVzLm9mZignY29yZTpmaWxlLWFkZCcsIHRoaXMuaGlkZUFsbFBhbmVscyk7XG4gICAgYnVzLm9mZignZGFzaGJvYXJkOmZpbGUtY2FyZCcsIHRoaXMuaGFuZGxlRmlsZUNhcmQpO1xuICB9O1xuXG4gIERhc2hib2FyZFVJLnByb3RvdHlwZS51cGRhdGVEYXNoYm9hcmRFbFdpZHRoID0gZnVuY3Rpb24gdXBkYXRlRGFzaGJvYXJkRWxXaWR0aCgpIHtcbiAgICB2YXIgZGFzaGJvYXJkRWwgPSB0aGlzLnRhcmdldC5xdWVyeVNlbGVjdG9yKCcuVXBweURhc2hib2FyZC1pbm5lcicpO1xuICAgIHZhciBjb250YWluZXJXaWR0aCA9IGRhc2hib2FyZEVsLm9mZnNldFdpZHRoO1xuICAgIGNvbnNvbGUubG9nKGNvbnRhaW5lcldpZHRoKTtcblxuICAgIHZhciBtb2RhbCA9IHRoaXMuY29yZS5nZXRTdGF0ZSgpLm1vZGFsO1xuICAgIHRoaXMuY29yZS5zZXRTdGF0ZSh7XG4gICAgICBtb2RhbDogX2V4dGVuZHMoe30sIG1vZGFsLCB7XG4gICAgICAgIGNvbnRhaW5lcldpZHRoOiBkYXNoYm9hcmRFbC5vZmZzZXRXaWR0aFxuICAgICAgfSlcbiAgICB9KTtcbiAgfTtcblxuICBEYXNoYm9hcmRVSS5wcm90b3R5cGUuaGFuZGxlRmlsZUNhcmQgPSBmdW5jdGlvbiBoYW5kbGVGaWxlQ2FyZChmaWxlSWQpIHtcbiAgICB2YXIgbW9kYWwgPSB0aGlzLmNvcmUuZ2V0U3RhdGUoKS5tb2RhbDtcblxuICAgIHRoaXMuY29yZS5zZXRTdGF0ZSh7XG4gICAgICBtb2RhbDogX2V4dGVuZHMoe30sIG1vZGFsLCB7XG4gICAgICAgIGZpbGVDYXJkRm9yOiBmaWxlSWQgfHwgZmFsc2VcbiAgICAgIH0pXG4gICAgfSk7XG4gIH07XG5cbiAgRGFzaGJvYXJkVUkucHJvdG90eXBlLmhhbmRsZURyb3AgPSBmdW5jdGlvbiBoYW5kbGVEcm9wKGZpbGVzKSB7XG4gICAgdmFyIF90aGlzMyA9IHRoaXM7XG5cbiAgICB0aGlzLmNvcmUubG9nKCdBbGwgcmlnaHQsIHNvbWVvbmUgZHJvcHBlZCBzb21ldGhpbmcuLi4nKTtcblxuICAgIGZpbGVzLmZvckVhY2goZnVuY3Rpb24gKGZpbGUpIHtcbiAgICAgIF90aGlzMy5jb3JlLmJ1cy5lbWl0KCdjb3JlOmZpbGUtYWRkJywge1xuICAgICAgICBzb3VyY2U6IF90aGlzMy5pZCxcbiAgICAgICAgbmFtZTogZmlsZS5uYW1lLFxuICAgICAgICB0eXBlOiBmaWxlLnR5cGUsXG4gICAgICAgIGRhdGE6IGZpbGVcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIERhc2hib2FyZFVJLnByb3RvdHlwZS5jYW5jZWxBbGwgPSBmdW5jdGlvbiBjYW5jZWxBbGwoKSB7XG4gICAgdGhpcy5jb3JlLmJ1cy5lbWl0KCdjb3JlOmNhbmNlbC1hbGwnKTtcbiAgfTtcblxuICBEYXNoYm9hcmRVSS5wcm90b3R5cGUucGF1c2VBbGwgPSBmdW5jdGlvbiBwYXVzZUFsbCgpIHtcbiAgICB0aGlzLmNvcmUuYnVzLmVtaXQoJ2NvcmU6cGF1c2UtYWxsJyk7XG4gIH07XG5cbiAgRGFzaGJvYXJkVUkucHJvdG90eXBlLnJlc3VtZUFsbCA9IGZ1bmN0aW9uIHJlc3VtZUFsbCgpIHtcbiAgICB0aGlzLmNvcmUuYnVzLmVtaXQoJ2NvcmU6cmVzdW1lLWFsbCcpO1xuICB9O1xuXG4gIERhc2hib2FyZFVJLnByb3RvdHlwZS5nZXRUb3RhbFNwZWVkID0gZnVuY3Rpb24gZ2V0VG90YWxTcGVlZChmaWxlcykge1xuICAgIHZhciB0b3RhbFNwZWVkID0gMDtcbiAgICBmaWxlcy5mb3JFYWNoKGZ1bmN0aW9uIChmaWxlKSB7XG4gICAgICB0b3RhbFNwZWVkID0gdG90YWxTcGVlZCArIGdldFNwZWVkKGZpbGUucHJvZ3Jlc3MpO1xuICAgIH0pO1xuICAgIHJldHVybiB0b3RhbFNwZWVkO1xuICB9O1xuXG4gIERhc2hib2FyZFVJLnByb3RvdHlwZS5nZXRUb3RhbEVUQSA9IGZ1bmN0aW9uIGdldFRvdGFsRVRBKGZpbGVzKSB7XG4gICAgdmFyIHRvdGFsU2Vjb25kcyA9IDA7XG5cbiAgICBmaWxlcy5mb3JFYWNoKGZ1bmN0aW9uIChmaWxlKSB7XG4gICAgICB0b3RhbFNlY29uZHMgPSB0b3RhbFNlY29uZHMgKyBnZXRFVEEoZmlsZS5wcm9ncmVzcyk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gdG90YWxTZWNvbmRzO1xuICB9O1xuXG4gIERhc2hib2FyZFVJLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiByZW5kZXIoc3RhdGUpIHtcbiAgICB2YXIgX3RoaXM0ID0gdGhpcztcblxuICAgIHZhciBmaWxlcyA9IHN0YXRlLmZpbGVzO1xuXG4gICAgdmFyIG5ld0ZpbGVzID0gT2JqZWN0LmtleXMoZmlsZXMpLmZpbHRlcihmdW5jdGlvbiAoZmlsZSkge1xuICAgICAgcmV0dXJuICFmaWxlc1tmaWxlXS5wcm9ncmVzcy51cGxvYWRTdGFydGVkO1xuICAgIH0pO1xuICAgIHZhciB1cGxvYWRTdGFydGVkRmlsZXMgPSBPYmplY3Qua2V5cyhmaWxlcykuZmlsdGVyKGZ1bmN0aW9uIChmaWxlKSB7XG4gICAgICByZXR1cm4gZmlsZXNbZmlsZV0ucHJvZ3Jlc3MudXBsb2FkU3RhcnRlZDtcbiAgICB9KTtcbiAgICB2YXIgY29tcGxldGVGaWxlcyA9IE9iamVjdC5rZXlzKGZpbGVzKS5maWx0ZXIoZnVuY3Rpb24gKGZpbGUpIHtcbiAgICAgIHJldHVybiBmaWxlc1tmaWxlXS5wcm9ncmVzcy51cGxvYWRDb21wbGV0ZTtcbiAgICB9KTtcbiAgICB2YXIgaW5Qcm9ncmVzc0ZpbGVzID0gT2JqZWN0LmtleXMoZmlsZXMpLmZpbHRlcihmdW5jdGlvbiAoZmlsZSkge1xuICAgICAgcmV0dXJuICFmaWxlc1tmaWxlXS5wcm9ncmVzcy51cGxvYWRDb21wbGV0ZSAmJiBmaWxlc1tmaWxlXS5wcm9ncmVzcy51cGxvYWRTdGFydGVkICYmICFmaWxlc1tmaWxlXS5pc1BhdXNlZDtcbiAgICB9KTtcblxuICAgIHZhciBpblByb2dyZXNzRmlsZXNBcnJheSA9IFtdO1xuICAgIGluUHJvZ3Jlc3NGaWxlcy5mb3JFYWNoKGZ1bmN0aW9uIChmaWxlKSB7XG4gICAgICBpblByb2dyZXNzRmlsZXNBcnJheS5wdXNoKGZpbGVzW2ZpbGVdKTtcbiAgICB9KTtcblxuICAgIHZhciB0b3RhbFNwZWVkID0gcHJldHR5Qnl0ZXModGhpcy5nZXRUb3RhbFNwZWVkKGluUHJvZ3Jlc3NGaWxlc0FycmF5KSk7XG4gICAgdmFyIHRvdGFsRVRBID0gcHJldHR5RVRBKHRoaXMuZ2V0VG90YWxFVEEoaW5Qcm9ncmVzc0ZpbGVzQXJyYXkpKTtcblxuICAgIC8vIHRvdGFsIHNpemUgYW5kIHVwbG9hZGVkIHNpemVcbiAgICB2YXIgdG90YWxTaXplID0gMDtcbiAgICB2YXIgdG90YWxVcGxvYWRlZFNpemUgPSAwO1xuICAgIGluUHJvZ3Jlc3NGaWxlc0FycmF5LmZvckVhY2goZnVuY3Rpb24gKGZpbGUpIHtcbiAgICAgIHRvdGFsU2l6ZSA9IHRvdGFsU2l6ZSArIChmaWxlLnByb2dyZXNzLmJ5dGVzVG90YWwgfHwgMCk7XG4gICAgICB0b3RhbFVwbG9hZGVkU2l6ZSA9IHRvdGFsVXBsb2FkZWRTaXplICsgKGZpbGUucHJvZ3Jlc3MuYnl0ZXNVcGxvYWRlZCB8fCAwKTtcbiAgICB9KTtcbiAgICB0b3RhbFNpemUgPSBwcmV0dHlCeXRlcyh0b3RhbFNpemUpO1xuICAgIHRvdGFsVXBsb2FkZWRTaXplID0gcHJldHR5Qnl0ZXModG90YWxVcGxvYWRlZFNpemUpO1xuXG4gICAgdmFyIGlzQWxsQ29tcGxldGUgPSBzdGF0ZS50b3RhbFByb2dyZXNzID09PSAxMDA7XG4gICAgdmFyIGlzQWxsUGF1c2VkID0gaW5Qcm9ncmVzc0ZpbGVzLmxlbmd0aCA9PT0gMCAmJiAhaXNBbGxDb21wbGV0ZSAmJiB1cGxvYWRTdGFydGVkRmlsZXMubGVuZ3RoID4gMDtcbiAgICB2YXIgaXNVcGxvYWRTdGFydGVkID0gdXBsb2FkU3RhcnRlZEZpbGVzLmxlbmd0aCA+IDA7XG5cbiAgICB2YXIgYWNxdWlyZXJzID0gc3RhdGUubW9kYWwudGFyZ2V0cy5maWx0ZXIoZnVuY3Rpb24gKHRhcmdldCkge1xuICAgICAgcmV0dXJuIHRhcmdldC50eXBlID09PSAnYWNxdWlyZXInO1xuICAgIH0pO1xuXG4gICAgdmFyIHByb2dyZXNzaW5kaWNhdG9ycyA9IHN0YXRlLm1vZGFsLnRhcmdldHMuZmlsdGVyKGZ1bmN0aW9uICh0YXJnZXQpIHtcbiAgICAgIHJldHVybiB0YXJnZXQudHlwZSA9PT0gJ3Byb2dyZXNzaW5kaWNhdG9yJztcbiAgICB9KTtcblxuICAgIHZhciBhZGRGaWxlID0gZnVuY3Rpb24gYWRkRmlsZShmaWxlKSB7XG4gICAgICBfdGhpczQuY29yZS5lbWl0dGVyLmVtaXQoJ2NvcmU6ZmlsZS1hZGQnLCBmaWxlKTtcbiAgICB9O1xuXG4gICAgdmFyIHJlbW92ZUZpbGUgPSBmdW5jdGlvbiByZW1vdmVGaWxlKGZpbGVJRCkge1xuICAgICAgX3RoaXM0LmNvcmUuZW1pdHRlci5lbWl0KCdjb3JlOmZpbGUtcmVtb3ZlJywgZmlsZUlEKTtcbiAgICB9O1xuXG4gICAgdmFyIHN0YXJ0VXBsb2FkID0gZnVuY3Rpb24gc3RhcnRVcGxvYWQoZXYpIHtcbiAgICAgIF90aGlzNC5jb3JlLnVwbG9hZCgpLmNhdGNoKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgLy8gTG9nIGVycm9yLlxuICAgICAgICBjb25zb2xlLmVycm9yKGVyci5zdGFjayB8fCBlcnIubWVzc2FnZSk7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdmFyIHBhdXNlVXBsb2FkID0gZnVuY3Rpb24gcGF1c2VVcGxvYWQoZmlsZUlEKSB7XG4gICAgICBfdGhpczQuY29yZS5lbWl0dGVyLmVtaXQoJ2NvcmU6dXBsb2FkLXBhdXNlJywgZmlsZUlEKTtcbiAgICB9O1xuXG4gICAgdmFyIGNhbmNlbFVwbG9hZCA9IGZ1bmN0aW9uIGNhbmNlbFVwbG9hZChmaWxlSUQpIHtcbiAgICAgIF90aGlzNC5jb3JlLmVtaXR0ZXIuZW1pdCgnY29yZTp1cGxvYWQtY2FuY2VsJywgZmlsZUlEKTtcbiAgICAgIF90aGlzNC5jb3JlLmVtaXR0ZXIuZW1pdCgnY29yZTpmaWxlLXJlbW92ZScsIGZpbGVJRCk7XG4gICAgfTtcblxuICAgIHZhciBzaG93RmlsZUNhcmQgPSBmdW5jdGlvbiBzaG93RmlsZUNhcmQoZmlsZUlEKSB7XG4gICAgICBfdGhpczQuY29yZS5lbWl0dGVyLmVtaXQoJ2Rhc2hib2FyZDpmaWxlLWNhcmQnLCBmaWxlSUQpO1xuICAgIH07XG5cbiAgICB2YXIgZmlsZUNhcmREb25lID0gZnVuY3Rpb24gZmlsZUNhcmREb25lKG1ldGEsIGZpbGVJRCkge1xuICAgICAgX3RoaXM0LmNvcmUuZW1pdHRlci5lbWl0KCdjb3JlOnVwZGF0ZS1tZXRhJywgbWV0YSwgZmlsZUlEKTtcbiAgICAgIF90aGlzNC5jb3JlLmVtaXR0ZXIuZW1pdCgnZGFzaGJvYXJkOmZpbGUtY2FyZCcpO1xuICAgIH07XG5cbiAgICB2YXIgaW5mbyA9IGZ1bmN0aW9uIGluZm8odGV4dCwgdHlwZSwgZHVyYXRpb24pIHtcbiAgICAgIF90aGlzNC5jb3JlLmVtaXR0ZXIuZW1pdCgnaW5mb3JtZXInLCB0ZXh0LCB0eXBlLCBkdXJhdGlvbik7XG4gICAgfTtcblxuICAgIHZhciByZXN1bWFibGVVcGxvYWRzID0gdGhpcy5jb3JlLmdldFN0YXRlKCkuY2FwYWJpbGl0aWVzLnJlc3VtYWJsZVVwbG9hZHMgfHwgZmFsc2U7XG5cbiAgICByZXR1cm4gRGFzaGJvYXJkKHtcbiAgICAgIHN0YXRlOiBzdGF0ZSxcbiAgICAgIG1vZGFsOiBzdGF0ZS5tb2RhbCxcbiAgICAgIG5ld0ZpbGVzOiBuZXdGaWxlcyxcbiAgICAgIGZpbGVzOiBmaWxlcyxcbiAgICAgIHRvdGFsRmlsZUNvdW50OiBPYmplY3Qua2V5cyhmaWxlcykubGVuZ3RoLFxuICAgICAgaXNVcGxvYWRTdGFydGVkOiBpc1VwbG9hZFN0YXJ0ZWQsXG4gICAgICBpblByb2dyZXNzOiB1cGxvYWRTdGFydGVkRmlsZXMubGVuZ3RoLFxuICAgICAgY29tcGxldGVGaWxlczogY29tcGxldGVGaWxlcyxcbiAgICAgIGluUHJvZ3Jlc3NGaWxlczogaW5Qcm9ncmVzc0ZpbGVzLFxuICAgICAgdG90YWxTcGVlZDogdG90YWxTcGVlZCxcbiAgICAgIHRvdGFsRVRBOiB0b3RhbEVUQSxcbiAgICAgIHRvdGFsUHJvZ3Jlc3M6IHN0YXRlLnRvdGFsUHJvZ3Jlc3MsXG4gICAgICB0b3RhbFNpemU6IHRvdGFsU2l6ZSxcbiAgICAgIHRvdGFsVXBsb2FkZWRTaXplOiB0b3RhbFVwbG9hZGVkU2l6ZSxcbiAgICAgIGlzQWxsQ29tcGxldGU6IGlzQWxsQ29tcGxldGUsXG4gICAgICBpc0FsbFBhdXNlZDogaXNBbGxQYXVzZWQsXG4gICAgICBhY3F1aXJlcnM6IGFjcXVpcmVycyxcbiAgICAgIGFjdGl2ZVBhbmVsOiBzdGF0ZS5tb2RhbC5hY3RpdmVQYW5lbCxcbiAgICAgIHByb2dyZXNzaW5kaWNhdG9yczogcHJvZ3Jlc3NpbmRpY2F0b3JzLFxuICAgICAgYXV0b1Byb2NlZWQ6IHRoaXMuY29yZS5vcHRzLmF1dG9Qcm9jZWVkLFxuICAgICAgaWQ6IHRoaXMuaWQsXG4gICAgICBoaWRlTW9kYWw6IHRoaXMuaGlkZU1vZGFsLFxuICAgICAgc2hvd1Byb2dyZXNzRGV0YWlsczogdGhpcy5vcHRzLnNob3dQcm9ncmVzc0RldGFpbHMsXG4gICAgICBpbmxpbmU6IHRoaXMub3B0cy5pbmxpbmUsXG4gICAgICBzZW1pVHJhbnNwYXJlbnQ6IHRoaXMub3B0cy5zZW1pVHJhbnNwYXJlbnQsXG4gICAgICBvblBhc3RlOiB0aGlzLmhhbmRsZVBhc3RlLFxuICAgICAgc2hvd1BhbmVsOiB0aGlzLnNob3dQYW5lbCxcbiAgICAgIGhpZGVBbGxQYW5lbHM6IHRoaXMuaGlkZUFsbFBhbmVscyxcbiAgICAgIGxvZzogdGhpcy5jb3JlLmxvZyxcbiAgICAgIGJ1czogdGhpcy5jb3JlLmVtaXR0ZXIsXG4gICAgICBpMThuOiB0aGlzLmNvbnRhaW5lcldpZHRoLFxuICAgICAgcGF1c2VBbGw6IHRoaXMucGF1c2VBbGwsXG4gICAgICByZXN1bWVBbGw6IHRoaXMucmVzdW1lQWxsLFxuICAgICAgY2FuY2VsQWxsOiB0aGlzLmNhbmNlbEFsbCxcbiAgICAgIGFkZEZpbGU6IGFkZEZpbGUsXG4gICAgICByZW1vdmVGaWxlOiByZW1vdmVGaWxlLFxuICAgICAgaW5mbzogaW5mbyxcbiAgICAgIG1ldGFGaWVsZHM6IHN0YXRlLm1ldGFGaWVsZHMsXG4gICAgICByZXN1bWFibGVVcGxvYWRzOiByZXN1bWFibGVVcGxvYWRzLFxuICAgICAgc3RhcnRVcGxvYWQ6IHN0YXJ0VXBsb2FkLFxuICAgICAgcGF1c2VVcGxvYWQ6IHBhdXNlVXBsb2FkLFxuICAgICAgY2FuY2VsVXBsb2FkOiBjYW5jZWxVcGxvYWQsXG4gICAgICBmaWxlQ2FyZEZvcjogc3RhdGUubW9kYWwuZmlsZUNhcmRGb3IsXG4gICAgICBzaG93RmlsZUNhcmQ6IHNob3dGaWxlQ2FyZCxcbiAgICAgIGZpbGVDYXJkRG9uZTogZmlsZUNhcmREb25lLFxuICAgICAgdXBkYXRlRGFzaGJvYXJkRWxXaWR0aDogdGhpcy51cGRhdGVEYXNoYm9hcmRFbFdpZHRoLFxuICAgICAgbWF4V2lkdGg6IHRoaXMub3B0cy5tYXhXaWR0aCxcbiAgICAgIG1heEhlaWdodDogdGhpcy5vcHRzLm1heEhlaWdodCxcbiAgICAgIGN1cnJlbnRXaWR0aDogc3RhdGUubW9kYWwuY29udGFpbmVyV2lkdGgsXG4gICAgICBpc1dpZGU6IHN0YXRlLm1vZGFsLmNvbnRhaW5lcldpZHRoID4gNDAwXG4gICAgfSk7XG4gIH07XG5cbiAgRGFzaGJvYXJkVUkucHJvdG90eXBlLmluc3RhbGwgPSBmdW5jdGlvbiBpbnN0YWxsKCkge1xuICAgIC8vIFNldCBkZWZhdWx0IHN0YXRlIGZvciBNb2RhbFxuICAgIHRoaXMuY29yZS5zZXRTdGF0ZSh7IG1vZGFsOiB7XG4gICAgICAgIGlzSGlkZGVuOiB0cnVlLFxuICAgICAgICBzaG93RmlsZUNhcmQ6IGZhbHNlLFxuICAgICAgICBhY3RpdmVQYW5lbDogZmFsc2UsXG4gICAgICAgIHRhcmdldHM6IFtdXG4gICAgICB9IH0pO1xuXG4gICAgdmFyIHRhcmdldCA9IHRoaXMub3B0cy50YXJnZXQ7XG4gICAgdmFyIHBsdWdpbiA9IHRoaXM7XG4gICAgdGhpcy50YXJnZXQgPSB0aGlzLm1vdW50KHRhcmdldCwgcGx1Z2luKTtcblxuICAgIHRoaXMuaW5pdEV2ZW50cygpO1xuICAgIHRoaXMuYWN0aW9ucygpO1xuICB9O1xuXG4gIERhc2hib2FyZFVJLnByb3RvdHlwZS51bmluc3RhbGwgPSBmdW5jdGlvbiB1bmluc3RhbGwoKSB7XG4gICAgdGhpcy51bm1vdW50KCk7XG4gICAgdGhpcy5yZW1vdmVBY3Rpb25zKCk7XG4gICAgdGhpcy5yZW1vdmVFdmVudHMoKTtcbiAgfTtcblxuICByZXR1cm4gRGFzaGJvYXJkVUk7XG59KFBsdWdpbik7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pbmRleC5qcy5tYXAiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfZXh0ZW5kcyA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gKHRhcmdldCkgeyBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgeyB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldOyBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7IGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoc291cmNlLCBrZXkpKSB7IHRhcmdldFtrZXldID0gc291cmNlW2tleV07IH0gfSB9IHJldHVybiB0YXJnZXQ7IH07XG5cbnZhciBfc3ZnTmFtZXNwYWNlID0gJ2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJyxcbiAgICBfYXBwZW5kQ2hpbGQgPSByZXF1aXJlKCd5by15b2lmeS9saWIvYXBwZW5kQ2hpbGQnKTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxuZnVuY3Rpb24gX3Bvc3NpYmxlQ29uc3RydWN0b3JSZXR1cm4oc2VsZiwgY2FsbCkgeyBpZiAoIXNlbGYpIHsgdGhyb3cgbmV3IFJlZmVyZW5jZUVycm9yKFwidGhpcyBoYXNuJ3QgYmVlbiBpbml0aWFsaXNlZCAtIHN1cGVyKCkgaGFzbid0IGJlZW4gY2FsbGVkXCIpOyB9IHJldHVybiBjYWxsICYmICh0eXBlb2YgY2FsbCA9PT0gXCJvYmplY3RcIiB8fCB0eXBlb2YgY2FsbCA9PT0gXCJmdW5jdGlvblwiKSA/IGNhbGwgOiBzZWxmOyB9XG5cbmZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykgeyBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09IFwiZnVuY3Rpb25cIiAmJiBzdXBlckNsYXNzICE9PSBudWxsKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiwgbm90IFwiICsgdHlwZW9mIHN1cGVyQ2xhc3MpOyB9IHN1YkNsYXNzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDbGFzcyAmJiBzdXBlckNsYXNzLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogeyB2YWx1ZTogc3ViQ2xhc3MsIGVudW1lcmFibGU6IGZhbHNlLCB3cml0YWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlIH0gfSk7IGlmIChzdXBlckNsYXNzKSBPYmplY3Quc2V0UHJvdG90eXBlT2YgPyBPYmplY3Quc2V0UHJvdG90eXBlT2Yoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzczsgfVxuXG52YXIgUGx1Z2luID0gcmVxdWlyZSgnLi8uLi9QbHVnaW4nKTtcbnZhciBUcmFuc2xhdG9yID0gcmVxdWlyZSgnLi4vLi4vY29yZS9UcmFuc2xhdG9yJyk7XG5cbnZhciBfcmVxdWlyZSA9IHJlcXVpcmUoJy4uLy4uL2NvcmUvVXRpbHMnKSxcbiAgICB0b0FycmF5ID0gX3JlcXVpcmUudG9BcnJheTtcblxudmFyIGRyYWdEcm9wID0gcmVxdWlyZSgnZHJhZy1kcm9wJyk7XG5cblxuLyoqXG4gKiBEcmFnICYgRHJvcCBwbHVnaW5cbiAqXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKF9QbHVnaW4pIHtcbiAgX2luaGVyaXRzKERyYWdEcm9wLCBfUGx1Z2luKTtcblxuICBmdW5jdGlvbiBEcmFnRHJvcChjb3JlLCBvcHRzKSB7XG4gICAgdmFyIF9wYXRoLCBfcGF0aDIsIF9wYXRoMywgX3VwcHlJY29uO1xuXG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIERyYWdEcm9wKTtcblxuICAgIHZhciBfdGhpcyA9IF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHRoaXMsIF9QbHVnaW4uY2FsbCh0aGlzLCBjb3JlLCBvcHRzKSk7XG5cbiAgICBfdGhpcy50eXBlID0gJ2FjcXVpcmVyJztcbiAgICBfdGhpcy5pZCA9ICdEcmFnRHJvcCc7XG4gICAgX3RoaXMudGl0bGUgPSAnRHJhZyAmIERyb3AnO1xuICAgIF90aGlzLmljb24gPSAoX3VwcHlJY29uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdzdmcnKSwgX3VwcHlJY29uLnNldEF0dHJpYnV0ZSgnd2lkdGgnLCAnMjgnKSwgX3VwcHlJY29uLnNldEF0dHJpYnV0ZSgnaGVpZ2h0JywgJzI4JyksIF91cHB5SWNvbi5zZXRBdHRyaWJ1dGUoJ3ZpZXdCb3gnLCAnMCAwIDE2IDE2JyksIF91cHB5SWNvbi5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlJY29uJyksIF9hcHBlbmRDaGlsZChfdXBweUljb24sIFsnICcsIChfcGF0aCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAncGF0aCcpLCBfcGF0aC5zZXRBdHRyaWJ1dGUoJ2QnLCAnTTE1Ljk4MiAyLjk3YzAtLjAyIDAtLjAyLS4wMTgtLjAzNyAwLS4wMTctLjAxNy0uMDM1LS4wMzUtLjA1MyAwIDAgMC0uMDE4LS4wMi0uMDE4LS4wMTctLjAxOC0uMDM0LS4wNTMtLjA1Mi0uMDdMMTMuMTkuMTIzYy0uMDE3LS4wMTctLjAzNC0uMDM1LS4wNy0uMDUzaC0uMDE4Yy0uMDE4LS4wMTctLjAzNS0uMDE3LS4wNTMtLjAzNGgtLjAyYy0uMDE3IDAtLjAzNC0uMDE4LS4wNTItLjAxOGgtNi4zMWEuNDE1LjQxNSAwIDAgMC0uNDQ2LjQyNlYxMS4xMWMwIC4yNS4xOTYuNDQ2LjQ0NS40NDZoOC44OUEuNDQuNDQgMCAwIDAgMTYgMTEuMTFWMy4wMjNjLS4wMTgtLjAxOC0uMDE4LS4wMzUtLjAxOC0uMDUzem0tMi42NS0xLjQ2bDEuMTU3IDEuMTU3aC0xLjE1N1YxLjUxem0xLjc4IDkuMTU3aC04Vi44OWg1LjMzMnYyLjIyYzAgLjI1LjE5Ni40NDYuNDQ1LjQ0NmgyLjIydjcuMTF6JyksIF9wYXRoKSwgJyAnLCAoX3BhdGgyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwYXRoJyksIF9wYXRoMi5zZXRBdHRyaWJ1dGUoJ2QnLCAnTTkuNzc4IDEyLjg5SDRWMi42NjZhLjQ0LjQ0IDAgMCAwLS40NDQtLjQ0NS40NC40NCAwIDAgMC0uNDQ1LjQ0NXYxMC42NjZjMCAuMjUuMTk3LjQ0NS40NDYuNDQ1aDYuMjIyYS40NC40NCAwIDAgMCAuNDQ0LS40NDUuNDQuNDQgMCAwIDAtLjQ0NC0uNDQ0eicpLCBfcGF0aDIpLCAnICcsIChfcGF0aDMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3BhdGgnKSwgX3BhdGgzLnNldEF0dHJpYnV0ZSgnZCcsICdNLjQ0NCAxNmg2LjIyM2EuNDQuNDQgMCAwIDAgLjQ0NC0uNDQ0LjQ0LjQ0IDAgMCAwLS40NDMtLjQ0NUguODlWNC44OWEuNDQuNDQgMCAwIDAtLjQ0Ni0uNDQ2QS40NC40NCAwIDAgMCAwIDQuODl2MTAuNjY2YzAgLjI0OC4xOTYuNDQ0LjQ0NC40NDR6JyksIF9wYXRoMyksICcgJ10pLCBfdXBweUljb24pO1xuXG4gICAgdmFyIGRlZmF1bHRMb2NhbGUgPSB7XG4gICAgICBzdHJpbmdzOiB7XG4gICAgICAgIGNob29zZUZpbGU6ICdDaG9vc2UgYSBmaWxlJyxcbiAgICAgICAgb3JEcmFnRHJvcDogJ29yIGRyb3AgaXQgaGVyZScsXG4gICAgICAgIHVwbG9hZDogJ1VwbG9hZCcsXG4gICAgICAgIHNlbGVjdGVkRmlsZXM6IHtcbiAgICAgICAgICAwOiAnJXtzbWFydF9jb3VudH0gZmlsZSBzZWxlY3RlZCcsXG4gICAgICAgICAgMTogJyV7c21hcnRfY291bnR9IGZpbGVzIHNlbGVjdGVkJ1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIC8vIERlZmF1bHQgb3B0aW9uc1xuICAgIHZhciBkZWZhdWx0T3B0cyA9IHtcbiAgICAgIHRhcmdldDogJy5VcHB5RHJhZ0Ryb3AnLFxuICAgICAgbG9jYWxlOiBkZWZhdWx0TG9jYWxlXG4gICAgfTtcblxuICAgIC8vIE1lcmdlIGRlZmF1bHQgb3B0aW9ucyB3aXRoIHRoZSBvbmVzIHNldCBieSB1c2VyXG4gICAgX3RoaXMub3B0cyA9IF9leHRlbmRzKHt9LCBkZWZhdWx0T3B0cywgb3B0cyk7XG5cbiAgICBfdGhpcy5sb2NhbGUgPSBfZXh0ZW5kcyh7fSwgZGVmYXVsdExvY2FsZSwgX3RoaXMub3B0cy5sb2NhbGUpO1xuICAgIF90aGlzLmxvY2FsZS5zdHJpbmdzID0gX2V4dGVuZHMoe30sIGRlZmF1bHRMb2NhbGUuc3RyaW5ncywgX3RoaXMub3B0cy5sb2NhbGUuc3RyaW5ncyk7XG5cbiAgICAvLyBDaGVjayBmb3IgYnJvd3NlciBkcmFnRHJvcCBzdXBwb3J0XG4gICAgX3RoaXMuaXNEcmFnRHJvcFN1cHBvcnRlZCA9IF90aGlzLmNoZWNrRHJhZ0Ryb3BTdXBwb3J0KCk7XG5cbiAgICAvLyBpMThuXG4gICAgX3RoaXMudHJhbnNsYXRvciA9IG5ldyBUcmFuc2xhdG9yKHsgbG9jYWxlOiBfdGhpcy5sb2NhbGUgfSk7XG4gICAgX3RoaXMuaTE4biA9IF90aGlzLnRyYW5zbGF0b3IudHJhbnNsYXRlLmJpbmQoX3RoaXMudHJhbnNsYXRvcik7XG5cbiAgICAvLyBCaW5kIGB0aGlzYCB0byBjbGFzcyBtZXRob2RzXG4gICAgX3RoaXMuaGFuZGxlRHJvcCA9IF90aGlzLmhhbmRsZURyb3AuYmluZChfdGhpcyk7XG4gICAgX3RoaXMuY2hlY2tEcmFnRHJvcFN1cHBvcnQgPSBfdGhpcy5jaGVja0RyYWdEcm9wU3VwcG9ydC5iaW5kKF90aGlzKTtcbiAgICBfdGhpcy5oYW5kbGVJbnB1dENoYW5nZSA9IF90aGlzLmhhbmRsZUlucHV0Q2hhbmdlLmJpbmQoX3RoaXMpO1xuICAgIF90aGlzLnJlbmRlciA9IF90aGlzLnJlbmRlci5iaW5kKF90aGlzKTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoZSBicm93c2VyIHN1cHBvcnRzIERyYWcgJiBEcm9wIChub3Qgc3VwcG9ydGVkIG9uIG1vYmlsZSBkZXZpY2VzLCBmb3IgZXhhbXBsZSkuXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59IHRydWUgaWYgc3VwcG9ydGVkLCBmYWxzZSBvdGhlcndpc2VcbiAgICovXG5cblxuICBEcmFnRHJvcC5wcm90b3R5cGUuY2hlY2tEcmFnRHJvcFN1cHBvcnQgPSBmdW5jdGlvbiBjaGVja0RyYWdEcm9wU3VwcG9ydCgpIHtcbiAgICB2YXIgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cbiAgICBpZiAoISgnZHJhZ2dhYmxlJyBpbiBkaXYpIHx8ICEoJ29uZHJhZ3N0YXJ0JyBpbiBkaXYgJiYgJ29uZHJvcCcgaW4gZGl2KSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmICghKCdGb3JtRGF0YScgaW4gd2luZG93KSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmICghKCdGaWxlUmVhZGVyJyBpbiB3aW5kb3cpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG5cbiAgRHJhZ0Ryb3AucHJvdG90eXBlLmhhbmRsZURyb3AgPSBmdW5jdGlvbiBoYW5kbGVEcm9wKGZpbGVzKSB7XG4gICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICB0aGlzLmNvcmUubG9nKCdBbGwgcmlnaHQsIHNvbWVvbmUgZHJvcHBlZCBzb21ldGhpbmcuLi4nKTtcblxuICAgIGZpbGVzLmZvckVhY2goZnVuY3Rpb24gKGZpbGUpIHtcbiAgICAgIF90aGlzMi5jb3JlLmFkZEZpbGUoe1xuICAgICAgICBzb3VyY2U6IF90aGlzMi5pZCxcbiAgICAgICAgbmFtZTogZmlsZS5uYW1lLFxuICAgICAgICB0eXBlOiBmaWxlLnR5cGUsXG4gICAgICAgIGRhdGE6IGZpbGVcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIERyYWdEcm9wLnByb3RvdHlwZS5oYW5kbGVJbnB1dENoYW5nZSA9IGZ1bmN0aW9uIGhhbmRsZUlucHV0Q2hhbmdlKGV2KSB7XG4gICAgdmFyIF90aGlzMyA9IHRoaXM7XG5cbiAgICB0aGlzLmNvcmUubG9nKCdBbGwgcmlnaHQsIHNvbWV0aGluZyBzZWxlY3RlZCB0aHJvdWdoIGlucHV0Li4uJyk7XG5cbiAgICB2YXIgZmlsZXMgPSB0b0FycmF5KGV2LnRhcmdldC5maWxlcyk7XG5cbiAgICBmaWxlcy5mb3JFYWNoKGZ1bmN0aW9uIChmaWxlKSB7XG4gICAgICBfdGhpczMuY29yZS5lbWl0dGVyLmVtaXQoJ2NvcmU6ZmlsZS1hZGQnLCB7XG4gICAgICAgIHNvdXJjZTogX3RoaXMzLmlkLFxuICAgICAgICBuYW1lOiBmaWxlLm5hbWUsXG4gICAgICAgIHR5cGU6IGZpbGUudHlwZSxcbiAgICAgICAgZGF0YTogZmlsZVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG5cbiAgRHJhZ0Ryb3AucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uIHJlbmRlcihzdGF0ZSkge1xuICAgIHZhciBfdGhpczQgPSB0aGlzLFxuICAgICAgICBfdXBweURyYWdEcm9wSW5wdXQsXG4gICAgICAgIF9zdHJvbmcsXG4gICAgICAgIF91cHB5RHJhZ0Ryb3BEcmFnVGV4dCxcbiAgICAgICAgX3VwcHlEcmFnRHJvcExhYmVsLFxuICAgICAgICBfdXBweURyYWdEcm9wSW5uZXIsXG4gICAgICAgIF9kaXYsXG4gICAgICAgIF91cHB5RHJhZ0Ryb3BTZWxlY3RlZENvdW50O1xuXG4gICAgdmFyIG9uU2VsZWN0ID0gZnVuY3Rpb24gb25TZWxlY3QoZXYpIHtcbiAgICAgIHZhciBpbnB1dCA9IF90aGlzNC50YXJnZXQucXVlcnlTZWxlY3RvcignLlVwcHlEcmFnRHJvcC1pbnB1dCcpO1xuICAgICAgaW5wdXQuY2xpY2soKTtcbiAgICB9O1xuXG4gICAgLy8gY29uc3QgbmV4dCA9IChldikgPT4ge1xuICAgIC8vICAgZXYucHJldmVudERlZmF1bHQoKVxuICAgIC8vICAgZXYuc3RvcFByb3BhZ2F0aW9uKClcbiAgICAvLyAgIHRoaXMuY29yZS5lbWl0dGVyLmVtaXQoJ2NvcmU6dXBsb2FkJylcbiAgICAvLyB9XG5cbiAgICAvLyBvbmxvYWQ9JHsoZXYpID0+IHtcbiAgICAvLyAgIGNvbnN0IGZpcnN0SW5wdXQgPSB0aGlzLnRhcmdldC5xdWVyeVNlbGVjdG9yKCcuVXBweURyYWdEcm9wLWZvY3VzJylcbiAgICAvLyAgIGZpcnN0SW5wdXQuZm9jdXMoKVxuICAgIC8vIH19XG5cbiAgICAvLyAkeyF0aGlzLmNvcmUub3B0cy5hdXRvUHJvY2VlZFxuICAgIC8vICAgPyBodG1sYDxidXR0b24gY2xhc3M9XCJVcHB5RHJhZ0Ryb3AtdXBsb2FkQnRuIFVwcHlOZXh0QnRuXCJcbiAgICAvLyAgICAgICAgICAgICAgICAgIHR5cGU9XCJzdWJtaXRcIlxuICAgIC8vICAgICAgICAgICAgICAgICAgb25jbGljaz0ke25leHR9PlxuICAgIC8vICAgICAgICAgICAke3RoaXMuaTE4bigndXBsb2FkJyl9XG4gICAgLy8gICAgIDwvYnV0dG9uPmBcbiAgICAvLyAgIDogJyd9XG5cbiAgICB2YXIgc2VsZWN0ZWRGaWxlc0NvdW50ID0gT2JqZWN0LmtleXMoc3RhdGUuZmlsZXMpLmxlbmd0aDtcblxuICAgIHJldHVybiBfZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksIF9kaXYuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5IFVwcHlUaGVtZS0tZGVmYXVsdCBVcHB5RHJhZ0Ryb3AtY29udGFpbmVyICcgKyBTdHJpbmcodGhpcy5pc0RyYWdEcm9wU3VwcG9ydGVkID8gJ2lzLWRyYWdkcm9wLXN1cHBvcnRlZCcgOiAnJykgKyAnJyksIF9hcHBlbmRDaGlsZChfZGl2LCBbJyAnLCAoX3VwcHlEcmFnRHJvcElubmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZm9ybScpLCBfdXBweURyYWdEcm9wSW5uZXIub25zdWJtaXQgPSBmdW5jdGlvbiAoZXYpIHtcbiAgICAgIHJldHVybiBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0sIF91cHB5RHJhZ0Ryb3BJbm5lci5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ1VwcHlEcmFnRHJvcC1pbm5lcicpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEcmFnRHJvcElubmVyLCBbJyAnLCAoX3VwcHlEcmFnRHJvcElucHV0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW5wdXQnKSwgX3VwcHlEcmFnRHJvcElucHV0LnNldEF0dHJpYnV0ZSgndHlwZScsICdmaWxlJyksIF91cHB5RHJhZ0Ryb3BJbnB1dC5zZXRBdHRyaWJ1dGUoJ25hbWUnLCAnZmlsZXNbXScpLCAndHJ1ZScgJiYgX3VwcHlEcmFnRHJvcElucHV0LnNldEF0dHJpYnV0ZSgnbXVsdGlwbGUnLCAnbXVsdGlwbGUnKSwgX3VwcHlEcmFnRHJvcElucHV0LnNldEF0dHJpYnV0ZSgndmFsdWUnLCAnJyksIF91cHB5RHJhZ0Ryb3BJbnB1dC5vbmNoYW5nZSA9IHRoaXMuaGFuZGxlSW5wdXRDaGFuZ2UuYmluZCh0aGlzKSwgX3VwcHlEcmFnRHJvcElucHV0LnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweURyYWdEcm9wLWlucHV0IFVwcHlEcmFnRHJvcC1mb2N1cycpLCBfdXBweURyYWdEcm9wSW5wdXQpLCAnICcsIChfdXBweURyYWdEcm9wTGFiZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsYWJlbCcpLCBfdXBweURyYWdEcm9wTGFiZWwub25jbGljayA9IG9uU2VsZWN0LCBfdXBweURyYWdEcm9wTGFiZWwuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RHJhZ0Ryb3AtbGFiZWwnKSwgX2FwcGVuZENoaWxkKF91cHB5RHJhZ0Ryb3BMYWJlbCwgWycgJywgKF9zdHJvbmcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzdHJvbmcnKSwgX2FwcGVuZENoaWxkKF9zdHJvbmcsIFt0aGlzLmkxOG4oJ2Nob29zZUZpbGUnKV0pLCBfc3Ryb25nKSwgJyAnLCAoX3VwcHlEcmFnRHJvcERyYWdUZXh0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpLCBfdXBweURyYWdEcm9wRHJhZ1RleHQuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RHJhZ0Ryb3AtZHJhZ1RleHQnKSwgX2FwcGVuZENoaWxkKF91cHB5RHJhZ0Ryb3BEcmFnVGV4dCwgW3RoaXMuaTE4bignb3JEcmFnRHJvcCcpXSksIF91cHB5RHJhZ0Ryb3BEcmFnVGV4dCksICcgJ10pLCBfdXBweURyYWdEcm9wTGFiZWwpLCAnICcsIHNlbGVjdGVkRmlsZXNDb3VudCA+IDAgPyAoX3VwcHlEcmFnRHJvcFNlbGVjdGVkQ291bnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSwgX3VwcHlEcmFnRHJvcFNlbGVjdGVkQ291bnQuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5RHJhZ0Ryb3Atc2VsZWN0ZWRDb3VudCcpLCBfYXBwZW5kQ2hpbGQoX3VwcHlEcmFnRHJvcFNlbGVjdGVkQ291bnQsIFsnICcsIHRoaXMuaTE4bignc2VsZWN0ZWRGaWxlcycsIHsgJ3NtYXJ0X2NvdW50Jzogc2VsZWN0ZWRGaWxlc0NvdW50IH0pLCAnICddKSwgX3VwcHlEcmFnRHJvcFNlbGVjdGVkQ291bnQpIDogJycsICcgJ10pLCBfdXBweURyYWdEcm9wSW5uZXIpLCAnICddKSwgX2RpdjtcbiAgfTtcblxuICBEcmFnRHJvcC5wcm90b3R5cGUuaW5zdGFsbCA9IGZ1bmN0aW9uIGluc3RhbGwoKSB7XG4gICAgdmFyIF90aGlzNSA9IHRoaXM7XG5cbiAgICB2YXIgdGFyZ2V0ID0gdGhpcy5vcHRzLnRhcmdldDtcbiAgICB2YXIgcGx1Z2luID0gdGhpcztcbiAgICB0aGlzLnRhcmdldCA9IHRoaXMubW91bnQodGFyZ2V0LCBwbHVnaW4pO1xuXG4gICAgdmFyIGRuZENvbnRhaW5lciA9IHRoaXMudGFyZ2V0LnF1ZXJ5U2VsZWN0b3IoJy5VcHB5RHJhZ0Ryb3AtY29udGFpbmVyJyk7XG4gICAgdGhpcy5yZW1vdmVEcmFnRHJvcExpc3RlbmVyID0gZHJhZ0Ryb3AoZG5kQ29udGFpbmVyLCBmdW5jdGlvbiAoZmlsZXMpIHtcbiAgICAgIF90aGlzNS5oYW5kbGVEcm9wKGZpbGVzKTtcbiAgICAgIF90aGlzNS5jb3JlLmxvZyhmaWxlcyk7XG4gICAgfSk7XG4gIH07XG5cbiAgRHJhZ0Ryb3AucHJvdG90eXBlLnVuaW5zdGFsbCA9IGZ1bmN0aW9uIHVuaW5zdGFsbCgpIHtcbiAgICB0aGlzLnJlbW92ZURyYWdEcm9wTGlzdGVuZXIoKTtcbiAgICB0aGlzLnVubW91bnQoKTtcbiAgfTtcblxuICByZXR1cm4gRHJhZ0Ryb3A7XG59KFBsdWdpbik7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pbmRleC5qcy5tYXAiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfc3ZnTmFtZXNwYWNlID0gJ2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJyxcbiAgICBfYXBwZW5kQ2hpbGQgPSByZXF1aXJlKCd5by15b2lmeS9saWIvYXBwZW5kQ2hpbGQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGZvbGRlcjogZnVuY3Rpb24gZm9sZGVyKCkge1xuICAgIHZhciBfcGF0aCwgX3VwcHlJY29uO1xuXG4gICAgcmV0dXJuIF91cHB5SWNvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAnc3ZnJyksIF91cHB5SWNvbi5zZXRBdHRyaWJ1dGUoJ3N0eWxlJywgJ3dpZHRoOjE2cHg7bWFyZ2luLXJpZ2h0OjNweCcpLCBfdXBweUljb24uc2V0QXR0cmlidXRlKCd2aWV3Qm94JywgJzAgMCAyNzYuMTU3IDI3Ni4xNTcnKSwgX3VwcHlJY29uLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnVXBweUljb24nKSwgX2FwcGVuZENoaWxkKF91cHB5SWNvbiwgWycgJywgKF9wYXRoID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwYXRoJyksIF9wYXRoLnNldEF0dHJpYnV0ZSgnZCcsICdNMjczLjA4IDEwMS4zNzhjLTMuMy00LjY1LTguODYtNy4zMi0xNS4yNTQtNy4zMmgtMjQuMzRWNjcuNTljMC0xMC4yLTguMy0xOC41LTE4LjUtMTguNWgtODUuMzIyYy0zLjYzIDAtOS4yOTUtMi44NzUtMTEuNDM2LTUuODA1bC02LjM4Ni04LjczNWMtNC45ODItNi44MTQtMTUuMTA0LTExLjk1NC0yMy41NDYtMTEuOTU0SDU4LjczYy05LjI5MiAwLTE4LjYzOCA2LjYwOC0yMS43MzcgMTUuMzcybC0yLjAzMyA1Ljc1MmMtLjk1OCAyLjcxLTQuNzIgNS4zNy03LjU5NiA1LjM3SDE4LjVDOC4zIDQ5LjA5IDAgNTcuMzkgMCA2Ny41OXYxNjcuMDdjMCAuODg2LjE2IDEuNzMuNDQzIDIuNTIuMTUyIDMuMzA2IDEuMTggNi40MjQgMy4wNTMgOS4wNjQgMy4zIDQuNjUyIDguODYgNy4zMiAxNS4yNTUgNy4zMmgxODguNDg3YzExLjM5NSAwIDIzLjI3LTguNDI1IDI3LjAzNS0xOS4xOGw0MC42NzctMTE2LjE4OGMyLjExLTYuMDM1IDEuNDMtMTIuMTY0LTEuODctMTYuODE2ek0xOC41IDY0LjA4OGg4Ljg2NGM5LjI5NSAwIDE4LjY0LTYuNjA3IDIxLjczOC0xNS4zN2wyLjAzMi01Ljc1Yy45Ni0yLjcxMiA0LjcyMi01LjM3MyA3LjU5Ny01LjM3M2gyOS41NjVjMy42MyAwIDkuMjk1IDIuODc2IDExLjQzNyA1LjgwNmw2LjM4NiA4LjczNWM0Ljk4MiA2LjgxNSAxNS4xMDQgMTEuOTU0IDIzLjU0NiAxMS45NTRoODUuMzIyYzEuODk4IDAgMy41IDEuNjAyIDMuNSAzLjV2MjYuNDdINjkuMzRjLTExLjM5NSAwLTIzLjI3IDguNDIzLTI3LjAzNSAxOS4xNzhMMTUgMTkxLjIzVjY3LjU5YzAtMS44OTggMS42MDMtMy41IDMuNS0zLjV6bTI0Mi4yOSA0OS4xNWwtNDAuNjc2IDExNi4xODhjLTEuNjc0IDQuNzgtNy44MTIgOS4xMzUtMTIuODc3IDkuMTM1SDE4Ljc1Yy0xLjQ0NyAwLTIuNTc2LS4zNzItMy4wMi0uOTk3LS40NDItLjYyNS0uNDIyLTEuODE0LjA1Ny0zLjE4bDQwLjY3Ny0xMTYuMTljMS42NzQtNC43OCA3LjgxMi05LjEzNCAxMi44NzctOS4xMzRoMTg4LjQ4N2MxLjQ0OCAwIDIuNTc3LjM3MiAzLjAyLjk5Ny40NDMuNjI1LjQyMyAxLjgxNC0uMDU2IDMuMTh6JyksIF9wYXRoKSwgJyAnXSksIF91cHB5SWNvbjtcbiAgfSxcbiAgbXVzaWM6IGZ1bmN0aW9uIG11c2ljKCkge1xuICAgIHZhciBfcGF0aDIsIF9wYXRoMywgX3BhdGg0LCBfcGF0aDUsIF9nLCBfdXBweUljb24yO1xuXG4gICAgcmV0dXJuIF91cHB5SWNvbjIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3N2ZycpLCBfdXBweUljb24yLnNldEF0dHJpYnV0ZSgnd2lkdGgnLCAnMTYuMDAwMDAwcHQnKSwgX3VwcHlJY29uMi5zZXRBdHRyaWJ1dGUoJ2hlaWdodCcsICcxNi4wMDAwMDBwdCcpLCBfdXBweUljb24yLnNldEF0dHJpYnV0ZSgndmlld0JveCcsICcwIDAgNDguMDAwMDAwIDQ4LjAwMDAwMCcpLCBfdXBweUljb24yLnNldEF0dHJpYnV0ZSgncHJlc2VydmVBc3BlY3RSYXRpbycsICd4TWlkWU1pZCBtZWV0JyksIF91cHB5SWNvbjIuc2V0QXR0cmlidXRlKCdjbGFzcycsICdVcHB5SWNvbicpLCBfYXBwZW5kQ2hpbGQoX3VwcHlJY29uMiwgWycgJywgKF9nID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdnJyksIF9nLnNldEF0dHJpYnV0ZSgndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgwLjAwMDAwMCw0OC4wMDAwMDApIHNjYWxlKDAuMTAwMDAwLC0wLjEwMDAwMCknKSwgX2cuc2V0QXR0cmlidXRlKCdmaWxsJywgJyM1MjUwNTAnKSwgX2cuc2V0QXR0cmlidXRlKCdzdHJva2UnLCAnbm9uZScpLCBfYXBwZW5kQ2hpbGQoX2csIFsnICcsIChfcGF0aDIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoX3N2Z05hbWVzcGFjZSwgJ3BhdGgnKSwgX3BhdGgyLnNldEF0dHJpYnV0ZSgnZCcsICdNMjA5IDQ3MyBjMCAtNSAwIC01MiAxIC0xMDYgMSAtNTQgLTIgLTExOCAtNiAtMTQzIGwtNyAtNDYgLTQ0IDVcXG4gICAgYy03MyA4IC0xMzMgLTQ2IC0xMzMgLTEyMCAwIC0xNyAtNSAtMzUgLTEwIC0zOCAtMTggLTExIDAgLTI1IDMzIC0yNCAzMCAxIDMwXFxuICAgIDEgNyA4IC0xNSA0IC0yMCAxMCAtMTMgMTQgNiA0IDkgMTYgNiAyNyAtOSAzNCA3IDcwIDQwIDkwIDE3IDExIDM5IDIwIDQ3IDIwXFxuICAgIDggMCAtMyAtOSAtMjYgLTE5IC00MiAtMTkgLTU0IC0zNiAtNTQgLTc1IDAgLTM2IDMwIC01NiA4NCAtNTYgNDEgMCA1MyA1IDgyXFxuICAgIDM0IDE5IDE5IDM0IDMxIDM0IDI3IDAgLTQgLTUgLTEyIC0xMiAtMTkgLTkgLTkgLTEgLTEyIDM5IC0xMiAxMDYgMCAxODMgLTIxXFxuICAgIDEyMSAtMzMgLTE3IC0zIC0xNCAtNSAxMCAtNiAyNSAtMSAzMiAzIDMyIDE3IDAgMjYgLTIwIDQyIC01MSA0MiAtMzkgMCAtNDNcXG4gICAgMTMgLTEwIDM4IDU2IDQxIDc2IDEyNCA0NSAxODUgLTI1IDQ4IC03MiAxMDUgLTEwMyAxMjMgLTE1IDkgLTM2IDI5IC00NyA0NVxcbiAgICAtMTcgMjYgLTYzIDQxIC02NSAyMnogbTU2IC00OCBjMTYgLTI0IDMxIC00MiAzNCAtMzkgOSA5IDc5IC02OSA3NCAtODMgLTMgLTdcXG4gICAgLTIgLTEzIDMgLTEyIDE4IDMgMjUgLTEgMTkgLTEyIC01IC03IC0xNiAtMiAtMzMgMTMgbC0yNiAyMyAxNiAtMjUgYzE3IC0yN1xcbiAgICAyOSAtOTIgMTYgLTg0IC00IDMgLTggLTggLTggLTI1IDAgLTE2IDQgLTMzIDEwIC0zNiA1IC0zIDcgMCA0IDkgLTMgOSAzIDIwXFxuICAgIDE1IDI4IDEzIDggMjEgMjQgMjIgNDMgMSAxOCAzIDIzIDYgMTIgMyAtMTAgMiAtMjkgLTEgLTQzIC03IC0yNiAtNjIgLTk0IC03N1xcbiAgICAtOTQgLTEzIDAgLTExIDE3IDQgMzIgMjEgMTkgNCA4OCAtMjggMTE1IC0xNCAxMyAtMjIgMjMgLTE2IDIzIDUgMCAyMSAtMTQgMzVcXG4gICAgLTMxIDE0IC0xNyAyNiAtMjUgMjYgLTE5IDAgMjEgLTYwIDcyIC03OSA2NyAtMTYgLTQgLTE3IC0xIC04IDM0IDYgMjQgMTQgMzZcXG4gICAgMjEgMzIgNiAtMyAxIDUgLTExIDE4IC0xMiAxMyAtMjIgMjkgLTIzIDM0IC0xIDYgLTYgMTcgLTEyIDI1IC02IDEwIC03IC0zOVxcbiAgICAtNCAtMTQyIGw2IC0xNTggLTI2IDEwIGMtMzMgMTMgLTQ0IDEyIC0yMSAtMSAxNyAtMTAgMjQgLTQ0IDEwIC01MiAtNSAtMyAtMzlcXG4gICAgLTggLTc2IC0xMiAtNjggLTcgLTY5IC03IC02NSAxNyA0IDI4IDY0IDYwIDExNyA2MiBsMzYgMSAwIDE1NyBjMCA4NyAyIDE1OCA1XFxuICAgIDE1OCAzIDAgMTggLTIwIDM1IC00NXogbTE1IC0xNTkgYzAgLTIgLTcgLTcgLTE2IC0xMCAtOCAtMyAtMTIgLTIgLTkgNCA2IDEwXFxuICAgIDI1IDE0IDI1IDZ6IG01MCAtOTIgYzAgLTEzIC00IC0yNiAtMTAgLTI5IC0xNCAtOSAtMTMgLTQ4IDIgLTYzIDkgLTkgNiAtMTJcXG4gICAgLTE1IC0xMiAtMjIgMCAtMjcgNSAtMjcgMjQgMCAxNCAtNCAyOCAtMTAgMzEgLTE1IDkgLTEzIDEwMiAzIDEwOCAxOCA3IDU3XFxuICAgIC0zMyA1NyAtNTl6IG0tMTM5IC0xMzUgYy0zMiAtMjYgLTEyMSAtMjUgLTEyMSAyIDAgNiA4IDUgMTkgLTEgMjYgLTE0IDY0IC0xM1xcbiAgICA1NSAxIC00IDggMSA5IDE2IDQgMTMgLTQgMjAgLTMgMTcgMiAtMyA1IDQgMTAgMTYgMTAgMjIgMiAyMiAyIC0yIC0xOHonKSwgX3BhdGgyKSwgJyAnLCAoX3BhdGgzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwYXRoJyksIF9wYXRoMy5zZXRBdHRyaWJ1dGUoJ2QnLCAnTTMzMCAzNDUgYzE5IC0xOSAzNiAtMzUgMzkgLTM1IDMgMCAtMTAgMTYgLTI5IDM1IC0xOSAxOSAtMzYgMzUgLTM5XFxuICAgIDM1IC0zIDAgMTAgLTE2IDI5IC0zNXonKSwgX3BhdGgzKSwgJyAnLCAoX3BhdGg0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdwYXRoJyksIF9wYXRoNC5zZXRBdHRyaWJ1dGUoJ2QnLCAnTTM0OSAxMjMgYy0xMyAtMTYgLTEyIC0xNyA0IC00IDE2IDEzIDIxIDIxIDEzIDIxIC0yIDAgLTEwIC04IC0xN1xcbiAgICAtMTd6JyksIF9wYXRoNCksICcgJywgKF9wYXRoNSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhfc3ZnTmFtZXNwYWNlLCAncGF0aCcpLCBfcGF0aDUuc2V0QXR0cmlidXRlKCdkJywgJ00yNDMgMTMgYzE1IC0yIDM5IC0yIDU1IDAgMTUgMiAyIDQgLTI4IDQgLTMwIDAgLTQzIC0yIC0yNyAtNHonKSwgX3BhdGg1KSwgJyAnXSksIF9nKSwgJyAnXSksIF91cHB5SWNvbjI7XG4gIH0sXG4gIHBhZ2Vfd2hpdGVfcGljdHVyZTogZnVuY3Rpb24gcGFnZV93aGl0ZV9waWN0dXJlKCkge1xuICAgIHZhciBfcGF0aDYsIF9wYXRoNywgX3BhdGg4LCBfcGF0aDksIF9wYXRoMTAsIF9wYXRoMTEsIF9wYXRoMTIsIF9wYXRoMTMsIF9wYXRoMTQsIF9nMiwgX3VwcHlJY29uMztcblxuICAgIHJldHVybiBfdXBweUljb24zID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKF9zdmdOYW1lc3BhY2UsICdzdmcnKSwgX3VwcHlJY29uMy5zZXRBdHRyaWJ1dGUoJ3dpZHRoJywgJzE2LjAwMDAwMHB0JyksIF91cHB5SWNvbjMuc2V0QXR0cmlidXRlKCdoZWlnaHQnLCAnMTYuMDAwMDAwcHQnKSwgX3VwcHlJY29uMy5zZXRBdHRyaWJ1dGUoJ3ZpZXdCb3gnLCAnMCAwIDQ4LjAwMDAwMCAzNi4wMDAwMDAnKSwgX3VwcHlJY2
View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment