appium-ios-simulator
Version:
iOS Simulator interface for Appium.
684 lines (535 loc) • 43 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);
var _semverCompare = require('semver-compare');
var _semverCompare2 = _interopRequireDefault(_semverCompare);
// returns path to plist based on id for plist.
// these ids are appium terms
function plistPaths(sim, identifier) {
var paths, simDirectory;
return _regeneratorRuntime.async(function plistPaths$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
paths = [];
simDirectory = sim.getDir();
context$1$0.t0 = identifier;
context$1$0.next = context$1$0.t0 === 'webInspector' ? 5 : context$1$0.t0 === 'mobileSafari' ? 7 : context$1$0.t0 === 'webUI' ? 15 : context$1$0.t0 === 'webFoundation' ? 17 : context$1$0.t0 === 'preferences' ? 19 : context$1$0.t0 === 'locationServices' ? 21 : context$1$0.t0 === 'locationClients' ? 23 : context$1$0.t0 === 'locationCache' ? 25 : context$1$0.t0 === 'userSettings' ? 28 : context$1$0.t0 === 'effectiveUserSettings' ? 30 : 33;
break;
case 5:
paths.push(_path4['default'].resolve(simDirectory, 'Library', 'Preferences', 'com.apple.webInspector.plist'));
return context$1$0.abrupt('break', 33);
case 7:
context$1$0.t1 = paths;
context$1$0.t2 = _path4['default'];
context$1$0.next = 11;
return _regeneratorRuntime.awrap(sim.getAppDir('com.apple.mobilesafari'));
case 11:
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', 33);
case 15:
paths.push(_path4['default'].resolve(simDirectory, 'Library', 'Preferences', 'com.apple.WebUI.plist'));
return context$1$0.abrupt('break', 33);
case 17:
paths.push(_path4['default'].resolve(simDirectory, 'Library', 'Preferences', 'com.apple.WebFoundation.plist'));
return context$1$0.abrupt('break', 33);
case 19:
paths.push(_path4['default'].resolve(simDirectory, 'Library', 'Preferences', 'com.apple.Preferences.plist'));
return context$1$0.abrupt('break', 33);
case 21:
paths.push(_path4['default'].resolve(simDirectory, 'Library', 'Preferences', 'com.apple.locationd.plist'));
return context$1$0.abrupt('break', 33);
case 23:
paths.push(_path4['default'].resolve(simDirectory, 'Library', 'Caches', 'locationd', 'clients.plist'));
return context$1$0.abrupt('break', 33);
case 25:
paths.push(_path4['default'].resolve(simDirectory, 'Library', 'Caches', 'locationd', 'cache.plist'));
paths.push(_path4['default'].resolve(simDirectory, 'Library', 'Preferences', 'com.apple.locationd.plist'));
return context$1$0.abrupt('break', 33);
case 28:
if ((0, _semverCompare2['default'])(sim.xcodeVersion.versionString, '7.3') < 0) {
paths.push(_path4['default'].resolve(simDirectory, 'Library', 'ConfigurationProfiles', 'UserSettings.plist'));
paths.push(_path4['default'].resolve(simDirectory, 'Library', 'ConfigurationProfiles', 'EffectiveUserSettings.plist'));
paths.push(_path4['default'].resolve(simDirectory, 'Library', 'ConfigurationProfiles', 'PublicInfo', 'PublicEffectiveUserSettings.plist'));
} else {
paths.push(_path4['default'].resolve(simDirectory, 'Library', 'UserConfigurationProfiles', 'UserSettings.plist'));
paths.push(_path4['default'].resolve(simDirectory, 'Library', 'UserConfigurationProfiles', 'EffectiveUserSettings.plist'));
paths.push(_path4['default'].resolve(simDirectory, 'Library', 'UserConfigurationProfiles', 'PublicInfo', 'PublicEffectiveUserSettings.plist'));
}
return context$1$0.abrupt('break', 33);
case 30:
paths.push(_path4['default'].resolve(simDirectory, 'Library', 'ConfigurationProfiles', 'EffectiveUserSettings.plist'));
paths.push(_path4['default'].resolve(simDirectory, 'Library', 'ConfigurationProfiles', 'PublicInfo', 'PublicEffectiveUserSettings.plist'));
return context$1$0.abrupt('break', 33);
case 33:
return context$1$0.abrupt('return', paths);
case 34:
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:
context$1$0.next = 2;
return _regeneratorRuntime.awrap(plistPaths(sim, plist));
case 2:
paths = context$1$0.sent;
_iteratorNormalCompletion = true;
_didIteratorError = false;
_iteratorError = undefined;
context$1$0.prev = 6;
_iterator = _getIterator(paths);
case 8:
if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
context$1$0.next = 15;
break;
}
_path = _step.value;
context$1$0.next = 12;
return _regeneratorRuntime.awrap(update(_path, updates));
case 12:
_iteratorNormalCompletion = true;
context$1$0.next = 8;
break;
case 15:
context$1$0.next = 21;
break;
case 17:
context$1$0.prev = 17;
context$1$0.t0 = context$1$0['catch'](6);
_didIteratorError = true;
_iteratorError = context$1$0.t0;
case 21:
context$1$0.prev = 21;
context$1$0.prev = 22;
if (!_iteratorNormalCompletion && _iterator['return']) {
_iterator['return']();
}
case 24:
context$1$0.prev = 24;
if (!_didIteratorError) {
context$1$0.next = 27;
break;
}
throw _iteratorError;
case 27:
return context$1$0.finish(24);
case 28:
return context$1$0.finish(21);
case 29:
case 'end':
return context$1$0.stop();
}
}, null, this, [[6, 17, 21, 29], [22,, 24, 28]]);
}
// 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:
context$1$0.next = 2;
return _regeneratorRuntime.awrap(read(pathToPlist));
case 2:
currentSettings = context$1$0.sent;
newSettings = _lodash2['default'].merge(currentSettings, updates);
context$1$0.next = 6;
return _regeneratorRuntime.awrap(_appiumSupport.plist.updatePlistFile(pathToPlist, newSettings, true, false));
case 6:
return context$1$0.abrupt('return', newSettings);
case 7:
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:
settings = {};
context$1$0.next = 3;
return _regeneratorRuntime.awrap(plistPaths(sim, plist));
case 3:
paths = context$1$0.sent;
_iteratorNormalCompletion2 = true;
_didIteratorError2 = false;
_iteratorError2 = undefined;
context$1$0.prev = 7;
_iterator2 = _getIterator(paths);
case 9:
if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) {
context$1$0.next = 17;
break;
}
_path2 = _step2.value;
context$1$0.next = 13;
return _regeneratorRuntime.awrap(read(_path2));
case 13:
settings[_path2] = context$1$0.sent;
case 14:
_iteratorNormalCompletion2 = true;
context$1$0.next = 9;
break;
case 17:
context$1$0.next = 23;
break;
case 19:
context$1$0.prev = 19;
context$1$0.t0 = context$1$0['catch'](7);
_didIteratorError2 = true;
_iteratorError2 = context$1$0.t0;
case 23:
context$1$0.prev = 23;
context$1$0.prev = 24;
if (!_iteratorNormalCompletion2 && _iterator2['return']) {
_iterator2['return']();
}
case 26:
context$1$0.prev = 26;
if (!_didIteratorError2) {
context$1$0.next = 29;
break;
}
throw _iteratorError2;
case 29:
return context$1$0.finish(26);
case 30:
return context$1$0.finish(23);
case 31:
return context$1$0.abrupt('return', settings);
case 32:
case 'end':
return context$1$0.stop();
}
}, null, this, [[7, 19, 23, 31], [24,, 26, 30]]);
}
function read(pathToPlist) {
return _regeneratorRuntime.async(function read$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
context$1$0.next = 2;
return _regeneratorRuntime.awrap(_appiumSupport.plist.parsePlistFile(pathToPlist, false));
case 2:
return context$1$0.abrupt('return', context$1$0.sent);
case 3:
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'].toPairs(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'].toPairs(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 beginning of the list of languages
if (language) {
_logger2['default'].debug('New language: ' + language);
supportedLangs = data.AppleLanguages || [];
// if the language is first, we don't need to do anything
if (supportedLangs.indexOf(language) !== 0) {
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;
}
// only need to update if it has changed
if (newLocaleAndCal !== curLocaleAndCal) {
_logger2['default'].debug('New locale: ' + newLocaleAndCal);
updates.AppleLocale = newLocaleAndCal;
}
}
if (!(_lodash2['default'].size(updates) === 0)) {
context$1$0.next = 10;
break;
}
_logger2['default'].debug('No locale updates necessary.');
return context$1$0.abrupt('return', false);
case 10:
_logger2['default'].debug('Writing new locale plist data');
context$1$0.next = 13;
return _regeneratorRuntime.awrap(update(globalPrefs, updates));
case 13:
return context$1$0.abrupt('return', true);
case 14:
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;charset=utf8;base64,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LE1BQU07O0FBQzlDLGNBQUksY0FBYyxFQUFFO0FBQ2xCLDJCQUFlLFFBQU0sZUFBZSxHQUFHLGNBQWMsQUFBRSxDQUFDO1dBQ3pEOztBQUVELGNBQUksZUFBZSxLQUFLLGVBQWUsRUFBRTtBQUN2QyxnQ0FBSSxLQUFLLGtCQUFnQixlQUFlLENBQUcsQ0FBQztBQUM1QyxtQkFBTyxDQUFDLFdBQVcsR0FBRyxlQUFlLENBQUM7V0FDdkM7U0FDRjs7Y0FFRyxvQkFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFBOzs7OztBQUN2Qiw0QkFBSSxLQUFLLENBQUMsOEJBQThCLENBQUMsQ0FBQzs0Q0FDbkMsS0FBSzs7OztBQUdkLDRCQUFJLEtBQUssQ0FBQywrQkFBK0IsQ0FBQyxDQUFDOzt5Q0FDckMsTUFBTSxDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUM7Ozs0Q0FDM0IsSUFBSTs7Ozs7OztDQUNaOztBQUVELFNBQWUsSUFBSTs7Ozs7eUNBQ0osVUFBVTs7Ozs7Ozs7OztDQUN4Qjs7UUFFUSxNQUFNLEdBQU4sTUFBTTtRQUFFLGNBQWMsR0FBZCxjQUFjO1FBQUUsc0JBQXNCLEdBQXRCLHNCQUFzQjtRQUM5Qyx3QkFBd0IsR0FBeEIsd0JBQXdCO1FBQUUsWUFBWSxHQUFaLFlBQVk7UUFBRSxJQUFJLEdBQUosSUFBSTtRQUFFLFlBQVksR0FBWixZQUFZO1FBQUUsSUFBSSxHQUFKLElBQUkiLCJmaWxlIjoibGliL3NldHRpbmdzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IHBsaXN0IH0gZnJvbSAnYXBwaXVtLXN1cHBvcnQnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgbG9nIGZyb20gJy4vbG9nZ2VyJztcbmltcG9ydCBjb21wYXJlIGZyb20gJ3NlbXZlci1jb21wYXJlJztcblxuXG4vLyByZXR1cm5zIHBhdGggdG8gcGxpc3QgYmFzZWQgb24gaWQgZm9yIHBsaXN0LlxuLy8gdGhlc2UgaWRzIGFyZSBhcHBpdW0gdGVybXNcbmFzeW5jIGZ1bmN0aW9uIHBsaXN0UGF0aHMgKHNpbSwgaWRlbnRpZmllcikge1xuICBsZXQgcGF0aHMgPSBbXTtcbiAgbGV0IHNpbURpcmVjdG9yeSA9IHNpbS5nZXREaXIoKTtcblxuICBzd2l0Y2ggKGlkZW50aWZpZXIpIHtcbiAgICBjYXNlICd3ZWJJbnNwZWN0b3InOlxuICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltRGlyZWN0b3J5LCAnTGlicmFyeScsICdQcmVmZXJlbmNlcycsICdjb20uYXBwbGUud2ViSW5zcGVjdG9yLnBsaXN0JykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnbW9iaWxlU2FmYXJpJzpcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKGF3YWl0IHNpbS5nZXRBcHBEaXIoJ2NvbS5hcHBsZS5tb2JpbGVzYWZhcmknKSwgJ0xpYnJhcnknLCAnUHJlZmVyZW5jZXMnLCAnY29tLmFwcGxlLm1vYmlsZXNhZmFyaS5wbGlzdCcpKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3dlYlVJJzpcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKHNpbURpcmVjdG9yeSwgJ0xpYnJhcnknLCAnUHJlZmVyZW5jZXMnLCAnY29tLmFwcGxlLldlYlVJLnBsaXN0JykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnd2ViRm91bmRhdGlvbic6XG4gICAgICBwYXRocy5wdXNoKHBhdGgucmVzb2x2ZShzaW1EaXJlY3RvcnksICdMaWJyYXJ5JywgJ1ByZWZlcmVuY2VzJywgJ2NvbS5hcHBsZS5XZWJGb3VuZGF0aW9uLnBsaXN0JykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAncHJlZmVyZW5jZXMnOlxuICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltRGlyZWN0b3J5LCAnTGlicmFyeScsICdQcmVmZXJlbmNlcycsICdjb20uYXBwbGUuUHJlZmVyZW5jZXMucGxpc3QnKSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdsb2NhdGlvblNlcnZpY2VzJzpcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKHNpbURpcmVjdG9yeSwgJ0xpYnJhcnknLCAnUHJlZmVyZW5jZXMnLCAnY29tLmFwcGxlLmxvY2F0aW9uZC5wbGlzdCcpKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2xvY2F0aW9uQ2xpZW50cyc6XG4gICAgICBwYXRocy5wdXNoKHBhdGgucmVzb2x2ZShzaW1EaXJlY3RvcnksICdMaWJyYXJ5JywgJ0NhY2hlcycsICdsb2NhdGlvbmQnLCAnY2xpZW50cy5wbGlzdCcpKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2xvY2F0aW9uQ2FjaGUnOlxuICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltRGlyZWN0b3J5LCAnTGlicmFyeScsICdDYWNoZXMnLCAnbG9jYXRpb25kJywgJ2NhY2hlLnBsaXN0JykpO1xuICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltRGlyZWN0b3J5LCAnTGlicmFyeScsICdQcmVmZXJlbmNlcycsICdjb20uYXBwbGUubG9jYXRpb25kLnBsaXN0JykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAndXNlclNldHRpbmdzJzpcbiAgICAgIGlmIChjb21wYXJlKHNpbS54Y29kZVZlcnNpb24udmVyc2lvblN0cmluZywgJzcuMycpIDwgMCkge1xuICAgICAgICBwYXRocy5wdXNoKHBhdGgucmVzb2x2ZShzaW1EaXJlY3RvcnksICdMaWJyYXJ5JywgJ0NvbmZpZ3VyYXRpb25Qcm9maWxlcycsICdVc2VyU2V0dGluZ3MucGxpc3QnKSk7XG4gICAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKHNpbURpcmVjdG9yeSwgJ0xpYnJhcnknLCAnQ29uZmlndXJhdGlvblByb2ZpbGVzJywgJ0VmZmVjdGl2ZVVzZXJTZXR0aW5ncy5wbGlzdCcpKTtcbiAgICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltRGlyZWN0b3J5LCAnTGlicmFyeScsICdDb25maWd1cmF0aW9uUHJvZmlsZXMnLCAnUHVibGljSW5mbycsICdQdWJsaWNFZmZlY3RpdmVVc2VyU2V0dGluZ3MucGxpc3QnKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwYXRocy5wdXNoKHBhdGgucmVzb2x2ZShzaW1EaXJlY3RvcnksICdMaWJyYXJ5JywgJ1VzZXJDb25maWd1cmF0aW9uUHJvZmlsZXMnLCAnVXNlclNldHRpbmdzLnBsaXN0JykpO1xuICAgICAgICBwYXRocy5wdXNoKHBhdGgucmVzb2x2ZShzaW1EaXJlY3RvcnksICdMaWJyYXJ5JywgJ1VzZXJDb25maWd1cmF0aW9uUHJvZmlsZXMnLCAnRWZmZWN0aXZlVXNlclNldHRpbmdzLnBsaXN0JykpO1xuICAgICAgICBwYXRocy5wdXNoKHBhdGgucmVzb2x2ZShzaW1EaXJlY3RvcnksICdMaWJyYXJ5JywgJ1VzZXJDb25maWd1cmF0aW9uUHJvZmlsZXMnLCAnUHVibGljSW5mbycsICdQdWJsaWNFZmZlY3RpdmVVc2VyU2V0dGluZ3MucGxpc3QnKSk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdlZmZlY3RpdmVVc2VyU2V0dGluZ3MnOlxuICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltRGlyZWN0b3J5LCAnTGlicmFyeScsICdDb25maWd1cmF0aW9uUHJvZmlsZXMnLCAnRWZmZWN0aXZlVXNlclNldHRpbmdzLnBsaXN0JykpO1xuICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltRGlyZWN0b3J5LCAnTGlicmFyeScsICdDb25maWd1cmF0aW9uUHJvZmlsZXMnLCAnUHVibGljSW5mbycsICdQdWJsaWNFZmZlY3RpdmVVc2VyU2V0dGluZ3MucGxpc3QnKSk7XG4gICAgICBicmVhaztcbiAgfVxuXG4gIHJldHVybiBwYXRocztcbn1cblxuYXN5bmMgZnVuY3Rpb24gdXBkYXRlU2V0dGluZ3MgKHNpbSwgcGxpc3QsIHVwZGF0ZXMpIHtcbiAgbGV0IHBhdGhzID0gYXdhaXQgcGxpc3RQYXRocyhzaW0sIHBsaXN0KTtcbiAgZm9yIChsZXQgcGF0aCBvZiBwYXRocykge1xuICAgIGF3YWl0IHVwZGF0ZShwYXRoLCB1cGRhdGVzKTtcbiAgfVxufVxuXG4vLyB1cGRhdGUgYSBwbGlzdCBmaWxlLCBsb2NhdGVkIGF0IHBhdGhUb1BsaXN0XG4vLyBwYXNzIGluIGFuIG9iamVjdCwgYWxsIHNldHRpbmdzIHNwZWNpZmllZCBpbiB0aGUgb2JqZWN0IHdpbGwgYmVcbi8vIHVwZGF0ZWQgb24gdGhlIHBsaXN0LCBhbGwgb3RoZXJzIGxlZnQgYXMtaXNcbmFzeW5jIGZ1bmN0aW9uIHVwZGF0ZSAocGF0aFRvUGxpc3QsIHVwZGF0ZXMpIHtcbiAgbGV0IGN1cnJlbnRTZXR0aW5ncyA9IGF3YWl0IHJlYWQocGF0aFRvUGxpc3QpO1xuICBsZXQgbmV3U2V0dGluZ3MgPSBfLm1lcmdlKGN1cnJlbnRTZXR0aW5ncywgdXBkYXRlcyk7XG4gIGF3YWl0IHBsaXN0LnVwZGF0ZVBsaXN0RmlsZShwYXRoVG9QbGlzdCwgbmV3U2V0dGluZ3MsIHRydWUsIGZhbHNlKTtcblxuICByZXR1cm4gbmV3U2V0dGluZ3M7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlYWRTZXR0aW5ncyAoc2ltLCBwbGlzdCkge1xuICBsZXQgc2V0dGluZ3MgPSB7fTtcbiAgbGV0IHBhdGhzID0gYXdhaXQgcGxpc3RQYXRocyhzaW0sIHBsaXN0KTtcbiAgZm9yIChsZXQgcGF0aCBvZiBwYXRocykge1xuICAgIHNldHRpbmdzW3BhdGhdID0gYXdhaXQgcmVhZChwYXRoKTtcbiAgfVxuICByZXR1cm4gc2V0dGluZ3M7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlYWQgKHBhdGhUb1BsaXN0KSB7XG4gIHJldHVybiBhd2FpdCBwbGlzdC5wYXJzZVBsaXN0RmlsZShwYXRoVG9QbGlzdCwgZmFsc2UpO1xufVxuXG5hc3luYyBmdW5jdGlvbiB1cGRhdGVMb2NhdGlvblNldHRpbmdzIChzaW0sIGJ1bmRsZUlkLCBhdXRob3JpemVkKSB7XG4gIC8vIHVwZGF0ZSBsb2NhdGlvbiBjYWNoZVxuICBsZXQgbmV3Q2FjaGVQcmVmcyA9IHtcbiAgICBMYXN0RmVuY2VBY3Rpdml0eVRpbWVzdGFtcDogNDEyMTIyMTAzLjIzMjk4MyxcbiAgICBDbGVhblNodXRkb3duOiB0cnVlXG4gIH07XG4gIGF3YWl0IHVwZGF0ZVNldHRpbmdzKHNpbSwgJ2xvY2F0aW9uQ2FjaGUnLCB7W2J1bmRsZUlkXTogbmV3Q2FjaGVQcmVmc30pO1xuXG4gIC8vIHVwZGF0ZSBsb2NhdGlvbiBjbGllbnRzXG4gIGxldCBuZXdDbGllbnRQcmVmcyA9IHtcbiAgICBCdW5kbGVJZDogYnVuZGxlSWQsXG4gICAgQXV0aG9yaXplZDogISFhdXRob3JpemVkLFxuICAgIFdoaXRlbGlzdGVkOiBmYWxzZSxcbiAgfTtcbiAgZm9yIChsZXQgZmlsZSBvZiBhd2FpdCBwbGlzdFBhdGhzKHNpbSwgJ2xvY2F0aW9uQ2xpZW50cycpKSB7XG4gICAgbG9nLmRlYnVnKGBVcGRhdGluZyBsb2NhdGlvbiBjbGllbnQgZmlsZTogJHtmaWxlfWApO1xuXG4gICAgbGV0IHVwZGF0ZXMgPSB7fTtcblxuICAgIC8vIHNlZSBpZiB0aGUgYnVuZGxlIGlzIGFscmVhZHkgdGhlcmVcbiAgICBsZXQgcGxpc3QgPSBhd2FpdCByZWFkKGZpbGUpO1xuXG4gICAgLy8gcmFuZG9tIGRhdGEgdGhhdCBhbHdheXMgc2VlbXMgdG8gYmUgaW4gdGhlIGNsaWVudHMucGxpc3RcbiAgICBsZXQgd2VpcmRMb2NLZXkgPSAnY29tLmFwcGxlLmxvY2F0aW9uZC5idW5kbGUtL1N5c3RlbS9MaWJyYXJ5LycgK1xuICAgICAgICAgICAgICAgICAgICAgICdQcml2YXRlRnJhbWV3b3Jrcy9BT1NOb3RpZmljYXRpb24uZnJhbWV3b3JrJztcbiAgICBpZiAoIV8uaGFzKHBsaXN0LCB3ZWlyZExvY0tleSkpIHtcbiAgICAgIHVwZGF0ZXNbd2VpcmRMb2NLZXldID0ge1xuICAgICAgICBCdW5kbGVQYXRoOiAnL1N5c3RlbS9MaWJyYXJ5L1ByaXZhdGVGcmFtZXdvcmtzL0FPU05vdGlmaWNhdGlvbi5mcmFtZXdvcmsnLFxuICAgICAgICBXaGl0ZWxpc3RlZDogZmFsc2UsXG4gICAgICAgIEV4ZWN1dGFibGU6ICcnLFxuICAgICAgICBSZWdpc3RlcmVkOiAnJ1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBjcmVhdGUgdGhlIHVwZGF0ZSwgYW5kIG1ha2Ugc3VyZSBpdCBoYXMgc2Vuc2libGUgdmFsdWVzXG4gICAgbGV0IGJhc2VTZXR0aW5nID0gXy5oYXMocGxpc3QsIGJ1bmRsZUlkKSA/IHBsaXN0W2J1bmRsZUlkXSA6IHt9O1xuICAgIHVwZGF0ZXNbYnVuZGxlSWRdID0gXy5kZWZhdWx0cyhuZXdDbGllbnRQcmVmcywgYmFzZVNldHRpbmcpO1xuICAgIHVwZGF0ZXNbYnVuZGxlSWRdLkV4ZWN1dGFibGUgPSB1cGRhdGVzW2J1bmRsZUlkXS5FeGVjdXRhYmxlIHx8ICcnO1xuICAgIHVwZGF0ZXNbYnVuZGxlSWRdLlJlZ2lzdGVyZWQgPSB1cGRhdGVzW2J1bmRsZUlkXS5SZWdpc3RlcmVkIHx8ICcnO1xuXG4gICAgYXdhaXQgdXBkYXRlKGZpbGUsIHVwZGF0ZXMpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHVwZGF0ZVNhZmFyaVVzZXJTZXR0aW5ncyAoc2ltLCBzZXR0aW5nU2V0KSB7XG4gIC8vIGFkZCBleHRyYSBzdHVmZiB0byBVc2VyU2V0dGluZ3MucGxpc3QgYW5kIEVmZmVjdGl2ZVVzZXJTZXR0aW5ncy5wbGlzdFxuICBsZXQgbmV3VXNlclNldHRpbmdzID0ge307XG4gIGlmIChfLmhhcyhzZXR0aW5nU2V0LCAnV2ViS2l0SmF2YVNjcmlwdEVuYWJsZWQnKSkge1xuICAgIG5ld1VzZXJTZXR0aW5ncy5zYWZhcmlBbGxvd0phdmFTY3JpcHQgPSBzZXR0aW5nU2V0LldlYktpdEphdmFTY3JpcHRFbmFibGVkO1xuICB9XG4gIGlmIChfLmhhcyhzZXR0aW5nU2V0LCAnV2ViS2l0SmF2YVNjcmlwdENhbk9wZW5XaW5kb3dzQXV0b21hdGljYWxseScpKSB7XG4gICAgbmV3VXNlclNldHRpbmdzLnNhZmFyaUFsbG93UG9wdXBzID0gc2V0dGluZ1NldC5XZWJLaXRKYXZhU2NyaXB0Q2FuT3BlbldpbmRvd3NBdXRvbWF0aWNhbGx5O1xuICB9XG4gIGlmIChfLmhhcyhzZXR0aW5nU2V0LCAnV2FybkFib3V0RnJhdWR1bGVudFdlYnNpdGVzJykpIHtcbiAgICBuZXdVc2VyU2V0dGluZ3Muc2FmYXJpRm9yY2VGcmF1ZFdhcm5pbmcgPSAhc2V0dGluZ1NldC5XYXJuQWJvdXRGcmF1ZHVsZW50V2Vic2l0ZXM7XG4gIH1cbiAgaWYgKF8uc2l6ZShuZXdVc2VyU2V0dGluZ3MpID4gMCkge1xuICAgIGxvZy5kZWJ1ZygnVXBkYXRpbmcgU2FmYXJpIHVzZXIgc2V0dGluZ3MnKTtcbiAgICBsZXQgY3VyVXNlclNldHRpbmdzID0gYXdhaXQgcmVhZFNldHRpbmdzKHNpbSwgJ3VzZXJTZXR0aW5ncycpO1xuICAgIGZvciAobGV0IFtmaWxlLCB1c2VyU2V0dGluZ1NldF0gb2YgXy50b1BhaXJzKGN1clVzZXJTZXR0aW5ncykpIHtcbiAgICAgIC8vIHRoZSB1c2VyIHNldHRpbmdzIHBsaXN0IGhhcyB0d28gYnVja2V0cywgb25lIGZvclxuICAgICAgLy8gYm9vbGVhbiBzZXR0aW5ncyAoYHJlc3RyaWN0ZWRCb29sYCkgYW5kIG9uZSBmb3JcbiAgICAgIC8vIG90aGVyIHZhbHVlIHNldHRpbmdzIChgcmVzdHJpY3RlZFZhbHVlYCkuIEluIGVhY2gsIHRoZSB2YWx1ZVxuICAgICAgLy8gaXMgaW4gYSBgdmFsdWVgIHN1Yi1maWVsZC5cbiAgICAgIGlmICghXy5oYXModXNlclNldHRpbmdTZXQsICdyZXN0cmljdGVkQm9vbCcpKSB7XG4gICAgICAgIHVzZXJTZXR0aW5nU2V0LnJlc3RyaWN0ZWRCb29sID0ge307XG4gICAgICB9XG4gICAgICBmb3IgKGxldCBba2V5LCB2YWx1ZV0gb2YgXy50b1BhaXJzKG5ld1VzZXJTZXR0aW5ncykpIHtcbiAgICAgICAgdXNlclNldHRpbmdTZXQucmVzdHJpY3RlZEJvb2xba2V5XSA9IHt2YWx1ZX07XG4gICAgICB9XG5cbiAgICAgIC8vIGFjdHVhbGx5IGRvIHRoZSB1cGRhdGVcbiAgICAgIGF3YWl0IHVwZGF0ZShmaWxlLCB1c2VyU2V0dGluZ1NldCk7XG4gICAgfVxuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHVwZGF0ZUxvY2FsZSAoc2ltLCBsYW5ndWFnZSwgbG9jYWxlLCBjYWxlbmRhckZvcm1hdCkge1xuICBsZXQgZ2xvYmFsUHJlZnMgPSBwYXRoLnJlc29sdmUoc2ltLmdldERpcigpLCAnTGlicmFyeScsICdQcmVmZXJlbmNlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLkdsb2JhbFByZWZlcmVuY2VzLnBsaXN0Jyk7XG5cbiAgLy8gZ2V0IHRoZSBjdXJyZW50IGRhdGFcbiAgbGV0IGRhdGEgPSBhd2FpdCByZWFkKGdsb2JhbFByZWZzKTtcbiAgbGV0IHVwZGF0ZXMgPSB7fTtcblxuICAvLyBpZiB3ZSBhcmUgc2V0dGluZyB0aGUgbGFuZ3VhZ2UsIGFkZCBpdCB0byB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaXN0IG9mIGxhbmd1YWdlc1xuICBpZiAobGFuZ3VhZ2UpIHtcbiAgICBsb2cuZGVidWcoYE5ldyBsYW5ndWFnZTogJHtsYW5ndWFnZX1gKTtcbiAgICBsZXQgc3VwcG9ydGVkTGFuZ3MgPSBkYXRhLkFwcGxlTGFuZ3VhZ2VzIHx8IFtdO1xuICAgIC8vIGlmIHRoZSBsYW5ndWFnZSBpcyBmaXJzdCwgd2UgZG9uJ3QgbmVlZCB0byBkbyBhbnl0aGluZ1xuICAgIGlmIChzdXBwb3J0ZWRMYW5ncy5pbmRleE9mKGxhbmd1YWdlKSAhPT0gMCkge1xuICAgICAgdXBkYXRlcy5BcHBsZUxhbmd1YWdlcyA9IFtsYW5ndWFnZV0uY29uY2F0KF8ud2l0aG91dChzdXBwb3J0ZWRMYW5ncywgbGFuZ3VhZ2UpKTtcbiAgICB9XG4gIH1cbiAgLy8gaWYgd2UgYXJlIHNldHRpbmcgdGhlIGxvY2FsZSBvciBjYWxlbmRhciBmb3JtYXQsIHNldCB0aGVtIGFzIGFwcHJvcHJpYXRlXG4gIGlmIChsb2NhbGUgfHwgY2FsZW5kYXJGb3JtYXQpIHtcbiAgICBsZXQgY2FsU3BsaXQgPSAnQGNhbGVuZGFyPSc7XG4gICAgbGV0IGN1ckxvY2FsZUFuZENhbCA9IGRhdGEuQXBwbGVMb2NhbGUgfHwgbGFuZ3VhZ2UgfHwgJ2VuJztcblxuICAgIGxldCBzcGxpdCA9IGN1ckxvY2FsZUFuZENhbC5zcGxpdChjYWxTcGxpdCk7XG4gICAgbGV0IGN1ckxvYyA9IHNwbGl0WzBdO1xuICAgIGlmIChjYWxlbmRhckZvcm1hdCB8fCBzcGxpdFsxXSkge1xuICAgICAgY2FsZW5kYXJGb3JtYXQgPSBgJHtjYWxTcGxpdH0ke2NhbGVuZGFyRm9ybWF0IHx8IHNwbGl0WzFdIHx8ICcnfWA7XG4gICAgfVxuICAgIGNhbGVuZGFyRm9ybWF0ID0gY2FsZW5kYXJGb3JtYXQgfHwgJyc7XG4gICAgbGV0IG5ld0xvY2FsZUFuZENhbCA9IGxvY2FsZSA/IGxvY2FsZSA6IGN1ckxvYztcbiAgICBpZiAoY2FsZW5kYXJGb3JtYXQpIHtcbiAgICAgIG5ld0xvY2FsZUFuZENhbCA9IGAke25ld0xvY2FsZUFuZENhbH0ke2NhbGVuZGFyRm9ybWF0fWA7XG4gICAgfVxuICAgIC8vIG9ubHkgbmVlZCB0byB1cGRhdGUgaWYgaXQgaGFzIGNoYW5nZWRcbiAgICBpZiAobmV3TG9jYWxlQW5kQ2FsICE9PSBjdXJMb2NhbGVBbmRDYWwpIHtcbiAgICAgIGxvZy5kZWJ1ZyhgTmV3IGxvY2FsZTogJHtuZXdMb2NhbGVBbmRDYWx9YCk7XG4gICAgICB1cGRhdGVzLkFwcGxlTG9jYWxlID0gbmV3TG9jYWxlQW5kQ2FsO1xuICAgIH1cbiAgfVxuXG4gIGlmIChfLnNpemUodXBkYXRlcykgPT09IDApIHtcbiAgICBsb2cuZGVidWcoJ05vIGxvY2FsZSB1cGRhdGVzIG5lY2Vzc2FyeS4nKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBsb2cuZGVidWcoJ1dyaXRpbmcgbmV3IGxvY2FsZSBwbGlzdCBkYXRhJyk7XG4gIGF3YWl0IHVwZGF0ZShnbG9iYWxQcmVmcywgdXBkYXRlcyk7XG4gIHJldHVybiB0cnVlO1xufVxuXG5hc3luYyBmdW5jdGlvbiBzdHViICgpIHtcbiAgcmV0dXJuIGF3YWl0IHBsaXN0UGF0aHM7XG59XG5cbmV4cG9ydCB7IHVwZGF0ZSwgdXBkYXRlU2V0dGluZ3MsIHVwZGF0ZUxvY2F0aW9uU2V0dGluZ3MsXG4gICAgICAgICB1cGRhdGVTYWZhcmlVc2VyU2V0dGluZ3MsIHVwZGF0ZUxvY2FsZSwgcmVhZCwgcmVhZFNldHRpbmdzLCBzdHViIH07XG4iXSwic291cmNlUm9vdCI6Ii4uLy4uIn0=