@beiguancyc/parse-server 9.9.0-ruixiang.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. package/LICENSE +176 -0
  2. package/NOTICE +10 -0
  3. package/README.md +1311 -0
  4. package/bin/parse-live-query-server +3 -0
  5. package/bin/parse-server +3 -0
  6. package/lib/AccountLockout.js +149 -0
  7. package/lib/Adapters/AdapterLoader.js +60 -0
  8. package/lib/Adapters/Analytics/AnalyticsAdapter.js +32 -0
  9. package/lib/Adapters/Auth/AuthAdapter.js +132 -0
  10. package/lib/Adapters/Auth/BaseCodeAuthAdapter.js +119 -0
  11. package/lib/Adapters/Auth/OAuth1Client.js +204 -0
  12. package/lib/Adapters/Auth/apple.js +125 -0
  13. package/lib/Adapters/Auth/facebook.js +187 -0
  14. package/lib/Adapters/Auth/gcenter.js +217 -0
  15. package/lib/Adapters/Auth/github.js +125 -0
  16. package/lib/Adapters/Auth/google.js +122 -0
  17. package/lib/Adapters/Auth/gpgames.js +125 -0
  18. package/lib/Adapters/Auth/httpsRequest.js +41 -0
  19. package/lib/Adapters/Auth/index.js +248 -0
  20. package/lib/Adapters/Auth/instagram.js +118 -0
  21. package/lib/Adapters/Auth/janraincapture.js +85 -0
  22. package/lib/Adapters/Auth/janrainengage.js +57 -0
  23. package/lib/Adapters/Auth/keycloak.js +168 -0
  24. package/lib/Adapters/Auth/ldap.js +193 -0
  25. package/lib/Adapters/Auth/line.js +125 -0
  26. package/lib/Adapters/Auth/linkedin.js +117 -0
  27. package/lib/Adapters/Auth/meetup.js +44 -0
  28. package/lib/Adapters/Auth/mfa.js +334 -0
  29. package/lib/Adapters/Auth/microsoft.js +111 -0
  30. package/lib/Adapters/Auth/oauth2.js +115 -0
  31. package/lib/Adapters/Auth/phantauth.js +53 -0
  32. package/lib/Adapters/Auth/qq.js +113 -0
  33. package/lib/Adapters/Auth/spotify.js +115 -0
  34. package/lib/Adapters/Auth/twitter.js +197 -0
  35. package/lib/Adapters/Auth/utils.js +28 -0
  36. package/lib/Adapters/Auth/vkontakte.js +55 -0
  37. package/lib/Adapters/Auth/wechat.js +110 -0
  38. package/lib/Adapters/Auth/weibo.js +141 -0
  39. package/lib/Adapters/Cache/CacheAdapter.js +40 -0
  40. package/lib/Adapters/Cache/InMemoryCache.js +61 -0
  41. package/lib/Adapters/Cache/InMemoryCacheAdapter.js +34 -0
  42. package/lib/Adapters/Cache/LRUCache.js +35 -0
  43. package/lib/Adapters/Cache/NullCacheAdapter.js +26 -0
  44. package/lib/Adapters/Cache/RedisCacheAdapter.js +109 -0
  45. package/lib/Adapters/Cache/SchemaCache.js +25 -0
  46. package/lib/Adapters/Email/MailAdapter.js +32 -0
  47. package/lib/Adapters/Files/FilesAdapter.js +129 -0
  48. package/lib/Adapters/Files/GridFSBucketAdapter.js +280 -0
  49. package/lib/Adapters/Files/GridStoreAdapter.js +5 -0
  50. package/lib/Adapters/Logger/LoggerAdapter.js +27 -0
  51. package/lib/Adapters/Logger/WinstonLogger.js +107 -0
  52. package/lib/Adapters/Logger/WinstonLoggerAdapter.js +63 -0
  53. package/lib/Adapters/MessageQueue/EventEmitterMQ.js +55 -0
  54. package/lib/Adapters/PubSub/EventEmitterPubSub.js +53 -0
  55. package/lib/Adapters/PubSub/PubSubAdapter.js +34 -0
  56. package/lib/Adapters/PubSub/RedisPubSub.js +49 -0
  57. package/lib/Adapters/Push/PushAdapter.js +40 -0
  58. package/lib/Adapters/Storage/Mongo/MongoCollection.js +212 -0
  59. package/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js +334 -0
  60. package/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js +1047 -0
  61. package/lib/Adapters/Storage/Mongo/MongoTransform.js +1397 -0
  62. package/lib/Adapters/Storage/Postgres/PostgresClient.js +38 -0
  63. package/lib/Adapters/Storage/Postgres/PostgresConfigParser.js +73 -0
  64. package/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js +2409 -0
  65. package/lib/Adapters/Storage/Postgres/sql/array/add-unique.sql +11 -0
  66. package/lib/Adapters/Storage/Postgres/sql/array/add.sql +11 -0
  67. package/lib/Adapters/Storage/Postgres/sql/array/contains-all-regex.sql +14 -0
  68. package/lib/Adapters/Storage/Postgres/sql/array/contains-all.sql +14 -0
  69. package/lib/Adapters/Storage/Postgres/sql/array/contains.sql +11 -0
  70. package/lib/Adapters/Storage/Postgres/sql/array/remove.sql +11 -0
  71. package/lib/Adapters/Storage/Postgres/sql/index.js +32 -0
  72. package/lib/Adapters/Storage/Postgres/sql/misc/json-object-set-keys.sql +19 -0
  73. package/lib/Adapters/Storage/StorageAdapter.js +2 -0
  74. package/lib/Adapters/WebSocketServer/WSAdapter.js +35 -0
  75. package/lib/Adapters/WebSocketServer/WSSAdapter.js +66 -0
  76. package/lib/Auth.js +687 -0
  77. package/lib/AuthDataLock.js +53 -0
  78. package/lib/ClientSDK.js +39 -0
  79. package/lib/Config.js +879 -0
  80. package/lib/Controllers/AdaptableController.js +72 -0
  81. package/lib/Controllers/AnalyticsController.js +43 -0
  82. package/lib/Controllers/CacheController.js +71 -0
  83. package/lib/Controllers/DatabaseController.js +1685 -0
  84. package/lib/Controllers/FilesController.js +122 -0
  85. package/lib/Controllers/HooksController.js +254 -0
  86. package/lib/Controllers/LiveQueryController.js +72 -0
  87. package/lib/Controllers/LoggerController.js +222 -0
  88. package/lib/Controllers/ParseGraphQLController.js +294 -0
  89. package/lib/Controllers/PushController.js +224 -0
  90. package/lib/Controllers/SchemaController.js +1563 -0
  91. package/lib/Controllers/UserController.js +364 -0
  92. package/lib/Controllers/index.js +251 -0
  93. package/lib/Controllers/types.js +2 -0
  94. package/lib/Deprecator/Deprecations.js +100 -0
  95. package/lib/Deprecator/Deprecator.js +140 -0
  96. package/lib/Error.js +50 -0
  97. package/lib/FileUrlValidator.js +69 -0
  98. package/lib/GraphQL/ParseGraphQLSchema.js +375 -0
  99. package/lib/GraphQL/ParseGraphQLServer.js +241 -0
  100. package/lib/GraphQL/helpers/objectsMutations.js +30 -0
  101. package/lib/GraphQL/helpers/objectsQueries.js +246 -0
  102. package/lib/GraphQL/helpers/queryComplexity.js +138 -0
  103. package/lib/GraphQL/loaders/configMutations.js +87 -0
  104. package/lib/GraphQL/loaders/configQueries.js +79 -0
  105. package/lib/GraphQL/loaders/defaultGraphQLMutations.js +21 -0
  106. package/lib/GraphQL/loaders/defaultGraphQLQueries.js +23 -0
  107. package/lib/GraphQL/loaders/defaultGraphQLTypes.js +1099 -0
  108. package/lib/GraphQL/loaders/defaultRelaySchema.js +53 -0
  109. package/lib/GraphQL/loaders/filesMutations.js +107 -0
  110. package/lib/GraphQL/loaders/functionsMutations.js +77 -0
  111. package/lib/GraphQL/loaders/parseClassMutations.js +267 -0
  112. package/lib/GraphQL/loaders/parseClassQueries.js +126 -0
  113. package/lib/GraphQL/loaders/parseClassTypes.js +493 -0
  114. package/lib/GraphQL/loaders/schemaDirectives.js +62 -0
  115. package/lib/GraphQL/loaders/schemaMutations.js +161 -0
  116. package/lib/GraphQL/loaders/schemaQueries.js +80 -0
  117. package/lib/GraphQL/loaders/schemaTypes.js +341 -0
  118. package/lib/GraphQL/loaders/usersMutations.js +433 -0
  119. package/lib/GraphQL/loaders/usersQueries.js +90 -0
  120. package/lib/GraphQL/parseGraphQLUtils.js +71 -0
  121. package/lib/GraphQL/transformers/className.js +14 -0
  122. package/lib/GraphQL/transformers/constraintType.js +53 -0
  123. package/lib/GraphQL/transformers/inputType.js +51 -0
  124. package/lib/GraphQL/transformers/mutation.js +280 -0
  125. package/lib/GraphQL/transformers/outputType.js +51 -0
  126. package/lib/GraphQL/transformers/query.js +237 -0
  127. package/lib/GraphQL/transformers/schemaFields.js +99 -0
  128. package/lib/InstallationDedup.js +178 -0
  129. package/lib/KeyPromiseQueue.js +48 -0
  130. package/lib/LiveQuery/Client.js +90 -0
  131. package/lib/LiveQuery/Id.js +20 -0
  132. package/lib/LiveQuery/ParseCloudCodePublisher.js +54 -0
  133. package/lib/LiveQuery/ParseLiveQueryServer.js +1071 -0
  134. package/lib/LiveQuery/ParsePubSub.js +37 -0
  135. package/lib/LiveQuery/ParseWebSocketServer.js +66 -0
  136. package/lib/LiveQuery/QueryTools.js +443 -0
  137. package/lib/LiveQuery/RequestSchema.js +161 -0
  138. package/lib/LiveQuery/SessionTokenCache.js +51 -0
  139. package/lib/LiveQuery/Subscription.js +47 -0
  140. package/lib/LiveQuery/equalObjects.js +50 -0
  141. package/lib/Options/Definitions.js +1599 -0
  142. package/lib/Options/docs.js +389 -0
  143. package/lib/Options/index.js +12 -0
  144. package/lib/Options/parsers.js +89 -0
  145. package/lib/Page.js +44 -0
  146. package/lib/ParseMessageQueue.js +24 -0
  147. package/lib/ParseServer.js +632 -0
  148. package/lib/ParseServerRESTController.js +173 -0
  149. package/lib/PromiseRouter.js +208 -0
  150. package/lib/Push/PushQueue.js +67 -0
  151. package/lib/Push/PushWorker.js +101 -0
  152. package/lib/Push/utils.js +129 -0
  153. package/lib/RestQuery.js +1208 -0
  154. package/lib/RestWrite.js +1671 -0
  155. package/lib/Routers/AggregateRouter.js +150 -0
  156. package/lib/Routers/AnalyticsRouter.js +26 -0
  157. package/lib/Routers/AudiencesRouter.js +54 -0
  158. package/lib/Routers/ClassesRouter.js +191 -0
  159. package/lib/Routers/CloudCodeRouter.js +87 -0
  160. package/lib/Routers/FeaturesRouter.js +72 -0
  161. package/lib/Routers/FilesRouter.js +772 -0
  162. package/lib/Routers/FunctionsRouter.js +341 -0
  163. package/lib/Routers/GlobalConfigRouter.js +123 -0
  164. package/lib/Routers/GraphQLRouter.js +41 -0
  165. package/lib/Routers/HooksRouter.js +121 -0
  166. package/lib/Routers/IAPValidationRouter.js +113 -0
  167. package/lib/Routers/InstallationsRouter.js +46 -0
  168. package/lib/Routers/LogsRouter.js +57 -0
  169. package/lib/Routers/PagesRouter.js +676 -0
  170. package/lib/Routers/PurgeRouter.js +45 -0
  171. package/lib/Routers/PushRouter.js +75 -0
  172. package/lib/Routers/RolesRouter.js +33 -0
  173. package/lib/Routers/SchemasRouter.js +118 -0
  174. package/lib/Routers/SecurityRouter.js +34 -0
  175. package/lib/Routers/SessionsRouter.js +126 -0
  176. package/lib/Routers/UsersRouter.js +733 -0
  177. package/lib/SchemaMigrations/DefinedSchemas.js +379 -0
  178. package/lib/SchemaMigrations/Migrations.js +30 -0
  179. package/lib/Security/Check.js +109 -0
  180. package/lib/Security/CheckGroup.js +44 -0
  181. package/lib/Security/CheckGroups/CheckGroupDatabase.js +44 -0
  182. package/lib/Security/CheckGroups/CheckGroupServerConfig.js +160 -0
  183. package/lib/Security/CheckGroups/CheckGroups.js +21 -0
  184. package/lib/Security/CheckRunner.js +213 -0
  185. package/lib/SharedRest.js +34 -0
  186. package/lib/StatusHandler.js +329 -0
  187. package/lib/TestUtils.js +87 -0
  188. package/lib/Utils.js +577 -0
  189. package/lib/batch.js +185 -0
  190. package/lib/cache.js +12 -0
  191. package/lib/cli/definitions/parse-live-query-server.js +9 -0
  192. package/lib/cli/definitions/parse-server.js +9 -0
  193. package/lib/cli/parse-live-query-server.js +14 -0
  194. package/lib/cli/parse-server.js +101 -0
  195. package/lib/cli/utils/commander.js +132 -0
  196. package/lib/cli/utils/runner.js +53 -0
  197. package/lib/cloud-code/Parse.Cloud.js +797 -0
  198. package/lib/cloud-code/Parse.Server.js +21 -0
  199. package/lib/cryptoUtils.js +54 -0
  200. package/lib/defaults.js +58 -0
  201. package/lib/deprecated.js +12 -0
  202. package/lib/index.js +89 -0
  203. package/lib/logger.js +40 -0
  204. package/lib/middlewares.js +810 -0
  205. package/lib/password.js +40 -0
  206. package/lib/request.js +175 -0
  207. package/lib/requiredParameter.js +11 -0
  208. package/lib/rest.js +264 -0
  209. package/lib/triggers.js +949 -0
  210. package/lib/vendor/README.md +8 -0
  211. package/lib/vendor/mongodbUrl.js +1012 -0
  212. package/package.json +172 -0
  213. package/postinstall.js +38 -0
  214. package/public/custom_json.html +17 -0
  215. package/public/custom_json.json +23 -0
  216. package/public/custom_page.html +15 -0
  217. package/public/de/email_verification_link_expired.html +24 -0
  218. package/public/de/email_verification_link_invalid.html +21 -0
  219. package/public/de/email_verification_send_fail.html +21 -0
  220. package/public/de/email_verification_send_success.html +19 -0
  221. package/public/de/email_verification_success.html +18 -0
  222. package/public/de/password_reset.html +65 -0
  223. package/public/de/password_reset_link_invalid.html +19 -0
  224. package/public/de/password_reset_success.html +18 -0
  225. package/public/de-AT/email_verification_link_expired.html +24 -0
  226. package/public/de-AT/email_verification_link_invalid.html +21 -0
  227. package/public/de-AT/email_verification_send_fail.html +21 -0
  228. package/public/de-AT/email_verification_send_success.html +19 -0
  229. package/public/de-AT/email_verification_success.html +18 -0
  230. package/public/de-AT/password_reset.html +65 -0
  231. package/public/de-AT/password_reset_link_invalid.html +19 -0
  232. package/public/de-AT/password_reset_success.html +18 -0
  233. package/public/email_verification_link_expired.html +24 -0
  234. package/public/email_verification_link_invalid.html +21 -0
  235. package/public/email_verification_send_fail.html +21 -0
  236. package/public/email_verification_send_success.html +19 -0
  237. package/public/email_verification_success.html +18 -0
  238. package/public/password_reset.html +65 -0
  239. package/public/password_reset_link_invalid.html +19 -0
  240. package/public/password_reset_success.html +18 -0
  241. package/types/@types/@parse/fs-files-adapter/index.d.ts +5 -0
  242. package/types/@types/deepcopy/index.d.ts +5 -0
  243. package/types/LiveQuery/ParseLiveQueryServer.d.ts +40 -0
  244. package/types/Options/index.d.ts +320 -0
  245. package/types/ParseServer.d.ts +65 -0
  246. package/types/eslint.config.mjs +30 -0
  247. package/types/index.d.ts +21 -0
  248. package/types/logger.d.ts +2 -0
  249. package/types/tests.ts +44 -0
  250. package/types/tsconfig.json +24 -0
  251. package/views/choose_password +215 -0
