1 | ;
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 |
|
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
8 |
|
9 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
10 |
|
11 | var https = require("https");
|
12 | var http = require("http");
|
13 | var request = require("request");
|
14 | var querystring = require("querystring");
|
15 |
|
16 | var HttpClient = function () {
|
17 | function HttpClient(options, credentials) {
|
18 | _classCallCheck(this, HttpClient);
|
19 |
|
20 | this.credentials = credentials;
|
21 | this.host = options.host || "rest.nexmo.com";
|
22 | this.port = options.port || 443;
|
23 | this.https = options.https || https;
|
24 | this.http = options.http || http;
|
25 | this.headers = {
|
26 | "Content-Type": "application/x-www-form-urlencoded",
|
27 | Accept: "application/json"
|
28 | };
|
29 | this.logger = options.logger;
|
30 | this.timeout = options.timeout;
|
31 | this.requestLib = request;
|
32 |
|
33 | if (options.userAgent) {
|
34 | this.headers["User-Agent"] = options.userAgent;
|
35 | }
|
36 | }
|
37 |
|
38 | _createClass(HttpClient, [{
|
39 | key: "request",
|
40 | value: function request(endpoint, method, callback) {
|
41 | var _this = this;
|
42 |
|
43 | var skipJsonParsing = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
44 | var customResponseParser = arguments[4];
|
45 |
|
46 | if (typeof method === "function") {
|
47 | callback = method;
|
48 | endpoint.method = endpoint.method || "GET";
|
49 | } else if (typeof method !== "undefined") {
|
50 | endpoint.method = method;
|
51 | }
|
52 |
|
53 | if (endpoint.method === "POST" || endpoint.method === "DELETE") {
|
54 | // TODO: verify the following fix is required
|
55 | // Fix broken due ot 411 Content-Length error now sent by Nexmo API
|
56 | // PL 2016-Sept-6 - commented out Content-Length 0
|
57 | // headers['Content-Length'] = 0;
|
58 | }
|
59 | var options = {
|
60 | host: endpoint.host ? endpoint.host : this.host,
|
61 | port: this.port,
|
62 | path: endpoint.path,
|
63 | method: endpoint.method,
|
64 | headers: Object.assign({}, this.headers)
|
65 | };
|
66 |
|
67 | if (this.timeout !== undefined) {
|
68 | options.timeout = this.timeout;
|
69 | }
|
70 |
|
71 | // Allow existing headers to be overridden
|
72 | // Allow new headers to be added
|
73 | if (endpoint.headers) {
|
74 | Object.keys(endpoint.headers).forEach(function (key) {
|
75 | options.headers[key] = endpoint.headers[key];
|
76 | });
|
77 | }
|
78 |
|
79 | if (this.credentials.signatureSecret && this.credentials.signatureMethod) {
|
80 | var splitPath = options.path.split(/\?(.+)/);
|
81 | var path = splitPath[0];
|
82 |
|
83 | var params = querystring.decode(splitPath[1]);
|
84 |
|
85 | // add timestamp if not already present
|
86 | if (!params.timestamp) {
|
87 | params.timestamp = new Date().getTime() / 1000 | 0; // floor to seconds
|
88 | params.timestamp = params.timestamp.toString();
|
89 | }
|
90 |
|
91 | // strip API Secret
|
92 | delete params.api_secret;
|
93 |
|
94 | var hash = this.credentials.generateSignature(params);
|
95 |
|
96 | var query = "";
|
97 |
|
98 | // rebuild query
|
99 | Object.keys(params).sort().forEach(function (key) {
|
100 | query += "&" + key + "=" + encodeURI(params[key]);
|
101 | });
|
102 |
|
103 | // replace the first & with ?
|
104 | query = query.replace(/&/i, "?");
|
105 |
|
106 | options.path = "" + path + query + "&sig=" + hash;
|
107 | }
|
108 |
|
109 | this.logger.info("Request:", options, "\nBody:", endpoint.body);
|
110 | var request;
|
111 |
|
112 | if (options.port === 443) {
|
113 | request = this.https.request(options);
|
114 | } else {
|
115 | request = this.http.request(options);
|
116 | }
|
117 |
|
118 | request.end(endpoint.body);
|
119 |
|
120 | // Keep an array of String or Buffers,
|
121 | // depending on content type (binary or JSON) of response
|
122 | var responseData = [];
|
123 |
|
124 | request.on("response", function (response) {
|
125 | var isBinary = response.headers["content-type"] === "application/octet-stream";
|
126 | if (!isBinary) {
|
127 | response.setEncoding("utf8");
|
128 | }
|
129 |
|
130 | response.on("data", function (chunk) {
|
131 | responseData.push(chunk);
|
132 | });
|
133 |
|
134 | response.on("end", function () {
|
135 | _this.logger.info("response ended:", response.statusCode);
|
136 | if (callback) {
|
137 | if (isBinary) {
|
138 | responseData = Buffer.concat(responseData);
|
139 | }
|
140 |
|
141 | _this.__parseResponse(response, responseData, endpoint.method, callback, skipJsonParsing, customResponseParser);
|
142 | }
|
143 | });
|
144 | response.on("close", function (e) {
|
145 | if (e) {
|
146 | _this.logger.error("problem with API request detailed stacktrace below ");
|
147 | _this.logger.error(e);
|
148 | callback(e);
|
149 | }
|
150 | });
|
151 | });
|
152 | request.on("error", function (e) {
|
153 | _this.logger.error("problem with API request detailed stacktrace below ");
|
154 | _this.logger.error(e);
|
155 | callback(e);
|
156 | });
|
157 | }
|
158 | }, {
|
159 | key: "__parseResponse",
|
160 | value: function __parseResponse(httpResponse, data, method, callback, skipJsonParsing, customResponseParser) {
|
161 | var isArrayOrBuffer = data instanceof Array || data instanceof Buffer;
|
162 | if (!isArrayOrBuffer) {
|
163 | throw new Error("data should be of type Array or Buffer");
|
164 | }
|
165 |
|
166 | var status = httpResponse.statusCode;
|
167 | var headers = httpResponse.headers;
|
168 |
|
169 | var response = null;
|
170 | var error = null;
|
171 |
|
172 | try {
|
173 | if (status >= 500) {
|
174 | error = {
|
175 | message: "Server Error",
|
176 | statusCode: status
|
177 | };
|
178 | } else if (httpResponse.headers["content-type"] === "application/octet-stream") {
|
179 | response = data;
|
180 | } else if (status === 429) {
|
181 | // 429 does not return a parsable body
|
182 | if (!headers["retry-after"]) {
|
183 | // retry based on allowed per second
|
184 | var retryAfterMillis = method === "POST" ? 1000 / 2 : 1000 / 5;
|
185 | headers["retry-after"] = retryAfterMillis;
|
186 | }
|
187 | error = {
|
188 | body: data.join("")
|
189 | };
|
190 | } else if (status === 204) {
|
191 | response = null;
|
192 | } else if (status >= 400 || status < 200) {
|
193 | error = {
|
194 | body: JSON.parse(data.join("")),
|
195 | headers: headers
|
196 | };
|
197 | } else if (method !== "DELETE") {
|
198 | if (!!skipJsonParsing) {
|
199 | response = data.join("");
|
200 | } else {
|
201 | response = JSON.parse(data.join(""));
|
202 | }
|
203 | } else {
|
204 | response = data;
|
205 | }
|
206 | } catch (parseError) {
|
207 | this.logger.error(parseError);
|
208 | this.logger.error("could not convert API response to JSON, above error is ignored and raw API response is returned to client");
|
209 | this.logger.error("Raw Error message from API ");
|
210 | this.logger.error("\"" + data + "\"");
|
211 |
|
212 | error = {
|
213 | status: status,
|
214 | message: "The API response could not be parsed.",
|
215 | body: data.join(""),
|
216 | parseError: parseError
|
217 | };
|
218 | }
|
219 |
|
220 | if (error) {
|
221 | error.statusCode = status;
|
222 | error.headers = headers;
|
223 | }
|
224 |
|
225 | if (typeof callback === "function") {
|
226 | if (typeof customResponseParser === "function") {
|
227 | // don't try to parse the response on errors
|
228 | if (response) {
|
229 | response = customResponseParser(response);
|
230 | }
|
231 | }
|
232 | callback(error, response);
|
233 | }
|
234 | }
|
235 | }, {
|
236 | key: "_addLimitedAccessMessageToErrors",
|
237 | value: function _addLimitedAccessMessageToErrors(callback, limitedAccessStatus) {
|
238 | return function (err, data) {
|
239 | if (err && err.status == limitedAccessStatus) {
|
240 | err._INFO_ = "This endpoint may need activating on your account. Please email support@nexmo.com for more information";
|
241 | }
|
242 |
|
243 | return callback(err, data);
|
244 | };
|
245 | }
|
246 | }, {
|
247 | key: "get",
|
248 | value: function get(path, params, callback) {
|
249 | var useJwt = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
250 | var useBasicAuth = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
251 |
|
252 | if (!callback) {
|
253 | if (typeof params == "function") {
|
254 | callback = params;
|
255 | params = {};
|
256 | }
|
257 | }
|
258 |
|
259 | params = params || {};
|
260 | if (!useJwt && !useBasicAuth) {
|
261 | params["api_key"] = this.credentials.apiKey;
|
262 | params["api_secret"] = this.credentials.apiSecret;
|
263 | }
|
264 |
|
265 | path = path + "?" + querystring.stringify(params);
|
266 |
|
267 | var headers = {
|
268 | "Content-Type": "application/json"
|
269 | };
|
270 | if (useJwt) {
|
271 | headers["Authorization"] = "Bearer " + this.credentials.generateJwt();
|
272 | }
|
273 | if (useBasicAuth) {
|
274 | headers["Authorization"] = "Basic " + Buffer.from(this.credentials.apiKey + ":" + this.credentials.apiSecret).toString("base64");
|
275 | }
|
276 |
|
277 | this.request({
|
278 | path: path,
|
279 | headers: headers
|
280 | }, "GET", callback);
|
281 | }
|
282 | }, {
|
283 | key: "delete",
|
284 | value: function _delete(path, callback, useJwt, useBasicAuth) {
|
285 | var params = {};
|
286 | if (!useJwt && !useBasicAuth) {
|
287 | params["api_key"] = this.credentials.apiKey;
|
288 | params["api_secret"] = this.credentials.apiSecret;
|
289 | }
|
290 |
|
291 | var headers = {};
|
292 |
|
293 | if (useBasicAuth) {
|
294 | headers["Authorization"] = "Basic " + Buffer.from(this.credentials.apiKey + ":" + this.credentials.apiSecret).toString("base64");
|
295 | }
|
296 | path = path + "?" + querystring.stringify(params);
|
297 |
|
298 | this.request({
|
299 | path: path,
|
300 | headers: headers
|
301 | }, "DELETE", callback);
|
302 | }
|
303 | }, {
|
304 | key: "postFile",
|
305 | value: function postFile(path, options, callback, useJwt) {
|
306 | var qs = {};
|
307 | if (!useJwt) {
|
308 | qs["api_key"] = this.credentials.apiKey;
|
309 | qs["api_secret"] = this.credentials.apiSecret;
|
310 | }
|
311 |
|
312 | if (Object.keys(qs).length) {
|
313 | var joinChar = "?";
|
314 | if (path.indexOf(joinChar) !== -1) {
|
315 | joinChar = "&";
|
316 | }
|
317 | path = path + joinChar + querystring.stringify(qs);
|
318 | }
|
319 |
|
320 | var file = options.file;
|
321 | delete options.file; // We don't send this as metadata
|
322 |
|
323 | var formData = {};
|
324 |
|
325 | if (file) {
|
326 | formData["filedata"] = {
|
327 | value: file,
|
328 | options: {
|
329 | filename: options.filename || null
|
330 | }
|
331 | };
|
332 | }
|
333 |
|
334 | if (options.info) {
|
335 | formData.info = JSON.stringify(options.info);
|
336 | }
|
337 |
|
338 | if (options.url) {
|
339 | formData.url = options.url;
|
340 | }
|
341 |
|
342 | this.requestLib.post({
|
343 | url: "https://" + this.host + path,
|
344 | formData: formData,
|
345 | headers: {
|
346 | Authorization: "Bearer " + this.credentials.generateJwt()
|
347 | }
|
348 | }, callback);
|
349 | }
|
350 | }, {
|
351 | key: "post",
|
352 | value: function post(path, params, callback, useJwt) {
|
353 | var qs = {};
|
354 | if (!useJwt) {
|
355 | qs["api_key"] = this.credentials.apiKey;
|
356 | qs["api_secret"] = this.credentials.apiSecret;
|
357 | }
|
358 |
|
359 | var joinChar = "?";
|
360 | if (path.indexOf(joinChar) !== -1) {
|
361 | joinChar = "&";
|
362 | }
|
363 |
|
364 | path = path + joinChar + querystring.stringify(qs);
|
365 |
|
366 | this.request({
|
367 | path: path,
|
368 | body: querystring.stringify(params)
|
369 | }, "POST", callback);
|
370 | }
|
371 | }, {
|
372 | key: "postJson",
|
373 | value: function postJson(path, params, callback, useJwt, useBasicAuth) {
|
374 | var qs = {};
|
375 | if (!useJwt && !useBasicAuth) {
|
376 | qs["api_key"] = this.credentials.apiKey;
|
377 | qs["api_secret"] = this.credentials.apiSecret;
|
378 | }
|
379 |
|
380 | var joinChar = "?";
|
381 | if (path.indexOf(joinChar) !== -1) {
|
382 | joinChar = "&";
|
383 | }
|
384 |
|
385 | path = path + joinChar + querystring.stringify(qs);
|
386 |
|
387 | var headers = {
|
388 | "Content-Type": "application/json"
|
389 | };
|
390 | if (useBasicAuth) {
|
391 | headers["Authorization"] = "Basic " + Buffer.from(this.credentials.apiKey + ":" + this.credentials.apiSecret).toString("base64");
|
392 | }
|
393 |
|
394 | this.request({
|
395 | path: path,
|
396 | body: JSON.stringify(params),
|
397 | headers: headers
|
398 | }, "POST", callback);
|
399 | }
|
400 | }, {
|
401 | key: "postUseQueryString",
|
402 | value: function postUseQueryString(path, params, callback, useJwt) {
|
403 | params = params || {};
|
404 | if (!useJwt) {
|
405 | params["api_key"] = this.credentials.apiKey;
|
406 | params["api_secret"] = this.credentials.apiSecret;
|
407 | }
|
408 |
|
409 | path = path + "?" + querystring.stringify(params);
|
410 |
|
411 | this.request({
|
412 | path: path
|
413 | }, "POST", callback);
|
414 | }
|
415 | }]);
|
416 |
|
417 | return HttpClient;
|
418 | }();
|
419 |
|
420 | exports.default = HttpClient;
|
421 | module.exports = exports["default"];
|
422 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9IdHRwQ2xpZW50LmpzIl0sIm5hbWVzIjpbImh0dHBzIiwicmVxdWlyZSIsImh0dHAiLCJyZXF1ZXN0IiwicXVlcnlzdHJpbmciLCJIdHRwQ2xpZW50Iiwib3B0aW9ucyIsImNyZWRlbnRpYWxzIiwiaG9zdCIsInBvcnQiLCJoZWFkZXJzIiwiQWNjZXB0IiwibG9nZ2VyIiwidGltZW91dCIsInJlcXVlc3RMaWIiLCJ1c2VyQWdlbnQiLCJlbmRwb2ludCIsIm1ldGhvZCIsImNhbGxiYWNrIiwic2tpcEpzb25QYXJzaW5nIiwiY3VzdG9tUmVzcG9uc2VQYXJzZXIiLCJwYXRoIiwiT2JqZWN0IiwiYXNzaWduIiwidW5kZWZpbmVkIiwia2V5cyIsImZvckVhY2giLCJrZXkiLCJzaWduYXR1cmVTZWNyZXQiLCJzaWduYXR1cmVNZXRob2QiLCJzcGxpdFBhdGgiLCJzcGxpdCIsInBhcmFtcyIsImRlY29kZSIsInRpbWVzdGFtcCIsIkRhdGUiLCJnZXRUaW1lIiwidG9TdHJpbmciLCJhcGlfc2VjcmV0IiwiaGFzaCIsImdlbmVyYXRlU2lnbmF0dXJlIiwicXVlcnkiLCJzb3J0IiwiZW5jb2RlVVJJIiwicmVwbGFjZSIsImluZm8iLCJib2R5IiwiZW5kIiwicmVzcG9uc2VEYXRhIiwib24iLCJpc0JpbmFyeSIsInJlc3BvbnNlIiwic2V0RW5jb2RpbmciLCJwdXNoIiwiY2h1bmsiLCJzdGF0dXNDb2RlIiwiQnVmZmVyIiwiY29uY2F0IiwiX19wYXJzZVJlc3BvbnNlIiwiZSIsImVycm9yIiwiaHR0cFJlc3BvbnNlIiwiZGF0YSIsImlzQXJyYXlPckJ1ZmZlciIsIkFycmF5IiwiRXJyb3IiLCJzdGF0dXMiLCJtZXNzYWdlIiwicmV0cnlBZnRlck1pbGxpcyIsImpvaW4iLCJKU09OIiwicGFyc2UiLCJwYXJzZUVycm9yIiwibGltaXRlZEFjY2Vzc1N0YXR1cyIsImVyciIsIl9JTkZPXyIsInVzZUp3dCIsInVzZUJhc2ljQXV0aCIsImFwaUtleSIsImFwaVNlY3JldCIsInN0cmluZ2lmeSIsImdlbmVyYXRlSnd0IiwiZnJvbSIsInFzIiwibGVuZ3RoIiwiam9pbkNoYXIiLCJpbmRleE9mIiwiZmlsZSIsImZvcm1EYXRhIiwidmFsdWUiLCJmaWxlbmFtZSIsInVybCIsInBvc3QiLCJBdXRob3JpemF0aW9uIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUEsSUFBSUEsUUFBUUMsUUFBUSxPQUFSLENBQVo7QUFDQSxJQUFJQyxPQUFPRCxRQUFRLE1BQVIsQ0FBWDtBQUNBLElBQUlFLFVBQVVGLFFBQVEsU0FBUixDQUFkO0FBQ0EsSUFBSUcsY0FBY0gsUUFBUSxhQUFSLENBQWxCOztJQUVNSSxVO0FBQ0osc0JBQVlDLE9BQVosRUFBcUJDLFdBQXJCLEVBQWtDO0FBQUE7O0FBQ2hDLFNBQUtBLFdBQUwsR0FBbUJBLFdBQW5CO0FBQ0EsU0FBS0MsSUFBTCxHQUFZRixRQUFRRSxJQUFSLElBQWdCLGdCQUE1QjtBQUNBLFNBQUtDLElBQUwsR0FBWUgsUUFBUUcsSUFBUixJQUFnQixHQUE1QjtBQUNBLFNBQUtULEtBQUwsR0FBYU0sUUFBUU4sS0FBUixJQUFpQkEsS0FBOUI7QUFDQSxTQUFLRSxJQUFMLEdBQVlJLFFBQVFKLElBQVIsSUFBZ0JBLElBQTVCO0FBQ0EsU0FBS1EsT0FBTCxHQUFlO0FBQ2Isc0JBQWdCLG1DQURIO0FBRWJDLGNBQVE7QUFGSyxLQUFmO0FBSUEsU0FBS0MsTUFBTCxHQUFjTixRQUFRTSxNQUF0QjtBQUNBLFNBQUtDLE9BQUwsR0FBZVAsUUFBUU8sT0FBdkI7QUFDQSxTQUFLQyxVQUFMLEdBQWtCWCxPQUFsQjs7QUFFQSxRQUFJRyxRQUFRUyxTQUFaLEVBQXVCO0FBQ3JCLFdBQUtMLE9BQUwsQ0FBYSxZQUFiLElBQTZCSixRQUFRUyxTQUFyQztBQUNEO0FBQ0Y7Ozs7NEJBR0NDLFEsRUFDQUMsTSxFQUNBQyxRLEVBR0E7QUFBQTs7QUFBQSxVQUZBQyxlQUVBLHVFQUZrQixLQUVsQjtBQUFBLFVBREFDLG9CQUNBOztBQUNBLFVBQUksT0FBT0gs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SzNFLFdBQUwsQ0FBaUJ1RSxNQUFqQixHQUEwQixHQUExQixHQUFnQyxLQUFLdkUsV0FBTCxDQUFpQndFLFNBRGYsRUFFbEMxQyxRQUZrQyxDQUV6QixRQUZ5QixDQUFwQztBQUdEOztBQUVELFdBQUtsQyxPQUFMLENBQ0U7QUFDRWtCLGNBQU1BLElBRFI7QUFFRXlCLGNBQU13QixLQUFLVSxTQUFMLENBQWVoRCxNQUFmLENBRlI7QUFHRXRCO0FBSEYsT0FERixFQU1FLE1BTkYsRUFPRVEsUUFQRjtBQVNEOzs7dUNBRWtCRyxJLEVBQU1XLE0sRUFBUWQsUSxFQUFVMEQsTSxFQUFRO0FBQ2pENUMsZUFBU0EsVUFBVSxFQUFuQjtBQUNBLFVBQUksQ0FBQzRDLE1BQUwsRUFBYTtBQUNYNUMsZUFBTyxTQUFQLElBQW9CLEtBQUt6QixXQUFMLENBQWlCdUUsTUFBckM7QUFDQTlDLGVBQU8sWUFBUCxJQUF1QixLQUFLekIsV0FBTCxDQUFpQndFLFNBQXhDO0FBQ0Q7O0FBRUQxRCxhQUFPQSxPQUFPLEdBQVAsR0FBYWpCLFlBQVk0RSxTQUFaLENBQXNCaEQsTUFBdEIsQ0FBcEI7O0FBRUEsV0FBSzdCLE9BQUwsQ0FDRTtBQUNFa0IsY0FBTUE7QUFEUixPQURGLEVBSUUsTUFKRixFQUtFSCxRQUxGO0FBT0Q7Ozs7OztrQkFHWWIsVSIsImZpbGUiOiJIdHRwQ2xpZW50LmpzIiwic291cmNlc0NvbnRlbnQiOlsidmFyIGh0dHBzID0gcmVxdWlyZShcImh0dHBzXCIpO1xudmFyIGh0dHAgPSByZXF1aXJlKFwiaHR0cFwiKTtcbnZhciByZXF1ZXN0ID0gcmVxdWlyZShcInJlcXVlc3RcIik7XG52YXIgcXVlcnlzdHJpbmcgPSByZXF1aXJlKFwicXVlcnlzdHJpbmdcIik7XG5cbmNsYXNzIEh0dHBDbGllbnQge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zLCBjcmVkZW50aWFscykge1xuICAgIHRoaXMuY3JlZGVudGlhbHMgPSBjcmVkZW50aWFscztcbiAgICB0aGlzLmhvc3QgPSBvcHRpb25zLmhvc3QgfHwgXCJyZXN0Lm5leG1vLmNvbVwiO1xuICAgIHRoaXMucG9ydCA9IG9wdGlvbnMucG9ydCB8fCA0NDM7XG4gICAgdGhpcy5odHRwcyA9IG9wdGlvbnMuaHR0cHMgfHwgaHR0cHM7XG4gICAgdGhpcy5odHRwID0gb3B0aW9ucy5odHRwIHx8IGh0dHA7XG4gICAgdGhpcy5oZWFkZXJzID0ge1xuICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWRcIixcbiAgICAgIEFjY2VwdDogXCJhcHBsaWNhdGlvbi9qc29uXCJcbiAgICB9O1xuICAgIHRoaXMubG9nZ2VyID0gb3B0aW9ucy5sb2dnZXI7XG4gICAgdGhpcy50aW1lb3V0ID0gb3B0aW9ucy50aW1lb3V0O1xuICAgIHRoaXMucmVxdWVzdExpYiA9IHJlcXVlc3Q7XG5cbiAgICBpZiAob3B0aW9ucy51c2VyQWdlbnQpIHtcbiAgICAgIHRoaXMuaGVhZGVyc1tcIlVzZXItQWdlbnRcIl0gPSBvcHRpb25zLnVzZXJBZ2VudDtcbiAgICB9XG4gIH1cblxuICByZXF1ZXN0KFxuICAgIGVuZHBvaW50LFxuICAgIG1ldGhvZCxcbiAgICBjYWxsYmFjayxcbiAgICBza2lwSnNvblBhcnNpbmcgPSBmYWxzZSxcbiAgICBjdXN0b21SZXNwb25zZVBhcnNlclxuICApIHtcbiAgICBpZiAodHlwZW9mIG1ldGhvZCA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICBjYWxsYmFjayA9IG1ldGhvZDtcbiAgICAgIGVuZHBvaW50Lm1ldGhvZCA9IGVuZHBvaW50Lm1ldGhvZCB8fCBcIkdFVFwiO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIG1ldGhvZCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgZW5kcG9pbnQubWV0aG9kID0gbWV0aG9kO1xuICAgIH1cblxuICAgIGlmIChlbmRwb2ludC5tZXRob2QgPT09IFwiUE9TVFwiIHx8IGVuZHBvaW50Lm1ldGhvZCA9PT0gXCJERUxFVEVcIikge1xuICAgICAgLy8gVE9ETzogdmVyaWZ5IHRoZSBmb2xsb3dpbmcgZml4IGlzIHJlcXVpcmVkXG4gICAgICAvLyBGaXggYnJva2VuIGR1ZSBvdCA0MTEgQ29udGVudC1MZW5ndGggZXJyb3Igbm93IHNlbnQgYnkgTmV4bW8gQVBJXG4gICAgICAvLyBQTCAyMDE2LVNlcHQtNiAtIGNvbW1lbnRlZCBvdXQgQ29udGVudC1MZW5ndGggMFxuICAgICAgLy8gaGVhZGVyc1snQ29udGVudC1MZW5ndGgnXSA9IDA7XG4gICAgfVxuICAgIHZhciBvcHRpb25zID0ge1xuICAgICAgaG9zdDogZW5kcG9pbnQuaG9zdCA/IGVuZHBvaW50Lmhvc3QgOiB0aGlzLmhvc3QsXG4gICAgICBwb3J0OiB0aGlzLnBvcnQsXG4gICAgICBwYXRoOiBlbmRwb2ludC5wYXRoLFxuICAgICAgbWV0aG9kOiBlbmRwb2ludC5tZXRob2QsXG4gICAgICBoZWFkZXJzOiBPYmplY3QuYXNzaWduKHt9LCB0aGlzLmhlYWRlcnMpXG4gICAgfTtcblxuICAgIGlmICh0aGlzLnRpbWVvdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgb3B0aW9ucy50aW1lb3V0ID0gdGhpcy50aW1lb3V0O1xuICAgIH1cblxuICAgIC8vIEFsbG93IGV4aXN0aW5nIGhlYWRlcnMgdG8gYmUgb3ZlcnJpZGRlblxuICAgIC8vIEFsbG93IG5ldyBoZWFkZXJzIHRvIGJlIGFkZGVkXG4gICAgaWYgKGVuZHBvaW50LmhlYWRlcnMpIHtcbiAgICAgIE9iamVjdC5rZXlzKGVuZHBvaW50LmhlYWRlcnMpLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7XG4gICAgICAgIG9wdGlvbnMuaGVhZGVyc1trZXldID0gZW5kcG9pbnQuaGVhZGVyc1trZXldO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY3JlZGVudGlhbHMuc2lnbmF0dXJlU2VjcmV0ICYmIHRoaXMuY3JlZGVudGlhbHMuc2lnbmF0dXJlTWV0aG9kKSB7XG4gICAgICBjb25zdCBzcGxpdFBhdGggPSBvcHRpb25zLnBhdGguc3BsaXQoL1xcPyguKykvKTtcbiAgICAgIGNvbnN0IHBhdGggPSBzcGxpdFBhdGhbMF07XG5cbiAgICAgIHZhciBwYXJhbXMgPSBxdWVyeXN0cmluZy5kZWNvZGUoc3BsaXRQYXRoWzFdKTtcblxuICAgICAgLy8gYWRkIHRpbWVzdGFtcCBpZiBub3QgYWxyZWFkeSBwcmVzZW50XG4gICAgICBpZiAoIXBhcmFtcy50aW1lc3RhbXApIHtcbiAgICAgICAgcGFyYW1zLnRpbWVzdGFtcCA9IChuZXcgRGF0ZSgpLmdldFRpbWUoKSAvIDEwMDApIHwgMDsgLy8gZmxvb3IgdG8gc2Vjb25kc1xuICAgICAgICBwYXJhbXMudGltZXN0YW1wID0gcGFyYW1zLnRpbWVzdGFtcC50b1N0cmluZygpO1xuICAgICAgfVxuXG4gICAgICAvLyBzdHJpcCBBUEkgU2VjcmV0XG4gICAgICBkZWxldGUgcGFyYW1zLmFwaV9zZWNyZXQ7XG5cbiAgICAgIGNvbnN0IGhhc2ggPSB0aGlzLmNyZWRlbnRpYWxzLmdlbmVyYXRlU2lnbmF0dXJlKHBhcmFtcyk7XG5cbiAgICAgIHZhciBxdWVyeSA9IFwiXCI7XG5cbiAgICAgIC8vIHJlYnVpbGQgcXVlcnlcbiAgICAgIE9iamVjdC5rZXlzKHBhcmFtcylcbiAgICAgICAgLnNvcnQoKVxuICAgICAgICAuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgIHF1ZXJ5ICs9IFwiJlwiICsga2V5ICsgXCI9XCIgKyBlbmNvZGVVUkkocGFyYW1zW2tleV0pO1xuICAgICAgICB9KTtcblxuICAgICAgLy8gcmVwbGFjZSB0aGUgZmlyc3QgJiB3aXRoID9cbiAgICAgIHF1ZXJ5ID0gcXVlcnkucmVwbGFjZSgvJi9pLCBcIj9cIik7XG5cbiAgICAgIG9wdGlvbnMucGF0aCA9IGAke3BhdGh9JHtxdWVyeX0mc2lnPSR7aGFzaH1gO1xuICAgIH1cblxuICAgIHRoaXMubG9nZ2VyLmluZm8oXCJSZXF1ZXN0OlwiLCBvcHRpb25zLCBcIlxcbkJvZHk6XCIsIGVuZHBvaW50LmJvZHkpO1xuICAgIHZhciByZXF1ZXN0O1xuXG4gICAgaWYgKG9wdGlvbnMucG9ydCA9PT0gNDQzKSB7XG4gICAgICByZXF1ZXN0ID0gdGhpcy5odHRwcy5yZXF1ZXN0KG9wdGlvbnMpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXF1ZXN0ID0gdGhpcy5odHRwLnJlcXVlc3Qob3B0aW9ucyk7XG4gICAgfVxuXG4gICAgcmVxdWVzdC5lbmQoZW5kcG9pbnQuYm9keSk7XG5cbiAgICAvLyBLZWVwIGFuIGFycmF5IG9mIFN0cmluZyBvciBCdWZmZXJzLFxuICAgIC8vIGRlcGVuZGluZyBvbiBjb250ZW50IHR5cGUgKGJpbmFyeSBvciBKU09OKSBvZiByZXNwb25zZVxuICAgIHZhciByZXNwb25zZURhdGEgPSBbXTtcblxuICAgIHJlcXVlc3Qub24oXCJyZXNwb25zZVwiLCByZXNwb25zZSA9PiB7XG4gICAgICB2YXIgaXNCaW5hcnkgPVxuICAgICAgICByZXNwb25zZS5oZWFkZXJzW1wiY29udGVudC10eXBlXCJdID09PSBcImFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbVwiO1xuICAgICAgaWYgKCFpc0JpbmFyeSkge1xuICAgICAgICByZXNwb25zZS5zZXRFbmNvZGluZyhcInV0ZjhcIik7XG4gICAgICB9XG5cbiAgICAgIHJlc3BvbnNlLm9uKFwiZGF0YVwiLCBjaHVuayA9PiB7XG4gICAgICAgIHJlc3BvbnNlRGF0YS5wdXNoKGNodW5rKTtcbiAgICAgIH0pO1xuXG4gICAgICByZXNwb25zZS5vbihcImVuZFwiLCAoKSA9PiB7XG4gICAgICAgIHRoaXMubG9nZ2VyLmluZm8oXCJyZXNwb25zZSBlbmRlZDpcIiwgcmVzcG9uc2Uuc3RhdHVzQ29kZSk7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGlmIChpc0JpbmFyeSkge1xuICAgICAgICAgICAgcmVzcG9uc2VEYXRhID0gQnVmZmVyLmNvbmNhdChyZXNwb25zZURhdGEpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuX19wYXJzZVJlc3BvbnNlKFxuICAgICAgICAgICAgcmVzcG9uc2UsXG4gICAgICAgICAgICByZXNwb25zZURhdGEsXG4gICAgICAgICAgICBlbmRwb2ludC5tZXRob2QsXG4gICAgICAgICAgICBjYWxsYmFjayxcbiAgICAgICAgICAgIHNraXBKc29uUGFyc2luZyxcbiAgICAgICAgICAgIGN1c3RvbVJlc3BvbnNlUGFyc2VyXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXNwb25zZS5vbihcImNsb3NlXCIsIGUgPT4ge1xuICAgICAgICBpZiAoZSkge1xuICAgICAgICAgIHRoaXMubG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgXCJwcm9ibGVtIHdpdGggQVBJIHJlcXVlc3QgZGV0YWlsZWQgc3RhY2t0cmFjZSBiZWxvdyBcIlxuICAgICAgICAgICk7XG4gICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoZSk7XG4gICAgICAgICAgY2FsbGJhY2soZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIHJlcXVlc3Qub24oXCJlcnJvclwiLCBlID0+IHtcbiAgICAgIHRoaXMubG9nZ2VyLmVycm9yKFwicHJvYmxlbSB3aXRoIEFQSSByZXF1ZXN0IGRldGFpbGVkIHN0YWNrdHJhY2UgYmVsb3cgXCIpO1xuICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoZSk7XG4gICAgICBjYWxsYmFjayhlKTtcbiAgICB9KTtcbiAgfVxuXG4gIF9fcGFyc2VSZXNwb25zZShcbiAgICBodHRwUmVzcG9uc2UsXG4gICAgZGF0YSxcbiAgICBtZXRob2QsXG4gICAgY2FsbGJhY2ssXG4gICAgc2tpcEpzb25QYXJzaW5nLFxuICAgIGN1c3RvbVJlc3BvbnNlUGFyc2VyXG4gICkge1xuICAgIGNvbnN0IGlzQXJyYXlPckJ1ZmZlciA9IGRhdGEgaW5zdGFuY2VvZiBBcnJheSB8fCBkYXRhIGluc3RhbmNlb2YgQnVmZmVyO1xuICAgIGlmICghaXNBcnJheU9yQnVmZmVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJkYXRhIHNob3VsZCBiZSBvZiB0eXBlIEFycmF5IG9yIEJ1ZmZlclwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBzdGF0dXMgPSBodHRwUmVzcG9uc2Uuc3RhdHVzQ29kZTtcbiAgICBjb25zdCBoZWFkZXJzID0gaHR0cFJlc3BvbnNlLmhlYWRlcnM7XG5cbiAgICBsZXQgcmVzcG9uc2UgPSBudWxsO1xuICAgIHZhciBlcnJvciA9IG51bGw7XG5cbiAgICB0cnkge1xuICAgICAgaWYgKHN0YXR1cyA+PSA1MDApIHtcbiAgICAgICAgZXJyb3IgPSB7XG4gICAgICAgICAgbWVzc2FnZTogXCJTZXJ2ZXIgRXJyb3JcIixcbiAgICAgICAgICBzdGF0dXNDb2RlOiBzdGF0dXNcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGh0dHBSZXNwb25zZS5oZWFkZXJzW1wiY29udGVudC10eXBlXCJdID09PSBcImFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbVwiXG4gICAgICApIHtcbiAgICAgICAgcmVzcG9uc2UgPSBkYXRhO1xuICAgICAgfSBlbHNlIGlmIChzdGF0dXMgPT09IDQyOSkge1xuICAgICAgICAvLyA0MjkgZG9lcyBub3QgcmV0dXJuIGEgcGFyc2FibGUgYm9keVxuICAgICAgICBpZiAoIWhlYWRlcnNbXCJyZXRyeS1hZnRlclwiXSkge1xuICAgICAgICAgIC8vIHJldHJ5IGJhc2VkIG9uIGFsbG93ZWQgcGVyIHNlY29uZFxuICAgICAgICAgIGNvbnN0IHJldHJ5QWZ0ZXJNaWxsaXMgPSBtZXRob2QgPT09IFwiUE9TVFwiID8gMTAwMCAvIDIgOiAxMDAwIC8gNTtcbiAgICAgICAgICBoZWFkZXJzW1wicmV0cnktYWZ0ZXJcIl0gPSByZXRyeUFmdGVyTWlsbGlzO1xuICAgICAgICB9XG4gICAgICAgIGVycm9yID0ge1xuICAgICAgICAgIGJvZHk6IGRhdGEuam9pbihcIlwiKVxuICAgICAgICB9O1xuICAgICAgfSBlbHNlIGlmIChzdGF0dXMgPT09IDIwNCkge1xuICAgICAgICByZXNwb25zZSA9IG51bGw7XG4gICAgICB9IGVsc2UgaWYgKHN0YXR1cyA+PSA0MDAgfHwgc3RhdHVzIDwgMjAwKSB7XG4gICAgICAgIGVycm9yID0ge1xuICAgICAgICAgIGJvZHk6IEpTT04ucGFyc2UoZGF0YS5qb2luKFwiXCIpKSxcbiAgICAgICAgICBoZWFkZXJzXG4gICAgICAgIH07XG4gICAgICB9IGVsc2UgaWYgKG1ldGhvZCAhPT0gXCJERUxFVEVcIikge1xuICAgICAgICBpZiAoISFza2lwSnNvblBhcnNpbmcpIHtcbiAgICAgICAgICByZXNwb25zZSA9IGRhdGEuam9pbihcIlwiKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNwb25zZSA9IEpTT04ucGFyc2UoZGF0YS5qb2luKFwiXCIpKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzcG9uc2UgPSBkYXRhO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKHBhcnNlRXJyb3IpIHtcbiAgICAgIHRoaXMubG9nZ2VyLmVycm9yKHBhcnNlRXJyb3IpO1xuICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoXG4gICAgICAgIFwiY291bGQgbm90IGNvbnZlcnQgQVBJIHJlc3BvbnNlIHRvIEpTT04sIGFib3ZlIGVycm9yIGlzIGlnbm9yZWQgYW5kIHJhdyBBUEkgcmVzcG9uc2UgaXMgcmV0dXJuZWQgdG8gY2xpZW50XCJcbiAgICAgICk7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihcIlJhdyBFcnJvciBtZXNzYWdlIGZyb20gQVBJIFwiKTtcbiAgICAgIHRoaXMubG9nZ2VyLmVycm9yKGBcIiR7ZGF0YX1cImApO1xuXG4gICAgICBlcnJvciA9IHtcbiAgICAgICAgc3RhdHVzOiBzdGF0dXMsXG4gICAgICAgIG1lc3NhZ2U6IFwiVGhlIEFQSSByZXNwb25zZSBjb3VsZCBub3QgYmUgcGFyc2VkLlwiLFxuICAgICAgICBib2R5OiBkYXRhLmpvaW4oXCJcIiksXG4gICAgICAgIHBhcnNlRXJyb3I6IHBhcnNlRXJyb3JcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKGVycm9yKSB7XG4gICAgICBlcnJvci5zdGF0dXNDb2RlID0gc3RhdHVzO1xuICAgICAgZXJyb3IuaGVhZGVycyA9IGhlYWRlcnM7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBjYWxsYmFjayA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICBpZiAodHlwZW9mIGN1c3RvbVJlc3BvbnNlUGFyc2VyID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgLy8gZG9uJ3QgdHJ5IHRvIHBhcnNlIHRoZSByZXNwb25zZSBvbiBlcnJvcnNcbiAgICAgICAgaWYgKHJlc3BvbnNlKSB7XG4gICAgICAgICAgcmVzcG9uc2UgPSBjdXN0b21SZXNwb25zZVBhcnNlcihyZXNwb25zZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNhbGxiYWNrKGVycm9yLCByZXNwb25zZSk7XG4gICAgfVxuICB9XG5cbiAgX2FkZExpbWl0ZWRBY2Nlc3NNZXNzYWdlVG9FcnJvcnMoY2FsbGJhY2ssIGxpbWl0ZWRBY2Nlc3NTdGF0dXMpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oZXJyLCBkYXRhKSB7XG4gICAgICBpZiAoZXJyICYmIGVyci5zdGF0dXMgPT0gbGltaXRlZEFjY2Vzc1N0YXR1cykge1xuICAgICAgICBlcnIuX0lORk9fID1cbiAgICAgICAgICBcIlRoaXMgZW5kcG9pbnQgbWF5IG5lZWQgYWN0aXZhdGluZyBvbiB5b3VyIGFjY291bnQuIFBsZWFzZSBlbWFpbCBzdXBwb3J0QG5leG1vLmNvbSBmb3IgbW9yZSBpbmZvcm1hdGlvblwiO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gY2FsbGJhY2soZXJyLCBkYXRhKTtcbiAgICB9O1xuICB9XG5cbiAgZ2V0KHBhdGgsIHBhcmFtcywgY2FsbGJhY2ssIHVzZUp3dCA9IGZhbHNlLCB1c2VCYXNpY0F1dGggPSBmYWxzZSkge1xuICAgIGlmICghY2FsbGJhY2spIHtcbiAgICAgIGlmICh0eXBlb2YgcGFyYW1zID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICBjYWxsYmFjayA9IHBhcmFtcztcbiAgICAgICAgcGFyYW1zID0ge307XG4gICAgICB9XG4gICAgfVxuXG4gICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICAgIGlmICghdXNlSnd0ICYmICF1c2VCYXNpY0F1dGgpIHtcbiAgICAgIHBhcmFtc1tcImFwaV9rZXlcIl0gPSB0aGlzLmNyZWRlbnRpYWxzLmFwaUtleTtcbiAgICAgIHBhcmFtc1tcImFwaV9zZWNyZXRcIl0gPSB0aGlzLmNyZWRlbnRpYWxzLmFwaVNlY3JldDtcbiAgICB9XG5cbiAgICBwYXRoID0gcGF0aCArIFwiP1wiICsgcXVlcnlzdHJpbmcuc3RyaW5naWZ5KHBhcmFtcyk7XG5cbiAgICBjb25zdCBoZWFkZXJzID0ge1xuICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCJcbiAgICB9O1xuICAgIGlmICh1c2VKd3QpIHtcbiAgICAgIGhlYWRlcnNbXCJBdXRob3JpemF0aW9uXCJdID0gYEJlYXJlciAke3RoaXMuY3JlZGVudGlhbHMuZ2VuZXJhdGVKd3QoKX1gO1xuICAgIH1cbiAgICBpZiAodXNlQmFzaWNBdXRoKSB7XG4gICAgICBoZWFkZXJzW1wiQXV0aG9yaXphdGlvblwiXSA9IGBCYXNpYyAke0J1ZmZlci5mcm9tKFxuICAgICAgICB0aGlzLmNyZWRlbnRpYWxzLmFwaUtleSArIFwiOlwiICsgdGhpcy5jcmVkZW50aWFscy5hcGlTZWNyZXRcbiAgICAgICkudG9TdHJpbmcoXCJiYXNlNjRcIil9YDtcbiAgICB9XG5cbiAgICB0aGlzLnJlcXVlc3QoXG4gICAgICB7XG4gICAgICAgIHBhdGg6IHBhdGgsXG4gICAgICAgIGhlYWRlcnNcbiAgICAgIH0sXG4gICAgICBcIkdFVFwiLFxuICAgICAgY2FsbGJhY2tcbiAgICApO1xuICB9XG5cbiAgZGVsZXRlKHBhdGgsIGNhbGxiYWNrLCB1c2VKd3QsIHVzZUJhc2ljQXV0aCkge1xuICAgIGxldCBwYXJhbXMgPSB7fTtcbiAgICBpZiAoIXVzZUp3dCAmJiAhdXNlQmFzaWNBdXRoKSB7XG4gICAgICBwYXJhbXNbXCJhcGlfa2V5XCJdID0gdGhpcy5jcmVkZW50aWFscy5hcGlLZXk7XG4gICAgICBwYXJhbXNbXCJhcGlfc2VjcmV0XCJdID0gdGhpcy5jcmVkZW50aWFscy5hcGlTZWNyZXQ7XG4gICAgfVxuXG4gICAgbGV0IGhlYWRlcnMgPSB7fTtcblxuICAgIGlmICh1c2VCYXNpY0F1dGgpIHtcbiAgICAgIGhlYWRlcnNbXCJBdXRob3JpemF0aW9uXCJdID0gYEJhc2ljICR7QnVmZmVyLmZyb20oXG4gICAgICAgIHRoaXMuY3JlZGVudGlhbHMuYXBpS2V5ICsgXCI6XCIgKyB0aGlzLmNyZWRlbnRpYWxzLmFwaVNlY3JldFxuICAgICAgKS50b1N0cmluZyhcImJhc2U2NFwiKX1gO1xuICAgIH1cbiAgICBwYXRoID0gcGF0aCArIFwiP1wiICsgcXVlcnlzdHJpbmcuc3RyaW5naWZ5KHBhcmFtcyk7XG5cbiAgICB0aGlzLnJlcXVlc3QoXG4gICAgICB7XG4gICAgICAgIHBhdGg6IHBhdGgsXG4gICAgICAgIGhlYWRlcnNcbiAgICAgIH0sXG4gICAgICBcIkRFTEVURVwiLFxuICAgICAgY2FsbGJhY2tcbiAgICApO1xuICB9XG5cbiAgcG9zdEZpbGUocGF0aCwgb3B0aW9ucywgY2FsbGJhY2ssIHVzZUp3dCkge1xuICAgIGxldCBxcyA9IHt9O1xuICAgIGlmICghdXNlSnd0KSB7XG4gICAgICBxc1tcImFwaV9rZXlcIl0gPSB0aGlzLmNyZWRlbnRpYWxzLmFwaUtleTtcbiAgICAgIHFzW1wiYXBpX3NlY3JldFwiXSA9IHRoaXMuY3JlZGVudGlhbHMuYXBpU2VjcmV0O1xuICAgIH1cblxuICAgIGlmIChPYmplY3Qua2V5cyhxcykubGVuZ3RoKSB7XG4gICAgICBsZXQgam9pbkNoYXIgPSBcIj9cIjtcbiAgICAgIGlmIChwYXRoLmluZGV4T2Yoam9pbkNoYXIpICE9PSAtMSkge1xuICAgICAgICBqb2luQ2hhciA9IFwiJlwiO1xuICAgICAgfVxuICAgICAgcGF0aCA9IHBhdGggKyBqb2luQ2hhciArIHF1ZXJ5c3RyaW5nLnN0cmluZ2lmeShxcyk7XG4gICAgfVxuXG4gICAgY29uc3QgZmlsZSA9IG9wdGlvbnMuZmlsZTtcbiAgICBkZWxldGUgb3B0aW9ucy5maWxlOyAvLyBXZSBkb24ndCBzZW5kIHRoaXMgYXMgbWV0YWRhdGFcblxuICAgIGNvbnN0IGZvcm1EYXRhID0ge307XG5cbiAgICBpZiAoZmlsZSkge1xuICAgICAgZm9ybURhdGFbXCJmaWxlZGF0YVwiXSA9IHtcbiAgICAgICAgdmFsdWU6IGZpbGUsXG4gICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICBmaWxlbmFtZTogb3B0aW9ucy5maWxlbmFtZSB8fCBudWxsXG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMuaW5mbykge1xuICAgICAgZm9ybURhdGEuaW5mbyA9IEpTT04uc3RyaW5naWZ5KG9wdGlvbnMuaW5mbyk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMudXJsKSB7XG4gICAgICBmb3JtRGF0YS51cmwgPSBvcHRpb25zLnVybDtcbiAgICB9XG5cbiAgICB0aGlzLnJlcXVlc3RMaWIucG9zdChcbiAgICAgIHtcbiAgICAgICAgdXJsOiBcImh0dHBzOi8vXCIgKyB0aGlzLmhvc3QgKyBwYXRoLFxuICAgICAgICBmb3JtRGF0YTogZm9ybURhdGEsXG4gICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7dGhpcy5jcmVkZW50aWFscy5nZW5lcmF0ZUp3dCgpfWBcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGNhbGxiYWNrXG4gICAgKTtcbiAgfVxuXG4gIHBvc3QocGF0aCwgcGFyYW1zLCBjYWxsYmFjaywgdXNlSnd0KSB7XG4gICAgbGV0IHFzID0ge307XG4gICAgaWYgKCF1c2VKd3QpIHtcbiAgICAgIHFzW1wiYXBpX2tleVwiXSA9IHRoaXMuY3JlZGVudGlhbHMuYXBpS2V5O1xuICAgICAgcXNbXCJhcGlfc2VjcmV0XCJdID0gdGhpcy5jcmVkZW50aWFscy5hcGlTZWNyZXQ7XG4gICAgfVxuXG4gICAgbGV0IGpvaW5DaGFyID0gXCI/XCI7XG4gICAgaWYgKHBhdGguaW5kZXhPZihqb2luQ2hhcikgIT09IC0xKSB7XG4gICAgICBqb2luQ2hhciA9IFwiJlwiO1xuICAgIH1cblxuICAgIHBhdGggPSBwYXRoICsgam9pbkNoYXIgKyBxdWVyeXN0cmluZy5zdHJpbmdpZnkocXMpO1xuXG4gICAgdGhpcy5yZXF1ZXN0KFxuICAgICAge1xuICAgICAgICBwYXRoOiBwYXRoLFxuICAgICAgICBib2R5OiBxdWVyeXN0cmluZy5zdHJpbmdpZnkocGFyYW1zKVxuICAgICAgfSxcbiAgICAgIFwiUE9TVFwiLFxuICAgICAgY2FsbGJhY2tcbiAgICApO1xuICB9XG5cbiAgcG9zdEpzb24ocGF0aCwgcGFyYW1zLCBjYWxsYmFjaywgdXNlSnd0LCB1c2VCYXNpY0F1dGgpIHtcbiAgICBsZXQgcXMgPSB7fTtcbiAgICBpZiAoIXVzZUp3dCAmJiAhdXNlQmFzaWNBdXRoKSB7XG4gICAgICBxc1tcImFwaV9rZXlcIl0gPSB0aGlzLmNyZWRlbnRpYWxzLmFwaUtleTtcbiAgICAgIHFzW1wiYXBpX3NlY3JldFwiXSA9IHRoaXMuY3JlZGVudGlhbHMuYXBpU2VjcmV0O1xuICAgIH1cblxuICAgIGxldCBqb2luQ2hhciA9IFwiP1wiO1xuICAgIGlmIChwYXRoLmluZGV4T2Yoam9pbkNoYXIpICE9PSAtMSkge1xuICAgICAgam9pbkNoYXIgPSBcIiZcIjtcbiAgICB9XG5cbiAgICBwYXRoID0gcGF0aCArIGpvaW5DaGFyICsgcXVlcnlzdHJpbmcuc3RyaW5naWZ5KHFzKTtcblxuICAgIGxldCBoZWFkZXJzID0ge1xuICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCJcbiAgICB9O1xuICAgIGlmICh1c2VCYXNpY0F1dGgpIHtcbiAgICAgIGhlYWRlcnNbXCJBdXRob3JpemF0aW9uXCJdID0gYEJhc2ljICR7QnVmZmVyLmZyb20oXG4gICAgICAgIHRoaXMuY3JlZGVudGlhbHMuYXBpS2V5ICsgXCI6XCIgKyB0aGlzLmNyZWRlbnRpYWxzLmFwaVNlY3JldFxuICAgICAgKS50b1N0cmluZyhcImJhc2U2NFwiKX1gO1xuICAgIH1cblxuICAgIHRoaXMucmVxdWVzdChcbiAgICAgIHtcbiAgICAgICAgcGF0aDogcGF0aCxcbiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkocGFyYW1zKSxcbiAgICAgICAgaGVhZGVyc1xuICAgICAgfSxcbiAgICAgIFwiUE9TVFwiLFxuICAgICAgY2FsbGJhY2tcbiAgICApO1xuICB9XG5cbiAgcG9zdFVzZVF1ZXJ5U3RyaW5nKHBhdGgsIHBhcmFtcywgY2FsbGJhY2ssIHVzZUp3dCkge1xuICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgICBpZiAoIXVzZUp3dCkge1xuICAgICAgcGFyYW1zW1wiYXBpX2tleVwiXSA9IHRoaXMuY3JlZGVudGlhbHMuYXBpS2V5O1xuICAgICAgcGFyYW1zW1wiYXBpX3NlY3JldFwiXSA9IHRoaXMuY3JlZGVudGlhbHMuYXBpU2VjcmV0O1xuICAgIH1cblxuICAgIHBhdGggPSBwYXRoICsgXCI/XCIgKyBxdWVyeXN0cmluZy5zdHJpbmdpZnkocGFyYW1zKTtcblxuICAgIHRoaXMucmVxdWVzdChcbiAgICAgIHtcbiAgICAgICAgcGF0aDogcGF0aFxuICAgICAgfSxcbiAgICAgIFwiUE9TVFwiLFxuICAgICAgY2FsbGJhY2tcbiAgICApO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEh0dHBDbGllbnQ7XG4iXX0= |
\ | No newline at end of file |