appium-ios-simulator
Version:
iOS Simulator interface for Appium.
659 lines (516 loc) • 40.9 kB
JavaScript
;
var _defineProperty = require('babel-runtime/helpers/define-property')['default'];
var _slicedToArray = require('babel-runtime/helpers/sliced-to-array')['default'];
var _regeneratorRuntime = require('babel-runtime/regenerator')['default'];
var _getIterator = require('babel-runtime/core-js/get-iterator')['default'];
var _Symbol$iterator = require('babel-runtime/core-js/symbol/iterator')['default'];
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
Object.defineProperty(exports, '__esModule', {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _appiumSupport = require('appium-support');
var _path3 = require('path');
var _path4 = _interopRequireDefault(_path3);
var _logger = require('./logger');
var _logger2 = _interopRequireDefault(_logger);
// returns path to plist based on id for plist.
// these ids are appium terms
function plistPaths(sim, identifier) {
var paths;
return _regeneratorRuntime.async(function plistPaths$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
paths = [];
context$1$0.t0 = identifier;
context$1$0.next = context$1$0.t0 === 'webInspector' ? 4 : context$1$0.t0 === 'mobileSafari' ? 6 : context$1$0.t0 === 'webUI' ? 14 : context$1$0.t0 === 'webFoundation' ? 16 : context$1$0.t0 === 'preferences' ? 18 : context$1$0.t0 === 'locationServices' ? 20 : context$1$0.t0 === 'locationClients' ? 22 : context$1$0.t0 === 'locationCache' ? 24 : context$1$0.t0 === 'userSettings' ? 27 : context$1$0.t0 === 'effectiveUserSettings' ? 31 : 34;
break;
case 4:
paths.push(_path4['default'].resolve(sim.getDir(), 'Library', 'Preferences', 'com.apple.webInspector.plist'));
return context$1$0.abrupt('break', 34);
case 6:
context$1$0.t1 = paths;
context$1$0.t2 = _path4['default'];
context$1$0.next = 10;
return _regeneratorRuntime.awrap(sim.getAppDir('com.apple.mobilesafari'));
case 10:
context$1$0.t3 = context$1$0.sent;
context$1$0.t4 = context$1$0.t2.resolve.call(context$1$0.t2, context$1$0.t3, 'Library', 'Preferences', 'com.apple.mobilesafari.plist');
context$1$0.t1.push.call(context$1$0.t1, context$1$0.t4);
return context$1$0.abrupt('break', 34);
case 14:
paths.push(_path4['default'].resolve(sim.getDir(), 'Library', 'Preferences', 'com.apple.WebUI.plist'));
return context$1$0.abrupt('break', 34);
case 16:
paths.push(_path4['default'].resolve(sim.getDir(), 'Library', 'Preferences', 'com.apple.WebFoundation.plist'));
return context$1$0.abrupt('break', 34);
case 18:
paths.push(_path4['default'].resolve(sim.getDir(), 'Library', 'Preferences', 'com.apple.Preferences.plist'));
return context$1$0.abrupt('break', 34);
case 20:
paths.push(_path4['default'].resolve(sim.getDir(), 'Library', 'Preferences', 'com.apple.locationd.plist'));
return context$1$0.abrupt('break', 34);
case 22:
paths.push(_path4['default'].resolve(sim.getDir(), 'Library', 'Caches', 'locationd', 'clients.plist'));
return context$1$0.abrupt('break', 34);
case 24:
paths.push(_path4['default'].resolve(sim.getDir(), 'Library', 'Caches', 'locationd', 'cache.plist'));
paths.push(_path4['default'].resolve(sim.getDir(), 'Library', 'Preferences', 'com.apple.locationd.plist'));
return context$1$0.abrupt('break', 34);
case 27:
paths.push(_path4['default'].resolve(sim.getDir(), 'Library', 'ConfigurationProfiles', 'UserSettings.plist'));
paths.push(_path4['default'].resolve(sim.getDir(), 'Library', 'ConfigurationProfiles', 'EffectiveUserSettings.plist'));
paths.push(_path4['default'].resolve(sim.getDir(), 'Library', 'ConfigurationProfiles', 'PublicInfo', 'PublicEffectiveUserSettings.plist'));
return context$1$0.abrupt('break', 34);
case 31:
paths.push(_path4['default'].resolve(sim.getDir(), 'Libary', 'ConfigurationProfiles', 'EffectiveUserSettings.plist'));
paths.push(_path4['default'].resolve(sim.getDir(), 'Library', 'ConfigurationProfiles', 'PublicInfo', 'PublicEffectiveUserSettings.plist'));
return context$1$0.abrupt('break', 34);
case 34:
return context$1$0.abrupt('return', paths);
case 35:
case 'end':
return context$1$0.stop();
}
}, null, this);
}
function updateSettings(sim, plist, updates) {
var paths, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _path;
return _regeneratorRuntime.async(function updateSettings$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
_logger2['default'].debug('Updating settings for \'' + plist + '\'');
context$1$0.next = 3;
return _regeneratorRuntime.awrap(plistPaths(sim, plist));
case 3:
paths = context$1$0.sent;
_iteratorNormalCompletion = true;
_didIteratorError = false;
_iteratorError = undefined;
context$1$0.prev = 7;
_iterator = _getIterator(paths);
case 9:
if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
context$1$0.next = 16;
break;
}
_path = _step.value;
context$1$0.next = 13;
return _regeneratorRuntime.awrap(update(_path, updates));
case 13:
_iteratorNormalCompletion = true;
context$1$0.next = 9;
break;
case 16:
context$1$0.next = 22;
break;
case 18:
context$1$0.prev = 18;
context$1$0.t0 = context$1$0['catch'](7);
_didIteratorError = true;
_iteratorError = context$1$0.t0;
case 22:
context$1$0.prev = 22;
context$1$0.prev = 23;
if (!_iteratorNormalCompletion && _iterator['return']) {
_iterator['return']();
}
case 25:
context$1$0.prev = 25;
if (!_didIteratorError) {
context$1$0.next = 28;
break;
}
throw _iteratorError;
case 28:
return context$1$0.finish(25);
case 29:
return context$1$0.finish(22);
case 30:
case 'end':
return context$1$0.stop();
}
}, null, this, [[7, 18, 22, 30], [23,, 25, 29]]);
}
// update a plist file, located at pathToPlist
// pass in an object, all settings specified in the object will be
// updated on the plist, all others left as-is
function update(pathToPlist, updates) {
var currentSettings, newSettings;
return _regeneratorRuntime.async(function update$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
_logger2['default'].debug('Updating settings for \'' + pathToPlist + '\'');
_logger2['default'].debug(' ' + JSON.stringify(updates));
context$1$0.next = 4;
return _regeneratorRuntime.awrap(read(pathToPlist));
case 4:
currentSettings = context$1$0.sent;
newSettings = _lodash2['default'].merge(currentSettings, updates);
context$1$0.next = 8;
return _regeneratorRuntime.awrap(_appiumSupport.plist.updatePlistFile(pathToPlist, newSettings, true, false));
case 8:
return context$1$0.abrupt('return', newSettings);
case 9:
case 'end':
return context$1$0.stop();
}
}, null, this);
}
function readSettings(sim, plist) {
var settings, paths, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, _path2;
return _regeneratorRuntime.async(function readSettings$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
_logger2['default'].debug('Retrieving settings for \'' + plist + '\'');
settings = {};
context$1$0.next = 4;
return _regeneratorRuntime.awrap(plistPaths(sim, plist));
case 4:
paths = context$1$0.sent;
_iteratorNormalCompletion2 = true;
_didIteratorError2 = false;
_iteratorError2 = undefined;
context$1$0.prev = 8;
_iterator2 = _getIterator(paths);
case 10:
if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) {
context$1$0.next = 18;
break;
}
_path2 = _step2.value;
context$1$0.next = 14;
return _regeneratorRuntime.awrap(read(_path2));
case 14:
settings[_path2] = context$1$0.sent;
case 15:
_iteratorNormalCompletion2 = true;
context$1$0.next = 10;
break;
case 18:
context$1$0.next = 24;
break;
case 20:
context$1$0.prev = 20;
context$1$0.t0 = context$1$0['catch'](8);
_didIteratorError2 = true;
_iteratorError2 = context$1$0.t0;
case 24:
context$1$0.prev = 24;
context$1$0.prev = 25;
if (!_iteratorNormalCompletion2 && _iterator2['return']) {
_iterator2['return']();
}
case 27:
context$1$0.prev = 27;
if (!_didIteratorError2) {
context$1$0.next = 30;
break;
}
throw _iteratorError2;
case 30:
return context$1$0.finish(27);
case 31:
return context$1$0.finish(24);
case 32:
return context$1$0.abrupt('return', settings);
case 33:
case 'end':
return context$1$0.stop();
}
}, null, this, [[8, 20, 24, 32], [25,, 27, 31]]);
}
function read(pathToPlist) {
return _regeneratorRuntime.async(function read$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
_logger2['default'].debug('Retrieving settings for ' + pathToPlist);
context$1$0.next = 3;
return _regeneratorRuntime.awrap(_appiumSupport.plist.parsePlistFile(pathToPlist, false));
case 3:
return context$1$0.abrupt('return', context$1$0.sent);
case 4:
case 'end':
return context$1$0.stop();
}
}, null, this);
}
function updateLocationSettings(sim, bundleId, authorized) {
var newCachePrefs, newClientPrefs, _iteratorNormalCompletion3, _didIteratorError3, _iteratorError3, _iterator3, _step3, file, updates, _plist, weirdLocKey, baseSetting;
return _regeneratorRuntime.async(function updateLocationSettings$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
newCachePrefs = {
LastFenceActivityTimestamp: 412122103.232983,
CleanShutdown: true
};
context$1$0.next = 3;
return _regeneratorRuntime.awrap(updateSettings(sim, 'locationCache', _defineProperty({}, bundleId, newCachePrefs)));
case 3:
newClientPrefs = {
BundleId: bundleId,
Authorized: !!authorized,
Whitelisted: false
};
_iteratorNormalCompletion3 = true;
_didIteratorError3 = false;
_iteratorError3 = undefined;
context$1$0.prev = 7;
context$1$0.next = 10;
return _regeneratorRuntime.awrap(plistPaths(sim, 'locationClients'));
case 10:
context$1$0.t0 = _Symbol$iterator;
_iterator3 = context$1$0.sent[context$1$0.t0]();
case 12:
if (_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done) {
context$1$0.next = 30;
break;
}
file = _step3.value;
_logger2['default'].debug('Updating location client file: ' + file);
updates = {};
context$1$0.next = 18;
return _regeneratorRuntime.awrap(read(file));
case 18:
_plist = context$1$0.sent;
weirdLocKey = 'com.apple.locationd.bundle-/System/Library/' + 'PrivateFrameworks/AOSNotification.framework';
if (!_lodash2['default'].has(_plist, weirdLocKey)) {
updates[weirdLocKey] = {
BundlePath: '/System/Library/PrivateFrameworks/AOSNotification.framework',
Whitelisted: false,
Executable: '',
Registered: ''
};
}
// create the update, and make sure it has sensible values
baseSetting = _lodash2['default'].has(_plist, bundleId) ? _plist[bundleId] : {};
updates[bundleId] = _lodash2['default'].defaults(newClientPrefs, baseSetting);
updates[bundleId].Executable = updates[bundleId].Executable || '';
updates[bundleId].Registered = updates[bundleId].Registered || '';
context$1$0.next = 27;
return _regeneratorRuntime.awrap(update(file, updates));
case 27:
_iteratorNormalCompletion3 = true;
context$1$0.next = 12;
break;
case 30:
context$1$0.next = 36;
break;
case 32:
context$1$0.prev = 32;
context$1$0.t1 = context$1$0['catch'](7);
_didIteratorError3 = true;
_iteratorError3 = context$1$0.t1;
case 36:
context$1$0.prev = 36;
context$1$0.prev = 37;
if (!_iteratorNormalCompletion3 && _iterator3['return']) {
_iterator3['return']();
}
case 39:
context$1$0.prev = 39;
if (!_didIteratorError3) {
context$1$0.next = 42;
break;
}
throw _iteratorError3;
case 42:
return context$1$0.finish(39);
case 43:
return context$1$0.finish(36);
case 44:
case 'end':
return context$1$0.stop();
}
}, null, this, [[7, 32, 36, 44], [37,, 39, 43]]);
}
function updateSafariUserSettings(sim, settingSet) {
var newUserSettings, curUserSettings, _iteratorNormalCompletion4, _didIteratorError4, _iteratorError4, _iterator4, _step4, _step4$value, file, userSettingSet, _iteratorNormalCompletion5, _didIteratorError5, _iteratorError5, _iterator5, _step5, _step5$value, key, value;
return _regeneratorRuntime.async(function updateSafariUserSettings$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
newUserSettings = {};
if (_lodash2['default'].has(settingSet, 'WebKitJavaScriptEnabled')) {
newUserSettings.safariAllowJavaScript = settingSet.WebKitJavaScriptEnabled;
}
if (_lodash2['default'].has(settingSet, 'WebKitJavaScriptCanOpenWindowsAutomatically')) {
newUserSettings.safariAllowPopups = settingSet.WebKitJavaScriptCanOpenWindowsAutomatically;
}
if (_lodash2['default'].has(settingSet, 'WarnAboutFraudulentWebsites')) {
newUserSettings.safariForceFraudWarning = !settingSet.WarnAboutFraudulentWebsites;
}
if (!(_lodash2['default'].size(newUserSettings) > 0)) {
context$1$0.next = 57;
break;
}
_logger2['default'].debug('Updating Safari user settings');
context$1$0.next = 8;
return _regeneratorRuntime.awrap(readSettings(sim, 'userSettings'));
case 8:
curUserSettings = context$1$0.sent;
_iteratorNormalCompletion4 = true;
_didIteratorError4 = false;
_iteratorError4 = undefined;
context$1$0.prev = 12;
_iterator4 = _getIterator(_lodash2['default'].pairs(curUserSettings));
case 14:
if (_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done) {
context$1$0.next = 43;
break;
}
_step4$value = _slicedToArray(_step4.value, 2);
file = _step4$value[0];
userSettingSet = _step4$value[1];
// the user settings plist has two buckets, one for
// boolean settings (`restrictedBool`) and one for
// other value settings (`restrictedValue`). In each, the value
// is in a `value` sub-field.
if (!_lodash2['default'].has(userSettingSet, 'restrictedBool')) {
userSettingSet.restrictedBool = {};
}
_iteratorNormalCompletion5 = true;
_didIteratorError5 = false;
_iteratorError5 = undefined;
context$1$0.prev = 22;
for (_iterator5 = _getIterator(_lodash2['default'].pairs(newUserSettings)); !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
_step5$value = _slicedToArray(_step5.value, 2);
key = _step5$value[0];
value = _step5$value[1];
userSettingSet.restrictedBool[key] = { value: value };
}
// actually do the update
context$1$0.next = 30;
break;
case 26:
context$1$0.prev = 26;
context$1$0.t0 = context$1$0['catch'](22);
_didIteratorError5 = true;
_iteratorError5 = context$1$0.t0;
case 30:
context$1$0.prev = 30;
context$1$0.prev = 31;
if (!_iteratorNormalCompletion5 && _iterator5['return']) {
_iterator5['return']();
}
case 33:
context$1$0.prev = 33;
if (!_didIteratorError5) {
context$1$0.next = 36;
break;
}
throw _iteratorError5;
case 36:
return context$1$0.finish(33);
case 37:
return context$1$0.finish(30);
case 38:
context$1$0.next = 40;
return _regeneratorRuntime.awrap(update(file, userSettingSet));
case 40:
_iteratorNormalCompletion4 = true;
context$1$0.next = 14;
break;
case 43:
context$1$0.next = 49;
break;
case 45:
context$1$0.prev = 45;
context$1$0.t1 = context$1$0['catch'](12);
_didIteratorError4 = true;
_iteratorError4 = context$1$0.t1;
case 49:
context$1$0.prev = 49;
context$1$0.prev = 50;
if (!_iteratorNormalCompletion4 && _iterator4['return']) {
_iterator4['return']();
}
case 52:
context$1$0.prev = 52;
if (!_didIteratorError4) {
context$1$0.next = 55;
break;
}
throw _iteratorError4;
case 55:
return context$1$0.finish(52);
case 56:
return context$1$0.finish(49);
case 57:
case 'end':
return context$1$0.stop();
}
}, null, this, [[12, 45, 49, 57], [22, 26, 30, 38], [31,, 33, 37], [50,, 52, 56]]);
}
function updateLocale(sim, language, locale, calendarFormat) {
var globalPrefs, data, updates, supportedLangs, calSplit, curLocaleAndCal, split, curLoc, newLocaleAndCal;
return _regeneratorRuntime.async(function updateLocale$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
globalPrefs = _path4['default'].resolve(sim.getDir(), 'Library', 'Preferences', '.GlobalPreferences.plist');
context$1$0.next = 3;
return _regeneratorRuntime.awrap(read(globalPrefs));
case 3:
data = context$1$0.sent;
updates = {};
// if we are setting the language, add it to the list of languages
if (language) {
_logger2['default'].debug('New language: ' + language);
supportedLangs = data.AppleLanguages || [];
updates.AppleLanguages = [language].concat(_lodash2['default'].without(supportedLangs, language));
}
// if we are setting the locale or calendar format, set them as appropriate
if (locale || calendarFormat) {
calSplit = '@calendar=';
curLocaleAndCal = data.AppleLocale || language || 'en';
split = curLocaleAndCal.split(calSplit);
curLoc = split[0];
if (calendarFormat || split[1]) {
calendarFormat = '' + calSplit + (calendarFormat || split[1] || '');
}
calendarFormat = calendarFormat || '';
newLocaleAndCal = locale ? locale : curLoc;
if (calendarFormat) {
newLocaleAndCal = '' + newLocaleAndCal + calendarFormat;
}
_logger2['default'].debug('New locale: ' + newLocaleAndCal);
updates.AppleLocale = newLocaleAndCal;
}
_logger2['default'].debug('Writing new locale plist data');
context$1$0.next = 10;
return _regeneratorRuntime.awrap(update(globalPrefs, updates));
case 10:
case 'end':
return context$1$0.stop();
}
}, null, this);
}
function stub() {
return _regeneratorRuntime.async(function stub$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
context$1$0.next = 2;
return _regeneratorRuntime.awrap(plistPaths);
case 2:
return context$1$0.abrupt('return', context$1$0.sent);
case 3:
case 'end':
return context$1$0.stop();
}
}, null, this);
}
exports.update = update;
exports.updateSettings = updateSettings;
exports.updateLocationSettings = updateLocationSettings;
exports.updateSafariUserSettings = updateSafariUserSettings;
exports.updateLocale = updateLocale;
exports.read = read;
exports.readSettings = readSettings;
exports.stub = stub;
// update location cache
// update location clients
// see if the bundle is already there
// random data that always seems to be in the clients.plist
// add extra stuff to UserSettings.plist and EffectiveUserSettings.plist
// get the current data
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi9zZXR0aW5ncy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7c0JBQWMsUUFBUTs7Ozs2QkFDQSxnQkFBZ0I7O3FCQUNyQixNQUFNOzs7O3NCQUNQLFVBQVU7Ozs7OztBQUsxQixTQUFlLFVBQVUsQ0FBRSxHQUFHLEVBQUUsVUFBVTtNQUNwQyxLQUFLOzs7O0FBQUwsYUFBSyxHQUFHLEVBQUU7eUJBQ04sVUFBVTs4Q0FDWCxjQUFjLDBCQUdkLGNBQWMsMEJBR2QsT0FBTywyQkFHUCxlQUFlLDJCQUdmLGFBQWEsMkJBR2Isa0JBQWtCLDJCQUdsQixpQkFBaUIsMkJBR2pCLGVBQWUsMkJBSWYsY0FBYywyQkFLZCx1QkFBdUI7Ozs7QUE3QjFCLGFBQUssQ0FBQyxJQUFJLENBQUMsa0JBQUssT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxTQUFTLEVBQUUsYUFBYSxFQUFFLDhCQUE4QixDQUFDLENBQUMsQ0FBQzs7Ozt5QkFHakcsS0FBSzs7O3lDQUF5QixHQUFHLENBQUMsU0FBUyxDQUFDLHdCQUF3QixDQUFDOzs7O3dDQUFyRCxPQUFPLHNDQUFnRCxTQUFTLEVBQUUsYUFBYSxFQUFFLDhCQUE4Qjt1QkFBekgsSUFBSTs7OztBQUdWLGFBQUssQ0FBQyxJQUFJLENBQUMsa0JBQUssT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxTQUFTLEVBQUUsYUFBYSxFQUFFLHVCQUF1QixDQUFDLENBQUMsQ0FBQzs7OztBQUcxRixhQUFLLENBQUMsSUFBSSxDQUFDLGtCQUFLLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSwrQkFBK0IsQ0FBQyxDQUFDLENBQUM7Ozs7QUFHbEcsYUFBSyxDQUFDLElBQUksQ0FBQyxrQkFBSyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxFQUFFLFNBQVMsRUFBRSxhQUFhLEVBQUUsNkJBQTZCLENBQUMsQ0FBQyxDQUFDOzs7O0FBR2hHLGFBQUssQ0FBQyxJQUFJLENBQUMsa0JBQUssT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxTQUFTLEVBQUUsYUFBYSxFQUFFLDJCQUEyQixDQUFDLENBQUMsQ0FBQzs7OztBQUc5RixhQUFLLENBQUMsSUFBSSxDQUFDLGtCQUFLLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsZUFBZSxDQUFDLENBQUMsQ0FBQzs7OztBQUcxRixhQUFLLENBQUMsSUFBSSxDQUFDLGtCQUFLLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsYUFBYSxDQUFDLENBQUMsQ0FBQztBQUN4RixhQUFLLENBQUMsSUFBSSxDQUFDLGtCQUFLLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSwyQkFBMkIsQ0FBQyxDQUFDLENBQUM7Ozs7QUFHOUYsYUFBSyxDQUFDLElBQUksQ0FBQyxrQkFBSyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxFQUFFLFNBQVMsRUFBRSx1QkFBdUIsRUFBRSxvQkFBb0IsQ0FBQyxDQUFDLENBQUM7QUFDakcsYUFBSyxDQUFDLElBQUksQ0FBQyxrQkFBSyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxFQUFFLFNBQVMsRUFBRSx1QkFBdUIsRUFBRSw2QkFBNkIsQ0FBQyxDQUFDLENBQUM7QUFDMUcsYUFBSyxDQUFDLElBQUksQ0FBQyxrQkFBSyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxFQUFFLFNBQVMsRUFBRSx1QkFBdUIsRUFBRSxZQUFZLEVBQUUsbUNBQW1DLENBQUMsQ0FBQyxDQUFDOzs7O0FBRzlILGFBQUssQ0FBQyxJQUFJLENBQUMsa0JBQUssT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxRQUFRLEVBQUUsdUJBQXVCLEVBQUUsNkJBQTZCLENBQUMsQ0FBQyxDQUFDO0FBQ3pHLGFBQUssQ0FBQyxJQUFJLENBQUMsa0JBQUssT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxTQUFTLEVBQUUsdUJBQXVCLEVBQUUsWUFBWSxFQUFFLG1DQUFtQyxDQUFDLENBQUMsQ0FBQzs7Ozs0Q0FJM0gsS0FBSzs7Ozs7OztDQUNiOztBQUVELFNBQWUsY0FBYyxDQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsT0FBTztNQUU1QyxLQUFLLGtGQUNBLEtBQUk7Ozs7O0FBRmIsNEJBQUksS0FBSyw4QkFBMkIsS0FBSyxRQUFJLENBQUM7O3lDQUM1QixVQUFVLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQzs7O0FBQXBDLGFBQUs7Ozs7O2lDQUNRLEtBQUs7Ozs7Ozs7O0FBQWIsYUFBSTs7eUNBQ0wsTUFBTSxDQUFDLEtBQUksRUFBRSxPQUFPLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0FFOUI7Ozs7O0FBS0QsU0FBZSxNQUFNLENBQUUsV0FBVyxFQUFFLE9BQU87TUFJckMsZUFBZSxFQUNmLFdBQVc7Ozs7QUFKZiw0QkFBSSxLQUFLLDhCQUEyQixXQUFXLFFBQUksQ0FBQztBQUNwRCw0QkFBSSxLQUFLLFVBQVEsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBRyxDQUFDOzs7eUNBRWhCLElBQUksQ0FBQyxXQUFXLENBQUM7OztBQUF6Qyx1QkFBZTtBQUNmLG1CQUFXLEdBQUcsb0JBQUUsS0FBSyxDQUFDLGVBQWUsRUFBRSxPQUFPLENBQUM7O3lDQUM3QyxxQkFBTSxlQUFlLENBQUMsV0FBVyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDOzs7NENBRTNELFdBQVc7Ozs7Ozs7Q0FDbkI7O0FBRUQsU0FBZSxZQUFZLENBQUUsR0FBRyxFQUFFLEtBQUs7TUFFakMsUUFBUSxFQUNSLEtBQUssdUZBQ0EsTUFBSTs7Ozs7QUFIYiw0QkFBSSxLQUFLLGdDQUE2QixLQUFLLFFBQUksQ0FBQztBQUM1QyxnQkFBUSxHQUFHLEVBQUU7O3lDQUNDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDOzs7QUFBcEMsYUFBSzs7Ozs7a0NBQ1EsS0FBSzs7Ozs7Ozs7QUFBYixjQUFJOzt5Q0FDWSxJQUFJLENBQUMsTUFBSSxDQUFDOzs7QUFBakMsZ0JBQVEsQ0FBQyxNQUFJLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs0Q0FFVCxRQUFROzs7Ozs7O0NBQ2hCOztBQUVELFNBQWUsSUFBSSxDQUFFLFdBQVc7Ozs7QUFDOUIsNEJBQUksS0FBSyw4QkFBNEIsV0FBVyxDQUFHLENBQUM7O3lDQUN2QyxxQkFBTSxjQUFjLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQzs7Ozs7Ozs7OztDQUN0RDs7QUFFRCxTQUFlLHNCQUFzQixDQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsVUFBVTtNQUUxRCxhQUFhLEVBT2IsY0FBYyx1RkFLVCxJQUFJLEVBR1AsT0FBTyxFQUdQLE1BQUssRUFHTCxXQUFXLEVBWVgsV0FBVzs7Ozs7QUFqQ2IscUJBQWEsR0FBRztBQUNsQixvQ0FBMEIsRUFBRSxnQkFBZ0I7QUFDNUMsdUJBQWEsRUFBRSxJQUFJO1NBQ3BCOzt5Q0FDSyxjQUFjLENBQUMsR0FBRyxFQUFFLGVBQWUsc0JBQUksUUFBUSxFQUFHLGFBQWEsRUFBRTs7O0FBR25FLHNCQUFjLEdBQUc7QUFDbkIsa0JBQVEsRUFBRSxRQUFRO0FBQ2xCLG9CQUFVLEVBQUUsQ0FBQyxDQUFDLFVBQVU7QUFDeEIscUJBQVcsRUFBRSxLQUFLO1NBQ25COzs7Ozs7eUNBQ3NCLFVBQVUsQ0FBQyxHQUFHLEVBQUUsaUJBQWlCLENBQUM7Ozs7Ozs7Ozs7OztBQUFoRCxZQUFJOztBQUNYLDRCQUFJLEtBQUsscUNBQW1DLElBQUksQ0FBRyxDQUFDOztBQUVoRCxlQUFPLEdBQUcsRUFBRTs7eUNBR0UsSUFBSSxDQUFDLElBQUksQ0FBQzs7O0FBQXhCLGNBQUs7QUFHTCxtQkFBVyxHQUFHLDZDQUE2QyxHQUM3Qyw2Q0FBNkM7O0FBQy9ELFlBQUksQ0FBQyxvQkFBRSxHQUFHLENBQUMsTUFBSyxFQUFFLFdBQVcsQ0FBQyxFQUFFO0FBQzlCLGlCQUFPLENBQUMsV0FBVyxDQUFDLEdBQUc7QUFDckIsc0JBQVUsRUFBRSw2REFBNkQ7QUFDekUsdUJBQVcsRUFBRSxLQUFLO0FBQ2xCLHNCQUFVLEVBQUUsRUFBRTtBQUNkLHNCQUFVLEVBQUUsRUFBRTtXQUNmLENBQUM7U0FDSDs7O0FBR0csbUJBQVcsR0FBRyxvQkFBRSxHQUFHLENBQUMsTUFBSyxFQUFFLFFBQVEsQ0FBQyxHQUFHLE1BQUssQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFOztBQUMvRCxlQUFPLENBQUMsUUFBUSxDQUFDLEdBQUcsb0JBQUUsUUFBUSxDQUFDLGNBQWMsRUFBRSxXQUFXLENBQUMsQ0FBQztBQUM1RCxlQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDO0FBQ2xFLGVBQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLFVBQVUsSUFBSSxFQUFFLENBQUM7Ozt5Q0FFNUQsTUFBTSxDQUFDLElBQUksRUFBRSxPQUFPLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0FFOUI7O0FBRUQsU0FBZSx3QkFBd0IsQ0FBRSxHQUFHLEVBQUUsVUFBVTtNQUVsRCxlQUFlLEVBWWIsZUFBZSxxR0FDVCxJQUFJLEVBQUUsY0FBYyxxR0FRbEIsR0FBRyxFQUFFLEtBQUs7Ozs7O0FBckJwQix1QkFBZSxHQUFHLEVBQUU7O0FBQ3hCLFlBQUksb0JBQUUsR0FBRyxDQUFDLFVBQVUsRUFBRSx5QkFBeUIsQ0FBQyxFQUFFO0FBQ2hELHlCQUFlLENBQUMscUJBQXFCLEdBQUcsVUFBVSxDQUFDLHVCQUF1QixDQUFDO1NBQzVFO0FBQ0QsWUFBSSxvQkFBRSxHQUFHLENBQUMsVUFBVSxFQUFFLDZDQUE2QyxDQUFDLEVBQUU7QUFDcEUseUJBQWUsQ0FBQyxpQkFBaUIsR0FBRyxVQUFVLENBQUMsMkNBQTJDLENBQUM7U0FDNUY7QUFDRCxZQUFJLG9CQUFFLEdBQUcsQ0FBQyxVQUFVLEVBQUUsNkJBQTZCLENBQUMsRUFBRTtBQUNwRCx5QkFBZSxDQUFDLHVCQUF1QixHQUFHLENBQUMsVUFBVSxDQUFDLDJCQUEyQixDQUFDO1NBQ25GOztjQUNHLG9CQUFFLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUE7Ozs7O0FBQzdCLDRCQUFJLEtBQUssQ0FBQywrQkFBK0IsQ0FBQyxDQUFDOzt5Q0FDZixZQUFZLENBQUMsR0FBRyxFQUFFLGNBQWMsQ0FBQzs7O0FBQXpELHVCQUFlOzs7OztrQ0FDZ0Isb0JBQUUsS0FBSyxDQUFDLGVBQWUsQ0FBQzs7Ozs7Ozs7O0FBQWpELFlBQUk7QUFBRSxzQkFBYzs7Ozs7O0FBSzVCLFlBQUksQ0FBQyxvQkFBRSxHQUFHLENBQUMsY0FBYyxFQUFFLGdCQUFnQixDQUFDLEVBQUU7QUFDNUMsd0JBQWMsQ0FBQyxjQUFjLEdBQUcsRUFBRSxDQUFDO1NBQ3BDOzs7OztBQUNELHVDQUF5QixvQkFBRSxLQUFLLENBQUMsZUFBZSxDQUFDLHlHQUFFOztBQUF6QyxhQUFHO0FBQUUsZUFBSzs7QUFDbEIsd0JBQWMsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBQyxLQUFLLEVBQUwsS0FBSyxFQUFDLENBQUM7U0FDOUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O3lDQUdLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsY0FBYyxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBR3ZDOztBQUVELFNBQWUsWUFBWSxDQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLGNBQWM7TUFDNUQsV0FBVyxFQUlYLElBQUksRUFDSixPQUFPLEVBS0wsY0FBYyxFQUtkLFFBQVEsRUFDUixlQUFlLEVBRWYsS0FBSyxFQUNMLE1BQU0sRUFLTixlQUFlOzs7O0FBeEJqQixtQkFBVyxHQUFHLGtCQUFLLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFDdEMsMEJBQTBCLENBQUM7O3lDQUd6QyxJQUFJLENBQUMsV0FBVyxDQUFDOzs7QUFBOUIsWUFBSTtBQUNKLGVBQU8sR0FBRyxFQUFFOzs7QUFHaEIsWUFBSSxRQUFRLEVBQUU7QUFDWiw4QkFBSSxLQUFLLG9CQUFrQixRQUFRLENBQUcsQ0FBQztBQUNuQyx3QkFBYyxHQUFHLElBQUksQ0FBQyxjQUFjLElBQUksRUFBRTs7QUFDOUMsaUJBQU8sQ0FBQyxjQUFjLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsb0JBQUUsT0FBTyxDQUFDLGNBQWMsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDO1NBQ2pGOztBQUVELFlBQUksTUFBTSxJQUFJLGNBQWMsRUFBRTtBQUN4QixrQkFBUSxHQUFHLFlBQVk7QUFDdkIseUJBQWUsR0FBRyxJQUFJLENBQUMsV0FBVyxJQUFJLFFBQVEsSUFBSSxJQUFJO0FBRXRELGVBQUssR0FBRyxlQUFlLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQztBQUN2QyxnQkFBTSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7O0FBQ3JCLGNBQUksY0FBYyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtBQUM5QiwwQkFBYyxRQUFNLFFBQVEsSUFBRyxjQUFjLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQSxBQUFFLENBQUM7V0FDbkU7QUFDRCx3QkFBYyxHQUFHLGNBQWMsSUFBSSxFQUFFLENBQUM7QUFDbEMseUJBQWUsR0FBRyxNQUFNLEdBQUcsTUFBTSxHQUFHLE1BQU07O0FBQzlDLGNBQUksY0FBYyxFQUFFO0FBQ2xCLDJCQUFlLFFBQU0sZUFBZSxHQUFHLGNBQWMsQUFBRSxDQUFDO1dBQ3pEO0FBQ0QsOEJBQUksS0FBSyxrQkFBZ0IsZUFBZSxDQUFHLENBQUM7QUFDNUMsaUJBQU8sQ0FBQyxXQUFXLEdBQUcsZUFBZSxDQUFDO1NBQ3ZDOztBQUVELDRCQUFJLEtBQUssQ0FBQywrQkFBK0IsQ0FBQyxDQUFDOzt5Q0FDckMsTUFBTSxDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUM7Ozs7Ozs7Q0FDbkM7O0FBRUQsU0FBZSxJQUFJOzs7Ozt5Q0FDSixVQUFVOzs7Ozs7Ozs7O0NBQ3hCOztRQUVRLE1BQU0sR0FBTixNQUFNO1FBQUUsY0FBYyxHQUFkLGNBQWM7UUFBRSxzQkFBc0IsR0FBdEIsc0JBQXNCO1FBQzlDLHdCQUF3QixHQUF4Qix3QkFBd0I7UUFBRSxZQUFZLEdBQVosWUFBWTtRQUFFLElBQUksR0FBSixJQUFJO1FBQUUsWUFBWSxHQUFaLFlBQVk7UUFBRSxJQUFJLEdBQUosSUFBSSIsImZpbGUiOiJsaWIvc2V0dGluZ3MuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHsgcGxpc3QgfSBmcm9tICdhcHBpdW0tc3VwcG9ydCc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCBsb2cgZnJvbSAnLi9sb2dnZXInO1xuXG5cbi8vIHJldHVybnMgcGF0aCB0byBwbGlzdCBiYXNlZCBvbiBpZCBmb3IgcGxpc3QuXG4vLyB0aGVzZSBpZHMgYXJlIGFwcGl1bSB0ZXJtc1xuYXN5bmMgZnVuY3Rpb24gcGxpc3RQYXRocyAoc2ltLCBpZGVudGlmaWVyKSB7XG4gIGxldCBwYXRocyA9IFtdO1xuICBzd2l0Y2ggKGlkZW50aWZpZXIpIHtcbiAgICBjYXNlICd3ZWJJbnNwZWN0b3InOlxuICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltLmdldERpcigpLCAnTGlicmFyeScsICdQcmVmZXJlbmNlcycsICdjb20uYXBwbGUud2ViSW5zcGVjdG9yLnBsaXN0JykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnbW9iaWxlU2FmYXJpJzpcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKGF3YWl0IHNpbS5nZXRBcHBEaXIoJ2NvbS5hcHBsZS5tb2JpbGVzYWZhcmknKSwgJ0xpYnJhcnknLCAnUHJlZmVyZW5jZXMnLCAnY29tLmFwcGxlLm1vYmlsZXNhZmFyaS5wbGlzdCcpKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3dlYlVJJzpcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKHNpbS5nZXREaXIoKSwgJ0xpYnJhcnknLCAnUHJlZmVyZW5jZXMnLCAnY29tLmFwcGxlLldlYlVJLnBsaXN0JykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnd2ViRm91bmRhdGlvbic6XG4gICAgICBwYXRocy5wdXNoKHBhdGgucmVzb2x2ZShzaW0uZ2V0RGlyKCksICdMaWJyYXJ5JywgJ1ByZWZlcmVuY2VzJywgJ2NvbS5hcHBsZS5XZWJGb3VuZGF0aW9uLnBsaXN0JykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAncHJlZmVyZW5jZXMnOlxuICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltLmdldERpcigpLCAnTGlicmFyeScsICdQcmVmZXJlbmNlcycsICdjb20uYXBwbGUuUHJlZmVyZW5jZXMucGxpc3QnKSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdsb2NhdGlvblNlcnZpY2VzJzpcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKHNpbS5nZXREaXIoKSwgJ0xpYnJhcnknLCAnUHJlZmVyZW5jZXMnLCAnY29tLmFwcGxlLmxvY2F0aW9uZC5wbGlzdCcpKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2xvY2F0aW9uQ2xpZW50cyc6XG4gICAgICBwYXRocy5wdXNoKHBhdGgucmVzb2x2ZShzaW0uZ2V0RGlyKCksICdMaWJyYXJ5JywgJ0NhY2hlcycsICdsb2NhdGlvbmQnLCAnY2xpZW50cy5wbGlzdCcpKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2xvY2F0aW9uQ2FjaGUnOlxuICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltLmdldERpcigpLCAnTGlicmFyeScsICdDYWNoZXMnLCAnbG9jYXRpb25kJywgJ2NhY2hlLnBsaXN0JykpO1xuICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltLmdldERpcigpLCAnTGlicmFyeScsICdQcmVmZXJlbmNlcycsICdjb20uYXBwbGUubG9jYXRpb25kLnBsaXN0JykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAndXNlclNldHRpbmdzJzpcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKHNpbS5nZXREaXIoKSwgJ0xpYnJhcnknLCAnQ29uZmlndXJhdGlvblByb2ZpbGVzJywgJ1VzZXJTZXR0aW5ncy5wbGlzdCcpKTtcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKHNpbS5nZXREaXIoKSwgJ0xpYnJhcnknLCAnQ29uZmlndXJhdGlvblByb2ZpbGVzJywgJ0VmZmVjdGl2ZVVzZXJTZXR0aW5ncy5wbGlzdCcpKTtcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKHNpbS5nZXREaXIoKSwgJ0xpYnJhcnknLCAnQ29uZmlndXJhdGlvblByb2ZpbGVzJywgJ1B1YmxpY0luZm8nLCAnUHVibGljRWZmZWN0aXZlVXNlclNldHRpbmdzLnBsaXN0JykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnZWZmZWN0aXZlVXNlclNldHRpbmdzJzpcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKHNpbS5nZXREaXIoKSwgJ0xpYmFyeScsICdDb25maWd1cmF0aW9uUHJvZmlsZXMnLCAnRWZmZWN0aXZlVXNlclNldHRpbmdzLnBsaXN0JykpO1xuICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltLmdldERpcigpLCAnTGlicmFyeScsICdDb25maWd1cmF0aW9uUHJvZmlsZXMnLCAnUHVibGljSW5mbycsICdQdWJsaWNFZmZlY3RpdmVVc2VyU2V0dGluZ3MucGxpc3QnKSk7XG4gICAgICBicmVhaztcbiAgfVxuXG4gIHJldHVybiBwYXRocztcbn1cblxuYXN5bmMgZnVuY3Rpb24gdXBkYXRlU2V0dGluZ3MgKHNpbSwgcGxpc3QsIHVwZGF0ZXMpIHtcbiAgbG9nLmRlYnVnKGBVcGRhdGluZyBzZXR0aW5ncyBmb3IgJyR7cGxpc3R9J2ApO1xuICBsZXQgcGF0aHMgPSBhd2FpdCBwbGlzdFBhdGhzKHNpbSwgcGxpc3QpO1xuICBmb3IgKGxldCBwYXRoIG9mIHBhdGhzKSB7XG4gICAgYXdhaXQgdXBkYXRlKHBhdGgsIHVwZGF0ZXMpO1xuICB9XG59XG5cbi8vIHVwZGF0ZSBhIHBsaXN0IGZpbGUsIGxvY2F0ZWQgYXQgcGF0aFRvUGxpc3Rcbi8vIHBhc3MgaW4gYW4gb2JqZWN0LCBhbGwgc2V0dGluZ3Mgc3BlY2lmaWVkIGluIHRoZSBvYmplY3Qgd2lsbCBiZVxuLy8gdXBkYXRlZCBvbiB0aGUgcGxpc3QsIGFsbCBvdGhlcnMgbGVmdCBhcy1pc1xuYXN5bmMgZnVuY3Rpb24gdXBkYXRlIChwYXRoVG9QbGlzdCwgdXBkYXRlcykge1xuICBsb2cuZGVidWcoYFVwZGF0aW5nIHNldHRpbmdzIGZvciAnJHtwYXRoVG9QbGlzdH0nYCk7XG4gIGxvZy5kZWJ1ZyhgICAgICR7SlNPTi5zdHJpbmdpZnkodXBkYXRlcyl9YCk7XG5cbiAgbGV0IGN1cnJlbnRTZXR0aW5ncyA9IGF3YWl0IHJlYWQocGF0aFRvUGxpc3QpO1xuICBsZXQgbmV3U2V0dGluZ3MgPSBfLm1lcmdlKGN1cnJlbnRTZXR0aW5ncywgdXBkYXRlcyk7XG4gIGF3YWl0IHBsaXN0LnVwZGF0ZVBsaXN0RmlsZShwYXRoVG9QbGlzdCwgbmV3U2V0dGluZ3MsIHRydWUsIGZhbHNlKTtcblxuICByZXR1cm4gbmV3U2V0dGluZ3M7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlYWRTZXR0aW5ncyAoc2ltLCBwbGlzdCkge1xuICBsb2cuZGVidWcoYFJldHJpZXZpbmcgc2V0dGluZ3MgZm9yICcke3BsaXN0fSdgKTtcbiAgbGV0IHNldHRpbmdzID0ge307XG4gIGxldCBwYXRocyA9IGF3YWl0IHBsaXN0UGF0aHMoc2ltLCBwbGlzdCk7XG4gIGZvciAobGV0IHBhdGggb2YgcGF0aHMpIHtcbiAgICBzZXR0aW5nc1twYXRoXSA9IGF3YWl0IHJlYWQocGF0aCk7XG4gIH1cbiAgcmV0dXJuIHNldHRpbmdzO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZWFkIChwYXRoVG9QbGlzdCkge1xuICBsb2cuZGVidWcoYFJldHJpZXZpbmcgc2V0dGluZ3MgZm9yICR7cGF0aFRvUGxpc3R9YCk7XG4gIHJldHVybiBhd2FpdCBwbGlzdC5wYXJzZVBsaXN0RmlsZShwYXRoVG9QbGlzdCwgZmFsc2UpO1xufVxuXG5hc3luYyBmdW5jdGlvbiB1cGRhdGVMb2NhdGlvblNldHRpbmdzIChzaW0sIGJ1bmRsZUlkLCBhdXRob3JpemVkKSB7XG4gIC8vIHVwZGF0ZSBsb2NhdGlvbiBjYWNoZVxuICBsZXQgbmV3Q2FjaGVQcmVmcyA9IHtcbiAgICBMYXN0RmVuY2VBY3Rpdml0eVRpbWVzdGFtcDogNDEyMTIyMTAzLjIzMjk4MyxcbiAgICBDbGVhblNodXRkb3duOiB0cnVlXG4gIH07XG4gIGF3YWl0IHVwZGF0ZVNldHRpbmdzKHNpbSwgJ2xvY2F0aW9uQ2FjaGUnLCB7W2J1bmRsZUlkXTogbmV3Q2FjaGVQcmVmc30pO1xuXG4gIC8vIHVwZGF0ZSBsb2NhdGlvbiBjbGllbnRzXG4gIGxldCBuZXdDbGllbnRQcmVmcyA9IHtcbiAgICBCdW5kbGVJZDogYnVuZGxlSWQsXG4gICAgQXV0aG9yaXplZDogISFhdXRob3JpemVkLFxuICAgIFdoaXRlbGlzdGVkOiBmYWxzZSxcbiAgfTtcbiAgZm9yIChsZXQgZmlsZSBvZiBhd2FpdCBwbGlzdFBhdGhzKHNpbSwgJ2xvY2F0aW9uQ2xpZW50cycpKSB7XG4gICAgbG9nLmRlYnVnKGBVcGRhdGluZyBsb2NhdGlvbiBjbGllbnQgZmlsZTogJHtmaWxlfWApO1xuXG4gICAgbGV0IHVwZGF0ZXMgPSB7fTtcblxuICAgIC8vIHNlZSBpZiB0aGUgYnVuZGxlIGlzIGFscmVhZHkgdGhlcmVcbiAgICBsZXQgcGxpc3QgPSBhd2FpdCByZWFkKGZpbGUpO1xuXG4gICAgLy8gcmFuZG9tIGRhdGEgdGhhdCBhbHdheXMgc2VlbXMgdG8gYmUgaW4gdGhlIGNsaWVudHMucGxpc3RcbiAgICBsZXQgd2VpcmRMb2NLZXkgPSAnY29tLmFwcGxlLmxvY2F0aW9uZC5idW5kbGUtL1N5c3RlbS9MaWJyYXJ5LycgK1xuICAgICAgICAgICAgICAgICAgICAgICdQcml2YXRlRnJhbWV3b3Jrcy9BT1NOb3RpZmljYXRpb24uZnJhbWV3b3JrJztcbiAgICBpZiAoIV8uaGFzKHBsaXN0LCB3ZWlyZExvY0tleSkpIHtcbiAgICAgIHVwZGF0ZXNbd2VpcmRMb2NLZXldID0ge1xuICAgICAgICBCdW5kbGVQYXRoOiAnL1N5c3RlbS9MaWJyYXJ5L1ByaXZhdGVGcmFtZXdvcmtzL0FPU05vdGlmaWNhdGlvbi5mcmFtZXdvcmsnLFxuICAgICAgICBXaGl0ZWxpc3RlZDogZmFsc2UsXG4gICAgICAgIEV4ZWN1dGFibGU6ICcnLFxuICAgICAgICBSZWdpc3RlcmVkOiAnJ1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBjcmVhdGUgdGhlIHVwZGF0ZSwgYW5kIG1ha2Ugc3VyZSBpdCBoYXMgc2Vuc2libGUgdmFsdWVzXG4gICAgbGV0IGJhc2VTZXR0aW5nID0gXy5oYXMocGxpc3QsIGJ1bmRsZUlkKSA/IHBsaXN0W2J1bmRsZUlkXSA6IHt9O1xuICAgIHVwZGF0ZXNbYnVuZGxlSWRdID0gXy5kZWZhdWx0cyhuZXdDbGllbnRQcmVmcywgYmFzZVNldHRpbmcpO1xuICAgIHVwZGF0ZXNbYnVuZGxlSWRdLkV4ZWN1dGFibGUgPSB1cGRhdGVzW2J1bmRsZUlkXS5FeGVjdXRhYmxlIHx8ICcnO1xuICAgIHVwZGF0ZXNbYnVuZGxlSWRdLlJlZ2lzdGVyZWQgPSB1cGRhdGVzW2J1bmRsZUlkXS5SZWdpc3RlcmVkIHx8ICcnO1xuXG4gICAgYXdhaXQgdXBkYXRlKGZpbGUsIHVwZGF0ZXMpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHVwZGF0ZVNhZmFyaVVzZXJTZXR0aW5ncyAoc2ltLCBzZXR0aW5nU2V0KSB7XG4gIC8vIGFkZCBleHRyYSBzdHVmZiB0byBVc2VyU2V0dGluZ3MucGxpc3QgYW5kIEVmZmVjdGl2ZVVzZXJTZXR0aW5ncy5wbGlzdFxuICBsZXQgbmV3VXNlclNldHRpbmdzID0ge307XG4gIGlmIChfLmhhcyhzZXR0aW5nU2V0LCAnV2ViS2l0SmF2YVNjcmlwdEVuYWJsZWQnKSkge1xuICAgIG5ld1VzZXJTZXR0aW5ncy5zYWZhcmlBbGxvd0phdmFTY3JpcHQgPSBzZXR0aW5nU2V0LldlYktpdEphdmFTY3JpcHRFbmFibGVkO1xuICB9XG4gIGlmIChfLmhhcyhzZXR0aW5nU2V0LCAnV2ViS2l0SmF2YVNjcmlwdENhbk9wZW5XaW5kb3dzQXV0b21hdGljYWxseScpKSB7XG4gICAgbmV3VXNlclNldHRpbmdzLnNhZmFyaUFsbG93UG9wdXBzID0gc2V0dGluZ1NldC5XZWJLaXRKYXZhU2NyaXB0Q2FuT3BlbldpbmRvd3NBdXRvbWF0aWNhbGx5O1xuICB9XG4gIGlmIChfLmhhcyhzZXR0aW5nU2V0LCAnV2FybkFib3V0RnJhdWR1bGVudFdlYnNpdGVzJykpIHtcbiAgICBuZXdVc2VyU2V0dGluZ3Muc2FmYXJpRm9yY2VGcmF1ZFdhcm5pbmcgPSAhc2V0dGluZ1NldC5XYXJuQWJvdXRGcmF1ZHVsZW50V2Vic2l0ZXM7XG4gIH1cbiAgaWYgKF8uc2l6ZShuZXdVc2VyU2V0dGluZ3MpID4gMCkge1xuICAgIGxvZy5kZWJ1ZygnVXBkYXRpbmcgU2FmYXJpIHVzZXIgc2V0dGluZ3MnKTtcbiAgICBsZXQgY3VyVXNlclNldHRpbmdzID0gYXdhaXQgcmVhZFNldHRpbmdzKHNpbSwgJ3VzZXJTZXR0aW5ncycpO1xuICAgIGZvciAobGV0IFtmaWxlLCB1c2VyU2V0dGluZ1NldF0gb2YgXy5wYWlycyhjdXJVc2VyU2V0dGluZ3MpKSB7XG4gICAgICAvLyB0aGUgdXNlciBzZXR0aW5ncyBwbGlzdCBoYXMgdHdvIGJ1Y2tldHMsIG9uZSBmb3JcbiAgICAgIC8vIGJvb2xlYW4gc2V0dGluZ3MgKGByZXN0cmljdGVkQm9vbGApIGFuZCBvbmUgZm9yXG4gICAgICAvLyBvdGhlciB2YWx1ZSBzZXR0aW5ncyAoYHJlc3RyaWN0ZWRWYWx1ZWApLiBJbiBlYWNoLCB0aGUgdmFsdWVcbiAgICAgIC8vIGlzIGluIGEgYHZhbHVlYCBzdWItZmllbGQuXG4gICAgICBpZiAoIV8uaGFzKHVzZXJTZXR0aW5nU2V0LCAncmVzdHJpY3RlZEJvb2wnKSkge1xuICAgICAgICB1c2VyU2V0dGluZ1NldC5yZXN0cmljdGVkQm9vbCA9IHt9O1xuICAgICAgfVxuICAgICAgZm9yIChsZXQgW2tleSwgdmFsdWVdIG9mIF8ucGFpcnMobmV3VXNlclNldHRpbmdzKSkge1xuICAgICAgICB1c2VyU2V0dGluZ1NldC5yZXN0cmljdGVkQm9vbFtrZXldID0ge3ZhbHVlfTtcbiAgICAgIH1cblxuICAgICAgLy8gYWN0dWFsbHkgZG8gdGhlIHVwZGF0ZVxuICAgICAgYXdhaXQgdXBkYXRlKGZpbGUsIHVzZXJTZXR0aW5nU2V0KTtcbiAgICB9XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gdXBkYXRlTG9jYWxlIChzaW0sIGxhbmd1YWdlLCBsb2NhbGUsIGNhbGVuZGFyRm9ybWF0KSB7XG4gIGxldCBnbG9iYWxQcmVmcyA9IHBhdGgucmVzb2x2ZShzaW0uZ2V0RGlyKCksICdMaWJyYXJ5JywgJ1ByZWZlcmVuY2VzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcuR2xvYmFsUHJlZmVyZW5jZXMucGxpc3QnKTtcblxuICAvLyBnZXQgdGhlIGN1cnJlbnQgZGF0YVxuICBsZXQgZGF0YSA9IGF3YWl0IHJlYWQoZ2xvYmFsUHJlZnMpO1xuICBsZXQgdXBkYXRlcyA9IHt9O1xuXG4gIC8vIGlmIHdlIGFyZSBzZXR0aW5nIHRoZSBsYW5ndWFnZSwgYWRkIGl0IHRvIHRoZSBsaXN0IG9mIGxhbmd1YWdlc1xuICBpZiAobGFuZ3VhZ2UpIHtcbiAgICBsb2cuZGVidWcoYE5ldyBsYW5ndWFnZTogJHtsYW5ndWFnZX1gKTtcbiAgICBsZXQgc3VwcG9ydGVkTGFuZ3MgPSBkYXRhLkFwcGxlTGFuZ3VhZ2VzIHx8IFtdO1xuICAgIHVwZGF0ZXMuQXBwbGVMYW5ndWFnZXMgPSBbbGFuZ3VhZ2VdLmNvbmNhdChfLndpdGhvdXQoc3VwcG9ydGVkTGFuZ3MsIGxhbmd1YWdlKSk7XG4gIH1cbiAgLy8gaWYgd2UgYXJlIHNldHRpbmcgdGhlIGxvY2FsZSBvciBjYWxlbmRhciBmb3JtYXQsIHNldCB0aGVtIGFzIGFwcHJvcHJpYXRlXG4gIGlmIChsb2NhbGUgfHwgY2FsZW5kYXJGb3JtYXQpIHtcbiAgICBsZXQgY2FsU3BsaXQgPSAnQGNhbGVuZGFyPSc7XG4gICAgbGV0IGN1ckxvY2FsZUFuZENhbCA9IGRhdGEuQXBwbGVMb2NhbGUgfHwgbGFuZ3VhZ2UgfHwgJ2VuJztcblxuICAgIGxldCBzcGxpdCA9IGN1ckxvY2FsZUFuZENhbC5zcGxpdChjYWxTcGxpdCk7XG4gICAgbGV0IGN1ckxvYyA9IHNwbGl0WzBdO1xuICAgIGlmIChjYWxlbmRhckZvcm1hdCB8fCBzcGxpdFsxXSkge1xuICAgICAgY2FsZW5kYXJGb3JtYXQgPSBgJHtjYWxTcGxpdH0ke2NhbGVuZGFyRm9ybWF0IHx8IHNwbGl0WzFdIHx8ICcnfWA7XG4gICAgfVxuICAgIGNhbGVuZGFyRm9ybWF0ID0gY2FsZW5kYXJGb3JtYXQgfHwgJyc7XG4gICAgbGV0IG5ld0xvY2FsZUFuZENhbCA9IGxvY2FsZSA/IGxvY2FsZSA6IGN1ckxvYztcbiAgICBpZiAoY2FsZW5kYXJGb3JtYXQpIHtcbiAgICAgIG5ld0xvY2FsZUFuZENhbCA9IGAke25ld0xvY2FsZUFuZENhbH0ke2NhbGVuZGFyRm9ybWF0fWA7XG4gICAgfVxuICAgIGxvZy5kZWJ1ZyhgTmV3IGxvY2FsZTogJHtuZXdMb2NhbGVBbmRDYWx9YCk7XG4gICAgdXBkYXRlcy5BcHBsZUxvY2FsZSA9IG5ld0xvY2FsZUFuZENhbDtcbiAgfVxuXG4gIGxvZy5kZWJ1ZygnV3JpdGluZyBuZXcgbG9jYWxlIHBsaXN0IGRhdGEnKTtcbiAgYXdhaXQgdXBkYXRlKGdsb2JhbFByZWZzLCB1cGRhdGVzKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc3R1YiAoKSB7XG4gIHJldHVybiBhd2FpdCBwbGlzdFBhdGhzO1xufVxuXG5leHBvcnQgeyB1cGRhdGUsIHVwZGF0ZVNldHRpbmdzLCB1cGRhdGVMb2NhdGlvblNldHRpbmdzLFxuICAgICAgICAgdXBkYXRlU2FmYXJpVXNlclNldHRpbmdzLCB1cGRhdGVMb2NhbGUsIHJlYWQsIHJlYWRTZXR0aW5ncywgc3R1YiB9O1xuIl19