UNPKG

appium-ios-simulator

Version:
684 lines (535 loc) 43 kB
'use strict'; 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=