UNPKG

ng-smart-on-fhir

Version:

[![SRDC](https://www.srdc.com.tr/wp-content/uploads/2014/12/srdc-wp.png)](https://srdc.com.tr/en)

142 lines 21.1 kB
import { Injectable } from '@angular/core'; import { firstValueFrom } from "rxjs"; import * as jose from 'jose'; import * as pako from 'pako'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common/http"; /** * SMART Health Link Service * Executes the requests, parses and validates SMART Health Links as defined in the HL7 documentations */ export class ShlService { get emptyBundle() { return { resourceType: 'Bundle', type: 'document', entry: [] }; } constructor(http) { this.http = http; } async handleShl(shl) { if (shl.startsWith('shlink:/')) { shl = shl.slice('shlink:/'.length); } const metadata = JSON.parse(atob(shl)); if (!metadata.url) { throw new Error('URL is missing in SMART Health Link'); } let payload; if (metadata.flag?.includes('U')) { payload = await firstValueFrom(this.http.get(metadata.url + '?recipient=' + window.location.origin)) .then((data) => data.files.filter((file) => file.contentType === 'application/smart-health-card' && file.embedded).map((file) => file.embedded)); } else { let passcode; if (metadata.flag?.includes('P')) { passcode = prompt('Enter the passcode for SMART Health Link'); } payload = await firstValueFrom(this.http.post(metadata.url, { recipient: window.location.origin, passcode })).then(async (data) => { const embedded = data.files.filter((file) => file.contentType === 'application/smart-health-card' && file.embedded).map((file) => file.embedded); const links = data.files.filter((file) => file.contentType === 'application/fhir+json' && file.location); const requests = links.map((file) => firstValueFrom(this.http.get(file.location, { responseType: 'text' }))); const linkedCards = await Promise.all(requests); return [...embedded, ...linkedCards]; }); } if (!payload) { throw new Error('Cannot get SMART Health Link content.'); } const shcs = await this.decryptSHLPayloadAndGetSHCs(payload, metadata.key); const bundles = await Promise.all(shcs.map(shc => this.getSingleBundle(shc))); return { label: metadata.label, shc: shcs, verified: await Promise.all(shcs.map(_shc => this.verifyShc(_shc))).then(results => results.every(value => value)), bundle: Object.assign(this.emptyBundle, { entry: bundles.filter(_ => _).map(bundle => bundle.entry).reduce((arr, entries) => arr.concat(entries), []) }) }; } async decryptSHLPayloadAndGetSHCs(payload, key) { const SHCs = []; for (const encrypted of payload) { const data = await jose.compactDecrypt(encrypted, jose.base64url.decode(key)); SHCs.push(...JSON.parse(new TextDecoder().decode(data.plaintext)).verifiableCredential); } return SHCs; } async handleShc(shc) { if (shc.startsWith('shc:/')) { shc = shc.slice('shc:/'.length); } return { shc: [shc], bundle: await this.getSingleBundle(shc), verified: await this.verifyShc(shc) }; } async getSingleBundle(shc) { return await this.parseShc(shc).then(data => data.vc.credentialSubject.fhirBundle); } async parseShc(shc) { try { const [h, p, s] = shc.split('.').map((part) => this.base64UrlToBytes(part)); return JSON.parse(this.inflate(p)); } catch (error) { console.error('Error parsing SMART Health Card:', error); throw error; } } async verifyShc(shc) { try { await jose.compactVerify(shc, jose.createLocalJWKSet(await this.fetchJWKs(shc))); return true; } catch (err) { return false; } } async fetchJWKs(shc) { try { const card = JSON.parse(this.inflate(this.base64UrlToBytes(shc.split('.')[1]))); const issuer = card.iss; const jwksUrl = `${issuer.replace(/\/$/, '')}/.well-known/jwks`; const jwksResponse = await firstValueFrom(this.http.get(jwksUrl)); return jwksResponse; } catch (error) { console.error('Error fetching JWKs:', error); throw new Error('Unable to fetch JWKs for signature verification'); } } inflate(data) { try { const decompressed = pako.inflateRaw(data, { to: 'string' }); return decompressed; } catch (error) { console.error('Error inflating data:', error); throw new Error('Failed to inflate data'); } } base64UrlToBytes(base64Url) { const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); const binaryString = atob(base64); return new Uint8Array([...binaryString].map((char) => char.charCodeAt(0))); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ShlService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ShlService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ShlService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1.HttpClient }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hsLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zbWFydC1vbi1maGlyL3NyYy9saWIvc2VydmljZXMvc2hsLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUV6QyxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQ3BDLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDOzs7QUFFN0I7OztHQUdHO0FBSUgsTUFBTSxPQUFPLFVBQVU7SUFFckIsSUFBSSxXQUFXO1FBQ2IsT0FBTztZQUNMLFlBQVksRUFBRSxRQUFRO1lBQ3RCLElBQUksRUFBRSxVQUFVO1lBQ2hCLEtBQUssRUFBRSxFQUFFO1NBQ1YsQ0FBQTtJQUNILENBQUM7SUFFRCxZQUFvQixJQUFnQjtRQUFoQixTQUFJLEdBQUosSUFBSSxDQUFZO0lBQ3BDLENBQUM7SUFFRCxLQUFLLENBQUMsU0FBUyxDQUFDLEdBQVc7UUFDekIsSUFBSSxHQUFHLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFBQyxHQUFHLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUE7UUFBQyxDQUFDO1FBQ3RFLE1BQU0sUUFBUSxHQUFnRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO1FBQ25HLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDbEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQ0FBcUMsQ0FBQyxDQUFBO1FBQ3hELENBQUM7UUFDRCxJQUFJLE9BQU8sQ0FBQztRQUNaLElBQUksUUFBUSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsR0FBRyxDQUFDLEVB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QztZQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsdUJBQXVCLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDOUMsTUFBTSxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1FBQzVDLENBQUM7SUFDSCxDQUFDO0lBRU8sZ0JBQWdCLENBQUMsU0FBaUI7UUFDeEMsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztRQUMvRCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDbEMsT0FBTyxJQUFJLFVBQVUsQ0FBQyxDQUFDLEdBQUcsWUFBWSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM3RSxDQUFDOytHQXpIVSxVQUFVO21IQUFWLFVBQVUsY0FGVCxNQUFNOzs0RkFFUCxVQUFVO2tCQUh0QixVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNO2lCQUNuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7SW5qZWN0YWJsZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7SHR0cENsaWVudH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vbi9odHRwXCI7XHJcbmltcG9ydCB7Zmlyc3RWYWx1ZUZyb219IGZyb20gXCJyeGpzXCI7XHJcbmltcG9ydCAqIGFzIGpvc2UgZnJvbSAnam9zZSc7XHJcbmltcG9ydCAqIGFzIHBha28gZnJvbSAncGFrbyc7XHJcblxyXG4vKipcclxuICogU01BUlQgSGVhbHRoIExpbmsgU2VydmljZVxyXG4gKiBFeGVjdXRlcyB0aGUgcmVxdWVzdHMsIHBhcnNlcyBhbmQgdmFsaWRhdGVzIFNNQVJUIEhlYWx0aCBMaW5rcyBhcyBkZWZpbmVkIGluIHRoZSBITDcgZG9jdW1lbnRhdGlvbnNcclxuICovXHJcbkBJbmplY3RhYmxlKHtcclxuICBwcm92aWRlZEluOiAncm9vdCdcclxufSlcclxuZXhwb3J0IGNsYXNzIFNobFNlcnZpY2Uge1xyXG5cclxuICBnZXQgZW1wdHlCdW5kbGUoKTogZmhpcjQuQnVuZGxlIHtcclxuICAgIHJldHVybiB7XHJcbiAgICAgIHJlc291cmNlVHlwZTogJ0J1bmRsZScsXHJcbiAgICAgIHR5cGU6ICdkb2N1bWVudCcsXHJcbiAgICAgIGVudHJ5OiBbXVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50KSB7XHJcbiAgfVxyXG5cclxuICBhc3luYyBoYW5kbGVTaGwoc2hsOiBzdHJpbmcpIHtcclxuICAgIGlmIChzaGwuc3RhcnRzV2l0aCgnc2hsaW5rOi8nKSkgeyBzaGwgPSBzaGwuc2xpY2UoJ3NobGluazovJy5sZW5ndGgpIH1cclxuICAgIGNvbnN0IG1ldGFkYXRhOiB7IHVybDogc3RyaW5nLCBsYWJlbD86IHN0cmluZywgZmxhZz86IHN0cmluZywga2V5OiBzdHJpbmcgfSA9IEpTT04ucGFyc2UoYXRvYihzaGwpKVxyXG4gICAgaWYgKCFtZXRhZGF0YS51cmwpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVUkwgaXMgbWlzc2luZyBpbiBTTUFSVCBIZWFsdGggTGluaycpXHJcbiAgICB9XHJcbiAgICBsZXQgcGF5bG9hZDtcclxuICAgIGlmIChtZXRhZGF0YS5mbGFnPy5pbmNsdWRlcygnVScpKSB7XHJcbiAgICAgIHBheWxvYWQgPSBhd2FpdCBmaXJzdFZhbHVlRnJvbSh0aGlzLmh0dHAuZ2V0KG1ldGFkYXRhLnVybCArICc/cmVjaXBpZW50PScgKyB3aW5kb3cubG9jYXRpb24ub3JpZ2luKSlcclxuICAgICAgICAudGhlbigoZGF0YTogYW55KSA9PiBkYXRhLmZpbGVzLmZpbHRlcigoZmlsZTogYW55KSA9PiBmaWxlLmNvbnRlbnRUeXBlID09PSAnYXBwbGljYXRpb24vc21hcnQtaGVhbHRoLWNhcmQnICYmIGZpbGUuZW1iZWRkZWQpLm1hcCgoZmlsZTogYW55KSA9PiBmaWxlLmVtYmVkZGVkKSlcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGxldCBwYXNzY29kZTtcclxuICAgICAgaWYgKG1ldGFkYXRhLmZsYWc/LmluY2x1ZGVzKCdQJykpIHtcclxuICAgICAgICBwYXNzY29kZSA9IHByb21wdCgnRW50ZXIgdGhlIHBhc3Njb2RlIGZvciBTTUFSVCBIZWFsdGggTGluaycpXHJcbiAgICAgIH1cclxuICAgICAgcGF5bG9hZCA9IGF3YWl0IGZpcnN0VmFsdWVGcm9tKHRoaXMuaHR0cC5wb3N0KG1ldGFkYXRhLnVybCwge1xyXG4gICAgICAgIHJlY2lwaWVudDogd2luZG93LmxvY2F0aW9uLm9yaWdpbixcclxuICAgICAgICBwYXNzY29kZVxyXG4gICAgICB9KSkudGhlbihhc3luYyAoZGF0YTogYW55KSA9PiB7XHJcbiAgICAgICAgY29uc3QgZW1iZWRkZWQgPSBkYXRhLmZpbGVzLmZpbHRlcigoZmlsZTogYW55KSA9PiBmaWxlLmNvbnRlbnRUeXBlID09PSAnYXBwbGljYXRpb24vc21hcnQtaGVhbHRoLWNhcmQnICYmIGZpbGUuZW1iZWRkZWQpLm1hcCgoZmlsZTogYW55KSA9PiBmaWxlLmVtYmVkZGVkKVxyXG4gICAgICAgIGNvbnN0IGxpbmtzID0gZGF0YS5maWxlcy5maWx0ZXIoKGZpbGU6IGFueSkgPT4gZmlsZS5jb250ZW50VHlwZSA9PT0gJ2FwcGxpY2F0aW9uL2ZoaXIranNvbicgJiYgZmlsZS5sb2NhdGlvbilcclxuICAgICAgICBjb25zdCByZXF1ZXN0cyA9IGxpbmtzLm1hcCgoZmlsZTogYW55KSA9PiBmaXJzdFZhbHVlRnJvbSh0aGlzLmh0dHAuZ2V0KGZpbGUubG9jYXRpb24sIHsgcmVzcG9uc2VUeXBlOiAndGV4dCcgfSkpKVxyXG4gICAgICAgIGNvbnN0IGxpbmtlZENhcmRzID0gYXdhaXQgUHJvbWlzZS5hbGwocmVxdWVzdHMpXHJcbiAgICAgICAgcmV0dXJuIFsuLi5lbWJlZGRlZCwgLi4ubGlua2VkQ2FyZHNdXHJcbiAgICAgIH0pXHJcbiAgICB9XHJcbiAgICBpZiAoIXBheWxvYWQpIHsgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZ2V0IFNNQVJUIEhlYWx0aCBMaW5rIGNvbnRlbnQuJykgfVxyXG4gICAgY29uc3Qgc2hjcyA9IGF3YWl0IHRoaXMuZGVjcnlwdFNITFBheWxvYWRBbmRHZXRTSENzKHBheWxvYWQsIG1ldGFkYXRhLmtleSlcclxuICAgIGNvbnN0IGJ1bmRsZXMgPSBhd2FpdCBQcm9taXNlLmFsbChzaGNzLm1hcChzaGMgPT4gdGhpcy5nZXRTaW5nbGVCdW5kbGUoc2hjKSkpXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBsYWJlbDogbWV0YWRhdGEubGFiZWwsXHJcbiAgICAgIHNoYzogc2hjcyxcclxuICAgICAgdmVyaWZpZWQ6IGF3YWl0IFByb21pc2UuYWxsKHNoY3MubWFwKF9zaGMgPT4gdGhpcy52ZXJpZnlTaGMoX3NoYykpKS50aGVuKHJlc3VsdHMgPT4gcmVzdWx0cy5ldmVyeSh2YWx1ZSA9PiB2YWx1ZSkpLFxyXG4gICAgICBidW5kbGU6IDxmaGlyNC5CdW5kbGU+T2JqZWN0LmFzc2lnbih0aGlzLmVtcHR5QnVuZGxlLCB7XHJcbiAgICAgICAgZW50cnk6IGJ1bmRsZXMuZmlsdGVyKF8gPT4gXykubWFwKGJ1bmRsZSA9PiBidW5kbGUuZW50cnkpLnJlZHVjZSgoYXJyLCBlbnRyaWVzKSA9PiBhcnIuY29uY2F0KGVudHJpZXMpLCBbXSlcclxuICAgICAgfSlcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGFzeW5jIGRlY3J5cHRTSExQYXlsb2FkQW5kR2V0U0hDcyhwYXlsb2FkOiBzdHJpbmdbXSwga2V5OiBzdHJpbmcpIHtcclxuICAgIGNvbnN0IFNIQ3M6IHN0cmluZ1tdID0gW11cclxuICAgIGZvciAoY29uc3QgZW5jcnlwdGVkIG9mIHBheWxvYWQpIHtcclxuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGpvc2UuY29tcGFjdERlY3J5cHQoZW5jcnlwdGVkLCBqb3NlLmJhc2U2NHVybC5kZWNvZGUoa2V5KSlcclxuICAgICAgU0hDcy5wdXNoKC4uLkpTT04ucGFyc2UobmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGRhdGEucGxhaW50ZXh0KSkudmVyaWZpYWJsZUNyZWRlbnRpYWwpXHJcbiAgICB9XHJcbiAgICByZXR1cm4gU0hDcztcclxuICB9XHJcblxyXG4gIGFzeW5jIGhhbmRsZVNoYyhzaGM6IHN0cmluZykge1xyXG4gICAgaWYgKHNoYy5zdGFydHNXaXRoKCdzaGM6LycpKSB7IHNoYyA9IHNoYy5zbGljZSgnc2hjOi8nLmxlbmd0aCkgfVxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgc2hjOiBbc2hjXSxcclxuICAgICAgYnVuZGxlOiBhd2FpdCB0aGlzLmdldFNpbmdsZUJ1bmRsZShzaGMpLFxyXG4gICAgICB2ZXJpZmllZDogYXdhaXQgdGhpcy52ZXJpZnlTaGMoc2hjKVxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGdldFNpbmdsZUJ1bmRsZShzaGM6IHN0cmluZykge1xyXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMucGFyc2VTaGMoc2hjKS50aGVuKGRhdGEgPT4gZGF0YS52Yy5jcmVkZW50aWFsU3ViamVjdC5maGlyQnVuZGxlKVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBwYXJzZVNoYyhzaGM6IHN0cmluZyk6IFByb21pc2U8YW55PiB7XHJcbiAgICB0cnkge1xyXG4gICAgICBjb25zdCBbaCwgcCwgc10gPSBzaGMuc3BsaXQoJy4nKS5tYXAoKHBhcnQpID0+IHRoaXMuYmFzZTY0VXJsVG9CeXRlcyhwYXJ0KSk7XHJcbiAgICAgIHJldHVybiBKU09OLnBhcnNlKHRoaXMuaW5mbGF0ZShwKSk7XHJcbiAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBwYXJzaW5nIFNNQVJUIEhlYWx0aCBDYXJkOicsIGVycm9yKTtcclxuICAgICAgdGhyb3cgZXJyb3I7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGFzeW5jIHZlcmlmeVNoYyhzaGM6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xyXG4gICAgdHJ5IHtcclxuICAgICAgYXdhaXQgam9zZS5jb21wYWN0VmVyaWZ5KHNoYywgam9zZS5jcmVhdGVMb2NhbEpXS1NldChhd2FpdCB0aGlzLmZldGNoSldLcyhzaGMpKSk7XHJcbiAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXN5bmMgZmV0Y2hKV0tzKHNoYzogc3RyaW5nKTogUHJvbWlzZTxqb3NlLkpTT05XZWJLZXlTZXQ+IHtcclxuICAgIHRyeSB7XHJcbiAgICAgIGNvbnN0IGNhcmQgPSBKU09OLnBhcnNlKHRoaXMuaW5mbGF0ZSh0aGlzLmJhc2U2NFVybFRvQnl0ZXMoc2hjLnNwbGl0KCcuJylbMV0pKSk7XHJcbiAgICAgIGNvbnN0IGlzc3VlciA9IGNhcmQuaXNzO1xyXG4gICAgICBjb25zdCBqd2tzVXJsID0gYCR7aXNzdWVyLnJlcGxhY2UoL1xcLyQvLCAnJyl9Ly53ZWxsLWtub3duL2p3a3NgO1xyXG5cclxuICAgICAgY29uc3Qgandrc1Jlc3BvbnNlID0gYXdhaXQgZmlyc3RWYWx1ZUZyb20odGhpcy5odHRwLmdldDxqb3NlLkpTT05XZWJLZXlTZXQ+KGp3a3NVcmwpKTtcclxuICAgICAgcmV0dXJuIGp3a3NSZXNwb25zZTtcclxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGZldGNoaW5nIEpXS3M6JywgZXJyb3IpO1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBmZXRjaCBKV0tzIGZvciBzaWduYXR1cmUgdmVyaWZpY2F0aW9uJyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGluZmxhdGUoZGF0YTogVWludDhBcnJheSk6IHN0cmluZyB7XHJcbiAgICB0cnkge1xyXG4gICAgICBjb25zdCBkZWNvbXByZXNzZWQgPSBwYWtvLmluZmxhdGVSYXcoZGF0YSwgeyB0bzogJ3N0cmluZycgfSk7XHJcbiAgICAgIHJldHVybiBkZWNvbXByZXNzZWQ7XHJcbiAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBpbmZsYXRpbmcgZGF0YTonLCBlcnJvcik7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcignRmFpbGVkIHRvIGluZmxhdGUgZGF0YScpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBiYXNlNjRVcmxUb0J5dGVzKGJhc2U2NFVybDogc3RyaW5nKTogVWludDhBcnJheSB7XHJcbiAgICBjb25zdCBiYXNlNjQgPSBiYXNlNjRVcmwucmVwbGFjZSgvLS9nLCAnKycpLnJlcGxhY2UoL18vZywgJy8nKTtcclxuICAgIGNvbnN0IGJpbmFyeVN0cmluZyA9IGF0b2IoYmFzZTY0KTtcclxuICAgIHJldHVybiBuZXcgVWludDhBcnJheShbLi4uYmluYXJ5U3RyaW5nXS5tYXAoKGNoYXIpID0+IGNoYXIuY2hhckNvZGVBdCgwKSkpO1xyXG4gIH1cclxuXHJcblxyXG59XHJcbiJdfQ==