@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.
- package/LICENSE +176 -0
- package/NOTICE +10 -0
- package/README.md +1311 -0
- package/bin/parse-live-query-server +3 -0
- package/bin/parse-server +3 -0
- package/lib/AccountLockout.js +149 -0
- package/lib/Adapters/AdapterLoader.js +60 -0
- package/lib/Adapters/Analytics/AnalyticsAdapter.js +32 -0
- package/lib/Adapters/Auth/AuthAdapter.js +132 -0
- package/lib/Adapters/Auth/BaseCodeAuthAdapter.js +119 -0
- package/lib/Adapters/Auth/OAuth1Client.js +204 -0
- package/lib/Adapters/Auth/apple.js +125 -0
- package/lib/Adapters/Auth/facebook.js +187 -0
- package/lib/Adapters/Auth/gcenter.js +217 -0
- package/lib/Adapters/Auth/github.js +125 -0
- package/lib/Adapters/Auth/google.js +122 -0
- package/lib/Adapters/Auth/gpgames.js +125 -0
- package/lib/Adapters/Auth/httpsRequest.js +41 -0
- package/lib/Adapters/Auth/index.js +248 -0
- package/lib/Adapters/Auth/instagram.js +118 -0
- package/lib/Adapters/Auth/janraincapture.js +85 -0
- package/lib/Adapters/Auth/janrainengage.js +57 -0
- package/lib/Adapters/Auth/keycloak.js +168 -0
- package/lib/Adapters/Auth/ldap.js +193 -0
- package/lib/Adapters/Auth/line.js +125 -0
- package/lib/Adapters/Auth/linkedin.js +117 -0
- package/lib/Adapters/Auth/meetup.js +44 -0
- package/lib/Adapters/Auth/mfa.js +334 -0
- package/lib/Adapters/Auth/microsoft.js +111 -0
- package/lib/Adapters/Auth/oauth2.js +115 -0
- package/lib/Adapters/Auth/phantauth.js +53 -0
- package/lib/Adapters/Auth/qq.js +113 -0
- package/lib/Adapters/Auth/spotify.js +115 -0
- package/lib/Adapters/Auth/twitter.js +197 -0
- package/lib/Adapters/Auth/utils.js +28 -0
- package/lib/Adapters/Auth/vkontakte.js +55 -0
- package/lib/Adapters/Auth/wechat.js +110 -0
- package/lib/Adapters/Auth/weibo.js +141 -0
- package/lib/Adapters/Cache/CacheAdapter.js +40 -0
- package/lib/Adapters/Cache/InMemoryCache.js +61 -0
- package/lib/Adapters/Cache/InMemoryCacheAdapter.js +34 -0
- package/lib/Adapters/Cache/LRUCache.js +35 -0
- package/lib/Adapters/Cache/NullCacheAdapter.js +26 -0
- package/lib/Adapters/Cache/RedisCacheAdapter.js +109 -0
- package/lib/Adapters/Cache/SchemaCache.js +25 -0
- package/lib/Adapters/Email/MailAdapter.js +32 -0
- package/lib/Adapters/Files/FilesAdapter.js +129 -0
- package/lib/Adapters/Files/GridFSBucketAdapter.js +280 -0
- package/lib/Adapters/Files/GridStoreAdapter.js +5 -0
- package/lib/Adapters/Logger/LoggerAdapter.js +27 -0
- package/lib/Adapters/Logger/WinstonLogger.js +107 -0
- package/lib/Adapters/Logger/WinstonLoggerAdapter.js +63 -0
- package/lib/Adapters/MessageQueue/EventEmitterMQ.js +55 -0
- package/lib/Adapters/PubSub/EventEmitterPubSub.js +53 -0
- package/lib/Adapters/PubSub/PubSubAdapter.js +34 -0
- package/lib/Adapters/PubSub/RedisPubSub.js +49 -0
- package/lib/Adapters/Push/PushAdapter.js +40 -0
- package/lib/Adapters/Storage/Mongo/MongoCollection.js +212 -0
- package/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js +334 -0
- package/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js +1047 -0
- package/lib/Adapters/Storage/Mongo/MongoTransform.js +1397 -0
- package/lib/Adapters/Storage/Postgres/PostgresClient.js +38 -0
- package/lib/Adapters/Storage/Postgres/PostgresConfigParser.js +73 -0
- package/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js +2409 -0
- package/lib/Adapters/Storage/Postgres/sql/array/add-unique.sql +11 -0
- package/lib/Adapters/Storage/Postgres/sql/array/add.sql +11 -0
- package/lib/Adapters/Storage/Postgres/sql/array/contains-all-regex.sql +14 -0
- package/lib/Adapters/Storage/Postgres/sql/array/contains-all.sql +14 -0
- package/lib/Adapters/Storage/Postgres/sql/array/contains.sql +11 -0
- package/lib/Adapters/Storage/Postgres/sql/array/remove.sql +11 -0
- package/lib/Adapters/Storage/Postgres/sql/index.js +32 -0
- package/lib/Adapters/Storage/Postgres/sql/misc/json-object-set-keys.sql +19 -0
- package/lib/Adapters/Storage/StorageAdapter.js +2 -0
- package/lib/Adapters/WebSocketServer/WSAdapter.js +35 -0
- package/lib/Adapters/WebSocketServer/WSSAdapter.js +66 -0
- package/lib/Auth.js +687 -0
- package/lib/AuthDataLock.js +53 -0
- package/lib/ClientSDK.js +39 -0
- package/lib/Config.js +879 -0
- package/lib/Controllers/AdaptableController.js +72 -0
- package/lib/Controllers/AnalyticsController.js +43 -0
- package/lib/Controllers/CacheController.js +71 -0
- package/lib/Controllers/DatabaseController.js +1685 -0
- package/lib/Controllers/FilesController.js +122 -0
- package/lib/Controllers/HooksController.js +254 -0
- package/lib/Controllers/LiveQueryController.js +72 -0
- package/lib/Controllers/LoggerController.js +222 -0
- package/lib/Controllers/ParseGraphQLController.js +294 -0
- package/lib/Controllers/PushController.js +224 -0
- package/lib/Controllers/SchemaController.js +1563 -0
- package/lib/Controllers/UserController.js +364 -0
- package/lib/Controllers/index.js +251 -0
- package/lib/Controllers/types.js +2 -0
- package/lib/Deprecator/Deprecations.js +100 -0
- package/lib/Deprecator/Deprecator.js +140 -0
- package/lib/Error.js +50 -0
- package/lib/FileUrlValidator.js +69 -0
- package/lib/GraphQL/ParseGraphQLSchema.js +375 -0
- package/lib/GraphQL/ParseGraphQLServer.js +241 -0
- package/lib/GraphQL/helpers/objectsMutations.js +30 -0
- package/lib/GraphQL/helpers/objectsQueries.js +246 -0
- package/lib/GraphQL/helpers/queryComplexity.js +138 -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 +1099 -0
- package/lib/GraphQL/loaders/defaultRelaySchema.js +53 -0
- package/lib/GraphQL/loaders/filesMutations.js +107 -0
- package/lib/GraphQL/loaders/functionsMutations.js +77 -0
- package/lib/GraphQL/loaders/parseClassMutations.js +267 -0
- package/lib/GraphQL/loaders/parseClassQueries.js +126 -0
- package/lib/GraphQL/loaders/parseClassTypes.js +493 -0
- package/lib/GraphQL/loaders/schemaDirectives.js +62 -0
- package/lib/GraphQL/loaders/schemaMutations.js +161 -0
- package/lib/GraphQL/loaders/schemaQueries.js +80 -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 +71 -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 +280 -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/InstallationDedup.js +178 -0
- package/lib/KeyPromiseQueue.js +48 -0
- package/lib/LiveQuery/Client.js +90 -0
- package/lib/LiveQuery/Id.js +20 -0
- package/lib/LiveQuery/ParseCloudCodePublisher.js +54 -0
- package/lib/LiveQuery/ParseLiveQueryServer.js +1071 -0
- package/lib/LiveQuery/ParsePubSub.js +37 -0
- package/lib/LiveQuery/ParseWebSocketServer.js +66 -0
- package/lib/LiveQuery/QueryTools.js +443 -0
- package/lib/LiveQuery/RequestSchema.js +161 -0
- package/lib/LiveQuery/SessionTokenCache.js +51 -0
- package/lib/LiveQuery/Subscription.js +47 -0
- package/lib/LiveQuery/equalObjects.js +50 -0
- package/lib/Options/Definitions.js +1599 -0
- package/lib/Options/docs.js +389 -0
- package/lib/Options/index.js +12 -0
- package/lib/Options/parsers.js +89 -0
- package/lib/Page.js +44 -0
- package/lib/ParseMessageQueue.js +24 -0
- package/lib/ParseServer.js +632 -0
- package/lib/ParseServerRESTController.js +173 -0
- package/lib/PromiseRouter.js +208 -0
- package/lib/Push/PushQueue.js +67 -0
- package/lib/Push/PushWorker.js +101 -0
- package/lib/Push/utils.js +129 -0
- package/lib/RestQuery.js +1208 -0
- package/lib/RestWrite.js +1671 -0
- package/lib/Routers/AggregateRouter.js +150 -0
- package/lib/Routers/AnalyticsRouter.js +26 -0
- package/lib/Routers/AudiencesRouter.js +54 -0
- package/lib/Routers/ClassesRouter.js +191 -0
- package/lib/Routers/CloudCodeRouter.js +87 -0
- package/lib/Routers/FeaturesRouter.js +72 -0
- package/lib/Routers/FilesRouter.js +772 -0
- package/lib/Routers/FunctionsRouter.js +341 -0
- package/lib/Routers/GlobalConfigRouter.js +123 -0
- package/lib/Routers/GraphQLRouter.js +41 -0
- package/lib/Routers/HooksRouter.js +121 -0
- package/lib/Routers/IAPValidationRouter.js +113 -0
- package/lib/Routers/InstallationsRouter.js +46 -0
- package/lib/Routers/LogsRouter.js +57 -0
- package/lib/Routers/PagesRouter.js +676 -0
- package/lib/Routers/PurgeRouter.js +45 -0
- package/lib/Routers/PushRouter.js +75 -0
- package/lib/Routers/RolesRouter.js +33 -0
- package/lib/Routers/SchemasRouter.js +118 -0
- package/lib/Routers/SecurityRouter.js +34 -0
- package/lib/Routers/SessionsRouter.js +126 -0
- package/lib/Routers/UsersRouter.js +733 -0
- 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 +160 -0
- package/lib/Security/CheckGroups/CheckGroups.js +21 -0
- package/lib/Security/CheckRunner.js +213 -0
- package/lib/SharedRest.js +34 -0
- package/lib/StatusHandler.js +329 -0
- package/lib/TestUtils.js +87 -0
- package/lib/Utils.js +577 -0
- package/lib/batch.js +185 -0
- package/lib/cache.js +12 -0
- package/lib/cli/definitions/parse-live-query-server.js +9 -0
- package/lib/cli/definitions/parse-server.js +9 -0
- package/lib/cli/parse-live-query-server.js +14 -0
- package/lib/cli/parse-server.js +101 -0
- package/lib/cli/utils/commander.js +132 -0
- package/lib/cli/utils/runner.js +53 -0
- package/lib/cloud-code/Parse.Cloud.js +797 -0
- package/lib/cloud-code/Parse.Server.js +21 -0
- package/lib/cryptoUtils.js +54 -0
- package/lib/defaults.js +58 -0
- package/lib/deprecated.js +12 -0
- package/lib/index.js +89 -0
- package/lib/logger.js +40 -0
- package/lib/middlewares.js +810 -0
- package/lib/password.js +40 -0
- package/lib/request.js +175 -0
- package/lib/requiredParameter.js +11 -0
- package/lib/rest.js +264 -0
- package/lib/triggers.js +949 -0
- package/lib/vendor/README.md +8 -0
- package/lib/vendor/mongodbUrl.js +1012 -0
- package/package.json +172 -0
- package/postinstall.js +38 -0
- package/public/custom_json.html +17 -0
- package/public/custom_json.json +23 -0
- package/public/custom_page.html +15 -0
- package/public/de/email_verification_link_expired.html +24 -0
- package/public/de/email_verification_link_invalid.html +21 -0
- package/public/de/email_verification_send_fail.html +21 -0
- package/public/de/email_verification_send_success.html +19 -0
- package/public/de/email_verification_success.html +18 -0
- package/public/de/password_reset.html +65 -0
- package/public/de/password_reset_link_invalid.html +19 -0
- package/public/de/password_reset_success.html +18 -0
- package/public/de-AT/email_verification_link_expired.html +24 -0
- package/public/de-AT/email_verification_link_invalid.html +21 -0
- package/public/de-AT/email_verification_send_fail.html +21 -0
- package/public/de-AT/email_verification_send_success.html +19 -0
- package/public/de-AT/email_verification_success.html +18 -0
- package/public/de-AT/password_reset.html +65 -0
- package/public/de-AT/password_reset_link_invalid.html +19 -0
- package/public/de-AT/password_reset_success.html +18 -0
- package/public/email_verification_link_expired.html +24 -0
- package/public/email_verification_link_invalid.html +21 -0
- package/public/email_verification_send_fail.html +21 -0
- package/public/email_verification_send_success.html +19 -0
- package/public/email_verification_success.html +18 -0
- package/public/password_reset.html +65 -0
- package/public/password_reset_link_invalid.html +19 -0
- package/public/password_reset_success.html +18 -0
- 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 +320 -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/views/choose_password +215 -0
|
@@ -0,0 +1,1397 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _logger = _interopRequireDefault(require("../../../logger"));
|
|
4
|
+
var _lodash = _interopRequireDefault(require("lodash"));
|
|
5
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
6
|
+
var mongodb = require('mongodb');
|
|
7
|
+
var Parse = require('parse/node').Parse;
|
|
8
|
+
const Utils = require('../../../Utils');
|
|
9
|
+
const transformKey = (className, fieldName, schema) => {
|
|
10
|
+
// Check if the schema is known since it's a built-in field.
|
|
11
|
+
switch (fieldName) {
|
|
12
|
+
case 'objectId':
|
|
13
|
+
return '_id';
|
|
14
|
+
case 'createdAt':
|
|
15
|
+
return '_created_at';
|
|
16
|
+
case 'updatedAt':
|
|
17
|
+
return '_updated_at';
|
|
18
|
+
case 'sessionToken':
|
|
19
|
+
return '_session_token';
|
|
20
|
+
case 'lastUsed':
|
|
21
|
+
return '_last_used';
|
|
22
|
+
case 'timesUsed':
|
|
23
|
+
return 'times_used';
|
|
24
|
+
}
|
|
25
|
+
if (schema.fields[fieldName] && schema.fields[fieldName].__type == 'Pointer') {
|
|
26
|
+
fieldName = '_p_' + fieldName;
|
|
27
|
+
} else if (schema.fields[fieldName] && schema.fields[fieldName].type == 'Pointer') {
|
|
28
|
+
fieldName = '_p_' + fieldName;
|
|
29
|
+
}
|
|
30
|
+
return fieldName;
|
|
31
|
+
};
|
|
32
|
+
const transformKeyValueForUpdate = (className, restKey, restValue, parseFormatSchema) => {
|
|
33
|
+
// Check if the schema is known since it's a built-in field.
|
|
34
|
+
var key = restKey;
|
|
35
|
+
var timeField = false;
|
|
36
|
+
switch (key) {
|
|
37
|
+
case 'objectId':
|
|
38
|
+
case '_id':
|
|
39
|
+
if (['_GlobalConfig', '_GraphQLConfig'].includes(className)) {
|
|
40
|
+
return {
|
|
41
|
+
key: key,
|
|
42
|
+
value: parseInt(restValue)
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
key = '_id';
|
|
46
|
+
break;
|
|
47
|
+
case 'createdAt':
|
|
48
|
+
case '_created_at':
|
|
49
|
+
key = '_created_at';
|
|
50
|
+
timeField = true;
|
|
51
|
+
break;
|
|
52
|
+
case 'updatedAt':
|
|
53
|
+
case '_updated_at':
|
|
54
|
+
key = '_updated_at';
|
|
55
|
+
timeField = true;
|
|
56
|
+
break;
|
|
57
|
+
case 'sessionToken':
|
|
58
|
+
case '_session_token':
|
|
59
|
+
key = '_session_token';
|
|
60
|
+
break;
|
|
61
|
+
case 'expiresAt':
|
|
62
|
+
case '_expiresAt':
|
|
63
|
+
key = 'expiresAt';
|
|
64
|
+
timeField = true;
|
|
65
|
+
break;
|
|
66
|
+
case '_email_verify_token_expires_at':
|
|
67
|
+
key = '_email_verify_token_expires_at';
|
|
68
|
+
timeField = true;
|
|
69
|
+
break;
|
|
70
|
+
case '_account_lockout_expires_at':
|
|
71
|
+
key = '_account_lockout_expires_at';
|
|
72
|
+
timeField = true;
|
|
73
|
+
break;
|
|
74
|
+
case '_failed_login_count':
|
|
75
|
+
key = '_failed_login_count';
|
|
76
|
+
break;
|
|
77
|
+
case '_perishable_token_expires_at':
|
|
78
|
+
key = '_perishable_token_expires_at';
|
|
79
|
+
timeField = true;
|
|
80
|
+
break;
|
|
81
|
+
case '_password_changed_at':
|
|
82
|
+
key = '_password_changed_at';
|
|
83
|
+
timeField = true;
|
|
84
|
+
break;
|
|
85
|
+
case '_rperm':
|
|
86
|
+
case '_wperm':
|
|
87
|
+
return {
|
|
88
|
+
key: key,
|
|
89
|
+
value: restValue
|
|
90
|
+
};
|
|
91
|
+
case 'lastUsed':
|
|
92
|
+
case '_last_used':
|
|
93
|
+
key = '_last_used';
|
|
94
|
+
timeField = true;
|
|
95
|
+
break;
|
|
96
|
+
case 'timesUsed':
|
|
97
|
+
case 'times_used':
|
|
98
|
+
key = 'times_used';
|
|
99
|
+
timeField = true;
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
if (parseFormatSchema.fields[key] && parseFormatSchema.fields[key].type === 'Pointer' || !key.includes('.') && !parseFormatSchema.fields[key] && restValue && restValue.__type == 'Pointer' // Do not use the _p_ prefix for pointers inside nested documents
|
|
103
|
+
) {
|
|
104
|
+
key = '_p_' + key;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Handle atomic values
|
|
108
|
+
var value = transformTopLevelAtom(restValue);
|
|
109
|
+
if (value !== CannotTransform) {
|
|
110
|
+
if (timeField && typeof value === 'string') {
|
|
111
|
+
value = new Date(value);
|
|
112
|
+
}
|
|
113
|
+
if (restKey.indexOf('.') > 0) {
|
|
114
|
+
return {
|
|
115
|
+
key,
|
|
116
|
+
value: restValue
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
key,
|
|
121
|
+
value
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Handle arrays
|
|
126
|
+
if (Array.isArray(restValue)) {
|
|
127
|
+
value = restValue.map(transformInteriorValue);
|
|
128
|
+
return {
|
|
129
|
+
key,
|
|
130
|
+
value
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Handle update operators
|
|
135
|
+
if (typeof restValue === 'object' && '__op' in restValue) {
|
|
136
|
+
return {
|
|
137
|
+
key,
|
|
138
|
+
value: transformUpdateOperator(restValue, false)
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Handle normal objects by recursing
|
|
143
|
+
value = mapValues(restValue, transformInteriorValue);
|
|
144
|
+
return {
|
|
145
|
+
key,
|
|
146
|
+
value
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
const isRegex = value => {
|
|
150
|
+
return value && Utils.isRegExp(value);
|
|
151
|
+
};
|
|
152
|
+
const isStartsWithRegex = value => {
|
|
153
|
+
if (!isRegex(value)) {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
const matches = value.toString().match(/\/\^\\Q.*\\E\//);
|
|
157
|
+
return !!matches;
|
|
158
|
+
};
|
|
159
|
+
const isAllValuesRegexOrNone = values => {
|
|
160
|
+
if (!values || !Array.isArray(values) || values.length === 0) {
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
const firstValuesIsRegex = isStartsWithRegex(values[0]);
|
|
164
|
+
if (values.length === 1) {
|
|
165
|
+
return firstValuesIsRegex;
|
|
166
|
+
}
|
|
167
|
+
for (let i = 1, length = values.length; i < length; ++i) {
|
|
168
|
+
if (firstValuesIsRegex !== isStartsWithRegex(values[i])) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return true;
|
|
173
|
+
};
|
|
174
|
+
const isAnyValueRegex = values => {
|
|
175
|
+
return values.some(function (value) {
|
|
176
|
+
return isRegex(value);
|
|
177
|
+
});
|
|
178
|
+
};
|
|
179
|
+
const transformInteriorValue = restValue => {
|
|
180
|
+
if (restValue !== null && typeof restValue === 'object' && Object.keys(restValue).some(key => key.includes('$') || key.includes('.'))) {
|
|
181
|
+
throw new Parse.Error(Parse.Error.INVALID_NESTED_KEY, "Nested keys should not contain the '$' or '.' characters");
|
|
182
|
+
}
|
|
183
|
+
// Handle atomic values
|
|
184
|
+
var value = transformInteriorAtom(restValue);
|
|
185
|
+
if (value !== CannotTransform) {
|
|
186
|
+
if (value && typeof value === 'object') {
|
|
187
|
+
if (Utils.isDate(value)) {
|
|
188
|
+
return value;
|
|
189
|
+
}
|
|
190
|
+
if (Array.isArray(value)) {
|
|
191
|
+
value = value.map(transformInteriorValue);
|
|
192
|
+
} else {
|
|
193
|
+
value = mapValues(value, transformInteriorValue);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return value;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Handle arrays
|
|
200
|
+
if (Array.isArray(restValue)) {
|
|
201
|
+
return restValue.map(transformInteriorValue);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Handle update operators
|
|
205
|
+
if (typeof restValue === 'object' && '__op' in restValue) {
|
|
206
|
+
return transformUpdateOperator(restValue, true);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Handle normal objects by recursing
|
|
210
|
+
return mapValues(restValue, transformInteriorValue);
|
|
211
|
+
};
|
|
212
|
+
const valueAsDate = value => {
|
|
213
|
+
if (typeof value === 'string') {
|
|
214
|
+
return new Date(value);
|
|
215
|
+
} else if (Utils.isDate(value)) {
|
|
216
|
+
return value;
|
|
217
|
+
}
|
|
218
|
+
return false;
|
|
219
|
+
};
|
|
220
|
+
function transformQueryKeyValue(className, key, value, schema, count = false) {
|
|
221
|
+
switch (key) {
|
|
222
|
+
case 'createdAt':
|
|
223
|
+
if (valueAsDate(value)) {
|
|
224
|
+
return {
|
|
225
|
+
key: '_created_at',
|
|
226
|
+
value: valueAsDate(value)
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
key = '_created_at';
|
|
230
|
+
break;
|
|
231
|
+
case 'updatedAt':
|
|
232
|
+
if (valueAsDate(value)) {
|
|
233
|
+
return {
|
|
234
|
+
key: '_updated_at',
|
|
235
|
+
value: valueAsDate(value)
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
key = '_updated_at';
|
|
239
|
+
break;
|
|
240
|
+
case 'expiresAt':
|
|
241
|
+
if (valueAsDate(value)) {
|
|
242
|
+
return {
|
|
243
|
+
key: 'expiresAt',
|
|
244
|
+
value: valueAsDate(value)
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
break;
|
|
248
|
+
case '_email_verify_token_expires_at':
|
|
249
|
+
if (valueAsDate(value)) {
|
|
250
|
+
return {
|
|
251
|
+
key: '_email_verify_token_expires_at',
|
|
252
|
+
value: valueAsDate(value)
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
break;
|
|
256
|
+
case 'objectId':
|
|
257
|
+
{
|
|
258
|
+
if (['_GlobalConfig', '_GraphQLConfig'].includes(className)) {
|
|
259
|
+
value = parseInt(value);
|
|
260
|
+
}
|
|
261
|
+
return {
|
|
262
|
+
key: '_id',
|
|
263
|
+
value
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
case '_account_lockout_expires_at':
|
|
267
|
+
if (valueAsDate(value)) {
|
|
268
|
+
return {
|
|
269
|
+
key: '_account_lockout_expires_at',
|
|
270
|
+
value: valueAsDate(value)
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
break;
|
|
274
|
+
case '_failed_login_count':
|
|
275
|
+
return {
|
|
276
|
+
key,
|
|
277
|
+
value
|
|
278
|
+
};
|
|
279
|
+
case 'sessionToken':
|
|
280
|
+
return {
|
|
281
|
+
key: '_session_token',
|
|
282
|
+
value
|
|
283
|
+
};
|
|
284
|
+
case '_perishable_token_expires_at':
|
|
285
|
+
if (valueAsDate(value)) {
|
|
286
|
+
return {
|
|
287
|
+
key: '_perishable_token_expires_at',
|
|
288
|
+
value: valueAsDate(value)
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
break;
|
|
292
|
+
case '_password_changed_at':
|
|
293
|
+
if (valueAsDate(value)) {
|
|
294
|
+
return {
|
|
295
|
+
key: '_password_changed_at',
|
|
296
|
+
value: valueAsDate(value)
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
break;
|
|
300
|
+
case '_rperm':
|
|
301
|
+
case '_wperm':
|
|
302
|
+
case '_perishable_token':
|
|
303
|
+
case '_email_verify_token':
|
|
304
|
+
return {
|
|
305
|
+
key,
|
|
306
|
+
value
|
|
307
|
+
};
|
|
308
|
+
case '$or':
|
|
309
|
+
case '$and':
|
|
310
|
+
case '$nor':
|
|
311
|
+
return {
|
|
312
|
+
key: key,
|
|
313
|
+
value: value.map(subQuery => transformWhere(className, subQuery, schema, count))
|
|
314
|
+
};
|
|
315
|
+
case 'lastUsed':
|
|
316
|
+
if (valueAsDate(value)) {
|
|
317
|
+
return {
|
|
318
|
+
key: '_last_used',
|
|
319
|
+
value: valueAsDate(value)
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
key = '_last_used';
|
|
323
|
+
break;
|
|
324
|
+
case 'timesUsed':
|
|
325
|
+
return {
|
|
326
|
+
key: 'times_used',
|
|
327
|
+
value: value
|
|
328
|
+
};
|
|
329
|
+
default:
|
|
330
|
+
{
|
|
331
|
+
// Other auth data
|
|
332
|
+
const authDataMatch = key.match(/^authData\.([a-zA-Z0-9_]+)(\.(.+))?$/);
|
|
333
|
+
if (authDataMatch && className === '_User') {
|
|
334
|
+
const provider = authDataMatch[1];
|
|
335
|
+
const subField = authDataMatch[3];
|
|
336
|
+
return {
|
|
337
|
+
key: `_auth_data_${provider}${subField ? `.${subField}` : ''}`,
|
|
338
|
+
value
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
const expectedTypeIsArray = schema && schema.fields[key] && schema.fields[key].type === 'Array';
|
|
344
|
+
const expectedTypeIsPointer = schema && schema.fields[key] && schema.fields[key].type === 'Pointer';
|
|
345
|
+
const field = schema && schema.fields[key];
|
|
346
|
+
if (expectedTypeIsPointer || !schema && !key.includes('.') && value && value.__type === 'Pointer') {
|
|
347
|
+
key = '_p_' + key;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Handle query constraints
|
|
351
|
+
const transformedConstraint = transformConstraint(value, field, key, count);
|
|
352
|
+
if (transformedConstraint !== CannotTransform) {
|
|
353
|
+
if (transformedConstraint.$text) {
|
|
354
|
+
return {
|
|
355
|
+
key: '$text',
|
|
356
|
+
value: transformedConstraint.$text
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
if (transformedConstraint.$elemMatch) {
|
|
360
|
+
return {
|
|
361
|
+
key: '$nor',
|
|
362
|
+
value: [{
|
|
363
|
+
[key]: transformedConstraint
|
|
364
|
+
}]
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
return {
|
|
368
|
+
key,
|
|
369
|
+
value: transformedConstraint
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
if (expectedTypeIsArray && !Array.isArray(value)) {
|
|
373
|
+
return {
|
|
374
|
+
key,
|
|
375
|
+
value: {
|
|
376
|
+
$all: [transformInteriorAtom(value)]
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Handle atomic values
|
|
382
|
+
const transformRes = key.includes('.') ? transformInteriorAtom(value) : transformTopLevelAtom(value);
|
|
383
|
+
if (transformRes !== CannotTransform) {
|
|
384
|
+
return {
|
|
385
|
+
key,
|
|
386
|
+
value: transformRes
|
|
387
|
+
};
|
|
388
|
+
} else {
|
|
389
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, `You cannot use ${value} as a query parameter.`);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Main exposed method to help run queries.
|
|
394
|
+
// restWhere is the "where" clause in REST API form.
|
|
395
|
+
// Returns the mongo form of the query.
|
|
396
|
+
function transformWhere(className, restWhere, schema, count = false) {
|
|
397
|
+
const mongoWhere = {};
|
|
398
|
+
for (const restKey in restWhere) {
|
|
399
|
+
const out = transformQueryKeyValue(className, restKey, restWhere[restKey], schema, count);
|
|
400
|
+
mongoWhere[out.key] = out.value;
|
|
401
|
+
}
|
|
402
|
+
return mongoWhere;
|
|
403
|
+
}
|
|
404
|
+
const parseObjectKeyValueToMongoObjectKeyValue = (restKey, restValue, schema) => {
|
|
405
|
+
// Check if the schema is known since it's a built-in field.
|
|
406
|
+
let transformedValue;
|
|
407
|
+
let coercedToDate;
|
|
408
|
+
switch (restKey) {
|
|
409
|
+
case 'objectId':
|
|
410
|
+
return {
|
|
411
|
+
key: '_id',
|
|
412
|
+
value: restValue
|
|
413
|
+
};
|
|
414
|
+
case 'expiresAt':
|
|
415
|
+
transformedValue = transformTopLevelAtom(restValue);
|
|
416
|
+
coercedToDate = typeof transformedValue === 'string' ? new Date(transformedValue) : transformedValue;
|
|
417
|
+
return {
|
|
418
|
+
key: 'expiresAt',
|
|
419
|
+
value: coercedToDate
|
|
420
|
+
};
|
|
421
|
+
case '_email_verify_token_expires_at':
|
|
422
|
+
transformedValue = transformTopLevelAtom(restValue);
|
|
423
|
+
coercedToDate = typeof transformedValue === 'string' ? new Date(transformedValue) : transformedValue;
|
|
424
|
+
return {
|
|
425
|
+
key: '_email_verify_token_expires_at',
|
|
426
|
+
value: coercedToDate
|
|
427
|
+
};
|
|
428
|
+
case '_account_lockout_expires_at':
|
|
429
|
+
transformedValue = transformTopLevelAtom(restValue);
|
|
430
|
+
coercedToDate = typeof transformedValue === 'string' ? new Date(transformedValue) : transformedValue;
|
|
431
|
+
return {
|
|
432
|
+
key: '_account_lockout_expires_at',
|
|
433
|
+
value: coercedToDate
|
|
434
|
+
};
|
|
435
|
+
case '_perishable_token_expires_at':
|
|
436
|
+
transformedValue = transformTopLevelAtom(restValue);
|
|
437
|
+
coercedToDate = typeof transformedValue === 'string' ? new Date(transformedValue) : transformedValue;
|
|
438
|
+
return {
|
|
439
|
+
key: '_perishable_token_expires_at',
|
|
440
|
+
value: coercedToDate
|
|
441
|
+
};
|
|
442
|
+
case '_password_changed_at':
|
|
443
|
+
transformedValue = transformTopLevelAtom(restValue);
|
|
444
|
+
coercedToDate = typeof transformedValue === 'string' ? new Date(transformedValue) : transformedValue;
|
|
445
|
+
return {
|
|
446
|
+
key: '_password_changed_at',
|
|
447
|
+
value: coercedToDate
|
|
448
|
+
};
|
|
449
|
+
case '_failed_login_count':
|
|
450
|
+
case '_rperm':
|
|
451
|
+
case '_wperm':
|
|
452
|
+
case '_email_verify_token':
|
|
453
|
+
case '_hashed_password':
|
|
454
|
+
case '_perishable_token':
|
|
455
|
+
return {
|
|
456
|
+
key: restKey,
|
|
457
|
+
value: restValue
|
|
458
|
+
};
|
|
459
|
+
case 'sessionToken':
|
|
460
|
+
return {
|
|
461
|
+
key: '_session_token',
|
|
462
|
+
value: restValue
|
|
463
|
+
};
|
|
464
|
+
default:
|
|
465
|
+
// Auth data should have been transformed already
|
|
466
|
+
if (restKey.match(/^authData\.([a-zA-Z0-9_]+)\.id$/)) {
|
|
467
|
+
throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'can only query on ' + restKey);
|
|
468
|
+
}
|
|
469
|
+
// Trust that the auth data has been transformed and save it directly
|
|
470
|
+
if (restKey.match(/^_auth_data_[a-zA-Z0-9_]+$/)) {
|
|
471
|
+
return {
|
|
472
|
+
key: restKey,
|
|
473
|
+
value: restValue
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
//skip straight to transformTopLevelAtom for Bytes, they don't show up in the schema for some reason
|
|
478
|
+
if (restValue && restValue.__type !== 'Bytes') {
|
|
479
|
+
//Note: We may not know the type of a field here, as the user could be saving (null) to a field
|
|
480
|
+
//That never existed before, meaning we can't infer the type.
|
|
481
|
+
if (schema.fields[restKey] && schema.fields[restKey].type == 'Pointer' || restValue.__type == 'Pointer') {
|
|
482
|
+
restKey = '_p_' + restKey;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// Handle atomic values
|
|
487
|
+
var value = transformTopLevelAtom(restValue);
|
|
488
|
+
if (value !== CannotTransform) {
|
|
489
|
+
return {
|
|
490
|
+
key: restKey,
|
|
491
|
+
value: value
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// ACLs are handled before this method is called
|
|
496
|
+
// If an ACL key still exists here, something is wrong.
|
|
497
|
+
if (restKey === 'ACL') {
|
|
498
|
+
throw 'There was a problem transforming an ACL.';
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// Handle arrays
|
|
502
|
+
if (Array.isArray(restValue)) {
|
|
503
|
+
value = restValue.map(transformInteriorValue);
|
|
504
|
+
return {
|
|
505
|
+
key: restKey,
|
|
506
|
+
value: value
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Handle normal objects by recursing
|
|
511
|
+
if (Object.keys(restValue).some(key => key.includes('$') || key.includes('.'))) {
|
|
512
|
+
throw new Parse.Error(Parse.Error.INVALID_NESTED_KEY, "Nested keys should not contain the '$' or '.' characters");
|
|
513
|
+
}
|
|
514
|
+
value = mapValues(restValue, transformInteriorValue);
|
|
515
|
+
return {
|
|
516
|
+
key: restKey,
|
|
517
|
+
value
|
|
518
|
+
};
|
|
519
|
+
};
|
|
520
|
+
const parseObjectToMongoObjectForCreate = (className, restCreate, schema) => {
|
|
521
|
+
restCreate = addLegacyACL(restCreate);
|
|
522
|
+
const mongoCreate = {};
|
|
523
|
+
for (const restKey in restCreate) {
|
|
524
|
+
if (restCreate[restKey] && restCreate[restKey].__type === 'Relation') {
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
const {
|
|
528
|
+
key,
|
|
529
|
+
value
|
|
530
|
+
} = parseObjectKeyValueToMongoObjectKeyValue(restKey, restCreate[restKey], schema);
|
|
531
|
+
if (value !== undefined) {
|
|
532
|
+
mongoCreate[key] = value;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// Use the legacy mongo format for createdAt and updatedAt
|
|
537
|
+
if (mongoCreate.createdAt) {
|
|
538
|
+
mongoCreate._created_at = new Date(mongoCreate.createdAt.iso || mongoCreate.createdAt);
|
|
539
|
+
delete mongoCreate.createdAt;
|
|
540
|
+
}
|
|
541
|
+
if (mongoCreate.updatedAt) {
|
|
542
|
+
mongoCreate._updated_at = new Date(mongoCreate.updatedAt.iso || mongoCreate.updatedAt);
|
|
543
|
+
delete mongoCreate.updatedAt;
|
|
544
|
+
}
|
|
545
|
+
return mongoCreate;
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
// Main exposed method to help update old objects.
|
|
549
|
+
const transformUpdate = (className, restUpdate, parseFormatSchema) => {
|
|
550
|
+
const mongoUpdate = {};
|
|
551
|
+
const acl = addLegacyACL(restUpdate);
|
|
552
|
+
if (acl._rperm || acl._wperm || acl._acl) {
|
|
553
|
+
mongoUpdate.$set = {};
|
|
554
|
+
if (acl._rperm) {
|
|
555
|
+
mongoUpdate.$set._rperm = acl._rperm;
|
|
556
|
+
}
|
|
557
|
+
if (acl._wperm) {
|
|
558
|
+
mongoUpdate.$set._wperm = acl._wperm;
|
|
559
|
+
}
|
|
560
|
+
if (acl._acl) {
|
|
561
|
+
mongoUpdate.$set._acl = acl._acl;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
for (var restKey in restUpdate) {
|
|
565
|
+
if (restUpdate[restKey] && restUpdate[restKey].__type === 'Relation') {
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
var out = transformKeyValueForUpdate(className, restKey, restUpdate[restKey], parseFormatSchema);
|
|
569
|
+
|
|
570
|
+
// If the output value is an object with any $ keys, it's an
|
|
571
|
+
// operator that needs to be lifted onto the top level update
|
|
572
|
+
// object.
|
|
573
|
+
if (typeof out.value === 'object' && out.value !== null && out.value.__op) {
|
|
574
|
+
mongoUpdate[out.value.__op] = mongoUpdate[out.value.__op] || {};
|
|
575
|
+
mongoUpdate[out.value.__op][out.key] = out.value.arg;
|
|
576
|
+
} else {
|
|
577
|
+
mongoUpdate['$set'] = mongoUpdate['$set'] || {};
|
|
578
|
+
mongoUpdate['$set'][out.key] = out.value;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return mongoUpdate;
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
// Add the legacy _acl format.
|
|
585
|
+
const addLegacyACL = restObject => {
|
|
586
|
+
const restObjectCopy = {
|
|
587
|
+
...restObject
|
|
588
|
+
};
|
|
589
|
+
const _acl = {};
|
|
590
|
+
if (restObject._wperm) {
|
|
591
|
+
restObject._wperm.forEach(entry => {
|
|
592
|
+
_acl[entry] = {
|
|
593
|
+
w: true
|
|
594
|
+
};
|
|
595
|
+
});
|
|
596
|
+
restObjectCopy._acl = _acl;
|
|
597
|
+
}
|
|
598
|
+
if (restObject._rperm) {
|
|
599
|
+
restObject._rperm.forEach(entry => {
|
|
600
|
+
if (!(entry in _acl)) {
|
|
601
|
+
_acl[entry] = {
|
|
602
|
+
r: true
|
|
603
|
+
};
|
|
604
|
+
} else {
|
|
605
|
+
_acl[entry].r = true;
|
|
606
|
+
}
|
|
607
|
+
});
|
|
608
|
+
restObjectCopy._acl = _acl;
|
|
609
|
+
}
|
|
610
|
+
return restObjectCopy;
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
// A sentinel value that helper transformations return when they
|
|
614
|
+
// cannot perform a transformation
|
|
615
|
+
function CannotTransform() {}
|
|
616
|
+
const transformInteriorAtom = atom => {
|
|
617
|
+
// TODO: check validity harder for the __type-defined types
|
|
618
|
+
if (typeof atom === 'object' && atom && !Utils.isDate(atom) && atom.__type === 'Pointer') {
|
|
619
|
+
return {
|
|
620
|
+
__type: 'Pointer',
|
|
621
|
+
className: atom.className,
|
|
622
|
+
objectId: atom.objectId
|
|
623
|
+
};
|
|
624
|
+
} else if (typeof atom === 'function' || typeof atom === 'symbol') {
|
|
625
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, `cannot transform value: ${atom}`);
|
|
626
|
+
} else if (DateCoder.isValidJSON(atom)) {
|
|
627
|
+
return DateCoder.JSONToDatabase(atom);
|
|
628
|
+
} else if (BytesCoder.isValidJSON(atom)) {
|
|
629
|
+
return BytesCoder.JSONToDatabase(atom);
|
|
630
|
+
} else if (typeof atom === 'object' && atom && atom.$regex !== undefined) {
|
|
631
|
+
return new RegExp(atom.$regex);
|
|
632
|
+
} else {
|
|
633
|
+
return atom;
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
|
|
637
|
+
// Helper function to transform an atom from REST format to Mongo format.
|
|
638
|
+
// An atom is anything that can't contain other expressions. So it
|
|
639
|
+
// includes things where objects are used to represent other
|
|
640
|
+
// datatypes, like pointers and dates, but it does not include objects
|
|
641
|
+
// or arrays with generic stuff inside.
|
|
642
|
+
// Raises an error if this cannot possibly be valid REST format.
|
|
643
|
+
// Returns CannotTransform if it's just not an atom
|
|
644
|
+
function transformTopLevelAtom(atom, field) {
|
|
645
|
+
switch (typeof atom) {
|
|
646
|
+
case 'number':
|
|
647
|
+
case 'boolean':
|
|
648
|
+
case 'undefined':
|
|
649
|
+
return atom;
|
|
650
|
+
case 'string':
|
|
651
|
+
if (field && field.type === 'Pointer') {
|
|
652
|
+
return `${field.targetClass}$${atom}`;
|
|
653
|
+
}
|
|
654
|
+
return atom;
|
|
655
|
+
case 'symbol':
|
|
656
|
+
case 'function':
|
|
657
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, `cannot transform value: ${atom}`);
|
|
658
|
+
case 'object':
|
|
659
|
+
if (Utils.isDate(atom)) {
|
|
660
|
+
// Technically dates are not rest format, but, it seems pretty
|
|
661
|
+
// clear what they should be transformed to, so let's just do it.
|
|
662
|
+
return atom;
|
|
663
|
+
}
|
|
664
|
+
if (atom === null) {
|
|
665
|
+
return atom;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// TODO: check validity harder for the __type-defined types
|
|
669
|
+
if (atom.__type == 'Pointer') {
|
|
670
|
+
return `${atom.className}$${atom.objectId}`;
|
|
671
|
+
}
|
|
672
|
+
if (DateCoder.isValidJSON(atom)) {
|
|
673
|
+
return DateCoder.JSONToDatabase(atom);
|
|
674
|
+
}
|
|
675
|
+
if (BytesCoder.isValidJSON(atom)) {
|
|
676
|
+
return BytesCoder.JSONToDatabase(atom);
|
|
677
|
+
}
|
|
678
|
+
if (GeoPointCoder.isValidJSON(atom)) {
|
|
679
|
+
return GeoPointCoder.JSONToDatabase(atom);
|
|
680
|
+
}
|
|
681
|
+
if (PolygonCoder.isValidJSON(atom)) {
|
|
682
|
+
return PolygonCoder.JSONToDatabase(atom);
|
|
683
|
+
}
|
|
684
|
+
if (FileCoder.isValidJSON(atom)) {
|
|
685
|
+
return FileCoder.JSONToDatabase(atom);
|
|
686
|
+
}
|
|
687
|
+
return CannotTransform;
|
|
688
|
+
default:
|
|
689
|
+
// I don't think typeof can ever let us get here
|
|
690
|
+
throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, `really did not expect value: ${atom}`);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// Transforms a query constraint from REST API format to Mongo format.
|
|
695
|
+
// A constraint is something with fields like $lt.
|
|
696
|
+
// If it is not a valid constraint but it could be a valid something
|
|
697
|
+
// else, return CannotTransform.
|
|
698
|
+
// inArray is whether this is an array field.
|
|
699
|
+
function transformConstraint(constraint, field, queryKey, count = false) {
|
|
700
|
+
const inArray = field && field.type && field.type === 'Array';
|
|
701
|
+
// Check wether the given key has `.`
|
|
702
|
+
const isNestedKey = queryKey.indexOf('.') > -1;
|
|
703
|
+
if (typeof constraint !== 'object' || !constraint) {
|
|
704
|
+
return CannotTransform;
|
|
705
|
+
}
|
|
706
|
+
// For inArray or nested key, we need to transform the interior atom
|
|
707
|
+
const transformFunction = inArray || isNestedKey ? transformInteriorAtom : transformTopLevelAtom;
|
|
708
|
+
const transformer = atom => {
|
|
709
|
+
const result = transformFunction(atom, field);
|
|
710
|
+
if (result === CannotTransform) {
|
|
711
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad atom: ${JSON.stringify(atom)}`);
|
|
712
|
+
}
|
|
713
|
+
return result;
|
|
714
|
+
};
|
|
715
|
+
// keys is the constraints in reverse alphabetical order.
|
|
716
|
+
// This is a hack so that:
|
|
717
|
+
// $regex is handled before $options
|
|
718
|
+
// $nearSphere is handled before $maxDistance
|
|
719
|
+
var keys = Object.keys(constraint).sort().reverse();
|
|
720
|
+
var answer = {};
|
|
721
|
+
for (var key of keys) {
|
|
722
|
+
switch (key) {
|
|
723
|
+
case '$lt':
|
|
724
|
+
case '$lte':
|
|
725
|
+
case '$gt':
|
|
726
|
+
case '$gte':
|
|
727
|
+
case '$exists':
|
|
728
|
+
case '$ne':
|
|
729
|
+
case '$eq':
|
|
730
|
+
{
|
|
731
|
+
const val = constraint[key];
|
|
732
|
+
if (val && typeof val === 'object' && val.$relativeTime) {
|
|
733
|
+
if (field && field.type !== 'Date') {
|
|
734
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, '$relativeTime can only be used with Date field');
|
|
735
|
+
}
|
|
736
|
+
switch (key) {
|
|
737
|
+
case '$exists':
|
|
738
|
+
case '$ne':
|
|
739
|
+
case '$eq':
|
|
740
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, '$relativeTime can only be used with the $lt, $lte, $gt, and $gte operators');
|
|
741
|
+
}
|
|
742
|
+
const parserResult = Utils.relativeTimeToDate(val.$relativeTime);
|
|
743
|
+
if (parserResult.status === 'success') {
|
|
744
|
+
answer[key] = parserResult.result;
|
|
745
|
+
break;
|
|
746
|
+
}
|
|
747
|
+
_logger.default.info('Error while parsing relative date', parserResult);
|
|
748
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $relativeTime (${key}) value. ${parserResult.info}`);
|
|
749
|
+
}
|
|
750
|
+
answer[key] = transformer(val);
|
|
751
|
+
break;
|
|
752
|
+
}
|
|
753
|
+
case '$in':
|
|
754
|
+
case '$nin':
|
|
755
|
+
{
|
|
756
|
+
const arr = constraint[key];
|
|
757
|
+
if (!Array.isArray(arr)) {
|
|
758
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad ' + key + ' value');
|
|
759
|
+
}
|
|
760
|
+
answer[key] = _lodash.default.flatMap(arr, value => {
|
|
761
|
+
return (atom => {
|
|
762
|
+
if (Array.isArray(atom)) {
|
|
763
|
+
return value.map(transformer);
|
|
764
|
+
} else {
|
|
765
|
+
return transformer(atom);
|
|
766
|
+
}
|
|
767
|
+
})(value);
|
|
768
|
+
});
|
|
769
|
+
break;
|
|
770
|
+
}
|
|
771
|
+
case '$all':
|
|
772
|
+
{
|
|
773
|
+
const arr = constraint[key];
|
|
774
|
+
if (!Array.isArray(arr)) {
|
|
775
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad ' + key + ' value');
|
|
776
|
+
}
|
|
777
|
+
answer[key] = arr.map(transformInteriorAtom);
|
|
778
|
+
const values = answer[key];
|
|
779
|
+
if (isAnyValueRegex(values) && !isAllValuesRegexOrNone(values)) {
|
|
780
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'All $all values must be of regex type or none: ' + values);
|
|
781
|
+
}
|
|
782
|
+
break;
|
|
783
|
+
}
|
|
784
|
+
case '$regex':
|
|
785
|
+
var s = constraint[key];
|
|
786
|
+
if (typeof s !== 'string') {
|
|
787
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad regex: ' + s);
|
|
788
|
+
}
|
|
789
|
+
answer[key] = s;
|
|
790
|
+
break;
|
|
791
|
+
case '$containedBy':
|
|
792
|
+
{
|
|
793
|
+
const arr = constraint[key];
|
|
794
|
+
if (!Array.isArray(arr)) {
|
|
795
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $containedBy: should be an array`);
|
|
796
|
+
}
|
|
797
|
+
answer.$elemMatch = {
|
|
798
|
+
$nin: arr.map(transformer)
|
|
799
|
+
};
|
|
800
|
+
break;
|
|
801
|
+
}
|
|
802
|
+
case '$options':
|
|
803
|
+
answer[key] = constraint[key];
|
|
804
|
+
break;
|
|
805
|
+
case '$text':
|
|
806
|
+
{
|
|
807
|
+
const search = constraint[key].$search;
|
|
808
|
+
if (typeof search !== 'object') {
|
|
809
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $text: $search, should be object`);
|
|
810
|
+
}
|
|
811
|
+
if (!search.$term || typeof search.$term !== 'string') {
|
|
812
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $text: $term, should be string`);
|
|
813
|
+
} else {
|
|
814
|
+
answer[key] = {
|
|
815
|
+
$search: search.$term
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
if (search.$language && typeof search.$language !== 'string') {
|
|
819
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $text: $language, should be string`);
|
|
820
|
+
} else if (search.$language) {
|
|
821
|
+
answer[key].$language = search.$language;
|
|
822
|
+
}
|
|
823
|
+
if (search.$caseSensitive && typeof search.$caseSensitive !== 'boolean') {
|
|
824
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $text: $caseSensitive, should be boolean`);
|
|
825
|
+
} else if (search.$caseSensitive) {
|
|
826
|
+
answer[key].$caseSensitive = search.$caseSensitive;
|
|
827
|
+
}
|
|
828
|
+
if (search.$diacriticSensitive && typeof search.$diacriticSensitive !== 'boolean') {
|
|
829
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad $text: $diacriticSensitive, should be boolean`);
|
|
830
|
+
} else if (search.$diacriticSensitive) {
|
|
831
|
+
answer[key].$diacriticSensitive = search.$diacriticSensitive;
|
|
832
|
+
}
|
|
833
|
+
break;
|
|
834
|
+
}
|
|
835
|
+
case '$nearSphere':
|
|
836
|
+
{
|
|
837
|
+
const point = constraint[key];
|
|
838
|
+
if (count) {
|
|
839
|
+
answer.$geoWithin = {
|
|
840
|
+
$centerSphere: [[point.longitude, point.latitude], constraint.$maxDistance]
|
|
841
|
+
};
|
|
842
|
+
} else {
|
|
843
|
+
answer[key] = [point.longitude, point.latitude];
|
|
844
|
+
}
|
|
845
|
+
break;
|
|
846
|
+
}
|
|
847
|
+
case '$maxDistance':
|
|
848
|
+
{
|
|
849
|
+
if (count) {
|
|
850
|
+
break;
|
|
851
|
+
}
|
|
852
|
+
answer[key] = constraint[key];
|
|
853
|
+
break;
|
|
854
|
+
}
|
|
855
|
+
// The SDKs don't seem to use these but they are documented in the
|
|
856
|
+
// REST API docs.
|
|
857
|
+
case '$maxDistanceInRadians':
|
|
858
|
+
answer['$maxDistance'] = constraint[key];
|
|
859
|
+
break;
|
|
860
|
+
case '$maxDistanceInMiles':
|
|
861
|
+
answer['$maxDistance'] = constraint[key] / 3959;
|
|
862
|
+
break;
|
|
863
|
+
case '$maxDistanceInKilometers':
|
|
864
|
+
answer['$maxDistance'] = constraint[key] / 6371;
|
|
865
|
+
break;
|
|
866
|
+
case '$select':
|
|
867
|
+
case '$dontSelect':
|
|
868
|
+
throw new Parse.Error(Parse.Error.COMMAND_UNAVAILABLE, 'the ' + key + ' constraint is not supported yet');
|
|
869
|
+
case '$within':
|
|
870
|
+
var box = constraint[key]['$box'];
|
|
871
|
+
if (!box || box.length != 2) {
|
|
872
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'malformatted $within arg');
|
|
873
|
+
}
|
|
874
|
+
answer[key] = {
|
|
875
|
+
$box: [[box[0].longitude, box[0].latitude], [box[1].longitude, box[1].latitude]]
|
|
876
|
+
};
|
|
877
|
+
break;
|
|
878
|
+
case '$geoWithin':
|
|
879
|
+
{
|
|
880
|
+
const polygon = constraint[key]['$polygon'];
|
|
881
|
+
const centerSphere = constraint[key]['$centerSphere'];
|
|
882
|
+
if (polygon !== undefined) {
|
|
883
|
+
let points;
|
|
884
|
+
if (typeof polygon === 'object' && polygon.__type === 'Polygon') {
|
|
885
|
+
if (!polygon.coordinates || polygon.coordinates.length < 3) {
|
|
886
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value; Polygon.coordinates should contain at least 3 lon/lat pairs');
|
|
887
|
+
}
|
|
888
|
+
points = polygon.coordinates;
|
|
889
|
+
} else if (Array.isArray(polygon)) {
|
|
890
|
+
if (polygon.length < 3) {
|
|
891
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value; $polygon should contain at least 3 GeoPoints');
|
|
892
|
+
}
|
|
893
|
+
points = polygon;
|
|
894
|
+
} else {
|
|
895
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, "bad $geoWithin value; $polygon should be Polygon object or Array of Parse.GeoPoint's");
|
|
896
|
+
}
|
|
897
|
+
points = points.map(point => {
|
|
898
|
+
if (Array.isArray(point) && point.length === 2) {
|
|
899
|
+
Parse.GeoPoint._validate(point[1], point[0]);
|
|
900
|
+
return point;
|
|
901
|
+
}
|
|
902
|
+
if (!GeoPointCoder.isValidJSON(point)) {
|
|
903
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value');
|
|
904
|
+
} else {
|
|
905
|
+
Parse.GeoPoint._validate(point.latitude, point.longitude);
|
|
906
|
+
}
|
|
907
|
+
return [point.longitude, point.latitude];
|
|
908
|
+
});
|
|
909
|
+
answer[key] = {
|
|
910
|
+
$polygon: points
|
|
911
|
+
};
|
|
912
|
+
} else if (centerSphere !== undefined) {
|
|
913
|
+
if (!Array.isArray(centerSphere) || centerSphere.length < 2) {
|
|
914
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value; $centerSphere should be an array of Parse.GeoPoint and distance');
|
|
915
|
+
}
|
|
916
|
+
// Get point, convert to geo point if necessary and validate
|
|
917
|
+
let point = centerSphere[0];
|
|
918
|
+
if (Array.isArray(point) && point.length === 2) {
|
|
919
|
+
point = new Parse.GeoPoint(point[1], point[0]);
|
|
920
|
+
} else if (!GeoPointCoder.isValidJSON(point)) {
|
|
921
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value; $centerSphere geo point invalid');
|
|
922
|
+
}
|
|
923
|
+
Parse.GeoPoint._validate(point.latitude, point.longitude);
|
|
924
|
+
// Get distance and validate
|
|
925
|
+
const distance = centerSphere[1];
|
|
926
|
+
if (isNaN(distance) || distance < 0) {
|
|
927
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value; $centerSphere distance invalid');
|
|
928
|
+
}
|
|
929
|
+
answer[key] = {
|
|
930
|
+
$centerSphere: [[point.longitude, point.latitude], distance]
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
break;
|
|
934
|
+
}
|
|
935
|
+
case '$geoIntersects':
|
|
936
|
+
{
|
|
937
|
+
const point = constraint[key]['$point'];
|
|
938
|
+
if (!GeoPointCoder.isValidJSON(point)) {
|
|
939
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoIntersect value; $point should be GeoPoint');
|
|
940
|
+
} else {
|
|
941
|
+
Parse.GeoPoint._validate(point.latitude, point.longitude);
|
|
942
|
+
}
|
|
943
|
+
answer[key] = {
|
|
944
|
+
$geometry: {
|
|
945
|
+
type: 'Point',
|
|
946
|
+
coordinates: [point.longitude, point.latitude]
|
|
947
|
+
}
|
|
948
|
+
};
|
|
949
|
+
break;
|
|
950
|
+
}
|
|
951
|
+
default:
|
|
952
|
+
if (key.match(/^\$+/)) {
|
|
953
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad constraint: ' + key);
|
|
954
|
+
}
|
|
955
|
+
return CannotTransform;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
return answer;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
// Transforms an update operator from REST format to mongo format.
|
|
962
|
+
// To be transformed, the input should have an __op field.
|
|
963
|
+
// If flatten is true, this will flatten operators to their static
|
|
964
|
+
// data format. For example, an increment of 2 would simply become a
|
|
965
|
+
// 2.
|
|
966
|
+
// The output for a non-flattened operator is a hash with __op being
|
|
967
|
+
// the mongo op, and arg being the argument.
|
|
968
|
+
// The output for a flattened operator is just a value.
|
|
969
|
+
// Returns undefined if this should be a no-op.
|
|
970
|
+
|
|
971
|
+
function transformUpdateOperator({
|
|
972
|
+
__op,
|
|
973
|
+
amount,
|
|
974
|
+
objects
|
|
975
|
+
}, flatten) {
|
|
976
|
+
switch (__op) {
|
|
977
|
+
case 'Delete':
|
|
978
|
+
if (flatten) {
|
|
979
|
+
return undefined;
|
|
980
|
+
} else {
|
|
981
|
+
return {
|
|
982
|
+
__op: '$unset',
|
|
983
|
+
arg: ''
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
case 'Increment':
|
|
987
|
+
if (typeof amount !== 'number') {
|
|
988
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'incrementing must provide a number');
|
|
989
|
+
}
|
|
990
|
+
if (flatten) {
|
|
991
|
+
return amount;
|
|
992
|
+
} else {
|
|
993
|
+
return {
|
|
994
|
+
__op: '$inc',
|
|
995
|
+
arg: amount
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
case 'SetOnInsert':
|
|
999
|
+
if (flatten) {
|
|
1000
|
+
return amount;
|
|
1001
|
+
} else {
|
|
1002
|
+
return {
|
|
1003
|
+
__op: '$setOnInsert',
|
|
1004
|
+
arg: amount
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
1007
|
+
case 'Add':
|
|
1008
|
+
case 'AddUnique':
|
|
1009
|
+
if (!Array.isArray(objects)) {
|
|
1010
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'objects to add must be an array');
|
|
1011
|
+
}
|
|
1012
|
+
var toAdd = objects.map(transformInteriorAtom);
|
|
1013
|
+
if (flatten) {
|
|
1014
|
+
return toAdd;
|
|
1015
|
+
} else {
|
|
1016
|
+
var mongoOp = {
|
|
1017
|
+
Add: '$push',
|
|
1018
|
+
AddUnique: '$addToSet'
|
|
1019
|
+
}[__op];
|
|
1020
|
+
return {
|
|
1021
|
+
__op: mongoOp,
|
|
1022
|
+
arg: {
|
|
1023
|
+
$each: toAdd
|
|
1024
|
+
}
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
case 'Remove':
|
|
1028
|
+
if (!Array.isArray(objects)) {
|
|
1029
|
+
throw new Parse.Error(Parse.Error.INVALID_JSON, 'objects to remove must be an array');
|
|
1030
|
+
}
|
|
1031
|
+
var toRemove = objects.map(transformInteriorAtom);
|
|
1032
|
+
if (flatten) {
|
|
1033
|
+
return [];
|
|
1034
|
+
} else {
|
|
1035
|
+
return {
|
|
1036
|
+
__op: '$pullAll',
|
|
1037
|
+
arg: toRemove
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
default:
|
|
1041
|
+
throw new Parse.Error(Parse.Error.COMMAND_UNAVAILABLE, `The ${__op} operator is not supported yet.`);
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
function mapValues(object, iterator) {
|
|
1045
|
+
const result = {};
|
|
1046
|
+
Object.keys(object).forEach(key => {
|
|
1047
|
+
result[key] = iterator(object[key]);
|
|
1048
|
+
});
|
|
1049
|
+
return result;
|
|
1050
|
+
}
|
|
1051
|
+
const nestedMongoObjectToNestedParseObject = mongoObject => {
|
|
1052
|
+
switch (typeof mongoObject) {
|
|
1053
|
+
case 'string':
|
|
1054
|
+
case 'number':
|
|
1055
|
+
case 'boolean':
|
|
1056
|
+
case 'undefined':
|
|
1057
|
+
return mongoObject;
|
|
1058
|
+
case 'symbol':
|
|
1059
|
+
case 'function':
|
|
1060
|
+
throw 'bad value in nestedMongoObjectToNestedParseObject';
|
|
1061
|
+
case 'object':
|
|
1062
|
+
if (mongoObject === null) {
|
|
1063
|
+
return null;
|
|
1064
|
+
}
|
|
1065
|
+
if (Array.isArray(mongoObject)) {
|
|
1066
|
+
return mongoObject.map(nestedMongoObjectToNestedParseObject);
|
|
1067
|
+
}
|
|
1068
|
+
if (Utils.isDate(mongoObject)) {
|
|
1069
|
+
return Parse._encode(mongoObject);
|
|
1070
|
+
}
|
|
1071
|
+
if (mongoObject instanceof mongodb.Long) {
|
|
1072
|
+
return mongoObject.toNumber();
|
|
1073
|
+
}
|
|
1074
|
+
if (mongoObject instanceof mongodb.Double) {
|
|
1075
|
+
return mongoObject.value;
|
|
1076
|
+
}
|
|
1077
|
+
if (BytesCoder.isValidDatabaseObject(mongoObject)) {
|
|
1078
|
+
return BytesCoder.databaseToJSON(mongoObject);
|
|
1079
|
+
}
|
|
1080
|
+
if (Object.prototype.hasOwnProperty.call(mongoObject, '__type') && mongoObject.__type == 'Date' && Utils.isDate(mongoObject.iso)) {
|
|
1081
|
+
mongoObject.iso = mongoObject.iso.toJSON();
|
|
1082
|
+
return mongoObject;
|
|
1083
|
+
}
|
|
1084
|
+
return mapValues(mongoObject, nestedMongoObjectToNestedParseObject);
|
|
1085
|
+
default:
|
|
1086
|
+
throw 'unknown js type';
|
|
1087
|
+
}
|
|
1088
|
+
};
|
|
1089
|
+
const transformPointerString = (schema, field, pointerString) => {
|
|
1090
|
+
const objData = pointerString.split('$');
|
|
1091
|
+
if (objData[0] !== schema.fields[field].targetClass) {
|
|
1092
|
+
throw 'pointer to incorrect className';
|
|
1093
|
+
}
|
|
1094
|
+
return {
|
|
1095
|
+
__type: 'Pointer',
|
|
1096
|
+
className: objData[0],
|
|
1097
|
+
objectId: objData[1]
|
|
1098
|
+
};
|
|
1099
|
+
};
|
|
1100
|
+
|
|
1101
|
+
// Converts from a mongo-format object to a REST-format object.
|
|
1102
|
+
// Does not strip out anything based on a lack of authentication.
|
|
1103
|
+
const mongoObjectToParseObject = (className, mongoObject, schema) => {
|
|
1104
|
+
switch (typeof mongoObject) {
|
|
1105
|
+
case 'string':
|
|
1106
|
+
case 'number':
|
|
1107
|
+
case 'boolean':
|
|
1108
|
+
case 'undefined':
|
|
1109
|
+
return mongoObject;
|
|
1110
|
+
case 'symbol':
|
|
1111
|
+
case 'function':
|
|
1112
|
+
throw 'bad value in mongoObjectToParseObject';
|
|
1113
|
+
case 'object':
|
|
1114
|
+
{
|
|
1115
|
+
if (mongoObject === null) {
|
|
1116
|
+
return null;
|
|
1117
|
+
}
|
|
1118
|
+
if (Array.isArray(mongoObject)) {
|
|
1119
|
+
return mongoObject.map(nestedMongoObjectToNestedParseObject);
|
|
1120
|
+
}
|
|
1121
|
+
if (Utils.isDate(mongoObject)) {
|
|
1122
|
+
return Parse._encode(mongoObject);
|
|
1123
|
+
}
|
|
1124
|
+
if (mongoObject instanceof mongodb.Long) {
|
|
1125
|
+
return mongoObject.toNumber();
|
|
1126
|
+
}
|
|
1127
|
+
if (mongoObject instanceof mongodb.Double) {
|
|
1128
|
+
return mongoObject.value;
|
|
1129
|
+
}
|
|
1130
|
+
if (BytesCoder.isValidDatabaseObject(mongoObject)) {
|
|
1131
|
+
return BytesCoder.databaseToJSON(mongoObject);
|
|
1132
|
+
}
|
|
1133
|
+
const restObject = {};
|
|
1134
|
+
if (mongoObject._rperm || mongoObject._wperm) {
|
|
1135
|
+
restObject._rperm = mongoObject._rperm || [];
|
|
1136
|
+
restObject._wperm = mongoObject._wperm || [];
|
|
1137
|
+
delete mongoObject._rperm;
|
|
1138
|
+
delete mongoObject._wperm;
|
|
1139
|
+
}
|
|
1140
|
+
for (var key in mongoObject) {
|
|
1141
|
+
switch (key) {
|
|
1142
|
+
case '_id':
|
|
1143
|
+
restObject['objectId'] = '' + mongoObject[key];
|
|
1144
|
+
break;
|
|
1145
|
+
case '_hashed_password':
|
|
1146
|
+
restObject._hashed_password = mongoObject[key];
|
|
1147
|
+
break;
|
|
1148
|
+
case '_acl':
|
|
1149
|
+
break;
|
|
1150
|
+
case '_email_verify_token':
|
|
1151
|
+
case '_perishable_token':
|
|
1152
|
+
case '_perishable_token_expires_at':
|
|
1153
|
+
case '_password_changed_at':
|
|
1154
|
+
case '_tombstone':
|
|
1155
|
+
case '_email_verify_token_expires_at':
|
|
1156
|
+
case '_account_lockout_expires_at':
|
|
1157
|
+
case '_failed_login_count':
|
|
1158
|
+
case '_password_history':
|
|
1159
|
+
// Those keys will be deleted if needed in the DB Controller
|
|
1160
|
+
restObject[key] = mongoObject[key];
|
|
1161
|
+
break;
|
|
1162
|
+
case '_session_token':
|
|
1163
|
+
restObject['sessionToken'] = mongoObject[key];
|
|
1164
|
+
break;
|
|
1165
|
+
case 'updatedAt':
|
|
1166
|
+
case '_updated_at':
|
|
1167
|
+
restObject['updatedAt'] = Parse._encode(new Date(mongoObject[key])).iso;
|
|
1168
|
+
break;
|
|
1169
|
+
case 'createdAt':
|
|
1170
|
+
case '_created_at':
|
|
1171
|
+
restObject['createdAt'] = Parse._encode(new Date(mongoObject[key])).iso;
|
|
1172
|
+
break;
|
|
1173
|
+
case 'expiresAt':
|
|
1174
|
+
case '_expiresAt':
|
|
1175
|
+
restObject['expiresAt'] = Parse._encode(new Date(mongoObject[key]));
|
|
1176
|
+
break;
|
|
1177
|
+
case 'lastUsed':
|
|
1178
|
+
case '_last_used':
|
|
1179
|
+
restObject['lastUsed'] = Parse._encode(new Date(mongoObject[key])).iso;
|
|
1180
|
+
break;
|
|
1181
|
+
case 'timesUsed':
|
|
1182
|
+
case 'times_used':
|
|
1183
|
+
restObject['timesUsed'] = mongoObject[key];
|
|
1184
|
+
break;
|
|
1185
|
+
case 'authData':
|
|
1186
|
+
if (className === '_User') {
|
|
1187
|
+
_logger.default.warn('ignoring authData in _User as this key is reserved to be synthesized of `_auth_data_*` keys');
|
|
1188
|
+
} else {
|
|
1189
|
+
restObject['authData'] = mongoObject[key];
|
|
1190
|
+
}
|
|
1191
|
+
break;
|
|
1192
|
+
default:
|
|
1193
|
+
// Check other auth data keys
|
|
1194
|
+
var authDataMatch = key.match(/^_auth_data_([a-zA-Z0-9_]+)$/);
|
|
1195
|
+
if (authDataMatch && className === '_User') {
|
|
1196
|
+
var provider = authDataMatch[1];
|
|
1197
|
+
restObject['authData'] = restObject['authData'] || {};
|
|
1198
|
+
restObject['authData'][provider] = mongoObject[key];
|
|
1199
|
+
break;
|
|
1200
|
+
}
|
|
1201
|
+
if (key.indexOf('_p_') == 0) {
|
|
1202
|
+
var newKey = key.substring(3);
|
|
1203
|
+
if (!schema.fields[newKey]) {
|
|
1204
|
+
_logger.default.info('transform.js', 'Found a pointer column not in the schema, dropping it.', className, newKey);
|
|
1205
|
+
break;
|
|
1206
|
+
}
|
|
1207
|
+
if (schema.fields[newKey].type !== 'Pointer') {
|
|
1208
|
+
_logger.default.info('transform.js', 'Found a pointer in a non-pointer column, dropping it.', className, key);
|
|
1209
|
+
break;
|
|
1210
|
+
}
|
|
1211
|
+
if (mongoObject[key] === null) {
|
|
1212
|
+
break;
|
|
1213
|
+
}
|
|
1214
|
+
restObject[newKey] = transformPointerString(schema, newKey, mongoObject[key]);
|
|
1215
|
+
break;
|
|
1216
|
+
} else if (key[0] == '_' && key != '__type') {
|
|
1217
|
+
throw 'bad key in untransform: ' + key;
|
|
1218
|
+
} else {
|
|
1219
|
+
var value = mongoObject[key];
|
|
1220
|
+
if (schema.fields[key] && schema.fields[key].type === 'File' && FileCoder.isValidDatabaseObject(value)) {
|
|
1221
|
+
restObject[key] = FileCoder.databaseToJSON(value);
|
|
1222
|
+
break;
|
|
1223
|
+
}
|
|
1224
|
+
if (schema.fields[key] && schema.fields[key].type === 'GeoPoint' && GeoPointCoder.isValidDatabaseObject(value)) {
|
|
1225
|
+
restObject[key] = GeoPointCoder.databaseToJSON(value);
|
|
1226
|
+
break;
|
|
1227
|
+
}
|
|
1228
|
+
if (schema.fields[key] && schema.fields[key].type === 'Polygon' && PolygonCoder.isValidDatabaseObject(value)) {
|
|
1229
|
+
restObject[key] = PolygonCoder.databaseToJSON(value);
|
|
1230
|
+
break;
|
|
1231
|
+
}
|
|
1232
|
+
if (schema.fields[key] && schema.fields[key].type === 'Bytes' && BytesCoder.isValidDatabaseObject(value)) {
|
|
1233
|
+
restObject[key] = BytesCoder.databaseToJSON(value);
|
|
1234
|
+
break;
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
restObject[key] = nestedMongoObjectToNestedParseObject(mongoObject[key]);
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
const relationFieldNames = Object.keys(schema.fields).filter(fieldName => schema.fields[fieldName].type === 'Relation');
|
|
1241
|
+
const relationFields = {};
|
|
1242
|
+
relationFieldNames.forEach(relationFieldName => {
|
|
1243
|
+
relationFields[relationFieldName] = {
|
|
1244
|
+
__type: 'Relation',
|
|
1245
|
+
className: schema.fields[relationFieldName].targetClass
|
|
1246
|
+
};
|
|
1247
|
+
});
|
|
1248
|
+
return {
|
|
1249
|
+
...restObject,
|
|
1250
|
+
...relationFields
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
default:
|
|
1254
|
+
throw 'unknown js type';
|
|
1255
|
+
}
|
|
1256
|
+
};
|
|
1257
|
+
var DateCoder = {
|
|
1258
|
+
JSONToDatabase(json) {
|
|
1259
|
+
return new Date(json.iso);
|
|
1260
|
+
},
|
|
1261
|
+
isValidJSON(value) {
|
|
1262
|
+
return typeof value === 'object' && value !== null && value.__type === 'Date';
|
|
1263
|
+
}
|
|
1264
|
+
};
|
|
1265
|
+
var BytesCoder = {
|
|
1266
|
+
base64Pattern: new RegExp('^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$'),
|
|
1267
|
+
isBase64Value(object) {
|
|
1268
|
+
if (typeof object !== 'string') {
|
|
1269
|
+
return false;
|
|
1270
|
+
}
|
|
1271
|
+
return this.base64Pattern.test(object);
|
|
1272
|
+
},
|
|
1273
|
+
databaseToJSON(object) {
|
|
1274
|
+
let value;
|
|
1275
|
+
if (this.isBase64Value(object)) {
|
|
1276
|
+
value = object;
|
|
1277
|
+
} else {
|
|
1278
|
+
value = object.buffer.toString('base64');
|
|
1279
|
+
}
|
|
1280
|
+
return {
|
|
1281
|
+
__type: 'Bytes',
|
|
1282
|
+
base64: value
|
|
1283
|
+
};
|
|
1284
|
+
},
|
|
1285
|
+
isValidDatabaseObject(object) {
|
|
1286
|
+
return object instanceof mongodb.Binary || this.isBase64Value(object);
|
|
1287
|
+
},
|
|
1288
|
+
JSONToDatabase(json) {
|
|
1289
|
+
return new mongodb.Binary(Buffer.from(json.base64, 'base64'));
|
|
1290
|
+
},
|
|
1291
|
+
isValidJSON(value) {
|
|
1292
|
+
return typeof value === 'object' && value !== null && value.__type === 'Bytes';
|
|
1293
|
+
}
|
|
1294
|
+
};
|
|
1295
|
+
var GeoPointCoder = {
|
|
1296
|
+
databaseToJSON(object) {
|
|
1297
|
+
return {
|
|
1298
|
+
__type: 'GeoPoint',
|
|
1299
|
+
latitude: object[1],
|
|
1300
|
+
longitude: object[0]
|
|
1301
|
+
};
|
|
1302
|
+
},
|
|
1303
|
+
isValidDatabaseObject(object) {
|
|
1304
|
+
return Array.isArray(object) && object.length == 2;
|
|
1305
|
+
},
|
|
1306
|
+
JSONToDatabase(json) {
|
|
1307
|
+
return [json.longitude, json.latitude];
|
|
1308
|
+
},
|
|
1309
|
+
isValidJSON(value) {
|
|
1310
|
+
return typeof value === 'object' && value !== null && value.__type === 'GeoPoint';
|
|
1311
|
+
}
|
|
1312
|
+
};
|
|
1313
|
+
var PolygonCoder = {
|
|
1314
|
+
databaseToJSON(object) {
|
|
1315
|
+
// Convert lng/lat -> lat/lng
|
|
1316
|
+
const coords = object.coordinates[0].map(coord => {
|
|
1317
|
+
return [coord[1], coord[0]];
|
|
1318
|
+
});
|
|
1319
|
+
return {
|
|
1320
|
+
__type: 'Polygon',
|
|
1321
|
+
coordinates: coords
|
|
1322
|
+
};
|
|
1323
|
+
},
|
|
1324
|
+
isValidDatabaseObject(object) {
|
|
1325
|
+
const coords = object.coordinates[0];
|
|
1326
|
+
if (object.type !== 'Polygon' || !Array.isArray(coords)) {
|
|
1327
|
+
return false;
|
|
1328
|
+
}
|
|
1329
|
+
for (let i = 0; i < coords.length; i++) {
|
|
1330
|
+
const point = coords[i];
|
|
1331
|
+
if (!GeoPointCoder.isValidDatabaseObject(point)) {
|
|
1332
|
+
return false;
|
|
1333
|
+
}
|
|
1334
|
+
Parse.GeoPoint._validate(parseFloat(point[1]), parseFloat(point[0]));
|
|
1335
|
+
}
|
|
1336
|
+
return true;
|
|
1337
|
+
},
|
|
1338
|
+
JSONToDatabase(json) {
|
|
1339
|
+
let coords = json.coordinates;
|
|
1340
|
+
// Add first point to the end to close polygon
|
|
1341
|
+
if (coords[0][0] !== coords[coords.length - 1][0] || coords[0][1] !== coords[coords.length - 1][1]) {
|
|
1342
|
+
coords.push(coords[0]);
|
|
1343
|
+
}
|
|
1344
|
+
const unique = coords.filter((item, index, ar) => {
|
|
1345
|
+
let foundIndex = -1;
|
|
1346
|
+
for (let i = 0; i < ar.length; i += 1) {
|
|
1347
|
+
const pt = ar[i];
|
|
1348
|
+
if (pt[0] === item[0] && pt[1] === item[1]) {
|
|
1349
|
+
foundIndex = i;
|
|
1350
|
+
break;
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
return foundIndex === index;
|
|
1354
|
+
});
|
|
1355
|
+
if (unique.length < 3) {
|
|
1356
|
+
throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'GeoJSON: Loop must have at least 3 different vertices');
|
|
1357
|
+
}
|
|
1358
|
+
// Convert lat/long -> long/lat
|
|
1359
|
+
coords = coords.map(coord => {
|
|
1360
|
+
return [coord[1], coord[0]];
|
|
1361
|
+
});
|
|
1362
|
+
return {
|
|
1363
|
+
type: 'Polygon',
|
|
1364
|
+
coordinates: [coords]
|
|
1365
|
+
};
|
|
1366
|
+
},
|
|
1367
|
+
isValidJSON(value) {
|
|
1368
|
+
return typeof value === 'object' && value !== null && value.__type === 'Polygon';
|
|
1369
|
+
}
|
|
1370
|
+
};
|
|
1371
|
+
var FileCoder = {
|
|
1372
|
+
databaseToJSON(object) {
|
|
1373
|
+
return {
|
|
1374
|
+
__type: 'File',
|
|
1375
|
+
name: object
|
|
1376
|
+
};
|
|
1377
|
+
},
|
|
1378
|
+
isValidDatabaseObject(object) {
|
|
1379
|
+
return typeof object === 'string';
|
|
1380
|
+
},
|
|
1381
|
+
JSONToDatabase(json) {
|
|
1382
|
+
return json.name;
|
|
1383
|
+
},
|
|
1384
|
+
isValidJSON(value) {
|
|
1385
|
+
return typeof value === 'object' && value !== null && value.__type === 'File';
|
|
1386
|
+
}
|
|
1387
|
+
};
|
|
1388
|
+
module.exports = {
|
|
1389
|
+
transformKey,
|
|
1390
|
+
parseObjectToMongoObjectForCreate,
|
|
1391
|
+
transformUpdate,
|
|
1392
|
+
transformWhere,
|
|
1393
|
+
mongoObjectToParseObject,
|
|
1394
|
+
transformConstraint,
|
|
1395
|
+
transformPointerString
|
|
1396
|
+
};
|
|
1397
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbG9nZ2VyIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfbG9kYXNoIiwiZSIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwibW9uZ29kYiIsIlBhcnNlIiwiVXRpbHMiLCJ0cmFuc2Zvcm1LZXkiLCJjbGFzc05hbWUiLCJmaWVsZE5hbWUiLCJzY2hlbWEiLCJmaWVsZHMiLCJfX3R5cGUiLCJ0eXBlIiwidHJhbnNmb3JtS2V5VmFsdWVGb3JVcGRhdGUiLCJyZXN0S2V5IiwicmVzdFZhbHVlIiwicGFyc2VGb3JtYXRTY2hlbWEiLCJrZXkiLCJ0aW1lRmllbGQiLCJpbmNsdWRlcyIsInZhbHVlIiwicGFyc2VJbnQiLCJ0cmFuc2Zvcm1Ub3BMZXZlbEF0b20iLCJDYW5ub3RUcmFuc2Zvcm0iLCJEYXRlIiwiaW5kZXhPZiIsIkFycmF5IiwiaXNBcnJheSIsIm1hcCIsInRyYW5zZm9ybUludGVyaW9yVmFsdWUiLCJ0cmFuc2Zvcm1VcGRhdGVPcGVyYXRvciIsIm1hcFZhbHVlcyIsImlzUmVnZXgiLCJpc1JlZ0V4cCIsImlzU3RhcnRzV2l0aFJlZ2V4IiwibWF0Y2hlcyIsInRvU3RyaW5nIiwibWF0Y2giLCJpc0FsbFZhbHVlc1JlZ2V4T3JOb25lIiwidmFsdWVzIiwibGVuZ3RoIiwiZmlyc3RWYWx1ZXNJc1JlZ2V4IiwiaSIsImlzQW55VmFsdWVSZWdleCIsInNvbWUiLCJPYmplY3QiLCJrZXlzIiwiRXJyb3IiLCJJTlZBTElEX05FU1RFRF9LRVkiLCJ0cmFuc2Zvcm1JbnRlcmlvckF0b20iLCJpc0RhdGUiLCJ2YWx1ZUFzRGF0ZSIsInRyYW5zZm9ybVF1ZXJ5S2V5VmFsdWUiLCJjb3VudCIsInN1YlF1ZXJ5IiwidHJhbnNmb3JtV2hlcmUiLCJhdXRoRGF0YU1hdGNoIiwicHJvdmlkZXIiLCJzdWJGaWVsZCIsImV4cGVjdGVkVHlwZUlzQXJyYXkiLCJleHBlY3RlZFR5cGVJc1BvaW50ZXIiLCJmaWVsZCIsInRyYW5zZm9ybWVkQ29uc3RyYWludCIsInRyYW5zZm9ybUNvbnN0cmFpbnQiLCIkdGV4dCIsIiRlbGVtTWF0Y2giLCIkYWxsIiwidHJhbnNmb3JtUmVzIiwiSU5WQUxJRF9KU09OIiwicmVzdFdoZXJlIiwibW9uZ29XaGVyZSIsIm91dCIsInBhcnNlT2JqZWN0S2V5VmFsdWVUb01vbmdvT2JqZWN0S2V5VmFsdWUiLCJ0cmFuc2Zvcm1lZFZhbHVlIiwiY29lcmNlZFRvRGF0ZSIsIklOVkFMSURfS0VZX05BTUUiLCJwYXJzZU9iamVjdFRvTW9uZ29PYmplY3RGb3JDcmVhdGUiLCJyZXN0Q3JlYXRlIiwiYWRkTGVnYWN5QUNMIiwibW9uZ29DcmVhdGUiLCJ1bmRlZmluZWQiLCJjcmVhdGVkQXQiLCJfY3JlYXRlZF9hdCIsImlzbyIsInVwZGF0ZWRBdCIsIl91cGRhdGVkX2F0IiwidHJhbnNmb3JtVXBkYXRlIiwicmVzdFVwZGF0ZSIsIm1vbmdvVXBkYXRlIiwiYWNsIiwiX3JwZXJtIiwiX3dwZXJtIiwiX2FjbCIsIiRzZXQiLCJfX29wIiwiYXJnIiwicmVzdE9iamVjdCIsInJlc3RPYmplY3RDb3B5IiwiZm9yRWFjaCIsImVudHJ5IiwidyIsInIiLCJhdG9tIiwib2JqZWN0SWQiLCJEYXRlQ29kZXIiLCJpc1ZhbGlkSlNPTiIsIkpTT05Ub0RhdGFiYXNlIiwiQnl0ZXNDb2RlciIsIiRyZWdleCIsIlJlZ0V4cCIsInRhcmdldENsYXNzIiwiR2VvUG9pbnRDb2RlciIsIlBvbHlnb25Db2RlciIsIkZpbGVDb2RlciIsIklOVEVSTkFMX1NFUlZFUl9FUlJPUiIsImNvbnN0cmFpbnQiLCJxdWVyeUtleSIsImluQXJyYXkiLCJpc05lc3RlZEtleSIsInRyYW5zZm9ybUZ1bmN0aW9uIiwidHJhbnNmb3JtZXIiLCJyZXN1bHQiLCJKU09OIiwic3RyaW5naWZ5Iiwic29ydCIsInJldmVyc2UiLCJhbnN3ZXIiLCJ2YWwiLCIkcmVsYXRpdmVUaW1lIiwicGFyc2VyUmVzdWx0IiwicmVsYXRpdmVUaW1lVG9EYXRlIiwic3RhdHVzIiwibG9nIiwiaW5mbyIsImFyciIsIl8iLCJmbGF0TWFwIiwicyIsIiRuaW4iLCJzZWFyY2giLCIkc2VhcmNoIiwiJHRlcm0iLCIkbGFuZ3VhZ2UiLCIkY2FzZVNlbnNpdGl2ZSIsIiRkaWFjcml0aWNTZW5zaXRpdmUiLCJwb2ludCIsIiRnZW9XaXRoaW4iLCIkY2VudGVyU3BoZXJlIiwibG9uZ2l0dWRlIiwibGF0aXR1ZGUiLCIkbWF4RGlzdGFuY2UiLCJDT01NQU5EX1VOQVZBSUxBQkxFIiwiYm94IiwiJGJveCIsInBvbHlnb24iLCJjZW50ZXJTcGhlcmUiLCJwb2ludHMiLCJjb29yZGluYXRlcyIsIkdlb1BvaW50IiwiX3ZhbGlkYXRlIiwiJHBvbHlnb24iLCJkaXN0YW5jZSIsImlzTmFOIiwiJGdlb21ldHJ5IiwiYW1vdW50Iiwib2JqZWN0cyIsImZsYXR0ZW4iLCJ0b0FkZCIsIm1vbmdvT3AiLCJBZGQiLCJBZGRVbmlxdWUiLCIkZWFjaCIsInRvUmVtb3ZlIiwib2JqZWN0IiwiaXRlcmF0b3IiLCJuZXN0ZWRNb25nb09iamVjdFRvTmVzdGVkUGFyc2VPYmplY3QiLCJtb25nb09iamVjdCIsIl9lbmNvZGUiLCJMb25nIiwidG9OdW1iZXIiLCJEb3VibGUiLCJpc1ZhbGlkRGF0YWJhc2VPYmplY3QiLCJkYXRhYmFzZVRvSlNPTiIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsInRvSlNPTiIsInRyYW5zZm9ybVBvaW50ZXJTdHJpbmciLCJwb2ludGVyU3RyaW5nIiwib2JqRGF0YSIsInNwbGl0IiwibW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0IiwiX2hhc2hlZF9wYXNzd29yZCIsIndhcm4iLCJuZXdLZXkiLCJzdWJzdHJpbmciLCJyZWxhdGlvbkZpZWxkTmFtZXMiLCJmaWx0ZXIiLCJyZWxhdGlvbkZpZWxkcyIsInJlbGF0aW9uRmllbGROYW1lIiwianNvbiIsImJhc2U2NFBhdHRlcm4iLCJpc0Jhc2U2NFZhbHVlIiwidGVzdCIsImJ1ZmZlciIsImJhc2U2NCIsIkJpbmFyeSIsIkJ1ZmZlciIsImZyb20iLCJjb29yZHMiLCJjb29yZCIsInBhcnNlRmxvYXQiLCJwdXNoIiwidW5pcXVlIiwiaXRlbSIsImluZGV4IiwiYXIiLCJmb3VuZEluZGV4IiwicHQiLCJuYW1lIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9BZGFwdGVycy9TdG9yYWdlL01vbmdvL01vbmdvVHJhbnNmb3JtLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBsb2cgZnJvbSAnLi4vLi4vLi4vbG9nZ2VyJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG52YXIgbW9uZ29kYiA9IHJlcXVpcmUoJ21vbmdvZGInKTtcbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbmNvbnN0IFV0aWxzID0gcmVxdWlyZSgnLi4vLi4vLi4vVXRpbHMnKTtcblxuY29uc3QgdHJhbnNmb3JtS2V5ID0gKGNsYXNzTmFtZSwgZmllbGROYW1lLCBzY2hlbWEpID0+IHtcbiAgLy8gQ2hlY2sgaWYgdGhlIHNjaGVtYSBpcyBrbm93biBzaW5jZSBpdCdzIGEgYnVpbHQtaW4gZmllbGQuXG4gIHN3aXRjaCAoZmllbGROYW1lKSB7XG4gICAgY2FzZSAnb2JqZWN0SWQnOlxuICAgICAgcmV0dXJuICdfaWQnO1xuICAgIGNhc2UgJ2NyZWF0ZWRBdCc6XG4gICAgICByZXR1cm4gJ19jcmVhdGVkX2F0JztcbiAgICBjYXNlICd1cGRhdGVkQXQnOlxuICAgICAgcmV0dXJuICdfdXBkYXRlZF9hdCc7XG4gICAgY2FzZSAnc2Vzc2lvblRva2VuJzpcbiAgICAgIHJldHVybiAnX3Nlc3Npb25fdG9rZW4nO1xuICAgIGNhc2UgJ2xhc3RVc2VkJzpcbiAgICAgIHJldHVybiAnX2xhc3RfdXNlZCc7XG4gICAgY2FzZSAndGltZXNVc2VkJzpcbiAgICAgIHJldHVybiAndGltZXNfdXNlZCc7XG4gIH1cblxuICBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdICYmIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS5fX3R5cGUgPT0gJ1BvaW50ZXInKSB7XG4gICAgZmllbGROYW1lID0gJ19wXycgKyBmaWVsZE5hbWU7XG4gIH0gZWxzZSBpZiAoc2NoZW1hLmZpZWxkc1tmaWVsZE5hbWVdICYmIHNjaGVtYS5maWVsZHNbZmllbGROYW1lXS50eXBlID09ICdQb2ludGVyJykge1xuICAgIGZpZWxkTmFtZSA9ICdfcF8nICsgZmllbGROYW1lO1xuICB9XG5cbiAgcmV0dXJuIGZpZWxkTmFtZTtcbn07XG5cbmNvbnN0IHRyYW5zZm9ybUtleVZhbHVlRm9yVXBkYXRlID0gKGNsYXNzTmFtZSwgcmVzdEtleSwgcmVzdFZhbHVlLCBwYXJzZUZvcm1hdFNjaGVtYSkgPT4ge1xuICAvLyBDaGVjayBpZiB0aGUgc2NoZW1hIGlzIGtub3duIHNpbmNlIGl0J3MgYSBidWlsdC1pbiBmaWVsZC5cbiAgdmFyIGtleSA9IHJlc3RLZXk7XG4gIHZhciB0aW1lRmllbGQgPSBmYWxzZTtcbiAgc3dpdGNoIChrZXkpIHtcbiAgICBjYXNlICdvYmplY3RJZCc6XG4gICAgY2FzZSAnX2lkJzpcbiAgICAgIGlmIChbJ19HbG9iYWxDb25maWcnLCAnX0dyYXBoUUxDb25maWcnXS5pbmNsdWRlcyhjbGFzc05hbWUpKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAga2V5OiBrZXksXG4gICAgICAgICAgdmFsdWU6IHBhcnNlSW50KHJlc3RWYWx1ZSksXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBrZXkgPSAnX2lkJztcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2NyZWF0ZWRBdCc6XG4gICAgY2FzZSAnX2NyZWF0ZWRfYXQnOlxuICAgICAga2V5ID0gJ19jcmVhdGVkX2F0JztcbiAgICAgIHRpbWVGaWVsZCA9IHRydWU7XG4gICAgICBicmVhaztcbiAgICBjYXNlICd1cGRhdGVkQXQnOlxuICAgIGNhc2UgJ191cGRhdGVkX2F0JzpcbiAgICAgIGtleSA9ICdfdXBkYXRlZF9hdCc7XG4gICAgICB0aW1lRmllbGQgPSB0cnVlO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnc2Vzc2lvblRva2VuJzpcbiAgICBjYXNlICdfc2Vzc2lvbl90b2tlbic6XG4gICAgICBrZXkgPSAnX3Nlc3Npb25fdG9rZW4nO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnZXhwaXJlc0F0JzpcbiAgICBjYXNlICdfZXhwaXJlc0F0JzpcbiAgICAgIGtleSA9ICdleHBpcmVzQXQnO1xuICAgICAgdGltZUZpZWxkID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ19lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCc6XG4gICAgICBrZXkgPSAnX2VtYWlsX3ZlcmlmeV90b2tlbl9leHBpcmVzX2F0JztcbiAgICAgIHRpbWVGaWVsZCA9IHRydWU7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQnOlxuICAgICAga2V5ID0gJ19hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCc7XG4gICAgICB0aW1lRmllbGQgPSB0cnVlO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnX2ZhaWxlZF9sb2dpbl9jb3VudCc6XG4gICAgICBrZXkgPSAnX2ZhaWxlZF9sb2dpbl9jb3VudCc7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdfcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0JzpcbiAgICAgIGtleSA9ICdfcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0JztcbiAgICAgIHRpbWVGaWVsZCA9IHRydWU7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdfcGFzc3dvcmRfY2hhbmdlZF9hdCc6XG4gICAgICBrZXkgPSAnX3Bhc3N3b3JkX2NoYW5nZWRfYXQnO1xuICAgICAgdGltZUZpZWxkID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ19ycGVybSc6XG4gICAgY2FzZSAnX3dwZXJtJzpcbiAgICAgIHJldHVybiB7IGtleToga2V5LCB2YWx1ZTogcmVzdFZhbHVlIH07XG4gICAgY2FzZSAnbGFzdFVzZWQnOlxuICAgIGNhc2UgJ19sYXN0X3VzZWQnOlxuICAgICAga2V5ID0gJ19sYXN0X3VzZWQnO1xuICAgICAgdGltZUZpZWxkID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3RpbWVzVXNlZCc6XG4gICAgY2FzZSAndGltZXNfdXNlZCc6XG4gICAgICBrZXkgPSAndGltZXNfdXNlZCc7XG4gICAgICB0aW1lRmllbGQgPSB0cnVlO1xuICAgICAgYnJlYWs7XG4gIH1cblxuICBpZiAoXG4gICAgKHBhcnNlRm9ybWF0U2NoZW1hLmZpZWxkc1trZXldICYmIHBhcnNlRm9ybWF0U2NoZW1hLmZpZWxkc1trZXldLnR5cGUgPT09ICdQb2ludGVyJykgfHxcbiAgICAoIWtleS5pbmNsdWRlcygnLicpICYmXG4gICAgICAhcGFyc2VGb3JtYXRTY2hlbWEuZmllbGRzW2tleV0gJiZcbiAgICAgIHJlc3RWYWx1ZSAmJlxuICAgICAgcmVzdFZhbHVlLl9fdHlwZSA9PSAnUG9pbnRlcicpIC8vIERvIG5vdCB1c2UgdGhlIF9wXyBwcmVmaXggZm9yIHBvaW50ZXJzIGluc2lkZSBuZXN0ZWQgZG9jdW1lbnRzXG4gICkge1xuICAgIGtleSA9ICdfcF8nICsga2V5O1xuICB9XG5cbiAgLy8gSGFuZGxlIGF0b21pYyB2YWx1ZXNcbiAgdmFyIHZhbHVlID0gdHJhbnNmb3JtVG9wTGV2ZWxBdG9tKHJlc3RWYWx1ZSk7XG4gIGlmICh2YWx1ZSAhPT0gQ2Fubm90VHJhbnNmb3JtKSB7XG4gICAgaWYgKHRpbWVGaWVsZCAmJiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICB2YWx1ZSA9IG5ldyBEYXRlKHZhbHVlKTtcbiAgICB9XG4gICAgaWYgKHJlc3RLZXkuaW5kZXhPZignLicpID4gMCkge1xuICAgICAgcmV0dXJuIHsga2V5LCB2YWx1ZTogcmVzdFZhbHVlIH07XG4gICAgfVxuICAgIHJldHVybiB7IGtleSwgdmFsdWUgfTtcbiAgfVxuXG4gIC8vIEhhbmRsZSBhcnJheXNcbiAgaWYgKEFycmF5LmlzQXJyYXkocmVzdFZhbHVlKSkge1xuICAgIHZhbHVlID0gcmVzdFZhbHVlLm1hcCh0cmFuc2Zvcm1JbnRlcmlvclZhbHVlKTtcbiAgICByZXR1cm4geyBrZXksIHZhbHVlIH07XG4gIH1cblxuICAvLyBIYW5kbGUgdXBkYXRlIG9wZXJhdG9yc1xuICBpZiAodHlwZW9mIHJlc3RWYWx1ZSA9PT0gJ29iamVjdCcgJiYgJ19fb3AnIGluIHJlc3RWYWx1ZSkge1xuICAgIHJldHVybiB7IGtleSwgdmFsdWU6IHRyYW5zZm9ybVVwZGF0ZU9wZXJhdG9yKHJlc3RWYWx1ZSwgZmFsc2UpIH07XG4gIH1cblxuICAvLyBIYW5kbGUgbm9ybWFsIG9iamVjdHMgYnkgcmVjdXJzaW5nXG4gIHZhbHVlID0gbWFwVmFsdWVzKHJlc3RWYWx1ZSwgdHJhbnNmb3JtSW50ZXJpb3JWYWx1ZSk7XG4gIHJldHVybiB7IGtleSwgdmFsdWUgfTtcbn07XG5cbmNvbnN0IGlzUmVnZXggPSB2YWx1ZSA9PiB7XG4gIHJldHVybiB2YWx1ZSAmJiBVdGlscy5pc1JlZ0V4cCh2YWx1ZSk7XG59O1xuXG5jb25zdCBpc1N0YXJ0c1dpdGhSZWdleCA9IHZhbHVlID0+IHtcbiAgaWYgKCFpc1JlZ2V4KHZhbHVlKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGNvbnN0IG1hdGNoZXMgPSB2YWx1ZS50b1N0cmluZygpLm1hdGNoKC9cXC9cXF5cXFxcUS4qXFxcXEVcXC8vKTtcbiAgcmV0dXJuICEhbWF0Y2hlcztcbn07XG5cbmNvbnN0IGlzQWxsVmFsdWVzUmVnZXhPck5vbmUgPSB2YWx1ZXMgPT4ge1xuICBpZiAoIXZhbHVlcyB8fCAhQXJyYXkuaXNBcnJheSh2YWx1ZXMpIHx8IHZhbHVlcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGNvbnN0IGZpcnN0VmFsdWVzSXNSZWdleCA9IGlzU3RhcnRzV2l0aFJlZ2V4KHZhbHVlc1swXSk7XG4gIGlmICh2YWx1ZXMubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIGZpcnN0VmFsdWVzSXNSZWdleDtcbiAgfVxuXG4gIGZvciAobGV0IGkgPSAxLCBsZW5ndGggPSB2YWx1ZXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoZmlyc3RWYWx1ZXNJc1JlZ2V4ICE9PSBpc1N0YXJ0c1dpdGhSZWdleCh2YWx1ZXNbaV0pKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59O1xuXG5jb25zdCBpc0FueVZhbHVlUmVnZXggPSB2YWx1ZXMgPT4ge1xuICByZXR1cm4gdmFsdWVzLnNvbWUoZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIGlzUmVnZXgodmFsdWUpO1xuICB9KTtcbn07XG5cbmNvbnN0IHRyYW5zZm9ybUludGVyaW9yVmFsdWUgPSByZXN0VmFsdWUgPT4ge1xuICBpZiAoXG4gICAgcmVzdFZhbHVlICE9PSBudWxsICYmXG4gICAgdHlwZW9mIHJlc3RWYWx1ZSA9PT0gJ29iamVjdCcgJiZcbiAgICBPYmplY3Qua2V5cyhyZXN0VmFsdWUpLnNvbWUoa2V5ID0+IGtleS5pbmNsdWRlcygnJCcpIHx8IGtleS5pbmNsdWRlcygnLicpKVxuICApIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5JTlZBTElEX05FU1RFRF9LRVksXG4gICAgICBcIk5lc3RlZCBrZXlzIHNob3VsZCBub3QgY29udGFpbiB0aGUgJyQnIG9yICcuJyBjaGFyYWN0ZXJzXCJcbiAgICApO1xuICB9XG4gIC8vIEhhbmRsZSBhdG9taWMgdmFsdWVzXG4gIHZhciB2YWx1ZSA9IHRyYW5zZm9ybUludGVyaW9yQXRvbShyZXN0VmFsdWUpO1xuICBpZiAodmFsdWUgIT09IENhbm5vdFRyYW5zZm9ybSkge1xuICAgIGlmICh2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICBpZiAoVXRpbHMuaXNEYXRlKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgdmFsdWUgPSB2YWx1ZS5tYXAodHJhbnNmb3JtSW50ZXJpb3JWYWx1ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YWx1ZSA9IG1hcFZhbHVlcyh2YWx1ZSwgdHJhbnNmb3JtSW50ZXJpb3JWYWx1ZSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIC8vIEhhbmRsZSBhcnJheXNcbiAgaWYgKEFycmF5LmlzQXJyYXkocmVzdFZhbHVlKSkge1xuICAgIHJldHVybiByZXN0VmFsdWUubWFwKHRyYW5zZm9ybUludGVyaW9yVmFsdWUpO1xuICB9XG5cbiAgLy8gSGFuZGxlIHVwZGF0ZSBvcGVyYXRvcnNcbiAgaWYgKHR5cGVvZiByZXN0VmFsdWUgPT09ICdvYmplY3QnICYmICdfX29wJyBpbiByZXN0VmFsdWUpIHtcbiAgICByZXR1cm4gdHJhbnNmb3JtVXBkYXRlT3BlcmF0b3IocmVzdFZhbHVlLCB0cnVlKTtcbiAgfVxuXG4gIC8vIEhhbmRsZSBub3JtYWwgb2JqZWN0cyBieSByZWN1cnNpbmdcbiAgcmV0dXJuIG1hcFZhbHVlcyhyZXN0VmFsdWUsIHRyYW5zZm9ybUludGVyaW9yVmFsdWUpO1xufTtcblxuY29uc3QgdmFsdWVBc0RhdGUgPSB2YWx1ZSA9PiB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIG5ldyBEYXRlKHZhbHVlKTtcbiAgfSBlbHNlIGlmIChVdGlscy5pc0RhdGUodmFsdWUpKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn07XG5cbmZ1bmN0aW9uIHRyYW5zZm9ybVF1ZXJ5S2V5VmFsdWUoY2xhc3NOYW1lLCBrZXksIHZhbHVlLCBzY2hlbWEsIGNvdW50ID0gZmFsc2UpIHtcbiAgc3dpdGNoIChrZXkpIHtcbiAgICBjYXNlICdjcmVhdGVkQXQnOlxuICAgICAgaWYgKHZhbHVlQXNEYXRlKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4geyBrZXk6ICdfY3JlYXRlZF9hdCcsIHZhbHVlOiB2YWx1ZUFzRGF0ZSh2YWx1ZSkgfTtcbiAgICAgIH1cbiAgICAgIGtleSA9ICdfY3JlYXRlZF9hdCc7XG4gICAgICBicmVhaztcbiAgICBjYXNlICd1cGRhdGVkQXQnOlxuICAgICAgaWYgKHZhbHVlQXNEYXRlKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4geyBrZXk6ICdfdXBkYXRlZF9hdCcsIHZhbHVlOiB2YWx1ZUFzRGF0ZSh2YWx1ZSkgfTtcbiAgICAgIH1cbiAgICAgIGtleSA9ICdfdXBkYXRlZF9hdCc7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdleHBpcmVzQXQnOlxuICAgICAgaWYgKHZhbHVlQXNEYXRlKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4geyBrZXk6ICdleHBpcmVzQXQnLCB2YWx1ZTogdmFsdWVBc0RhdGUodmFsdWUpIH07XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdfZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQnOlxuICAgICAgaWYgKHZhbHVlQXNEYXRlKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGtleTogJ19lbWFpbF92ZXJpZnlfdG9rZW5fZXhwaXJlc19hdCcsXG4gICAgICAgICAgdmFsdWU6IHZhbHVlQXNEYXRlKHZhbHVlKSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ29iamVjdElkJzoge1xuICAgICAgaWYgKFsnX0dsb2JhbENvbmZpZycsICdfR3JhcGhRTENvbmZpZyddLmluY2x1ZGVzKGNsYXNzTmFtZSkpIHtcbiAgICAgICAgdmFsdWUgPSBwYXJzZUludCh2YWx1ZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4geyBrZXk6ICdfaWQnLCB2YWx1ZSB9O1xuICAgIH1cbiAgICBjYXNlICdfYWNjb3VudF9sb2Nrb3V0X2V4cGlyZXNfYXQnOlxuICAgICAgaWYgKHZhbHVlQXNEYXRlKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGtleTogJ19hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCcsXG4gICAgICAgICAgdmFsdWU6IHZhbHVlQXNEYXRlKHZhbHVlKSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ19mYWlsZWRfbG9naW5fY291bnQnOlxuICAgICAgcmV0dXJuIHsga2V5LCB2YWx1ZSB9O1xuICAgIGNhc2UgJ3Nlc3Npb25Ub2tlbic6XG4gICAgICByZXR1cm4geyBrZXk6ICdfc2Vzc2lvbl90b2tlbicsIHZhbHVlIH07XG4gICAgY2FzZSAnX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCc6XG4gICAgICBpZiAodmFsdWVBc0RhdGUodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAga2V5OiAnX3BlcmlzaGFibGVfdG9rZW5fZXhwaXJlc19hdCcsXG4gICAgICAgICAgdmFsdWU6IHZhbHVlQXNEYXRlKHZhbHVlKSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ19wYXNzd29yZF9jaGFuZ2VkX2F0JzpcbiAgICAgIGlmICh2YWx1ZUFzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHsga2V5OiAnX3Bhc3N3b3JkX2NoYW5nZWRfYXQnLCB2YWx1ZTogdmFsdWVBc0RhdGUodmFsdWUpIH07XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdfcnBlcm0nOlxuICAgIGNhc2UgJ193cGVybSc6XG4gICAgY2FzZSAnX3BlcmlzaGFibGVfdG9rZW4nOlxuICAgIGNhc2UgJ19lbWFpbF92ZXJpZnlfdG9rZW4nOlxuICAgICAgcmV0dXJuIHsga2V5LCB2YWx1ZSB9O1xuICAgIGNhc2UgJyRvcic6XG4gICAgY2FzZSAnJGFuZCc6XG4gICAgY2FzZSAnJG5vcic6XG4gICAgICByZXR1cm4ge1xuICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgdmFsdWU6IHZhbHVlLm1hcChzdWJRdWVyeSA9PiB0cmFuc2Zvcm1XaGVyZShjbGFzc05hbWUsIHN1YlF1ZXJ5LCBzY2hlbWEsIGNvdW50KSksXG4gICAgICB9O1xuICAgIGNhc2UgJ2xhc3RVc2VkJzpcbiAgICAgIGlmICh2YWx1ZUFzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHsga2V5OiAnX2xhc3RfdXNlZCcsIHZhbHVlOiB2YWx1ZUFzRGF0ZSh2YWx1ZSkgfTtcbiAgICAgIH1cbiAgICAgIGtleSA9ICdfbGFzdF91c2VkJztcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3RpbWVzVXNlZCc6XG4gICAgICByZXR1cm4geyBrZXk6ICd0aW1lc191c2VkJywgdmFsdWU6IHZhbHVlIH07XG4gICAgZGVmYXVsdDoge1xuICAgICAgLy8gT3RoZXIgYXV0aCBkYXRhXG4gICAgICBjb25zdCBhdXRoRGF0YU1hdGNoID0ga2V5Lm1hdGNoKC9eYXV0aERhdGFcXC4oW2EtekEtWjAtOV9dKykoXFwuKC4rKSk/JC8pO1xuICAgICAgaWYgKGF1dGhEYXRhTWF0Y2ggJiYgY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgICAgIGNvbnN0IHByb3ZpZGVyID0gYXV0aERhdGFNYXRjaFsxXTtcbiAgICAgICAgY29uc3Qgc3ViRmllbGQgPSBhdXRoRGF0YU1hdGNoWzNdO1xuICAgICAgICByZXR1cm4geyBrZXk6IGBfYXV0aF9kYXRhXyR7cHJvdmlkZXJ9JHtzdWJGaWVsZCA/IGAuJHtzdWJGaWVsZH1gIDogJyd9YCwgdmFsdWUgfTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjb25zdCBleHBlY3RlZFR5cGVJc0FycmF5ID0gc2NoZW1hICYmIHNjaGVtYS5maWVsZHNba2V5XSAmJiBzY2hlbWEuZmllbGRzW2tleV0udHlwZSA9PT0gJ0FycmF5JztcblxuICBjb25zdCBleHBlY3RlZFR5cGVJc1BvaW50ZXIgPVxuICAgIHNjaGVtYSAmJiBzY2hlbWEuZmllbGRzW2tleV0gJiYgc2NoZW1hLmZpZWxkc1trZXldLnR5cGUgPT09ICdQb2ludGVyJztcblxuICBjb25zdCBmaWVsZCA9IHNjaGVtYSAmJiBzY2hlbWEuZmllbGRzW2tleV07XG4gIGlmIChcbiAgICBleHBlY3RlZFR5cGVJc1BvaW50ZXIgfHxcbiAgICAoIXNjaGVtYSAmJiAha2V5LmluY2x1ZGVzKCcuJykgJiYgdmFsdWUgJiYgdmFsdWUuX190eXBlID09PSAnUG9pbnRlcicpXG4gICkge1xuICAgIGtleSA9ICdfcF8nICsga2V5O1xuICB9XG5cbiAgLy8gSGFuZGxlIHF1ZXJ5IGNvbnN0cmFpbnRzXG4gIGNvbnN0IHRyYW5zZm9ybWVkQ29uc3RyYWludCA9IHRyYW5zZm9ybUNvbnN0cmFpbnQodmFsdWUsIGZpZWxkLCBrZXksIGNvdW50KTtcbiAgaWYgKHRyYW5zZm9ybWVkQ29uc3RyYWludCAhPT0gQ2Fubm90VHJhbnNmb3JtKSB7XG4gICAgaWYgKHRyYW5zZm9ybWVkQ29uc3RyYWludC4kdGV4dCkge1xuICAgICAgcmV0dXJuIHsga2V5OiAnJHRleHQnLCB2YWx1ZTogdHJhbnNmb3JtZWRDb25zdHJhaW50LiR0ZXh0IH07XG4gICAgfVxuICAgIGlmICh0cmFuc2Zvcm1lZENvbnN0cmFpbnQuJGVsZW1NYXRjaCkge1xuICAgICAgcmV0dXJuIHsga2V5OiAnJG5vcicsIHZhbHVlOiBbeyBba2V5XTogdHJhbnNmb3JtZWRDb25zdHJhaW50IH1dIH07XG4gICAgfVxuICAgIHJldHVybiB7IGtleSwgdmFsdWU6IHRyYW5zZm9ybWVkQ29uc3RyYWludCB9O1xuICB9XG5cbiAgaWYgKGV4cGVjdGVkVHlwZUlzQXJyYXkgJiYgIUFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgcmV0dXJuIHsga2V5LCB2YWx1ZTogeyAkYWxsOiBbdHJhbnNmb3JtSW50ZXJpb3JBdG9tKHZhbHVlKV0gfSB9O1xuICB9XG5cbiAgLy8gSGFuZGxlIGF0b21pYyB2YWx1ZXNcbiAgY29uc3QgdHJhbnNmb3JtUmVzID0ga2V5LmluY2x1ZGVzKCcuJylcbiAgICA/IHRyYW5zZm9ybUludGVyaW9yQXRvbSh2YWx1ZSlcbiAgICA6IHRyYW5zZm9ybVRvcExldmVsQXRvbSh2YWx1ZSk7XG4gIGlmICh0cmFuc2Zvcm1SZXMgIT09IENhbm5vdFRyYW5zZm9ybSkge1xuICAgIHJldHVybiB7IGtleSwgdmFsdWU6IHRyYW5zZm9ybVJlcyB9O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgIGBZb3UgY2Fubm90IHVzZSAke3ZhbHVlfSBhcyBhIHF1ZXJ5IHBhcmFtZXRlci5gXG4gICAgKTtcbiAgfVxufVxuXG4vLyBNYWluIGV4cG9zZWQgbWV0aG9kIHRvIGhlbHAgcnVuIHF1ZXJpZXMuXG4vLyByZXN0V2hlcmUgaXMgdGhlIFwid2hlcmVcIiBjbGF1c2UgaW4gUkVTVCBBUEkgZm9ybS5cbi8vIFJldHVybnMgdGhlIG1vbmdvIGZvcm0gb2YgdGhlIHF1ZXJ5LlxuZnVuY3Rpb24gdHJhbnNmb3JtV2hlcmUoY2xhc3NOYW1lLCByZXN0V2hlcmUsIHNjaGVtYSwgY291bnQgPSBmYWxzZSkge1xuICBjb25zdCBtb25nb1doZXJlID0ge307XG4gIGZvciAoY29uc3QgcmVzdEtleSBpbiByZXN0V2hlcmUpIHtcbiAgICBjb25zdCBvdXQgPSB0cmFuc2Zvcm1RdWVyeUtleVZhbHVlKGNsYXNzTmFtZSwgcmVzdEtleSwgcmVzdFdoZXJlW3Jlc3RLZXldLCBzY2hlbWEsIGNvdW50KTtcbiAgICBtb25nb1doZXJlW291dC5rZXldID0gb3V0LnZhbHVlO1xuICB9XG4gIHJldHVybiBtb25nb1doZXJlO1xufVxuXG5jb25zdCBwYXJzZU9iamVjdEtleVZhbHVlVG9Nb25nb09iamVjdEtleVZhbHVlID0gKHJlc3RLZXksIHJlc3RWYWx1ZSwgc2NoZW1hKSA9PiB7XG4gIC8vIENoZWNrIGlmIHRoZSBzY2hlbWEgaXMga25vd24gc2luY2UgaXQncyBhIGJ1aWx0LWluIGZpZWxkLlxuICBsZXQgdHJhbnNmb3JtZWRWYWx1ZTtcbiAgbGV0IGNvZXJjZWRUb0RhdGU7XG4gIHN3aXRjaCAocmVzdEtleSkge1xuICAgIGNhc2UgJ29iamVjdElkJzpcbiAgICAgIHJldHVybiB7IGtleTogJ19pZCcsIHZhbHVlOiByZXN0VmFsdWUgfTtcbiAgICBjYXNlICdleHBpcmVzQXQnOlxuICAgICAgdHJhbnNmb3JtZWRWYWx1ZSA9IHRyYW5zZm9ybVRvcExldmVsQXRvbShyZXN0VmFsdWUpO1xuICAgICAgY29lcmNlZFRvRGF0ZSA9XG4gICAgICAgIHR5cGVvZiB0cmFuc2Zvcm1lZFZhbHVlID09PSAnc3RyaW5nJyA/IG5ldyBEYXRlKHRyYW5zZm9ybWVkVmFsdWUpIDogdHJhbnNmb3JtZWRWYWx1ZTtcbiAgICAgIHJldHVybiB7IGtleTogJ2V4cGlyZXNBdCcsIHZhbHVlOiBjb2VyY2VkVG9EYXRlIH07XG4gICAgY2FzZSAnX2VtYWlsX3ZlcmlmeV90b2tlbl9leHBpcmVzX2F0JzpcbiAgICAgIHRyYW5zZm9ybWVkVmFsdWUgPSB0cmFuc2Zvcm1Ub3BMZXZlbEF0b20ocmVzdFZhbHVlKTtcbiAgICAgIGNvZXJjZWRUb0RhdGUgPVxuICAgICAgICB0eXBlb2YgdHJhbnNmb3JtZWRWYWx1ZSA9PT0gJ3N0cmluZycgPyBuZXcgRGF0ZSh0cmFuc2Zvcm1lZFZhbHVlKSA6IHRyYW5zZm9ybWVkVmFsdWU7XG4gICAgICByZXR1cm4geyBrZXk6ICdfZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQnLCB2YWx1ZTogY29lcmNlZFRvRGF0ZSB9O1xuICAgIGNhc2UgJ19hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCc6XG4gICAgICB0cmFuc2Zvcm1lZFZhbHVlID0gdHJhbnNmb3JtVG9wTGV2ZWxBdG9tKHJlc3RWYWx1ZSk7XG4gICAgICBjb2VyY2VkVG9EYXRlID1cbiAgICAgICAgdHlwZW9mIHRyYW5zZm9ybWVkVmFsdWUgPT09ICdzdHJpbmcnID8gbmV3IERhdGUodHJhbnNmb3JtZWRWYWx1ZSkgOiB0cmFuc2Zvcm1lZFZhbHVlO1xuICAgICAgcmV0dXJuIHsga2V5OiAnX2FjY291bnRfbG9ja291dF9leHBpcmVzX2F0JywgdmFsdWU6IGNvZXJjZWRUb0RhdGUgfTtcbiAgICBjYXNlICdfcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0JzpcbiAgICAgIHRyYW5zZm9ybWVkVmFsdWUgPSB0cmFuc2Zvcm1Ub3BMZXZlbEF0b20ocmVzdFZhbHVlKTtcbiAgICAgIGNvZXJjZWRUb0RhdGUgPVxuICAgICAgICB0eXBlb2YgdHJhbnNmb3JtZWRWYWx1ZSA9PT0gJ3N0cmluZycgPyBuZXcgRGF0ZSh0cmFuc2Zvcm1lZFZhbHVlKSA6IHRyYW5zZm9ybWVkVmFsdWU7XG4gICAgICByZXR1cm4geyBrZXk6ICdfcGVyaXNoYWJsZV90b2tlbl9leHBpcmVzX2F0JywgdmFsdWU6IGNvZXJjZWRUb0RhdGUgfTtcbiAgICBjYXNlICdfcGFzc3dvcmRfY2hhbmdlZF9hdCc6XG4gICAgICB0cmFuc2Zvcm1lZFZhbHVlID0gdHJhbnNmb3JtVG9wTGV2ZWxBdG9tKHJlc3RWYWx1ZSk7XG4gICAgICBjb2VyY2VkVG9EYXRlID1cbiAgICAgICAgdHlwZW9mIHRyYW5zZm9ybWVkVmFsdWUgPT09ICdzdHJpbmcnID8gbmV3IERhdGUodHJhbnNmb3JtZWRWYWx1ZSkgOiB0cmFuc2Zvcm1lZFZhbHVlO1xuICAgICAgcmV0dXJuIHsga2V5OiAnX3Bhc3N3b3JkX2NoYW5nZWRfYXQnLCB2YWx1ZTogY29lcmNlZFRvRGF0ZSB9O1xuICAgIGNhc2UgJ19mYWlsZWRfbG9naW5fY291bnQnOlxuICAgIGNhc2UgJ19ycGVybSc6XG4gICAgY2FzZSAnX3dwZXJtJzpcbiAgICBjYXNlICdfZW1haWxfdmVyaWZ5X3Rva2VuJzpcbiAgICBjYXNlICdfaGFzaGVkX3Bhc3N3b3JkJzpcbiAgICBjYXNlICdfcGVyaXNoYWJsZV90b2tlbic6XG4gICAgICByZXR1cm4geyBrZXk6IHJlc3RLZXksIHZhbHVlOiByZXN0VmFsdWUgfTtcbiAgICBjYXNlICdzZXNzaW9uVG9rZW4nOlxuICAgICAgcmV0dXJuIHsga2V5OiAnX3Nlc3Npb25fdG9rZW4nLCB2YWx1ZTogcmVzdFZhbHVlIH07XG4gICAgZGVmYXVsdDpcbiAgICAgIC8vIEF1dGggZGF0YSBzaG91bGQgaGF2ZSBiZWVuIHRyYW5zZm9ybWVkIGFscmVhZHlcbiAgICAgIGlmIChyZXN0S2V5Lm1hdGNoKC9eYXV0aERhdGFcXC4oW2EtekEtWjAtOV9dKylcXC5pZCQvKSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9LRVlfTkFNRSwgJ2NhbiBvbmx5IHF1ZXJ5IG9uICcgKyByZXN0S2V5KTtcbiAgICAgIH1cbiAgICAgIC8vIFRydXN0IHRoYXQgdGhlIGF1dGggZGF0YSBoYXMgYmVlbiB0cmFuc2Zvcm1lZCBhbmQgc2F2ZSBpdCBkaXJlY3RseVxuICAgICAgaWYgKHJlc3RLZXkubWF0Y2goL15fYXV0aF9kYXRhX1thLXpBLVowLTlfXSskLykpIHtcbiAgICAgICAgcmV0dXJuIHsga2V5OiByZXN0S2V5LCB2YWx1ZTogcmVzdFZhbHVlIH07XG4gICAgICB9XG4gIH1cbiAgLy9za2lwIHN0cmFpZ2h0IHRvIHRyYW5zZm9ybVRvcExldmVsQXRvbSBmb3IgQnl0ZXMsIHRoZXkgZG9uJ3Qgc2hvdyB1cCBpbiB0aGUgc2NoZW1hIGZvciBzb21lIHJlYXNvblxuICBpZiAocmVzdFZhbHVlICYmIHJlc3RWYWx1ZS5fX3R5cGUgIT09ICdCeXRlcycpIHtcbiAgICAvL05vdGU6IFdlIG1heSBub3Qga25vdyB0aGUgdHlwZSBvZiBhIGZpZWxkIGhlcmUsIGFzIHRoZSB1c2VyIGNvdWxkIGJlIHNhdmluZyAobnVsbCkgdG8gYSBmaWVsZFxuICAgIC8vVGhhdCBuZXZlciBleGlzdGVkIGJlZm9yZSwgbWVhbmluZyB3ZSBjYW4ndCBpbmZlciB0aGUgdHlwZS5cbiAgICBpZiAoXG4gICAgICAoc2NoZW1hLmZpZWxkc1tyZXN0S2V5XSAmJiBzY2hlbWEuZmllbGRzW3Jlc3RLZXldLnR5cGUgPT0gJ1BvaW50ZXInKSB8fFxuICAgICAgcmVzdFZhbHVlLl9fdHlwZSA9PSAnUG9pbnRlcidcbiAgICApIHtcbiAgICAgIHJlc3RLZXkgPSAnX3BfJyArIHJlc3RLZXk7XG4gICAgfVxuICB9XG5cbiAgLy8gSGFuZGxlIGF0b21pYyB2YWx1ZXNcbiAgdmFyIHZhbHVlID0gdHJhbnNmb3JtVG9wTGV2ZWxBdG9tKHJlc3RWYWx1ZSk7XG4gIGlmICh2YWx1ZSAhPT0gQ2Fubm90VHJhbnNmb3JtKSB7XG4gICAgcmV0dXJuIHsga2V5OiByZXN0S2V5LCB2YWx1ZTogdmFsdWUgfTtcbiAgfVxuXG4gIC8vIEFDTHMgYXJlIGhhbmRsZWQgYmVmb3JlIHRoaXMgbWV0aG9kIGlzIGNhbGxlZFxuICAvLyBJZiBhbiBBQ0wga2V5IHN0aWxsIGV4aXN0cyBoZXJlLCBzb21ldGhpbmcgaXMgd3JvbmcuXG4gIGlmIChyZXN0S2V5ID09PSAnQUNMJykge1xuICAgIHRocm93ICdUaGVyZSB3YXMgYSBwcm9ibGVtIHRyYW5zZm9ybWluZyBhbiBBQ0wuJztcbiAgfVxuXG4gIC8vIEhhbmRsZSBhcnJheXNcbiAgaWYgKEFycmF5LmlzQXJyYXkocmVzdFZhbHVlKSkge1xuICAgIHZhbHVlID0gcmVzdFZhbHVlLm1hcCh0cmFuc2Zvcm1JbnRlcmlvclZhbHVlKTtcbiAgICByZXR1cm4geyBrZXk6IHJlc3RLZXksIHZhbHVlOiB2YWx1ZSB9O1xuICB9XG5cbiAgLy8gSGFuZGxlIG5vcm1hbCBvYmplY3RzIGJ5IHJlY3Vyc2luZ1xuICBpZiAoT2JqZWN0LmtleXMocmVzdFZhbHVlKS5zb21lKGtleSA9PiBrZXkuaW5jbHVkZXMoJyQnKSB8fCBrZXkuaW5jbHVkZXMoJy4nKSkpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICBQYXJzZS5FcnJvci5JTlZBTElEX05FU1RFRF9LRVksXG4gICAgICBcIk5lc3RlZCBrZXlzIHNob3VsZCBub3QgY29udGFpbiB0aGUgJyQnIG9yICcuJyBjaGFyYWN0ZXJzXCJcbiAgICApO1xuICB9XG4gIHZhbHVlID0gbWFwVmFsdWVzKHJlc3RWYWx1ZSwgdHJhbnNmb3JtSW50ZXJpb3JWYWx1ZSk7XG5cbiAgcmV0dXJuIHsga2V5OiByZXN0S2V5LCB2YWx1ZSB9O1xufTtcblxuY29uc3QgcGFyc2VPYmplY3RUb01vbmdvT2JqZWN0Rm9yQ3JlYXRlID0gKGNsYXNzTmFtZSwgcmVzdENyZWF0ZSwgc2NoZW1hKSA9PiB7XG4gIHJlc3RDcmVhdGUgPSBhZGRMZWdhY3lBQ0wocmVzdENyZWF0ZSk7XG4gIGNvbnN0IG1vbmdvQ3JlYXRlID0ge307XG4gIGZvciAoY29uc3QgcmVzdEtleSBpbiByZXN0Q3JlYXRlKSB7XG4gICAgaWYgKHJlc3RDcmVhdGVbcmVzdEtleV0gJiYgcmVzdENyZWF0ZVtyZXN0S2V5XS5fX3R5cGUgPT09ICdSZWxhdGlvbicpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCB7IGtleSwgdmFsdWUgfSA9IHBhcnNlT2JqZWN0S2V5VmFsdWVUb01vbmdvT2JqZWN0S2V5VmFsdWUoXG4gICAgICByZXN0S2V5LFxuICAgICAgcmVzdENyZWF0ZVtyZXN0S2V5XSxcbiAgICAgIHNjaGVtYVxuICAgICk7XG4gICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIG1vbmdvQ3JlYXRlW2tleV0gPSB2YWx1ZTtcbiAgICB9XG4gIH1cblxuICAvLyBVc2UgdGhlIGxlZ2FjeSBtb25nbyBmb3JtYXQgZm9yIGNyZWF0ZWRBdCBhbmQgdXBkYXRlZEF0XG4gIGlmIChtb25nb0NyZWF0ZS5jcmVhdGVkQXQpIHtcbiAgICBtb25nb0NyZWF0ZS5fY3JlYXRlZF9hdCA9IG5ldyBEYXRlKG1vbmdvQ3JlYXRlLmNyZWF0ZWRBdC5pc28gfHwgbW9uZ29DcmVhdGUuY3JlYXRlZEF0KTtcbiAgICBkZWxldGUgbW9uZ29DcmVhdGUuY3JlYXRlZEF0O1xuICB9XG4gIGlmIChtb25nb0NyZWF0ZS51cGRhdGVkQXQpIHtcbiAgICBtb25nb0NyZWF0ZS5fdXBkYXRlZF9hdCA9IG5ldyBEYXRlKG1vbmdvQ3JlYXRlLnVwZGF0ZWRBdC5pc28gfHwgbW9uZ29DcmVhdGUudXBkYXRlZEF0KTtcbiAgICBkZWxldGUgbW9uZ29DcmVhdGUudXBkYXRlZEF0O1xuICB9XG5cbiAgcmV0dXJuIG1vbmdvQ3JlYXRlO1xufTtcblxuLy8gTWFpbiBleHBvc2VkIG1ldGhvZCB0byBoZWxwIHVwZGF0ZSBvbGQgb2JqZWN0cy5cbmNvbnN0IHRyYW5zZm9ybVVwZGF0ZSA9IChjbGFzc05hbWUsIHJlc3RVcGRhdGUsIHBhcnNlRm9ybWF0U2NoZW1hKSA9PiB7XG4gIGNvbnN0IG1vbmdvVXBkYXRlID0ge307XG4gIGNvbnN0IGFjbCA9IGFkZExlZ2FjeUFDTChyZXN0VXBkYXRlKTtcbiAgaWYgKGFjbC5fcnBlcm0gfHwgYWNsLl93cGVybSB8fCBhY2wuX2FjbCkge1xuICAgIG1vbmdvVXBkYXRlLiRzZXQgPSB7fTtcbiAgICBpZiAoYWNsLl9ycGVybSkge1xuICAgICAgbW9uZ29VcGRhdGUuJHNldC5fcnBlcm0gPSBhY2wuX3JwZXJtO1xuICAgIH1cbiAgICBpZiAoYWNsLl93cGVybSkge1xuICAgICAgbW9uZ29VcGRhdGUuJHNldC5fd3Blcm0gPSBhY2wuX3dwZXJtO1xuICAgIH1cbiAgICBpZiAoYWNsLl9hY2wpIHtcbiAgICAgIG1vbmdvVXBkYXRlLiRzZXQuX2FjbCA9IGFjbC5fYWNsO1xuICAgIH1cbiAgfVxuICBmb3IgKHZhciByZXN0S2V5IGluIHJlc3RVcGRhdGUpIHtcbiAgICBpZiAocmVzdFVwZGF0ZVtyZXN0S2V5XSAmJiByZXN0VXBkYXRlW3Jlc3RLZXldLl9fdHlwZSA9PT0gJ1JlbGF0aW9uJykge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIHZhciBvdXQgPSB0cmFuc2Zvcm1LZXlWYWx1ZUZvclVwZGF0ZShcbiAgICAgIGNsYXNzTmFtZSxcbiAgICAgIHJlc3RLZXksXG4gICAgICByZXN0VXBkYXRlW3Jlc3RLZXldLFxuICAgICAgcGFyc2VGb3JtYXRTY2hlbWFcbiAgICApO1xuXG4gICAgLy8gSWYgdGhlIG91dHB1dCB2YWx1ZSBpcyBhbiBvYmplY3Qgd2l0aCBhbnkgJCBrZXlzLCBpdCdzIGFuXG4gICAgLy8gb3BlcmF0b3IgdGhhdCBuZWVkcyB0byBiZSBsaWZ0ZWQgb250byB0aGUgdG9wIGxldmVsIHVwZGF0ZVxuICAgIC8vIG9iamVjdC5cbiAgICBpZiAodHlwZW9mIG91dC52YWx1ZSA9PT0gJ29iamVjdCcgJiYgb3V0LnZhbHVlICE9PSBudWxsICYmIG91dC52YWx1ZS5fX29wKSB7XG4gICAgICBtb25nb1VwZGF0ZVtvdXQudmFsdWUuX19vcF0gPSBtb25nb1VwZGF0ZVtvdXQudmFsdWUuX19vcF0gfHwge307XG4gICAgICBtb25nb1VwZGF0ZVtvdXQudmFsdWUuX19vcF1bb3V0LmtleV0gPSBvdXQudmFsdWUuYXJnO1xuICAgIH0gZWxzZSB7XG4gICAgICBtb25nb1VwZGF0ZVsnJHNldCddID0gbW9uZ29VcGRhdGVbJyRzZXQnXSB8fCB7fTtcbiAgICAgIG1vbmdvVXBkYXRlWyckc2V0J11bb3V0LmtleV0gPSBvdXQudmFsdWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG1vbmdvVXBkYXRlO1xufTtcblxuLy8gQWRkIHRoZSBsZWdhY3kgX2FjbCBmb3JtYXQuXG5jb25zdCBhZGRMZWdhY3lBQ0wgPSByZXN0T2JqZWN0ID0+IHtcbiAgY29uc3QgcmVzdE9iamVjdENvcHkgPSB7IC4uLnJlc3RPYmplY3QgfTtcbiAgY29uc3QgX2FjbCA9IHt9O1xuXG4gIGlmIChyZXN0T2JqZWN0Ll93cGVybSkge1xuICAgIHJlc3RPYmplY3QuX3dwZXJtLmZvckVhY2goZW50cnkgPT4ge1xuICAgICAgX2FjbFtlbnRyeV0gPSB7IHc6IHRydWUgfTtcbiAgICB9KTtcbiAgICByZXN0T2JqZWN0Q29weS5fYWNsID0gX2FjbDtcbiAgfVxuXG4gIGlmIChyZXN0T2JqZWN0Ll9ycGVybSkge1xuICAgIHJlc3RPYmplY3QuX3JwZXJtLmZvckVhY2goZW50cnkgPT4ge1xuICAgICAgaWYgKCEoZW50cnkgaW4gX2FjbCkpIHtcbiAgICAgICAgX2FjbFtlbnRyeV0gPSB7IHI6IHRydWUgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIF9hY2xbZW50cnldLnIgPSB0cnVlO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJlc3RPYmplY3RDb3B5Ll9hY2wgPSBfYWNsO1xuICB9XG5cbiAgcmV0dXJuIHJlc3RPYmplY3RDb3B5O1xufTtcblxuLy8gQSBzZW50aW5lbCB2YWx1ZSB0aGF0IGhlbHBlciB0cmFuc2Zvcm1hdGlvbnMgcmV0dXJuIHdoZW4gdGhleVxuLy8gY2Fubm90IHBlcmZvcm0gYSB0cmFuc2Zvcm1hdGlvblxuZnVuY3Rpb24gQ2Fubm90VHJhbnNmb3JtKCkge31cblxuY29uc3QgdHJhbnNmb3JtSW50ZXJpb3JBdG9tID0gYXRvbSA9PiB7XG4gIC8vIFRPRE86IGNoZWNrIHZhbGlkaXR5IGhhcmRlciBmb3IgdGhlIF9fdHlwZS1kZWZpbmVkIHR5cGVzXG4gIGlmICh0eXBlb2YgYXRvbSA9PT0gJ29iamVjdCcgJiYgYXRvbSAmJiAhVXRpbHMuaXNEYXRlKGF0b20pICYmIGF0b20uX190eXBlID09PSAnUG9pbnRlcicpIHtcbiAgICByZXR1cm4ge1xuICAgICAgX190eXBlOiAnUG9pbnRlcicsXG4gICAgICBjbGFzc05hbWU6IGF0b20uY2xhc3NOYW1lLFxuICAgICAgb2JqZWN0SWQ6IGF0b20ub2JqZWN0SWQsXG4gICAgfTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgYXRvbSA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgYXRvbSA9PT0gJ3N5bWJvbCcpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCBgY2Fubm90IHRyYW5zZm9ybSB2YWx1ZTogJHthdG9tfWApO1xuICB9IGVsc2UgaWYgKERhdGVDb2Rlci5pc1ZhbGlkSlNPTihhdG9tKSkge1xuICAgIHJldHVybiBEYXRlQ29kZXIuSlNPTlRvRGF0YWJhc2UoYXRvbSk7XG4gIH0gZWxzZSBpZiAoQnl0ZXNDb2Rlci5pc1ZhbGlkSlNPTihhdG9tKSkge1xuICAgIHJldHVybiBCeXRlc0NvZGVyLkpTT05Ub0RhdGFiYXNlKGF0b20pO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBhdG9tID09PSAnb2JqZWN0JyAmJiBhdG9tICYmIGF0b20uJHJlZ2V4ICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cChhdG9tLiRyZWdleCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGF0b207XG4gIH1cbn07XG5cbi8vIEhlbHBlciBmdW5jdGlvbiB0byB0cmFuc2Zvcm0gYW4gYXRvbSBmcm9tIFJFU1QgZm9ybWF0IHRvIE1vbmdvIGZvcm1hdC5cbi8vIEFuIGF0b20gaXMgYW55dGhpbmcgdGhhdCBjYW4ndCBjb250YWluIG90aGVyIGV4cHJlc3Npb25zLiBTbyBpdFxuLy8gaW5jbHVkZXMgdGhpbmdzIHdoZXJlIG9iamVjdHMgYXJlIHVzZWQgdG8gcmVwcmVzZW50IG90aGVyXG4vLyBkYXRhdHlwZXMsIGxpa2UgcG9pbnRlcnMgYW5kIGRhdGVzLCBidXQgaXQgZG9lcyBub3QgaW5jbHVkZSBvYmplY3RzXG4vLyBvciBhcnJheXMgd2l0aCBnZW5lcmljIHN0dWZmIGluc2lkZS5cbi8vIFJhaXNlcyBhbiBlcnJvciBpZiB0aGlzIGNhbm5vdCBwb3NzaWJseSBiZSB2YWxpZCBSRVNUIGZvcm1hdC5cbi8vIFJldHVybnMgQ2Fubm90VHJhbnNmb3JtIGlmIGl0J3MganVzdCBub3QgYW4gYXRvbVxuZnVuY3Rpb24gdHJhbnNmb3JtVG9wTGV2ZWxBdG9tKGF0b20sIGZpZWxkKSB7XG4gIHN3aXRjaCAodHlwZW9mIGF0b20pIHtcbiAgICBjYXNlICdudW1iZXInOlxuICAgIGNhc2UgJ2Jvb2xlYW4nOlxuICAgIGNhc2UgJ3VuZGVmaW5lZCc6XG4gICAgICByZXR1cm4gYXRvbTtcbiAgICBjYXNlICdzdHJpbmcnOlxuICAgICAgaWYgKGZpZWxkICYmIGZpZWxkLnR5cGUgPT09ICdQb2ludGVyJykge1xuICAgICAgICByZXR1cm4gYCR7ZmllbGQudGFyZ2V0Q2xhc3N9JCR7YXRvbX1gO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGF0b207XG4gICAgY2FzZSAnc3ltYm9sJzpcbiAgICBjYXNlICdmdW5jdGlvbic6XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCBgY2Fubm90IHRyYW5zZm9ybSB2YWx1ZTogJHthdG9tfWApO1xuICAgIGNhc2UgJ29iamVjdCc6XG4gICAgICBpZiAoVXRpbHMuaXNEYXRlKGF0b20pKSB7XG4gICAgICAgIC8vIFRlY2huaWNhbGx5IGRhdGVzIGFyZSBub3QgcmVzdCBmb3JtYXQsIGJ1dCwgaXQgc2VlbXMgcHJldHR5XG4gICAgICAgIC8vIGNsZWFyIHdoYXQgdGhleSBzaG91bGQgYmUgdHJhbnNmb3JtZWQgdG8sIHNvIGxldCdzIGp1c3QgZG8gaXQuXG4gICAgICAgIHJldHVybiBhdG9tO1xuICAgICAgfVxuXG4gICAgICBpZiAoYXRvbSA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gYXRvbTtcbiAgICAgIH1cblxuICAgICAgLy8gVE9ETzogY2hlY2sgdmFsaWRpdHkgaGFyZGVyIGZvciB0aGUgX190eXBlLWRlZmluZWQgdHlwZXNcbiAgICAgIGlmIChhdG9tLl9fdHlwZSA9PSAnUG9pbnRlcicpIHtcbiAgICAgICAgcmV0dXJuIGAke2F0b20uY2xhc3NOYW1lfSQke2F0b20ub2JqZWN0SWR9YDtcbiAgICAgIH1cbiAgICAgIGlmIChEYXRlQ29kZXIuaXNWYWxpZEpTT04oYXRvbSkpIHtcbiAgICAgICAgcmV0dXJuIERhdGVDb2Rlci5KU09OVG9EYXRhYmFzZShhdG9tKTtcbiAgICAgIH1cbiAgICAgIGlmIChCeXRlc0NvZGVyLmlzVmFsaWRKU09OKGF0b20pKSB7XG4gICAgICAgIHJldHVybiBCeXRlc0NvZGVyLkpTT05Ub0RhdGFiYXNlKGF0b20pO1xuICAgICAgfVxuICAgICAgaWYgKEdlb1BvaW50Q29kZXIuaXNWYWxpZEpTT04oYXRvbSkpIHtcbiAgICAgICAgcmV0dXJuIEdlb1BvaW50Q29kZXIuSlNPTlRvRGF0YWJhc2UoYXRvbSk7XG4gICAgICB9XG4gICAgICBpZiAoUG9seWdvbkNvZGVyLmlzVmFsaWRKU09OKGF0b20pKSB7XG4gICAgICAgIHJldHVybiBQb2x5Z29uQ29kZXIuSlNPTlRvRGF0YWJhc2UoYXRvbSk7XG4gICAgICB9XG4gICAgICBpZiAoRmlsZUNvZGVyLmlzVmFsaWRKU09OKGF0b20pKSB7XG4gICAgICAgIHJldHVybiBGaWxlQ29kZXIuSlNPTlRvRGF0YWJhc2UoYXRvbSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gQ2Fubm90VHJhbnNmb3JtO1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIC8vIEkgZG9uJ3QgdGhpbmsgdHlwZW9mIGNhbiBldmVyIGxldCB1cyBnZXQgaGVyZVxuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1IsXG4gICAgICAgIGByZWFsbHkgZGlkIG5vdCBleHBlY3QgdmFsdWU6ICR7YXRvbX1gXG4gICAgICApO1xuICB9XG59XG5cbi8vIFRyYW5zZm9ybXMgYSBxdWVyeSBjb25zdHJhaW50IGZyb20gUkVTVCBBUEkgZm9ybWF0IHRvIE1vbmdvIGZvcm1hdC5cbi8vIEEgY29uc3RyYWludCBpcyBzb21ldGhpbmcgd2l0aCBmaWVsZHMgbGlrZSAkbHQuXG4vLyBJZiBpdCBpcyBub3QgYSB2YWxpZCBjb25zdHJhaW50IGJ1dCBpdCBjb3VsZCBiZSBhIHZhbGlkIHNvbWV0aGluZ1xuLy8gZWxzZSwgcmV0dXJuIENhbm5vdFRyYW5zZm9ybS5cbi8vIGluQXJyYXkgaXMgd2hldGhlciB0aGlzIGlzIGFuIGFycmF5IGZpZWxkLlxuZnVuY3Rpb24gdHJhbnNmb3JtQ29uc3RyYWludChjb25zdHJhaW50LCBmaWVsZCwgcXVlcnlLZXksIGNvdW50ID0gZmFsc2UpIHtcbiAgY29uc3QgaW5BcnJheSA9IGZpZWxkICYmIGZpZWxkLnR5cGUgJiYgZmllbGQudHlwZSA9PT0gJ0FycmF5JztcbiAgLy8gQ2hlY2sgd2V0aGVyIHRoZSBnaXZlbiBrZXkgaGFzIGAuYFxuICBjb25zdCBpc05lc3RlZEtleSA9IHF1ZXJ5S2V5LmluZGV4T2YoJy4nKSA+IC0xO1xuICBpZiAodHlwZW9mIGNvbnN0cmFpbnQgIT09ICdvYmplY3QnIHx8ICFjb25zdHJhaW50KSB7XG4gICAgcmV0dXJuIENhbm5vdFRyYW5zZm9ybTtcbiAgfVxuICAvLyBGb3IgaW5BcnJheSBvciBuZXN0ZWQga2V5LCB3ZSBuZWVkIHRvIHRyYW5zZm9ybSB0aGUgaW50ZXJpb3IgYXRvbVxuICBjb25zdCB0cmFuc2Zvcm1GdW5jdGlvbiA9IChpbkFycmF5IHx8IGlzTmVzdGVkS2V5KSA/IHRyYW5zZm9ybUludGVyaW9yQXRvbSA6IHRyYW5zZm9ybVRvcExldmVsQXRvbTtcbiAgY29uc3QgdHJhbnNmb3JtZXIgPSBhdG9tID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSB0cmFuc2Zvcm1GdW5jdGlvbihhdG9tLCBmaWVsZCk7XG4gICAgaWYgKHJlc3VsdCA9PT0gQ2Fubm90VHJhbnNmb3JtKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCBgYmFkIGF0b206ICR7SlNPTi5zdHJpbmdpZnkoYXRvbSl9YCk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG4gIC8vIGtleXMgaXMgdGhlIGNvbnN0cmFpbnRzIGluIHJldmVyc2UgYWxwaGFiZXRpY2FsIG9yZGVyLlxuICAvLyBUaGlzIGlzIGEgaGFjayBzbyB0aGF0OlxuICAvLyAgICRyZWdleCBpcyBoYW5kbGVkIGJlZm9yZSAkb3B0aW9uc1xuICAvLyAgICRuZWFyU3BoZXJlIGlzIGhhbmRsZWQgYmVmb3JlICRtYXhEaXN0YW5jZVxuICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGNvbnN0cmFpbnQpLnNvcnQoKS5yZXZlcnNlKCk7XG4gIHZhciBhbnN3ZXIgPSB7fTtcbiAgZm9yICh2YXIga2V5IG9mIGtleXMpIHtcbiAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgY2FzZSAnJGx0JzpcbiAgICAgIGNhc2UgJyRsdGUnOlxuICAgICAgY2FzZSAnJGd0JzpcbiAgICAgIGNhc2UgJyRndGUnOlxuICAgICAgY2FzZSAnJGV4aXN0cyc6XG4gICAgICBjYXNlICckbmUnOlxuICAgICAgY2FzZSAnJGVxJzoge1xuICAgICAgICBjb25zdCB2YWwgPSBjb25zdHJhaW50W2tleV07XG4gICAgICAgIGlmICh2YWwgJiYgdHlwZW9mIHZhbCA9PT0gJ29iamVjdCcgJiYgdmFsLiRyZWxhdGl2ZVRpbWUpIHtcbiAgICAgICAgICBpZiAoZmllbGQgJiYgZmllbGQudHlwZSAhPT0gJ0RhdGUnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICAgJyRyZWxhdGl2ZVRpbWUgY2FuIG9ubHkgYmUgdXNlZCB3aXRoIERhdGUgZmllbGQnXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgICAgICBjYXNlICckZXhpc3RzJzpcbiAgICAgICAgICAgIGNhc2UgJyRuZSc6XG4gICAgICAgICAgICBjYXNlICckZXEnOlxuICAgICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgICAgICckcmVsYXRpdmVUaW1lIGNhbiBvbmx5IGJlIHVzZWQgd2l0aCB0aGUgJGx0LCAkbHRlLCAkZ3QsIGFuZCAkZ3RlIG9wZXJhdG9ycydcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBwYXJzZXJSZXN1bHQgPSBVdGlscy5yZWxhdGl2ZVRpbWVUb0RhdGUodmFsLiRyZWxhdGl2ZVRpbWUpO1xuICAgICAgICAgIGlmIChwYXJzZXJSZXN1bHQuc3RhdHVzID09PSAnc3VjY2VzcycpIHtcbiAgICAgICAgICAgIGFuc3dlcltrZXldID0gcGFyc2VyUmVzdWx0LnJlc3VsdDtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGxvZy5pbmZvKCdFcnJvciB3aGlsZSBwYXJzaW5nIHJlbGF0aXZlIGRhdGUnLCBwYXJzZXJSZXN1bHQpO1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgIGBiYWQgJHJlbGF0aXZlVGltZSAoJHtrZXl9KSB2YWx1ZS4gJHtwYXJzZXJSZXN1bHQuaW5mb31gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGFuc3dlcltrZXldID0gdHJhbnNmb3JtZXIodmFsKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIGNhc2UgJyRpbic6XG4gICAgICBjYXNlICckbmluJzoge1xuICAgICAgICBjb25zdCBhcnIgPSBjb25zdHJhaW50W2tleV07XG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheShhcnIpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgJ2JhZCAnICsga2V5ICsgJyB2YWx1ZScpO1xuICAgICAgICB9XG4gICAgICAgIGFuc3dlcltrZXldID0gXy5mbGF0TWFwKGFyciwgdmFsdWUgPT4ge1xuICAgICAgICAgIHJldHVybiAoYXRvbSA9PiB7XG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShhdG9tKSkge1xuICAgICAgICAgICAgICByZXR1cm4gdmFsdWUubWFwKHRyYW5zZm9ybWVyKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiB0cmFuc2Zvcm1lcihhdG9tKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KSh2YWx1ZSk7XG4gICAgICAgIH0pO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJyRhbGwnOiB7XG4gICAgICAgIGNvbnN0IGFyciA9IGNvbnN0cmFpbnRba2V5XTtcbiAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGFycikpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnYmFkICcgKyBrZXkgKyAnIHZhbHVlJyk7XG4gICAgICAgIH1cbiAgICAgICAgYW5zd2VyW2tleV0gPSBhcnIubWFwKHRyYW5zZm9ybUludGVyaW9yQXRvbSk7XG5cbiAgICAgICAgY29uc3QgdmFsdWVzID0gYW5zd2VyW2tleV07XG4gICAgICAgIGlmIChpc0FueVZhbHVlUmVnZXgodmFsdWVzKSAmJiAhaXNBbGxWYWx1ZXNSZWdleE9yTm9uZSh2YWx1ZXMpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgJ0FsbCAkYWxsIHZhbHVlcyBtdXN0IGJlIG9mIHJlZ2V4IHR5cGUgb3Igbm9uZTogJyArIHZhbHVlc1xuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJyRyZWdleCc6XG4gICAgICAgIHZhciBzID0gY29uc3RyYWludFtrZXldO1xuICAgICAgICBpZiAodHlwZW9mIHMgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgJ2JhZCByZWdleDogJyArIHMpO1xuICAgICAgICB9XG4gICAgICAgIGFuc3dlcltrZXldID0gcztcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJyRjb250YWluZWRCeSc6IHtcbiAgICAgICAgY29uc3QgYXJyID0gY29uc3RyYWludFtrZXldO1xuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoYXJyKSkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sIGBiYWQgJGNvbnRhaW5lZEJ5OiBzaG91bGQgYmUgYW4gYXJyYXlgKTtcbiAgICAgICAgfVxuICAgICAgICBhbnN3ZXIuJGVsZW1NYXRjaCA9IHtcbiAgICAgICAgICAkbmluOiBhcnIubWFwKHRyYW5zZm9ybWVyKSxcbiAgICAgICAgfTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICckb3B0aW9ucyc6XG4gICAgICAgIGFuc3dlcltrZXldID0gY29uc3RyYWludFtrZXldO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnJHRleHQnOiB7XG4gICAgICAgIGNvbnN0IHNlYXJjaCA9IGNvbnN0cmFpbnRba2V5XS4kc2VhcmNoO1xuICAgICAgICBpZiAodHlwZW9mIHNlYXJjaCAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCBgYmFkICR0ZXh0OiAkc2VhcmNoLCBzaG91bGQgYmUgb2JqZWN0YCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFzZWFyY2guJHRlcm0gfHwgdHlwZW9mIHNlYXJjaC4kdGVybSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCBgYmFkICR0ZXh0OiAkdGVybSwgc2hvdWxkIGJlIHN0cmluZ2ApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFuc3dlcltrZXldID0ge1xuICAgICAgICAgICAgJHNlYXJjaDogc2VhcmNoLiR0ZXJtLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNlYXJjaC4kbGFuZ3VhZ2UgJiYgdHlwZW9mIHNlYXJjaC4kbGFuZ3VhZ2UgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgYGJhZCAkdGV4dDogJGxhbmd1YWdlLCBzaG91bGQgYmUgc3RyaW5nYCk7XG4gICAgICAgIH0gZWxzZSBpZiAoc2VhcmNoLiRsYW5ndWFnZSkge1xuICAgICAgICAgIGFuc3dlcltrZXldLiRsYW5ndWFnZSA9IHNlYXJjaC4kbGFuZ3VhZ2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNlYXJjaC4kY2FzZVNlbnNpdGl2ZSAmJiB0eXBlb2Ygc2VhcmNoLiRjYXNlU2Vuc2l0aXZlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICBgYmFkICR0ZXh0OiAkY2FzZVNlbnNpdGl2ZSwgc2hvdWxkIGJlIGJvb2xlYW5gXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmIChzZWFyY2guJGNhc2VTZW5zaXRpdmUpIHtcbiAgICAgICAgICBhbnN3ZXJba2V5XS4kY2FzZVNlbnNpdGl2ZSA9IHNlYXJjaC4kY2FzZVNlbnNpdGl2ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2VhcmNoLiRkaWFjcml0aWNTZW5zaXRpdmUgJiYgdHlwZW9mIHNlYXJjaC4kZGlhY3JpdGljU2Vuc2l0aXZlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICBgYmFkICR0ZXh0OiAkZGlhY3JpdGljU2Vuc2l0aXZlLCBzaG91bGQgYmUgYm9vbGVhbmBcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2UgaWYgKHNlYXJjaC4kZGlhY3JpdGljU2Vuc2l0aXZlKSB7XG4gICAgICAgICAgYW5zd2VyW2tleV0uJGRpYWNyaXRpY1NlbnNpdGl2ZSA9IHNlYXJjaC4kZGlhY3JpdGljU2Vuc2l0aXZlO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAnJG5lYXJTcGhlcmUnOiB7XG4gICAgICAgIGNvbnN0IHBvaW50ID0gY29uc3RyYWludFtrZXldO1xuICAgICAgICBpZiAoY291bnQpIHtcbiAgICAgICAgICBhbnN3ZXIuJGdlb1dpdGhpbiA9IHtcbiAgICAgICAgICAgICRjZW50ZXJTcGhlcmU6IFtbcG9pbnQubG9uZ2l0dWRlLCBwb2ludC5sYXRpdHVkZV0sIGNvbnN0cmFpbnQuJG1heERpc3RhbmNlXSxcbiAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFuc3dlcltrZXldID0gW3BvaW50LmxvbmdpdHVkZSwgcG9pbnQubGF0aXR1ZGVdO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAnJG1heERpc3RhbmNlJzoge1xuICAgICAgICBpZiAoY291bnQpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBhbnN3ZXJba2V5XSA9IGNvbnN0cmFpbnRba2V5XTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICAvLyBUaGUgU0RLcyBkb24ndCBzZWVtIHRvIHVzZSB0aGVzZSBidXQgdGhleSBhcmUgZG9jdW1lbnRlZCBpbiB0aGVcbiAgICAgIC8vIFJFU1QgQVBJIGRvY3MuXG4gICAgICBjYXNlICckbWF4RGlzdGFuY2VJblJhZGlhbnMnOlxuICAgICAgICBhbnN3ZXJbJyRtYXhEaXN0YW5jZSddID0gY29uc3RyYWludFtrZXldO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJyRtYXhEaXN0YW5jZUluTWlsZXMnOlxuICAgICAgICBhbnN3ZXJbJyRtYXhEaXN0YW5jZSddID0gY29uc3RyYWludFtrZXldIC8gMzk1OTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICckbWF4RGlzdGFuY2VJbktpbG9tZXRlcnMnOlxuICAgICAgICBhbnN3ZXJbJyRtYXhEaXN0YW5jZSddID0gY29uc3RyYWludFtrZXldIC8gNjM3MTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJyRzZWxlY3QnOlxuICAgICAgY2FzZSAnJGRvbnRTZWxlY3QnOlxuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgUGFyc2UuRXJyb3IuQ09NTUFORF9VTkFWQUlMQUJMRSxcbiAgICAgICAgICAndGhlICcgKyBrZXkgKyAnIGNvbnN0cmFpbnQgaXMgbm90IHN1cHBvcnRlZCB5ZXQnXG4gICAgICAgICk7XG5cbiAgICAgIGNhc2UgJyR3aXRoaW4nOlxuICAgICAgICB2YXIgYm94ID0gY29uc3RyYWludFtrZXldWyckYm94J107XG4gICAgICAgIGlmICghYm94IHx8IGJveC5sZW5ndGggIT0gMikge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sICdtYWxmb3JtYXR0ZWQgJHdpdGhpbiBhcmcnKTtcbiAgICAgICAgfVxuICAgICAgICBhbnN3ZXJba2V5XSA9IHtcbiAgICAgICAgICAkYm94OiBbXG4gICAgICAgICAgICBbYm94WzBdLmxvbmdpdHVkZSwgYm94WzBdLmxhdGl0dWRlXSxcbiAgICAgICAgICAgIFtib3hbMV0ubG9uZ2l0dWRlLCBib3hbMV0ubGF0aXR1ZGVdLFxuICAgICAgICAgIF0sXG4gICAgICAgIH07XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICckZ2VvV2l0aGluJzoge1xuICAgICAgICBjb25zdCBwb2x5Z29uID0gY29uc3RyYWludFtrZXldWyckcG9seWdvbiddO1xuICAgICAgICBjb25zdCBjZW50ZXJTcGhlcmUgPSBjb25zdHJhaW50W2tleV1bJyRjZW50ZXJTcGhlcmUnXTtcbiAgICAgICAgaWYgKHBvbHlnb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGxldCBwb2ludHM7XG4gICAgICAgICAgaWYgKHR5cGVvZiBwb2x5Z29uID09PSAnb2JqZWN0JyAmJiBwb2x5Z29uLl9fdHlwZSA9PT0gJ1BvbHlnb24nKSB7XG4gICAgICAgICAgICBpZiAoIXBvbHlnb24uY29vcmRpbmF0ZXMgfHwgcG9seWdvbi5jb29yZGluYXRlcy5sZW5ndGggPCAzKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAgICAgJ2JhZCAkZ2VvV2l0aGluIHZhbHVlOyBQb2x5Z29uLmNvb3JkaW5hdGVzIHNob3VsZCBjb250YWluIGF0IGxlYXN0IDMgbG9uL2xhdCBwYWlycydcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBvaW50cyA9IHBvbHlnb24uY29vcmRpbmF0ZXM7XG4gICAgICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KHBvbHlnb24pKSB7XG4gICAgICAgICAgICBpZiAocG9seWdvbi5sZW5ndGggPCAzKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAgICAgJ2JhZCAkZ2VvV2l0aGluIHZhbHVlOyAkcG9seWdvbiBzaG91bGQgY29udGFpbiBhdCBsZWFzdCAzIEdlb1BvaW50cydcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBvaW50cyA9IHBvbHlnb247XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgICBcImJhZCAkZ2VvV2l0aGluIHZhbHVlOyAkcG9seWdvbiBzaG91bGQgYmUgUG9seWdvbiBvYmplY3Qgb3IgQXJyYXkgb2YgUGFyc2UuR2VvUG9pbnQnc1wiXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBwb2ludHMgPSBwb2ludHMubWFwKHBvaW50ID0+IHtcbiAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHBvaW50KSAmJiBwb2ludC5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICAgICAgUGFyc2UuR2VvUG9pbnQuX3ZhbGlkYXRlKHBvaW50WzFdLCBwb2ludFswXSk7XG4gICAgICAgICAgICAgIHJldHVybiBwb2ludDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghR2VvUG9pbnRDb2Rlci5pc1ZhbGlkSlNPTihwb2ludCkpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVkFMSURfSlNPTiwgJ2JhZCAkZ2VvV2l0aGluIHZhbHVlJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBQYXJzZS5HZW9Qb2ludC5fdmFsaWRhdGUocG9pbnQubGF0aXR1ZGUsIHBvaW50LmxvbmdpdHVkZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gW3BvaW50LmxvbmdpdHVkZSwgcG9pbnQubGF0aXR1ZGVdO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGFuc3dlcltrZXldID0ge1xuICAgICAgICAgICAgJHBvbHlnb246IHBvaW50cyxcbiAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2UgaWYgKGNlbnRlclNwaGVyZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGNlbnRlclNwaGVyZSkgfHwgY2VudGVyU3BoZXJlLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgICAgICAgUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLFxuICAgICAgICAgICAgICAnYmFkICRnZW9XaXRoaW4gdmFsdWU7ICRjZW50ZXJTcGhlcmUgc2hvdWxkIGJlIGFuIGFycmF5IG9mIFBhcnNlLkdlb1BvaW50IGFuZCBkaXN0YW5jZSdcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIEdldCBwb2ludCwgY29udmVydCB0byBnZW8gcG9pbnQgaWYgbmVjZXNzYXJ5IGFuZCB2YWxpZGF0ZVxuICAgICAgICAgIGxldCBwb2ludCA9IGNlbnRlclNwaGVyZVswXTtcbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShwb2ludCkgJiYgcG9pbnQubGVuZ3RoID09PSAyKSB7XG4gICAgICAgICAgICBwb2ludCA9IG5ldyBQYXJzZS5HZW9Qb2ludChwb2ludFsxXSwgcG9pbnRbMF0pO1xuICAgICAgICAgIH0gZWxzZSBpZiAoIUdlb1BvaW50Q29kZXIuaXNWYWxpZEpTT04ocG9pbnQpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLklOVkFMSURfSlNPTixcbiAgICAgICAgICAgICAgJ2JhZCAkZ2VvV2l0aGluIHZhbHVlOyAkY2VudGVyU3BoZXJlIGdlbyBwb2ludCBpbnZhbGlkJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgUGFyc2UuR2VvUG9pbnQuX3ZhbGlkYXRlKHBvaW50LmxhdGl0dWRlLCBwb2ludC5sb25naXR1ZGUpO1xuICAgICAgICAgIC8vIEdldCBkaXN0YW5jZSBhbmQgdmFsaWRhdGVcbiAgICAgICAgICBjb25zdCBkaXN0YW5jZSA9IGNlbnRlclNwaGVyZVsxXTtcbiAgICAgICAgICBpZiAoaXNOYU4oZGlzdGFuY2UpIHx8IGRpc3RhbmNlIDwgMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAgICdiYWQgJGdlb1dpdGhpbiB2YWx1ZTsgJGNlbnRlclNwaGVyZSBkaXN0YW5jZSBpbnZhbGlkJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYW5zd2VyW2tleV0gPSB7XG4gICAgICAgICAgICAkY2VudGVyU3BoZXJlOiBbW3BvaW50LmxvbmdpdHVkZSwgcG9pbnQubGF0aXR1ZGVdLCBkaXN0YW5jZV0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJyRnZW9JbnRlcnNlY3RzJzoge1xuICAgICAgICBjb25zdCBwb2ludCA9IGNvbnN0cmFpbnRba2V5XVsnJHBvaW50J107XG4gICAgICAgIGlmICghR2VvUG9pbnRDb2Rlci5pc1ZhbGlkSlNPTihwb2ludCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICBQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sXG4gICAgICAgICAgICAnYmFkICRnZW9JbnRlcnNlY3QgdmFsdWU7ICRwb2ludCBzaG91bGQgYmUgR2VvUG9pbnQnXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBQYXJzZS5HZW9Qb2ludC5fdmFsaWRhdGUocG9pbnQubGF0aXR1ZGUsIHBvaW50LmxvbmdpdHVkZSk7XG4gICAgICAgIH1cbiAgICAgICAgYW5zd2VyW2tleV0gPSB7XG4gICAgICAgICAgJGdlb21ldHJ5OiB7XG4gICAgICAgICAgICB0eXBlOiAnUG9pbnQnLFxuICAgICAgICAgICAgY29vcmRpbmF0ZXM6IFtwb2ludC5sb25naXR1ZGUsIHBvaW50LmxhdGl0dWRlXSxcbiAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChrZXkubWF0Y2goL15cXCQrLykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnYmFkIGNvbnN0cmFpbnQ6ICcgKyBrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBDYW5ub3RUcmFuc2Zvcm07XG4gICAgfVxuICB9XG4gIHJldHVybiBhbnN3ZXI7XG59XG5cbi8vIFRyYW5zZm9ybXMgYW4gdXBkYXRlIG9wZXJhdG9yIGZyb20gUkVTVCBmb3JtYXQgdG8gbW9uZ28gZm9ybWF0LlxuLy8gVG8gYmUgdHJhbnNmb3JtZWQsIHRoZSBpbnB1dCBzaG91bGQgaGF2ZSBhbiBfX29wIGZpZWxkLlxuLy8gSWYgZmxhdHRlbiBpcyB0cnVlLCB0aGlzIHdpbGwgZmxhdHRlbiBvcGVyYXRvcnMgdG8gdGhlaXIgc3RhdGljXG4vLyBkYXRhIGZvcm1hdC4gRm9yIGV4YW1wbGUsIGFuIGluY3JlbWVudCBvZiAyIHdvdWxkIHNpbXBseSBiZWNvbWUgYVxuLy8gMi5cbi8vIFRoZSBvdXRwdXQgZm9yIGEgbm9uLWZsYXR0ZW5lZCBvcGVyYXRvciBpcyBhIGhhc2ggd2l0aCBfX29wIGJlaW5nXG4vLyB0aGUgbW9uZ28gb3AsIGFuZCBhcmcgYmVpbmcgdGhlIGFyZ3VtZW50LlxuLy8gVGhlIG91dHB1dCBmb3IgYSBmbGF0dGVuZWQgb3BlcmF0b3IgaXMganVzdCBhIHZhbHVlLlxuLy8gUmV0dXJucyB1bmRlZmluZWQgaWYgdGhpcyBzaG91bGQgYmUgYSBuby1vcC5cblxuZnVuY3Rpb24gdHJhbnNmb3JtVXBkYXRlT3BlcmF0b3IoeyBfX29wLCBhbW91bnQsIG9iamVjdHMgfSwgZmxhdHRlbikge1xuICBzd2l0Y2ggKF9fb3ApIHtcbiAgICBjYXNlICdEZWxldGUnOlxuICAgICAgaWYgKGZsYXR0ZW4pIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB7IF9fb3A6ICckdW5zZXQnLCBhcmc6ICcnIH07XG4gICAgICB9XG5cbiAgICBjYXNlICdJbmNyZW1lbnQnOlxuICAgICAgaWYgKHR5cGVvZiBhbW91bnQgIT09ICdudW1iZXInKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sICdpbmNyZW1lbnRpbmcgbXVzdCBwcm92aWRlIGEgbnVtYmVyJyk7XG4gICAgICB9XG4gICAgICBpZiAoZmxhdHRlbikge1xuICAgICAgICByZXR1cm4gYW1vdW50O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHsgX19vcDogJyRpbmMnLCBhcmc6IGFtb3VudCB9O1xuICAgICAgfVxuXG4gICAgY2FzZSAnU2V0T25JbnNlcnQnOlxuICAgICAgaWYgKGZsYXR0ZW4pIHtcbiAgICAgICAgcmV0dXJuIGFtb3VudDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB7IF9fb3A6ICckc2V0T25JbnNlcnQnLCBhcmc6IGFtb3VudCB9O1xuICAgICAgfVxuXG4gICAgY2FzZSAnQWRkJzpcbiAgICBjYXNlICdBZGRVbmlxdWUnOlxuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdHMpKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlZBTElEX0pTT04sICdvYmplY3RzIHRvIGFkZCBtdXN0IGJlIGFuIGFycmF5Jyk7XG4gICAgICB9XG4gICAgICB2YXIgdG9BZGQgPSBvYmplY3RzLm1hcCh0cmFuc2Zvcm1JbnRlcmlvckF0b20pO1xuICAgICAgaWYgKGZsYXR0ZW4pIHtcbiAgICAgICAgcmV0dXJuIHRvQWRkO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIG1vbmdvT3AgPSB7XG4gICAgICAgICAgQWRkOiAnJHB1c2gnLFxuICAgICAgICAgIEFkZFVuaXF1ZTogJyRhZGRUb1NldCcsXG4gICAgICAgIH1bX19vcF07XG4gICAgICAgIHJldHVybiB7IF9fb3A6IG1vbmdvT3AsIGFyZzogeyAkZWFjaDogdG9BZGQgfSB9O1xuICAgICAgfVxuXG4gICAgY2FzZSAnUmVtb3ZlJzpcbiAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3RzKSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5WQUxJRF9KU09OLCAnb2JqZWN0cyB0byByZW1vdmUgbXVzdCBiZSBhbiBhcnJheScpO1xuICAgICAgfVxuICAgICAgdmFyIHRvUmVtb3ZlID0gb2JqZWN0cy5tYXAodHJhbnNmb3JtSW50ZXJpb3JBdG9tKTtcbiAgICAgIGlmIChmbGF0dGVuKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB7IF9fb3A6ICckcHVsbEFsbCcsIGFyZzogdG9SZW1vdmUgfTtcbiAgICAgIH1cblxuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLkNPTU1BTkRfVU5BVkFJTEFCTEUsXG4gICAgICAgIGBUaGUgJHtfX29wfSBvcGVyYXRvciBpcyBub3Qgc3VwcG9ydGVkIHlldC5gXG4gICAgICApO1xuICB9XG59XG5mdW5jdGlvbiBtYXBWYWx1ZXMob2JqZWN0LCBpdGVyYXRvcikge1xuICBjb25zdCByZXN1bHQgPSB7fTtcbiAgT2JqZWN0LmtleXMob2JqZWN0KS5mb3JFYWNoKGtleSA9PiB7XG4gICAgcmVzdWx0W2tleV0gPSBpdGVyYXRvcihvYmplY3Rba2V5XSk7XG4gIH0pO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5jb25zdCBuZXN0ZWRNb25nb09iamVjdFRvTmVzdGVkUGFyc2VPYmplY3QgPSBtb25nb09iamVjdCA9PiB7XG4gIHN3aXRjaCAodHlwZW9mIG1vbmdvT2JqZWN0KSB7XG4gICAgY2FzZSAnc3RyaW5nJzpcbiAgICBjYXNlICdudW1iZXInOlxuICAgIGNhc2UgJ2Jvb2xlYW4nOlxuICAgIGNhc2UgJ3VuZGVmaW5lZCc6XG4gICAgICByZXR1cm4gbW9uZ29PYmplY3Q7XG4gICAgY2FzZSAnc3ltYm9sJzpcbiAgICBjYXNlICdmdW5jdGlvbic6XG4gICAgICB0aHJvdyAnYmFkIHZhbHVlIGluIG5lc3RlZE1vbmdvT2JqZWN0VG9OZXN0ZWRQYXJzZU9iamVjdCc7XG4gICAgY2FzZSAnb2JqZWN0JzpcbiAgICAgIGlmIChtb25nb09iamVjdCA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIGlmIChBcnJheS5pc0FycmF5KG1vbmdvT2JqZWN0KSkge1xuICAgICAgICByZXR1cm4gbW9uZ29PYmplY3QubWFwKG5lc3RlZE1vbmdvT2JqZWN0VG9OZXN0ZWRQYXJzZU9iamVjdCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChVdGlscy5pc0RhdGUobW9uZ29PYmplY3QpKSB7XG4gICAgICAgIHJldHVybiBQYXJzZS5fZW5jb2RlKG1vbmdvT2JqZWN0KTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1vbmdvT2JqZWN0IGluc3RhbmNlb2YgbW9uZ29kYi5Mb25nKSB7XG4gICAgICAgIHJldHVybiBtb25nb09iamVjdC50b051bWJlcigpO1xuICAgICAgfVxuXG4gICAgICBpZiAobW9uZ29PYmplY3QgaW5zdGFuY2VvZiBtb25nb2RiLkRvdWJsZSkge1xuICAgICAgICByZXR1cm4gbW9uZ29PYmplY3QudmFsdWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChCeXRlc0NvZGVyLmlzVmFsaWREYXRhYmFzZU9iamVjdChtb25nb09iamVjdCkpIHtcbiAgICAgICAgcmV0dXJuIEJ5dGVzQ29kZXIuZGF0YWJhc2VUb0pTT04obW9uZ29PYmplY3QpO1xuICAgICAgfVxuXG4gICAgICBpZiAoXG4gICAgICAgIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb25nb09iamVjdCwgJ19fdHlwZScpICYmXG4gICAgICAgIG1vbmdvT2JqZWN0Ll9fdHlwZSA9PSAnRGF0ZScgJiZcbiAgICAgICAgVXRpbHMuaXNEYXRlKG1vbmdvT2JqZWN0LmlzbylcbiAgICAgICkge1xuICAgICAgICBtb25nb09iamVjdC5pc28gPSBtb25nb09iamVjdC5pc28udG9KU09OKCk7XG4gICAgICAgIHJldHVybiBtb25nb09iamVjdDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG1hcFZhbHVlcyhtb25nb09iamVjdCwgbmVzdGVkTW9uZ29PYmplY3RUb05lc3RlZFBhcnNlT2JqZWN0KTtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgJ3Vua25vd24ganMgdHlwZSc7XG4gIH1cbn07XG5cbmNvbnN0IHRyYW5zZm9ybVBvaW50ZXJTdHJpbmcgPSAoc2NoZW1hLCBmaWVsZCwgcG9pbnRlclN0cmluZykgPT4ge1xuICBjb25zdCBvYmpEYXRhID0gcG9pbnRlclN0cmluZy5zcGxpdCgnJCcpO1xuICBpZiAob2JqRGF0YVswXSAhPT0gc2NoZW1hLmZpZWxkc1tmaWVsZF0udGFyZ2V0Q2xhc3MpIHtcbiAgICB0aHJvdyAncG9pbnRlciB0byBpbmNvcnJlY3QgY2xhc3NOYW1lJztcbiAgfVxuICByZXR1cm4ge1xuICAgIF9fdHlwZTogJ1BvaW50ZXInLFxuICAgIGNsYXNzTmFtZTogb2JqRGF0YVswXSxcbiAgICBvYmplY3RJZDogb2JqRGF0YVsxXSxcbiAgfTtcbn07XG5cbi8vIENvbnZlcnRzIGZyb20gYSBtb25nby1mb3JtYXQgb2JqZWN0IHRvIGEgUkVTVC1mb3JtYXQgb2JqZWN0LlxuLy8gRG9lcyBub3Qgc3RyaXAgb3V0IGFueXRoaW5nIGJhc2VkIG9uIGEgbGFjayBvZiBhdXRoZW50aWNhdGlvbi5cbmNvbnN0IG1vbmdvT2JqZWN0VG9QYXJzZU9iamVjdCA9IChjbGFzc05hbWUsIG1vbmdvT2JqZWN0LCBzY2hlbWEpID0+IHtcbiAgc3dpdGNoICh0eXBlb2YgbW9uZ29PYmplY3QpIHtcbiAgICBjYXNlICdzdHJpbmcnOlxuICAgIGNhc2UgJ251bWJlcic6XG4gICAgY2FzZSAnYm9vbGVhbic6XG4gICAgY2FzZSAndW5kZWZpbmVkJzpcbiAgICAgIHJldHVybiBtb25nb09iamVjdDtcbiAgICBjYXNlICdzeW1ib2wnOlxuICAgIGNhc2UgJ2Z1bmN0aW9uJzpcbiAgICAgIHRocm93ICdiYWQgdmFsdWUgaW4gbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0JztcbiAgICBjYXNlICdvYmplY3QnOiB7XG4gICAgICBpZiAobW9uZ29PYmplY3QgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShtb25nb09iamVjdCkpIHtcbiAgICAgICAgcmV0dXJuIG1vbmdvT2JqZWN0Lm1hcChuZXN0ZWRNb25nb09iamVjdFRvTmVzdGVkUGFyc2VPYmplY3QpO1xuICAgICAgfVxuXG4gICAgICBpZiAoVXRpbHMuaXNEYXRlKG1vbmdvT2JqZWN0KSkge1xuICAgICAgICByZXR1cm4gUGFyc2UuX2VuY29kZShtb25nb09iamVjdCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChtb25nb09iamVjdCBpbnN0YW5jZW9mIG1vbmdvZGIuTG9uZykge1xuICAgICAgICByZXR1cm4gbW9uZ29PYmplY3QudG9OdW1iZXIoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1vbmdvT2JqZWN0IGluc3RhbmNlb2YgbW9uZ29kYi5Eb3VibGUpIHtcbiAgICAgICAgcmV0dXJuIG1vbmdvT2JqZWN0LnZhbHVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoQnl0ZXNDb2Rlci5pc1ZhbGlkRGF0YWJhc2VPYmplY3QobW9uZ29PYmplY3QpKSB7XG4gICAgICAgIHJldHVybiBCeXRlc0NvZGVyLmRhdGFiYXNlVG9KU09OKG1vbmdvT2JqZWN0KTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVzdE9iamVjdCA9IHt9O1xuICAgICAgaWYgKG1vbmdvT2JqZWN0Ll9ycGVybSB8fCBtb25nb09iamVjdC5fd3Blcm0pIHtcbiAgICAgICAgcmVzdE9iamVjdC5fcnBlcm0gPSBtb25nb09iamVjdC5fcnBlcm0gfHwgW107XG4gICAgICAgIHJlc3RPYmplY3QuX3dwZXJtID0gbW9uZ29PYmplY3QuX3dwZXJtIHx8IFtdO1xuICAgICAgICBkZWxldGUgbW9uZ29PYmplY3QuX3JwZXJtO1xuICAgICAgICBkZWxldGUgbW9uZ29PYmplY3QuX3dwZXJtO1xuICAgICAgfVxuXG4gICAgICBmb3IgKHZhciBrZXkgaW4gbW9uZ29PYmplY3QpIHtcbiAgICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgICBjYXNlICdfaWQnOlxuICAgICAgICAgICAgcmVzdE9iamVjdFsnb2JqZWN0SWQnXSA9ICcnICsgbW9uZ29PYmplY3Rba2V5XTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ19oYXNoZWRfcGFzc3dvcmQnOlxuICAgICAgICAgICAgcmVzdE9iamVjdC5faGFzaGVkX3Bhc3N3b3JkID0gbW9uZ29PYmplY3Rba2V5XTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ19hY2wnOlxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnX2VtYWlsX3ZlcmlmeV90b2tlbic6XG4gICAgICAgICAgY2FzZSAnX3BlcmlzaGFibGVfdG9rZW4nOlxuICAgICAgICAgIGNhc2UgJ19wZXJpc2hhYmxlX3Rva2VuX2V4cGlyZXNfYXQnOlxuICAgICAgICAgIGNhc2UgJ19wYXNzd29yZF9jaGFuZ2VkX2F0JzpcbiAgICAgICAgICBjYXNlICdfdG9tYnN0b25lJzpcbiAgICAgICAgICBjYXNlICdfZW1haWxfdmVyaWZ5X3Rva2VuX2V4cGlyZXNfYXQnOlxuICAgICAgICAgIGNhc2UgJ19hY2NvdW50X2xvY2tvdXRfZXhwaXJlc19hdCc6XG4gICAgICAgICAgY2FzZSAnX2ZhaWxlZF9sb2dpbl9jb3VudCc6XG4gICAgICAgICAgY2FzZSAnX3Bhc3N3b3JkX2hpc3RvcnknOlxuICAgICAgICAgICAgLy8gVGhvc2Uga2V5cyB3aWxsIGJlIGRlbGV0ZWQgaWYgbmVlZGVkIGluIHRoZSBEQiBDb250cm9sbGVyXG4gICAgICAgICAgICByZXN0T2JqZWN0W2tleV0gPSBtb25nb09iamVjdFtrZXldO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnX3Nlc3Npb25fdG9rZW4nOlxuICAgICAgICAgICAgcmVzdE9iamVjdFsnc2Vzc2lvblRva2VuJ10gPSBtb25nb09iamVjdFtrZXldO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAndXBkYXRlZEF0JzpcbiAgICAgICAgICBjYXNlICdfdXBkYXRlZF9hdCc6XG4gICAgICAgICAgICByZXN0T2JqZWN0Wyd1cGRhdGVkQXQnXSA9IFBhcnNlLl9lbmNvZGUobmV3IERhdGUobW9uZ29PYmplY3Rba2V5XSkpLmlzbztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ2NyZWF0ZWRBdCc6XG4gICAgICAgICAgY2FzZSAnX2NyZWF0ZWRfYXQnOlxuICAgICAgICAgICAgcmVzdE9iamVjdFsnY3JlYXRlZEF0J10gPSBQYXJzZS5fZW5jb2RlKG5ldyBEYXRlKG1vbmdvT2JqZWN0W2tleV0pKS5pc287XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICdleHBpcmVzQXQnOlxuICAgICAgICAgIGNhc2UgJ19leHBpcmVzQXQnOlxuICAgICAgICAgICAgcmVzdE9iamVjdFsnZXhwaXJlc0F0J10gPSBQYXJzZS5fZW5jb2RlKG5ldyBEYXRlKG1vbmdvT2JqZWN0W2tleV0pKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ2xhc3RVc2VkJzpcbiAgICAgICAgICBjYXNlICdfbGFzdF91c2VkJzpcbiAgICAgICAgICAgIHJlc3RPYmplY3RbJ2xhc3RVc2VkJ10gPSBQYXJzZS5fZW5jb2RlKG5ldyBEYXRlKG1vbmdvT2JqZWN0W2tleV0pKS5pc287XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICd0aW1lc1VzZWQnOlxuICAgICAgICAgIGNhc2UgJ3RpbWVzX3VzZWQnOlxuICAgICAgICAgICAgcmVzdE9iamVjdFsndGltZXNVc2VkJ10gPSBtb25nb09iamVjdFtrZXldO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnYXV0aERhdGEnOlxuICAgICAgICAgICAgaWYgKGNsYXNzTmFtZSA9PT0gJ19Vc2VyJykge1xuICAgICAgICAgICAgICBsb2cud2FybihcbiAgICAgICAgICAgICAgICAnaWdub3JpbmcgYXV0aERhdGEgaW4gX1VzZXIgYXMgdGhpcyBrZXkgaXMgcmVzZXJ2ZWQgdG8gYmUgc3ludGhlc2l6ZWQgb2YgYF9hdXRoX2RhdGFfKmAga2V5cydcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJlc3RPYmplY3RbJ2F1dGhEYXRhJ10gPSBtb25nb09iamVjdFtrZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIC8vIENoZWNrIG90aGVyIGF1dGggZGF0YSBrZXlzXG4gICAgICAgICAgICB2YXIgYXV0aERhdGFNYXRjaCA9IGtleS5tYXRjaCgvXl9hdXRoX2RhdGFfKFthLXpBLVowLTlfXSspJC8pO1xuICAgICAgICAgICAgaWYgKGF1dGhEYXRhTWF0Y2ggJiYgY2xhc3NOYW1lID09PSAnX1VzZXInKSB7XG4gICAgICAgICAgICAgIHZhciBwcm92aWRlciA9IGF1dGhEYXRhTWF0Y2hbMV07XG4gICAgICAgICAgICAgIHJlc3RPYmplY3RbJ2F1dGhEYXRhJ10gPSByZXN0T2JqZWN0WydhdXRoRGF0YSddIHx8IHt9O1xuICAgICAgICAgICAgICByZXN0T2JqZWN0WydhdXRoRGF0YSddW3Byb3ZpZGVyXSA9IG1vbmdvT2JqZWN0W2tleV07XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoa2V5LmluZGV4T2YoJ19wXycpID09IDApIHtcbiAgICAgICAgICAgICAgdmFyIG5ld0tleSA9IGtleS5zdWJzdHJpbmcoMyk7XG4gICAgICAgICAgICAgIGlmICghc2NoZW1hLmZpZWxkc1tuZXdLZXldKSB7XG4gICAgICAgICAgICAgICAgbG9nLmluZm8oXG4gICAgICAgICAgICAgICAgICAndHJhbnNmb3JtLmpzJyxcbiAgICAgICAgICAgICAgICAgICdGb3VuZCBhIHBvaW50ZXIgY29sdW1uIG5vdCBpbiB0aGUgc2NoZW1hLCBkcm9wcGluZyBpdC4nLFxuICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICAgICAgbmV3S2V5XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAoc2NoZW1hLmZpZWxkc1tuZXdLZXldLnR5cGUgIT09ICdQb2ludGVyJykge1xuICAgICAgICAgICAgICAgIGxvZy5pbmZvKFxuICAgICAgICAgICAgICAgICAgJ3RyYW5zZm9ybS5qcycsXG4gICAgICAgICAgICAgICAgICAnRm91bmQgYSBwb2ludGVyIGluIGEgbm9uLXBvaW50ZXIgY29sdW1uLCBkcm9wcGluZyBpdC4nLFxuICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICAgICAga2V5XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAobW9uZ29PYmplY3Rba2V5XSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlc3RPYmplY3RbbmV3S2V5XSA9IHRyYW5zZm9ybVBvaW50ZXJTdHJpbmcoc2NoZW1hLCBuZXdLZXksIG1vbmdvT2JqZWN0W2tleV0pO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoa2V5WzBdID09ICdfJyAmJiBrZXkgIT0gJ19fdHlwZScpIHtcbiAgICAgICAgICAgICAgdGhyb3cgJ2JhZCBrZXkgaW4gdW50cmFuc2Zvcm06ICcgKyBrZXk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBtb25nb09iamVjdFtrZXldO1xuICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgc2NoZW1hLmZpZWxkc1trZXldICYmXG4gICAgICAgICAgICAgICAgc2NoZW1hLmZpZWxkc1trZXldLnR5cGUgPT09ICdGaWxlJyAmJlxuICAgICAgICAgICAgICAgIEZpbGVDb2Rlci5pc1ZhbGlkRGF0YWJhc2VPYmplY3QodmFsdWUpXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJlc3RPYmplY3Rba2V5XSA9IEZpbGVDb2Rlci5kYXRhYmFzZVRvSlNPTih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIHNjaGVtYS5maWVsZHNba2V5XSAmJlxuICAgICAgICAgICAgICAgIHNjaGVtYS5maWVsZHNba2V5XS50eXBlID09PSAnR2VvUG9pbnQnICYmXG4gICAgICAgICAgICAgICAgR2VvUG9pbnRDb2Rlci5pc1ZhbGlkRGF0YWJhc2VPYmplY3QodmFsdWUpXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJlc3RPYmplY3Rba2V5XSA9IEdlb1BvaW50Q29kZXIuZGF0YWJhc2VUb0pTT04odmFsdWUpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBzY2hlbWEuZmllbGRzW2tleV0gJiZcbiAgICAgICAgICAgICAgICBzY2hlbWEuZmllbGRzW2tleV0udHlwZSA9PT0gJ1BvbHlnb24nICYmXG4gICAgICAgICAgICAgICAgUG9seWdvbkNvZGVyLmlzVmFsaWREYXRhYmFzZU9iamVjdCh2YWx1ZSlcbiAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmVzdE9iamVjdFtrZXldID0gUG9seWdvbkNvZGVyLmRhdGFiYXNlVG9KU09OKHZhbHVlKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgc2NoZW1hLmZpZWxkc1trZXldICYmXG4gICAgICAgICAgICAgICAgc2NoZW1hLmZpZWxkc1trZXldLnR5cGUgPT09ICdCeXRlcycgJiZcbiAgICAgICAgICAgICAgICBCeXRlc0NvZGVyLmlzVmFsaWREYXRhYmFzZU9iamVjdCh2YWx1ZSlcbiAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmVzdE9iamVjdFtrZXldID0gQnl0ZXNDb2Rlci5kYXRhYmFzZVRvSlNPTih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc3RPYmplY3Rba2V5XSA9IG5lc3RlZE1vbmdvT2JqZWN0VG9OZXN0ZWRQYXJzZU9iamVjdChtb25nb09iamVjdFtrZXldKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCByZWxhdGlvbkZpZWxkTmFtZXMgPSBPYmplY3Qua2V5cyhzY2hlbWEuZmllbGRzKS5maWx0ZXIoXG4gICAgICAgIGZpZWxkTmFtZSA9PiBzY2hlbWEuZmllbGRzW2ZpZWxkTmFtZV0udHlwZSA9PT0gJ1JlbGF0aW9uJ1xuICAgICAgKTtcbiAgICAgIGNvbnN0IHJlbGF0aW9uRmllbGRzID0ge307XG4gICAgICByZWxhdGlvbkZpZWxkTmFtZXMuZm9yRWFjaChyZWxhdGlvbkZpZWxkTmFtZSA9PiB7XG4gICAgICAgIHJlbGF0aW9uRmllbGRzW3JlbGF0aW9uRmllbGROYW1lXSA9IHtcbiAgICAgICAgICBfX3R5cGU6ICdSZWxhdGlvbicsXG4gICAgICAgICAgY2xhc3NOYW1lOiBzY2hlbWEuZmllbGRzW3JlbGF0aW9uRmllbGROYW1lXS50YXJnZXRDbGFzcyxcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4geyAuLi5yZXN0T2JqZWN0LCAuLi5yZWxhdGlvbkZpZWxkcyB9O1xuICAgIH1cbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgJ3Vua25vd24ganMgdHlwZSc7XG4gIH1cbn07XG5cbnZhciBEYXRlQ29kZXIgPSB7XG4gIEpTT05Ub0RhdGFiYXNlKGpzb24pIHtcbiAgICByZXR1cm4gbmV3IERhdGUoanNvbi5pc28pO1xuICB9LFxuXG4gIGlzVmFsaWRKU09OKHZhbHVlKSB7XG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgIT09IG51bGwgJiYgdmFsdWUuX190eXBlID09PSAnRGF0ZSc7XG4gIH0sXG59O1xuXG52YXIgQnl0ZXNDb2RlciA9IHtcbiAgYmFzZTY0UGF0dGVybjogbmV3IFJlZ0V4cCgnXig/OltBLVphLXowLTkrL117NH0pKig/OltBLVphLXowLTkrL117Mn09PXxbQS1aYS16MC05Ky9dezN9PSk/JCcpLFxuICBpc0Jhc2U2NFZhbHVlKG9iamVjdCkge1xuICAgIGlmICh0eXBlb2Ygb2JqZWN0ICE9PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5iYXNlNjRQYXR0ZXJuLnRlc3Qob2JqZWN0KTtcbiAgfSxcblxuICBkYXRhYmFzZVRvSlNPTihvYmplY3QpIHtcbiAgICBsZXQgdmFsdWU7XG4gICAgaWYgKHRoaXMuaXNCYXNlNjRWYWx1ZShvYmplY3QpKSB7XG4gICAgICB2YWx1ZSA9IG9iamVjdDtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFsdWUgPSBvYmplY3QuYnVmZmVyLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIF9fdHlwZTogJ0J5dGVzJyxcbiAgICAgIGJhc2U2NDogdmFsdWUsXG4gICAgfTtcbiAgfSxcblxuICBpc1ZhbGlkRGF0YWJhc2VPYmplY3Qob2JqZWN0KSB7XG4gICAgcmV0dXJuIG9iamVjdCBpbnN0YW5jZW9mIG1vbmdvZGIuQmluYXJ5IHx8IHRoaXMuaXNCYXNlNjRWYWx1ZShvYmplY3QpO1xuICB9LFxuXG4gIEpTT05Ub0RhdGFiYXNlKGpzb24pIHtcbiAgICByZXR1cm4gbmV3IG1vbmdvZGIuQmluYXJ5KEJ1ZmZlci5mcm9tKGpzb24uYmFzZTY0LCAnYmFzZTY0JykpO1xuICB9LFxuXG4gIGlzVmFsaWRKU09OKHZhbHVlKSB7XG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgIT09IG51bGwgJiYgdmFsdWUuX190eXBlID09PSAnQnl0ZXMnO1xuICB9LFxufTtcblxudmFyIEdlb1BvaW50Q29kZXIgPSB7XG4gIGRhdGFiYXNlVG9KU09OKG9iamVjdCkge1xuICAgIHJldHVybiB7XG4gICAgICBfX3R5cGU6ICdHZW9Qb2ludCcsXG4gICAgICBsYXRpdHVkZTogb2JqZWN0WzFdLFxuICAgICAgbG9uZ2l0dWRlOiBvYmplY3RbMF0sXG4gICAgfTtcbiAgfSxcblxuICBpc1ZhbGlkRGF0YWJhc2VPYmplY3Qob2JqZWN0KSB7XG4gICAgcmV0dXJuIEFycmF5LmlzQXJyYXkob2JqZWN0KSAmJiBvYmplY3QubGVuZ3RoID09IDI7XG4gIH0sXG5cbiAgSlNPTlRvRGF0YWJhc2UoanNvbikge1xuICAgIHJldHVybiBbanNvbi5sb25naXR1ZGUsIGpzb24ubGF0aXR1ZGVdO1xuICB9LFxuXG4gIGlzVmFsaWRKU09OKHZhbHVlKSB7XG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgIT09IG51bGwgJiYgdmFsdWUuX190eXBlID09PSAnR2VvUG9pbnQnO1xuICB9LFxufTtcblxudmFyIFBvbHlnb25Db2RlciA9IHtcbiAgZGF0YWJhc2VUb0pTT04ob2JqZWN0KSB7XG4gICAgLy8gQ29udmVydCBsbmcvbGF0IC0+IGxhdC9sbmdcbiAgICBjb25zdCBjb29yZHMgPSBvYmplY3QuY29vcmRpbmF0ZXNbMF0ubWFwKGNvb3JkID0+IHtcbiAgICAgIHJldHVybiBbY29vcmRbMV0sIGNvb3JkWzBdXTtcbiAgICB9KTtcbiAgICByZXR1cm4ge1xuICAgICAgX190eXBlOiAnUG9seWdvbicsXG4gICAgICBjb29yZGluYXRlczogY29vcmRzLFxuICAgIH07XG4gIH0sXG5cbiAgaXNWYWxpZERhdGFiYXNlT2JqZWN0KG9iamVjdCkge1xuICAgIGNvbnN0IGNvb3JkcyA9IG9iamVjdC5jb29yZGluYXRlc1swXTtcbiAgICBpZiAob2JqZWN0LnR5cGUgIT09ICdQb2x5Z29uJyB8fCAhQXJyYXkuaXNBcnJheShjb29yZHMpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBwb2ludCA9IGNvb3Jkc1tpXTtcbiAgICAgIGlmICghR2VvUG9pbnRDb2Rlci5pc1ZhbGlkRGF0YWJhc2VPYmplY3QocG9pbnQpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIFBhcnNlLkdlb1BvaW50Ll92YWxpZGF0ZShwYXJzZUZsb2F0KHBvaW50WzFdKSwgcGFyc2VGbG9hdChwb2ludFswXSkpO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBKU09OVG9EYXRhYmFzZShqc29uKSB7XG4gICAgbGV0IGNvb3JkcyA9IGpzb24uY29vcmRpbmF0ZXM7XG4gICAgLy8gQWRkIGZpcnN0IHBvaW50IHRvIHRoZSBlbmQgdG8gY2xvc2UgcG9seWdvblxuICAgIGlmIChcbiAgICAgIGNvb3Jkc1swXVswXSAhPT0gY29vcmRzW2Nvb3Jkcy5sZW5ndGggLSAxXVswXSB8fFxuICAgICAgY29vcmRzWzBdWzFdICE9PSBjb29yZHNbY29vcmRzLmxlbmd0aCAtIDFdWzFdXG4gICAgKSB7XG4gICAgICBjb29yZHMucHVzaChjb29yZHNbMF0pO1xuICAgIH1cbiAgICBjb25zdCB1bmlxdWUgPSBjb29yZHMuZmlsdGVyKChpdGVtLCBpbmRleCwgYXIpID0+IHtcbiAgICAgIGxldCBmb3VuZEluZGV4ID0gLTE7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFyLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgIGNvbnN0IHB0ID0gYXJbaV07XG4gICAgICAgIGlmIChwdFswXSA9PT0gaXRlbVswXSAmJiBwdFsxXSA9PT0gaXRlbVsxXSkge1xuICAgICAgICAgIGZvdW5kSW5kZXggPSBpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gZm91bmRJbmRleCA9PT0gaW5kZXg7XG4gICAgfSk7XG4gICAgaWYgKHVuaXF1ZS5sZW5ndGggPCAzKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUixcbiAgICAgICAgJ0dlb0pTT046IExvb3AgbXVzdCBoYXZlIGF0IGxlYXN0IDMgZGlmZmVyZW50IHZlcnRpY2VzJ1xuICAgICAgKTtcbiAgICB9XG4gICAgLy8gQ29udmVydCBsYXQvbG9uZyAtPiBsb25nL2xhdFxuICAgIGNvb3JkcyA9IGNvb3Jkcy5tYXAoY29vcmQgPT4ge1xuICAgICAgcmV0dXJuIFtjb29yZFsxXSwgY29vcmRbMF1dO1xuICAgIH0pO1xuICAgIHJldHVybiB7IHR5cGU6ICdQb2x5Z29uJywgY29vcmRpbmF0ZXM6IFtjb29yZHNdIH07XG4gIH0sXG5cbiAgaXNWYWxpZEpTT04odmFsdWUpIHtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbCAmJiB2YWx1ZS5fX3R5cGUgPT09ICdQb2x5Z29uJztcbiAgfSxcbn07XG5cbnZhciBGaWxlQ29kZXIgPSB7XG4gIGRhdGFiYXNlVG9KU09OKG9iamVjdCkge1xuICAgIHJldHVybiB7XG4gICAgICBfX3R5cGU6ICdGaWxlJyxcbiAgICAgIG5hbWU6IG9iamVjdCxcbiAgICB9O1xuICB9LFxuXG4gIGlzVmFsaWREYXRhYmFzZU9iamVjdChvYmplY3QpIHtcbiAgICByZXR1cm4gdHlwZW9mIG9iamVjdCA9PT0gJ3N0cmluZyc7XG4gIH0sXG5cbiAgSlNPTlRvRGF0YWJhc2UoanNvbikge1xuICAgIHJldHVybiBqc29uLm5hbWU7XG4gIH0sXG5cbiAgaXNWYWxpZEpTT04odmFsdWUpIHtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbCAmJiB2YWx1ZS5fX3R5cGUgPT09ICdGaWxlJztcbiAgfSxcbn07XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB0cmFuc2Zvcm1LZXksXG4gIHBhcnNlT2JqZWN0VG9Nb25nb09iamVjdEZvckNyZWF0ZSxcbiAgdHJhbnNmb3JtVXBkYXRlLFxuICB0cmFuc2Zvcm1XaGVyZSxcbiAgbW9uZ29PYmplY3RUb1BhcnNlT2JqZWN0LFxuICB0cmFuc2Zvcm1Db25zdHJhaW50LFxuICB0cmFuc2Zvcm1Qb2ludGVyU3RyaW5nLFxufTtcbiJdLCJtYXBwaW5ncyI6Ijs7QUFBQSxJQUFBQSxPQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxPQUFBLEdBQUFGLHNCQUFBLENBQUFDLE9BQUE7QUFBdUIsU0FBQUQsdUJBQUFHLENBQUEsV0FBQUEsQ0FBQSxJQUFBQSxDQUFBLENBQUFDLFVBQUEsR0FBQUQsQ0FBQSxLQUFBRSxPQUFBLEVBQUFGLENBQUE7QUFDdkIsSUFBSUcsT0FBTyxHQUFHTCxPQUFPLENBQUMsU0FBUyxDQUFDO0FBQ2hDLElBQUlNLEtBQUssR0FBR04sT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDTSxLQUFLO0FBQ3ZDLE1BQU1DLEtBQUssR0FBR1AsT0FBTyxDQUFDLGdCQUFnQixDQUFDO0FBRXZDLE1BQU1RLFlBQVksR0FBR0EsQ0FBQ0MsU0FBUyxFQUFFQyxTQUFTLEVBQUVDLE1BQU0sS0FBSztFQUNyRDtFQUNBLFFBQVFELFNBQVM7SUFDZixLQUFLLFVBQVU7TUFDYixPQUFPLEtBQUs7SUFDZCxLQUFL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
|