UNPKG

kwikid-components

Version:
284 lines 40.2 kB
import { __awaiter, __decorate } from "tslib"; import { Injectable } from "@angular/core"; import axios from "axios"; import { decryptWithAES, encryptWithAES, isNotEmptyValue, logMethod } from "kwikid-toolkit"; import { Observable } from "rxjs"; import { v4 as uuidv4 } from "uuid"; import * as i0 from "@angular/core"; export class KwikIDApiService { constructor() { this.bytecode = [0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38]; } // Function to derive logic from data dataDerivativeLogic(data) { if (isNotEmptyValue(data)) { const dataString = JSON.stringify(data); const charCounts = {}; const targetCharacters = ["a", "i", "p", "t"]; // Count occurrences of target characters in the data string for (const char of dataString) { if (targetCharacters.includes(char)) { charCounts[char] = (charCounts[char] || 0) + 1; } } // Construct the output string based on the character counts const outputString = targetCharacters .map((char) => char + (charCounts[char] || 0)) .join(""); return outputString; } return undefined; } // Function to preprocess header data preProcessHeader(headerData, isVerifySignature) { if (!headerData) headerData = {}; if (!headerData.headers) headerData.headers = {}; // Generate a unique identifier if signature verification is required if (isVerifySignature) { headerData.headers.xrid = uuidv4(); } // Retrieve session ID from local storage and add it to headers const session_id = localStorage.getItem("session_id"); if (session_id) headerData.headers.ses = session_id; return headerData; } // Function to verify the signature verifySignature(data, header, url, isVerifySignature) { return new Promise((resolve, reject) => { // Check if the signature is disabled if (!isVerifySignature) { resolve(true); } // Check if data is invalid else if (!data) { resolve(true); } // Check if the signature is missing in headers when authentication is not skipped else if (isVerifySignature && header && !(header === null || header === void 0 ? void 0 : header.sig)) { reject(false); } // Verify the signature when public key and header with signature are present and authentication is not skipped else if (isVerifySignature && header && (header === null || header === void 0 ? void 0 : header.sig)) { // Extract the signature and decode it let signature = header.sig.split(".")[0]; const rawSignature = atob(signature); // Split the decoded signature to get the parts signature = rawSignature.split(".")[0]; const exp = `${rawSignature.split(".")[1]}000`; // Expiration time in milliseconds const iat = `${rawSignature.split(".")[2]}000`; // Issued at time in milliseconds // Check if the signature is valid if (signature) { // Check if the current time is before the expiration time const dateValue = new Date().valueOf(); const dateCheck = dateValue < parseInt(exp); // Check if the signature matches the data const res = signature === data; // Resolve the promise if the signature is valid and the date check passes if (res && dateCheck) { resolve(res); } else { // Reject the promise if the signature is invalid or the date check fails reject(res); } } else { // Reject the promise if the signature is not in the required format reject(false); } } else { // Resolve the promise if the signature is missing in headers resolve(true); } }); } // Function to perform POST request post(url, body, headerData, isEncrypt = false, isDecrypt = false, isVerifySignature = false, isSkipHeaderAlteration = false) { let preProcessedHeader = headerData; // Preprocess header data unless instructed to skip if (!isSkipHeaderAlteration) { preProcessedHeader = this.preProcessHeader(headerData, isVerifySignature); } else { preProcessedHeader.observe = "response"; } // Encrypt body if required if (isEncrypt) { body = encryptWithAES(JSON.stringify(body)); } return new Observable((subscriber) => { axios.post(url, body, headerData).then((res) => __awaiter(this, void 0, void 0, function* () { var _a; let { data } = res; // Decrypt response if required if (data && isDecrypt) { const encryptedResponse = data; const decryptedResponse = yield decryptWithAES(encryptedResponse); data = JSON.parse(decryptedResponse); res.data = data; } if (!res.data) { res.data = {}; } res.data.statusCode = (_a = res.status) !== null && _a !== void 0 ? _a : 200; // Verify signature and handle response this.verifySignature(this.dataDerivativeLogic(data), res === null || res === void 0 ? void 0 : res.headers, url, isVerifySignature) .then((verification) => { subscriber.next(res === null || res === void 0 ? void 0 : res.data); subscriber.complete(); }) .catch((err) => { var _a; subscriber.error((_a = err === null || err === void 0 ? void 0 : err.response) === null || _a === void 0 ? void 0 : _a.data); }); }), (err) => __awaiter(this, void 0, void 0, function* () { var _b, _c, _d, _e; let data = (_b = err === null || err === void 0 ? void 0 : err.response) === null || _b === void 0 ? void 0 : _b.data; // Decrypt error response if required if (data && isDecrypt) { const encryptedResponse = data; const decryptedResponse = yield decryptWithAES(encryptedResponse); data = JSON.parse(decryptedResponse); err.response.data = data; } const statusCode = (_d = (_c = err === null || err === void 0 ? void 0 : err.response) === null || _c === void 0 ? void 0 : _c.status) !== null && _d !== void 0 ? _d : 404; if (!err) { err = {}; } if (!err.response) { err.response = {}; } if (!err.response.data) { err.response.data = {}; } err.response.data.statusCode = statusCode; // Verify signature and handle response this.verifySignature(this.dataDerivativeLogic(data), (_e = err === null || err === void 0 ? void 0 : err.response) === null || _e === void 0 ? void 0 : _e.headers, url, isVerifySignature) .then((verification) => { var _a; subscriber.error((_a = err === null || err === void 0 ? void 0 : err.response) === null || _a === void 0 ? void 0 : _a.data); }) .catch((err) => { var _a; subscriber.error((_a = err === null || err === void 0 ? void 0 : err.response) === null || _a === void 0 ? void 0 : _a.data); }); })); }); } // Function to perform GET request get(url, headerData = undefined, isDecrypt = false, isVerifySignature = false, isSkipHeaderAlteration = false) { let preProcessedHeader = headerData; // Preprocess header data unless instructed to skip if (!isSkipHeaderAlteration) { preProcessedHeader = this.preProcessHeader(headerData, isVerifySignature); } else { preProcessedHeader.observe = "response"; } return new Observable((subscriber) => { axios.get(url, preProcessedHeader).then((res) => __awaiter(this, void 0, void 0, function* () { var _a; let { data } = res; // Decrypt response if required if (isDecrypt) { const encryptedResponse = data; const decryptedResponse = yield decryptWithAES(encryptedResponse); data = JSON.parse(decryptedResponse); res.data = data; } if (!res.data) { res.data = {}; } res.data.statusCode = (_a = res.status) !== null && _a !== void 0 ? _a : 200; // Verify signature and handle response this.verifySignature(this.dataDerivativeLogic(data), res === null || res === void 0 ? void 0 : res.headers, url, isVerifySignature) .then((verification) => { subscriber.next(res === null || res === void 0 ? void 0 : res.data); subscriber.complete(); }) .catch((err) => { var _a; subscriber.error((_a = err === null || err === void 0 ? void 0 : err.response) === null || _a === void 0 ? void 0 : _a.data); }); }), (err) => __awaiter(this, void 0, void 0, function* () { var _b, _c, _d, _e; let data = (_b = err === null || err === void 0 ? void 0 : err.response) === null || _b === void 0 ? void 0 : _b.data; // Decrypt error response if required if (data && isDecrypt) { const encryptedResponse = data; const decryptedResponse = yield decryptWithAES(encryptedResponse); data = JSON.parse(decryptedResponse); err.response.data = data; } const statusCode = (_d = (_c = err === null || err === void 0 ? void 0 : err.response) === null || _c === void 0 ? void 0 : _c.status) !== null && _d !== void 0 ? _d : 404; if (!err) { err = {}; } if (!err.response) { err.response = {}; } if (!err.response.data) { err.response.data = {}; } err.response.data.statusCode = statusCode; // Verify signature and handle response this.verifySignature(this.dataDerivativeLogic(data), (_e = err === null || err === void 0 ? void 0 : err.response) === null || _e === void 0 ? void 0 : _e.headers, url, isVerifySignature) .then((verification) => { var _a; subscriber.error((_a = err === null || err === void 0 ? void 0 : err.response) === null || _a === void 0 ? void 0 : _a.data); }) .catch((err) => { var _a; subscriber.error((_a = err === null || err === void 0 ? void 0 : err.response) === null || _a === void 0 ? void 0 : _a.data); }); })); }); } // Function to execute API call based on method type executeApiCall(url, method, body, headers, isEncrypt, isDecrypt, isVerifySignature) { return new Promise((resolve) => { if (method == "GET") { this.get(url, { headers }, isDecrypt, isVerifySignature).subscribe((res) => { resolve(res); }, (err) => { resolve(err); }); } else { this.post(url, body, { headers }, isEncrypt, isDecrypt, isVerifySignature).subscribe((res) => { resolve(res); }, (err) => { resolve(err); }); } }); } } /** @nocollapse */ KwikIDApiService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: KwikIDApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); /** @nocollapse */ KwikIDApiService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: KwikIDApiService, providedIn: "root" }); __decorate([ logMethod ], KwikIDApiService.prototype, "dataDerivativeLogic", null); __decorate([ logMethod ], KwikIDApiService.prototype, "preProcessHeader", null); __decorate([ logMethod ], KwikIDApiService.prototype, "verifySignature", null); __decorate([ logMethod ], KwikIDApiService.prototype, "post", null); __decorate([ logMethod ], KwikIDApiService.prototype, "get", null); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: KwikIDApiService, decorators: [{ type: Injectable, args: [{ providedIn: "root" }] }], ctorParameters: function () { return []; }, propDecorators: { dataDerivativeLogic: [], preProcessHeader: [], verifySignature: [], post: [], get: [] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBpLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9rd2lraWQtY29tcG9uZW50cy9zcmMvbGliL3NlcnZpY2VzL2FwaS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUMxQixPQUFPLEVBQ0wsY0FBYyxFQUNkLGNBQWMsRUFDZCxlQUFlLEVBQ2YsU0FBUyxFQUNWLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNsQyxPQUFPLEVBQUUsRUFBRSxJQUFJLE1BQU0sRUFBRSxNQUFNLE1BQU0sQ0FBQzs7QUFLcEMsTUFBTSxPQUFPLGdCQUFnQjtJQUczQjtRQUZRLGFBQVEsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztJQUVyRCxDQUFDO0lBRWhCLHFDQUFxQztJQUVyQyxtQkFBbUIsQ0FBQyxJQUFJO1FBQ3RCLElBQUksZUFBZSxDQUFDLElBQUksQ0FBQyxFQUFFO1lBQ3pCLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDeEMsTUFBTSxVQUFVLEdBQUcsRUFBRSxDQUFDO1lBQ3RCLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUU5Qyw0REFBNEQ7WUFDNUQsS0FBSyxNQUFNLElBQUksSUFBSSxVQUFVLEVBQUU7Z0JBQzdCLElBQUksZ0JBQWdCLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFO29CQUNuQyxVQUFVLENBQUMsSUFBSSxD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SCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7O2lJQWxWVSxnQkFBZ0I7cUlBQWhCLGdCQUFnQixjQUZmLE1BQU07QUFTbEI7SUFEQyxTQUFTOzJEQXFCVDtBQUlEO0lBREMsU0FBUzt3REFlVDtBQUlEO0lBREMsU0FBUzt1REF1RFQ7QUFJRDtJQURDLFNBQVM7NENBa0dUO0FBSUQ7SUFEQyxTQUFTOzJDQTJGVDs0RkExU1UsZ0JBQWdCO2tCQUg1QixVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNO2lCQUNuQjswRUFRQyxtQkFBbUIsTUF3Qm5CLGdCQUFnQixNQWtCaEIsZUFBZSxNQTBEZixJQUFJLE1BcUdKLEdBQUciLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCBheGlvcyBmcm9tIFwiYXhpb3NcIjtcbmltcG9ydCB7XG4gIGRlY3J5cHRXaXRoQUVTLFxuICBlbmNyeXB0V2l0aEFFUyxcbiAgaXNOb3RFbXB0eVZhbHVlLFxuICBsb2dNZXRob2Rcbn0gZnJvbSBcImt3aWtpZC10b29sa2l0XCI7XG5pbXBvcnQgeyBPYnNlcnZhYmxlIH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7IHY0IGFzIHV1aWR2NCB9IGZyb20gXCJ1dWlkXCI7XG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogXCJyb290XCJcbn0pXG5leHBvcnQgY2xhc3MgS3dpa0lEQXBpU2VydmljZSB7XG4gIHByaXZhdGUgYnl0ZWNvZGUgPSBbMHgzOCwgMHgzOCwgMHgzOCwgMHgzOCwgMHgzOCwgMHgzOCwgMHgzOCwgMHgzOF07XG5cbiAgY29uc3RydWN0b3IoKSB7fVxuXG4gIC8vIEZ1bmN0aW9uIHRvIGRlcml2ZSBsb2dpYyBmcm9tIGRhdGFcbiAgQGxvZ01ldGhvZFxuICBkYXRhRGVyaXZhdGl2ZUxvZ2ljKGRhdGEpIHtcbiAgICBpZiAoaXNOb3RFbXB0eVZhbHVlKGRhdGEpKSB7XG4gICAgICBjb25zdCBkYXRhU3RyaW5nID0gSlNPTi5zdHJpbmdpZnkoZGF0YSk7XG4gICAgICBjb25zdCBjaGFyQ291bnRzID0ge307XG4gICAgICBjb25zdCB0YXJnZXRDaGFyYWN0ZXJzID0gW1wiYVwiLCBcImlcIiwgXCJwXCIsIFwidFwiXTtcblxuICAgICAgLy8gQ291bnQgb2NjdXJyZW5jZXMgb2YgdGFyZ2V0IGNoYXJhY3RlcnMgaW4gdGhlIGRhdGEgc3RyaW5nXG4gICAgICBmb3IgKGNvbnN0IGNoYXIgb2YgZGF0YVN0cmluZykge1xuICAgICAgICBpZiAodGFyZ2V0Q2hhcmFjdGVycy5pbmNsdWRlcyhjaGFyKSkge1xuICAgICAgICAgIGNoYXJDb3VudHNbY2hhcl0gPSAoY2hhckNvdW50c1tjaGFyXSB8fCAwKSArIDE7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gQ29uc3RydWN0IHRoZSBvdXRwdXQgc3RyaW5nIGJhc2VkIG9uIHRoZSBjaGFyYWN0ZXIgY291bnRzXG4gICAgICBjb25zdCBvdXRwdXRTdHJpbmcgPSB0YXJnZXRDaGFyYWN0ZXJzXG4gICAgICAgIC5tYXAoKGNoYXIpID0+IGNoYXIgKyAoY2hhckNvdW50c1tjaGFyXSB8fCAwKSlcbiAgICAgICAgLmpvaW4oXCJcIik7XG4gICAgICByZXR1cm4gb3V0cHV0U3RyaW5nO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLy8gRnVuY3Rpb24gdG8gcHJlcHJvY2VzcyBoZWFkZXIgZGF0YVxuICBAbG9nTWV0aG9kXG4gIHByZVByb2Nlc3NIZWFkZXIoaGVhZGVyRGF0YTogYW55LCBpc1ZlcmlmeVNpZ25hdHVyZTogYm9vbGVhbik6IGFueSB7XG4gICAgaWYgKCFoZWFkZXJEYXRhKSBoZWFkZXJEYXRhID0ge307XG4gICAgaWYgKCFoZWFkZXJEYXRhLmhlYWRlcnMpIGhlYWRlckRhdGEuaGVhZGVycyA9IHt9O1xuXG4gICAgLy8gR2VuZXJhdGUgYSB1bmlxdWUgaWRlbnRpZmllciBpZiBzaWduYXR1cmUgdmVyaWZpY2F0aW9uIGlzIHJlcXVpcmVkXG4gICAgaWYgKGlzVmVyaWZ5U2lnbmF0dXJlKSB7XG4gICAgICBoZWFkZXJEYXRhLmhlYWRlcnMueHJpZCA9IHV1aWR2NCgpO1xuICAgIH1cblxuICAgIC8vIFJldHJpZXZlIHNlc3Npb24gSUQgZnJvbSBsb2NhbCBzdG9yYWdlIGFuZCBhZGQgaXQgdG8gaGVhZGVyc1xuICAgIGNvbnN0IHNlc3Npb25faWQgPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbShcInNlc3Npb25faWRcIik7XG4gICAgaWYgKHNlc3Npb25faWQpIGhlYWRlckRhdGEuaGVhZGVycy5zZXMgPSBzZXNzaW9uX2lkO1xuXG4gICAgcmV0dXJuIGhlYWRlckRhdGE7XG4gIH1cblxuICAvLyBGdW5jdGlvbiB0byB2ZXJpZnkgdGhlIHNpZ25hdHVyZVxuICBAbG9nTWV0aG9kXG4gIHZlcmlmeVNpZ25hdHVyZShkYXRhLCBoZWFkZXIsIHVybCwgaXNWZXJpZnlTaWduYXR1cmUpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgLy8gQ2hlY2sgaWYgdGhlIHNpZ25hdHVyZSBpcyBkaXNhYmxlZFxuICAgICAgaWYgKCFpc1ZlcmlmeVNpZ25hdHVyZSkge1xuICAgICAgICByZXNvbHZlKHRydWUpO1xuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayBpZiBkYXRhIGlzIGludmFsaWRcbiAgICAgIGVsc2UgaWYgKCFkYXRhKSB7XG4gICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICB9XG5cbiAgICAgIC8vIENoZWNrIGlmIHRoZSBzaWduYXR1cmUgaXMgbWlzc2luZyBpbiBoZWFkZXJzIHdoZW4gYXV0aGVudGljYXRpb24gaXMgbm90IHNraXBwZWRcbiAgICAgIGVsc2UgaWYgKGlzVmVyaWZ5U2lnbmF0dXJlICYmIGhlYWRlciAmJiAhaGVhZGVyPy5zaWcpIHtcbiAgICAgICAgcmVqZWN0KGZhbHNlKTtcbiAgICAgIH1cblxuICAgICAgLy8gVmVyaWZ5IHRoZSBzaWduYXR1cmUgd2hlbiBwdWJsaWMga2V5IGFuZCBoZWFkZXIgd2l0aCBzaWduYXR1cmUgYXJlIHByZXNlbnQgYW5kIGF1dGhlbnRpY2F0aW9uIGlzIG5vdCBza2lwcGVkXG4gICAgICBlbHNlIGlmIChpc1ZlcmlmeVNpZ25hdHVyZSAmJiBoZWFkZXIgJiYgaGVhZGVyPy5zaWcpIHtcbiAgICAgICAgLy8gRXh0cmFjdCB0aGUgc2lnbmF0dXJlIGFuZCBkZWNvZGUgaXRcbiAgICAgICAgbGV0IHNpZ25hdHVyZSA9IGhlYWRlci5zaWcuc3BsaXQoXCIuXCIpWzBdO1xuICAgICAgICBjb25zdCByYXdTaWduYXR1cmUgPSBhdG9iKHNpZ25hdHVyZSk7XG5cbiAgICAgICAgLy8gU3BsaXQgdGhlIGRlY29kZWQgc2lnbmF0dXJlIHRvIGdldCB0aGUgcGFydHNcbiAgICAgICAgc2lnbmF0dXJlID0gcmF3U2lnbmF0dXJlLnNwbGl0KFwiLlwiKVswXTtcbiAgICAgICAgY29uc3QgZXhwID0gYCR7cmF3U2lnbmF0dXJlLnNwbGl0KFwiLlwiKVsxXX0wMDBgOyAvLyBFeHBpcmF0aW9uIHRpbWUgaW4gbWlsbGlzZWNvbmRzXG4gICAgICAgIGNvbnN0IGlhdCA9IGAke3Jhd1NpZ25hdHVyZS5zcGxpdChcIi5cIilbMl19MDAwYDsgLy8gSXNzdWVkIGF0IHRpbWUgaW4gbWlsbGlzZWNvbmRzXG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIHNpZ25hdHVyZSBpcyB2YWxpZFxuICAgICAgICBpZiAoc2lnbmF0dXJlKSB7XG4gICAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIGN1cnJlbnQgdGltZSBpcyBiZWZvcmUgdGhlIGV4cGlyYXRpb24gdGltZVxuICAgICAgICAgIGNvbnN0IGRhdGVWYWx1ZSA9IG5ldyBEYXRlKCkudmFsdWVPZigpO1xuICAgICAgICAgIGNvbnN0IGRhdGVDaGVjayA9IGRhdGVWYWx1ZSA8IHBhcnNlSW50KGV4cCk7XG5cbiAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgc2lnbmF0dXJlIG1hdGNoZXMgdGhlIGRhdGFcbiAgICAgICAgICBjb25zdCByZXMgPSBzaWduYXR1cmUgPT09IGRhdGE7XG5cbiAgICAgICAgICAvLyBSZXNvbHZlIHRoZSBwcm9taXNlIGlmIHRoZSBzaWduYXR1cmUgaXMgdmFsaWQgYW5kIHRoZSBkYXRlIGNoZWNrIHBhc3Nlc1xuICAgICAgICAgIGlmIChyZXMgJiYgZGF0ZUNoZWNrKSB7XG4gICAgICAgICAgICByZXNvbHZlKHJlcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJlamVjdCB0aGUgcHJvbWlzZSBpZiB0aGUgc2lnbmF0dXJlIGlzIGludmFsaWQgb3IgdGhlIGRhdGUgY2hlY2sgZmFpbHNcbiAgICAgICAgICAgIHJlamVjdChyZXMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBSZWplY3QgdGhlIHByb21pc2UgaWYgdGhlIHNpZ25hdHVyZSBpcyBub3QgaW4gdGhlIHJlcXVpcmVkIGZvcm1hdFxuXG4gICAgICAgICAgcmVqZWN0KGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gUmVzb2x2ZSB0aGUgcHJvbWlzZSBpZiB0aGUgc2lnbmF0dXJlIGlzIG1pc3NpbmcgaW4gaGVhZGVyc1xuICAgICAgICByZXNvbHZlKHRydWUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gRnVuY3Rpb24gdG8gcGVyZm9ybSBQT1NUIHJlcXVlc3RcbiAgQGxvZ01ldGhvZFxuICBwb3N0KFxuICAgIHVybCxcbiAgICBib2R5LFxuICAgIGhlYWRlckRhdGEsXG4gICAgaXNFbmNyeXB0ID0gZmFsc2UsXG4gICAgaXNEZWNyeXB0ID0gZmFsc2UsXG4gICAgaXNWZXJpZnlTaWduYXR1cmUgPSBmYWxzZSxcbiAgICBpc1NraXBIZWFkZXJBbHRlcmF0aW9uID0gZmFsc2VcbiAgKSB7XG4gICAgbGV0IHByZVByb2Nlc3NlZEhlYWRlciA9IGhlYWRlckRhdGE7XG5cbiAgICAvLyBQcmVwcm9jZXNzIGhlYWRlciBkYXRhIHVubGVzcyBpbnN0cnVjdGVkIHRvIHNraXBcbiAgICBpZiAoIWlzU2tpcEhlYWRlckFsdGVyYXRpb24pIHtcbiAgICAgIHByZVByb2Nlc3NlZEhlYWRlciA9IHRoaXMucHJlUHJvY2Vzc0hlYWRlcihoZWFkZXJEYXRhLCBpc1ZlcmlmeVNpZ25hdHVyZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHByZVByb2Nlc3NlZEhlYWRlci5vYnNlcnZlID0gXCJyZXNwb25zZVwiO1xuICAgIH1cblxuICAgIC8vIEVuY3J5cHQgYm9keSBpZiByZXF1aXJlZFxuICAgIGlmIChpc0VuY3J5cHQpIHtcbiAgICAgIGJvZHkgPSBlbmNyeXB0V2l0aEFFUyhKU09OLnN0cmluZ2lmeShib2R5KSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlKChzdWJzY3JpYmVyKSA9PiB7XG4gICAgICBheGlvcy5wb3N0KHVybCwgYm9keSwgaGVhZGVyRGF0YSkudGhlbihcbiAgICAgICAgYXN5bmMocmVzKSA9PiB7XG4gICAgICAgICAgbGV0IHsgZGF0YSB9ID0gcmVzO1xuXG4gICAgICAgICAgLy8gRGVjcnlwdCByZXNwb25zZSBpZiByZXF1aXJlZFxuICAgICAgICAgIGlmIChkYXRhICYmIGlzRGVjcnlwdCkge1xuICAgICAgICAgICAgY29uc3QgZW5jcnlwdGVkUmVzcG9uc2UgPSBkYXRhO1xuICAgICAgICAgICAgY29uc3QgZGVjcnlwdGVkUmVzcG9uc2UgPSBhd2FpdCBkZWNyeXB0V2l0aEFFUyhlbmNyeXB0ZWRSZXNwb25zZSk7XG4gICAgICAgICAgICBkYXRhID0gSlNPTi5wYXJzZShkZWNyeXB0ZWRSZXNwb25zZSk7XG4gICAgICAgICAgICByZXMuZGF0YSA9IGRhdGE7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFyZXMuZGF0YSkge1xuICAgICAgICAgICAgcmVzLmRhdGEgPSB7fTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzLmRhdGEuc3RhdHVzQ29kZSA9IHJlcy5zdGF0dXMgPz8gMjAwO1xuXG4gICAgICAgICAgLy8gVmVyaWZ5IHNpZ25hdHVyZSBhbmQgaGFuZGxlIHJlc3BvbnNlXG4gICAgICAgICAgdGhpcy52ZXJpZnlTaWduYXR1cmUoXG4gICAgICAgICAgICB0aGlzLmRhdGFEZXJpdmF0aXZlTG9naWMoZGF0YSksXG4gICAgICAgICAgICByZXM/LmhlYWRlcnMsXG4gICAgICAgICAgICB1cmwsXG4gICAgICAgICAgICBpc1ZlcmlmeVNpZ25hdHVyZVxuICAgICAgICAgIClcbiAgICAgICAgICAgIC50aGVuKCh2ZXJpZmljYXRpb24pID0+IHtcbiAgICAgICAgICAgICAgc3Vic2NyaWJlci5uZXh0KHJlcz8uZGF0YSk7XG4gICAgICAgICAgICAgIHN1YnNjcmliZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgICAgICBzdWJzY3JpYmVyLmVycm9yKGVycj8ucmVzcG9uc2U/LmRhdGEpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIGFzeW5jKGVycikgPT4ge1xuICAgICAgICAgIGxldCBkYXRhID0gZXJyPy5yZXNwb25zZT8uZGF0YTtcblxuICAgICAgICAgIC8vIERlY3J5cHQgZXJyb3IgcmVzcG9uc2UgaWYgcmVxdWlyZWRcbiAgICAgICAgICBpZiAoZGF0YSAmJiBpc0RlY3J5cHQpIHtcbiAgICAgICAgICAgIGNvbnN0IGVuY3J5cHRlZFJlc3BvbnNlID0gZGF0YTtcbiAgICAgICAgICAgIGNvbnN0IGRlY3J5cHRlZFJlc3BvbnNlID0gYXdhaXQgZGVjcnlwdFdpdGhBRVMoZW5jcnlwdGVkUmVzcG9uc2UpO1xuICAgICAgICAgICAgZGF0YSA9IEpTT04ucGFyc2UoZGVjcnlwdGVkUmVzcG9uc2UpO1xuICAgICAgICAgICAgZXJyLnJlc3BvbnNlLmRhdGEgPSBkYXRhO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHN0YXR1c0NvZGUgPSBlcnI/LnJlc3BvbnNlPy5zdGF0dXMgPz8gNDA0O1xuXG4gICAgICAgICAgaWYgKCFlcnIpIHtcbiAgICAgICAgICAgIGVyciA9IHt9O1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIWVyci5yZXNwb25zZSkge1xuICAgICAgICAgICAgZXJyLnJlc3BvbnNlID0ge307XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghZXJyLnJlc3BvbnNlLmRhdGEpIHtcbiAgICAgICAgICAgIGVyci5yZXNwb25zZS5kYXRhID0ge307XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZXJyLnJlc3BvbnNlLmRhdGEuc3RhdHVzQ29kZSA9IHN0YXR1c0NvZGU7XG5cbiAgICAgICAgICAvLyBWZXJpZnkgc2lnbmF0dXJlIGFuZCBoYW5kbGUgcmVzcG9uc2VcbiAgICAgICAgICB0aGlzLnZlcmlmeVNpZ25hdHVyZShcbiAgICAgICAgICAgIHRoaXMuZGF0YURlcml2YXRpdmVMb2dpYyhkYXRhKSxcbiAgICAgICAgICAgIGVycj8ucmVzcG9uc2U/LmhlYWRlcnMsXG4gICAgICAgICAgICB1cmwsXG4gICAgICAgICAgICBpc1ZlcmlmeVNpZ25hdHVyZVxuICAgICAgICAgIClcbiAgICAgICAgICAgIC50aGVuKCh2ZXJpZmljYXRpb24pID0+IHtcbiAgICAgICAgICAgICAgc3Vic2NyaWJlci5lcnJvcihlcnI/LnJlc3BvbnNlPy5kYXRhKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgICAgICBzdWJzY3JpYmVyLmVycm9yKGVycj8ucmVzcG9uc2U/LmRhdGEpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICAvLyBGdW5jdGlvbiB0byBwZXJmb3JtIEdFVCByZXF1ZXN0XG4gIEBsb2dNZXRob2RcbiAgZ2V0KFxuICAgIHVybCxcbiAgICBoZWFkZXJEYXRhID0gdW5kZWZpbmVkLFxuICAgIGlzRGVjcnlwdCA9IGZhbHNlLFxuICAgIGlzVmVyaWZ5U2lnbmF0dXJlID0gZmFsc2UsXG4gICAgaXNTa2lwSGVhZGVyQWx0ZXJhdGlvbiA9IGZhbHNlXG4gICkge1xuICAgIGxldCBwcmVQcm9jZXNzZWRIZWFkZXIgPSBoZWFkZXJEYXRhO1xuXG4gICAgLy8gUHJlcHJvY2VzcyBoZWFkZXIgZGF0YSB1bmxlc3MgaW5zdHJ1Y3RlZCB0byBza2lwXG4gICAgaWYgKCFpc1NraXBIZWFkZXJBbHRlcmF0aW9uKSB7XG4gICAgICBwcmVQcm9jZXNzZWRIZWFkZXIgPSB0aGlzLnByZVByb2Nlc3NIZWFkZXIoaGVhZGVyRGF0YSwgaXNWZXJpZnlTaWduYXR1cmUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcmVQcm9jZXNzZWRIZWFkZXIub2JzZXJ2ZSA9IFwicmVzcG9uc2VcIjtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKHN1YnNjcmliZXIpID0+IHtcbiAgICAgIGF4aW9zLmdldCh1cmwsIHByZVByb2Nlc3NlZEhlYWRlcikudGhlbihcbiAgICAgICAgYXN5bmMocmVzOiBhbnkpID0+IHtcbiAgICAgICAgICBsZXQgeyBkYXRhIH0gPSByZXM7XG5cbiAgICAgICAgICAvLyBEZWNyeXB0IHJlc3BvbnNlIGlmIHJlcXVpcmVkXG4gICAgICAgICAgaWYgKGlzRGVjcnlwdCkge1xuICAgICAgICAgICAgY29uc3QgZW5jcnlwdGVkUmVzcG9uc2UgPSBkYXRhO1xuICAgICAgICAgICAgY29uc3QgZGVjcnlwdGVkUmVzcG9uc2UgPSBhd2FpdCBkZWNyeXB0V2l0aEFFUyhlbmNyeXB0ZWRSZXNwb25zZSk7XG4gICAgICAgICAgICBkYXRhID0gSlNPTi5wYXJzZShkZWNyeXB0ZWRSZXNwb25zZSk7XG4gICAgICAgICAgICByZXMuZGF0YSA9IGRhdGE7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFyZXMuZGF0YSkge1xuICAgICAgICAgICAgcmVzLmRhdGEgPSB7fTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzLmRhdGEuc3RhdHVzQ29kZSA9IHJlcy5zdGF0dXMgPz8gMjAwO1xuXG4gICAgICAgICAgLy8gVmVyaWZ5IHNpZ25hdHVyZSBhbmQgaGFuZGxlIHJlc3BvbnNlXG4gICAgICAgICAgdGhpcy52ZXJpZnlTaWduYXR1cmUoXG4gICAgICAgICAgICB0aGlzLmRhdGFEZXJpdmF0aXZlTG9naWMoZGF0YSksXG4gICAgICAgICAgICByZXM/LmhlYWRlcnMsXG4gICAgICAgICAgICB1cmwsXG4gICAgICAgICAgICBpc1ZlcmlmeVNpZ25hdHVyZVxuICAgICAgICAgIClcbiAgICAgICAgICAgIC50aGVuKCh2ZXJpZmljYXRpb24pID0+IHtcbiAgICAgICAgICAgICAgc3Vic2NyaWJlci5uZXh0KHJlcz8uZGF0YSk7XG4gICAgICAgICAgICAgIHN1YnNjcmliZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgICAgICBzdWJzY3JpYmVyLmVycm9yKGVycj8ucmVzcG9uc2U/LmRhdGEpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIGFzeW5jKGVycikgPT4ge1xuICAgICAgICAgIGxldCBkYXRhID0gZXJyPy5yZXNwb25zZT8uZGF0YTtcblxuICAgICAgICAgIC8vIERlY3J5cHQgZXJyb3IgcmVzcG9uc2UgaWYgcmVxdWlyZWRcbiAgICAgICAgICBpZiAoZGF0YSAmJiBpc0RlY3J5cHQpIHtcbiAgICAgICAgICAgIGNvbnN0IGVuY3J5cHRlZFJlc3BvbnNlID0gZGF0YTtcbiAgICAgICAgICAgIGNvbnN0IGRlY3J5cHRlZFJlc3BvbnNlID0gYXdhaXQgZGVjcnlwdFdpdGhBRVMoZW5jcnlwdGVkUmVzcG9uc2UpO1xuICAgICAgICAgICAgZGF0YSA9IEpTT04ucGFyc2UoZGVjcnlwdGVkUmVzcG9uc2UpO1xuICAgICAgICAgICAgZXJyLnJlc3BvbnNlLmRhdGEgPSBkYXRhO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHN0YXR1c0NvZGUgPSBlcnI/LnJlc3BvbnNlPy5zdGF0dXMgPz8gNDA0O1xuXG4gICAgICAgICAgaWYgKCFlcnIpIHtcbiAgICAgICAgICAgIGVyciA9IHt9O1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIWVyci5yZXNwb25zZSkge1xuICAgICAgICAgICAgZXJyLnJlc3BvbnNlID0ge307XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghZXJyLnJlc3BvbnNlLmRhdGEpIHtcbiAgICAgICAgICAgIGVyci5yZXNwb25zZS5kYXRhID0ge307XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZXJyLnJlc3BvbnNlLmRhdGEuc3RhdHVzQ29kZSA9IHN0YXR1c0NvZGU7XG5cbiAgICAgICAgICAvLyBWZXJpZnkgc2lnbmF0dXJlIGFuZCBoYW5kbGUgcmVzcG9uc2VcbiAgICAgICAgICB0aGlzLnZlcmlmeVNpZ25hdHVyZShcbiAgICAgICAgICAgIHRoaXMuZGF0YURlcml2YXRpdmVMb2dpYyhkYXRhKSxcbiAgICAgICAgICAgIGVycj8ucmVzcG9uc2U/LmhlYWRlcnMsXG4gICAgICAgICAgICB1cmwsXG4gICAgICAgICAgICBpc1ZlcmlmeVNpZ25hdHVyZVxuICAgICAgICAgIClcbiAgICAgICAgICAgIC50aGVuKCh2ZXJpZmljYXRpb24pID0+IHtcbiAgICAgICAgICAgICAgc3Vic2NyaWJlci5lcnJvcihlcnI/LnJlc3BvbnNlPy5kYXRhKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgICAgICBzdWJzY3JpYmVyLmVycm9yKGVycj8ucmVzcG9uc2U/LmRhdGEpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICAvLyBGdW5jdGlvbiB0byBleGVjdXRlIEFQSSBjYWxsIGJhc2VkIG9uIG1ldGhvZCB0eXBlXG4gIGV4ZWN1dGVBcGlDYWxsKFxuICAgIHVybCxcbiAgICBtZXRob2QsXG4gICAgYm9keSxcbiAgICBoZWFkZXJzLFxuICAgIGlzRW5jcnlwdCxcbiAgICBpc0RlY3J5cHQsXG4gICAgaXNWZXJpZnlTaWduYXR1cmVcbiAgKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICBpZiAobWV0aG9kID09IFwiR0VUXCIpIHtcbiAgICAgICAgdGhpcy5nZXQodXJsLCB7IGhlYWRlcnMgfSwgaXNEZWNyeXB0LCBpc1ZlcmlmeVNpZ25hdHVyZSkuc3Vic2NyaWJlKFxuICAgICAgICAgIChyZXM6IGFueSkgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZShyZXMpO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgKGVycikgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZShlcnIpO1xuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucG9zdChcbiAgICAgICAgICB1cmwsXG4gICAgICAgICAgYm9keSxcbiAgICAgICAgICB7IGhlYWRlcnMgfSxcbiAgICAgICAgICBpc0VuY3J5cHQsXG4gICAgICAgICAgaXNEZWNyeXB0LFxuICAgICAgICAgIGlzVmVyaWZ5U2lnbmF0dXJlXG4gICAgICAgICkuc3Vic2NyaWJlKFxuICAgICAgICAgIChyZXM6IGFueSkgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZShyZXMpO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgKGVycikgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZShlcnIpO1xuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuIl19