@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,772 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.RESERVED_DIRECTORY_SEGMENTS = exports.FilesRouter = void 0;
7
+ exports.createSizeLimitedStream = createSizeLimitedStream;
8
+ var _express = _interopRequireDefault(require("express"));
9
+ var Middlewares = _interopRequireWildcard(require("../middlewares"));
10
+ var _node = _interopRequireDefault(require("parse/node"));
11
+ var _Config = _interopRequireDefault(require("../Config"));
12
+ var _logger = _interopRequireDefault(require("../logger"));
13
+ var _stream = require("stream");
14
+ var _Error = require("../Error");
15
+ 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); }
16
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
17
+ const triggers = require('../triggers');
18
+ const Utils = require('../Utils');
19
+ /**
20
+ * Wraps a readable stream in a Readable that enforces a byte size limit.
21
+ * Data flow is lazy: the source is not read until a consumer starts reading
22
+ * from the returned stream (via pipe or 'data' listener). This ensures the
23
+ * consumer's error listener is attached before any data (or error) is emitted.
24
+ */
25
+ function createSizeLimitedStream(source, maxBytes) {
26
+ let totalBytes = 0;
27
+ let started = false;
28
+ let sourceEnded = false;
29
+ let onData, onEnd, onError;
30
+ const output = new _stream.Readable({
31
+ read() {
32
+ if (!started) {
33
+ started = true;
34
+ onData = chunk => {
35
+ totalBytes += chunk.length;
36
+ if (totalBytes > maxBytes) {
37
+ output.destroy(new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, `File size exceeds maximum allowed: ${maxBytes} bytes.`));
38
+ return;
39
+ }
40
+ if (!output.push(chunk)) {
41
+ source.pause();
42
+ }
43
+ };
44
+ onEnd = () => {
45
+ sourceEnded = true;
46
+ output.push(null);
47
+ };
48
+ onError = err => output.destroy(err);
49
+ source.on('data', onData);
50
+ source.on('end', onEnd);
51
+ source.on('error', onError);
52
+ }
53
+
54
+ // Resume source in case it was paused due to backpressure
55
+ if (!sourceEnded) {
56
+ source.resume();
57
+ }
58
+ },
59
+ destroy(err, callback) {
60
+ if (onData) {
61
+ source.removeListener('data', onData);
62
+ }
63
+ if (onEnd) {
64
+ source.removeListener('end', onEnd);
65
+ }
66
+ if (onError) {
67
+ source.removeListener('error', onError);
68
+ }
69
+ // Suppress errors emitted during drain (e.g. client disconnect)
70
+ source.on('error', () => {});
71
+ if (!sourceEnded) {
72
+ source.resume();
73
+ }
74
+ callback(err);
75
+ }
76
+ });
77
+ return output;
78
+ }
79
+
80
+ // Segments that conflict with sub-routes under GET /files/:appId/*. If a file
81
+ // directory starts with one of these, its URL would match the wrong route
82
+ // handler. Update this list when adding new sub-routes to expressRouter().
83
+ const RESERVED_DIRECTORY_SEGMENTS = exports.RESERVED_DIRECTORY_SEGMENTS = ['metadata'];
84
+ class FilesRouter {
85
+ expressRouter({
86
+ maxUploadSize = '20Mb'
87
+ } = {}) {
88
+ var router = _express.default.Router();
89
+ // Lightweight info initializer so handleParseSession can resolve session tokens.
90
+ // Unlike POST/DELETE routes, GET file routes skip handleParseHeaders (which
91
+ // normally sets req.info) because those requests may not carry Parse headers.
92
+ const initInfo = (req, res, next) => {
93
+ if (!req.info) {
94
+ const sessionToken = req.get('X-Parse-Session-Token');
95
+ req.info = {
96
+ sessionToken,
97
+ installationId: req.get('X-Parse-Installation-Id')
98
+ };
99
+ // If no session token and no auth yet (public access), set a minimal
100
+ // auth object so handleParseSession skips session resolution.
101
+ if (!sessionToken && !req.auth) {
102
+ req.auth = {
103
+ isMaster: false
104
+ };
105
+ }
106
+ }
107
+ next();
108
+ };
109
+ // Metadata route must come before the catch-all GET route
110
+ router.get('/files/:appId/metadata/*filepath', initInfo, Middlewares.handleParseSession, this.metadataHandler);
111
+ router.get('/files/:appId/*filepath', initInfo, Middlewares.handleParseSession, this.getHandler);
112
+ router.post('/files', function (req, res, next) {
113
+ next(new _node.default.Error(_node.default.Error.INVALID_FILE_NAME, 'Filename not provided.'));
114
+ });
115
+ router.post('/files/:filename', this._earlyHeadersMiddleware(), this._bodyParsingMiddleware(maxUploadSize), Middlewares.handleParseHeaders, Middlewares.handleParseSession, this.createHandler.bind(this));
116
+ router.delete('/files/*filepath', Middlewares.handleParseHeaders, Middlewares.handleParseSession, Middlewares.enforceMasterKeyAccess, this.deleteHandler);
117
+ return router;
118
+ }
119
+ static _getFilenameFromParams(req) {
120
+ const parts = req.params.filepath;
121
+ return Array.isArray(parts) ? parts.join('/') : parts;
122
+ }
123
+ static validateDirectory(directory) {
124
+ if (typeof directory !== 'string') {
125
+ return new _node.default.Error(_node.default.Error.INVALID_FILE_NAME, 'Directory must be a string.');
126
+ }
127
+ if (directory.length === 0) {
128
+ return new _node.default.Error(_node.default.Error.INVALID_FILE_NAME, 'Directory must not be empty.');
129
+ }
130
+ if (directory.length > 256) {
131
+ return new _node.default.Error(_node.default.Error.INVALID_FILE_NAME, 'Directory path is too long.');
132
+ }
133
+ if (directory.includes('..')) {
134
+ return new _node.default.Error(_node.default.Error.INVALID_FILE_NAME, 'Directory must not contain "..".');
135
+ }
136
+ if (directory.startsWith('/') || directory.endsWith('/')) {
137
+ return new _node.default.Error(_node.default.Error.INVALID_FILE_NAME, 'Directory must not start or end with "/".');
138
+ }
139
+ if (directory.includes('//')) {
140
+ return new _node.default.Error(_node.default.Error.INVALID_FILE_NAME, 'Directory must not contain consecutive slashes.');
141
+ }
142
+ const firstSegment = directory.split('/')[0];
143
+ if (RESERVED_DIRECTORY_SEGMENTS.includes(firstSegment)) {
144
+ return new _node.default.Error(_node.default.Error.INVALID_FILE_NAME, `Directory must not start with reserved segment "${firstSegment}".`);
145
+ }
146
+ const dirRegex = /^[a-zA-Z0-9][a-zA-Z0-9_\-/]*$/;
147
+ if (!dirRegex.test(directory)) {
148
+ return new _node.default.Error(_node.default.Error.INVALID_FILE_NAME, 'Directory contains invalid characters.');
149
+ }
150
+ return null;
151
+ }
152
+ static _validateFileDownload(req, config) {
153
+ const isMaster = req.auth?.isMaster;
154
+ const isMaintenance = req.auth?.isMaintenance;
155
+ if (isMaster || isMaintenance) {
156
+ return;
157
+ }
158
+ const user = req.auth?.user;
159
+ const isLinked = user && _node.default.AnonymousUtils.isLinked(user);
160
+ if (!config.fileDownload.enableForAnonymousUser && isLinked) {
161
+ throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, 'File download by anonymous user is disabled.');
162
+ }
163
+ if (!config.fileDownload.enableForAuthenticatedUser && !isLinked && user) {
164
+ throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, 'File download by authenticated user is disabled.');
165
+ }
166
+ if (!config.fileDownload.enableForPublic && !user) {
167
+ throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, 'File download by public is disabled.');
168
+ }
169
+ }
170
+ async getHandler(req, res) {
171
+ const config = _Config.default.get(req.params.appId);
172
+ if (!config) {
173
+ const error = (0, _Error.createSanitizedHttpError)(403, 'Invalid application ID.', config);
174
+ res.status(error.status);
175
+ res.json({
176
+ error: error.message
177
+ });
178
+ return;
179
+ }
180
+ FilesRouter._validateFileDownload(req, config);
181
+ let filename = FilesRouter._getFilenameFromParams(req);
182
+ try {
183
+ const filesController = config.filesController;
184
+ const mime = (await import('mime')).default;
185
+ let contentType = mime.getType(filename);
186
+ let file = new _node.default.File(filename, {
187
+ base64: ''
188
+ }, contentType);
189
+ const fileAuth = req.auth;
190
+ const triggerResult = await triggers.maybeRunFileTrigger(triggers.Types.beforeFind, {
191
+ file
192
+ }, config, fileAuth);
193
+ if (triggerResult?.file?._name) {
194
+ filename = triggerResult?.file?._name;
195
+ contentType = mime.getType(filename);
196
+ }
197
+ const defaultResponseHeaders = {
198
+ 'X-Content-Type-Options': 'nosniff'
199
+ };
200
+ if (isFileStreamable(req, filesController)) {
201
+ const afterFind = await triggers.maybeRunFileTrigger(triggers.Types.afterFind, {
202
+ file,
203
+ forceDownload: false,
204
+ responseHeaders: {
205
+ ...defaultResponseHeaders
206
+ }
207
+ }, config, fileAuth);
208
+ if (afterFind?.forceDownload) {
209
+ res.set('Content-Disposition', `attachment;filename=${afterFind.file?._name || filename}`);
210
+ }
211
+ for (const [key, value] of Object.entries(afterFind?.responseHeaders ?? defaultResponseHeaders)) {
212
+ res.set(key, value);
213
+ }
214
+ filesController.handleFileStream(config, filename, req, res, contentType).catch(() => {
215
+ res.status(404);
216
+ res.set('Content-Type', 'text/plain');
217
+ res.end('File not found.');
218
+ });
219
+ return;
220
+ }
221
+ let data = await filesController.getFileData(config, filename).catch(() => {
222
+ res.status(404);
223
+ res.set('Content-Type', 'text/plain');
224
+ res.end('File not found.');
225
+ });
226
+ if (!data) {
227
+ return;
228
+ }
229
+ file = new _node.default.File(filename, {
230
+ base64: data.toString('base64')
231
+ }, contentType);
232
+ const afterFind = await triggers.maybeRunFileTrigger(triggers.Types.afterFind, {
233
+ file,
234
+ forceDownload: false,
235
+ responseHeaders: {
236
+ ...defaultResponseHeaders
237
+ }
238
+ }, config, fileAuth);
239
+ if (afterFind?.file) {
240
+ contentType = mime.getType(afterFind.file._name);
241
+ data = Buffer.from(afterFind.file._data, 'base64');
242
+ }
243
+ res.status(200);
244
+ res.set('Content-Type', contentType);
245
+ res.set('Content-Length', data.length);
246
+ if (afterFind.forceDownload) {
247
+ res.set('Content-Disposition', `attachment;filename=${afterFind.file._name}`);
248
+ }
249
+ if (afterFind.responseHeaders) {
250
+ for (const [key, value] of Object.entries(afterFind.responseHeaders)) {
251
+ res.set(key, value);
252
+ }
253
+ }
254
+ res.end(data);
255
+ } catch (e) {
256
+ const err = triggers.resolveError(e, {
257
+ code: _node.default.Error.SCRIPT_FAILED,
258
+ message: `Could not find file: ${filename}.`
259
+ });
260
+ res.status(403);
261
+ res.json({
262
+ code: err.code,
263
+ error: err.message
264
+ });
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Middleware that runs before body parsing to handle headers that must be
270
+ * resolved before the request body is consumed. Currently supports:
271
+ *
272
+ * - `X-Parse-File-Max-Upload-Size`: Overrides the server-wide `maxUploadSize`
273
+ * for this request. Requires the master key. The value uses the same format
274
+ * as the server option (e.g. `'50mb'`, `'1gb'`). Sets `req._maxUploadSizeOverride`
275
+ * (in bytes) for `_bodyParsingMiddleware` to use.
276
+ */
277
+ _earlyHeadersMiddleware() {
278
+ return async (req, res, next) => {
279
+ const maxUploadSizeOverride = req.get('X-Parse-File-Max-Upload-Size');
280
+ if (!maxUploadSizeOverride) {
281
+ return next();
282
+ }
283
+ const appId = req.get('X-Parse-Application-Id');
284
+ const config = _Config.default.get(appId);
285
+ if (!config) {
286
+ const error = (0, _Error.createSanitizedHttpError)(403, 'Invalid application ID.', undefined);
287
+ res.status(error.status);
288
+ res.json({
289
+ error: error.message
290
+ });
291
+ return;
292
+ }
293
+ const masterKey = await config.loadMasterKey();
294
+ if (req.get('X-Parse-Master-Key') !== masterKey) {
295
+ const error = (0, _Error.createSanitizedHttpError)(403, 'unauthorized: master key is required', config);
296
+ res.status(error.status);
297
+ res.json({
298
+ error: error.message
299
+ });
300
+ return;
301
+ }
302
+ if (config.masterKeyIps?.length && !Middlewares.checkIp(req.ip, config.masterKeyIps, config.masterKeyIpsStore)) {
303
+ const error = (0, _Error.createSanitizedHttpError)(403, 'unauthorized: master key is required', config);
304
+ res.status(error.status);
305
+ res.json({
306
+ error: error.message
307
+ });
308
+ return;
309
+ }
310
+ let parsedBytes;
311
+ try {
312
+ parsedBytes = Utils.parseSizeToBytes(maxUploadSizeOverride);
313
+ } catch {
314
+ return next(new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, `Invalid maxUploadSize override value: ${maxUploadSizeOverride}`));
315
+ }
316
+ req._maxUploadSizeOverride = parsedBytes;
317
+ next();
318
+ };
319
+ }
320
+ _bodyParsingMiddleware(maxUploadSize) {
321
+ const defaultMaxBytes = Utils.parseSizeToBytes(maxUploadSize);
322
+ return (req, res, next) => {
323
+ if (req.get('X-Parse-Upload-Mode') === 'stream') {
324
+ req._maxUploadSizeBytes = req._maxUploadSizeOverride ?? defaultMaxBytes;
325
+ return next();
326
+ }
327
+ const limit = req._maxUploadSizeOverride ?? maxUploadSize;
328
+ return _express.default.raw({
329
+ type: () => true,
330
+ limit
331
+ })(req, res, next);
332
+ };
333
+ }
334
+ async createHandler(req, res, next) {
335
+ if (req.auth.isReadOnly) {
336
+ const error = (0, _Error.createSanitizedHttpError)(403, "read-only masterKey isn't allowed to create a file.", req.config);
337
+ res.status(error.status);
338
+ res.end(`{"error":"${error.message}"}`);
339
+ return;
340
+ }
341
+ const config = req.config;
342
+ const isMaster = req.auth.isMaster;
343
+ const isMaintenance = req.auth.isMaintenance;
344
+ if (!isMaster && !isMaintenance) {
345
+ const user = req.auth.user;
346
+ const isLinked = user && _node.default.AnonymousUtils.isLinked(user);
347
+ if (!config.fileUpload.enableForAnonymousUser && isLinked) {
348
+ next(new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, 'File upload by anonymous user is disabled.'));
349
+ return;
350
+ }
351
+ if (!config.fileUpload.enableForAuthenticatedUser && !isLinked && user) {
352
+ next(new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, 'File upload by authenticated user is disabled.'));
353
+ return;
354
+ }
355
+ if (!config.fileUpload.enableForPublic && !user) {
356
+ next(new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, 'File upload by public is disabled.'));
357
+ return;
358
+ }
359
+ }
360
+ const filesController = config.filesController;
361
+ const {
362
+ filename
363
+ } = req.params;
364
+ const contentType = req.get('Content-type');
365
+ const error = filesController.validateFilename(filename);
366
+ if (error) {
367
+ next(error);
368
+ return;
369
+ }
370
+ const fileExtensions = config.fileUpload?.fileExtensions;
371
+ if (!isMaster && fileExtensions) {
372
+ const isValidExtension = extension => {
373
+ return fileExtensions.some(ext => {
374
+ if (ext === '*') {
375
+ return true;
376
+ }
377
+ const regex = new RegExp(ext);
378
+ if (regex.test(extension)) {
379
+ return true;
380
+ }
381
+ });
382
+ };
383
+ let extension = contentType;
384
+ if (filename && filename.includes('.')) {
385
+ extension = filename.substring(filename.lastIndexOf('.') + 1);
386
+ } else if (contentType && contentType.includes('/')) {
387
+ extension = contentType.split('/')[1];
388
+ }
389
+ // Strip MIME parameters (e.g. ";charset=utf-8") and whitespace
390
+ extension = extension?.split(';')[0]?.replace(/\s+/g, '');
391
+ if (extension && !isValidExtension(extension)) {
392
+ next(new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, `File upload of extension ${extension} is disabled.`));
393
+ return;
394
+ }
395
+ }
396
+
397
+ // For streaming uploads, read file data from headers since the body is the raw stream
398
+ if (req.get('X-Parse-Upload-Mode') === 'stream') {
399
+ req.fileData = {};
400
+ if (req.get('X-Parse-File-Directory')) {
401
+ req.fileData.directory = req.get('X-Parse-File-Directory');
402
+ }
403
+ if (req.get('X-Parse-File-Metadata')) {
404
+ try {
405
+ const parsed = JSON.parse(req.get('X-Parse-File-Metadata'));
406
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
407
+ throw new Error();
408
+ }
409
+ req.fileData.metadata = parsed;
410
+ } catch {
411
+ next(new _node.default.Error(_node.default.Error.INVALID_JSON, 'Invalid JSON in X-Parse-File-Metadata header.'));
412
+ return;
413
+ }
414
+ }
415
+ if (req.get('X-Parse-File-Tags')) {
416
+ try {
417
+ const parsed = JSON.parse(req.get('X-Parse-File-Tags'));
418
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
419
+ throw new Error();
420
+ }
421
+ req.fileData.tags = parsed;
422
+ } catch {
423
+ next(new _node.default.Error(_node.default.Error.INVALID_JSON, 'Invalid JSON in X-Parse-File-Tags header.'));
424
+ return;
425
+ }
426
+ }
427
+ }
428
+
429
+ // Validate directory option (requires master key)
430
+ const directory = req.fileData?.directory;
431
+ if (directory !== undefined) {
432
+ if (!isMaster) {
433
+ next(new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, 'Directory can only be set using the Master Key.'));
434
+ return;
435
+ }
436
+ const directoryError = FilesRouter.validateDirectory(directory);
437
+ if (directoryError) {
438
+ next(directoryError);
439
+ return;
440
+ }
441
+ }
442
+
443
+ // Dispatch to the appropriate handler based on whether the body was buffered
444
+ if (Buffer.isBuffer(req.body)) {
445
+ return this._handleBufferedUpload(req, res, next);
446
+ }
447
+ return this._handleStreamUpload(req, res, next);
448
+ }
449
+ async _handleBufferedUpload(req, res, next) {
450
+ const config = req.config;
451
+ const filesController = config.filesController;
452
+ const {
453
+ filename
454
+ } = req.params;
455
+ const contentType = req.get('Content-type');
456
+ if (!req.body || !req.body.length) {
457
+ next(new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, 'Invalid file upload.'));
458
+ return;
459
+ }
460
+ const base64 = req.body.toString('base64');
461
+ const file = new _node.default.File(filename, {
462
+ base64
463
+ }, contentType);
464
+ const {
465
+ metadata = {},
466
+ tags = {},
467
+ directory
468
+ } = req.fileData || {};
469
+ try {
470
+ // Scan request data for denied keywords
471
+ Utils.checkProhibitedKeywords(config, metadata);
472
+ Utils.checkProhibitedKeywords(config, tags);
473
+ } catch (error) {
474
+ next(new _node.default.Error(_node.default.Error.INVALID_KEY_NAME, error));
475
+ return;
476
+ }
477
+ file.setTags(tags);
478
+ file.setMetadata(metadata);
479
+ if (directory) {
480
+ file.setDirectory(directory);
481
+ }
482
+ const fileSize = Buffer.byteLength(req.body);
483
+ const fileObject = {
484
+ file,
485
+ fileSize
486
+ };
487
+ try {
488
+ // run beforeSaveFile trigger
489
+ const triggerResult = await triggers.maybeRunFileTrigger(triggers.Types.beforeSave, fileObject, config, req.auth);
490
+ let saveResult;
491
+ // if a new ParseFile is returned check if it's an already saved file
492
+ if (triggerResult instanceof _node.default.File) {
493
+ fileObject.file = triggerResult;
494
+ if (triggerResult.url()) {
495
+ // set fileSize to null because we wont know how big it is here
496
+ fileObject.fileSize = null;
497
+ saveResult = {
498
+ url: triggerResult.url(),
499
+ name: triggerResult._name
500
+ };
501
+ }
502
+ }
503
+ // if the file returned by the trigger has already been saved skip saving anything
504
+ if (!saveResult) {
505
+ // update fileSize
506
+ let bufferData;
507
+ if (fileObject.file._source?.format === 'buffer') {
508
+ bufferData = fileObject.file._source.buffer;
509
+ } else {
510
+ bufferData = Buffer.from(fileObject.file._data, 'base64');
511
+ }
512
+ fileObject.fileSize = Buffer.byteLength(bufferData);
513
+ // prepare file options
514
+ const fileOptions = {
515
+ metadata: fileObject.file._metadata
516
+ };
517
+ // some s3-compatible providers (DigitalOcean, Linode) do not accept tags
518
+ // so we do not include the tags option if it is empty.
519
+ const fileTags = Object.keys(fileObject.file._tags).length > 0 ? {
520
+ tags: fileObject.file._tags
521
+ } : {};
522
+ Object.assign(fileOptions, fileTags);
523
+ // include directory if set (from client request or beforeSaveFile trigger)
524
+ if (fileObject.file._directory) {
525
+ fileOptions.directory = fileObject.file._directory;
526
+ }
527
+ // save file
528
+ const createFileResult = await filesController.createFile(config, fileObject.file._name, bufferData, fileObject.file._source.type, fileOptions);
529
+ // update file with new data
530
+ fileObject.file._name = createFileResult.name;
531
+ fileObject.file._url = createFileResult.url;
532
+ fileObject.file._requestTask = null;
533
+ fileObject.file._previousSave = Promise.resolve(fileObject.file);
534
+ saveResult = {
535
+ url: createFileResult.url,
536
+ name: createFileResult.name
537
+ };
538
+ }
539
+ // run afterSaveFile trigger
540
+ await triggers.maybeRunFileTrigger(triggers.Types.afterSave, fileObject, config, req.auth);
541
+ res.status(201);
542
+ res.set('Location', saveResult.url);
543
+ res.json(saveResult);
544
+ } catch (e) {
545
+ _logger.default.error('Error creating a file: ', e);
546
+ const error = triggers.resolveError(e, {
547
+ code: _node.default.Error.FILE_SAVE_ERROR,
548
+ message: `Could not store file: ${fileObject.file._name}.`
549
+ });
550
+ next(error);
551
+ }
552
+ }
553
+ async _handleStreamUpload(req, res, next) {
554
+ const config = req.config;
555
+ const filesController = config.filesController;
556
+ const {
557
+ filename
558
+ } = req.params;
559
+ let contentType = req.get('Content-Type');
560
+ const maxBytes = req._maxUploadSizeBytes;
561
+ let stream;
562
+ try {
563
+ // Early rejection via Content-Length header
564
+ const contentLength = req.get('Content-Length');
565
+ if (contentLength && parseInt(contentLength, 10) > maxBytes) {
566
+ req.resume();
567
+ next(new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, `File size exceeds maximum allowed: ${maxBytes} bytes.`));
568
+ return;
569
+ }
570
+ const mime = (await import('mime')).default;
571
+
572
+ // Infer content type from extension or add extension from content type
573
+ const hasExtension = filename && filename.includes('.');
574
+ if (hasExtension && !contentType) {
575
+ contentType = mime.getType(filename);
576
+ } else if (!hasExtension && contentType) {
577
+ // extension will be added by filesController.createFile
578
+ }
579
+
580
+ // Create size-limited stream wrapping the request
581
+ stream = createSizeLimitedStream(req, maxBytes);
582
+
583
+ // Build a Parse.File with no _data (streaming mode)
584
+ const file = new _node.default.File(filename, {
585
+ base64: ''
586
+ }, contentType);
587
+ const {
588
+ metadata = {},
589
+ tags = {},
590
+ directory
591
+ } = req.fileData || {};
592
+
593
+ // Validate metadata and tags for prohibited keywords
594
+ try {
595
+ Utils.checkProhibitedKeywords(config, metadata);
596
+ Utils.checkProhibitedKeywords(config, tags);
597
+ } catch (error) {
598
+ stream.destroy();
599
+ next(new _node.default.Error(_node.default.Error.INVALID_KEY_NAME, error));
600
+ return;
601
+ }
602
+ file.setTags(tags);
603
+ file.setMetadata(metadata);
604
+ if (directory) {
605
+ file.setDirectory(directory);
606
+ }
607
+ const fileSize = req.get('Content-Length') ? parseInt(req.get('Content-Length'), 10) : null;
608
+ const fileObject = {
609
+ file,
610
+ fileSize,
611
+ stream: true
612
+ };
613
+
614
+ // Run beforeSaveFile trigger
615
+ const triggerResult = await triggers.maybeRunFileTrigger(triggers.Types.beforeSave, fileObject, config, req.auth);
616
+ let saveResult;
617
+ // If a new ParseFile is returned, check if it's an already saved file
618
+ if (triggerResult instanceof _node.default.File) {
619
+ fileObject.file = triggerResult;
620
+ if (triggerResult.url()) {
621
+ fileObject.fileSize = null;
622
+ saveResult = {
623
+ url: triggerResult.url(),
624
+ name: triggerResult._name
625
+ };
626
+ // Destroy stream to remove listeners and drain request
627
+ stream.destroy();
628
+ }
629
+ }
630
+
631
+ // If the file returned by the trigger has already been saved, skip saving
632
+ if (!saveResult) {
633
+ // Prepare file options
634
+ const fileOptions = {
635
+ metadata: fileObject.file._metadata
636
+ };
637
+ const fileTags = Object.keys(fileObject.file._tags).length > 0 ? {
638
+ tags: fileObject.file._tags
639
+ } : {};
640
+ Object.assign(fileOptions, fileTags);
641
+ // include directory if set (from client request or beforeSaveFile trigger)
642
+ if (fileObject.file._directory) {
643
+ fileOptions.directory = fileObject.file._directory;
644
+ }
645
+
646
+ // Pass stream directly to filesController — it will buffer if adapter doesn't support streaming
647
+ const sourceType = fileObject.file._source?.type || contentType;
648
+ const createFileResult = await filesController.createFile(config, fileObject.file._name, stream, sourceType, fileOptions);
649
+
650
+ // Update file with new data
651
+ fileObject.file._name = createFileResult.name;
652
+ fileObject.file._url = createFileResult.url;
653
+ fileObject.file._requestTask = null;
654
+ fileObject.file._previousSave = Promise.resolve(fileObject.file);
655
+ saveResult = {
656
+ url: createFileResult.url,
657
+ name: createFileResult.name
658
+ };
659
+ }
660
+
661
+ // Run afterSaveFile trigger
662
+ await triggers.maybeRunFileTrigger(triggers.Types.afterSave, fileObject, config, req.auth);
663
+ res.status(201);
664
+ res.set('Location', saveResult.url);
665
+ res.json(saveResult);
666
+ } catch (e) {
667
+ // Destroy stream to remove listeners and drain request, or resume directly
668
+ if (stream) {
669
+ stream.destroy();
670
+ } else {
671
+ req.resume();
672
+ }
673
+ _logger.default.error('Error creating a file: ', e);
674
+ const error = triggers.resolveError(e, {
675
+ code: _node.default.Error.FILE_SAVE_ERROR,
676
+ message: `Could not store file: ${filename}.`
677
+ });
678
+ next(error);
679
+ }
680
+ }
681
+ async deleteHandler(req, res, next) {
682
+ if (req.auth.isReadOnly) {
683
+ const error = (0, _Error.createSanitizedHttpError)(403, "read-only masterKey isn't allowed to delete a file.", req.config);
684
+ res.status(error.status);
685
+ res.end(`{"error":"${error.message}"}`);
686
+ return;
687
+ }
688
+ try {
689
+ const {
690
+ filesController
691
+ } = req.config;
692
+ const filename = FilesRouter._getFilenameFromParams(req);
693
+ // run beforeDeleteFile trigger
694
+ const file = new _node.default.File(filename);
695
+ file._url = await filesController.adapter.getFileLocation(req.config, filename);
696
+ const fileObject = {
697
+ file,
698
+ fileSize: null
699
+ };
700
+ await triggers.maybeRunFileTrigger(triggers.Types.beforeDelete, fileObject, req.config, req.auth);
701
+ // delete file
702
+ await filesController.deleteFile(req.config, filename);
703
+ // run afterDeleteFile trigger
704
+ await triggers.maybeRunFileTrigger(triggers.Types.afterDelete, fileObject, req.config, req.auth);
705
+ res.status(200);
706
+ // TODO: return useful JSON here?
707
+ res.end();
708
+ } catch (e) {
709
+ _logger.default.error('Error deleting a file: ', e);
710
+ const error = triggers.resolveError(e, {
711
+ code: _node.default.Error.FILE_DELETE_ERROR,
712
+ message: 'Could not delete file.'
713
+ });
714
+ next(error);
715
+ }
716
+ }
717
+ async metadataHandler(req, res) {
718
+ try {
719
+ const config = _Config.default.get(req.params.appId);
720
+ if (!config) {
721
+ res.status(200);
722
+ res.json({});
723
+ return;
724
+ }
725
+ FilesRouter._validateFileDownload(req, config);
726
+ const {
727
+ filesController
728
+ } = config;
729
+ let filename = FilesRouter._getFilenameFromParams(req);
730
+ const file = new _node.default.File(filename, {
731
+ base64: ''
732
+ });
733
+ const fileAuth = req.auth;
734
+ const triggerResult = await triggers.maybeRunFileTrigger(triggers.Types.beforeFind, {
735
+ file
736
+ }, config, fileAuth);
737
+ if (triggerResult?.file?._name) {
738
+ filename = triggerResult.file._name;
739
+ }
740
+ const data = await filesController.getMetadata(filename).catch(() => {
741
+ res.status(200);
742
+ res.json({});
743
+ });
744
+ if (!data) {
745
+ return;
746
+ }
747
+ await triggers.maybeRunFileTrigger(triggers.Types.afterFind, {
748
+ file
749
+ }, config, fileAuth);
750
+ res.status(200);
751
+ res.json(data);
752
+ } catch (e) {
753
+ const err = triggers.resolveError(e, {
754
+ code: _node.default.Error.SCRIPT_FAILED,
755
+ message: 'Could not get file metadata.'
756
+ });
757
+ res.status(403);
758
+ res.json({
759
+ code: err.code,
760
+ error: err.message
761
+ });
762
+ }
763
+ }
764
+ }
765
+ exports.FilesRouter = FilesRouter;
766
+ function isFileStreamable(req, filesController) {
767
+ const range = (req.get('Range') || '/-/').split('-');
768
+ const start = Number(range[0]);
769
+ const end = Number(range[1]);
770
+ return (!isNaN(start) || !isNaN(end)) && typeof filesController.adapter.handleFileStream === 'function';
771
+ }
772
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZXhwcmVzcyIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJyZXF1aXJlIiwiTWlkZGxld2FyZXMiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsIl9ub2RlIiwiX0NvbmZpZyIsIl9sb2dnZXIiLCJfc3RyZWFtIiwiX0Vycm9yIiwiZSIsInQiLCJXZWFrTWFwIiwiciIsIm4iLCJfX2VzTW9kdWxlIiwibyIsImkiLCJmIiwiX19wcm90b19fIiwiZGVmYXVsdCIsImhhcyIsImdldCIsInNldCIsImhhc093blByb3BlcnR5IiwiY2FsbCIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwidHJpZ2dlcnMiLCJVdGlscyIsImNyZWF0ZVNpemVMaW1pdGVkU3RyZWFtIiwic291cmNlIiwibWF4Qnl0ZXMiLCJ0b3RhbEJ5dGVzIiwic3RhcnRlZCIsInNvdXJjZUVuZGVkIiwib25EYXRhIiwib25FbmQiLCJvbkVycm9yIiwib3V0cHV0IiwiUmVhZGFibGUiLCJyZWFkIiwiY2h1bmsiLCJsZW5ndGgiLCJkZXN0cm95IiwiUGFyc2UiLCJFcnJvciIsIkZJTEVfU0FWRV9FUlJPUiIsInB1c2giLCJwYXVzZSIsImVyciIsIm9uIiwicmVzdW1lIiwiY2FsbGJhY2siLCJyZW1vdmVMaXN0ZW5lciIsIlJFU0VSVkVEX0RJUkVDVE9SWV9TRUdNRU5UUyIsImV4cG9ydHMiLCJGaWxlc1JvdXRlciIsImV4cHJlc3NSb3V0ZXIiLCJtYXhVcGxvYWRTaXplIiwicm91dGVyIiwiZXhwcmVzcyIsIlJvdXRlciIsImluaXRJbmZvIiwicmVxIiwicmVzIiwibmV4dCIsImluZm8iLCJzZXNzaW9uVG9rZW4iLCJpbnN0YWxsYXRpb25JZCIsImF1dGgiLCJpc01hc3RlciIsImhhbmRsZVBhcnNlU2Vzc2lvbiIsIm1ldGFkYXRhSGFuZGxlciIsImdldEhhbmRsZXIiLCJwb3N0IiwiSU5WQUxJRF9GSUxFX05BTUUiLCJfZWFybHlIZWFkZXJzTWlkZGxld2FyZSIsIl9ib2R5UGFyc2luZ01pZGRsZXdhcmUiLCJoYW5kbGVQYXJzZUhlYWRlcnMiLCJjcmVhdGVIYW5kbGVyIiwiYmluZCIsImRlbGV0ZSIsImVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MiLCJkZWxldGVIYW5kbGVyIiwiX2dldEZpbGVuYW1lRnJvbVBhcmFtcyIsInBhcnRzIiwicGFyYW1zIiwiZmlsZXBhdGgiLCJBcnJheSIsImlzQXJyYXkiLCJqb2luIiwidmFsaWRhdGVEaXJlY3RvcnkiLCJkaXJlY3RvcnkiLCJpbmNsdWRlcyIsInN0YXJ0c1dpdGgiLCJlbmRzV2l0aCIsImZpcnN0U2VnbWVudCIsInNwbGl0IiwiZGlyUmVnZXgiLCJ0ZXN0IiwiX3ZhbGlkYXRlRmlsZURvd25sb2FkIiwiY29uZmlnIiwiaXNNYWludGVuYW5jZSIsInVzZXIiLCJpc0xpbmtlZCIsIkFub255bW91c1V0aWxzIiwiZmlsZURvd25sb2FkIiwiZW5hYmxlRm9yQW5vbnltb3VzVXNlciIsIk9QRVJBVElPTl9GT1JCSURERU4iLCJlbmFibGVGb3JBdXRoZW50aWNhdGVkVXNlciIsImVuYWJsZUZvclB1YmxpYyIsIkNvbmZpZyIsImFwcElkIiwiZXJyb3IiLCJjcmVhdGVTYW5pdGl6ZWRIdHRwRXJyb3IiLCJzdGF0dXMiLCJqc29uIiwibWVzc2FnZSIsImZpbGVuYW1lIiwiZmlsZXNDb250cm9sbGVyIiwibWltZSIsImNvbnRlbnRUeXBlIiwiZ2V0VHlwZSIsImZpbGUiLCJGaWxlIiwiYmFzZTY0IiwiZmlsZUF1dGgiLCJ0cmlnZ2VyUmVzdWx0IiwibWF5YmVSdW5GaWxlVHJpZ2dlciIsIlR5cGVzIiwiYmVmb3JlRmluZCIsIl9uYW1lIiwiZGVmYXVsdFJlc3BvbnNlSGVhZGVycyIsImlzRmlsZVN0cmVhbWFibGUiLCJhZnRlckZpbmQiLCJmb3JjZURvd25sb2FkIiwicmVzcG9uc2VIZWFkZXJzIiwia2V5IiwidmFsdWUiLCJlbnRyaWVzIiwiaGFuZGxlRmlsZVN0cmVhbSIsImNhdGNoIiwiZW5kIiwiZGF0YSIsImdldEZpbGVEYXRhIiwidG9TdHJpbmciLCJCdWZmZXIiLCJmcm9tIiwiX2RhdGEiLCJyZXNvbHZlRXJyb3IiLCJjb2RlIiwiU0NSSVBUX0ZBSUxFRCIsIm1heFVwbG9hZFNpemVPdmVycmlkZSIsInVuZGVmaW5lZCIsIm1hc3RlcktleSIsImxvYWRNYXN0ZXJLZXkiLCJtYXN0ZXJLZXlJcHMiLCJjaGVja0lwIiwiaXAiLCJtYXN0ZXJLZXlJcHNTdG9yZSIsInBhcnNlZEJ5dGVzIiwicGFyc2VTaXplVG9CeXRlcyIsIl9tYXhVcGxvYWRTaXplT3ZlcnJpZGUiLCJkZWZhdWx0TWF4Qnl0ZXMiLCJfbWF4VXBsb2FkU2l6ZUJ5dGVzIiwibGltaXQiLCJyYXciLCJ0eXBlIiwiaXNSZWFkT25seSIsImZpbGVVcGxvYWQiLCJ2YWxpZGF0ZUZpbGVuYW1lIiwiZmlsZUV4dGVuc2lvbnMiLCJpc1ZhbGlkRXh0ZW5zaW9uIiwiZXh0ZW5zaW9uIiwic29tZSIsImV4dCIsInJlZ2V4IiwiUmVnRXhwIiwic3Vic3RyaW5nIiwibGFzdEluZGV4T2YiLCJyZXBsYWNlIiwiZmlsZURhdGEiLCJwYXJzZWQiLCJKU09OIiwicGFyc2UiLCJtZXRhZGF0YSIsIklOVkFMSURfSlNPTiIsInRhZ3MiLCJkaXJlY3RvcnlFcnJvciIsImlzQnVmZmVyIiwiYm9keSIsIl9oYW5kbGVCdWZmZXJlZFVwbG9hZCIsIl9oYW5kbGVTdHJlYW1VcGxvYWQiLCJjaGVja1Byb2hpYml0ZWRLZXl3b3JkcyIsIklOVkFMSURfS0VZX05BTUUiLCJzZXRUYWdzIiwic2V0TWV0YWRhdGEiLCJzZXREaXJlY3RvcnkiLCJmaWxlU2l6ZSIsImJ5dGVMZW5ndGgiLCJmaWxlT2JqZWN0IiwiYmVmb3JlU2F2ZSIsInNhdmVSZXN1bHQiLCJ1cmwiLCJuYW1lIiwiYnVmZmVyRGF0YSIsIl9zb3VyY2UiLCJmb3JtYXQiLCJidWZmZXIiLCJmaWxlT3B0aW9ucyIsIl9tZXRhZGF0YSIsImZpbGVUYWdzIiwia2V5cyIsIl90YWdzIiwiYXNzaWduIiwiX2RpcmVjdG9yeSIsImNyZWF0ZUZpbGVSZXN1bHQiLCJjcmVhdGVGaWxlIiwiX3VybCIsIl9yZXF1ZXN0VGFzayIsIl9wcmV2aW91c1NhdmUiLCJQcm9taXNlIiwicmVzb2x2ZSIsImFmdGVyU2F2ZSIsImxvZ2dlciIsInN0cmVhbSIsImNvbnRlbnRMZW5ndGgiLCJwYXJzZUludCIsImhhc0V4dGVuc2lvbiIsInNvdXJjZVR5cGUiLCJhZGFwdGVyIiwiZ2V0RmlsZUxvY2F0aW9uIiwiYmVmb3JlRGVsZXRlIiwiZGVsZXRlRmlsZSIsImFmdGVyRGVsZXRlIiwiRklMRV9ERUxFVEVfRVJST1IiLCJnZXRNZXRhZGF0YSIsInJhbmdlIiwic3RhcnQiLCJOdW1iZXIiLCJpc05hTiJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0ZpbGVzUm91dGVyLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBleHByZXNzIGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0ICogYXMgTWlkZGxld2FyZXMgZnJvbSAnLi4vbWlkZGxld2FyZXMnO1xuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IENvbmZpZyBmcm9tICcuLi9Db25maWcnO1xuaW1wb3J0IGxvZ2dlciBmcm9tICcuLi9sb2dnZXInO1xuY29uc3QgdHJpZ2dlcnMgPSByZXF1aXJlKCcuLi90cmlnZ2VycycpO1xuY29uc3QgVXRpbHMgPSByZXF1aXJlKCcuLi9VdGlscycpO1xuaW1wb3J0IHsgUmVhZGFibGUgfSBmcm9tICdzdHJlYW0nO1xuaW1wb3J0IHsgY3JlYXRlU2FuaXRpemVkSHR0cEVycm9yIH0gZnJvbSAnLi4vRXJyb3InO1xuXG4vKipcbiAqIFdyYXBzIGEgcmVhZGFibGUgc3RyZWFtIGluIGEgUmVhZGFibGUgdGhhdCBlbmZvcmNlcyBhIGJ5dGUgc2l6ZSBsaW1pdC5cbiAqIERhdGEgZmxvdyBpcyBsYXp5OiB0aGUgc291cmNlIGlzIG5vdCByZWFkIHVudGlsIGEgY29uc3VtZXIgc3RhcnRzIHJlYWRpbmdcbiAqIGZyb20gdGhlIHJldHVybmVkIHN0cmVhbSAodmlhIHBpcGUgb3IgJ2RhdGEnIGxpc3RlbmVyKS4gVGhpcyBlbnN1cmVzIHRoZVxuICogY29uc3VtZXIncyBlcnJvciBsaXN0ZW5lciBpcyBhdHRhY2hlZCBiZWZvcmUgYW55IGRhdGEgKG9yIGVycm9yKSBpcyBlbWl0dGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2l6ZUxpbWl0ZWRTdHJlYW0oc291cmNlLCBtYXhCeXRlcykge1xuICBsZXQgdG90YWxCeXRlcyA9IDA7XG4gIGxldCBzdGFydGVkID0gZmFsc2U7XG4gIGxldCBzb3VyY2VFbmRlZCA9IGZhbHNlO1xuICBsZXQgb25EYXRhLCBvbkVuZCwgb25FcnJvcjtcblxuICBjb25zdCBvdXRwdXQgPSBuZXcgUmVhZGFibGUoe1xuICAgIHJlYWQoKSB7XG4gICAgICBpZiAoIXN0YXJ0ZWQpIHtcbiAgICAgICAgc3RhcnRlZCA9IHRydWU7XG5cbiAgICAgICAgb25EYXRhID0gKGNodW5rKSA9PiB7XG4gICAgICAgICAgdG90YWxCeXRlcyArPSBjaHVuay5sZW5ndGg7XG4gICAgICAgICAgaWYgKHRvdGFsQnl0ZXMgPiBtYXhCeXRlcykge1xuICAgICAgICAgICAgb3V0cHV0LmRlc3Ryb3koXG4gICAgICAgICAgICAgIG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgICBQYXJzZS5FcnJvci5GSUxFX1NBVkVfRVJST1IsXG4gICAgICAgICAgICAgICAgYEZpbGUgc2l6ZSBleGNlZWRzIG1heGltdW0gYWxsb3dlZDogJHttYXhCeXRlc30gYnl0ZXMuYFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIW91dHB1dC5wdXNoKGNodW5rKSkge1xuICAgICAgICAgICAgc291cmNlLnBhdXNlKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIG9uRW5kID0gKCkgPT4ge1xuICAgICAgICAgIHNvdXJjZUVuZGVkID0gdHJ1ZTtcbiAgICAgICAgICBvdXRwdXQucHVzaChudWxsKTtcbiAgICAgICAgfTtcblxuICAgICAgICBvbkVycm9yID0gKGVycikgPT4gb3V0cHV0LmRlc3Ryb3koZXJyKTtcblxuICAgICAgICBzb3VyY2Uub24oJ2RhdGEnLCBvbkRhdGEpO1xuICAgICAgICBzb3VyY2Uub24oJ2VuZCcsIG9uRW5kKTtcbiAgICAgICAgc291cmNlLm9uKCdlcnJvcicsIG9uRXJyb3IpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXN1bWUgc291cmNlIGluIGNhc2UgaXQgd2FzIHBhdXNlZCBkdWUgdG8gYmFja3ByZXNzdXJlXG4gICAgICBpZiAoIXNvdXJjZUVuZGVkKSB7XG4gICAgICAgIHNvdXJjZS5yZXN1bWUoKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGRlc3Ryb3koZXJyLCBjYWxsYmFjaykge1xuICAgICAgaWYgKG9uRGF0YSkge1xuICAgICAgICBzb3VyY2UucmVtb3ZlTGlzdGVuZXIoJ2RhdGEnLCBvbkRhdGEpO1xuICAgICAgfVxuICAgICAgaWYgKG9uRW5kKSB7XG4gICAgICAgIHNvdXJjZS5yZW1vdmVMaXN0ZW5lcignZW5kJywgb25FbmQpO1xuICAgICAgfVxuICAgICAgaWYgKG9uRXJyb3IpIHtcbiAgICAgICAgc291cmNlLnJlbW92ZUxpc3RlbmVyKCdlcnJvcicsIG9uRXJyb3IpO1xuICAgICAgfVxuICAgICAgLy8gU3VwcHJlc3MgZXJyb3JzIGVtaXR0ZWQgZHVyaW5nIGRyYWluIChlLmcuIGNsaWVudCBkaXNjb25uZWN0KVxuICAgICAgc291cmNlLm9uKCdlcnJvcicsICgpID0+IHt9KTtcbiAgICAgIGlmICghc291cmNlRW5kZWQpIHtcbiAgICAgICAgc291cmNlLnJlc3VtZSgpO1xuICAgICAgfVxuICAgICAgY2FsbGJhY2soZXJyKTtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBvdXRwdXQ7XG59XG5cbi8vIFNlZ21lbnRzIHRoYXQgY29uZmxpY3Qgd2l0aCBzdWItcm91dGVzIHVuZGVyIEdFVCAvZmlsZXMvOmFwcElkLyouIElmIGEgZmlsZVxuLy8gZGlyZWN0b3J5IHN0YXJ0cyB3aXRoIG9uZSBvZiB0aGVzZSwgaXRzIFVSTCB3b3VsZCBtYXRjaCB0aGUgd3Jvbmcgcm91dGVcbi8vIGhhbmRsZXIuIFVwZGF0ZSB0aGlzIGxpc3Qgd2hlbiBhZGRpbmcgbmV3IHN1Yi1yb3V0ZXMgdG8gZXhwcmVzc1JvdXRlcigpLlxuZXhwb3J0IGNvbnN0IFJFU0VSVkVEX0RJUkVDVE9SWV9TRUdNRU5UUyA9IFsnbWV0YWRhdGEnXTtcblxuZXhwb3J0IGNsYXNzIEZpbGVzUm91dGVyIHtcbiAgZXhwcmVzc1JvdXRlcih7IG1heFVwbG9hZFNpemUgPSAnMjBNYicgfSA9IHt9KSB7XG4gICAgdmFyIHJvdXRlciA9IGV4cHJlc3MuUm91dGVyKCk7XG4gICAgLy8gTGlnaHR3ZWlnaHQgaW5mbyBpbml0aWFsaXplciBzbyBoYW5kbGVQYXJzZVNlc3Npb24gY2FuIHJlc29sdmUgc2Vzc2lvbiB0b2tlbnMuXG4gICAgLy8gVW5saWtlIFBPU1QvREVMRVRFIHJvdXRlcywgR0VUIGZpbGUgcm91dGVzIHNraXAgaGFuZGxlUGFyc2VIZWFkZXJzICh3aGljaFxuICAgIC8vIG5vcm1hbGx5IHNldHMgcmVxLmluZm8pIGJlY2F1c2UgdGhvc2UgcmVxdWVzdHMgbWF5IG5vdCBjYXJyeSBQYXJzZSBoZWFkZXJzLlxuICAgIGNvbnN0IGluaXRJbmZvID0gKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgICBpZiAoIXJlcS5pbmZvKSB7XG4gICAgICAgIGNvbnN0IHNlc3Npb25Ub2tlbiA9IHJlcS5nZXQoJ1gtUGFyc2UtU2Vzc2lvbi1Ub2tlbicpO1xuICAgICAgICByZXEuaW5mbyA9IHtcbiAgICAgICAgICBzZXNzaW9uVG9rZW4sXG4gICAgICAgICAgaW5zdGFsbGF0aW9uSWQ6IHJlcS5nZXQoJ1gtUGFyc2UtSW5zdGFsbGF0aW9uLUlkJyksXG4gICAgICAgIH07XG4gICAgICAgIC8vIElmIG5vIHNlc3Npb24gdG9rZW4gYW5kIG5vIGF1dGggeWV0IChwdWJsaWMgYWNjZXNzKSwgc2V0IGEgbWluaW1hbFxuICAgICAgICAvLyBhdXRoIG9iamVjdCBzbyBoYW5kbGVQYXJzZVNlc3Npb24gc2tpcHMgc2Vzc2lvbiByZXNvbHV0aW9uLlxuICAgICAgICBpZiAoIXNlc3Npb25Ub2tlbiAmJiAhcmVxLmF1dGgpIHtcbiAgICAgICAgICByZXEuYXV0aCA9IHsgaXNNYXN0ZXI6IGZhbHNlIH07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIG5leHQoKTtcbiAgICB9O1xuICAgIC8vIE1ldGFkYXRhIHJvdXRlIG11c3QgY29tZSBiZWZvcmUgdGhlIGNhdGNoLWFsbCBHRVQgcm91dGVcbiAgICByb3V0ZXIuZ2V0KCcvZmlsZXMvOmFwcElkL21ldGFkYXRhLypmaWxlcGF0aCcsIGluaXRJbmZvLCBNaWRkbGV3YXJlcy5oYW5kbGVQYXJzZVNlc3Npb24sIHRoaXMubWV0YWRhdGFIYW5kbGVyKTtcbiAgICByb3V0ZXIuZ2V0KCcvZmlsZXMvOmFwcElkLypmaWxlcGF0aCcsIGluaXRJbmZvLCBNaWRkbGV3YXJlcy5oYW5kbGVQYXJzZVNlc3Npb24sIHRoaXMuZ2V0SGFuZGxlcik7XG5cbiAgICByb3V0ZXIucG9zdCgnL2ZpbGVzJywgZnVuY3Rpb24gKHJlcSwgcmVzLCBuZXh0KSB7XG4gICAgICBuZXh0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0ZJTEVfTkFNRSwgJ0ZpbGVuYW1lIG5vdCBwcm92aWRlZC4nKSk7XG4gICAgfSk7XG5cbiAgICByb3V0ZXIucG9zdChcbiAgICAgICcvZmlsZXMvOmZpbGVuYW1lJyxcbiAgICAgIHRoaXMuX2Vhcmx5SGVhZGVyc01pZGRsZXdhcmUoKSxcbiAgICAgIHRoaXMuX2JvZHlQYXJzaW5nTWlkZGxld2FyZShtYXhVcGxvYWRTaXplKSxcbiAgICAgIE1pZGRsZXdhcmVzLmhhbmRsZVBhcnNlSGVhZGVycyxcbiAgICAgIE1pZGRsZXdhcmVzLmhhbmRsZVBhcnNlU2Vzc2lvbixcbiAgICAgIHRoaXMuY3JlYXRlSGFuZGxlci5iaW5kKHRoaXMpXG4gICAgKTtcblxuICAgIHJvdXRlci5kZWxldGUoXG4gICAgICAnL2ZpbGVzLypmaWxlcGF0aCcsXG4gICAgICBNaWRkbGV3YXJlcy5oYW5kbGVQYXJzZUhlYWRlcnMsXG4gICAgICBNaWRkbGV3YXJlcy5oYW5kbGVQYXJzZVNlc3Npb24sXG4gICAgICBNaWRkbGV3YXJlcy5lbmZvcmNlTWFzdGVyS2V5QWNjZXNzLFxuICAgICAgdGhpcy5kZWxldGVIYW5kbGVyXG4gICAgKTtcbiAgICByZXR1cm4gcm91dGVyO1xuICB9XG5cbiAgc3RhdGljIF9nZXRGaWxlbmFtZUZyb21QYXJhbXMocmVxKSB7XG4gICAgY29uc3QgcGFydHMgPSByZXEucGFyYW1zLmZpbGVwYXRoO1xuICAgIHJldHVybiBBcnJheS5pc0FycmF5KHBhcnRzKSA/IHBhcnRzLmpvaW4oJy8nKSA6IHBhcnRzO1xuICB9XG5cbiAgc3RhdGljIHZhbGlkYXRlRGlyZWN0b3J5KGRpcmVjdG9yeSkge1xuICAgIGlmICh0eXBlb2YgZGlyZWN0b3J5ICE9PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0ZJTEVfTkFNRSwgJ0RpcmVjdG9yeSBtdXN0IGJlIGEgc3RyaW5nLicpO1xuICAgIH1cbiAgICBpZiAoZGlyZWN0b3J5Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0ZJTEVfTkFNRSwgJ0RpcmVjdG9yeSBtdXN0IG5vdCBiZSBlbXB0eS4nKTtcbiAgICB9XG4gICAgaWYgKGRpcmVjdG9yeS5sZW5ndGggPiAyNTYpIHtcbiAgICAgIHJldHVybiBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9GSUxFX05BTUUsICdEaXJlY3RvcnkgcGF0aCBpcyB0b28gbG9uZy4nKTtcbiAgICB9XG4gICAgaWYgKGRpcmVjdG9yeS5pbmNsdWRlcygnLi4nKSkge1xuICAgICAgcmV0dXJuIG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0ZJTEVfTkFNRSwgJ0RpcmVjdG9yeSBtdXN0IG5vdCBjb250YWluIFwiLi5cIi4nKTtcbiAgICB9XG4gICAgaWYgKGRpcmVjdG9yeS5zdGFydHNXaXRoKCcvJykgfHwgZGlyZWN0b3J5LmVuZHNXaXRoKCcvJykpIHtcbiAgICAgIHJldHVybiBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfRklMRV9OQU1FLFxuICAgICAgICAnRGlyZWN0b3J5IG11c3Qgbm90IHN0YXJ0IG9yIGVuZCB3aXRoIFwiL1wiLidcbiAgICAgICk7XG4gICAgfVxuICAgIGlmIChkaXJlY3RvcnkuaW5jbHVkZXMoJy8vJykpIHtcbiAgICAgIHJldHVybiBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfRklMRV9OQU1FLFxuICAgICAgICAnRGlyZWN0b3J5IG11c3Qgbm90IGNvbnRhaW4gY29uc2VjdXRpdmUgc2xhc2hlcy4nXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBmaXJzdFNlZ21lbnQgPSBkaXJlY3Rvcnkuc3BsaXQoJy8nKVswXTtcbiAgICBpZiAoUkVTRVJWRURfRElSRUNUT1JZX1NFR01FTlRTLmluY2x1ZGVzKGZpcnN0U2VnbWVudCkpIHtcbiAgICAgIHJldHVybiBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfRklMRV9OQU1FLFxuICAgICAgICBgRGlyZWN0b3J5IG11c3Qgbm90IHN0YXJ0IHdpdGggcmVzZXJ2ZWQgc2VnbWVudCBcIiR7Zmlyc3RTZWdtZW50fVwiLmBcbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnN0IGRpclJlZ2V4ID0gL15bYS16QS1aMC05XVthLXpBLVowLTlfXFwtL10qJC87XG4gICAgaWYgKCFkaXJSZWdleC50ZXN0KGRpcmVjdG9yeSkpIHtcbiAgICAgIHJldHVybiBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfRklMRV9OQU1FLFxuICAgICAgICAnRGlyZWN0b3J5IGNvbnRhaW5zIGludmFsaWQgY2hhcmFjdGVycy4nXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHN0YXRpYyBfdmFsaWRhdGVGaWxlRG93bmxvYWQocmVxLCBjb25maWcpIHtcbiAgICBjb25zdCBpc01hc3RlciA9IHJlcS5hdXRoPy5pc01hc3RlcjtcbiAgICBjb25zdCBpc01haW50ZW5hbmNlID0gcmVxLmF1dGg/LmlzTWFpbnRlbmFuY2U7XG4gICAgaWYgKGlzTWFzdGVyIHx8IGlzTWFpbnRlbmFuY2UpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgdXNlciA9IHJlcS5hdXRoPy51c2VyO1xuICAgIGNvbnN0IGlzTGlua2VkID0gdXNlciAmJiBQYXJzZS5Bbm9ueW1vdXNVdGlscy5pc0xpbmtlZCh1c2VyKTtcbiAgICBpZiAoIWNvbmZpZy5maWxlRG93bmxvYWQuZW5hYmxlRm9yQW5vbnltb3VzVXNlciAmJiBpc0xpbmtlZCkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICAnRmlsZSBkb3dubG9hZCBieSBhbm9ueW1vdXMgdXNlciBpcyBkaXNhYmxlZC4nXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoIWNvbmZpZy5maWxlRG93bmxvYWQuZW5hYmxlRm9yQXV0aGVudGljYXRlZFVzZXIgJiYgIWlzTGlua2VkICYmIHVzZXIpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuT1BFUkFUSU9OX0ZPUkJJRERFTixcbiAgICAgICAgJ0ZpbGUgZG93bmxvYWQgYnkgYXV0aGVudGljYXRlZCB1c2VyIGlzIGRpc2FibGVkLidcbiAgICAgICk7XG4gICAgfVxuICAgIGlmICghY29uZmlnLmZpbGVEb3dubG9hZC5lbmFibGVGb3JQdWJsaWMgJiYgIXVzZXIpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuT1BFUkFUSU9OX0ZPUkJJRERFTixcbiAgICAgICAgJ0ZpbGUgZG93bmxvYWQgYnkgcHVibGljIGlzIGRpc2FibGVkLidcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZ2V0SGFuZGxlcihyZXEsIHJlcykge1xuICAgIGNvbnN0IGNvbmZpZyA9IENvbmZpZy5nZXQocmVxLnBhcmFtcy5hcHBJZCk7XG4gICAgaWYgKCFjb25maWcpIHtcbiAgICAgIGNvbnN0IGVycm9yID0gY3JlYXRlU2FuaXRpemVkSHR0cEVycm9yKDQwMywgJ0ludmFsaWQgYXBwbGljYXRpb24gSUQuJywgY29uZmlnKTtcbiAgICAgIHJlcy5zdGF0dXMoZXJyb3Iuc3RhdHVzKTtcbiAgICAgIHJlcy5qc29uKHsgZXJyb3I6IGVycm9yLm1lc3NhZ2UgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgRmlsZXNSb3V0ZXIuX3ZhbGlkYXRlRmlsZURvd25sb2FkKHJlcSwgY29uZmlnKTtcblxuICAgIGxldCBmaWxlbmFtZSA9IEZpbGVzUm91dGVyLl9nZXRGaWxlbmFtZUZyb21QYXJhbXMocmVxKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgZmlsZXNDb250cm9sbGVyID0gY29uZmlnLmZpbGVzQ29udHJvbGxlcjtcbiAgICAgIGNvbnN0IG1pbWUgPSAoYXdhaXQgaW1wb3J0KCdtaW1lJykpLmRlZmF1bHQ7XG4gICAgICBsZXQgY29udGVudFR5cGUgPSBtaW1lLmdldFR5cGUoZmlsZW5hbWUpO1xuICAgICAgbGV0IGZpbGUgPSBuZXcgUGFyc2UuRmlsZShmaWxlbmFtZSwgeyBiYXNlNjQ6ICcnIH0sIGNvbnRlbnRUeXBlKTtcbiAgICAgIGNvbnN0IGZpbGVBdXRoID0gcmVxLmF1dGg7XG4gICAgICBjb25zdCB0cmlnZ2VyUmVzdWx0ID0gYXdhaXQgdHJpZ2dlcnMubWF5YmVSdW5GaWxlVHJpZ2dlcihcbiAgICAgICAgdHJpZ2dlcnMuVHlwZXMuYmVmb3JlRmluZCxcbiAgICAgICAgeyBmaWxlIH0sXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgZmlsZUF1dGhcbiAgICAgICk7XG4gICAgICBpZiAodHJpZ2dlclJlc3VsdD8uZmlsZT8uX25hbWUpIHtcbiAgICAgICAgZmlsZW5hbWUgPSB0cmlnZ2VyUmVzdWx0Py5maWxlPy5fbmFtZTtcbiAgICAgICAgY29udGVudFR5cGUgPSBtaW1lLmdldFR5cGUoZmlsZW5hbWUpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBkZWZhdWx0UmVzcG9uc2VIZWFkZXJzID0geyAnWC1Db250ZW50LVR5cGUtT3B0aW9ucyc6ICdub3NuaWZmJyB9O1xuXG4gICAgICBpZiAoaXNGaWxlU3RyZWFtYWJsZShyZXEsIGZpbGVzQ29udHJvbGxlcikpIHtcbiAgICAgICAgY29uc3QgYWZ0ZXJGaW5kID0gYXdhaXQgdHJpZ2dlcnMubWF5YmVSdW5GaWxlVHJpZ2dlcihcbiAgICAgICAgICB0cmlnZ2Vycy5UeXBlcy5hZnRlckZpbmQsXG4gICAgICAgICAgeyBmaWxlLCBmb3JjZURvd25sb2FkOiBmYWxzZSwgcmVzcG9uc2VIZWFkZXJzOiB7IC4uLmRlZmF1bHRSZXNwb25zZUhlYWRlcnMgfSB9LFxuICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICBmaWxlQXV0aFxuICAgICAgICApO1xuICAgICAgICBpZiAoYWZ0ZXJGaW5kPy5mb3JjZURvd25sb2FkKSB7XG4gICAgICAgICAgcmVzLnNldCgnQ29udGVudC1EaXNwb3NpdGlvbicsIGBhdHRhY2htZW50O2ZpbGVuYW1lPSR7YWZ0ZXJGaW5kLmZpbGU/Ll9uYW1lIHx8IGZpbGVuYW1lfWApO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGFmdGVyRmluZD8ucmVzcG9uc2VIZWFkZXJzID8/IGRlZmF1bHRSZXNwb25zZUhlYWRlcnMpKSB7XG4gICAgICAgICAgcmVzLnNldChrZXksIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBmaWxlc0NvbnRyb2xsZXIuaGFuZGxlRmlsZVN0cmVhbShjb25maWcsIGZpbGVuYW1lLCByZXEsIHJlcywgY29udGVudFR5cGUpLmNhdGNoKCgpID0+IHtcbiAgICAgICAgICByZXMuc3RhdHVzKDQwNCk7XG4gICAgICAgICAgcmVzLnNldCgnQ29udGVudC1UeXBlJywgJ3RleHQvcGxhaW4nKTtcbiAgICAgICAgICByZXMuZW5kKCdGaWxlIG5vdCBmb3VuZC4nKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgbGV0IGRhdGEgPSBhd2FpdCBmaWxlc0NvbnRyb2xsZXIuZ2V0RmlsZURhdGEoY29uZmlnLCBmaWxlbmFtZSkuY2F0Y2goKCkgPT4ge1xuICAgICAgICByZXMuc3RhdHVzKDQwNCk7XG4gICAgICAgIHJlcy5zZXQoJ0NvbnRlbnQtVHlwZScsICd0ZXh0L3BsYWluJyk7XG4gICAgICAgIHJlcy5lbmQoJ0ZpbGUgbm90IGZvdW5kLicpO1xuICAgICAgfSk7XG4gICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgZmlsZSA9IG5ldyBQYXJzZS5GaWxlKGZpbGVuYW1lLCB7IGJhc2U2NDogZGF0YS50b1N0cmluZygnYmFzZTY0JykgfSwgY29udGVudFR5cGUpO1xuICAgICAgY29uc3QgYWZ0ZXJGaW5kID0gYXdhaXQgdHJpZ2dlcnMubWF5YmVSdW5GaWxlVHJpZ2dlcihcbiAgICAgICAgdHJpZ2dlcnMuVHlwZXMuYWZ0ZXJGaW5kLFxuICAgICAgICB7IGZpbGUsIGZvcmNlRG93bmxvYWQ6IGZhbHNlLCByZXNwb25zZUhlYWRlcnM6IHsgLi4uZGVmYXVsdFJlc3BvbnNlSGVhZGVycyB9IH0sXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgZmlsZUF1dGhcbiAgICAgICk7XG5cbiAgICAgIGlmIChhZnRlckZpbmQ/LmZpbGUpIHtcbiAgICAgICAgY29udGVudFR5cGUgPSBtaW1lLmdldFR5cGUoYWZ0ZXJGaW5kLmZpbGUuX25hbWUpO1xuICAgICAgICBkYXRhID0gQnVmZmVyLmZyb20oYWZ0ZXJGaW5kLmZpbGUuX2RhdGEsICdiYXNlNjQnKTtcbiAgICAgIH1cblxuICAgICAgcmVzLnN0YXR1cygyMDApO1xuICAgICAgcmVzLnNldCgnQ29udGVudC1UeXBlJywgY29udGVudFR5cGUpO1xuICAgICAgcmVzLnNldCgnQ29udGVudC1MZW5ndGgnLCBkYXRhLmxlbmd0aCk7XG4gICAgICBpZiAoYWZ0ZXJGaW5kLmZvcmNlRG93bmxvYWQpIHtcbiAgICAgICAgcmVzLnNldCgnQ29udGVudC1EaXNwb3NpdGlvbicsIGBhdHRhY2htZW50O2ZpbGVuYW1lPSR7YWZ0ZXJGaW5kLmZpbGUuX25hbWV9YCk7XG4gICAgICB9XG4gICAgICBpZiAoYWZ0ZXJGaW5kLnJlc3BvbnNlSGVhZGVycykge1xuICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhhZnRlckZpbmQucmVzcG9uc2VIZWFkZXJzKSkge1xuICAgICAgICAgIHJlcy5zZXQoa2V5LCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJlcy5lbmQoZGF0YSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc3QgZXJyID0gdHJpZ2dlcnMucmVzb2x2ZUVycm9yKGUsIHtcbiAgICAgICAgY29kZTogUGFyc2UuRXJyb3IuU0NSSVBUX0ZBSUxFRCxcbiAgICAgICAgbWVzc2FnZTogYENvdWxkIG5vdCBmaW5kIGZpbGU6ICR7ZmlsZW5hbWV9LmAsXG4gICAgICB9KTtcbiAgICAgIHJlcy5zdGF0dXMoNDAzKTtcbiAgICAgIHJlcy5qc29uKHsgY29kZTogZXJyLmNvZGUsIGVycm9yOiBlcnIubWVzc2FnZSB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWlkZGxld2FyZSB0aGF0IHJ1bnMgYmVmb3JlIGJvZHkgcGFyc2luZyB0byBoYW5kbGUgaGVhZGVycyB0aGF0IG11c3QgYmVcbiAgICogcmVzb2x2ZWQgYmVmb3JlIHRoZSByZXF1ZXN0IGJvZHkgaXMgY29uc3VtZWQuIEN1cnJlbnRseSBzdXBwb3J0czpcbiAgICpcbiAgICogLSBgWC1QYXJzZS1GaWxlLU1heC1VcGxvYWQtU2l6ZWA6IE92ZXJyaWRlcyB0aGUgc2VydmVyLXdpZGUgYG1heFVwbG9hZFNpemVgXG4gICAqICAgZm9yIHRoaXMgcmVxdWVzdC4gUmVxdWlyZXMgdGhlIG1hc3RlciBrZXkuIFRoZSB2YWx1ZSB1c2VzIHRoZSBzYW1lIGZvcm1hdFxuICAgKiAgIGFzIHRoZSBzZXJ2ZXIgb3B0aW9uIChlLmcuIGAnNTBtYidgLCBgJzFnYidgKS4gU2V0cyBgcmVxLl9tYXhVcGxvYWRTaXplT3ZlcnJpZGVgXG4gICAqICAgKGluIGJ5dGVzKSBmb3IgYF9ib2R5UGFyc2luZ01pZGRsZXdhcmVgIHRvIHVzZS5cbiAgICovXG4gIF9lYXJseUhlYWRlcnNNaWRkbGV3YXJlKCkge1xuICAgIHJldHVybiBhc3luYyAocmVxLCByZXMsIG5leHQpID0+IHtcbiAgICAgIGNvbnN0IG1heFVwbG9hZFNpemVPdmVycmlkZSA9IHJlcS5nZXQoJ1gtUGFyc2UtRmlsZS1NYXgtVXBsb2FkLVNpemUnKTtcbiAgICAgIGlmICghbWF4VXBsb2FkU2l6ZU92ZXJyaWRlKSB7XG4gICAgICAgIHJldHVybiBuZXh0KCk7XG4gICAgICB9XG4gICAgICBjb25zdCBhcHBJZCA9IHJlcS5nZXQoJ1gtUGFyc2UtQXBwbGljYXRpb24tSWQnKTtcbiAgICAgIGNvbnN0IGNvbmZpZyA9IENvbmZpZy5nZXQoYXBwSWQpO1xuICAgICAgaWYgKCFjb25maWcpIHtcbiAgICAgICAgY29uc3QgZXJyb3IgPSBjcmVhdGVTYW5pdGl6ZWRIdHRwRXJyb3IoNDAzLCAnSW52YWxpZCBhcHBsaWNhdGlvbiBJRC4nLCB1bmRlZmluZWQpO1xuICAgICAgICByZXMuc3RhdHVzKGVycm9yLnN0YXR1cyk7XG4gICAgICAgIHJlcy5qc29uKHsgZXJyb3I6IGVycm9yLm1lc3NhZ2UgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IG1hc3RlcktleSA9IGF3YWl0IGNvbmZpZy5sb2FkTWFzdGVyS2V5KCk7XG4gICAgICBpZiAocmVxLmdldCgnWC1QYXJzZS1NYXN0ZXItS2V5JykgIT09IG1hc3RlcktleSkge1xuICAgICAgICBjb25zdCBlcnJvciA9IGNyZWF0ZVNhbml0aXplZEh0dHBFcnJvcig0MDMsICd1bmF1dGhvcml6ZWQ6IG1hc3RlciBrZXkgaXMgcmVxdWlyZWQnLCBjb25maWcpO1xuICAgICAgICByZXMuc3RhdHVzKGVycm9yLnN0YXR1cyk7XG4gICAgICAgIHJlcy5qc29uKHsgZXJyb3I6IGVycm9yLm1lc3NhZ2UgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmIChjb25maWcubWFzdGVyS2V5SXBzPy5sZW5ndGggJiYgIU1pZGRsZXdhcmVzLmNoZWNrSXAocmVxLmlwLCBjb25maWcubWFzdGVyS2V5SXBzLCBjb25maWcubWFzdGVyS2V5SXBzU3RvcmUpKSB7XG4gICAgICAgIGNvbnN0IGVycm9yID0gY3JlYXRlU2FuaXRpemVkSHR0cEVycm9yKDQwMywgJ3VuYXV0aG9yaXplZDogbWFzdGVyIGtleSBpcyByZXF1aXJlZCcsIGNvbmZpZyk7XG4gICAgICAgIHJlcy5zdGF0dXMoZXJyb3Iuc3RhdHVzKTtcbiAgICAgICAgcmVzLmpzb24oeyBlcnJvcjogZXJyb3IubWVzc2FnZSB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgbGV0IHBhcnNlZEJ5dGVzO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcGFyc2VkQnl0ZXMgPSBVdGlscy5wYXJzZVNpemVUb0J5dGVzKG1heFVwbG9hZFNpemVPdmVycmlkZSk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIG5leHQoXG4gICAgICAgICAgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuRklMRV9TQVZFX0VSUk9SLFxuICAgICAgICAgICAgYEludmFsaWQgbWF4VXBsb2FkU2l6ZSBvdmVycmlkZSB2YWx1ZTogJHttYXhVcGxvYWRTaXplT3ZlcnJpZGV9YFxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHJlcS5fbWF4VXBsb2FkU2l6ZU92ZXJyaWRlID0gcGFyc2VkQnl0ZXM7XG4gICAgICBuZXh0KCk7XG4gICAgfTtcbiAgfVxuXG4gIF9ib2R5UGFyc2luZ01pZGRsZXdhcmUobWF4VXBsb2FkU2l6ZSkge1xuICAgIGNvbnN0IGRlZmF1bHRNYXhCeXRlcyA9IFV0aWxzLnBhcnNlU2l6ZVRvQnl0ZXMobWF4VXBsb2FkU2l6ZSk7XG4gICAgcmV0dXJuIChyZXEsIHJlcywgbmV4dCkgPT4ge1xuICAgICAgaWYgKHJlcS5nZXQoJ1gtUGFyc2UtVXBsb2FkLU1vZGUnKSA9PT0gJ3N0cmVhbScpIHtcbiAgICAgICAgcmVxLl9tYXhVcGxvYWRTaXplQnl0ZXMgPSByZXEuX21heFVwbG9hZFNpemVPdmVycmlkZSA/PyBkZWZhdWx0TWF4Qnl0ZXM7XG4gICAgICAgIHJldHVybiBuZXh0KCk7XG4gICAgICB9XG4gICAgICBjb25zdCBsaW1pdCA9IHJlcS5fbWF4VXBsb2FkU2l6ZU92ZXJyaWRlID8/IG1heFVwbG9hZFNpemU7XG4gICAgICByZXR1cm4gZXhwcmVzcy5yYXcoeyB0eXBlOiAoKSA9PiB0cnVlLCBsaW1pdCB9KShyZXEsIHJlcywgbmV4dCk7XG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGNyZWF0ZUhhbmRsZXIocmVxLCByZXMsIG5leHQpIHtcbiAgICBpZiAocmVxLmF1dGguaXNSZWFkT25seSkge1xuICAgICAgY29uc3QgZXJyb3IgPSBjcmVhdGVTYW5pdGl6ZWRIdHRwRXJyb3IoNDAzLCBcInJlYWQtb25seSBtYXN0ZXJLZXkgaXNuJ3QgYWxsb3dlZCB0byBjcmVhdGUgYSBmaWxlLlwiLCByZXEuY29uZmlnKTtcbiAgICAgIHJlcy5zdGF0dXMoZXJyb3Iuc3RhdHVzKTtcbiAgICAgIHJlcy5lbmQoYHtcImVycm9yXCI6XCIke2Vycm9yLm1lc3NhZ2V9XCJ9YCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGNvbmZpZyA9IHJlcS5jb25maWc7XG4gICAgY29uc3QgaXNNYXN0ZXIgPSByZXEuYXV0aC5pc01hc3RlcjtcbiAgICBjb25zdCBpc01haW50ZW5hbmNlID0gcmVxLmF1dGguaXNNYWludGVuYW5jZTtcbiAgICBpZiAoIWlzTWFzdGVyICYmICFpc01haW50ZW5hbmNlKSB7XG4gICAgICBjb25zdCB1c2VyID0gcmVxLmF1dGgudXNlcjtcbiAgICAgIGNvbnN0IGlzTGlua2VkID0gdXNlciAmJiBQYXJzZS5Bbm9ueW1vdXNVdGlscy5pc0xpbmtlZCh1c2VyKTtcbiAgICAgIGlmICghY29uZmlnLmZpbGVVcGxvYWQuZW5hYmxlRm9yQW5vbnltb3VzVXNlciAmJiBpc0xpbmtlZCkge1xuICAgICAgICBuZXh0KFxuICAgICAgICAgIG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5GSUxFX1NBVkVfRVJST1IsICdGaWxlIHVwbG9hZCBieSBhbm9ueW1vdXMgdXNlciBpcyBkaXNhYmxlZC4nKVxuICAgICAgICApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoIWNvbmZpZy5maWxlVXBsb2FkLmVuYWJsZUZvckF1dGhlbnRpY2F0ZWRVc2VyICYmICFpc0xpbmtlZCAmJiB1c2VyKSB7XG4gICAgICAgIG5leHQoXG4gICAgICAgICAgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuRklMRV9TQVZFX0VSUk9SLFxuICAgICAgICAgICAgJ0ZpbGUgdXBsb2FkIGJ5IGF1dGhlbnRpY2F0ZWQgdXNlciBpcyBkaXNhYmxlZC4nXG4gICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoIWNvbmZpZy5maWxlVXBsb2FkLmVuYWJsZUZvclB1YmxpYyAmJiAhdXNlcikge1xuICAgICAgICBuZXh0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5GSUxFX1NBVkVfRVJST1IsICdGaWxlIHVwbG9hZCBieSBwdWJsaWMgaXMgZGlzYWJsZWQuJykpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGZpbGVzQ29udHJvbGxlciA9IGNvbmZpZy5maWxlc0NvbnRyb2xsZXI7XG4gICAgY29uc3QgeyBmaWxlbmFtZSB9ID0gcmVxLnBhcmFtcztcbiAgICBjb25zdCBjb250ZW50VHlwZSA9IHJlcS5nZXQoJ0NvbnRlbnQtdHlwZScpO1xuXG4gICAgY29uc3QgZXJyb3IgPSBmaWxlc0NvbnRyb2xsZXIudmFsaWRhdGVGaWxlbmFtZShmaWxlbmFtZSk7XG4gICAgaWYgKGVycm9yKSB7XG4gICAgICBuZXh0KGVycm9yKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBmaWxlRXh0ZW5zaW9ucyA9IGNvbmZpZy5maWxlVXBsb2FkPy5maWxlRXh0ZW5zaW9ucztcbiAgICBpZiAoIWlzTWFzdGVyICYmIGZpbGVFeHRlbnNpb25zKSB7XG4gICAgICBjb25zdCBpc1ZhbGlkRXh0ZW5zaW9uID0gZXh0ZW5zaW9uID0+IHtcbiAgICAgICAgcmV0dXJuIGZpbGVFeHRlbnNpb25zLnNvbWUoZXh0ID0+IHtcbiAgICAgICAgICBpZiAoZXh0ID09PSAnKicpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCByZWdleCA9IG5ldyBSZWdFeHAoZXh0KTtcbiAgICAgICAgICBpZiAocmVnZXgudGVzdChleHRlbnNpb24pKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfTtcbiAgICAgIGxldCBleHRlbnNpb24gPSBjb250ZW50VHlwZTtcbiAgICAgIGlmIChmaWxlbmFtZSAmJiBmaWxlbmFtZS5pbmNsdWRlcygnLicpKSB7XG4gICAgICAgIGV4dGVuc2lvbiA9IGZpbGVuYW1lLnN1YnN0cmluZyhmaWxlbmFtZS5sYXN0SW5kZXhPZignLicpICsgMSk7XG4gICAgICB9IGVsc2UgaWYgKGNvbnRlbnRUeXBlICYmIGNvbnRlbnRUeXBlLmluY2x1ZGVzKCcvJykpIHtcbiAgICAgICAgZXh0ZW5zaW9uID0gY29udGVudFR5cGUuc3BsaXQoJy8nKVsxXTtcbiAgICAgIH1cbiAgICAgIC8vIFN0cmlwIE1JTUUgcGFyYW1ldGVycyAoZS5nLiBcIjtjaGFyc2V0PXV0Zi04XCIpIGFuZCB3aGl0ZXNwYWNlXG4gICAgICBleHRlbnNpb24gPSBleHRlbnNpb24/LnNwbGl0KCc7JylbMF0/LnJlcGxhY2UoL1xccysvZywgJycpO1xuXG4gICAgICBpZiAoZXh0ZW5zaW9uICYmICFpc1ZhbGlkRXh0ZW5zaW9uKGV4dGVuc2lvbikpIHtcbiAgICAgICAgbmV4dChcbiAgICAgICAgICBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5GSUxFX1NBVkVfRVJST1IsXG4gICAgICAgICAgICBgRmlsZSB1cGxvYWQgb2YgZXh0ZW5zaW9uICR7ZXh0ZW5zaW9ufSBpcyBkaXNhYmxlZC5gXG4gICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRm9yIHN0cmVhbWluZyB1cGxvYWRzLCByZWFkIGZpbGUgZGF0YSBmcm9tIGhlYWRlcnMgc2luY2UgdGhlIGJvZHkgaXMgdGhlIHJhdyBzdHJlYW1cbiAgICBpZiAocmVxLmdldCgnWC1QYXJzZS1VcGxvYWQtTW9kZScpID09PSAnc3RyZWFtJykge1xuICAgICAgcmVxLmZpbGVEYXRhID0ge307XG4gICAgICBpZiAocmVxLmdldCgnWC1QYXJzZS1GaWxlLURpcmVjdG9yeScpKSB7XG4gICAgICAgIHJlcS5maWxlRGF0YS5kaXJlY3RvcnkgPSByZXEuZ2V0KCdYLVBhcnNlLUZpbGUtRGlyZWN0b3J5Jyk7XG4gICAgICB9XG4gICAgICBpZiAocmVxLmdldCgnWC1QYXJzZS1GaWxlLU1ldGFkYXRhJykpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKHJlcS5nZXQoJ1gtUGFyc2UtRmlsZS1NZXRhZGF0YScpKTtcbiAgICAgICAgICBpZiAoIXBhcnNlZCB8fCB0eXBlb2YgcGFyc2VkICE9PSAnb2JqZWN0JyB8fCBBcnJheS5pc0FycmF5KHBhcnNlZCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXEuZmlsZURhdGEubWV0YWRhdGEgPSBwYXJzZWQ7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIG5leHQobmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgJ0ludmFsaWQgSlNPTiBpbiBYLVBhcnNlLUZpbGUtTWV0YWRhdGEgaGVhZGVyLicpKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChyZXEuZ2V0KCdYLVBhcnNlLUZpbGUtVGFncycpKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShyZXEuZ2V0KCdYLVBhcnNlLUZpbGUtVGFncycpKTtcbiAgICAgICAgICBpZiAoIXBhcnNlZCB8fCB0eXBlb2YgcGFyc2VkICE9PSAnb2JqZWN0JyB8fCBBcnJheS5pc0FycmF5KHBhcnNlZCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXEuZmlsZURhdGEudGFncyA9IHBhcnNlZDtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgbmV4dChuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnSW52YWxpZCBKU09OIGluIFgtUGFyc2UtRmlsZS1UYWdzIGhlYWRlci4nKSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgZGlyZWN0b3J5IG9wdGlvbiAocmVxdWlyZXMgbWFzdGVyIGtleSlcbiAgICBjb25zdCBkaXJlY3RvcnkgPSByZXEuZmlsZURhdGE/LmRpcmVjdG9yeTtcbiAgICBpZiAoZGlyZWN0b3J5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmICghaXNNYXN0ZXIpIHtcbiAgICAgICAgbmV4dChcbiAgICAgICAgICBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLFxuICAgICAgICAgICAgJ0RpcmVjdG9yeSBjYW4gb25seSBiZSBzZXQgdXNpbmcgdGhlIE1hc3RlciBLZXkuJ1xuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY29uc3QgZGlyZWN0b3J5RXJyb3IgPSBGaWxlc1JvdXRlci52YWxpZGF0ZURpcmVjdG9yeShkaXJlY3RvcnkpO1xuICAgICAgaWYgKGRpcmVjdG9yeUVycm9yKSB7XG4gICAgICAgIG5leHQoZGlyZWN0b3J5RXJyb3IpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRGlzcGF0Y2ggdG8gdGhlIGFwcHJvcHJpYXRlIGhhbmRsZXIgYmFzZWQgb24gd2hldGhlciB0aGUgYm9keSB3YXMgYnVmZmVyZWRcbiAgICBpZiAoQnVmZmVyLmlzQnVmZmVyKHJlcS5ib2R5KSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2hhbmRsZUJ1ZmZlcmVkVXBsb2FkKHJlcSwgcmVzLCBuZXh0KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2hhbmRsZVN0cmVhbVVwbG9hZChyZXEsIHJlcywgbmV4dCk7XG4gIH1cblxuICBhc3luYyBfaGFuZGxlQnVmZmVyZWRVcGxvYWQocmVxLCByZXMsIG5leHQpIHtcbiAgICBjb25zdCBjb25maWcgPSByZXEuY29uZmlnO1xuICAgIGNvbnN0IGZpbGVzQ29udHJvbGxlciA9IGNvbmZpZy5maWxlc0NvbnRyb2xsZXI7XG4gICAgY29uc3QgeyBmaWxlbmFtZSB9ID0gcmVxLnBhcmFtcztcbiAgICBjb25zdCBjb250ZW50VHlwZSA9IHJlcS5nZXQoJ0NvbnRlbnQtdHlwZScpO1xuXG4gICAgaWYgKCFyZXEuYm9keSB8fCAhcmVxLmJvZHkubGVuZ3RoKSB7XG4gICAgICBuZXh0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5GSUxFX1NBVkVfRVJST1IsICdJbnZhbGlkIGZpbGUgdXBsb2FkLicpKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBiYXNlNjQgPSByZXEuYm9keS50b1N0cmluZygnYmFzZTY0Jyk7XG4gICAgY29uc3QgZmlsZSA9IG5ldyBQYXJzZS5GaWxlKGZpbGVuYW1lLCB7IGJhc2U2NCB9LCBjb250ZW50VHlwZSk7XG4gICAgY29uc3QgeyBtZXRhZGF0YSA9IHt9LCB0YWdzID0ge30sIGRpcmVjdG9yeSB9ID0gcmVxLmZpbGVEYXRhIHx8IHt9O1xuICAgIHRyeSB7XG4gICAgICAvLyBTY2FuIHJlcXVlc3QgZGF0YSBmb3IgZGVuaWVkIGtleXdvcmRzXG4gICAgICBVdGlscy5jaGVja1Byb2hpYml0ZWRLZXl3b3Jkcyhjb25maWcsIG1ldGFkYXRhKTtcbiAgICAgIFV0aWxzLmNoZWNrUHJvaGliaXRlZEtleXdvcmRzKGNvbmZpZywgdGFncyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIG5leHQobmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUsIGVycm9yKSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZpbGUuc2V0VGFncyh0YWdzKTtcbiAgICBmaWxlLnNldE1ldGFkYXRhKG1ldGFkYXRhKTtcbiAgICBpZiAoZGlyZWN0b3J5KSB7XG4gICAgICBmaWxlLnNldERpcmVjdG9yeShkaXJlY3RvcnkpO1xuICAgIH1cbiAgICBjb25zdCBmaWxlU2l6ZSA9IEJ1ZmZlci5ieXRlTGVuZ3RoKHJlcS5ib2R5KTtcbiAgICBjb25zdCBmaWxlT2JqZWN0ID0geyBmaWxlLCBmaWxlU2l6ZSB9O1xuICAgIHRyeSB7XG4gICAgICAvLyBydW4gYmVmb3JlU2F2ZUZpbGUgdHJpZ2dlclxuICAgICAgY29uc3QgdHJpZ2dlclJlc3VsdCA9IGF3YWl0IHRyaWdnZXJzLm1heWJlUnVuRmlsZVRyaWdnZXIoXG4gICAgICAgIHRyaWdnZXJzLlR5cGVzLmJlZm9yZVNhdmUsXG4gICAgICAgIGZpbGVPYmplY3QsXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgcmVxLmF1dGhcbiAgICAgICk7XG4gICAgICBsZXQgc2F2ZVJlc3VsdDtcbiAgICAgIC8vIGlmIGEgbmV3IFBhcnNlRmlsZSBpcyByZXR1cm5lZCBjaGVjayBpZiBpdCdzIGFuIGFscmVhZHkgc2F2ZWQgZmlsZVxuICAgICAgaWYgKHRyaWdnZXJSZXN1bHQgaW5zdGFuY2VvZiBQYXJzZS5GaWxlKSB7XG4gICAgICAgIGZpbGVPYmplY3QuZmlsZSA9IHRyaWdnZXJSZXN1bHQ7XG4gICAgICAgIGlmICh0cmlnZ2VyUmVzdWx0LnVybCgpKSB7XG4gICAgICAgICAgLy8gc2V0IGZpbGVTaXplIHRvIG51bGwgYmVjYXVzZSB3ZSB3b250IGtub3cgaG93IGJpZyBpdCBpcyBoZXJlXG4gICAgICAgICAgZmlsZU9iamVjdC5maWxlU2l6ZSA9IG51bGw7XG4gICAgICAgICAgc2F2ZVJlc3VsdCA9IHtcbiAgICAgICAgICAgIHVybDogdHJpZ2dlclJlc3VsdC51cmwoKSxcbiAgICAgICAgICAgIG5hbWU6IHRyaWdnZXJSZXN1bHQuX25hbWUsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gaWYgdGhlIGZpbGUgcmV0dXJuZWQgYnkgdGhlIHRyaWdnZXIgaGFzIGFscmVhZHkgYmVlbiBzYXZlZCBza2lwIHNhdmluZyBhbnl0aGluZ1xuICAgICAgaWYgKCFzYXZlUmVzdWx0KSB7XG4gICAgICAgIC8vIHVwZGF0ZSBmaWxlU2l6ZVxuICAgICAgICBsZXQgYnVmZmVyRGF0YTtcbiAgICAgICAgaWYgKGZpbGVPYmplY3QuZmlsZS5fc291cmNlPy5mb3JtYXQgPT09ICdidWZmZXInKSB7XG4gICAgICAgICAgYnVmZmVyRGF0YSA9IGZpbGVPYmplY3QuZmlsZS5fc291cmNlLmJ1ZmZlcjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBidWZmZXJEYXRhID0gQnVmZmVyLmZyb20oZmlsZU9iamVjdC5maWxlLl9kYXRhLCAnYmFzZTY0Jyk7XG4gICAgICAgIH1cbiAgICAgICAgZmlsZU9iamVjdC5maWxlU2l6ZSA9IEJ1ZmZlci5ieXRlTGVuZ3RoKGJ1ZmZlckRhdGEpO1xuICAgICAgICAvLyBwcmVwYXJlIGZpbGUgb3B0aW9uc1xuICAgICAgICBjb25zdCBmaWxlT3B0aW9ucyA9IHtcbiAgICAgICAgICBtZXRhZGF0YTogZmlsZU9iamVjdC5maWxlLl9tZXRhZGF0YSxcbiAgICAgICAgfTtcbiAgICAgICAgLy8gc29tZSBzMy1jb21wYXRpYmxlIHByb3ZpZGVycyAoRGlnaXRhbE9jZWFuLCBMaW5vZGUpIGRvIG5vdCBhY2NlcHQgdGFnc1xuICAgICAgICAvLyBzbyB3ZSBkbyBub3QgaW5jbHVkZSB0aGUgdGFncyBvcHRpb24gaWYgaXQgaXMgZW1wdHkuXG4gICAgICAgIGNvbnN0IGZpbGVUYWdzID1cbiAgICAgICAgICBPYmplY3Qua2V5cyhmaWxlT2JqZWN0LmZpbGUuX3RhZ3MpLmxlbmd0aCA+IDAgPyB7IHRhZ3M6IGZpbGVPYmplY3QuZmlsZS5fdGFncyB9IDoge307XG4gICAgICAgIE9iamVjdC5hc3NpZ24oZmlsZU9wdGlvbnMsIGZpbGVUYWdzKTtcbiAgICAgICAgLy8gaW5jbHVkZSBkaXJlY3RvcnkgaWYgc2V0IChmcm9tIGNsaWVudCByZXF1ZXN0IG9yIGJlZm9yZVNhdmVGaWxlIHRyaWdnZXIpXG4gICAgICAgIGlmIChmaWxlT2JqZWN0LmZpbGUuX2RpcmVjdG9yeSkge1xuICAgICAgICAgIGZpbGVPcHRpb25zLmRpcmVjdG9yeSA9IGZpbGVPYmplY3QuZmlsZS5fZGlyZWN0b3J5O1xuICAgICAgICB9XG4gICAgICAgIC8vIHNhdmUgZmlsZVxuICAgICAgICBjb25zdCBjcmVhdGVGaWxlUmVzdWx0ID0gYXdhaXQgZmlsZXNDb250cm9sbGVyLmNyZWF0ZUZpbGUoXG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICAgIGZpbGVPYmplY3QuZmlsZS5fbmFtZSxcbiAgICAgICAgICBidWZmZXJEYXRhLFxuICAgICAgICAgIGZpbGVPYmplY3QuZmlsZS5fc291cmNlLnR5cGUsXG4gICAgICAgICAgZmlsZU9wdGlvbnNcbiAgICAgICAgKTtcbiAgICAgICAgLy8gdXBkYXRlIGZpbGUgd2l0aCBuZXcgZGF0YVxuICAgICAgICBmaWxlT2JqZWN0LmZpbGUuX25hbWUgPSBjcmVhdGVGaWxlUmVzdWx0Lm5hbWU7XG4gICAgICAgIGZpbGVPYmplY3QuZmlsZS5fdXJsID0gY3JlYXRlRmlsZVJlc3VsdC51cmw7XG4gICAgICAgIGZpbGVPYmplY3QuZmlsZS5fcmVxdWVzdFRhc2sgPSBudWxsO1xuICAgICAgICBmaWxlT2JqZWN0LmZpbGUuX3ByZXZpb3VzU2F2ZSA9IFByb21pc2UucmVzb2x2ZShmaWxlT2JqZWN0LmZpbGUpO1xuICAgICAgICBzYXZlUmVzdWx0ID0ge1xuICAgICAgICAgIHVybDogY3JlYXRlRmlsZVJlc3VsdC51cmwsXG4gICAgICAgICAgbmFtZTogY3JlYXRlRmlsZVJlc3VsdC5uYW1lLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgLy8gcnVuIGFmdGVyU2F2ZUZpbGUgdHJpZ2dlclxuICAgICAgYXdhaXQgdHJpZ2dlcnMubWF5YmVSdW5GaWxlVHJpZ2dlcih0cmlnZ2Vycy5UeXBlcy5hZnRlclNhdmUsIGZpbGVPYmplY3QsIGNvbmZpZywgcmVxLmF1dGgpO1xuICAgICAgcmVzLnN0YXR1cygyMDEpO1xuICAgICAgcmVzLnNldCgnTG9jYXRpb24nLCBzYXZlUmVzdWx0LnVybCk7XG4gICAgICByZXMuanNvbihzYXZlUmVzdWx0KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ0Vycm9yIGNyZWF0aW5nIGEgZmlsZTogJywgZSk7XG4gICAgICBjb25zdCBlcnJvciA9IHRyaWdnZXJzLnJlc29sdmVFcnJvcihlLCB7XG4gICAgICAgIGNvZGU6IFBhcnNlLkVycm9yLkZJTEVfU0FWRV9FUlJPUixcbiAgICAgICAgbWVzc2FnZTogYENvdWxkIG5vdCBzdG9yZSBmaWxlOiAke2ZpbGVPYmplY3QuZmlsZS5fbmFtZX0uYCxcbiAgICAgIH0pO1xuICAgICAgbmV4dChlcnJvcik7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgX2hhbmRsZVN0cmVhbVVwbG9hZChyZXEsIHJlcywgbmV4dCkge1xuICAgIGNvbnN0IGNvbmZpZyA9IHJlcS5jb25maWc7XG4gICAgY29uc3QgZmlsZXNDb250cm9sbGVyID0gY29uZmlnLmZpbGVzQ29udHJvbGxlcjtcbiAgICBjb25zdCB7IGZpbGVuYW1lIH0gPSByZXEucGFyYW1zO1xuICAgIGxldCBjb250ZW50VHlwZSA9IHJlcS5nZXQoJ0NvbnRlbnQtVHlwZScpO1xuICAgIGNvbnN0IG1heEJ5dGVzID0gcmVxLl9tYXhVcGxvYWRTaXplQnl0ZXM7XG4gICAgbGV0IHN0cmVhbTtcblxuICAgIHRyeSB7XG4gICAgICAvLyBFYXJseSByZWplY3Rpb24gdmlhIENvbnRlbnQtTGVuZ3RoIGhlYWRlclxuICAgICAgY29uc3QgY29udGVudExlbmd0aCA9IHJlcS5nZXQoJ0NvbnRlbnQtTGVuZ3RoJyk7XG4gICAgICBpZiAoY29udGVudExlbmd0aCAmJiBwYXJzZUludChjb250ZW50TGVuZ3RoLCAxMCkgPiBtYXhCeXRlcykge1xuICAgICAgICByZXEucmVzdW1lKCk7XG4gICAgICAgIG5leHQobmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgIFBhcnNlLkVycm9yLkZJTEVfU0FWRV9FUlJPUixcbiAgICAgICAgICBgRmlsZSBzaXplIGV4Y2VlZHMgbWF4aW11bSBhbGxvd2VkOiAke21heEJ5dGVzfSBieXRlcy5gXG4gICAgICAgICkpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG1pbWUgPSAoYXdhaXQgaW1wb3J0KCdtaW1lJykpLmRlZmF1bHQ7XG5cbiAgICAgIC8vIEluZmVyIGNvbnRlbnQgdHlwZSBmcm9tIGV4dGVuc2lvbiBvciBhZGQgZXh0ZW5zaW9uIGZyb20gY29udGVudCB0eXBlXG4gICAgICBjb25zdCBoYXNFeHRlbnNpb24gPSBmaWxlbmFtZSAmJiBmaWxlbmFtZS5pbmNsdWRlcygnLicpO1xuICAgICAgaWYgKGhhc0V4dGVuc2lvbiAmJiAhY29udGVudFR5cGUpIHtcbiAgICAgICAgY29udGVudFR5cGUgPSBtaW1lLmdldFR5cGUoZmlsZW5hbWUpO1xuICAgICAgfSBlbHNlIGlmICghaGFzRXh0ZW5zaW9uICYmIGNvbnRlbnRUeXBlKSB7XG4gICAgICAgIC8vIGV4dGVuc2lvbiB3aWxsIGJlIGFkZGVkIGJ5IGZpbGVzQ29udHJvbGxlci5jcmVhdGVGaWxlXG4gICAgICB9XG5cbiAgICAgIC8vIENyZWF0ZSBzaXplLWxpbWl0ZWQgc3RyZWFtIHdyYXBwaW5nIHRoZSByZXF1ZXN0XG4gICAgICBzdHJlYW0gPSBjcmVhdGVTaXplTGltaXRlZFN0cmVhbShyZXEsIG1heEJ5dGVzKTtcblxuICAgICAgLy8gQnVpbGQgYSBQYXJzZS5GaWxlIHdpdGggbm8gX2RhdGEgKHN0cmVhbWluZyBtb2RlKVxuICAgICAgY29uc3QgZmlsZSA9IG5ldyBQYXJzZS5GaWxlKGZpbGVuYW1lLCB7IGJhc2U2NDogJycgfSwgY29udGVudFR5cGUpO1xuICAgICAgY29uc3QgeyBtZXRhZGF0YSA9IHt9LCB0YWdzID0ge30sIGRpcmVjdG9yeSB9ID0gcmVxLmZpbGVEYXRhIHx8IHt9O1xuXG4gICAgICAvLyBWYWxpZGF0ZSBtZXRhZGF0YSBhbmQgdGFncyBmb3IgcHJvaGliaXRlZCBrZXl3b3Jkc1xuICAgICAgdHJ5IHtcbiAgICAgICAgVXRpbHMuY2hlY2tQcm9oaWJpdGVkS2V5d29yZHMoY29uZmlnLCBtZXRhZGF0YSk7XG4gICAgICAgIFV0aWxzLmNoZWNrUHJvaGliaXRlZEtleXdvcmRzKGNvbmZpZywgdGFncyk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBzdHJlYW0uZGVzdHJveSgpO1xuICAgICAgICBuZXh0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0tFWV9OQU1FLCBlcnJvcikpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGZpbGUuc2V0VGFncyh0YWdzKTtcbiAgICAgIGZpbGUuc2V0TWV0YWRhdGEobWV0YWRhdGEpO1xuICAgICAgaWYgKGRpcmVjdG9yeSkge1xuICAgICAgICBmaWxlLnNldERpcmVjdG9yeShkaXJlY3RvcnkpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBmaWxlU2l6ZSA9IHJlcS5nZXQoJ0NvbnRlbnQtTGVuZ3RoJylcbiAgICAgICAgPyBwYXJzZUludChyZXEuZ2V0KCdDb250ZW50LUxlbmd0aCcpLCAxMClcbiAgICAgICAgOiBudWxsO1xuICAgICAgY29uc3QgZmlsZU9iamVjdCA9IHsgZmlsZSwgZmlsZVNpemUsIHN0cmVhbTogdHJ1ZSB9O1xuXG4gICAgICAvLyBSdW4gYmVmb3JlU2F2ZUZpbGUgdHJpZ2dlclxuICAgICAgY29uc3QgdHJpZ2dlclJlc3VsdCA9IGF3YWl0IHRyaWdnZXJzLm1heWJlUnVuRmlsZVRyaWdnZXIoXG4gICAgICAgIHRyaWdnZXJzLlR5cGVzLmJlZm9yZVNhdmUsXG4gICAgICAgIGZpbGVPYmplY3QsXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgcmVxLmF1dGhcbiAgICAgICk7XG5cbiAgICAgIGxldCBzYXZlUmVzdWx0O1xuICAgICAgLy8gSWYgYSBuZXcgUGFyc2VGaWxlIGlzIHJldHVybmVkLCBjaGVjayBpZiBpdCdzIGFuIGFscmVhZHkgc2F2ZWQgZmlsZVxuICAgICAgaWYgKHRyaWdnZXJSZXN1bHQgaW5zdGFuY2VvZiBQYXJzZS5GaWxlKSB7XG4gICAgICAgIGZpbGVPYmplY3QuZmlsZSA9IHRyaWdnZXJSZXN1bHQ7XG4gICAgICAgIGlmICh0cmlnZ2VyUmVzdWx0LnVybCgpKSB7XG4gICAgICAgICAgZmlsZU9iamVjdC5maWxlU2l6ZSA9IG51bGw7XG4gICAgICAgICAgc2F2ZVJlc3VsdCA9IHtcbiAgICAgICAgICAgIHVybDogdHJpZ2dlclJlc3VsdC51cmwoKSxcbiAgICAgICAgICAgIG5hbWU6IHRyaWdnZXJSZXN1bHQuX25hbWUsXG4gICAgICAgICAgfTtcbiAgICAgICAgICAvLyBEZXN0cm95IHN0cmVhbSB0byByZW1vdmUgbGlzdGVuZXJzIGFuZCBkcmFpbiByZXF1ZXN0XG4gICAgICAgICAgc3RyZWFtLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBJZiB0aGUgZmlsZSByZXR1cm5lZCBieSB0aGUgdHJpZ2dlciBoYXMgYWxyZWFkeSBiZWVuIHNhdmVkLCBza2lwIHNhdmluZ1xuICAgICAgaWYgKCFzYXZlUmVzdWx0KSB7XG4gICAgICAgIC8vIFByZXBhcmUgZmlsZSBvcHRpb25zXG4gICAgICAgIGNvbnN0IGZpbGVPcHRpb25zID0ge1xuICAgICAgICAgIG1ldGFkYXRhOiBmaWxlT2JqZWN0LmZpbGUuX21ldGFkYXRhLFxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBmaWxlVGFncyA9XG4gICAgICAgICAgT2JqZWN0LmtleXMoZmlsZU9iamVjdC5maWxlLl90YWdzKS5sZW5ndGggPiAwID8geyB0YWdzOiBmaWxlT2JqZWN0LmZpbGUuX3RhZ3MgfSA6IHt9O1xuICAgICAgICBPYmplY3QuYXNzaWduKGZpbGVPcHRpb25zLCBmaWxlVGFncyk7XG4gICAgICAgIC8vIGluY2x1ZGUgZGlyZWN0b3J5IGlmIHNldCAoZnJvbSBjbGllbnQgcmVxdWVzdCBvciBiZWZvcmVTYXZlRmlsZSB0cmlnZ2VyKVxuICAgICAgICBpZiAoZmlsZU9iamVjdC5maWxlLl9kaXJlY3RvcnkpIHtcbiAgICAgICAgICBmaWxlT3B0aW9ucy5kaXJlY3RvcnkgPSBmaWxlT2JqZWN0LmZpbGUuX2RpcmVjdG9yeTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFBhc3Mgc3RyZWFtIGRpcmVjdGx5IHRvIGZpbGVzQ29udHJvbGxlciDigJQgaXQgd2lsbCBidWZmZXIgaWYgYWRhcHRlciBkb2Vzbid0IHN1cHBvcnQgc3RyZWFtaW5nXG4gICAgICAgIGNvbnN0IHNvdXJjZVR5cGUgPSBmaWxlT2JqZWN0LmZpbGUuX3NvdXJjZT8udHlwZSB8fCBjb250ZW50VHlwZTtcbiAgICAgICAgY29uc3QgY3JlYXRlRmlsZVJlc3VsdCA9IGF3YWl0IGZpbGVzQ29udHJvbGxlci5jcmVhdGVGaWxlKFxuICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICBmaWxlT2JqZWN0LmZpbGUuX25hbWUsXG4gICAgICAgICAgc3RyZWFtLFxuICAgICAgICAgIHNvdXJjZVR5cGUsXG4gICAgICAgICAgZmlsZU9wdGlvbnNcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBVcGRhdGUgZmlsZSB3aXRoIG5ldyBkYXRhXG4gICAgICAgIGZpbGVPYmplY3QuZmlsZS5fbmFtZSA9IGNyZWF0ZUZpbGVSZXN1bHQubmFtZTtcbiAgICAgICAgZmlsZU9iamVjdC5maWxlLl91cmwgPSBjcmVhdGVGaWxlUmVzdWx0LnVybDtcbiAgICAgICAgZmlsZU9iamVjdC5maWxlLl9yZXF1ZXN0VGFzayA9IG51bGw7XG4gICAgICAgIGZpbGVPYmplY3QuZmlsZS5fcHJldmlvdXNTYXZlID0gUHJvbWlzZS5yZXNvbHZlKGZpbGVPYmplY3QuZmlsZSk7XG4gICAgICAgIHNhdmVSZXN1bHQgPSB7XG4gICAgICAgICAgdXJsOiBjcmVhdGVGaWxlUmVzdWx0LnVybCxcbiAgICAgICAgICBuYW1lOiBjcmVhdGVGaWxlUmVzdWx0Lm5hbWUsXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIFJ1biBhZnRlclNhdmVGaWxlIHRyaWdnZXJcbiAgICAgIGF3YWl0IHRyaWdnZXJzLm1heWJlUnVuRmlsZVRyaWdnZXIodHJpZ2dlcnMuVHlwZXMuYWZ0ZXJTYXZlLCBmaWxlT2JqZWN0LCBjb25maWcsIHJlcS5hdXRoKTtcbiAgICAgIHJlcy5zdGF0dXMoMjAxKTtcbiAgICAgIHJlcy5zZXQoJ0xvY2F0aW9uJywgc2F2ZVJlc3VsdC51cmwpO1xuICAgICAgcmVzLmpzb24oc2F2ZVJlc3VsdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLy8gRGVzdHJveSBzdHJlYW0gdG8gcmVtb3ZlIGxpc3RlbmVycyBhbmQgZHJhaW4gcmVxdWVzdCwgb3IgcmVzdW1lIGRpcmVjdGx5XG4gICAgICBpZiAoc3RyZWFtKSB7XG4gICAgICAgIHN0cmVhbS5kZXN0cm95KCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXEucmVzdW1lKCk7XG4gICAgICB9XG4gICAgICBsb2dnZXIuZXJyb3IoJ0Vycm9yIGNyZWF0aW5nIGEgZmlsZTogJywgZSk7XG4gICAgICBjb25zdCBlcnJvciA9IHRyaWdnZXJzLnJlc29sdmVFcnJvcihlLCB7XG4gICAgICAgIGNvZGU6IFBhcnNlLkVycm9yLkZJTEVfU0FWRV9FUlJPUixcbiAgICAgICAgbWVzc2FnZTogYENvdWxkIG5vdCBzdG9yZSBmaWxlOiAke2ZpbGVuYW1lfS5gLFxuICAgICAgfSk7XG4gICAgICBuZXh0KGVycm9yKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBkZWxldGVIYW5kbGVyKHJlcSwgcmVzLCBuZXh0KSB7XG4gICAgaWYgKHJlcS5hdXRoLmlzUmVhZE9ubHkpIHtcbiAgICAgIGNvbnN0IGVycm9yID0gY3JlYXRlU2FuaXRpemVkSHR0cEVycm9yKDQwMywgXCJyZWFkLW9ubHkgbWFzdGVyS2V5IGlzbid0IGFsbG93ZWQgdG8gZGVsZXRlIGEgZmlsZS5cIiwgcmVxLmNvbmZpZyk7XG4gICAgICByZXMuc3RhdHVzKGVycm9yLnN0YXR1cyk7XG4gICAgICByZXMuZW5kKGB7XCJlcnJvclwiOlwiJHtlcnJvci5tZXNzYWdlfVwifWApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgY29uc3QgeyBmaWxlc0NvbnRyb2xsZXIgfSA9IHJlcS5jb25maWc7XG4gICAgICBjb25zdCBmaWxlbmFtZSA9IEZpbGVzUm91dGVyLl9nZXRGaWxlbmFtZUZyb21QYXJhbXMocmVxKTtcbiAgICAgIC8vIHJ1biBiZWZvcmVEZWxldGVGaWxlIHRyaWdnZXJcbiAgICAgIGNvbnN0IGZpbGUgPSBuZXcgUGFyc2UuRmlsZShmaWxlbmFtZSk7XG4gICAgICBmaWxlLl91cmwgPSBhd2FpdCBmaWxlc0NvbnRyb2xsZXIuYWRhcHRlci5nZXRGaWxlTG9jYXRpb24ocmVxLmNvbmZpZywgZmlsZW5hbWUpO1xuICAgICAgY29uc3QgZmlsZU9iamVjdCA9IHsgZmlsZSwgZmlsZVNpemU6IG51bGwgfTtcbiAgICAgIGF3YWl0IHRyaWdnZXJzLm1heWJlUnVuRmlsZVRyaWdnZXIoXG4gICAgICAgIHRyaWdnZXJzLlR5cGVzLmJlZm9yZURlbGV0ZSxcbiAgICAgICAgZmlsZU9iamVjdCxcbiAgICAgICAgcmVxLmNvbmZpZyxcbiAgICAgICAgcmVxLmF1dGhcbiAgICAgICk7XG4gICAgICAvLyBkZWxldGUgZmlsZVxuICAgICAgYXdhaXQgZmlsZXNDb250cm9sbGVyLmRlbGV0ZUZpbGUocmVxLmNvbmZpZywgZmlsZW5hbWUpO1xuICAgICAgLy8gcnVuIGFmdGVyRGVsZXRlRmlsZSB0cmlnZ2VyXG4gICAgICBhd2FpdCB0cmlnZ2Vycy5tYXliZVJ1bkZpbGVUcmlnZ2VyKFxuICAgICAgICB0cmlnZ2Vycy5UeXBlcy5hZnRlckRlbGV0ZSxcbiAgICAgICAgZmlsZU9iamVjdCxcbiAgICAgICAgcmVxLmNvbmZpZyxcbiAgICAgICAgcmVxLmF1dGhcbiAgICAgICk7XG4gICAgICByZXMuc3RhdHVzKDIwMCk7XG4gICAgICAvLyBUT0RPOiByZXR1cm4gdXNlZnVsIEpTT04gaGVyZT9cbiAgICAgIHJlcy5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ0Vycm9yIGRlbGV0aW5nIGEgZmlsZTogJywgZSk7XG4gICAgICBjb25zdCBlcnJvciA9IHRyaWdnZXJzLnJlc29sdmVFcnJvcihlLCB7XG4gICAgICAgIGNvZGU6IFBhcnNlLkVycm9yLkZJTEVfREVMRVRFX0VSUk9SLFxuICAgICAgICBtZXNzYWdlOiAnQ291bGQgbm90IGRlbGV0ZSBmaWxlLicsXG4gICAgICB9KTtcbiAgICAgIG5leHQoZXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIG1ldGFkYXRhSGFuZGxlcihyZXEsIHJlcykge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBjb25maWcgPSBDb25maWcuZ2V0KHJlcS5wYXJhbXMuYXBwSWQpO1xuICAgICAgaWYgKCFjb25maWcpIHtcbiAgICAgICAgcmVzLnN0YXR1cygyMDApO1xuICAgICAgICByZXMuanNvbih7fSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIEZpbGVzUm91dGVyLl92YWxpZGF0ZUZpbGVEb3dubG9hZChyZXEsIGNvbmZpZyk7XG4gICAgICBjb25zdCB7IGZpbGVzQ29udHJvbGxlciB9ID0gY29uZmlnO1xuICAgICAgbGV0IGZpbGVuYW1lID0gRmlsZXNSb3V0ZXIuX2dldEZpbGVuYW1lRnJvbVBhcmFtcyhyZXEpO1xuICAgICAgY29uc3QgZmlsZSA9IG5ldyBQYXJzZS5GaWxlKGZpbGVuYW1lLCB7IGJhc2U2NDogJycgfSk7XG4gICAgICBjb25zdCBmaWxlQXV0aCA9IHJlcS5hdXRoO1xuICAgICAgY29uc3QgdHJpZ2dlclJlc3VsdCA9IGF3YWl0IHRyaWdnZXJzLm1heWJlUnVuRmlsZVRyaWdnZXIoXG4gICAgICAgIHRyaWdnZXJzLlR5cGVzLmJlZm9yZUZpbmQsXG4gICAgICAgIHsgZmlsZSB9LFxuICAgICAgICBjb25maWcsXG4gICAgICAgIGZpbGVBdXRoXG4gICAgICApO1xuICAgICAgaWYgKHRyaWdnZXJSZXN1bHQ/LmZpbGU/Ll9uYW1lKSB7XG4gICAgICAgIGZpbGVuYW1lID0gdHJpZ2dlclJlc3VsdC5maWxlLl9uYW1lO1xuICAgICAgfVxuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGZpbGVzQ29udHJvbGxlci5nZXRNZXRhZGF0YShmaWxlbmFtZSkuY2F0Y2goKCkgPT4ge1xuICAgICAgICByZXMuc3RhdHVzKDIwMCk7XG4gICAgICAgIHJlcy5qc29uKHt9KTtcbiAgICAgIH0pO1xuICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGF3YWl0IHRyaWdnZXJzLm1heWJlUnVuRmlsZVRyaWdnZXIoXG4gICAgICAgIHRyaWdnZXJzLlR5cGVzLmFmdGVyRmluZCxcbiAgICAgICAgeyBmaWxlIH0sXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgZmlsZUF1dGhcbiAgICAgICk7XG4gICAgICByZXMuc3RhdHVzKDIwMCk7XG4gICAgICByZXMuanNvbihkYXRhKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zdCBlcnIgPSB0cmlnZ2Vycy5yZXNvbHZlRXJyb3IoZSwge1xuICAgICAgICBjb2RlOiBQYXJzZS5FcnJvci5TQ1JJUFRfRkFJTEVELFxuICAgICAgICBtZXNzYWdlOiAnQ291bGQgbm90IGdldCBmaWxlIG1ldGFkYXRhLicsXG4gICAgICB9KTtcbiAgICAgIHJlcy5zdGF0dXMoNDAzKTtcbiAgICAgIHJlcy5qc29uKHsgY29kZTogZXJyLmNvZGUsIGVycm9yOiBlcnIubWVzc2FnZSB9KTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gaXNGaWxlU3RyZWFtYWJsZShyZXEsIGZpbGVzQ29udHJvbGxlcikge1xuICBjb25zdCByYW5nZSA9IChyZXEuZ2V0KCdSYW5nZScpIHx8ICcvLS8nKS5zcGxpdCgnLScpO1xuICBjb25zdCBzdGFydCA9IE51bWJlcihyYW5nZVswXSk7XG4gIGNvbnN0IGVuZCA9IE51bWJlcihyYW5nZVsxXSk7XG4gIHJldHVybiAoXG4gICAgKCFpc05hTihzdGFydCkgfHwgIWlzTmFOKGVuZCkpICYmIHR5cGVvZiBmaWxlc0NvbnRyb2xsZXIuYWRhcHRlci5oYW5kbGVGaWxlU3RyZWFtID09PSAnZnVuY3Rpb24nXG4gICk7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQSxJQUFBQSxRQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxXQUFBLEdBQUFDLHVCQUFBLENBQUFGLE9BQUE7QUFDQSxJQUFBRyxLQUFBLEdBQUFKLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBSSxPQUFBLEdBQUFMLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBSyxPQUFBLEdBQUFOLHNCQUFBLENBQUFDLE9BQUE7QUFHQSxJQUFBTSxPQUFBLEdBQUFOLE9BQUE7QUFDQSxJQUFBTyxNQUFBLEdBQUFQLE9BQUE7QUFBb0QsU0FBQUUsd0JBQUFNLENBQUEsRUFBQUMsQ0FBQSw2QkFBQUMsT0FBQSxNQUFBQyxDQUFBLE9BQUFELE9BQUEsSUFBQUUsQ0FBQSxPQUFBRixPQUFBLFlBQUFSLHVCQUFBLFlBQUFBLENBQUFNLENBQUEsRUFBQUMsQ0FBQSxTQUFBQSxDQUFBLElBQUFELENBQUEsSUFBQUEsQ0FBQSxDQUFBSyxVQUFBLFNBQUFMLENBQUEsTUFBQU0sQ0FBQSxFQUFBQyxDQUFBLEVBQUFDLENBQUEsS0FBQUMsU0FBQSxRQUFBQyxPQUFBLEVBQUFWLENBQUEsaUJBQUFBLENBQUEsdUJBQUFBLENBQUEseUJBQUFBLENBQUEsU0FBQVEsQ0FBQSxNQUFBRixDQUFBLEdBQUFMLENBQUEsR0FBQUcsQ0FBQSxHQUFBRCxDQUFBLFFBQUFHLENBQUEsQ0FBQUssR0FBQSxDQUFBWCxDQUFBLFVBQUFNLENBQUEsQ0FBQU0sR0FBQSxDQUFBWixDQUFBLEdBQUFNLENBQUEsQ0FBQU8sR0FBQSxDQUFBYixDQUFBLEVBQUFRLENBQUEsZ0JBQUFQLENBQUEsSUFBQUQsQ0FBQSxnQkFBQUMsQ0FBQSxPQUFBYSxjQUFBLENBQUFDLElBQUEsQ0FBQWYsQ0FBQSxFQUFBQyxDQUFBLE9BQUFNLENBQUEsSUFBQUQsQ0FBQSxHQUFBVSxNQUFBLENBQUFDLGNBQUEsS0FBQUQsTUFBQSxDQUFBRSx3QkFBQSxDQUFBbEIsQ0FBQSxFQUFBQyxDQUFBLE9BQUFNLENBQUEsQ0FBQUssR0FBQSxJQUFBTCxDQUFBLENBQUFNLEdBQUEsSUFBQVAsQ0FBQSxDQUFBRSxDQUFBLEVBQUFQLENBQUEsRUFBQU0sQ0FBQSxJQUFBQyxDQUFBLENBQUFQLENBQUEsSUFBQUQsQ0FBQSxDQUFBQyxDQUFBLFdBQUFPLENBQUEsS0FBQVIsQ0FBQSxFQUFBQyxDQUFBO0FBQUEsU0FBQVYsdUJBQUFTLENBQUEsV0FBQUEsQ0FBQSxJQUFBQSxDQUFBLENBQUFLLFVBQUEsR0FBQUwsQ0FBQSxLQUFBVSxPQUFBLEVBQUFWLENBQUE7QUFIcEQsTUFBTW1CLFFBQVEsR0FBRzNCLE9BQU8sQ0FBQyxhQUFhLENBQUM7QUFDdkMsTUFBTTRCLEtBQUssR0FBRzVCLE9BQU8sQ0FBQyxVQUFVLENBQUM7QUFJakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sU0FBUzZCLHVCQUF1QkEsQ0FBQ0MsTUFBTSxFQUFFQyxRQUFRLEVBQUU7RUFDeEQsSUFBSUMsVUFBVSxHQUFHLENBQUM7RUFDbEIsSUFBSUMsT0FBTyxHQUFHLEtBQUs7RUFDbkIsSUFBSUMsV0FBVyxHQUFHLEtBQUs7RUFDdkIsSUFBSUMsTUFBTSxFQUFFQyxLQUFLLEVBQUVDLE9BQU87RUFFMUIsTUFBTUMsTUFBTSxHQUFHLElBQUlDLGdCQUFRLENBQUM7SUFDMUJDLElBQUlBLENBQUEsRUFBRztNQUNMLElBQUksQ0FBQ1AsT0FBTyxFQUFFO1FBQ1pBLE9BQU8sR0FBRyxJQUFJO1FBRWRFLE1BQU0sR0FBSU0sS0FBSyxJQUFLO1VBQ2xCVCxVQUFVLElBQUlTLEtBQUssQ0FBQ0MsTUFBTTtVQUMxQixJQUFJVixVQUFVLEdBQUdELFFBQVEsRUFBRTtZQUN6Qk8sTUFBTSxDQUFDSyxPQUFPLENBQ1osSUFBSUMsYUFBSyxDQUFDQyxLQUFLLENBQ2JELGFBQUssQ0FBQ0MsS0FBSyxDQUFDQyxlQUFlLEVBQzNCLHNDQUFzQ2YsUUFBUSxTQUNoRCxDQUNGLENBQUM7WUFDRDtVQUNGO1VBQ0EsSUFBSSxDQUFDTyxNQUFNLENBQUNTLElBQUksQ0FBQ04sS0FBSyxDQUFDLEVBQUU7WUFDdkJYLE1BQU0sQ0FBQ2tCLEtBQUssQ0FBQyxDQUFDO1VBQ2hCO1FBQ0YsQ0FBQztRQUVEWixLQUFLLEdBQUdBLENBQUEsS0FBTTtVQUNaRixXQUFXLEdBQUcsSUFBSTtVQUNsQkksTUFBTSxDQUFDUyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBQ25CLENBQUM7UUFFRFYsT0FBTyxHQUFJWSxHQUFHLElBQUtYLE1BQU0sQ0FBQ0ssT0FBTyxDQUFDTSxHQUFHLENBQUM7UUFFdENuQixNQUFNLENBQUNvQixFQUFFLENBQUMsTUFBTSxFQUFFZixNQUFNLENBQUM7UUFDekJMLE1BQU0sQ0FBQ29CLEVBQUUsQ0FBQyxLQUFLLEVBQUVkLEtBQUssQ0FBQztRQUN2Qk4sTUFBTSxDQUFDb0IsRUFBRSxDQUFDLE9BQU8sRUFBRWIsT0FBTyxDQUFDO01BQzdCOztNQUVBO01BQ0EsSUFBSSxDQUFDSCxXQUFXLEVBQUU7UUFDaEJKLE1BQU0sQ0FBQ3FCLE1BQU0sQ0FBQyxDQUFDO01BQ2pCO0lBQ0YsQ0FBQztJQUNEUixPQUFPQSxDQUFDTSxHQUFHLEVBQUVHLFFBQVEsRUFBRTtNQUNyQixJQUFJakIsTUFBTSxFQUFFO1FBQ1ZMLE1BQU0sQ0FBQ3VCLGNBQWMsQ0FBQyxNQUFNLEVBQUVsQixNQUFNLENBQUM7TUFDdkM7TUFDQSxJQUFJQyxLQUFLLEVBQUU7UUFDVE4sTUFBTSxDQUFDdUIsY0FBYyxDQUFDLEtBQUssRUFBRWpCLEtBQUssQ0FBQztNQUNyQztNQUNBLElBQUlDLE9BQU8sRUFBRTtRQUNYUCxNQUFNLENBQUN1QixjQUFjLENBQUMsT0FBTyxFQUFFaEIsT0FBTyxDQUFDO01BQ3pDO01BQ0E7TUFDQVAsTUFBTSxDQUFDb0IsRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO01BQzVCLElBQUksQ0FBQ2hCLFdBQVcsRUFBRTtRQUNoQkosTUFBTSxDQUFDcUIsTUFBTSxDQUFDLENBQUM7TUFDakI7TUFDQUMsUUFBUSxDQUFDSCxHQUFHLENBQUM7SUFDZjtFQUNGLENBQUMsQ0FBQztFQUVGLE9BQU9YLE1BQU07QUFDZjs7QUFFQTtBQUNBO0FBQ0E7QUFDTyxNQUFNZ0IsMkJBQTJCLEdBQUFDLE9BQUEsQ0FBQUQsMkJBQUEsR0FBRyxDQUFDLFVBQVUsQ0FBQztBQUVoRCxNQUFNRSxXQUFXLENBQUM7RUFDdkJDLGFBQWFBLENBQUM7SUFBRUMsYUFBYSxHQUFHO0VBQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFO0lBQzdDLElBQUlDLE1BQU0sR0FBR0MsZ0JBQU8sQ0FBQ0MsTUFBTSxDQUFDLENBQUM7SUFDN0I7SUFDQTtJQUNBO0lBQ0EsTUFBTUMsUUFBUSxHQUFHQSxDQUFDQyxHQUFHLEVBQUVDLEdBQUcsRUFBRUMsSUFBSSxLQUFLO01BQ25DLElBQUksQ0FBQ0YsR0FBRyxDQUFDRyxJQUFJLEVBQUU7UUFDYixNQUFNQyxZQUFZLEdBQUdKLEdBQUcsQ0FBQzNDLEdBQUcsQ0FBQyx1QkFBdUIsQ0FBQztRQUNyRDJDLEdBQUcsQ0FBQ0csSUFBSSxHQUFHO1VBQ1RDLFlBQVk7VUFDWkMsY0FBYyxFQUFFTCxHQUFHLENBQUMzQyxHQUFHLENBQUMseUJBQXlCO1FBQ25ELENBQUM7UUFDRDtRQUNBO1FBQ0EsSUFBSSxDQUFDK0MsWUFBWSxJQUFJLENBQUNKLEdBQUcsQ0FBQ00sSUFBSSxFQUFFO1VBQzlCTixHQUFHLENBQUNNLElBQUksR0FBRztZQUFFQyxRQUFRLEVBQUU7VUFBTSxDQUFDO1FBQ2hDO01BQ0Y7TUFDQUwsSUFBSSxDQUFDLENBQUM7SUFDUixDQUFDO0lBQ0Q7SUFDQU4sTUFBTSxDQUFDdkMsR0FBRyxDQUFDLGtDQUFrQyxFQUFFMEMsUUFBUSxFQUFFN0QsV0FBVyxDQUFDc0Usa0JBQWtCLEVBQUUsSUFBSSxDQUFDQyxlQUFlLENBQUM7SUFDOUdiLE1BQU0sQ0FBQ3ZDLEdBQUcsQ0FBQyx5QkFBeUIsRUFBRTBDLFFBQVEsRUFBRTdELFdBQVcsQ0FBQ3NFLGtCQUFrQixFQUFFLElBQUksQ0FBQ0UsVUFBVSxDQUFDO0lBRWhHZCxNQUFNLENBQUNlLElBQUksQ0FBQyxRQUFRLEVBQUUsVUFBVVgsR0FBRyxFQUFFQyxHQUFHLEVBQUVDLElBQUksRUFBRTtNQUM5Q0EsSUFBSSxDQUFDLElBQUlyQixhQUFLLENBQUNDLEtBQUssQ0FBQ0QsYUFBSyxDQUFDQyxLQUFLLENBQUM4QixpQkFBaUIsRUFBRSx3QkFBd0IsQ0FBQyxDQUFDO0lBQ2hGLENBQUMsQ0FBQztJQUVGaEIsTUFBTSxDQUFDZSxJQUFJLENBQ1Qsa0JBQWtCLEVBQ2xCLElBQUksQ0FBQ0UsdUJBQXVCLENBQUMsQ0FBQyxFQUM5QixJQUFJLENBQUNDLHNCQUFzQixDQUFDbkIsYUFBYSxDQUFDLEVBQzFDekQsV0FBVyxDQUFDNkUsa0JBQWtCLEVBQzlCN0UsV0FBVyxDQUFDc0Usa0JBQWtCLEVBQzlCLElBQUksQ0FBQ1EsYUFBYSxDQUFDQyxJQUFJLENBQUMsSUFBSSxDQUM5QixDQUFDO0lBRURyQixNQUFNLENBQUNzQixNQUFNLENBQ1gsa0JBQWtCLEVBQ2xCaEYsV0FBVyxDQUFDNkUsa0JBQWtCLEVBQzlCN0UsV0FBVyxDQUFDc0Usa0JBQWtCLEVBQzlCdEUsV0FBVyxDQUFDaUYsc0JBQXNCLEVBQ2xDLElBQUksQ0FBQ0MsYUFDUCxDQUFDO0lBQ0QsT0FBT3hCLE1BQU07RUFDZjtFQUVBLE9BQU95QixzQkFBc0JBLENBQUNyQixHQUFHLEVBQUU7SUFDakMsTUFBTXNCLEtBQUssR0FBR3RCLEdBQUcsQ0FBQ3VCLE1BQU0sQ0FBQ0MsUUFBUTtJQUNqQyxPQUFPQyxLQUFLLENBQUNDLE9BQU8sQ0FBQ0osS0FBSyxDQUFDLEdBQUdBLEtBQUssQ0FBQ0ssSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHTCxLQUFLO0VBQ3ZEO0VBRUEsT0FBT00saUJBQWlCQSxDQUFDQyxTQUFTLEVBQUU7SUFDbEMsSUFBSSxPQUFPQSxTQUFTLEtBQUssUUFBUSxFQUFFO01BQ2pDLE9BQU8sSUFBSWhELGFBQUssQ0FBQ0MsS0FBSyxDQUFDRCxhQUFLLENBQUNDLEtBQUssQ0FBQzhCLGlCQUFpQixFQUFFLDZCQUE2QixDQUFDO0lBQ3RGO0lBQ0EsSUFBSWlCLFNBQVMsQ0FBQ2xELE1BQU0sS0FBSyxDQUFDLEVBQUU7TUFDMUIsT0FBTyxJQUFJRSxhQUFLLENBQUNDLEtBQUssQ0FBQ0QsYUFBSyxDQUFDQyxLQUFLLENBQUM4QixpQkFBaUIsRUFBRSw4QkFBOEIsQ0FBQztJQUN2RjtJQUNBLElBQUlpQixTQUFTLENBQUNsRCxNQUFNLEdBQUcsR0FBRyxFQUFFO01BQzFCLE9BQU8sSUFBSUUsYUFBSyxDQUFDQyxLQUFLLENBQUNELGFBQUssQ0FBQ0MsS0FBSyxDQUFDOEIsaUJBQWlCLEVBQUUsNkJBQTZCLENBQUM7SUFDdEY7SUFDQSxJQUFJaUIsU0FBUyxDQUFDQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUU7TUFDNUIsT0FBTyxJQUFJakQsYUFBSyxDQUFDQyxLQUFLLENBQUNELGFBQUssQ0FBQ0MsS0FBSyxDQUFDOEIsaUJBQWlCLEVBQUUsa0NBQWtDLENBQUM7SUFDM0Y7SUFDQSxJQUFJaUIsU0FBUyxDQUFDRSxVQUFVLENBQUMsR0FBRyxDQUFDLElBQUlGLFNBQVMsQ0FBQ0csUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFO01BQ3hELE9BQU8sSUFBSW5ELGFBQUssQ0FBQ0MsS0FBSyxDQUNwQkQsYUFBSyxDQUFDQyxLQUFLLENBQUM4QixpQkFBaUIsRUFDN0IsMkNBQ0YsQ0FBQztJQUNIO0lBQ0EsSUFBSWlCLFNBQVMsQ0FBQ0MsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFO01BQzVCLE9BQU8sSUFBSWpELGFBQUssQ0FBQ0MsS0FBSyxDQUNwQkQsYUFBSyxDQUFDQyxLQUFLLENBQUM4QixpQkFBaUIsRUFDN0IsaURBQ0YsQ0FBQztJQUNIO0lBQ0EsTUFBTXFCLFlBQVksR0FBR0osU0FBUyxDQUFDSyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVDLElBQUkzQywyQkFBMkIsQ0FBQ3VDLFFBQVEsQ0FBQ0csWUFBWSxDQUFDLEVBQUU7TUFDdEQsT0FBTyxJQUFJcEQsYUFBSyxDQUFDQyxLQUFLLENBQ3BCRCxhQUFLLENBQUNDLEtBQUssQ0FBQzhCLGlCQUFpQixFQUM3QixtREFBbURxQixZQUFZLElBQ2pFLENBQUM7SUFDSDtJQUNBLE1BQU1FLFFBQVEsR0FBRywrQkFBK0I7SUFDaEQsSUFBSSxDQUFDQSxRQUFRLENBQUNDLElBQUksQ0FBQ1AsU0FBUyxDQUFDLEVBQUU7TUFDN0IsT0FBTyxJQUFJaEQsYUFBSyxDQUFDQyxLQUFLLENBQ3BCRCxhQUFLLENBQUNDLEtBQUssQ0FBQzhCLGlCQUFpQixFQUM3Qix3Q0FDRixDQUFDO0lBQ0g7SUFDQSxPQUFPLElBQUk7RUFDYjtFQUVBLE9BQU95QixxQkFBcUJBLENBQUNyQyxHQUFHLEVBQUVzQyxNQUFNLEVBQUU7SUFDeEMsTUFBTS9CLFFBQVEsR0FBR1AsR0FBRyxDQUFDTSxJQUFJLEVBQUVDLFFBQVE7SUFDbkMsTUFBTWdDLGFBQWEsR0FBR3ZDLEdBQUcsQ0FBQ00sSUFBSSxFQUFFaUMsYUFBYTtJQUM3QyxJQUFJaEMsUUFBUSxJQUFJZ0MsYUFBYSxFQUFFO01BQzdCO0lBQ0Y7SUFDQSxNQUFNQyxJQUFJLEdBQUd4QyxHQUFHLENBQUNNLElBQUksRUFBRWtDLElBQUk7SUFDM0IsTUFBTUMsUUFBUSxHQUFHRCxJQUFJLElBQUkzRCxhQUFLLENBQUM2RCxjQUFjLENBQUNELFFBQVEsQ0FBQ0QsSUFBSSxDQUFDO0lBQzVELElBQUksQ0FBQ0YsTUFBTSxDQUFDSyxZQUFZLENBQUNDLHNCQUFzQixJQUFJSCxRQUFRLEVBQUU7TUFDM0QsTUFBTSxJQUFJNUQsYUFBSyxDQUFDQyxLQUFLLENBQ25CRCxhQUFLLENBQUNDLEtBQUssQ0FBQytELG1CQUFtQixFQUMvQiw4Q0FDRixDQUFDO0lBQ0g7SUFDQSxJQUFJLENBQUNQLE1BQU0sQ0FBQ0ssWUFBWSxDQUFDRywwQkFBMEIsSUFBSSxDQUFDTCxRQUFRLElBQUlELElBQUksRUFBRTtNQUN4RSxNQUFNLElBQUkzRCxhQUFLLENBQUNDLEtBQUssQ0FDbkJELGFBQUssQ0FBQ0MsS0FBSyxDQUFDK0QsbUJBQW1CLEVBQy9CLGtEQUNGLENBQUM7SUFDSDtJQUNBLElBQUksQ0FBQ1AsTUFBTSxDQUFDSyxZQUFZLENBQUNJLGVBQWUsSUFBSSxDQUFDUCxJQUFJLEVBQUU7TUFDakQsTUFBTSxJQUFJM0QsYUFBSyxDQUFDQyxLQUFLLENBQ25CRCxhQUFLLENBQUNDLEtBQUssQ0FBQytELG1CQUFtQixFQUMvQixzQ0FDRixDQUFDO0lBQ0g7RUFDRjtFQUVBLE1BQU1uQyxVQUFVQSxDQUFDVixHQUFHLEVBQUVDLEdBQUcsRUFBRTtJQUN6QixNQUFNcUMsTUFBTSxHQUFHVSxlQUFNLENBQUMzRixHQUFHLENBQUMyQyxHQUFHLENBQUN1QixNQUFNLENBQUMwQixLQUFLLENBQUM7SUFDM0MsSUFBSSxDQUFDWCxNQUFNLEVBQUU7TUFDWCxNQUFNWSxLQUFLLEdBQUcsSUFBQUMsK0JBQXdCLEVBQUMsR0FBRyxFQUFFLHlCQUF5QixFQUFFYixNQUFNLENBQUM7TUFDOUVyQyxHQUFHLENBQUNtRCxNQUFNLENBQUNGLEtBQUssQ0FBQ0UsTUFBTSxDQUFDO01BQ3hCbkQsR0FBRyxDQUFDb0QsSUFBSSxDQUFDO1FBQUVILEtBQUssRUFBRUEsS0FBSyxDQUFDSTtNQUFRLENBQUMsQ0FBQztNQUNsQztJQUNGO0lBRUE3RCxXQUFXLENBQUM0QyxxQkFBcUIsQ0FBQ3JDLEdBQUcsRUFBRXNDLE1BQU0sQ0FBQztJQUU5QyxJQUFJaUIsUUFBUSxHQUFHOUQsV0FBVyxDQUFDNEIsc0JBQXNCLENBQUNyQixHQUFHLENBQUM7SUFDdEQsSUFBSTtNQUNGLE1BQU13RCxlQUFlLEdBQUdsQixNQUFNLENBQUNrQixlQUFlO01BQzlDLE1BQU1DLElBQUksR0FBRyxDQUFDLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFdEcsT0FBTztNQUMzQyxJQUFJdUcsV0FBVyxHQUFHRCxJQUFJLENBQUNFLE9BQU8sQ0FBQ0osUUFBUSxDQUFDO01BQ3hDLElBQUlLLElBQUksR0FBRyxJQUFJL0UsYUFBSyxDQUFDZ0YsSUFBSSxDQUFDTixRQUFRLEVBQUU7UUFBRU8sTUFBTSxFQUFFO01BQUcsQ0FBQyxFQUFFSixXQUFXLENBQUM7TUFDaEUsTUFBTUssUUFBUSxHQUFHL0QsR0FBRyxDQUFDTSxJQUFJO01BQ3pCLE1BQU0wRCxhQUFhLEdBQUcsTUFBTXBHLFFBQVEsQ0FBQ3FHLG1CQUFtQixDQUN0RHJHLFFBQVEsQ0FBQ3NHLEtBQUssQ0FBQ0MsVUFBVSxFQUN6QjtRQUFFUDtNQUFLLENBQUMsRUFDUnRCLE1BQU0sRUFDTnlCLFFBQ0YsQ0FBQztNQUNELElBQUlDLGFBQWEsRUFBRUosSUFBSSxFQUFFUSxLQUFLLEVBQUU7UUFDOUJiLFFBQVEsR0FBR1MsYUFBYSxFQUFFSixJQUFJLEVBQUVRLEtBQUs7UUFDckNWLFdBQVcsR0FBR0QsSUFBSSxDQUFDRSxPQUFPLENBQUNKLFFBQVEsQ0FBQztNQUN0QztNQUVBLE1BQU1jLHNCQUFzQixHQUFHO1FBQUUsd0JBQXdCLEVBQUU7TUFBVSxDQUFDO01BRXRFLElBQUlDLGdCQUFnQixDQUFDdEUsR0FBRyxFQUFFd0QsZUFBZSxDQUFDLEVBQUU7UUFDMUMsTUFBTWUsU0FBUyxHQUFHLE1BQU0zRyxRQUFRLENBQUNxRyxtQkFBbUIsQ0FDbERyRyxRQUFRLENBQUNzRyxLQUFLLENBQUNLLFNBQVMsRUFDeEI7VUFBRVgsSUFBSTtVQUFFWSxhQUFhLEVBQUUsS0FBSztVQUFFQyxlQUFlLEVBQUU7WUFBRSxHQUFHSjtVQUF1QjtRQUFFLENBQUMsRUFDOUUvQixNQUFNLEVBQ055QixRQUNGLENBQUM7UUFDRCxJQUFJUSxTQUFTLEVBQUVDLGFBQWEsRUFBRTtVQUM1QnZFLEdBQUcsQ0FBQzNDLEdBQUcsQ0FBQyxxQkFBcUIsRUFBRSx1QkFBdUJpSCxTQUFTLENBQUNYLElBQUksRUFBRVEsS0FBSyxJQUFJYixRQUFRLEVBQUUsQ0FBQztRQUM1RjtRQUNBLEtBQUssTUFBTSxDQUFDbUIsR0FBRyxFQUFFQyxLQUFLLENBQUMsSUFBSWxILE1BQU0sQ0FBQ21ILE9BQU8sQ0FBQ0wsU0FBUyxFQUFFRSxlQUFlLElBQUlKLHNCQUFzQixDQUFDLEVBQUU7VUFDL0ZwRSxHQUFHLENBQUMzQyxHQUFHLENBQUNvSCxHQUFHLEVBQUVDLEtBQUssQ0FBQztRQUNyQjtRQUNBbkIsZUFBZSxDQUFDcUIsZ0JBQWdCLENBQUN2QyxNQUFNLEVBQUVpQixRQUFRLEVBQUV2RCxHQUFHLEVBQUVDLEdBQUcsRUFBRXlELFdBQVcsQ0FBQyxDQUFDb0IsS0FBSyxDQUFDLE1BQU07VUFDcEY3RSxHQUFHLENBQUNtRCxNQUFNLENBQUMsR0FBRyxDQUFDO1VBQ2ZuRCxHQUFHLENBQUMzQyxHQUFHLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQztVQUNyQzJDLEdBQUcsQ0FBQzhFLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQztRQUM1QixDQUFDLENBQUM7UUFDRjtNQUNGO01BRUEsSUFBSUMsSUFBSSxHQUFHLE1BQU14QixlQUFlLENBQUN5QixXQUFXLENBQUMzQyxNQUFNLEVBQUVpQixRQUFRLENBQUMsQ0FBQ3VCLEtBQUssQ0FBQyxNQUFNO1FBQ3pFN0UsR0FBRyxDQUFDbUQsTUFBTSxDQUFDLEdBQUcsQ0FBQztRQUNmbkQsR0FBRyxDQUFDM0MsR0FBRyxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUM7UUFDckMyQyxHQUFHLENBQUM4RSxHQUFHLENBQUMsaUJBQWlCLENBQUM7TUFDNUIsQ0FBQyxDQUFDO01BQ0YsSUFBSSxDQUFDQyxJQUFJLEVBQUU7UUFDVDtNQUNGO01BQ0FwQixJQUFJLEdBQUcsSUFBSS9FLGFBQUssQ0FBQ2dGLElBQUksQ0FBQ04sUUFBUSxFQUFFO1FBQUVPLE1BQU0sRUFBRWtCLElBQUksQ0FBQ0UsUUFBUSxDQUFDLFFBQVE7TUFBRSxDQUFDLEVBQUV4QixXQUFXLENBQUM7TUFDakYsTUFBTWEsU0FBUyxHQUFHLE1BQU0zRyxRQUFRLENBQUNxRyxtQkFBbUIsQ0FDbERyRyxRQUFRLENBQUNzRyxLQUFLLENBQUNLLFNBQVMsRUFDeEI7UUFBRVgsSUFBSTtRQUFFWSxhQUFhLEVBQUUsS0FBSztRQUFFQyxlQUFlLEVBQUU7VUFBRSxHQUFHSjtRQUF1QjtNQUFFLENBQUMsRUFDOUUvQixNQUFNLEVBQ055QixRQUNGLENBQUM7TUFFRCxJQUFJUSxTQUFTLEVBQUVYLElBQUksRUFBRTtRQUNuQkYsV0FBVyxHQUFHRCxJQUFJLENBQUNFLE9BQU8sQ0FBQ1ksU0FBUyxDQUFDWCxJQUFJLENBQUNRLEtBQUssQ0FBQztRQUNoRFksSUFBSSxHQUFHRyxNQUFNLENBQUNDLElBQUksQ0FBQ2IsU0FBUyxDQUFDWCxJQUFJLENBQUN5QixLQUFLLEVBQUUsUUFBUSxDQUFDO01BQ3BEO01BRUFwRixHQUFHLENBQUNtRCxNQUFNLENBQUMsR0FBRyxDQUFDO01BQ2ZuRCxHQUFHLENBQUMzQyxHQUFHLENBQUMsY0FBYyxFQUFFb0csV0FBVyxDQUFDO01BQ3BDekQsR0FBRyxDQUFDM0MsR0FBRyxDQUFDLGdCQUFnQixFQUFFMEgsSUFBSSxDQUFDckcsTUFBTSxDQUFDO01BQ3RDLElBQUk0RixTQUFTLENBQUNDLGFBQWEsRUFBRTtRQUMzQnZFLEdBQUcsQ0FBQzNDLEdBQUcsQ0FBQyxxQkFBcUIsRUFBRSx1QkFBdUJpSCxTQUFTLENBQUNYLElBQUksQ0FBQ1EsS0FBSyxFQUFFLENBQUM7TUFDL0U7TUFDQSxJQUFJRyxTQUFTLENBQUNFLGVBQWUsRUFBRTtRQUM3QixLQUFLLE1BQU0sQ0FBQ0MsR0FBRyxFQUFFQyxLQUFLLENBQUMsSUFBSWxILE1BQU0sQ0FBQ21ILE9BQU8sQ0FBQ0wsU0FBUyxDQUFDRSxlQUFlLENBQUMsRUFBRTtVQUNwRXhFLEdBQUcsQ0FBQzNDLEdBQUcsQ0FBQ29ILEdBQUcsRUFBRUMsS0FBSyxDQUFDO1FBQ3JCO01BQ0Y7TUFDQTFFLEdBQUcsQ0FBQzhFLEdBQUcsQ0FBQ0MsSUFBSSxDQUFDO0lBQ2YsQ0FBQyxDQUFDLE9BQU92SSxDQUFDLEVBQUU7TUFDVixNQUFNeUMsR0FBRyxHQUFHdEIsUUFBUSxDQUFDMEgsWUFBWSxDQUFDN0ksQ0FBQyxFQUFFO1FBQ25DOEksSUFBSSxFQUFFMUcsYUFBSyxDQUFDQyxLQUFLLENBQUMwRyxhQUFhO1FBQy9CbEMsT0FBTyxFQUFFLHdCQUF3QkMsUUFBUTtNQUMzQyxDQUFDLENBQUM7TUFDRnRELEdBQUcsQ0FBQ21ELE1BQU0sQ0FBQyxHQUFHLENBQUM7TUFDZm5ELEdBQUcsQ0FBQ29ELElBQUksQ0FBQztRQUFFa0MsSUFBSSxFQUFFckcsR0FBRyxDQUFDcUcsSUFBSTtRQUFFckMsS0FBSyxFQUFFaEUsR0FBRyxDQUFDb0U7TUFBUSxDQUFDLENBQUM7SUFDbEQ7RUFDRjs7RUFFQTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDRXpDLHVCQUF1QkEsQ0FBQSxFQUFHO0lBQ3hCLE9BQU8sT0FBT2IsR0FBRyxFQUFFQyxHQUFHLEVBQUVDLElBQUksS0FBSztNQUMvQixNQUFNdUYscUJBQXFCLEdBQUd6RixHQUFHLENBQUMzQyxHQUFHLENBQUMsOEJBQThCLENBQUM7TUFDckUsSUFBSSxDQUFDb0kscUJBQXFCLEVBQUU7UUFDMUIsT0FBT3ZGLElBQUksQ0FBQyxDQUFDO01BQ2Y7TUFDQSxNQUFNK0MsS0FBSyxHQUFHakQsR0FBRyxDQUFDM0MsR0FBRyxDQUFDLHdCQUF3QixDQUFDO01BQy9DLE1BQU1pRixNQUFNLEdBQUdVLGVBQU0sQ0FBQzNGLEdBQUcsQ0FBQzRGLEtBQUssQ0FBQztNQUNoQyxJQUFJLENBQUNYLE1BQU0sRUFBRTtRQUNYLE1BQU1ZLEtBQUssR0FBRyxJQUFBQywrQkFBd0IsRUFBQyxHQUFHLEVBQUUseUJBQXlCLEVBQUV1QyxTQUFTLENBQUM7UUFDakZ6RixHQUFHLENBQUNtRCxNQUFNLENBQUNGLEtBQUssQ0FBQ0UsTUFBTSxDQUFDO1FBQ3hCbkQsR0FBRyxDQUFDb0QsSUFBSSxDQUFDO1VBQUVILEtBQUssRUFBRUEsS0FBSyxDQUFDSTtRQUFRLENBQUMsQ0FBQztRQUNsQztNQUNGO01BQ0EsTUFBTXFDLFNBQVMsR0FBRyxNQUFNckQsTUFBTSxDQUFDc0QsYUFBYSxDQUFDLENBQUM7TUFDOUMsSUFBSTVGLEdBQUcsQ0FBQzNDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxLQUFLc0ksU0FBUyxFQUFFO1FBQy9DLE1BQU16QyxLQUFLLEdBQUcsSUFBQUMsK0JBQXdCLEVBQUMsR0FBRyxFQUFFLHNDQUFzQyxFQUFFYixNQUFNLENBQUM7UUFDM0ZyQyxHQUFHLENBQUNtRCxNQUFNLENBQUNGLEtBQUssQ0FBQ0UsTUFBTSxDQUFDO1FBQ3hCbkQsR0FBRyxDQUFDb0QsSUFBSSxDQUFDO1VBQUVILEtBQUssRUFBRUEsS0FBSyxDQUFDSTtRQUFRLENBQUMsQ0FBQztRQUNsQztNQUNGO01BQ0EsSUFBSWhCLE1BQU0sQ0FBQ3VELFlBQVksRUFBRWxILE1BQU0sSUFBSSxDQUFDekMsV0FBVyxDQUFDNEosT0FBTyxDQUFDOUYsR0FBRyxDQUFDK0YsRUFBRSxFQUFFekQsTUFBTSxDQUFDdUQsWUFBWSxFQUFFdkQsTUFBTSxDQUFDMEQsaUJBQWlCLENBQUMsRUFBRTtRQUM5RyxNQUFNOUMsS0FBSyxHQUFHLElBQUFDLCtCQUF3QixFQUFDLEdBQUcsRUFBRSxzQ0FBc0MsRUFBRWIsTUFBTSxDQUFDO1FBQzNGckMsR0FBRyxDQUFDbUQsTUFBTSxDQUFDRixLQUFLLENBQUNFLE1BQU0sQ0FBQztRQUN4Qm5ELEdBQUcsQ0FBQ29ELElBQUksQ0FBQztVQUFFSCxLQUFLLEVBQUVBLEtBQUssQ0FBQ0k7UUFBUSxDQUFDLENBQUM7UUFDbEM7TUFDRjtNQUNBLElBQUkyQyxXQUFXO01BQ2YsSUFBSTtRQUNGQSxXQUFXLEdBQUdwSSxLQUFLLENBQUNxSSxnQkFBZ0IsQ0FBQ1QscUJBQXFCLENBQUM7TUFDN0QsQ0FBQyxDQUFDLE1BQU07UUFDTixPQUFPdkYsSUFBSSxDQUNULElBQUlyQixhQUFLLENBQUNDLEtBQUssQ0FDYkQsYUFBSyxDQUFDQyxLQUFLLENBQUNDLGVBQWUsRUFDM0IseUNBQXlDMEcscUJBQXFCLEVBQ2hFLENBQ0YsQ0FBQztNQUNIO01BQ0F6RixHQUFHLENBQUNtRyxzQkFBc0IsR0FBR0YsV0FBVztNQUN4Qy9GLElBQUksQ0FBQyxDQUFDO0lBQ1IsQ0FBQztFQUNIO0VBRUFZLHNCQUFzQkEsQ0FBQ25CLGFBQWEsRUFBRTtJQUNwQyxNQUFNeUcsZUFBZSxHQUFHdkksS0FBSyxDQUFDcUksZ0JBQWdCLENBQUN2RyxhQUFhLENBQUM7SUFDN0QsT0FBTyxDQUFDSyxHQUFHLEVBQUVDLEdBQUcsRUFBRUMsSUFBSSxLQUFLO01BQ3pCLElBQUlGLEdBQUcsQ0FBQzNDLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLLFFBQVEsRUFBRTtRQUMvQzJDLEdBQUcsQ0FBQ3FHLG1CQUFtQixHQUFHckcsR0FBRyxDQUFDbUcsc0JBQXNCLElBQUlDLGVBQWU7UUFDdkUsT0FBT2xHLElBQUksQ0FBQyxDQUFDO01BQ2Y7TUFDQSxNQUFNb0csS0FBSyxHQUFHdEcsR0FBRyxDQUFDbUcsc0JBQXNCLElBQUl4RyxhQUFhO01BQ3pELE9BQU9FLGdCQUFPLENBQUMwRyxHQUFHLENBQUM7UUFBRUMsSUFBSSxFQUFFQSxDQUFBLEtBQU0sSUFBSTtRQUFFRjtNQUFNLENBQUMsQ0FBQyxDQUFDdEcsR0FBRyxFQUFFQyxHQUFHLEVBQUVDLElBQUksQ0FBQztJQUNqRSxDQUFDO0VBQ0g7RUFFQSxNQUFNYyxhQUFhQSxDQUFDaEIsR0FBRyxFQUFFQyxHQUFHLEVBQUVDLElBQUksRUFBRTtJQUNsQyxJQUFJRixHQUFHLENBQUNNLElBQUksQ0FBQ21HLFVBQVUsRUFBRTtNQUN2QixNQUFNdkQsS0FBSyxHQUFHLElBQUFDLCtCQUF3QixFQUFDLEdBQUcsRUFBRSxxREFBcUQsRUFBRW5ELEdBQUcsQ0FBQ3NDLE1BQU0sQ0FBQztNQUM5R3JDLEdBQUcsQ0FBQ21ELE1BQU0sQ0FBQ0YsS0FBSyxDQUFDRSxNQUFNLENBQUM7TUFDeEJuRCxHQUFHLENBQUM4RSxHQUFHLENBQUMsYUFBYTdCLEtBQUssQ0FBQ0ksT0FBTyxJQUFJLENBQUM7TUFDdkM7SUFDRjtJQUNBLE1BQU1oQixNQUFNLEdBQUd0QyxHQUFHLENBQUNzQyxNQUFNO0lBQ3pCLE1BQU0vQixRQUFRLEdBQUdQLEdBQUcsQ0FBQ00sSUFBSSxDQUFDQyxRQUFRO0lBQ2xDLE1BQU1nQyxhQUFhLEdBQUd2QyxHQUFHLENBQUNNLElBQUksQ0FBQ2lDLGFBQWE7SUFDNUMsSUFBSSxDQUFDaEMsUUFBUSxJQUFJLENBQUNnQyxhQUFhLEVBQUU7TUFDL0IsTUFBTUMsSUFBSSxHQUFHeEMsR0FBRyxDQUFDTSxJQUFJLENBQUNrQyxJQUFJO01BQzFCLE1BQU1DLFFBQVEsR0FBR0QsSUFBSSxJQUFJM0QsYUFBSyxDQUFDNkQsY0FBYyxDQUFDRCxRQUFRLENBQUNELElBQUksQ0FBQztNQUM1RCxJQUFJLENBQUNGLE1BQU0sQ0FBQ29FLFVBQVUsQ0FBQzlELHNCQUFzQixJQUFJSCxRQUFRLEVBQUU7UUFDekR2QyxJQUFJLENBQ0YsSUFBSXJCLGFBQUssQ0FBQ0MsS0FBSyxDQUFDRCxhQUFLLENBQUNDLEtBQUssQ0FBQ0MsZUFBZSxFQUFFLDRDQUE0QyxDQUMzRixDQUFDO1FBQ0Q7TUFDRjtNQUNBLElBQUksQ0FBQ3VELE1BQU0sQ0FBQ29FLFVBQVUsQ0FBQzVELDBCQUEwQixJQUFJLENBQUNMLFFBQVEsSUFBSUQsSUFBSSxFQUFFO1FBQ3RFdEMsSUFBSSxDQUNGLElBQUlyQixhQUFLLENBQUNDLEtBQUssQ0FDYkQsYUFBSyxDQUFDQyxLQUFLLENBQUNDLGVBQWUsRUFDM0IsZ0RBQ0YsQ0FDRixDQUFDO1FBQ0Q7TUFDRjtNQUNBLElBQUksQ0FBQ3VELE1BQU0sQ0FBQ29FLFVBQVUsQ0FBQzNELGVBQWUsSUFBSSxDQUFDUCxJQUFJLEVBQUU7UUFDL0N0QyxJQUFJLENBQUMsSUFBSXJCLGFBQUssQ0FBQ0MsS0FBSyxDQUFDRCxhQUFLLENBQUNDLEtBQUssQ0FBQ0MsZUFBZSxFQUFFLG9DQUFvQyxDQUFDLENBQUM7UUFDeEY7TUFDRjtJQUNGO0lBQ0EsTUFBTXlFLGVBQWUsR0FBR2xCLE1BQU0sQ0FBQ2tCLGVBQWU7SUFDOUMsTUFBTTtNQUFFRDtJQUFTLENBQUMsR0FBR3ZELEdBQUcsQ0FBQ3VCLE1BQU07SUFDL0IsTUFBTW1DLFdBQVcsR0FBRzFELEdBQUcsQ0FBQzNDLEdBQUcsQ0FBQyxjQUFjLENBQUM7SUFFM0MsTUFBTTZGLEtBQUssR0FBR00sZUFBZSxDQUFDbUQsZ0JBQWdCLENBQUNwRCxRQUFRLENBQUM7SUFDeEQsSUFBSUwsS0FBSyxFQUFFO01BQ1RoRCxJQUFJLENBQUNnRCxLQUFLLENBQUM7TUFDWDtJQUNGO0lBRUEsTUFBTTBELGNBQWMsR0FBR3RFLE1BQU0sQ0FBQ29FLFVBQVUsRUFBRUUsY0FBYztJQUN4RCxJQUFJLENBQUNyRyxRQUFRLElBQUlxRyxjQUFjLEVBQUU7TUFDL0IsTUFBTUMsZ0JBQWdCLEdBQUdDLFNBQVMsSUFBSTtRQUNwQyxPQUFPRixjQUFjLENBQUNHLElBQUksQ0FBQ0MsR0FBRyxJQUFJO1VBQ2hDLElBQUlBLEdBQUcsS0FBSyxHQUFHLEVBQUU7WUFDZixPQUFPLElBQUk7VUFDYjtVQUNBLE1BQU1DLEtBQUssR0FBRyxJQUFJQyxNQUFNLENBQUNGLEdBQUcsQ0FBQztVQUM3QixJQUFJQyxLQUFLLENBQUM3RSxJQUFJLENBQUMwRSxTQUFTLENBQUMsRUFBRTtZQUN6QixPQUFPLElBQUk7VUFDYjtRQUNGLENBQUMsQ0FBQztNQUNKLENBQUM7TUFDRCxJQUFJQSxTQUFTLEdBQUdwRCxXQUFXO01BQzNCLElBQUlILFFBQVEsSUFBSUEsUUFBUSxDQUFDekIsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFO1FBQ3RDZ0YsU0FBUyxHQUFHdkQsUUFBUSxDQUFDNEQsU0FBUyxDQUFDNUQsUUFBUSxDQUFDNkQsV0FBVyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztNQUMvRCxDQUFDLE1BQU0sSUFBSTFELFdBQVcsSUFBSUEsV0FBVyxDQUFDNUIsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFO1FBQ25EZ0YsU0FBUyxHQUFHcEQsV0FBVyxDQUFDeEIsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztNQUN2QztNQUNBO01BQ0E0RSxTQUFTLEdBQUdBLFNBQVMsRUFBRTVFLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRW1GLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO01BRXpELElBQUlQLFNBQVMsSUFBSSxDQUFDRCxnQkFBZ0IsQ0FBQ0MsU0FBUyxDQUFDLEVBQUU7UUFDN0M1RyxJQUFJLENBQ0YsSUFBSXJCLGFBQUssQ0FBQ0MsS0FBSyxDQUNiRCxhQUFLLENBQUNDLEtBQUssQ0FBQ0MsZUFBZSxFQUMzQiw0QkFBNEIrSCxTQUFTLGVBQ3ZDLENBQ0YsQ0FBQztRQUNEO01BQ0Y7SUFDRjs7SUFFQTtJQUNBLElBQUk5RyxHQUFHLENBQUMzQyxHQUFHLENBQUMscUJBQXFCLENBQUMsS0FBSyxRQUFRLEVBQUU7TUFDL0MyQyxHQUFHLENBQUNzSCxRQUFRLEdBQUcsQ0FBQyxDQUFDO01BQ2pCLElBQUl0SCxHQUFHLENBQUMzQyxHQUFHLENBQUMsd0JBQXdCLENBQUMsRUFBRTtRQUNyQzJDLEdBQUcsQ0FBQ3NILFFBQVEsQ0FBQ3pGLFNBQVMsR0FBRzdCLEdBQUcsQ0FBQzNDLEdBQUcsQ0FBQyx3QkFBd0IsQ0FBQztNQUM1RDtNQUNBLElBQUkyQyxHQUFHLENBQUMzQyxHQUFHLENBQUMsdUJBQXVCLENBQUMsRUFBRTtRQUNwQyxJQUFJO1VBQ0YsTUFBTWtLLE1BQU0sR0FBR0MsSUFBSSxDQUFDQyxLQUFLLENBQUN6SCxHQUFHLENBQUMzQyxHQUFHLENBQUMsdUJBQXVCLENBQUMsQ0FBQztVQUMzRCxJQUFJLENBQUNrSyxNQUFNLElBQUksT0FBT0EsTUFBTSxLQUFLLFFBQVEsSUFBSTlGLEtBQUssQ0FBQ0MsT0FBTyxDQUFDNkYsTUFBTSxDQUFDLEVBQUU7WUFDbEUsTUFBTSxJQUFJekksS0FBSyxDQUFDLENBQUM7VUFDbkI7VUFDQWtCLEdBQUcsQ0FBQ3NILFFBQVEsQ0FBQ0ksUUFBUSxHQUFHSCxNQUFNO1FBQ2hDLENBQUMsQ0FBQyxNQUFNO1VBQ05ySCxJQUFJLENBQUMsSUFBSXJCLGFBQUssQ0FBQ0MsS0FBSyxDQUFDRCxhQUFLLENBQUNDLEtBQUssQ0FBQzZJLFlBQVksRUFBRSwrQ0FBK0MsQ0FBQyxDQUFDO1VBQ2hHO1FBQ0Y7TUFDRjtNQUNBLElBQUkzSCxHQUFHLENBQUMzQyxHQUFHLENBQUMsbUJBQW1CLENBQUMsRUFBRTtRQUNoQyxJQUFJO1VBQ0YsTUFBTWtLLE1BQU0sR0FBR0MsSUFBSSxDQUFDQyxLQUFLLENBQUN6SCxHQUFHLENBQUMzQyxHQUFHLENBQUMsbUJBQW1CLENBQUMsQ0FBQztVQUN2RCxJQUFJLENBQUNrSyxNQUFNLElBQUksT0FBT0EsTUFBTSxLQUFLLFFBQVEsSUFBSTlGLEtBQUssQ0FBQ0MsT0FBTyxDQUFDNkYsTUFBTSxDQUFDLEVBQUU7WUFDbEUsTUFBTSxJQUFJekksS0FBSyxDQUFDLENBQUM7VUFDbkI7VUFDQWtCLEdBQUcsQ0FBQ3NILFFBQVEsQ0FBQ00sSUFBSSxHQUFHTCxNQUFNO1FBQzVCLENBQUMsQ0FBQyxNQUFNO1VBQ05ySCxJQUFJLENBQUMsSUFBSXJCLGFBQUssQ0FBQ0MsS0FBSyxDQUFDRCxhQUFLLENBQUNDLEtBQUssQ0FBQzZJLFlBQVksRUFBRSwyQ0FBMkMsQ0FBQyxDQUFDO1VBQzVGO1FBQ0Y7TUFDRjtJQUNGOztJQUVBO0lBQ0EsTUFBTTlGLFNBQVMsR0FBRzdCLEdBQUcsQ0FBQ3NILFFBQVEsRUFBRXpGLFNBQVM7SUFDekMsSUFBSUEsU0FBUyxLQUFLNkQsU0FBUyxFQUFFO01BQzNCLElBQUksQ0FBQ25GLFFBQVEsRUFBRTtRQUNiTCxJQUFJLENBQ0YsSUFBSXJCLGFBQUssQ0FBQ0MsS0FBSyxDQUNiRCxhQUFLLENBQUNDLEtBQUssQ0FBQytELG1CQUFtQixFQUMvQixpREFDRixDQUNGLENBQUM7UUFDRDtNQUNGO01BQ0EsTUFBTWdGLGNBQWMsR0FBR3BJLFdBQVcsQ0FBQ21DLGlCQUFpQixDQUFDQyxTQUFTLENBQUM7TUFDL0QsSUFBSWdHLGNBQWMsRUFBRTtRQUNsQjNILElBQUksQ0FBQzJILGNBQWMsQ0FBQztRQUNwQjtNQUNGO0lBQ0Y7O0lBRUE7SUFDQSxJQUFJMUMsTUFBTSxDQUFDMkMsUUFBUSxDQUFDOUgsR0FBRyxDQUFDK0gsSUFBSSxDQUFDLEVBQUU7TUFDN0IsT0FBTyxJQUFJLENBQUNDLHFCQUFxQixDQUFDaEksR0FBRyxFQUFFQyxHQUFHLEVBQUVDLElBQUksQ0FBQztJQUNuRDtJQUNBLE9BQU8sSUFBSSxDQUFDK0gsbUJBQW1CLENBQUNqSSxHQUFHLEVBQUVDLEdBQUcsRUFBRUMsSUFBSSxDQUFDO0VBQ2pEO0VBRUEsTUFBTThILHFCQUFxQkEsQ0FBQ2hJLEdBQUcsRUFBRUMsR0FBRyxFQUFFQyxJQUFJLEVBQUU7SUFDMUMsTUFBTW9DLE1BQU0sR0FBR3RDLEdBQUcsQ0FBQ3NDLE1BQU07SUFDekIsTUFBTWtCLGVBQWUsR0FBR2xCLE1BQU0sQ0FBQ2tCLGVBQWU7SUFDOUMsTUFBTTtNQUFFRDtJQUFTLENBQUMsR0FBR3ZELEdBQUcsQ0FBQ3VCLE1BQU07SUFDL0IsTUFBTW1DLFdBQVcsR0FBRzFELEdBQUcsQ0FBQzNDLEdBQUcsQ0FBQyxjQUFjLENBQUM7SUFFM0MsSUFBSSxDQUFDMkMsR0FBRyxDQUFDK0gsSUFBSSxJQUFJLENBQUMvSCxHQUFHLENBQUMrSCxJQUFJLENBQUNwSixNQUFNLEVBQUU7TUFDakN1QixJQUFJLENBQUMsSUFBSXJCLGFBQUssQ0FBQ0MsS0FBSyxDQUFDRCxhQUFLLENBQUNDLEtBQUssQ0FBQ0MsZUFBZSxFQUFFLHNCQUFzQixDQUFDLENBQUM7TUFDMUU7SUFDRjtJQUVBLE1BQU0rRSxNQUFNLEdBQUc5RCxHQUFHLENBQUMrSCxJQUFJLENBQUM3QyxRQUFRLENBQUMsUUFBUSxDQUFDO0lBQzFDLE1BQU10QixJQUFJLEdBQUcsSUFBSS9FLGFBQUssQ0FBQ2dGLElBQUksQ0FBQ04sUUFBUSxFQUFFO01BQUVPO0lBQU8sQ0FBQyxFQUFFSixXQUFXLENBQUM7SUFDOUQsTUFBTTtNQUFFZ0UsUUFBUSxHQUFHLENBQUMsQ0FBQztNQUFFRSxJQUFJLEdBQUcsQ0FBQyxDQUFDO01BQUUvRjtJQUFVLENBQUMsR0FBRzdCLEdBQUcsQ0FBQ3NILFFBQVEsSUFBSSxDQUFDLENBQUM7SUFDbEUsSUFBSTtNQUNGO01BQ0F6SixLQUFLLENBQUNxSyx1QkFBdUIsQ0FBQzVGLE1BQU0sRUFBRW9GLFFBQVEsQ0FBQztNQUMvQzdKLEtBQUssQ0FBQ3FLLHVCQUF1QixDQUFDNUYsTUFBTSxFQUFFc0YsSUFBSSxDQUFDO0lBQzdDLENBQUMsQ0FBQyxPQUFPMUUsS0FBSyxFQUFFO01BQ2RoRCxJQUFJLENBQUMsSUFBSXJCLGFBQUssQ0FBQ0MsS0FBSyxDQUFDRCxhQUFLLENBQUNDLEtBQUssQ0FBQ3FKLGdCQUFnQixFQUFFakYsS0FBSyxDQUFDLENBQUM7TUFDMUQ7SUFDRjtJQUNBVSxJQUFJLENBQUN3RSxPQUFPLENBQUNSLElBQUksQ0FBQztJQUNsQmhFLElBQUksQ0FBQ3lFLFdBQVcsQ0FBQ1gsUUFBUSxDQUFDO0lBQzFCLElBQUk3RixTQUFTLEVBQUU7TUFDYitCLElBQUksQ0FBQzBFLFlBQVksQ0FBQ3pHLFNBQVMsQ0FBQztJQUM5QjtJQUNBLE1BQU0wRyxRQUFRLEdBQUdwRCxNQUFNLENBQUNxRCxVQUFVLENBQUN4SSxHQUFHLENBQUMrSCxJQUFJLENBQUM7SUFDNUMsTUFBTVUsVUFBVSxHQUFHO01BQUU3RSxJQUFJO01BQUUyRTtJQUFTLENBQUM7SUFDckMsSUFBSTtNQUNGO01BQ0EsTUFBTXZFLGFBQWEsR0FBRyxNQUFNcEcsUUFBUSxDQUFDcUcsbUJBQW1CLENBQ3REckcsUUFBUSxDQUFDc0csS0FBSyxDQUFDd0UsVUFBVSxFQUN6QkQsVUFBVSxFQUNWbkcsTUFBTSxFQUNOdEMsR0FBRyxDQUFDTSxJQUNOLENBQUM7TUFDRCxJQUFJcUksVUFBVTtNQUNkO01BQ0EsSUFBSTNFLGFBQWEsWUFBWW5GLGFBQUssQ0FBQ2dGLElBQUksRUFBRTtRQUN2QzRFLFVBQVUsQ0FBQzdFLElBQUksR0FBR0ksYUFBYTtRQUMvQixJQUFJQSxhQUFhLENBQUM0RSxHQUFHLENBQUMsQ0FBQyxFQUFFO1VBQ3ZCO1VBQ0FILFVBQVUsQ0FBQ0YsUUFBUSxHQUFHLElBQUk7VUFDMUJJLFVBQVUsR0FBRztZQUNYQyxHQUFHLEVBQUU1RSxhQUFhLENBQUM0RSxHQUFHLENBQUMsQ0FBQztZQUN4QkMsSUFBSSxFQUFFN0UsYUFBYSxDQUFDSTtVQUN0QixDQUFDO1FBQ0g7TUFDRjtNQUNBO01BQ0EsSUFBSSxDQUFDdUUsVUFBVSxFQUFFO1FBQ2Y7UUFDQSxJQUFJRyxVQUFVO1FBQ2QsSUFBSUwsVUFBVSxDQUFDN0UsSUFBSSxDQUFDbUYsT0FBTyxFQUFFQyxNQUFNLEtBQUssUUFBUSxFQUFFO1VBQ2hERixVQUFVLEdBQUdMLFVBQVUsQ0FBQzdFLElBQUksQ0FBQ21GLE9BQU8sQ0FBQ0UsTUFBTTtRQUM3QyxDQUFDLE1BQU07VUFDTEgsVUFBVSxHQUFHM0QsTUFBTSxDQUFDQyxJQUFJLENBQUNxRCxVQUFVLENBQUM3RSxJQUFJLENBQUN5QixLQUFLLEVBQUUsUUFBUSxDQUFDO1FBQzNEO1FBQ0FvRCxVQUFVLENBQUNGLFFBQVEsR0FBR3BELE1BQU0sQ0FBQ3FELFVBQVUsQ0FBQ00sVUFBVSxDQUFDO1FBQ25EO1FBQ0EsTUFBTUksV0FBVyxHQUFHO1VBQ2xCeEIsUUFBUSxFQUFFZSxVQUFVLENBQUM3RSxJQUFJLENBQUN1RjtRQUM1QixDQUFDO1FBQ0Q7UUFDQTtRQUNBLE1BQU1DLFFBQVEsR0FDWjNMLE1BQU0sQ0FBQzRMLElBQUksQ0FBQ1osVUFBVSxDQUFDN0UsSUFBSSxDQUFDMEYsS0FBSyxDQUFDLENBQUMzSyxNQUFNLEdBQUcsQ0FBQyxHQUFHO1VBQUVpSixJQUFJLEVBQUVhLFVBQVUsQ0FBQzdFLElBQUksQ0FBQzBGO1FBQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN0RjdMLE1BQU0sQ0FBQzhMLE1BQU0sQ0FBQ0wsV0FBVyxFQUFFRSxRQUFRLENBQUM7UUFDcEM7UUFDQSxJQUFJWCxVQUFVLENBQUM3RSxJQUFJLENBQUM0RixVQUFVLEVBQUU7VUFDOUJOLFdBQVcsQ0FBQ3JILFNBQVMsR0FBRzRHLFVBQVUsQ0FBQzdFLElBQUksQ0FBQzRGLFVBQVU7UUFDcEQ7UUFDQTtRQUNBLE1BQU1DLGdCQUFnQixHQUFHLE1BQU1qRyxlQUFlLENBQUNrRyxVQUFVLENBQ3ZEcEgsTUFBTSxFQUNObUcsVUFBVSxDQUFDN0UsSUFBSSxDQUFDUSxLQUFLLEVBQ3JCMEUsVUFBVSxFQUNWTCxVQUFVLENBQUM3RSxJQUFJLENBQUNtRixPQUFPLENBQUN2QyxJQUFJLEVBQzVCMEMsV0FDRixDQUFDO1FBQ0Q7UUFDQVQsVUFBVSxDQUFDN0UsSUFBSSxDQUFDUSxLQUFLLEdBQUdxRixnQkFBZ0IsQ0FBQ1osSUFBSTtRQUM3Q0osVUFBVSxDQUFDN0UsSUFBSSxDQUFDK0YsSUFBSSxHQUFHRixnQkFBZ0IsQ0FBQ2IsR0FBRztRQUMzQ0gsVUFBVSxDQUFDN0UsSUFBSSxDQUFDZ0csWUFBWSxHQUFHLElBQUk7UUFDbkNuQixVQUFVLENBQUM3RSxJQUFJLENBQUNpRyxhQUFhLEdBQUdDLE9BQU8sQ0FBQ0MsT0FBTyxDQUFDdEIsVUFBVSxDQUFDN0UsSUFBSSxDQUFDO1FBQ2hFK0UsVUFBVSxHQUFHO1VBQ1hDLEdBQUcsRUFBRWEsZ0JBQWdCLENBQUNiLEdBQUc7VUFDekJDLElBQUksRUFBRVksZ0JBQWdCLENBQUNaO1FBQ3pCLENBQUM7TUFDSDtNQUNBO01BQ0EsTUFBTWpMLFFBQVEsQ0FBQ3FHLG1CQUFtQixDQUFDckcsUUFBUSxDQUFDc0csS0FBSyxDQUFDOEYsU0FBUyxFQUFFdkIsVUFBVSxFQUFFbkcsTUFBTSxFQUFFdEMsR0FBRyxDQUFDTSxJQUFJLENBQUM7TUFDMUZMLEdBQUcsQ0FBQ21ELE1BQU0sQ0FBQyxHQUFHLENBQUM7TUFDZm5ELEdBQUcsQ0FBQzNDLEdBQUcsQ0FBQyxVQUFVLEVBQUVxTCxVQUFVLENBQUNDLEdBQUcsQ0FBQztNQUNuQzNJLEdBQUcsQ0FBQ29ELElBQUksQ0FBQ3NGLFVBQVUsQ0FBQztJQUN0QixDQUFDLENBQUMsT0FBT2xNLENBQUMsRUFBRTtNQUNWd04sZUFBTSxDQUFDL0csS0FBSyxDQUFDLHlCQUF5QixFQUFFekcsQ0FBQyxDQUFDO01BQzFDLE1BQU15RyxLQUFLLEdBQUd0RixRQUFRLENBQUMwSCxZQUFZLENBQUM3SSxDQUFDLEVBQUU7UUFDckM4SSxJQUFJLEVBQUUxRyxhQUFLLENBQUNDLEtBQUssQ0FBQ0MsZUFBZTtRQUNqQ3VFLE9BQU8sRUFBRSx5QkFBeUJtRixVQUFVLENBQUM3RSxJQUFJLENBQUNRLEtBQUs7TUFDekQsQ0FBQyxDQUFDO01BQ0ZsRSxJQUFJLENBQUNnRCxLQUFLLENBQUM7SUFDYjtFQUNGO0VBRUEsTUFBTStFLG1CQUFtQkEsQ0FBQ2pJLEdBQUcsRUFBRUMsR0FBRyxFQUFFQyxJQUFJLEVBQUU7SUFDeEMsTUFBTW9DLE1BQU0sR0FBR3RDLEdBQUcsQ0FBQ3NDLE1BQU07SUFDekIsTUFBTWtCLGVBQWUsR0FBR2xCLE1BQU0sQ0FBQ2tCLGVBQWU7SUFDOUMsTUFBTTtNQUFFRDtJQUFTLENBQUMsR0FBR3ZELEdBQUcsQ0FBQ3VCLE1BQU07SUFDL0IsSUFBSW1DLFdBQVcsR0FBRzFELEdBQUcsQ0FBQzNDLEdBQUcsQ0FBQyxjQUFjLENBQUM7SUFDekMsTUFBTVcsUUFBUSxHQUFHZ0MsR0FBRyxDQUFDcUcsbUJBQW1CO0lBQ3hDLElBQUk2RCxNQUFNO0lBRVYsSUFBSTtNQUNGO01BQ0EsTUFBTUMsYUFBYSxHQUFHbkssR0FBRyxDQUFDM0MsR0FBRyxDQUFDLGdCQUFnQixDQUFDO01BQy9DLElBQUk4TSxhQUFhLElBQUlDLFFBQVEsQ0FBQ0QsYUFBYSxFQUFFLEVBQUUsQ0FBQyxHQUFHbk0sUUFBUSxFQUFFO1FBQzNEZ0MsR0FBRyxDQUFDWixNQUFNLENBQUMsQ0FBQztRQUNaYyxJQUFJLENBQUMsSUFBSXJCLGFBQUssQ0FBQ0MsS0FBSyxDQUNsQkQsYUFBSyxDQUFDQyxLQUFLLENBQUNDLGVBQWUsRUFDM0Isc0NBQXNDZixRQUFRLFNBQ2hELENBQUMsQ0FBQztRQUNGO01BQ0Y7TUFFQSxNQUFNeUYsSUFBSSxHQUFHLENBQUMsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUV0RyxPQUFPOztNQUUzQztNQUNBLE1BQU1rTixZQUFZLEdBQUc5RyxRQUFRLElBQUlBLFFBQVEsQ0FBQ3pCLFFBQVEsQ0FBQyxHQUFHLENBQUM7TUFDdkQsSUFBSXVJLFlBQVksSUFBSSxDQUFDM0csV0FBVyxFQUFFO1FBQ2hDQSxXQUFXLEdBQUdELElBQUksQ0FBQ0UsT0FBTyxDQUFDSixRQUFRLENBQUM7TUFDdEMsQ0FBQyxNQUFNLElBQUksQ0FBQzhHLFlBQVksSUFBSTNHLFdBQVcsRUFBRTtRQUN2QztNQUFBOztNQUdGO01BQ0F3RyxNQUFNLEdBQUdwTSx1QkFBdUIsQ0FBQ2tDLEdBQUcsRUFBRWhDLFFBQVEsQ0FBQzs7TUFFL0M7TUFDQSxNQUFNNEYsSUFBSSxHQUFHLElBQUkvRSxhQUFLLENBQUNnRixJQUFJLENBQUNOLFFBQVEsRUFBRTtRQUFFTyxNQUFNLEVBQUU7TUFBRyxDQUFDLEVBQUVKLFdBQVcsQ0FBQztNQUNsRSxNQUFNO1FBQUVnRSxRQUFRLEdBQUcsQ0FBQyxDQUFDO1FBQUVFLElBQUksR0FBRyxDQUFDLENBQUM7UUFBRS9GO01BQVUsQ0FBQyxHQUFHN0IsR0FBRyxDQUFDc0gsUUFBUSxJQUFJLENBQUMsQ0FBQzs7TUFFbEU7TUFDQSxJQUFJO1FBQ0Z6SixLQUFLLENBQUNxSyx1QkFBdUIsQ0FBQzVGLE1BQU0sRUFBRW9GLFFBQVEsQ0FBQztRQUMvQzdKLEtBQUssQ0FBQ3FLLHVCQUF1QixDQUFDNUYsTUFBTSxFQUFFc0YsSUFBSSxDQUFDO01BQzdDLENBQUMsQ0FBQyxPQUFPMUUsS0FBSyxFQUFFO1FBQ2RnSCxNQUFNLENBQUN0TCxPQUFPLENBQUMsQ0FBQztRQUNoQnNCLElBQUksQ0FBQyxJQUFJckIsYUFBSyxDQUFDQyxLQUFLLENBQUNELGFBQUssQ0FBQ0MsS0FBSyxDQUFDcUosZ0JBQWdCLEVBQUVqRixLQUFLLENBQUMsQ0FBQztRQUMxRDtNQUNGO01BRUFVLElBQUksQ0FBQ3dFLE9BQU8sQ0FBQ1IsSUFBSSxDQUFDO01BQ2xCaEUsSUFBSSxDQUFDeUUsV0FBVyxDQUFDWCxRQUFRLENBQUM7TUFDMUIsSUFBSTdGLFNBQVMsRUFBRTtRQUNiK0IsSUFBSSxDQUFDMEUsWUFBWSxDQUFDekcsU0FBUyxDQUFDO01BQzlCO01BRUEsTUFBTTBHLFFBQVEsR0FBR3ZJLEdBQUcsQ0FBQzNDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUN0QytNLFFBQVEsQ0FBQ3BLLEdBQUcsQ0FBQzNDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUN2QyxJQUFJO01BQ1IsTUFBTW9MLFVBQVUsR0FBRztRQUFFN0UsSUFBSTtRQUFFMkUsUUFBUTtRQUFFMkIsTUFBTSxFQUFFO01BQUssQ0FBQzs7TUFFbkQ7TUFDQSxNQUFNbEcsYUFBYSxHQUFHLE1BQU1wRyxRQUFRLENBQUNxRyxtQkFBbUIsQ0FDdERyRyxRQUFRLENBQUNzRyxLQUFLLENBQUN3RSxVQUFVLEVBQ3pCRCxVQUFVLEVBQ1ZuRyxNQUFNLEVBQ050QyxHQUFHLENBQUNNLElBQ04sQ0FBQztNQUVELElBQUlxSSxVQUFVO01BQ2Q7TUFDQSxJQUFJM0UsYUFBYSxZQUFZbkYsYUFBSyxDQUFDZ0YsSUFBSSxFQUFFO1FBQ3ZDNEUsVUFBVSxDQUFDN0UsSUFBSSxHQUFHSSxhQUFhO1FBQy9CLElBQUlBLGFBQWEsQ0FBQzRFLEdBQUcsQ0FBQyxDQUFDLEVBQUU7VUFDdkJILFVBQVUsQ0FBQ0YsUUFBUSxHQUFHLElBQUk7VUFDMUJJLFVBQVUsR0FBRztZQUNYQyxHQUFHLEVBQUU1RSxhQUFhLENBQUM0RSxHQUFHLENBQUMsQ0FBQztZQUN4QkMsSUFBSSxFQUFFN0UsYUFBYSxDQUFDSTtVQUN0QixDQUFDO1VBQ0Q7VUFDQThGLE1BQU0sQ0FBQ3RMLE9BQU8sQ0FBQyxDQUFDO1FBQ2xCO01BQ0Y7O01BRUE7TUFDQSxJQUFJLENBQUMrSixVQUFVLEVBQUU7UUFDZjtRQUNBLE1BQU1PLFdBQVcsR0FBRztVQUNsQnhCLFFBQVEsRUFBRWUsVUFBVSxDQUFDN0UsSUFBSSxDQUFDdUY7UUFDNUIsQ0FBQztRQUNELE1BQU1DLFFBQVEsR0FDWjNMLE1BQU0sQ0FBQzRMLElBQUksQ0FBQ1osVUFBVSxDQUFDN0UsSUFBSSxDQUFDMEYsS0FBSyxDQUFDLENBQUMzSyxNQUFNLEdBQUcsQ0FBQyxHQUFHO1VBQUVpSixJQUFJLEVBQUVhLFVBQVUsQ0FBQzdFLElBQUksQ0FBQzBGO1FBQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN0RjdMLE1BQU0sQ0FBQzhMLE1BQU0sQ0FBQ0wsV0FBVyxFQUFFRSxRQUFRLENBQUM7UUFDcEM7UUFDQSxJQUFJWCxVQUFVLENBQUM3RSxJQUFJLENBQUM0RixVQUFVLEVBQUU7VUFDOUJOLFdBQVcsQ0FBQ3JILFNBQVMsR0FBRzRHLFVBQVUsQ0FBQzdFLElBQUksQ0FBQzRGLFVBQVU7UUFDcEQ7O1FBRUE7UUFDQSxNQUFNYyxVQUFVLEdBQUc3QixVQUFVLENBQUM3RSxJQUFJLENBQUNtRixPQUFPLEVBQUV2QyxJQUFJLElBQUk5QyxXQUFXO1FBQy9ELE1BQU0rRixnQkFBZ0IsR0FBRyxNQUFNakcsZUFBZSxDQUFDa0csVUFBVSxDQUN2RHBILE1BQU0sRUFDTm1HLFVBQVUsQ0FBQzdFLElBQUksQ0FBQ1EsS0FBSyxFQUNyQjhGLE1BQU0sRUFDTkksVUFBVSxFQUNWcEIsV0FDRixDQUFDOztRQUVEO1FBQ0FULFVBQVUsQ0FBQzdFLElBQUksQ0FBQ1EsS0FBSyxHQUFHcUYsZ0JBQWdCLENBQUNaLElBQUk7UUFDN0NKLFVBQVUsQ0FBQzdFLElBQUksQ0FBQytGLElBQUksR0FBR0YsZ0JBQWdCLENBQUNiLEdBQUc7UUFDM0NILFVBQVUsQ0FBQzdFLElBQUksQ0FBQ2dHLFlBQVksR0FBRyxJQUFJO1FBQ25DbkIsVUFBVSxDQUFDN0UsSUFBSSxDQUFDaUcsYUFBYSxHQUFHQyxPQUFPLENBQUNDLE9BQU8sQ0FBQ3RCLFVBQVUsQ0FBQzdFLElBQUksQ0FBQztRQUNoRStFLFVBQVUsR0FBRztVQUNYQyxHQUFHLEVBQUVhLGdCQUFnQixDQUFDYixHQUFHO1VBQ3pCQyxJQUFJLEVBQUVZLGdCQUFnQixDQUFDWjtRQUN6QixDQUFDO01BQ0g7O01BRUE7TUFDQSxNQUFNakwsUUFBUSxDQUFDcUcsbUJBQW1CLENBQUNyRyxRQUFRLENBQUNzRyxLQUFLLENBQUM4RixTQUFTLEVBQUV2QixVQUFVLEVBQUVuRyxNQUFNLEVBQUV0QyxHQUFHLENBQUNNLElBQUksQ0FBQztNQUMxRkwsR0FBRyxDQUFDbUQsTUFBTSxDQUFDLEdBQUcsQ0FBQztNQUNmbkQsR0FBRyxDQUFDM0MsR0FBRyxDQUFDLFVBQVUsRUFBRXFMLFVBQVUsQ0FBQ0MsR0FBRyxDQUFDO01BQ25DM0ksR0FBRyxDQUFDb0QsSUFBSSxDQUFDc0YsVUFBVSxDQUFDO0lBQ3RCLENBQUMsQ0FBQyxPQUFPbE0sQ0FBQyxFQUFFO01BQ1Y7TUFDQSxJQUFJeU4sTUFBTSxFQUFFO1FBQ1ZBLE1BQU0sQ0FBQ3RMLE9BQU8sQ0FBQyxDQUFDO01BQ2xCLENBQUMsTUFBTTtRQUNMb0IsR0FBRyxDQUFDWixNQUFNLENBQUMsQ0FBQztNQUNkO01BQ0E2SyxlQUFNLENBQUMvRyxLQUFLLENBQUMseUJBQXlCLEVBQUV6RyxDQUFDLENBQUM7TUFDMUMsTUFBTXlHLEtBQUssR0FBR3RGLFFBQVEsQ0FBQzBILFlBQVksQ0FBQzdJLENBQUMsRUFBRTtRQUNyQzhJLElBQUksRUFBRTFHLGFBQUssQ0FBQ0MsS0FBSyxDQUFDQyxlQUFlO1FBQ2pDdUUsT0FBTyxFQUFFLHlCQUF5QkMsUUFBUTtNQUM1QyxDQUFDLENBQUM7TUFDRnJELElBQUksQ0FBQ2dELEtBQUssQ0FBQztJQUNiO0VBQ0Y7RUFFQSxNQUFNOUIsYUFBYUEsQ0FBQ3BCLEdBQUcsRUFBRUMsR0FBRyxFQUFFQyxJQUFJLEVBQUU7SUFDbEMsSUFBSUYsR0FBRyxDQUFDTSxJQUFJLENBQUNtRyxVQUFVLEVBQUU7TUFDdkIsTUFBTXZELEtBQUssR0FBRyxJQUFBQywrQkFBd0IsRUFBQyxHQUFHLEVBQUUscURBQXFELEVBQUVuRCxHQUFHLENBQUNzQyxNQUFNLENBQUM7TUFDOUdyQyxHQUFHLENBQUNtRCxNQUFNLENBQUNGLEtBQUssQ0FBQ0UsTUFBTSxDQUFDO01BQ3hCbkQsR0FBRyxDQUFDOEUsR0FBRyxDQUFDLGFBQWE3QixLQUFLLENBQUNJLE9BQU8sSUFBSSxDQUFDO01BQ3ZDO0lBQ0Y7SUFDQSxJQUFJO01BQ0YsTUFBTTtRQUFFRTtNQUFnQixDQUFDLEdBQUd4RCxHQUFHLENBQUNzQyxNQUFNO01BQ3RDLE1BQU1pQixRQUFRLEdBQUc5RCxXQUFXLENBQUM0QixzQkFBc0IsQ0FBQ3JCLEdBQUcsQ0FBQztNQUN4RDtNQUNBLE1BQU00RCxJQUFJLEdBQUcsSUFBSS9FLGFBQUssQ0FBQ2dGLElBQUksQ0FBQ04sUUFBUSxDQUFDO01BQ3JDSyxJQUFJLENBQUMrRixJQUFJLEdBQUcsTUFBTW5HLGVBQWUsQ0FBQytHLE9BQU8sQ0FBQ0MsZUFBZSxDQUFDeEssR0FBRyxDQUFDc0MsTUFBTSxFQUFFaUIsUUFBUSxDQUFDO01BQy9FLE1BQU1rRixVQUFVLEdBQUc7UUFBRTdFLElBQUk7UUFBRTJFLFFBQVEsRUFBRTtNQUFLLENBQUM7TUFDM0MsTUFBTTNLLFFBQVEsQ0FBQ3FHLG1CQUFtQixDQUNoQ3JHLFFBQVEsQ0FBQ3NHLEtBQUssQ0FBQ3VHLFlBQVksRUFDM0JoQyxVQUFVLEVBQ1Z6SSxHQUFHLENBQUNzQyxNQUFNLEVBQ1Z0QyxHQUFHLENBQUNNLElBQ04sQ0FBQztNQUNEO01BQ0EsTUFBTWtELGVBQWUsQ0FBQ2tILFVBQVUsQ0FBQzFLLEdBQUcsQ0FBQ3NDLE1BQU0sRUFBRWlCLFFBQVEsQ0FBQztNQUN0RDtNQUNBLE1BQU0zRixRQUFRLENBQUNxRyxtQkFBbUIsQ0FDaENyRyxRQUFRLENBQUNzRyxLQUFLLENBQUN5RyxXQUFXLEVBQzFCbEMsVUFBVSxFQUNWekksR0FBRyxDQUFDc0MsTUFBTSxFQUNWdEMsR0FBRyxDQUFDTSxJQUNOLENBQUM7TUFDREwsR0FBRyxDQUFDbUQsTUFBTSxDQUFDLEdBQUcsQ0FBQztNQUNmO01BQ0FuRCxHQUFHLENBQUM4RSxHQUFHLENBQUMsQ0FBQztJQUNYLENBQUMsQ0FBQyxPQUFPdEksQ0FBQyxFQUFFO01BQ1Z3TixlQUFNLENBQUMvRyxLQUFLLENBQUMseUJBQXlCLEVBQUV6RyxDQUFDLENBQUM7TUFDMUMsTUFBTXlHLEtBQUssR0FBR3RGLFFBQVEsQ0FBQzBILFlBQVksQ0FBQzdJLENBQUMsRUFBRTtRQUNyQzhJLElBQUksRUFBRTFHLGFBQUssQ0FBQ0MsS0FBSyxDQUFDOEwsaUJBQWlCO1FBQ25DdEgsT0FBTyxFQUFFO01BQ1gsQ0FBQyxDQUFDO01BQ0ZwRCxJQUFJLENBQUNnRCxLQUFLLENBQUM7SUFDYjtFQUNGO0VBRUEsTUFBTXpDLGVBQWVBLENBQUNULEdBQUcsRUFBRUMsR0FBRyxFQUFFO0lBQzlCLElBQUk7TUFDRixNQUFNcUMsTUFBTSxHQUFHVSxlQUFNLENBQUMzRixHQUFHLENBQUMyQyxHQUFHLENBQUN1QixNQUFNLENBQUMwQixLQUFLLENBQUM7TUFDM0MsSUFBSSxDQUFDWCxNQUFNLEVBQUU7UUFDWHJDLEdBQUcsQ0FBQ21ELE1BQU0sQ0FBQyxHQUFHLENBQUM7UUFDZm5ELEdBQUcsQ0FBQ29ELElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNaO01BQ0Y7TUFDQTVELFdBQVcsQ0FBQzRDLHFCQUFxQixDQUFDckMsR0FBRyxFQUFFc0MsTUFBTSxDQUFDO01BQzlDLE1BQU07UUFBRWtCO01BQWdCLENBQUMsR0FBR2xCLE1BQU07TUFDbEMsSUFBSWlCLFFBQVEsR0FBRzlELFdBQVcsQ0FBQzRCLHNCQUFzQixDQUFDckIsR0FBRyxDQUFDO01BQ3RELE1BQU00RCxJQUFJLEdBQUcsSUFBSS9FLGFBQUssQ0FBQ2dGLElBQUksQ0FBQ04sUUFBUSxFQUFFO1FBQUVPLE1BQU0sRUFBRTtNQUFHLENBQUMsQ0FBQztNQUNyRCxNQUFNQyxRQUFRLEdBQUcvRCxHQUFHLENBQUNNLElBQUk7TUFDekIsTUFBTTBELGFBQWEsR0FBRyxNQUFNcEcsUUFBUSxDQUFDcUcsbUJBQW1CLENBQ3REckcsUUFBUSxDQUFDc0csS0FBSyxDQUFDQyxVQUFVLEVBQ3pCO1FBQUVQO01BQUssQ0FBQyxFQUNSdEIsTUFBTSxFQUNOeUIsUUFDRixDQUFDO01BQ0QsSUFBSUMsYUFBYSxFQUFFSixJQUFJLEVBQUVRLEtBQUssRUFBRTtRQUM5QmIsUUFBUSxHQUFHUyxhQUFhLENBQUNKLElBQUksQ0FBQ1EsS0FBSztNQUNyQztNQUNBLE1BQU1ZLElBQUksR0FBRyxNQUFNeEIsZUFBZSxDQUFDcUgsV0FBVyxDQUFDdEgsUUFBUSxDQUFDLENBQUN1QixLQUFLLENBQUMsTUFBTTtRQUNuRTdFLEdBQUcsQ0FBQ21ELE1BQU0sQ0FBQyxHQUFHLENBQUM7UUFDZm5ELEdBQUcsQ0FBQ29ELElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztNQUNkLENBQUMsQ0FBQztNQUNGLElBQUksQ0FBQzJCLElBQUksRUFBRTtRQUNUO01BQ0Y7TUFDQSxNQUFNcEgsUUFBUSxDQUFDcUcsbUJBQW1CLENBQ2hDckcsUUFBUSxDQUFDc0csS0FBSyxDQUFDSyxTQUFTLEVBQ3hCO1FBQUVYO01BQUssQ0FBQyxFQUNSdEIsTUFBTSxFQUNOeUIsUUFDRixDQUFDO01BQ0Q5RCxHQUFHLENBQUNtRCxNQUFNLENBQUMsR0FBRyxDQUFDO01BQ2ZuRCxHQUFHLENBQUNvRCxJQUFJLENBQUMyQixJQUFJLENBQUM7SUFDaEIsQ0FBQyxDQUFDLE9BQU92SSxDQUFDLEVBQUU7TUFDVixNQUFNeUMsR0FBRyxHQUFHdEIsUUFBUSxDQUFDMEgsWUFBWSxDQUFDN0ksQ0FBQyxFQUFFO1FBQ25DOEksSUFBSSxFQUFFMUcsYUFBSyxDQUFDQyxLQUFLLENBQUMwRyxhQUFhO1FBQy9CbEMsT0FBTyxFQUFFO01BQ1gsQ0FBQyxDQUFDO01BQ0ZyRCxHQUFHLENBQUNtRCxNQUFNLENBQUMsR0FBRyxDQUFDO01BQ2ZuRCxHQUFHLENBQUNvRCxJQUFJLENBQUM7UUFBRWtDLElBQUksRUFBRXJHLEdBQUcsQ0FBQ3FHLElBQUk7UUFBRXJDLEtBQUssRUFBRWhFLEdBQUcsQ0FBQ29FO01BQVEsQ0FBQyxDQUFDO0lBQ2xEO0VBQ0Y7QUFDRjtBQUFDOUQsT0FBQSxDQUFBQyxXQUFBLEdBQUFBLFdBQUE7QUFFRCxTQUFTNkUsZ0JBQWdCQSxDQUFDdEUsR0FBRyxFQUFFd0QsZUFBZSxFQUFFO0VBQzlDLE1BQU1zSCxLQUFLLEdBQUcsQ0FBQzlLLEdBQUcsQ0FBQzNDLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxLQUFLLEVBQUU2RSxLQUFLLENBQUMsR0FBRyxDQUFDO0VBQ3BELE1BQU02SSxLQUFLLEdBQUdDLE1BQU0sQ0FBQ0YsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0VBQzlCLE1BQU0vRixHQUFHLEdBQUdpRyxNQUFNLENBQUNGLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztFQUM1QixPQUNFLENBQUMsQ0FBQ0csS0FBSyxDQUFDRixLQUFLLENBQUMsSUFBSSxDQUFDRSxLQUFLLENBQUNsRyxHQUFHLENBQUMsS0FBSyxPQUFPdkIsZUFBZSxDQUFDK0csT0FBTyxDQUFDMUYsZ0JBQWdCLEtBQUssVUFBVTtBQUVwRyIsImlnbm9yZUxpc3QiOltdfQ==