| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007 |
- import * as crypto from "crypto";
- import * as fs from "fs";
- import * as http from "http";
- import * as https from "https";
- import * as path from "path";
- import * as stream from "stream";
- import * as async from 'async';
- import BlockStream2 from 'block-stream2';
- import { isBrowser } from 'browser-or-node';
- import _ from 'lodash';
- import * as qs from 'query-string';
- import xml2js from 'xml2js';
- import { CredentialProvider } from "../CredentialProvider.mjs";
- import * as errors from "../errors.mjs";
- import { CopyDestinationOptions, CopySourceOptions, DEFAULT_REGION, LEGAL_HOLD_STATUS, PRESIGN_EXPIRY_DAYS_MAX, RETENTION_MODES, RETENTION_VALIDITY_UNITS } from "../helpers.mjs";
- import { NotificationConfig, NotificationPoller } from "../notification.mjs";
- import { postPresignSignatureV4, presignSignatureV4, signV4 } from "../signing.mjs";
- import { fsp, streamPromise } from "./async.mjs";
- import { CopyConditions } from "./copy-conditions.mjs";
- import { Extensions } from "./extensions.mjs";
- import { calculateEvenSplits, extractMetadata, getContentLength, getScope, getSourceVersionId, getVersionId, hashBinary, insertContentType, isAmazonEndpoint, isBoolean, isDefined, isEmpty, isNumber, isObject, isPlainObject, isReadableStream, isString, isValidBucketName, isValidEndpoint, isValidObjectName, isValidPort, isValidPrefix, isVirtualHostStyle, makeDateLong, PART_CONSTRAINTS, partsRequired, prependXAMZMeta, readableStream, sanitizeETag, toMd5, toSha256, uriEscape, uriResourceEscape } from "./helper.mjs";
- import { joinHostPort } from "./join-host-port.mjs";
- import { PostPolicy } from "./post-policy.mjs";
- import { requestWithRetry } from "./request.mjs";
- import { drainResponse, readAsBuffer, readAsString } from "./response.mjs";
- import { getS3Endpoint } from "./s3-endpoints.mjs";
- import { parseBucketNotification, parseCompleteMultipart, parseInitiateMultipart, parseListObjects, parseListObjectsV2, parseObjectLegalHoldConfig, parseSelectObjectContentResponse, uploadPartParser } from "./xml-parser.mjs";
- import * as xmlParsers from "./xml-parser.mjs";
- const xml = new xml2js.Builder({
- renderOpts: {
- pretty: false
- },
- headless: true
- });
- // will be replaced by bundler.
- const Package = {
- version: "8.0.7" || 'development'
- };
- const requestOptionProperties = ['agent', 'ca', 'cert', 'ciphers', 'clientCertEngine', 'crl', 'dhparam', 'ecdhCurve', 'family', 'honorCipherOrder', 'key', 'passphrase', 'pfx', 'rejectUnauthorized', 'secureOptions', 'secureProtocol', 'servername', 'sessionIdContext'];
- export class TypedClient {
- partSize = 64 * 1024 * 1024;
- maximumPartSize = 5 * 1024 * 1024 * 1024;
- maxObjectSize = 5 * 1024 * 1024 * 1024 * 1024;
- constructor(params) {
- // @ts-expect-error deprecated property
- if (params.secure !== undefined) {
- throw new Error('"secure" option deprecated, "useSSL" should be used instead');
- }
- // Default values if not specified.
- if (params.useSSL === undefined) {
- params.useSSL = true;
- }
- if (!params.port) {
- params.port = 0;
- }
- // Validate input params.
- if (!isValidEndpoint(params.endPoint)) {
- throw new errors.InvalidEndpointError(`Invalid endPoint : ${params.endPoint}`);
- }
- if (!isValidPort(params.port)) {
- throw new errors.InvalidArgumentError(`Invalid port : ${params.port}`);
- }
- if (!isBoolean(params.useSSL)) {
- throw new errors.InvalidArgumentError(`Invalid useSSL flag type : ${params.useSSL}, expected to be of type "boolean"`);
- }
- // Validate region only if its set.
- if (params.region) {
- if (!isString(params.region)) {
- throw new errors.InvalidArgumentError(`Invalid region : ${params.region}`);
- }
- }
- const host = params.endPoint.toLowerCase();
- let port = params.port;
- let protocol;
- let transport;
- let transportAgent;
- // Validate if configuration is not using SSL
- // for constructing relevant endpoints.
- if (params.useSSL) {
- // Defaults to secure.
- transport = https;
- protocol = 'https:';
- port = port || 443;
- transportAgent = https.globalAgent;
- } else {
- transport = http;
- protocol = 'http:';
- port = port || 80;
- transportAgent = http.globalAgent;
- }
- // if custom transport is set, use it.
- if (params.transport) {
- if (!isObject(params.transport)) {
- throw new errors.InvalidArgumentError(`Invalid transport type : ${params.transport}, expected to be type "object"`);
- }
- transport = params.transport;
- }
- // if custom transport agent is set, use it.
- if (params.transportAgent) {
- if (!isObject(params.transportAgent)) {
- throw new errors.InvalidArgumentError(`Invalid transportAgent type: ${params.transportAgent}, expected to be type "object"`);
- }
- transportAgent = params.transportAgent;
- }
- // User Agent should always following the below style.
- // Please open an issue to discuss any new changes here.
- //
- // MinIO (OS; ARCH) LIB/VER APP/VER
- //
- const libraryComments = `(${process.platform}; ${process.arch})`;
- const libraryAgent = `MinIO ${libraryComments} minio-js/${Package.version}`;
- // User agent block ends.
- this.transport = transport;
- this.transportAgent = transportAgent;
- this.host = host;
- this.port = port;
- this.protocol = protocol;
- this.userAgent = `${libraryAgent}`;
- // Default path style is true
- if (params.pathStyle === undefined) {
- this.pathStyle = true;
- } else {
- this.pathStyle = params.pathStyle;
- }
- this.accessKey = params.accessKey ?? '';
- this.secretKey = params.secretKey ?? '';
- this.sessionToken = params.sessionToken;
- this.anonymous = !this.accessKey || !this.secretKey;
- if (params.credentialsProvider) {
- this.anonymous = false;
- this.credentialsProvider = params.credentialsProvider;
- }
- this.regionMap = {};
- if (params.region) {
- this.region = params.region;
- }
- if (params.partSize) {
- this.partSize = params.partSize;
- this.overRidePartSize = true;
- }
- if (this.partSize < 5 * 1024 * 1024) {
- throw new errors.InvalidArgumentError(`Part size should be greater than 5MB`);
- }
- if (this.partSize > 5 * 1024 * 1024 * 1024) {
- throw new errors.InvalidArgumentError(`Part size should be less than 5GB`);
- }
- // SHA256 is enabled only for authenticated http requests. If the request is authenticated
- // and the connection is https we use x-amz-content-sha256=UNSIGNED-PAYLOAD
- // header for signature calculation.
- this.enableSHA256 = !this.anonymous && !params.useSSL;
- this.s3AccelerateEndpoint = params.s3AccelerateEndpoint || undefined;
- this.reqOptions = {};
- this.clientExtensions = new Extensions(this);
- if (params.retryOptions) {
- if (!isObject(params.retryOptions)) {
- throw new errors.InvalidArgumentError(`Invalid retryOptions type: ${params.retryOptions}, expected to be type "object"`);
- }
- this.retryOptions = params.retryOptions;
- } else {
- this.retryOptions = {
- disableRetry: false
- };
- }
- }
- /**
- * Minio extensions that aren't necessary present for Amazon S3 compatible storage servers
- */
- get extensions() {
- return this.clientExtensions;
- }
- /**
- * @param endPoint - valid S3 acceleration end point
- */
- setS3TransferAccelerate(endPoint) {
- this.s3AccelerateEndpoint = endPoint;
- }
- /**
- * Sets the supported request options.
- */
- setRequestOptions(options) {
- if (!isObject(options)) {
- throw new TypeError('request options should be of type "object"');
- }
- this.reqOptions = _.pick(options, requestOptionProperties);
- }
- /**
- * This is s3 Specific and does not hold validity in any other Object storage.
- */
- getAccelerateEndPointIfSet(bucketName, objectName) {
- if (!isEmpty(this.s3AccelerateEndpoint) && !isEmpty(bucketName) && !isEmpty(objectName)) {
- // http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html
- // Disable transfer acceleration for non-compliant bucket names.
- if (bucketName.includes('.')) {
- throw new Error(`Transfer Acceleration is not supported for non compliant bucket:${bucketName}`);
- }
- // If transfer acceleration is requested set new host.
- // For more details about enabling transfer acceleration read here.
- // http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html
- return this.s3AccelerateEndpoint;
- }
- return false;
- }
- /**
- * Set application specific information.
- * Generates User-Agent in the following style.
- * MinIO (OS; ARCH) LIB/VER APP/VER
- */
- setAppInfo(appName, appVersion) {
- if (!isString(appName)) {
- throw new TypeError(`Invalid appName: ${appName}`);
- }
- if (appName.trim() === '') {
- throw new errors.InvalidArgumentError('Input appName cannot be empty.');
- }
- if (!isString(appVersion)) {
- throw new TypeError(`Invalid appVersion: ${appVersion}`);
- }
- if (appVersion.trim() === '') {
- throw new errors.InvalidArgumentError('Input appVersion cannot be empty.');
- }
- this.userAgent = `${this.userAgent} ${appName}/${appVersion}`;
- }
- /**
- * returns options object that can be used with http.request()
- * Takes care of constructing virtual-host-style or path-style hostname
- */
- getRequestOptions(opts) {
- const method = opts.method;
- const region = opts.region;
- const bucketName = opts.bucketName;
- let objectName = opts.objectName;
- const headers = opts.headers;
- const query = opts.query;
- let reqOptions = {
- method,
- headers: {},
- protocol: this.protocol,
- // If custom transportAgent was supplied earlier, we'll inject it here
- agent: this.transportAgent
- };
- // Verify if virtual host supported.
- let virtualHostStyle;
- if (bucketName) {
- virtualHostStyle = isVirtualHostStyle(this.host, this.protocol, bucketName, this.pathStyle);
- }
- let path = '/';
- let host = this.host;
- let port;
- if (this.port) {
- port = this.port;
- }
- if (objectName) {
- objectName = uriResourceEscape(objectName);
- }
- // For Amazon S3 endpoint, get endpoint based on region.
- if (isAmazonEndpoint(host)) {
- const accelerateEndPoint = this.getAccelerateEndPointIfSet(bucketName, objectName);
- if (accelerateEndPoint) {
- host = `${accelerateEndPoint}`;
- } else {
- host = getS3Endpoint(region);
- }
- }
- if (virtualHostStyle && !opts.pathStyle) {
- // For all hosts which support virtual host style, `bucketName`
- // is part of the hostname in the following format:
- //
- // var host = 'bucketName.example.com'
- //
- if (bucketName) {
- host = `${bucketName}.${host}`;
- }
- if (objectName) {
- path = `/${objectName}`;
- }
- } else {
- // For all S3 compatible storage services we will fallback to
- // path style requests, where `bucketName` is part of the URI
- // path.
- if (bucketName) {
- path = `/${bucketName}`;
- }
- if (objectName) {
- path = `/${bucketName}/${objectName}`;
- }
- }
- if (query) {
- path += `?${query}`;
- }
- reqOptions.headers.host = host;
- if (reqOptions.protocol === 'http:' && port !== 80 || reqOptions.protocol === 'https:' && port !== 443) {
- reqOptions.headers.host = joinHostPort(host, port);
- }
- reqOptions.headers['user-agent'] = this.userAgent;
- if (headers) {
- // have all header keys in lower case - to make signing easy
- for (const [k, v] of Object.entries(headers)) {
- reqOptions.headers[k.toLowerCase()] = v;
- }
- }
- // Use any request option specified in minioClient.setRequestOptions()
- reqOptions = Object.assign({}, this.reqOptions, reqOptions);
- return {
- ...reqOptions,
- headers: _.mapValues(_.pickBy(reqOptions.headers, isDefined), v => v.toString()),
- host,
- port,
- path
- };
- }
- async setCredentialsProvider(credentialsProvider) {
- if (!(credentialsProvider instanceof CredentialProvider)) {
- throw new Error('Unable to get credentials. Expected instance of CredentialProvider');
- }
- this.credentialsProvider = credentialsProvider;
- await this.checkAndRefreshCreds();
- }
- async checkAndRefreshCreds() {
- if (this.credentialsProvider) {
- try {
- const credentialsConf = await this.credentialsProvider.getCredentials();
- this.accessKey = credentialsConf.getAccessKey();
- this.secretKey = credentialsConf.getSecretKey();
- this.sessionToken = credentialsConf.getSessionToken();
- } catch (e) {
- throw new Error(`Unable to get credentials: ${e}`, {
- cause: e
- });
- }
- }
- }
- /**
- * log the request, response, error
- */
- logHTTP(reqOptions, response, err) {
- // if no logStream available return.
- if (!this.logStream) {
- return;
- }
- if (!isObject(reqOptions)) {
- throw new TypeError('reqOptions should be of type "object"');
- }
- if (response && !isReadableStream(response)) {
- throw new TypeError('response should be of type "Stream"');
- }
- if (err && !(err instanceof Error)) {
- throw new TypeError('err should be of type "Error"');
- }
- const logStream = this.logStream;
- const logHeaders = headers => {
- Object.entries(headers).forEach(([k, v]) => {
- if (k == 'authorization') {
- if (isString(v)) {
- const redactor = new RegExp('Signature=([0-9a-f]+)');
- v = v.replace(redactor, 'Signature=**REDACTED**');
- }
- }
- logStream.write(`${k}: ${v}\n`);
- });
- logStream.write('\n');
- };
- logStream.write(`REQUEST: ${reqOptions.method} ${reqOptions.path}\n`);
- logHeaders(reqOptions.headers);
- if (response) {
- this.logStream.write(`RESPONSE: ${response.statusCode}\n`);
- logHeaders(response.headers);
- }
- if (err) {
- logStream.write('ERROR BODY:\n');
- const errJSON = JSON.stringify(err, null, '\t');
- logStream.write(`${errJSON}\n`);
- }
- }
- /**
- * Enable tracing
- */
- traceOn(stream) {
- if (!stream) {
- stream = process.stdout;
- }
- this.logStream = stream;
- }
- /**
- * Disable tracing
- */
- traceOff() {
- this.logStream = undefined;
- }
- /**
- * makeRequest is the primitive used by the apis for making S3 requests.
- * payload can be empty string in case of no payload.
- * statusCode is the expected statusCode. If response.statusCode does not match
- * we parse the XML error and call the callback with the error message.
- *
- * A valid region is passed by the calls - listBuckets, makeBucket and getBucketRegion.
- *
- * @internal
- */
- async makeRequestAsync(options, payload = '', expectedCodes = [200], region = '') {
- if (!isObject(options)) {
- throw new TypeError('options should be of type "object"');
- }
- if (!isString(payload) && !isObject(payload)) {
- // Buffer is of type 'object'
- throw new TypeError('payload should be of type "string" or "Buffer"');
- }
- expectedCodes.forEach(statusCode => {
- if (!isNumber(statusCode)) {
- throw new TypeError('statusCode should be of type "number"');
- }
- });
- if (!isString(region)) {
- throw new TypeError('region should be of type "string"');
- }
- if (!options.headers) {
- options.headers = {};
- }
- if (options.method === 'POST' || options.method === 'PUT' || options.method === 'DELETE') {
- options.headers['content-length'] = payload.length.toString();
- }
- const sha256sum = this.enableSHA256 ? toSha256(payload) : '';
- return this.makeRequestStreamAsync(options, payload, sha256sum, expectedCodes, region);
- }
- /**
- * new request with promise
- *
- * No need to drain response, response body is not valid
- */
- async makeRequestAsyncOmit(options, payload = '', statusCodes = [200], region = '') {
- const res = await this.makeRequestAsync(options, payload, statusCodes, region);
- await drainResponse(res);
- return res;
- }
- /**
- * makeRequestStream will be used directly instead of makeRequest in case the payload
- * is available as a stream. for ex. putObject
- *
- * @internal
- */
- async makeRequestStreamAsync(options, body, sha256sum, statusCodes, region) {
- if (!isObject(options)) {
- throw new TypeError('options should be of type "object"');
- }
- if (!(Buffer.isBuffer(body) || typeof body === 'string' || isReadableStream(body))) {
- throw new errors.InvalidArgumentError(`stream should be a Buffer, string or readable Stream, got ${typeof body} instead`);
- }
- if (!isString(sha256sum)) {
- throw new TypeError('sha256sum should be of type "string"');
- }
- statusCodes.forEach(statusCode => {
- if (!isNumber(statusCode)) {
- throw new TypeError('statusCode should be of type "number"');
- }
- });
- if (!isString(region)) {
- throw new TypeError('region should be of type "string"');
- }
- // sha256sum will be empty for anonymous or https requests
- if (!this.enableSHA256 && sha256sum.length !== 0) {
- throw new errors.InvalidArgumentError(`sha256sum expected to be empty for anonymous or https requests`);
- }
- // sha256sum should be valid for non-anonymous http requests.
- if (this.enableSHA256 && sha256sum.length !== 64) {
- throw new errors.InvalidArgumentError(`Invalid sha256sum : ${sha256sum}`);
- }
- await this.checkAndRefreshCreds();
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- region = region || (await this.getBucketRegionAsync(options.bucketName));
- const reqOptions = this.getRequestOptions({
- ...options,
- region
- });
- if (!this.anonymous) {
- // For non-anonymous https requests sha256sum is 'UNSIGNED-PAYLOAD' for signature calculation.
- if (!this.enableSHA256) {
- sha256sum = 'UNSIGNED-PAYLOAD';
- }
- const date = new Date();
- reqOptions.headers['x-amz-date'] = makeDateLong(date);
- reqOptions.headers['x-amz-content-sha256'] = sha256sum;
- if (this.sessionToken) {
- reqOptions.headers['x-amz-security-token'] = this.sessionToken;
- }
- reqOptions.headers.authorization = signV4(reqOptions, this.accessKey, this.secretKey, region, date, sha256sum);
- }
- const response = await requestWithRetry(this.transport, reqOptions, body, this.retryOptions.disableRetry === true ? 0 : this.retryOptions.maximumRetryCount, this.retryOptions.baseDelayMs, this.retryOptions.maximumDelayMs);
- if (!response.statusCode) {
- throw new Error("BUG: response doesn't have a statusCode");
- }
- if (!statusCodes.includes(response.statusCode)) {
- // For an incorrect region, S3 server always sends back 400.
- // But we will do cache invalidation for all errors so that,
- // in future, if AWS S3 decides to send a different status code or
- // XML error code we will still work fine.
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- delete this.regionMap[options.bucketName];
- const err = await xmlParsers.parseResponseError(response);
- this.logHTTP(reqOptions, response, err);
- throw err;
- }
- this.logHTTP(reqOptions, response);
- return response;
- }
- /**
- * gets the region of the bucket
- *
- * @param bucketName
- *
- */
- async getBucketRegionAsync(bucketName) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError(`Invalid bucket name : ${bucketName}`);
- }
- // Region is set with constructor, return the region right here.
- if (this.region) {
- return this.region;
- }
- const cached = this.regionMap[bucketName];
- if (cached) {
- return cached;
- }
- const extractRegionAsync = async response => {
- const body = await readAsString(response);
- const region = xmlParsers.parseBucketRegion(body) || DEFAULT_REGION;
- this.regionMap[bucketName] = region;
- return region;
- };
- const method = 'GET';
- const query = 'location';
- // `getBucketLocation` behaves differently in following ways for
- // different environments.
- //
- // - For nodejs env we default to path style requests.
- // - For browser env path style requests on buckets yields CORS
- // error. To circumvent this problem we make a virtual host
- // style request signed with 'us-east-1'. This request fails
- // with an error 'AuthorizationHeaderMalformed', additionally
- // the error XML also provides Region of the bucket. To validate
- // this region is proper we retry the same request with the newly
- // obtained region.
- const pathStyle = this.pathStyle && !isBrowser;
- let region;
- try {
- const res = await this.makeRequestAsync({
- method,
- bucketName,
- query,
- pathStyle
- }, '', [200], DEFAULT_REGION);
- return extractRegionAsync(res);
- } catch (e) {
- // make alignment with mc cli
- if (e instanceof errors.S3Error) {
- const errCode = e.code;
- const errRegion = e.region;
- if (errCode === 'AccessDenied' && !errRegion) {
- return DEFAULT_REGION;
- }
- }
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- if (!(e.name === 'AuthorizationHeaderMalformed')) {
- throw e;
- }
- // @ts-expect-error we set extra properties on error object
- region = e.Region;
- if (!region) {
- throw e;
- }
- }
- const res = await this.makeRequestAsync({
- method,
- bucketName,
- query,
- pathStyle
- }, '', [200], region);
- return await extractRegionAsync(res);
- }
- /**
- * makeRequest is the primitive used by the apis for making S3 requests.
- * payload can be empty string in case of no payload.
- * statusCode is the expected statusCode. If response.statusCode does not match
- * we parse the XML error and call the callback with the error message.
- * A valid region is passed by the calls - listBuckets, makeBucket and
- * getBucketRegion.
- *
- * @deprecated use `makeRequestAsync` instead
- */
- makeRequest(options, payload = '', expectedCodes = [200], region = '', returnResponse, cb) {
- let prom;
- if (returnResponse) {
- prom = this.makeRequestAsync(options, payload, expectedCodes, region);
- } else {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-expect-error compatible for old behaviour
- prom = this.makeRequestAsyncOmit(options, payload, expectedCodes, region);
- }
- prom.then(result => cb(null, result), err => {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- cb(err);
- });
- }
- /**
- * makeRequestStream will be used directly instead of makeRequest in case the payload
- * is available as a stream. for ex. putObject
- *
- * @deprecated use `makeRequestStreamAsync` instead
- */
- makeRequestStream(options, stream, sha256sum, statusCodes, region, returnResponse, cb) {
- const executor = async () => {
- const res = await this.makeRequestStreamAsync(options, stream, sha256sum, statusCodes, region);
- if (!returnResponse) {
- await drainResponse(res);
- }
- return res;
- };
- executor().then(result => cb(null, result),
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- err => cb(err));
- }
- /**
- * @deprecated use `getBucketRegionAsync` instead
- */
- getBucketRegion(bucketName, cb) {
- return this.getBucketRegionAsync(bucketName).then(result => cb(null, result),
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- err => cb(err));
- }
- // Bucket operations
- /**
- * Creates the bucket `bucketName`.
- *
- */
- async makeBucket(bucketName, region = '', makeOpts) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- // Backward Compatibility
- if (isObject(region)) {
- makeOpts = region;
- region = '';
- }
- if (!isString(region)) {
- throw new TypeError('region should be of type "string"');
- }
- if (makeOpts && !isObject(makeOpts)) {
- throw new TypeError('makeOpts should be of type "object"');
- }
- let payload = '';
- // Region already set in constructor, validate if
- // caller requested bucket location is same.
- if (region && this.region) {
- if (region !== this.region) {
- throw new errors.InvalidArgumentError(`Configured region ${this.region}, requested ${region}`);
- }
- }
- // sending makeBucket request with XML containing 'us-east-1' fails. For
- // default region server expects the request without body
- if (region && region !== DEFAULT_REGION) {
- payload = xml.buildObject({
- CreateBucketConfiguration: {
- $: {
- xmlns: 'http://s3.amazonaws.com/doc/2006-03-01/'
- },
- LocationConstraint: region
- }
- });
- }
- const method = 'PUT';
- const headers = {};
- if (makeOpts && makeOpts.ObjectLocking) {
- headers['x-amz-bucket-object-lock-enabled'] = true;
- }
- // For custom region clients default to custom region specified in client constructor
- const finalRegion = this.region || region || DEFAULT_REGION;
- const requestOpt = {
- method,
- bucketName,
- headers
- };
- try {
- await this.makeRequestAsyncOmit(requestOpt, payload, [200], finalRegion);
- } catch (err) {
- if (region === '' || region === DEFAULT_REGION) {
- if (err instanceof errors.S3Error) {
- const errCode = err.code;
- const errRegion = err.region;
- if (errCode === 'AuthorizationHeaderMalformed' && errRegion !== '') {
- // Retry with region returned as part of error
- await this.makeRequestAsyncOmit(requestOpt, payload, [200], errCode);
- }
- }
- }
- throw err;
- }
- }
- /**
- * To check if a bucket already exists.
- */
- async bucketExists(bucketName) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- const method = 'HEAD';
- try {
- await this.makeRequestAsyncOmit({
- method,
- bucketName
- });
- } catch (err) {
- // @ts-ignore
- if (err.code === 'NoSuchBucket' || err.code === 'NotFound') {
- return false;
- }
- throw err;
- }
- return true;
- }
- /**
- * @deprecated use promise style API
- */
- async removeBucket(bucketName) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- const method = 'DELETE';
- await this.makeRequestAsyncOmit({
- method,
- bucketName
- }, '', [204]);
- delete this.regionMap[bucketName];
- }
- /**
- * Callback is called with readable stream of the object content.
- */
- async getObject(bucketName, objectName, getOpts) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- return this.getPartialObject(bucketName, objectName, 0, 0, getOpts);
- }
- /**
- * Callback is called with readable stream of the partial object content.
- * @param bucketName
- * @param objectName
- * @param offset
- * @param length - length of the object that will be read in the stream (optional, if not specified we read the rest of the file from the offset)
- * @param getOpts
- */
- async getPartialObject(bucketName, objectName, offset, length = 0, getOpts) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- if (!isNumber(offset)) {
- throw new TypeError('offset should be of type "number"');
- }
- if (!isNumber(length)) {
- throw new TypeError('length should be of type "number"');
- }
- let range = '';
- if (offset || length) {
- if (offset) {
- range = `bytes=${+offset}-`;
- } else {
- range = 'bytes=0-';
- offset = 0;
- }
- if (length) {
- range += `${+length + offset - 1}`;
- }
- }
- let query = '';
- let headers = {
- ...(range !== '' && {
- range
- })
- };
- if (getOpts) {
- const sseHeaders = {
- ...(getOpts.SSECustomerAlgorithm && {
- 'X-Amz-Server-Side-Encryption-Customer-Algorithm': getOpts.SSECustomerAlgorithm
- }),
- ...(getOpts.SSECustomerKey && {
- 'X-Amz-Server-Side-Encryption-Customer-Key': getOpts.SSECustomerKey
- }),
- ...(getOpts.SSECustomerKeyMD5 && {
- 'X-Amz-Server-Side-Encryption-Customer-Key-MD5': getOpts.SSECustomerKeyMD5
- })
- };
- query = qs.stringify(getOpts);
- headers = {
- ...prependXAMZMeta(sseHeaders),
- ...headers
- };
- }
- const expectedStatusCodes = [200];
- if (range) {
- expectedStatusCodes.push(206);
- }
- const method = 'GET';
- return await this.makeRequestAsync({
- method,
- bucketName,
- objectName,
- headers,
- query
- }, '', expectedStatusCodes);
- }
- /**
- * download object content to a file.
- * This method will create a temp file named `${filename}.${base64(etag)}.part.minio` when downloading.
- *
- * @param bucketName - name of the bucket
- * @param objectName - name of the object
- * @param filePath - path to which the object data will be written to
- * @param getOpts - Optional object get option
- */
- async fGetObject(bucketName, objectName, filePath, getOpts) {
- // Input validation.
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- if (!isString(filePath)) {
- throw new TypeError('filePath should be of type "string"');
- }
- const downloadToTmpFile = async () => {
- let partFileStream;
- const objStat = await this.statObject(bucketName, objectName, getOpts);
- const encodedEtag = Buffer.from(objStat.etag).toString('base64');
- const partFile = `${filePath}.${encodedEtag}.part.minio`;
- await fsp.mkdir(path.dirname(filePath), {
- recursive: true
- });
- let offset = 0;
- try {
- const stats = await fsp.stat(partFile);
- if (objStat.size === stats.size) {
- return partFile;
- }
- offset = stats.size;
- partFileStream = fs.createWriteStream(partFile, {
- flags: 'a'
- });
- } catch (e) {
- if (e instanceof Error && e.code === 'ENOENT') {
- // file not exist
- partFileStream = fs.createWriteStream(partFile, {
- flags: 'w'
- });
- } else {
- // other error, maybe access deny
- throw e;
- }
- }
- const downloadStream = await this.getPartialObject(bucketName, objectName, offset, 0, getOpts);
- await streamPromise.pipeline(downloadStream, partFileStream);
- const stats = await fsp.stat(partFile);
- if (stats.size === objStat.size) {
- return partFile;
- }
- throw new Error('Size mismatch between downloaded file and the object');
- };
- const partFile = await downloadToTmpFile();
- await fsp.rename(partFile, filePath);
- }
- /**
- * Stat information of the object.
- */
- async statObject(bucketName, objectName, statOpts) {
- const statOptDef = statOpts || {};
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- if (!isObject(statOptDef)) {
- throw new errors.InvalidArgumentError('statOpts should be of type "object"');
- }
- const query = qs.stringify(statOptDef);
- const method = 'HEAD';
- const res = await this.makeRequestAsyncOmit({
- method,
- bucketName,
- objectName,
- query
- });
- return {
- size: parseInt(res.headers['content-length']),
- metaData: extractMetadata(res.headers),
- lastModified: new Date(res.headers['last-modified']),
- versionId: getVersionId(res.headers),
- etag: sanitizeETag(res.headers.etag)
- };
- }
- async removeObject(bucketName, objectName, removeOpts) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- if (removeOpts && !isObject(removeOpts)) {
- throw new errors.InvalidArgumentError('removeOpts should be of type "object"');
- }
- const method = 'DELETE';
- const headers = {};
- if (removeOpts !== null && removeOpts !== void 0 && removeOpts.governanceBypass) {
- headers['X-Amz-Bypass-Governance-Retention'] = true;
- }
- if (removeOpts !== null && removeOpts !== void 0 && removeOpts.forceDelete) {
- headers['x-minio-force-delete'] = true;
- }
- const queryParams = {};
- if (removeOpts !== null && removeOpts !== void 0 && removeOpts.versionId) {
- queryParams.versionId = `${removeOpts.versionId}`;
- }
- const query = qs.stringify(queryParams);
- await this.makeRequestAsyncOmit({
- method,
- bucketName,
- objectName,
- headers,
- query
- }, '', [200, 204]);
- }
- // Calls implemented below are related to multipart.
- listIncompleteUploads(bucket, prefix, recursive) {
- if (prefix === undefined) {
- prefix = '';
- }
- if (recursive === undefined) {
- recursive = false;
- }
- if (!isValidBucketName(bucket)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucket);
- }
- if (!isValidPrefix(prefix)) {
- throw new errors.InvalidPrefixError(`Invalid prefix : ${prefix}`);
- }
- if (!isBoolean(recursive)) {
- throw new TypeError('recursive should be of type "boolean"');
- }
- const delimiter = recursive ? '' : '/';
- let keyMarker = '';
- let uploadIdMarker = '';
- const uploads = [];
- let ended = false;
- // TODO: refactor this with async/await and `stream.Readable.from`
- const readStream = new stream.Readable({
- objectMode: true
- });
- readStream._read = () => {
- // push one upload info per _read()
- if (uploads.length) {
- return readStream.push(uploads.shift());
- }
- if (ended) {
- return readStream.push(null);
- }
- this.listIncompleteUploadsQuery(bucket, prefix, keyMarker, uploadIdMarker, delimiter).then(result => {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- result.prefixes.forEach(prefix => uploads.push(prefix));
- async.eachSeries(result.uploads, (upload, cb) => {
- // for each incomplete upload add the sizes of its uploaded parts
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- this.listParts(bucket, upload.key, upload.uploadId).then(parts => {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- upload.size = parts.reduce((acc, item) => acc + item.size, 0);
- uploads.push(upload);
- cb();
- }, err => cb(err));
- }, err => {
- if (err) {
- readStream.emit('error', err);
- return;
- }
- if (result.isTruncated) {
- keyMarker = result.nextKeyMarker;
- uploadIdMarker = result.nextUploadIdMarker;
- } else {
- ended = true;
- }
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- readStream._read();
- });
- }, e => {
- readStream.emit('error', e);
- });
- };
- return readStream;
- }
- /**
- * Called by listIncompleteUploads to fetch a batch of incomplete uploads.
- */
- async listIncompleteUploadsQuery(bucketName, prefix, keyMarker, uploadIdMarker, delimiter) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isString(prefix)) {
- throw new TypeError('prefix should be of type "string"');
- }
- if (!isString(keyMarker)) {
- throw new TypeError('keyMarker should be of type "string"');
- }
- if (!isString(uploadIdMarker)) {
- throw new TypeError('uploadIdMarker should be of type "string"');
- }
- if (!isString(delimiter)) {
- throw new TypeError('delimiter should be of type "string"');
- }
- const queries = [];
- queries.push(`prefix=${uriEscape(prefix)}`);
- queries.push(`delimiter=${uriEscape(delimiter)}`);
- if (keyMarker) {
- queries.push(`key-marker=${uriEscape(keyMarker)}`);
- }
- if (uploadIdMarker) {
- queries.push(`upload-id-marker=${uploadIdMarker}`);
- }
- const maxUploads = 1000;
- queries.push(`max-uploads=${maxUploads}`);
- queries.sort();
- queries.unshift('uploads');
- let query = '';
- if (queries.length > 0) {
- query = `${queries.join('&')}`;
- }
- const method = 'GET';
- const res = await this.makeRequestAsync({
- method,
- bucketName,
- query
- });
- const body = await readAsString(res);
- return xmlParsers.parseListMultipart(body);
- }
- /**
- * Initiate a new multipart upload.
- * @internal
- */
- async initiateNewMultipartUpload(bucketName, objectName, headers) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- if (!isObject(headers)) {
- throw new errors.InvalidObjectNameError('contentType should be of type "object"');
- }
- const method = 'POST';
- const query = 'uploads';
- const res = await this.makeRequestAsync({
- method,
- bucketName,
- objectName,
- query,
- headers
- });
- const body = await readAsBuffer(res);
- return parseInitiateMultipart(body.toString());
- }
- /**
- * Internal Method to abort a multipart upload request in case of any errors.
- *
- * @param bucketName - Bucket Name
- * @param objectName - Object Name
- * @param uploadId - id of a multipart upload to cancel during compose object sequence.
- */
- async abortMultipartUpload(bucketName, objectName, uploadId) {
- const method = 'DELETE';
- const query = `uploadId=${uploadId}`;
- const requestOptions = {
- method,
- bucketName,
- objectName: objectName,
- query
- };
- await this.makeRequestAsyncOmit(requestOptions, '', [204]);
- }
- async findUploadId(bucketName, objectName) {
- var _latestUpload;
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- let latestUpload;
- let keyMarker = '';
- let uploadIdMarker = '';
- for (;;) {
- const result = await this.listIncompleteUploadsQuery(bucketName, objectName, keyMarker, uploadIdMarker, '');
- for (const upload of result.uploads) {
- if (upload.key === objectName) {
- if (!latestUpload || upload.initiated.getTime() > latestUpload.initiated.getTime()) {
- latestUpload = upload;
- }
- }
- }
- if (result.isTruncated) {
- keyMarker = result.nextKeyMarker;
- uploadIdMarker = result.nextUploadIdMarker;
- continue;
- }
- break;
- }
- return (_latestUpload = latestUpload) === null || _latestUpload === void 0 ? void 0 : _latestUpload.uploadId;
- }
- /**
- * this call will aggregate the parts on the server into a single object.
- */
- async completeMultipartUpload(bucketName, objectName, uploadId, etags) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- if (!isString(uploadId)) {
- throw new TypeError('uploadId should be of type "string"');
- }
- if (!isObject(etags)) {
- throw new TypeError('etags should be of type "Array"');
- }
- if (!uploadId) {
- throw new errors.InvalidArgumentError('uploadId cannot be empty');
- }
- const method = 'POST';
- const query = `uploadId=${uriEscape(uploadId)}`;
- const builder = new xml2js.Builder();
- const payload = builder.buildObject({
- CompleteMultipartUpload: {
- $: {
- xmlns: 'http://s3.amazonaws.com/doc/2006-03-01/'
- },
- Part: etags.map(etag => {
- return {
- PartNumber: etag.part,
- ETag: etag.etag
- };
- })
- }
- });
- const res = await this.makeRequestAsync({
- method,
- bucketName,
- objectName,
- query
- }, payload);
- const body = await readAsBuffer(res);
- const result = parseCompleteMultipart(body.toString());
- if (!result) {
- throw new Error('BUG: failed to parse server response');
- }
- if (result.errCode) {
- // Multipart Complete API returns an error XML after a 200 http status
- throw new errors.S3Error(result.errMessage);
- }
- return {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- etag: result.etag,
- versionId: getVersionId(res.headers)
- };
- }
- /**
- * Get part-info of all parts of an incomplete upload specified by uploadId.
- */
- async listParts(bucketName, objectName, uploadId) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- if (!isString(uploadId)) {
- throw new TypeError('uploadId should be of type "string"');
- }
- if (!uploadId) {
- throw new errors.InvalidArgumentError('uploadId cannot be empty');
- }
- const parts = [];
- let marker = 0;
- let result;
- do {
- result = await this.listPartsQuery(bucketName, objectName, uploadId, marker);
- marker = result.marker;
- parts.push(...result.parts);
- } while (result.isTruncated);
- return parts;
- }
- /**
- * Called by listParts to fetch a batch of part-info
- */
- async listPartsQuery(bucketName, objectName, uploadId, marker) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- if (!isString(uploadId)) {
- throw new TypeError('uploadId should be of type "string"');
- }
- if (!isNumber(marker)) {
- throw new TypeError('marker should be of type "number"');
- }
- if (!uploadId) {
- throw new errors.InvalidArgumentError('uploadId cannot be empty');
- }
- let query = `uploadId=${uriEscape(uploadId)}`;
- if (marker) {
- query += `&part-number-marker=${marker}`;
- }
- const method = 'GET';
- const res = await this.makeRequestAsync({
- method,
- bucketName,
- objectName,
- query
- });
- return xmlParsers.parseListParts(await readAsString(res));
- }
- async listBuckets() {
- const method = 'GET';
- const regionConf = this.region || DEFAULT_REGION;
- const httpRes = await this.makeRequestAsync({
- method
- }, '', [200], regionConf);
- const xmlResult = await readAsString(httpRes);
- return xmlParsers.parseListBucket(xmlResult);
- }
- /**
- * Calculate part size given the object size. Part size will be atleast this.partSize
- */
- calculatePartSize(size) {
- if (!isNumber(size)) {
- throw new TypeError('size should be of type "number"');
- }
- if (size > this.maxObjectSize) {
- throw new TypeError(`size should not be more than ${this.maxObjectSize}`);
- }
- if (this.overRidePartSize) {
- return this.partSize;
- }
- let partSize = this.partSize;
- for (;;) {
- // while(true) {...} throws linting error.
- // If partSize is big enough to accomodate the object size, then use it.
- if (partSize * 10000 > size) {
- return partSize;
- }
- // Try part sizes as 64MB, 80MB, 96MB etc.
- partSize += 16 * 1024 * 1024;
- }
- }
- /**
- * Uploads the object using contents from a file
- */
- async fPutObject(bucketName, objectName, filePath, metaData) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- if (!isString(filePath)) {
- throw new TypeError('filePath should be of type "string"');
- }
- if (metaData && !isObject(metaData)) {
- throw new TypeError('metaData should be of type "object"');
- }
- // Inserts correct `content-type` attribute based on metaData and filePath
- metaData = insertContentType(metaData || {}, filePath);
- const stat = await fsp.stat(filePath);
- return await this.putObject(bucketName, objectName, fs.createReadStream(filePath), stat.size, metaData);
- }
- /**
- * Uploading a stream, "Buffer" or "string".
- * It's recommended to pass `size` argument with stream.
- */
- async putObject(bucketName, objectName, stream, size, metaData) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- // We'll need to shift arguments to the left because of metaData
- // and size being optional.
- if (isObject(size)) {
- metaData = size;
- }
- // Ensures Metadata has appropriate prefix for A3 API
- const headers = prependXAMZMeta(metaData);
- if (typeof stream === 'string' || stream instanceof Buffer) {
- // Adapts the non-stream interface into a stream.
- size = stream.length;
- stream = readableStream(stream);
- } else if (!isReadableStream(stream)) {
- throw new TypeError('third argument should be of type "stream.Readable" or "Buffer" or "string"');
- }
- if (isNumber(size) && size < 0) {
- throw new errors.InvalidArgumentError(`size cannot be negative, given size: ${size}`);
- }
- // Get the part size and forward that to the BlockStream. Default to the
- // largest block size possible if necessary.
- if (!isNumber(size)) {
- size = this.maxObjectSize;
- }
- // Get the part size and forward that to the BlockStream. Default to the
- // largest block size possible if necessary.
- if (size === undefined) {
- const statSize = await getContentLength(stream);
- if (statSize !== null) {
- size = statSize;
- }
- }
- if (!isNumber(size)) {
- // Backward compatibility
- size = this.maxObjectSize;
- }
- if (size === 0) {
- return this.uploadBuffer(bucketName, objectName, headers, Buffer.from(''));
- }
- const partSize = this.calculatePartSize(size);
- if (typeof stream === 'string' || Buffer.isBuffer(stream) || size <= partSize) {
- const buf = isReadableStream(stream) ? await readAsBuffer(stream) : Buffer.from(stream);
- return this.uploadBuffer(bucketName, objectName, headers, buf);
- }
- return this.uploadStream(bucketName, objectName, headers, stream, partSize);
- }
- /**
- * method to upload buffer in one call
- * @private
- */
- async uploadBuffer(bucketName, objectName, headers, buf) {
- const {
- md5sum,
- sha256sum
- } = hashBinary(buf, this.enableSHA256);
- headers['Content-Length'] = buf.length;
- if (!this.enableSHA256) {
- headers['Content-MD5'] = md5sum;
- }
- const res = await this.makeRequestStreamAsync({
- method: 'PUT',
- bucketName,
- objectName,
- headers
- }, buf, sha256sum, [200], '');
- await drainResponse(res);
- return {
- etag: sanitizeETag(res.headers.etag),
- versionId: getVersionId(res.headers)
- };
- }
- /**
- * upload stream with MultipartUpload
- * @private
- */
- async uploadStream(bucketName, objectName, headers, body, partSize) {
- // A map of the previously uploaded chunks, for resuming a file upload. This
- // will be null if we aren't resuming an upload.
- const oldParts = {};
- // Keep track of the etags for aggregating the chunks together later. Each
- // etag represents a single chunk of the file.
- const eTags = [];
- const previousUploadId = await this.findUploadId(bucketName, objectName);
- let uploadId;
- if (!previousUploadId) {
- uploadId = await this.initiateNewMultipartUpload(bucketName, objectName, headers);
- } else {
- uploadId = previousUploadId;
- const oldTags = await this.listParts(bucketName, objectName, previousUploadId);
- oldTags.forEach(e => {
- oldParts[e.part] = e;
- });
- }
- const chunkier = new BlockStream2({
- size: partSize,
- zeroPadding: false
- });
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- const [_, o] = await Promise.all([new Promise((resolve, reject) => {
- body.pipe(chunkier).on('error', reject);
- chunkier.on('end', resolve).on('error', reject);
- }), (async () => {
- let partNumber = 1;
- for await (const chunk of chunkier) {
- const md5 = crypto.createHash('md5').update(chunk).digest();
- const oldPart = oldParts[partNumber];
- if (oldPart) {
- if (oldPart.etag === md5.toString('hex')) {
- eTags.push({
- part: partNumber,
- etag: oldPart.etag
- });
- partNumber++;
- continue;
- }
- }
- partNumber++;
- // now start to upload missing part
- const options = {
- method: 'PUT',
- query: qs.stringify({
- partNumber,
- uploadId
- }),
- headers: {
- 'Content-Length': chunk.length,
- 'Content-MD5': md5.toString('base64')
- },
- bucketName,
- objectName
- };
- const response = await this.makeRequestAsyncOmit(options, chunk);
- let etag = response.headers.etag;
- if (etag) {
- etag = etag.replace(/^"/, '').replace(/"$/, '');
- } else {
- etag = '';
- }
- eTags.push({
- part: partNumber,
- etag
- });
- }
- return await this.completeMultipartUpload(bucketName, objectName, uploadId, eTags);
- })()]);
- return o;
- }
- async removeBucketReplication(bucketName) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- const method = 'DELETE';
- const query = 'replication';
- await this.makeRequestAsyncOmit({
- method,
- bucketName,
- query
- }, '', [200, 204], '');
- }
- async setBucketReplication(bucketName, replicationConfig) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isObject(replicationConfig)) {
- throw new errors.InvalidArgumentError('replicationConfig should be of type "object"');
- } else {
- if (_.isEmpty(replicationConfig.role)) {
- throw new errors.InvalidArgumentError('Role cannot be empty');
- } else if (replicationConfig.role && !isString(replicationConfig.role)) {
- throw new errors.InvalidArgumentError('Invalid value for role', replicationConfig.role);
- }
- if (_.isEmpty(replicationConfig.rules)) {
- throw new errors.InvalidArgumentError('Minimum one replication rule must be specified');
- }
- }
- const method = 'PUT';
- const query = 'replication';
- const headers = {};
- const replicationParamsConfig = {
- ReplicationConfiguration: {
- Role: replicationConfig.role,
- Rule: replicationConfig.rules
- }
- };
- const builder = new xml2js.Builder({
- renderOpts: {
- pretty: false
- },
- headless: true
- });
- const payload = builder.buildObject(replicationParamsConfig);
- headers['Content-MD5'] = toMd5(payload);
- await this.makeRequestAsyncOmit({
- method,
- bucketName,
- query,
- headers
- }, payload);
- }
- async getBucketReplication(bucketName) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- const method = 'GET';
- const query = 'replication';
- const httpRes = await this.makeRequestAsync({
- method,
- bucketName,
- query
- }, '', [200, 204]);
- const xmlResult = await readAsString(httpRes);
- return xmlParsers.parseReplicationConfig(xmlResult);
- }
- async getObjectLegalHold(bucketName, objectName, getOpts) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- if (getOpts) {
- if (!isObject(getOpts)) {
- throw new TypeError('getOpts should be of type "Object"');
- } else if (Object.keys(getOpts).length > 0 && getOpts.versionId && !isString(getOpts.versionId)) {
- throw new TypeError('versionId should be of type string.:', getOpts.versionId);
- }
- }
- const method = 'GET';
- let query = 'legal-hold';
- if (getOpts !== null && getOpts !== void 0 && getOpts.versionId) {
- query += `&versionId=${getOpts.versionId}`;
- }
- const httpRes = await this.makeRequestAsync({
- method,
- bucketName,
- objectName,
- query
- }, '', [200]);
- const strRes = await readAsString(httpRes);
- return parseObjectLegalHoldConfig(strRes);
- }
- async setObjectLegalHold(bucketName, objectName, setOpts = {
- status: LEGAL_HOLD_STATUS.ENABLED
- }) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- if (!isObject(setOpts)) {
- throw new TypeError('setOpts should be of type "Object"');
- } else {
- if (![LEGAL_HOLD_STATUS.ENABLED, LEGAL_HOLD_STATUS.DISABLED].includes(setOpts === null || setOpts === void 0 ? void 0 : setOpts.status)) {
- throw new TypeError('Invalid status: ' + setOpts.status);
- }
- if (setOpts.versionId && !setOpts.versionId.length) {
- throw new TypeError('versionId should be of type string.:' + setOpts.versionId);
- }
- }
- const method = 'PUT';
- let query = 'legal-hold';
- if (setOpts.versionId) {
- query += `&versionId=${setOpts.versionId}`;
- }
- const config = {
- Status: setOpts.status
- };
- const builder = new xml2js.Builder({
- rootName: 'LegalHold',
- renderOpts: {
- pretty: false
- },
- headless: true
- });
- const payload = builder.buildObject(config);
- const headers = {};
- headers['Content-MD5'] = toMd5(payload);
- await this.makeRequestAsyncOmit({
- method,
- bucketName,
- objectName,
- query,
- headers
- }, payload);
- }
- /**
- * Get Tags associated with a Bucket
- */
- async getBucketTagging(bucketName) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
- }
- const method = 'GET';
- const query = 'tagging';
- const requestOptions = {
- method,
- bucketName,
- query
- };
- const response = await this.makeRequestAsync(requestOptions);
- const body = await readAsString(response);
- return xmlParsers.parseTagging(body);
- }
- /**
- * Get the tags associated with a bucket OR an object
- */
- async getObjectTagging(bucketName, objectName, getOpts) {
- const method = 'GET';
- let query = 'tagging';
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidBucketNameError('Invalid object name: ' + objectName);
- }
- if (getOpts && !isObject(getOpts)) {
- throw new errors.InvalidArgumentError('getOpts should be of type "object"');
- }
- if (getOpts && getOpts.versionId) {
- query = `${query}&versionId=${getOpts.versionId}`;
- }
- const requestOptions = {
- method,
- bucketName,
- query
- };
- if (objectName) {
- requestOptions['objectName'] = objectName;
- }
- const response = await this.makeRequestAsync(requestOptions);
- const body = await readAsString(response);
- return xmlParsers.parseTagging(body);
- }
- /**
- * Set the policy on a bucket or an object prefix.
- */
- async setBucketPolicy(bucketName, policy) {
- // Validate arguments.
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
- }
- if (!isString(policy)) {
- throw new errors.InvalidBucketPolicyError(`Invalid bucket policy: ${policy} - must be "string"`);
- }
- const query = 'policy';
- let method = 'DELETE';
- if (policy) {
- method = 'PUT';
- }
- await this.makeRequestAsyncOmit({
- method,
- bucketName,
- query
- }, policy, [204], '');
- }
- /**
- * Get the policy on a bucket or an object prefix.
- */
- async getBucketPolicy(bucketName) {
- // Validate arguments.
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
- }
- const method = 'GET';
- const query = 'policy';
- const res = await this.makeRequestAsync({
- method,
- bucketName,
- query
- });
- return await readAsString(res);
- }
- async putObjectRetention(bucketName, objectName, retentionOpts = {}) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- if (!isObject(retentionOpts)) {
- throw new errors.InvalidArgumentError('retentionOpts should be of type "object"');
- } else {
- if (retentionOpts.governanceBypass && !isBoolean(retentionOpts.governanceBypass)) {
- throw new errors.InvalidArgumentError(`Invalid value for governanceBypass: ${retentionOpts.governanceBypass}`);
- }
- if (retentionOpts.mode && ![RETENTION_MODES.COMPLIANCE, RETENTION_MODES.GOVERNANCE].includes(retentionOpts.mode)) {
- throw new errors.InvalidArgumentError(`Invalid object retention mode: ${retentionOpts.mode}`);
- }
- if (retentionOpts.retainUntilDate && !isString(retentionOpts.retainUntilDate)) {
- throw new errors.InvalidArgumentError(`Invalid value for retainUntilDate: ${retentionOpts.retainUntilDate}`);
- }
- if (retentionOpts.versionId && !isString(retentionOpts.versionId)) {
- throw new errors.InvalidArgumentError(`Invalid value for versionId: ${retentionOpts.versionId}`);
- }
- }
- const method = 'PUT';
- let query = 'retention';
- const headers = {};
- if (retentionOpts.governanceBypass) {
- headers['X-Amz-Bypass-Governance-Retention'] = true;
- }
- const builder = new xml2js.Builder({
- rootName: 'Retention',
- renderOpts: {
- pretty: false
- },
- headless: true
- });
- const params = {};
- if (retentionOpts.mode) {
- params.Mode = retentionOpts.mode;
- }
- if (retentionOpts.retainUntilDate) {
- params.RetainUntilDate = retentionOpts.retainUntilDate;
- }
- if (retentionOpts.versionId) {
- query += `&versionId=${retentionOpts.versionId}`;
- }
- const payload = builder.buildObject(params);
- headers['Content-MD5'] = toMd5(payload);
- await this.makeRequestAsyncOmit({
- method,
- bucketName,
- objectName,
- query,
- headers
- }, payload, [200, 204]);
- }
- async getObjectLockConfig(bucketName) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- const method = 'GET';
- const query = 'object-lock';
- const httpRes = await this.makeRequestAsync({
- method,
- bucketName,
- query
- });
- const xmlResult = await readAsString(httpRes);
- return xmlParsers.parseObjectLockConfig(xmlResult);
- }
- async setObjectLockConfig(bucketName, lockConfigOpts) {
- const retentionModes = [RETENTION_MODES.COMPLIANCE, RETENTION_MODES.GOVERNANCE];
- const validUnits = [RETENTION_VALIDITY_UNITS.DAYS, RETENTION_VALIDITY_UNITS.YEARS];
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (lockConfigOpts.mode && !retentionModes.includes(lockConfigOpts.mode)) {
- throw new TypeError(`lockConfigOpts.mode should be one of ${retentionModes}`);
- }
- if (lockConfigOpts.unit && !validUnits.includes(lockConfigOpts.unit)) {
- throw new TypeError(`lockConfigOpts.unit should be one of ${validUnits}`);
- }
- if (lockConfigOpts.validity && !isNumber(lockConfigOpts.validity)) {
- throw new TypeError(`lockConfigOpts.validity should be a number`);
- }
- const method = 'PUT';
- const query = 'object-lock';
- const config = {
- ObjectLockEnabled: 'Enabled'
- };
- const configKeys = Object.keys(lockConfigOpts);
- const isAllKeysSet = ['unit', 'mode', 'validity'].every(lck => configKeys.includes(lck));
- // Check if keys are present and all keys are present.
- if (configKeys.length > 0) {
- if (!isAllKeysSet) {
- throw new TypeError(`lockConfigOpts.mode,lockConfigOpts.unit,lockConfigOpts.validity all the properties should be specified.`);
- } else {
- config.Rule = {
- DefaultRetention: {}
- };
- if (lockConfigOpts.mode) {
- config.Rule.DefaultRetention.Mode = lockConfigOpts.mode;
- }
- if (lockConfigOpts.unit === RETENTION_VALIDITY_UNITS.DAYS) {
- config.Rule.DefaultRetention.Days = lockConfigOpts.validity;
- } else if (lockConfigOpts.unit === RETENTION_VALIDITY_UNITS.YEARS) {
- config.Rule.DefaultRetention.Years = lockConfigOpts.validity;
- }
- }
- }
- const builder = new xml2js.Builder({
- rootName: 'ObjectLockConfiguration',
- renderOpts: {
- pretty: false
- },
- headless: true
- });
- const payload = builder.buildObject(config);
- const headers = {};
- headers['Content-MD5'] = toMd5(payload);
- await this.makeRequestAsyncOmit({
- method,
- bucketName,
- query,
- headers
- }, payload);
- }
- async getBucketVersioning(bucketName) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- const method = 'GET';
- const query = 'versioning';
- const httpRes = await this.makeRequestAsync({
- method,
- bucketName,
- query
- });
- const xmlResult = await readAsString(httpRes);
- return await xmlParsers.parseBucketVersioningConfig(xmlResult);
- }
- async setBucketVersioning(bucketName, versionConfig) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!Object.keys(versionConfig).length) {
- throw new errors.InvalidArgumentError('versionConfig should be of type "object"');
- }
- const method = 'PUT';
- const query = 'versioning';
- const builder = new xml2js.Builder({
- rootName: 'VersioningConfiguration',
- renderOpts: {
- pretty: false
- },
- headless: true
- });
- const payload = builder.buildObject(versionConfig);
- await this.makeRequestAsyncOmit({
- method,
- bucketName,
- query
- }, payload);
- }
- async setTagging(taggingParams) {
- const {
- bucketName,
- objectName,
- tags,
- putOpts
- } = taggingParams;
- const method = 'PUT';
- let query = 'tagging';
- if (putOpts && putOpts !== null && putOpts !== void 0 && putOpts.versionId) {
- query = `${query}&versionId=${putOpts.versionId}`;
- }
- const tagsList = [];
- for (const [key, value] of Object.entries(tags)) {
- tagsList.push({
- Key: key,
- Value: value
- });
- }
- const taggingConfig = {
- Tagging: {
- TagSet: {
- Tag: tagsList
- }
- }
- };
- const headers = {};
- const builder = new xml2js.Builder({
- headless: true,
- renderOpts: {
- pretty: false
- }
- });
- const payloadBuf = Buffer.from(builder.buildObject(taggingConfig));
- const requestOptions = {
- method,
- bucketName,
- query,
- headers,
- ...(objectName && {
- objectName: objectName
- })
- };
- headers['Content-MD5'] = toMd5(payloadBuf);
- await this.makeRequestAsyncOmit(requestOptions, payloadBuf);
- }
- async removeTagging({
- bucketName,
- objectName,
- removeOpts
- }) {
- const method = 'DELETE';
- let query = 'tagging';
- if (removeOpts && Object.keys(removeOpts).length && removeOpts.versionId) {
- query = `${query}&versionId=${removeOpts.versionId}`;
- }
- const requestOptions = {
- method,
- bucketName,
- objectName,
- query
- };
- if (objectName) {
- requestOptions['objectName'] = objectName;
- }
- await this.makeRequestAsync(requestOptions, '', [200, 204]);
- }
- async setBucketTagging(bucketName, tags) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isPlainObject(tags)) {
- throw new errors.InvalidArgumentError('tags should be of type "object"');
- }
- if (Object.keys(tags).length > 10) {
- throw new errors.InvalidArgumentError('maximum tags allowed is 10"');
- }
- await this.setTagging({
- bucketName,
- tags
- });
- }
- async removeBucketTagging(bucketName) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- await this.removeTagging({
- bucketName
- });
- }
- async setObjectTagging(bucketName, objectName, tags, putOpts) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidBucketNameError('Invalid object name: ' + objectName);
- }
- if (!isPlainObject(tags)) {
- throw new errors.InvalidArgumentError('tags should be of type "object"');
- }
- if (Object.keys(tags).length > 10) {
- throw new errors.InvalidArgumentError('Maximum tags allowed is 10"');
- }
- await this.setTagging({
- bucketName,
- objectName,
- tags,
- putOpts
- });
- }
- async removeObjectTagging(bucketName, objectName, removeOpts) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidBucketNameError('Invalid object name: ' + objectName);
- }
- if (removeOpts && Object.keys(removeOpts).length && !isObject(removeOpts)) {
- throw new errors.InvalidArgumentError('removeOpts should be of type "object"');
- }
- await this.removeTagging({
- bucketName,
- objectName,
- removeOpts
- });
- }
- async selectObjectContent(bucketName, objectName, selectOpts) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- if (!_.isEmpty(selectOpts)) {
- if (!isString(selectOpts.expression)) {
- throw new TypeError('sqlExpression should be of type "string"');
- }
- if (!_.isEmpty(selectOpts.inputSerialization)) {
- if (!isObject(selectOpts.inputSerialization)) {
- throw new TypeError('inputSerialization should be of type "object"');
- }
- } else {
- throw new TypeError('inputSerialization is required');
- }
- if (!_.isEmpty(selectOpts.outputSerialization)) {
- if (!isObject(selectOpts.outputSerialization)) {
- throw new TypeError('outputSerialization should be of type "object"');
- }
- } else {
- throw new TypeError('outputSerialization is required');
- }
- } else {
- throw new TypeError('valid select configuration is required');
- }
- const method = 'POST';
- const query = `select&select-type=2`;
- const config = [{
- Expression: selectOpts.expression
- }, {
- ExpressionType: selectOpts.expressionType || 'SQL'
- }, {
- InputSerialization: [selectOpts.inputSerialization]
- }, {
- OutputSerialization: [selectOpts.outputSerialization]
- }];
- // Optional
- if (selectOpts.requestProgress) {
- config.push({
- RequestProgress: selectOpts === null || selectOpts === void 0 ? void 0 : selectOpts.requestProgress
- });
- }
- // Optional
- if (selectOpts.scanRange) {
- config.push({
- ScanRange: selectOpts.scanRange
- });
- }
- const builder = new xml2js.Builder({
- rootName: 'SelectObjectContentRequest',
- renderOpts: {
- pretty: false
- },
- headless: true
- });
- const payload = builder.buildObject(config);
- const res = await this.makeRequestAsync({
- method,
- bucketName,
- objectName,
- query
- }, payload);
- const body = await readAsBuffer(res);
- return parseSelectObjectContentResponse(body);
- }
- async applyBucketLifecycle(bucketName, policyConfig) {
- const method = 'PUT';
- const query = 'lifecycle';
- const headers = {};
- const builder = new xml2js.Builder({
- rootName: 'LifecycleConfiguration',
- headless: true,
- renderOpts: {
- pretty: false
- }
- });
- const payload = builder.buildObject(policyConfig);
- headers['Content-MD5'] = toMd5(payload);
- await this.makeRequestAsyncOmit({
- method,
- bucketName,
- query,
- headers
- }, payload);
- }
- async removeBucketLifecycle(bucketName) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- const method = 'DELETE';
- const query = 'lifecycle';
- await this.makeRequestAsyncOmit({
- method,
- bucketName,
- query
- }, '', [204]);
- }
- async setBucketLifecycle(bucketName, lifeCycleConfig) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (_.isEmpty(lifeCycleConfig)) {
- await this.removeBucketLifecycle(bucketName);
- } else {
- await this.applyBucketLifecycle(bucketName, lifeCycleConfig);
- }
- }
- async getBucketLifecycle(bucketName) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- const method = 'GET';
- const query = 'lifecycle';
- const res = await this.makeRequestAsync({
- method,
- bucketName,
- query
- });
- const body = await readAsString(res);
- return xmlParsers.parseLifecycleConfig(body);
- }
- async setBucketEncryption(bucketName, encryptionConfig) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!_.isEmpty(encryptionConfig) && encryptionConfig.Rule.length > 1) {
- throw new errors.InvalidArgumentError('Invalid Rule length. Only one rule is allowed.: ' + encryptionConfig.Rule);
- }
- let encryptionObj = encryptionConfig;
- if (_.isEmpty(encryptionConfig)) {
- encryptionObj = {
- // Default MinIO Server Supported Rule
- Rule: [{
- ApplyServerSideEncryptionByDefault: {
- SSEAlgorithm: 'AES256'
- }
- }]
- };
- }
- const method = 'PUT';
- const query = 'encryption';
- const builder = new xml2js.Builder({
- rootName: 'ServerSideEncryptionConfiguration',
- renderOpts: {
- pretty: false
- },
- headless: true
- });
- const payload = builder.buildObject(encryptionObj);
- const headers = {};
- headers['Content-MD5'] = toMd5(payload);
- await this.makeRequestAsyncOmit({
- method,
- bucketName,
- query,
- headers
- }, payload);
- }
- async getBucketEncryption(bucketName) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- const method = 'GET';
- const query = 'encryption';
- const res = await this.makeRequestAsync({
- method,
- bucketName,
- query
- });
- const body = await readAsString(res);
- return xmlParsers.parseBucketEncryptionConfig(body);
- }
- async removeBucketEncryption(bucketName) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- const method = 'DELETE';
- const query = 'encryption';
- await this.makeRequestAsyncOmit({
- method,
- bucketName,
- query
- }, '', [204]);
- }
- async getObjectRetention(bucketName, objectName, getOpts) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- if (getOpts && !isObject(getOpts)) {
- throw new errors.InvalidArgumentError('getOpts should be of type "object"');
- } else if (getOpts !== null && getOpts !== void 0 && getOpts.versionId && !isString(getOpts.versionId)) {
- throw new errors.InvalidArgumentError('versionId should be of type "string"');
- }
- const method = 'GET';
- let query = 'retention';
- if (getOpts !== null && getOpts !== void 0 && getOpts.versionId) {
- query += `&versionId=${getOpts.versionId}`;
- }
- const res = await this.makeRequestAsync({
- method,
- bucketName,
- objectName,
- query
- });
- const body = await readAsString(res);
- return xmlParsers.parseObjectRetentionConfig(body);
- }
- async removeObjects(bucketName, objectsList) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!Array.isArray(objectsList)) {
- throw new errors.InvalidArgumentError('objectsList should be a list');
- }
- const runDeleteObjects = async batch => {
- const delObjects = batch.map(value => {
- return isObject(value) ? {
- Key: value.name,
- VersionId: value.versionId
- } : {
- Key: value
- };
- });
- const remObjects = {
- Delete: {
- Quiet: true,
- Object: delObjects
- }
- };
- const payload = Buffer.from(new xml2js.Builder({
- headless: true
- }).buildObject(remObjects));
- const headers = {
- 'Content-MD5': toMd5(payload)
- };
- const res = await this.makeRequestAsync({
- method: 'POST',
- bucketName,
- query: 'delete',
- headers
- }, payload);
- const body = await readAsString(res);
- return xmlParsers.removeObjectsParser(body);
- };
- const maxEntries = 1000; // max entries accepted in server for DeleteMultipleObjects API.
- // Client side batching
- const batches = [];
- for (let i = 0; i < objectsList.length; i += maxEntries) {
- batches.push(objectsList.slice(i, i + maxEntries));
- }
- const batchResults = await Promise.all(batches.map(runDeleteObjects));
- return batchResults.flat();
- }
- async removeIncompleteUpload(bucketName, objectName) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.IsValidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- const removeUploadId = await this.findUploadId(bucketName, objectName);
- const method = 'DELETE';
- const query = `uploadId=${removeUploadId}`;
- await this.makeRequestAsyncOmit({
- method,
- bucketName,
- objectName,
- query
- }, '', [204]);
- }
- async copyObjectV1(targetBucketName, targetObjectName, sourceBucketNameAndObjectName, conditions) {
- if (typeof conditions == 'function') {
- conditions = null;
- }
- if (!isValidBucketName(targetBucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + targetBucketName);
- }
- if (!isValidObjectName(targetObjectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${targetObjectName}`);
- }
- if (!isString(sourceBucketNameAndObjectName)) {
- throw new TypeError('sourceBucketNameAndObjectName should be of type "string"');
- }
- if (sourceBucketNameAndObjectName === '') {
- throw new errors.InvalidPrefixError(`Empty source prefix`);
- }
- if (conditions != null && !(conditions instanceof CopyConditions)) {
- throw new TypeError('conditions should be of type "CopyConditions"');
- }
- const headers = {};
- headers['x-amz-copy-source'] = uriResourceEscape(sourceBucketNameAndObjectName);
- if (conditions) {
- if (conditions.modified !== '') {
- headers['x-amz-copy-source-if-modified-since'] = conditions.modified;
- }
- if (conditions.unmodified !== '') {
- headers['x-amz-copy-source-if-unmodified-since'] = conditions.unmodified;
- }
- if (conditions.matchETag !== '') {
- headers['x-amz-copy-source-if-match'] = conditions.matchETag;
- }
- if (conditions.matchETagExcept !== '') {
- headers['x-amz-copy-source-if-none-match'] = conditions.matchETagExcept;
- }
- }
- const method = 'PUT';
- const res = await this.makeRequestAsync({
- method,
- bucketName: targetBucketName,
- objectName: targetObjectName,
- headers
- });
- const body = await readAsString(res);
- return xmlParsers.parseCopyObject(body);
- }
- async copyObjectV2(sourceConfig, destConfig) {
- if (!(sourceConfig instanceof CopySourceOptions)) {
- throw new errors.InvalidArgumentError('sourceConfig should of type CopySourceOptions ');
- }
- if (!(destConfig instanceof CopyDestinationOptions)) {
- throw new errors.InvalidArgumentError('destConfig should of type CopyDestinationOptions ');
- }
- if (!destConfig.validate()) {
- return Promise.reject();
- }
- if (!destConfig.validate()) {
- return Promise.reject();
- }
- const headers = Object.assign({}, sourceConfig.getHeaders(), destConfig.getHeaders());
- const bucketName = destConfig.Bucket;
- const objectName = destConfig.Object;
- const method = 'PUT';
- const res = await this.makeRequestAsync({
- method,
- bucketName,
- objectName,
- headers
- });
- const body = await readAsString(res);
- const copyRes = xmlParsers.parseCopyObject(body);
- const resHeaders = res.headers;
- const sizeHeaderValue = resHeaders && resHeaders['content-length'];
- const size = typeof sizeHeaderValue === 'number' ? sizeHeaderValue : undefined;
- return {
- Bucket: destConfig.Bucket,
- Key: destConfig.Object,
- LastModified: copyRes.lastModified,
- MetaData: extractMetadata(resHeaders),
- VersionId: getVersionId(resHeaders),
- SourceVersionId: getSourceVersionId(resHeaders),
- Etag: sanitizeETag(resHeaders.etag),
- Size: size
- };
- }
- async copyObject(...allArgs) {
- if (typeof allArgs[0] === 'string') {
- const [targetBucketName, targetObjectName, sourceBucketNameAndObjectName, conditions] = allArgs;
- return await this.copyObjectV1(targetBucketName, targetObjectName, sourceBucketNameAndObjectName, conditions);
- }
- const [source, dest] = allArgs;
- return await this.copyObjectV2(source, dest);
- }
- async uploadPart(partConfig, payload) {
- const {
- bucketName,
- objectName,
- uploadID,
- partNumber,
- headers
- } = partConfig;
- const method = 'PUT';
- const query = `uploadId=${uploadID}&partNumber=${partNumber}`;
- const requestOptions = {
- method,
- bucketName,
- objectName: objectName,
- query,
- headers
- };
- const res = await this.makeRequestAsync(requestOptions, payload);
- const body = await readAsString(res);
- const partRes = uploadPartParser(body);
- const partEtagVal = sanitizeETag(res.headers.etag) || sanitizeETag(partRes.ETag);
- return {
- etag: partEtagVal,
- key: objectName,
- part: partNumber
- };
- }
- async composeObject(destObjConfig, sourceObjList, {
- maxConcurrency = 10
- } = {}) {
- const sourceFilesLength = sourceObjList.length;
- if (!Array.isArray(sourceObjList)) {
- throw new errors.InvalidArgumentError('sourceConfig should an array of CopySourceOptions ');
- }
- if (!(destObjConfig instanceof CopyDestinationOptions)) {
- throw new errors.InvalidArgumentError('destConfig should of type CopyDestinationOptions ');
- }
- if (sourceFilesLength < 1 || sourceFilesLength > PART_CONSTRAINTS.MAX_PARTS_COUNT) {
- throw new errors.InvalidArgumentError(`"There must be as least one and up to ${PART_CONSTRAINTS.MAX_PARTS_COUNT} source objects.`);
- }
- for (let i = 0; i < sourceFilesLength; i++) {
- const sObj = sourceObjList[i];
- if (!sObj.validate()) {
- return false;
- }
- }
- if (!destObjConfig.validate()) {
- return false;
- }
- const getStatOptions = srcConfig => {
- let statOpts = {};
- if (!_.isEmpty(srcConfig.VersionID)) {
- statOpts = {
- versionId: srcConfig.VersionID
- };
- }
- return statOpts;
- };
- const srcObjectSizes = [];
- let totalSize = 0;
- let totalParts = 0;
- const sourceObjStats = sourceObjList.map(srcItem => this.statObject(srcItem.Bucket, srcItem.Object, getStatOptions(srcItem)));
- const srcObjectInfos = await Promise.all(sourceObjStats);
- const validatedStats = srcObjectInfos.map((resItemStat, index) => {
- const srcConfig = sourceObjList[index];
- let srcCopySize = resItemStat.size;
- // Check if a segment is specified, and if so, is the
- // segment within object bounds?
- if (srcConfig && srcConfig.MatchRange) {
- // Since range is specified,
- // 0 <= src.srcStart <= src.srcEnd
- // so only invalid case to check is:
- const srcStart = srcConfig.Start;
- const srcEnd = srcConfig.End;
- if (srcEnd >= srcCopySize || srcStart < 0) {
- throw new errors.InvalidArgumentError(`CopySrcOptions ${index} has invalid segment-to-copy [${srcStart}, ${srcEnd}] (size is ${srcCopySize})`);
- }
- srcCopySize = srcEnd - srcStart + 1;
- }
- // Only the last source may be less than `absMinPartSize`
- if (srcCopySize < PART_CONSTRAINTS.ABS_MIN_PART_SIZE && index < sourceFilesLength - 1) {
- throw new errors.InvalidArgumentError(`CopySrcOptions ${index} is too small (${srcCopySize}) and it is not the last part.`);
- }
- // Is data to copy too large?
- totalSize += srcCopySize;
- if (totalSize > PART_CONSTRAINTS.MAX_MULTIPART_PUT_OBJECT_SIZE) {
- throw new errors.InvalidArgumentError(`Cannot compose an object of size ${totalSize} (> 5TiB)`);
- }
- // record source size
- srcObjectSizes[index] = srcCopySize;
- // calculate parts needed for current source
- totalParts += partsRequired(srcCopySize);
- // Do we need more parts than we are allowed?
- if (totalParts > PART_CONSTRAINTS.MAX_PARTS_COUNT) {
- throw new errors.InvalidArgumentError(`Your proposed compose object requires more than ${PART_CONSTRAINTS.MAX_PARTS_COUNT} parts`);
- }
- return resItemStat;
- });
- if (totalParts === 1 && totalSize <= PART_CONSTRAINTS.MAX_PART_SIZE || totalSize === 0) {
- return await this.copyObject(sourceObjList[0], destObjConfig); // use copyObjectV2
- }
- // preserve etag to avoid modification of object while copying.
- for (let i = 0; i < sourceFilesLength; i++) {
- ;
- sourceObjList[i].MatchETag = validatedStats[i].etag;
- }
- const splitPartSizeList = validatedStats.map((resItemStat, idx) => {
- return calculateEvenSplits(srcObjectSizes[idx], sourceObjList[idx]);
- });
- const getUploadPartConfigList = uploadId => {
- const uploadPartConfigList = [];
- splitPartSizeList.forEach((splitSize, splitIndex) => {
- if (splitSize) {
- const {
- startIndex: startIdx,
- endIndex: endIdx,
- objInfo: objConfig
- } = splitSize;
- const partIndex = splitIndex + 1; // part index starts from 1.
- const totalUploads = Array.from(startIdx);
- const headers = sourceObjList[splitIndex].getHeaders();
- totalUploads.forEach((splitStart, upldCtrIdx) => {
- const splitEnd = endIdx[upldCtrIdx];
- const sourceObj = `${objConfig.Bucket}/${objConfig.Object}`;
- headers['x-amz-copy-source'] = `${sourceObj}`;
- headers['x-amz-copy-source-range'] = `bytes=${splitStart}-${splitEnd}`;
- const uploadPartConfig = {
- bucketName: destObjConfig.Bucket,
- objectName: destObjConfig.Object,
- uploadID: uploadId,
- partNumber: partIndex,
- headers: headers,
- sourceObj: sourceObj
- };
- uploadPartConfigList.push(uploadPartConfig);
- });
- }
- });
- return uploadPartConfigList;
- };
- const uploadAllParts = async uploadList => {
- const partUploads = [];
- // Process upload parts in batches to avoid too many concurrent requests
- for (const batch of _.chunk(uploadList, maxConcurrency)) {
- const batchResults = await Promise.all(batch.map(item => this.uploadPart(item)));
- partUploads.push(...batchResults);
- }
- // Process results here if needed
- return partUploads;
- };
- const performUploadParts = async uploadId => {
- const uploadList = getUploadPartConfigList(uploadId);
- const partsRes = await uploadAllParts(uploadList);
- return partsRes.map(partCopy => ({
- etag: partCopy.etag,
- part: partCopy.part
- }));
- };
- const newUploadHeaders = destObjConfig.getHeaders();
- const uploadId = await this.initiateNewMultipartUpload(destObjConfig.Bucket, destObjConfig.Object, newUploadHeaders);
- try {
- const partsDone = await performUploadParts(uploadId);
- return await this.completeMultipartUpload(destObjConfig.Bucket, destObjConfig.Object, uploadId, partsDone);
- } catch (err) {
- return await this.abortMultipartUpload(destObjConfig.Bucket, destObjConfig.Object, uploadId);
- }
- }
- async presignedUrl(method, bucketName, objectName, expires, reqParams, requestDate) {
- var _requestDate;
- if (this.anonymous) {
- throw new errors.AnonymousRequestError(`Presigned ${method} url cannot be generated for anonymous requests`);
- }
- if (!expires) {
- expires = PRESIGN_EXPIRY_DAYS_MAX;
- }
- if (!reqParams) {
- reqParams = {};
- }
- if (!requestDate) {
- requestDate = new Date();
- }
- // Type assertions
- if (expires && typeof expires !== 'number') {
- throw new TypeError('expires should be of type "number"');
- }
- if (reqParams && typeof reqParams !== 'object') {
- throw new TypeError('reqParams should be of type "object"');
- }
- if (requestDate && !(requestDate instanceof Date) || requestDate && isNaN((_requestDate = requestDate) === null || _requestDate === void 0 ? void 0 : _requestDate.getTime())) {
- throw new TypeError('requestDate should be of type "Date" and valid');
- }
- const query = reqParams ? qs.stringify(reqParams) : undefined;
- try {
- const region = await this.getBucketRegionAsync(bucketName);
- await this.checkAndRefreshCreds();
- const reqOptions = this.getRequestOptions({
- method,
- region,
- bucketName,
- objectName,
- query
- });
- return presignSignatureV4(reqOptions, this.accessKey, this.secretKey, this.sessionToken, region, requestDate, expires);
- } catch (err) {
- if (err instanceof errors.InvalidBucketNameError) {
- throw new errors.InvalidArgumentError(`Unable to get bucket region for ${bucketName}.`);
- }
- throw err;
- }
- }
- async presignedGetObject(bucketName, objectName, expires, respHeaders, requestDate) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- const validRespHeaders = ['response-content-type', 'response-content-language', 'response-expires', 'response-cache-control', 'response-content-disposition', 'response-content-encoding'];
- validRespHeaders.forEach(header => {
- // @ts-ignore
- if (respHeaders !== undefined && respHeaders[header] !== undefined && !isString(respHeaders[header])) {
- throw new TypeError(`response header ${header} should be of type "string"`);
- }
- });
- return this.presignedUrl('GET', bucketName, objectName, expires, respHeaders, requestDate);
- }
- async presignedPutObject(bucketName, objectName, expires) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
- }
- if (!isValidObjectName(objectName)) {
- throw new errors.InvalidObjectNameError(`Invalid object name: ${objectName}`);
- }
- return this.presignedUrl('PUT', bucketName, objectName, expires);
- }
- newPostPolicy() {
- return new PostPolicy();
- }
- async presignedPostPolicy(postPolicy) {
- if (this.anonymous) {
- throw new errors.AnonymousRequestError('Presigned POST policy cannot be generated for anonymous requests');
- }
- if (!isObject(postPolicy)) {
- throw new TypeError('postPolicy should be of type "object"');
- }
- const bucketName = postPolicy.formData.bucket;
- try {
- const region = await this.getBucketRegionAsync(bucketName);
- const date = new Date();
- const dateStr = makeDateLong(date);
- await this.checkAndRefreshCreds();
- if (!postPolicy.policy.expiration) {
- // 'expiration' is mandatory field for S3.
- // Set default expiration date of 7 days.
- const expires = new Date();
- expires.setSeconds(PRESIGN_EXPIRY_DAYS_MAX);
- postPolicy.setExpires(expires);
- }
- postPolicy.policy.conditions.push(['eq', '$x-amz-date', dateStr]);
- postPolicy.formData['x-amz-date'] = dateStr;
- postPolicy.policy.conditions.push(['eq', '$x-amz-algorithm', 'AWS4-HMAC-SHA256']);
- postPolicy.formData['x-amz-algorithm'] = 'AWS4-HMAC-SHA256';
- postPolicy.policy.conditions.push(['eq', '$x-amz-credential', this.accessKey + '/' + getScope(region, date)]);
- postPolicy.formData['x-amz-credential'] = this.accessKey + '/' + getScope(region, date);
- if (this.sessionToken) {
- postPolicy.policy.conditions.push(['eq', '$x-amz-security-token', this.sessionToken]);
- postPolicy.formData['x-amz-security-token'] = this.sessionToken;
- }
- const policyBase64 = Buffer.from(JSON.stringify(postPolicy.policy)).toString('base64');
- postPolicy.formData.policy = policyBase64;
- postPolicy.formData['x-amz-signature'] = postPresignSignatureV4(region, date, this.secretKey, policyBase64);
- const opts = {
- region: region,
- bucketName: bucketName,
- method: 'POST'
- };
- const reqOptions = this.getRequestOptions(opts);
- const portStr = this.port == 80 || this.port === 443 ? '' : `:${this.port.toString()}`;
- const urlStr = `${reqOptions.protocol}//${reqOptions.host}${portStr}${reqOptions.path}`;
- return {
- postURL: urlStr,
- formData: postPolicy.formData
- };
- } catch (err) {
- if (err instanceof errors.InvalidBucketNameError) {
- throw new errors.InvalidArgumentError(`Unable to get bucket region for ${bucketName}.`);
- }
- throw err;
- }
- }
- // list a batch of objects
- async listObjectsQuery(bucketName, prefix, marker, listQueryOpts) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isString(prefix)) {
- throw new TypeError('prefix should be of type "string"');
- }
- if (marker && !isString(marker)) {
- throw new TypeError('marker should be of type "string"');
- }
- if (listQueryOpts && !isObject(listQueryOpts)) {
- throw new TypeError('listQueryOpts should be of type "object"');
- }
- let {
- Delimiter,
- MaxKeys,
- IncludeVersion,
- versionIdMarker,
- keyMarker
- } = listQueryOpts;
- if (!isString(Delimiter)) {
- throw new TypeError('Delimiter should be of type "string"');
- }
- if (!isNumber(MaxKeys)) {
- throw new TypeError('MaxKeys should be of type "number"');
- }
- const queries = [];
- // escape every value in query string, except maxKeys
- queries.push(`prefix=${uriEscape(prefix)}`);
- queries.push(`delimiter=${uriEscape(Delimiter)}`);
- queries.push(`encoding-type=url`);
- if (IncludeVersion) {
- queries.push(`versions`);
- }
- if (IncludeVersion) {
- // v1 version listing..
- if (keyMarker) {
- queries.push(`key-marker=${keyMarker}`);
- }
- if (versionIdMarker) {
- queries.push(`version-id-marker=${versionIdMarker}`);
- }
- } else if (marker) {
- marker = uriEscape(marker);
- queries.push(`marker=${marker}`);
- }
- // no need to escape maxKeys
- if (MaxKeys) {
- if (MaxKeys >= 1000) {
- MaxKeys = 1000;
- }
- queries.push(`max-keys=${MaxKeys}`);
- }
- queries.sort();
- let query = '';
- if (queries.length > 0) {
- query = `${queries.join('&')}`;
- }
- const method = 'GET';
- const res = await this.makeRequestAsync({
- method,
- bucketName,
- query
- });
- const body = await readAsString(res);
- const listQryList = parseListObjects(body);
- return listQryList;
- }
- listObjects(bucketName, prefix, recursive, listOpts) {
- if (prefix === undefined) {
- prefix = '';
- }
- if (recursive === undefined) {
- recursive = false;
- }
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidPrefix(prefix)) {
- throw new errors.InvalidPrefixError(`Invalid prefix : ${prefix}`);
- }
- if (!isString(prefix)) {
- throw new TypeError('prefix should be of type "string"');
- }
- if (!isBoolean(recursive)) {
- throw new TypeError('recursive should be of type "boolean"');
- }
- if (listOpts && !isObject(listOpts)) {
- throw new TypeError('listOpts should be of type "object"');
- }
- let marker = '';
- let keyMarker = '';
- let versionIdMarker = '';
- let objects = [];
- let ended = false;
- const readStream = new stream.Readable({
- objectMode: true
- });
- readStream._read = async () => {
- // push one object per _read()
- if (objects.length) {
- readStream.push(objects.shift());
- return;
- }
- if (ended) {
- return readStream.push(null);
- }
- try {
- const listQueryOpts = {
- Delimiter: recursive ? '' : '/',
- // if recursive is false set delimiter to '/'
- MaxKeys: 1000,
- IncludeVersion: listOpts === null || listOpts === void 0 ? void 0 : listOpts.IncludeVersion,
- // version listing specific options
- keyMarker: keyMarker,
- versionIdMarker: versionIdMarker
- };
- const result = await this.listObjectsQuery(bucketName, prefix, marker, listQueryOpts);
- if (result.isTruncated) {
- marker = result.nextMarker || undefined;
- if (result.keyMarker) {
- keyMarker = result.keyMarker;
- }
- if (result.versionIdMarker) {
- versionIdMarker = result.versionIdMarker;
- }
- } else {
- ended = true;
- }
- if (result.objects) {
- objects = result.objects;
- }
- // @ts-ignore
- readStream._read();
- } catch (err) {
- readStream.emit('error', err);
- }
- };
- return readStream;
- }
- async listObjectsV2Query(bucketName, prefix, continuationToken, delimiter, maxKeys, startAfter) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isString(prefix)) {
- throw new TypeError('prefix should be of type "string"');
- }
- if (!isString(continuationToken)) {
- throw new TypeError('continuationToken should be of type "string"');
- }
- if (!isString(delimiter)) {
- throw new TypeError('delimiter should be of type "string"');
- }
- if (!isNumber(maxKeys)) {
- throw new TypeError('maxKeys should be of type "number"');
- }
- if (!isString(startAfter)) {
- throw new TypeError('startAfter should be of type "string"');
- }
- const queries = [];
- queries.push(`list-type=2`);
- queries.push(`encoding-type=url`);
- queries.push(`prefix=${uriEscape(prefix)}`);
- queries.push(`delimiter=${uriEscape(delimiter)}`);
- if (continuationToken) {
- queries.push(`continuation-token=${uriEscape(continuationToken)}`);
- }
- if (startAfter) {
- queries.push(`start-after=${uriEscape(startAfter)}`);
- }
- if (maxKeys) {
- if (maxKeys >= 1000) {
- maxKeys = 1000;
- }
- queries.push(`max-keys=${maxKeys}`);
- }
- queries.sort();
- let query = '';
- if (queries.length > 0) {
- query = `${queries.join('&')}`;
- }
- const method = 'GET';
- const res = await this.makeRequestAsync({
- method,
- bucketName,
- query
- });
- const body = await readAsString(res);
- return parseListObjectsV2(body);
- }
- listObjectsV2(bucketName, prefix, recursive, startAfter) {
- if (prefix === undefined) {
- prefix = '';
- }
- if (recursive === undefined) {
- recursive = false;
- }
- if (startAfter === undefined) {
- startAfter = '';
- }
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isValidPrefix(prefix)) {
- throw new errors.InvalidPrefixError(`Invalid prefix : ${prefix}`);
- }
- if (!isString(prefix)) {
- throw new TypeError('prefix should be of type "string"');
- }
- if (!isBoolean(recursive)) {
- throw new TypeError('recursive should be of type "boolean"');
- }
- if (!isString(startAfter)) {
- throw new TypeError('startAfter should be of type "string"');
- }
- const delimiter = recursive ? '' : '/';
- const prefixStr = prefix;
- const startAfterStr = startAfter;
- let continuationToken = '';
- let objects = [];
- let ended = false;
- const readStream = new stream.Readable({
- objectMode: true
- });
- readStream._read = async () => {
- if (objects.length) {
- readStream.push(objects.shift());
- return;
- }
- if (ended) {
- return readStream.push(null);
- }
- try {
- const result = await this.listObjectsV2Query(bucketName, prefixStr, continuationToken, delimiter, 1000, startAfterStr);
- if (result.isTruncated) {
- continuationToken = result.nextContinuationToken;
- } else {
- ended = true;
- }
- objects = result.objects;
- // @ts-ignore
- readStream._read();
- } catch (err) {
- readStream.emit('error', err);
- }
- };
- return readStream;
- }
- async setBucketNotification(bucketName, config) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- if (!isObject(config)) {
- throw new TypeError('notification config should be of type "Object"');
- }
- const method = 'PUT';
- const query = 'notification';
- const builder = new xml2js.Builder({
- rootName: 'NotificationConfiguration',
- renderOpts: {
- pretty: false
- },
- headless: true
- });
- const payload = builder.buildObject(config);
- await this.makeRequestAsyncOmit({
- method,
- bucketName,
- query
- }, payload);
- }
- async removeAllBucketNotification(bucketName) {
- await this.setBucketNotification(bucketName, new NotificationConfig());
- }
- async getBucketNotification(bucketName) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName);
- }
- const method = 'GET';
- const query = 'notification';
- const res = await this.makeRequestAsync({
- method,
- bucketName,
- query
- });
- const body = await readAsString(res);
- return parseBucketNotification(body);
- }
- listenBucketNotification(bucketName, prefix, suffix, events) {
- if (!isValidBucketName(bucketName)) {
- throw new errors.InvalidBucketNameError(`Invalid bucket name: ${bucketName}`);
- }
- if (!isString(prefix)) {
- throw new TypeError('prefix must be of type string');
- }
- if (!isString(suffix)) {
- throw new TypeError('suffix must be of type string');
- }
- if (!Array.isArray(events)) {
- throw new TypeError('events must be of type Array');
- }
- const listener = new NotificationPoller(this, bucketName, prefix, suffix, events);
- listener.start();
- return listener;
- }
- }
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJjcnlwdG8iLCJmcyIsImh0dHAiLCJodHRwcyIsInBhdGgiLCJzdHJlYW0iLCJhc3luYyIsIkJsb2NrU3RyZWFtMiIsImlzQnJvd3NlciIsIl8iLCJxcyIsInhtbDJqcyIsIkNyZWRlbnRpYWxQcm92aWRlciIsImVycm9ycyIsIkNvcHlEZXN0aW5hdGlvbk9wdGlvbnMiLCJDb3B5U291cmNlT3B0aW9ucyIsIkRFRkFVTFRfUkVHSU9OIiwiTEVHQUxfSE9MRF9TVEFUVVMiLCJQUkVTSUdOX0VYUElSWV9EQVlTX01BWCIsIlJFVEVOVElPTl9NT0RFUyIsIlJFVEVOVElPTl9WQUxJRElUWV9VTklUUyIsIk5vdGlmaWNhdGlvbkNvbmZpZyIsIk5vdGlmaWNhdGlvblBvbGxlciIsInBvc3RQcmVzaWduU2lnbmF0dXJlVjQiLCJwcmVzaWduU2lnbmF0dXJlVjQiLCJzaWduVjQiLCJmc3AiLCJzdHJlYW1Qcm9taXNlIiwiQ29weUNvbmRpdGlvbnMiLCJFeHRlbnNpb25zIiwiY2FsY3VsYXRlRXZlblNwbGl0cyIsImV4dHJhY3RNZXRhZGF0YSIsImdldENvbnRlbnRMZW5ndGgiLCJnZXRTY29wZSIsImdldFNvdXJjZVZlcnNpb25JZCIsImdldFZlcnNpb25JZCIsImhhc2hCaW5hcnkiLCJpbnNlcnRDb250ZW50VHlwZSIsImlzQW1hem9uRW5kcG9pbnQiLCJpc0Jvb2xlYW4iLCJpc0RlZmluZWQiLCJpc0VtcHR5IiwiaXNOdW1iZXIiLCJpc09iamVjdCIsImlzUGxhaW5PYmplY3QiLCJpc1JlYWRhYmxlU3RyZWFtIiwiaXNTdHJpbmciLCJpc1ZhbGlkQnVja2V0TmFtZSIsImlzVmFsaWRFbmRwb2ludCIsImlzVmFsaWRPYmplY3ROYW1lIiwiaXNWYWxpZFBvcnQiLCJpc1ZhbGlkUHJlZml4IiwiaXNWaXJ0dWFsSG9zdFN0eWxlIiwibWFrZURhdGVMb25nIiwiUEFSVF9DT05TVFJBSU5UUyIsInBhcnRzUmVxdWlyZWQiLCJwcmVwZW5kWEFNWk1ldGEiLCJyZWFkYWJsZVN0cmVhbSIsInNhbml0aXplRVRhZyIsInRvTWQ1IiwidG9TaGEyNTYiLCJ1cmlFc2NhcGUiLCJ1cmlSZXNvdXJjZUVzY2FwZSIsImpvaW5Ib3N0UG9ydCIsIlBvc3RQb2xpY3kiLCJyZXF1ZXN0V2l0aFJldHJ5IiwiZHJhaW5SZXNwb25zZSIsInJlYWRBc0J1ZmZlciIsInJlYWRBc1N0cmluZyIsImdldFMzRW5kcG9pbnQiLCJwYXJzZUJ1Y2tldE5vdGlmaWNhdGlvbiIsInBhcnNlQ29tcGxldGVNdWx0aXBhcnQiLCJwYXJzZUluaXRpYXRlTXVsdGlwYXJ0IiwicGFyc2VMaXN0T2JqZWN0cyIsInBhcnNlTGlzdE9iamVjdHNWMiIsInBhcnNlT2JqZWN0TGVnYWxIb2xkQ29uZmlnIiwicGFyc2VTZWxlY3RPYmplY3RDb250ZW50UmVzcG9uc2UiLCJ1cGxvYWRQYXJ0UGFyc2VyIiwieG1sUGFyc2VycyIsInhtbCIsIkJ1aWxkZXIiLCJyZW5kZXJPcHRzIiwicHJldHR5IiwiaGVhZGxlc3MiLCJQYWNrYWdlIiwidmVyc2lvbiIsInJlcXVlc3RPcHRpb25Qcm9wZXJ0aWVzIiwiVHlwZWRDbGllbnQiLCJwYXJ0U2l6ZSIsIm1heGltdW1QYXJ0U2l6ZSIsIm1heE9iamVjdFNpemUiLCJjb25zdHJ1Y3RvciIsInBhcmFtcyIsInNlY3VyZSIsInVuZGVmaW5lZCIsIkVycm9yIiwidXNlU1NMIiwicG9ydCIsImVuZFBvaW50IiwiSW52YWxpZEVuZHBvaW50RXJyb3IiLCJJbnZhbGlkQXJndW1lbnRFcnJvciIsInJlZ2lvbiIsImhvc3QiLCJ0b0xvd2VyQ2FzZSIsInByb3RvY29sIiwidHJhbnNwb3J0IiwidHJhbnNwb3J0QWdlbnQiLCJnbG9iYWxBZ2VudCIsImxpYnJhcnlDb21tZW50cyIsInByb2Nlc3MiLCJwbGF0Zm9ybSIsImFyY2giLCJsaWJyYXJ5QWdlbnQiLCJ1c2VyQWdlbnQiLCJwYXRoU3R5bGUiLCJhY2Nlc3NLZXkiLCJzZWNyZXRLZXkiLCJzZXNzaW9uVG9rZW4iLCJhbm9ueW1vdXMiLCJjcmVkZW50aWFsc1Byb3ZpZGVyIiwicmVnaW9uTWFwIiwib3ZlclJpZGVQYXJ0U2l6ZSIsImVuYWJsZVNIQTI1NiIsInMzQWNjZWxlcmF0ZUVuZHBvaW50IiwicmVxT3B0aW9ucyIsImNsaWVudEV4dGVuc2lvbnMiLCJyZXRyeU9wdGlvbnMiLCJkaXNhYmxlUmV0cnkiLCJleHRlbnNpb25zIiwic2V0UzNUcmFuc2ZlckFjY2VsZXJhdGUiLCJzZXRSZXF1ZXN0T3B0aW9ucyIsIm9wdGlvbnMiLCJUeXBlRXJyb3IiLCJwaWNrIiwiZ2V0QWNjZWxlcmF0ZUVuZFBvaW50SWZTZXQiLCJidWNrZXROYW1lIiwib2JqZWN0TmFtZSIsImluY2x1ZGVzIiwic2V0QXBwSW5mbyIsImFwcE5hbWUiLCJhcHBWZXJzaW9uIiwidHJpbSIsImdldFJlcXVlc3RPcHRpb25zIiwib3B0cyIsIm1ldGhvZCIsImhlYWRlcnMiLCJxdWVyeSIsImFnZW50IiwidmlydHVhbEhvc3RTdHlsZSIsImFjY2VsZXJhdGVFbmRQb2ludCIsImsiLCJ2IiwiT2JqZWN0IiwiZW50cmllcyIsImFzc2lnbiIsIm1hcFZhbHVlcyIsInBpY2tCeSIsInRvU3RyaW5nIiwic2V0Q3JlZGVudGlhbHNQcm92aWRlciIsImNoZWNrQW5kUmVmcmVzaENyZWRzIiwiY3JlZGVudGlhbHNDb25mIiwiZ2V0Q3JlZGVudGlhbHMiLCJnZXRBY2Nlc3NLZXkiLCJnZXRTZWNyZXRLZXkiLCJnZXRTZXNzaW9uVG9rZW4iLCJlIiwiY2F1c2UiLCJsb2dIVFRQIiwicmVzcG9uc2UiLCJlcnIiLCJsb2dTdHJlYW0iLCJsb2dIZWFkZXJzIiwiZm9yRWFjaCIsInJlZGFjdG9yIiwiUmVnRXhwIiwicmVwbGFjZSIsIndyaXRlIiwic3RhdHVzQ29kZSIsImVyckpTT04iLCJKU09OIiwic3RyaW5naWZ5IiwidHJhY2VPbiIsInN0ZG91dCIsInRyYWNlT2ZmIiwibWFrZVJlcXVlc3RBc3luYyIsInBheWxvYWQiLCJleHBlY3RlZENvZGVzIiwibGVuZ3RoIiwic2hhMjU2c3VtIiwibWFrZVJlcXVlc3RTdHJlYW1Bc3luYyIsIm1ha2VSZXF1ZXN0QXN5bmNPbWl0Iiwic3RhdHVzQ29kZXMiLCJyZXMiLCJib2R5IiwiQnVmZmVyIiwiaXNCdWZmZXIiLCJnZXRCdWNrZXRSZWdpb25Bc3luYyIsImRhdGUiLCJEYXRlIiwiYXV0aG9yaXphdGlvbiIsIm1heGltdW1SZXRyeUNvdW50IiwiYmFzZURlbGF5TXMiLCJtYXhpbXVtRGVsYXlNcyIsInBhcnNlUmVzcG9uc2VFcnJvciIsIkludmFsaWRCdWNrZXROYW1lRXJyb3IiLCJjYWNoZWQiLCJleHRyYWN0UmVnaW9uQXN5bmMiLCJwYXJzZUJ1Y2tldFJlZ2lvbiIsIlMzRXJyb3IiLCJlcnJDb2RlIiwiY29kZSIsImVyclJlZ2lvbiIsIm5hbWUiLCJSZWdpb24iLCJtYWtlUmVxdWVzdCIsInJldHVyblJlc3BvbnNlIiwiY2IiLCJwcm9tIiwidGhlbiIsInJlc3VsdCIsIm1ha2VSZXF1ZXN0U3RyZWFtIiwiZXhlY3V0b3IiLCJnZXRCdWNrZXRSZWdpb24iLCJtYWtlQnVja2V0IiwibWFrZU9wdHMiLCJidWlsZE9iamVjdCIsIkNyZWF0ZUJ1Y2tldENvbmZpZ3VyYXRpb24iLCIkIiwieG1sbnMiLCJMb2NhdGlvbkNvbnN0cmFpbnQiLCJPYmplY3RMb2NraW5nIiwiZmluYWxSZWdpb24iLCJyZXF1ZXN0T3B0IiwiYnVja2V0RXhpc3RzIiwicmVtb3ZlQnVja2V0IiwiZ2V0T2JqZWN0IiwiZ2V0T3B0cyIsIkludmFsaWRPYmplY3ROYW1lRXJyb3IiLCJnZXRQYXJ0aWFsT2JqZWN0Iiwib2Zmc2V0IiwicmFuZ2UiLCJzc2VIZWFkZXJzIiwiU1NFQ3VzdG9tZXJBbGdvcml0aG0iLCJTU0VDdXN0b21lcktleSIsIlNTRUN1c3RvbWVyS2V5TUQ1IiwiZXhwZWN0ZWRTdGF0dXNDb2RlcyIsInB1c2giLCJmR2V0T2JqZWN0IiwiZmlsZVBhdGgiLCJkb3dubG9hZFRvVG1wRmlsZSIsInBhcnRGaWxlU3RyZWFtIiwib2JqU3RhdCIsInN0YXRPYmplY3QiLCJlbmNvZGVkRXRhZyIsImZyb20iLCJldGFnIiwicGFydEZpbGUiLCJta2RpciIsImRpcm5hbWUiLCJyZWN1cnNpdmUiLCJzdGF0cyIsInN0YXQiLCJzaXplIiwiY3JlYXRlV3JpdGVTdHJlYW0iLCJmbGFncyIsImRvd25sb2FkU3RyZWFtIiwicGlwZWxpbmUiLCJyZW5hbWUiLCJzdGF0T3B0cyIsInN0YXRPcHREZWYiLCJwYXJzZUludCIsIm1ldGFEYXRhIiwibGFzdE1vZGlmaWVkIiwidmVyc2lvbklkIiwicmVtb3ZlT2JqZWN0IiwicmVtb3ZlT3B0cyIsImdvdmVybmFuY2VCeXBhc3MiLCJmb3JjZURlbGV0ZSIsInF1ZXJ5UGFyYW1zIiwibGlzdEluY29tcGxldGVVcGxvYWRzIiwiYnVja2V0IiwicHJlZml4IiwiSW52YWxpZFByZWZpeEVycm9yIiwiZGVsaW1pdGVyIiwia2V5TWFya2VyIiwidXBsb2FkSWRNYXJrZXIiLCJ1cGxvYWRzIiwiZW5kZWQiLCJyZWFkU3RyZWFtIiwiUmVhZGFibGUiLCJvYmplY3RNb2RlIiwiX3JlYWQiLCJzaGlmdCIsImxpc3RJbmNvbXBsZXRlVXBsb2Fkc1F1ZXJ5IiwicHJlZml4ZXMiLCJlYWNoU2VyaWVzIiwidXBsb2FkIiwibGlzdFBhcnRzIiwia2V5IiwidXBsb2FkSWQiLCJwYXJ0cyIsInJlZHVjZSIsImFjYyIsIml0ZW0iLCJlbWl0IiwiaXNUcnVuY2F0ZWQiLCJuZXh0S2V5TWFya2VyIiwibmV4dFVwbG9hZElkTWFya2VyIiwicXVlcmllcyIsIm1heFVwbG9hZHMiLCJzb3J0IiwidW5zaGlmdCIsImpvaW4iLCJwYXJzZUxpc3RNdWx0aXBhcnQiLCJpbml0aWF0ZU5ld011bHRpcGFydFVwbG9hZCIsImFib3J0TXVsdGlwYXJ0VXBsb2FkIiwicmVxdWVzdE9wdGlvbnMiLCJmaW5kVXBsb2FkSWQiLCJfbGF0ZXN0VXBsb2FkIiwibGF0ZXN0VXBsb2FkIiwiaW5pdGlhdGVkIiwiZ2V0VGltZSIsImNvbXBsZXRlTXVsdGlwYXJ0VXBsb2FkIiwiZXRhZ3MiLCJidWlsZGVyIiwiQ29tcGxldGVNdWx0aXBhcnRVcGxvYWQiLCJQYXJ0IiwibWFwIiwiUGFydE51bWJlciIsInBhcnQiLCJFVGFnIiwiZXJyTWVzc2FnZSIsIm1hcmtlciIsImxpc3RQYXJ0c1F1ZXJ5IiwicGFyc2VMaXN0UGFydHMiLCJsaXN0QnVja2V0cyIsInJlZ2lvbkNvbmYiLCJodHRwUmVzIiwieG1sUmVzdWx0IiwicGFyc2VMaXN0QnVja2V0IiwiY2FsY3VsYXRlUGFydFNpemUiLCJmUHV0T2JqZWN0IiwicHV0T2JqZWN0IiwiY3JlYXRlUmVhZFN0cmVhbSIsInN0YXRTaXplIiwidXBsb2FkQnVmZmVyIiwiYnVmIiwidXBsb2FkU3RyZWFtIiwibWQ1c3VtIiwib2xkUGFydHMiLCJlVGFncyIsInByZXZpb3VzVXBsb2FkSWQiLCJvbGRUYWdzIiwiY2h1bmtpZXIiLCJ6ZXJvUGFkZGluZyIsIm8iLCJQcm9taXNlIiwiYWxsIiwicmVzb2x2ZSIsInJlamVjdCIsInBpcGUiLCJvbiIsInBhcnROdW1iZXIiLCJjaHVuayIsIm1kNSIsImNyZWF0ZUhhc2giLCJ1cGRhdGUiLCJkaWdlc3QiLCJvbGRQYXJ0IiwicmVtb3ZlQnVja2V0UmVwbGljYXRpb24iLCJzZXRCdWNrZXRSZXBsaWNhdGlvbiIsInJlcGxpY2F0aW9uQ29uZmlnIiwicm9sZSIsInJ1bGVzIiwicmVwbGljYXRpb25QYXJhbXNDb25maWciLCJSZXBsaWNhdGlvbkNvbmZpZ3VyYXRpb24iLCJSb2xlIiwiUnVsZSIsImdldEJ1Y2tldFJlcGxpY2F0aW9uIiwicGFyc2VSZXBsaWNhdGlvbkNvbmZpZyIsImdldE9iamVjdExlZ2FsSG9sZCIsImtleXMiLCJzdHJSZXMiLCJzZXRPYmplY3RMZWdhbEhvbGQiLCJzZXRPcHRzIiwic3RhdHVzIiwiRU5BQkxFRCIsIkRJU0FCTEVEIiwiY29uZmlnIiwiU3RhdHVzIiwicm9vdE5hbWUiLCJnZXRCdWNrZXRUYWdnaW5nIiwicGFyc2VUYWdnaW5nIiwiZ2V0T2JqZWN0VGFnZ2luZyIsInNldEJ1Y2tldFBvbGljeSIsInBvbGljeSIsIkludmFsaWRCdWNrZXRQb2xpY3lFcnJvciIsImdldEJ1Y2tldFBvbGljeSIsInB1dE9iamVjdFJldGVudGlvbiIsInJldGVudGlvbk9wdHMiLCJtb2RlIiwiQ09NUExJQU5DRSIsIkdPVkVSTkFOQ0UiLCJyZXRhaW5VbnRpbERhdGUiLCJNb2RlIiwiUmV0YWluVW50aWxEYXRlIiwiZ2V0T2JqZWN0TG9ja0NvbmZpZyIsInBhcnNlT2JqZWN0TG9ja0NvbmZpZyIsInNldE9iamVjdExvY2tDb25maWciLCJsb2NrQ29uZmlnT3B0cyIsInJldGVudGlvbk1vZGVzIiwidmFsaWRVbml0cyIsIkRBWVMiLCJZRUFSUyIsInVuaXQiLCJ2YWxpZGl0eSIsIk9iamVjdExvY2tFbmFibGVkIiwiY29uZmlnS2V5cyIsImlzQWxsS2V5c1NldCIsImV2ZXJ5IiwibGNrIiwiRGVmYXVsdFJldGVudGlvbiIsIkRheXMiLCJZZWFycyIsImdldEJ1Y2tldFZlcnNpb25pbmciLCJwYXJzZUJ1Y2tldFZlcnNpb25pbmdDb25maWciLCJzZXRCdWNrZXRWZXJzaW9uaW5nIiwidmVyc2lvbkNvbmZpZyIsInNldFRhZ2dpbmciLCJ0YWdnaW5nUGFyYW1zIiwidGFncyIsInB1dE9wdHMiLCJ0YWdzTGlzdCIsInZhbHVlIiwiS2V5IiwiVmFsdWUiLCJ0YWdnaW5nQ29uZmlnIiwiVGFnZ2luZyIsIlRhZ1NldCIsIlRhZyIsInBheWxvYWRCdWYiLCJyZW1vdmVUYWdnaW5nIiwic2V0QnVja2V0VGFnZ2luZyIsInJlbW92ZUJ1Y2tldFRhZ2dpbmciLCJzZXRPYmplY3RUYWdnaW5nIiwicmVtb3ZlT2JqZWN0VGFnZ2luZyIsInNlbGVjdE9iamVjdENvbnRlbnQiLCJzZWxlY3RPcHRzIiwiZXhwcmVzc2lvbiIsImlucHV0U2VyaWFsaXphdGlvbiIsIm91dHB1dFNlcmlhbGl6YXRpb24iLCJFeHByZXNzaW9uIiwiRXhwcmVzc2lvblR5cGUiLCJleHByZXNzaW9uVHlwZSIsIklucHV0U2VyaWFsaXphdGlvbiIsIk91dHB1dFNlcmlhbGl6YXRpb24iLCJyZXF1ZXN0UHJvZ3Jlc3MiLCJSZXF1ZXN0UHJvZ3Jlc3MiLCJzY2FuUmFuZ2UiLCJTY2FuUmFuZ2UiLCJhcHBseUJ1Y2tldExpZmVjeWNsZSIsInBvbGljeUNvbmZpZyIsInJlbW92ZUJ1Y2tldExpZmVjeWNsZSIsInNldEJ1Y2tldExpZmVjeWNsZSIsImxpZmVDeWNsZUNvbmZpZyIsImdldEJ1Y2tldExpZmVjeWNsZSIsInBhcnNlTGlmZWN5Y2xlQ29uZmlnIiwic2V0QnVja2V0RW5jcnlwdGlvbiIsImVuY3J5cHRpb25Db25maWciLCJlbmNyeXB0aW9uT2JqIiwiQXBwbHlTZXJ2ZXJTaWRlRW5jcnlwdGlvbkJ5RGVmYXVsdCIsIlNTRUFsZ29yaXRobSIsImdldEJ1Y2tldEVuY3J5cHRpb24iLCJwYXJzZUJ1Y2tldEVuY3J5cHRpb25Db25maWciLCJyZW1vdmVCdWNrZXRFbmNyeXB0aW9uIiwiZ2V0T2JqZWN0UmV0ZW50aW9uIiwicGFyc2VPYmplY3RSZXRlbnRpb25Db25maWciLCJyZW1vdmVPYmplY3RzIiwib2JqZWN0c0xpc3QiLCJBcnJheSIsImlzQXJyYXkiLCJydW5EZWxldGVPYmplY3RzIiwiYmF0Y2giLCJkZWxPYmplY3RzIiwiVmVyc2lvbklkIiwicmVtT2JqZWN0cyIsIkRlbGV0ZSIsIlF1aWV0IiwicmVtb3ZlT2JqZWN0c1BhcnNlciIsIm1heEVudHJpZXMiLCJiYXRjaGVzIiwiaSIsInNsaWNlIiwiYmF0Y2hSZXN1bHRzIiwiZmxhdCIsInJlbW92ZUluY29tcGxldGVVcGxvYWQiLCJJc1ZhbGlkQnVja2V0TmFtZUVycm9yIiwicmVtb3ZlVXBsb2FkSWQiLCJjb3B5T2JqZWN0VjEiLCJ0YXJnZXRCdWNrZXROYW1lIiwidGFyZ2V0T2JqZWN0TmFtZSIsInNvdXJjZUJ1Y2tldE5hbWVBbmRPYmplY3ROYW1lIiwiY29uZGl0aW9ucyIsIm1vZGlmaWVkIiwidW5tb2RpZmllZCIsIm1hdGNoRVRhZyIsIm1hdGNoRVRhZ0V4Y2VwdCIsInBhcnNlQ29weU9iamVjdCIsImNvcHlPYmplY3RWMiIsInNvdXJjZUNvbmZpZyIsImRlc3RDb25maWciLCJ2YWxpZGF0ZSIsImdldEhlYWRlcnMiLCJCdWNrZXQiLCJjb3B5UmVzIiwicmVzSGVhZGVycyIsInNpemVIZWFkZXJWYWx1ZSIsIkxhc3RNb2RpZmllZCIsIk1ldGFEYXRhIiwiU291cmNlVmVyc2lvbklkIiwiRXRhZyIsIlNpemUiLCJjb3B5T2JqZWN0IiwiYWxsQXJncyIsInNvdXJjZSIsImRlc3QiLCJ1cGxvYWRQYXJ0IiwicGFydENvbmZpZyIsInVwbG9hZElEIiwicGFydFJlcyIsInBhcnRFdGFnVmFsIiwiY29tcG9zZU9iamVjdCIsImRlc3RPYmpDb25maWciLCJzb3VyY2VPYmpMaXN0IiwibWF4Q29uY3VycmVuY3kiLCJzb3VyY2VGaWxlc0xlbmd0aCIsIk1BWF9QQVJUU19DT1VOVCIsInNPYmoiLCJnZXRTdGF0T3B0aW9ucyIsInNyY0NvbmZpZyIsIlZlcnNpb25JRCIsInNyY09iamVjdFNpemVzIiwidG90YWxTaXplIiwidG90YWxQYXJ0cyIsInNvdXJjZU9ialN0YXRzIiwic3JjSXRlbSIsInNyY09iamVjdEluZm9zIiwidmFsaWRhdGVkU3RhdHMiLCJyZXNJdGVtU3RhdCIsImluZGV4Iiwic3JjQ29weVNpemUiLCJNYXRjaFJhbmdlIiwic3JjU3RhcnQiLCJTdGFydCIsInNyY0VuZCIsIkVuZCIsIkFCU19NSU5fUEFSVF9TSVpFIiwiTUFYX01VTFRJUEFSVF9QVVRfT0JKRUNUX1NJWkUiLCJNQVhfUEFSVF9TSVpFIiwiTWF0Y2hFVGFnIiwic3BsaXRQYXJ0U2l6ZUxpc3QiLCJpZHgiLCJnZXRVcGxvYWRQYXJ0Q29uZmlnTGlzdCIsInVwbG9hZFBhcnRDb25maWdMaXN0Iiwic3BsaXRTaXplIiwic3BsaXRJbmRleCIsInN0YXJ0SW5kZXgiLCJzdGFydElkeCIsImVuZEluZGV4IiwiZW5kSWR4Iiwib2JqSW5mbyIsIm9iakNvbmZpZyIsInBhcnRJbmRleCIsInRvdGFsVXBsb2FkcyIsInNwbGl0U3RhcnQiLCJ1cGxkQ3RySWR4Iiwic3BsaXRFbmQiLCJzb3VyY2VPYmoiLCJ1cGxvYWRQYXJ0Q29uZmlnIiwidXBsb2FkQWxsUGFydHMiLCJ1cGxvYWRMaXN0IiwicGFydFVwbG9hZHMiLCJwZXJmb3JtVXBsb2FkUGFydHMiLCJwYXJ0c1JlcyIsInBhcnRDb3B5IiwibmV3VXBsb2FkSGVhZGVycyIsInBhcnRzRG9uZSIsInByZXNpZ25lZFVybCIsImV4cGlyZXMiLCJyZXFQYXJhbXMiLCJyZXF1ZXN0RGF0ZSIsIl9yZXF1ZXN0RGF0ZSIsIkFub255bW91c1JlcXVlc3RFcnJvciIsImlzTmFOIiwicHJlc2lnbmVkR2V0T2JqZWN0IiwicmVzcEhlYWRlcnMiLCJ2YWxpZFJlc3BIZWFkZXJzIiwiaGVhZGVyIiwicHJlc2lnbmVkUHV0T2JqZWN0IiwibmV3UG9zdFBvbGljeSIsInByZXNpZ25lZFBvc3RQb2xpY3kiLCJwb3N0UG9saWN5IiwiZm9ybURhdGEiLCJkYXRlU3RyIiwiZXhwaXJhdGlvbiIsInNldFNlY29uZHMiLCJzZXRFeHBpcmVzIiwicG9saWN5QmFzZTY0IiwicG9ydFN0ciIsInVybFN0ciIsInBvc3RVUkwiLCJsaXN0T2JqZWN0c1F1ZXJ5IiwibGlzdFF1ZXJ5T3B0cyIsIkRlbGltaXRlciIsIk1heEtleXMiLCJJbmNsdWRlVmVyc2lvbiIsInZlcnNpb25JZE1hcmtlciIsImxpc3RRcnlMaXN0IiwibGlzdE9iamVjdHMiLCJsaXN0T3B0cyIsIm9iamVjdHMiLCJuZXh0TWFya2VyIiwibGlzdE9iamVjdHNWMlF1ZXJ5IiwiY29udGludWF0aW9uVG9rZW4iLCJtYXhLZXlzIiwic3RhcnRBZnRlciIsImxpc3RPYmplY3RzVjIiLCJwcmVmaXhTdHIiLCJzdGFydEFmdGVyU3RyIiwibmV4dENvbnRpbnVhdGlvblRva2VuIiwic2V0QnVja2V0Tm90aWZpY2F0aW9uIiwicmVtb3ZlQWxsQnVja2V0Tm90aWZpY2F0aW9uIiwiZ2V0QnVja2V0Tm90aWZpY2F0aW9uIiwibGlzdGVuQnVja2V0Tm90aWZpY2F0aW9uIiwic3VmZml4IiwiZXZlbnRzIiwibGlzdGVuZXIiLCJzdGFydCJdLCJzb3VyY2VzIjpbImNsaWVudC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjcnlwdG8gZnJvbSAnbm9kZTpjcnlwdG8nXG5pbXBvcnQgKiBhcyBmcyBmcm9tICdub2RlOmZzJ1xuaW1wb3J0IHR5cGUgeyBJbmNvbWluZ0h0dHBIZWFkZXJzIH0gZnJvbSAnbm9kZTpodHRwJ1xuaW1wb3J0ICogYXMgaHR0cCBmcm9tICdub2RlOmh0dHAnXG5pbXBvcnQgKiBhcyBodHRwcyBmcm9tICdub2RlOmh0dHBzJ1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdub2RlOnBhdGgnXG5pbXBvcnQgKiBhcyBzdHJlYW0gZnJvbSAnbm9kZTpzdHJlYW0nXG5cbmltcG9ydCAqIGFzIGFzeW5jIGZyb20gJ2FzeW5jJ1xuaW1wb3J0IEJsb2NrU3RyZWFtMiBmcm9tICdibG9jay1zdHJlYW0yJ1xuaW1wb3J0IHsgaXNCcm93c2VyIH0gZnJvbSAnYnJvd3Nlci1vci1ub2RlJ1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJ1xuaW1wb3J0ICogYXMgcXMgZnJvbSAncXVlcnktc3RyaW5nJ1xuaW1wb3J0IHhtbDJqcyBmcm9tICd4bWwyanMnXG5cbmltcG9ydCB7IENyZWRlbnRpYWxQcm92aWRlciB9IGZyb20gJy4uL0NyZWRlbnRpYWxQcm92aWRlci50cydcbmltcG9ydCAqIGFzIGVycm9ycyBmcm9tICcuLi9lcnJvcnMudHMnXG5pbXBvcnQgdHlwZSB7IFNlbGVjdFJlc3VsdHMgfSBmcm9tICcuLi9oZWxwZXJzLnRzJ1xuaW1wb3J0IHtcbiAgQ29weURlc3RpbmF0aW9uT3B0aW9ucyxcbiAgQ29weVNvdXJjZU9wdGlvbnMsXG4gIERFRkFVTFRfUkVHSU9OLFxuICBMRUdBTF9IT0xEX1NUQVRVUyxcbiAgUFJFU0lHTl9FWFBJUllfREFZU19NQVgsXG4gIFJFVEVOVElPTl9NT0RFUyxcbiAgUkVURU5USU9OX1ZBTElESVRZX1VOSVRTLFxufSBmcm9tICcuLi9oZWxwZXJzLnRzJ1xuaW1wb3J0IHR5cGUgeyBOb3RpZmljYXRpb25FdmVudCB9IGZyb20gJy4uL25vdGlmaWNhdGlvbi50cydcbmltcG9ydCB7IE5vdGlmaWNhdGlvbkNvbmZpZywgTm90aWZpY2F0aW9uUG9sbGVyIH0gZnJvbSAnLi4vbm90aWZpY2F0aW9uLnRzJ1xuaW1wb3J0IHsgcG9zdFByZXNpZ25TaWduYXR1cmVWNCwgcHJlc2lnblNpZ25hdHVyZVY0LCBzaWduVjQgfSBmcm9tICcuLi9zaWduaW5nLnRzJ1xuaW1wb3J0IHsgZnNwLCBzdHJlYW1Qcm9taXNlIH0gZnJvbSAnLi9hc3luYy50cydcbmltcG9ydCB7IENvcHlDb25kaXRpb25zIH0gZnJvbSAnLi9jb3B5LWNvbmRpdGlvbnMudHMnXG5pbXBvcnQgeyBFeHRlbnNpb25zIH0gZnJvbSAnLi9leHRlbnNpb25zLnRzJ1xuaW1wb3J0IHtcbiAgY2FsY3VsYXRlRXZlblNwbGl0cyxcbiAgZXh0cmFjdE1ldGFkYXRhLFxuICBnZXRDb250ZW50TGVuZ3RoLFxuICBnZXRTY29wZSxcbiAgZ2V0U291cmNlVmVyc2lvbklkLFxuICBnZXRWZXJzaW9uSWQsXG4gIGhhc2hCaW5hcnksXG4gIGluc2VydENvbnRlbnRUeXBlLFxuICBpc0FtYXpvbkVuZHBvaW50LFxuICBpc0Jvb2xlYW4sXG4gIGlzRGVmaW5lZCxcbiAgaXNFbXB0eSxcbiAgaXNOdW1iZXIsXG4gIGlzT2JqZWN0LFxuICBpc1BsYWluT2JqZWN0LFxuICBpc1JlYWRhYmxlU3RyZWFtLFxuICBpc1N0cmluZyxcbiAgaXNWYWxpZEJ1Y2tldE5hbWUsXG4gIGlzVmFsaWRFbmRwb2ludCxcbiAgaXNWYWxpZE9iamVjdE5hbWUsXG4gIGlzVmFsaWRQb3J0LFxuICBpc1ZhbGlkUHJlZml4LFxuICBpc1ZpcnR1YWxIb3N0U3R5bGUsXG4gIG1ha2VEYXRlTG9uZyxcbiAgUEFSVF9DT05TVFJBSU5UUyxcbiAgcGFydHNSZXF1aXJlZCxcbiAgcHJlcGVuZFhBTVpNZXRhLFxuICByZWFkYWJsZVN0cmVhbSxcbiAgc2FuaXRpemVFVGFnLFxuICB0b01kNSxcbiAgdG9TaGEyNTYsXG4gIHVyaUVzY2FwZSxcbiAgdXJpUmVzb3VyY2VFc2NhcGUsXG59IGZyb20gJy4vaGVscGVyLnRzJ1xuaW1wb3J0IHsgam9pbkhvc3RQb3J0IH0gZnJvbSAnLi9qb2luLWhvc3QtcG9ydC50cydcbmltcG9ydCB7IFBvc3RQb2xpY3kgfSBmcm9tICcuL3Bvc3QtcG9saWN5LnRzJ1xuaW1wb3J0IHsgcmVxdWVzdFdpdGhSZXRyeSB9IGZyb20gJy4vcmVxdWVzdC50cydcbmltcG9ydCB7IGRyYWluUmVzcG9uc2UsIHJlYWRBc0J1ZmZlciwgcmVhZEFzU3RyaW5nIH0gZnJvbSAnLi9yZXNwb25zZS50cydcbmltcG9ydCB0eXBlIHsgUmVnaW9uIH0gZnJvbSAnLi9zMy1lbmRwb2ludHMudHMnXG5pbXBvcnQgeyBnZXRTM0VuZHBvaW50IH0gZnJvbSAnLi9zMy1lbmRwb2ludHMudHMnXG5pbXBvcnQgdHlwZSB7XG4gIEJpbmFyeSxcbiAgQnVja2V0SXRlbSxcbiAgQnVja2V0SXRlbUZyb21MaXN0LFxuICBCdWNrZXRJdGVtU3RhdCxcbiAgQnVja2V0U3RyZWFtLFxuICBCdWNrZXRWZXJzaW9uaW5nQ29uZmlndXJhdGlvbixcbiAgQ29weU9iamVjdFBhcmFtcyxcbiAgQ29weU9iamVjdFJlc3VsdCxcbiAgQ29weU9iamVjdFJlc3VsdFYyLFxuICBFbmNyeXB0aW9uQ29uZmlnLFxuICBHZXRPYmplY3RMZWdhbEhvbGRPcHRpb25zLFxuICBHZXRPYmplY3RPcHRzLFxuICBHZXRPYmplY3RSZXRlbnRpb25PcHRzLFxuICBJbmNvbXBsZXRlVXBsb2FkZWRCdWNrZXRJdGVtLFxuICBJUmVxdWVzdCxcbiAgSXRlbUJ1Y2tldE1ldGFkYXRhLFxuICBMaWZlY3ljbGVDb25maWcsXG4gIExpZmVDeWNsZUNvbmZpZ1BhcmFtLFxuICBMaXN0T2JqZWN0UXVlcnlPcHRzLFxuICBMaXN0T2JqZWN0UXVlcnlSZXMsXG4gIExpc3RPYmplY3RWMlJlcyxcbiAgTm90aWZpY2F0aW9uQ29uZmlnUmVzdWx0LFxuICBPYmplY3RJbmZvLFxuICBPYmplY3RMb2NrQ29uZmlnUGFyYW0sXG4gIE9iamVjdExvY2tJbmZvLFxuICBPYmplY3RNZXRhRGF0YSxcbiAgT2JqZWN0UmV0ZW50aW9uSW5mbyxcbiAgUG9zdFBvbGljeVJlc3VsdCxcbiAgUHJlU2lnblJlcXVlc3RQYXJhbXMsXG4gIFB1dE9iamVjdExlZ2FsSG9sZE9wdGlvbnMsXG4gIFB1dFRhZ2dpbmdQYXJhbXMsXG4gIFJlbW92ZU9iamVjdHNQYXJhbSxcbiAgUmVtb3ZlT2JqZWN0c1JlcXVlc3RFbnRyeSxcbiAgUmVtb3ZlT2JqZWN0c1Jlc3BvbnNlLFxuICBSZW1vdmVUYWdnaW5nUGFyYW1zLFxuICBSZXBsaWNhdGlvbkNvbmZpZyxcbiAgUmVwbGljYXRpb25Db25maWdPcHRzLFxuICBSZXF1ZXN0SGVhZGVycyxcbiAgUmVzcG9uc2VIZWFkZXIsXG4gIFJlc3VsdENhbGxiYWNrLFxuICBSZXRlbnRpb24sXG4gIFNlbGVjdE9wdGlvbnMsXG4gIFN0YXRPYmplY3RPcHRzLFxuICBUYWcsXG4gIFRhZ2dpbmdPcHRzLFxuICBUYWdzLFxuICBUcmFuc3BvcnQsXG4gIFVwbG9hZGVkT2JqZWN0SW5mbyxcbiAgVXBsb2FkUGFydENvbmZpZyxcbn0gZnJvbSAnLi90eXBlLnRzJ1xuaW1wb3J0IHR5cGUgeyBMaXN0TXVsdGlwYXJ0UmVzdWx0LCBVcGxvYWRlZFBhcnQgfSBmcm9tICcuL3htbC1wYXJzZXIudHMnXG5pbXBvcnQge1xuICBwYXJzZUJ1Y2tldE5vdGlmaWNhdGlvbixcbiAgcGFyc2VDb21wbGV0ZU11bHRpcGFydCxcbiAgcGFyc2VJbml0aWF0ZU11bHRpcGFydCxcbiAgcGFyc2VMaXN0T2JqZWN0cyxcbiAgcGFyc2VMaXN0T2JqZWN0c1YyLFxuICBwYXJzZU9iamVjdExlZ2FsSG9sZENvbmZpZyxcbiAgcGFyc2VTZWxlY3RPYmplY3RDb250ZW50UmVzcG9uc2UsXG4gIHVwbG9hZFBhcnRQYXJzZXIsXG59IGZyb20gJy4veG1sLXBhcnNlci50cydcbmltcG9ydCAqIGFzIHhtbFBhcnNlcnMgZnJvbSAnLi94bWwtcGFyc2VyLnRzJ1xuXG5jb25zdCB4bWwgPSBuZXcgeG1sMmpzLkJ1aWxkZXIoeyByZW5kZXJPcHRzOiB7IHByZXR0eTogZmFsc2UgfSwgaGVhZGxlc3M6IHRydWUgfSlcblxuLy8gd2lsbCBiZSByZXBsYWNlZCBieSBidW5kbGVyLlxuY29uc3QgUGFja2FnZSA9IHsgdmVyc2lvbjogcHJvY2Vzcy5lbnYuTUlOSU9fSlNfUEFDS0FHRV9WRVJTSU9OIHx8ICdkZXZlbG9wbWVudCcgfVxuXG5jb25zdCByZXF1ZXN0T3B0aW9uUHJvcGVydGllcyA9IFtcbiAgJ2FnZW50JyxcbiAgJ2NhJyxcbiAgJ2NlcnQnLFxuICAnY2lwaGVycycsXG4gICdjbGllbnRDZXJ0RW5naW5lJyxcbiAgJ2NybCcsXG4gICdkaHBhcmFtJyxcbiAgJ2VjZGhDdXJ2ZScsXG4gICdmYW1pbHknLFxuICAnaG9ub3JDaXBoZXJPcmRlcicsXG4gICdrZXknLFxuICAncGFzc3BocmFzZScsXG4gICdwZngnLFxuICAncmVqZWN0VW5hdXRob3JpemVkJyxcbiAgJ3NlY3VyZU9wdGlvbnMnLFxuICAnc2VjdXJlUHJvdG9jb2wnLFxuICAnc2VydmVybmFtZScsXG4gICdzZXNzaW9uSWRDb250ZXh0Jyxcbl0gYXMgY29uc3RcblxuZXhwb3J0IGludGVyZmFjZSBSZXRyeU9wdGlvbnMge1xuICAvKipcbiAgICogSWYgdGhpcyBzZXQgdG8gdHJ1ZSwgaXQgd2lsbCB0YWtlIHByZWNlZGVuY2Ugb3ZlciBhbGwgb3RoZXIgcmV0cnkgb3B0aW9ucy5cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIGRpc2FibGVSZXRyeT86IGJvb2xlYW5cbiAgLyoqXG4gICAqIFRoZSBtYXhpbXVtIGFtb3VudCBvZiByZXRyaWVzIGZvciBhIHJlcXVlc3QuXG4gICAqIEBkZWZhdWx0IDFcbiAgICovXG4gIG1heGltdW1SZXRyeUNvdW50PzogbnVtYmVyXG4gIC8qKlxuICAgKiBUaGUgbWluaW11bSBkdXJhdGlvbiAoaW4gbWlsbGlzZWNvbmRzKSBmb3IgdGhlIGV4cG9uZW50aWFsIGJhY2tvZmYgYWxnb3JpdGhtLlxuICAgKiBAZGVmYXVsdCAxMDBcbiAgICovXG4gIGJhc2VEZWxheU1zPzogbnVtYmVyXG4gIC8qKlxuICAgKiBUaGUgbWF4aW11bSBkdXJhdGlvbiAoaW4gbWlsbGlzZWNvbmRzKSBmb3IgdGhlIGV4cG9uZW50aWFsIGJhY2tvZmYgYWxnb3JpdGhtLlxuICAgKiBAZGVmYXVsdCA2MDAwMFxuICAgKi9cbiAgbWF4aW11bURlbGF5TXM/OiBudW1iZXJcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDbGllbnRPcHRpb25zIHtcbiAgZW5kUG9pbnQ6IHN0cmluZ1xuICBhY2Nlc3NLZXk/OiBzdHJpbmdcbiAgc2VjcmV0S2V5Pzogc3RyaW5nXG4gIHVzZVNTTD86IGJvb2xlYW5cbiAgcG9ydD86IG51bWJlclxuICByZWdpb24/OiBSZWdpb25cbiAgdHJhbnNwb3J0PzogVHJhbnNwb3J0XG4gIHNlc3Npb25Ub2tlbj86IHN0cmluZ1xuICBwYXJ0U2l6ZT86IG51bWJlclxuICBwYXRoU3R5bGU/OiBib29sZWFuXG4gIGNyZWRlbnRpYWxzUHJvdmlkZXI/OiBDcmVkZW50aWFsUHJvdmlkZXJcbiAgczNBY2NlbGVyYXRlRW5kcG9pbnQ/OiBzdHJpbmdcbiAgdHJhbnNwb3J0QWdlbnQ/OiBodHRwLkFnZW50XG4gIHJldHJ5T3B0aW9ucz86IFJldHJ5T3B0aW9uc1xufVxuXG5leHBvcnQgdHlwZSBSZXF1ZXN0T3B0aW9uID0gUGFydGlhbDxJUmVxdWVzdD4gJiB7XG4gIG1ldGhvZDogc3RyaW5nXG4gIGJ1Y2tldE5hbWU/OiBzdHJpbmdcbiAgb2JqZWN0TmFtZT86IHN0cmluZ1xuICBxdWVyeT86IHN0cmluZ1xuICBwYXRoU3R5bGU/OiBib29sZWFuXG59XG5cbmV4cG9ydCB0eXBlIE5vUmVzdWx0Q2FsbGJhY2sgPSAoZXJyb3I6IHVua25vd24pID0+IHZvaWRcblxuZXhwb3J0IGludGVyZmFjZSBNYWtlQnVja2V0T3B0IHtcbiAgT2JqZWN0TG9ja2luZz86IGJvb2xlYW5cbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZW1vdmVPcHRpb25zIHtcbiAgdmVyc2lvbklkPzogc3RyaW5nXG4gIGdvdmVybmFuY2VCeXBhc3M/OiBib29sZWFuXG4gIGZvcmNlRGVsZXRlPzogYm9vbGVhblxufVxuXG50eXBlIFBhcnQgPSB7XG4gIHBhcnQ6IG51bWJlclxuICBldGFnOiBzdHJpbmdcbn1cblxuZXhwb3J0IGNsYXNzIFR5cGVkQ2xpZW50IHtcbiAgcHJvdGVjdGVkIHRyYW5zcG9ydDogVHJhbnNwb3J0XG4gIHByb3RlY3RlZCBob3N0OiBzdHJpbmdcbiAgcHJvdGVjdGVkIHBvcnQ6IG51bWJlclxuICBwcm90ZWN0ZWQgcHJvdG9jb2w6IHN0cmluZ1xuICBwcm90ZWN0ZWQgYWNjZXNzS2V5OiBzdHJpbmdcbiAgcHJvdGVjdGVkIHNlY3JldEtleTogc3RyaW5nXG4gIHByb3RlY3RlZCBzZXNzaW9uVG9rZW4/OiBzdHJpbmdcbiAgcHJvdGVjdGVkIHVzZXJBZ2VudDogc3RyaW5nXG4gIHByb3RlY3RlZCBhbm9ueW1vdXM6IGJvb2xlYW5cbiAgcHJvdGVjdGVkIHBhdGhTdHlsZTogYm9vbGVhblxuICBwcm90ZWN0ZWQgcmVnaW9uTWFwOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+XG4gIHB1YmxpYyByZWdpb24/OiBzdHJpbmdcbiAgcHJvdGVjdGVkIGNyZWRlbnRpYWxzUHJvdmlkZXI/OiBDcmVkZW50aWFsUHJvdmlkZXJcbiAgcGFydFNpemU6IG51bWJlciA9IDY0ICogMTAyNCAqIDEwMjRcbiAgcHJvdGVjdGVkIG92ZXJSaWRlUGFydFNpemU/OiBib29sZWFuXG4gIHByb3RlY3RlZCByZXRyeU9wdGlvbnM6IFJldHJ5T3B0aW9uc1xuXG4gIHByb3RlY3RlZCBtYXhpbXVtUGFydFNpemUgPSA1ICogMTAyNCAqIDEwMjQgKiAxMDI0XG4gIHByb3RlY3RlZCBtYXhPYmplY3RTaXplID0gNSAqIDEwMjQgKiAxMDI0ICogMTAyNCAqIDEwMjRcbiAgcHVibGljIGVuYWJsZVNIQTI1NjogYm9vbGVhblxuICBwcm90ZWN0ZWQgczNBY2NlbGVyYXRlRW5kcG9pbnQ/OiBzdHJpbmdcbiAgcHJvdGVjdGVkIHJlcU9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+XG5cbiAgcHJvdGVjdGVkIHRyYW5zcG9ydEFnZW50OiBodHRwLkFnZW50XG4gIHByaXZhdGUgcmVhZG9ubHkgY2xpZW50RXh0ZW5zaW9uczogRXh0ZW5zaW9uc1xuXG4gIGNvbnN0cnVjdG9yKHBhcmFtczogQ2xpZW50T3B0aW9ucykge1xuICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgZGVwcmVjYXRlZCBwcm9wZXJ0eVxuICAgIGlmIChwYXJhbXMuc2VjdXJlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJzZWN1cmVcIiBvcHRpb24gZGVwcmVjYXRlZCwgXCJ1c2VTU0xcIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkJylcbiAgICB9XG4gICAgLy8gRGVmYXVsdCB2YWx1ZXMgaWYgbm90IHNwZWNpZmllZC5cbiAgICBpZiAocGFyYW1zLnVzZVNTTCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBwYXJhbXMudXNlU1NMID0gdHJ1ZVxuICAgIH1cbiAgICBpZiAoIXBhcmFtcy5wb3J0KSB7XG4gICAgICBwYXJhbXMucG9ydCA9IDBcbiAgICB9XG4gICAgLy8gVmFsaWRhdGUgaW5wdXQgcGFyYW1zLlxuICAgIGlmICghaXNWYWxpZEVuZHBvaW50KHBhcmFtcy5lbmRQb2ludCkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEVuZHBvaW50RXJyb3IoYEludmFsaWQgZW5kUG9pbnQgOiAke3BhcmFtcy5lbmRQb2ludH1gKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRQb3J0KHBhcmFtcy5wb3J0KSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihgSW52YWxpZCBwb3J0IDogJHtwYXJhbXMucG9ydH1gKVxuICAgIH1cbiAgICBpZiAoIWlzQm9vbGVhbihwYXJhbXMudXNlU1NMKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihcbiAgICAgICAgYEludmFsaWQgdXNlU1NMIGZsYWcgdHlwZSA6ICR7cGFyYW1zLnVzZVNTTH0sIGV4cGVjdGVkIHRvIGJlIG9mIHR5cGUgXCJib29sZWFuXCJgLFxuICAgICAgKVxuICAgIH1cblxuICAgIC8vIFZhbGlkYXRlIHJlZ2lvbiBvbmx5IGlmIGl0cyBzZXQuXG4gICAgaWYgKHBhcmFtcy5yZWdpb24pIHtcbiAgICAgIGlmICghaXNTdHJpbmcocGFyYW1zLnJlZ2lvbikpIHtcbiAgICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihgSW52YWxpZCByZWdpb24gOiAke3BhcmFtcy5yZWdpb259YClcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBob3N0ID0gcGFyYW1zLmVuZFBvaW50LnRvTG93ZXJDYXNlKClcbiAgICBsZXQgcG9ydCA9IHBhcmFtcy5wb3J0XG4gICAgbGV0IHByb3RvY29sOiBzdHJpbmdcbiAgICBsZXQgdHJhbnNwb3J0XG4gICAgbGV0IHRyYW5zcG9ydEFnZW50OiBodHRwLkFnZW50XG4gICAgLy8gVmFsaWRhdGUgaWYgY29uZmlndXJhdGlvbiBpcyBub3QgdXNpbmcgU1NMXG4gICAgLy8gZm9yIGNvbnN0cnVjdGluZyByZWxldmFudCBlbmRwb2ludHMuXG4gICAgaWYgKHBhcmFtcy51c2VTU0wpIHtcbiAgICAgIC8vIERlZmF1bHRzIHRvIHNlY3VyZS5cbiAgICAgIHRyYW5zcG9ydCA9IGh0dHBzXG4gICAgICBwcm90b2NvbCA9ICdodHRwczonXG4gICAgICBwb3J0ID0gcG9ydCB8fCA0NDNcbiAgICAgIHRyYW5zcG9ydEFnZW50ID0gaHR0cHMuZ2xvYmFsQWdlbnRcbiAgICB9IGVsc2Uge1xuICAgICAgdHJhbnNwb3J0ID0gaHR0cFxuICAgICAgcHJvdG9jb2wgPSAnaHR0cDonXG4gICAgICBwb3J0ID0gcG9ydCB8fCA4MFxuICAgICAgdHJhbnNwb3J0QWdlbnQgPSBodHRwLmdsb2JhbEFnZW50XG4gICAgfVxuXG4gICAgLy8gaWYgY3VzdG9tIHRyYW5zcG9ydCBpcyBzZXQsIHVzZSBpdC5cbiAgICBpZiAocGFyYW1zLnRyYW5zcG9ydCkge1xuICAgICAgaWYgKCFpc09iamVjdChwYXJhbXMudHJhbnNwb3J0KSkge1xuICAgICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKFxuICAgICAgICAgIGBJbnZhbGlkIHRyYW5zcG9ydCB0eXBlIDogJHtwYXJhbXMudHJhbnNwb3J0fSwgZXhwZWN0ZWQgdG8gYmUgdHlwZSBcIm9iamVjdFwiYCxcbiAgICAgICAgKVxuICAgICAgfVxuICAgICAgdHJhbnNwb3J0ID0gcGFyYW1zLnRyYW5zcG9ydFxuICAgIH1cblxuICAgIC8vIGlmIGN1c3RvbSB0cmFuc3BvcnQgYWdlbnQgaXMgc2V0LCB1c2UgaXQuXG4gICAgaWYgKHBhcmFtcy50cmFuc3BvcnRBZ2VudCkge1xuICAgICAgaWYgKCFpc09iamVjdChwYXJhbXMudHJhbnNwb3J0QWdlbnQpKSB7XG4gICAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoXG4gICAgICAgICAgYEludmFsaWQgdHJhbnNwb3J0QWdlbnQgdHlwZTogJHtwYXJhbXMudHJhbnNwb3J0QWdlbnR9LCBleHBlY3RlZCB0byBiZSB0eXBlIFwib2JqZWN0XCJgLFxuICAgICAgICApXG4gICAgICB9XG5cbiAgICAgIHRyYW5zcG9ydEFnZW50ID0gcGFyYW1zLnRyYW5zcG9ydEFnZW50XG4gICAgfVxuXG4gICAgLy8gVXNlciBBZ2VudCBzaG91bGQgYWx3YXlzIGZvbGxvd2luZyB0aGUgYmVsb3cgc3R5bGUuXG4gICAgLy8gUGxlYXNlIG9wZW4gYW4gaXNzdWUgdG8gZGlzY3VzcyBhbnkgbmV3IGNoYW5nZXMgaGVyZS5cbiAgICAvL1xuICAgIC8vICAgICAgIE1pbklPIChPUzsgQVJDSCkgTElCL1ZFUiBBUFAvVkVSXG4gICAgLy9cbiAgICBjb25zdCBsaWJyYXJ5Q29tbWVudHMgPSBgKCR7cHJvY2Vzcy5wbGF0Zm9ybX07ICR7cHJvY2Vzcy5hcmNofSlgXG4gICAgY29uc3QgbGlicmFyeUFnZW50ID0gYE1pbklPICR7bGlicmFyeUNvbW1lbnRzfSBtaW5pby1qcy8ke1BhY2thZ2UudmVyc2lvbn1gXG4gICAgLy8gVXNlciBhZ2VudCBibG9jayBlbmRzLlxuXG4gICAgdGhpcy50cmFuc3BvcnQgPSB0cmFuc3BvcnRcbiAgICB0aGlzLnRyYW5zcG9ydEFnZW50ID0gdHJhbnNwb3J0QWdlbnRcbiAgICB0aGlzLmhvc3QgPSBob3N0XG4gICAgdGhpcy5wb3J0ID0gcG9ydFxuICAgIHRoaXMucHJvdG9jb2wgPSBwcm90b2NvbFxuICAgIHRoaXMudXNlckFnZW50ID0gYCR7bGlicmFyeUFnZW50fWBcblxuICAgIC8vIERlZmF1bHQgcGF0aCBzdHlsZSBpcyB0cnVlXG4gICAgaWYgKHBhcmFtcy5wYXRoU3R5bGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5wYXRoU3R5bGUgPSB0cnVlXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucGF0aFN0eWxlID0gcGFyYW1zLnBhdGhTdHlsZVxuICAgIH1cblxuICAgIHRoaXMuYWNjZXNzS2V5ID0gcGFyYW1zLmFjY2Vzc0tleSA/PyAnJ1xuICAgIHRoaXMuc2VjcmV0S2V5ID0gcGFyYW1zLnNlY3JldEtleSA/PyAnJ1xuICAgIHRoaXMuc2Vzc2lvblRva2VuID0gcGFyYW1zLnNlc3Npb25Ub2tlblxuICAgIHRoaXMuYW5vbnltb3VzID0gIXRoaXMuYWNjZXNzS2V5IHx8ICF0aGlzLnNlY3JldEtleVxuXG4gICAgaWYgKHBhcmFtcy5jcmVkZW50aWFsc1Byb3ZpZGVyKSB7XG4gICAgICB0aGlzLmFub255bW91cyA9IGZhbHNlXG4gICAgICB0aGlzLmNyZWRlbnRpYWxzUHJvdmlkZXIgPSBwYXJhbXMuY3JlZGVudGlhbHNQcm92aWRlclxuICAgIH1cblxuICAgIHRoaXMucmVnaW9uTWFwID0ge31cbiAgICBpZiAocGFyYW1zLnJlZ2lvbikge1xuICAgICAgdGhpcy5yZWdpb24gPSBwYXJhbXMucmVnaW9uXG4gICAgfVxuXG4gICAgaWYgKHBhcmFtcy5wYXJ0U2l6ZSkge1xuICAgICAgdGhpcy5wYXJ0U2l6ZSA9IHBhcmFtcy5wYXJ0U2l6ZVxuICAgICAgdGhpcy5vdmVyUmlkZVBhcnRTaXplID0gdHJ1ZVxuICAgIH1cbiAgICBpZiAodGhpcy5wYXJ0U2l6ZSA8IDUgKiAxMDI0ICogMTAyNCkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihgUGFydCBzaXplIHNob3VsZCBiZSBncmVhdGVyIHRoYW4gNU1CYClcbiAgICB9XG4gICAgaWYgKHRoaXMucGFydFNpemUgPiA1ICogMTAyNCAqIDEwMjQgKiAxMDI0KSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKGBQYXJ0IHNpemUgc2hvdWxkIGJlIGxlc3MgdGhhbiA1R0JgKVxuICAgIH1cblxuICAgIC8vIFNIQTI1NiBpcyBlbmFibGVkIG9ubHkgZm9yIGF1dGhlbnRpY2F0ZWQgaHR0cCByZXF1ZXN0cy4gSWYgdGhlIHJlcXVlc3QgaXMgYXV0aGVudGljYXRlZFxuICAgIC8vIGFuZCB0aGUgY29ubmVjdGlvbiBpcyBodHRwcyB3ZSB1c2UgeC1hbXotY29udGVudC1zaGEyNTY9VU5TSUdORUQtUEFZTE9BRFxuICAgIC8vIGhlYWRlciBmb3Igc2lnbmF0dXJlIGNhbGN1bGF0aW9uLlxuICAgIHRoaXMuZW5hYmxlU0hBMjU2ID0gIXRoaXMuYW5vbnltb3VzICYmICFwYXJhbXMudXNlU1NMXG5cbiAgICB0aGlzLnMzQWNjZWxlcmF0ZUVuZHBvaW50ID0gcGFyYW1zLnMzQWNjZWxlcmF0ZUVuZHBvaW50IHx8IHVuZGVmaW5lZFxuICAgIHRoaXMucmVxT3B0aW9ucyA9IHt9XG4gICAgdGhpcy5jbGllbnRFeHRlbnNpb25zID0gbmV3IEV4dGVuc2lvbnModGhpcylcblxuICAgIGlmIChwYXJhbXMucmV0cnlPcHRpb25zKSB7XG4gICAgICBpZiAoIWlzT2JqZWN0KHBhcmFtcy5yZXRyeU9wdGlvbnMpKSB7XG4gICAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoXG4gICAgICAgICAgYEludmFsaWQgcmV0cnlPcHRpb25zIHR5cGU6ICR7cGFyYW1zLnJldHJ5T3B0aW9uc30sIGV4cGVjdGVkIHRvIGJlIHR5cGUgXCJvYmplY3RcImAsXG4gICAgICAgIClcbiAgICAgIH1cblxuICAgICAgdGhpcy5yZXRyeU9wdGlvbnMgPSBwYXJhbXMucmV0cnlPcHRpb25zXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmV0cnlPcHRpb25zID0ge1xuICAgICAgICBkaXNhYmxlUmV0cnk6IGZhbHNlLFxuICAgICAgfVxuICAgIH1cbiAgfVxuICAvKipcbiAgICogTWluaW8gZXh0ZW5zaW9ucyB0aGF0IGFyZW4ndCBuZWNlc3NhcnkgcHJlc2VudCBmb3IgQW1hem9uIFMzIGNvbXBhdGlibGUgc3RvcmFnZSBzZXJ2ZXJzXG4gICAqL1xuICBnZXQgZXh0ZW5zaW9ucygpIHtcbiAgICByZXR1cm4gdGhpcy5jbGllbnRFeHRlbnNpb25zXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIGVuZFBvaW50IC0gdmFsaWQgUzMgYWNjZWxlcmF0aW9uIGVuZCBwb2ludFxuICAgKi9cbiAgc2V0UzNUcmFuc2ZlckFjY2VsZXJhdGUoZW5kUG9pbnQ6IHN0cmluZykge1xuICAgIHRoaXMuczNBY2NlbGVyYXRlRW5kcG9pbnQgPSBlbmRQb2ludFxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIHN1cHBvcnRlZCByZXF1ZXN0IG9wdGlvbnMuXG4gICAqL1xuICBwdWJsaWMgc2V0UmVxdWVzdE9wdGlvbnMob3B0aW9uczogUGljazxodHRwcy5SZXF1ZXN0T3B0aW9ucywgKHR5cGVvZiByZXF1ZXN0T3B0aW9uUHJvcGVydGllcylbbnVtYmVyXT4pIHtcbiAgICBpZiAoIWlzT2JqZWN0KG9wdGlvbnMpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZXF1ZXN0IG9wdGlvbnMgc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gICAgfVxuICAgIHRoaXMucmVxT3B0aW9ucyA9IF8ucGljayhvcHRpb25zLCByZXF1ZXN0T3B0aW9uUHJvcGVydGllcylcbiAgfVxuXG4gIC8qKlxuICAgKiAgVGhpcyBpcyBzMyBTcGVjaWZpYyBhbmQgZG9lcyBub3QgaG9sZCB2YWxpZGl0eSBpbiBhbnkgb3RoZXIgT2JqZWN0IHN0b3JhZ2UuXG4gICAqL1xuICBwcml2YXRlIGdldEFjY2VsZXJhdGVFbmRQb2ludElmU2V0KGJ1Y2tldE5hbWU/OiBzdHJpbmcsIG9iamVjdE5hbWU/OiBzdHJpbmcpIHtcbiAgICBpZiAoIWlzRW1wdHkodGhpcy5zM0FjY2VsZXJhdGVFbmRwb2ludCkgJiYgIWlzRW1wdHkoYnVja2V0TmFtZSkgJiYgIWlzRW1wdHkob2JqZWN0TmFtZSkpIHtcbiAgICAgIC8vIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvblMzL2xhdGVzdC9kZXYvdHJhbnNmZXItYWNjZWxlcmF0aW9uLmh0bWxcbiAgICAgIC8vIERpc2FibGUgdHJhbnNmZXIgYWNjZWxlcmF0aW9uIGZvciBub24tY29tcGxpYW50IGJ1Y2tldCBuYW1lcy5cbiAgICAgIGlmIChidWNrZXROYW1lLmluY2x1ZGVzKCcuJykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUcmFuc2ZlciBBY2NlbGVyYXRpb24gaXMgbm90IHN1cHBvcnRlZCBmb3Igbm9uIGNvbXBsaWFudCBidWNrZXQ6JHtidWNrZXROYW1lfWApXG4gICAgICB9XG4gICAgICAvLyBJZiB0cmFuc2ZlciBhY2NlbGVyYXRpb24gaXMgcmVxdWVzdGVkIHNldCBuZXcgaG9zdC5cbiAgICAgIC8vIEZvciBtb3JlIGRldGFpbHMgYWJvdXQgZW5hYmxpbmcgdHJhbnNmZXIgYWNjZWxlcmF0aW9uIHJlYWQgaGVyZS5cbiAgICAgIC8vIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvblMzL2xhdGVzdC9kZXYvdHJhbnNmZXItYWNjZWxlcmF0aW9uLmh0bWxcbiAgICAgIHJldHVybiB0aGlzLnMzQWNjZWxlcmF0ZUVuZHBvaW50XG4gICAgfVxuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgLyoqXG4gICAqICAgU2V0IGFwcGxpY2F0aW9uIHNwZWNpZmljIGluZm9ybWF0aW9uLlxuICAgKiAgIEdlbmVyYXRlcyBVc2VyLUFnZW50IGluIHRoZSBmb2xsb3dpbmcgc3R5bGUuXG4gICAqICAgTWluSU8gKE9TOyBBUkNIKSBMSUIvVkVSIEFQUC9WRVJcbiAgICovXG4gIHNldEFwcEluZm8oYXBwTmFtZTogc3RyaW5nLCBhcHBWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBpZiAoIWlzU3RyaW5nKGFwcE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBJbnZhbGlkIGFwcE5hbWU6ICR7YXBwTmFtZX1gKVxuICAgIH1cbiAgICBpZiAoYXBwTmFtZS50cmltKCkgPT09ICcnKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCdJbnB1dCBhcHBOYW1lIGNhbm5vdCBiZSBlbXB0eS4nKVxuICAgIH1cbiAgICBpZiAoIWlzU3RyaW5nKGFwcFZlcnNpb24pKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBJbnZhbGlkIGFwcFZlcnNpb246ICR7YXBwVmVyc2lvbn1gKVxuICAgIH1cbiAgICBpZiAoYXBwVmVyc2lvbi50cmltKCkgPT09ICcnKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCdJbnB1dCBhcHBWZXJzaW9uIGNhbm5vdCBiZSBlbXB0eS4nKVxuICAgIH1cbiAgICB0aGlzLnVzZXJBZ2VudCA9IGAke3RoaXMudXNlckFnZW50fSAke2FwcE5hbWV9LyR7YXBwVmVyc2lvbn1gXG4gIH1cblxuICAvKipcbiAgICogcmV0dXJucyBvcHRpb25zIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIHdpdGggaHR0cC5yZXF1ZXN0KClcbiAgICogVGFrZXMgY2FyZSBvZiBjb25zdHJ1Y3RpbmcgdmlydHVhbC1ob3N0LXN0eWxlIG9yIHBhdGgtc3R5bGUgaG9zdG5hbWVcbiAgICovXG4gIHByb3RlY3RlZCBnZXRSZXF1ZXN0T3B0aW9ucyhcbiAgICBvcHRzOiBSZXF1ZXN0T3B0aW9uICYge1xuICAgICAgcmVnaW9uOiBzdHJpbmdcbiAgICB9LFxuICApOiBJUmVxdWVzdCAmIHtcbiAgICBob3N0OiBzdHJpbmdcbiAgICBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+XG4gIH0ge1xuICAgIGNvbnN0IG1ldGhvZCA9IG9wdHMubWV0aG9kXG4gICAgY29uc3QgcmVnaW9uID0gb3B0cy5yZWdpb25cbiAgICBjb25zdCBidWNrZXROYW1lID0gb3B0cy5idWNrZXROYW1lXG4gICAgbGV0IG9iamVjdE5hbWUgPSBvcHRzLm9iamVjdE5hbWVcbiAgICBjb25zdCBoZWFkZXJzID0gb3B0cy5oZWFkZXJzXG4gICAgY29uc3QgcXVlcnkgPSBvcHRzLnF1ZXJ5XG5cbiAgICBsZXQgcmVxT3B0aW9ucyA9IHtcbiAgICAgIG1ldGhvZCxcbiAgICAgIGhlYWRlcnM6IHt9IGFzIFJlcXVlc3RIZWFkZXJzLFxuICAgICAgcHJvdG9jb2w6IHRoaXMucHJvdG9jb2wsXG4gICAgICAvLyBJZiBjdXN0b20gdHJhbnNwb3J0QWdlbnQgd2FzIHN1cHBsaWVkIGVhcmxpZXIsIHdlJ2xsIGluamVjdCBpdCBoZXJlXG4gICAgICBhZ2VudDogdGhpcy50cmFuc3BvcnRBZ2VudCxcbiAgICB9XG5cbiAgICAvLyBWZXJpZnkgaWYgdmlydHVhbCBob3N0IHN1cHBvcnRlZC5cbiAgICBsZXQgdmlydHVhbEhvc3RTdHlsZVxuICAgIGlmIChidWNrZXROYW1lKSB7XG4gICAgICB2aXJ0dWFsSG9zdFN0eWxlID0gaXNWaXJ0dWFsSG9zdFN0eWxlKHRoaXMuaG9zdCwgdGhpcy5wcm90b2NvbCwgYnVja2V0TmFtZSwgdGhpcy5wYXRoU3R5bGUpXG4gICAgfVxuXG4gICAgbGV0IHBhdGggPSAnLydcbiAgICBsZXQgaG9zdCA9IHRoaXMuaG9zdFxuXG4gICAgbGV0IHBvcnQ6IHVuZGVmaW5lZCB8IG51bWJlclxuICAgIGlmICh0aGlzLnBvcnQpIHtcbiAgICAgIHBvcnQgPSB0aGlzLnBvcnRcbiAgICB9XG5cbiAgICBpZiAob2JqZWN0TmFtZSkge1xuICAgICAgb2JqZWN0TmFtZSA9IHVyaVJlc291cmNlRXNjYXBlKG9iamVjdE5hbWUpXG4gICAgfVxuXG4gICAgLy8gRm9yIEFtYXpvbiBTMyBlbmRwb2ludCwgZ2V0IGVuZHBvaW50IGJhc2VkIG9uIHJlZ2lvbi5cbiAgICBpZiAoaXNBbWF6b25FbmRwb2ludChob3N0KSkge1xuICAgICAgY29uc3QgYWNjZWxlcmF0ZUVuZFBvaW50ID0gdGhpcy5nZXRBY2NlbGVyYXRlRW5kUG9pbnRJZlNldChidWNrZXROYW1lLCBvYmplY3ROYW1lKVxuICAgICAgaWYgKGFjY2VsZXJhdGVFbmRQb2ludCkge1xuICAgICAgICBob3N0ID0gYCR7YWNjZWxlcmF0ZUVuZFBvaW50fWBcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGhvc3QgPSBnZXRTM0VuZHBvaW50KHJlZ2lvbilcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodmlydHVhbEhvc3RTdHlsZSAmJiAhb3B0cy5wYXRoU3R5bGUpIHtcbiAgICAgIC8vIEZvciBhbGwgaG9zdHMgd2hpY2ggc3VwcG9ydCB2aXJ0dWFsIGhvc3Qgc3R5bGUsIGBidWNrZXROYW1lYFxuICAgICAgLy8gaXMgcGFydCBvZiB0aGUgaG9zdG5hbWUgaW4gdGhlIGZvbGxvd2luZyBmb3JtYXQ6XG4gICAgICAvL1xuICAgICAgLy8gIHZhciBob3N0ID0gJ2J1Y2tldE5hbWUuZXhhbXBsZS5jb20nXG4gICAgICAvL1xuICAgICAgaWYgKGJ1Y2tldE5hbWUpIHtcbiAgICAgICAgaG9zdCA9IGAke2J1Y2tldE5hbWV9LiR7aG9zdH1gXG4gICAgICB9XG4gICAgICBpZiAob2JqZWN0TmFtZSkge1xuICAgICAgICBwYXRoID0gYC8ke29iamVjdE5hbWV9YFxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBGb3IgYWxsIFMzIGNvbXBhdGlibGUgc3RvcmFnZSBzZXJ2aWNlcyB3ZSB3aWxsIGZhbGxiYWNrIHRvXG4gICAgICAvLyBwYXRoIHN0eWxlIHJlcXVlc3RzLCB3aGVyZSBgYnVja2V0TmFtZWAgaXMgcGFydCBvZiB0aGUgVVJJXG4gICAgICAvLyBwYXRoLlxuICAgICAgaWYgKGJ1Y2tldE5hbWUpIHtcbiAgICAgICAgcGF0aCA9IGAvJHtidWNrZXROYW1lfWBcbiAgICAgIH1cbiAgICAgIGlmIChvYmplY3ROYW1lKSB7XG4gICAgICAgIHBhdGggPSBgLyR7YnVja2V0TmFtZX0vJHtvYmplY3ROYW1lfWBcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocXVlcnkpIHtcbiAgICAgIHBhdGggKz0gYD8ke3F1ZXJ5fWBcbiAgICB9XG4gICAgcmVxT3B0aW9ucy5oZWFkZXJzLmhvc3QgPSBob3N0XG4gICAgaWYgKChyZXFPcHRpb25zLnByb3RvY29sID09PSAnaHR0cDonICYmIHBvcnQgIT09IDgwKSB8fCAocmVxT3B0aW9ucy5wcm90b2NvbCA9PT0gJ2h0dHBzOicgJiYgcG9ydCAhPT0gNDQzKSkge1xuICAgICAgcmVxT3B0aW9ucy5oZWFkZXJzLmhvc3QgPSBqb2luSG9zdFBvcnQoaG9zdCwgcG9ydClcbiAgICB9XG5cbiAgICByZXFPcHRpb25zLmhlYWRlcnNbJ3VzZXItYWdlbnQnXSA9IHRoaXMudXNlckFnZW50XG4gICAgaWYgKGhlYWRlcnMpIHtcbiAgICAgIC8vIGhhdmUgYWxsIGhlYWRlciBrZXlzIGluIGxvd2VyIGNhc2UgLSB0byBtYWtlIHNpZ25pbmcgZWFzeVxuICAgICAgZm9yIChjb25zdCBbaywgdl0gb2YgT2JqZWN0LmVudHJpZXMoaGVhZGVycykpIHtcbiAgICAgICAgcmVxT3B0aW9ucy5oZWFkZXJzW2sudG9Mb3dlckNhc2UoKV0gPSB2XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVXNlIGFueSByZXF1ZXN0IG9wdGlvbiBzcGVjaWZpZWQgaW4gbWluaW9DbGllbnQuc2V0UmVxdWVzdE9wdGlvbnMoKVxuICAgIHJlcU9wdGlvbnMgPSBPYmplY3QuYXNzaWduKHt9LCB0aGlzLnJlcU9wdGlvbnMsIHJlcU9wdGlvbnMpXG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4ucmVxT3B0aW9ucyxcbiAgICAgIGhlYWRlcnM6IF8ubWFwVmFsdWVzKF8ucGlja0J5KHJlcU9wdGlvbnMuaGVhZGVycywgaXNEZWZpbmVkKSwgKHYpID0+IHYudG9TdHJpbmcoKSksXG4gICAgICBob3N0LFxuICAgICAgcG9ydCxcbiAgICAgIHBhdGgsXG4gICAgfSBzYXRpc2ZpZXMgaHR0cHMuUmVxdWVzdE9wdGlvbnNcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBzZXRDcmVkZW50aWFsc1Byb3ZpZGVyKGNyZWRlbnRpYWxzUHJvdmlkZXI6IENyZWRlbnRpYWxQcm92aWRlcikge1xuICAgIGlmICghKGNyZWRlbnRpYWxzUHJvdmlkZXIgaW5zdGFuY2VvZiBDcmVkZW50aWFsUHJvdmlkZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBnZXQgY3JlZGVudGlhbHMuIEV4cGVjdGVkIGluc3RhbmNlIG9mIENyZWRlbnRpYWxQcm92aWRlcicpXG4gICAgfVxuICAgIHRoaXMuY3JlZGVudGlhbHNQcm92aWRlciA9IGNyZWRlbnRpYWxzUHJvdmlkZXJcbiAgICBhd2FpdCB0aGlzLmNoZWNrQW5kUmVmcmVzaENyZWRzKClcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY2hlY2tBbmRSZWZyZXNoQ3JlZHMoKSB7XG4gICAgaWYgKHRoaXMuY3JlZGVudGlhbHNQcm92aWRlcikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgY3JlZGVudGlhbHNDb25mID0gYXdhaXQgdGhpcy5jcmVkZW50aWFsc1Byb3ZpZGVyLmdldENyZWRlbnRpYWxzKClcbiAgICAgICAgdGhpcy5hY2Nlc3NLZXkgPSBjcmVkZW50aWFsc0NvbmYuZ2V0QWNjZXNzS2V5KClcbiAgICAgICAgdGhpcy5zZWNyZXRLZXkgPSBjcmVkZW50aWFsc0NvbmYuZ2V0U2VjcmV0S2V5KClcbiAgICAgICAgdGhpcy5zZXNzaW9uVG9rZW4gPSBjcmVkZW50aWFsc0NvbmYuZ2V0U2Vzc2lvblRva2VuKClcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gZ2V0IGNyZWRlbnRpYWxzOiAke2V9YCwgeyBjYXVzZTogZSB9KVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbG9nU3RyZWFtPzogc3RyZWFtLldyaXRhYmxlXG5cbiAgLyoqXG4gICAqIGxvZyB0aGUgcmVxdWVzdCwgcmVzcG9uc2UsIGVycm9yXG4gICAqL1xuICBwcml2YXRlIGxvZ0hUVFAocmVxT3B0aW9uczogSVJlcXVlc3QsIHJlc3BvbnNlOiBodHRwLkluY29taW5nTWVzc2FnZSB8IG51bGwsIGVycj86IHVua25vd24pIHtcbiAgICAvLyBpZiBubyBsb2dTdHJlYW0gYXZhaWxhYmxlIHJldHVybi5cbiAgICBpZiAoIXRoaXMubG9nU3RyZWFtKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgaWYgKCFpc09iamVjdChyZXFPcHRpb25zKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncmVxT3B0aW9ucyBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgICB9XG4gICAgaWYgKHJlc3BvbnNlICYmICFpc1JlYWRhYmxlU3RyZWFtKHJlc3BvbnNlKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncmVzcG9uc2Ugc2hvdWxkIGJlIG9mIHR5cGUgXCJTdHJlYW1cIicpXG4gICAgfVxuICAgIGlmIChlcnIgJiYgIShlcnIgaW5zdGFuY2VvZiBFcnJvcikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2VyciBzaG91bGQgYmUgb2YgdHlwZSBcIkVycm9yXCInKVxuICAgIH1cbiAgICBjb25zdCBsb2dTdHJlYW0gPSB0aGlzLmxvZ1N0cmVhbVxuICAgIGNvbnN0IGxvZ0hlYWRlcnMgPSAoaGVhZGVyczogUmVxdWVzdEhlYWRlcnMpID0+IHtcbiAgICAgIE9iamVjdC5lbnRyaWVzKGhlYWRlcnMpLmZvckVhY2goKFtrLCB2XSkgPT4ge1xuICAgICAgICBpZiAoayA9PSAnYXV0aG9yaXphdGlvbicpIHtcbiAgICAgICAgICBpZiAoaXNTdHJpbmcodikpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlZGFjdG9yID0gbmV3IFJlZ0V4cCgnU2lnbmF0dXJlPShbMC05YS1mXSspJylcbiAgICAgICAgICAgIHYgPSB2LnJlcGxhY2UocmVkYWN0b3IsICdTaWduYXR1cmU9KipSRURBQ1RFRCoqJylcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbG9nU3RyZWFtLndyaXRlKGAke2t9OiAke3Z9XFxuYClcbiAgICAgIH0pXG4gICAgICBsb2dTdHJlYW0ud3JpdGUoJ1xcbicpXG4gICAgfVxuICAgIGxvZ1N0cmVhbS53cml0ZShgUkVRVUVTVDogJHtyZXFPcHRpb25zLm1ldGhvZH0gJHtyZXFPcHRpb25zLnBhdGh9XFxuYClcbiAgICBsb2dIZWFkZXJzKHJlcU9wdGlvbnMuaGVhZGVycylcbiAgICBpZiAocmVzcG9uc2UpIHtcbiAgICAgIHRoaXMubG9nU3RyZWFtLndyaXRlKGBSRVNQT05TRTogJHtyZXNwb25zZS5zdGF0dXNDb2RlfVxcbmApXG4gICAgICBsb2dIZWFkZXJzKHJlc3BvbnNlLmhlYWRlcnMgYXMgUmVxdWVzdEhlYWRlcnMpXG4gICAgfVxuICAgIGlmIChlcnIpIHtcbiAgICAgIGxvZ1N0cmVhbS53cml0ZSgnRVJST1IgQk9EWTpcXG4nKVxuICAgICAgY29uc3QgZXJySlNPTiA9IEpTT04uc3RyaW5naWZ5KGVyciwgbnVsbCwgJ1xcdCcpXG4gICAgICBsb2dTdHJlYW0ud3JpdGUoYCR7ZXJySlNPTn1cXG5gKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGUgdHJhY2luZ1xuICAgKi9cbiAgcHVibGljIHRyYWNlT24oc3RyZWFtPzogc3RyZWFtLldyaXRhYmxlKSB7XG4gICAgaWYgKCFzdHJlYW0pIHtcbiAgICAgIHN0cmVhbSA9IHByb2Nlc3Muc3Rkb3V0XG4gICAgfVxuICAgIHRoaXMubG9nU3RyZWFtID0gc3RyZWFtXG4gIH1cblxuICAvKipcbiAgICogRGlzYWJsZSB0cmFjaW5nXG4gICAqL1xuICBwdWJsaWMgdHJhY2VPZmYoKSB7XG4gICAgdGhpcy5sb2dTdHJlYW0gPSB1bmRlZmluZWRcbiAgfVxuXG4gIC8qKlxuICAgKiBtYWtlUmVxdWVzdCBpcyB0aGUgcHJpbWl0aXZlIHVzZWQgYnkgdGhlIGFwaXMgZm9yIG1ha2luZyBTMyByZXF1ZXN0cy5cbiAgICogcGF5bG9hZCBjYW4gYmUgZW1wdHkgc3RyaW5nIGluIGNhc2Ugb2Ygbm8gcGF5bG9hZC5cbiAgICogc3RhdHVzQ29kZSBpcyB0aGUgZXhwZWN0ZWQgc3RhdHVzQ29kZS4gSWYgcmVzcG9uc2Uuc3RhdHVzQ29kZSBkb2VzIG5vdCBtYXRjaFxuICAgKiB3ZSBwYXJzZSB0aGUgWE1MIGVycm9yIGFuZCBjYWxsIHRoZSBjYWxsYmFjayB3aXRoIHRoZSBlcnJvciBtZXNzYWdlLlxuICAgKlxuICAgKiBBIHZhbGlkIHJlZ2lvbiBpcyBwYXNzZWQgYnkgdGhlIGNhbGxzIC0gbGlzdEJ1Y2tldHMsIG1ha2VCdWNrZXQgYW5kIGdldEJ1Y2tldFJlZ2lvbi5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBhc3luYyBtYWtlUmVxdWVzdEFzeW5jKFxuICAgIG9wdGlvbnM6IFJlcXVlc3RPcHRpb24sXG4gICAgcGF5bG9hZDogQmluYXJ5ID0gJycsXG4gICAgZXhwZWN0ZWRDb2RlczogbnVtYmVyW10gPSBbMjAwXSxcbiAgICByZWdpb24gPSAnJyxcbiAgKTogUHJvbWlzZTxodHRwLkluY29taW5nTWVzc2FnZT4ge1xuICAgIGlmICghaXNPYmplY3Qob3B0aW9ucykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ29wdGlvbnMgc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gICAgfVxuICAgIGlmICghaXNTdHJpbmcocGF5bG9hZCkgJiYgIWlzT2JqZWN0KHBheWxvYWQpKSB7XG4gICAgICAvLyBCdWZmZXIgaXMgb2YgdHlwZSAnb2JqZWN0J1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncGF5bG9hZCBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiIG9yIFwiQnVmZmVyXCInKVxuICAgIH1cbiAgICBleHBlY3RlZENvZGVzLmZvckVhY2goKHN0YXR1c0NvZGUpID0+IHtcbiAgICAgIGlmICghaXNOdW1iZXIoc3RhdHVzQ29kZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignc3RhdHVzQ29kZSBzaG91bGQgYmUgb2YgdHlwZSBcIm51bWJlclwiJylcbiAgICAgIH1cbiAgICB9KVxuICAgIGlmICghaXNTdHJpbmcocmVnaW9uKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncmVnaW9uIHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICAgIH1cbiAgICBpZiAoIW9wdGlvbnMuaGVhZGVycykge1xuICAgICAgb3B0aW9ucy5oZWFkZXJzID0ge31cbiAgICB9XG4gICAgaWYgKG9wdGlvbnMubWV0aG9kID09PSAnUE9TVCcgfHwgb3B0aW9ucy5tZXRob2QgPT09ICdQVVQnIHx8IG9wdGlvbnMubWV0aG9kID09PSAnREVMRVRFJykge1xuICAgICAgb3B0aW9ucy5oZWFkZXJzWydjb250ZW50LWxlbmd0aCddID0gcGF5bG9hZC5sZW5ndGgudG9TdHJpbmcoKVxuICAgIH1cbiAgICBjb25zdCBzaGEyNTZzdW0gPSB0aGlzLmVuYWJsZVNIQTI1NiA/IHRvU2hhMjU2KHBheWxvYWQpIDogJydcbiAgICByZXR1cm4gdGhpcy5tYWtlUmVxdWVzdFN0cmVhbUFzeW5jKG9wdGlvbnMsIHBheWxvYWQsIHNoYTI1NnN1bSwgZXhwZWN0ZWRDb2RlcywgcmVnaW9uKVxuICB9XG5cbiAgLyoqXG4gICAqIG5ldyByZXF1ZXN0IHdpdGggcHJvbWlzZVxuICAgKlxuICAgKiBObyBuZWVkIHRvIGRyYWluIHJlc3BvbnNlLCByZXNwb25zZSBib2R5IGlzIG5vdCB2YWxpZFxuICAgKi9cbiAgYXN5bmMgbWFrZVJlcXVlc3RBc3luY09taXQoXG4gICAgb3B0aW9uczogUmVxdWVzdE9wdGlvbixcbiAgICBwYXlsb2FkOiBCaW5hcnkgPSAnJyxcbiAgICBzdGF0dXNDb2RlczogbnVtYmVyW10gPSBbMjAwXSxcbiAgICByZWdpb24gPSAnJyxcbiAgKTogUHJvbWlzZTxPbWl0PGh0dHAuSW5jb21pbmdNZXNzYWdlLCAnb24nPj4ge1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyhvcHRpb25zLCBwYXlsb2FkLCBzdGF0dXNDb2RlcywgcmVnaW9uKVxuICAgIGF3YWl0IGRyYWluUmVzcG9uc2UocmVzKVxuICAgIHJldHVybiByZXNcbiAgfVxuXG4gIC8qKlxuICAgKiBtYWtlUmVxdWVzdFN0cmVhbSB3aWxsIGJlIHVzZWQgZGlyZWN0bHkgaW5zdGVhZCBvZiBtYWtlUmVxdWVzdCBpbiBjYXNlIHRoZSBwYXlsb2FkXG4gICAqIGlzIGF2YWlsYWJsZSBhcyBhIHN0cmVhbS4gZm9yIGV4LiBwdXRPYmplY3RcbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBhc3luYyBtYWtlUmVxdWVzdFN0cmVhbUFzeW5jKFxuICAgIG9wdGlvbnM6IFJlcXVlc3RPcHRpb24sXG4gICAgYm9keTogc3RyZWFtLlJlYWRhYmxlIHwgQmluYXJ5LFxuICAgIHNoYTI1NnN1bTogc3RyaW5nLFxuICAgIHN0YXR1c0NvZGVzOiBudW1iZXJbXSxcbiAgICByZWdpb246IHN0cmluZyxcbiAgKTogUHJvbWlzZTxodHRwLkluY29taW5nTWVzc2FnZT4ge1xuICAgIGlmICghaXNPYmplY3Qob3B0aW9ucykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ29wdGlvbnMgc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gICAgfVxuICAgIGlmICghKEJ1ZmZlci5pc0J1ZmZlcihib2R5KSB8fCB0eXBlb2YgYm9keSA9PT0gJ3N0cmluZycgfHwgaXNSZWFkYWJsZVN0cmVhbShib2R5KSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoXG4gICAgICAgIGBzdHJlYW0gc2hvdWxkIGJlIGEgQnVmZmVyLCBzdHJpbmcgb3IgcmVhZGFibGUgU3RyZWFtLCBnb3QgJHt0eXBlb2YgYm9keX0gaW5zdGVhZGAsXG4gICAgICApXG4gICAgfVxuICAgIGlmICghaXNTdHJpbmcoc2hhMjU2c3VtKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignc2hhMjU2c3VtIHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICAgIH1cbiAgICBzdGF0dXNDb2Rlcy5mb3JFYWNoKChzdGF0dXNDb2RlKSA9PiB7XG4gICAgICBpZiAoIWlzTnVtYmVyKHN0YXR1c0NvZGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3N0YXR1c0NvZGUgc2hvdWxkIGJlIG9mIHR5cGUgXCJudW1iZXJcIicpXG4gICAgICB9XG4gICAgfSlcbiAgICBpZiAoIWlzU3RyaW5nKHJlZ2lvbikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3JlZ2lvbiBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgICB9XG4gICAgLy8gc2hhMjU2c3VtIHdpbGwgYmUgZW1wdHkgZm9yIGFub255bW91cyBvciBodHRwcyByZXF1ZXN0c1xuICAgIGlmICghdGhpcy5lbmFibGVTSEEyNTYgJiYgc2hhMjU2c3VtLmxlbmd0aCAhPT0gMCkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihgc2hhMjU2c3VtIGV4cGVjdGVkIHRvIGJlIGVtcHR5IGZvciBhbm9ueW1vdXMgb3IgaHR0cHMgcmVxdWVzdHNgKVxuICAgIH1cbiAgICAvLyBzaGEyNTZzdW0gc2hvdWxkIGJlIHZhbGlkIGZvciBub24tYW5vbnltb3VzIGh0dHAgcmVxdWVzdHMuXG4gICAgaWYgKHRoaXMuZW5hYmxlU0hBMjU2ICYmIHNoYTI1NnN1bS5sZW5ndGggIT09IDY0KSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKGBJbnZhbGlkIHNoYTI1NnN1bSA6ICR7c2hhMjU2c3VtfWApXG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5jaGVja0FuZFJlZnJlc2hDcmVkcygpXG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgIHJlZ2lvbiA9IHJlZ2lvbiB8fCAoYXdhaXQgdGhpcy5nZXRCdWNrZXRSZWdpb25Bc3luYyhvcHRpb25zLmJ1Y2tldE5hbWUhKSlcblxuICAgIGNvbnN0IHJlcU9wdGlvbnMgPSB0aGlzLmdldFJlcXVlc3RPcHRpb25zKHsgLi4ub3B0aW9ucywgcmVnaW9uIH0pXG4gICAgaWYgKCF0aGlzLmFub255bW91cykge1xuICAgICAgLy8gRm9yIG5vbi1hbm9ueW1vdXMgaHR0cHMgcmVxdWVzdHMgc2hhMjU2c3VtIGlzICdVTlNJR05FRC1QQVlMT0FEJyBmb3Igc2lnbmF0dXJlIGNhbGN1bGF0aW9uLlxuICAgICAgaWYgKCF0aGlzLmVuYWJsZVNIQTI1Nikge1xuICAgICAgICBzaGEyNTZzdW0gPSAnVU5TSUdORUQtUEFZTE9BRCdcbiAgICAgIH1cbiAgICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZSgpXG4gICAgICByZXFPcHRpb25zLmhlYWRlcnNbJ3gtYW16LWRhdGUnXSA9IG1ha2VEYXRlTG9uZyhkYXRlKVxuICAgICAgcmVxT3B0aW9ucy5oZWFkZXJzWyd4LWFtei1jb250ZW50LXNoYTI1NiddID0gc2hhMjU2c3VtXG4gICAgICBpZiAodGhpcy5zZXNzaW9uVG9rZW4pIHtcbiAgICAgICAgcmVxT3B0aW9ucy5oZWFkZXJzWyd4LWFtei1zZWN1cml0eS10b2tlbiddID0gdGhpcy5zZXNzaW9uVG9rZW5cbiAgICAgIH1cbiAgICAgIHJlcU9wdGlvbnMuaGVhZGVycy5hdXRob3JpemF0aW9uID0gc2lnblY0KHJlcU9wdGlvbnMsIHRoaXMuYWNjZXNzS2V5LCB0aGlzLnNlY3JldEtleSwgcmVnaW9uLCBkYXRlLCBzaGEyNTZzdW0pXG4gICAgfVxuXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCByZXF1ZXN0V2l0aFJldHJ5KFxuICAgICAgdGhpcy50cmFuc3BvcnQsXG4gICAgICByZXFPcHRpb25zLFxuICAgICAgYm9keSxcbiAgICAgIHRoaXMucmV0cnlPcHRpb25zLmRpc2FibGVSZXRyeSA9PT0gdHJ1ZSA/IDAgOiB0aGlzLnJldHJ5T3B0aW9ucy5tYXhpbXVtUmV0cnlDb3VudCxcbiAgICAgIHRoaXMucmV0cnlPcHRpb25zLmJhc2VEZWxheU1zLFxuICAgICAgdGhpcy5yZXRyeU9wdGlvbnMubWF4aW11bURlbGF5TXMsXG4gICAgKVxuICAgIGlmICghcmVzcG9uc2Uuc3RhdHVzQ29kZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQlVHOiByZXNwb25zZSBkb2Vzbid0IGhhdmUgYSBzdGF0dXNDb2RlXCIpXG4gICAgfVxuXG4gICAgaWYgKCFzdGF0dXNDb2Rlcy5pbmNsdWRlcyhyZXNwb25zZS5zdGF0dXNDb2RlKSkge1xuICAgICAgLy8gRm9yIGFuIGluY29ycmVjdCByZWdpb24sIFMzIHNlcnZlciBhbHdheXMgc2VuZHMgYmFjayA0MDAuXG4gICAgICAvLyBCdXQgd2Ugd2lsbCBkbyBjYWNoZSBpbnZhbGlkYXRpb24gZm9yIGFsbCBlcnJvcnMgc28gdGhhdCxcbiAgICAgIC8vIGluIGZ1dHVyZSwgaWYgQVdTIFMzIGRlY2lkZXMgdG8gc2VuZCBhIGRpZmZlcmVudCBzdGF0dXMgY29kZSBvclxuICAgICAgLy8gWE1MIGVycm9yIGNvZGUgd2Ugd2lsbCBzdGlsbCB3b3JrIGZpbmUuXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgZGVsZXRlIHRoaXMucmVnaW9uTWFwW29wdGlvbnMuYnVja2V0TmFtZSFdXG5cbiAgICAgIGNvbnN0IGVyciA9IGF3YWl0IHhtbFBhcnNlcnMucGFyc2VSZXNwb25zZUVycm9yKHJlc3BvbnNlKVxuICAgICAgdGhpcy5sb2dIVFRQKHJlcU9wdGlvbnMsIHJlc3BvbnNlLCBlcnIpXG4gICAgICB0aHJvdyBlcnJcbiAgICB9XG5cbiAgICB0aGlzLmxvZ0hUVFAocmVxT3B0aW9ucywgcmVzcG9uc2UpXG5cbiAgICByZXR1cm4gcmVzcG9uc2VcbiAgfVxuXG4gIC8qKlxuICAgKiBnZXRzIHRoZSByZWdpb24gb2YgdGhlIGJ1Y2tldFxuICAgKlxuICAgKiBAcGFyYW0gYnVja2V0TmFtZVxuICAgKlxuICAgKi9cbiAgYXN5bmMgZ2V0QnVja2V0UmVnaW9uQXN5bmMoYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoYEludmFsaWQgYnVja2V0IG5hbWUgOiAke2J1Y2tldE5hbWV9YClcbiAgICB9XG5cbiAgICAvLyBSZWdpb24gaXMgc2V0IHdpdGggY29uc3RydWN0b3IsIHJldHVybiB0aGUgcmVnaW9uIHJpZ2h0IGhlcmUuXG4gICAgaWYgKHRoaXMucmVnaW9uKSB7XG4gICAgICByZXR1cm4gdGhpcy5yZWdpb25cbiAgICB9XG5cbiAgICBjb25zdCBjYWNoZWQgPSB0aGlzLnJlZ2lvbk1hcFtidWNrZXROYW1lXVxuICAgIGlmIChjYWNoZWQpIHtcbiAgICAgIHJldHVybiBjYWNoZWRcbiAgICB9XG5cbiAgICBjb25zdCBleHRyYWN0UmVnaW9uQXN5bmMgPSBhc3luYyAocmVzcG9uc2U6IGh0dHAuSW5jb21pbmdNZXNzYWdlKSA9PiB7XG4gICAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVhZEFzU3RyaW5nKHJlc3BvbnNlKVxuICAgICAgY29uc3QgcmVnaW9uID0geG1sUGFyc2Vycy5wYXJzZUJ1Y2tldFJlZ2lvbihib2R5KSB8fCBERUZBVUxUX1JFR0lPTlxuICAgICAgdGhpcy5yZWdpb25NYXBbYnVja2V0TmFtZV0gPSByZWdpb25cbiAgICAgIHJldHVybiByZWdpb25cbiAgICB9XG5cbiAgICBjb25zdCBtZXRob2QgPSAnR0VUJ1xuICAgIGNvbnN0IHF1ZXJ5ID0gJ2xvY2F0aW9uJ1xuICAgIC8vIGBnZXRCdWNrZXRMb2NhdGlvbmAgYmVoYXZlcyBkaWZmZXJlbnRseSBpbiBmb2xsb3dpbmcgd2F5cyBmb3JcbiAgICAvLyBkaWZmZXJlbnQgZW52aXJvbm1lbnRzLlxuICAgIC8vXG4gICAgLy8gLSBGb3Igbm9kZWpzIGVudiB3ZSBkZWZhdWx0IHRvIHBhdGggc3R5bGUgcmVxdWVzdHMuXG4gICAgLy8gLSBGb3IgYnJvd3NlciBlbnYgcGF0aCBzdHlsZSByZXF1ZXN0cyBvbiBidWNrZXRzIHlpZWxkcyBDT1JTXG4gICAgLy8gICBlcnJvci4gVG8gY2lyY3VtdmVudCB0aGlzIHByb2JsZW0gd2UgbWFrZSBhIHZpcnR1YWwgaG9zdFxuICAgIC8vICAgc3R5bGUgcmVxdWVzdCBzaWduZWQgd2l0aCAndXMtZWFzdC0xJy4gVGhpcyByZXF1ZXN0IGZhaWxzXG4gICAgLy8gICB3aXRoIGFuIGVycm9yICdBdXRob3JpemF0aW9uSGVhZGVyTWFsZm9ybWVkJywgYWRkaXRpb25hbGx5XG4gICAgLy8gICB0aGUgZXJyb3IgWE1MIGFsc28gcHJvdmlkZXMgUmVnaW9uIG9mIHRoZSBidWNrZXQuIFRvIHZhbGlkYXRlXG4gICAgLy8gICB0aGlzIHJlZ2lvbiBpcyBwcm9wZXIgd2UgcmV0cnkgdGhlIHNhbWUgcmVxdWVzdCB3aXRoIHRoZSBuZXdseVxuICAgIC8vICAgb2J0YWluZWQgcmVnaW9uLlxuICAgIGNvbnN0IHBhdGhTdHlsZSA9IHRoaXMucGF0aFN0eWxlICYmICFpc0Jyb3dzZXJcbiAgICBsZXQgcmVnaW9uOiBzdHJpbmdcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kLCBidWNrZXROYW1lLCBxdWVyeSwgcGF0aFN0eWxlIH0sICcnLCBbMjAwXSwgREVGQVVMVF9SRUdJT04pXG4gICAgICByZXR1cm4gZXh0cmFjdFJlZ2lvbkFzeW5jKHJlcylcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyBtYWtlIGFsaWdubWVudCB3aXRoIG1jIGNsaVxuICAgICAgaWYgKGUgaW5zdGFuY2VvZiBlcnJvcnMuUzNFcnJvcikge1xuICAgICAgICBjb25zdCBlcnJDb2RlID0gZS5jb2RlXG4gICAgICAgIGNvbnN0IGVyclJlZ2lvbiA9IGUucmVnaW9uXG4gICAgICAgIGlmIChlcnJDb2RlID09PSAnQWNjZXNzRGVuaWVkJyAmJiAhZXJyUmVnaW9uKSB7XG4gICAgICAgICAgcmV0dXJuIERFRkFVTFRfUkVHSU9OXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXRzLWNvbW1lbnRcbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIGlmICghKGUubmFtZSA9PT0gJ0F1dGhvcml6YXRpb25IZWFkZXJNYWxmb3JtZWQnKSkge1xuICAgICAgICB0aHJvdyBlXG4gICAgICB9XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIHdlIHNldCBleHRyYSBwcm9wZXJ0aWVzIG9uIGVycm9yIG9iamVjdFxuICAgICAgcmVnaW9uID0gZS5SZWdpb24gYXMgc3RyaW5nXG4gICAgICBpZiAoIXJlZ2lvbikge1xuICAgICAgICB0aHJvdyBlXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kLCBidWNrZXROYW1lLCBxdWVyeSwgcGF0aFN0eWxlIH0sICcnLCBbMjAwXSwgcmVnaW9uKVxuICAgIHJldHVybiBhd2FpdCBleHRyYWN0UmVnaW9uQXN5bmMocmVzKVxuICB9XG5cbiAgLyoqXG4gICAqIG1ha2VSZXF1ZXN0IGlzIHRoZSBwcmltaXRpdmUgdXNlZCBieSB0aGUgYXBpcyBmb3IgbWFraW5nIFMzIHJlcXVlc3RzLlxuICAgKiBwYXlsb2FkIGNhbiBiZSBlbXB0eSBzdHJpbmcgaW4gY2FzZSBvZiBubyBwYXlsb2FkLlxuICAgKiBzdGF0dXNDb2RlIGlzIHRoZSBleHBlY3RlZCBzdGF0dXNDb2RlLiBJZiByZXNwb25zZS5zdGF0dXNDb2RlIGRvZXMgbm90IG1hdGNoXG4gICAqIHdlIHBhcnNlIHRoZSBYTUwgZXJyb3IgYW5kIGNhbGwgdGhlIGNhbGxiYWNrIHdpdGggdGhlIGVycm9yIG1lc3NhZ2UuXG4gICAqIEEgdmFsaWQgcmVnaW9uIGlzIHBhc3NlZCBieSB0aGUgY2FsbHMgLSBsaXN0QnVja2V0cywgbWFrZUJ1Y2tldCBhbmRcbiAgICogZ2V0QnVja2V0UmVnaW9uLlxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCB1c2UgYG1ha2VSZXF1ZXN0QXN5bmNgIGluc3RlYWRcbiAgICovXG4gIG1ha2VSZXF1ZXN0KFxuICAgIG9wdGlvbnM6IFJlcXVlc3RPcHRpb24sXG4gICAgcGF5bG9hZDogQmluYXJ5ID0gJycsXG4gICAgZXhwZWN0ZWRDb2RlczogbnVtYmVyW10gPSBbMjAwXSxcbiAgICByZWdpb24gPSAnJyxcbiAgICByZXR1cm5SZXNwb25zZTogYm9vbGVhbixcbiAgICBjYjogKGNiOiB1bmtub3duLCByZXN1bHQ6IGh0dHAuSW5jb21pbmdNZXNzYWdlKSA9PiB2b2lkLFxuICApIHtcbiAgICBsZXQgcHJvbTogUHJvbWlzZTxodHRwLkluY29taW5nTWVzc2FnZT5cbiAgICBpZiAocmV0dXJuUmVzcG9uc2UpIHtcbiAgICAgIHByb20gPSB0aGlzLm1ha2VSZXF1ZXN0QXN5bmMob3B0aW9ucywgcGF5bG9hZCwgZXhwZWN0ZWRDb2RlcywgcmVnaW9uKVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10cy1jb21tZW50XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIGNvbXBhdGlibGUgZm9yIG9sZCBiZWhhdmlvdXJcbiAgICAgIHByb20gPSB0aGlzLm1ha2VSZXF1ZXN0QXN5bmNPbWl0KG9wdGlvbnMsIHBheWxvYWQsIGV4cGVjdGVkQ29kZXMsIHJlZ2lvbilcbiAgICB9XG5cbiAgICBwcm9tLnRoZW4oXG4gICAgICAocmVzdWx0KSA9PiBjYihudWxsLCByZXN1bHQpLFxuICAgICAgKGVycikgPT4ge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10cy1jb21tZW50XG4gICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgY2IoZXJyKVxuICAgICAgfSxcbiAgICApXG4gIH1cblxuICAvKipcbiAgICogbWFrZVJlcXVlc3RTdHJlYW0gd2lsbCBiZSB1c2VkIGRpcmVjdGx5IGluc3RlYWQgb2YgbWFrZVJlcXVlc3QgaW4gY2FzZSB0aGUgcGF5bG9hZFxuICAgKiBpcyBhdmFpbGFibGUgYXMgYSBzdHJlYW0uIGZvciBleC4gcHV0T2JqZWN0XG4gICAqXG4gICAqIEBkZXByZWNhdGVkIHVzZSBgbWFrZVJlcXVlc3RTdHJlYW1Bc3luY2AgaW5zdGVhZFxuICAgKi9cbiAgbWFrZVJlcXVlc3RTdHJlYW0oXG4gICAgb3B0aW9uczogUmVxdWVzdE9wdGlvbixcbiAgICBzdHJlYW06IHN0cmVhbS5SZWFkYWJsZSB8IEJ1ZmZlcixcbiAgICBzaGEyNTZzdW06IHN0cmluZyxcbiAgICBzdGF0dXNDb2RlczogbnVtYmVyW10sXG4gICAgcmVnaW9uOiBzdHJpbmcsXG4gICAgcmV0dXJuUmVzcG9uc2U6IGJvb2xlYW4sXG4gICAgY2I6IChjYjogdW5rbm93biwgcmVzdWx0OiBodHRwLkluY29taW5nTWVzc2FnZSkgPT4gdm9pZCxcbiAgKSB7XG4gICAgY29uc3QgZXhlY3V0b3IgPSBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0U3RyZWFtQXN5bmMob3B0aW9ucywgc3RyZWFtLCBzaGEyNTZzdW0sIHN0YXR1c0NvZGVzLCByZWdpb24pXG4gICAgICBpZiAoIXJldHVyblJlc3BvbnNlKSB7XG4gICAgICAgIGF3YWl0IGRyYWluUmVzcG9uc2UocmVzKVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzXG4gICAgfVxuXG4gICAgZXhlY3V0b3IoKS50aGVuKFxuICAgICAgKHJlc3VsdCkgPT4gY2IobnVsbCwgcmVzdWx0KSxcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXRzLWNvbW1lbnRcbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIChlcnIpID0+IGNiKGVyciksXG4gICAgKVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIHVzZSBgZ2V0QnVja2V0UmVnaW9uQXN5bmNgIGluc3RlYWRcbiAgICovXG4gIGdldEJ1Y2tldFJlZ2lvbihidWNrZXROYW1lOiBzdHJpbmcsIGNiOiAoZXJyOiB1bmtub3duLCByZWdpb246IHN0cmluZykgPT4gdm9pZCkge1xuICAgIHJldHVybiB0aGlzLmdldEJ1Y2tldFJlZ2lvbkFzeW5jKGJ1Y2tldE5hbWUpLnRoZW4oXG4gICAgICAocmVzdWx0KSA9PiBjYihudWxsLCByZXN1bHQpLFxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHMtY29tbWVudFxuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgKGVycikgPT4gY2IoZXJyKSxcbiAgICApXG4gIH1cblxuICAvLyBCdWNrZXQgb3BlcmF0aW9uc1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIHRoZSBidWNrZXQgYGJ1Y2tldE5hbWVgLlxuICAgKlxuICAgKi9cbiAgYXN5bmMgbWFrZUJ1Y2tldChidWNrZXROYW1lOiBzdHJpbmcsIHJlZ2lvbjogUmVnaW9uID0gJycsIG1ha2VPcHRzPzogTWFrZUJ1Y2tldE9wdCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIC8vIEJhY2t3YXJkIENvbXBhdGliaWxpdHlcbiAgICBpZiAoaXNPYmplY3QocmVnaW9uKSkge1xuICAgICAgbWFrZU9wdHMgPSByZWdpb25cbiAgICAgIHJlZ2lvbiA9ICcnXG4gICAgfVxuXG4gICAgaWYgKCFpc1N0cmluZyhyZWdpb24pKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZWdpb24gc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIGlmIChtYWtlT3B0cyAmJiAhaXNPYmplY3QobWFrZU9wdHMpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtYWtlT3B0cyBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgICB9XG5cbiAgICBsZXQgcGF5bG9hZCA9ICcnXG5cbiAgICAvLyBSZWdpb24gYWxyZWFkeSBzZXQgaW4gY29uc3RydWN0b3IsIHZhbGlkYXRlIGlmXG4gICAgLy8gY2FsbGVyIHJlcXVlc3RlZCBidWNrZXQgbG9jYXRpb24gaXMgc2FtZS5cbiAgICBpZiAocmVnaW9uICYmIHRoaXMucmVnaW9uKSB7XG4gICAgICBpZiAocmVnaW9uICE9PSB0aGlzLnJlZ2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKGBDb25maWd1cmVkIHJlZ2lvbiAke3RoaXMucmVnaW9ufSwgcmVxdWVzdGVkICR7cmVnaW9ufWApXG4gICAgICB9XG4gICAgfVxuICAgIC8vIHNlbmRpbmcgbWFrZUJ1Y2tldCByZXF1ZXN0IHdpdGggWE1MIGNvbnRhaW5pbmcgJ3VzLWVhc3QtMScgZmFpbHMuIEZvclxuICAgIC8vIGRlZmF1bHQgcmVnaW9uIHNlcnZlciBleHBlY3RzIHRoZSByZXF1ZXN0IHdpdGhvdXQgYm9keVxuICAgIGlmIChyZWdpb24gJiYgcmVnaW9uICE9PSBERUZBVUxUX1JFR0lPTikge1xuICAgICAgcGF5bG9hZCA9IHhtbC5idWlsZE9iamVjdCh7XG4gICAgICAgIENyZWF0ZUJ1Y2tldENvbmZpZ3VyYXRpb246IHtcbiAgICAgICAgICAkOiB7IHhtbG5zOiAnaHR0cDovL3MzLmFtYXpvbmF3cy5jb20vZG9jLzIwMDYtMDMtMDEvJyB9LFxuICAgICAgICAgIExvY2F0aW9uQ29uc3RyYWludDogcmVnaW9uLFxuICAgICAgICB9LFxuICAgICAgfSlcbiAgICB9XG4gICAgY29uc3QgbWV0aG9kID0gJ1BVVCdcbiAgICBjb25zdCBoZWFkZXJzOiBSZXF1ZXN0SGVhZGVycyA9IHt9XG5cbiAgICBpZiAobWFrZU9wdHMgJiYgbWFrZU9wdHMuT2JqZWN0TG9ja2luZykge1xuICAgICAgaGVhZGVyc1sneC1hbXotYnVja2V0LW9iamVjdC1sb2NrLWVuYWJsZWQnXSA9IHRydWVcbiAgICB9XG5cbiAgICAvLyBGb3IgY3VzdG9tIHJlZ2lvbiBjbGllbnRzICBkZWZhdWx0IHRvIGN1c3RvbSByZWdpb24gc3BlY2lmaWVkIGluIGNsaWVudCBjb25zdHJ1Y3RvclxuICAgIGNvbnN0IGZpbmFsUmVnaW9uID0gdGhpcy5yZWdpb24gfHwgcmVnaW9uIHx8IERFRkFVTFRfUkVHSU9OXG5cbiAgICBjb25zdCByZXF1ZXN0T3B0OiBSZXF1ZXN0T3B0aW9uID0geyBtZXRob2QsIGJ1Y2tldE5hbWUsIGhlYWRlcnMgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luY09taXQocmVxdWVzdE9wdCwgcGF5bG9hZCwgWzIwMF0sIGZpbmFsUmVnaW9uKVxuICAgIH0gY2F0Y2ggKGVycjogdW5rbm93bikge1xuICAgICAgaWYgKHJlZ2lvbiA9PT0gJycgfHwgcmVnaW9uID09PSBERUZBVUxUX1JFR0lPTikge1xuICAgICAgICBpZiAoZXJyIGluc3RhbmNlb2YgZXJyb3JzLlMzRXJyb3IpIHtcbiAgICAgICAgICBjb25zdCBlcnJDb2RlID0gZXJyLmNvZGVcbiAgICAgICAgICBjb25zdCBlcnJSZWdpb24gPSBlcnIucmVnaW9uXG4gICAgICAgICAgaWYgKGVyckNvZGUgPT09ICdBdXRob3JpemF0aW9uSGVhZGVyTWFsZm9ybWVkJyAmJiBlcnJSZWdpb24gIT09ICcnKSB7XG4gICAgICAgICAgICAvLyBSZXRyeSB3aXRoIHJlZ2lvbiByZXR1cm5lZCBhcyBwYXJ0IG9mIGVycm9yXG4gICAgICAgICAgICBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmNPbWl0KHJlcXVlc3RPcHQsIHBheWxvYWQsIFsyMDBdLCBlcnJDb2RlKVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhyb3cgZXJyXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRvIGNoZWNrIGlmIGEgYnVja2V0IGFscmVhZHkgZXhpc3RzLlxuICAgKi9cbiAgYXN5bmMgYnVja2V0RXhpc3RzKGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGNvbnN0IG1ldGhvZCA9ICdIRUFEJ1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmNPbWl0KHsgbWV0aG9kLCBidWNrZXROYW1lIH0pXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICBpZiAoZXJyLmNvZGUgPT09ICdOb1N1Y2hCdWNrZXQnIHx8IGVyci5jb2RlID09PSAnTm90Rm91bmQnKSB7XG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgfVxuICAgICAgdGhyb3cgZXJyXG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWVcbiAgfVxuXG4gIGFzeW5jIHJlbW92ZUJ1Y2tldChidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+XG5cbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIHVzZSBwcm9taXNlIHN0eWxlIEFQSVxuICAgKi9cbiAgcmVtb3ZlQnVja2V0KGJ1Y2tldE5hbWU6IHN0cmluZywgY2FsbGJhY2s6IE5vUmVzdWx0Q2FsbGJhY2spOiB2b2lkXG5cbiAgYXN5bmMgcmVtb3ZlQnVja2V0KGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGNvbnN0IG1ldGhvZCA9ICdERUxFVEUnXG4gICAgYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jT21pdCh7IG1ldGhvZCwgYnVja2V0TmFtZSB9LCAnJywgWzIwNF0pXG4gICAgZGVsZXRlIHRoaXMucmVnaW9uTWFwW2J1Y2tldE5hbWVdXG4gIH1cblxuICAvKipcbiAgICogQ2FsbGJhY2sgaXMgY2FsbGVkIHdpdGggcmVhZGFibGUgc3RyZWFtIG9mIHRoZSBvYmplY3QgY29udGVudC5cbiAgICovXG4gIGFzeW5jIGdldE9iamVjdChidWNrZXROYW1lOiBzdHJpbmcsIG9iamVjdE5hbWU6IHN0cmluZywgZ2V0T3B0cz86IEdldE9iamVjdE9wdHMpOiBQcm9taXNlPHN0cmVhbS5SZWFkYWJsZT4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNWYWxpZE9iamVjdE5hbWUob2JqZWN0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZE9iamVjdE5hbWVFcnJvcihgSW52YWxpZCBvYmplY3QgbmFtZTogJHtvYmplY3ROYW1lfWApXG4gICAgfVxuICAgIHJldHVybiB0aGlzLmdldFBhcnRpYWxPYmplY3QoYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgMCwgMCwgZ2V0T3B0cylcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBpcyBjYWxsZWQgd2l0aCByZWFkYWJsZSBzdHJlYW0gb2YgdGhlIHBhcnRpYWwgb2JqZWN0IGNvbnRlbnQuXG4gICAqIEBwYXJhbSBidWNrZXROYW1lXG4gICAqIEBwYXJhbSBvYmplY3ROYW1lXG4gICAqIEBwYXJhbSBvZmZzZXRcbiAgICogQHBhcmFtIGxlbmd0aCAtIGxlbmd0aCBvZiB0aGUgb2JqZWN0IHRoYXQgd2lsbCBiZSByZWFkIGluIHRoZSBzdHJlYW0gKG9wdGlvbmFsLCBpZiBub3Qgc3BlY2lmaWVkIHdlIHJlYWQgdGhlIHJlc3Qgb2YgdGhlIGZpbGUgZnJvbSB0aGUgb2Zmc2V0KVxuICAgKiBAcGFyYW0gZ2V0T3B0c1xuICAgKi9cbiAgYXN5bmMgZ2V0UGFydGlhbE9iamVjdChcbiAgICBidWNrZXROYW1lOiBzdHJpbmcsXG4gICAgb2JqZWN0TmFtZTogc3RyaW5nLFxuICAgIG9mZnNldDogbnVtYmVyLFxuICAgIGxlbmd0aCA9IDAsXG4gICAgZ2V0T3B0cz86IEdldE9iamVjdE9wdHMsXG4gICk6IFByb21pc2U8c3RyZWFtLlJlYWRhYmxlPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgaWYgKCFpc1ZhbGlkT2JqZWN0TmFtZShvYmplY3ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkT2JqZWN0TmFtZUVycm9yKGBJbnZhbGlkIG9iamVjdCBuYW1lOiAke29iamVjdE5hbWV9YClcbiAgICB9XG4gICAgaWYgKCFpc051bWJlcihvZmZzZXQpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdvZmZzZXQgc2hvdWxkIGJlIG9mIHR5cGUgXCJudW1iZXJcIicpXG4gICAgfVxuICAgIGlmICghaXNOdW1iZXIobGVuZ3RoKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbGVuZ3RoIHNob3VsZCBiZSBvZiB0eXBlIFwibnVtYmVyXCInKVxuICAgIH1cblxuICAgIGxldCByYW5nZSA9ICcnXG4gICAgaWYgKG9mZnNldCB8fCBsZW5ndGgpIHtcbiAgICAgIGlmIChvZmZzZXQpIHtcbiAgICAgICAgcmFuZ2UgPSBgYnl0ZXM9JHsrb2Zmc2V0fS1gXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByYW5nZSA9ICdieXRlcz0wLSdcbiAgICAgICAgb2Zmc2V0ID0gMFxuICAgICAgfVxuICAgICAgaWYgKGxlbmd0aCkge1xuICAgICAgICByYW5nZSArPSBgJHsrbGVuZ3RoICsgb2Zmc2V0IC0gMX1gXG4gICAgICB9XG4gICAgfVxuXG4gICAgbGV0IHF1ZXJ5ID0gJydcbiAgICBsZXQgaGVhZGVyczogUmVxdWVzdEhlYWRlcnMgPSB7XG4gICAgICAuLi4ocmFuZ2UgIT09ICcnICYmIHsgcmFuZ2UgfSksXG4gICAgfVxuXG4gICAgaWYgKGdldE9wdHMpIHtcbiAgICAgIGNvbnN0IHNzZUhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICAgIC4uLihnZXRPcHRzLlNTRUN1c3RvbWVyQWxnb3JpdGhtICYmIHtcbiAgICAgICAgICAnWC1BbXotU2VydmVyLVNpZGUtRW5jcnlwdGlvbi1DdXN0b21lci1BbGdvcml0aG0nOiBnZXRPcHRzLlNTRUN1c3RvbWVyQWxnb3JpdGhtLFxuICAgICAgICB9KSxcbiAgICAgICAgLi4uKGdldE9wdHMuU1NFQ3VzdG9tZXJLZXkgJiYgeyAnWC1BbXotU2VydmVyLVNpZGUtRW5jcnlwdGlvbi1DdXN0b21lci1LZXknOiBnZXRPcHRzLlNTRUN1c3RvbWVyS2V5IH0pLFxuICAgICAgICAuLi4oZ2V0T3B0cy5TU0VDdXN0b21lcktleU1ENSAmJiB7XG4gICAgICAgICAgJ1gtQW16LVNlcnZlci1TaWRlLUVuY3J5cHRpb24tQ3VzdG9tZXItS2V5LU1ENSc6IGdldE9wdHMuU1NFQ3VzdG9tZXJLZXlNRDUsXG4gICAgICAgIH0pLFxuICAgICAgfVxuICAgICAgcXVlcnkgPSBxcy5zdHJpbmdpZnkoZ2V0T3B0cylcbiAgICAgIGhlYWRlcnMgPSB7XG4gICAgICAgIC4uLnByZXBlbmRYQU1aTWV0YShzc2VIZWFkZXJzKSxcbiAgICAgICAgLi4uaGVhZGVycyxcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBleHBlY3RlZFN0YXR1c0NvZGVzID0gWzIwMF1cbiAgICBpZiAocmFuZ2UpIHtcbiAgICAgIGV4cGVjdGVkU3RhdHVzQ29kZXMucHVzaCgyMDYpXG4gICAgfVxuICAgIGNvbnN0IG1ldGhvZCA9ICdHRVQnXG5cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kLCBidWNrZXROYW1lLCBvYmplY3ROYW1lLCBoZWFkZXJzLCBxdWVyeSB9LCAnJywgZXhwZWN0ZWRTdGF0dXNDb2RlcylcbiAgfVxuXG4gIC8qKlxuICAgKiBkb3dubG9hZCBvYmplY3QgY29udGVudCB0byBhIGZpbGUuXG4gICAqIFRoaXMgbWV0aG9kIHdpbGwgY3JlYXRlIGEgdGVtcCBmaWxlIG5hbWVkIGAke2ZpbGVuYW1lfS4ke2Jhc2U2NChldGFnKX0ucGFydC5taW5pb2Agd2hlbiBkb3dubG9hZGluZy5cbiAgICpcbiAgICogQHBhcmFtIGJ1Y2tldE5hbWUgLSBuYW1lIG9mIHRoZSBidWNrZXRcbiAgICogQHBhcmFtIG9iamVjdE5hbWUgLSBuYW1lIG9mIHRoZSBvYmplY3RcbiAgICogQHBhcmFtIGZpbGVQYXRoIC0gcGF0aCB0byB3aGljaCB0aGUgb2JqZWN0IGRhdGEgd2lsbCBiZSB3cml0dGVuIHRvXG4gICAqIEBwYXJhbSBnZXRPcHRzIC0gT3B0aW9uYWwgb2JqZWN0IGdldCBvcHRpb25cbiAgICovXG4gIGFzeW5jIGZHZXRPYmplY3QoYnVja2V0TmFtZTogc3RyaW5nLCBvYmplY3ROYW1lOiBzdHJpbmcsIGZpbGVQYXRoOiBzdHJpbmcsIGdldE9wdHM/OiBHZXRPYmplY3RPcHRzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gSW5wdXQgdmFsaWRhdGlvbi5cbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoIWlzU3RyaW5nKGZpbGVQYXRoKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZmlsZVBhdGggc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuXG4gICAgY29uc3QgZG93bmxvYWRUb1RtcEZpbGUgPSBhc3luYyAoKTogUHJvbWlzZTxzdHJpbmc+ID0+IHtcbiAgICAgIGxldCBwYXJ0RmlsZVN0cmVhbTogc3RyZWFtLldyaXRhYmxlXG4gICAgICBjb25zdCBvYmpTdGF0ID0gYXdhaXQgdGhpcy5zdGF0T2JqZWN0KGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIGdldE9wdHMpXG4gICAgICBjb25zdCBlbmNvZGVkRXRhZyA9IEJ1ZmZlci5mcm9tKG9ialN0YXQuZXRhZykudG9TdHJpbmcoJ2Jhc2U2NCcpXG4gICAgICBjb25zdCBwYXJ0RmlsZSA9IGAke2ZpbGVQYXRofS4ke2VuY29kZWRFdGFnfS5wYXJ0Lm1pbmlvYFxuXG4gICAgICBhd2FpdCBmc3AubWtkaXIocGF0aC5kaXJuYW1lKGZpbGVQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSlcblxuICAgICAgbGV0IG9mZnNldCA9IDBcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHN0YXRzID0gYXdhaXQgZnNwLnN0YXQocGFydEZpbGUpXG4gICAgICAgIGlmIChvYmpTdGF0LnNpemUgPT09IHN0YXRzLnNpemUpIHtcbiAgICAgICAgICByZXR1cm4gcGFydEZpbGVcbiAgICAgICAgfVxuICAgICAgICBvZmZzZXQgPSBzdGF0cy5zaXplXG4gICAgICAgIHBhcnRGaWxlU3RyZWFtID0gZnMuY3JlYXRlV3JpdGVTdHJlYW0ocGFydEZpbGUsIHsgZmxhZ3M6ICdhJyB9KVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIEVycm9yICYmIChlIGFzIHVua25vd24gYXMgeyBjb2RlOiBzdHJpbmcgfSkuY29kZSA9PT0gJ0VOT0VOVCcpIHtcbiAgICAgICAgICAvLyBmaWxlIG5vdCBleGlzdFxuICAgICAgICAgIHBhcnRGaWxlU3RyZWFtID0gZnMuY3JlYXRlV3JpdGVTdHJlYW0ocGFydEZpbGUsIHsgZmxhZ3M6ICd3JyB9KVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIG90aGVyIGVycm9yLCBtYXliZSBhY2Nlc3MgZGVueVxuICAgICAgICAgIHRocm93IGVcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBkb3dubG9hZFN0cmVhbSA9IGF3YWl0IHRoaXMuZ2V0UGFydGlhbE9iamVjdChidWNrZXROYW1lLCBvYmplY3ROYW1lLCBvZmZzZXQsIDAsIGdldE9wdHMpXG5cbiAgICAgIGF3YWl0IHN0cmVhbVByb21pc2UucGlwZWxpbmUoZG93bmxvYWRTdHJlYW0sIHBhcnRGaWxlU3RyZWFtKVxuICAgICAgY29uc3Qgc3RhdHMgPSBhd2FpdCBmc3Auc3RhdChwYXJ0RmlsZSlcbiAgICAgIGlmIChzdGF0cy5zaXplID09PSBvYmpTdGF0LnNpemUpIHtcbiAgICAgICAgcmV0dXJuIHBhcnRGaWxlXG4gICAgICB9XG5cbiAgICAgIHRocm93IG5ldyBFcnJvcignU2l6ZSBtaXNtYXRjaCBiZXR3ZWVuIGRvd25sb2FkZWQgZmlsZSBhbmQgdGhlIG9iamVjdCcpXG4gICAgfVxuXG4gICAgY29uc3QgcGFydEZpbGUgPSBhd2FpdCBkb3dubG9hZFRvVG1wRmlsZSgpXG4gICAgYXdhaXQgZnNwLnJlbmFtZShwYXJ0RmlsZSwgZmlsZVBhdGgpXG4gIH1cblxuICAvKipcbiAgICogU3RhdCBpbmZvcm1hdGlvbiBvZiB0aGUgb2JqZWN0LlxuICAgKi9cbiAgYXN5bmMgc3RhdE9iamVjdChidWNrZXROYW1lOiBzdHJpbmcsIG9iamVjdE5hbWU6IHN0cmluZywgc3RhdE9wdHM/OiBTdGF0T2JqZWN0T3B0cyk6IFByb21pc2U8QnVja2V0SXRlbVN0YXQ+IHtcbiAgICBjb25zdCBzdGF0T3B0RGVmID0gc3RhdE9wdHMgfHwge31cbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cblxuICAgIGlmICghaXNPYmplY3Qoc3RhdE9wdERlZikpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ3N0YXRPcHRzIHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICAgIH1cblxuICAgIGNvbnN0IHF1ZXJ5ID0gcXMuc3RyaW5naWZ5KHN0YXRPcHREZWYpXG4gICAgY29uc3QgbWV0aG9kID0gJ0hFQUQnXG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jT21pdCh7IG1ldGhvZCwgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgcXVlcnkgfSlcblxuICAgIHJldHVybiB7XG4gICAgICBzaXplOiBwYXJzZUludChyZXMuaGVhZGVyc1snY29udGVudC1sZW5ndGgnXSBhcyBzdHJpbmcpLFxuICAgICAgbWV0YURhdGE6IGV4dHJhY3RNZXRhZGF0YShyZXMuaGVhZGVycyBhcyBSZXNwb25zZUhlYWRlciksXG4gICAgICBsYXN0TW9kaWZpZWQ6IG5ldyBEYXRlKHJlcy5oZWFkZXJzWydsYXN0LW1vZGlmaWVkJ10gYXMgc3RyaW5nKSxcbiAgICAgIHZlcnNpb25JZDogZ2V0VmVyc2lvbklkKHJlcy5oZWFkZXJzIGFzIFJlc3BvbnNlSGVhZGVyKSxcbiAgICAgIGV0YWc6IHNhbml0aXplRVRhZyhyZXMuaGVhZGVycy5ldGFnKSxcbiAgICB9XG4gIH1cblxuICBhc3luYyByZW1vdmVPYmplY3QoYnVja2V0TmFtZTogc3RyaW5nLCBvYmplY3ROYW1lOiBzdHJpbmcsIHJlbW92ZU9wdHM/OiBSZW1vdmVPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKGBJbnZhbGlkIGJ1Y2tldCBuYW1lOiAke2J1Y2tldE5hbWV9YClcbiAgICB9XG4gICAgaWYgKCFpc1ZhbGlkT2JqZWN0TmFtZShvYmplY3ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkT2JqZWN0TmFtZUVycm9yKGBJbnZhbGlkIG9iamVjdCBuYW1lOiAke29iamVjdE5hbWV9YClcbiAgICB9XG5cbiAgICBpZiAocmVtb3ZlT3B0cyAmJiAhaXNPYmplY3QocmVtb3ZlT3B0cykpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ3JlbW92ZU9wdHMgc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gICAgfVxuXG4gICAgY29uc3QgbWV0aG9kID0gJ0RFTEVURSdcblxuICAgIGNvbnN0IGhlYWRlcnM6IFJlcXVlc3RIZWFkZXJzID0ge31cbiAgICBpZiAocmVtb3ZlT3B0cz8uZ292ZXJuYW5jZUJ5cGFzcykge1xuICAgICAgaGVhZGVyc1snWC1BbXotQnlwYXNzLUdvdmVybmFuY2UtUmV0ZW50aW9uJ10gPSB0cnVlXG4gICAgfVxuICAgIGlmIChyZW1vdmVPcHRzPy5mb3JjZURlbGV0ZSkge1xuICAgICAgaGVhZGVyc1sneC1taW5pby1mb3JjZS1kZWxldGUnXSA9IHRydWVcbiAgICB9XG5cbiAgICBjb25zdCBxdWVyeVBhcmFtczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9XG4gICAgaWYgKHJlbW92ZU9wdHM/LnZlcnNpb25JZCkge1xuICAgICAgcXVlcnlQYXJhbXMudmVyc2lvbklkID0gYCR7cmVtb3ZlT3B0cy52ZXJzaW9uSWR9YFxuICAgIH1cbiAgICBjb25zdCBxdWVyeSA9IHFzLnN0cmluZ2lmeShxdWVyeVBhcmFtcylcblxuICAgIGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luY09taXQoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIGhlYWRlcnMsIHF1ZXJ5IH0sICcnLCBbMjAwLCAyMDRdKVxuICB9XG5cbiAgLy8gQ2FsbHMgaW1wbGVtZW50ZWQgYmVsb3cgYXJlIHJlbGF0ZWQgdG8gbXVsdGlwYXJ0LlxuXG4gIGxpc3RJbmNvbXBsZXRlVXBsb2FkcyhcbiAgICBidWNrZXQ6IHN0cmluZyxcbiAgICBwcmVmaXg6IHN0cmluZyxcbiAgICByZWN1cnNpdmU6IGJvb2xlYW4sXG4gICk6IEJ1Y2tldFN0cmVhbTxJbmNvbXBsZXRlVXBsb2FkZWRCdWNrZXRJdGVtPiB7XG4gICAgaWYgKHByZWZpeCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcmVmaXggPSAnJ1xuICAgIH1cbiAgICBpZiAocmVjdXJzaXZlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJlY3Vyc2l2ZSA9IGZhbHNlXG4gICAgfVxuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0KSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0KVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRQcmVmaXgocHJlZml4KSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkUHJlZml4RXJyb3IoYEludmFsaWQgcHJlZml4IDogJHtwcmVmaXh9YClcbiAgICB9XG4gICAgaWYgKCFpc0Jvb2xlYW4ocmVjdXJzaXZlKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncmVjdXJzaXZlIHNob3VsZCBiZSBvZiB0eXBlIFwiYm9vbGVhblwiJylcbiAgICB9XG4gICAgY29uc3QgZGVsaW1pdGVyID0gcmVjdXJzaXZlID8gJycgOiAnLydcbiAgICBsZXQga2V5TWFya2VyID0gJydcbiAgICBsZXQgdXBsb2FkSWRNYXJrZXIgPSAnJ1xuICAgIGNvbnN0IHVwbG9hZHM6IHVua25vd25bXSA9IFtdXG4gICAgbGV0IGVuZGVkID0gZmFsc2VcblxuICAgIC8vIFRPRE86IHJlZmFjdG9yIHRoaXMgd2l0aCBhc3luYy9hd2FpdCBhbmQgYHN0cmVhbS5SZWFkYWJsZS5mcm9tYFxuICAgIGNvbnN0IHJlYWRTdHJlYW0gPSBuZXcgc3RyZWFtLlJlYWRhYmxlKHsgb2JqZWN0TW9kZTogdHJ1ZSB9KVxuICAgIHJlYWRTdHJlYW0uX3JlYWQgPSAoKSA9PiB7XG4gICAgICAvLyBwdXNoIG9uZSB1cGxvYWQgaW5mbyBwZXIgX3JlYWQoKVxuICAgICAgaWYgKHVwbG9hZHMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiByZWFkU3RyZWFtLnB1c2godXBsb2Fkcy5zaGlmdCgpKVxuICAgICAgfVxuICAgICAgaWYgKGVuZGVkKSB7XG4gICAgICAgIHJldHVybiByZWFkU3RyZWFtLnB1c2gobnVsbClcbiAgICAgIH1cbiAgICAgIHRoaXMubGlzdEluY29tcGxldGVVcGxvYWRzUXVlcnkoYnVja2V0LCBwcmVmaXgsIGtleU1hcmtlciwgdXBsb2FkSWRNYXJrZXIsIGRlbGltaXRlcikudGhlbihcbiAgICAgICAgKHJlc3VsdCkgPT4ge1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXRzLWNvbW1lbnRcbiAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgcmVzdWx0LnByZWZpeGVzLmZvckVhY2goKHByZWZpeCkgPT4gdXBsb2Fkcy5wdXNoKHByZWZpeCkpXG4gICAgICAgICAgYXN5bmMuZWFjaFNlcmllcyhcbiAgICAgICAgICAgIHJlc3VsdC51cGxvYWRzLFxuICAgICAgICAgICAgKHVwbG9hZCwgY2IpID0+IHtcbiAgICAgICAgICAgICAgLy8gZm9yIGVhY2ggaW5jb21wbGV0ZSB1cGxvYWQgYWRkIHRoZSBzaXplcyBvZiBpdHMgdXBsb2FkZWQgcGFydHNcbiAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHMtY29tbWVudFxuICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICAgIHRoaXMubGlzdFBhcnRzKGJ1Y2tldCwgdXBsb2FkLmtleSwgdXBsb2FkLnVwbG9hZElkKS50aGVuKFxuICAgICAgICAgICAgICAgIChwYXJ0czogUGFydFtdKSA9PiB7XG4gICAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10cy1jb21tZW50XG4gICAgICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICAgICAgICB1cGxvYWQuc2l6ZSA9IHBhcnRzLnJlZHVjZSgoYWNjLCBpdGVtKSA9PiBhY2MgKyBpdGVtLnNpemUsIDApXG4gICAgICAgICAgICAgICAgICB1cGxvYWRzLnB1c2godXBsb2FkKVxuICAgICAgICAgICAgICAgICAgY2IoKVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgKGVycjogRXJyb3IpID0+IGNiKGVyciksXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZWFkU3RyZWFtLmVtaXQoJ2Vycm9yJywgZXJyKVxuICAgICAgICAgICAgICAgIHJldHVyblxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChyZXN1bHQuaXNUcnVuY2F0ZWQpIHtcbiAgICAgICAgICAgICAgICBrZXlNYXJrZXIgPSByZXN1bHQubmV4dEtleU1hcmtlclxuICAgICAgICAgICAgICAgIHVwbG9hZElkTWFya2VyID0gcmVzdWx0Lm5leHRVcGxvYWRJZE1hcmtlclxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVuZGVkID0gdHJ1ZVxuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHMtY29tbWVudFxuICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICAgIHJlYWRTdHJlYW0uX3JlYWQoKVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICApXG4gICAgICAgIH0sXG4gICAgICAgIChlKSA9PiB7XG4gICAgICAgICAgcmVhZFN0cmVhbS5lbWl0KCdlcnJvcicsIGUpXG4gICAgICAgIH0sXG4gICAgICApXG4gICAgfVxuICAgIHJldHVybiByZWFkU3RyZWFtXG4gIH1cblxuICAvKipcbiAgICogQ2FsbGVkIGJ5IGxpc3RJbmNvbXBsZXRlVXBsb2FkcyB0byBmZXRjaCBhIGJhdGNoIG9mIGluY29tcGxldGUgdXBsb2Fkcy5cbiAgICovXG4gIGFzeW5jIGxpc3RJbmNvbXBsZXRlVXBsb2Fkc1F1ZXJ5KFxuICAgIGJ1Y2tldE5hbWU6IHN0cmluZyxcbiAgICBwcmVmaXg6IHN0cmluZyxcbiAgICBrZXlNYXJrZXI6IHN0cmluZyxcbiAgICB1cGxvYWRJZE1hcmtlcjogc3RyaW5nLFxuICAgIGRlbGltaXRlcjogc3RyaW5nLFxuICApOiBQcm9taXNlPExpc3RNdWx0aXBhcnRSZXN1bHQ+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzU3RyaW5nKHByZWZpeCkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ByZWZpeCBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyhrZXlNYXJrZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdrZXlNYXJrZXIgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIGlmICghaXNTdHJpbmcodXBsb2FkSWRNYXJrZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd1cGxvYWRJZE1hcmtlciBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyhkZWxpbWl0ZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkZWxpbWl0ZXIgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIGNvbnN0IHF1ZXJpZXMgPSBbXVxuICAgIHF1ZXJpZXMucHVzaChgcHJlZml4PSR7dXJpRXNjYXBlKHByZWZpeCl9YClcbiAgICBxdWVyaWVzLnB1c2goYGRlbGltaXRlcj0ke3VyaUVzY2FwZShkZWxpbWl0ZXIpfWApXG5cbiAgICBpZiAoa2V5TWFya2VyKSB7XG4gICAgICBxdWVyaWVzLnB1c2goYGtleS1tYXJrZXI9JHt1cmlFc2NhcGUoa2V5TWFya2VyKX1gKVxuICAgIH1cbiAgICBpZiAodXBsb2FkSWRNYXJrZXIpIHtcbiAgICAgIHF1ZXJpZXMucHVzaChgdXBsb2FkLWlkLW1hcmtlcj0ke3VwbG9hZElkTWFya2VyfWApXG4gICAgfVxuXG4gICAgY29uc3QgbWF4VXBsb2FkcyA9IDEwMDBcbiAgICBxdWVyaWVzLnB1c2goYG1heC11cGxvYWRzPSR7bWF4VXBsb2Fkc31gKVxuICAgIHF1ZXJpZXMuc29ydCgpXG4gICAgcXVlcmllcy51bnNoaWZ0KCd1cGxvYWRzJylcbiAgICBsZXQgcXVlcnkgPSAnJ1xuICAgIGlmIChxdWVyaWVzLmxlbmd0aCA+IDApIHtcbiAgICAgIHF1ZXJ5ID0gYCR7cXVlcmllcy5qb2luKCcmJyl9YFxuICAgIH1cbiAgICBjb25zdCBtZXRob2QgPSAnR0VUJ1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfSlcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVhZEFzU3RyaW5nKHJlcylcbiAgICByZXR1cm4geG1sUGFyc2Vycy5wYXJzZUxpc3RNdWx0aXBhcnQoYm9keSlcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWF0ZSBhIG5ldyBtdWx0aXBhcnQgdXBsb2FkLlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIGFzeW5jIGluaXRpYXRlTmV3TXVsdGlwYXJ0VXBsb2FkKGJ1Y2tldE5hbWU6IHN0cmluZywgb2JqZWN0TmFtZTogc3RyaW5nLCBoZWFkZXJzOiBSZXF1ZXN0SGVhZGVycyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgaWYgKCFpc1ZhbGlkT2JqZWN0TmFtZShvYmplY3ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkT2JqZWN0TmFtZUVycm9yKGBJbnZhbGlkIG9iamVjdCBuYW1lOiAke29iamVjdE5hbWV9YClcbiAgICB9XG4gICAgaWYgKCFpc09iamVjdChoZWFkZXJzKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkT2JqZWN0TmFtZUVycm9yKCdjb250ZW50VHlwZSBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgICB9XG4gICAgY29uc3QgbWV0aG9kID0gJ1BPU1QnXG4gICAgY29uc3QgcXVlcnkgPSAndXBsb2FkcydcbiAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmMoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIHF1ZXJ5LCBoZWFkZXJzIH0pXG4gICAgY29uc3QgYm9keSA9IGF3YWl0IHJlYWRBc0J1ZmZlcihyZXMpXG4gICAgcmV0dXJuIHBhcnNlSW5pdGlhdGVNdWx0aXBhcnQoYm9keS50b1N0cmluZygpKVxuICB9XG5cbiAgLyoqXG4gICAqIEludGVybmFsIE1ldGhvZCB0byBhYm9ydCBhIG11bHRpcGFydCB1cGxvYWQgcmVxdWVzdCBpbiBjYXNlIG9mIGFueSBlcnJvcnMuXG4gICAqXG4gICAqIEBwYXJhbSBidWNrZXROYW1lIC0gQnVja2V0IE5hbWVcbiAgICogQHBhcmFtIG9iamVjdE5hbWUgLSBPYmplY3QgTmFtZVxuICAgKiBAcGFyYW0gdXBsb2FkSWQgLSBpZCBvZiBhIG11bHRpcGFydCB1cGxvYWQgdG8gY2FuY2VsIGR1cmluZyBjb21wb3NlIG9iamVjdCBzZXF1ZW5jZS5cbiAgICovXG4gIGFzeW5jIGFib3J0TXVsdGlwYXJ0VXBsb2FkKGJ1Y2tldE5hbWU6IHN0cmluZywgb2JqZWN0TmFtZTogc3RyaW5nLCB1cGxvYWRJZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgbWV0aG9kID0gJ0RFTEVURSdcbiAgICBjb25zdCBxdWVyeSA9IGB1cGxvYWRJZD0ke3VwbG9hZElkfWBcblxuICAgIGNvbnN0IHJlcXVlc3RPcHRpb25zID0geyBtZXRob2QsIGJ1Y2tldE5hbWUsIG9iamVjdE5hbWU6IG9iamVjdE5hbWUsIHF1ZXJ5IH1cbiAgICBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmNPbWl0KHJlcXVlc3RPcHRpb25zLCAnJywgWzIwNF0pXG4gIH1cblxuICBhc3luYyBmaW5kVXBsb2FkSWQoYnVja2V0TmFtZTogc3RyaW5nLCBvYmplY3ROYW1lOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNWYWxpZE9iamVjdE5hbWUob2JqZWN0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZE9iamVjdE5hbWVFcnJvcihgSW52YWxpZCBvYmplY3QgbmFtZTogJHtvYmplY3ROYW1lfWApXG4gICAgfVxuXG4gICAgbGV0IGxhdGVzdFVwbG9hZDogTGlzdE11bHRpcGFydFJlc3VsdFsndXBsb2FkcyddW251bWJlcl0gfCB1bmRlZmluZWRcbiAgICBsZXQga2V5TWFya2VyID0gJydcbiAgICBsZXQgdXBsb2FkSWRNYXJrZXIgPSAnJ1xuICAgIGZvciAoOzspIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMubGlzdEluY29tcGxldGVVcGxvYWRzUXVlcnkoYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwga2V5TWFya2VyLCB1cGxvYWRJZE1hcmtlciwgJycpXG4gICAgICBmb3IgKGNvbnN0IHVwbG9hZCBvZiByZXN1bHQudXBsb2Fkcykge1xuICAgICAgICBpZiAodXBsb2FkLmtleSA9PT0gb2JqZWN0TmFtZSkge1xuICAgICAgICAgIGlmICghbGF0ZXN0VXBsb2FkIHx8IHVwbG9hZC5pbml0aWF0ZWQuZ2V0VGltZSgpID4gbGF0ZXN0VXBsb2FkLmluaXRpYXRlZC5nZXRUaW1lKCkpIHtcbiAgICAgICAgICAgIGxhdGVzdFVwbG9hZCA9IHVwbG9hZFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHJlc3VsdC5pc1RydW5jYXRlZCkge1xuICAgICAgICBrZXlNYXJrZXIgPSByZXN1bHQubmV4dEtleU1hcmtlclxuICAgICAgICB1cGxvYWRJZE1hcmtlciA9IHJlc3VsdC5uZXh0VXBsb2FkSWRNYXJrZXJcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgYnJlYWtcbiAgICB9XG4gICAgcmV0dXJuIGxhdGVzdFVwbG9hZD8udXBsb2FkSWRcbiAgfVxuXG4gIC8qKlxuICAgKiB0aGlzIGNhbGwgd2lsbCBhZ2dyZWdhdGUgdGhlIHBhcnRzIG9uIHRoZSBzZXJ2ZXIgaW50byBhIHNpbmdsZSBvYmplY3QuXG4gICAqL1xuICBhc3luYyBjb21wbGV0ZU11bHRpcGFydFVwbG9hZChcbiAgICBidWNrZXROYW1lOiBzdHJpbmcsXG4gICAgb2JqZWN0TmFtZTogc3RyaW5nLFxuICAgIHVwbG9hZElkOiBzdHJpbmcsXG4gICAgZXRhZ3M6IHtcbiAgICAgIHBhcnQ6IG51bWJlclxuICAgICAgZXRhZz86IHN0cmluZ1xuICAgIH1bXSxcbiAgKTogUHJvbWlzZTx7IGV0YWc6IHN0cmluZzsgdmVyc2lvbklkOiBzdHJpbmcgfCBudWxsIH0+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoIWlzU3RyaW5nKHVwbG9hZElkKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndXBsb2FkSWQgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIGlmICghaXNPYmplY3QoZXRhZ3MpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdldGFncyBzaG91bGQgYmUgb2YgdHlwZSBcIkFycmF5XCInKVxuICAgIH1cblxuICAgIGlmICghdXBsb2FkSWQpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ3VwbG9hZElkIGNhbm5vdCBiZSBlbXB0eScpXG4gICAgfVxuXG4gICAgY29uc3QgbWV0aG9kID0gJ1BPU1QnXG4gICAgY29uc3QgcXVlcnkgPSBgdXBsb2FkSWQ9JHt1cmlFc2NhcGUodXBsb2FkSWQpfWBcblxuICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgeG1sMmpzLkJ1aWxkZXIoKVxuICAgIGNvbnN0IHBheWxvYWQgPSBidWlsZGVyLmJ1aWxkT2JqZWN0KHtcbiAgICAgIENvbXBsZXRlTXVsdGlwYXJ0VXBsb2FkOiB7XG4gICAgICAgICQ6IHtcbiAgICAgICAgICB4bWxuczogJ2h0dHA6Ly9zMy5hbWF6b25hd3MuY29tL2RvYy8yMDA2LTAzLTAxLycsXG4gICAgICAgIH0sXG4gICAgICAgIFBhcnQ6IGV0YWdzLm1hcCgoZXRhZykgPT4ge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBQYXJ0TnVtYmVyOiBldGFnLnBhcnQsXG4gICAgICAgICAgICBFVGFnOiBldGFnLmV0YWcsXG4gICAgICAgICAgfVxuICAgICAgICB9KSxcbiAgICAgIH0sXG4gICAgfSlcblxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZCwgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgcXVlcnkgfSwgcGF5bG9hZClcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVhZEFzQnVmZmVyKHJlcylcbiAgICBjb25zdCByZXN1bHQgPSBwYXJzZUNvbXBsZXRlTXVsdGlwYXJ0KGJvZHkudG9TdHJpbmcoKSlcbiAgICBpZiAoIXJlc3VsdCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdCVUc6IGZhaWxlZCB0byBwYXJzZSBzZXJ2ZXIgcmVzcG9uc2UnKVxuICAgIH1cblxuICAgIGlmIChyZXN1bHQuZXJyQ29kZSkge1xuICAgICAgLy8gTXVsdGlwYXJ0IENvbXBsZXRlIEFQSSByZXR1cm5zIGFuIGVycm9yIFhNTCBhZnRlciBhIDIwMCBodHRwIHN0YXR1c1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5TM0Vycm9yKHJlc3VsdC5lcnJNZXNzYWdlKVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10cy1jb21tZW50XG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICBldGFnOiByZXN1bHQuZXRhZyBhcyBzdHJpbmcsXG4gICAgICB2ZXJzaW9uSWQ6IGdldFZlcnNpb25JZChyZXMuaGVhZGVycyBhcyBSZXNwb25zZUhlYWRlciksXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCBwYXJ0LWluZm8gb2YgYWxsIHBhcnRzIG9mIGFuIGluY29tcGxldGUgdXBsb2FkIHNwZWNpZmllZCBieSB1cGxvYWRJZC5cbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBsaXN0UGFydHMoYnVja2V0TmFtZTogc3RyaW5nLCBvYmplY3ROYW1lOiBzdHJpbmcsIHVwbG9hZElkOiBzdHJpbmcpOiBQcm9taXNlPFVwbG9hZGVkUGFydFtdPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgaWYgKCFpc1ZhbGlkT2JqZWN0TmFtZShvYmplY3ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkT2JqZWN0TmFtZUVycm9yKGBJbnZhbGlkIG9iamVjdCBuYW1lOiAke29iamVjdE5hbWV9YClcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyh1cGxvYWRJZCkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3VwbG9hZElkIHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICAgIH1cbiAgICBpZiAoIXVwbG9hZElkKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCd1cGxvYWRJZCBjYW5ub3QgYmUgZW1wdHknKVxuICAgIH1cblxuICAgIGNvbnN0IHBhcnRzOiBVcGxvYWRlZFBhcnRbXSA9IFtdXG4gICAgbGV0IG1hcmtlciA9IDBcbiAgICBsZXQgcmVzdWx0XG4gICAgZG8ge1xuICAgICAgcmVzdWx0ID0gYXdhaXQgdGhpcy5saXN0UGFydHNRdWVyeShidWNrZXROYW1lLCBvYmplY3ROYW1lLCB1cGxvYWRJZCwgbWFya2VyKVxuICAgICAgbWFya2VyID0gcmVzdWx0Lm1hcmtlclxuICAgICAgcGFydHMucHVzaCguLi5yZXN1bHQucGFydHMpXG4gICAgfSB3aGlsZSAocmVzdWx0LmlzVHJ1bmNhdGVkKVxuXG4gICAgcmV0dXJuIHBhcnRzXG4gIH1cblxuICAvKipcbiAgICogQ2FsbGVkIGJ5IGxpc3RQYXJ0cyB0byBmZXRjaCBhIGJhdGNoIG9mIHBhcnQtaW5mb1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBsaXN0UGFydHNRdWVyeShidWNrZXROYW1lOiBzdHJpbmcsIG9iamVjdE5hbWU6IHN0cmluZywgdXBsb2FkSWQ6IHN0cmluZywgbWFya2VyOiBudW1iZXIpIHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoIWlzU3RyaW5nKHVwbG9hZElkKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndXBsb2FkSWQgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIGlmICghaXNOdW1iZXIobWFya2VyKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbWFya2VyIHNob3VsZCBiZSBvZiB0eXBlIFwibnVtYmVyXCInKVxuICAgIH1cbiAgICBpZiAoIXVwbG9hZElkKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCd1cGxvYWRJZCBjYW5ub3QgYmUgZW1wdHknKVxuICAgIH1cblxuICAgIGxldCBxdWVyeSA9IGB1cGxvYWRJZD0ke3VyaUVzY2FwZSh1cGxvYWRJZCl9YFxuICAgIGlmIChtYXJrZXIpIHtcbiAgICAgIHF1ZXJ5ICs9IGAmcGFydC1udW1iZXItbWFya2VyPSR7bWFya2VyfWBcbiAgICB9XG5cbiAgICBjb25zdCBtZXRob2QgPSAnR0VUJ1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZCwgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgcXVlcnkgfSlcbiAgICByZXR1cm4geG1sUGFyc2Vycy5wYXJzZUxpc3RQYXJ0cyhhd2FpdCByZWFkQXNTdHJpbmcocmVzKSlcbiAgfVxuXG4gIGFzeW5jIGxpc3RCdWNrZXRzKCk6IFByb21pc2U8QnVja2V0SXRlbUZyb21MaXN0W10+IHtcbiAgICBjb25zdCBtZXRob2QgPSAnR0VUJ1xuICAgIGNvbnN0IHJlZ2lvbkNvbmYgPSB0aGlzLnJlZ2lvbiB8fCBERUZBVUxUX1JFR0lPTlxuICAgIGNvbnN0IGh0dHBSZXMgPSBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmMoeyBtZXRob2QgfSwgJycsIFsyMDBdLCByZWdpb25Db25mKVxuICAgIGNvbnN0IHhtbFJlc3VsdCA9IGF3YWl0IHJlYWRBc1N0cmluZyhodHRwUmVzKVxuICAgIHJldHVybiB4bWxQYXJzZXJzLnBhcnNlTGlzdEJ1Y2tldCh4bWxSZXN1bHQpXG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIHBhcnQgc2l6ZSBnaXZlbiB0aGUgb2JqZWN0IHNpemUuIFBhcnQgc2l6ZSB3aWxsIGJlIGF0bGVhc3QgdGhpcy5wYXJ0U2l6ZVxuICAgKi9cbiAgY2FsY3VsYXRlUGFydFNpemUoc2l6ZTogbnVtYmVyKSB7XG4gICAgaWYgKCFpc051bWJlcihzaXplKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignc2l6ZSBzaG91bGQgYmUgb2YgdHlwZSBcIm51bWJlclwiJylcbiAgICB9XG4gICAgaWYgKHNpemUgPiB0aGlzLm1heE9iamVjdFNpemUpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYHNpemUgc2hvdWxkIG5vdCBiZSBtb3JlIHRoYW4gJHt0aGlzLm1heE9iamVjdFNpemV9YClcbiAgICB9XG4gICAgaWYgKHRoaXMub3ZlclJpZGVQYXJ0U2l6ZSkge1xuICAgICAgcmV0dXJuIHRoaXMucGFydFNpemVcbiAgICB9XG4gICAgbGV0IHBhcnRTaXplID0gdGhpcy5wYXJ0U2l6ZVxuICAgIGZvciAoOzspIHtcbiAgICAgIC8vIHdoaWxlKHRydWUpIHsuLi59IHRocm93cyBsaW50aW5nIGVycm9yLlxuICAgICAgLy8gSWYgcGFydFNpemUgaXMgYmlnIGVub3VnaCB0byBhY2NvbW9kYXRlIHRoZSBvYmplY3Qgc2l6ZSwgdGhlbiB1c2UgaXQuXG4gICAgICBpZiAocGFydFNpemUgKiAxMDAwMCA+IHNpemUpIHtcbiAgICAgICAgcmV0dXJuIHBhcnRTaXplXG4gICAgICB9XG4gICAgICAvLyBUcnkgcGFydCBzaXplcyBhcyA2NE1CLCA4ME1CLCA5Nk1CIGV0Yy5cbiAgICAgIHBhcnRTaXplICs9IDE2ICogMTAyNCAqIDEwMjRcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVXBsb2FkcyB0aGUgb2JqZWN0IHVzaW5nIGNvbnRlbnRzIGZyb20gYSBmaWxlXG4gICAqL1xuICBhc3luYyBmUHV0T2JqZWN0KGJ1Y2tldE5hbWU6IHN0cmluZywgb2JqZWN0TmFtZTogc3RyaW5nLCBmaWxlUGF0aDogc3RyaW5nLCBtZXRhRGF0YT86IE9iamVjdE1ldGFEYXRhKSB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgaWYgKCFpc1ZhbGlkT2JqZWN0TmFtZShvYmplY3ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkT2JqZWN0TmFtZUVycm9yKGBJbnZhbGlkIG9iamVjdCBuYW1lOiAke29iamVjdE5hbWV9YClcbiAgICB9XG5cbiAgICBpZiAoIWlzU3RyaW5nKGZpbGVQYXRoKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZmlsZVBhdGggc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIGlmIChtZXRhRGF0YSAmJiAhaXNPYmplY3QobWV0YURhdGEpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtZXRhRGF0YSBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgICB9XG5cbiAgICAvLyBJbnNlcnRzIGNvcnJlY3QgYGNvbnRlbnQtdHlwZWAgYXR0cmlidXRlIGJhc2VkIG9uIG1ldGFEYXRhIGFuZCBmaWxlUGF0aFxuICAgIG1ldGFEYXRhID0gaW5zZXJ0Q29udGVudFR5cGUobWV0YURhdGEgfHwge30sIGZpbGVQYXRoKVxuICAgIGNvbnN0IHN0YXQgPSBhd2FpdCBmc3Auc3RhdChmaWxlUGF0aClcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5wdXRPYmplY3QoYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgZnMuY3JlYXRlUmVhZFN0cmVhbShmaWxlUGF0aCksIHN0YXQuc2l6ZSwgbWV0YURhdGEpXG4gIH1cblxuICAvKipcbiAgICogIFVwbG9hZGluZyBhIHN0cmVhbSwgXCJCdWZmZXJcIiBvciBcInN0cmluZ1wiLlxuICAgKiAgSXQncyByZWNvbW1lbmRlZCB0byBwYXNzIGBzaXplYCBhcmd1bWVudCB3aXRoIHN0cmVhbS5cbiAgICovXG4gIGFzeW5jIHB1dE9iamVjdChcbiAgICBidWNrZXROYW1lOiBzdHJpbmcsXG4gICAgb2JqZWN0TmFtZTogc3RyaW5nLFxuICAgIHN0cmVhbTogc3RyZWFtLlJlYWRhYmxlIHwgQnVmZmVyIHwgc3RyaW5nLFxuICAgIHNpemU/OiBudW1iZXIsXG4gICAgbWV0YURhdGE/OiBJdGVtQnVja2V0TWV0YWRhdGEsXG4gICk6IFByb21pc2U8VXBsb2FkZWRPYmplY3RJbmZvPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKGBJbnZhbGlkIGJ1Y2tldCBuYW1lOiAke2J1Y2tldE5hbWV9YClcbiAgICB9XG4gICAgaWYgKCFpc1ZhbGlkT2JqZWN0TmFtZShvYmplY3ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkT2JqZWN0TmFtZUVycm9yKGBJbnZhbGlkIG9iamVjdCBuYW1lOiAke29iamVjdE5hbWV9YClcbiAgICB9XG5cbiAgICAvLyBXZSdsbCBuZWVkIHRvIHNoaWZ0IGFyZ3VtZW50cyB0byB0aGUgbGVmdCBiZWNhdXNlIG9mIG1ldGFEYXRhXG4gICAgLy8gYW5kIHNpemUgYmVpbmcgb3B0aW9uYWwuXG4gICAgaWYgKGlzT2JqZWN0KHNpemUpKSB7XG4gICAgICBtZXRhRGF0YSA9IHNpemVcbiAgICB9XG4gICAgLy8gRW5zdXJlcyBNZXRhZGF0YSBoYXMgYXBwcm9wcmlhdGUgcHJlZml4IGZvciBBMyBBUElcbiAgICBjb25zdCBoZWFkZXJzID0gcHJlcGVuZFhBTVpNZXRhKG1ldGFEYXRhKVxuICAgIGlmICh0eXBlb2Ygc3RyZWFtID09PSAnc3RyaW5nJyB8fCBzdHJlYW0gaW5zdGFuY2VvZiBCdWZmZXIpIHtcbiAgICAgIC8vIEFkYXB0cyB0aGUgbm9uLXN0cmVhbSBpbnRlcmZhY2UgaW50byBhIHN0cmVhbS5cbiAgICAgIHNpemUgPSBzdHJlYW0ubGVuZ3RoXG4gICAgICBzdHJlYW0gPSByZWFkYWJsZVN0cmVhbShzdHJlYW0pXG4gICAgfSBlbHNlIGlmICghaXNSZWFkYWJsZVN0cmVhbShzdHJlYW0pKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd0aGlyZCBhcmd1bWVudCBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmVhbS5SZWFkYWJsZVwiIG9yIFwiQnVmZmVyXCIgb3IgXCJzdHJpbmdcIicpXG4gICAgfVxuXG4gICAgaWYgKGlzTnVtYmVyKHNpemUpICYmIHNpemUgPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKGBzaXplIGNhbm5vdCBiZSBuZWdhdGl2ZSwgZ2l2ZW4gc2l6ZTogJHtzaXplfWApXG4gICAgfVxuXG4gICAgLy8gR2V0IHRoZSBwYXJ0IHNpemUgYW5kIGZvcndhcmQgdGhhdCB0byB0aGUgQmxvY2tTdHJlYW0uIERlZmF1bHQgdG8gdGhlXG4gICAgLy8gbGFyZ2VzdCBibG9jayBzaXplIHBvc3NpYmxlIGlmIG5lY2Vzc2FyeS5cbiAgICBpZiAoIWlzTnVtYmVyKHNpemUpKSB7XG4gICAgICBzaXplID0gdGhpcy5tYXhPYmplY3RTaXplXG4gICAgfVxuXG4gICAgLy8gR2V0IHRoZSBwYXJ0IHNpemUgYW5kIGZvcndhcmQgdGhhdCB0byB0aGUgQmxvY2tTdHJlYW0uIERlZmF1bHQgdG8gdGhlXG4gICAgLy8gbGFyZ2VzdCBibG9jayBzaXplIHBvc3NpYmxlIGlmIG5lY2Vzc2FyeS5cbiAgICBpZiAoc2l6ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCBzdGF0U2l6ZSA9IGF3YWl0IGdldENvbnRlbnRMZW5ndGgoc3RyZWFtKVxuICAgICAgaWYgKHN0YXRTaXplICE9PSBudWxsKSB7XG4gICAgICAgIHNpemUgPSBzdGF0U2l6ZVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghaXNOdW1iZXIoc2l6ZSkpIHtcbiAgICAgIC8vIEJhY2t3YXJkIGNvbXBhdGliaWxpdHlcbiAgICAgIHNpemUgPSB0aGlzLm1heE9iamVjdFNpemVcbiAgICB9XG4gICAgaWYgKHNpemUgPT09IDApIHtcbiAgICAgIHJldHVybiB0aGlzLnVwbG9hZEJ1ZmZlcihidWNrZXROYW1lLCBvYmplY3ROYW1lLCBoZWFkZXJzLCBCdWZmZXIuZnJvbSgnJykpXG4gICAgfVxuXG4gICAgY29uc3QgcGFydFNpemUgPSB0aGlzLmNhbGN1bGF0ZVBhcnRTaXplKHNpemUpXG4gICAgaWYgKHR5cGVvZiBzdHJlYW0gPT09ICdzdHJpbmcnIHx8IEJ1ZmZlci5pc0J1ZmZlcihzdHJlYW0pIHx8IHNpemUgPD0gcGFydFNpemUpIHtcbiAgICAgIGNvbnN0IGJ1ZiA9IGlzUmVhZGFibGVTdHJlYW0oc3RyZWFtKSA/IGF3YWl0IHJlYWRBc0J1ZmZlcihzdHJlYW0pIDogQnVmZmVyLmZyb20oc3RyZWFtKVxuICAgICAgcmV0dXJuIHRoaXMudXBsb2FkQnVmZmVyKGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIGhlYWRlcnMsIGJ1ZilcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy51cGxvYWRTdHJlYW0oYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgaGVhZGVycywgc3RyZWFtLCBwYXJ0U2l6ZSlcbiAgfVxuXG4gIC8qKlxuICAgKiBtZXRob2QgdG8gdXBsb2FkIGJ1ZmZlciBpbiBvbmUgY2FsbFxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyB1cGxvYWRCdWZmZXIoXG4gICAgYnVja2V0TmFtZTogc3RyaW5nLFxuICAgIG9iamVjdE5hbWU6IHN0cmluZyxcbiAgICBoZWFkZXJzOiBSZXF1ZXN0SGVhZGVycyxcbiAgICBidWY6IEJ1ZmZlcixcbiAgKTogUHJvbWlzZTxVcGxvYWRlZE9iamVjdEluZm8+IHtcbiAgICBjb25zdCB7IG1kNXN1bSwgc2hhMjU2c3VtIH0gPSBoYXNoQmluYXJ5KGJ1ZiwgdGhpcy5lbmFibGVTSEEyNTYpXG4gICAgaGVhZGVyc1snQ29udGVudC1MZW5ndGgnXSA9IGJ1Zi5sZW5ndGhcbiAgICBpZiAoIXRoaXMuZW5hYmxlU0hBMjU2KSB7XG4gICAgICBoZWFkZXJzWydDb250ZW50LU1ENSddID0gbWQ1c3VtXG4gICAgfVxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RTdHJlYW1Bc3luYyhcbiAgICAgIHtcbiAgICAgICAgbWV0aG9kOiAnUFVUJyxcbiAgICAgICAgYnVja2V0TmFtZSxcbiAgICAgICAgb2JqZWN0TmFtZSxcbiAgICAgICAgaGVhZGVycyxcbiAgICAgIH0sXG4gICAgICBidWYsXG4gICAgICBzaGEyNTZzdW0sXG4gICAgICBbMjAwXSxcbiAgICAgICcnLFxuICAgIClcbiAgICBhd2FpdCBkcmFpblJlc3BvbnNlKHJlcylcbiAgICByZXR1cm4ge1xuICAgICAgZXRhZzogc2FuaXRpemVFVGFnKHJlcy5oZWFkZXJzLmV0YWcpLFxuICAgICAgdmVyc2lvbklkOiBnZXRWZXJzaW9uSWQocmVzLmhlYWRlcnMgYXMgUmVzcG9uc2VIZWFkZXIpLFxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiB1cGxvYWQgc3RyZWFtIHdpdGggTXVsdGlwYXJ0VXBsb2FkXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHVwbG9hZFN0cmVhbShcbiAgICBidWNrZXROYW1lOiBzdHJpbmcsXG4gICAgb2JqZWN0TmFtZTogc3RyaW5nLFxuICAgIGhlYWRlcnM6IFJlcXVlc3RIZWFkZXJzLFxuICAgIGJvZHk6IHN0cmVhbS5SZWFkYWJsZSxcbiAgICBwYXJ0U2l6ZTogbnVtYmVyLFxuICApOiBQcm9taXNlPFVwbG9hZGVkT2JqZWN0SW5mbz4ge1xuICAgIC8vIEEgbWFwIG9mIHRoZSBwcmV2aW91c2x5IHVwbG9hZGVkIGNodW5rcywgZm9yIHJlc3VtaW5nIGEgZmlsZSB1cGxvYWQuIFRoaXNcbiAgICAvLyB3aWxsIGJlIG51bGwgaWYgd2UgYXJlbid0IHJlc3VtaW5nIGFuIHVwbG9hZC5cbiAgICBjb25zdCBvbGRQYXJ0czogUmVjb3JkPG51bWJlciwgUGFydD4gPSB7fVxuXG4gICAgLy8gS2VlcCB0cmFjayBvZiB0aGUgZXRhZ3MgZm9yIGFnZ3JlZ2F0aW5nIHRoZSBjaHVua3MgdG9nZXRoZXIgbGF0ZXIuIEVhY2hcbiAgICAvLyBldGFnIHJlcHJlc2VudHMgYSBzaW5nbGUgY2h1bmsgb2YgdGhlIGZpbGUuXG4gICAgY29uc3QgZVRhZ3M6IFBhcnRbXSA9IFtdXG5cbiAgICBjb25zdCBwcmV2aW91c1VwbG9hZElkID0gYXdhaXQgdGhpcy5maW5kVXBsb2FkSWQoYnVja2V0TmFtZSwgb2JqZWN0TmFtZSlcbiAgICBsZXQgdXBsb2FkSWQ6IHN0cmluZ1xuICAgIGlmICghcHJldmlvdXNVcGxvYWRJZCkge1xuICAgICAgdXBsb2FkSWQgPSBhd2FpdCB0aGlzLmluaXRpYXRlTmV3TXVsdGlwYXJ0VXBsb2FkKGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIGhlYWRlcnMpXG4gICAgfSBlbHNlIHtcbiAgICAgIHVwbG9hZElkID0gcHJldmlvdXNVcGxvYWRJZFxuICAgICAgY29uc3Qgb2xkVGFncyA9IGF3YWl0IHRoaXMubGlzdFBhcnRzKGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIHByZXZpb3VzVXBsb2FkSWQpXG4gICAgICBvbGRUYWdzLmZvckVhY2goKGUpID0+IHtcbiAgICAgICAgb2xkUGFydHNbZS5wYXJ0XSA9IGVcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgY29uc3QgY2h1bmtpZXIgPSBuZXcgQmxvY2tTdHJlYW0yKHsgc2l6ZTogcGFydFNpemUsIHplcm9QYWRkaW5nOiBmYWxzZSB9KVxuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIGNvbnN0IFtfLCBvXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgYm9keS5waXBlKGNodW5raWVyKS5vbignZXJyb3InLCByZWplY3QpXG4gICAgICAgIGNodW5raWVyLm9uKCdlbmQnLCByZXNvbHZlKS5vbignZXJyb3InLCByZWplY3QpXG4gICAgICB9KSxcbiAgICAgIChhc3luYyAoKSA9PiB7XG4gICAgICAgIGxldCBwYXJ0TnVtYmVyID0gMVxuXG4gICAgICAgIGZvciBhd2FpdCAoY29uc3QgY2h1bmsgb2YgY2h1bmtpZXIpIHtcbiAgICAgICAgICBjb25zdCBtZDUgPSBjcnlwdG8uY3JlYXRlSGFzaCgnbWQ1JykudXBkYXRlKGNodW5rKS5kaWdlc3QoKVxuXG4gICAgICAgICAgY29uc3Qgb2xkUGFydCA9IG9sZFBhcnRzW3BhcnROdW1iZXJdXG4gICAgICAgICAgaWYgKG9sZFBhcnQpIHtcbiAgICAgICAgICAgIGlmIChvbGRQYXJ0LmV0YWcgPT09IG1kNS50b1N0cmluZygnaGV4JykpIHtcbiAgICAgICAgICAgICAgZVRhZ3MucHVzaCh7IHBhcnQ6IHBhcnROdW1iZXIsIGV0YWc6IG9sZFBhcnQuZXRhZyB9KVxuICAgICAgICAgICAgICBwYXJ0TnVtYmVyKytcbiAgICAgICAgICAgICAgY29udGludWVcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBwYXJ0TnVtYmVyKytcblxuICAgICAgICAgIC8vIG5vdyBzdGFydCB0byB1cGxvYWQgbWlzc2luZyBwYXJ0XG4gICAgICAgICAgY29uc3Qgb3B0aW9uczogUmVxdWVzdE9wdGlvbiA9IHtcbiAgICAgICAgICAgIG1ldGhvZDogJ1BVVCcsXG4gICAgICAgICAgICBxdWVyeTogcXMuc3RyaW5naWZ5KHsgcGFydE51bWJlciwgdXBsb2FkSWQgfSksXG4gICAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAgICdDb250ZW50LUxlbmd0aCc6IGNodW5rLmxlbmd0aCxcbiAgICAgICAgICAgICAgJ0NvbnRlbnQtTUQ1JzogbWQ1LnRvU3RyaW5nKCdiYXNlNjQnKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBidWNrZXROYW1lLFxuICAgICAgICAgICAgb2JqZWN0TmFtZSxcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luY09taXQob3B0aW9ucywgY2h1bmspXG5cbiAgICAgICAgICBsZXQgZXRhZyA9IHJlc3BvbnNlLmhlYWRlcnMuZXRhZ1xuICAgICAgICAgIGlmIChldGFnKSB7XG4gICAgICAgICAgICBldGFnID0gZXRhZy5yZXBsYWNlKC9eXCIvLCAnJykucmVwbGFjZSgvXCIkLywgJycpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGV0YWcgPSAnJ1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGVUYWdzLnB1c2goeyBwYXJ0OiBwYXJ0TnVtYmVyLCBldGFnIH0pXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5jb21wbGV0ZU11bHRpcGFydFVwbG9hZChidWNrZXROYW1lLCBvYmplY3ROYW1lLCB1cGxvYWRJZCwgZVRhZ3MpXG4gICAgICB9KSgpLFxuICAgIF0pXG5cbiAgICByZXR1cm4gb1xuICB9XG5cbiAgYXN5bmMgcmVtb3ZlQnVja2V0UmVwbGljYXRpb24oYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPlxuICByZW1vdmVCdWNrZXRSZXBsaWNhdGlvbihidWNrZXROYW1lOiBzdHJpbmcsIGNhbGxiYWNrOiBOb1Jlc3VsdENhbGxiYWNrKTogdm9pZFxuICBhc3luYyByZW1vdmVCdWNrZXRSZXBsaWNhdGlvbihidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBjb25zdCBtZXRob2QgPSAnREVMRVRFJ1xuICAgIGNvbnN0IHF1ZXJ5ID0gJ3JlcGxpY2F0aW9uJ1xuICAgIGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luY09taXQoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIHF1ZXJ5IH0sICcnLCBbMjAwLCAyMDRdLCAnJylcbiAgfVxuXG4gIHNldEJ1Y2tldFJlcGxpY2F0aW9uKGJ1Y2tldE5hbWU6IHN0cmluZywgcmVwbGljYXRpb25Db25maWc6IFJlcGxpY2F0aW9uQ29uZmlnT3B0cyk6IHZvaWRcbiAgYXN5bmMgc2V0QnVja2V0UmVwbGljYXRpb24oYnVja2V0TmFtZTogc3RyaW5nLCByZXBsaWNhdGlvbkNvbmZpZzogUmVwbGljYXRpb25Db25maWdPcHRzKTogUHJvbWlzZTx2b2lkPlxuICBhc3luYyBzZXRCdWNrZXRSZXBsaWNhdGlvbihidWNrZXROYW1lOiBzdHJpbmcsIHJlcGxpY2F0aW9uQ29uZmlnOiBSZXBsaWNhdGlvbkNvbmZpZ09wdHMpIHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzT2JqZWN0KHJlcGxpY2F0aW9uQ29uZmlnKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcigncmVwbGljYXRpb25Db25maWcgc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChfLmlzRW1wdHkocmVwbGljYXRpb25Db25maWcucm9sZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcignUm9sZSBjYW5ub3QgYmUgZW1wdHknKVxuICAgICAgfSBlbHNlIGlmIChyZXBsaWNhdGlvbkNvbmZpZy5yb2xlICYmICFpc1N0cmluZyhyZXBsaWNhdGlvbkNvbmZpZy5yb2xlKSkge1xuICAgICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCdJbnZhbGlkIHZhbHVlIGZvciByb2xlJywgcmVwbGljYXRpb25Db25maWcucm9sZSlcbiAgICAgIH1cbiAgICAgIGlmIChfLmlzRW1wdHkocmVwbGljYXRpb25Db25maWcucnVsZXMpKSB7XG4gICAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ01pbmltdW0gb25lIHJlcGxpY2F0aW9uIHJ1bGUgbXVzdCBiZSBzcGVjaWZpZWQnKVxuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBtZXRob2QgPSAnUFVUJ1xuICAgIGNvbnN0IHF1ZXJ5ID0gJ3JlcGxpY2F0aW9uJ1xuICAgIGNvbnN0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fVxuXG4gICAgY29uc3QgcmVwbGljYXRpb25QYXJhbXNDb25maWcgPSB7XG4gICAgICBSZXBsaWNhdGlvbkNvbmZpZ3VyYXRpb246IHtcbiAgICAgICAgUm9sZTogcmVwbGljYXRpb25Db25maWcucm9sZSxcbiAgICAgICAgUnVsZTogcmVwbGljYXRpb25Db25maWcucnVsZXMsXG4gICAgICB9LFxuICAgIH1cblxuICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgeG1sMmpzLkJ1aWxkZXIoeyByZW5kZXJPcHRzOiB7IHByZXR0eTogZmFsc2UgfSwgaGVhZGxlc3M6IHRydWUgfSlcbiAgICBjb25zdCBwYXlsb2FkID0gYnVpbGRlci5idWlsZE9iamVjdChyZXBsaWNhdGlvblBhcmFtc0NvbmZpZylcbiAgICBoZWFkZXJzWydDb250ZW50LU1ENSddID0gdG9NZDUocGF5bG9hZClcbiAgICBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmNPbWl0KHsgbWV0aG9kLCBidWNrZXROYW1lLCBxdWVyeSwgaGVhZGVycyB9LCBwYXlsb2FkKVxuICB9XG5cbiAgZ2V0QnVja2V0UmVwbGljYXRpb24oYnVja2V0TmFtZTogc3RyaW5nKTogdm9pZFxuICBhc3luYyBnZXRCdWNrZXRSZXBsaWNhdGlvbihidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPFJlcGxpY2F0aW9uQ29uZmlnPlxuICBhc3luYyBnZXRCdWNrZXRSZXBsaWNhdGlvbihidWNrZXROYW1lOiBzdHJpbmcpIHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBjb25zdCBtZXRob2QgPSAnR0VUJ1xuICAgIGNvbnN0IHF1ZXJ5ID0gJ3JlcGxpY2F0aW9uJ1xuXG4gICAgY29uc3QgaHR0cFJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfSwgJycsIFsyMDAsIDIwNF0pXG4gICAgY29uc3QgeG1sUmVzdWx0ID0gYXdhaXQgcmVhZEFzU3RyaW5nKGh0dHBSZXMpXG4gICAgcmV0dXJuIHhtbFBhcnNlcnMucGFyc2VSZXBsaWNhdGlvbkNvbmZpZyh4bWxSZXN1bHQpXG4gIH1cblxuICBnZXRPYmplY3RMZWdhbEhvbGQoXG4gICAgYnVja2V0TmFtZTogc3RyaW5nLFxuICAgIG9iamVjdE5hbWU6IHN0cmluZyxcbiAgICBnZXRPcHRzPzogR2V0T2JqZWN0TGVnYWxIb2xkT3B0aW9ucyxcbiAgICBjYWxsYmFjaz86IFJlc3VsdENhbGxiYWNrPExFR0FMX0hPTERfU1RBVFVTPixcbiAgKTogUHJvbWlzZTxMRUdBTF9IT0xEX1NUQVRVUz5cbiAgYXN5bmMgZ2V0T2JqZWN0TGVnYWxIb2xkKFxuICAgIGJ1Y2tldE5hbWU6IHN0cmluZyxcbiAgICBvYmplY3ROYW1lOiBzdHJpbmcsXG4gICAgZ2V0T3B0cz86IEdldE9iamVjdExlZ2FsSG9sZE9wdGlvbnMsXG4gICk6IFByb21pc2U8TEVHQUxfSE9MRF9TVEFUVVM+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cblxuICAgIGlmIChnZXRPcHRzKSB7XG4gICAgICBpZiAoIWlzT2JqZWN0KGdldE9wdHMpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2dldE9wdHMgc2hvdWxkIGJlIG9mIHR5cGUgXCJPYmplY3RcIicpXG4gICAgICB9IGVsc2UgaWYgKE9iamVjdC5rZXlzKGdldE9wdHMpLmxlbmd0aCA+IDAgJiYgZ2V0T3B0cy52ZXJzaW9uSWQgJiYgIWlzU3RyaW5nKGdldE9wdHMudmVyc2lvbklkKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2ZXJzaW9uSWQgc2hvdWxkIGJlIG9mIHR5cGUgc3RyaW5nLjonLCBnZXRPcHRzLnZlcnNpb25JZClcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBtZXRob2QgPSAnR0VUJ1xuICAgIGxldCBxdWVyeSA9ICdsZWdhbC1ob2xkJ1xuXG4gICAgaWYgKGdldE9wdHM/LnZlcnNpb25JZCkge1xuICAgICAgcXVlcnkgKz0gYCZ2ZXJzaW9uSWQ9JHtnZXRPcHRzLnZlcnNpb25JZH1gXG4gICAgfVxuXG4gICAgY29uc3QgaHR0cFJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZCwgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgcXVlcnkgfSwgJycsIFsyMDBdKVxuICAgIGNvbnN0IHN0clJlcyA9IGF3YWl0IHJlYWRBc1N0cmluZyhodHRwUmVzKVxuICAgIHJldHVybiBwYXJzZU9iamVjdExlZ2FsSG9sZENvbmZpZyhzdHJSZXMpXG4gIH1cblxuICBzZXRPYmplY3RMZWdhbEhvbGQoYnVja2V0TmFtZTogc3RyaW5nLCBvYmplY3ROYW1lOiBzdHJpbmcsIHNldE9wdHM/OiBQdXRPYmplY3RMZWdhbEhvbGRPcHRpb25zKTogdm9pZFxuICBhc3luYyBzZXRPYmplY3RMZWdhbEhvbGQoXG4gICAgYnVja2V0TmFtZTogc3RyaW5nLFxuICAgIG9iamVjdE5hbWU6IHN0cmluZyxcbiAgICBzZXRPcHRzID0ge1xuICAgICAgc3RhdHVzOiBMRUdBTF9IT0xEX1NUQVRVUy5FTkFCTEVELFxuICAgIH0gYXMgUHV0T2JqZWN0TGVnYWxIb2xkT3B0aW9ucyxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgaWYgKCFpc1ZhbGlkT2JqZWN0TmFtZShvYmplY3ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkT2JqZWN0TmFtZUVycm9yKGBJbnZhbGlkIG9iamVjdCBuYW1lOiAke29iamVjdE5hbWV9YClcbiAgICB9XG5cbiAgICBpZiAoIWlzT2JqZWN0KHNldE9wdHMpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdzZXRPcHRzIHNob3VsZCBiZSBvZiB0eXBlIFwiT2JqZWN0XCInKVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIVtMRUdBTF9IT0xEX1NUQVRVUy5FTkFCTEVELCBMRUdBTF9IT0xEX1NUQVRVUy5ESVNBQkxFRF0uaW5jbHVkZXMoc2V0T3B0cz8uc3RhdHVzKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdJbnZhbGlkIHN0YXR1czogJyArIHNldE9wdHMuc3RhdHVzKVxuICAgICAgfVxuICAgICAgaWYgKHNldE9wdHMudmVyc2lvbklkICYmICFzZXRPcHRzLnZlcnNpb25JZC5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndmVyc2lvbklkIHNob3VsZCBiZSBvZiB0eXBlIHN0cmluZy46JyArIHNldE9wdHMudmVyc2lvbklkKVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IG1ldGhvZCA9ICdQVVQnXG4gICAgbGV0IHF1ZXJ5ID0gJ2xlZ2FsLWhvbGQnXG5cbiAgICBpZiAoc2V0T3B0cy52ZXJzaW9uSWQpIHtcbiAgICAgIHF1ZXJ5ICs9IGAmdmVyc2lvbklkPSR7c2V0T3B0cy52ZXJzaW9uSWR9YFxuICAgIH1cblxuICAgIGNvbnN0IGNvbmZpZyA9IHtcbiAgICAgIFN0YXR1czogc2V0T3B0cy5zdGF0dXMsXG4gICAgfVxuXG4gICAgY29uc3QgYnVpbGRlciA9IG5ldyB4bWwyanMuQnVpbGRlcih7IHJvb3ROYW1lOiAnTGVnYWxIb2xkJywgcmVuZGVyT3B0czogeyBwcmV0dHk6IGZhbHNlIH0sIGhlYWRsZXNzOiB0cnVlIH0pXG4gICAgY29uc3QgcGF5bG9hZCA9IGJ1aWxkZXIuYnVpbGRPYmplY3QoY29uZmlnKVxuICAgIGNvbnN0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fVxuICAgIGhlYWRlcnNbJ0NvbnRlbnQtTUQ1J10gPSB0b01kNShwYXlsb2FkKVxuXG4gICAgYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jT21pdCh7IG1ldGhvZCwgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgcXVlcnksIGhlYWRlcnMgfSwgcGF5bG9hZClcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgVGFncyBhc3NvY2lhdGVkIHdpdGggYSBCdWNrZXRcbiAgICovXG4gIGFzeW5jIGdldEJ1Y2tldFRhZ2dpbmcoYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTxUYWdbXT4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcihgSW52YWxpZCBidWNrZXQgbmFtZTogJHtidWNrZXROYW1lfWApXG4gICAgfVxuXG4gICAgY29uc3QgbWV0aG9kID0gJ0dFVCdcbiAgICBjb25zdCBxdWVyeSA9ICd0YWdnaW5nJ1xuICAgIGNvbnN0IHJlcXVlc3RPcHRpb25zID0geyBtZXRob2QsIGJ1Y2tldE5hbWUsIHF1ZXJ5IH1cblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHJlcXVlc3RPcHRpb25zKVxuICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZWFkQXNTdHJpbmcocmVzcG9uc2UpXG4gICAgcmV0dXJuIHhtbFBhcnNlcnMucGFyc2VUYWdnaW5nKGJvZHkpXG4gIH1cblxuICAvKipcbiAgICogIEdldCB0aGUgdGFncyBhc3NvY2lhdGVkIHdpdGggYSBidWNrZXQgT1IgYW4gb2JqZWN0XG4gICAqL1xuICBhc3luYyBnZXRPYmplY3RUYWdnaW5nKGJ1Y2tldE5hbWU6IHN0cmluZywgb2JqZWN0TmFtZTogc3RyaW5nLCBnZXRPcHRzPzogR2V0T2JqZWN0T3B0cyk6IFByb21pc2U8VGFnW10+IHtcbiAgICBjb25zdCBtZXRob2QgPSAnR0VUJ1xuICAgIGxldCBxdWVyeSA9ICd0YWdnaW5nJ1xuXG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgaWYgKCFpc1ZhbGlkT2JqZWN0TmFtZShvYmplY3ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIG9iamVjdCBuYW1lOiAnICsgb2JqZWN0TmFtZSlcbiAgICB9XG4gICAgaWYgKGdldE9wdHMgJiYgIWlzT2JqZWN0KGdldE9wdHMpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCdnZXRPcHRzIHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICAgIH1cblxuICAgIGlmIChnZXRPcHRzICYmIGdldE9wdHMudmVyc2lvbklkKSB7XG4gICAgICBxdWVyeSA9IGAke3F1ZXJ5fSZ2ZXJzaW9uSWQ9JHtnZXRPcHRzLnZlcnNpb25JZH1gXG4gICAgfVxuICAgIGNvbnN0IHJlcXVlc3RPcHRpb25zOiBSZXF1ZXN0T3B0aW9uID0geyBtZXRob2QsIGJ1Y2tldE5hbWUsIHF1ZXJ5IH1cbiAgICBpZiAob2JqZWN0TmFtZSkge1xuICAgICAgcmVxdWVzdE9wdGlvbnNbJ29iamVjdE5hbWUnXSA9IG9iamVjdE5hbWVcbiAgICB9XG5cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyhyZXF1ZXN0T3B0aW9ucylcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVhZEFzU3RyaW5nKHJlc3BvbnNlKVxuICAgIHJldHVybiB4bWxQYXJzZXJzLnBhcnNlVGFnZ2luZyhib2R5KVxuICB9XG5cbiAgLyoqXG4gICAqICBTZXQgdGhlIHBvbGljeSBvbiBhIGJ1Y2tldCBvciBhbiBvYmplY3QgcHJlZml4LlxuICAgKi9cbiAgYXN5bmMgc2V0QnVja2V0UG9saWN5KGJ1Y2tldE5hbWU6IHN0cmluZywgcG9saWN5OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBWYWxpZGF0ZSBhcmd1bWVudHMuXG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKGBJbnZhbGlkIGJ1Y2tldCBuYW1lOiAke2J1Y2tldE5hbWV9YClcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyhwb2xpY3kpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXRQb2xpY3lFcnJvcihgSW52YWxpZCBidWNrZXQgcG9saWN5OiAke3BvbGljeX0gLSBtdXN0IGJlIFwic3RyaW5nXCJgKVxuICAgIH1cblxuICAgIGNvbnN0IHF1ZXJ5ID0gJ3BvbGljeSdcblxuICAgIGxldCBtZXRob2QgPSAnREVMRVRFJ1xuICAgIGlmIChwb2xpY3kpIHtcbiAgICAgIG1ldGhvZCA9ICdQVVQnXG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jT21pdCh7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfSwgcG9saWN5LCBbMjA0XSwgJycpXG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBwb2xpY3kgb24gYSBidWNrZXQgb3IgYW4gb2JqZWN0IHByZWZpeC5cbiAgICovXG4gIGFzeW5jIGdldEJ1Y2tldFBvbGljeShidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIC8vIFZhbGlkYXRlIGFyZ3VtZW50cy5cbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoYEludmFsaWQgYnVja2V0IG5hbWU6ICR7YnVja2V0TmFtZX1gKVxuICAgIH1cblxuICAgIGNvbnN0IG1ldGhvZCA9ICdHRVQnXG4gICAgY29uc3QgcXVlcnkgPSAncG9saWN5J1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfSlcbiAgICByZXR1cm4gYXdhaXQgcmVhZEFzU3RyaW5nKHJlcylcbiAgfVxuXG4gIGFzeW5jIHB1dE9iamVjdFJldGVudGlvbihidWNrZXROYW1lOiBzdHJpbmcsIG9iamVjdE5hbWU6IHN0cmluZywgcmV0ZW50aW9uT3B0czogUmV0ZW50aW9uID0ge30pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoYEludmFsaWQgYnVja2V0IG5hbWU6ICR7YnVja2V0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoIWlzT2JqZWN0KHJldGVudGlvbk9wdHMpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCdyZXRlbnRpb25PcHRzIHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAocmV0ZW50aW9uT3B0cy5nb3Zlcm5hbmNlQnlwYXNzICYmICFpc0Jvb2xlYW4ocmV0ZW50aW9uT3B0cy5nb3Zlcm5hbmNlQnlwYXNzKSkge1xuICAgICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKGBJbnZhbGlkIHZhbHVlIGZvciBnb3Zlcm5hbmNlQnlwYXNzOiAke3JldGVudGlvbk9wdHMuZ292ZXJuYW5jZUJ5cGFzc31gKVxuICAgICAgfVxuICAgICAgaWYgKFxuICAgICAgICByZXRlbnRpb25PcHRzLm1vZGUgJiZcbiAgICAgICAgIVtSRVRFTlRJT05fTU9ERVMuQ09NUExJQU5DRSwgUkVURU5USU9OX01PREVTLkdPVkVSTkFOQ0VdLmluY2x1ZGVzKHJldGVudGlvbk9wdHMubW9kZSlcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKGBJbnZhbGlkIG9iamVjdCByZXRlbnRpb24gbW9kZTogJHtyZXRlbnRpb25PcHRzLm1vZGV9YClcbiAgICAgIH1cbiAgICAgIGlmIChyZXRlbnRpb25PcHRzLnJldGFpblVudGlsRGF0ZSAmJiAhaXNTdHJpbmcocmV0ZW50aW9uT3B0cy5yZXRhaW5VbnRpbERhdGUpKSB7XG4gICAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoYEludmFsaWQgdmFsdWUgZm9yIHJldGFpblVudGlsRGF0ZTogJHtyZXRlbnRpb25PcHRzLnJldGFpblVudGlsRGF0ZX1gKVxuICAgICAgfVxuICAgICAgaWYgKHJldGVudGlvbk9wdHMudmVyc2lvbklkICYmICFpc1N0cmluZyhyZXRlbnRpb25PcHRzLnZlcnNpb25JZCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihgSW52YWxpZCB2YWx1ZSBmb3IgdmVyc2lvbklkOiAke3JldGVudGlvbk9wdHMudmVyc2lvbklkfWApXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgbWV0aG9kID0gJ1BVVCdcbiAgICBsZXQgcXVlcnkgPSAncmV0ZW50aW9uJ1xuXG4gICAgY29uc3QgaGVhZGVyczogUmVxdWVzdEhlYWRlcnMgPSB7fVxuICAgIGlmIChyZXRlbnRpb25PcHRzLmdvdmVybmFuY2VCeXBhc3MpIHtcbiAgICAgIGhlYWRlcnNbJ1gtQW16LUJ5cGFzcy1Hb3Zlcm5hbmNlLVJldGVudGlvbiddID0gdHJ1ZVxuICAgIH1cblxuICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgeG1sMmpzLkJ1aWxkZXIoeyByb290TmFtZTogJ1JldGVudGlvbicsIHJlbmRlck9wdHM6IHsgcHJldHR5OiBmYWxzZSB9LCBoZWFkbGVzczogdHJ1ZSB9KVxuICAgIGNvbnN0IHBhcmFtczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9XG5cbiAgICBpZiAocmV0ZW50aW9uT3B0cy5tb2RlKSB7XG4gICAgICBwYXJhbXMuTW9kZSA9IHJldGVudGlvbk9wdHMubW9kZVxuICAgIH1cbiAgICBpZiAocmV0ZW50aW9uT3B0cy5yZXRhaW5VbnRpbERhdGUpIHtcbiAgICAgIHBhcmFtcy5SZXRhaW5VbnRpbERhdGUgPSByZXRlbnRpb25PcHRzLnJldGFpblVudGlsRGF0ZVxuICAgIH1cbiAgICBpZiAocmV0ZW50aW9uT3B0cy52ZXJzaW9uSWQpIHtcbiAgICAgIHF1ZXJ5ICs9IGAmdmVyc2lvbklkPSR7cmV0ZW50aW9uT3B0cy52ZXJzaW9uSWR9YFxuICAgIH1cblxuICAgIGNvbnN0IHBheWxvYWQgPSBidWlsZGVyLmJ1aWxkT2JqZWN0KHBhcmFtcylcblxuICAgIGhlYWRlcnNbJ0NvbnRlbnQtTUQ1J10gPSB0b01kNShwYXlsb2FkKVxuICAgIGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luY09taXQoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIHF1ZXJ5LCBoZWFkZXJzIH0sIHBheWxvYWQsIFsyMDAsIDIwNF0pXG4gIH1cblxuICBnZXRPYmplY3RMb2NrQ29uZmlnKGJ1Y2tldE5hbWU6IHN0cmluZywgY2FsbGJhY2s6IFJlc3VsdENhbGxiYWNrPE9iamVjdExvY2tJbmZvPik6IHZvaWRcbiAgZ2V0T2JqZWN0TG9ja0NvbmZpZyhidWNrZXROYW1lOiBzdHJpbmcpOiB2b2lkXG4gIGFzeW5jIGdldE9iamVjdExvY2tDb25maWcoYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTxPYmplY3RMb2NrSW5mbz5cbiAgYXN5bmMgZ2V0T2JqZWN0TG9ja0NvbmZpZyhidWNrZXROYW1lOiBzdHJpbmcpIHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBjb25zdCBtZXRob2QgPSAnR0VUJ1xuICAgIGNvbnN0IHF1ZXJ5ID0gJ29iamVjdC1sb2NrJ1xuXG4gICAgY29uc3QgaHR0cFJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfSlcbiAgICBjb25zdCB4bWxSZXN1bHQgPSBhd2FpdCByZWFkQXNTdHJpbmcoaHR0cFJlcylcbiAgICByZXR1cm4geG1sUGFyc2Vycy5wYXJzZU9iamVjdExvY2tDb25maWcoeG1sUmVzdWx0KVxuICB9XG5cbiAgc2V0T2JqZWN0TG9ja0NvbmZpZyhidWNrZXROYW1lOiBzdHJpbmcsIGxvY2tDb25maWdPcHRzOiBPbWl0PE9iamVjdExvY2tJbmZvLCAnb2JqZWN0TG9ja0VuYWJsZWQnPik6IHZvaWRcbiAgYXN5bmMgc2V0T2JqZWN0TG9ja0NvbmZpZyhcbiAgICBidWNrZXROYW1lOiBzdHJpbmcsXG4gICAgbG9ja0NvbmZpZ09wdHM6IE9taXQ8T2JqZWN0TG9ja0luZm8sICdvYmplY3RMb2NrRW5hYmxlZCc+LFxuICApOiBQcm9taXNlPHZvaWQ+XG4gIGFzeW5jIHNldE9iamVjdExvY2tDb25maWcoYnVja2V0TmFtZTogc3RyaW5nLCBsb2NrQ29uZmlnT3B0czogT21pdDxPYmplY3RMb2NrSW5mbywgJ29iamVjdExvY2tFbmFibGVkJz4pIHtcbiAgICBjb25zdCByZXRlbnRpb25Nb2RlcyA9IFtSRVRFTlRJT05fTU9ERVMuQ09NUExJQU5DRSwgUkVURU5USU9OX01PREVTLkdPVkVSTkFOQ0VdXG4gICAgY29uc3QgdmFsaWRVbml0cyA9IFtSRVRFTlRJT05fVkFMSURJVFlfVU5JVFMuREFZUywgUkVURU5USU9OX1ZBTElESVRZX1VOSVRTLllFQVJTXVxuXG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG5cbiAgICBpZiAobG9ja0NvbmZpZ09wdHMubW9kZSAmJiAhcmV0ZW50aW9uTW9kZXMuaW5jbHVkZXMobG9ja0NvbmZpZ09wdHMubW9kZSkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYGxvY2tDb25maWdPcHRzLm1vZGUgc2hvdWxkIGJlIG9uZSBvZiAke3JldGVudGlvbk1vZGVzfWApXG4gICAgfVxuICAgIGlmIChsb2NrQ29uZmlnT3B0cy51bml0ICYmICF2YWxpZFVuaXRzLmluY2x1ZGVzKGxvY2tDb25maWdPcHRzLnVuaXQpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBsb2NrQ29uZmlnT3B0cy51bml0IHNob3VsZCBiZSBvbmUgb2YgJHt2YWxpZFVuaXRzfWApXG4gICAgfVxuICAgIGlmIChsb2NrQ29uZmlnT3B0cy52YWxpZGl0eSAmJiAhaXNOdW1iZXIobG9ja0NvbmZpZ09wdHMudmFsaWRpdHkpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBsb2NrQ29uZmlnT3B0cy52YWxpZGl0eSBzaG91bGQgYmUgYSBudW1iZXJgKVxuICAgIH1cblxuICAgIGNvbnN0IG1ldGhvZCA9ICdQVVQnXG4gICAgY29uc3QgcXVlcnkgPSAnb2JqZWN0LWxvY2snXG5cbiAgICBjb25zdCBjb25maWc6IE9iamVjdExvY2tDb25maWdQYXJhbSA9IHtcbiAgICAgIE9iamVjdExvY2tFbmFibGVkOiAnRW5hYmxlZCcsXG4gICAgfVxuICAgIGNvbnN0IGNvbmZpZ0tleXMgPSBPYmplY3Qua2V5cyhsb2NrQ29uZmlnT3B0cylcblxuICAgIGNvbnN0IGlzQWxsS2V5c1NldCA9IFsndW5pdCcsICdtb2RlJywgJ3ZhbGlkaXR5J10uZXZlcnkoKGxjaykgPT4gY29uZmlnS2V5cy5pbmNsdWRlcyhsY2spKVxuICAgIC8vIENoZWNrIGlmIGtleXMgYXJlIHByZXNlbnQgYW5kIGFsbCBrZXlzIGFyZSBwcmVzZW50LlxuICAgIGlmIChjb25maWdLZXlzLmxlbmd0aCA+IDApIHtcbiAgICAgIGlmICghaXNBbGxLZXlzU2V0KSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgYGxvY2tDb25maWdPcHRzLm1vZGUsbG9ja0NvbmZpZ09wdHMudW5pdCxsb2NrQ29uZmlnT3B0cy52YWxpZGl0eSBhbGwgdGhlIHByb3BlcnRpZXMgc2hvdWxkIGJlIHNwZWNpZmllZC5gLFxuICAgICAgICApXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25maWcuUnVsZSA9IHtcbiAgICAgICAgICBEZWZhdWx0UmV0ZW50aW9uOiB7fSxcbiAgICAgICAgfVxuICAgICAgICBpZiAobG9ja0NvbmZpZ09wdHMubW9kZSkge1xuICAgICAgICAgIGNvbmZpZy5SdWxlLkRlZmF1bHRSZXRlbnRpb24uTW9kZSA9IGxvY2tDb25maWdPcHRzLm1vZGVcbiAgICAgICAgfVxuICAgICAgICBpZiAobG9ja0NvbmZpZ09wdHMudW5pdCA9PT0gUkVURU5USU9OX1ZBTElESVRZX1VOSVRTLkRBWVMpIHtcbiAgICAgICAgICBjb25maWcuUnVsZS5EZWZhdWx0UmV0ZW50aW9uLkRheXMgPSBsb2NrQ29uZmlnT3B0cy52YWxpZGl0eVxuICAgICAgICB9IGVsc2UgaWYgKGxvY2tDb25maWdPcHRzLnVuaXQgPT09IFJFVEVOVElPTl9WQUxJRElUWV9VTklUUy5ZRUFSUykge1xuICAgICAgICAgIGNvbmZpZy5SdWxlLkRlZmF1bHRSZXRlbnRpb24uWWVhcnMgPSBsb2NrQ29uZmlnT3B0cy52YWxpZGl0eVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgYnVpbGRlciA9IG5ldyB4bWwyanMuQnVpbGRlcih7XG4gICAgICByb290TmFtZTogJ09iamVjdExvY2tDb25maWd1cmF0aW9uJyxcbiAgICAgIHJlbmRlck9wdHM6IHsgcHJldHR5OiBmYWxzZSB9LFxuICAgICAgaGVhZGxlc3M6IHRydWUsXG4gICAgfSlcbiAgICBjb25zdCBwYXlsb2FkID0gYnVpbGRlci5idWlsZE9iamVjdChjb25maWcpXG5cbiAgICBjb25zdCBoZWFkZXJzOiBSZXF1ZXN0SGVhZGVycyA9IHt9XG4gICAgaGVhZGVyc1snQ29udGVudC1NRDUnXSA9IHRvTWQ1KHBheWxvYWQpXG5cbiAgICBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmNPbWl0KHsgbWV0aG9kLCBidWNrZXROYW1lLCBxdWVyeSwgaGVhZGVycyB9LCBwYXlsb2FkKVxuICB9XG5cbiAgYXN5bmMgZ2V0QnVja2V0VmVyc2lvbmluZyhidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPEJ1Y2tldFZlcnNpb25pbmdDb25maWd1cmF0aW9uPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgY29uc3QgbWV0aG9kID0gJ0dFVCdcbiAgICBjb25zdCBxdWVyeSA9ICd2ZXJzaW9uaW5nJ1xuXG4gICAgY29uc3QgaHR0cFJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfSlcbiAgICBjb25zdCB4bWxSZXN1bHQgPSBhd2FpdCByZWFkQXNTdHJpbmcoaHR0cFJlcylcbiAgICByZXR1cm4gYXdhaXQgeG1sUGFyc2Vycy5wYXJzZUJ1Y2tldFZlcnNpb25pbmdDb25maWcoeG1sUmVzdWx0KVxuICB9XG5cbiAgYXN5bmMgc2V0QnVja2V0VmVyc2lvbmluZyhidWNrZXROYW1lOiBzdHJpbmcsIHZlcnNpb25Db25maWc6IEJ1Y2tldFZlcnNpb25pbmdDb25maWd1cmF0aW9uKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgaWYgKCFPYmplY3Qua2V5cyh2ZXJzaW9uQ29uZmlnKS5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ3ZlcnNpb25Db25maWcgc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gICAgfVxuXG4gICAgY29uc3QgbWV0aG9kID0gJ1BVVCdcbiAgICBjb25zdCBxdWVyeSA9ICd2ZXJzaW9uaW5nJ1xuICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgeG1sMmpzLkJ1aWxkZXIoe1xuICAgICAgcm9vdE5hbWU6ICdWZXJzaW9uaW5nQ29uZmlndXJhdGlvbicsXG4gICAgICByZW5kZXJPcHRzOiB7IHByZXR0eTogZmFsc2UgfSxcbiAgICAgIGhlYWRsZXNzOiB0cnVlLFxuICAgIH0pXG4gICAgY29uc3QgcGF5bG9hZCA9IGJ1aWxkZXIuYnVpbGRPYmplY3QodmVyc2lvbkNvbmZpZylcblxuICAgIGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luY09taXQoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIHF1ZXJ5IH0sIHBheWxvYWQpXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHNldFRhZ2dpbmcodGFnZ2luZ1BhcmFtczogUHV0VGFnZ2luZ1BhcmFtcyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgdGFncywgcHV0T3B0cyB9ID0gdGFnZ2luZ1BhcmFtc1xuICAgIGNvbnN0IG1ldGhvZCA9ICdQVVQnXG4gICAgbGV0IHF1ZXJ5ID0gJ3RhZ2dpbmcnXG5cbiAgICBpZiAocHV0T3B0cyAmJiBwdXRPcHRzPy52ZXJzaW9uSWQpIHtcbiAgICAgIHF1ZXJ5ID0gYCR7cXVlcnl9JnZlcnNpb25JZD0ke3B1dE9wdHMudmVyc2lvbklkfWBcbiAgICB9XG4gICAgY29uc3QgdGFnc0xpc3QgPSBbXVxuICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHRhZ3MpKSB7XG4gICAgICB0YWdzTGlzdC5wdXNoKHsgS2V5OiBrZXksIFZhbHVlOiB2YWx1ZSB9KVxuICAgIH1cbiAgICBjb25zdCB0YWdnaW5nQ29uZmlnID0ge1xuICAgICAgVGFnZ2luZzoge1xuICAgICAgICBUYWdTZXQ6IHtcbiAgICAgICAgICBUYWc6IHRhZ3NMaXN0LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9XG4gICAgY29uc3QgaGVhZGVycyA9IHt9IGFzIFJlcXVlc3RIZWFkZXJzXG4gICAgY29uc3QgYnVpbGRlciA9IG5ldyB4bWwyanMuQnVpbGRlcih7IGhlYWRsZXNzOiB0cnVlLCByZW5kZXJPcHRzOiB7IHByZXR0eTogZmFsc2UgfSB9KVxuICAgIGNvbnN0IHBheWxvYWRCdWYgPSBCdWZmZXIuZnJvbShidWlsZGVyLmJ1aWxkT2JqZWN0KHRhZ2dpbmdDb25maWcpKVxuICAgIGNvbnN0IHJlcXVlc3RPcHRpb25zID0ge1xuICAgICAgbWV0aG9kLFxuICAgICAgYnVja2V0TmFtZSxcbiAgICAgIHF1ZXJ5LFxuICAgICAgaGVhZGVycyxcblxuICAgICAgLi4uKG9iamVjdE5hbWUgJiYgeyBvYmplY3ROYW1lOiBvYmplY3ROYW1lIH0pLFxuICAgIH1cblxuICAgIGhlYWRlcnNbJ0NvbnRlbnQtTUQ1J10gPSB0b01kNShwYXlsb2FkQnVmKVxuXG4gICAgYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jT21pdChyZXF1ZXN0T3B0aW9ucywgcGF5bG9hZEJ1ZilcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcmVtb3ZlVGFnZ2luZyh7IGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIHJlbW92ZU9wdHMgfTogUmVtb3ZlVGFnZ2luZ1BhcmFtcyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG1ldGhvZCA9ICdERUxFVEUnXG4gICAgbGV0IHF1ZXJ5ID0gJ3RhZ2dpbmcnXG5cbiAgICBpZiAocmVtb3ZlT3B0cyAmJiBPYmplY3Qua2V5cyhyZW1vdmVPcHRzKS5sZW5ndGggJiYgcmVtb3ZlT3B0cy52ZXJzaW9uSWQpIHtcbiAgICAgIHF1ZXJ5ID0gYCR7cXVlcnl9JnZlcnNpb25JZD0ke3JlbW92ZU9wdHMudmVyc2lvbklkfWBcbiAgICB9XG4gICAgY29uc3QgcmVxdWVzdE9wdGlvbnMgPSB7IG1ldGhvZCwgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgcXVlcnkgfVxuXG4gICAgaWYgKG9iamVjdE5hbWUpIHtcbiAgICAgIHJlcXVlc3RPcHRpb25zWydvYmplY3ROYW1lJ10gPSBvYmplY3ROYW1lXG4gICAgfVxuICAgIGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyhyZXF1ZXN0T3B0aW9ucywgJycsIFsyMDAsIDIwNF0pXG4gIH1cblxuICBhc3luYyBzZXRCdWNrZXRUYWdnaW5nKGJ1Y2tldE5hbWU6IHN0cmluZywgdGFnczogVGFncyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNQbGFpbk9iamVjdCh0YWdzKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcigndGFncyBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgICB9XG4gICAgaWYgKE9iamVjdC5rZXlzKHRhZ3MpLmxlbmd0aCA+IDEwKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCdtYXhpbXVtIHRhZ3MgYWxsb3dlZCBpcyAxMFwiJylcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLnNldFRhZ2dpbmcoeyBidWNrZXROYW1lLCB0YWdzIH0pXG4gIH1cblxuICBhc3luYyByZW1vdmVCdWNrZXRUYWdnaW5nKGJ1Y2tldE5hbWU6IHN0cmluZykge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGF3YWl0IHRoaXMucmVtb3ZlVGFnZ2luZyh7IGJ1Y2tldE5hbWUgfSlcbiAgfVxuXG4gIGFzeW5jIHNldE9iamVjdFRhZ2dpbmcoYnVja2V0TmFtZTogc3RyaW5nLCBvYmplY3ROYW1lOiBzdHJpbmcsIHRhZ3M6IFRhZ3MsIHB1dE9wdHM/OiBUYWdnaW5nT3B0cykge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNWYWxpZE9iamVjdE5hbWUob2JqZWN0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBvYmplY3QgbmFtZTogJyArIG9iamVjdE5hbWUpXG4gICAgfVxuXG4gICAgaWYgKCFpc1BsYWluT2JqZWN0KHRhZ3MpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCd0YWdzIHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICAgIH1cbiAgICBpZiAoT2JqZWN0LmtleXModGFncykubGVuZ3RoID4gMTApIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ01heGltdW0gdGFncyBhbGxvd2VkIGlzIDEwXCInKVxuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuc2V0VGFnZ2luZyh7IGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIHRhZ3MsIHB1dE9wdHMgfSlcbiAgfVxuXG4gIGFzeW5jIHJlbW92ZU9iamVjdFRhZ2dpbmcoYnVja2V0TmFtZTogc3RyaW5nLCBvYmplY3ROYW1lOiBzdHJpbmcsIHJlbW92ZU9wdHM6IFRhZ2dpbmdPcHRzKSB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgaWYgKCFpc1ZhbGlkT2JqZWN0TmFtZShvYmplY3ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIG9iamVjdCBuYW1lOiAnICsgb2JqZWN0TmFtZSlcbiAgICB9XG4gICAgaWYgKHJlbW92ZU9wdHMgJiYgT2JqZWN0LmtleXMocmVtb3ZlT3B0cykubGVuZ3RoICYmICFpc09iamVjdChyZW1vdmVPcHRzKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcigncmVtb3ZlT3B0cyBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLnJlbW92ZVRhZ2dpbmcoeyBidWNrZXROYW1lLCBvYmplY3ROYW1lLCByZW1vdmVPcHRzIH0pXG4gIH1cblxuICBhc3luYyBzZWxlY3RPYmplY3RDb250ZW50KFxuICAgIGJ1Y2tldE5hbWU6IHN0cmluZyxcbiAgICBvYmplY3ROYW1lOiBzdHJpbmcsXG4gICAgc2VsZWN0T3B0czogU2VsZWN0T3B0aW9ucyxcbiAgKTogUHJvbWlzZTxTZWxlY3RSZXN1bHRzIHwgdW5kZWZpbmVkPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKGBJbnZhbGlkIGJ1Y2tldCBuYW1lOiAke2J1Y2tldE5hbWV9YClcbiAgICB9XG4gICAgaWYgKCFpc1ZhbGlkT2JqZWN0TmFtZShvYmplY3ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkT2JqZWN0TmFtZUVycm9yKGBJbnZhbGlkIG9iamVjdCBuYW1lOiAke29iamVjdE5hbWV9YClcbiAgICB9XG4gICAgaWYgKCFfLmlzRW1wdHkoc2VsZWN0T3B0cykpIHtcbiAgICAgIGlmICghaXNTdHJpbmcoc2VsZWN0T3B0cy5leHByZXNzaW9uKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdzcWxFeHByZXNzaW9uIHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICAgICAgfVxuICAgICAgaWYgKCFfLmlzRW1wdHkoc2VsZWN0T3B0cy5pbnB1dFNlcmlhbGl6YXRpb24pKSB7XG4gICAgICAgIGlmICghaXNPYmplY3Qoc2VsZWN0T3B0cy5pbnB1dFNlcmlhbGl6YXRpb24pKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaW5wdXRTZXJpYWxpemF0aW9uIHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdpbnB1dFNlcmlhbGl6YXRpb24gaXMgcmVxdWlyZWQnKVxuICAgICAgfVxuICAgICAgaWYgKCFfLmlzRW1wdHkoc2VsZWN0T3B0cy5vdXRwdXRTZXJpYWxpemF0aW9uKSkge1xuICAgICAgICBpZiAoIWlzT2JqZWN0KHNlbGVjdE9wdHMub3V0cHV0U2VyaWFsaXphdGlvbikpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdvdXRwdXRTZXJpYWxpemF0aW9uIHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdvdXRwdXRTZXJpYWxpemF0aW9uIGlzIHJlcXVpcmVkJylcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndmFsaWQgc2VsZWN0IGNvbmZpZ3VyYXRpb24gaXMgcmVxdWlyZWQnKVxuICAgIH1cblxuICAgIGNvbnN0IG1ldGhvZCA9ICdQT1NUJ1xuICAgIGNvbnN0IHF1ZXJ5ID0gYHNlbGVjdCZzZWxlY3QtdHlwZT0yYFxuXG4gICAgY29uc3QgY29uZmlnOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPltdID0gW1xuICAgICAge1xuICAgICAgICBFeHByZXNzaW9uOiBzZWxlY3RPcHRzLmV4cHJlc3Npb24sXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBFeHByZXNzaW9uVHlwZTogc2VsZWN0T3B0cy5leHByZXNzaW9uVHlwZSB8fCAnU1FMJyxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIElucHV0U2VyaWFsaXphdGlvbjogW3NlbGVjdE9wdHMuaW5wdXRTZXJpYWxpemF0aW9uXSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIE91dHB1dFNlcmlhbGl6YXRpb246IFtzZWxlY3RPcHRzLm91dHB1dFNlcmlhbGl6YXRpb25dLFxuICAgICAgfSxcbiAgICBdXG5cbiAgICAvLyBPcHRpb25hbFxuICAgIGlmIChzZWxlY3RPcHRzLnJlcXVlc3RQcm9ncmVzcykge1xuICAgICAgY29uZmlnLnB1c2goeyBSZXF1ZXN0UHJvZ3Jlc3M6IHNlbGVjdE9wdHM/LnJlcXVlc3RQcm9ncmVzcyB9KVxuICAgIH1cbiAgICAvLyBPcHRpb25hbFxuICAgIGlmIChzZWxlY3RPcHRzLnNjYW5SYW5nZSkge1xuICAgICAgY29uZmlnLnB1c2goeyBTY2FuUmFuZ2U6IHNlbGVjdE9wdHMuc2NhblJhbmdlIH0pXG4gICAgfVxuXG4gICAgY29uc3QgYnVpbGRlciA9IG5ldyB4bWwyanMuQnVpbGRlcih7XG4gICAgICByb290TmFtZTogJ1NlbGVjdE9iamVjdENvbnRlbnRSZXF1ZXN0JyxcbiAgICAgIHJlbmRlck9wdHM6IHsgcHJldHR5OiBmYWxzZSB9LFxuICAgICAgaGVhZGxlc3M6IHRydWUsXG4gICAgfSlcbiAgICBjb25zdCBwYXlsb2FkID0gYnVpbGRlci5idWlsZE9iamVjdChjb25maWcpXG5cbiAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmMoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUsIHF1ZXJ5IH0sIHBheWxvYWQpXG4gICAgY29uc3QgYm9keSA9IGF3YWl0IHJlYWRBc0J1ZmZlcihyZXMpXG4gICAgcmV0dXJuIHBhcnNlU2VsZWN0T2JqZWN0Q29udGVudFJlc3BvbnNlKGJvZHkpXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGFwcGx5QnVja2V0TGlmZWN5Y2xlKGJ1Y2tldE5hbWU6IHN0cmluZywgcG9saWN5Q29uZmlnOiBMaWZlQ3ljbGVDb25maWdQYXJhbSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG1ldGhvZCA9ICdQVVQnXG4gICAgY29uc3QgcXVlcnkgPSAnbGlmZWN5Y2xlJ1xuXG4gICAgY29uc3QgaGVhZGVyczogUmVxdWVzdEhlYWRlcnMgPSB7fVxuICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgeG1sMmpzLkJ1aWxkZXIoe1xuICAgICAgcm9vdE5hbWU6ICdMaWZlY3ljbGVDb25maWd1cmF0aW9uJyxcbiAgICAgIGhlYWRsZXNzOiB0cnVlLFxuICAgICAgcmVuZGVyT3B0czogeyBwcmV0dHk6IGZhbHNlIH0sXG4gICAgfSlcbiAgICBjb25zdCBwYXlsb2FkID0gYnVpbGRlci5idWlsZE9iamVjdChwb2xpY3lDb25maWcpXG4gICAgaGVhZGVyc1snQ29udGVudC1NRDUnXSA9IHRvTWQ1KHBheWxvYWQpXG5cbiAgICBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmNPbWl0KHsgbWV0aG9kLCBidWNrZXROYW1lLCBxdWVyeSwgaGVhZGVycyB9LCBwYXlsb2FkKVxuICB9XG5cbiAgYXN5bmMgcmVtb3ZlQnVja2V0TGlmZWN5Y2xlKGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGNvbnN0IG1ldGhvZCA9ICdERUxFVEUnXG4gICAgY29uc3QgcXVlcnkgPSAnbGlmZWN5Y2xlJ1xuICAgIGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luY09taXQoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIHF1ZXJ5IH0sICcnLCBbMjA0XSlcbiAgfVxuXG4gIGFzeW5jIHNldEJ1Y2tldExpZmVjeWNsZShidWNrZXROYW1lOiBzdHJpbmcsIGxpZmVDeWNsZUNvbmZpZzogTGlmZUN5Y2xlQ29uZmlnUGFyYW0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoXy5pc0VtcHR5KGxpZmVDeWNsZUNvbmZpZykpIHtcbiAgICAgIGF3YWl0IHRoaXMucmVtb3ZlQnVja2V0TGlmZWN5Y2xlKGJ1Y2tldE5hbWUpXG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IHRoaXMuYXBwbHlCdWNrZXRMaWZlY3ljbGUoYnVja2V0TmFtZSwgbGlmZUN5Y2xlQ29uZmlnKVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGdldEJ1Y2tldExpZmVjeWNsZShidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPExpZmVjeWNsZUNvbmZpZyB8IG51bGw+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBjb25zdCBtZXRob2QgPSAnR0VUJ1xuICAgIGNvbnN0IHF1ZXJ5ID0gJ2xpZmVjeWNsZSdcblxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfSlcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVhZEFzU3RyaW5nKHJlcylcbiAgICByZXR1cm4geG1sUGFyc2Vycy5wYXJzZUxpZmVjeWNsZUNvbmZpZyhib2R5KVxuICB9XG5cbiAgYXN5bmMgc2V0QnVja2V0RW5jcnlwdGlvbihidWNrZXROYW1lOiBzdHJpbmcsIGVuY3J5cHRpb25Db25maWc/OiBFbmNyeXB0aW9uQ29uZmlnKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgaWYgKCFfLmlzRW1wdHkoZW5jcnlwdGlvbkNvbmZpZykgJiYgZW5jcnlwdGlvbkNvbmZpZy5SdWxlLmxlbmd0aCA+IDEpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ0ludmFsaWQgUnVsZSBsZW5ndGguIE9ubHkgb25lIHJ1bGUgaXMgYWxsb3dlZC46ICcgKyBlbmNyeXB0aW9uQ29uZmlnLlJ1bGUpXG4gICAgfVxuXG4gICAgbGV0IGVuY3J5cHRpb25PYmogPSBlbmNyeXB0aW9uQ29uZmlnXG4gICAgaWYgKF8uaXNFbXB0eShlbmNyeXB0aW9uQ29uZmlnKSkge1xuICAgICAgZW5jcnlwdGlvbk9iaiA9IHtcbiAgICAgICAgLy8gRGVmYXVsdCBNaW5JTyBTZXJ2ZXIgU3VwcG9ydGVkIFJ1bGVcbiAgICAgICAgUnVsZTogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIEFwcGx5U2VydmVyU2lkZUVuY3J5cHRpb25CeURlZmF1bHQ6IHtcbiAgICAgICAgICAgICAgU1NFQWxnb3JpdGhtOiAnQUVTMjU2JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBtZXRob2QgPSAnUFVUJ1xuICAgIGNvbnN0IHF1ZXJ5ID0gJ2VuY3J5cHRpb24nXG4gICAgY29uc3QgYnVpbGRlciA9IG5ldyB4bWwyanMuQnVpbGRlcih7XG4gICAgICByb290TmFtZTogJ1NlcnZlclNpZGVFbmNyeXB0aW9uQ29uZmlndXJhdGlvbicsXG4gICAgICByZW5kZXJPcHRzOiB7IHByZXR0eTogZmFsc2UgfSxcbiAgICAgIGhlYWRsZXNzOiB0cnVlLFxuICAgIH0pXG4gICAgY29uc3QgcGF5bG9hZCA9IGJ1aWxkZXIuYnVpbGRPYmplY3QoZW5jcnlwdGlvbk9iailcblxuICAgIGNvbnN0IGhlYWRlcnM6IFJlcXVlc3RIZWFkZXJzID0ge31cbiAgICBoZWFkZXJzWydDb250ZW50LU1ENSddID0gdG9NZDUocGF5bG9hZClcblxuICAgIGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luY09taXQoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIHF1ZXJ5LCBoZWFkZXJzIH0sIHBheWxvYWQpXG4gIH1cblxuICBhc3luYyBnZXRCdWNrZXRFbmNyeXB0aW9uKGJ1Y2tldE5hbWU6IHN0cmluZykge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGNvbnN0IG1ldGhvZCA9ICdHRVQnXG4gICAgY29uc3QgcXVlcnkgPSAnZW5jcnlwdGlvbidcblxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfSlcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVhZEFzU3RyaW5nKHJlcylcbiAgICByZXR1cm4geG1sUGFyc2Vycy5wYXJzZUJ1Y2tldEVuY3J5cHRpb25Db25maWcoYm9keSlcbiAgfVxuXG4gIGFzeW5jIHJlbW92ZUJ1Y2tldEVuY3J5cHRpb24oYnVja2V0TmFtZTogc3RyaW5nKSB7XG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZShidWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgYnVja2V0TmFtZSlcbiAgICB9XG4gICAgY29uc3QgbWV0aG9kID0gJ0RFTEVURSdcbiAgICBjb25zdCBxdWVyeSA9ICdlbmNyeXB0aW9uJ1xuXG4gICAgYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jT21pdCh7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfSwgJycsIFsyMDRdKVxuICB9XG5cbiAgYXN5bmMgZ2V0T2JqZWN0UmV0ZW50aW9uKFxuICAgIGJ1Y2tldE5hbWU6IHN0cmluZyxcbiAgICBvYmplY3ROYW1lOiBzdHJpbmcsXG4gICAgZ2V0T3B0cz86IEdldE9iamVjdFJldGVudGlvbk9wdHMsXG4gICk6IFByb21pc2U8T2JqZWN0UmV0ZW50aW9uSW5mbyB8IG51bGwgfCB1bmRlZmluZWQ+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoZ2V0T3B0cyAmJiAhaXNPYmplY3QoZ2V0T3B0cykpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ2dldE9wdHMgc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gICAgfSBlbHNlIGlmIChnZXRPcHRzPy52ZXJzaW9uSWQgJiYgIWlzU3RyaW5nKGdldE9wdHMudmVyc2lvbklkKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcigndmVyc2lvbklkIHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICAgIH1cblxuICAgIGNvbnN0IG1ldGhvZCA9ICdHRVQnXG4gICAgbGV0IHF1ZXJ5ID0gJ3JldGVudGlvbidcbiAgICBpZiAoZ2V0T3B0cz8udmVyc2lvbklkKSB7XG4gICAgICBxdWVyeSArPSBgJnZlcnNpb25JZD0ke2dldE9wdHMudmVyc2lvbklkfWBcbiAgICB9XG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kLCBidWNrZXROYW1lLCBvYmplY3ROYW1lLCBxdWVyeSB9KVxuICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZWFkQXNTdHJpbmcocmVzKVxuICAgIHJldHVybiB4bWxQYXJzZXJzLnBhcnNlT2JqZWN0UmV0ZW50aW9uQ29uZmlnKGJvZHkpXG4gIH1cblxuICBhc3luYyByZW1vdmVPYmplY3RzKGJ1Y2tldE5hbWU6IHN0cmluZywgb2JqZWN0c0xpc3Q6IFJlbW92ZU9iamVjdHNQYXJhbSk6IFByb21pc2U8UmVtb3ZlT2JqZWN0c1Jlc3BvbnNlW10+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0c0xpc3QpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCdvYmplY3RzTGlzdCBzaG91bGQgYmUgYSBsaXN0JylcbiAgICB9XG5cbiAgICBjb25zdCBydW5EZWxldGVPYmplY3RzID0gYXN5bmMgKGJhdGNoOiBSZW1vdmVPYmplY3RzUGFyYW0pOiBQcm9taXNlPFJlbW92ZU9iamVjdHNSZXNwb25zZVtdPiA9PiB7XG4gICAgICBjb25zdCBkZWxPYmplY3RzOiBSZW1vdmVPYmplY3RzUmVxdWVzdEVudHJ5W10gPSBiYXRjaC5tYXAoKHZhbHVlKSA9PiB7XG4gICAgICAgIHJldHVybiBpc09iamVjdCh2YWx1ZSkgPyB7IEtleTogdmFsdWUubmFtZSwgVmVyc2lvbklkOiB2YWx1ZS52ZXJzaW9uSWQgfSA6IHsgS2V5OiB2YWx1ZSB9XG4gICAgICB9KVxuXG4gICAgICBjb25zdCByZW1PYmplY3RzID0geyBEZWxldGU6IHsgUXVpZXQ6IHRydWUsIE9iamVjdDogZGVsT2JqZWN0cyB9IH1cbiAgICAgIGNvbnN0IHBheWxvYWQgPSBCdWZmZXIuZnJvbShuZXcgeG1sMmpzLkJ1aWxkZXIoeyBoZWFkbGVzczogdHJ1ZSB9KS5idWlsZE9iamVjdChyZW1PYmplY3RzKSlcbiAgICAgIGNvbnN0IGhlYWRlcnM6IFJlcXVlc3RIZWFkZXJzID0geyAnQ29udGVudC1NRDUnOiB0b01kNShwYXlsb2FkKSB9XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZDogJ1BPU1QnLCBidWNrZXROYW1lLCBxdWVyeTogJ2RlbGV0ZScsIGhlYWRlcnMgfSwgcGF5bG9hZClcbiAgICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZWFkQXNTdHJpbmcocmVzKVxuICAgICAgcmV0dXJuIHhtbFBhcnNlcnMucmVtb3ZlT2JqZWN0c1BhcnNlcihib2R5KVxuICAgIH1cblxuICAgIGNvbnN0IG1heEVudHJpZXMgPSAxMDAwIC8vIG1heCBlbnRyaWVzIGFjY2VwdGVkIGluIHNlcnZlciBmb3IgRGVsZXRlTXVsdGlwbGVPYmplY3RzIEFQSS5cbiAgICAvLyBDbGllbnQgc2lkZSBiYXRjaGluZ1xuICAgIGNvbnN0IGJhdGNoZXMgPSBbXVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb2JqZWN0c0xpc3QubGVuZ3RoOyBpICs9IG1heEVudHJpZXMpIHtcbiAgICAgIGJhdGNoZXMucHVzaChvYmplY3RzTGlzdC5zbGljZShpLCBpICsgbWF4RW50cmllcykpXG4gICAgfVxuXG4gICAgY29uc3QgYmF0Y2hSZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoYmF0Y2hlcy5tYXAocnVuRGVsZXRlT2JqZWN0cykpXG4gICAgcmV0dXJuIGJhdGNoUmVzdWx0cy5mbGF0KClcbiAgfVxuXG4gIGFzeW5jIHJlbW92ZUluY29tcGxldGVVcGxvYWQoYnVja2V0TmFtZTogc3RyaW5nLCBvYmplY3ROYW1lOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLklzVmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cbiAgICBjb25zdCByZW1vdmVVcGxvYWRJZCA9IGF3YWl0IHRoaXMuZmluZFVwbG9hZElkKGJ1Y2tldE5hbWUsIG9iamVjdE5hbWUpXG4gICAgY29uc3QgbWV0aG9kID0gJ0RFTEVURSdcbiAgICBjb25zdCBxdWVyeSA9IGB1cGxvYWRJZD0ke3JlbW92ZVVwbG9hZElkfWBcbiAgICBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmNPbWl0KHsgbWV0aG9kLCBidWNrZXROYW1lLCBvYmplY3ROYW1lLCBxdWVyeSB9LCAnJywgWzIwNF0pXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNvcHlPYmplY3RWMShcbiAgICB0YXJnZXRCdWNrZXROYW1lOiBzdHJpbmcsXG4gICAgdGFyZ2V0T2JqZWN0TmFtZTogc3RyaW5nLFxuICAgIHNvdXJjZUJ1Y2tldE5hbWVBbmRPYmplY3ROYW1lOiBzdHJpbmcsXG4gICAgY29uZGl0aW9ucz86IG51bGwgfCBDb3B5Q29uZGl0aW9ucyxcbiAgKSB7XG4gICAgaWYgKHR5cGVvZiBjb25kaXRpb25zID09ICdmdW5jdGlvbicpIHtcbiAgICAgIGNvbmRpdGlvbnMgPSBudWxsXG4gICAgfVxuXG4gICAgaWYgKCFpc1ZhbGlkQnVja2V0TmFtZSh0YXJnZXRCdWNrZXROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKCdJbnZhbGlkIGJ1Y2tldCBuYW1lOiAnICsgdGFyZ2V0QnVja2V0TmFtZSlcbiAgICB9XG4gICAgaWYgKCFpc1ZhbGlkT2JqZWN0TmFtZSh0YXJnZXRPYmplY3ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkT2JqZWN0TmFtZUVycm9yKGBJbnZhbGlkIG9iamVjdCBuYW1lOiAke3RhcmdldE9iamVjdE5hbWV9YClcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyhzb3VyY2VCdWNrZXROYW1lQW5kT2JqZWN0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3NvdXJjZUJ1Y2tldE5hbWVBbmRPYmplY3ROYW1lIHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICAgIH1cbiAgICBpZiAoc291cmNlQnVja2V0TmFtZUFuZE9iamVjdE5hbWUgPT09ICcnKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRQcmVmaXhFcnJvcihgRW1wdHkgc291cmNlIHByZWZpeGApXG4gICAgfVxuXG4gICAgaWYgKGNvbmRpdGlvbnMgIT0gbnVsbCAmJiAhKGNvbmRpdGlvbnMgaW5zdGFuY2VvZiBDb3B5Q29uZGl0aW9ucykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2NvbmRpdGlvbnMgc2hvdWxkIGJlIG9mIHR5cGUgXCJDb3B5Q29uZGl0aW9uc1wiJylcbiAgICB9XG5cbiAgICBjb25zdCBoZWFkZXJzOiBSZXF1ZXN0SGVhZGVycyA9IHt9XG4gICAgaGVhZGVyc1sneC1hbXotY29weS1zb3VyY2UnXSA9IHVyaVJlc291cmNlRXNjYXBlKHNvdXJjZUJ1Y2tldE5hbWVBbmRPYmplY3ROYW1lKVxuXG4gICAgaWYgKGNvbmRpdGlvbnMpIHtcbiAgICAgIGlmIChjb25kaXRpb25zLm1vZGlmaWVkICE9PSAnJykge1xuICAgICAgICBoZWFkZXJzWyd4LWFtei1jb3B5LXNvdXJjZS1pZi1tb2RpZmllZC1zaW5jZSddID0gY29uZGl0aW9ucy5tb2RpZmllZFxuICAgICAgfVxuICAgICAgaWYgKGNvbmRpdGlvbnMudW5tb2RpZmllZCAhPT0gJycpIHtcbiAgICAgICAgaGVhZGVyc1sneC1hbXotY29weS1zb3VyY2UtaWYtdW5tb2RpZmllZC1zaW5jZSddID0gY29uZGl0aW9ucy51bm1vZGlmaWVkXG4gICAgICB9XG4gICAgICBpZiAoY29uZGl0aW9ucy5tYXRjaEVUYWcgIT09ICcnKSB7XG4gICAgICAgIGhlYWRlcnNbJ3gtYW16LWNvcHktc291cmNlLWlmLW1hdGNoJ10gPSBjb25kaXRpb25zLm1hdGNoRVRhZ1xuICAgICAgfVxuICAgICAgaWYgKGNvbmRpdGlvbnMubWF0Y2hFVGFnRXhjZXB0ICE9PSAnJykge1xuICAgICAgICBoZWFkZXJzWyd4LWFtei1jb3B5LXNvdXJjZS1pZi1ub25lLW1hdGNoJ10gPSBjb25kaXRpb25zLm1hdGNoRVRhZ0V4Y2VwdFxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IG1ldGhvZCA9ICdQVVQnXG5cbiAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmMoe1xuICAgICAgbWV0aG9kLFxuICAgICAgYnVja2V0TmFtZTogdGFyZ2V0QnVja2V0TmFtZSxcbiAgICAgIG9iamVjdE5hbWU6IHRhcmdldE9iamVjdE5hbWUsXG4gICAgICBoZWFkZXJzLFxuICAgIH0pXG4gICAgY29uc3QgYm9keSA9IGF3YWl0IHJlYWRBc1N0cmluZyhyZXMpXG4gICAgcmV0dXJuIHhtbFBhcnNlcnMucGFyc2VDb3B5T2JqZWN0KGJvZHkpXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNvcHlPYmplY3RWMihcbiAgICBzb3VyY2VDb25maWc6IENvcHlTb3VyY2VPcHRpb25zLFxuICAgIGRlc3RDb25maWc6IENvcHlEZXN0aW5hdGlvbk9wdGlvbnMsXG4gICk6IFByb21pc2U8Q29weU9iamVjdFJlc3VsdFYyPiB7XG4gICAgaWYgKCEoc291cmNlQ29uZmlnIGluc3RhbmNlb2YgQ29weVNvdXJjZU9wdGlvbnMpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCdzb3VyY2VDb25maWcgc2hvdWxkIG9mIHR5cGUgQ29weVNvdXJjZU9wdGlvbnMgJylcbiAgICB9XG4gICAgaWYgKCEoZGVzdENvbmZpZyBpbnN0YW5jZW9mIENvcHlEZXN0aW5hdGlvbk9wdGlvbnMpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCdkZXN0Q29uZmlnIHNob3VsZCBvZiB0eXBlIENvcHlEZXN0aW5hdGlvbk9wdGlvbnMgJylcbiAgICB9XG4gICAgaWYgKCFkZXN0Q29uZmlnLnZhbGlkYXRlKCkpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgpXG4gICAgfVxuICAgIGlmICghZGVzdENvbmZpZy52YWxpZGF0ZSgpKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoKVxuICAgIH1cblxuICAgIGNvbnN0IGhlYWRlcnMgPSBPYmplY3QuYXNzaWduKHt9LCBzb3VyY2VDb25maWcuZ2V0SGVhZGVycygpLCBkZXN0Q29uZmlnLmdldEhlYWRlcnMoKSlcblxuICAgIGNvbnN0IGJ1Y2tldE5hbWUgPSBkZXN0Q29uZmlnLkJ1Y2tldFxuICAgIGNvbnN0IG9iamVjdE5hbWUgPSBkZXN0Q29uZmlnLk9iamVjdFxuXG4gICAgY29uc3QgbWV0aG9kID0gJ1BVVCdcblxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMubWFrZVJlcXVlc3RBc3luYyh7IG1ldGhvZCwgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgaGVhZGVycyB9KVxuICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZWFkQXNTdHJpbmcocmVzKVxuICAgIGNvbnN0IGNvcHlSZXMgPSB4bWxQYXJzZXJzLnBhcnNlQ29weU9iamVjdChib2R5KVxuICAgIGNvbnN0IHJlc0hlYWRlcnM6IEluY29taW5nSHR0cEhlYWRlcnMgPSByZXMuaGVhZGVyc1xuXG4gICAgY29uc3Qgc2l6ZUhlYWRlclZhbHVlID0gcmVzSGVhZGVycyAmJiByZXNIZWFkZXJzWydjb250ZW50LWxlbmd0aCddXG4gICAgY29uc3Qgc2l6ZSA9IHR5cGVvZiBzaXplSGVhZGVyVmFsdWUgPT09ICdudW1iZXInID8gc2l6ZUhlYWRlclZhbHVlIDogdW5kZWZpbmVkXG5cbiAgICByZXR1cm4ge1xuICAgICAgQnVja2V0OiBkZXN0Q29uZmlnLkJ1Y2tldCxcbiAgICAgIEtleTogZGVzdENvbmZpZy5PYmplY3QsXG4gICAgICBMYXN0TW9kaWZpZWQ6IGNvcHlSZXMubGFzdE1vZGlmaWVkLFxuICAgICAgTWV0YURhdGE6IGV4dHJhY3RNZXRhZGF0YShyZXNIZWFkZXJzIGFzIFJlc3BvbnNlSGVhZGVyKSxcbiAgICAgIFZlcnNpb25JZDogZ2V0VmVyc2lvbklkKHJlc0hlYWRlcnMgYXMgUmVzcG9uc2VIZWFkZXIpLFxuICAgICAgU291cmNlVmVyc2lvbklkOiBnZXRTb3VyY2VWZXJzaW9uSWQocmVzSGVhZGVycyBhcyBSZXNwb25zZUhlYWRlciksXG4gICAgICBFdGFnOiBzYW5pdGl6ZUVUYWcocmVzSGVhZGVycy5ldGFnKSxcbiAgICAgIFNpemU6IHNpemUsXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgY29weU9iamVjdChzb3VyY2U6IENvcHlTb3VyY2VPcHRpb25zLCBkZXN0OiBDb3B5RGVzdGluYXRpb25PcHRpb25zKTogUHJvbWlzZTxDb3B5T2JqZWN0UmVzdWx0PlxuICBhc3luYyBjb3B5T2JqZWN0KFxuICAgIHRhcmdldEJ1Y2tldE5hbWU6IHN0cmluZyxcbiAgICB0YXJnZXRPYmplY3ROYW1lOiBzdHJpbmcsXG4gICAgc291cmNlQnVja2V0TmFtZUFuZE9iamVjdE5hbWU6IHN0cmluZyxcbiAgICBjb25kaXRpb25zPzogQ29weUNvbmRpdGlvbnMsXG4gICk6IFByb21pc2U8Q29weU9iamVjdFJlc3VsdD5cbiAgYXN5bmMgY29weU9iamVjdCguLi5hbGxBcmdzOiBDb3B5T2JqZWN0UGFyYW1zKTogUHJvbWlzZTxDb3B5T2JqZWN0UmVzdWx0PiB7XG4gICAgaWYgKHR5cGVvZiBhbGxBcmdzWzBdID09PSAnc3RyaW5nJykge1xuICAgICAgY29uc3QgW3RhcmdldEJ1Y2tldE5hbWUsIHRhcmdldE9iamVjdE5hbWUsIHNvdXJjZUJ1Y2tldE5hbWVBbmRPYmplY3ROYW1lLCBjb25kaXRpb25zXSA9IGFsbEFyZ3MgYXMgW1xuICAgICAgICBzdHJpbmcsXG4gICAgICAgIHN0cmluZyxcbiAgICAgICAgc3RyaW5nLFxuICAgICAgICBDb3B5Q29uZGl0aW9ucz8sXG4gICAgICBdXG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5jb3B5T2JqZWN0VjEodGFyZ2V0QnVja2V0TmFtZSwgdGFyZ2V0T2JqZWN0TmFtZSwgc291cmNlQnVja2V0TmFtZUFuZE9iamVjdE5hbWUsIGNvbmRpdGlvbnMpXG4gICAgfVxuICAgIGNvbnN0IFtzb3VyY2UsIGRlc3RdID0gYWxsQXJncyBhcyBbQ29weVNvdXJjZU9wdGlvbnMsIENvcHlEZXN0aW5hdGlvbk9wdGlvbnNdXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuY29weU9iamVjdFYyKHNvdXJjZSwgZGVzdClcbiAgfVxuXG4gIGFzeW5jIHVwbG9hZFBhcnQoXG4gICAgcGFydENvbmZpZzoge1xuICAgICAgYnVja2V0TmFtZTogc3RyaW5nXG4gICAgICBvYmplY3ROYW1lOiBzdHJpbmdcbiAgICAgIHVwbG9hZElEOiBzdHJpbmdcbiAgICAgIHBhcnROdW1iZXI6IG51bWJlclxuICAgICAgaGVhZGVyczogUmVxdWVzdEhlYWRlcnNcbiAgICB9LFxuICAgIHBheWxvYWQ/OiBCaW5hcnksXG4gICkge1xuICAgIGNvbnN0IHsgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgdXBsb2FkSUQsIHBhcnROdW1iZXIsIGhlYWRlcnMgfSA9IHBhcnRDb25maWdcblxuICAgIGNvbnN0IG1ldGhvZCA9ICdQVVQnXG4gICAgY29uc3QgcXVlcnkgPSBgdXBsb2FkSWQ9JHt1cGxvYWRJRH0mcGFydE51bWJlcj0ke3BhcnROdW1iZXJ9YFxuICAgIGNvbnN0IHJlcXVlc3RPcHRpb25zID0geyBtZXRob2QsIGJ1Y2tldE5hbWUsIG9iamVjdE5hbWU6IG9iamVjdE5hbWUsIHF1ZXJ5LCBoZWFkZXJzIH1cbiAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmMocmVxdWVzdE9wdGlvbnMsIHBheWxvYWQpXG4gICAgY29uc3QgYm9keSA9IGF3YWl0IHJlYWRBc1N0cmluZyhyZXMpXG4gICAgY29uc3QgcGFydFJlcyA9IHVwbG9hZFBhcnRQYXJzZXIoYm9keSlcbiAgICBjb25zdCBwYXJ0RXRhZ1ZhbCA9IHNhbml0aXplRVRhZyhyZXMuaGVhZGVycy5ldGFnKSB8fCBzYW5pdGl6ZUVUYWcocGFydFJlcy5FVGFnKVxuICAgIHJldHVybiB7XG4gICAgICBldGFnOiBwYXJ0RXRhZ1ZhbCxcbiAgICAgIGtleTogb2JqZWN0TmFtZSxcbiAgICAgIHBhcnQ6IHBhcnROdW1iZXIsXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgY29tcG9zZU9iamVjdChcbiAgICBkZXN0T2JqQ29uZmlnOiBDb3B5RGVzdGluYXRpb25PcHRpb25zLFxuICAgIHNvdXJjZU9iakxpc3Q6IENvcHlTb3VyY2VPcHRpb25zW10sXG4gICAgeyBtYXhDb25jdXJyZW5jeSA9IDEwIH0gPSB7fSxcbiAgKTogUHJvbWlzZTxib29sZWFuIHwgeyBldGFnOiBzdHJpbmc7IHZlcnNpb25JZDogc3RyaW5nIHwgbnVsbCB9IHwgUHJvbWlzZTx2b2lkPiB8IENvcHlPYmplY3RSZXN1bHQ+IHtcbiAgICBjb25zdCBzb3VyY2VGaWxlc0xlbmd0aCA9IHNvdXJjZU9iakxpc3QubGVuZ3RoXG5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoc291cmNlT2JqTGlzdCkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoJ3NvdXJjZUNvbmZpZyBzaG91bGQgYW4gYXJyYXkgb2YgQ29weVNvdXJjZU9wdGlvbnMgJylcbiAgICB9XG4gICAgaWYgKCEoZGVzdE9iakNvbmZpZyBpbnN0YW5jZW9mIENvcHlEZXN0aW5hdGlvbk9wdGlvbnMpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKCdkZXN0Q29uZmlnIHNob3VsZCBvZiB0eXBlIENvcHlEZXN0aW5hdGlvbk9wdGlvbnMgJylcbiAgICB9XG5cbiAgICBpZiAoc291cmNlRmlsZXNMZW5ndGggPCAxIHx8IHNvdXJjZUZpbGVzTGVuZ3RoID4gUEFSVF9DT05TVFJBSU5UUy5NQVhfUEFSVFNfQ09VTlQpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoXG4gICAgICAgIGBcIlRoZXJlIG11c3QgYmUgYXMgbGVhc3Qgb25lIGFuZCB1cCB0byAke1BBUlRfQ09OU1RSQUlOVFMuTUFYX1BBUlRTX0NPVU5UfSBzb3VyY2Ugb2JqZWN0cy5gLFxuICAgICAgKVxuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc291cmNlRmlsZXNMZW5ndGg7IGkrKykge1xuICAgICAgY29uc3Qgc09iaiA9IHNvdXJjZU9iakxpc3RbaV0gYXMgQ29weVNvdXJjZU9wdGlvbnNcbiAgICAgIGlmICghc09iai52YWxpZGF0ZSgpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghKGRlc3RPYmpDb25maWcgYXMgQ29weURlc3RpbmF0aW9uT3B0aW9ucykudmFsaWRhdGUoKSkge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuXG4gICAgY29uc3QgZ2V0U3RhdE9wdGlvbnMgPSAoc3JjQ29uZmlnOiBDb3B5U291cmNlT3B0aW9ucykgPT4ge1xuICAgICAgbGV0IHN0YXRPcHRzID0ge31cbiAgICAgIGlmICghXy5pc0VtcHR5KHNyY0NvbmZpZy5WZXJzaW9uSUQpKSB7XG4gICAgICAgIHN0YXRPcHRzID0ge1xuICAgICAgICAgIHZlcnNpb25JZDogc3JjQ29uZmlnLlZlcnNpb25JRCxcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHN0YXRPcHRzXG4gICAgfVxuICAgIGNvbnN0IHNyY09iamVjdFNpemVzOiBudW1iZXJbXSA9IFtdXG4gICAgbGV0IHRvdGFsU2l6ZSA9IDBcbiAgICBsZXQgdG90YWxQYXJ0cyA9IDBcblxuICAgIGNvbnN0IHNvdXJjZU9ialN0YXRzID0gc291cmNlT2JqTGlzdC5tYXAoKHNyY0l0ZW0pID0+XG4gICAgICB0aGlzLnN0YXRPYmplY3Qoc3JjSXRlbS5CdWNrZXQsIHNyY0l0ZW0uT2JqZWN0LCBnZXRTdGF0T3B0aW9ucyhzcmNJdGVtKSksXG4gICAgKVxuXG4gICAgY29uc3Qgc3JjT2JqZWN0SW5mb3MgPSBhd2FpdCBQcm9taXNlLmFsbChzb3VyY2VPYmpTdGF0cylcblxuICAgIGNvbnN0IHZhbGlkYXRlZFN0YXRzID0gc3JjT2JqZWN0SW5mb3MubWFwKChyZXNJdGVtU3RhdCwgaW5kZXgpID0+IHtcbiAgICAgIGNvbnN0IHNyY0NvbmZpZzogQ29weVNvdXJjZU9wdGlvbnMgfCB1bmRlZmluZWQgPSBzb3VyY2VPYmpMaXN0W2luZGV4XVxuXG4gICAgICBsZXQgc3JjQ29weVNpemUgPSByZXNJdGVtU3RhdC5zaXplXG4gICAgICAvLyBDaGVjayBpZiBhIHNlZ21lbnQgaXMgc3BlY2lmaWVkLCBhbmQgaWYgc28sIGlzIHRoZVxuICAgICAgLy8gc2VnbWVudCB3aXRoaW4gb2JqZWN0IGJvdW5kcz9cbiAgICAgIGlmIChzcmNDb25maWcgJiYgc3JjQ29uZmlnLk1hdGNoUmFuZ2UpIHtcbiAgICAgICAgLy8gU2luY2UgcmFuZ2UgaXMgc3BlY2lmaWVkLFxuICAgICAgICAvLyAgICAwIDw9IHNyYy5zcmNTdGFydCA8PSBzcmMuc3JjRW5kXG4gICAgICAgIC8vIHNvIG9ubHkgaW52YWxpZCBjYXNlIHRvIGNoZWNrIGlzOlxuICAgICAgICBjb25zdCBzcmNTdGFydCA9IHNyY0NvbmZpZy5TdGFydFxuICAgICAgICBjb25zdCBzcmNFbmQgPSBzcmNDb25maWcuRW5kXG4gICAgICAgIGlmIChzcmNFbmQgPj0gc3JjQ29weVNpemUgfHwgc3JjU3RhcnQgPCAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihcbiAgICAgICAgICAgIGBDb3B5U3JjT3B0aW9ucyAke2luZGV4fSBoYXMgaW52YWxpZCBzZWdtZW50LXRvLWNvcHkgWyR7c3JjU3RhcnR9LCAke3NyY0VuZH1dIChzaXplIGlzICR7c3JjQ29weVNpemV9KWAsXG4gICAgICAgICAgKVxuICAgICAgICB9XG4gICAgICAgIHNyY0NvcHlTaXplID0gc3JjRW5kIC0gc3JjU3RhcnQgKyAxXG4gICAgICB9XG5cbiAgICAgIC8vIE9ubHkgdGhlIGxhc3Qgc291cmNlIG1heSBiZSBsZXNzIHRoYW4gYGFic01pblBhcnRTaXplYFxuICAgICAgaWYgKHNyY0NvcHlTaXplIDwgUEFSVF9DT05TVFJBSU5UUy5BQlNfTUlOX1BBUlRfU0laRSAmJiBpbmRleCA8IHNvdXJjZUZpbGVzTGVuZ3RoIC0gMSkge1xuICAgICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKFxuICAgICAgICAgIGBDb3B5U3JjT3B0aW9ucyAke2luZGV4fSBpcyB0b28gc21hbGwgKCR7c3JjQ29weVNpemV9KSBhbmQgaXQgaXMgbm90IHRoZSBsYXN0IHBhcnQuYCxcbiAgICAgICAgKVxuICAgICAgfVxuXG4gICAgICAvLyBJcyBkYXRhIHRvIGNvcHkgdG9vIGxhcmdlP1xuICAgICAgdG90YWxTaXplICs9IHNyY0NvcHlTaXplXG4gICAgICBpZiAodG90YWxTaXplID4gUEFSVF9DT05TVFJBSU5UUy5NQVhfTVVMVElQQVJUX1BVVF9PQkpFQ1RfU0laRSkge1xuICAgICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRBcmd1bWVudEVycm9yKGBDYW5ub3QgY29tcG9zZSBhbiBvYmplY3Qgb2Ygc2l6ZSAke3RvdGFsU2l6ZX0gKD4gNVRpQilgKVxuICAgICAgfVxuXG4gICAgICAvLyByZWNvcmQgc291cmNlIHNpemVcbiAgICAgIHNyY09iamVjdFNpemVzW2luZGV4XSA9IHNyY0NvcHlTaXplXG5cbiAgICAgIC8vIGNhbGN1bGF0ZSBwYXJ0cyBuZWVkZWQgZm9yIGN1cnJlbnQgc291cmNlXG4gICAgICB0b3RhbFBhcnRzICs9IHBhcnRzUmVxdWlyZWQoc3JjQ29weVNpemUpXG4gICAgICAvLyBEbyB3ZSBuZWVkIG1vcmUgcGFydHMgdGhhbiB3ZSBhcmUgYWxsb3dlZD9cbiAgICAgIGlmICh0b3RhbFBhcnRzID4gUEFSVF9DT05TVFJBSU5UUy5NQVhfUEFSVFNfQ09VTlQpIHtcbiAgICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkQXJndW1lbnRFcnJvcihcbiAgICAgICAgICBgWW91ciBwcm9wb3NlZCBjb21wb3NlIG9iamVjdCByZXF1aXJlcyBtb3JlIHRoYW4gJHtQQVJUX0NPTlNUUkFJTlRTLk1BWF9QQVJUU19DT1VOVH0gcGFydHNgLFxuICAgICAgICApXG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXNJdGVtU3RhdFxuICAgIH0pXG5cbiAgICBpZiAoKHRvdGFsUGFydHMgPT09IDEgJiYgdG90YWxTaXplIDw9IFBBUlRfQ09OU1RSQUlOVFMuTUFYX1BBUlRfU0laRSkgfHwgdG90YWxTaXplID09PSAwKSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5jb3B5T2JqZWN0KHNvdXJjZU9iakxpc3RbMF0gYXMgQ29weVNvdXJjZU9wdGlvbnMsIGRlc3RPYmpDb25maWcpIC8vIHVzZSBjb3B5T2JqZWN0VjJcbiAgICB9XG5cbiAgICAvLyBwcmVzZXJ2ZSBldGFnIHRvIGF2b2lkIG1vZGlmaWNhdGlvbiBvZiBvYmplY3Qgd2hpbGUgY29weWluZy5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNvdXJjZUZpbGVzTGVuZ3RoOyBpKyspIHtcbiAgICAgIDsoc291cmNlT2JqTGlzdFtpXSBhcyBDb3B5U291cmNlT3B0aW9ucykuTWF0Y2hFVGFnID0gKHZhbGlkYXRlZFN0YXRzW2ldIGFzIEJ1Y2tldEl0ZW1TdGF0KS5ldGFnXG4gICAgfVxuXG4gICAgY29uc3Qgc3BsaXRQYXJ0U2l6ZUxpc3QgPSB2YWxpZGF0ZWRTdGF0cy5tYXAoKHJlc0l0ZW1TdGF0LCBpZHgpID0+IHtcbiAgICAgIHJldHVybiBjYWxjdWxhdGVFdmVuU3BsaXRzKHNyY09iamVjdFNpemVzW2lkeF0gYXMgbnVtYmVyLCBzb3VyY2VPYmpMaXN0W2lkeF0gYXMgQ29weVNvdXJjZU9wdGlvbnMpXG4gICAgfSlcblxuICAgIGNvbnN0IGdldFVwbG9hZFBhcnRDb25maWdMaXN0ID0gKHVwbG9hZElkOiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IHVwbG9hZFBhcnRDb25maWdMaXN0OiBVcGxvYWRQYXJ0Q29uZmlnW10gPSBbXVxuXG4gICAgICBzcGxpdFBhcnRTaXplTGlzdC5mb3JFYWNoKChzcGxpdFNpemUsIHNwbGl0SW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgICBpZiAoc3BsaXRTaXplKSB7XG4gICAgICAgICAgY29uc3QgeyBzdGFydEluZGV4OiBzdGFydElkeCwgZW5kSW5kZXg6IGVuZElkeCwgb2JqSW5mbzogb2JqQ29uZmlnIH0gPSBzcGxpdFNpemVcblxuICAgICAgICAgIGNvbnN0IHBhcnRJbmRleCA9IHNwbGl0SW5kZXggKyAxIC8vIHBhcnQgaW5kZXggc3RhcnRzIGZyb20gMS5cbiAgICAgICAgICBjb25zdCB0b3RhbFVwbG9hZHMgPSBBcnJheS5mcm9tKHN0YXJ0SWR4KVxuXG4gICAgICAgICAgY29uc3QgaGVhZGVycyA9IChzb3VyY2VPYmpMaXN0W3NwbGl0SW5kZXhdIGFzIENvcHlTb3VyY2VPcHRpb25zKS5nZXRIZWFkZXJzKClcblxuICAgICAgICAgIHRvdGFsVXBsb2Fkcy5mb3JFYWNoKChzcGxpdFN0YXJ0LCB1cGxkQ3RySWR4KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzcGxpdEVuZCA9IGVuZElkeFt1cGxkQ3RySWR4XVxuXG4gICAgICAgICAgICBjb25zdCBzb3VyY2VPYmogPSBgJHtvYmpDb25maWcuQnVja2V0fS8ke29iakNvbmZpZy5PYmplY3R9YFxuICAgICAgICAgICAgaGVhZGVyc1sneC1hbXotY29weS1zb3VyY2UnXSA9IGAke3NvdXJjZU9ian1gXG4gICAgICAgICAgICBoZWFkZXJzWyd4LWFtei1jb3B5LXNvdXJjZS1yYW5nZSddID0gYGJ5dGVzPSR7c3BsaXRTdGFydH0tJHtzcGxpdEVuZH1gXG5cbiAgICAgICAgICAgIGNvbnN0IHVwbG9hZFBhcnRDb25maWcgPSB7XG4gICAgICAgICAgICAgIGJ1Y2tldE5hbWU6IGRlc3RPYmpDb25maWcuQnVja2V0LFxuICAgICAgICAgICAgICBvYmplY3ROYW1lOiBkZXN0T2JqQ29uZmlnLk9iamVjdCxcbiAgICAgICAgICAgICAgdXBsb2FkSUQ6IHVwbG9hZElkLFxuICAgICAgICAgICAgICBwYXJ0TnVtYmVyOiBwYXJ0SW5kZXgsXG4gICAgICAgICAgICAgIGhlYWRlcnM6IGhlYWRlcnMsXG4gICAgICAgICAgICAgIHNvdXJjZU9iajogc291cmNlT2JqLFxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB1cGxvYWRQYXJ0Q29uZmlnTGlzdC5wdXNoKHVwbG9hZFBhcnRDb25maWcpXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgfSlcblxuICAgICAgcmV0dXJuIHVwbG9hZFBhcnRDb25maWdMaXN0XG4gICAgfVxuXG4gICAgY29uc3QgdXBsb2FkQWxsUGFydHMgPSBhc3luYyAodXBsb2FkTGlzdDogVXBsb2FkUGFydENvbmZpZ1tdKSA9PiB7XG4gICAgICBjb25zdCBwYXJ0VXBsb2FkczogQXdhaXRlZDxSZXR1cm5UeXBlPHR5cGVvZiB0aGlzLnVwbG9hZFBhcnQ+PltdID0gW11cblxuICAgICAgLy8gUHJvY2VzcyB1cGxvYWQgcGFydHMgaW4gYmF0Y2hlcyB0byBhdm9pZCB0b28gbWFueSBjb25jdXJyZW50IHJlcXVlc3RzXG4gICAgICBmb3IgKGNvbnN0IGJhdGNoIG9mIF8uY2h1bmsodXBsb2FkTGlzdCwgbWF4Q29uY3VycmVuY3kpKSB7XG4gICAgICAgIGNvbnN0IGJhdGNoUmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKGJhdGNoLm1hcCgoaXRlbSkgPT4gdGhpcy51cGxvYWRQYXJ0KGl0ZW0pKSlcblxuICAgICAgICBwYXJ0VXBsb2Fkcy5wdXNoKC4uLmJhdGNoUmVzdWx0cylcbiAgICAgIH1cblxuICAgICAgLy8gUHJvY2VzcyByZXN1bHRzIGhlcmUgaWYgbmVlZGVkXG4gICAgICByZXR1cm4gcGFydFVwbG9hZHNcbiAgICB9XG5cbiAgICBjb25zdCBwZXJmb3JtVXBsb2FkUGFydHMgPSBhc3luYyAodXBsb2FkSWQ6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgdXBsb2FkTGlzdCA9IGdldFVwbG9hZFBhcnRDb25maWdMaXN0KHVwbG9hZElkKVxuICAgICAgY29uc3QgcGFydHNSZXMgPSBhd2FpdCB1cGxvYWRBbGxQYXJ0cyh1cGxvYWRMaXN0KVxuICAgICAgcmV0dXJuIHBhcnRzUmVzLm1hcCgocGFydENvcHkpID0+ICh7IGV0YWc6IHBhcnRDb3B5LmV0YWcsIHBhcnQ6IHBhcnRDb3B5LnBhcnQgfSkpXG4gICAgfVxuXG4gICAgY29uc3QgbmV3VXBsb2FkSGVhZGVycyA9IGRlc3RPYmpDb25maWcuZ2V0SGVhZGVycygpXG5cbiAgICBjb25zdCB1cGxvYWRJZCA9IGF3YWl0IHRoaXMuaW5pdGlhdGVOZXdNdWx0aXBhcnRVcGxvYWQoZGVzdE9iakNvbmZpZy5CdWNrZXQsIGRlc3RPYmpDb25maWcuT2JqZWN0LCBuZXdVcGxvYWRIZWFkZXJzKVxuICAgIHRyeSB7XG4gICAgICBjb25zdCBwYXJ0c0RvbmUgPSBhd2FpdCBwZXJmb3JtVXBsb2FkUGFydHModXBsb2FkSWQpXG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5jb21wbGV0ZU11bHRpcGFydFVwbG9hZChkZXN0T2JqQ29uZmlnLkJ1Y2tldCwgZGVzdE9iakNvbmZpZy5PYmplY3QsIHVwbG9hZElkLCBwYXJ0c0RvbmUpXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5hYm9ydE11bHRpcGFydFVwbG9hZChkZXN0T2JqQ29uZmlnLkJ1Y2tldCwgZGVzdE9iakNvbmZpZy5PYmplY3QsIHVwbG9hZElkKVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHByZXNpZ25lZFVybChcbiAgICBtZXRob2Q6IHN0cmluZyxcbiAgICBidWNrZXROYW1lOiBzdHJpbmcsXG4gICAgb2JqZWN0TmFtZTogc3RyaW5nLFxuICAgIGV4cGlyZXM/OiBudW1iZXIgfCBQcmVTaWduUmVxdWVzdFBhcmFtcyB8IHVuZGVmaW5lZCxcbiAgICByZXFQYXJhbXM/OiBQcmVTaWduUmVxdWVzdFBhcmFtcyB8IERhdGUsXG4gICAgcmVxdWVzdERhdGU/OiBEYXRlLFxuICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGlmICh0aGlzLmFub255bW91cykge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5Bbm9ueW1vdXNSZXF1ZXN0RXJyb3IoYFByZXNpZ25lZCAke21ldGhvZH0gdXJsIGNhbm5vdCBiZSBnZW5lcmF0ZWQgZm9yIGFub255bW91cyByZXF1ZXN0c2ApXG4gICAgfVxuXG4gICAgaWYgKCFleHBpcmVzKSB7XG4gICAgICBleHBpcmVzID0gUFJFU0lHTl9FWFBJUllfREFZU19NQVhcbiAgICB9XG4gICAgaWYgKCFyZXFQYXJhbXMpIHtcbiAgICAgIHJlcVBhcmFtcyA9IHt9XG4gICAgfVxuICAgIGlmICghcmVxdWVzdERhdGUpIHtcbiAgICAgIHJlcXVlc3REYXRlID0gbmV3IERhdGUoKVxuICAgIH1cblxuICAgIC8vIFR5cGUgYXNzZXJ0aW9uc1xuICAgIGlmIChleHBpcmVzICYmIHR5cGVvZiBleHBpcmVzICE9PSAnbnVtYmVyJykge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZXhwaXJlcyBzaG91bGQgYmUgb2YgdHlwZSBcIm51bWJlclwiJylcbiAgICB9XG4gICAgaWYgKHJlcVBhcmFtcyAmJiB0eXBlb2YgcmVxUGFyYW1zICE9PSAnb2JqZWN0Jykge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncmVxUGFyYW1zIHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICAgIH1cbiAgICBpZiAoKHJlcXVlc3REYXRlICYmICEocmVxdWVzdERhdGUgaW5zdGFuY2VvZiBEYXRlKSkgfHwgKHJlcXVlc3REYXRlICYmIGlzTmFOKHJlcXVlc3REYXRlPy5nZXRUaW1lKCkpKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncmVxdWVzdERhdGUgc2hvdWxkIGJlIG9mIHR5cGUgXCJEYXRlXCIgYW5kIHZhbGlkJylcbiAgICB9XG5cbiAgICBjb25zdCBxdWVyeSA9IHJlcVBhcmFtcyA/IHFzLnN0cmluZ2lmeShyZXFQYXJhbXMpIDogdW5kZWZpbmVkXG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVnaW9uID0gYXdhaXQgdGhpcy5nZXRCdWNrZXRSZWdpb25Bc3luYyhidWNrZXROYW1lKVxuICAgICAgYXdhaXQgdGhpcy5jaGVja0FuZFJlZnJlc2hDcmVkcygpXG4gICAgICBjb25zdCByZXFPcHRpb25zID0gdGhpcy5nZXRSZXF1ZXN0T3B0aW9ucyh7IG1ldGhvZCwgcmVnaW9uLCBidWNrZXROYW1lLCBvYmplY3ROYW1lLCBxdWVyeSB9KVxuXG4gICAgICByZXR1cm4gcHJlc2lnblNpZ25hdHVyZVY0KFxuICAgICAgICByZXFPcHRpb25zLFxuICAgICAgICB0aGlzLmFjY2Vzc0tleSxcbiAgICAgICAgdGhpcy5zZWNyZXRLZXksXG4gICAgICAgIHRoaXMuc2Vzc2lvblRva2VuLFxuICAgICAgICByZWdpb24sXG4gICAgICAgIHJlcXVlc3REYXRlLFxuICAgICAgICBleHBpcmVzLFxuICAgICAgKVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoYFVuYWJsZSB0byBnZXQgYnVja2V0IHJlZ2lvbiBmb3IgJHtidWNrZXROYW1lfS5gKVxuICAgICAgfVxuXG4gICAgICB0aHJvdyBlcnJcbiAgICB9XG4gIH1cblxuICBhc3luYyBwcmVzaWduZWRHZXRPYmplY3QoXG4gICAgYnVja2V0TmFtZTogc3RyaW5nLFxuICAgIG9iamVjdE5hbWU6IHN0cmluZyxcbiAgICBleHBpcmVzPzogbnVtYmVyLFxuICAgIHJlc3BIZWFkZXJzPzogUHJlU2lnblJlcXVlc3RQYXJhbXMgfCBEYXRlLFxuICAgIHJlcXVlc3REYXRlPzogRGF0ZSxcbiAgKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cblxuICAgIGNvbnN0IHZhbGlkUmVzcEhlYWRlcnMgPSBbXG4gICAgICAncmVzcG9uc2UtY29udGVudC10eXBlJyxcbiAgICAgICdyZXNwb25zZS1jb250ZW50LWxhbmd1YWdlJyxcbiAgICAgICdyZXNwb25zZS1leHBpcmVzJyxcbiAgICAgICdyZXNwb25zZS1jYWNoZS1jb250cm9sJyxcbiAgICAgICdyZXNwb25zZS1jb250ZW50LWRpc3Bvc2l0aW9uJyxcbiAgICAgICdyZXNwb25zZS1jb250ZW50LWVuY29kaW5nJyxcbiAgICBdXG4gICAgdmFsaWRSZXNwSGVhZGVycy5mb3JFYWNoKChoZWFkZXIpID0+IHtcbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIGlmIChyZXNwSGVhZGVycyAhPT0gdW5kZWZpbmVkICYmIHJlc3BIZWFkZXJzW2hlYWRlcl0gIT09IHVuZGVmaW5lZCAmJiAhaXNTdHJpbmcocmVzcEhlYWRlcnNbaGVhZGVyXSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgcmVzcG9uc2UgaGVhZGVyICR7aGVhZGVyfSBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiYClcbiAgICAgIH1cbiAgICB9KVxuICAgIHJldHVybiB0aGlzLnByZXNpZ25lZFVybCgnR0VUJywgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgZXhwaXJlcywgcmVzcEhlYWRlcnMsIHJlcXVlc3REYXRlKVxuICB9XG5cbiAgYXN5bmMgcHJlc2lnbmVkUHV0T2JqZWN0KGJ1Y2tldE5hbWU6IHN0cmluZywgb2JqZWN0TmFtZTogc3RyaW5nLCBleHBpcmVzPzogbnVtYmVyKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoYEludmFsaWQgYnVja2V0IG5hbWU6ICR7YnVja2V0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRPYmplY3ROYW1lKG9iamVjdE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRPYmplY3ROYW1lRXJyb3IoYEludmFsaWQgb2JqZWN0IG5hbWU6ICR7b2JqZWN0TmFtZX1gKVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnByZXNpZ25lZFVybCgnUFVUJywgYnVja2V0TmFtZSwgb2JqZWN0TmFtZSwgZXhwaXJlcylcbiAgfVxuXG4gIG5ld1Bvc3RQb2xpY3koKTogUG9zdFBvbGljeSB7XG4gICAgcmV0dXJuIG5ldyBQb3N0UG9saWN5KClcbiAgfVxuXG4gIGFzeW5jIHByZXNpZ25lZFBvc3RQb2xpY3kocG9zdFBvbGljeTogUG9zdFBvbGljeSk6IFByb21pc2U8UG9zdFBvbGljeVJlc3VsdD4ge1xuICAgIGlmICh0aGlzLmFub255bW91cykge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5Bbm9ueW1vdXNSZXF1ZXN0RXJyb3IoJ1ByZXNpZ25lZCBQT1NUIHBvbGljeSBjYW5ub3QgYmUgZ2VuZXJhdGVkIGZvciBhbm9ueW1vdXMgcmVxdWVzdHMnKVxuICAgIH1cbiAgICBpZiAoIWlzT2JqZWN0KHBvc3RQb2xpY3kpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdwb3N0UG9saWN5IHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICAgIH1cbiAgICBjb25zdCBidWNrZXROYW1lID0gcG9zdFBvbGljeS5mb3JtRGF0YS5idWNrZXQgYXMgc3RyaW5nXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlZ2lvbiA9IGF3YWl0IHRoaXMuZ2V0QnVja2V0UmVnaW9uQXN5bmMoYnVja2V0TmFtZSlcblxuICAgICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKClcbiAgICAgIGNvbnN0IGRhdGVTdHIgPSBtYWtlRGF0ZUxvbmcoZGF0ZSlcbiAgICAgIGF3YWl0IHRoaXMuY2hlY2tBbmRSZWZyZXNoQ3JlZHMoKVxuXG4gICAgICBpZiAoIXBvc3RQb2xpY3kucG9saWN5LmV4cGlyYXRpb24pIHtcbiAgICAgICAgLy8gJ2V4cGlyYXRpb24nIGlzIG1hbmRhdG9yeSBmaWVsZCBmb3IgUzMuXG4gICAgICAgIC8vIFNldCBkZWZhdWx0IGV4cGlyYXRpb24gZGF0ZSBvZiA3IGRheXMuXG4gICAgICAgIGNvbnN0IGV4cGlyZXMgPSBuZXcgRGF0ZSgpXG4gICAgICAgIGV4cGlyZXMuc2V0U2Vjb25kcyhQUkVTSUdOX0VYUElSWV9EQVlTX01BWClcbiAgICAgICAgcG9zdFBvbGljeS5zZXRFeHBpcmVzKGV4cGlyZXMpXG4gICAgICB9XG5cbiAgICAgIHBvc3RQb2xpY3kucG9saWN5LmNvbmRpdGlvbnMucHVzaChbJ2VxJywgJyR4LWFtei1kYXRlJywgZGF0ZVN0cl0pXG4gICAgICBwb3N0UG9saWN5LmZvcm1EYXRhWyd4LWFtei1kYXRlJ10gPSBkYXRlU3RyXG5cbiAgICAgIHBvc3RQb2xpY3kucG9saWN5LmNvbmRpdGlvbnMucHVzaChbJ2VxJywgJyR4LWFtei1hbGdvcml0aG0nLCAnQVdTNC1ITUFDLVNIQTI1NiddKVxuICAgICAgcG9zdFBvbGljeS5mb3JtRGF0YVsneC1hbXotYWxnb3JpdGhtJ10gPSAnQVdTNC1ITUFDLVNIQTI1NidcblxuICAgICAgcG9zdFBvbGljeS5wb2xpY3kuY29uZGl0aW9ucy5wdXNoKFsnZXEnLCAnJHgtYW16LWNyZWRlbnRpYWwnLCB0aGlzLmFjY2Vzc0tleSArICcvJyArIGdldFNjb3BlKHJlZ2lvbiwgZGF0ZSldKVxuICAgICAgcG9zdFBvbGljeS5mb3JtRGF0YVsneC1hbXotY3JlZGVudGlhbCddID0gdGhpcy5hY2Nlc3NLZXkgKyAnLycgKyBnZXRTY29wZShyZWdpb24sIGRhdGUpXG5cbiAgICAgIGlmICh0aGlzLnNlc3Npb25Ub2tlbikge1xuICAgICAgICBwb3N0UG9saWN5LnBvbGljeS5jb25kaXRpb25zLnB1c2goWydlcScsICckeC1hbXotc2VjdXJpdHktdG9rZW4nLCB0aGlzLnNlc3Npb25Ub2tlbl0pXG4gICAgICAgIHBvc3RQb2xpY3kuZm9ybURhdGFbJ3gtYW16LXNlY3VyaXR5LXRva2VuJ10gPSB0aGlzLnNlc3Npb25Ub2tlblxuICAgICAgfVxuXG4gICAgICBjb25zdCBwb2xpY3lCYXNlNjQgPSBCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeShwb3N0UG9saWN5LnBvbGljeSkpLnRvU3RyaW5nKCdiYXNlNjQnKVxuXG4gICAgICBwb3N0UG9saWN5LmZvcm1EYXRhLnBvbGljeSA9IHBvbGljeUJhc2U2NFxuXG4gICAgICBwb3N0UG9saWN5LmZvcm1EYXRhWyd4LWFtei1zaWduYXR1cmUnXSA9IHBvc3RQcmVzaWduU2lnbmF0dXJlVjQocmVnaW9uLCBkYXRlLCB0aGlzLnNlY3JldEtleSwgcG9saWN5QmFzZTY0KVxuICAgICAgY29uc3Qgb3B0cyA9IHtcbiAgICAgICAgcmVnaW9uOiByZWdpb24sXG4gICAgICAgIGJ1Y2tldE5hbWU6IGJ1Y2tldE5hbWUsXG4gICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgfVxuICAgICAgY29uc3QgcmVxT3B0aW9ucyA9IHRoaXMuZ2V0UmVxdWVzdE9wdGlvbnMob3B0cylcbiAgICAgIGNvbnN0IHBvcnRTdHIgPSB0aGlzLnBvcnQgPT0gODAgfHwgdGhpcy5wb3J0ID09PSA0NDMgPyAnJyA6IGA6JHt0aGlzLnBvcnQudG9TdHJpbmcoKX1gXG4gICAgICBjb25zdCB1cmxTdHIgPSBgJHtyZXFPcHRpb25zLnByb3RvY29sfS8vJHtyZXFPcHRpb25zLmhvc3R9JHtwb3J0U3RyfSR7cmVxT3B0aW9ucy5wYXRofWBcbiAgICAgIHJldHVybiB7IHBvc3RVUkw6IHVybFN0ciwgZm9ybURhdGE6IHBvc3RQb2xpY3kuZm9ybURhdGEgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIGVycm9ycy5JbnZhbGlkQnVja2V0TmFtZUVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEFyZ3VtZW50RXJyb3IoYFVuYWJsZSB0byBnZXQgYnVja2V0IHJlZ2lvbiBmb3IgJHtidWNrZXROYW1lfS5gKVxuICAgICAgfVxuXG4gICAgICB0aHJvdyBlcnJcbiAgICB9XG4gIH1cbiAgLy8gbGlzdCBhIGJhdGNoIG9mIG9iamVjdHNcbiAgYXN5bmMgbGlzdE9iamVjdHNRdWVyeShidWNrZXROYW1lOiBzdHJpbmcsIHByZWZpeD86IHN0cmluZywgbWFya2VyPzogc3RyaW5nLCBsaXN0UXVlcnlPcHRzPzogTGlzdE9iamVjdFF1ZXJ5T3B0cykge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNTdHJpbmcocHJlZml4KSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncHJlZml4IHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICAgIH1cbiAgICBpZiAobWFya2VyICYmICFpc1N0cmluZyhtYXJrZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtYXJrZXIgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuXG4gICAgaWYgKGxpc3RRdWVyeU9wdHMgJiYgIWlzT2JqZWN0KGxpc3RRdWVyeU9wdHMpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsaXN0UXVlcnlPcHRzIHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICAgIH1cbiAgICBsZXQgeyBEZWxpbWl0ZXIsIE1heEtleXMsIEluY2x1ZGVWZXJzaW9uLCB2ZXJzaW9uSWRNYXJrZXIsIGtleU1hcmtlciB9ID0gbGlzdFF1ZXJ5T3B0cyBhcyBMaXN0T2JqZWN0UXVlcnlPcHRzXG5cbiAgICBpZiAoIWlzU3RyaW5nKERlbGltaXRlcikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0RlbGltaXRlciBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgICB9XG4gICAgaWYgKCFpc051bWJlcihNYXhLZXlzKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignTWF4S2V5cyBzaG91bGQgYmUgb2YgdHlwZSBcIm51bWJlclwiJylcbiAgICB9XG5cbiAgICBjb25zdCBxdWVyaWVzID0gW11cbiAgICAvLyBlc2NhcGUgZXZlcnkgdmFsdWUgaW4gcXVlcnkgc3RyaW5nLCBleGNlcHQgbWF4S2V5c1xuICAgIHF1ZXJpZXMucHVzaChgcHJlZml4PSR7dXJpRXNjYXBlKHByZWZpeCl9YClcbiAgICBxdWVyaWVzLnB1c2goYGRlbGltaXRlcj0ke3VyaUVzY2FwZShEZWxpbWl0ZXIpfWApXG4gICAgcXVlcmllcy5wdXNoKGBlbmNvZGluZy10eXBlPXVybGApXG5cbiAgICBpZiAoSW5jbHVkZVZlcnNpb24pIHtcbiAgICAgIHF1ZXJpZXMucHVzaChgdmVyc2lvbnNgKVxuICAgIH1cblxuICAgIGlmIChJbmNsdWRlVmVyc2lvbikge1xuICAgICAgLy8gdjEgdmVyc2lvbiBsaXN0aW5nLi5cbiAgICAgIGlmIChrZXlNYXJrZXIpIHtcbiAgICAgICAgcXVlcmllcy5wdXNoKGBrZXktbWFya2VyPSR7a2V5TWFya2VyfWApXG4gICAgICB9XG4gICAgICBpZiAodmVyc2lvbklkTWFya2VyKSB7XG4gICAgICAgIHF1ZXJpZXMucHVzaChgdmVyc2lvbi1pZC1tYXJrZXI9JHt2ZXJzaW9uSWRNYXJrZXJ9YClcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKG1hcmtlcikge1xuICAgICAgbWFya2VyID0gdXJpRXNjYXBlKG1hcmtlcilcbiAgICAgIHF1ZXJpZXMucHVzaChgbWFya2VyPSR7bWFya2VyfWApXG4gICAgfVxuXG4gICAgLy8gbm8gbmVlZCB0byBlc2NhcGUgbWF4S2V5c1xuICAgIGlmIChNYXhLZXlzKSB7XG4gICAgICBpZiAoTWF4S2V5cyA+PSAxMDAwKSB7XG4gICAgICAgIE1heEtleXMgPSAxMDAwXG4gICAgICB9XG4gICAgICBxdWVyaWVzLnB1c2goYG1heC1rZXlzPSR7TWF4S2V5c31gKVxuICAgIH1cbiAgICBxdWVyaWVzLnNvcnQoKVxuICAgIGxldCBxdWVyeSA9ICcnXG4gICAgaWYgKHF1ZXJpZXMubGVuZ3RoID4gMCkge1xuICAgICAgcXVlcnkgPSBgJHtxdWVyaWVzLmpvaW4oJyYnKX1gXG4gICAgfVxuXG4gICAgY29uc3QgbWV0aG9kID0gJ0dFVCdcbiAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmMoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIHF1ZXJ5IH0pXG4gICAgY29uc3QgYm9keSA9IGF3YWl0IHJlYWRBc1N0cmluZyhyZXMpXG4gICAgY29uc3QgbGlzdFFyeUxpc3QgPSBwYXJzZUxpc3RPYmplY3RzKGJvZHkpXG4gICAgcmV0dXJuIGxpc3RRcnlMaXN0XG4gIH1cblxuICBsaXN0T2JqZWN0cyhcbiAgICBidWNrZXROYW1lOiBzdHJpbmcsXG4gICAgcHJlZml4Pzogc3RyaW5nLFxuICAgIHJlY3Vyc2l2ZT86IGJvb2xlYW4sXG4gICAgbGlzdE9wdHM/OiBMaXN0T2JqZWN0UXVlcnlPcHRzIHwgdW5kZWZpbmVkLFxuICApOiBCdWNrZXRTdHJlYW08T2JqZWN0SW5mbz4ge1xuICAgIGlmIChwcmVmaXggPT09IHVuZGVmaW5lZCkge1xuICAgICAgcHJlZml4ID0gJydcbiAgICB9XG4gICAgaWYgKHJlY3Vyc2l2ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZWN1cnNpdmUgPSBmYWxzZVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRQcmVmaXgocHJlZml4KSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkUHJlZml4RXJyb3IoYEludmFsaWQgcHJlZml4IDogJHtwcmVmaXh9YClcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyhwcmVmaXgpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdwcmVmaXggc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIGlmICghaXNCb29sZWFuKHJlY3Vyc2l2ZSkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3JlY3Vyc2l2ZSBzaG91bGQgYmUgb2YgdHlwZSBcImJvb2xlYW5cIicpXG4gICAgfVxuICAgIGlmIChsaXN0T3B0cyAmJiAhaXNPYmplY3QobGlzdE9wdHMpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdsaXN0T3B0cyBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgICB9XG4gICAgbGV0IG1hcmtlcjogc3RyaW5nIHwgdW5kZWZpbmVkID0gJydcbiAgICBsZXQga2V5TWFya2VyOiBzdHJpbmcgfCB1bmRlZmluZWQgPSAnJ1xuICAgIGxldCB2ZXJzaW9uSWRNYXJrZXI6IHN0cmluZyB8IHVuZGVmaW5lZCA9ICcnXG4gICAgbGV0IG9iamVjdHM6IE9iamVjdEluZm9bXSA9IFtdXG4gICAgbGV0IGVuZGVkID0gZmFsc2VcbiAgICBjb25zdCByZWFkU3RyZWFtOiBzdHJlYW0uUmVhZGFibGUgPSBuZXcgc3RyZWFtLlJlYWRhYmxlKHsgb2JqZWN0TW9kZTogdHJ1ZSB9KVxuICAgIHJlYWRTdHJlYW0uX3JlYWQgPSBhc3luYyAoKSA9PiB7XG4gICAgICAvLyBwdXNoIG9uZSBvYmplY3QgcGVyIF9yZWFkKClcbiAgICAgIGlmIChvYmplY3RzLmxlbmd0aCkge1xuICAgICAgICByZWFkU3RyZWFtLnB1c2gob2JqZWN0cy5zaGlmdCgpKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICAgIGlmIChlbmRlZCkge1xuICAgICAgICByZXR1cm4gcmVhZFN0cmVhbS5wdXNoKG51bGwpXG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGxpc3RRdWVyeU9wdHMgPSB7XG4gICAgICAgICAgRGVsaW1pdGVyOiByZWN1cnNpdmUgPyAnJyA6ICcvJywgLy8gaWYgcmVjdXJzaXZlIGlzIGZhbHNlIHNldCBkZWxpbWl0ZXIgdG8gJy8nXG4gICAgICAgICAgTWF4S2V5czogMTAwMCxcbiAgICAgICAgICBJbmNsdWRlVmVyc2lvbjogbGlzdE9wdHM/LkluY2x1ZGVWZXJzaW9uLFxuICAgICAgICAgIC8vIHZlcnNpb24gbGlzdGluZyBzcGVjaWZpYyBvcHRpb25zXG4gICAgICAgICAga2V5TWFya2VyOiBrZXlNYXJrZXIsXG4gICAgICAgICAgdmVyc2lvbklkTWFya2VyOiB2ZXJzaW9uSWRNYXJrZXIsXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHQ6IExpc3RPYmplY3RRdWVyeVJlcyA9IGF3YWl0IHRoaXMubGlzdE9iamVjdHNRdWVyeShidWNrZXROYW1lLCBwcmVmaXgsIG1hcmtlciwgbGlzdFF1ZXJ5T3B0cylcbiAgICAgICAgaWYgKHJlc3VsdC5pc1RydW5jYXRlZCkge1xuICAgICAgICAgIG1hcmtlciA9IHJlc3VsdC5uZXh0TWFya2VyIHx8IHVuZGVmaW5lZFxuICAgICAgICAgIGlmIChyZXN1bHQua2V5TWFya2VyKSB7XG4gICAgICAgICAgICBrZXlNYXJrZXIgPSByZXN1bHQua2V5TWFya2VyXG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChyZXN1bHQudmVyc2lvbklkTWFya2VyKSB7XG4gICAgICAgICAgICB2ZXJzaW9uSWRNYXJrZXIgPSByZXN1bHQudmVyc2lvbklkTWFya2VyXG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVuZGVkID0gdHJ1ZVxuICAgICAgICB9XG4gICAgICAgIGlmIChyZXN1bHQub2JqZWN0cykge1xuICAgICAgICAgIG9iamVjdHMgPSByZXN1bHQub2JqZWN0c1xuICAgICAgICB9XG4gICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgcmVhZFN0cmVhbS5fcmVhZCgpXG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgcmVhZFN0cmVhbS5lbWl0KCdlcnJvcicsIGVycilcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlYWRTdHJlYW1cbiAgfVxuXG4gIGFzeW5jIGxpc3RPYmplY3RzVjJRdWVyeShcbiAgICBidWNrZXROYW1lOiBzdHJpbmcsXG4gICAgcHJlZml4OiBzdHJpbmcsXG4gICAgY29udGludWF0aW9uVG9rZW46IHN0cmluZyxcbiAgICBkZWxpbWl0ZXI6IHN0cmluZyxcbiAgICBtYXhLZXlzOiBudW1iZXIsXG4gICAgc3RhcnRBZnRlcjogc3RyaW5nLFxuICApOiBQcm9taXNlPExpc3RPYmplY3RWMlJlcz4ge1xuICAgIGlmICghaXNWYWxpZEJ1Y2tldE5hbWUoYnVja2V0TmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBlcnJvcnMuSW52YWxpZEJ1Y2tldE5hbWVFcnJvcignSW52YWxpZCBidWNrZXQgbmFtZTogJyArIGJ1Y2tldE5hbWUpXG4gICAgfVxuICAgIGlmICghaXNTdHJpbmcocHJlZml4KSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncHJlZml4IHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICAgIH1cbiAgICBpZiAoIWlzU3RyaW5nKGNvbnRpbnVhdGlvblRva2VuKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignY29udGludWF0aW9uVG9rZW4gc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIGlmICghaXNTdHJpbmcoZGVsaW1pdGVyKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGVsaW1pdGVyIHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICAgIH1cbiAgICBpZiAoIWlzTnVtYmVyKG1heEtleXMpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtYXhLZXlzIHNob3VsZCBiZSBvZiB0eXBlIFwibnVtYmVyXCInKVxuICAgIH1cbiAgICBpZiAoIWlzU3RyaW5nKHN0YXJ0QWZ0ZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdzdGFydEFmdGVyIHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICAgIH1cblxuICAgIGNvbnN0IHF1ZXJpZXMgPSBbXVxuICAgIHF1ZXJpZXMucHVzaChgbGlzdC10eXBlPTJgKVxuICAgIHF1ZXJpZXMucHVzaChgZW5jb2RpbmctdHlwZT11cmxgKVxuICAgIHF1ZXJpZXMucHVzaChgcHJlZml4PSR7dXJpRXNjYXBlKHByZWZpeCl9YClcbiAgICBxdWVyaWVzLnB1c2goYGRlbGltaXRlcj0ke3VyaUVzY2FwZShkZWxpbWl0ZXIpfWApXG5cbiAgICBpZiAoY29udGludWF0aW9uVG9rZW4pIHtcbiAgICAgIHF1ZXJpZXMucHVzaChgY29udGludWF0aW9uLXRva2VuPSR7dXJpRXNjYXBlKGNvbnRpbnVhdGlvblRva2VuKX1gKVxuICAgIH1cbiAgICBpZiAoc3RhcnRBZnRlcikge1xuICAgICAgcXVlcmllcy5wdXNoKGBzdGFydC1hZnRlcj0ke3VyaUVzY2FwZShzdGFydEFmdGVyKX1gKVxuICAgIH1cbiAgICBpZiAobWF4S2V5cykge1xuICAgICAgaWYgKG1heEtleXMgPj0gMTAwMCkge1xuICAgICAgICBtYXhLZXlzID0gMTAwMFxuICAgICAgfVxuICAgICAgcXVlcmllcy5wdXNoKGBtYXgta2V5cz0ke21heEtleXN9YClcbiAgICB9XG4gICAgcXVlcmllcy5zb3J0KClcbiAgICBsZXQgcXVlcnkgPSAnJ1xuICAgIGlmIChxdWVyaWVzLmxlbmd0aCA+IDApIHtcbiAgICAgIHF1ZXJ5ID0gYCR7cXVlcmllcy5qb2luKCcmJyl9YFxuICAgIH1cblxuICAgIGNvbnN0IG1ldGhvZCA9ICdHRVQnXG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jKHsgbWV0aG9kLCBidWNrZXROYW1lLCBxdWVyeSB9KVxuICAgIGNvbnN0IGJvZHkgPSBhd2FpdCByZWFkQXNTdHJpbmcocmVzKVxuICAgIHJldHVybiBwYXJzZUxpc3RPYmplY3RzVjIoYm9keSlcbiAgfVxuXG4gIGxpc3RPYmplY3RzVjIoXG4gICAgYnVja2V0TmFtZTogc3RyaW5nLFxuICAgIHByZWZpeD86IHN0cmluZyxcbiAgICByZWN1cnNpdmU/OiBib29sZWFuLFxuICAgIHN0YXJ0QWZ0ZXI/OiBzdHJpbmcsXG4gICk6IEJ1Y2tldFN0cmVhbTxCdWNrZXRJdGVtPiB7XG4gICAgaWYgKHByZWZpeCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcmVmaXggPSAnJ1xuICAgIH1cbiAgICBpZiAocmVjdXJzaXZlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJlY3Vyc2l2ZSA9IGZhbHNlXG4gICAgfVxuICAgIGlmIChzdGFydEFmdGVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHN0YXJ0QWZ0ZXIgPSAnJ1xuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRQcmVmaXgocHJlZml4KSkge1xuICAgICAgdGhyb3cgbmV3IGVycm9ycy5JbnZhbGlkUHJlZml4RXJyb3IoYEludmFsaWQgcHJlZml4IDogJHtwcmVmaXh9YClcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyhwcmVmaXgpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdwcmVmaXggc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuICAgIGlmICghaXNCb29sZWFuKHJlY3Vyc2l2ZSkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3JlY3Vyc2l2ZSBzaG91bGQgYmUgb2YgdHlwZSBcImJvb2xlYW5cIicpXG4gICAgfVxuICAgIGlmICghaXNTdHJpbmcoc3RhcnRBZnRlcikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3N0YXJ0QWZ0ZXIgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gICAgfVxuXG4gICAgY29uc3QgZGVsaW1pdGVyID0gcmVjdXJzaXZlID8gJycgOiAnLydcbiAgICBjb25zdCBwcmVmaXhTdHIgPSBwcmVmaXhcbiAgICBjb25zdCBzdGFydEFmdGVyU3RyID0gc3RhcnRBZnRlclxuICAgIGxldCBjb250aW51YXRpb25Ub2tlbiA9ICcnXG4gICAgbGV0IG9iamVjdHM6IEJ1Y2tldEl0ZW1bXSA9IFtdXG4gICAgbGV0IGVuZGVkID0gZmFsc2VcbiAgICBjb25zdCByZWFkU3RyZWFtOiBzdHJlYW0uUmVhZGFibGUgPSBuZXcgc3RyZWFtLlJlYWRhYmxlKHsgb2JqZWN0TW9kZTogdHJ1ZSB9KVxuICAgIHJlYWRTdHJlYW0uX3JlYWQgPSBhc3luYyAoKSA9PiB7XG4gICAgICBpZiAob2JqZWN0cy5sZW5ndGgpIHtcbiAgICAgICAgcmVhZFN0cmVhbS5wdXNoKG9iamVjdHMuc2hpZnQoKSlcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgICBpZiAoZW5kZWQpIHtcbiAgICAgICAgcmV0dXJuIHJlYWRTdHJlYW0ucHVzaChudWxsKVxuICAgICAgfVxuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmxpc3RPYmplY3RzVjJRdWVyeShcbiAgICAgICAgICBidWNrZXROYW1lLFxuICAgICAgICAgIHByZWZpeFN0cixcbiAgICAgICAgICBjb250aW51YXRpb25Ub2tlbixcbiAgICAgICAgICBkZWxpbWl0ZXIsXG4gICAgICAgICAgMTAwMCxcbiAgICAgICAgICBzdGFydEFmdGVyU3RyLFxuICAgICAgICApXG4gICAgICAgIGlmIChyZXN1bHQuaXNUcnVuY2F0ZWQpIHtcbiAgICAgICAgICBjb250aW51YXRpb25Ub2tlbiA9IHJlc3VsdC5uZXh0Q29udGludWF0aW9uVG9rZW5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBlbmRlZCA9IHRydWVcbiAgICAgICAgfVxuICAgICAgICBvYmplY3RzID0gcmVzdWx0Lm9iamVjdHNcbiAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICByZWFkU3RyZWFtLl9yZWFkKClcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICByZWFkU3RyZWFtLmVtaXQoJ2Vycm9yJywgZXJyKVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVhZFN0cmVhbVxuICB9XG5cbiAgYXN5bmMgc2V0QnVja2V0Tm90aWZpY2F0aW9uKGJ1Y2tldE5hbWU6IHN0cmluZywgY29uZmlnOiBOb3RpZmljYXRpb25Db25maWcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBpZiAoIWlzT2JqZWN0KGNvbmZpZykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ25vdGlmaWNhdGlvbiBjb25maWcgc2hvdWxkIGJlIG9mIHR5cGUgXCJPYmplY3RcIicpXG4gICAgfVxuICAgIGNvbnN0IG1ldGhvZCA9ICdQVVQnXG4gICAgY29uc3QgcXVlcnkgPSAnbm90aWZpY2F0aW9uJ1xuICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgeG1sMmpzLkJ1aWxkZXIoe1xuICAgICAgcm9vdE5hbWU6ICdOb3RpZmljYXRpb25Db25maWd1cmF0aW9uJyxcbiAgICAgIHJlbmRlck9wdHM6IHsgcHJldHR5OiBmYWxzZSB9LFxuICAgICAgaGVhZGxlc3M6IHRydWUsXG4gICAgfSlcbiAgICBjb25zdCBwYXlsb2FkID0gYnVpbGRlci5idWlsZE9iamVjdChjb25maWcpXG4gICAgYXdhaXQgdGhpcy5tYWtlUmVxdWVzdEFzeW5jT21pdCh7IG1ldGhvZCwgYnVja2V0TmFtZSwgcXVlcnkgfSwgcGF5bG9hZClcbiAgfVxuXG4gIGFzeW5jIHJlbW92ZUFsbEJ1Y2tldE5vdGlmaWNhdGlvbihidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLnNldEJ1Y2tldE5vdGlmaWNhdGlvbihidWNrZXROYW1lLCBuZXcgTm90aWZpY2F0aW9uQ29uZmlnKCkpXG4gIH1cblxuICBhc3luYyBnZXRCdWNrZXROb3RpZmljYXRpb24oYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTxOb3RpZmljYXRpb25Db25maWdSZXN1bHQ+IHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoJ0ludmFsaWQgYnVja2V0IG5hbWU6ICcgKyBidWNrZXROYW1lKVxuICAgIH1cbiAgICBjb25zdCBtZXRob2QgPSAnR0VUJ1xuICAgIGNvbnN0IHF1ZXJ5ID0gJ25vdGlmaWNhdGlvbidcbiAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLm1ha2VSZXF1ZXN0QXN5bmMoeyBtZXRob2QsIGJ1Y2tldE5hbWUsIHF1ZXJ5IH0pXG4gICAgY29uc3QgYm9keSA9IGF3YWl0IHJlYWRBc1N0cmluZyhyZXMpXG4gICAgcmV0dXJuIHBhcnNlQnVja2V0Tm90aWZpY2F0aW9uKGJvZHkpXG4gIH1cblxuICBsaXN0ZW5CdWNrZXROb3RpZmljYXRpb24oXG4gICAgYnVja2V0TmFtZTogc3RyaW5nLFxuICAgIHByZWZpeDogc3RyaW5nLFxuICAgIHN1ZmZpeDogc3RyaW5nLFxuICAgIGV2ZW50czogTm90aWZpY2F0aW9uRXZlbnRbXSxcbiAgKTogTm90aWZpY2F0aW9uUG9sbGVyIHtcbiAgICBpZiAoIWlzVmFsaWRCdWNrZXROYW1lKGJ1Y2tldE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLkludmFsaWRCdWNrZXROYW1lRXJyb3IoYEludmFsaWQgYnVja2V0IG5hbWU6ICR7YnVja2V0TmFtZX1gKVxuICAgIH1cbiAgICBpZiAoIWlzU3RyaW5nKHByZWZpeCkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ByZWZpeCBtdXN0IGJlIG9mIHR5cGUgc3RyaW5nJylcbiAgICB9XG4gICAgaWYgKCFpc1N0cmluZyhzdWZmaXgpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdzdWZmaXggbXVzdCBiZSBvZiB0eXBlIHN0cmluZycpXG4gICAgfVxuICAgIGlmICghQXJyYXkuaXNBcnJheShldmVudHMpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdldmVudHMgbXVzdCBiZSBvZiB0eXBlIEFycmF5JylcbiAgICB9XG4gICAgY29uc3QgbGlzdGVuZXIgPSBuZXcgTm90aWZpY2F0aW9uUG9sbGVyKHRoaXMsIGJ1Y2tldE5hbWUsIHByZWZpeCwgc3VmZml4LCBldmVudHMpXG4gICAgbGlzdGVuZXIuc3RhcnQoKVxuICAgIHJldHVybiBsaXN0ZW5lclxuICB9XG59XG4iXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBS0EsTUFBTTtBQUNsQixPQUFPLEtBQUtDLEVBQUU7QUFFZCxPQUFPLEtBQUtDLElBQUk7QUFDaEIsT0FBTyxLQUFLQyxLQUFLO0FBQ2pCLE9BQU8sS0FBS0MsSUFBSTtBQUNoQixPQUFPLEtBQUtDLE1BQU07QUFFbEIsT0FBTyxLQUFLQyxLQUFLLE1BQU0sT0FBTztBQUM5QixPQUFPQyxZQUFZLE1BQU0sZUFBZTtBQUN4QyxTQUFTQyxTQUFTLFFBQVEsaUJBQWlCO0FBQzNDLE9BQU9DLENBQUMsTUFBTSxRQUFRO0FBQ3RCLE9BQU8sS0FBS0MsRUFBRSxNQUFNLGNBQWM7QUFDbEMsT0FBT0MsTUFBTSxNQUFNLFFBQVE7QUFFM0IsU0FBU0Msa0JBQWtCLFFBQVEsMkJBQTBCO0FBQzdELE9BQU8sS0FBS0MsTUFBTSxNQUFNLGVBQWM7QUFFdEMsU0FDRUMsc0JBQXNCLEVBQ3RCQyxpQkFBaUIsRUFDakJDLGNBQWMsRUFDZEMsaUJBQWlCLEVBQ2pCQyx1QkFBdUIsRUFDdkJDLGVBQWUsRUFDZkMsd0JBQXdCLFFBQ25CLGdCQUFlO0FBRXRCLFNBQVNDLGtCQUFrQixFQUFFQyxrQkFBa0IsUUFBUSxxQkFBb0I7QUFDM0UsU0FBU0Msc0JBQXNCLEVBQUVDLGtCQUFrQixFQUFFQyxNQUFNLFFBQVEsZ0JBQWU7QUFDbEYsU0FBU0MsR0FBRyxFQUFFQyxhQUFhLFFBQVEsYUFBWTtBQUMvQyxTQUFTQyxjQUFj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
|