ClassesRouter.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = exports.ClassesRouter = void 0;
  6. var _PromiseRouter = _interopRequireDefault(require("../PromiseRouter"));
  7. var _rest = _interopRequireDefault(require("../rest"));
  8. var _lodash = _interopRequireDefault(require("lodash"));
  9. var _node = _interopRequireDefault(require("parse/node"));
  10. var _middlewares = require("../middlewares");
  11. function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
  12. const ALLOWED_GET_QUERY_KEYS = ['keys', 'include', 'excludeKeys', 'readPreference', 'includeReadPreference', 'subqueryReadPreference'];
  13. class ClassesRouter extends _PromiseRouter.default {
  14. className(req) {
  15. return req.params.className;
  16. }
  17. handleFind(req) {
  18. const body = Object.assign(req.body, ClassesRouter.JSONFromQuery(req.query));
  19. const options = ClassesRouter.optionsFromBody(body, req.config.defaultLimit);
  20. if (req.config.maxLimit && body.limit > req.config.maxLimit) {
  21. // Silently replace the limit on the query with the max configured
  22. options.limit = Number(req.config.maxLimit);
  23. }
  24. if (body.redirectClassNameForKey) {
  25. options.redirectClassNameForKey = String(body.redirectClassNameForKey);
  26. }
  27. if (typeof body.where === 'string') {
  28. body.where = JSON.parse(body.where);
  29. }
  30. return _rest.default.find(req.config, req.auth, this.className(req), body.where, options, req.info.clientSDK, req.info.context).then(response => {
  31. return {
  32. response: response
  33. };
  34. });
  35. }
  36. // Returns a promise for a {response} object.
  37. handleGet(req) {
  38. const body = Object.assign(req.body, ClassesRouter.JSONFromQuery(req.query));
  39. const options = {};
  40. for (const key of Object.keys(body)) {
  41. if (ALLOWED_GET_QUERY_KEYS.indexOf(key) === -1) {
  42. throw new _node.default.Error(_node.default.Error.INVALID_QUERY, 'Improper encode of parameter');
  43. }
  44. }
  45. if (body.keys != null) {
  46. options.keys = String(body.keys);
  47. }
  48. if (body.include != null) {
  49. options.include = String(body.include);
  50. }
  51. if (body.excludeKeys != null) {
  52. options.excludeKeys = String(body.excludeKeys);
  53. }
  54. if (typeof body.readPreference === 'string') {
  55. options.readPreference = body.readPreference;
  56. }
  57. if (typeof body.includeReadPreference === 'string') {
  58. options.includeReadPreference = body.includeReadPreference;
  59. }
  60. if (typeof body.subqueryReadPreference === 'string') {
  61. options.subqueryReadPreference = body.subqueryReadPreference;
  62. }
  63. return _rest.default.get(req.config, req.auth, this.className(req), req.params.objectId, options, req.info.clientSDK, req.info.context).then(response => {
  64. if (!response.results || response.results.length == 0) {
  65. throw new _node.default.Error(_node.default.Error.OBJECT_NOT_FOUND, 'Object not found.');
  66. }
  67. if (this.className(req) === '_User') {
  68. delete response.results[0].sessionToken;
  69. const user = response.results[0];
  70. if (req.auth.user && user.objectId == req.auth.user.id) {
  71. // Force the session token
  72. response.results[0].sessionToken = req.info.sessionToken;
  73. }
  74. }
  75. return {
  76. response: response.results[0]
  77. };
  78. });
  79. }
  80. handleCreate(req) {
  81. var _req$body;
  82. if (this.className(req) === '_User' && typeof ((_req$body = req.body) === null || _req$body === void 0 ? void 0 : _req$body.objectId) === 'string' && req.body.objectId.startsWith('role:')) {
  83. throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, 'Invalid object ID.');
  84. }
  85. return _rest.default.create(req.config, req.auth, this.className(req), req.body, req.info.clientSDK, req.info.context);
  86. }
  87. handleUpdate(req) {
  88. const where = {
  89. objectId: req.params.objectId
  90. };
  91. return _rest.default.update(req.config, req.auth, this.className(req), where, req.body, req.info.clientSDK, req.info.context);
  92. }
  93. handleDelete(req) {
  94. return _rest.default.del(req.config, req.auth, this.className(req), req.params.objectId, req.info.context).then(() => {
  95. return {
  96. response: {}
  97. };
  98. });
  99. }
  100. static JSONFromQuery(query) {
  101. const json = {};
  102. for (const [key, value] of _lodash.default.entries(query)) {
  103. try {
  104. json[key] = JSON.parse(value);
  105. } catch (e) {
  106. json[key] = value;
  107. }
  108. }
  109. return json;
  110. }
  111. static optionsFromBody(body, defaultLimit) {
  112. const allowConstraints = ['skip', 'limit', 'order', 'count', 'keys', 'excludeKeys', 'include', 'includeAll', 'redirectClassNameForKey', 'where', 'readPreference', 'includeReadPreference', 'subqueryReadPreference', 'hint', 'explain', 'comment'];
  113. for (const key of Object.keys(body)) {
  114. if (allowConstraints.indexOf(key) === -1) {
  115. throw new _node.default.Error(_node.default.Error.INVALID_QUERY, `Invalid parameter for query: ${key}`);
  116. }
  117. }
  118. const options = {};
  119. if (body.skip) {
  120. options.skip = Number(body.skip);
  121. }
  122. if (body.limit || body.limit === 0) {
  123. options.limit = Number(body.limit);
  124. } else {
  125. options.limit = Number(defaultLimit);
  126. }
  127. if (body.order) {
  128. options.order = String(body.order);
  129. }
  130. if (body.count) {
  131. options.count = true;
  132. }
  133. if (body.keys != null) {
  134. options.keys = String(body.keys);
  135. }
  136. if (body.excludeKeys != null) {
  137. options.excludeKeys = String(body.excludeKeys);
  138. }
  139. if (body.include != null) {
  140. options.include = String(body.include);
  141. }
  142. if (body.includeAll) {
  143. options.includeAll = true;
  144. }
  145. if (typeof body.readPreference === 'string') {
  146. options.readPreference = body.readPreference;
  147. }
  148. if (typeof body.includeReadPreference === 'string') {
  149. options.includeReadPreference = body.includeReadPreference;
  150. }
  151. if (typeof body.subqueryReadPreference === 'string') {
  152. options.subqueryReadPreference = body.subqueryReadPreference;
  153. }
  154. if (body.hint && (typeof body.hint === 'string' || typeof body.hint === 'object')) {
  155. options.hint = body.hint;
  156. }
  157. if (body.explain) {
  158. options.explain = body.explain;
  159. }
  160. if (body.comment && typeof body.comment === 'string') {
  161. options.comment = body.comment;
  162. }
  163. return options;
  164. }
  165. mountRoutes() {
  166. this.route('GET', '/classes/:className', req => {
  167. return this.handleFind(req);
  168. });
  169. this.route('GET', '/classes/:className/:objectId', req => {
  170. return this.handleGet(req);
  171. });
  172. this.route('POST', '/classes/:className', _middlewares.promiseEnsureIdempotency, req => {
  173. return this.handleCreate(req);
  174. });
  175. this.route('PUT', '/classes/:className/:objectId', _middlewares.promiseEnsureIdempotency, req => {
  176. return this.handleUpdate(req);
  177. });
  178. this.route('DELETE', '/classes/:className/:objectId', req => {
  179. return this.handleDelete(req);
  180. });
  181. }
  182. }
  183. exports.ClassesRouter = ClassesRouter;
  184. var _default = exports.default = ClassesRouter;
  185. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfUHJvbWlzZVJvdXRlciIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJyZXF1aXJlIiwiX3Jlc3QiLCJfbG9kYXNoIiwiX25vZGUiLCJfbWlkZGxld2FyZXMiLCJlIiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJBTExPV0VEX0dFVF9RVUVSWV9LRVlTIiwiQ2xhc3Nlc1JvdXRlciIsIlByb21pc2VSb3V0ZXIiLCJjbGFzc05hbWUiLCJyZXEiLCJwYXJhbXMiLCJoYW5kbGVGaW5kIiwiYm9keSIsIk9iamVjdCIsImFzc2lnbiIsIkpTT05Gcm9tUXVlcnkiLCJxdWVyeSIsIm9wdGlvbnMiLCJvcHRpb25zRnJvbUJvZHkiLCJjb25maWciLCJkZWZhdWx0TGltaXQiLCJtYXhMaW1pdCIsImxpbWl0IiwiTnVtYmVyIiwicmVkaXJlY3RDbGFzc05hbWVGb3JLZXkiLCJTdHJpbmciLCJ3aGVyZSIsIkpTT04iLCJwYXJzZSIsInJlc3QiLCJmaW5kIiwiYXV0aCIsImluZm8iLCJjbGllbnRTREsiLCJjb250ZXh0IiwidGhlbiIsInJlc3BvbnNlIiwiaGFuZGxlR2V0Iiwia2V5Iiwia2V5cyIsImluZGV4T2YiLCJQYXJzZSIsIkVycm9yIiwiSU5WQUxJRF9RVUVSWSIsImluY2x1ZGUiLCJleGNsdWRlS2V5cyIsInJlYWRQcmVmZXJlbmNlIiwiaW5jbHVkZVJlYWRQcmVmZXJlbmNlIiwic3VicXVlcnlSZWFkUHJlZmVyZW5jZSIsImdldCIsIm9iamVjdElkIiwicmVzdWx0cyIsImxlbmd0aCIsIk9CSkVDVF9OT1RfRk9VTkQiLCJzZXNzaW9uVG9rZW4iLCJ1c2VyIiwiaWQiLCJoYW5kbGVDcmVhdGUiLCJfcmVxJGJvZHkiLCJzdGFydHNXaXRoIiwiT1BFUkFUSU9OX0ZPUkJJRERFTiIsImNyZWF0ZSIsImhhbmRsZVVwZGF0ZSIsInVwZGF0ZSIsImhhbmRsZURlbGV0ZSIsImRlbCIsImpzb24iLCJ2YWx1ZSIsIl8iLCJlbnRyaWVzIiwiYWxsb3dDb25zdHJhaW50cyIsInNraXAiLCJvcmRlciIsImNvdW50IiwiaW5jbHVkZUFsbCIsImhpbnQiLCJleHBsYWluIiwiY29tbWVudCIsIm1vdW50Um91dGVzIiwicm91dGUiLCJwcm9taXNlRW5zdXJlSWRlbXBvdGVuY3kiLCJleHBvcnRzIiwiX2RlZmF1bHQiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvUm91dGVycy9DbGFzc2VzUm91dGVyLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBQcm9taXNlUm91dGVyIGZyb20gJy4uL1Byb21pc2VSb3V0ZXInO1xuaW1wb3J0IHJlc3QgZnJvbSAnLi4vcmVzdCc7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IHsgcHJvbWlzZUVuc3VyZUlkZW1wb3RlbmN5IH0gZnJvbSAnLi4vbWlkZGxld2FyZXMnO1xuXG5jb25zdCBBTExPV0VEX0dFVF9RVUVSWV9LRVlTID0gW1xuICAna2V5cycsXG4gICdpbmNsdWRlJyxcbiAgJ2V4Y2x1ZGVLZXlzJyxcbiAgJ3JlYWRQcmVmZXJlbmNlJyxcbiAgJ2luY2x1ZGVSZWFkUHJlZmVyZW5jZScsXG4gICdzdWJxdWVyeVJlYWRQcmVmZXJlbmNlJyxcbl07XG5cbmV4cG9ydCBjbGFzcyBDbGFzc2VzUm91dGVyIGV4dGVuZHMgUHJvbWlzZVJvdXRlciB7XG4gIGNsYXNzTmFtZShyZXEpIHtcbiAgICByZXR1cm4gcmVxLnBhcmFtcy5jbGFzc05hbWU7XG4gIH1cblxuICBoYW5kbGVGaW5kKHJlcSkge1xuICAgIGNvbnN0IGJvZHkgPSBPYmplY3QuYXNzaWduKHJlcS5ib2R5LCBDbGFzc2VzUm91dGVyLkpTT05Gcm9tUXVlcnkocmVxLnF1ZXJ5KSk7XG4gICAgY29uc3Qgb3B0aW9ucyA9IENsYXNzZXNSb3V0ZXIub3B0aW9uc0Zyb21Cb2R5KGJvZHksIHJlcS5jb25maWcuZGVmYXVsdExpbWl0KTtcbiAgICBpZiAocmVxLmNvbmZpZy5tYXhMaW1pdCAmJiBib2R5LmxpbWl0ID4gcmVxLmNvbmZpZy5tYXhMaW1pdCkge1xuICAgICAgLy8gU2lsZW50bHkgcmVwbGFjZSB0aGUgbGltaXQgb24gdGhlIHF1ZXJ5IHdpdGggdGhlIG1heCBjb25maWd1cmVkXG4gICAgICBvcHRpb25zLmxpbWl0ID0gTnVtYmVyKHJlcS5jb25maWcubWF4TGltaXQpO1xuICAgIH1cbiAgICBpZiAoYm9keS5yZWRpcmVjdENsYXNzTmFtZUZvcktleSkge1xuICAgICAgb3B0aW9ucy5yZWRpcmVjdENsYXNzTmFtZUZvcktleSA9IFN0cmluZyhib2R5LnJlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5KTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBib2R5LndoZXJlID09PSAnc3RyaW5nJykge1xuICAgICAgYm9keS53aGVyZSA9IEpTT04ucGFyc2UoYm9keS53aGVyZSk7XG4gICAgfVxuICAgIHJldHVybiByZXN0XG4gICAgICAuZmluZChcbiAgICAgICAgcmVxLmNvbmZpZyxcbiAgICAgICAgcmVxLmF1dGgsXG4gICAgICAgIHRoaXMuY2xhc3NOYW1lKHJlcSksXG4gICAgICAgIGJvZHkud2hlcmUsXG4gICAgICAgIG9wdGlvbnMsXG4gICAgICAgIHJlcS5pbmZvLmNsaWVudFNESyxcbiAgICAgICAgcmVxLmluZm8uY29udGV4dFxuICAgICAgKVxuICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICByZXR1cm4geyByZXNwb25zZTogcmVzcG9uc2UgfTtcbiAgICAgIH0pO1xuICB9XG5cbiAgLy8gUmV0dXJucyBhIHByb21pc2UgZm9yIGEge3Jlc3BvbnNlfSBvYmplY3QuXG4gIGhhbmRsZUdldChyZXEpIHtcbiAgICBjb25zdCBib2R5ID0gT2JqZWN0LmFzc2lnbihyZXEuYm9keSwgQ2xhc3Nlc1JvdXRlci5KU09ORnJvbVF1ZXJ5KHJlcS5xdWVyeSkpO1xuICAgIGNvbnN0IG9wdGlvbnMgPSB7fTtcblxuICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGJvZHkpKSB7XG4gICAgICBpZiAoQUxMT1dFRF9HRVRfUVVFUllfS0VZUy5pbmRleE9mKGtleSkgPT09IC0xKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLCAnSW1wcm9wZXIgZW5jb2RlIG9mIHBhcmFtZXRlcicpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChib2R5LmtleXMgIT0gbnVsbCkge1xuICAgICAgb3B0aW9ucy5rZXlzID0gU3RyaW5nKGJvZHkua2V5cyk7XG4gICAgfVxuICAgIGlmIChib2R5LmluY2x1ZGUgIT0gbnVsbCkge1xuICAgICAgb3B0aW9ucy5pbmNsdWRlID0gU3RyaW5nKGJvZHkuaW5jbHVkZSk7XG4gICAgfVxuICAgIGlmIChib2R5LmV4Y2x1ZGVLZXlzICE9IG51bGwpIHtcbiAgICAgIG9wdGlvbnMuZXhjbHVkZUtleXMgPSBTdHJpbmcoYm9keS5leGNsdWRlS2V5cyk7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgYm9keS5yZWFkUHJlZmVyZW5jZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIG9wdGlvbnMucmVhZFByZWZlcmVuY2UgPSBib2R5LnJlYWRQcmVmZXJlbmNlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGJvZHkuaW5jbHVkZVJlYWRQcmVmZXJlbmNlID09PSAnc3RyaW5nJykge1xuICAgICAgb3B0aW9ucy5pbmNsdWRlUmVhZFByZWZlcmVuY2UgPSBib2R5LmluY2x1ZGVSZWFkUHJlZmVyZW5jZTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBib2R5LnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICBvcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UgPSBib2R5LnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3RcbiAgICAgIC5nZXQoXG4gICAgICAgIHJlcS5jb25maWcsXG4gICAgICAgIHJlcS5hdXRoLFxuICAgICAgICB0aGlzLmNsYXNzTmFtZShyZXEpLFxuICAgICAgICByZXEucGFyYW1zLm9iamVjdElkLFxuICAgICAgICBvcHRpb25zLFxuICAgICAgICByZXEuaW5mby5jbGllbnRTREssXG4gICAgICAgIHJlcS5pbmZvLmNvbnRleHRcbiAgICAgIClcbiAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgaWYgKCFyZXNwb25zZS5yZXN1bHRzIHx8IHJlc3BvbnNlLnJlc3VsdHMubGVuZ3RoID09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ09iamVjdCBub3QgZm91bmQuJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5jbGFzc05hbWUocmVxKSA9PT0gJ19Vc2VyJykge1xuICAgICAgICAgIGRlbGV0ZSByZXNwb25zZS5yZXN1bHRzWzBdLnNlc3Npb25Ub2tlbjtcblxuICAgICAgICAgIGNvbnN0IHVzZXIgPSByZXNwb25zZS5yZXN1bHRzWzBdO1xuXG4gICAgICAgICAgaWYgKHJlcS5hdXRoLnVzZXIgJiYgdXNlci5vYmplY3RJZCA9PSByZXEuYXV0aC51c2VyLmlkKSB7XG4gICAgICAgICAgICAvLyBGb3JjZSB0aGUgc2Vzc2lvbiB0b2tlblxuICAgICAgICAgICAgcmVzcG9uc2UucmVzdWx0c1swXS5zZXNzaW9uVG9rZW4gPSByZXEuaW5mby5zZXNzaW9uVG9rZW47XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IHJlc3BvbnNlOiByZXNwb25zZS5yZXN1bHRzWzBdIH07XG4gICAgICB9KTtcbiAgfVxuXG4gIGhhbmRsZUNyZWF0ZShyZXEpIHtcbiAgICBpZiAoXG4gICAgICB0aGlzLmNsYXNzTmFtZShyZXEpID09PSAnX1VzZXInICYmXG4gICAgICB0eXBlb2YgcmVxLmJvZHk/Lm9iamVjdElkID09PSAnc3RyaW5nJyAmJlxuICAgICAgcmVxLmJvZHkub2JqZWN0SWQuc3RhcnRzV2l0aCgncm9sZTonKVxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9QRVJBVElPTl9GT1JCSURERU4sICdJbnZhbGlkIG9iamVjdCBJRC4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3QuY3JlYXRlKFxuICAgICAgcmVxLmNvbmZpZyxcbiAgICAgIHJlcS5hdXRoLFxuICAgICAgdGhpcy5jbGFzc05hbWUocmVxKSxcbiAgICAgIHJlcS5ib2R5LFxuICAgICAgcmVxLmluZm8uY2xpZW50U0RLLFxuICAgICAgcmVxLmluZm8uY29udGV4dFxuICAgICk7XG4gIH1cblxuICBoYW5kbGVVcGRhdGUocmVxKSB7XG4gICAgY29uc3Qgd2hlcmUgPSB7IG9iamVjdElkOiByZXEucGFyYW1zLm9iamVjdElkIH07XG4gICAgcmV0dXJuIHJlc3QudXBkYXRlKFxuICAgICAgcmVxLmNvbmZpZyxcbiAgICAgIHJlcS5hdXRoLFxuICAgICAgdGhpcy5jbGFzc05hbWUocmVxKSxcbiAgICAgIHdoZXJlLFxuICAgICAgcmVxLmJvZHksXG4gICAgICByZXEuaW5mby5jbGllbnRTREssXG4gICAgICByZXEuaW5mby5jb250ZXh0XG4gICAgKTtcbiAgfVxuXG4gIGhhbmRsZURlbGV0ZShyZXEpIHtcbiAgICByZXR1cm4gcmVzdFxuICAgICAgLmRlbChyZXEuY29uZmlnLCByZXEuYXV0aCwgdGhpcy5jbGFzc05hbWUocmVxKSwgcmVxLnBhcmFtcy5vYmplY3RJZCwgcmVxLmluZm8uY29udGV4dClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIHsgcmVzcG9uc2U6IHt9IH07XG4gICAgICB9KTtcbiAgfVxuXG4gIHN0YXRpYyBKU09ORnJvbVF1ZXJ5KHF1ZXJ5KSB7XG4gICAgY29uc3QganNvbiA9IHt9O1xuICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIF8uZW50cmllcyhxdWVyeSkpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGpzb25ba2V5XSA9IEpTT04ucGFyc2UodmFsdWUpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBqc29uW2tleV0gPSB2YWx1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGpzb247XG4gIH1cblxuICBzdGF0aWMgb3B0aW9uc0Zyb21Cb2R5KGJvZHksIGRlZmF1bHRMaW1pdCkge1xuICAgIGNvbnN0IGFsbG93Q29uc3RyYWludHMgPSBbXG4gICAgICAnc2tpcCcsXG4gICAgICAnbGltaXQnLFxuICAgICAgJ29yZGVyJyxcbiAgICAgICdjb3VudCcsXG4gICAgICAna2V5cycsXG4gICAgICAnZXhjbHVkZUtleXMnLFxuICAgICAgJ2luY2x1ZGUnLFxuICAgICAgJ2luY2x1ZGVBbGwnLFxuICAgICAgJ3JlZGlyZWN0Q2xhc3NOYW1lRm9yS2V5JyxcbiAgICAgICd3aGVyZScsXG4gICAgICAncmVhZFByZWZlcmVuY2UnLFxuICAgICAgJ2luY2x1ZGVSZWFkUHJlZmVyZW5jZScsXG4gICAgICAnc3VicXVlcnlSZWFkUHJlZmVyZW5jZScsXG4gICAgICAnaGludCcsXG4gICAgICAnZXhwbGFpbicsXG4gICAgICAnY29tbWVudCcsXG4gICAgXTtcblxuICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGJvZHkpKSB7XG4gICAgICBpZiAoYWxsb3dDb25zdHJhaW50cy5pbmRleE9mKGtleSkgPT09IC0xKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX1FVRVJZLCBgSW52YWxpZCBwYXJhbWV0ZXIgZm9yIHF1ZXJ5OiAke2tleX1gKTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3Qgb3B0aW9ucyA9IHt9O1xuICAgIGlmIChib2R5LnNraXApIHtcbiAgICAgIG9wdGlvbnMuc2tpcCA9IE51bWJlcihib2R5LnNraXApO1xuICAgIH1cbiAgICBpZiAoYm9keS5saW1pdCB8fCBib2R5LmxpbWl0ID09PSAwKSB7XG4gICAgICBvcHRpb25zLmxpbWl0ID0gTnVtYmVyKGJvZHkubGltaXQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBvcHRpb25zLmxpbWl0ID0gTnVtYmVyKGRlZmF1bHRMaW1pdCk7XG4gICAgfVxuICAgIGlmIChib2R5Lm9yZGVyKSB7XG4gICAgICBvcHRpb25zLm9yZGVyID0gU3RyaW5nKGJvZHkub3JkZXIpO1xuICAgIH1cbiAgICBpZiAoYm9keS5jb3VudCkge1xuICAgICAgb3B0aW9ucy5jb3VudCA9IHRydWU7XG4gICAgfVxuICAgIGlmIChib2R5LmtleXMgIT0gbnVsbCkge1xuICAgICAgb3B0aW9ucy5rZXlzID0gU3RyaW5nKGJvZHkua2V5cyk7XG4gICAgfVxuICAgIGlmIChib2R5LmV4Y2x1ZGVLZXlzICE9IG51bGwpIHtcbiAgICAgIG9wdGlvbnMuZXhjbHVkZUtleXMgPSBTdHJpbmcoYm9keS5leGNsdWRlS2V5cyk7XG4gICAgfVxuICAgIGlmIChib2R5LmluY2x1ZGUgIT0gbnVsbCkge1xuICAgICAgb3B0aW9ucy5pbmNsdWRlID0gU3RyaW5nKGJvZHkuaW5jbHVkZSk7XG4gICAgfVxuICAgIGlmIChib2R5LmluY2x1ZGVBbGwpIHtcbiAgICAgIG9wdGlvbnMuaW5jbHVkZUFsbCA9IHRydWU7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgYm9keS5yZWFkUHJlZmVyZW5jZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIG9wdGlvbnMucmVhZFByZWZlcmVuY2UgPSBib2R5LnJlYWRQcmVmZXJlbmNlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGJvZHkuaW5jbHVkZVJlYWRQcmVmZXJlbmNlID09PSAnc3RyaW5nJykge1xuICAgICAgb3B0aW9ucy5pbmNsdWRlUmVhZFByZWZlcmVuY2UgPSBib2R5LmluY2x1ZGVSZWFkUHJlZmVyZW5jZTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBib2R5LnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICBvcHRpb25zLnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2UgPSBib2R5LnN1YnF1ZXJ5UmVhZFByZWZlcmVuY2U7XG4gICAgfVxuICAgIGlmIChib2R5LmhpbnQgJiYgKHR5cGVvZiBib2R5LmhpbnQgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiBib2R5LmhpbnQgPT09ICdvYmplY3QnKSkge1xuICAgICAgb3B0aW9ucy5oaW50ID0gYm9keS5oaW50O1xuICAgIH1cbiAgICBpZiAoYm9keS5leHBsYWluKSB7XG4gICAgICBvcHRpb25zLmV4cGxhaW4gPSBib2R5LmV4cGxhaW47XG4gICAgfVxuICAgIGlmIChib2R5LmNvbW1lbnQgJiYgdHlwZW9mIGJvZHkuY29tbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIG9wdGlvbnMuY29tbWVudCA9IGJvZHkuY29tbWVudDtcbiAgICB9XG4gICAgcmV0dXJuIG9wdGlvbnM7XG4gIH1cblxuICBtb3VudFJvdXRlcygpIHtcbiAgICB0aGlzLnJvdXRlKCdHRVQnLCAnL2NsYXNzZXMvOmNsYXNzTmFtZScsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVGaW5kKHJlcSk7XG4gICAgfSk7XG4gICAgdGhpcy5yb3V0ZSgnR0VUJywgJy9jbGFzc2VzLzpjbGFzc05hbWUvOm9iamVjdElkJywgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZUdldChyZXEpO1xuICAgIH0pO1xuICAgIHRoaXMucm91dGUoJ1BPU1QnLCAnL2NsYXNzZXMvOmNsYXNzTmFtZScsIHByb21pc2VFbnN1cmVJZGVtcG90ZW5jeSwgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZUNyZWF0ZShyZXEpO1xuICAgIH0pO1xuICAgIHRoaXMucm91dGUoJ1BVVCcsICcvY2xhc3Nlcy86Y2xhc3NOYW1lLzpvYmplY3RJZCcsIHByb21pc2VFbnN1cmVJZGVtcG90ZW5jeSwgcmVxID0+IHtcbiAgICAgIHJldHVybiB0aGlzLmhhbmRsZVVwZGF0ZShyZXEpO1xuICAgIH0pO1xuICAgIHRoaXMucm91dGUoJ0RFTEVURScsICcvY2xhc3Nlcy86Y2xhc3NOYW1lLzpvYmplY3RJZCcsIHJlcSA9PiB7XG4gICAgICByZXR1cm4gdGhpcy5oYW5kbGVEZWxldGUocmVxKTtcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBDbGFzc2VzUm91dGVyO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxJQUFBQSxjQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxLQUFBLEdBQUFGLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBRSxPQUFBLEdBQUFILHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBRyxLQUFBLEdBQUFKLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBSSxZQUFBLEdBQUFKLE9BQUE7QUFBMEQsU0FBQUQsdUJBQUFNLENBQUEsV0FBQUEsQ0FBQSxJQUFBQSxDQUFBLENBQUFDLFVBQUEsR0FBQUQsQ0FBQSxLQUFBRSxPQUFBLEVBQUFGLENBQUE7QUFFMUQsTUFBTUcsc0JBQXNCLEdBQUcsQ0FDN0IsTUFBTSxFQUNOLFNBQVMsRUFDVCxhQUFhLEVBQ2IsZ0JBQWdCLEVBQ2hCLHVCQUF1QixFQUN2Qix3QkFBd0IsQ0FDekI7QUFFTSxNQUFNQyxhQUFhLFNBQVNDLHNCQUFhLENBQUM7RUFDL0NDLFNBQVNBLENBQUNDLEdBQUcsRUFBRTtJQUNiLE9BQU9BLEdBQUcsQ0FBQ0MsTUFBTSxDQUFDRixTQUFTO0VBQzdCO0VBRUFHLFVBQVVBLENBQUNGLEdBQUcsRUFBRTtJQUNkLE1BQU1HLElBQUksR0FBR0MsTUFBTSxDQUFDQyxNQUFNLENBQUNMLEdBQUcsQ0FBQ0csSUFBSSxFQUFFTixhQUFhLENBQUNTLGFBQWEsQ0FBQ04sR0FBRyxDQUFDTyxLQUFLLENBQUMsQ0FBQztJQUM1RSxNQUFNQyxPQUFPLEdBQUdYLGFBQWEsQ0FBQ1ksZUFBZSxDQUFDTixJQUFJLEVBQUVILEdBQUcsQ0FBQ1UsTUFBTSxDQUFDQyxZQUFZLENBQUM7SUFDNUUsSUFBSVgsR0FBRyxDQUFDVSxNQUFNLENBQUNFLFFBQVEsSUFBSVQsSUFBSSxDQUFDVSxLQUFLLEdBQUdiLEdBQUcsQ0FBQ1UsTUFBTSxDQUFDRSxRQUFRLEVBQUU7TUFDM0Q7TUFDQUosT0FBTyxDQUFDSyxLQUFLLEdBQUdDLE1BQU0sQ0FBQ2QsR0FBRyxDQUFDVSxNQUFNLENBQUNFLFFBQVEsQ0FBQztJQUM3QztJQUNBLElBQUlULElBQUksQ0FBQ1ksdUJBQXVCLEVBQUU7TUFDaENQLE9BQU8sQ0FBQ08sdUJBQXVCLEdBQUdDLE1BQU0sQ0FBQ2IsSUFBSSxDQUFDWSx1QkFBdUIsQ0FBQztJQUN4RTtJQUNBLElBQUksT0FBT1osSUFBSSxDQUFDYyxLQUFLLEtBQUssUUFBUSxFQUFFO01BQ2xDZCxJQUFJLENBQUNjLEtBQUssR0FBR0MsSUFBSSxDQUFDQyxLQUFLLENBQUNoQixJQUFJLENBQUNjLEtBQUssQ0FBQztJQUNyQztJQUNBLE9BQU9HLGFBQUksQ0FDUkMsSUFBSSxDQUNIckIsR0FBRyxDQUFDVSxNQUFNLEVBQ1ZWLEdBQUcsQ0FBQ3NCLElBQUksRUFDUixJQUFJLENBQUN2QixTQUFTLENBQUNDLEdBQUcsQ0FBQyxFQUNuQkcsSUFBSSxDQUFDYyxLQUFLLEVBQ1ZULE9BQU8sRUFDUFIsR0FBRyxDQUFDdUIsSUFBSSxDQUFDQyxTQUFTLEVBQ2xCeEIsR0FBRyxDQUFDdUIsSUFBSSxDQUFDRSxPQUNYLENBQUMsQ0FDQUMsSUFBSSxDQUFDQyxRQUFRLElBQUk7TUFDaEIsT0FBTztRQUFFQSxRQUFRLEVBQUVBO01BQVMsQ0FBQztJQUMvQixDQUFDLENBQUM7RUFDTjs7RUFFQTtFQUNBQyxTQUFTQSxDQUFDNUIsR0FBRyxFQUFFO0lBQ2IsTUFBTUcsSUFBSSxHQUFHQyxNQUFNLENBQUNDLE1BQU0sQ0FBQ0wsR0FBRyxDQUFDRyxJQUFJLEVBQUVOLGFBQWEsQ0FBQ1MsYUFBYSxDQUFDTixHQUFHLENBQUNPLEtBQUssQ0FBQyxDQUFDO0lBQzVFLE1BQU1DLE9BQU8sR0FBRyxDQUFDLENBQUM7SUFFbEIsS0FBSyxNQUFNcUIsR0FBRyxJQUFJekIsTUFBTSxDQUFDMEIsSUFBSSxDQUFDM0IsSUFBSSxDQUFDLEVBQUU7TUFDbkMsSUFBSVAsc0JBQXNCLENBQUNtQyxPQUFPLENBQUNGLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFO1FBQzlDLE1BQU0sSUFBSUcsYUFBSyxDQUFDQyxLQUFLLENBQUNELGFBQUssQ0FBQ0MsS0FBSyxDQUFDQyxhQUFhLEVBQUUsOEJBQThCLENBQUM7TUFDbEY7SUFDRjtJQUVBLElBQUkvQixJQUFJLENBQUMyQixJQUFJLElBQUksSUFBSSxFQUFFO01BQ3JCdEIsT0FBTyxDQUFDc0IsSUFBSSxHQUFHZCxNQUFNLENBQUNiLElBQUksQ0FBQzJCLElBQUksQ0FBQztJQUNsQztJQUNBLElBQUkzQixJQUFJLENBQUNnQyxPQUFPLElBQUksSUFBSSxFQUFFO01BQ3hCM0IsT0FBTyxDQUFDMkIsT0FBTyxHQUFHbkIsTUFBTSxDQUFDYixJQUFJLENBQUNnQyxPQUFPLENBQUM7SUFDeEM7SUFDQSxJQUFJaEMsSUFBSSxDQUFDaUMsV0FBVyxJQUFJLElBQUksRUFBRTtNQUM1QjVCLE9BQU8sQ0FBQzRCLFdBQVcsR0FBR3BCLE1BQU0sQ0FBQ2IsSUFBSSxDQUFDaUMsV0FBVyxDQUFDO0lBQ2hEO0lBQ0EsSUFBSSxPQUFPakMsSUFBSSxDQUFDa0MsY0FBYyxLQUFLLFFBQVEsRUFBRTtNQUMzQzdCLE9BQU8sQ0FBQzZCLGNBQWMsR0FBR2xDLElBQUksQ0FBQ2tDLGNBQWM7SUFDOUM7SUFDQSxJQUFJLE9BQU9sQyxJQUFJLENBQUNtQyxxQkFBcUIsS0FBSyxRQUFRLEVBQUU7TUFDbEQ5QixPQUFPLENBQUM4QixxQkFBcUIsR0FBR25DLElBQUksQ0FBQ21DLHFCQUFxQjtJQUM1RDtJQUNBLElBQUksT0FBT25DLElBQUksQ0FBQ29DLHNCQUFzQixLQUFLLFFBQVEsRUFBRTtNQUNuRC9CLE9BQU8sQ0FBQytCLHNCQUFzQixHQUFHcEMsSUFBSSxDQUFDb0Msc0JBQXNCO0lBQzlEO0lBRUEsT0FBT25CLGFBQUksQ0FDUm9CLEdBQUcsQ0FDRnhDLEdBQUcsQ0FBQ1UsTUFBTSxFQUNWVixHQUFHLENBQUNzQixJQUFJLEVBQ1IsSUFBSSxDQUFDdkIsU0FBUyxDQUFDQyxHQUFHLENBQUMsRUFDbkJBLEdBQUcsQ0FBQ0MsTUFBTSxDQUFDd0MsUUFBUSxFQUNuQmpDLE9BQU8sRUFDUFIsR0FBRyxDQUFDdUIsSUFBSSxDQUFDQyxTQUFTLEVBQ2xCeEIsR0FBRyxDQUFDdUIsSUFBSSxDQUFDRSxPQUNYLENBQUMsQ0FDQUMsSUFBSSxDQUFDQyxRQUFRLElBQUk7TUFDaEIsSUFBSSxDQUFDQSxRQUFRLENBQUNlLE9BQU8sSUFBSWYsUUFBUSxDQUFDZSxPQUFPLENBQUNDLE1BQU0sSUFBSSxDQUFDLEVBQUU7UUFDckQsTUFBTSxJQUFJWCxhQUFLLENBQUNDLEtBQUssQ0FBQ0QsYUFBSyxDQUFDQyxLQUFLLENBQUNXLGdCQUFnQixFQUFFLG1CQUFtQixDQUFDO01BQzFFO01BRUEsSUFBSSxJQUFJLENBQUM3QyxTQUFTLENBQUNDLEdBQUcsQ0FBQyxLQUFLLE9BQU8sRUFBRTtRQUNuQyxPQUFPMkIsUUFBUSxDQUFDZSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUNHLFlBQVk7UUFFdkMsTUFBTUMsSUFBSSxHQUFHbkIsUUFBUSxDQUFDZSxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBRWhDLElBQUkxQyxHQUFHLENBQUNzQixJQUFJLENBQUN3QixJQUFJLElBQUlBLElBQUksQ0FBQ0wsUUFBUSxJQUFJekMsR0FBRyxDQUFDc0IsSUFBSSxDQUFDd0IsSUFBSSxDQUFDQyxFQUFFLEVBQUU7VUFDdEQ7VUFDQXBCLFFBQVEsQ0FBQ2UsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDRyxZQUFZLEdBQUc3QyxHQUFHLENBQUN1QixJQUFJLENBQUNzQixZQUFZO1FBQzFEO01BQ0Y7TUFDQSxPQUFPO1FBQUVsQixRQUFRLEVBQUVBLFFBQVEsQ0FBQ2UsT0FBTyxDQUFDLENBQUM7TUFBRSxDQUFDO0lBQzFDLENBQUMsQ0FBQztFQUNOO0VBRUFNLFlBQVlBLENBQUNoRCxHQUFHLEVBQUU7SUFBQSxJQUFBaUQsU0FBQTtJQUNoQixJQUNFLElBQUksQ0FBQ2xELFNBQVMsQ0FBQ0MsR0FBRyxDQUFDLEtBQUssT0FBTyxJQUMvQixTQUFBaUQsU0FBQSxHQUFPakQsR0FBRyxDQUFDRyxJQUFJLGNBQUE4QyxTQUFBLHVCQUFSQSxTQUFBLENBQVVSLFFBQVEsTUFBSyxRQUFRLElBQ3RDekMsR0FBRyxDQUFDRyxJQUFJLENBQUNzQyxRQUFRLENBQUNTLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFDckM7TUFDQSxNQUFNLElBQUlsQixhQUFLLENBQUNDLEtBQUssQ0FBQ0QsYUFBSyxDQUFDQyxLQUFLLENBQUNrQixtQkFBbUIsRUFBRSxvQkFBb0IsQ0FBQztJQUM5RTtJQUNBLE9BQU8vQixhQUFJLENBQUNnQyxNQUFNLENBQ2hCcEQsR0FBRyxDQUFDVSxNQUFNLEVBQ1ZWLEdBQUcsQ0FBQ3NCLElBQUksRUFDUixJQUFJLENBQUN2QixTQUFTLENBQUNDLEdBQUcsQ0FBQyxFQUNuQkEsR0FBRyxDQUFDRyxJQUFJLEVBQ1JILEdBQUcsQ0FBQ3VCLElBQUksQ0FBQ0MsU0FBUyxFQUNsQnhCLEdBQUcsQ0FBQ3VCLElBQUksQ0FBQ0UsT0FDWCxDQUFDO0VBQ0g7RUFFQTRCLFlBQVlBLENBQUNyRCxHQUFHLEVBQUU7SUFDaEIsTUFBTWlCLEtBQUssR0FBRztNQUFFd0IsUUFBUSxFQUFFekMsR0FBRyxDQUFDQyxNQUFNLENBQUN3QztJQUFTLENBQUM7SUFDL0MsT0FBT3JCLGFBQUksQ0FBQ2tDLE1BQU0sQ0FDaEJ0RCxHQUFHLENBQUNVLE1BQU0sRUFDVlYsR0FBRyxDQUFDc0IsSUFBSSxFQUNSLElBQUksQ0FBQ3ZCLFNBQVMsQ0FBQ0MsR0FBRyxDQUFDLEVBQ25CaUIsS0FBSyxFQUNMakIsR0FBRyxDQUFDRyxJQUFJLEVBQ1JILEdBQUcsQ0FBQ3VCLElBQUksQ0FBQ0MsU0FBUyxFQUNsQnhCLEdBQUcsQ0FBQ3VCLElBQUksQ0FBQ0UsT0FDWCxDQUFDO0VBQ0g7RUFFQThCLFlBQVlBLENBQUN2RCxHQUFHLEVBQUU7SUFDaEIsT0FBT29CLGFBQUksQ0FDUm9DLEdBQUcsQ0FBQ3hELEdBQUcsQ0FBQ1UsTUFBTSxFQUFFVixHQUFHLENBQUNzQixJQUFJLEVBQUUsSUFBSSxDQUFDdkIsU0FBUyxDQUFDQyxHQUFHLENBQUMsRUFBRUEsR0FBRyxDQUFDQyxNQUFNLENBQUN3QyxRQUFRLEVBQUV6QyxHQUFHLENBQUN1QixJQUFJLENBQUNFLE9BQU8sQ0FBQyxDQUNyRkMsSUFBSSxDQUFDLE1BQU07TUFDVixPQUFPO1FBQUVDLFFBQVEsRUFBRSxDQUFDO01BQUUsQ0FBQztJQUN6QixDQUFDLENBQUM7RUFDTjtFQUVBLE9BQU9yQixhQUFhQSxDQUFDQyxLQUFLLEVBQUU7SUFDMUIsTUFBTWtELElBQUksR0FBRyxDQUFDLENBQUM7SUFDZixLQUFLLE1BQU0sQ0FBQzVCLEdBQUcsRUFBRTZCLEtBQUssQ0FBQyxJQUFJQyxlQUFDLENBQUNDLE9BQU8sQ0FBQ3JELEtBQUssQ0FBQyxFQUFFO01BQzNDLElBQUk7UUFDRmtELElBQUksQ0FBQzVCLEdBQUcsQ0FBQyxHQUFHWCxJQUFJLENBQUNDLEtBQUssQ0FBQ3VDLEtBQUssQ0FBQztNQUMvQixDQUFDLENBQUMsT0FBT2pFLENBQUMsRUFBRTtRQUNWZ0UsSUFBSSxDQUFDNUIsR0FBRyxDQUFDLEdBQUc2QixLQUFLO01BQ25CO0lBQ0Y7SUFDQSxPQUFPRCxJQUFJO0VBQ2I7RUFFQSxPQUFPaEQsZUFBZUEsQ0FBQ04sSUFBSSxFQUFFUSxZQUFZLEVBQUU7SUFDekMsTUFBTWtELGdCQUFnQixHQUFHLENBQ3ZCLE1BQU0sRUFDTixPQUFPLEVBQ1AsT0FBTyxFQUNQLE9BQU8sRUFDUCxNQUFNLEVBQ04sYUFBYSxFQUNiLFNBQVMsRUFDVCxZQUFZLEVBQ1oseUJBQXlCLEVBQ3pCLE9BQU8sRUFDUCxnQkFBZ0IsRUFDaEIsdUJBQXVCLEVBQ3ZCLHdCQUF3QixFQUN4QixNQUFNLEVBQ04sU0FBUyxFQUNULFNBQVMsQ0FDVjtJQUVELEtBQUssTUFBTWhDLEdBQUcsSUFBSXpCLE1BQU0sQ0FBQzBCLElBQUksQ0FBQzNCLElBQUksQ0FBQyxFQUFFO01BQ25DLElBQUkwRCxnQkFBZ0IsQ0FBQzlCLE9BQU8sQ0FBQ0YsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUU7UUFDeEMsTUFBTSxJQUFJRyxhQUFLLENBQUNDLEtBQUssQ0FBQ0QsYUFBSyxDQUFDQyxLQUFLLENBQUNDLGFBQWEsRUFBRSxnQ0FBZ0NMLEdBQUcsRUFBRSxDQUFDO01BQ3pGO0lBQ0Y7SUFDQSxNQUFNckIsT0FBTyxHQUFHLENBQUMsQ0FBQztJQUNsQixJQUFJTCxJQUFJLENBQUMyRCxJQUFJLEVBQUU7TUFDYnRELE9BQU8sQ0FBQ3NELElBQUksR0FBR2hELE1BQU0sQ0FBQ1gsSUFBSSxDQUFDMkQsSUFBSSxDQUFDO0lBQ2xDO0lBQ0EsSUFBSTNELElBQUksQ0FBQ1UsS0FBSyxJQUFJVixJQUFJLENBQUNVLEtBQUssS0FBSyxDQUFDLEVBQUU7TUFDbENMLE9BQU8sQ0FBQ0ssS0FBSyxHQUFHQyxNQUFNLENBQUNYLElBQUksQ0FBQ1UsS0FBSyxDQUFDO0lBQ3BDLENBQUMsTUFBTTtNQUNMTCxPQUFPLENBQUNLLEtBQUssR0FBR0MsTUFBTSxDQUFDSCxZQUFZLENBQUM7SUFDdEM7SUFDQSxJQUFJUixJQUFJLENBQUM0RCxLQUFLLEVBQUU7TUFDZHZELE9BQU8sQ0FBQ3VELEtBQUssR0FBRy9DLE1BQU0sQ0FBQ2IsSUFBSSxDQUFDNEQsS0FBSyxDQUFDO0lBQ3BDO0lBQ0EsSUFBSTVELElBQUksQ0FBQzZELEtBQUssRUFBRTtNQUNkeEQsT0FBTyxDQUFDd0QsS0FBSyxHQUFHLElBQUk7SUFDdEI7SUFDQSxJQUFJN0QsSUFBSSxDQUFDMkIsSUFBSSxJQUFJLElBQUksRUFBRTtNQUNyQnRCLE9BQU8sQ0FBQ3NCLElBQUksR0FBR2QsTUFBTSxDQUFDYixJQUFJLENBQUMyQixJQUFJLENBQUM7SUFDbEM7SUFDQSxJQUFJM0IsSUFBSSxDQUFDaUMsV0FBVyxJQUFJLElBQUksRUFBRTtNQUM1QjVCLE9BQU8sQ0FBQzRCLFdBQVcsR0FBR3BCLE1BQU0sQ0FBQ2IsSUFBSSxDQUFDaUMsV0FBVyxDQUFDO0lBQ2hEO0lBQ0EsSUFBSWpDLElBQUksQ0FBQ2dDLE9BQU8sSUFBSSxJQUFJLEVBQUU7TUFDeEIzQixPQUFPLENBQUMyQixPQUFPLEdBQUduQixNQUFNLENBQUNiLElBQUksQ0FBQ2dDLE9BQU8sQ0FBQztJQUN4QztJQUNBLElBQUloQyxJQUFJLENBQUM4RCxVQUFVLEVBQUU7TUFDbkJ6RCxPQUFPLENBQUN5RCxVQUFVLEdBQUcsSUFBSTtJQUMzQjtJQUNBLElBQUksT0FBTzlELElBQUksQ0FBQ2tDLGNBQWMsS0FBSyxRQUFRLEVBQUU7TUFDM0M3QixPQUFPLENBQUM2QixjQUFjLEdBQUdsQyxJQUFJLENBQUNrQyxjQUFjO0lBQzlDO0lBQ0EsSUFBSSxPQUFPbEMsSUFBSSxDQUFDbUMscUJBQXFCLEtBQUssUUFBUSxFQUFFO01BQ2xEOUIsT0FBTyxDQUFDOEIscUJBQXFCLEdBQUduQyxJQUFJLENBQUNtQyxxQkFBcUI7SUFDNUQ7SUFDQSxJQUFJLE9BQU9uQyxJQUFJLENBQUNvQyxzQkFBc0IsS0FBSyxRQUFRLEVBQUU7TUFDbkQvQixPQUFPLENBQUMrQixzQkFBc0IsR0FBR3BDLElBQUksQ0FBQ29DLHNCQUFzQjtJQUM5RDtJQUNBLElBQUlwQyxJQUFJLENBQUMrRCxJQUFJLEtBQUssT0FBTy9ELElBQUksQ0FBQytELElBQUksS0FBSyxRQUFRLElBQUksT0FBTy9ELElBQUksQ0FBQytELElBQUksS0FBSyxRQUFRLENBQUMsRUFBRTtNQUNqRjFELE9BQU8sQ0FBQzBELElBQUksR0FBRy9ELElBQUksQ0FBQytELElBQUk7SUFDMUI7SUFDQSxJQUFJL0QsSUFBSSxDQUFDZ0UsT0FBTyxFQUFFO01BQ2hCM0QsT0FBTyxDQUFDMkQsT0FBTyxHQUFHaEUsSUFBSSxDQUFDZ0UsT0FBTztJQUNoQztJQUNBLElBQUloRSxJQUFJLENBQUNpRSxPQUFPLElBQUksT0FBT2pFLElBQUksQ0FBQ2lFLE9BQU8sS0FBSyxRQUFRLEVBQUU7TUFDcEQ1RCxPQUFPLENBQUM0RCxPQUFPLEdBQUdqRSxJQUFJLENBQUNpRSxPQUFPO0lBQ2hDO0lBQ0EsT0FBTzVELE9BQU87RUFDaEI7RUFFQTZELFdBQVdBLENBQUEsRUFBRztJQUNaLElBQUksQ0FBQ0MsS0FBSyxDQUFDLEtBQUssRUFBRSxxQkFBcUIsRUFBRXRFLEdBQUcsSUFBSTtNQUM5QyxPQUFPLElBQUksQ0FBQ0UsVUFBVSxDQUFDRixHQUFHLENBQUM7SUFDN0IsQ0FBQyxDQUFDO0lBQ0YsSUFBSSxDQUFDc0UsS0FBSyxDQUFDLEtBQUssRUFBRSwrQkFBK0IsRUFBRXRFLEdBQUcsSUFBSTtNQUN4RCxPQUFPLElBQUksQ0FBQzRCLFNBQVMsQ0FBQzVCLEdBQUcsQ0FBQztJQUM1QixDQUFDLENBQUM7SUFDRixJQUFJLENBQUNzRSxLQUFLLENBQUMsTUFBTSxFQUFFLHFCQUFxQixFQUFFQyxxQ0FBd0IsRUFBRXZFLEdBQUcsSUFBSTtNQUN6RSxPQUFPLElBQUksQ0FBQ2dELFlBQVksQ0FBQ2hELEdBQUcsQ0FBQztJQUMvQixDQUFDLENBQUM7SUFDRixJQUFJLENBQUNzRSxLQUFLLENBQUMsS0FBSyxFQUFFLCtCQUErQixFQUFFQyxxQ0FBd0IsRUFBRXZFLEdBQUcsSUFBSTtNQUNsRixPQUFPLElBQUksQ0FBQ3FELFlBQVksQ0FBQ3JELEdBQUcsQ0FBQztJQUMvQixDQUFDLENBQUM7SUFDRixJQUFJLENBQUNzRSxLQUFLLENBQUMsUUFBUSxFQUFFLCtCQUErQixFQUFFdEUsR0FBRyxJQUFJO01BQzNELE9BQU8sSUFBSSxDQUFDdUQsWUFBWSxDQUFDdkQsR0FBRyxDQUFDO0lBQy9CLENBQUMsQ0FBQztFQUNKO0FBQ0Y7QUFBQ3dFLE9BQUEsQ0FBQTNFLGFBQUEsR0FBQUEsYUFBQTtBQUFBLElBQUE0RSxRQUFBLEdBQUFELE9BQUEsQ0FBQTdFLE9BQUEsR0FFY0UsYUFBYSIsImlnbm9yZUxpc3QiOltdfQ==