parse-server 2.8.4 → 8.6.2
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.
- package/LICENSE +167 -25
- package/NOTICE +10 -0
- package/README.md +929 -278
- package/lib/AccountLockout.js +47 -30
- package/lib/Adapters/AdapterLoader.js +21 -6
- package/lib/Adapters/Analytics/AnalyticsAdapter.js +15 -12
- package/lib/Adapters/Auth/AuthAdapter.js +116 -13
- package/lib/Adapters/Auth/BaseCodeAuthAdapter.js +99 -0
- package/lib/Adapters/Auth/OAuth1Client.js +27 -46
- package/lib/Adapters/Auth/apple.js +123 -0
- package/lib/Adapters/Auth/facebook.js +162 -35
- package/lib/Adapters/Auth/gcenter.js +217 -0
- package/lib/Adapters/Auth/github.js +118 -48
- package/lib/Adapters/Auth/google.js +160 -51
- package/lib/Adapters/Auth/gpgames.js +125 -0
- package/lib/Adapters/Auth/httpsRequest.js +6 -7
- package/lib/Adapters/Auth/index.js +170 -62
- package/lib/Adapters/Auth/instagram.js +114 -40
- package/lib/Adapters/Auth/janraincapture.js +52 -23
- package/lib/Adapters/Auth/janrainengage.js +19 -36
- package/lib/Adapters/Auth/keycloak.js +148 -0
- package/lib/Adapters/Auth/ldap.js +167 -0
- package/lib/Adapters/Auth/line.js +125 -0
- package/lib/Adapters/Auth/linkedin.js +111 -55
- package/lib/Adapters/Auth/meetup.js +24 -34
- package/lib/Adapters/Auth/mfa.js +324 -0
- package/lib/Adapters/Auth/microsoft.js +111 -0
- package/lib/Adapters/Auth/oauth2.js +97 -162
- package/lib/Adapters/Auth/phantauth.js +53 -0
- package/lib/Adapters/Auth/qq.js +108 -49
- package/lib/Adapters/Auth/spotify.js +107 -55
- package/lib/Adapters/Auth/twitter.js +188 -48
- package/lib/Adapters/Auth/utils.js +28 -0
- package/lib/Adapters/Auth/vkontakte.js +26 -39
- package/lib/Adapters/Auth/wechat.js +106 -44
- package/lib/Adapters/Auth/weibo.js +132 -58
- package/lib/Adapters/Cache/CacheAdapter.js +13 -8
- package/lib/Adapters/Cache/InMemoryCache.js +3 -13
- package/lib/Adapters/Cache/InMemoryCacheAdapter.js +5 -13
- package/lib/Adapters/Cache/LRUCache.js +13 -27
- package/lib/Adapters/Cache/NullCacheAdapter.js +3 -8
- package/lib/Adapters/Cache/RedisCacheAdapter.js +85 -76
- package/lib/Adapters/Cache/SchemaCache.js +25 -0
- package/lib/Adapters/Email/MailAdapter.js +10 -8
- package/lib/Adapters/Files/FilesAdapter.js +83 -25
- package/lib/Adapters/Files/GridFSBucketAdapter.js +231 -0
- package/lib/Adapters/Files/GridStoreAdapter.js +4 -91
- package/lib/Adapters/Logger/LoggerAdapter.js +18 -14
- package/lib/Adapters/Logger/WinstonLogger.js +69 -88
- package/lib/Adapters/Logger/WinstonLoggerAdapter.js +7 -16
- package/lib/Adapters/MessageQueue/EventEmitterMQ.js +8 -26
- package/lib/Adapters/PubSub/EventEmitterPubSub.js +12 -25
- package/lib/Adapters/PubSub/PubSubAdapter.js +34 -0
- package/lib/Adapters/PubSub/RedisPubSub.js +42 -19
- package/lib/Adapters/Push/PushAdapter.js +14 -7
- package/lib/Adapters/Storage/Mongo/MongoCollection.js +137 -45
- package/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js +158 -63
- package/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js +320 -168
- package/lib/Adapters/Storage/Mongo/MongoTransform.js +279 -306
- package/lib/Adapters/Storage/Postgres/PostgresClient.js +14 -10
- package/lib/Adapters/Storage/Postgres/PostgresConfigParser.js +47 -21
- package/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js +854 -468
- package/lib/Adapters/Storage/Postgres/sql/index.js +4 -6
- package/lib/Adapters/Storage/StorageAdapter.js +1 -1
- package/lib/Adapters/WebSocketServer/WSAdapter.js +35 -0
- package/lib/Adapters/WebSocketServer/WSSAdapter.js +66 -0
- package/lib/Auth.js +488 -125
- package/lib/ClientSDK.js +2 -6
- package/lib/Config.js +525 -94
- package/lib/Controllers/AdaptableController.js +5 -25
- package/lib/Controllers/AnalyticsController.js +22 -23
- package/lib/Controllers/CacheController.js +10 -31
- package/lib/Controllers/DatabaseController.js +767 -313
- package/lib/Controllers/FilesController.js +49 -54
- package/lib/Controllers/HooksController.js +80 -84
- package/lib/Controllers/LiveQueryController.js +35 -22
- package/lib/Controllers/LoggerController.js +22 -58
- package/lib/Controllers/ParseGraphQLController.js +293 -0
- package/lib/Controllers/PushController.js +58 -49
- package/lib/Controllers/SchemaController.js +916 -422
- package/lib/Controllers/UserController.js +265 -180
- package/lib/Controllers/index.js +90 -125
- package/lib/Controllers/types.js +1 -1
- package/lib/Deprecator/Deprecations.js +30 -0
- package/lib/Deprecator/Deprecator.js +127 -0
- package/lib/Error.js +48 -0
- package/lib/GraphQL/ParseGraphQLSchema.js +375 -0
- package/lib/GraphQL/ParseGraphQLServer.js +214 -0
- package/lib/GraphQL/helpers/objectsMutations.js +30 -0
- package/lib/GraphQL/helpers/objectsQueries.js +246 -0
- package/lib/GraphQL/loaders/configMutations.js +87 -0
- package/lib/GraphQL/loaders/configQueries.js +79 -0
- package/lib/GraphQL/loaders/defaultGraphQLMutations.js +21 -0
- package/lib/GraphQL/loaders/defaultGraphQLQueries.js +23 -0
- package/lib/GraphQL/loaders/defaultGraphQLTypes.js +1098 -0
- package/lib/GraphQL/loaders/defaultRelaySchema.js +53 -0
- package/lib/GraphQL/loaders/filesMutations.js +107 -0
- package/lib/GraphQL/loaders/functionsMutations.js +78 -0
- package/lib/GraphQL/loaders/parseClassMutations.js +268 -0
- package/lib/GraphQL/loaders/parseClassQueries.js +127 -0
- package/lib/GraphQL/loaders/parseClassTypes.js +493 -0
- package/lib/GraphQL/loaders/schemaDirectives.js +62 -0
- package/lib/GraphQL/loaders/schemaMutations.js +162 -0
- package/lib/GraphQL/loaders/schemaQueries.js +81 -0
- package/lib/GraphQL/loaders/schemaTypes.js +341 -0
- package/lib/GraphQL/loaders/usersMutations.js +433 -0
- package/lib/GraphQL/loaders/usersQueries.js +90 -0
- package/lib/GraphQL/parseGraphQLUtils.js +63 -0
- package/lib/GraphQL/transformers/className.js +14 -0
- package/lib/GraphQL/transformers/constraintType.js +53 -0
- package/lib/GraphQL/transformers/inputType.js +51 -0
- package/lib/GraphQL/transformers/mutation.js +274 -0
- package/lib/GraphQL/transformers/outputType.js +51 -0
- package/lib/GraphQL/transformers/query.js +237 -0
- package/lib/GraphQL/transformers/schemaFields.js +99 -0
- package/lib/KeyPromiseQueue.js +48 -0
- package/lib/LiveQuery/Client.js +25 -33
- package/lib/LiveQuery/Id.js +2 -5
- package/lib/LiveQuery/ParseCloudCodePublisher.js +26 -23
- package/lib/LiveQuery/ParseLiveQueryServer.js +560 -285
- package/lib/LiveQuery/ParsePubSub.js +7 -16
- package/lib/LiveQuery/ParseWebSocketServer.js +42 -39
- package/lib/LiveQuery/QueryTools.js +76 -15
- package/lib/LiveQuery/RequestSchema.js +111 -97
- package/lib/LiveQuery/SessionTokenCache.js +23 -36
- package/lib/LiveQuery/Subscription.js +8 -17
- package/lib/LiveQuery/equalObjects.js +2 -3
- package/lib/Options/Definitions.js +1355 -382
- package/lib/Options/docs.js +301 -62
- package/lib/Options/index.js +11 -1
- package/lib/Options/parsers.js +14 -10
- package/lib/Page.js +44 -0
- package/lib/ParseMessageQueue.js +6 -13
- package/lib/ParseServer.js +474 -235
- package/lib/ParseServerRESTController.js +102 -40
- package/lib/PromiseRouter.js +39 -50
- package/lib/Push/PushQueue.js +24 -30
- package/lib/Push/PushWorker.js +32 -56
- package/lib/Push/utils.js +22 -35
- package/lib/RestQuery.js +361 -139
- package/lib/RestWrite.js +713 -344
- package/lib/Routers/AggregateRouter.js +97 -71
- package/lib/Routers/AnalyticsRouter.js +8 -14
- package/lib/Routers/AudiencesRouter.js +16 -35
- package/lib/Routers/ClassesRouter.js +86 -72
- package/lib/Routers/CloudCodeRouter.js +28 -37
- package/lib/Routers/FeaturesRouter.js +22 -25
- package/lib/Routers/FilesRouter.js +266 -171
- package/lib/Routers/FunctionsRouter.js +87 -103
- package/lib/Routers/GlobalConfigRouter.js +94 -33
- package/lib/Routers/GraphQLRouter.js +41 -0
- package/lib/Routers/HooksRouter.js +43 -47
- package/lib/Routers/IAPValidationRouter.js +57 -70
- package/lib/Routers/InstallationsRouter.js +17 -25
- package/lib/Routers/LogsRouter.js +10 -25
- package/lib/Routers/PagesRouter.js +647 -0
- package/lib/Routers/PublicAPIRouter.js +104 -112
- package/lib/Routers/PurgeRouter.js +19 -29
- package/lib/Routers/PushRouter.js +14 -28
- package/lib/Routers/RolesRouter.js +7 -14
- package/lib/Routers/SchemasRouter.js +63 -42
- package/lib/Routers/SecurityRouter.js +34 -0
- package/lib/Routers/SessionsRouter.js +25 -38
- package/lib/Routers/UsersRouter.js +463 -190
- package/lib/SchemaMigrations/DefinedSchemas.js +379 -0
- package/lib/SchemaMigrations/Migrations.js +30 -0
- package/lib/Security/Check.js +109 -0
- package/lib/Security/CheckGroup.js +44 -0
- package/lib/Security/CheckGroups/CheckGroupDatabase.js +44 -0
- package/lib/Security/CheckGroups/CheckGroupServerConfig.js +96 -0
- package/lib/Security/CheckGroups/CheckGroups.js +21 -0
- package/lib/Security/CheckRunner.js +213 -0
- package/lib/SharedRest.js +29 -0
- package/lib/StatusHandler.js +96 -93
- package/lib/TestUtils.js +70 -14
- package/lib/Utils.js +468 -0
- package/lib/batch.js +74 -40
- package/lib/cache.js +8 -8
- package/lib/cli/definitions/parse-live-query-server.js +4 -3
- package/lib/cli/definitions/parse-server.js +4 -3
- package/lib/cli/parse-live-query-server.js +9 -17
- package/lib/cli/parse-server.js +49 -47
- package/lib/cli/utils/commander.js +20 -29
- package/lib/cli/utils/runner.js +31 -32
- package/lib/cloud-code/Parse.Cloud.js +711 -36
- package/lib/cloud-code/Parse.Server.js +21 -0
- package/lib/cryptoUtils.js +6 -11
- package/lib/defaults.js +21 -15
- package/lib/deprecated.js +1 -1
- package/lib/index.js +78 -67
- package/lib/logger.js +12 -20
- package/lib/middlewares.js +484 -160
- package/lib/password.js +10 -6
- package/lib/request.js +175 -0
- package/lib/requiredParameter.js +4 -3
- package/lib/rest.js +157 -82
- package/lib/triggers.js +627 -185
- package/lib/vendor/README.md +3 -3
- package/lib/vendor/mongodbUrl.js +224 -137
- package/package.json +135 -57
- package/postinstall.js +38 -50
- package/public_html/invalid_verification_link.html +3 -3
- package/types/@types/@parse/fs-files-adapter/index.d.ts +5 -0
- package/types/@types/deepcopy/index.d.ts +5 -0
- package/types/LiveQuery/ParseLiveQueryServer.d.ts +40 -0
- package/types/Options/index.d.ts +301 -0
- package/types/ParseServer.d.ts +65 -0
- package/types/eslint.config.mjs +30 -0
- package/types/index.d.ts +21 -0
- package/types/logger.d.ts +2 -0
- package/types/tests.ts +44 -0
- package/types/tsconfig.json +24 -0
- package/CHANGELOG.md +0 -1246
- package/PATENTS +0 -37
- package/bin/dev +0 -37
- package/lib/.DS_Store +0 -0
- package/lib/Adapters/Auth/common.js +0 -2
- package/lib/Adapters/Auth/facebookaccountkit.js +0 -69
- package/lib/Controllers/SchemaCache.js +0 -97
- package/lib/LiveQuery/.DS_Store +0 -0
- package/lib/cli/utils/parsers.js +0 -77
- package/lib/cloud-code/.DS_Store +0 -0
- package/lib/cloud-code/HTTPResponse.js +0 -57
- package/lib/cloud-code/Untitled-1 +0 -123
- package/lib/cloud-code/httpRequest.js +0 -102
- package/lib/cloud-code/team.html +0 -123
- package/lib/graphql/ParseClass.js +0 -234
- package/lib/graphql/Schema.js +0 -197
- package/lib/graphql/index.js +0 -1
- package/lib/graphql/types/ACL.js +0 -35
- package/lib/graphql/types/Date.js +0 -25
- package/lib/graphql/types/File.js +0 -24
- package/lib/graphql/types/GeoPoint.js +0 -35
- package/lib/graphql/types/JSONObject.js +0 -30
- package/lib/graphql/types/NumberInput.js +0 -43
- package/lib/graphql/types/NumberQuery.js +0 -42
- package/lib/graphql/types/Pointer.js +0 -35
- package/lib/graphql/types/QueryConstraint.js +0 -61
- package/lib/graphql/types/StringQuery.js +0 -39
- package/lib/graphql/types/index.js +0 -110
|
@@ -1,206 +1,301 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.FilesRouter =
|
|
7
|
-
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
var
|
|
11
|
-
|
|
12
|
-
var
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
var _middlewares = require('../middlewares');
|
|
17
|
-
|
|
18
|
-
var Middlewares = _interopRequireWildcard(_middlewares);
|
|
19
|
-
|
|
20
|
-
var _node = require('parse/node');
|
|
21
|
-
|
|
22
|
-
var _node2 = _interopRequireDefault(_node);
|
|
23
|
-
|
|
24
|
-
var _Config = require('../Config');
|
|
25
|
-
|
|
26
|
-
var _Config2 = _interopRequireDefault(_Config);
|
|
27
|
-
|
|
28
|
-
var _mime = require('mime');
|
|
29
|
-
|
|
30
|
-
var _mime2 = _interopRequireDefault(_mime);
|
|
31
|
-
|
|
32
|
-
var _logger = require('../logger');
|
|
33
|
-
|
|
34
|
-
var _logger2 = _interopRequireDefault(_logger);
|
|
35
|
-
|
|
36
|
-
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
|
|
37
|
-
|
|
38
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
39
|
-
|
|
6
|
+
exports.FilesRouter = void 0;
|
|
7
|
+
var _express = _interopRequireDefault(require("express"));
|
|
8
|
+
var Middlewares = _interopRequireWildcard(require("../middlewares"));
|
|
9
|
+
var _node = _interopRequireDefault(require("parse/node"));
|
|
10
|
+
var _Config = _interopRequireDefault(require("../Config"));
|
|
11
|
+
var _logger = _interopRequireDefault(require("../logger"));
|
|
12
|
+
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); }
|
|
13
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
|
+
const triggers = require('../triggers');
|
|
15
|
+
const Utils = require('../Utils');
|
|
40
16
|
class FilesRouter {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
17
|
+
expressRouter({
|
|
18
|
+
maxUploadSize = '20Mb'
|
|
19
|
+
} = {}) {
|
|
20
|
+
var router = _express.default.Router();
|
|
44
21
|
router.get('/files/:appId/:filename', this.getHandler);
|
|
45
|
-
|
|
22
|
+
router.get('/files/:appId/metadata/:filename', this.metadataHandler);
|
|
46
23
|
router.post('/files', function (req, res, next) {
|
|
47
|
-
next(new
|
|
24
|
+
next(new _node.default.Error(_node.default.Error.INVALID_FILE_NAME, 'Filename not provided.'));
|
|
48
25
|
});
|
|
49
|
-
|
|
50
|
-
|
|
26
|
+
router.post('/files/:filename', _express.default.raw({
|
|
27
|
+
type: () => {
|
|
51
28
|
return true;
|
|
52
|
-
},
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
29
|
+
},
|
|
30
|
+
limit: maxUploadSize
|
|
31
|
+
}),
|
|
32
|
+
// Allow uploads without Content-Type, or with any Content-Type.
|
|
33
|
+
Middlewares.handleParseHeaders, Middlewares.handleParseSession, this.createHandler);
|
|
34
|
+
router.delete('/files/:filename', Middlewares.handleParseHeaders, Middlewares.handleParseSession, Middlewares.enforceMasterKeyAccess, this.deleteHandler);
|
|
56
35
|
return router;
|
|
57
36
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
filesController.getFileStream(config, filename).then(stream => {
|
|
66
|
-
handleFileStream(stream, req, res, contentType);
|
|
67
|
-
}).catch(() => {
|
|
68
|
-
res.status(404);
|
|
69
|
-
res.set('Content-Type', 'text/plain');
|
|
70
|
-
res.end('File not found.');
|
|
37
|
+
async getHandler(req, res) {
|
|
38
|
+
const config = _Config.default.get(req.params.appId);
|
|
39
|
+
if (!config) {
|
|
40
|
+
res.status(403);
|
|
41
|
+
res.json({
|
|
42
|
+
code: _node.default.Error.OPERATION_FORBIDDEN,
|
|
43
|
+
error: 'Invalid application ID.'
|
|
71
44
|
});
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
let filename = req.params.filename;
|
|
48
|
+
try {
|
|
49
|
+
const filesController = config.filesController;
|
|
50
|
+
const mime = (await import('mime')).default;
|
|
51
|
+
let contentType = mime.getType(filename);
|
|
52
|
+
let file = new _node.default.File(filename, {
|
|
53
|
+
base64: ''
|
|
54
|
+
}, contentType);
|
|
55
|
+
const triggerResult = await triggers.maybeRunFileTrigger(triggers.Types.beforeFind, {
|
|
56
|
+
file
|
|
57
|
+
}, config, req.auth);
|
|
58
|
+
if (triggerResult?.file?._name) {
|
|
59
|
+
filename = triggerResult?.file?._name;
|
|
60
|
+
contentType = mime.getType(filename);
|
|
61
|
+
}
|
|
62
|
+
if (isFileStreamable(req, filesController)) {
|
|
63
|
+
filesController.handleFileStream(config, filename, req, res, contentType).catch(() => {
|
|
64
|
+
res.status(404);
|
|
65
|
+
res.set('Content-Type', 'text/plain');
|
|
66
|
+
res.end('File not found.');
|
|
67
|
+
});
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
let data = await filesController.getFileData(config, filename).catch(() => {
|
|
79
71
|
res.status(404);
|
|
80
72
|
res.set('Content-Type', 'text/plain');
|
|
81
73
|
res.end('File not found.');
|
|
82
74
|
});
|
|
75
|
+
if (!data) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
file = new _node.default.File(filename, {
|
|
79
|
+
base64: data.toString('base64')
|
|
80
|
+
}, contentType);
|
|
81
|
+
const afterFind = await triggers.maybeRunFileTrigger(triggers.Types.afterFind, {
|
|
82
|
+
file,
|
|
83
|
+
forceDownload: false
|
|
84
|
+
}, config, req.auth);
|
|
85
|
+
if (afterFind?.file) {
|
|
86
|
+
contentType = mime.getType(afterFind.file._name);
|
|
87
|
+
data = Buffer.from(afterFind.file._data, 'base64');
|
|
88
|
+
}
|
|
89
|
+
res.status(200);
|
|
90
|
+
res.set('Content-Type', contentType);
|
|
91
|
+
res.set('Content-Length', data.length);
|
|
92
|
+
if (afterFind.forceDownload) {
|
|
93
|
+
res.set('Content-Disposition', `attachment;filename=${afterFind.file._name}`);
|
|
94
|
+
}
|
|
95
|
+
res.end(data);
|
|
96
|
+
} catch (e) {
|
|
97
|
+
const err = triggers.resolveError(e, {
|
|
98
|
+
code: _node.default.Error.SCRIPT_FAILED,
|
|
99
|
+
message: `Could not find file: ${filename}.`
|
|
100
|
+
});
|
|
101
|
+
res.status(403);
|
|
102
|
+
res.json({
|
|
103
|
+
code: err.code,
|
|
104
|
+
error: err.message
|
|
105
|
+
});
|
|
83
106
|
}
|
|
84
107
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
108
|
+
async createHandler(req, res, next) {
|
|
109
|
+
const config = req.config;
|
|
110
|
+
const user = req.auth.user;
|
|
111
|
+
const isMaster = req.auth.isMaster;
|
|
112
|
+
const isLinked = user && _node.default.AnonymousUtils.isLinked(user);
|
|
113
|
+
if (!isMaster && !config.fileUpload.enableForAnonymousUser && isLinked) {
|
|
114
|
+
next(new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, 'File upload by anonymous user is disabled.'));
|
|
89
115
|
return;
|
|
90
116
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
next(new _node2.default.Error(_node2.default.Error.INVALID_FILE_NAME, 'Filename too long.'));
|
|
117
|
+
if (!isMaster && !config.fileUpload.enableForAuthenticatedUser && !isLinked && user) {
|
|
118
|
+
next(new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, 'File upload by authenticated user is disabled.'));
|
|
94
119
|
return;
|
|
95
120
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
next(new _node2.default.Error(_node2.default.Error.INVALID_FILE_NAME, 'Filename contains invalid characters.'));
|
|
121
|
+
if (!isMaster && !config.fileUpload.enableForPublic && !user) {
|
|
122
|
+
next(new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, 'File upload by public is disabled.'));
|
|
99
123
|
return;
|
|
100
124
|
}
|
|
101
|
-
|
|
102
|
-
const filename = req.params.filename;
|
|
103
|
-
const contentType = req.get('Content-type');
|
|
104
|
-
const config = req.config;
|
|
105
125
|
const filesController = config.filesController;
|
|
106
|
-
|
|
107
|
-
|
|
126
|
+
const {
|
|
127
|
+
filename
|
|
128
|
+
} = req.params;
|
|
129
|
+
const contentType = req.get('Content-type');
|
|
130
|
+
if (!req.body || !req.body.length) {
|
|
131
|
+
next(new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, 'Invalid file upload.'));
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const error = filesController.validateFilename(filename);
|
|
135
|
+
if (error) {
|
|
136
|
+
next(error);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const fileExtensions = config.fileUpload?.fileExtensions;
|
|
140
|
+
if (!isMaster && fileExtensions) {
|
|
141
|
+
const isValidExtension = extension => {
|
|
142
|
+
return fileExtensions.some(ext => {
|
|
143
|
+
if (ext === '*') {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
const regex = new RegExp(ext);
|
|
147
|
+
if (regex.test(extension)) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
let extension = contentType;
|
|
153
|
+
if (filename && filename.includes('.')) {
|
|
154
|
+
extension = filename.substring(filename.lastIndexOf('.') + 1);
|
|
155
|
+
} else if (contentType && contentType.includes('/')) {
|
|
156
|
+
extension = contentType.split('/')[1];
|
|
157
|
+
}
|
|
158
|
+
extension = extension?.split(' ')?.join('');
|
|
159
|
+
if (extension && !isValidExtension(extension)) {
|
|
160
|
+
next(new _node.default.Error(_node.default.Error.FILE_SAVE_ERROR, `File upload of extension ${extension} is disabled.`));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const base64 = req.body.toString('base64');
|
|
165
|
+
const file = new _node.default.File(filename, {
|
|
166
|
+
base64
|
|
167
|
+
}, contentType);
|
|
168
|
+
const {
|
|
169
|
+
metadata = {},
|
|
170
|
+
tags = {}
|
|
171
|
+
} = req.fileData || {};
|
|
172
|
+
try {
|
|
173
|
+
// Scan request data for denied keywords
|
|
174
|
+
Utils.checkProhibitedKeywords(config, metadata);
|
|
175
|
+
Utils.checkProhibitedKeywords(config, tags);
|
|
176
|
+
} catch (error) {
|
|
177
|
+
next(new _node.default.Error(_node.default.Error.INVALID_KEY_NAME, error));
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
file.setTags(tags);
|
|
181
|
+
file.setMetadata(metadata);
|
|
182
|
+
const fileSize = Buffer.byteLength(req.body);
|
|
183
|
+
const fileObject = {
|
|
184
|
+
file,
|
|
185
|
+
fileSize
|
|
186
|
+
};
|
|
187
|
+
try {
|
|
188
|
+
// run beforeSaveFile trigger
|
|
189
|
+
const triggerResult = await triggers.maybeRunFileTrigger(triggers.Types.beforeSave, fileObject, config, req.auth);
|
|
190
|
+
let saveResult;
|
|
191
|
+
// if a new ParseFile is returned check if it's an already saved file
|
|
192
|
+
if (triggerResult instanceof _node.default.File) {
|
|
193
|
+
fileObject.file = triggerResult;
|
|
194
|
+
if (triggerResult.url()) {
|
|
195
|
+
// set fileSize to null because we wont know how big it is here
|
|
196
|
+
fileObject.fileSize = null;
|
|
197
|
+
saveResult = {
|
|
198
|
+
url: triggerResult.url(),
|
|
199
|
+
name: triggerResult._name
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// if the file returned by the trigger has already been saved skip saving anything
|
|
204
|
+
if (!saveResult) {
|
|
205
|
+
// update fileSize
|
|
206
|
+
const bufferData = Buffer.from(fileObject.file._data, 'base64');
|
|
207
|
+
fileObject.fileSize = Buffer.byteLength(bufferData);
|
|
208
|
+
// prepare file options
|
|
209
|
+
const fileOptions = {
|
|
210
|
+
metadata: fileObject.file._metadata
|
|
211
|
+
};
|
|
212
|
+
// some s3-compatible providers (DigitalOcean, Linode) do not accept tags
|
|
213
|
+
// so we do not include the tags option if it is empty.
|
|
214
|
+
const fileTags = Object.keys(fileObject.file._tags).length > 0 ? {
|
|
215
|
+
tags: fileObject.file._tags
|
|
216
|
+
} : {};
|
|
217
|
+
Object.assign(fileOptions, fileTags);
|
|
218
|
+
// save file
|
|
219
|
+
const createFileResult = await filesController.createFile(config, fileObject.file._name, bufferData, fileObject.file._source.type, fileOptions);
|
|
220
|
+
// update file with new data
|
|
221
|
+
fileObject.file._name = createFileResult.name;
|
|
222
|
+
fileObject.file._url = createFileResult.url;
|
|
223
|
+
fileObject.file._requestTask = null;
|
|
224
|
+
fileObject.file._previousSave = Promise.resolve(fileObject.file);
|
|
225
|
+
saveResult = {
|
|
226
|
+
url: createFileResult.url,
|
|
227
|
+
name: createFileResult.name
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
// run afterSaveFile trigger
|
|
231
|
+
await triggers.maybeRunFileTrigger(triggers.Types.afterSave, fileObject, config, req.auth);
|
|
108
232
|
res.status(201);
|
|
109
|
-
res.set('Location',
|
|
110
|
-
res.json(
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
233
|
+
res.set('Location', saveResult.url);
|
|
234
|
+
res.json(saveResult);
|
|
235
|
+
} catch (e) {
|
|
236
|
+
_logger.default.error('Error creating a file: ', e);
|
|
237
|
+
const error = triggers.resolveError(e, {
|
|
238
|
+
code: _node.default.Error.FILE_SAVE_ERROR,
|
|
239
|
+
message: `Could not store file: ${fileObject.file._name}.`
|
|
240
|
+
});
|
|
241
|
+
next(error);
|
|
242
|
+
}
|
|
115
243
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
244
|
+
async deleteHandler(req, res, next) {
|
|
245
|
+
try {
|
|
246
|
+
const {
|
|
247
|
+
filesController
|
|
248
|
+
} = req.config;
|
|
249
|
+
const {
|
|
250
|
+
filename
|
|
251
|
+
} = req.params;
|
|
252
|
+
// run beforeDeleteFile trigger
|
|
253
|
+
const file = new _node.default.File(filename);
|
|
254
|
+
file._url = await filesController.adapter.getFileLocation(req.config, filename);
|
|
255
|
+
const fileObject = {
|
|
256
|
+
file,
|
|
257
|
+
fileSize: null
|
|
258
|
+
};
|
|
259
|
+
await triggers.maybeRunFileTrigger(triggers.Types.beforeDelete, fileObject, req.config, req.auth);
|
|
260
|
+
// delete file
|
|
261
|
+
await filesController.deleteFile(req.config, filename);
|
|
262
|
+
// run afterDeleteFile trigger
|
|
263
|
+
await triggers.maybeRunFileTrigger(triggers.Types.afterDelete, fileObject, req.config, req.auth);
|
|
120
264
|
res.status(200);
|
|
121
265
|
// TODO: return useful JSON here?
|
|
122
266
|
res.end();
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
|
|
267
|
+
} catch (e) {
|
|
268
|
+
_logger.default.error('Error deleting a file: ', e);
|
|
269
|
+
const error = triggers.resolveError(e, {
|
|
270
|
+
code: _node.default.Error.FILE_DELETE_ERROR,
|
|
271
|
+
message: 'Could not delete file.'
|
|
272
|
+
});
|
|
273
|
+
next(error);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
async metadataHandler(req, res) {
|
|
277
|
+
try {
|
|
278
|
+
const config = _Config.default.get(req.params.appId);
|
|
279
|
+
const {
|
|
280
|
+
filesController
|
|
281
|
+
} = config;
|
|
282
|
+
const {
|
|
283
|
+
filename
|
|
284
|
+
} = req.params;
|
|
285
|
+
const data = await filesController.getMetadata(filename);
|
|
286
|
+
res.status(200);
|
|
287
|
+
res.json(data);
|
|
288
|
+
} catch {
|
|
289
|
+
res.status(200);
|
|
290
|
+
res.json({});
|
|
291
|
+
}
|
|
126
292
|
}
|
|
127
293
|
}
|
|
128
|
-
|
|
129
294
|
exports.FilesRouter = FilesRouter;
|
|
130
295
|
function isFileStreamable(req, filesController) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const parts = req.get('Range').replace(/bytes=/, "").split("-");
|
|
136
|
-
return { start: parseInt(parts[0], 10), end: parseInt(parts[1], 10) };
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// handleFileStream is licenced under Creative Commons Attribution 4.0 International License (https://creativecommons.org/licenses/by/4.0/).
|
|
140
|
-
// Author: LEROIB at weightingformypizza (https://weightingformypizza.wordpress.com/2015/06/24/stream-html5-media-content-like-video-audio-from-mongodb-using-express-and-gridstore/).
|
|
141
|
-
function handleFileStream(stream, req, res, contentType) {
|
|
142
|
-
const buffer_size = 1024 * 1024; //1024Kb
|
|
143
|
-
// Range request, partiall stream the file
|
|
144
|
-
let {
|
|
145
|
-
start, end
|
|
146
|
-
} = getRange(req);
|
|
147
|
-
|
|
148
|
-
const notEnded = !end && end !== 0;
|
|
149
|
-
const notStarted = !start && start !== 0;
|
|
150
|
-
// No end provided, we want all bytes
|
|
151
|
-
if (notEnded) {
|
|
152
|
-
end = stream.length - 1;
|
|
153
|
-
}
|
|
154
|
-
// No start provided, we're reading backwards
|
|
155
|
-
if (notStarted) {
|
|
156
|
-
start = stream.length - end;
|
|
157
|
-
end = start + end - 1;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Data exceeds the buffer_size, cap
|
|
161
|
-
if (end - start >= buffer_size) {
|
|
162
|
-
end = start + buffer_size - 1;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const contentLength = end - start + 1;
|
|
166
|
-
|
|
167
|
-
res.writeHead(206, {
|
|
168
|
-
'Content-Range': 'bytes ' + start + '-' + end + '/' + stream.length,
|
|
169
|
-
'Accept-Ranges': 'bytes',
|
|
170
|
-
'Content-Length': contentLength,
|
|
171
|
-
'Content-Type': contentType
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
stream.seek(start, function () {
|
|
175
|
-
// get gridFile stream
|
|
176
|
-
const gridFileStream = stream.stream(true);
|
|
177
|
-
let bufferAvail = 0;
|
|
178
|
-
let remainingBytesToWrite = contentLength;
|
|
179
|
-
let totalBytesWritten = 0;
|
|
180
|
-
// write to response
|
|
181
|
-
gridFileStream.on('data', function (data) {
|
|
182
|
-
bufferAvail += data.length;
|
|
183
|
-
if (bufferAvail > 0) {
|
|
184
|
-
// slice returns the same buffer if overflowing
|
|
185
|
-
// safe to call in any case
|
|
186
|
-
const buffer = data.slice(0, remainingBytesToWrite);
|
|
187
|
-
// write the buffer
|
|
188
|
-
res.write(buffer);
|
|
189
|
-
// increment total
|
|
190
|
-
totalBytesWritten += buffer.length;
|
|
191
|
-
// decrement remaining
|
|
192
|
-
remainingBytesToWrite -= data.length;
|
|
193
|
-
// decrement the avaialbe buffer
|
|
194
|
-
bufferAvail -= buffer.length;
|
|
195
|
-
}
|
|
196
|
-
// in case of small slices, all values will be good at that point
|
|
197
|
-
// we've written enough, end...
|
|
198
|
-
if (totalBytesWritten >= contentLength) {
|
|
199
|
-
stream.close();
|
|
200
|
-
res.end();
|
|
201
|
-
this.destroy();
|
|
202
|
-
}
|
|
203
|
-
});
|
|
204
|
-
});
|
|
296
|
+
const range = (req.get('Range') || '/-/').split('-');
|
|
297
|
+
const start = Number(range[0]);
|
|
298
|
+
const end = Number(range[1]);
|
|
299
|
+
return (!isNaN(start) || !isNaN(end)) && typeof filesController.adapter.handleFileStream === 'function';
|
|
205
300
|
}
|
|
206
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0ZpbGVzUm91dGVyLmpzIl0sIm5hbWVzIjpbIk1pZGRsZXdhcmVzIiwiRmlsZXNSb3V0ZXIiLCJleHByZXNzUm91dGVyIiwibWF4VXBsb2FkU2l6ZSIsInJvdXRlciIsImV4cHJlc3MiLCJSb3V0ZXIiLCJnZXQiLCJnZXRIYW5kbGVyIiwicG9zdCIsInJlcSIsInJlcyIsIm5leHQiLCJQYXJzZSIsIkVycm9yIiwiSU5WQUxJRF9GSUxFX05BTUUiLCJhbGxvd0Nyb3NzRG9tYWluIiwiQm9keVBhcnNlciIsInJhdyIsInR5cGUiLCJsaW1pdCIsImhhbmRsZVBhcnNlSGVhZGVycyIsImNyZWF0ZUhhbmRsZXIiLCJkZWxldGUiLCJlbmZvcmNlTWFzdGVyS2V5QWNjZXNzIiwiZGVsZXRlSGFuZGxlciIsImNvbmZpZyIsIkNvbmZpZyIsInBhcmFtcyIsImFwcElkIiwiZmlsZXNDb250cm9sbGVyIiwiZmlsZW5hbWUiLCJjb250ZW50VHlwZSIsIm1pbWUiLCJnZXRUeXBlIiwiaXNGaWxlU3RyZWFtYWJsZSIsImdldEZpbGVTdHJlYW0iLCJ0aGVuIiwic3RyZWFtIiwiaGFuZGxlRmlsZVN0cmVhbSIsImNhdGNoIiwic3RhdHVzIiwic2V0IiwiZW5kIiwiZ2V0RmlsZURhdGEiLCJkYXRhIiwibGVuZ3RoIiwiYm9keSIsIkZJTEVfU0FWRV9FUlJPUiIsIm1hdGNoIiwiY3JlYXRlRmlsZSIsInJlc3VsdCIsInVybCIsImpzb24iLCJlIiwibG9nZ2VyIiwiZXJyb3IiLCJtZXNzYWdlIiwiZGVsZXRlRmlsZSIsIkZJTEVfREVMRVRFX0VSUk9SIiwiYWRhcHRlciIsImdldFJhbmdlIiwicGFydHMiLCJyZXBsYWNlIiwic3BsaXQiLCJzdGFydCIsInBhcnNlSW50IiwiYnVmZmVyX3NpemUiLCJub3RFbmRlZCIsIm5vdFN0YXJ0ZWQiLCJjb250ZW50TGVuZ3RoIiwid3JpdGVIZWFkIiwic2VlayIsImdyaWRGaWxlU3RyZWFtIiwiYnVmZmVyQXZhaWwiLCJyZW1haW5pbmdCeXRlc1RvV3JpdGUiLCJ0b3RhbEJ5dGVzV3JpdHRlbiIsIm9uIiwiYnVmZmVyIiwic2xpY2UiLCJ3cml0ZSIsImNsb3NlIiwiZGVzdHJveSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOzs7O0FBQ0E7Ozs7QUFDQTs7SUFBWUEsVzs7QUFDWjs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7Ozs7QUFFTyxNQUFNQyxXQUFOLENBQWtCOztBQUV2QkMsZ0JBQWMsRUFBRUMsZ0JBQWdCLE1BQWxCLEtBQTZCLEVBQTNDLEVBQStDO0FBQzdDLFFBQUlDLFNBQVNDLGtCQUFRQyxNQUFSLEVBQWI7QUFDQUYsV0FBT0csR0FBUCxDQUFXLHlCQUFYLEVBQXNDLEtBQUtDLFVBQTNDOztBQUVBSixXQUFPSyxJQUFQLENBQVksUUFBWixFQUFzQixVQUFTQyxHQUFULEVBQWNDLEdBQWQsRUFBbUJDLElBQW5CLEVBQXlCO0FBQzdDQSxXQUFLLElBQUlDLGVBQU1DLEtBQVYsQ0FBZ0JELGVBQU1DLEtBQU4sQ0FBWUMsaUJBQTVCLEVBQ0gsd0JBREcsQ0FBTDtBQUVELEtBSEQ7O0FBS0FYLFdBQU9LLElBQVAsQ0FBWSxrQkFBWixFQUNFVCxZQUFZZ0IsZ0JBRGQsRUFFRUMscUJBQVdDLEdBQVgsQ0FBZSxFQUFDQyxNQUFNLE1BQU07QUFBRSxlQUFPLElBQVA7QUFBYyxPQUE3QixFQUErQkMsT0FBT2pCLGFBQXRDLEVBQWYsQ0FGRixFQUV5RTtBQUN2RUgsZ0JBQVlxQixrQkFIZCxFQUlFLEtBQUtDLGFBSlA7O0FBT0FsQixXQUFPbUIsTUFBUCxDQUFjLGtCQUFkLEVBQ0V2QixZQUFZZ0IsZ0JBRGQsRUFFRWhCLFlBQVlxQixrQkFGZCxFQUdFckIsWUFBWXdCLHNCQUhkLEVBSUUsS0FBS0MsYUFKUDtBQU1BLFdBQU9yQixNQUFQO0FBQ0Q7O0FBRURJLGFBQVdFLEdBQVgsRUFBZ0JDLEdBQWhCLEVBQXFCO0FBQ25CLFVBQU1lLFNBQVNDLGlCQUFPcEIsR0FBUCxDQUFXRyxJQUFJa0IsTUFBSixD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LE1BQVAsQ0FBYyxJQUFkLENBQXZCO0FBQ0EsUUFBSW9DLGNBQWMsQ0FBbEI7QUFDQSxRQUFJQyx3QkFBd0JMLGFBQTVCO0FBQ0EsUUFBSU0sb0JBQW9CLENBQXhCO0FBQ0E7QUFDQUgsbUJBQWVJLEVBQWYsQ0FBa0IsTUFBbEIsRUFBMEIsVUFBVWhDLElBQVYsRUFBZ0I7QUFDeEM2QixxQkFBZTdCLEtBQUtDLE1BQXBCO0FBQ0EsVUFBSTRCLGNBQWMsQ0FBbEIsRUFBcUI7QUFDbkI7QUFDQTtBQUNBLGNBQU1JLFNBQVNqQyxLQUFLa0MsS0FBTCxDQUFXLENBQVgsRUFBY0oscUJBQWQsQ0FBZjtBQUNBO0FBQ0FoRSxZQUFJcUUsS0FBSixDQUFVRixNQUFWO0FBQ0E7QUFDQUYsNkJBQXFCRSxPQUFPaEMsTUFBNUI7QUFDQTtBQUNBNkIsaUNBQXlCOUIsS0FBS0MsTUFBOUI7QUFDQTtBQUNBNEIsdUJBQWVJLE9BQU9oQyxNQUF0QjtBQUNEO0FBQ0Q7QUFDQTtBQUNBLFVBQUk4QixxQkFBcUJOLGFBQXpCLEVBQXdDO0FBQ3RDaEMsZUFBTzJDLEtBQVA7QUFDQXRFLFlBQUlnQyxHQUFKO0FBQ0EsYUFBS3VDLE9BQUw7QUFDRDtBQUNGLEtBdEJEO0FBdUJELEdBOUJEO0FBK0JEIiwiZmlsZSI6IkZpbGVzUm91dGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGV4cHJlc3MgICAgICAgICAgICAgZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQgQm9keVBhcnNlciAgICAgICAgICBmcm9tICdib2R5LXBhcnNlcic7XG5pbXBvcnQgKiBhcyBNaWRkbGV3YXJlcyAgICBmcm9tICcuLi9taWRkbGV3YXJlcyc7XG5pbXBvcnQgUGFyc2UgICAgICAgICAgICAgICBmcm9tICdwYXJzZS9ub2RlJztcbmltcG9ydCBDb25maWcgICAgICAgICAgICAgIGZyb20gJy4uL0NvbmZpZyc7XG5pbXBvcnQgbWltZSAgICAgICAgICAgICAgICBmcm9tICdtaW1lJztcbmltcG9ydCBsb2dnZXIgICAgICAgICAgICAgIGZyb20gJy4uL2xvZ2dlcic7XG5cbmV4cG9ydCBjbGFzcyBGaWxlc1JvdXRlciB7XG5cbiAgZXhwcmVzc1JvdXRlcih7IG1heFVwbG9hZFNpemUgPSAnMjBNYicgfSA9IHt9KSB7XG4gICAgdmFyIHJvdXRlciA9IGV4cHJlc3MuUm91dGVyKCk7XG4gICAgcm91dGVyLmdldCgnL2ZpbGVzLzphcHBJZC86ZmlsZW5hbWUnLCB0aGlzLmdldEhhbmRsZXIpO1xuXG4gICAgcm91dGVyLnBvc3QoJy9maWxlcycsIGZ1bmN0aW9uKHJlcSwgcmVzLCBuZXh0KSB7XG4gICAgICBuZXh0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0ZJTEVfTkFNRSxcbiAgICAgICAgJ0ZpbGVuYW1lIG5vdCBwcm92aWRlZC4nKSk7XG4gICAgfSk7XG5cbiAgICByb3V0ZXIucG9zdCgnL2ZpbGVzLzpmaWxlbmFtZScsXG4gICAgICBNaWRkbGV3YXJlcy5hbGxvd0Nyb3NzRG9tYWluLFxuICAgICAgQm9keVBhcnNlci5yYXcoe3R5cGU6ICgpID0+IHsgcmV0dXJuIHRydWU7IH0sIGxpbWl0OiBtYXhVcGxvYWRTaXplIH0pLCAvLyBBbGxvdyB1cGxvYWRzIHdpdGhvdXQgQ29udGVudC1UeXBlLCBvciB3aXRoIGFueSBDb250ZW50LVR5cGUuXG4gICAgICBNaWRkbGV3YXJlcy5oYW5kbGVQYXJzZUhlYWRlcnMsXG4gICAgICB0aGlzLmNyZWF0ZUhhbmRsZXJcbiAgICApO1xuXG4gICAgcm91dGVyLmRlbGV0ZSgnL2ZpbGVzLzpmaWxlbmFtZScsXG4gICAgICBNaWRkbGV3YXJlcy5hbGxvd0Nyb3NzRG9tYWluLFxuICAgICAgTWlkZGxld2FyZXMuaGFuZGxlUGFyc2VIZWFkZXJzLFxuICAgICAgTWlkZGxld2FyZXMuZW5mb3JjZU1hc3RlcktleUFjY2VzcyxcbiAgICAgIHRoaXMuZGVsZXRlSGFuZGxlclxuICAgICk7XG4gICAgcmV0dXJuIHJvdXRlcjtcbiAgfVxuXG4gIGdldEhhbmRsZXIocmVxLCByZXMpIHtcbiAgICBjb25zdCBjb25maWcgPSBDb25maWcuZ2V0KHJlcS5wYXJhbXMuYXBwSWQpO1xuICAgIGNvbnN0IGZpbGVzQ29udHJvbGxlciA9IGNvbmZpZy5maWxlc0NvbnRyb2xsZXI7XG4gICAgY29uc3QgZmlsZW5hbWUgPSByZXEucGFyYW1zLmZpbGVuYW1lO1xuICAgIGNvbnN0IGNvbnRlbnRUeXBlID0gbWltZS5nZXRUeXBlKGZpbGVuYW1lKTtcbiAgICBpZiAoaXNGaWxlU3RyZWFtYWJsZShyZXEsIGZpbGVzQ29udHJvbGxlcikpIHtcbiAgICAgIGZpbGVzQ29udHJvbGxlci5nZXRGaWxlU3RyZWFtKGNvbmZpZywgZmlsZW5hbWUpLnRoZW4oKHN0cmVhbSkgPT4ge1xuICAgICAgICBoYW5kbGVGaWxlU3RyZWFtKHN0cmVhbSwgcmVxLCByZXMsIGNvbnRlbnRUeXBlKTtcbiAgICAgIH0pLmNhdGNoKCgpID0+IHtcbiAgICAgICAgcmVzLnN0YXR1cyg0MDQpO1xuICAgICAgICByZXMuc2V0KCdDb250ZW50LVR5cGUnLCAndGV4dC9wbGFpbicpO1xuICAgICAgICByZXMuZW5kKCdGaWxlIG5vdCBmb3VuZC4nKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBmaWxlc0NvbnRyb2xsZXIuZ2V0RmlsZURhdGEoY29uZmlnLCBmaWxlbmFtZSkudGhlbigoZGF0YSkgPT4ge1xuICAgICAgICByZXMuc3RhdHVzKDIwMCk7XG4gICAgICAgIHJlcy5zZXQoJ0NvbnRlbnQtVHlwZScsIGNvbnRlbnRUeXBlKTtcbiAgICAgICAgcmVzLnNldCgnQ29udGVudC1MZW5ndGgnLCBkYXRhLmxlbmd0aCk7XG4gICAgICAgIHJlcy5lbmQoZGF0YSk7XG4gICAgICB9KS5jYXRjaCgoKSA9PiB7XG4gICAgICAgIHJlcy5zdGF0dXMoNDA0KTtcbiAgICAgICAgcmVzLnNldCgnQ29udGVudC1UeXBlJywgJ3RleHQvcGxhaW4nKTtcbiAgICAgICAgcmVzLmVuZCgnRmlsZSBub3QgZm91bmQuJyk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBjcmVhdGVIYW5kbGVyKHJlcSwgcmVzLCBuZXh0KSB7XG4gICAgaWYgKCFyZXEuYm9keSB8fCAhcmVxLmJvZHkubGVuZ3RoKSB7XG4gICAgICBuZXh0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5GSUxFX1NBVkVfRVJST1IsXG4gICAgICAgICdJbnZhbGlkIGZpbGUgdXBsb2FkLicpKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAocmVxLnBhcmFtcy5maWxlbmFtZS5sZW5ndGggPiAxMjgpIHtcbiAgICAgIG5leHQobmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfRklMRV9OQU1FLFxuICAgICAgICAnRmlsZW5hbWUgdG9vIGxvbmcuJykpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghcmVxLnBhcmFtcy5maWxlbmFtZS5tYXRjaCgvXltfYS16QS1aMC05XVthLXpBLVowLTlAXFwuXFwgfl8tXSokLykpIHtcbiAgICAgIG5leHQobmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfRklMRV9OQU1FLFxuICAgICAgICAnRmlsZW5hbWUgY29udGFpbnMgaW52YWxpZCBjaGFyYWN0ZXJzLicpKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBmaWxlbmFtZSA9IHJlcS5wYXJhbXMuZmlsZW5hbWU7XG4gICAgY29uc3QgY29udGVudFR5cGUgPSByZXEuZ2V0KCdDb250ZW50LXR5cGUnKTtcbiAgICBjb25zdCBjb25maWcgPSByZXEuY29uZmlnO1xuICAgIGNvbnN0IGZpbGVzQ29udHJvbGxlciA9IGNvbmZpZy5maWxlc0NvbnRyb2xsZXI7XG5cbiAgICBmaWxlc0NvbnRyb2xsZXIuY3JlYXRlRmlsZShjb25maWcsIGZpbGVuYW1lLCByZXEuYm9keSwgY29udGVudFR5cGUpLnRoZW4oKHJlc3VsdCkgPT4ge1xuICAgICAgcmVzLnN0YXR1cygyMDEpO1xuICAgICAgcmVzLnNldCgnTG9jYXRpb24nLCByZXN1bHQudXJsKTtcbiAgICAgIHJlcy5qc29uKHJlc3VsdCk7XG4gICAgfSkuY2F0Y2goKGUpID0+IHtcbiAgICAgIGxvZ2dlci5lcnJvcihlLm1lc3NhZ2UsIGUpO1xuICAgICAgbmV4dChuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRklMRV9TQVZFX0VSUk9SLCAnQ291bGQgbm90IHN0b3JlIGZpbGUuJykpO1xuICAgIH0pO1xuICB9XG5cbiAgZGVsZXRlSGFuZGxlcihyZXEsIHJlcywgbmV4dCkge1xuICAgIGNvbnN0IGZpbGVzQ29udHJvbGxlciA9IHJlcS5jb25maWcuZmlsZXNDb250cm9sbGVyO1xuICAgIGZpbGVzQ29udHJvbGxlci5kZWxldGVGaWxlKHJlcS5jb25maWcsIHJlcS5wYXJhbXMuZmlsZW5hbWUpLnRoZW4oKCkgPT4ge1xuICAgICAgcmVzLnN0YXR1cygyMDApO1xuICAgICAgLy8gVE9ETzogcmV0dXJuIHVzZWZ1bCBKU09OIGhlcmU/XG4gICAgICByZXMuZW5kKCk7XG4gICAgfSkuY2F0Y2goKCkgPT4ge1xuICAgICAgbmV4dChuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRklMRV9ERUxFVEVfRVJST1IsXG4gICAgICAgICdDb3VsZCBub3QgZGVsZXRlIGZpbGUuJykpO1xuICAgIH0pO1xuICB9XG59XG5cbmZ1bmN0aW9uIGlzRmlsZVN0cmVhbWFibGUocmVxLCBmaWxlc0NvbnRyb2xsZXIpe1xuICByZXR1cm4gIHJlcS5nZXQoJ1JhbmdlJykgJiYgdHlwZW9mIGZpbGVzQ29udHJvbGxlci5hZGFwdGVyLmdldEZpbGVTdHJlYW0gPT09ICdmdW5jdGlvbic7XG59XG5cbmZ1bmN0aW9uIGdldFJhbmdlKHJlcSkge1xuICBjb25zdCBwYXJ0cyA9IHJlcS5nZXQoJ1JhbmdlJykucmVwbGFjZSgvYnl0ZXM9LywgXCJcIikuc3BsaXQoXCItXCIpO1xuICByZXR1cm4geyBzdGFydDogcGFyc2VJbnQocGFydHNbMF0sIDEwKSwgZW5kOiBwYXJzZUludChwYXJ0c1sxXSwgMTApIH07XG59XG5cbi8vIGhhbmRsZUZpbGVTdHJlYW0gaXMgbGljZW5jZWQgdW5kZXIgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbiA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlIChodHRwczovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnkvNC4wLykuXG4vLyBBdXRob3I6IExFUk9JQiBhdCB3ZWlnaHRpbmdmb3JteXBpenphIChodHRwczovL3dlaWdodGluZ2Zvcm15cGl6emEud29yZHByZXNzLmNvbS8yMDE1LzA2LzI0L3N0cmVhbS1odG1sNS1tZWRpYS1jb250ZW50LWxpa2UtdmlkZW8tYXVkaW8tZnJvbS1tb25nb2RiLXVzaW5nLWV4cHJlc3MtYW5kLWdyaWRzdG9yZS8pLlxuZnVuY3Rpb24gaGFuZGxlRmlsZVN0cmVhbShzdHJlYW0sIHJlcSwgcmVzLCBjb250ZW50VHlwZSkge1xuICBjb25zdCBidWZmZXJfc2l6ZSA9IDEwMjQgKiAxMDI0OyAvLzEwMjRLYlxuICAvLyBSYW5nZSByZXF1ZXN0LCBwYXJ0aWFsbCBzdHJlYW0gdGhlIGZpbGVcbiAgbGV0IHtcbiAgICBzdGFydCwgZW5kXG4gIH0gPSBnZXRSYW5nZShyZXEpO1xuXG4gIGNvbnN0IG5vdEVuZGVkID0gKCFlbmQgJiYgZW5kICE9PSAwKTtcbiAgY29uc3Qgbm90U3RhcnRlZCA9ICghc3RhcnQgJiYgc3RhcnQgIT09IDApO1xuICAvLyBObyBlbmQgcHJvdmlkZWQsIHdlIHdhbnQgYWxsIGJ5dGVzXG4gIGlmIChub3RFbmRlZCkge1xuICAgIGVuZCA9IHN0cmVhbS5sZW5ndGggLSAxO1xuICB9XG4gIC8vIE5vIHN0YXJ0IHByb3ZpZGVkLCB3ZSdyZSByZWFkaW5nIGJhY2t3YXJkc1xuICBpZiAobm90U3RhcnRlZCkge1xuICAgIHN0YXJ0ID0gc3RyZWFtLmxlbmd0aCAtIGVuZDtcbiAgICBlbmQgPSBzdGFydCArIGVuZCAtIDE7XG4gIH1cblxuICAvLyBEYXRhIGV4Y2VlZHMgdGhlIGJ1ZmZlcl9zaXplLCBjYXBcbiAgaWYgKGVuZCAtIHN0YXJ0ID49IGJ1ZmZlcl9zaXplKSB7XG4gICAgZW5kID0gc3RhcnQgKyBidWZmZXJfc2l6ZSAtIDE7XG4gIH1cblxuICBjb25zdCBjb250ZW50TGVuZ3RoID0gKGVuZCAtIHN0YXJ0KSArIDE7XG5cbiAgcmVzLndyaXRlSGVhZCgyMDYsIHtcbiAgICAnQ29udGVudC1SYW5nZSc6ICdieXRlcyAnICsgc3RhcnQgKyAnLScgKyBlbmQgKyAnLycgKyBzdHJlYW0ubGVuZ3RoLFxuICAgICdBY2NlcHQtUmFuZ2VzJzogJ2J5dGVzJyxcbiAgICAnQ29udGVudC1MZW5ndGgnOiBjb250ZW50TGVuZ3RoLFxuICAgICdDb250ZW50LVR5cGUnOiBjb250ZW50VHlwZSxcbiAgfSk7XG5cbiAgc3RyZWFtLnNlZWsoc3RhcnQsIGZ1bmN0aW9uICgpIHtcbiAgICAvLyBnZXQgZ3JpZEZpbGUgc3RyZWFtXG4gICAgY29uc3QgZ3JpZEZpbGVTdHJlYW0gPSBzdHJlYW0uc3RyZWFtKHRydWUpO1xuICAgIGxldCBidWZmZXJBdmFpbCA9IDA7XG4gICAgbGV0IHJlbWFpbmluZ0J5dGVzVG9Xcml0ZSA9IGNvbnRlbnRMZW5ndGg7XG4gICAgbGV0IHRvdGFsQnl0ZXNXcml0dGVuID0gMDtcbiAgICAvLyB3cml0ZSB0byByZXNwb25zZVxuICAgIGdyaWRGaWxlU3RyZWFtLm9uKCdkYXRhJywgZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgIGJ1ZmZlckF2YWlsICs9IGRhdGEubGVuZ3RoO1xuICAgICAgaWYgKGJ1ZmZlckF2YWlsID4gMCkge1xuICAgICAgICAvLyBzbGljZSByZXR1cm5zIHRoZSBzYW1lIGJ1ZmZlciBpZiBvdmVyZmxvd2luZ1xuICAgICAgICAvLyBzYWZlIHRvIGNhbGwgaW4gYW55IGNhc2VcbiAgICAgICAgY29uc3QgYnVmZmVyID0gZGF0YS5zbGljZSgwLCByZW1haW5pbmdCeXRlc1RvV3JpdGUpO1xuICAgICAgICAvLyB3cml0ZSB0aGUgYnVmZmVyXG4gICAgICAgIHJlcy53cml0ZShidWZmZXIpO1xuICAgICAgICAvLyBpbmNyZW1lbnQgdG90YWxcbiAgICAgICAgdG90YWxCeXRlc1dyaXR0ZW4gKz0gYnVmZmVyLmxlbmd0aDtcbiAgICAgICAgLy8gZGVjcmVtZW50IHJlbWFpbmluZ1xuICAgICAgICByZW1haW5pbmdCeXRlc1RvV3JpdGUgLT0gZGF0YS5sZW5ndGg7XG4gICAgICAgIC8vIGRlY3JlbWVudCB0aGUgYXZhaWFsYmUgYnVmZmVyXG4gICAgICAgIGJ1ZmZlckF2YWlsIC09IGJ1ZmZlci5sZW5ndGg7XG4gICAgICB9XG4gICAgICAvLyBpbiBjYXNlIG9mIHNtYWxsIHNsaWNlcywgYWxsIHZhbHVlcyB3aWxsIGJlIGdvb2QgYXQgdGhhdCBwb2ludFxuICAgICAgLy8gd2UndmUgd3JpdHRlbiBlbm91Z2gsIGVuZC4uLlxuICAgICAgaWYgKHRvdGFsQnl0ZXNXcml0dGVuID49IGNvbnRlbnRMZW5ndGgpIHtcbiAgICAgICAgc3RyZWFtLmNsb3NlKCk7XG4gICAgICAgIHJlcy5lbmQoKTtcbiAgICAgICAgdGhpcy5kZXN0cm95KCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuIl19
|
|
301
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZXhwcmVzcyIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJyZXF1aXJlIiwiTWlkZGxld2FyZXMiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsIl9ub2RlIiwiX0NvbmZpZyIsIl9sb2dnZXIiLCJlIiwidCIsIldlYWtNYXAiLCJyIiwibiIsIl9fZXNNb2R1bGUiLCJvIiwiaSIsImYiLCJfX3Byb3RvX18iLCJkZWZhdWx0IiwiaGFzIiwiZ2V0Iiwic2V0IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ0cmlnZ2VycyIsIlV0aWxzIiwiRmlsZXNSb3V0ZXIiLCJleHByZXNzUm91dGVyIiwibWF4VXBsb2FkU2l6ZSIsInJvdXRlciIsImV4cHJlc3MiLCJSb3V0ZXIiLCJnZXRIYW5kbGVyIiwibWV0YWRhdGFIYW5kbGVyIiwicG9zdCIsInJlcSIsInJlcyIsIm5leHQiLCJQYXJzZSIsIkVycm9yIiwiSU5WQUxJRF9GSUxFX05BTUUiLCJyYXciLCJ0eXBlIiwibGltaXQiLCJoYW5kbGVQYXJzZUhlYWRlcnMiLCJoYW5kbGVQYXJzZVNlc3Npb24iLCJjcmVhdGVIYW5kbGVyIiwiZGVsZXRlIiwiZW5mb3JjZU1hc3RlcktleUFjY2VzcyIsImRlbGV0ZUhhbmRsZXIiLCJjb25maWciLCJDb25maWciLCJwYXJhbXMiLCJhcHBJZCIsInN0YXR1cyIsImpzb24iLCJjb2RlIiwiT1BFUkFUSU9OX0ZPUkJJRERFTiIsImVycm9yIiwiZmlsZW5hbWUiLCJmaWxlc0NvbnRyb2xsZXIiLCJtaW1lIiwiY29udGVudFR5cGUiLCJnZXRUeXBlIiwiZmlsZSIsIkZpbGUiLCJiYXNlNjQiLCJ0cmlnZ2VyUmVzdWx0IiwibWF5YmVSdW5GaWxlVHJpZ2dlciIsIlR5cGVzIiwiYmVmb3JlRmluZCIsImF1dGgiLCJfbmFtZSIsImlzRmlsZVN0cmVhbWFibGUiLCJoYW5kbGVGaWxlU3RyZWFtIiwiY2F0Y2giLCJlbmQiLCJkYXRhIiwiZ2V0RmlsZURhdGEiLCJ0b1N0cmluZyIsImFmdGVyRmluZCIsImZvcmNlRG93bmxvYWQiLCJCdWZmZXIiLCJmcm9tIiwiX2RhdGEiLCJsZW5ndGgiLCJlcnIiLCJyZXNvbHZlRXJyb3IiLCJTQ1JJUFRfRkFJTEVEIiwibWVzc2FnZSIsInVzZXIiLCJpc01hc3RlciIsImlzTGlua2VkIiwiQW5vbnltb3VzVXRpbHMiLCJmaWxlVXBsb2FkIiwiZW5hYmxlRm9yQW5vbnltb3VzVXNlciIsIkZJTEVfU0FWRV9FUlJPUiIsImVuYWJsZUZvckF1dGhlbnRpY2F0ZWRVc2VyIiwiZW5hYmxlRm9yUHVibGljIiwiYm9keSIsInZhbGlkYXRlRmlsZW5hbWUiLCJmaWxlRXh0ZW5zaW9ucyIsImlzVmFsaWRFeHRlbnNpb24iLCJleHRlbnNpb24iLCJzb21lIiwiZXh0IiwicmVnZXgiLCJSZWdFeHAiLCJ0ZXN0IiwiaW5jbHVkZXMiLCJzdWJzdHJpbmciLCJsYXN0SW5kZXhPZiIsInNwbGl0Iiwiam9pbiIsIm1ldGFkYXRhIiwidGFncyIsImZpbGVEYXRhIiwiY2hlY2tQcm9oaWJpdGVkS2V5d29yZHMiLCJJTlZBTElEX0tFWV9OQU1FIiwic2V0VGFncyIsInNldE1ldGFkYXRhIiwiZmlsZVNpemUiLCJieXRlTGVuZ3RoIiwiZmlsZU9iamVjdCIsImJlZm9yZVNhdmUiLCJzYXZlUmVzdWx0IiwidXJsIiwibmFtZSIsImJ1ZmZlckRhdGEiLCJmaWxlT3B0aW9ucyIsIl9tZXRhZGF0YSIsImZpbGVUYWdzIiwia2V5cyIsIl90YWdzIiwiYXNzaWduIiwiY3JlYXRlRmlsZVJlc3VsdCIsImNyZWF0ZUZpbGUiLCJfc291cmNlIiwiX3VybCIsIl9yZXF1ZXN0VGFzayIsIl9wcmV2aW91c1NhdmUiLCJQcm9taXNlIiwicmVzb2x2ZSIsImFmdGVyU2F2ZSIsImxvZ2dlciIsImFkYXB0ZXIiLCJnZXRGaWxlTG9jYXRpb24iLCJiZWZvcmVEZWxldGUiLCJkZWxldGVGaWxlIiwiYWZ0ZXJEZWxldGUiLCJGSUxFX0RFTEVURV9FUlJPUiIsImdldE1ldGFkYXRhIiwiZXhwb3J0cyIsInJhbmdlIiwic3RhcnQiLCJOdW1iZXIiLCJpc05hTiJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Sb3V0ZXJzL0ZpbGVzUm91dGVyLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBleHByZXNzIGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0ICogYXMgTWlkZGxld2FyZXMgZnJvbSAnLi4vbWlkZGxld2FyZXMnO1xuaW1wb3J0IFBhcnNlIGZyb20gJ3BhcnNlL25vZGUnO1xuaW1wb3J0IENvbmZpZyBmcm9tICcuLi9Db25maWcnO1xuaW1wb3J0IGxvZ2dlciBmcm9tICcuLi9sb2dnZXInO1xuY29uc3QgdHJpZ2dlcnMgPSByZXF1aXJlKCcuLi90cmlnZ2VycycpO1xuY29uc3QgVXRpbHMgPSByZXF1aXJlKCcuLi9VdGlscycpO1xuXG5leHBvcnQgY2xhc3MgRmlsZXNSb3V0ZXIge1xuICBleHByZXNzUm91dGVyKHsgbWF4VXBsb2FkU2l6ZSA9ICcyME1iJyB9ID0ge30pIHtcbiAgICB2YXIgcm91dGVyID0gZXhwcmVzcy5Sb3V0ZXIoKTtcbiAgICByb3V0ZXIuZ2V0KCcvZmlsZXMvOmFwcElkLzpmaWxlbmFtZScsIHRoaXMuZ2V0SGFuZGxlcik7XG4gICAgcm91dGVyLmdldCgnL2ZpbGVzLzphcHBJZC9tZXRhZGF0YS86ZmlsZW5hbWUnLCB0aGlzLm1ldGFkYXRhSGFuZGxlcik7XG5cbiAgICByb3V0ZXIucG9zdCgnL2ZpbGVzJywgZnVuY3Rpb24gKHJlcSwgcmVzLCBuZXh0KSB7XG4gICAgICBuZXh0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0ZJTEVfTkFNRSwgJ0ZpbGVuYW1lIG5vdCBwcm92aWRlZC4nKSk7XG4gICAgfSk7XG5cbiAgICByb3V0ZXIucG9zdChcbiAgICAgICcvZmlsZXMvOmZpbGVuYW1lJyxcbiAgICAgIGV4cHJlc3MucmF3KHtcbiAgICAgICAgdHlwZTogKCkgPT4ge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9LFxuICAgICAgICBsaW1pdDogbWF4VXBsb2FkU2l6ZSxcbiAgICAgIH0pLCAvLyBBbGxvdyB1cGxvYWRzIHdpdGhvdXQgQ29udGVudC1UeXBlLCBvciB3aXRoIGFueSBDb250ZW50LVR5cGUuXG4gICAgICBNaWRkbGV3YXJlcy5oYW5kbGVQYXJzZUhlYWRlcnMsXG4gICAgICBNaWRkbGV3YXJlcy5oYW5kbGVQYXJzZVNlc3Npb24sXG4gICAgICB0aGlzLmNyZWF0ZUhhbmRsZXJcbiAgICApO1xuXG4gICAgcm91dGVyLmRlbGV0ZShcbiAgICAgICcvZmlsZXMvOmZpbGVuYW1lJyxcbiAgICAgIE1pZGRsZXdhcmVzLmhhbmRsZVBhcnNlSGVhZGVycyxcbiAgICAgIE1pZGRsZXdhcmVzLmhhbmRsZVBhcnNlU2Vzc2lvbixcbiAgICAgIE1pZGRsZXdhcmVzLmVuZm9yY2VNYXN0ZXJLZXlBY2Nlc3MsXG4gICAgICB0aGlzLmRlbGV0ZUhhbmRsZXJcbiAgICApO1xuICAgIHJldHVybiByb3V0ZXI7XG4gIH1cblxuICBhc3luYyBnZXRIYW5kbGVyKHJlcSwgcmVzKSB7XG4gICAgY29uc3QgY29uZmlnID0gQ29uZmlnLmdldChyZXEucGFyYW1zLmFwcElkKTtcbiAgICBpZiAoIWNvbmZpZykge1xuICAgICAgcmVzLnN0YXR1cyg0MDMpO1xuICAgICAgcmVzLmpzb24oeyBjb2RlOiBQYXJzZS5FcnJvci5PUEVSQVRJT05fRk9SQklEREVOLCBlcnJvcjogJ0ludmFsaWQgYXBwbGljYXRpb24gSUQuJyB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgZmlsZW5hbWUgPSByZXEucGFyYW1zLmZpbGVuYW1lO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBmaWxlc0NvbnRyb2xsZXIgPSBjb25maWcuZmlsZXNDb250cm9sbGVyO1xuICAgICAgY29uc3QgbWltZSA9IChhd2FpdCBpbXBvcnQoJ21pbWUnKSkuZGVmYXVsdDtcbiAgICAgIGxldCBjb250ZW50VHlwZSA9IG1pbWUuZ2V0VHlwZShmaWxlbmFtZSk7XG4gICAgICBsZXQgZmlsZSA9IG5ldyBQYXJzZS5GaWxlKGZpbGVuYW1lLCB7IGJhc2U2NDogJycgfSwgY29udGVudFR5cGUpO1xuICAgICAgY29uc3QgdHJpZ2dlclJlc3VsdCA9IGF3YWl0IHRyaWdnZXJzLm1heWJlUnVuRmlsZVRyaWdnZXIoXG4gICAgICAgIHRyaWdnZXJzLlR5cGVzLmJlZm9yZUZpbmQsXG4gICAgICAgIHsgZmlsZSB9LFxuICAgICAgICBjb25maWcsXG4gICAgICAgIHJlcS5hdXRoXG4gICAgICApO1xuICAgICAgaWYgKHRyaWdnZXJSZXN1bHQ/LmZpbGU/Ll9uYW1lKSB7XG4gICAgICAgIGZpbGVuYW1lID0gdHJpZ2dlclJlc3VsdD8uZmlsZT8uX25hbWU7XG4gICAgICAgIGNvbnRlbnRUeXBlID0gbWltZS5nZXRUeXBlKGZpbGVuYW1lKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzRmlsZVN0cmVhbWFibGUocmVxLCBmaWxlc0NvbnRyb2xsZXIpKSB7XG4gICAgICAgIGZpbGVzQ29udHJvbGxlci5oYW5kbGVGaWxlU3RyZWFtKGNvbmZpZywgZmlsZW5hbWUsIHJlcSwgcmVzLCBjb250ZW50VHlwZSkuY2F0Y2goKCkgPT4ge1xuICAgICAgICAgIHJlcy5zdGF0dXMoNDA0KTtcbiAgICAgICAgICByZXMuc2V0KCdDb250ZW50LVR5cGUnLCAndGV4dC9wbGFpbicpO1xuICAgICAgICAgIHJlcy5lbmQoJ0ZpbGUgbm90IGZvdW5kLicpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBsZXQgZGF0YSA9IGF3YWl0IGZpbGVzQ29udHJvbGxlci5nZXRGaWxlRGF0YShjb25maWcsIGZpbGVuYW1lKS5jYXRjaCgoKSA9PiB7XG4gICAgICAgIHJlcy5zdGF0dXMoNDA0KTtcbiAgICAgICAgcmVzLnNldCgnQ29udGVudC1UeXBlJywgJ3RleHQvcGxhaW4nKTtcbiAgICAgICAgcmVzLmVuZCgnRmlsZSBub3QgZm91bmQuJyk7XG4gICAgICB9KTtcbiAgICAgIGlmICghZGF0YSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBmaWxlID0gbmV3IFBhcnNlLkZpbGUoZmlsZW5hbWUsIHsgYmFzZTY0OiBkYXRhLnRvU3RyaW5nKCdiYXNlNjQnKSB9LCBjb250ZW50VHlwZSk7XG4gICAgICBjb25zdCBhZnRlckZpbmQgPSBhd2FpdCB0cmlnZ2Vycy5tYXliZVJ1bkZpbGVUcmlnZ2VyKFxuICAgICAgICB0cmlnZ2Vycy5UeXBlcy5hZnRlckZpbmQsXG4gICAgICAgIHsgZmlsZSwgZm9yY2VEb3dubG9hZDogZmFsc2UgfSxcbiAgICAgICAgY29uZmlnLFxuICAgICAgICByZXEuYXV0aFxuICAgICAgKTtcblxuICAgICAgaWYgKGFmdGVyRmluZD8uZmlsZSkge1xuICAgICAgICBjb250ZW50VHlwZSA9IG1pbWUuZ2V0VHlwZShhZnRlckZpbmQuZmlsZS5fbmFtZSk7XG4gICAgICAgIGRhdGEgPSBCdWZmZXIuZnJvbShhZnRlckZpbmQuZmlsZS5fZGF0YSwgJ2Jhc2U2NCcpO1xuICAgICAgfVxuXG4gICAgICByZXMuc3RhdHVzKDIwMCk7XG4gICAgICByZXMuc2V0KCdDb250ZW50LVR5cGUnLCBjb250ZW50VHlwZSk7XG4gICAgICByZXMuc2V0KCdDb250ZW50LUxlbmd0aCcsIGRhdGEubGVuZ3RoKTtcbiAgICAgIGlmIChhZnRlckZpbmQuZm9yY2VEb3dubG9hZCkge1xuICAgICAgICByZXMuc2V0KCdDb250ZW50LURpc3Bvc2l0aW9uJywgYGF0dGFjaG1lbnQ7ZmlsZW5hbWU9JHthZnRlckZpbmQuZmlsZS5fbmFtZX1gKTtcbiAgICAgIH1cbiAgICAgIHJlcy5lbmQoZGF0YSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc3QgZXJyID0gdHJpZ2dlcnMucmVzb2x2ZUVycm9yKGUsIHtcbiAgICAgICAgY29kZTogUGFyc2UuRXJyb3IuU0NSSVBUX0ZBSUxFRCxcbiAgICAgICAgbWVzc2FnZTogYENvdWxkIG5vdCBmaW5kIGZpbGU6ICR7ZmlsZW5hbWV9LmAsXG4gICAgICB9KTtcbiAgICAgIHJlcy5zdGF0dXMoNDAzKTtcbiAgICAgIHJlcy5qc29uKHsgY29kZTogZXJyLmNvZGUsIGVycm9yOiBlcnIubWVzc2FnZSB9KTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBjcmVhdGVIYW5kbGVyKHJlcSwgcmVzLCBuZXh0KSB7XG4gICAgY29uc3QgY29uZmlnID0gcmVxLmNvbmZpZztcbiAgICBjb25zdCB1c2VyID0gcmVxLmF1dGgudXNlcjtcbiAgICBjb25zdCBpc01hc3RlciA9IHJlcS5hdXRoLmlzTWFzdGVyO1xuICAgIGNvbnN0IGlzTGlua2VkID0gdXNlciAmJiBQYXJzZS5Bbm9ueW1vdXNVdGlscy5pc0xpbmtlZCh1c2VyKTtcbiAgICBpZiAoIWlzTWFzdGVyICYmICFjb25maWcuZmlsZVVwbG9hZC5lbmFibGVGb3JBbm9ueW1vdXNVc2VyICYmIGlzTGlua2VkKSB7XG4gICAgICBuZXh0KFxuICAgICAgICBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuRklMRV9TQVZFX0VSUk9SLCAnRmlsZSB1cGxvYWQgYnkgYW5vbnltb3VzIHVzZXIgaXMgZGlzYWJsZWQuJylcbiAgICAgICk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghaXNNYXN0ZXIgJiYgIWNvbmZpZy5maWxlVXBsb2FkLmVuYWJsZUZvckF1dGhlbnRpY2F0ZWRVc2VyICYmICFpc0xpbmtlZCAmJiB1c2VyKSB7XG4gICAgICBuZXh0KFxuICAgICAgICBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuRklMRV9TQVZFX0VSUk9SLFxuICAgICAgICAgICdGaWxlIHVwbG9hZCBieSBhdXRoZW50aWNhdGVkIHVzZXIgaXMgZGlzYWJsZWQuJ1xuICAgICAgICApXG4gICAgICApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIWlzTWFzdGVyICYmICFjb25maWcuZmlsZVVwbG9hZC5lbmFibGVGb3JQdWJsaWMgJiYgIXVzZXIpIHtcbiAgICAgIG5leHQobmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLkZJTEVfU0FWRV9FUlJPUiwgJ0ZpbGUgdXBsb2FkIGJ5IHB1YmxpYyBpcyBkaXNhYmxlZC4nKSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGZpbGVzQ29udHJvbGxlciA9IGNvbmZpZy5maWxlc0NvbnRyb2xsZXI7XG4gICAgY29uc3QgeyBmaWxlbmFtZSB9ID0gcmVxLnBhcmFtcztcbiAgICBjb25zdCBjb250ZW50VHlwZSA9IHJlcS5nZXQoJ0NvbnRlbnQtdHlwZScpO1xuXG4gICAgaWYgKCFyZXEuYm9keSB8fCAhcmVxLmJvZHkubGVuZ3RoKSB7XG4gICAgICBuZXh0KG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5GSUxFX1NBVkVfRVJST1IsICdJbnZhbGlkIGZpbGUgdXBsb2FkLicpKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBlcnJvciA9IGZpbGVzQ29udHJvbGxlci52YWxpZGF0ZUZpbGVuYW1lKGZpbGVuYW1lKTtcbiAgICBpZiAoZXJyb3IpIHtcbiAgICAgIG5leHQoZXJyb3IpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGZpbGVFeHRlbnNpb25zID0gY29uZmlnLmZpbGVVcGxvYWQ/LmZpbGVFeHRlbnNpb25zO1xuICAgIGlmICghaXNNYXN0ZXIgJiYgZmlsZUV4dGVuc2lvbnMpIHtcbiAgICAgIGNvbnN0IGlzVmFsaWRFeHRlbnNpb24gPSBleHRlbnNpb24gPT4ge1xuICAgICAgICByZXR1cm4gZmlsZUV4dGVuc2lvbnMuc29tZShleHQgPT4ge1xuICAgICAgICAgIGlmIChleHQgPT09ICcqJykge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IHJlZ2V4ID0gbmV3IFJlZ0V4cChleHQpO1xuICAgICAgICAgIGlmIChyZWdleC50ZXN0KGV4dGVuc2lvbikpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9O1xuICAgICAgbGV0IGV4dGVuc2lvbiA9IGNvbnRlbnRUeXBlO1xuICAgICAgaWYgKGZpbGVuYW1lICYmIGZpbGVuYW1lLmluY2x1ZGVzKCcuJykpIHtcbiAgICAgICAgZXh0ZW5zaW9uID0gZmlsZW5hbWUuc3Vic3RyaW5nKGZpbGVuYW1lLmxhc3RJbmRleE9mKCcuJykgKyAxKTtcbiAgICAgIH0gZWxzZSBpZiAoY29udGVudFR5cGUgJiYgY29udGVudFR5cGUuaW5jbHVkZXMoJy8nKSkge1xuICAgICAgICBleHRlbnNpb24gPSBjb250ZW50VHlwZS5zcGxpdCgnLycpWzFdO1xuICAgICAgfVxuICAgICAgZXh0ZW5zaW9uID0gZXh0ZW5zaW9uPy5zcGxpdCgnICcpPy5qb2luKCcnKTtcblxuICAgICAgaWYgKGV4dGVuc2lvbiAmJiAhaXNWYWxpZEV4dGVuc2lvbihleHRlbnNpb24pKSB7XG4gICAgICAgIG5leHQoXG4gICAgICAgICAgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuRklMRV9TQVZFX0VSUk9SLFxuICAgICAgICAgICAgYEZpbGUgdXBsb2FkIG9mIGV4dGVuc2lvbiAke2V4dGVuc2lvbn0gaXMgZGlzYWJsZWQuYFxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGJhc2U2NCA9IHJlcS5ib2R5LnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICBjb25zdCBmaWxlID0gbmV3IFBhcnNlLkZpbGUoZmlsZW5hbWUsIHsgYmFzZTY0IH0sIGNvbnRlbnRUeXBlKTtcbiAgICBjb25zdCB7IG1ldGFkYXRhID0ge30sIHRhZ3MgPSB7fSB9ID0gcmVxLmZpbGVEYXRhIHx8IHt9O1xuICAgIHRyeSB7XG4gICAgICAvLyBTY2FuIHJlcXVlc3QgZGF0YSBmb3IgZGVuaWVkIGtleXdvcmRzXG4gICAgICBVdGlscy5jaGVja1Byb2hpYml0ZWRLZXl3b3Jkcyhjb25maWcsIG1ldGFkYXRhKTtcbiAgICAgIFV0aWxzLmNoZWNrUHJvaGliaXRlZEtleXdvcmRzKGNvbmZpZywgdGFncyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIG5leHQobmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfS0VZX05BTUUsIGVycm9yKSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZpbGUuc2V0VGFncyh0YWdzKTtcbiAgICBmaWxlLnNldE1ldGFkYXRhKG1ldGFkYXRhKTtcbiAgICBjb25zdCBmaWxlU2l6ZSA9IEJ1ZmZlci5ieXRlTGVuZ3RoKHJlcS5ib2R5KTtcbiAgICBjb25zdCBmaWxlT2JqZWN0ID0geyBmaWxlLCBmaWxlU2l6ZSB9O1xuICAgIHRyeSB7XG4gICAgICAvLyBydW4gYmVmb3JlU2F2ZUZpbGUgdHJpZ2dlclxuICAgICAgY29uc3QgdHJpZ2dlclJlc3VsdCA9IGF3YWl0IHRyaWdnZXJzLm1heWJlUnVuRmlsZVRyaWdnZXIoXG4gICAgICAgIHRyaWdnZXJzLlR5cGVzLmJlZm9yZVNhdmUsXG4gICAgICAgIGZpbGVPYmplY3QsXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgcmVxLmF1dGhcbiAgICAgICk7XG4gICAgICBsZXQgc2F2ZVJlc3VsdDtcbiAgICAgIC8vIGlmIGEgbmV3IFBhcnNlRmlsZSBpcyByZXR1cm5lZCBjaGVjayBpZiBpdCdzIGFuIGFscmVhZHkgc2F2ZWQgZmlsZVxuICAgICAgaWYgKHRyaWdnZXJSZXN1bHQgaW5zdGFuY2VvZiBQYXJzZS5GaWxlKSB7XG4gICAgICAgIGZpbGVPYmplY3QuZmlsZSA9IHRyaWdnZXJSZXN1bHQ7XG4gICAgICAgIGlmICh0cmlnZ2VyUmVzdWx0LnVybCgpKSB7XG4gICAgICAgICAgLy8gc2V0IGZpbGVTaXplIHRvIG51bGwgYmVjYXVzZSB3ZSB3b250IGtub3cgaG93IGJpZyBpdCBpcyBoZXJlXG4gICAgICAgICAgZmlsZU9iamVjdC5maWxlU2l6ZSA9IG51bGw7XG4gICAgICAgICAgc2F2ZVJlc3VsdCA9IHtcbiAgICAgICAgICAgIHVybDogdHJpZ2dlclJlc3VsdC51cmwoKSxcbiAgICAgICAgICAgIG5hbWU6IHRyaWdnZXJSZXN1bHQuX25hbWUsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gaWYgdGhlIGZpbGUgcmV0dXJuZWQgYnkgdGhlIHRyaWdnZXIgaGFzIGFscmVhZHkgYmVlbiBzYXZlZCBza2lwIHNhdmluZyBhbnl0aGluZ1xuICAgICAgaWYgKCFzYXZlUmVzdWx0KSB7XG4gICAgICAgIC8vIHVwZGF0ZSBmaWxlU2l6ZVxuICAgICAgICBjb25zdCBidWZmZXJEYXRhID0gQnVmZmVyLmZyb20oZmlsZU9iamVjdC5maWxlLl9kYXRhLCAnYmFzZTY0Jyk7XG4gICAgICAgIGZpbGVPYmplY3QuZmlsZVNpemUgPSBCdWZmZXIuYnl0ZUxlbmd0aChidWZmZXJEYXRhKTtcbiAgICAgICAgLy8gcHJlcGFyZSBmaWxlIG9wdGlvbnNcbiAgICAgICAgY29uc3QgZmlsZU9wdGlvbnMgPSB7XG4gICAgICAgICAgbWV0YWRhdGE6IGZpbGVPYmplY3QuZmlsZS5fbWV0YWRhdGEsXG4gICAgICAgIH07XG4gICAgICAgIC8vIHNvbWUgczMtY29tcGF0aWJsZSBwcm92aWRlcnMgKERpZ2l0YWxPY2VhbiwgTGlub2RlKSBkbyBub3QgYWNjZXB0IHRhZ3NcbiAgICAgICAgLy8gc28gd2UgZG8gbm90IGluY2x1ZGUgdGhlIHRhZ3Mgb3B0aW9uIGlmIGl0IGlzIGVtcHR5LlxuICAgICAgICBjb25zdCBmaWxlVGFncyA9XG4gICAgICAgICAgT2JqZWN0LmtleXMoZmlsZU9iamVjdC5maWxlLl90YWdzKS5sZW5ndGggPiAwID8geyB0YWdzOiBmaWxlT2JqZWN0LmZpbGUuX3RhZ3MgfSA6IHt9O1xuICAgICAgICBPYmplY3QuYXNzaWduKGZpbGVPcHRpb25zLCBmaWxlVGFncyk7XG4gICAgICAgIC8vIHNhdmUgZmlsZVxuICAgICAgICBjb25zdCBjcmVhdGVGaWxlUmVzdWx0ID0gYXdhaXQgZmlsZXNDb250cm9sbGVyLmNyZWF0ZUZpbGUoXG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICAgIGZpbGVPYmplY3QuZmlsZS5fbmFtZSxcbiAgICAgICAgICBidWZmZXJEYXRhLFxuICAgICAgICAgIGZpbGVPYmplY3QuZmlsZS5fc291cmNlLnR5cGUsXG4gICAgICAgICAgZmlsZU9wdGlvbnNcbiAgICAgICAgKTtcbiAgICAgICAgLy8gdXBkYXRlIGZpbGUgd2l0aCBuZXcgZGF0YVxuICAgICAgICBmaWxlT2JqZWN0LmZpbGUuX25hbWUgPSBjcmVhdGVGaWxlUmVzdWx0Lm5hbWU7XG4gICAgICAgIGZpbGVPYmplY3QuZmlsZS5fdXJsID0gY3JlYXRlRmlsZVJlc3VsdC51cmw7XG4gICAgICAgIGZpbGVPYmplY3QuZmlsZS5fcmVxdWVzdFRhc2sgPSBudWxsO1xuICAgICAgICBmaWxlT2JqZWN0LmZpbGUuX3ByZXZpb3VzU2F2ZSA9IFByb21pc2UucmVzb2x2ZShmaWxlT2JqZWN0LmZpbGUpO1xuICAgICAgICBzYXZlUmVzdWx0ID0ge1xuICAgICAgICAgIHVybDogY3JlYXRlRmlsZVJlc3VsdC51cmwsXG4gICAgICAgICAgbmFtZTogY3JlYXRlRmlsZVJlc3VsdC5uYW1lLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgLy8gcnVuIGFmdGVyU2F2ZUZpbGUgdHJpZ2dlclxuICAgICAgYXdhaXQgdHJpZ2dlcnMubWF5YmVSdW5GaWxlVHJpZ2dlcih0cmlnZ2Vycy5UeXBlcy5hZnRlclNhdmUsIGZpbGVPYmplY3QsIGNvbmZpZywgcmVxLmF1dGgpO1xuICAgICAgcmVzLnN0YXR1cygyMDEpO1xuICAgICAgcmVzLnNldCgnTG9jYXRpb24nLCBzYXZlUmVzdWx0LnVybCk7XG4gICAgICByZXMuanNvbihzYXZlUmVzdWx0KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ0Vycm9yIGNyZWF0aW5nIGEgZmlsZTogJywgZSk7XG4gICAgICBjb25zdCBlcnJvciA9IHRyaWdnZXJzLnJlc29sdmVFcnJvcihlLCB7XG4gICAgICAgIGNvZGU6IFBhcnNlLkVycm9yLkZJTEVfU0FWRV9FUlJPUixcbiAgICAgICAgbWVzc2FnZTogYENvdWxkIG5vdCBzdG9yZSBmaWxlOiAke2ZpbGVPYmplY3QuZmlsZS5fbmFtZX0uYCxcbiAgICAgIH0pO1xuICAgICAgbmV4dChlcnJvcik7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZGVsZXRlSGFuZGxlcihyZXEsIHJlcywgbmV4dCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB7IGZpbGVzQ29udHJvbGxlciB9ID0gcmVxLmNvbmZpZztcbiAgICAgIGNvbnN0IHsgZmlsZW5hbWUgfSA9IHJlcS5wYXJhbXM7XG4gICAgICAvLyBydW4gYmVmb3JlRGVsZXRlRmlsZSB0cmlnZ2VyXG4gICAgICBjb25zdCBmaWxlID0gbmV3IFBhcnNlLkZpbGUoZmlsZW5hbWUpO1xuICAgICAgZmlsZS5fdXJsID0gYXdhaXQgZmlsZXNDb250cm9sbGVyLmFkYXB0ZXIuZ2V0RmlsZUxvY2F0aW9uKHJlcS5jb25maWcsIGZpbGVuYW1lKTtcbiAgICAgIGNvbnN0IGZpbGVPYmplY3QgPSB7IGZpbGUsIGZpbGVTaXplOiBudWxsIH07XG4gICAgICBhd2FpdCB0cmlnZ2Vycy5tYXliZVJ1bkZpbGVUcmlnZ2VyKFxuICAgICAgICB0cmlnZ2Vycy5UeXBlcy5iZWZvcmVEZWxldGUsXG4gICAgICAgIGZpbGVPYmplY3QsXG4gICAgICAgIHJlcS5jb25maWcsXG4gICAgICAgIHJlcS5hdXRoXG4gICAgICApO1xuICAgICAgLy8gZGVsZXRlIGZpbGVcbiAgICAgIGF3YWl0IGZpbGVzQ29udHJvbGxlci5kZWxldGVGaWxlKHJlcS5jb25maWcsIGZpbGVuYW1lKTtcbiAgICAgIC8vIHJ1biBhZnRlckRlbGV0ZUZpbGUgdHJpZ2dlclxuICAgICAgYXdhaXQgdHJpZ2dlcnMubWF5YmVSdW5GaWxlVHJpZ2dlcihcbiAgICAgICAgdHJpZ2dlcnMuVHlwZXMuYWZ0ZXJEZWxldGUsXG4gICAgICAgIGZpbGVPYmplY3QsXG4gICAgICAgIHJlcS5jb25maWcsXG4gICAgICAgIHJlcS5hdXRoXG4gICAgICApO1xuICAgICAgcmVzLnN0YXR1cygyMDApO1xuICAgICAgLy8gVE9ETzogcmV0dXJuIHVzZWZ1bCBKU09OIGhlcmU/XG4gICAgICByZXMuZW5kKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbG9nZ2VyLmVycm9yKCdFcnJvciBkZWxldGluZyBhIGZpbGU6ICcsIGUpO1xuICAgICAgY29uc3QgZXJyb3IgPSB0cmlnZ2Vycy5yZXNvbHZlRXJyb3IoZSwge1xuICAgICAgICBjb2RlOiBQYXJzZS5FcnJvci5GSUxFX0RFTEVURV9FUlJPUixcbiAgICAgICAgbWVzc2FnZTogJ0NvdWxkIG5vdCBkZWxldGUgZmlsZS4nLFxuICAgICAgfSk7XG4gICAgICBuZXh0KGVycm9yKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBtZXRhZGF0YUhhbmRsZXIocmVxLCByZXMpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY29uZmlnID0gQ29uZmlnLmdldChyZXEucGFyYW1zLmFwcElkKTtcbiAgICAgIGNvbnN0IHsgZmlsZXNDb250cm9sbGVyIH0gPSBjb25maWc7XG4gICAgICBjb25zdCB7IGZpbGVuYW1lIH0gPSByZXEucGFyYW1zO1xuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGZpbGVzQ29udHJvbGxlci5nZXRNZXRhZGF0YShmaWxlbmFtZSk7XG4gICAgICByZXMuc3RhdHVzKDIwMCk7XG4gICAgICByZXMuanNvbihkYXRhKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJlcy5zdGF0dXMoMjAwKTtcbiAgICAgIHJlcy5qc29uKHt9KTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gaXNGaWxlU3RyZWFtYWJsZShyZXEsIGZpbGVzQ29udHJvbGxlcikge1xuICBjb25zdCByYW5nZSA9IChyZXEuZ2V0KCdSYW5nZScpIHx8ICcvLS8nKS5zcGxpdCgnLScpO1xuICBjb25zdCBzdGFydCA9IE51bWJlcihyYW5nZVswXSk7XG4gIGNvbnN0IGVuZCA9IE51bWJlcihyYW5nZVsxXSk7XG4gIHJldHVybiAoXG4gICAgKCFpc05hTihzdGFydCkgfHwgIWlzTmFOKGVuZCkpICYmIHR5cGVvZiBmaWxlc0NvbnRyb2xsZXIuYWRhcHRlci5oYW5kbGVGaWxlU3RyZWFtID09PSAnZnVuY3Rpb24nXG4gICk7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLElBQUFBLFFBQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLFdBQUEsR0FBQUMsdUJBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFHLEtBQUEsR0FBQUosc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFJLE9BQUEsR0FBQUwsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFLLE9BQUEsR0FBQU4sc0JBQUEsQ0FBQUMsT0FBQTtBQUErQixTQUFBRSx3QkFBQUksQ0FBQSxFQUFBQyxDQUFBLDZCQUFBQyxPQUFBLE1BQUFDLENBQUEsT0FBQUQsT0FBQSxJQUFBRSxDQUFBLE9BQUFGLE9BQUEsWUFBQU4sdUJBQUEsWUFBQUEsQ0FBQUksQ0FBQSxFQUFBQyxDQUFBLFNBQUFBLENBQUEsSUFBQUQsQ0FBQSxJQUFBQSxDQUFBLENBQUFLLFVBQUEsU0FBQUwsQ0FBQSxNQUFBTSxDQUFBLEVBQUFDLENBQUEsRUFBQUMsQ0FBQSxLQUFBQyxTQUFBLFFBQUFDLE9BQUEsRUFBQVYsQ0FBQSxpQkFBQUEsQ0FBQSx1QkFBQUEsQ0FBQSx5QkFBQUEsQ0FBQSxTQUFBUSxDQUFBLE1BQUFGLENBQUEsR0FBQUwsQ0FBQSxHQUFBRyxDQUFBLEdBQUFELENBQUEsUUFBQUcsQ0FBQSxDQUFBSyxHQUFBLENBQUFYLENBQUEsVUFBQU0sQ0FBQSxDQUFBTSxHQUFBLENBQUFaLENBQUEsR0FBQU0sQ0FBQSxDQUFBTyxHQUFB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
|