UNPKG

appium-ios-simulator

Version:
659 lines (516 loc) 40.9 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); // 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,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Z0IsZUFBZSxDQUFHLENBQUM7QUFDNUMsaUJBQU8sQ0FBQyxXQUFXLEdBQUcsZUFBZSxDQUFDO1NBQ3ZDOztBQUVELDRCQUFJLEtBQUssQ0FBQywrQkFBK0IsQ0FBQyxDQUFDOzt5Q0FDckMsTUFBTSxDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUM7Ozs7Ozs7Q0FDbkM7O0FBRUQsU0FBZSxJQUFJOzs7Ozt5Q0FDSixVQUFVOzs7Ozs7Ozs7O0NBQ3hCOztRQUVRLE1BQU0sR0FBTixNQUFNO1FBQUUsY0FBYyxHQUFkLGNBQWM7UUFBRSxzQkFBc0IsR0FBdEIsc0JBQXNCO1FBQzlDLHdCQUF3QixHQUF4Qix3QkFBd0I7UUFBRSxZQUFZLEdBQVosWUFBWTtRQUFFLElBQUksR0FBSixJQUFJO1FBQUUsWUFBWSxHQUFaLFlBQVk7UUFBRSxJQUFJLEdBQUosSUFBSSIsImZpbGUiOiJsaWIvc2V0dGluZ3MuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHsgcGxpc3QgfSBmcm9tICdhcHBpdW0tc3VwcG9ydCc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCBsb2cgZnJvbSAnLi9sb2dnZXInO1xuXG5cbi8vIHJldHVybnMgcGF0aCB0byBwbGlzdCBiYXNlZCBvbiBpZCBmb3IgcGxpc3QuXG4vLyB0aGVzZSBpZHMgYXJlIGFwcGl1bSB0ZXJtc1xuYXN5bmMgZnVuY3Rpb24gcGxpc3RQYXRocyAoc2ltLCBpZGVudGlmaWVyKSB7XG4gIGxldCBwYXRocyA9IFtdO1xuICBzd2l0Y2ggKGlkZW50aWZpZXIpIHtcbiAgICBjYXNlICd3ZWJJbnNwZWN0b3InOlxuICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltLmdldERpcigpLCAnTGlicmFyeScsICdQcmVmZXJlbmNlcycsICdjb20uYXBwbGUud2ViSW5zcGVjdG9yLnBsaXN0JykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnbW9iaWxlU2FmYXJpJzpcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKGF3YWl0IHNpbS5nZXRBcHBEaXIoJ2NvbS5hcHBsZS5tb2JpbGVzYWZhcmknKSwgJ0xpYnJhcnknLCAnUHJlZmVyZW5jZXMnLCAnY29tLmFwcGxlLm1vYmlsZXNhZmFyaS5wbGlzdCcpKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3dlYlVJJzpcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKHNpbS5nZXREaXIoKSwgJ0xpYnJhcnknLCAnUHJlZmVyZW5jZXMnLCAnY29tLmFwcGxlLldlYlVJLnBsaXN0JykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnd2ViRm91bmRhdGlvbic6XG4gICAgICBwYXRocy5wdXNoKHBhdGgucmVzb2x2ZShzaW0uZ2V0RGlyKCksICdMaWJyYXJ5JywgJ1ByZWZlcmVuY2VzJywgJ2NvbS5hcHBsZS5XZWJGb3VuZGF0aW9uLnBsaXN0JykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAncHJlZmVyZW5jZXMnOlxuICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltLmdldERpcigpLCAnTGlicmFyeScsICdQcmVmZXJlbmNlcycsICdjb20uYXBwbGUuUHJlZmVyZW5jZXMucGxpc3QnKSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdsb2NhdGlvblNlcnZpY2VzJzpcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKHNpbS5nZXREaXIoKSwgJ0xpYnJhcnknLCAnUHJlZmVyZW5jZXMnLCAnY29tLmFwcGxlLmxvY2F0aW9uZC5wbGlzdCcpKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2xvY2F0aW9uQ2xpZW50cyc6XG4gICAgICBwYXRocy5wdXNoKHBhdGgucmVzb2x2ZShzaW0uZ2V0RGlyKCksICdMaWJyYXJ5JywgJ0NhY2hlcycsICdsb2NhdGlvbmQnLCAnY2xpZW50cy5wbGlzdCcpKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2xvY2F0aW9uQ2FjaGUnOlxuICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltLmdldERpcigpLCAnTGlicmFyeScsICdDYWNoZXMnLCAnbG9jYXRpb25kJywgJ2NhY2hlLnBsaXN0JykpO1xuICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltLmdldERpcigpLCAnTGlicmFyeScsICdQcmVmZXJlbmNlcycsICdjb20uYXBwbGUubG9jYXRpb25kLnBsaXN0JykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAndXNlclNldHRpbmdzJzpcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKHNpbS5nZXREaXIoKSwgJ0xpYnJhcnknLCAnQ29uZmlndXJhdGlvblByb2ZpbGVzJywgJ1VzZXJTZXR0aW5ncy5wbGlzdCcpKTtcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKHNpbS5nZXREaXIoKSwgJ0xpYnJhcnknLCAnQ29uZmlndXJhdGlvblByb2ZpbGVzJywgJ0VmZmVjdGl2ZVVzZXJTZXR0aW5ncy5wbGlzdCcpKTtcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKHNpbS5nZXREaXIoKSwgJ0xpYnJhcnknLCAnQ29uZmlndXJhdGlvblByb2ZpbGVzJywgJ1B1YmxpY0luZm8nLCAnUHVibGljRWZmZWN0aXZlVXNlclNldHRpbmdzLnBsaXN0JykpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnZWZmZWN0aXZlVXNlclNldHRpbmdzJzpcbiAgICAgIHBhdGhzLnB1c2gocGF0aC5yZXNvbHZlKHNpbS5nZXREaXIoKSwgJ0xpYmFyeScsICdDb25maWd1cmF0aW9uUHJvZmlsZXMnLCAnRWZmZWN0aXZlVXNlclNldHRpbmdzLnBsaXN0JykpO1xuICAgICAgcGF0aHMucHVzaChwYXRoLnJlc29sdmUoc2ltLmdldERpcigpLCAnTGlicmFyeScsICdDb25maWd1cmF0aW9uUHJvZmlsZXMnLCAnUHVibGljSW5mbycsICdQdWJsaWNFZmZlY3RpdmVVc2VyU2V0dGluZ3MucGxpc3QnKSk7XG4gICAgICBicmVhaztcbiAgfVxuXG4gIHJldHVybiBwYXRocztcbn1cblxuYXN5bmMgZnVuY3Rpb24gdXBkYXRlU2V0dGluZ3MgKHNpbSwgcGxpc3QsIHVwZGF0ZXMpIHtcbiAgbG9nLmRlYnVnKGBVcGRhdGluZyBzZXR0aW5ncyBmb3IgJyR7cGxpc3R9J2ApO1xuICBsZXQgcGF0aHMgPSBhd2FpdCBwbGlzdFBhdGhzKHNpbSwgcGxpc3QpO1xuICBmb3IgKGxldCBwYXRoIG9mIHBhdGhzKSB7XG4gICAgYXdhaXQgdXBkYXRlKHBhdGgsIHVwZGF0ZXMpO1xuICB9XG59XG5cbi8vIHVwZGF0ZSBhIHBsaXN0IGZpbGUsIGxvY2F0ZWQgYXQgcGF0aFRvUGxpc3Rcbi8vIHBhc3MgaW4gYW4gb2JqZWN0LCBhbGwgc2V0dGluZ3Mgc3BlY2lmaWVkIGluIHRoZSBvYmplY3Qgd2lsbCBiZVxuLy8gdXBkYXRlZCBvbiB0aGUgcGxpc3QsIGFsbCBvdGhlcnMgbGVmdCBhcy1pc1xuYXN5bmMgZnVuY3Rpb24gdXBkYXRlIChwYXRoVG9QbGlzdCwgdXBkYXRlcykge1xuICBsb2cuZGVidWcoYFVwZGF0aW5nIHNldHRpbmdzIGZvciAnJHtwYXRoVG9QbGlzdH0nYCk7XG4gIGxvZy5kZWJ1ZyhgICAgICR7SlNPTi5zdHJpbmdpZnkodXBkYXRlcyl9YCk7XG5cbiAgbGV0IGN1cnJlbnRTZXR0aW5ncyA9IGF3YWl0IHJlYWQocGF0aFRvUGxpc3QpO1xuICBsZXQgbmV3U2V0dGluZ3MgPSBfLm1lcmdlKGN1cnJlbnRTZXR0aW5ncywgdXBkYXRlcyk7XG4gIGF3YWl0IHBsaXN0LnVwZGF0ZVBsaXN0RmlsZShwYXRoVG9QbGlzdCwgbmV3U2V0dGluZ3MsIHRydWUsIGZhbHNlKTtcblxuICByZXR1cm4gbmV3U2V0dGluZ3M7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlYWRTZXR0aW5ncyAoc2ltLCBwbGlzdCkge1xuICBsb2cuZGVidWcoYFJldHJpZXZpbmcgc2V0dGluZ3MgZm9yICcke3BsaXN0fSdgKTtcbiAgbGV0IHNldHRpbmdzID0ge307XG4gIGxldCBwYXRocyA9IGF3YWl0IHBsaXN0UGF0aHMoc2ltLCBwbGlzdCk7XG4gIGZvciAobGV0IHBhdGggb2YgcGF0aHMpIHtcbiAgICBzZXR0aW5nc1twYXRoXSA9IGF3YWl0IHJlYWQocGF0aCk7XG4gIH1cbiAgcmV0dXJuIHNldHRpbmdzO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZWFkIChwYXRoVG9QbGlzdCkge1xuICBsb2cuZGVidWcoYFJldHJpZXZpbmcgc2V0dGluZ3MgZm9yICR7cGF0aFRvUGxpc3R9YCk7XG4gIHJldHVybiBhd2FpdCBwbGlzdC5wYXJzZVBsaXN0RmlsZShwYXRoVG9QbGlzdCwgZmFsc2UpO1xufVxuXG5hc3luYyBmdW5jdGlvbiB1cGRhdGVMb2NhdGlvblNldHRpbmdzIChzaW0sIGJ1bmRsZUlkLCBhdXRob3JpemVkKSB7XG4gIC8vIHVwZGF0ZSBsb2NhdGlvbiBjYWNoZVxuICBsZXQgbmV3Q2FjaGVQcmVmcyA9IHtcbiAgICBMYXN0RmVuY2VBY3Rpdml0eVRpbWVzdGFtcDogNDEyMTIyMTAzLjIzMjk4MyxcbiAgICBDbGVhblNodXRkb3duOiB0cnVlXG4gIH07XG4gIGF3YWl0IHVwZGF0ZVNldHRpbmdzKHNpbSwgJ2xvY2F0aW9uQ2FjaGUnLCB7W2J1bmRsZUlkXTogbmV3Q2FjaGVQcmVmc30pO1xuXG4gIC8vIHVwZGF0ZSBsb2NhdGlvbiBjbGllbnRzXG4gIGxldCBuZXdDbGllbnRQcmVmcyA9IHtcbiAgICBCdW5kbGVJZDogYnVuZGxlSWQsXG4gICAgQXV0aG9yaXplZDogISFhdXRob3JpemVkLFxuICAgIFdoaXRlbGlzdGVkOiBmYWxzZSxcbiAgfTtcbiAgZm9yIChsZXQgZmlsZSBvZiBhd2FpdCBwbGlzdFBhdGhzKHNpbSwgJ2xvY2F0aW9uQ2xpZW50cycpKSB7XG4gICAgbG9nLmRlYnVnKGBVcGRhdGluZyBsb2NhdGlvbiBjbGllbnQgZmlsZTogJHtmaWxlfWApO1xuXG4gICAgbGV0IHVwZGF0ZXMgPSB7fTtcblxuICAgIC8vIHNlZSBpZiB0aGUgYnVuZGxlIGlzIGFscmVhZHkgdGhlcmVcbiAgICBsZXQgcGxpc3QgPSBhd2FpdCByZWFkKGZpbGUpO1xuXG4gICAgLy8gcmFuZG9tIGRhdGEgdGhhdCBhbHdheXMgc2VlbXMgdG8gYmUgaW4gdGhlIGNsaWVudHMucGxpc3RcbiAgICBsZXQgd2VpcmRMb2NLZXkgPSAnY29tLmFwcGxlLmxvY2F0aW9uZC5idW5kbGUtL1N5c3RlbS9MaWJyYXJ5LycgK1xuICAgICAgICAgICAgICAgICAgICAgICdQcml2YXRlRnJhbWV3b3Jrcy9BT1NOb3RpZmljYXRpb24uZnJhbWV3b3JrJztcbiAgICBpZiAoIV8uaGFzKHBsaXN0LCB3ZWlyZExvY0tleSkpIHtcbiAgICAgIHVwZGF0ZXNbd2VpcmRMb2NLZXldID0ge1xuICAgICAgICBCdW5kbGVQYXRoOiAnL1N5c3RlbS9MaWJyYXJ5L1ByaXZhdGVGcmFtZXdvcmtzL0FPU05vdGlmaWNhdGlvbi5mcmFtZXdvcmsnLFxuICAgICAgICBXaGl0ZWxpc3RlZDogZmFsc2UsXG4gICAgICAgIEV4ZWN1dGFibGU6ICcnLFxuICAgICAgICBSZWdpc3RlcmVkOiAnJ1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBjcmVhdGUgdGhlIHVwZGF0ZSwgYW5kIG1ha2Ugc3VyZSBpdCBoYXMgc2Vuc2libGUgdmFsdWVzXG4gICAgbGV0IGJhc2VTZXR0aW5nID0gXy5oYXMocGxpc3QsIGJ1bmRsZUlkKSA/IHBsaXN0W2J1bmRsZUlkXSA6IHt9O1xuICAgIHVwZGF0ZXNbYnVuZGxlSWRdID0gXy5kZWZhdWx0cyhuZXdDbGllbnRQcmVmcywgYmFzZVNldHRpbmcpO1xuICAgIHVwZGF0ZXNbYnVuZGxlSWRdLkV4ZWN1dGFibGUgPSB1cGRhdGVzW2J1bmRsZUlkXS5FeGVjdXRhYmxlIHx8ICcnO1xuICAgIHVwZGF0ZXNbYnVuZGxlSWRdLlJlZ2lzdGVyZWQgPSB1cGRhdGVzW2J1bmRsZUlkXS5SZWdpc3RlcmVkIHx8ICcnO1xuXG4gICAgYXdhaXQgdXBkYXRlKGZpbGUsIHVwZGF0ZXMpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHVwZGF0ZVNhZmFyaVVzZXJTZXR0aW5ncyAoc2ltLCBzZXR0aW5nU2V0KSB7XG4gIC8vIGFkZCBleHRyYSBzdHVmZiB0byBVc2VyU2V0dGluZ3MucGxpc3QgYW5kIEVmZmVjdGl2ZVVzZXJTZXR0aW5ncy5wbGlzdFxuICBsZXQgbmV3VXNlclNldHRpbmdzID0ge307XG4gIGlmIChfLmhhcyhzZXR0aW5nU2V0LCAnV2ViS2l0SmF2YVNjcmlwdEVuYWJsZWQnKSkge1xuICAgIG5ld1VzZXJTZXR0aW5ncy5zYWZhcmlBbGxvd0phdmFTY3JpcHQgPSBzZXR0aW5nU2V0LldlYktpdEphdmFTY3JpcHRFbmFibGVkO1xuICB9XG4gIGlmIChfLmhhcyhzZXR0aW5nU2V0LCAnV2ViS2l0SmF2YVNjcmlwdENhbk9wZW5XaW5kb3dzQXV0b21hdGljYWxseScpKSB7XG4gICAgbmV3VXNlclNldHRpbmdzLnNhZmFyaUFsbG93UG9wdXBzID0gc2V0dGluZ1NldC5XZWJLaXRKYXZhU2NyaXB0Q2FuT3BlbldpbmRvd3NBdXRvbWF0aWNhbGx5O1xuICB9XG4gIGlmIChfLmhhcyhzZXR0aW5nU2V0LCAnV2FybkFib3V0RnJhdWR1bGVudFdlYnNpdGVzJykpIHtcbiAgICBuZXdVc2VyU2V0dGluZ3Muc2FmYXJpRm9yY2VGcmF1ZFdhcm5pbmcgPSAhc2V0dGluZ1NldC5XYXJuQWJvdXRGcmF1ZHVsZW50V2Vic2l0ZXM7XG4gIH1cbiAgaWYgKF8uc2l6ZShuZXdVc2VyU2V0dGluZ3MpID4gMCkge1xuICAgIGxvZy5kZWJ1ZygnVXBkYXRpbmcgU2FmYXJpIHVzZXIgc2V0dGluZ3MnKTtcbiAgICBsZXQgY3VyVXNlclNldHRpbmdzID0gYXdhaXQgcmVhZFNldHRpbmdzKHNpbSwgJ3VzZXJTZXR0aW5ncycpO1xuICAgIGZvciAobGV0IFtmaWxlLCB1c2VyU2V0dGluZ1NldF0gb2YgXy5wYWlycyhjdXJVc2VyU2V0dGluZ3MpKSB7XG4gICAgICAvLyB0aGUgdXNlciBzZXR0aW5ncyBwbGlzdCBoYXMgdHdvIGJ1Y2tldHMsIG9uZSBmb3JcbiAgICAgIC8vIGJvb2xlYW4gc2V0dGluZ3MgKGByZXN0cmljdGVkQm9vbGApIGFuZCBvbmUgZm9yXG4gICAgICAvLyBvdGhlciB2YWx1ZSBzZXR0aW5ncyAoYHJlc3RyaWN0ZWRWYWx1ZWApLiBJbiBlYWNoLCB0aGUgdmFsdWVcbiAgICAgIC8vIGlzIGluIGEgYHZhbHVlYCBzdWItZmllbGQuXG4gICAgICBpZiAoIV8uaGFzKHVzZXJTZXR0aW5nU2V0LCAncmVzdHJpY3RlZEJvb2wnKSkge1xuICAgICAgICB1c2VyU2V0dGluZ1NldC5yZXN0cmljdGVkQm9vbCA9IHt9O1xuICAgICAgfVxuICAgICAgZm9yIChsZXQgW2tleSwgdmFsdWVdIG9mIF8ucGFpcnMobmV3VXNlclNldHRpbmdzKSkge1xuICAgICAgICB1c2VyU2V0dGluZ1NldC5yZXN0cmljdGVkQm9vbFtrZXldID0ge3ZhbHVlfTtcbiAgICAgIH1cblxuICAgICAgLy8gYWN0dWFsbHkgZG8gdGhlIHVwZGF0ZVxuICAgICAgYXdhaXQgdXBkYXRlKGZpbGUsIHVzZXJTZXR0aW5nU2V0KTtcbiAgICB9XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gdXBkYXRlTG9jYWxlIChzaW0sIGxhbmd1YWdlLCBsb2NhbGUsIGNhbGVuZGFyRm9ybWF0KSB7XG4gIGxldCBnbG9iYWxQcmVmcyA9IHBhdGgucmVzb2x2ZShzaW0uZ2V0RGlyKCksICdMaWJyYXJ5JywgJ1ByZWZlcmVuY2VzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcuR2xvYmFsUHJlZmVyZW5jZXMucGxpc3QnKTtcblxuICAvLyBnZXQgdGhlIGN1cnJlbnQgZGF0YVxuICBsZXQgZGF0YSA9IGF3YWl0IHJlYWQoZ2xvYmFsUHJlZnMpO1xuICBsZXQgdXBkYXRlcyA9IHt9O1xuXG4gIC8vIGlmIHdlIGFyZSBzZXR0aW5nIHRoZSBsYW5ndWFnZSwgYWRkIGl0IHRvIHRoZSBsaXN0IG9mIGxhbmd1YWdlc1xuICBpZiAobGFuZ3VhZ2UpIHtcbiAgICBsb2cuZGVidWcoYE5ldyBsYW5ndWFnZTogJHtsYW5ndWFnZX1gKTtcbiAgICBsZXQgc3VwcG9ydGVkTGFuZ3MgPSBkYXRhLkFwcGxlTGFuZ3VhZ2VzIHx8IFtdO1xuICAgIHVwZGF0ZXMuQXBwbGVMYW5ndWFnZXMgPSBbbGFuZ3VhZ2VdLmNvbmNhdChfLndpdGhvdXQoc3VwcG9ydGVkTGFuZ3MsIGxhbmd1YWdlKSk7XG4gIH1cbiAgLy8gaWYgd2UgYXJlIHNldHRpbmcgdGhlIGxvY2FsZSBvciBjYWxlbmRhciBmb3JtYXQsIHNldCB0aGVtIGFzIGFwcHJvcHJpYXRlXG4gIGlmIChsb2NhbGUgfHwgY2FsZW5kYXJGb3JtYXQpIHtcbiAgICBsZXQgY2FsU3BsaXQgPSAnQGNhbGVuZGFyPSc7XG4gICAgbGV0IGN1ckxvY2FsZUFuZENhbCA9IGRhdGEuQXBwbGVMb2NhbGUgfHwgbGFuZ3VhZ2UgfHwgJ2VuJztcblxuICAgIGxldCBzcGxpdCA9IGN1ckxvY2FsZUFuZENhbC5zcGxpdChjYWxTcGxpdCk7XG4gICAgbGV0IGN1ckxvYyA9IHNwbGl0WzBdO1xuICAgIGlmIChjYWxlbmRhckZvcm1hdCB8fCBzcGxpdFsxXSkge1xuICAgICAgY2FsZW5kYXJGb3JtYXQgPSBgJHtjYWxTcGxpdH0ke2NhbGVuZGFyRm9ybWF0IHx8IHNwbGl0WzFdIHx8ICcnfWA7XG4gICAgfVxuICAgIGNhbGVuZGFyRm9ybWF0ID0gY2FsZW5kYXJGb3JtYXQgfHwgJyc7XG4gICAgbGV0IG5ld0xvY2FsZUFuZENhbCA9IGxvY2FsZSA/IGxvY2FsZSA6IGN1ckxvYztcbiAgICBpZiAoY2FsZW5kYXJGb3JtYXQpIHtcbiAgICAgIG5ld0xvY2FsZUFuZENhbCA9IGAke25ld0xvY2FsZUFuZENhbH0ke2NhbGVuZGFyRm9ybWF0fWA7XG4gICAgfVxuICAgIGxvZy5kZWJ1ZyhgTmV3IGxvY2FsZTogJHtuZXdMb2NhbGVBbmRDYWx9YCk7XG4gICAgdXBkYXRlcy5BcHBsZUxvY2FsZSA9IG5ld0xvY2FsZUFuZENhbDtcbiAgfVxuXG4gIGxvZy5kZWJ1ZygnV3JpdGluZyBuZXcgbG9jYWxlIHBsaXN0IGRhdGEnKTtcbiAgYXdhaXQgdXBkYXRlKGdsb2JhbFByZWZzLCB1cGRhdGVzKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc3R1YiAoKSB7XG4gIHJldHVybiBhd2FpdCBwbGlzdFBhdGhzO1xufVxuXG5leHBvcnQgeyB1cGRhdGUsIHVwZGF0ZVNldHRpbmdzLCB1cGRhdGVMb2NhdGlvblNldHRpbmdzLFxuICAgICAgICAgdXBkYXRlU2FmYXJpVXNlclNldHRpbmdzLCB1cGRhdGVMb2NhbGUsIHJlYWQsIHJlYWRTZXR0aW5ncywgc3R1YiB9O1xuIl19