@@ -0,0 +1,632 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _QueryTools = require("./LiveQuery/QueryTools");
8
+ var _defaults = _interopRequireWildcard(require("./defaults"));
9
+ var logging = _interopRequireWildcard(require("./logger"));
10
+ var _Config = _interopRequireDefault(require("./Config"));
11
+ var _PromiseRouter = _interopRequireDefault(require("./PromiseRouter"));
12
+ var _requiredParameter = _interopRequireDefault(require("./requiredParameter"));
13
+ var _AnalyticsRouter = require("./Routers/AnalyticsRouter");
14
+ var _ClassesRouter = require("./Routers/ClassesRouter");
15
+ var _FeaturesRouter = require("./Routers/FeaturesRouter");
16
+ var _FilesRouter = require("./Routers/FilesRouter");
17
+ var _FunctionsRouter = require("./Routers/FunctionsRouter");
18
+ var _GlobalConfigRouter = require("./Routers/GlobalConfigRouter");
19
+ var _GraphQLRouter = require("./Routers/GraphQLRouter");
20
+ var _HooksRouter = require("./Routers/HooksRouter");
21
+ var _IAPValidationRouter = require("./Routers/IAPValidationRouter");
22
+ var _InstallationsRouter = require("./Routers/InstallationsRouter");
23
+ var _LogsRouter = require("./Routers/LogsRouter");
24
+ var _ParseLiveQueryServer = require("./LiveQuery/ParseLiveQueryServer");
25
+ var _PagesRouter = require("./Routers/PagesRouter");
26
+ var _PushRouter = require("./Routers/PushRouter");
27
+ var _CloudCodeRouter = require("./Routers/CloudCodeRouter");
28
+ var _RolesRouter = require("./Routers/RolesRouter");
29
+ var _SchemasRouter = require("./Routers/SchemasRouter");
30
+ var _SessionsRouter = require("./Routers/SessionsRouter");
31
+ var _UsersRouter = require("./Routers/UsersRouter");
32
+ var _PurgeRouter = require("./Routers/PurgeRouter");
33
+ var _AudiencesRouter = require("./Routers/AudiencesRouter");
34
+ var _AggregateRouter = require("./Routers/AggregateRouter");
35
+ var _ParseServerRESTController = require("./ParseServerRESTController");
36
+ var controllers = _interopRequireWildcard(require("./Controllers"));
37
+ var _ParseGraphQLServer = require("./GraphQL/ParseGraphQLServer");
38
+ var _SecurityRouter = require("./Routers/SecurityRouter");
39
+ var _CheckRunner = _interopRequireDefault(require("./Security/CheckRunner"));
40
+ var _Deprecator = _interopRequireDefault(require("./Deprecator/Deprecator"));
41
+ var _DefinedSchemas = require("./SchemaMigrations/DefinedSchemas");
42
+ var _Definitions = _interopRequireDefault(require("./Options/Definitions"));
43
+ var _TestUtils = require("./TestUtils");
44
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
45
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
46
+ // ParseServer - open-source compatible API Server for Parse apps
47
+
48
+ var batch = require('./batch'),
49
+ express = require('express'),
50
+ middlewares = require('./middlewares'),
51
+ Parse = require('parse/node').Parse,
52
+ {
53
+ parse
54
+ } = require('graphql'),
55
+ path = require('path'),
56
+ fs = require('fs');
57
+ // Mutate the Parse object to add the Cloud Code handlers
58
+ addParseCloud();
59
+
60
+ // Track connections to destroy them on shutdown
61
+ const connections = new _TestUtils.Connections();
62
+
63
+ // ParseServer works like a constructor of an express app.
64
+ // https://parseplatform.org/parse-server/api/master/ParseServerOptions.html
65
+ class ParseServer {
66
+ /**
67
+ * @constructor
68
+ * @param {ParseServerOptions} options the parse server initialization options
69
+ */
70
+ constructor(options) {
71
+ // Scan for deprecated Parse Server options
72
+ _Deprecator.default.scanParseServerOptions(options);
73
+ const interfaces = JSON.parse(JSON.stringify(_Definitions.default));
74
+ function getValidObject(root) {
75
+ const result = {};
76
+ for (const key in root) {
77
+ if (Object.prototype.hasOwnProperty.call(root[key], 'type')) {
78
+ if (root[key].type.endsWith('[]')) {
79
+ result[key] = [getValidObject(interfaces[root[key].type.slice(0, -2)])];
80
+ } else {
81
+ result[key] = getValidObject(interfaces[root[key].type]);
82
+ }
83
+ } else {
84
+ result[key] = '';
85
+ }
86
+ }
87
+ return result;
88
+ }
89
+ const optionsBlueprint = getValidObject(interfaces['ParseServerOptions']);
90
+ function validateKeyNames(original, ref, name = '') {
91
+ let result = [];
92
+ const prefix = name + (name !== '' ? '.' : '');
93
+ for (const key in original) {
94
+ if (!Object.prototype.hasOwnProperty.call(ref, key)) {
95
+ result.push(prefix + key);
96
+ } else {
97
+ if (ref[key] === '') {
98
+ continue;
99
+ }
100
+ let res = [];
101
+ if (Array.isArray(original[key]) && Array.isArray(ref[key])) {
102
+ const type = ref[key][0];
103
+ original[key].forEach((item, idx) => {
104
+ if (typeof item === 'object' && item !== null) {
105
+ res = res.concat(validateKeyNames(item, type, prefix + key + `[${idx}]`));
106
+ }
107
+ });
108
+ } else if (typeof original[key] === 'object' && typeof ref[key] === 'object') {
109
+ res = validateKeyNames(original[key], ref[key], prefix + key);
110
+ }
111
+ result = result.concat(res);
112
+ }
113
+ }
114
+ return result;
115
+ }
116
+ const diff = validateKeyNames(options, optionsBlueprint);
117
+ if (diff.length > 0) {
118
+ const logger = logging.logger;
119
+ logger.error(`Invalid key(s) found in Parse Server configuration: ${diff.join(', ')}`);
120
+ }
121
+
122
+ // Set option defaults
123
+ injectDefaults(options);
124
+ const {
125
+ appId = (0, _requiredParameter.default)('You must provide an appId!'),
126
+ masterKey = (0, _requiredParameter.default)('You must provide a masterKey!'),
127
+ javascriptKey,
128
+ serverURL = (0, _requiredParameter.default)('You must provide a serverURL!')
129
+ } = options;
130
+ // Initialize the node client SDK automatically
131
+ Parse.initialize(appId, javascriptKey || 'unused', masterKey);
132
+ Parse.serverURL = serverURL;
133
+ _Config.default.validateOptions(options);
134
+ const allControllers = controllers.getControllers(options);
135
+ options.state = 'initialized';
136
+ this.config = _Config.default.put(Object.assign({}, options, allControllers));
137
+ this.config.masterKeyIpsStore = new Map();
138
+ this.config.maintenanceKeyIpsStore = new Map();
139
+ this.config.readOnlyMasterKeyIpsStore = new Map();
140
+ (0, _QueryTools.setRegexTimeout)(options.liveQuery?.regexTimeout);
141
+ logging.setLogger(allControllers.loggerController);
142
+ }
143
+
144
+ /**
145
+ * Starts Parse Server as an express app; this promise resolves when Parse Server is ready to accept requests.
146
+ */
147
+
148
+ async start() {
149
+ try {
150
+ if (this.config.state === 'ok') {
151
+ return this;
152
+ }
153
+ this.config.state = 'starting';
154
+ _Config.default.put(this.config);
155
+ const {
156
+ databaseController,
157
+ hooksController,
158
+ cacheController,
159
+ cloud,
160
+ security,
161
+ schema,
162
+ liveQueryController
163
+ } = this.config;
164
+ try {
165
+ await databaseController.performInitialization();
166
+ } catch (e) {
167
+ if (e.code !== Parse.Error.DUPLICATE_VALUE) {
168
+ throw e;
169
+ }
170
+ }
171
+ const pushController = await controllers.getPushController(this.config);
172
+ await hooksController.load();
173
+ const startupPromises = [this.config.loadMasterKey?.()];
174
+ if (schema) {
175
+ startupPromises.push(new _DefinedSchemas.DefinedSchemas(schema, this.config).execute());
176
+ }
177
+ if (cacheController.adapter?.connect && typeof cacheController.adapter.connect === 'function') {
178
+ startupPromises.push(cacheController.adapter.connect());
179
+ }
180
+ startupPromises.push(liveQueryController.connect());
181
+ await Promise.all(startupPromises);
182
+ if (cloud) {
183
+ addParseCloud();
184
+ if (typeof cloud === 'function') {
185
+ await Promise.resolve(cloud(Parse));
186
+ } else if (typeof cloud === 'string') {
187
+ let json;
188
+ if (process.env.npm_package_json) {
189
+ json = require(process.env.npm_package_json);
190
+ }
191
+ if (process.env.npm_package_type === 'module' || json?.type === 'module') {
192
+ await import(path.resolve(process.cwd(), cloud));
193
+ } else {
194
+ require(path.resolve(process.cwd(), cloud));
195
+ }
196
+ } else {
197
+ throw "argument 'cloud' must either be a string or a function";
198
+ }
199
+ await new Promise(resolve => setTimeout(resolve, 10));
200
+ }
201
+ if (security && security.enableCheck && security.enableCheckLog) {
202
+ new _CheckRunner.default(security).run();
203
+ }
204
+ this.config.state = 'ok';
205
+ this.config = {
206
+ ...this.config,
207
+ ...pushController
208
+ };
209
+ _Config.default.put(this.config);
210
+ return this;
211
+ } catch (error) {
212
+ // eslint-disable-next-line no-console
213
+ console.error(error);
214
+ this.config.state = 'error';
215
+ throw error;
216
+ }
217
+ }
218
+ get app() {
219
+ if (!this._app) {
220
+ this._app = ParseServer.app(this.config);
221
+ }
222
+ return this._app;
223
+ }
224
+
225
+ /**
226
+ * Stops the parse server, cancels any ongoing requests and closes all connections.
227
+ *
228
+ * Currently, express doesn't shut down immediately after receiving SIGINT/SIGTERM
229
+ * if it has client connections that haven't timed out.
230
+ * (This is a known issue with node - https://github.com/nodejs/node/issues/2642)
231
+ *
232
+ * @returns {Promise<void>} a promise that resolves when the server is stopped
233
+ */
234
+ async handleShutdown() {
235
+ const serverClosePromise = (0, _TestUtils.resolvingPromise)();
236
+ const liveQueryServerClosePromise = (0, _TestUtils.resolvingPromise)();
237
+ const promises = [];
238
+ this.server.close(error => {
239
+ /* istanbul ignore next */
240
+ if (error) {
241
+ // eslint-disable-next-line no-console
242
+ console.error('Error while closing parse server', error);
243
+ }
244
+ serverClosePromise.resolve();
245
+ });
246
+ if (this.liveQueryServer?.server?.close && this.liveQueryServer.server !== this.server) {
247
+ this.liveQueryServer.server.close(error => {
248
+ /* istanbul ignore next */
249
+ if (error) {
250
+ // eslint-disable-next-line no-console
251
+ console.error('Error while closing live query server', error);
252
+ }
253
+ liveQueryServerClosePromise.resolve();
254
+ });
255
+ } else {
256
+ liveQueryServerClosePromise.resolve();
257
+ }
258
+ const {
259
+ adapter: databaseAdapter
260
+ } = this.config.databaseController;
261
+ if (databaseAdapter && typeof databaseAdapter.handleShutdown === 'function') {
262
+ promises.push(databaseAdapter.handleShutdown());
263
+ }
264
+ const {
265
+ adapter: fileAdapter
266
+ } = this.config.filesController;
267
+ if (fileAdapter && typeof fileAdapter.handleShutdown === 'function') {
268
+ promises.push(fileAdapter.handleShutdown());
269
+ }
270
+ const {
271
+ adapter: cacheAdapter
272
+ } = this.config.cacheController;
273
+ if (cacheAdapter && typeof cacheAdapter.handleShutdown === 'function') {
274
+ promises.push(cacheAdapter.handleShutdown());
275
+ }
276
+ if (this.liveQueryServer) {
277
+ promises.push(this.liveQueryServer.shutdown());
278
+ }
279
+ await Promise.all(promises);
280
+ connections.destroyAll();
281
+ await Promise.all([serverClosePromise, liveQueryServerClosePromise]);
282
+ if (this.config.serverCloseComplete) {
283
+ this.config.serverCloseComplete();
284
+ }
285
+ }
286
+
287
+ /**
288
+ * @static
289
+ * Allow developers to customize each request with inversion of control/dependency injection
290
+ */
291
+ static applyRequestContextMiddleware(api, options) {
292
+ if (options.requestContextMiddleware) {
293
+ if (typeof options.requestContextMiddleware !== 'function') {
294
+ throw new Error('requestContextMiddleware must be a function');
295
+ }
296
+ api.use(options.requestContextMiddleware);
297
+ }
298
+ }
299
+ /**
300
+ * @static
301
+ * Create an express app for the parse server
302
+ * @param {Object} options let you specify the maxUploadSize when creating the express app */
303
+ static app(options) {
304
+ const {
305
+ maxUploadSize = '20mb',
306
+ appId,
307
+ directAccess,
308
+ pages,
309
+ rateLimit = []
310
+ } = options;
311
+ // This app serves the Parse API directly.
312
+ // It's the equivalent of https://api.parse.com/1 in the hosted Parse API.
313
+ var api = express();
314
+ //api.use("/apps", express.static(__dirname + "/public"));
315
+ api.use(middlewares.allowCrossDomain(appId));
316
+ api.use(middlewares.allowDoubleForwardSlash);
317
+ api.use(middlewares.handleParseAuth(appId));
318
+ // File handling needs to be before the default JSON body parser because file
319
+ // uploads send binary data that should not be parsed as JSON.
320
+ api.use('/', new _FilesRouter.FilesRouter().expressRouter({
321
+ maxUploadSize: maxUploadSize
322
+ }));
323
+ api.use('/health', middlewares.enforceRouteAllowList, middlewares.handleParseHealth(options));
324
+ api.use('/', express.urlencoded({
325
+ extended: false
326
+ }), new _PagesRouter.PagesRouter(pages).expressRouter());
327
+ api.use(express.json({
328
+ type: req => !req.is('multipart/form-data'),
329
+ limit: maxUploadSize
330
+ }));
331
+ api.use(middlewares.allowMethodOverride);
332
+ api.use(middlewares.handleParseHeaders);
333
+ api.use(middlewares.enforceRouteAllowList);
334
+ api.set('query parser', 'extended');
335
+ const routes = Array.isArray(rateLimit) ? rateLimit : [rateLimit];
336
+ for (const route of routes) {
337
+ middlewares.addRateLimit(route, options);
338
+ }
339
+ api.use(middlewares.handleParseSession);
340
+ this.applyRequestContextMiddleware(api, options);
341
+ const appRouter = ParseServer.promiseRouter({
342
+ appId,
343
+ options
344
+ });
345
+ api.use(appRouter.expressRouter());
346
+ api.use(middlewares.handleParseErrors);
347
+
348
+ // run the following when not testing
349
+ if (!process.env.TESTING) {
350
+ //This causes tests to spew some useless warnings, so disable in test
351
+ /* istanbul ignore next */
352
+ process.on('uncaughtException', err => {
353
+ if (err.code === 'EADDRINUSE') {
354
+ // user-friendly message for this common error
355
+ process.stderr.write(`Unable to listen on port ${err.port}. The port is already in use.`);
356
+ process.exit(0);
357
+ } else {
358
+ if (err.message) {
359
+ process.stderr.write('An uncaught exception occurred: ' + err.message);
360
+ }
361
+ if (err.stack) {
362
+ process.stderr.write('Stack Trace:\n' + err.stack);
363
+ } else {
364
+ process.stderr.write(err);
365
+ }
366
+ process.exit(1);
367
+ }
368
+ });
369
+ }
370
+ if (process.env.PARSE_SERVER_ENABLE_EXPERIMENTAL_DIRECT_ACCESS === '1' || directAccess) {
371
+ Parse.CoreManager.setRESTController((0, _ParseServerRESTController.ParseServerRESTController)(appId, appRouter));
372
+ }
373
+ return api;
374
+ }
375
+ static promiseRouter({
376
+ appId,
377
+ options
378
+ }) {
379
+ const routers = [new _ClassesRouter.ClassesRouter(), new _UsersRouter.UsersRouter(), new _SessionsRouter.SessionsRouter(), new _RolesRouter.RolesRouter(), new _AnalyticsRouter.AnalyticsRouter(), new _InstallationsRouter.InstallationsRouter(), new _FunctionsRouter.FunctionsRouter(), new _SchemasRouter.SchemasRouter(), new _PushRouter.PushRouter(), new _LogsRouter.LogsRouter(), new _FeaturesRouter.FeaturesRouter(), new _GlobalConfigRouter.GlobalConfigRouter(), new _GraphQLRouter.GraphQLRouter(), new _PurgeRouter.PurgeRouter(), new _HooksRouter.HooksRouter(), new _CloudCodeRouter.CloudCodeRouter(), new _AudiencesRouter.AudiencesRouter(), new _AggregateRouter.AggregateRouter(), new _SecurityRouter.SecurityRouter()];
380
+ if (options?.enableProductPurchaseLegacyApi !== false) {
381
+ routers.push(new _IAPValidationRouter.IAPValidationRouter());
382
+ }
383
+ const routes = routers.reduce((memo, router) => {
384
+ return memo.concat(router.routes);
385
+ }, []);
386
+ const appRouter = new _PromiseRouter.default(routes, appId);
387
+ batch.mountOnto(appRouter);
388
+ return appRouter;
389
+ }
390
+
391
+ /**
392
+ * starts the parse server's express app
393
+ * @param {ParseServerOptions} options to use to start the server
394
+ * @returns {ParseServer} the parse server instance
395
+ */
396
+
397
+ async startApp(options) {
398
+ try {
399
+ await this.start();
400
+ } catch (e) {
401
+ // eslint-disable-next-line no-console
402
+ console.error('Error on ParseServer.startApp: ', e);
403
+ throw e;
404
+ }
405
+ const app = express();
406
+ if (options.middleware) {
407
+ let middleware;
408
+ if (typeof options.middleware == 'string') {
409
+ middleware = require(path.resolve(process.cwd(), options.middleware));
410
+ } else {
411
+ middleware = options.middleware; // use as-is let express fail
412
+ }
413
+ app.use(middleware);
414
+ }
415
+ app.use(options.mountPath, this.app);
416
+ if (options.mountGraphQL === true || options.mountPlayground === true) {
417
+ let graphQLCustomTypeDefs = undefined;
418
+ if (typeof options.graphQLSchema === 'string') {
419
+ graphQLCustomTypeDefs = parse(fs.readFileSync(options.graphQLSchema, 'utf8'));
420
+ } else if (typeof options.graphQLSchema === 'object' || typeof options.graphQLSchema === 'function') {
421
+ graphQLCustomTypeDefs = options.graphQLSchema;
422
+ }
423
+ const parseGraphQLServer = new _ParseGraphQLServer.ParseGraphQLServer(this, {
424
+ graphQLPath: options.graphQLPath,
425
+ playgroundPath: options.playgroundPath,
426
+ graphQLCustomTypeDefs
427
+ });
428
+ if (options.mountGraphQL) {
429
+ parseGraphQLServer.applyGraphQL(app);
430
+ }
431
+ if (options.mountPlayground) {
432
+ parseGraphQLServer.applyPlayground(app);
433
+ logging.getLogger().warn('GraphQL Playground is deprecated and will be removed in a future version. It exposes the master key in the browser. Use Parse Dashboard as GraphQL IDE or configure a third-party GraphQL client with custom request headers.');
434
+ }
435
+ }
436
+ const server = await new Promise(resolve => {
437
+ app.listen(options.port, options.host, function () {
438
+ resolve(this);
439
+ });
440
+ });
441
+ this.server = server;
442
+ connections.track(server);
443
+ if (options.startLiveQueryServer || options.liveQueryServerOptions) {
444
+ this.liveQueryServer = await ParseServer.createLiveQueryServer(server, options.liveQueryServerOptions, options);
445
+ if (this.liveQueryServer.server !== this.server) {
446
+ connections.track(this.liveQueryServer.server);
447
+ }
448
+ }
449
+ if (options.trustProxy) {
450
+ app.set('trust proxy', options.trustProxy);
451
+ }
452
+ /* istanbul ignore next */
453
+ if (!process.env.TESTING) {
454
+ configureListeners(this);
455
+ if (options.verifyServerUrl !== false) {
456
+ await ParseServer.verifyServerUrl();
457
+ }
458
+ }
459
+ this.expressApp = app;
460
+ return this;
461
+ }
462
+
463
+ /**
464
+ * Creates a new ParseServer and starts it.
465
+ * @param {ParseServerOptions} options used to start the server
466
+ * @returns {ParseServer} the parse server instance
467
+ */
468
+ static async startApp(options) {
469
+ const parseServer = new ParseServer(options);
470
+ return parseServer.startApp(options);
471
+ }
472
+
473
+ /**
474
+ * Helper method to create a liveQuery server
475
+ * @static
476
+ * @param {Server} httpServer an optional http server to pass
477
+ * @param {LiveQueryServerOptions} config options for the liveQueryServer
478
+ * @param {ParseServerOptions} options options for the ParseServer
479
+ * @returns {Promise<ParseLiveQueryServer>} the live query server instance
480
+ */
481
+ static async createLiveQueryServer(httpServer, config, options) {
482
+ if (!httpServer || config && config.port) {
483
+ var app = express();
484
+ httpServer = require('http').createServer(app);
485
+ httpServer.listen(config.port);
486
+ }
487
+ const server = new _ParseLiveQueryServer.ParseLiveQueryServer(httpServer, config, options);
488
+ await server.connect();
489
+ return server;
490
+ }
491
+ static async verifyServerUrl() {
492
+ // perform a health check on the serverURL value
493
+ if (Parse.serverURL) {
494
+ const isValidHttpUrl = string => {
495
+ let url;
496
+ try {
497
+ url = new URL(string);
498
+ } catch {
499
+ return false;
500
+ }
501
+ return url.protocol === 'http:' || url.protocol === 'https:';
502
+ };
503
+ const url = `${Parse.serverURL.replace(/\/$/, '')}/health`;
504
+ if (!isValidHttpUrl(url)) {
505
+ // eslint-disable-next-line no-console
506
+ console.warn(`\nWARNING, Unable to connect to '${Parse.serverURL}' as the URL is invalid.` + ` Cloud code and push notifications may be unavailable!\n`);
507
+ return;
508
+ }
509
+ const request = require('./request');
510
+ const response = await request({
511
+ url
512
+ }).catch(response => response);
513
+ const json = response.data || null;
514
+ const retry = response.headers?.['retry-after'];
515
+ if (retry) {
516
+ await new Promise(resolve => setTimeout(resolve, retry * 1000));
517
+ return this.verifyServerUrl();
518
+ }
519
+ if (response.status !== 200 || json?.status !== 'ok') {
520
+ /* eslint-disable no-console */
521
+ console.warn(`\nWARNING, Unable to connect to '${Parse.serverURL}'.` + ` Cloud code and push notifications may be unavailable!\n`);
522
+ /* eslint-enable no-console */
523
+ return;
524
+ }
525
+ return true;
526
+ }
527
+ }
528
+ }
529
+ function addParseCloud() {
530
+ const ParseCloud = require('./cloud-code/Parse.Cloud');
531
+ const ParseServer = require('./cloud-code/Parse.Server');
532
+ Object.defineProperty(Parse, 'Server', {
533
+ get() {
534
+ const conf = _Config.default.get(Parse.applicationId);
535
+ return {
536
+ ...conf,
537
+ ...ParseServer
538
+ };
539
+ },
540
+ set(newVal) {
541
+ newVal.appId = Parse.applicationId;
542
+ _Config.default.put(newVal);
543
+ },
544
+ configurable: true
545
+ });
546
+ Object.assign(Parse.Cloud, ParseCloud);
547
+ global.Parse = Parse;
548
+ }
549
+ function injectDefaults(options) {
550
+ Object.keys(_defaults.default).forEach(key => {
551
+ if (!Object.prototype.hasOwnProperty.call(options, key)) {
552
+ options[key] = _defaults.default[key];
553
+ }
554
+ });
555
+
556
+ // Inject defaults for database options; only when no explicit database adapter is set,
557
+ // because an explicit adapter manages its own options and passing databaseOptions alongside
558
+ // it would cause a conflict error in getDatabaseController.
559
+ if (!options.databaseAdapter) {
560
+ if (options.databaseOptions == null) {
561
+ options.databaseOptions = {};
562
+ }
563
+ if (typeof options.databaseOptions === 'object' && !Array.isArray(options.databaseOptions)) {
564
+ Object.keys(_defaults.DatabaseOptionDefaults).forEach(key => {
565
+ if (!Object.prototype.hasOwnProperty.call(options.databaseOptions, key)) {
566
+ options.databaseOptions[key] = _defaults.DatabaseOptionDefaults[key];
567
+ }
568
+ });
569
+ }
570
+ }
571
+ if (!Object.prototype.hasOwnProperty.call(options, 'serverURL')) {
572
+ options.serverURL = `http://localhost:${options.port}${options.mountPath}`;
573
+ }
574
+
575
+ // Reserved Characters
576
+ if (options.appId) {
577
+ const regex = /[!#$%'()*+&/:;=?@[\]{}^,|<>]/g;
578
+ if (options.appId.match(regex)) {
579
+ // eslint-disable-next-line no-console
580
+ console.warn(`\nWARNING, appId that contains special characters can cause issues while using with urls.\n`);
581
+ }
582
+ }
583
+
584
+ // Backwards compatibility
585
+ if (options.userSensitiveFields) {
586
+ /* eslint-disable no-console */
587
+ !process.env.TESTING && console.warn(`\nDEPRECATED: userSensitiveFields has been replaced by protectedFields allowing the ability to protect fields in all classes with CLP. \n`);
588
+ /* eslint-enable no-console */
589
+
590
+ const userSensitiveFields = Array.from(new Set([...(_defaults.default.userSensitiveFields || []), ...(options.userSensitiveFields || [])]));
591
+
592
+ // If the options.protectedFields is unset,
593
+ // it'll be assigned the default above.
594
+ // Here, protect against the case where protectedFields
595
+ // is set, but doesn't have _User.
596
+ if (!('_User' in options.protectedFields)) {
597
+ options.protectedFields = Object.assign({
598
+ _User: []
599
+ }, options.protectedFields);
600
+ }
601
+ options.protectedFields['_User']['*'] = Array.from(new Set([...(options.protectedFields['_User']['*'] || []), ...userSensitiveFields]));
602
+ }
603
+
604
+ // Merge protectedFields options with defaults.
605
+ Object.keys(_defaults.default.protectedFields).forEach(c => {
606
+ const cur = options.protectedFields[c];
607
+ if (!cur) {
608
+ options.protectedFields[c] = _defaults.default.protectedFields[c];
609
+ } else {
610
+ Object.keys(_defaults.default.protectedFields[c]).forEach(r => {
611
+ if (options.protectedFields[c][r] && options.protectedFieldsOwnerExempt === false) {
612
+ return;
613
+ }
614
+ const unq = new Set([...(options.protectedFields[c][r] || []), ..._defaults.default.protectedFields[c][r]]);
615
+ options.protectedFields[c][r] = Array.from(unq);
616
+ });
617
+ }
618
+ });
619
+ }
620
+
621
+ // Those can't be tested as it requires a subprocess
622
+ /* istanbul ignore next */
623
+ function configureListeners(parseServer) {
624
+ const handleShutdown = function () {
625
+ process.stdout.write('Termination signal received. Shutting down.');
626
+ parseServer.handleShutdown();
627
+ };
628
+ process.on('SIGTERM', handleShutdown);
629
+ process.on('SIGINT', handleShutdown);
630
+ }
631
+ var _default = exports.default = ParseServer;
632
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfUXVlcnlUb29scyIsInJlcXVpcmUiLCJfZGVmYXVsdHMiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsImxvZ2dpbmciLCJfQ29uZmlnIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl9Qcm9taXNlUm91dGVyIiwiX3JlcXVpcmVkUGFyYW1ldGVyIiwiX0FuYWx5dGljc1JvdXRlciIsIl9DbGFzc2VzUm91dGVyIiwiX0ZlYXR1cmVzUm91dGVyIiwiX0ZpbGVzUm91dGVyIiwiX0Z1bmN0aW9uc1JvdXRlciIsIl9HbG9iYWxDb25maWdSb3V0ZXIiLCJfR3JhcGhRTFJvdXRlciIsIl9Ib29rc1JvdXRlciIsIl9JQVBWYWxpZGF0aW9uUm91dGVyIiwiX0luc3RhbGxhdGlvbnNSb3V0ZXIiLCJfTG9nc1JvdXRlciIsIl9QYXJzZUxpdmVRdWVyeVNlcnZlciIsIl9QYWdlc1JvdXRlciIsIl9QdXNoUm91dGVyIiwiX0Nsb3VkQ29kZVJvdXRlciIsIl9Sb2xlc1JvdXRlciIsIl9TY2hlbWFzUm91dGVyIiwiX1Nlc3Npb25zUm91dGVyIiwiX1VzZXJzUm91dGVyIiwiX1B1cmdlUm91dGVyIiwiX0F1ZGllbmNlc1JvdXRlciIsIl9BZ2dyZWdhdGVSb3V0ZXIiLCJfUGFyc2VTZXJ2ZXJSRVNUQ29udHJvbGxlciIsImNvbnRyb2xsZXJzIiwiX1BhcnNlR3JhcGhRTFNlcnZlciIsIl9TZWN1cml0eVJvdXRlciIsIl9DaGVja1J1bm5lciIsIl9EZXByZWNhdG9yIiwiX0RlZmluZWRTY2hlbWFzIiwiX0RlZmluaXRpb25zIiwiX1Rlc3RVdGlscyIsImUiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsInQiLCJXZWFrTWFwIiwiciIsIm4iLCJvIiwiaSIsImYiLCJfX3Byb3RvX18iLCJoYXMiLCJnZXQiLCJzZXQiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsImJhdGNoIiwiZXhwcmVzcyIsIm1pZGRsZXdhcmVzIiwiUGFyc2UiLCJwYXJzZSIsInBhdGgiLCJmcyIsImFkZFBhcnNlQ2xvdWQiLCJjb25uZWN0aW9ucyIsIkNvbm5lY3Rpb25zIiwiUGFyc2VTZXJ2ZXIiLCJjb25zdHJ1Y3RvciIsIm9wdGlvbnMiLCJEZXByZWNhdG9yIiwic2NhblBhcnNlU2VydmVyT3B0aW9ucyIsImludGVyZmFjZXMiLCJKU09OIiwic3RyaW5naWZ5IiwiT3B0aW9uc0RlZmluaXRpb25zIiwiZ2V0VmFsaWRPYmplY3QiLCJyb290IiwicmVzdWx0Iiwia2V5IiwicHJvdG90eXBlIiwidHlwZSIsImVuZHNXaXRoIiwic2xpY2UiLCJvcHRpb25zQmx1ZXByaW50IiwidmFsaWRhdGVLZXlOYW1lcyIsIm9yaWdpbmFsIiwicmVmIiwibmFtZSIsInByZWZpeCIsInB1c2giLCJyZXMiLCJBcnJheSIsImlzQXJyYXkiLCJmb3JFYWNoIiwiaXRlbSIsImlkeCIsImNvbmNhdCIsImRpZmYiLCJsZW5ndGgiLCJsb2dnZXIiLCJlcnJvciIsImpvaW4iLCJpbmplY3REZWZhdWx0cyIsImFwcElkIiwicmVxdWlyZWRQYXJhbWV0ZXIiLCJtYXN0ZXJLZXkiLCJqYXZhc2NyaXB0S2V5Iiwic2VydmVyVVJMIiwiaW5pdGlhbGl6ZSIsIkNvbmZpZyIsInZhbGlkYXRlT3B0aW9ucyIsImFsbENvbnRyb2xsZXJzIiwiZ2V0Q29udHJvbGxlcnMiLCJzdGF0ZSIsImNvbmZpZyIsInB1dCIsImFzc2lnbiIsIm1hc3RlcktleUlwc1N0b3JlIiwiTWFwIiwibWFpbnRlbmFuY2VLZXlJcHNTdG9yZSIsInJlYWRPbmx5TWFzdGVyS2V5SXBzU3RvcmUiLCJzZXRSZWdleFRpbWVvdXQiLCJsaXZlUXVlcnkiLCJyZWdleFRpbWVvdXQiLCJzZXRMb2dnZXIiLCJsb2dnZXJDb250cm9sbGVyIiwic3RhcnQiLCJkYXRhYmFzZUNvbnRyb2xsZXIiLCJob29rc0NvbnRyb2xsZXIiLCJjYWNoZUNvbnRyb2xsZXIiLCJjbG91ZCIsInNlY3VyaXR5Iiwic2NoZW1hIiwibGl2ZVF1ZXJ5Q29udHJvbGxlciIsInBlcmZvcm1Jbml0aWFsaXphdGlvbiIsImNvZGUiLCJFcnJvciIsIkRVUExJQ0FURV9WQUxVRSIsInB1c2hDb250cm9sbGVyIiwiZ2V0UHVzaENvbnRyb2xsZXIiLCJsb2FkIiwic3RhcnR1cFByb21pc2VzIiwibG9hZE1hc3RlcktleSIsIkRlZmluZWRTY2hlbWFzIiwiZXhlY3V0ZSIsImFkYXB0ZXIiLCJjb25uZWN0IiwiUHJvbWlzZSIsImFsbCIsInJlc29sdmUiLCJqc29uIiwicHJvY2VzcyIsImVudiIsIm5wbV9wYWNrYWdlX2pzb24iLCJucG1fcGFja2FnZV90eXBlIiwiY3dkIiwic2V0VGltZW91dCIsImVuYWJsZUNoZWNrIiwiZW5hYmxlQ2hlY2tMb2ciLCJDaGVja1J1bm5lciIsInJ1biIsImNvbnNvbGUiLCJhcHAiLCJfYXBwIiwiaGFuZGxlU2h1dGRvd24iLCJzZXJ2ZXJDbG9zZVByb21pc2UiLCJyZXNvbHZpbmdQcm9taXNlIiwibGl2ZVF1ZXJ5U2VydmVyQ2xvc2VQcm9taXNlIiwicHJvbWlzZXMiLCJzZXJ2ZXIiLCJjbG9zZSIsImxpdmVRdWVyeVNlcnZlciIsImRhdGFiYXNlQWRhcHRlciIsImZpbGVBZGFwdGVyIiwiZmlsZXNDb250cm9sbGVyIiwiY2FjaGVBZGFwdGVyIiwic2h1dGRvd24iLCJkZXN0cm95QWxsIiwic2VydmVyQ2xvc2VDb21wbGV0ZSIsImFwcGx5UmVxdWVzdENvbnRleHRNaWRkbGV3YXJlIiwiYXBpIiwicmVxdWVzdENvbnRleHRNaWRkbGV3YXJlIiwidXNlIiwibWF4VXBsb2FkU2l6ZSIsImRpcmVjdEFjY2VzcyIsInBhZ2VzIiwicmF0ZUxpbWl0IiwiYWxsb3dDcm9zc0RvbWFpbiIsImFsbG93RG91YmxlRm9yd2FyZFNsYXNoIiwiaGFuZGxlUGFyc2VBdXRoIiwiRmlsZXNSb3V0ZXIiLCJleHByZXNzUm91dGVyIiwiZW5mb3JjZVJvdXRlQWxsb3dMaXN0IiwiaGFuZGxlUGFyc2VIZWFsdGgiLCJ1cmxlbmNvZGVkIiwiZXh0ZW5kZWQiLCJQYWdlc1JvdXRlciIsInJlcSIsImlzIiwibGltaXQiLCJhbGxvd01ldGhvZE92ZXJyaWRlIiwiaGFuZGxlUGFyc2VIZWFkZXJzIiwicm91dGVzIiwicm91dGUiLCJhZGRSYXRlTGltaXQiLCJoYW5kbGVQYXJzZVNlc3Npb24iLCJhcHBSb3V0ZXIiLCJwcm9taXNlUm91dGVyIiwiaGFuZGxlUGFyc2VFcnJvcnMiLCJURVNUSU5HIiwib24iLCJlcnIiLCJzdGRlcnIiLCJ3cml0ZSIsInBvcnQiLCJleGl0IiwibWVzc2FnZSIsInN0YWNrIiwiUEFSU0VfU0VSVkVSX0VOQUJMRV9FWFBFUklNRU5UQUxfRElSRUNUX0FDQ0VTUyIsIkNvcmVNYW5hZ2VyIiwic2V0UkVTVENvbnRyb2xsZXIiLCJQYXJzZVNlcnZlclJFU1RDb250cm9sbGVyIiwicm91dGVycyIsIkNsYXNzZXNSb3V0ZXIiLCJVc2Vyc1JvdXRlciIsIlNlc3Npb25zUm91dGVyIiwiUm9sZXNSb3V0ZXIiLCJBbmFseXRpY3NSb3V0ZXIiLCJJbnN0YWxsYXRpb25zUm91dGVyIiwiRnVuY3Rpb25zUm91dGVyIiwiU2NoZW1hc1JvdXRlciIsIlB1c2hSb3V0ZXIiLCJMb2dzUm91dGVyIiwiRmVhdHVyZXNSb3V0ZXIiLCJHbG9iYWxDb25maWdSb3V0ZXIiLCJHcmFwaFFMUm91dGVyIiwiUHVyZ2VSb3V0ZXIiLCJIb29rc1JvdXRlciIsIkNsb3VkQ29kZVJvdXRlciIsIkF1ZGllbmNlc1JvdXRlciIsIkFnZ3JlZ2F0ZVJvdXRlciIsIlNlY3VyaXR5Um91dGVyIiwiZW5hYmxlUHJvZHVjdFB1cmNoYXNlTGVnYWN5QXBpIiwiSUFQVmFsaWRhdGlvblJvdXRlciIsInJlZHVjZSIsIm1lbW8iLCJyb3V0ZXIiLCJQcm9taXNlUm91dGVyIiwibW91bnRPbnRvIiwic3RhcnRBcHAiLCJtaWRkbGV3YXJlIiwibW91bnRQYXRoIiwibW91bnRHcmFwaFFMIiwibW91bnRQbGF5Z3JvdW5kIiwiZ3JhcGhRTEN1c3RvbVR5cGVEZWZzIiwidW5kZWZpbmVkIiwiZ3JhcGhRTFNjaGVtYSIsInJlYWRGaWxlU3luYyIsInBhcnNlR3JhcGhRTFNlcnZlciIsIlBhcnNlR3JhcGhRTFNlcnZlciIsImdyYXBoUUxQYXRoIiwicGxheWdyb3VuZFBhdGgiLCJhcHBseUdyYXBoUUwiLCJhcHBseVBsYXlncm91bmQiLCJnZXRMb2dnZXIiLCJ3YXJuIiwibGlzdGVuIiwiaG9zdCIsInRyYWNrIiwic3RhcnRMaXZlUXVlcnlTZXJ2ZXIiLCJsaXZlUXVlcnlTZXJ2ZXJPcHRpb25zIiwiY3JlYXRlTGl2ZVF1ZXJ5U2VydmVyIiwidHJ1c3RQcm94eSIsImNvbmZpZ3VyZUxpc3RlbmVycyIsInZlcmlmeVNlcnZlclVybCIsImV4cHJlc3NBcHAiLCJwYXJzZVNlcnZlciIsImh0dHBTZXJ2ZXIiLCJjcmVhdGVTZXJ2ZXIiLCJQYXJzZUxpdmVRdWVyeVNlcnZlciIsImlzVmFsaWRIdHRwVXJsIiwic3RyaW5nIiwidXJsIiwiVVJMIiwicHJvdG9jb2wiLCJyZXBsYWNlIiwicmVxdWVzdCIsInJlc3BvbnNlIiwiY2F0Y2giLCJkYXRhIiwicmV0cnkiLCJoZWFkZXJzIiwic3RhdHVzIiwiUGFyc2VDbG91ZCIsImNvbmYiLCJhcHBsaWNhdGlvbklkIiwibmV3VmFsIiwiY29uZmlndXJhYmxlIiwiQ2xvdWQiLCJnbG9iYWwiLCJrZXlzIiwiZGVmYXVsdHMiLCJkYXRhYmFzZU9wdGlvbnMiLCJEYXRhYmFzZU9wdGlvbkRlZmF1bHRzIiwicmVnZXgiLCJtYXRjaCIsInVzZXJTZW5zaXRpdmVGaWVsZHMiLCJmcm9tIiwiU2V0IiwicHJvdGVjdGVkRmllbGRzIiwiX1VzZXIiLCJjIiwiY3VyIiwicHJvdGVjdGVkRmllbGRzT3duZXJFeGVtcHQiLCJ1bnEiLCJzdGRvdXQiLCJfZGVmYXVsdCIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi9zcmMvUGFyc2VTZXJ2ZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gUGFyc2VTZXJ2ZXIgLSBvcGVuLXNvdXJjZSBjb21wYXRpYmxlIEFQSSBTZXJ2ZXIgZm9yIFBhcnNlIGFwcHNcblxudmFyIGJhdGNoID0gcmVxdWlyZSgnLi9iYXRjaCcpLFxuICBleHByZXNzID0gcmVxdWlyZSgnZXhwcmVzcycpLFxuICBtaWRkbGV3YXJlcyA9IHJlcXVpcmUoJy4vbWlkZGxld2FyZXMnKSxcbiAgUGFyc2UgPSByZXF1aXJlKCdwYXJzZS9ub2RlJykuUGFyc2UsXG4gIHsgcGFyc2UgfSA9IHJlcXVpcmUoJ2dyYXBocWwnKSxcbiAgcGF0aCA9IHJlcXVpcmUoJ3BhdGgnKSxcbiAgZnMgPSByZXF1aXJlKCdmcycpO1xuXG5pbXBvcnQgeyBQYXJzZVNlcnZlck9wdGlvbnMsIExpdmVRdWVyeVNlcnZlck9wdGlvbnMgfSBmcm9tICcuL09wdGlvbnMnO1xuaW1wb3J0IHsgc2V0UmVnZXhUaW1lb3V0IH0gZnJvbSAnLi9MaXZlUXVlcnkvUXVlcnlUb29scyc7XG5pbXBvcnQgZGVmYXVsdHMsIHsgRGF0YWJhc2VPcHRpb25EZWZhdWx0cyB9IGZyb20gJy4vZGVmYXVsdHMnO1xuaW1wb3J0ICogYXMgbG9nZ2luZyBmcm9tICcuL2xvZ2dlcic7XG5pbXBvcnQgQ29uZmlnIGZyb20gJy4vQ29uZmlnJztcbmltcG9ydCBQcm9taXNlUm91dGVyIGZyb20gJy4vUHJvbWlzZVJvdXRlcic7XG5pbXBvcnQgcmVxdWlyZWRQYXJhbWV0ZXIgZnJvbSAnLi9yZXF1aXJlZFBhcmFtZXRlcic7XG5pbXBvcnQgeyBBbmFseXRpY3NSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvQW5hbHl0aWNzUm91dGVyJztcbmltcG9ydCB7IENsYXNzZXNSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvQ2xhc3Nlc1JvdXRlcic7XG5pbXBvcnQgeyBGZWF0dXJlc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9GZWF0dXJlc1JvdXRlcic7XG5pbXBvcnQgeyBGaWxlc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9GaWxlc1JvdXRlcic7XG5pbXBvcnQgeyBGdW5jdGlvbnNSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvRnVuY3Rpb25zUm91dGVyJztcbmltcG9ydCB7IEdsb2JhbENvbmZpZ1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9HbG9iYWxDb25maWdSb3V0ZXInO1xuaW1wb3J0IHsgR3JhcGhRTFJvdXRlciB9IGZyb20gJy4vUm91dGVycy9HcmFwaFFMUm91dGVyJztcbmltcG9ydCB7IEhvb2tzUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0hvb2tzUm91dGVyJztcbmltcG9ydCB7IElBUFZhbGlkYXRpb25Sb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvSUFQVmFsaWRhdGlvblJvdXRlcic7XG5pbXBvcnQgeyBJbnN0YWxsYXRpb25zUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0luc3RhbGxhdGlvbnNSb3V0ZXInO1xuaW1wb3J0IHsgTG9nc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9Mb2dzUm91dGVyJztcbmltcG9ydCB7IFBhcnNlTGl2ZVF1ZXJ5U2VydmVyIH0gZnJvbSAnLi9MaXZlUXVlcnkvUGFyc2VMaXZlUXVlcnlTZXJ2ZXInO1xuaW1wb3J0IHsgUGFnZXNSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvUGFnZXNSb3V0ZXInO1xuaW1wb3J0IHsgUHVzaFJvdXRlciB9IGZyb20gJy4vUm91dGVycy9QdXNoUm91dGVyJztcbmltcG9ydCB7IENsb3VkQ29kZVJvdXRlciB9IGZyb20gJy4vUm91dGVycy9DbG91ZENvZGVSb3V0ZXInO1xuaW1wb3J0IHsgUm9sZXNSb3V0ZXIgfSBmcm9tICcuL1JvdXRlcnMvUm9sZXNSb3V0ZXInO1xuaW1wb3J0IHsgU2NoZW1hc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9TY2hlbWFzUm91dGVyJztcbmltcG9ydCB7IFNlc3Npb25zUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL1Nlc3Npb25zUm91dGVyJztcbmltcG9ydCB7IFVzZXJzUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL1VzZXJzUm91dGVyJztcbmltcG9ydCB7IFB1cmdlUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL1B1cmdlUm91dGVyJztcbmltcG9ydCB7IEF1ZGllbmNlc1JvdXRlciB9IGZyb20gJy4vUm91dGVycy9BdWRpZW5jZXNSb3V0ZXInO1xuaW1wb3J0IHsgQWdncmVnYXRlUm91dGVyIH0gZnJvbSAnLi9Sb3V0ZXJzL0FnZ3JlZ2F0ZVJvdXRlcic7XG5pbXBvcnQgeyBQYXJzZVNlcnZlclJFU1RDb250cm9sbGVyIH0gZnJvbSAnLi9QYXJzZVNlcnZlclJFU1RDb250cm9sbGVyJztcbmltcG9ydCAqIGFzIGNvbnRyb2xsZXJzIGZyb20gJy4vQ29udHJvbGxlcnMnO1xuaW1wb3J0IHsgUGFyc2VHcmFwaFFMU2VydmVyIH0gZnJvbSAnLi9HcmFwaFFML1BhcnNlR3JhcGhRTFNlcnZlcic7XG5pbXBvcnQgeyBTZWN1cml0eVJvdXRlciB9IGZyb20gJy4vUm91dGVycy9TZWN1cml0eVJvdXRlcic7XG5pbXBvcnQgQ2hlY2tSdW5uZXIgZnJvbSAnLi9TZWN1cml0eS9DaGVja1J1bm5lcic7XG5pbXBvcnQgRGVwcmVjYXRvciBmcm9tICcuL0RlcHJlY2F0b3IvRGVwcmVjYXRvcic7XG5pbXBvcnQgeyBEZWZpbmVkU2NoZW1hcyB9IGZyb20gJy4vU2NoZW1hTWlncmF0aW9ucy9EZWZpbmVkU2NoZW1hcyc7XG5pbXBvcnQgT3B0aW9uc0RlZmluaXRpb25zIGZyb20gJy4vT3B0aW9ucy9EZWZpbml0aW9ucyc7XG5pbXBvcnQgeyByZXNvbHZpbmdQcm9taXNlLCBDb25uZWN0aW9ucyB9IGZyb20gJy4vVGVzdFV0aWxzJztcblxuLy8gTXV0YXRlIHRoZSBQYXJzZSBvYmplY3QgdG8gYWRkIHRoZSBDbG91ZCBDb2RlIGhhbmRsZXJzXG5hZGRQYXJzZUNsb3VkKCk7XG5cbi8vIFRyYWNrIGNvbm5lY3Rpb25zIHRvIGRlc3Ryb3kgdGhlbSBvbiBzaHV0ZG93blxuY29uc3QgY29ubmVjdGlvbnMgPSBuZXcgQ29ubmVjdGlvbnMoKTtcblxuLy8gUGFyc2VTZXJ2ZXIgd29ya3MgbGlrZSBhIGNvbnN0cnVjdG9yIG9mIGFuIGV4cHJlc3MgYXBwLlxuLy8gaHR0cHM6Ly9wYXJzZXBsYXRmb3JtLm9yZy9wYXJzZS1zZXJ2ZXIvYXBpL21hc3Rlci9QYXJzZVNlcnZlck9wdGlvbnMuaHRtbFxuY2xhc3MgUGFyc2VTZXJ2ZXIge1xuICBfYXBwOiBhbnk7XG4gIGNvbmZpZzogYW55O1xuICBzZXJ2ZXI6IGFueTtcbiAgZXhwcmVzc0FwcDogYW55O1xuICBsaXZlUXVlcnlTZXJ2ZXI6IGFueTtcbiAgLyoqXG4gICAqIEBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge1BhcnNlU2VydmVyT3B0aW9uc30gb3B0aW9ucyB0aGUgcGFyc2Ugc2VydmVyIGluaXRpYWxpemF0aW9uIG9wdGlvbnNcbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucykge1xuICAgIC8vIFNjYW4gZm9yIGRlcHJlY2F0ZWQgUGFyc2UgU2VydmVyIG9wdGlvbnNcbiAgICBEZXByZWNhdG9yLnNjYW5QYXJzZVNlcnZlck9wdGlvbnMob3B0aW9ucyk7XG5cbiAgICBjb25zdCBpbnRlcmZhY2VzID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShPcHRpb25zRGVmaW5pdGlvbnMpKTtcblxuICAgIGZ1bmN0aW9uIGdldFZhbGlkT2JqZWN0KHJvb3QpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHt9O1xuICAgICAgZm9yIChjb25zdCBrZXkgaW4gcm9vdCkge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJvb3Rba2V5XSwgJ3R5cGUnKSkge1xuICAgICAgICAgIGlmIChyb290W2tleV0udHlwZS5lbmRzV2l0aCgnW10nKSkge1xuICAgICAgICAgICAgcmVzdWx0W2tleV0gPSBbZ2V0VmFsaWRPYmplY3QoaW50ZXJmYWNlc1tyb290W2tleV0udHlwZS5zbGljZSgwLCAtMildKV07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdFtrZXldID0gZ2V0VmFsaWRPYmplY3QoaW50ZXJmYWNlc1tyb290W2tleV0udHlwZV0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXN1bHRba2V5XSA9ICcnO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGNvbnN0IG9wdGlvbnNCbHVlcHJpbnQgPSBnZXRWYWxpZE9iamVjdChpbnRlcmZhY2VzWydQYXJzZVNlcnZlck9wdGlvbnMnXSk7XG5cbiAgICBmdW5jdGlvbiB2YWxpZGF0ZUtleU5hbWVzKG9yaWdpbmFsLCByZWYsIG5hbWUgPSAnJykge1xuICAgICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgY29uc3QgcHJlZml4ID0gbmFtZSArIChuYW1lICE9PSAnJyA/ICcuJyA6ICcnKTtcbiAgICAgIGZvciAoY29uc3Qga2V5IGluIG9yaWdpbmFsKSB7XG4gICAgICAgIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJlZiwga2V5KSkge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKHByZWZpeCArIGtleSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKHJlZltrZXldID09PSAnJykgeyBjb250aW51ZTsgfVxuICAgICAgICAgIGxldCByZXMgPSBbXTtcbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShvcmlnaW5hbFtrZXldKSAmJiBBcnJheS5pc0FycmF5KHJlZltrZXldKSkge1xuICAgICAgICAgICAgY29uc3QgdHlwZSA9IHJlZltrZXldWzBdO1xuICAgICAgICAgICAgb3JpZ2luYWxba2V5XS5mb3JFYWNoKChpdGVtLCBpZHgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKHR5cGVvZiBpdGVtID09PSAnb2JqZWN0JyAmJiBpdGVtICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmVzID0gcmVzLmNvbmNhdCh2YWxpZGF0ZUtleU5hbWVzKGl0ZW0sIHR5cGUsIHByZWZpeCArIGtleSArIGBbJHtpZHh9XWApKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygb3JpZ2luYWxba2V5XSA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIHJlZltrZXldID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmVzID0gdmFsaWRhdGVLZXlOYW1lcyhvcmlnaW5hbFtrZXldLCByZWZba2V5XSwgcHJlZml4ICsga2V5KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LmNvbmNhdChyZXMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGNvbnN0IGRpZmYgPSB2YWxpZGF0ZUtleU5hbWVzKG9wdGlvbnMsIG9wdGlvbnNCbHVlcHJpbnQpO1xuICAgIGlmIChkaWZmLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IGxvZ2dlciA9IChsb2dnaW5nIGFzIGFueSkubG9nZ2VyO1xuICAgICAgbG9nZ2VyLmVycm9yKGBJbnZhbGlkIGtleShzKSBmb3VuZCBpbiBQYXJzZSBTZXJ2ZXIgY29uZmlndXJhdGlvbjogJHtkaWZmLmpvaW4oJywgJyl9YCk7XG4gICAgfVxuXG4gICAgLy8gU2V0IG9wdGlvbiBkZWZhdWx0c1xuICAgIGluamVjdERlZmF1bHRzKG9wdGlvbnMpO1xuICAgIGNvbnN0IHtcbiAgICAgIGFwcElkID0gcmVxdWlyZWRQYXJhbWV0ZXIoJ1lvdSBtdXN0IHByb3ZpZGUgYW4gYXBwSWQhJyksXG4gICAgICBtYXN0ZXJLZXkgPSByZXF1aXJlZFBhcmFtZXRlcignWW91IG11c3QgcHJvdmlkZSBhIG1hc3RlcktleSEnKSxcbiAgICAgIGphdmFzY3JpcHRLZXksXG4gICAgICBzZXJ2ZXJVUkwgPSByZXF1aXJlZFBhcmFtZXRlcignWW91IG11c3QgcHJvdmlkZSBhIHNlcnZlclVSTCEnKSxcbiAgICB9ID0gb3B0aW9ucztcbiAgICAvLyBJbml0aWFsaXplIHRoZSBub2RlIGNsaWVudCBTREsgYXV0b21hdGljYWxseVxuICAgIFBhcnNlLmluaXRpYWxpemUoYXBwSWQsIGphdmFzY3JpcHRLZXkgfHwgJ3VudXNlZCcsIG1hc3RlcktleSk7XG4gICAgUGFyc2Uuc2VydmVyVVJMID0gc2VydmVyVVJMO1xuICAgIENvbmZpZy52YWxpZGF0ZU9wdGlvbnMob3B0aW9ucyk7XG4gICAgY29uc3QgYWxsQ29udHJvbGxlcnMgPSBjb250cm9sbGVycy5nZXRDb250cm9sbGVycyhvcHRpb25zKTtcblxuICAgIChvcHRpb25zIGFzIGFueSkuc3RhdGUgPSAnaW5pdGlhbGl6ZWQnO1xuICAgIHRoaXMuY29uZmlnID0gQ29uZmlnLnB1dChPYmplY3QuYXNzaWduKHt9LCBvcHRpb25zLCBhbGxDb250cm9sbGVycykpO1xuICAgIHRoaXMuY29uZmlnLm1hc3RlcktleUlwc1N0b3JlID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuY29uZmlnLm1haW50ZW5hbmNlS2V5SXBzU3RvcmUgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5jb25maWcucmVhZE9ubHlNYXN0ZXJLZXlJcHNTdG9yZSA9IG5ldyBNYXAoKTtcbiAgICBzZXRSZWdleFRpbWVvdXQob3B0aW9ucy5saXZlUXVlcnk/LnJlZ2V4VGltZW91dCk7XG4gICAgbG9nZ2luZy5zZXRMb2dnZXIoYWxsQ29udHJvbGxlcnMubG9nZ2VyQ29udHJvbGxlcik7XG4gIH1cblxuICAvKipcbiAgICogU3RhcnRzIFBhcnNlIFNlcnZlciBhcyBhbiBleHByZXNzIGFwcDsgdGhpcyBwcm9taXNlIHJlc29sdmVzIHdoZW4gUGFyc2UgU2VydmVyIGlzIHJlYWR5IHRvIGFjY2VwdCByZXF1ZXN0cy5cbiAgICovXG5cbiAgYXN5bmMgc3RhcnQoKTogUHJvbWlzZTx0aGlzPiB7XG4gICAgdHJ5IHtcbiAgICAgIGlmICh0aGlzLmNvbmZpZy5zdGF0ZSA9PT0gJ29rJykge1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cbiAgICAgIHRoaXMuY29uZmlnLnN0YXRlID0gJ3N0YXJ0aW5nJztcbiAgICAgIENvbmZpZy5wdXQodGhpcy5jb25maWcpO1xuICAgICAgY29uc3Qge1xuICAgICAgICBkYXRhYmFzZUNvbnRyb2xsZXIsXG4gICAgICAgIGhvb2tzQ29udHJvbGxlcixcbiAgICAgICAgY2FjaGVDb250cm9sbGVyLFxuICAgICAgICBjbG91ZCxcbiAgICAgICAgc2VjdXJpdHksXG4gICAgICAgIHNjaGVtYSxcbiAgICAgICAgbGl2ZVF1ZXJ5Q29udHJvbGxlcixcbiAgICAgIH0gPSB0aGlzLmNvbmZpZztcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGRhdGFiYXNlQ29udHJvbGxlci5wZXJmb3JtSW5pdGlhbGl6YXRpb24oKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGUuY29kZSAhPT0gUGFyc2UuRXJyb3IuRFVQTElDQVRFX1ZBTFVFKSB7XG4gICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY29uc3QgcHVzaENvbnRyb2xsZXIgPSBhd2FpdCBjb250cm9sbGVycy5nZXRQdXNoQ29udHJvbGxlcih0aGlzLmNvbmZpZyk7XG4gICAgICBhd2FpdCBob29rc0NvbnRyb2xsZXIubG9hZCgpO1xuICAgICAgY29uc3Qgc3RhcnR1cFByb21pc2VzID0gW3RoaXMuY29uZmlnLmxvYWRNYXN0ZXJLZXk/LigpXTtcbiAgICAgIGlmIChzY2hlbWEpIHtcbiAgICAgICAgc3RhcnR1cFByb21pc2VzLnB1c2gobmV3IERlZmluZWRTY2hlbWFzKHNjaGVtYSwgdGhpcy5jb25maWcpLmV4ZWN1dGUoKSk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgIGNhY2hlQ29udHJvbGxlci5hZGFwdGVyPy5jb25uZWN0ICYmXG4gICAgICAgIHR5cGVvZiBjYWNoZUNvbnRyb2xsZXIuYWRhcHRlci5jb25uZWN0ID09PSAnZnVuY3Rpb24nXG4gICAgICApIHtcbiAgICAgICAgc3RhcnR1cFByb21pc2VzLnB1c2goY2FjaGVDb250cm9sbGVyLmFkYXB0ZXIuY29ubmVjdCgpKTtcbiAgICAgIH1cbiAgICAgIHN0YXJ0dXBQcm9taXNlcy5wdXNoKGxpdmVRdWVyeUNvbnRyb2xsZXIuY29ubmVjdCgpKTtcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKHN0YXJ0dXBQcm9taXNlcyk7XG4gICAgICBpZiAoY2xvdWQpIHtcbiAgICAgICAgYWRkUGFyc2VDbG91ZCgpO1xuICAgICAgICBpZiAodHlwZW9mIGNsb3VkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgYXdhaXQgUHJvbWlzZS5yZXNvbHZlKGNsb3VkKFBhcnNlKSk7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGNsb3VkID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIGxldCBqc29uO1xuICAgICAgICAgIGlmIChwcm9jZXNzLmVudi5ucG1fcGFja2FnZV9qc29uKSB7XG4gICAgICAgICAgICBqc29uID0gcmVxdWlyZShwcm9jZXNzLmVudi5ucG1fcGFja2FnZV9qc29uKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHByb2Nlc3MuZW52Lm5wbV9wYWNrYWdlX3R5cGUgPT09ICdtb2R1bGUnIHx8IGpzb24/LnR5cGUgPT09ICdtb2R1bGUnKSB7XG4gICAgICAgICAgICBhd2FpdCBpbXBvcnQocGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIGNsb3VkKSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcXVpcmUocGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIGNsb3VkKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IFwiYXJndW1lbnQgJ2Nsb3VkJyBtdXN0IGVpdGhlciBiZSBhIHN0cmluZyBvciBhIGZ1bmN0aW9uXCI7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDEwKSk7XG4gICAgICB9XG4gICAgICBpZiAoc2VjdXJpdHkgJiYgc2VjdXJpdHkuZW5hYmxlQ2hlY2sgJiYgc2VjdXJpdHkuZW5hYmxlQ2hlY2tMb2cpIHtcbiAgICAgICAgbmV3IENoZWNrUnVubmVyKHNlY3VyaXR5KS5ydW4oKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuY29uZmlnLnN0YXRlID0gJ29rJztcbiAgICAgIHRoaXMuY29uZmlnID0geyAuLi50aGlzLmNvbmZpZywgLi4ucHVzaENvbnRyb2xsZXIgfTtcbiAgICAgIENvbmZpZy5wdXQodGhpcy5jb25maWcpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgIHRoaXMuY29uZmlnLnN0YXRlID0gJ2Vycm9yJztcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfVxuXG4gIGdldCBhcHAoKSB7XG4gICAgaWYgKCF0aGlzLl9hcHApIHtcbiAgICAgIHRoaXMuX2FwcCA9IFBhcnNlU2VydmVyLmFwcCh0aGlzLmNvbmZpZyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9hcHA7XG4gIH1cblxuICAvKipcbiAgICogU3RvcHMgdGhlIHBhcnNlIHNlcnZlciwgY2FuY2VscyBhbnkgb25nb2luZyByZXF1ZXN0cyBhbmQgY2xvc2VzIGFsbCBjb25uZWN0aW9ucy5cbiAgICpcbiAgICogQ3VycmVudGx5LCBleHByZXNzIGRvZXNuJ3Qgc2h1dCBkb3duIGltbWVkaWF0ZWx5IGFmdGVyIHJlY2VpdmluZyBTSUdJTlQvU0lHVEVSTVxuICAgKiBpZiBpdCBoYXMgY2xpZW50IGNvbm5lY3Rpb25zIHRoYXQgaGF2ZW4ndCB0aW1lZCBvdXQuXG4gICAqIChUaGlzIGlzIGEga25vd24gaXNzdWUgd2l0aCBub2RlIC0gaHR0cHM6Ly9naXRodWIuY29tL25vZGVqcy9ub2RlL2lzc3Vlcy8yNjQyKVxuICAgKlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgc2VydmVyIGlzIHN0b3BwZWRcbiAgICovXG4gIGFzeW5jIGhhbmRsZVNodXRkb3duKCkge1xuICAgIGNvbnN0IHNlcnZlckNsb3NlUHJvbWlzZSA9IHJlc29sdmluZ1Byb21pc2UoKTtcbiAgICBjb25zdCBsaXZlUXVlcnlTZXJ2ZXJDbG9zZVByb21pc2UgPSByZXNvbHZpbmdQcm9taXNlKCk7XG4gICAgY29uc3QgcHJvbWlzZXMgPSBbXTtcbiAgICB0aGlzLnNlcnZlci5jbG9zZSgoZXJyb3IpID0+IHtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3Igd2hpbGUgY2xvc2luZyBwYXJzZSBzZXJ2ZXInLCBlcnJvcik7XG4gICAgICB9XG4gICAgICBzZXJ2ZXJDbG9zZVByb21pc2UucmVzb2x2ZSgpO1xuICAgIH0pO1xuICAgIGlmICh0aGlzLmxpdmVRdWVyeVNlcnZlcj8uc2VydmVyPy5jbG9zZSAmJiB0aGlzLmxpdmVRdWVyeVNlcnZlci5zZXJ2ZXIgIT09IHRoaXMuc2VydmVyKSB7XG4gICAgICB0aGlzLmxpdmVRdWVyeVNlcnZlci5zZXJ2ZXIuY2xvc2UoKGVycm9yKSA9PiB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3Igd2hpbGUgY2xvc2luZyBsaXZlIHF1ZXJ5IHNlcnZlcicsIGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgICBsaXZlUXVlcnlTZXJ2ZXJDbG9zZVByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxpdmVRdWVyeVNlcnZlckNsb3NlUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuICAgIGNvbnN0IHsgYWRhcHRlcjogZGF0YWJhc2VBZGFwdGVyIH0gPSB0aGlzLmNvbmZpZy5kYXRhYmFzZUNvbnRyb2xsZXI7XG4gICAgaWYgKGRhdGFiYXNlQWRhcHRlciAmJiB0eXBlb2YgZGF0YWJhc2VBZGFwdGVyLmhhbmRsZVNodXRkb3duID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBwcm9taXNlcy5wdXNoKGRhdGFiYXNlQWRhcHRlci5oYW5kbGVTaHV0ZG93bigpKTtcbiAgICB9XG4gICAgY29uc3QgeyBhZGFwdGVyOiBmaWxlQWRhcHRlciB9ID0gdGhpcy5jb25maWcuZmlsZXNDb250cm9sbGVyO1xuICAgIGlmIChmaWxlQWRhcHRlciAmJiB0eXBlb2YgZmlsZUFkYXB0ZXIuaGFuZGxlU2h1dGRvd24gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHByb21pc2VzLnB1c2goZmlsZUFkYXB0ZXIuaGFuZGxlU2h1dGRvd24oKSk7XG4gICAgfVxuICAgIGNvbnN0IHsgYWRhcHRlcjogY2FjaGVBZGFwdGVyIH0gPSB0aGlzLmNvbmZpZy5jYWNoZUNvbnRyb2xsZXI7XG4gICAgaWYgKGNhY2hlQWRhcHRlciAmJiB0eXBlb2YgY2FjaGVBZGFwdGVyLmhhbmRsZVNodXRkb3duID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBwcm9taXNlcy5wdXNoKGNhY2hlQWRhcHRlci5oYW5kbGVTaHV0ZG93bigpKTtcbiAgICB9XG4gICAgaWYgKHRoaXMubGl2ZVF1ZXJ5U2VydmVyKSB7XG4gICAgICBwcm9taXNlcy5wdXNoKHRoaXMubGl2ZVF1ZXJ5U2VydmVyLnNodXRkb3duKCkpO1xuICAgIH1cbiAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgY29ubmVjdGlvbnMuZGVzdHJveUFsbCgpO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFtzZXJ2ZXJDbG9zZVByb21pc2UsIGxpdmVRdWVyeVNlcnZlckNsb3NlUHJvbWlzZV0pO1xuICAgIGlmICh0aGlzLmNvbmZpZy5zZXJ2ZXJDbG9zZUNvbXBsZXRlKSB7XG4gICAgICB0aGlzLmNvbmZpZy5zZXJ2ZXJDbG9zZUNvbXBsZXRlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBzdGF0aWNcbiAgICogQWxsb3cgZGV2ZWxvcGVycyB0byBjdXN0b21pemUgZWFjaCByZXF1ZXN0IHdpdGggaW52ZXJzaW9uIG9mIGNvbnRyb2wvZGVwZW5kZW5jeSBpbmplY3Rpb25cbiAgICovXG4gIHN0YXRpYyBhcHBseVJlcXVlc3RDb250ZXh0TWlkZGxld2FyZShhcGksIG9wdGlvbnMpIHtcbiAgICBpZiAob3B0aW9ucy5yZXF1ZXN0Q29udGV4dE1pZGRsZXdhcmUpIHtcbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5yZXF1ZXN0Q29udGV4dE1pZGRsZXdhcmUgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdyZXF1ZXN0Q29udGV4dE1pZGRsZXdhcmUgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gICAgICB9XG4gICAgICBhcGkudXNlKG9wdGlvbnMucmVxdWVzdENvbnRleHRNaWRkbGV3YXJlKTtcbiAgICB9XG4gIH1cbiAgLyoqXG4gICAqIEBzdGF0aWNcbiAgICogQ3JlYXRlIGFuIGV4cHJlc3MgYXBwIGZvciB0aGUgcGFyc2Ugc2VydmVyXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIGxldCB5b3Ugc3BlY2lmeSB0aGUgbWF4VXBsb2FkU2l6ZSB3aGVuIGNyZWF0aW5nIHRoZSBleHByZXNzIGFwcCAgKi9cbiAgc3RhdGljIGFwcChvcHRpb25zKSB7XG4gICAgY29uc3Qge1xuICAgICAgbWF4VXBsb2FkU2l6ZSA9ICcyMG1iJyxcbiAgICAgIGFwcElkLFxuICAgICAgZGlyZWN0QWNjZXNzLFxuICAgICAgcGFnZXMsXG4gICAgICByYXRlTGltaXQgPSBbXSxcbiAgICB9ID0gb3B0aW9ucztcbiAgICAvLyBUaGlzIGFwcCBzZXJ2ZXMgdGhlIFBhcnNlIEFQSSBkaXJlY3RseS5cbiAgICAvLyBJdCdzIHRoZSBlcXVpdmFsZW50IG9mIGh0dHBzOi8vYXBpLnBhcnNlLmNvbS8xIGluIHRoZSBob3N0ZWQgUGFyc2UgQVBJLlxuICAgIHZhciBhcGkgPSBleHByZXNzKCk7XG4gICAgLy9hcGkudXNlKFwiL2FwcHNcIiwgZXhwcmVzcy5zdGF0aWMoX19kaXJuYW1lICsgXCIvcHVibGljXCIpKTtcbiAgICBhcGkudXNlKG1pZGRsZXdhcmVzLmFsbG93Q3Jvc3NEb21haW4oYXBwSWQpKTtcbiAgICBhcGkudXNlKG1pZGRsZXdhcmVzLmFsbG93RG91YmxlRm9yd2FyZFNsYXNoKTtcbiAgICBhcGkudXNlKG1pZGRsZXdhcmVzLmhhbmRsZVBhcnNlQXV0aChhcHBJZCkpO1xuICAgIC8vIEZpbGUgaGFuZGxpbmcgbmVlZHMgdG8gYmUgYmVmb3JlIHRoZSBkZWZhdWx0IEpTT04gYm9keSBwYXJzZXIgYmVjYXVzZSBmaWxlXG4gICAgLy8gdXBsb2FkcyBzZW5kIGJpbmFyeSBkYXRhIHRoYXQgc2hvdWxkIG5vdCBiZSBwYXJzZWQgYXMgSlNPTi5cbiAgICBhcGkudXNlKFxuICAgICAgJy8nLFxuICAgICAgbmV3IEZpbGVzUm91dGVyKCkuZXhwcmVzc1JvdXRlcih7XG4gICAgICAgIG1heFVwbG9hZFNpemU6IG1heFVwbG9hZFNpemUsXG4gICAgICB9KVxuICAgICk7XG5cbiAgICBhcGkudXNlKCcvaGVhbHRoJywgbWlkZGxld2FyZXMuZW5mb3JjZVJvdXRlQWxsb3dMaXN0LCBtaWRkbGV3YXJlcy5oYW5kbGVQYXJzZUhlYWx0aChvcHRpb25zKSk7XG5cbiAgICBhcGkudXNlKFxuICAgICAgJy8nLFxuICAgICAgZXhwcmVzcy51cmxlbmNvZGVkKHsgZXh0ZW5kZWQ6IGZhbHNlIH0pLFxuICAgICAgbmV3IFBhZ2VzUm91dGVyKHBhZ2VzKS5leHByZXNzUm91dGVyKClcbiAgICApO1xuXG4gICAgYXBpLnVzZShleHByZXNzLmpzb24oeyB0eXBlOiByZXEgPT4gIXJlcS5pcygnbXVsdGlwYXJ0L2Zvcm0tZGF0YScpLCBsaW1pdDogbWF4VXBsb2FkU2l6ZSB9KSk7XG4gICAgYXBpLnVzZShtaWRkbGV3YXJlcy5hbGxvd01ldGhvZE92ZXJyaWRlKTtcbiAgICBhcGkudXNlKG1pZGRsZXdhcmVzLmhhbmRsZVBhcnNlSGVhZGVycyk7XG4gICAgYXBpLnVzZShtaWRkbGV3YXJlcy5lbmZvcmNlUm91dGVBbGxvd0xpc3QpO1xuICAgIGFwaS5zZXQoJ3F1ZXJ5IHBhcnNlcicsICdleHRlbmRlZCcpO1xuICAgIGNvbnN0IHJvdXRlcyA9IEFycmF5LmlzQXJyYXkocmF0ZUxpbWl0KSA/IHJhdGVMaW1pdCA6IFtyYXRlTGltaXRdO1xuICAgIGZvciAoY29uc3Qgcm91dGUgb2Ygcm91dGVzKSB7XG4gICAgICBtaWRkbGV3YXJlcy5hZGRSYXRlTGltaXQocm91dGUsIG9wdGlvbnMpO1xuICAgIH1cbiAgICBhcGkudXNlKG1pZGRsZXdhcmVzLmhhbmRsZVBhcnNlU2Vzc2lvbik7XG4gICAgdGhpcy5hcHBseVJlcXVlc3RDb250ZXh0TWlkZGxld2FyZShhcGksIG9wdGlvbnMpO1xuICAgIGNvbnN0IGFwcFJvdXRlciA9IFBhcnNlU2VydmVyLnByb21pc2VSb3V0ZXIoeyBhcHBJZCwgb3B0aW9ucyB9KTtcbiAgICBhcGkudXNlKGFwcFJvdXRlci5leHByZXNzUm91dGVyKCkpO1xuXG4gICAgYXBpLnVzZShtaWRkbGV3YXJlcy5oYW5kbGVQYXJzZUVycm9ycyk7XG5cbiAgICAvLyBydW4gdGhlIGZvbGxvd2luZyB3aGVuIG5vdCB0ZXN0aW5nXG4gICAgaWYgKCFwcm9jZXNzLmVudi5URVNUSU5HKSB7XG4gICAgICAvL1RoaXMgY2F1c2VzIHRlc3RzIHRvIHNwZXcgc29tZSB1c2VsZXNzIHdhcm5pbmdzLCBzbyBkaXNhYmxlIGluIHRlc3RcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICBwcm9jZXNzLm9uKCd1bmNhdWdodEV4Y2VwdGlvbicsIChlcnI6IGFueSkgPT4ge1xuICAgICAgICBpZiAoZXJyLmNvZGUgPT09ICdFQUREUklOVVNFJykge1xuICAgICAgICAgIC8vIHVzZXItZnJpZW5kbHkgbWVzc2FnZSBmb3IgdGhpcyBjb21tb24gZXJyb3JcbiAgICAgICAgICBwcm9jZXNzLnN0ZGVyci53cml0ZShgVW5hYmxlIHRvIGxpc3RlbiBvbiBwb3J0ICR7ZXJyLnBvcnR9LiBUaGUgcG9ydCBpcyBhbHJlYWR5IGluIHVzZS5gKTtcbiAgICAgICAgICBwcm9jZXNzLmV4aXQoMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGVyci5tZXNzYWdlKSB7XG4gICAgICAgICAgICBwcm9jZXNzLnN0ZGVyci53cml0ZSgnQW4gdW5jYXVnaHQgZXhjZXB0aW9uIG9jY3VycmVkOiAnICsgZXJyLm1lc3NhZ2UpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZXJyLnN0YWNrKSB7XG4gICAgICAgICAgICBwcm9jZXNzLnN0ZGVyci53cml0ZSgnU3RhY2sgVHJhY2U6XFxuJyArIGVyci5zdGFjayk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHByb2Nlc3Muc3RkZXJyLndyaXRlKGVycik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICAgIGlmIChwcm9jZXNzLmVudi5QQVJTRV9TRVJWRVJfRU5BQkxFX0VYUEVSSU1FTlRBTF9ESVJFQ1RfQUNDRVNTID09PSAnMScgfHwgZGlyZWN0QWNjZXNzKSB7XG4gICAgICBQYXJzZS5Db3JlTWFuYWdlci5zZXRSRVNUQ29udHJvbGxlcihQYXJzZVNlcnZlclJFU1RDb250cm9sbGVyKGFwcElkLCBhcHBSb3V0ZXIpKTtcbiAgICB9XG4gICAgcmV0dXJuIGFwaTtcbiAgfVxuXG4gIHN0YXRpYyBwcm9taXNlUm91dGVyKHsgYXBwSWQsIG9wdGlvbnMgfSkge1xuICAgIGNvbnN0IHJvdXRlcnMgPSBbXG4gICAgICBuZXcgQ2xhc3Nlc1JvdXRlcigpLFxuICAgICAgbmV3IFVzZXJzUm91dGVyKCksXG4gICAgICBuZXcgU2Vzc2lvbnNSb3V0ZXIoKSxcbiAgICAgIG5ldyBSb2xlc1JvdXRlcigpLFxuICAgICAgbmV3IEFuYWx5dGljc1JvdXRlcigpLFxuICAgICAgbmV3IEluc3RhbGxhdGlvbnNSb3V0ZXIoKSxcbiAgICAgIG5ldyBGdW5jdGlvbnNSb3V0ZXIoKSxcbiAgICAgIG5ldyBTY2hlbWFzUm91dGVyKCksXG4gICAgICBuZXcgUHVzaFJvdXRlcigpLFxuICAgICAgbmV3IExvZ3NSb3V0ZXIoKSxcbiAgICAgIG5ldyBGZWF0dXJlc1JvdXRlcigpLFxuICAgICAgbmV3IEdsb2JhbENvbmZpZ1JvdXRlcigpLFxuICAgICAgbmV3IEdyYXBoUUxSb3V0ZXIoKSxcbiAgICAgIG5ldyBQdXJnZVJvdXRlcigpLFxuICAgICAgbmV3IEhvb2tzUm91dGVyKCksXG4gICAgICBuZXcgQ2xvdWRDb2RlUm91dGVyKCksXG4gICAgICBuZXcgQXVkaWVuY2VzUm91dGVyKCksXG4gICAgICBuZXcgQWdncmVnYXRlUm91dGVyKCksXG4gICAgICBuZXcgU2VjdXJpdHlSb3V0ZXIoKSxcbiAgICBdO1xuXG4gICAgaWYgKG9wdGlvbnM/LmVuYWJsZVByb2R1Y3RQdXJjaGFzZUxlZ2FjeUFwaSAhPT0gZmFsc2UpIHtcbiAgICAgIHJvdXRlcnMucHVzaChuZXcgSUFQVmFsaWRhdGlvblJvdXRlcigpKTtcbiAgICB9XG5cbiAgICBjb25zdCByb3V0ZXMgPSByb3V0ZXJzLnJlZHVjZSgobWVtbywgcm91dGVyKSA9PiB7XG4gICAgICByZXR1cm4gbWVtby5jb25jYXQocm91dGVyLnJvdXRlcyk7XG4gICAgfSwgW10pO1xuXG4gICAgY29uc3QgYXBwUm91dGVyID0gbmV3IFByb21pc2VSb3V0ZXIocm91dGVzLCBhcHBJZCk7XG5cbiAgICBiYXRjaC5tb3VudE9udG8oYXBwUm91dGVyKTtcbiAgICByZXR1cm4gYXBwUm91dGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIHN0YXJ0cyB0aGUgcGFyc2Ugc2VydmVyJ3MgZXhwcmVzcyBhcHBcbiAgICogQHBhcmFtIHtQYXJzZVNlcnZlck9wdGlvbnN9IG9wdGlvbnMgdG8gdXNlIHRvIHN0YXJ0IHRoZSBzZXJ2ZXJcbiAgICogQHJldHVybnMge1BhcnNlU2VydmVyfSB0aGUgcGFyc2Ugc2VydmVyIGluc3RhbmNlXG4gICAqL1xuXG4gIGFzeW5jIHN0YXJ0QXBwKG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucykge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLnN0YXJ0KCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIG9uIFBhcnNlU2VydmVyLnN0YXJ0QXBwOiAnLCBlKTtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICAgIGNvbnN0IGFwcCA9IGV4cHJlc3MoKTtcbiAgICBpZiAob3B0aW9ucy5taWRkbGV3YXJlKSB7XG4gICAgICBsZXQgbWlkZGxld2FyZTtcbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5taWRkbGV3YXJlID09ICdzdHJpbmcnKSB7XG4gICAgICAgIG1pZGRsZXdhcmUgPSByZXF1aXJlKHBhdGgucmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCBvcHRpb25zLm1pZGRsZXdhcmUpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG1pZGRsZXdhcmUgPSBvcHRpb25zLm1pZGRsZXdhcmU7IC8vIHVzZSBhcy1pcyBsZXQgZXhwcmVzcyBmYWlsXG4gICAgICB9XG4gICAgICBhcHAudXNlKG1pZGRsZXdhcmUpO1xuICAgIH1cbiAgICBhcHAudXNlKG9wdGlvbnMubW91bnRQYXRoLCB0aGlzLmFwcCk7XG5cbiAgICBpZiAob3B0aW9ucy5tb3VudEdyYXBoUUwgPT09IHRydWUgfHwgb3B0aW9ucy5tb3VudFBsYXlncm91bmQgPT09IHRydWUpIHtcbiAgICAgIGxldCBncmFwaFFMQ3VzdG9tVHlwZURlZnMgPSB1bmRlZmluZWQ7XG4gICAgICBpZiAodHlwZW9mIG9wdGlvbnMuZ3JhcGhRTFNjaGVtYSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgZ3JhcGhRTEN1c3RvbVR5cGVEZWZzID0gcGFyc2UoZnMucmVhZEZpbGVTeW5jKG9wdGlvbnMuZ3JhcGhRTFNjaGVtYSwgJ3V0ZjgnKSk7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICB0eXBlb2Ygb3B0aW9ucy5ncmFwaFFMU2NoZW1hID09PSAnb2JqZWN0JyB8fFxuICAgICAgICB0eXBlb2Ygb3B0aW9ucy5ncmFwaFFMU2NoZW1hID09PSAnZnVuY3Rpb24nXG4gICAgICApIHtcbiAgICAgICAgZ3JhcGhRTEN1c3RvbVR5cGVEZWZzID0gb3B0aW9ucy5ncmFwaFFMU2NoZW1hO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwYXJzZUdyYXBoUUxTZXJ2ZXIgPSBuZXcgUGFyc2VHcmFwaFFMU2VydmVyKHRoaXMsIHtcbiAgICAgICAgZ3JhcGhRTFBhdGg6IG9wdGlvbnMuZ3JhcGhRTFBhdGgsXG4gICAgICAgIHBsYXlncm91bmRQYXRoOiBvcHRpb25zLnBsYXlncm91bmRQYXRoLFxuICAgICAgICBncmFwaFFMQ3VzdG9tVHlwZURlZnMsXG4gICAgICB9KTtcblxuICAgICAgaWYgKG9wdGlvbnMubW91bnRHcmFwaFFMKSB7XG4gICAgICAgIHBhcnNlR3JhcGhRTFNlcnZlci5hcHBseUdyYXBoUUwoYXBwKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMubW91bnRQbGF5Z3JvdW5kKSB7XG4gICAgICAgIHBhcnNlR3JhcGhRTFNlcnZlci5hcHBseVBsYXlncm91bmQoYXBwKTtcbiAgICAgICAgbG9nZ2luZy5nZXRMb2dnZXIoKS53YXJuKFxuICAgICAgICAgICdHcmFwaFFMIFBsYXlncm91bmQgaXMgZGVwcmVjYXRlZCBhbmQgd2lsbCBiZSByZW1vdmVkIGluIGEgZnV0dXJlIHZlcnNpb24uIEl0IGV4cG9zZXMgdGhlIG1hc3RlciBrZXkgaW4gdGhlIGJyb3dzZXIuIFVzZSBQYXJzZSBEYXNoYm9hcmQgYXMgR3JhcGhRTCBJREUgb3IgY29uZmlndXJlIGEgdGhpcmQtcGFydHkgR3JhcGhRTCBjbGllbnQgd2l0aCBjdXN0b20gcmVxdWVzdCBoZWFkZXJzLidcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3Qgc2VydmVyID0gYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICBhcHAubGlzdGVuKG9wdGlvbnMucG9ydCwgb3B0aW9ucy5ob3N0LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJlc29sdmUodGhpcyk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICB0aGlzLnNlcnZlciA9IHNlcnZlcjtcbiAgICBjb25uZWN0aW9ucy50cmFjayhzZXJ2ZXIpO1xuXG4gICAgaWYgKG9wdGlvbnMuc3RhcnRMaXZlUXVlcnlTZXJ2ZXIgfHwgb3B0aW9ucy5saXZlUXVlcnlTZXJ2ZXJPcHRpb25zKSB7XG4gICAgICB0aGlzLmxpdmVRdWVyeVNlcnZlciA9IGF3YWl0IFBhcnNlU2VydmVyLmNyZWF0ZUxpdmVRdWVyeVNlcnZlcihcbiAgICAgICAgc2VydmVyLFxuICAgICAgICBvcHRpb25zLmxpdmVRdWVyeVNlcnZlck9wdGlvbnMsXG4gICAgICAgIG9wdGlvbnNcbiAgICAgICk7XG4gICAgICBpZiAodGhpcy5saXZlUXVlcnlTZXJ2ZXIuc2VydmVyICE9PSB0aGlzLnNlcnZlcikge1xuICAgICAgICBjb25uZWN0aW9ucy50cmFjayh0aGlzLmxpdmVRdWVyeVNlcnZlci5zZXJ2ZXIpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAob3B0aW9ucy50cnVzdFByb3h5KSB7XG4gICAgICBhcHAuc2V0KCd0cnVzdCBwcm94eScsIG9wdGlvbnMudHJ1c3RQcm94eSk7XG4gICAgfVxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgaWYgKCFwcm9jZXNzLmVudi5URVNUSU5HKSB7XG4gICAgICBjb25maWd1cmVMaXN0ZW5lcnModGhpcyk7XG4gICAgICBpZiAob3B0aW9ucy52ZXJpZnlTZXJ2ZXJVcmwgIT09IGZhbHNlKSB7XG4gICAgICAgIGF3YWl0IFBhcnNlU2VydmVyLnZlcmlmeVNlcnZlclVybCgpO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLmV4cHJlc3NBcHAgPSBhcHA7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBQYXJzZVNlcnZlciBhbmQgc3RhcnRzIGl0LlxuICAgKiBAcGFyYW0ge1BhcnNlU2VydmVyT3B0aW9uc30gb3B0aW9ucyB1c2VkIHRvIHN0YXJ0IHRoZSBzZXJ2ZXJcbiAgICogQHJldHVybnMge1BhcnNlU2VydmVyfSB0aGUgcGFyc2Ugc2VydmVyIGluc3RhbmNlXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgc3RhcnRBcHAob3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zKSB7XG4gICAgY29uc3QgcGFyc2VTZXJ2ZXIgPSBuZXcgUGFyc2VTZXJ2ZXIob3B0aW9ucyk7XG4gICAgcmV0dXJuIHBhcnNlU2VydmVyLnN0YXJ0QXBwKG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhlbHBlciBtZXRob2QgdG8gY3JlYXRlIGEgbGl2ZVF1ZXJ5IHNlcnZlclxuICAgKiBAc3RhdGljXG4gICAqIEBwYXJhbSB7U2VydmVyfSBodHRwU2VydmVyIGFuIG9wdGlvbmFsIGh0dHAgc2VydmVyIHRvIHBhc3NcbiAgICogQHBhcmFtIHtMaXZlUXVlcnlTZXJ2ZXJPcHRpb25zfSBjb25maWcgb3B0aW9ucyBmb3IgdGhlIGxpdmVRdWVyeVNlcnZlclxuICAgKiBAcGFyYW0ge1BhcnNlU2VydmVyT3B0aW9uc30gb3B0aW9ucyBvcHRpb25zIGZvciB0aGUgUGFyc2VTZXJ2ZXJcbiAgICogQHJldHVybnMge1Byb21pc2U8UGFyc2VMaXZlUXVlcnlTZXJ2ZXI+fSB0aGUgbGl2ZSBxdWVyeSBzZXJ2ZXIgaW5zdGFuY2VcbiAgICovXG4gIHN0YXRpYyBhc3luYyBjcmVhdGVMaXZlUXVlcnlTZXJ2ZXIoXG4gICAgaHR0cFNlcnZlcixcbiAgICBjb25maWc6IExpdmVRdWVyeVNlcnZlck9wdGlvbnMsXG4gICAgb3B0aW9uczogUGFyc2VTZXJ2ZXJPcHRpb25zXG4gICk6IFByb21pc2U8UGFyc2VMaXZlUXVlcnlTZXJ2ZXI+IHtcbiAgICBpZiAoIWh0dHBTZXJ2ZXIgfHwgKGNvbmZpZyAmJiBjb25maWcucG9ydCkpIHtcbiAgICAgIHZhciBhcHAgPSBleHByZXNzKCk7XG4gICAgICBodHRwU2VydmVyID0gcmVxdWlyZSgnaHR0cCcpLmNyZWF0ZVNlcnZlcihhcHApO1xuICAgICAgaHR0cFNlcnZlci5saXN0ZW4oY29uZmlnLnBvcnQpO1xuICAgIH1cbiAgICBjb25zdCBzZXJ2ZXIgPSBuZXcgUGFyc2VMaXZlUXVlcnlTZXJ2ZXIoaHR0cFNlcnZlciwgY29uZmlnLCBvcHRpb25zKTtcbiAgICBhd2FpdCBzZXJ2ZXIuY29ubmVjdCgpO1xuICAgIHJldHVybiBzZXJ2ZXI7XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgdmVyaWZ5U2VydmVyVXJsKCkge1xuICAgIC8vIHBlcmZvcm0gYSBoZWFsdGggY2hlY2sgb24gdGhlIHNlcnZlclVSTCB2YWx1ZVxuICAgIGlmIChQYXJzZS5zZXJ2ZXJVUkwpIHtcbiAgICAgIGNvbnN0IGlzVmFsaWRIdHRwVXJsID0gc3RyaW5nID0+IHtcbiAgICAgICAgbGV0IHVybDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB1cmwgPSBuZXcgVVJMKHN0cmluZyk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdXJsLnByb3RvY29sID09PSAnaHR0cDonIHx8IHVybC5wcm90b2NvbCA9PT0gJ2h0dHBzOic7XG4gICAgICB9O1xuICAgICAgY29uc3QgdXJsID0gYCR7UGFyc2Uuc2VydmVyVVJMLnJlcGxhY2UoL1xcLyQvLCAnJyl9L2hlYWx0aGA7XG4gICAgICBpZiAoIWlzVmFsaWRIdHRwVXJsKHVybCkpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgIGBcXG5XQVJOSU5HLCBVbmFibGUgdG8gY29ubmVjdCB0byAnJHtQYXJzZS5zZXJ2ZXJVUkx9JyBhcyB0aGUgVVJMIGlzIGludmFsaWQuYCArXG4gICAgICAgICAgICBgIENsb3VkIGNvZGUgYW5kIHB1c2ggbm90aWZpY2F0aW9ucyBtYXkgYmUgdW5hdmFpbGFibGUhXFxuYFxuICAgICAgICApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCByZXF1ZXN0ID0gcmVxdWlyZSgnLi9yZXF1ZXN0Jyk7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHJlcXVlc3QoeyB1cmwgfSkuY2F0Y2gocmVzcG9uc2UgPT4gcmVzcG9uc2UpO1xuICAgICAgY29uc3QganNvbiA9IHJlc3BvbnNlLmRhdGEgfHwgbnVsbDtcbiAgICAgIGNvbnN0IHJldHJ5ID0gcmVzcG9uc2UuaGVhZGVycz8uWydyZXRyeS1hZnRlciddO1xuICAgICAgaWYgKHJldHJ5KSB7XG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCByZXRyeSAqIDEwMDApKTtcbiAgICAgICAgcmV0dXJuIHRoaXMudmVyaWZ5U2VydmVyVXJsKCk7XG4gICAgICB9XG4gICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzICE9PSAyMDAgfHwganNvbj8uc3RhdHVzICE9PSAnb2snKSB7XG4gICAgICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgIGBcXG5XQVJOSU5HLCBVbmFibGUgdG8gY29ubmVjdCB0byAnJHtQYXJzZS5zZXJ2ZXJVUkx9Jy5gICtcbiAgICAgICAgICAgIGAgQ2xvdWQgY29kZSBhbmQgcHVzaCBub3RpZmljYXRpb25zIG1heSBiZSB1bmF2YWlsYWJsZSFcXG5gXG4gICAgICAgICk7XG4gICAgICAgIC8qIGVzbGludC1lbmFibGUgbm8tY29uc29sZSAqL1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gYWRkUGFyc2VDbG91ZCgpIHtcbiAgY29uc3QgUGFyc2VDbG91ZCA9IHJlcXVpcmUoJy4vY2xvdWQtY29kZS9QYXJzZS5DbG91ZCcpO1xuICBjb25zdCBQYXJzZVNlcnZlciA9IHJlcXVpcmUoJy4vY2xvdWQtY29kZS9QYXJzZS5TZXJ2ZXInKTtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFBhcnNlLCAnU2VydmVyJywge1xuICAgIGdldCgpIHtcbiAgICAgIGNvbnN0IGNvbmYgPSBDb25maWcuZ2V0KFBhcnNlLmFwcGxpY2F0aW9uSWQpO1xuICAgICAgcmV0dXJuIHsgLi4uY29uZiwgLi4uUGFyc2VTZXJ2ZXIgfTtcbiAgICB9LFxuICAgIHNldChuZXdWYWwpIHtcbiAgICAgIG5ld1ZhbC5hcHBJZCA9IFBhcnNlLmFwcGxpY2F0aW9uSWQ7XG4gICAgICBDb25maWcucHV0KG5ld1ZhbCk7XG4gICAgfSxcbiAgICBjb25maWd1cmFibGU6IHRydWUsXG4gIH0pO1xuICBPYmplY3QuYXNzaWduKFBhcnNlLkNsb3VkLCBQYXJzZUNsb3VkKTtcbiAgZ2xvYmFsLlBhcnNlID0gUGFyc2U7XG59XG5cbmZ1bmN0aW9uIGluamVjdERlZmF1bHRzKG9wdGlvbnM6IFBhcnNlU2VydmVyT3B0aW9ucykge1xuICBPYmplY3Qua2V5cyhkZWZhdWx0cykuZm9yRWFjaChrZXkgPT4ge1xuICAgIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9wdGlvbnMsIGtleSkpIHtcbiAgICAgIG9wdGlvbnNba2V5XSA9IGRlZmF1bHRzW2tleV07XG4gICAgfVxuICB9KTtcblxuICAvLyBJbmplY3QgZGVmYXVsdHMgZm9yIGRhdGFiYXNlIG9wdGlvbnM7IG9ubHkgd2hlbiBubyBleHBsaWNpdCBkYXRhYmFzZSBhZGFwdGVyIGlzIHNldCxcbiAgLy8gYmVjYXVzZSBhbiBleHBsaWNpdCBhZGFwdGVyIG1hbmFnZXMgaXRzIG93biBvcHRpb25zIGFuZCBwYXNzaW5nIGRhdGFiYXNlT3B0aW9ucyBhbG9uZ3NpZGVcbiAgLy8gaXQgd291bGQgY2F1c2UgYSBjb25mbGljdCBlcnJvciBpbiBnZXREYXRhYmFzZUNvbnRyb2xsZXIuXG4gIGlmICghb3B0aW9ucy5kYXRhYmFzZUFkYXB0ZXIpIHtcbiAgICBpZiAob3B0aW9ucy5kYXRhYmFzZU9wdGlvbnMgPT0gbnVsbCkge1xuICAgICAgb3B0aW9ucy5kYXRhYmFzZU9wdGlvbnMgPSB7fTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLmRhdGFiYXNlT3B0aW9ucyA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkob3B0aW9ucy5kYXRhYmFzZU9wdGlvbnMpKSB7XG4gICAgICBPYmplY3Qua2V5cyhEYXRhYmFzZU9wdGlvbkRlZmF1bHRzKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9wdGlvbnMuZGF0YWJhc2VPcHRpb25zLCBrZXkpKSB7XG4gICAgICAgICAgb3B0aW9ucy5kYXRhYmFzZU9wdGlvbnNba2V5XSA9IERhdGFiYXNlT3B0aW9uRGVmYXVsdHNba2V5XTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob3B0aW9ucywgJ3NlcnZlclVSTCcpKSB7XG4gICAgb3B0aW9ucy5zZXJ2ZXJVUkwgPSBgaHR0cDovL2xvY2FsaG9zdDoke29wdGlvbnMucG9ydH0ke29wdGlvbnMubW91bnRQYXRofWA7XG4gIH1cblxuICAvLyBSZXNlcnZlZCBDaGFyYWN0ZXJzXG4gIGlmIChvcHRpb25zLmFwcElkKSB7XG4gICAgY29uc3QgcmVnZXggPSAvWyEjJCUnKCkqKyYvOjs9P0BbXFxde31eLHw8Pl0vZztcbiAgICBpZiAob3B0aW9ucy5hcHBJZC5tYXRjaChyZWdleCkpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIGBcXG5XQVJOSU5HLCBhcHBJZCB0aGF0IGNvbnRhaW5zIHNwZWNpYWwgY2hhcmFjdGVycyBjYW4gY2F1c2UgaXNzdWVzIHdoaWxlIHVzaW5nIHdpdGggdXJscy5cXG5gXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8vIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5XG4gIGlmIChvcHRpb25zLnVzZXJTZW5zaXRpdmVGaWVsZHMpIHtcbiAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG4gICAgIXByb2Nlc3MuZW52LlRFU1RJTkcgJiZcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYFxcbkRFUFJFQ0FURUQ6IHVzZXJTZW5zaXRpdmVGaWVsZHMgaGFzIGJlZW4gcmVwbGFjZWQgYnkgcHJvdGVjdGVkRmllbGRzIGFsbG93aW5nIHRoZSBhYmlsaXR5IHRvIHByb3RlY3QgZmllbGRzIGluIGFsbCBjbGFzc2VzIHdpdGggQ0xQLiBcXG5gXG4gICAgICApO1xuICAgIC8qIGVzbGludC1lbmFibGUgbm8tY29uc29sZSAqL1xuXG4gICAgY29uc3QgdXNlclNlbnNpdGl2ZUZpZWxkcyA9IEFycmF5LmZyb20oXG4gICAgICBuZXcgU2V0KFsuLi4oZGVmYXVsdHMudXNlclNlbnNpdGl2ZUZpZWxkcyB8fCBbXSksIC4uLihvcHRpb25zLnVzZXJTZW5zaXRpdmVGaWVsZHMgfHwgW10pXSlcbiAgICApO1xuXG4gICAgLy8gSWYgdGhlIG9wdGlvbnMucHJvdGVjdGVkRmllbGRzIGlzIHVuc2V0LFxuICAgIC8vIGl0J2xsIGJlIGFzc2lnbmVkIHRoZSBkZWZhdWx0IGFib3ZlLlxuICAgIC8vIEhlcmUsIHByb3RlY3QgYWdhaW5zdCB0aGUgY2FzZSB3aGVyZSBwcm90ZWN0ZWRGaWVsZHNcbiAgICAvLyBpcyBzZXQsIGJ1dCBkb2Vzbid0IGhhdmUgX1VzZXIuXG4gICAgaWYgKCEoJ19Vc2VyJyBpbiBvcHRpb25zLnByb3RlY3RlZEZpZWxkcykpIHtcbiAgICAgIG9wdGlvbnMucHJvdGVjdGVkRmllbGRzID0gT2JqZWN0LmFzc2lnbih7IF9Vc2VyOiBbXSB9LCBvcHRpb25zLnByb3RlY3RlZEZpZWxkcyk7XG4gICAgfVxuXG4gICAgb3B0aW9ucy5wcm90ZWN0ZWRGaWVsZHNbJ19Vc2VyJ11bJyonXSA9IEFycmF5LmZyb20oXG4gICAgICBuZXcgU2V0KFsuLi4ob3B0aW9ucy5wcm90ZWN0ZWRGaWVsZHNbJ19Vc2VyJ11bJyonXSB8fCBbXSksIC4uLnVzZXJTZW5zaXRpdmVGaWVsZHNdKVxuICAgICk7XG4gIH1cblxuICAvLyBNZXJnZSBwcm90ZWN0ZWRGaWVsZHMgb3B0aW9ucyB3aXRoIGRlZmF1bHRzLlxuICBPYmplY3Qua2V5cyhkZWZhdWx0cy5wcm90ZWN0ZWRGaWVsZHMpLmZvckVhY2goYyA9PiB7XG4gICAgY29uc3QgY3VyID0gb3B0aW9ucy5wcm90ZWN0ZWRGaWVsZHNbY107XG4gICAgaWYgKCFjdXIpIHtcbiAgICAgIG9wdGlvbnMucHJvdGVjdGVkRmllbGRzW2NdID0gZGVmYXVsdHMucHJvdGVjdGVkRmllbGRzW2NdO1xuICAgIH0gZWxzZSB7XG4gICAgICBPYmplY3Qua2V5cyhkZWZhdWx0cy5wcm90ZWN0ZWRGaWVsZHNbY10pLmZvckVhY2gociA9PiB7XG4gICAgICAgIGlmIChvcHRpb25zLnByb3RlY3RlZEZpZWxkc1tjXVtyXSAmJiBvcHRpb25zLnByb3RlY3RlZEZpZWxkc093bmVyRXhlbXB0ID09PSBmYWxzZSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB1bnEgPSBuZXcgU2V0KFtcbiAgICAgICAgICAuLi4ob3B0aW9ucy5wcm90ZWN0ZWRGaWVsZHNbY11bcl0gfHwgW10pLFxuICAgICAgICAgIC4uLmRlZmF1bHRzLnByb3RlY3RlZEZpZWxkc1tjXVtyXSxcbiAgICAgICAgXSk7XG4gICAgICAgIG9wdGlvbnMucHJvdGVjdGVkRmllbGRzW2NdW3JdID0gQXJyYXkuZnJvbSh1bnEpO1xuICAgICAgfSk7XG4gICAgfVxuICB9KTtcbn1cblxuLy8gVGhvc2UgY2FuJ3QgYmUgdGVzdGVkIGFzIGl0IHJlcXVpcmVzIGEgc3VicHJvY2Vzc1xuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbmZ1bmN0aW9uIGNvbmZpZ3VyZUxpc3RlbmVycyhwYXJzZVNlcnZlcikge1xuICBjb25zdCBoYW5kbGVTaHV0ZG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICBwcm9jZXNzLnN0ZG91dC53cml0ZSgnVGVybWluYXRpb24gc2lnbmFsIHJlY2VpdmVkLiBTaHV0dGluZyBkb3duLicpO1xuICAgIHBhcnNlU2VydmVyLmhhbmRsZVNodXRkb3duKCk7XG4gIH07XG4gIHByb2Nlc3Mub24oJ1NJR1RFUk0nLCBoYW5kbGVTaHV0ZG93bik7XG4gIHByb2Nlc3Mub24oJ1NJR0lOVCcsIGhhbmRsZVNodXRkb3duKTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgUGFyc2VTZXJ2ZXI7XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQVdBLElBQUFBLFdBQUEsR0FBQUMsT0FBQTtBQUNBLElBQUFDLFNBQUEsR0FBQUMsdUJBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFHLE9BQUEsR0FBQUQsdUJBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFJLE9BQUEsR0FBQUMsc0JBQUEsQ0FBQUwsT0FBQTtBQUNBLElBQUFNLGNBQUEsR0FBQUQsc0JBQUEsQ0FBQUwsT0FBQTtBQUNBLElBQUFPLGtCQUFBLEdBQUFGLHNCQUFBLENBQUFMLE9BQUE7QUFDQSxJQUFBUSxnQkFBQSxHQUFBUixPQUFBO0FBQ0EsSUFBQVMsY0FBQSxHQUFBVCxPQUFBO0FBQ0EsSUFBQVUsZUFBQSxHQUFBVixPQUFBO0FBQ0EsSUFBQVcsWUFBQSxHQUFBWCxPQUFBO0FBQ0EsSUFBQVksZ0JBQUEsR0FBQVosT0FBQTtBQUNBLElBQUFhLG1CQUFBLEdBQUFiLE9BQUE7QUFDQSxJQUFBYyxjQUFBLEdBQUFkLE9BQUE7QUFDQSxJQUFBZSxZQUFBLEdBQUFmLE9BQUE7QUFDQSxJQUFBZ0Isb0JBQUEsR0FBQWhCLE9BQUE7QUFDQSxJQUFBaUIsb0JBQUEsR0FBQWpCLE9BQUE7QUFDQSxJQUFBa0IsV0FBQSxHQUFBbEIsT0FBQTtBQUNBLElBQUFtQixxQkFBQSxHQUFBbkIsT0FBQTtBQUNBLElBQUFvQixZQUFBLEdBQUFwQixPQUFBO0FBQ0EsSUFBQXFCLFdBQUEsR0FBQXJCLE9BQUE7QUFDQSxJQUFBc0IsZ0JBQUEsR0FBQXRCLE9BQUE7QUFDQSxJQUFBdUIsWUFBQSxHQUFBdkIsT0FBQTtBQUNBLElBQUF3QixjQUFBLEdBQUF4QixPQUFBO0FBQ0EsSUFBQXlCLGVBQUEsR0FBQXpCLE9BQUE7QUFDQSxJQUFBMEIsWUFBQSxHQUFBMUIsT0FBQTtBQUNBLElBQUEyQixZQUFBLEdBQUEzQixPQUFBO0FBQ0EsSUFBQTRCLGdCQUFBLEdBQUE1QixPQUFBO0FBQ0EsSUFBQTZCLGdCQUFBLEdBQUE3QixPQUFBO0FBQ0EsSUFBQThCLDBCQUFBLEdBQUE5QixPQUFBO0FBQ0EsSUFBQStCLFdBQUEsR0FBQTdCLHVCQUFBLENBQUFGLE9BQUE7QUFDQSxJQUFBZ0MsbUJBQUEsR0FBQWhDLE9BQUE7QUFDQSxJQUFBaUMsZUFBQSxHQUFBakMsT0FBQTtBQUNBLElBQUFrQyxZQUFBLEdBQUE3QixzQkFBQSxDQUFBTCxPQUFBO0FBQ0EsSUFBQW1DLFdBQUEsR0FBQTlCLHNCQUFBLENBQUFMLE9BQUE7QUFDQSxJQUFBb0MsZUFBQSxHQUFBcEMsT0FBQTtBQUNBLElBQUFxQyxZQUFBLEdBQUFoQyxzQkFBQSxDQUFBTCxPQUFBO0FBQ0EsSUFBQXNDLFVBQUEsR0FBQXRDLE9BQUE7QUFBNEQsU0FBQUssdUJBQUFrQyxDQUFBLFdBQUFBLENBQUEsSUFBQUEsQ0FBQSxDQUFBQyxVQUFBLEdBQUFELENBQUEsS0FBQUUsT0FBQSxFQUFBRixDQUFBO0FBQUEsU0FBQXJDLHdCQUFBcUMsQ0FBQSxFQUFBRyxDQUFBLDZCQUFBQyxPQUFBLE1BQUFDLENBQUEsT0FBQUQsT0FBQSxJQUFBRSxDQUFBLE9BQUFGLE9BQUEsWUFBQXpDLHVCQUFBLFlBQUFBLENBQUFxQyxDQUFBLEVBQUFHLENBQUEsU0FBQUEsQ0FBQSxJQUFBSCxDQUFBLElBQUFBLENBQUEsQ0FBQUMsVUFBQSxTQUFBRCxDQUFBLE1BQUFPLENBQUEsRUFBQUMsQ0FBQSxFQUFBQyxDQUFBLEtBQUFDLFNBQUEsUUFBQVIsT0FBQSxFQUFBRixDQUFBLGlCQUFBQSxDQUFBLHVCQUFBQSxDQUFBLHlCQUFBQSxDQUFBLFNBQUFTLENBQUEsTUFBQUYsQ0FBQSxHQUFBSixDQUFBLEdBQUFHLENBQUEsR0FBQUQsQ0FBQSxRQUFBRSxDQUFBLENBQUFJLEdBQUEsQ0FBQVgsQ0FBQSxVQUFBTyxDQUFBLENBQUFLLEdBQUEsQ0FBQVosQ0FBQSxHQUFBTyxDQUFBLENBQUFNLEdBQUEsQ0FBQWIsQ0FBQSxFQUFBUyxDQUFBLGdCQUFBTixDQUFBLElBQUFILENBQUEsZ0JBQUFHLENBQUEsT0FBQVcsY0FBQSxDQUFBQyxJQUFBLENBQUFmLENBQUEsRUFBQUcsQ0FBQSxPQUFBSyxDQUFBLElBQUFELENBQUEsR0FBQVMsTUFBQSxDQUFBQyxjQUFBLEtBQUFELE1BQUEsQ0FBQUUsd0JBQUEsQ0FBQWxCLENBQUEsRUFBQUcsQ0FBQSxPQUFBSyxDQUFBLENBQUFJLEdBQUEsSUFBQUosQ0FBQSxDQUFBSyxHQUFBLElBQUFOLENBQUEsQ0FBQUUsQ0FBQSxFQUFBTixDQUFBLEVBQUFLLENBQUEsSUFBQUMsQ0FBQSxDQUFBTixDQUFBLElBQUFILENBQUEsQ0FBQUcsQ0FBQSxXQUFBTSxDQUFBLEtBQUFULENBQUEsRUFBQUcsQ0FBQTtBQS9DNUQ7O0FBRUEsSUFBSWdCLEtBQUssR0FBRzFELE9BQU8sQ0FBQyxTQUFTLENBQUM7RUFDNUIyRCxPQUFPLEdBQUczRCxPQUFPLENBQUMsU0FBUyxDQUFDO0VBQzVCNEQsV0FBVyxHQUFHNUQsT0FBTyxDQUFDLGVBQWUsQ0FBQztFQUN0QzZELEtBQUssR0FBRzdELE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQzZELEtBQUs7RUFDbkM7SUFBRUM7RUFBTSxDQUFDLEdBQUc5RCxPQUFPLENBQUMsU0FBUyxDQUFDO0VBQzlCK0QsSUFBSSxHQUFHL0QsT0FBTyxDQUFDLE1BQU0sQ0FBQztFQUN0QmdFLEVBQUUsR0FBR2hFLE9BQU8sQ0FBQyxJQUFJLENBQUM7QUF5Q3BCO0FBQ0FpRSxhQUFhLENBQUMsQ0FBQzs7QUFFZjtBQUNBLE1BQU1DLFdBQVcsR0FBRyxJQUFJQyxzQkFBVyxDQUFDLENBQUM7O0FBRXJDO0FBQ0E7QUFDQSxNQUFNQyxXQUFXLENBQUM7RUFNaEI7QUFDRjtBQUNBO0FBQ0E7RUFDRUMsV0FBV0EsQ0FBQ0MsT0FBMkIsRUFBRTtJQUN2QztJQUNBQyxtQkFBVSxDQUFDQyxzQkFBc0IsQ0FBQ0YsT0FBTyxDQUFDO0lBRTFDLE1BQU1HLFVBQVUsR0FBR0MsSUFBSSxDQUFDWixLQUFLLENBQUNZLElBQUksQ0FBQ0MsU0FBUyxDQUFDQyxvQkFBa0IsQ0FBQyxDQUFDO0lBRWpFLFNBQVNDLGNBQWNBLENBQUNDLElBQUksRUFBRTtNQUM1QixNQUFNQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO01BQ2pCLEtBQUssTUFBTUMsR0FBRyxJQUFJRixJQUFJLEVBQUU7UUFDdEIsSUFBSXZCLE1BQU0sQ0FBQzBCLFNBQVMsQ0FBQzVCLGNBQWMsQ0FBQ0MsSUFBSSxDQUFDd0IsSUFBSSxDQUFDRSxHQUFHLENBQUMsRUFBRSxNQUFNLENBQUMsRUFBRTtVQUMzRCxJQUFJRixJQUFJLENBQUNFLEdBQUcsQ0FBQyxDQUFDRSxJQUFJLENBQUNDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUNqQ0osTUFBTSxDQUFDQyxHQUFHLENBQUMsR0FBRyxDQUFDSCxjQUFjLENBQUNKLFVBQVUsQ0FBQ0ssSUFBSSxDQUFDRSxHQUFHLENBQUMsQ0FBQ0UsSUFBSSxDQUFDRSxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1VBQ3pFLENBQUMsTUFBTTtZQUNMTCxNQUFNLENBQUNDLEdBQUcsQ0FBQyxHQUFHSCxjQUFjLENBQUNKLFVBQVUsQ0FBQ0ssSUFBSSxDQUFDRSxHQUFHLENBQUMsQ0FBQ0UsSUFBSSxDQUFDLENBQUM7VUFDMUQ7UUFDRixDQUFDLE1BQU07VUFDTEgsTUFBTSxDQUFDQyxHQUFHLENBQUMsR0FBRyxFQUFFO1FBQ2xCO01BQ0Y7TUFDQSxPQUFPRCxNQUFNO0lBQ2Y7SUFFQSxNQUFNTSxnQkFBZ0IsR0FBR1IsY0FBYyxDQUFDSixVQUFVLENBQUMsb0JBQW9CLENBQUMsQ0FBQztJQUV6RSxTQUFTYSxnQkFBZ0JBLENBQUNDLFFBQVEsRUFBRUMsR0FBRyxFQUFFQyxJQUFJLEdBQUcsRUFBRSxFQUFFO01BQ2xELElBQUlWLE1BQU0sR0FBRyxFQUFFO01BQ2YsTUFBTVcsTUFBTSxHQUFHRCxJQUFJLElBQUlBLElBQUksS0FBSyxFQUFFLEdBQUcsR0FBRyxHQUFHLEVBQUUsQ0FBQztNQUM5QyxLQUFLLE1BQU1ULEdBQUcsSUFBSU8sUUFBUSxFQUFFO1FBQzFCLElBQUksQ0FBQ2hDLE1BQU0sQ0FBQzBCLFNBQVMsQ0FBQzVCLGNBQWMsQ0FBQ0MsSUFBSSxDQUFDa0MsR0FBRyxFQUFFUixHQUFHLENBQUMsRUFBRTtVQUNuREQsTUFBTSxDQUFDWSxJQUFJLENBQUNELE1BQU0sR0FBR1YsR0FBRyxDQUFDO1FBQzNCLENBQUMsTUFBTTtVQUNMLElBQUlRLEdBQUcsQ0FBQ1IsR0FBRyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQUU7VUFBVTtVQUNqQyxJQUFJWSxHQUFHLEdBQUcsRUFBRTtVQUNaLElBQUlDLEtBQUssQ0FBQ0MsT0FBTyxDQUFDUCxRQUFRLENBQUNQLEdBQUcsQ0FBQyxDQUFDLElBQUlhLEtBQUssQ0FBQ0MsT0FBTyxDQUFDTixHQUFHLENBQUNSLEdBQUcsQ0FBQyxDQUFDLEVBQUU7WUFDM0QsTUFBTUUsSUFBSSxHQUFHTSxHQUFHLENBQUNSLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN4Qk8sUUFBUSxDQUFDUCxHQUFHLENBQUMsQ0FBQ2UsT0FBTyxDQUFDLENBQUNDLElBQUksRUFBRUMsR0FBRyxLQUFLO2NBQ25DLElBQUksT0FBT0QsSUFBSSxLQUFLLFFBQVEsSUFBSUEsSUFBSSxLQUFLLElBQUksRUFBRTtnQkFDN0NKLEdBQUcsR0FBR0EsR0FBRyxDQUFDTSxNQUFNLENBQUNaLGdCQUFnQixDQUFDVSxJQUFJLEVBQUVkLElBQUksRUFBRVEsTUFBTSxHQUFHVixHQUFHLEdBQUcsSUFBSWlCLEdBQUcsR0FBRyxDQUFDLENBQUM7Y0FDM0U7WUFDRixDQUFDLENBQUM7VUFDSixDQUFDLE1BQU0sSUFBSSxPQUFPVixRQUFRLENBQUNQLEdBQUcsQ0FBQyxLQUFLLFFBQVEsSUFBSSxPQUFPUSxHQUFHLENBQUNSLEdBQUcsQ0FBQyxLQUFLLFFBQVEsRUFBRTtZQUM1RVksR0FBRyxHQUFHTixnQkFBZ0IsQ0FBQ0MsUUFBUSxDQUFDUCxHQUFHLENBQUMsRUFBRVEsR0FBRyxDQUFDUixHQUFHLENBQUMsRUFBRVUsTUFBTSxHQUFHVixHQUFHLENBQUM7VUFDL0Q7VUFDQUQsTUFBTSxHQUFHQSxNQUFNLENBQUNtQixNQUFNLENBQUNOLEdBQUcsQ0FBQztRQUM3QjtNQUNGO01BQ0EsT0FBT2IsTUFBTTtJQUNmO0lBRUEsTUFBTW9CLElBQUksR0FBR2IsZ0JBQWdCLENBQUNoQixPQUFPLEVBQUVlLGdCQUFnQixDQUFDO0lBQ3hELElBQUljLElBQUksQ0FBQ0MsTUFBTSxHQUFHLENBQUMsRUFBRTtNQUNuQixNQUFNQyxNQUFNLEdBQUlsRyxPQUFPLENBQVNrRyxNQUFNO01BQ3RDQSxNQUFNLENBQUNDLEtBQUssQ0FBQyx1REFBdURILElBQUksQ0FBQ0ksSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7SUFDeEY7O0lBRUE7SUFDQUMsY0FBYyxDQUFDbEMsT0FBTyxDQUFDO0lBQ3ZCLE1BQU07TUFDSm1DLEtBQUssR0FBRyxJQUFBQywwQkFBaUIsRUFBQyw0QkFBNEIsQ0FBQztNQUN2REMsU0FBUyxHQUFHLElBQUFELDBCQUFpQixFQUFDLCtCQUErQixDQUFDO01BQzlERSxhQUFhO01BQ2JDLFNBQVMsR0FBRyxJQUFBSCwwQkFBaUIsRUFBQywrQkFBK0I7SUFDL0QsQ0FBQyxHQUFHcEMsT0FBTztJQUNYO0lBQ0FULEtBQUssQ0FBQ2lELFVBQVUsQ0FBQ0wsS0FBSyxFQUFFRyxhQUFhLElBQUksUUFBUSxFQUFFRCxTQUFTLENBQUM7SUFDN0Q5QyxLQUFLLENBQUNnRCxTQUFTLEdBQUdBLFNBQVM7SUFDM0JFLGVBQU0sQ0FBQ0MsZUFBZSxDQUFDMUMsT0FBTyxDQUFDO0lBQy9CLE1BQU0yQyxjQUFjLEdBQUdsRixXQUFXLENBQUNtRixjQUFjLENBQUM1QyxPQUFPLENBQUM7SUFFekRBLE9BQU8sQ0FBUzZDLEtBQUssR0FBRyxhQUFhO0lBQ3RDLElBQUksQ0FBQ0MsTUFBTSxHQUFHTCxlQUFNLENBQUNNLEdBQUcsQ0FBQzlELE1BQU0sQ0FBQytELE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRWhELE9BQU8sRUFBRTJDLGNBQWMsQ0FBQyxDQUFDO0lBQ3BFLElBQUksQ0FBQ0csTUFBTSxDQUFDRyxpQkFBaUIsR0FBRyxJQUFJQyxHQUFHLENBQUMsQ0FBQztJQUN6QyxJQUFJLENBQUNKLE1BQU0sQ0FBQ0ssc0JBQXNCLEdBQUcsSUFBSUQsR0FBRyxDQUFDLENBQUM7SUFDOUMsSUFBSSxDQUFDSixNQUFNLENBQUNNLHlCQUF5QixHQUFHLElBQUlGLEdBQUcsQ0FBQyxDQUFDO0lBQ2pELElBQUFHLDJCQUFlLEVBQUNyRCxPQUFPLENBQUNzRCxTQUFTLEVBQUVDLFlBQVksQ0FBQztJQUNoRDFILE9BQU8sQ0FBQzJILFNBQVMsQ0FBQ2IsY0FBYyxDQUFDYyxnQkFBZ0IsQ0FBQztFQUNwRDs7RUFFQTtBQUNGO0FBQ0E7O0VBRUUsTUFBTUMsS0FBS0EsQ0FBQSxFQUFrQjtJQUMzQixJQUFJO01BQ0YsSUFBSSxJQUFJLENBQUNaLE1BQU0sQ0FBQ0QsS0FBSyxLQUFLLElBQUksRUFBRTtRQUM5QixPQUFPLElBQUk7TUFDYjtNQUNBLElBQUksQ0FBQ0MsTUFBTSxDQUFDRCxLQUFLLEdBQUcsVUFBVTtNQUM5QkosZUFBTSxDQUFDTSxHQUFHLENBQUMsSUFBSSxDQUFDRCxNQUFNLENBQUM7TUFDdkIsTUFBTTtRQUNKYSxrQkFBa0I7UUFDbEJDLGVBQWU7UUFDZkMsZUFBZTtRQUNmQyxLQUFLO1FBQ0xDLFFBQVE7UUFDUkMsTUFBTTtRQUNOQztNQUNGLENBQUMsR0FBRyxJQUFJLENBQUNuQixNQUFNO01BQ2YsSUFBSTtRQUNGLE1BQU1hLGtCQUFrQixDQUFDTyxxQkFBcUIsQ0FBQyxDQUFDO01BQ2xELENBQUMsQ0FBQyxPQUFPakcsQ0FBQyxFQUFFO1FBQ1YsSUFBSUEsQ0FBQyxDQUFDa0csSUFBSSxLQUFLNUUsS0FBSyxDQUFDNkUsS0FBSyxDQUFDQyxlQUFlLEVBQUU7VUFDMUMsTUFBTXBHLENBQUM7UUFDVDtNQUNGO01BQ0EsTUFBTXFHLGNBQWMsR0FBRyxNQUFNN0csV0FBVyxDQUFDOEcsaUJBQWlCLENBQUMsSUFBSSxDQUFDekIsTUFBTSxDQUFDO01BQ3ZFLE1BQU1jLGVBQWUsQ0FBQ1ksSUFBSSxDQUFDLENBQUM7TUFDNUIsTUFBTUMsZUFBZSxHQUFHLENBQUMsSUFBSSxDQUFDM0IsTUFBTSxDQUFDNEIsYUFBYSxHQUFHLENBQUMsQ0FBQztNQUN2RCxJQUFJVixNQUFNLEVBQUU7UUFDVlMsZUFBZSxDQUFDcEQsSUFBSSxDQUFDLElBQUlzRCw4QkFBYyxDQUFDWCxNQUFNLEVBQUUsSUFBSSxDQUFDbEIsTUFBTSxDQUFDLENBQUM4QixPQUFPLENBQUMsQ0FBQyxDQUFDO01BQ3pFO01BQ0EsSUFDRWYsZUFBZSxDQUFDZ0IsT0FBTyxFQUFFQyxPQUFPLElBQ2hDLE9BQU9qQixlQUFlLENBQUNnQixPQUFPLENBQUNDLE9BQU8sS0FBSyxVQUFVLEVBQ3JEO1FBQ0FMLGVBQWUsQ0FBQ3BELElBQUksQ0FBQ3dDLGVBQWUsQ0FBQ2dCLE9BQU8sQ0FBQ0MsT0FBTyxDQUFDLENBQUMsQ0FBQztNQUN6RDtNQUNBTCxlQUFlLENBQUNwRCxJQUFJLENBQUM0QyxtQkFBbUIsQ0FBQ2EsT0FBTyxDQUFDLENBQUMsQ0FBQztNQUNuRCxNQUFNQyxPQUFPLENBQUNDLEdBQUcsQ0FBQ1AsZUFBZSxDQUFDO01BQ2xDLElBQUlYLEtBQUssRUFBRTtRQUNUbkUsYUFBYSxDQUFDLENBQUM7UUFDZixJQUFJLE9BQU9tRSxLQUFLLEtBQUssVUFBVSxFQUFFO1VBQy9CLE1BQU1pQixPQUFPLENBQUNFLE9BQU8sQ0FBQ25CLEtBQUssQ0FBQ3ZFLEtBQUssQ0FBQyxDQUFDO1FBQ3JDLENBQUMsTUFBTSxJQUFJLE9BQU91RSxLQUFLLEtBQUssUUFBUSxFQUFFO1VBQ3BDLElBQUlvQixJQUFJO1VBQ1IsSUFBSUMsT0FBTyxDQUFDQyxHQUFHLENBQUNDLGdCQUFnQixFQUFFO1lBQ2hDSCxJQUFJLEdBQUd4SixPQUFPLENBQUN5SixPQUFPLENBQUNDLEdBQUcsQ0FBQ0MsZ0JBQWdCLENBQUM7VUFDOUM7VUFDQSxJQUFJRixPQUFPLENBQUNDLEdBQUcsQ0FBQ0UsZ0JBQWdCLEtBQUssUUFBUSxJQUFJSixJQUFJLEVBQUV0RSxJQUFJLEtBQUssUUFBUSxFQUFFO1lBQ3hFLE1BQU0sTUFBTSxDQUFDbkIsSUFBSSxDQUFDd0YsT0FBTyxDQUFDRSxPQUFPLENBQUNJLEdBQUcsQ0FBQyxDQUFDLEVBQUV6QixLQUFLLENBQUMsQ0FBQztVQUNsRCxDQUFDLE1BQU07WUFDTHBJLE9BQU8sQ0FBQytELElBQUksQ0FBQ3dGLE9BQU8sQ0FBQ0UsT0FBTyxDQUFDSSxHQUFHLENBQUMsQ0FBQyxFQUFFekIsS0FBSyxDQUFDLENBQUM7VUFDN0M7UUFDRixDQUFDLE1BQU07VUFDTCxNQUFNLHdEQUF3RDtRQUNoRTtRQUNBLE1BQU0sSUFBSWlCLE9BQU8sQ0FBQ0UsT0FBTyxJQUFJTyxVQUFVLENBQUNQLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztNQUN2RDtNQUNBLElBQUlsQixRQUFRLElBQUlBLFFBQVEsQ0FBQzBCLFdBQVcsSUFBSTFCLFFBQVEsQ0FBQzJCLGNBQWMsRUFBRTtRQUMvRCxJQUFJQyxvQkFBVyxDQUFDNUIsUUFBUSxDQUFDLENBQUM2QixHQUFHLENBQUMsQ0FBQztNQUNqQztNQUNBLElBQUksQ0FBQzlDLE1BQU0sQ0FBQ0QsS0FBSyxHQUFHLElBQUk7TUFDeEIsSUFBSSxDQUFDQyxNQUFNLEdBQUc7UUFBRSxHQUFHLElBQUksQ0FBQ0EsTUFBTTtRQUFFLEdBQUd3QjtNQUFlLENBQUM7TUFDbkQ3QixlQUFNLENBQUNNLEdBQUcsQ0FBQyxJQUFJLENBQUNELE1BQU0sQ0FBQztNQUN2QixPQUFPLElBQUk7SUFDYixDQUFDLENBQUMsT0FBT2QsS0FBSyxFQUFFO01BQ2Q7TUFDQTZELE9BQU8sQ0FBQzdELEtBQUssQ0FBQ0EsS0FBSyxDQUFDO01BQ3BCLElBQUksQ0FBQ2MsTUFBTSxDQUFDRCxLQUFLLEdBQUcsT0FBTztNQUMzQixNQUFNYixLQUFLO0lBQ2I7RUFDRjtFQUVBLElBQUk4RCxHQUFHQSxDQUFBLEVBQUc7SUFDUixJQUFJLENBQUMsSUFBSSxDQUFDQyxJQUFJLEVBQUU7TUFDZCxJQUFJLENBQUNBLElBQUksR0FBR2pHLFdBQVcsQ0FBQ2dHLEdBQUcsQ0FBQyxJQUFJLENBQUNoRCxNQUFNLENBQUM7SUFDMUM7SUFDQSxPQUFPLElBQUksQ0FBQ2lELElBQUk7RUFDbEI7O0VBRUE7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0UsTUFBTUMsY0FBY0EsQ0FBQSxFQUFHO0lBQ3JCLE1BQU1DLGtCQUFrQixHQUFHLElBQUFDLDJCQUFnQixFQUFDLENBQUM7SUFDN0MsTUFBTUMsMkJBQTJCLEdBQUcsSUFBQUQsMkJBQWdCLEVBQUMsQ0FBQztJQUN0RCxNQUFNRSxRQUFRLEdBQUcsRUFBRTtJQUNuQixJQUFJLENBQUNDLE1BQU0sQ0FBQ0MsS0FBSyxDQUFFdEUsS0FBSyxJQUFLO01BQzNCO01BQ0EsSUFBSUEsS0FBSyxFQUFFO1FBQ1Q7UUFDQTZELE9BQU8sQ0FBQzdELEtBQUssQ0FBQyxrQ0FBa0MsRUFBRUEsS0FBSyxDQUFDO01BQzFEO01BQ0FpRSxrQkFBa0IsQ0FBQ2hCLE9BQU8sQ0FBQyxDQUFDO0lBQzlCLENBQUMsQ0FBQztJQUNGLElBQUksSUFBSSxDQUFDc0IsZUFBZSxFQUFFRixNQUFNLEVBQUVDLEtBQUssSUFBSSxJQUFJLENBQUNDLGVBQWUsQ0FBQ0YsTUFBTSxLQUFLLElBQUksQ0FBQ0EsTUFBTSxFQUFFO01BQ3RGLElBQUksQ0FBQ0UsZUFBZSxDQUFDRixNQUFNLENBQUNDLEtBQUssQ0FBRXRFLEtBQUssSUFBSztRQUMzQztRQUNBLElBQUlBLEtBQUssRUFBRTtVQUNUO1VBQ0E2RCxPQUFPLENBQUM3RCxLQUFLLENBQUMsdUNBQXVDLEVBQUVBLEtBQUssQ0FBQztRQUMvRDtRQUNBbUUsMkJBQTJCLENBQUNsQixPQUFPLENBQUMsQ0FBQztNQUN2QyxDQUFDLENBQUM7SUFDSixDQUFDLE1BQU07TUFDTGtCLDJCQUEyQixDQUFDbEIsT0FBTyxDQUFDLENBQUM7SUFDdkM7SUFDQSxNQUFNO01BQUVKLE9BQU8sRUFBRTJCO0lBQWdCLENBQUMsR0FBRyxJQUFJLENBQUMxRCxNQUFNLENBQUNhLGtCQUFrQjtJQUNuRSxJQUFJNkMsZUFBZSxJQUFJLE9BQU9BLGVBQWUsQ0FBQ1IsY0FBYyxLQUFLLFVBQVUsRUFBRTtNQUMzRUksUUFBUSxDQUFDL0UsSUFBSSxDQUFDbUYsZUFBZSxDQUFDUixjQUFjLENBQUMsQ0FBQyxDQUFDO0lBQ2pEO0lBQ0EsTUFBTTtNQUFFbkIsT0FBTyxFQUFFNEI7SUFBWSxDQUFDLEdBQUcsSUFBSSxDQUFDM0QsTUFBTSxDQUFDNEQsZUFBZTtJQUM1RCxJQUFJRCxXQUFXLElBQUksT0FBT0EsV0FBVyxDQUFDVCxjQUFjLEtBQUssVUFBVSxFQUFFO01BQ25FSSxRQUFRLENBQUMvRSxJQUFJLENBQUNvRixXQUFXLENBQUNULGNBQWMsQ0FBQyxDQUFDLENBQUM7SUFDN0M7SUFDQSxNQUFNO01BQUVuQixPQUFPLEVBQUU4QjtJQUFhLENBQUMsR0FBRyxJQUFJLENBQUM3RCxNQUFNLENBQUNlLGVBQWU7SUFDN0QsSUFBSThDLFlBQVksSUFBSSxPQUFPQSxZQUFZLENBQUNYLGNBQWMsS0FBSyxVQUFVLEVBQUU7TUFDckVJLFFBQVEsQ0FBQy9FLElBQUksQ0FBQ3NGLFlBQVksQ0FBQ1gsY0FBYyxDQUFDLENBQUMsQ0FBQztJQUM5QztJQUNBLElBQUksSUFBSSxDQUFDTyxlQUFlLEVBQUU7TUFDeEJILFFBQVEsQ0FBQy9FLElBQUksQ0FBQyxJQUFJLENBQUNrRixlQUFlLENBQUNLLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFDaEQ7SUFDQSxNQUFNN0IsT0FBTyxDQUFDQyxHQUFHLENBQUNvQixRQUFRLENBQUM7SUFDM0J4RyxXQUFXLENBQUNpSCxVQUFVLENBQUMsQ0FBQztJQUN4QixNQUFNOUIsT0FBTyxDQUFDQyxHQUFHLENBQUMsQ0FBQ2lCLGtCQUFrQixFQUFFRSwyQkFBMkIsQ0FBQyxDQUFDO0lBQ3BFLElBQUksSUFBSSxDQUFDckQsTUFBTSxDQUFDZ0UsbUJBQW1CLEVBQUU7TUFDbkMsSUFBSSxDQUFDaEUsTUFBTSxDQUFDZ0UsbUJBQW1CLENBQUMsQ0FBQztJQUNuQztFQUNGOztFQUVBO0FBQ0Y7QUFDQTtBQUNBO0VBQ0UsT0FBT0MsNkJBQTZCQSxDQUFDQyxHQUFHLEVBQUVoSCxPQUFPLEVBQUU7SUFDakQsSUFBSUEsT0FBTyxDQUFDaUgsd0JBQXdCLEVBQUU7TUFDcEMsSUFBSSxPQUFPakgsT0FBTyxDQUFDaUgsd0JBQXdCLEtBQUssVUFBVSxFQUFFO1FBQzFELE1BQU0sSUFBSTdDLEtBQUssQ0FBQyw2Q0FBNkMsQ0FBQztNQUNoRTtNQUNBNEMsR0FBRyxDQUFDRSxHQUFHLENBQUNsSCxPQUFPLENBQUNpSCx3QkFBd0IsQ0FBQztJQUMzQztFQUNGO0VBQ0E7QUFDRjtBQUNBO0FBQ0E7RUFDRSxPQUFPbkIsR0FBR0EsQ0FBQzlGLE9BQU8sRUFBRTtJQUNsQixNQUFNO01BQ0ptSCxhQUFhLEdBQUcsTUFBTTtNQUN0QmhGLEtBQUs7TUFDTGlGLFlBQVk7TUFDWkMsS0FBSztNQUNMQyxTQUFTLEdBQUc7SUFDZCxDQUFDLEdBQUd0SCxPQUFPO0lBQ1g7SUFDQTtJQUNBLElBQUlnSCxHQUFHLEdBQUczSCxPQUFPLENBQUMsQ0FBQztJQUNuQjtJQUNBMkgsR0FBRyxDQUFDRSxHQUFHLENBQUM1SCxXQUFXLENBQUNpSSxnQkFBZ0IsQ0FBQ3BGLEtBQUssQ0FBQyxDQUFDO0lBQzVDNkUsR0FBRyxDQUFDRSxHQUFHLENBQUM1SCxXQUFXLENBQUNrSSx1QkFBdUIsQ0FBQztJQUM1Q1IsR0FBRyxDQUFDRSxHQUFHLENBQUM1SCxXQUFXLENBQUNtSSxlQUFlLENBQUN0RixLQUFLLENBQUMsQ0FBQztJQUMzQztJQUNBO0lBQ0E2RSxHQUFHLENBQUNFLEdBQUcsQ0FDTCxHQUFHLEVBQ0gsSUFBSVEsd0JBQVcsQ0FBQyxDQUFDLENBQUNDLGFBQWEsQ0FBQztNQUM5QlIsYUFBYSxFQUFFQTtJQUNqQixDQUFDLENBQ0gsQ0FBQztJQUVESCxHQUFHLENBQUNFLEdBQUcsQ0FBQyxTQUFTLEVBQUU1SCxXQUFXLENBQUNzSSxxQkFBcUIsRUFBRXRJLFdBQVcsQ0FBQ3VJLGlCQUFpQixDQUFDN0gsT0FBTyxDQUFDLENBQUM7SUFFN0ZnSCxHQUFHLENBQUNFLEdBQUcsQ0FDTCxHQUFHLEVBQ0g3SCxPQUFPLENBQUN5SSxVQUFVLENBQUM7TUFBRUMsUUFBUSxFQUFFO0lBQU0sQ0FBQyxDQUFDLEVBQ3ZDLElBQUlDLHdCQUFXLENBQUNYLEtBQUssQ0FBQyxDQUFDTSxhQUFhLENBQUMsQ0FDdkMsQ0FBQztJQUVEWCxHQUFHLENBQUNFLEdBQUcsQ0FBQzdILE9BQU8sQ0FBQzZGLElBQUksQ0FBQztNQUFFdEUsSUFBSSxFQUFFcUgsR0FBRyxJQUFJLENBQUNBLEdBQUcsQ0FBQ0MsRUFBRSxDQUFDLHFCQUFxQixDQUFDO01BQUVDLEtBQUssRUFBRWhCO0lBQWMsQ0FBQyxDQUFDLENBQUM7SUFDNUZILEdBQUcsQ0FBQ0UsR0FBRyxDQUFDNUgsV0FBVyxDQUFDOEksbUJBQW1CLENBQUM7SUFDeENwQixHQUFHLENBQUNFLEdBQUcsQ0FBQzVILFdBQVcsQ0FBQytJLGtCQUFrQixDQUFDO0lBQ3ZDckIsR0FBRyxDQUFDRSxHQUFHLENBQUM1SCxXQUFXLENBQUNzSSxxQkFBcUIsQ0FBQztJQUMxQ1osR0FBRyxDQUFDbEksR0FBRyxDQUFDLGNBQWMsRUFBRSxVQUFVLENBQUM7SUFDbkMsTUFBTXdKLE1BQU0sR0FBRy9HLEtBQUssQ0FBQ0MsT0FBTyxDQUFDOEYsU0FBUyxDQUFDLEdBQUdBLFNBQVMsR0FBRyxDQUFDQSxTQUFTLENBQUM7SUFDakUsS0FBSyxNQUFNaUIsS0FBSyxJQUFJRCxNQUFNLEVBQUU7TUFDMUJoSixXQUFXLENBQUNrSixZQUFZLENBQUNELEtBQUssRUFBRXZJLE9BQU8sQ0FBQztJQUMxQztJQUNBZ0gsR0FBRyxDQUFDRSxHQUFHLENBQUM1SCxXQUFXLENBQUNtSixrQkFBa0IsQ0FBQztJQUN2QyxJQUFJLENBQUMxQiw2QkFBNkIsQ0FBQ0MsR0FBRyxFQUFFaEgsT0FBTyxDQUFDO0lBQ2hELE1BQU0wSSxTQUFTLEdBQUc1SSxXQUFXLENBQUM2SSxhQUFhLENBQUM7TUFBRXhHLEtBQUs7TUFBRW5DO0lBQVEsQ0FBQyxDQUFDO0lBQy9EZ0gsR0FBRyxDQUFDRSxHQUFHLENBQUN3QixTQUFTLENBQUNmLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFFbENYLEdBQUcsQ0FBQ0UsR0FBRyxDQUFDNUgsV0FBVyxDQUFDc0osaUJBQWlCLENBQUM7O0lBRXRDO0lBQ0EsSUFBSSxDQUFDekQsT0FBTyxDQUFDQyxHQUFHLENBQUN5RCxPQUFPLEVBQUU7TUFDeEI7TUFDQTtNQUNBMUQsT0FBTyxDQUFDMkQsRUFBRSxDQUFDLG1CQUFtQixFQUFHQyxHQUFRLElBQUs7UUFDNUMsSUFBSUEsR0FBRyxDQUFDNUUsSUFBSSxLQUFLLFlBQVksRUFBRTtVQUM3QjtVQUNBZ0IsT0FBTyxDQUFDNkQsTUFBTSxDQUFDQyxLQUFLLENBQUMsNEJBQTRCRixHQUFHLENBQUNHLElBQUksK0JBQStCLENBQUM7VUFDekYvRCxPQUFPLENBQUNnRSxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ2pCLENBQUMsTUFBTTtVQUNMLElBQUlKLEdBQUcsQ0FBQ0ssT0FBTyxFQUFFO1lBQ2ZqRSxPQUFPLENBQUM2RCxNQUFNLENBQUNDLEtBQUssQ0FBQyxrQ0FBa0MsR0FBR0YsR0FBRyxDQUFDSyxPQUFPLENBQUM7VUFDeEU7VUFDQSxJQUFJTCxHQUFHLENBQUNNLEtBQUssRUFBRTtZQUNibEUsT0FBTyxDQUFDNkQsTUFBTSxDQUFDQyxLQUFLLENBQUMsZ0JBQWdCLEdBQUdGLEdBQUcsQ0FBQ00sS0FBSyxDQUFDO1VBQ3BELENBQUMsTUFBTTtZQUNMbEUsT0FBTyxDQUFDNkQsTUFBTSxDQUFDQyxLQUFLLENBQUNGLEdBQUcsQ0FBQztVQUMzQjtVQUNBNUQsT0FBTyxDQUFDZ0UsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNqQjtNQUNGLENBQUMsQ0FBQztJQUNKO0lBQ0EsSUFBSWhFLE9BQU8sQ0FBQ0MsR0FBRyxDQUFDa0UsOENBQThDLEtBQUssR0FBRyxJQUFJbEMsWUFBWSxFQUFFO01BQ3RGN0gsS0FBSyxDQUFDZ0ssV0FBVyxDQUFDQyxpQkFBaUIsQ0FBQyxJQUFBQyxvREFBeUIsRUFBQ3RILEtBQUssRUFBRXVHLFNBQVMsQ0FBQyxDQUFDO0lBQ2xGO0lBQ0EsT0FBTzFCLEdBQUc7RUFDWjtFQUVBLE9BQU8yQixhQUFhQSxDQUFDO0lBQUV4RyxLQUFLO0lBQUVuQztFQUFRLENBQUMsRUFBRTtJQUN2QyxNQUFNMEosT0FBTyxHQUFHLENBQ2QsSUFBSUMsNEJBQWEsQ0FBQyxDQUFDLEVBQ25CLElBQUlDLHdCQUFXLENBQUMsQ0FBQyxFQUNqQixJQUFJQyw4QkFBYyxDQUFDLENBQUMsRUFDcEIsSUFBSUMsd0JBQVcsQ0FBQyxDQUFDLEVBQ2pCLElBQUlDLGdDQUFlLENBQUMsQ0FBQyxFQUNyQixJQUFJQyx3Q0FBbUIsQ0FBQyxDQUFDLEVBQ3pCLElBQUlDLGdDQUFlLENBQUMsQ0FBQyxFQUNyQixJQUFJQyw0QkFBYSxDQUFDLENBQUMsRUFDbkIsSUFBSUMsc0JBQVUsQ0FBQyxDQUFDLEVBQ2hCLElBQUlDLHNCQUFVLENBQUMsQ0FBQyxFQUNoQixJQUFJQyw4QkFBYyxDQUFDLENBQUMsRUFDcEIsSUFBSUMsc0NBQWtCLENBQUMsQ0FBQyxFQUN4QixJQUFJQyw0QkFBYSxDQUFDLENBQUMsRUFDbkIsSUFBSUMsd0JBQVcsQ0FBQyxDQUFDLEVBQ2pCLElBQUlDLHdCQUFXLENBQUMsQ0FBQyxFQUNqQixJQUFJQyxnQ0FBZSxDQUFDLENBQUMsRUFDckIsSUFBSUMsZ0NBQWUsQ0FBQyxDQUFDLEVBQ3JCLElBQUlDLGdDQUFlLENBQUMsQ0FBQyxFQUNyQixJQUFJQyw4QkFBYyxDQUFDLENBQUMsQ0FDckI7SUFFRCxJQUFJN0ssT0FBTyxFQUFFOEssOEJBQThCLEtBQUssS0FBSyxFQUFFO01BQ3JEcEIsT0FBTyxDQUFDckksSUFBSSxDQUFDLElBQUkwSix3Q0FBbUIsQ0FBQyxDQUFDLENBQUM7SUFDekM7SUFFQSxNQUFNekMsTUFBTSxHQUFHb0IsT0FBTyxDQUFDc0IsTUFBTSxDQUFDLENBQUNDLElBQUksRUFBRUMsTUFBTSxLQUFLO01BQzlDLE9BQU9ELElBQUksQ0FBQ3JKLE1BQU0sQ0FBQ3NKLE1BQU0sQ0FBQzVDLE1BQU0sQ0FBQztJQUNuQyxDQUFDLEVBQUUsRUFBRSxDQUFDO0lBRU4sTUFBTUksU0FBUyxHQUFHLElBQUl5QyxzQkFBYSxDQUFDN0MsTUFBTSxFQUFFbkcsS0FBSyxDQUFDO0lBRWxEL0MsS0FBSyxDQUFDZ00sU0FBUyxDQUFDMUMsU0FBUyxDQUFDO0lBQzFCLE9BQU9BLFNBQVM7RUFDbEI7O0VBRUE7QUFDRjtBQUNBO0FBQ0E7QUFDQTs7RUFFRSxNQUFNMkMsUUFBUUEsQ0FBQ3JMLE9BQTJCLEVBQUU7SUFDMUMsSUFBSTtNQUNGLE1BQU0sSUFBSSxDQUFDMEQsS0FBSyxDQUFDLENBQUM7SUFDcEIsQ0FBQyxDQUFDLE9BQU96RixDQUFDLEVBQUU7TUFDVjtNQUNBNEgsT0FBTyxDQUFDN0QsS0FBSyxDQUFDLGlDQUFpQyxFQUFFL0QsQ0FBQyxDQUFDO01BQ25ELE1BQU1BLENBQUM7SUFDVDtJQUNBLE1BQU02SCxHQUFHLEdBQUd6RyxPQUFPLENBQUMsQ0FBQztJQUNyQixJQUFJVyxPQUFPLENBQUNzTCxVQUFVLEVBQUU7TUFDdEIsSUFBSUEsVUFBVTtNQUNkLElBQUksT0FBT3RMLE9BQU8sQ0FBQ3NMLFVBQVUsSUFBSSxRQUFRLEVBQUU7UUFDekNBLFVBQVUsR0FBRzVQLE9BQU8sQ0FBQytELElBQUksQ0FBQ3dGLE9BQU8sQ0FBQ0UsT0FBTyxDQUFDSSxHQUFHLENBQUMsQ0FBQyxFQUFFdkYsT0FBTyxDQUFDc0wsVUFBVSxDQUFDLENBQUM7TUFDdkUsQ0FBQyxNQUFNO1FBQ0xBLFVBQVUsR0FBR3RMLE9BQU8sQ0FBQ3NMLFVBQVUsQ0FBQyxDQUFDO01BQ25DO01BQ0F4RixHQUFHLENBQUNvQixHQUFHLENBQUNvRSxVQUFVLENBQUM7SUFDckI7SUFDQXhGLEdBQUcsQ0FBQ29CLEdBQUcsQ0FBQ2xILE9BQU8sQ0FBQ3VMLFNBQVMsRUFBRSxJQUFJLENBQUN6RixHQUFHLENBQUM7SUFFcEMsSUFBSTlGLE9BQU8sQ0FBQ3dMLFlBQVksS0FBSyxJQUFJLElBQUl4TCxPQUFPLENBQUN5TCxlQUFlLEtBQUssSUFBSSxFQUFFO01BQ3JFLElBQUlDLHFCQUFxQixHQUFHQyxTQUFTO01BQ3JDLElBQUksT0FBTzNMLE9BQU8sQ0FBQzRMLGFBQWEsS0FBSyxRQUFRLEVBQUU7UUFDN0NGLHFCQUFxQixHQUFHbE0sS0FBSyxDQUFDRSxFQUFFLENBQUNtTSxZQUFZLENBQUM3TCxPQUFPLENBQUM0TCxhQUFhLEVBQUUsTUFBTSxDQUFDLENBQUM7TUFDL0UsQ0FBQyxNQUFNLElBQ0wsT0FBTzVMLE9BQU8sQ0FBQzRMLGFBQWEsS0FBSyxRQUFRLElBQ3pDLE9BQU81TCxPQUFPLENBQUM0TCxhQUFhLEtBQUssVUFBVSxFQUMzQztRQUNBRixxQkFBcUIsR0FBRzFMLE9BQU8sQ0FBQzRMLGFBQWE7TUFDL0M7TUFFQSxNQUFNRSxrQkFBa0IsR0FBRyxJQUFJQyxzQ0FBa0IsQ0FBQyxJQUFJLEVBQUU7UUFDdERDLFdBQVcsRUFBRWhNLE9BQU8sQ0FBQ2dNLFdBQVc7UUFDaENDLGNBQWMsRUFBRWpNLE9BQU8sQ0FBQ2lNLGNBQWM7UUFDdENQO01BQ0YsQ0FBQyxDQUFDO01BRUYsSUFBSTFMLE9BQU8sQ0FBQ3dMLFlBQVksRUFBRTtRQUN4Qk0sa0JBQWtCLENBQUNJLFlBQVksQ0FBQ3BHLEdBQUcsQ0FBQztNQUN0QztNQUVBLElBQUk5RixPQUFPLENBQUN5TCxlQUFlLEVBQUU7UUFDM0JLLGtCQUFrQixDQUFDSyxlQUFlLENBQUNyRyxHQUFHLENBQUM7UUFDdkNqSyxPQUFPLENBQUN1USxTQUFTLENBQUMsQ0FBQyxDQUFDQyxJQUFJLENBQ3RCLCtOQUNGLENBQUM7TUFDSDtJQUNGO0lBQ0EsTUFBTWhHLE1BQU0sR0FBRyxNQUFNLElBQUl0QixPQUFPLENBQUNFLE9BQU8sSUFBSTtNQUMxQ2EsR0FBRyxDQUFDd0csTUFBTSxDQUFDdE0sT0FBTyxDQUFDa0osSUFBSSxFQUFFbEosT0FBTyxDQUFDdU0sSUFBSSxFQUFFLFlBQVk7UUFDakR0SCxPQUFPLENBQUMsSUFBSSxDQUFDO01BQ2YsQ0FBQyxDQUFDO0lBQ0osQ0FBQyxDQUFDO0lBQ0YsSUFBSSxDQUFDb0IsTUFBTSxHQUFHQSxNQUFNO0lBQ3BCekcsV0FBVyxDQUFDNE0sS0FBSyxDQUFDbkcsTUFBTSxDQUFDO0lBRXpCLElBQUlyRyxPQUFPLENBQUN5TSxvQkFBb0IsSUFBSXpNLE9BQU8sQ0FBQzBNLHNCQUFzQixFQUFFO01BQ2xFLElBQUksQ0FBQ25HLGVBQWUsR0FBRyxNQUFNekcsV0FBVyxDQUFDNk0scUJBQXFCLENBQzVEdEcsTUFBTSxFQUNOckcsT0FBTyxDQUFDME0sc0JBQXNCLEVBQzlCMU0sT0FDRixDQUFDO01BQ0QsSUFBSSxJQUFJLENBQUN1RyxlQUFlLENBQUNGLE1BQU0sS0FBSyxJQUFJLENBQUNBLE1BQU0sRUFBRTtRQUMvQ3pHLFdBQVcsQ0FBQzRNLEtBQUssQ0FBQyxJQUFJLENBQUNqRyxlQUFlLENBQUNGLE1BQU0sQ0FBQztNQUNoRDtJQUNGO0lBQ0EsSUFBSXJHLE9BQU8sQ0FBQzRNLFVBQVUsRUFBRTtNQUN0QjlHLEdBQUcsQ0FBQ2hILEdBQUcsQ0FBQyxhQUFhLEVBQUVrQixPQUFPLENBQUM0TSxVQUFVLENBQUM7SUFDNUM7SUFDQTtJQUNBLElBQUksQ0FBQ3pILE9BQU8sQ0FBQ0MsR0FBRyxDQUFDeUQsT0FBTyxFQUFFO01BQ3hCZ0Usa0JBQWtCLENBQUMsSUFBSSxDQUFDO01BQ3hCLElBQUk3TSxPQUFPLENBQUM4TSxlQUFlLEtBQUssS0FBSyxFQUFFO1FBQ3JDLE1BQU1oTixXQUFXLENBQUNnTixlQUFlLENBQUMsQ0FBQztNQUNyQztJQUNGO0lBQ0EsSUFBSSxDQUFDQyxVQUFVLEdBQUdqSCxHQUFHO0lBQ3JCLE9BQU8sSUFBSTtFQUNiOztFQUVBO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7RUFDRSxhQUFhdUYsUUFBUUEsQ0FBQ3JMLE9BQTJCLEVBQUU7SUFDakQsTUFBTWdOLFdBQVcsR0FBRyxJQUFJbE4sV0FBVyxDQUFDRSxPQUFPLENBQUM7SUFDNUMsT0FBT2dOLFdBQVcsQ0FBQzNCLFFBQVEsQ0FBQ3JMLE9BQU8sQ0FBQztFQUN0Qzs7RUFFQTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0UsYUFBYTJNLHFCQUFxQkEsQ0FDaENNLFVBQVUsRUFDVm5LLE1BQThCLEVBQzlCOUMsT0FBMkIsRUFDSTtJQUMvQixJQUFJLENBQUNpTixVQUFVLElBQUtuSyxNQUFNLElBQUlBLE1BQU0sQ0FBQ29HLElBQUssRUFBRTtNQUMxQyxJQUFJcEQsR0FBRyxHQUFHekcsT0FBTyxDQUFDLENBQUM7TUFDbkI0TixVQUFVLEdBQUd2UixPQUFPLENBQUMsTUFBTSxDQUFDLENBQUN3UixZQUFZLENBQUNwSCxHQUFHLENBQUM7TUFDOUNtSCxVQUFVLENBQUNYLE1BQU0sQ0FBQ3hKLE1BQU0sQ0FBQ29HLElBQUksQ0FBQztJQUNoQztJQUNBLE1BQU03QyxNQUFNLEdBQUcsSUFBSThHLDBDQUFvQixDQUFDRixVQUFVLEVBQUVuSyxNQUFNLEVBQUU5QyxPQUFPLENBQUM7SUFDcEUsTUFBTXFHLE1BQU0sQ0FBQ3ZCLE9BQU8sQ0FBQyxDQUFDO0lBQ3RCLE9BQU91QixNQUFNO0VBQ2Y7RUFFQSxhQUFheUcsZUFBZUEsQ0FBQSxFQUFHO0lBQzdCO0lBQ0EsSUFBSXZOLEtBQUssQ0FBQ2dELFNBQVMsRUFBRTtNQUNuQixNQUFNNkssY0FBYyxHQUFHQyxNQUFNLElBQUk7UUFDL0IsSUFBSUMsR0FBRztRQUNQLElBQUk7VUFDRkEsR0FBRyxHQUFHLElBQUlDLEdBQUcsQ0FBQ0YsTUFBTSxDQUFDO1FBQ3ZCLENBQUMsQ0FBQyxNQUFNO1VBQ04sT0FBTyxLQUFLO1FBQ2Q7UUFDQSxPQUFPQyxHQUFHLENBQUNFLFFBQVEsS0FBSyxPQUFPLElBQUlGLEdBQUcsQ0FBQ0UsUUFBUSxLQUFLLFFBQVE7TUFDOUQsQ0FBQztNQUNELE1BQU1GLEdBQUcsR0FBRyxHQUFHL04sS0FBSyxDQUFDZ0QsU0FBUyxDQUFDa0wsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsU0FBUztNQUMxRCxJQUFJLENBQUNMLGNBQWMsQ0FBQ0UsR0FBRyxDQUFDLEVBQUU7UUFDeEI7UUFDQXpILE9BQU8sQ0FBQ3dHLElBQUksQ0FDVixvQ0FBb0M5TSxLQUFLLENBQUNnRCxTQUFTLDBCQUEwQixHQUMzRSwwREFDSixDQUFDO1FBQ0Q7TUFDRjtNQUNBLE1BQU1tTCxPQUFPLEdBQUdoUyxPQUFPLENBQUMsV0FBVyxDQUFDO01BQ3BDLE1BQU1pUyxRQUFRLEdBQUcsTUFBTUQsT0FBTyxDQUFDO1FBQUVKO01BQUksQ0FBQyxDQUFDLENBQUNNLEtBQUssQ0FBQ0QsUUFBUSxJQUFJQSxRQUFRLENBQUM7TUFDbkUsTUFBTXpJLElBQUksR0FBR3lJLFFBQVEsQ0FBQ0UsSUFBSSxJQUFJLElBQUk7TUFDbEMsTUFBTUMsS0FBSyxHQUFHSCxRQUFRLENBQUNJLE9BQU8sR0FBRyxhQUFhLENBQUM7TUFDL0MsSUFBSUQsS0FBSyxFQUFFO1FBQ1QsTUFBTSxJQUFJL0ksT0FBTyxDQUFDRSxPQUFPLElBQUlPLFVBQVUsQ0FBQ1AsT0FBTyxFQUFFNkksS0FBSyxHQUFHLElBQUksQ0FBQyxDQUFDO1FBQy9ELE9BQU8sSUFBSSxDQUFDaEIsZUFBZSxDQUFDLENBQUM7TUFDL0I7TUFDQSxJQUFJYSxRQUFRLENBQUNLLE1BQU0sS0FBSyxHQUFHLElBQUk5SSxJQUFJLEVBQUU4SSxNQUFNLEtBQUssSUFBSSxFQUFFO1FBQ3BEO1FBQ0FuSSxPQUFPLENBQUN3RyxJQUFJLENBQ1Ysb0NBQW9DOU0sS0FBSyxDQUFDZ0QsU0FBUyxJQUFJLEdBQ3JELDBEQUNKLENBQUM7UUFDRDtRQUNBO01BQ0Y7TUFDQSxPQUFPLElBQUk7SUFDYjtFQUNGO0FBQ0Y7QUFFQSxTQUFTNUMsYUFBYUEsQ0FBQSxFQUFHO0VBQ3ZCLE1BQU1zTyxVQUFVLEdBQUd2UyxPQUFPLENBQUMsMEJBQTBCLENBQUM7RUFDdEQsTUFBTW9FLFdBQVcsR0FBR3BFLE9BQU8sQ0FBQywyQkFBMkIsQ0FBQztFQUN4RHVELE1BQU0sQ0FBQ0MsY0FBYyxDQUFDSyxLQUFLLEVBQUUsUUFBUSxFQUFFO0lBQ3JDVixHQUFHQSxDQUFBLEVBQUc7TUFDSixNQUFNcVAsSUFBSSxHQUFHekwsZUFBTSxDQUFDNUQsR0FBRyxDQUFDVSxLQUFLLENBQUM0TyxhQUFhLENBQUM7TUFDNUMsT0FBTztRQUFFLEdBQUdELElBQUk7UUFBRSxHQUFHcE87TUFBWSxDQUFDO0lBQ3BDLENBQUM7SUFDRGhCLEdBQUdBLENBQUNzUCxNQUFNLEVBQUU7TUFDVkEsTUFBTSxDQUFDak0sS0FBSyxHQUFHNUMsS0FBSyxDQUFDNE8sYUFBYTtNQUNsQzFMLGVBQU0sQ0FBQ00sR0FBRyxDQUFDcUwsTUFBTSxDQUFDO0lBQ3BCLENBQUM7SUFDREMsWUFBWSxFQUFFO0VBQ2hCLENBQUMsQ0FBQztFQUNGcFAsTUFBTSxDQUFDK0QsTUFBTSxDQUFDekQsS0FBSyxDQUFDK08sS0FBSyxFQUFFTCxVQUFVLENBQUM7RUFDdENNLE1BQU0sQ0FBQ2hQLEtBQUssR0FBR0EsS0FBSztBQUN0QjtBQUVBLFNBQVMyQyxjQUFjQSxDQUFDbEMsT0FBMkIsRUFBRTtFQUNuRGYsTUFBTSxDQUFDdVAsSUFBSSxDQUFDQyxpQkFBUSxDQUFDLENBQUNoTixPQUFPLENBQUNmLEdBQUcsSUFBSTtJQUNuQyxJQUFJLENBQUN6QixNQUFNLENBQUMwQixTQUFTLENBQUM1QixjQUFjLENBQUNDLElBQUksQ0FBQ2dCLE9BQU8sRUFBRVUsR0FBRyxDQUFDLEVBQUU7TUFDdkRWLE9BQU8sQ0FBQ1UsR0FBRyxDQUFDLEdBQUcrTixpQkFBUSxDQUFDL04sR0FBRyxDQUFDO0lBQzlCO0VBQ0YsQ0FBQyxDQUFDOztFQUVGO0VBQ0E7RUFDQTtFQUNBLElBQUksQ0FBQ1YsT0FBTyxDQUFDd0csZUFBZSxFQUFFO0lBQzVCLElBQUl4RyxPQUFPLENBQUMwTyxlQUFlLElBQUksSUFBSSxFQUFFO01BQ25DMU8sT0FBTyxDQUFDME8sZUFBZSxHQUFHLENBQUMsQ0FBQztJQUM5QjtJQUNBLElBQUksT0FBTzFPLE9BQU8sQ0FBQzBPLGVBQWUsS0FBSyxRQUFRLElBQUksQ0FBQ25OLEtBQUssQ0FBQ0MsT0FBTyxDQUFDeEIsT0FBTyxDQUFDME8sZUFBZSxDQUFDLEVBQUU7TUFDMUZ6UCxNQUFNLENBQUN1UCxJQUFJLENBQUNHLGdDQUFzQixDQUFDLENBQUNsTixPQUFPLENBQUNmLEdBQUcsSUFBSTtRQUNqRCxJQUFJLENBQUN6QixNQUFNLENBQUMwQixTQUFTLENBQUM1QixjQUFjLENBQUNDLElBQUksQ0FBQ2dCLE9BQU8sQ0FBQzBPLGVBQWUsRUFBRWhPLEdBQUcsQ0FBQyxFQUFFO1VBQ3ZFVixPQUFPLENBQUMwTyxlQUFlLENBQUNoTyxHQUFHLENBQUMsR0FBR2lPLGdDQUFzQixDQUFDak8sR0FBRyxDQUFDO1FBQzVEO01BQ0YsQ0FBQyxDQUFDO0lBQ0o7RUFDRjtFQUVBLElBQUksQ0FBQ3pCLE1BQU0sQ0FBQzBCLFNBQVMsQ0FBQzVCLGNBQWMsQ0FBQ0MsSUFBSSxDQUFDZ0IsT0FBTyxFQUFFLFdBQVcsQ0FBQyxFQUFFO0lBQy9EQSxPQUFPLENBQUN1QyxTQUFTLEdBQUcsb0JBQW9CdkMsT0FBTyxDQUFDa0osSUFBSSxHQUFHbEosT0FBTyxDQUFDdUwsU0FBUyxFQUFFO0VBQzVFOztFQUVBO0VBQ0EsSUFBSXZMLE9BQU8sQ0FBQ21DLEtBQUssRUFBRTtJQUNqQixNQUFNeU0sS0FBSyxHQUFHLCtCQUErQjtJQUM3QyxJQUFJNU8sT0FBTyxDQUFDbUMsS0FBSyxDQUFDME0sS0FBSyxDQUFDRCxLQUFLLENBQUMsRUFBRTtNQUM5QjtNQUNBL0ksT0FBTyxDQUFDd0csSUFBSSxDQUNWLDZGQUNGLENBQUM7SUFDSDtFQUNGOztFQUVBO0VBQ0EsSUFBSXJNLE9BQU8sQ0FBQzhPLG1CQUFtQixFQUFFO0lBQy9CO0lBQ0EsQ0FBQzNKLE9BQU8sQ0FBQ0MsR0FBRyxDQUFDeUQsT0FBTyxJQUNsQmhELE9BQU8sQ0FBQ3dHLElBQUksQ0FDViwySUFDRixDQUFDO0lBQ0g7O0lBRUEsTUFBTXlDLG1CQUFtQixHQUFHdk4sS0FBSyxDQUFDd04sSUFBSSxDQUNwQyxJQUFJQyxHQUFHLENBQUMsQ0FBQyxJQUFJUCxpQkFBUSxDQUFDSyxtQkFBbUIsSUFBSSxFQUFFLENBQUMsRUFBRSxJQUFJOU8sT0FBTyxDQUFDOE8sbUJBQW1CLElBQUksRUFBRSxDQUFDLENBQUMsQ0FDM0YsQ0FBQzs7SUFFRDtJQUNBO0lBQ0E7SUFDQTtJQUNBLElBQUksRUFBRSxPQUFPLElBQUk5TyxPQUFPLENBQUNpUCxlQUFlLENBQUMsRUFBRTtNQUN6Q2pQLE9BQU8sQ0FBQ2lQLGVBQWUsR0FBR2hRLE1BQU0sQ0FBQytELE1BQU0sQ0FBQztRQUFFa00sS0FBSyxFQUFFO01BQUcsQ0FBQyxFQUFFbFAsT0FBTyxDQUFDaVAsZUFBZSxDQUFDO0lBQ2pGO0lBRUFqUCxPQUFPLENBQUNpUCxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcxTixLQUFLLENBQUN3TixJQUFJLENBQ2hELElBQUlDLEdBQUcsQ0FBQyxDQUFDLElBQUloUCxPQUFPLENBQUNpUCxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsR0FBR0gsbUJBQW1CLENBQUMsQ0FDcEYsQ0FBQztFQUNIOztFQUVBO0VBQ0E3UCxNQUFNLENBQUN1UCxJQUFJLENBQUNDLGlCQUFRLENBQUNRLGVBQWUsQ0FBQyxDQUFDeE4sT0FBTyxDQUFDME4sQ0FBQyxJQUFJO0lBQ2pELE1BQU1DLEdBQUcsR0FBR3BQLE9BQU8sQ0FBQ2lQLGVBQWUsQ0FBQ0UsQ0FBQyxDQUFDO0lBQ3RDLElBQUksQ0FBQ0MsR0FBRyxFQUFFO01BQ1JwUCxPQUFPLENBQUNpUCxlQUFlLENBQUNFLENBQUMsQ0FBQyxHQUFHVixpQkFBUSxDQUFDUSxlQUFlLENBQUNFLENBQUMsQ0FBQztJQUMxRCxDQUFDLE1BQU07TUFDTGxRLE1BQU0sQ0FBQ3VQLElBQUksQ0FBQ0MsaUJBQVEsQ0FBQ1EsZUFBZSxDQUFDRSxDQUFDLENBQUMsQ0FBQyxDQUFDMU4sT0FBTyxDQUFDbkQsQ0FBQyxJQUFJO1FBQ3BELElBQUkwQixPQUFPLENBQUNpUCxlQUFlLENBQUNFLENBQUMsQ0FBQyxDQUFDN1EsQ0FBQyxDQUFDLElBQUkwQixPQUFPLENBQUNxUCwwQkFBMEIsS0FBSyxLQUFLLEVBQUU7VUFDakY7UUFDRjtRQUNBLE1BQU1DLEdBQUcsR0FBRyxJQUFJTixHQUFHLENBQUMsQ0FDbEIsSUFBSWhQLE9BQU8sQ0FBQ2lQLGVBQWUsQ0FBQ0UsQ0FBQyxDQUFDLENBQUM3USxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsRUFDeEMsR0FBR21RLGlCQUFRLENBQUNRLGVBQWUsQ0FBQ0UsQ0FBQyxDQUFDLENBQUM3USxDQUFDLENBQUMsQ0FDbEMsQ0FBQztRQUNGMEIsT0FBTyxDQUFDaVAsZUFBZSxDQUFDRSxDQUFDLENBQUMsQ0FBQzdRLENBQUMsQ0FBQyxHQUFHaUQsS0FBSyxDQUFDd04sSUFBSSxDQUFDTyxHQUFHLENBQUM7TUFDakQsQ0FBQyxDQUFDO0lBQ0o7RUFDRixDQUFDLENBQUM7QUFDSjs7QUFFQTtBQUNBO0FBQ0EsU0FBU3pDLGtCQUFrQkEsQ0FBQ0csV0FBVyxFQUFFO0VBQ3ZDLE1BQU1oSCxjQUFjLEdBQUcsU0FBQUEsQ0FBQSxFQUFZO0lBQ2pDYixPQUFPLENBQUNvSyxNQUFNLENBQUN0RyxLQUFLLENBQUMsNkNBQTZDLENBQUM7SUFDbkUrRCxXQUFXLENBQUNoSCxjQUFjLENBQUMsQ0FBQztFQUM5QixDQUFDO0VBQ0RiLE9BQU8sQ0FBQzJELEVBQUUsQ0FBQyxTQUFTLEVBQUU5QyxjQUFjLENBQUM7RUFDckNiLE9BQU8sQ0FBQzJELEVBQUUsQ0FBQyxRQUFRLEVBQUU5QyxjQUFjLENBQUM7QUFDdEM7QUFBQyxJQUFBd0osUUFBQSxHQUFBQyxPQUFBLENBQUF0UixPQUFBLEdBRWMyQixXQUFXIiwiaWdub3JlTGlzdCI6W119